• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
8 #include "src/gpu/mock/GrMockBuffer.h"
9 #include "src/gpu/mock/GrMockCaps.h"
10 #include "src/gpu/mock/GrMockGpu.h"
11 #include "src/gpu/mock/GrMockGpuCommandBuffer.h"
12 #include "src/gpu/mock/GrMockStencilAttachment.h"
13 #include "src/gpu/mock/GrMockTexture.h"
14 #include <atomic>
15 
NextInternalTextureID()16 int GrMockGpu::NextInternalTextureID() {
17     static std::atomic<int> nextID{1};
18     int id;
19     do {
20         id = nextID.fetch_add(1);
21     } while (0 == id);  // Reserve 0 for an invalid ID.
22     return id;
23 }
24 
NextExternalTextureID()25 int GrMockGpu::NextExternalTextureID() {
26     // We use negative ints for the "testing only external textures" so they can easily be
27     // identified when debugging.
28     static std::atomic<int> nextID{-1};
29     return nextID--;
30 }
31 
NextInternalRenderTargetID()32 int GrMockGpu::NextInternalRenderTargetID() {
33     // We start off with large numbers to differentiate from texture IDs, even though they're
34     // technically in a different space.
35     static std::atomic<int> nextID{SK_MaxS32};
36     return nextID--;
37 }
38 
NextExternalRenderTargetID()39 int GrMockGpu::NextExternalRenderTargetID() {
40     // We use large negative ints for the "testing only external render targets" so they can easily
41     // be identified when debugging.
42     static std::atomic<int> nextID{SK_MinS32};
43     return nextID++;
44 }
45 
Make(const GrMockOptions * mockOptions,const GrContextOptions & contextOptions,GrContext * context)46 sk_sp<GrGpu> GrMockGpu::Make(const GrMockOptions* mockOptions,
47                              const GrContextOptions& contextOptions, GrContext* context) {
48     static const GrMockOptions kDefaultOptions = GrMockOptions();
49     if (!mockOptions) {
50         mockOptions = &kDefaultOptions;
51     }
52     return sk_sp<GrGpu>(new GrMockGpu(context, *mockOptions, contextOptions));
53 }
54 
getCommandBuffer(GrRenderTarget * rt,GrSurfaceOrigin origin,const SkRect & bounds,const GrGpuRTCommandBuffer::LoadAndStoreInfo &,const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo &)55 GrGpuRTCommandBuffer* GrMockGpu::getCommandBuffer(
56                                 GrRenderTarget* rt, GrSurfaceOrigin origin, const SkRect& bounds,
57                                 const GrGpuRTCommandBuffer::LoadAndStoreInfo&,
58                                 const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo&) {
59     return new GrMockGpuRTCommandBuffer(this, rt, origin);
60 }
61 
getCommandBuffer(GrTexture * texture,GrSurfaceOrigin origin)62 GrGpuTextureCommandBuffer* GrMockGpu::getCommandBuffer(GrTexture* texture, GrSurfaceOrigin origin) {
63     return new GrMockGpuTextureCommandBuffer(texture, origin);
64 }
65 
submit(GrGpuCommandBuffer * buffer)66 void GrMockGpu::submit(GrGpuCommandBuffer* buffer) {
67     if (buffer->asRTCommandBuffer()) {
68         this->submitCommandBuffer(
69                         static_cast<GrMockGpuRTCommandBuffer*>(buffer->asRTCommandBuffer()));
70     }
71 
72     delete buffer;
73 }
74 
submitCommandBuffer(const GrMockGpuRTCommandBuffer * cmdBuffer)75 void GrMockGpu::submitCommandBuffer(const GrMockGpuRTCommandBuffer* cmdBuffer) {
76     for (int i = 0; i < cmdBuffer->numDraws(); ++i) {
77         fStats.incNumDraws();
78     }
79 }
80 
GrMockGpu(GrContext * context,const GrMockOptions & options,const GrContextOptions & contextOptions)81 GrMockGpu::GrMockGpu(GrContext* context, const GrMockOptions& options,
82                      const GrContextOptions& contextOptions)
83         : INHERITED(context)
84         , fMockOptions(options) {
85     fCaps.reset(new GrMockCaps(contextOptions, options));
86 }
87 
querySampleLocations(GrRenderTarget * rt,SkTArray<SkPoint> * sampleLocations)88 void GrMockGpu::querySampleLocations(GrRenderTarget* rt, SkTArray<SkPoint>* sampleLocations) {
89     sampleLocations->reset();
90     int numRemainingSamples = rt->numSamples();
91     while (numRemainingSamples > 0) {
92         // Use standard D3D sample locations.
93         switch (numRemainingSamples) {
94             case 0:
95             case 1:
96                 sampleLocations->push_back().set(.5, .5);
97                 break;
98             case 2:
99                 sampleLocations->push_back().set(.75, .75);
100                 sampleLocations->push_back().set(.25, .25);
101                 break;
102             case 3:
103             case 4:
104                 sampleLocations->push_back().set(.375, .125);
105                 sampleLocations->push_back().set(.875, .375);
106                 sampleLocations->push_back().set(.125, .625);
107                 sampleLocations->push_back().set(.625, .875);
108                 break;
109             case 5:
110             case 6:
111             case 7:
112             case 8:
113                 sampleLocations->push_back().set(.5625, .3125);
114                 sampleLocations->push_back().set(.4375, .6875);
115                 sampleLocations->push_back().set(.8125, .5625);
116                 sampleLocations->push_back().set(.3125, .1875);
117                 sampleLocations->push_back().set(.1875, .8125);
118                 sampleLocations->push_back().set(.0625, .4375);
119                 sampleLocations->push_back().set(.6875, .4375);
120                 sampleLocations->push_back().set(.4375, .0625);
121                 break;
122             default:
123                 sampleLocations->push_back().set(.5625, .5625);
124                 sampleLocations->push_back().set(.4375, .3125);
125                 sampleLocations->push_back().set(.3125, .6250);
126                 sampleLocations->push_back().set(.2500, .4375);
127                 sampleLocations->push_back().set(.1875, .3750);
128                 sampleLocations->push_back().set(.6250, .8125);
129                 sampleLocations->push_back().set(.8125, .6875);
130                 sampleLocations->push_back().set(.6875, .1875);
131                 sampleLocations->push_back().set(.3750, .8750);
132                 sampleLocations->push_back().set(.5000, .0625);
133                 sampleLocations->push_back().set(.2500, .1250);
134                 sampleLocations->push_back().set(.1250, .2500);
135                 sampleLocations->push_back().set(.0000, .5000);
136                 sampleLocations->push_back().set(.4375, .2500);
137                 sampleLocations->push_back().set(.8750, .4375);
138                 sampleLocations->push_back().set(.0625, .0000);
139                 break;
140         }
141         numRemainingSamples = rt->numSamples() - sampleLocations->count();
142     }
143 }
144 
onCreateTexture(const GrSurfaceDesc & desc,const GrBackendFormat & format,GrRenderable renderable,int renderTargetSampleCnt,SkBudgeted budgeted,GrProtected isProtected,const GrMipLevel texels[],int mipLevelCount)145 sk_sp<GrTexture> GrMockGpu::onCreateTexture(const GrSurfaceDesc& desc,
146                                             const GrBackendFormat& format,
147                                             GrRenderable renderable,
148                                             int renderTargetSampleCnt,
149                                             SkBudgeted budgeted,
150                                             GrProtected isProtected,
151                                             const GrMipLevel texels[],
152                                             int mipLevelCount) {
153     if (fMockOptions.fFailTextureAllocations) {
154         return nullptr;
155     }
156 
157     GrColorType ct = format.asMockColorType();
158     SkASSERT(ct != GrColorType::kUnknown);
159 
160     GrMipMapsStatus mipMapsStatus = mipLevelCount > 1 ? GrMipMapsStatus::kValid
161                                                       : GrMipMapsStatus::kNotAllocated;
162     GrMockTextureInfo texInfo(ct, NextInternalTextureID());
163     if (renderable == GrRenderable::kYes) {
164         GrMockRenderTargetInfo rtInfo(ct, NextInternalRenderTargetID());
165         return sk_sp<GrTexture>(new GrMockTextureRenderTarget(this, budgeted, desc,
166                                                               renderTargetSampleCnt, isProtected,
167                                                               mipMapsStatus, texInfo, rtInfo));
168     }
169     return sk_sp<GrTexture>(
170             new GrMockTexture(this, budgeted, desc, isProtected, mipMapsStatus, texInfo));
171 }
172 
onCreateCompressedTexture(int width,int height,const GrBackendFormat &,SkImage::CompressionType compressionType,SkBudgeted budgeted,const void * data)173 sk_sp<GrTexture> GrMockGpu::onCreateCompressedTexture(int width, int height, const GrBackendFormat&,
174                                                       SkImage::CompressionType compressionType,
175                                                       SkBudgeted budgeted, const void* data) {
176     return nullptr;
177 }
178 
onWrapBackendTexture(const GrBackendTexture & tex,GrColorType colorType,GrWrapOwnership ownership,GrWrapCacheable wrapType,GrIOType ioType)179 sk_sp<GrTexture> GrMockGpu::onWrapBackendTexture(const GrBackendTexture& tex, GrColorType colorType,
180                                                  GrWrapOwnership ownership,
181                                                  GrWrapCacheable wrapType, GrIOType ioType) {
182     GrMockTextureInfo texInfo;
183     SkAssertResult(tex.getMockTextureInfo(&texInfo));
184 
185     SkASSERT(colorType == texInfo.fColorType);
186     GrSurfaceDesc desc;
187     desc.fWidth = tex.width();
188     desc.fHeight = tex.height();
189     desc.fConfig = texInfo.pixelConfig();
190 
191     GrMipMapsStatus mipMapsStatus = tex.hasMipMaps() ? GrMipMapsStatus::kValid
192                                                      : GrMipMapsStatus::kNotAllocated;
193     auto isProtected = GrProtected(tex.isProtected());
194     return sk_sp<GrTexture>(
195             new GrMockTexture(this, desc, isProtected, mipMapsStatus, texInfo, wrapType, ioType));
196 }
197 
onWrapRenderableBackendTexture(const GrBackendTexture & tex,int sampleCnt,GrColorType colorType,GrWrapOwnership ownership,GrWrapCacheable cacheable)198 sk_sp<GrTexture> GrMockGpu::onWrapRenderableBackendTexture(const GrBackendTexture& tex,
199                                                            int sampleCnt,
200                                                            GrColorType colorType,
201                                                            GrWrapOwnership ownership,
202                                                            GrWrapCacheable cacheable) {
203     GrMockTextureInfo texInfo;
204     SkAssertResult(tex.getMockTextureInfo(&texInfo));
205 
206     SkASSERT(colorType == texInfo.fColorType);
207     GrSurfaceDesc desc;
208     desc.fWidth = tex.width();
209     desc.fHeight = tex.height();
210     desc.fConfig = texInfo.pixelConfig();
211 
212     GrMipMapsStatus mipMapsStatus =
213             tex.hasMipMaps() ? GrMipMapsStatus::kValid : GrMipMapsStatus::kNotAllocated;
214 
215     // The client gave us the texture ID but we supply the render target ID.
216     GrMockRenderTargetInfo rtInfo(texInfo.fColorType, NextInternalRenderTargetID());
217 
218     auto isProtected = GrProtected(tex.isProtected());
219     return sk_sp<GrTexture>(new GrMockTextureRenderTarget(
220             this, desc, sampleCnt, isProtected, mipMapsStatus, texInfo, rtInfo, cacheable));
221 }
222 
onWrapBackendRenderTarget(const GrBackendRenderTarget & rt,GrColorType colorType)223 sk_sp<GrRenderTarget> GrMockGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& rt,
224                                                            GrColorType colorType) {
225     GrMockRenderTargetInfo info;
226     SkAssertResult(rt.getMockRenderTargetInfo(&info));
227 
228     SkASSERT(colorType == info.colorType());
229     GrSurfaceDesc desc;
230     desc.fWidth = rt.width();
231     desc.fHeight = rt.height();
232     desc.fConfig = info.pixelConfig();
233 
234     auto isProtected = GrProtected(rt.isProtected());
235     return sk_sp<GrRenderTarget>(new GrMockRenderTarget(this, GrMockRenderTarget::kWrapped, desc,
236                                                         rt.sampleCnt(), isProtected, info));
237 }
238 
onWrapBackendTextureAsRenderTarget(const GrBackendTexture & tex,int sampleCnt,GrColorType colorType)239 sk_sp<GrRenderTarget> GrMockGpu::onWrapBackendTextureAsRenderTarget(const GrBackendTexture& tex,
240                                                                     int sampleCnt,
241                                                                     GrColorType colorType) {
242     GrMockTextureInfo texInfo;
243     SkAssertResult(tex.getMockTextureInfo(&texInfo));
244 
245     SkASSERT(colorType == texInfo.fColorType);
246     GrSurfaceDesc desc;
247     desc.fWidth = tex.width();
248     desc.fHeight = tex.height();
249     desc.fConfig = texInfo.pixelConfig();
250 
251     // The client gave us the texture ID but we supply the render target ID.
252     GrMockRenderTargetInfo rtInfo(texInfo.fColorType, NextInternalRenderTargetID());
253 
254     auto isProtected = GrProtected(tex.isProtected());
255     return sk_sp<GrRenderTarget>(new GrMockRenderTarget(this, GrMockRenderTarget::kWrapped, desc,
256                                                         sampleCnt, isProtected, rtInfo));
257 }
258 
onCreateBuffer(size_t sizeInBytes,GrGpuBufferType type,GrAccessPattern accessPattern,const void *)259 sk_sp<GrGpuBuffer> GrMockGpu::onCreateBuffer(size_t sizeInBytes, GrGpuBufferType type,
260                                              GrAccessPattern accessPattern, const void*) {
261     return sk_sp<GrGpuBuffer>(new GrMockBuffer(this, sizeInBytes, type, accessPattern));
262 }
263 
createStencilAttachmentForRenderTarget(const GrRenderTarget * rt,int width,int height,int numStencilSamples)264 GrStencilAttachment* GrMockGpu::createStencilAttachmentForRenderTarget(
265         const GrRenderTarget* rt, int width, int height, int numStencilSamples) {
266     SkASSERT(numStencilSamples == rt->numSamples());
267     static constexpr int kBits = 8;
268     fStats.incStencilAttachmentCreates();
269     return new GrMockStencilAttachment(this, width, height, kBits, rt->numSamples());
270 }
271 
createBackendTexture(int w,int h,const GrBackendFormat & format,GrMipMapped mipMapped,GrRenderable,const void *,size_t,const SkColor4f *,GrProtected)272 GrBackendTexture GrMockGpu::createBackendTexture(int w, int h,
273                                                  const GrBackendFormat& format,
274                                                  GrMipMapped mipMapped,
275                                                  GrRenderable /* renderable */,
276                                                  const void* /* pixels */,
277                                                  size_t /* rowBytes */,
278                                                  const SkColor4f* /* color */,
279                                                  GrProtected /* isProtected */) {
280     auto colorType = format.asMockColorType();
281     if (!this->caps()->isFormatTexturable(format)) {
282         return GrBackendTexture();  // invalid
283     }
284 
285     GrMockTextureInfo info(colorType, NextExternalTextureID());
286 
287     fOutstandingTestingOnlyTextureIDs.add(info.fID);
288     return GrBackendTexture(w, h, mipMapped, info);
289 }
290 
deleteBackendTexture(const GrBackendTexture & tex)291 void GrMockGpu::deleteBackendTexture(const GrBackendTexture& tex) {
292     SkASSERT(GrBackendApi::kMock == tex.backend());
293 
294     GrMockTextureInfo info;
295     if (tex.getMockTextureInfo(&info)) {
296         fOutstandingTestingOnlyTextureIDs.remove(info.fID);
297     }
298 }
299 
300 #if GR_TEST_UTILS
isTestingOnlyBackendTexture(const GrBackendTexture & tex) const301 bool GrMockGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
302     SkASSERT(GrBackendApi::kMock == tex.backend());
303 
304     GrMockTextureInfo info;
305     if (!tex.getMockTextureInfo(&info)) {
306         return false;
307     }
308 
309     return fOutstandingTestingOnlyTextureIDs.contains(info.fID);
310 }
311 
createTestingOnlyBackendRenderTarget(int w,int h,GrColorType colorType)312 GrBackendRenderTarget GrMockGpu::createTestingOnlyBackendRenderTarget(int w, int h,
313                                                                       GrColorType colorType) {
314     GrMockRenderTargetInfo info(colorType, NextExternalRenderTargetID());
315     static constexpr int kSampleCnt = 1;
316     static constexpr int kStencilBits = 8;
317     return GrBackendRenderTarget(w, h, kSampleCnt, kStencilBits, info);
318 }
319 
deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget &)320 void GrMockGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) {}
321 #endif
322