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