blob: d670e16b731b2a38ef41fa5c7bb43208aef75095 [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
bsalomon5eb41fd2016-09-06 13:49:32 -07008#include "GrDrawingManager.h"
bsalomonb77a9072016-09-07 10:02:04 -07009
10#include "GrContext.h"
Brian Osman11052242016-10-27 14:47:55 -040011#include "GrRenderTargetContext.h"
12#include "GrPathRenderingRenderTargetContext.h"
Robert Phillipsc7635fa2016-10-28 13:25:24 -040013#include "GrRenderTargetProxy.h"
robertphillips3dc6ae52015-10-20 09:54:32 -070014#include "GrResourceProvider.h"
robertphillips68737822015-10-29 12:12:21 -070015#include "GrSoftwarePathRenderer.h"
bsalomon6a2b1942016-09-08 11:28:59 -070016#include "GrSurfacePriv.h"
Brian Osman45580d32016-11-23 09:37:01 -050017#include "GrTextureContext.h"
18#include "GrTextureOpList.h"
brianosman0e22eb82016-08-30 07:07:59 -070019#include "SkSurface_Gpu.h"
robertphillips3dc6ae52015-10-20 09:54:32 -070020#include "SkTTopoSort.h"
21
joshualitte8042922015-12-11 06:11:21 -080022#include "text/GrAtlasTextContext.h"
23#include "text/GrStencilAndCoverTextContext.h"
robertphillips498d7ac2015-10-30 10:11:30 -070024
robertphillips3dc6ae52015-10-20 09:54:32 -070025void GrDrawingManager::cleanup() {
Robert Phillipsf2361d22016-10-25 14:20:06 -040026 for (int i = 0; i < fOpLists.count(); ++i) {
27 fOpLists[i]->makeClosed(); // no opList should receive a new command after this
28 fOpLists[i]->clearTarget();
robertphillips0dfa62c2015-11-16 06:23:31 -080029
Robert Phillipsf2361d22016-10-25 14:20:06 -040030 // We shouldn't need to do this, but it turns out some clients still hold onto opLists
joshualitt20ccd402016-01-05 08:56:56 -080031 // after a cleanup
Robert Phillipsf2361d22016-10-25 14:20:06 -040032 fOpLists[i]->reset();
33 fOpLists[i]->unref();
robertphillips3dc6ae52015-10-20 09:54:32 -070034 }
35
Robert Phillipsf2361d22016-10-25 14:20:06 -040036 fOpLists.reset();
robertphillips3dc6ae52015-10-20 09:54:32 -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;
Robert Phillipsf2361d22016-10-25 14:20:06 -040049 for (int i = 0; i < fOpLists.count(); ++i) {
50 fOpLists[i]->abandonGpuResources();
csmartdaltona7f29642016-07-07 08:49:11 -070051 }
robertphillips3dc6ae52015-10-20 09:54:32 -070052 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);
Robert Phillipsf2361d22016-10-25 14:20:06 -040060 for (int i = 0; i < fOpLists.count(); ++i) {
61 fOpLists[i]->freeGpuResources();
csmartdaltona7f29642016-07-07 08:49:11 -070062 }
robertphillips68737822015-10-29 12:12:21 -070063}
64
robertphillips3dc6ae52015-10-20 09:54:32 -070065void GrDrawingManager::reset() {
Robert Phillipsf2361d22016-10-25 14:20:06 -040066 for (int i = 0; i < fOpLists.count(); ++i) {
67 fOpLists[i]->reset();
robertphillips3dc6ae52015-10-20 09:54:32 -070068 }
robertphillipsa13e2022015-11-11 12:01:09 -080069 fFlushState.reset();
robertphillips3dc6ae52015-10-20 09:54:32 -070070}
71
bsalomonb77a9072016-09-07 10:02:04 -070072void GrDrawingManager::internalFlush(GrResourceCache::FlushType type) {
robertphillips7761d612016-05-16 09:14:53 -070073 if (fFlushing || this->wasAbandoned()) {
bsalomonb77a9072016-09-07 10:02:04 -070074 return;
joshualittb8918c42015-12-18 09:59:46 -080075 }
76 fFlushing = true;
bsalomondc438982016-08-31 11:53:49 -070077 bool flushed = false;
halcanary9d524f22016-03-29 09:03:52 -070078 SkDEBUGCODE(bool result =)
Robert Phillipsf2361d22016-10-25 14:20:06 -040079 SkTTopoSort<GrOpList, GrOpList::TopoSortTraits>(&fOpLists);
robertphillips3dc6ae52015-10-20 09:54:32 -070080 SkASSERT(result);
81
Robert Phillipsf2361d22016-10-25 14:20:06 -040082 for (int i = 0; i < fOpLists.count(); ++i) {
Brian Salomon1e41f4a2016-12-07 15:05:04 -050083 fOpLists[i]->prepareOps(&fFlushState);
robertphillips27fe1f82016-06-29 13:43:22 -070084 }
85
robertphillipsa13e2022015-11-11 12:01:09 -080086#if 0
Brian Salomon09d994e2016-12-21 11:14:46 -050087 // Enable this to print out verbose GrOp information
Robert Phillipsf2361d22016-10-25 14:20:06 -040088 for (int i = 0; i < fOpLists.count(); ++i) {
89 SkDEBUGCODE(fOpLists[i]->dump();)
robertphillips3dc6ae52015-10-20 09:54:32 -070090 }
robertphillipsa13e2022015-11-11 12:01:09 -080091#endif
92
robertphillipsa13e2022015-11-11 12:01:09 -080093 // Upload all data to the GPU
94 fFlushState.preIssueDraws();
95
Robert Phillipsf2361d22016-10-25 14:20:06 -040096 for (int i = 0; i < fOpLists.count(); ++i) {
Brian Salomon1e41f4a2016-12-07 15:05:04 -050097 if (fOpLists[i]->executeOps(&fFlushState)) {
bsalomondc438982016-08-31 11:53:49 -070098 flushed = true;
99 }
robertphillipsa13e2022015-11-11 12:01:09 -0800100 }
101
bsalomon342bfc22016-04-01 06:06:20 -0700102 SkASSERT(fFlushState.nextDrawToken() == fFlushState.nextTokenToFlush());
robertphillips3dc6ae52015-10-20 09:54:32 -0700103
Robert Phillipsf2361d22016-10-25 14:20:06 -0400104 for (int i = 0; i < fOpLists.count(); ++i) {
105 fOpLists[i]->reset();
robertphillips0dfa62c2015-11-16 06:23:31 -0800106#ifdef ENABLE_MDB
Robert Phillipsf2361d22016-10-25 14:20:06 -0400107 fOpLists[i]->unref();
robertphillips0dfa62c2015-11-16 06:23:31 -0800108#endif
109 }
110
robertphillips3dc6ae52015-10-20 09:54:32 -0700111#ifndef ENABLE_MDB
Robert Phillipsf2361d22016-10-25 14:20:06 -0400112 // When MDB is disabled we keep reusing the same GrOpList
113 if (fOpLists.count()) {
114 SkASSERT(fOpLists.count() == 1);
robertphillips0dfa62c2015-11-16 06:23:31 -0800115 // Clear out this flag so the topological sort's SkTTopoSort_CheckAllUnmarked check
116 // won't bark
Robert Phillipsf2361d22016-10-25 14:20:06 -0400117 fOpLists[0]->resetFlag(GrOpList::kWasOutput_Flag);
robertphillips3dc6ae52015-10-20 09:54:32 -0700118 }
robertphillips0dfa62c2015-11-16 06:23:31 -0800119#else
Robert Phillipsf2361d22016-10-25 14:20:06 -0400120 fOpLists.reset();
robertphillips3dc6ae52015-10-20 09:54:32 -0700121#endif
robertphillipsa13e2022015-11-11 12:01:09 -0800122
robertphillipsa13e2022015-11-11 12:01:09 -0800123 fFlushState.reset();
robertphillipsee843b22016-10-04 05:30:20 -0700124 // We always have to notify the cache when it requested a flush so it can reset its state.
125 if (flushed || type == GrResourceCache::FlushType::kCacheRequested) {
bsalomonb77a9072016-09-07 10:02:04 -0700126 fContext->getResourceCache()->notifyFlushOccurred(type);
127 }
joshualittb8918c42015-12-18 09:59:46 -0800128 fFlushing = false;
robertphillips3dc6ae52015-10-20 09:54:32 -0700129}
130
bsalomon6a2b1942016-09-08 11:28:59 -0700131void GrDrawingManager::prepareSurfaceForExternalIO(GrSurface* surface) {
132 if (this->wasAbandoned()) {
133 return;
134 }
135 SkASSERT(surface);
136 SkASSERT(surface->getContext() == fContext);
137
138 if (surface->surfacePriv().hasPendingIO()) {
139 this->flush();
140 }
141
142 GrRenderTarget* rt = surface->asRenderTarget();
143 if (fContext->getGpu() && rt) {
144 fContext->getGpu()->resolveRenderTarget(rt);
145 }
146}
147
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400148GrRenderTargetOpList* GrDrawingManager::newOpList(GrRenderTargetProxy* rtp) {
robertphillips3dc6ae52015-10-20 09:54:32 -0700149 SkASSERT(fContext);
150
151#ifndef ENABLE_MDB
Robert Phillipsf2361d22016-10-25 14:20:06 -0400152 // When MDB is disabled we always just return the single GrOpList
153 if (fOpLists.count()) {
154 SkASSERT(fOpLists.count() == 1);
155 // In the non-MDB-world the same GrOpList gets reused for multiple render targets.
robertphillips0dfa62c2015-11-16 06:23:31 -0800156 // Update this pointer so all the asserts are happy
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400157 rtp->setLastOpList(fOpLists[0]);
robertphillips3dc6ae52015-10-20 09:54:32 -0700158 // DrawingManager gets the creation ref - this ref is for the caller
Robert Phillipsf2361d22016-10-25 14:20:06 -0400159
160 // TODO: although this is true right now it isn't cool
161 return SkRef((GrRenderTargetOpList*) fOpLists[0]);
robertphillips3dc6ae52015-10-20 09:54:32 -0700162 }
163#endif
164
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400165 GrRenderTargetOpList* opList = new GrRenderTargetOpList(rtp,
Robert Phillipsf2361d22016-10-25 14:20:06 -0400166 fContext->getGpu(),
167 fContext->resourceProvider(),
168 fContext->getAuditTrail(),
169 fOptionsForOpLists);
robertphillips3dc6ae52015-10-20 09:54:32 -0700170
Robert Phillipsf2361d22016-10-25 14:20:06 -0400171 *fOpLists.append() = opList;
robertphillips3dc6ae52015-10-20 09:54:32 -0700172
halcanary9d524f22016-03-29 09:03:52 -0700173 // DrawingManager gets the creation ref - this ref is for the caller
Robert Phillipsf2361d22016-10-25 14:20:06 -0400174 return SkRef(opList);
robertphillips3dc6ae52015-10-20 09:54:32 -0700175}
176
Brian Osman45580d32016-11-23 09:37:01 -0500177GrTextureOpList* GrDrawingManager::newOpList(GrTextureProxy* textureProxy) {
178 SkASSERT(fContext);
179
180 GrTextureOpList* opList = new GrTextureOpList(textureProxy, fContext->getGpu(),
181 fContext->getAuditTrail());
182
183#ifndef ENABLE_MDB
184 // When MDB is disabled we still create a new GrOpList, but don't store or ref it - we rely
185 // on the caller to immediately execute and free it.
186 return opList;
187#else
188 *fOpLists.append() = opList;
189
190 // Drawing manager gets the creation ref - this ref is for the caller
191 return SkRef(opList);
192#endif
193}
194
brianosman86e76262016-08-11 12:17:31 -0700195GrAtlasTextContext* GrDrawingManager::getAtlasTextContext() {
196 if (!fAtlasTextContext) {
197 fAtlasTextContext.reset(GrAtlasTextContext::Create());
198 }
199
200 return fAtlasTextContext.get();
201}
202
robertphillips68737822015-10-29 12:12:21 -0700203/*
204 * This method finds a path renderer that can draw the specified path on
205 * the provided target.
206 * Due to its expense, the software path renderer has split out so it can
207 * can be individually allowed/disallowed via the "allowSW" boolean.
208 */
209GrPathRenderer* GrDrawingManager::getPathRenderer(const GrPathRenderer::CanDrawPathArgs& args,
210 bool allowSW,
211 GrPathRendererChain::DrawType drawType,
212 GrPathRenderer::StencilSupport* stencilSupport) {
213
214 if (!fPathRendererChain) {
bsalomon6b2552f2016-09-15 13:50:26 -0700215 fPathRendererChain = new GrPathRendererChain(fContext, fOptionsForPathRendererChain);
robertphillips68737822015-10-29 12:12:21 -0700216 }
217
218 GrPathRenderer* pr = fPathRendererChain->getPathRenderer(args, drawType, stencilSupport);
219 if (!pr && allowSW) {
220 if (!fSoftwarePathRenderer) {
bsalomon39ef7fb2016-09-21 11:16:05 -0700221 fSoftwarePathRenderer =
Brian Osman32342f02017-03-04 08:12:46 -0500222 new GrSoftwarePathRenderer(fContext->resourceProvider(),
bsalomon39ef7fb2016-09-21 11:16:05 -0700223 fOptionsForPathRendererChain.fAllowPathMaskCaching);
robertphillips68737822015-10-29 12:12:21 -0700224 }
Brian Salomon0e8fc8b2016-12-09 15:10:07 -0500225 if (fSoftwarePathRenderer->canDrawPath(args)) {
226 pr = fSoftwarePathRenderer;
227 }
robertphillips68737822015-10-29 12:12:21 -0700228 }
229
230 return pr;
231}
232
Brian Osman11052242016-10-27 14:47:55 -0400233sk_sp<GrRenderTargetContext> GrDrawingManager::makeRenderTargetContext(
Robert Phillips37430132016-11-09 06:50:43 -0500234 sk_sp<GrSurfaceProxy> sProxy,
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400235 sk_sp<SkColorSpace> colorSpace,
236 const SkSurfaceProps* surfaceProps) {
Robert Phillips37430132016-11-09 06:50:43 -0500237 if (this->wasAbandoned() || !sProxy->asRenderTargetProxy()) {
robertphillips3dc6ae52015-10-20 09:54:32 -0700238 return nullptr;
239 }
240
brianosman0e22eb82016-08-30 07:07:59 -0700241 // SkSurface catches bad color space usage at creation. This check handles anything that slips
242 // by, including internal usage. We allow a null color space here, for read/write pixels and
243 // other special code paths. If a color space is provided, though, enforce all other rules.
Robert Phillips2c862492017-01-18 10:08:39 -0500244 if (colorSpace && !SkSurface_Gpu::Valid(fContext, sProxy->config(), colorSpace.get())) {
brianosmana9c3c6a2016-09-29 10:08:36 -0700245 SkDEBUGFAIL("Invalid config and colorspace combination");
brianosman0e22eb82016-08-30 07:07:59 -0700246 return nullptr;
247 }
joshualitt96880d92016-02-16 10:36:53 -0800248
Robert Phillips2c862492017-01-18 10:08:39 -0500249 sk_sp<GrRenderTargetProxy> rtp(sk_ref_sp(sProxy->asRenderTargetProxy()));
250
joshualitt96880d92016-02-16 10:36:53 -0800251 bool useDIF = false;
252 if (surfaceProps) {
253 useDIF = surfaceProps->isUseDeviceIndependentFonts();
254 }
255
256 if (useDIF && fContext->caps()->shaderCaps()->pathRenderingSupport() &&
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400257 rtp->isStencilBufferMultisampled()) {
258 // TODO: defer stencil buffer attachment for PathRenderingDrawContext
Brian Osman32342f02017-03-04 08:12:46 -0500259 sk_sp<GrRenderTarget> rt(sk_ref_sp(rtp->instantiate(fContext->resourceProvider())));
Robert Phillipse60ad622016-11-17 10:22:48 -0500260 if (!rt) {
261 return nullptr;
262 }
robertphillips6c7e3252016-04-27 10:47:51 -0700263 GrStencilAttachment* sb = fContext->resourceProvider()->attachStencilAttachment(rt.get());
joshualitt96880d92016-02-16 10:36:53 -0800264 if (sb) {
Brian Osman11052242016-10-27 14:47:55 -0400265 return sk_sp<GrRenderTargetContext>(new GrPathRenderingRenderTargetContext(
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400266 fContext, this, std::move(rtp),
brianosmandfe4f2e2016-07-21 13:28:36 -0700267 std::move(colorSpace), surfaceProps,
robertphillips6c7e3252016-04-27 10:47:51 -0700268 fContext->getAuditTrail(), fSingleOwner));
joshualitt96880d92016-02-16 10:36:53 -0800269 }
270 }
271
Robert Phillipsc7635fa2016-10-28 13:25:24 -0400272 return sk_sp<GrRenderTargetContext>(new GrRenderTargetContext(fContext, this, std::move(rtp),
Brian Osman11052242016-10-27 14:47:55 -0400273 std::move(colorSpace),
274 surfaceProps,
275 fContext->getAuditTrail(),
276 fSingleOwner));
robertphillips3dc6ae52015-10-20 09:54:32 -0700277}
Brian Osman45580d32016-11-23 09:37:01 -0500278
Robert Phillips2c862492017-01-18 10:08:39 -0500279sk_sp<GrTextureContext> GrDrawingManager::makeTextureContext(sk_sp<GrSurfaceProxy> sProxy,
280 sk_sp<SkColorSpace> colorSpace) {
Brian Osman45580d32016-11-23 09:37:01 -0500281 if (this->wasAbandoned() || !sProxy->asTextureProxy()) {
282 return nullptr;
283 }
284
Robert Phillips2c862492017-01-18 10:08:39 -0500285 // SkSurface catches bad color space usage at creation. This check handles anything that slips
286 // by, including internal usage. We allow a null color space here, for read/write pixels and
287 // other special code paths. If a color space is provided, though, enforce all other rules.
288 if (colorSpace && !SkSurface_Gpu::Valid(fContext, sProxy->config(), colorSpace.get())) {
289 SkDEBUGFAIL("Invalid config and colorspace combination");
290 return nullptr;
291 }
292
Brian Osman45580d32016-11-23 09:37:01 -0500293 // GrTextureRenderTargets should always be using GrRenderTargetContext
294 SkASSERT(!sProxy->asRenderTargetProxy());
295
296 sk_sp<GrTextureProxy> textureProxy(sk_ref_sp(sProxy->asTextureProxy()));
297
298 return sk_sp<GrTextureContext>(new GrTextureContext(fContext, this, std::move(textureProxy),
Robert Phillips2c862492017-01-18 10:08:39 -0500299 std::move(colorSpace),
300 fContext->getAuditTrail(),
301 fSingleOwner));
Brian Osman45580d32016-11-23 09:37:01 -0500302}