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