Skip to content

Commit

Permalink
[Fuchsia] Enable YCbCr samplers support
Browse files Browse the repository at this point in the history
Previously compositor supported YCbCr samplers only on Android and only
for external Vulkan images. On Fuchsia sysmem APIs use Vulkan I420
formats to return decoded images and so YCbCr samplers have to be used
to render them on the screen. In this CL:
 1. Updated VulkanImplementation::CreateImageFromGpuMemoryHandle() to
    make it possible to return YCbCr info.
 2. Added image_format in gpu::VulkanYCbCrInfo to remove the
    assumption YCbCr images are always external.
 3. ExternalVkImageBacking now bundles returned YCbCr info in
    GrVkImageInfo when wrapping in GrBackendTexture.
 4. SkiaOutputSurfaceImpl now passes image format when initializing
    GrVkYcbcrConversionInfo.
 5. Updated VulkanDeviceQueue and VulkanImplementationScenic to
    enable YCbCr sampler extension on Fuchsia.

Bug: 981022
Change-Id: I477ebf698d098bafefaadbf77dfa8d373f9ae076
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1730311
Commit-Queue: Sergey Ulanov <sergeyu@chromium.org>
Reviewed-by: Eric Karl <ericrk@chromium.org>
Reviewed-by: Michael Spang <spang@chromium.org>
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#686649}
  • Loading branch information
