egl/android: Switch to generic buffer-info code

Switch to a new common buffer-info layer. After this change, the virgl
fallback logic is changed, but it should work as well.

Signed-off-by: Roman Stratiienko <r.stratiienko@gmail.com>
Tested-by: Mauro Rossi <issor.oruam@gmail.com>
Reviewed-by: Yiwei Zhang <zzyiwei@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24374>
This commit is contained in:
Roman Stratiienko
2023-07-27 21:42:44 +03:00
committed by Marge Bot
parent ff82868a60
commit efe12ae7ee
6 changed files with 59 additions and 670 deletions

View File

@@ -1243,6 +1243,10 @@ dri2_display_destroy(_EGLDisplay *disp)
free(dri2_dpy->device_name);
#endif
#ifdef HAVE_ANDROID_PLATFORM
u_gralloc_destroy(&dri2_dpy->gralloc);
#endif
switch (disp->Platform) {
case _EGL_PLATFORM_X11:
dri2_teardown_x11(dri2_dpy);

View File

@@ -72,6 +72,8 @@ struct zwp_linux_dmabuf_feedback_v1;
#include <hardware/gralloc.h>
#include "util/u_gralloc/u_gralloc.h"
#if ANDROID_API_LEVEL >= 26
#include <vndk/window.h>
#else
@@ -311,7 +313,7 @@ struct dri2_egl_display {
#endif
#ifdef HAVE_ANDROID_PLATFORM
const gralloc_module_t *gralloc;
struct u_gralloc *gralloc;
/* gralloc vendor usage bit for front rendering */
uint32_t front_rendering_usage;
#endif

View File

@@ -48,390 +48,29 @@
#include "loader.h"
#include "platform_android.h"
#define ALIGN(val, align) (((val) + (align)-1) & ~((align)-1))
enum chroma_order {
YCbCr,
YCrCb,
};
struct droid_yuv_format {
/* Lookup keys */
int native; /* HAL_PIXEL_FORMAT_ */
enum chroma_order chroma_order; /* chroma order is {Cb, Cr} or {Cr, Cb} */
int chroma_step; /* Distance in bytes between subsequent chroma pixels. */
/* Result */
int fourcc; /* DRM_FORMAT_ */
};
/* The following table is used to look up a DRI image FourCC based
* on native format and information contained in android_ycbcr struct. */
static const struct droid_yuv_format droid_yuv_formats[] = {
/* Native format, YCrCb, Chroma step, DRI image FourCC */
{HAL_PIXEL_FORMAT_YCbCr_420_888, YCbCr, 2, DRM_FORMAT_NV12},
{HAL_PIXEL_FORMAT_YCbCr_420_888, YCbCr, 1, DRM_FORMAT_YUV420},
{HAL_PIXEL_FORMAT_YCbCr_420_888, YCrCb, 1, DRM_FORMAT_YVU420},
{HAL_PIXEL_FORMAT_YV12, YCrCb, 1, DRM_FORMAT_YVU420},
/* HACK: See droid_create_image_from_prime_fds() and
* https://issuetracker.google.com/32077885. */
{HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCbCr, 2, DRM_FORMAT_NV12},
{HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCbCr, 1, DRM_FORMAT_YUV420},
{HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, DRM_FORMAT_YVU420},
{HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, DRM_FORMAT_AYUV},
{HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED, YCrCb, 1, DRM_FORMAT_XYUV8888},
};
static int
get_fourcc_yuv(int native, enum chroma_order chroma_order, int chroma_step)
{
for (int i = 0; i < ARRAY_SIZE(droid_yuv_formats); ++i)
if (droid_yuv_formats[i].native == native &&
droid_yuv_formats[i].chroma_order == chroma_order &&
droid_yuv_formats[i].chroma_step == chroma_step)
return droid_yuv_formats[i].fourcc;
return -1;
}
static bool
is_yuv(int native)
{
for (int i = 0; i < ARRAY_SIZE(droid_yuv_formats); ++i)
if (droid_yuv_formats[i].native == native)
return true;
return false;
}
static int
get_format_bpp(int native)
{
int bpp;
switch (native) {
case HAL_PIXEL_FORMAT_RGBA_FP16:
bpp = 8;
break;
case HAL_PIXEL_FORMAT_RGBA_8888:
case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
/*
* HACK: Hardcode this to RGBX_8888 as per cros_gralloc hack.
* TODO: Remove this once https://issuetracker.google.com/32077885 is
* fixed.
*/
case HAL_PIXEL_FORMAT_RGBX_8888:
case HAL_PIXEL_FORMAT_BGRA_8888:
case HAL_PIXEL_FORMAT_RGBA_1010102:
bpp = 4;
break;
case HAL_PIXEL_FORMAT_RGB_565:
bpp = 2;
break;
default:
bpp = 0;
break;
}
return bpp;
}
/* createImageFromFds requires fourcc format */
static int
get_fourcc(int native)
{
switch (native) {
case HAL_PIXEL_FORMAT_RGB_565:
return DRM_FORMAT_RGB565;
case HAL_PIXEL_FORMAT_BGRA_8888:
return DRM_FORMAT_ARGB8888;
case HAL_PIXEL_FORMAT_RGBA_8888:
return DRM_FORMAT_ABGR8888;
case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED:
/*
* HACK: Hardcode this to RGBX_8888 as per cros_gralloc hack.
* TODO: Remove this once https://issuetracker.google.com/32077885 is
* fixed.
*/
case HAL_PIXEL_FORMAT_RGBX_8888:
return DRM_FORMAT_XBGR8888;
case HAL_PIXEL_FORMAT_RGBA_FP16:
return DRM_FORMAT_ABGR16161616F;
case HAL_PIXEL_FORMAT_RGBA_1010102:
return DRM_FORMAT_ABGR2101010;
default:
_eglLog(_EGL_WARNING, "unsupported native buffer format 0x%x", native);
}
return -1;
}
/* returns # of fds, and by reference the actual fds */
static unsigned
get_native_buffer_fds(struct ANativeWindowBuffer *buf, int fds[3])
{
native_handle_t *handle = (native_handle_t *)buf->handle;
if (!handle)
return 0;
/*
* Various gralloc implementations exist, but the dma-buf fd tends
* to be first. Access it directly to avoid a dependency on specific
* gralloc versions.
*/
for (int i = 0; i < handle->numFds; i++)
fds[i] = handle->data[i];
return handle->numFds;
}
static int
get_yuv_buffer_info(struct dri2_egl_display *dri2_dpy,
struct ANativeWindowBuffer *buf,
struct buffer_info *out_buf_info)
{
struct android_ycbcr ycbcr;
enum chroma_order chroma_order;
int drm_fourcc = 0;
int num_fds = 0;
int fds[3];
int ret;
num_fds = get_native_buffer_fds(buf, fds);
if (num_fds == 0)
return -EINVAL;
if (!dri2_dpy->gralloc->lock_ycbcr) {
_eglLog(_EGL_WARNING, "Gralloc does not support lock_ycbcr");
return -EINVAL;
}
memset(&ycbcr, 0, sizeof(ycbcr));
ret = dri2_dpy->gralloc->lock_ycbcr(dri2_dpy->gralloc, buf->handle, 0, 0, 0,
0, 0, &ycbcr);
if (ret) {
/* HACK: See native_window_buffer_get_buffer_info() and
* https://issuetracker.google.com/32077885.*/
if (buf->format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)
return -EAGAIN;
_eglLog(_EGL_WARNING, "gralloc->lock_ycbcr failed: %d", ret);
return -EINVAL;
}
dri2_dpy->gralloc->unlock(dri2_dpy->gralloc, buf->handle);
chroma_order = ((size_t)ycbcr.cr < (size_t)ycbcr.cb) ? YCrCb : YCbCr;
/* .chroma_step is the byte distance between the same chroma channel
* values of subsequent pixels, assumed to be the same for Cb and Cr. */
drm_fourcc = get_fourcc_yuv(buf->format, chroma_order, ycbcr.chroma_step);
if (drm_fourcc == -1) {
_eglLog(_EGL_WARNING,
"unsupported YUV format, native = %x, chroma_order = %s, "
"chroma_step = %d",
buf->format, chroma_order == YCbCr ? "YCbCr" : "YCrCb",
ycbcr.chroma_step);
return -EINVAL;
}
*out_buf_info = (struct buffer_info){
.width = buf->width,
.height = buf->height,
.drm_fourcc = drm_fourcc,
.num_planes = ycbcr.chroma_step == 2 ? 2 : 3,
.fds = {-1, -1, -1, -1},
.modifier = DRM_FORMAT_MOD_INVALID,
.yuv_color_space = EGL_ITU_REC601_EXT,
.sample_range = EGL_YUV_NARROW_RANGE_EXT,
.horizontal_siting = EGL_YUV_CHROMA_SITING_0_EXT,
.vertical_siting = EGL_YUV_CHROMA_SITING_0_EXT,
};
/* When lock_ycbcr's usage argument contains no SW_READ/WRITE flags
* it will return the .y/.cb/.cr pointers based on a NULL pointer,
* so they can be interpreted as offsets. */
out_buf_info->offsets[0] = (size_t)ycbcr.y;
/* We assume here that all the planes are located in one DMA-buf. */
if (chroma_order == YCrCb) {
out_buf_info->offsets[1] = (size_t)ycbcr.cr;
out_buf_info->offsets[2] = (size_t)ycbcr.cb;
} else {
out_buf_info->offsets[1] = (size_t)ycbcr.cb;
out_buf_info->offsets[2] = (size_t)ycbcr.cr;
}
/* .ystride is the line length (in bytes) of the Y plane,
* .cstride is the line length (in bytes) of any of the remaining
* Cb/Cr/CbCr planes, assumed to be the same for Cb and Cr for fully
* planar formats. */
out_buf_info->pitches[0] = ycbcr.ystride;
out_buf_info->pitches[1] = out_buf_info->pitches[2] = ycbcr.cstride;
/*
* Since this is EGL_NATIVE_BUFFER_ANDROID don't assume that
* the single-fd case cannot happen. So handle eithe single
* fd or fd-per-plane case:
*/
if (num_fds == 1) {
out_buf_info->fds[1] = out_buf_info->fds[0] = fds[0];
if (out_buf_info->num_planes == 3)
out_buf_info->fds[2] = fds[0];
} else {
assert(num_fds == out_buf_info->num_planes);
out_buf_info->fds[0] = fds[0];
out_buf_info->fds[1] = fds[1];
out_buf_info->fds[2] = fds[2];
}
return 0;
}
static int
native_window_buffer_get_buffer_info(struct dri2_egl_display *dri2_dpy,
struct ANativeWindowBuffer *buf,
struct buffer_info *out_buf_info)
{
int num_planes = 0;
int drm_fourcc = 0;
int pitch = 0;
int fds[3];
if (is_yuv(buf->format)) {
int ret = get_yuv_buffer_info(dri2_dpy, buf, out_buf_info);
/*
* HACK: https://issuetracker.google.com/32077885
* There is no API available to properly query the IMPLEMENTATION_DEFINED
* format. As a workaround we rely here on gralloc allocating either
* an arbitrary YCbCr 4:2:0 or RGBX_8888, with the latter being recognized
* by lock_ycbcr failing.
*/
if (ret != -EAGAIN)
return ret;
}
/*
* Non-YUV formats could *also* have multiple planes, such as ancillary
* color compression state buffer, but the rest of the code isn't ready
* yet to deal with modifiers:
*/
num_planes = get_native_buffer_fds(buf, fds);
if (num_planes == 0)
return -EINVAL;
assert(num_planes == 1);
drm_fourcc = get_fourcc(buf->format);
if (drm_fourcc == -1) {
_eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
return -EINVAL;
}
pitch = buf->stride * get_format_bpp(buf->format);
if (pitch == 0) {
_eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR");
return -EINVAL;
}
*out_buf_info = (struct buffer_info){
.width = buf->width,
.height = buf->height,
.drm_fourcc = drm_fourcc,
.num_planes = num_planes,
.fds = {fds[0], -1, -1, -1},
.modifier = DRM_FORMAT_MOD_INVALID,
.offsets = {0, 0, 0, 0},
.pitches = {pitch, 0, 0, 0},
.yuv_color_space = EGL_ITU_REC601_EXT,
.sample_range = EGL_YUV_NARROW_RANGE_EXT,
.horizontal_siting = EGL_YUV_CHROMA_SITING_0_EXT,
.vertical_siting = EGL_YUV_CHROMA_SITING_0_EXT,
};
return 0;
}
/* More recent CrOS gralloc has a perform op that fills out the struct below
* with canonical information about the buffer and its modifier, planes,
* offsets and strides. If we have this, we can skip straight to
* createImageFromDmaBufs2() and avoid all the guessing and recalculations.
* This also gives us the modifier and plane offsets/strides for multiplanar
* compressed buffers (eg Intel CCS buffers) in order to make that work in
* Android.
*/
static const char cros_gralloc_module_name[] = "CrOS Gralloc";
#define CROS_GRALLOC_DRM_GET_BUFFER_INFO 4
#define CROS_GRALLOC_DRM_GET_USAGE 5
#define CROS_GRALLOC_DRM_GET_USAGE_FRONT_RENDERING_BIT 0x1
struct cros_gralloc0_buffer_info {
uint32_t drm_fourcc;
int num_fds;
int fds[4];
uint64_t modifier;
int offset[4];
int stride[4];
};
static int
cros_get_buffer_info(struct dri2_egl_display *dri2_dpy,
struct ANativeWindowBuffer *buf,
struct buffer_info *out_buf_info)
{
struct cros_gralloc0_buffer_info info;
if (strcmp(dri2_dpy->gralloc->common.name, cros_gralloc_module_name) == 0 &&
dri2_dpy->gralloc->perform &&
dri2_dpy->gralloc->perform(dri2_dpy->gralloc,
CROS_GRALLOC_DRM_GET_BUFFER_INFO, buf->handle,
&info) == 0) {
*out_buf_info = (struct buffer_info){
.width = buf->width,
.height = buf->height,
.drm_fourcc = info.drm_fourcc,
.num_planes = info.num_fds,
.fds = {-1, -1, -1, -1},
.modifier = info.modifier,
.yuv_color_space = EGL_ITU_REC601_EXT,
.sample_range = EGL_YUV_NARROW_RANGE_EXT,
.horizontal_siting = EGL_YUV_CHROMA_SITING_0_EXT,
.vertical_siting = EGL_YUV_CHROMA_SITING_0_EXT,
};
for (int i = 0; i < out_buf_info->num_planes; i++) {
out_buf_info->fds[i] = info.fds[i];
out_buf_info->offsets[i] = info.offset[i];
out_buf_info->pitches[i] = info.stride[i];
}
return 0;
}
return -EINVAL;
}
static __DRIimage *
droid_create_image_from_buffer_info(struct dri2_egl_display *dri2_dpy,
struct buffer_info *buf_info, void *priv)
droid_create_image_from_buffer_info(
struct dri2_egl_display *dri2_dpy, int width, int height,
struct u_gralloc_buffer_basic_info *buf_info,
struct u_gralloc_buffer_color_info *color_info, void *priv)
{
unsigned error;
if (dri2_dpy->image->base.version >= 15 &&
dri2_dpy->image->createImageFromDmaBufs2 != NULL) {
return dri2_dpy->image->createImageFromDmaBufs2(
dri2_dpy->dri_screen_render_gpu, buf_info->width, buf_info->height,
buf_info->drm_fourcc, buf_info->modifier, buf_info->fds,
buf_info->num_planes, buf_info->pitches, buf_info->offsets,
buf_info->yuv_color_space, buf_info->sample_range,
buf_info->horizontal_siting, buf_info->vertical_siting, &error, priv);
dri2_dpy->dri_screen_render_gpu, width, height, buf_info->drm_fourcc,
buf_info->modifier, buf_info->fds, buf_info->num_planes,
buf_info->strides, buf_info->offsets, color_info->yuv_color_space,
color_info->sample_range, color_info->horizontal_siting,
color_info->vertical_siting, &error, priv);
}
return dri2_dpy->image->createImageFromDmaBufs(
dri2_dpy->dri_screen_render_gpu, buf_info->width, buf_info->height,
buf_info->drm_fourcc, buf_info->fds, buf_info->num_planes,
buf_info->pitches, buf_info->offsets, buf_info->yuv_color_space,
buf_info->sample_range, buf_info->horizontal_siting,
buf_info->vertical_siting, &error, priv);
dri2_dpy->dri_screen_render_gpu, width, height, buf_info->drm_fourcc,
buf_info->fds, buf_info->num_planes, buf_info->strides, buf_info->offsets,
color_info->yuv_color_space, color_info->sample_range,
color_info->horizontal_siting, color_info->vertical_siting, &error, priv);
}
static __DRIimage *
@@ -440,23 +79,41 @@ droid_create_image_from_native_buffer(_EGLDisplay *disp,
void *priv)
{
struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
struct buffer_info buf_info;
struct u_gralloc_buffer_basic_info buf_info;
struct u_gralloc_buffer_color_info color_info = {
.yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC601,
.sample_range = __DRI_YUV_NARROW_RANGE,
.horizontal_siting = __DRI_YUV_CHROMA_SITING_0,
.vertical_siting = __DRI_YUV_CHROMA_SITING_0,
};
struct u_gralloc_buffer_handle gr_handle = {
.handle = buf->handle,
.hal_format = buf->format,
.pixel_stride = buf->stride,
};
__DRIimage *img = NULL;
/* If dri driver is gallium virgl, real modifier info queried back from
* CrOS info (and potentially mapper metadata if integrated later) cannot
* get resolved and the buffer import will fail. Thus the fallback behavior
* is preserved down to native_window_buffer_get_buffer_info() so that the
* buffer can be imported without modifier info as a last resort.
*/
if (!img && !mapper_metadata_get_buffer_info(buf, &buf_info))
img = droid_create_image_from_buffer_info(dri2_dpy, &buf_info, priv);
if (u_gralloc_get_buffer_basic_info(dri2_dpy->gralloc, &gr_handle,
&buf_info))
return 0;
if (!img && !cros_get_buffer_info(dri2_dpy, buf, &buf_info))
img = droid_create_image_from_buffer_info(dri2_dpy, &buf_info, priv);
/* May fail in some cases, defaults will be used in that case */
u_gralloc_get_buffer_color_info(dri2_dpy->gralloc, &gr_handle, &color_info);
if (!img && !native_window_buffer_get_buffer_info(dri2_dpy, buf, &buf_info))
img = droid_create_image_from_buffer_info(dri2_dpy, &buf_info, priv);
img = droid_create_image_from_buffer_info(dri2_dpy, buf->width, buf->height,
&buf_info, &color_info, priv);
if (!img) {
/* If dri driver is gallium virgl, real modifier info queried back from
* CrOS info (and potentially mapper metadata if integrated later) cannot
* get resolved and the buffer import will fail. Thus the fallback
* behavior is preserved so that the buffer can be imported without
* modifier info as a last resort.
*/
buf_info.modifier = DRM_FORMAT_MOD_INVALID;
img = droid_create_image_from_buffer_info(
dri2_dpy, buf->width, buf->height, &buf_info, &color_info, priv);
}
return img;
}
@@ -1479,7 +1136,6 @@ dri2_initialize_android(_EGLDisplay *disp)
bool device_opened = false;
struct dri2_egl_display *dri2_dpy;
const char *err;
int ret;
dri2_dpy = calloc(1, sizeof(*dri2_dpy));
if (!dri2_dpy)
@@ -1487,10 +1143,10 @@ dri2_initialize_android(_EGLDisplay *disp)
dri2_dpy->fd_render_gpu = -1;
dri2_dpy->fd_display_gpu = -1;
ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
(const hw_module_t **)&dri2_dpy->gralloc);
if (ret) {
err = "DRI2: failed to get gralloc module";
dri2_dpy->gralloc = u_gralloc_create(U_GRALLOC_TYPE_AUTO);
if (dri2_dpy->gralloc == NULL) {
err = "DRI2: failed to get gralloc";
goto cleanup;
}
@@ -1571,13 +1227,9 @@ dri2_initialize_android(_EGLDisplay *disp)
*
* So at least we can force BO_USE_LINEAR as the fallback.
*/
uint32_t front_rendering_usage = 0;
if (!strcmp(dri2_dpy->gralloc->common.name, cros_gralloc_module_name) &&
dri2_dpy->gralloc->perform &&
dri2_dpy->gralloc->perform(
dri2_dpy->gralloc, CROS_GRALLOC_DRM_GET_USAGE,
CROS_GRALLOC_DRM_GET_USAGE_FRONT_RENDERING_BIT,
&front_rendering_usage) == 0) {
uint64_t front_rendering_usage = 0;
if (!u_gralloc_get_front_rendering_usage(dri2_dpy->gralloc,
&front_rendering_usage)) {
dri2_dpy->front_rendering_usage = front_rendering_usage;
disp->Extensions.KHR_mutable_render_buffer = EGL_TRUE;
}

View File

@@ -117,38 +117,4 @@ ANativeWindow_query(const struct ANativeWindow *window,
}
#endif // ANDROID_API_LEVEL < 26
struct buffer_info {
int width;
int height;
uint32_t drm_fourcc;
int num_planes;
int fds[4];
uint64_t modifier;
int offsets[4];
int pitches[4];
enum __DRIYUVColorSpace yuv_color_space;
enum __DRISampleRange sample_range;
enum __DRIChromaSiting horizontal_siting;
enum __DRIChromaSiting vertical_siting;
};
#ifdef USE_IMAPPER4_METADATA_API
#ifdef __cplusplus
extern "C" {
#endif
extern int
mapper_metadata_get_buffer_info(struct ANativeWindowBuffer *buf,
struct buffer_info *out_buf_info);
#ifdef __cplusplus
}
#endif
#else
static inline int
mapper_metadata_get_buffer_info(struct ANativeWindowBuffer *buf,
struct buffer_info *out_buf_info)
{
return -ENOTSUP;
}
#endif /* USE_IMAPPER4_METADATA_API */
#endif /* EGL_ANDROID_INCLUDED */

View File

@@ -1,230 +0,0 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2021 GlobalLogic Ukraine
* Copyright (C) 2021 Roman Stratiienko (r.stratiienko@gmail.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include "platform_android.h"
#include <aidl/android/hardware/graphics/common/ChromaSiting.h>
#include <aidl/android/hardware/graphics/common/Dataspace.h>
#include <aidl/android/hardware/graphics/common/ExtendableType.h>
#include <aidl/android/hardware/graphics/common/PlaneLayoutComponent.h>
#include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h>
#include <gralloctypes/Gralloc4.h>
#include <system/window.h>
using aidl::android::hardware::graphics::common::ChromaSiting;
using aidl::android::hardware::graphics::common::Dataspace;
using aidl::android::hardware::graphics::common::ExtendableType;
using aidl::android::hardware::graphics::common::PlaneLayout;
using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
using android::hardware::hidl_handle;
using android::hardware::hidl_vec;
using android::hardware::graphics::common::V1_2::BufferUsage;
using android::hardware::graphics::mapper::V4_0::Error;
using android::hardware::graphics::mapper::V4_0::IMapper;
using MetadataType =
android::hardware::graphics::mapper::V4_0::IMapper::MetadataType;
Error
GetMetadata(android::sp<IMapper> mapper, const native_handle_t *buffer,
MetadataType type, hidl_vec<uint8_t> *metadata)
{
Error error = Error::NONE;
auto native_handle = const_cast<native_handle_t *>(buffer);
auto ret = mapper->get(native_handle, type,
[&](const auto &get_error, const auto &get_metadata) {
error = get_error;
*metadata = get_metadata;
});
if (!ret.isOk())
error = Error::NO_RESOURCES;
return error;
}
std::optional<std::vector<PlaneLayout>>
GetPlaneLayouts(android::sp<IMapper> mapper, const native_handle_t *buffer)
{
hidl_vec<uint8_t> encoded_layouts;
Error error =
GetMetadata(mapper, buffer, android::gralloc4::MetadataType_PlaneLayouts,
&encoded_layouts);
if (error != Error::NONE)
return std::nullopt;
std::vector<PlaneLayout> plane_layouts;
auto status =
android::gralloc4::decodePlaneLayouts(encoded_layouts, &plane_layouts);
if (status != android::OK)
return std::nullopt;
return plane_layouts;
}
extern "C" {
int
mapper_metadata_get_buffer_info(struct ANativeWindowBuffer *buf,
struct buffer_info *out_buf_info)
{
static android::sp<IMapper> mapper = IMapper::getService();
struct buffer_info buf_info = *out_buf_info;
if (mapper == nullptr)
return -EINVAL;
if (!buf->handle)
return -EINVAL;
buf_info.width = buf->width;
buf_info.height = buf->height;
hidl_vec<uint8_t> encoded_format;
auto err = GetMetadata(mapper, buf->handle,
android::gralloc4::MetadataType_PixelFormatFourCC,
&encoded_format);
if (err != Error::NONE)
return -EINVAL;
auto status = android::gralloc4::decodePixelFormatFourCC(
encoded_format, &buf_info.drm_fourcc);
if (status != android::OK)
return -EINVAL;
hidl_vec<uint8_t> encoded_modifier;
err = GetMetadata(mapper, buf->handle,
android::gralloc4::MetadataType_PixelFormatModifier,
&encoded_modifier);
if (err != Error::NONE)
return -EINVAL;
status = android::gralloc4::decodePixelFormatModifier(encoded_modifier,
&buf_info.modifier);
if (status != android::OK)
return -EINVAL;
auto layouts_opt = GetPlaneLayouts(mapper, buf->handle);
if (!layouts_opt)
return -EINVAL;
std::vector<PlaneLayout> &layouts = *layouts_opt;
buf_info.num_planes = layouts.size();
bool per_plane_unique_fd = buf->handle->numFds == buf_info.num_planes;
for (uint32_t i = 0; i < layouts.size(); i++) {
buf_info.fds[i] =
per_plane_unique_fd ? buf->handle->data[i] : buf->handle->data[0];
buf_info.pitches[i] = layouts[i].strideInBytes;
buf_info.offsets[i] = layouts[i].offsetInBytes;
}
/* optional attributes */
hidl_vec<uint8_t> encoded_chroma_siting;
err = GetMetadata(mapper, buf->handle,
android::gralloc4::MetadataType_ChromaSiting,
&encoded_chroma_siting);
if (err == Error::NONE) {
ExtendableType chroma_siting_ext;
status = android::gralloc4::decodeChromaSiting(encoded_chroma_siting,
&chroma_siting_ext);
if (status != android::OK)
return -EINVAL;
ChromaSiting chroma_siting =
android::gralloc4::getStandardChromaSitingValue(chroma_siting_ext);
switch (chroma_siting) {
case ChromaSiting::SITED_INTERSTITIAL:
buf_info.horizontal_siting = __DRI_YUV_CHROMA_SITING_0_5;
buf_info.vertical_siting = __DRI_YUV_CHROMA_SITING_0_5;
break;
case ChromaSiting::COSITED_HORIZONTAL:
buf_info.horizontal_siting = __DRI_YUV_CHROMA_SITING_0;
buf_info.vertical_siting = __DRI_YUV_CHROMA_SITING_0_5;
break;
default:
break;
}
}
hidl_vec<uint8_t> encoded_dataspace;
err = GetMetadata(mapper, buf->handle,
android::gralloc4::MetadataType_Dataspace,
&encoded_dataspace);
if (err == Error::NONE) {
Dataspace dataspace;
status =
android::gralloc4::decodeDataspace(encoded_dataspace, &dataspace);
if (status != android::OK)
return -EINVAL;
Dataspace standard =
(Dataspace)((int)dataspace & (uint32_t)Dataspace::STANDARD_MASK);
switch (standard) {
case Dataspace::STANDARD_BT709:
buf_info.yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC709;
break;
case Dataspace::STANDARD_BT601_625:
case Dataspace::STANDARD_BT601_625_UNADJUSTED:
case Dataspace::STANDARD_BT601_525:
case Dataspace::STANDARD_BT601_525_UNADJUSTED:
buf_info.yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC601;
break;
case Dataspace::STANDARD_BT2020:
case Dataspace::STANDARD_BT2020_CONSTANT_LUMINANCE:
buf_info.yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC2020;
break;
default:
break;
}
Dataspace range =
(Dataspace)((int)dataspace & (uint32_t)Dataspace::RANGE_MASK);
switch (range) {
case Dataspace::RANGE_FULL:
buf_info.sample_range = __DRI_YUV_FULL_RANGE;
break;
case Dataspace::RANGE_LIMITED:
buf_info.sample_range = __DRI_YUV_NARROW_RANGE;
break;
default:
break;
}
}
*out_buf_info = buf_info;
return 0;
}
} // extern "C"

View File

@@ -133,13 +133,8 @@ if with_dri2
incs_for_egl += include_directories('wayland/wayland-drm')
endif
if with_platform_android
deps_for_egl += dep_android
deps_for_egl += [dep_android, idep_u_gralloc]
files_egl += files('drivers/dri2/platform_android.c')
if dep_android_mapper4.found()
files_egl += files('drivers/dri2/platform_android_mapper.cpp')
c_args_for_egl += '-DUSE_IMAPPER4_METADATA_API'
cpp_args_for_egl += '-DUSE_IMAPPER4_METADATA_API'
endif
endif
elif with_platform_haiku
c_args_for_egl += [