1/* 2 * Copyright 2018 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "src/gpu/vk/GrVkSamplerYcbcrConversion.h" 9 10#include "src/gpu/vk/GrVkGpu.h" 11 12GrVkSamplerYcbcrConversion* GrVkSamplerYcbcrConversion::Create( 13 GrVkGpu* gpu, const GrVkYcbcrConversionInfo& info) { 14 if (!gpu->vkCaps().supportsYcbcrConversion()) { 15 return nullptr; 16 } 17 18#ifdef SK_DEBUG 19 const VkFormatFeatureFlags& featureFlags = info.fFormatFeatures; 20 if (info.fXChromaOffset == VK_CHROMA_LOCATION_MIDPOINT || 21 info.fYChromaOffset == VK_CHROMA_LOCATION_MIDPOINT) { 22 SkASSERT(featureFlags & VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT); 23 } 24 if (info.fXChromaOffset == VK_CHROMA_LOCATION_COSITED_EVEN || 25 info.fYChromaOffset == VK_CHROMA_LOCATION_COSITED_EVEN) { 26 SkASSERT(featureFlags & VK_FORMAT_FEATURE_COSITED_CHROMA_SAMPLES_BIT); 27 } 28 if (info.fChromaFilter == VK_FILTER_LINEAR) { 29 SkASSERT(featureFlags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT); 30 } 31 if (info.fForceExplicitReconstruction) { 32 SkASSERT(featureFlags & 33 VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT); 34 } 35#endif 36 37 38 VkSamplerYcbcrConversionCreateInfo ycbcrCreateInfo; 39 ycbcrCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO; 40 ycbcrCreateInfo.pNext = nullptr; 41 ycbcrCreateInfo.format = info.fFormat; 42 ycbcrCreateInfo.ycbcrModel = info.fYcbcrModel; 43 ycbcrCreateInfo.ycbcrRange = info.fYcbcrRange; 44 45 // Components is ignored for external format conversions. For all other formats identity swizzle 46 // is used. It can be added to GrVkYcbcrConversionInfo if necessary. 47 ycbcrCreateInfo.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, 48 VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY}; 49 ycbcrCreateInfo.xChromaOffset = info.fXChromaOffset; 50 ycbcrCreateInfo.yChromaOffset = info.fYChromaOffset; 51 ycbcrCreateInfo.chromaFilter = info.fChromaFilter; 52 ycbcrCreateInfo.forceExplicitReconstruction = info.fForceExplicitReconstruction; 53 54#ifdef SK_BUILD_FOR_ANDROID 55 VkExternalFormatANDROID externalFormat; 56 if (info.fExternalFormat) { 57 // Format must not be specified for external images. 58 SkASSERT(info.fFormat == VK_FORMAT_UNDEFINED); 59 externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID; 60 externalFormat.pNext = nullptr; 61 externalFormat.externalFormat = info.fExternalFormat; 62 ycbcrCreateInfo.pNext = &externalFormat; 63 } 64#elif defined(VK_USE_PLATFORM_OHOS) 65 VkExternalFormatOHOS externalFormat; 66 if (info.fExternalFormat) { 67 // Format must not be specified for external images. 68 SkASSERT(info.fFormat == VK_FORMAT_UNDEFINED); 69 externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_OHOS; 70 externalFormat.pNext = nullptr; 71 externalFormat.externalFormat = info.fExternalFormat; 72 ycbcrCreateInfo.pNext = &externalFormat; 73 } 74#else 75 // External images are supported only on Android/OpenHarmony; 76 SkASSERT(!info.fExternalFormat); 77#endif 78 79 if (!info.fExternalFormat) { 80 SkASSERT(info.fFormat != VK_FORMAT_UNDEFINED); 81 } 82 83 VkSamplerYcbcrConversion conversion; 84 VkResult result; 85 GR_VK_CALL_RESULT(gpu, result, CreateSamplerYcbcrConversion(gpu->device(), &ycbcrCreateInfo, 86 nullptr, &conversion)); 87 if (result != VK_SUCCESS) { 88 return nullptr; 89 } 90 91 return new GrVkSamplerYcbcrConversion(gpu, conversion, GenerateKey(info)); 92} 93 94void GrVkSamplerYcbcrConversion::freeGPUData() const { 95 SkASSERT(fYcbcrConversion); 96 GR_VK_CALL(fGpu->vkInterface(), DestroySamplerYcbcrConversion(fGpu->device(), 97 fYcbcrConversion, nullptr)); 98} 99 100GrVkSamplerYcbcrConversion::Key GrVkSamplerYcbcrConversion::GenerateKey( 101 const GrVkYcbcrConversionInfo& ycbcrInfo) { 102 SkASSERT(static_cast<int>(ycbcrInfo.fYcbcrModel <= 7)); 103 static const int kRangeShift = 3; 104 SkASSERT(static_cast<int>(ycbcrInfo.fYcbcrRange) <= 1); 105 static const int kXChromaOffsetShift = kRangeShift + 1; 106 SkASSERT(static_cast<int>(ycbcrInfo.fXChromaOffset) <= 1); 107 static const int kYChromaOffsetShift = kXChromaOffsetShift + 1; 108 SkASSERT(static_cast<int>(ycbcrInfo.fXChromaOffset) <= 1); 109 static const int kChromaFilterShift = kYChromaOffsetShift + 1; 110 SkASSERT(static_cast<int>(ycbcrInfo.fChromaFilter) <= 1); 111 static const int kReconShift = kChromaFilterShift + 1; 112 SkASSERT(static_cast<int>(ycbcrInfo.fForceExplicitReconstruction) <= 1); 113 static_assert(kReconShift <= 7); 114 115 uint8_t ycbcrKey = static_cast<uint8_t>(ycbcrInfo.fYcbcrModel); 116 ycbcrKey |= (static_cast<uint8_t>(ycbcrInfo.fYcbcrRange) << kRangeShift); 117 ycbcrKey |= (static_cast<uint8_t>(ycbcrInfo.fXChromaOffset) << kXChromaOffsetShift); 118 ycbcrKey |= (static_cast<uint8_t>(ycbcrInfo.fYChromaOffset) << kYChromaOffsetShift); 119 ycbcrKey |= (static_cast<uint8_t>(ycbcrInfo.fChromaFilter) << kChromaFilterShift); 120 ycbcrKey |= (static_cast<uint8_t>(ycbcrInfo.fForceExplicitReconstruction) << kReconShift); 121 122 return Key{ycbcrInfo.fFormat, ycbcrInfo.fExternalFormat, ycbcrKey}; 123} 124