diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 01:00:38 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 01:00:38 +0000 |
commit | 2fd64cad52d2ded3ec1f39309608aa73dfe6c8e4 (patch) | |
tree | 6e875bc030bdfb362f5851eb8bde03d87e82d935 | |
parent | 9f5a22cfcb2cc23f3ef8ecbe73b76a2c34382ffb (diff) | |
parent | 9b05077bc12b7b13ad680bfaec35ddd3cff5dd93 (diff) | |
download | minigbm-aml_cbr_341610000.tar.gz |
Snap for 10447354 from 9b05077bc12b7b13ad680bfaec35ddd3cff5dd93 to mainline-cellbroadcast-releaseaml_cbr_341710000aml_cbr_341610000aml_cbr_341510010aml_cbr_341410010aml_cbr_341311010aml_cbr_341110000aml_cbr_341011000aml_cbr_340914000android14-mainline-cellbroadcast-release
Change-Id: I66e7dda0ad65e2641cd8ed9bedbc850308344fe5
44 files changed, 2018 insertions, 562 deletions
diff --git a/DIR_METADATA b/DIR_METADATA new file mode 100644 index 0000000..55fd9f0 --- /dev/null +++ b/DIR_METADATA @@ -0,0 +1,34 @@ +# Metadata information for this directory. +# +# For more information on DIR_METADATA files, see: +# https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/README.md +# +# For the schema of this file, see Metadata message: +# https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/proto/dir_metadata.proto + +buganizer { + # ChromeOS > Platform > Graphics > Graphics Virtualization + component_id: 964076 +} + +chromeos { + cq { + source_test_plans { + test_plan_starlark_files { + host: "chrome-internal.googlesource.com" + project: "chromeos/config-internal" + path: "test/plans/v2/ctpv1_compatible/legacy_default_tast_hw.star" + } + test_plan_starlark_files { + host: "chrome-internal.googlesource.com" + project: "chromeos/config-internal" + path: "test/plans/v2/ctpv1_compatible/legacy_default_autotest_hw.star" + } + test_plan_starlark_files { + host: "chrome-internal.googlesource.com" + project: "chromeos/config-internal" + path: "test/plans/v2/ctpv1_compatible/legacy_default_vm.star" + } + } + } +} @@ -59,3 +59,4 @@ install: all ln -sf $(MINIGBM_FILENAME) $(DESTDIR)/$(LIBDIR)/libgbm.so.$(GBM_VERSION_MAJOR) install -D -m 0644 $(SRC)/gbm.pc $(DESTDIR)$(LIBDIR)/pkgconfig/gbm.pc install -D -m 0644 $(SRC)/gbm.h $(DESTDIR)/usr/include/gbm.h + install -D -m 0644 $(SRC)/minigbm_helpers.h $(DESTDIR)/usr/include/minigbm/minigbm_helpers.h @@ -10,6 +10,7 @@ #include <drm_fourcc.h> #include <errno.h> #include <fcntl.h> +#include <inttypes.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -278,7 +279,7 @@ static int sdma_copy(struct amdgpu_priv *priv, int fd, uint32_t src_handle, uint ret = drmCommandWriteRead(fd, DRM_AMDGPU_CS, &cs, sizeof(cs)); if (ret) { - drv_log("SDMA copy command buffer submission failed %d\n", ret); + drv_loge("SDMA copy command buffer submission failed %d\n", ret); goto unmap_dst; } @@ -289,9 +290,9 @@ static int sdma_copy(struct amdgpu_priv *priv, int fd, uint32_t src_handle, uint ret = drmCommandWriteRead(fd, DRM_AMDGPU_WAIT_CS, &wait_cs, sizeof(wait_cs)); if (ret) { - drv_log("Could not wait for CS to finish\n"); + drv_loge("Could not wait for CS to finish\n"); } else if (wait_cs.out.status) { - drv_log("Infinite wait timed out, likely GPU hang.\n"); + drv_loge("Infinite wait timed out, likely GPU hang.\n"); ret = -ENODEV; } @@ -345,6 +346,18 @@ static bool is_modifier_scanout_capable(struct amdgpu_priv *priv, uint32_t forma return true; } +static void amdgpu_preload(bool load) +{ + static void *handle; + + if (load && !handle) + handle = dri_dlopen(DRI_PATH); + else if (!load && handle) { + dri_dlclose(handle); + handle = NULL; + } +} + static int amdgpu_init(struct driver *drv) { struct amdgpu_priv *priv; @@ -380,7 +393,7 @@ static int amdgpu_init(struct driver *drv) /* Continue on failure, as we can still succesfully map things without SDMA. */ if (sdma_init(priv, drv_get_fd(drv))) - drv_log("SDMA init failed\n"); + drv_loge("SDMA init failed\n"); metadata.tiling = TILE_TYPE_LINEAR; metadata.priority = 1; @@ -425,7 +438,8 @@ static int amdgpu_init(struct driver *drv) */ drv_modify_combination(drv, DRM_FORMAT_R8, &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_GPU_DATA_BUFFER | + BO_USE_SENSOR_DIRECT_DATA); /* * The following formats will be allocated by the DRI backend and may be potentially tiled. @@ -504,26 +518,44 @@ static int amdgpu_create_bo_linear(struct bo *bo, uint32_t width, uint32_t heigh uint64_t use_flags) { int ret; - size_t num_planes; + uint32_t stride_align = 1; uint32_t plane, stride; union drm_amdgpu_gem_create gem_create = { { 0 } }; struct amdgpu_priv *priv = bo->drv->priv; stride = drv_stride_from_format(format, width, 0); - num_planes = drv_num_planes_from_format(format); - /* - * 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 and Stoney for now (b/171013552, b/190484589). - * This only applies to the Android YUV (multiplane) format. - * */ - 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); + if (use_flags & BO_USE_HW_MASK) { + /* GFX9+ requires the stride to be aligned to 256 bytes */ + stride_align = 256; + stride = ALIGN(stride, stride_align); + + /* Android YV12 requires the UV stride to be half of the Y + * stride. Before GFX10, we can double the alignment for the + * Y stride, which makes sure the UV stride is still aligned + * to 256 bytes after halving. + * + * GFX10+ additionally requires the stride to be as small as + * possible. It is impossible to support the format in some + * cases. Instead, we force DRM_FORMAT_YVU420 and knowingly + * vioate Android YV12 stride requirement. This is done + * because + * + * - we would like to know what breaks, and + * - when used as a classic resource by virglrenderer, the + * requirement hopefully does not matter + */ + bool double_align = format == DRM_FORMAT_YVU420_ANDROID; + if (double_align && priv->dev_info.family >= AMDGPU_FAMILY_NV && + (use_flags & BO_USE_GPU_HW) && ((stride / stride_align) & 1)) { + drv_loge("allocating %dx%d YV12 bo (usage 0x%" PRIx64 ") with bad strides", + width, height, use_flags); + format = DRM_FORMAT_YVU420; + double_align = false; + } + if (double_align) + stride = ALIGN(stride, stride_align * 2); + } /* * Currently, allocator used by chrome aligns the height for Encoder/ @@ -535,7 +567,7 @@ static int amdgpu_create_bo_linear(struct bo *bo, uint32_t width, uint32_t heigh if (use_flags & (BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER)) height = ALIGN(height, CHROME_HEIGHT_ALIGN); - drv_bo_from_format(bo, stride, height, format); + drv_bo_from_format(bo, stride, stride_align, height, format); gem_create.in.bo_size = ALIGN(bo->meta.total_size, priv->dev_info.virtual_address_alignment); @@ -625,8 +657,8 @@ static int amdgpu_import_bo(struct bo *bo, struct drv_import_fd_data *data) dri_tiling = combo->metadata.tiling != TILE_TYPE_LINEAR; } - bo->meta.num_planes = dri_num_planes_from_modifier(bo->drv, data->format, - data->format_modifier); + 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); @@ -650,19 +682,19 @@ static int amdgpu_destroy_bo(struct bo *bo) return drv_gem_bo_destroy(bo); } -static void *amdgpu_map_bo(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags) +static void *amdgpu_map_bo(struct bo *bo, struct vma *vma, uint32_t map_flags) { void *addr = MAP_FAILED; int ret; union drm_amdgpu_gem_mmap gem_map = { { 0 } }; struct drm_amdgpu_gem_create_in bo_info = { 0 }; struct drm_amdgpu_gem_op gem_op = { 0 }; - uint32_t handle = bo->handles[plane].u32; + uint32_t handle = bo->handles[0].u32; struct amdgpu_linear_vma_priv *priv = NULL; struct amdgpu_priv *drv_priv; if (bo->priv) - return dri_bo_map(bo, vma, plane, map_flags); + return dri_bo_map(bo, vma, 0, map_flags); drv_priv = bo->drv->priv; gem_op.handle = handle; @@ -691,7 +723,7 @@ static void *amdgpu_map_bo(struct bo *bo, struct vma *vma, size_t plane, uint32_ ret = drmCommandWriteRead(bo->drv->fd, DRM_AMDGPU_GEM_CREATE, &gem_create, sizeof(gem_create)); if (ret < 0) { - drv_log("GEM create failed\n"); + drv_loge("GEM create failed\n"); free(priv); return MAP_FAILED; } @@ -702,7 +734,7 @@ static void *amdgpu_map_bo(struct bo *bo, struct vma *vma, size_t plane, uint32_ ret = sdma_copy(bo->drv->priv, bo->drv->fd, bo->handles[0].u32, priv->handle, bo_info.bo_size); if (ret) { - drv_log("SDMA copy for read failed\n"); + drv_loge("SDMA copy for read failed\n"); goto fail; } } @@ -710,7 +742,7 @@ static void *amdgpu_map_bo(struct bo *bo, struct vma *vma, size_t plane, uint32_ gem_map.in.handle = handle; ret = drmIoctl(bo->drv->fd, DRM_IOCTL_AMDGPU_GEM_MMAP, &gem_map); if (ret) { - drv_log("DRM_IOCTL_AMDGPU_GEM_MMAP failed\n"); + drv_loge("DRM_IOCTL_AMDGPU_GEM_MMAP failed\n"); goto fail; } @@ -775,18 +807,19 @@ static int amdgpu_bo_invalidate(struct bo *bo, struct mapping *mapping) sizeof(wait_idle)); if (ret < 0) { - drv_log("DRM_AMDGPU_GEM_WAIT_IDLE failed with %d\n", ret); + drv_loge("DRM_AMDGPU_GEM_WAIT_IDLE failed with %d\n", ret); return ret; } if (ret == 0 && wait_idle.out.status) - drv_log("DRM_AMDGPU_GEM_WAIT_IDLE BO is busy\n"); + drv_loge("DRM_AMDGPU_GEM_WAIT_IDLE BO is busy\n"); return 0; } const struct backend backend_amdgpu = { .name = "amdgpu", + .preload = amdgpu_preload, .init = amdgpu_init, .close = amdgpu_close, .bo_create = amdgpu_create_bo, diff --git a/cros_gralloc/Makefile b/cros_gralloc/Makefile index c95ad2c..b0d62d7 100644 --- a/cros_gralloc/Makefile +++ b/cros_gralloc/Makefile @@ -9,7 +9,7 @@ SRCS += $(wildcard ../*.c) SRCS += $(wildcard gralloc0/*.cc) -SOURCES = $(filter-out ../gbm%, $(SRCS)) +SOURCES = $(filter-out ../gbm% ../minigbm%, $(SRCS)) PKG_CONFIG ?= pkg-config VPATH = $(dir $(SOURCES)) diff --git a/cros_gralloc/aidl/Allocator.cpp b/cros_gralloc/aidl/Allocator.cpp index 0d81d5c..2ea5a0d 100644 --- a/cros_gralloc/aidl/Allocator.cpp +++ b/cros_gralloc/aidl/Allocator.cpp @@ -16,7 +16,7 @@ #include "cros_gralloc/gralloc4/CrosGralloc4Utils.h" using aidl::android::hardware::common::NativeHandle; -using BufferDescriptorInfo = +using BufferDescriptorInfoV4 = android::hardware::graphics::mapper::V4_0::IMapper::BufferDescriptorInfo; namespace aidl::android::hardware::graphics::allocator::impl { @@ -78,7 +78,7 @@ ndk::ScopedAStatus Allocator::allocate(const std::vector<uint8_t>& descriptor, i return ToBinderStatus(AllocationError::NO_RESOURCES); } - BufferDescriptorInfo description; + BufferDescriptorInfoV4 description; int ret = ::android::gralloc4::decodeBufferDescriptorInfo(descriptor, &description); if (ret) { @@ -109,7 +109,7 @@ ndk::ScopedAStatus Allocator::allocate(const std::vector<uint8_t>& descriptor, i return ndk::ScopedAStatus::ok(); } -ndk::ScopedAStatus Allocator::allocate(const BufferDescriptorInfo& descriptor, int32_t* outStride, +ndk::ScopedAStatus Allocator::allocate(const BufferDescriptorInfoV4& descriptor, int32_t* outStride, native_handle_t** outHandle) { if (!mDriver) { ALOGE("Failed to allocate. Driver is uninitialized.\n"); @@ -154,6 +154,85 @@ ndk::ScopedAStatus Allocator::allocate(const BufferDescriptorInfo& descriptor, i return ndk::ScopedAStatus::ok(); } +static BufferDescriptorInfoV4 convertAidlToIMapperV4Descriptor(const BufferDescriptorInfo& info) { + return BufferDescriptorInfoV4 { + .name{reinterpret_cast<const char*>(info.name.data())}, + .width = static_cast<uint32_t>(info.width), + .height = static_cast<uint32_t>(info.height), + .layerCount = static_cast<uint32_t>(info.layerCount), + .format = static_cast<::android::hardware::graphics::common::V1_2::PixelFormat>(info.format), + .usage = static_cast<uint64_t>(info.usage), + .reservedSize = 0, + }; +} + +ndk::ScopedAStatus Allocator::allocate2(const BufferDescriptorInfo& descriptor, int32_t count, + allocator::AllocationResult* outResult) { + if (!mDriver) { + ALOGE("Failed to allocate. Driver is uninitialized.\n"); + return ToBinderStatus(AllocationError::NO_RESOURCES); + } + + if (!descriptor.additionalOptions.empty()) { + return ToBinderStatus(AllocationError::UNSUPPORTED); + } + + BufferDescriptorInfoV4 descriptionV4 = convertAidlToIMapperV4Descriptor(descriptor); + + std::vector<native_handle_t*> handles; + handles.resize(count, nullptr); + + for (int32_t i = 0; i < count; i++) { + ndk::ScopedAStatus status = allocate(descriptionV4, &outResult->stride, &handles[i]); + if (!status.isOk()) { + for (int32_t j = 0; j < i; j++) { + releaseBufferAndHandle(handles[j]); + } + return status; + } + } + + outResult->buffers.resize(count); + for (int32_t i = 0; i < count; i++) { + auto handle = handles[i]; + outResult->buffers[i] = ::android::dupToAidl(handle); + releaseBufferAndHandle(handle); + } + + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Allocator::isSupported(const BufferDescriptorInfo& descriptor, + bool* outResult) { + if (!mDriver) { + ALOGE("Failed to allocate. Driver is uninitialized.\n"); + return ToBinderStatus(AllocationError::NO_RESOURCES); + } + + if (!descriptor.additionalOptions.empty()) { + *outResult = false; + return ndk::ScopedAStatus::ok(); + } + + struct cros_gralloc_buffer_descriptor crosDescriptor; + if (convertToCrosDescriptor(convertAidlToIMapperV4Descriptor(descriptor), &crosDescriptor)) { + // Failing to convert the descriptor means the layer count, pixel format, or usage is + // unsupported, thus isSupported() = false + *outResult = false; + return ndk::ScopedAStatus::ok(); + } + + crosDescriptor.reserved_region_size += sizeof(CrosGralloc4Metadata); + + *outResult = mDriver->is_supported(&crosDescriptor); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Allocator::getIMapperLibrarySuffix(std::string* outResult) { + *outResult = "minigbm"; + return ndk::ScopedAStatus::ok(); +} + ::ndk::SpAIBinder Allocator::createBinder() { auto binder = BnAllocator::createBinder(); AIBinder_setInheritRt(binder.get(), true); diff --git a/cros_gralloc/aidl/Allocator.h b/cros_gralloc/aidl/Allocator.h index 801c852..5c12308 100644 --- a/cros_gralloc/aidl/Allocator.h +++ b/cros_gralloc/aidl/Allocator.h @@ -26,6 +26,14 @@ class Allocator : public BnAllocator { ndk::ScopedAStatus allocate(const std::vector<uint8_t>& descriptor, int32_t count, allocator::AllocationResult* outResult) override; + ndk::ScopedAStatus allocate2(const BufferDescriptorInfo& descriptor, int32_t count, + allocator::AllocationResult* outResult) override; + + ndk::ScopedAStatus isSupported(const BufferDescriptorInfo& descriptor, + bool* outResult) override; + + ndk::ScopedAStatus getIMapperLibrarySuffix(std::string* outResult) override; + protected: ndk::SpAIBinder createBinder() override; diff --git a/cros_gralloc/aidl/Android.bp b/cros_gralloc/aidl/Android.bp index 71e2ae7..da8f670 100644 --- a/cros_gralloc/aidl/Android.bp +++ b/cros_gralloc/aidl/Android.bp @@ -24,14 +24,14 @@ package { } cc_binary { - name: "android.hardware.graphics.allocator-V1-service.minigbm", + name: "android.hardware.graphics.allocator-service.minigbm", defaults: ["minigbm_cros_gralloc_defaults"], relative_install_path: "hw", - init_rc: [":allocator_rc"], - vintf_fragments: [":allocator_xml"], + init_rc: ["allocator.rc"], + vintf_fragments: ["allocator.xml"], vendor: true, shared_libs: [ - "android.hardware.graphics.allocator-V1-ndk", + "android.hardware.graphics.allocator-V2-ndk", "android.hardware.graphics.mapper@4.0", "libbase", "libbinder_ndk", @@ -49,13 +49,3 @@ cc_binary { "Main.cpp", ], } - -filegroup { - name: "allocator_rc", - srcs: ["allocator.rc"], -} - -filegroup { - name: "allocator_xml", - srcs: ["allocator.xml"], -}
\ No newline at end of file diff --git a/cros_gralloc/aidl/allocator.rc b/cros_gralloc/aidl/allocator.rc index 5859384..24a7c45 100644 --- a/cros_gralloc/aidl/allocator.rc +++ b/cros_gralloc/aidl/allocator.rc @@ -1,4 +1,4 @@ -service vendor.graphics.allocator /vendor/bin/hw/android.hardware.graphics.allocator-V1-service.minigbm +service vendor.graphics.allocator /vendor/bin/hw/android.hardware.graphics.allocator-service.minigbm class hal animation user system group graphics drmrpc diff --git a/cros_gralloc/aidl/allocator.xml b/cros_gralloc/aidl/allocator.xml index 74fd4cd..4d375b3 100644 --- a/cros_gralloc/aidl/allocator.xml +++ b/cros_gralloc/aidl/allocator.xml @@ -1,7 +1,7 @@ <manifest version="1.0" type="device"> <hal format="aidl"> <name>android.hardware.graphics.allocator</name> - <version>1</version> + <version>2</version> <interface> <name>IAllocator</name> <instance>default</instance> diff --git a/cros_gralloc/cros_gralloc_buffer.cc b/cros_gralloc/cros_gralloc_buffer.cc index e1af7a4..0cac133 100644 --- a/cros_gralloc/cros_gralloc_buffer.cc +++ b/cros_gralloc/cros_gralloc_buffer.cc @@ -19,14 +19,14 @@ cros_gralloc_buffer::create(struct bo *acquire_bo, 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"); + ALOGE("Failed to create cros_gralloc_buffer: failed to clone handle."); 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"); + ALOGE("Failed to create cros_gralloc_buffer: failed to allocate."); native_handle_close(acquire_hnd); native_handle_delete(acquire_hnd); return {}; @@ -65,6 +65,11 @@ uint32_t cros_gralloc_buffer::get_width() const return hnd_->width; } +uint32_t cros_gralloc_buffer::get_pixel_stride() const +{ + return hnd_->pixel_stride; +} + uint32_t cros_gralloc_buffer::get_height() const { return hnd_->height; @@ -138,7 +143,7 @@ int32_t cros_gralloc_buffer::lock(const struct rectangle *rect, uint32_t map_fla * just use the first kernel buffer. */ if (drv_num_buffers_per_bo(bo_) != 1) { - drv_log("Can only support one buffer per bo.\n"); + ALOGE("Can only support one buffer per bo."); return -EINVAL; } @@ -162,7 +167,7 @@ int32_t cros_gralloc_buffer::lock(const struct rectangle *rect, uint32_t map_fla } if (vaddr == MAP_FAILED) { - drv_log("Mapping failed.\n"); + ALOGE("Mapping failed."); return -EFAULT; } } @@ -177,7 +182,7 @@ int32_t cros_gralloc_buffer::lock(const struct rectangle *rect, uint32_t map_fla int32_t cros_gralloc_buffer::unlock() { if (lockcount_ <= 0) { - drv_log("Buffer was not locked.\n"); + ALOGE("Buffer was not locked."); return -EINVAL; } @@ -201,7 +206,7 @@ int32_t cros_gralloc_buffer::resource_info(uint32_t strides[DRV_MAX_PLANES], int32_t cros_gralloc_buffer::invalidate() { if (lockcount_ <= 0) { - drv_log("Buffer was not locked.\n"); + ALOGE("Buffer was not locked."); return -EINVAL; } @@ -214,7 +219,7 @@ int32_t cros_gralloc_buffer::invalidate() int32_t cros_gralloc_buffer::flush() { if (lockcount_ <= 0) { - drv_log("Buffer was not locked.\n"); + ALOGE("Buffer was not locked."); return -EINVAL; } @@ -228,7 +233,7 @@ int32_t cros_gralloc_buffer::get_reserved_region(void **addr, uint64_t *size) co { int32_t reserved_region_fd = hnd_->fds[hnd_->num_planes]; if (reserved_region_fd < 0) { - drv_log("Buffer does not have reserved region.\n"); + ALOGE("Buffer does not have reserved region."); return -EINVAL; } @@ -237,7 +242,7 @@ int32_t cros_gralloc_buffer::get_reserved_region(void **addr, uint64_t *size) co 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)); + ALOGE("Failed to mmap reserved region: %s.", strerror(errno)); return -errno; } } diff --git a/cros_gralloc/cros_gralloc_buffer.h b/cros_gralloc/cros_gralloc_buffer.h index 21f8306..71947d9 100644 --- a/cros_gralloc/cros_gralloc_buffer.h +++ b/cros_gralloc/cros_gralloc_buffer.h @@ -21,6 +21,7 @@ class cros_gralloc_buffer uint32_t get_id() const; uint32_t get_width() const; + uint32_t get_pixel_stride() const; uint32_t get_height() const; uint32_t get_format() const; uint64_t get_format_modifier() const; diff --git a/cros_gralloc/cros_gralloc_driver.cc b/cros_gralloc/cros_gralloc_driver.cc index 46de30d..a714798 100644 --- a/cros_gralloc/cros_gralloc_driver.cc +++ b/cros_gralloc/cros_gralloc_driver.cc @@ -7,6 +7,7 @@ #include "cros_gralloc_driver.h" #include <cstdlib> +#include <cutils/properties.h> #include <fcntl.h> #include <hardware/gralloc.h> #include <sys/mman.h> @@ -25,6 +26,22 @@ // DRM Card nodes start at 0 #define DRM_CARD_NODE_START 0 +class cros_gralloc_driver_preloader +{ + public: + cros_gralloc_driver_preloader() + { + drv_preload(true); + } + + ~cros_gralloc_driver_preloader() + { + drv_preload(false); + } +}; + +static class cros_gralloc_driver_preloader cros_gralloc_driver_preloader; + int memfd_create_wrapper(const char *name, unsigned int flags) { int fd; @@ -34,12 +51,12 @@ int memfd_create_wrapper(const char *name, unsigned int flags) #elif defined(__NR_memfd_create) fd = syscall(__NR_memfd_create, name, flags); #else - drv_log("Failed to create memfd '%s': memfd_create not available.", name); + ALOGE("Failed to create memfd '%s': memfd_create not available.", name); return -1; #endif if (fd == -1) - drv_log("Failed to create memfd '%s': %s.\n", name, strerror(errno)); + ALOGE("Failed to create memfd '%s': %s.", name, strerror(errno)); return fd; } @@ -53,7 +70,7 @@ int memfd_create_reserved_region(const std::string &buffer_name, uint64_t reserv return -errno; if (ftruncate(reserved_region_fd, reserved_region_size)) { - drv_log("Failed to set reserved region size: %s.\n", strerror(errno)); + ALOGE("Failed to set reserved region size: %s.", strerror(errno)); return -errno; } @@ -65,7 +82,7 @@ cros_gralloc_driver *cros_gralloc_driver::get_instance() static cros_gralloc_driver s_instance; if (!s_instance.is_initialized()) { - drv_log("Failed to initialize driver.\n"); + ALOGE("Failed to initialize driver."); return nullptr; } @@ -138,6 +155,9 @@ static void drv_destroy_and_close(struct driver *drv) cros_gralloc_driver::cros_gralloc_driver() : drv_(init_try_nodes(), drv_destroy_and_close) { + char buf[PROP_VALUE_MAX]; + property_get("ro.product.device", buf, "unknown"); + mt8183_camera_quirk_ = !strncmp(buf, "kukui", strlen("kukui")); } cros_gralloc_driver::~cros_gralloc_driver() @@ -159,6 +179,14 @@ bool cros_gralloc_driver::get_resolved_format_and_use_flags( uint64_t resolved_use_flags; struct combination *combo; + if (mt8183_camera_quirk_ && (descriptor->use_flags & BO_USE_CAMERA_READ) && + !(descriptor->use_flags & BO_USE_SCANOUT) && + descriptor->drm_format == DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED) { + *out_use_flags = descriptor->use_flags; + *out_format = DRM_FORMAT_MTISP_SXYZW10; + return true; + } + drv_resolve_format_and_use_flags(drv_.get(), descriptor->drm_format, descriptor->use_flags, &resolved_format, &resolved_use_flags); @@ -172,7 +200,7 @@ bool cros_gralloc_driver::get_resolved_format_and_use_flags( 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)) { + if (!combo && (descriptor->droid_usage & BUFFER_USAGE_FRONT_RENDERING_MASK)) { resolved_use_flags &= ~BO_USE_FRONT_RENDERING; resolved_use_flags |= BO_USE_LINEAR; combo = drv_get_combination(drv_.get(), resolved_format, resolved_use_flags); @@ -215,7 +243,7 @@ int cros_gralloc_driver::create_reserved_region(const std::string &buffer_name, if (ret >= 0) return ret; - drv_log("Failed to create_reserved_region.\n"); + ALOGE("Failed to create_reserved_region."); return -1; } @@ -234,14 +262,14 @@ int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descripto std::unique_ptr<cros_gralloc_buffer> buffer; if (!get_resolved_format_and_use_flags(descriptor, &resolved_format, &resolved_use_flags)) { - drv_log("Failed to resolve format and use_flags.\n"); + ALOGE("Failed to resolve format and use_flags."); return -EINVAL; } bo = drv_bo_create(drv_.get(), descriptor->width, descriptor->height, resolved_format, resolved_use_flags); if (!bo) { - drv_log("Failed to create bo.\n"); + ALOGE("Failed to create bo."); return -errno; } @@ -251,7 +279,7 @@ int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descripto * send more than one fd. GL/Vulkan drivers may also have to modified. */ if (drv_num_buffers_per_bo(bo) != 1) { - drv_log("Can only support one buffer per bo.\n"); + ALOGE("Can only support one buffer per bo."); goto destroy_bo; } @@ -308,7 +336,7 @@ int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descripto buffer = cros_gralloc_buffer::create(bo, hnd); if (!buffer) { - drv_log("Failed to allocate: failed to create cros_gralloc_buffer.\n"); + ALOGE("Failed to allocate: failed to create cros_gralloc_buffer."); ret = -1; goto destroy_hnd; } @@ -342,7 +370,7 @@ int32_t cros_gralloc_driver::retain(buffer_handle_t handle) auto hnd = cros_gralloc_convert_handle(handle); if (!hnd) { - drv_log("Invalid handle.\n"); + ALOGE("Invalid handle."); return -EINVAL; } @@ -393,7 +421,7 @@ int32_t cros_gralloc_driver::retain(buffer_handle_t handle) auto scoped_buffer = cros_gralloc_buffer::create(bo, hnd); if (!scoped_buffer) { - drv_log("Failed to import: failed to create cros_gralloc_buffer.\n"); + ALOGE("Failed to import: failed to create cros_gralloc_buffer."); return -1; } buffer = scoped_buffer.get(); @@ -414,13 +442,13 @@ int32_t cros_gralloc_driver::release(buffer_handle_t handle) auto hnd = cros_gralloc_convert_handle(handle); if (!hnd) { - drv_log("Invalid handle.\n"); + ALOGE("Invalid handle."); return -EINVAL; } auto buffer = get_buffer(hnd); if (!buffer) { - drv_log("Invalid reference (release() called on unregistered handle).\n"); + ALOGE("Invalid reference (release() called on unregistered handle)."); return -EINVAL; } @@ -446,13 +474,13 @@ int32_t cros_gralloc_driver::lock(buffer_handle_t handle, int32_t acquire_fence, auto hnd = cros_gralloc_convert_handle(handle); if (!hnd) { - drv_log("Invalid handle.\n"); + ALOGE("Invalid handle."); return -EINVAL; } auto buffer = get_buffer(hnd); if (!buffer) { - drv_log("Invalid reference (lock() called on unregistered handle).\n"); + ALOGE("Invalid reference (lock() called on unregistered handle)."); return -EINVAL; } @@ -465,13 +493,13 @@ int32_t cros_gralloc_driver::unlock(buffer_handle_t handle, int32_t *release_fen auto hnd = cros_gralloc_convert_handle(handle); if (!hnd) { - drv_log("Invalid handle.\n"); + ALOGE("Invalid handle."); return -EINVAL; } auto buffer = get_buffer(hnd); if (!buffer) { - drv_log("Invalid reference (unlock() called on unregistered handle).\n"); + ALOGE("Invalid reference (unlock() called on unregistered handle)."); return -EINVAL; } @@ -491,42 +519,35 @@ int32_t cros_gralloc_driver::invalidate(buffer_handle_t handle) auto hnd = cros_gralloc_convert_handle(handle); if (!hnd) { - drv_log("Invalid handle.\n"); + ALOGE("Invalid handle."); return -EINVAL; } auto buffer = get_buffer(hnd); if (!buffer) { - drv_log("Invalid reference (invalidate() called on unregistered handle).\n"); + ALOGE("Invalid reference (invalidate() called on unregistered handle)."); return -EINVAL; } return buffer->invalidate(); } -int32_t cros_gralloc_driver::flush(buffer_handle_t handle, int32_t *release_fence) +int32_t cros_gralloc_driver::flush(buffer_handle_t handle) { std::lock_guard<std::mutex> lock(mutex_); auto hnd = cros_gralloc_convert_handle(handle); if (!hnd) { - drv_log("Invalid handle.\n"); + ALOGE("Invalid handle."); return -EINVAL; } auto buffer = get_buffer(hnd); if (!buffer) { - drv_log("Invalid reference (flush() called on unregistered handle).\n"); + ALOGE("Invalid reference (flush() called on unregistered handle)."); return -EINVAL; } - /* - * From the ANativeWindow::dequeueBuffer documentation: - * - * "A value of -1 indicates that the caller may access the buffer immediately without - * waiting on a fence." - */ - *release_fence = -1; return buffer->flush(); } @@ -536,13 +557,13 @@ int32_t cros_gralloc_driver::get_backing_store(buffer_handle_t handle, uint64_t auto hnd = cros_gralloc_convert_handle(handle); if (!hnd) { - drv_log("Invalid handle.\n"); + ALOGE("Invalid handle."); return -EINVAL; } auto buffer = get_buffer(hnd); if (!buffer) { - drv_log("Invalid reference (get_backing_store() called on unregistered handle).\n"); + ALOGE("Invalid reference (get_backing_store() called on unregistered handle)."); return -EINVAL; } @@ -558,13 +579,13 @@ int32_t cros_gralloc_driver::resource_info(buffer_handle_t handle, uint32_t stri auto hnd = cros_gralloc_convert_handle(handle); if (!hnd) { - drv_log("Invalid handle.\n"); + ALOGE("Invalid handle."); return -EINVAL; } auto buffer = get_buffer(hnd); if (!buffer) { - drv_log("Invalid reference (resource_info() called on unregistered handle).\n"); + ALOGE("Invalid reference (resource_info() called on unregistered handle)."); return -EINVAL; } @@ -579,14 +600,13 @@ int32_t cros_gralloc_driver::get_reserved_region(buffer_handle_t handle, auto hnd = cros_gralloc_convert_handle(handle); if (!hnd) { - drv_log("Invalid handle.\n"); + ALOGE("Invalid handle."); return -EINVAL; } auto buffer = get_buffer(hnd); if (!buffer) { - drv_log( - "Invalid reference (get_reserved_region() called on unregistered handle).\n"); + ALOGE("Invalid reference (get_reserved_region() called on unregistered handle)."); return -EINVAL; } @@ -620,7 +640,7 @@ void cros_gralloc_driver::with_buffer(cros_gralloc_handle_t hnd, auto buffer = get_buffer(hnd); if (!buffer) { - drv_log("Invalid reference (with_buffer() called on unregistered handle).\n"); + ALOGE("Invalid reference (with_buffer() called on unregistered handle)."); return; } diff --git a/cros_gralloc/cros_gralloc_driver.h b/cros_gralloc/cros_gralloc_driver.h index 5678b76..f35757c 100644 --- a/cros_gralloc/cros_gralloc_driver.h +++ b/cros_gralloc/cros_gralloc_driver.h @@ -36,7 +36,7 @@ class cros_gralloc_driver int32_t unlock(buffer_handle_t handle, int32_t *release_fence); int32_t invalidate(buffer_handle_t handle); - int32_t flush(buffer_handle_t handle, int32_t *release_fence); + int32_t flush(buffer_handle_t handle); int32_t get_backing_store(buffer_handle_t handle, uint64_t *out_store); int32_t resource_info(buffer_handle_t handle, uint32_t strides[DRV_MAX_PLANES], @@ -83,6 +83,7 @@ class cros_gralloc_driver std::mutex mutex_; 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_; + bool mt8183_camera_quirk_ = false; }; #endif diff --git a/cros_gralloc/cros_gralloc_helpers.cc b/cros_gralloc/cros_gralloc_helpers.cc index 3301522..8c86c66 100644 --- a/cros_gralloc/cros_gralloc_helpers.cc +++ b/cros_gralloc/cros_gralloc_helpers.cc @@ -12,9 +12,15 @@ /* 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) +/* Define to match AIDL PixelFormat::R_8. */ +#define HAL_PIXEL_FORMAT_R8 0x38 + uint32_t cros_gralloc_convert_format(int format) { /* @@ -50,6 +56,7 @@ uint32_t cros_gralloc_convert_format(int format) * equal to their size in bytes. */ case HAL_PIXEL_FORMAT_BLOB: + case HAL_PIXEL_FORMAT_R8: return DRM_FORMAT_R8; case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: return DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED; @@ -119,11 +126,13 @@ uint64_t cros_gralloc_convert_usage(uint64_t usage) 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); + handle_usage(&usage, BUFFER_USAGE_FRONT_RENDERING_MASK, &use_flags, BO_USE_FRONT_RENDERING); if (usage) { - drv_log("Unhandled gralloc usage: %llx\n", (unsigned long long)usage); + ALOGE("Unhandled gralloc usage: %llx", (unsigned long long)usage); return BO_USE_NONE; } @@ -162,10 +171,10 @@ int32_t cros_gralloc_sync_wait(int32_t fence, bool close_fence) */ int err = sync_wait(fence, 1000); if (err < 0) { - drv_log("Timed out on sync wait, err = %s\n", strerror(errno)); + ALOGE("Timed out on sync wait, err = %s", strerror(errno)); err = sync_wait(fence, -1); if (err < 0) { - drv_log("sync wait error = %s\n", strerror(errno)); + ALOGE("sync wait error = %s", strerror(errno)); return -errno; } } @@ -173,7 +182,7 @@ int32_t cros_gralloc_sync_wait(int32_t fence, bool close_fence) if (close_fence) { err = close(fence); if (err) { - drv_log("Unable to close fence fd, err = %s\n", strerror(errno)); + ALOGE("Unable to close fence fd, err = %s", strerror(errno)); return -errno; } } diff --git a/cros_gralloc/cros_gralloc_helpers.h b/cros_gralloc/cros_gralloc_helpers.h index 312d2f7..9fcb995 100644 --- a/cros_gralloc/cros_gralloc_helpers.h +++ b/cros_gralloc/cros_gralloc_helpers.h @@ -10,6 +10,7 @@ #include "../drv.h" #include "cros_gralloc_handle.h" +#include <log/log.h> #include <system/graphics.h> #include <system/window.h> @@ -20,6 +21,9 @@ // BO_USE_FRONT_RENDERING or BO_USE_LINEAR upon buffer allocaton. #define BUFFER_USAGE_FRONT_RENDERING (1U << 28) +// Adopt BufferUsage::FRONT_BUFFER from api level 33 +#define BUFFER_USAGE_FRONT_RENDERING_MASK (BUFFER_USAGE_FRONT_RENDERING | (1ULL << 32)) + struct cros_gralloc_buffer_descriptor { uint32_t width; uint32_t height; diff --git a/cros_gralloc/gralloc0/gralloc0.cc b/cros_gralloc/gralloc0/gralloc0.cc index ce62521..3412e85 100644 --- a/cros_gralloc/gralloc0/gralloc0.cc +++ b/cros_gralloc/gralloc0/gralloc0.cc @@ -84,10 +84,10 @@ static int gralloc0_alloc(alloc_device_t *dev, int w, int h, int format, int usa descriptor.reserved_region_size = 0; 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), - static_cast<unsigned long long>(descriptor.use_flags)); + ALOGE("Unsupported combination -- HAL format: %u, HAL usage: %u, " + "drv_format: %4.4s, use_flags: %llu", + format, usage, reinterpret_cast<char *>(&descriptor.drm_format), + static_cast<unsigned long long>(descriptor.use_flags)); return -EINVAL; } @@ -160,7 +160,7 @@ static int gralloc0_open(const struct hw_module_t *mod, const char *name, struct } if (strcmp(name, GRALLOC_HARDWARE_GPU0)) { - drv_log("Incorrect device name - %s.\n", name); + ALOGE("Incorrect device name - %s.", name); return -EINVAL; } @@ -247,7 +247,7 @@ static int gralloc0_perform(struct gralloc_module_t const *module, int op, ...) hnd = cros_gralloc_convert_handle(handle); if (!hnd) { va_end(args); - drv_log("Invalid handle.\n"); + ALOGE("Invalid handle."); return -EINVAL; } break; @@ -351,12 +351,12 @@ static int gralloc0_lock_async(struct gralloc_module_t const *module, buffer_han auto hnd = cros_gralloc_convert_handle(handle); if (!hnd) { - drv_log("Invalid handle.\n"); + ALOGE("Invalid handle."); return -EINVAL; } if (hnd->droid_format == HAL_PIXEL_FORMAT_YCbCr_420_888) { - drv_log("HAL_PIXEL_FORMAT_YCbCr_*_888 format not compatible.\n"); + ALOGE("HAL_PIXEL_FORMAT_YCbCr_*_888 format not compatible."); return -EINVAL; } @@ -402,13 +402,13 @@ static int gralloc0_lock_async_ycbcr(struct gralloc_module_t const *module, buff auto hnd = cros_gralloc_convert_handle(handle); if (!hnd) { - drv_log("Invalid handle.\n"); + ALOGE("Invalid handle."); return -EINVAL; } if (!gralloc0_droid_yuv_format(hnd->droid_format) && hnd->droid_format != HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED) { - drv_log("Non-YUV format not compatible.\n"); + ALOGE("Non-YUV format not compatible."); return -EINVAL; } diff --git a/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc b/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc index 43c0b0c..3166793 100644 --- a/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc +++ b/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc @@ -35,12 +35,12 @@ 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"); + ALOGE("Failed to initializeMetadata. Driver is uninitialized."); return Error::NO_RESOURCES; } if (!crosHandle) { - drv_log("Failed to initializeMetadata. Invalid handle.\n"); + ALOGE("Failed to initializeMetadata. Invalid handle."); return Error::BAD_BUFFER; } @@ -48,7 +48,7 @@ Error CrosGralloc4Allocator::initializeMetadata( uint64_t size; int ret = mDriver->get_reserved_region(crosHandle, &addr, &size); if (ret) { - drv_log("Failed to getReservedRegion.\n"); + ALOGE("Failed to getReservedRegion."); return Error::NO_RESOURCES; } @@ -65,7 +65,7 @@ Error CrosGralloc4Allocator::initializeMetadata( Error CrosGralloc4Allocator::allocate(const BufferDescriptorInfo& descriptor, uint32_t* outStride, hidl_handle* outHandle) { if (!mDriver) { - drv_log("Failed to allocate. Driver is uninitialized.\n"); + ALOGE("Failed to allocate. Driver is uninitialized."); return Error::NO_RESOURCES; } @@ -84,8 +84,8 @@ Error CrosGralloc4Allocator::allocate(const BufferDescriptorInfo& descriptor, ui 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()); + ALOGE("Unsupported combination -- pixel format: %s, drm format:%s, usage: %s", + pixelFormatString.c_str(), drmFormatString.c_str(), usageString.c_str()); return Error::UNSUPPORTED; } @@ -116,7 +116,7 @@ Return<void> CrosGralloc4Allocator::allocate(const hidl_vec<uint8_t>& descriptor hidl_vec<hidl_handle> handles; if (!mDriver) { - drv_log("Failed to allocate. Driver is uninitialized.\n"); + ALOGE("Failed to allocate. Driver is uninitialized."); hidlCb(Error::NO_RESOURCES, 0, handles); return Void(); } @@ -125,7 +125,7 @@ Return<void> CrosGralloc4Allocator::allocate(const hidl_vec<uint8_t>& descriptor int ret = android::gralloc4::decodeBufferDescriptorInfo(descriptor, &description); if (ret) { - drv_log("Failed to allocate. Failed to decode buffer descriptor: %d.\n", ret); + ALOGE("Failed to allocate. Failed to decode buffer descriptor: %d.", ret); hidlCb(Error::BAD_DESCRIPTOR, 0, handles); return Void(); } diff --git a/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc b/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc index cc2c4d5..a8a4f52 100644 --- a/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc +++ b/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc @@ -34,26 +34,26 @@ Return<void> CrosGralloc4Mapper::createDescriptor(const BufferDescriptorInfo& de hidl_vec<uint8_t> descriptor; if (description.width == 0) { - drv_log("Failed to createDescriptor. Bad width: %d.\n", description.width); + ALOGE("Failed to createDescriptor. Bad width: %d.", description.width); hidlCb(Error::BAD_VALUE, descriptor); return Void(); } if (description.height == 0) { - drv_log("Failed to createDescriptor. Bad height: %d.\n", description.height); + ALOGE("Failed to createDescriptor. Bad height: %d.", 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); + ALOGE("Failed to createDescriptor. Bad layer count: %d.", description.layerCount); hidlCb(Error::BAD_VALUE, descriptor); return Void(); } int ret = android::gralloc4::encodeBufferDescriptorInfo(description, &descriptor); if (ret) { - drv_log("Failed to createDescriptor. Failed to encode: %d.\n", ret); + ALOGE("Failed to createDescriptor. Failed to encode: %d.", ret); hidlCb(Error::BAD_VALUE, descriptor); return Void(); } @@ -64,21 +64,21 @@ Return<void> CrosGralloc4Mapper::createDescriptor(const BufferDescriptorInfo& de Return<void> CrosGralloc4Mapper::importBuffer(const hidl_handle& handle, importBuffer_cb hidlCb) { if (!mDriver) { - drv_log("Failed to import buffer. Driver is uninitialized.\n"); + ALOGE("Failed to import buffer. Driver is uninitialized."); 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"); + ALOGE("Failed to importBuffer. Bad handle."); 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: %s.\n", strerror(errno)); + ALOGE("Failed to importBuffer. Handle clone failed: %s.", strerror(errno)); hidlCb(Error::NO_RESOURCES, nullptr); return Void(); } @@ -97,13 +97,13 @@ Return<void> CrosGralloc4Mapper::importBuffer(const hidl_handle& handle, importB Return<Error> CrosGralloc4Mapper::freeBuffer(void* rawHandle) { if (!mDriver) { - drv_log("Failed to freeBuffer. Driver is uninitialized.\n"); + ALOGE("Failed to freeBuffer. Driver is uninitialized."); return Error::NO_RESOURCES; } native_handle_t* bufferHandle = reinterpret_cast<native_handle_t*>(rawHandle); if (!bufferHandle) { - drv_log("Failed to freeBuffer. Empty handle.\n"); + ALOGE("Failed to freeBuffer. Empty handle."); return Error::BAD_BUFFER; } @@ -121,43 +121,49 @@ Return<Error> CrosGralloc4Mapper::validateBufferSize(void* rawHandle, const BufferDescriptorInfo& descriptor, uint32_t stride) { if (!mDriver) { - drv_log("Failed to validateBufferSize. Driver is uninitialized.\n"); + ALOGE("Failed to validateBufferSize. Driver is uninitialized."); return Error::NO_RESOURCES; } native_handle_t* bufferHandle = reinterpret_cast<native_handle_t*>(rawHandle); if (!bufferHandle) { - drv_log("Failed to validateBufferSize. Empty handle.\n"); + ALOGE("Failed to validateBufferSize. Empty handle."); return Error::BAD_BUFFER; } cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle); if (!crosHandle) { - drv_log("Failed to validateBufferSize. Invalid handle.\n"); + ALOGE("Failed to validateBufferSize. Invalid handle."); return Error::BAD_BUFFER; } PixelFormat crosHandleFormat = static_cast<PixelFormat>(crosHandle->droid_format); if (descriptor.format != crosHandleFormat) { - drv_log("Failed to validateBufferSize. Format mismatch.\n"); + ALOGE("Failed to validateBufferSize. Format mismatch."); return Error::BAD_BUFFER; } if (descriptor.width != crosHandle->width) { - drv_log("Failed to validateBufferSize. Width mismatch (%d vs %d).\n", descriptor.width, - crosHandle->width); + ALOGE("Failed to validateBufferSize. Width mismatch (%d vs %d).", 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); + ALOGE("Failed to validateBufferSize. Height mismatch (%d vs %d).", 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); + if (crosHandle->droid_format == HAL_PIXEL_FORMAT_BLOB) { + if (stride > crosHandle->pixel_stride) { + ALOGE("Failed to validateBufferSize. Oversized stride (%d vs %d).", stride, + crosHandle->pixel_stride); + return Error::BAD_VALUE; + } + } else if (stride != crosHandle->pixel_stride) { + ALOGE("Failed to validateBufferSize. Stride mismatch (%d vs %d).", stride, + crosHandle->pixel_stride); return Error::BAD_VALUE; } @@ -166,14 +172,14 @@ Return<Error> CrosGralloc4Mapper::validateBufferSize(void* rawHandle, Return<void> CrosGralloc4Mapper::getTransportSize(void* rawHandle, getTransportSize_cb hidlCb) { if (!mDriver) { - drv_log("Failed to getTransportSize. Driver is uninitialized.\n"); + ALOGE("Failed to getTransportSize. Driver is uninitialized."); 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"); + ALOGE("Failed to getTransportSize. Bad handle."); hidlCb(Error::BAD_BUFFER, 0, 0); return Void(); } @@ -186,20 +192,20 @@ Return<void> CrosGralloc4Mapper::getTransportSize(void* rawHandle, getTransportS Return<void> CrosGralloc4Mapper::lock(void* rawBuffer, uint64_t cpuUsage, const Rect& region, const hidl_handle& acquireFence, lock_cb hidlCb) { if (!mDriver) { - drv_log("Failed to lock. Driver is uninitialized.\n"); + ALOGE("Failed to lock. Driver is uninitialized."); hidlCb(Error::NO_RESOURCES, nullptr); return Void(); } buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawBuffer); if (!bufferHandle) { - drv_log("Failed to lock. Empty handle.\n"); + ALOGE("Failed to lock. Empty handle."); hidlCb(Error::BAD_BUFFER, nullptr); return Void(); } if (cpuUsage == 0) { - drv_log("Failed to lock. Bad cpu usage: %" PRIu64 ".\n", cpuUsage); + ALOGE("Failed to lock. Bad cpu usage: %" PRIu64 ".", cpuUsage); hidlCb(Error::BAD_VALUE, nullptr); return Void(); } @@ -207,52 +213,52 @@ Return<void> CrosGralloc4Mapper::lock(void* rawBuffer, uint64_t cpuUsage, const uint32_t mapUsage = 0; int ret = convertToMapUsage(cpuUsage, &mapUsage); if (ret) { - drv_log("Failed to lock. Convert usage failed.\n"); + ALOGE("Failed to lock. Convert usage failed."); hidlCb(Error::BAD_VALUE, nullptr); return Void(); } cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle); if (crosHandle == nullptr) { - drv_log("Failed to lock. Invalid handle.\n"); + ALOGE("Failed to lock. Invalid handle."); hidlCb(Error::BAD_VALUE, nullptr); return Void(); } if (region.left < 0) { - drv_log("Failed to lock. Invalid region: negative left value %d.\n", region.left); + ALOGE("Failed to lock. Invalid region: negative left value %d.", region.left); hidlCb(Error::BAD_VALUE, nullptr); return Void(); } if (region.top < 0) { - drv_log("Failed to lock. Invalid region: negative top value %d.\n", region.top); + ALOGE("Failed to lock. Invalid region: negative top value %d.", region.top); hidlCb(Error::BAD_VALUE, nullptr); return Void(); } if (region.width < 0) { - drv_log("Failed to lock. Invalid region: negative width value %d.\n", region.width); + ALOGE("Failed to lock. Invalid region: negative width value %d.", region.width); hidlCb(Error::BAD_VALUE, nullptr); return Void(); } if (region.height < 0) { - drv_log("Failed to lock. Invalid region: negative height value %d.\n", region.height); + ALOGE("Failed to lock. Invalid region: negative height value %d.", region.height); hidlCb(Error::BAD_VALUE, nullptr); return Void(); } 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); + ALOGE("Failed to lock. Invalid region: width greater than buffer width (%d vs %d).", + region.width, crosHandle->width); hidlCb(Error::BAD_VALUE, nullptr); return Void(); } 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); + ALOGE("Failed to lock. Invalid region: height greater than buffer height (%d vs %d).", + region.height, crosHandle->height); hidlCb(Error::BAD_VALUE, nullptr); return Void(); } @@ -270,7 +276,7 @@ Return<void> CrosGralloc4Mapper::lock(void* rawBuffer, uint64_t cpuUsage, const int acquireFenceFd = -1; ret = convertToFenceFd(acquireFence, &acquireFenceFd); if (ret) { - drv_log("Failed to lock. Bad acquire fence.\n"); + ALOGE("Failed to lock. Bad acquire fence."); hidlCb(Error::BAD_VALUE, nullptr); return Void(); } @@ -289,14 +295,14 @@ Return<void> CrosGralloc4Mapper::lock(void* rawBuffer, uint64_t cpuUsage, const Return<void> CrosGralloc4Mapper::unlock(void* rawHandle, unlock_cb hidlCb) { if (!mDriver) { - drv_log("Failed to unlock. Driver is uninitialized.\n"); + ALOGE("Failed to unlock. Driver is uninitialized."); 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"); + ALOGE("Failed to unlock. Empty handle."); hidlCb(Error::BAD_BUFFER, nullptr); return Void(); } @@ -304,7 +310,7 @@ Return<void> CrosGralloc4Mapper::unlock(void* rawHandle, unlock_cb hidlCb) { int releaseFenceFd = -1; int ret = mDriver->unlock(bufferHandle, &releaseFenceFd); if (ret) { - drv_log("Failed to unlock.\n"); + ALOGE("Failed to unlock."); hidlCb(Error::BAD_BUFFER, nullptr); return Void(); } @@ -312,7 +318,7 @@ Return<void> CrosGralloc4Mapper::unlock(void* rawHandle, unlock_cb hidlCb) { hidl_handle releaseFenceHandle; ret = convertToFenceHandle(releaseFenceFd, &releaseFenceHandle); if (ret) { - drv_log("Failed to unlock. Failed to convert release fence to handle.\n"); + ALOGE("Failed to unlock. Failed to convert release fence to handle."); hidlCb(Error::BAD_BUFFER, nullptr); return Void(); } @@ -323,22 +329,28 @@ Return<void> CrosGralloc4Mapper::unlock(void* rawHandle, unlock_cb hidlCb) { Return<void> CrosGralloc4Mapper::flushLockedBuffer(void* rawHandle, flushLockedBuffer_cb hidlCb) { if (!mDriver) { - drv_log("Failed to flushLockedBuffer. Driver is uninitialized.\n"); + ALOGE("Failed to flushLockedBuffer. Driver is uninitialized."); hidlCb(Error::NO_RESOURCES, nullptr); return Void(); } buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle); if (!bufferHandle) { - drv_log("Failed to flushLockedBuffer. Empty handle.\n"); + ALOGE("Failed to flushLockedBuffer. Empty handle."); hidlCb(Error::BAD_BUFFER, nullptr); return Void(); } + /* + * From the ANativeWindow::dequeueBuffer documentation: + * + * "A value of -1 indicates that the caller may access the buffer immediately without + * waiting on a fence." + */ int releaseFenceFd = -1; - int ret = mDriver->flush(bufferHandle, &releaseFenceFd); + int ret = mDriver->flush(bufferHandle); if (ret) { - drv_log("Failed to flushLockedBuffer. Flush failed.\n"); + ALOGE("Failed to flushLockedBuffer. Flush failed."); hidlCb(Error::BAD_BUFFER, nullptr); return Void(); } @@ -346,7 +358,7 @@ Return<void> CrosGralloc4Mapper::flushLockedBuffer(void* rawHandle, flushLockedB hidl_handle releaseFenceHandle; ret = convertToFenceHandle(releaseFenceFd, &releaseFenceHandle); if (ret) { - drv_log("Failed to flushLockedBuffer. Failed to convert release fence to handle.\n"); + ALOGE("Failed to flushLockedBuffer. Failed to convert release fence to handle."); hidlCb(Error::BAD_BUFFER, nullptr); return Void(); } @@ -357,19 +369,19 @@ Return<void> CrosGralloc4Mapper::flushLockedBuffer(void* rawHandle, flushLockedB Return<Error> CrosGralloc4Mapper::rereadLockedBuffer(void* rawHandle) { if (!mDriver) { - drv_log("Failed to rereadLockedBuffer. Driver is uninitialized.\n"); + ALOGE("Failed to rereadLockedBuffer. Driver is uninitialized."); return Error::NO_RESOURCES; } buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle); if (!bufferHandle) { - drv_log("Failed to rereadLockedBuffer. Empty handle.\n"); + ALOGE("Failed to rereadLockedBuffer. Empty handle."); return Error::BAD_BUFFER; } int ret = mDriver->invalidate(bufferHandle); if (ret) { - drv_log("Failed to rereadLockedBuffer. Failed to invalidate.\n"); + ALOGE("Failed to rereadLockedBuffer. Failed to invalidate."); return Error::BAD_BUFFER; } @@ -379,7 +391,7 @@ Return<Error> CrosGralloc4Mapper::rereadLockedBuffer(void* rawHandle) { Return<void> CrosGralloc4Mapper::isSupported(const BufferDescriptorInfo& descriptor, isSupported_cb hidlCb) { if (!mDriver) { - drv_log("Failed to isSupported. Driver is uninitialized.\n"); + ALOGE("Failed to isSupported. Driver is uninitialized."); hidlCb(Error::BAD_VALUE, false); return Void(); } @@ -399,21 +411,21 @@ Return<void> CrosGralloc4Mapper::get(void* rawHandle, const MetadataType& metada hidl_vec<uint8_t> encodedMetadata; if (!mDriver) { - drv_log("Failed to get. Driver is uninitialized.\n"); + ALOGE("Failed to get. Driver is uninitialized."); hidlCb(Error::NO_RESOURCES, encodedMetadata); return Void(); } buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle); if (!bufferHandle) { - drv_log("Failed to get. Empty handle.\n"); + ALOGE("Failed to get. Empty handle."); hidlCb(Error::BAD_BUFFER, encodedMetadata); return Void(); } cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle); if (!crosHandle) { - drv_log("Failed to get. Invalid handle.\n"); + ALOGE("Failed to get. Invalid handle."); hidlCb(Error::BAD_BUFFER, encodedMetadata); return Void(); } @@ -429,13 +441,13 @@ Return<void> CrosGralloc4Mapper::get(const cros_gralloc_buffer* crosBuffer, hidl_vec<uint8_t> encodedMetadata; if (!mDriver) { - drv_log("Failed to get. Driver is uninitialized.\n"); + ALOGE("Failed to get. Driver is uninitialized."); hidlCb(Error::NO_RESOURCES, encodedMetadata); return Void(); } if (!crosBuffer) { - drv_log("Failed to get. Invalid buffer.\n"); + ALOGE("Failed to get. Invalid buffer."); hidlCb(Error::BAD_BUFFER, encodedMetadata); return Void(); } @@ -448,7 +460,7 @@ Return<void> CrosGralloc4Mapper::get(const cros_gralloc_buffer* crosBuffer, 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"); + ALOGE("Failed to get. Failed to get buffer metadata."); hidlCb(Error::NO_RESOURCES, encodedMetadata); return Void(); } @@ -540,7 +552,7 @@ Return<void> CrosGralloc4Mapper::get(const cros_gralloc_buffer* crosBuffer, if (status != android::NO_ERROR) { hidlCb(Error::NO_RESOURCES, encodedMetadata); - drv_log("Failed to get. Failed to encode metadata.\n"); + ALOGE("Failed to get. Failed to encode metadata."); return Void(); } @@ -551,19 +563,19 @@ Return<void> CrosGralloc4Mapper::get(const cros_gralloc_buffer* crosBuffer, Return<Error> CrosGralloc4Mapper::set(void* rawHandle, const MetadataType& metadataType, const hidl_vec<uint8_t>& encodedMetadata) { if (!mDriver) { - drv_log("Failed to set. Driver is uninitialized.\n"); + ALOGE("Failed to set. Driver is uninitialized."); return Error::NO_RESOURCES; } buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle); if (!bufferHandle) { - drv_log("Failed to set. Empty handle.\n"); + ALOGE("Failed to set. Empty handle."); return Error::BAD_BUFFER; } cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle); if (!crosHandle) { - drv_log("Failed to set. Invalid handle.\n"); + ALOGE("Failed to set. Invalid handle."); return Error::BAD_BUFFER; } @@ -601,12 +613,12 @@ Return<Error> CrosGralloc4Mapper::set(void* rawHandle, const MetadataType& metad 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"); + ALOGE("Failed to set. Driver is uninitialized."); return Error::NO_RESOURCES; } if (!crosBuffer) { - drv_log("Failed to set. Invalid buffer.\n"); + ALOGE("Failed to set. Invalid buffer."); return Error::BAD_BUFFER; } @@ -614,32 +626,32 @@ Error CrosGralloc4Mapper::set(cros_gralloc_buffer* crosBuffer, const MetadataTyp Error error = getMutableMetadata(crosBuffer, &crosMetadata); if (error != Error::NONE) { - drv_log("Failed to set. Failed to get buffer metadata.\n"); + ALOGE("Failed to set. Failed to get buffer metadata."); 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"); + ALOGE("Failed to set. Failed to decode blend mode."); 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"); + ALOGE("Failed to set. Failed to decode cta861_3."); 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"); + ALOGE("Failed to set. Failed to decode dataspace."); 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"); + ALOGE("Failed to set. Failed to decode smpte2086."); return Error::UNSUPPORTED; } } @@ -652,24 +664,23 @@ int CrosGralloc4Mapper::getResolvedDrmFormat(PixelFormat pixelFormat, uint64_t b 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()); + ALOGE("Failed to getResolvedDrmFormat. Failed to convert format %s", + 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()); + ALOGE("Failed to getResolvedDrmFormat. Failed to convert usage %s", 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()); + ALOGE("Failed to getResolvedDrmFormat. Failed to resolve drm format %s", + drmFormatString.c_str()); return -EINVAL; } @@ -684,7 +695,7 @@ Return<void> CrosGralloc4Mapper::getFromBufferDescriptorInfo( hidl_vec<uint8_t> encodedMetadata; if (!mDriver) { - drv_log("Failed to getFromBufferDescriptorInfo. Driver is uninitialized.\n"); + ALOGE("Failed to getFromBufferDescriptorInfo. Driver is uninitialized."); hidlCb(Error::NO_RESOURCES, encodedMetadata); return Void(); } @@ -769,7 +780,7 @@ Return<void> CrosGralloc4Mapper::listSupportedMetadataTypes(listSupportedMetadat hidl_vec<MetadataTypeDescription> supported; if (!mDriver) { - drv_log("Failed to listSupportedMetadataTypes. Driver is uninitialized.\n"); + ALOGE("Failed to listSupportedMetadataTypes. Driver is uninitialized."); hidlCb(Error::NO_RESOURCES, supported); return Void(); } @@ -866,6 +877,12 @@ Return<void> CrosGralloc4Mapper::listSupportedMetadataTypes(listSupportedMetadat /*isSettable=*/false, }, { + android::gralloc4::MetadataType_Crop, + "", + /*isGettable=*/true, + /*isSettable=*/false, + }, + { android::gralloc4::MetadataType_Dataspace, "", /*isGettable=*/true, @@ -905,21 +922,21 @@ Return<void> CrosGralloc4Mapper::dumpBuffer(void* rawHandle, dumpBuffer_cb hidlC BufferDump bufferDump; if (!mDriver) { - drv_log("Failed to dumpBuffer. Driver is uninitialized.\n"); + ALOGE("Failed to dumpBuffer. Driver is uninitialized."); hidlCb(Error::NO_RESOURCES, bufferDump); return Void(); } buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle); if (!bufferHandle) { - drv_log("Failed to dumpBuffer. Empty handle.\n"); + ALOGE("Failed to dumpBuffer. Empty handle."); hidlCb(Error::BAD_BUFFER, bufferDump); return Void(); } cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle); if (!crosHandle) { - drv_log("Failed to dumpBuffer. Invalid handle.\n"); + ALOGE("Failed to dumpBuffer. Invalid handle."); hidlCb(Error::BAD_BUFFER, bufferDump); return Void(); } @@ -935,7 +952,7 @@ Return<void> CrosGralloc4Mapper::dumpBuffer(const cros_gralloc_buffer* crosBuffe BufferDump bufferDump; if (!mDriver) { - drv_log("Failed to dumpBuffer. Driver is uninitialized.\n"); + ALOGE("Failed to dumpBuffer. Driver is uninitialized."); hidlCb(Error::NO_RESOURCES, bufferDump); return Void(); } @@ -1010,7 +1027,7 @@ Return<void> CrosGralloc4Mapper::dumpBuffers(dumpBuffers_cb hidlCb) { std::vector<BufferDump> bufferDumps; if (!mDriver) { - drv_log("Failed to dumpBuffers. Driver is uninitialized.\n"); + ALOGE("Failed to dumpBuffers. Driver is uninitialized."); hidlCb(Error::NO_RESOURCES, bufferDumps); return Void(); } @@ -1035,18 +1052,18 @@ Error CrosGralloc4Mapper::getReservedRegionArea(const cros_gralloc_buffer* crosB ReservedRegionArea area, void** outAddr, uint64_t* outSize) { if (!mDriver) { - drv_log("Failed to getReservedRegionArea. Driver is uninitialized.\n"); + ALOGE("Failed to getReservedRegionArea. Driver is uninitialized."); return Error::NO_RESOURCES; } if (!crosBuffer) { - drv_log("Failed to getReservedRegionArea. Invalid buffer.\n"); + ALOGE("Failed to getReservedRegionArea. Invalid buffer."); return Error::BAD_BUFFER; } int ret = crosBuffer->get_reserved_region(outAddr, outSize); if (ret) { - drv_log("Failed to getReservedRegionArea.\n"); + ALOGE("Failed to getReservedRegionArea."); *outAddr = nullptr; *outSize = 0; return Error::NO_RESOURCES; @@ -1102,21 +1119,21 @@ Error CrosGralloc4Mapper::getMutableMetadata(cros_gralloc_buffer* crosBuffer, Return<void> CrosGralloc4Mapper::getReservedRegion(void* rawHandle, getReservedRegion_cb hidlCb) { if (!mDriver) { - drv_log("Failed to getReservedRegion. Driver is uninitialized.\n"); + ALOGE("Failed to getReservedRegion. Driver is uninitialized."); hidlCb(Error::NO_RESOURCES, nullptr, 0); return Void(); } buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle); if (!bufferHandle) { - drv_log("Failed to getReservedRegion. Empty handle.\n"); + ALOGE("Failed to getReservedRegion. Empty handle."); hidlCb(Error::BAD_BUFFER, nullptr, 0); return Void(); } cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle); if (!crosHandle) { - drv_log("Failed to getReservedRegion. Invalid handle.\n"); + ALOGE("Failed to getReservedRegion. Invalid handle."); hidlCb(Error::BAD_BUFFER, nullptr, 0); return Void(); } @@ -1131,7 +1148,7 @@ Return<void> CrosGralloc4Mapper::getReservedRegion(void* rawHandle, getReservedR }); if (error != Error::NONE) { - drv_log("Failed to getReservedRegion. Failed to getReservedRegionArea.\n"); + ALOGE("Failed to getReservedRegion. Failed to getReservedRegionArea."); hidlCb(Error::BAD_BUFFER, nullptr, 0); return Void(); } diff --git a/cros_gralloc/gralloc4/CrosGralloc4Utils.cc b/cros_gralloc/gralloc4/CrosGralloc4Utils.cc index 6c07189..515269a 100644 --- a/cros_gralloc/gralloc4/CrosGralloc4Utils.cc +++ b/cros_gralloc/gralloc4/CrosGralloc4Utils.cc @@ -64,18 +64,17 @@ int convertToCrosDescriptor(const BufferDescriptorInfo& descriptor, outCrosDescriptor->droid_usage = descriptor.usage; outCrosDescriptor->reserved_region_size = descriptor.reservedSize; if (descriptor.layerCount > 1) { - drv_log("Failed to convert descriptor. Unsupported layerCount: %d\n", - descriptor.layerCount); + ALOGE("Failed to convert descriptor. Unsupported layerCount: %d", 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()); + ALOGE("Failed to convert descriptor. Unsupported format %s", 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()); + ALOGE("Failed to convert descriptor. Unsupported usage flags %s", usageString.c_str()); return -EINVAL; } return 0; @@ -342,7 +341,7 @@ const std::unordered_map<uint32_t, std::vector<PlaneLayout>>& GetPlaneLayoutsMap }, { .components = {{.type = android::gralloc4:: - PlaneLayoutComponentType_CB, + PlaneLayoutComponentType_CR, .offsetInBits = 0, .sizeInBits = 8}}, .sampleIncrementInBits = 8, @@ -351,7 +350,7 @@ const std::unordered_map<uint32_t, std::vector<PlaneLayout>>& GetPlaneLayoutsMap }, { .components = {{.type = android::gralloc4:: - PlaneLayoutComponentType_CR, + PlaneLayoutComponentType_CB, .offsetInBits = 0, .sizeInBits = 8}}, .sampleIncrementInBits = 8, @@ -398,7 +397,7 @@ int getPlaneLayouts(uint32_t drmFormat, std::vector<PlaneLayout>* outPlaneLayout const auto& planeLayoutsMap = GetPlaneLayoutsMap(); const auto it = planeLayoutsMap.find(drmFormat); if (it == planeLayoutsMap.end()) { - drv_log("Unknown plane layout for format %d\n", drmFormat); + ALOGE("Unknown plane layout for format %d", drmFormat); return -EINVAL; } diff --git a/cros_gralloc/mapper_stablec/.clang-format b/cros_gralloc/mapper_stablec/.clang-format new file mode 100644 index 0000000..e5e7076 --- /dev/null +++ b/cros_gralloc/mapper_stablec/.clang-format @@ -0,0 +1,19 @@ +# 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. +# +# 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/mapper_stablec/Android.bp b/cros_gralloc/mapper_stablec/Android.bp new file mode 100644 index 0000000..b25be17 --- /dev/null +++ b/cros_gralloc/mapper_stablec/Android.bp @@ -0,0 +1,44 @@ +// +// Copyright (C) 2022 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-Apache-2.0 + // SPDX-license-identifier-BSD + default_applicable_licenses: ["external_minigbm_license"], +} + +cc_library_shared { + name: "mapper.minigbm", + defaults: ["minigbm_gralloc4_common_defaults"], + vintf_fragments: ["mapper.minigbm.xml"], + shared_libs: [ + "android.hardware.graphics.allocator-V2-ndk", + "libminigbm_gralloc", + ], + header_libs: [ + "libbase_headers", + "libimapper_stablec", + "libimapper_providerutils", + ], + srcs: [ + ":minigbm_gralloc4_mapper_files", + "Mapper.cpp", + ], + cpp_std: "c++20", +} diff --git a/cros_gralloc/mapper_stablec/Mapper.cpp b/cros_gralloc/mapper_stablec/Mapper.cpp new file mode 100644 index 0000000..6c4ac86 --- /dev/null +++ b/cros_gralloc/mapper_stablec/Mapper.cpp @@ -0,0 +1,745 @@ +/* + * 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. + */ + +#include <aidl/android/hardware/graphics/allocator/BufferDescriptorInfo.h> +#include <aidl/android/hardware/graphics/common/BufferUsage.h> +#include <aidl/android/hardware/graphics/common/PixelFormat.h> +#include <aidl/android/hardware/graphics/common/StandardMetadataType.h> +#include <android-base/unique_fd.h> +#include <android/hardware/graphics/mapper/IMapper.h> +#include <android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h> +#include <android/hardware/graphics/mapper/utils/IMapperProvider.h> +#include <cutils/native_handle.h> +#include <gralloctypes/Gralloc4.h> + +#include "cros_gralloc/cros_gralloc_driver.h" +#include "cros_gralloc/cros_gralloc_handle.h" +#include "cros_gralloc/gralloc4/CrosGralloc4Metadata.h" +#include "cros_gralloc/gralloc4/CrosGralloc4Utils.h" + +using namespace ::aidl::android::hardware::graphics::common; +using namespace ::android::hardware::graphics::mapper; +using ::aidl::android::hardware::graphics::allocator::BufferDescriptorInfo; +using ::android::base::unique_fd; + +#define REQUIRE_DRIVER() \ + if (!mDriver) { \ + ALOGE("Failed to %s. Driver is uninitialized.", __func__); \ + return AIMAPPER_ERROR_NO_RESOURCES; \ + } + +#define VALIDATE_BUFFER_HANDLE(bufferHandle) \ + if (!(bufferHandle)) { \ + ALOGE("Failed to %s. Null buffer_handle_t.", __func__); \ + return AIMAPPER_ERROR_BAD_BUFFER; \ + } + +#define VALIDATE_DRIVER_AND_BUFFER_HANDLE(bufferHandle) \ + REQUIRE_DRIVER() \ + VALIDATE_BUFFER_HANDLE(bufferHandle) + +static_assert(CROS_GRALLOC4_METADATA_MAX_NAME_SIZE >= + decltype(std::declval<BufferDescriptorInfo>().name){}.size(), + "Metadata name storage too small to fit a BufferDescriptorInfo::name"); + +constexpr const char* STANDARD_METADATA_NAME = + "android.hardware.graphics.common.StandardMetadataType"; + +static bool isStandardMetadata(AIMapper_MetadataType metadataType) { + return strcmp(STANDARD_METADATA_NAME, metadataType.name) == 0; +} + +class CrosGrallocMapperV5 final : public vendor::mapper::IMapperV5Impl { + private: + cros_gralloc_driver* mDriver = cros_gralloc_driver::get_instance(); + + public: + explicit CrosGrallocMapperV5() = default; + ~CrosGrallocMapperV5() override = default; + + AIMapper_Error importBuffer(const native_handle_t* _Nonnull handle, + buffer_handle_t _Nullable* _Nonnull outBufferHandle) override; + + AIMapper_Error freeBuffer(buffer_handle_t _Nonnull buffer) override; + + AIMapper_Error getTransportSize(buffer_handle_t _Nonnull buffer, uint32_t* _Nonnull outNumFds, + uint32_t* _Nonnull outNumInts) override; + + AIMapper_Error lock(buffer_handle_t _Nonnull buffer, uint64_t cpuUsage, ARect accessRegion, + int acquireFence, void* _Nullable* _Nonnull outData) override; + + AIMapper_Error unlock(buffer_handle_t _Nonnull buffer, int* _Nonnull releaseFence) override; + + AIMapper_Error flushLockedBuffer(buffer_handle_t _Nonnull buffer) override; + + AIMapper_Error rereadLockedBuffer(buffer_handle_t _Nonnull buffer) override; + + int32_t getMetadata(buffer_handle_t _Nonnull buffer, AIMapper_MetadataType metadataType, + void* _Nonnull outData, size_t outDataSize) override; + + int32_t getStandardMetadata(buffer_handle_t _Nonnull buffer, int64_t standardMetadataType, + void* _Nonnull outData, size_t outDataSize) override; + + AIMapper_Error setMetadata(buffer_handle_t _Nonnull buffer, AIMapper_MetadataType metadataType, + const void* _Nonnull metadata, size_t metadataSize) override; + + AIMapper_Error setStandardMetadata(buffer_handle_t _Nonnull buffer, + int64_t standardMetadataType, const void* _Nonnull metadata, + size_t metadataSize) override; + + AIMapper_Error listSupportedMetadataTypes( + const AIMapper_MetadataTypeDescription* _Nullable* _Nonnull outDescriptionList, + size_t* _Nonnull outNumberOfDescriptions) override; + + AIMapper_Error dumpBuffer(buffer_handle_t _Nonnull bufferHandle, + AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback, + void* _Null_unspecified context) override; + + AIMapper_Error dumpAllBuffers(AIMapper_BeginDumpBufferCallback _Nonnull beginDumpBufferCallback, + AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback, + void* _Null_unspecified context) override; + + AIMapper_Error getReservedRegion(buffer_handle_t _Nonnull buffer, + void* _Nullable* _Nonnull outReservedRegion, + uint64_t* _Nonnull outReservedSize) override; + + private: + enum class ReservedRegionArea { + /* CrosGralloc4Metadata */ + MAPPER4_METADATA, + + /* External user metadata */ + USER_METADATA, + }; + + AIMapper_Error getReservedRegionArea(const cros_gralloc_buffer* crosBuffer, + ReservedRegionArea area, void** outAddr, + uint64_t* outSize); + + AIMapper_Error getCrosMetadata(const cros_gralloc_buffer* crosBuffer, + const CrosGralloc4Metadata** outMetadata); + + AIMapper_Error getMutableCrosMetadata(cros_gralloc_buffer* crosBuffer, + CrosGralloc4Metadata** outMetadata); + + template <typename F, StandardMetadataType TYPE> + int32_t getStandardMetadata(const cros_gralloc_buffer* crosBuffer, F&& provide, + StandardMetadata<TYPE>); + + template <StandardMetadataType TYPE> + AIMapper_Error setStandardMetadata(CrosGralloc4Metadata* crosMetadata, + typename StandardMetadata<TYPE>::value_type&& value); + + void dumpBuffer( + const cros_gralloc_buffer* crosBuffer, + std::function<void(AIMapper_MetadataType, const std::vector<uint8_t>&)> callback); +}; + +AIMapper_Error CrosGrallocMapperV5::importBuffer( + const native_handle_t* _Nonnull bufferHandle, + buffer_handle_t _Nullable* _Nonnull outBufferHandle) { + REQUIRE_DRIVER() + + if (!bufferHandle || bufferHandle->numFds == 0) { + ALOGE("Failed to importBuffer. Bad handle."); + return AIMAPPER_ERROR_BAD_BUFFER; + } + + native_handle_t* importedBufferHandle = native_handle_clone(bufferHandle); + if (!importedBufferHandle) { + ALOGE("Failed to importBuffer. Handle clone failed: %s.", strerror(errno)); + return AIMAPPER_ERROR_NO_RESOURCES; + } + + int ret = mDriver->retain(importedBufferHandle); + if (ret) { + native_handle_close(importedBufferHandle); + native_handle_delete(importedBufferHandle); + return AIMAPPER_ERROR_NO_RESOURCES; + } + + *outBufferHandle = importedBufferHandle; + return AIMAPPER_ERROR_NONE; +} + +AIMapper_Error CrosGrallocMapperV5::freeBuffer(buffer_handle_t _Nonnull buffer) { + VALIDATE_DRIVER_AND_BUFFER_HANDLE(buffer) + + int ret = mDriver->release(buffer); + if (ret) { + return AIMAPPER_ERROR_BAD_BUFFER; + } + + native_handle_close(buffer); + native_handle_delete(const_cast<native_handle_t*>(buffer)); + return AIMAPPER_ERROR_NONE; +} + +AIMapper_Error CrosGrallocMapperV5::getTransportSize(buffer_handle_t _Nonnull bufferHandle, + uint32_t* _Nonnull outNumFds, + uint32_t* _Nonnull outNumInts) { + VALIDATE_DRIVER_AND_BUFFER_HANDLE(bufferHandle) + + // No local process data is currently stored on the native handle. + *outNumFds = bufferHandle->numFds; + *outNumInts = bufferHandle->numInts; + return AIMAPPER_ERROR_NONE; +} + +AIMapper_Error CrosGrallocMapperV5::lock(buffer_handle_t _Nonnull bufferHandle, uint64_t cpuUsage, + ARect region, int acquireFenceRawFd, + void* _Nullable* _Nonnull outData) { + // We take ownership of the FD in all cases, even for errors + unique_fd acquireFence(acquireFenceRawFd); + VALIDATE_DRIVER_AND_BUFFER_HANDLE(bufferHandle) + if (cpuUsage == 0) { + ALOGE("Failed to lock. Bad cpu usage: %" PRIu64 ".", cpuUsage); + return AIMAPPER_ERROR_BAD_VALUE; + } + + uint32_t mapUsage = cros_gralloc_convert_map_usage(cpuUsage); + + cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle); + if (crosHandle == nullptr) { + ALOGE("Failed to lock. Invalid handle."); + return AIMAPPER_ERROR_BAD_VALUE; + } + + struct rectangle rect; + + // An access region of all zeros means the entire buffer. + if (region.left == 0 && region.top == 0 && region.right == 0 && region.bottom == 0) { + rect = {0, 0, crosHandle->width, crosHandle->height}; + } else { + if (region.left < 0 || region.top < 0 || region.right <= region.left || + region.bottom <= region.top) { + ALOGE("Failed to lock. Invalid accessRegion: [%d, %d, %d, %d]", region.left, region.top, + region.right, region.bottom); + return AIMAPPER_ERROR_BAD_VALUE; + } + + if (region.right > crosHandle->width) { + ALOGE("Failed to lock. Invalid region: width greater than buffer width (%d vs %d).", + region.right, crosHandle->width); + return AIMAPPER_ERROR_BAD_VALUE; + } + + if (region.bottom > crosHandle->height) { + ALOGE("Failed to lock. Invalid region: height greater than buffer height (%d vs " + "%d).", + region.bottom, crosHandle->height); + return AIMAPPER_ERROR_BAD_VALUE; + } + + rect = {static_cast<uint32_t>(region.left), static_cast<uint32_t>(region.top), + static_cast<uint32_t>(region.right - region.left), + static_cast<uint32_t>(region.bottom - region.top)}; + } + + uint8_t* addr[DRV_MAX_PLANES]; + int32_t status = mDriver->lock(bufferHandle, acquireFence.get(), + /*close_acquire_fence=*/false, &rect, mapUsage, addr); + if (status) { + return AIMAPPER_ERROR_BAD_VALUE; + } + + *outData = addr[0]; + return AIMAPPER_ERROR_NONE; +} + +AIMapper_Error CrosGrallocMapperV5::unlock(buffer_handle_t _Nonnull buffer, + int* _Nonnull releaseFence) { + VALIDATE_DRIVER_AND_BUFFER_HANDLE(buffer) + int ret = mDriver->unlock(buffer, releaseFence); + if (ret) { + ALOGE("Failed to unlock."); + return AIMAPPER_ERROR_BAD_BUFFER; + } + return AIMAPPER_ERROR_NONE; +} + +AIMapper_Error CrosGrallocMapperV5::flushLockedBuffer(buffer_handle_t _Nonnull buffer) { + VALIDATE_DRIVER_AND_BUFFER_HANDLE(buffer) + int ret = mDriver->flush(buffer); + if (ret) { + ALOGE("Failed to flushLockedBuffer. Flush failed."); + return AIMAPPER_ERROR_BAD_BUFFER; + } + return AIMAPPER_ERROR_NONE; +} + +AIMapper_Error CrosGrallocMapperV5::rereadLockedBuffer(buffer_handle_t _Nonnull buffer) { + VALIDATE_DRIVER_AND_BUFFER_HANDLE(buffer) + int ret = mDriver->invalidate(buffer); + if (ret) { + ALOGE("Failed to rereadLockedBuffer. Failed to invalidate."); + return AIMAPPER_ERROR_BAD_BUFFER; + } + + return AIMAPPER_ERROR_NONE; +} + +int32_t CrosGrallocMapperV5::getMetadata(buffer_handle_t _Nonnull buffer, + AIMapper_MetadataType metadataType, void* _Nonnull outData, + size_t outDataSize) { + // We don't have any vendor-specific metadata, so divert to getStandardMetadata after validating + // that this is a standard metadata request + if (isStandardMetadata(metadataType)) { + return getStandardMetadata(buffer, metadataType.value, outData, outDataSize); + } + return -AIMAPPER_ERROR_UNSUPPORTED; +} + +int32_t CrosGrallocMapperV5::getStandardMetadata(buffer_handle_t _Nonnull bufferHandle, + int64_t standardType, void* _Nonnull outData, + size_t outDataSize) { + // Can't use VALIDATE_DRIVER_AND_BUFFER_HANDLE because we need to negate the error + // for this call + if (!mDriver) { + ALOGE("Failed to %s. Driver is uninitialized.", __func__); + return -AIMAPPER_ERROR_NO_RESOURCES; + } + if (!(bufferHandle)) { + ALOGE("Failed to %s. Null buffer_handle_t.", __func__); + return -AIMAPPER_ERROR_BAD_BUFFER; + } + + cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle); + if (!crosHandle) { + ALOGE("Failed to get. Invalid handle."); + return -AIMAPPER_ERROR_BAD_BUFFER; + } + + int32_t retValue = -AIMAPPER_ERROR_UNSUPPORTED; + mDriver->with_buffer(crosHandle, [&](cros_gralloc_buffer* crosBuffer) { + auto provider = [&]<StandardMetadataType T>(auto&& provide) -> int32_t { + return getStandardMetadata(crosBuffer, provide, StandardMetadata<T>{}); + }; + retValue = provideStandardMetadata(static_cast<StandardMetadataType>(standardType), outData, + outDataSize, provider); + }); + return retValue; +} + +template <typename F, StandardMetadataType metadataType> +int32_t CrosGrallocMapperV5::getStandardMetadata(const cros_gralloc_buffer* crosBuffer, F&& provide, + StandardMetadata<metadataType>) { + const CrosGralloc4Metadata* crosMetadata = nullptr; + if constexpr (metadataType == StandardMetadataType::BLEND_MODE || + metadataType == StandardMetadataType::CTA861_3 || + metadataType == StandardMetadataType::DATASPACE || + metadataType == StandardMetadataType::NAME || + metadataType == StandardMetadataType::SMPTE2086) { + AIMapper_Error error = getCrosMetadata(crosBuffer, &crosMetadata); + if (error != AIMAPPER_ERROR_NONE) { + ALOGE("Failed to get. Failed to get buffer metadata."); + return -AIMAPPER_ERROR_NO_RESOURCES; + } + } + if constexpr (metadataType == StandardMetadataType::BUFFER_ID) { + return provide(crosBuffer->get_id()); + } + if constexpr (metadataType == StandardMetadataType::NAME) { + return provide(crosMetadata->name); + } + if constexpr (metadataType == StandardMetadataType::WIDTH) { + return provide(crosBuffer->get_width()); + } + if constexpr (metadataType == StandardMetadataType::STRIDE) { + return provide(crosBuffer->get_pixel_stride()); + } + if constexpr (metadataType == StandardMetadataType::HEIGHT) { + return provide(crosBuffer->get_height()); + } + if constexpr (metadataType == StandardMetadataType::LAYER_COUNT) { + return provide(1); + } + if constexpr (metadataType == StandardMetadataType::PIXEL_FORMAT_REQUESTED) { + return provide(static_cast<PixelFormat>(crosBuffer->get_android_format())); + } + if constexpr (metadataType == StandardMetadataType::PIXEL_FORMAT_FOURCC) { + return provide(drv_get_standard_fourcc(crosBuffer->get_format())); + } + if constexpr (metadataType == StandardMetadataType::PIXEL_FORMAT_MODIFIER) { + return provide(crosBuffer->get_format_modifier()); + } + if constexpr (metadataType == StandardMetadataType::USAGE) { + return provide(static_cast<BufferUsage>(crosBuffer->get_android_usage())); + } + if constexpr (metadataType == StandardMetadataType::ALLOCATION_SIZE) { + return provide(crosBuffer->get_total_size()); + } + if constexpr (metadataType == StandardMetadataType::PROTECTED_CONTENT) { + uint64_t hasProtectedContent = + crosBuffer->get_android_usage() & static_cast<int64_t>(BufferUsage::PROTECTED) ? 1 + : 0; + return provide(hasProtectedContent); + } + if constexpr (metadataType == StandardMetadataType::COMPRESSION) { + return provide(android::gralloc4::Compression_None); + } + if constexpr (metadataType == StandardMetadataType::INTERLACED) { + return provide(android::gralloc4::Interlaced_None); + } + if constexpr (metadataType == StandardMetadataType::CHROMA_SITING) { + return provide(android::gralloc4::ChromaSiting_None); + } + if constexpr (metadataType == StandardMetadataType::PLANE_LAYOUTS) { + std::vector<PlaneLayout> planeLayouts; + getPlaneLayouts(crosBuffer->get_format(), &planeLayouts); + + for (size_t plane = 0; plane < planeLayouts.size(); plane++) { + PlaneLayout& planeLayout = planeLayouts[plane]; + 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; + } + + return provide(planeLayouts); + } + if constexpr (metadataType == StandardMetadataType::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 (uint32_t plane = 0; plane < numPlanes; plane++) { + aidl::android::hardware::graphics::common::Rect crop; + crop.left = 0; + crop.top = 0; + crop.right = w; + crop.bottom = h; + crops.push_back(crop); + } + + return provide(crops); + } + if constexpr (metadataType == StandardMetadataType::DATASPACE) { + return provide(crosMetadata->dataspace); + } + if constexpr (metadataType == StandardMetadataType::BLEND_MODE) { + return provide(crosMetadata->blendMode); + } + if constexpr (metadataType == StandardMetadataType::SMPTE2086) { + return crosMetadata->smpte2086 ? provide(*crosMetadata->smpte2086) : 0; + } + if constexpr (metadataType == StandardMetadataType::CTA861_3) { + return crosMetadata->cta861_3 ? provide(*crosMetadata->cta861_3) : 0; + } + return -AIMAPPER_ERROR_UNSUPPORTED; +} + +AIMapper_Error CrosGrallocMapperV5::setMetadata(buffer_handle_t _Nonnull buffer, + AIMapper_MetadataType metadataType, + const void* _Nonnull metadata, + size_t metadataSize) { + // We don't have any vendor-specific metadata, so divert to setStandardMetadata after validating + // that this is a standard metadata request + if (isStandardMetadata(metadataType)) { + return setStandardMetadata(buffer, metadataType.value, metadata, metadataSize); + } + return AIMAPPER_ERROR_UNSUPPORTED; +} + +AIMapper_Error CrosGrallocMapperV5::setStandardMetadata(buffer_handle_t _Nonnull bufferHandle, + int64_t standardTypeRaw, + const void* _Nonnull metadata, + size_t metadataSize) { + VALIDATE_DRIVER_AND_BUFFER_HANDLE(bufferHandle) + + cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle); + if (!crosHandle) { + ALOGE("Failed to get. Invalid handle."); + return AIMAPPER_ERROR_BAD_BUFFER; + } + + auto standardType = static_cast<StandardMetadataType>(standardTypeRaw); + + switch (standardType) { + // Read-only values + case StandardMetadataType::BUFFER_ID: + case StandardMetadataType::NAME: + case StandardMetadataType::WIDTH: + case StandardMetadataType::HEIGHT: + case StandardMetadataType::LAYER_COUNT: + case StandardMetadataType::PIXEL_FORMAT_REQUESTED: + case StandardMetadataType::USAGE: + return AIMAPPER_ERROR_BAD_VALUE; + + // Supported to set + case StandardMetadataType::BLEND_MODE: + case StandardMetadataType::CTA861_3: + case StandardMetadataType::DATASPACE: + case StandardMetadataType::SMPTE2086: + break; + + // Everything else unsupported + default: + return AIMAPPER_ERROR_UNSUPPORTED; + } + + AIMapper_Error status = AIMAPPER_ERROR_UNSUPPORTED; + mDriver->with_buffer(crosHandle, [&](cros_gralloc_buffer* crosBuffer) { + CrosGralloc4Metadata* crosMetadata = nullptr; + status = getMutableCrosMetadata(crosBuffer, &crosMetadata); + if (status != AIMAPPER_ERROR_NONE) { + return; + } + + auto applier = [&]<StandardMetadataType T>(auto&& value) -> AIMapper_Error { + return setStandardMetadata<T>(crosMetadata, std::forward<decltype(value)>(value)); + }; + + status = applyStandardMetadata(standardType, metadata, metadataSize, applier); + }); + return status; +} + +template <StandardMetadataType TYPE> +AIMapper_Error CrosGrallocMapperV5::setStandardMetadata( + CrosGralloc4Metadata* crosMetadata, typename StandardMetadata<TYPE>::value_type&& value) { + if constexpr (TYPE == StandardMetadataType::BLEND_MODE) { + crosMetadata->blendMode = value; + } + if constexpr (TYPE == StandardMetadataType::CTA861_3) { + crosMetadata->cta861_3 = value; + } + if constexpr (TYPE == StandardMetadataType::DATASPACE) { + crosMetadata->dataspace = value; + } + if constexpr (TYPE == StandardMetadataType::SMPTE2086) { + crosMetadata->smpte2086 = value; + } + // Unsupported metadatas were already filtered before we reached this point + return AIMAPPER_ERROR_NONE; +} + +constexpr AIMapper_MetadataTypeDescription describeStandard(StandardMetadataType type, + bool isGettable, bool isSettable) { + return {{STANDARD_METADATA_NAME, static_cast<int64_t>(type)}, + nullptr, + isGettable, + isSettable, + {0}}; +} + +AIMapper_Error CrosGrallocMapperV5::listSupportedMetadataTypes( + const AIMapper_MetadataTypeDescription* _Nullable* _Nonnull outDescriptionList, + size_t* _Nonnull outNumberOfDescriptions) { + static constexpr std::array<AIMapper_MetadataTypeDescription, 22> sSupportedMetadaTypes{ + describeStandard(StandardMetadataType::BUFFER_ID, true, false), + describeStandard(StandardMetadataType::NAME, true, false), + describeStandard(StandardMetadataType::WIDTH, true, false), + describeStandard(StandardMetadataType::HEIGHT, true, false), + describeStandard(StandardMetadataType::LAYER_COUNT, true, false), + describeStandard(StandardMetadataType::PIXEL_FORMAT_REQUESTED, true, false), + describeStandard(StandardMetadataType::PIXEL_FORMAT_FOURCC, true, false), + describeStandard(StandardMetadataType::PIXEL_FORMAT_MODIFIER, true, false), + describeStandard(StandardMetadataType::USAGE, true, false), + describeStandard(StandardMetadataType::ALLOCATION_SIZE, true, false), + describeStandard(StandardMetadataType::PROTECTED_CONTENT, true, false), + describeStandard(StandardMetadataType::COMPRESSION, true, false), + describeStandard(StandardMetadataType::INTERLACED, true, false), + describeStandard(StandardMetadataType::CHROMA_SITING, true, false), + describeStandard(StandardMetadataType::PLANE_LAYOUTS, true, false), + describeStandard(StandardMetadataType::CROP, true, false), + describeStandard(StandardMetadataType::DATASPACE, true, true), + describeStandard(StandardMetadataType::COMPRESSION, true, false), + describeStandard(StandardMetadataType::BLEND_MODE, true, true), + describeStandard(StandardMetadataType::SMPTE2086, true, true), + describeStandard(StandardMetadataType::CTA861_3, true, true), + describeStandard(StandardMetadataType::STRIDE, true, false), + }; + *outDescriptionList = sSupportedMetadaTypes.data(); + *outNumberOfDescriptions = sSupportedMetadaTypes.size(); + return AIMAPPER_ERROR_NONE; +} + +void CrosGrallocMapperV5::dumpBuffer( + const cros_gralloc_buffer* crosBuffer, + std::function<void(AIMapper_MetadataType, const std::vector<uint8_t>&)> callback) { + // Temp buffer of ~10kb, should be large enough for any of the metadata we want to dump + std::vector<uint8_t> tempBuffer; + tempBuffer.resize(10000); + AIMapper_MetadataType metadataType; + metadataType.name = STANDARD_METADATA_NAME; + + // Take an instance of the empty StandardMetadat<T> class just to allow auto-deduction + // to happen as explicit template invocation on lambdas is ugly + auto dump = [&]<StandardMetadataType T>(StandardMetadata<T>) { + // Nested templated lambdas! Woo! But the cleanness of the result is worth it + // The outer lambda exists basically just to capture the StandardMetadataType that's + // being dumped, as the `provider` parameter of getStandardMetadata only knows + // the value_type that the enum maps to but not the enum value itself, which we need to + // construct the `AIMapper_MetadataType` to pass to the dump callback + auto dumpInner = [&](const typename StandardMetadata<T>::value_type& value) -> int32_t { + int32_t size = + StandardMetadata<T>::value::encode(value, tempBuffer.data(), tempBuffer.size()); + // The initial size should always be large enough, but just in case... + if (size > tempBuffer.size()) { + tempBuffer.resize(size * 2); + size = StandardMetadata<T>::value::encode(value, tempBuffer.data(), + tempBuffer.size()); + } + // If the first resize failed _somehow_, just give up. Also don't notify if any + // errors occurred during encoding. + if (size >= 0 && size <= tempBuffer.size()) { + metadataType.value = static_cast<int64_t>(T); + callback(metadataType, tempBuffer); + } + // We don't actually care about the return value in this case, but why not use the + // real value anyway + return size; + }; + getStandardMetadata(crosBuffer, dumpInner, StandardMetadata<T>{}); + }; + + // So clean. So pretty. + dump(StandardMetadata<StandardMetadataType::BUFFER_ID>{}); + dump(StandardMetadata<StandardMetadataType::NAME>{}); + dump(StandardMetadata<StandardMetadataType::WIDTH>{}); + dump(StandardMetadata<StandardMetadataType::HEIGHT>{}); + dump(StandardMetadata<StandardMetadataType::LAYER_COUNT>{}); + dump(StandardMetadata<StandardMetadataType::PIXEL_FORMAT_REQUESTED>{}); + dump(StandardMetadata<StandardMetadataType::PIXEL_FORMAT_FOURCC>{}); + dump(StandardMetadata<StandardMetadataType::PIXEL_FORMAT_MODIFIER>{}); + dump(StandardMetadata<StandardMetadataType::USAGE>{}); + dump(StandardMetadata<StandardMetadataType::ALLOCATION_SIZE>{}); + dump(StandardMetadata<StandardMetadataType::PROTECTED_CONTENT>{}); + dump(StandardMetadata<StandardMetadataType::COMPRESSION>{}); + dump(StandardMetadata<StandardMetadataType::INTERLACED>{}); + dump(StandardMetadata<StandardMetadataType::CHROMA_SITING>{}); + dump(StandardMetadata<StandardMetadataType::PLANE_LAYOUTS>{}); + dump(StandardMetadata<StandardMetadataType::DATASPACE>{}); + dump(StandardMetadata<StandardMetadataType::BLEND_MODE>{}); +} + +AIMapper_Error CrosGrallocMapperV5::dumpBuffer( + buffer_handle_t _Nonnull bufferHandle, + AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback, void* _Null_unspecified context) { + VALIDATE_DRIVER_AND_BUFFER_HANDLE(bufferHandle) + cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle); + if (!crosHandle) { + ALOGE("Failed to get. Invalid handle."); + return AIMAPPER_ERROR_BAD_BUFFER; + } + auto callback = [&](AIMapper_MetadataType type, const std::vector<uint8_t>& buffer) { + dumpBufferCallback(context, type, buffer.data(), buffer.size()); + }; + mDriver->with_buffer( + crosHandle, [&](cros_gralloc_buffer* crosBuffer) { dumpBuffer(crosBuffer, callback); }); + return AIMAPPER_ERROR_NONE; +} + +AIMapper_Error CrosGrallocMapperV5::dumpAllBuffers( + AIMapper_BeginDumpBufferCallback _Nonnull beginDumpBufferCallback, + AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback, void* _Null_unspecified context) { + REQUIRE_DRIVER() + auto callback = [&](AIMapper_MetadataType type, const std::vector<uint8_t>& buffer) { + dumpBufferCallback(context, type, buffer.data(), buffer.size()); + }; + mDriver->with_each_buffer([&](cros_gralloc_buffer* crosBuffer) { + beginDumpBufferCallback(context); + dumpBuffer(crosBuffer, callback); + }); + return AIMAPPER_ERROR_NONE; +} + +AIMapper_Error CrosGrallocMapperV5::getReservedRegion(buffer_handle_t _Nonnull buffer, + void* _Nullable* _Nonnull outReservedRegion, + uint64_t* _Nonnull outReservedSize) { + VALIDATE_DRIVER_AND_BUFFER_HANDLE(buffer) + cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(buffer); + if (!crosHandle) { + ALOGE("Failed to getReservedRegion. Invalid handle."); + return AIMAPPER_ERROR_BAD_BUFFER; + } + + void* reservedRegionAddr = nullptr; + uint64_t reservedRegionSize = 0; + + AIMapper_Error error = AIMAPPER_ERROR_NONE; + mDriver->with_buffer(crosHandle, [&, this](cros_gralloc_buffer* crosBuffer) { + error = getReservedRegionArea(crosBuffer, ReservedRegionArea::USER_METADATA, + &reservedRegionAddr, &reservedRegionSize); + }); + + if (error != AIMAPPER_ERROR_NONE) { + ALOGE("Failed to getReservedRegion. Failed to getReservedRegionArea."); + return AIMAPPER_ERROR_BAD_BUFFER; + } + + return AIMAPPER_ERROR_NONE; +} + +AIMapper_Error CrosGrallocMapperV5::getReservedRegionArea(const cros_gralloc_buffer* crosBuffer, + ReservedRegionArea area, void** outAddr, + uint64_t* outSize) { + int ret = crosBuffer->get_reserved_region(outAddr, outSize); + if (ret) { + ALOGE("Failed to getReservedRegionArea."); + *outAddr = nullptr; + *outSize = 0; + return AIMAPPER_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 AIMAPPER_ERROR_NONE; +} + +AIMapper_Error CrosGrallocMapperV5::getCrosMetadata(const cros_gralloc_buffer* crosBuffer, + const CrosGralloc4Metadata** outMetadata) { + void* addr = nullptr; + uint64_t size; + + auto error = + getReservedRegionArea(crosBuffer, ReservedRegionArea::MAPPER4_METADATA, &addr, &size); + if (error != AIMAPPER_ERROR_NONE) { + return error; + } + + *outMetadata = reinterpret_cast<const CrosGralloc4Metadata*>(addr); + return AIMAPPER_ERROR_NONE; +} + +AIMapper_Error CrosGrallocMapperV5::getMutableCrosMetadata(cros_gralloc_buffer* crosBuffer, + CrosGralloc4Metadata** outMetadata) { + void* addr = nullptr; + uint64_t size; + + auto error = + getReservedRegionArea(crosBuffer, ReservedRegionArea::MAPPER4_METADATA, &addr, &size); + if (error != AIMAPPER_ERROR_NONE) { + return error; + } + + *outMetadata = reinterpret_cast<CrosGralloc4Metadata*>(addr); + return AIMAPPER_ERROR_NONE; +} + +extern "C" uint32_t ANDROID_HAL_MAPPER_VERSION = AIMAPPER_VERSION_5; + +extern "C" AIMapper_Error AIMapper_loadIMapper(AIMapper* _Nullable* _Nonnull outImplementation) { + static vendor::mapper::IMapperProvider<CrosGrallocMapperV5> provider; + return provider.load(outImplementation); +}
\ No newline at end of file diff --git a/cros_gralloc/mapper_stablec/mapper.minigbm.xml b/cros_gralloc/mapper_stablec/mapper.minigbm.xml new file mode 100644 index 0000000..282f7c8 --- /dev/null +++ b/cros_gralloc/mapper_stablec/mapper.minigbm.xml @@ -0,0 +1,9 @@ +<manifest version="1.0" type="device"> + <hal format="native"> + <name>mapper</name> + <version>5.0</version> + <interface> + <instance>minigbm</instance> + </interface> + </hal> +</manifest> @@ -78,7 +78,7 @@ static void close_gem_handle(uint32_t handle, int fd) gem_close.handle = handle; ret = drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &gem_close); if (ret) - drv_log("DRM_IOCTL_GEM_CLOSE failed (handle=%x) error %d\n", handle, ret); + drv_loge("DRM_IOCTL_GEM_CLOSE failed (handle=%x) error %d\n", handle, ret); } /* @@ -135,7 +135,7 @@ static int import_into_minigbm(struct dri_driver *dri, struct bo *bo) close(prime_fd); if (ret) { - drv_log("drmPrimeFDToHandle failed with %s\n", strerror(errno)); + drv_loge("drmPrimeFDToHandle failed with %s\n", strerror(errno)); goto cleanup; } @@ -186,6 +186,20 @@ cleanup: return ret; } +const __DRIuseInvalidateExtension use_invalidate = { + .base = { __DRI_USE_INVALIDATE, 1 }, +}; + +void *dri_dlopen(const char *dri_so_path) +{ + return dlopen(dri_so_path, RTLD_NOW | RTLD_GLOBAL); +} + +void dri_dlclose(void *dri_so_handle) +{ + dlclose(dri_so_handle); +} + /* * The caller is responsible for setting drv->priv to a structure that derives from dri_driver. */ @@ -193,7 +207,7 @@ int dri_init(struct driver *drv, const char *dri_so_path, const char *driver_suf { char fname[128]; const __DRIextension **(*get_extensions)(); - const __DRIextension *loader_extensions[] = { NULL }; + const __DRIextension *loader_extensions[] = { &use_invalidate.base, NULL }; struct dri_driver *dri = drv->priv; char *node_name = drmGetRenderDeviceNameFromFd(drv_get_fd(drv)); @@ -205,7 +219,7 @@ int dri_init(struct driver *drv, const char *dri_so_path, const char *driver_suf if (dri->fd < 0) return -ENODEV; - dri->driver_handle = dlopen(dri_so_path, RTLD_NOW | RTLD_GLOBAL); + dri->driver_handle = dri_dlopen(dri_so_path); if (!dri->driver_handle) goto close_dri_fd; @@ -253,7 +267,7 @@ free_context: free_screen: dri->core_extension->destroyScreen(dri->device); free_handle: - dlclose(dri->driver_handle); + dri_dlclose(dri->driver_handle); dri->driver_handle = NULL; close_dri_fd: close(dri->fd); @@ -269,7 +283,7 @@ void dri_close(struct driver *drv) dri->core_extension->destroyContext(dri->context); dri->core_extension->destroyScreen(dri->device); - dlclose(dri->driver_handle); + dri_dlclose(dri->driver_handle); dri->driver_handle = NULL; close(dri->fd); } @@ -26,6 +26,9 @@ struct dri_driver { const __DRIconfig **configs; }; +void *dri_dlopen(const char *dri_so_path); +void dri_dlclose(void *dri_so_handle); + int dri_init(struct driver *drv, const char *dri_so_path, const char *driver_suffix); void dri_close(struct driver *drv); int dri_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, @@ -30,15 +30,9 @@ extern const struct backend backend_amdgpu; #ifdef DRV_I915 extern const struct backend backend_i915; #endif -#ifdef DRV_MEDIATEK -extern const struct backend backend_mediatek; -#endif #ifdef DRV_MSM extern const struct backend backend_msm; #endif -#ifdef DRV_ROCKCHIP -extern const struct backend backend_rockchip; -#endif #ifdef DRV_VC4 extern const struct backend backend_vc4; #endif @@ -46,15 +40,47 @@ extern const struct backend backend_vc4; // Dumb / generic drivers extern const struct backend backend_evdi; extern const struct backend backend_marvell; +extern const struct backend backend_mediatek; extern const struct backend backend_meson; extern const struct backend backend_nouveau; extern const struct backend backend_komeda; extern const struct backend backend_radeon; +extern const struct backend backend_rockchip; +extern const struct backend backend_sun4i_drm; extern const struct backend backend_synaptics; extern const struct backend backend_virtgpu; extern const struct backend backend_udl; extern const struct backend backend_vkms; +static const struct backend *drv_backend_list[] = { +#ifdef DRV_AMDGPU + &backend_amdgpu, +#endif +#ifdef DRV_I915 + &backend_i915, +#endif +#ifdef DRV_MSM + &backend_msm, +#endif +#ifdef DRV_VC4 + &backend_vc4, +#endif + &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 +}; + +void drv_preload(bool load) +{ + unsigned int i; + for (i = 0; i < ARRAY_SIZE(drv_backend_list); i++) { + const struct backend *b = drv_backend_list[i]; + if (b->preload) + b->preload(load); + } +} + static const struct backend *drv_get_backend(int fd) { drmVersionPtr drm_version; @@ -65,32 +91,8 @@ static const struct backend *drv_get_backend(int fd) if (!drm_version) return NULL; - const struct backend *backend_list[] = { -#ifdef DRV_AMDGPU - &backend_amdgpu, -#endif -#ifdef DRV_I915 - &backend_i915, -#endif -#ifdef DRV_MEDIATEK - &backend_mediatek, -#endif -#ifdef DRV_MSM - &backend_msm, -#endif -#ifdef DRV_ROCKCHIP - &backend_rockchip, -#endif -#ifdef DRV_VC4 - &backend_vc4, -#endif - &backend_evdi, &backend_marvell, &backend_meson, &backend_nouveau, - &backend_komeda, &backend_radeon, &backend_synaptics, &backend_virtgpu, - &backend_udl, &backend_virtgpu, &backend_vkms - }; - - for (i = 0; i < ARRAY_SIZE(backend_list); i++) { - const struct backend *b = backend_list[i]; + for (i = 0; i < ARRAY_SIZE(drv_backend_list); i++) { + const struct backend *b = drv_backend_list[i]; if (!strcmp(drm_version->name, b->name)) { drmFreeVersion(drm_version); return b; @@ -258,7 +260,7 @@ static void drv_bo_mapping_destroy(struct bo *bo) if (ret) { pthread_mutex_unlock(&drv->mappings_lock); assert(ret); - drv_log("munmap failed\n"); + drv_loge("munmap failed\n"); return; } @@ -438,7 +440,7 @@ struct bo *drv_bo_import(struct driver *drv, struct drv_import_fd_data *data) seek_end = lseek(data->fds[plane], 0, SEEK_END); if (seek_end == (off_t)(-1)) { - drv_log("lseek() failed with %s\n", strerror(errno)); + drv_loge("lseek() failed with %s\n", strerror(errno)); goto destroy_bo; } @@ -449,7 +451,7 @@ struct bo *drv_bo_import(struct driver *drv, struct drv_import_fd_data *data) bo->meta.sizes[plane] = data->offsets[plane + 1] - data->offsets[plane]; if ((int64_t)bo->meta.offsets[plane] + bo->meta.sizes[plane] > seek_end) { - drv_log("buffer size is too large.\n"); + drv_loge("buffer size is too large.\n"); goto destroy_bo; } @@ -521,7 +523,7 @@ void *drv_bo_map(struct bo *bo, const struct rectangle *rect, uint32_t map_flags } memcpy(mapping.vma->map_strides, bo->meta.strides, sizeof(mapping.vma->map_strides)); - addr = drv->backend->bo_map(bo, mapping.vma, plane, map_flags); + addr = drv->backend->bo_map(bo, mapping.vma, map_flags); if (addr == MAP_FAILED) { *map_data = NULL; free(mapping.vma); @@ -660,7 +662,7 @@ int drv_bo_get_plane_fd(struct bo *bo, size_t plane) ret = drmPrimeHandleToFD(bo->drv->fd, bo->handles[plane].u32, DRM_CLOEXEC, &fd); if (ret) - drv_log("Failed to get plane fd: %s\n", strerror(errno)); + drv_loge("Failed to get plane fd: %s\n", strerror(errno)); return (ret) ? ret : fd; } @@ -744,7 +746,8 @@ uint32_t drv_num_buffers_per_bo(struct bo *bo) return count; } -void drv_log_prefix(const char *prefix, const char *file, int line, const char *format, ...) +void drv_log_prefix(enum drv_log_level level, const char *prefix, const char *file, int line, + const char *format, ...) { char buf[50]; snprintf(buf, sizeof(buf), "[%s:%s(%d)]", prefix, basename(file), line); @@ -752,10 +755,30 @@ void drv_log_prefix(const char *prefix, const char *file, int line, const char * va_list args; va_start(args, format); #ifdef __ANDROID__ - __android_log_vprint(ANDROID_LOG_ERROR, buf, format, args); + int prio = ANDROID_LOG_ERROR; + switch (level) { + case DRV_LOGV: + prio = ANDROID_LOG_VERBOSE; + break; + case DRV_LOGD: + prio = ANDROID_LOG_DEBUG; + break; + case DRV_LOGI: + prio = ANDROID_LOG_INFO; + break; + case DRV_LOGE: + default: + break; + }; + __android_log_vprint(prio, buf, format, args); #else - fprintf(stderr, "%s ", buf); - vfprintf(stderr, format, args); + if (level == DRV_LOGE) { + fprintf(stderr, "%s ", buf); + vfprintf(stderr, format, args); + } else { + fprintf(stdout, "%s ", buf); + vfprintf(stdout, format, args); + } #endif va_end(args); } @@ -41,6 +41,9 @@ extern "C" { #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) + +#define BO_USE_ARC_SCREEN_CAP_PROBED (1ull << 63) /* Quirks for allocating a buffer. */ #define BO_QUIRK_NONE 0 @@ -76,6 +79,10 @@ extern "C" { #define I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS fourcc_mod_code(INTEL, 6) #endif +//TODO: remove this defination once drm_fourcc.h contains it. +#ifndef I915_FORMAT_MOD_4_TILED +#define I915_FORMAT_MOD_4_TILED fourcc_mod_code(INTEL, 9) +#endif // clang-format on struct driver; struct bo; @@ -124,6 +131,8 @@ struct mapping { uint32_t refcount; }; +void drv_preload(bool load); + struct driver *drv_create(int fd); void drv_destroy(struct driver *drv); @@ -206,12 +215,25 @@ int drv_resource_info(struct bo *bo, uint32_t strides[DRV_MAX_PLANES], uint32_t drv_get_max_texture_2d_size(struct driver *drv); -#define drv_log(format, ...) \ +enum drv_log_level { + DRV_LOGV, + DRV_LOGD, + DRV_LOGI, + DRV_LOGE, +}; + +#define _drv_log(level, format, ...) \ do { \ - drv_log_prefix("minigbm", __FILE__, __LINE__, format, ##__VA_ARGS__); \ + drv_log_prefix(level, "minigbm", __FILE__, __LINE__, format, ##__VA_ARGS__); \ } while (0) -__attribute__((format(printf, 4, 5))) void drv_log_prefix(const char *prefix, const char *file, +#define drv_loge(format, ...) _drv_log(DRV_LOGE, format, ##__VA_ARGS__) +#define drv_logv(format, ...) _drv_log(DRV_LOGV, format, ##__VA_ARGS__) +#define drv_logd(format, ...) _drv_log(DRV_LOGD, format, ##__VA_ARGS__) +#define drv_logi(format, ...) _drv_log(DRV_LOGI, format, ##__VA_ARGS__) + +__attribute__((format(printf, 5, 6))) void drv_log_prefix(enum drv_log_level level, + const char *prefix, const char *file, int line, const char *format, ...); #ifdef __cplusplus diff --git a/drv_helpers.c b/drv_helpers.c index 6ea4b8e..cd51881 100644 --- a/drv_helpers.c +++ b/drv_helpers.c @@ -163,7 +163,7 @@ static const struct planar_layout *layout_from_format(uint32_t format) return &packed_8bpp_layout; default: - drv_log("UNKNOWN FORMAT %d\n", format); + drv_loge("UNKNOWN FORMAT %d\n", format); return NULL; } } @@ -250,18 +250,30 @@ uint32_t drv_size_from_format(uint32_t format, uint32_t stride, uint32_t height, return stride * drv_height_from_format(format, height, plane); } -static uint32_t subsample_stride(uint32_t stride, uint32_t format, size_t plane) +static uint32_t subsample_stride(uint32_t stride, uint32_t stride_align, uint32_t format, + size_t plane) { + uint32_t plane_stride = stride; + if (plane != 0) { switch (format) { case DRM_FORMAT_YVU420: case DRM_FORMAT_YVU420_ANDROID: - stride = DIV_ROUND_UP(stride, 2); + plane_stride = DIV_ROUND_UP(plane_stride, 2); break; } } - return stride; + plane_stride = ALIGN(plane_stride, stride_align); + + if (format == DRM_FORMAT_YVU420_ANDROID) { + if (plane != 0) + assert(plane_stride == ALIGN(stride / 2, 16)); + else + assert(plane_stride % 16 == 0); + } + + return plane_stride; } /* @@ -269,14 +281,17 @@ static uint32_t subsample_stride(uint32_t stride, uint32_t format, size_t plane) * the first plane, height and a format. This function assumes there is just * one kernel buffer per buffer object. */ -int drv_bo_from_format(struct bo *bo, uint32_t stride, uint32_t aligned_height, uint32_t format) +int drv_bo_from_format(struct bo *bo, uint32_t stride, uint32_t stride_align, + uint32_t aligned_height, uint32_t format) { uint32_t padding[DRV_MAX_PLANES] = { 0 }; - return drv_bo_from_format_and_padding(bo, stride, aligned_height, format, padding); + return drv_bo_from_format_and_padding(bo, stride, stride_align, aligned_height, format, + padding); } -int drv_bo_from_format_and_padding(struct bo *bo, uint32_t stride, uint32_t aligned_height, - uint32_t format, uint32_t padding[DRV_MAX_PLANES]) +int drv_bo_from_format_and_padding(struct bo *bo, uint32_t stride, uint32_t stride_align, + uint32_t aligned_height, uint32_t format, + uint32_t padding[DRV_MAX_PLANES]) { size_t p, num_planes; uint32_t offset = 0; @@ -287,16 +302,18 @@ int drv_bo_from_format_and_padding(struct bo *bo, uint32_t stride, uint32_t alig /* * HAL_PIXEL_FORMAT_YV12 requires that (see <system/graphics.h>): * - the aligned height is same as the buffer's height. - * - the chroma stride is 16 bytes aligned, i.e., the luma's strides - * is 32 bytes aligned. + * - the luma stride is 16 bytes aligned + * - the chroma stride is ALIGN(luma_stride / 2, 16) */ if (format == DRM_FORMAT_YVU420_ANDROID) { assert(aligned_height == bo->meta.height); - assert(stride == ALIGN(stride, 32)); + /* force 16 if the caller has no requirement */ + if (stride_align <= 1) + stride_align = 16; } for (p = 0; p < num_planes; p++) { - bo->meta.strides[p] = subsample_stride(stride, format, p); + bo->meta.strides[p] = subsample_stride(stride, stride_align, format, p); bo->meta.sizes[p] = drv_size_from_format(format, bo->meta.strides[p], aligned_height, p) + padding[p]; @@ -353,6 +370,9 @@ int drv_dumb_bo_create_ex(struct bo *bo, uint32_t width, uint32_t height, uint32 DIV_ROUND_UP(aligned_width * layout_from_format(format)->bytes_per_pixel[0], 4); create_dumb.bpp = 32; } else { + /* Align for llvmpipe 64-byte tile size for dumb_driver */ + aligned_width = ALIGN(aligned_width, MESA_LLVMPIPE_TILE_SIZE); + aligned_height = ALIGN(aligned_height, MESA_LLVMPIPE_TILE_SIZE); create_dumb.bpp = layout_from_format(format)->bytes_per_pixel[0] * 8; } create_dumb.width = aligned_width; @@ -361,11 +381,11 @@ int drv_dumb_bo_create_ex(struct bo *bo, uint32_t width, uint32_t height, uint32 ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb); if (ret) { - drv_log("DRM_IOCTL_MODE_CREATE_DUMB failed (%d, %d)\n", bo->drv->fd, errno); + drv_loge("DRM_IOCTL_MODE_CREATE_DUMB failed (%d, %d)\n", bo->drv->fd, errno); return -errno; } - drv_bo_from_format(bo, create_dumb.pitch, height, format); + drv_bo_from_format(bo, create_dumb.pitch, 1, height, format); for (plane = 0; plane < bo->meta.num_planes; plane++) bo->handles[plane].u32 = create_dumb.handle; @@ -388,7 +408,7 @@ int drv_dumb_bo_destroy(struct bo *bo) destroy_dumb.handle = bo->handles[0].u32; ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb); if (ret) { - drv_log("DRM_IOCTL_MODE_DESTROY_DUMB failed (handle=%x)\n", bo->handles[0].u32); + drv_loge("DRM_IOCTL_MODE_DESTROY_DUMB failed (handle=%x)\n", bo->handles[0].u32); return -errno; } @@ -414,8 +434,8 @@ int drv_gem_bo_destroy(struct bo *bo) ret = drmIoctl(bo->drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close); if (ret) { - drv_log("DRM_IOCTL_GEM_CLOSE failed (handle=%x) error %d\n", - bo->handles[plane].u32, ret); + drv_loge("DRM_IOCTL_GEM_CLOSE failed (handle=%x) error %d\n", + bo->handles[plane].u32, ret); error = -errno; } } @@ -436,7 +456,7 @@ int drv_prime_bo_import(struct bo *bo, struct drv_import_fd_data *data) ret = drmIoctl(bo->drv->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &prime_handle); if (ret) { - drv_log("DRM_IOCTL_PRIME_FD_TO_HANDLE failed (fd=%u)\n", prime_handle.fd); + drv_loge("DRM_IOCTL_PRIME_FD_TO_HANDLE failed (fd=%u)\n", prime_handle.fd); /* * Need to call GEM close on planes that were opened, @@ -456,24 +476,23 @@ int drv_prime_bo_import(struct bo *bo, struct drv_import_fd_data *data) return 0; } -void *drv_dumb_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags) +void *drv_dumb_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags) { int ret; size_t i; struct drm_mode_map_dumb map_dumb; memset(&map_dumb, 0, sizeof(map_dumb)); - map_dumb.handle = bo->handles[plane].u32; + map_dumb.handle = bo->handles[0].u32; ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb); if (ret) { - drv_log("DRM_IOCTL_MODE_MAP_DUMB failed\n"); + drv_loge("DRM_IOCTL_MODE_MAP_DUMB failed\n"); return MAP_FAILED; } for (i = 0; i < bo->meta.num_planes; i++) - if (bo->handles[i].u32 == bo->handles[plane].u32) - vma->length += bo->meta.sizes[i]; + vma->length += bo->meta.sizes[i]; return mmap(0, vma->length, drv_get_prot(map_flags), MAP_SHARED, bo->drv->fd, map_dumb.offset); diff --git a/drv_helpers.h b/drv_helpers.h index edb69bf..0ea9ba9 100644 --- a/drv_helpers.h +++ b/drv_helpers.h @@ -21,9 +21,11 @@ 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); -int drv_bo_from_format(struct bo *bo, uint32_t stride, uint32_t aligned_height, uint32_t format); -int drv_bo_from_format_and_padding(struct bo *bo, uint32_t stride, uint32_t aligned_height, - uint32_t format, uint32_t padding[DRV_MAX_PLANES]); +int drv_bo_from_format(struct bo *bo, uint32_t stride, uint32_t stride_align, + uint32_t aligned_height, uint32_t format); +int drv_bo_from_format_and_padding(struct bo *bo, uint32_t stride, uint32_t stride_align, + uint32_t aligned_height, uint32_t format, + uint32_t padding[DRV_MAX_PLANES]); int drv_dumb_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, uint64_t use_flags); int drv_dumb_bo_create_ex(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, @@ -31,7 +33,7 @@ int drv_dumb_bo_create_ex(struct bo *bo, uint32_t width, uint32_t height, uint32 int drv_dumb_bo_destroy(struct bo *bo); 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); +void *drv_dumb_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags); int drv_bo_munmap(struct bo *bo, struct vma *vma); int drv_get_prot(uint32_t map_flags); void drv_add_combination(struct driver *drv, uint32_t format, struct format_metadata *metadata, @@ -74,6 +74,7 @@ struct driver { struct backend { char *name; + void (*preload)(bool load); int (*init)(struct driver *drv); void (*close)(struct driver *drv); int (*bo_create)(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, @@ -90,7 +91,7 @@ struct backend { /* 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); + void *(*bo_map)(struct bo *bo, struct vma *vma, 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); @@ -115,14 +116,24 @@ struct backend { #define BO_USE_SW_MASK (BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN | \ BO_USE_SW_READ_RARELY | BO_USE_SW_WRITE_RARELY | BO_USE_FRONT_RENDERING) +#define BO_USE_GPU_HW (BO_USE_RENDERING | BO_USE_TEXTURE | BO_USE_GPU_DATA_BUFFER) + #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) + +#define BO_USE_HW_MASK (BO_USE_GPU_HW | BO_USE_NON_GPU_HW) #ifndef DRM_FORMAT_MOD_LINEAR #define DRM_FORMAT_MOD_LINEAR DRM_FORMAT_MOD_NONE #endif #define LINEAR_METADATA (struct format_metadata) { 1, 0, DRM_FORMAT_MOD_LINEAR } + +#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) + // clang-format on #endif diff --git a/dumb_driver.c b/dumb_driver.c index c667a51..f74d237 100644 --- a/dumb_driver.c +++ b/dumb_driver.c @@ -10,9 +10,9 @@ #include "drv_priv.h" #include "util.h" -#define INIT_DUMB_DRIVER(driver) \ +#define INIT_DUMB_DRIVER_WITH_NAME(driver, _name) \ const struct backend backend_##driver = { \ - .name = #driver, \ + .name = _name, \ .init = dumb_driver_init, \ .bo_create = drv_dumb_bo_create, \ .bo_create_with_modifiers = dumb_bo_create_with_modifiers, \ @@ -23,6 +23,8 @@ .resolve_format_and_use_flags = drv_resolve_format_and_use_flags_helper, \ }; +#define INIT_DUMB_DRIVER(driver) INIT_DUMB_DRIVER_WITH_NAME(driver, #driver) + static const uint32_t scanout_render_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888, DRM_FORMAT_ABGR8888, DRM_FORMAT_XBGR8888, DRM_FORMAT_BGR888, DRM_FORMAT_RGB565 }; @@ -40,7 +42,8 @@ static int dumb_driver_init(struct driver *drv) 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); + BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | + BO_USE_GPU_DATA_BUFFER | BO_USE_SENSOR_DIRECT_DATA); 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); @@ -67,6 +70,14 @@ INIT_DUMB_DRIVER(marvell) INIT_DUMB_DRIVER(meson) INIT_DUMB_DRIVER(nouveau) INIT_DUMB_DRIVER(radeon) +INIT_DUMB_DRIVER_WITH_NAME(sun4i_drm, "sun4i-drm") INIT_DUMB_DRIVER(synaptics) INIT_DUMB_DRIVER(udl) INIT_DUMB_DRIVER(vkms) + +#ifndef DRV_ROCKCHIP +INIT_DUMB_DRIVER(rockchip) +#endif +#ifndef DRV_MEDIATEK +INIT_DUMB_DRIVER(mediatek) +#endif diff --git a/external/i915_drm.h b/external/i915_drm.h index e301c5f..e009a9e 100644 --- a/external/i915_drm.h +++ b/external/i915_drm.h @@ -1306,7 +1306,8 @@ struct drm_i915_gem_caching { #define I915_TILING_NONE 0 #define I915_TILING_X 1 #define I915_TILING_Y 2 -#define I915_TILING_LAST I915_TILING_Y +#define I915_TILING_4 9 +#define I915_TILING_LAST I915_TILING_4 #define I915_BIT_6_SWIZZLE_NONE 0 #define I915_BIT_6_SWIZZLE_9 1 @@ -290,6 +290,21 @@ enum gbm_bo_flags { * with pixel data. */ GBM_BO_USE_FRONT_RENDERING = (1 << 16), + + /** + * (1 << 17) is reserved for RenderScript (deprecated in Android 12). + */ + + /** + * The buffer will be used as a shader storage or uniform buffer + * object. + */ + GBM_BO_USE_GPU_DATA_BUFFER = (1 << 18), + + /** + * The buffer will be used as a sensor direct report output. + */ + GBM_BO_USE_SENSOR_DIRECT_DATA = (1 << 19), }; int diff --git a/gbm_helpers.c b/gbm_helpers.c index 17dcf1f..e5bcb40 100644 --- a/gbm_helpers.c +++ b/gbm_helpers.c @@ -46,6 +46,10 @@ uint64_t gbm_convert_usage(uint32_t usage) use_flags |= BO_USE_HW_VIDEO_ENCODER; if (usage & GBM_BO_USE_FRONT_RENDERING) use_flags |= BO_USE_FRONT_RENDERING; + if (usage & GBM_BO_USE_GPU_DATA_BUFFER) + use_flags |= BO_USE_GPU_DATA_BUFFER; + if (usage & GBM_BO_USE_SENSOR_DIRECT_DATA) + use_flags |= BO_USE_SENSOR_DIRECT_DATA; return use_flags; } @@ -44,18 +44,25 @@ static const uint64_t gen12_modifier_order[] = { I915_FORMAT_MOD_Y_TILED_GEN12_R 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, + DRM_FORMAT_MOD_LINEAR }; + struct modifier_support_t { const uint64_t *order; uint32_t count; }; struct i915_device { - uint32_t gen; + uint32_t graphics_version; int32_t has_llc; int32_t has_hw_protection; struct modifier_support_t modifier; int device_id; - bool is_adlp; + bool is_xelpd; + /*TODO : cleanup is_mtl to avoid adding variables for every new platforms */ + bool is_mtl; + int32_t num_fences_avail; + bool has_mmap_offset; }; static void i915_info_from_device_id(struct i915_device *i915) @@ -103,72 +110,91 @@ static void i915_info_from_device_id(struct i915_device *i915) 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 }; + 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 }; + + const uint16_t rplp_ids[] = { 0xA720, 0xA721, 0xA7A0, 0xA7A1, 0xA7A8, 0xA7A9 }; + + const uint16_t mtl_ids[] = { 0x7D40, 0x7D60, 0x7D45, 0x7D55, 0x7DD5 }; + unsigned i; - i915->gen = 4; - i915->is_adlp = false; + i915->graphics_version = 4; + i915->is_xelpd = false; + i915->is_mtl = false; for (i = 0; i < ARRAY_SIZE(gen3_ids); i++) if (gen3_ids[i] == i915->device_id) - i915->gen = 3; + i915->graphics_version = 3; /* Gen 4 */ for (i = 0; i < ARRAY_SIZE(gen4_ids); i++) if (gen4_ids[i] == i915->device_id) - i915->gen = 4; + i915->graphics_version = 4; /* Gen 5 */ for (i = 0; i < ARRAY_SIZE(gen5_ids); i++) if (gen5_ids[i] == i915->device_id) - i915->gen = 5; + i915->graphics_version = 5; /* Gen 6 */ for (i = 0; i < ARRAY_SIZE(gen6_ids); i++) if (gen6_ids[i] == i915->device_id) - i915->gen = 6; + i915->graphics_version = 6; /* Gen 7 */ for (i = 0; i < ARRAY_SIZE(gen7_ids); i++) if (gen7_ids[i] == i915->device_id) - i915->gen = 7; + i915->graphics_version = 7; /* Gen 8 */ for (i = 0; i < ARRAY_SIZE(gen8_ids); i++) if (gen8_ids[i] == i915->device_id) - i915->gen = 8; + i915->graphics_version = 8; /* Gen 9 */ for (i = 0; i < ARRAY_SIZE(gen9_ids); i++) if (gen9_ids[i] == i915->device_id) - i915->gen = 9; + i915->graphics_version = 9; /* Gen 11 */ for (i = 0; i < ARRAY_SIZE(gen11_ids); i++) if (gen11_ids[i] == i915->device_id) - i915->gen = 11; + i915->graphics_version = 11; /* Gen 12 */ for (i = 0; i < ARRAY_SIZE(gen12_ids); i++) if (gen12_ids[i] == i915->device_id) - i915->gen = 12; + i915->graphics_version = 12; for (i = 0; i < ARRAY_SIZE(adlp_ids); i++) if (adlp_ids[i] == i915->device_id) { - i915->is_adlp = true; - i915->gen = 12; + i915->is_xelpd = true; + i915->graphics_version = 12; + } + + for (i = 0; i < ARRAY_SIZE(rplp_ids); i++) + if (rplp_ids[i] == i915->device_id) { + i915->is_xelpd = true; + i915->graphics_version = 12; + } + + for (i = 0; i < ARRAY_SIZE(mtl_ids); i++) + if (mtl_ids[i] == i915->device_id) { + i915->graphics_version = 12; + i915->is_mtl = true; } } static void i915_get_modifier_order(struct i915_device *i915) { - if (i915->gen == 12) { + if (i915->is_mtl) { + i915->modifier.order = xe_lpdp_modifier_order; + i915->modifier.count = ARRAY_SIZE(xe_lpdp_modifier_order); + } else if (i915->graphics_version == 12) { i915->modifier.order = gen12_modifier_order; i915->modifier.count = ARRAY_SIZE(gen12_modifier_order); - } - else if (i915->gen == 11) { + } else if (i915->graphics_version == 11) { i915->modifier.order = gen11_modifier_order; i915->modifier.count = ARRAY_SIZE(gen11_modifier_order); } else { @@ -229,7 +255,8 @@ static int i915_add_combinations(struct driver *drv) */ drv_modify_combination(drv, DRM_FORMAT_R8, &metadata_linear, 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_GPU_DATA_BUFFER | + BO_USE_SENSOR_DIRECT_DATA); const uint64_t render_not_linear = unset_flags(render, linear_mask); const uint64_t scanout_and_render_not_linear = render_not_linear | BO_USE_SCANOUT; @@ -243,34 +270,57 @@ static int i915_add_combinations(struct driver *drv) drv_add_combinations(drv, scanout_render_formats, ARRAY_SIZE(scanout_render_formats), &metadata_x_tiled, scanout_and_render_not_linear); - struct format_metadata metadata_y_tiled = { .tiling = I915_TILING_Y, - .priority = 3, - .modifier = I915_FORMAT_MOD_Y_TILED }; - + if (i915->is_mtl) { + struct format_metadata metadata_4_tiled = { .tiling = I915_TILING_4, + .priority = 3, + .modifier = I915_FORMAT_MOD_4_TILED }; +/* Support tile4 NV12 and P010 for libva */ +#ifdef I915_SCANOUT_4_TILED + const uint64_t nv12_usage = + BO_USE_TEXTURE | BO_USE_HW_VIDEO_DECODER | BO_USE_SCANOUT | hw_protected; + const uint64_t p010_usage = + BO_USE_TEXTURE | BO_USE_HW_VIDEO_DECODER | hw_protected | BO_USE_SCANOUT; +#else + 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_4_tiled, nv12_usage); + drv_add_combination(drv, DRM_FORMAT_P010, &metadata_4_tiled, p010_usage); + drv_add_combinations(drv, render_formats, ARRAY_SIZE(render_formats), + &metadata_4_tiled, render_not_linear); + drv_add_combinations(drv, scanout_render_formats, + ARRAY_SIZE(scanout_render_formats), &metadata_4_tiled, + render_not_linear); + } else { + 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 = - BO_USE_TEXTURE | BO_USE_HW_VIDEO_DECODER | BO_USE_SCANOUT | hw_protected; - const uint64_t p010_usage = BO_USE_TEXTURE | BO_USE_HW_VIDEO_DECODER | hw_protected | - (i915->gen >= 11 ? BO_USE_SCANOUT : 0); + const uint64_t nv12_usage = + BO_USE_TEXTURE | BO_USE_HW_VIDEO_DECODER | BO_USE_SCANOUT | hw_protected; + const uint64_t p010_usage = BO_USE_TEXTURE | BO_USE_HW_VIDEO_DECODER | + hw_protected | + (i915->graphics_version >= 11 ? BO_USE_SCANOUT : 0); #else - const uint64_t nv12_usage = BO_USE_TEXTURE | BO_USE_HW_VIDEO_DECODER; - const uint64_t p010_usage = nv12_usage; + 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); - - 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 - // |scanout_render_formats| without that USE flag. - 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); + 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 + * |scanout_render_formats| without that USE flag. + */ + drv_add_combinations(drv, scanout_render_formats, + ARRAY_SIZE(scanout_render_formats), &metadata_y_tiled, + render_not_linear); + } return 0; } -static int i915_align_dimensions(struct bo *bo, uint32_t tiling, uint32_t *stride, +static int i915_align_dimensions(struct bo *bo, uint32_t format, uint32_t tiling, uint32_t *stride, uint32_t *aligned_height) { struct i915_device *i915 = bo->drv->priv; @@ -296,7 +346,24 @@ static int i915_align_dimensions(struct bo *bo, uint32_t tiling, uint32_t *strid #else horizontal_alignment = 64; #endif - vertical_alignment = 4; + /* + * For R8 and height=1, we assume the surface will be used as a linear buffer blob + * (such as VkBuffer). The hardware allows vertical_alignment=1 only for non-tiled + * 1D surfaces, which covers the VkBuffer case. However, if the app uses the surface + * as a 2D image with height=1, then this code is buggy. For 2D images, the hardware + * requires a vertical_alignment >= 4, and underallocating with vertical_alignment=1 + * will cause the GPU to read out-of-bounds. + * + * TODO: add a new DRM_FORMAT_BLOB format for this case, or further tighten up the + * constraints with GPU_DATA_BUFFER usage when the guest has migrated to use + * virtgpu_cross_domain backend which passes that flag through. + */ + if (format == DRM_FORMAT_R8 && *aligned_height == 1) { + vertical_alignment = 1; + } else { + vertical_alignment = 4; + } + break; case I915_TILING_X: @@ -305,7 +372,8 @@ static int i915_align_dimensions(struct bo *bo, uint32_t tiling, uint32_t *strid break; case I915_TILING_Y: - if (i915->gen == 3) { + case I915_TILING_4: + if (i915->graphics_version == 3) { horizontal_alignment = 512; vertical_alignment = 8; } else { @@ -316,7 +384,7 @@ static int i915_align_dimensions(struct bo *bo, uint32_t tiling, uint32_t *strid } *aligned_height = ALIGN(*aligned_height, vertical_alignment); - if (i915->gen > 3) { + if (i915->graphics_version > 3) { *stride = ALIGN(*stride, horizontal_alignment); } else { while (*stride > horizontal_alignment) @@ -325,7 +393,7 @@ static int i915_align_dimensions(struct bo *bo, uint32_t tiling, uint32_t *strid *stride = horizontal_alignment; } - if (i915->gen <= 3 && *stride > 8192) + if (i915->graphics_version <= 3 && *stride > 8192) return -EINVAL; return 0; @@ -345,7 +413,7 @@ static void i915_clflush(void *start, size_t size) static int i915_init(struct driver *drv) { - int ret; + int ret, val; struct i915_device *i915; drm_i915_getparam_t get_param = { 0 }; @@ -357,11 +425,11 @@ static int i915_init(struct driver *drv) get_param.value = &(i915->device_id); ret = drmIoctl(drv->fd, DRM_IOCTL_I915_GETPARAM, &get_param); if (ret) { - drv_log("Failed to get I915_PARAM_CHIPSET_ID\n"); + drv_loge("Failed to get I915_PARAM_CHIPSET_ID\n"); free(i915); return -EINVAL; } - /* must call before i915->gen is used anywhere else */ + /* must call before i915->graphics_version is used anywhere else */ i915_info_from_device_id(i915); i915_get_modifier_order(i915); @@ -371,12 +439,34 @@ static int i915_init(struct driver *drv) get_param.value = &i915->has_llc; ret = drmIoctl(drv->fd, DRM_IOCTL_I915_GETPARAM, &get_param); if (ret) { - drv_log("Failed to get I915_PARAM_HAS_LLC\n"); + drv_loge("Failed to get I915_PARAM_HAS_LLC\n"); + free(i915); + return -EINVAL; + } + + memset(&get_param, 0, sizeof(get_param)); + get_param.param = I915_PARAM_NUM_FENCES_AVAIL; + get_param.value = &i915->num_fences_avail; + ret = drmIoctl(drv->fd, DRM_IOCTL_I915_GETPARAM, &get_param); + if (ret) { + drv_loge("Failed to get I915_PARAM_NUM_FENCES_AVAIL\n"); + free(i915); + return -EINVAL; + } + + memset(&get_param, 0, sizeof(get_param)); + get_param.param = I915_PARAM_MMAP_GTT_VERSION; + get_param.value = &val; + + ret = drmIoctl(drv->fd, DRM_IOCTL_I915_GETPARAM, &get_param); + if (ret) { + drv_loge("Failed to get I915_PARAM_MMAP_GTT_VERSION\n"); free(i915); return -EINVAL; } + i915->has_mmap_offset = (val >= 4); - if (i915->gen >= 12) + if (i915->graphics_version >= 12) i915->has_hw_protection = 1; drv->priv = i915; @@ -395,7 +485,7 @@ static bool i915_format_needs_LCU_alignment(uint32_t format, size_t plane, case DRM_FORMAT_NV12: case DRM_FORMAT_P010: case DRM_FORMAT_P016: - return (i915->gen == 11 || i915->gen == 12) && plane == 1; + return (i915->graphics_version == 11 || i915->graphics_version == 12) && plane == 1; } return false; } @@ -417,7 +507,7 @@ static int i915_bo_from_format(struct bo *bo, uint32_t width, uint32_t height, u if (bo->meta.tiling != I915_TILING_NONE) assert(IS_ALIGNED(offset, pagesize)); - ret = i915_align_dimensions(bo, bo->meta.tiling, &stride, &plane_height); + ret = i915_align_dimensions(bo, format, bo->meta.tiling, &stride, &plane_height); if (ret) return ret; @@ -441,8 +531,7 @@ 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) +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 || @@ -459,7 +548,7 @@ static int i915_bo_compute_metadata(struct bo *bo, uint32_t width, uint32_t heig { uint64_t modifier; struct i915_device *i915 = bo->drv->priv; - bool huge_bo = (i915->gen < 11) && (width > 4096); + bool huge_bo = (i915->graphics_version < 11) && (width > 4096); if (modifiers) { modifier = @@ -505,7 +594,7 @@ static int i915_bo_compute_metadata(struct bo *bo, uint32_t width, uint32_t heig } /* Prevent gen 8 and earlier from trying to use a tiling modifier */ - if (i915->gen <= 8 && format == DRM_FORMAT_ARGB8888) { + if (i915->graphics_version <= 8 && format == DRM_FORMAT_ARGB8888) { modifier = DRM_FORMAT_MOD_LINEAR; } @@ -524,6 +613,9 @@ static int i915_bo_compute_metadata(struct bo *bo, uint32_t width, uint32_t heig case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS: bo->meta.tiling = I915_TILING_Y; break; + case I915_FORMAT_MOD_4_TILED: + bo->meta.tiling = I915_TILING_4; + break; } bo->meta.format_modifier = modifier; @@ -538,7 +630,7 @@ static int i915_bo_compute_metadata(struct bo *bo, uint32_t width, uint32_t heig * aligning to 32 bytes here. */ uint32_t stride = ALIGN(width, 32); - drv_bo_from_format(bo, stride, height, format); + return drv_bo_from_format(bo, stride, 1, height, format); } else if (modifier == I915_FORMAT_MOD_Y_TILED_CCS) { /* * For compressed surfaces, we need a color control surface @@ -593,7 +685,7 @@ static int i915_bo_compute_metadata(struct bo *bo, uint32_t width, uint32_t heig height = ALIGN(drv_height_from_format(format, height, 0), 32); - if (i915->is_adlp && (stride > 1)) { + if (i915->is_xelpd && (stride > 1)) { stride = 1 << (32 - __builtin_clz(stride - 1)); height = ALIGN(drv_height_from_format(format, height, 0), 128); } @@ -616,7 +708,7 @@ static int i915_bo_compute_metadata(struct bo *bo, uint32_t width, uint32_t heig 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); + return i915_bo_from_format(bo, width, height, format); } return 0; } @@ -642,8 +734,8 @@ static int i915_bo_create_from_metadata(struct bo *bo) 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) (ret=%d) \n", - create_ext.size, ret); + drv_loge("DRM_IOCTL_I915_GEM_CREATE_EXT failed (size=%llu) (ret=%d) \n", + create_ext.size, ret); return -errno; } @@ -653,7 +745,7 @@ static int i915_bo_create_from_metadata(struct bo *bo) gem_create.size = bo->meta.total_size; ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_CREATE, &gem_create); if (ret) { - drv_log("DRM_IOCTL_I915_GEM_CREATE failed (size=%llu)\n", gem_create.size); + drv_loge("DRM_IOCTL_I915_GEM_CREATE failed (size=%llu)\n", gem_create.size); return -errno; } @@ -663,20 +755,24 @@ static int i915_bo_create_from_metadata(struct bo *bo) for (plane = 0; plane < bo->meta.num_planes; plane++) bo->handles[plane].u32 = gem_handle; - gem_set_tiling.handle = bo->handles[0].u32; - gem_set_tiling.tiling_mode = bo->meta.tiling; - gem_set_tiling.stride = bo->meta.strides[0]; + /* Set/Get tiling ioctl not supported based on fence availability + Refer : "https://patchwork.freedesktop.org/patch/325343/" + */ + if (i915->num_fences_avail) { + gem_set_tiling.handle = bo->handles[0].u32; + gem_set_tiling.tiling_mode = bo->meta.tiling; + gem_set_tiling.stride = bo->meta.strides[0]; - ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_SET_TILING, &gem_set_tiling); - if (ret) { - struct drm_gem_close gem_close = { 0 }; - gem_close.handle = bo->handles[0].u32; - drmIoctl(bo->drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close); + ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_SET_TILING, &gem_set_tiling); + if (ret) { + struct drm_gem_close gem_close = { 0 }; + gem_close.handle = bo->handles[0].u32; + drmIoctl(bo->drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close); - drv_log("DRM_IOCTL_I915_GEM_SET_TILING failed with %d\n", errno); - return -errno; + drv_loge("DRM_IOCTL_I915_GEM_SET_TILING failed with %d\n", errno); + return -errno; + } } - return 0; } @@ -690,68 +786,85 @@ 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 }; + struct i915_device *i915 = bo->drv->priv; - bo->meta.num_planes = i915_num_planes_from_modifier(bo->drv, data->format, - data->format_modifier); + 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; - /* TODO(gsingh): export modifiers and get rid of backdoor tiling. */ - gem_get_tiling.handle = bo->handles[0].u32; + /* Set/Get tiling ioctl not supported based on fence availability + Refer : "https://patchwork.freedesktop.org/patch/325343/" + */ + if (i915->num_fences_avail) { + /* TODO(gsingh): export modifiers and get rid of backdoor tiling. */ + gem_get_tiling.handle = bo->handles[0].u32; - ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_GET_TILING, &gem_get_tiling); - if (ret) { - drv_gem_bo_destroy(bo); - drv_log("DRM_IOCTL_I915_GEM_GET_TILING failed.\n"); - return ret; + ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_GET_TILING, &gem_get_tiling); + if (ret) { + drv_gem_bo_destroy(bo); + drv_loge("DRM_IOCTL_I915_GEM_GET_TILING failed.\n"); + return ret; + } + bo->meta.tiling = gem_get_tiling.tiling_mode; } - - bo->meta.tiling = gem_get_tiling.tiling_mode; return 0; } -static void *i915_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags) +static void *i915_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags) { int ret; void *addr = MAP_FAILED; + struct i915_device *i915 = bo->drv->priv; - 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) + 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_4_TILED)) 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 - * detect the use cases for which WC mapping is really needed. - * The current heuristic seems overly coarse and may be slowing - * down some other use cases unnecessarily. - * - * For now, care must be taken not to use WC mappings for - * Renderscript and camera use cases, as they're - * performance-sensitive. */ - if ((bo->meta.use_flags & BO_USE_SCANOUT) && - !(bo->meta.use_flags & - (BO_USE_RENDERSCRIPT | BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE))) - gem_map.flags = I915_MMAP_WC; - - gem_map.handle = bo->handles[0].u32; - gem_map.offset = 0; - gem_map.size = bo->meta.total_size; - - ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_MMAP, &gem_map); - /* DRM_IOCTL_I915_GEM_MMAP mmaps the underlying shm - * file and returns a user space address directly, ie, - * doesn't go through mmap. If we try that on a - * dma-buf that doesn't have a shm file, i915.ko - * returns ENXIO. Fall through to - * DRM_IOCTL_I915_GEM_MMAP_GTT in that case, which - * will mmap on the drm fd instead. */ - if (ret == 0) - addr = (void *)(uintptr_t)gem_map.addr_ptr; + if (i915->has_mmap_offset) { + struct drm_i915_gem_mmap_offset gem_map = { 0 }; + gem_map.handle = bo->handles[0].u32; + gem_map.flags = I915_MMAP_OFFSET_WB; + + /* Get the fake offset back */ + ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_MMAP_OFFSET, &gem_map); + if (ret == 0) + addr = mmap(0, bo->meta.total_size, drv_get_prot(map_flags), + MAP_SHARED, bo->drv->fd, gem_map.offset); + } else { + struct drm_i915_gem_mmap gem_map = { 0 }; + /* TODO(b/118799155): We don't seem to have a good way to + * detect the use cases for which WC mapping is really needed. + * The current heuristic seems overly coarse and may be slowing + * down some other use cases unnecessarily. + * + * For now, care must be taken not to use WC mappings for + * Renderscript and camera use cases, as they're + * performance-sensitive. */ + if ((bo->meta.use_flags & BO_USE_SCANOUT) && + !(bo->meta.use_flags & + (BO_USE_RENDERSCRIPT | BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE))) + gem_map.flags = I915_MMAP_WC; + + gem_map.handle = bo->handles[0].u32; + gem_map.offset = 0; + gem_map.size = bo->meta.total_size; + + ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_MMAP, &gem_map); + /* DRM_IOCTL_I915_GEM_MMAP mmaps the underlying shm + * file and returns a user space address directly, ie, + * doesn't go through mmap. If we try that on a + * dma-buf that doesn't have a shm file, i915.ko + * returns ENXIO. Fall through to + * DRM_IOCTL_I915_GEM_MMAP_GTT in that case, which + * will mmap on the drm fd instead. */ + if (ret == 0) + addr = (void *)(uintptr_t)gem_map.addr_ptr; + } } if (addr == MAP_FAILED) { @@ -760,7 +873,7 @@ static void *i915_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t gem_map.handle = bo->handles[0].u32; ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_MMAP_GTT, &gem_map); if (ret) { - drv_log("DRM_IOCTL_I915_GEM_MMAP_GTT failed\n"); + drv_loge("DRM_IOCTL_I915_GEM_MMAP_GTT failed\n"); return MAP_FAILED; } @@ -769,7 +882,7 @@ static void *i915_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t } if (addr == MAP_FAILED) { - drv_log("i915 GEM mmap failed\n"); + drv_loge("i915 GEM mmap failed\n"); return addr; } @@ -795,7 +908,7 @@ static int i915_bo_invalidate(struct bo *bo, struct mapping *mapping) ret = drmIoctl(bo->drv->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain); if (ret) { - drv_log("DRM_IOCTL_I915_GEM_SET_DOMAIN with %d\n", ret); + drv_loge("DRM_IOCTL_I915_GEM_SET_DOMAIN with %d\n", ret); return ret; } @@ -25,17 +25,34 @@ #define TILE_TYPE_LINEAR 0 -#if defined(MTK_MT8183) || defined(MTK_MT8186) -#define SUPPORTS_YUV422_AND_HIGH_BIT_DEPTH_TEXTURING +// clang-format off +#if defined(MTK_MT8183) || \ + defined(MTK_MT8186) +// clang-format on +#define SUPPORTS_YUV422 #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) +// clang-format off +#if defined(MTK_MT8183) || \ + defined(MTK_MT8186) || \ + defined(MTK_MT8188G) || \ + defined(MTK_MT8192) || \ + defined(MTK_MT8195) +// clang-format on #define USE_NV12_FOR_HW_VIDEO_DECODING #else #define DONT_USE_64_ALIGNMENT_FOR_VIDEO_BUFFERS #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 +// chroma plane. +#if defined(MTK_MT8186) +#define USE_EXTRA_PADDING_FOR_YVU420 +#endif + struct mediatek_private_map_data { void *cached_addr; void *gem_addr; @@ -48,12 +65,12 @@ static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMA // clang-format off static const uint32_t texture_source_formats[] = { -#ifdef SUPPORTS_YUV422_AND_HIGH_BIT_DEPTH_TEXTURING +#ifdef SUPPORTS_YUV422 DRM_FORMAT_NV21, DRM_FORMAT_YUYV, +#endif DRM_FORMAT_ABGR2101010, DRM_FORMAT_ABGR16161616F, -#endif DRM_FORMAT_NV12, DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID @@ -62,6 +79,7 @@ static const uint32_t texture_source_formats[] = { static const uint32_t video_yuv_formats[] = { DRM_FORMAT_NV21, DRM_FORMAT_NV12, + DRM_FORMAT_YUYV, DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID }; @@ -89,6 +107,11 @@ static int mediatek_init(struct driver *drv) drv_add_combination(drv, DRM_FORMAT_R8, &LINEAR_METADATA, BO_USE_SW_MASK | BO_USE_LINEAR); + /* YUYV format for video overlay and camera subsystem. */ + drv_add_combination(drv, DRM_FORMAT_YUYV, &LINEAR_METADATA, + BO_USE_HW_VIDEO_DECODER | BO_USE_SCANOUT | BO_USE_LINEAR | + BO_USE_TEXTURE); + /* Android CTS tests require this. */ drv_add_combination(drv, DRM_FORMAT_BGR888, &LINEAR_METADATA, BO_USE_SW_MASK); @@ -109,7 +132,8 @@ static int mediatek_init(struct driver *drv) */ drv_modify_combination(drv, DRM_FORMAT_R8, &metadata, BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER | - BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE); + BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | + BO_USE_GPU_DATA_BUFFER | BO_USE_SENSOR_DIRECT_DATA); /* NV12 format for encoding and display. */ drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata, @@ -149,7 +173,7 @@ static int mediatek_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint if (!drv_has_modifier(modifiers, count, DRM_FORMAT_MOD_LINEAR)) { errno = EINVAL; - drv_log("no usable modifier found\n"); + drv_loge("no usable modifier found\n"); return -EINVAL; } @@ -177,9 +201,9 @@ static int mediatek_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint (32 / drv_vertical_subsampling_from_format(format, plane)); } - drv_bo_from_format_and_padding(bo, stride, aligned_height, format, padding); + drv_bo_from_format_and_padding(bo, stride, 1, aligned_height, format, padding); } else { -#ifdef SUPPORTS_YUV422_AND_HIGH_BIT_DEPTH_TEXTURING +#ifdef SUPPORTS_YUV422 /* * JPEG Encoder Accelerator requires 16x16 alignment. We want the buffer * from camera can be put in JEA directly so align the height to 16 @@ -188,14 +212,43 @@ static int mediatek_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint if (format == DRM_FORMAT_NV12) height = ALIGN(height, 16); #endif - drv_bo_from_format(bo, stride, height, format); + drv_bo_from_format(bo, stride, 1, height, format); + +#ifdef USE_EXTRA_PADDING_FOR_YVU420 + /* + * Apply extra padding for YV12 if the height does not meet round up requirement and + * the image is to be sampled by gpu. + */ + static const uint32_t required_round_up = 4; + const uint32_t height_mod = height % required_round_up; + if ((format == DRM_FORMAT_YVU420 || format == DRM_FORMAT_YVU420_ANDROID) && + (bo->meta.use_flags & BO_USE_TEXTURE) && height_mod) { + const uint32_t height_padding = required_round_up - height_mod; + const uint32_t u_padding = + drv_size_from_format(format, bo->meta.strides[2], height_padding, 2); + + bo->meta.total_size += u_padding; + + /* + * Since we are not aligning Y, we must make sure that its padding fits + * inside the rest of the space allocated for the V/U planes. + */ + const uint32_t y_padding = + drv_size_from_format(format, bo->meta.strides[0], height_padding, 0); + const uint32_t vu_size = drv_bo_get_plane_size(bo, 2) * 2; + if (y_padding > vu_size) { + /* Align with mali workaround to pad all 3 planes. */ + bo->meta.total_size += y_padding + u_padding; + } + } +#endif } gem_create.size = bo->meta.total_size; ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MTK_GEM_CREATE, &gem_create); if (ret) { - drv_log("DRM_IOCTL_MTK_GEM_CREATE failed (size=%" PRIu64 ")\n", gem_create.size); + drv_loge("DRM_IOCTL_MTK_GEM_CREATE failed (size=%" PRIu64 ")\n", gem_create.size); return -errno; } @@ -213,7 +266,7 @@ static int mediatek_bo_create(struct bo *bo, uint32_t width, uint32_t height, ui ARRAY_SIZE(modifiers)); } -static void *mediatek_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags) +static void *mediatek_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags) { int ret, prime_fd; struct drm_mtk_gem_map_off gem_map = { 0 }; @@ -224,13 +277,13 @@ static void *mediatek_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint3 ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MTK_GEM_MAP_OFFSET, &gem_map); if (ret) { - drv_log("DRM_IOCTL_MTK_GEM_MAP_OFFSET failed\n"); + drv_loge("DRM_IOCTL_MTK_GEM_MAP_OFFSET failed\n"); return MAP_FAILED; } prime_fd = drv_bo_get_plane_fd(bo, 0); if (prime_fd < 0) { - drv_log("Failed to get a prime fd\n"); + drv_loge("Failed to get a prime fd\n"); return MAP_FAILED; } @@ -303,7 +356,7 @@ static int mediatek_bo_invalidate(struct bo *bo, struct mapping *mapping) poll(&fds, 1, -1); if (fds.revents != fds.events) - drv_log("poll prime_fd failed\n"); + drv_loge("poll prime_fd failed\n"); if (priv->cached_addr) memcpy(priv->cached_addr, priv->gem_addr, bo->meta.total_size); diff --git a/minigbm_helpers.c b/minigbm_helpers.c index cea0b48..d1da7c4 100644 --- a/minigbm_helpers.c +++ b/minigbm_helpers.c @@ -17,6 +17,7 @@ #include <xf86drm.h> #include <xf86drmMode.h> +#include "gbm.h" #include "minigbm_helpers.h" #include "util.h" @@ -210,7 +211,7 @@ done: return 0; } -PUBLIC int gbm_get_default_device_fd(void) +static int gbm_get_default_device_fd(void) { DIR *dir; int ret, fd, dfd = -1; @@ -312,3 +313,63 @@ PUBLIC int gbm_detect_device_info_path(unsigned int detect_flags, const char *de close(fd); return ret; } + +static struct gbm_device *try_drm_devices(drmDevicePtr *devs, int dev_count, int type, int *out_fd) +{ + int i; + + for (i = 0; i < dev_count; i++) { + drmDevicePtr dev = devs[i]; + int fd; + + if (!(dev->available_nodes & (1 << type))) + continue; + + fd = open(dev->nodes[type], O_RDWR | O_CLOEXEC); + if (fd >= 0) { + struct gbm_device *gbm = gbm_create_device(fd); + if (gbm) { + // DRM master might be taken by accident on a primary node even + // if master is not needed for GBM. Drop it so that programs + // that actually need DRM master (e.g. Chrome) won't be blocked. + if (type == DRM_NODE_PRIMARY && drmIsMaster(fd)) + drmDropMaster(fd); + *out_fd = fd; + return gbm; + } + close(fd); + } + } + + return NULL; +} + +PUBLIC struct gbm_device *minigbm_create_default_device(int *out_fd) +{ + struct gbm_device *gbm; + drmDevicePtr devs[64]; + int dev_count; + int fd; + + /* try gbm_get_default_device_fd first */ + fd = gbm_get_default_device_fd(); + if (fd >= 0) { + gbm = gbm_create_device(fd); + if (gbm) { + *out_fd = fd; + return gbm; + } + close(fd); + } + + dev_count = drmGetDevices2(0, devs, sizeof(devs) / sizeof(devs[0])); + + /* try render nodes and then primary nodes */ + gbm = try_drm_devices(devs, dev_count, DRM_NODE_RENDER, out_fd); + if (!gbm) + gbm = try_drm_devices(devs, dev_count, DRM_NODE_PRIMARY, out_fd); + + drmFreeDevices(devs, dev_count); + + return gbm; +} diff --git a/minigbm_helpers.h b/minigbm_helpers.h index 08e6283..dbbb644 100644 --- a/minigbm_helpers.h +++ b/minigbm_helpers.h @@ -6,6 +6,8 @@ #ifndef _MINIGBM_HELPERS_H_ #define _MINIGBM_HELPERS_H_ +#include <stdint.h> + #ifdef __cplusplus extern "C" { #endif @@ -18,6 +20,8 @@ extern "C" { #define GBM_DEV_TYPE_FLAG_BLOCKED (1u << 5) /* Unsuitable device e.g. vgem, udl, evdi. */ #define GBM_DEV_TYPE_FLAG_INTERNAL_LCD (1u << 6) /* Device is driving internal LCD. */ +struct gbm_device; + struct gbm_device_info { uint32_t dev_type_flags; int dri_node_num; /* DRI node number (0..63), for easy matching of devices. */ @@ -32,9 +36,9 @@ int gbm_detect_device_info_path(unsigned int detect_flags, const char *dev_node, struct gbm_device_info *info); /* - * Select "default" device to use for graphics memory allocator. + * Create "default" gbm device. */ -int gbm_get_default_device_fd(void); +struct gbm_device *minigbm_create_default_device(int *out_fd); #ifdef __cplusplus } @@ -36,9 +36,9 @@ #define MSM_UBWC_TILING 1 -static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888, - DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888, - DRM_FORMAT_XRGB8888, DRM_FORMAT_ABGR2101010, +static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888, + DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888, + DRM_FORMAT_XRGB8888, DRM_FORMAT_ABGR2101010, DRM_FORMAT_ABGR16161616F }; static const uint32_t texture_source_formats[] = { DRM_FORMAT_NV12, DRM_FORMAT_R8, @@ -73,6 +73,8 @@ static unsigned get_pitch_alignment(struct bo *bo) switch (bo->meta.format) { case DRM_FORMAT_NV12: return VENUS_STRIDE_ALIGN; + case DRM_FORMAT_P010: + return VENUS_STRIDE_ALIGN * 2; case DRM_FORMAT_YVU420: case DRM_FORMAT_YVU420_ANDROID: /* TODO other YUV formats? */ @@ -105,8 +107,8 @@ static void msm_calculate_layout(struct bo *bo) if (bo->meta.format == DRM_FORMAT_P010) width *= 2; - y_stride = ALIGN(width, VENUS_STRIDE_ALIGN); - uv_stride = ALIGN(width, VENUS_STRIDE_ALIGN); + y_stride = ALIGN(width, get_pitch_alignment(bo)); + uv_stride = ALIGN(width, get_pitch_alignment(bo)); y_scanline = ALIGN(height, VENUS_SCANLINE_ALIGN * 2); uv_scanline = ALIGN(DIV_ROUND_UP(height, 2), VENUS_SCANLINE_ALIGN * (bo->meta.tiling ? 2 : 1)); @@ -138,7 +140,9 @@ static void msm_calculate_layout(struct bo *bo) DRM_FORMAT_R8 of height one is used for JPEG camera output, so don't height align that. */ if (bo->meta.format == DRM_FORMAT_YVU420_ANDROID || + bo->meta.format == DRM_FORMAT_YVU420 || (bo->meta.format == DRM_FORMAT_R8 && height == 1)) { + assert(bo->meta.tiling != MSM_UBWC_TILING); alignh = height; } else { alignh = ALIGN(height, DEFAULT_ALIGNMENT); @@ -147,7 +151,7 @@ static void msm_calculate_layout(struct bo *bo) stride = drv_stride_from_format(bo->meta.format, alignw, 0); /* Calculate size and assign stride, size, offset to each plane based on format */ - drv_bo_from_format(bo, stride, alignh, bo->meta.format); + drv_bo_from_format(bo, stride, 1, alignh, bo->meta.format); /* For all RGB UBWC formats */ if (bo->meta.tiling == MSM_UBWC_TILING) { @@ -204,22 +208,7 @@ static bool should_avoid_ubwc(void) * See b/163137550 */ if (dlsym(RTLD_DEFAULT, "waffle_display_connect")) { - drv_log("WARNING: waffle detected, disabling UBWC\n"); - return true; - } - - /* 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/229147702 - */ - if (!dlsym(RTLD_DEFAULT, "cupsFilePrintf")) { - drv_log("WARNING: virtualization detected, disabling UBWC\n"); + drv_logi("WARNING: waffle detected, disabling UBWC\n"); return true; } #endif @@ -258,7 +247,8 @@ static int msm_init(struct driver *drv) */ 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_GPU_DATA_BUFFER | + BO_USE_SENSOR_DIRECT_DATA); /* * Android also frequently requests YV12 formats for some camera implementations @@ -266,6 +256,8 @@ static int msm_init(struct driver *drv) */ drv_modify_combination(drv, DRM_FORMAT_YVU420_ANDROID, &LINEAR_METADATA, BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE); + drv_modify_combination(drv, DRM_FORMAT_YVU420, &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); @@ -314,7 +306,7 @@ static int msm_bo_create_for_modifier(struct bo *bo, uint32_t width, uint32_t he ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MSM_GEM_NEW, &req); if (ret) { - drv_log("DRM_IOCTL_MSM_GEM_NEW failed with %s\n", strerror(errno)); + drv_loge("DRM_IOCTL_MSM_GEM_NEW failed with %s\n", strerror(errno)); return -errno; } @@ -353,22 +345,25 @@ static int msm_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_ struct combination *combo = drv_get_combination(bo->drv, format, flags); if (!combo) { - drv_log("invalid format = %d, flags = %" PRIx64 " combination\n", format, flags); + drv_loge("invalid format = %d, flags = %" PRIx64 " combination\n", format, flags); return -EINVAL; } return msm_bo_create_for_modifier(bo, width, height, format, combo->metadata.modifier); } -static void *msm_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags) +static void *msm_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags) { int ret; struct drm_msm_gem_info req = { 0 }; + if (bo->meta.format_modifier) + return MAP_FAILED; + req.handle = bo->handles[0].u32; ret = drmIoctl(bo->drv->fd, DRM_IOCTL_MSM_GEM_INFO, &req); if (ret) { - drv_log("DRM_IOCLT_MSM_GEM_INFO failed with %s\n", strerror(errno)); + drv_loge("DRM_IOCLT_MSM_GEM_INFO failed with %s\n", strerror(errno)); return MAP_FAILED; } vma->length = bo->meta.total_size; @@ -107,7 +107,8 @@ static int rockchip_init(struct driver *drv) */ drv_add_combination(drv, DRM_FORMAT_R8, &metadata, BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_SW_MASK | - BO_USE_LINEAR | BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER); + BO_USE_LINEAR | BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER | + BO_USE_GPU_DATA_BUFFER | BO_USE_SENSOR_DIRECT_DATA); return 0; } @@ -135,7 +136,7 @@ static int rockchip_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint uint32_t aligned_width = w_mbs * 16; uint32_t aligned_height = h_mbs * 16; - drv_bo_from_format(bo, aligned_width, aligned_height, format); + drv_bo_from_format(bo, aligned_width, 1, aligned_height, format); /* * drv_bo_from_format updates total_size. Add an extra data space for rockchip video * driver to store motion vectors. @@ -148,7 +149,7 @@ static int rockchip_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint } else { if (!drv_has_modifier(modifiers, count, DRM_FORMAT_MOD_LINEAR)) { errno = EINVAL; - drv_log("no usable modifier found\n"); + drv_loge("no usable modifier found\n"); return -errno; } @@ -165,15 +166,15 @@ static int rockchip_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint else stride = ALIGN(stride, 64); - drv_bo_from_format(bo, stride, height, format); + drv_bo_from_format(bo, stride, 1, height, format); } gem_create.size = bo->meta.total_size; ret = drmIoctl(bo->drv->fd, DRM_IOCTL_ROCKCHIP_GEM_CREATE, &gem_create); if (ret) { - drv_log("DRM_IOCTL_ROCKCHIP_GEM_CREATE failed (size=%" PRIu64 ")\n", - gem_create.size); + drv_loge("DRM_IOCTL_ROCKCHIP_GEM_CREATE failed (size=%" PRIu64 ")\n", + gem_create.size); return -errno; } @@ -191,7 +192,7 @@ static int rockchip_bo_create(struct bo *bo, uint32_t width, uint32_t height, ui ARRAY_SIZE(modifiers)); } -static void *rockchip_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags) +static void *rockchip_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags) { int ret; struct rockchip_private_map_data *priv; @@ -207,7 +208,7 @@ static void *rockchip_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint3 gem_map.handle = bo->handles[0].u32; ret = drmIoctl(bo->drv->fd, DRM_IOCTL_ROCKCHIP_GEM_MAP_OFFSET, &gem_map); if (ret) { - drv_log("DRM_IOCTL_ROCKCHIP_GEM_MAP_OFFSET failed\n"); + drv_loge("DRM_IOCTL_ROCKCHIP_GEM_MAP_OFFSET failed\n"); return MAP_FAILED; } @@ -52,7 +52,7 @@ static int vc4_bo_create_for_modifier(struct bo *bo, uint32_t width, uint32_t he case DRM_FORMAT_MOD_LINEAR: break; case DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED: - drv_log("DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED not supported yet\n"); + drv_loge("DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED not supported yet\n"); return -EINVAL; default: return -EINVAL; @@ -64,13 +64,13 @@ static int vc4_bo_create_for_modifier(struct bo *bo, uint32_t width, uint32_t he */ stride = drv_stride_from_format(format, width, 0); stride = ALIGN(stride, 64); - drv_bo_from_format(bo, stride, height, format); + drv_bo_from_format(bo, stride, 1, height, format); bo_create.size = bo->meta.total_size; ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VC4_CREATE_BO, &bo_create); if (ret) { - drv_log("DRM_IOCTL_VC4_CREATE_BO failed (size=%zu)\n", bo->meta.total_size); + drv_loge("DRM_IOCTL_VC4_CREATE_BO failed (size=%zu)\n", bo->meta.total_size); return -errno; } @@ -105,7 +105,7 @@ static int vc4_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint32_t return vc4_bo_create_for_modifier(bo, width, height, format, modifier); } -static void *vc4_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags) +static void *vc4_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags) { int ret; struct drm_vc4_mmap_bo bo_map = { 0 }; @@ -113,7 +113,7 @@ static void *vc4_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t m bo_map.handle = bo->handles[0].u32; ret = drmCommandWriteRead(bo->drv->fd, DRM_VC4_MMAP_BO, &bo_map, sizeof(bo_map)); if (ret) { - drv_log("DRM_VC4_MMAP_BO failed\n"); + drv_loge("DRM_VC4_MMAP_BO failed\n"); return MAP_FAILED; } @@ -48,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("virtgpu backend not enabling %s\n", params[i].name); + drv_logi("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 10930fc..45b5580 100644 --- a/virtgpu_cross_domain.c +++ b/virtgpu_cross_domain.c @@ -19,16 +19,16 @@ #define CAPSET_CROSS_DOMAIN 5 #define CAPSET_CROSS_FAKE 30 -static const uint32_t scanout_render_formats[] = { DRM_FORMAT_ABGR2101010, DRM_FORMAT_ABGR8888, - DRM_FORMAT_ARGB2101010, DRM_FORMAT_ARGB8888, - DRM_FORMAT_RGB565, DRM_FORMAT_XBGR2101010, - DRM_FORMAT_XBGR8888, DRM_FORMAT_XRGB2101010, +static const uint32_t scanout_render_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888, + DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888, DRM_FORMAT_XRGB8888 }; -static const uint32_t render_formats[] = { DRM_FORMAT_ABGR16161616F }; - -static const uint32_t texture_only_formats[] = { DRM_FORMAT_R8, DRM_FORMAT_NV12, DRM_FORMAT_P010, - DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID }; +static const uint32_t texture_only_formats[] = { + DRM_FORMAT_R8, DRM_FORMAT_NV12, DRM_FORMAT_P010, + DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID, DRM_FORMAT_ABGR2101010, + DRM_FORMAT_ARGB2101010, DRM_FORMAT_XBGR2101010, DRM_FORMAT_XRGB2101010, + DRM_FORMAT_ABGR16161616F +}; extern struct virtgpu_param params[]; @@ -53,8 +53,8 @@ static void cross_domain_release_private(struct driver *drv) ret = drmIoctl(drv->fd, DRM_IOCTL_GEM_CLOSE, &gem_close); if (ret) { - drv_log("DRM_IOCTL_GEM_CLOSE failed (handle=%x) error %d\n", - priv->ring_handle, ret); + drv_loge("DRM_IOCTL_GEM_CLOSE failed (handle=%x) error %d\n", + priv->ring_handle, ret); } } @@ -78,9 +78,6 @@ static void add_combinations(struct driver *drv) drv_add_combinations(drv, scanout_render_formats, ARRAY_SIZE(scanout_render_formats), &metadata, BO_USE_RENDER_MASK | BO_USE_SCANOUT); - drv_add_combinations(drv, render_formats, ARRAY_SIZE(render_formats), &metadata, - BO_USE_RENDER_MASK); - drv_add_combinations(drv, texture_only_formats, ARRAY_SIZE(texture_only_formats), &metadata, BO_USE_TEXTURE_MASK); @@ -89,15 +86,18 @@ static void add_combinations(struct driver *drv) drv_modify_combination(drv, DRM_FORMAT_YVU420, &metadata, BO_USE_HW_VIDEO_ENCODER); drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata, - BO_USE_HW_VIDEO_DECODER | BO_USE_SCANOUT | BO_USE_HW_VIDEO_ENCODER); + BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_DECODER | + BO_USE_SCANOUT | BO_USE_HW_VIDEO_ENCODER); /* * R8 format is used for Android's HAL_PIXEL_FORMAT_BLOB and is used for JPEG snapshots - * from camera and input/output from hardware decoder/encoder. + * from camera, input/output from hardware decoder/encoder and sensors, and + * AHBs used as SSBOs/UBOs. */ drv_modify_combination(drv, DRM_FORMAT_R8, &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); drv_modify_linear_combinations(drv); } @@ -109,17 +109,17 @@ static int cross_domain_submit_cmd(struct driver *drv, uint32_t *cmd, uint32_t c struct drm_virtgpu_execbuffer exec = { 0 }; struct cross_domain_private *priv = drv->priv; + exec.flags = VIRTGPU_EXECBUF_RING_IDX; exec.command = (uint64_t)&cmd[0]; exec.size = cmd_size; if (wait) { - exec.flags = VIRTGPU_EXECBUF_RING_IDX; exec.bo_handles = (uint64_t)&priv->ring_handle; exec.num_bo_handles = 1; } ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_EXECBUFFER, &exec); if (ret < 0) { - drv_log("DRM_IOCTL_VIRTGPU_EXECBUFFER failed with %s\n", strerror(errno)); + drv_loge("DRM_IOCTL_VIRTGPU_EXECBUFFER failed with %s\n", strerror(errno)); return -EINVAL; } @@ -130,7 +130,7 @@ static int cross_domain_submit_cmd(struct driver *drv, uint32_t *cmd, uint32_t c } if (ret < 0) { - drv_log("DRM_IOCTL_VIRTGPU_WAIT failed with %s\n", strerror(errno)); + drv_loge("DRM_IOCTL_VIRTGPU_WAIT failed with %s\n", strerror(errno)); return ret; } @@ -212,6 +212,22 @@ out_unlock: return ret; } +/* Fill out metadata for guest buffers, used only for CPU access: */ +void cross_domain_get_emulated_metadata(struct bo_metadata *metadata) +{ + uint32_t offset = 0; + + for (size_t i = 0; i < metadata->num_planes; i++) { + metadata->strides[i] = drv_stride_from_format(metadata->format, metadata->width, i); + metadata->sizes[i] = drv_size_from_format(metadata->format, metadata->strides[i], + metadata->height, i); + metadata->offsets[i] = offset; + offset += metadata->sizes[i]; + } + + metadata->total_size = offset; +} + static int cross_domain_init(struct driver *drv) { int ret; @@ -264,7 +280,7 @@ static int cross_domain_init(struct driver *drv) ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GET_CAPS, &args); if (ret) { - drv_log("DRM_IOCTL_VIRTGPU_GET_CAPS failed with %s\n", strerror(errno)); + drv_loge("DRM_IOCTL_VIRTGPU_GET_CAPS failed with %s\n", strerror(errno)); goto free_private; } @@ -287,7 +303,7 @@ static int cross_domain_init(struct driver *drv) init.num_params = 2; ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_CONTEXT_INIT, &init); if (ret) { - drv_log("DRM_IOCTL_VIRTGPU_CONTEXT_INIT failed with %s\n", strerror(errno)); + drv_loge("DRM_IOCTL_VIRTGPU_CONTEXT_INIT failed with %s\n", strerror(errno)); goto free_private; } @@ -298,7 +314,7 @@ static int cross_domain_init(struct driver *drv) ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB, &drm_rc_blob); if (ret < 0) { - drv_log("DRM_VIRTGPU_RESOURCE_CREATE_BLOB failed with %s\n", strerror(errno)); + drv_loge("DRM_VIRTGPU_RESOURCE_CREATE_BLOB failed with %s\n", strerror(errno)); goto free_private; } @@ -308,7 +324,7 @@ static int cross_domain_init(struct driver *drv) map.handle = priv->ring_handle; ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_MAP, &map); if (ret < 0) { - drv_log("DRM_IOCTL_VIRTGPU_MAP failed with %s\n", strerror(errno)); + drv_loge("DRM_IOCTL_VIRTGPU_MAP failed with %s\n", strerror(errno)); goto free_private; } @@ -316,7 +332,7 @@ static int cross_domain_init(struct driver *drv) mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, drv->fd, map.offset); if (priv->ring_addr == MAP_FAILED) { - drv_log("mmap failed with %s\n", strerror(errno)); + drv_loge("mmap failed with %s\n", strerror(errno)); goto free_private; } @@ -349,36 +365,42 @@ static int cross_domain_bo_create(struct bo *bo, uint32_t width, uint32_t height uint32_t blob_flags = VIRTGPU_BLOB_FLAG_USE_SHAREABLE; struct drm_virtgpu_resource_create_blob drm_rc_blob = { 0 }; - ret = cross_domain_metadata_query(bo->drv, &bo->meta); - if (ret < 0) { - drv_log("Metadata query failed"); - return ret; - } - - if (use_flags & BO_USE_SW_MASK) + if (use_flags & (BO_USE_SW_MASK | BO_USE_GPU_DATA_BUFFER)) blob_flags |= VIRTGPU_BLOB_FLAG_USE_MAPPABLE; - 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. - /// But for the immediate use cases, we will either have one or the other. For now, just - /// prefer guest memory since adding that feature is more involved (requires --udmabuf - /// flag to crosvm), so developers would likely test that. - if (params[param_create_guest_handle].value) { + if (!(use_flags & BO_USE_HW_MASK)) { + cross_domain_get_emulated_metadata(&bo->meta); drm_rc_blob.blob_mem = VIRTGPU_BLOB_MEM_GUEST; - blob_flags |= VIRTGPU_BLOB_FLAG_CREATE_GUEST_HANDLE; - } else if (params[param_host_visible].value) { - drm_rc_blob.blob_mem = VIRTGPU_BLOB_MEM_HOST3D; + } else { + ret = cross_domain_metadata_query(bo->drv, &bo->meta); + if (ret < 0) { + drv_loge("Metadata query failed"); + return ret; + } + + 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. But for the immediate use cases, we will either have one or the + /// other. For now, just prefer guest memory since adding that feature is more + /// involved (requires --udmabuf flag to crosvm), so developers would likely test + /// that. + if (params[param_create_guest_handle].value) { + drm_rc_blob.blob_mem = VIRTGPU_BLOB_MEM_GUEST; + blob_flags |= VIRTGPU_BLOB_FLAG_CREATE_GUEST_HANDLE; + } else if (params[param_host_visible].value) { + drm_rc_blob.blob_mem = VIRTGPU_BLOB_MEM_HOST3D; + } + drm_rc_blob.blob_id = (uint64_t)bo->meta.blob_id; } drm_rc_blob.size = bo->meta.total_size; drm_rc_blob.blob_flags = blob_flags; - 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) { - drv_log("DRM_VIRTGPU_RESOURCE_CREATE_BLOB failed with %s\n", strerror(errno)); + drv_loge("DRM_VIRTGPU_RESOURCE_CREATE_BLOB failed with %s\n", strerror(errno)); return -errno; } @@ -388,7 +410,7 @@ static int cross_domain_bo_create(struct bo *bo, uint32_t width, uint32_t height return 0; } -static void *cross_domain_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags) +static void *cross_domain_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags) { int ret; struct drm_virtgpu_map gem_map = { 0 }; @@ -396,7 +418,7 @@ static void *cross_domain_bo_map(struct bo *bo, struct vma *vma, size_t plane, u gem_map.handle = bo->handles[0].u32; ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_MAP, &gem_map); if (ret) { - drv_log("DRM_IOCTL_VIRTGPU_MAP failed with %s\n", strerror(errno)); + drv_loge("DRM_IOCTL_VIRTGPU_MAP failed with %s\n", strerror(errno)); return MAP_FAILED; } diff --git a/virtgpu_virgl.c b/virtgpu_virgl.c index 8bcfc9d..9474c40 100644 --- a/virtgpu_virgl.c +++ b/virtgpu_virgl.c @@ -6,10 +6,13 @@ #include <assert.h> #include <errno.h> +#include <fcntl.h> #include <stdatomic.h> #include <stdint.h> +#include <stdio.h> #include <string.h> #include <sys/mman.h> +#include <unistd.h> #include <xf86drm.h> #include "drv_helpers.h" @@ -22,11 +25,6 @@ #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 @@ -98,7 +96,7 @@ static uint32_t translate_format(uint32_t drm_fourcc) case DRM_FORMAT_YVU420_ANDROID: return VIRGL_FORMAT_YV12; default: - drv_log("Unhandled format:%d\n", drm_fourcc); + drv_loge("Unhandled format:%d\n", drm_fourcc); return 0; } } @@ -352,13 +350,13 @@ static void virgl_add_combination(struct driver *drv, uint32_t 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); + drv_logi("Strip scanout on format: %d\n", drm_format); use_flags &= ~BO_USE_SCANOUT; } if (!virgl_supports_combination_natively(drv, drm_format, use_flags) && !virgl_supports_combination_through_emulation(drv, drm_format, use_flags)) { - drv_log("Skipping unsupported combination format:%d\n", drm_format); + drv_logi("Skipping unsupported combination format:%d\n", drm_format); return; } } @@ -398,7 +396,7 @@ static inline void handle_flag(uint64_t *flag, uint64_t check_flag, uint32_t *bi } } -static uint32_t compute_virgl_bind_flags(uint64_t use_flags, uint32_t format) +static uint32_t compute_virgl_bind_flags(uint64_t use_flags) { /* In crosvm, VIRGL_BIND_SHARED means minigbm will allocate, not virglrenderer. */ uint32_t bind = VIRGL_BIND_SHARED; @@ -408,6 +406,7 @@ 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); @@ -440,7 +439,7 @@ static uint32_t compute_virgl_bind_flags(uint64_t use_flags, uint32_t format) VIRGL_BIND_MINIGBM_HW_VIDEO_ENCODER); if (use_flags) - drv_log("Unhandled bo use flag: %llx\n", (unsigned long long)use_flags); + drv_loge("Unhandled bo use flag: %llx\n", (unsigned long long)use_flags); return bind; } @@ -456,7 +455,7 @@ static int virgl_3d_bo_create(struct bo *bo, uint32_t width, uint32_t height, ui if (virgl_supports_combination_natively(bo->drv, format, use_flags)) { stride = drv_stride_from_format(format, width, 0); - drv_bo_from_format(bo, stride, height, format); + drv_bo_from_format(bo, stride, 1, height, format); } else { assert(virgl_supports_combination_through_emulation(bo->drv, format, use_flags)); @@ -483,7 +482,7 @@ static int virgl_3d_bo_create(struct bo *bo, uint32_t width, uint32_t height, ui res_create.target = PIPE_TEXTURE_2D; res_create.format = translate_format(format); - res_create.bind = compute_virgl_bind_flags(use_flags, format); + res_create.bind = compute_virgl_bind_flags(use_flags); res_create.width = width; res_create.height = height; @@ -496,7 +495,7 @@ static int virgl_3d_bo_create(struct bo *bo, uint32_t width, uint32_t height, ui res_create.size = ALIGN(bo->meta.total_size, PAGE_SIZE); // PAGE_SIZE = 0x1000 ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE, &res_create); if (ret) { - drv_log("DRM_IOCTL_VIRTGPU_RESOURCE_CREATE failed with %s\n", strerror(errno)); + drv_loge("DRM_IOCTL_VIRTGPU_RESOURCE_CREATE failed with %s\n", strerror(errno)); return ret; } @@ -506,7 +505,7 @@ static int virgl_3d_bo_create(struct bo *bo, uint32_t width, uint32_t height, ui return 0; } -static void *virgl_3d_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags) +static void *virgl_3d_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags) { int ret; struct drm_virtgpu_map gem_map = { 0 }; @@ -514,7 +513,7 @@ static void *virgl_3d_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint3 gem_map.handle = bo->handles[0].u32; ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_MAP, &gem_map); if (ret) { - drv_log("DRM_IOCTL_VIRTGPU_MAP failed with %s\n", strerror(errno)); + drv_loge("DRM_IOCTL_VIRTGPU_MAP failed with %s\n", strerror(errno)); return MAP_FAILED; } @@ -551,7 +550,7 @@ static int virgl_get_caps(struct driver *drv, union virgl_caps *caps, int *caps_ ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GET_CAPS, &cap_args); if (ret) { - drv_log("DRM_IOCTL_VIRTGPU_GET_CAPS failed with %s\n", strerror(errno)); + drv_loge("DRM_IOCTL_VIRTGPU_GET_CAPS failed with %s\n", strerror(errno)); *caps_is_v2 = 0; // Fallback to v1 @@ -560,7 +559,7 @@ static int virgl_get_caps(struct driver *drv, union virgl_caps *caps, int *caps_ ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_GET_CAPS, &cap_args); if (ret) - drv_log("DRM_IOCTL_VIRTGPU_GET_CAPS failed with %s\n", strerror(errno)); + drv_loge("DRM_IOCTL_VIRTGPU_GET_CAPS failed with %s\n", strerror(errno)); } return ret; @@ -642,9 +641,11 @@ static int virgl_init(struct driver *drv) virgl_add_combination(drv, DRM_FORMAT_P010, &LINEAR_METADATA, 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_GPU_DATA_BUFFER); + 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, @@ -686,7 +687,7 @@ static int virgl_bo_create_blob(struct driver *drv, struct bo *bo) struct virgl_priv *priv = (struct virgl_priv *)drv->priv; uint32_t blob_flags = VIRTGPU_BLOB_FLAG_USE_SHAREABLE; - if (bo->meta.use_flags & BO_USE_SW_MASK) + if (bo->meta.use_flags & (BO_USE_SW_MASK | BO_USE_GPU_DATA_BUFFER)) blob_flags |= VIRTGPU_BLOB_FLAG_USE_MAPPABLE; // For now, all blob use cases are cross device. When we add wider @@ -695,7 +696,7 @@ static int virgl_bo_create_blob(struct driver *drv, struct bo *bo) cur_blob_id = atomic_fetch_add(&priv->next_blob_id, 1); stride = drv_stride_from_format(bo->meta.format, bo->meta.width, 0); - drv_bo_from_format(bo, stride, bo->meta.height, bo->meta.format); + drv_bo_from_format(bo, stride, 1, bo->meta.height, bo->meta.format); bo->meta.total_size = ALIGN(bo->meta.total_size, PAGE_SIZE); bo->meta.tiling = blob_flags; @@ -704,8 +705,7 @@ static int virgl_bo_create_blob(struct driver *drv, struct bo *bo) cmd[VIRGL_PIPE_RES_CREATE_WIDTH] = bo->meta.width; cmd[VIRGL_PIPE_RES_CREATE_HEIGHT] = bo->meta.height; cmd[VIRGL_PIPE_RES_CREATE_FORMAT] = translate_format(bo->meta.format); - cmd[VIRGL_PIPE_RES_CREATE_BIND] = - compute_virgl_bind_flags(bo->meta.use_flags, bo->meta.format); + cmd[VIRGL_PIPE_RES_CREATE_BIND] = compute_virgl_bind_flags(bo->meta.use_flags); cmd[VIRGL_PIPE_RES_CREATE_DEPTH] = 1; cmd[VIRGL_PIPE_RES_CREATE_BLOB_ID] = cur_blob_id; @@ -718,7 +718,7 @@ static int virgl_bo_create_blob(struct driver *drv, struct bo *bo) ret = drmIoctl(drv->fd, DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB, &drm_rc_blob); if (ret < 0) { - drv_log("DRM_VIRTGPU_RESOURCE_CREATE_BLOB failed with %s\n", strerror(errno)); + drv_loge("DRM_VIRTGPU_RESOURCE_CREATE_BLOB failed with %s\n", strerror(errno)); return -errno; } @@ -774,6 +774,21 @@ static int virgl_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint3 return virgl_2d_dumb_bo_create(bo, width, height, format, use_flags); } +static int virgl_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint32_t height, + uint32_t format, const uint64_t *modifiers, + uint32_t count) +{ + uint64_t use_flags = 0; + + for (uint32_t i = 0; i < count; i++) { + if (modifiers[i] == DRM_FORMAT_MOD_LINEAR) { + return virgl_bo_create(bo, width, height, format, use_flags); + } + } + + return -EINVAL; +} + static int virgl_bo_destroy(struct bo *bo) { if (params[param_3d].value) @@ -782,12 +797,42 @@ static int virgl_bo_destroy(struct bo *bo) return drv_dumb_bo_destroy(bo); } -static void *virgl_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags) +static void *virgl_bo_map(struct bo *bo, struct vma *vma, uint32_t map_flags) { if (params[param_3d].value) - return virgl_3d_bo_map(bo, vma, plane, map_flags); + return virgl_3d_bo_map(bo, vma, map_flags); else - return drv_dumb_bo_map(bo, vma, plane, map_flags); + return drv_dumb_bo_map(bo, vma, map_flags); +} + +static bool is_arc_screen_capture_bo(struct bo *bo) +{ + struct drm_prime_handle prime_handle = {}; + int ret, fd; + char tmp[256]; + + if (bo->meta.num_planes != 1 || + (bo->meta.format != DRM_FORMAT_ABGR8888 && bo->meta.format != DRM_FORMAT_ARGB8888 && + bo->meta.format != DRM_FORMAT_XRGB8888 && bo->meta.format != DRM_FORMAT_XBGR8888)) + return false; + prime_handle.handle = bo->handles[0].u32; + ret = drmIoctl(bo->drv->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &prime_handle); + if (ret < 0) + return false; + snprintf(tmp, sizeof(tmp), "/proc/self/fdinfo/%d", prime_handle.fd); + fd = open(tmp, O_RDONLY); + if (fd < 0) { + close(prime_handle.fd); + return false; + } + ret = read(fd, tmp, sizeof(tmp) - 1); + close(prime_handle.fd); + close(fd); + if (ret < 0) + return false; + tmp[ret] = 0; + + return strstr(tmp, "ARC-SCREEN-CAP"); } static int virgl_bo_invalidate(struct bo *bo, struct mapping *mapping) @@ -812,6 +857,15 @@ static int virgl_bo_invalidate(struct bo *bo, struct mapping *mapping) else host_write_flags |= BO_USE_HW_VIDEO_DECODER; + // TODO(b/267892346): Revert this workaround after migrating to virtgpu_cross_domain + // backend since it's a special arc only behavior. + if (!(bo->meta.use_flags & (BO_USE_ARC_SCREEN_CAP_PROBED | BO_USE_RENDERING))) { + bo->meta.use_flags |= BO_USE_ARC_SCREEN_CAP_PROBED; + if (is_arc_screen_capture_bo(bo)) { + bo->meta.use_flags |= BO_USE_RENDERING; + } + } + if ((bo->meta.use_flags & host_write_flags) == 0) return 0; @@ -863,8 +917,8 @@ static int virgl_bo_invalidate(struct bo *bo, struct mapping *mapping) ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST, &xfer); if (ret) { - drv_log("DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST failed with %s\n", - strerror(errno)); + drv_loge("DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST failed with %s\n", + strerror(errno)); return -errno; } } @@ -875,7 +929,7 @@ static int virgl_bo_invalidate(struct bo *bo, struct mapping *mapping) waitcmd.handle = mapping->vma->handle; ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_WAIT, &waitcmd); if (ret) { - drv_log("DRM_IOCTL_VIRTGPU_WAIT failed with %s\n", strerror(errno)); + drv_loge("DRM_IOCTL_VIRTGPU_WAIT failed with %s\n", strerror(errno)); return -errno; } @@ -939,8 +993,8 @@ static int virgl_bo_flush(struct bo *bo, struct mapping *mapping) ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST, &xfer); if (ret) { - drv_log("DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST failed with %s\n", - strerror(errno)); + drv_loge("DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST failed with %s\n", + strerror(errno)); return -errno; } } @@ -954,7 +1008,7 @@ static int virgl_bo_flush(struct bo *bo, struct mapping *mapping) ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_WAIT, &waitcmd); if (ret) { - drv_log("DRM_IOCTL_VIRTGPU_WAIT failed with %s\n", strerror(errno)); + drv_loge("DRM_IOCTL_VIRTGPU_WAIT failed with %s\n", strerror(errno)); return -errno; } } @@ -968,22 +1022,31 @@ static void virgl_3d_resolve_format_and_use_flags(struct driver *drv, uint32_t f { *out_format = format; *out_use_flags = use_flags; + + /* resolve flexible format into explicit format */ 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 */ + /* HACK: See b/28671744 and b/264408280 */ *out_format = DRM_FORMAT_XBGR8888; *out_use_flags &= ~BO_USE_HW_VIDEO_ENCODER; + *out_use_flags |= BO_USE_LINEAR; } 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. */ *out_format = DRM_FORMAT_NV12; - /* fallthrough */ + break; + default: + break; + } + + /* resolve explicit format */ + switch (*out_format) { case DRM_FORMAT_NV12: case DRM_FORMAT_ABGR8888: case DRM_FORMAT_ARGB8888: @@ -992,8 +1055,8 @@ static void virgl_3d_resolve_format_and_use_flags(struct driver *drv, uint32_t f 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)) + if ((*out_use_flags & BO_USE_SCANOUT) && + !virgl_supports_combination_natively(drv, *out_format, BO_USE_SCANOUT)) *out_use_flags &= ~BO_USE_SCANOUT; break; case DRM_FORMAT_YVU420_ANDROID: @@ -1066,7 +1129,7 @@ static int virgl_resource_info(struct bo *bo, uint32_t strides[DRV_MAX_PLANES], res_info.type = VIRTGPU_RESOURCE_INFO_TYPE_EXTENDED; ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VIRTGPU_RESOURCE_INFO_CROS, &res_info); if (ret) { - drv_log("DRM_IOCTL_VIRTGPU_RESOURCE_INFO failed with %s\n", strerror(errno)); + drv_loge("DRM_IOCTL_VIRTGPU_RESOURCE_INFO failed with %s\n", strerror(errno)); return ret; } @@ -1098,6 +1161,7 @@ const struct backend virtgpu_virgl = { .name = "virtgpu_virgl", .init = virgl_init, .close = virgl_close, .bo_create = virgl_bo_create, + .bo_create_with_modifiers = virgl_bo_create_with_modifiers, .bo_destroy = virgl_bo_destroy, .bo_import = drv_prime_bo_import, .bo_map = virgl_bo_map, |