1 /*
2 * Copyright 2021 Google LLC
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/GrYUVATextureProxies.h"
9
10 #include "include/core/SkColor.h"
11 #include "include/core/SkTypes.h"
12 #include "include/gpu/ganesh/GrBackendSurface.h"
13 #include "include/private/gpu/ganesh/GrTypesPriv.h"
14 #include "src/core/SkYUVAInfoLocation.h"
15 #include "src/gpu/ganesh/GrTextureProxy.h"
16
17 #include <cstddef>
18 #include <cstdint>
19 #include <utility>
20
21 #ifdef SK_DEBUG
num_channels(uint32_t channelFlags)22 static int num_channels(uint32_t channelFlags) {
23 switch (channelFlags) {
24 case kRed_SkColorChannelFlag : return 1;
25 case kAlpha_SkColorChannelFlag : return 1;
26 case kGray_SkColorChannelFlag : return 1;
27 case kGrayAlpha_SkColorChannelFlags : return 2;
28 case kRG_SkColorChannelFlags : return 2;
29 case kRGB_SkColorChannelFlags : return 3;
30 case kRGBA_SkColorChannelFlags : return 4;
31
32 default:
33 SkDEBUGFAILF("Unexpected channel combination 0x%08x", channelFlags);
34 return 0;
35 }
36 }
37 #endif
38
GrYUVATextureProxies(const SkYUVAInfo & yuvaInfo,sk_sp<GrSurfaceProxy> proxies[SkYUVAInfo::kMaxPlanes],GrSurfaceOrigin textureOrigin)39 GrYUVATextureProxies::GrYUVATextureProxies(const SkYUVAInfo& yuvaInfo,
40 sk_sp<GrSurfaceProxy> proxies[SkYUVAInfo::kMaxPlanes],
41 GrSurfaceOrigin textureOrigin)
42 : fYUVAInfo(yuvaInfo), fTextureOrigin(textureOrigin) {
43 int n = yuvaInfo.numPlanes();
44 if (n == 0) {
45 *this = {};
46 SkASSERT(!this->isValid());
47 return;
48 }
49 uint32_t textureChannelMasks[SkYUVAInfo::kMaxPlanes];
50 for (int i = 0; i < n; ++i) {
51 if (!proxies[i]) {
52 *this = {};
53 SkASSERT(!this->isValid());
54 return;
55 }
56 textureChannelMasks[i] = proxies[i]->backendFormat().channelMask();
57 }
58 fYUVALocations = yuvaInfo.toYUVALocations(textureChannelMasks);
59 if (fYUVALocations[0].fPlane < 0) {
60 *this = {};
61 SkASSERT(!this->isValid());
62 return;
63 }
64 fMipmapped = skgpu::Mipmapped::kYes;
65 for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
66 if (!proxies[i]) {
67 *this = {};
68 SkASSERT(!this->isValid());
69 return;
70 }
71 SkASSERT(proxies[i]->asTextureProxy());
72 if (proxies[i]->asTextureProxy()->mipmapped() == skgpu::Mipmapped::kNo) {
73 fMipmapped = skgpu::Mipmapped::kNo;
74 }
75 fProxies[i] = std::move(proxies[i]);
76 }
77 SkASSERT(this->isValid());
78 }
79
GrYUVATextureProxies(const SkYUVAInfo & yuvaInfo,GrSurfaceProxyView views[SkYUVAInfo::kMaxPlanes],GrColorType colorTypes[SkYUVAInfo::kMaxPlanes])80 GrYUVATextureProxies::GrYUVATextureProxies(const SkYUVAInfo& yuvaInfo,
81 GrSurfaceProxyView views[SkYUVAInfo::kMaxPlanes],
82 GrColorType colorTypes[SkYUVAInfo::kMaxPlanes])
83 : fYUVAInfo(yuvaInfo) {
84 uint32_t pixmapChannelMasks[SkYUVAInfo::kMaxPlanes];
85 int n = yuvaInfo.numPlanes();
86 if (n == 0) {
87 *this = {};
88 SkASSERT(!this->isValid());
89 return;
90 }
91 fMipmapped = skgpu::Mipmapped::kYes;
92 for (int i = 0; i < n; ++i) {
93 pixmapChannelMasks[i] = GrColorTypeChannelFlags(colorTypes[i]);
94 SkASSERT(num_channels(pixmapChannelMasks[i]) <=
95 num_channels(views[i].proxy()->backendFormat().channelMask()));
96 if (!views[i] || views[i].origin() != views[0].origin()) {
97 *this = {};
98 SkASSERT(!this->isValid());
99 return;
100 }
101 if (views[i].proxy()->asTextureProxy()->mipmapped() == skgpu::Mipmapped::kNo) {
102 fMipmapped = skgpu::Mipmapped::kNo;
103 }
104 }
105 // Initial locations refer to the CPU pixmap channels.
106 fYUVALocations = yuvaInfo.toYUVALocations(pixmapChannelMasks);
107 if (fYUVALocations[0].fPlane < 0) {
108 *this = {};
109 SkASSERT(!this->isValid());
110 return;
111 }
112
113 // Run each location through the proxy view's swizzle to get the actual texture format channel.
114 for (int i = 0; i < SkYUVAInfo::kYUVAChannelCount; ++i) {
115 int plane = fYUVALocations[i].fPlane;
116 if (plane >= 0) {
117 int chanAsIdx = static_cast<int>(fYUVALocations[i].fChannel);
118 switch (views[plane].swizzle()[chanAsIdx]) {
119 case 'r': fYUVALocations[i].fChannel = SkColorChannel::kR; break;
120 case 'g': fYUVALocations[i].fChannel = SkColorChannel::kG; break;
121 case 'b': fYUVALocations[i].fChannel = SkColorChannel::kB; break;
122 case 'a': fYUVALocations[i].fChannel = SkColorChannel::kA; break;
123
124 default:
125 SkDEBUGFAILF("Unexpected swizzle value: %c", views[i].swizzle()[chanAsIdx]);
126 *this = {};
127 SkASSERT(!this->isValid());
128 return;
129 }
130 }
131 }
132 for (int i = 0; i < n; ++i) {
133 fProxies[i] = views[i].detachProxy();
134 }
135 fTextureOrigin = views[0].origin();
136 SkASSERT(this->isValid());
137 }
138