2 // Copyright (c) 2016 Intel Corporation
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
17 #include "drmbuffer.h"
19 #include <drm_fourcc.h>
22 #include <xf86drmMode.h>
25 #include <nativebufferhandler.h>
29 namespace hwcomposer {
31 DrmBuffer::~DrmBuffer() {
34 if (buffer_handler_ && handle_) {
35 buffer_handler_->ReleaseBuffer(handle_);
36 buffer_handler_->DestroyHandle(handle_);
40 void DrmBuffer::Initialize(const HwcBuffer& bo) {
43 for (uint32_t i = 0; i < 4; i++) {
44 pitches_[i] = bo.pitches[i];
45 offsets_[i] = bo.offsets[i];
46 gem_handles_[i] = bo.gem_handles[i];
50 if (format_ == DRM_FORMAT_NV12_Y_TILED_INTEL || format_ == DRM_FORMAT_NV21)
51 format_ = DRM_FORMAT_NV12;
53 prime_fd_ = bo.prime_fd;
55 if (usage_ & hwcomposer::kLayerCursor) {
56 // We support DRM_FORMAT_ARGB8888 for cursor.
57 frame_buffer_format_ = DRM_FORMAT_ARGB8888;
59 frame_buffer_format_ = format_;
68 case DRM_FORMAT_YVU420:
69 case DRM_FORMAT_YUV420:
70 case DRM_FORMAT_YUV422:
71 case DRM_FORMAT_YUV444:
72 case DRM_FORMAT_YVU420_ANDROID:
90 void DrmBuffer::InitializeFromNativeHandle(
91 HWCNativeHandle handle, NativeBufferHandler* buffer_handler) {
93 buffer_handler->CopyHandle(handle, &handle_);
94 if (!buffer_handler->ImportBuffer(handle_, &bo)) {
95 ETRACE("Failed to Import buffer.");
99 buffer_handler_ = buffer_handler;
103 GpuImage DrmBuffer::ImportImage(GpuDisplay egl_display) {
105 EGLImageKHR image = EGL_NO_IMAGE_KHR;
106 // Note: If eglCreateImageKHR is successful for a EGL_LINUX_DMA_BUF_EXT
107 // target, the EGL will take a reference to the dma_buf.
108 if (is_yuv_ && total_planes_ > 1) {
109 if (total_planes_ == 2) {
110 const EGLint attr_list_nv12[] = {
111 EGL_WIDTH, static_cast<EGLint>(width_),
112 EGL_HEIGHT, static_cast<EGLint>(height_),
113 EGL_LINUX_DRM_FOURCC_EXT, static_cast<EGLint>(format_),
114 EGL_DMA_BUF_PLANE0_FD_EXT, static_cast<EGLint>(prime_fd_),
115 EGL_DMA_BUF_PLANE0_PITCH_EXT, static_cast<EGLint>(pitches_[0]),
116 EGL_DMA_BUF_PLANE0_OFFSET_EXT, static_cast<EGLint>(offsets_[0]),
117 EGL_DMA_BUF_PLANE1_FD_EXT, static_cast<EGLint>(prime_fd_),
118 EGL_DMA_BUF_PLANE1_PITCH_EXT, static_cast<EGLint>(pitches_[1]),
119 EGL_DMA_BUF_PLANE1_OFFSET_EXT, static_cast<EGLint>(offsets_[1]),
121 image = eglCreateImageKHR(
122 egl_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT,
123 static_cast<EGLClientBuffer>(nullptr), attr_list_nv12);
125 const EGLint attr_list_yv12[] = {
126 EGL_WIDTH, static_cast<EGLint>(width_),
127 EGL_HEIGHT, static_cast<EGLint>(height_),
128 EGL_LINUX_DRM_FOURCC_EXT, static_cast<EGLint>(format_),
129 EGL_DMA_BUF_PLANE0_FD_EXT, static_cast<EGLint>(prime_fd_),
130 EGL_DMA_BUF_PLANE0_PITCH_EXT, static_cast<EGLint>(pitches_[0]),
131 EGL_DMA_BUF_PLANE0_OFFSET_EXT, static_cast<EGLint>(offsets_[0]),
132 EGL_DMA_BUF_PLANE1_FD_EXT, static_cast<EGLint>(prime_fd_),
133 EGL_DMA_BUF_PLANE1_PITCH_EXT, static_cast<EGLint>(pitches_[1]),
134 EGL_DMA_BUF_PLANE1_OFFSET_EXT, static_cast<EGLint>(offsets_[1]),
135 EGL_DMA_BUF_PLANE2_FD_EXT, static_cast<EGLint>(prime_fd_),
136 EGL_DMA_BUF_PLANE2_PITCH_EXT, static_cast<EGLint>(pitches_[2]),
137 EGL_DMA_BUF_PLANE2_OFFSET_EXT, static_cast<EGLint>(offsets_[2]),
139 image = eglCreateImageKHR(
140 egl_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT,
141 static_cast<EGLClientBuffer>(nullptr), attr_list_yv12);
144 const EGLint attr_list[] = {
145 EGL_WIDTH, static_cast<EGLint>(width_),
146 EGL_HEIGHT, static_cast<EGLint>(height_),
147 EGL_LINUX_DRM_FOURCC_EXT, static_cast<EGLint>(format_),
148 EGL_DMA_BUF_PLANE0_FD_EXT, static_cast<EGLint>(prime_fd_),
149 EGL_DMA_BUF_PLANE0_PITCH_EXT, static_cast<EGLint>(pitches_[0]),
150 EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0,
153 eglCreateImageKHR(egl_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT,
154 static_cast<EGLClientBuffer>(nullptr), attr_list);
159 struct vk_import import;
161 PFN_vkCreateDmaBufImageINTEL vkCreateDmaBufImageINTEL =
162 (PFN_vkCreateDmaBufImageINTEL)vkGetDeviceProcAddr(
163 egl_display, "vkCreateDmaBufImageINTEL");
164 if (vkCreateDmaBufImageINTEL == NULL) {
165 ETRACE("vkGetDeviceProcAddr(\"vkCreateDmaBufImageINTEL\") failed\n");
166 import.res = VK_ERROR_INITIALIZATION_FAILED;
170 VkFormat vk_format = NativeToVkFormat(format_);
171 if (vk_format == VK_FORMAT_UNDEFINED) {
172 ETRACE("Failed DRM -> Vulkan format conversion\n");
173 import.res = VK_ERROR_FORMAT_NOT_SUPPORTED;
177 VkExtent3D image_extent = {};
178 image_extent.width = width_;
179 image_extent.height = height_;
180 image_extent.depth = 1;
182 VkDmaBufImageCreateInfo image_create = {};
184 (enum VkStructureType)VK_STRUCTURE_TYPE_DMA_BUF_IMAGE_CREATE_INFO_INTEL;
185 image_create.fd = static_cast<int>(prime_fd_);
186 image_create.format = vk_format;
187 image_create.extent = image_extent;
188 image_create.strideInBytes = pitches_[0];
190 import.res = vkCreateDmaBufImageINTEL(egl_display, &image_create, NULL,
191 &import.memory, &import.image);
199 void DrmBuffer::SetRecommendedFormat(uint32_t format) {
200 frame_buffer_format_ = format;
203 bool DrmBuffer::CreateFrameBuffer(uint32_t gpu_fd) {
204 ReleaseFrameBuffer();
205 int ret = drmModeAddFB2(gpu_fd, width_, height_, frame_buffer_format_,
206 gem_handles_, pitches_, offsets_, &fb_id_, 0);
209 ETRACE("drmModeAddFB2 error (%dx%d, %c%c%c%c, handle %d pitch %d) (%s)",
210 width_, height_, frame_buffer_format_, frame_buffer_format_ >> 8,
211 frame_buffer_format_ >> 16, frame_buffer_format_ >> 24,
212 gem_handles_[0], pitches_[0], strerror(-ret));
222 void DrmBuffer::ReleaseFrameBuffer() {
223 if (fb_id_ && gpu_fd_ && drmModeRmFB(gpu_fd_, fb_id_))
224 ETRACE("Failed to remove fb %s", PRINTERROR());
229 void DrmBuffer::Dump() {
230 DUMPTRACE("DrmBuffer Information Starts. -------------");
231 if (usage_ & kLayerNormal)
232 DUMPTRACE("BufferUsage: kLayerNormal.");
233 if (usage_ & kLayerCursor)
234 DUMPTRACE("BufferUsage: kLayerCursor.");
235 if (usage_ & kLayerProtected)
236 DUMPTRACE("BufferUsage: kLayerProtected.");
237 if (usage_ & kLayerVideo)
238 DUMPTRACE("BufferUsage: kLayerVideo.");
239 DUMPTRACE("Width: %d", width_);
240 DUMPTRACE("Height: %d", height_);
241 DUMPTRACE("Fb: %d", fb_id_);
242 DUMPTRACE("Prime Handle: %d", prime_fd_);
243 DUMPTRACE("Format: %4.4s", (char*)&format_);
244 for (uint32_t i = 0; i < 4; i++) {
245 DUMPTRACE("Pitch:%d value:%d", i, pitches_[i]);
246 DUMPTRACE("Offset:%d value:%d", i, offsets_[i]);
247 DUMPTRACE("Gem Handles:%d value:%d", i, gem_handles_[i]);
249 DUMPTRACE("DrmBuffer Information Ends. -------------");
252 OverlayBuffer* OverlayBuffer::CreateOverlayBuffer() {
253 return new DrmBuffer();
256 } // namespace hwcomposer