diff options
31 files changed, 3053 insertions, 124 deletions
@@ -25,6 +25,9 @@ endif ifdef DRV_MESON CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_meson) endif +ifdef DRV_MSM + CFLAGS += -ldl +endif ifdef DRV_RADEON CFLAGS += $(shell $(PKG_CONFIG) --cflags libdrm_radeon) endif @@ -47,9 +47,11 @@ struct amdgpu_linear_vma_priv { uint32_t map_flags; }; -const static uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888, - DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888, - DRM_FORMAT_XRGB8888 }; +const static 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_ARGB2101010, DRM_FORMAT_XBGR2101010, DRM_FORMAT_XRGB2101010, +}; const static uint32_t texture_source_formats[] = { DRM_FORMAT_GR88, DRM_FORMAT_R8, DRM_FORMAT_NV21, DRM_FORMAT_NV12, @@ -364,6 +366,11 @@ static int amdgpu_init(struct driver *drv) drv_modify_combination(drv, DRM_FORMAT_ABGR8888, &metadata, BO_USE_SCANOUT); drv_modify_combination(drv, DRM_FORMAT_XBGR8888, &metadata, BO_USE_SCANOUT); + drv_modify_combination(drv, DRM_FORMAT_ABGR2101010, &metadata, BO_USE_SCANOUT); + drv_modify_combination(drv, DRM_FORMAT_ARGB2101010, &metadata, BO_USE_SCANOUT); + drv_modify_combination(drv, DRM_FORMAT_XBGR2101010, &metadata, BO_USE_SCANOUT); + drv_modify_combination(drv, DRM_FORMAT_XRGB2101010, &metadata, BO_USE_SCANOUT); + drv_modify_combination(drv, DRM_FORMAT_NV21, &metadata, BO_USE_SCANOUT); /* @@ -395,6 +402,11 @@ static int amdgpu_init(struct driver *drv) drv_modify_combination(drv, DRM_FORMAT_XRGB8888, &metadata, BO_USE_CURSOR | BO_USE_SCANOUT); drv_modify_combination(drv, DRM_FORMAT_ABGR8888, &metadata, BO_USE_SCANOUT); drv_modify_combination(drv, DRM_FORMAT_XBGR8888, &metadata, BO_USE_SCANOUT); + + drv_modify_combination(drv, DRM_FORMAT_ABGR2101010, &metadata, BO_USE_SCANOUT); + drv_modify_combination(drv, DRM_FORMAT_ARGB2101010, &metadata, BO_USE_SCANOUT); + drv_modify_combination(drv, DRM_FORMAT_XBGR2101010, &metadata, BO_USE_SCANOUT); + drv_modify_combination(drv, DRM_FORMAT_XRGB2101010, &metadata, BO_USE_SCANOUT); return 0; } @@ -418,12 +430,12 @@ static int amdgpu_create_bo_linear(struct bo *bo, uint32_t width, uint32_t heigh stride = ALIGN(stride, 256); /* - * Currently, allocator used by chrome aligns the height for Encoder/ - * Decoder buffers while allocator used by android(gralloc/minigbm) - * doesn't provide any aligment. - * - * See b/153130069 - */ + * Currently, allocator used by chrome aligns the height for Encoder/ + * Decoder buffers while allocator used by android(gralloc/minigbm) + * doesn't provide any aligment. + * + * See b/153130069 + */ if (use_flags & (BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER)) height = ALIGN(height, CHROME_HEIGHT_ALIGN); diff --git a/cros_gralloc/cros_gralloc_driver.cc b/cros_gralloc/cros_gralloc_driver.cc index e32704a..ab7c654 100644 --- a/cros_gralloc/cros_gralloc_driver.cc +++ b/cros_gralloc/cros_gralloc_driver.cc @@ -55,7 +55,7 @@ int32_t cros_gralloc_driver::init() if (asprintf(&node, str, DRM_DIR_NAME, j) < 0) continue; - fd = open(node, O_RDWR, 0); + fd = open(node, O_RDWR | O_CLOEXEC); free(node); if (fd < 0) @@ -217,6 +217,7 @@ int32_t cros_gralloc_driver::allocate(const struct cros_gralloc_buffer_descripto hnd->width = drv_bo_get_width(bo); hnd->height = drv_bo_get_height(bo); hnd->format = drv_bo_get_format(bo); + hnd->tiling = bo->meta.tiling; hnd->format_modifier = drv_bo_get_plane_format_modifier(bo, 0); hnd->use_flags = descriptor->use_flags; bytes_per_pixel = drv_bytes_per_pixel_from_format(hnd->format, 0); @@ -271,6 +272,7 @@ int32_t cros_gralloc_driver::retain(buffer_handle_t handle) struct bo *bo; struct drv_import_fd_data data; data.format = hnd->format; + data.tiling = hnd->tiling; data.width = hnd->width; data.height = hnd->height; @@ -503,4 +505,4 @@ void cros_gralloc_driver::for_each_handle( for (const auto &pair : handles_) { function(pair.first); } -}
\ No newline at end of file +} diff --git a/cros_gralloc/cros_gralloc_handle.h b/cros_gralloc/cros_gralloc_handle.h index d2e1607..b5525d1 100644 --- a/cros_gralloc/cros_gralloc_handle.h +++ b/cros_gralloc/cros_gralloc_handle.h @@ -31,6 +31,7 @@ struct cros_gralloc_handle { uint32_t width; uint32_t height; uint32_t format; /* DRM format */ + uint32_t tiling; uint64_t format_modifier; uint64_t use_flags; /* Buffer creation flags */ uint32_t magic; diff --git a/cros_gralloc/gralloc0/gralloc0.cc b/cros_gralloc/gralloc0/gralloc0.cc index 170dae9..b0fe945 100644 --- a/cros_gralloc/gralloc0/gralloc0.cc +++ b/cros_gralloc/gralloc0/gralloc0.cc @@ -19,6 +19,15 @@ struct gralloc0_module { std::mutex initialization_mutex; }; +struct cros_gralloc0_buffer_info { + uint32_t drm_fourcc; + int num_fds; + int fds[4]; + uint64_t modifier; + uint32_t offset[4]; + uint32_t stride[4]; +}; + /* This enumeration must match the one in <gralloc_drm.h>. * The functions supported by this gralloc's temporary private API are listed * below. Use of these functions is highly discouraged and should only be @@ -31,6 +40,7 @@ enum { GRALLOC_DRM_GET_FORMAT, GRALLOC_DRM_GET_DIMENSIONS, GRALLOC_DRM_GET_BACKING_STORE, + GRALLOC_DRM_GET_BUFFER_INFO, }; // clang-format on @@ -265,6 +275,7 @@ static int gralloc0_perform(struct gralloc_module_t const *module, int op, ...) uint32_t *out_width, *out_height, *out_stride; uint32_t strides[DRV_MAX_PLANES] = { 0, 0, 0, 0 }; uint32_t offsets[DRV_MAX_PLANES] = { 0, 0, 0, 0 }; + struct cros_gralloc0_buffer_info *info; auto mod = (struct gralloc0_module const *)module; switch (op) { @@ -272,6 +283,7 @@ static int gralloc0_perform(struct gralloc_module_t const *module, int op, ...) case GRALLOC_DRM_GET_FORMAT: case GRALLOC_DRM_GET_DIMENSIONS: case GRALLOC_DRM_GET_BACKING_STORE: + case GRALLOC_DRM_GET_BUFFER_INFO: break; default: return -EINVAL; @@ -316,6 +328,17 @@ static int gralloc0_perform(struct gralloc_module_t const *module, int op, ...) out_store = va_arg(args, uint64_t *); ret = mod->driver->get_backing_store(handle, out_store); break; + case GRALLOC_DRM_GET_BUFFER_INFO: + info = va_arg(args, struct cros_gralloc0_buffer_info *); + info->drm_fourcc = hnd->format; + info->num_fds = hnd->num_planes; + info->modifier = hnd->format_modifier; + for (uint32_t i = 0; i < hnd->num_planes; i++) { + info->fds[i] = hnd->fds[i]; + info->offset[i] = hnd->offsets[i]; + info->stride[i] = hnd->strides[i]; + } + break; default: ret = -EINVAL; } diff --git a/cros_gralloc/gralloc3/Android.bp b/cros_gralloc/gralloc3/Android.bp deleted file mode 100644 index 96317ed..0000000 --- a/cros_gralloc/gralloc3/Android.bp +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2020 The Chromium OS Authors. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -cc_binary { - name: "android.hardware.graphics.allocator@3.0-service.minigbm", - relative_install_path: "hw", - vendor: true, - init_rc: ["android.hardware.graphics.allocator@3.0-service.minigbm.rc"], - - cflags: [ - "-Wall", - "-Werror", - ], - - shared_libs: [ - "android.hardware.graphics.allocator@3.0", - "android.hardware.graphics.mapper@3.0", - "libbase", - "libcutils", - "libhidlbase", - "liblog", - "libsync", - "libutils", - ], - - static_libs: [ - "libdrm", - "libminigbm_gralloc", - ], - - srcs: [ - "CrosGralloc3Allocator.cc", - "CrosGralloc3AllocatorService.cc", - "CrosGralloc3Utils.cc", - ], -} - -cc_library_shared { - name: "android.hardware.graphics.mapper@3.0-impl.minigbm", - relative_install_path: "hw", - vendor: true, - - cflags: [ - "-Wall", - "-Werror", - ], - - shared_libs: [ - "android.hardware.graphics.mapper@3.0", - "libbase", - "libcutils", - "libhidlbase", - "liblog", - "libsync", - "libutils", - ], - - static_libs: [ - "libdrm", - "libminigbm_gralloc", - ], - - srcs: [ - "CrosGralloc3Mapper.cc", - "CrosGralloc3Utils.cc", - ], -} diff --git a/cros_gralloc/gralloc4/.clang-format b/cros_gralloc/gralloc4/.clang-format new file mode 100644 index 0000000..b310cc1 --- /dev/null +++ b/cros_gralloc/gralloc4/.clang-format @@ -0,0 +1,19 @@ +# Copyright 2020 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# This directory is formatted to match the format of the interfaces implemented. + +BasedOnStyle: Google +Standard: Cpp11 +AccessModifierOffset: -2 +AllowShortFunctionsOnASingleLine: Inline +ColumnLimit: 100 +CommentPragmas: NOLINT:.* +DerivePointerAlignment: false +IncludeBlocks: Preserve +IndentWidth: 4 +ContinuationIndentWidth: 8 +PointerAlignment: Left +TabWidth: 4 +UseTab: Never
\ No newline at end of file diff --git a/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc b/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc new file mode 100644 index 0000000..4fb7845 --- /dev/null +++ b/cros_gralloc/gralloc4/CrosGralloc4Allocator.cc @@ -0,0 +1,122 @@ +/* + * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cros_gralloc/gralloc4/CrosGralloc4Allocator.h" + +#include <android/hardware/graphics/mapper/4.0/IMapper.h> +#include <gralloctypes/Gralloc4.h> + +#include "cros_gralloc/cros_gralloc_helpers.h" +#include "cros_gralloc/gralloc4/CrosGralloc4Utils.h" + +using android::hardware::hidl_handle; +using android::hardware::hidl_vec; +using android::hardware::Return; +using android::hardware::Void; +using android::hardware::graphics::common::V1_2::BufferUsage; +using android::hardware::graphics::common::V1_2::PixelFormat; +using android::hardware::graphics::mapper::V4_0::Error; + +using BufferDescriptorInfo = + android::hardware::graphics::mapper::V4_0::IMapper::BufferDescriptorInfo; + +CrosGralloc4Allocator::CrosGralloc4Allocator() : mDriver(std::make_unique<cros_gralloc_driver>()) { + if (mDriver->init()) { + drv_log("Failed to initialize driver.\n"); + mDriver = nullptr; + } +} + +Error CrosGralloc4Allocator::allocate(const BufferDescriptorInfo& descriptor, uint32_t* outStride, + hidl_handle* outHandle) { + if (!mDriver) { + drv_log("Failed to allocate. Driver is uninitialized.\n"); + return Error::NO_RESOURCES; + } + + if (!outStride || !outHandle) { + return Error::NO_RESOURCES; + } + + struct cros_gralloc_buffer_descriptor crosDescriptor; + if (convertToCrosDescriptor(descriptor, &crosDescriptor)) { + return Error::UNSUPPORTED; + } + + bool supported = mDriver->is_supported(&crosDescriptor); + if (!supported && (descriptor.usage & BufferUsage::COMPOSER_OVERLAY)) { + crosDescriptor.use_flags &= ~BO_USE_SCANOUT; + supported = mDriver->is_supported(&crosDescriptor); + } + + if (!supported) { + std::string drmFormatString = getDrmFormatString(crosDescriptor.drm_format); + std::string pixelFormatString = getPixelFormatString(descriptor.format); + std::string usageString = getUsageString(descriptor.usage); + drv_log("Unsupported combination -- pixel format: %s, drm format:%s, usage: %s\n", + pixelFormatString.c_str(), drmFormatString.c_str(), usageString.c_str()); + return Error::UNSUPPORTED; + } + + buffer_handle_t handle; + int ret = mDriver->allocate(&crosDescriptor, &handle); + if (ret) { + return Error::NO_RESOURCES; + } + + cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(handle); + if (!crosHandle) { + return Error::NO_RESOURCES; + } + + *outHandle = handle; + *outStride = crosHandle->pixel_stride; + + return Error::NONE; +} + +Return<void> CrosGralloc4Allocator::allocate(const hidl_vec<uint8_t>& descriptor, uint32_t count, + allocate_cb hidlCb) { + hidl_vec<hidl_handle> handles; + + if (!mDriver) { + drv_log("Failed to allocate. Driver is uninitialized.\n"); + hidlCb(Error::NO_RESOURCES, 0, handles); + return Void(); + } + + BufferDescriptorInfo description; + + int ret = android::gralloc4::decodeBufferDescriptorInfo(descriptor, &description); + if (ret) { + drv_log("Failed to allocate. Failed to decode buffer descriptor: %d.\n", ret); + hidlCb(Error::BAD_DESCRIPTOR, 0, handles); + return Void(); + } + + handles.resize(count); + + uint32_t stride = 0; + for (int i = 0; i < handles.size(); i++) { + Error err = allocate(description, &stride, &(handles[i])); + if (err != Error::NONE) { + for (int j = 0; j < i; j++) { + mDriver->release(handles[j].getNativeHandle()); + } + handles.resize(0); + hidlCb(err, 0, handles); + return Void(); + } + } + + hidlCb(Error::NONE, stride, handles); + + for (const hidl_handle& handle : handles) { + mDriver->release(handle.getNativeHandle()); + } + + return Void(); +} diff --git a/cros_gralloc/gralloc4/CrosGralloc4Allocator.h b/cros_gralloc/gralloc4/CrosGralloc4Allocator.h new file mode 100644 index 0000000..21ad7ad --- /dev/null +++ b/cros_gralloc/gralloc4/CrosGralloc4Allocator.h @@ -0,0 +1,26 @@ +/* + * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <android/hardware/graphics/allocator/4.0/IAllocator.h> +#include <android/hardware/graphics/mapper/4.0/IMapper.h> + +#include "cros_gralloc/cros_gralloc_driver.h" + +class CrosGralloc4Allocator : public android::hardware::graphics::allocator::V4_0::IAllocator { + public: + CrosGralloc4Allocator(); + + android::hardware::Return<void> allocate(const android::hardware::hidl_vec<uint8_t>& descriptor, + uint32_t count, allocate_cb hidl_cb) override; + + private: + android::hardware::graphics::mapper::V4_0::Error allocate( + const android::hardware::graphics::mapper::V4_0::IMapper::BufferDescriptorInfo& + description, + uint32_t* outStride, android::hardware::hidl_handle* outHandle); + + std::unique_ptr<cros_gralloc_driver> mDriver; +}; diff --git a/cros_gralloc/gralloc4/CrosGralloc4AllocatorService.cc b/cros_gralloc/gralloc4/CrosGralloc4AllocatorService.cc new file mode 100644 index 0000000..5b79860 --- /dev/null +++ b/cros_gralloc/gralloc4/CrosGralloc4AllocatorService.cc @@ -0,0 +1,30 @@ +/* + * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#define LOG_TAG "AllocatorService" + +#include <hidl/LegacySupport.h> + +#include "cros_gralloc/gralloc4/CrosGralloc4Allocator.h" + +using android::sp; +using android::hardware::configureRpcThreadpool; +using android::hardware::joinRpcThreadpool; +using android::hardware::graphics::allocator::V4_0::IAllocator; + +int main(int, char**) { + sp<IAllocator> allocator = new CrosGralloc4Allocator(); + configureRpcThreadpool(4, true /* callerWillJoin */); + if (allocator->registerAsService() != android::NO_ERROR) { + ALOGE("failed to register graphics IAllocator 4.0 service"); + return -EINVAL; + } + + ALOGI("graphics IAllocator 4.0 service is initialized"); + android::hardware::joinRpcThreadpool(); + ALOGI("graphics IAllocator 4.0 service is terminating"); + return 0; +} diff --git a/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc b/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc new file mode 100644 index 0000000..4795216 --- /dev/null +++ b/cros_gralloc/gralloc4/CrosGralloc4Mapper.cc @@ -0,0 +1,1009 @@ +/* + * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cros_gralloc/gralloc4/CrosGralloc4Mapper.h" + +#include <aidl/android/hardware/graphics/common/BlendMode.h> +#include <aidl/android/hardware/graphics/common/Dataspace.h> +#include <aidl/android/hardware/graphics/common/PlaneLayout.h> +#include <aidl/android/hardware/graphics/common/Rect.h> +#include <cutils/native_handle.h> +#include <gralloctypes/Gralloc4.h> + +#include "cros_gralloc/gralloc4/CrosGralloc4Utils.h" +#include "helpers.h" + +using aidl::android::hardware::graphics::common::BlendMode; +using aidl::android::hardware::graphics::common::Dataspace; +using aidl::android::hardware::graphics::common::PlaneLayout; +using aidl::android::hardware::graphics::common::Rect; +using android::hardware::hidl_handle; +using android::hardware::hidl_vec; +using android::hardware::Return; +using android::hardware::Void; +using android::hardware::graphics::common::V1_2::BufferUsage; +using android::hardware::graphics::common::V1_2::PixelFormat; +using android::hardware::graphics::mapper::V4_0::Error; +using android::hardware::graphics::mapper::V4_0::IMapper; + +CrosGralloc4Mapper::CrosGralloc4Mapper() : mDriver(std::make_unique<cros_gralloc_driver>()) { + if (mDriver->init()) { + drv_log("Failed to initialize driver.\n"); + mDriver = nullptr; + } +} + +Return<void> CrosGralloc4Mapper::createDescriptor(const BufferDescriptorInfo& description, + createDescriptor_cb hidlCb) { + hidl_vec<uint8_t> descriptor; + + if (description.width == 0) { + drv_log("Failed to createDescriptor. Bad width: %d.\n", description.width); + hidlCb(Error::BAD_VALUE, descriptor); + return Void(); + } + + if (description.height == 0) { + drv_log("Failed to createDescriptor. Bad height: %d.\n", description.height); + hidlCb(Error::BAD_VALUE, descriptor); + return Void(); + } + + if (description.layerCount == 0) { + drv_log("Failed to createDescriptor. Bad layer count: %d.\n", description.layerCount); + hidlCb(Error::BAD_VALUE, descriptor); + return Void(); + } + + int ret = android::gralloc4::encodeBufferDescriptorInfo(description, &descriptor); + if (ret) { + drv_log("Failed to createDescriptor. Failed to encode: %d.\n", ret); + hidlCb(Error::BAD_VALUE, descriptor); + return Void(); + } + + hidlCb(Error::NONE, descriptor); + return Void(); +} + +Return<void> CrosGralloc4Mapper::importBuffer(const hidl_handle& handle, importBuffer_cb hidlCb) { + if (!mDriver) { + drv_log("Failed to import buffer. Driver is uninitialized.\n"); + hidlCb(Error::NO_RESOURCES, nullptr); + return Void(); + } + + const native_handle_t* bufferHandle = handle.getNativeHandle(); + if (!bufferHandle || bufferHandle->numFds == 0) { + drv_log("Failed to importBuffer. Bad handle.\n"); + hidlCb(Error::BAD_BUFFER, nullptr); + return Void(); + } + + native_handle_t* importedBufferHandle = native_handle_clone(bufferHandle); + if (!importedBufferHandle) { + drv_log("Failed to importBuffer. Handle clone failed: %s.\n", strerror(errno)); + hidlCb(Error::NO_RESOURCES, nullptr); + return Void(); + } + + int ret = mDriver->retain(importedBufferHandle); + if (ret) { + native_handle_close(importedBufferHandle); + native_handle_delete(importedBufferHandle); + hidlCb(Error::NO_RESOURCES, nullptr); + return Void(); + } + + hidlCb(Error::NONE, importedBufferHandle); + return Void(); +} + +Return<Error> CrosGralloc4Mapper::freeBuffer(void* rawHandle) { + if (!mDriver) { + drv_log("Failed to freeBuffer. Driver is uninitialized.\n"); + return Error::NO_RESOURCES; + } + + native_handle_t* bufferHandle = reinterpret_cast<native_handle_t*>(rawHandle); + if (!bufferHandle) { + drv_log("Failed to freeBuffer. Empty handle.\n"); + return Error::BAD_BUFFER; + } + + int ret = mDriver->release(bufferHandle); + if (ret) { + return Error::BAD_BUFFER; + } + + native_handle_close(bufferHandle); + native_handle_delete(bufferHandle); + return Error::NONE; +} + +Return<Error> CrosGralloc4Mapper::validateBufferSize(void* rawHandle, + const BufferDescriptorInfo& descriptor, + uint32_t stride) { + if (!mDriver) { + drv_log("Failed to validateBufferSize. Driver is uninitialized.\n"); + return Error::NO_RESOURCES; + } + + native_handle_t* bufferHandle = reinterpret_cast<native_handle_t*>(rawHandle); + if (!bufferHandle) { + drv_log("Failed to validateBufferSize. Empty handle.\n"); + return Error::BAD_BUFFER; + } + + cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle); + if (!crosHandle) { + drv_log("Failed to validateBufferSize. Invalid handle.\n"); + return Error::BAD_BUFFER; + } + + PixelFormat crosHandleFormat = static_cast<PixelFormat>(crosHandle->droid_format); + if (descriptor.format != crosHandleFormat) { + drv_log("Failed to validateBufferSize. Format mismatch.\n"); + return Error::BAD_BUFFER; + } + + if (descriptor.width != crosHandle->width) { + drv_log("Failed to validateBufferSize. Width mismatch (%d vs %d).\n", descriptor.width, + crosHandle->width); + return Error::BAD_VALUE; + } + + if (descriptor.height != crosHandle->height) { + drv_log("Failed to validateBufferSize. Height mismatch (%d vs %d).\n", descriptor.height, + crosHandle->height); + return Error::BAD_VALUE; + } + + if (stride != crosHandle->pixel_stride) { + drv_log("Failed to validateBufferSize. Stride mismatch (%d vs %d).\n", stride, + crosHandle->pixel_stride); + return Error::BAD_VALUE; + } + + return Error::NONE; +} + +Return<void> CrosGralloc4Mapper::getTransportSize(void* rawHandle, getTransportSize_cb hidlCb) { + if (!mDriver) { + drv_log("Failed to getTransportSize. Driver is uninitialized.\n"); + hidlCb(Error::BAD_BUFFER, 0, 0); + return Void(); + } + + native_handle_t* bufferHandle = reinterpret_cast<native_handle_t*>(rawHandle); + if (!bufferHandle) { + drv_log("Failed to getTransportSize. Bad handle.\n"); + hidlCb(Error::BAD_BUFFER, 0, 0); + return Void(); + } + + // No local process data is currently stored on the native handle. + hidlCb(Error::NONE, bufferHandle->numFds, bufferHandle->numInts); + return Void(); +} + +Return<void> 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"); + 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"); + hidlCb(Error::BAD_BUFFER, nullptr); + return Void(); + } + + if (cpuUsage == 0) { + drv_log("Failed to lock. Bad cpu usage: %" PRIu64 ".\n", cpuUsage); + hidlCb(Error::BAD_VALUE, nullptr); + return Void(); + } + + uint32_t mapUsage = 0; + int ret = convertToMapUsage(cpuUsage, &mapUsage); + if (ret) { + drv_log("Failed to lock. Convert usage failed.\n"); + 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"); + 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); + 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); + 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); + 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); + 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); + 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); + hidlCb(Error::BAD_VALUE, nullptr); + return Void(); + } + + struct rectangle rect = {static_cast<uint32_t>(region.left), static_cast<uint32_t>(region.top), + static_cast<uint32_t>(region.width), + static_cast<uint32_t>(region.height)}; + + // An access region of all zeros means the entire buffer. + if (rect.x == 0 && rect.y == 0 && rect.width == 0 && rect.height == 0) { + rect.width = crosHandle->width; + rect.height = crosHandle->height; + } + + int acquireFenceFd = -1; + ret = convertToFenceFd(acquireFence, &acquireFenceFd); + if (ret) { + drv_log("Failed to lock. Bad acquire fence.\n"); + hidlCb(Error::BAD_VALUE, nullptr); + return Void(); + } + + uint8_t* addr[DRV_MAX_PLANES]; + ret = mDriver->lock(bufferHandle, acquireFenceFd, /*close_acquire_fence=*/false, &rect, + mapUsage, addr); + if (ret) { + hidlCb(Error::BAD_VALUE, nullptr); + return Void(); + } + + hidlCb(Error::NONE, addr[0]); + return Void(); +} + +Return<void> CrosGralloc4Mapper::unlock(void* rawHandle, unlock_cb hidlCb) { + if (!mDriver) { + drv_log("Failed to unlock. Driver is uninitialized.\n"); + hidlCb(Error::BAD_BUFFER, nullptr); + return Void(); + } + + buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle); + if (!bufferHandle) { + drv_log("Failed to unlock. Empty handle.\n"); + hidlCb(Error::BAD_BUFFER, nullptr); + return Void(); + } + + int releaseFenceFd = -1; + int ret = mDriver->unlock(bufferHandle, &releaseFenceFd); + if (ret) { + drv_log("Failed to unlock.\n"); + hidlCb(Error::BAD_BUFFER, nullptr); + return Void(); + } + + hidl_handle releaseFenceHandle; + ret = convertToFenceHandle(releaseFenceFd, &releaseFenceHandle); + if (ret) { + drv_log("Failed to unlock. Failed to convert release fence to handle.\n"); + hidlCb(Error::BAD_BUFFER, nullptr); + return Void(); + } + + hidlCb(Error::NONE, releaseFenceHandle); + return Void(); +} + +Return<void> CrosGralloc4Mapper::flushLockedBuffer(void* rawHandle, flushLockedBuffer_cb hidlCb) { + if (!mDriver) { + drv_log("Failed to flushLockedBuffer. Driver is uninitialized.\n"); + 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"); + hidlCb(Error::BAD_BUFFER, nullptr); + return Void(); + } + + int releaseFenceFd = -1; + int ret = mDriver->flush(bufferHandle, &releaseFenceFd); + if (ret) { + drv_log("Failed to flushLockedBuffer. Flush failed.\n"); + hidlCb(Error::BAD_BUFFER, nullptr); + return Void(); + } + + hidl_handle releaseFenceHandle; + ret = convertToFenceHandle(releaseFenceFd, &releaseFenceHandle); + if (ret) { + drv_log("Failed to flushLockedBuffer. Failed to convert release fence to handle.\n"); + hidlCb(Error::BAD_BUFFER, nullptr); + return Void(); + } + + hidlCb(Error::NONE, releaseFenceHandle); + return Void(); +} + +Return<Error> CrosGralloc4Mapper::rereadLockedBuffer(void* rawHandle) { + if (!mDriver) { + drv_log("Failed to rereadLockedBuffer. Driver is uninitialized.\n"); + return Error::NO_RESOURCES; + } + + buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle); + if (!bufferHandle) { + drv_log("Failed to rereadLockedBuffer. Empty handle.\n"); + return Error::BAD_BUFFER; + } + + int ret = mDriver->invalidate(bufferHandle); + if (ret) { + drv_log("Failed to rereadLockedBuffer. Failed to invalidate.\n"); + return Error::BAD_BUFFER; + } + + return Error::NONE; +} + +Return<void> CrosGralloc4Mapper::isSupported(const BufferDescriptorInfo& descriptor, + isSupported_cb hidlCb) { + if (!mDriver) { + drv_log("Failed to isSupported. Driver is uninitialized.\n"); + hidlCb(Error::BAD_VALUE, false); + return Void(); + } + + struct cros_gralloc_buffer_descriptor crosDescriptor; + if (convertToCrosDescriptor(descriptor, &crosDescriptor)) { + hidlCb(Error::NONE, false); + return Void(); + } + + bool supported = mDriver->is_supported(&crosDescriptor); + if (!supported) { + crosDescriptor.use_flags &= ~BO_USE_SCANOUT; + supported = mDriver->is_supported(&crosDescriptor); + } + + hidlCb(Error::NONE, supported); + return Void(); +} + +Return<void> CrosGralloc4Mapper::get(void* rawHandle, const MetadataType& metadataType, + get_cb hidlCb) { + hidl_vec<uint8_t> encodedMetadata; + + if (!mDriver) { + drv_log("Failed to get. Driver is uninitialized.\n"); + 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"); + 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"); + hidlCb(Error::BAD_BUFFER, encodedMetadata); + return Void(); + } + + get(crosHandle, metadataType, hidlCb); + return Void(); +} + +Return<void> CrosGralloc4Mapper::get(cros_gralloc_handle_t crosHandle, + const MetadataType& metadataType, get_cb hidlCb) { + hidl_vec<uint8_t> encodedMetadata; + + if (!mDriver) { + drv_log("Failed to get. Driver is uninitialized.\n"); + hidlCb(Error::NO_RESOURCES, encodedMetadata); + return Void(); + } + + if (!crosHandle) { + drv_log("Failed to get. Invalid handle.\n"); + hidlCb(Error::BAD_BUFFER, encodedMetadata); + return Void(); + } + + android::status_t status = android::NO_ERROR; + if (metadataType == android::gralloc4::MetadataType_BufferId) { + status = android::gralloc4::encodeBufferId(crosHandle->id, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_Name) { + const char* name = (const char*)(&crosHandle->base.data[crosHandle->name_offset]); + status = android::gralloc4::encodeName(name, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_Width) { + status = android::gralloc4::encodeWidth(crosHandle->width, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_Height) { + status = android::gralloc4::encodeHeight(crosHandle->height, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_LayerCount) { + status = android::gralloc4::encodeLayerCount(1, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_PixelFormatRequested) { + PixelFormat pixelFormat = static_cast<PixelFormat>(crosHandle->droid_format); + status = android::gralloc4::encodePixelFormatRequested(pixelFormat, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_PixelFormatFourCC) { + uint32_t format = crosHandle->format; + // Map internal fourcc codes back to standard fourcc codes. + if (format == DRM_FORMAT_YVU420_ANDROID) { + format = DRM_FORMAT_YVU420; + } + status = android::gralloc4::encodePixelFormatFourCC(format, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_PixelFormatModifier) { + status = android::gralloc4::encodePixelFormatModifier(crosHandle->format_modifier, + &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_Usage) { + uint64_t usage = static_cast<uint64_t>(crosHandle->usage); + status = android::gralloc4::encodeUsage(usage, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_AllocationSize) { + status = android::gralloc4::encodeAllocationSize(crosHandle->total_size, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_ProtectedContent) { + uint64_t hasProtectedContent = crosHandle->usage & BufferUsage::PROTECTED ? 1 : 0; + status = android::gralloc4::encodeProtectedContent(hasProtectedContent, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_Compression) { + status = android::gralloc4::encodeCompression(android::gralloc4::Compression_None, + &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_Interlaced) { + status = android::gralloc4::encodeInterlaced(android::gralloc4::Interlaced_None, + &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_ChromaSiting) { + status = android::gralloc4::encodeChromaSiting(android::gralloc4::ChromaSiting_None, + &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_PlaneLayouts) { + std::vector<PlaneLayout> planeLayouts; + getPlaneLayouts(crosHandle->format, &planeLayouts); + + for (size_t plane = 0; plane < planeLayouts.size(); plane++) { + PlaneLayout& planeLayout = planeLayouts[plane]; + planeLayout.offsetInBytes = crosHandle->offsets[plane]; + planeLayout.strideInBytes = crosHandle->strides[plane]; + planeLayout.totalSizeInBytes = crosHandle->sizes[plane]; + planeLayout.widthInSamples = crosHandle->width; + planeLayout.heightInSamples = crosHandle->height; + } + + status = android::gralloc4::encodePlaneLayouts(planeLayouts, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_Crop) { + std::vector<aidl::android::hardware::graphics::common::Rect> crops; + for (size_t plane = 0; plane < crosHandle->num_planes; plane++) { + aidl::android::hardware::graphics::common::Rect crop; + crop.left = 0; + crop.top = 0; + crop.right = crosHandle->width; + crop.bottom = crosHandle->height; + crops.push_back(crop); + } + + status = android::gralloc4::encodeCrop(crops, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_Dataspace) { + status = android::gralloc4::encodeDataspace(Dataspace::UNKNOWN, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_BlendMode) { + status = android::gralloc4::encodeBlendMode(BlendMode::INVALID, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_Smpte2086) { + status = android::gralloc4::encodeSmpte2086(std::nullopt, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_Cta861_3) { + status = android::gralloc4::encodeCta861_3(std::nullopt, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_Smpte2094_40) { + status = android::gralloc4::encodeSmpte2094_40(std::nullopt, &encodedMetadata); + } else { + hidlCb(Error::UNSUPPORTED, encodedMetadata); + return Void(); + } + + if (status != android::NO_ERROR) { + hidlCb(Error::NO_RESOURCES, encodedMetadata); + drv_log("Failed to get. Failed to encode metadata.\n"); + return Void(); + } + + hidlCb(Error::NONE, encodedMetadata); + return Void(); +} + +Return<Error> CrosGralloc4Mapper::set(void* rawHandle, const MetadataType& metadataType, + const hidl_vec<uint8_t>& /*metadata*/) { + if (!mDriver) { + drv_log("Failed to set. Driver is uninitialized.\n"); + return Error::NO_RESOURCES; + } + + buffer_handle_t bufferHandle = reinterpret_cast<buffer_handle_t>(rawHandle); + if (!bufferHandle) { + drv_log("Failed to set. Empty handle.\n"); + return Error::BAD_BUFFER; + } + + cros_gralloc_handle_t crosHandle = cros_gralloc_convert_handle(bufferHandle); + if (!crosHandle) { + drv_log("Failed to set. Invalid handle.\n"); + return Error::BAD_BUFFER; + } + + if (metadataType == android::gralloc4::MetadataType_BufferId) { + return Error::BAD_VALUE; + } else if (metadataType == android::gralloc4::MetadataType_Name) { + return Error::BAD_VALUE; + } else if (metadataType == android::gralloc4::MetadataType_Width) { + return Error::BAD_VALUE; + } else if (metadataType == android::gralloc4::MetadataType_Height) { + return Error::BAD_VALUE; + } else if (metadataType == android::gralloc4::MetadataType_LayerCount) { + return Error::BAD_VALUE; + } else if (metadataType == android::gralloc4::MetadataType_PixelFormatRequested) { + return Error::BAD_VALUE; + } else if (metadataType == android::gralloc4::MetadataType_Usage) { + return Error::BAD_VALUE; + } + + return Error::UNSUPPORTED; +} + +int CrosGralloc4Mapper::getResolvedDrmFormat(PixelFormat pixelFormat, uint64_t bufferUsage, + uint32_t* outDrmFormat) { + uint32_t drmFormat; + if (convertToDrmFormat(pixelFormat, &drmFormat)) { + std::string pixelFormatString = getPixelFormatString(pixelFormat); + drv_log("Failed to getResolvedDrmFormat. Failed to convert format %s\n", + pixelFormatString.c_str()); + return -1; + } + + uint64_t usage; + if (convertToBufferUsage(bufferUsage, &usage)) { + std::string usageString = getUsageString(bufferUsage); + drv_log("Failed to getResolvedDrmFormat. Failed to convert usage %s\n", + usageString.c_str()); + return -1; + } + + uint32_t resolvedDrmFormat = mDriver->get_resolved_drm_format(drmFormat, usage); + if (resolvedDrmFormat == DRM_FORMAT_INVALID) { + std::string drmFormatString = getDrmFormatString(drmFormat); + drv_log("Failed to getResolvedDrmFormat. Failed to resolve drm format %s\n", + drmFormatString.c_str()); + return -1; + } + + *outDrmFormat = resolvedDrmFormat; + + return 0; +} + +Return<void> CrosGralloc4Mapper::getFromBufferDescriptorInfo( + const BufferDescriptorInfo& descriptor, const MetadataType& metadataType, + getFromBufferDescriptorInfo_cb hidlCb) { + hidl_vec<uint8_t> encodedMetadata; + + if (!mDriver) { + drv_log("Failed to getFromBufferDescriptorInfo. Driver is uninitialized.\n"); + hidlCb(Error::NO_RESOURCES, encodedMetadata); + return Void(); + } + + android::status_t status = android::NO_ERROR; + if (metadataType == android::gralloc4::MetadataType_Name) { + status = android::gralloc4::encodeName(descriptor.name, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_Width) { + status = android::gralloc4::encodeWidth(descriptor.width, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_Height) { + status = android::gralloc4::encodeHeight(descriptor.height, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_LayerCount) { + status = android::gralloc4::encodeLayerCount(1, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_PixelFormatRequested) { + status = android::gralloc4::encodePixelFormatRequested(descriptor.format, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_PixelFormatFourCC) { + uint32_t drmFormat; + if (getResolvedDrmFormat(descriptor.format, descriptor.usage, &drmFormat)) { + hidlCb(Error::BAD_VALUE, encodedMetadata); + return Void(); + } + status = android::gralloc4::encodePixelFormatFourCC(drmFormat, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_Usage) { + status = android::gralloc4::encodeUsage(descriptor.usage, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_ProtectedContent) { + uint64_t hasProtectedContent = descriptor.usage & BufferUsage::PROTECTED ? 1 : 0; + status = android::gralloc4::encodeProtectedContent(hasProtectedContent, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_Compression) { + status = android::gralloc4::encodeCompression(android::gralloc4::Compression_None, + &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_Interlaced) { + status = android::gralloc4::encodeInterlaced(android::gralloc4::Interlaced_None, + &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_ChromaSiting) { + status = android::gralloc4::encodeChromaSiting(android::gralloc4::ChromaSiting_None, + &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_Crop) { + uint32_t drmFormat; + if (getResolvedDrmFormat(descriptor.format, descriptor.usage, &drmFormat)) { + hidlCb(Error::BAD_VALUE, encodedMetadata); + return Void(); + } + + size_t numPlanes = drv_num_planes_from_format(drmFormat); + + std::vector<aidl::android::hardware::graphics::common::Rect> crops; + for (size_t plane = 0; plane < numPlanes; plane++) { + aidl::android::hardware::graphics::common::Rect crop; + crop.left = 0; + crop.top = 0; + crop.right = descriptor.width; + crop.bottom = descriptor.height; + crops.push_back(crop); + } + status = android::gralloc4::encodeCrop(crops, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_Dataspace) { + status = android::gralloc4::encodeDataspace(Dataspace::UNKNOWN, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_BlendMode) { + status = android::gralloc4::encodeBlendMode(BlendMode::INVALID, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_Smpte2086) { + status = android::gralloc4::encodeSmpte2086(std::nullopt, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_Cta861_3) { + status = android::gralloc4::encodeCta861_3(std::nullopt, &encodedMetadata); + } else if (metadataType == android::gralloc4::MetadataType_Smpte2094_40) { + status = android::gralloc4::encodeSmpte2094_40(std::nullopt, &encodedMetadata); + } else { + hidlCb(Error::UNSUPPORTED, encodedMetadata); + return Void(); + } + + if (status != android::NO_ERROR) { + hidlCb(Error::NO_RESOURCES, encodedMetadata); + return Void(); + } + + hidlCb(Error::NONE, encodedMetadata); + return Void(); +} + +Return<void> CrosGralloc4Mapper::listSupportedMetadataTypes(listSupportedMetadataTypes_cb hidlCb) { + hidl_vec<MetadataTypeDescription> supported; + + if (!mDriver) { + drv_log("Failed to listSupportedMetadataTypes. Driver is uninitialized.\n"); + hidlCb(Error::NO_RESOURCES, supported); + return Void(); + } + + supported = hidl_vec<IMapper::MetadataTypeDescription>({ + { + android::gralloc4::MetadataType_BufferId, + "", + /*isGettable=*/true, + /*isSettable=*/false, + }, + { + android::gralloc4::MetadataType_Name, + "", + /*isGettable=*/true, + /*isSettable=*/false, + }, + { + android::gralloc4::MetadataType_Width, + "", + /*isGettable=*/true, + /*isSettable=*/false, + }, + { + android::gralloc4::MetadataType_Height, + "", + /*isGettable=*/true, + /*isSettable=*/false, + }, + { + android::gralloc4::MetadataType_LayerCount, + "", + /*isGettable=*/true, + /*isSettable=*/false, + }, + { + android::gralloc4::MetadataType_PixelFormatRequested, + "", + /*isGettable=*/true, + /*isSettable=*/false, + }, + { + android::gralloc4::MetadataType_PixelFormatFourCC, + "", + /*isGettable=*/true, + /*isSettable=*/false, + }, + { + android::gralloc4::MetadataType_PixelFormatModifier, + "", + /*isGettable=*/true, + /*isSettable=*/false, + }, + { + android::gralloc4::MetadataType_Usage, + "", + /*isGettable=*/true, + /*isSettable=*/false, + }, + { + android::gralloc4::MetadataType_AllocationSize, + "", + /*isGettable=*/true, + /*isSettable=*/false, + }, + { + android::gralloc4::MetadataType_ProtectedContent, + "", + /*isGettable=*/true, + /*isSettable=*/false, + }, + { + android::gralloc4::MetadataType_Compression, + "", + /*isGettable=*/true, + /*isSettable=*/false, + }, + { + android::gralloc4::MetadataType_Interlaced, + "", + /*isGettable=*/true, + /*isSettable=*/false, + }, + { + android::gralloc4::MetadataType_ChromaSiting, + "", + /*isGettable=*/true, + /*isSettable=*/false, + }, + { + android::gralloc4::MetadataType_PlaneLayouts, + "", + /*isGettable=*/true, + /*isSettable=*/false, + }, + { + android::gralloc4::MetadataType_Dataspace, + "", + /*isGettable=*/true, + /*isSettable=*/false, + }, + { + android::gralloc4::MetadataType_BlendMode, + "", + /*isGettable=*/true, + /*isSettable=*/false, + }, + { + android::gralloc4::MetadataType_Smpte2086, + "", + /*isGettable=*/true, + /*isSettable=*/false, + }, + { + android::gralloc4::MetadataType_Cta861_3, + "", + /*isGettable=*/true, + /*isSettable=*/false, + }, + { + android::gralloc4::MetadataType_Smpte2094_40, + "", + /*isGettable=*/true, + /*isSettable=*/false, + }, + }); + + hidlCb(Error::NONE, supported); + return Void(); +} + +Return<void> CrosGralloc4Mapper::dumpBuffer(void* rawHandle, dumpBuffer_cb hidlCb) { + BufferDump bufferDump; + + if (!mDriver) { + drv_log("Failed to dumpBuffer. Driver is uninitialized.\n"); + 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"); + 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"); + hidlCb(Error::BAD_BUFFER, bufferDump); + return Void(); + } + + return dumpBuffer(crosHandle, hidlCb); +} + +Return<void> CrosGralloc4Mapper::dumpBuffer(cros_gralloc_handle_t crosHandle, + dumpBuffer_cb hidlCb) { + BufferDump bufferDump; + + if (!mDriver) { + drv_log("Failed to dumpBuffer. Driver is uninitialized.\n"); + hidlCb(Error::NO_RESOURCES, bufferDump); + return Void(); + } + + if (!crosHandle) { + drv_log("Failed to dumpBuffer. Invalid handle.\n"); + hidlCb(Error::BAD_BUFFER, bufferDump); + return Void(); + } + + std::vector<MetadataDump> metadataDumps; + + MetadataType metadataType = android::gralloc4::MetadataType_BufferId; + auto metadata_get_callback = [&](Error, hidl_vec<uint8_t> metadata) { + MetadataDump metadataDump; + metadataDump.metadataType = metadataType; + metadataDump.metadata = metadata; + metadataDumps.push_back(metadataDump); + }; + + metadataType = android::gralloc4::MetadataType_BufferId; + get(crosHandle, metadataType, metadata_get_callback); + + metadataType = android::gralloc4::MetadataType_Name; + get(crosHandle, metadataType, metadata_get_callback); + + metadataType = android::gralloc4::MetadataType_Width; + get(crosHandle, metadataType, metadata_get_callback); + + metadataType = android::gralloc4::MetadataType_Height; + get(crosHandle, metadataType, metadata_get_callback); + + metadataType = android::gralloc4::MetadataType_LayerCount; + get(crosHandle, metadataType, metadata_get_callback); + + metadataType = android::gralloc4::MetadataType_PixelFormatRequested; + get(crosHandle, metadataType, metadata_get_callback); + + metadataType = android::gralloc4::MetadataType_PixelFormatFourCC; + get(crosHandle, metadataType, metadata_get_callback); + + metadataType = android::gralloc4::MetadataType_PixelFormatModifier; + get(crosHandle, metadataType, metadata_get_callback); + + metadataType = android::gralloc4::MetadataType_Usage; + get(crosHandle, metadataType, metadata_get_callback); + + metadataType = android::gralloc4::MetadataType_AllocationSize; + get(crosHandle, metadataType, metadata_get_callback); + + metadataType = android::gralloc4::MetadataType_ProtectedContent; + get(crosHandle, metadataType, metadata_get_callback); + + metadataType = android::gralloc4::MetadataType_Compression; + get(crosHandle, metadataType, metadata_get_callback); + + metadataType = android::gralloc4::MetadataType_Interlaced; + get(crosHandle, metadataType, metadata_get_callback); + + metadataType = android::gralloc4::MetadataType_ChromaSiting; + get(crosHandle, metadataType, metadata_get_callback); + + metadataType = android::gralloc4::MetadataType_PlaneLayouts; + get(crosHandle, metadataType, metadata_get_callback); + + metadataType = android::gralloc4::MetadataType_Dataspace; + get(crosHandle, metadataType, metadata_get_callback); + + metadataType = android::gralloc4::MetadataType_BlendMode; + get(crosHandle, metadataType, metadata_get_callback); + + bufferDump.metadataDump = metadataDumps; + hidlCb(Error::NONE, bufferDump); + return Void(); +} + +Return<void> CrosGralloc4Mapper::dumpBuffers(dumpBuffers_cb hidlCb) { + std::vector<BufferDump> bufferDumps; + + if (!mDriver) { + drv_log("Failed to dumpBuffers. Driver is uninitialized.\n"); + hidlCb(Error::NO_RESOURCES, bufferDumps); + return Void(); + } + + Error error = Error::NONE; + + auto handleCallback = [&](cros_gralloc_handle_t crosHandle) { + auto dumpBufferCallback = [&](Error err, BufferDump bufferDump) { + error = err; + if (error == Error::NONE) { + bufferDumps.push_back(bufferDump); + } + }; + + dumpBuffer(crosHandle, dumpBufferCallback); + }; + mDriver->for_each_handle(handleCallback); + + hidlCb(error, bufferDumps); + return Void(); +} + +Return<void> CrosGralloc4Mapper::getReservedRegion(void* rawHandle, getReservedRegion_cb hidlCb) { + if (!mDriver) { + drv_log("Failed to getReservedRegion. Driver is uninitialized.\n"); + 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"); + 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"); + hidlCb(Error::BAD_BUFFER, nullptr, 0); + return Void(); + } + + void* reservedRegionAddr = nullptr; + uint64_t reservedRegionSize = 0; + int ret = mDriver->get_reserved_region(bufferHandle, &reservedRegionAddr, &reservedRegionSize); + if (ret) { + drv_log("Failed to getReservedRegion.\n"); + hidlCb(Error::BAD_BUFFER, nullptr, 0); + return Void(); + } + + hidlCb(Error::NONE, reservedRegionAddr, reservedRegionSize); + return Void(); +} + +android::hardware::graphics::mapper::V4_0::IMapper* HIDL_FETCH_IMapper(const char* /*name*/) { + return static_cast<android::hardware::graphics::mapper::V4_0::IMapper*>(new CrosGralloc4Mapper); +} diff --git a/cros_gralloc/gralloc4/CrosGralloc4Mapper.h b/cros_gralloc/gralloc4/CrosGralloc4Mapper.h new file mode 100644 index 0000000..b318930 --- /dev/null +++ b/cros_gralloc/gralloc4/CrosGralloc4Mapper.h @@ -0,0 +1,80 @@ +/* + * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <android/hardware/graphics/mapper/4.0/IMapper.h> + +#include "cros_gralloc/cros_gralloc_driver.h" +#include "cros_gralloc/cros_gralloc_handle.h" + +class CrosGralloc4Mapper : public android::hardware::graphics::mapper::V4_0::IMapper { + public: + CrosGralloc4Mapper(); + + android::hardware::Return<void> createDescriptor(const BufferDescriptorInfo& description, + createDescriptor_cb hidlCb) override; + + android::hardware::Return<void> importBuffer(const android::hardware::hidl_handle& rawHandle, + importBuffer_cb hidlCb) override; + + android::hardware::Return<android::hardware::graphics::mapper::V4_0::Error> freeBuffer( + void* rawHandle) override; + + android::hardware::Return<android::hardware::graphics::mapper::V4_0::Error> validateBufferSize( + void* rawHandle, const BufferDescriptorInfo& descriptor, uint32_t stride) override; + + android::hardware::Return<void> getTransportSize(void* rawHandle, + getTransportSize_cb hidlCb) override; + + android::hardware::Return<void> lock(void* rawHandle, uint64_t cpuUsage, + const Rect& accessRegion, + const android::hardware::hidl_handle& acquireFence, + lock_cb hidlCb) override; + + android::hardware::Return<void> unlock(void* rawHandle, unlock_cb hidlCb) override; + + android::hardware::Return<void> flushLockedBuffer(void* rawHandle, + flushLockedBuffer_cb hidlCb) override; + + android::hardware::Return<android::hardware::graphics::mapper::V4_0::Error> rereadLockedBuffer( + void* rawHandle) override; + + android::hardware::Return<void> isSupported(const BufferDescriptorInfo& descriptor, + isSupported_cb hidlCb) override; + + android::hardware::Return<void> get(void* rawHandle, const MetadataType& metadataType, + get_cb hidlCb) override; + + android::hardware::Return<android::hardware::graphics::mapper::V4_0::Error> set( + void* rawHandle, const MetadataType& metadataType, + const android::hardware::hidl_vec<uint8_t>& metadata) override; + + android::hardware::Return<void> getFromBufferDescriptorInfo( + const BufferDescriptorInfo& descriptor, const MetadataType& metadataType, + getFromBufferDescriptorInfo_cb hidlCb) override; + + android::hardware::Return<void> listSupportedMetadataTypes( + listSupportedMetadataTypes_cb hidlCb) override; + + android::hardware::Return<void> dumpBuffer(void* rawHandle, dumpBuffer_cb hidlCb) override; + android::hardware::Return<void> dumpBuffers(dumpBuffers_cb hidlCb) override; + + android::hardware::Return<void> getReservedRegion(void* rawHandle, + getReservedRegion_cb hidlCb) override; + + private: + android::hardware::Return<void> get(cros_gralloc_handle_t crosHandle, + const MetadataType& metadataType, get_cb hidlCb); + + android::hardware::Return<void> dumpBuffer(cros_gralloc_handle_t crosHandle, + dumpBuffer_cb hidlCb); + + int getResolvedDrmFormat(android::hardware::graphics::common::V1_2::PixelFormat pixelFormat, + uint64_t bufferUsage, uint32_t* outDrmFormat); + + std::unique_ptr<cros_gralloc_driver> mDriver; +}; + +extern "C" android::hardware::graphics::mapper::V4_0::IMapper* HIDL_FETCH_IMapper(const char* name); diff --git a/cros_gralloc/gralloc4/CrosGralloc4Utils.cc b/cros_gralloc/gralloc4/CrosGralloc4Utils.cc new file mode 100644 index 0000000..8931164 --- /dev/null +++ b/cros_gralloc/gralloc4/CrosGralloc4Utils.cc @@ -0,0 +1,772 @@ +/* + * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cros_gralloc/gralloc4/CrosGralloc4Utils.h" + +#include <array> +#include <unordered_map> + +#include <aidl/android/hardware/graphics/common/PlaneLayoutComponent.h> +#include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h> +#include <android-base/stringprintf.h> +#include <android-base/strings.h> +#include <cutils/native_handle.h> +#include <gralloctypes/Gralloc4.h> + +#include "cros_gralloc/cros_gralloc_helpers.h" + +using aidl::android::hardware::graphics::common::PlaneLayout; +using aidl::android::hardware::graphics::common::PlaneLayoutComponent; +using aidl::android::hardware::graphics::common::PlaneLayoutComponentType; +using android::hardware::hidl_bitfield; +using android::hardware::hidl_handle; +using android::hardware::graphics::common::V1_2::BufferUsage; +using android::hardware::graphics::common::V1_2::PixelFormat; + +using BufferDescriptorInfo = + android::hardware::graphics::mapper::V4_0::IMapper::BufferDescriptorInfo; + +std::string getDrmFormatString(uint32_t drmFormat) { + switch (drmFormat) { + case DRM_FORMAT_ABGR1555: + return "DRM_FORMAT_ABGR1555"; + case DRM_FORMAT_ABGR2101010: + return "DRM_FORMAT_ABGR2101010"; + case DRM_FORMAT_ABGR4444: + return "DRM_FORMAT_ABGR4444"; + case DRM_FORMAT_ABGR8888: + return "DRM_FORMAT_ABGR8888"; + case DRM_FORMAT_ARGB1555: + return "DRM_FORMAT_ARGB1555"; + case DRM_FORMAT_ARGB2101010: + return "DRM_FORMAT_ARGB2101010"; + case DRM_FORMAT_ARGB4444: + return "DRM_FORMAT_ARGB4444"; + case DRM_FORMAT_ARGB8888: + return "DRM_FORMAT_ARGB8888"; + case DRM_FORMAT_AYUV: + return "DRM_FORMAT_AYUV"; + case DRM_FORMAT_BGR233: + return "DRM_FORMAT_BGR233"; + case DRM_FORMAT_BGR565: + return "DRM_FORMAT_BGR565"; + case DRM_FORMAT_BGR888: + return "DRM_FORMAT_BGR888"; + case DRM_FORMAT_BGRA1010102: + return "DRM_FORMAT_BGRA1010102"; + case DRM_FORMAT_BGRA4444: + return "DRM_FORMAT_BGRA4444"; + case DRM_FORMAT_BGRA5551: + return "DRM_FORMAT_BGRA5551"; + case DRM_FORMAT_BGRA8888: + return "DRM_FORMAT_BGRA8888"; + case DRM_FORMAT_BGRX1010102: + return "DRM_FORMAT_BGRX1010102"; + case DRM_FORMAT_BGRX4444: + return "DRM_FORMAT_BGRX4444"; + case DRM_FORMAT_BGRX5551: + return "DRM_FORMAT_BGRX5551"; + case DRM_FORMAT_BGRX8888: + return "DRM_FORMAT_BGRX8888"; + case DRM_FORMAT_C8: + return "DRM_FORMAT_C8"; + case DRM_FORMAT_GR88: + return "DRM_FORMAT_GR88"; + case DRM_FORMAT_NV12: + return "DRM_FORMAT_NV12"; + case DRM_FORMAT_NV21: + return "DRM_FORMAT_NV21"; + case DRM_FORMAT_R8: + return "DRM_FORMAT_R8"; + case DRM_FORMAT_RG88: + return "DRM_FORMAT_RG88"; + case DRM_FORMAT_RGB332: + return "DRM_FORMAT_RGB332"; + case DRM_FORMAT_RGB565: + return "DRM_FORMAT_RGB565"; + case DRM_FORMAT_RGB888: + return "DRM_FORMAT_RGB888"; + case DRM_FORMAT_RGBA1010102: + return "DRM_FORMAT_RGBA1010102"; + case DRM_FORMAT_RGBA4444: + return "DRM_FORMAT_RGBA4444"; + case DRM_FORMAT_RGBA5551: + return "DRM_FORMAT_RGBA5551"; + case DRM_FORMAT_RGBA8888: + return "DRM_FORMAT_RGBA8888"; + case DRM_FORMAT_RGBX1010102: + return "DRM_FORMAT_RGBX1010102"; + case DRM_FORMAT_RGBX4444: + return "DRM_FORMAT_RGBX4444"; + case DRM_FORMAT_RGBX5551: + return "DRM_FORMAT_RGBX5551"; + case DRM_FORMAT_RGBX8888: + return "DRM_FORMAT_RGBX8888"; + case DRM_FORMAT_UYVY: + return "DRM_FORMAT_UYVY"; + case DRM_FORMAT_VYUY: + return "DRM_FORMAT_VYUY"; + case DRM_FORMAT_XBGR1555: + return "DRM_FORMAT_XBGR1555"; + case DRM_FORMAT_XBGR2101010: + return "DRM_FORMAT_XBGR2101010"; + case DRM_FORMAT_XBGR4444: + return "DRM_FORMAT_XBGR4444"; + case DRM_FORMAT_XBGR8888: + return "DRM_FORMAT_XBGR8888"; + case DRM_FORMAT_XRGB1555: + return "DRM_FORMAT_XRGB1555"; + case DRM_FORMAT_XRGB2101010: + return "DRM_FORMAT_XRGB2101010"; + case DRM_FORMAT_XRGB4444: + return "DRM_FORMAT_XRGB4444"; + case DRM_FORMAT_XRGB8888: + return "DRM_FORMAT_XRGB8888"; + case DRM_FORMAT_YUYV: + return "DRM_FORMAT_YUYV"; + case DRM_FORMAT_YVU420: + return "DRM_FORMAT_YVU420"; + case DRM_FORMAT_YVYU: + return "DRM_FORMAT_YVYU"; + } + return android::base::StringPrintf("Unknown(%d)", drmFormat); +} + +std::string getPixelFormatString(PixelFormat format) { + switch (format) { + case PixelFormat::BGRA_8888: + return "PixelFormat::BGRA_8888"; + case PixelFormat::BLOB: + return "PixelFormat::BLOB"; + case PixelFormat::DEPTH_16: + return "PixelFormat::DEPTH_16"; + case PixelFormat::DEPTH_24: + return "PixelFormat::DEPTH_24"; + case PixelFormat::DEPTH_24_STENCIL_8: + return "PixelFormat::DEPTH_24_STENCIL_8"; + case PixelFormat::DEPTH_32F: + return "PixelFormat::DEPTH_24"; + case PixelFormat::DEPTH_32F_STENCIL_8: + return "PixelFormat::DEPTH_24_STENCIL_8"; + case PixelFormat::HSV_888: + return "PixelFormat::HSV_888"; + case PixelFormat::IMPLEMENTATION_DEFINED: + return "PixelFormat::IMPLEMENTATION_DEFINED"; + case PixelFormat::RAW10: + return "PixelFormat::RAW10"; + case PixelFormat::RAW12: + return "PixelFormat::RAW12"; + case PixelFormat::RAW16: + return "PixelFormat::RAW16"; + case PixelFormat::RAW_OPAQUE: + return "PixelFormat::RAW_OPAQUE"; + case PixelFormat::RGBA_1010102: + return "PixelFormat::RGBA_1010102"; + case PixelFormat::RGBA_8888: + return "PixelFormat::RGBA_8888"; + case PixelFormat::RGBA_FP16: + return "PixelFormat::RGBA_FP16"; + case PixelFormat::RGBX_8888: + return "PixelFormat::RGBX_8888"; + case PixelFormat::RGB_565: + return "PixelFormat::RGB_565"; + case PixelFormat::RGB_888: + return "PixelFormat::RGB_888"; + case PixelFormat::STENCIL_8: + return "PixelFormat::STENCIL_8"; + case PixelFormat::Y16: + return "PixelFormat::Y16"; + case PixelFormat::Y8: + return "PixelFormat::Y8"; + case PixelFormat::YCBCR_420_888: + return "PixelFormat::YCBCR_420_888"; + case PixelFormat::YCBCR_422_I: + return "PixelFormat::YCBCR_422_I"; + case PixelFormat::YCBCR_422_SP: + return "PixelFormat::YCBCR_422_SP"; + case PixelFormat::YCBCR_P010: + return "PixelFormat::YCBCR_P010"; + case PixelFormat::YCRCB_420_SP: + return "PixelFormat::YCRCB_420_SP"; + case PixelFormat::YV12: + return "PixelFormat::YV12"; + } + return android::base::StringPrintf("PixelFormat::Unknown(%d)", static_cast<uint32_t>(format)); +} + +std::string getUsageString(hidl_bitfield<BufferUsage> bufferUsage) { + using Underlying = typename std::underlying_type<BufferUsage>::type; + + Underlying usage = static_cast<Underlying>(bufferUsage); + + std::vector<std::string> usages; + if (usage & BufferUsage::CAMERA_INPUT) { + usage &= ~static_cast<Underlying>(BufferUsage::CAMERA_INPUT); + usages.push_back("BufferUsage::CAMERA_INPUT"); + } + if (usage & BufferUsage::CAMERA_OUTPUT) { + usage &= ~static_cast<Underlying>(BufferUsage::CAMERA_OUTPUT); + usages.push_back("BufferUsage::CAMERA_OUTPUT"); + } + if (usage & BufferUsage::COMPOSER_CURSOR) { + usage &= ~static_cast<Underlying>(BufferUsage::COMPOSER_CURSOR); + usages.push_back("BufferUsage::COMPOSER_CURSOR"); + } + if (usage & BufferUsage::COMPOSER_OVERLAY) { + usage &= ~static_cast<Underlying>(BufferUsage::COMPOSER_OVERLAY); + usages.push_back("BufferUsage::COMPOSER_OVERLAY"); + } + if (usage & BufferUsage::CPU_READ_OFTEN) { + usage &= ~static_cast<Underlying>(BufferUsage::CPU_READ_OFTEN); + usages.push_back("BufferUsage::CPU_READ_OFTEN"); + } + if (usage & BufferUsage::CPU_READ_NEVER) { + usage &= ~static_cast<Underlying>(BufferUsage::CPU_READ_NEVER); + usages.push_back("BufferUsage::CPU_READ_NEVER"); + } + if (usage & BufferUsage::CPU_READ_RARELY) { + usage &= ~static_cast<Underlying>(BufferUsage::CPU_READ_RARELY); + usages.push_back("BufferUsage::CPU_READ_RARELY"); + } + if (usage & BufferUsage::CPU_WRITE_NEVER) { + usage &= ~static_cast<Underlying>(BufferUsage::CPU_WRITE_NEVER); + usages.push_back("BufferUsage::CPU_WRITE_NEVER"); + } + if (usage & BufferUsage::CPU_WRITE_OFTEN) { + usage &= ~static_cast<Underlying>(BufferUsage::CPU_WRITE_OFTEN); + usages.push_back("BufferUsage::CPU_WRITE_OFTEN"); + } + if (usage & BufferUsage::CPU_WRITE_RARELY) { + usage &= ~static_cast<Underlying>(BufferUsage::CPU_WRITE_RARELY); + usages.push_back("BufferUsage::CPU_WRITE_RARELY"); + } + if (usage & BufferUsage::GPU_RENDER_TARGET) { + usage &= ~static_cast<Underlying>(BufferUsage::GPU_RENDER_TARGET); + usages.push_back("BufferUsage::GPU_RENDER_TARGET"); + } + if (usage & BufferUsage::GPU_TEXTURE) { + usage &= ~static_cast<Underlying>(BufferUsage::GPU_TEXTURE); + usages.push_back("BufferUsage::GPU_TEXTURE"); + } + if (usage & BufferUsage::PROTECTED) { + usage &= ~static_cast<Underlying>(BufferUsage::PROTECTED); + usages.push_back("BufferUsage::PROTECTED"); + } + if (usage & BufferUsage::RENDERSCRIPT) { + usage &= ~static_cast<Underlying>(BufferUsage::RENDERSCRIPT); + usages.push_back("BufferUsage::RENDERSCRIPT"); + } + if (usage & BufferUsage::VIDEO_DECODER) { + usage &= ~static_cast<Underlying>(BufferUsage::VIDEO_DECODER); + usages.push_back("BufferUsage::VIDEO_DECODER"); + } + if (usage & BufferUsage::VIDEO_ENCODER) { + usage &= ~static_cast<Underlying>(BufferUsage::VIDEO_ENCODER); + usages.push_back("BufferUsage::VIDEO_ENCODER"); + } + + if (usage) { + usages.push_back(android::base::StringPrintf("UnknownUsageBits-%" PRIu64, usage)); + } + + return android::base::Join(usages, '|'); +} + +int convertToDrmFormat(PixelFormat format, uint32_t* outDrmFormat) { + switch (format) { + case PixelFormat::BGRA_8888: + *outDrmFormat = DRM_FORMAT_ARGB8888; + return 0; + /** + * Choose DRM_FORMAT_R8 because <system/graphics.h> requires the buffers + * with a format HAL_PIXEL_FORMAT_BLOB have a height of 1, and width + * equal to their size in bytes. + */ + case PixelFormat::BLOB: + *outDrmFormat = DRM_FORMAT_R8; + return 0; + case PixelFormat::DEPTH_16: + return -EINVAL; + case PixelFormat::DEPTH_24: + return -EINVAL; + case PixelFormat::DEPTH_24_STENCIL_8: + return -EINVAL; + case PixelFormat::DEPTH_32F: + return -EINVAL; + case PixelFormat::DEPTH_32F_STENCIL_8: + return -EINVAL; + case PixelFormat::HSV_888: + return -EINVAL; + case PixelFormat::IMPLEMENTATION_DEFINED: + *outDrmFormat = DRM_FORMAT_FLEX_IMPLEMENTATION_DEFINED; + return 0; + case PixelFormat::RAW10: + return -EINVAL; + case PixelFormat::RAW12: + return -EINVAL; + case PixelFormat::RAW16: + *outDrmFormat = DRM_FORMAT_R16; + return 0; + /* TODO use blob */ + case PixelFormat::RAW_OPAQUE: + return -EINVAL; + case PixelFormat::RGBA_1010102: + *outDrmFormat = DRM_FORMAT_ABGR2101010; + return 0; + case PixelFormat::RGBA_8888: + *outDrmFormat = DRM_FORMAT_ABGR8888; + return 0; + case PixelFormat::RGBA_FP16: + *outDrmFormat = DRM_FORMAT_ABGR16161616F; + return 0; + case PixelFormat::RGBX_8888: + *outDrmFormat = DRM_FORMAT_XBGR8888; + return 0; + case PixelFormat::RGB_565: + *outDrmFormat = DRM_FORMAT_RGB565; + return 0; + case PixelFormat::RGB_888: + *outDrmFormat = DRM_FORMAT_RGB888; + return 0; + case PixelFormat::STENCIL_8: + return -EINVAL; + case PixelFormat::Y16: + *outDrmFormat = DRM_FORMAT_R16; + return 0; + case PixelFormat::Y8: + *outDrmFormat = DRM_FORMAT_R8; + return 0; + case PixelFormat::YCBCR_420_888: + *outDrmFormat = DRM_FORMAT_FLEX_YCbCr_420_888; + return 0; + case PixelFormat::YCBCR_422_SP: + return -EINVAL; + case PixelFormat::YCBCR_422_I: + return -EINVAL; + case PixelFormat::YCBCR_P010: + *outDrmFormat = DRM_FORMAT_P010; + return 0; + case PixelFormat::YCRCB_420_SP: + *outDrmFormat = DRM_FORMAT_NV21; + return 0; + case PixelFormat::YV12: + *outDrmFormat = DRM_FORMAT_YVU420_ANDROID; + return 0; + }; + return -EINVAL; +} + +int convertToBufferUsage(uint64_t grallocUsage, uint64_t* outBufferUsage) { + uint64_t bufferUsage = BO_USE_NONE; + + if ((grallocUsage & BufferUsage::CPU_READ_MASK) == + static_cast<uint64_t>(BufferUsage::CPU_READ_RARELY)) { + bufferUsage |= BO_USE_SW_READ_RARELY; + } + if ((grallocUsage & BufferUsage::CPU_READ_MASK) == + static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN)) { + bufferUsage |= BO_USE_SW_READ_OFTEN; + } + if ((grallocUsage & BufferUsage::CPU_WRITE_MASK) == + static_cast<uint64_t>(BufferUsage::CPU_WRITE_RARELY)) { + bufferUsage |= BO_USE_SW_WRITE_RARELY; + } + if ((grallocUsage & BufferUsage::CPU_WRITE_MASK) == + static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN)) { + bufferUsage |= BO_USE_SW_WRITE_OFTEN; + } + if (grallocUsage & BufferUsage::GPU_TEXTURE) { + bufferUsage |= BO_USE_TEXTURE; + } + if (grallocUsage & BufferUsage::GPU_RENDER_TARGET) { + bufferUsage |= BO_USE_RENDERING; + } + if (grallocUsage & BufferUsage::COMPOSER_OVERLAY) { + /* HWC wants to use display hardware, but can defer to OpenGL. */ + bufferUsage |= BO_USE_SCANOUT | BO_USE_TEXTURE; + } + if (grallocUsage & BufferUsage::PROTECTED) { + bufferUsage |= BO_USE_PROTECTED; + } + if (grallocUsage & BufferUsage::COMPOSER_CURSOR) { + bufferUsage |= BO_USE_NONE; + } + if (grallocUsage & BufferUsage::VIDEO_ENCODER) { + /*HACK: See b/30054495 */ + bufferUsage |= BO_USE_SW_READ_OFTEN; + } + if (grallocUsage & BufferUsage::CAMERA_OUTPUT) { + bufferUsage |= BO_USE_CAMERA_WRITE; + } + if (grallocUsage & BufferUsage::CAMERA_INPUT) { + bufferUsage |= BO_USE_CAMERA_READ; + } + if (grallocUsage & BufferUsage::RENDERSCRIPT) { + bufferUsage |= BO_USE_RENDERSCRIPT; + } + if (grallocUsage & BufferUsage::VIDEO_DECODER) { + bufferUsage |= BO_USE_HW_VIDEO_DECODER; + } + + *outBufferUsage = bufferUsage; + return 0; +} + +int convertToCrosDescriptor(const BufferDescriptorInfo& descriptor, + struct cros_gralloc_buffer_descriptor* outCrosDescriptor) { + outCrosDescriptor->name = descriptor.name; + outCrosDescriptor->width = descriptor.width; + outCrosDescriptor->height = descriptor.height; + outCrosDescriptor->droid_format = static_cast<int32_t>(descriptor.format); + outCrosDescriptor->droid_usage = descriptor.usage; + outCrosDescriptor->reserved_region_size = descriptor.reservedSize; + + if (convertToDrmFormat(descriptor.format, &outCrosDescriptor->drm_format)) { + std::string pixelFormatString = getPixelFormatString(descriptor.format); + drv_log("Failed to convert descriptor. Unsupported fomat %s\n", pixelFormatString.c_str()); + return -1; + } + if (convertToBufferUsage(descriptor.usage, &outCrosDescriptor->use_flags)) { + std::string usageString = getUsageString(descriptor.usage); + drv_log("Failed to convert descriptor. Unsupported usage flags %s\n", usageString.c_str()); + return -1; + } + return 0; +} + +int convertToMapUsage(uint64_t grallocUsage, uint32_t* outMapUsage) { + uint32_t mapUsage = BO_MAP_NONE; + + if (grallocUsage & BufferUsage::CPU_READ_MASK) { + mapUsage |= BO_MAP_READ; + } + if (grallocUsage & BufferUsage::CPU_WRITE_MASK) { + mapUsage |= BO_MAP_WRITE; + } + + *outMapUsage = mapUsage; + return 0; +} + +int convertToFenceFd(const hidl_handle& fenceHandle, int* outFenceFd) { + if (!outFenceFd) { + return -EINVAL; + } + + const native_handle_t* nativeHandle = fenceHandle.getNativeHandle(); + if (nativeHandle && nativeHandle->numFds > 1) { + return -EINVAL; + } + + *outFenceFd = (nativeHandle && nativeHandle->numFds == 1) ? nativeHandle->data[0] : -1; + return 0; +} + +int convertToFenceHandle(int fenceFd, hidl_handle* outFenceHandle) { + if (!outFenceHandle) { + return -EINVAL; + } + if (fenceFd < 0) { + return 0; + } + + NATIVE_HANDLE_DECLARE_STORAGE(handleStorage, 1, 0); + auto fenceHandle = native_handle_init(handleStorage, 1, 0); + fenceHandle->data[0] = fenceFd; + + *outFenceHandle = fenceHandle; + return 0; +} + +const std::unordered_map<uint32_t, std::vector<PlaneLayout>>& GetPlaneLayoutsMap() { + static const auto* kPlaneLayoutsMap = + new std::unordered_map<uint32_t, std::vector<PlaneLayout>>({ + {DRM_FORMAT_ABGR8888, + {{ + .components = {{.type = android::gralloc4::PlaneLayoutComponentType_R, + .offsetInBits = 0, + .sizeInBits = 8}, + {.type = android::gralloc4::PlaneLayoutComponentType_G, + .offsetInBits = 8, + .sizeInBits = 8}, + {.type = android::gralloc4::PlaneLayoutComponentType_B, + .offsetInBits = 16, + .sizeInBits = 8}, + {.type = android::gralloc4::PlaneLayoutComponentType_A, + .offsetInBits = 24, + .sizeInBits = 8}}, + .sampleIncrementInBits = 32, + .horizontalSubsampling = 1, + .verticalSubsampling = 1, + }}}, + + {DRM_FORMAT_ABGR2101010, + {{ + .components = {{.type = android::gralloc4::PlaneLayoutComponentType_R, + .offsetInBits = 0, + .sizeInBits = 10}, + {.type = android::gralloc4::PlaneLayoutComponentType_G, + .offsetInBits = 10, + .sizeInBits = 10}, + {.type = android::gralloc4::PlaneLayoutComponentType_B, + .offsetInBits = 20, + .sizeInBits = 10}, + {.type = android::gralloc4::PlaneLayoutComponentType_A, + .offsetInBits = 30, + .sizeInBits = 2}}, + .sampleIncrementInBits = 32, + .horizontalSubsampling = 1, + .verticalSubsampling = 1, + }}}, + + {DRM_FORMAT_ABGR16161616F, + {{ + .components = {{.type = android::gralloc4::PlaneLayoutComponentType_R, + .offsetInBits = 0, + .sizeInBits = 16}, + {.type = android::gralloc4::PlaneLayoutComponentType_G, + .offsetInBits = 16, + .sizeInBits = 16}, + {.type = android::gralloc4::PlaneLayoutComponentType_B, + .offsetInBits = 32, + .sizeInBits = 16}, + {.type = android::gralloc4::PlaneLayoutComponentType_A, + .offsetInBits = 48, + .sizeInBits = 16}}, + .sampleIncrementInBits = 64, + .horizontalSubsampling = 1, + .verticalSubsampling = 1, + }}}, + + {DRM_FORMAT_ARGB8888, + {{ + .components = {{.type = android::gralloc4::PlaneLayoutComponentType_B, + .offsetInBits = 0, + .sizeInBits = 8}, + {.type = android::gralloc4::PlaneLayoutComponentType_G, + .offsetInBits = 8, + .sizeInBits = 8}, + {.type = android::gralloc4::PlaneLayoutComponentType_R, + .offsetInBits = 16, + .sizeInBits = 8}, + {.type = android::gralloc4::PlaneLayoutComponentType_A, + .offsetInBits = 24, + .sizeInBits = 8}}, + .sampleIncrementInBits = 32, + .horizontalSubsampling = 1, + .verticalSubsampling = 1, + }}}, + + {DRM_FORMAT_NV12, + {{ + .components = {{.type = android::gralloc4::PlaneLayoutComponentType_Y, + .offsetInBits = 0, + .sizeInBits = 8}}, + .sampleIncrementInBits = 8, + .horizontalSubsampling = 1, + .verticalSubsampling = 1, + }, + { + .components = + {{.type = android::gralloc4::PlaneLayoutComponentType_CB, + .offsetInBits = 0, + .sizeInBits = 8}, + {.type = android::gralloc4::PlaneLayoutComponentType_CR, + .offsetInBits = 8, + .sizeInBits = 8}}, + .sampleIncrementInBits = 16, + .horizontalSubsampling = 2, + .verticalSubsampling = 2, + }}}, + + {DRM_FORMAT_NV21, + {{ + .components = {{.type = android::gralloc4::PlaneLayoutComponentType_Y, + .offsetInBits = 0, + .sizeInBits = 8}}, + .sampleIncrementInBits = 8, + .horizontalSubsampling = 1, + .verticalSubsampling = 1, + }, + { + .components = + {{.type = android::gralloc4::PlaneLayoutComponentType_CR, + .offsetInBits = 0, + .sizeInBits = 8}, + {.type = android::gralloc4::PlaneLayoutComponentType_CB, + .offsetInBits = 8, + .sizeInBits = 8}}, + .sampleIncrementInBits = 16, + .horizontalSubsampling = 2, + .verticalSubsampling = 2, + }}}, + + {DRM_FORMAT_P010, + {{ + .components = {{.type = android::gralloc4::PlaneLayoutComponentType_Y, + .offsetInBits = 6, + .sizeInBits = 10}}, + .sampleIncrementInBits = 16, + .horizontalSubsampling = 1, + .verticalSubsampling = 1, + }, + { + .components = + {{.type = android::gralloc4::PlaneLayoutComponentType_CB, + .offsetInBits = 6, + .sizeInBits = 10}, + {.type = android::gralloc4::PlaneLayoutComponentType_CR, + .offsetInBits = 22, + .sizeInBits = 10}}, + .sampleIncrementInBits = 32, + .horizontalSubsampling = 2, + .verticalSubsampling = 2, + }}}, + + {DRM_FORMAT_R8, + {{ + .components = {{.type = android::gralloc4::PlaneLayoutComponentType_R, + .offsetInBits = 0, + .sizeInBits = 8}}, + .sampleIncrementInBits = 8, + .horizontalSubsampling = 1, + .verticalSubsampling = 1, + }}}, + + {DRM_FORMAT_R16, + {{ + .components = {{.type = android::gralloc4::PlaneLayoutComponentType_R, + .offsetInBits = 0, + .sizeInBits = 16}}, + .sampleIncrementInBits = 16, + .horizontalSubsampling = 1, + .verticalSubsampling = 1, + }}}, + + {DRM_FORMAT_RGB565, + {{ + .components = {{.type = android::gralloc4::PlaneLayoutComponentType_R, + .offsetInBits = 0, + .sizeInBits = 5}, + {.type = android::gralloc4::PlaneLayoutComponentType_G, + .offsetInBits = 5, + .sizeInBits = 6}, + {.type = android::gralloc4::PlaneLayoutComponentType_B, + .offsetInBits = 11, + .sizeInBits = 5}}, + .sampleIncrementInBits = 16, + .horizontalSubsampling = 1, + .verticalSubsampling = 1, + }}}, + + {DRM_FORMAT_RGB888, + {{ + .components = {{.type = android::gralloc4::PlaneLayoutComponentType_R, + .offsetInBits = 0, + .sizeInBits = 8}, + {.type = android::gralloc4::PlaneLayoutComponentType_G, + .offsetInBits = 8, + .sizeInBits = 8}, + {.type = android::gralloc4::PlaneLayoutComponentType_B, + .offsetInBits = 16, + .sizeInBits = 8}}, + .sampleIncrementInBits = 24, + .horizontalSubsampling = 1, + .verticalSubsampling = 1, + }}}, + + {DRM_FORMAT_XBGR8888, + {{ + .components = {{.type = android::gralloc4::PlaneLayoutComponentType_B, + .offsetInBits = 0, + .sizeInBits = 8}, + {.type = android::gralloc4::PlaneLayoutComponentType_G, + .offsetInBits = 8, + .sizeInBits = 8}, + {.type = android::gralloc4::PlaneLayoutComponentType_R, + .offsetInBits = 16, + .sizeInBits = 8}}, + .sampleIncrementInBits = 32, + .horizontalSubsampling = 1, + .verticalSubsampling = 1, + }}}, + + {DRM_FORMAT_YVU420, + { + { + .components = {{.type = android::gralloc4:: + PlaneLayoutComponentType_Y, + .offsetInBits = 0, + .sizeInBits = 8}}, + .sampleIncrementInBits = 8, + .horizontalSubsampling = 1, + .verticalSubsampling = 1, + }, + { + .components = {{.type = android::gralloc4:: + PlaneLayoutComponentType_CB, + .offsetInBits = 0, + .sizeInBits = 8}}, + .sampleIncrementInBits = 8, + .horizontalSubsampling = 2, + .verticalSubsampling = 2, + }, + { + .components = {{.type = android::gralloc4:: + PlaneLayoutComponentType_CR, + .offsetInBits = 0, + .sizeInBits = 8}}, + .sampleIncrementInBits = 8, + .horizontalSubsampling = 2, + .verticalSubsampling = 2, + }, + }}, + + {DRM_FORMAT_YVU420_ANDROID, + { + { + .components = {{.type = android::gralloc4:: + PlaneLayoutComponentType_Y, + .offsetInBits = 0, + .sizeInBits = 8}}, + .sampleIncrementInBits = 8, + .horizontalSubsampling = 1, + .verticalSubsampling = 1, + }, + { + .components = {{.type = android::gralloc4:: + PlaneLayoutComponentType_CR, + .offsetInBits = 0, + .sizeInBits = 8}}, + .sampleIncrementInBits = 8, + .horizontalSubsampling = 2, + .verticalSubsampling = 2, + }, + { + .components = {{.type = android::gralloc4:: + PlaneLayoutComponentType_CB, + .offsetInBits = 0, + .sizeInBits = 8}}, + .sampleIncrementInBits = 8, + .horizontalSubsampling = 2, + .verticalSubsampling = 2, + }, + }}, + }); + return *kPlaneLayoutsMap; +} + +int getPlaneLayouts(uint32_t drmFormat, std::vector<PlaneLayout>* outPlaneLayouts) { + const auto& planeLayoutsMap = GetPlaneLayoutsMap(); + const auto it = planeLayoutsMap.find(drmFormat); + if (it == planeLayoutsMap.end()) { + drv_log("Unknown plane layout for format %d\n", drmFormat); + return -1; + } + + *outPlaneLayouts = it->second; + return 0; +}
\ No newline at end of file diff --git a/cros_gralloc/gralloc4/CrosGralloc4Utils.h b/cros_gralloc/gralloc4/CrosGralloc4Utils.h new file mode 100644 index 0000000..094ef74 --- /dev/null +++ b/cros_gralloc/gralloc4/CrosGralloc4Utils.h @@ -0,0 +1,41 @@ +/* + * Copyright 2020 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include <string> +#include <vector> + +#include <aidl/android/hardware/graphics/common/PlaneLayout.h> +#include <android/hardware/graphics/common/1.2/types.h> +#include <android/hardware/graphics/mapper/4.0/IMapper.h> + +#include "cros_gralloc/cros_gralloc_types.h" + +std::string getDrmFormatString(uint32_t drmFormat); + +std::string getPixelFormatString(android::hardware::graphics::common::V1_2::PixelFormat format); + +std::string getUsageString( + android::hardware::hidl_bitfield<android::hardware::graphics::common::V1_2::BufferUsage> + usage); + +int convertToDrmFormat(android::hardware::graphics::common::V1_2::PixelFormat format, + uint32_t* outDrmFormat); + +int convertToBufferUsage(uint64_t grallocUsage, uint64_t* outBufferUsage); + +int convertToCrosDescriptor( + const android::hardware::graphics::mapper::V4_0::IMapper::BufferDescriptorInfo& descriptor, + struct cros_gralloc_buffer_descriptor* outCrosDescriptor); + +int convertToMapUsage(uint64_t grallocUsage, uint32_t* outMapUsage); + +int convertToFenceFd(const android::hardware::hidl_handle& fence_handle, int* out_fence_fd); + +int convertToFenceHandle(int fence_fd, android::hardware::hidl_handle* out_fence_handle); + +int getPlaneLayouts( + uint32_t drm_format, + std::vector<aidl::android::hardware::graphics::common::PlaneLayout>* out_layouts);
\ No newline at end of file diff --git a/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm.rc b/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm.rc new file mode 100644 index 0000000..a96a6e1 --- /dev/null +++ b/cros_gralloc/gralloc4/android.hardware.graphics.allocator@4.0-service.minigbm.rc @@ -0,0 +1,24 @@ +# +# Copyright 2020 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +service vendor.graphics.allocator-4-0 /vendor/bin/hw/android.hardware.graphics.allocator@4.0-service.minigbm + interface android.hardware.graphics.allocator@4.0::IAllocator default + class hal animation + user system + group graphics drmrpc + capabilities SYS_NICE + onrestart restart surfaceflinger + writepid /dev/cpuset/system-background/tasks @@ -34,7 +34,9 @@ static const struct { { DRM_FORMAT_XBGR8888, __DRI_IMAGE_FORMAT_XBGR8888 }, { DRM_FORMAT_ABGR8888, __DRI_IMAGE_FORMAT_ABGR8888 }, { DRM_FORMAT_XRGB2101010, __DRI_IMAGE_FORMAT_XRGB2101010 }, + { DRM_FORMAT_XBGR2101010, __DRI_IMAGE_FORMAT_XBGR2101010 }, { DRM_FORMAT_ARGB2101010, __DRI_IMAGE_FORMAT_ARGB2101010 }, + { DRM_FORMAT_ABGR2101010, __DRI_IMAGE_FORMAT_ABGR2101010 }, }; static int drm_format_to_dri_format(uint32_t drm_format) @@ -89,6 +89,7 @@ struct drv_import_fd_data { uint32_t width; uint32_t height; uint32_t format; + uint32_t tiling; uint64_t use_flags; }; diff --git a/virgl_hw.h b/external/virgl_hw.h index 7f4a63f..7f4a63f 100644 --- a/virgl_hw.h +++ b/external/virgl_hw.h diff --git a/external/virgl_protocol.h b/external/virgl_protocol.h new file mode 100644 index 0000000..d9884df --- /dev/null +++ b/external/virgl_protocol.h @@ -0,0 +1,632 @@ +/* + * Copyright 2014, 2015 Red Hat. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef VIRGL_PROTOCOL_H +#define VIRGL_PROTOCOL_H + +#define VIRGL_QUERY_STATE_NEW 0 +#define VIRGL_QUERY_STATE_DONE 1 +#define VIRGL_QUERY_STATE_WAIT_HOST 2 + +struct virgl_host_query_state { + uint32_t query_state; + uint32_t result_size; + uint64_t result; +}; + +enum virgl_object_type { + VIRGL_OBJECT_NULL, + VIRGL_OBJECT_BLEND, + VIRGL_OBJECT_RASTERIZER, + VIRGL_OBJECT_DSA, + VIRGL_OBJECT_SHADER, + VIRGL_OBJECT_VERTEX_ELEMENTS, + VIRGL_OBJECT_SAMPLER_VIEW, + VIRGL_OBJECT_SAMPLER_STATE, + VIRGL_OBJECT_SURFACE, + VIRGL_OBJECT_QUERY, + VIRGL_OBJECT_STREAMOUT_TARGET, + VIRGL_MAX_OBJECTS, +}; + +/* context cmds to be encoded in the command stream */ +enum virgl_context_cmd { + VIRGL_CCMD_NOP = 0, + VIRGL_CCMD_CREATE_OBJECT = 1, + VIRGL_CCMD_BIND_OBJECT, + VIRGL_CCMD_DESTROY_OBJECT, + VIRGL_CCMD_SET_VIEWPORT_STATE, + VIRGL_CCMD_SET_FRAMEBUFFER_STATE, + VIRGL_CCMD_SET_VERTEX_BUFFERS, + VIRGL_CCMD_CLEAR, + VIRGL_CCMD_DRAW_VBO, + VIRGL_CCMD_RESOURCE_INLINE_WRITE, + VIRGL_CCMD_SET_SAMPLER_VIEWS, + VIRGL_CCMD_SET_INDEX_BUFFER, + VIRGL_CCMD_SET_CONSTANT_BUFFER, + VIRGL_CCMD_SET_STENCIL_REF, + VIRGL_CCMD_SET_BLEND_COLOR, + VIRGL_CCMD_SET_SCISSOR_STATE, + VIRGL_CCMD_BLIT, + VIRGL_CCMD_RESOURCE_COPY_REGION, + VIRGL_CCMD_BIND_SAMPLER_STATES, + VIRGL_CCMD_BEGIN_QUERY, + VIRGL_CCMD_END_QUERY, + VIRGL_CCMD_GET_QUERY_RESULT, + VIRGL_CCMD_SET_POLYGON_STIPPLE, + VIRGL_CCMD_SET_CLIP_STATE, + VIRGL_CCMD_SET_SAMPLE_MASK, + VIRGL_CCMD_SET_STREAMOUT_TARGETS, + VIRGL_CCMD_SET_RENDER_CONDITION, + VIRGL_CCMD_SET_UNIFORM_BUFFER, + + VIRGL_CCMD_SET_SUB_CTX, + VIRGL_CCMD_CREATE_SUB_CTX, + VIRGL_CCMD_DESTROY_SUB_CTX, + VIRGL_CCMD_BIND_SHADER, + VIRGL_CCMD_SET_TESS_STATE, + VIRGL_CCMD_SET_MIN_SAMPLES, + VIRGL_CCMD_SET_SHADER_BUFFERS, + VIRGL_CCMD_SET_SHADER_IMAGES, + VIRGL_CCMD_MEMORY_BARRIER, + VIRGL_CCMD_LAUNCH_GRID, + VIRGL_CCMD_SET_FRAMEBUFFER_STATE_NO_ATTACH, + VIRGL_CCMD_TEXTURE_BARRIER, + VIRGL_CCMD_SET_ATOMIC_BUFFERS, + VIRGL_CCMD_SET_DEBUG_FLAGS, + VIRGL_CCMD_GET_QUERY_RESULT_QBO, + VIRGL_CCMD_TRANSFER3D, + VIRGL_CCMD_END_TRANSFERS, + VIRGL_CCMD_COPY_TRANSFER3D, + VIRGL_CCMD_SET_TWEAKS, + VIRGL_CCMD_CLEAR_TEXTURE, + VIRGL_CCMD_PIPE_RESOURCE_CREATE, +}; + +/* + 8-bit cmd headers + 8-bit object type + 16-bit length +*/ + +#define VIRGL_CMD0(cmd, obj, len) ((cmd) | ((obj) << 8) | ((len) << 16)) +#define VIRGL_CMD0_MAX_DWORDS (((1ULL << 16) - 1) / 4) * 4 + +/* hw specification */ +#define VIRGL_MAX_COLOR_BUFS 8 +#define VIRGL_MAX_CLIP_PLANES 8 + +#define VIRGL_OBJ_CREATE_HEADER 0 +#define VIRGL_OBJ_CREATE_HANDLE 1 + +#define VIRGL_OBJ_BIND_HEADER 0 +#define VIRGL_OBJ_BIND_HANDLE 1 + +#define VIRGL_OBJ_DESTROY_HANDLE 1 + +/* some of these defines are a specification - not used in the code */ +/* bit offsets for blend state object */ +#define VIRGL_OBJ_BLEND_SIZE (VIRGL_MAX_COLOR_BUFS + 3) +#define VIRGL_OBJ_BLEND_HANDLE 1 +#define VIRGL_OBJ_BLEND_S0 2 +#define VIRGL_OBJ_BLEND_S0_INDEPENDENT_BLEND_ENABLE(x) ((x) & 0x1 << 0) +#define VIRGL_OBJ_BLEND_S0_LOGICOP_ENABLE(x) (((x) & 0x1) << 1) +#define VIRGL_OBJ_BLEND_S0_DITHER(x) (((x) & 0x1) << 2) +#define VIRGL_OBJ_BLEND_S0_ALPHA_TO_COVERAGE(x) (((x) & 0x1) << 3) +#define VIRGL_OBJ_BLEND_S0_ALPHA_TO_ONE(x) (((x) & 0x1) << 4) +#define VIRGL_OBJ_BLEND_S1 3 +#define VIRGL_OBJ_BLEND_S1_LOGICOP_FUNC(x) (((x) & 0xf) << 0) +/* repeated once per number of cbufs */ + +#define VIRGL_OBJ_BLEND_S2(cbuf) (4 + (cbuf)) +#define VIRGL_OBJ_BLEND_S2_RT_BLEND_ENABLE(x) (((x) & 0x1) << 0) +#define VIRGL_OBJ_BLEND_S2_RT_RGB_FUNC(x) (((x) & 0x7) << 1) +#define VIRGL_OBJ_BLEND_S2_RT_RGB_SRC_FACTOR(x) (((x) & 0x1f) << 4) +#define VIRGL_OBJ_BLEND_S2_RT_RGB_DST_FACTOR(x) (((x) & 0x1f) << 9) +#define VIRGL_OBJ_BLEND_S2_RT_ALPHA_FUNC(x) (((x) & 0x7) << 14) +#define VIRGL_OBJ_BLEND_S2_RT_ALPHA_SRC_FACTOR(x) (((x) & 0x1f) << 17) +#define VIRGL_OBJ_BLEND_S2_RT_ALPHA_DST_FACTOR(x) (((x) & 0x1f) << 22) +#define VIRGL_OBJ_BLEND_S2_RT_COLORMASK(x) (((x) & 0xf) << 27) + +/* bit offsets for DSA state */ +#define VIRGL_OBJ_DSA_SIZE 5 +#define VIRGL_OBJ_DSA_HANDLE 1 +#define VIRGL_OBJ_DSA_S0 2 +#define VIRGL_OBJ_DSA_S0_DEPTH_ENABLE(x) (((x) & 0x1) << 0) +#define VIRGL_OBJ_DSA_S0_DEPTH_WRITEMASK(x) (((x) & 0x1) << 1) +#define VIRGL_OBJ_DSA_S0_DEPTH_FUNC(x) (((x) & 0x7) << 2) +#define VIRGL_OBJ_DSA_S0_ALPHA_ENABLED(x) (((x) & 0x1) << 8) +#define VIRGL_OBJ_DSA_S0_ALPHA_FUNC(x) (((x) & 0x7) << 9) +#define VIRGL_OBJ_DSA_S1 3 +#define VIRGL_OBJ_DSA_S2 4 +#define VIRGL_OBJ_DSA_S1_STENCIL_ENABLED(x) (((x) & 0x1) << 0) +#define VIRGL_OBJ_DSA_S1_STENCIL_FUNC(x) (((x) & 0x7) << 1) +#define VIRGL_OBJ_DSA_S1_STENCIL_FAIL_OP(x) (((x) & 0x7) << 4) +#define VIRGL_OBJ_DSA_S1_STENCIL_ZPASS_OP(x) (((x) & 0x7) << 7) +#define VIRGL_OBJ_DSA_S1_STENCIL_ZFAIL_OP(x) (((x) & 0x7) << 10) +#define VIRGL_OBJ_DSA_S1_STENCIL_VALUEMASK(x) (((x) & 0xff) << 13) +#define VIRGL_OBJ_DSA_S1_STENCIL_WRITEMASK(x) (((x) & 0xff) << 21) +#define VIRGL_OBJ_DSA_ALPHA_REF 5 + +/* offsets for rasterizer state */ +#define VIRGL_OBJ_RS_SIZE 9 +#define VIRGL_OBJ_RS_HANDLE 1 +#define VIRGL_OBJ_RS_S0 2 +#define VIRGL_OBJ_RS_S0_FLATSHADE(x) (((x) & 0x1) << 0) +#define VIRGL_OBJ_RS_S0_DEPTH_CLIP(x) (((x) & 0x1) << 1) +#define VIRGL_OBJ_RS_S0_CLIP_HALFZ(x) (((x) & 0x1) << 2) +#define VIRGL_OBJ_RS_S0_RASTERIZER_DISCARD(x) (((x) & 0x1) << 3) +#define VIRGL_OBJ_RS_S0_FLATSHADE_FIRST(x) (((x) & 0x1) << 4) +#define VIRGL_OBJ_RS_S0_LIGHT_TWOSIZE(x) (((x) & 0x1) << 5) +#define VIRGL_OBJ_RS_S0_SPRITE_COORD_MODE(x) (((x) & 0x1) << 6) +#define VIRGL_OBJ_RS_S0_POINT_QUAD_RASTERIZATION(x) (((x) & 0x1) << 7) +#define VIRGL_OBJ_RS_S0_CULL_FACE(x) (((x) & 0x3) << 8) +#define VIRGL_OBJ_RS_S0_FILL_FRONT(x) (((x) & 0x3) << 10) +#define VIRGL_OBJ_RS_S0_FILL_BACK(x) (((x) & 0x3) << 12) +#define VIRGL_OBJ_RS_S0_SCISSOR(x) (((x) & 0x1) << 14) +#define VIRGL_OBJ_RS_S0_FRONT_CCW(x) (((x) & 0x1) << 15) +#define VIRGL_OBJ_RS_S0_CLAMP_VERTEX_COLOR(x) (((x) & 0x1) << 16) +#define VIRGL_OBJ_RS_S0_CLAMP_FRAGMENT_COLOR(x) (((x) & 0x1) << 17) +#define VIRGL_OBJ_RS_S0_OFFSET_LINE(x) (((x) & 0x1) << 18) +#define VIRGL_OBJ_RS_S0_OFFSET_POINT(x) (((x) & 0x1) << 19) +#define VIRGL_OBJ_RS_S0_OFFSET_TRI(x) (((x) & 0x1) << 20) +#define VIRGL_OBJ_RS_S0_POLY_SMOOTH(x) (((x) & 0x1) << 21) +#define VIRGL_OBJ_RS_S0_POLY_STIPPLE_ENABLE(x) (((x) & 0x1) << 22) +#define VIRGL_OBJ_RS_S0_POINT_SMOOTH(x) (((x) & 0x1) << 23) +#define VIRGL_OBJ_RS_S0_POINT_SIZE_PER_VERTEX(x) (((x) & 0x1) << 24) +#define VIRGL_OBJ_RS_S0_MULTISAMPLE(x) (((x) & 0x1) << 25) +#define VIRGL_OBJ_RS_S0_LINE_SMOOTH(x) (((x) & 0x1) << 26) +#define VIRGL_OBJ_RS_S0_LINE_STIPPLE_ENABLE(x) (((x) & 0x1) << 27) +#define VIRGL_OBJ_RS_S0_LINE_LAST_PIXEL(x) (((x) & 0x1) << 28) +#define VIRGL_OBJ_RS_S0_HALF_PIXEL_CENTER(x) (((x) & 0x1) << 29) +#define VIRGL_OBJ_RS_S0_BOTTOM_EDGE_RULE(x) (((x) & 0x1) << 30) +#define VIRGL_OBJ_RS_S0_FORCE_PERSAMPLE_INTERP(x) (((x) & 0x1) << 31) + +#define VIRGL_OBJ_RS_POINT_SIZE 3 +#define VIRGL_OBJ_RS_SPRITE_COORD_ENABLE 4 +#define VIRGL_OBJ_RS_S3 5 + +#define VIRGL_OBJ_RS_S3_LINE_STIPPLE_PATTERN(x) (((x) & 0xffff) << 0) +#define VIRGL_OBJ_RS_S3_LINE_STIPPLE_FACTOR(x) (((x) & 0xff) << 16) +#define VIRGL_OBJ_RS_S3_CLIP_PLANE_ENABLE(x) (((x) & 0xff) << 24) +#define VIRGL_OBJ_RS_LINE_WIDTH 6 +#define VIRGL_OBJ_RS_OFFSET_UNITS 7 +#define VIRGL_OBJ_RS_OFFSET_SCALE 8 +#define VIRGL_OBJ_RS_OFFSET_CLAMP 9 + +#define VIRGL_OBJ_CLEAR_SIZE 8 +#define VIRGL_OBJ_CLEAR_BUFFERS 1 +#define VIRGL_OBJ_CLEAR_COLOR_0 2 /* color is 4 * u32/f32/i32 */ +#define VIRGL_OBJ_CLEAR_COLOR_1 3 +#define VIRGL_OBJ_CLEAR_COLOR_2 4 +#define VIRGL_OBJ_CLEAR_COLOR_3 5 +#define VIRGL_OBJ_CLEAR_DEPTH_0 6 /* depth is a double precision float */ +#define VIRGL_OBJ_CLEAR_DEPTH_1 7 +#define VIRGL_OBJ_CLEAR_STENCIL 8 + +/* shader object */ +#define VIRGL_OBJ_SHADER_HDR_SIZE(nso) (5 + ((nso) ? (2 * nso) + 4 : 0)) +#define VIRGL_OBJ_SHADER_HANDLE 1 +#define VIRGL_OBJ_SHADER_TYPE 2 +#define VIRGL_OBJ_SHADER_OFFSET 3 +#define VIRGL_OBJ_SHADER_OFFSET_VAL(x) (((x) & 0x7fffffff) << 0) +/* start contains full length in VAL - also implies continuations */ +/* continuation contains offset in VAL */ +#define VIRGL_OBJ_SHADER_OFFSET_CONT (0x1u << 31) +#define VIRGL_OBJ_SHADER_NUM_TOKENS 4 +#define VIRGL_OBJ_SHADER_SO_NUM_OUTPUTS 5 +#define VIRGL_OBJ_SHADER_SO_STRIDE(x) (6 + (x)) +#define VIRGL_OBJ_SHADER_SO_OUTPUT0(x) (10 + (x * 2)) +#define VIRGL_OBJ_SHADER_SO_OUTPUT_REGISTER_INDEX(x) (((x) & 0xff) << 0) +#define VIRGL_OBJ_SHADER_SO_OUTPUT_START_COMPONENT(x) (((x) & 0x3) << 8) +#define VIRGL_OBJ_SHADER_SO_OUTPUT_NUM_COMPONENTS(x) (((x) & 0x7) << 10) +#define VIRGL_OBJ_SHADER_SO_OUTPUT_BUFFER(x) (((x) & 0x7) << 13) +#define VIRGL_OBJ_SHADER_SO_OUTPUT_DST_OFFSET(x) (((x) & 0xffff) << 16) +#define VIRGL_OBJ_SHADER_SO_OUTPUT0_SO(x) (11 + (x * 2)) +#define VIRGL_OBJ_SHADER_SO_OUTPUT_STREAM(x) (((x) & 0x03) << 0) + +/* viewport state */ +#define VIRGL_SET_VIEWPORT_STATE_SIZE(num_viewports) ((6 * num_viewports) + 1) +#define VIRGL_SET_VIEWPORT_START_SLOT 1 +#define VIRGL_SET_VIEWPORT_STATE_SCALE_0(x) (2 + (x * 6)) +#define VIRGL_SET_VIEWPORT_STATE_SCALE_1(x) (3 + (x * 6)) +#define VIRGL_SET_VIEWPORT_STATE_SCALE_2(x) (4 + (x * 6)) +#define VIRGL_SET_VIEWPORT_STATE_TRANSLATE_0(x) (5 + (x * 6)) +#define VIRGL_SET_VIEWPORT_STATE_TRANSLATE_1(x) (6 + (x * 6)) +#define VIRGL_SET_VIEWPORT_STATE_TRANSLATE_2(x) (7 + (x * 6)) + +/* framebuffer state */ +#define VIRGL_SET_FRAMEBUFFER_STATE_SIZE(nr_cbufs) (nr_cbufs + 2) +#define VIRGL_SET_FRAMEBUFFER_STATE_NR_CBUFS 1 +#define VIRGL_SET_FRAMEBUFFER_STATE_NR_ZSURF_HANDLE 2 +#define VIRGL_SET_FRAMEBUFFER_STATE_CBUF_HANDLE(x) ((x) + 3) + +/* vertex elements object */ +#define VIRGL_OBJ_VERTEX_ELEMENTS_SIZE(num_elements) (((num_elements) * 4) + 1) +#define VIRGL_OBJ_VERTEX_ELEMENTS_HANDLE 1 +#define VIRGL_OBJ_VERTEX_ELEMENTS_V0_SRC_OFFSET(x) (((x) * 4) + 2) /* repeated per VE */ +#define VIRGL_OBJ_VERTEX_ELEMENTS_V0_INSTANCE_DIVISOR(x) (((x) * 4) + 3) +#define VIRGL_OBJ_VERTEX_ELEMENTS_V0_VERTEX_BUFFER_INDEX(x) (((x) * 4) + 4) +#define VIRGL_OBJ_VERTEX_ELEMENTS_V0_SRC_FORMAT(x) (((x) * 4) + 5) + +/* vertex buffers */ +#define VIRGL_SET_VERTEX_BUFFERS_SIZE(num_buffers) ((num_buffers) * 3) +#define VIRGL_SET_VERTEX_BUFFER_STRIDE(x) (((x) * 3) + 1) +#define VIRGL_SET_VERTEX_BUFFER_OFFSET(x) (((x) * 3) + 2) +#define VIRGL_SET_VERTEX_BUFFER_HANDLE(x) (((x) * 3) + 3) + +/* index buffer */ +#define VIRGL_SET_INDEX_BUFFER_SIZE(ib) (((ib) ? 2 : 0) + 1) +#define VIRGL_SET_INDEX_BUFFER_HANDLE 1 +#define VIRGL_SET_INDEX_BUFFER_INDEX_SIZE 2 /* only if sending an IB handle */ +#define VIRGL_SET_INDEX_BUFFER_OFFSET 3 /* only if sending an IB handle */ + +/* constant buffer */ +#define VIRGL_SET_CONSTANT_BUFFER_SHADER_TYPE 1 +#define VIRGL_SET_CONSTANT_BUFFER_INDEX 2 +#define VIRGL_SET_CONSTANT_BUFFER_DATA_START 3 + +#define VIRGL_SET_UNIFORM_BUFFER_SIZE 5 +#define VIRGL_SET_UNIFORM_BUFFER_SHADER_TYPE 1 +#define VIRGL_SET_UNIFORM_BUFFER_INDEX 2 +#define VIRGL_SET_UNIFORM_BUFFER_OFFSET 3 +#define VIRGL_SET_UNIFORM_BUFFER_LENGTH 4 +#define VIRGL_SET_UNIFORM_BUFFER_RES_HANDLE 5 + +/* draw VBO */ +#define VIRGL_DRAW_VBO_SIZE 12 +#define VIRGL_DRAW_VBO_SIZE_TESS 14 +#define VIRGL_DRAW_VBO_SIZE_INDIRECT 20 +#define VIRGL_DRAW_VBO_START 1 +#define VIRGL_DRAW_VBO_COUNT 2 +#define VIRGL_DRAW_VBO_MODE 3 +#define VIRGL_DRAW_VBO_INDEXED 4 +#define VIRGL_DRAW_VBO_INSTANCE_COUNT 5 +#define VIRGL_DRAW_VBO_INDEX_BIAS 6 +#define VIRGL_DRAW_VBO_START_INSTANCE 7 +#define VIRGL_DRAW_VBO_PRIMITIVE_RESTART 8 +#define VIRGL_DRAW_VBO_RESTART_INDEX 9 +#define VIRGL_DRAW_VBO_MIN_INDEX 10 +#define VIRGL_DRAW_VBO_MAX_INDEX 11 +#define VIRGL_DRAW_VBO_COUNT_FROM_SO 12 +/* tess packet */ +#define VIRGL_DRAW_VBO_VERTICES_PER_PATCH 13 +#define VIRGL_DRAW_VBO_DRAWID 14 +/* indirect packet */ +#define VIRGL_DRAW_VBO_INDIRECT_HANDLE 15 +#define VIRGL_DRAW_VBO_INDIRECT_OFFSET 16 +#define VIRGL_DRAW_VBO_INDIRECT_STRIDE 17 +#define VIRGL_DRAW_VBO_INDIRECT_DRAW_COUNT 18 +#define VIRGL_DRAW_VBO_INDIRECT_DRAW_COUNT_OFFSET 19 +#define VIRGL_DRAW_VBO_INDIRECT_DRAW_COUNT_HANDLE 20 + +/* create surface */ +#define VIRGL_OBJ_SURFACE_SIZE 5 +#define VIRGL_OBJ_SURFACE_HANDLE 1 +#define VIRGL_OBJ_SURFACE_RES_HANDLE 2 +#define VIRGL_OBJ_SURFACE_FORMAT 3 +#define VIRGL_OBJ_SURFACE_BUFFER_FIRST_ELEMENT 4 +#define VIRGL_OBJ_SURFACE_BUFFER_LAST_ELEMENT 5 +#define VIRGL_OBJ_SURFACE_TEXTURE_LEVEL 4 +#define VIRGL_OBJ_SURFACE_TEXTURE_LAYERS 5 + +/* create streamout target */ +#define VIRGL_OBJ_STREAMOUT_SIZE 4 +#define VIRGL_OBJ_STREAMOUT_HANDLE 1 +#define VIRGL_OBJ_STREAMOUT_RES_HANDLE 2 +#define VIRGL_OBJ_STREAMOUT_BUFFER_OFFSET 3 +#define VIRGL_OBJ_STREAMOUT_BUFFER_SIZE 4 + +/* sampler state */ +#define VIRGL_OBJ_SAMPLER_STATE_SIZE 9 +#define VIRGL_OBJ_SAMPLER_STATE_HANDLE 1 +#define VIRGL_OBJ_SAMPLER_STATE_S0 2 +#define VIRGL_OBJ_SAMPLE_STATE_S0_WRAP_S(x) (((x) & 0x7) << 0) +#define VIRGL_OBJ_SAMPLE_STATE_S0_WRAP_T(x) (((x) & 0x7) << 3) +#define VIRGL_OBJ_SAMPLE_STATE_S0_WRAP_R(x) (((x) & 0x7) << 6) +#define VIRGL_OBJ_SAMPLE_STATE_S0_MIN_IMG_FILTER(x) (((x) & 0x3) << 9) +#define VIRGL_OBJ_SAMPLE_STATE_S0_MIN_MIP_FILTER(x) (((x) & 0x3) << 11) +#define VIRGL_OBJ_SAMPLE_STATE_S0_MAG_IMG_FILTER(x) (((x) & 0x3) << 13) +#define VIRGL_OBJ_SAMPLE_STATE_S0_COMPARE_MODE(x) (((x) & 0x1) << 15) +#define VIRGL_OBJ_SAMPLE_STATE_S0_COMPARE_FUNC(x) (((x) & 0x7) << 16) +#define VIRGL_OBJ_SAMPLE_STATE_S0_SEAMLESS_CUBE_MAP(x) (((x) & 0x1) << 19) + +#define VIRGL_OBJ_SAMPLER_STATE_LOD_BIAS 3 +#define VIRGL_OBJ_SAMPLER_STATE_MIN_LOD 4 +#define VIRGL_OBJ_SAMPLER_STATE_MAX_LOD 5 +#define VIRGL_OBJ_SAMPLER_STATE_BORDER_COLOR(x) ((x) + 6) /* 6 - 9 */ + + +/* sampler view */ +#define VIRGL_OBJ_SAMPLER_VIEW_SIZE 6 +#define VIRGL_OBJ_SAMPLER_VIEW_HANDLE 1 +#define VIRGL_OBJ_SAMPLER_VIEW_RES_HANDLE 2 +#define VIRGL_OBJ_SAMPLER_VIEW_FORMAT 3 +#define VIRGL_OBJ_SAMPLER_VIEW_BUFFER_FIRST_ELEMENT 4 +#define VIRGL_OBJ_SAMPLER_VIEW_BUFFER_LAST_ELEMENT 5 +#define VIRGL_OBJ_SAMPLER_VIEW_TEXTURE_LAYER 4 +#define VIRGL_OBJ_SAMPLER_VIEW_TEXTURE_LEVEL 5 +#define VIRGL_OBJ_SAMPLER_VIEW_SWIZZLE 6 +#define VIRGL_OBJ_SAMPLER_VIEW_SWIZZLE_R(x) (((x) & 0x7) << 0) +#define VIRGL_OBJ_SAMPLER_VIEW_SWIZZLE_G(x) (((x) & 0x7) << 3) +#define VIRGL_OBJ_SAMPLER_VIEW_SWIZZLE_B(x) (((x) & 0x7) << 6) +#define VIRGL_OBJ_SAMPLER_VIEW_SWIZZLE_A(x) (((x) & 0x7) << 9) + +/* set sampler views */ +#define VIRGL_SET_SAMPLER_VIEWS_SIZE(num_views) ((num_views) + 2) +#define VIRGL_SET_SAMPLER_VIEWS_SHADER_TYPE 1 +#define VIRGL_SET_SAMPLER_VIEWS_START_SLOT 2 +#define VIRGL_SET_SAMPLER_VIEWS_V0_HANDLE 3 + +/* bind sampler states */ +#define VIRGL_BIND_SAMPLER_STATES(num_states) ((num_states) + 2) +#define VIRGL_BIND_SAMPLER_STATES_SHADER_TYPE 1 +#define VIRGL_BIND_SAMPLER_STATES_START_SLOT 2 +#define VIRGL_BIND_SAMPLER_STATES_S0_HANDLE 3 + +/* set stencil reference */ +#define VIRGL_SET_STENCIL_REF_SIZE 1 +#define VIRGL_SET_STENCIL_REF 1 +#define VIRGL_STENCIL_REF_VAL(f, s) ((f & 0xff) | (((s & 0xff) << 8))) + +/* set blend color */ +#define VIRGL_SET_BLEND_COLOR_SIZE 4 +#define VIRGL_SET_BLEND_COLOR(x) ((x) + 1) + +/* set scissor state */ +#define VIRGL_SET_SCISSOR_STATE_SIZE(x) (1 + 2 * x) +#define VIRGL_SET_SCISSOR_START_SLOT 1 +#define VIRGL_SET_SCISSOR_MINX_MINY(x) (2 + (x * 2)) +#define VIRGL_SET_SCISSOR_MAXX_MAXY(x) (3 + (x * 2)) + +/* resource copy region */ +#define VIRGL_CMD_RESOURCE_COPY_REGION_SIZE 13 +#define VIRGL_CMD_RCR_DST_RES_HANDLE 1 +#define VIRGL_CMD_RCR_DST_LEVEL 2 +#define VIRGL_CMD_RCR_DST_X 3 +#define VIRGL_CMD_RCR_DST_Y 4 +#define VIRGL_CMD_RCR_DST_Z 5 +#define VIRGL_CMD_RCR_SRC_RES_HANDLE 6 +#define VIRGL_CMD_RCR_SRC_LEVEL 7 +#define VIRGL_CMD_RCR_SRC_X 8 +#define VIRGL_CMD_RCR_SRC_Y 9 +#define VIRGL_CMD_RCR_SRC_Z 10 +#define VIRGL_CMD_RCR_SRC_W 11 +#define VIRGL_CMD_RCR_SRC_H 12 +#define VIRGL_CMD_RCR_SRC_D 13 + +/* blit */ +#define VIRGL_CMD_BLIT_SIZE 21 +#define VIRGL_CMD_BLIT_S0 1 +#define VIRGL_CMD_BLIT_S0_MASK(x) (((x) & 0xff) << 0) +#define VIRGL_CMD_BLIT_S0_FILTER(x) (((x) & 0x3) << 8) +#define VIRGL_CMD_BLIT_S0_SCISSOR_ENABLE(x) (((x) & 0x1) << 10) +#define VIRGL_CMD_BLIT_S0_RENDER_CONDITION_ENABLE(x) (((x) & 0x1) << 11) +#define VIRGL_CMD_BLIT_S0_ALPHA_BLEND(x) (((x) & 0x1) << 12) +#define VIRGL_CMD_BLIT_SCISSOR_MINX_MINY 2 +#define VIRGL_CMD_BLIT_SCISSOR_MAXX_MAXY 3 +#define VIRGL_CMD_BLIT_DST_RES_HANDLE 4 +#define VIRGL_CMD_BLIT_DST_LEVEL 5 +#define VIRGL_CMD_BLIT_DST_FORMAT 6 +#define VIRGL_CMD_BLIT_DST_X 7 +#define VIRGL_CMD_BLIT_DST_Y 8 +#define VIRGL_CMD_BLIT_DST_Z 9 +#define VIRGL_CMD_BLIT_DST_W 10 +#define VIRGL_CMD_BLIT_DST_H 11 +#define VIRGL_CMD_BLIT_DST_D 12 +#define VIRGL_CMD_BLIT_SRC_RES_HANDLE 13 +#define VIRGL_CMD_BLIT_SRC_LEVEL 14 +#define VIRGL_CMD_BLIT_SRC_FORMAT 15 +#define VIRGL_CMD_BLIT_SRC_X 16 +#define VIRGL_CMD_BLIT_SRC_Y 17 +#define VIRGL_CMD_BLIT_SRC_Z 18 +#define VIRGL_CMD_BLIT_SRC_W 19 +#define VIRGL_CMD_BLIT_SRC_H 20 +#define VIRGL_CMD_BLIT_SRC_D 21 + +/* query object */ +#define VIRGL_OBJ_QUERY_SIZE 4 +#define VIRGL_OBJ_QUERY_HANDLE 1 +#define VIRGL_OBJ_QUERY_TYPE_INDEX 2 +#define VIRGL_OBJ_QUERY_TYPE(x) (x & 0xffff) +#define VIRGL_OBJ_QUERY_INDEX(x) ((x & 0xffff) << 16) +#define VIRGL_OBJ_QUERY_OFFSET 3 +#define VIRGL_OBJ_QUERY_RES_HANDLE 4 + +#define VIRGL_QUERY_BEGIN_HANDLE 1 + +#define VIRGL_QUERY_END_HANDLE 1 + +#define VIRGL_QUERY_RESULT_SIZE 2 +#define VIRGL_QUERY_RESULT_HANDLE 1 +#define VIRGL_QUERY_RESULT_WAIT 2 + +/* render condition */ +#define VIRGL_RENDER_CONDITION_SIZE 3 +#define VIRGL_RENDER_CONDITION_HANDLE 1 +#define VIRGL_RENDER_CONDITION_CONDITION 2 +#define VIRGL_RENDER_CONDITION_MODE 3 + +/* resource inline write */ +#define VIRGL_RESOURCE_IW_RES_HANDLE 1 +#define VIRGL_RESOURCE_IW_LEVEL 2 +#define VIRGL_RESOURCE_IW_USAGE 3 +#define VIRGL_RESOURCE_IW_STRIDE 4 +#define VIRGL_RESOURCE_IW_LAYER_STRIDE 5 +#define VIRGL_RESOURCE_IW_X 6 +#define VIRGL_RESOURCE_IW_Y 7 +#define VIRGL_RESOURCE_IW_Z 8 +#define VIRGL_RESOURCE_IW_W 9 +#define VIRGL_RESOURCE_IW_H 10 +#define VIRGL_RESOURCE_IW_D 11 +#define VIRGL_RESOURCE_IW_DATA_START 12 + +/* set streamout targets */ +#define VIRGL_SET_STREAMOUT_TARGETS_APPEND_BITMASK 1 +#define VIRGL_SET_STREAMOUT_TARGETS_H0 2 + +/* set sample mask */ +#define VIRGL_SET_SAMPLE_MASK_SIZE 1 +#define VIRGL_SET_SAMPLE_MASK_MASK 1 + +/* set clip state */ +#define VIRGL_SET_CLIP_STATE_SIZE 32 +#define VIRGL_SET_CLIP_STATE_C0 1 + +/* polygon stipple */ +#define VIRGL_POLYGON_STIPPLE_SIZE 32 +#define VIRGL_POLYGON_STIPPLE_P0 1 + +#define VIRGL_BIND_SHADER_SIZE 2 +#define VIRGL_BIND_SHADER_HANDLE 1 +#define VIRGL_BIND_SHADER_TYPE 2 + +/* tess state */ +#define VIRGL_TESS_STATE_SIZE 6 + +/* set min samples */ +#define VIRGL_SET_MIN_SAMPLES_SIZE 1 +#define VIRGL_SET_MIN_SAMPLES_MASK 1 + +/* set shader buffers */ +#define VIRGL_SET_SHADER_BUFFER_ELEMENT_SIZE 3 +#define VIRGL_SET_SHADER_BUFFER_SIZE(x) (VIRGL_SET_SHADER_BUFFER_ELEMENT_SIZE * (x)) + 2 +#define VIRGL_SET_SHADER_BUFFER_SHADER_TYPE 1 +#define VIRGL_SET_SHADER_BUFFER_START_SLOT 2 +#define VIRGL_SET_SHADER_BUFFER_OFFSET(x) ((x) * VIRGL_SET_SHADER_BUFFER_ELEMENT_SIZE + 3) +#define VIRGL_SET_SHADER_BUFFER_LENGTH(x) ((x) * VIRGL_SET_SHADER_BUFFER_ELEMENT_SIZE + 4) +#define VIRGL_SET_SHADER_BUFFER_RES_HANDLE(x) ((x) * VIRGL_SET_SHADER_BUFFER_ELEMENT_SIZE + 5) + +/* set shader images */ +#define VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE 5 +#define VIRGL_SET_SHADER_IMAGE_SIZE(x) (VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE * (x)) + 2 +#define VIRGL_SET_SHADER_IMAGE_SHADER_TYPE 1 +#define VIRGL_SET_SHADER_IMAGE_START_SLOT 2 +#define VIRGL_SET_SHADER_IMAGE_FORMAT(x) ((x) * VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE + 3) +#define VIRGL_SET_SHADER_IMAGE_ACCESS(x) ((x) * VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE + 4) +#define VIRGL_SET_SHADER_IMAGE_LAYER_OFFSET(x) ((x) * VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE + 5) +#define VIRGL_SET_SHADER_IMAGE_LEVEL_SIZE(x) ((x) * VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE + 6) +#define VIRGL_SET_SHADER_IMAGE_RES_HANDLE(x) ((x) * VIRGL_SET_SHADER_IMAGE_ELEMENT_SIZE + 7) + +/* memory barrier */ +#define VIRGL_MEMORY_BARRIER_SIZE 1 +#define VIRGL_MEMORY_BARRIER_FLAGS 1 + +/* launch grid */ +#define VIRGL_LAUNCH_GRID_SIZE 8 +#define VIRGL_LAUNCH_BLOCK_X 1 +#define VIRGL_LAUNCH_BLOCK_Y 2 +#define VIRGL_LAUNCH_BLOCK_Z 3 +#define VIRGL_LAUNCH_GRID_X 4 +#define VIRGL_LAUNCH_GRID_Y 5 +#define VIRGL_LAUNCH_GRID_Z 6 +#define VIRGL_LAUNCH_INDIRECT_HANDLE 7 +#define VIRGL_LAUNCH_INDIRECT_OFFSET 8 + +/* framebuffer state no attachment */ +#define VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_SIZE 2 +#define VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_WIDTH_HEIGHT 1 +#define VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_WIDTH(x) (x & 0xffff) +#define VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_HEIGHT(x) ((x >> 16) & 0xffff) +#define VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_LAYERS_SAMPLES 2 +#define VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_LAYERS(x) (x & 0xffff) +#define VIRGL_SET_FRAMEBUFFER_STATE_NO_ATTACH_SAMPLES(x) ((x >> 16) & 0xff) + +/* texture barrier */ +#define VIRGL_TEXTURE_BARRIER_SIZE 1 +#define VIRGL_TEXTURE_BARRIER_FLAGS 1 + +/* hw atomics */ +#define VIRGL_SET_ATOMIC_BUFFER_ELEMENT_SIZE 3 +#define VIRGL_SET_ATOMIC_BUFFER_SIZE(x) (VIRGL_SET_ATOMIC_BUFFER_ELEMENT_SIZE * (x)) + 1 +#define VIRGL_SET_ATOMIC_BUFFER_START_SLOT 1 +#define VIRGL_SET_ATOMIC_BUFFER_OFFSET(x) ((x) * VIRGL_SET_ATOMIC_BUFFER_ELEMENT_SIZE + 2) +#define VIRGL_SET_ATOMIC_BUFFER_LENGTH(x) ((x) * VIRGL_SET_ATOMIC_BUFFER_ELEMENT_SIZE + 3) +#define VIRGL_SET_ATOMIC_BUFFER_RES_HANDLE(x) ((x) * VIRGL_SET_ATOMIC_BUFFER_ELEMENT_SIZE + 4) + +/* qbo */ +#define VIRGL_QUERY_RESULT_QBO_SIZE 6 +#define VIRGL_QUERY_RESULT_QBO_HANDLE 1 +#define VIRGL_QUERY_RESULT_QBO_QBO_HANDLE 2 +#define VIRGL_QUERY_RESULT_QBO_WAIT 3 +#define VIRGL_QUERY_RESULT_QBO_RESULT_TYPE 4 +#define VIRGL_QUERY_RESULT_QBO_OFFSET 5 +#define VIRGL_QUERY_RESULT_QBO_INDEX 6 + +#define VIRGL_TRANSFER_TO_HOST 1 +#define VIRGL_TRANSFER_FROM_HOST 2 + +/* Transfer */ +#define VIRGL_TRANSFER3D_SIZE 13 +/* The first 11 dwords are the same as VIRGL_RESOURCE_IW_* */ +#define VIRGL_TRANSFER3D_DATA_OFFSET 12 +#define VIRGL_TRANSFER3D_DIRECTION 13 + +/* Copy transfer */ +#define VIRGL_COPY_TRANSFER3D_SIZE 14 +/* The first 11 dwords are the same as VIRGL_RESOURCE_IW_* */ +#define VIRGL_COPY_TRANSFER3D_SRC_RES_HANDLE 12 +#define VIRGL_COPY_TRANSFER3D_SRC_RES_OFFSET 13 +#define VIRGL_COPY_TRANSFER3D_SYNCHRONIZED 14 + +/* set tweak flags */ +#define VIRGL_SET_TWEAKS_SIZE 2 +#define VIRGL_SET_TWEAKS_ID 1 +#define VIRGL_SET_TWEAKS_VALUE 2 + +/* virgl create */ +#define VIRGL_PIPE_RES_CREATE_SIZE 11 +#define VIRGL_PIPE_RES_CREATE_TARGET 1 +#define VIRGL_PIPE_RES_CREATE_FORMAT 2 +#define VIRGL_PIPE_RES_CREATE_BIND 3 +#define VIRGL_PIPE_RES_CREATE_WIDTH 4 +#define VIRGL_PIPE_RES_CREATE_HEIGHT 5 +#define VIRGL_PIPE_RES_CREATE_DEPTH 6 +#define VIRGL_PIPE_RES_CREATE_ARRAY_SIZE 7 +#define VIRGL_PIPE_RES_CREATE_LAST_LEVEL 8 +#define VIRGL_PIPE_RES_CREATE_NR_SAMPLES 9 +#define VIRGL_PIPE_RES_CREATE_FLAGS 10 +#define VIRGL_PIPE_RES_CREATE_BLOB_ID 11 + +enum vrend_tweak_type { + virgl_tweak_gles_brga_emulate, + virgl_tweak_gles_brga_apply_dest_swizzle, + virgl_tweak_gles_tf3_samples_passes_multiplier, + virgl_tweak_undefined +}; + +/* Clear texture */ +#define VIRGL_CLEAR_TEXTURE_SIZE 12 +#define VIRGL_TEXTURE_HANDLE 1 +#define VIRGL_TEXTURE_LEVEL 2 +#define VIRGL_TEXTURE_SRC_X 3 +#define VIRGL_TEXTURE_SRC_Y 4 +#define VIRGL_TEXTURE_SRC_Z 5 +#define VIRGL_TEXTURE_SRC_W 6 +#define VIRGL_TEXTURE_SRC_H 7 +#define VIRGL_TEXTURE_SRC_D 8 +#define VIRGL_TEXTURE_ARRAY_A 9 +#define VIRGL_TEXTURE_ARRAY_B 10 +#define VIRGL_TEXTURE_ARRAY_C 11 +#define VIRGL_TEXTURE_ARRAY_D 12 + +#endif diff --git a/virtgpu_drm.h b/external/virtgpu_drm.h index a92d764..f324520 100644 --- a/virtgpu_drm.h +++ b/external/virtgpu_drm.h @@ -46,6 +46,7 @@ extern "C" { #define DRM_VIRTGPU_TRANSFER_TO_HOST 0x07 #define DRM_VIRTGPU_WAIT 0x08 #define DRM_VIRTGPU_GET_CAPS 0x09 +#define DRM_VIRTGPU_RESOURCE_CREATE_BLOB 0x0a #define VIRTGPU_EXECBUF_FENCE_FD_IN 0x01 #define VIRTGPU_EXECBUF_FENCE_FD_OUT 0x02 @@ -71,6 +72,9 @@ struct drm_virtgpu_execbuffer { #define VIRTGPU_PARAM_3D_FEATURES 1 /* do we have 3D features in the hw */ #define VIRTGPU_PARAM_CAPSET_QUERY_FIX 2 /* do we have the capset fix */ +#define VIRTGPU_PARAM_RESOURCE_BLOB 3 /* DRM_VIRTGPU_RESOURCE_CREATE_BLOB */ +#define VIRTGPU_PARAM_HOST_VISIBLE 4 /* Host blob resources are mappable */ +#define VIRTGPU_PARAM_CROSS_DEVICE 5 /* Cross virtio-device resource sharing */ struct drm_virtgpu_getparam { __u64 param; @@ -101,9 +105,9 @@ struct drm_virtgpu_resource_info { __u32 res_handle; __u32 size; union { - __u32 stride; + __u32 blob_mem; __u32 strides[4]; /* strides[0] is accessible with stride. */ - }; + }; __u32 num_planes; __u32 offsets[4]; __u64 format_modifier; @@ -123,6 +127,8 @@ struct drm_virtgpu_3d_transfer_to_host { struct drm_virtgpu_3d_box box; __u32 level; __u32 offset; + __u32 stride; + __u32 layer_stride; }; struct drm_virtgpu_3d_transfer_from_host { @@ -130,6 +136,8 @@ struct drm_virtgpu_3d_transfer_from_host { struct drm_virtgpu_3d_box box; __u32 level; __u32 offset; + __u32 stride; + __u32 layer_stride; }; #define VIRTGPU_WAIT_NOWAIT 1 /* like it */ @@ -146,6 +154,31 @@ struct drm_virtgpu_get_caps { __u32 pad; }; +struct drm_virtgpu_resource_create_blob { +#define VIRTGPU_BLOB_MEM_GUEST 0x0001 +#define VIRTGPU_BLOB_MEM_HOST3D 0x0002 +#define VIRTGPU_BLOB_MEM_HOST3D_GUEST 0x0003 + +#define VIRTGPU_BLOB_FLAG_USE_MAPPABLE 0x0001 +#define VIRTGPU_BLOB_FLAG_USE_SHAREABLE 0x0002 +#define VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE 0x0004 + /* zero is invalid blob_mem */ + __u32 blob_mem; + __u32 blob_flags; + __u32 bo_handle; + __u32 res_handle; + __u64 size; + + /* + * for 3D contexts with VIRTGPU_BLOB_MEM_HOST3D_GUEST and + * VIRTGPU_BLOB_MEM_HOST3D otherwise, must be zero. + */ + __u32 pad; + __u32 cmd_size; + __u64 cmd; + __u64 blob_id; +}; + #define DRM_IOCTL_VIRTGPU_MAP \ DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_MAP, struct drm_virtgpu_map) @@ -181,6 +214,10 @@ struct drm_virtgpu_get_caps { DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_GET_CAPS, \ struct drm_virtgpu_get_caps) +#define DRM_IOCTL_VIRTGPU_RESOURCE_CREATE_BLOB \ + DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_CREATE_BLOB, \ + struct drm_virtgpu_resource_create_blob) + #if defined(__cplusplus) } #endif @@ -263,6 +263,12 @@ PUBLIC struct gbm_bo *gbm_bo_import(struct gbm_device *gbm, uint32_t type, void return bo; } +PUBLIC void *gbm_bo_map(struct gbm_bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height, + uint32_t transfer_flags, uint32_t *stride, void **map_data) +{ + return gbm_bo_map2(bo, x, y, width, height, transfer_flags, stride, map_data, 0); +} + PUBLIC void gbm_bo_unmap(struct gbm_bo *bo, void *map_data) { assert(bo); @@ -393,12 +399,6 @@ PUBLIC int gbm_bo_get_plane_fd(struct gbm_bo *bo, size_t plane) return drv_bo_get_plane_fd(bo->bo, plane); } -PUBLIC void *gbm_bo_map(struct gbm_bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height, - uint32_t transfer_flags, uint32_t *stride, void **map_data, size_t plane) -{ - return gbm_bo_map2(bo, x, y, width, height, transfer_flags, stride, map_data, plane); -} - PUBLIC void *gbm_bo_map2(struct gbm_bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint32_t transfer_flags, uint32_t *stride, void **map_data, int plane) { @@ -373,6 +373,11 @@ enum gbm_bo_transfer_flags { GBM_BO_TRANSFER_READ_WRITE = (GBM_BO_TRANSFER_READ | GBM_BO_TRANSFER_WRITE), }; +void * +gbm_bo_map(struct gbm_bo *bo, + uint32_t x, uint32_t y, uint32_t width, uint32_t height, + uint32_t flags, uint32_t *stride, void **map_data); + void gbm_bo_unmap(struct gbm_bo *bo, void *map_data); @@ -471,10 +476,6 @@ int gbm_bo_get_plane_fd(struct gbm_bo *bo, size_t plane); void * -gbm_bo_map(struct gbm_bo *bo, - uint32_t x, uint32_t y, uint32_t width, uint32_t height, - uint32_t flags, uint32_t *stride, void **map_data, size_t plane); -void * gbm_bo_map2(struct gbm_bo *bo, uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint32_t flags, uint32_t *stride, void **map_data, int plane); @@ -451,6 +451,7 @@ int drv_prime_bo_import(struct bo *bo, struct drv_import_fd_data *data) bo->handles[plane].u32 = prime_handle.handle; } + bo->meta.tiling = data->tiling; return 0; } @@ -34,23 +34,53 @@ 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 uint64_t gen_modifier_order[] = { I915_FORMAT_MOD_Y_TILED, I915_FORMAT_MOD_X_TILED, + DRM_FORMAT_MOD_LINEAR }; + +static const uint64_t gen11_modifier_order[] = { I915_FORMAT_MOD_Y_TILED_CCS, + I915_FORMAT_MOD_Y_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; int32_t has_llc; + struct modifier_support_t modifier; }; static uint32_t i915_get_gen(int device_id) { const uint16_t gen3_ids[] = { 0x2582, 0x2592, 0x2772, 0x27A2, 0x27AE, 0x29C2, 0x29B2, 0x29D2, 0xA001, 0xA011 }; + const uint16_t gen11_ids[] = { 0x4E71, 0x4E61, 0x4E51, 0x4E55, 0x4E57 }; + unsigned i; for (i = 0; i < ARRAY_SIZE(gen3_ids); i++) if (gen3_ids[i] == device_id) return 3; + /* Gen 11 */ + for (i = 0; i < ARRAY_SIZE(gen11_ids); i++) + if (gen11_ids[i] == device_id) + return 11; return 4; } +static void i915_get_modifier_order(struct i915_device *i915) +{ + if (i915->gen == 11) { + i915->modifier.order = gen11_modifier_order; + i915->modifier.count = ARRAY_SIZE(gen11_modifier_order); + } else { + i915->modifier.order = gen_modifier_order; + i915->modifier.count = ARRAY_SIZE(gen_modifier_order); + } +} + static uint64_t unset_flags(uint64_t current_flags, uint64_t mask) { uint64_t value = current_flags & ~mask; @@ -221,6 +251,7 @@ static int i915_init(struct driver *drv) } i915->gen = i915_get_gen(device_id); + i915_get_modifier_order(i915); memset(&get_param, 0, sizeof(get_param)); get_param.param = I915_PARAM_HAS_LLC; @@ -270,18 +301,13 @@ static int i915_bo_from_format(struct bo *bo, uint32_t width, uint32_t height, u static int i915_bo_compute_metadata(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, uint64_t use_flags, const uint64_t *modifiers, uint32_t count) { - static const uint64_t modifier_order[] = { - I915_FORMAT_MOD_Y_TILED, - I915_FORMAT_MOD_X_TILED, - DRM_FORMAT_MOD_LINEAR, - }; uint64_t modifier; struct i915_device *i915 = bo->drv->priv; bool huge_bo = (i915->gen <= 11) && (width > 4096); if (modifiers) { modifier = - drv_pick_modifier(modifiers, count, modifier_order, ARRAY_SIZE(modifier_order)); + drv_pick_modifier(modifiers, count, i915->modifier.order, i915->modifier.count); } else { struct combination *combo = drv_get_combination(bo->drv, format, use_flags); if (!combo) @@ -66,31 +66,32 @@ static int mediatek_init(struct driver *drv) metadata.modifier = DRM_FORMAT_MOD_LINEAR; drv_modify_combination(drv, DRM_FORMAT_YVU420, &metadata, BO_USE_HW_VIDEO_DECODER); drv_modify_combination(drv, DRM_FORMAT_YVU420_ANDROID, &metadata, BO_USE_HW_VIDEO_DECODER); +#ifdef MTK_MT8183 + // TODO(hiroh): Switch to use NV12 for video decoder on MT8173 as well. drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata, BO_USE_HW_VIDEO_DECODER); +#endif /* * R8 format is used for Android's HAL_PIXEL_FORMAT_BLOB for input/output from * hardware decoder/encoder. */ drv_modify_combination(drv, DRM_FORMAT_R8, &metadata, - BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER); + BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER | + BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE); -#ifdef MTK_MT8183 /* NV12 format for encoding and display. */ drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata, - BO_USE_SCANOUT | BO_USE_HW_VIDEO_ENCODER); + BO_USE_SCANOUT | BO_USE_HW_VIDEO_ENCODER | BO_USE_CAMERA_READ | + BO_USE_CAMERA_WRITE); +#ifdef MTK_MT8183 /* Only for MT8183 Camera subsystem */ - drv_modify_combination(drv, DRM_FORMAT_NV12, &metadata, - BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE); drv_modify_combination(drv, DRM_FORMAT_NV21, &metadata, BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE); drv_modify_combination(drv, DRM_FORMAT_YUYV, &metadata, BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE); drv_modify_combination(drv, DRM_FORMAT_YVU420, &metadata, BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE); - drv_modify_combination(drv, DRM_FORMAT_R8, &metadata, - BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE); /* Private formats for private reprocessing in camera */ drv_add_combination(drv, DRM_FORMAT_MTISP_SXYZW10, &metadata, BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_SW_MASK); @@ -270,21 +271,23 @@ static uint32_t mediatek_resolve_format(struct driver *drv, uint32_t format, uin * reprocessing and hence given the private format for MTK. */ if (use_flags & BO_USE_CAMERA_READ) return DRM_FORMAT_MTISP_SXYZW10; - /* For non-reprocessing uses, only MT8183 Camera subsystem - * requires NV12. */ - else if (use_flags & BO_USE_CAMERA_WRITE) - return DRM_FORMAT_NV12; #endif + if (use_flags & BO_USE_CAMERA_WRITE) + return DRM_FORMAT_NV12; + /*HACK: See b/28671744 */ return DRM_FORMAT_XBGR8888; case DRM_FORMAT_FLEX_YCbCr_420_888: #ifdef MTK_MT8183 - /* MT8183 camera and decoder subsystems require NV12. */ - if (use_flags & (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | - BO_USE_HW_VIDEO_DECODER | BO_USE_HW_VIDEO_ENCODER)) { + // TODO(hiroh): Switch to use NV12 for video decoder on MT8173 as well. + if (use_flags & (BO_USE_HW_VIDEO_DECODER)) { return DRM_FORMAT_NV12; } #endif + if (use_flags & + (BO_USE_CAMERA_READ | BO_USE_CAMERA_WRITE | BO_USE_HW_VIDEO_ENCODER)) { + return DRM_FORMAT_NV12; + } return DRM_FORMAT_YVU420; default: return format; @@ -12,13 +12,24 @@ static const uint32_t scanout_render_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_XRGB8888, DRM_FORMAT_ABGR8888, DRM_FORMAT_XBGR8888, - DRM_FORMAT_BGR888, DRM_FORMAT_BGR565}; + DRM_FORMAT_BGR888, DRM_FORMAT_BGR565 }; + +static const uint32_t texture_only_formats[] = { DRM_FORMAT_NV12, DRM_FORMAT_NV21, + DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID }; static int meson_init(struct driver *drv) { drv_add_combinations(drv, scanout_render_formats, ARRAY_SIZE(scanout_render_formats), &LINEAR_METADATA, BO_USE_RENDER_MASK | BO_USE_SCANOUT); + drv_add_combinations(drv, texture_only_formats, ARRAY_SIZE(texture_only_formats), + &LINEAR_METADATA, BO_USE_TEXTURE_MASK); + + 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); + drv_modify_combination(drv, DRM_FORMAT_NV21, &LINEAR_METADATA, BO_USE_HW_VIDEO_ENCODER); + return drv_modify_linear_combinations(drv); } @@ -7,6 +7,7 @@ #ifdef DRV_MSM #include <assert.h> +#include <dlfcn.h> #include <drm_fourcc.h> #include <errno.h> #include <inttypes.h> @@ -82,11 +83,14 @@ static void msm_calculate_layout(struct bo *bo) y_stride = ALIGN(width, VENUS_STRIDE_ALIGN); uv_stride = ALIGN(width, VENUS_STRIDE_ALIGN); y_scanline = ALIGN(height, VENUS_SCANLINE_ALIGN * 2); - uv_scanline = ALIGN(DIV_ROUND_UP(height, 2), VENUS_SCANLINE_ALIGN); + uv_scanline = ALIGN(DIV_ROUND_UP(height, 2), + VENUS_SCANLINE_ALIGN * (bo->meta.tiling ? 2 : 1)); y_plane = y_stride * y_scanline; uv_plane = uv_stride * uv_scanline; if (bo->meta.tiling == MSM_UBWC_TILING) { + y_plane = ALIGN(y_plane, PLANE_SIZE_ALIGN); + uv_plane = ALIGN(uv_plane, PLANE_SIZE_ALIGN); y_plane += get_ubwc_meta_size(width, height, 32, 8); uv_plane += get_ubwc_meta_size(width >> 1, height >> 1, 16, 8); extra_padding = NV12_UBWC_PADDING(y_stride); @@ -157,12 +161,35 @@ static void msm_add_ubwc_combinations(struct driver *drv, const uint32_t *format } } +/** + * Check for buggy apps that are known to not support modifiers, to avoid surprising them + * with a UBWC buffer. + */ +static bool should_avoid_ubwc(void) +{ +#ifndef __ANDROID__ + /* waffle is buggy and, requests a renderable buffer (which on qcom platforms, we + * want to use UBWC), and then passes it to the kernel discarding the modifier. + * So mesa ends up correctly rendering to as tiled+compressed, but kernel tries + * to display as linear. Other platforms do not see this issue, simply because + * they only use compressed (ex, AFBC) with the BO_USE_SCANOUT flag. + * + * See b/163137550 + */ + if (dlsym(RTLD_DEFAULT, "waffle_display_connect")) { + drv_log("WARNING: waffle detected, disabling UBWC\n"); + return true; + } +#endif + return false; +} + static int msm_init(struct driver *drv) { struct format_metadata metadata; uint64_t render_use_flags = BO_USE_RENDER_MASK | BO_USE_SCANOUT; uint64_t texture_use_flags = BO_USE_TEXTURE_MASK | BO_USE_HW_VIDEO_DECODER; - uint64_t sw_flags = (BO_USE_RENDERSCRIPT | BO_USE_SW_WRITE_OFTEN | BO_USE_SW_READ_OFTEN | + uint64_t sw_flags = (BO_USE_RENDERSCRIPT | BO_USE_SW_MASK | BO_USE_LINEAR | BO_USE_PROTECTED); drv_add_combinations(drv, render_target_formats, ARRAY_SIZE(render_target_formats), @@ -181,7 +208,7 @@ static int msm_init(struct driver *drv) * 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. */ - drv_modify_combination(drv, DRM_FORMAT_R8, &metadata, + 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); @@ -190,6 +217,9 @@ static int msm_init(struct driver *drv) drv_modify_linear_combinations(drv); + if (should_avoid_ubwc()) + return 0; + metadata.tiling = MSM_UBWC_TILING; metadata.priority = 2; metadata.modifier = DRM_FORMAT_MOD_QCOM_COMPRESSED; diff --git a/presubmit.sh b/presubmit.sh index 5e8a32a..128862e 100755 --- a/presubmit.sh +++ b/presubmit.sh @@ -6,4 +6,5 @@ find \ '(' -name '*.[ch]' -or -name '*.cc' ')' \ -not -name 'virtgpu_drm.h' \ -not -name 'gbm.h' -not -name 'virgl_hw.h' \ + -not -name 'virgl_protocol.h' \ -exec clang-format -style=file -i {} + diff --git a/synaptics.c b/synaptics.c index 28cb518..62f3a6b 100644 --- a/synaptics.c +++ b/synaptics.c @@ -10,10 +10,10 @@ #include "util.h" static const uint32_t render_target_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_ABGR8888, - DRM_FORMAT_XRGB8888 }; + DRM_FORMAT_XRGB8888 }; static const uint32_t texture_source_formats[] = { DRM_FORMAT_R8, DRM_FORMAT_NV12, - DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID }; + DRM_FORMAT_YVU420, DRM_FORMAT_YVU420_ANDROID }; static int synaptics_init(struct driver *drv) { @@ -59,7 +59,7 @@ static int vc4_bo_create_for_modifier(struct bo *bo, uint32_t width, uint32_t he ret = drmIoctl(bo->drv->fd, DRM_IOCTL_VC4_CREATE_BO, &bo_create); if (ret) { - drv_log("DRM_IOCTL_VC4_GEM_CREATE failed (size=%zu)\n", bo->meta.total_size); + drv_log("DRM_IOCTL_VC4_CREATE_BO failed (size=%zu)\n", bo->meta.total_size); return -errno; } diff --git a/virtio_gpu.c b/virtio_gpu.c index f7cf015..a5fe732 100644 --- a/virtio_gpu.c +++ b/virtio_gpu.c @@ -13,10 +13,11 @@ #include <xf86drm.h> #include "drv_priv.h" +#include "external/virgl_hw.h" +#include "external/virgl_protocol.h" +#include "external/virtgpu_drm.h" #include "helpers.h" #include "util.h" -#include "virgl_hw.h" -#include "virtgpu_drm.h" #ifndef PAGE_SIZE #define PAGE_SIZE 0x1000 @@ -35,6 +36,9 @@ struct feature { enum feature_id { feat_3d, feat_capset_fix, + feat_resource_blob, + feat_host_visible, + feat_host_cross_device, feat_max, }; @@ -44,8 +48,11 @@ enum feature_id { x, #x, 0 \ } -static struct feature features[] = { FEATURE(VIRTGPU_PARAM_3D_FEATURES), - FEATURE(VIRTGPU_PARAM_CAPSET_QUERY_FIX) }; +static struct feature features[] = { + FEATURE(VIRTGPU_PARAM_3D_FEATURES), FEATURE(VIRTGPU_PARAM_CAPSET_QUERY_FIX), + FEATURE(VIRTGPU_PARAM_RESOURCE_BLOB), FEATURE(VIRTGPU_PARAM_HOST_VISIBLE), + FEATURE(VIRTGPU_PARAM_CROSS_DEVICE), +}; static const uint32_t render_target_formats[] = { DRM_FORMAT_ABGR8888, DRM_FORMAT_ARGB8888, DRM_FORMAT_RGB565, DRM_FORMAT_XBGR8888, @@ -673,9 +680,84 @@ static void virtio_gpu_close(struct driver *drv) drv->priv = NULL; } +static int virtio_gpu_bo_create_blob(struct driver *drv, struct bo *bo) +{ + int ret; + uint32_t stride; + uint32_t cmd[VIRGL_PIPE_RES_CREATE_SIZE + 1] = { 0 }; + struct drm_virtgpu_resource_create_blob drm_rc_blob = { 0 }; + + uint32_t blob_flags = VIRTGPU_BLOB_FLAG_USE_MAPPABLE | VIRTGPU_BLOB_FLAG_USE_SHAREABLE; + if (bo->meta.use_flags & BO_USE_NON_GPU_HW) { + blob_flags |= VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE; + } + + stride = drv_stride_from_format(bo->meta.format, bo->meta.width, 0); + drv_bo_from_format(bo, stride, bo->meta.height, bo->meta.format); + bo->meta.total_size = ALIGN(bo->meta.total_size, PAGE_SIZE); + bo->meta.tiling = blob_flags; + + cmd[0] = VIRGL_CMD0(VIRGL_CCMD_PIPE_RESOURCE_CREATE, 0, VIRGL_PIPE_RES_CREATE_SIZE); + cmd[VIRGL_PIPE_RES_CREATE_TARGET] = PIPE_TEXTURE_2D; + 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] = use_flags_to_bind(bo->meta.use_flags); + cmd[VIRGL_PIPE_RES_CREATE_DEPTH] = 1; + + drm_rc_blob.cmd = (uint64_t)&cmd; + drm_rc_blob.cmd_size = 4 * (VIRGL_PIPE_RES_CREATE_SIZE + 1); + drm_rc_blob.size = bo->meta.total_size; + drm_rc_blob.blob_mem = VIRTGPU_BLOB_MEM_HOST3D; + drm_rc_blob.blob_flags = blob_flags; + + 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)); + return -errno; + } + + for (uint32_t plane = 0; plane < bo->meta.num_planes; plane++) + bo->handles[plane].u32 = drm_rc_blob.bo_handle; + + return 0; +} + +static bool should_use_blob(struct driver *drv, uint32_t format, uint64_t use_flags) +{ + struct virtio_gpu_priv *priv = (struct virtio_gpu_priv *)drv->priv; + + // TODO(gurchetansingh): remove once all minigbm users are blob-safe +#ifndef VIRTIO_GPU_NEXT + return false; +#endif + + // Only use blob when host gbm is available + if (!priv->host_gbm_enabled) + return false; + + // Focus on non-GPU apps for now + if (use_flags & (BO_USE_RENDERING | BO_USE_TEXTURE)) + return false; + + // Simple, strictly defined formats for now + if (format != DRM_FORMAT_YVU420_ANDROID && format != DRM_FORMAT_R8) + return false; + + if (use_flags & + (BO_USE_SW_READ_OFTEN | BO_USE_SW_WRITE_OFTEN | BO_USE_LINEAR | BO_USE_NON_GPU_HW)) + return true; + + return false; +} + static int virtio_gpu_bo_create(struct bo *bo, uint32_t width, uint32_t height, uint32_t format, uint64_t use_flags) { + if (features[feat_resource_blob].enabled && features[feat_host_visible].enabled && + should_use_blob(bo->drv, format, use_flags)) + return virtio_gpu_bo_create_blob(bo->drv, bo); + if (features[feat_3d].enabled) return virtio_virgl_bo_create(bo, width, height, format, use_flags); else @@ -715,6 +797,10 @@ static int virtio_gpu_bo_invalidate(struct bo *bo, struct mapping *mapping) BO_USE_HW_VIDEO_ENCODER | BO_USE_HW_VIDEO_DECODER)) == 0) return 0; + if (features[feat_resource_blob].enabled && + (bo->meta.tiling & VIRTGPU_BLOB_FLAG_USE_MAPPABLE)) + return 0; + memset(&xfer, 0, sizeof(xfer)); xfer.bo_handle = mapping->vma->handle; @@ -798,6 +884,10 @@ static int virtio_gpu_bo_flush(struct bo *bo, struct mapping *mapping) if (!(mapping->vma->map_flags & BO_MAP_WRITE)) return 0; + if (features[feat_resource_blob].enabled && + (bo->meta.tiling & VIRTGPU_BLOB_FLAG_USE_MAPPABLE)) + return 0; + memset(&xfer, 0, sizeof(xfer)); xfer.bo_handle = mapping->vma->handle; |
