diff options
author | Jason Macnak <natsu@google.com> | 2023-12-20 19:48:58 +0000 |
---|---|---|
committer | Jason Macnak <natsu@google.com> | 2023-12-20 19:51:35 +0000 |
commit | 31b7dab231a66074e4c22d05c809cba62d19fcb9 (patch) | |
tree | 2e67969f3176fbf88e2855c0acca37afc3ae1ce9 | |
parent | b5db10cf57040470d521cd05bcb292da1f238108 (diff) | |
parent | 6897f2aa86c67198812320c7ad54c9e73e0a87ae (diff) | |
download | minigbm-android12-gsi.tar.gz |
Merge remote-tracking branch 'aosp/android13-gsi' into 'aosp/android12-gsi'android12-gsi
... to pull in http://crrev.com/c/3265944 to disable GPU_MIPMAP_COMPLETE.
Bug: b/303050016
Test: cts -m CtsNativeHardwareTestCases
Change-Id: I0aaf6930443ce55f907d765703a0ebd1b87cc2c7
65 files changed, 2363 insertions, 2896 deletions
@@ -32,16 +32,15 @@ license { ], } -cc_defaults { - name: "minigbm_defaults", +filegroup { + name: "minigbm_core_files", srcs: [ "amdgpu.c", "drv.c", + "drv_array_helpers.c", + "drv_helpers.c", "dumb_driver.c", - "exynos.c", - "helpers_array.c", - "helpers.c", "i915.c", "mediatek.c", "msm.c", @@ -51,6 +50,25 @@ cc_defaults { "virtgpu_cross_domain.c", "virtgpu_virgl.c", ], +} + +filegroup { + name: "minigbm_gralloc_common_files", + + srcs: [ + "cros_gralloc/cros_gralloc_buffer.cc", + "cros_gralloc/cros_gralloc_helpers.cc", + "cros_gralloc/cros_gralloc_driver.cc", + ], +} + +filegroup { + name: "minigbm_gralloc0_files", + srcs: ["cros_gralloc/gralloc0/gralloc0.cc"], +} + +cc_defaults { + name: "minigbm_defaults", cflags: [ "-D_GNU_SOURCE=1", @@ -63,7 +81,18 @@ cc_defaults { "-Wno-unused-parameter", ], - cppflags: ["-std=c++14"], + product_variables: { + platform_sdk_version: { + cflags: ["-DANDROID_API_LEVEL=%d"], + }, + }, +} + +cc_library_headers { + name: "minigbm_headers", + host_supported: true, + vendor_available: true, + export_include_dirs: ["."], } cc_defaults { @@ -74,58 +103,54 @@ cc_defaults { header_libs: [ "libhardware_headers", "libnativebase_headers", - "libnativewindow_headers", "libsystem_headers", - ], - - export_header_lib_headers: [ - "libhardware_headers", - "libnativebase_headers", - "libnativewindow_headers", - "libsystem_headers", - ], - - srcs: [ - "cros_gralloc/cros_gralloc_buffer.cc", - "cros_gralloc/cros_gralloc_helpers.cc", - "cros_gralloc/cros_gralloc_driver.cc", + "minigbm_headers", ], static_libs: ["libarect"], - export_static_lib_headers: ["libarect"], - vendor: true, shared_libs: [ "libcutils", + "libdmabufheap", "libdrm", "libnativewindow", "libsync", "liblog", ], - - relative_install_path: "hw", } cc_defaults { - name: "gbm_defaults", - - defaults: ["minigbm_defaults"], + name: "minigbm_cros_gralloc_library_defaults", + defaults: ["minigbm_cros_gralloc_defaults"], srcs: [ - "gbm.c", - "gbm_helpers.c", + ":minigbm_core_files", + ":minigbm_gralloc_common_files", ], +} - export_include_dirs: ["."], +cc_defaults { + name: "minigbm_cros_gralloc0_defaults", + + defaults: ["minigbm_cros_gralloc_defaults"], + relative_install_path: "hw", + + srcs: [":minigbm_gralloc0_files"], } cc_library { name: "libgbm", - defaults: ["gbm_defaults"], + defaults: ["minigbm_defaults"], host_supported: true, + srcs: [ + ":minigbm_core_files", + "gbm.c", + "gbm_helpers.c", + ], + target: { host: { // Avoid linking to another host copy of libdrm; this library will cause @@ -145,31 +170,43 @@ cc_library { "//apex_available:platform", "com.android.virt", ], -} - -cc_defaults { - name: "libminigbm_cros_gralloc_defaults", - defaults: ["minigbm_cros_gralloc_defaults"], - shared_libs: ["liblog"], - static_libs: ["libdrm"], export_include_dirs: ["."], } -cc_library_static { - name: "libminigbm_cros_gralloc", - defaults: ["libminigbm_cros_gralloc_defaults"], +// Generic +cc_library_shared { + name: "libminigbm_gralloc", + defaults: ["minigbm_cros_gralloc_library_defaults"], + cflags: ["-DHAS_DMABUF_SYSTEM_HEAP"], } cc_library_shared { name: "gralloc.minigbm", - defaults: ["minigbm_cros_gralloc_defaults"], - srcs: ["cros_gralloc/gralloc0/gralloc0.cc"], + defaults: ["minigbm_cros_gralloc0_defaults"], + shared_libs: ["libminigbm_gralloc"], +} + +// Intel +cc_library_shared { + name: "libminigbm_gralloc_intel", + defaults: ["minigbm_cros_gralloc_library_defaults"], + cflags: ["-DDRV_I915"], + enabled: false, + arch: { + x86: { + enabled: true, + }, + x86_64: { + enabled: true, + }, + }, } cc_library_shared { name: "gralloc.minigbm_intel", - defaults: ["minigbm_cros_gralloc_defaults"], + defaults: ["minigbm_cros_gralloc0_defaults"], + shared_libs: ["libminigbm_gralloc_intel"], enabled: false, arch: { x86: { @@ -179,28 +216,47 @@ cc_library_shared { enabled: true, }, }, - cflags: ["-DDRV_I915"], - srcs: ["cros_gralloc/gralloc0/gralloc0.cc"], } +// Meson cc_library_shared { - name: "gralloc.minigbm_meson", - defaults: ["minigbm_cros_gralloc_defaults"], + name: "libminigbm_gralloc_meson", + defaults: ["minigbm_cros_gralloc_library_defaults"], cflags: ["-DDRV_MESON"], - srcs: ["cros_gralloc/gralloc0/gralloc0.cc"], } cc_library_shared { - name: "gralloc.minigbm_msm", - defaults: ["minigbm_cros_gralloc_defaults"], - cflags: ["-DDRV_MSM"], - srcs: [ - "cros_gralloc/gralloc0/gralloc0.cc", + name: "gralloc.minigbm_meson", + defaults: ["minigbm_cros_gralloc0_defaults"], + shared_libs: ["libminigbm_gralloc_meson"], +} + +// MSM +cc_library_shared { + name: "libminigbm_gralloc_msm", + defaults: ["minigbm_cros_gralloc_library_defaults"], + cflags: [ + "-DDRV_MSM", + "-DQCOM_DISABLE_COMPRESSED_NV12", + "-DHAS_DMABUF_SYSTEM_HEAP", ], } -cc_library_static { - name: "libminigbm_cros_gralloc_msm", - defaults: ["libminigbm_cros_gralloc_defaults"], - cflags: ["-DDRV_MSM"], +cc_library_shared { + name: "gralloc.minigbm_msm", + defaults: ["minigbm_cros_gralloc0_defaults"], + shared_libs: ["libminigbm_gralloc_msm"], +} + +// ARCVM +cc_library_shared { + name: "libminigbm_gralloc_arcvm", + defaults: ["minigbm_cros_gralloc_library_defaults"], + cflags: ["-DVIRTIO_GPU_NEXT"], +} + +cc_library_shared { + name: "gralloc.minigbm_arcvm", + defaults: ["minigbm_cros_gralloc0_defaults"], + shared_libs: ["libminigbm_gralloc_arcvm"], } diff --git a/Android.gralloc.mk b/Android.gralloc.mk deleted file mode 100644 index ff269c0..0000000 --- a/Android.gralloc.mk +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright 2017 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -LOCAL_CPP_EXTENSION := .cc - -LOCAL_SRC_FILES += \ - cros_gralloc/cros_gralloc_buffer.cc \ - cros_gralloc/cros_gralloc_driver.cc \ - cros_gralloc/cros_gralloc_helpers.cc \ - cros_gralloc/gralloc0/gralloc0.cc @@ -16,9 +16,6 @@ ifdef DRV_AMDGPU CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_amdgpu) LDLIBS += -ldrm_amdgpu -ldl endif -ifdef DRV_EXYNOS - CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_exynos) -endif ifdef DRV_I915 CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_intel) endif @@ -49,6 +46,7 @@ MINIGBM_FILENAME := libminigbm.so.$(MINIGBM_VERSION) CC_LIBRARY($(MINIGBM_FILENAME)): LDFLAGS += -Wl,-soname,libgbm.so.$(GBM_VERSION_MAJOR) CC_LIBRARY($(MINIGBM_FILENAME)): $(C_OBJECTS) +CC_STATIC_LIBRARY(libminigbm.pie.a): $(C_OBJECTS) all: CC_LIBRARY($(MINIGBM_FILENAME)) @@ -1,10 +1,20 @@ +basni@chromium.org +dbehr@chromium.org +ddavenport@chromium.org gurchetansingh@chromium.org +hiroh@chromium.org hoegsberg@chromium.org marcheu@chromium.org -stevensd@chromium.org +mcasas@chromium.org +olv@google.com +robdclark@chromium.org tfiga@chromium.org +zzyiwei@chromium.org -# Also natsu@google.com is great for gralloc/Android stuff but doesn't have a -# chromium account. -# So any team members can +2 -* +# just reference for backend specific reviews +per-file amdgpu.c = basni@chromium.org, ddavenport@chromium.org +per-file i915.c = chadversary@chromium.org, hoegsberg@chromium.org +per-file mediatek.c = fshao@chromium.org, hsinyi@chromium.org, tzungbi@chromium.org +per-file msm.c = robdclark@chromium.org, hoegsberg@chromium.org +per-file rockchip.c = tfiga@chromium.org +per-file virtgpu* = jbates@chromium.org, natsu@google.com, olv@google.com, zzyiwei@chromium.org @@ -6,16 +6,21 @@ #ifdef DRV_AMDGPU #include <amdgpu.h> #include <amdgpu_drm.h> +#include <assert.h> +#include <drm_fourcc.h> #include <errno.h> +#include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/mman.h> +#include <unistd.h> #include <xf86drm.h> +#include <xf86drmMode.h> #include "dri.h" +#include "drv_helpers.h" #include "drv_priv.h" -#include "helpers.h" #include "util.h" // clang-format off @@ -23,8 +28,10 @@ // clang-format on #define TILE_TYPE_LINEAR 0 +/* We decide a modifier and then use DRI to manage allocation */ +#define TILE_TYPE_DRI_MODIFIER 1 /* DRI backend decides tiling in this case. */ -#define TILE_TYPE_DRI 1 +#define TILE_TYPE_DRI 2 /* Height alignement for Encoder/Decoder buffers */ #define CHROME_HEIGHT_ALIGN 16 @@ -305,6 +312,39 @@ unmap_src: return ret; } +static bool is_modifier_scanout_capable(struct amdgpu_priv *priv, uint32_t format, + uint64_t modifier) +{ + unsigned bytes_per_pixel = drv_stride_from_format(format, 1, 0); + + if (modifier == DRM_FORMAT_MOD_LINEAR) + return true; + + if ((modifier >> 56) != DRM_FORMAT_MOD_VENDOR_AMD) + return false; + + unsigned swizzle = AMD_FMT_MOD_GET(TILE, modifier); + if (priv->dev_info.family >= AMDGPU_FAMILY_RV) { /* DCN based GPUs */ + /* D swizzle only supported for 64 bpp */ + if ((swizzle & 3) == 2 && bytes_per_pixel != 8) + return false; + + /* S swizzle not supported for 64 bpp */ + if ((swizzle & 3) == 1 && bytes_per_pixel == 8) + return false; + } else { /* DCE based GPUs with GFX9 based modifier swizzling. */ + assert(priv->dev_info.family == AMDGPU_FAMILY_AI); + /* Only D swizzles are allowed for display */ + if ((swizzle & 3) != 2) + return false; + } + + if (AMD_FMT_MOD_GET(DCC, modifier) && + (AMD_FMT_MOD_GET(DCC_PIPE_ALIGN, modifier) || !AMD_FMT_MOD_GET(DCC_RETILE, modifier))) + return false; + return true; +} + static int amdgpu_init(struct driver *drv) { struct amdgpu_priv *priv; @@ -370,6 +410,7 @@ static int amdgpu_init(struct driver *drv) drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT); drv_modify_combination(drv, DRM_FORMAT_ABGR8888, &metadata, BO_USE_SCANOUT); drv_modify_combination(drv, DRM_FORMAT_XBGR8888, &metadata, BO_USE_SCANOUT); + drv_modify_combination(drv, DRM_FORMAT_RGB565, &metadata, BO_USE_SCANOUT); drv_modify_combination(drv, DRM_FORMAT_ABGR2101010, &metadata, BO_USE_SCANOUT); drv_modify_combination(drv, DRM_FORMAT_ARGB2101010, &metadata, BO_USE_SCANOUT); @@ -394,24 +435,60 @@ static int amdgpu_init(struct driver *drv) use_flags &= ~BO_USE_RENDERSCRIPT; use_flags &= ~BO_USE_SW_WRITE_OFTEN; use_flags &= ~BO_USE_SW_READ_OFTEN; +#if __ANDROID__ + use_flags &= ~BO_USE_SW_WRITE_RARELY; + use_flags &= ~BO_USE_SW_READ_RARELY; +#endif use_flags &= ~BO_USE_LINEAR; - metadata.tiling = TILE_TYPE_DRI; metadata.priority = 2; - drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), - &metadata, use_flags); - - /* Potentially tiled formats supported by display. */ - drv_modify_combination(drv, DRM_FORMAT_ARGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT); - drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT); - drv_modify_combination(drv, DRM_FORMAT_ABGR8888, &metadata, BO_USE_SCANOUT); - drv_modify_combination(drv, DRM_FORMAT_XBGR8888, &metadata, BO_USE_SCANOUT); - - drv_modify_combination(drv, DRM_FORMAT_ABGR2101010, &metadata, BO_USE_SCANOUT); - drv_modify_combination(drv, DRM_FORMAT_ARGB2101010, &metadata, BO_USE_SCANOUT); - drv_modify_combination(drv, DRM_FORMAT_XBGR2101010, &metadata, BO_USE_SCANOUT); - drv_modify_combination(drv, DRM_FORMAT_XRGB2101010, &metadata, BO_USE_SCANOUT); + for (unsigned f = 0; f < ARRAY_SIZE(render_target_formats); ++f) { + uint32_t format = render_target_formats[f]; + int mod_cnt; + if (dri_query_modifiers(drv, format, 0, NULL, &mod_cnt) && mod_cnt) { + uint64_t *modifiers = calloc(mod_cnt, sizeof(uint64_t)); + dri_query_modifiers(drv, format, mod_cnt, modifiers, &mod_cnt); + metadata.tiling = TILE_TYPE_DRI_MODIFIER; + for (int i = 0; i < mod_cnt; ++i) { + bool scanout = + is_modifier_scanout_capable(drv->priv, format, modifiers[i]); + + /* LINEAR will be handled using the LINEAR metadata. */ + if (modifiers[i] == DRM_FORMAT_MOD_LINEAR) + continue; + + /* The virtgpu minigbm can't handle auxiliary planes in the host. */ + if (dri_num_planes_from_modifier(drv, format, modifiers[i]) != + drv_num_planes_from_format(format)) + continue; + + metadata.modifier = modifiers[i]; + drv_add_combination(drv, format, &metadata, + use_flags | (scanout ? BO_USE_SCANOUT : 0)); + } + free(modifiers); + } else { + bool scanout = false; + switch (format) { + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_ABGR2101010: + case DRM_FORMAT_ARGB2101010: + case DRM_FORMAT_XBGR2101010: + case DRM_FORMAT_XRGB2101010: + scanout = true; + break; + default: + break; + } + metadata.tiling = TILE_TYPE_DRI; + drv_add_combination(drv, format, &metadata, + use_flags | (scanout ? BO_USE_SCANOUT : 0)); + } + } return 0; } @@ -439,9 +516,11 @@ static int amdgpu_create_bo_linear(struct bo *bo, uint32_t width, uint32_t heigh * For multiplane formats, align the stride to 512 to ensure that subsample strides are 256 * aligned. This uses more memory than necessary since the first plane only needs to be * 256 aligned, but it's acceptable for a short-term fix. It's probably safe for other gpu - * families, but let's restrict it to Raven for now (b/171013552). + * families, but let's restrict it to Raven and Stoney for now (b/171013552, b/190484589). + * This only applies to the Android YUV (multiplane) format. * */ - if (priv->dev_info.family == AMDGPU_FAMILY_RV && num_planes > 1) + if (format == DRM_FORMAT_YVU420_ANDROID && + (priv->dev_info.family == AMDGPU_FAMILY_RV || priv->dev_info.family == AMDGPU_FAMILY_CZ)) stride = ALIGN(stride, 512); else stride = ALIGN(stride, 256); @@ -503,28 +582,16 @@ static int amdgpu_create_bo(struct bo *bo, uint32_t width, uint32_t height, uint return -EINVAL; if (combo->metadata.tiling == TILE_TYPE_DRI) { - bool needs_alignment = false; -#ifdef __ANDROID__ - /* - * Currently, the gralloc API doesn't differentiate between allocation time and map - * time strides. A workaround for amdgpu DRI buffers is to always to align to 256 at - * allocation time. - * - * See b/115946221,b/117942643 - */ - if (use_flags & (BO_USE_SW_MASK)) - needs_alignment = true; -#endif // See b/122049612 - if (use_flags & (BO_USE_SCANOUT) && priv->dev_info.family == AMDGPU_FAMILY_CZ) - needs_alignment = true; - - if (needs_alignment) { + if (use_flags & (BO_USE_SCANOUT) && priv->dev_info.family == AMDGPU_FAMILY_CZ) { uint32_t bytes_per_pixel = drv_bytes_per_pixel_from_format(format, 0); width = ALIGN(width, 256 / bytes_per_pixel); } return dri_bo_create(bo, width, height, format, use_flags); + } else if (combo->metadata.tiling == TILE_TYPE_DRI_MODIFIER) { + return dri_bo_create_with_modifiers(bo, width, height, format, + &combo->metadata.modifier, 1); } return amdgpu_create_bo_linear(bo, width, height, format, use_flags); @@ -555,15 +622,26 @@ static int amdgpu_import_bo(struct bo *bo, struct drv_import_fd_data *data) if (!combo) return -EINVAL; - dri_tiling = combo->metadata.tiling == TILE_TYPE_DRI; + dri_tiling = combo->metadata.tiling != TILE_TYPE_LINEAR; } + bo->meta.num_planes = dri_num_planes_from_modifier(bo->drv, data->format, + data->format_modifier); + if (dri_tiling) return dri_bo_import(bo, data); else return drv_prime_bo_import(bo, data); } +static int amdgpu_release_bo(struct bo *bo) +{ + if (bo->priv) + return dri_bo_release(bo); + + return 0; +} + static int amdgpu_destroy_bo(struct bo *bo) { if (bo->priv) @@ -713,12 +791,13 @@ const struct backend backend_amdgpu = { .close = amdgpu_close, .bo_create = amdgpu_create_bo, .bo_create_with_modifiers = amdgpu_create_bo_with_modifiers, + .bo_release = amdgpu_release_bo, .bo_destroy = amdgpu_destroy_bo, .bo_import = amdgpu_import_bo, .bo_map = amdgpu_map_bo, .bo_unmap = amdgpu_unmap_bo, .bo_invalidate = amdgpu_bo_invalidate, - .resolve_format = drv_resolve_format_helper, + .resolve_format_and_use_flags = drv_resolve_format_and_use_flags_helper, .num_planes_from_modifier = dri_num_planes_from_modifier, }; @@ -7,7 +7,7 @@ # # NOTE NOTE NOTE # The authoritative common.mk is located in: -# https://chromium.googlesource.com/chromiumos/platform2/+/master/common-mk +# https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/common-mk # Please make all changes there, then copy into place in other repos. # NOTE NOTE NOTE # diff --git a/cros_gralloc/OWNERS b/cros_gralloc/OWNERS new file mode 100644 index 0000000..cd8d003 --- /dev/null +++ b/cros_gralloc/OWNERS @@ -0,0 +1,3 @@ +set noparent +natsu@google.com +zzyiwei@chromium.org diff --git a/cros_gralloc/cros_gralloc_buffer.cc b/cros_gralloc/cros_gralloc_buffer.cc index 2f4ceb0..e1af7a4 100644 --- a/cros_gralloc/cros_gralloc_buffer.cc +++ b/cros_gralloc/cros_gralloc_buffer.cc @@ -9,34 +9,110 @@ #include <assert.h> #include <sys/mman.h> -cros_gralloc_buffer::cros_gralloc_buffer(uint32_t id, struct bo *acquire_bo, - struct cros_gralloc_handle *acquire_handle, - int32_t reserved_region_fd, uint64_t reserved_region_size) - : id_(id), bo_(acquire_bo), hnd_(acquire_handle), refcount_(1), lockcount_(0), - reserved_region_fd_(reserved_region_fd), reserved_region_size_(reserved_region_size), - reserved_region_addr_(nullptr) +#include <cutils/native_handle.h> + +/*static*/ +std::unique_ptr<cros_gralloc_buffer> +cros_gralloc_buffer::create(struct bo *acquire_bo, + const struct cros_gralloc_handle *borrowed_handle) +{ + auto acquire_hnd = + reinterpret_cast<struct cros_gralloc_handle *>(native_handle_clone(borrowed_handle)); + if (!acquire_hnd) { + drv_log("Failed to create cros_gralloc_buffer: failed to clone handle.\n"); + return {}; + } + + std::unique_ptr<cros_gralloc_buffer> buffer( + new cros_gralloc_buffer(acquire_bo, acquire_hnd)); + if (!buffer) { + drv_log("Failed to create cros_gralloc_buffer: failed to allocate.\n"); + native_handle_close(acquire_hnd); + native_handle_delete(acquire_hnd); + return {}; + } + + return buffer; +} + +cros_gralloc_buffer::cros_gralloc_buffer(struct bo *acquire_bo, + struct cros_gralloc_handle *acquire_handle) + : bo_(acquire_bo), hnd_(acquire_handle) { assert(bo_); - num_planes_ = drv_bo_get_num_planes(bo_); - for (uint32_t plane = 0; plane < num_planes_; plane++) + assert(hnd_); + for (uint32_t plane = 0; plane < DRV_MAX_PLANES; plane++) lock_data_[plane] = nullptr; } cros_gralloc_buffer::~cros_gralloc_buffer() { drv_bo_destroy(bo_); - if (hnd_) { - native_handle_close(hnd_); - native_handle_delete(hnd_); - } if (reserved_region_addr_) { - munmap(reserved_region_addr_, reserved_region_size_); + munmap(reserved_region_addr_, hnd_->reserved_region_size); } + native_handle_close(hnd_); + native_handle_delete(hnd_); } uint32_t cros_gralloc_buffer::get_id() const { - return id_; + return hnd_->id; +} + +uint32_t cros_gralloc_buffer::get_width() const +{ + return hnd_->width; +} + +uint32_t cros_gralloc_buffer::get_height() const +{ + return hnd_->height; +} + +uint32_t cros_gralloc_buffer::get_format() const +{ + return hnd_->format; +} + +uint64_t cros_gralloc_buffer::get_format_modifier() const +{ + return hnd_->format_modifier; +} + +uint64_t cros_gralloc_buffer::get_total_size() const +{ + return hnd_->total_size; +} + +uint32_t cros_gralloc_buffer::get_num_planes() const +{ + return hnd_->num_planes; +} + +uint32_t cros_gralloc_buffer::get_plane_offset(uint32_t plane) const +{ + return hnd_->offsets[plane]; +} + +uint32_t cros_gralloc_buffer::get_plane_stride(uint32_t plane) const +{ + return hnd_->strides[plane]; +} + +uint32_t cros_gralloc_buffer::get_plane_size(uint32_t plane) const +{ + return hnd_->sizes[plane]; +} + +int32_t cros_gralloc_buffer::get_android_format() const +{ + return hnd_->droid_format; +} + +uint64_t cros_gralloc_buffer::get_android_usage() const +{ + return static_cast<uint64_t>(hnd_->usage); } int32_t cros_gralloc_buffer::increase_refcount() @@ -91,7 +167,7 @@ int32_t cros_gralloc_buffer::lock(const struct rectangle *rect, uint32_t map_fla } } - for (uint32_t plane = 0; plane < num_planes_; plane++) + for (uint32_t plane = 0; plane < hnd_->num_planes; plane++) addr[plane] = static_cast<uint8_t *>(vaddr) + drv_bo_get_plane_offset(bo_, plane); lockcount_++; @@ -148,16 +224,18 @@ int32_t cros_gralloc_buffer::flush() return 0; } -int32_t cros_gralloc_buffer::get_reserved_region(void **addr, uint64_t *size) +int32_t cros_gralloc_buffer::get_reserved_region(void **addr, uint64_t *size) const { - if (reserved_region_fd_ <= 0) { + int32_t reserved_region_fd = hnd_->fds[hnd_->num_planes]; + if (reserved_region_fd < 0) { drv_log("Buffer does not have reserved region.\n"); return -EINVAL; } if (!reserved_region_addr_) { - reserved_region_addr_ = mmap(nullptr, reserved_region_size_, PROT_WRITE | PROT_READ, - MAP_SHARED, reserved_region_fd_, 0); + reserved_region_addr_ = + mmap(nullptr, hnd_->reserved_region_size, PROT_WRITE | PROT_READ, MAP_SHARED, + reserved_region_fd, 0); if (reserved_region_addr_ == MAP_FAILED) { drv_log("Failed to mmap reserved region: %s.\n", strerror(errno)); return -errno; @@ -165,6 +243,6 @@ int32_t cros_gralloc_buffer::get_reserved_region(void **addr, uint64_t *size) } *addr = reserved_region_addr_; - *size = reserved_region_size_; + *size = hnd_->reserved_region_size; return 0; } diff --git a/cros_gralloc/cros_gralloc_buffer.h b/cros_gralloc/cros_gralloc_buffer.h index 9bc0ef0..21f8306 100644 --- a/cros_gralloc/cros_gralloc_buffer.h +++ b/cros_gralloc/cros_gralloc_buffer.h @@ -7,18 +7,30 @@ #ifndef CROS_GRALLOC_BUFFER_H #define CROS_GRALLOC_BUFFER_H -#include "../drv.h" +#include <memory> + #include "cros_gralloc_helpers.h" class cros_gralloc_buffer { public: - cros_gralloc_buffer(uint32_t id, struct bo *acquire_bo, - struct cros_gralloc_handle *acquire_handle, int32_t reserved_region_fd, - uint64_t reserved_region_size); + static std::unique_ptr<cros_gralloc_buffer> + create(struct bo *acquire_bo, const struct cros_gralloc_handle *borrowed_handle); + ~cros_gralloc_buffer(); uint32_t get_id() const; + uint32_t get_width() const; + uint32_t get_height() const; + uint32_t get_format() const; + uint64_t get_format_modifier() const; + uint64_t get_total_size() const; + uint32_t get_num_planes() const; + uint32_t get_plane_offset(uint32_t plane) const; + uint32_t get_plane_stride(uint32_t plane) const; + uint32_t get_plane_size(uint32_t plane) const; + int32_t get_android_format() const; + uint64_t get_android_usage() const; /* The new reference count is returned by both these functions. */ int32_t increase_refcount(); @@ -33,28 +45,27 @@ class cros_gralloc_buffer int32_t invalidate(); int32_t flush(); - int32_t get_reserved_region(void **reserved_region_addr, uint64_t *reserved_region_size); + int32_t get_reserved_region(void **reserved_region_addr, + uint64_t *reserved_region_size) const; private: + cros_gralloc_buffer(struct bo *acquire_bo, struct cros_gralloc_handle *acquire_handle); + cros_gralloc_buffer(cros_gralloc_buffer const &); cros_gralloc_buffer operator=(cros_gralloc_buffer const &); - uint32_t id_; struct bo *bo_; /* Note: this will be nullptr for imported/retained buffers. */ struct cros_gralloc_handle *hnd_; - int32_t refcount_; - int32_t lockcount_; - uint32_t num_planes_; + int32_t refcount_ = 1; + int32_t lockcount_ = 0; struct mapping *lock_data_[DRV_MAX_PLANES]; /* Optional additional shared memory region attached to some gralloc buffers. */ - int32_t reserved_region_fd_; - uint64_t reserved_region_size_; - void *reserved_region_addr_; + mutable void *reserved_region_addr_ = nullptr; }; #endif diff --git a/cros_gralloc/cros_gralloc_driver.cc b/cros_gralloc/cros_gralloc_driver.cc index f0c0392..46de30d 100644 --- a/cros_gralloc/cros_gralloc_driver.cc +++ b/cros_gralloc/cros_gralloc_driver.cc @@ -8,12 +8,11 @@ #include <cstdlib> #include <fcntl.h> +#include <hardware/gralloc.h> #include <sys/mman.h> #include <syscall.h> #include <xf86drm.h> -#include "../drv_priv.h" -#include "../helpers.h" #include "../util.h" // Constants taken from pipe_loader_drm.c in Mesa @@ -45,21 +44,32 @@ int memfd_create_wrapper(const char *name, unsigned int flags) return fd; } -cros_gralloc_driver::cros_gralloc_driver() : drv_(nullptr) +int memfd_create_reserved_region(const std::string &buffer_name, uint64_t reserved_region_size) { + const std::string reserved_region_name = buffer_name + " reserved region"; + + int reserved_region_fd = memfd_create_wrapper(reserved_region_name.c_str(), FD_CLOEXEC); + if (reserved_region_fd == -1) + return -errno; + + if (ftruncate(reserved_region_fd, reserved_region_size)) { + drv_log("Failed to set reserved region size: %s.\n", strerror(errno)); + return -errno; + } + + return reserved_region_fd; } -cros_gralloc_driver::~cros_gralloc_driver() +cros_gralloc_driver *cros_gralloc_driver::get_instance() { - buffers_.clear(); - handles_.clear(); + static cros_gralloc_driver s_instance; - if (drv_) { - int fd = drv_get_fd(drv_); - drv_destroy(drv_); - drv_ = nullptr; - close(fd); + if (!s_instance.is_initialized()) { + drv_log("Failed to initialize driver.\n"); + return nullptr; } + + return &s_instance; } static struct driver *init_try_node(int idx, char const *str) @@ -84,7 +94,7 @@ static struct driver *init_try_node(int idx, char const *str) return drv; } -int32_t cros_gralloc_driver::init() +static struct driver *init_try_nodes() { /* * Create a driver from render nodes first, then try card @@ -93,6 +103,7 @@ int32_t cros_gralloc_driver::init() * TODO(gsingh): Enable render nodes on udl/evdi. */ + struct driver *drv; char const *render_nodes_fmt = "%s/renderD%d"; char const *card_nodes_fmt = "%s/card%d"; uint32_t num_nodes = DRM_NUM_NODES; @@ -103,84 +114,132 @@ int32_t cros_gralloc_driver::init() // Try render nodes... for (uint32_t i = min_render_node; i < max_render_node; i++) { - drv_ = init_try_node(i, render_nodes_fmt); - if (drv_) - return 0; + drv = init_try_node(i, render_nodes_fmt); + if (drv) + return drv; } // Try card nodes... for vkms mostly. for (uint32_t i = min_card_node; i < max_card_node; i++) { - drv_ = init_try_node(i, card_nodes_fmt); - if (drv_) - return 0; + drv = init_try_node(i, card_nodes_fmt); + if (drv) + return drv; } - return -ENODEV; + return nullptr; } -bool cros_gralloc_driver::is_supported(const struct cros_gralloc_buffer_descriptor *descriptor) +static void drv_destroy_and_close(struct driver *drv) +{ + int fd = drv_get_fd(drv); + drv_destroy(drv); + close(fd); +} + +cros_gralloc_driver::cros_gralloc_driver() : drv_(init_try_nodes(), drv_destroy_and_close) { - struct combination *combo; - uint32_t resolved_format; - resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags); - combo = drv_get_combination(drv_, resolved_format, descriptor->use_flags); - return (combo != nullptr); } -int32_t create_reserved_region(const std::string &buffer_name, uint64_t reserved_region_size) +cros_gralloc_driver::~cros_gralloc_driver() { - std::string reserved_region_name = buffer_name + " reserved region"; + buffers_.clear(); + handles_.clear(); +} - int32_t reserved_region_fd = memfd_create_wrapper(reserved_region_name.c_str(), FD_CLOEXEC); - if (reserved_region_fd == -1) - return -errno; +bool cros_gralloc_driver::is_initialized() +{ + return drv_ != nullptr; +} - if (ftruncate(reserved_region_fd, reserved_region_size)) { - drv_log("Failed to set reserved region size: %s.\n", strerror(errno)); - return -errno; +bool cros_gralloc_driver::get_resolved_format_and_use_flags( + const struct cros_gralloc_buffer_descriptor *descriptor, uint32_t *out_format, + uint64_t *out_use_flags) +{ + uint32_t resolved_format; + uint64_t resolved_use_flags; + struct combination *combo; + + drv_resolve_format_and_use_flags(drv_.get(), descriptor->drm_format, descriptor->use_flags, + &resolved_format, &resolved_use_flags); + + combo = drv_get_combination(drv_.get(), resolved_format, resolved_use_flags); + if (!combo && (descriptor->droid_usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) && + descriptor->droid_format != HAL_PIXEL_FORMAT_YCbCr_420_888) { + // Unmask BO_USE_HW_VIDEO_ENCODER for other formats. They are mostly + // intermediate formats not passed directly to the encoder (e.g. + // camera). YV12 is passed to the encoder component, but it is converted + // to YCbCr_420_888 before being passed to the hw encoder. + resolved_use_flags &= ~BO_USE_HW_VIDEO_ENCODER; + combo = drv_get_combination(drv_.get(), resolved_format, resolved_use_flags); + } + if (!combo && (descriptor->droid_usage & BUFFER_USAGE_FRONT_RENDERING)) { + resolved_use_flags &= ~BO_USE_FRONT_RENDERING; + resolved_use_flags |= BO_USE_LINEAR; + combo = drv_get_combination(drv_.get(), resolved_format, resolved_use_flags); } + if (!combo) + return false; - return reserved_region_fd; + *out_format = resolved_format; + *out_use_flags = resolved_use_flags; + return true; +} + +bool cros_gralloc_driver::is_supported(const struct cros_gralloc_buffer_descriptor *descriptor) +{ + uint32_t resolved_format; + uint64_t resolved_use_flags; + uint32_t max_texture_size = drv_get_max_texture_2d_size(drv_.get()); + if (!get_resolved_format_and_use_flags(descriptor, &resolved_format, &resolved_use_flags)) + return false; + + // Allow blob buffers to go beyond the limit. + if (descriptor->droid_format == HAL_PIXEL_FORMAT_BLOB) + return true; + + return descriptor->width <= max_texture_size && descriptor->height <= max_texture_size; } -void cros_gralloc_driver::emplace_buffer(struct bo *bo, struct cros_gralloc_handle *hnd) +int cros_gralloc_driver::create_reserved_region(const std::string &buffer_name, + uint64_t reserved_region_size) { - auto buffer = new cros_gralloc_buffer(hnd->id, bo, hnd, hnd->fds[hnd->num_planes], - hnd->reserved_region_size); + int ret; - std::lock_guard<std::mutex> lock(mutex_); - buffers_.emplace(hnd->id, buffer); - handles_.emplace(hnd, std::make_pair(buffer, 1)); +#if ANDROID_API_LEVEL >= 31 && defined(HAS_DMABUF_SYSTEM_HEAP) + ret = allocator_.Alloc(kDmabufSystemHeapName, reserved_region_size); + if (ret >= 0) + return ret; +#endif + + ret = memfd_create_reserved_region(buffer_name, reserved_region_size); + if (ret >= 0) + return ret; + + drv_log("Failed to create_reserved_region.\n"); + return -1; } int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descriptor *descriptor, - buffer_handle_t *out_handle) + native_handle_t **out_handle) { int ret = 0; size_t num_planes; size_t num_fds; size_t num_ints; - size_t num_bytes; uint32_t resolved_format; uint32_t bytes_per_pixel; - uint64_t use_flags; - char *name; + uint64_t resolved_use_flags; struct bo *bo; struct cros_gralloc_handle *hnd; + std::unique_ptr<cros_gralloc_buffer> buffer; - resolved_format = drv_resolve_format(drv_, descriptor->drm_format, descriptor->use_flags); - use_flags = descriptor->use_flags; - - /* - * This unmask is a backup in the case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED is resolved - * to non-YUV formats. - */ - if (descriptor->drm_format == DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED && - (resolved_format == DRM_FORMAT_XBGR8888 || resolved_format == DRM_FORMAT_ABGR8888)) { - use_flags &= ~BO_USE_HW_VIDEO_ENCODER; + if (!get_resolved_format_and_use_flags(descriptor, &resolved_format, &resolved_use_flags)) { + drv_log("Failed to resolve format and use_flags.\n"); + return -EINVAL; } - bo = drv_bo_create(drv_, descriptor->width, descriptor->height, resolved_format, use_flags); + bo = drv_bo_create(drv_.get(), descriptor->width, descriptor->height, resolved_format, + resolved_use_flags); if (!bo) { drv_log("Failed to create bo.\n"); return -errno; @@ -202,14 +261,8 @@ int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descripto if (descriptor->reserved_region_size > 0) num_fds += 1; - num_bytes = sizeof(struct cros_gralloc_handle); - num_bytes += (descriptor->name.size() + 1); - /* - * Ensure that the total number of bytes is a multiple of sizeof(int) as - * native_handle_clone() copies data based on hnd->base.numInts. - */ - num_bytes = ALIGN(num_bytes, sizeof(int)); - num_ints = ((num_bytes - sizeof(native_handle_t)) / sizeof(int)) - num_fds; + num_ints = ((sizeof(struct cros_gralloc_handle) - sizeof(native_handle_t)) / sizeof(int)) - + num_fds; hnd = reinterpret_cast<struct cros_gralloc_handle *>(native_handle_create(num_fds, num_ints)); @@ -243,23 +296,35 @@ int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descripto hnd->width = drv_bo_get_width(bo); hnd->height = drv_bo_get_height(bo); hnd->format = drv_bo_get_format(bo); - hnd->tiling = bo->meta.tiling; + hnd->tiling = drv_bo_get_tiling(bo); hnd->format_modifier = drv_bo_get_format_modifier(bo); - hnd->use_flags = descriptor->use_flags; + hnd->use_flags = drv_bo_get_use_flags(bo); bytes_per_pixel = drv_bytes_per_pixel_from_format(hnd->format, 0); hnd->pixel_stride = DIV_ROUND_UP(hnd->strides[0], bytes_per_pixel); hnd->magic = cros_gralloc_magic; hnd->droid_format = descriptor->droid_format; hnd->usage = descriptor->droid_usage; - hnd->total_size = descriptor->reserved_region_size + bo->meta.total_size; - hnd->name_offset = handle_data_size; + hnd->total_size = descriptor->reserved_region_size + drv_bo_get_total_size(bo); + + buffer = cros_gralloc_buffer::create(bo, hnd); + if (!buffer) { + drv_log("Failed to allocate: failed to create cros_gralloc_buffer.\n"); + ret = -1; + goto destroy_hnd; + } - name = (char *)(&hnd->data[hnd->name_offset]); - snprintf(name, descriptor->name.size() + 1, "%s", descriptor->name.c_str()); + { + std::lock_guard<std::mutex> lock(mutex_); - emplace_buffer(bo, hnd); + struct cros_gralloc_imported_handle_info hnd_info = { + .buffer = buffer.get(), + .refcount = 1, + }; + handles_.emplace(hnd, hnd_info); + buffers_.emplace(hnd->id, std::move(buffer)); + } - *out_handle = reinterpret_cast<buffer_handle_t>(hnd); + *out_handle = hnd; return 0; destroy_hnd: @@ -273,7 +338,6 @@ destroy_bo: int32_t cros_gralloc_driver::retain(buffer_handle_t handle) { - uint32_t id; std::lock_guard<std::mutex> lock(mutex_); auto hnd = cros_gralloc_convert_handle(handle); @@ -282,43 +346,65 @@ int32_t cros_gralloc_driver::retain(buffer_handle_t handle) return -EINVAL; } - auto buffer = get_buffer(hnd); - if (buffer) { - handles_[hnd].second++; - buffer->increase_refcount(); + auto hnd_it = handles_.find(hnd); + if (hnd_it != handles_.end()) { + // The underlying buffer (as multiple handles can refer to the same buffer) + // has already been imported into this process and the given handle has + // already been registered in this process. Increase both the buffer and + // handle reference count. + auto &hnd_info = hnd_it->second; + + hnd_info.buffer->increase_refcount(); + hnd_info.refcount++; + return 0; } - id = hnd->id; + uint32_t id = hnd->id; + + cros_gralloc_buffer *buffer = nullptr; - if (buffers_.count(id)) { - buffer = buffers_[id]; + auto buffer_it = buffers_.find(id); + if (buffer_it != buffers_.end()) { + // The underlying buffer (as multiple handles can refer to the same buffer) + // has already been imported into this process but the given handle has not + // yet been registered. Increase the buffer reference count (here) and start + // to track the handle (below). + buffer = buffer_it->second.get(); buffer->increase_refcount(); } else { - struct bo *bo; - struct drv_import_fd_data data; - data.format = hnd->format; - data.tiling = hnd->tiling; - - data.width = hnd->width; - data.height = hnd->height; - data.use_flags = hnd->use_flags; - + // The underlying buffer has not yet been imported into this process. Import + // and start to track the buffer (here) and start to track the handle (below). + struct drv_import_fd_data data = { + .format_modifier = hnd->format_modifier, + .width = hnd->width, + .height = hnd->height, + .format = hnd->format, + .tiling = hnd->tiling, + .use_flags = hnd->use_flags, + }; memcpy(data.fds, hnd->fds, sizeof(data.fds)); memcpy(data.strides, hnd->strides, sizeof(data.strides)); memcpy(data.offsets, hnd->offsets, sizeof(data.offsets)); - data.format_modifier = hnd->format_modifier; - bo = drv_bo_import(drv_, &data); + struct bo *bo = drv_bo_import(drv_.get(), &data); if (!bo) return -EFAULT; - buffer = new cros_gralloc_buffer(id, bo, nullptr, hnd->fds[hnd->num_planes], - hnd->reserved_region_size); - buffers_.emplace(id, buffer); + auto scoped_buffer = cros_gralloc_buffer::create(bo, hnd); + if (!scoped_buffer) { + drv_log("Failed to import: failed to create cros_gralloc_buffer.\n"); + return -1; + } + buffer = scoped_buffer.get(); + buffers_.emplace(id, std::move(scoped_buffer)); } - handles_.emplace(hnd, std::make_pair(buffer, 1)); + struct cros_gralloc_imported_handle_info hnd_info = { + .buffer = buffer, + .refcount = 1, + }; + handles_.emplace(hnd, hnd_info); return 0; } @@ -334,16 +420,15 @@ int32_t cros_gralloc_driver::release(buffer_handle_t handle) auto buffer = get_buffer(hnd); if (!buffer) { - drv_log("Invalid Reference.\n"); + drv_log("Invalid reference (release() called on unregistered handle).\n"); return -EINVAL; } - if (!--handles_[hnd].second) + if (!--handles_[hnd].refcount) handles_.erase(hnd); if (buffer->decrease_refcount() == 0) { buffers_.erase(buffer->get_id()); - delete buffer; } return 0; @@ -358,6 +443,7 @@ int32_t cros_gralloc_driver::lock(buffer_handle_t handle, int32_t acquire_fence, return ret; std::lock_guard<std::mutex> lock(mutex_); + auto hnd = cros_gralloc_convert_handle(handle); if (!hnd) { drv_log("Invalid handle.\n"); @@ -366,7 +452,7 @@ int32_t cros_gralloc_driver::lock(buffer_handle_t handle, int32_t acquire_fence, auto buffer = get_buffer(hnd); if (!buffer) { - drv_log("Invalid Reference.\n"); + drv_log("Invalid reference (lock() called on unregistered handle).\n"); return -EINVAL; } @@ -385,7 +471,7 @@ int32_t cros_gralloc_driver::unlock(buffer_handle_t handle, int32_t *release_fen auto buffer = get_buffer(hnd); if (!buffer) { - drv_log("Invalid Reference.\n"); + drv_log("Invalid reference (unlock() called on unregistered handle).\n"); return -EINVAL; } @@ -411,7 +497,7 @@ int32_t cros_gralloc_driver::invalidate(buffer_handle_t handle) auto buffer = get_buffer(hnd); if (!buffer) { - drv_log("Invalid Reference.\n"); + drv_log("Invalid reference (invalidate() called on unregistered handle).\n"); return -EINVAL; } @@ -430,7 +516,7 @@ int32_t cros_gralloc_driver::flush(buffer_handle_t handle, int32_t *release_fenc auto buffer = get_buffer(hnd); if (!buffer) { - drv_log("Invalid Reference.\n"); + drv_log("Invalid reference (flush() called on unregistered handle).\n"); return -EINVAL; } @@ -456,7 +542,7 @@ int32_t cros_gralloc_driver::get_backing_store(buffer_handle_t handle, uint64_t auto buffer = get_buffer(hnd); if (!buffer) { - drv_log("Invalid Reference.\n"); + drv_log("Invalid reference (get_backing_store() called on unregistered handle).\n"); return -EINVAL; } @@ -478,7 +564,7 @@ int32_t cros_gralloc_driver::resource_info(buffer_handle_t handle, uint32_t stri auto buffer = get_buffer(hnd); if (!buffer) { - drv_log("Invalid Reference.\n"); + drv_log("Invalid reference (resource_info() called on unregistered handle).\n"); return -EINVAL; } @@ -499,32 +585,53 @@ int32_t cros_gralloc_driver::get_reserved_region(buffer_handle_t handle, auto buffer = get_buffer(hnd); if (!buffer) { - drv_log("Invalid Reference.\n"); + drv_log( + "Invalid reference (get_reserved_region() called on unregistered handle).\n"); return -EINVAL; } return buffer->get_reserved_region(reserved_region_addr, reserved_region_size); } -uint32_t cros_gralloc_driver::get_resolved_drm_format(uint32_t drm_format, uint64_t usage) +uint32_t cros_gralloc_driver::get_resolved_drm_format(uint32_t drm_format, uint64_t use_flags) { - return drv_resolve_format(drv_, drm_format, usage); + uint32_t resolved_format; + uint64_t resolved_use_flags; + + drv_resolve_format_and_use_flags(drv_.get(), drm_format, use_flags, &resolved_format, + &resolved_use_flags); + + return resolved_format; } cros_gralloc_buffer *cros_gralloc_driver::get_buffer(cros_gralloc_handle_t hnd) { /* Assumes driver mutex is held. */ if (handles_.count(hnd)) - return handles_[hnd].first; + return handles_[hnd].buffer; return nullptr; } -void cros_gralloc_driver::for_each_handle( - const std::function<void(cros_gralloc_handle_t)> &function) +void cros_gralloc_driver::with_buffer(cros_gralloc_handle_t hnd, + const std::function<void(cros_gralloc_buffer *)> &function) +{ + std::lock_guard<std::mutex> lock(mutex_); + + auto buffer = get_buffer(hnd); + if (!buffer) { + drv_log("Invalid reference (with_buffer() called on unregistered handle).\n"); + return; + } + + function(buffer); +} + +void cros_gralloc_driver::with_each_buffer( + const std::function<void(cros_gralloc_buffer *)> &function) { std::lock_guard<std::mutex> lock(mutex_); - for (const auto &pair : handles_) - function(pair.first); + for (const auto &pair : buffers_) + function(pair.second.get()); } diff --git a/cros_gralloc/cros_gralloc_driver.h b/cros_gralloc/cros_gralloc_driver.h index ef9e21f..5678b76 100644 --- a/cros_gralloc/cros_gralloc_driver.h +++ b/cros_gralloc/cros_gralloc_driver.h @@ -10,19 +10,22 @@ #include "cros_gralloc_buffer.h" #include <functional> +#include <memory> #include <mutex> +#include <string> #include <unordered_map> +#if ANDROID_API_LEVEL >= 31 && defined(HAS_DMABUF_SYSTEM_HEAP) +#include <BufferAllocator/BufferAllocator.h> +#endif + class cros_gralloc_driver { public: - cros_gralloc_driver(); - ~cros_gralloc_driver(); - - int32_t init(); + static cros_gralloc_driver *get_instance(); bool is_supported(const struct cros_gralloc_buffer_descriptor *descriptor); int32_t allocate(const struct cros_gralloc_buffer_descriptor *descriptor, - buffer_handle_t *out_handle); + native_handle_t **out_handle); int32_t retain(buffer_handle_t handle); int32_t release(buffer_handle_t handle); @@ -42,21 +45,44 @@ class cros_gralloc_driver int32_t get_reserved_region(buffer_handle_t handle, void **reserved_region_addr, uint64_t *reserved_region_size); - uint32_t get_resolved_drm_format(uint32_t drm_format, uint64_t usage); + uint32_t get_resolved_drm_format(uint32_t drm_format, uint64_t use_flags); - void for_each_handle(const std::function<void(cros_gralloc_handle_t)> &function); + void with_buffer(cros_gralloc_handle_t hnd, + const std::function<void(cros_gralloc_buffer *)> &function); + void with_each_buffer(const std::function<void(cros_gralloc_buffer *)> &function); private: - cros_gralloc_driver(cros_gralloc_driver const &); - cros_gralloc_driver operator=(cros_gralloc_driver const &); + cros_gralloc_driver(); + ~cros_gralloc_driver(); + bool is_initialized(); cros_gralloc_buffer *get_buffer(cros_gralloc_handle_t hnd); - void emplace_buffer(struct bo *bo, struct cros_gralloc_handle *hnd); + bool + get_resolved_format_and_use_flags(const struct cros_gralloc_buffer_descriptor *descriptor, + uint32_t *out_format, uint64_t *out_use_flags); + + int create_reserved_region(const std::string &buffer_name, uint64_t reserved_region_size); + +#if ANDROID_API_LEVEL >= 31 && defined(HAS_DMABUF_SYSTEM_HEAP) + /* For allocating cros_gralloc_buffer reserved regions for metadata. */ + BufferAllocator allocator_; +#endif + + std::unique_ptr<struct driver, void (*)(struct driver *)> drv_; + + struct cros_gralloc_imported_handle_info { + /* + * The underlying buffer for referred to by this handle (as multiple handles can + * refer to the same buffer). + */ + cros_gralloc_buffer *buffer = nullptr; + + /* The handle's refcount as a handle can be imported multiple times.*/ + int32_t refcount = 1; + }; - struct driver *drv_; std::mutex mutex_; - std::unordered_map<uint32_t, cros_gralloc_buffer *> buffers_; - std::unordered_map<cros_gralloc_handle_t, std::pair<cros_gralloc_buffer *, int32_t>> - handles_; + std::unordered_map<uint32_t, std::unique_ptr<cros_gralloc_buffer>> buffers_; + std::unordered_map<cros_gralloc_handle_t, cros_gralloc_imported_handle_info> handles_; }; #endif diff --git a/cros_gralloc/cros_gralloc_handle.h b/cros_gralloc/cros_gralloc_handle.h index 2b70d4b..2d0e1ac 100644 --- a/cros_gralloc/cros_gralloc_handle.h +++ b/cros_gralloc/cros_gralloc_handle.h @@ -40,10 +40,6 @@ struct cros_gralloc_handle : public native_handle_t { uint32_t num_planes; uint64_t reserved_region_size; uint64_t total_size; /* Total allocation size */ - /* - * Name is a null terminated char array located at handle->base.data[handle->name_offset]. - */ - uint32_t name_offset; } __attribute__((packed)); typedef const struct cros_gralloc_handle *cros_gralloc_handle_t; diff --git a/cros_gralloc/cros_gralloc_helpers.cc b/cros_gralloc/cros_gralloc_helpers.cc index 4319936..90cd5c4 100644 --- a/cros_gralloc/cros_gralloc_helpers.cc +++ b/cros_gralloc/cros_gralloc_helpers.cc @@ -6,8 +6,18 @@ #include "cros_gralloc_helpers.h" +#include <hardware/gralloc.h> #include <sync/sync.h> +/* Define to match AIDL BufferUsage::VIDEO_DECODER. */ +#define BUFFER_USAGE_VIDEO_DECODER (1 << 22) + +/* Define to match AIDL BufferUsage::SENSOR_DIRECT_DATA. */ +#define BUFFER_USAGE_SENSOR_DIRECT_DATA (1 << 23) + +/* Define to match AIDL BufferUsage::GPU_DATA_BUFFER. */ +#define BUFFER_USAGE_GPU_DATA_BUFFER (1 << 24) + uint32_t cros_gralloc_convert_format(int format) { /* @@ -16,24 +26,27 @@ uint32_t cros_gralloc_convert_format(int format) */ switch (format) { - case HAL_PIXEL_FORMAT_BGRA_8888: - return DRM_FORMAT_ARGB8888; - case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: - return DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED; - case HAL_PIXEL_FORMAT_RAW16: - return DRM_FORMAT_R16; - case HAL_PIXEL_FORMAT_RGB_565: - return DRM_FORMAT_RGB565; - case HAL_PIXEL_FORMAT_RGB_888: - return DRM_FORMAT_BGR888; case HAL_PIXEL_FORMAT_RGBA_8888: return DRM_FORMAT_ABGR8888; case HAL_PIXEL_FORMAT_RGBX_8888: return DRM_FORMAT_XBGR8888; - case HAL_PIXEL_FORMAT_YCbCr_420_888: - return DRM_FORMAT_FLEX_YCbCr_420_888; - case HAL_PIXEL_FORMAT_YV12: - return DRM_FORMAT_YVU420_ANDROID; + case HAL_PIXEL_FORMAT_RGB_888: + return DRM_FORMAT_BGR888; + /* + * Confusingly, HAL_PIXEL_FORMAT_RGB_565 is defined as: + * + * "16-bit packed format that has 5-bit R, 6-bit G, and 5-bit B components, in that + * order, from the most-sigfinicant bits to the least-significant bits." + * + * so the order of the components is intentionally not flipped between the pixel + * format and the DRM format. + */ + case HAL_PIXEL_FORMAT_RGB_565: + return DRM_FORMAT_RGB565; + case HAL_PIXEL_FORMAT_BGRA_8888: + return DRM_FORMAT_ARGB8888; + case HAL_PIXEL_FORMAT_RAW16: + return DRM_FORMAT_R16; /* * Choose DRM_FORMAT_R8 because <system/graphics.h> requires the buffers * with a format HAL_PIXEL_FORMAT_BLOB have a height of 1, and width @@ -41,17 +54,99 @@ uint32_t cros_gralloc_convert_format(int format) */ case HAL_PIXEL_FORMAT_BLOB: return DRM_FORMAT_R8; -#if ANDROID_VERSION >= 0x0a00 - case HAL_PIXEL_FORMAT_RGBA_1010102: - return DRM_FORMAT_ABGR2101010; + case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: + return DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED; + case HAL_PIXEL_FORMAT_YCbCr_420_888: + return DRM_FORMAT_FLEX_YCbCr_420_888; + case HAL_PIXEL_FORMAT_Y8: + return DRM_FORMAT_R8; + case HAL_PIXEL_FORMAT_Y16: + return DRM_FORMAT_R16; + case HAL_PIXEL_FORMAT_YV12: + return DRM_FORMAT_YVU420_ANDROID; +#if ANDROID_API_LEVEL >= 29 case HAL_PIXEL_FORMAT_RGBA_FP16: return DRM_FORMAT_ABGR16161616F; + case HAL_PIXEL_FORMAT_RGBA_1010102: + return DRM_FORMAT_ABGR2101010; +#endif +#if ANDROID_API_LEVEL >= 30 + case HAL_PIXEL_FORMAT_YCBCR_P010: + return DRM_FORMAT_P010; #endif } return DRM_FORMAT_NONE; } +static inline void handle_usage(uint64_t *gralloc_usage, uint64_t gralloc_mask, + uint64_t *bo_use_flags, uint64_t bo_mask) +{ + if ((*gralloc_usage) & gralloc_mask) { + (*gralloc_usage) &= ~gralloc_mask; + (*bo_use_flags) |= bo_mask; + } +} + +uint64_t cros_gralloc_convert_usage(uint64_t usage) +{ + uint64_t use_flags = BO_USE_NONE; + + /* + * GRALLOC_USAGE_SW_READ_OFTEN contains GRALLOC_USAGE_SW_READ_RARELY, thus OFTEN must be + * handled first. The same applies to GRALLOC_USAGE_SW_WRITE_OFTEN. + */ + handle_usage(&usage, GRALLOC_USAGE_SW_READ_OFTEN, &use_flags, BO_USE_SW_READ_OFTEN); + handle_usage(&usage, GRALLOC_USAGE_SW_READ_RARELY, &use_flags, BO_USE_SW_READ_RARELY); + handle_usage(&usage, GRALLOC_USAGE_SW_WRITE_OFTEN, &use_flags, BO_USE_SW_WRITE_OFTEN); + handle_usage(&usage, GRALLOC_USAGE_SW_WRITE_RARELY, &use_flags, BO_USE_SW_WRITE_RARELY); + handle_usage(&usage, GRALLOC_USAGE_HW_TEXTURE, &use_flags, BO_USE_TEXTURE); + handle_usage(&usage, GRALLOC_USAGE_HW_RENDER, &use_flags, BO_USE_RENDERING); + handle_usage(&usage, GRALLOC_USAGE_HW_2D, &use_flags, BO_USE_RENDERING); + /* HWC wants to use display hardware, but can defer to OpenGL. */ + handle_usage(&usage, GRALLOC_USAGE_HW_COMPOSER, &use_flags, + BO_USE_SCANOUT | BO_USE_TEXTURE); + handle_usage(&usage, GRALLOC_USAGE_HW_FB, &use_flags, BO_USE_NONE); + /* + * This flag potentially covers external display for the normal drivers (i915/rockchip) and + * usb monitors (evdi/udl). It's complicated so ignore it. + */ + handle_usage(&usage, GRALLOC_USAGE_EXTERNAL_DISP, &use_flags, BO_USE_NONE); + /* Map PROTECTED to linear until real HW protection is available on Android. */ + handle_usage(&usage, GRALLOC_USAGE_PROTECTED, &use_flags, BO_USE_LINEAR); + handle_usage(&usage, GRALLOC_USAGE_CURSOR, &use_flags, BO_USE_NONE); + /* HACK: See b/30054495 for BO_USE_SW_READ_OFTEN. */ + handle_usage(&usage, GRALLOC_USAGE_HW_VIDEO_ENCODER, &use_flags, + BO_USE_HW_VIDEO_ENCODER | BO_USE_SW_READ_OFTEN); + handle_usage(&usage, GRALLOC_USAGE_HW_CAMERA_WRITE, &use_flags, BO_USE_CAMERA_WRITE); + handle_usage(&usage, GRALLOC_USAGE_HW_CAMERA_READ, &use_flags, BO_USE_CAMERA_READ); + handle_usage(&usage, GRALLOC_USAGE_RENDERSCRIPT, &use_flags, BO_USE_RENDERSCRIPT); + handle_usage(&usage, BUFFER_USAGE_VIDEO_DECODER, &use_flags, BO_USE_HW_VIDEO_DECODER); + handle_usage(&usage, BUFFER_USAGE_SENSOR_DIRECT_DATA, &use_flags, + BO_USE_SENSOR_DIRECT_DATA); + handle_usage(&usage, BUFFER_USAGE_GPU_DATA_BUFFER, &use_flags, BO_USE_GPU_DATA_BUFFER); + handle_usage(&usage, BUFFER_USAGE_FRONT_RENDERING, &use_flags, BO_USE_FRONT_RENDERING); + + if (usage) { + drv_log("Unhandled gralloc usage: %llx\n", (unsigned long long)usage); + return BO_USE_NONE; + } + + return use_flags; +} + +uint32_t cros_gralloc_convert_map_usage(uint64_t usage) +{ + uint32_t map_flags = BO_MAP_NONE; + + if (usage & GRALLOC_USAGE_SW_READ_MASK) + map_flags |= BO_MAP_READ; + if (usage & GRALLOC_USAGE_SW_WRITE_MASK) + map_flags |= BO_MAP_WRITE; + + return map_flags; +} + cros_gralloc_handle_t cros_gralloc_convert_handle(buffer_handle_t handle) { auto hnd = reinterpret_cast<cros_gralloc_handle_t>(handle); diff --git a/cros_gralloc/cros_gralloc_helpers.h b/cros_gralloc/cros_gralloc_helpers.h index a43833d..312d2f7 100644 --- a/cros_gralloc/cros_gralloc_helpers.h +++ b/cros_gralloc/cros_gralloc_helpers.h @@ -9,17 +9,38 @@ #include "../drv.h" #include "cros_gralloc_handle.h" -#include "cros_gralloc_types.h" #include <system/graphics.h> #include <system/window.h> +#include <string> + +// Reserve the GRALLOC_USAGE_PRIVATE_0 bit from hardware/gralloc.h for buffers +// used for front rendering. minigbm backend later decides to use +// BO_USE_FRONT_RENDERING or BO_USE_LINEAR upon buffer allocaton. +#define BUFFER_USAGE_FRONT_RENDERING (1U << 28) + +struct cros_gralloc_buffer_descriptor { + uint32_t width; + uint32_t height; + int32_t droid_format; + int32_t droid_usage; + uint32_t drm_format; + uint64_t use_flags; + uint64_t reserved_region_size; + std::string name; +}; + constexpr uint32_t cros_gralloc_magic = 0xABCDDCBA; constexpr uint32_t handle_data_size = ((sizeof(struct cros_gralloc_handle) - offsetof(cros_gralloc_handle, fds[0])) / sizeof(int)); uint32_t cros_gralloc_convert_format(int32_t format); +uint64_t cros_gralloc_convert_usage(uint64_t usage); + +uint32_t cros_gralloc_convert_map_usage(uint64_t usage); + cros_gralloc_handle_t cros_gralloc_convert_handle(buffer_handle_t handle); int32_t cros_gralloc_sync_wait(int32_t fence, bool close_fence); diff --git a/cros_gralloc/cros_gralloc_types.h b/cros_gralloc/cros_gralloc_types.h deleted file mode 100644 index 22f58e2..0000000 --- a/cros_gralloc/cros_gralloc_types.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2017 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef CROS_GRALLOC_TYPES_H -#define CROS_GRALLOC_TYPES_H - -#include <string> - -struct cros_gralloc_buffer_descriptor { - uint32_t width; - uint32_t height; - int32_t droid_format; - int32_t droid_usage; - uint32_t drm_format; - uint64_t use_flags; - uint64_t reserved_region_size; - std::string name; -}; - -#endif diff --git a/cros_gralloc/gralloc0/gralloc0.cc b/cros_gralloc/gralloc0/gralloc0.cc index 5899d5a..ce62521 100644 --- a/cros_gralloc/gralloc0/gralloc0.cc +++ b/cros_gralloc/gralloc0/gralloc0.cc @@ -4,18 +4,18 @@ * found in the LICENSE file. */ -#include "../../helpers.h" #include "../../util.h" #include "../cros_gralloc_driver.h" #include <cassert> +#include <cutils/native_handle.h> #include <hardware/gralloc.h> #include <memory.h> struct gralloc0_module { gralloc_module_t base; std::unique_ptr<alloc_device_t> alloc; - std::unique_ptr<cros_gralloc_driver> driver; + cros_gralloc_driver *driver; bool initialized; std::mutex initialization_mutex; }; @@ -61,93 +61,17 @@ enum { }; // clang-format on -// Gralloc0 doesn't define a video decoder flag. However, the IAllocator gralloc0 -// passthrough gives the low 32-bits of the BufferUsage flags to gralloc0 in their -// entirety, so we can detect the video decoder flag passed by IAllocator clients. -#define BUFFER_USAGE_VIDEO_DECODER (1 << 22) - -// Reserve the GRALLOC_USAGE_PRIVATE_0 bit for buffers used for front rendering. -// minigbm backend later decides to use BO_USE_FRONT_RENDERING or BO_USE_LINEAR -// upon buffer allocaton. -#define BUFFER_USAGE_FRONT_RENDERING GRALLOC_USAGE_PRIVATE_0 - -static uint64_t gralloc0_convert_usage(int usage) -{ - uint64_t use_flags = BO_USE_NONE; - - if (usage & GRALLOC_USAGE_CURSOR) - use_flags |= BO_USE_NONE; - if ((usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_RARELY) - use_flags |= BO_USE_SW_READ_RARELY; - if ((usage & GRALLOC_USAGE_SW_READ_MASK) == GRALLOC_USAGE_SW_READ_OFTEN) - use_flags |= BO_USE_SW_READ_OFTEN; - if ((usage & GRALLOC_USAGE_SW_WRITE_MASK) == GRALLOC_USAGE_SW_WRITE_RARELY) - use_flags |= BO_USE_SW_WRITE_RARELY; - if ((usage & GRALLOC_USAGE_SW_WRITE_MASK) == GRALLOC_USAGE_SW_WRITE_OFTEN) - use_flags |= BO_USE_SW_WRITE_OFTEN; - if (usage & GRALLOC_USAGE_HW_TEXTURE) - use_flags |= BO_USE_TEXTURE; - if (usage & GRALLOC_USAGE_HW_RENDER) - use_flags |= BO_USE_RENDERING; - if (usage & GRALLOC_USAGE_HW_2D) - use_flags |= BO_USE_RENDERING; - if (usage & GRALLOC_USAGE_HW_COMPOSER) - /* HWC wants to use display hardware, but can defer to OpenGL. */ - use_flags |= BO_USE_SCANOUT | BO_USE_TEXTURE; - if (usage & GRALLOC_USAGE_HW_FB) - use_flags |= BO_USE_NONE; - if (usage & GRALLOC_USAGE_EXTERNAL_DISP) - /* - * This flag potentially covers external display for the normal drivers (i915, - * rockchip) and usb monitors (evdi/udl). It's complicated so ignore it. - * */ - use_flags |= BO_USE_NONE; - /* Map this flag to linear until real HW protection is available on Android. */ - if (usage & GRALLOC_USAGE_PROTECTED) - use_flags |= BO_USE_LINEAR; - if (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) { - use_flags |= BO_USE_HW_VIDEO_ENCODER; - /*HACK: See b/30054495 */ - use_flags |= BO_USE_SW_READ_OFTEN; - } - if (usage & GRALLOC_USAGE_HW_CAMERA_WRITE) - use_flags |= BO_USE_CAMERA_WRITE; - if (usage & GRALLOC_USAGE_HW_CAMERA_READ) - use_flags |= BO_USE_CAMERA_READ; - if (usage & GRALLOC_USAGE_RENDERSCRIPT) - use_flags |= BO_USE_RENDERSCRIPT; - if (usage & BUFFER_USAGE_VIDEO_DECODER) - use_flags |= BO_USE_HW_VIDEO_DECODER; - if (usage & BUFFER_USAGE_FRONT_RENDERING) - use_flags |= BO_USE_FRONT_RENDERING; - - return use_flags; -} - -static uint32_t gralloc0_convert_map_usage(int map_usage) -{ - uint32_t map_flags = BO_MAP_NONE; - - if (map_usage & GRALLOC_USAGE_SW_READ_MASK) - map_flags |= BO_MAP_READ; - if (map_usage & GRALLOC_USAGE_SW_WRITE_MASK) - map_flags |= BO_MAP_WRITE; - - return map_flags; -} - static int gralloc0_droid_yuv_format(int droid_format) { - return (droid_format == HAL_PIXEL_FORMAT_YCbCr_420_888 || droid_format == HAL_PIXEL_FORMAT_YV12); } static int gralloc0_alloc(alloc_device_t *dev, int w, int h, int format, int usage, - buffer_handle_t *handle, int *stride) + buffer_handle_t *out_handle, int *out_stride) { int32_t ret; - bool supported; + native_handle_t *handle; struct cros_gralloc_buffer_descriptor descriptor; auto mod = (struct gralloc0_module const *)dev->common.module; @@ -156,31 +80,10 @@ static int gralloc0_alloc(alloc_device_t *dev, int w, int h, int format, int usa descriptor.droid_format = format; descriptor.droid_usage = usage; descriptor.drm_format = cros_gralloc_convert_format(format); - descriptor.use_flags = gralloc0_convert_usage(usage); + descriptor.use_flags = cros_gralloc_convert_usage(usage); descriptor.reserved_region_size = 0; - supported = mod->driver->is_supported(&descriptor); - if (!supported && (usage & GRALLOC_USAGE_HW_COMPOSER)) { - descriptor.use_flags &= ~BO_USE_SCANOUT; - supported = mod->driver->is_supported(&descriptor); - } - if (!supported && (usage & GRALLOC_USAGE_HW_VIDEO_ENCODER) && - format != HAL_PIXEL_FORMAT_YCbCr_420_888) { - // Unmask BO_USE_HW_VIDEO_ENCODER for other formats. They are mostly - // intermediate formats not passed directly to the encoder (e.g. - // camera). YV12 is passed to the encoder component, but it is converted - // to YCbCr_420_888 before being passed to the hw encoder. - descriptor.use_flags &= ~BO_USE_HW_VIDEO_ENCODER; - drv_log("Retrying format %u allocation without encoder flag", format); - supported = mod->driver->is_supported(&descriptor); - } - if (!supported && (usage & BUFFER_USAGE_FRONT_RENDERING)) { - descriptor.use_flags &= ~BO_USE_FRONT_RENDERING; - descriptor.use_flags |= BO_USE_LINEAR; - supported = mod->driver->is_supported(&descriptor); - } - - if (!supported) { + if (!mod->driver->is_supported(&descriptor)) { drv_log("Unsupported combination -- HAL format: %u, HAL usage: %u, " "drv_format: %4.4s, use_flags: %llu\n", format, usage, reinterpret_cast<char *>(&descriptor.drm_format), @@ -188,20 +91,31 @@ static int gralloc0_alloc(alloc_device_t *dev, int w, int h, int format, int usa return -EINVAL; } - ret = mod->driver->allocate(&descriptor, handle); + ret = mod->driver->allocate(&descriptor, &handle); if (ret) return ret; - auto hnd = cros_gralloc_convert_handle(*handle); - *stride = hnd->pixel_stride; + auto hnd = cros_gralloc_convert_handle(handle); + *out_handle = handle; + *out_stride = hnd->pixel_stride; return 0; } static int gralloc0_free(alloc_device_t *dev, buffer_handle_t handle) { + int32_t ret; auto mod = (struct gralloc0_module const *)dev->common.module; - return mod->driver->release(handle); + + ret = mod->driver->release(handle); + if (ret) + return ret; + + auto hnd = const_cast<native_handle_t *>(handle); + native_handle_close(hnd); + native_handle_delete(hnd); + + return 0; } static int gralloc0_close(struct hw_device_t *dev) @@ -217,11 +131,9 @@ static int gralloc0_init(struct gralloc0_module *mod, bool initialize_alloc) if (mod->initialized) return 0; - mod->driver = std::make_unique<cros_gralloc_driver>(); - if (mod->driver->init()) { - drv_log("Failed to initialize driver.\n"); + mod->driver = cros_gralloc_driver::get_instance(); + if (!mod->driver) return -ENODEV; - } if (initialize_alloc) { mod->alloc = std::make_unique<alloc_device_t>(); @@ -381,20 +293,20 @@ static int gralloc0_perform(struct gralloc_module_t const *module, int op, ...) memset(info, 0, sizeof(*info)); info->drm_fourcc = drv_get_standard_fourcc(hnd->format); info->num_fds = hnd->num_planes; + for (int i = 0; i < info->num_fds; i++) + info->fds[i] = hnd->fds[i]; + ret = mod->driver->resource_info(handle, strides, offsets, &format_modifier); if (ret) break; info->modifier = format_modifier ? format_modifier : hnd->format_modifier; - for (uint32_t i = 0; i < hnd->num_planes; i++) { - info->fds[i] = hnd->fds[i]; - if (strides[i]) { - info->stride[i] = strides[i]; - info->offset[i] = offsets[i]; - } else { - info->stride[i] = hnd->strides[i]; - info->offset[i] = hnd->offsets[i]; - } + for (uint32_t i = 0; i < DRV_MAX_PLANES; i++) { + if (!strides[i]) + break; + + info->stride[i] = strides[i]; + info->offset[i] = offsets[i]; } break; case GRALLOC_DRM_GET_USAGE: @@ -453,7 +365,7 @@ static int gralloc0_lock_async(struct gralloc_module_t const *module, buffer_han assert(w >= 0); assert(h >= 0); - map_flags = gralloc0_convert_map_usage(usage); + map_flags = cros_gralloc_convert_map_usage(static_cast<uint64_t>(usage)); ret = mod->driver->lock(handle, fence_fd, true, &rect, map_flags, addr); *vaddr = addr[0]; return ret; @@ -505,7 +417,7 @@ static int gralloc0_lock_async_ycbcr(struct gralloc_module_t const *module, buff assert(w >= 0); assert(h >= 0); - map_flags = gralloc0_convert_map_usage(usage); + map_flags = cros_gralloc_convert_map_usage(static_cast<uint64_t>(usage)); ret = mod->driver->lock(handle, fence_fd, true, &rect, map_flags, addr); if (ret) return ret; diff --git a/cros_gralloc/gralloc0/tests/gralloctest.c b/cros_gralloc/gralloc0/tests/gralloctest.c index eea36e4..9d8101c 100644 --- a/cros_gralloc/gralloc0/tests/gralloctest.c +++ b/cros_gralloc/gralloc0/tests/gralloctest.c @@ -262,6 +262,8 @@ static struct gralloctest_context *test_init_gralloc() int err; hw_module_t const *hw_module; struct gralloctest_context *ctx = calloc(1, sizeof(*ctx)); + if (!ctx) + return NULL; err = hw_get_module(GRALLOC_HARDWARE_MODULE_ID, &hw_module); if (err) diff --git a/cros_gralloc/gralloc3/.clang-format b/cros_gralloc/gralloc3/.clang-format deleted file mode 100644 index 534cd32..0000000 --- a/cros_gralloc/gralloc3/.clang-format +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2020 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# This directory is formatted to match the format of the interfaces implemented. - -BasedOnStyle: Google -Standard: Cpp11 -AccessModifierOffset: -2 -AllowShortFunctionsOnASingleLine: Inline -ColumnLimit: 100 -CommentPragmas: NOLINT:.* -DerivePointerAlignment: false -IncludeBlocks: Preserve -IndentWidth: 4 -ContinuationIndentWidth: 8 -PointerAlignment: Left -TabWidth: 4 -UseTab: Never
\ No newline at end of file diff --git a/cros_gralloc/gralloc3/Android.bp b/cros_gralloc/gralloc3/Android.bp deleted file mode 100644 index 6e36c5b..0000000 --- a/cros_gralloc/gralloc3/Android.bp +++ /dev/null @@ -1,88 +0,0 @@ -// -// Copyright (C) 2020 The Android Open Source Project -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package { - // See: http://go/android-license-faq - // A large-scale-change added 'default_applicable_licenses' to import - // all of the 'license_kinds' from "external_minigbm_license" - // to get the below license kinds: - // SPDX-license-identifier-BSD - default_applicable_licenses: ["external_minigbm_license"], -} - -cc_binary { - name: "android.hardware.graphics.allocator@3.0-service.minigbm", - relative_install_path: "hw", - vendor: true, - init_rc: ["android.hardware.graphics.allocator@3.0-service.minigbm.rc"], - - cflags: [ - "-Wall", - "-Werror", - ], - - shared_libs: [ - "android.hardware.graphics.allocator@3.0", - "android.hardware.graphics.mapper@3.0", - "libbase", - "libcutils", - "libhidlbase", - "liblog", - "libsync", - "libutils", - ], - - static_libs: [ - "libdrm", - "libminigbm_cros_gralloc", - ], - - srcs: [ - "CrosGralloc3Allocator.cc", - "CrosGralloc3AllocatorService.cc", - "CrosGralloc3Utils.cc", - ], -} - -cc_library_shared { - name: "android.hardware.graphics.mapper@3.0-impl.minigbm", - relative_install_path: "hw", - vendor: true, - - cflags: [ - "-Wall", - "-Werror", - ], - - shared_libs: [ - "android.hardware.graphics.mapper@3.0", - "libbase", - "libcutils", - "libhidlbase", - "liblog", - "libsync", - "libutils", - ], - - static_libs: [ - "libdrm", - "libminigbm_cros_gralloc", - ], - - srcs: [ - "CrosGralloc3Mapper.cc", - "CrosGralloc3Utils.cc", - ], -} diff --git a/cros_gralloc/gralloc3/CrosGralloc3Allocator.cc b/cros_gralloc/gralloc3/CrosGralloc3Allocator.cc deleted file mode 100644 index 57c49e9..0000000 --- a/cros_gralloc/gralloc3/CrosGralloc3Allocator.cc +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "cros_gralloc/gralloc3/CrosGralloc3Allocator.h" - -#include <optional> - -#include <android/hardware/graphics/mapper/3.0/IMapper.h> - -#include "cros_gralloc/cros_gralloc_helpers.h" -#include "cros_gralloc/gralloc3/CrosGralloc3Utils.h" - -using android::hardware::hidl_handle; -using android::hardware::hidl_vec; -using android::hardware::Return; -using android::hardware::Void; -using android::hardware::graphics::common::V1_2::BufferUsage; -using android::hardware::graphics::common::V1_2::PixelFormat; -using android::hardware::graphics::mapper::V3_0::Error; - -using BufferDescriptorInfo = - android::hardware::graphics::mapper::V3_0::IMapper::BufferDescriptorInfo; - -CrosGralloc3Allocator::CrosGralloc3Allocator() : mDriver(std::make_unique<cros_gralloc_driver>()) { - if (mDriver->init()) { - drv_log("Failed to initialize driver.\n"); - mDriver = nullptr; - } -} - -Error CrosGralloc3Allocator::allocate(const BufferDescriptorInfo& descriptor, uint32_t* outStride, - hidl_handle* outHandle) { - if (!mDriver) { - drv_log("Failed to allocate. Driver is uninitialized.\n"); - return Error::NO_RESOURCES; - } - - if (!outStride || !outHandle) { - return Error::NO_RESOURCES; - } - - struct cros_gralloc_buffer_descriptor crosDescriptor; - if (convertToCrosDescriptor(descriptor, &crosDescriptor)) { - return Error::UNSUPPORTED; - } - - bool supported = mDriver->is_supported(&crosDescriptor); - if (!supported && (descriptor.usage & BufferUsage::COMPOSER_OVERLAY)) { - crosDescriptor.use_flags &= ~BO_USE_SCANOUT; - supported = mDriver->is_supported(&crosDescriptor); - } - - if (!supported) { - std::string drmFormatString = get_drm_format_string(crosDescriptor.drm_format); - std::string pixelFormatString = getPixelFormatString(descriptor.format); - std::string usageString = getUsageString(descriptor.usage); - drv_log("Unsupported combination -- pixel format: %s, drm format:%s, usage: %s\n", - pixelFormatString.c_str(), drmFormatString.c_str(), usageString.c_str()); - return Error::UNSUPPORTED; - } - - buffer_handle_t handle; - int ret = mDriver->allocate(&crosDescriptor, &handle); - if (ret) { - return Error::NO_RESOURCES; - } - - cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(handle); - if (!crosHandle) { - return Error::NO_RESOURCES; - } - - *outHandle = handle; - *outStride = crosHandle->pixel_stride; - - return Error::NONE; -} - -Return<void> CrosGralloc3Allocator::allocate(const hidl_vec<uint32_t>& encoded, uint32_t count, - allocate_cb hidlCb) { - hidl_vec<hidl_handle> handles; - - if (!mDriver) { - drv_log("Failed to allocate. Driver is uninitialized.\n"); - hidlCb(Error::NO_RESOURCES, 0, handles); - return Void(); - } - - auto descriptor_opt = decodeBufferDescriptorInfo(encoded); - if (!descriptor_opt) { - drv_log("Failed to allocate. Failed to decode buffer descriptor.\n"); - hidlCb(Error::BAD_DESCRIPTOR, 0, handles); - return Void(); - } - - BufferDescriptorInfo descriptor = *descriptor_opt; - - handles.resize(count); - - uint32_t stride = 0; - for (int i = 0; i < handles.size(); i++) { - Error err = allocate(descriptor, &stride, &(handles[i])); - if (err != Error::NONE) { - for (int j = 0; j < i; j++) { - mDriver->release(handles[j].getNativeHandle()); - } - handles.resize(0); - hidlCb(err, 0, handles); - return Void(); - } - } - - hidlCb(Error::NONE, stride, handles); - - for (const hidl_handle& handle : handles) { - mDriver->release(handle.getNativeHandle()); - } - - return Void(); -} - -Return<void> CrosGralloc3Allocator::dumpDebugInfo(dumpDebugInfo_cb hidl_cb) { - hidl_cb("CrosGralloc3Allocator::dumpDebugInfo unimplemented."); - return Void(); -} diff --git a/cros_gralloc/gralloc3/CrosGralloc3Allocator.h b/cros_gralloc/gralloc3/CrosGralloc3Allocator.h deleted file mode 100644 index 655143c..0000000 --- a/cros_gralloc/gralloc3/CrosGralloc3Allocator.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <android/hardware/graphics/allocator/3.0/IAllocator.h> -#include <android/hardware/graphics/mapper/3.0/IMapper.h> - -#include "cros_gralloc/cros_gralloc_driver.h" - -class CrosGralloc3Allocator : public android::hardware::graphics::allocator::V3_0::IAllocator { - public: - CrosGralloc3Allocator(); - - android::hardware::Return<void> allocate( - const android::hardware::hidl_vec<uint32_t>& descriptor, uint32_t count, - allocate_cb hidl_cb) override; - - android::hardware::Return<void> dumpDebugInfo(dumpDebugInfo_cb hidl_cb) override; - - private: - android::hardware::graphics::mapper::V3_0::Error allocate( - const android::hardware::graphics::mapper::V3_0::IMapper::BufferDescriptorInfo& - description, - uint32_t* outStride, android::hardware::hidl_handle* outHandle); - - std::unique_ptr<cros_gralloc_driver> mDriver; -}; diff --git a/cros_gralloc/gralloc3/CrosGralloc3AllocatorService.cc b/cros_gralloc/gralloc3/CrosGralloc3AllocatorService.cc deleted file mode 100644 index daab508..0000000 --- a/cros_gralloc/gralloc3/CrosGralloc3AllocatorService.cc +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#define LOG_TAG "AllocatorService" - -#include <hidl/LegacySupport.h> - -#include "cros_gralloc/gralloc3/CrosGralloc3Allocator.h" - -using android::sp; -using android::hardware::configureRpcThreadpool; -using android::hardware::joinRpcThreadpool; -using android::hardware::graphics::allocator::V3_0::IAllocator; - -int main(int, char**) { - sp<IAllocator> allocator = new CrosGralloc3Allocator(); - configureRpcThreadpool(4, true /* callerWillJoin */); - if (allocator->registerAsService() != android::NO_ERROR) { - ALOGE("failed to register graphics IAllocator 3.0 service"); - return -EINVAL; - } - - ALOGI("graphics IAllocator 3.0 service is initialized"); - android::hardware::joinRpcThreadpool(); - ALOGI("graphics IAllocator 3.0 service is terminating"); - return 0; -} diff --git a/cros_gralloc/gralloc3/CrosGralloc3Mapper.cc b/cros_gralloc/gralloc3/CrosGralloc3Mapper.cc deleted file mode 100644 index 08da016..0000000 --- a/cros_gralloc/gralloc3/CrosGralloc3Mapper.cc +++ /dev/null @@ -1,490 +0,0 @@ -/* - * Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "cros_gralloc/gralloc3/CrosGralloc3Mapper.h" - -#include <cutils/native_handle.h> - -#include "cros_gralloc/cros_gralloc_helpers.h" -#include "cros_gralloc/gralloc3/CrosGralloc3Utils.h" - -#include "helpers.h" - -using android::hardware::hidl_handle; -using android::hardware::hidl_vec; -using android::hardware::Return; -using android::hardware::Void; -using android::hardware::graphics::common::V1_2::BufferUsage; -using android::hardware::graphics::common::V1_2::PixelFormat; -using android::hardware::graphics::mapper::V3_0::Error; -using android::hardware::graphics::mapper::V3_0::IMapper; -using android::hardware::graphics::mapper::V3_0::YCbCrLayout; - -CrosGralloc3Mapper::CrosGralloc3Mapper() : mDriver(std::make_unique<cros_gralloc_driver>()) { - if (mDriver->init()) { - drv_log("Failed to initialize driver.\n"); - mDriver = nullptr; - } -} - -Return<void> CrosGralloc3Mapper::createDescriptor(const BufferDescriptorInfo& description, - createDescriptor_cb hidlCb) { - hidl_vec<uint32_t> descriptor; - - if (description.width == 0) { - drv_log("Failed to createDescriptor. Bad width: %d.\n", description.width); - hidlCb(Error::BAD_VALUE, descriptor); - return Void(); - } - - if (description.height == 0) { - drv_log("Failed to createDescriptor. Bad height: %d.\n", description.height); - hidlCb(Error::BAD_VALUE, descriptor); - return Void(); - } - - if (description.layerCount == 0) { - drv_log("Failed to createDescriptor. Bad layer count: %d.\n", description.layerCount); - hidlCb(Error::BAD_VALUE, descriptor); - return Void(); - } - - auto descriptor_opt = encodeBufferDescriptorInfo(description); - if (!descriptor_opt) { - drv_log("Failed to createDescriptor. Failed to encodeBufferDescriptorInfo\n"); - hidlCb(Error::BAD_VALUE, descriptor); - return Void(); - } - - descriptor = *descriptor_opt; - hidlCb(Error::NONE, descriptor); - return Void(); -} - -Return<void> CrosGralloc3Mapper::importBuffer(const hidl_handle& handle, importBuffer_cb hidlCb) { - if (!mDriver) { - drv_log("Failed to import buffer. Driver is uninitialized.\n"); - hidlCb(Error::NO_RESOURCES, nullptr); - return Void(); - } - - const native_handle_t* bufferHandle = handle.getNativeHandle(); - if (!bufferHandle || bufferHandle->numFds == 0) { - drv_log("Failed to importBuffer. Bad handle.\n"); - hidlCb(Error::BAD_BUFFER, nullptr); - return Void(); - } - - native_handle_t* importedBufferHandle = native_handle_clone(bufferHandle); - if (!importedBufferHandle) { - drv_log("Failed to importBuffer. Handle clone failed.\n"); - hidlCb(Error::NO_RESOURCES, nullptr); - return Void(); - } - - int ret = mDriver->retain(importedBufferHandle); - if (ret) { - native_handle_close(importedBufferHandle); - native_handle_delete(importedBufferHandle); - hidlCb(Error::NO_RESOURCES, nullptr); - return Void(); - } - - hidlCb(Error::NONE, importedBufferHandle); - return Void(); -} - -Return<Error> CrosGralloc3Mapper::freeBuffer(void* rawHandle) { - if (!mDriver) { - drv_log("Failed to freeBuffer. Driver is uninitialized.\n"); - return Error::NO_RESOURCES; - } - - native_handle_t* bufferHandle = reinterpret_cast<native_handle_t*>(rawHandle); - if (!bufferHandle) { - drv_log("Failed to freeBuffer. Empty handle.\n"); - return Error::BAD_BUFFER; - } - - int ret = mDriver->release(bufferHandle); - if (ret) { - drv_log("Failed to freeBuffer.\n"); - return Error::BAD_BUFFER; - } - - native_handle_close(bufferHandle); - native_handle_delete(bufferHandle); - return Error::NONE; -} - -Return<Error> CrosGralloc3Mapper::validateBufferSize(void* rawHandle, - const BufferDescriptorInfo& descriptor, - uint32_t stride) { - if (!mDriver) { - drv_log("Failed to validateBufferSize. Driver is uninitialized.\n"); - return Error::NO_RESOURCES; - } - - native_handle_t* bufferHandle = reinterpret_cast<native_handle_t*>(rawHandle); - if (!bufferHandle) { - drv_log("Failed to validateBufferSize. Empty handle.\n"); - return Error::BAD_BUFFER; - } - - cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle); - if (!crosHandle) { - drv_log("Failed to validateBufferSize. Invalid handle.\n"); - return Error::BAD_BUFFER; - } - - PixelFormat crosHandleFormat = static_cast<PixelFormat>(crosHandle->droid_format); - if (descriptor.format != crosHandleFormat) { - drv_log("Failed to validateBufferSize. Format mismatch.\n"); - return Error::BAD_BUFFER; - } - - if (descriptor.width != crosHandle->width) { - drv_log("Failed to validateBufferSize. Width mismatch (%d vs %d).\n", descriptor.width, - crosHandle->width); - return Error::BAD_VALUE; - } - - if (descriptor.height != crosHandle->height) { - drv_log("Failed to validateBufferSize. Height mismatch (%d vs %d).\n", descriptor.height, - crosHandle->height); - return Error::BAD_VALUE; - } - - if (stride != crosHandle->pixel_stride) { - drv_log("Failed to validateBufferSize. Stride mismatch (%d vs %d).\n", stride, - crosHandle->pixel_stride); - return Error::BAD_VALUE; - } - - return Error::NONE; -} - -Return<void> CrosGralloc3Mapper::getTransportSize(void* rawHandle, getTransportSize_cb hidlCb) { - if (!mDriver) { - drv_log("Failed to getTransportSize. Driver is uninitialized.\n"); - hidlCb(Error::BAD_BUFFER, 0, 0); - return Void(); - } - - native_handle_t* bufferHandle = reinterpret_cast<native_handle_t*>(rawHandle); - if (!bufferHandle) { - drv_log("Failed to getTransportSize. Bad handle.\n"); - hidlCb(Error::BAD_BUFFER, 0, 0); - return Void(); - } - - // No local process data is currently stored on the native handle. - hidlCb(Error::NONE, bufferHandle->numFds, bufferHandle->numInts); - return Void(); -} - -Return<void> CrosGralloc3Mapper::lock(void* rawHandle, uint64_t cpuUsage, const Rect& accessRegion, - const hidl_handle& acquireFence, lock_cb hidlCb) { - if (!mDriver) { - drv_log("Failed to lock. Driver is uninitialized.\n"); - hidlCb(Error::NO_RESOURCES, nullptr, 0, 0); - return Void(); - } - - buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle); - if (!bufferHandle) { - drv_log("Failed to lock. Empty handle.\n"); - hidlCb(Error::BAD_BUFFER, nullptr, 0, 0); - return Void(); - } - - cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle); - if (crosHandle == nullptr) { - drv_log("Failed to lock. Invalid handle.\n"); - hidlCb(Error::BAD_BUFFER, nullptr, 0, 0); - return Void(); - } - - LockResult result = lockInternal(crosHandle, cpuUsage, accessRegion, acquireFence); - if (result.error != Error::NONE) { - drv_log("Failed to lock. Failed to lockInternal.\n"); - hidlCb(result.error, nullptr, 0, 0); - return Void(); - } - - int32_t bytesPerPixel = drv_bytes_per_pixel_from_format(crosHandle->format, 0); - int32_t bytesPerStride = static_cast<int32_t>(crosHandle->strides[0]); - - hidlCb(Error::NONE, result.mapped[0], bytesPerPixel, bytesPerStride); - return Void(); -} - -Return<void> CrosGralloc3Mapper::lockYCbCr(void* rawHandle, uint64_t cpuUsage, - const Rect& accessRegion, - const android::hardware::hidl_handle& acquireFence, - lockYCbCr_cb hidlCb) { - YCbCrLayout ycbcr = {}; - - if (!mDriver) { - drv_log("Failed to lock. Driver is uninitialized.\n"); - hidlCb(Error::NO_RESOURCES, ycbcr); - return Void(); - } - - buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle); - if (!bufferHandle) { - drv_log("Failed to lockYCbCr. Empty handle.\n"); - hidlCb(Error::BAD_BUFFER, ycbcr); - return Void(); - } - - cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle); - if (crosHandle == nullptr) { - drv_log("Failed to lockYCbCr. Invalid handle.\n"); - hidlCb(Error::BAD_BUFFER, ycbcr); - return Void(); - } - - LockResult result = lockInternal(crosHandle, cpuUsage, accessRegion, acquireFence); - if (result.error != Error::NONE) { - drv_log("Failed to lockYCbCr. Failed to lockInternal.\n"); - hidlCb(result.error, ycbcr); - return Void(); - } - - switch (crosHandle->format) { - case DRM_FORMAT_NV12: { - ycbcr.y = result.mapped[0] + crosHandle->offsets[0]; - ycbcr.cb = result.mapped[0] + crosHandle->offsets[1]; - ycbcr.cr = result.mapped[0] + crosHandle->offsets[1] + 1; - ycbcr.yStride = crosHandle->strides[0]; - ycbcr.cStride = crosHandle->strides[1]; - ycbcr.chromaStep = 2; - break; - } - case DRM_FORMAT_NV21: { - ycbcr.y = result.mapped[0] + crosHandle->offsets[0]; - ycbcr.cb = result.mapped[0] + crosHandle->offsets[1] + 1; - ycbcr.cr = result.mapped[0] + crosHandle->offsets[1]; - ycbcr.yStride = crosHandle->strides[0]; - ycbcr.cStride = crosHandle->strides[1]; - ycbcr.chromaStep = 2; - break; - } - case DRM_FORMAT_YVU420: { - ycbcr.y = result.mapped[0] + crosHandle->offsets[0]; - ycbcr.cb = result.mapped[0] + crosHandle->offsets[1]; - ycbcr.cr = result.mapped[0] + crosHandle->offsets[2]; - ycbcr.yStride = crosHandle->strides[0]; - ycbcr.cStride = crosHandle->strides[1]; - ycbcr.chromaStep = 1; - break; - } - case DRM_FORMAT_YVU420_ANDROID: { - ycbcr.y = result.mapped[0] + crosHandle->offsets[0]; - ycbcr.cb = result.mapped[0] + crosHandle->offsets[2]; - ycbcr.cr = result.mapped[0] + crosHandle->offsets[1]; - ycbcr.yStride = crosHandle->strides[0]; - ycbcr.cStride = crosHandle->strides[1]; - ycbcr.chromaStep = 1; - break; - } - default: { - std::string format = get_drm_format_string(crosHandle->format); - drv_log("Failed to lockYCbCr. Unhandled format: %s\n", format.c_str()); - hidlCb(Error::BAD_BUFFER, ycbcr); - return Void(); - } - } - - hidlCb(Error::NONE, ycbcr); - return Void(); -} - -CrosGralloc3Mapper::LockResult CrosGralloc3Mapper::lockInternal( - cros_gralloc_handle_t crosHandle, uint64_t cpuUsage, const Rect& region, - const android::hardware::hidl_handle& acquireFence) { - LockResult result = {}; - - if (!mDriver) { - drv_log("Failed to lock. Driver is uninitialized.\n"); - result.error = Error::NO_RESOURCES; - return result; - } - - if (cpuUsage == 0) { - drv_log("Failed to lock. Bad cpu usage: %" PRIu64 ".\n", cpuUsage); - result.error = Error::BAD_VALUE; - return result; - } - - uint32_t mapUsage = 0; - int ret = convertToMapUsage(cpuUsage, &mapUsage); - if (ret) { - drv_log("Failed to lock. Convert usage failed.\n"); - result.error = Error::BAD_VALUE; - return result; - } - - if (region.left < 0) { - drv_log("Failed to lock. Invalid region: negative left value %d.\n", region.left); - result.error = Error::BAD_VALUE; - return result; - } - - if (region.top < 0) { - drv_log("Failed to lock. Invalid region: negative top value %d.\n", region.top); - result.error = Error::BAD_VALUE; - return result; - } - - if (region.width < 0) { - drv_log("Failed to lock. Invalid region: negative width value %d.\n", region.width); - result.error = Error::BAD_VALUE; - return result; - } - - if (region.height < 0) { - drv_log("Failed to lock. Invalid region: negative height value %d.\n", region.height); - result.error = Error::BAD_VALUE; - return result; - } - - if (region.width > crosHandle->width) { - drv_log("Failed to lock. Invalid region: width greater than buffer width (%d vs %d).\n", - region.width, crosHandle->width); - result.error = Error::BAD_VALUE; - return result; - } - - if (region.height > crosHandle->height) { - drv_log("Failed to lock. Invalid region: height greater than buffer height (%d vs %d).\n", - region.height, crosHandle->height); - result.error = Error::BAD_VALUE; - return result; - } - - struct rectangle rect = {static_cast<uint32_t>(region.left), static_cast<uint32_t>(region.top), - static_cast<uint32_t>(region.width), - static_cast<uint32_t>(region.height)}; - - // An access region of all zeros means the entire buffer. - if (rect.x == 0 && rect.y == 0 && rect.width == 0 && rect.height == 0) { - rect.width = crosHandle->width; - rect.height = crosHandle->height; - } - - int acquireFenceFd = -1; - ret = convertToFenceFd(acquireFence, &acquireFenceFd); - if (ret) { - drv_log("Failed to lock. Bad acquire fence.\n"); - result.error = Error::BAD_VALUE; - return result; - } - - buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(crosHandle); - ret = mDriver->lock(bufferHandle, acquireFenceFd, false, &rect, mapUsage, result.mapped); - if (ret) { - result.error = Error::BAD_VALUE; - return result; - } - - result.error = Error::NONE; - return result; -} - -Return<void> CrosGralloc3Mapper::unlock(void* rawHandle, unlock_cb hidlCb) { - if (!mDriver) { - drv_log("Failed to unlock. Driver is uninitialized.\n"); - hidlCb(Error::BAD_BUFFER, nullptr); - return Void(); - } - - buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle); - if (!bufferHandle) { - drv_log("Failed to unlock. Empty handle.\n"); - hidlCb(Error::BAD_BUFFER, nullptr); - return Void(); - } - - int releaseFenceFd = -1; - int ret = mDriver->unlock(bufferHandle, &releaseFenceFd); - if (ret) { - drv_log("Failed to unlock.\n"); - hidlCb(Error::BAD_BUFFER, nullptr); - return Void(); - } - - hidl_handle releaseFenceHandle; - ret = convertToFenceHandle(releaseFenceFd, &releaseFenceHandle); - if (ret) { - drv_log("Failed to unlock. Failed to convert release fence to handle.\n"); - hidlCb(Error::BAD_BUFFER, nullptr); - return Void(); - } - - hidlCb(Error::NONE, releaseFenceHandle); - return Void(); -} - -Return<void> CrosGralloc3Mapper::isSupported(const BufferDescriptorInfo& descriptor, - isSupported_cb hidlCb) { - if (!mDriver) { - drv_log("Failed to isSupported. Driver is uninitialized.\n"); - hidlCb(Error::BAD_VALUE, false); - return Void(); - } - - struct cros_gralloc_buffer_descriptor crosDescriptor; - if (convertToCrosDescriptor(descriptor, &crosDescriptor)) { - hidlCb(Error::NONE, false); - return Void(); - } - - bool supported = mDriver->is_supported(&crosDescriptor); - if (!supported) { - crosDescriptor.use_flags &= ~BO_USE_SCANOUT; - supported = mDriver->is_supported(&crosDescriptor); - } - - hidlCb(Error::NONE, supported); - return Void(); -} - -int CrosGralloc3Mapper::getResolvedDrmFormat(PixelFormat pixelFormat, uint64_t bufferUsage, - uint32_t* outDrmFormat) { - uint32_t drmFormat; - if (convertToDrmFormat(pixelFormat, &drmFormat)) { - std::string pixelFormatString = getPixelFormatString(pixelFormat); - drv_log("Failed to getResolvedDrmFormat. Failed to convert format %s\n", - pixelFormatString.c_str()); - return -EINVAL; - } - - uint64_t usage; - if (convertToBufferUsage(bufferUsage, &usage)) { - std::string usageString = getUsageString(bufferUsage); - drv_log("Failed to getResolvedDrmFormat. Failed to convert usage %s\n", - usageString.c_str()); - return -EINVAL; - } - - uint32_t resolvedDrmFormat = mDriver->get_resolved_drm_format(drmFormat, usage); - if (resolvedDrmFormat == DRM_FORMAT_INVALID) { - std::string drmFormatString = get_drm_format_string(drmFormat); - drv_log("Failed to getResolvedDrmFormat. Failed to resolve drm format %s\n", - drmFormatString.c_str()); - return -EINVAL; - } - - *outDrmFormat = resolvedDrmFormat; - - return 0; -} - -android::hardware::graphics::mapper::V3_0::IMapper* HIDL_FETCH_IMapper(const char* /*name*/) { - return static_cast<android::hardware::graphics::mapper::V3_0::IMapper*>(new CrosGralloc3Mapper); -} diff --git a/cros_gralloc/gralloc3/CrosGralloc3Mapper.h b/cros_gralloc/gralloc3/CrosGralloc3Mapper.h deleted file mode 100644 index 7ec92d5..0000000 --- a/cros_gralloc/gralloc3/CrosGralloc3Mapper.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <android/hardware/graphics/mapper/3.0/IMapper.h> - -#include <optional> - -#include "cros_gralloc/cros_gralloc_driver.h" -#include "cros_gralloc/cros_gralloc_handle.h" - -class CrosGralloc3Mapper : public android::hardware::graphics::mapper::V3_0::IMapper { - public: - CrosGralloc3Mapper(); - - android::hardware::Return<void> createDescriptor(const BufferDescriptorInfo& description, - createDescriptor_cb hidlCb) override; - - android::hardware::Return<void> importBuffer(const android::hardware::hidl_handle& rawHandle, - importBuffer_cb hidlCb) override; - - android::hardware::Return<android::hardware::graphics::mapper::V3_0::Error> freeBuffer( - void* rawHandle) override; - - android::hardware::Return<android::hardware::graphics::mapper::V3_0::Error> validateBufferSize( - void* rawHandle, const BufferDescriptorInfo& descriptor, uint32_t stride) override; - - android::hardware::Return<void> getTransportSize(void* rawHandle, - getTransportSize_cb hidlCb) override; - - android::hardware::Return<void> lock(void* rawHandle, uint64_t cpuUsage, - const Rect& accessRegion, - const android::hardware::hidl_handle& acquireFence, - lock_cb hidlCb) override; - - android::hardware::Return<void> lockYCbCr(void* rawHandle, uint64_t cpuUsage, - const Rect& accessRegion, - const android::hardware::hidl_handle& acquireFence, - lockYCbCr_cb _hidl_cb) override; - - android::hardware::Return<void> unlock(void* rawHandle, unlock_cb hidlCb) override; - - android::hardware::Return<void> isSupported(const BufferDescriptorInfo& descriptor, - isSupported_cb hidlCb) override; - - private: - int getResolvedDrmFormat(android::hardware::graphics::common::V1_2::PixelFormat pixelFormat, - uint64_t bufferUsage, uint32_t* outDrmFormat); - - struct LockResult { - android::hardware::graphics::mapper::V3_0::Error error; - - uint8_t* mapped[DRV_MAX_PLANES]; - }; - LockResult lockInternal(cros_gralloc_handle_t crosHandle, uint64_t cpuUsage, - const Rect& accessRegion, - const android::hardware::hidl_handle& acquireFence); - - std::unique_ptr<cros_gralloc_driver> mDriver; -}; - -extern "C" android::hardware::graphics::mapper::V3_0::IMapper* HIDL_FETCH_IMapper(const char* name); diff --git a/cros_gralloc/gralloc3/CrosGralloc3Utils.cc b/cros_gralloc/gralloc3/CrosGralloc3Utils.cc deleted file mode 100644 index 3f39305..0000000 --- a/cros_gralloc/gralloc3/CrosGralloc3Utils.cc +++ /dev/null @@ -1,402 +0,0 @@ -/* - * Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "cros_gralloc/gralloc3/CrosGralloc3Utils.h" - -#include <array> -#include <limits> -#include <unordered_map> - -#include <android-base/stringprintf.h> -#include <android-base/strings.h> -#include <cutils/native_handle.h> - -#include "cros_gralloc/cros_gralloc_helpers.h" - -using android::hardware::hidl_bitfield; -using android::hardware::hidl_handle; -using android::hardware::hidl_vec; -using android::hardware::graphics::common::V1_2::BufferUsage; -using android::hardware::graphics::common::V1_2::PixelFormat; - -using BufferDescriptorInfo = - android::hardware::graphics::mapper::V3_0::IMapper::BufferDescriptorInfo; - -std::string getPixelFormatString(PixelFormat format) { - switch (format) { - case PixelFormat::BGRA_8888: - return "PixelFormat::BGRA_8888"; - case PixelFormat::BLOB: - return "PixelFormat::BLOB"; - case PixelFormat::DEPTH_16: - return "PixelFormat::DEPTH_16"; - case PixelFormat::DEPTH_24: - return "PixelFormat::DEPTH_24"; - case PixelFormat::DEPTH_24_STENCIL_8: - return "PixelFormat::DEPTH_24_STENCIL_8"; - case PixelFormat::DEPTH_32F: - return "PixelFormat::DEPTH_24"; - case PixelFormat::DEPTH_32F_STENCIL_8: - return "PixelFormat::DEPTH_24_STENCIL_8"; - case PixelFormat::HSV_888: - return "PixelFormat::HSV_888"; - case PixelFormat::IMPLEMENTATION_DEFINED: - return "PixelFormat::IMPLEMENTATION_DEFINED"; - case PixelFormat::RAW10: - return "PixelFormat::RAW10"; - case PixelFormat::RAW12: - return "PixelFormat::RAW12"; - case PixelFormat::RAW16: - return "PixelFormat::RAW16"; - case PixelFormat::RAW_OPAQUE: - return "PixelFormat::RAW_OPAQUE"; - case PixelFormat::RGBA_1010102: - return "PixelFormat::RGBA_1010102"; - case PixelFormat::RGBA_8888: - return "PixelFormat::RGBA_8888"; - case PixelFormat::RGBA_FP16: - return "PixelFormat::RGBA_FP16"; - case PixelFormat::RGBX_8888: - return "PixelFormat::RGBX_8888"; - case PixelFormat::RGB_565: - return "PixelFormat::RGB_565"; - case PixelFormat::RGB_888: - return "PixelFormat::RGB_888"; - case PixelFormat::STENCIL_8: - return "PixelFormat::STENCIL_8"; - case PixelFormat::Y16: - return "PixelFormat::Y16"; - case PixelFormat::Y8: - return "PixelFormat::Y8"; - case PixelFormat::YCBCR_420_888: - return "PixelFormat::YCBCR_420_888"; - case PixelFormat::YCBCR_422_I: - return "PixelFormat::YCBCR_422_I"; - case PixelFormat::YCBCR_422_SP: - return "PixelFormat::YCBCR_422_SP"; - case PixelFormat::YCBCR_P010: - return "PixelFormat::YCBCR_P010"; - case PixelFormat::YCRCB_420_SP: - return "PixelFormat::YCRCB_420_SP"; - case PixelFormat::YV12: - return "PixelFormat::YV12"; - } - return android::base::StringPrintf("PixelFormat::Unknown(%d)", static_cast<uint32_t>(format)); -} - -std::string getUsageString(hidl_bitfield<BufferUsage> bufferUsage) { - using Underlying = typename std::underlying_type<BufferUsage>::type; - - Underlying usage = static_cast<Underlying>(bufferUsage); - - std::vector<std::string> usages; - if (usage & BufferUsage::CAMERA_INPUT) { - usage &= ~static_cast<Underlying>(BufferUsage::CAMERA_INPUT); - usages.push_back("BufferUsage::CAMERA_INPUT"); - } - if (usage & BufferUsage::CAMERA_OUTPUT) { - usage &= ~static_cast<Underlying>(BufferUsage::CAMERA_OUTPUT); - usages.push_back("BufferUsage::CAMERA_OUTPUT"); - } - if (usage & BufferUsage::COMPOSER_CURSOR) { - usage &= ~static_cast<Underlying>(BufferUsage::COMPOSER_CURSOR); - usages.push_back("BufferUsage::COMPOSER_CURSOR"); - } - if (usage & BufferUsage::COMPOSER_OVERLAY) { - usage &= ~static_cast<Underlying>(BufferUsage::COMPOSER_OVERLAY); - usages.push_back("BufferUsage::COMPOSER_OVERLAY"); - } - if (usage & BufferUsage::CPU_READ_OFTEN) { - usage &= ~static_cast<Underlying>(BufferUsage::CPU_READ_OFTEN); - usages.push_back("BufferUsage::CPU_READ_OFTEN"); - } - if (usage & BufferUsage::CPU_READ_NEVER) { - usage &= ~static_cast<Underlying>(BufferUsage::CPU_READ_NEVER); - usages.push_back("BufferUsage::CPU_READ_NEVER"); - } - if (usage & BufferUsage::CPU_READ_RARELY) { - usage &= ~static_cast<Underlying>(BufferUsage::CPU_READ_RARELY); - usages.push_back("BufferUsage::CPU_READ_RARELY"); - } - if (usage & BufferUsage::CPU_WRITE_NEVER) { - usage &= ~static_cast<Underlying>(BufferUsage::CPU_WRITE_NEVER); - usages.push_back("BufferUsage::CPU_WRITE_NEVER"); - } - if (usage & BufferUsage::CPU_WRITE_OFTEN) { - usage &= ~static_cast<Underlying>(BufferUsage::CPU_WRITE_OFTEN); - usages.push_back("BufferUsage::CPU_WRITE_OFTEN"); - } - if (usage & BufferUsage::CPU_WRITE_RARELY) { - usage &= ~static_cast<Underlying>(BufferUsage::CPU_WRITE_RARELY); - usages.push_back("BufferUsage::CPU_WRITE_RARELY"); - } - if (usage & BufferUsage::GPU_RENDER_TARGET) { - usage &= ~static_cast<Underlying>(BufferUsage::GPU_RENDER_TARGET); - usages.push_back("BufferUsage::GPU_RENDER_TARGET"); - } - if (usage & BufferUsage::GPU_TEXTURE) { - usage &= ~static_cast<Underlying>(BufferUsage::GPU_TEXTURE); - usages.push_back("BufferUsage::GPU_TEXTURE"); - } - if (usage & BufferUsage::PROTECTED) { - usage &= ~static_cast<Underlying>(BufferUsage::PROTECTED); - usages.push_back("BufferUsage::PROTECTED"); - } - if (usage & BufferUsage::RENDERSCRIPT) { - usage &= ~static_cast<Underlying>(BufferUsage::RENDERSCRIPT); - usages.push_back("BufferUsage::RENDERSCRIPT"); - } - if (usage & BufferUsage::VIDEO_DECODER) { - usage &= ~static_cast<Underlying>(BufferUsage::VIDEO_DECODER); - usages.push_back("BufferUsage::VIDEO_DECODER"); - } - if (usage & BufferUsage::VIDEO_ENCODER) { - usage &= ~static_cast<Underlying>(BufferUsage::VIDEO_ENCODER); - usages.push_back("BufferUsage::VIDEO_ENCODER"); - } - - if (usage) { - usages.push_back(android::base::StringPrintf("UnknownUsageBits-%" PRIu64, usage)); - } - - return android::base::Join(usages, '|'); -} - -int convertToDrmFormat(PixelFormat format, uint32_t* outDrmFormat) { - switch (format) { - case PixelFormat::BGRA_8888: - *outDrmFormat = DRM_FORMAT_ARGB8888; - return 0; - /** - * Choose DRM_FORMAT_R8 because <system/graphics.h> requires the buffers - * with a format HAL_PIXEL_FORMAT_BLOB have a height of 1, and width - * equal to their size in bytes. - */ - case PixelFormat::BLOB: - *outDrmFormat = DRM_FORMAT_R8; - return 0; - case PixelFormat::DEPTH_16: - return -EINVAL; - case PixelFormat::DEPTH_24: - return -EINVAL; - case PixelFormat::DEPTH_24_STENCIL_8: - return -EINVAL; - case PixelFormat::DEPTH_32F: - return -EINVAL; - case PixelFormat::DEPTH_32F_STENCIL_8: - return -EINVAL; - case PixelFormat::HSV_888: - return -EINVAL; - case PixelFormat::IMPLEMENTATION_DEFINED: - *outDrmFormat = DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED; - return 0; - case PixelFormat::RAW10: - return -EINVAL; - case PixelFormat::RAW12: - return -EINVAL; - case PixelFormat::RAW16: - *outDrmFormat = DRM_FORMAT_R16; - return 0; - /* TODO use blob */ - case PixelFormat::RAW_OPAQUE: - return -EINVAL; - case PixelFormat::RGBA_1010102: - *outDrmFormat = DRM_FORMAT_ABGR2101010; - return 0; - case PixelFormat::RGBA_8888: - *outDrmFormat = DRM_FORMAT_ABGR8888; - return 0; - case PixelFormat::RGBA_FP16: - *outDrmFormat = DRM_FORMAT_ABGR16161616F; - return 0; - case PixelFormat::RGBX_8888: - *outDrmFormat = DRM_FORMAT_XBGR8888; - return 0; - case PixelFormat::RGB_565: - *outDrmFormat = DRM_FORMAT_RGB565; - return 0; - case PixelFormat::RGB_888: - *outDrmFormat = DRM_FORMAT_RGB888; - return 0; - case PixelFormat::STENCIL_8: - return -EINVAL; - case PixelFormat::Y16: - *outDrmFormat = DRM_FORMAT_R16; - return 0; - case PixelFormat::Y8: - *outDrmFormat = DRM_FORMAT_R8; - return 0; - case PixelFormat::YCBCR_420_888: - *outDrmFormat = DRM_FORMAT_FLEX_YCbCr_420_888; - return 0; - case PixelFormat::YCBCR_422_SP: - return -EINVAL; - case PixelFormat::YCBCR_422_I: - return -EINVAL; - case PixelFormat::YCBCR_P010: - *outDrmFormat = DRM_FORMAT_P010; - return 0; - case PixelFormat::YCRCB_420_SP: - *outDrmFormat = DRM_FORMAT_NV21; - return 0; - case PixelFormat::YV12: - *outDrmFormat = DRM_FORMAT_YVU420_ANDROID; - return 0; - }; - return -EINVAL; -} - -int convertToBufferUsage(uint64_t grallocUsage, uint64_t* outBufferUsage) { - uint64_t bufferUsage = BO_USE_NONE; - - if ((grallocUsage & BufferUsage::CPU_READ_MASK) == - static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY)) { - bufferUsage |= BO_USE_SW_READ_RARELY; - } - if ((grallocUsage & BufferUsage::CPU_READ_MASK) == - static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN)) { - bufferUsage |= BO_USE_SW_READ_OFTEN; - } - if ((grallocUsage & BufferUsage::CPU_WRITE_MASK) == - static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY)) { - bufferUsage |= BO_USE_SW_WRITE_RARELY; - } - if ((grallocUsage & BufferUsage::CPU_WRITE_MASK) == - static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN)) { - bufferUsage |= BO_USE_SW_WRITE_OFTEN; - } - if (grallocUsage & BufferUsage::GPU_TEXTURE) { - bufferUsage |= BO_USE_TEXTURE; - } - if (grallocUsage & BufferUsage::GPU_RENDER_TARGET) { - bufferUsage |= BO_USE_RENDERING; - } - if (grallocUsage & BufferUsage::COMPOSER_OVERLAY) { - /* HWC wants to use display hardware, but can defer to OpenGL. */ - bufferUsage |= BO_USE_SCANOUT | BO_USE_TEXTURE; - } - /* Map this flag to linear until real HW protection is available on Android. */ - if (grallocUsage & BufferUsage::PROTECTED) { - bufferUsage |= BO_USE_LINEAR; - } - if (grallocUsage & BufferUsage::COMPOSER_CURSOR) { - bufferUsage |= BO_USE_NONE; - } - if (grallocUsage & BufferUsage::VIDEO_ENCODER) { - /*HACK: See b/30054495 */ - bufferUsage |= BO_USE_SW_READ_OFTEN; - } - if (grallocUsage & BufferUsage::CAMERA_OUTPUT) { - bufferUsage |= BO_USE_CAMERA_WRITE; - } - if (grallocUsage & BufferUsage::CAMERA_INPUT) { - bufferUsage |= BO_USE_CAMERA_READ; - } - if (grallocUsage & BufferUsage::RENDERSCRIPT) { - bufferUsage |= BO_USE_RENDERSCRIPT; - } - if (grallocUsage & BufferUsage::VIDEO_DECODER) { - bufferUsage |= BO_USE_HW_VIDEO_DECODER; - } - - *outBufferUsage = bufferUsage; - return 0; -} - -int convertToMapUsage(uint64_t grallocUsage, uint32_t* outMapUsage) { - uint32_t mapUsage = BO_MAP_NONE; - - if (grallocUsage & BufferUsage::CPU_READ_MASK) { - mapUsage |= BO_MAP_READ; - } - if (grallocUsage & BufferUsage::CPU_WRITE_MASK) { - mapUsage |= BO_MAP_WRITE; - } - - *outMapUsage = mapUsage; - return 0; -} - -int convertToCrosDescriptor(const BufferDescriptorInfo& descriptor, - struct cros_gralloc_buffer_descriptor* outCrosDescriptor) { - outCrosDescriptor->width = descriptor.width; - outCrosDescriptor->height = descriptor.height; - outCrosDescriptor->droid_format = static_cast<int32_t>(descriptor.format); - outCrosDescriptor->droid_usage = descriptor.usage; - outCrosDescriptor->reserved_region_size = 0; - if (descriptor.layerCount > 1) { - drv_log("Failed to convert descriptor. Unsupported layerCount: %d\n", - descriptor.layerCount); - return -EINVAL; - } - if (convertToDrmFormat(descriptor.format, &outCrosDescriptor->drm_format)) { - std::string pixelFormatString = getPixelFormatString(descriptor.format); - drv_log("Failed to convert descriptor. Unsupported format %s\n", pixelFormatString.c_str()); - return -EINVAL; - } - if (convertToBufferUsage(descriptor.usage, &outCrosDescriptor->use_flags)) { - std::string usageString = getUsageString(descriptor.usage); - drv_log("Failed to convert descriptor. Unsupported usage flags %s\n", usageString.c_str()); - return -EINVAL; - } - return 0; -} - -int convertToFenceFd(const hidl_handle& fenceHandle, int* outFenceFd) { - if (!outFenceFd) { - return -EINVAL; - } - - const native_handle_t* nativeHandle = fenceHandle.getNativeHandle(); - if (nativeHandle && nativeHandle->numFds > 1) { - return -EINVAL; - } - - *outFenceFd = (nativeHandle && nativeHandle->numFds == 1) ? nativeHandle->data[0] : -1; - return 0; -} - -int convertToFenceHandle(int fenceFd, hidl_handle* outFenceHandle) { - if (!outFenceHandle) { - return -EINVAL; - } - if (fenceFd < 0) { - return 0; - } - - NATIVE_HANDLE_DECLARE_STORAGE(handleStorage, 1, 0); - auto fenceHandle = native_handle_init(handleStorage, 1, 0); - fenceHandle->data[0] = fenceFd; - - *outFenceHandle = fenceHandle; - return 0; -} - -std::optional<BufferDescriptorInfo> decodeBufferDescriptorInfo(const hidl_vec<uint32_t>& encoded) { - if (encoded.size() != 5) { - drv_log("Failed to decodeBufferDescriptorInfo. Invalid size: %zd.\n", encoded.size()); - return {}; - } - - BufferDescriptorInfo descriptor; - descriptor.width = encoded[0]; - descriptor.height = encoded[1]; - descriptor.layerCount = encoded[2]; - descriptor.format = static_cast<PixelFormat>(encoded[3]); - descriptor.usage = encoded[4]; - return std::move(descriptor); -} - -std::optional<hidl_vec<uint32_t>> encodeBufferDescriptorInfo(const BufferDescriptorInfo& info) { - hidl_vec<uint32_t> encoded; - encoded.resize(5); - encoded[0] = info.width; - encoded[1] = info.height; - encoded[2] = info.layerCount; - encoded[3] = static_cast<uint32_t>(info.format); - encoded[4] = info.usage & std::numeric_limits<uint32_t>::max(); - return std::move(encoded); -} diff --git a/cros_gralloc/gralloc3/CrosGralloc3Utils.h b/cros_gralloc/gralloc3/CrosGralloc3Utils.h deleted file mode 100644 index 0492568..0000000 --- a/cros_gralloc/gralloc3/CrosGralloc3Utils.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <optional> -#include <string> -#include <vector> - -#include <android/hardware/graphics/common/1.2/types.h> -#include <android/hardware/graphics/mapper/3.0/IMapper.h> - -std::string getPixelFormatString(android::hardware::graphics::common::V1_2::PixelFormat format); - -std::string getUsageString( - android::hardware::hidl_bitfield<android::hardware::graphics::common::V1_2::BufferUsage> - usage); - -int convertToDrmFormat(android::hardware::graphics::common::V1_2::PixelFormat format, - uint32_t* outDrmFormat); - -int convertToBufferUsage(uint64_t grallocUsage, uint64_t* outBufferUsage); - -int convertToMapUsage(uint64_t grallocUsage, uint32_t* outMapUsage); - -int convertToCrosDescriptor( - const android::hardware::graphics::mapper::V3_0::IMapper::BufferDescriptorInfo& descriptor, - struct cros_gralloc_buffer_descriptor* outCrosDescriptor); - -int convertToFenceFd(const android::hardware::hidl_handle& fence_handle, int* out_fence_fd); - -int convertToFenceHandle(int fence_fd, android::hardware::hidl_handle* out_fence_handle); - -std::optional<android::hardware::graphics::mapper::V3_0::IMapper::BufferDescriptorInfo> -decodeBufferDescriptorInfo(const android::hardware::hidl_vec<uint32_t>& encoded); - -std::optional<android::hardware::hidl_vec<uint32_t>> encodeBufferDescriptorInfo( - const android::hardware::graphics::mapper::V3_0::IMapper::BufferDescriptorInfo& info); diff --git a/cros_gralloc/gralloc3/android.hardware.graphics.allocator@3.0-service.minigbm.rc b/cros_gralloc/gralloc3/android.hardware.graphics.allocator@3.0-service.minigbm.rc deleted file mode 100644 index 7377cee..0000000 --- a/cros_gralloc/gralloc3/android.hardware.graphics.allocator@3.0-service.minigbm.rc +++ /dev/null @@ -1,14 +0,0 @@ -# -# Copyright 2020 The Chromium OS Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -# - -service vendor.graphics.allocator-3-0 /vendor/bin/hw/android.hardware.graphics.allocator@3.0-service.minigbm - interface android.hardware.graphics.allocator@3.0::IAllocator default - class hal animation - user system - group graphics drmrpc - capabilities SYS_NICE - onrestart restart surfaceflinger - writepid /dev/cpuset/system-background/tasks diff --git a/cros_gralloc/gralloc4/Android.bp b/cros_gralloc/gralloc4/Android.bp index 4d2b542..fb6aca9 100644 --- a/cros_gralloc/gralloc4/Android.bp +++ b/cros_gralloc/gralloc4/Android.bp @@ -23,108 +23,140 @@ package { default_applicable_licenses: ["external_minigbm_license"], } -cc_defaults { - name: "service_minigbm_defaults", - relative_install_path: "hw", - vendor: true, +filegroup { + name: "minigbm_gralloc4_allocator_files", + srcs: [ + "CrosGralloc4Allocator.cc", + "CrosGralloc4AllocatorService.cc", + "CrosGralloc4Utils.cc", + ], +} - vintf_fragments: ["android.hardware.graphics.allocator@4.0.xml"], +filegroup { + name: "minigbm_gralloc4_mapper_files", + srcs: [ + "CrosGralloc4Mapper.cc", + "CrosGralloc4Utils.cc", + ], +} - cflags: [ - "-Wall", - "-Werror", +cc_library { + name: "libminigbm_gralloc4_utils", + defaults: ["minigbm_cros_gralloc_defaults"], + vendor: true, + srcs: [ + "CrosGralloc4Utils.cc", + ], + shared_libs: [ + "android.hardware.graphics.mapper@4.0", + "libgralloctypes", + "libhidlbase", + "libminigbm_gralloc", ], +} + +cc_defaults { + name: "minigbm_gralloc4_common_defaults", + defaults: ["minigbm_cros_gralloc_defaults"], shared_libs: [ - "android.hardware.graphics.allocator@4.0", "android.hardware.graphics.mapper@4.0", - "libbase", - "libcutils", "libgralloctypes", "libhidlbase", - "liblog", - "libsync", + "libbase", "libutils", ], - static_libs: [ - "libdrm", - ], + cflags: ["-Wno-sign-compare"], + relative_install_path: "hw", +} - srcs: [ - "CrosGralloc4Allocator.cc", - "CrosGralloc4AllocatorService.cc", - "CrosGralloc4Utils.cc", - ], +cc_defaults { + name: "minigbm_gralloc4_allocator_defaults", + defaults: ["minigbm_gralloc4_common_defaults"], + + shared_libs: ["android.hardware.graphics.allocator@4.0"], + srcs: [":minigbm_gralloc4_allocator_files"], } cc_binary { name: "android.hardware.graphics.allocator@4.0-service.minigbm", + defaults: ["minigbm_gralloc4_allocator_defaults"], + shared_libs: ["libminigbm_gralloc"], + vintf_fragments: ["android.hardware.graphics.allocator@4.0.xml"], init_rc: ["android.hardware.graphics.allocator@4.0-service.minigbm.rc"], - defaults: ["service_minigbm_defaults"], - static_libs: [ - "libminigbm_cros_gralloc", - ], } cc_binary { name: "android.hardware.graphics.allocator@4.0-service.minigbm_msm", + defaults: ["minigbm_gralloc4_allocator_defaults"], + shared_libs: ["libminigbm_gralloc_msm"], + vintf_fragments: ["android.hardware.graphics.allocator@4.0.xml"], init_rc: ["android.hardware.graphics.allocator@4.0-service.minigbm_msm.rc"], - defaults: ["service_minigbm_defaults"], - static_libs: [ - "libminigbm_cros_gralloc_msm", - ], } -cc_defaults { - name: "impl_minigbm_defaults", - relative_install_path: "hw", - vendor: true, - - vintf_fragments: ["android.hardware.graphics.mapper@4.0.xml"], - - cflags: [ - "-Wall", - "-Werror", - ], - - shared_libs: [ - "android.hardware.graphics.mapper@4.0", - "libbase", - "libcutils", - "libgralloctypes", - "libhidlbase", - "liblog", - "libsync", - "libutils", - ], - - static_libs: [ - "libdrm", - ], +cc_binary { + name: "android.hardware.graphics.allocator@4.0-service.minigbm_arcvm", + defaults: ["minigbm_gralloc4_allocator_defaults"], + shared_libs: ["libminigbm_gralloc_arcvm"], + vintf_fragments: ["android.hardware.graphics.allocator@4.0.xml"], + init_rc: ["android.hardware.graphics.allocator@4.0-service.minigbm_arcvm.rc"], +} - srcs: [ - "CrosGralloc4Mapper.cc", - "CrosGralloc4Utils.cc", - ], +cc_binary { + name: "android.hardware.graphics.allocator@4.0-service.minigbm_intel", + defaults: ["minigbm_gralloc4_allocator_defaults"], + shared_libs: ["libminigbm_gralloc_intel"], + vintf_fragments: ["android.hardware.graphics.allocator@4.0.xml"], + init_rc: ["android.hardware.graphics.allocator@4.0-service.minigbm_intel.rc"], + enabled: false, + arch: { + x86: { + enabled: true, + }, + x86_64: { + enabled: true, + }, + }, } cc_library_shared { name: "android.hardware.graphics.mapper@4.0-impl.minigbm", - defaults: ["impl_minigbm_defaults"], - - static_libs: [ - "libminigbm_cros_gralloc", - ], - + defaults: ["minigbm_gralloc4_common_defaults"], + shared_libs: ["libminigbm_gralloc"], + vintf_fragments: ["android.hardware.graphics.mapper@4.0.xml"], + srcs: [":minigbm_gralloc4_mapper_files"], } cc_library_shared { name: "android.hardware.graphics.mapper@4.0-impl.minigbm_msm", - defaults: ["impl_minigbm_defaults"], + defaults: ["minigbm_gralloc4_common_defaults"], + shared_libs: ["libminigbm_gralloc_msm"], + vintf_fragments: ["android.hardware.graphics.mapper@4.0.xml"], + srcs: [":minigbm_gralloc4_mapper_files"], +} - static_libs: [ - "libminigbm_cros_gralloc_msm", - ], +cc_library_shared { + name: "android.hardware.graphics.mapper@4.0-impl.minigbm_arcvm", + defaults: ["minigbm_gralloc4_common_defaults"], + shared_libs: ["libminigbm_gralloc_arcvm"], + vintf_fragments: ["android.hardware.graphics.mapper@4.0.xml"], + srcs: [":minigbm_gralloc4_mapper_files"], +} +cc_library_shared { + name: "android.hardware.graphics.mapper@4.0-impl.minigbm_intel", + defaults: ["minigbm_gralloc4_common_defaults"], + shared_libs: ["libminigbm_gralloc_intel"], + vintf_fragments: ["android.hardware.graphics.mapper@4.0.xml"], + srcs: [":minigbm_gralloc4_mapper_files"], + enabled: false, + arch: { + x86: { + enabled: true, + }, + x86_64: { + enabled: true, + }, + }, } diff --git a/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc b/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc index e7e5f3a..43c0b0c 100644 --- a/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc +++ b/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc @@ -10,8 +10,11 @@ #include <gralloctypes/Gralloc4.h> #include "cros_gralloc/cros_gralloc_helpers.h" +#include "cros_gralloc/gralloc4/CrosGralloc4Metadata.h" #include "cros_gralloc/gralloc4/CrosGralloc4Utils.h" +using aidl::android::hardware::graphics::common::BlendMode; +using aidl::android::hardware::graphics::common::Dataspace; using android::hardware::hidl_handle; using android::hardware::hidl_vec; using android::hardware::Return; @@ -23,11 +26,40 @@ using android::hardware::graphics::mapper::V4_0::Error; using BufferDescriptorInfo = android::hardware::graphics::mapper::V4_0::IMapper::BufferDescriptorInfo; -CrosGralloc4Allocator::CrosGralloc4Allocator() : mDriver(std::make_unique<cros_gralloc_driver>()) { - if (mDriver->init()) { - drv_log("Failed to initialize driver.\n"); - mDriver = nullptr; +Error CrosGralloc4Allocator::init() { + mDriver = cros_gralloc_driver::get_instance(); + return mDriver ? Error::NONE : Error::NO_RESOURCES; +} + +Error CrosGralloc4Allocator::initializeMetadata( + cros_gralloc_handle_t crosHandle, + const struct cros_gralloc_buffer_descriptor& crosDescriptor) { + if (!mDriver) { + drv_log("Failed to initializeMetadata. Driver is uninitialized.\n"); + return Error::NO_RESOURCES; + } + + if (!crosHandle) { + drv_log("Failed to initializeMetadata. Invalid handle.\n"); + return Error::BAD_BUFFER; } + + void* addr; + uint64_t size; + int ret = mDriver->get_reserved_region(crosHandle, &addr, &size); + if (ret) { + drv_log("Failed to getReservedRegion.\n"); + return Error::NO_RESOURCES; + } + + CrosGralloc4Metadata* crosMetadata = reinterpret_cast<CrosGralloc4Metadata*>(addr); + + snprintf(crosMetadata->name, CROS_GRALLOC4_METADATA_MAX_NAME_SIZE, "%s", + crosDescriptor.name.c_str()); + crosMetadata->dataspace = Dataspace::UNKNOWN; + crosMetadata->blendMode = BlendMode::INVALID; + + return Error::NONE; } Error CrosGralloc4Allocator::allocate(const BufferDescriptorInfo& descriptor, uint32_t* outStride, @@ -46,13 +78,9 @@ Error CrosGralloc4Allocator::allocate(const BufferDescriptorInfo& descriptor, ui return Error::UNSUPPORTED; } - bool supported = mDriver->is_supported(&crosDescriptor); - if (!supported && (descriptor.usage & BufferUsage::COMPOSER_OVERLAY)) { - crosDescriptor.use_flags &= ~BO_USE_SCANOUT; - supported = mDriver->is_supported(&crosDescriptor); - } + crosDescriptor.reserved_region_size += sizeof(CrosGralloc4Metadata); - if (!supported) { + if (!mDriver->is_supported(&crosDescriptor)) { std::string drmFormatString = get_drm_format_string(crosDescriptor.drm_format); std::string pixelFormatString = getPixelFormatString(descriptor.format); std::string usageString = getUsageString(descriptor.usage); @@ -61,18 +89,23 @@ Error CrosGralloc4Allocator::allocate(const BufferDescriptorInfo& descriptor, ui return Error::UNSUPPORTED; } - buffer_handle_t handle; + native_handle_t* handle; int ret = mDriver->allocate(&crosDescriptor, &handle); if (ret) { return Error::NO_RESOURCES; } cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(handle); - if (!crosHandle) { - return Error::NO_RESOURCES; + + Error error = initializeMetadata(crosHandle, crosDescriptor); + if (error != Error::NONE) { + mDriver->release(handle); + native_handle_close(handle); + native_handle_delete(handle); + return error; } - *outHandle = handle; + outHandle->setTo(handle, /*shouldOwn=*/true); *outStride = crosHandle->pixel_stride; return Error::NONE; diff --git a/cros_gralloc/gralloc4/CrosGralloc4Allocator.h b/cros_gralloc/gralloc4/CrosGralloc4Allocator.h index 21ad7ad..9c1c783 100644 --- a/cros_gralloc/gralloc4/CrosGralloc4Allocator.h +++ b/cros_gralloc/gralloc4/CrosGralloc4Allocator.h @@ -8,19 +8,27 @@ #include <android/hardware/graphics/mapper/4.0/IMapper.h> #include "cros_gralloc/cros_gralloc_driver.h" +#include "cros_gralloc/cros_gralloc_helpers.h" +#include "cros_gralloc/gralloc4/CrosGralloc4Metadata.h" class CrosGralloc4Allocator : public android::hardware::graphics::allocator::V4_0::IAllocator { public: - CrosGralloc4Allocator(); + CrosGralloc4Allocator() = default; android::hardware::Return<void> allocate(const android::hardware::hidl_vec<uint8_t>& descriptor, uint32_t count, allocate_cb hidl_cb) override; + android::hardware::graphics::mapper::V4_0::Error init(); + private: + android::hardware::graphics::mapper::V4_0::Error initializeMetadata( + cros_gralloc_handle_t crosHandle, + const struct cros_gralloc_buffer_descriptor& crosDescriptor); + android::hardware::graphics::mapper::V4_0::Error allocate( const android::hardware::graphics::mapper::V4_0::IMapper::BufferDescriptorInfo& description, uint32_t* outStride, android::hardware::hidl_handle* outHandle); - std::unique_ptr<cros_gralloc_driver> mDriver; + cros_gralloc_driver* mDriver = nullptr; }; diff --git a/cros_gralloc/gralloc4/CrosGralloc4AllocatorService.cc b/cros_gralloc/gralloc4/CrosGralloc4AllocatorService.cc index 5b79860..99bc92e 100644 --- a/cros_gralloc/gralloc4/CrosGralloc4AllocatorService.cc +++ b/cros_gralloc/gralloc4/CrosGralloc4AllocatorService.cc @@ -13,18 +13,23 @@ using android::sp; using android::hardware::configureRpcThreadpool; using android::hardware::joinRpcThreadpool; -using android::hardware::graphics::allocator::V4_0::IAllocator; +using android::hardware::graphics::mapper::V4_0::Error; int main(int, char**) { - sp<IAllocator> allocator = new CrosGralloc4Allocator(); + sp<CrosGralloc4Allocator> allocator = new CrosGralloc4Allocator(); + if (allocator->init() != Error::NONE) { + ALOGE("Failed to initialize IAllocator 4.0 service."); + return -EINVAL; + } + configureRpcThreadpool(4, true /* callerWillJoin */); if (allocator->registerAsService() != android::NO_ERROR) { - ALOGE("failed to register graphics IAllocator 4.0 service"); + ALOGE("Failed to register graphics IAllocator 4.0 service."); return -EINVAL; } - ALOGI("graphics IAllocator 4.0 service is initialized"); + ALOGI("IAllocator 4.0 service is initialized."); android::hardware::joinRpcThreadpool(); - ALOGI("graphics IAllocator 4.0 service is terminating"); + ALOGI("IAllocator 4.0 service is terminating."); return 0; } diff --git a/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc b/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc index 1bfd442..cc2c4d5 100644 --- a/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc +++ b/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc @@ -16,8 +16,6 @@ #include "cros_gralloc/cros_gralloc_helpers.h" #include "cros_gralloc/gralloc4/CrosGralloc4Utils.h" -#include "helpers.h" - using aidl::android::hardware::graphics::common::BlendMode; using aidl::android::hardware::graphics::common::Dataspace; using aidl::android::hardware::graphics::common::PlaneLayout; @@ -31,62 +29,6 @@ using android::hardware::graphics::common::V1_2::PixelFormat; using android::hardware::graphics::mapper::V4_0::Error; using android::hardware::graphics::mapper::V4_0::IMapper; -namespace { - -// Provides a single instance of cros_gralloc_driver to all active instances of -// CrosGralloc4Mapper in a single process while destroying the cros_gralloc_driver -// when there are no active instances of CrosGralloc4Mapper. -class DriverProvider { - public: - static DriverProvider* Get() { - static DriverProvider* instance = new DriverProvider(); - return instance; - } - - cros_gralloc_driver* GetAndReferenceDriver() { - std::lock_guard<std::mutex> lock(mMutex); - if (!mDriver) { - mDriver = std::make_unique<cros_gralloc_driver>(); - if (mDriver->init()) { - drv_log("Failed to initialize driver.\n"); - mDriver.reset(); - return nullptr; - } - } - - ++mReferenceCount; - return mDriver.get(); - } - - void UnreferenceDriver() { - std::lock_guard<std::mutex> lock(mMutex); - - --mReferenceCount; - - if (mReferenceCount == 0) { - mDriver.reset(); - } - } - - private: - DriverProvider() = default; - - std::mutex mMutex; - std::unique_ptr<cros_gralloc_driver> mDriver; - std::size_t mReferenceCount = 0; -}; - -} // namespace - -CrosGralloc4Mapper::CrosGralloc4Mapper() { - mDriver = DriverProvider::Get()->GetAndReferenceDriver(); -} - -CrosGralloc4Mapper::~CrosGralloc4Mapper() { - mDriver = nullptr; - DriverProvider::Get()->UnreferenceDriver(); -} - Return<void> CrosGralloc4Mapper::createDescriptor(const BufferDescriptorInfo& description, createDescriptor_cb hidlCb) { hidl_vec<uint8_t> descriptor; @@ -448,13 +390,7 @@ Return<void> CrosGralloc4Mapper::isSupported(const BufferDescriptorInfo& descrip return Void(); } - bool supported = mDriver->is_supported(&crosDescriptor); - if (!supported) { - crosDescriptor.use_flags &= ~BO_USE_SCANOUT; - supported = mDriver->is_supported(&crosDescriptor); - } - - hidlCb(Error::NONE, supported); + hidlCb(Error::NONE, mDriver->is_supported(&crosDescriptor)); return Void(); } @@ -482,11 +418,13 @@ Return<void> CrosGralloc4Mapper::get(void* rawHandle, const MetadataType& metada return Void(); } - get(crosHandle, metadataType, hidlCb); + mDriver->with_buffer(crosHandle, [&, this](cros_gralloc_buffer* crosBuffer) { + get(crosBuffer, metadataType, hidlCb); + }); return Void(); } -Return<void> CrosGralloc4Mapper::get(cros_gralloc_handle_t crosHandle, +Return<void> CrosGralloc4Mapper::get(const cros_gralloc_buffer* crosBuffer, const MetadataType& metadataType, get_cb hidlCb) { hidl_vec<uint8_t> encodedMetadata; @@ -496,40 +434,54 @@ Return<void> CrosGralloc4Mapper::get(cros_gralloc_handle_t crosHandle, return Void(); } - if (!crosHandle) { - drv_log("Failed to get. Invalid handle.\n"); + if (!crosBuffer) { + drv_log("Failed to get. Invalid buffer.\n"); hidlCb(Error::BAD_BUFFER, encodedMetadata); return Void(); } + const CrosGralloc4Metadata* crosMetadata = nullptr; + if (metadataType == android::gralloc4::MetadataType_BlendMode || + metadataType == android::gralloc4::MetadataType_Cta861_3 || + metadataType == android::gralloc4::MetadataType_Dataspace || + metadataType == android::gralloc4::MetadataType_Name || + metadataType == android::gralloc4::MetadataType_Smpte2086) { + Error error = getMetadata(crosBuffer, &crosMetadata); + if (error != Error::NONE) { + drv_log("Failed to get. Failed to get buffer metadata.\n"); + hidlCb(Error::NO_RESOURCES, encodedMetadata); + return Void(); + } + } + android::status_t status = android::NO_ERROR; if (metadataType == android::gralloc4::MetadataType_BufferId) { - status = android::gralloc4::encodeBufferId(crosHandle->id, &encodedMetadata); + status = android::gralloc4::encodeBufferId(crosBuffer->get_id(), &encodedMetadata); } else if (metadataType == android::gralloc4::MetadataType_Name) { - const char* name = (const char*)(&crosHandle->data[crosHandle->name_offset]); - status = android::gralloc4::encodeName(name, &encodedMetadata); + status = android::gralloc4::encodeName(crosMetadata->name, &encodedMetadata); } else if (metadataType == android::gralloc4::MetadataType_Width) { - status = android::gralloc4::encodeWidth(crosHandle->width, &encodedMetadata); + status = android::gralloc4::encodeWidth(crosBuffer->get_width(), &encodedMetadata); } else if (metadataType == android::gralloc4::MetadataType_Height) { - status = android::gralloc4::encodeHeight(crosHandle->height, &encodedMetadata); + status = android::gralloc4::encodeHeight(crosBuffer->get_height(), &encodedMetadata); } else if (metadataType == android::gralloc4::MetadataType_LayerCount) { status = android::gralloc4::encodeLayerCount(1, &encodedMetadata); } else if (metadataType == android::gralloc4::MetadataType_PixelFormatRequested) { - PixelFormat pixelFormat = static_cast<PixelFormat>(crosHandle->droid_format); + PixelFormat pixelFormat = static_cast<PixelFormat>(crosBuffer->get_android_format()); status = android::gralloc4::encodePixelFormatRequested(pixelFormat, &encodedMetadata); } else if (metadataType == android::gralloc4::MetadataType_PixelFormatFourCC) { status = android::gralloc4::encodePixelFormatFourCC( - drv_get_standard_fourcc(crosHandle->format), &encodedMetadata); + drv_get_standard_fourcc(crosBuffer->get_format()), &encodedMetadata); } else if (metadataType == android::gralloc4::MetadataType_PixelFormatModifier) { - status = android::gralloc4::encodePixelFormatModifier(crosHandle->format_modifier, + status = android::gralloc4::encodePixelFormatModifier(crosBuffer->get_format_modifier(), &encodedMetadata); } else if (metadataType == android::gralloc4::MetadataType_Usage) { - uint64_t usage = static_cast<uint64_t>(crosHandle->usage); - status = android::gralloc4::encodeUsage(usage, &encodedMetadata); + status = android::gralloc4::encodeUsage(crosBuffer->get_android_usage(), &encodedMetadata); } else if (metadataType == android::gralloc4::MetadataType_AllocationSize) { - status = android::gralloc4::encodeAllocationSize(crosHandle->total_size, &encodedMetadata); + status = android::gralloc4::encodeAllocationSize(crosBuffer->get_total_size(), + &encodedMetadata); } else if (metadataType == android::gralloc4::MetadataType_ProtectedContent) { - uint64_t hasProtectedContent = crosHandle->usage & BufferUsage::PROTECTED ? 1 : 0; + uint64_t hasProtectedContent = + crosBuffer->get_android_usage() & BufferUsage::PROTECTED ? 1 : 0; status = android::gralloc4::encodeProtectedContent(hasProtectedContent, &encodedMetadata); } else if (metadataType == android::gralloc4::MetadataType_Compression) { status = android::gralloc4::encodeCompression(android::gralloc4::Compression_None, @@ -542,38 +494,43 @@ Return<void> CrosGralloc4Mapper::get(cros_gralloc_handle_t crosHandle, &encodedMetadata); } else if (metadataType == android::gralloc4::MetadataType_PlaneLayouts) { std::vector<PlaneLayout> planeLayouts; - getPlaneLayouts(crosHandle->format, &planeLayouts); + getPlaneLayouts(crosBuffer->get_format(), &planeLayouts); for (size_t plane = 0; plane < planeLayouts.size(); plane++) { PlaneLayout& planeLayout = planeLayouts[plane]; - planeLayout.offsetInBytes = crosHandle->offsets[plane]; - planeLayout.strideInBytes = crosHandle->strides[plane]; - planeLayout.totalSizeInBytes = crosHandle->sizes[plane]; - planeLayout.widthInSamples = crosHandle->width / planeLayout.horizontalSubsampling; - planeLayout.heightInSamples = crosHandle->height / planeLayout.verticalSubsampling; + planeLayout.offsetInBytes = crosBuffer->get_plane_offset(plane); + planeLayout.strideInBytes = crosBuffer->get_plane_stride(plane); + planeLayout.totalSizeInBytes = crosBuffer->get_plane_size(plane); + planeLayout.widthInSamples = + crosBuffer->get_width() / planeLayout.horizontalSubsampling; + planeLayout.heightInSamples = + crosBuffer->get_height() / planeLayout.verticalSubsampling; } status = android::gralloc4::encodePlaneLayouts(planeLayouts, &encodedMetadata); } else if (metadataType == android::gralloc4::MetadataType_Crop) { + const uint32_t numPlanes = crosBuffer->get_num_planes(); + const uint32_t w = crosBuffer->get_width(); + const uint32_t h = crosBuffer->get_height(); std::vector<aidl::android::hardware::graphics::common::Rect> crops; - for (size_t plane = 0; plane < crosHandle->num_planes; plane++) { + for (uint32_t plane = 0; plane < numPlanes; plane++) { aidl::android::hardware::graphics::common::Rect crop; crop.left = 0; crop.top = 0; - crop.right = crosHandle->width; - crop.bottom = crosHandle->height; + crop.right = w; + crop.bottom = h; crops.push_back(crop); } status = android::gralloc4::encodeCrop(crops, &encodedMetadata); } else if (metadataType == android::gralloc4::MetadataType_Dataspace) { - status = android::gralloc4::encodeDataspace(Dataspace::UNKNOWN, &encodedMetadata); + status = android::gralloc4::encodeDataspace(crosMetadata->dataspace, &encodedMetadata); } else if (metadataType == android::gralloc4::MetadataType_BlendMode) { - status = android::gralloc4::encodeBlendMode(BlendMode::INVALID, &encodedMetadata); + status = android::gralloc4::encodeBlendMode(crosMetadata->blendMode, &encodedMetadata); } else if (metadataType == android::gralloc4::MetadataType_Smpte2086) { - status = android::gralloc4::encodeSmpte2086(std::nullopt, &encodedMetadata); + status = android::gralloc4::encodeSmpte2086(crosMetadata->smpte2086, &encodedMetadata); } else if (metadataType == android::gralloc4::MetadataType_Cta861_3) { - status = android::gralloc4::encodeCta861_3(std::nullopt, &encodedMetadata); + status = android::gralloc4::encodeCta861_3(crosMetadata->cta861_3, &encodedMetadata); } else if (metadataType == android::gralloc4::MetadataType_Smpte2094_40) { status = android::gralloc4::encodeSmpte2094_40(std::nullopt, &encodedMetadata); } else { @@ -592,7 +549,7 @@ Return<void> CrosGralloc4Mapper::get(cros_gralloc_handle_t crosHandle, } Return<Error> CrosGralloc4Mapper::set(void* rawHandle, const MetadataType& metadataType, - const hidl_vec<uint8_t>& /*metadata*/) { + const hidl_vec<uint8_t>& encodedMetadata) { if (!mDriver) { drv_log("Failed to set. Driver is uninitialized.\n"); return Error::NO_RESOURCES; @@ -626,7 +583,68 @@ Return<Error> CrosGralloc4Mapper::set(void* rawHandle, const MetadataType& metad return Error::BAD_VALUE; } - return Error::UNSUPPORTED; + if (metadataType != android::gralloc4::MetadataType_BlendMode && + metadataType != android::gralloc4::MetadataType_Cta861_3 && + metadataType != android::gralloc4::MetadataType_Dataspace && + metadataType != android::gralloc4::MetadataType_Smpte2086) { + return Error::UNSUPPORTED; + } + + Error error = Error::NONE; + mDriver->with_buffer(crosHandle, [&, this](cros_gralloc_buffer* crosBuffer) { + error = set(crosBuffer, metadataType, encodedMetadata); + }); + + return error; +} + +Error CrosGralloc4Mapper::set(cros_gralloc_buffer* crosBuffer, const MetadataType& metadataType, + const android::hardware::hidl_vec<uint8_t>& encodedMetadata) { + if (!mDriver) { + drv_log("Failed to set. Driver is uninitialized.\n"); + return Error::NO_RESOURCES; + } + + if (!crosBuffer) { + drv_log("Failed to set. Invalid buffer.\n"); + return Error::BAD_BUFFER; + } + + CrosGralloc4Metadata* crosMetadata = nullptr; + + Error error = getMutableMetadata(crosBuffer, &crosMetadata); + if (error != Error::NONE) { + drv_log("Failed to set. Failed to get buffer metadata.\n"); + return Error::UNSUPPORTED; + } + + if (metadataType == android::gralloc4::MetadataType_BlendMode) { + auto status = android::gralloc4::decodeBlendMode(encodedMetadata, &crosMetadata->blendMode); + if (status != android::NO_ERROR) { + drv_log("Failed to set. Failed to decode blend mode.\n"); + return Error::UNSUPPORTED; + } + } else if (metadataType == android::gralloc4::MetadataType_Cta861_3) { + auto status = android::gralloc4::decodeCta861_3(encodedMetadata, &crosMetadata->cta861_3); + if (status != android::NO_ERROR) { + drv_log("Failed to set. Failed to decode cta861_3.\n"); + return Error::UNSUPPORTED; + } + } else if (metadataType == android::gralloc4::MetadataType_Dataspace) { + auto status = android::gralloc4::decodeDataspace(encodedMetadata, &crosMetadata->dataspace); + if (status != android::NO_ERROR) { + drv_log("Failed to set. Failed to decode dataspace.\n"); + return Error::UNSUPPORTED; + } + } else if (metadataType == android::gralloc4::MetadataType_Smpte2086) { + auto status = android::gralloc4::decodeSmpte2086(encodedMetadata, &crosMetadata->smpte2086); + if (status != android::NO_ERROR) { + drv_log("Failed to set. Failed to decode smpte2086.\n"); + return Error::UNSUPPORTED; + } + } + + return Error::NONE; } int CrosGralloc4Mapper::getResolvedDrmFormat(PixelFormat pixelFormat, uint64_t bufferUsage, @@ -851,25 +869,25 @@ Return<void> CrosGralloc4Mapper::listSupportedMetadataTypes(listSupportedMetadat android::gralloc4::MetadataType_Dataspace, "", /*isGettable=*/true, - /*isSettable=*/false, + /*isSettable=*/true, }, { android::gralloc4::MetadataType_BlendMode, "", /*isGettable=*/true, - /*isSettable=*/false, + /*isSettable=*/true, }, { android::gralloc4::MetadataType_Smpte2086, "", /*isGettable=*/true, - /*isSettable=*/false, + /*isSettable=*/true, }, { android::gralloc4::MetadataType_Cta861_3, "", /*isGettable=*/true, - /*isSettable=*/false, + /*isSettable=*/true, }, { android::gralloc4::MetadataType_Smpte2094_40, @@ -906,10 +924,13 @@ Return<void> CrosGralloc4Mapper::dumpBuffer(void* rawHandle, dumpBuffer_cb hidlC return Void(); } - return dumpBuffer(crosHandle, hidlCb); + mDriver->with_buffer(crosHandle, [&, this](cros_gralloc_buffer* crosBuffer) { + dumpBuffer(crosBuffer, hidlCb); + }); + return Void(); } -Return<void> CrosGralloc4Mapper::dumpBuffer(cros_gralloc_handle_t crosHandle, +Return<void> CrosGralloc4Mapper::dumpBuffer(const cros_gralloc_buffer* crosBuffer, dumpBuffer_cb hidlCb) { BufferDump bufferDump; @@ -919,12 +940,6 @@ Return<void> CrosGralloc4Mapper::dumpBuffer(cros_gralloc_handle_t crosHandle, return Void(); } - if (!crosHandle) { - drv_log("Failed to dumpBuffer. Invalid handle.\n"); - hidlCb(Error::BAD_BUFFER, bufferDump); - return Void(); - } - std::vector<MetadataDump> metadataDumps; MetadataType metadataType = android::gralloc4::MetadataType_BufferId; @@ -936,55 +951,55 @@ Return<void> CrosGralloc4Mapper::dumpBuffer(cros_gralloc_handle_t crosHandle, }; metadataType = android::gralloc4::MetadataType_BufferId; - get(crosHandle, metadataType, metadata_get_callback); + get(crosBuffer, metadataType, metadata_get_callback); metadataType = android::gralloc4::MetadataType_Name; - get(crosHandle, metadataType, metadata_get_callback); + get(crosBuffer, metadataType, metadata_get_callback); metadataType = android::gralloc4::MetadataType_Width; - get(crosHandle, metadataType, metadata_get_callback); + get(crosBuffer, metadataType, metadata_get_callback); metadataType = android::gralloc4::MetadataType_Height; - get(crosHandle, metadataType, metadata_get_callback); + get(crosBuffer, metadataType, metadata_get_callback); metadataType = android::gralloc4::MetadataType_LayerCount; - get(crosHandle, metadataType, metadata_get_callback); + get(crosBuffer, metadataType, metadata_get_callback); metadataType = android::gralloc4::MetadataType_PixelFormatRequested; - get(crosHandle, metadataType, metadata_get_callback); + get(crosBuffer, metadataType, metadata_get_callback); metadataType = android::gralloc4::MetadataType_PixelFormatFourCC; - get(crosHandle, metadataType, metadata_get_callback); + get(crosBuffer, metadataType, metadata_get_callback); metadataType = android::gralloc4::MetadataType_PixelFormatModifier; - get(crosHandle, metadataType, metadata_get_callback); + get(crosBuffer, metadataType, metadata_get_callback); metadataType = android::gralloc4::MetadataType_Usage; - get(crosHandle, metadataType, metadata_get_callback); + get(crosBuffer, metadataType, metadata_get_callback); metadataType = android::gralloc4::MetadataType_AllocationSize; - get(crosHandle, metadataType, metadata_get_callback); + get(crosBuffer, metadataType, metadata_get_callback); metadataType = android::gralloc4::MetadataType_ProtectedContent; - get(crosHandle, metadataType, metadata_get_callback); + get(crosBuffer, metadataType, metadata_get_callback); metadataType = android::gralloc4::MetadataType_Compression; - get(crosHandle, metadataType, metadata_get_callback); + get(crosBuffer, metadataType, metadata_get_callback); metadataType = android::gralloc4::MetadataType_Interlaced; - get(crosHandle, metadataType, metadata_get_callback); + get(crosBuffer, metadataType, metadata_get_callback); metadataType = android::gralloc4::MetadataType_ChromaSiting; - get(crosHandle, metadataType, metadata_get_callback); + get(crosBuffer, metadataType, metadata_get_callback); metadataType = android::gralloc4::MetadataType_PlaneLayouts; - get(crosHandle, metadataType, metadata_get_callback); + get(crosBuffer, metadataType, metadata_get_callback); metadataType = android::gralloc4::MetadataType_Dataspace; - get(crosHandle, metadataType, metadata_get_callback); + get(crosBuffer, metadataType, metadata_get_callback); metadataType = android::gralloc4::MetadataType_BlendMode; - get(crosHandle, metadataType, metadata_get_callback); + get(crosBuffer, metadataType, metadata_get_callback); bufferDump.metadataDump = metadataDumps; hidlCb(Error::NONE, bufferDump); @@ -1002,22 +1017,89 @@ Return<void> CrosGralloc4Mapper::dumpBuffers(dumpBuffers_cb hidlCb) { Error error = Error::NONE; - auto handleCallback = [&](cros_gralloc_handle_t crosHandle) { - auto dumpBufferCallback = [&](Error err, BufferDump bufferDump) { - error = err; - if (error == Error::NONE) { - bufferDumps.push_back(bufferDump); - } - }; - - dumpBuffer(crosHandle, dumpBufferCallback); + const auto dumpBufferCallback = [&](Error err, BufferDump bufferDump) { + error = err; + if (error == Error::NONE) { + bufferDumps.push_back(bufferDump); + } }; - mDriver->for_each_handle(handleCallback); + + mDriver->with_each_buffer( + [&](cros_gralloc_buffer* crosBuffer) { dumpBuffer(crosBuffer, dumpBufferCallback); }); hidlCb(error, bufferDumps); return Void(); } +Error CrosGralloc4Mapper::getReservedRegionArea(const cros_gralloc_buffer* crosBuffer, + ReservedRegionArea area, void** outAddr, + uint64_t* outSize) { + if (!mDriver) { + drv_log("Failed to getReservedRegionArea. Driver is uninitialized.\n"); + return Error::NO_RESOURCES; + } + + if (!crosBuffer) { + drv_log("Failed to getReservedRegionArea. Invalid buffer.\n"); + return Error::BAD_BUFFER; + } + + int ret = crosBuffer->get_reserved_region(outAddr, outSize); + if (ret) { + drv_log("Failed to getReservedRegionArea.\n"); + *outAddr = nullptr; + *outSize = 0; + return Error::NO_RESOURCES; + } + + switch (area) { + case ReservedRegionArea::MAPPER4_METADATA: { + // CrosGralloc4Metadata resides at the beginning reserved region. + *outSize = sizeof(CrosGralloc4Metadata); + break; + } + case ReservedRegionArea::USER_METADATA: { + // User metadata resides after the CrosGralloc4Metadata. + *outAddr = reinterpret_cast<void*>(reinterpret_cast<char*>(*outAddr) + + sizeof(CrosGralloc4Metadata)); + *outSize = *outSize - sizeof(CrosGralloc4Metadata); + break; + } + } + + return Error::NONE; +} + +Error CrosGralloc4Mapper::getMetadata(const cros_gralloc_buffer* crosBuffer, + const CrosGralloc4Metadata** outMetadata) { + void* addr = nullptr; + uint64_t size; + + Error error = + getReservedRegionArea(crosBuffer, ReservedRegionArea::MAPPER4_METADATA, &addr, &size); + if (error != Error::NONE) { + return error; + } + + *outMetadata = reinterpret_cast<const CrosGralloc4Metadata*>(addr); + return Error::NONE; +} + +Error CrosGralloc4Mapper::getMutableMetadata(cros_gralloc_buffer* crosBuffer, + CrosGralloc4Metadata** outMetadata) { + void* addr = nullptr; + uint64_t size; + + Error error = + getReservedRegionArea(crosBuffer, ReservedRegionArea::MAPPER4_METADATA, &addr, &size); + if (error != Error::NONE) { + return error; + } + + *outMetadata = reinterpret_cast<CrosGralloc4Metadata*>(addr); + return Error::NONE; +} + Return<void> CrosGralloc4Mapper::getReservedRegion(void* rawHandle, getReservedRegion_cb hidlCb) { if (!mDriver) { drv_log("Failed to getReservedRegion. Driver is uninitialized.\n"); @@ -1041,9 +1123,15 @@ Return<void> CrosGralloc4Mapper::getReservedRegion(void* rawHandle, getReservedR void* reservedRegionAddr = nullptr; uint64_t reservedRegionSize = 0; - int ret = mDriver->get_reserved_region(bufferHandle, &reservedRegionAddr, &reservedRegionSize); - if (ret) { - drv_log("Failed to getReservedRegion.\n"); + + Error error = Error::NONE; + mDriver->with_buffer(crosHandle, [&, this](cros_gralloc_buffer* crosBuffer) { + error = getReservedRegionArea(crosBuffer, ReservedRegionArea::USER_METADATA, + &reservedRegionAddr, &reservedRegionSize); + }); + + if (error != Error::NONE) { + drv_log("Failed to getReservedRegion. Failed to getReservedRegionArea.\n"); hidlCb(Error::BAD_BUFFER, nullptr, 0); return Void(); } diff --git a/cros_gralloc/gralloc4/CrosGralloc4Mapper.h b/cros_gralloc/gralloc4/CrosGralloc4Mapper.h index 3c159a2..1734feb 100644 --- a/cros_gralloc/gralloc4/CrosGralloc4Mapper.h +++ b/cros_gralloc/gralloc4/CrosGralloc4Mapper.h @@ -8,11 +8,11 @@ #include "cros_gralloc/cros_gralloc_driver.h" #include "cros_gralloc/cros_gralloc_handle.h" +#include "cros_gralloc/gralloc4/CrosGralloc4Metadata.h" class CrosGralloc4Mapper : public android::hardware::graphics::mapper::V4_0::IMapper { public: - CrosGralloc4Mapper(); - ~CrosGralloc4Mapper(); + CrosGralloc4Mapper() = default; android::hardware::Return<void> createDescriptor(const BufferDescriptorInfo& description, createDescriptor_cb hidlCb) override; @@ -66,16 +66,38 @@ class CrosGralloc4Mapper : public android::hardware::graphics::mapper::V4_0::IMa getReservedRegion_cb hidlCb) override; private: - android::hardware::Return<void> get(cros_gralloc_handle_t crosHandle, + enum class ReservedRegionArea { + /* CrosGralloc4Metadata */ + MAPPER4_METADATA, + + /* External user metadata */ + USER_METADATA, + }; + + android::hardware::graphics::mapper::V4_0::Error getReservedRegionArea( + const cros_gralloc_buffer* crosBuffer, ReservedRegionArea area, void** outAddr, + uint64_t* outSize); + + android::hardware::graphics::mapper::V4_0::Error getMetadata( + const cros_gralloc_buffer* crosBuffer, const CrosGralloc4Metadata** outMetadata); + + android::hardware::graphics::mapper::V4_0::Error getMutableMetadata( + cros_gralloc_buffer* crosBuffer, CrosGralloc4Metadata** outMetadata); + + android::hardware::Return<void> get(const cros_gralloc_buffer* crosBuffer, const MetadataType& metadataType, get_cb hidlCb); - android::hardware::Return<void> dumpBuffer(cros_gralloc_handle_t crosHandle, + android::hardware::graphics::mapper::V4_0::Error set( + cros_gralloc_buffer* crosBuffer, const MetadataType& metadataType, + const android::hardware::hidl_vec<uint8_t>& metadata); + + android::hardware::Return<void> dumpBuffer(const cros_gralloc_buffer* crosBuffer, dumpBuffer_cb hidlCb); int getResolvedDrmFormat(android::hardware::graphics::common::V1_2::PixelFormat pixelFormat, uint64_t bufferUsage, uint32_t* outDrmFormat); - cros_gralloc_driver* mDriver = nullptr; + cros_gralloc_driver* mDriver = cros_gralloc_driver::get_instance(); }; extern "C" android::hardware::graphics::mapper::V4_0::IMapper* HIDL_FETCH_IMapper(const char* name); diff --git a/cros_gralloc/gralloc4/CrosGralloc4Metadata.h b/cros_gralloc/gralloc4/CrosGralloc4Metadata.h new file mode 100644 index 0000000..c908e35 --- /dev/null +++ b/cros_gralloc/gralloc4/CrosGralloc4Metadata.h @@ -0,0 +1,37 @@ +/* + * Copyright 2022 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef CROSGRALLOC4METADATA_H +#define CROSGRALLOC4METADATA_H + +#include <aidl/android/hardware/graphics/common/BlendMode.h> +#include <aidl/android/hardware/graphics/common/Cta861_3.h> +#include <aidl/android/hardware/graphics/common/Dataspace.h> +#include <aidl/android/hardware/graphics/common/Smpte2086.h> + +#define CROS_GRALLOC4_METADATA_MAX_NAME_SIZE 1024 + +/* + * The metadata for cros_gralloc_buffer-s that should reside in a shared memory region + * instead of directly in cros_gralloc_handle-s. + * + * Any metadata that is mutable must be stored in this shared memory region as + * cros_gralloc_handle-s can not be tracked and updated across processes. + */ +struct CrosGralloc4Metadata { + /* + * Name is stored in the shared memory metadata to simplify cros_gralloc_handle + * creation. This allows us to keep handles small while avoiding variable sized + * handles. + */ + char name[CROS_GRALLOC4_METADATA_MAX_NAME_SIZE]; + aidl::android::hardware::graphics::common::BlendMode blendMode; + aidl::android::hardware::graphics::common::Dataspace dataspace; + std::optional<aidl::android::hardware::graphics::common::Cta861_3> cta861_3; + std::optional<aidl::android::hardware::graphics::common::Smpte2086> smpte2086; +}; + +#endif diff --git a/cros_gralloc/gralloc4/CrosGralloc4Utils.cc b/cros_gralloc/gralloc4/CrosGralloc4Utils.cc index 9bc27cb..6c07189 100644 --- a/cros_gralloc/gralloc4/CrosGralloc4Utils.cc +++ b/cros_gralloc/gralloc4/CrosGralloc4Utils.cc @@ -30,283 +30,28 @@ using BufferDescriptorInfo = android::hardware::graphics::mapper::V4_0::IMapper::BufferDescriptorInfo; std::string getPixelFormatString(PixelFormat format) { - switch (format) { - case PixelFormat::BGRA_8888: - return "PixelFormat::BGRA_8888"; - case PixelFormat::BLOB: - return "PixelFormat::BLOB"; - case PixelFormat::DEPTH_16: - return "PixelFormat::DEPTH_16"; - case PixelFormat::DEPTH_24: - return "PixelFormat::DEPTH_24"; - case PixelFormat::DEPTH_24_STENCIL_8: - return "PixelFormat::DEPTH_24_STENCIL_8"; - case PixelFormat::DEPTH_32F: - return "PixelFormat::DEPTH_24"; - case PixelFormat::DEPTH_32F_STENCIL_8: - return "PixelFormat::DEPTH_24_STENCIL_8"; - case PixelFormat::HSV_888: - return "PixelFormat::HSV_888"; - case PixelFormat::IMPLEMENTATION_DEFINED: - return "PixelFormat::IMPLEMENTATION_DEFINED"; - case PixelFormat::RAW10: - return "PixelFormat::RAW10"; - case PixelFormat::RAW12: - return "PixelFormat::RAW12"; - case PixelFormat::RAW16: - return "PixelFormat::RAW16"; - case PixelFormat::RAW_OPAQUE: - return "PixelFormat::RAW_OPAQUE"; - case PixelFormat::RGBA_1010102: - return "PixelFormat::RGBA_1010102"; - case PixelFormat::RGBA_8888: - return "PixelFormat::RGBA_8888"; - case PixelFormat::RGBA_FP16: - return "PixelFormat::RGBA_FP16"; - case PixelFormat::RGBX_8888: - return "PixelFormat::RGBX_8888"; - case PixelFormat::RGB_565: - return "PixelFormat::RGB_565"; - case PixelFormat::RGB_888: - return "PixelFormat::RGB_888"; - case PixelFormat::STENCIL_8: - return "PixelFormat::STENCIL_8"; - case PixelFormat::Y16: - return "PixelFormat::Y16"; - case PixelFormat::Y8: - return "PixelFormat::Y8"; - case PixelFormat::YCBCR_420_888: - return "PixelFormat::YCBCR_420_888"; - case PixelFormat::YCBCR_422_I: - return "PixelFormat::YCBCR_422_I"; - case PixelFormat::YCBCR_422_SP: - return "PixelFormat::YCBCR_422_SP"; - case PixelFormat::YCBCR_P010: - return "PixelFormat::YCBCR_P010"; - case PixelFormat::YCRCB_420_SP: - return "PixelFormat::YCRCB_420_SP"; - case PixelFormat::YV12: - return "PixelFormat::YV12"; - } - return android::base::StringPrintf("PixelFormat::Unknown(%d)", static_cast<uint32_t>(format)); + return android::hardware::graphics::common::V1_2::toString(format); } std::string getUsageString(hidl_bitfield<BufferUsage> bufferUsage) { - using Underlying = typename std::underlying_type<BufferUsage>::type; - - Underlying usage = static_cast<Underlying>(bufferUsage); - - std::vector<std::string> usages; - if (usage & BufferUsage::CAMERA_INPUT) { - usage &= ~static_cast<Underlying>(BufferUsage::CAMERA_INPUT); - usages.push_back("BufferUsage::CAMERA_INPUT"); - } - if (usage & BufferUsage::CAMERA_OUTPUT) { - usage &= ~static_cast<Underlying>(BufferUsage::CAMERA_OUTPUT); - usages.push_back("BufferUsage::CAMERA_OUTPUT"); - } - if (usage & BufferUsage::COMPOSER_CURSOR) { - usage &= ~static_cast<Underlying>(BufferUsage::COMPOSER_CURSOR); - usages.push_back("BufferUsage::COMPOSER_CURSOR"); - } - if (usage & BufferUsage::COMPOSER_OVERLAY) { - usage &= ~static_cast<Underlying>(BufferUsage::COMPOSER_OVERLAY); - usages.push_back("BufferUsage::COMPOSER_OVERLAY"); - } - if (usage & BufferUsage::CPU_READ_OFTEN) { - usage &= ~static_cast<Underlying>(BufferUsage::CPU_READ_OFTEN); - usages.push_back("BufferUsage::CPU_READ_OFTEN"); - } - if (usage & BufferUsage::CPU_READ_NEVER) { - usage &= ~static_cast<Underlying>(BufferUsage::CPU_READ_NEVER); - usages.push_back("BufferUsage::CPU_READ_NEVER"); - } - if (usage & BufferUsage::CPU_READ_RARELY) { - usage &= ~static_cast<Underlying>(BufferUsage::CPU_READ_RARELY); - usages.push_back("BufferUsage::CPU_READ_RARELY"); - } - if (usage & BufferUsage::CPU_WRITE_NEVER) { - usage &= ~static_cast<Underlying>(BufferUsage::CPU_WRITE_NEVER); - usages.push_back("BufferUsage::CPU_WRITE_NEVER"); - } - if (usage & BufferUsage::CPU_WRITE_OFTEN) { - usage &= ~static_cast<Underlying>(BufferUsage::CPU_WRITE_OFTEN); - usages.push_back("BufferUsage::CPU_WRITE_OFTEN"); - } - if (usage & BufferUsage::CPU_WRITE_RARELY) { - usage &= ~static_cast<Underlying>(BufferUsage::CPU_WRITE_RARELY); - usages.push_back("BufferUsage::CPU_WRITE_RARELY"); - } - if (usage & BufferUsage::GPU_RENDER_TARGET) { - usage &= ~static_cast<Underlying>(BufferUsage::GPU_RENDER_TARGET); - usages.push_back("BufferUsage::GPU_RENDER_TARGET"); - } - if (usage & BufferUsage::GPU_TEXTURE) { - usage &= ~static_cast<Underlying>(BufferUsage::GPU_TEXTURE); - usages.push_back("BufferUsage::GPU_TEXTURE"); - } - if (usage & BufferUsage::PROTECTED) { - usage &= ~static_cast<Underlying>(BufferUsage::PROTECTED); - usages.push_back("BufferUsage::PROTECTED"); - } - if (usage & BufferUsage::RENDERSCRIPT) { - usage &= ~static_cast<Underlying>(BufferUsage::RENDERSCRIPT); - usages.push_back("BufferUsage::RENDERSCRIPT"); - } - if (usage & BufferUsage::VIDEO_DECODER) { - usage &= ~static_cast<Underlying>(BufferUsage::VIDEO_DECODER); - usages.push_back("BufferUsage::VIDEO_DECODER"); - } - if (usage & BufferUsage::VIDEO_ENCODER) { - usage &= ~static_cast<Underlying>(BufferUsage::VIDEO_ENCODER); - usages.push_back("BufferUsage::VIDEO_ENCODER"); - } + static_assert(std::is_same<std::underlying_type<BufferUsage>::type, uint64_t>::value); - if (usage) { - usages.push_back(android::base::StringPrintf("UnknownUsageBits-%" PRIu64, usage)); - } - - return android::base::Join(usages, '|'); + const uint64_t usage = static_cast<uint64_t>(bufferUsage); + return android::hardware::graphics::common::V1_2::toString<BufferUsage>(usage); } int convertToDrmFormat(PixelFormat format, uint32_t* outDrmFormat) { - switch (format) { - case PixelFormat::BGRA_8888: - *outDrmFormat = DRM_FORMAT_ARGB8888; - return 0; - /** - * Choose DRM_FORMAT_R8 because <system/graphics.h> requires the buffers - * with a format HAL_PIXEL_FORMAT_BLOB have a height of 1, and width - * equal to their size in bytes. - */ - case PixelFormat::BLOB: - *outDrmFormat = DRM_FORMAT_R8; - return 0; - case PixelFormat::DEPTH_16: - return -EINVAL; - case PixelFormat::DEPTH_24: - return -EINVAL; - case PixelFormat::DEPTH_24_STENCIL_8: - return -EINVAL; - case PixelFormat::DEPTH_32F: - return -EINVAL; - case PixelFormat::DEPTH_32F_STENCIL_8: - return -EINVAL; - case PixelFormat::HSV_888: - return -EINVAL; - case PixelFormat::IMPLEMENTATION_DEFINED: - *outDrmFormat = DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED; - return 0; - case PixelFormat::RAW10: - return -EINVAL; - case PixelFormat::RAW12: - return -EINVAL; - case PixelFormat::RAW16: - *outDrmFormat = DRM_FORMAT_R16; - return 0; - /* TODO use blob */ - case PixelFormat::RAW_OPAQUE: - return -EINVAL; - case PixelFormat::RGBA_1010102: - *outDrmFormat = DRM_FORMAT_ABGR2101010; - return 0; - case PixelFormat::RGBA_8888: - *outDrmFormat = DRM_FORMAT_ABGR8888; - return 0; - case PixelFormat::RGBA_FP16: - *outDrmFormat = DRM_FORMAT_ABGR16161616F; - return 0; - case PixelFormat::RGBX_8888: - *outDrmFormat = DRM_FORMAT_XBGR8888; - return 0; - case PixelFormat::RGB_565: - *outDrmFormat = DRM_FORMAT_RGB565; - return 0; - case PixelFormat::RGB_888: - *outDrmFormat = DRM_FORMAT_RGB888; - return 0; - case PixelFormat::STENCIL_8: - return -EINVAL; - case PixelFormat::Y16: - *outDrmFormat = DRM_FORMAT_R16; - return 0; - case PixelFormat::Y8: - *outDrmFormat = DRM_FORMAT_R8; - return 0; - case PixelFormat::YCBCR_420_888: - *outDrmFormat = DRM_FORMAT_FLEX_YCbCr_420_888; - return 0; - case PixelFormat::YCBCR_422_SP: - return -EINVAL; - case PixelFormat::YCBCR_422_I: - return -EINVAL; - case PixelFormat::YCBCR_P010: - *outDrmFormat = DRM_FORMAT_P010; - return 0; - case PixelFormat::YCRCB_420_SP: - *outDrmFormat = DRM_FORMAT_NV21; - return 0; - case PixelFormat::YV12: - *outDrmFormat = DRM_FORMAT_YVU420_ANDROID; - return 0; - }; - return -EINVAL; -} + static_assert(std::is_same<std::underlying_type<PixelFormat>::type, int32_t>::value); -int convertToBufferUsage(uint64_t grallocUsage, uint64_t* outBufferUsage) { - uint64_t bufferUsage = BO_USE_NONE; + const uint32_t drmFormat = cros_gralloc_convert_format(static_cast<int32_t>(format)); + if (drmFormat == DRM_FORMAT_NONE) return -EINVAL; - if ((grallocUsage & BufferUsage::CPU_READ_MASK) == - static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY)) { - bufferUsage |= BO_USE_SW_READ_RARELY; - } - if ((grallocUsage & BufferUsage::CPU_READ_MASK) == - static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN)) { - bufferUsage |= BO_USE_SW_READ_OFTEN; - } - if ((grallocUsage & BufferUsage::CPU_WRITE_MASK) == - static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY)) { - bufferUsage |= BO_USE_SW_WRITE_RARELY; - } - if ((grallocUsage & BufferUsage::CPU_WRITE_MASK) == - static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN)) { - bufferUsage |= BO_USE_SW_WRITE_OFTEN; - } - if (grallocUsage & BufferUsage::GPU_TEXTURE) { - bufferUsage |= BO_USE_TEXTURE; - } - if (grallocUsage & BufferUsage::GPU_RENDER_TARGET) { - bufferUsage |= BO_USE_RENDERING; - } - if (grallocUsage & BufferUsage::COMPOSER_OVERLAY) { - /* HWC wants to use display hardware, but can defer to OpenGL. */ - bufferUsage |= BO_USE_SCANOUT | BO_USE_TEXTURE; - } - /* Map this flag to linear until real HW protection is available on Android. */ - if (grallocUsage & BufferUsage::PROTECTED) { - bufferUsage |= BO_USE_LINEAR; - } - if (grallocUsage & BufferUsage::COMPOSER_CURSOR) { - bufferUsage |= BO_USE_NONE; - } - if (grallocUsage & BufferUsage::VIDEO_ENCODER) { - /*HACK: See b/30054495 */ - bufferUsage |= BO_USE_SW_READ_OFTEN; - } - if (grallocUsage & BufferUsage::CAMERA_OUTPUT) { - bufferUsage |= BO_USE_CAMERA_WRITE; - } - if (grallocUsage & BufferUsage::CAMERA_INPUT) { - bufferUsage |= BO_USE_CAMERA_READ; - } - if (grallocUsage & BufferUsage::RENDERSCRIPT) { - bufferUsage |= BO_USE_RENDERSCRIPT; - } - if (grallocUsage & BufferUsage::VIDEO_DECODER) { - bufferUsage |= BO_USE_HW_VIDEO_DECODER; - } + *outDrmFormat = drmFormat; + return 0; +} - *outBufferUsage = bufferUsage; +int convertToBufferUsage(uint64_t grallocUsage, uint64_t* outBufferUsage) { + *outBufferUsage = cros_gralloc_convert_usage(grallocUsage); return 0; } @@ -337,16 +82,7 @@ int convertToCrosDescriptor(const BufferDescriptorInfo& descriptor, } int convertToMapUsage(uint64_t grallocUsage, uint32_t* outMapUsage) { - uint32_t mapUsage = BO_MAP_NONE; - - if (grallocUsage & BufferUsage::CPU_READ_MASK) { - mapUsage |= BO_MAP_READ; - } - if (grallocUsage & BufferUsage::CPU_WRITE_MASK) { - mapUsage |= BO_MAP_WRITE; - } - - *outMapUsage = mapUsage; + *outMapUsage = cros_gralloc_convert_map_usage(grallocUsage); return 0; } @@ -547,13 +283,13 @@ const std::unordered_map<uint32_t, std::vector<PlaneLayout>>& GetPlaneLayoutsMap {DRM_FORMAT_RGB565, {{ - .components = {{.type = android::gralloc4::PlaneLayoutComponentType_R, + .components = {{.type = android::gralloc4::PlaneLayoutComponentType_B, .offsetInBits = 0, .sizeInBits = 5}, {.type = android::gralloc4::PlaneLayoutComponentType_G, .offsetInBits = 5, .sizeInBits = 6}, - {.type = android::gralloc4::PlaneLayoutComponentType_B, + {.type = android::gralloc4::PlaneLayoutComponentType_R, .offsetInBits = 11, .sizeInBits = 5}}, .sampleIncrementInBits = 16, @@ -561,7 +297,7 @@ const std::unordered_map<uint32_t, std::vector<PlaneLayout>>& GetPlaneLayoutsMap .verticalSubsampling = 1, }}}, - {DRM_FORMAT_RGB888, + {DRM_FORMAT_BGR888, {{ .components = {{.type = android::gralloc4::PlaneLayoutComponentType_R, .offsetInBits = 0, @@ -579,13 +315,13 @@ const std::unordered_map<uint32_t, std::vector<PlaneLayout>>& GetPlaneLayoutsMap {DRM_FORMAT_XBGR8888, {{ - .components = {{.type = android::gralloc4::PlaneLayoutComponentType_B, + .components = {{.type = android::gralloc4::PlaneLayoutComponentType_R, .offsetInBits = 0, .sizeInBits = 8}, {.type = android::gralloc4::PlaneLayoutComponentType_G, .offsetInBits = 8, .sizeInBits = 8}, - {.type = android::gralloc4::PlaneLayoutComponentType_R, + {.type = android::gralloc4::PlaneLayoutComponentType_B, .offsetInBits = 16, .sizeInBits = 8}}, .sampleIncrementInBits = 32, diff --git a/cros_gralloc/gralloc4/CrosGralloc4Utils.h b/cros_gralloc/gralloc4/CrosGralloc4Utils.h index 370922c..fa096ef 100644 --- a/cros_gralloc/gralloc4/CrosGralloc4Utils.h +++ b/cros_gralloc/gralloc4/CrosGralloc4Utils.h @@ -11,7 +11,7 @@ #include <android/hardware/graphics/common/1.2/types.h> #include <android/hardware/graphics/mapper/4.0/IMapper.h> -#include "cros_gralloc/cros_gralloc_types.h" +struct cros_gralloc_buffer_descriptor; std::string getPixelFormatString(android::hardware::graphics::common::V1_2::PixelFormat format); diff --git a/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm.rc b/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm.rc index a96a6e1..4f8680b 100644 --- a/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm.rc +++ b/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm.rc @@ -21,4 +21,4 @@ service vendor.graphics.allocator-4-0 /vendor/bin/hw/android.hardware.graphics.a group graphics drmrpc capabilities SYS_NICE onrestart restart surfaceflinger - writepid /dev/cpuset/system-background/tasks + task_profiles ServiceCapacityLow diff --git a/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm_arcvm.rc b/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm_arcvm.rc new file mode 100644 index 0000000..4e8818a --- /dev/null +++ b/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm_arcvm.rc @@ -0,0 +1,24 @@ +# +# Copyright 2021 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +service vendor.graphics.allocator-4-0 /vendor/bin/hw/android.hardware.graphics.allocator@4.0-service.minigbm_arcvm + interface android.hardware.graphics.allocator@4.0::IAllocator default + class hal animation + user system + group graphics drmrpc + capabilities SYS_NICE + onrestart restart surfaceflinger + task_profiles ServiceCapacityLow diff --git a/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm_intel.rc b/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm_intel.rc new file mode 100644 index 0000000..9a3512f --- /dev/null +++ b/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm_intel.rc @@ -0,0 +1,24 @@ +# +# Copyright 2020 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +service vendor.graphics.allocator-4-0 /vendor/bin/hw/android.hardware.graphics.allocator@4.0-service.minigbm_intel + interface android.hardware.graphics.allocator@4.0::IAllocator default + class hal animation + user system + group graphics drmrpc + capabilities SYS_NICE + onrestart restart surfaceflinger + task_profiles ServiceCapacityLow diff --git a/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm_msm.rc b/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm_msm.rc index dceb747..8ecc94b 100644 --- a/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm_msm.rc +++ b/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm_msm.rc @@ -21,4 +21,4 @@ service vendor.graphics.allocator-4-0 /vendor/bin/hw/android.hardware.graphics.a group graphics drmrpc capabilities SYS_NICE onrestart restart surfaceflinger - writepid /dev/cpuset/system-background/tasks + task_profiles ServiceCapacityLow @@ -18,8 +18,8 @@ #include <xf86drm.h> #include "dri.h" +#include "drv_helpers.h" #include "drv_priv.h" -#include "helpers.h" #include "util.h" static const struct { @@ -196,8 +196,12 @@ int dri_init(struct driver *drv, const char *dri_so_path, const char *driver_suf const __DRIextension *loader_extensions[] = { NULL }; struct dri_driver *dri = drv->priv; + char *node_name = drmGetRenderDeviceNameFromFd(drv_get_fd(drv)); + if (!node_name) + return -ENODEV; - dri->fd = open(drmGetRenderDeviceNameFromFd(drv_get_fd(drv)), O_RDWR); + dri->fd = open(node_name, O_RDWR); + free(node_name); if (dri->fd < 0) return -ENODEV; @@ -385,13 +389,20 @@ int dri_bo_import(struct bo *bo, struct drv_import_fd_data *data) return 0; } -int dri_bo_destroy(struct bo *bo) +int dri_bo_release(struct bo *bo) { struct dri_driver *dri = bo->drv->priv; assert(bo->priv); - close_gem_handle(bo->handles[0].u32, bo->drv->fd); dri->image_extension->destroyImage(bo->priv); + /* Not clearing bo->priv as we still use it to determine which destroy to call. */ + return 0; +} + +int dri_bo_destroy(struct bo *bo) +{ + assert(bo->priv); + close_gem_handle(bo->handles[0].u32, bo->drv->fd); bo->priv = NULL; return 0; } @@ -441,19 +452,29 @@ int dri_bo_unmap(struct bo *bo, struct vma *vma) size_t dri_num_planes_from_modifier(struct driver *drv, uint32_t format, uint64_t modifier) { struct dri_driver *dri = drv->priv; - if (!dri->image_extension->queryDmaBufFormatModifierAttribs) { - /* We do not do any modifier checks here. The create will fail - * later if the modifier is not supported. */ - return drv_num_planes_from_format(format); - } + uint64_t planes = 0; + + /* We do not do any modifier checks here. The create will fail later if the modifier is not + * supported. + */ + if (dri->image_extension->queryDmaBufFormatModifierAttribs && + dri->image_extension->queryDmaBufFormatModifierAttribs( + dri->device, format, modifier, __DRI_IMAGE_FORMAT_MODIFIER_ATTRIB_PLANE_COUNT, + &planes)) + return planes; - uint64_t planes; - GLboolean ret = dri->image_extension->queryDmaBufFormatModifierAttribs( - dri->device, format, modifier, __DRI_IMAGE_ATTRIB_NUM_PLANES, &planes); - if (!ret) - return 0; + return drv_num_planes_from_format(format); +} + +bool dri_query_modifiers(struct driver *drv, uint32_t format, int max, uint64_t *modifiers, + int *count) +{ + struct dri_driver *dri = drv->priv; + if (!dri->image_extension->queryDmaBufModifiers) + return false; - return planes; + return dri->image_extension->queryDmaBufModifiers(dri->device, format, max, modifiers, NULL, + count); } #endif @@ -33,9 +33,12 @@ int dri_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t forma int dri_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, const uint64_t *modifiers, uint32_t modifier_count); int dri_bo_import(struct bo *bo, struct drv_import_fd_data *data); +int dri_bo_release(struct bo *bo); int dri_bo_destroy(struct bo *bo); void *dri_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags); int dri_bo_unmap(struct bo *bo, struct vma *vma); size_t dri_num_planes_from_modifier(struct driver *drv, uint32_t format, uint64_t modifier); +bool dri_query_modifiers(struct driver *drv, uint32_t format, int max, uint64_t *modifiers, + int *count); #endif @@ -9,7 +9,6 @@ #include <pthread.h> #include <stdint.h> #include <stdio.h> -#include <stdlib.h> #include <string.h> #include <sys/mman.h> #include <sys/types.h> @@ -21,16 +20,13 @@ #include <libgen.h> #endif +#include "drv_helpers.h" #include "drv_priv.h" -#include "helpers.h" #include "util.h" #ifdef DRV_AMDGPU extern const struct backend backend_amdgpu; #endif -#ifdef DRV_EXYNOS -extern const struct backend backend_exynos; -#endif #ifdef DRV_I915 extern const struct backend backend_i915; #endif @@ -73,9 +69,6 @@ static const struct backend *drv_get_backend(int fd) #ifdef DRV_AMDGPU &backend_amdgpu, #endif -#ifdef DRV_EXYNOS - &backend_exynos, -#endif #ifdef DRV_I915 &backend_i915, #endif @@ -128,16 +121,19 @@ struct driver *drv_create(int fd) if (!drv->backend) goto free_driver; - if (pthread_mutex_init(&drv->driver_lock, NULL)) + if (pthread_mutex_init(&drv->buffer_table_lock, NULL)) goto free_driver; drv->buffer_table = drmHashCreate(); if (!drv->buffer_table) - goto free_lock; + goto free_buffer_table_lock; + + if (pthread_mutex_init(&drv->mappings_lock, NULL)) + goto free_buffer_table; drv->mappings = drv_array_init(sizeof(struct mapping)); if (!drv->mappings) - goto free_buffer_table; + goto free_mappings_lock; drv->combos = drv_array_init(sizeof(struct combination)); if (!drv->combos) @@ -155,10 +151,12 @@ struct driver *drv_create(int fd) free_mappings: drv_array_destroy(drv->mappings); +free_mappings_lock: + pthread_mutex_destroy(&drv->mappings_lock); free_buffer_table: drmHashDestroy(drv->buffer_table); -free_lock: - pthread_mutex_destroy(&drv->driver_lock); +free_buffer_table_lock: + pthread_mutex_destroy(&drv->buffer_table_lock); free_driver: free(drv); return NULL; @@ -166,17 +164,16 @@ free_driver: void drv_destroy(struct driver *drv) { - pthread_mutex_lock(&drv->driver_lock); - if (drv->backend->close) drv->backend->close(drv); - drmHashDestroy(drv->buffer_table); - drv_array_destroy(drv->mappings); drv_array_destroy(drv->combos); - pthread_mutex_unlock(&drv->driver_lock); - pthread_mutex_destroy(&drv->driver_lock); + drv_array_destroy(drv->mappings); + pthread_mutex_destroy(&drv->mappings_lock); + + drmHashDestroy(drv->buffer_table); + pthread_mutex_destroy(&drv->buffer_table_lock); free(drv); } @@ -230,17 +227,111 @@ struct bo *drv_bo_new(struct driver *drv, uint32_t width, uint32_t height, uint3 if (!bo->meta.num_planes) { free(bo); + errno = EINVAL; return NULL; } return bo; } +static void drv_bo_mapping_destroy(struct bo *bo) +{ + struct driver *drv = bo->drv; + uint32_t idx = 0; + + /* + * This function is called right before the buffer is destroyed. It will free any mappings + * associated with the buffer. + */ + pthread_mutex_lock(&drv->mappings_lock); + for (size_t plane = 0; plane < bo->meta.num_planes; plane++) { + while (idx < drv_array_size(drv->mappings)) { + struct mapping *mapping = + (struct mapping *)drv_array_at_idx(drv->mappings, idx); + if (mapping->vma->handle != bo->handles[plane].u32) { + idx++; + continue; + } + + if (!--mapping->vma->refcount) { + int ret = drv->backend->bo_unmap(bo, mapping->vma); + if (ret) { + pthread_mutex_unlock(&drv->mappings_lock); + assert(ret); + drv_log("munmap failed\n"); + return; + } + + free(mapping->vma); + } + + /* This shrinks and shifts the array, so don't increment idx. */ + drv_array_remove(drv->mappings, idx); + } + } + pthread_mutex_unlock(&drv->mappings_lock); +} + +/* + * Acquire a reference on plane buffers of the bo. + */ +static void drv_bo_acquire(struct bo *bo) +{ + struct driver *drv = bo->drv; + + pthread_mutex_lock(&drv->buffer_table_lock); + for (size_t plane = 0; plane < bo->meta.num_planes; plane++) { + uintptr_t num = 0; + + if (!drmHashLookup(drv->buffer_table, bo->handles[plane].u32, (void **)&num)) + drmHashDelete(drv->buffer_table, bo->handles[plane].u32); + + drmHashInsert(drv->buffer_table, bo->handles[plane].u32, (void *)(num + 1)); + } + pthread_mutex_unlock(&drv->buffer_table_lock); +} + +/* + * Release a reference on plane buffers of the bo. Return true when the bo has lost all its + * references. Otherwise, return false. + */ +static bool drv_bo_release(struct bo *bo) +{ + struct driver *drv = bo->drv; + uintptr_t num; + + if (drv->backend->bo_release) + drv->backend->bo_release(bo); + + pthread_mutex_lock(&drv->buffer_table_lock); + for (size_t plane = 0; plane < bo->meta.num_planes; plane++) { + if (!drmHashLookup(drv->buffer_table, bo->handles[plane].u32, (void **)&num)) { + drmHashDelete(drv->buffer_table, bo->handles[plane].u32); + + if (num > 1) { + drmHashInsert(drv->buffer_table, bo->handles[plane].u32, + (void *)(num - 1)); + } + } + } + + /* The same buffer can back multiple planes with different offsets. */ + for (size_t plane = 0; plane < bo->meta.num_planes; plane++) { + if (!drmHashLookup(drv->buffer_table, bo->handles[plane].u32, (void **)&num)) { + /* num is positive if found in the hashmap. */ + pthread_mutex_unlock(&drv->buffer_table_lock); + return false; + } + } + pthread_mutex_unlock(&drv->buffer_table_lock); + + return true; +} + struct bo *drv_bo_create(struct driver *drv, uint32_t width, uint32_t height, uint32_t format, uint64_t use_flags) { int ret; - size_t plane; struct bo *bo; bool is_test_alloc; @@ -263,20 +354,12 @@ struct bo *drv_bo_create(struct driver *drv, uint32_t width, uint32_t height, ui } if (ret) { + errno = -ret; free(bo); return NULL; } - pthread_mutex_lock(&drv->driver_lock); - - for (plane = 0; plane < bo->meta.num_planes; plane++) { - if (plane > 0) - assert(bo->meta.offsets[plane] >= bo->meta.offsets[plane - 1]); - - drv_increment_reference_count(drv, bo, plane); - } - - pthread_mutex_unlock(&drv->driver_lock); + drv_bo_acquire(bo); return bo; } @@ -285,7 +368,6 @@ struct bo *drv_bo_create_with_modifiers(struct driver *drv, uint32_t width, uint uint32_t format, const uint64_t *modifiers, uint32_t count) { int ret; - size_t plane; struct bo *bo; if (!drv->backend->bo_create_with_modifiers && !drv->backend->bo_compute_metadata) { @@ -314,43 +396,16 @@ struct bo *drv_bo_create_with_modifiers(struct driver *drv, uint32_t width, uint return NULL; } - pthread_mutex_lock(&drv->driver_lock); - - for (plane = 0; plane < bo->meta.num_planes; plane++) { - if (plane > 0) - assert(bo->meta.offsets[plane] >= bo->meta.offsets[plane - 1]); - - drv_increment_reference_count(drv, bo, plane); - } - - pthread_mutex_unlock(&drv->driver_lock); + drv_bo_acquire(bo); return bo; } void drv_bo_destroy(struct bo *bo) { - int ret; - size_t plane; - uintptr_t total = 0; - struct driver *drv = bo->drv; - - if (!bo->is_test_buffer) { - pthread_mutex_lock(&drv->driver_lock); - - for (plane = 0; plane < bo->meta.num_planes; plane++) - drv_decrement_reference_count(drv, bo, plane); - - for (plane = 0; plane < bo->meta.num_planes; plane++) - total += drv_get_reference_count(drv, bo, plane); - - pthread_mutex_unlock(&drv->driver_lock); - - if (total == 0) { - ret = drv_mapping_destroy(bo); - assert(ret == 0); - bo->drv->backend->bo_destroy(bo); - } + if (!bo->is_test_buffer && drv_bo_release(bo)) { + drv_bo_mapping_destroy(bo); + bo->drv->backend->bo_destroy(bo); } free(bo); @@ -374,11 +429,7 @@ struct bo *drv_bo_import(struct driver *drv, struct drv_import_fd_data *data) return NULL; } - for (plane = 0; plane < bo->meta.num_planes; plane++) { - pthread_mutex_lock(&bo->drv->driver_lock); - drv_increment_reference_count(bo->drv, bo, plane); - pthread_mutex_unlock(&bo->drv->driver_lock); - } + drv_bo_acquire(bo); bo->meta.format_modifier = data->format_modifier; for (plane = 0; plane < bo->meta.num_planes; plane++) { @@ -415,6 +466,7 @@ destroy_bo: void *drv_bo_map(struct bo *bo, const struct rectangle *rect, uint32_t map_flags, struct mapping **map_data, size_t plane) { + struct driver *drv = bo->drv; uint32_t i; uint8_t *addr; struct mapping mapping = { 0 }; @@ -433,10 +485,10 @@ void *drv_bo_map(struct bo *bo, const struct rectangle *rect, uint32_t map_flags mapping.rect = *rect; mapping.refcount = 1; - pthread_mutex_lock(&bo->drv->driver_lock); + pthread_mutex_lock(&drv->mappings_lock); - for (i = 0; i < drv_array_size(bo->drv->mappings); i++) { - struct mapping *prior = (struct mapping *)drv_array_at_idx(bo->drv->mappings, i); + for (i = 0; i < drv_array_size(drv->mappings); i++) { + struct mapping *prior = (struct mapping *)drv_array_at_idx(drv->mappings, i); if (prior->vma->handle != bo->handles[plane].u32 || prior->vma->map_flags != map_flags) continue; @@ -450,8 +502,8 @@ void *drv_bo_map(struct bo *bo, const struct rectangle *rect, uint32_t map_flags goto exact_match; } - for (i = 0; i < drv_array_size(bo->drv->mappings); i++) { - struct mapping *prior = (struct mapping *)drv_array_at_idx(bo->drv->mappings, i); + for (i = 0; i < drv_array_size(drv->mappings); i++) { + struct mapping *prior = (struct mapping *)drv_array_at_idx(drv->mappings, i); if (prior->vma->handle != bo->handles[plane].u32 || prior->vma->map_flags != map_flags) continue; @@ -462,12 +514,18 @@ void *drv_bo_map(struct bo *bo, const struct rectangle *rect, uint32_t map_flags } mapping.vma = calloc(1, sizeof(*mapping.vma)); + if (!mapping.vma) { + *map_data = NULL; + pthread_mutex_unlock(&drv->mappings_lock); + return MAP_FAILED; + } + memcpy(mapping.vma->map_strides, bo->meta.strides, sizeof(mapping.vma->map_strides)); - addr = bo->drv->backend->bo_map(bo, mapping.vma, plane, map_flags); + addr = drv->backend->bo_map(bo, mapping.vma, plane, map_flags); if (addr == MAP_FAILED) { *map_data = NULL; free(mapping.vma); - pthread_mutex_unlock(&bo->drv->driver_lock); + pthread_mutex_unlock(&drv->mappings_lock); return MAP_FAILED; } @@ -477,39 +535,40 @@ void *drv_bo_map(struct bo *bo, const struct rectangle *rect, uint32_t map_flags mapping.vma->map_flags = map_flags; success: - *map_data = drv_array_append(bo->drv->mappings, &mapping); + *map_data = drv_array_append(drv->mappings, &mapping); exact_match: drv_bo_invalidate(bo, *map_data); addr = (uint8_t *)((*map_data)->vma->addr); addr += drv_bo_get_plane_offset(bo, plane); - pthread_mutex_unlock(&bo->drv->driver_lock); + pthread_mutex_unlock(&drv->mappings_lock); return (void *)addr; } int drv_bo_unmap(struct bo *bo, struct mapping *mapping) { + struct driver *drv = bo->drv; uint32_t i; int ret = 0; - pthread_mutex_lock(&bo->drv->driver_lock); + pthread_mutex_lock(&drv->mappings_lock); if (--mapping->refcount) goto out; if (!--mapping->vma->refcount) { - ret = bo->drv->backend->bo_unmap(bo, mapping->vma); + ret = drv->backend->bo_unmap(bo, mapping->vma); free(mapping->vma); } - for (i = 0; i < drv_array_size(bo->drv->mappings); i++) { - if (mapping == (struct mapping *)drv_array_at_idx(bo->drv->mappings, i)) { - drv_array_remove(bo->drv->mappings, i); + for (i = 0; i < drv_array_size(drv->mappings); i++) { + if (mapping == (struct mapping *)drv_array_at_idx(drv->mappings, i)) { + drv_array_remove(drv->mappings, i); break; } } out: - pthread_mutex_unlock(&bo->drv->driver_lock); + pthread_mutex_unlock(&drv->mappings_lock); return ret; } @@ -634,17 +693,36 @@ uint32_t drv_bo_get_format(struct bo *bo) return bo->meta.format; } +uint32_t drv_bo_get_tiling(struct bo *bo) +{ + return bo->meta.tiling; +} + +uint64_t drv_bo_get_use_flags(struct bo *bo) +{ + return bo->meta.use_flags; +} + size_t drv_bo_get_total_size(struct bo *bo) { return bo->meta.total_size; } -uint32_t drv_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags) +/* + * Map internal fourcc codes back to standard fourcc codes. + */ +uint32_t drv_get_standard_fourcc(uint32_t fourcc_internal) +{ + return (fourcc_internal == DRM_FORMAT_YVU420_ANDROID) ? DRM_FORMAT_YVU420 : fourcc_internal; +} + +void drv_resolve_format_and_use_flags(struct driver *drv, uint32_t format, uint64_t use_flags, + uint32_t *out_format, uint64_t *out_use_flags) { - if (drv->backend->resolve_format) - return drv->backend->resolve_format(drv, format, use_flags); + assert(drv->backend->resolve_format_and_use_flags); - return format; + drv->backend->resolve_format_and_use_flags(drv, format, use_flags, out_format, + out_use_flags); } uint32_t drv_num_buffers_per_bo(struct bo *bo) @@ -696,3 +774,11 @@ int drv_resource_info(struct bo *bo, uint32_t strides[DRV_MAX_PLANES], return 0; } + +uint32_t drv_get_max_texture_2d_size(struct driver *drv) +{ + if (drv->backend->get_max_texture_2d_size) + return drv->backend->get_max_texture_2d_size(drv); + + return UINT32_MAX; +} @@ -14,6 +14,7 @@ extern "C" { #include <drm_fourcc.h> #include <stdbool.h> #include <stdint.h> +#include <stdlib.h> #define DRV_MAX_PLANES 4 @@ -39,6 +40,8 @@ extern "C" { #define BO_USE_TEST_ALLOC (1ull << 15) #define BO_USE_FRONT_RENDERING (1ull << 16) #define BO_USE_RENDERSCRIPT (1ull << 17) +#define BO_USE_GPU_DATA_BUFFER (1ull << 18) +#define BO_USE_SENSOR_DIRECT_DATA (1ull << 19) /* Quirks for allocating a buffer. */ #define BO_QUIRK_NONE 0 @@ -69,6 +72,11 @@ extern "C" { #define DRM_FORMAT_P010 fourcc_code('P', '0', '1', '0') #endif +//TODO: remove this defination once drm_fourcc.h contains it. +#ifndef I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS +#define I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS fourcc_mod_code(INTEL, 6) +#endif + // clang-format on struct driver; struct bo; @@ -171,11 +179,22 @@ uint64_t drv_bo_get_format_modifier(struct bo *bo); uint32_t drv_bo_get_format(struct bo *bo); +uint32_t drv_bo_get_tiling(struct bo *bo); + +uint64_t drv_bo_get_use_flags(struct bo *bo); + +size_t drv_bo_get_total_size(struct bo *bo); + +uint32_t drv_get_standard_fourcc(uint32_t fourcc_internal); + uint32_t drv_bytes_per_pixel_from_format(uint32_t format, size_t plane); uint32_t drv_stride_from_format(uint32_t format, uint32_t width, size_t plane); -uint32_t drv_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags); +void drv_resolve_format_and_use_flags(struct driver *drv, uint32_t format, uint64_t use_flags, + uint32_t *out_format, uint64_t *out_use_flags); + +uint64_t drv_resolve_use_flags(struct driver *drv, uint32_t format, uint64_t use_flags); size_t drv_num_planes_from_format(uint32_t format); @@ -186,6 +205,8 @@ uint32_t drv_num_buffers_per_bo(struct bo *bo); int drv_resource_info(struct bo *bo, uint32_t strides[DRV_MAX_PLANES], uint32_t offsets[DRV_MAX_PLANES], uint64_t *format_modifier); +uint32_t drv_get_max_texture_2d_size(struct driver *drv); + #define drv_log(format, ...) \ do { \ drv_log_prefix("minigbm", __FILE__, __LINE__, format, ##__VA_ARGS__); \ diff --git a/helpers_array.c b/drv_array_helpers.c index 20b43e2..b4e7750 100644 --- a/helpers_array.c +++ b/drv_array_helpers.c @@ -3,6 +3,7 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ +#include "drv_array_helpers.h" #include <assert.h> #include <stdint.h> @@ -23,10 +24,17 @@ struct drv_array *drv_array_init(uint32_t item_size) struct drv_array *array; array = calloc(1, sizeof(*array)); + if (!array) + return NULL; /* Start with a power of 2 number of allocations. */ array->allocations = 2; array->items = calloc(array->allocations, sizeof(*array->items)); + if (!array->items) { + free(array); + return NULL; + } + array->item_size = item_size; return array; } diff --git a/helpers_array.h b/drv_array_helpers.h index 2893976..77544d3 100644 --- a/helpers_array.h +++ b/drv_array_helpers.h @@ -4,6 +4,11 @@ * found in the LICENSE file. */ +#ifndef DRV_ARRAY_HELPERS_H +#define DRV_ARRAY_HELPERS_H + +#include <stdint.h> + struct drv_array; struct drv_array *drv_array_init(uint32_t item_size); @@ -20,3 +25,5 @@ uint32_t drv_array_size(struct drv_array *array); /* The array and all associated data will be freed. */ void drv_array_destroy(struct drv_array *array); + +#endif diff --git a/helpers.c b/drv_helpers.c index a182347..6ea4b8e 100644 --- a/helpers.c +++ b/drv_helpers.c @@ -4,6 +4,8 @@ * found in the LICENSE file. */ +#include "drv_helpers.h" + #include <assert.h> #include <errno.h> #include <stdio.h> @@ -15,7 +17,6 @@ #include <xf86drm.h> #include "drv_priv.h" -#include "helpers.h" #include "util.h" struct planar_layout { @@ -483,80 +484,11 @@ int drv_bo_munmap(struct bo *bo, struct vma *vma) return munmap(vma->addr, vma->length); } -int drv_mapping_destroy(struct bo *bo) -{ - int ret; - size_t plane; - struct mapping *mapping; - uint32_t idx; - - /* - * This function is called right before the buffer is destroyed. It will free any mappings - * associated with the buffer. - */ - - idx = 0; - for (plane = 0; plane < bo->meta.num_planes; plane++) { - while (idx < drv_array_size(bo->drv->mappings)) { - mapping = (struct mapping *)drv_array_at_idx(bo->drv->mappings, idx); - if (mapping->vma->handle != bo->handles[plane].u32) { - idx++; - continue; - } - - if (!--mapping->vma->refcount) { - ret = bo->drv->backend->bo_unmap(bo, mapping->vma); - if (ret) { - drv_log("munmap failed\n"); - return ret; - } - - free(mapping->vma); - } - - /* This shrinks and shifts the array, so don't increment idx. */ - drv_array_remove(bo->drv->mappings, idx); - } - } - - return 0; -} - int drv_get_prot(uint32_t map_flags) { return (BO_MAP_WRITE & map_flags) ? PROT_WRITE | PROT_READ : PROT_READ; } -uintptr_t drv_get_reference_count(struct driver *drv, struct bo *bo, size_t plane) -{ - void *count; - uintptr_t num = 0; - - if (!drmHashLookup(drv->buffer_table, bo->handles[plane].u32, &count)) - num = (uintptr_t)(count); - - return num; -} - -void drv_increment_reference_count(struct driver *drv, struct bo *bo, size_t plane) -{ - uintptr_t num = drv_get_reference_count(drv, bo, plane); - - /* If a value isn't in the table, drmHashDelete is a no-op */ - drmHashDelete(drv->buffer_table, bo->handles[plane].u32); - drmHashInsert(drv->buffer_table, bo->handles[plane].u32, (void *)(num + 1)); -} - -void drv_decrement_reference_count(struct driver *drv, struct bo *bo, size_t plane) -{ - uintptr_t num = drv_get_reference_count(drv, bo, plane); - - drmHashDelete(drv->buffer_table, bo->handles[plane].u32); - - if (num > 0) - drmHashInsert(drv->buffer_table, bo->handles[plane].u32, (void *)(num - 1)); -} - void drv_add_combination(struct driver *drv, const uint32_t format, struct format_metadata *metadata, uint64_t use_flags) { @@ -641,27 +573,31 @@ bool drv_has_modifier(const uint64_t *list, uint32_t count, uint64_t modifier) return false; } -/* - * Map internal fourcc codes back to standard fourcc codes. - */ -uint32_t drv_get_standard_fourcc(uint32_t fourcc_internal) -{ - return (fourcc_internal == DRM_FORMAT_YVU420_ANDROID) ? DRM_FORMAT_YVU420 : fourcc_internal; -} - -uint32_t drv_resolve_format_helper(struct driver *drv, uint32_t format, uint64_t use_flags) +void drv_resolve_format_and_use_flags_helper(struct driver *drv, uint32_t format, + uint64_t use_flags, uint32_t *out_format, + uint64_t *out_use_flags) { + *out_format = format; + *out_use_flags = use_flags; switch (format) { case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED: /* Common camera implementation defined format. */ - if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE)) - return DRM_FORMAT_NV12; - /* A common hack: See b/28671744 */ - return DRM_FORMAT_XBGR8888; + if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE)) { + *out_format = DRM_FORMAT_NV12; + } else { + /* HACK: See b/28671744 */ + *out_format = DRM_FORMAT_XBGR8888; + *out_use_flags &= ~BO_USE_HW_VIDEO_ENCODER; + } + break; case DRM_FORMAT_FLEX_YCbCr_420_888: /* Common flexible video format. */ - return DRM_FORMAT_NV12; + *out_format = DRM_FORMAT_NV12; + break; + case DRM_FORMAT_YVU420_ANDROID: + *out_use_flags &= ~BO_USE_SCANOUT; + break; default: - return format; + break; } } diff --git a/helpers.h b/drv_helpers.h index d906dcf..edb69bf 100644 --- a/helpers.h +++ b/drv_helpers.h @@ -4,22 +4,20 @@ * found in the LICENSE file. */ -#ifndef HELPERS_H -#define HELPERS_H - -#ifdef __cplusplus -extern "C" { -#endif +#ifndef DRV_HELPERS_H +#define DRV_HELPERS_H #include <stdbool.h> #include "drv.h" -#include "helpers_array.h" +#include "drv_array_helpers.h" #ifndef PAGE_SIZE #define PAGE_SIZE 0x1000 #endif +struct format_metadata; + uint32_t drv_height_from_format(uint32_t format, uint32_t height, size_t plane); uint32_t drv_vertical_subsampling_from_format(uint32_t format, size_t plane); uint32_t drv_size_from_format(uint32_t format, uint32_t stride, uint32_t height, size_t plane); @@ -35,11 +33,7 @@ int drv_gem_bo_destroy(struct bo *bo); int drv_prime_bo_import(struct bo *bo, struct drv_import_fd_data *data); void *drv_dumb_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags); int drv_bo_munmap(struct bo *bo, struct vma *vma); -int drv_mapping_destroy(struct bo *bo); int drv_get_prot(uint32_t map_flags); -uintptr_t drv_get_reference_count(struct driver *drv, struct bo *bo, size_t plane); -void drv_increment_reference_count(struct driver *drv, struct bo *bo, size_t plane); -void drv_decrement_reference_count(struct driver *drv, struct bo *bo, size_t plane); void drv_add_combination(struct driver *drv, uint32_t format, struct format_metadata *metadata, uint64_t usage); void drv_add_combinations(struct driver *drv, const uint32_t *formats, uint32_t num_formats, @@ -50,11 +44,8 @@ int drv_modify_linear_combinations(struct driver *drv); uint64_t drv_pick_modifier(const uint64_t *modifiers, uint32_t count, const uint64_t *modifier_order, uint32_t order_count); bool drv_has_modifier(const uint64_t *list, uint32_t count, uint64_t modifier); -uint32_t drv_get_standard_fourcc(uint32_t fourcc_internal); -uint32_t drv_resolve_format_helper(struct driver *drv, uint32_t format, uint64_t use_flags); - -#ifdef __cplusplus -} -#endif +void drv_resolve_format_and_use_flags_helper(struct driver *drv, uint32_t format, + uint64_t use_flags, uint32_t *out_format, + uint64_t *out_use_flags); #endif @@ -34,7 +34,7 @@ struct bo_metadata { * specific metadata. It's easiest just to stuff all the metadata here rather than * having two metadata structs. */ - uint64_t blob_id; + uint32_t blob_id; uint32_t map_info; int32_t memory_idx; int32_t physical_device_idx; @@ -64,10 +64,11 @@ struct driver { int fd; const struct backend *backend; void *priv; + pthread_mutex_t buffer_table_lock; void *buffer_table; + pthread_mutex_t mappings_lock; struct drv_array *mappings; struct drv_array *combos; - pthread_mutex_t driver_lock; bool compression; }; @@ -84,16 +85,22 @@ struct backend { int (*bo_compute_metadata)(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, uint64_t use_flags, const uint64_t *modifiers, uint32_t count); int (*bo_create_from_metadata)(struct bo *bo); + /* Called for every non-test-buffer BO on free */ + int (*bo_release)(struct bo *bo); + /* Called on free if this bo is the last object referencing the contained GEM BOs */ int (*bo_destroy)(struct bo *bo); int (*bo_import)(struct bo *bo, struct drv_import_fd_data *data); void *(*bo_map)(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags); int (*bo_unmap)(struct bo *bo, struct vma *vma); int (*bo_invalidate)(struct bo *bo, struct mapping *mapping); int (*bo_flush)(struct bo *bo, struct mapping *mapping); - uint32_t (*resolve_format)(struct driver *drv, uint32_t format, uint64_t use_flags); + void (*resolve_format_and_use_flags)(struct driver *drv, uint32_t format, + uint64_t use_flags, uint32_t *out_format, + uint64_t *out_use_flags); size_t (*num_planes_from_modifier)(struct driver *drv, uint32_t format, uint64_t modifier); int (*resource_info)(struct bo *bo, uint32_t strides[DRV_MAX_PLANES], uint32_t offsets[DRV_MAX_PLANES], uint64_t *format_modifier); + uint32_t (*get_max_texture_2d_size)(struct driver *drv); }; // clang-format off @@ -109,7 +116,7 @@ struct backend { BO_USE_SW_READ_RARELY | BO_USE_SW_WRITE_RARELY | BO_USE_FRONT_RENDERING) #define BO_USE_NON_GPU_HW (BO_USE_SCANOUT | BO_USE_CAMERA_WRITE | BO_USE_CAMERA_READ | \ - BO_USE_HW_VIDEO_ENCODER | BO_USE_HW_VIDEO_DECODER) + BO_USE_HW_VIDEO_ENCODER | BO_USE_HW_VIDEO_DECODER | BO_USE_SENSOR_DIRECT_DATA) #ifndef DRM_FORMAT_MOD_LINEAR #define DRM_FORMAT_MOD_LINEAR DRM_FORMAT_MOD_NONE diff --git a/dumb_driver.c b/dumb_driver.c index f5a62aa..c667a51 100644 --- a/dumb_driver.c +++ b/dumb_driver.c @@ -4,8 +4,10 @@ * found in the LICENSE file. */ +#include <errno.h> + +#include "drv_helpers.h" #include "drv_priv.h" -#include "helpers.h" #include "util.h" #define INIT_DUMB_DRIVER(driver) \ @@ -13,17 +15,19 @@ .name = #driver, \ .init = dumb_driver_init, \ .bo_create = drv_dumb_bo_create, \ + .bo_create_with_modifiers = dumb_bo_create_with_modifiers, \ .bo_destroy = drv_dumb_bo_destroy, \ .bo_import = drv_prime_bo_import, \ .bo_map = drv_dumb_bo_map, \ .bo_unmap = drv_bo_munmap, \ + .resolve_format_and_use_flags = drv_resolve_format_and_use_flags_helper, \ }; static const uint32_t scanout_render_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888, DRM_FORMAT_ABGR8888, DRM_FORMAT_XBGR8888, - DRM_FORMAT_BGR888, DRM_FORMAT_BGR565 }; + DRM_FORMAT_BGR888, DRM_FORMAT_RGB565 }; -static const uint32_t texture_only_formats[] = { DRM_FORMAT_NV12, DRM_FORMAT_NV21, +static const uint32_t texture_only_formats[] = { DRM_FORMAT_R8, DRM_FORMAT_NV12, DRM_FORMAT_NV21, DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID }; static int dumb_driver_init(struct driver *drv) @@ -34,6 +38,9 @@ static int dumb_driver_init(struct driver *drv) drv_add_combinations(drv, texture_only_formats, ARRAY_SIZE(texture_only_formats), &LINEAR_METADATA, BO_USE_TEXTURE_MASK); + drv_modify_combination(drv, DRM_FORMAT_R8, &LINEAR_METADATA, + BO_USE_HW_VIDEO_ENCODER | BO_USE_HW_VIDEO_DECODER | + BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE); drv_modify_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA, BO_USE_HW_VIDEO_ENCODER | BO_USE_HW_VIDEO_DECODER | BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE); @@ -42,6 +49,18 @@ static int dumb_driver_init(struct driver *drv) return drv_modify_linear_combinations(drv); } +static int dumb_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint32_t height, + uint32_t format, const uint64_t *modifiers, uint32_t count) +{ + for (uint32_t i = 0; i < count; i++) { + if (modifiers[i] == DRM_FORMAT_MOD_LINEAR) { + return drv_dumb_bo_create(bo, width, height, format, 0); + } + } + + return -EINVAL; +} + INIT_DUMB_DRIVER(evdi) INIT_DUMB_DRIVER(komeda) INIT_DUMB_DRIVER(marvell) diff --git a/external/i915_drm.h b/external/i915_drm.h index f5991a8..e301c5f 100644 --- a/external/i915_drm.h +++ b/external/i915_drm.h @@ -359,7 +359,7 @@ typedef struct _drm_i915_sarea { #define DRM_I915_QUERY 0x39 #define DRM_I915_GEM_VM_CREATE 0x3a #define DRM_I915_GEM_VM_DESTROY 0x3b -#define DRM_I915_PXP_OPS 0x3c +#define DRM_I915_GEM_CREATE_EXT 0x3c /* Must be kept compact -- no holes */ #define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t) @@ -392,7 +392,7 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_GEM_ENTERVT DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_ENTERVT) #define DRM_IOCTL_I915_GEM_LEAVEVT DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_LEAVEVT) #define DRM_IOCTL_I915_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_CREATE, struct drm_i915_gem_create) -#define DRM_IOCTL_I915_GEM_CREATE_EXT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_CREATE, struct drm_i915_gem_create_ext) +#define DRM_IOCTL_I915_GEM_CREATE_EXT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_CREATE_EXT, struct drm_i915_gem_create_ext) #define DRM_IOCTL_I915_GEM_PREAD DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PREAD, struct drm_i915_gem_pread) #define DRM_IOCTL_I915_GEM_PWRITE DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_PWRITE, struct drm_i915_gem_pwrite) #define DRM_IOCTL_I915_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct drm_i915_gem_mmap) @@ -424,7 +424,6 @@ typedef struct _drm_i915_sarea { #define DRM_IOCTL_I915_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query) #define DRM_IOCTL_I915_GEM_VM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_VM_CREATE, struct drm_i915_gem_vm_control) #define DRM_IOCTL_I915_GEM_VM_DESTROY DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_VM_DESTROY, struct drm_i915_gem_vm_control) -#define DRM_IOCTL_I915_PXP_OPS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_PXP_OPS, struct drm_i915_pxp_ops) /* Allow drivers to submit batchbuffers directly to hardware, relying * on the security mechanisms provided by hardware. @@ -725,27 +724,6 @@ struct drm_i915_gem_create { __u32 pad; }; -struct drm_i915_gem_create_ext { - /** - * Requested size for the object. - * - * The (page-aligned) allocated size for the object will be returned. - */ - __u64 size; - /** - * Returned handle for the object. - * - * Object handles are nonzero. - */ - __u32 handle; - __u32 pad; -#define I915_GEM_CREATE_EXT_SETPARAM (1u << 0) -#define I915_GEM_CREATE_EXT_FLAGS_UNKNOWN \ - (-(I915_GEM_CREATE_EXT_SETPARAM << 1)) - __u64 extensions; - -}; - struct drm_i915_gem_pread { /** Handle for the object being read. */ __u32 handle; @@ -1645,51 +1623,28 @@ struct drm_i915_gem_context_param { #define I915_CONTEXT_PARAM_PERSISTENCE 0xb /* - * I915_CONTEXT_PARAM_PROTECTED_CONTENT: + * I915_CONTEXT_PARAM_RINGSIZE: * - * If set to true (1) PAVP content protection is enabled. - * When enabled, the context is marked unrecoverable and may - * become invalid due to PAVP teardown event or other error. - */ -#define I915_CONTEXT_PARAM_PROTECTED_CONTENT 0xd -/* Must be kept compact -- no holes and well documented */ - - __u64 value; -}; - -struct drm_i915_gem_object_param { - /* Object handle (0 for I915_GEM_CREATE_EXT_SETPARAM) */ - __u32 handle; - - /* Data pointer size */ - __u32 size; - -/* - * I915_OBJECT_PARAM: + * Sets the size of the CS ringbuffer to use for logical ring contexts. This + * applies a limit of how many batches can be queued to HW before the caller + * is blocked due to lack of space for more commands. * - * Select object namespace for the param. - */ -#define I915_OBJECT_PARAM (1ull<<32) - -/* - * I915_PARAM_PROTECTED_CONTENT: + * Only reliably possible to be set prior to first use, i.e. during + * construction. At any later point, the current execution must be flushed as + * the ring can only be changed while the context is idle. Note, the ringsize + * can be specified as a constructor property, see + * I915_CONTEXT_CREATE_EXT_SETPARAM, but can also be set later if required. + * + * Only applies to the current set of engine and lost when those engines + * are replaced by a new mapping (see I915_CONTEXT_PARAM_ENGINES). * - * If set to true (1) buffer contents is expected to be protected by - * PAVP encryption and requires decryption for scan out and processing. - * Protected buffers can only be used in PAVP protected contexts. - * A protected buffer may become invalid as a result of PAVP teardown. + * Must be between 4 - 512 KiB, in intervals of page size [4 KiB]. + * Default is 16 KiB. */ -#define I915_PARAM_PROTECTED_CONTENT 0x1 - - __u64 param; - - /* Data value or pointer */ - __u64 data; -}; +#define I915_CONTEXT_PARAM_RINGSIZE 0xc +/* Must be kept compact -- no holes and well documented */ -struct drm_i915_gem_create_ext_setparam { - struct i915_user_extension base; - struct drm_i915_gem_object_param param; + __u64 value; }; /** @@ -1892,76 +1847,6 @@ struct drm_i915_gem_vm_control { __u32 vm_id; }; -/* - * struct pxp_sm_query_pxp_tag - Params to query the PXP tag of specified - * session id and whether the session is alive from PXP state machine. - */ -struct pxp_sm_query_pxp_tag { - __u32 session_is_alive; - __u32 pxp_tag; /* in - Session ID, out pxp tag */ -}; - -/* - * struct pxp_set_session_status_params - Params to reserved, set or destroy - * the session from the PXP state machine. - */ -struct pxp_set_session_status_params { - __u32 pxp_tag; /* in [optional], for Arbitrator session, out pxp tag */ - __u32 session_type; /* in, session type */ - __u32 session_mode; /* in, session mode */ - __u32 req_session_state; /* in, new session state */ -}; - -/* - * struct pxp_tee_io_message_params - Params to send/receive message to/from TEE. - */ -struct pxp_tee_io_message_params { - __u8 *msg_in; /* in - message input */ - __u32 msg_in_size; /* in - message input size */ - __u8 *msg_out; /* in - message output buffer */ - __u32 msg_out_size; /* out- message output size from TEE */ - __u32 msg_out_buf_size; /* in - message output buffer size */ -}; - -/* - * struct pxp_info - Params for PXP operation. - */ -struct pxp_info { - __u32 action; /* in - specified action of this operation */ - __u32 sm_status; /* out - status output for this operation */ - - union { - /* in - action params to query PXP tag */ - struct pxp_sm_query_pxp_tag query_pxp_tag; - /* in - action params to set the PXP session state */ - struct pxp_set_session_status_params set_session_status; - /* in - action params to send TEE commands */ - struct pxp_tee_io_message_params tee_io_message; - - /* in - action params to set user space context */ - __u32 set_user_ctx; - }; -} __attribute__((packed)); - -/* - * DRM_I915_PXP_OPS - - * - * PXP is an i915 componment, that helps user space to establish the hardware - * protected session and manage the status of each alive software session, - * as well as the life cycle of each session. - * - * This ioctl is to allow user space driver to create, set, and destroy each - * session. It also provides the communication chanel to TEE (Trusted - * Execution Environment) for the protected hardware session creation. - */ -struct drm_i915_pxp_ops { - /* in - user space pointer to struct pxp_info */ - struct pxp_info *info_ptr; - - /* in - memory size that info_ptr points to */ - __u32 info_size; -}; - struct drm_i915_reg_read { /* * Register offset. @@ -2086,6 +1971,17 @@ enum drm_i915_perf_property_id { */ DRM_I915_PERF_PROP_HOLD_PREEMPTION, + /** + * Specifying this pins all contexts to the specified SSEU power + * configuration for the duration of the recording. + * + * This parameter's value is a pointer to a struct + * drm_i915_gem_context_param_sseu. + * + * This property is available in perf revision 4. + */ + DRM_I915_PERF_PROP_GLOBAL_SSEU, + DRM_I915_PERF_PROP_MAX /* non-ABI */ }; @@ -2415,6 +2311,77 @@ struct drm_i915_query_perf_config { __u8 data[]; }; +/** + * struct drm_i915_gem_create_ext - Existing gem_create behaviour, with added + * extension support using struct i915_user_extension. + * + * Note that in the future we want to have our buffer flags here, at least for + * the stuff that is immutable. Previously we would have two ioctls, one to + * create the object with gem_create, and another to apply various parameters, + * however this creates some ambiguity for the params which are considered + * immutable. Also in general we're phasing out the various SET/GET ioctls. + */ +struct drm_i915_gem_create_ext { + /** + * @size: Requested size for the object. + * + * The (page-aligned) allocated size for the object will be returned. + * + */ + __u64 size; + /** + * @handle: Returned handle for the object. + * + * Object handles are nonzero. + */ + __u32 handle; + /** @flags: MBZ */ + __u32 flags; + /** + * @extensions: The chain of extensions to apply to this object. + * + * This will be useful in the future when we need to support several + * different extensions, and we need to apply more than one when + * creating the object. See struct i915_user_extension. + * + * If we don't supply any extensions then we get the same old gem_create + * behaviour. + * + * For I915_GEM_CREATE_EXT_PROTECTED_CONTENT usage see + * struct drm_i915_gem_create_ext_protected_content. + */ +#define I915_GEM_CREATE_EXT_PROTECTED_CONTENT 1 + __u64 extensions; +}; + +/** + * struct drm_i915_gem_create_ext_protected_content - The + * I915_OBJECT_PARAM_PROTECTED_CONTENT extension. + * + * If this extension is provided, buffer contents are expected to be protected + * by PXP encryption and require decryption for scan out and processing. This + * is only possible on platforms that have PXP enabled, on all other scenarios + * using this extension will cause the ioctl to fail and return -ENODEV. The + * flags parameter is reserved for future expansion and must currently be set + * to zero. + * + * The buffer contents are considered invalid after a PXP session teardown. + * + * The encryption is guaranteed to be processed correctly only if the object + * is submitted with a context created using the + * I915_CONTEXT_PARAM_PROTECTED_CONTENT flag. This will also enable extra checks + * at submission time on the validity of the objects involved. + */ +struct drm_i915_gem_create_ext_protected_content { + /** @base: Extension link. See struct i915_user_extension. */ + struct i915_user_extension base; + /** @flags: reserved for future usage, currently MBZ */ + __u32 flags; +}; + +/* ID of the protected content session managed by i915 when PXP is active */ +#define I915_PROTECTED_CONTENT_DEFAULT_SESSION 0xf + #if defined(__cplusplus) } #endif diff --git a/external/virgl_hw.h b/external/virgl_hw.h index 7f4a63f..4527ced 100644 --- a/external/virgl_hw.h +++ b/external/virgl_hw.h @@ -222,6 +222,12 @@ enum virgl_formats { VIRGL_FORMAT_A4B4G4R4_UNORM = 311, VIRGL_FORMAT_R8_SRGB = 312, + VIRGL_FORMAT_R8G8_SRGB = 313, + + VIRGL_FORMAT_P010 = 314, + VIRGL_FORMAT_P012 = 315, + VIRGL_FORMAT_P016 = 316, + VIRGL_FORMAT_MAX /* = PIPE_FORMAT_COUNT */, /* Below formats must not be used in the guest. */ diff --git a/external/virtgpu_cross_domain_protocol.h b/external/virtgpu_cross_domain_protocol.h index eaeebd3..afae541 100644 --- a/external/virtgpu_cross_domain_protocol.h +++ b/external/virtgpu_cross_domain_protocol.h @@ -10,11 +10,43 @@ // Cross-domain commands (only a maximum of 255 supported) #define CROSS_DOMAIN_CMD_INIT 1 #define CROSS_DOMAIN_CMD_GET_IMAGE_REQUIREMENTS 2 +#define CROSS_DOMAIN_CMD_POLL 3 +#define CROSS_DOMAIN_CMD_SEND 4 +#define CROSS_DOMAIN_CMD_RECEIVE 5 +#define CROSS_DOMAIN_CMD_READ 6 +#define CROSS_DOMAIN_CMD_WRITE 7 // Channel types (must match rutabaga channel types) #define CROSS_DOMAIN_CHANNEL_TYPE_WAYLAND 0x0001 #define CROSS_DOMAIN_CHANNEL_TYPE_CAMERA 0x0002 +// The maximum number of identifiers (value based on wp_linux_dmabuf) +#define CROSS_DOMAIN_MAX_IDENTIFIERS 4 + +// virtgpu memory resource ID. Also works with non-blob memory resources, +// despite the name. +#define CROSS_DOMAIN_ID_TYPE_VIRTGPU_BLOB 1 + +// virtgpu synchronization resource id. +#define CROSS_DOMAIN_ID_TYPE_VIRTGPU_SYNC 2 + +// ID for Wayland pipe used for reading. The reading is done by the guest proxy +// and the host proxy. The host sends the write end of the proxied pipe over +// the host Wayland socket. +#define CROSS_DOMAIN_ID_TYPE_READ_PIPE 3 + +// ID for Wayland pipe used for writing. The writing is done by the guest and +// the host proxy. The host receives the write end of the pipe over the host +// Wayland socket. +#define CROSS_DOMAIN_ID_TYPE_WRITE_PIPE 4 + +// No ring used +#define CROSS_DOMAIN_RING_NONE 0xffffffff +// A ring for metadata queries. +#define CROSS_DOMAIN_QUERY_RING 0 +// A ring based on this particular context's channel. +#define CROSS_DOMAIN_CHANNEL_RING 1 + struct CrossDomainCapabilities { uint32_t version; uint32_t supported_channels; @@ -27,9 +59,8 @@ struct CrossDomainImageRequirements { uint32_t offsets[4]; uint64_t modifier; uint64_t size; - uint64_t blob_id; + uint32_t blob_id; uint32_t map_info; - uint32_t pad; int32_t memory_idx; int32_t physical_device_idx; }; @@ -55,4 +86,26 @@ struct CrossDomainGetImageRequirements { uint32_t flags; }; +struct CrossDomainPoll { + struct CrossDomainHeader hdr; + uint64_t pad; +}; + +struct CrossDomainSendReceive { + struct CrossDomainHeader hdr; + uint32_t num_identifiers; + uint32_t opaque_data_size; + uint32_t identifiers[CROSS_DOMAIN_MAX_IDENTIFIERS]; + uint32_t identifier_types[CROSS_DOMAIN_MAX_IDENTIFIERS]; + uint32_t identifier_sizes[CROSS_DOMAIN_MAX_IDENTIFIERS]; +}; + +struct CrossDomainReadWrite { + struct CrossDomainHeader hdr; + uint32_t identifier; + uint32_t hang_up; + uint32_t opaque_data_size; + uint32_t pad; +}; + #endif diff --git a/external/virtgpu_drm.h b/external/virtgpu_drm.h index 9b46138..7720900 100644 --- a/external/virtgpu_drm.h +++ b/external/virtgpu_drm.h @@ -51,11 +51,11 @@ extern "C" { #define VIRTGPU_EXECBUF_FENCE_FD_IN 0x01 #define VIRTGPU_EXECBUF_FENCE_FD_OUT 0x02 -#define VIRTGPU_EXECBUF_FENCE_CONTEXT 0x04 +#define VIRTGPU_EXECBUF_RING_IDX 0x04 #define VIRTGPU_EXECBUF_FLAGS (\ VIRTGPU_EXECBUF_FENCE_FD_IN |\ VIRTGPU_EXECBUF_FENCE_FD_OUT |\ - VIRTGPU_EXECBUF_FENCE_CONTEXT |\ + VIRTGPU_EXECBUF_RING_IDX |\ 0) struct drm_virtgpu_map { @@ -208,8 +208,9 @@ struct drm_virtgpu_resource_create_blob { __u64 blob_id; }; -#define VIRTGPU_CONTEXT_PARAM_CAPSET_ID 0x0001 -#define VIRTGPU_CONTEXT_PARAM_NUM_FENCE_CONTEXTS 0x0002 +#define VIRTGPU_CONTEXT_PARAM_CAPSET_ID 0x0001 +#define VIRTGPU_CONTEXT_PARAM_NUM_RINGS 0x0002 +#define VIRTGPU_CONTEXT_PARAM_POLL_RINGS_MASK 0x0003 struct drm_virtgpu_context_set_param { __u64 param; __u64 value; diff --git a/exynos.c b/exynos.c deleted file mode 100644 index 5862643..0000000 --- a/exynos.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2014 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifdef DRV_EXYNOS - -// clang-format off -#include <assert.h> -#include <errno.h> -#include <stdio.h> -#include <string.h> -#include <xf86drm.h> -#include <exynos_drm.h> -// clang-format on - -#include "drv_priv.h" -#include "helpers.h" -#include "util.h" - -static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888 }; - -static const uint32_t texture_source_formats[] = { DRM_FORMAT_NV12 }; - -static int exynos_init(struct driver *drv) -{ - drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), - &LINEAR_METADATA, BO_USE_RENDER_MASK); - - drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats), - &LINEAR_METADATA, BO_USE_TEXTURE_MASK); - - return drv_modify_linear_combinations(drv); -} - -static int exynos_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, - uint64_t use_flags) -{ - size_t plane; - - if (format == DRM_FORMAT_NV12) { - uint32_t chroma_height; - /* V4L2 s5p-mfc requires width to be 16 byte aligned and height 32. */ - width = ALIGN(width, 16); - height = ALIGN(height, 32); - chroma_height = ALIGN(height / 2, 32); - bo->meta.strides[0] = bo->meta.strides[1] = width; - /* MFC v8+ requires 64 byte padding in the end of luma and chroma buffers. */ - bo->meta.sizes[0] = bo->meta.strides[0] * height + 64; - bo->meta.sizes[1] = bo->meta.strides[1] * chroma_height + 64; - bo->meta.offsets[0] = bo->meta.offsets[1] = 0; - bo->meta.total_size = bo->meta.sizes[0] + bo->meta.sizes[1]; - } else if (format == DRM_FORMAT_XRGB8888 || format == DRM_FORMAT_ARGB8888) { - bo->meta.strides[0] = drv_stride_from_format(format, width, 0); - bo->meta.total_size = bo->meta.sizes[0] = height * bo->meta.strides[0]; - bo->meta.offsets[0] = 0; - } else { - drv_log("unsupported format %X\n", format); - assert(0); - return -EINVAL; - } - - int ret; - for (plane = 0; plane < bo->meta.num_planes; plane++) { - size_t size = bo->meta.sizes[plane]; - struct drm_exynos_gem_create gem_create = { 0 }; - - gem_create.size = size; - gem_create.flags = EXYNOS_BO_NONCONTIG; - - ret = drmIoctl(bo->drv->fd, DRM_IOCTL_EXYNOS_GEM_CREATE, &gem_create); - if (ret) { - drv_log("DRM_IOCTL_EXYNOS_GEM_CREATE failed (size=%zu)\n", size); - ret = -errno; - goto cleanup_planes; - } - - bo->handles[plane].u32 = gem_create.handle; - } - - return 0; - -cleanup_planes: - for (; plane != 0; plane--) { - struct drm_gem_close gem_close = { 0 }; - - gem_close.handle = bo->handles[plane - 1].u32; - int gem_close_ret = drmIoctl(bo->drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close); - if (gem_close_ret) { - drv_log("DRM_IOCTL_GEM_CLOSE failed: %d\n", gem_close_ret); - } - } - - return ret; -} - -/* - * Use dumb mapping with exynos even though a GEM buffer is created. - * libdrm does the same thing in exynos_drm.c - */ -const struct backend backend_exynos = { - .name = "exynos", - .init = exynos_init, - .bo_create = exynos_bo_create, - .bo_destroy = drv_gem_bo_destroy, - .bo_import = drv_prime_bo_import, - .bo_map = drv_dumb_bo_map, - .bo_unmap = drv_bo_munmap, -}; - -#endif @@ -140,9 +140,9 @@ PUBLIC struct gbm_bo *gbm_bo_create(struct gbm_device *gbm, uint32_t width, uint return NULL; /* - * HACK: This is for HAL_PIXEL_FORMAT_YV12 buffers allocated by arcvm. None of - * our platforms can display YV12, so we can treat as a SW buffer. Remove once - * this can be intelligently resolved in the guest. Also see compute_virgl_bind_flags. + * HACK: See b/132939420. This is for HAL_PIXEL_FORMAT_YV12 buffers allocated by arcvm. None + * of our platforms can display YV12, so we can treat as a SW buffer. Remove once this can + * be intelligently resolved in the guest. Also see virgl_resolve_use_flags. */ if (format == GBM_FORMAT_YVU420 && (usage & GBM_BO_USE_LINEAR)) format = DRM_FORMAT_YVU420_ANDROID; @@ -15,9 +15,9 @@ #include <unistd.h> #include <xf86drm.h> +#include "drv_helpers.h" #include "drv_priv.h" #include "external/i915_drm.h" -#include "helpers.h" #include "util.h" #define I915_CACHELINE_SIZE 64 @@ -37,6 +37,10 @@ static const uint32_t texture_only_formats[] = { DRM_FORMAT_R8, DRM_FORMAT_NV12, static const uint64_t gen_modifier_order[] = { I915_FORMAT_MOD_Y_TILED_CCS, I915_FORMAT_MOD_Y_TILED, I915_FORMAT_MOD_X_TILED, DRM_FORMAT_MOD_LINEAR }; +static const uint64_t gen12_modifier_order[] = { I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS, + I915_FORMAT_MOD_Y_TILED, I915_FORMAT_MOD_X_TILED, + DRM_FORMAT_MOD_LINEAR }; + static const uint64_t gen11_modifier_order[] = { I915_FORMAT_MOD_Y_TILED, I915_FORMAT_MOD_X_TILED, DRM_FORMAT_MOD_LINEAR }; @@ -58,13 +62,51 @@ static void i915_info_from_device_id(struct i915_device *i915) { const uint16_t gen3_ids[] = { 0x2582, 0x2592, 0x2772, 0x27A2, 0x27AE, 0x29C2, 0x29B2, 0x29D2, 0xA001, 0xA011 }; - const uint16_t gen11_ids[] = { 0x4E71, 0x4E61, 0x4E51, 0x4E55, 0x4E57 }; - const uint16_t gen12_ids[] = { 0x9A40, 0x9A49, 0x9A59, 0x9A60, 0x9A68, 0x9A70, - 0x9A78, 0x9AC0, 0x9AC9, 0x9AD9, 0x9AF8 }; - const uint16_t adlp_ids[] = { 0x46A0, 0x46A1, 0x46A2, 0x46A3, 0x46A6, - 0x46A8, 0x46AA, 0x462A, 0x4626, 0x4628, - 0x46B0, 0x46B1, 0x46B2, 0x46B3, 0x46C0, - 0x46C1, 0x46C2, 0x46C3 }; + const uint16_t gen4_ids[] = { 0x29A2, 0x2992, 0x2982, 0x2972, 0x2A02, 0x2A12, 0x2A42, + 0x2E02, 0x2E12, 0x2E22, 0x2E32, 0x2E42, 0x2E92 }; + const uint16_t gen5_ids[] = { 0x0042, 0x0046 }; + const uint16_t gen6_ids[] = { 0x0102, 0x0112, 0x0122, 0x0106, 0x0116, 0x0126, 0x010A }; + const uint16_t gen7_ids[] = { + 0x0152, 0x0162, 0x0156, 0x0166, 0x015a, 0x016a, 0x0402, 0x0412, 0x0422, + 0x0406, 0x0416, 0x0426, 0x040A, 0x041A, 0x042A, 0x040B, 0x041B, 0x042B, + 0x040E, 0x041E, 0x042E, 0x0C02, 0x0C12, 0x0C22, 0x0C06, 0x0C16, 0x0C26, + 0x0C0A, 0x0C1A, 0x0C2A, 0x0C0B, 0x0C1B, 0x0C2B, 0x0C0E, 0x0C1E, 0x0C2E, + 0x0A02, 0x0A12, 0x0A22, 0x0A06, 0x0A16, 0x0A26, 0x0A0A, 0x0A1A, 0x0A2A, + 0x0A0B, 0x0A1B, 0x0A2B, 0x0A0E, 0x0A1E, 0x0A2E, 0x0D02, 0x0D12, 0x0D22, + 0x0D06, 0x0D16, 0x0D26, 0x0D0A, 0x0D1A, 0x0D2A, 0x0D0B, 0x0D1B, 0x0D2B, + 0x0D0E, 0x0D1E, 0x0D2E, 0x0F31, 0x0F32, 0x0F33, 0x0157, 0x0155 + }; + const uint16_t gen8_ids[] = { 0x22B0, 0x22B1, 0x22B2, 0x22B3, 0x1602, 0x1606, + 0x160A, 0x160B, 0x160D, 0x160E, 0x1612, 0x1616, + 0x161A, 0x161B, 0x161D, 0x161E, 0x1622, 0x1626, + 0x162A, 0x162B, 0x162D, 0x162E }; + const uint16_t gen9_ids[] = { + 0x1902, 0x1906, 0x190A, 0x190B, 0x190E, 0x1912, 0x1913, 0x1915, 0x1916, 0x1917, + 0x191A, 0x191B, 0x191D, 0x191E, 0x1921, 0x1923, 0x1926, 0x1927, 0x192A, 0x192B, + 0x192D, 0x1932, 0x193A, 0x193B, 0x193D, 0x0A84, 0x1A84, 0x1A85, 0x5A84, 0x5A85, + 0x3184, 0x3185, 0x5902, 0x5906, 0x590A, 0x5908, 0x590B, 0x590E, 0x5913, 0x5915, + 0x5917, 0x5912, 0x5916, 0x591A, 0x591B, 0x591D, 0x591E, 0x5921, 0x5923, 0x5926, + 0x5927, 0x593B, 0x591C, 0x87C0, 0x87CA, 0x3E90, 0x3E93, 0x3E99, 0x3E9C, 0x3E91, + 0x3E92, 0x3E96, 0x3E98, 0x3E9A, 0x3E9B, 0x3E94, 0x3EA9, 0x3EA5, 0x3EA6, 0x3EA7, + 0x3EA8, 0x3EA1, 0x3EA4, 0x3EA0, 0x3EA3, 0x3EA2, 0x9B21, 0x9BA0, 0x9BA2, 0x9BA4, + 0x9BA5, 0x9BA8, 0x9BAA, 0x9BAB, 0x9BAC, 0x9B41, 0x9BC0, 0x9BC2, 0x9BC4, 0x9BC5, + 0x9BC6, 0x9BC8, 0x9BCA, 0x9BCB, 0x9BCC, 0x9BE6, 0x9BF6 + }; + const uint16_t gen11_ids[] = { 0x8A50, 0x8A51, 0x8A52, 0x8A53, 0x8A54, 0x8A56, 0x8A57, + 0x8A58, 0x8A59, 0x8A5A, 0x8A5B, 0x8A5C, 0x8A5D, 0x8A71, + 0x4500, 0x4541, 0x4551, 0x4555, 0x4557, 0x4571, 0x4E51, + 0x4E55, 0x4E57, 0x4E61, 0x4E71 }; + const uint16_t gen12_ids[] = { + 0x4c8a, 0x4c8b, 0x4c8c, 0x4c90, 0x4c9a, 0x4680, 0x4681, 0x4682, 0x4683, 0x4688, + 0x4689, 0x4690, 0x4691, 0x4692, 0x4693, 0x4698, 0x4699, 0x4626, 0x4628, 0x462a, + 0x46a0, 0x46a1, 0x46a2, 0x46a3, 0x46a6, 0x46a8, 0x46aa, 0x46b0, 0x46b1, 0x46b2, + 0x46b3, 0x46c0, 0x46c1, 0x46c2, 0x46c3, 0x9A40, 0x9A49, 0x9A59, 0x9A60, 0x9A68, + 0x9A70, 0x9A78, 0x9AC0, 0x9AC9, 0x9AD9, 0x9AF8, 0x4905, 0x4906, 0x4907, 0x4908 + }; + const uint16_t adlp_ids[] = { 0x46A0, 0x46A1, 0x46A2, 0x46A3, 0x46A6, 0x46A8, + 0x46AA, 0x462A, 0x4626, 0x4628, 0x46B0, 0x46B1, + 0x46B2, 0x46B3, 0x46C0, 0x46C1, 0x46C2, 0x46C3, + 0x46D0, 0x46D1, 0x46D2 }; unsigned i; i915->gen = 4; i915->is_adlp = false; @@ -73,6 +115,36 @@ static void i915_info_from_device_id(struct i915_device *i915) if (gen3_ids[i] == i915->device_id) i915->gen = 3; + /* Gen 4 */ + for (i = 0; i < ARRAY_SIZE(gen4_ids); i++) + if (gen4_ids[i] == i915->device_id) + i915->gen = 4; + + /* Gen 5 */ + for (i = 0; i < ARRAY_SIZE(gen5_ids); i++) + if (gen5_ids[i] == i915->device_id) + i915->gen = 5; + + /* Gen 6 */ + for (i = 0; i < ARRAY_SIZE(gen6_ids); i++) + if (gen6_ids[i] == i915->device_id) + i915->gen = 6; + + /* Gen 7 */ + for (i = 0; i < ARRAY_SIZE(gen7_ids); i++) + if (gen7_ids[i] == i915->device_id) + i915->gen = 7; + + /* Gen 8 */ + for (i = 0; i < ARRAY_SIZE(gen8_ids); i++) + if (gen8_ids[i] == i915->device_id) + i915->gen = 8; + + /* Gen 9 */ + for (i = 0; i < ARRAY_SIZE(gen9_ids); i++) + if (gen9_ids[i] == i915->device_id) + i915->gen = 9; + /* Gen 11 */ for (i = 0; i < ARRAY_SIZE(gen11_ids); i++) if (gen11_ids[i] == i915->device_id) @@ -92,7 +164,11 @@ static void i915_info_from_device_id(struct i915_device *i915) static void i915_get_modifier_order(struct i915_device *i915) { - if (i915->gen == 11) { + if (i915->gen == 12) { + i915->modifier.order = gen12_modifier_order; + i915->modifier.count = ARRAY_SIZE(gen12_modifier_order); + } + else if (i915->gen == 11) { i915->modifier.order = gen11_modifier_order; i915->modifier.count = ARRAY_SIZE(gen11_modifier_order); } else { @@ -249,10 +325,6 @@ static int i915_align_dimensions(struct bo *bo, uint32_t tiling, uint32_t *strid *stride = horizontal_alignment; } - /* stride must be power-of-two aligned for ADL-P tiled buffers*/ - if (i915->is_adlp && (*stride > 1) && (tiling != I915_TILING_NONE)) - *stride = 1 << (32 - __builtin_clz(*stride -1)); - if (i915->gen <= 3 && *stride > 8192) return -EINVAL; @@ -316,7 +388,8 @@ static int i915_init(struct driver *drv) * to the largest coded unit (LCU) assuming that it will be used for video. This * is based on gmmlib's GmmIsYUVFormatLCUAligned(). */ -static bool i915_format_needs_LCU_alignment(uint32_t format, size_t plane, const struct i915_device* i915) +static bool i915_format_needs_LCU_alignment(uint32_t format, size_t plane, + const struct i915_device *i915) { switch (format) { case DRM_FORMAT_NV12: @@ -368,6 +441,19 @@ static int i915_bo_from_format(struct bo *bo, uint32_t width, uint32_t height, u return 0; } +static size_t i915_num_planes_from_modifier(struct driver *drv, uint32_t format, + uint64_t modifier) +{ + size_t num_planes = drv_num_planes_from_format(format); + if (modifier == I915_FORMAT_MOD_Y_TILED_CCS || + modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS) { + assert(num_planes == 1); + return 2; + } + + return num_planes; +} + static int i915_bo_compute_metadata(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, uint64_t use_flags, const uint64_t *modifiers, uint32_t count) { @@ -418,6 +504,11 @@ static int i915_bo_compute_metadata(struct bo *bo, uint32_t width, uint32_t heig modifier = I915_FORMAT_MOD_Y_TILED; } + /* Prevent gen 8 and earlier from trying to use a tiling modifier */ + if (i915->gen <= 8 && format == DRM_FORMAT_ARGB8888) { + modifier = DRM_FORMAT_MOD_LINEAR; + } + switch (modifier) { case DRM_FORMAT_MOD_LINEAR: bo->meta.tiling = I915_TILING_NONE; @@ -427,6 +518,10 @@ static int i915_bo_compute_metadata(struct bo *bo, uint32_t width, uint32_t heig break; case I915_FORMAT_MOD_Y_TILED: case I915_FORMAT_MOD_Y_TILED_CCS: + /* For now support only I915_TILING_Y as this works with all + * IPs(render/media/display) + */ + case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: bo->meta.tiling = I915_TILING_Y; break; } @@ -483,8 +578,43 @@ static int i915_bo_compute_metadata(struct bo *bo, uint32_t width, uint32_t heig bo->meta.offsets[1] = offset; offset += ccs_size; - bo->meta.num_planes = 2; + bo->meta.num_planes = i915_num_planes_from_modifier(bo->drv, format, modifier); bo->meta.total_size = offset; + } else if (modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS) { + + /* + * considering only 128 byte compression and one cache line of + * aux buffer(64B) contains compression status of 4-Y tiles. + * Which is 4 * (128B * 32L). + * line stride(bytes) is 4 * 128B + * and tile stride(lines) is 32L + */ + uint32_t stride = ALIGN(drv_stride_from_format(format, width, 0), 512); + + height = ALIGN(drv_height_from_format(format, height, 0), 32); + + if (i915->is_adlp && (stride > 1)) { + stride = 1 << (32 - __builtin_clz(stride - 1)); + height = ALIGN(drv_height_from_format(format, height, 0), 128); + } + + bo->meta.strides[0] = stride; + /* size calculation and alignment are 64KB aligned + * size as per spec + */ + bo->meta.sizes[0] = ALIGN(stride * height, 65536); + bo->meta.offsets[0] = 0; + + /* Aux buffer is linear and page aligned. It is placed after + * other planes and aligned to main buffer stride. + */ + bo->meta.strides[1] = bo->meta.strides[0] / 8; + /* Aligned to page size */ + bo->meta.sizes[1] = ALIGN(bo->meta.sizes[0] / 256, getpagesize()); + bo->meta.offsets[1] = bo->meta.sizes[0]; + /* Total number of planes & sizes */ + bo->meta.num_planes = i915_num_planes_from_modifier(bo->drv, format, modifier); + bo->meta.total_size = bo->meta.sizes[0] + bo->meta.sizes[1]; } else { i915_bo_from_format(bo, width, height, format); } @@ -500,25 +630,20 @@ static int i915_bo_create_from_metadata(struct bo *bo) struct i915_device *i915 = bo->drv->priv; if (i915->has_hw_protection && (bo->meta.use_flags & BO_USE_PROTECTED)) { - struct drm_i915_gem_object_param protected_param = { - .param = I915_OBJECT_PARAM | I915_PARAM_PROTECTED_CONTENT, - .data = 1, - }; - - struct drm_i915_gem_create_ext_setparam setparam_protected = { - .base = { .name = I915_GEM_CREATE_EXT_SETPARAM }, - .param = protected_param, + struct drm_i915_gem_create_ext_protected_content protected_content = { + .base = { .name = I915_GEM_CREATE_EXT_PROTECTED_CONTENT }, + .flags = 0, }; struct drm_i915_gem_create_ext create_ext = { .size = bo->meta.total_size, - .extensions = (uintptr_t)&setparam_protected, + .extensions = (uintptr_t)&protected_content, }; ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_CREATE_EXT, &create_ext); if (ret) { - drv_log("DRM_IOCTL_I915_GEM_CREATE_EXT failed (size=%llu)\n", - create_ext.size); + drv_log("DRM_IOCTL_I915_GEM_CREATE_EXT failed (size=%llu) (ret=%d) \n", + create_ext.size, ret); return -errno; } @@ -566,6 +691,9 @@ static int i915_bo_import(struct bo *bo, struct drv_import_fd_data *data) int ret; struct drm_i915_gem_get_tiling gem_get_tiling = { 0 }; + bo->meta.num_planes = i915_num_planes_from_modifier(bo->drv, data->format, + data->format_modifier); + ret = drv_prime_bo_import(bo, data); if (ret) return ret; @@ -592,6 +720,9 @@ static void *i915_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t if (bo->meta.format_modifier == I915_FORMAT_MOD_Y_TILED_CCS) return MAP_FAILED; + if (bo->meta.format_modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS) + return MAP_FAILED; + if (bo->meta.tiling == I915_TILING_NONE) { struct drm_i915_gem_mmap gem_map = { 0 }; /* TODO(b/118799155): We don't seem to have a good way to @@ -692,7 +823,8 @@ const struct backend backend_i915 = { .bo_unmap = drv_bo_munmap, .bo_invalidate = i915_bo_invalidate, .bo_flush = i915_bo_flush, - .resolve_format = drv_resolve_format_helper, + .resolve_format_and_use_flags = drv_resolve_format_and_use_flags_helper, + .num_planes_from_modifier = i915_num_planes_from_modifier, }; #endif @@ -19,12 +19,23 @@ #include <mediatek_drm.h> // clang-format on +#include "drv_helpers.h" #include "drv_priv.h" -#include "helpers.h" #include "util.h" #define TILE_TYPE_LINEAR 0 +#if defined(MTK_MT8183) || defined(MTK_MT8186) +#define SUPPORTS_YUV422_AND_HIGH_BIT_DEPTH_TEXTURING +#endif + +// All platforms except MT8173 should USE_NV12_FOR_HW_VIDEO_DECODING. +#if defined(MTK_MT8183) || defined(MTK_MT8186) || defined(MTK_MT8192) || defined(MTK_MT8195) +#define USE_NV12_FOR_HW_VIDEO_DECODING +#else +#define DONT_USE_64_ALIGNMENT_FOR_VIDEO_BUFFERS +#endif + struct mediatek_private_map_data { void *cached_addr; void *gem_addr; @@ -35,14 +46,36 @@ static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMA DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888, DRM_FORMAT_XRGB8888 }; -#ifdef MTK_MT8183 -static const uint32_t texture_source_formats[] = { DRM_FORMAT_NV21, DRM_FORMAT_NV12, - DRM_FORMAT_YUYV, DRM_FORMAT_YVU420, - DRM_FORMAT_YVU420_ANDROID }; -#else -static const uint32_t texture_source_formats[] = { DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID, - DRM_FORMAT_NV12 }; +// clang-format off +static const uint32_t texture_source_formats[] = { +#ifdef SUPPORTS_YUV422_AND_HIGH_BIT_DEPTH_TEXTURING + DRM_FORMAT_NV21, + DRM_FORMAT_YUYV, + DRM_FORMAT_ABGR2101010, + DRM_FORMAT_ABGR16161616F, #endif + DRM_FORMAT_NV12, + DRM_FORMAT_YVU420, + DRM_FORMAT_YVU420_ANDROID +}; + +static const uint32_t video_yuv_formats[] = { + DRM_FORMAT_NV21, + DRM_FORMAT_NV12, + DRM_FORMAT_YVU420, + DRM_FORMAT_YVU420_ANDROID +}; +// clang-format on + +static bool is_video_yuv_format(uint32_t format) +{ + size_t i; + for (i = 0; i < ARRAY_SIZE(video_yuv_formats); ++i) { + if (format == video_yuv_formats[i]) + return true; + } + return false; +} static int mediatek_init(struct driver *drv) { @@ -65,7 +98,7 @@ static int mediatek_init(struct driver *drv) metadata.modifier = DRM_FORMAT_MOD_LINEAR; drv_modify_combination(drv, DRM_FORMAT_YVU420, &metadata, BO_USE_HW_VIDEO_DECODER); drv_modify_combination(drv, DRM_FORMAT_YVU420_ANDROID, &metadata, BO_USE_HW_VIDEO_DECODER); -#if defined(MTK_MT8183) || defined(MTK_MT8192) || defined(MTK_MT8195) +#ifdef USE_NV12_FOR_HW_VIDEO_DECODING // TODO(hiroh): Switch to use NV12 for video decoder on MT8173 as well. drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata, BO_USE_HW_VIDEO_DECODER); #endif @@ -107,6 +140,12 @@ static int mediatek_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint size_t plane; uint32_t stride; struct drm_mtk_gem_create gem_create = { 0 }; + /* + * We identify the ChromeOS Camera App buffers via these two USE flags. Those buffers need + * the same alignment as the video hardware encoding. + */ + const bool is_camera_preview = + (bo->meta.use_flags & BO_USE_SCANOUT) && (bo->meta.use_flags & BO_USE_CAMERA_WRITE); if (!drv_has_modifier(modifiers, count, DRM_FORMAT_MOD_LINEAR)) { errno = EINVAL; @@ -116,12 +155,19 @@ static int mediatek_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint /* * Since the ARM L1 cache line size is 64 bytes, align to that as a - * performance optimization. + * performance optimization, except for video buffers on certain platforms, + * these should only be accessed from the GPU and VCODEC subsystems (maybe + * also MDP), so it's better to align to macroblocks. */ stride = drv_stride_from_format(format, width, 0); +#ifdef DONT_USE_64_ALIGNMENT_FOR_VIDEO_BUFFERS + const uint32_t alignment = is_video_yuv_format(format) ? 16 : 64; + stride = ALIGN(stride, alignment); +#else stride = ALIGN(stride, 64); +#endif - if (bo->meta.use_flags & BO_USE_HW_VIDEO_ENCODER) { + if ((bo->meta.use_flags & BO_USE_HW_VIDEO_ENCODER) || is_camera_preview) { uint32_t aligned_height = ALIGN(height, 32); uint32_t padding[DRV_MAX_PLANES] = { 0 }; @@ -133,7 +179,7 @@ static int mediatek_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint drv_bo_from_format_and_padding(bo, stride, aligned_height, format, padding); } else { -#ifdef MTK_MT8183 +#ifdef SUPPORTS_YUV422_AND_HIGH_BIT_DEPTH_TEXTURING /* * JPEG Encoder Accelerator requires 16x16 alignment. We want the buffer * from camera can be put in JEA directly so align the height to 16 @@ -172,6 +218,7 @@ static void *mediatek_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint3 int ret, prime_fd; struct drm_mtk_gem_map_off gem_map = { 0 }; struct mediatek_private_map_data *priv; + void *addr = NULL; gem_map.handle = bo->handles[0].u32; @@ -187,22 +234,38 @@ static void *mediatek_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint3 return MAP_FAILED; } - void *addr = mmap(0, bo->meta.total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd, - gem_map.offset); + addr = mmap(0, bo->meta.total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd, + gem_map.offset); + if (addr == MAP_FAILED) + goto out_close_prime_fd; vma->length = bo->meta.total_size; priv = calloc(1, sizeof(*priv)); - priv->prime_fd = prime_fd; - vma->priv = priv; + if (!priv) + goto out_unmap_addr; if (bo->meta.use_flags & BO_USE_RENDERSCRIPT) { priv->cached_addr = calloc(1, bo->meta.total_size); + if (!priv->cached_addr) + goto out_free_priv; + priv->gem_addr = addr; addr = priv->cached_addr; } + priv->prime_fd = prime_fd; + vma->priv = priv; + return addr; + +out_free_priv: + free(priv); +out_unmap_addr: + munmap(addr, bo->meta.total_size); +out_close_prime_fd: + close(prime_fd); + return MAP_FAILED; } static int mediatek_bo_unmap(struct bo *bo, struct vma *vma) @@ -258,37 +321,56 @@ static int mediatek_bo_flush(struct bo *bo, struct mapping *mapping) return 0; } -static uint32_t mediatek_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags) +static void mediatek_resolve_format_and_use_flags(struct driver *drv, uint32_t format, + uint64_t use_flags, uint32_t *out_format, + uint64_t *out_use_flags) { + *out_format = format; + *out_use_flags = use_flags; switch (format) { case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED: #ifdef MTK_MT8183 /* Only MT8183 Camera subsystem offers private reprocessing * capability. CAMERA_READ indicates the buffer is intended for * reprocessing and hence given the private format for MTK. */ - if (use_flags & BO_USE_CAMERA_READ) - return DRM_FORMAT_MTISP_SXYZW10; + if (use_flags & BO_USE_CAMERA_READ) { + *out_format = DRM_FORMAT_MTISP_SXYZW10; + break; + } #endif - if (use_flags & BO_USE_CAMERA_WRITE) - return DRM_FORMAT_NV12; + if (use_flags & BO_USE_CAMERA_WRITE) { + *out_format = DRM_FORMAT_NV12; + break; + } - /*HACK: See b/28671744 */ - return DRM_FORMAT_XBGR8888; + /* HACK: See b/28671744 */ + *out_format = DRM_FORMAT_XBGR8888; + *out_use_flags &= ~BO_USE_HW_VIDEO_ENCODER; + break; case DRM_FORMAT_FLEX_YCbCr_420_888: -#if defined(MTK_MT8183) || defined(MTK_MT8192) || defined(MTK_MT8195) +#ifdef USE_NV12_FOR_HW_VIDEO_DECODING // TODO(hiroh): Switch to use NV12 for video decoder on MT8173 as well. if (use_flags & (BO_USE_HW_VIDEO_DECODER)) { - return DRM_FORMAT_NV12; + *out_format = DRM_FORMAT_NV12; + break; } #endif if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_ENCODER)) { - return DRM_FORMAT_NV12; + *out_format = DRM_FORMAT_NV12; + break; } - return DRM_FORMAT_YVU420; + + /* HACK: See b/139714614 */ + *out_format = DRM_FORMAT_YVU420; + *out_use_flags &= ~BO_USE_SCANOUT; + break; default: - return format; + break; } + /* Mediatek doesn't support YUV overlays */ + if (is_video_yuv_format(format)) + *out_use_flags &= ~BO_USE_SCANOUT; } const struct backend backend_mediatek = { @@ -302,7 +384,7 @@ const struct backend backend_mediatek = { .bo_unmap = mediatek_bo_unmap, .bo_invalidate = mediatek_bo_invalidate, .bo_flush = mediatek_bo_flush, - .resolve_format = mediatek_resolve_format, + .resolve_format_and_use_flags = mediatek_resolve_format_and_use_flags, }; #endif diff --git a/minigbm_helpers.c b/minigbm_helpers.c index 137e5a1..cea0b48 100644 --- a/minigbm_helpers.c +++ b/minigbm_helpers.c @@ -273,6 +273,9 @@ PUBLIC int gbm_get_default_device_fd(void) break; } } + + closedir(dir); + if (dfd >= 0) return dfd; @@ -18,8 +18,8 @@ #include <sys/mman.h> #include <xf86drm.h> +#include "drv_helpers.h" #include "drv_priv.h" -#include "helpers.h" #include "util.h" /* Alignment values are based on SDM845 Gfx IP */ @@ -38,10 +38,12 @@ static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888, DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888, - DRM_FORMAT_XRGB8888 }; + DRM_FORMAT_XRGB8888, DRM_FORMAT_ABGR2101010, + DRM_FORMAT_ABGR16161616F }; static const uint32_t texture_source_formats[] = { DRM_FORMAT_NV12, DRM_FORMAT_R8, - DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID }; + DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID, + DRM_FORMAT_P010 }; /* * Each macrotile consists of m x n (mostly 4 x 4) tiles. @@ -94,10 +96,15 @@ static void msm_calculate_layout(struct bo *bo) /* NV12 format requires extra padding with platform * specific alignments for venus driver */ - if (bo->meta.format == DRM_FORMAT_NV12) { + if (bo->meta.format == DRM_FORMAT_NV12 || bo->meta.format == DRM_FORMAT_P010) { uint32_t y_stride, uv_stride, y_scanline, uv_scanline, y_plane, uv_plane, size, extra_padding; + // P010 has the same layout as NV12. The difference is that each + // pixel in P010 takes 2 bytes, while in NV12 each pixel takes 1 byte. + if (bo->meta.format == DRM_FORMAT_P010) + width *= 2; + y_stride = ALIGN(width, VENUS_STRIDE_ALIGN); uv_stride = ALIGN(width, VENUS_STRIDE_ALIGN); y_scanline = ALIGN(height, VENUS_SCANLINE_ALIGN * 2); @@ -158,7 +165,9 @@ static bool is_ubwc_fmt(uint32_t format) case DRM_FORMAT_ABGR8888: case DRM_FORMAT_XRGB8888: case DRM_FORMAT_ARGB8888: +#ifndef QCOM_DISABLE_COMPRESSED_NV12 case DRM_FORMAT_NV12: +#endif return 1; default: return 0; @@ -199,19 +208,18 @@ static bool should_avoid_ubwc(void) return true; } - /* The video_decode_accelerator_tests needs to read back the frames - * to verify they are correct. The frame verification relies on - * computing the MD5 of the video frame. UBWC results in a different - * MD5. This turns off UBWC for gtest until a proper frame - * comparison can be made - * Rely on the same mechanism that waffle is using, but this time check - * for a dynamic library function that is present in chrome, but missing - * in gtest. Cups is not loaded for video tests. + /* Sommelier relies on implicit modifier, which does not pass host modifier to + * zwp_linux_buffer_params_v1_add. Graphics will be broken if UBWC is enabled. + * Sommelier shall be fixed to mirror what arc wayland_service does, and then + * we can re-enable UBWC here. + * + * Inherit the trick from crrev/c/2523246 previously used for gtest. The side + * effect is all VM guests on msm will revert back to use linear modifier. * - * See b/171260705 + * See b/229147702 */ if (!dlsym(RTLD_DEFAULT, "cupsFilePrintf")) { - drv_log("WARNING: gtest detected, disabling UBWC\n"); + drv_log("WARNING: virtualization detected, disabling UBWC\n"); return true; } #endif @@ -252,9 +260,21 @@ static int msm_init(struct driver *drv) BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER); + /* + * Android also frequently requests YV12 formats for some camera implementations + * (including the external provider implmenetation). + */ + drv_modify_combination(drv, DRM_FORMAT_YVU420_ANDROID, &LINEAR_METADATA, + BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE); + /* Android CTS tests require this. */ drv_add_combination(drv, DRM_FORMAT_BGR888, &LINEAR_METADATA, BO_USE_SW_MASK); +#ifdef SC_7280 + drv_modify_combination(drv, DRM_FORMAT_P010, &LINEAR_METADATA, + BO_USE_SCANOUT | BO_USE_HW_VIDEO_ENCODER); +#endif + drv_modify_linear_combinations(drv); if (should_avoid_ubwc() || !drv->compression) @@ -366,6 +386,6 @@ const struct backend backend_msm = { .bo_import = drv_prime_bo_import, .bo_map = msm_bo_map, .bo_unmap = drv_bo_munmap, - .resolve_format = drv_resolve_format_helper, + .resolve_format_and_use_flags = drv_resolve_format_and_use_flags_helper, }; #endif /* DRV_MSM */ @@ -6,6 +6,7 @@ #ifdef DRV_ROCKCHIP +#include <drm_fourcc.h> #include <errno.h> #include <inttypes.h> #include <rockchip_drm.h> @@ -14,10 +15,14 @@ #include <sys/mman.h> #include <xf86drm.h> +#include "drv_helpers.h" #include "drv_priv.h" -#include "helpers.h" #include "util.h" +#define DRM_FORMAT_MOD_ROCKCHIP_AFBC \ + DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_16x16 | AFBC_FORMAT_MOD_SPARSE | \ + AFBC_FORMAT_MOD_YTR) + struct rockchip_private_map_data { void *cached_addr; void *gem_addr; @@ -30,7 +35,8 @@ static const uint32_t scanout_render_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORM static const uint32_t texture_only_formats[] = { DRM_FORMAT_NV12, DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID }; -static int afbc_bo_from_format(struct bo *bo, uint32_t width, uint32_t height, uint32_t format) +static int afbc_bo_from_format(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, + uint64_t modifier) { /* We've restricted ourselves to four bytes per pixel. */ const uint32_t pixel_size = 4; @@ -69,7 +75,7 @@ static int afbc_bo_from_format(struct bo *bo, uint32_t width, uint32_t height, u bo->meta.total_size = total_size; - bo->meta.format_modifier = DRM_FORMAT_MOD_CHROMEOS_ROCKCHIP_AFBC; + bo->meta.format_modifier = modifier; return 0; } @@ -113,6 +119,14 @@ static int rockchip_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint int ret; size_t plane; struct drm_rockchip_gem_create gem_create = { 0 }; + uint64_t afbc_modifier; + + if (drv_has_modifier(modifiers, count, DRM_FORMAT_MOD_ROCKCHIP_AFBC)) + afbc_modifier = DRM_FORMAT_MOD_ROCKCHIP_AFBC; + else if (drv_has_modifier(modifiers, count, DRM_FORMAT_MOD_CHROMEOS_ROCKCHIP_AFBC)) + afbc_modifier = DRM_FORMAT_MOD_CHROMEOS_ROCKCHIP_AFBC; + else + afbc_modifier = 0; if (format == DRM_FORMAT_NV12) { uint32_t w_mbs = DIV_ROUND_UP(width, 16); @@ -127,12 +141,10 @@ static int rockchip_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint * driver to store motion vectors. */ bo->meta.total_size += w_mbs * h_mbs * 128; - } else if (width <= 2560 && - drv_has_modifier(modifiers, count, DRM_FORMAT_MOD_CHROMEOS_ROCKCHIP_AFBC) && - bo->drv->compression) { + } else if (width <= 2560 && afbc_modifier && bo->drv->compression) { /* If the caller has decided they can use AFBC, always * pick that */ - afbc_bo_from_format(bo, width, height, format); + afbc_bo_from_format(bo, width, height, format, afbc_modifier); } else { if (!drv_has_modifier(modifiers, count, DRM_FORMAT_MOD_LINEAR)) { errno = EINVAL; @@ -184,10 +196,12 @@ static void *rockchip_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint3 int ret; struct rockchip_private_map_data *priv; struct drm_rockchip_gem_map_off gem_map = { 0 }; + void *addr = NULL; /* We can only map buffers created with SW access flags, which should * have no modifiers (ie, not AFBC). */ - if (bo->meta.format_modifier == DRM_FORMAT_MOD_CHROMEOS_ROCKCHIP_AFBC) + if (bo->meta.format_modifier == DRM_FORMAT_MOD_CHROMEOS_ROCKCHIP_AFBC || + bo->meta.format_modifier == DRM_FORMAT_MOD_ROCKCHIP_AFBC) return MAP_FAILED; gem_map.handle = bo->handles[0].u32; @@ -197,20 +211,34 @@ static void *rockchip_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint3 return MAP_FAILED; } - void *addr = mmap(0, bo->meta.total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd, - gem_map.offset); + addr = mmap(0, bo->meta.total_size, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd, + gem_map.offset); + if (addr == MAP_FAILED) + return MAP_FAILED; vma->length = bo->meta.total_size; if (bo->meta.use_flags & BO_USE_RENDERSCRIPT) { priv = calloc(1, sizeof(*priv)); + if (!priv) + goto out_unmap_addr; + priv->cached_addr = calloc(1, bo->meta.total_size); + if (!priv->cached_addr) + goto out_free_priv; + priv->gem_addr = addr; vma->priv = priv; addr = priv->cached_addr; } return addr; + +out_free_priv: + free(priv); +out_unmap_addr: + munmap(addr, bo->meta.total_size); + return MAP_FAILED; } static int rockchip_bo_unmap(struct bo *bo, struct vma *vma) @@ -256,7 +284,7 @@ const struct backend backend_rockchip = { .bo_unmap = rockchip_bo_unmap, .bo_invalidate = rockchip_bo_invalidate, .bo_flush = rockchip_bo_flush, - .resolve_format = drv_resolve_format_helper, + .resolve_format_and_use_flags = drv_resolve_format_and_use_flags_helper, }; #endif @@ -13,8 +13,8 @@ #include <vc4_drm.h> #include <xf86drm.h> +#include "drv_helpers.h" #include "drv_priv.h" -#include "helpers.h" #include "util.h" static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_RGB565, @@ -131,6 +131,7 @@ const struct backend backend_vc4 = { .bo_destroy = drv_gem_bo_destroy, .bo_map = vc4_bo_map, .bo_unmap = drv_bo_munmap, + .resolve_format_and_use_flags = drv_resolve_format_and_use_flags_helper, }; #endif @@ -13,7 +13,6 @@ #include "drv_priv.h" #include "external/virtgpu_drm.h" -#include "helpers.h" #include "util.h" #include "virtgpu.h" @@ -49,7 +48,7 @@ static int virtgpu_init(struct driver *drv) get_param.value = (uint64_t)(uintptr_t)¶ms[i].value; int ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GETPARAM, &get_param); if (ret) - drv_log("DRM_IOCTL_VIRTGPU_GET_PARAM failed with %s\n", strerror(errno)); + drv_log("virtgpu backend not enabling %s\n", params[i].name); } for (uint32_t i = 0; i < ARRAY_SIZE(virtgpu_backends); i++) { diff --git a/virtgpu_cross_domain.c b/virtgpu_cross_domain.c index b02a949..10930fc 100644 --- a/virtgpu_cross_domain.c +++ b/virtgpu_cross_domain.c @@ -9,10 +9,10 @@ #include <sys/mman.h> #include <xf86drm.h> +#include "drv_helpers.h" #include "drv_priv.h" #include "external/virtgpu_cross_domain_protocol.h" #include "external/virtgpu_drm.h" -#include "helpers.h" #include "util.h" #include "virtgpu.h" @@ -36,6 +36,7 @@ struct cross_domain_private { uint32_t ring_handle; void *ring_addr; struct drv_array *metadata_cache; + pthread_mutex_t metadata_cache_lock; }; static void cross_domain_release_private(struct driver *drv) @@ -57,7 +58,11 @@ static void cross_domain_release_private(struct driver *drv) } } - drv_array_destroy(priv->metadata_cache); + if (priv->metadata_cache) + drv_array_destroy(priv->metadata_cache); + + pthread_mutex_destroy(&priv->metadata_cache_lock); + free(priv); } @@ -107,7 +112,7 @@ static int cross_domain_submit_cmd(struct driver *drv, uint32_t *cmd, uint32_t c exec.command = (uint64_t)&cmd[0]; exec.size = cmd_size; if (wait) { - exec.flags = VIRTGPU_EXECBUF_FENCE_CONTEXT; + exec.flags = VIRTGPU_EXECBUF_RING_IDX; exec.bo_handles = (uint64_t)&priv->ring_handle; exec.num_bo_handles = 1; } @@ -150,7 +155,7 @@ static int cross_domain_metadata_query(struct driver *drv, struct bo_metadata *m uint32_t plane, remaining_size; memset(&cmd_get_reqs, 0, sizeof(cmd_get_reqs)); - pthread_mutex_lock(&drv->driver_lock); + pthread_mutex_lock(&priv->metadata_cache_lock); for (uint32_t i = 0; i < drv_array_size(priv->metadata_cache); i++) { cached_data = (struct bo_metadata *)drv_array_at_idx(priv->metadata_cache, i); if (!metadata_equal(metadata, cached_data)) @@ -185,11 +190,11 @@ static int cross_domain_metadata_query(struct driver *drv, struct bo_metadata *m memcpy(&metadata->offsets, &addr[4], 4 * sizeof(uint32_t)); memcpy(&metadata->format_modifier, &addr[8], sizeof(uint64_t)); memcpy(&metadata->total_size, &addr[10], sizeof(uint64_t)); - memcpy(&metadata->blob_id, &addr[12], sizeof(uint64_t)); + memcpy(&metadata->blob_id, &addr[12], sizeof(uint32_t)); - metadata->map_info = addr[14]; - metadata->memory_idx = addr[16]; - metadata->physical_device_idx = addr[17]; + metadata->map_info = addr[13]; + metadata->memory_idx = addr[14]; + metadata->physical_device_idx = addr[15]; remaining_size = metadata->total_size; for (plane = 0; plane < metadata->num_planes; plane++) { @@ -203,7 +208,7 @@ static int cross_domain_metadata_query(struct driver *drv, struct bo_metadata *m drv_array_append(priv->metadata_cache, metadata); out_unlock: - pthread_mutex_unlock(&drv->driver_lock); + pthread_mutex_unlock(&priv->metadata_cache_lock); return ret; } @@ -234,16 +239,22 @@ static int cross_domain_init(struct driver *drv) if (!params[param_host_visible].value && !params[param_create_guest_handle].value) return -ENOTSUP; - /* - * crosvm never reports the fake capset. This is just an extra check to make sure we - * don't use the cross-domain context by accident. Developers may remove this for - * testing purposes. - */ - if ((params[param_supported_capset_ids].value & (1 << CAPSET_CROSS_FAKE)) == 0) - return -ENOTSUP; - priv = calloc(1, sizeof(*priv)); + if (!priv) + return -ENOMEM; + + ret = pthread_mutex_init(&priv->metadata_cache_lock, NULL); + if (ret) { + free(priv); + return ret; + } + priv->metadata_cache = drv_array_init(sizeof(struct bo_metadata)); + if (!priv->metadata_cache) { + ret = -ENOMEM; + goto free_private; + } + priv->ring_addr = MAP_FAILED; drv->priv = priv; @@ -269,7 +280,7 @@ static int cross_domain_init(struct driver *drv) // queries. ctx_set_params[0].param = VIRTGPU_CONTEXT_PARAM_CAPSET_ID; ctx_set_params[0].value = CAPSET_CROSS_DOMAIN; - ctx_set_params[1].param = VIRTGPU_CONTEXT_PARAM_NUM_FENCE_CONTEXTS; + ctx_set_params[1].param = VIRTGPU_CONTEXT_PARAM_NUM_RINGS; ctx_set_params[1].value = 1; init.ctx_set_params = (unsigned long long)&ctx_set_params[0]; @@ -347,7 +358,7 @@ static int cross_domain_bo_create(struct bo *bo, uint32_t width, uint32_t height if (use_flags & BO_USE_SW_MASK) blob_flags |= VIRTGPU_BLOB_FLAG_USE_MAPPABLE; - if (params[param_cross_device].value && (use_flags & BO_USE_NON_GPU_HW)) + if (params[param_cross_device].value) blob_flags |= VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE; /// It may be possible to have host3d blobs and handles from guest memory at the same time. @@ -363,7 +374,7 @@ static int cross_domain_bo_create(struct bo *bo, uint32_t width, uint32_t height drm_rc_blob.size = bo->meta.total_size; drm_rc_blob.blob_flags = blob_flags; - drm_rc_blob.blob_id = bo->meta.blob_id; + drm_rc_blob.blob_id = (uint64_t)bo->meta.blob_id; ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB, &drm_rc_blob); if (ret < 0) { @@ -403,5 +414,5 @@ const struct backend virtgpu_cross_domain = { .bo_destroy = drv_gem_bo_destroy, .bo_map = cross_domain_bo_map, .bo_unmap = drv_bo_munmap, - .resolve_format = drv_resolve_format_helper, + .resolve_format_and_use_flags = drv_resolve_format_and_use_flags_helper, }; diff --git a/virtgpu_virgl.c b/virtgpu_virgl.c index 32ca6a1..7194e42 100644 --- a/virtgpu_virgl.c +++ b/virtgpu_virgl.c @@ -12,31 +12,46 @@ #include <sys/mman.h> #include <xf86drm.h> +#include "drv_helpers.h" #include "drv_priv.h" #include "external/virgl_hw.h" #include "external/virgl_protocol.h" #include "external/virtgpu_drm.h" -#include "helpers.h" #include "util.h" #include "virtgpu.h" #define PIPE_TEXTURE_2D 2 +#define MESA_LLVMPIPE_MAX_TEXTURE_2D_LEVELS 15 +#define MESA_LLVMPIPE_MAX_TEXTURE_2D_SIZE (1 << (MESA_LLVMPIPE_MAX_TEXTURE_2D_LEVELS - 1)) #define MESA_LLVMPIPE_TILE_ORDER 6 #define MESA_LLVMPIPE_TILE_SIZE (1 << MESA_LLVMPIPE_TILE_ORDER) +// This comes from a combination of SwiftShader's VkPhysicalDeviceLimits::maxFramebufferWidth and +// VkPhysicalDeviceLimits::maxImageDimension2D (see https://crrev.com/c/1917130). +#define ANGLE_ON_SWIFTSHADER_MAX_TEXTURE_2D_SIZE 8192 + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif +#define VIRGL_2D_MAX_TEXTURE_2D_SIZE \ + MIN(ANGLE_ON_SWIFTSHADER_MAX_TEXTURE_2D_SIZE, MESA_LLVMPIPE_MAX_TEXTURE_2D_SIZE) + static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888, DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888, DRM_FORMAT_XRGB8888 }; static const uint32_t dumb_texture_source_formats[] = { - DRM_FORMAT_R8, DRM_FORMAT_R16, DRM_FORMAT_YVU420, - DRM_FORMAT_NV12, DRM_FORMAT_NV21, DRM_FORMAT_YVU420_ANDROID + DRM_FORMAT_R8, DRM_FORMAT_R16, DRM_FORMAT_YVU420, + DRM_FORMAT_NV12, DRM_FORMAT_NV21, DRM_FORMAT_YVU420_ANDROID, + DRM_FORMAT_ABGR2101010, DRM_FORMAT_ABGR16161616F }; -static const uint32_t texture_source_formats[] = { DRM_FORMAT_NV12, DRM_FORMAT_NV21, - DRM_FORMAT_R8, DRM_FORMAT_R16, - DRM_FORMAT_RG88, DRM_FORMAT_YVU420_ANDROID }; +static const uint32_t texture_source_formats[] = { + DRM_FORMAT_NV12, DRM_FORMAT_NV21, DRM_FORMAT_R8, + DRM_FORMAT_R16, DRM_FORMAT_RG88, DRM_FORMAT_YVU420_ANDROID, + DRM_FORMAT_ABGR2101010, DRM_FORMAT_ABGR16161616F +}; extern struct virtgpu_param params[]; @@ -63,6 +78,8 @@ static uint32_t translate_format(uint32_t drm_fourcc) return VIRGL_FORMAT_R8G8B8A8_UNORM; case DRM_FORMAT_ABGR16161616F: return VIRGL_FORMAT_R16G16B16A16_FLOAT; + case DRM_FORMAT_ABGR2101010: + return VIRGL_FORMAT_R10G10B10A2_UNORM; case DRM_FORMAT_RGB565: return VIRGL_FORMAT_B5G6R5_UNORM; case DRM_FORMAT_R8: @@ -75,6 +92,8 @@ static uint32_t translate_format(uint32_t drm_fourcc) return VIRGL_FORMAT_NV12; case DRM_FORMAT_NV21: return VIRGL_FORMAT_NV21; + case DRM_FORMAT_P010: + return VIRGL_FORMAT_P010; case DRM_FORMAT_YVU420: case DRM_FORMAT_YVU420_ANDROID: return VIRGL_FORMAT_YV12; @@ -330,12 +349,10 @@ static bool virgl_supports_combination_through_emulation(struct driver *drv, uin static void virgl_add_combination(struct driver *drv, uint32_t drm_format, struct format_metadata *metadata, uint64_t use_flags) { - struct virgl_priv *priv = (struct virgl_priv *)drv->priv; - - if (params[param_3d].value && priv->caps.max_version >= 1) { - if ((use_flags & BO_USE_SCANOUT) && priv->caps_is_v2 && - !virgl_supports_combination_natively(drv, drm_format, use_flags)) { - drv_log("Scanout format: %d\n", drm_format); + if (params[param_3d].value) { + if ((use_flags & BO_USE_SCANOUT) && + !virgl_supports_combination_natively(drv, drm_format, BO_USE_SCANOUT)) { + drv_log("Strip scanout on format: %d\n", drm_format); use_flags &= ~BO_USE_SCANOUT; } @@ -361,8 +378,8 @@ static void virgl_add_combinations(struct driver *drv, const uint32_t *drm_forma virgl_add_combination(drv, drm_formats[i], metadata, use_flags); } -static int virtio_dumb_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, - uint64_t use_flags) +static int virgl_2d_dumb_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, + uint64_t use_flags) { if (bo->meta.format != DRM_FORMAT_R8) { width = ALIGN(width, MESA_LLVMPIPE_TILE_SIZE); @@ -391,6 +408,9 @@ static uint32_t compute_virgl_bind_flags(uint64_t use_flags, uint32_t format) handle_flag(&use_flags, BO_USE_SCANOUT, &bind, VIRGL_BIND_SCANOUT); handle_flag(&use_flags, BO_USE_CURSOR, &bind, VIRGL_BIND_CURSOR); handle_flag(&use_flags, BO_USE_LINEAR, &bind, VIRGL_BIND_LINEAR); + handle_flag(&use_flags, BO_USE_SENSOR_DIRECT_DATA, &bind, VIRGL_BIND_LINEAR); + handle_flag(&use_flags, BO_USE_GPU_DATA_BUFFER, &bind, VIRGL_BIND_LINEAR); + handle_flag(&use_flags, BO_USE_FRONT_RENDERING, &bind, VIRGL_BIND_LINEAR); if (use_flags & BO_USE_PROTECTED) { handle_flag(&use_flags, BO_USE_PROTECTED, &bind, VIRGL_BIND_MINIGBM_PROTECTED); @@ -420,14 +440,6 @@ static uint32_t compute_virgl_bind_flags(uint64_t use_flags, uint32_t format) handle_flag(&use_flags, BO_USE_HW_VIDEO_ENCODER, &bind, VIRGL_BIND_MINIGBM_HW_VIDEO_ENCODER); - /* - * HACK: This is for HAL_PIXEL_FORMAT_YV12 buffers allocated by arcvm. None of - * our platforms can display YV12, so we can treat as a SW buffer. Remove once - * this can be intelligently resolved in the guest. Also see gbm_bo_create. - */ - if (format == DRM_FORMAT_YVU420_ANDROID) - bind |= VIRGL_BIND_LINEAR; - if (use_flags) drv_log("Unhandled bo use flag: %llx\n", (unsigned long long)use_flags); @@ -512,6 +524,16 @@ static void *virgl_3d_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint3 gem_map.offset); } +static uint32_t virgl_3d_get_max_texture_2d_size(struct driver *drv) +{ + struct virgl_priv *priv = (struct virgl_priv *)drv->priv; + + if (priv->caps.v2.max_texture_2d_size) + return priv->caps.v2.max_texture_2d_size; + + return UINT32_MAX; +} + static int virgl_get_caps(struct driver *drv, union virgl_caps *caps, int *caps_is_v2) { int ret; @@ -569,6 +591,9 @@ static int virgl_init(struct driver *drv) struct virgl_priv *priv; priv = calloc(1, sizeof(*priv)); + if (!priv) + return -ENOMEM; + drv->priv = priv; virgl_init_params_and_caps(drv); @@ -582,6 +607,12 @@ static int virgl_init(struct driver *drv) virgl_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats), &LINEAR_METADATA, BO_USE_TEXTURE_MASK); + /* NV12 with scanout must flow through virgl_add_combination, so that the native + * support is checked and scanout use_flag can be conditionally stripped. */ + virgl_add_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA, + BO_USE_TEXTURE_MASK | BO_USE_CAMERA_READ | + BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER | + BO_USE_HW_VIDEO_ENCODER | BO_USE_SCANOUT); } else { /* Virtio primary plane only allows this format. */ virgl_add_combination(drv, DRM_FORMAT_XRGB8888, &LINEAR_METADATA, @@ -598,28 +629,25 @@ static int virgl_init(struct driver *drv) virgl_add_combinations(drv, dumb_texture_source_formats, ARRAY_SIZE(dumb_texture_source_formats), &LINEAR_METADATA, BO_USE_TEXTURE_MASK); - virgl_add_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA, - BO_USE_SW_MASK | BO_USE_LINEAR); - virgl_add_combination(drv, DRM_FORMAT_NV21, &LINEAR_METADATA, - BO_USE_SW_MASK | BO_USE_LINEAR); + drv_modify_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA, + BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | + BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER); } /* Android CTS tests require this. */ virgl_add_combination(drv, DRM_FORMAT_RGB888, &LINEAR_METADATA, BO_USE_SW_MASK); virgl_add_combination(drv, DRM_FORMAT_BGR888, &LINEAR_METADATA, BO_USE_SW_MASK); - virgl_add_combination(drv, DRM_FORMAT_ABGR16161616F, &LINEAR_METADATA, - BO_USE_SW_MASK | BO_USE_TEXTURE_MASK); - virgl_add_combination(drv, DRM_FORMAT_ABGR2101010, &LINEAR_METADATA, - BO_USE_SW_MASK | BO_USE_TEXTURE_MASK); + /* Android Camera CTS tests requires this. Additionally, the scanout usage is needed for + * Camera preview and is expected to be conditionally stripped by virgl_add_combination + * when not natively supported and instead handled by HWComposer. */ virgl_add_combination(drv, DRM_FORMAT_P010, &LINEAR_METADATA, - BO_USE_SW_MASK | BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE); - - drv_modify_combination(drv, DRM_FORMAT_NV12, &LINEAR_METADATA, - BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER | - BO_USE_HW_VIDEO_ENCODER); + BO_USE_SCANOUT | BO_USE_TEXTURE | BO_USE_SW_MASK | + BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE); + /* Android VTS sensors hal tests require BO_USE_SENSOR_DIRECT_DATA. */ drv_modify_combination(drv, DRM_FORMAT_R8, &LINEAR_METADATA, BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER | - BO_USE_HW_VIDEO_ENCODER); + BO_USE_HW_VIDEO_ENCODER | BO_USE_SENSOR_DIRECT_DATA | + BO_USE_GPU_DATA_BUFFER); if (!priv->host_gbm_enabled) { drv_modify_combination(drv, DRM_FORMAT_ABGR8888, &LINEAR_METADATA, @@ -663,8 +691,10 @@ static int virgl_bo_create_blob(struct driver *drv, struct bo *bo) uint32_t blob_flags = VIRTGPU_BLOB_FLAG_USE_SHAREABLE; if (bo->meta.use_flags & BO_USE_SW_MASK) blob_flags |= VIRTGPU_BLOB_FLAG_USE_MAPPABLE; - if (bo->meta.use_flags & BO_USE_NON_GPU_HW) - blob_flags |= VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE; + + // For now, all blob use cases are cross device. When we add wider + // support for blobs, we can revisit making this unconditional. + blob_flags |= VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE; cur_blob_id = atomic_fetch_add(&priv->next_blob_id, 1); stride = drv_stride_from_format(bo->meta.format, bo->meta.width, 0); @@ -714,16 +744,17 @@ static bool should_use_blob(struct driver *drv, uint32_t format, uint64_t use_fl if (!priv->host_gbm_enabled) return false; - // Use regular resources if only the GPU needs efficient access - if (!(use_flags & - (BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN | BO_USE_LINEAR | BO_USE_NON_GPU_HW))) + // Use regular resources if only the GPU needs efficient access. Blob resource is a better + // fit for BO_USE_GPU_DATA_BUFFER which is mapped to VIRGL_BIND_LINEAR. + if (!(use_flags & (BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN | BO_USE_LINEAR | + BO_USE_NON_GPU_HW | BO_USE_GPU_DATA_BUFFER))) return false; switch (format) { - case DRM_FORMAT_YVU420_ANDROID: case DRM_FORMAT_R8: // Formats with strictly defined strides are supported return true; + case DRM_FORMAT_YVU420_ANDROID: case DRM_FORMAT_NV12: // Knowing buffer metadata at buffer creation isn't yet supported, so buffers // can't be properly mapped into the guest. @@ -743,7 +774,7 @@ static int virgl_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint3 if (params[param_3d].value) return virgl_3d_bo_create(bo, width, height, format, use_flags); else - return virtio_dumb_bo_create(bo, width, height, format, use_flags); + return virgl_2d_dumb_bo_create(bo, width, height, format, use_flags); } static int virgl_bo_destroy(struct bo *bo) @@ -778,7 +809,7 @@ static int virgl_bo_invalidate(struct bo *bo, struct mapping *mapping) // Invalidate is only necessary if the host writes to the buffer. The encoder and // decoder flags don't differentiate between input and output buffers, but we can // use the format to determine whether this buffer could be encoder/decoder output. - host_write_flags = BO_USE_RENDERING | BO_USE_CAMERA_WRITE; + host_write_flags = BO_USE_RENDERING | BO_USE_CAMERA_WRITE | BO_USE_GPU_DATA_BUFFER; if (bo->meta.format == DRM_FORMAT_R8) host_write_flags |= BO_USE_HW_VIDEO_ENCODER; else @@ -934,28 +965,97 @@ static int virgl_bo_flush(struct bo *bo, struct mapping *mapping) return 0; } -static uint32_t virgl_resolve_format(struct driver *drv, uint32_t format, uint64_t use_flags) +static void virgl_3d_resolve_format_and_use_flags(struct driver *drv, uint32_t format, + uint64_t use_flags, uint32_t *out_format, + uint64_t *out_use_flags) { + *out_format = format; + *out_use_flags = use_flags; switch (format) { case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED: /* Camera subsystem requires NV12. */ - if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE)) - return DRM_FORMAT_NV12; - /*HACK: See b/28671744 */ - return DRM_FORMAT_XBGR8888; + if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE)) { + *out_format = DRM_FORMAT_NV12; + } else { + /* HACK: See b/28671744 */ + *out_format = DRM_FORMAT_XBGR8888; + *out_use_flags &= ~BO_USE_HW_VIDEO_ENCODER; + } + break; case DRM_FORMAT_FLEX_YCbCr_420_888: - /* - * All of our host drivers prefer NV12 as their flexible media format. - * If that changes, this will need to be modified. - */ - if (params[param_3d].value) - return DRM_FORMAT_NV12; - else - return DRM_FORMAT_YVU420_ANDROID; + /* All of our host drivers prefer NV12 as their flexible media format. + * If that changes, this will need to be modified. */ + *out_format = DRM_FORMAT_NV12; + /* fallthrough */ + case DRM_FORMAT_NV12: + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_RGB565: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_XRGB8888: + /* These are the scanout capable formats to the guest. Strip scanout use_flag if the + * host does not natively support scanout on the requested format. */ + if ((use_flags & BO_USE_SCANOUT) && + !virgl_supports_combination_natively(drv, format, BO_USE_SCANOUT)) + *out_use_flags &= ~BO_USE_SCANOUT; + break; + case DRM_FORMAT_YVU420_ANDROID: + *out_use_flags &= ~BO_USE_SCANOUT; + /* HACK: See b/172389166. Also see gbm_bo_create. */ + *out_use_flags |= BO_USE_LINEAR; + break; + default: + break; + } +} + +static void virgl_2d_resolve_format_and_use_flags(uint32_t format, uint64_t use_flags, + uint32_t *out_format, uint64_t *out_use_flags) +{ + *out_format = format; + *out_use_flags = use_flags; + + /* HACK: See crrev/c/1849773 */ + if (format != DRM_FORMAT_XRGB8888) + *out_use_flags &= ~BO_USE_SCANOUT; + + switch (format) { + case DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED: + /* Camera subsystem requires NV12. */ + if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE)) { + *out_format = DRM_FORMAT_NV12; + } else { + /* HACK: See b/28671744 */ + *out_format = DRM_FORMAT_XBGR8888; + *out_use_flags &= ~BO_USE_HW_VIDEO_ENCODER; + } + break; + case DRM_FORMAT_FLEX_YCbCr_420_888: + *out_format = DRM_FORMAT_YVU420_ANDROID; + /* fallthrough */ + case DRM_FORMAT_YVU420_ANDROID: + *out_use_flags &= ~BO_USE_SCANOUT; + /* HACK: See b/172389166. Also see gbm_bo_create. */ + *out_use_flags |= BO_USE_LINEAR; + break; default: - return format; + break; + } +} + +static void virgl_resolve_format_and_use_flags(struct driver *drv, uint32_t format, + uint64_t use_flags, uint32_t *out_format, + uint64_t *out_use_flags) +{ + if (params[param_3d].value) { + return virgl_3d_resolve_format_and_use_flags(drv, format, use_flags, out_format, + out_use_flags); + } else { + return virgl_2d_resolve_format_and_use_flags(format, use_flags, out_format, + out_use_flags); } } + static int virgl_resource_info(struct bo *bo, uint32_t strides[DRV_MAX_PLANES], uint32_t offsets[DRV_MAX_PLANES], uint64_t *format_modifier) { @@ -973,21 +1073,30 @@ static int virgl_resource_info(struct bo *bo, uint32_t strides[DRV_MAX_PLANES], return ret; } - for (uint32_t plane = 0; plane < bo->meta.num_planes; plane++) { + for (uint32_t plane = 0; plane < DRV_MAX_PLANES; plane++) { /* * Currently, kernel v4.14 (Betty) doesn't have the extended resource info * ioctl. */ - if (res_info.strides[plane]) { - strides[plane] = res_info.strides[plane]; - offsets[plane] = res_info.offsets[plane]; - } + if (!res_info.strides[plane]) + break; + + strides[plane] = res_info.strides[plane]; + offsets[plane] = res_info.offsets[plane]; } *format_modifier = res_info.format_modifier; return 0; } +static uint32_t virgl_get_max_texture_2d_size(struct driver *drv) +{ + if (params[param_3d].value) + return virgl_3d_get_max_texture_2d_size(drv); + else + return VIRGL_2D_MAX_TEXTURE_2D_SIZE; +} + const struct backend virtgpu_virgl = { .name = "virtgpu_virgl", .init = virgl_init, .close = virgl_close, @@ -998,5 +1107,7 @@ const struct backend virtgpu_virgl = { .name = "virtgpu_virgl", .bo_unmap = drv_bo_munmap, .bo_invalidate = virgl_bo_invalidate, .bo_flush = virgl_bo_flush, - .resolve_format = virgl_resolve_format, - .resource_info = virgl_resource_info }; + .resolve_format_and_use_flags = + virgl_resolve_format_and_use_flags, + .resource_info = virgl_resource_info, + .get_max_texture_2d_size = virgl_get_max_texture_2d_size }; |