• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2013 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 "GrTest.h"
9 #include <algorithm>
10 #include "GrBackendSurface.h"
11 #include "GrContextOptions.h"
12 #include "GrContextPriv.h"
13 #include "GrDrawOpAtlas.h"
14 #include "GrDrawingManager.h"
15 #include "GrGpu.h"
16 #include "GrGpuResourceCacheAccess.h"
17 #include "GrRenderTargetContext.h"
18 #include "GrRenderTargetContextPriv.h"
19 #include "GrRenderTargetProxy.h"
20 #include "GrResourceCache.h"
21 #include "GrSemaphore.h"
22 #include "GrSurfaceContextPriv.h"
23 #include "GrTexture.h"
24 #include "SkGr.h"
25 #include "SkImage_Gpu.h"
26 #include "SkMathPriv.h"
27 #include "SkString.h"
28 #include "ops/GrMeshDrawOp.h"
29 #include "text/GrAtlasGlyphCache.h"
30 #include "text/GrTextBlobCache.h"
31 
32 namespace GrTest {
33 
SetupAlwaysEvictAtlas(GrContext * context)34 void SetupAlwaysEvictAtlas(GrContext* context) {
35     // These sizes were selected because they allow each atlas to hold a single plot and will thus
36     // stress the atlas
37     int dim = GrDrawOpAtlas::kGlyphMaxDim;
38     GrDrawOpAtlasConfig configs[3];
39     configs[kA8_GrMaskFormat].fWidth = dim;
40     configs[kA8_GrMaskFormat].fHeight = dim;
41     configs[kA8_GrMaskFormat].fPlotWidth = dim;
42     configs[kA8_GrMaskFormat].fPlotHeight = dim;
43 
44     configs[kA565_GrMaskFormat].fWidth = dim;
45     configs[kA565_GrMaskFormat].fHeight = dim;
46     configs[kA565_GrMaskFormat].fPlotWidth = dim;
47     configs[kA565_GrMaskFormat].fPlotHeight = dim;
48 
49     configs[kARGB_GrMaskFormat].fWidth = dim;
50     configs[kARGB_GrMaskFormat].fHeight = dim;
51     configs[kARGB_GrMaskFormat].fPlotWidth = dim;
52     configs[kARGB_GrMaskFormat].fPlotHeight = dim;
53 
54     context->setTextContextAtlasSizes_ForTesting(configs);
55 }
56 
CreateBackendTexture(GrBackend backend,int width,int height,GrPixelConfig config,GrMipMapped mipMapped,GrBackendObject handle)57 GrBackendTexture CreateBackendTexture(GrBackend backend, int width, int height,
58                                       GrPixelConfig config, GrMipMapped mipMapped,
59                                       GrBackendObject handle) {
60     switch (backend) {
61 #ifdef SK_VULKAN
62         case kVulkan_GrBackend: {
63             GrVkImageInfo* vkInfo = (GrVkImageInfo*)(handle);
64             SkASSERT((GrMipMapped::kYes == mipMapped) == (vkInfo->fLevelCount > 1));
65             return GrBackendTexture(width, height, *vkInfo);
66         }
67 #endif
68         case kOpenGL_GrBackend: {
69             GrGLTextureInfo* glInfo = (GrGLTextureInfo*)(handle);
70             SkASSERT(glInfo->fFormat);
71             return GrBackendTexture(width, height, mipMapped, *glInfo);
72         }
73         case kMock_GrBackend: {
74             GrMockTextureInfo* mockInfo = (GrMockTextureInfo*)(handle);
75             return GrBackendTexture(width, height, config, mipMapped, *mockInfo);
76         }
77         default:
78             return GrBackendTexture();
79     }
80 }
81 
82 }  // namespace GrTest
83 
isWrapped_ForTesting() const84 bool GrSurfaceProxy::isWrapped_ForTesting() const {
85     return SkToBool(fTarget);
86 }
87 
isWrapped_ForTesting() const88 bool GrRenderTargetContext::isWrapped_ForTesting() const {
89     return fRenderTargetProxy->isWrapped_ForTesting();
90 }
91 
setTextBlobCacheLimit_ForTesting(size_t bytes)92 void GrContext::setTextBlobCacheLimit_ForTesting(size_t bytes) {
93     fTextBlobCache->setBudget(bytes);
94 }
95 
setTextContextAtlasSizes_ForTesting(const GrDrawOpAtlasConfig * configs)96 void GrContext::setTextContextAtlasSizes_ForTesting(const GrDrawOpAtlasConfig* configs) {
97     fAtlasGlyphCache->setAtlasSizes_ForTesting(configs);
98 }
99 
100 ///////////////////////////////////////////////////////////////////////////////
101 
purgeAllUnlockedResources()102 void GrContext::purgeAllUnlockedResources() {
103     fResourceCache->purgeAllUnlocked();
104 }
105 
resetGpuStats() const106 void GrContext::resetGpuStats() const {
107 #if GR_GPU_STATS
108     fGpu->stats()->reset();
109 #endif
110 }
111 
dumpCacheStats(SkString * out) const112 void GrContext::dumpCacheStats(SkString* out) const {
113 #if GR_CACHE_STATS
114     fResourceCache->dumpStats(out);
115 #endif
116 }
117 
dumpCacheStatsKeyValuePairs(SkTArray<SkString> * keys,SkTArray<double> * values) const118 void GrContext::dumpCacheStatsKeyValuePairs(SkTArray<SkString>* keys,
119                                             SkTArray<double>* values) const {
120 #if GR_CACHE_STATS
121     fResourceCache->dumpStatsKeyValuePairs(keys, values);
122 #endif
123 }
124 
printCacheStats() const125 void GrContext::printCacheStats() const {
126     SkString out;
127     this->dumpCacheStats(&out);
128     SkDebugf("%s", out.c_str());
129 }
130 
dumpGpuStats(SkString * out) const131 void GrContext::dumpGpuStats(SkString* out) const {
132 #if GR_GPU_STATS
133     return fGpu->stats()->dump(out);
134 #endif
135 }
136 
dumpGpuStatsKeyValuePairs(SkTArray<SkString> * keys,SkTArray<double> * values) const137 void GrContext::dumpGpuStatsKeyValuePairs(SkTArray<SkString>* keys,
138                                           SkTArray<double>* values) const {
139 #if GR_GPU_STATS
140     return fGpu->stats()->dumpKeyValuePairs(keys, values);
141 #endif
142 }
143 
printGpuStats() const144 void GrContext::printGpuStats() const {
145     SkString out;
146     this->dumpGpuStats(&out);
147     SkDebugf("%s", out.c_str());
148 }
149 
getFontAtlasImage_ForTesting(GrMaskFormat format,uint32_t index)150 sk_sp<SkImage> GrContext::getFontAtlasImage_ForTesting(GrMaskFormat format, uint32_t index) {
151     GrAtlasGlyphCache* cache = this->contextPriv().getAtlasGlyphCache();
152 
153     const sk_sp<GrTextureProxy>* proxies = cache->getProxies(format);
154     if (index >= cache->getAtlasPageCount(format) || !proxies[index]) {
155         return nullptr;
156     }
157 
158     SkASSERT(proxies[index]->priv().isExact());
159     sk_sp<SkImage> image(new SkImage_Gpu(this, kNeedNewImageUniqueID, kPremul_SkAlphaType,
160                                          proxies[index], nullptr, SkBudgeted::kNo));
161     return image;
162 }
163 
164 #if GR_GPU_STATS
dump(SkString * out)165 void GrGpu::Stats::dump(SkString* out) {
166     out->appendf("Render Target Binds: %d\n", fRenderTargetBinds);
167     out->appendf("Shader Compilations: %d\n", fShaderCompilations);
168     out->appendf("Textures Created: %d\n", fTextureCreates);
169     out->appendf("Texture Uploads: %d\n", fTextureUploads);
170     out->appendf("Transfers to Texture: %d\n", fTransfersToTexture);
171     out->appendf("Stencil Buffer Creates: %d\n", fStencilAttachmentCreates);
172     out->appendf("Number of draws: %d\n", fNumDraws);
173 }
174 
dumpKeyValuePairs(SkTArray<SkString> * keys,SkTArray<double> * values)175 void GrGpu::Stats::dumpKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* values) {
176     keys->push_back(SkString("render_target_binds")); values->push_back(fRenderTargetBinds);
177     keys->push_back(SkString("shader_compilations")); values->push_back(fShaderCompilations);
178     keys->push_back(SkString("texture_uploads")); values->push_back(fTextureUploads);
179     keys->push_back(SkString("number_of_draws")); values->push_back(fNumDraws);
180     keys->push_back(SkString("number_of_failed_draws")); values->push_back(fNumFailedDraws);
181 }
182 
183 #endif
184 
185 #if GR_CACHE_STATS
getStats(Stats * stats) const186 void GrResourceCache::getStats(Stats* stats) const {
187     stats->reset();
188 
189     stats->fTotal = this->getResourceCount();
190     stats->fNumNonPurgeable = fNonpurgeableResources.count();
191     stats->fNumPurgeable = fPurgeableQueue.count();
192 
193     for (int i = 0; i < fNonpurgeableResources.count(); ++i) {
194         stats->update(fNonpurgeableResources[i]);
195     }
196     for (int i = 0; i < fPurgeableQueue.count(); ++i) {
197         stats->update(fPurgeableQueue.at(i));
198     }
199 }
200 
dumpStats(SkString * out) const201 void GrResourceCache::dumpStats(SkString* out) const {
202     this->validate();
203 
204     Stats stats;
205 
206     this->getStats(&stats);
207 
208     float countUtilization = (100.f * fBudgetedCount) / fMaxCount;
209     float byteUtilization = (100.f * fBudgetedBytes) / fMaxBytes;
210 
211     out->appendf("Budget: %d items %d bytes\n", fMaxCount, (int)fMaxBytes);
212     out->appendf("\t\tEntry Count: current %d"
213                  " (%d budgeted, %d wrapped, %d locked, %d scratch %.2g%% full), high %d\n",
214                  stats.fTotal, fBudgetedCount, stats.fWrapped, stats.fNumNonPurgeable,
215                  stats.fScratch, countUtilization, fHighWaterCount);
216     out->appendf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full, %d unbudgeted) high %d\n",
217                  SkToInt(fBytes), SkToInt(fBudgetedBytes), byteUtilization,
218                  SkToInt(stats.fUnbudgetedSize), SkToInt(fHighWaterBytes));
219 }
220 
dumpStatsKeyValuePairs(SkTArray<SkString> * keys,SkTArray<double> * values) const221 void GrResourceCache::dumpStatsKeyValuePairs(SkTArray<SkString>* keys,
222                                              SkTArray<double>* values) const {
223     this->validate();
224 
225     Stats stats;
226     this->getStats(&stats);
227 
228     keys->push_back(SkString("gpu_cache_purgable_entries")); values->push_back(stats.fNumPurgeable);
229 }
230 
231 #endif
232 
233 ///////////////////////////////////////////////////////////////////////////////
234 
changeTimestamp(uint32_t newTimestamp)235 void GrResourceCache::changeTimestamp(uint32_t newTimestamp) { fTimestamp = newTimestamp; }
236 
237 #ifdef SK_DEBUG
countUniqueKeysWithTag(const char * tag) const238 int GrResourceCache::countUniqueKeysWithTag(const char* tag) const {
239     int count = 0;
240     UniqueHash::ConstIter iter(&fUniqueHash);
241     while (!iter.done()) {
242         if (0 == strcmp(tag, (*iter).getUniqueKey().tag())) {
243             ++count;
244         }
245         ++iter;
246     }
247     return count;
248 }
249 #endif
250 
251 ///////////////////////////////////////////////////////////////////////////////
252 
253 #define ASSERT_SINGLE_OWNER \
254     SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fRenderTargetContext->singleOwner());)
255 
256 
testingOnly_getOpListID()257 uint32_t GrRenderTargetContextPriv::testingOnly_getOpListID() {
258     return fRenderTargetContext->getOpList()->uniqueID();
259 }
260 
testingOnly_addDrawOp(std::unique_ptr<GrDrawOp> op)261 uint32_t GrRenderTargetContextPriv::testingOnly_addDrawOp(std::unique_ptr<GrDrawOp> op) {
262     return this->testingOnly_addDrawOp(GrNoClip(), std::move(op));
263 }
264 
testingOnly_addDrawOp(const GrClip & clip,std::unique_ptr<GrDrawOp> op)265 uint32_t GrRenderTargetContextPriv::testingOnly_addDrawOp(const GrClip& clip,
266                                                           std::unique_ptr<GrDrawOp> op) {
267     ASSERT_SINGLE_OWNER
268     if (fRenderTargetContext->drawingManager()->wasAbandoned()) {
269         return SK_InvalidUniqueID;
270     }
271     SkDEBUGCODE(fRenderTargetContext->validate());
272     GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
273                               "GrRenderTargetContext::testingOnly_addDrawOp");
274     return fRenderTargetContext->addDrawOp(clip, std::move(op));
275 }
276 
277 #undef ASSERT_SINGLE_OWNER
278 
279 ///////////////////////////////////////////////////////////////////////////////
280 
testingOnly_getFlags() const281 GrRenderTargetFlags GrRenderTargetProxy::testingOnly_getFlags() const {
282     return fRenderTargetFlags;
283 }
284 
285 //////////////////////////////////////////////////////////////////////////////
286 
testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject * cb)287 void GrContextPriv::testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject* cb) {
288     fContext->flush();
289     fContext->fDrawingManager->testingOnly_removeOnFlushCallbackObject(cb);
290 }
291 
testingOnly_removeOnFlushCallbackObject(GrOnFlushCallbackObject * cb)292 void GrDrawingManager::testingOnly_removeOnFlushCallbackObject(GrOnFlushCallbackObject* cb) {
293     int n = std::find(fOnFlushCBObjects.begin(), fOnFlushCBObjects.end(), cb) -
294             fOnFlushCBObjects.begin();
295     SkASSERT(n < fOnFlushCBObjects.count());
296     fOnFlushCBObjects.removeShuffle(n);
297 }
298 
299 //////////////////////////////////////////////////////////////////////////////
300 
301 #define DRAW_OP_TEST_EXTERN(Op) \
302     extern std::unique_ptr<GrDrawOp> Op##__Test(GrPaint&&, SkRandom*, GrContext*, GrFSAAType)
303 #define DRAW_OP_TEST_ENTRY(Op) Op##__Test
304 
305 DRAW_OP_TEST_EXTERN(AAConvexPathOp);
306 DRAW_OP_TEST_EXTERN(AAFillRectOp);
307 DRAW_OP_TEST_EXTERN(AAFlatteningConvexPathOp);
308 DRAW_OP_TEST_EXTERN(AAHairlineOp);
309 DRAW_OP_TEST_EXTERN(AAStrokeRectOp);
310 DRAW_OP_TEST_EXTERN(CircleOp);
311 DRAW_OP_TEST_EXTERN(DashOp);
312 DRAW_OP_TEST_EXTERN(DefaultPathOp);
313 DRAW_OP_TEST_EXTERN(DIEllipseOp);
314 DRAW_OP_TEST_EXTERN(EllipseOp);
315 DRAW_OP_TEST_EXTERN(GrAtlasTextOp);
316 DRAW_OP_TEST_EXTERN(GrDrawAtlasOp);
317 DRAW_OP_TEST_EXTERN(GrDrawVerticesOp);
318 DRAW_OP_TEST_EXTERN(NonAAFillRectOp);
319 DRAW_OP_TEST_EXTERN(NonAALatticeOp);
320 DRAW_OP_TEST_EXTERN(NonAAStrokeRectOp);
321 DRAW_OP_TEST_EXTERN(ShadowRRectOp);
322 DRAW_OP_TEST_EXTERN(SmallPathOp);
323 DRAW_OP_TEST_EXTERN(RegionOp);
324 DRAW_OP_TEST_EXTERN(RRectOp);
325 DRAW_OP_TEST_EXTERN(TesselatingPathOp);
326 DRAW_OP_TEST_EXTERN(TextureOp);
327 
GrDrawRandomOp(SkRandom * random,GrRenderTargetContext * renderTargetContext,GrPaint && paint)328 void GrDrawRandomOp(SkRandom* random, GrRenderTargetContext* renderTargetContext, GrPaint&& paint) {
329     GrContext* context = renderTargetContext->surfPriv().getContext();
330     using MakeDrawOpFn = std::unique_ptr<GrDrawOp>(GrPaint&&, SkRandom*, GrContext*, GrFSAAType);
331     static constexpr MakeDrawOpFn* gFactories[] = {
332             DRAW_OP_TEST_ENTRY(AAConvexPathOp),
333             DRAW_OP_TEST_ENTRY(AAFillRectOp),
334             DRAW_OP_TEST_ENTRY(AAFlatteningConvexPathOp),
335             DRAW_OP_TEST_ENTRY(AAHairlineOp),
336             DRAW_OP_TEST_ENTRY(AAStrokeRectOp),
337             DRAW_OP_TEST_ENTRY(CircleOp),
338             DRAW_OP_TEST_ENTRY(DashOp),
339             DRAW_OP_TEST_ENTRY(DefaultPathOp),
340             DRAW_OP_TEST_ENTRY(DIEllipseOp),
341             DRAW_OP_TEST_ENTRY(EllipseOp),
342             DRAW_OP_TEST_ENTRY(GrAtlasTextOp),
343             DRAW_OP_TEST_ENTRY(GrDrawAtlasOp),
344             DRAW_OP_TEST_ENTRY(GrDrawVerticesOp),
345             DRAW_OP_TEST_ENTRY(NonAAFillRectOp),
346             DRAW_OP_TEST_ENTRY(NonAALatticeOp),
347             DRAW_OP_TEST_ENTRY(NonAAStrokeRectOp),
348             DRAW_OP_TEST_ENTRY(ShadowRRectOp),
349             DRAW_OP_TEST_ENTRY(SmallPathOp),
350             DRAW_OP_TEST_ENTRY(RegionOp),
351             DRAW_OP_TEST_ENTRY(RRectOp),
352             DRAW_OP_TEST_ENTRY(TesselatingPathOp),
353             DRAW_OP_TEST_ENTRY(TextureOp),
354     };
355 
356     static constexpr size_t kTotal = SK_ARRAY_COUNT(gFactories);
357     uint32_t index = random->nextULessThan(static_cast<uint32_t>(kTotal));
358     auto op = gFactories[index](
359             std::move(paint), random, context, renderTargetContext->fsaaType());
360     SkASSERT(op);
361     renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
362 }
363