xref: /aosp_15_r20/external/skia/src/gpu/ganesh/mock/GrMockGpu.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2017 Google Inc.
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 #include "src/gpu/ganesh/mock/GrMockGpu.h"
8 
9 #include "include/gpu/GpuTypes.h"
10 #include "include/private/base/SkDebug.h"
11 #include "include/private/base/SkMath.h"
12 #include "src/gpu/ganesh/GrCaps.h"
13 #include "src/gpu/ganesh/GrGpuBuffer.h"
14 #include "src/gpu/ganesh/GrRenderTarget.h"
15 #include "src/gpu/ganesh/GrTexture.h"
16 #include "src/gpu/ganesh/GrThreadSafePipelineBuilder.h"  // IWYU pragma: keep
17 #include "src/gpu/ganesh/mock/GrMockAttachment.h"
18 #include "src/gpu/ganesh/mock/GrMockBuffer.h"
19 #include "src/gpu/ganesh/mock/GrMockCaps.h"
20 #include "src/gpu/ganesh/mock/GrMockOpsRenderPass.h"
21 #include "src/gpu/ganesh/mock/GrMockTexture.h"
22 
23 #include <atomic>
24 
25 using namespace skia_private;
26 
NextInternalTextureID()27 int GrMockGpu::NextInternalTextureID() {
28     static std::atomic<int> nextID{1};
29     int id;
30     do {
31         id = nextID.fetch_add(1, std::memory_order_relaxed);
32     } while (0 == id);  // Reserve 0 for an invalid ID.
33     return id;
34 }
35 
NextExternalTextureID()36 int GrMockGpu::NextExternalTextureID() {
37     // We use negative ints for the "testing only external textures" so they can easily be
38     // identified when debugging.
39     static std::atomic<int> nextID{-1};
40     return nextID.fetch_add(-1, std::memory_order_relaxed);
41 }
42 
NextInternalRenderTargetID()43 int GrMockGpu::NextInternalRenderTargetID() {
44     // We start off with large numbers to differentiate from texture IDs, even though they're
45     // technically in a different space.
46     static std::atomic<int> nextID{SK_MaxS32};
47     return nextID.fetch_add(-1, std::memory_order_relaxed);
48 }
49 
NextExternalRenderTargetID()50 int GrMockGpu::NextExternalRenderTargetID() {
51     // We use large negative ints for the "testing only external render targets" so they can easily
52     // be identified when debugging.
53     static std::atomic<int> nextID{SK_MinS32};
54     return nextID.fetch_add(1, std::memory_order_relaxed);
55 }
56 
Make(const GrMockOptions * mockOptions,const GrContextOptions & contextOptions,GrDirectContext * direct)57 std::unique_ptr<GrGpu> GrMockGpu::Make(const GrMockOptions* mockOptions,
58                                        const GrContextOptions& contextOptions,
59                                        GrDirectContext* direct) {
60     static const GrMockOptions kDefaultOptions = GrMockOptions();
61     if (!mockOptions) {
62         mockOptions = &kDefaultOptions;
63     }
64     return std::unique_ptr<GrGpu>(new GrMockGpu(direct, *mockOptions, contextOptions));
65 }
66 
onGetOpsRenderPass(GrRenderTarget * rt,bool,GrAttachment *,GrSurfaceOrigin origin,const SkIRect & bounds,const GrOpsRenderPass::LoadAndStoreInfo & colorInfo,const GrOpsRenderPass::StencilLoadAndStoreInfo &,const TArray<GrSurfaceProxy *,true> & sampledProxies,GrXferBarrierFlags renderPassXferBarriers)67 GrOpsRenderPass* GrMockGpu::onGetOpsRenderPass(GrRenderTarget* rt,
68                                                bool /*useMSAASurface*/,
69                                                GrAttachment*,
70                                                GrSurfaceOrigin origin,
71                                                const SkIRect& bounds,
72                                                const GrOpsRenderPass::LoadAndStoreInfo& colorInfo,
73                                                const GrOpsRenderPass::StencilLoadAndStoreInfo&,
74                                                const TArray<GrSurfaceProxy*,true>& sampledProxies,
75                                                GrXferBarrierFlags renderPassXferBarriers) {
76     return new GrMockOpsRenderPass(this, rt, origin, colorInfo);
77 }
78 
submit(GrOpsRenderPass * renderPass)79 void GrMockGpu::submit(GrOpsRenderPass* renderPass) {
80     for (int i = 0; i < static_cast<GrMockOpsRenderPass*>(renderPass)->numDraws(); ++i) {
81         fStats.incNumDraws();
82     }
83     delete renderPass;
84 }
85 
GrMockGpu(GrDirectContext * direct,const GrMockOptions & options,const GrContextOptions & contextOptions)86 GrMockGpu::GrMockGpu(GrDirectContext* direct, const GrMockOptions& options,
87                      const GrContextOptions& contextOptions)
88         : INHERITED(direct)
89         , fMockOptions(options) {
90     this->initCaps(sk_make_sp<GrMockCaps>(contextOptions, options));
91 }
92 
~GrMockGpu()93 GrMockGpu::~GrMockGpu() {}
94 
pipelineBuilder()95 GrThreadSafePipelineBuilder* GrMockGpu::pipelineBuilder() {
96     return nullptr;
97 }
98 
refPipelineBuilder()99 sk_sp<GrThreadSafePipelineBuilder> GrMockGpu::refPipelineBuilder() {
100     return nullptr;
101 }
102 
onCreateTexture(SkISize dimensions,const GrBackendFormat & format,GrRenderable renderable,int renderTargetSampleCnt,skgpu::Budgeted budgeted,GrProtected isProtected,int mipLevelCount,uint32_t levelClearMask,std::string_view label)103 sk_sp<GrTexture> GrMockGpu::onCreateTexture(SkISize dimensions,
104                                             const GrBackendFormat& format,
105                                             GrRenderable renderable,
106                                             int renderTargetSampleCnt,
107                                             skgpu::Budgeted budgeted,
108                                             GrProtected isProtected,
109                                             int mipLevelCount,
110                                             uint32_t levelClearMask,
111                                             std::string_view label) {
112     if (fMockOptions.fFailTextureAllocations) {
113         return nullptr;
114     }
115 
116     // Compressed formats should go through onCreateCompressedTexture
117     SkASSERT(format.asMockCompressionType() == SkTextureCompressionType::kNone);
118 
119     GrColorType ct = format.asMockColorType();
120     SkASSERT(ct != GrColorType::kUnknown);
121 
122     GrMipmapStatus mipmapStatus =
123             mipLevelCount > 1 ? GrMipmapStatus::kDirty : GrMipmapStatus::kNotAllocated;
124     GrMockTextureInfo texInfo(ct, SkTextureCompressionType::kNone, NextInternalTextureID(),
125                               isProtected);
126     if (renderable == GrRenderable::kYes) {
127         GrMockRenderTargetInfo rtInfo(ct, NextInternalRenderTargetID(), isProtected);
128         return sk_sp<GrTexture>(new GrMockTextureRenderTarget(this, budgeted, dimensions,
129                                                               renderTargetSampleCnt,
130                                                               mipmapStatus,
131                                                               texInfo,
132                                                               rtInfo,
133                                                               label));
134     }
135     return sk_sp<GrTexture>(new GrMockTexture(
136             this, budgeted, dimensions, mipmapStatus, texInfo, label));
137 }
138 
139 // TODO: why no 'isProtected' ?!
onCreateCompressedTexture(SkISize dimensions,const GrBackendFormat & format,skgpu::Budgeted budgeted,skgpu::Mipmapped mipmapped,GrProtected isProtected,const void * data,size_t dataSize)140 sk_sp<GrTexture> GrMockGpu::onCreateCompressedTexture(SkISize dimensions,
141                                                       const GrBackendFormat& format,
142                                                       skgpu::Budgeted budgeted,
143                                                       skgpu::Mipmapped mipmapped,
144                                                       GrProtected isProtected,
145                                                       const void* data,
146                                                       size_t dataSize) {
147     if (fMockOptions.fFailTextureAllocations) {
148         return nullptr;
149     }
150 
151 #ifdef SK_DEBUG
152     // Uncompressed formats should go through onCreateTexture
153     SkTextureCompressionType compression = format.asMockCompressionType();
154     SkASSERT(compression != SkTextureCompressionType::kNone);
155 #endif
156 
157     GrMipmapStatus mipmapStatus = (mipmapped == skgpu::Mipmapped::kYes)
158                                           ? GrMipmapStatus::kValid
159                                           : GrMipmapStatus::kNotAllocated;
160     GrMockTextureInfo texInfo(GrColorType::kUnknown,
161                               format.asMockCompressionType(),
162                               NextInternalTextureID(),
163                               isProtected);
164 
165     return sk_sp<GrTexture>(new GrMockTexture(
166             this, budgeted, dimensions, mipmapStatus, texInfo,
167             /*label=*/"MockGpu_CreateCompressedTexture"));
168 }
169 
onWrapBackendTexture(const GrBackendTexture & tex,GrWrapOwnership ownership,GrWrapCacheable wrapType,GrIOType ioType)170 sk_sp<GrTexture> GrMockGpu::onWrapBackendTexture(const GrBackendTexture& tex,
171                                                  GrWrapOwnership ownership,
172                                                  GrWrapCacheable wrapType,
173                                                  GrIOType ioType) {
174     GrMockTextureInfo texInfo;
175     SkAssertResult(tex.getMockTextureInfo(&texInfo));
176 
177     SkTextureCompressionType compression = texInfo.compressionType();
178     if (compression != SkTextureCompressionType::kNone) {
179         return nullptr;
180     }
181 
182     GrMipmapStatus mipmapStatus = tex.hasMipmaps() ? GrMipmapStatus::kValid
183                                                    : GrMipmapStatus::kNotAllocated;
184     return sk_sp<GrTexture>(new GrMockTexture(this,
185                                               tex.dimensions(),
186                                               mipmapStatus,
187                                               texInfo,
188                                               wrapType,
189                                               ioType,
190                                               /*label=*/"MockGpu_WrapBackendTexture"));
191 }
192 
onWrapCompressedBackendTexture(const GrBackendTexture & tex,GrWrapOwnership ownership,GrWrapCacheable wrapType)193 sk_sp<GrTexture> GrMockGpu::onWrapCompressedBackendTexture(const GrBackendTexture& tex,
194                                                            GrWrapOwnership ownership,
195                                                            GrWrapCacheable wrapType) {
196     return nullptr;
197 }
198 
onWrapRenderableBackendTexture(const GrBackendTexture & tex,int sampleCnt,GrWrapOwnership ownership,GrWrapCacheable cacheable)199 sk_sp<GrTexture> GrMockGpu::onWrapRenderableBackendTexture(const GrBackendTexture& tex,
200                                                            int sampleCnt,
201                                                            GrWrapOwnership ownership,
202                                                            GrWrapCacheable cacheable) {
203     GrMockTextureInfo texInfo;
204     SkAssertResult(tex.getMockTextureInfo(&texInfo));
205     SkASSERT(texInfo.compressionType() == SkTextureCompressionType::kNone);
206 
207     GrMipmapStatus mipmapStatus =
208             tex.hasMipmaps() ? GrMipmapStatus::kValid : GrMipmapStatus::kNotAllocated;
209 
210     // The client gave us the texture ID but we supply the render target ID.
211     GrMockRenderTargetInfo rtInfo(texInfo.colorType(), NextInternalRenderTargetID(),
212                                   texInfo.getProtected());
213 
214     return sk_sp<GrTexture>(
215             new GrMockTextureRenderTarget(this,
216                                           tex.dimensions(),
217                                           sampleCnt,
218                                           mipmapStatus,
219                                           texInfo,
220                                           rtInfo,
221                                           cacheable,
222                                           /*label=*/"MockGpu_WrapRenderableBackendTexture"));
223 }
224 
onWrapBackendRenderTarget(const GrBackendRenderTarget & rt)225 sk_sp<GrRenderTarget> GrMockGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& rt) {
226     GrMockRenderTargetInfo info;
227     SkAssertResult(rt.getMockRenderTargetInfo(&info));
228 
229     return sk_sp<GrRenderTarget>(
230             new GrMockRenderTarget(this,
231                                    GrMockRenderTarget::kWrapped,
232                                    rt.dimensions(),
233                                    rt.sampleCnt(),
234                                    info,
235                                    /*label=*/"MockGpu_WrapBackendRenderTarget"));
236 }
237 
onCreateBuffer(size_t sizeInBytes,GrGpuBufferType type,GrAccessPattern accessPattern)238 sk_sp<GrGpuBuffer> GrMockGpu::onCreateBuffer(size_t sizeInBytes,
239                                              GrGpuBufferType type,
240                                              GrAccessPattern accessPattern) {
241     return sk_sp<GrGpuBuffer>(
242             new GrMockBuffer(this, sizeInBytes, type, accessPattern,
243                              /*label=*/"MockGpu_CreateBuffer"));
244 }
245 
makeStencilAttachment(const GrBackendFormat &,SkISize dimensions,int numStencilSamples)246 sk_sp<GrAttachment> GrMockGpu::makeStencilAttachment(const GrBackendFormat& /*colorFormat*/,
247                                                      SkISize dimensions, int numStencilSamples) {
248     fStats.incStencilAttachmentCreates();
249     return sk_sp<GrAttachment>(new GrMockAttachment(this,
250                                                     dimensions,
251                                                     GrAttachment::UsageFlags::kStencilAttachment,
252                                                     numStencilSamples,
253                                                     /*label=*/"MockGpu_MakeStencilAttachment"));
254 }
255 
onCreateBackendTexture(SkISize dimensions,const GrBackendFormat & format,GrRenderable,skgpu::Mipmapped mipmapped,GrProtected isProtected,std::string_view label)256 GrBackendTexture GrMockGpu::onCreateBackendTexture(SkISize dimensions,
257                                                    const GrBackendFormat& format,
258                                                    GrRenderable,
259                                                    skgpu::Mipmapped mipmapped,
260                                                    GrProtected isProtected,
261                                                    std::string_view label) {
262     SkTextureCompressionType compression = format.asMockCompressionType();
263     if (compression != SkTextureCompressionType::kNone) {
264         return {}; // should go through onCreateCompressedBackendTexture
265     }
266 
267     auto colorType = format.asMockColorType();
268     if (!this->caps()->isFormatTexturable(format, GrTextureType::k2D)) {
269         return GrBackendTexture();  // invalid
270     }
271 
272     GrMockTextureInfo info(colorType, SkTextureCompressionType::kNone, NextExternalTextureID(),
273                            isProtected);
274 
275     fOutstandingTestingOnlyTextureIDs.add(info.id());
276     return GrBackendTexture(dimensions.width(), dimensions.height(), mipmapped, info);
277 }
278 
onCreateCompressedBackendTexture(SkISize dimensions,const GrBackendFormat & format,skgpu::Mipmapped mipmapped,GrProtected isProtected)279 GrBackendTexture GrMockGpu::onCreateCompressedBackendTexture(SkISize dimensions,
280                                                              const GrBackendFormat& format,
281                                                              skgpu::Mipmapped mipmapped,
282                                                              GrProtected isProtected) {
283     SkTextureCompressionType compression = format.asMockCompressionType();
284     if (compression == SkTextureCompressionType::kNone) {
285         return {}; // should go through onCreateBackendTexture
286     }
287 
288     if (!this->caps()->isFormatTexturable(format, GrTextureType::k2D)) {
289         return {};
290     }
291 
292     GrMockTextureInfo info(GrColorType::kUnknown, compression, NextExternalTextureID(),
293                            isProtected);
294 
295     fOutstandingTestingOnlyTextureIDs.add(info.id());
296     return GrBackendTexture(dimensions.width(), dimensions.height(), mipmapped, info);
297 }
298 
deleteBackendTexture(const GrBackendTexture & tex)299 void GrMockGpu::deleteBackendTexture(const GrBackendTexture& tex) {
300     SkASSERT(GrBackendApi::kMock == tex.backend());
301 
302     GrMockTextureInfo info;
303     if (tex.getMockTextureInfo(&info)) {
304         fOutstandingTestingOnlyTextureIDs.remove(info.id());
305     }
306 }
307 
308 #if defined(GPU_TEST_UTILS)
isTestingOnlyBackendTexture(const GrBackendTexture & tex) const309 bool GrMockGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
310     SkASSERT(GrBackendApi::kMock == tex.backend());
311 
312     GrMockTextureInfo info;
313     if (!tex.getMockTextureInfo(&info)) {
314         return false;
315     }
316 
317     return fOutstandingTestingOnlyTextureIDs.contains(info.id());
318 }
319 
createTestingOnlyBackendRenderTarget(SkISize dimensions,GrColorType colorType,int sampleCnt,GrProtected isProtected)320 GrBackendRenderTarget GrMockGpu::createTestingOnlyBackendRenderTarget(SkISize dimensions,
321                                                                       GrColorType colorType,
322                                                                       int sampleCnt,
323                                                                       GrProtected isProtected) {
324     GrMockRenderTargetInfo info(colorType, NextExternalRenderTargetID(), isProtected);
325     static constexpr int kStencilBits = 8;
326     return GrBackendRenderTarget(dimensions.width(), dimensions.height(), sampleCnt, kStencilBits,
327                                  info);
328 }
329 
deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget &)330 void GrMockGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) {}
331 #endif
332