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