xref: /aosp_15_r20/external/skia/src/gpu/ganesh/GrResourceProvider.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2015 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrResourceProvider.h"
9*c8dee2aaSAndroid Build Coastguard Worker 
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkAlphaType.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkData.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/GpuTypes.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrBackendSurface.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrTypes.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SingleOwner.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTemplates.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkMathPriv.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkMipmap.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/BufferWriter.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ResourceKey.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/SkBackingFit.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrAttachment.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrCaps.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDataUtils.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGpu.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGpuBuffer.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrGpuResourcePriv.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrImageInfo.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrPixmap.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrRenderTarget.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrResourceCache.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSemaphore.h"
36*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurface.h"
37*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrTexture.h"
38*c8dee2aaSAndroid Build Coastguard Worker 
39*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
40*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
41*c8dee2aaSAndroid Build Coastguard Worker 
42*c8dee2aaSAndroid Build Coastguard Worker struct SkImageInfo;
43*c8dee2aaSAndroid Build Coastguard Worker 
44*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
45*c8dee2aaSAndroid Build Coastguard Worker 
46*c8dee2aaSAndroid Build Coastguard Worker #define ASSERT_SINGLE_OWNER SKGPU_ASSERT_SINGLE_OWNER(fSingleOwner)
47*c8dee2aaSAndroid Build Coastguard Worker 
GrResourceProvider(GrGpu * gpu,GrResourceCache * cache,skgpu::SingleOwner * owner)48*c8dee2aaSAndroid Build Coastguard Worker GrResourceProvider::GrResourceProvider(GrGpu* gpu,
49*c8dee2aaSAndroid Build Coastguard Worker                                        GrResourceCache* cache,
50*c8dee2aaSAndroid Build Coastguard Worker                                        skgpu::SingleOwner* owner)
51*c8dee2aaSAndroid Build Coastguard Worker         : fCache(cache)
52*c8dee2aaSAndroid Build Coastguard Worker         , fGpu(gpu)
53*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
54*c8dee2aaSAndroid Build Coastguard Worker         , fSingleOwner(owner)
55*c8dee2aaSAndroid Build Coastguard Worker #endif
56*c8dee2aaSAndroid Build Coastguard Worker {
57*c8dee2aaSAndroid Build Coastguard Worker     fCaps = sk_ref_sp(fGpu->caps());
58*c8dee2aaSAndroid Build Coastguard Worker }
59*c8dee2aaSAndroid Build Coastguard Worker 
createTexture(SkISize dimensions,const GrBackendFormat & format,GrTextureType textureType,GrColorType colorType,GrRenderable renderable,int renderTargetSampleCnt,skgpu::Budgeted budgeted,skgpu::Mipmapped mipmapped,GrProtected isProtected,const GrMipLevel texels[],std::string_view label)60*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrResourceProvider::createTexture(SkISize dimensions,
61*c8dee2aaSAndroid Build Coastguard Worker                                                    const GrBackendFormat& format,
62*c8dee2aaSAndroid Build Coastguard Worker                                                    GrTextureType textureType,
63*c8dee2aaSAndroid Build Coastguard Worker                                                    GrColorType colorType,
64*c8dee2aaSAndroid Build Coastguard Worker                                                    GrRenderable renderable,
65*c8dee2aaSAndroid Build Coastguard Worker                                                    int renderTargetSampleCnt,
66*c8dee2aaSAndroid Build Coastguard Worker                                                    skgpu::Budgeted budgeted,
67*c8dee2aaSAndroid Build Coastguard Worker                                                    skgpu::Mipmapped mipmapped,
68*c8dee2aaSAndroid Build Coastguard Worker                                                    GrProtected isProtected,
69*c8dee2aaSAndroid Build Coastguard Worker                                                    const GrMipLevel texels[],
70*c8dee2aaSAndroid Build Coastguard Worker                                                    std::string_view label) {
71*c8dee2aaSAndroid Build Coastguard Worker     ASSERT_SINGLE_OWNER
72*c8dee2aaSAndroid Build Coastguard Worker 
73*c8dee2aaSAndroid Build Coastguard Worker     if (this->isAbandoned()) {
74*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
75*c8dee2aaSAndroid Build Coastguard Worker     }
76*c8dee2aaSAndroid Build Coastguard Worker 
77*c8dee2aaSAndroid Build Coastguard Worker     int numMipLevels = 1;
78*c8dee2aaSAndroid Build Coastguard Worker     if (mipmapped == skgpu::Mipmapped::kYes) {
79*c8dee2aaSAndroid Build Coastguard Worker         numMipLevels = SkMipmap::ComputeLevelCount(dimensions.fWidth, dimensions.fHeight) + 1;
80*c8dee2aaSAndroid Build Coastguard Worker     }
81*c8dee2aaSAndroid Build Coastguard Worker 
82*c8dee2aaSAndroid Build Coastguard Worker     if (!fCaps->validateSurfaceParams(dimensions,
83*c8dee2aaSAndroid Build Coastguard Worker                                       format,
84*c8dee2aaSAndroid Build Coastguard Worker                                       renderable,
85*c8dee2aaSAndroid Build Coastguard Worker                                       renderTargetSampleCnt,
86*c8dee2aaSAndroid Build Coastguard Worker                                       mipmapped,
87*c8dee2aaSAndroid Build Coastguard Worker                                       textureType)) {
88*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
89*c8dee2aaSAndroid Build Coastguard Worker     }
90*c8dee2aaSAndroid Build Coastguard Worker     // Current rule is that you can provide no level data, just the base, or all the levels.
91*c8dee2aaSAndroid Build Coastguard Worker     bool hasPixels = texels[0].fPixels;
92*c8dee2aaSAndroid Build Coastguard Worker     auto scratch = this->getExactScratch(dimensions,
93*c8dee2aaSAndroid Build Coastguard Worker                                          format,
94*c8dee2aaSAndroid Build Coastguard Worker                                          textureType,
95*c8dee2aaSAndroid Build Coastguard Worker                                          renderable,
96*c8dee2aaSAndroid Build Coastguard Worker                                          renderTargetSampleCnt,
97*c8dee2aaSAndroid Build Coastguard Worker                                          budgeted,
98*c8dee2aaSAndroid Build Coastguard Worker                                          mipmapped,
99*c8dee2aaSAndroid Build Coastguard Worker                                          isProtected,
100*c8dee2aaSAndroid Build Coastguard Worker                                          label);
101*c8dee2aaSAndroid Build Coastguard Worker     if (scratch) {
102*c8dee2aaSAndroid Build Coastguard Worker         if (!hasPixels) {
103*c8dee2aaSAndroid Build Coastguard Worker             return scratch;
104*c8dee2aaSAndroid Build Coastguard Worker         }
105*c8dee2aaSAndroid Build Coastguard Worker         return this->writePixels(std::move(scratch), colorType, dimensions, texels, numMipLevels);
106*c8dee2aaSAndroid Build Coastguard Worker     }
107*c8dee2aaSAndroid Build Coastguard Worker     AutoSTArray<14, GrMipLevel> tmpTexels;
108*c8dee2aaSAndroid Build Coastguard Worker     AutoSTArray<14, std::unique_ptr<char[]>> tmpDatas;
109*c8dee2aaSAndroid Build Coastguard Worker     GrColorType tempColorType = GrColorType::kUnknown;
110*c8dee2aaSAndroid Build Coastguard Worker     if (hasPixels) {
111*c8dee2aaSAndroid Build Coastguard Worker         tempColorType = this->prepareLevels(format, colorType, dimensions, texels, numMipLevels,
112*c8dee2aaSAndroid Build Coastguard Worker                                             &tmpTexels, &tmpDatas);
113*c8dee2aaSAndroid Build Coastguard Worker         if (tempColorType == GrColorType::kUnknown) {
114*c8dee2aaSAndroid Build Coastguard Worker             return nullptr;
115*c8dee2aaSAndroid Build Coastguard Worker         }
116*c8dee2aaSAndroid Build Coastguard Worker     }
117*c8dee2aaSAndroid Build Coastguard Worker     return fGpu->createTexture(dimensions,
118*c8dee2aaSAndroid Build Coastguard Worker                                format,
119*c8dee2aaSAndroid Build Coastguard Worker                                textureType,
120*c8dee2aaSAndroid Build Coastguard Worker                                renderable,
121*c8dee2aaSAndroid Build Coastguard Worker                                renderTargetSampleCnt,
122*c8dee2aaSAndroid Build Coastguard Worker                                budgeted,
123*c8dee2aaSAndroid Build Coastguard Worker                                isProtected,
124*c8dee2aaSAndroid Build Coastguard Worker                                colorType,
125*c8dee2aaSAndroid Build Coastguard Worker                                tempColorType,
126*c8dee2aaSAndroid Build Coastguard Worker                                tmpTexels.get(),
127*c8dee2aaSAndroid Build Coastguard Worker                                numMipLevels,
128*c8dee2aaSAndroid Build Coastguard Worker                                label);
129*c8dee2aaSAndroid Build Coastguard Worker }
130*c8dee2aaSAndroid Build Coastguard Worker 
getExactScratch(SkISize dimensions,const GrBackendFormat & format,GrTextureType textureType,GrRenderable renderable,int renderTargetSampleCnt,skgpu::Budgeted budgeted,skgpu::Mipmapped mipmapped,GrProtected isProtected,std::string_view label)131*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrResourceProvider::getExactScratch(SkISize dimensions,
132*c8dee2aaSAndroid Build Coastguard Worker                                                      const GrBackendFormat& format,
133*c8dee2aaSAndroid Build Coastguard Worker                                                      GrTextureType textureType,
134*c8dee2aaSAndroid Build Coastguard Worker                                                      GrRenderable renderable,
135*c8dee2aaSAndroid Build Coastguard Worker                                                      int renderTargetSampleCnt,
136*c8dee2aaSAndroid Build Coastguard Worker                                                      skgpu::Budgeted budgeted,
137*c8dee2aaSAndroid Build Coastguard Worker                                                      skgpu::Mipmapped mipmapped,
138*c8dee2aaSAndroid Build Coastguard Worker                                                      GrProtected isProtected,
139*c8dee2aaSAndroid Build Coastguard Worker                                                      std::string_view label) {
140*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<GrTexture> tex(this->findAndRefScratchTexture(dimensions,
141*c8dee2aaSAndroid Build Coastguard Worker                                                         format,
142*c8dee2aaSAndroid Build Coastguard Worker                                                         textureType,
143*c8dee2aaSAndroid Build Coastguard Worker                                                         renderable,
144*c8dee2aaSAndroid Build Coastguard Worker                                                         renderTargetSampleCnt,
145*c8dee2aaSAndroid Build Coastguard Worker                                                         mipmapped,
146*c8dee2aaSAndroid Build Coastguard Worker                                                         isProtected,
147*c8dee2aaSAndroid Build Coastguard Worker                                                         label));
148*c8dee2aaSAndroid Build Coastguard Worker     if (tex && skgpu::Budgeted::kNo == budgeted) {
149*c8dee2aaSAndroid Build Coastguard Worker         tex->resourcePriv().makeUnbudgeted();
150*c8dee2aaSAndroid Build Coastguard Worker     }
151*c8dee2aaSAndroid Build Coastguard Worker 
152*c8dee2aaSAndroid Build Coastguard Worker     return tex;
153*c8dee2aaSAndroid Build Coastguard Worker }
154*c8dee2aaSAndroid Build Coastguard Worker 
createTexture(SkISize dimensions,const GrBackendFormat & format,GrTextureType textureType,GrColorType colorType,GrRenderable renderable,int renderTargetSampleCnt,skgpu::Budgeted budgeted,SkBackingFit fit,GrProtected isProtected,const GrMipLevel & mipLevel,std::string_view label)155*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrResourceProvider::createTexture(SkISize dimensions,
156*c8dee2aaSAndroid Build Coastguard Worker                                                    const GrBackendFormat& format,
157*c8dee2aaSAndroid Build Coastguard Worker                                                    GrTextureType textureType,
158*c8dee2aaSAndroid Build Coastguard Worker                                                    GrColorType colorType,
159*c8dee2aaSAndroid Build Coastguard Worker                                                    GrRenderable renderable,
160*c8dee2aaSAndroid Build Coastguard Worker                                                    int renderTargetSampleCnt,
161*c8dee2aaSAndroid Build Coastguard Worker                                                    skgpu::Budgeted budgeted,
162*c8dee2aaSAndroid Build Coastguard Worker                                                    SkBackingFit fit,
163*c8dee2aaSAndroid Build Coastguard Worker                                                    GrProtected isProtected,
164*c8dee2aaSAndroid Build Coastguard Worker                                                    const GrMipLevel& mipLevel,
165*c8dee2aaSAndroid Build Coastguard Worker                                                    std::string_view label) {
166*c8dee2aaSAndroid Build Coastguard Worker     ASSERT_SINGLE_OWNER
167*c8dee2aaSAndroid Build Coastguard Worker 
168*c8dee2aaSAndroid Build Coastguard Worker     if (!mipLevel.fPixels) {
169*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
170*c8dee2aaSAndroid Build Coastguard Worker     }
171*c8dee2aaSAndroid Build Coastguard Worker 
172*c8dee2aaSAndroid Build Coastguard Worker     if (SkBackingFit::kApprox == fit) {
173*c8dee2aaSAndroid Build Coastguard Worker         if (this->isAbandoned()) {
174*c8dee2aaSAndroid Build Coastguard Worker             return nullptr;
175*c8dee2aaSAndroid Build Coastguard Worker         }
176*c8dee2aaSAndroid Build Coastguard Worker         if (!fCaps->validateSurfaceParams(dimensions,
177*c8dee2aaSAndroid Build Coastguard Worker                                           format,
178*c8dee2aaSAndroid Build Coastguard Worker                                           renderable,
179*c8dee2aaSAndroid Build Coastguard Worker                                           renderTargetSampleCnt,
180*c8dee2aaSAndroid Build Coastguard Worker                                           skgpu::Mipmapped::kNo,
181*c8dee2aaSAndroid Build Coastguard Worker                                           textureType)) {
182*c8dee2aaSAndroid Build Coastguard Worker             return nullptr;
183*c8dee2aaSAndroid Build Coastguard Worker         }
184*c8dee2aaSAndroid Build Coastguard Worker 
185*c8dee2aaSAndroid Build Coastguard Worker         auto tex = this->createApproxTexture(dimensions,
186*c8dee2aaSAndroid Build Coastguard Worker                                              format,
187*c8dee2aaSAndroid Build Coastguard Worker                                              textureType,
188*c8dee2aaSAndroid Build Coastguard Worker                                              renderable,
189*c8dee2aaSAndroid Build Coastguard Worker                                              renderTargetSampleCnt,
190*c8dee2aaSAndroid Build Coastguard Worker                                              isProtected,
191*c8dee2aaSAndroid Build Coastguard Worker                                              label);
192*c8dee2aaSAndroid Build Coastguard Worker         if (!tex) {
193*c8dee2aaSAndroid Build Coastguard Worker             return nullptr;
194*c8dee2aaSAndroid Build Coastguard Worker         }
195*c8dee2aaSAndroid Build Coastguard Worker         return this->writePixels(std::move(tex), colorType, dimensions, &mipLevel, 1);
196*c8dee2aaSAndroid Build Coastguard Worker     } else {
197*c8dee2aaSAndroid Build Coastguard Worker         return this->createTexture(dimensions,
198*c8dee2aaSAndroid Build Coastguard Worker                                    format,
199*c8dee2aaSAndroid Build Coastguard Worker                                    textureType,
200*c8dee2aaSAndroid Build Coastguard Worker                                    colorType,
201*c8dee2aaSAndroid Build Coastguard Worker                                    renderable,
202*c8dee2aaSAndroid Build Coastguard Worker                                    renderTargetSampleCnt,
203*c8dee2aaSAndroid Build Coastguard Worker                                    budgeted,
204*c8dee2aaSAndroid Build Coastguard Worker                                    skgpu::Mipmapped::kNo,
205*c8dee2aaSAndroid Build Coastguard Worker                                    isProtected,
206*c8dee2aaSAndroid Build Coastguard Worker                                    &mipLevel,
207*c8dee2aaSAndroid Build Coastguard Worker                                    label);
208*c8dee2aaSAndroid Build Coastguard Worker     }
209*c8dee2aaSAndroid Build Coastguard Worker }
210*c8dee2aaSAndroid Build Coastguard Worker 
createCompressedTexture(SkISize dimensions,const GrBackendFormat & format,skgpu::Budgeted budgeted,skgpu::Mipmapped mipmapped,GrProtected isProtected,SkData * data,std::string_view label)211*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrResourceProvider::createCompressedTexture(SkISize dimensions,
212*c8dee2aaSAndroid Build Coastguard Worker                                                              const GrBackendFormat& format,
213*c8dee2aaSAndroid Build Coastguard Worker                                                              skgpu::Budgeted budgeted,
214*c8dee2aaSAndroid Build Coastguard Worker                                                              skgpu::Mipmapped mipmapped,
215*c8dee2aaSAndroid Build Coastguard Worker                                                              GrProtected isProtected,
216*c8dee2aaSAndroid Build Coastguard Worker                                                              SkData* data,
217*c8dee2aaSAndroid Build Coastguard Worker                                                              std::string_view label) {
218*c8dee2aaSAndroid Build Coastguard Worker     ASSERT_SINGLE_OWNER
219*c8dee2aaSAndroid Build Coastguard Worker     if (this->isAbandoned()) {
220*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
221*c8dee2aaSAndroid Build Coastguard Worker     }
222*c8dee2aaSAndroid Build Coastguard Worker     return fGpu->createCompressedTexture(dimensions,
223*c8dee2aaSAndroid Build Coastguard Worker                                          format,
224*c8dee2aaSAndroid Build Coastguard Worker                                          budgeted,
225*c8dee2aaSAndroid Build Coastguard Worker                                          mipmapped,
226*c8dee2aaSAndroid Build Coastguard Worker                                          isProtected,
227*c8dee2aaSAndroid Build Coastguard Worker                                          data->data(),
228*c8dee2aaSAndroid Build Coastguard Worker                                          data->size());
229*c8dee2aaSAndroid Build Coastguard Worker }
230*c8dee2aaSAndroid Build Coastguard Worker 
createTexture(SkISize dimensions,const GrBackendFormat & format,GrTextureType textureType,GrRenderable renderable,int renderTargetSampleCnt,skgpu::Mipmapped mipmapped,skgpu::Budgeted budgeted,GrProtected isProtected,std::string_view label)231*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrResourceProvider::createTexture(SkISize dimensions,
232*c8dee2aaSAndroid Build Coastguard Worker                                                    const GrBackendFormat& format,
233*c8dee2aaSAndroid Build Coastguard Worker                                                    GrTextureType textureType,
234*c8dee2aaSAndroid Build Coastguard Worker                                                    GrRenderable renderable,
235*c8dee2aaSAndroid Build Coastguard Worker                                                    int renderTargetSampleCnt,
236*c8dee2aaSAndroid Build Coastguard Worker                                                    skgpu::Mipmapped mipmapped,
237*c8dee2aaSAndroid Build Coastguard Worker                                                    skgpu::Budgeted budgeted,
238*c8dee2aaSAndroid Build Coastguard Worker                                                    GrProtected isProtected,
239*c8dee2aaSAndroid Build Coastguard Worker                                                    std::string_view label) {
240*c8dee2aaSAndroid Build Coastguard Worker     ASSERT_SINGLE_OWNER
241*c8dee2aaSAndroid Build Coastguard Worker     if (this->isAbandoned()) {
242*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
243*c8dee2aaSAndroid Build Coastguard Worker     }
244*c8dee2aaSAndroid Build Coastguard Worker 
245*c8dee2aaSAndroid Build Coastguard Worker     if (!fCaps->validateSurfaceParams(dimensions, format, renderable, renderTargetSampleCnt,
246*c8dee2aaSAndroid Build Coastguard Worker                                       mipmapped, textureType)) {
247*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
248*c8dee2aaSAndroid Build Coastguard Worker     }
249*c8dee2aaSAndroid Build Coastguard Worker 
250*c8dee2aaSAndroid Build Coastguard Worker     // Currently we don't recycle compressed textures as scratch. Additionally all compressed
251*c8dee2aaSAndroid Build Coastguard Worker     // textures should be created through the createCompressedTexture function.
252*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!this->caps()->isFormatCompressed(format));
253*c8dee2aaSAndroid Build Coastguard Worker 
254*c8dee2aaSAndroid Build Coastguard Worker     // TODO: Support skgpu::Mipmapped::kYes in scratch texture lookup here.
255*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<GrTexture> tex =
256*c8dee2aaSAndroid Build Coastguard Worker             this->getExactScratch(dimensions,
257*c8dee2aaSAndroid Build Coastguard Worker                                   format,
258*c8dee2aaSAndroid Build Coastguard Worker                                   textureType,
259*c8dee2aaSAndroid Build Coastguard Worker                                   renderable,
260*c8dee2aaSAndroid Build Coastguard Worker                                   renderTargetSampleCnt,
261*c8dee2aaSAndroid Build Coastguard Worker                                   budgeted,
262*c8dee2aaSAndroid Build Coastguard Worker                                   mipmapped,
263*c8dee2aaSAndroid Build Coastguard Worker                                   isProtected,
264*c8dee2aaSAndroid Build Coastguard Worker                                   label);
265*c8dee2aaSAndroid Build Coastguard Worker     if (tex) {
266*c8dee2aaSAndroid Build Coastguard Worker         return tex;
267*c8dee2aaSAndroid Build Coastguard Worker     }
268*c8dee2aaSAndroid Build Coastguard Worker 
269*c8dee2aaSAndroid Build Coastguard Worker     return fGpu->createTexture(dimensions,
270*c8dee2aaSAndroid Build Coastguard Worker                                format,
271*c8dee2aaSAndroid Build Coastguard Worker                                textureType,
272*c8dee2aaSAndroid Build Coastguard Worker                                renderable,
273*c8dee2aaSAndroid Build Coastguard Worker                                renderTargetSampleCnt,
274*c8dee2aaSAndroid Build Coastguard Worker                                mipmapped,
275*c8dee2aaSAndroid Build Coastguard Worker                                budgeted,
276*c8dee2aaSAndroid Build Coastguard Worker                                isProtected,
277*c8dee2aaSAndroid Build Coastguard Worker                                label);
278*c8dee2aaSAndroid Build Coastguard Worker }
279*c8dee2aaSAndroid Build Coastguard Worker 
createApproxTexture(SkISize dimensions,const GrBackendFormat & format,GrTextureType textureType,GrRenderable renderable,int renderTargetSampleCnt,GrProtected isProtected,std::string_view label)280*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrResourceProvider::createApproxTexture(SkISize dimensions,
281*c8dee2aaSAndroid Build Coastguard Worker                                                          const GrBackendFormat& format,
282*c8dee2aaSAndroid Build Coastguard Worker                                                          GrTextureType textureType,
283*c8dee2aaSAndroid Build Coastguard Worker                                                          GrRenderable renderable,
284*c8dee2aaSAndroid Build Coastguard Worker                                                          int renderTargetSampleCnt,
285*c8dee2aaSAndroid Build Coastguard Worker                                                          GrProtected isProtected,
286*c8dee2aaSAndroid Build Coastguard Worker                                                          std::string_view label) {
287*c8dee2aaSAndroid Build Coastguard Worker     ASSERT_SINGLE_OWNER
288*c8dee2aaSAndroid Build Coastguard Worker 
289*c8dee2aaSAndroid Build Coastguard Worker     if (this->isAbandoned()) {
290*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
291*c8dee2aaSAndroid Build Coastguard Worker     }
292*c8dee2aaSAndroid Build Coastguard Worker 
293*c8dee2aaSAndroid Build Coastguard Worker     // Currently we don't recycle compressed textures as scratch. Additionally all compressed
294*c8dee2aaSAndroid Build Coastguard Worker     // textures should be created through the createCompressedTexture function.
295*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!this->caps()->isFormatCompressed(format));
296*c8dee2aaSAndroid Build Coastguard Worker 
297*c8dee2aaSAndroid Build Coastguard Worker     if (!fCaps->validateSurfaceParams(dimensions,
298*c8dee2aaSAndroid Build Coastguard Worker                                       format,
299*c8dee2aaSAndroid Build Coastguard Worker                                       renderable,
300*c8dee2aaSAndroid Build Coastguard Worker                                       renderTargetSampleCnt,
301*c8dee2aaSAndroid Build Coastguard Worker                                       skgpu::Mipmapped::kNo,
302*c8dee2aaSAndroid Build Coastguard Worker                                       textureType)) {
303*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
304*c8dee2aaSAndroid Build Coastguard Worker     }
305*c8dee2aaSAndroid Build Coastguard Worker 
306*c8dee2aaSAndroid Build Coastguard Worker     auto copyDimensions = skgpu::GetApproxSize(dimensions);
307*c8dee2aaSAndroid Build Coastguard Worker 
308*c8dee2aaSAndroid Build Coastguard Worker     if (auto tex = this->findAndRefScratchTexture(copyDimensions,
309*c8dee2aaSAndroid Build Coastguard Worker                                                   format,
310*c8dee2aaSAndroid Build Coastguard Worker                                                   textureType,
311*c8dee2aaSAndroid Build Coastguard Worker                                                   renderable,
312*c8dee2aaSAndroid Build Coastguard Worker                                                   renderTargetSampleCnt,
313*c8dee2aaSAndroid Build Coastguard Worker                                                   skgpu::Mipmapped::kNo,
314*c8dee2aaSAndroid Build Coastguard Worker                                                   isProtected,
315*c8dee2aaSAndroid Build Coastguard Worker                                                   label)) {
316*c8dee2aaSAndroid Build Coastguard Worker         return tex;
317*c8dee2aaSAndroid Build Coastguard Worker     }
318*c8dee2aaSAndroid Build Coastguard Worker 
319*c8dee2aaSAndroid Build Coastguard Worker     return fGpu->createTexture(copyDimensions,
320*c8dee2aaSAndroid Build Coastguard Worker                                format,
321*c8dee2aaSAndroid Build Coastguard Worker                                textureType,
322*c8dee2aaSAndroid Build Coastguard Worker                                renderable,
323*c8dee2aaSAndroid Build Coastguard Worker                                renderTargetSampleCnt,
324*c8dee2aaSAndroid Build Coastguard Worker                                skgpu::Mipmapped::kNo,
325*c8dee2aaSAndroid Build Coastguard Worker                                skgpu::Budgeted::kYes,
326*c8dee2aaSAndroid Build Coastguard Worker                                isProtected,
327*c8dee2aaSAndroid Build Coastguard Worker                                label);
328*c8dee2aaSAndroid Build Coastguard Worker }
329*c8dee2aaSAndroid Build Coastguard Worker 
findAndRefScratchTexture(const skgpu::ScratchKey & key,std::string_view label)330*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrResourceProvider::findAndRefScratchTexture(const skgpu::ScratchKey& key,
331*c8dee2aaSAndroid Build Coastguard Worker                                                               std::string_view label) {
332*c8dee2aaSAndroid Build Coastguard Worker     ASSERT_SINGLE_OWNER
333*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!this->isAbandoned());
334*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(key.isValid());
335*c8dee2aaSAndroid Build Coastguard Worker 
336*c8dee2aaSAndroid Build Coastguard Worker     if (GrGpuResource* resource = fCache->findAndRefScratchResource(key)) {
337*c8dee2aaSAndroid Build Coastguard Worker         fGpu->stats()->incNumScratchTexturesReused();
338*c8dee2aaSAndroid Build Coastguard Worker         GrSurface* surface = static_cast<GrSurface*>(resource);
339*c8dee2aaSAndroid Build Coastguard Worker         resource->setLabel(std::move(label));
340*c8dee2aaSAndroid Build Coastguard Worker         return sk_sp<GrTexture>(surface->asTexture());
341*c8dee2aaSAndroid Build Coastguard Worker     }
342*c8dee2aaSAndroid Build Coastguard Worker     return nullptr;
343*c8dee2aaSAndroid Build Coastguard Worker }
344*c8dee2aaSAndroid Build Coastguard Worker 
findAndRefScratchTexture(SkISize dimensions,const GrBackendFormat & format,GrTextureType textureType,GrRenderable renderable,int renderTargetSampleCnt,skgpu::Mipmapped mipmapped,GrProtected isProtected,std::string_view label)345*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrResourceProvider::findAndRefScratchTexture(SkISize dimensions,
346*c8dee2aaSAndroid Build Coastguard Worker                                                               const GrBackendFormat& format,
347*c8dee2aaSAndroid Build Coastguard Worker                                                               GrTextureType textureType,
348*c8dee2aaSAndroid Build Coastguard Worker                                                               GrRenderable renderable,
349*c8dee2aaSAndroid Build Coastguard Worker                                                               int renderTargetSampleCnt,
350*c8dee2aaSAndroid Build Coastguard Worker                                                               skgpu::Mipmapped mipmapped,
351*c8dee2aaSAndroid Build Coastguard Worker                                                               GrProtected isProtected,
352*c8dee2aaSAndroid Build Coastguard Worker                                                               std::string_view label) {
353*c8dee2aaSAndroid Build Coastguard Worker     ASSERT_SINGLE_OWNER
354*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!this->isAbandoned());
355*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!this->caps()->isFormatCompressed(format));
356*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fCaps->validateSurfaceParams(dimensions,
357*c8dee2aaSAndroid Build Coastguard Worker                                           format,
358*c8dee2aaSAndroid Build Coastguard Worker                                           renderable,
359*c8dee2aaSAndroid Build Coastguard Worker                                           renderTargetSampleCnt,
360*c8dee2aaSAndroid Build Coastguard Worker                                           skgpu::Mipmapped::kNo,
361*c8dee2aaSAndroid Build Coastguard Worker                                           textureType));
362*c8dee2aaSAndroid Build Coastguard Worker 
363*c8dee2aaSAndroid Build Coastguard Worker     // We could make initial clears work with scratch textures but it is a rare case so we just opt
364*c8dee2aaSAndroid Build Coastguard Worker     // to fall back to making a new texture.
365*c8dee2aaSAndroid Build Coastguard Worker     if (fGpu->caps()->reuseScratchTextures() || renderable == GrRenderable::kYes) {
366*c8dee2aaSAndroid Build Coastguard Worker         skgpu::ScratchKey key;
367*c8dee2aaSAndroid Build Coastguard Worker         GrTexture::ComputeScratchKey(*this->caps(), format, dimensions, renderable,
368*c8dee2aaSAndroid Build Coastguard Worker                                      renderTargetSampleCnt, mipmapped, isProtected, &key);
369*c8dee2aaSAndroid Build Coastguard Worker         return this->findAndRefScratchTexture(key, label);
370*c8dee2aaSAndroid Build Coastguard Worker     }
371*c8dee2aaSAndroid Build Coastguard Worker 
372*c8dee2aaSAndroid Build Coastguard Worker     return nullptr;
373*c8dee2aaSAndroid Build Coastguard Worker }
374*c8dee2aaSAndroid Build Coastguard Worker 
wrapBackendTexture(const GrBackendTexture & tex,GrWrapOwnership ownership,GrWrapCacheable cacheable,GrIOType ioType)375*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrResourceProvider::wrapBackendTexture(const GrBackendTexture& tex,
376*c8dee2aaSAndroid Build Coastguard Worker                                                         GrWrapOwnership ownership,
377*c8dee2aaSAndroid Build Coastguard Worker                                                         GrWrapCacheable cacheable,
378*c8dee2aaSAndroid Build Coastguard Worker                                                         GrIOType ioType) {
379*c8dee2aaSAndroid Build Coastguard Worker     ASSERT_SINGLE_OWNER
380*c8dee2aaSAndroid Build Coastguard Worker     if (this->isAbandoned()) {
381*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
382*c8dee2aaSAndroid Build Coastguard Worker     }
383*c8dee2aaSAndroid Build Coastguard Worker     return fGpu->wrapBackendTexture(tex, ownership, cacheable, ioType);
384*c8dee2aaSAndroid Build Coastguard Worker }
385*c8dee2aaSAndroid Build Coastguard Worker 
wrapCompressedBackendTexture(const GrBackendTexture & tex,GrWrapOwnership ownership,GrWrapCacheable cacheable)386*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrResourceProvider::wrapCompressedBackendTexture(const GrBackendTexture& tex,
387*c8dee2aaSAndroid Build Coastguard Worker                                                                   GrWrapOwnership ownership,
388*c8dee2aaSAndroid Build Coastguard Worker                                                                   GrWrapCacheable cacheable) {
389*c8dee2aaSAndroid Build Coastguard Worker     ASSERT_SINGLE_OWNER
390*c8dee2aaSAndroid Build Coastguard Worker     if (this->isAbandoned()) {
391*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
392*c8dee2aaSAndroid Build Coastguard Worker     }
393*c8dee2aaSAndroid Build Coastguard Worker 
394*c8dee2aaSAndroid Build Coastguard Worker     return fGpu->wrapCompressedBackendTexture(tex, ownership, cacheable);
395*c8dee2aaSAndroid Build Coastguard Worker }
396*c8dee2aaSAndroid Build Coastguard Worker 
397*c8dee2aaSAndroid Build Coastguard Worker 
wrapRenderableBackendTexture(const GrBackendTexture & tex,int sampleCnt,GrWrapOwnership ownership,GrWrapCacheable cacheable)398*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrResourceProvider::wrapRenderableBackendTexture(const GrBackendTexture& tex,
399*c8dee2aaSAndroid Build Coastguard Worker                                                                   int sampleCnt,
400*c8dee2aaSAndroid Build Coastguard Worker                                                                   GrWrapOwnership ownership,
401*c8dee2aaSAndroid Build Coastguard Worker                                                                   GrWrapCacheable cacheable) {
402*c8dee2aaSAndroid Build Coastguard Worker     ASSERT_SINGLE_OWNER
403*c8dee2aaSAndroid Build Coastguard Worker     if (this->isAbandoned()) {
404*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
405*c8dee2aaSAndroid Build Coastguard Worker     }
406*c8dee2aaSAndroid Build Coastguard Worker     return fGpu->wrapRenderableBackendTexture(tex, sampleCnt, ownership, cacheable);
407*c8dee2aaSAndroid Build Coastguard Worker }
408*c8dee2aaSAndroid Build Coastguard Worker 
wrapBackendRenderTarget(const GrBackendRenderTarget & backendRT)409*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrRenderTarget> GrResourceProvider::wrapBackendRenderTarget(
410*c8dee2aaSAndroid Build Coastguard Worker         const GrBackendRenderTarget& backendRT) {
411*c8dee2aaSAndroid Build Coastguard Worker     ASSERT_SINGLE_OWNER
412*c8dee2aaSAndroid Build Coastguard Worker     return this->isAbandoned() ? nullptr : fGpu->wrapBackendRenderTarget(backendRT);
413*c8dee2aaSAndroid Build Coastguard Worker }
414*c8dee2aaSAndroid Build Coastguard Worker 
wrapVulkanSecondaryCBAsRenderTarget(const SkImageInfo & imageInfo,const GrVkDrawableInfo & vkInfo)415*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrRenderTarget> GrResourceProvider::wrapVulkanSecondaryCBAsRenderTarget(
416*c8dee2aaSAndroid Build Coastguard Worker         const SkImageInfo& imageInfo, const GrVkDrawableInfo& vkInfo) {
417*c8dee2aaSAndroid Build Coastguard Worker     ASSERT_SINGLE_OWNER
418*c8dee2aaSAndroid Build Coastguard Worker     return this->isAbandoned() ? nullptr : fGpu->wrapVulkanSecondaryCBAsRenderTarget(imageInfo,
419*c8dee2aaSAndroid Build Coastguard Worker                                                                                      vkInfo);
420*c8dee2aaSAndroid Build Coastguard Worker 
421*c8dee2aaSAndroid Build Coastguard Worker }
422*c8dee2aaSAndroid Build Coastguard Worker 
assignUniqueKeyToResource(const skgpu::UniqueKey & key,GrGpuResource * resource)423*c8dee2aaSAndroid Build Coastguard Worker void GrResourceProvider::assignUniqueKeyToResource(const skgpu::UniqueKey& key,
424*c8dee2aaSAndroid Build Coastguard Worker                                                    GrGpuResource* resource) {
425*c8dee2aaSAndroid Build Coastguard Worker     ASSERT_SINGLE_OWNER
426*c8dee2aaSAndroid Build Coastguard Worker     if (this->isAbandoned() || !resource) {
427*c8dee2aaSAndroid Build Coastguard Worker         return;
428*c8dee2aaSAndroid Build Coastguard Worker     }
429*c8dee2aaSAndroid Build Coastguard Worker     resource->resourcePriv().setUniqueKey(key);
430*c8dee2aaSAndroid Build Coastguard Worker }
431*c8dee2aaSAndroid Build Coastguard Worker 
findResourceByUniqueKey(const skgpu::UniqueKey & key)432*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrGpuResource> GrResourceProvider::findResourceByUniqueKey(const skgpu::UniqueKey& key) {
433*c8dee2aaSAndroid Build Coastguard Worker     ASSERT_SINGLE_OWNER
434*c8dee2aaSAndroid Build Coastguard Worker     return this->isAbandoned() ? nullptr
435*c8dee2aaSAndroid Build Coastguard Worker                                : sk_sp<GrGpuResource>(fCache->findAndRefUniqueResource(key));
436*c8dee2aaSAndroid Build Coastguard Worker }
437*c8dee2aaSAndroid Build Coastguard Worker 
findOrMakeStaticBuffer(GrGpuBufferType intendedType,size_t size,const void * staticData,const skgpu::UniqueKey & key)438*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrGpuBuffer> GrResourceProvider::findOrMakeStaticBuffer(GrGpuBufferType intendedType,
439*c8dee2aaSAndroid Build Coastguard Worker                                                                     size_t size,
440*c8dee2aaSAndroid Build Coastguard Worker                                                                     const void* staticData,
441*c8dee2aaSAndroid Build Coastguard Worker                                                                     const skgpu::UniqueKey& key) {
442*c8dee2aaSAndroid Build Coastguard Worker     if (auto buffer = this->findByUniqueKey<GrGpuBuffer>(key)) {
443*c8dee2aaSAndroid Build Coastguard Worker         return buffer;
444*c8dee2aaSAndroid Build Coastguard Worker     }
445*c8dee2aaSAndroid Build Coastguard Worker 
446*c8dee2aaSAndroid Build Coastguard Worker     auto buffer = this->createBuffer(staticData, size, intendedType, kStatic_GrAccessPattern);
447*c8dee2aaSAndroid Build Coastguard Worker     if (!buffer) {
448*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
449*c8dee2aaSAndroid Build Coastguard Worker     }
450*c8dee2aaSAndroid Build Coastguard Worker 
451*c8dee2aaSAndroid Build Coastguard Worker     // We shouldn't bin and/or cache static buffers.
452*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(buffer->size() == size);
453*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!buffer->resourcePriv().getScratchKey().isValid());
454*c8dee2aaSAndroid Build Coastguard Worker 
455*c8dee2aaSAndroid Build Coastguard Worker     buffer->resourcePriv().setUniqueKey(key);
456*c8dee2aaSAndroid Build Coastguard Worker 
457*c8dee2aaSAndroid Build Coastguard Worker     return buffer;
458*c8dee2aaSAndroid Build Coastguard Worker }
459*c8dee2aaSAndroid Build Coastguard Worker 
findOrMakeStaticBuffer(GrGpuBufferType intendedType,size_t size,const skgpu::UniqueKey & uniqueKey,InitializeBufferFn initializeBufferFn)460*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrGpuBuffer> GrResourceProvider::findOrMakeStaticBuffer(
461*c8dee2aaSAndroid Build Coastguard Worker         GrGpuBufferType intendedType,
462*c8dee2aaSAndroid Build Coastguard Worker         size_t size,
463*c8dee2aaSAndroid Build Coastguard Worker         const skgpu::UniqueKey& uniqueKey,
464*c8dee2aaSAndroid Build Coastguard Worker         InitializeBufferFn initializeBufferFn) {
465*c8dee2aaSAndroid Build Coastguard Worker     if (auto buffer = this->findByUniqueKey<GrGpuBuffer>(uniqueKey)) {
466*c8dee2aaSAndroid Build Coastguard Worker         return buffer;
467*c8dee2aaSAndroid Build Coastguard Worker     }
468*c8dee2aaSAndroid Build Coastguard Worker 
469*c8dee2aaSAndroid Build Coastguard Worker     auto buffer = this->createBuffer(size,
470*c8dee2aaSAndroid Build Coastguard Worker                                      intendedType,
471*c8dee2aaSAndroid Build Coastguard Worker                                      kStatic_GrAccessPattern,
472*c8dee2aaSAndroid Build Coastguard Worker                                      ZeroInit::kNo);
473*c8dee2aaSAndroid Build Coastguard Worker     if (!buffer) {
474*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
475*c8dee2aaSAndroid Build Coastguard Worker     }
476*c8dee2aaSAndroid Build Coastguard Worker 
477*c8dee2aaSAndroid Build Coastguard Worker     // We shouldn't bin and/or cache static buffers.
478*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(buffer->size() == size);
479*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!buffer->resourcePriv().getScratchKey().isValid());
480*c8dee2aaSAndroid Build Coastguard Worker 
481*c8dee2aaSAndroid Build Coastguard Worker     buffer->resourcePriv().setUniqueKey(uniqueKey);
482*c8dee2aaSAndroid Build Coastguard Worker 
483*c8dee2aaSAndroid Build Coastguard Worker     // Map the buffer. Use a staging buffer on the heap if mapping isn't supported.
484*c8dee2aaSAndroid Build Coastguard Worker     skgpu::VertexWriter vertexWriter = {buffer->map(), size};
485*c8dee2aaSAndroid Build Coastguard Worker     AutoTMalloc<char> stagingBuffer;
486*c8dee2aaSAndroid Build Coastguard Worker     if (!vertexWriter) {
487*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(!buffer->isMapped());
488*c8dee2aaSAndroid Build Coastguard Worker         vertexWriter = {stagingBuffer.reset(size), size};
489*c8dee2aaSAndroid Build Coastguard Worker     }
490*c8dee2aaSAndroid Build Coastguard Worker 
491*c8dee2aaSAndroid Build Coastguard Worker     initializeBufferFn(std::move(vertexWriter), size);
492*c8dee2aaSAndroid Build Coastguard Worker 
493*c8dee2aaSAndroid Build Coastguard Worker     if (buffer->isMapped()) {
494*c8dee2aaSAndroid Build Coastguard Worker         buffer->unmap();
495*c8dee2aaSAndroid Build Coastguard Worker     } else {
496*c8dee2aaSAndroid Build Coastguard Worker         buffer->updateData(stagingBuffer, /*offset=*/0, size, /*preserve=*/false);
497*c8dee2aaSAndroid Build Coastguard Worker     }
498*c8dee2aaSAndroid Build Coastguard Worker 
499*c8dee2aaSAndroid Build Coastguard Worker     return buffer;
500*c8dee2aaSAndroid Build Coastguard Worker }
501*c8dee2aaSAndroid Build Coastguard Worker 
createPatternedIndexBuffer(const uint16_t * pattern,int patternSize,int reps,int vertCount,const skgpu::UniqueKey * key)502*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrGpuBuffer> GrResourceProvider::createPatternedIndexBuffer(
503*c8dee2aaSAndroid Build Coastguard Worker         const uint16_t* pattern,
504*c8dee2aaSAndroid Build Coastguard Worker         int patternSize,
505*c8dee2aaSAndroid Build Coastguard Worker         int reps,
506*c8dee2aaSAndroid Build Coastguard Worker         int vertCount,
507*c8dee2aaSAndroid Build Coastguard Worker         const skgpu::UniqueKey* key) {
508*c8dee2aaSAndroid Build Coastguard Worker     size_t bufferSize = patternSize * reps * sizeof(uint16_t);
509*c8dee2aaSAndroid Build Coastguard Worker 
510*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<GrGpuBuffer> buffer = this->createBuffer(bufferSize,
511*c8dee2aaSAndroid Build Coastguard Worker                                                    GrGpuBufferType::kIndex,
512*c8dee2aaSAndroid Build Coastguard Worker                                                    kStatic_GrAccessPattern,
513*c8dee2aaSAndroid Build Coastguard Worker                                                    ZeroInit::kNo);
514*c8dee2aaSAndroid Build Coastguard Worker     if (!buffer) {
515*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
516*c8dee2aaSAndroid Build Coastguard Worker     }
517*c8dee2aaSAndroid Build Coastguard Worker     uint16_t* data = (uint16_t*) buffer->map();
518*c8dee2aaSAndroid Build Coastguard Worker     AutoTArray<uint16_t> temp;
519*c8dee2aaSAndroid Build Coastguard Worker     if (!data) {
520*c8dee2aaSAndroid Build Coastguard Worker         temp.reset(reps * patternSize);
521*c8dee2aaSAndroid Build Coastguard Worker         data = temp.get();
522*c8dee2aaSAndroid Build Coastguard Worker     }
523*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < reps; ++i) {
524*c8dee2aaSAndroid Build Coastguard Worker         int baseIdx = i * patternSize;
525*c8dee2aaSAndroid Build Coastguard Worker         uint16_t baseVert = (uint16_t)(i * vertCount);
526*c8dee2aaSAndroid Build Coastguard Worker         for (int j = 0; j < patternSize; ++j) {
527*c8dee2aaSAndroid Build Coastguard Worker             data[baseIdx+j] = baseVert + pattern[j];
528*c8dee2aaSAndroid Build Coastguard Worker         }
529*c8dee2aaSAndroid Build Coastguard Worker     }
530*c8dee2aaSAndroid Build Coastguard Worker     if (temp.get()) {
531*c8dee2aaSAndroid Build Coastguard Worker         if (!buffer->updateData(data, /*offset=*/0, bufferSize, /*preserve=*/false)) {
532*c8dee2aaSAndroid Build Coastguard Worker             return nullptr;
533*c8dee2aaSAndroid Build Coastguard Worker         }
534*c8dee2aaSAndroid Build Coastguard Worker     } else {
535*c8dee2aaSAndroid Build Coastguard Worker         buffer->unmap();
536*c8dee2aaSAndroid Build Coastguard Worker     }
537*c8dee2aaSAndroid Build Coastguard Worker     if (key) {
538*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(key->isValid());
539*c8dee2aaSAndroid Build Coastguard Worker         this->assignUniqueKeyToResource(*key, buffer.get());
540*c8dee2aaSAndroid Build Coastguard Worker     }
541*c8dee2aaSAndroid Build Coastguard Worker     return buffer;
542*c8dee2aaSAndroid Build Coastguard Worker }
543*c8dee2aaSAndroid Build Coastguard Worker 
544*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////////////////////////
545*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kMaxNumNonAAQuads = 1 << 12;  // max possible: (1 << 14) - 1;
546*c8dee2aaSAndroid Build Coastguard Worker static const int kVertsPerNonAAQuad = 4;
547*c8dee2aaSAndroid Build Coastguard Worker static const int kIndicesPerNonAAQuad = 6;
548*c8dee2aaSAndroid Build Coastguard Worker 
createNonAAQuadIndexBuffer()549*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrGpuBuffer> GrResourceProvider::createNonAAQuadIndexBuffer() {
550*c8dee2aaSAndroid Build Coastguard Worker     static_assert(kVertsPerNonAAQuad * kMaxNumNonAAQuads <= 65535);  // indices fit in a uint16_t
551*c8dee2aaSAndroid Build Coastguard Worker 
552*c8dee2aaSAndroid Build Coastguard Worker     static const uint16_t kNonAAQuadIndexPattern[] = {
553*c8dee2aaSAndroid Build Coastguard Worker         0, 1, 2, 2, 1, 3
554*c8dee2aaSAndroid Build Coastguard Worker     };
555*c8dee2aaSAndroid Build Coastguard Worker 
556*c8dee2aaSAndroid Build Coastguard Worker     static_assert(std::size(kNonAAQuadIndexPattern) == kIndicesPerNonAAQuad);
557*c8dee2aaSAndroid Build Coastguard Worker 
558*c8dee2aaSAndroid Build Coastguard Worker     return this->createPatternedIndexBuffer(kNonAAQuadIndexPattern, kIndicesPerNonAAQuad,
559*c8dee2aaSAndroid Build Coastguard Worker                                             kMaxNumNonAAQuads, kVertsPerNonAAQuad, nullptr);
560*c8dee2aaSAndroid Build Coastguard Worker }
561*c8dee2aaSAndroid Build Coastguard Worker 
MaxNumNonAAQuads()562*c8dee2aaSAndroid Build Coastguard Worker int GrResourceProvider::MaxNumNonAAQuads() { return kMaxNumNonAAQuads; }
NumVertsPerNonAAQuad()563*c8dee2aaSAndroid Build Coastguard Worker int GrResourceProvider::NumVertsPerNonAAQuad() { return kVertsPerNonAAQuad; }
NumIndicesPerNonAAQuad()564*c8dee2aaSAndroid Build Coastguard Worker int GrResourceProvider::NumIndicesPerNonAAQuad() { return kIndicesPerNonAAQuad; }
565*c8dee2aaSAndroid Build Coastguard Worker 
566*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////////////////////////
567*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kMaxNumAAQuads = 1 << 9;  // max possible: (1 << 13) - 1;
568*c8dee2aaSAndroid Build Coastguard Worker static const int kVertsPerAAQuad = 8;
569*c8dee2aaSAndroid Build Coastguard Worker static const int kIndicesPerAAQuad = 30;
570*c8dee2aaSAndroid Build Coastguard Worker 
createAAQuadIndexBuffer()571*c8dee2aaSAndroid Build Coastguard Worker sk_sp<const GrGpuBuffer> GrResourceProvider::createAAQuadIndexBuffer() {
572*c8dee2aaSAndroid Build Coastguard Worker     static_assert(kVertsPerAAQuad * kMaxNumAAQuads <= 65535);  // indices fit in a uint16_t
573*c8dee2aaSAndroid Build Coastguard Worker 
574*c8dee2aaSAndroid Build Coastguard Worker     // clang-format off
575*c8dee2aaSAndroid Build Coastguard Worker     static const uint16_t kAAQuadIndexPattern[] = {
576*c8dee2aaSAndroid Build Coastguard Worker         0, 1, 2, 1, 3, 2,
577*c8dee2aaSAndroid Build Coastguard Worker         0, 4, 1, 4, 5, 1,
578*c8dee2aaSAndroid Build Coastguard Worker         0, 6, 4, 0, 2, 6,
579*c8dee2aaSAndroid Build Coastguard Worker         2, 3, 6, 3, 7, 6,
580*c8dee2aaSAndroid Build Coastguard Worker         1, 5, 3, 3, 5, 7,
581*c8dee2aaSAndroid Build Coastguard Worker     };
582*c8dee2aaSAndroid Build Coastguard Worker     // clang-format on
583*c8dee2aaSAndroid Build Coastguard Worker 
584*c8dee2aaSAndroid Build Coastguard Worker     static_assert(std::size(kAAQuadIndexPattern) == kIndicesPerAAQuad);
585*c8dee2aaSAndroid Build Coastguard Worker 
586*c8dee2aaSAndroid Build Coastguard Worker     return this->createPatternedIndexBuffer(kAAQuadIndexPattern, kIndicesPerAAQuad,
587*c8dee2aaSAndroid Build Coastguard Worker                                             kMaxNumAAQuads, kVertsPerAAQuad, nullptr);
588*c8dee2aaSAndroid Build Coastguard Worker }
589*c8dee2aaSAndroid Build Coastguard Worker 
MaxNumAAQuads()590*c8dee2aaSAndroid Build Coastguard Worker int GrResourceProvider::MaxNumAAQuads() { return kMaxNumAAQuads; }
NumVertsPerAAQuad()591*c8dee2aaSAndroid Build Coastguard Worker int GrResourceProvider::NumVertsPerAAQuad() { return kVertsPerAAQuad; }
NumIndicesPerAAQuad()592*c8dee2aaSAndroid Build Coastguard Worker int GrResourceProvider::NumIndicesPerAAQuad() { return kIndicesPerAAQuad; }
593*c8dee2aaSAndroid Build Coastguard Worker 
594*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////////////////////////
595*c8dee2aaSAndroid Build Coastguard Worker 
createBuffer(size_t size,GrGpuBufferType intendedType,GrAccessPattern accessPattern,ZeroInit zeroInit)596*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrGpuBuffer> GrResourceProvider::createBuffer(size_t size,
597*c8dee2aaSAndroid Build Coastguard Worker                                                     GrGpuBufferType intendedType,
598*c8dee2aaSAndroid Build Coastguard Worker                                                     GrAccessPattern accessPattern,
599*c8dee2aaSAndroid Build Coastguard Worker                                                     ZeroInit zeroInit) {
600*c8dee2aaSAndroid Build Coastguard Worker     if (this->isAbandoned()) {
601*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
602*c8dee2aaSAndroid Build Coastguard Worker     }
603*c8dee2aaSAndroid Build Coastguard Worker     if (kDynamic_GrAccessPattern != accessPattern) {
604*c8dee2aaSAndroid Build Coastguard Worker         if (this->caps()->buffersAreInitiallyZero()) {
605*c8dee2aaSAndroid Build Coastguard Worker             zeroInit = ZeroInit::kNo;
606*c8dee2aaSAndroid Build Coastguard Worker         }
607*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<GrGpuBuffer> buffer = this->gpu()->createBuffer(size, intendedType, accessPattern);
608*c8dee2aaSAndroid Build Coastguard Worker         if (buffer && zeroInit == ZeroInit::kYes && !buffer->clearToZero()) {
609*c8dee2aaSAndroid Build Coastguard Worker             return nullptr;
610*c8dee2aaSAndroid Build Coastguard Worker         }
611*c8dee2aaSAndroid Build Coastguard Worker         return buffer;
612*c8dee2aaSAndroid Build Coastguard Worker     }
613*c8dee2aaSAndroid Build Coastguard Worker     // bin by pow2+midpoint with a reasonable min
614*c8dee2aaSAndroid Build Coastguard Worker     static const size_t MIN_SIZE = 1 << 12;
615*c8dee2aaSAndroid Build Coastguard Worker     static const size_t MIN_UNIFORM_SIZE = 1 << 7;
616*c8dee2aaSAndroid Build Coastguard Worker     size_t allocSize = intendedType == GrGpuBufferType::kUniform ? std::max(size, MIN_UNIFORM_SIZE)
617*c8dee2aaSAndroid Build Coastguard Worker                                                                  : std::max(size, MIN_SIZE);
618*c8dee2aaSAndroid Build Coastguard Worker     size_t ceilPow2 = SkNextSizePow2(allocSize);
619*c8dee2aaSAndroid Build Coastguard Worker     size_t floorPow2 = ceilPow2 >> 1;
620*c8dee2aaSAndroid Build Coastguard Worker     size_t mid = floorPow2 + (floorPow2 >> 1);
621*c8dee2aaSAndroid Build Coastguard Worker     allocSize = (allocSize <= mid) ? mid : ceilPow2;
622*c8dee2aaSAndroid Build Coastguard Worker 
623*c8dee2aaSAndroid Build Coastguard Worker     skgpu::ScratchKey key;
624*c8dee2aaSAndroid Build Coastguard Worker     GrGpuBuffer::ComputeScratchKeyForDynamicBuffer(allocSize, intendedType, &key);
625*c8dee2aaSAndroid Build Coastguard Worker     auto buffer =
626*c8dee2aaSAndroid Build Coastguard Worker             sk_sp<GrGpuBuffer>(static_cast<GrGpuBuffer*>(this->cache()->findAndRefScratchResource(
627*c8dee2aaSAndroid Build Coastguard Worker                     key)));
628*c8dee2aaSAndroid Build Coastguard Worker     if (!buffer) {
629*c8dee2aaSAndroid Build Coastguard Worker         if (this->caps()->buffersAreInitiallyZero()) {
630*c8dee2aaSAndroid Build Coastguard Worker             zeroInit = ZeroInit::kNo;
631*c8dee2aaSAndroid Build Coastguard Worker         }
632*c8dee2aaSAndroid Build Coastguard Worker         buffer = this->gpu()->createBuffer(allocSize, intendedType, kDynamic_GrAccessPattern);
633*c8dee2aaSAndroid Build Coastguard Worker     }
634*c8dee2aaSAndroid Build Coastguard Worker     if (buffer && zeroInit == ZeroInit::kYes && !buffer->clearToZero()) {
635*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
636*c8dee2aaSAndroid Build Coastguard Worker     }
637*c8dee2aaSAndroid Build Coastguard Worker     return buffer;
638*c8dee2aaSAndroid Build Coastguard Worker }
639*c8dee2aaSAndroid Build Coastguard Worker 
createBuffer(const void * data,size_t size,GrGpuBufferType type,GrAccessPattern pattern)640*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrGpuBuffer> GrResourceProvider::createBuffer(const void* data,
641*c8dee2aaSAndroid Build Coastguard Worker                                                     size_t size,
642*c8dee2aaSAndroid Build Coastguard Worker                                                     GrGpuBufferType type,
643*c8dee2aaSAndroid Build Coastguard Worker                                                     GrAccessPattern pattern) {
644*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(data);
645*c8dee2aaSAndroid Build Coastguard Worker     auto buffer = this->createBuffer(size, type, pattern, ZeroInit::kNo);
646*c8dee2aaSAndroid Build Coastguard Worker     if (!buffer) {
647*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
648*c8dee2aaSAndroid Build Coastguard Worker     }
649*c8dee2aaSAndroid Build Coastguard Worker     if (!buffer->updateData(data, /*offset=*/0, size, /*preserve=*/false)) {
650*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
651*c8dee2aaSAndroid Build Coastguard Worker     }
652*c8dee2aaSAndroid Build Coastguard Worker     return buffer;
653*c8dee2aaSAndroid Build Coastguard Worker }
654*c8dee2aaSAndroid Build Coastguard Worker 
num_stencil_samples(const GrRenderTarget * rt,bool useMSAASurface,const GrCaps & caps)655*c8dee2aaSAndroid Build Coastguard Worker static int num_stencil_samples(const GrRenderTarget* rt, bool useMSAASurface, const GrCaps& caps) {
656*c8dee2aaSAndroid Build Coastguard Worker     int numSamples = rt->numSamples();
657*c8dee2aaSAndroid Build Coastguard Worker     if (numSamples == 1 && useMSAASurface) {  // Are we using dynamic msaa?
658*c8dee2aaSAndroid Build Coastguard Worker         numSamples = caps.internalMultisampleCount(rt->backendFormat());
659*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(numSamples > 1);  // Caller must ensure dmsaa is supported before trying to use it.
660*c8dee2aaSAndroid Build Coastguard Worker     }
661*c8dee2aaSAndroid Build Coastguard Worker     return numSamples;
662*c8dee2aaSAndroid Build Coastguard Worker }
663*c8dee2aaSAndroid Build Coastguard Worker 
attachStencilAttachment(GrRenderTarget * rt,bool useMSAASurface)664*c8dee2aaSAndroid Build Coastguard Worker bool GrResourceProvider::attachStencilAttachment(GrRenderTarget* rt, bool useMSAASurface) {
665*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(rt);
666*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!this->caps()->avoidStencilBuffers());
667*c8dee2aaSAndroid Build Coastguard Worker 
668*c8dee2aaSAndroid Build Coastguard Worker     GrAttachment* stencil = rt->getStencilAttachment(useMSAASurface);
669*c8dee2aaSAndroid Build Coastguard Worker     if (stencil) {
670*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(stencil->numSamples() == num_stencil_samples(rt, useMSAASurface, *this->caps()));
671*c8dee2aaSAndroid Build Coastguard Worker         return true;
672*c8dee2aaSAndroid Build Coastguard Worker     }
673*c8dee2aaSAndroid Build Coastguard Worker 
674*c8dee2aaSAndroid Build Coastguard Worker     if (!rt->wasDestroyed() && rt->canAttemptStencilAttachment(useMSAASurface)) {
675*c8dee2aaSAndroid Build Coastguard Worker         skgpu::UniqueKey sbKey;
676*c8dee2aaSAndroid Build Coastguard Worker 
677*c8dee2aaSAndroid Build Coastguard Worker #if 0
678*c8dee2aaSAndroid Build Coastguard Worker         if (this->caps()->oversizedStencilSupport()) {
679*c8dee2aaSAndroid Build Coastguard Worker             width  = SkNextPow2(width);
680*c8dee2aaSAndroid Build Coastguard Worker             height = SkNextPow2(height);
681*c8dee2aaSAndroid Build Coastguard Worker         }
682*c8dee2aaSAndroid Build Coastguard Worker #endif
683*c8dee2aaSAndroid Build Coastguard Worker         GrBackendFormat stencilFormat = this->gpu()->getPreferredStencilFormat(rt->backendFormat());
684*c8dee2aaSAndroid Build Coastguard Worker         if (!stencilFormat.isValid()) {
685*c8dee2aaSAndroid Build Coastguard Worker             return false;
686*c8dee2aaSAndroid Build Coastguard Worker         }
687*c8dee2aaSAndroid Build Coastguard Worker         GrProtected isProtected = rt->isProtected() ? GrProtected::kYes : GrProtected::kNo;
688*c8dee2aaSAndroid Build Coastguard Worker         int numStencilSamples = num_stencil_samples(rt, useMSAASurface, *this->caps());
689*c8dee2aaSAndroid Build Coastguard Worker         GrAttachment::ComputeSharedAttachmentUniqueKey(*this->caps(),
690*c8dee2aaSAndroid Build Coastguard Worker                                                        stencilFormat,
691*c8dee2aaSAndroid Build Coastguard Worker                                                        rt->dimensions(),
692*c8dee2aaSAndroid Build Coastguard Worker                                                        GrAttachment::UsageFlags::kStencilAttachment,
693*c8dee2aaSAndroid Build Coastguard Worker                                                        numStencilSamples,
694*c8dee2aaSAndroid Build Coastguard Worker                                                        skgpu::Mipmapped::kNo,
695*c8dee2aaSAndroid Build Coastguard Worker                                                        isProtected,
696*c8dee2aaSAndroid Build Coastguard Worker                                                        GrMemoryless::kNo,
697*c8dee2aaSAndroid Build Coastguard Worker                                                        &sbKey);
698*c8dee2aaSAndroid Build Coastguard Worker         auto keyedStencil = this->findByUniqueKey<GrAttachment>(sbKey);
699*c8dee2aaSAndroid Build Coastguard Worker         if (!keyedStencil) {
700*c8dee2aaSAndroid Build Coastguard Worker             // Need to try and create a new stencil
701*c8dee2aaSAndroid Build Coastguard Worker             keyedStencil = this->gpu()->makeStencilAttachment(rt->backendFormat(), rt->dimensions(),
702*c8dee2aaSAndroid Build Coastguard Worker                                                               numStencilSamples);
703*c8dee2aaSAndroid Build Coastguard Worker             if (!keyedStencil) {
704*c8dee2aaSAndroid Build Coastguard Worker                 return false;
705*c8dee2aaSAndroid Build Coastguard Worker             }
706*c8dee2aaSAndroid Build Coastguard Worker             this->assignUniqueKeyToResource(sbKey, keyedStencil.get());
707*c8dee2aaSAndroid Build Coastguard Worker         }
708*c8dee2aaSAndroid Build Coastguard Worker         rt->attachStencilAttachment(std::move(keyedStencil), useMSAASurface);
709*c8dee2aaSAndroid Build Coastguard Worker     }
710*c8dee2aaSAndroid Build Coastguard Worker     stencil = rt->getStencilAttachment(useMSAASurface);
711*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!stencil ||
712*c8dee2aaSAndroid Build Coastguard Worker              stencil->numSamples() == num_stencil_samples(rt, useMSAASurface, *this->caps()));
713*c8dee2aaSAndroid Build Coastguard Worker     return stencil != nullptr;
714*c8dee2aaSAndroid Build Coastguard Worker }
715*c8dee2aaSAndroid Build Coastguard Worker 
getDiscardableMSAAAttachment(SkISize dimensions,const GrBackendFormat & format,int sampleCnt,GrProtected isProtected,GrMemoryless memoryless)716*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrAttachment> GrResourceProvider::getDiscardableMSAAAttachment(SkISize dimensions,
717*c8dee2aaSAndroid Build Coastguard Worker                                                                      const GrBackendFormat& format,
718*c8dee2aaSAndroid Build Coastguard Worker                                                                      int sampleCnt,
719*c8dee2aaSAndroid Build Coastguard Worker                                                                      GrProtected isProtected,
720*c8dee2aaSAndroid Build Coastguard Worker                                                                      GrMemoryless memoryless) {
721*c8dee2aaSAndroid Build Coastguard Worker     ASSERT_SINGLE_OWNER
722*c8dee2aaSAndroid Build Coastguard Worker 
723*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(sampleCnt > 1);
724*c8dee2aaSAndroid Build Coastguard Worker 
725*c8dee2aaSAndroid Build Coastguard Worker     if (this->isAbandoned()) {
726*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
727*c8dee2aaSAndroid Build Coastguard Worker     }
728*c8dee2aaSAndroid Build Coastguard Worker 
729*c8dee2aaSAndroid Build Coastguard Worker     if (!fCaps->validateSurfaceParams(dimensions,
730*c8dee2aaSAndroid Build Coastguard Worker                                       format,
731*c8dee2aaSAndroid Build Coastguard Worker                                       GrRenderable::kYes,
732*c8dee2aaSAndroid Build Coastguard Worker                                       sampleCnt,
733*c8dee2aaSAndroid Build Coastguard Worker                                       skgpu::Mipmapped::kNo,
734*c8dee2aaSAndroid Build Coastguard Worker                                       GrTextureType::kNone)) {
735*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
736*c8dee2aaSAndroid Build Coastguard Worker     }
737*c8dee2aaSAndroid Build Coastguard Worker 
738*c8dee2aaSAndroid Build Coastguard Worker     skgpu::UniqueKey key;
739*c8dee2aaSAndroid Build Coastguard Worker     GrAttachment::ComputeSharedAttachmentUniqueKey(*this->caps(),
740*c8dee2aaSAndroid Build Coastguard Worker                                                    format,
741*c8dee2aaSAndroid Build Coastguard Worker                                                    dimensions,
742*c8dee2aaSAndroid Build Coastguard Worker                                                    GrAttachment::UsageFlags::kColorAttachment,
743*c8dee2aaSAndroid Build Coastguard Worker                                                    sampleCnt,
744*c8dee2aaSAndroid Build Coastguard Worker                                                    skgpu::Mipmapped::kNo,
745*c8dee2aaSAndroid Build Coastguard Worker                                                    isProtected,
746*c8dee2aaSAndroid Build Coastguard Worker                                                    memoryless,
747*c8dee2aaSAndroid Build Coastguard Worker                                                    &key);
748*c8dee2aaSAndroid Build Coastguard Worker     auto msaaAttachment = this->findByUniqueKey<GrAttachment>(key);
749*c8dee2aaSAndroid Build Coastguard Worker     if (msaaAttachment) {
750*c8dee2aaSAndroid Build Coastguard Worker         return msaaAttachment;
751*c8dee2aaSAndroid Build Coastguard Worker     }
752*c8dee2aaSAndroid Build Coastguard Worker     msaaAttachment = this->makeMSAAAttachment(dimensions, format, sampleCnt, isProtected,
753*c8dee2aaSAndroid Build Coastguard Worker                                               memoryless);
754*c8dee2aaSAndroid Build Coastguard Worker     if (msaaAttachment) {
755*c8dee2aaSAndroid Build Coastguard Worker         this->assignUniqueKeyToResource(key, msaaAttachment.get());
756*c8dee2aaSAndroid Build Coastguard Worker     }
757*c8dee2aaSAndroid Build Coastguard Worker     return msaaAttachment;
758*c8dee2aaSAndroid Build Coastguard Worker }
759*c8dee2aaSAndroid Build Coastguard Worker 
makeMSAAAttachment(SkISize dimensions,const GrBackendFormat & format,int sampleCnt,GrProtected isProtected,GrMemoryless memoryless)760*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrAttachment> GrResourceProvider::makeMSAAAttachment(SkISize dimensions,
761*c8dee2aaSAndroid Build Coastguard Worker                                                            const GrBackendFormat& format,
762*c8dee2aaSAndroid Build Coastguard Worker                                                            int sampleCnt,
763*c8dee2aaSAndroid Build Coastguard Worker                                                            GrProtected isProtected,
764*c8dee2aaSAndroid Build Coastguard Worker                                                            GrMemoryless memoryless) {
765*c8dee2aaSAndroid Build Coastguard Worker     ASSERT_SINGLE_OWNER
766*c8dee2aaSAndroid Build Coastguard Worker 
767*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(sampleCnt > 1);
768*c8dee2aaSAndroid Build Coastguard Worker 
769*c8dee2aaSAndroid Build Coastguard Worker     if (this->isAbandoned()) {
770*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
771*c8dee2aaSAndroid Build Coastguard Worker     }
772*c8dee2aaSAndroid Build Coastguard Worker 
773*c8dee2aaSAndroid Build Coastguard Worker     if (!fCaps->validateSurfaceParams(dimensions,
774*c8dee2aaSAndroid Build Coastguard Worker                                       format,
775*c8dee2aaSAndroid Build Coastguard Worker                                       GrRenderable::kYes,
776*c8dee2aaSAndroid Build Coastguard Worker                                       sampleCnt,
777*c8dee2aaSAndroid Build Coastguard Worker                                       skgpu::Mipmapped::kNo,
778*c8dee2aaSAndroid Build Coastguard Worker                                       GrTextureType::kNone)) {
779*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
780*c8dee2aaSAndroid Build Coastguard Worker     }
781*c8dee2aaSAndroid Build Coastguard Worker 
782*c8dee2aaSAndroid Build Coastguard Worker     auto scratch = this->refScratchMSAAAttachment(dimensions,
783*c8dee2aaSAndroid Build Coastguard Worker                                                   format,
784*c8dee2aaSAndroid Build Coastguard Worker                                                   sampleCnt,
785*c8dee2aaSAndroid Build Coastguard Worker                                                   isProtected,
786*c8dee2aaSAndroid Build Coastguard Worker                                                   memoryless,
787*c8dee2aaSAndroid Build Coastguard Worker                                                   /*label=*/"MakeMSAAAttachment");
788*c8dee2aaSAndroid Build Coastguard Worker     if (scratch) {
789*c8dee2aaSAndroid Build Coastguard Worker         return scratch;
790*c8dee2aaSAndroid Build Coastguard Worker     }
791*c8dee2aaSAndroid Build Coastguard Worker 
792*c8dee2aaSAndroid Build Coastguard Worker     return fGpu->makeMSAAAttachment(dimensions, format, sampleCnt, isProtected, memoryless);
793*c8dee2aaSAndroid Build Coastguard Worker }
794*c8dee2aaSAndroid Build Coastguard Worker 
refScratchMSAAAttachment(SkISize dimensions,const GrBackendFormat & format,int sampleCnt,GrProtected isProtected,GrMemoryless memoryless,std::string_view label)795*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrAttachment> GrResourceProvider::refScratchMSAAAttachment(SkISize dimensions,
796*c8dee2aaSAndroid Build Coastguard Worker                                                                  const GrBackendFormat& format,
797*c8dee2aaSAndroid Build Coastguard Worker                                                                  int sampleCnt,
798*c8dee2aaSAndroid Build Coastguard Worker                                                                  GrProtected isProtected,
799*c8dee2aaSAndroid Build Coastguard Worker                                                                  GrMemoryless memoryless,
800*c8dee2aaSAndroid Build Coastguard Worker                                                                  std::string_view label) {
801*c8dee2aaSAndroid Build Coastguard Worker     ASSERT_SINGLE_OWNER
802*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!this->isAbandoned());
803*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!this->caps()->isFormatCompressed(format));
804*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(fCaps->validateSurfaceParams(dimensions,
805*c8dee2aaSAndroid Build Coastguard Worker                                           format,
806*c8dee2aaSAndroid Build Coastguard Worker                                           GrRenderable::kYes,
807*c8dee2aaSAndroid Build Coastguard Worker                                           sampleCnt,
808*c8dee2aaSAndroid Build Coastguard Worker                                           skgpu::Mipmapped::kNo,
809*c8dee2aaSAndroid Build Coastguard Worker                                           GrTextureType::kNone));
810*c8dee2aaSAndroid Build Coastguard Worker 
811*c8dee2aaSAndroid Build Coastguard Worker     skgpu::ScratchKey key;
812*c8dee2aaSAndroid Build Coastguard Worker     GrAttachment::ComputeScratchKey(*this->caps(),
813*c8dee2aaSAndroid Build Coastguard Worker                                     format,
814*c8dee2aaSAndroid Build Coastguard Worker                                     dimensions,
815*c8dee2aaSAndroid Build Coastguard Worker                                     GrAttachment::UsageFlags::kColorAttachment,
816*c8dee2aaSAndroid Build Coastguard Worker                                     sampleCnt,
817*c8dee2aaSAndroid Build Coastguard Worker                                     skgpu::Mipmapped::kNo,
818*c8dee2aaSAndroid Build Coastguard Worker                                     isProtected,
819*c8dee2aaSAndroid Build Coastguard Worker                                     memoryless,
820*c8dee2aaSAndroid Build Coastguard Worker                                     &key);
821*c8dee2aaSAndroid Build Coastguard Worker     GrGpuResource* resource = fCache->findAndRefScratchResource(key);
822*c8dee2aaSAndroid Build Coastguard Worker     if (resource) {
823*c8dee2aaSAndroid Build Coastguard Worker         fGpu->stats()->incNumScratchMSAAAttachmentsReused();
824*c8dee2aaSAndroid Build Coastguard Worker         GrAttachment* attachment = static_cast<GrAttachment*>(resource);
825*c8dee2aaSAndroid Build Coastguard Worker         resource->setLabel(std::move(label));
826*c8dee2aaSAndroid Build Coastguard Worker         return sk_sp<GrAttachment>(attachment);
827*c8dee2aaSAndroid Build Coastguard Worker     }
828*c8dee2aaSAndroid Build Coastguard Worker 
829*c8dee2aaSAndroid Build Coastguard Worker     return nullptr;
830*c8dee2aaSAndroid Build Coastguard Worker }
831*c8dee2aaSAndroid Build Coastguard Worker 
makeSemaphore(bool isOwned)832*c8dee2aaSAndroid Build Coastguard Worker [[nodiscard]] std::unique_ptr<GrSemaphore> GrResourceProvider::makeSemaphore(bool isOwned) {
833*c8dee2aaSAndroid Build Coastguard Worker     return this->isAbandoned() ? nullptr : fGpu->makeSemaphore(isOwned);
834*c8dee2aaSAndroid Build Coastguard Worker }
835*c8dee2aaSAndroid Build Coastguard Worker 
wrapBackendSemaphore(const GrBackendSemaphore & semaphore,GrSemaphoreWrapType wrapType,GrWrapOwnership ownership)836*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<GrSemaphore> GrResourceProvider::wrapBackendSemaphore(
837*c8dee2aaSAndroid Build Coastguard Worker         const GrBackendSemaphore& semaphore,
838*c8dee2aaSAndroid Build Coastguard Worker         GrSemaphoreWrapType wrapType,
839*c8dee2aaSAndroid Build Coastguard Worker         GrWrapOwnership ownership) {
840*c8dee2aaSAndroid Build Coastguard Worker     ASSERT_SINGLE_OWNER
841*c8dee2aaSAndroid Build Coastguard Worker     return this->isAbandoned() ? nullptr : fGpu->wrapBackendSemaphore(semaphore,
842*c8dee2aaSAndroid Build Coastguard Worker                                                                       wrapType,
843*c8dee2aaSAndroid Build Coastguard Worker                                                                       ownership);
844*c8dee2aaSAndroid Build Coastguard Worker }
845*c8dee2aaSAndroid Build Coastguard Worker 
846*c8dee2aaSAndroid Build Coastguard Worker // Ensures the row bytes are populated (not 0) and makes a copy to a temporary
847*c8dee2aaSAndroid Build Coastguard Worker // to make the row bytes tight if necessary. Returns false if the input row bytes are invalid.
prepare_level(const GrMipLevel & inLevel,SkISize dimensions,bool rowBytesSupport,GrColorType origColorType,GrColorType allowedColorType,GrMipLevel * outLevel,std::unique_ptr<char[]> * data)848*c8dee2aaSAndroid Build Coastguard Worker static bool prepare_level(const GrMipLevel& inLevel,
849*c8dee2aaSAndroid Build Coastguard Worker                           SkISize dimensions,
850*c8dee2aaSAndroid Build Coastguard Worker                           bool rowBytesSupport,
851*c8dee2aaSAndroid Build Coastguard Worker                           GrColorType origColorType,
852*c8dee2aaSAndroid Build Coastguard Worker                           GrColorType allowedColorType,
853*c8dee2aaSAndroid Build Coastguard Worker                           GrMipLevel* outLevel,
854*c8dee2aaSAndroid Build Coastguard Worker                           std::unique_ptr<char[]>* data) {
855*c8dee2aaSAndroid Build Coastguard Worker     if (!inLevel.fPixels) {
856*c8dee2aaSAndroid Build Coastguard Worker         outLevel->fPixels = nullptr;
857*c8dee2aaSAndroid Build Coastguard Worker         outLevel->fRowBytes = 0;
858*c8dee2aaSAndroid Build Coastguard Worker         return true;
859*c8dee2aaSAndroid Build Coastguard Worker     }
860*c8dee2aaSAndroid Build Coastguard Worker     size_t minRB = dimensions.fWidth * GrColorTypeBytesPerPixel(origColorType);
861*c8dee2aaSAndroid Build Coastguard Worker     size_t actualRB = inLevel.fRowBytes ? inLevel.fRowBytes : minRB;
862*c8dee2aaSAndroid Build Coastguard Worker     if (actualRB < minRB) {
863*c8dee2aaSAndroid Build Coastguard Worker         return false;
864*c8dee2aaSAndroid Build Coastguard Worker     }
865*c8dee2aaSAndroid Build Coastguard Worker     if (origColorType == allowedColorType && (actualRB == minRB || rowBytesSupport)) {
866*c8dee2aaSAndroid Build Coastguard Worker         outLevel->fRowBytes = actualRB;
867*c8dee2aaSAndroid Build Coastguard Worker         outLevel->fPixels = inLevel.fPixels;
868*c8dee2aaSAndroid Build Coastguard Worker         return true;
869*c8dee2aaSAndroid Build Coastguard Worker     }
870*c8dee2aaSAndroid Build Coastguard Worker     auto tempRB = dimensions.fWidth * GrColorTypeBytesPerPixel(allowedColorType);
871*c8dee2aaSAndroid Build Coastguard Worker     data->reset(new char[tempRB * dimensions.fHeight]);
872*c8dee2aaSAndroid Build Coastguard Worker     outLevel->fPixels = data->get();
873*c8dee2aaSAndroid Build Coastguard Worker     outLevel->fRowBytes = tempRB;
874*c8dee2aaSAndroid Build Coastguard Worker     GrImageInfo srcInfo(   origColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
875*c8dee2aaSAndroid Build Coastguard Worker     GrImageInfo dstInfo(allowedColorType, kUnpremul_SkAlphaType, nullptr, dimensions);
876*c8dee2aaSAndroid Build Coastguard Worker     return GrConvertPixels( GrPixmap(dstInfo,     data->get(),   tempRB),
877*c8dee2aaSAndroid Build Coastguard Worker                            GrCPixmap(srcInfo, inLevel.fPixels, actualRB));
878*c8dee2aaSAndroid Build Coastguard Worker }
879*c8dee2aaSAndroid Build Coastguard Worker 
prepareLevels(const GrBackendFormat & format,GrColorType colorType,SkISize baseSize,const GrMipLevel texels[],int mipLevelCount,TempLevels * tempLevels,TempLevelDatas * tempLevelDatas) const880*c8dee2aaSAndroid Build Coastguard Worker GrColorType GrResourceProvider::prepareLevels(const GrBackendFormat& format,
881*c8dee2aaSAndroid Build Coastguard Worker                                               GrColorType colorType,
882*c8dee2aaSAndroid Build Coastguard Worker                                               SkISize baseSize,
883*c8dee2aaSAndroid Build Coastguard Worker                                               const GrMipLevel texels[],
884*c8dee2aaSAndroid Build Coastguard Worker                                               int mipLevelCount,
885*c8dee2aaSAndroid Build Coastguard Worker                                               TempLevels* tempLevels,
886*c8dee2aaSAndroid Build Coastguard Worker                                               TempLevelDatas* tempLevelDatas) const {
887*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(mipLevelCount && texels && texels[0].fPixels);
888*c8dee2aaSAndroid Build Coastguard Worker 
889*c8dee2aaSAndroid Build Coastguard Worker     auto allowedColorType =
890*c8dee2aaSAndroid Build Coastguard Worker             this->caps()->supportedWritePixelsColorType(colorType, format, colorType).fColorType;
891*c8dee2aaSAndroid Build Coastguard Worker     if (allowedColorType == GrColorType::kUnknown) {
892*c8dee2aaSAndroid Build Coastguard Worker         return GrColorType::kUnknown;
893*c8dee2aaSAndroid Build Coastguard Worker     }
894*c8dee2aaSAndroid Build Coastguard Worker     bool rowBytesSupport = this->caps()->writePixelsRowBytesSupport();
895*c8dee2aaSAndroid Build Coastguard Worker     tempLevels->reset(mipLevelCount);
896*c8dee2aaSAndroid Build Coastguard Worker     tempLevelDatas->reset(mipLevelCount);
897*c8dee2aaSAndroid Build Coastguard Worker     auto size = baseSize;
898*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < mipLevelCount; ++i) {
899*c8dee2aaSAndroid Build Coastguard Worker         if (!prepare_level(texels[i], size, rowBytesSupport, colorType, allowedColorType,
900*c8dee2aaSAndroid Build Coastguard Worker                            &(*tempLevels)[i], &(*tempLevelDatas)[i])) {
901*c8dee2aaSAndroid Build Coastguard Worker             return GrColorType::kUnknown;
902*c8dee2aaSAndroid Build Coastguard Worker         }
903*c8dee2aaSAndroid Build Coastguard Worker         size = {std::max(size.fWidth / 2, 1), std::max(size.fHeight / 2, 1)};
904*c8dee2aaSAndroid Build Coastguard Worker     }
905*c8dee2aaSAndroid Build Coastguard Worker     return allowedColorType;
906*c8dee2aaSAndroid Build Coastguard Worker }
907*c8dee2aaSAndroid Build Coastguard Worker 
writePixels(sk_sp<GrTexture> texture,GrColorType colorType,SkISize baseSize,const GrMipLevel texels[],int mipLevelCount) const908*c8dee2aaSAndroid Build Coastguard Worker sk_sp<GrTexture> GrResourceProvider::writePixels(sk_sp<GrTexture> texture,
909*c8dee2aaSAndroid Build Coastguard Worker                                                  GrColorType colorType,
910*c8dee2aaSAndroid Build Coastguard Worker                                                  SkISize baseSize,
911*c8dee2aaSAndroid Build Coastguard Worker                                                  const GrMipLevel texels[],
912*c8dee2aaSAndroid Build Coastguard Worker                                                  int mipLevelCount) const {
913*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(!this->isAbandoned());
914*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(texture);
915*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(colorType != GrColorType::kUnknown);
916*c8dee2aaSAndroid Build Coastguard Worker     SkASSERT(mipLevelCount && texels && texels[0].fPixels);
917*c8dee2aaSAndroid Build Coastguard Worker 
918*c8dee2aaSAndroid Build Coastguard Worker     AutoSTArray<14, GrMipLevel> tmpTexels;
919*c8dee2aaSAndroid Build Coastguard Worker     AutoSTArray<14, std::unique_ptr<char[]>> tmpDatas;
920*c8dee2aaSAndroid Build Coastguard Worker     auto tempColorType = this->prepareLevels(texture->backendFormat(), colorType, baseSize, texels,
921*c8dee2aaSAndroid Build Coastguard Worker                                              mipLevelCount, &tmpTexels, &tmpDatas);
922*c8dee2aaSAndroid Build Coastguard Worker     if (tempColorType == GrColorType::kUnknown) {
923*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
924*c8dee2aaSAndroid Build Coastguard Worker     }
925*c8dee2aaSAndroid Build Coastguard Worker     SkAssertResult(fGpu->writePixels(texture.get(),
926*c8dee2aaSAndroid Build Coastguard Worker                                      SkIRect::MakeSize(baseSize),
927*c8dee2aaSAndroid Build Coastguard Worker                                      colorType,
928*c8dee2aaSAndroid Build Coastguard Worker                                      tempColorType,
929*c8dee2aaSAndroid Build Coastguard Worker                                      tmpTexels.get(),
930*c8dee2aaSAndroid Build Coastguard Worker                                      mipLevelCount));
931*c8dee2aaSAndroid Build Coastguard Worker     return texture;
932*c8dee2aaSAndroid Build Coastguard Worker }
933