xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrYUVABackendTextures.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2020 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/ganesh/GrYUVABackendTextures.h"
9 
10 #include "include/core/SkColor.h"
11 #include "include/core/SkSize.h"
12 #include "include/private/base/SkDebug.h"
13 #include "src/core/SkYUVAInfoLocation.h"
14 
15 #include <algorithm>
16 #include <cstdint>
17 
num_channels(const GrBackendFormat & format)18 static int num_channels(const GrBackendFormat& format) {
19     switch (format.channelMask()) {
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 }
30 
GrYUVABackendTextureInfo(const SkYUVAInfo & yuvaInfo,const GrBackendFormat formats[kMaxPlanes],skgpu::Mipmapped mipmapped,GrSurfaceOrigin origin)31 GrYUVABackendTextureInfo::GrYUVABackendTextureInfo(const SkYUVAInfo& yuvaInfo,
32                                                    const GrBackendFormat formats[kMaxPlanes],
33                                                    skgpu::Mipmapped mipmapped,
34                                                    GrSurfaceOrigin origin)
35         : fYUVAInfo(yuvaInfo), fMipmapped(mipmapped), fTextureOrigin(origin) {
36     if (!yuvaInfo.isValid()) {
37         *this = {};
38         SkASSERT(!this->isValid());
39         return;
40     }
41     int n = yuvaInfo.numPlanes();
42     for (size_t i = 0; i < static_cast<size_t>(n); ++i) {
43         if (!formats[i].isValid() || formats[i].backend() != formats[0].backend()) {
44             *this = {};
45             SkASSERT(!this->isValid());
46             return;
47         }
48         int numRequiredChannels = yuvaInfo.numChannelsInPlane(i);
49         SkASSERT(numRequiredChannels > 0);
50         int numActualChannels = num_channels(formats[i]);
51         if (numActualChannels < numRequiredChannels) {
52             *this = {};
53             SkASSERT(!this->isValid());
54             return;
55         }
56         fPlaneFormats[i] = formats[i];
57     }
58     SkASSERT(this->isValid());
59 }
60 
operator ==(const GrYUVABackendTextureInfo & that) const61 bool GrYUVABackendTextureInfo::operator==(const GrYUVABackendTextureInfo& that) const {
62     if (fYUVAInfo != that.fYUVAInfo ||
63         fMipmapped != that.fMipmapped ||
64         fTextureOrigin != that.fTextureOrigin) {
65         return false;
66     }
67     int n = fYUVAInfo.numPlanes();
68     return std::equal(fPlaneFormats, fPlaneFormats + n, that.fPlaneFormats);
69 }
70 
toYUVALocations() const71 SkYUVAInfo::YUVALocations GrYUVABackendTextureInfo::toYUVALocations() const {
72     uint32_t channelFlags[] = {fPlaneFormats[0].channelMask(),
73                                fPlaneFormats[1].channelMask(),
74                                fPlaneFormats[2].channelMask(),
75                                fPlaneFormats[3].channelMask()};
76     auto result = fYUVAInfo.toYUVALocations(channelFlags);
77     SkDEBUGCODE(int numPlanes;)
78     SkASSERT(SkYUVAInfo::YUVALocation::AreValidLocations(result, &numPlanes));
79     SkASSERT(numPlanes == this->numPlanes());
80     return result;
81 }
82 
83 //////////////////////////////////////////////////////////////////////////////
84 
GrYUVABackendTextures(const SkYUVAInfo & yuvaInfo,const GrBackendTexture textures[SkYUVAInfo::kMaxPlanes],GrSurfaceOrigin textureOrigin)85 GrYUVABackendTextures::GrYUVABackendTextures(
86         const SkYUVAInfo& yuvaInfo,
87         const GrBackendTexture textures[SkYUVAInfo::kMaxPlanes],
88         GrSurfaceOrigin textureOrigin)
89         : fYUVAInfo(yuvaInfo), fTextureOrigin(textureOrigin) {
90     if (!fYUVAInfo.isValid()) {
91         return;
92     }
93     SkISize planeDimensions[SkYUVAInfo::kMaxPlanes];
94     int numPlanes = yuvaInfo.planeDimensions(planeDimensions);
95     for (int i = 0; i < numPlanes; ++i) {
96         int numRequiredChannels = fYUVAInfo.numChannelsInPlane(i);
97         if (!textures[i].isValid() ||
98             textures[i].dimensions() != planeDimensions[i] ||
99             textures[i].backend() != textures[0].backend() ||
100             num_channels(textures[i].getBackendFormat()) < numRequiredChannels) {
101             *this = {};
102             return;
103         }
104         fTextures[i] = textures[i];
105     }
106 }
107 
toYUVALocations() const108 SkYUVAInfo::YUVALocations GrYUVABackendTextures::toYUVALocations() const {
109     uint32_t channelFlags[] = {fTextures[0].getBackendFormat().channelMask(),
110                                fTextures[1].getBackendFormat().channelMask(),
111                                fTextures[2].getBackendFormat().channelMask(),
112                                fTextures[3].getBackendFormat().channelMask()};
113     auto result = fYUVAInfo.toYUVALocations(channelFlags);
114     SkDEBUGCODE(int numPlanes;)
115     SkASSERT(SkYUVAInfo::YUVALocation::AreValidLocations(result, &numPlanes));
116     SkASSERT(numPlanes == this->numPlanes());
117     return result;
118 }
119