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 "GrMockGpu.h"
9 #include "GrMockBuffer.h"
10 #include "GrMockCaps.h"
11 #include "GrMockGpuCommandBuffer.h"
12 #include "GrMockStencilAttachment.h"
13 #include "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
onCreateTexture(const GrSurfaceDesc & desc,SkBudgeted budgeted,const GrMipLevel texels[],int mipLevelCount)88 sk_sp<GrTexture> GrMockGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
89 const GrMipLevel texels[], int mipLevelCount) {
90 if (fMockOptions.fFailTextureAllocations) {
91 return nullptr;
92 }
93
94 GrMipMapsStatus mipMapsStatus = mipLevelCount > 1 ? GrMipMapsStatus::kValid
95 : GrMipMapsStatus::kNotAllocated;
96 GrMockTextureInfo texInfo;
97 texInfo.fConfig = desc.fConfig;
98 texInfo.fID = NextInternalTextureID();
99 if (desc.fFlags & kRenderTarget_GrSurfaceFlag) {
100 GrMockRenderTargetInfo rtInfo;
101 rtInfo.fConfig = desc.fConfig;
102 rtInfo.fID = NextInternalRenderTargetID();
103 return sk_sp<GrTexture>(new GrMockTextureRenderTarget(this, budgeted, desc, mipMapsStatus,
104 texInfo, rtInfo));
105 }
106 return sk_sp<GrTexture>(new GrMockTexture(this, budgeted, desc, mipMapsStatus, texInfo));
107 }
108
onWrapBackendTexture(const GrBackendTexture & tex,GrWrapOwnership ownership,GrWrapCacheable wrapType,GrIOType ioType)109 sk_sp<GrTexture> GrMockGpu::onWrapBackendTexture(const GrBackendTexture& tex,
110 GrWrapOwnership ownership,
111 GrWrapCacheable wrapType, GrIOType ioType) {
112 GrSurfaceDesc desc;
113 desc.fWidth = tex.width();
114 desc.fHeight = tex.height();
115
116 GrMockTextureInfo info;
117 SkAssertResult(tex.getMockTextureInfo(&info));
118 desc.fConfig = info.fConfig;
119
120 GrMipMapsStatus mipMapsStatus = tex.hasMipMaps() ? GrMipMapsStatus::kValid
121 : GrMipMapsStatus::kNotAllocated;
122
123 return sk_sp<GrTexture>(new GrMockTexture(this, desc, mipMapsStatus, info, wrapType, ioType));
124 }
125
onWrapRenderableBackendTexture(const GrBackendTexture & tex,int sampleCnt,GrWrapOwnership ownership,GrWrapCacheable cacheable)126 sk_sp<GrTexture> GrMockGpu::onWrapRenderableBackendTexture(const GrBackendTexture& tex,
127 int sampleCnt,
128 GrWrapOwnership ownership,
129 GrWrapCacheable cacheable) {
130 GrSurfaceDesc desc;
131 desc.fFlags = kRenderTarget_GrSurfaceFlag;
132 desc.fWidth = tex.width();
133 desc.fHeight = tex.height();
134
135 GrMockTextureInfo texInfo;
136 SkAssertResult(tex.getMockTextureInfo(&texInfo));
137 desc.fConfig = texInfo.fConfig;
138
139 GrMipMapsStatus mipMapsStatus =
140 tex.hasMipMaps() ? GrMipMapsStatus::kValid : GrMipMapsStatus::kNotAllocated;
141
142 GrMockRenderTargetInfo rtInfo;
143 rtInfo.fConfig = texInfo.fConfig;
144 // The client gave us the texture ID but we supply the render target ID.
145 rtInfo.fID = NextInternalRenderTargetID();
146
147 return sk_sp<GrTexture>(
148 new GrMockTextureRenderTarget(this, desc, mipMapsStatus, texInfo, rtInfo, cacheable));
149 }
150
onWrapBackendRenderTarget(const GrBackendRenderTarget & rt)151 sk_sp<GrRenderTarget> GrMockGpu::onWrapBackendRenderTarget(const GrBackendRenderTarget& rt) {
152 GrSurfaceDesc desc;
153 desc.fFlags = kRenderTarget_GrSurfaceFlag;
154 desc.fWidth = rt.width();
155 desc.fHeight = rt.height();
156
157 GrMockRenderTargetInfo info;
158 SkAssertResult(rt.getMockRenderTargetInfo(&info));
159 desc.fConfig = info.fConfig;
160
161 return sk_sp<GrRenderTarget>(
162 new GrMockRenderTarget(this, GrMockRenderTarget::kWrapped, desc, info));
163 }
164
onWrapBackendTextureAsRenderTarget(const GrBackendTexture & tex,int sampleCnt)165 sk_sp<GrRenderTarget> GrMockGpu::onWrapBackendTextureAsRenderTarget(const GrBackendTexture& tex,
166 int sampleCnt) {
167 GrSurfaceDesc desc;
168 desc.fFlags = kRenderTarget_GrSurfaceFlag;
169 desc.fWidth = tex.width();
170 desc.fHeight = tex.height();
171
172 GrMockTextureInfo texInfo;
173 SkAssertResult(tex.getMockTextureInfo(&texInfo));
174 desc.fConfig = texInfo.fConfig;
175 desc.fSampleCnt = sampleCnt;
176
177 GrMockRenderTargetInfo rtInfo;
178 rtInfo.fConfig = texInfo.fConfig;
179 // The client gave us the texture ID but we supply the render target ID.
180 rtInfo.fID = NextInternalRenderTargetID();
181
182 return sk_sp<GrRenderTarget>(
183 new GrMockRenderTarget(this, GrMockRenderTarget::kWrapped, desc, rtInfo));
184 }
185
onCreateBuffer(size_t sizeInBytes,GrBufferType type,GrAccessPattern accessPattern,const void *)186 sk_sp<GrBuffer> GrMockGpu::onCreateBuffer(size_t sizeInBytes, GrBufferType type,
187 GrAccessPattern accessPattern, const void*) {
188 return sk_sp<GrBuffer>(new GrMockBuffer(this, sizeInBytes, type, accessPattern));
189 }
190
createStencilAttachmentForRenderTarget(const GrRenderTarget * rt,int width,int height)191 GrStencilAttachment* GrMockGpu::createStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
192 int width,
193 int height) {
194 static constexpr int kBits = 8;
195 fStats.incStencilAttachmentCreates();
196 return new GrMockStencilAttachment(this, width, height, kBits, rt->numColorSamples());
197 }
198
199 #if GR_TEST_UTILS
createTestingOnlyBackendTexture(const void * pixels,int w,int h,GrColorType colorType,bool isRT,GrMipMapped mipMapped,size_t rowBytes)200 GrBackendTexture GrMockGpu::createTestingOnlyBackendTexture(const void* pixels, int w, int h,
201 GrColorType colorType, bool isRT,
202 GrMipMapped mipMapped,
203 size_t rowBytes) {
204
205 GrPixelConfig config = GrColorTypeToPixelConfig(colorType, GrSRGBEncoded::kNo);
206 if (!this->caps()->isConfigTexturable(config)) {
207 return GrBackendTexture(); // invalid
208 }
209
210 GrMockTextureInfo info;
211 info.fConfig = config;
212 info.fID = NextExternalTextureID();
213 fOutstandingTestingOnlyTextureIDs.add(info.fID);
214 return GrBackendTexture(w, h, mipMapped, info);
215 }
216
isTestingOnlyBackendTexture(const GrBackendTexture & tex) const217 bool GrMockGpu::isTestingOnlyBackendTexture(const GrBackendTexture& tex) const {
218 SkASSERT(GrBackendApi::kMock == tex.backend());
219
220 GrMockTextureInfo info;
221 if (!tex.getMockTextureInfo(&info)) {
222 return false;
223 }
224
225 return fOutstandingTestingOnlyTextureIDs.contains(info.fID);
226 }
227
deleteTestingOnlyBackendTexture(const GrBackendTexture & tex)228 void GrMockGpu::deleteTestingOnlyBackendTexture(const GrBackendTexture& tex) {
229 SkASSERT(GrBackendApi::kMock == tex.backend());
230
231 GrMockTextureInfo info;
232 if (tex.getMockTextureInfo(&info)) {
233 fOutstandingTestingOnlyTextureIDs.remove(info.fID);
234 }
235 }
236
createTestingOnlyBackendRenderTarget(int w,int h,GrColorType colorType)237 GrBackendRenderTarget GrMockGpu::createTestingOnlyBackendRenderTarget(int w, int h,
238 GrColorType colorType) {
239 auto config = GrColorTypeToPixelConfig(colorType, GrSRGBEncoded::kNo);
240 if (kUnknown_GrPixelConfig == config) {
241 return {};
242 }
243 GrMockRenderTargetInfo info = {config, NextExternalRenderTargetID()};
244 static constexpr int kSampleCnt = 1;
245 static constexpr int kStencilBits = 8;
246 return {w, h, kSampleCnt, kStencilBits, info};
247 }
248
deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget &)249 void GrMockGpu::deleteTestingOnlyBackendRenderTarget(const GrBackendRenderTarget&) {}
250 #endif
251