xref: /aosp_15_r20/external/mesa3d/src/util/u_gralloc/u_gralloc_internal.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright © 2021, Google Inc.
5  * Copyright (C) 2023 Roman Stratiienko ([email protected])
6  * SPDX-License-Identifier: MIT
7  */
8 
9 #include "u_gralloc_internal.h"
10 
11 #include <hardware/gralloc.h>
12 #include <errno.h>
13 
14 #include "drm-uapi/drm_fourcc.h"
15 #include "util/log.h"
16 
17 enum chroma_order {
18    YCbCr,
19    YCrCb,
20 };
21 
22 struct droid_yuv_format {
23    /* Lookup keys */
24    int native;                     /* HAL_PIXEL_FORMAT_ */
25    enum chroma_order chroma_order; /* chroma order is {Cb, Cr} or {Cr, Cb} */
26    int chroma_step; /* Distance in bytes between subsequent chroma pixels. */
27 
28    /* Result */
29    int fourcc; /* DRM_FORMAT_ */
30 };
31 
32 /* The following table is used to look up a DRI image FourCC based
33  * on native format and information contained in android_ycbcr struct. */
34 static const struct droid_yuv_format droid_yuv_formats[] = {
35    /* Native format, YCrCb, Chroma step, DRI image FourCC */
36    {HAL_PIXEL_FORMAT_YCbCr_420_888, YCbCr, 2, DRM_FORMAT_NV12},
37    {HAL_PIXEL_FORMAT_YCbCr_420_888, YCbCr, 1, DRM_FORMAT_YUV420},
38    {HAL_PIXEL_FORMAT_YCbCr_420_888, YCrCb, 1, DRM_FORMAT_YVU420},
39    {HAL_PIXEL_FORMAT_YV12, YCrCb, 1, DRM_FORMAT_YVU420},
40    /* HACK: See droid_create_image_from_prime_fds() and
41     * https://issuetracker.google.com/32077885. */
42    {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCbCr, 2, DRM_FORMAT_NV12},
43    {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCbCr, 1, DRM_FORMAT_YUV420},
44    {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, DRM_FORMAT_YVU420},
45    {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, DRM_FORMAT_AYUV},
46    {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, DRM_FORMAT_XYUV8888},
47 };
48 
49 static int
get_fourcc_yuv(int native,enum chroma_order chroma_order,int chroma_step)50 get_fourcc_yuv(int native, enum chroma_order chroma_order, int chroma_step)
51 {
52    for (int i = 0; i < ARRAY_SIZE(droid_yuv_formats); ++i)
53       if (droid_yuv_formats[i].native == native &&
54           droid_yuv_formats[i].chroma_order == chroma_order &&
55           droid_yuv_formats[i].chroma_step == chroma_step)
56          return droid_yuv_formats[i].fourcc;
57 
58    return -1;
59 }
60 
61 bool
is_hal_format_yuv(int native)62 is_hal_format_yuv(int native)
63 {
64    for (int i = 0; i < ARRAY_SIZE(droid_yuv_formats); ++i)
65       if (droid_yuv_formats[i].native == native)
66          return true;
67 
68    return false;
69 }
70 
71 int
get_hal_format_bpp(int native)72 get_hal_format_bpp(int native)
73 {
74    int bpp;
75 
76    switch (native) {
77    case HAL_PIXEL_FORMAT_RGBA_FP16:
78       bpp = 8;
79       break;
80    case HAL_PIXEL_FORMAT_RGBA_8888:
81    case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
82       /*
83        * HACK: Hardcode this to RGBX_8888 as per cros_gralloc hack.
84        * TODO: Remove this once https://issuetracker.google.com/32077885 is
85        * fixed.
86        */
87    case HAL_PIXEL_FORMAT_RGBX_8888:
88    case HAL_PIXEL_FORMAT_BGRA_8888:
89    case HAL_PIXEL_FORMAT_RGBA_1010102:
90       bpp = 4;
91       break;
92    case HAL_PIXEL_FORMAT_RGB_565:
93       bpp = 2;
94       break;
95    default:
96       bpp = 0;
97       break;
98    }
99 
100    return bpp;
101 }
102 
103 int
get_fourcc_from_hal_format(int native)104 get_fourcc_from_hal_format(int native)
105 {
106    switch (native) {
107    case HAL_PIXEL_FORMAT_RGB_565:
108       return DRM_FORMAT_RGB565;
109    case HAL_PIXEL_FORMAT_BGRA_8888:
110       return DRM_FORMAT_ARGB8888;
111    case HAL_PIXEL_FORMAT_RGBA_8888:
112       return DRM_FORMAT_ABGR8888;
113    case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
114       /*
115        * HACK: Hardcode this to RGBX_8888 as per cros_gralloc hack.
116        * TODO: Remove this once https://issuetracker.google.com/32077885 is
117        * fixed.
118        */
119    case HAL_PIXEL_FORMAT_RGBX_8888:
120       return DRM_FORMAT_XBGR8888;
121    case HAL_PIXEL_FORMAT_RGBA_FP16:
122       return DRM_FORMAT_ABGR16161616F;
123    case HAL_PIXEL_FORMAT_RGBA_1010102:
124       return DRM_FORMAT_ABGR2101010;
125    default:
126       mesa_logw("unsupported native buffer format 0x%x", native);
127    }
128    return -1;
129 }
130 
131 /* Fill the bufferinfo structure using the information from the
132  * android_ycbcr struct. fds[] are not filled by this function.
133  */
134 int
bufferinfo_from_ycbcr(const struct android_ycbcr * ycbcr,struct u_gralloc_buffer_handle * hnd,struct u_gralloc_buffer_basic_info * out)135 bufferinfo_from_ycbcr(const struct android_ycbcr *ycbcr,
136                       struct u_gralloc_buffer_handle *hnd,
137                       struct u_gralloc_buffer_basic_info *out)
138 {
139    enum chroma_order chroma_order =
140       ((size_t)ycbcr->cr < (size_t)ycbcr->cb) ? YCrCb : YCbCr;
141 
142    /* .chroma_step is the byte distance between the same chroma channel
143     * values of subsequent pixels, assumed to be the same for Cb and Cr. */
144    int drm_fourcc =
145       get_fourcc_yuv(hnd->hal_format, chroma_order, ycbcr->chroma_step);
146 
147    if (drm_fourcc == -1) {
148       mesa_logw("unsupported YUV format, native = %x, chroma_order = %s, "
149                 "chroma_step = %zu",
150                 hnd->hal_format, chroma_order == YCbCr ? "YCbCr" : "YCrCb",
151                 ycbcr->chroma_step);
152       return -EINVAL;
153    }
154 
155    out->drm_fourcc = drm_fourcc;
156 
157    out->num_planes = ycbcr->chroma_step == 2 ? 2 : 3;
158    /* When lock_ycbcr's usage argument contains no SW_READ/WRITE flags
159     * it will return the .y/.cb/.cr pointers based on a NULL pointer,
160     * so they can be interpreted as offsets. */
161    out->offsets[0] = (size_t)ycbcr->y;
162    /* We assume here that all the planes are located in one DMA-buf. */
163    if (chroma_order == YCrCb) {
164       out->offsets[1] = (size_t)ycbcr->cr;
165       out->offsets[2] = (size_t)ycbcr->cb;
166    } else {
167       out->offsets[1] = (size_t)ycbcr->cb;
168       out->offsets[2] = (size_t)ycbcr->cr;
169    }
170 
171    /* .ystride is the line length (in bytes) of the Y plane,
172     * .cstride is the line length (in bytes) of any of the remaining
173     * Cb/Cr/CbCr planes, assumed to be the same for Cb and Cr for fully
174     * planar formats. */
175    out->strides[0] = ycbcr->ystride;
176    out->strides[1] = out->strides[2] = ycbcr->cstride;
177 
178    return 0;
179 }
180