OSDN Git Service

Add missing support for packed and planar YUV formats.
[android-x86/external-IA-Hardware-Composer.git] / wsi / drm / drmbuffer.cpp
1 /*
2 // Copyright (c) 2016 Intel Corporation
3 //
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
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
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.
15 */
16
17 #include "drmbuffer.h"
18
19 #include <drm_fourcc.h>
20 #include <unistd.h>
21 #include <xf86drm.h>
22 #include <xf86drmMode.h>
23
24 #include <hwcdefs.h>
25 #include <nativebufferhandler.h>
26
27 #include "hwctrace.h"
28
29 namespace hwcomposer {
30
31 DrmBuffer::~DrmBuffer() {
32   ReleaseFrameBuffer();
33
34   if (buffer_handler_ && handle_) {
35     buffer_handler_->ReleaseBuffer(handle_);
36     buffer_handler_->DestroyHandle(handle_);
37   }
38 }
39
40 void DrmBuffer::Initialize(const HwcBuffer& bo) {
41   width_ = bo.width;
42   height_ = bo.height;
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];
47   }
48
49   format_ = bo.format;
50   if (format_ == DRM_FORMAT_NV12_Y_TILED_INTEL || format_ == DRM_FORMAT_NV21)
51     format_ = DRM_FORMAT_NV12;
52
53   prime_fd_ = bo.prime_fd;
54   usage_ = bo.usage;
55   if (usage_ & hwcomposer::kLayerCursor) {
56     // We support DRM_FORMAT_ARGB8888 for cursor.
57     frame_buffer_format_ = DRM_FORMAT_ARGB8888;
58   } else {
59     frame_buffer_format_ = format_;
60   }
61
62   switch (format_) {
63     case DRM_FORMAT_NV12:
64     case DRM_FORMAT_NV16:
65       total_planes_ = 2;
66       is_yuv_ = true;
67       break;
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:
73       is_yuv_ = true;
74       total_planes_ = 3;
75       break;
76     case DRM_FORMAT_UYVY:
77     case DRM_FORMAT_YUYV:
78     case DRM_FORMAT_YVYU:
79     case DRM_FORMAT_VYUY:
80     case DRM_FORMAT_AYUV:
81       is_yuv_ = true;
82       total_planes_ = 1;
83       break;
84     default:
85       is_yuv_ = false;
86       total_planes_ = 1;
87   }
88 }
89
90 void DrmBuffer::InitializeFromNativeHandle(
91     HWCNativeHandle handle, NativeBufferHandler* buffer_handler) {
92   struct HwcBuffer bo;
93   buffer_handler->CopyHandle(handle, &handle_);
94   if (!buffer_handler->ImportBuffer(handle_, &bo)) {
95     ETRACE("Failed to Import buffer.");
96     return;
97   }
98
99   buffer_handler_ = buffer_handler;
100   Initialize(bo);
101 }
102
103 GpuImage DrmBuffer::ImportImage(GpuDisplay egl_display) {
104 #ifdef USE_GL
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]),
120           EGL_NONE,                      0};
121       image = eglCreateImageKHR(
122           egl_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT,
123           static_cast<EGLClientBuffer>(nullptr), attr_list_nv12);
124     } else {
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]),
138           EGL_NONE,                      0};
139       image = eglCreateImageKHR(
140           egl_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT,
141           static_cast<EGLClientBuffer>(nullptr), attr_list_yv12);
142     }
143   } else {
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,
151         EGL_NONE,                      0};
152     image =
153         eglCreateImageKHR(egl_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT,
154                           static_cast<EGLClientBuffer>(nullptr), attr_list);
155   }
156
157   return image;
158 #elif USE_VK
159   struct vk_import import;
160
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;
167     return import;
168   }
169
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;
174     return import;
175   }
176
177   VkExtent3D image_extent = {};
178   image_extent.width = width_;
179   image_extent.height = height_;
180   image_extent.depth = 1;
181
182   VkDmaBufImageCreateInfo image_create = {};
183   image_create.sType =
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];
189
190   import.res = vkCreateDmaBufImageINTEL(egl_display, &image_create, NULL,
191                                         &import.memory, &import.image);
192
193   return import;
194 #else
195   return NULL;
196 #endif
197 }
198
199 void DrmBuffer::SetRecommendedFormat(uint32_t format) {
200   frame_buffer_format_ = format;
201 }
202
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);
207
208   if (ret) {
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));
213
214     fb_id_ = 0;
215     return false;
216   }
217
218   gpu_fd_ = gpu_fd;
219   return true;
220 }
221
222 void DrmBuffer::ReleaseFrameBuffer() {
223   if (fb_id_ && gpu_fd_ && drmModeRmFB(gpu_fd_, fb_id_))
224     ETRACE("Failed to remove fb %s", PRINTERROR());
225
226   fb_id_ = 0;
227 }
228
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]);
248   }
249   DUMPTRACE("DrmBuffer Information Ends. -------------");
250 }
251
252 OverlayBuffer* OverlayBuffer::CreateOverlayBuffer() {
253   return new DrmBuffer();
254 }
255
256 }  // namespace hwcomposer