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/ganesh/vk/GrVkSamplerYcbcrConversion.h"
9
10 #include "include/gpu/vk/VulkanTypes.h"
11 #include "include/private/base/SkAssert.h"
12 #include "src/gpu/ganesh/vk/GrVkCaps.h"
13 #include "src/gpu/ganesh/vk/GrVkGpu.h"
14 #include "src/gpu/ganesh/vk/GrVkUtil.h"
15 #include "src/gpu/vk/VulkanUtilsPriv.h"
16
Create(GrVkGpu * gpu,const skgpu::VulkanYcbcrConversionInfo & info)17 GrVkSamplerYcbcrConversion* GrVkSamplerYcbcrConversion::Create(
18 GrVkGpu* gpu, const skgpu::VulkanYcbcrConversionInfo& info) {
19 if (!gpu->vkCaps().supportsYcbcrConversion()) {
20 return nullptr;
21 }
22
23 VkSamplerYcbcrConversionCreateInfo ycbcrCreateInfo;
24 skgpu::SetupSamplerYcbcrConversionInfo(&ycbcrCreateInfo, info);
25
26 #ifdef SK_BUILD_FOR_ANDROID
27 VkExternalFormatANDROID externalFormat;
28 if (info.fExternalFormat) {
29 // Format must not be specified for external images.
30 SkASSERT(info.fFormat == VK_FORMAT_UNDEFINED);
31 externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID;
32 externalFormat.pNext = nullptr;
33 externalFormat.externalFormat = info.fExternalFormat;
34 SkASSERT(ycbcrCreateInfo.pNext == nullptr);
35 ycbcrCreateInfo.pNext = &externalFormat;
36 }
37 #elif defined(VK_USE_PLATFORM_OHOS)
38 VkExternalFormatOHOS externalFormat;
39 if (info.fExternalFormat) {
40 // Format must not be specified for external images.
41 SkASSERT(info.fFormat == VK_FORMAT_UNDEFINED);
42 externalFormat.sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_OHOS;
43 externalFormat.pNext = nullptr;
44 externalFormat.externalFormat = info.fExternalFormat;
45 ycbcrCreateInfo.pNext = &externalFormat;
46 }
47 #else
48 // External images are supported only on Android/OpenHarmony.
49 SkASSERT(!info.fExternalFormat);
50 #endif
51
52 if (!info.fExternalFormat) {
53 SkASSERT(info.fFormat != VK_FORMAT_UNDEFINED);
54 }
55
56 VkSamplerYcbcrConversion conversion;
57 VkResult result;
58 GR_VK_CALL_RESULT(gpu, result, CreateSamplerYcbcrConversion(gpu->device(), &ycbcrCreateInfo,
59 nullptr, &conversion));
60 if (result != VK_SUCCESS) {
61 return nullptr;
62 }
63
64 return new GrVkSamplerYcbcrConversion(gpu, conversion, GenerateKey(info));
65 }
66
freeGPUData() const67 void GrVkSamplerYcbcrConversion::freeGPUData() const {
68 SkASSERT(fYcbcrConversion);
69 GR_VK_CALL(fGpu->vkInterface(), DestroySamplerYcbcrConversion(fGpu->device(),
70 fYcbcrConversion, nullptr));
71 }
72
GenerateKey(const skgpu::VulkanYcbcrConversionInfo & ycbcrInfo)73 GrVkSamplerYcbcrConversion::Key GrVkSamplerYcbcrConversion::GenerateKey(
74 const skgpu::VulkanYcbcrConversionInfo& ycbcrInfo) {
75 SkASSERT(static_cast<int>(ycbcrInfo.fYcbcrModel <= 7));
76 static const int kRangeShift = 3;
77 SkASSERT(static_cast<int>(ycbcrInfo.fYcbcrRange) <= 1);
78 static const int kXChromaOffsetShift = kRangeShift + 1;
79 SkASSERT(static_cast<int>(ycbcrInfo.fXChromaOffset) <= 1);
80 static const int kYChromaOffsetShift = kXChromaOffsetShift + 1;
81 SkASSERT(static_cast<int>(ycbcrInfo.fXChromaOffset) <= 1);
82 static const int kChromaFilterShift = kYChromaOffsetShift + 1;
83 SkASSERT(static_cast<int>(ycbcrInfo.fChromaFilter) <= 1);
84 static const int kReconShift = kChromaFilterShift + 1;
85 SkASSERT(static_cast<int>(ycbcrInfo.fForceExplicitReconstruction) <= 1);
86 static const int kCompRShift = kReconShift + 1;
87 static const int kCompGShift = kCompRShift + 3;
88 static const int kCompBShift = kCompGShift + 3;
89 static const int kCompAShift = kCompBShift + 3;
90 SkASSERT(static_cast<int>(ycbcrInfo.fComponents.r <= 6) &&
91 static_cast<int>(ycbcrInfo.fComponents.g <= 6) &&
92 static_cast<int>(ycbcrInfo.fComponents.b <= 6) &&
93 static_cast<int>(ycbcrInfo.fComponents.a <= 6));
94 static_assert(kCompAShift <= 17);
95
96 uint32_t ycbcrKey = static_cast<uint32_t>(ycbcrInfo.fYcbcrModel);
97 ycbcrKey |= (static_cast<uint32_t>(ycbcrInfo.fYcbcrRange) << kRangeShift);
98 ycbcrKey |= (static_cast<uint32_t>(ycbcrInfo.fXChromaOffset) << kXChromaOffsetShift);
99 ycbcrKey |= (static_cast<uint32_t>(ycbcrInfo.fYChromaOffset) << kYChromaOffsetShift);
100 ycbcrKey |= (static_cast<uint32_t>(ycbcrInfo.fChromaFilter) << kChromaFilterShift);
101 ycbcrKey |= (static_cast<uint32_t>(ycbcrInfo.fForceExplicitReconstruction) << kReconShift);
102 ycbcrKey |= (static_cast<uint32_t>(ycbcrInfo.fComponents.r) << kCompRShift);
103 ycbcrKey |= (static_cast<uint32_t>(ycbcrInfo.fComponents.g) << kCompGShift);
104 ycbcrKey |= (static_cast<uint32_t>(ycbcrInfo.fComponents.b) << kCompBShift);
105 ycbcrKey |= (static_cast<uint32_t>(ycbcrInfo.fComponents.a) << kCompAShift);
106
107 return Key{ycbcrInfo.fFormat, ycbcrInfo.fExternalFormat, ycbcrKey};
108 }
109