Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2015 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 "GrDrawContext.h"
      9 #include "GrDrawingManager.h"
     10 #include "GrDrawTarget.h"
     11 #include "GrPathRenderingDrawContext.h"
     12 #include "GrResourceProvider.h"
     13 #include "GrSoftwarePathRenderer.h"
     14 #include "SkTTopoSort.h"
     15 
     16 #include "text/GrAtlasTextContext.h"
     17 #include "text/GrStencilAndCoverTextContext.h"
     18 
     19 void GrDrawingManager::cleanup() {
     20     for (int i = 0; i < fDrawTargets.count(); ++i) {
     21         fDrawTargets[i]->makeClosed();  // no drawTarget should receive a new command after this
     22         fDrawTargets[i]->clearRT();
     23 
     24         // We shouldn't need to do this, but it turns out some clients still hold onto drawtargets
     25         // after a cleanup
     26         fDrawTargets[i]->reset();
     27         fDrawTargets[i]->unref();
     28     }
     29 
     30     fDrawTargets.reset();
     31 
     32     delete fPathRendererChain;
     33     fPathRendererChain = nullptr;
     34     SkSafeSetNull(fSoftwarePathRenderer);
     35 }
     36 
     37 GrDrawingManager::~GrDrawingManager() {
     38     this->cleanup();
     39 }
     40 
     41 void GrDrawingManager::abandon() {
     42     fAbandoned = true;
     43     this->cleanup();
     44 }
     45 
     46 void GrDrawingManager::freeGpuResources() {
     47     // a path renderer may be holding onto resources
     48     delete fPathRendererChain;
     49     fPathRendererChain = nullptr;
     50     SkSafeSetNull(fSoftwarePathRenderer);
     51 }
     52 
     53 void GrDrawingManager::reset() {
     54     for (int i = 0; i < fDrawTargets.count(); ++i) {
     55         fDrawTargets[i]->reset();
     56     }
     57     fFlushState.reset();
     58 }
     59 
     60 void GrDrawingManager::flush() {
     61     if (fFlushing || this->abandoned()) {
     62         return;
     63     }
     64     fFlushing = true;
     65 
     66     SkDEBUGCODE(bool result =)
     67                         SkTTopoSort<GrDrawTarget, GrDrawTarget::TopoSortTraits>(&fDrawTargets);
     68     SkASSERT(result);
     69 
     70 #if 0
     71     for (int i = 0; i < fDrawTargets.count(); ++i) {
     72         SkDEBUGCODE(fDrawTargets[i]->dump();)
     73     }
     74 #endif
     75 
     76     for (int i = 0; i < fDrawTargets.count(); ++i) {
     77         fDrawTargets[i]->prepareBatches(&fFlushState);
     78     }
     79 
     80     // Upload all data to the GPU
     81     fFlushState.preIssueDraws();
     82 
     83     for (int i = 0; i < fDrawTargets.count(); ++i) {
     84         fDrawTargets[i]->drawBatches(&fFlushState);
     85     }
     86 
     87     SkASSERT(fFlushState.lastFlushedToken() == fFlushState.currentToken());
     88 
     89     for (int i = 0; i < fDrawTargets.count(); ++i) {
     90         fDrawTargets[i]->reset();
     91 #ifdef ENABLE_MDB
     92         fDrawTargets[i]->unref();
     93 #endif
     94     }
     95 
     96 #ifndef ENABLE_MDB
     97     // When MDB is disabled we keep reusing the same drawTarget
     98     if (fDrawTargets.count()) {
     99         SkASSERT(fDrawTargets.count() == 1);
    100         // Clear out this flag so the topological sort's SkTTopoSort_CheckAllUnmarked check
    101         // won't bark
    102         fDrawTargets[0]->resetFlag(GrDrawTarget::kWasOutput_Flag);
    103     }
    104 #else
    105     fDrawTargets.reset();
    106 #endif
    107 
    108     fFlushState.reset();
    109     fFlushing = false;
    110 }
    111 
    112 GrDrawTarget* GrDrawingManager::newDrawTarget(GrRenderTarget* rt) {
    113     SkASSERT(fContext);
    114 
    115 #ifndef ENABLE_MDB
    116     // When MDB is disabled we always just return the single drawTarget
    117     if (fDrawTargets.count()) {
    118         SkASSERT(fDrawTargets.count() == 1);
    119         // In the non-MDB-world the same drawTarget gets reused for multiple render targets.
    120         // Update this pointer so all the asserts are happy
    121         rt->setLastDrawTarget(fDrawTargets[0]);
    122         // DrawingManager gets the creation ref - this ref is for the caller
    123         return SkRef(fDrawTargets[0]);
    124     }
    125 #endif
    126 
    127     GrDrawTarget* dt = new GrDrawTarget(rt, fContext->getGpu(), fContext->resourceProvider(),
    128                                         fContext->getAuditTrail(), fOptionsForDrawTargets);
    129 
    130     *fDrawTargets.append() = dt;
    131 
    132     // DrawingManager gets the creation ref - this ref is for the caller
    133     return SkRef(dt);
    134 }
    135 
    136 /*
    137  * This method finds a path renderer that can draw the specified path on
    138  * the provided target.
    139  * Due to its expense, the software path renderer has split out so it can
    140  * can be individually allowed/disallowed via the "allowSW" boolean.
    141  */
    142 GrPathRenderer* GrDrawingManager::getPathRenderer(const GrPathRenderer::CanDrawPathArgs& args,
    143                                                   bool allowSW,
    144                                                   GrPathRendererChain::DrawType drawType,
    145                                                   GrPathRenderer::StencilSupport* stencilSupport) {
    146 
    147     if (!fPathRendererChain) {
    148         fPathRendererChain = new GrPathRendererChain(fContext);
    149     }
    150 
    151     GrPathRenderer* pr = fPathRendererChain->getPathRenderer(args, drawType, stencilSupport);
    152     if (!pr && allowSW) {
    153         if (!fSoftwarePathRenderer) {
    154             fSoftwarePathRenderer = new GrSoftwarePathRenderer(fContext);
    155         }
    156         pr = fSoftwarePathRenderer;
    157     }
    158 
    159     return pr;
    160 }
    161 
    162 GrDrawContext* GrDrawingManager::drawContext(GrRenderTarget* rt,
    163                                              const SkSurfaceProps* surfaceProps) {
    164     if (this->abandoned()) {
    165         return nullptr;
    166     }
    167 
    168 
    169     bool useDIF = false;
    170     if (surfaceProps) {
    171         useDIF = surfaceProps->isUseDeviceIndependentFonts();
    172     }
    173 
    174     if (useDIF && fContext->caps()->shaderCaps()->pathRenderingSupport() &&
    175         rt->isStencilBufferMultisampled()) {
    176         GrStencilAttachment* sb = fContext->resourceProvider()->attachStencilAttachment(rt);
    177         if (sb) {
    178             return new GrPathRenderingDrawContext(fContext, this, rt, surfaceProps,
    179                                                   fContext->getAuditTrail(), fSingleOwner);
    180         }
    181     }
    182 
    183     return new GrDrawContext(fContext, this, rt, surfaceProps, fContext->getAuditTrail(),
    184                              fSingleOwner);
    185 }
    186