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