blob: a94e7fee72479a05b3cf98ed2970fbf2125256f9 [file]
/*
* 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"
/* 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_USAGE_FRONT_RENDERING_BIT 0x1
struct cros_gralloc0_buffer_info {
uint32_t drm_fourcc;
int num_fds;
int fds[4];
uint64_t modifier;
int offset[4];
int stride[4];
};
static int
cros_get_buffer_info(struct 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
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_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;
}