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