mirror of
https://github.com/elwrcl/intel-hard-graphics.git
synced 2026-11-01 03:18:02 +03:00
init
This commit is contained in:
12511 files changed
+6156641
No files matched your search
@@ -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)
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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__ */
|
||||
@@ -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;
|
||||
}
|
||||
Reference in new issue
Block a user