blob: da89eb5bb132369e47e6f2459fe22a85e42e3bda [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 Stratiienkod21071f2021-03-09 21:56:50 +020026#include "utils/log.h"
27#include "utils/properties.h"
28
Roman Stratiienko946126c2020-10-02 19:01:10 +030029namespace android {
30
Roman Stratiienkob2e9fe22020-10-03 10:52:36 +030031LEGACY_BUFFER_INFO_GETTER(BufferInfoLibdrm);
Roman Stratiienko946126c2020-10-02 19:01:10 +030032
33enum chroma_order {
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +020034 kYCbCr,
35 kYCrCb,
Roman Stratiienko946126c2020-10-02 19:01:10 +030036};
37
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +020038struct DroidYuvFormat {
Roman Stratiienko946126c2020-10-02 19:01:10 +030039 /* Lookup keys */
Roman Stratiienkod26619b2021-08-04 19:55:37 +030040 uint32_t native; /* HAL_PIXEL_FORMAT_ */
Roman Stratiienko946126c2020-10-02 19:01:10 +030041 enum chroma_order chroma_order; /* chroma order is {Cb, Cr} or {Cr, Cb} */
Roman Stratiienkod26619b2021-08-04 19:55:37 +030042 size_t chroma_step; /* Distance in bytes between subsequent chroma pixels. */
Roman Stratiienko946126c2020-10-02 19:01:10 +030043
44 /* Result */
45 int fourcc; /* DRM_FORMAT_ */
46};
47
48/* The following table is used to look up a DRI image FourCC based
49 * on native format and information contained in android_ycbcr struct. */
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +020050static const struct DroidYuvFormat kDroidYuvFormats[] = {
Roman Stratiienko946126c2020-10-02 19:01:10 +030051 /* Native format, YCrCb, Chroma step, DRI image FourCC */
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +020052 {HAL_PIXEL_FORMAT_YCbCr_420_888, kYCbCr, 2, DRM_FORMAT_NV12},
53 {HAL_PIXEL_FORMAT_YCbCr_420_888, kYCbCr, 1, DRM_FORMAT_YUV420},
54 {HAL_PIXEL_FORMAT_YCbCr_420_888, kYCrCb, 1, DRM_FORMAT_YVU420},
55 {HAL_PIXEL_FORMAT_YV12, kYCrCb, 1, DRM_FORMAT_YVU420},
Roman Stratiienko946126c2020-10-02 19:01:10 +030056 /* HACK: See droid_create_image_from_prime_fds() and
57 * https://issuetracker.google.com/32077885. */
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +020058 {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCbCr, 2, DRM_FORMAT_NV12},
59 {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCbCr, 1, DRM_FORMAT_YUV420},
60 {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCrCb, 1, DRM_FORMAT_YVU420},
61 {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCrCb, 1, DRM_FORMAT_AYUV},
62 {HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, kYCrCb, 1, DRM_FORMAT_XYUV8888},
Roman Stratiienko946126c2020-10-02 19:01:10 +030063};
64
65#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
66
Roman Stratiienkod26619b2021-08-04 19:55:37 +030067static int get_fourcc_yuv(uint32_t native, enum chroma_order chroma_order,
68 size_t chroma_step) {
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +020069 for (auto droid_yuv_format : kDroidYuvFormats)
70 if (droid_yuv_format.native == native &&
71 droid_yuv_format.chroma_order == chroma_order &&
72 droid_yuv_format.chroma_step == chroma_step)
73 return droid_yuv_format.fourcc;
Roman Stratiienko946126c2020-10-02 19:01:10 +030074
75 return -1;
76}
77
Roman Stratiienkod26619b2021-08-04 19:55:37 +030078static bool is_yuv(uint32_t native) {
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +020079 for (auto droid_yuv_format : kDroidYuvFormats)
80 if (droid_yuv_format.native == native)
Roman Stratiienko946126c2020-10-02 19:01:10 +030081 return true;
82
83 return false;
84}
85
Roman Stratiienkob2e9fe22020-10-03 10:52:36 +030086bool BufferInfoLibdrm::GetYuvPlaneInfo(int num_fds, buffer_handle_t handle,
87 hwc_drm_bo_t *bo) {
Roman Stratiienkob3b5c1e2021-02-15 13:44:19 +020088 struct android_ycbcr ycbcr {};
89 enum chroma_order chroma_order {};
90 int ret = 0;
Roman Stratiienko946126c2020-10-02 19:01:10 +030091
92 if (!gralloc_->lock_ycbcr) {
93 static std::once_flag once;
94 std::call_once(once,
95 []() { ALOGW("Gralloc does not support lock_ycbcr()"); });
96 return false;
97 }
98
99 memset(&ycbcr, 0, sizeof(ycbcr));
100 ret = gralloc_->lock_ycbcr(gralloc_, handle, 0, 0, 0, 0, 0, &ycbcr);
101 if (ret) {
102 ALOGW("gralloc->lock_ycbcr failed: %d", ret);
103 return false;
104 }
105 gralloc_->unlock(gralloc_, handle);
106
107 /* When lock_ycbcr's usage argument contains no SW_READ/WRITE flags
108 * it will return the .y/.cb/.cr pointers based on a NULL pointer,
109 * so they can be interpreted as offsets. */
110 bo->offsets[0] = (size_t)ycbcr.y;
111 /* We assume here that all the planes are located in one DMA-buf. */
112 if ((size_t)ycbcr.cr < (size_t)ycbcr.cb) {
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +0200113 chroma_order = kYCrCb;
Roman Stratiienko946126c2020-10-02 19:01:10 +0300114 bo->offsets[1] = (size_t)ycbcr.cr;
115 bo->offsets[2] = (size_t)ycbcr.cb;
116 } else {
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +0200117 chroma_order = kYCbCr;
Roman Stratiienko946126c2020-10-02 19:01:10 +0300118 bo->offsets[1] = (size_t)ycbcr.cb;
119 bo->offsets[2] = (size_t)ycbcr.cr;
120 }
121
122 /* .ystride is the line length (in bytes) of the Y plane,
123 * .cstride is the line length (in bytes) of any of the remaining
124 * Cb/Cr/CbCr planes, assumed to be the same for Cb and Cr for fully
125 * planar formats. */
126 bo->pitches[0] = ycbcr.ystride;
127 bo->pitches[1] = bo->pitches[2] = ycbcr.cstride;
128
129 /* .chroma_step is the byte distance between the same chroma channel
130 * values of subsequent pixels, assumed to be the same for Cb and Cr. */
131 bo->format = get_fourcc_yuv(bo->hal_format, chroma_order, ycbcr.chroma_step);
132 if (bo->format == -1) {
133 ALOGW(
134 "unsupported YUV format, native = %x, chroma_order = %s, chroma_step = "
135 "%d",
Roman Stratiienkoe2f2c922021-02-13 10:57:47 +0200136 bo->hal_format, chroma_order == kYCbCr ? "YCbCr" : "YCrCb",
Roman Stratiienko946126c2020-10-02 19:01:10 +0300137 (int)ycbcr.chroma_step);
138 return false;
139 }
140
141 /*
142 * Since this is EGL_NATIVE_BUFFER_ANDROID don't assume that
143 * the single-fd case cannot happen. So handle eithe single
144 * fd or fd-per-plane case:
145 */
146 if (num_fds == 1) {
147 bo->prime_fds[2] = bo->prime_fds[1] = bo->prime_fds[0];
148 } else {
149 int expected_planes = (ycbcr.chroma_step == 2) ? 2 : 3;
150 if (num_fds != expected_planes)
151 return false;
152 }
153
154 return true;
155}
156
Roman Stratiienkob2e9fe22020-10-03 10:52:36 +0300157int BufferInfoLibdrm::ConvertBoInfo(buffer_handle_t handle, hwc_drm_bo_t *bo) {
Roman Stratiienko946126c2020-10-02 19:01:10 +0300158 gralloc_handle_t *gr_handle = gralloc_handle(handle);
159 if (!gr_handle)
160 return -EINVAL;
161
162 bo->width = gr_handle->width;
163 bo->height = gr_handle->height;
164 bo->hal_format = gr_handle->format;
165
166#if GRALLOC_HANDLE_VERSION < 4
167 static std::once_flag once;
168 std::call_once(once, []() {
169 ALOGE(
170 "libdrm < v2.4.97 has broken gralloc_handle structure. Please update.");
171 });
172#endif
173#if GRALLOC_HANDLE_VERSION == 4
174 bo->modifiers[0] = gr_handle->modifier;
Roman Stratiienko946126c2020-10-02 19:01:10 +0300175#endif
176
177 bo->usage = gr_handle->usage;
178 bo->prime_fds[0] = gr_handle->prime_fd;
179
180 if (is_yuv(gr_handle->format)) {
181 if (!GetYuvPlaneInfo(handle->numFds, handle, bo))
182 return -EINVAL;
183 } else {
184 bo->pitches[0] = gr_handle->stride;
185 bo->offsets[0] = 0;
Roman Stratiienko32819fe2020-10-30 13:53:00 +0200186
187 /* FOSS graphic components (gbm_gralloc, mesa3d) are translating
188 * HAL_PIXEL_FORMAT_RGB_565 to DRM_FORMAT_RGB565 without swapping
189 * the R and B components. Same must be done here. */
190 switch (bo->hal_format) {
191 case HAL_PIXEL_FORMAT_RGB_565:
192 bo->format = DRM_FORMAT_RGB565;
193 break;
194 default:
195 bo->format = ConvertHalFormatToDrm(gr_handle->format);
196 }
197
Roman Stratiienko946126c2020-10-02 19:01:10 +0300198 if (bo->format == DRM_FORMAT_INVALID)
199 return -EINVAL;
200 }
201
Roman Stratiienko946126c2020-10-02 19:01:10 +0300202 return 0;
203}
204
205} // namespace android