blob: f33f5216dc0964cd95ef01f599caceb262be3bbe [file] [log] [blame]
Greg Daniel7e000222018-12-03 10:08:21 -05001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/gpu/vk/GrVkSamplerYcbcrConversion.h"
Greg Daniel7e000222018-12-03 10:08:21 -05009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "src/gpu/vk/GrVkGpu.h"
Greg Daniel7e000222018-12-03 10:08:21 -050011
12GrVkSamplerYcbcrConversion* GrVkSamplerYcbcrConversion::Create(
13 const GrVkGpu* gpu, const GrVkYcbcrConversionInfo& info) {
14 if (!gpu->vkCaps().supportsYcbcrConversion()) {
15 return nullptr;
16 }
Greg Daniel7e000222018-12-03 10:08:21 -050017
18#ifdef SK_DEBUG
Sergey Ulanov2739fd22019-08-11 22:46:33 -070019 const VkFormatFeatureFlags& featureFlags = info.fFormatFeatures;
Greg Daniel7e000222018-12-03 10:08:21 -050020 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
Greg Daniel7e000222018-12-03 10:08:21 -050037
38 VkSamplerYcbcrConversionCreateInfo ycbcrCreateInfo;
Greg Daniel7e000222018-12-03 10:08:21 -050039 ycbcrCreateInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO;
Sergey Ulanov2739fd22019-08-11 22:46:33 -070040 ycbcrCreateInfo.pNext = nullptr;
41 ycbcrCreateInfo.format = info.fFormat;
Greg Daniel7e000222018-12-03 10:08:21 -050042 ycbcrCreateInfo.ycbcrModel = info.fYcbcrModel;
43 ycbcrCreateInfo.ycbcrRange = info.fYcbcrRange;
Sergey Ulanov2739fd22019-08-11 22:46:33 -070044
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};
Greg Daniel7e000222018-12-03 10:08:21 -050049 ycbcrCreateInfo.xChromaOffset = info.fXChromaOffset;
50 ycbcrCreateInfo.yChromaOffset = info.fYChromaOffset;
51 ycbcrCreateInfo.chromaFilter = info.fChromaFilter;
52 ycbcrCreateInfo.forceExplicitReconstruction = info.fForceExplicitReconstruction;
53
Sergey Ulanov2739fd22019-08-11 22:46:33 -070054#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#else
65 // External images are supported only on Android;
66 SkASSERT(!info.fExternalFormat);
67#endif
68
69 if (!info.fExternalFormat) {
70 SkASSERT(info.fFormat != VK_FORMAT_UNDEFINED);
71 }
72
Greg Daniel7e000222018-12-03 10:08:21 -050073 VkSamplerYcbcrConversion conversion;
74 GR_VK_CALL(gpu->vkInterface(), CreateSamplerYcbcrConversion(gpu->device(), &ycbcrCreateInfo,
75 nullptr, &conversion));
76 if (conversion == VK_NULL_HANDLE) {
77 return nullptr;
78 }
Sergey Ulanov2739fd22019-08-11 22:46:33 -070079
Greg Daniel7e000222018-12-03 10:08:21 -050080 return new GrVkSamplerYcbcrConversion(conversion, GenerateKey(info));
Greg Daniel7e000222018-12-03 10:08:21 -050081}
82
Ethan Nicholas8e265a72018-12-12 16:22:40 -050083void GrVkSamplerYcbcrConversion::freeGPUData(GrVkGpu* gpu) const {
Greg Daniel7e000222018-12-03 10:08:21 -050084 SkASSERT(fYcbcrConversion);
85 GR_VK_CALL(gpu->vkInterface(), DestroySamplerYcbcrConversion(gpu->device(), fYcbcrConversion,
86 nullptr));
87}
88
89GrVkSamplerYcbcrConversion::Key GrVkSamplerYcbcrConversion::GenerateKey(
90 const GrVkYcbcrConversionInfo& ycbcrInfo) {
91 SkASSERT(static_cast<int>(ycbcrInfo.fYcbcrModel <= 7));
92 static const int kRangeShift = 3;
93 SkASSERT(static_cast<int>(ycbcrInfo.fYcbcrRange) <= 1);
94 static const int kXChromaOffsetShift = kRangeShift + 1;
95 SkASSERT(static_cast<int>(ycbcrInfo.fXChromaOffset) <= 1);
96 static const int kYChromaOffsetShift = kXChromaOffsetShift + 1;
97 SkASSERT(static_cast<int>(ycbcrInfo.fXChromaOffset) <= 1);
98 static const int kChromaFilterShift = kYChromaOffsetShift + 1;
99 SkASSERT(static_cast<int>(ycbcrInfo.fChromaFilter) <= 1);
100 static const int kReconShift = kChromaFilterShift + 1;
101 SkASSERT(static_cast<int>(ycbcrInfo.fForceExplicitReconstruction) <= 1);
102 GR_STATIC_ASSERT(kReconShift <= 7);
103
104 uint8_t ycbcrKey = static_cast<uint8_t>(ycbcrInfo.fYcbcrModel);
105 ycbcrKey |= (static_cast<uint8_t>(ycbcrInfo.fYcbcrRange) << kRangeShift);
106 ycbcrKey |= (static_cast<uint8_t>(ycbcrInfo.fXChromaOffset) << kXChromaOffsetShift);
107 ycbcrKey |= (static_cast<uint8_t>(ycbcrInfo.fYChromaOffset) << kYChromaOffsetShift);
108 ycbcrKey |= (static_cast<uint8_t>(ycbcrInfo.fChromaFilter) << kChromaFilterShift);
109 ycbcrKey |= (static_cast<uint8_t>(ycbcrInfo.fForceExplicitReconstruction) << kReconShift);
110
Sergey Ulanov2739fd22019-08-11 22:46:33 -0700111 return Key{ycbcrInfo.fFormat, ycbcrInfo.fExternalFormat, ycbcrKey};
Greg Daniel7e000222018-12-03 10:08:21 -0500112}