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 "GrBackendSurface.h"
9 #include "GrClip.h"
10 #include "GrContextOptions.h"
11 #include "GrContextPriv.h"
12 #include "GrDrawOpAtlas.h"
13 #include "GrDrawingManager.h"
14 #include "GrGpu.h"
15 #include "GrGpuResourceCacheAccess.h"
16 #include "GrMemoryPool.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 "SkTo.h"
29 #include "ccpr/GrCoverageCountingPathRenderer.h"
30 #include "ccpr/GrCCPathCache.h"
31 #include "ops/GrMeshDrawOp.h"
32 #include "text/GrStrikeCache.h"
33 #include "text/GrTextBlobCache.h"
34
35 #include <algorithm>
36
isWrapped_ForTesting() const37 bool GrSurfaceProxy::isWrapped_ForTesting() const {
38 return SkToBool(fTarget);
39 }
40
isWrapped_ForTesting() const41 bool GrRenderTargetContext::isWrapped_ForTesting() const {
42 return fRenderTargetProxy->isWrapped_ForTesting();
43 }
44
setTextBlobCacheLimit_ForTesting(size_t bytes)45 void GrContextPriv::setTextBlobCacheLimit_ForTesting(size_t bytes) {
46 fContext->fTextBlobCache->setBudget(bytes);
47 }
48
49 ///////////////////////////////////////////////////////////////////////////////
50
purgeAllUnlockedResources_ForTesting()51 void GrContextPriv::purgeAllUnlockedResources_ForTesting() {
52 fContext->fResourceCache->purgeAllUnlocked();
53 }
54
resetGpuStats() const55 void GrContextPriv::resetGpuStats() const {
56 #if GR_GPU_STATS
57 fContext->fGpu->stats()->reset();
58 #endif
59 }
60
dumpCacheStats(SkString * out) const61 void GrContextPriv::dumpCacheStats(SkString* out) const {
62 #if GR_CACHE_STATS
63 fContext->fResourceCache->dumpStats(out);
64 #endif
65 }
66
dumpCacheStatsKeyValuePairs(SkTArray<SkString> * keys,SkTArray<double> * values) const67 void GrContextPriv::dumpCacheStatsKeyValuePairs(SkTArray<SkString>* keys,
68 SkTArray<double>* values) const {
69 #if GR_CACHE_STATS
70 fContext->fResourceCache->dumpStatsKeyValuePairs(keys, values);
71 #endif
72 }
73
printCacheStats() const74 void GrContextPriv::printCacheStats() const {
75 SkString out;
76 this->dumpCacheStats(&out);
77 SkDebugf("%s", out.c_str());
78 }
79
dumpGpuStats(SkString * out) const80 void GrContextPriv::dumpGpuStats(SkString* out) const {
81 #if GR_GPU_STATS
82 return fContext->fGpu->stats()->dump(out);
83 #endif
84 }
85
dumpGpuStatsKeyValuePairs(SkTArray<SkString> * keys,SkTArray<double> * values) const86 void GrContextPriv::dumpGpuStatsKeyValuePairs(SkTArray<SkString>* keys,
87 SkTArray<double>* values) const {
88 #if GR_GPU_STATS
89 return fContext->fGpu->stats()->dumpKeyValuePairs(keys, values);
90 #endif
91 }
92
printGpuStats() const93 void GrContextPriv::printGpuStats() const {
94 SkString out;
95 this->dumpGpuStats(&out);
96 SkDebugf("%s", out.c_str());
97 }
98
getFontAtlasImage_ForTesting(GrMaskFormat format,unsigned int index)99 sk_sp<SkImage> GrContextPriv::getFontAtlasImage_ForTesting(GrMaskFormat format, unsigned int index) {
100 auto atlasManager = this->getAtlasManager();
101 if (!atlasManager) {
102 return nullptr;
103 }
104
105 unsigned int numActiveProxies;
106 const sk_sp<GrTextureProxy>* proxies = atlasManager->getProxies(format, &numActiveProxies);
107 if (index >= numActiveProxies || !proxies || !proxies[index]) {
108 return nullptr;
109 }
110
111 SkASSERT(proxies[index]->priv().isExact());
112 sk_sp<SkImage> image(new SkImage_Gpu(sk_ref_sp(fContext), kNeedNewImageUniqueID,
113 kPremul_SkAlphaType, proxies[index], nullptr));
114 return image;
115 }
116
117 #if GR_GPU_STATS
dump(SkString * out)118 void GrGpu::Stats::dump(SkString* out) {
119 out->appendf("Render Target Binds: %d\n", fRenderTargetBinds);
120 out->appendf("Shader Compilations: %d\n", fShaderCompilations);
121 out->appendf("Textures Created: %d\n", fTextureCreates);
122 out->appendf("Texture Uploads: %d\n", fTextureUploads);
123 out->appendf("Transfers to Texture: %d\n", fTransfersToTexture);
124 out->appendf("Stencil Buffer Creates: %d\n", fStencilAttachmentCreates);
125 out->appendf("Number of draws: %d\n", fNumDraws);
126 }
127
dumpKeyValuePairs(SkTArray<SkString> * keys,SkTArray<double> * values)128 void GrGpu::Stats::dumpKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* values) {
129 keys->push_back(SkString("render_target_binds")); values->push_back(fRenderTargetBinds);
130 keys->push_back(SkString("shader_compilations")); values->push_back(fShaderCompilations);
131 keys->push_back(SkString("texture_uploads")); values->push_back(fTextureUploads);
132 keys->push_back(SkString("number_of_draws")); values->push_back(fNumDraws);
133 keys->push_back(SkString("number_of_failed_draws")); values->push_back(fNumFailedDraws);
134 }
135
136 #endif
137
138 #if GR_CACHE_STATS
getStats(Stats * stats) const139 void GrResourceCache::getStats(Stats* stats) const {
140 stats->reset();
141
142 stats->fTotal = this->getResourceCount();
143 stats->fNumNonPurgeable = fNonpurgeableResources.count();
144 stats->fNumPurgeable = fPurgeableQueue.count();
145
146 for (int i = 0; i < fNonpurgeableResources.count(); ++i) {
147 stats->update(fNonpurgeableResources[i]);
148 }
149 for (int i = 0; i < fPurgeableQueue.count(); ++i) {
150 stats->update(fPurgeableQueue.at(i));
151 }
152 }
153
dumpStats(SkString * out) const154 void GrResourceCache::dumpStats(SkString* out) const {
155 this->validate();
156
157 Stats stats;
158
159 this->getStats(&stats);
160
161 float countUtilization = (100.f * fBudgetedCount) / fMaxCount;
162 float byteUtilization = (100.f * fBudgetedBytes) / fMaxBytes;
163
164 out->appendf("Budget: %d items %d bytes\n", fMaxCount, (int)fMaxBytes);
165 out->appendf("\t\tEntry Count: current %d"
166 " (%d budgeted, %d wrapped, %d locked, %d scratch %.2g%% full), high %d\n",
167 stats.fTotal, fBudgetedCount, stats.fWrapped, stats.fNumNonPurgeable,
168 stats.fScratch, countUtilization, fHighWaterCount);
169 out->appendf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full, %d unbudgeted) high %d\n",
170 SkToInt(fBytes), SkToInt(fBudgetedBytes), byteUtilization,
171 SkToInt(stats.fUnbudgetedSize), SkToInt(fHighWaterBytes));
172 }
173
dumpStatsKeyValuePairs(SkTArray<SkString> * keys,SkTArray<double> * values) const174 void GrResourceCache::dumpStatsKeyValuePairs(SkTArray<SkString>* keys,
175 SkTArray<double>* values) const {
176 this->validate();
177
178 Stats stats;
179 this->getStats(&stats);
180
181 keys->push_back(SkString("gpu_cache_purgable_entries")); values->push_back(stats.fNumPurgeable);
182 }
183
184 #endif
185
186 ///////////////////////////////////////////////////////////////////////////////
187
changeTimestamp(uint32_t newTimestamp)188 void GrResourceCache::changeTimestamp(uint32_t newTimestamp) { fTimestamp = newTimestamp; }
189
190 #ifdef SK_DEBUG
countUniqueKeysWithTag(const char * tag) const191 int GrResourceCache::countUniqueKeysWithTag(const char* tag) const {
192 int count = 0;
193 UniqueHash::ConstIter iter(&fUniqueHash);
194 while (!iter.done()) {
195 if (0 == strcmp(tag, (*iter).getUniqueKey().tag())) {
196 ++count;
197 }
198 ++iter;
199 }
200 return count;
201 }
202 #endif
203
204 ///////////////////////////////////////////////////////////////////////////////
205
testingOnly_createInstantiatedProxy(const GrSurfaceDesc & desc,GrSurfaceOrigin origin,SkBackingFit fit,SkBudgeted budgeted)206 sk_sp<GrTextureProxy> GrProxyProvider::testingOnly_createInstantiatedProxy(
207 const GrSurfaceDesc& desc, GrSurfaceOrigin origin, SkBackingFit fit, SkBudgeted budgeted) {
208 sk_sp<GrTexture> tex;
209
210 if (SkBackingFit::kApprox == fit) {
211 tex = fResourceProvider->createApproxTexture(desc, GrResourceProvider::Flags::kNone);
212 } else {
213 tex = fResourceProvider->createTexture(desc, budgeted, GrResourceProvider::Flags::kNone);
214 }
215 if (!tex) {
216 return nullptr;
217 }
218
219 return this->createWrapped(std::move(tex), origin);
220 }
221
testingOnly_createWrapped(sk_sp<GrTexture> tex,GrSurfaceOrigin origin)222 sk_sp<GrTextureProxy> GrProxyProvider::testingOnly_createWrapped(sk_sp<GrTexture> tex,
223 GrSurfaceOrigin origin) {
224 return this->createWrapped(std::move(tex), origin);
225 }
226
227 ///////////////////////////////////////////////////////////////////////////////
228
229 #define ASSERT_SINGLE_OWNER \
230 SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fRenderTargetContext->singleOwner());)
231
232
testingOnly_getOpListID()233 uint32_t GrRenderTargetContextPriv::testingOnly_getOpListID() {
234 return fRenderTargetContext->getOpList()->uniqueID();
235 }
236
testingOnly_addDrawOp(std::unique_ptr<GrDrawOp> op)237 void GrRenderTargetContextPriv::testingOnly_addDrawOp(std::unique_ptr<GrDrawOp> op) {
238 this->testingOnly_addDrawOp(GrNoClip(), std::move(op));
239 }
240
testingOnly_addDrawOp(const GrClip & clip,std::unique_ptr<GrDrawOp> op,const std::function<GrRenderTargetContext::WillAddOpFn> & willAddFn)241 void GrRenderTargetContextPriv::testingOnly_addDrawOp(
242 const GrClip& clip,
243 std::unique_ptr<GrDrawOp> op,
244 const std::function<GrRenderTargetContext::WillAddOpFn>& willAddFn) {
245 ASSERT_SINGLE_OWNER
246 if (fRenderTargetContext->drawingManager()->wasAbandoned()) {
247 fRenderTargetContext->fContext->contextPriv().opMemoryPool()->release(std::move(op));
248 return;
249 }
250 SkDEBUGCODE(fRenderTargetContext->validate());
251 GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
252 "GrRenderTargetContext::testingOnly_addDrawOp");
253 fRenderTargetContext->addDrawOp(clip, std::move(op), willAddFn);
254 }
255
256 #undef ASSERT_SINGLE_OWNER
257
258 ///////////////////////////////////////////////////////////////////////////////
259
testingOnly_getFlags() const260 GrInternalSurfaceFlags GrSurfaceProxy::testingOnly_getFlags() const {
261 return fSurfaceFlags;
262 }
263
264 //////////////////////////////////////////////////////////////////////////////
265
testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject * cb)266 void GrContextPriv::testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject* cb) {
267 fContext->flush();
268 fContext->fDrawingManager->testingOnly_removeOnFlushCallbackObject(cb);
269 }
270
testingOnly_removeOnFlushCallbackObject(GrOnFlushCallbackObject * cb)271 void GrDrawingManager::testingOnly_removeOnFlushCallbackObject(GrOnFlushCallbackObject* cb) {
272 int n = std::find(fOnFlushCBObjects.begin(), fOnFlushCBObjects.end(), cb) -
273 fOnFlushCBObjects.begin();
274 SkASSERT(n < fOnFlushCBObjects.count());
275 fOnFlushCBObjects.removeShuffle(n);
276 }
277
278 //////////////////////////////////////////////////////////////////////////////
279
testingOnly_drawPathDirectly(const DrawPathArgs & args)280 void GrCoverageCountingPathRenderer::testingOnly_drawPathDirectly(const DrawPathArgs& args) {
281 // Call onDrawPath() directly: We want to test paths that might fail onCanDrawPath() simply for
282 // performance reasons, and GrPathRenderer::drawPath() assert that this call returns true.
283 // The test is responsible to not draw any paths that CCPR is not actually capable of.
284 this->onDrawPath(args);
285 }
286
287 const GrCCPerFlushResources*
testingOnly_getCurrentFlushResources()288 GrCoverageCountingPathRenderer::testingOnly_getCurrentFlushResources() {
289 SkASSERT(fFlushing);
290 if (fFlushingPaths.empty()) {
291 return nullptr;
292 }
293 // All pending paths should share the same resources.
294 const GrCCPerFlushResources* resources = fFlushingPaths.front()->fFlushResources.get();
295 #ifdef SK_DEBUG
296 for (const auto& flushingPaths : fFlushingPaths) {
297 SkASSERT(flushingPaths->fFlushResources.get() == resources);
298 }
299 #endif
300 return resources;
301 }
302
testingOnly_getPathCache() const303 const GrCCPathCache* GrCoverageCountingPathRenderer::testingOnly_getPathCache() const {
304 return fPathCache.get();
305 }
306
testingOnly_frontCopyAtlasTexture() const307 const GrTexture* GrCCPerFlushResources::testingOnly_frontCopyAtlasTexture() const {
308 if (fCopyAtlasStack.empty()) {
309 return nullptr;
310 }
311 const GrTextureProxy* proxy = fCopyAtlasStack.front().textureProxy();
312 return (proxy) ? proxy->peekTexture() : nullptr;
313 }
314
testingOnly_frontRenderedAtlasTexture() const315 const GrTexture* GrCCPerFlushResources::testingOnly_frontRenderedAtlasTexture() const {
316 if (fRenderedAtlasStack.empty()) {
317 return nullptr;
318 }
319 const GrTextureProxy* proxy = fRenderedAtlasStack.front().textureProxy();
320 return (proxy) ? proxy->peekTexture() : nullptr;
321 }
322
323 const SkTHashTable<GrCCPathCache::HashNode, const GrCCPathCache::Key&>&
testingOnly_getHashTable() const324 GrCCPathCache::testingOnly_getHashTable() const {
325 return fHashTable;
326 }
327
testingOnly_getLRU() const328 const SkTInternalLList<GrCCPathCacheEntry>& GrCCPathCache::testingOnly_getLRU() const {
329 return fLRU;
330 }
331
testingOnly_peekOnFlushRefCnt() const332 int GrCCPathCacheEntry::testingOnly_peekOnFlushRefCnt() const { return fOnFlushRefCnt; }
333
testingOnly_peekOnFlushRefCnt() const334 int GrCCCachedAtlas::testingOnly_peekOnFlushRefCnt() const { return fOnFlushRefCnt; }
335
336 //////////////////////////////////////////////////////////////////////////////
337
338 #define DRAW_OP_TEST_EXTERN(Op) \
339 extern std::unique_ptr<GrDrawOp> Op##__Test(GrPaint&&, SkRandom*, GrContext*, GrFSAAType)
340 #define DRAW_OP_TEST_ENTRY(Op) Op##__Test
341
342 DRAW_OP_TEST_EXTERN(AAConvexPathOp);
343 DRAW_OP_TEST_EXTERN(AAFlatteningConvexPathOp);
344 DRAW_OP_TEST_EXTERN(AAHairlineOp);
345 DRAW_OP_TEST_EXTERN(AAStrokeRectOp);
346 DRAW_OP_TEST_EXTERN(CircleOp);
347 DRAW_OP_TEST_EXTERN(DashOp);
348 DRAW_OP_TEST_EXTERN(DefaultPathOp);
349 DRAW_OP_TEST_EXTERN(DIEllipseOp);
350 DRAW_OP_TEST_EXTERN(EllipseOp);
351 DRAW_OP_TEST_EXTERN(FillRectOp);
352 DRAW_OP_TEST_EXTERN(GrAtlasTextOp);
353 DRAW_OP_TEST_EXTERN(GrDrawAtlasOp);
354 DRAW_OP_TEST_EXTERN(GrDrawVerticesOp);
355 DRAW_OP_TEST_EXTERN(NonAALatticeOp);
356 DRAW_OP_TEST_EXTERN(NonAAStrokeRectOp);
357 DRAW_OP_TEST_EXTERN(ShadowRRectOp);
358 DRAW_OP_TEST_EXTERN(SmallPathOp);
359 DRAW_OP_TEST_EXTERN(RegionOp);
360 DRAW_OP_TEST_EXTERN(RRectOp);
361 DRAW_OP_TEST_EXTERN(TesselatingPathOp);
362 DRAW_OP_TEST_EXTERN(TextureOp);
363
GrDrawRandomOp(SkRandom * random,GrRenderTargetContext * renderTargetContext,GrPaint && paint)364 void GrDrawRandomOp(SkRandom* random, GrRenderTargetContext* renderTargetContext, GrPaint&& paint) {
365 GrContext* context = renderTargetContext->surfPriv().getContext();
366 using MakeDrawOpFn = std::unique_ptr<GrDrawOp>(GrPaint&&, SkRandom*, GrContext*, GrFSAAType);
367 static constexpr MakeDrawOpFn* gFactories[] = {
368 DRAW_OP_TEST_ENTRY(AAConvexPathOp),
369 DRAW_OP_TEST_ENTRY(AAFlatteningConvexPathOp),
370 DRAW_OP_TEST_ENTRY(AAHairlineOp),
371 DRAW_OP_TEST_ENTRY(AAStrokeRectOp),
372 DRAW_OP_TEST_ENTRY(CircleOp),
373 DRAW_OP_TEST_ENTRY(DashOp),
374 DRAW_OP_TEST_ENTRY(DefaultPathOp),
375 DRAW_OP_TEST_ENTRY(DIEllipseOp),
376 DRAW_OP_TEST_ENTRY(EllipseOp),
377 DRAW_OP_TEST_ENTRY(FillRectOp),
378 DRAW_OP_TEST_ENTRY(GrAtlasTextOp),
379 DRAW_OP_TEST_ENTRY(GrDrawAtlasOp),
380 DRAW_OP_TEST_ENTRY(GrDrawVerticesOp),
381 DRAW_OP_TEST_ENTRY(NonAALatticeOp),
382 DRAW_OP_TEST_ENTRY(NonAAStrokeRectOp),
383 DRAW_OP_TEST_ENTRY(ShadowRRectOp),
384 DRAW_OP_TEST_ENTRY(SmallPathOp),
385 DRAW_OP_TEST_ENTRY(RegionOp),
386 DRAW_OP_TEST_ENTRY(RRectOp),
387 DRAW_OP_TEST_ENTRY(TesselatingPathOp),
388 DRAW_OP_TEST_ENTRY(TextureOp),
389 };
390
391 static constexpr size_t kTotal = SK_ARRAY_COUNT(gFactories);
392 uint32_t index = random->nextULessThan(static_cast<uint32_t>(kTotal));
393 auto op = gFactories[index](
394 std::move(paint), random, context, renderTargetContext->fsaaType());
395 SkASSERT(op);
396 renderTargetContext->priv().testingOnly_addDrawOp(std::move(op));
397 }
398