/* * Mesa 3-D graphics library * * Copyright © 2021, Google Inc. * SPDX-License-Identifier: MIT */ #include #include #include #include #include #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; }