blob: 6e84f22e2cc7e05f98c26c1bbf7152587f2aa313 [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
robertphillips3dc6ae52015-10-20 09:54:32 -070023 fDrawTargets[i]->unref();
24 }
25
26 fDrawTargets.reset();
27
28 delete fNVPRTextContext;
29 fNVPRTextContext = nullptr;
30
31 for (int i = 0; i < kNumPixelGeometries; ++i) {
32 delete fTextContexts[i][0];
33 fTextContexts[i][0] = nullptr;
34 delete fTextContexts[i][1];
35 fTextContexts[i][1] = nullptr;
36 }
robertphillips68737822015-10-29 12:12:21 -070037
robertphillips13391dd2015-10-30 05:15:11 -070038 delete fPathRendererChain;
39 fPathRendererChain = nullptr;
robertphillips68737822015-10-29 12:12:21 -070040 SkSafeSetNull(fSoftwarePathRenderer);
robertphillips3dc6ae52015-10-20 09:54:32 -070041}
42
43GrDrawingManager::~GrDrawingManager() {
44 this->cleanup();
45}
46
47void GrDrawingManager::abandon() {
48 fAbandoned = true;
49 this->cleanup();
50}
51
robertphillips68737822015-10-29 12:12:21 -070052void GrDrawingManager::freeGpuResources() {
53 // a path renderer may be holding onto resources
robertphillips13391dd2015-10-30 05:15:11 -070054 delete fPathRendererChain;
55 fPathRendererChain = nullptr;
robertphillips68737822015-10-29 12:12:21 -070056 SkSafeSetNull(fSoftwarePathRenderer);
57}
58
robertphillips3dc6ae52015-10-20 09:54:32 -070059void GrDrawingManager::reset() {
60 for (int i = 0; i < fDrawTargets.count(); ++i) {
61 fDrawTargets[i]->reset();
62 }
robertphillipsa13e2022015-11-11 12:01:09 -080063 fFlushState.reset();
robertphillips3dc6ae52015-10-20 09:54:32 -070064}
65
66void GrDrawingManager::flush() {
67 SkDEBUGCODE(bool result =)
68 SkTTopoSort<GrDrawTarget, GrDrawTarget::TopoSortTraits>(&fDrawTargets);
69 SkASSERT(result);
70
robertphillipsa13e2022015-11-11 12:01:09 -080071#if 0
robertphillips3dc6ae52015-10-20 09:54:32 -070072 for (int i = 0; i < fDrawTargets.count(); ++i) {
robertphillipsa13e2022015-11-11 12:01:09 -080073 SkDEBUGCODE(fDrawTargets[i]->dump();)
robertphillips3dc6ae52015-10-20 09:54:32 -070074 }
robertphillipsa13e2022015-11-11 12:01:09 -080075#endif
76
77 for (int i = 0; i < fDrawTargets.count(); ++i) {
78 fDrawTargets[i]->prepareBatches(&fFlushState);
79 }
80
81 // Upload all data to the GPU
82 fFlushState.preIssueDraws();
83
84 for (int i = 0; i < fDrawTargets.count(); ++i) {
85 fDrawTargets[i]->drawBatches(&fFlushState);
86 }
87
88 SkASSERT(fFlushState.lastFlushedToken() == fFlushState.currentToken());
robertphillips3dc6ae52015-10-20 09:54:32 -070089
robertphillips0dfa62c2015-11-16 06:23:31 -080090 for (int i = 0; i < fDrawTargets.count(); ++i) {
91 fDrawTargets[i]->reset();
92#ifdef ENABLE_MDB
93 fDrawTargets[i]->unref();
94#endif
95 }
96
robertphillips3dc6ae52015-10-20 09:54:32 -070097#ifndef ENABLE_MDB
98 // When MDB is disabled we keep reusing the same drawTarget
99 if (fDrawTargets.count()) {
100 SkASSERT(fDrawTargets.count() == 1);
robertphillips0dfa62c2015-11-16 06:23:31 -0800101 // Clear out this flag so the topological sort's SkTTopoSort_CheckAllUnmarked check
102 // won't bark
robertphillips3dc6ae52015-10-20 09:54:32 -0700103 fDrawTargets[0]->resetFlag(GrDrawTarget::kWasOutput_Flag);
104 }
robertphillips0dfa62c2015-11-16 06:23:31 -0800105#else
106 fDrawTargets.reset();
robertphillips3dc6ae52015-10-20 09:54:32 -0700107#endif
robertphillipsa13e2022015-11-11 12:01:09 -0800108
robertphillipsa13e2022015-11-11 12:01:09 -0800109 fFlushState.reset();
robertphillips3dc6ae52015-10-20 09:54:32 -0700110}
111
112GrTextContext* GrDrawingManager::textContext(const SkSurfaceProps& props,
113 GrRenderTarget* rt) {
114 if (this->abandoned()) {
115 return nullptr;
116 }
117
118 SkASSERT(props.pixelGeometry() < kNumPixelGeometries);
119 bool useDIF = props.isUseDeviceIndependentFonts();
120
121 if (useDIF && fContext->caps()->shaderCaps()->pathRenderingSupport() &&
122 rt->isStencilBufferMultisampled()) {
123 GrStencilAttachment* sb = fContext->resourceProvider()->attachStencilAttachment(rt);
124 if (sb) {
125 if (!fNVPRTextContext) {
126 fNVPRTextContext = GrStencilAndCoverTextContext::Create(fContext, props);
127 }
128
129 return fNVPRTextContext;
130 }
131 }
132
133 if (!fTextContexts[props.pixelGeometry()][useDIF]) {
134 fTextContexts[props.pixelGeometry()][useDIF] = GrAtlasTextContext::Create(fContext, props);
135 }
136
137 return fTextContexts[props.pixelGeometry()][useDIF];
138}
139
140GrDrawTarget* GrDrawingManager::newDrawTarget(GrRenderTarget* rt) {
141 SkASSERT(fContext);
142
143#ifndef ENABLE_MDB
144 // When MDB is disabled we always just return the single drawTarget
145 if (fDrawTargets.count()) {
146 SkASSERT(fDrawTargets.count() == 1);
robertphillips0dfa62c2015-11-16 06:23:31 -0800147 // In the non-MDB-world the same drawTarget gets reused for multiple render targets.
148 // Update this pointer so all the asserts are happy
149 rt->setLastDrawTarget(fDrawTargets[0]);
robertphillips3dc6ae52015-10-20 09:54:32 -0700150 // DrawingManager gets the creation ref - this ref is for the caller
151 return SkRef(fDrawTargets[0]);
152 }
153#endif
154
bsalomon69cfe952015-11-30 13:27:47 -0800155 GrDrawTarget* dt = new GrDrawTarget(rt, fContext->getGpu(), fContext->resourceProvider(),
156 fOptionsForDrawTargets);
robertphillips3dc6ae52015-10-20 09:54:32 -0700157
158 *fDrawTargets.append() = dt;
159
160 // DrawingManager gets the creation ref - this ref is for the caller
161 return SkRef(dt);
162}
163
robertphillips68737822015-10-29 12:12:21 -0700164/*
165 * This method finds a path renderer that can draw the specified path on
166 * the provided target.
167 * Due to its expense, the software path renderer has split out so it can
168 * can be individually allowed/disallowed via the "allowSW" boolean.
169 */
170GrPathRenderer* GrDrawingManager::getPathRenderer(const GrPathRenderer::CanDrawPathArgs& args,
171 bool allowSW,
172 GrPathRendererChain::DrawType drawType,
173 GrPathRenderer::StencilSupport* stencilSupport) {
174
175 if (!fPathRendererChain) {
176 fPathRendererChain = new GrPathRendererChain(fContext);
177 }
178
179 GrPathRenderer* pr = fPathRendererChain->getPathRenderer(args, drawType, stencilSupport);
180 if (!pr && allowSW) {
181 if (!fSoftwarePathRenderer) {
182 fSoftwarePathRenderer = new GrSoftwarePathRenderer(fContext);
183 }
184 pr = fSoftwarePathRenderer;
185 }
186
187 return pr;
188}
189
190GrDrawContext* GrDrawingManager::drawContext(GrRenderTarget* rt,
robertphillips3dc6ae52015-10-20 09:54:32 -0700191 const SkSurfaceProps* surfaceProps) {
192 if (this->abandoned()) {
193 return nullptr;
194 }
195
196 return new GrDrawContext(this, rt, surfaceProps);
197}