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 "GrTest.h"
      9 
     10 #include "GrBatchAtlas.h"
     11 #include "GrContextOptions.h"
     12 #include "GrDrawContext.h"
     13 #include "GrDrawingManager.h"
     14 #include "GrGpuResourceCacheAccess.h"
     15 #include "GrResourceCache.h"
     16 
     17 #include "SkGpuDevice.h"
     18 #include "SkGrPriv.h"
     19 #include "SkString.h"
     20 
     21 #include "text/GrBatchFontCache.h"
     22 #include "text/GrTextBlobCache.h"
     23 
     24 namespace GrTest {
     25 void SetupAlwaysEvictAtlas(GrContext* context) {
     26     // These sizes were selected because they allow each atlas to hold a single plot and will thus
     27     // stress the atlas
     28     int dim = GrBatchAtlas::kGlyphMaxDim;
     29     GrBatchAtlasConfig configs[3];
     30     configs[kA8_GrMaskFormat].fWidth = dim;
     31     configs[kA8_GrMaskFormat].fHeight = dim;
     32     configs[kA8_GrMaskFormat].fLog2Width = SkNextLog2(dim);
     33     configs[kA8_GrMaskFormat].fLog2Height = SkNextLog2(dim);
     34     configs[kA8_GrMaskFormat].fPlotWidth = dim;
     35     configs[kA8_GrMaskFormat].fPlotHeight = dim;
     36 
     37     configs[kA565_GrMaskFormat].fWidth = dim;
     38     configs[kA565_GrMaskFormat].fHeight = dim;
     39     configs[kA565_GrMaskFormat].fLog2Width = SkNextLog2(dim);
     40     configs[kA565_GrMaskFormat].fLog2Height = SkNextLog2(dim);
     41     configs[kA565_GrMaskFormat].fPlotWidth = dim;
     42     configs[kA565_GrMaskFormat].fPlotHeight = dim;
     43 
     44     configs[kARGB_GrMaskFormat].fWidth = dim;
     45     configs[kARGB_GrMaskFormat].fHeight = dim;
     46     configs[kARGB_GrMaskFormat].fLog2Width = SkNextLog2(dim);
     47     configs[kARGB_GrMaskFormat].fLog2Height = SkNextLog2(dim);
     48     configs[kARGB_GrMaskFormat].fPlotWidth = dim;
     49     configs[kARGB_GrMaskFormat].fPlotHeight = dim;
     50 
     51     context->setTextContextAtlasSizes_ForTesting(configs);
     52 }
     53 };
     54 
     55 void GrTestTarget::init(GrContext* ctx, GrDrawTarget* target, GrRenderTarget* rt) {
     56     SkASSERT(!fContext);
     57 
     58     fContext.reset(SkRef(ctx));
     59     fDrawTarget.reset(SkRef(target));
     60     fRenderTarget.reset(SkRef(rt));
     61 }
     62 
     63 void GrContext::getTestTarget(GrTestTarget* tar, GrRenderTarget* rt) {
     64     this->flush();
     65     // We could create a proxy GrDrawTarget that passes through to fGpu until ~GrTextTarget() and
     66     // then disconnects. This would help prevent test writers from mixing using the returned
     67     // GrDrawTarget and regular drawing. We could also assert or fail in GrContext drawing methods
     68     // until ~GrTestTarget().
     69     if (!rt) {
     70         GrSurfaceDesc desc;
     71         desc.fFlags = kRenderTarget_GrSurfaceFlag;
     72         desc.fWidth = 32;
     73         desc.fHeight = 32;
     74         desc.fConfig = kRGBA_8888_GrPixelConfig;
     75         desc.fSampleCnt = 0;
     76 
     77         SkAutoTUnref<GrTexture> texture(this->textureProvider()->createTexture(
     78             desc, SkBudgeted::kNo, nullptr, 0));
     79         if (nullptr == texture) {
     80             return;
     81         }
     82         SkASSERT(nullptr != texture->asRenderTarget());
     83         rt = texture->asRenderTarget();
     84     }
     85 
     86     SkAutoTUnref<GrDrawTarget> dt(fDrawingManager->newDrawTarget(rt));
     87     tar->init(this, dt, rt);
     88 }
     89 
     90 void GrContext::setTextBlobCacheLimit_ForTesting(size_t bytes) {
     91     fTextBlobCache->setBudget(bytes);
     92 }
     93 
     94 void GrContext::setTextContextAtlasSizes_ForTesting(const GrBatchAtlasConfig* configs) {
     95     fBatchFontCache->setAtlasSizes_ForTesting(configs);
     96 }
     97 
     98 ///////////////////////////////////////////////////////////////////////////////
     99 
    100 void GrContext::purgeAllUnlockedResources() {
    101     fResourceCache->purgeAllUnlocked();
    102 }
    103 
    104 void GrContext::resetGpuStats() const {
    105 #if GR_GPU_STATS
    106     fGpu->stats()->reset();
    107 #endif
    108 }
    109 
    110 void GrContext::dumpCacheStats(SkString* out) const {
    111 #if GR_CACHE_STATS
    112     fResourceCache->dumpStats(out);
    113 #endif
    114 }
    115 
    116 void GrContext::dumpCacheStatsKeyValuePairs(SkTArray<SkString>* keys,
    117                                             SkTArray<double>* values) const {
    118 #if GR_CACHE_STATS
    119     fResourceCache->dumpStatsKeyValuePairs(keys, values);
    120 #endif
    121 }
    122 
    123 void GrContext::printCacheStats() const {
    124     SkString out;
    125     this->dumpCacheStats(&out);
    126     SkDebugf("%s", out.c_str());
    127 }
    128 
    129 void GrContext::dumpGpuStats(SkString* out) const {
    130 #if GR_GPU_STATS
    131     return fGpu->stats()->dump(out);
    132 #endif
    133 }
    134 
    135 void GrContext::dumpGpuStatsKeyValuePairs(SkTArray<SkString>* keys,
    136                                           SkTArray<double>* values) const {
    137 #if GR_GPU_STATS
    138     return fGpu->stats()->dumpKeyValuePairs(keys, values);
    139 #endif
    140 }
    141 
    142 void GrContext::printGpuStats() const {
    143     SkString out;
    144     this->dumpGpuStats(&out);
    145     SkDebugf("%s", out.c_str());
    146 }
    147 
    148 GrTexture* GrContext::getFontAtlasTexture(GrMaskFormat format) {
    149     GrBatchFontCache* cache = this->getBatchFontCache();
    150 
    151     return cache->getTexture(format);
    152 }
    153 
    154 void SkGpuDevice::drawTexture(GrTexture* tex, const SkRect& dst, const SkPaint& paint) {
    155     GrPaint grPaint;
    156     SkMatrix mat;
    157     mat.reset();
    158     if (!SkPaintToGrPaint(this->context(), paint, mat, &grPaint)) {
    159         return;
    160     }
    161     SkMatrix textureMat;
    162     textureMat.reset();
    163     textureMat[SkMatrix::kMScaleX] = 1.0f/dst.width();
    164     textureMat[SkMatrix::kMScaleY] = 1.0f/dst.height();
    165     textureMat[SkMatrix::kMTransX] = -dst.fLeft/dst.width();
    166     textureMat[SkMatrix::kMTransY] = -dst.fTop/dst.height();
    167 
    168     grPaint.addColorTextureProcessor(tex, textureMat);
    169 
    170     GrClip clip;
    171     fDrawContext->drawRect(clip, grPaint, mat, dst);
    172 }
    173 
    174 
    175 #if GR_GPU_STATS
    176 void GrGpu::Stats::dump(SkString* out) {
    177     out->appendf("Render Target Binds: %d\n", fRenderTargetBinds);
    178     out->appendf("Shader Compilations: %d\n", fShaderCompilations);
    179     out->appendf("Textures Created: %d\n", fTextureCreates);
    180     out->appendf("Texture Uploads: %d\n", fTextureUploads);
    181     out->appendf("Transfers to Texture: %d\n", fTransfersToTexture);
    182     out->appendf("Stencil Buffer Creates: %d\n", fStencilAttachmentCreates);
    183     out->appendf("Number of draws: %d\n", fNumDraws);
    184 }
    185 
    186 void GrGpu::Stats::dumpKeyValuePairs(SkTArray<SkString>* keys, SkTArray<double>* values) {
    187     keys->push_back(SkString("render_target_binds")); values->push_back(fRenderTargetBinds);
    188     keys->push_back(SkString("shader_compilations")); values->push_back(fShaderCompilations);
    189     keys->push_back(SkString("textures_created")); values->push_back(fTextureCreates);
    190     keys->push_back(SkString("texture_uploads")); values->push_back(fTextureUploads);
    191     keys->push_back(SkString("transfers_to_texture")); values->push_back(fTransfersToTexture);
    192     keys->push_back(SkString("stencil_buffer_creates")); values->push_back(fStencilAttachmentCreates);
    193     keys->push_back(SkString("number_of_draws")); values->push_back(fNumDraws);
    194 }
    195 
    196 #endif
    197 
    198 #if GR_CACHE_STATS
    199 void GrResourceCache::getStats(Stats* stats) const {
    200     stats->reset();
    201 
    202     stats->fTotal = this->getResourceCount();
    203     stats->fNumNonPurgeable = fNonpurgeableResources.count();
    204     stats->fNumPurgeable = fPurgeableQueue.count();
    205 
    206     for (int i = 0; i < fNonpurgeableResources.count(); ++i) {
    207         stats->update(fNonpurgeableResources[i]);
    208     }
    209     for (int i = 0; i < fPurgeableQueue.count(); ++i) {
    210         stats->update(fPurgeableQueue.at(i));
    211     }
    212 }
    213 
    214 void GrResourceCache::dumpStats(SkString* out) const {
    215     this->validate();
    216 
    217     Stats stats;
    218 
    219     this->getStats(&stats);
    220 
    221     float countUtilization = (100.f * fBudgetedCount) / fMaxCount;
    222     float byteUtilization = (100.f * fBudgetedBytes) / fMaxBytes;
    223 
    224     out->appendf("Budget: %d items %d bytes\n", fMaxCount, (int)fMaxBytes);
    225     out->appendf("\t\tEntry Count: current %d"
    226                  " (%d budgeted, %d external(%d borrowed, %d adopted), %d locked, %d scratch %.2g%% full), high %d\n",
    227                  stats.fTotal, fBudgetedCount, stats.fExternal, stats.fBorrowed,
    228                  stats.fAdopted, stats.fNumNonPurgeable, stats.fScratch, countUtilization,
    229                  fHighWaterCount);
    230     out->appendf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full, %d unbudgeted) high %d\n",
    231                  SkToInt(fBytes), SkToInt(fBudgetedBytes), byteUtilization,
    232                  SkToInt(stats.fUnbudgetedSize), SkToInt(fHighWaterBytes));
    233 }
    234 
    235 void GrResourceCache::dumpStatsKeyValuePairs(SkTArray<SkString>* keys,
    236                                              SkTArray<double>* values) const {
    237     this->validate();
    238 
    239     Stats stats;
    240     this->getStats(&stats);
    241 
    242     keys->push_back(SkString("gpu_cache_total_entries")); values->push_back(stats.fTotal);
    243     keys->push_back(SkString("gpu_cache_external_entries")); values->push_back(stats.fExternal);
    244     keys->push_back(SkString("gpu_cache_borrowed_entries")); values->push_back(stats.fBorrowed);
    245     keys->push_back(SkString("gpu_cache_adopted_entries")); values->push_back(stats.fAdopted);
    246     keys->push_back(SkString("gpu_cache_purgable_entries")); values->push_back(stats.fNumPurgeable);
    247     keys->push_back(SkString("gpu_cache_non_purgable_entries")); values->push_back(stats.fNumNonPurgeable);
    248     keys->push_back(SkString("gpu_cache_scratch_entries")); values->push_back(stats.fScratch);
    249     keys->push_back(SkString("gpu_cache_unbudgeted_size")); values->push_back((double)stats.fUnbudgetedSize);
    250 }
    251 
    252 #endif
    253 
    254 ///////////////////////////////////////////////////////////////////////////////
    255 
    256 void GrResourceCache::changeTimestamp(uint32_t newTimestamp) { fTimestamp = newTimestamp; }
    257 
    258 ///////////////////////////////////////////////////////////////////////////////
    259 
    260 #define ASSERT_SINGLE_OWNER \
    261     SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fSingleOwner);)
    262 #define RETURN_IF_ABANDONED        if (fDrawingManager->abandoned()) { return; }
    263 
    264 void GrDrawContext::internal_drawBatch(const GrPipelineBuilder& pipelineBuilder,
    265                                        GrDrawBatch* batch) {
    266     ASSERT_SINGLE_OWNER
    267     RETURN_IF_ABANDONED
    268     SkDEBUGCODE(this->validate();)
    269     GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrDrawContext::internal_drawBatch");
    270 
    271     this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
    272 }
    273 
    274 #undef ASSERT_SINGLE_OWNER
    275 #undef RETURN_IF_ABANDONED
    276 
    277 ///////////////////////////////////////////////////////////////////////////////
    278 // Code for the mock context. It's built on a mock GrGpu class that does nothing.
    279 ////
    280 
    281 #include "GrGpu.h"
    282 
    283 class GrPipeline;
    284 
    285 class MockCaps : public GrCaps {
    286 public:
    287     explicit MockCaps(const GrContextOptions& options) : INHERITED(options) {}
    288     bool isConfigTexturable(GrPixelConfig config) const override { return false; }
    289     bool isConfigRenderable(GrPixelConfig config, bool withMSAA) const override { return false; }
    290 private:
    291     typedef GrCaps INHERITED;
    292 };
    293 
    294 class MockGpu : public GrGpu {
    295 public:
    296     MockGpu(GrContext* context, const GrContextOptions& options) : INHERITED(context) {
    297         fCaps.reset(new MockCaps(options));
    298     }
    299     ~MockGpu() override {}
    300 
    301     bool onGetReadPixelsInfo(GrSurface* srcSurface, int readWidth, int readHeight, size_t rowBytes,
    302                              GrPixelConfig readConfig, DrawPreference*,
    303                              ReadPixelTempDrawInfo*) override { return false; }
    304 
    305     bool onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height,
    306                               GrPixelConfig srcConfig, DrawPreference*,
    307                               WritePixelTempDrawInfo*) override { return false; }
    308 
    309     void buildProgramDesc(GrProgramDesc*, const GrPrimitiveProcessor&,
    310                           const GrPipeline&) const override {}
    311 
    312     void discard(GrRenderTarget*) override {}
    313 
    314     bool onCopySurface(GrSurface* dst,
    315                        GrSurface* src,
    316                        const SkIRect& srcRect,
    317                        const SkIPoint& dstPoint) override { return false; };
    318 
    319     bool initCopySurfaceDstDesc(const GrSurface* src, GrSurfaceDesc* desc) const override {
    320         return false;
    321     }
    322 
    323     void drawDebugWireRect(GrRenderTarget*, const SkIRect&, GrColor) override {};
    324 
    325 private:
    326     void onResetContext(uint32_t resetBits) override {}
    327 
    328     void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}
    329 
    330     GrTexture* onCreateTexture(const GrSurfaceDesc& desc, GrGpuResource::LifeCycle lifeCycle,
    331                                const void* srcData, size_t rowBytes) override {
    332         return nullptr;
    333     }
    334 
    335     GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc, GrGpuResource::LifeCycle,
    336                                          const void* srcData) override {
    337         return nullptr;
    338     }
    339 
    340     GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&,
    341                                     GrWrapOwnership) override { return nullptr; }
    342 
    343     GrRenderTarget* onWrapBackendRenderTarget(const GrBackendRenderTargetDesc&,
    344                                               GrWrapOwnership) override {
    345         return nullptr;
    346     }
    347 
    348     GrRenderTarget* onWrapBackendTextureAsRenderTarget(const GrBackendTextureDesc&,
    349                                                        GrWrapOwnership) override {
    350         return nullptr;
    351     }
    352 
    353     GrVertexBuffer* onCreateVertexBuffer(size_t size, bool dynamic) override { return nullptr; }
    354 
    355     GrIndexBuffer* onCreateIndexBuffer(size_t size, bool dynamic) override { return nullptr; }
    356 
    357     GrTransferBuffer* onCreateTransferBuffer(size_t, TransferType) override { return nullptr; }
    358 
    359     void onClear(GrRenderTarget*, const SkIRect& rect, GrColor color) override {}
    360 
    361     void onClearStencilClip(GrRenderTarget*, const SkIRect& rect, bool insideClip) override {}
    362 
    363     void onDraw(const DrawArgs&, const GrNonInstancedVertices&) override {}
    364 
    365     bool onReadPixels(GrSurface* surface,
    366                       int left, int top, int width, int height,
    367                       GrPixelConfig,
    368                       void* buffer,
    369                       size_t rowBytes) override {
    370         return false;
    371     }
    372 
    373     bool onWritePixels(GrSurface* surface,
    374                        int left, int top, int width, int height,
    375                        GrPixelConfig config, const void* buffer,
    376                        size_t rowBytes) override {
    377         return false;
    378     }
    379 
    380     bool onTransferPixels(GrSurface* surface,
    381                           int left, int top, int width, int height,
    382                           GrPixelConfig config, GrTransferBuffer* buffer,
    383                           size_t offset, size_t rowBytes) override {
    384         return false;
    385     }
    386 
    387     void onResolveRenderTarget(GrRenderTarget* target) override { return; }
    388 
    389     GrStencilAttachment* createStencilAttachmentForRenderTarget(const GrRenderTarget*,
    390                                                                 int width,
    391                                                                 int height) override {
    392         return nullptr;
    393     }
    394 
    395     void clearStencil(GrRenderTarget* target) override  {}
    396 
    397     GrBackendObject createTestingOnlyBackendTexture(void* pixels, int w, int h,
    398                                                     GrPixelConfig config) override {
    399         return 0;
    400     }
    401     bool isTestingOnlyBackendTexture(GrBackendObject ) const override { return false; }
    402     void deleteTestingOnlyBackendTexture(GrBackendObject, bool abandonTexture) override {}
    403 
    404     typedef GrGpu INHERITED;
    405 };
    406 
    407 GrContext* GrContext::CreateMockContext() {
    408     GrContext* context = new GrContext;
    409 
    410     context->initMockContext();
    411     return context;
    412 }
    413 
    414 void GrContext::initMockContext() {
    415     GrContextOptions options;
    416     options.fGeometryBufferMapThreshold = 0;
    417     SkASSERT(nullptr == fGpu);
    418     fGpu = new MockGpu(this, options);
    419     SkASSERT(fGpu);
    420     this->initCommon(options);
    421 
    422     // We delete these because we want to test the cache starting with zero resources. Also, none of
    423     // these objects are required for any of tests that use this context. TODO: make stop allocating
    424     // resources in the buffer pools.
    425     fDrawingManager->abandon();
    426 }
    427