This commit is contained in:
elwrcl committed 2026-06-06 13:25:15 +03:00
1 parent 04d4dc8b09
commit 818cab85dc
12511 files changed
+6156641

No files matched your search

+49
View File
@@ -0,0 +1,49 @@
# Mesa 3-D graphics library
#
# Copyright (C) 2022 Roman Stratiienko ([email protected])
# SPDX-License-Identifier: MIT
c_args_for_u_gralloc = []
cpp_args_for_u_gralloc = []
options_for_u_gralloc = []
deps_for_u_gralloc = [dep_android]
files_u_gralloc = files(
'u_gralloc.c',
'u_gralloc_internal.c',
'u_gralloc_fallback.c',
'u_gralloc_cros_api.c',
'u_gralloc_libdrm.c',
'u_gralloc_qcom.c',
)
if dep_android_ui.found()
files_u_gralloc += files('u_gralloc_imapper5_api.cpp')
c_args_for_u_gralloc += '-DUSE_IMAPPER4_METADATA_API'
cpp_args_for_u_gralloc += '-DUSE_IMAPPER4_METADATA_API'
options_for_u_gralloc += 'cpp_std=c++17'
elif dep_android_mapper4.found()
files_u_gralloc += files('u_gralloc_imapper4_api.cpp')
c_args_for_u_gralloc += '-DUSE_IMAPPER4_METADATA_API'
cpp_args_for_u_gralloc += '-DUSE_IMAPPER4_METADATA_API'
options_for_u_gralloc += 'cpp_std=c++17'
deps_for_u_gralloc += dep_android_mapper4
endif
if with_freedreno_vk or with_gallium_freedreno
c_args_for_u_gralloc += '-DHAS_FREEDRENO'
endif
_libmesa_u_gralloc = static_library(
'_mesa_u_gralloc',
[files_u_gralloc],
include_directories : [inc_include, inc_util],
c_args : c_args_for_u_gralloc,
cpp_args : cpp_args_for_u_gralloc,
override_options : options_for_u_gralloc,
gnu_symbol_visibility : 'hidden',
build_by_default : false,
dependencies: deps_for_u_gralloc,
)
idep_u_gralloc = declare_dependency(link_with: _libmesa_u_gralloc)
+156
View File
@@ -0,0 +1,156 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2022 Roman Stratiienko ([email protected])
* SPDX-License-Identifier: MIT
*/
#include "u_gralloc_internal.h"
#include <assert.h>
#include <errno.h>
#include "drm-uapi/drm_fourcc.h"
#include "util/log.h"
#include "util/macros.h"
#include "util/simple_mtx.h"
#include "util/u_atomic.h"
#include "util/u_memory.h"
static simple_mtx_t u_gralloc_mutex = SIMPLE_MTX_INITIALIZER;
static const struct u_grallocs {
enum u_gralloc_type type;
struct u_gralloc *(*create)();
} u_grallocs[] = {
/* Prefer the CrOS API as it is significantly faster than IMapper4 */
{.type = U_GRALLOC_TYPE_CROS, .create = u_gralloc_cros_api_create},
#ifdef USE_IMAPPER4_METADATA_API
{.type = U_GRALLOC_TYPE_GRALLOC4, .create = u_gralloc_imapper_api_create},
#endif /* USE_IMAPPER4_METADATA_API */
{.type = U_GRALLOC_TYPE_LIBDRM, .create = u_gralloc_libdrm_create},
{.type = U_GRALLOC_TYPE_QCOM, .create = u_gralloc_qcom_create},
{.type = U_GRALLOC_TYPE_FALLBACK, .create = u_gralloc_fallback_create},
};
static struct u_gralloc_cache {
struct u_gralloc *u_gralloc;
int refcount;
} u_gralloc_cache[U_GRALLOC_TYPE_COUNT] = {0};
struct u_gralloc *
u_gralloc_create(enum u_gralloc_type type)
{
struct u_gralloc *out_gralloc = NULL;
simple_mtx_lock(&u_gralloc_mutex);
if (u_gralloc_cache[type].u_gralloc != NULL) {
u_gralloc_cache[type].refcount++;
out_gralloc = u_gralloc_cache[type].u_gralloc;
goto out;
}
for (int i = 0; i < ARRAY_SIZE(u_grallocs); i++) {
if (u_grallocs[i].type != type && type != U_GRALLOC_TYPE_AUTO)
continue;
u_gralloc_cache[type].u_gralloc = u_grallocs[i].create();
if (u_gralloc_cache[type].u_gralloc) {
assert(u_gralloc_cache[type].u_gralloc->ops.get_buffer_basic_info);
assert(u_gralloc_cache[type].u_gralloc->ops.destroy);
u_gralloc_cache[type].u_gralloc->type = u_grallocs[i].type;
u_gralloc_cache[type].refcount = 1;
out_gralloc = u_gralloc_cache[type].u_gralloc;
goto out;
}
}
out:
simple_mtx_unlock(&u_gralloc_mutex);
return out_gralloc;
}
void
u_gralloc_destroy(struct u_gralloc **gralloc)
{
int i;
if (*gralloc == NULL)
return;
simple_mtx_lock(&u_gralloc_mutex);
for (i = 0; i < ARRAY_SIZE(u_gralloc_cache); i++) {
if (u_gralloc_cache[i].u_gralloc == *gralloc) {
u_gralloc_cache[i].refcount--;
if (u_gralloc_cache[i].refcount == 0) {
u_gralloc_cache[i].u_gralloc->ops.destroy(
u_gralloc_cache[i].u_gralloc);
u_gralloc_cache[i].u_gralloc = NULL;
}
break;
}
}
simple_mtx_unlock(&u_gralloc_mutex);
assert(i < ARRAY_SIZE(u_grallocs));
*gralloc = NULL;
}
int
u_gralloc_get_buffer_basic_info(struct u_gralloc *gralloc,
struct u_gralloc_buffer_handle *hnd,
struct u_gralloc_buffer_basic_info *out)
{
struct u_gralloc_buffer_basic_info info = {0};
int ret;
ret = gralloc->ops.get_buffer_basic_info(gralloc, hnd, &info);
if (ret)
return ret;
*out = info;
return 0;
}
int
u_gralloc_get_buffer_color_info(struct u_gralloc *gralloc,
struct u_gralloc_buffer_handle *hnd,
struct u_gralloc_buffer_color_info *out)
{
if (gralloc->ops.get_buffer_color_info)
return gralloc->ops.get_buffer_color_info(gralloc, hnd, out);
*out = (struct u_gralloc_buffer_color_info){
.yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC601,
.sample_range = __DRI_YUV_NARROW_RANGE,
.horizontal_siting = __DRI_YUV_CHROMA_SITING_0_5,
.vertical_siting = __DRI_YUV_CHROMA_SITING_0_5,
};
return 0;
}
int
u_gralloc_get_front_rendering_usage(struct u_gralloc *gralloc,
uint64_t *out_usage)
{
if (!gralloc->ops.get_front_rendering_usage)
return -ENOTSUP;
return gralloc->ops.get_front_rendering_usage(gralloc, out_usage);
}
int
u_gralloc_get_type(struct u_gralloc *gralloc)
{
return gralloc->type;
}
+83
View File
@@ -0,0 +1,83 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2022 Roman Stratiienko ([email protected])
* SPDX-License-Identifier: MIT
*/
#ifndef U_GRALLOC_H
#define U_GRALLOC_H
#ifdef __cplusplus
extern "C" {
#endif
#include <cutils/native_handle.h>
#include <stdbool.h>
#include "util/macros.h"
#include "gallium/include/mesa_interface.h"
struct u_gralloc;
/* Both Vulkan and EGL API exposes HAL format / pixel stride which is required
* by the fallback implementation.
*/
struct u_gralloc_buffer_handle {
const native_handle_t *handle;
int hal_format;
int pixel_stride;
};
struct u_gralloc_buffer_basic_info {
uint32_t drm_fourcc;
uint64_t modifier;
int num_planes;
int fds[4];
int offsets[4];
int strides[4];
};
struct u_gralloc_buffer_color_info {
enum __DRIYUVColorSpace yuv_color_space;
enum __DRISampleRange sample_range;
enum __DRIChromaSiting horizontal_siting;
enum __DRIChromaSiting vertical_siting;
};
enum u_gralloc_type {
U_GRALLOC_TYPE_AUTO,
U_GRALLOC_TYPE_GRALLOC4,
U_GRALLOC_TYPE_CROS,
U_GRALLOC_TYPE_LIBDRM,
U_GRALLOC_TYPE_QCOM,
U_GRALLOC_TYPE_FALLBACK,
U_GRALLOC_TYPE_COUNT,
};
struct u_gralloc *u_gralloc_create(enum u_gralloc_type type);
void u_gralloc_destroy(struct u_gralloc **gralloc);
int u_gralloc_get_buffer_basic_info(
struct u_gralloc *gralloc,
struct u_gralloc_buffer_handle *hnd,
struct u_gralloc_buffer_basic_info *out);
int u_gralloc_get_buffer_color_info(
struct u_gralloc *gralloc,
struct u_gralloc_buffer_handle *hnd,
struct u_gralloc_buffer_color_info *out);
int u_gralloc_get_front_rendering_usage(struct u_gralloc *gralloc,
uint64_t *out_usage);
int u_gralloc_get_type(struct u_gralloc *gralloc);
#ifdef __cplusplus
}
#endif
#endif /* U_GRALLOC_H */
+249
View File
@@ -0,0 +1,249 @@
/*
* Mesa 3-D graphics library
*
* Copyright © 2021, Google Inc.
* SPDX-License-Identifier: MIT
*/
#include <assert.h>
#include <dlfcn.h>
#include <errno.h>
#include <string.h>
#include <hardware/gralloc.h>
#include "util/log.h"
#include "util/u_memory.h"
#include "u_gralloc_internal.h"
/* The following defines are selectively copied over from auto-generated
* AIDL sources which are no longer released as headers in VNDK from api
* level 35 on.
* These need to be kept in sync with AIDL sources and additional
* defines to be added as needed.
*/
enum cros_gralloc0_dataspace {
DATASPACE_STANDARD_MASK = 63 << 16,
DATASPACE_STANDARD_BT709 = 1 << 16,
DATASPACE_STANDARD_BT601_625 = 2 << 16,
DATASPACE_STANDARD_BT601_625_UNADJUSTED = 3 << 16,
DATASPACE_STANDARD_BT601_525 = 4 << 16,
DATASPACE_STANDARD_BT601_525_UNADJUSTED = 5 << 16,
DATASPACE_STANDARD_BT2020 = 6 << 16,
DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE = 7 << 16,
DATASPACE_RANGE_MASK= 7 << 27,
DATASPACE_RANGE_FULL = 1 << 27,
DATASPACE_RANGE_LIMITED = 2 << 27,
};
enum cros_gralloc0_chroma_siting {
CHROMA_SITING_SITED_NONE = 0,
CHROMA_SITING_SITED_UNKNOWN = 1,
CHROMA_SITING_SITED_INTERSTITIAL = 2,
CHROMA_SITING_COSITED_HORIZONTAL = 3,
CHROMA_SITING_COSITED_VERTICAL = 4,
CHROMA_SITING_COSITED_BOTH = 5,
};
/* 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.
*/
struct cros_gralloc {
struct u_gralloc base;
gralloc_module_t *gralloc_module;
};
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_BUFFER_COLOR_INFO 6
#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];
};
struct cros_gralloc0_buffer_color_info {
int32_t dataspace;
int32_t chroma_siting;
};
static int
cros_get_buffer_info(struct u_gralloc *gralloc,
struct u_gralloc_buffer_handle *hnd,
struct u_gralloc_buffer_basic_info *out)
{
struct cros_gralloc0_buffer_info info;
struct cros_gralloc *gr = (struct cros_gralloc *)gralloc;
gralloc_module_t *gr_mod = gr->gralloc_module;
if (gr_mod->perform(gr_mod, CROS_GRALLOC_DRM_GET_BUFFER_INFO, hnd->handle,
&info) == 0) {
out->drm_fourcc = info.drm_fourcc;
out->modifier = info.modifier;
out->num_planes = info.num_fds;
for (int i = 0; i < out->num_planes; i++) {
out->fds[i] = info.fds[i];
out->offsets[i] = info.offset[i];
out->strides[i] = info.stride[i];
}
return 0;
}
return -EINVAL;
}
static int
cros_get_front_rendering_usage(struct u_gralloc *gralloc, uint64_t *out_usage)
{
struct cros_gralloc *gr = (struct cros_gralloc *)gralloc;
uint32_t front_rendering_usage = 0;
if (gr->gralloc_module->perform(
gr->gralloc_module, CROS_GRALLOC_DRM_GET_USAGE,
CROS_GRALLOC_DRM_GET_USAGE_FRONT_RENDERING_BIT,
&front_rendering_usage) == 0) {
*out_usage = front_rendering_usage;
return 0;
}
return -ENOTSUP;
}
static int
cros_get_buffer_color_info(struct u_gralloc * gralloc,
struct u_gralloc_buffer_handle *hnd,
struct u_gralloc_buffer_color_info *out)
{
struct cros_gralloc0_buffer_color_info color_info;
struct cros_gralloc *gr = (struct cros_gralloc *)gralloc;
gralloc_module_t *gr_mod = gr->gralloc_module;
if (gr_mod->perform(gr_mod, CROS_GRALLOC_DRM_GET_BUFFER_COLOR_INFO, hnd->handle,
&color_info)) {
/* Return default values if CROS_GRALLOC_DRM_GET_BUFFER_COLOR_INFO
* fails or is not implemented for backwards compat.
*/
*out = (struct u_gralloc_buffer_color_info){
.yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC601,
.sample_range = __DRI_YUV_NARROW_RANGE,
.horizontal_siting = __DRI_YUV_CHROMA_SITING_0_5,
.vertical_siting = __DRI_YUV_CHROMA_SITING_0_5,
};
return 0;
}
/* default to __DRI_YUV_COLOR_SPACE_ITU_REC601 */
int32_t standard = color_info.dataspace & DATASPACE_STANDARD_MASK;
switch (standard) {
case DATASPACE_STANDARD_BT709:
out->yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC709;
break;
case DATASPACE_STANDARD_BT2020:
case DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE:
out->yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC2020;
break;
case DATASPACE_STANDARD_BT601_625:
case DATASPACE_STANDARD_BT601_625_UNADJUSTED:
case DATASPACE_STANDARD_BT601_525:
case DATASPACE_STANDARD_BT601_525_UNADJUSTED:
default:
out->yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC601;
break;
}
/* default to __DRI_YUV_NARROW_RANGE */
int32_t range = color_info.dataspace & DATASPACE_RANGE_MASK;
switch (range) {
case DATASPACE_RANGE_FULL:
out->sample_range = __DRI_YUV_FULL_RANGE;
break;
case DATASPACE_RANGE_LIMITED:
default:
out->sample_range = __DRI_YUV_NARROW_RANGE;
break;
}
/* default to __DRI_YUV_CHROMA_SITING_0_5 */
switch (color_info.chroma_siting) {
case CHROMA_SITING_COSITED_HORIZONTAL:
out->horizontal_siting = __DRI_YUV_CHROMA_SITING_0;
out->vertical_siting = __DRI_YUV_CHROMA_SITING_0_5;
break;
case CHROMA_SITING_COSITED_VERTICAL:
out->horizontal_siting = __DRI_YUV_CHROMA_SITING_0_5;
out->vertical_siting = __DRI_YUV_CHROMA_SITING_0;
break;
case CHROMA_SITING_COSITED_BOTH:
out->horizontal_siting = __DRI_YUV_CHROMA_SITING_0;
out->vertical_siting = __DRI_YUV_CHROMA_SITING_0;
break;
case CHROMA_SITING_SITED_INTERSTITIAL:
default:
out->horizontal_siting = __DRI_YUV_CHROMA_SITING_0_5;
out->vertical_siting = __DRI_YUV_CHROMA_SITING_0_5;
break;
}
return 0;
}
static int
destroy(struct u_gralloc *gralloc)
{
struct cros_gralloc *gr = (struct cros_gralloc *)gralloc;
if (gr->gralloc_module)
dlclose(gr->gralloc_module->common.dso);
FREE(gr);
return 0;
}
struct u_gralloc *
u_gralloc_cros_api_create()
{
struct cros_gralloc *gr = CALLOC_STRUCT(cros_gralloc);
int err = 0;
err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
(const hw_module_t **)&gr->gralloc_module);
if (err)
goto fail;
if (strcmp(gr->gralloc_module->common.name, cros_gralloc_module_name) != 0)
goto fail;
if (!gr->gralloc_module->perform) {
mesa_logw("Oops. CrOS gralloc doesn't have perform callback");
goto fail;
}
gr->base.ops.get_buffer_basic_info = cros_get_buffer_info;
gr->base.ops.get_buffer_color_info = cros_get_buffer_color_info;
gr->base.ops.get_front_rendering_usage = cros_get_front_rendering_usage;
gr->base.ops.destroy = destroy;
mesa_logi("Using gralloc0 CrOS API");
return &gr->base;
fail:
destroy(&gr->base);
return NULL;
}
+198
View File
@@ -0,0 +1,198 @@
/*
* Mesa 3-D graphics library
*
* Copyright © 2021, Google Inc.
* SPDX-License-Identifier: MIT
*/
#include "u_gralloc_internal.h"
#include <hardware/gralloc.h>
#include "drm-uapi/drm_fourcc.h"
#include "util/log.h"
#include "util/macros.h"
#include "util/u_memory.h"
#include <dlfcn.h>
#include <errno.h>
#include <string.h>
struct fallback_gralloc {
struct u_gralloc base;
gralloc_module_t *gralloc_module;
};
/* returns # of fds, and by reference the actual fds */
static unsigned
get_native_buffer_fds(const native_handle_t *handle, int fds[3])
{
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
fallback_gralloc_get_yuv_info(struct u_gralloc *gralloc,
struct u_gralloc_buffer_handle *hnd,
struct u_gralloc_buffer_basic_info *out)
{
struct fallback_gralloc *gr = (struct fallback_gralloc *)gralloc;
gralloc_module_t *gr_mod = gr->gralloc_module;
struct android_ycbcr ycbcr;
int num_fds = 0;
int fds[3];
int ret;
num_fds = get_native_buffer_fds(hnd->handle, fds);
if (num_fds == 0)
return -EINVAL;
if (!gr_mod || !gr_mod->lock_ycbcr) {
return -EINVAL;
}
memset(&ycbcr, 0, sizeof(ycbcr));
ret = gr_mod->lock_ycbcr(gr_mod, hnd->handle, 0, 0, 0, 0, 0, &ycbcr);
if (ret) {
/* HACK: See native_window_buffer_get_buffer_info() and
* https://issuetracker.google.com/32077885.*/
if (hnd->hal_format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)
return -EAGAIN;
mesa_logw("gralloc->lock_ycbcr failed: %d", ret);
return -EINVAL;
}
gr_mod->unlock(gr_mod, hnd->handle);
ret = bufferinfo_from_ycbcr(&ycbcr, hnd, out);
if (ret)
return ret;
/*
* 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->fds[1] = out->fds[0] = fds[0];
if (out->num_planes == 3)
out->fds[2] = fds[0];
} else {
assert(num_fds == out->num_planes);
out->fds[0] = fds[0];
out->fds[1] = fds[1];
out->fds[2] = fds[2];
}
return 0;
}
static int
fallback_gralloc_get_buffer_info(struct u_gralloc *gralloc,
struct u_gralloc_buffer_handle *hnd,
struct u_gralloc_buffer_basic_info *out)
{
int num_planes = 0;
int drm_fourcc = 0;
int stride = 0;
if (hnd->handle->numFds == 0)
return -EINVAL;
if (is_hal_format_yuv(hnd->hal_format)) {
int ret = fallback_gralloc_get_yuv_info(gralloc, hnd, out);
/*
* 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 = 1;
drm_fourcc = get_fourcc_from_hal_format(hnd->hal_format);
if (drm_fourcc == -1) {
mesa_loge("Failed to get drm_fourcc");
return -EINVAL;
}
stride = hnd->pixel_stride * get_hal_format_bpp(hnd->hal_format);
if (stride == 0) {
mesa_loge("Failed to calcuulate stride");
return -EINVAL;
}
out->drm_fourcc = drm_fourcc;
out->modifier = DRM_FORMAT_MOD_INVALID;
out->num_planes = num_planes;
out->fds[0] = hnd->handle->data[0];
out->strides[0] = stride;
#ifdef HAS_FREEDRENO
uint32_t gmsm = ('g' << 24) | ('m' << 16) | ('s' << 8) | 'm';
if (hnd->handle->numInts >= 2 && hnd->handle->data[hnd->handle->numFds] == gmsm) {
/* This UBWC flag was introduced in a5xx. */
bool ubwc = hnd->handle->data[hnd->handle->numFds + 1] & 0x08000000;
out->modifier = ubwc ? DRM_FORMAT_MOD_QCOM_COMPRESSED : DRM_FORMAT_MOD_LINEAR;
}
#endif
return 0;
}
static int
destroy(struct u_gralloc *gralloc)
{
struct fallback_gralloc *gr = (struct fallback_gralloc *)gralloc;
if (gr->gralloc_module) {
dlclose(gr->gralloc_module->common.dso);
}
FREE(gr);
return 0;
}
struct u_gralloc *
u_gralloc_fallback_create()
{
struct fallback_gralloc *gr = CALLOC_STRUCT(fallback_gralloc);
int err = 0;
err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
(const hw_module_t **)&gr->gralloc_module);
if (err) {
mesa_logw(
"No gralloc hwmodule detected (video buffers won't be supported)");
} else if (!gr->gralloc_module->lock_ycbcr) {
mesa_logw("Gralloc doesn't support lock_ycbcr (video buffers won't be "
"supported)");
}
gr->base.ops.get_buffer_basic_info = fallback_gralloc_get_buffer_info;
gr->base.ops.destroy = destroy;
mesa_logi("Using fallback gralloc implementation");
return &gr->base;
}
@@ -0,0 +1,304 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2021 GlobalLogic Ukraine
* Copyright (C) 2021-2022 Roman Stratiienko ([email protected])
* SPDX-License-Identifier: MIT
*/
#include <aidl/android/hardware/graphics/common/BufferUsage.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>
#include "util/log.h"
#include "u_gralloc_internal.h"
using aidl::android::hardware::graphics::common::BufferUsage;
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::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;
}
struct gralloc4 {
struct u_gralloc base;
android::sp<IMapper> mapper;
};
extern "C" {
static int
mapper4_get_buffer_basic_info(struct u_gralloc *gralloc,
struct u_gralloc_buffer_handle *hnd,
struct u_gralloc_buffer_basic_info *out)
{
gralloc4 *gr4 = (gralloc4 *)gralloc;
if (gr4->mapper == nullptr)
return -EINVAL;
if (!hnd->handle)
return -EINVAL;
hidl_vec<uint8_t> encoded_format;
auto err = GetMetadata(gr4->mapper, hnd->handle,
android::gralloc4::MetadataType_PixelFormatFourCC,
&encoded_format);
if (err != Error::NONE)
return -EINVAL;
uint32_t drm_fourcc;
auto status =
android::gralloc4::decodePixelFormatFourCC(encoded_format, &drm_fourcc);
if (status != android::OK)
return -EINVAL;
uint64_t drm_modifier;
hidl_vec<uint8_t> encoded_modifier;
err = GetMetadata(gr4->mapper, hnd->handle,
android::gralloc4::MetadataType_PixelFormatModifier,
&encoded_modifier);
if (err != Error::NONE)
return -EINVAL;
status = android::gralloc4::decodePixelFormatModifier(encoded_modifier,
&drm_modifier);
if (status != android::OK)
return -EINVAL;
out->drm_fourcc = drm_fourcc;
out->modifier = drm_modifier;
auto layouts_opt = GetPlaneLayouts(gr4->mapper, hnd->handle);
if (!layouts_opt)
return -EINVAL;
std::vector<PlaneLayout> &layouts = *layouts_opt;
out->num_planes = layouts.size();
int fd_index = 0;
for (uint32_t i = 0; i < layouts.size(); i++) {
out->strides[i] = layouts[i].strideInBytes;
out->offsets[i] = layouts[i].offsetInBytes;
/* offset == 0 means layer is located in different dma-buf */
if (out->offsets[i] == 0 && i > 0)
fd_index++;
if (fd_index >= hnd->handle->numFds)
return -EINVAL;
out->fds[i] = hnd->handle->data[fd_index];
}
return 0;
}
static int
mapper4_get_buffer_color_info(struct u_gralloc *gralloc,
struct u_gralloc_buffer_handle *hnd,
struct u_gralloc_buffer_color_info *out)
{
gralloc4 *gr4 = (gralloc4 *)gralloc;
if (gr4->mapper == nullptr)
return -EINVAL;
if (!hnd->handle)
return -EINVAL;
/* optional attributes */
hidl_vec<uint8_t> encoded_chroma_siting;
std::optional<ChromaSiting> chroma_siting;
auto err = GetMetadata(gr4->mapper, hnd->handle,
android::gralloc4::MetadataType_ChromaSiting,
&encoded_chroma_siting);
if (err == Error::NONE) {
ExtendableType chroma_siting_ext;
auto status = android::gralloc4::decodeChromaSiting(
encoded_chroma_siting, &chroma_siting_ext);
if (status != android::OK)
return -EINVAL;
chroma_siting =
android::gralloc4::getStandardChromaSitingValue(chroma_siting_ext);
}
hidl_vec<uint8_t> encoded_dataspace;
err = GetMetadata(gr4->mapper, hnd->handle,
android::gralloc4::MetadataType_Dataspace,
&encoded_dataspace);
if (err == Error::NONE) {
Dataspace dataspace;
auto status =
android::gralloc4::decodeDataspace(encoded_dataspace, &dataspace);
if (status != android::OK)
return -EINVAL;
/* default to __DRI_YUV_COLOR_SPACE_ITU_REC601 */
Dataspace standard =
(Dataspace)((int)dataspace & (uint32_t)Dataspace::STANDARD_MASK);
switch (standard) {
case Dataspace::STANDARD_BT709:
out->yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC709;
break;
case Dataspace::STANDARD_BT2020:
case Dataspace::STANDARD_BT2020_CONSTANT_LUMINANCE:
out->yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC2020;
break;
case Dataspace::STANDARD_BT601_625:
case Dataspace::STANDARD_BT601_625_UNADJUSTED:
case Dataspace::STANDARD_BT601_525:
case Dataspace::STANDARD_BT601_525_UNADJUSTED:
default:
out->yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC601;
break;
}
/* default to __DRI_YUV_NARROW_RANGE */
Dataspace range =
(Dataspace)((int)dataspace & (uint32_t)Dataspace::RANGE_MASK);
switch (range) {
case Dataspace::RANGE_FULL:
out->sample_range = __DRI_YUV_FULL_RANGE;
break;
case Dataspace::RANGE_LIMITED:
default:
out->sample_range = __DRI_YUV_NARROW_RANGE;
break;
}
}
/* default to __DRI_YUV_CHROMA_SITING_0_5 */
if (chroma_siting) {
switch (*chroma_siting) {
case ChromaSiting::COSITED_HORIZONTAL:
out->horizontal_siting = __DRI_YUV_CHROMA_SITING_0;
out->vertical_siting = __DRI_YUV_CHROMA_SITING_0_5;
break;
#if ANDROID_API_LEVEL >= 35
case ChromaSiting::COSITED_VERTICAL:
out->horizontal_siting = __DRI_YUV_CHROMA_SITING_0_5;
out->vertical_siting = __DRI_YUV_CHROMA_SITING_0;
break;
case ChromaSiting::COSITED_BOTH:
out->horizontal_siting = __DRI_YUV_CHROMA_SITING_0;
out->vertical_siting = __DRI_YUV_CHROMA_SITING_0;
break;
#endif
case ChromaSiting::SITED_INTERSTITIAL:
default:
out->horizontal_siting = __DRI_YUV_CHROMA_SITING_0_5;
out->vertical_siting = __DRI_YUV_CHROMA_SITING_0_5;
break;
}
}
return 0;
}
static int
mapper4_get_front_rendering_usage(struct u_gralloc *gralloc,
uint64_t *out_usage)
{
assert(out_usage);
#if ANDROID_API_LEVEL >= 33
*out_usage = static_cast<uint64_t>(BufferUsage::FRONT_BUFFER);
return 0;
#else
return -ENOTSUP;
#endif
}
static int
destroy(struct u_gralloc *gralloc)
{
gralloc4 *gr = (struct gralloc4 *)gralloc;
delete gr;
return 0;
}
struct u_gralloc *
u_gralloc_imapper_api_create()
{
auto mapper = IMapper::getService();
if (!mapper)
return NULL;
auto gr = new gralloc4;
gr->mapper = mapper;
gr->base.ops.get_buffer_basic_info = mapper4_get_buffer_basic_info;
gr->base.ops.get_buffer_color_info = mapper4_get_buffer_color_info;
gr->base.ops.get_front_rendering_usage = mapper4_get_front_rendering_usage;
gr->base.ops.destroy = destroy;
mesa_logi("Using IMapper v4 API");
return &gr->base;
}
} // extern "C"
@@ -0,0 +1,218 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2021 GlobalLogic Ukraine
* Copyright (C) 2021-2022 Roman Stratiienko ([email protected])
* SPDX-License-Identifier: MIT
*/
#include <aidl/android/hardware/graphics/common/BufferUsage.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 <ui/GraphicBufferMapper.h>
#include <system/window.h>
#include "util/log.h"
#include "u_gralloc_internal.h"
using aidl::android::hardware::graphics::common::BufferUsage;
using aidl::android::hardware::graphics::common::ChromaSiting;
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::graphics::common::V1_2::Dataspace;
using android::GraphicBufferMapper;
using android::OK;
using android::status_t;
std::optional<std::vector<PlaneLayout>>
GetPlaneLayouts(const native_handle_t *buffer)
{
std::vector<PlaneLayout> plane_layouts;
status_t error = GraphicBufferMapper::get().getPlaneLayouts(buffer, &plane_layouts);
if (error != OK)
return std::nullopt;
return plane_layouts;
}
struct gralloc_mapper {
struct u_gralloc base;
};
extern "C" {
static int
mapper5_get_buffer_basic_info(struct u_gralloc *gralloc,
struct u_gralloc_buffer_handle *hnd,
struct u_gralloc_buffer_basic_info *out)
{
if (!hnd->handle)
return -EINVAL;
uint32_t drm_fourcc;
status_t error = GraphicBufferMapper::get().getPixelFormatFourCC(hnd->handle, &drm_fourcc);
if (error != OK)
return -EINVAL;
uint64_t modifier;
error = GraphicBufferMapper::get().getPixelFormatModifier(hnd->handle,&modifier);
if (error != OK)
return -EINVAL;
out->drm_fourcc = drm_fourcc;
out->modifier = modifier;
auto layouts_opt = GetPlaneLayouts(hnd->handle);
if (!layouts_opt)
return -EINVAL;
std::vector<PlaneLayout> &layouts = *layouts_opt;
out->num_planes = layouts.size();
int fd_index = 0;
for (uint32_t i = 0; i < layouts.size(); i++) {
out->strides[i] = layouts[i].strideInBytes;
out->offsets[i] = layouts[i].offsetInBytes;
/* offset == 0 means layer is located in different dma-buf */
if (out->offsets[i] == 0 && i > 0)
fd_index++;
if (fd_index >= hnd->handle->numFds)
return -EINVAL;
out->fds[i] = hnd->handle->data[fd_index];
}
return 0;
}
static int
mapper5_get_buffer_color_info(struct u_gralloc *gralloc,
struct u_gralloc_buffer_handle *hnd,
struct u_gralloc_buffer_color_info *out)
{
if (!hnd->handle)
return -EINVAL;
/* optional attributes */
ChromaSiting chroma_siting;
status_t error = GraphicBufferMapper::get().getChromaSiting(hnd->handle, &chroma_siting);
if (error != OK)
return -EINVAL;
Dataspace dataspace;
error = GraphicBufferMapper::get().getDataspace(hnd->handle, &dataspace);
if (error != OK)
return -EINVAL;
/* default to __DRI_YUV_COLOR_SPACE_ITU_REC601 */
Dataspace standard =
(Dataspace)((int)dataspace & (uint32_t)Dataspace::STANDARD_MASK);
switch (standard) {
case Dataspace::STANDARD_BT709:
out->yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC709;
break;
case Dataspace::STANDARD_BT2020:
case Dataspace::STANDARD_BT2020_CONSTANT_LUMINANCE:
out->yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC2020;
break;
case Dataspace::STANDARD_BT601_625:
case Dataspace::STANDARD_BT601_625_UNADJUSTED:
case Dataspace::STANDARD_BT601_525:
case Dataspace::STANDARD_BT601_525_UNADJUSTED:
default:
out->yuv_color_space = __DRI_YUV_COLOR_SPACE_ITU_REC601;
break;
}
/* default to __DRI_YUV_NARROW_RANGE */
Dataspace range =
(Dataspace)((int)dataspace & (uint32_t)Dataspace::RANGE_MASK);
switch (range) {
case Dataspace::RANGE_FULL:
out->sample_range = __DRI_YUV_FULL_RANGE;
break;
case Dataspace::RANGE_LIMITED:
default:
out->sample_range = __DRI_YUV_NARROW_RANGE;
break;
}
/* default to __DRI_YUV_CHROMA_SITING_0_5 */
switch (chroma_siting) {
case ChromaSiting::COSITED_HORIZONTAL:
out->horizontal_siting = __DRI_YUV_CHROMA_SITING_0;
out->vertical_siting = __DRI_YUV_CHROMA_SITING_0_5;
break;
case ChromaSiting::COSITED_VERTICAL:
out->horizontal_siting = __DRI_YUV_CHROMA_SITING_0_5;
out->vertical_siting = __DRI_YUV_CHROMA_SITING_0;
break;
case ChromaSiting::COSITED_BOTH:
out->horizontal_siting = __DRI_YUV_CHROMA_SITING_0;
out->vertical_siting = __DRI_YUV_CHROMA_SITING_0;
break;
case ChromaSiting::SITED_INTERSTITIAL:
default:
out->horizontal_siting = __DRI_YUV_CHROMA_SITING_0_5;
out->vertical_siting = __DRI_YUV_CHROMA_SITING_0_5;
break;
}
return 0;
}
static int
mapper5_get_front_rendering_usage(struct u_gralloc *gralloc,
uint64_t *out_usage)
{
assert(out_usage);
#if ANDROID_API_LEVEL >= 33
*out_usage = static_cast<uint64_t>(BufferUsage::FRONT_BUFFER);
return 0;
#else
return -ENOTSUP;
#endif
}
static int
destroy(struct u_gralloc *gralloc)
{
gralloc_mapper *gr = (struct gralloc_mapper *)gralloc;
delete gr;
return 0;
}
struct u_gralloc *
u_gralloc_imapper_api_create()
{
auto &mapper = GraphicBufferMapper::get();
if(mapper.getMapperVersion() < GraphicBufferMapper::GRALLOC_4) {
mesa_logi("Could not find IMapper v4/v5 API");
return NULL;
}
auto gr = new gralloc_mapper;
gr->base.ops.get_buffer_basic_info = mapper5_get_buffer_basic_info;
gr->base.ops.get_buffer_color_info = mapper5_get_buffer_color_info;
gr->base.ops.get_front_rendering_usage = mapper5_get_front_rendering_usage;
gr->base.ops.destroy = destroy;
mesa_logi("Using IMapper %d API", mapper.getMapperVersion());
return &gr->base;
}
} // extern "C"
+179
View File
@@ -0,0 +1,179 @@
/*
* Mesa 3-D graphics library
*
* Copyright © 2021, Google Inc.
* Copyright (C) 2023 Roman Stratiienko ([email protected])
* SPDX-License-Identifier: MIT
*/
#include "u_gralloc_internal.h"
#include <hardware/gralloc.h>
#include <errno.h>
#include "drm-uapi/drm_fourcc.h"
#include "util/log.h"
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;
}
bool
is_hal_format_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;
}
int
get_hal_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;
}
int
get_fourcc_from_hal_format(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:
mesa_logw("unsupported native buffer format 0x%x", native);
}
return -1;
}
/* Fill the bufferinfo structure using the information from the
* android_ycbcr struct. fds[] are not filled by this function.
*/
int
bufferinfo_from_ycbcr(const struct android_ycbcr *ycbcr,
struct u_gralloc_buffer_handle *hnd,
struct u_gralloc_buffer_basic_info *out)
{
enum chroma_order 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. */
int drm_fourcc =
get_fourcc_yuv(hnd->hal_format, chroma_order, ycbcr->chroma_step);
if (drm_fourcc == -1) {
mesa_logw("unsupported YUV format, native = %x, chroma_order = %s, "
"chroma_step = %zu",
hnd->hal_format, chroma_order == YCbCr ? "YCbCr" : "YCrCb",
ycbcr->chroma_step);
return -EINVAL;
}
out->drm_fourcc = drm_fourcc;
out->num_planes = ycbcr->chroma_step == 2 ? 2 : 3;
/* 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->offsets[0] = (size_t)ycbcr->y;
/* We assume here that all the planes are located in one DMA-buf. */
if (chroma_order == YCrCb) {
out->offsets[1] = (size_t)ycbcr->cr;
out->offsets[2] = (size_t)ycbcr->cb;
} else {
out->offsets[1] = (size_t)ycbcr->cb;
out->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->strides[0] = ycbcr->ystride;
out->strides[1] = out->strides[2] = ycbcr->cstride;
return 0;
}
+56
View File
@@ -0,0 +1,56 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2023 Roman Stratiienko ([email protected])
* SPDX-License-Identifier: MIT
*/
#ifndef U_GRALLOC_INTERNAL_H
#define U_GRALLOC_INTERNAL_H
#ifdef __cplusplus
extern "C" {
#endif
#include "u_gralloc.h"
struct u_gralloc_ops {
int (*get_buffer_basic_info)(struct u_gralloc *gralloc,
struct u_gralloc_buffer_handle *hnd,
struct u_gralloc_buffer_basic_info *out);
int (*get_buffer_color_info)(struct u_gralloc *gralloc,
struct u_gralloc_buffer_handle *hnd,
struct u_gralloc_buffer_color_info *out);
int (*get_front_rendering_usage)(struct u_gralloc *gralloc,
uint64_t *out_usage);
int (*destroy)(struct u_gralloc *gralloc);
};
struct u_gralloc {
struct u_gralloc_ops ops;
int type;
};
extern struct u_gralloc *u_gralloc_cros_api_create(void);
#ifdef USE_IMAPPER4_METADATA_API
extern struct u_gralloc *u_gralloc_imapper_api_create(void);
#endif
extern struct u_gralloc *u_gralloc_qcom_create(void);
extern struct u_gralloc *u_gralloc_libdrm_create(void);
extern struct u_gralloc *u_gralloc_fallback_create(void);
/* Helpers for legacy grallocs */
struct android_ycbcr;
bool is_hal_format_yuv(int native);
int get_hal_format_bpp(int native);
int get_fourcc_from_hal_format(int native);
int bufferinfo_from_ycbcr(const struct android_ycbcr *ycbcr,
struct u_gralloc_buffer_handle *hnd,
struct u_gralloc_buffer_basic_info *out);
#ifdef __cplusplus
}
#endif
#endif /* U_GRALLOC_INTERNAL_H */
+106
View File
@@ -0,0 +1,106 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2023 Roman Stratiienko ([email protected])
* SPDX-License-Identifier: MIT
*/
#include "u_gralloc_libdrm.h"
#include <assert.h>
#include <dlfcn.h>
#include <errno.h>
#include <string.h>
#include <hardware/gralloc.h>
#include "util/log.h"
#include "util/u_memory.h"
#include "u_gralloc_internal.h"
/* Despite minigbm becoming standard gralloc for many distributions, some
* users still rely on legacy grallocs, like gbm_gralloc that use a native
* handle header that is located at libdrm/android/gralloc_handle.h.
* Using this gralloc is not recommended for new distributions.
*/
struct libdrm_gralloc {
struct u_gralloc base;
gralloc_module_t *gralloc_module;
struct u_gralloc *fallback_gralloc;
};
static const char gbm_gralloc_module_name[] = "GBM Memory Allocator";
static int
get_buffer_info(struct u_gralloc *gralloc,
struct u_gralloc_buffer_handle *hnd,
struct u_gralloc_buffer_basic_info *out)
{
struct libdrm_gralloc *gr = (struct libdrm_gralloc *)gralloc;
struct gralloc_handle_t *handle = (struct gralloc_handle_t *)hnd->handle;
assert(handle->base.numFds == GRALLOC_HANDLE_NUM_FDS);
assert(handle->base.numInts == GRALLOC_HANDLE_NUM_INTS);
assert(handle->magic == GRALLOC_HANDLE_MAGIC);
if (handle->version != GRALLOC_HANDLE_VERSION)
mesa_loge("Unexpected gralloc handle version %d", handle->version);
assert(handle->version == GRALLOC_HANDLE_VERSION);
/* Query basic information using fallback gralloc */
u_gralloc_get_buffer_basic_info(gr->fallback_gralloc, hnd, out);
/* Fill the known data using libdrm gralloc handle */
out->modifier = handle->modifier;
out->strides[0] = handle->stride;
return 0;
}
static int
destroy(struct u_gralloc *gralloc)
{
struct libdrm_gralloc *gr = (struct libdrm_gralloc *)gralloc;
if (gr->gralloc_module)
dlclose(gr->gralloc_module->common.dso);
if (gr->fallback_gralloc)
gr->fallback_gralloc->ops.destroy(gr->fallback_gralloc);
FREE(gr);
return 0;
}
struct u_gralloc *
u_gralloc_libdrm_create()
{
struct libdrm_gralloc *gr = CALLOC_STRUCT(libdrm_gralloc);
int err = 0;
err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
(const hw_module_t **)&gr->gralloc_module);
if (err)
goto fail;
if (strcmp(gr->gralloc_module->common.name, gbm_gralloc_module_name) != 0)
goto fail;
gr->base.ops.get_buffer_basic_info = get_buffer_info;
gr->base.ops.destroy = destroy;
mesa_logw("Using gralloc header from libdrm/android/gralloc_handle.h. "
" This is not recommended for new distributions. "
" Initializing a fallback gralloc as a helper:");
gr->fallback_gralloc = u_gralloc_fallback_create();
return &gr->base;
fail:
destroy(&gr->base);
return NULL;
}
+62
View File
@@ -0,0 +1,62 @@
/*
* Copyright (C) 2010-2011 Chia-I Wu <[email protected]>
* Copyright (C) 2010-2011 LunarG Inc.
* Copyright (C) 2016 Linaro, Ltd., Rob Herring <[email protected]>
* Copyright (C) 2018 Collabora, Robert Foss <[email protected]>
*
* SPDX-License-Identifier: MIT
*
* Copied from:
* https://gitlab.freedesktop.org/mesa/drm/-/blob/6abc164052e4902f67213baa279d743cf46227d4/android/gralloc_handle.h
*/
#ifndef __ANDROID_GRALLOC_HANDLE_H__
#define __ANDROID_GRALLOC_HANDLE_H__
#include <cutils/native_handle.h>
#include <stdint.h>
struct gralloc_handle_t {
native_handle_t base;
/* dma-buf file descriptor
* Must be located first since, native_handle_t is allocated
* using native_handle_create(), which allocates space for
* sizeof(native_handle_t) + sizeof(int) * (numFds + numInts)
* numFds = GRALLOC_HANDLE_NUM_FDS
* numInts = GRALLOC_HANDLE_NUM_INTS
* Where numFds represents the number of FDs and
* numInts represents the space needed for the
* remainder of this struct.
* And the FDs are expected to be found first following
* native_handle_t.
*/
int prime_fd;
/* api variables */
uint32_t magic; /* differentiate between allocator impls */
uint32_t version; /* api version */
uint32_t width; /* width of buffer in pixels */
uint32_t height; /* height of buffer in pixels */
uint32_t format; /* pixel format (Android) */
uint32_t usage; /* android libhardware usage flags */
uint32_t stride; /* the stride in bytes */
int data_owner; /* owner of data (for validation) */
uint64_t modifier __attribute__((aligned(8))); /* buffer modifiers */
union {
void *data; /* pointer to struct gralloc_gbm_bo_t */
uint64_t reserved;
} __attribute__((aligned(8)));
};
#define GRALLOC_HANDLE_VERSION 4
#define GRALLOC_HANDLE_MAGIC 0x60585350
#define GRALLOC_HANDLE_NUM_FDS 1
#define GRALLOC_HANDLE_NUM_INTS ( \
((sizeof(struct gralloc_handle_t) - sizeof(native_handle_t))/sizeof(int)) \
- GRALLOC_HANDLE_NUM_FDS)
#endif /* __ANDROID_GRALLOC_HANDLE_H__ */
+228
View File
@@ -0,0 +1,228 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2023 Roman Stratiienko ([email protected])
* SPDX-License-Identifier: MIT
*/
#include <assert.h>
#include <dlfcn.h>
#include <errno.h>
#include <string.h>
#include <hardware/gralloc.h>
#include <hardware/gralloc1.h>
#include "drm-uapi/drm_fourcc.h"
#include "util/log.h"
#include "util/u_memory.h"
#include "u_gralloc_internal.h"
/* Using this gralloc is not recommended for new distributions. */
struct qcom_gralloc {
struct u_gralloc base;
hw_module_t *gralloc_module;
gralloc1_device_t *gralloc1_device;
void *perform_handle;
int (* perform)(void *dev, int op, ...);
struct u_gralloc *fallback_gralloc;
};
#define GRALLOC1_FUNCTION_PERFORM 0x00001000 /* QCOM gralloc-specific */
static const char qcom_gralloc_name[] = "Graphics Memory Allocator Module";
static const char qcom_gralloc_author[] = "The Android Open Source Project";
static const char caf_gralloc_name[] = "Graphics Memory Module";
static const char caf_gralloc_author[] = "Code Aurora Forum";
#define QCOM_GRALLOC_PROBE_WIDTH 1024
#define QCOM_GRALLOC_PROBE_FORMAT 1 /* HAL_PIXEL_FORMAT_RGBA_8888 */
#define GRALLOC_MODULE_PERFORM_GET_STRIDE 2
#define GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO 7
#define GRALLOC_MODULE_PERFORM_GET_UBWC_FLAG 9
static int
fallback_gralloc_get_yuv_info(struct u_gralloc *gralloc,
struct u_gralloc_buffer_handle *hnd,
struct u_gralloc_buffer_basic_info *out)
{
struct qcom_gralloc *gr = (struct qcom_gralloc *)gralloc;
struct android_ycbcr ycbcr;
int ret;
memset(&ycbcr, 0, sizeof(ycbcr));
ret = gr->perform(gr->perform_handle,
GRALLOC_MODULE_PERFORM_GET_YUV_PLANE_INFO,
hnd->handle, &ycbcr);
if (ret) {
/* HACK: See native_window_buffer_get_buffer_info() and
* https://issuetracker.google.com/32077885.*/
if (hnd->hal_format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)
return -EAGAIN;
mesa_logw("gralloc->lock_ycbcr failed: %d", ret);
return -EINVAL;
}
ret = bufferinfo_from_ycbcr(&ycbcr, hnd, out);
if (ret)
return ret;
out->fds[1] = out->fds[0] = hnd->handle->data[0];
if (out->num_planes == 3)
out->fds[2] = hnd->handle->data[0];
return 0;
}
static int
get_buffer_info(struct u_gralloc *gralloc,
struct u_gralloc_buffer_handle *hnd,
struct u_gralloc_buffer_basic_info *out)
{
struct qcom_gralloc *gr = (struct qcom_gralloc *)gralloc;
int drm_fourcc = 0;
int stride = 0;
int out_flag = 0;
int err;
err = gr->perform(gr->perform_handle, GRALLOC_MODULE_PERFORM_GET_UBWC_FLAG,
hnd->handle, &out_flag);
/* This may fail since some earlier MSM grallocs do not support this
* perform call
*/
if (!err && out_flag)
out->modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED;
else
out->modifier = DRM_FORMAT_MOD_LINEAR;
if (is_hal_format_yuv(hnd->hal_format)) {
int ret = fallback_gralloc_get_yuv_info(gralloc, hnd, out);
/*
* 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;
}
drm_fourcc = get_fourcc_from_hal_format(hnd->hal_format);
if (drm_fourcc == -1) {
mesa_loge("Failed to get drm_fourcc");
return -EINVAL;
}
stride = hnd->pixel_stride * get_hal_format_bpp(hnd->hal_format);
if (stride == 0) {
mesa_loge("Failed to calcuulate stride");
return -EINVAL;
}
out->drm_fourcc = drm_fourcc;
out->num_planes = 1;
out->fds[0] = hnd->handle->data[0];
out->strides[0] = stride;
return 0;
}
static int
destroy(struct u_gralloc *gralloc)
{
struct qcom_gralloc *gr = (struct qcom_gralloc *)gralloc;
if (gr->gralloc1_device)
gralloc1_close(gr->gralloc1_device);
if (gr->gralloc_module)
dlclose(gr->gralloc_module->dso);
if (gr->fallback_gralloc)
gr->fallback_gralloc->ops.destroy(gr->fallback_gralloc);
FREE(gr);
return 0;
}
struct u_gralloc *
u_gralloc_qcom_create()
{
struct qcom_gralloc *gr = CALLOC_STRUCT(qcom_gralloc);
int err = 0;
err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
(const hw_module_t **)&gr->gralloc_module);
if (err)
goto fail;
bool match = false;
if (strcmp(gr->gralloc_module->name, qcom_gralloc_name) == 0 &&
strcmp(gr->gralloc_module->author, qcom_gralloc_author) == 0) {
match = true;
}
if (strcmp(gr->gralloc_module->name, caf_gralloc_name) == 0 &&
strcmp(gr->gralloc_module->author, caf_gralloc_author) == 0) {
match = true;
}
if (!match)
goto fail;
if (gr->gralloc_module->module_api_version <= GRALLOC_MODULE_API_VERSION_0_3) {
gralloc_module_t *gralloc_module =
(gralloc_module_t *)gr->gralloc_module;
gr->perform = (int (*)(void *, int, ...))gralloc_module->perform;
gr->perform_handle = gr->gralloc_module;
} else {
err = gralloc1_open(gr->gralloc_module, &gr->gralloc1_device);
if (err)
goto fail;
gr->perform = (int (*)(void *, int, ...))gr->gralloc1_device->
getFunction(gr->gralloc1_device, GRALLOC1_FUNCTION_PERFORM);
gr->perform_handle = gr->gralloc1_device;
}
if (!gr->perform)
goto fail;
/* Check if the gralloc module supports the required perform call */
int out_stride = 0;
err = gr->perform(gr->perform_handle,
GRALLOC_MODULE_PERFORM_GET_STRIDE,
QCOM_GRALLOC_PROBE_WIDTH,
QCOM_GRALLOC_PROBE_FORMAT,
&out_stride);
if (err)
goto fail;
if (out_stride == 0)
goto fail;
gr->base.ops.get_buffer_basic_info = get_buffer_info;
gr->base.ops.destroy = destroy;
mesa_logi("Using QCOM gralloc (aosp/hardware/qcom/display/*/libgralloc). ");
mesa_logw("QCOM Gralloc API is old. Consider using Gralloc4 API instead.");
gr->fallback_gralloc = u_gralloc_fallback_create();
return &gr->base;
fail:
destroy(&gr->base);
return NULL;
}