• 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 "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