• Home
  • History
  • Annotate
  • 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