blob: 976fbb62a49e0c8ec499ce7f0a66fb6afa295cca [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"
joshualitt96880d92016-02-16 10:36:53 -080011#include "GrPathRenderingDrawContext.h"
robertphillips3dc6ae52015-10-20 09:54:32 -070012#include "GrResourceProvider.h"
robertphillips68737822015-10-29 12:12:21 -070013#include "GrSoftwarePathRenderer.h"
robertphillips3dc6ae52015-10-20 09:54:32 -070014#include "SkTTopoSort.h"
15
joshualitte8042922015-12-11 06:11:21 -080016#include "text/GrAtlasTextContext.h"
17#include "text/GrStencilAndCoverTextContext.h"
robertphillips498d7ac2015-10-30 10:11:30 -070018
robertphillips3dc6ae52015-10-20 09:54:32 -070019void GrDrawingManager::cleanup() {
20 for (int i = 0; i < fDrawTargets.count(); ++i) {
robertphillips0dfa62c2015-11-16 06:23:31 -080021 fDrawTargets[i]->makeClosed(); // no drawTarget should receive a new command after this
22 fDrawTargets[i]->clearRT();
23
joshualitt20ccd402016-01-05 08:56:56 -080024 // 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();
robertphillips3dc6ae52015-10-20 09:54:32 -070027 fDrawTargets[i]->unref();
28 }
29
30 fDrawTargets.reset();
31
robertphillips13391dd2015-10-30 05:15:11 -070032 delete fPathRendererChain;
33 fPathRendererChain = nullptr;
robertphillips68737822015-10-29 12:12:21 -070034 SkSafeSetNull(fSoftwarePathRenderer);
robertphillips3dc6ae52015-10-20 09:54:32 -070035}
36
37GrDrawingManager::~GrDrawingManager() {
38 this->cleanup();
39}
40
41void GrDrawingManager::abandon() {
42 fAbandoned = true;
43 this->cleanup();
44}
45
robertphillips68737822015-10-29 12:12:21 -070046void GrDrawingManager::freeGpuResources() {
47 // a path renderer may be holding onto resources
robertphillips13391dd2015-10-30 05:15:11 -070048 delete fPathRendererChain;
49 fPathRendererChain = nullptr;
robertphillips68737822015-10-29 12:12:21 -070050 SkSafeSetNull(fSoftwarePathRenderer);
51}
52
robertphillips3dc6ae52015-10-20 09:54:32 -070053void GrDrawingManager::reset() {
54 for (int i = 0; i < fDrawTargets.count(); ++i) {
55 fDrawTargets[i]->reset();
56 }
robertphillipsa13e2022015-11-11 12:01:09 -080057 fFlushState.reset();
robertphillips3dc6ae52015-10-20 09:54:32 -070058}
59
60void GrDrawingManager::flush() {
joshualitt719c4802016-02-09 10:09:55 -080061 if (fFlushing || this->abandoned()) {
joshualittb8918c42015-12-18 09:59:46 -080062 return;
63 }
64 fFlushing = true;
65
halcanary9d524f22016-03-29 09:03:52 -070066 SkDEBUGCODE(bool result =)
robertphillips3dc6ae52015-10-20 09:54:32 -070067 SkTTopoSort<GrDrawTarget, GrDrawTarget::TopoSortTraits>(&fDrawTargets);
68 SkASSERT(result);
69
robertphillipsa13e2022015-11-11 12:01:09 -080070#if 0
robertphillips3dc6ae52015-10-20 09:54:32 -070071 for (int i = 0; i < fDrawTargets.count(); ++i) {
robertphillipsa13e2022015-11-11 12:01:09 -080072 SkDEBUGCODE(fDrawTargets[i]->dump();)
robertphillips3dc6ae52015-10-20 09:54:32 -070073 }
robertphillipsa13e2022015-11-11 12:01:09 -080074#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
bsalomon342bfc22016-04-01 06:06:20 -070087 SkASSERT(fFlushState.nextDrawToken() == fFlushState.nextTokenToFlush());
robertphillips3dc6ae52015-10-20 09:54:32 -070088
robertphillips0dfa62c2015-11-16 06:23:31 -080089 for (int i = 0; i < fDrawTargets.count(); ++i) {
90 fDrawTargets[i]->reset();
91#ifdef ENABLE_MDB
92 fDrawTargets[i]->unref();
93#endif
94 }
95
robertphillips3dc6ae52015-10-20 09:54:32 -070096#ifndef ENABLE_MDB
97 // When MDB is disabled we keep reusing the same drawTarget
98 if (fDrawTargets.count()) {
99 SkASSERT(fDrawTargets.count() == 1);
robertphillips0dfa62c2015-11-16 06:23:31 -0800100 // Clear out this flag so the topological sort's SkTTopoSort_CheckAllUnmarked check
101 // won't bark
robertphillips3dc6ae52015-10-20 09:54:32 -0700102 fDrawTargets[0]->resetFlag(GrDrawTarget::kWasOutput_Flag);
103 }
robertphillips0dfa62c2015-11-16 06:23:31 -0800104#else
105 fDrawTargets.reset();
robertphillips3dc6ae52015-10-20 09:54:32 -0700106#endif
robertphillipsa13e2022015-11-11 12:01:09 -0800107
robertphillipsa13e2022015-11-11 12:01:09 -0800108 fFlushState.reset();
joshualittb8918c42015-12-18 09:59:46 -0800109 fFlushing = false;
robertphillips3dc6ae52015-10-20 09:54:32 -0700110}
111
robertphillips3dc6ae52015-10-20 09:54:32 -0700112GrDrawTarget* 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);
robertphillips0dfa62c2015-11-16 06:23:31 -0800119 // 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]);
robertphillips3dc6ae52015-10-20 09:54:32 -0700122 // DrawingManager gets the creation ref - this ref is for the caller
123 return SkRef(fDrawTargets[0]);
124 }
125#endif
126
bsalomon69cfe952015-11-30 13:27:47 -0800127 GrDrawTarget* dt = new GrDrawTarget(rt, fContext->getGpu(), fContext->resourceProvider(),
joshualitt086cee12016-01-12 06:45:24 -0800128 fContext->getAuditTrail(), fOptionsForDrawTargets);
robertphillips3dc6ae52015-10-20 09:54:32 -0700129
130 *fDrawTargets.append() = dt;
131
halcanary9d524f22016-03-29 09:03:52 -0700132 // DrawingManager gets the creation ref - this ref is for the caller
robertphillips3dc6ae52015-10-20 09:54:32 -0700133 return SkRef(dt);
134}
135
robertphillips68737822015-10-29 12:12:21 -0700136/*
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 */
142GrPathRenderer* 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
162GrDrawContext* GrDrawingManager::drawContext(GrRenderTarget* rt,
robertphillips3dc6ae52015-10-20 09:54:32 -0700163 const SkSurfaceProps* surfaceProps) {
164 if (this->abandoned()) {
165 return nullptr;
166 }
167
joshualitt96880d92016-02-16 10:36:53 -0800168
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
joshualitt1b39f432016-02-11 06:46:52 -0800183 return new GrDrawContext(fContext, this, rt, surfaceProps, fContext->getAuditTrail(),
184 fSingleOwner);
robertphillips3dc6ae52015-10-20 09:54:32 -0700185}