blob: 2a27f6aac453557aca310f1629563d01929f6348 [file] [log] [blame]
robertphillips3dc6ae52015-10-20 09:54:32 -07001/*
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
robertphillips3dc6ae52015-10-20 09:54:32 -07008#include "GrDrawContext.h"
9#include "GrDrawingManager.h"
10#include "GrDrawTarget.h"
11#include "GrResourceProvider.h"
robertphillips68737822015-10-29 12:12:21 -070012#include "GrSoftwarePathRenderer.h"
robertphillips3dc6ae52015-10-20 09:54:32 -070013#include "SkTTopoSort.h"
14
joshualitte8042922015-12-11 06:11:21 -080015#include "text/GrAtlasTextContext.h"
16#include "text/GrStencilAndCoverTextContext.h"
robertphillips498d7ac2015-10-30 10:11:30 -070017
robertphillips3dc6ae52015-10-20 09:54:32 -070018void GrDrawingManager::cleanup() {
19 for (int i = 0; i < fDrawTargets.count(); ++i) {
robertphillips0dfa62c2015-11-16 06:23:31 -080020 fDrawTargets[i]->makeClosed(); // no drawTarget should receive a new command after this
21 fDrawTargets[i]->clearRT();
22
joshualitt20ccd402016-01-05 08:56:56 -080023 // We shouldn't need to do this, but it turns out some clients still hold onto drawtargets
24 // after a cleanup
25 fDrawTargets[i]->reset();
robertphillips3dc6ae52015-10-20 09:54:32 -070026 fDrawTargets[i]->unref();
27 }
28
29 fDrawTargets.reset();
30
31 delete fNVPRTextContext;
32 fNVPRTextContext = nullptr;
33
34 for (int i = 0; i < kNumPixelGeometries; ++i) {
35 delete fTextContexts[i][0];
36 fTextContexts[i][0] = nullptr;
37 delete fTextContexts[i][1];
38 fTextContexts[i][1] = nullptr;
39 }
robertphillips68737822015-10-29 12:12:21 -070040
robertphillips13391dd2015-10-30 05:15:11 -070041 delete fPathRendererChain;
42 fPathRendererChain = nullptr;
robertphillips68737822015-10-29 12:12:21 -070043 SkSafeSetNull(fSoftwarePathRenderer);
robertphillips3dc6ae52015-10-20 09:54:32 -070044}
45
46GrDrawingManager::~GrDrawingManager() {
47 this->cleanup();
48}
49
50void GrDrawingManager::abandon() {
51 fAbandoned = true;
52 this->cleanup();
53}
54
robertphillips68737822015-10-29 12:12:21 -070055void GrDrawingManager::freeGpuResources() {
56 // a path renderer may be holding onto resources
robertphillips13391dd2015-10-30 05:15:11 -070057 delete fPathRendererChain;
58 fPathRendererChain = nullptr;
robertphillips68737822015-10-29 12:12:21 -070059 SkSafeSetNull(fSoftwarePathRenderer);
60}
61
robertphillips3dc6ae52015-10-20 09:54:32 -070062void GrDrawingManager::reset() {
63 for (int i = 0; i < fDrawTargets.count(); ++i) {
64 fDrawTargets[i]->reset();
65 }
robertphillipsa13e2022015-11-11 12:01:09 -080066 fFlushState.reset();
robertphillips3dc6ae52015-10-20 09:54:32 -070067}
68
69void GrDrawingManager::flush() {
joshualittb8918c42015-12-18 09:59:46 -080070 if (fFlushing) {
71 return;
72 }
73 fFlushing = true;
74
robertphillips3dc6ae52015-10-20 09:54:32 -070075 SkDEBUGCODE(bool result =)
76 SkTTopoSort<GrDrawTarget, GrDrawTarget::TopoSortTraits>(&fDrawTargets);
77 SkASSERT(result);
78
robertphillipsa13e2022015-11-11 12:01:09 -080079#if 0
robertphillips3dc6ae52015-10-20 09:54:32 -070080 for (int i = 0; i < fDrawTargets.count(); ++i) {
robertphillipsa13e2022015-11-11 12:01:09 -080081 SkDEBUGCODE(fDrawTargets[i]->dump();)
robertphillips3dc6ae52015-10-20 09:54:32 -070082 }
robertphillipsa13e2022015-11-11 12:01:09 -080083#endif
84
85 for (int i = 0; i < fDrawTargets.count(); ++i) {
86 fDrawTargets[i]->prepareBatches(&fFlushState);
87 }
88
89 // Upload all data to the GPU
90 fFlushState.preIssueDraws();
91
92 for (int i = 0; i < fDrawTargets.count(); ++i) {
93 fDrawTargets[i]->drawBatches(&fFlushState);
94 }
95
96 SkASSERT(fFlushState.lastFlushedToken() == fFlushState.currentToken());
robertphillips3dc6ae52015-10-20 09:54:32 -070097
robertphillips0dfa62c2015-11-16 06:23:31 -080098 for (int i = 0; i < fDrawTargets.count(); ++i) {
99 fDrawTargets[i]->reset();
100#ifdef ENABLE_MDB
101 fDrawTargets[i]->unref();
102#endif
103 }
104
robertphillips3dc6ae52015-10-20 09:54:32 -0700105#ifndef ENABLE_MDB
106 // When MDB is disabled we keep reusing the same drawTarget
107 if (fDrawTargets.count()) {
108 SkASSERT(fDrawTargets.count() == 1);
robertphillips0dfa62c2015-11-16 06:23:31 -0800109 // Clear out this flag so the topological sort's SkTTopoSort_CheckAllUnmarked check
110 // won't bark
robertphillips3dc6ae52015-10-20 09:54:32 -0700111 fDrawTargets[0]->resetFlag(GrDrawTarget::kWasOutput_Flag);
112 }
robertphillips0dfa62c2015-11-16 06:23:31 -0800113#else
114 fDrawTargets.reset();
robertphillips3dc6ae52015-10-20 09:54:32 -0700115#endif
robertphillipsa13e2022015-11-11 12:01:09 -0800116
robertphillipsa13e2022015-11-11 12:01:09 -0800117 fFlushState.reset();
joshualittb8918c42015-12-18 09:59:46 -0800118 fFlushing = false;
robertphillips3dc6ae52015-10-20 09:54:32 -0700119}
120
121GrTextContext* GrDrawingManager::textContext(const SkSurfaceProps& props,
122 GrRenderTarget* rt) {
123 if (this->abandoned()) {
124 return nullptr;
125 }
126
127 SkASSERT(props.pixelGeometry() < kNumPixelGeometries);
128 bool useDIF = props.isUseDeviceIndependentFonts();
129
130 if (useDIF && fContext->caps()->shaderCaps()->pathRenderingSupport() &&
131 rt->isStencilBufferMultisampled()) {
132 GrStencilAttachment* sb = fContext->resourceProvider()->attachStencilAttachment(rt);
133 if (sb) {
134 if (!fNVPRTextContext) {
135 fNVPRTextContext = GrStencilAndCoverTextContext::Create(fContext, props);
136 }
137
138 return fNVPRTextContext;
139 }
140 }
141
142 if (!fTextContexts[props.pixelGeometry()][useDIF]) {
143 fTextContexts[props.pixelGeometry()][useDIF] = GrAtlasTextContext::Create(fContext, props);
144 }
145
146 return fTextContexts[props.pixelGeometry()][useDIF];
147}
148
149GrDrawTarget* GrDrawingManager::newDrawTarget(GrRenderTarget* rt) {
150 SkASSERT(fContext);
151
152#ifndef ENABLE_MDB
153 // When MDB is disabled we always just return the single drawTarget
154 if (fDrawTargets.count()) {
155 SkASSERT(fDrawTargets.count() == 1);
robertphillips0dfa62c2015-11-16 06:23:31 -0800156 // In the non-MDB-world the same drawTarget gets reused for multiple render targets.
157 // Update this pointer so all the asserts are happy
158 rt->setLastDrawTarget(fDrawTargets[0]);
robertphillips3dc6ae52015-10-20 09:54:32 -0700159 // DrawingManager gets the creation ref - this ref is for the caller
160 return SkRef(fDrawTargets[0]);
161 }
162#endif
163
bsalomon69cfe952015-11-30 13:27:47 -0800164 GrDrawTarget* dt = new GrDrawTarget(rt, fContext->getGpu(), fContext->resourceProvider(),
165 fOptionsForDrawTargets);
robertphillips3dc6ae52015-10-20 09:54:32 -0700166
167 *fDrawTargets.append() = dt;
168
169 // DrawingManager gets the creation ref - this ref is for the caller
170 return SkRef(dt);
171}
172
robertphillips68737822015-10-29 12:12:21 -0700173/*
174 * This method finds a path renderer that can draw the specified path on
175 * the provided target.
176 * Due to its expense, the software path renderer has split out so it can
177 * can be individually allowed/disallowed via the "allowSW" boolean.
178 */
179GrPathRenderer* GrDrawingManager::getPathRenderer(const GrPathRenderer::CanDrawPathArgs& args,
180 bool allowSW,
181 GrPathRendererChain::DrawType drawType,
182 GrPathRenderer::StencilSupport* stencilSupport) {
183
184 if (!fPathRendererChain) {
185 fPathRendererChain = new GrPathRendererChain(fContext);
186 }
187
188 GrPathRenderer* pr = fPathRendererChain->getPathRenderer(args, drawType, stencilSupport);
189 if (!pr && allowSW) {
190 if (!fSoftwarePathRenderer) {
191 fSoftwarePathRenderer = new GrSoftwarePathRenderer(fContext);
192 }
193 pr = fSoftwarePathRenderer;
194 }
195
196 return pr;
197}
198
199GrDrawContext* GrDrawingManager::drawContext(GrRenderTarget* rt,
robertphillips3dc6ae52015-10-20 09:54:32 -0700200 const SkSurfaceProps* surfaceProps) {
201 if (this->abandoned()) {
202 return nullptr;
203 }
204
205 return new GrDrawContext(this, rt, surfaceProps);
206}