blob: 6c75c0d1474512a7db41b860f89a7e7680f1cca7 [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"
brianosman0e22eb82016-08-30 07:07:59 -070014#include "SkSurface_Gpu.h"
robertphillips3dc6ae52015-10-20 09:54:32 -070015#include "SkTTopoSort.h"
16
csmartdaltona7f29642016-07-07 08:49:11 -070017#include "instanced/InstancedRendering.h"
18
joshualitte8042922015-12-11 06:11:21 -080019#include "text/GrAtlasTextContext.h"
20#include "text/GrStencilAndCoverTextContext.h"
robertphillips498d7ac2015-10-30 10:11:30 -070021
csmartdaltona7f29642016-07-07 08:49:11 -070022using gr_instanced::InstancedRendering;
23
robertphillips3dc6ae52015-10-20 09:54:32 -070024void GrDrawingManager::cleanup() {
25 for (int i = 0; i < fDrawTargets.count(); ++i) {
robertphillips0dfa62c2015-11-16 06:23:31 -080026 fDrawTargets[i]->makeClosed(); // no drawTarget should receive a new command after this
27 fDrawTargets[i]->clearRT();
28
joshualitt20ccd402016-01-05 08:56:56 -080029 // We shouldn't need to do this, but it turns out some clients still hold onto drawtargets
30 // after a cleanup
31 fDrawTargets[i]->reset();
robertphillips3dc6ae52015-10-20 09:54:32 -070032 fDrawTargets[i]->unref();
33 }
34
35 fDrawTargets.reset();
36
robertphillips13391dd2015-10-30 05:15:11 -070037 delete fPathRendererChain;
38 fPathRendererChain = nullptr;
robertphillips68737822015-10-29 12:12:21 -070039 SkSafeSetNull(fSoftwarePathRenderer);
robertphillips3dc6ae52015-10-20 09:54:32 -070040}
41
42GrDrawingManager::~GrDrawingManager() {
43 this->cleanup();
44}
45
46void GrDrawingManager::abandon() {
47 fAbandoned = true;
csmartdaltona7f29642016-07-07 08:49:11 -070048 for (int i = 0; i < fDrawTargets.count(); ++i) {
csmartdaltone0d36292016-07-29 08:14:20 -070049 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
50 InstancedRendering* ir = fDrawTargets[i]->instancedRendering();
csmartdaltona7f29642016-07-07 08:49:11 -070051 ir->resetGpuResources(InstancedRendering::ResetType::kAbandon);
52 }
53 }
robertphillips3dc6ae52015-10-20 09:54:32 -070054 this->cleanup();
55}
56
robertphillips68737822015-10-29 12:12:21 -070057void GrDrawingManager::freeGpuResources() {
58 // a path renderer may be holding onto resources
robertphillips13391dd2015-10-30 05:15:11 -070059 delete fPathRendererChain;
60 fPathRendererChain = nullptr;
robertphillips68737822015-10-29 12:12:21 -070061 SkSafeSetNull(fSoftwarePathRenderer);
csmartdaltona7f29642016-07-07 08:49:11 -070062 for (int i = 0; i < fDrawTargets.count(); ++i) {
csmartdaltone0d36292016-07-29 08:14:20 -070063 if (GrCaps::InstancedSupport::kNone != fContext->caps()->instancedSupport()) {
64 InstancedRendering* ir = fDrawTargets[i]->instancedRendering();
csmartdaltona7f29642016-07-07 08:49:11 -070065 ir->resetGpuResources(InstancedRendering::ResetType::kDestroy);
66 }
67 }
robertphillips68737822015-10-29 12:12:21 -070068}
69
robertphillips3dc6ae52015-10-20 09:54:32 -070070void GrDrawingManager::reset() {
71 for (int i = 0; i < fDrawTargets.count(); ++i) {
72 fDrawTargets[i]->reset();
73 }
robertphillipsa13e2022015-11-11 12:01:09 -080074 fFlushState.reset();
robertphillips3dc6ae52015-10-20 09:54:32 -070075}
76
bsalomondc438982016-08-31 11:53:49 -070077bool GrDrawingManager::flush() {
robertphillips7761d612016-05-16 09:14:53 -070078 if (fFlushing || this->wasAbandoned()) {
bsalomondc438982016-08-31 11:53:49 -070079 return false;
joshualittb8918c42015-12-18 09:59:46 -080080 }
81 fFlushing = true;
bsalomondc438982016-08-31 11:53:49 -070082 bool flushed = false;
halcanary9d524f22016-03-29 09:03:52 -070083 SkDEBUGCODE(bool result =)
robertphillips3dc6ae52015-10-20 09:54:32 -070084 SkTTopoSort<GrDrawTarget, GrDrawTarget::TopoSortTraits>(&fDrawTargets);
85 SkASSERT(result);
86
robertphillips27fe1f82016-06-29 13:43:22 -070087 for (int i = 0; i < fDrawTargets.count(); ++i) {
88 fDrawTargets[i]->prepareBatches(&fFlushState);
89 }
90
robertphillips26726d12016-06-28 14:45:31 -070091 // Enable this to print out verbose batching information
robertphillipsa13e2022015-11-11 12:01:09 -080092#if 0
robertphillips3dc6ae52015-10-20 09:54:32 -070093 for (int i = 0; i < fDrawTargets.count(); ++i) {
robertphillipsa13e2022015-11-11 12:01:09 -080094 SkDEBUGCODE(fDrawTargets[i]->dump();)
robertphillips3dc6ae52015-10-20 09:54:32 -070095 }
robertphillipsa13e2022015-11-11 12:01:09 -080096#endif
97
robertphillipsa13e2022015-11-11 12:01:09 -080098 // Upload all data to the GPU
99 fFlushState.preIssueDraws();
100
101 for (int i = 0; i < fDrawTargets.count(); ++i) {
bsalomondc438982016-08-31 11:53:49 -0700102 if (fDrawTargets[i]->drawBatches(&fFlushState)) {
103 flushed = true;
104 }
robertphillipsa13e2022015-11-11 12:01:09 -0800105 }
106
bsalomon342bfc22016-04-01 06:06:20 -0700107 SkASSERT(fFlushState.nextDrawToken() == fFlushState.nextTokenToFlush());
robertphillips3dc6ae52015-10-20 09:54:32 -0700108
robertphillips0dfa62c2015-11-16 06:23:31 -0800109 for (int i = 0; i < fDrawTargets.count(); ++i) {
110 fDrawTargets[i]->reset();
111#ifdef ENABLE_MDB
112 fDrawTargets[i]->unref();
113#endif
114 }
115
robertphillips3dc6ae52015-10-20 09:54:32 -0700116#ifndef ENABLE_MDB
117 // When MDB is disabled we keep reusing the same drawTarget
118 if (fDrawTargets.count()) {
119 SkASSERT(fDrawTargets.count() == 1);
robertphillips0dfa62c2015-11-16 06:23:31 -0800120 // Clear out this flag so the topological sort's SkTTopoSort_CheckAllUnmarked check
121 // won't bark
robertphillips3dc6ae52015-10-20 09:54:32 -0700122 fDrawTargets[0]->resetFlag(GrDrawTarget::kWasOutput_Flag);
123 }
robertphillips0dfa62c2015-11-16 06:23:31 -0800124#else
125 fDrawTargets.reset();
robertphillips3dc6ae52015-10-20 09:54:32 -0700126#endif
robertphillipsa13e2022015-11-11 12:01:09 -0800127
robertphillipsa13e2022015-11-11 12:01:09 -0800128 fFlushState.reset();
joshualittb8918c42015-12-18 09:59:46 -0800129 fFlushing = false;
bsalomondc438982016-08-31 11:53:49 -0700130 return flushed;
robertphillips3dc6ae52015-10-20 09:54:32 -0700131}
132
robertphillips3dc6ae52015-10-20 09:54:32 -0700133GrDrawTarget* GrDrawingManager::newDrawTarget(GrRenderTarget* rt) {
134 SkASSERT(fContext);
135
136#ifndef ENABLE_MDB
137 // When MDB is disabled we always just return the single drawTarget
138 if (fDrawTargets.count()) {
139 SkASSERT(fDrawTargets.count() == 1);
robertphillips0dfa62c2015-11-16 06:23:31 -0800140 // In the non-MDB-world the same drawTarget gets reused for multiple render targets.
141 // Update this pointer so all the asserts are happy
142 rt->setLastDrawTarget(fDrawTargets[0]);
robertphillips3dc6ae52015-10-20 09:54:32 -0700143 // DrawingManager gets the creation ref - this ref is for the caller
144 return SkRef(fDrawTargets[0]);
145 }
146#endif
147
bsalomon69cfe952015-11-30 13:27:47 -0800148 GrDrawTarget* dt = new GrDrawTarget(rt, fContext->getGpu(), fContext->resourceProvider(),
joshualitt086cee12016-01-12 06:45:24 -0800149 fContext->getAuditTrail(), fOptionsForDrawTargets);
robertphillips3dc6ae52015-10-20 09:54:32 -0700150
151 *fDrawTargets.append() = dt;
152
halcanary9d524f22016-03-29 09:03:52 -0700153 // DrawingManager gets the creation ref - this ref is for the caller
robertphillips3dc6ae52015-10-20 09:54:32 -0700154 return SkRef(dt);
155}
156
brianosman86e76262016-08-11 12:17:31 -0700157GrAtlasTextContext* GrDrawingManager::getAtlasTextContext() {
158 if (!fAtlasTextContext) {
159 fAtlasTextContext.reset(GrAtlasTextContext::Create());
160 }
161
162 return fAtlasTextContext.get();
163}
164
robertphillips68737822015-10-29 12:12:21 -0700165/*
166 * This method finds a path renderer that can draw the specified path on
167 * the provided target.
168 * Due to its expense, the software path renderer has split out so it can
169 * can be individually allowed/disallowed via the "allowSW" boolean.
170 */
171GrPathRenderer* GrDrawingManager::getPathRenderer(const GrPathRenderer::CanDrawPathArgs& args,
172 bool allowSW,
173 GrPathRendererChain::DrawType drawType,
174 GrPathRenderer::StencilSupport* stencilSupport) {
175
176 if (!fPathRendererChain) {
177 fPathRendererChain = new GrPathRendererChain(fContext);
178 }
179
180 GrPathRenderer* pr = fPathRendererChain->getPathRenderer(args, drawType, stencilSupport);
181 if (!pr && allowSW) {
182 if (!fSoftwarePathRenderer) {
robertphillips0152d732016-05-20 06:38:43 -0700183 fSoftwarePathRenderer = new GrSoftwarePathRenderer(fContext->textureProvider());
robertphillips68737822015-10-29 12:12:21 -0700184 }
185 pr = fSoftwarePathRenderer;
186 }
187
188 return pr;
189}
190
robertphillips29f9fe42016-08-05 09:28:20 -0700191sk_sp<GrDrawContext> GrDrawingManager::makeDrawContext(sk_sp<GrRenderTarget> rt,
192 sk_sp<SkColorSpace> colorSpace,
193 const SkSurfaceProps* surfaceProps) {
robertphillips7761d612016-05-16 09:14:53 -0700194 if (this->wasAbandoned()) {
robertphillips3dc6ae52015-10-20 09:54:32 -0700195 return nullptr;
196 }
197
brianosman0e22eb82016-08-30 07:07:59 -0700198 // SkSurface catches bad color space usage at creation. This check handles anything that slips
199 // by, including internal usage. We allow a null color space here, for read/write pixels and
200 // other special code paths. If a color space is provided, though, enforce all other rules.
201 if (colorSpace && !SkSurface_Gpu::Valid(fContext, rt->config(), colorSpace.get())) {
202 return nullptr;
203 }
joshualitt96880d92016-02-16 10:36:53 -0800204
205 bool useDIF = false;
206 if (surfaceProps) {
207 useDIF = surfaceProps->isUseDeviceIndependentFonts();
208 }
209
210 if (useDIF && fContext->caps()->shaderCaps()->pathRenderingSupport() &&
211 rt->isStencilBufferMultisampled()) {
robertphillips6c7e3252016-04-27 10:47:51 -0700212 GrStencilAttachment* sb = fContext->resourceProvider()->attachStencilAttachment(rt.get());
joshualitt96880d92016-02-16 10:36:53 -0800213 if (sb) {
robertphillips6c7e3252016-04-27 10:47:51 -0700214 return sk_sp<GrDrawContext>(new GrPathRenderingDrawContext(
brianosmandfe4f2e2016-07-21 13:28:36 -0700215 fContext, this, std::move(rt),
216 std::move(colorSpace), surfaceProps,
robertphillips6c7e3252016-04-27 10:47:51 -0700217 fContext->getAuditTrail(), fSingleOwner));
joshualitt96880d92016-02-16 10:36:53 -0800218 }
219 }
220
brianosmandfe4f2e2016-07-21 13:28:36 -0700221 return sk_sp<GrDrawContext>(new GrDrawContext(fContext, this, std::move(rt),
222 std::move(colorSpace), surfaceProps,
robertphillips6c7e3252016-04-27 10:47:51 -0700223 fContext->getAuditTrail(),
224 fSingleOwner));
robertphillips3dc6ae52015-10-20 09:54:32 -0700225}