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