SergeyUlanov authored and Commit Bot committed Aug 14, 2019
1 parent 272d4b0 commit 6ff66f2
Show file tree
Hide file tree
Showing 26 changed files with 196 additions and 115 deletions.
4 changes: 3 additions & 1 deletion components/viz/common/resources/resource_format_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -450,9 +450,11 @@ VkFormat ToVkFormat(ResourceFormat format) {
return VK_FORMAT_R8_UNORM;
case LUMINANCE_8:
return VK_FORMAT_R8_UNORM;
case LUMINANCE_F16:
case YVU_420:
return VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM;
case YUV_420_BIPLANAR:
return VK_FORMAT_G8_B8R8_2PLANE_420_UNORM;
case LUMINANCE_F16:
case UYVY_422:
case ETC1:
case P010:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -649,17 +649,19 @@ GrBackendFormat SkiaOutputSurfaceImpl::GetGrBackendFormatForTexture(
if (!ycbcr_info)
return GrBackendFormat::MakeVk(ToVkFormat(resource_format));

GrVkYcbcrConversionInfo fYcbcrConversionInfo(
VkFormat format = ycbcr_info->external_format ? VK_FORMAT_UNDEFINED
: ToVkFormat(resource_format);
GrVkYcbcrConversionInfo gr_ycbcr_info(
format, ycbcr_info->external_format,
static_cast<VkSamplerYcbcrModelConversion>(
ycbcr_info->suggested_ycbcr_model),
static_cast<VkSamplerYcbcrRange>(ycbcr_info->suggested_ycbcr_range),
static_cast<VkChromaLocation>(ycbcr_info->suggested_xchroma_offset),
static_cast<VkChromaLocation>(ycbcr_info->suggested_ychroma_offset),
VK_FILTER_LINEAR, // VkFilter
0, // VkBool32 forceExplicitReconstruction,
ycbcr_info->external_format,
static_cast<VkFormatFeatureFlags>(ycbcr_info->format_features));
return GrBackendFormat::MakeVk(fYcbcrConversionInfo);
return GrBackendFormat::MakeVk(gr_ycbcr_info);
#else
NOTREACHED();
return GrBackendFormat();
Expand Down
1 change: 1 addition & 0 deletions gpu/command_buffer/service/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ target(link_target_type, "gles2_sources") {
"//gpu/command_buffer/common:gles2_utils",
"//gpu/config",
"//gpu/ipc/common:surface_handle_type",
"//gpu/ipc/common:vulkan_ycbcr_info",
"//gpu/vulkan:buildflags",
"//third_party/angle:angle_image_util",
"//third_party/angle:commit_id",
Expand Down
62 changes: 41 additions & 21 deletions gpu/command_buffer/service/external_vk_image_backing.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "components/viz/common/resources/resource_sizes.h"
#include "gpu/command_buffer/service/external_vk_image_gl_representation.h"
#include "gpu/command_buffer/service/external_vk_image_skia_representation.h"
#include "gpu/ipc/common/vulkan_ycbcr_info.h"
#include "gpu/vulkan/vulkan_command_buffer.h"
#include "gpu/vulkan/vulkan_command_pool.h"
#include "gpu/vulkan/vulkan_fence_helper.h"
Expand All @@ -37,12 +38,28 @@ GrVkImageInfo CreateGrVkImageInfo(VkImage image,
VkFormat vk_format,
VkDeviceMemory memory,
size_t memory_size,
bool use_protected_memory) {
bool use_protected_memory,
base::Optional<VulkanYCbCrInfo> ycbcr_info) {
GrVkYcbcrConversionInfo gr_ycbcr_info{};
if (ycbcr_info) {
gr_ycbcr_info = GrVkYcbcrConversionInfo(
static_cast<VkFormat>(ycbcr_info->image_format),
ycbcr_info->external_format,
static_cast<VkSamplerYcbcrModelConversion>(
ycbcr_info->suggested_ycbcr_model),
static_cast<VkSamplerYcbcrRange>(ycbcr_info->suggested_ycbcr_range),
static_cast<VkChromaLocation>(ycbcr_info->suggested_xchroma_offset),
static_cast<VkChromaLocation>(ycbcr_info->suggested_ychroma_offset),
static_cast<VkFilter>(VK_FILTER_LINEAR),
/*forceExplicitReconstruction=*/false,
static_cast<VkFormatFeatureFlags>(ycbcr_info->format_features));
}
GrVkAlloc alloc(memory, 0 /* offset */, memory_size, 0 /* flags */);
return GrVkImageInfo(
image, alloc, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_LAYOUT_UNDEFINED,
vk_format, 1 /* levelCount */, VK_QUEUE_FAMILY_IGNORED,
use_protected_memory ? GrProtected::kYes : GrProtected::kNo);
use_protected_memory ? GrProtected::kYes : GrProtected::kNo,
gr_ycbcr_info);
}

VkResult CreateVkImage(SharedContextState* context_state,
Expand Down Expand Up @@ -140,7 +157,8 @@ std::unique_ptr<ExternalVkImageBacking> ExternalVkImageBacking::Create(
const gfx::ColorSpace& color_space,
uint32_t usage,
base::span<const uint8_t> pixel_data,
bool using_gmb) {
bool using_gmb,
base::Optional<VulkanYCbCrInfo> ycbcr_info) {
VkDevice device =
context_state->vk_context_provider()->GetDeviceQueue()->GetVulkanDevice();
VkFormat vk_format = ToVkFormat(format);
Expand Down Expand Up @@ -206,7 +224,7 @@ std::unique_ptr<ExternalVkImageBacking> ExternalVkImageBacking::Create(

auto backing = base::WrapUnique(new ExternalVkImageBacking(
mailbox, format, size, color_space, usage, context_state, image, memory,
requirements.size, vk_format, command_pool));
requirements.size, vk_format, command_pool, ycbcr_info));

if (!pixel_data.empty()) {
backing->WritePixels(
Expand All @@ -229,11 +247,6 @@ std::unique_ptr<ExternalVkImageBacking> ExternalVkImageBacking::CreateFromGMB(
const gfx::Size& size,
const gfx::ColorSpace& color_space,
uint32_t usage) {
if (gfx::NumberOfPlanesForLinearBufferFormat(buffer_format) != 1) {
DLOG(ERROR) << "Invalid image format.";
return nullptr;
}

if (!gpu::IsImageSizeValidForGpuMemoryBufferFormat(size, buffer_format)) {
DLOG(ERROR) << "Invalid image size for format.";
return nullptr;
Expand All @@ -250,17 +263,18 @@ std::unique_ptr<ExternalVkImageBacking> ExternalVkImageBacking::CreateFromGMB(
VkImageCreateInfo vk_image_info = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO};
VkDeviceMemory vk_device_memory = VK_NULL_HANDLE;
VkDeviceSize memory_size = 0;
base::Optional<gpu::VulkanYCbCrInfo> ycbcr_info;

if (!vulkan_implementation->CreateImageFromGpuMemoryHandle(
vk_device, std::move(handle), size, &vk_image, &vk_image_info,
&vk_device_memory, &memory_size)) {
&vk_device_memory, &memory_size, &ycbcr_info)) {
DLOG(ERROR) << "Failed to create VkImage from GpuMemoryHandle.";
return nullptr;
}

VkFormat expected_format = ToVkFormat(resource_format);
if (expected_format != vk_image_info.format) {
DLOG(ERROR) << "BufferFormat doesn't match the buffer";
DLOG(ERROR) << "BufferFormat doesn't match the buffer ";
vkFreeMemory(vk_device, vk_device_memory, nullptr);
vkDestroyImage(vk_device, vk_image, nullptr);
return nullptr;
Expand All @@ -269,7 +283,12 @@ std::unique_ptr<ExternalVkImageBacking> ExternalVkImageBacking::CreateFromGMB(
return base::WrapUnique(new ExternalVkImageBacking(
mailbox, viz::GetResourceFormat(buffer_format), size, color_space,
usage, context_state, vk_image, vk_device_memory, memory_size,
vk_image_info.format, command_pool));
vk_image_info.format, command_pool, ycbcr_info));
}

if (gfx::NumberOfPlanesForLinearBufferFormat(buffer_format) != 1) {
DLOG(ERROR) << "Invalid image format.";
return nullptr;
}

DCHECK_EQ(handle.type, gfx::SHARED_MEMORY_BUFFER);
Expand Down Expand Up @@ -363,7 +382,8 @@ ExternalVkImageBacking::ExternalVkImageBacking(
VkDeviceMemory memory,
size_t memory_size,
VkFormat vk_format,
VulkanCommandPool* command_pool)
VulkanCommandPool* command_pool,
base::Optional<VulkanYCbCrInfo> ycbcr_info)
: SharedImageBacking(mailbox,
format,
size,
Expand All @@ -372,14 +392,14 @@ ExternalVkImageBacking::ExternalVkImageBacking(
memory_size,
false /* is_thread_safe */),
context_state_(context_state),
backend_texture_(
size.width(),
size.height(),
CreateGrVkImageInfo(image,
vk_format,
memory,
memory_size,
usage & SHARED_IMAGE_USAGE_PROTECTED)),
backend_texture_(size.width(),
size.height(),
CreateGrVkImageInfo(image,
vk_format,
memory,
memory_size,
usage & SHARED_IMAGE_USAGE_PROTECTED,
ycbcr_info)),
command_pool_(command_pool) {}

ExternalVkImageBacking::~ExternalVkImageBacking() {
Expand Down
8 changes: 6 additions & 2 deletions gpu/command_buffer/service/external_vk_image_backing.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@

#include "base/memory/scoped_refptr.h"
#include "base/memory/shared_memory_mapping.h"
#include "base/optional.h"
#include "components/viz/common/gpu/vulkan_context_provider.h"
#include "gpu/command_buffer/common/shared_image_usage.h"
#include "gpu/command_buffer/service/shared_context_state.h"
#include "gpu/command_buffer/service/shared_image_backing.h"
#include "gpu/command_buffer/service/texture_manager.h"
#include "gpu/ipc/common/vulkan_ycbcr_info.h"
#include "gpu/vulkan/semaphore_handle.h"
#include "gpu/vulkan/vulkan_device_queue.h"
#include "ui/gfx/gpu_memory_buffer.h"
Expand All @@ -34,7 +36,8 @@ class ExternalVkImageBacking : public SharedImageBacking {
const gfx::ColorSpace& color_space,
uint32_t usage,
base::span<const uint8_t> pixel_data,
bool using_gmb = false);
bool using_gmb = false,
base::Optional<VulkanYCbCrInfo> ycbcr_info = base::nullopt);

static std::unique_ptr<ExternalVkImageBacking> CreateFromGMB(
SharedContextState* context_state,
Expand Down Expand Up @@ -116,7 +119,8 @@ class ExternalVkImageBacking : public SharedImageBacking {
VkDeviceMemory memory,
size_t memory_size,
VkFormat vk_format,
VulkanCommandPool* command_pool);
VulkanCommandPool* command_pool,
base::Optional<VulkanYCbCrInfo> ycbcr_info);

// Install a shared memory GMB to the backing.
void InstallSharedMemory(
Expand Down
14 changes: 12 additions & 2 deletions gpu/ipc/common/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,6 @@ source_set("ipc_common_sources") {
"gpu_watchdog_timeout.h",
"memory_stats.cc",
"memory_stats.h",
"vulkan_ycbcr_info.cc",
"vulkan_ycbcr_info.h",
]

if (is_mac) {
Expand Down Expand Up @@ -122,6 +120,7 @@ source_set("ipc_common_sources") {
public_deps = [
":command_buffer_traits_sources",
":surface_handle_type",
":vulkan_ycbcr_info",
"//ipc",
"//url/ipc:url_ipc",
]
Expand Down Expand Up @@ -190,6 +189,16 @@ source_set("surface_handle_type") {
]
}

source_set("vulkan_ycbcr_info") {
sources = [
"vulkan_ycbcr_info.cc",
"vulkan_ycbcr_info.h",
]
deps = [
"//base",
]
}

mojom("interfaces") {
sources = [
"capabilities.mojom",
Expand Down Expand Up @@ -254,6 +263,7 @@ source_set("mojom_traits") {
deps = [
":interfaces_shared_cpp_sources",
":surface_handle_type",
":vulkan_ycbcr_info",
"//gpu/command_buffer/common",
"//gpu/ipc/common",
"//mojo/public/cpp/bindings:bindings",
Expand Down
17 changes: 12 additions & 5 deletions gpu/ipc/common/vulkan_ycbcr_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,28 @@

#include "gpu/ipc/common/vulkan_ycbcr_info.h"

#include "base/logging.h"

namespace gpu {

VulkanYCbCrInfo::VulkanYCbCrInfo() = default;

VulkanYCbCrInfo::VulkanYCbCrInfo(uint32_t suggested_ycbcr_model,
VulkanYCbCrInfo::VulkanYCbCrInfo(uint32_t image_format,
uint64_t external_format,
uint32_t suggested_ycbcr_model,
uint32_t suggested_ycbcr_range,
uint32_t suggested_xchroma_offset,
uint32_t suggested_ychroma_offset,
uint64_t external_format,
uint32_t format_features)
: suggested_ycbcr_model(suggested_ycbcr_model),
: image_format(image_format),
external_format(external_format),
suggested_ycbcr_model(suggested_ycbcr_model),
suggested_ycbcr_range(suggested_ycbcr_range),
suggested_xchroma_offset(suggested_xchroma_offset),
suggested_ychroma_offset(suggested_ychroma_offset),
external_format(external_format),
format_features(format_features) {}
format_features(format_features) {
// One and only one of the format fields must be non-zero.
DCHECK((image_format == 0) ^ (external_format == 0));
}

} // namespace gpu
29 changes: 16 additions & 13 deletions gpu/ipc/common/vulkan_ycbcr_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,28 @@

#include <stdint.h>

#include "gpu/gpu_export.h"

namespace gpu {

// Sampler Ycbcr conversion information.
struct GPU_EXPORT VulkanYCbCrInfo {
struct VulkanYCbCrInfo {
VulkanYCbCrInfo();
VulkanYCbCrInfo(uint32_t suggested_ycbcr_model,
VulkanYCbCrInfo(uint32_t image_format,
uint64_t external_format,
uint32_t suggested_ycbcr_model,
uint32_t suggested_ycbcr_range,
uint32_t suggested_xchroma_offset,
uint32_t suggested_ychroma_offset,
uint64_t external_format,
uint32_t format_features);

// Source image format.
// Corresponds to vulkan type: VkFormat.
uint32_t image_format;

// Implementation-defined external format identifier for use with
// VkExternalFormatANDROID.
// This property is driver specific.
uint64_t external_format;

// Describes the color matrix for conversion between color models.
// Corresponds to vulkan type: VkSamplerYcbcrModelConversion.
uint32_t suggested_ycbcr_model;
Expand All @@ -42,14 +50,9 @@ struct GPU_EXPORT VulkanYCbCrInfo {
// Corresponds to vulkan type: VkChromaLocation.
uint32_t suggested_ychroma_offset;

// Implementation-defined external format identifier for use with
// VkExternalFormatANDROID.
// This property is driver specific.
uint64_t external_format;

// Describes the capabilities of the external format when used with an image
// bound to memory imported from buffer.
// Corresponds to vulkan type: VkFormatFeatureFlags.
// Describes the capabilities of the format when used with an image bound to
// memory imported from buffer. Corresponds to vulkan type:
// VkFormatFeatureFlags.
uint32_t format_features;
};

Expand Down
3 changes: 2 additions & 1 deletion gpu/ipc/common/vulkan_ycbcr_info.mojom
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ module gpu.mojom;
// in chrome.
// See gpu/ipc/common/vulkan_ycbcr_info.h.
struct VulkanYCbCrInfo {
uint32 image_format;
uint64 external_format;
uint32 suggested_ycbcr_model;
uint32 suggested_ycbcr_range;
uint32 suggested_xchroma_offset;
uint32 suggested_ychroma_offset;
uint64 external_format;
uint32 format_features;
};
15 changes: 10 additions & 5 deletions gpu/ipc/common/vulkan_ycbcr_info_mojom_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ namespace mojo {

template <>
struct StructTraits<gpu::mojom::VulkanYCbCrInfoDataView, gpu::VulkanYCbCrInfo> {
static uint32_t image_format(const gpu::VulkanYCbCrInfo& info) {
return info.image_format;
}

static uint64_t external_format(const gpu::VulkanYCbCrInfo& info) {
return info.external_format;
}

static uint32_t suggested_ycbcr_model(const gpu::VulkanYCbCrInfo& info) {
return info.suggested_ycbcr_model;
}
Expand All @@ -28,21 +36,18 @@ struct StructTraits<gpu::mojom::VulkanYCbCrInfoDataView, gpu::VulkanYCbCrInfo> {
return info.suggested_ychroma_offset;
}

static uint64_t external_format(const gpu::VulkanYCbCrInfo& info) {
return info.external_format;
}

static uint32_t format_features(const gpu::VulkanYCbCrInfo& info) {
return info.format_features;
}

static bool Read(gpu::mojom::VulkanYCbCrInfoDataView data,
gpu::VulkanYCbCrInfo* out) {
out->image_format = data.image_format();
out->external_format = data.external_format();
out->suggested_ycbcr_model = data.suggested_ycbcr_model();
out->suggested_ycbcr_range = data.suggested_ycbcr_range();
out->suggested_xchroma_offset = data.suggested_xchroma_offset();
out->suggested_ychroma_offset = data.suggested_ychroma_offset();
out->external_format = data.external_format();
out->format_features = data.format_features();
return true;
}
Expand Down
Loading

0 comments on commit 6ff66f2

Please sign in to comment.