blob: 4f942fe30b49fb3b5810b10c32984406d8b67979 [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 Stratiienkodeb77352021-12-06 12:59:26 +020069static uint32_t 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
Roman Stratiienkodeb77352021-12-06 12:59:26 +020077 return UINT32_MAX;
Roman Stratiienko946126c2020-10-02 19:01:10 +030078}
79
Roman Stratiienkod26619b2021-08-04 19:55:37 +030080static bool is_yuv(uint32_t native) {
Roman Stratiienko568e5982022-01-04 11:42:33 +020081 // NOLINTNEXTLINE(readability-use-anyofallof)
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +020082 for (auto droid_yuv_format : kDroidYuvFormats)
83 if (droid_yuv_format.native == native)
Roman Stratiienko946126c2020-10-02 19:01:10 +030084 return true;
85
86 return false;
87}
88
Roman Stratiienkob2e9fe22020-10-03 10:52:36 +030089bool BufferInfoLibdrm::GetYuvPlaneInfo(int num_fds, buffer_handle_t handle,
90 hwc_drm_bo_t *bo) {
Roman Stratiienkob3b5c1e2021-02-15 13:44:19 +020091 struct android_ycbcr ycbcr {};
92 enum chroma_order chroma_order {};
93 int ret = 0;
Roman Stratiienko946126c2020-10-02 19:01:10 +030094
95 if (!gralloc_->lock_ycbcr) {
96 static std::once_flag once;
97 std::call_once(once,
98 []() { ALOGW("Gralloc does not support lock_ycbcr()"); });
99 return false;
100 }
101
102 memset(&ycbcr, 0, sizeof(ycbcr));
103 ret = gralloc_->lock_ycbcr(gralloc_, handle, 0, 0, 0, 0, 0, &ycbcr);
104 if (ret) {
105 ALOGW("gralloc->lock_ycbcr failed: %d", ret);
106 return false;
107 }
108 gralloc_->unlock(gralloc_, handle);
109
110 /* When lock_ycbcr's usage argument contains no SW_READ/WRITE flags
111 * it will return the .y/.cb/.cr pointers based on a NULL pointer,
112 * so they can be interpreted as offsets. */
113 bo->offsets[0] = (size_t)ycbcr.y;
114 /* We assume here that all the planes are located in one DMA-buf. */
115 if ((size_t)ycbcr.cr < (size_t)ycbcr.cb) {
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +0200116 chroma_order = kYCrCb;
Roman Stratiienko946126c2020-10-02 19:01:10 +0300117 bo->offsets[1] = (size_t)ycbcr.cr;
118 bo->offsets[2] = (size_t)ycbcr.cb;
119 } else {
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +0200120 chroma_order = kYCbCr;
Roman Stratiienko946126c2020-10-02 19:01:10 +0300121 bo->offsets[1] = (size_t)ycbcr.cb;
122 bo->offsets[2] = (size_t)ycbcr.cr;
123 }
124
125 /* .ystride is the line length (in bytes) of the Y plane,
126 * .cstride is the line length (in bytes) of any of the remaining
127 * Cb/Cr/CbCr planes, assumed to be the same for Cb and Cr for fully
128 * planar formats. */
129 bo->pitches[0] = ycbcr.ystride;
130 bo->pitches[1] = bo->pitches[2] = ycbcr.cstride;
131
132 /* .chroma_step is the byte distance between the same chroma channel
133 * values of subsequent pixels, assumed to be the same for Cb and Cr. */
134 bo->format = get_fourcc_yuv(bo->hal_format, chroma_order, ycbcr.chroma_step);
Roman Stratiienkodeb77352021-12-06 12:59:26 +0200135 if (bo->format == UINT32_MAX) {
Roman Stratiienko946126c2020-10-02 19:01:10 +0300136 ALOGW(
137 "unsupported YUV format, native = %x, chroma_order = %s, chroma_step = "
138 "%d",
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +0200139 bo->hal_format, chroma_order == kYCbCr ? "YCbCr" : "YCrCb",
Roman Stratiienko946126c2020-10-02 19:01:10 +0300140 (int)ycbcr.chroma_step);
141 return false;
142 }
143
144 /*
145 * Since this is EGL_NATIVE_BUFFER_ANDROID don't assume that
146 * the single-fd case cannot happen. So handle eithe single
147 * fd or fd-per-plane case:
148 */
149 if (num_fds == 1) {
150 bo->prime_fds[2] = bo->prime_fds[1] = bo->prime_fds[0];
151 } else {
152 int expected_planes = (ycbcr.chroma_step == 2) ? 2 : 3;
153 if (num_fds != expected_planes)
154 return false;
155 }
156
157 return true;
158}
159
Roman Stratiienkob2e9fe22020-10-03 10:52:36 +0300160int BufferInfoLibdrm::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) {
Roman Stratiienko946126c2020-10-02 19:01:10 +0300161 gralloc_handle_t *gr_handle = gralloc_handle(handle);
162 if (!gr_handle)
163 return -EINVAL;
164
165 bo->width = gr_handle->width;
166 bo->height = gr_handle->height;
167 bo->hal_format = gr_handle->format;
168
169#if GRALLOC_HANDLE_VERSION < 4
170 static std::once_flag once;
171 std::call_once(once, []() {
172 ALOGE(
173 "libdrm < v2.4.97 has broken gralloc_handle structure. Please update.");
174 });
175#endif
176#if GRALLOC_HANDLE_VERSION == 4
177 bo->modifiers[0] = gr_handle->modifier;
Roman Stratiienko946126c2020-10-02 19:01:10 +0300178#endif
179
180 bo->usage = gr_handle->usage;
181 bo->prime_fds[0] = gr_handle->prime_fd;
182
183 if (is_yuv(gr_handle->format)) {
184 if (!GetYuvPlaneInfo(handle->numFds, handle, bo))
185 return -EINVAL;
186 } else {
187 bo->pitches[0] = gr_handle->stride;
188 bo->offsets[0] = 0;
Roman Stratiienko32819fe2020-10-30 13:53:00 +0200189
190 /* FOSS graphic components (gbm_gralloc, mesa3d) are translating
191 * HAL_PIXEL_FORMAT_RGB_565 to DRM_FORMAT_RGB565 without swapping
192 * the R and B components. Same must be done here. */
193 switch (bo->hal_format) {
194 case HAL_PIXEL_FORMAT_RGB_565:
195 bo->format = DRM_FORMAT_RGB565;
196 break;
197 default:
198 bo->format = ConvertHalFormatToDrm(gr_handle->format);
199 }
200
Roman Stratiienko946126c2020-10-02 19:01:10 +0300201 if (bo->format == DRM_FORMAT_INVALID)
202 return -EINVAL;
203 }
204
Roman Stratiienko946126c2020-10-02 19:01:10 +0300205 return 0;
206}
207
Roman Stratiienko39d8f7e2021-11-30 17:06:44 +0200208constexpr char gbm_gralloc_module_name[] = "GBM Memory Allocator";
209constexpr char drm_gralloc_module_name[] = "DRM Memory Allocator";
210
211int BufferInfoLibdrm::ValidateGralloc() {
212 if (strcmp(gralloc_->common.name, drm_gralloc_module_name) != 0 &&
213 strcmp(gralloc_->common.name, gbm_gralloc_module_name) != 0) {
214 ALOGE(
215 "Gralloc name isn't valid: Expected: \"%s\" or \"%s\", Actual: \"%s\"",
216 gbm_gralloc_module_name, drm_gralloc_module_name,
217 gralloc_->common.name);
218 return -EINVAL;
219 }
220
221 return 0;
222}
223
Roman Stratiienko946126c2020-10-02 19:01:10 +0300224} // namespace android