blob: 1dc26bc8c60fc49a4d3f66e24774d345b492211c [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
bsalomon648c6962015-10-23 09:06:59 -070035GrDrawTarget::GrDrawTarget(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)
joshualittf6d259b2015-10-02 11:27:14 -070039 , fFlushState(fGpu, fResourceProvider, 0)
bsalomon512be532015-09-10 10:42:55 -070040 , fFlushing(false)
robertphillipsa106c622015-10-16 09:07:06 -070041 , fFirstUnpreparedBatch(0)
bsalomon648c6962015-10-23 09:06:59 -070042 , fFlags(0)
43 , fOptions(options) {
bsalomonb3b9aec2015-09-10 11:16:35 -070044 // TODO: Stop extracting the context (currently needed by GrClipMaskManager)
45 fContext = fGpu->getContext();
Brian Salomone66fec22015-09-10 14:40:20 -040046 fClipMaskManager.reset(new GrClipMaskManager(this));
robertphillips4beb5c12015-10-20 07:50:00 -070047
48#ifdef SK_DEBUG
49 static int debugID = 0;
50 fDebugID = debugID++;
51#endif
bsalomon4061b122015-05-29 10:26:19 -070052}
53
54GrDrawTarget::~GrDrawTarget() {
55 fGpu->unref();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000056}
57
58////////////////////////////////////////////////////////////////////////////////
59
robertphillips6a186652015-10-20 07:37:58 -070060// Add a GrDrawTarget-based dependency
61void GrDrawTarget::addDependency(GrDrawTarget* dependedOn) {
62 SkASSERT(!dependedOn->dependsOn(this)); // loops are bad
63
64 if (this->dependsOn(dependedOn)) {
65 return; // don't add duplicate dependencies
66 }
67
68 *fDependencies.push() = dependedOn;
69}
70
71// Convert from a GrSurface-based dependency to a GrDrawTarget one
72void GrDrawTarget::addDependency(GrSurface* dependedOn) {
73 if (dependedOn->asRenderTarget() && dependedOn->asRenderTarget()->getLastDrawTarget()) {
74 // If it is still receiving dependencies, this DT shouldn't be closed
75 SkASSERT(!this->isClosed());
76
77 GrDrawTarget* dt = dependedOn->asRenderTarget()->getLastDrawTarget();
78 if (dt == this) {
79 // self-read - presumably for dst reads
80 } else {
81 this->addDependency(dt);
82
83 // Can't make it closed in the self-read case
84 dt->makeClosed();
85 }
86 }
87}
88
robertphillips4beb5c12015-10-20 07:50:00 -070089#ifdef SK_DEBUG
90void GrDrawTarget::dump() const {
91 SkDebugf("--------------------------------------------------------------\n");
92 SkDebugf("node: %d\n");
93 SkDebugf("relies On (%d): ", fDependencies.count());
94 for (int i = 0; i < fDependencies.count(); ++i) {
95 SkDebugf("%d, ", fDependencies[i]->fDebugID);
96 }
97 SkDebugf("\n");
98 SkDebugf("batches (%d):\n", fBatches.count());
99 for (int i = 0; i < fBatches.count(); ++i) {
100#if 0
101 SkDebugf("*******************************\n");
102#endif
103 SkDebugf("%d: %s\n", i, fBatches[i]->name());
104#if 0
105 SkString str = fBatches[i]->dumpInfo();
106 SkDebugf("%s\n", str.c_str());
107#endif
108 }
109}
110#endif
111
bsalomon50785a32015-02-06 07:02:37 -0800112bool GrDrawTarget::setupDstReadIfNecessary(const GrPipelineBuilder& pipelineBuilder,
egdaniele36914c2015-02-13 09:00:33 -0800113 const GrProcOptInfo& colorPOI,
114 const GrProcOptInfo& coveragePOI,
bsalomon6a44c6a2015-05-26 09:49:05 -0700115 GrXferProcessor::DstTexture* dstTexture,
bsalomonad792c12015-09-10 11:10:50 -0700116 const SkRect& batchBounds) {
117 SkRect bounds = batchBounds;
118 bounds.outset(0.5f, 0.5f);
119
bsalomon6a44c6a2015-05-26 09:49:05 -0700120 if (!pipelineBuilder.willXPNeedDstTexture(*this->caps(), colorPOI, coveragePOI)) {
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000121 return true;
122 }
cdalton9954bc32015-04-29 14:17:00 -0700123
bsalomon50785a32015-02-06 07:02:37 -0800124 GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
cdalton9954bc32015-04-29 14:17:00 -0700125
126 if (this->caps()->textureBarrierSupport()) {
127 if (GrTexture* rtTex = rt->asTexture()) {
bsalomondc47ff72015-05-26 12:16:59 -0700128 // The render target is a texture, so we can read from it directly in the shader. The XP
cdalton9954bc32015-04-29 14:17:00 -0700129 // will be responsible to detect this situation and request a texture barrier.
bsalomon6a44c6a2015-05-26 09:49:05 -0700130 dstTexture->setTexture(rtTex);
131 dstTexture->setOffset(0, 0);
cdalton9954bc32015-04-29 14:17:00 -0700132 return true;
133 }
134 }
135
136 SkIRect copyRect;
joshualitt44701df2015-02-23 14:44:57 -0800137 pipelineBuilder.clip().getConservativeBounds(rt, &copyRect);
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000138
bsalomonad792c12015-09-10 11:10:50 -0700139 SkIRect drawIBounds;
140 bounds.roundOut(&drawIBounds);
141 if (!copyRect.intersect(drawIBounds)) {
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +0000142#ifdef SK_DEBUG
bsalomonb3b9aec2015-09-10 11:16:35 -0700143 GrCapsDebugf(this->caps(), "Missed an early reject. "
144 "Bailing on draw from setupDstReadIfNecessary.\n");
commit-bot@chromium.orgbb5c4652013-04-01 12:49:31 +0000145#endif
bsalomonad792c12015-09-10 11:10:50 -0700146 return false;
commit-bot@chromium.orgbb5c4652013-04-01 12:49:31 +0000147 }
skia.committer@gmail.com05a2ee02013-04-02 07:01:34 +0000148
commit-bot@chromium.org63150af2013-04-11 22:00:22 +0000149 // MSAA consideration: When there is support for reading MSAA samples in the shader we could
150 // have per-sample dst values by making the copy multisampled.
bsalomonf2703d82014-10-28 14:33:06 -0700151 GrSurfaceDesc desc;
bsalomonb3b9aec2015-09-10 11:16:35 -0700152 if (!fGpu->initCopySurfaceDstDesc(rt, &desc)) {
bsalomona73239a2015-04-28 13:35:17 -0700153 desc.fOrigin = kDefault_GrSurfaceOrigin;
154 desc.fFlags = kRenderTarget_GrSurfaceFlag;
155 desc.fConfig = rt->config();
156 }
157
commit-bot@chromium.orgbb5c4652013-04-01 12:49:31 +0000158 desc.fWidth = copyRect.width();
159 desc.fHeight = copyRect.height();
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000160
bsalomoneae62002015-07-31 13:59:30 -0700161 static const uint32_t kFlags = 0;
162 SkAutoTUnref<GrTexture> copy(fResourceProvider->createApproxTexture(desc, kFlags));
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000163
bsalomone3059732014-10-14 11:47:22 -0700164 if (!copy) {
tfarina38406c82014-10-31 07:11:12 -0700165 SkDebugf("Failed to create temporary copy of destination texture.\n");
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000166 return false;
167 }
bsalomon@google.come4617bf2013-04-03 14:56:40 +0000168 SkIPoint dstPoint = {0, 0};
bsalomon6df86402015-06-01 10:41:49 -0700169 this->copySurface(copy, rt, copyRect, dstPoint);
170 dstTexture->setTexture(copy);
171 dstTexture->setOffset(copyRect.fLeft, copyRect.fTop);
172 return true;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000173}
174
bsalomona73239a2015-04-28 13:35:17 -0700175void GrDrawTarget::flush() {
176 if (fFlushing) {
177 return;
178 }
179 fFlushing = true;
180
robertphillipsa106c622015-10-16 09:07:06 -0700181 // Semi-usually the drawTargets are already closed at this point, but sometimes Ganesh
182 // needs to flush mid-draw. In that case, the SkGpuDevice's drawTargets won't be closed
183 // but need to be flushed anyway. Closing such drawTargets here will mean new
184 // drawTargets will be created to replace them if the SkGpuDevice(s) write to them again.
185 this->makeClosed();
186
robertphillipsa352b142015-10-22 05:31:32 -0700187 // Loop over all batches and generate geometry
joshualittf6d259b2015-10-02 11:27:14 -0700188 for (; fFirstUnpreparedBatch < fBatches.count(); ++fFirstUnpreparedBatch) {
189 fBatches[fFirstUnpreparedBatch]->prepare(&fFlushState);
bsalomon512be532015-09-10 10:42:55 -0700190 }
191
192 // Upload all data to the GPU
joshualittf6d259b2015-10-02 11:27:14 -0700193 fFlushState.preIssueDraws();
bsalomon512be532015-09-10 10:42:55 -0700194
195 // Draw all the generated geometry.
196 for (int i = 0; i < fBatches.count(); ++i) {
joshualittf6d259b2015-10-02 11:27:14 -0700197 fBatches[i]->draw(&fFlushState);
bsalomon512be532015-09-10 10:42:55 -0700198 }
199
joshualittf6d259b2015-10-02 11:27:14 -0700200 SkASSERT(fFlushState.lastFlushedToken() == fFlushState.currentToken());
201 this->reset();
bsalomona73239a2015-04-28 13:35:17 -0700202
bsalomona73239a2015-04-28 13:35:17 -0700203 fFlushing = false;
bsalomona73239a2015-04-28 13:35:17 -0700204}
205
bsalomon512be532015-09-10 10:42:55 -0700206void GrDrawTarget::reset() {
joshualittf6d259b2015-10-02 11:27:14 -0700207 fFirstUnpreparedBatch = 0;
bsalomon512be532015-09-10 10:42:55 -0700208 fBatches.reset();
joshualittf6d259b2015-10-02 11:27:14 -0700209 fFlushState.reset();
bsalomon512be532015-09-10 10:42:55 -0700210}
211
bsalomonabd30f52015-08-13 13:34:48 -0700212void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder, GrDrawBatch* batch) {
joshualitt4d8da812015-01-28 12:53:54 -0800213 // Setup clip
214 GrScissorState scissorState;
joshualitt4d8da812015-01-28 12:53:54 -0800215 GrPipelineBuilder::AutoRestoreStencil ars;
bsalomon0ba8c242015-10-07 09:20:28 -0700216 GrAppliedClip clip;
217 if (!fClipMaskManager->setupClipping(pipelineBuilder, &ars, &scissorState, &batch->bounds(),
218 &clip)) {
joshualitt4d8da812015-01-28 12:53:54 -0800219 return;
220 }
bsalomon0ba8c242015-10-07 09:20:28 -0700221 GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps;
222 if (clip.clipCoverageFragmentProcessor()) {
223 arfps.set(&pipelineBuilder);
224 arfps.addCoverageFragmentProcessor(clip.clipCoverageFragmentProcessor());
225 }
joshualitt4d8da812015-01-28 12:53:54 -0800226
bsalomonad792c12015-09-10 11:10:50 -0700227 GrPipeline::CreateArgs args;
228 if (!this->installPipelineInDrawBatch(&pipelineBuilder, &scissorState, batch)) {
egdaniele36914c2015-02-13 09:00:33 -0800229 return;
230 }
bsalomonad792c12015-09-10 11:10:50 -0700231
bsalomon512be532015-09-10 10:42:55 -0700232 this->recordBatch(batch);
joshualitt4d8da812015-01-28 12:53:54 -0800233}
234
joshualitt2c93efe2014-11-06 12:57:13 -0800235static const GrStencilSettings& winding_path_stencil_settings() {
236 GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
237 kIncClamp_StencilOp,
238 kIncClamp_StencilOp,
239 kAlwaysIfInClip_StencilFunc,
240 0xFFFF, 0xFFFF, 0xFFFF);
241 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
242}
243
244static const GrStencilSettings& even_odd_path_stencil_settings() {
245 GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
246 kInvert_StencilOp,
247 kInvert_StencilOp,
248 kAlwaysIfInClip_StencilFunc,
249 0xFFFF, 0xFFFF, 0xFFFF);
250 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
251}
252
253void GrDrawTarget::getPathStencilSettingsForFilltype(GrPathRendering::FillType fill,
egdaniel8dc7c3a2015-04-16 11:22:42 -0700254 const GrStencilAttachment* sb,
joshualitt2c93efe2014-11-06 12:57:13 -0800255 GrStencilSettings* outStencilSettings) {
256
257 switch (fill) {
258 default:
259 SkFAIL("Unexpected path fill.");
260 case GrPathRendering::kWinding_FillType:
261 *outStencilSettings = winding_path_stencil_settings();
262 break;
263 case GrPathRendering::kEvenOdd_FillType:
264 *outStencilSettings = even_odd_path_stencil_settings();
265 break;
266 }
bsalomonb3b9aec2015-09-10 11:16:35 -0700267 fClipMaskManager->adjustPathStencilParams(sb, outStencilSettings);
joshualitt2c93efe2014-11-06 12:57:13 -0800268}
269
joshualitt1c735482015-07-13 08:08:25 -0700270void GrDrawTarget::stencilPath(const GrPipelineBuilder& pipelineBuilder,
joshualittf2384692015-09-10 11:00:51 -0700271 const SkMatrix& viewMatrix,
joshualitt9853cce2014-11-17 14:22:48 -0800272 const GrPath* path,
273 GrPathRendering::FillType fill) {
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000274 // TODO: extract portions of checkDraw that are relevant to path stenciling.
bsalomon49f085d2014-09-05 13:34:00 -0700275 SkASSERT(path);
jvanverthe9c0fc62015-04-29 11:18:05 -0700276 SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
joshualitt2c93efe2014-11-06 12:57:13 -0800277
278 // Setup clip
bsalomon3e791242014-12-17 13:43:13 -0800279 GrScissorState scissorState;
egdaniel8dd688b2015-01-22 10:16:09 -0800280 GrPipelineBuilder::AutoRestoreStencil ars;
bsalomon0ba8c242015-10-07 09:20:28 -0700281 GrAppliedClip clip;
282 if (!fClipMaskManager->setupClipping(pipelineBuilder, &ars, &scissorState, nullptr, &clip)) {
joshualitt2c93efe2014-11-06 12:57:13 -0800283 return;
284 }
285
bsalomon0ba8c242015-10-07 09:20:28 -0700286 GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps;
287 if (clip.clipCoverageFragmentProcessor()) {
288 arfps.set(&pipelineBuilder);
289 arfps.addCoverageFragmentProcessor(clip.clipCoverageFragmentProcessor());
290 }
291
joshualitt2c93efe2014-11-06 12:57:13 -0800292 // set stencil settings for path
293 GrStencilSettings stencilSettings;
joshualitt1c735482015-07-13 08:08:25 -0700294 GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
egdanielec00d942015-09-14 12:56:10 -0700295 GrStencilAttachment* sb = fResourceProvider->attachStencilAttachment(rt);
bsalomon6bc1b5f2015-02-23 09:06:38 -0800296 this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings);
joshualitt2c93efe2014-11-06 12:57:13 -0800297
joshualittf2384692015-09-10 11:00:51 -0700298 GrBatch* batch = GrStencilPathBatch::Create(viewMatrix,
bsalomona44919e2015-08-18 13:28:19 -0700299 pipelineBuilder.isHWAntialias(),
300 stencilSettings, scissorState,
301 pipelineBuilder.getRenderTarget(),
302 path);
bsalomon512be532015-09-10 10:42:55 -0700303 this->recordBatch(batch);
bsalomona44919e2015-08-18 13:28:19 -0700304 batch->unref();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000305}
306
joshualitt1c735482015-07-13 08:08:25 -0700307void GrDrawTarget::drawPath(const GrPipelineBuilder& pipelineBuilder,
joshualittf2384692015-09-10 11:00:51 -0700308 const SkMatrix& viewMatrix,
309 GrColor color,
joshualitt9853cce2014-11-17 14:22:48 -0800310 const GrPath* path,
311 GrPathRendering::FillType fill) {
bsalomon49f085d2014-09-05 13:34:00 -0700312 SkASSERT(path);
jvanverthe9c0fc62015-04-29 11:18:05 -0700313 SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000314
joshualittf2384692015-09-10 11:00:51 -0700315 GrDrawPathBatchBase* batch = GrDrawPathBatch::Create(viewMatrix, color, path);
bsalomon1fcc01c2015-09-09 09:48:06 -0700316 this->drawPathBatch(pipelineBuilder, batch, fill);
317 batch->unref();
318}
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000319
bsalomon1fcc01c2015-09-09 09:48:06 -0700320void GrDrawTarget::drawPathsFromRange(const GrPipelineBuilder& pipelineBuilder,
joshualittf2384692015-09-10 11:00:51 -0700321 const SkMatrix& viewMatrix,
322 const SkMatrix& localMatrix,
323 GrColor color,
cdalton8585dd22015-10-08 08:04:09 -0700324 GrPathRange* range,
bsalomon1fcc01c2015-09-09 09:48:06 -0700325 GrPathRangeDraw* draw,
326 GrPathRendering::FillType fill) {
cdalton8585dd22015-10-08 08:04:09 -0700327 GrDrawPathBatchBase* batch = GrDrawPathRangeBatch::Create(viewMatrix, localMatrix, color,
328 range, draw);
bsalomon1fcc01c2015-09-09 09:48:06 -0700329 this->drawPathBatch(pipelineBuilder, batch, fill);
330 batch->unref();
331}
332
333void GrDrawTarget::drawPathBatch(const GrPipelineBuilder& pipelineBuilder,
334 GrDrawPathBatchBase* batch,
335 GrPathRendering::FillType fill) {
bsalomonadd79ef2015-08-19 13:26:49 -0700336 // This looks like drawBatch() but there is an added wrinkle that stencil settings get inserted
bsalomonb3b9aec2015-09-10 11:16:35 -0700337 // after setting up clipping but before onDrawBatch(). TODO: Figure out a better model for
338 // handling stencil settings WRT interactions between pipeline(builder), clipmaskmanager, and
339 // batches.
bsalomonadd79ef2015-08-19 13:26:49 -0700340
bsalomon3e791242014-12-17 13:43:13 -0800341 GrScissorState scissorState;
egdaniel8dd688b2015-01-22 10:16:09 -0800342 GrPipelineBuilder::AutoRestoreStencil ars;
bsalomon0ba8c242015-10-07 09:20:28 -0700343 GrAppliedClip clip;
344 if (!fClipMaskManager->setupClipping(pipelineBuilder, &ars, &scissorState, &batch->bounds(),
345 &clip)) {
bsalomonadd79ef2015-08-19 13:26:49 -0700346 return;
joshualitt2c93efe2014-11-06 12:57:13 -0800347 }
348
bsalomon0ba8c242015-10-07 09:20:28 -0700349 GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps;
350 if (clip.clipCoverageFragmentProcessor()) {
351 arfps.set(&pipelineBuilder);
352 arfps.addCoverageFragmentProcessor(clip.clipCoverageFragmentProcessor());
353 }
354
bsalomonadd79ef2015-08-19 13:26:49 -0700355 // Ensure the render target has a stencil buffer and get the stencil settings.
joshualitt2c93efe2014-11-06 12:57:13 -0800356 GrStencilSettings stencilSettings;
joshualitt1c735482015-07-13 08:08:25 -0700357 GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
egdanielec00d942015-09-14 12:56:10 -0700358 GrStencilAttachment* sb = fResourceProvider->attachStencilAttachment(rt);
bsalomon6bc1b5f2015-02-23 09:06:38 -0800359 this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings);
bsalomonadd79ef2015-08-19 13:26:49 -0700360 batch->setStencilSettings(stencilSettings);
joshualitt2c93efe2014-11-06 12:57:13 -0800361
bsalomonad792c12015-09-10 11:10:50 -0700362 GrPipeline::CreateArgs args;
363 if (!this->installPipelineInDrawBatch(&pipelineBuilder, &scissorState, batch)) {
bsalomonadd79ef2015-08-19 13:26:49 -0700364 return;
365 }
egdaniele36914c2015-02-13 09:00:33 -0800366
bsalomon512be532015-09-10 10:42:55 -0700367 this->recordBatch(batch);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000368}
369
joshualittd2b23e02015-08-21 10:53:34 -0700370void GrDrawTarget::drawNonAARect(const GrPipelineBuilder& pipelineBuilder,
joshualitt1c735482015-07-13 08:08:25 -0700371 GrColor color,
372 const SkMatrix& viewMatrix,
joshualittb6b513b2015-08-21 10:25:18 -0700373 const SkRect& rect) {
joshualittd2b23e02015-08-21 10:53:34 -0700374 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, viewMatrix, rect,
375 nullptr, nullptr));
joshualittad17cfc2015-05-05 10:45:57 -0700376 this->drawBatch(pipelineBuilder, batch);
377}
378
joshualittd2b23e02015-08-21 10:53:34 -0700379void GrDrawTarget::drawNonAARect(const GrPipelineBuilder& pipelineBuilder,
joshualittb6b513b2015-08-21 10:25:18 -0700380 GrColor color,
381 const SkMatrix& viewMatrix,
382 const SkRect& rect,
383 const SkMatrix& localMatrix) {
joshualittd2b23e02015-08-21 10:53:34 -0700384 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, viewMatrix, rect,
385 nullptr, &localMatrix));
joshualittb6b513b2015-08-21 10:25:18 -0700386 this->drawBatch(pipelineBuilder, batch);
387}
388
joshualittd2b23e02015-08-21 10:53:34 -0700389void GrDrawTarget::drawNonAARect(const GrPipelineBuilder& pipelineBuilder,
joshualittb6b513b2015-08-21 10:25:18 -0700390 GrColor color,
391 const SkMatrix& viewMatrix,
392 const SkRect& rect,
393 const SkRect& localRect) {
joshualittd2b23e02015-08-21 10:53:34 -0700394 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, viewMatrix, rect,
395 &localRect, nullptr));
joshualittb6b513b2015-08-21 10:25:18 -0700396 this->drawBatch(pipelineBuilder, batch);
397}
398
399
joshualitt1c735482015-07-13 08:08:25 -0700400void GrDrawTarget::drawAARect(const GrPipelineBuilder& pipelineBuilder,
robertphillipsea461502015-05-26 11:38:03 -0700401 GrColor color,
402 const SkMatrix& viewMatrix,
403 const SkRect& rect,
404 const SkRect& devRect) {
joshualittd2b23e02015-08-21 10:53:34 -0700405 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateAAFill(color, viewMatrix, rect,
bsalomonabd30f52015-08-13 13:34:48 -0700406 devRect));
joshualitt14205b12015-08-10 11:40:56 -0700407 this->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700408}
409
joshualitt9853cce2014-11-17 14:22:48 -0800410void GrDrawTarget::clear(const SkIRect* rect,
411 GrColor color,
412 bool canIgnoreRect,
bsalomon63b21962014-11-05 07:05:34 -0800413 GrRenderTarget* renderTarget) {
egdaniel51c8d402015-08-06 10:54:13 -0700414 SkIRect rtRect = SkIRect::MakeWH(renderTarget->width(), renderTarget->height());
415 SkIRect clippedRect;
416 if (!rect ||
417 (canIgnoreRect && this->caps()->fullClearIsFree()) ||
418 rect->contains(rtRect)) {
419 rect = &rtRect;
420 } else {
421 clippedRect = *rect;
422 if (!clippedRect.intersect(rtRect)) {
423 return;
424 }
425 rect = &clippedRect;
426 }
427
bsalomonb3b9aec2015-09-10 11:16:35 -0700428 if (this->caps()->useDrawInsteadOfClear()) {
bsalomon63b21962014-11-05 07:05:34 -0800429 // This works around a driver bug with clear by drawing a rect instead.
430 // The driver will ignore a clear if it is the only thing rendered to a
431 // target before the target is read.
egdaniel51c8d402015-08-06 10:54:13 -0700432 if (rect == &rtRect) {
bsalomon63b21962014-11-05 07:05:34 -0800433 this->discard(renderTarget);
434 }
bsalomon63b21962014-11-05 07:05:34 -0800435
egdaniel8dd688b2015-01-22 10:16:09 -0800436 GrPipelineBuilder pipelineBuilder;
437 pipelineBuilder.setRenderTarget(renderTarget);
joshualitt9853cce2014-11-17 14:22:48 -0800438
joshualittd2b23e02015-08-21 10:53:34 -0700439 this->drawNonAARect(pipelineBuilder, color, SkMatrix::I(), *rect);
bsalomon53469832015-08-18 09:20:09 -0700440 } else {
halcanary385fe4d2015-08-26 13:07:48 -0700441 GrBatch* batch = new GrClearBatch(*rect, color, renderTarget);
bsalomon512be532015-09-10 10:42:55 -0700442 this->recordBatch(batch);
bsalomon53469832015-08-18 09:20:09 -0700443 batch->unref();
444 }
445}
446
447void GrDrawTarget::discard(GrRenderTarget* renderTarget) {
448 if (this->caps()->discardRenderTargetSupport()) {
halcanary385fe4d2015-08-26 13:07:48 -0700449 GrBatch* batch = new GrDiscardBatch(renderTarget);
bsalomon512be532015-09-10 10:42:55 -0700450 this->recordBatch(batch);
bsalomon53469832015-08-18 09:20:09 -0700451 batch->unref();
bsalomon63b21962014-11-05 07:05:34 -0800452 }
453}
454
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000455////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000456
bsalomon6df86402015-06-01 10:41:49 -0700457void GrDrawTarget::copySurface(GrSurface* dst,
bsalomon@google.com116ad842013-04-09 15:38:19 +0000458 GrSurface* src,
459 const SkIRect& srcRect,
460 const SkIPoint& dstPoint) {
bsalomon872062c2015-08-18 12:12:35 -0700461 GrBatch* batch = GrCopySurfaceBatch::Create(dst, src, srcRect, dstPoint);
462 if (batch) {
bsalomon512be532015-09-10 10:42:55 -0700463 this->recordBatch(batch);
bsalomon872062c2015-08-18 12:12:35 -0700464 batch->unref();
bsalomon@google.come4617bf2013-04-03 14:56:40 +0000465 }
bsalomon@google.comeb851172013-04-15 13:51:00 +0000466}
467
bsalomon512be532015-09-10 10:42:55 -0700468template <class Left, class Right> static bool intersect(const Left& a, const Right& b) {
469 SkASSERT(a.fLeft <= a.fRight && a.fTop <= a.fBottom &&
470 b.fLeft <= b.fRight && b.fTop <= b.fBottom);
471 return a.fLeft < b.fRight && b.fLeft < a.fRight && a.fTop < b.fBottom && b.fTop < a.fBottom;
472}
473
474void GrDrawTarget::recordBatch(GrBatch* batch) {
robertphillipsa106c622015-10-16 09:07:06 -0700475 // A closed drawTarget should never receive new/more batches
robertphillips6a186652015-10-20 07:37:58 -0700476 SkASSERT(!this->isClosed());
bsalomon648c6962015-10-23 09:06:59 -0700477 // Should never have batches queued up when in immediate mode.
478 SkASSERT(!fOptions.fImmediateMode || !fBatches.count());
robertphillipsa106c622015-10-16 09:07:06 -0700479
bsalomon512be532015-09-10 10:42:55 -0700480 // Check if there is a Batch Draw we can batch with by linearly searching back until we either
481 // 1) check every draw
482 // 2) intersect with something
483 // 3) find a 'blocker'
484 // Experimentally we have found that most batching occurs within the first 10 comparisons.
485 static const int kMaxLookback = 10;
486
487 GrBATCH_INFO("Re-Recording (%s, B%u)\n"
joshualitte2bcec32015-09-30 06:22:22 -0700488 "\tBounds LRTB (%f, %f, %f, %f)\n",
bsalomon512be532015-09-10 10:42:55 -0700489 batch->name(),
490 batch->uniqueID(),
491 batch->bounds().fLeft, batch->bounds().fRight,
492 batch->bounds().fTop, batch->bounds().fBottom);
493 GrBATCH_INFO(SkTabString(batch->dumpInfo(), 1).c_str());
494 GrBATCH_INFO("\tOutcome:\n");
495 int maxCandidates = SkTMin(kMaxLookback, fBatches.count());
496 if (maxCandidates) {
497 int i = 0;
498 while (true) {
499 GrBatch* candidate = fBatches.fromBack(i);
500 // We cannot continue to search backwards if the render target changes
501 if (candidate->renderTargetUniqueID() != batch->renderTargetUniqueID()) {
502 GrBATCH_INFO("\t\tBreaking because of (%s, B%u) Rendertarget\n",
503 candidate->name(), candidate->uniqueID());
504 break;
505 }
506 if (candidate->combineIfPossible(batch, *this->caps())) {
507 GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name(),
508 candidate->uniqueID());
509 return;
510 }
511 // Stop going backwards if we would cause a painter's order violation.
512 if (intersect(candidate->bounds(), batch->bounds())) {
513 GrBATCH_INFO("\t\tIntersects with (%s, B%u)\n", candidate->name(),
514 candidate->uniqueID());
515 break;
516 }
517 ++i;
518 if (i == maxCandidates) {
519 GrBATCH_INFO("\t\tReached max lookback or beginning of batch array %d\n", i);
520 break;
521 }
522 }
523 } else {
524 GrBATCH_INFO("\t\tFirstBatch\n");
525 }
526 fBatches.push_back().reset(SkRef(batch));
joshualittf6d259b2015-10-02 11:27:14 -0700527 if (fBatches.count() > kMaxLookback) {
528 SkASSERT(fBatches.count() - kMaxLookback - fFirstUnpreparedBatch == 1);
529 fBatches[fFirstUnpreparedBatch++]->prepare(&fFlushState);
530 }
bsalomon648c6962015-10-23 09:06:59 -0700531 if (fOptions.fImmediateMode) {
532 this->flush();
533 }
bsalomon512be532015-09-10 10:42:55 -0700534}
535
egdaniele36914c2015-02-13 09:00:33 -0800536///////////////////////////////////////////////////////////////////////////////
537
bsalomonad792c12015-09-10 11:10:50 -0700538bool GrDrawTarget::installPipelineInDrawBatch(const GrPipelineBuilder* pipelineBuilder,
539 const GrScissorState* scissor,
540 GrDrawBatch* batch) {
541 GrPipeline::CreateArgs args;
542 args.fPipelineBuilder = pipelineBuilder;
543 args.fCaps = this->caps();
544 args.fScissor = scissor;
545 args.fColorPOI = pipelineBuilder->colorProcInfo(batch);
546 args.fCoveragePOI = pipelineBuilder->coverageProcInfo(batch);
547 if (!this->setupDstReadIfNecessary(*pipelineBuilder, args.fColorPOI,
548 args.fCoveragePOI, &args.fDstTexture,
549 batch->bounds())) {
550 return false;
egdaniele36914c2015-02-13 09:00:33 -0800551 }
bsalomonad792c12015-09-10 11:10:50 -0700552
553 if (!batch->installPipeline(args)) {
554 return false;
555 }
556
557 return true;
egdaniele36914c2015-02-13 09:00:33 -0800558}
559
bsalomonb3b9aec2015-09-10 11:16:35 -0700560void GrDrawTarget::clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTarget* rt) {
halcanary385fe4d2015-08-26 13:07:48 -0700561 GrBatch* batch = new GrClearStencilClipBatch(rect, insideClip, rt);
bsalomon512be532015-09-10 10:42:55 -0700562 this->recordBatch(batch);
bsalomon5ea03632015-08-18 10:33:30 -0700563 batch->unref();
564}