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