blob: 0db31f29de983f5b9adbe48a1f819b63ea255f46 [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2010 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.
reed@google.comac10a2d2010-12-22 21:39:39 +00006 */
7
joshualittc2893c52015-01-28 06:54:30 -08008#include "GrDrawTarget.h"
joshualitt4d8da812015-01-28 12:53:54 -08009
joshualitt086cee12016-01-12 06:45:24 -080010#include "GrAuditTrail.h"
bsalomoneb1cb5c2015-05-22 08:01:09 -070011#include "GrCaps.h"
bsalomon4061b122015-05-29 10:26:19 -070012#include "GrGpu.h"
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +000013#include "GrPath.h"
egdaniele36914c2015-02-13 09:00:33 -080014#include "GrPipeline.h"
joshualittb7133be2015-04-08 09:08:31 -070015#include "GrMemoryPool.h"
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000016#include "GrRenderTarget.h"
bsalomon4061b122015-05-29 10:26:19 -070017#include "GrResourceProvider.h"
bsalomon6bc1b5f2015-02-23 09:06:38 -080018#include "GrRenderTargetPriv.h"
cdalton93a379b2016-05-11 13:58:08 -070019#include "GrStencilAttachment.h"
bsalomonafbf2d62014-09-30 12:18:44 -070020#include "GrSurfacePriv.h"
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000021#include "GrTexture.h"
ethannicholas22793252016-01-30 09:59:10 -080022#include "gl/GrGLRenderTarget.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000023
joshualitt086cee12016-01-12 06:45:24 -080024#include "SkStrokeRec.h"
25
bsalomon53469832015-08-18 09:20:09 -070026#include "batches/GrClearBatch.h"
bsalomon872062c2015-08-18 12:12:35 -070027#include "batches/GrCopySurfaceBatch.h"
bsalomon53469832015-08-18 09:20:09 -070028#include "batches/GrDiscardBatch.h"
bsalomon16b99132015-08-13 14:55:50 -070029#include "batches/GrDrawBatch.h"
bsalomonadd79ef2015-08-19 13:26:49 -070030#include "batches/GrDrawPathBatch.h"
joshualittecd1a692015-08-10 10:08:26 -070031#include "batches/GrRectBatchFactory.h"
bsalomona44919e2015-08-18 13:28:19 -070032#include "batches/GrStencilPathBatch.h"
joshualitt74417822015-08-07 11:42:16 -070033
reed@google.comac10a2d2010-12-22 21:39:39 +000034////////////////////////////////////////////////////////////////////////////////
35
bsalomon489147c2015-12-14 12:13:09 -080036// Experimentally we have found that most batching occurs within the first 10 comparisons.
bsalomonaecc0182016-03-07 11:50:44 -080037static const int kDefaultMaxBatchLookback = 10;
38static const int kDefaultMaxBatchLookahead = 10;
bsalomon489147c2015-12-14 12:13:09 -080039
bsalomon69cfe952015-11-30 13:27:47 -080040GrDrawTarget::GrDrawTarget(GrRenderTarget* rt, GrGpu* gpu, GrResourceProvider* resourceProvider,
joshualitt086cee12016-01-12 06:45:24 -080041 GrAuditTrail* auditTrail, const Options& options)
bsalomon4061b122015-05-29 10:26:19 -070042 : fGpu(SkRef(gpu))
bsalomon4061b122015-05-29 10:26:19 -070043 , fResourceProvider(resourceProvider)
joshualitt086cee12016-01-12 06:45:24 -080044 , fAuditTrail(auditTrail)
bsalomon648c6962015-10-23 09:06:59 -070045 , fFlags(0)
robertphillips498d7ac2015-10-30 10:11:30 -070046 , fRenderTarget(rt) {
bsalomonb3b9aec2015-09-10 11:16:35 -070047 // TODO: Stop extracting the context (currently needed by GrClipMaskManager)
48 fContext = fGpu->getContext();
cdalton862cff32016-05-12 15:09:48 -070049 fClipMaskManager.reset(new GrClipMaskManager(this));
robertphillips4beb5c12015-10-20 07:50:00 -070050
cdalton862cff32016-05-12 15:09:48 -070051 fClipBatchToBounds = options.fClipBatchToBounds;
bsalomon6dea83f2015-12-03 12:58:06 -080052 fDrawBatchBounds = options.fDrawBatchBounds;
bsalomon489147c2015-12-14 12:13:09 -080053 fMaxBatchLookback = (options.fMaxBatchLookback < 0) ? kDefaultMaxBatchLookback :
54 options.fMaxBatchLookback;
bsalomonaecc0182016-03-07 11:50:44 -080055 fMaxBatchLookahead = (options.fMaxBatchLookahead < 0) ? kDefaultMaxBatchLookahead :
56 options.fMaxBatchLookahead;
bsalomon6dea83f2015-12-03 12:58:06 -080057
robertphillips0dfa62c2015-11-16 06:23:31 -080058 rt->setLastDrawTarget(this);
59
robertphillips4beb5c12015-10-20 07:50:00 -070060#ifdef SK_DEBUG
61 static int debugID = 0;
62 fDebugID = debugID++;
63#endif
bsalomon4061b122015-05-29 10:26:19 -070064}
65
66GrDrawTarget::~GrDrawTarget() {
robertphillips498d7ac2015-10-30 10:11:30 -070067 if (fRenderTarget && this == fRenderTarget->getLastDrawTarget()) {
68 fRenderTarget->setLastDrawTarget(nullptr);
69 }
70
bsalomon4061b122015-05-29 10:26:19 -070071 fGpu->unref();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000072}
73
74////////////////////////////////////////////////////////////////////////////////
75
robertphillips6a186652015-10-20 07:37:58 -070076// Add a GrDrawTarget-based dependency
77void GrDrawTarget::addDependency(GrDrawTarget* dependedOn) {
78 SkASSERT(!dependedOn->dependsOn(this)); // loops are bad
79
80 if (this->dependsOn(dependedOn)) {
81 return; // don't add duplicate dependencies
82 }
83
84 *fDependencies.push() = dependedOn;
85}
86
87// Convert from a GrSurface-based dependency to a GrDrawTarget one
88void GrDrawTarget::addDependency(GrSurface* dependedOn) {
89 if (dependedOn->asRenderTarget() && dependedOn->asRenderTarget()->getLastDrawTarget()) {
90 // If it is still receiving dependencies, this DT shouldn't be closed
91 SkASSERT(!this->isClosed());
92
93 GrDrawTarget* dt = dependedOn->asRenderTarget()->getLastDrawTarget();
94 if (dt == this) {
95 // self-read - presumably for dst reads
96 } else {
97 this->addDependency(dt);
98
99 // Can't make it closed in the self-read case
100 dt->makeClosed();
101 }
102 }
103}
104
robertphillips4beb5c12015-10-20 07:50:00 -0700105#ifdef SK_DEBUG
106void GrDrawTarget::dump() const {
107 SkDebugf("--------------------------------------------------------------\n");
robertphillipse004bfc2015-11-16 09:06:59 -0800108 SkDebugf("node: %d -> RT: %d\n", fDebugID, fRenderTarget ? fRenderTarget->getUniqueID() : -1);
robertphillips4beb5c12015-10-20 07:50:00 -0700109 SkDebugf("relies On (%d): ", fDependencies.count());
110 for (int i = 0; i < fDependencies.count(); ++i) {
111 SkDebugf("%d, ", fDependencies[i]->fDebugID);
112 }
113 SkDebugf("\n");
114 SkDebugf("batches (%d):\n", fBatches.count());
115 for (int i = 0; i < fBatches.count(); ++i) {
116#if 0
117 SkDebugf("*******************************\n");
118#endif
bsalomonaecc0182016-03-07 11:50:44 -0800119 if (fBatches[i]) {
120 SkDebugf("%d: <combined forward>\n", i);
121 } else {
122 SkDebugf("%d: %s\n", i, fBatches[i]->name());
robertphillips4beb5c12015-10-20 07:50:00 -0700123#if 0
bsalomonaecc0182016-03-07 11:50:44 -0800124 SkString str = fBatches[i]->dumpInfo();
125 SkDebugf("%s\n", str.c_str());
robertphillips4beb5c12015-10-20 07:50:00 -0700126#endif
bsalomonaecc0182016-03-07 11:50:44 -0800127 }
robertphillips4beb5c12015-10-20 07:50:00 -0700128 }
129}
130#endif
131
bsalomon50785a32015-02-06 07:02:37 -0800132bool GrDrawTarget::setupDstReadIfNecessary(const GrPipelineBuilder& pipelineBuilder,
cdalton862cff32016-05-12 15:09:48 -0700133 const GrClip& clip,
ethannicholasde4166a2015-11-30 08:57:38 -0800134 const GrPipelineOptimizations& optimizations,
bsalomon6a44c6a2015-05-26 09:49:05 -0700135 GrXferProcessor::DstTexture* dstTexture,
bsalomonad792c12015-09-10 11:10:50 -0700136 const SkRect& batchBounds) {
137 SkRect bounds = batchBounds;
138 bounds.outset(0.5f, 0.5f);
139
ethannicholasde4166a2015-11-30 08:57:38 -0800140 if (!pipelineBuilder.willXPNeedDstTexture(*this->caps(), optimizations)) {
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000141 return true;
142 }
cdalton9954bc32015-04-29 14:17:00 -0700143
bsalomon50785a32015-02-06 07:02:37 -0800144 GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
cdalton9954bc32015-04-29 14:17:00 -0700145
146 if (this->caps()->textureBarrierSupport()) {
147 if (GrTexture* rtTex = rt->asTexture()) {
bsalomondc47ff72015-05-26 12:16:59 -0700148 // The render target is a texture, so we can read from it directly in the shader. The XP
cdalton9954bc32015-04-29 14:17:00 -0700149 // will be responsible to detect this situation and request a texture barrier.
bsalomon6a44c6a2015-05-26 09:49:05 -0700150 dstTexture->setTexture(rtTex);
151 dstTexture->setOffset(0, 0);
cdalton9954bc32015-04-29 14:17:00 -0700152 return true;
153 }
154 }
155
156 SkIRect copyRect;
cdalton862cff32016-05-12 15:09:48 -0700157 clip.getConservativeBounds(rt->width(), rt->height(), &copyRect);
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000158
bsalomonad792c12015-09-10 11:10:50 -0700159 SkIRect drawIBounds;
160 bounds.roundOut(&drawIBounds);
161 if (!copyRect.intersect(drawIBounds)) {
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000162#ifdef SK_DEBUG
bsalomonb3b9aec2015-09-10 11:16:35 -0700163 GrCapsDebugf(this->caps(), "Missed an early reject. "
164 "Bailing on draw from setupDstReadIfNecessary.\n");
commit-bot@chromium.orgbb5c4652013-04-01 12:49:31 +0000165#endif
bsalomonad792c12015-09-10 11:10:50 -0700166 return false;
commit-bot@chromium.orgbb5c4652013-04-01 12:49:31 +0000167 }
skia.committer@gmail.com05a2ee02013-04-02 07:01:34 +0000168
commit-bot@chromium.org63150af2013-04-11 22:00:22 +0000169 // MSAA consideration: When there is support for reading MSAA samples in the shader we could
170 // have per-sample dst values by making the copy multisampled.
bsalomonf2703d82014-10-28 14:33:06 -0700171 GrSurfaceDesc desc;
bsalomonb3b9aec2015-09-10 11:16:35 -0700172 if (!fGpu->initCopySurfaceDstDesc(rt, &desc)) {
bsalomona73239a2015-04-28 13:35:17 -0700173 desc.fOrigin = kDefault_GrSurfaceOrigin;
174 desc.fFlags = kRenderTarget_GrSurfaceFlag;
175 desc.fConfig = rt->config();
176 }
177
commit-bot@chromium.orgbb5c4652013-04-01 12:49:31 +0000178 desc.fWidth = copyRect.width();
179 desc.fHeight = copyRect.height();
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000180
bsalomoneae62002015-07-31 13:59:30 -0700181 static const uint32_t kFlags = 0;
182 SkAutoTUnref<GrTexture> copy(fResourceProvider->createApproxTexture(desc, kFlags));
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000183
bsalomone3059732014-10-14 11:47:22 -0700184 if (!copy) {
tfarina38406c82014-10-31 07:11:12 -0700185 SkDebugf("Failed to create temporary copy of destination texture.\n");
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000186 return false;
187 }
bsalomon@google.come4617bf2013-04-03 14:56:40 +0000188 SkIPoint dstPoint = {0, 0};
bsalomon6df86402015-06-01 10:41:49 -0700189 this->copySurface(copy, rt, copyRect, dstPoint);
190 dstTexture->setTexture(copy);
191 dstTexture->setOffset(copyRect.fLeft, copyRect.fTop);
192 return true;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000193}
194
robertphillipsa13e2022015-11-11 12:01:09 -0800195void GrDrawTarget::prepareBatches(GrBatchFlushState* flushState) {
robertphillipsa106c622015-10-16 09:07:06 -0700196 // Semi-usually the drawTargets are already closed at this point, but sometimes Ganesh
197 // needs to flush mid-draw. In that case, the SkGpuDevice's drawTargets won't be closed
198 // but need to be flushed anyway. Closing such drawTargets here will mean new
199 // drawTargets will be created to replace them if the SkGpuDevice(s) write to them again.
200 this->makeClosed();
201
robertphillips498d7ac2015-10-30 10:11:30 -0700202 // Loop over the batches that haven't yet generated their geometry
robertphillips1f0e3502015-11-10 10:19:50 -0800203 for (int i = 0; i < fBatches.count(); ++i) {
bsalomonaecc0182016-03-07 11:50:44 -0800204 if (fBatches[i]) {
205 fBatches[i]->prepare(flushState);
206 }
bsalomon512be532015-09-10 10:42:55 -0700207 }
robertphillipsa13e2022015-11-11 12:01:09 -0800208}
bsalomon512be532015-09-10 10:42:55 -0700209
robertphillipsa13e2022015-11-11 12:01:09 -0800210void GrDrawTarget::drawBatches(GrBatchFlushState* flushState) {
bsalomon512be532015-09-10 10:42:55 -0700211 // Draw all the generated geometry.
bsalomon6dea83f2015-12-03 12:58:06 -0800212 SkRandom random;
bsalomon512be532015-09-10 10:42:55 -0700213 for (int i = 0; i < fBatches.count(); ++i) {
bsalomonaecc0182016-03-07 11:50:44 -0800214 if (!fBatches[i]) {
215 continue;
216 }
bsalomon6dea83f2015-12-03 12:58:06 -0800217 if (fDrawBatchBounds) {
218 const SkRect& bounds = fBatches[i]->bounds();
219 SkIRect ibounds;
220 bounds.roundOut(&ibounds);
221 // In multi-draw buffer all the batches use the same render target and we won't need to
222 // get the batchs bounds.
223 if (GrRenderTarget* rt = fBatches[i]->renderTarget()) {
224 fGpu->drawDebugWireRect(rt, ibounds, 0xFF000000 | random.nextU());
225 }
226 }
robertphillipsa13e2022015-11-11 12:01:09 -0800227 fBatches[i]->draw(flushState);
bsalomon512be532015-09-10 10:42:55 -0700228 }
ethannicholas22793252016-01-30 09:59:10 -0800229
jvanverthd2d2eb92016-02-17 14:04:46 -0800230 fGpu->finishDrawTarget();
bsalomona73239a2015-04-28 13:35:17 -0700231}
232
bsalomon512be532015-09-10 10:42:55 -0700233void GrDrawTarget::reset() {
234 fBatches.reset();
235}
236
robertphillips391395d2016-03-02 09:26:36 -0800237void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder,
cdalton862cff32016-05-12 15:09:48 -0700238 const GrClip& clip,
239 GrDrawBatch* batch) {
joshualitt4d8da812015-01-28 12:53:54 -0800240 // Setup clip
cdalton862cff32016-05-12 15:09:48 -0700241 GrAppliedClip appliedClip;
242 if (!fClipMaskManager->setupClipping(pipelineBuilder, clip, &batch->bounds(), &appliedClip)) {
243 return;
joshualitt4d8da812015-01-28 12:53:54 -0800244 }
robertphillips391395d2016-03-02 09:26:36 -0800245
cdaltond4727922015-11-10 12:49:06 -0800246 GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps;
cdalton862cff32016-05-12 15:09:48 -0700247 if (appliedClip.clipCoverageFragmentProcessor()) {
cdaltond4727922015-11-10 12:49:06 -0800248 arfps.set(&pipelineBuilder);
cdalton862cff32016-05-12 15:09:48 -0700249 arfps.addCoverageFragmentProcessor(appliedClip.clipCoverageFragmentProcessor());
cdaltond4727922015-11-10 12:49:06 -0800250 }
joshualitt4d8da812015-01-28 12:53:54 -0800251
bsalomonad792c12015-09-10 11:10:50 -0700252 GrPipeline::CreateArgs args;
cdalton193d9cf2016-05-12 11:52:02 -0700253 args.fPipelineBuilder = &pipelineBuilder;
254 args.fCaps = this->caps();
cdalton862cff32016-05-12 15:09:48 -0700255 args.fScissor = &appliedClip.scissorState();
256 args.fHasStencilClip = appliedClip.hasStencilClip();
257 if (pipelineBuilder.hasUserStencilSettings() || appliedClip.hasStencilClip()) {
cdalton193d9cf2016-05-12 11:52:02 -0700258 fResourceProvider->attachStencilAttachment(pipelineBuilder.getRenderTarget());
259 }
260 batch->getPipelineOptimizations(&args.fOpts);
261 GrScissorState finalScissor;
cdalton862cff32016-05-12 15:09:48 -0700262 if (args.fOpts.fOverrides.fUsePLSDstRead || fClipBatchToBounds) {
cdalton193d9cf2016-05-12 11:52:02 -0700263 GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
264 GrGLIRect viewport;
265 viewport.fLeft = 0;
266 viewport.fBottom = 0;
267 viewport.fWidth = rt->width();
268 viewport.fHeight = rt->height();
269 SkIRect ibounds;
270 ibounds.fLeft = SkTPin(SkScalarFloorToInt(batch->bounds().fLeft), viewport.fLeft,
271 viewport.fWidth);
272 ibounds.fTop = SkTPin(SkScalarFloorToInt(batch->bounds().fTop), viewport.fBottom,
273 viewport.fHeight);
274 ibounds.fRight = SkTPin(SkScalarCeilToInt(batch->bounds().fRight), viewport.fLeft,
275 viewport.fWidth);
276 ibounds.fBottom = SkTPin(SkScalarCeilToInt(batch->bounds().fBottom), viewport.fBottom,
277 viewport.fHeight);
cdalton862cff32016-05-12 15:09:48 -0700278 if (appliedClip.scissorState().enabled()) {
279 const SkIRect& scissorRect = appliedClip.scissorState().rect();
cdalton193d9cf2016-05-12 11:52:02 -0700280 if (!ibounds.intersect(scissorRect)) {
cdalton862cff32016-05-12 15:09:48 -0700281 return;
cdalton193d9cf2016-05-12 11:52:02 -0700282 }
283 }
284 finalScissor.set(ibounds);
285 args.fScissor = &finalScissor;
286 }
287 args.fOpts.fColorPOI.completeCalculations(pipelineBuilder.fColorFragmentProcessors.begin(),
288 pipelineBuilder.numColorFragmentProcessors());
289 args.fOpts.fCoveragePOI.completeCalculations(
290 pipelineBuilder.fCoverageFragmentProcessors.begin(),
291 pipelineBuilder.numCoverageFragmentProcessors());
cdalton862cff32016-05-12 15:09:48 -0700292 if (!this->setupDstReadIfNecessary(pipelineBuilder, clip, args.fOpts, &args.fDstTexture,
cdalton193d9cf2016-05-12 11:52:02 -0700293 batch->bounds())) {
294 return;
295 }
296
297 if (!batch->installPipeline(args)) {
egdaniele36914c2015-02-13 09:00:33 -0800298 return;
299 }
bsalomonad792c12015-09-10 11:10:50 -0700300
robertphillips498d7ac2015-10-30 10:11:30 -0700301#ifdef ENABLE_MDB
302 SkASSERT(fRenderTarget);
303 batch->pipeline()->addDependenciesTo(fRenderTarget);
304#endif
305
bsalomon512be532015-09-10 10:42:55 -0700306 this->recordBatch(batch);
joshualitt4d8da812015-01-28 12:53:54 -0800307}
308
joshualitt1c735482015-07-13 08:08:25 -0700309void GrDrawTarget::stencilPath(const GrPipelineBuilder& pipelineBuilder,
cdalton862cff32016-05-12 15:09:48 -0700310 const GrClip& clip,
joshualittf2384692015-09-10 11:00:51 -0700311 const SkMatrix& viewMatrix,
joshualitt9853cce2014-11-17 14:22:48 -0800312 const GrPath* path,
313 GrPathRendering::FillType fill) {
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000314 // TODO: extract portions of checkDraw that are relevant to path stenciling.
bsalomon49f085d2014-09-05 13:34:00 -0700315 SkASSERT(path);
jvanverthe9c0fc62015-04-29 11:18:05 -0700316 SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
joshualitt2c93efe2014-11-06 12:57:13 -0800317
318 // Setup clip
cdalton862cff32016-05-12 15:09:48 -0700319 GrAppliedClip appliedClip;
320 if (!fClipMaskManager->setupClipping(pipelineBuilder, clip, nullptr, &appliedClip)) {
joshualitt2c93efe2014-11-06 12:57:13 -0800321 return;
322 }
cdalton862cff32016-05-12 15:09:48 -0700323 // TODO: respect fClipBatchToBounds if we ever start computing bounds here.
joshualitt2c93efe2014-11-06 12:57:13 -0800324
bsalomon0ba8c242015-10-07 09:20:28 -0700325 GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps;
cdalton862cff32016-05-12 15:09:48 -0700326 if (appliedClip.clipCoverageFragmentProcessor()) {
bsalomon0ba8c242015-10-07 09:20:28 -0700327 arfps.set(&pipelineBuilder);
cdalton862cff32016-05-12 15:09:48 -0700328 arfps.addCoverageFragmentProcessor(appliedClip.clipCoverageFragmentProcessor());
bsalomon0ba8c242015-10-07 09:20:28 -0700329 }
330
joshualitt1c735482015-07-13 08:08:25 -0700331 GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
cdalton93a379b2016-05-11 13:58:08 -0700332 GrStencilAttachment* stencilAttachment = fResourceProvider->attachStencilAttachment(rt);
joshualitt2c93efe2014-11-06 12:57:13 -0800333
joshualittf2384692015-09-10 11:00:51 -0700334 GrBatch* batch = GrStencilPathBatch::Create(viewMatrix,
bsalomona44919e2015-08-18 13:28:19 -0700335 pipelineBuilder.isHWAntialias(),
cdalton193d9cf2016-05-12 11:52:02 -0700336 fill,
cdalton862cff32016-05-12 15:09:48 -0700337 appliedClip.hasStencilClip(),
cdalton93a379b2016-05-11 13:58:08 -0700338 stencilAttachment->bits(),
cdalton862cff32016-05-12 15:09:48 -0700339 appliedClip.scissorState(),
bsalomona44919e2015-08-18 13:28:19 -0700340 pipelineBuilder.getRenderTarget(),
341 path);
bsalomon512be532015-09-10 10:42:55 -0700342 this->recordBatch(batch);
bsalomona44919e2015-08-18 13:28:19 -0700343 batch->unref();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000344}
345
joshualitt9853cce2014-11-17 14:22:48 -0800346void GrDrawTarget::clear(const SkIRect* rect,
347 GrColor color,
348 bool canIgnoreRect,
bsalomon63b21962014-11-05 07:05:34 -0800349 GrRenderTarget* renderTarget) {
egdaniel51c8d402015-08-06 10:54:13 -0700350 SkIRect rtRect = SkIRect::MakeWH(renderTarget->width(), renderTarget->height());
351 SkIRect clippedRect;
352 if (!rect ||
353 (canIgnoreRect && this->caps()->fullClearIsFree()) ||
354 rect->contains(rtRect)) {
355 rect = &rtRect;
356 } else {
357 clippedRect = *rect;
358 if (!clippedRect.intersect(rtRect)) {
359 return;
360 }
361 rect = &clippedRect;
362 }
363
bsalomonb3b9aec2015-09-10 11:16:35 -0700364 if (this->caps()->useDrawInsteadOfClear()) {
bsalomon63b21962014-11-05 07:05:34 -0800365 // This works around a driver bug with clear by drawing a rect instead.
366 // The driver will ignore a clear if it is the only thing rendered to a
367 // target before the target is read.
egdaniel51c8d402015-08-06 10:54:13 -0700368 if (rect == &rtRect) {
bsalomon63b21962014-11-05 07:05:34 -0800369 this->discard(renderTarget);
370 }
bsalomon63b21962014-11-05 07:05:34 -0800371
egdaniel8dd688b2015-01-22 10:16:09 -0800372 GrPipelineBuilder pipelineBuilder;
egdanielc4b72722015-11-23 13:20:41 -0800373 pipelineBuilder.setXPFactory(
374 GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
egdaniel8dd688b2015-01-22 10:16:09 -0800375 pipelineBuilder.setRenderTarget(renderTarget);
joshualitt9853cce2014-11-17 14:22:48 -0800376
joshualitta8b84992016-01-13 13:35:35 -0800377 SkRect scalarRect = SkRect::Make(*rect);
378 SkAutoTUnref<GrDrawBatch> batch(
379 GrRectBatchFactory::CreateNonAAFill(color, SkMatrix::I(), scalarRect,
380 nullptr, nullptr));
cdalton862cff32016-05-12 15:09:48 -0700381 this->drawBatch(pipelineBuilder, GrClip::WideOpen(), batch);
bsalomon53469832015-08-18 09:20:09 -0700382 } else {
halcanary385fe4d2015-08-26 13:07:48 -0700383 GrBatch* batch = new GrClearBatch(*rect, color, renderTarget);
bsalomon512be532015-09-10 10:42:55 -0700384 this->recordBatch(batch);
bsalomon53469832015-08-18 09:20:09 -0700385 batch->unref();
386 }
387}
388
389void GrDrawTarget::discard(GrRenderTarget* renderTarget) {
390 if (this->caps()->discardRenderTargetSupport()) {
halcanary385fe4d2015-08-26 13:07:48 -0700391 GrBatch* batch = new GrDiscardBatch(renderTarget);
bsalomon512be532015-09-10 10:42:55 -0700392 this->recordBatch(batch);
bsalomon53469832015-08-18 09:20:09 -0700393 batch->unref();
bsalomon63b21962014-11-05 07:05:34 -0800394 }
395}
396
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000397////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000398
bsalomonb8fea972016-02-16 07:34:17 -0800399bool GrDrawTarget::copySurface(GrSurface* dst,
bsalomon@google.com116ad842013-04-09 15:38:19 +0000400 GrSurface* src,
401 const SkIRect& srcRect,
402 const SkIPoint& dstPoint) {
bsalomon872062c2015-08-18 12:12:35 -0700403 GrBatch* batch = GrCopySurfaceBatch::Create(dst, src, srcRect, dstPoint);
bsalomonb8fea972016-02-16 07:34:17 -0800404 if (!batch) {
405 return false;
406 }
robertphillips498d7ac2015-10-30 10:11:30 -0700407#ifdef ENABLE_MDB
bsalomonb8fea972016-02-16 07:34:17 -0800408 this->addDependency(src);
robertphillips498d7ac2015-10-30 10:11:30 -0700409#endif
410
bsalomonb8fea972016-02-16 07:34:17 -0800411 this->recordBatch(batch);
412 batch->unref();
413 return true;
bsalomon@google.comeb851172013-04-15 13:51:00 +0000414}
415
bsalomon512be532015-09-10 10:42:55 -0700416template <class Left, class Right> static bool intersect(const Left& a, const Right& b) {
417 SkASSERT(a.fLeft <= a.fRight && a.fTop <= a.fBottom &&
418 b.fLeft <= b.fRight && b.fTop <= b.fBottom);
419 return a.fLeft < b.fRight && b.fLeft < a.fRight && a.fTop < b.fBottom && b.fTop < a.fBottom;
420}
421
422void GrDrawTarget::recordBatch(GrBatch* batch) {
robertphillipsa106c622015-10-16 09:07:06 -0700423 // A closed drawTarget should never receive new/more batches
robertphillips6a186652015-10-20 07:37:58 -0700424 SkASSERT(!this->isClosed());
robertphillipsa106c622015-10-16 09:07:06 -0700425
bsalomon512be532015-09-10 10:42:55 -0700426 // Check if there is a Batch Draw we can batch with by linearly searching back until we either
427 // 1) check every draw
428 // 2) intersect with something
429 // 3) find a 'blocker'
joshualittb0666ad2016-03-08 10:43:41 -0800430 GR_AUDIT_TRAIL_ADDBATCH(fAuditTrail, batch);
bsalomon512be532015-09-10 10:42:55 -0700431 GrBATCH_INFO("Re-Recording (%s, B%u)\n"
joshualitte2bcec32015-09-30 06:22:22 -0700432 "\tBounds LRTB (%f, %f, %f, %f)\n",
bsalomon512be532015-09-10 10:42:55 -0700433 batch->name(),
434 batch->uniqueID(),
435 batch->bounds().fLeft, batch->bounds().fRight,
436 batch->bounds().fTop, batch->bounds().fBottom);
437 GrBATCH_INFO(SkTabString(batch->dumpInfo(), 1).c_str());
halcanary9d524f22016-03-29 09:03:52 -0700438 GrBATCH_INFO("\tOutcome:\n");
bsalomon489147c2015-12-14 12:13:09 -0800439 int maxCandidates = SkTMin(fMaxBatchLookback, fBatches.count());
bsalomon512be532015-09-10 10:42:55 -0700440 if (maxCandidates) {
441 int i = 0;
442 while (true) {
443 GrBatch* candidate = fBatches.fromBack(i);
444 // We cannot continue to search backwards if the render target changes
445 if (candidate->renderTargetUniqueID() != batch->renderTargetUniqueID()) {
446 GrBATCH_INFO("\t\tBreaking because of (%s, B%u) Rendertarget\n",
447 candidate->name(), candidate->uniqueID());
448 break;
449 }
450 if (candidate->combineIfPossible(batch, *this->caps())) {
451 GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name(),
452 candidate->uniqueID());
joshualittb0666ad2016-03-08 10:43:41 -0800453 GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(fAuditTrail, candidate, batch);
bsalomon512be532015-09-10 10:42:55 -0700454 return;
455 }
456 // Stop going backwards if we would cause a painter's order violation.
bsalomondb4758c2015-11-23 11:14:20 -0800457 // TODO: The bounds used here do not fully consider the clip. It may be advantageous
458 // to clip each batch's bounds to the clip.
bsalomon512be532015-09-10 10:42:55 -0700459 if (intersect(candidate->bounds(), batch->bounds())) {
460 GrBATCH_INFO("\t\tIntersects with (%s, B%u)\n", candidate->name(),
461 candidate->uniqueID());
462 break;
463 }
464 ++i;
465 if (i == maxCandidates) {
466 GrBATCH_INFO("\t\tReached max lookback or beginning of batch array %d\n", i);
467 break;
468 }
469 }
470 } else {
471 GrBATCH_INFO("\t\tFirstBatch\n");
472 }
joshualitt18d6b752016-02-26 08:07:50 -0800473 GR_AUDIT_TRAIL_BATCHING_RESULT_NEW(fAuditTrail, batch);
bsalomon512be532015-09-10 10:42:55 -0700474 fBatches.push_back().reset(SkRef(batch));
475}
476
bsalomonaecc0182016-03-07 11:50:44 -0800477void GrDrawTarget::forwardCombine() {
478 for (int i = 0; i < fBatches.count() - 2; ++i) {
479 GrBatch* batch = fBatches[i];
480 int maxCandidateIdx = SkTMin(i + fMaxBatchLookahead, fBatches.count() - 1);
481 int j = i + 1;
482 while (true) {
483 GrBatch* candidate = fBatches[j];
484 // We cannot continue to search if the render target changes
485 if (candidate->renderTargetUniqueID() != batch->renderTargetUniqueID()) {
486 GrBATCH_INFO("\t\tBreaking because of (%s, B%u) Rendertarget\n",
487 candidate->name(), candidate->uniqueID());
488 break;
489 }
490 if (j == i +1) {
491 // We assume batch would have combined with candidate when the candidate was added
492 // via backwards combining in recordBatch.
493 SkASSERT(!batch->combineIfPossible(candidate, *this->caps()));
494 } else if (batch->combineIfPossible(candidate, *this->caps())) {
495 GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name(),
496 candidate->uniqueID());
joshualittb0666ad2016-03-08 10:43:41 -0800497 GR_AUDIT_TRAIL_BATCHING_RESULT_COMBINED(fAuditTrail, batch, candidate);
bsalomonaecc0182016-03-07 11:50:44 -0800498 fBatches[j].reset(SkRef(batch));
499 fBatches[i].reset(nullptr);
500 break;
501 }
502 // Stop going traversing if we would cause a painter's order violation.
503 // TODO: The bounds used here do not fully consider the clip. It may be advantageous
504 // to clip each batch's bounds to the clip.
505 if (intersect(candidate->bounds(), batch->bounds())) {
506 GrBATCH_INFO("\t\tIntersects with (%s, B%u)\n", candidate->name(),
507 candidate->uniqueID());
508 break;
509 }
510 ++j;
511 if (j > maxCandidateIdx) {
512 GrBATCH_INFO("\t\tReached max lookahead or end of batch array %d\n", i);
513 break;
514 }
515 }
516 }
517}
518
egdaniele36914c2015-02-13 09:00:33 -0800519///////////////////////////////////////////////////////////////////////////////
520
bsalomonb3b9aec2015-09-10 11:16:35 -0700521void GrDrawTarget::clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTarget* rt) {
halcanary385fe4d2015-08-26 13:07:48 -0700522 GrBatch* batch = new GrClearStencilClipBatch(rect, insideClip, rt);
bsalomon512be532015-09-10 10:42:55 -0700523 this->recordBatch(batch);
bsalomon5ea03632015-08-18 10:33:30 -0700524 batch->unref();
525}