blob: e70536b4067ad570b1f67fa6c14ee3ee6a50cd6d [file] [log] [blame]
Roman Stratiienko946126c2020-10-02 19:01:10 +03001/*
Roman Stratiienkob2e9fe22020-10-03 10:52:36 +03002 * Copyright (C) 2020 The Android Open Source Project
Roman Stratiienko946126c2020-10-02 19:01:10 +03003 *
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
Roman Stratiienkob2e9fe22020-10-03 10:52:36 +030017#define LOG_TAG "hwc-bufferinfo-libdrm"
Roman Stratiienko946126c2020-10-02 19:01:10 +030018
Roman Stratiienkob2e9fe22020-10-03 10:52:36 +030019#include "BufferInfoLibdrm.h"
Roman Stratiienko946126c2020-10-02 19:01:10 +030020
Roman Stratiienko946126c2020-10-02 19:01:10 +030021#include <gralloc_handle.h>
22#include <hardware/gralloc.h>
Roman Stratiienko946126c2020-10-02 19:01:10 +030023#include <xf86drm.h>
24#include <xf86drmMode.h>
25
Roman Stratiienko1e053b42021-10-25 22:54:20 +030026#include <mutex>
27
Roman Stratiienkod21071f2021-03-09 21:56:50 +020028#include "utils/log.h"
29#include "utils/properties.h"
30
Roman Stratiienko946126c2020-10-02 19:01:10 +030031namespace android {
32
Roman Stratiienkob2e9fe22020-10-03 10:52:36 +030033LEGACY_BUFFER_INFO_GETTER(BufferInfoLibdrm);
Roman Stratiienko946126c2020-10-02 19:01:10 +030034
35enum chroma_order {
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +020036 kYCbCr,
37 kYCrCb,
Roman Stratiienko946126c2020-10-02 19:01:10 +030038};
39
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +020040struct DroidYuvFormat {
Roman Stratiienko946126c2020-10-02 19:01:10 +030041 /* Lookup keys */
Roman Stratiienkod26619b2021-08-04 19:55:37 +030042 uint32_t native; /* HAL_PIXEL_FORMAT_ */
Roman Stratiienko946126c2020-10-02 19:01:10 +030043 enum chroma_order chroma_order; /* chroma order is {Cb, Cr} or {Cr, Cb} */
Roman Stratiienkod26619b2021-08-04 19:55:37 +030044 size_t chroma_step; /* Distance in bytes between subsequent chroma pixels. */
Roman Stratiienko946126c2020-10-02 19:01:10 +030045
46 /* Result */
47 int fourcc; /* DRM_FORMAT_ */
48};
49
50/* The following table is used to look up a DRI image FourCC based
51 * on native format and information contained in android_ycbcr struct. */
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +020052static const struct DroidYuvFormat kDroidYuvFormats[] = {
Roman Stratiienko946126c2020-10-02 19:01:10 +030053 /* Native format, YCrCb, Chroma step, DRI image FourCC */
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +020054 {HAL_PIXEL_FORMAT_YCbCr_420_888, kYCbCr, 2, DRM_FORMAT_NV12},
55 {HAL_PIXEL_FORMAT_YCbCr_420_888, kYCbCr, 1, DRM_FORMAT_YUV420},
56 {HAL_PIXEL_FORMAT_YCbCr_420_888, kYCrCb, 1, DRM_FORMAT_YVU420},
57 {HAL_PIXEL_FORMAT_YV12, kYCrCb, 1, DRM_FORMAT_YVU420},
Roman Stratiienko946126c2020-10-02 19:01:10 +030058 /* HACK: See droid_create_image_from_prime_fds() and
59 * https://issuetracker.google.com/32077885. */
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +020060 {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCbCr, 2, DRM_FORMAT_NV12},
61 {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCbCr, 1, DRM_FORMAT_YUV420},
62 {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCrCb, 1, DRM_FORMAT_YVU420},
63 {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCrCb, 1, DRM_FORMAT_AYUV},
64 {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCrCb, 1, DRM_FORMAT_XYUV8888},
Roman Stratiienko946126c2020-10-02 19:01:10 +030065};
66
67#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
68
Roman Stratiienkod26619b2021-08-04 19:55:37 +030069static int get_fourcc_yuv(uint32_t native, enum chroma_order chroma_order,
70 size_t chroma_step) {
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +020071 for (auto droid_yuv_format : kDroidYuvFormats)
72 if (droid_yuv_format.native == native &&
73 droid_yuv_format.chroma_order == chroma_order &&
74 droid_yuv_format.chroma_step == chroma_step)
75 return droid_yuv_format.fourcc;
Roman Stratiienko946126c2020-10-02 19:01:10 +030076
77 return -1;
78}
79
Roman Stratiienkod26619b2021-08-04 19:55:37 +030080static bool is_yuv(uint32_t native) {
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +020081 for (auto droid_yuv_format : kDroidYuvFormats)
82 if (droid_yuv_format.native == native)
Roman Stratiienko946126c2020-10-02 19:01:10 +030083 return true;
84
85 return false;
86}
87
Roman Stratiienkob2e9fe22020-10-03 10:52:36 +030088bool BufferInfoLibdrm::GetYuvPlaneInfo(int num_fds, buffer_handle_t handle,
89 hwc_drm_bo_t *bo) {
Roman Stratiienkob3b5c1e2021-02-15 13:44:19 +020090 struct android_ycbcr ycbcr {};
91 enum chroma_order chroma_order {};
92 int ret = 0;
Roman Stratiienko946126c2020-10-02 19:01:10 +030093
94 if (!gralloc_->lock_ycbcr) {
95 static std::once_flag once;
96 std::call_once(once,
97 []() { ALOGW("Gralloc does not support lock_ycbcr()"); });
98 return false;
99 }
100
101 memset(&ycbcr, 0, sizeof(ycbcr));
102 ret = gralloc_->lock_ycbcr(gralloc_, handle, 0, 0, 0, 0, 0, &ycbcr);
103 if (ret) {
104 ALOGW("gralloc->lock_ycbcr failed: %d", ret);
105 return false;
106 }
107 gralloc_->unlock(gralloc_, handle);
108
109 /* When lock_ycbcr's usage argument contains no SW_READ/WRITE flags
110 * it will return the .y/.cb/.cr pointers based on a NULL pointer,
111 * so they can be interpreted as offsets. */
112 bo->offsets[0] = (size_t)ycbcr.y;
113 /* We assume here that all the planes are located in one DMA-buf. */
114 if ((size_t)ycbcr.cr < (size_t)ycbcr.cb) {
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +0200115 chroma_order = kYCrCb;
Roman Stratiienko946126c2020-10-02 19:01:10 +0300116 bo->offsets[1] = (size_t)ycbcr.cr;
117 bo->offsets[2] = (size_t)ycbcr.cb;
118 } else {
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +0200119 chroma_order = kYCbCr;
Roman Stratiienko946126c2020-10-02 19:01:10 +0300120 bo->offsets[1] = (size_t)ycbcr.cb;
121 bo->offsets[2] = (size_t)ycbcr.cr;
122 }
123
124 /* .ystride is the line length (in bytes) of the Y plane,
125 * .cstride is the line length (in bytes) of any of the remaining
126 * Cb/Cr/CbCr planes, assumed to be the same for Cb and Cr for fully
127 * planar formats. */
128 bo->pitches[0] = ycbcr.ystride;
129 bo->pitches[1] = bo->pitches[2] = ycbcr.cstride;
130
131 /* .chroma_step is the byte distance between the same chroma channel
132 * values of subsequent pixels, assumed to be the same for Cb and Cr. */
133 bo->format = get_fourcc_yuv(bo->hal_format, chroma_order, ycbcr.chroma_step);
134 if (bo->format == -1) {
135 ALOGW(
136 "unsupported YUV format, native = %x, chroma_order = %s, chroma_step = "
137 "%d",
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +0200138 bo->hal_format, chroma_order == kYCbCr ? "YCbCr" : "YCrCb",
Roman Stratiienko946126c2020-10-02 19:01:10 +0300139 (int)ycbcr.chroma_step);
140 return false;
141 }
142
143 /*
144 * Since this is EGL_NATIVE_BUFFER_ANDROID don't assume that
145 * the single-fd case cannot happen. So handle eithe single
146 * fd or fd-per-plane case:
147 */
148 if (num_fds == 1) {
149 bo->prime_fds[2] = bo->prime_fds[1] = bo->prime_fds[0];
150 } else {
151 int expected_planes = (ycbcr.chroma_step == 2) ? 2 : 3;
152 if (num_fds != expected_planes)
153 return false;
154 }
155
156 return true;
157}
158
Roman Stratiienkob2e9fe22020-10-03 10:52:36 +0300159int BufferInfoLibdrm::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) {
Roman Stratiienko946126c2020-10-02 19:01:10 +0300160 gralloc_handle_t *gr_handle = gralloc_handle(handle);
161 if (!gr_handle)
162 return -EINVAL;
163
164 bo->width = gr_handle->width;
165 bo->height = gr_handle->height;
166 bo->hal_format = gr_handle->format;
167
168#if GRALLOC_HANDLE_VERSION < 4
169 static std::once_flag once;
170 std::call_once(once, []() {
171 ALOGE(
172 "libdrm < v2.4.97 has broken gralloc_handle structure. Please update.");
173 });
174#endif
175#if GRALLOC_HANDLE_VERSION == 4
176 bo->modifiers[0] = gr_handle->modifier;
Roman Stratiienko946126c2020-10-02 19:01:10 +0300177#endif
178
179 bo->usage = gr_handle->usage;
180 bo->prime_fds[0] = gr_handle->prime_fd;
181
182 if (is_yuv(gr_handle->format)) {
183 if (!GetYuvPlaneInfo(handle->numFds, handle, bo))
184 return -EINVAL;
185 } else {
186 bo->pitches[0] = gr_handle->stride;
187 bo->offsets[0] = 0;
Roman Stratiienko32819fe2020-10-30 13:53:00 +0200188
189 /* FOSS graphic components (gbm_gralloc, mesa3d) are translating
190 * HAL_PIXEL_FORMAT_RGB_565 to DRM_FORMAT_RGB565 without swapping
191 * the R and B components. Same must be done here. */
192 switch (bo->hal_format) {
193 case HAL_PIXEL_FORMAT_RGB_565:
194 bo->format = DRM_FORMAT_RGB565;
195 break;
196 default:
197 bo->format = ConvertHalFormatToDrm(gr_handle->format);
198 }
199
Roman Stratiienko946126c2020-10-02 19:01:10 +0300200 if (bo->format == DRM_FORMAT_INVALID)
201 return -EINVAL;
202 }
203
Roman Stratiienko946126c2020-10-02 19:01:10 +0300204 return 0;
205}
206
Roman Stratiienko39d8f7e2021-11-30 17:06:44 +0200207constexpr char gbm_gralloc_module_name[] = "GBM Memory Allocator";
208constexpr char drm_gralloc_module_name[] = "DRM Memory Allocator";
209
210int BufferInfoLibdrm::ValidateGralloc() {
211 if (strcmp(gralloc_->common.name, drm_gralloc_module_name) != 0 &&
212 strcmp(gralloc_->common.name, gbm_gralloc_module_name) != 0) {
213 ALOGE(
214 "Gralloc name isn't valid: Expected: \"%s\" or \"%s\", Actual: \"%s\"",
215 gbm_gralloc_module_name, drm_gralloc_module_name,
216 gralloc_->common.name);
217 return -EINVAL;
218 }
219
220 return 0;
221}
222
Roman Stratiienko946126c2020-10-02 19:01:10 +0300223} // namespace android