xref: /aosp_15_r20/external/drm_hwcomposer/bufferinfo/legacy/BufferInfoLibdrm.cpp (revision 0a9764fe0a15e71ebbeb85e87e10990c23aab47f)
1*0a9764feSAndroid Build Coastguard Worker /*
2*0a9764feSAndroid Build Coastguard Worker  * Copyright (C) 2020 The Android Open Source Project
3*0a9764feSAndroid Build Coastguard Worker  *
4*0a9764feSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*0a9764feSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*0a9764feSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*0a9764feSAndroid Build Coastguard Worker  *
8*0a9764feSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*0a9764feSAndroid Build Coastguard Worker  *
10*0a9764feSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*0a9764feSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*0a9764feSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*0a9764feSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*0a9764feSAndroid Build Coastguard Worker  * limitations under the License.
15*0a9764feSAndroid Build Coastguard Worker  */
16*0a9764feSAndroid Build Coastguard Worker 
17*0a9764feSAndroid Build Coastguard Worker #define LOG_TAG "drmhwc"
18*0a9764feSAndroid Build Coastguard Worker 
19*0a9764feSAndroid Build Coastguard Worker #include "BufferInfoLibdrm.h"
20*0a9764feSAndroid Build Coastguard Worker 
21*0a9764feSAndroid Build Coastguard Worker #include <gralloc_handle.h>
22*0a9764feSAndroid Build Coastguard Worker #include <hardware/gralloc.h>
23*0a9764feSAndroid Build Coastguard Worker #include <xf86drm.h>
24*0a9764feSAndroid Build Coastguard Worker #include <xf86drmMode.h>
25*0a9764feSAndroid Build Coastguard Worker 
26*0a9764feSAndroid Build Coastguard Worker #include <mutex>
27*0a9764feSAndroid Build Coastguard Worker 
28*0a9764feSAndroid Build Coastguard Worker #include "utils/log.h"
29*0a9764feSAndroid Build Coastguard Worker #include "utils/properties.h"
30*0a9764feSAndroid Build Coastguard Worker 
31*0a9764feSAndroid Build Coastguard Worker namespace android {
32*0a9764feSAndroid Build Coastguard Worker 
33*0a9764feSAndroid Build Coastguard Worker LEGACY_BUFFER_INFO_GETTER(BufferInfoLibdrm);
34*0a9764feSAndroid Build Coastguard Worker 
35*0a9764feSAndroid Build Coastguard Worker enum chroma_order {
36*0a9764feSAndroid Build Coastguard Worker   kYCbCr,
37*0a9764feSAndroid Build Coastguard Worker   kYCrCb,
38*0a9764feSAndroid Build Coastguard Worker };
39*0a9764feSAndroid Build Coastguard Worker 
40*0a9764feSAndroid Build Coastguard Worker struct DroidYuvFormat {
41*0a9764feSAndroid Build Coastguard Worker   /* Lookup keys */
42*0a9764feSAndroid Build Coastguard Worker   uint32_t native;                /* HAL_PIXEL_FORMAT_ */
43*0a9764feSAndroid Build Coastguard Worker   enum chroma_order chroma_order; /* chroma order is {Cb, Cr} or {Cr, Cb} */
44*0a9764feSAndroid Build Coastguard Worker   size_t chroma_step; /* Distance in bytes between subsequent chroma pixels. */
45*0a9764feSAndroid Build Coastguard Worker 
46*0a9764feSAndroid Build Coastguard Worker   /* Result */
47*0a9764feSAndroid Build Coastguard Worker   int fourcc; /* DRM_FORMAT_ */
48*0a9764feSAndroid Build Coastguard Worker };
49*0a9764feSAndroid Build Coastguard Worker 
50*0a9764feSAndroid Build Coastguard Worker #ifndef DRM_FORMAT_XYUV8888
51*0a9764feSAndroid Build Coastguard Worker #define DRM_FORMAT_XYUV8888 \
52*0a9764feSAndroid Build Coastguard Worker   fourcc_code('X', 'Y', 'U', 'V') /* [31:0] X:Y:Cb:Cr 8:8:8:8 little endian */
53*0a9764feSAndroid Build Coastguard Worker #endif
54*0a9764feSAndroid Build Coastguard Worker 
55*0a9764feSAndroid Build Coastguard Worker /* The following table is used to look up a DRI image FourCC based
56*0a9764feSAndroid Build Coastguard Worker  * on native format and information contained in android_ycbcr struct. */
57*0a9764feSAndroid Build Coastguard Worker static const struct DroidYuvFormat kDroidYuvFormats[] = {
58*0a9764feSAndroid Build Coastguard Worker     /* Native format, YCrCb, Chroma step, DRI image FourCC */
59*0a9764feSAndroid Build Coastguard Worker     {HAL_PIXEL_FORMAT_YCbCr_420_888, kYCbCr, 2, DRM_FORMAT_NV12},
60*0a9764feSAndroid Build Coastguard Worker     {HAL_PIXEL_FORMAT_YCbCr_420_888, kYCbCr, 1, DRM_FORMAT_YUV420},
61*0a9764feSAndroid Build Coastguard Worker     {HAL_PIXEL_FORMAT_YCbCr_420_888, kYCrCb, 1, DRM_FORMAT_YVU420},
62*0a9764feSAndroid Build Coastguard Worker     {HAL_PIXEL_FORMAT_YV12, kYCrCb, 1, DRM_FORMAT_YVU420},
63*0a9764feSAndroid Build Coastguard Worker     /* HACK: See droid_create_image_from_prime_fds() and
64*0a9764feSAndroid Build Coastguard Worker      * https://issuetracker.google.com/32077885. */
65*0a9764feSAndroid Build Coastguard Worker     {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCbCr, 2, DRM_FORMAT_NV12},
66*0a9764feSAndroid Build Coastguard Worker     {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCbCr, 1, DRM_FORMAT_YUV420},
67*0a9764feSAndroid Build Coastguard Worker     {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCrCb, 1, DRM_FORMAT_YVU420},
68*0a9764feSAndroid Build Coastguard Worker     {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCrCb, 1, DRM_FORMAT_AYUV},
69*0a9764feSAndroid Build Coastguard Worker     {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCrCb, 1, DRM_FORMAT_XYUV8888},
70*0a9764feSAndroid Build Coastguard Worker };
71*0a9764feSAndroid Build Coastguard Worker 
72*0a9764feSAndroid Build Coastguard Worker #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
73*0a9764feSAndroid Build Coastguard Worker 
get_fourcc_yuv(uint32_t native,enum chroma_order chroma_order,size_t chroma_step)74*0a9764feSAndroid Build Coastguard Worker static uint32_t get_fourcc_yuv(uint32_t native, enum chroma_order chroma_order,
75*0a9764feSAndroid Build Coastguard Worker                                size_t chroma_step) {
76*0a9764feSAndroid Build Coastguard Worker   for (auto droid_yuv_format : kDroidYuvFormats)
77*0a9764feSAndroid Build Coastguard Worker     if (droid_yuv_format.native == native &&
78*0a9764feSAndroid Build Coastguard Worker         droid_yuv_format.chroma_order == chroma_order &&
79*0a9764feSAndroid Build Coastguard Worker         droid_yuv_format.chroma_step == chroma_step)
80*0a9764feSAndroid Build Coastguard Worker       return droid_yuv_format.fourcc;
81*0a9764feSAndroid Build Coastguard Worker 
82*0a9764feSAndroid Build Coastguard Worker   return UINT32_MAX;
83*0a9764feSAndroid Build Coastguard Worker }
84*0a9764feSAndroid Build Coastguard Worker 
is_yuv(uint32_t native)85*0a9764feSAndroid Build Coastguard Worker static bool is_yuv(uint32_t native) {
86*0a9764feSAndroid Build Coastguard Worker   // NOLINTNEXTLINE(readability-use-anyofallof)
87*0a9764feSAndroid Build Coastguard Worker   for (auto droid_yuv_format : kDroidYuvFormats)
88*0a9764feSAndroid Build Coastguard Worker     if (droid_yuv_format.native == native)
89*0a9764feSAndroid Build Coastguard Worker       return true;
90*0a9764feSAndroid Build Coastguard Worker 
91*0a9764feSAndroid Build Coastguard Worker   return false;
92*0a9764feSAndroid Build Coastguard Worker }
93*0a9764feSAndroid Build Coastguard Worker 
GetYuvPlaneInfo(uint32_t hal_format,int num_fds,buffer_handle_t handle,BufferInfo * bo)94*0a9764feSAndroid Build Coastguard Worker bool BufferInfoLibdrm::GetYuvPlaneInfo(uint32_t hal_format, int num_fds,
95*0a9764feSAndroid Build Coastguard Worker                                        buffer_handle_t handle, BufferInfo *bo) {
96*0a9764feSAndroid Build Coastguard Worker   struct android_ycbcr ycbcr {};
97*0a9764feSAndroid Build Coastguard Worker   enum chroma_order chroma_order {};
98*0a9764feSAndroid Build Coastguard Worker   int ret = 0;
99*0a9764feSAndroid Build Coastguard Worker 
100*0a9764feSAndroid Build Coastguard Worker   if (!gralloc_->lock_ycbcr) {
101*0a9764feSAndroid Build Coastguard Worker     static std::once_flag once;
102*0a9764feSAndroid Build Coastguard Worker     std::call_once(once,
103*0a9764feSAndroid Build Coastguard Worker                    []() { ALOGW("Gralloc does not support lock_ycbcr()"); });
104*0a9764feSAndroid Build Coastguard Worker     return false;
105*0a9764feSAndroid Build Coastguard Worker   }
106*0a9764feSAndroid Build Coastguard Worker 
107*0a9764feSAndroid Build Coastguard Worker   memset(&ycbcr, 0, sizeof(ycbcr));
108*0a9764feSAndroid Build Coastguard Worker   ret = gralloc_->lock_ycbcr(gralloc_, handle, 0, 0, 0, 0, 0, &ycbcr);
109*0a9764feSAndroid Build Coastguard Worker   if (ret) {
110*0a9764feSAndroid Build Coastguard Worker     ALOGW("gralloc->lock_ycbcr failed: %d", ret);
111*0a9764feSAndroid Build Coastguard Worker     return false;
112*0a9764feSAndroid Build Coastguard Worker   }
113*0a9764feSAndroid Build Coastguard Worker   gralloc_->unlock(gralloc_, handle);
114*0a9764feSAndroid Build Coastguard Worker 
115*0a9764feSAndroid Build Coastguard Worker   /* When lock_ycbcr's usage argument contains no SW_READ/WRITE flags
116*0a9764feSAndroid Build Coastguard Worker    * it will return the .y/.cb/.cr pointers based on a NULL pointer,
117*0a9764feSAndroid Build Coastguard Worker    * so they can be interpreted as offsets. */
118*0a9764feSAndroid Build Coastguard Worker   bo->offsets[0] = (size_t)ycbcr.y;
119*0a9764feSAndroid Build Coastguard Worker   /* We assume here that all the planes are located in one DMA-buf. */
120*0a9764feSAndroid Build Coastguard Worker   if ((size_t)ycbcr.cr < (size_t)ycbcr.cb) {
121*0a9764feSAndroid Build Coastguard Worker     chroma_order = kYCrCb;
122*0a9764feSAndroid Build Coastguard Worker     bo->offsets[1] = (size_t)ycbcr.cr;
123*0a9764feSAndroid Build Coastguard Worker     bo->offsets[2] = (size_t)ycbcr.cb;
124*0a9764feSAndroid Build Coastguard Worker   } else {
125*0a9764feSAndroid Build Coastguard Worker     chroma_order = kYCbCr;
126*0a9764feSAndroid Build Coastguard Worker     bo->offsets[1] = (size_t)ycbcr.cb;
127*0a9764feSAndroid Build Coastguard Worker     bo->offsets[2] = (size_t)ycbcr.cr;
128*0a9764feSAndroid Build Coastguard Worker   }
129*0a9764feSAndroid Build Coastguard Worker 
130*0a9764feSAndroid Build Coastguard Worker   /* .ystride is the line length (in bytes) of the Y plane,
131*0a9764feSAndroid Build Coastguard Worker    * .cstride is the line length (in bytes) of any of the remaining
132*0a9764feSAndroid Build Coastguard Worker    * Cb/Cr/CbCr planes, assumed to be the same for Cb and Cr for fully
133*0a9764feSAndroid Build Coastguard Worker    * planar formats. */
134*0a9764feSAndroid Build Coastguard Worker   bo->pitches[0] = ycbcr.ystride;
135*0a9764feSAndroid Build Coastguard Worker   bo->pitches[1] = bo->pitches[2] = ycbcr.cstride;
136*0a9764feSAndroid Build Coastguard Worker 
137*0a9764feSAndroid Build Coastguard Worker   /* .chroma_step is the byte distance between the same chroma channel
138*0a9764feSAndroid Build Coastguard Worker    * values of subsequent pixels, assumed to be the same for Cb and Cr. */
139*0a9764feSAndroid Build Coastguard Worker   bo->format = get_fourcc_yuv(hal_format, chroma_order, ycbcr.chroma_step);
140*0a9764feSAndroid Build Coastguard Worker   if (bo->format == UINT32_MAX) {
141*0a9764feSAndroid Build Coastguard Worker     ALOGW(
142*0a9764feSAndroid Build Coastguard Worker         "unsupported YUV format, native = %x, chroma_order = %s, chroma_step = "
143*0a9764feSAndroid Build Coastguard Worker         "%d",
144*0a9764feSAndroid Build Coastguard Worker         hal_format, chroma_order == kYCbCr ? "YCbCr" : "YCrCb",
145*0a9764feSAndroid Build Coastguard Worker         (int)ycbcr.chroma_step);
146*0a9764feSAndroid Build Coastguard Worker     return false;
147*0a9764feSAndroid Build Coastguard Worker   }
148*0a9764feSAndroid Build Coastguard Worker 
149*0a9764feSAndroid Build Coastguard Worker   /*
150*0a9764feSAndroid Build Coastguard Worker    * Since this is EGL_NATIVE_BUFFER_ANDROID don't assume that
151*0a9764feSAndroid Build Coastguard Worker    * the single-fd case cannot happen.  So handle eithe single
152*0a9764feSAndroid Build Coastguard Worker    * fd or fd-per-plane case:
153*0a9764feSAndroid Build Coastguard Worker    */
154*0a9764feSAndroid Build Coastguard Worker   if (num_fds == 1) {
155*0a9764feSAndroid Build Coastguard Worker     bo->prime_fds[2] = bo->prime_fds[1] = bo->prime_fds[0];
156*0a9764feSAndroid Build Coastguard Worker   } else {
157*0a9764feSAndroid Build Coastguard Worker     const int expected_planes = (ycbcr.chroma_step == 2) ? 2 : 3;
158*0a9764feSAndroid Build Coastguard Worker     if (num_fds != expected_planes)
159*0a9764feSAndroid Build Coastguard Worker       return false;
160*0a9764feSAndroid Build Coastguard Worker   }
161*0a9764feSAndroid Build Coastguard Worker 
162*0a9764feSAndroid Build Coastguard Worker   return true;
163*0a9764feSAndroid Build Coastguard Worker }
164*0a9764feSAndroid Build Coastguard Worker 
GetBoInfo(buffer_handle_t handle)165*0a9764feSAndroid Build Coastguard Worker auto BufferInfoLibdrm::GetBoInfo(buffer_handle_t handle)
166*0a9764feSAndroid Build Coastguard Worker     -> std::optional<BufferInfo> {
167*0a9764feSAndroid Build Coastguard Worker   gralloc_handle_t *gr_handle = gralloc_handle(handle);
168*0a9764feSAndroid Build Coastguard Worker   if (!gr_handle)
169*0a9764feSAndroid Build Coastguard Worker     return {};
170*0a9764feSAndroid Build Coastguard Worker 
171*0a9764feSAndroid Build Coastguard Worker   BufferInfo bi{};
172*0a9764feSAndroid Build Coastguard Worker 
173*0a9764feSAndroid Build Coastguard Worker   bi.width = gr_handle->width;
174*0a9764feSAndroid Build Coastguard Worker   bi.height = gr_handle->height;
175*0a9764feSAndroid Build Coastguard Worker 
176*0a9764feSAndroid Build Coastguard Worker #if GRALLOC_HANDLE_VERSION < 4
177*0a9764feSAndroid Build Coastguard Worker   static std::once_flag once;
178*0a9764feSAndroid Build Coastguard Worker   std::call_once(once, []() {
179*0a9764feSAndroid Build Coastguard Worker     ALOGE(
180*0a9764feSAndroid Build Coastguard Worker         "libdrm < v2.4.97 has broken gralloc_handle structure. Please update.");
181*0a9764feSAndroid Build Coastguard Worker   });
182*0a9764feSAndroid Build Coastguard Worker #endif
183*0a9764feSAndroid Build Coastguard Worker #if GRALLOC_HANDLE_VERSION == 4
184*0a9764feSAndroid Build Coastguard Worker   bi.modifiers[0] = gr_handle->modifier;
185*0a9764feSAndroid Build Coastguard Worker #endif
186*0a9764feSAndroid Build Coastguard Worker 
187*0a9764feSAndroid Build Coastguard Worker   bi.prime_fds[0] = gr_handle->prime_fd;
188*0a9764feSAndroid Build Coastguard Worker 
189*0a9764feSAndroid Build Coastguard Worker   if (is_yuv(gr_handle->format)) {
190*0a9764feSAndroid Build Coastguard Worker     if (!GetYuvPlaneInfo(gr_handle->format, handle->numFds, handle, &bi))
191*0a9764feSAndroid Build Coastguard Worker       return {};
192*0a9764feSAndroid Build Coastguard Worker   } else {
193*0a9764feSAndroid Build Coastguard Worker     bi.pitches[0] = gr_handle->stride;
194*0a9764feSAndroid Build Coastguard Worker     bi.offsets[0] = 0;
195*0a9764feSAndroid Build Coastguard Worker 
196*0a9764feSAndroid Build Coastguard Worker     /* FOSS graphic components (gbm_gralloc, mesa3d) are translating
197*0a9764feSAndroid Build Coastguard Worker      * HAL_PIXEL_FORMAT_RGB_565 to DRM_FORMAT_RGB565 without swapping
198*0a9764feSAndroid Build Coastguard Worker      * the R and B components. Same must be done here. */
199*0a9764feSAndroid Build Coastguard Worker     switch (gr_handle->format) {
200*0a9764feSAndroid Build Coastguard Worker       case HAL_PIXEL_FORMAT_RGB_565:
201*0a9764feSAndroid Build Coastguard Worker         bi.format = DRM_FORMAT_RGB565;
202*0a9764feSAndroid Build Coastguard Worker         break;
203*0a9764feSAndroid Build Coastguard Worker       default:
204*0a9764feSAndroid Build Coastguard Worker         bi.format = ConvertHalFormatToDrm(gr_handle->format);
205*0a9764feSAndroid Build Coastguard Worker     }
206*0a9764feSAndroid Build Coastguard Worker 
207*0a9764feSAndroid Build Coastguard Worker     if (bi.format == DRM_FORMAT_INVALID)
208*0a9764feSAndroid Build Coastguard Worker       return {};
209*0a9764feSAndroid Build Coastguard Worker   }
210*0a9764feSAndroid Build Coastguard Worker 
211*0a9764feSAndroid Build Coastguard Worker   return bi;
212*0a9764feSAndroid Build Coastguard Worker }
213*0a9764feSAndroid Build Coastguard Worker 
214*0a9764feSAndroid Build Coastguard Worker constexpr char gbm_gralloc_module_name[] = "GBM Memory Allocator";
215*0a9764feSAndroid Build Coastguard Worker constexpr char drm_gralloc_module_name[] = "DRM Memory Allocator";
216*0a9764feSAndroid Build Coastguard Worker 
ValidateGralloc()217*0a9764feSAndroid Build Coastguard Worker int BufferInfoLibdrm::ValidateGralloc() {
218*0a9764feSAndroid Build Coastguard Worker   if (strcmp(gralloc_->common.name, drm_gralloc_module_name) != 0 &&
219*0a9764feSAndroid Build Coastguard Worker       strcmp(gralloc_->common.name, gbm_gralloc_module_name) != 0) {
220*0a9764feSAndroid Build Coastguard Worker     ALOGE(
221*0a9764feSAndroid Build Coastguard Worker         "Gralloc name isn't valid: Expected: \"%s\" or \"%s\", Actual: \"%s\"",
222*0a9764feSAndroid Build Coastguard Worker         gbm_gralloc_module_name, drm_gralloc_module_name,
223*0a9764feSAndroid Build Coastguard Worker         gralloc_->common.name);
224*0a9764feSAndroid Build Coastguard Worker     return -EINVAL;
225*0a9764feSAndroid Build Coastguard Worker   }
226*0a9764feSAndroid Build Coastguard Worker 
227*0a9764feSAndroid Build Coastguard Worker   return 0;
228*0a9764feSAndroid Build Coastguard Worker }
229*0a9764feSAndroid Build Coastguard Worker 
230*0a9764feSAndroid Build Coastguard Worker }  // namespace android
231