blob: b9dc7945262056e753bf2b274d8573cef7ed6787 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@google.comac10a2d2010-12-22 21:39:39 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2010 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
reed@google.comac10a2d2010-12-22 21:39:39 +00007 */
8
joshualittc2893c52015-01-28 06:54:30 -08009#include "GrDrawTarget.h"
joshualitt4d8da812015-01-28 12:53:54 -080010
joshualitt086cee12016-01-12 06:45:24 -080011#include "GrAuditTrail.h"
bsalomoneb1cb5c2015-05-22 08:01:09 -070012#include "GrCaps.h"
bsalomon4061b122015-05-29 10:26:19 -070013#include "GrGpu.h"
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +000014#include "GrPath.h"
egdaniele36914c2015-02-13 09:00:33 -080015#include "GrPipeline.h"
joshualittb7133be2015-04-08 09:08:31 -070016#include "GrMemoryPool.h"
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000017#include "GrRenderTarget.h"
bsalomon4061b122015-05-29 10:26:19 -070018#include "GrResourceProvider.h"
bsalomon6bc1b5f2015-02-23 09:06:38 -080019#include "GrRenderTargetPriv.h"
bsalomonafbf2d62014-09-30 12:18:44 -070020#include "GrSurfacePriv.h"
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000021#include "GrTexture.h"
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000022#include "GrVertexBuffer.h"
ethannicholas22793252016-01-30 09:59:10 -080023#include "gl/GrGLRenderTarget.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000024
joshualitt086cee12016-01-12 06:45:24 -080025#include "SkStrokeRec.h"
26
bsalomon53469832015-08-18 09:20:09 -070027#include "batches/GrClearBatch.h"
bsalomon872062c2015-08-18 12:12:35 -070028#include "batches/GrCopySurfaceBatch.h"
bsalomon53469832015-08-18 09:20:09 -070029#include "batches/GrDiscardBatch.h"
bsalomon16b99132015-08-13 14:55:50 -070030#include "batches/GrDrawBatch.h"
bsalomonadd79ef2015-08-19 13:26:49 -070031#include "batches/GrDrawPathBatch.h"
joshualittecd1a692015-08-10 10:08:26 -070032#include "batches/GrRectBatchFactory.h"
bsalomona44919e2015-08-18 13:28:19 -070033#include "batches/GrStencilPathBatch.h"
joshualitt74417822015-08-07 11:42:16 -070034
reed@google.comac10a2d2010-12-22 21:39:39 +000035////////////////////////////////////////////////////////////////////////////////
36
bsalomon489147c2015-12-14 12:13:09 -080037// Experimentally we have found that most batching occurs within the first 10 comparisons.
38static const int kDefaultMaxBatchLookback = 10;
39
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();
bsalomon69cfe952015-11-30 13:27:47 -080049 fClipMaskManager.reset(new GrClipMaskManager(this, options.fClipBatchToBounds));
robertphillips4beb5c12015-10-20 07:50:00 -070050
bsalomon6dea83f2015-12-03 12:58:06 -080051 fDrawBatchBounds = options.fDrawBatchBounds;
bsalomon489147c2015-12-14 12:13:09 -080052 fMaxBatchLookback = (options.fMaxBatchLookback < 0) ? kDefaultMaxBatchLookback :
53 options.fMaxBatchLookback;
bsalomon6dea83f2015-12-03 12:58:06 -080054
robertphillips0dfa62c2015-11-16 06:23:31 -080055 rt->setLastDrawTarget(this);
56
robertphillips4beb5c12015-10-20 07:50:00 -070057#ifdef SK_DEBUG
58 static int debugID = 0;
59 fDebugID = debugID++;
60#endif
bsalomon4061b122015-05-29 10:26:19 -070061}
62
63GrDrawTarget::~GrDrawTarget() {
robertphillips498d7ac2015-10-30 10:11:30 -070064 if (fRenderTarget && this == fRenderTarget->getLastDrawTarget()) {
65 fRenderTarget->setLastDrawTarget(nullptr);
66 }
67
bsalomon4061b122015-05-29 10:26:19 -070068 fGpu->unref();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000069}
70
71////////////////////////////////////////////////////////////////////////////////
72
robertphillips6a186652015-10-20 07:37:58 -070073// Add a GrDrawTarget-based dependency
74void GrDrawTarget::addDependency(GrDrawTarget* dependedOn) {
75 SkASSERT(!dependedOn->dependsOn(this)); // loops are bad
76
77 if (this->dependsOn(dependedOn)) {
78 return; // don't add duplicate dependencies
79 }
80
81 *fDependencies.push() = dependedOn;
82}
83
84// Convert from a GrSurface-based dependency to a GrDrawTarget one
85void GrDrawTarget::addDependency(GrSurface* dependedOn) {
86 if (dependedOn->asRenderTarget() && dependedOn->asRenderTarget()->getLastDrawTarget()) {
87 // If it is still receiving dependencies, this DT shouldn't be closed
88 SkASSERT(!this->isClosed());
89
90 GrDrawTarget* dt = dependedOn->asRenderTarget()->getLastDrawTarget();
91 if (dt == this) {
92 // self-read - presumably for dst reads
93 } else {
94 this->addDependency(dt);
95
96 // Can't make it closed in the self-read case
97 dt->makeClosed();
98 }
99 }
100}
101
robertphillips4beb5c12015-10-20 07:50:00 -0700102#ifdef SK_DEBUG
103void GrDrawTarget::dump() const {
104 SkDebugf("--------------------------------------------------------------\n");
robertphillipse004bfc2015-11-16 09:06:59 -0800105 SkDebugf("node: %d -> RT: %d\n", fDebugID, fRenderTarget ? fRenderTarget->getUniqueID() : -1);
robertphillips4beb5c12015-10-20 07:50:00 -0700106 SkDebugf("relies On (%d): ", fDependencies.count());
107 for (int i = 0; i < fDependencies.count(); ++i) {
108 SkDebugf("%d, ", fDependencies[i]->fDebugID);
109 }
110 SkDebugf("\n");
111 SkDebugf("batches (%d):\n", fBatches.count());
112 for (int i = 0; i < fBatches.count(); ++i) {
113#if 0
114 SkDebugf("*******************************\n");
115#endif
116 SkDebugf("%d: %s\n", i, fBatches[i]->name());
117#if 0
118 SkString str = fBatches[i]->dumpInfo();
119 SkDebugf("%s\n", str.c_str());
120#endif
121 }
122}
123#endif
124
bsalomon50785a32015-02-06 07:02:37 -0800125bool GrDrawTarget::setupDstReadIfNecessary(const GrPipelineBuilder& pipelineBuilder,
ethannicholasde4166a2015-11-30 08:57:38 -0800126 const GrPipelineOptimizations& optimizations,
bsalomon6a44c6a2015-05-26 09:49:05 -0700127 GrXferProcessor::DstTexture* dstTexture,
bsalomonad792c12015-09-10 11:10:50 -0700128 const SkRect& batchBounds) {
129 SkRect bounds = batchBounds;
130 bounds.outset(0.5f, 0.5f);
131
ethannicholasde4166a2015-11-30 08:57:38 -0800132 if (!pipelineBuilder.willXPNeedDstTexture(*this->caps(), optimizations)) {
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000133 return true;
134 }
cdalton9954bc32015-04-29 14:17:00 -0700135
bsalomon50785a32015-02-06 07:02:37 -0800136 GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
cdalton9954bc32015-04-29 14:17:00 -0700137
138 if (this->caps()->textureBarrierSupport()) {
139 if (GrTexture* rtTex = rt->asTexture()) {
bsalomondc47ff72015-05-26 12:16:59 -0700140 // The render target is a texture, so we can read from it directly in the shader. The XP
cdalton9954bc32015-04-29 14:17:00 -0700141 // will be responsible to detect this situation and request a texture barrier.
bsalomon6a44c6a2015-05-26 09:49:05 -0700142 dstTexture->setTexture(rtTex);
143 dstTexture->setOffset(0, 0);
cdalton9954bc32015-04-29 14:17:00 -0700144 return true;
145 }
146 }
147
148 SkIRect copyRect;
robertphillips7bceedc2015-12-01 12:51:26 -0800149 pipelineBuilder.clip().getConservativeBounds(rt->width(), rt->height(), &copyRect);
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000150
bsalomonad792c12015-09-10 11:10:50 -0700151 SkIRect drawIBounds;
152 bounds.roundOut(&drawIBounds);
153 if (!copyRect.intersect(drawIBounds)) {
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000154#ifdef SK_DEBUG
bsalomonb3b9aec2015-09-10 11:16:35 -0700155 GrCapsDebugf(this->caps(), "Missed an early reject. "
156 "Bailing on draw from setupDstReadIfNecessary.\n");
commit-bot@chromium.orgbb5c4652013-04-01 12:49:31 +0000157#endif
bsalomonad792c12015-09-10 11:10:50 -0700158 return false;
commit-bot@chromium.orgbb5c4652013-04-01 12:49:31 +0000159 }
skia.committer@gmail.com05a2ee02013-04-02 07:01:34 +0000160
commit-bot@chromium.org63150af2013-04-11 22:00:22 +0000161 // MSAA consideration: When there is support for reading MSAA samples in the shader we could
162 // have per-sample dst values by making the copy multisampled.
bsalomonf2703d82014-10-28 14:33:06 -0700163 GrSurfaceDesc desc;
bsalomonb3b9aec2015-09-10 11:16:35 -0700164 if (!fGpu->initCopySurfaceDstDesc(rt, &desc)) {
bsalomona73239a2015-04-28 13:35:17 -0700165 desc.fOrigin = kDefault_GrSurfaceOrigin;
166 desc.fFlags = kRenderTarget_GrSurfaceFlag;
167 desc.fConfig = rt->config();
168 }
169
commit-bot@chromium.orgbb5c4652013-04-01 12:49:31 +0000170 desc.fWidth = copyRect.width();
171 desc.fHeight = copyRect.height();
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000172
bsalomoneae62002015-07-31 13:59:30 -0700173 static const uint32_t kFlags = 0;
174 SkAutoTUnref<GrTexture> copy(fResourceProvider->createApproxTexture(desc, kFlags));
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000175
bsalomone3059732014-10-14 11:47:22 -0700176 if (!copy) {
tfarina38406c82014-10-31 07:11:12 -0700177 SkDebugf("Failed to create temporary copy of destination texture.\n");
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000178 return false;
179 }
bsalomon@google.come4617bf2013-04-03 14:56:40 +0000180 SkIPoint dstPoint = {0, 0};
bsalomon6df86402015-06-01 10:41:49 -0700181 this->copySurface(copy, rt, copyRect, dstPoint);
182 dstTexture->setTexture(copy);
183 dstTexture->setOffset(copyRect.fLeft, copyRect.fTop);
184 return true;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000185}
186
robertphillipsa13e2022015-11-11 12:01:09 -0800187void GrDrawTarget::prepareBatches(GrBatchFlushState* flushState) {
robertphillipsa106c622015-10-16 09:07:06 -0700188 // Semi-usually the drawTargets are already closed at this point, but sometimes Ganesh
189 // needs to flush mid-draw. In that case, the SkGpuDevice's drawTargets won't be closed
190 // but need to be flushed anyway. Closing such drawTargets here will mean new
191 // drawTargets will be created to replace them if the SkGpuDevice(s) write to them again.
192 this->makeClosed();
193
robertphillips498d7ac2015-10-30 10:11:30 -0700194 // Loop over the batches that haven't yet generated their geometry
robertphillips1f0e3502015-11-10 10:19:50 -0800195 for (int i = 0; i < fBatches.count(); ++i) {
robertphillipsa13e2022015-11-11 12:01:09 -0800196 fBatches[i]->prepare(flushState);
bsalomon512be532015-09-10 10:42:55 -0700197 }
robertphillipsa13e2022015-11-11 12:01:09 -0800198}
bsalomon512be532015-09-10 10:42:55 -0700199
robertphillipsa13e2022015-11-11 12:01:09 -0800200void GrDrawTarget::drawBatches(GrBatchFlushState* flushState) {
bsalomon512be532015-09-10 10:42:55 -0700201 // Draw all the generated geometry.
bsalomon6dea83f2015-12-03 12:58:06 -0800202 SkRandom random;
bsalomon512be532015-09-10 10:42:55 -0700203 for (int i = 0; i < fBatches.count(); ++i) {
bsalomon6dea83f2015-12-03 12:58:06 -0800204 if (fDrawBatchBounds) {
205 const SkRect& bounds = fBatches[i]->bounds();
206 SkIRect ibounds;
207 bounds.roundOut(&ibounds);
208 // In multi-draw buffer all the batches use the same render target and we won't need to
209 // get the batchs bounds.
210 if (GrRenderTarget* rt = fBatches[i]->renderTarget()) {
211 fGpu->drawDebugWireRect(rt, ibounds, 0xFF000000 | random.nextU());
212 }
213 }
robertphillipsa13e2022015-11-11 12:01:09 -0800214 fBatches[i]->draw(flushState);
bsalomon512be532015-09-10 10:42:55 -0700215 }
ethannicholas22793252016-01-30 09:59:10 -0800216
217 fGpu->performFlushWorkaround();
bsalomona73239a2015-04-28 13:35:17 -0700218}
219
bsalomon512be532015-09-10 10:42:55 -0700220void GrDrawTarget::reset() {
221 fBatches.reset();
222}
223
bsalomonabd30f52015-08-13 13:34:48 -0700224void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder, GrDrawBatch* batch) {
joshualitt4d8da812015-01-28 12:53:54 -0800225 // Setup clip
joshualitt4d8da812015-01-28 12:53:54 -0800226 GrPipelineBuilder::AutoRestoreStencil ars;
bsalomon0ba8c242015-10-07 09:20:28 -0700227 GrAppliedClip clip;
bsalomone91f7b52015-10-27 06:42:50 -0700228 if (!fClipMaskManager->setupClipping(pipelineBuilder, &ars, &batch->bounds(), &clip)) {
joshualitt4d8da812015-01-28 12:53:54 -0800229 return;
230 }
cdaltond4727922015-11-10 12:49:06 -0800231 GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps;
232 if (clip.clipCoverageFragmentProcessor()) {
233 arfps.set(&pipelineBuilder);
234 arfps.addCoverageFragmentProcessor(clip.clipCoverageFragmentProcessor());
235 }
joshualitt4d8da812015-01-28 12:53:54 -0800236
bsalomonad792c12015-09-10 11:10:50 -0700237 GrPipeline::CreateArgs args;
cdaltond4727922015-11-10 12:49:06 -0800238 if (!this->installPipelineInDrawBatch(&pipelineBuilder, &clip.scissorState(), batch)) {
egdaniele36914c2015-02-13 09:00:33 -0800239 return;
240 }
bsalomonad792c12015-09-10 11:10:50 -0700241
robertphillips498d7ac2015-10-30 10:11:30 -0700242#ifdef ENABLE_MDB
243 SkASSERT(fRenderTarget);
244 batch->pipeline()->addDependenciesTo(fRenderTarget);
245#endif
246
bsalomon512be532015-09-10 10:42:55 -0700247 this->recordBatch(batch);
joshualitt4d8da812015-01-28 12:53:54 -0800248}
249
joshualitt2c93efe2014-11-06 12:57:13 -0800250static const GrStencilSettings& winding_path_stencil_settings() {
251 GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
252 kIncClamp_StencilOp,
253 kIncClamp_StencilOp,
254 kAlwaysIfInClip_StencilFunc,
255 0xFFFF, 0xFFFF, 0xFFFF);
256 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
257}
258
259static const GrStencilSettings& even_odd_path_stencil_settings() {
260 GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
261 kInvert_StencilOp,
262 kInvert_StencilOp,
263 kAlwaysIfInClip_StencilFunc,
264 0xFFFF, 0xFFFF, 0xFFFF);
265 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
266}
267
268void GrDrawTarget::getPathStencilSettingsForFilltype(GrPathRendering::FillType fill,
egdaniel8dc7c3a2015-04-16 11:22:42 -0700269 const GrStencilAttachment* sb,
joshualitt2c93efe2014-11-06 12:57:13 -0800270 GrStencilSettings* outStencilSettings) {
271
272 switch (fill) {
273 default:
274 SkFAIL("Unexpected path fill.");
275 case GrPathRendering::kWinding_FillType:
276 *outStencilSettings = winding_path_stencil_settings();
277 break;
278 case GrPathRendering::kEvenOdd_FillType:
279 *outStencilSettings = even_odd_path_stencil_settings();
280 break;
281 }
bsalomonb3b9aec2015-09-10 11:16:35 -0700282 fClipMaskManager->adjustPathStencilParams(sb, outStencilSettings);
joshualitt2c93efe2014-11-06 12:57:13 -0800283}
284
joshualitt1c735482015-07-13 08:08:25 -0700285void GrDrawTarget::stencilPath(const GrPipelineBuilder& pipelineBuilder,
joshualittf2384692015-09-10 11:00:51 -0700286 const SkMatrix& viewMatrix,
joshualitt9853cce2014-11-17 14:22:48 -0800287 const GrPath* path,
288 GrPathRendering::FillType fill) {
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000289 // TODO: extract portions of checkDraw that are relevant to path stenciling.
bsalomon49f085d2014-09-05 13:34:00 -0700290 SkASSERT(path);
jvanverthe9c0fc62015-04-29 11:18:05 -0700291 SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
joshualitt2c93efe2014-11-06 12:57:13 -0800292
293 // Setup clip
egdaniel8dd688b2015-01-22 10:16:09 -0800294 GrPipelineBuilder::AutoRestoreStencil ars;
bsalomon0ba8c242015-10-07 09:20:28 -0700295 GrAppliedClip clip;
bsalomone91f7b52015-10-27 06:42:50 -0700296 if (!fClipMaskManager->setupClipping(pipelineBuilder, &ars, nullptr, &clip)) {
joshualitt2c93efe2014-11-06 12:57:13 -0800297 return;
298 }
299
bsalomon0ba8c242015-10-07 09:20:28 -0700300 GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps;
301 if (clip.clipCoverageFragmentProcessor()) {
302 arfps.set(&pipelineBuilder);
303 arfps.addCoverageFragmentProcessor(clip.clipCoverageFragmentProcessor());
304 }
305
joshualitt2c93efe2014-11-06 12:57:13 -0800306 // set stencil settings for path
307 GrStencilSettings stencilSettings;
joshualitt1c735482015-07-13 08:08:25 -0700308 GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
egdanielec00d942015-09-14 12:56:10 -0700309 GrStencilAttachment* sb = fResourceProvider->attachStencilAttachment(rt);
bsalomon6bc1b5f2015-02-23 09:06:38 -0800310 this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings);
joshualitt2c93efe2014-11-06 12:57:13 -0800311
joshualittf2384692015-09-10 11:00:51 -0700312 GrBatch* batch = GrStencilPathBatch::Create(viewMatrix,
bsalomona44919e2015-08-18 13:28:19 -0700313 pipelineBuilder.isHWAntialias(),
bsalomone91f7b52015-10-27 06:42:50 -0700314 stencilSettings, clip.scissorState(),
bsalomona44919e2015-08-18 13:28:19 -0700315 pipelineBuilder.getRenderTarget(),
316 path);
bsalomon512be532015-09-10 10:42:55 -0700317 this->recordBatch(batch);
bsalomona44919e2015-08-18 13:28:19 -0700318 batch->unref();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000319}
320
bsalomon1fcc01c2015-09-09 09:48:06 -0700321void GrDrawTarget::drawPathBatch(const GrPipelineBuilder& pipelineBuilder,
cdalton8ff8d242015-12-08 10:20:32 -0800322 GrDrawPathBatchBase* batch) {
bsalomonadd79ef2015-08-19 13:26:49 -0700323 // This looks like drawBatch() but there is an added wrinkle that stencil settings get inserted
bsalomonb3b9aec2015-09-10 11:16:35 -0700324 // after setting up clipping but before onDrawBatch(). TODO: Figure out a better model for
325 // handling stencil settings WRT interactions between pipeline(builder), clipmaskmanager, and
326 // batches.
cdalton8ff8d242015-12-08 10:20:32 -0800327 SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
bsalomonadd79ef2015-08-19 13:26:49 -0700328
egdaniel8dd688b2015-01-22 10:16:09 -0800329 GrPipelineBuilder::AutoRestoreStencil ars;
bsalomon0ba8c242015-10-07 09:20:28 -0700330 GrAppliedClip clip;
bsalomone91f7b52015-10-27 06:42:50 -0700331 if (!fClipMaskManager->setupClipping(pipelineBuilder, &ars, &batch->bounds(), &clip)) {
bsalomonadd79ef2015-08-19 13:26:49 -0700332 return;
joshualitt2c93efe2014-11-06 12:57:13 -0800333 }
334
cdaltond4727922015-11-10 12:49:06 -0800335 GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps;
336 if (clip.clipCoverageFragmentProcessor()) {
337 arfps.set(&pipelineBuilder);
338 arfps.addCoverageFragmentProcessor(clip.clipCoverageFragmentProcessor());
339 }
340
bsalomonadd79ef2015-08-19 13:26:49 -0700341 // Ensure the render target has a stencil buffer and get the stencil settings.
joshualitt2c93efe2014-11-06 12:57:13 -0800342 GrStencilSettings stencilSettings;
joshualitt1c735482015-07-13 08:08:25 -0700343 GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
egdanielec00d942015-09-14 12:56:10 -0700344 GrStencilAttachment* sb = fResourceProvider->attachStencilAttachment(rt);
cdalton8ff8d242015-12-08 10:20:32 -0800345 this->getPathStencilSettingsForFilltype(batch->fillType(), sb, &stencilSettings);
bsalomonadd79ef2015-08-19 13:26:49 -0700346 batch->setStencilSettings(stencilSettings);
joshualitt2c93efe2014-11-06 12:57:13 -0800347
bsalomonad792c12015-09-10 11:10:50 -0700348 GrPipeline::CreateArgs args;
cdaltond4727922015-11-10 12:49:06 -0800349 if (!this->installPipelineInDrawBatch(&pipelineBuilder, &clip.scissorState(), batch)) {
bsalomonadd79ef2015-08-19 13:26:49 -0700350 return;
351 }
egdaniele36914c2015-02-13 09:00:33 -0800352
bsalomon512be532015-09-10 10:42:55 -0700353 this->recordBatch(batch);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000354}
355
joshualitt9853cce2014-11-17 14:22:48 -0800356void GrDrawTarget::clear(const SkIRect* rect,
357 GrColor color,
358 bool canIgnoreRect,
bsalomon63b21962014-11-05 07:05:34 -0800359 GrRenderTarget* renderTarget) {
egdaniel51c8d402015-08-06 10:54:13 -0700360 SkIRect rtRect = SkIRect::MakeWH(renderTarget->width(), renderTarget->height());
361 SkIRect clippedRect;
362 if (!rect ||
363 (canIgnoreRect && this->caps()->fullClearIsFree()) ||
364 rect->contains(rtRect)) {
365 rect = &rtRect;
366 } else {
367 clippedRect = *rect;
368 if (!clippedRect.intersect(rtRect)) {
369 return;
370 }
371 rect = &clippedRect;
372 }
373
bsalomonb3b9aec2015-09-10 11:16:35 -0700374 if (this->caps()->useDrawInsteadOfClear()) {
bsalomon63b21962014-11-05 07:05:34 -0800375 // This works around a driver bug with clear by drawing a rect instead.
376 // The driver will ignore a clear if it is the only thing rendered to a
377 // target before the target is read.
egdaniel51c8d402015-08-06 10:54:13 -0700378 if (rect == &rtRect) {
bsalomon63b21962014-11-05 07:05:34 -0800379 this->discard(renderTarget);
380 }
bsalomon63b21962014-11-05 07:05:34 -0800381
egdaniel8dd688b2015-01-22 10:16:09 -0800382 GrPipelineBuilder pipelineBuilder;
egdanielc4b72722015-11-23 13:20:41 -0800383 pipelineBuilder.setXPFactory(
384 GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
egdaniel8dd688b2015-01-22 10:16:09 -0800385 pipelineBuilder.setRenderTarget(renderTarget);
joshualitt9853cce2014-11-17 14:22:48 -0800386
joshualitta8b84992016-01-13 13:35:35 -0800387 SkRect scalarRect = SkRect::Make(*rect);
388 SkAutoTUnref<GrDrawBatch> batch(
389 GrRectBatchFactory::CreateNonAAFill(color, SkMatrix::I(), scalarRect,
390 nullptr, nullptr));
391 this->drawBatch(pipelineBuilder, batch);
bsalomon53469832015-08-18 09:20:09 -0700392 } else {
halcanary385fe4d2015-08-26 13:07:48 -0700393 GrBatch* batch = new GrClearBatch(*rect, color, renderTarget);
bsalomon512be532015-09-10 10:42:55 -0700394 this->recordBatch(batch);
bsalomon53469832015-08-18 09:20:09 -0700395 batch->unref();
396 }
397}
398
399void GrDrawTarget::discard(GrRenderTarget* renderTarget) {
400 if (this->caps()->discardRenderTargetSupport()) {
halcanary385fe4d2015-08-26 13:07:48 -0700401 GrBatch* batch = new GrDiscardBatch(renderTarget);
bsalomon512be532015-09-10 10:42:55 -0700402 this->recordBatch(batch);
bsalomon53469832015-08-18 09:20:09 -0700403 batch->unref();
bsalomon63b21962014-11-05 07:05:34 -0800404 }
405}
406
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000407////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000408
bsalomon6df86402015-06-01 10:41:49 -0700409void GrDrawTarget::copySurface(GrSurface* dst,
bsalomon@google.com116ad842013-04-09 15:38:19 +0000410 GrSurface* src,
411 const SkIRect& srcRect,
412 const SkIPoint& dstPoint) {
bsalomon872062c2015-08-18 12:12:35 -0700413 GrBatch* batch = GrCopySurfaceBatch::Create(dst, src, srcRect, dstPoint);
414 if (batch) {
robertphillips498d7ac2015-10-30 10:11:30 -0700415#ifdef ENABLE_MDB
416 this->addDependency(src);
417#endif
418
bsalomon512be532015-09-10 10:42:55 -0700419 this->recordBatch(batch);
bsalomon872062c2015-08-18 12:12:35 -0700420 batch->unref();
bsalomon@google.come4617bf2013-04-03 14:56:40 +0000421 }
bsalomon@google.comeb851172013-04-15 13:51:00 +0000422}
423
bsalomon512be532015-09-10 10:42:55 -0700424template <class Left, class Right> static bool intersect(const Left& a, const Right& b) {
425 SkASSERT(a.fLeft <= a.fRight && a.fTop <= a.fBottom &&
426 b.fLeft <= b.fRight && b.fTop <= b.fBottom);
427 return a.fLeft < b.fRight && b.fLeft < a.fRight && a.fTop < b.fBottom && b.fTop < a.fBottom;
428}
429
430void GrDrawTarget::recordBatch(GrBatch* batch) {
robertphillipsa106c622015-10-16 09:07:06 -0700431 // A closed drawTarget should never receive new/more batches
robertphillips6a186652015-10-20 07:37:58 -0700432 SkASSERT(!this->isClosed());
robertphillipsa106c622015-10-16 09:07:06 -0700433
bsalomon512be532015-09-10 10:42:55 -0700434 // Check if there is a Batch Draw we can batch with by linearly searching back until we either
435 // 1) check every draw
436 // 2) intersect with something
437 // 3) find a 'blocker'
joshualitt086cee12016-01-12 06:45:24 -0800438 GR_AUDIT_TRAIL_ADDBATCH(fAuditTrail, batch->name(), batch->bounds());
bsalomon512be532015-09-10 10:42:55 -0700439 GrBATCH_INFO("Re-Recording (%s, B%u)\n"
joshualitte2bcec32015-09-30 06:22:22 -0700440 "\tBounds LRTB (%f, %f, %f, %f)\n",
bsalomon512be532015-09-10 10:42:55 -0700441 batch->name(),
442 batch->uniqueID(),
443 batch->bounds().fLeft, batch->bounds().fRight,
444 batch->bounds().fTop, batch->bounds().fBottom);
445 GrBATCH_INFO(SkTabString(batch->dumpInfo(), 1).c_str());
446 GrBATCH_INFO("\tOutcome:\n");
bsalomon489147c2015-12-14 12:13:09 -0800447 int maxCandidates = SkTMin(fMaxBatchLookback, fBatches.count());
bsalomon512be532015-09-10 10:42:55 -0700448 if (maxCandidates) {
449 int i = 0;
450 while (true) {
451 GrBatch* candidate = fBatches.fromBack(i);
452 // We cannot continue to search backwards if the render target changes
453 if (candidate->renderTargetUniqueID() != batch->renderTargetUniqueID()) {
454 GrBATCH_INFO("\t\tBreaking because of (%s, B%u) Rendertarget\n",
455 candidate->name(), candidate->uniqueID());
456 break;
457 }
458 if (candidate->combineIfPossible(batch, *this->caps())) {
459 GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name(),
460 candidate->uniqueID());
461 return;
462 }
463 // Stop going backwards if we would cause a painter's order violation.
bsalomondb4758c2015-11-23 11:14:20 -0800464 // TODO: The bounds used here do not fully consider the clip. It may be advantageous
465 // to clip each batch's bounds to the clip.
bsalomon512be532015-09-10 10:42:55 -0700466 if (intersect(candidate->bounds(), batch->bounds())) {
467 GrBATCH_INFO("\t\tIntersects with (%s, B%u)\n", candidate->name(),
468 candidate->uniqueID());
469 break;
470 }
471 ++i;
472 if (i == maxCandidates) {
473 GrBATCH_INFO("\t\tReached max lookback or beginning of batch array %d\n", i);
474 break;
475 }
476 }
477 } else {
478 GrBATCH_INFO("\t\tFirstBatch\n");
479 }
480 fBatches.push_back().reset(SkRef(batch));
481}
482
egdaniele36914c2015-02-13 09:00:33 -0800483///////////////////////////////////////////////////////////////////////////////
484
bsalomonad792c12015-09-10 11:10:50 -0700485bool GrDrawTarget::installPipelineInDrawBatch(const GrPipelineBuilder* pipelineBuilder,
cdaltond4727922015-11-10 12:49:06 -0800486 const GrScissorState* scissor,
487 GrDrawBatch* batch) {
bsalomonad792c12015-09-10 11:10:50 -0700488 GrPipeline::CreateArgs args;
489 args.fPipelineBuilder = pipelineBuilder;
490 args.fCaps = this->caps();
cdaltond4727922015-11-10 12:49:06 -0800491 args.fScissor = scissor;
ethannicholasff210322015-11-24 12:10:10 -0800492 batch->getPipelineOptimizations(&args.fOpts);
ethannicholas22793252016-01-30 09:59:10 -0800493 GrScissorState finalScissor;
494 if (args.fOpts.fOverrides.fUsePLSDstRead) {
495 GrRenderTarget* rt = pipelineBuilder->getRenderTarget();
496 GrGLIRect viewport;
497 viewport.fLeft = 0;
498 viewport.fBottom = 0;
499 viewport.fWidth = rt->width();
500 viewport.fHeight = rt->height();
501 SkIRect ibounds;
502 ibounds.fLeft = SkTPin(SkScalarFloorToInt(batch->bounds().fLeft), viewport.fLeft,
503 viewport.fWidth);
504 ibounds.fTop = SkTPin(SkScalarFloorToInt(batch->bounds().fTop), viewport.fBottom,
505 viewport.fHeight);
506 ibounds.fRight = SkTPin(SkScalarCeilToInt(batch->bounds().fRight), viewport.fLeft,
507 viewport.fWidth);
508 ibounds.fBottom = SkTPin(SkScalarCeilToInt(batch->bounds().fBottom), viewport.fBottom,
509 viewport.fHeight);
510 if (scissor != nullptr && scissor->enabled()) {
511 if (!ibounds.intersect(scissor->rect())) {
512 ibounds = scissor->rect();
513 }
514 }
515 finalScissor.set(ibounds);
516 args.fScissor = &finalScissor;
517 }
ethannicholasff210322015-11-24 12:10:10 -0800518 args.fOpts.fColorPOI.completeCalculations(pipelineBuilder->fColorFragmentProcessors.begin(),
519 pipelineBuilder->numColorFragmentProcessors());
520 args.fOpts.fCoveragePOI.completeCalculations(
521 pipelineBuilder->fCoverageFragmentProcessors.begin(),
522 pipelineBuilder->numCoverageFragmentProcessors());
ethannicholasde4166a2015-11-30 08:57:38 -0800523 if (!this->setupDstReadIfNecessary(*pipelineBuilder, args.fOpts, &args.fDstTexture,
bsalomonad792c12015-09-10 11:10:50 -0700524 batch->bounds())) {
525 return false;
egdaniele36914c2015-02-13 09:00:33 -0800526 }
bsalomonad792c12015-09-10 11:10:50 -0700527
528 if (!batch->installPipeline(args)) {
529 return false;
530 }
531
532 return true;
egdaniele36914c2015-02-13 09:00:33 -0800533}
534
bsalomonb3b9aec2015-09-10 11:16:35 -0700535void GrDrawTarget::clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTarget* rt) {
halcanary385fe4d2015-08-26 13:07:48 -0700536 GrBatch* batch = new GrClearStencilClipBatch(rect, insideClip, rt);
bsalomon512be532015-09-10 10:42:55 -0700537 this->recordBatch(batch);
bsalomon5ea03632015-08-18 10:33:30 -0700538 batch->unref();
539}