/* * Copyright 2018 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "src/gpu/vk/GrVkSamplerYcbcrConversion.h" #include "src/gpu/vk/GrVkGpu.h" GrVkSamplerYcbcrConversion* GrVkSamplerYcbcrConversion::Create( GrVkGpu* gpu, const GrVkYcbcrConversionInfo& info) { if (!gpu->vkCaps().supportsYcbcrConversion()) { return nullptr; } #ifdef SK_DEBUG const VkFormatFeatureFlags& featureFlags = info.fFormatFeatures; if (info.fXChromaOffset == VK_CHROMA_LOCATION_MIDPOINT || info.fYChromaOffset == VK_CHROMA_LOCATION_MIDPOINT) { SkASSERT(featureFlags & VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT); } if (info.fXChromaOffset == VK_CHROMA_LOCATION_COSITED_EVEN || info.fYChromaOffset == VK_CHROMA_LOCATION_COSITED_EVEN) { SkASSERT(featureFlags & VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT); } if (info.fChromaFilter == VK_FILTER_LINEAR) { SkASSERT(featureFlags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT); } if (info.fForceExplicitReconstruction) { SkASSERT(featureFlags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT); } #endif VkSamplerYcbcrConversionCreateInfo ycbcrCreateInfo; ycbcrCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO; ycbcrCreateInfo.pNext = nullptr; ycbcrCreateInfo.format = info.fFormat; ycbcrCreateInfo.ycbcrModel = info.fYcbcrModel; ycbcrCreateInfo.ycbcrRange = info.fYcbcrRange; // Components is ignored for external format conversions. For all other formats identity swizzle // is used. It can be added to GrVkYcbcrConversionInfo if necessary. ycbcrCreateInfo.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY}; ycbcrCreateInfo.xChromaOffset = info.fXChromaOffset; ycbcrCreateInfo.yChromaOffset = info.fYChromaOffset; ycbcrCreateInfo.chromaFilter = info.fChromaFilter; ycbcrCreateInfo.forceExplicitReconstruction = info.fForceExplicitReconstruction; #ifdef SK_BUILD_FOR_ANDROID VkExternalFormatANDROID externalFormat; if (info.fExternalFormat) { // Format must not be specified for external images. SkASSERT(info.fFormat == VK_FORMAT_UNDEFINED); externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID; externalFormat.pNext = nullptr; externalFormat.externalFormat = info.fExternalFormat; ycbcrCreateInfo.pNext = &externalFormat; } #elif defined(VK_USE_PLATFORM_OHOS) VkExternalFormatOHOS externalFormat; if (info.fExternalFormat) { // Format must not be specified for external images. SkASSERT(info.fFormat == VK_FORMAT_UNDEFINED); externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_OHOS; externalFormat.pNext = nullptr; externalFormat.externalFormat = info.fExternalFormat; ycbcrCreateInfo.pNext = &externalFormat; } #else // External images are supported only on Android/OpenHarmony; SkASSERT(!info.fExternalFormat); #endif if (!info.fExternalFormat) { SkASSERT(info.fFormat != VK_FORMAT_UNDEFINED); } VkSamplerYcbcrConversion conversion; VkResult result; GR_VK_CALL_RESULT(gpu, result, CreateSamplerYcbcrConversion(gpu->device(), &ycbcrCreateInfo, nullptr, &conversion)); if (result != VK_SUCCESS) { return nullptr; } return new GrVkSamplerYcbcrConversion(gpu, conversion, GenerateKey(info)); } void GrVkSamplerYcbcrConversion::freeGPUData() const { SkASSERT(fYcbcrConversion); GR_VK_CALL(fGpu->vkInterface(), DestroySamplerYcbcrConversion(fGpu->device(), fYcbcrConversion, nullptr)); } GrVkSamplerYcbcrConversion::Key GrVkSamplerYcbcrConversion::GenerateKey( const GrVkYcbcrConversionInfo& ycbcrInfo) { SkASSERT(static_cast(ycbcrInfo.fYcbcrModel <= 7)); static const int kRangeShift = 3; SkASSERT(static_cast(ycbcrInfo.fYcbcrRange) <= 1); static const int kXChromaOffsetShift = kRangeShift + 1; SkASSERT(static_cast(ycbcrInfo.fXChromaOffset) <= 1); static const int kYChromaOffsetShift = kXChromaOffsetShift + 1; SkASSERT(static_cast(ycbcrInfo.fXChromaOffset) <= 1); static const int kChromaFilterShift = kYChromaOffsetShift + 1; SkASSERT(static_cast(ycbcrInfo.fChromaFilter) <= 1); static const int kReconShift = kChromaFilterShift + 1; SkASSERT(static_cast(ycbcrInfo.fForceExplicitReconstruction) <= 1); static_assert(kReconShift <= 7); uint8_t ycbcrKey = static_cast(ycbcrInfo.fYcbcrModel); ycbcrKey |= (static_cast(ycbcrInfo.fYcbcrRange) << kRangeShift); ycbcrKey |= (static_cast(ycbcrInfo.fXChromaOffset) << kXChromaOffsetShift); ycbcrKey |= (static_cast(ycbcrInfo.fYChromaOffset) << kYChromaOffsetShift); ycbcrKey |= (static_cast(ycbcrInfo.fChromaFilter) << kChromaFilterShift); ycbcrKey |= (static_cast(ycbcrInfo.fForceExplicitReconstruction) << kReconShift); return Key{ycbcrInfo.fFormat, ycbcrInfo.fExternalFormat, ycbcrKey}; }