blob: 960986fb89e998705f9c1c7f5c0b8e1789f1dc50 [file] [log] [blame]
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2022 Roman Stratiienko (r.stratiienko@gmail.com)
* 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;
}