mesa/src/util/u_gralloc/u_gralloc.c

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

153 lines
3.8 KiB
C
Raw Normal View History

android: Introduce the Android buffer info abstraction Both EGL and Vulkan implementations require obtaining buffer metadata, e.g., format, modifier, offsets, strides, etc. Currently, mesa3d doesn't have a generic solution, and every Vulkan implementation uses its getters. Most of the getters rely on kernel metadata storage that is available for x86-based GPU drivers. ARM-based Vulkan drivers rely on userspace metadata sharing, making it important to use advanced metadata API. Otherwise, the driver will work with limited functionality (no YUV, lack of support for modifiers, etc.) Current EGL buffer getter implementation is advanced enough and used as a base for a common Android buffer-getter logic. Use example: void android_buffer_test(android_handle_type *a_handle) { // First, get the gralloc object. It will be created if it doesn't // exist. Use U_GRALLOC_TYPE_AUTO to let the implementation choose // the best gralloc struct u_gralloc *gralloc = u_gralloc_create(U_GRALLOC_TYPE_AUTO); // Prepare the internal handle structure (hal_format and // pixel_stride are required for the fallback implementation). // Both Vulkan and EGL clients expose HAL format / pixel stride // in their structures. u_gralloc_buffer_handle hnd = { .handle = a_handle->native_handle, .hal_format = a_handle->hal_format, .pixel_stride = a_handle->pixel_stride, }; // Get the basic buffer info u_gralloc_buffer_basic_info basic_info; int ret = u_gralloc_get_buffer_basic_info(gralloc, &hnd, &basic_info); if (ret) { // Handle the error } // Get the color info u_gralloc_buffer_color_info color_info; ret = u_gralloc_get_buffer_color_info(gralloc, &hnd, &color_info); if (ret) { // Handle the error } // unref the gralloc object u_gralloc_destroy(&gralloc); } Signed-off-by: Roman Stratiienko <r.stratiienko@gmail.com> Reviewed-by: Chia-I Wu <olvaffe@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18215>
2022-08-23 20:08:22 +03:00
/*
* 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 */
android: Introduce the Android buffer info abstraction Both EGL and Vulkan implementations require obtaining buffer metadata, e.g., format, modifier, offsets, strides, etc. Currently, mesa3d doesn't have a generic solution, and every Vulkan implementation uses its getters. Most of the getters rely on kernel metadata storage that is available for x86-based GPU drivers. ARM-based Vulkan drivers rely on userspace metadata sharing, making it important to use advanced metadata API. Otherwise, the driver will work with limited functionality (no YUV, lack of support for modifiers, etc.) Current EGL buffer getter implementation is advanced enough and used as a base for a common Android buffer-getter logic. Use example: void android_buffer_test(android_handle_type *a_handle) { // First, get the gralloc object. It will be created if it doesn't // exist. Use U_GRALLOC_TYPE_AUTO to let the implementation choose // the best gralloc struct u_gralloc *gralloc = u_gralloc_create(U_GRALLOC_TYPE_AUTO); // Prepare the internal handle structure (hal_format and // pixel_stride are required for the fallback implementation). // Both Vulkan and EGL clients expose HAL format / pixel stride // in their structures. u_gralloc_buffer_handle hnd = { .handle = a_handle->native_handle, .hal_format = a_handle->hal_format, .pixel_stride = a_handle->pixel_stride, }; // Get the basic buffer info u_gralloc_buffer_basic_info basic_info; int ret = u_gralloc_get_buffer_basic_info(gralloc, &hnd, &basic_info); if (ret) { // Handle the error } // Get the color info u_gralloc_buffer_color_info color_info; ret = u_gralloc_get_buffer_color_info(gralloc, &hnd, &color_info); if (ret) { // Handle the error } // unref the gralloc object u_gralloc_destroy(&gralloc); } Signed-off-by: Roman Stratiienko <r.stratiienko@gmail.com> Reviewed-by: Chia-I Wu <olvaffe@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18215>
2022-08-23 20:08:22 +03:00
{.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_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].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 NONNULL)
{
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
android: Introduce the Android buffer info abstraction Both EGL and Vulkan implementations require obtaining buffer metadata, e.g., format, modifier, offsets, strides, etc. Currently, mesa3d doesn't have a generic solution, and every Vulkan implementation uses its getters. Most of the getters rely on kernel metadata storage that is available for x86-based GPU drivers. ARM-based Vulkan drivers rely on userspace metadata sharing, making it important to use advanced metadata API. Otherwise, the driver will work with limited functionality (no YUV, lack of support for modifiers, etc.) Current EGL buffer getter implementation is advanced enough and used as a base for a common Android buffer-getter logic. Use example: void android_buffer_test(android_handle_type *a_handle) { // First, get the gralloc object. It will be created if it doesn't // exist. Use U_GRALLOC_TYPE_AUTO to let the implementation choose // the best gralloc struct u_gralloc *gralloc = u_gralloc_create(U_GRALLOC_TYPE_AUTO); // Prepare the internal handle structure (hal_format and // pixel_stride are required for the fallback implementation). // Both Vulkan and EGL clients expose HAL format / pixel stride // in their structures. u_gralloc_buffer_handle hnd = { .handle = a_handle->native_handle, .hal_format = a_handle->hal_format, .pixel_stride = a_handle->pixel_stride, }; // Get the basic buffer info u_gralloc_buffer_basic_info basic_info; int ret = u_gralloc_get_buffer_basic_info(gralloc, &hnd, &basic_info); if (ret) { // Handle the error } // Get the color info u_gralloc_buffer_color_info color_info; ret = u_gralloc_get_buffer_color_info(gralloc, &hnd, &color_info); if (ret) { // Handle the error } // unref the gralloc object u_gralloc_destroy(&gralloc); } Signed-off-by: Roman Stratiienko <r.stratiienko@gmail.com> Reviewed-by: Chia-I Wu <olvaffe@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18215>
2022-08-23 20:08:22 +03:00
u_gralloc_get_buffer_basic_info(struct u_gralloc *gralloc NONNULL,
struct u_gralloc_buffer_handle *hnd NONNULL,
struct u_gralloc_buffer_basic_info *out
NONNULL)
{
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
android: Introduce the Android buffer info abstraction Both EGL and Vulkan implementations require obtaining buffer metadata, e.g., format, modifier, offsets, strides, etc. Currently, mesa3d doesn't have a generic solution, and every Vulkan implementation uses its getters. Most of the getters rely on kernel metadata storage that is available for x86-based GPU drivers. ARM-based Vulkan drivers rely on userspace metadata sharing, making it important to use advanced metadata API. Otherwise, the driver will work with limited functionality (no YUV, lack of support for modifiers, etc.) Current EGL buffer getter implementation is advanced enough and used as a base for a common Android buffer-getter logic. Use example: void android_buffer_test(android_handle_type *a_handle) { // First, get the gralloc object. It will be created if it doesn't // exist. Use U_GRALLOC_TYPE_AUTO to let the implementation choose // the best gralloc struct u_gralloc *gralloc = u_gralloc_create(U_GRALLOC_TYPE_AUTO); // Prepare the internal handle structure (hal_format and // pixel_stride are required for the fallback implementation). // Both Vulkan and EGL clients expose HAL format / pixel stride // in their structures. u_gralloc_buffer_handle hnd = { .handle = a_handle->native_handle, .hal_format = a_handle->hal_format, .pixel_stride = a_handle->pixel_stride, }; // Get the basic buffer info u_gralloc_buffer_basic_info basic_info; int ret = u_gralloc_get_buffer_basic_info(gralloc, &hnd, &basic_info); if (ret) { // Handle the error } // Get the color info u_gralloc_buffer_color_info color_info; ret = u_gralloc_get_buffer_color_info(gralloc, &hnd, &color_info); if (ret) { // Handle the error } // unref the gralloc object u_gralloc_destroy(&gralloc); } Signed-off-by: Roman Stratiienko <r.stratiienko@gmail.com> Reviewed-by: Chia-I Wu <olvaffe@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18215>
2022-08-23 20:08:22 +03:00
u_gralloc_get_buffer_color_info(struct u_gralloc *gralloc NONNULL,
struct u_gralloc_buffer_handle *hnd NONNULL,
struct u_gralloc_buffer_color_info *out
NONNULL)
{
struct u_gralloc_buffer_color_info info = {0};
int ret;
if (!gralloc->ops.get_buffer_color_info)
return -ENOTSUP;
ret = gralloc->ops.get_buffer_color_info(gralloc, hnd, &info);
if (ret)
return ret;
*out = info;
return 0;
}
int
android: Introduce the Android buffer info abstraction Both EGL and Vulkan implementations require obtaining buffer metadata, e.g., format, modifier, offsets, strides, etc. Currently, mesa3d doesn't have a generic solution, and every Vulkan implementation uses its getters. Most of the getters rely on kernel metadata storage that is available for x86-based GPU drivers. ARM-based Vulkan drivers rely on userspace metadata sharing, making it important to use advanced metadata API. Otherwise, the driver will work with limited functionality (no YUV, lack of support for modifiers, etc.) Current EGL buffer getter implementation is advanced enough and used as a base for a common Android buffer-getter logic. Use example: void android_buffer_test(android_handle_type *a_handle) { // First, get the gralloc object. It will be created if it doesn't // exist. Use U_GRALLOC_TYPE_AUTO to let the implementation choose // the best gralloc struct u_gralloc *gralloc = u_gralloc_create(U_GRALLOC_TYPE_AUTO); // Prepare the internal handle structure (hal_format and // pixel_stride are required for the fallback implementation). // Both Vulkan and EGL clients expose HAL format / pixel stride // in their structures. u_gralloc_buffer_handle hnd = { .handle = a_handle->native_handle, .hal_format = a_handle->hal_format, .pixel_stride = a_handle->pixel_stride, }; // Get the basic buffer info u_gralloc_buffer_basic_info basic_info; int ret = u_gralloc_get_buffer_basic_info(gralloc, &hnd, &basic_info); if (ret) { // Handle the error } // Get the color info u_gralloc_buffer_color_info color_info; ret = u_gralloc_get_buffer_color_info(gralloc, &hnd, &color_info); if (ret) { // Handle the error } // unref the gralloc object u_gralloc_destroy(&gralloc); } Signed-off-by: Roman Stratiienko <r.stratiienko@gmail.com> Reviewed-by: Chia-I Wu <olvaffe@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18215>
2022-08-23 20:08:22 +03:00
u_gralloc_get_front_rendering_usage(struct u_gralloc *gralloc NONNULL,
uint64_t *out_usage NONNULL)
{
if (!gralloc->ops.get_front_rendering_usage)
return -ENOTSUP;
return gralloc->ops.get_front_rendering_usage(gralloc, out_usage);
}