diff options
author | Marcin Radomski <dextero@google.com> | 2024-03-12 14:52:04 +0000 |
---|---|---|
committer | Marcin Radomski <dextero@google.com> | 2024-03-12 14:52:29 +0000 |
commit | b1dc3731382333c64f1e3af301f8041911f107ca (patch) | |
tree | c28403a41a30f971bcb538c6b28ef19f14fc4184 | |
parent | 4eceb378d6a3552d85df4285c469b1cd5ab70cad (diff) | |
parent | 40b28f098a29589b3f72de1ba6753d46a616c48b (diff) | |
download | minigbm-b1dc3731382333c64f1e3af301f8041911f107ca.tar.gz |
Merge remote-tracking branch 'cros/main'
To pull in https://crrev.com/c/5352370 and https://crrev.com/c/5352371.
Additionally, add backend_mock.c to Android.bp. It was added in
https://crrev.com/c/4923791, and drv.c uses symbols defined there
unconditionally.
The one merge conflict was an i915->is_media_compression_enabled assert
in i915_num_planes_from_modifier [1] that was removed upstream in
https://crrev.com/c/5118242. The assertion referenced a flag that was
set through an ENABLE_INTEL_MEDIA_COMPRESSION environment variable.
There are no references to that variable in AOSP sources.
[1] https://cs.android.com/android/platform/superproject/main/+/main:external/minigbm/i915.c;l=591;drc=350c09cf0fa662928e208eb6749a1f3ca34dac9f
Bug: b/328181805
Test: lunch aosp_cf_x86_64_only_phone-trunk_staging-userdebug
Test: m && cvd start && atest SurfaceFlinger_test
Change-Id: I8faba268580ad984af92a63c47366d6a69e8c9d0
-rw-r--r-- | Android.bp | 1 | ||||
-rw-r--r-- | Makefile | 11 | ||||
-rw-r--r-- | backend_mock.c | 16 | ||||
-rw-r--r-- | cros_gralloc/aidl/Allocator.h | 4 | ||||
-rw-r--r-- | drv.c | 46 | ||||
-rw-r--r-- | drv.h | 21 | ||||
-rw-r--r-- | drv_priv.h | 2 | ||||
-rw-r--r-- | gbm.c | 37 | ||||
-rw-r--r-- | gbm.h | 43 | ||||
-rw-r--r-- | gbm_unittest.cc | 82 | ||||
-rw-r--r-- | i915.c | 144 | ||||
-rw-r--r-- | mediatek.c | 83 | ||||
-rw-r--r-- | testrunner.cc | 15 | ||||
-rw-r--r-- | virtgpu.h | 6 | ||||
-rw-r--r-- | virtgpu_cross_domain.c | 7 | ||||
-rw-r--r-- | virtgpu_virgl.c | 27 |
16 files changed, 457 insertions, 88 deletions
@@ -37,6 +37,7 @@ filegroup { srcs: [ "amdgpu.c", + "backend_mock.c", "drv.c", "drv_array_helpers.c", "drv_helpers.c", @@ -12,6 +12,10 @@ CPPFLAGS += -D_GNU_SOURCE=1 CFLAGS += -std=c99 -Wall -Wsign-compare -Wpointer-arith -Wcast-qual \ -Wcast-align -D_GNU_SOURCE=1 -D_FILE_OFFSET_BITS=64 +# Dependencies that all gtest based unittests should have. +UNITTEST_LIBS := -lcap -lgtest -lgmock +UNITTEST_DEPS := gbm_unittest.o testrunner.o gbm.o dri.o drv_array_helpers.o drv_helpers.o drv.o backend_mock.o virtgpu_cross_domain.o virtgpu_virgl.o virtgpu.o msm.o vc4.o amdgpu.o i915.o mediatek.o dumb_driver.o + ifdef DRV_AMDGPU CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_amdgpu) LDLIBS += -ldrm_amdgpu -ldl @@ -52,6 +56,13 @@ all: CC_LIBRARY($(MINIGBM_FILENAME)) clean: CLEAN($(MINIGBM_FILENAME)) +CXX_BINARY(gbm_unittest): CXXFLAGS += -Wno-write-strings \ + $(GTEST_CXXFLAGS) +CXX_BINARY(gbm_unittest): LDLIBS += $(UNITTEST_LIBS) +CXX_BINARY(gbm_unittest): $(UNITTEST_DEPS) +clean: CLEAN(gbm_unittest) +tests: TEST(CXX_BINARY(gbm_unittest)) + install: all mkdir -p $(DESTDIR)/$(LIBDIR) install -D -m 755 $(OUT)/$(MINIGBM_FILENAME) $(DESTDIR)/$(LIBDIR) diff --git a/backend_mock.c b/backend_mock.c new file mode 100644 index 0000000..ae0d758 --- /dev/null +++ b/backend_mock.c @@ -0,0 +1,16 @@ +/* + * Copyright 2023 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 "drv_priv.h" + +static int backend_mock_init(struct driver *drv) { + return 0; +} + +const struct backend backend_mock = { + .name = "Mock Backend", + .init = backend_mock_init, +}; diff --git a/cros_gralloc/aidl/Allocator.h b/cros_gralloc/aidl/Allocator.h index 85a13cd..be06dbb 100644 --- a/cros_gralloc/aidl/Allocator.h +++ b/cros_gralloc/aidl/Allocator.h @@ -27,10 +27,10 @@ class Allocator : public BnAllocator { allocator::AllocationResult* outResult) override; ndk::ScopedAStatus allocate2(const BufferDescriptorInfo& descriptor, int32_t count, - allocator::AllocationResult* outResult) override; + allocator::AllocationResult* outResult) override; ndk::ScopedAStatus isSupported(const BufferDescriptorInfo& descriptor, - bool* outResult) override; + bool* outResult) override; ndk::ScopedAStatus getIMapperLibrarySuffix(std::string* outResult) override; @@ -6,6 +6,7 @@ #include <assert.h> #include <errno.h> #include <fcntl.h> +#include <inttypes.h> #include <pthread.h> #include <stdint.h> #include <stdio.h> @@ -55,6 +56,8 @@ extern const struct backend backend_virtgpu; extern const struct backend backend_udl; extern const struct backend backend_vkms; +extern const struct backend backend_mock; + static const struct backend *drv_backend_list[] = { #ifdef DRV_AMDGPU &backend_amdgpu, @@ -71,7 +74,7 @@ static const struct backend *drv_backend_list[] = { &backend_evdi, &backend_komeda, &backend_marvell, &backend_mediatek, &backend_meson, &backend_nouveau, &backend_radeon, &backend_rockchip, &backend_sun4i_drm, &backend_synaptics, &backend_udl, &backend_virtgpu, - &backend_vkms + &backend_vkms, &backend_mock }; void drv_preload(bool load) @@ -118,7 +121,8 @@ struct driver *drv_create(int fd) const char *minigbm_debug; minigbm_debug = drv_get_os_option(MINIGBM_DEBUG); - drv->compression = (minigbm_debug == NULL) || (strcmp(minigbm_debug, "nocompression") != 0); + drv->compression = (minigbm_debug == NULL) || (strstr(minigbm_debug, "nocompression") == NULL); + drv->log_bos = (minigbm_debug && strstr(minigbm_debug, "log_bos") != NULL); drv->fd = fd; drv->backend = drv_get_backend(fd); @@ -365,6 +369,9 @@ struct bo *drv_bo_create(struct driver *drv, uint32_t width, uint32_t height, ui drv_bo_acquire(bo); + if (drv->log_bos) + drv_bo_log_info(bo, "legacy created"); + return bo; } @@ -402,6 +409,9 @@ struct bo *drv_bo_create_with_modifiers(struct driver *drv, uint32_t width, uint drv_bo_acquire(bo); + if (drv->log_bos) + drv_bo_log_info(bo, "created"); + return bo; } @@ -460,6 +470,9 @@ struct bo *drv_bo_import(struct driver *drv, struct drv_import_fd_data *data) bo->meta.total_size += bo->meta.sizes[plane]; } + if (drv->log_bos) + drv_bo_log_info(bo, "imported"); + return bo; destroy_bo: @@ -574,6 +587,11 @@ out: return ret; } +bool drv_bo_cached(struct bo *bo) +{ + return bo->meta.cached; +} + int drv_bo_invalidate(struct bo *bo, struct mapping *mapping) { int ret = 0; @@ -710,6 +728,26 @@ size_t drv_bo_get_total_size(struct bo *bo) return bo->meta.total_size; } +void drv_bo_log_info(const struct bo *bo, const char *prefix) +{ + const struct bo_metadata *meta = &bo->meta; + + drv_logd("%s %s bo %p: %dx%d '%c%c%c%c' tiling %d plane %zu mod 0x%" PRIx64 " use 0x%" PRIx64 " size %zu\n", + prefix, bo->drv->backend->name, bo, + meta->width, meta->height, + meta->format & 0xff, + (meta->format >> 8) & 0xff, + (meta->format >> 16) & 0xff, + (meta->format >> 24) & 0xff, + meta->tiling, meta->num_planes, meta->format_modifier, + meta->use_flags, meta->total_size); + for (uint32_t i = 0; i < meta->num_planes; i++) { + drv_logd(" bo %p plane %d: offset %d size %d stride %d\n", + bo, i, meta->offsets[i], meta->sizes[i], + meta->strides[i]); + } +} + /* * Map internal fourcc codes back to standard fourcc codes. */ @@ -727,11 +765,11 @@ void drv_resolve_format_and_use_flags(struct driver *drv, uint32_t format, uint6 out_use_flags); } -void drv_log_prefix(enum drv_log_level level, const char *prefix, const char *file, int line, +void drv_log_prefix(enum drv_log_level level, const char *prefix, const char *func, int line, const char *format, ...) { char buf[50]; - snprintf(buf, sizeof(buf), "[%s:%s(%d)]", prefix, basename(file), line); + snprintf(buf, sizeof(buf), "[%s:%s(%d)]", prefix, func, line); va_list args; va_start(args, format); @@ -83,6 +83,21 @@ extern "C" { #ifndef I915_FORMAT_MOD_4_TILED #define I915_FORMAT_MOD_4_TILED fourcc_mod_code(INTEL, 9) #endif + +#ifndef I915_FORMAT_MOD_4_TILED_MTL_RC_CCS +//TODO: remove this defination once drm_fourcc.h contains it. +/* + * Intel color control surfaces (CCS) for display ver 14 render compression. + * + * The main surface is tile4 and at plane index 0, the CCS is linear and + * at index 1. A 64B CCS cache line corresponds to an area of 4x1 tiles in + * main surface. In other words, 4 bits in CCS map to a main surface cache + * line pair. The main surface pitch is required to be a multiple of four + * tile4 widths. + */ +#define I915_FORMAT_MOD_4_TILED_MTL_RC_CCS fourcc_mod_code(INTEL, 13) +#endif + // clang-format on struct driver; struct bo; @@ -161,6 +176,8 @@ void *drv_bo_map(struct bo *bo, const struct rectangle *rect, uint32_t map_flags int drv_bo_unmap(struct bo *bo, struct mapping *mapping); +bool drv_bo_cached(struct bo *bo); + int drv_bo_invalidate(struct bo *bo, struct mapping *mapping); int drv_bo_flush(struct bo *bo, struct mapping *mapping); @@ -193,6 +210,8 @@ uint64_t drv_bo_get_use_flags(struct bo *bo); size_t drv_bo_get_total_size(struct bo *bo); +void drv_bo_log_info(const struct bo *bo, const char *prefix); + uint32_t drv_get_standard_fourcc(uint32_t fourcc_internal); uint32_t drv_bytes_per_pixel_from_format(uint32_t format, size_t plane); @@ -221,7 +240,7 @@ enum drv_log_level { #define _drv_log(level, format, ...) \ do { \ - drv_log_prefix(level, "minigbm", __FILE__, __LINE__, format, ##__VA_ARGS__); \ + drv_log_prefix(level, "minigbm", __func__, __LINE__, format, ##__VA_ARGS__); \ } while (0) #define drv_loge(format, ...) _drv_log(DRV_LOGE, format, ##__VA_ARGS__) @@ -27,6 +27,7 @@ struct bo_metadata { uint64_t format_modifier; uint64_t use_flags; size_t total_size; + bool cached; /* * Most of the following metadata is virtgpu cross_domain specific. However, that backend @@ -70,6 +71,7 @@ struct driver { struct drv_array *mappings; struct drv_array *combos; bool compression; + bool log_bos; }; struct backend { @@ -87,10 +87,21 @@ PUBLIC struct gbm_surface *gbm_surface_create_with_modifiers(struct gbm_device * const uint64_t *modifiers, const unsigned int count) { + return gbm_surface_create_with_modifiers2(gbm, width, height, format, modifiers, count, 0); +} + +PUBLIC struct gbm_surface * +gbm_surface_create_with_modifiers2(struct gbm_device *gbm, uint32_t width, uint32_t height, + uint32_t format, const uint64_t *modifiers, + const unsigned int count, uint32_t flags) +{ if (count != 0 || modifiers != NULL) return NULL; - return gbm_surface_create(gbm, width, height, format, 0); + if (flags != 0) + return NULL; + + return gbm_surface_create(gbm, width, height, format, flags); } PUBLIC struct gbm_bo *gbm_surface_lock_front_buffer(struct gbm_surface *surface) @@ -161,8 +172,19 @@ PUBLIC struct gbm_bo *gbm_bo_create_with_modifiers(struct gbm_device *gbm, uint3 uint32_t height, uint32_t format, const uint64_t *modifiers, uint32_t count) { + return gbm_bo_create_with_modifiers2(gbm, width, height, format, modifiers, count, 0); +} + +PUBLIC struct gbm_bo *gbm_bo_create_with_modifiers2(struct gbm_device *gbm, uint32_t width, + uint32_t height, uint32_t format, + const uint64_t *modifiers, + const unsigned int count, uint32_t flags) +{ struct gbm_bo *bo; + if (flags != 0) + return NULL; + bo = gbm_bo_new(gbm, format); if (!bo) @@ -267,6 +289,13 @@ PUBLIC void *gbm_bo_map(struct gbm_bo *bo, uint32_t x, uint32_t y, uint32_t widt return gbm_bo_map2(bo, x, y, width, height, transfer_flags, stride, map_data, 0); } +PUBLIC enum gbm_bo_map_cache_mode gbm_bo_get_map_info(struct gbm_bo *bo) +{ + if (drv_bo_cached(bo->bo)) + return GBM_BO_MAP_CACHE_CACHED; + return GBM_BO_MAP_CACHE_WC; +} + PUBLIC void gbm_bo_unmap(struct gbm_bo *bo, void *map_data) { assert(bo); @@ -323,7 +352,7 @@ PUBLIC int gbm_bo_get_plane_count(struct gbm_bo *bo) return drv_bo_get_num_planes(bo->bo); } -PUBLIC union gbm_bo_handle gbm_bo_get_handle_for_plane(struct gbm_bo *bo, size_t plane) +PUBLIC union gbm_bo_handle gbm_bo_get_handle_for_plane(struct gbm_bo *bo, int plane) { return (union gbm_bo_handle)drv_bo_get_plane_handle(bo->bo, (size_t)plane).u64; } @@ -333,12 +362,12 @@ PUBLIC int gbm_bo_get_fd_for_plane(struct gbm_bo *bo, int plane) return drv_bo_get_plane_fd(bo->bo, plane); } -PUBLIC uint32_t gbm_bo_get_offset(struct gbm_bo *bo, size_t plane) +PUBLIC uint32_t gbm_bo_get_offset(struct gbm_bo *bo, int plane) { return drv_bo_get_plane_offset(bo->bo, (size_t)plane); } -PUBLIC uint32_t gbm_bo_get_stride_for_plane(struct gbm_bo *bo, size_t plane) +PUBLIC uint32_t gbm_bo_get_stride_for_plane(struct gbm_bo *bo, int plane) { return drv_bo_get_plane_stride(bo->bo, (size_t)plane); } @@ -339,6 +339,16 @@ gbm_bo_create_with_modifiers(struct gbm_device *gbm, uint32_t format, const uint64_t *modifiers, const unsigned int count); + +struct gbm_bo * +gbm_bo_create_with_modifiers2(struct gbm_device *gbm, + uint32_t width, + uint32_t height, + uint32_t format, + const uint64_t *modifiers, + const unsigned int count, + uint32_t flags); + #define GBM_BO_IMPORT_WL_BUFFER 0x5501 #define GBM_BO_IMPORT_EGL_IMAGE 0x5502 #define GBM_BO_IMPORT_FD 0x5503 @@ -403,6 +413,24 @@ gbm_bo_map(struct gbm_bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint32_t flags, uint32_t *stride, void **map_data); +/** + * Enum to indicate the cache attributes of CPU mapping returned by + * gbm_bo_map() + * + * Note that definition aligns with VIRTIO_GPU_MAP_CACHE_*, RUTABAGA_MAP_CACHE_*, + * and VIRGL_RENDERER_MAP_CACHE_* (but skipping the _NONE and _UNCACHED values as + * those don't actually make sense to use). + */ +enum gbm_bo_map_cache_mode { + /*GBM_BO_MAP_CACHE_NONE = 0,*/ + GBM_BO_MAP_CACHE_CACHED = 1, + /*GBM_BO_MAP_CACHE_UNCACHED = 2,*/ + GBM_BO_MAP_CACHE_WC = 3, +}; + +enum gbm_bo_map_cache_mode +gbm_bo_get_map_info(struct gbm_bo *bo); + void gbm_bo_unmap(struct gbm_bo *bo, void *map_data); @@ -416,7 +444,7 @@ uint32_t gbm_bo_get_stride(struct gbm_bo *bo); uint32_t -gbm_bo_get_stride_for_plane(struct gbm_bo *bo, size_t plane); +gbm_bo_get_stride_for_plane(struct gbm_bo *bo, int plane); uint32_t gbm_bo_get_format(struct gbm_bo *bo); @@ -425,7 +453,7 @@ uint32_t gbm_bo_get_bpp(struct gbm_bo *bo); uint32_t -gbm_bo_get_offset(struct gbm_bo *bo, size_t plane); +gbm_bo_get_offset(struct gbm_bo *bo, int plane); struct gbm_device * gbm_bo_get_device(struct gbm_bo *bo); @@ -443,7 +471,7 @@ int gbm_bo_get_plane_count(struct gbm_bo *bo); union gbm_bo_handle -gbm_bo_get_handle_for_plane(struct gbm_bo *bo, size_t plane); +gbm_bo_get_handle_for_plane(struct gbm_bo *bo, int plane); int gbm_bo_get_fd_for_plane(struct gbm_bo *bo, int plane); @@ -473,6 +501,15 @@ gbm_surface_create_with_modifiers(struct gbm_device *gbm, const uint64_t *modifiers, const unsigned int count); +struct gbm_surface * +gbm_surface_create_with_modifiers2(struct gbm_device *gbm, + uint32_t width, + uint32_t height, + uint32_t format, + const uint64_t *modifiers, + const unsigned int count, + uint32_t flags); + struct gbm_bo * gbm_surface_lock_front_buffer(struct gbm_surface *surface); diff --git a/gbm_unittest.cc b/gbm_unittest.cc new file mode 100644 index 0000000..9f2a46f --- /dev/null +++ b/gbm_unittest.cc @@ -0,0 +1,82 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Test gbm.h module code using gtest. + */ + +#include <drm/drm_fourcc.h> +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include <xf86drm.h> + +#include "gbm.h" + +class MockDrm +{ + public: + MOCK_METHOD(drmVersionPtr, drmGetVersion, (int fd)); + MOCK_METHOD(void, drmFreeVersion, (drmVersionPtr v)); +}; + +// Define a mock version of drmGetVersion +drmVersionPtr drmGetVersion(int fd) +{ + drmVersionPtr mock_version = new drmVersion(); + mock_version->name = "Mock Backend"; + return mock_version; +} + +// Define a mock version of drmFreeVersion +void drmFreeVersion(drmVersionPtr v) +{ + delete(v); +} + +/* TODO : This is a protocol to add unit tests for the public APIs in minigbm. + * + * The ultimate goal would be cover more APIs and the input combinations. + * Set fd to 0 for now, it doesn't have any particular meaning + */ + +TEST(gbm_unit_test, create_device) +{ + MockDrm mock_drm; // Create a mock object + + EXPECT_CALL(mock_drm, drmGetVersion(testing::_)) + .WillRepeatedly(testing::Invoke(&mock_drm, &MockDrm::drmGetVersion)); + + struct gbm_device *gbm_device = gbm_create_device(0); + + ASSERT_TRUE(gbm_device); + + gbm_device_destroy(gbm_device); +} + +TEST(gbm_unit_test, valid_fd) +{ + MockDrm mock_drm; // Create a mock object + + EXPECT_CALL(mock_drm, drmGetVersion(testing::_)) + .WillRepeatedly(testing::Invoke(&mock_drm, &MockDrm::drmGetVersion)); + struct gbm_device *gbm_device = gbm_create_device(99); + int fd = gbm_device_get_fd(gbm_device); + + ASSERT_EQ(fd, 99); + + gbm_device_destroy(gbm_device); +} + +TEST(gbm_unit_test, valid_backend_name) +{ + MockDrm mock_drm; // Create a mock object + + EXPECT_CALL(mock_drm, drmGetVersion(testing::_)) + .WillRepeatedly(testing::Invoke(&mock_drm, &MockDrm::drmGetVersion)); + struct gbm_device *gbm_device = gbm_create_device(0); + const char *backend_name = gbm_device_get_backend_name(gbm_device); + + ASSERT_STREQ(backend_name, "Mock Backend"); + + gbm_device_destroy(gbm_device); +} @@ -37,21 +37,16 @@ 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_without_mc[] = { 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 gen12_modifier_order_with_mc[] = { I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS, - I915_FORMAT_MOD_Y_TILED_GEN12_MC_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_GEN12_MC_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 }; -static const uint64_t xe_lpdp_modifier_order[] = { I915_FORMAT_MOD_4_TILED, I915_FORMAT_MOD_X_TILED, +static const uint64_t xe_lpdp_modifier_order[] = { I915_FORMAT_MOD_4_TILED_MTL_RC_CCS, + I915_FORMAT_MOD_4_TILED, I915_FORMAT_MOD_X_TILED, DRM_FORMAT_MOD_LINEAR }; struct modifier_support_t { @@ -70,7 +65,6 @@ struct i915_device { bool is_mtl; int32_t num_fences_avail; bool has_mmap_offset; - bool is_media_compression_enabled; }; static void i915_info_from_device_id(struct i915_device *i915) @@ -120,9 +114,10 @@ static void i915_info_from_device_id(struct i915_device *i915) }; 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 }; + 0x46C0, 0x46C1, 0x46C2, 0x46C3, 0x46D0, 0x46D1, 0x46D2, + 0x46D3, 0x46D4 }; - const uint16_t rplp_ids[] = { 0xA720, 0xA721, 0xA7A0, 0xA7A1, 0xA7A8, 0xA7A9 }; + const uint16_t rplp_ids[] = { 0xA720, 0xA721, 0xA7A0, 0xA7A1, 0xA7A8, 0xA7A9, 0xA7AA, 0xA7AB, 0xA7AC, 0xA7AD }; const uint16_t mtl_ids[] = { 0x7D40, 0x7D60, 0x7D45, 0x7D55, 0x7DD5 }; @@ -200,13 +195,12 @@ static void i915_get_modifier_order(struct i915_device *i915) i915->modifier.order = xe_lpdp_modifier_order; i915->modifier.count = ARRAY_SIZE(xe_lpdp_modifier_order); } else if (i915->graphics_version == 12) { - if (i915->is_media_compression_enabled) { - i915->modifier.order = gen12_modifier_order_with_mc; - i915->modifier.count = ARRAY_SIZE(gen12_modifier_order_with_mc); - } else { - i915->modifier.order = gen12_modifier_order_without_mc; - i915->modifier.count = ARRAY_SIZE(gen12_modifier_order_without_mc); - } + /* + * On ADL platforms of gen 12 onwards, Intel media compression is supported for + * video decoding on Chrome. + */ + i915->modifier.order = gen12_modifier_order; + i915->modifier.count = ARRAY_SIZE(gen12_modifier_order); } else if (i915->graphics_version == 11) { i915->modifier.order = gen11_modifier_order; i915->modifier.count = ARRAY_SIZE(gen11_modifier_order); @@ -308,14 +302,10 @@ static int i915_add_combinations(struct driver *drv) ARRAY_SIZE(scanout_render_formats), &metadata_4_tiled, scanout_and_render_not_linear); } else { - struct format_metadata metadata_y_tiled = { - .tiling = I915_TILING_Y, - .priority = 3, - .modifier = - (i915->graphics_version == 12 && i915->is_media_compression_enabled) - ? I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS - : I915_FORMAT_MOD_Y_TILED - }; + struct format_metadata metadata_y_tiled = { .tiling = I915_TILING_Y, + .priority = 3, + .modifier = I915_FORMAT_MOD_Y_TILED }; + /* Support y-tiled NV12 and P010 for libva */ #ifdef I915_SCANOUT_Y_TILED const uint64_t nv12_usage = @@ -327,13 +317,6 @@ static int i915_add_combinations(struct driver *drv) const uint64_t nv12_usage = BO_USE_TEXTURE | BO_USE_HW_VIDEO_DECODER; const uint64_t p010_usage = nv12_usage; #endif - drv_add_combination(drv, DRM_FORMAT_NV12, &metadata_y_tiled, nv12_usage); - drv_add_combination(drv, DRM_FORMAT_P010, &metadata_y_tiled, p010_usage); - - /* Don't allocate media compressed buffers for formats other than NV12 - * and P010. - */ - metadata_y_tiled.modifier = I915_FORMAT_MOD_Y_TILED; drv_add_combinations(drv, render_formats, ARRAY_SIZE(render_formats), &metadata_y_tiled, render_not_linear); /* Y-tiled scanout isn't available on old platforms so we add @@ -342,6 +325,8 @@ static int i915_add_combinations(struct driver *drv) drv_add_combinations(drv, scanout_render_formats, ARRAY_SIZE(scanout_render_formats), &metadata_y_tiled, render_not_linear); + drv_add_combination(drv, DRM_FORMAT_NV12, &metadata_y_tiled, nv12_usage); + drv_add_combination(drv, DRM_FORMAT_P010, &metadata_y_tiled, p010_usage); } return 0; } @@ -459,17 +444,6 @@ static int i915_init(struct driver *drv) if (!i915) return -ENOMEM; - const char *enable_intel_media_compression_env_var = - getenv("ENABLE_INTEL_MEDIA_COMPRESSION"); - if (enable_intel_media_compression_env_var == NULL) { - drv_logd("Failed to get ENABLE_INTEL_MEDIA_COMPRESSION"); - i915->is_media_compression_enabled = false; - } else { - i915->is_media_compression_enabled = - (drv->compression) && - (strcmp(enable_intel_media_compression_env_var, "1") == 0); - } - get_param.param = I915_PARAM_CHIPSET_ID; get_param.value = &(i915->device_id); ret = drmIoctl(drv->fd, DRM_IOCTL_I915_GETPARAM, &get_param); @@ -584,15 +558,11 @@ static size_t i915_num_planes_from_modifier(struct driver *drv, uint32_t format, { 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) { + modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS || + modifier == I915_FORMAT_MOD_4_TILED_MTL_RC_CCS) { assert(num_planes == 1); return 2; } else if (modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS) { - assert(drv); - struct i915_device *i915 = drv->priv; - assert(i915 && i915->is_media_compression_enabled); - (void)i915; - assert(num_planes == 2); return 4; } @@ -615,6 +585,19 @@ static int i915_bo_compute_metadata(struct bo *bo, uint32_t width, uint32_t heig if (!combo) return -EINVAL; modifier = combo->metadata.modifier; + /* + * Media compression modifiers should not be picked automatically by minigbm based + * on |use_flags|. Instead the client should request them explicitly through + * gbm_bo_create_with_modifiers(). + */ + assert(modifier != I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS); + /* TODO(b/323863689): Account for driver's bandwidth compression in minigbm for + * media compressed buffers. */ + } + if (modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS && + !(format == DRM_FORMAT_NV12 || format == DRM_FORMAT_P010)) { + drv_loge("Media compression is only supported for NV12 and P010\n"); + return -EINVAL; } /* @@ -655,9 +638,6 @@ static int i915_bo_compute_metadata(struct bo *bo, uint32_t width, uint32_t heig modifier = DRM_FORMAT_MOD_LINEAR; } - assert(modifier != I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS || - i915->is_media_compression_enabled); - switch (modifier) { case DRM_FORMAT_MOD_LINEAR: bo->meta.tiling = I915_TILING_NONE; @@ -675,6 +655,7 @@ static int i915_bo_compute_metadata(struct bo *bo, uint32_t width, uint32_t heig bo->meta.tiling = I915_TILING_Y; break; case I915_FORMAT_MOD_4_TILED: + case I915_FORMAT_MOD_4_TILED_MTL_RC_CCS: bo->meta.tiling = I915_TILING_4; break; } @@ -735,10 +716,17 @@ static int i915_bo_compute_metadata(struct bo *bo, uint32_t width, uint32_t heig bo->meta.total_size = offset; } else if (modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS || modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS) { + /* + * Media compression modifiers should only be possible via the + * gbm_bo_create_with_modifiers() path, i.e., the minigbm client needs to + * explicitly request it. + */ + assert(modifier != I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS || + use_flags == BO_USE_NONE); assert(modifier != I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS || - i915->is_media_compression_enabled); + bo->meta.use_flags == BO_USE_NONE); assert(modifier != I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS || - (format == DRM_FORMAT_NV12 || format == DRM_FORMAT_P010)); + (!!modifiers && count > 0)); assert(drv_num_planes_from_format(format) > 0); uint32_t offset = 0; @@ -794,6 +782,39 @@ static int i915_bo_compute_metadata(struct bo *bo, uint32_t width, uint32_t heig /* Total number of planes & sizes */ bo->meta.num_planes = plane + a_plane; bo->meta.total_size = offset; + } else if (modifier == I915_FORMAT_MOD_4_TILED_MTL_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); + stride = ALIGN(stride, 256); + + height = ALIGN(drv_height_from_format(format, height, 0), 32); + + + 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 = 2; + bo->meta.total_size = bo->meta.sizes[0] + bo->meta.sizes[1]; } else { return i915_bo_from_format(bo, width, height, format); } @@ -858,6 +879,10 @@ static int i915_bo_create_from_metadata(struct bo *bo) return -errno; } } + + bo->meta.cached = (i915->has_llc || i915->is_mtl) && + !(bo->meta.use_flags & BO_USE_SCANOUT); + return 0; } @@ -907,7 +932,8 @@ static void *i915_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags) if ((bo->meta.format_modifier == I915_FORMAT_MOD_Y_TILED_CCS) || (bo->meta.format_modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS) || (bo->meta.format_modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS) || - (bo->meta.format_modifier == I915_FORMAT_MOD_4_TILED)) + (bo->meta.format_modifier == I915_FORMAT_MOD_4_TILED) || + (bo->meta.format_modifier == I915_FORMAT_MOD_4_TILED_MTL_RC_CCS)) return MAP_FAILED; if (bo->meta.tiling == I915_TILING_NONE) { @@ -47,6 +47,17 @@ #define DONT_USE_64_ALIGNMENT_FOR_VIDEO_BUFFERS #endif +// Devices newer than MT8186 support AR30 overlays and 10-bit video. +// clang-format off +#if !defined(MTK_MT8173) && \ + !defined(MTK_MT8183) && \ + !defined(MTK_MT8186) && \ + !defined(MTK_MT8192) +// clang-format on +#define SUPPORT_P010 +#define SUPPORT_AR30_OVERLAYS +#endif + // For Mali Sigurd based GPUs, the texture unit reads outside the specified texture dimensions. // Therefore, certain formats require extra memory padding to its allocated surface to prevent the // hardware from reading outside an allocation. For YVU420, we need additional padding for the last @@ -71,6 +82,9 @@ static const uint32_t texture_source_formats[] = { DRM_FORMAT_NV21, DRM_FORMAT_YUYV, #endif +#ifdef SUPPORT_P010 + DRM_FORMAT_P010, +#endif #ifdef SUPPORT_FP16_AND_10BIT_ABGR DRM_FORMAT_ABGR2101010, DRM_FORMAT_ABGR16161616F, @@ -83,6 +97,9 @@ static const uint32_t texture_source_formats[] = { static const uint32_t video_yuv_formats[] = { DRM_FORMAT_NV21, DRM_FORMAT_NV12, +#ifdef SUPPORT_P010 + DRM_FORMAT_P010, +#endif DRM_FORMAT_YUYV, DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID @@ -110,7 +127,13 @@ static int mediatek_init(struct driver *drv) drv_add_combinations(drv, texture_source_formats, ARRAY_SIZE(texture_source_formats), &LINEAR_METADATA, BO_USE_TEXTURE_MASK | BO_USE_PROTECTED); - drv_add_combination(drv, DRM_FORMAT_R8, &LINEAR_METADATA, BO_USE_SW_MASK | BO_USE_LINEAR | BO_USE_PROTECTED); + drv_add_combination(drv, DRM_FORMAT_R8, &LINEAR_METADATA, + BO_USE_SW_MASK | BO_USE_LINEAR | BO_USE_PROTECTED); + +#ifdef SUPPORT_AR30_OVERLAYS + drv_add_combination(drv, DRM_FORMAT_ARGB2101010, &LINEAR_METADATA, + BO_USE_TEXTURE | BO_USE_SCANOUT | BO_USE_PROTECTED | BO_USE_LINEAR); +#endif /* YUYV format for video overlay and camera subsystem. */ drv_add_combination(drv, DRM_FORMAT_YUYV, &LINEAR_METADATA, @@ -124,12 +147,26 @@ static int mediatek_init(struct driver *drv) metadata.tiling = TILE_TYPE_LINEAR; metadata.priority = 1; metadata.modifier = DRM_FORMAT_MOD_LINEAR; - drv_modify_combination(drv, DRM_FORMAT_YVU420, &metadata, BO_USE_HW_VIDEO_DECODER | BO_USE_PROTECTED); - drv_modify_combination(drv, DRM_FORMAT_YVU420_ANDROID, &metadata, BO_USE_HW_VIDEO_DECODER | BO_USE_PROTECTED); + drv_modify_combination(drv, DRM_FORMAT_YVU420, &metadata, + BO_USE_HW_VIDEO_DECODER | BO_USE_PROTECTED); +#ifdef MTK_MT8173 + /* + * b/292507490: The MT8173 decoder can output YUV420 only. Some CTS tests feed the + * decoded buffer to the hardware encoder and the tests allocate the buffer with + * DRM_FORMAT_FLEX_YCbCr_420_888 with the mask of BO_USE_HW_VIDEO_ENCODER | + * BO_USE_HW_VIDEO_DECODER. Therefore, we have to allocate YUV420 in the case. + */ + drv_modify_combination(drv, DRM_FORMAT_YVU420, &metadata, BO_USE_HW_VIDEO_ENCODER); +#endif + drv_modify_combination(drv, DRM_FORMAT_YVU420_ANDROID, &metadata, + BO_USE_HW_VIDEO_DECODER | BO_USE_PROTECTED); #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 | BO_USE_PROTECTED); + drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata, + BO_USE_HW_VIDEO_DECODER | BO_USE_PROTECTED); #endif + drv_modify_combination(drv, DRM_FORMAT_P010, &metadata, + BO_USE_HW_VIDEO_DECODER | BO_USE_PROTECTED); /* * R8 format is used for Android's HAL_PIXEL_FORMAT_BLOB for input/output from @@ -176,6 +213,11 @@ static int mediatek_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint const bool is_camera_preview = (bo->meta.use_flags & BO_USE_SCANOUT) && (bo->meta.use_flags & BO_USE_CAMERA_WRITE); const bool is_hw_video_encoder = bo->meta.use_flags & BO_USE_HW_VIDEO_ENCODER; +#ifdef MTK_MT8173 + const bool is_mt8173_video_decoder = bo->meta.use_flags & BO_USE_HW_VIDEO_DECODER; +#else + const bool is_mt8173_video_decoder = false; +#endif /* * Android sends blobs for encoding in the shape of a single-row pixel buffer. Use R8 + * single row as a proxy for Android HAL_PIXEL_FORMAT_BLOB until a drm equivalent is @@ -203,7 +245,24 @@ static int mediatek_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint stride = ALIGN(stride, 64); #endif - if ((is_hw_video_encoder && !is_format_blob) || is_camera_preview) { + /* + * The mediatek video decoder requires to align width and height by 64. But this is + * the requirement for mediatek tiled format (e.g. MT21 and MM21). The buffers are + * not allocated by minigbm. So we don't have to care about it. The tiled buffer is + * converted to NV12 or YV12, which is allocated by minigbm. V4L2 MDP doesn't + * require any special alignment for them. + * On the other hand, the mediatek video encoder reuqires a padding on each plane. + * When both video decoder and encoder use flag is masked (in some CTS test), we + * align with the encoder alignment. + * However, V4L2VideoDecodeAccelerator used on MT8173 fails handling the buffer with + * padding, although V4L2VideoDecoder used on MT8183 and later can do. We workaround + * this problem to allocate a buffer without padding on MT8173. This works because + * MT8173 decoder's output NV12 is converted to YV12 buffer that is allocated with + * video encoder usage mask only and thus have padding in Android. + * See go/mediatek-video-buffer-alignment-note for detail. + */ + if ((is_hw_video_encoder && !is_mt8173_video_decoder && !is_format_blob) || + is_camera_preview) { uint32_t aligned_height = ALIGN(height, 32); uint32_t padding[DRV_MAX_PLANES] = { 0 }; @@ -432,12 +491,24 @@ static void mediatek_resolve_format_and_use_flags(struct driver *drv, uint32_t f break; } #endif + /* + * b/292507490: The MT8173 decoder can output YUV420 only. Some CTS tests feed the + * decoded buffer to the hardware encoder and the tests allocate the buffer with + * DRM_FORMAT_FLEX_YCbCr_420_888 with the mask of BO_USE_HW_VIDEO_ENCODER | + * BO_USE_HW_VIDEO_DECODER. Therefore, we have to allocate YUV420 in the case. + */ if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_ENCODER)) { +#ifndef MTK_MT8173 *out_format = DRM_FORMAT_NV12; break; +#else + if (!(use_flags & BO_USE_HW_VIDEO_DECODER)) { + *out_format = DRM_FORMAT_NV12; + break; + } +#endif } - /* HACK: See b/139714614 */ *out_format = DRM_FORMAT_YVU420; *out_use_flags &= ~BO_USE_SCANOUT; diff --git a/testrunner.cc b/testrunner.cc new file mode 100644 index 0000000..37a858f --- /dev/null +++ b/testrunner.cc @@ -0,0 +1,15 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Main entrypoint for gtest. + */ + +#include <gtest/gtest.h> + +int main(int argc, char **argv) +{ + testing::InitGoogleTest(&argc, argv); + + return RUN_ALL_TESTS(); +} @@ -23,3 +23,9 @@ enum virtgpu_param_id { param_guest_vram, param_max, }; + +#define VIRTIO_GPU_CAPSET_VIRGL 1 +#define VIRTIO_GPU_CAPSET_VIRGL2 2 +#define VIRTIO_GPU_CAPSET_GFXSTREAM 3 +#define VIRTIO_GPU_CAPSET_VENUS 4 +#define VIRTIO_GPU_CAPSET_CROSS_DOMAIN 5 diff --git a/virtgpu_cross_domain.c b/virtgpu_cross_domain.c index dc3fbc1..85589dc 100644 --- a/virtgpu_cross_domain.c +++ b/virtgpu_cross_domain.c @@ -16,7 +16,6 @@ #include "util.h" #include "virtgpu.h" -#define CAPSET_CROSS_DOMAIN 5 #define CAPSET_CROSS_FAKE 30 static const uint32_t scanout_render_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888, @@ -246,7 +245,7 @@ static int cross_domain_init(struct driver *drv) if (!params[param_context_init].value) return -ENOTSUP; - if ((params[param_supported_capset_ids].value & (1 << CAPSET_CROSS_DOMAIN)) == 0) + if ((params[param_supported_capset_ids].value & (1 << VIRTIO_GPU_CAPSET_CROSS_DOMAIN)) == 0) return -ENOTSUP; if (!params[param_resource_blob].value) @@ -275,7 +274,7 @@ static int cross_domain_init(struct driver *drv) priv->ring_addr = MAP_FAILED; drv->priv = priv; - args.cap_set_id = CAPSET_CROSS_DOMAIN; + args.cap_set_id = VIRTIO_GPU_CAPSET_CROSS_DOMAIN; args.size = sizeof(struct CrossDomainCapabilities); args.addr = (unsigned long long)&cross_domain_caps; @@ -296,7 +295,7 @@ static int cross_domain_init(struct driver *drv) // Intialize the cross domain context. Create one fence context to wait for metadata // queries. ctx_set_params[0].param = VIRTGPU_CONTEXT_PARAM_CAPSET_ID; - ctx_set_params[0].value = CAPSET_CROSS_DOMAIN; + ctx_set_params[0].value = VIRTIO_GPU_CAPSET_CROSS_DOMAIN; ctx_set_params[1].param = VIRTGPU_CONTEXT_PARAM_NUM_RINGS; ctx_set_params[1].value = 1; diff --git a/virtgpu_virgl.c b/virtgpu_virgl.c index b8517fc..222703e 100644 --- a/virtgpu_virgl.c +++ b/virtgpu_virgl.c @@ -549,14 +549,31 @@ static int virgl_get_caps(struct driver *drv, union virgl_caps *caps, int *caps_ int ret; struct drm_virtgpu_get_caps cap_args = { 0 }; + memset(caps, 0, sizeof(union virgl_caps)); *caps_is_v2 = 0; - cap_args.addr = (unsigned long long)caps; - if (params[param_capset_fix].value) { + + if (params[param_supported_capset_ids].value) { + drv_logi("Supported CAPSET IDs: %u.", params[param_supported_capset_ids].value); + if (params[param_supported_capset_ids].value & (1 << VIRTIO_GPU_CAPSET_VIRGL2)) { + *caps_is_v2 = 1; + } else if (params[param_supported_capset_ids].value & + (1 << VIRTIO_GPU_CAPSET_VIRGL)) { + *caps_is_v2 = 0; + } else { + drv_logi("Unrecognized CAPSET IDs: %u. Assuming all zero caps.", + params[param_supported_capset_ids].value); + return 0; + } + } else if (params[param_capset_fix].value) { *caps_is_v2 = 1; - cap_args.cap_set_id = 2; + } + + cap_args.addr = (unsigned long long)caps; + if (*caps_is_v2) { + cap_args.cap_set_id = VIRTIO_GPU_CAPSET_VIRGL2; cap_args.size = sizeof(union virgl_caps); } else { - cap_args.cap_set_id = 1; + cap_args.cap_set_id = VIRTIO_GPU_CAPSET_VIRGL; cap_args.size = sizeof(struct virgl_caps_v1); } @@ -566,7 +583,7 @@ static int virgl_get_caps(struct driver *drv, union virgl_caps *caps, int *caps_ *caps_is_v2 = 0; // Fallback to v1 - cap_args.cap_set_id = 1; + cap_args.cap_set_id = VIRTIO_GPU_CAPSET_VIRGL; cap_args.size = sizeof(struct virgl_caps_v1); ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GET_CAPS, &cap_args); |