xref: /aosp_15_r20/external/skia/src/gpu/graphite/YUVABackendTextures.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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