blob: 4f91a3cf96ff340d34ce6654fc8de2bc0bb378d8 [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
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"
bsalomonafbf2d62014-09-30 12:18:44 -070019#include "GrSurfacePriv.h"
bsalomon@google.com86afc2a2011-02-16 16:12:19 +000020#include "GrTexture.h"
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000021#include "GrVertexBuffer.h"
reed@google.comac10a2d2010-12-22 21:39:39 +000022
bsalomon53469832015-08-18 09:20:09 -070023#include "batches/GrClearBatch.h"
bsalomon872062c2015-08-18 12:12:35 -070024#include "batches/GrCopySurfaceBatch.h"
bsalomon53469832015-08-18 09:20:09 -070025#include "batches/GrDiscardBatch.h"
bsalomon16b99132015-08-13 14:55:50 -070026#include "batches/GrDrawBatch.h"
bsalomonadd79ef2015-08-19 13:26:49 -070027#include "batches/GrDrawPathBatch.h"
joshualittecd1a692015-08-10 10:08:26 -070028#include "batches/GrRectBatchFactory.h"
bsalomona44919e2015-08-18 13:28:19 -070029#include "batches/GrStencilPathBatch.h"
joshualitt74417822015-08-07 11:42:16 -070030
sugoi@google.com5f74cf82012-12-17 21:16:45 +000031#include "SkStrokeRec.h"
sugoi@google.com12b4e272012-12-06 20:13:11 +000032
reed@google.comac10a2d2010-12-22 21:39:39 +000033////////////////////////////////////////////////////////////////////////////////
34
bsalomon69cfe952015-11-30 13:27:47 -080035GrDrawTarget::GrDrawTarget(GrRenderTarget* rt, GrGpu* gpu, GrResourceProvider* resourceProvider,
36 const Options& options)
bsalomon4061b122015-05-29 10:26:19 -070037 : fGpu(SkRef(gpu))
bsalomon4061b122015-05-29 10:26:19 -070038 , fResourceProvider(resourceProvider)
bsalomon512be532015-09-10 10:42:55 -070039 , fFlushing(false)
bsalomon648c6962015-10-23 09:06:59 -070040 , fFlags(0)
robertphillips498d7ac2015-10-30 10:11:30 -070041 , fRenderTarget(rt) {
bsalomonb3b9aec2015-09-10 11:16:35 -070042 // TODO: Stop extracting the context (currently needed by GrClipMaskManager)
43 fContext = fGpu->getContext();
bsalomon69cfe952015-11-30 13:27:47 -080044 fClipMaskManager.reset(new GrClipMaskManager(this, options.fClipBatchToBounds));
robertphillips4beb5c12015-10-20 07:50:00 -070045
bsalomon6dea83f2015-12-03 12:58:06 -080046 fDrawBatchBounds = options.fDrawBatchBounds;
47
robertphillips0dfa62c2015-11-16 06:23:31 -080048 rt->setLastDrawTarget(this);
49
robertphillips4beb5c12015-10-20 07:50:00 -070050#ifdef SK_DEBUG
51 static int debugID = 0;
52 fDebugID = debugID++;
53#endif
bsalomon4061b122015-05-29 10:26:19 -070054}
55
56GrDrawTarget::~GrDrawTarget() {
robertphillips498d7ac2015-10-30 10:11:30 -070057 if (fRenderTarget && this == fRenderTarget->getLastDrawTarget()) {
58 fRenderTarget->setLastDrawTarget(nullptr);
59 }
60
bsalomon4061b122015-05-29 10:26:19 -070061 fGpu->unref();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000062}
63
64////////////////////////////////////////////////////////////////////////////////
65
robertphillips6a186652015-10-20 07:37:58 -070066// Add a GrDrawTarget-based dependency
67void GrDrawTarget::addDependency(GrDrawTarget* dependedOn) {
68 SkASSERT(!dependedOn->dependsOn(this)); // loops are bad
69
70 if (this->dependsOn(dependedOn)) {
71 return; // don't add duplicate dependencies
72 }
73
74 *fDependencies.push() = dependedOn;
75}
76
77// Convert from a GrSurface-based dependency to a GrDrawTarget one
78void GrDrawTarget::addDependency(GrSurface* dependedOn) {
79 if (dependedOn->asRenderTarget() && dependedOn->asRenderTarget()->getLastDrawTarget()) {
80 // If it is still receiving dependencies, this DT shouldn't be closed
81 SkASSERT(!this->isClosed());
82
83 GrDrawTarget* dt = dependedOn->asRenderTarget()->getLastDrawTarget();
84 if (dt == this) {
85 // self-read - presumably for dst reads
86 } else {
87 this->addDependency(dt);
88
89 // Can't make it closed in the self-read case
90 dt->makeClosed();
91 }
92 }
93}
94
robertphillips4beb5c12015-10-20 07:50:00 -070095#ifdef SK_DEBUG
96void GrDrawTarget::dump() const {
97 SkDebugf("--------------------------------------------------------------\n");
robertphillipse004bfc2015-11-16 09:06:59 -080098 SkDebugf("node: %d -> RT: %d\n", fDebugID, fRenderTarget ? fRenderTarget->getUniqueID() : -1);
robertphillips4beb5c12015-10-20 07:50:00 -070099 SkDebugf("relies On (%d): ", fDependencies.count());
100 for (int i = 0; i < fDependencies.count(); ++i) {
101 SkDebugf("%d, ", fDependencies[i]->fDebugID);
102 }
103 SkDebugf("\n");
104 SkDebugf("batches (%d):\n", fBatches.count());
105 for (int i = 0; i < fBatches.count(); ++i) {
106#if 0
107 SkDebugf("*******************************\n");
108#endif
109 SkDebugf("%d: %s\n", i, fBatches[i]->name());
110#if 0
111 SkString str = fBatches[i]->dumpInfo();
112 SkDebugf("%s\n", str.c_str());
113#endif
114 }
115}
116#endif
117
bsalomon50785a32015-02-06 07:02:37 -0800118bool GrDrawTarget::setupDstReadIfNecessary(const GrPipelineBuilder& pipelineBuilder,
ethannicholasde4166a2015-11-30 08:57:38 -0800119 const GrPipelineOptimizations& optimizations,
bsalomon6a44c6a2015-05-26 09:49:05 -0700120 GrXferProcessor::DstTexture* dstTexture,
bsalomonad792c12015-09-10 11:10:50 -0700121 const SkRect& batchBounds) {
122 SkRect bounds = batchBounds;
123 bounds.outset(0.5f, 0.5f);
124
ethannicholasde4166a2015-11-30 08:57:38 -0800125 if (!pipelineBuilder.willXPNeedDstTexture(*this->caps(), optimizations)) {
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000126 return true;
127 }
cdalton9954bc32015-04-29 14:17:00 -0700128
bsalomon50785a32015-02-06 07:02:37 -0800129 GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
cdalton9954bc32015-04-29 14:17:00 -0700130
131 if (this->caps()->textureBarrierSupport()) {
132 if (GrTexture* rtTex = rt->asTexture()) {
bsalomondc47ff72015-05-26 12:16:59 -0700133 // The render target is a texture, so we can read from it directly in the shader. The XP
cdalton9954bc32015-04-29 14:17:00 -0700134 // will be responsible to detect this situation and request a texture barrier.
bsalomon6a44c6a2015-05-26 09:49:05 -0700135 dstTexture->setTexture(rtTex);
136 dstTexture->setOffset(0, 0);
cdalton9954bc32015-04-29 14:17:00 -0700137 return true;
138 }
139 }
140
141 SkIRect copyRect;
robertphillips7bceedc2015-12-01 12:51:26 -0800142 pipelineBuilder.clip().getConservativeBounds(rt->width(), rt->height(), &copyRect);
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000143
bsalomonad792c12015-09-10 11:10:50 -0700144 SkIRect drawIBounds;
145 bounds.roundOut(&drawIBounds);
146 if (!copyRect.intersect(drawIBounds)) {
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000147#ifdef SK_DEBUG
bsalomonb3b9aec2015-09-10 11:16:35 -0700148 GrCapsDebugf(this->caps(), "Missed an early reject. "
149 "Bailing on draw from setupDstReadIfNecessary.\n");
commit-bot@chromium.orgbb5c4652013-04-01 12:49:31 +0000150#endif
bsalomonad792c12015-09-10 11:10:50 -0700151 return false;
commit-bot@chromium.orgbb5c4652013-04-01 12:49:31 +0000152 }
skia.committer@gmail.com05a2ee02013-04-02 07:01:34 +0000153
commit-bot@chromium.org63150af2013-04-11 22:00:22 +0000154 // MSAA consideration: When there is support for reading MSAA samples in the shader we could
155 // have per-sample dst values by making the copy multisampled.
bsalomonf2703d82014-10-28 14:33:06 -0700156 GrSurfaceDesc desc;
bsalomonb3b9aec2015-09-10 11:16:35 -0700157 if (!fGpu->initCopySurfaceDstDesc(rt, &desc)) {
bsalomona73239a2015-04-28 13:35:17 -0700158 desc.fOrigin = kDefault_GrSurfaceOrigin;
159 desc.fFlags = kRenderTarget_GrSurfaceFlag;
160 desc.fConfig = rt->config();
161 }
162
commit-bot@chromium.orgbb5c4652013-04-01 12:49:31 +0000163 desc.fWidth = copyRect.width();
164 desc.fHeight = copyRect.height();
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000165
bsalomoneae62002015-07-31 13:59:30 -0700166 static const uint32_t kFlags = 0;
167 SkAutoTUnref<GrTexture> copy(fResourceProvider->createApproxTexture(desc, kFlags));
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000168
bsalomone3059732014-10-14 11:47:22 -0700169 if (!copy) {
tfarina38406c82014-10-31 07:11:12 -0700170 SkDebugf("Failed to create temporary copy of destination texture.\n");
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000171 return false;
172 }
bsalomon@google.come4617bf2013-04-03 14:56:40 +0000173 SkIPoint dstPoint = {0, 0};
bsalomon6df86402015-06-01 10:41:49 -0700174 this->copySurface(copy, rt, copyRect, dstPoint);
175 dstTexture->setTexture(copy);
176 dstTexture->setOffset(copyRect.fLeft, copyRect.fTop);
177 return true;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000178}
179
robertphillipsa13e2022015-11-11 12:01:09 -0800180void GrDrawTarget::prepareBatches(GrBatchFlushState* flushState) {
bsalomona73239a2015-04-28 13:35:17 -0700181 if (fFlushing) {
182 return;
183 }
184 fFlushing = true;
185
robertphillipsa106c622015-10-16 09:07:06 -0700186 // Semi-usually the drawTargets are already closed at this point, but sometimes Ganesh
187 // needs to flush mid-draw. In that case, the SkGpuDevice's drawTargets won't be closed
188 // but need to be flushed anyway. Closing such drawTargets here will mean new
189 // drawTargets will be created to replace them if the SkGpuDevice(s) write to them again.
190 this->makeClosed();
191
robertphillips498d7ac2015-10-30 10:11:30 -0700192 // Loop over the batches that haven't yet generated their geometry
robertphillips1f0e3502015-11-10 10:19:50 -0800193 for (int i = 0; i < fBatches.count(); ++i) {
robertphillipsa13e2022015-11-11 12:01:09 -0800194 fBatches[i]->prepare(flushState);
bsalomon512be532015-09-10 10:42:55 -0700195 }
robertphillipsa13e2022015-11-11 12:01:09 -0800196}
bsalomon512be532015-09-10 10:42:55 -0700197
robertphillipsa13e2022015-11-11 12:01:09 -0800198void GrDrawTarget::drawBatches(GrBatchFlushState* flushState) {
bsalomon512be532015-09-10 10:42:55 -0700199 // Draw all the generated geometry.
bsalomon6dea83f2015-12-03 12:58:06 -0800200 SkRandom random;
bsalomon512be532015-09-10 10:42:55 -0700201 for (int i = 0; i < fBatches.count(); ++i) {
bsalomon6dea83f2015-12-03 12:58:06 -0800202 if (fDrawBatchBounds) {
203 const SkRect& bounds = fBatches[i]->bounds();
204 SkIRect ibounds;
205 bounds.roundOut(&ibounds);
206 // In multi-draw buffer all the batches use the same render target and we won't need to
207 // get the batchs bounds.
208 if (GrRenderTarget* rt = fBatches[i]->renderTarget()) {
209 fGpu->drawDebugWireRect(rt, ibounds, 0xFF000000 | random.nextU());
210 }
211 }
robertphillipsa13e2022015-11-11 12:01:09 -0800212 fBatches[i]->draw(flushState);
bsalomon512be532015-09-10 10:42:55 -0700213 }
214
bsalomona73239a2015-04-28 13:35:17 -0700215 fFlushing = false;
bsalomona73239a2015-04-28 13:35:17 -0700216}
217
bsalomon512be532015-09-10 10:42:55 -0700218void GrDrawTarget::reset() {
219 fBatches.reset();
220}
221
bsalomonabd30f52015-08-13 13:34:48 -0700222void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder, GrDrawBatch* batch) {
joshualitt4d8da812015-01-28 12:53:54 -0800223 // Setup clip
joshualitt4d8da812015-01-28 12:53:54 -0800224 GrPipelineBuilder::AutoRestoreStencil ars;
bsalomon0ba8c242015-10-07 09:20:28 -0700225 GrAppliedClip clip;
bsalomone91f7b52015-10-27 06:42:50 -0700226 if (!fClipMaskManager->setupClipping(pipelineBuilder, &ars, &batch->bounds(), &clip)) {
joshualitt4d8da812015-01-28 12:53:54 -0800227 return;
228 }
cdaltond4727922015-11-10 12:49:06 -0800229 GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps;
230 if (clip.clipCoverageFragmentProcessor()) {
231 arfps.set(&pipelineBuilder);
232 arfps.addCoverageFragmentProcessor(clip.clipCoverageFragmentProcessor());
233 }
joshualitt4d8da812015-01-28 12:53:54 -0800234
bsalomonad792c12015-09-10 11:10:50 -0700235 GrPipeline::CreateArgs args;
cdaltond4727922015-11-10 12:49:06 -0800236 if (!this->installPipelineInDrawBatch(&pipelineBuilder, &clip.scissorState(), batch)) {
egdaniele36914c2015-02-13 09:00:33 -0800237 return;
238 }
bsalomonad792c12015-09-10 11:10:50 -0700239
robertphillips498d7ac2015-10-30 10:11:30 -0700240#ifdef ENABLE_MDB
241 SkASSERT(fRenderTarget);
242 batch->pipeline()->addDependenciesTo(fRenderTarget);
243#endif
244
bsalomon512be532015-09-10 10:42:55 -0700245 this->recordBatch(batch);
joshualitt4d8da812015-01-28 12:53:54 -0800246}
247
joshualitt2c93efe2014-11-06 12:57:13 -0800248static const GrStencilSettings& winding_path_stencil_settings() {
249 GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
250 kIncClamp_StencilOp,
251 kIncClamp_StencilOp,
252 kAlwaysIfInClip_StencilFunc,
253 0xFFFF, 0xFFFF, 0xFFFF);
254 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
255}
256
257static const GrStencilSettings& even_odd_path_stencil_settings() {
258 GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
259 kInvert_StencilOp,
260 kInvert_StencilOp,
261 kAlwaysIfInClip_StencilFunc,
262 0xFFFF, 0xFFFF, 0xFFFF);
263 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
264}
265
266void GrDrawTarget::getPathStencilSettingsForFilltype(GrPathRendering::FillType fill,
egdaniel8dc7c3a2015-04-16 11:22:42 -0700267 const GrStencilAttachment* sb,
joshualitt2c93efe2014-11-06 12:57:13 -0800268 GrStencilSettings* outStencilSettings) {
269
270 switch (fill) {
271 default:
272 SkFAIL("Unexpected path fill.");
273 case GrPathRendering::kWinding_FillType:
274 *outStencilSettings = winding_path_stencil_settings();
275 break;
276 case GrPathRendering::kEvenOdd_FillType:
277 *outStencilSettings = even_odd_path_stencil_settings();
278 break;
279 }
bsalomonb3b9aec2015-09-10 11:16:35 -0700280 fClipMaskManager->adjustPathStencilParams(sb, outStencilSettings);
joshualitt2c93efe2014-11-06 12:57:13 -0800281}
282
joshualitt1c735482015-07-13 08:08:25 -0700283void GrDrawTarget::stencilPath(const GrPipelineBuilder& pipelineBuilder,
joshualittf2384692015-09-10 11:00:51 -0700284 const SkMatrix& viewMatrix,
joshualitt9853cce2014-11-17 14:22:48 -0800285 const GrPath* path,
286 GrPathRendering::FillType fill) {
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000287 // TODO: extract portions of checkDraw that are relevant to path stenciling.
bsalomon49f085d2014-09-05 13:34:00 -0700288 SkASSERT(path);
jvanverthe9c0fc62015-04-29 11:18:05 -0700289 SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
joshualitt2c93efe2014-11-06 12:57:13 -0800290
291 // Setup clip
egdaniel8dd688b2015-01-22 10:16:09 -0800292 GrPipelineBuilder::AutoRestoreStencil ars;
bsalomon0ba8c242015-10-07 09:20:28 -0700293 GrAppliedClip clip;
bsalomone91f7b52015-10-27 06:42:50 -0700294 if (!fClipMaskManager->setupClipping(pipelineBuilder, &ars, nullptr, &clip)) {
joshualitt2c93efe2014-11-06 12:57:13 -0800295 return;
296 }
297
bsalomon0ba8c242015-10-07 09:20:28 -0700298 GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps;
299 if (clip.clipCoverageFragmentProcessor()) {
300 arfps.set(&pipelineBuilder);
301 arfps.addCoverageFragmentProcessor(clip.clipCoverageFragmentProcessor());
302 }
303
joshualitt2c93efe2014-11-06 12:57:13 -0800304 // set stencil settings for path
305 GrStencilSettings stencilSettings;
joshualitt1c735482015-07-13 08:08:25 -0700306 GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
egdanielec00d942015-09-14 12:56:10 -0700307 GrStencilAttachment* sb = fResourceProvider->attachStencilAttachment(rt);
bsalomon6bc1b5f2015-02-23 09:06:38 -0800308 this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings);
joshualitt2c93efe2014-11-06 12:57:13 -0800309
joshualittf2384692015-09-10 11:00:51 -0700310 GrBatch* batch = GrStencilPathBatch::Create(viewMatrix,
bsalomona44919e2015-08-18 13:28:19 -0700311 pipelineBuilder.isHWAntialias(),
bsalomone91f7b52015-10-27 06:42:50 -0700312 stencilSettings, clip.scissorState(),
bsalomona44919e2015-08-18 13:28:19 -0700313 pipelineBuilder.getRenderTarget(),
314 path);
bsalomon512be532015-09-10 10:42:55 -0700315 this->recordBatch(batch);
bsalomona44919e2015-08-18 13:28:19 -0700316 batch->unref();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000317}
318
joshualitt1c735482015-07-13 08:08:25 -0700319void GrDrawTarget::drawPath(const GrPipelineBuilder& pipelineBuilder,
joshualittf2384692015-09-10 11:00:51 -0700320 const SkMatrix& viewMatrix,
321 GrColor color,
joshualitt9853cce2014-11-17 14:22:48 -0800322 const GrPath* path,
323 GrPathRendering::FillType fill) {
bsalomon49f085d2014-09-05 13:34:00 -0700324 SkASSERT(path);
jvanverthe9c0fc62015-04-29 11:18:05 -0700325 SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000326
joshualittf2384692015-09-10 11:00:51 -0700327 GrDrawPathBatchBase* batch = GrDrawPathBatch::Create(viewMatrix, color, path);
bsalomon1fcc01c2015-09-09 09:48:06 -0700328 this->drawPathBatch(pipelineBuilder, batch, fill);
329 batch->unref();
330}
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000331
bsalomon1fcc01c2015-09-09 09:48:06 -0700332void GrDrawTarget::drawPathsFromRange(const GrPipelineBuilder& pipelineBuilder,
joshualittf2384692015-09-10 11:00:51 -0700333 const SkMatrix& viewMatrix,
334 const SkMatrix& localMatrix,
335 GrColor color,
cdalton8585dd22015-10-08 08:04:09 -0700336 GrPathRange* range,
bsalomon1fcc01c2015-09-09 09:48:06 -0700337 GrPathRangeDraw* draw,
bsalomonbf074552015-11-23 14:25:19 -0800338 GrPathRendering::FillType fill,
339 const SkRect& bounds) {
cdalton8585dd22015-10-08 08:04:09 -0700340 GrDrawPathBatchBase* batch = GrDrawPathRangeBatch::Create(viewMatrix, localMatrix, color,
bsalomonbf074552015-11-23 14:25:19 -0800341 range, draw, bounds);
bsalomon1fcc01c2015-09-09 09:48:06 -0700342 this->drawPathBatch(pipelineBuilder, batch, fill);
343 batch->unref();
344}
345
346void GrDrawTarget::drawPathBatch(const GrPipelineBuilder& pipelineBuilder,
347 GrDrawPathBatchBase* batch,
348 GrPathRendering::FillType fill) {
bsalomonadd79ef2015-08-19 13:26:49 -0700349 // This looks like drawBatch() but there is an added wrinkle that stencil settings get inserted
bsalomonb3b9aec2015-09-10 11:16:35 -0700350 // after setting up clipping but before onDrawBatch(). TODO: Figure out a better model for
351 // handling stencil settings WRT interactions between pipeline(builder), clipmaskmanager, and
352 // batches.
bsalomonadd79ef2015-08-19 13:26:49 -0700353
egdaniel8dd688b2015-01-22 10:16:09 -0800354 GrPipelineBuilder::AutoRestoreStencil ars;
bsalomon0ba8c242015-10-07 09:20:28 -0700355 GrAppliedClip clip;
bsalomone91f7b52015-10-27 06:42:50 -0700356 if (!fClipMaskManager->setupClipping(pipelineBuilder, &ars, &batch->bounds(), &clip)) {
bsalomonadd79ef2015-08-19 13:26:49 -0700357 return;
joshualitt2c93efe2014-11-06 12:57:13 -0800358 }
359
cdaltond4727922015-11-10 12:49:06 -0800360 GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps;
361 if (clip.clipCoverageFragmentProcessor()) {
362 arfps.set(&pipelineBuilder);
363 arfps.addCoverageFragmentProcessor(clip.clipCoverageFragmentProcessor());
364 }
365
bsalomonadd79ef2015-08-19 13:26:49 -0700366 // Ensure the render target has a stencil buffer and get the stencil settings.
joshualitt2c93efe2014-11-06 12:57:13 -0800367 GrStencilSettings stencilSettings;
joshualitt1c735482015-07-13 08:08:25 -0700368 GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
egdanielec00d942015-09-14 12:56:10 -0700369 GrStencilAttachment* sb = fResourceProvider->attachStencilAttachment(rt);
bsalomon6bc1b5f2015-02-23 09:06:38 -0800370 this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings);
bsalomonadd79ef2015-08-19 13:26:49 -0700371 batch->setStencilSettings(stencilSettings);
joshualitt2c93efe2014-11-06 12:57:13 -0800372
bsalomonad792c12015-09-10 11:10:50 -0700373 GrPipeline::CreateArgs args;
cdaltond4727922015-11-10 12:49:06 -0800374 if (!this->installPipelineInDrawBatch(&pipelineBuilder, &clip.scissorState(), batch)) {
bsalomonadd79ef2015-08-19 13:26:49 -0700375 return;
376 }
egdaniele36914c2015-02-13 09:00:33 -0800377
bsalomon512be532015-09-10 10:42:55 -0700378 this->recordBatch(batch);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000379}
380
joshualittd2b23e02015-08-21 10:53:34 -0700381void GrDrawTarget::drawNonAARect(const GrPipelineBuilder& pipelineBuilder,
joshualitt1c735482015-07-13 08:08:25 -0700382 GrColor color,
383 const SkMatrix& viewMatrix,
joshualittb6b513b2015-08-21 10:25:18 -0700384 const SkRect& rect) {
joshualittd2b23e02015-08-21 10:53:34 -0700385 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, viewMatrix, rect,
386 nullptr, nullptr));
joshualittad17cfc2015-05-05 10:45:57 -0700387 this->drawBatch(pipelineBuilder, batch);
388}
389
joshualittd2b23e02015-08-21 10:53:34 -0700390void GrDrawTarget::drawNonAARect(const GrPipelineBuilder& pipelineBuilder,
joshualittb6b513b2015-08-21 10:25:18 -0700391 GrColor color,
392 const SkMatrix& viewMatrix,
393 const SkRect& rect,
394 const SkMatrix& localMatrix) {
joshualittd2b23e02015-08-21 10:53:34 -0700395 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, viewMatrix, rect,
396 nullptr, &localMatrix));
joshualittb6b513b2015-08-21 10:25:18 -0700397 this->drawBatch(pipelineBuilder, batch);
398}
399
joshualittd2b23e02015-08-21 10:53:34 -0700400void GrDrawTarget::drawNonAARect(const GrPipelineBuilder& pipelineBuilder,
joshualittb6b513b2015-08-21 10:25:18 -0700401 GrColor color,
402 const SkMatrix& viewMatrix,
403 const SkRect& rect,
404 const SkRect& localRect) {
joshualittd2b23e02015-08-21 10:53:34 -0700405 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, viewMatrix, rect,
406 &localRect, nullptr));
joshualittb6b513b2015-08-21 10:25:18 -0700407 this->drawBatch(pipelineBuilder, batch);
408}
409
410
joshualitt1c735482015-07-13 08:08:25 -0700411void GrDrawTarget::drawAARect(const GrPipelineBuilder& pipelineBuilder,
robertphillipsea461502015-05-26 11:38:03 -0700412 GrColor color,
413 const SkMatrix& viewMatrix,
414 const SkRect& rect,
415 const SkRect& devRect) {
joshualittd2b23e02015-08-21 10:53:34 -0700416 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateAAFill(color, viewMatrix, rect,
bsalomonabd30f52015-08-13 13:34:48 -0700417 devRect));
joshualitt14205b12015-08-10 11:40:56 -0700418 this->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700419}
420
joshualitt9853cce2014-11-17 14:22:48 -0800421void GrDrawTarget::clear(const SkIRect* rect,
422 GrColor color,
423 bool canIgnoreRect,
bsalomon63b21962014-11-05 07:05:34 -0800424 GrRenderTarget* renderTarget) {
egdaniel51c8d402015-08-06 10:54:13 -0700425 SkIRect rtRect = SkIRect::MakeWH(renderTarget->width(), renderTarget->height());
426 SkIRect clippedRect;
427 if (!rect ||
428 (canIgnoreRect && this->caps()->fullClearIsFree()) ||
429 rect->contains(rtRect)) {
430 rect = &rtRect;
431 } else {
432 clippedRect = *rect;
433 if (!clippedRect.intersect(rtRect)) {
434 return;
435 }
436 rect = &clippedRect;
437 }
438
bsalomonb3b9aec2015-09-10 11:16:35 -0700439 if (this->caps()->useDrawInsteadOfClear()) {
bsalomon63b21962014-11-05 07:05:34 -0800440 // This works around a driver bug with clear by drawing a rect instead.
441 // The driver will ignore a clear if it is the only thing rendered to a
442 // target before the target is read.
egdaniel51c8d402015-08-06 10:54:13 -0700443 if (rect == &rtRect) {
bsalomon63b21962014-11-05 07:05:34 -0800444 this->discard(renderTarget);
445 }
bsalomon63b21962014-11-05 07:05:34 -0800446
egdaniel8dd688b2015-01-22 10:16:09 -0800447 GrPipelineBuilder pipelineBuilder;
egdanielc4b72722015-11-23 13:20:41 -0800448 pipelineBuilder.setXPFactory(
449 GrPorterDuffXPFactory::Create(SkXfermode::kSrc_Mode))->unref();
egdaniel8dd688b2015-01-22 10:16:09 -0800450 pipelineBuilder.setRenderTarget(renderTarget);
joshualitt9853cce2014-11-17 14:22:48 -0800451
joshualittd2b23e02015-08-21 10:53:34 -0700452 this->drawNonAARect(pipelineBuilder, color, SkMatrix::I(), *rect);
bsalomon53469832015-08-18 09:20:09 -0700453 } else {
halcanary385fe4d2015-08-26 13:07:48 -0700454 GrBatch* batch = new GrClearBatch(*rect, color, renderTarget);
bsalomon512be532015-09-10 10:42:55 -0700455 this->recordBatch(batch);
bsalomon53469832015-08-18 09:20:09 -0700456 batch->unref();
457 }
458}
459
460void GrDrawTarget::discard(GrRenderTarget* renderTarget) {
461 if (this->caps()->discardRenderTargetSupport()) {
halcanary385fe4d2015-08-26 13:07:48 -0700462 GrBatch* batch = new GrDiscardBatch(renderTarget);
bsalomon512be532015-09-10 10:42:55 -0700463 this->recordBatch(batch);
bsalomon53469832015-08-18 09:20:09 -0700464 batch->unref();
bsalomon63b21962014-11-05 07:05:34 -0800465 }
466}
467
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000468////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000469
bsalomon6df86402015-06-01 10:41:49 -0700470void GrDrawTarget::copySurface(GrSurface* dst,
bsalomon@google.com116ad842013-04-09 15:38:19 +0000471 GrSurface* src,
472 const SkIRect& srcRect,
473 const SkIPoint& dstPoint) {
bsalomon872062c2015-08-18 12:12:35 -0700474 GrBatch* batch = GrCopySurfaceBatch::Create(dst, src, srcRect, dstPoint);
475 if (batch) {
robertphillips498d7ac2015-10-30 10:11:30 -0700476#ifdef ENABLE_MDB
477 this->addDependency(src);
478#endif
479
bsalomon512be532015-09-10 10:42:55 -0700480 this->recordBatch(batch);
bsalomon872062c2015-08-18 12:12:35 -0700481 batch->unref();
bsalomon@google.come4617bf2013-04-03 14:56:40 +0000482 }
bsalomon@google.comeb851172013-04-15 13:51:00 +0000483}
484
bsalomon512be532015-09-10 10:42:55 -0700485template <class Left, class Right> static bool intersect(const Left& a, const Right& b) {
486 SkASSERT(a.fLeft <= a.fRight && a.fTop <= a.fBottom &&
487 b.fLeft <= b.fRight && b.fTop <= b.fBottom);
488 return a.fLeft < b.fRight && b.fLeft < a.fRight && a.fTop < b.fBottom && b.fTop < a.fBottom;
489}
490
491void GrDrawTarget::recordBatch(GrBatch* batch) {
robertphillipsa106c622015-10-16 09:07:06 -0700492 // A closed drawTarget should never receive new/more batches
robertphillips6a186652015-10-20 07:37:58 -0700493 SkASSERT(!this->isClosed());
robertphillipsa106c622015-10-16 09:07:06 -0700494
bsalomon512be532015-09-10 10:42:55 -0700495 // Check if there is a Batch Draw we can batch with by linearly searching back until we either
496 // 1) check every draw
497 // 2) intersect with something
498 // 3) find a 'blocker'
499 // Experimentally we have found that most batching occurs within the first 10 comparisons.
500 static const int kMaxLookback = 10;
501
502 GrBATCH_INFO("Re-Recording (%s, B%u)\n"
joshualitte2bcec32015-09-30 06:22:22 -0700503 "\tBounds LRTB (%f, %f, %f, %f)\n",
bsalomon512be532015-09-10 10:42:55 -0700504 batch->name(),
505 batch->uniqueID(),
506 batch->bounds().fLeft, batch->bounds().fRight,
507 batch->bounds().fTop, batch->bounds().fBottom);
508 GrBATCH_INFO(SkTabString(batch->dumpInfo(), 1).c_str());
509 GrBATCH_INFO("\tOutcome:\n");
510 int maxCandidates = SkTMin(kMaxLookback, fBatches.count());
511 if (maxCandidates) {
512 int i = 0;
513 while (true) {
514 GrBatch* candidate = fBatches.fromBack(i);
515 // We cannot continue to search backwards if the render target changes
516 if (candidate->renderTargetUniqueID() != batch->renderTargetUniqueID()) {
517 GrBATCH_INFO("\t\tBreaking because of (%s, B%u) Rendertarget\n",
518 candidate->name(), candidate->uniqueID());
519 break;
520 }
521 if (candidate->combineIfPossible(batch, *this->caps())) {
522 GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name(),
523 candidate->uniqueID());
524 return;
525 }
526 // Stop going backwards if we would cause a painter's order violation.
bsalomondb4758c2015-11-23 11:14:20 -0800527 // TODO: The bounds used here do not fully consider the clip. It may be advantageous
528 // to clip each batch's bounds to the clip.
bsalomon512be532015-09-10 10:42:55 -0700529 if (intersect(candidate->bounds(), batch->bounds())) {
530 GrBATCH_INFO("\t\tIntersects with (%s, B%u)\n", candidate->name(),
531 candidate->uniqueID());
532 break;
533 }
534 ++i;
535 if (i == maxCandidates) {
536 GrBATCH_INFO("\t\tReached max lookback or beginning of batch array %d\n", i);
537 break;
538 }
539 }
540 } else {
541 GrBATCH_INFO("\t\tFirstBatch\n");
542 }
543 fBatches.push_back().reset(SkRef(batch));
544}
545
egdaniele36914c2015-02-13 09:00:33 -0800546///////////////////////////////////////////////////////////////////////////////
547
bsalomonad792c12015-09-10 11:10:50 -0700548bool GrDrawTarget::installPipelineInDrawBatch(const GrPipelineBuilder* pipelineBuilder,
cdaltond4727922015-11-10 12:49:06 -0800549 const GrScissorState* scissor,
550 GrDrawBatch* batch) {
bsalomonad792c12015-09-10 11:10:50 -0700551 GrPipeline::CreateArgs args;
552 args.fPipelineBuilder = pipelineBuilder;
553 args.fCaps = this->caps();
cdaltond4727922015-11-10 12:49:06 -0800554 args.fScissor = scissor;
ethannicholasff210322015-11-24 12:10:10 -0800555 batch->getPipelineOptimizations(&args.fOpts);
556 args.fOpts.fColorPOI.completeCalculations(pipelineBuilder->fColorFragmentProcessors.begin(),
557 pipelineBuilder->numColorFragmentProcessors());
558 args.fOpts.fCoveragePOI.completeCalculations(
559 pipelineBuilder->fCoverageFragmentProcessors.begin(),
560 pipelineBuilder->numCoverageFragmentProcessors());
ethannicholasde4166a2015-11-30 08:57:38 -0800561 if (!this->setupDstReadIfNecessary(*pipelineBuilder, args.fOpts, &args.fDstTexture,
bsalomonad792c12015-09-10 11:10:50 -0700562 batch->bounds())) {
563 return false;
egdaniele36914c2015-02-13 09:00:33 -0800564 }
bsalomonad792c12015-09-10 11:10:50 -0700565
566 if (!batch->installPipeline(args)) {
567 return false;
568 }
569
570 return true;
egdaniele36914c2015-02-13 09:00:33 -0800571}
572
bsalomonb3b9aec2015-09-10 11:16:35 -0700573void GrDrawTarget::clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTarget* rt) {
halcanary385fe4d2015-08-26 13:07:48 -0700574 GrBatch* batch = new GrClearStencilClipBatch(rect, insideClip, rt);
bsalomon512be532015-09-10 10:42:55 -0700575 this->recordBatch(batch);
bsalomon5ea03632015-08-18 10:33:30 -0700576 batch->unref();
577}