Home | History | Annotate | Download | only in gpu
      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 
     37 bool GrSurfaceProxy::isWrapped_ForTesting() const {
     38     return SkToBool(fTarget);
     39 }
     40 
     41 bool GrRenderTargetContext::isWrapped_ForTesting() const {
     42     return fRenderTargetProxy->isWrapped_ForTesting();
     43 }
     44 
     45 void GrContextPriv::setTextBlobCacheLimit_ForTesting(size_t bytes) {
     46     fContext->fTextBlobCache->setBudget(bytes);
     47 }
     48 
     49 ///////////////////////////////////////////////////////////////////////////////
     50 
     51 void GrContextPriv::purgeAllUnlockedResources_ForTesting() {
     52     fContext->fResourceCache->purgeAllUnlocked();
     53 }
     54 
     55 void GrContextPriv::resetGpuStats() const {
     56 #if GR_GPU_STATS
     57     fContext->fGpu->stats()->reset();
     58 #endif
     59 }
     60 
     61 void GrContextPriv::dumpCacheStats(SkString* out) const {
     62 #if GR_CACHE_STATS
     63     fContext->fResourceCache->dumpStats(out);
     64 #endif
     65 }
     66 
     67 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 
     74 void GrContextPriv::printCacheStats() const {
     75     SkString out;
     76     this->dumpCacheStats(&out);
     77     SkDebugf("%s", out.c_str());
     78 }
     79 
     80 void GrContextPriv::dumpGpuStats(SkString* out) const {
     81 #if GR_GPU_STATS
     82     return fContext->fGpu->stats()->dump(out);
     83 #endif
     84 }
     85 
     86 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 
     93 void GrContextPriv::printGpuStats() const {
     94     SkString out;
     95     this->dumpGpuStats(&out);
     96     SkDebugf("%s", out.c_str());
     97 }
     98 
     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
    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 
    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
    139 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 
    154 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 
    174 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 
    188 void GrResourceCache::changeTimestamp(uint32_t newTimestamp) { fTimestamp = newTimestamp; }
    189 
    190 #ifdef SK_DEBUG
    191 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 
    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 
    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 
    233 uint32_t GrRenderTargetContextPriv::testingOnly_getOpListID() {
    234     return fRenderTargetContext->getOpList()->uniqueID();
    235 }
    236 
    237 void GrRenderTargetContextPriv::testingOnly_addDrawOp(std::unique_ptr<GrDrawOp> op) {
    238     this->testingOnly_addDrawOp(GrNoClip(), std::move(op));
    239 }
    240 
    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 
    260 GrInternalSurfaceFlags GrSurfaceProxy::testingOnly_getFlags() const {
    261     return fSurfaceFlags;
    262 }
    263 
    264 //////////////////////////////////////////////////////////////////////////////
    265 
    266 void GrContextPriv::testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject* cb) {
    267     fContext->flush();
    268     fContext->fDrawingManager->testingOnly_removeOnFlushCallbackObject(cb);
    269 }
    270 
    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 
    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*
    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 
    303 const GrCCPathCache* GrCoverageCountingPathRenderer::testingOnly_getPathCache() const {
    304     return fPathCache.get();
    305 }
    306 
    307 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 
    315 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&>&
    324 GrCCPathCache::testingOnly_getHashTable() const {
    325     return fHashTable;
    326 }
    327 
    328 const SkTInternalLList<GrCCPathCacheEntry>& GrCCPathCache::testingOnly_getLRU() const {
    329     return fLRU;
    330 }
    331 
    332 int GrCCPathCacheEntry::testingOnly_peekOnFlushRefCnt() const { return fOnFlushRefCnt; }
    333 
    334 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 
    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