1 /*
2 * Copyright 2023 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 "include/gpu/graphite/YUVABackendTextures.h"
9
10 #include "include/gpu/graphite/Recorder.h"
11 #include "src/core/SkYUVAInfoLocation.h"
12 #include "src/gpu/graphite/Caps.h"
13 #include "src/gpu/graphite/RecorderPriv.h"
14
15 namespace skgpu::graphite {
16
17 namespace {
num_channels(uint32_t ChannelMasks)18 int num_channels(uint32_t ChannelMasks) {
19 switch (ChannelMasks) {
20 case kRed_SkColorChannelFlag : return 1;
21 case kAlpha_SkColorChannelFlag : return 1;
22 case kGray_SkColorChannelFlag : return 1;
23 case kGrayAlpha_SkColorChannelFlags : return 2;
24 case kRG_SkColorChannelFlags : return 2;
25 case kRGB_SkColorChannelFlags : return 3;
26 case kRGBA_SkColorChannelFlags : return 4;
27 default : return 0;
28 }
29 SkUNREACHABLE;
30 }
31 }
32
YUVABackendTextureInfo(const Recorder * recorder,const SkYUVAInfo & yuvaInfo,SkSpan<const TextureInfo> textureInfo,Mipmapped mipmapped)33 YUVABackendTextureInfo::YUVABackendTextureInfo(const Recorder* recorder,
34 const SkYUVAInfo& yuvaInfo,
35 SkSpan<const TextureInfo> textureInfo,
36 Mipmapped mipmapped)
37 : fYUVAInfo(yuvaInfo)
38 , fMipmapped(mipmapped) {
39 int numPlanes = yuvaInfo.numPlanes();
40 if (!yuvaInfo.isValid() ||
41 numPlanes == 0 ||
42 (size_t)numPlanes > textureInfo.size()) {
43 *this = {};
44 SkASSERT(!this->isValid());
45 return;
46 }
47 for (int i = 0; i < numPlanes; ++i) {
48 int numRequiredChannels = yuvaInfo.numChannelsInPlane(i);
49 SkASSERT(numRequiredChannels > 0);
50 fPlaneChannelMasks[i] = recorder->priv().caps()->channelMask(textureInfo[i]);
51 if (!textureInfo[i].isValid() ||
52 textureInfo[i].backend() != textureInfo[0].backend() ||
53 num_channels(fPlaneChannelMasks[i]) < numRequiredChannels) {
54 *this = {};
55 SkASSERT(!this->isValid());
56 return;
57 }
58 fPlaneTextureInfos[i] = textureInfo[i];
59 }
60 SkASSERT(this->isValid());
61 }
62
operator ==(const YUVABackendTextureInfo & that) const63 bool YUVABackendTextureInfo::operator==(const YUVABackendTextureInfo& that) const {
64 if (fYUVAInfo != that.fYUVAInfo || fMipmapped != that.fMipmapped) {
65 return false;
66 }
67 return fPlaneTextureInfos == that.fPlaneTextureInfos;
68 }
69
toYUVALocations() const70 SkYUVAInfo::YUVALocations YUVABackendTextureInfo::toYUVALocations() const {
71 auto result = fYUVAInfo.toYUVALocations(fPlaneChannelMasks.data());
72 SkDEBUGCODE(int numPlanes;)
73 SkASSERT(SkYUVAInfo::YUVALocation::AreValidLocations(result, &numPlanes));
74 SkASSERT(numPlanes == this->numPlanes());
75 return result;
76 }
77
78 //////////////////////////////////////////////////////////////////////////////
79
YUVABackendTextures(const Recorder * recorder,const SkYUVAInfo & yuvaInfo,SkSpan<const BackendTexture> textures)80 YUVABackendTextures::YUVABackendTextures(const Recorder* recorder,
81 const SkYUVAInfo& yuvaInfo,
82 SkSpan<const BackendTexture> textures)
83 : fYUVAInfo(yuvaInfo) {
84 if (!yuvaInfo.isValid()) {
85 SkASSERT(!this->isValid());
86 return;
87 }
88 SkISize planeDimensions[kMaxPlanes];
89 int numPlanes = yuvaInfo.planeDimensions(planeDimensions);
90 if (numPlanes == 0 || (size_t)numPlanes > textures.size()) {
91 fYUVAInfo = {};
92 SkASSERT(!this->isValid());
93 return;
94 }
95 for (int i = 0; i < numPlanes; ++i) {
96 int numRequiredChannels = yuvaInfo.numChannelsInPlane(i);
97 SkASSERT(numRequiredChannels > 0);
98 fPlaneChannelMasks[i] = recorder->priv().caps()->channelMask(textures[i].info());
99 if (!textures[i].isValid() ||
100 textures[i].dimensions() != planeDimensions[i] ||
101 textures[i].backend() != textures[0].backend() ||
102 num_channels(fPlaneChannelMasks[i]) < numRequiredChannels) {
103 SkASSERT(!this->isValid());
104 return;
105 }
106 fPlaneTextures[i] = textures[i];
107 }
108 SkASSERT(this->isValid());
109 }
110
toYUVALocations() const111 SkYUVAInfo::YUVALocations YUVABackendTextures::toYUVALocations() const {
112 auto result = fYUVAInfo.toYUVALocations(fPlaneChannelMasks.data());
113 SkDEBUGCODE(int numPlanes;)
114 SkASSERT(SkYUVAInfo::YUVALocation::AreValidLocations(result, &numPlanes));
115 SkASSERT(numPlanes == this->numPlanes());
116 return result;
117 }
118
119 } // End of namespace skgpu::graphite
120