• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Create(GrVkGpu * gpu,const GrVkYcbcrConversionInfo & info)12 GrVkSamplerYcbcrConversion* 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 
freeGPUData() const94 void GrVkSamplerYcbcrConversion::freeGPUData() const {
95     SkASSERT(fYcbcrConversion);
96     GR_VK_CALL(fGpu->vkInterface(), DestroySamplerYcbcrConversion(fGpu->device(),
97                                                                   fYcbcrConversion, nullptr));
98 }
99 
GenerateKey(const GrVkYcbcrConversionInfo & ycbcrInfo)100 GrVkSamplerYcbcrConversion::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