blob: 84f1e92003cae2c9468c55cfdc76bc5f5d5db923 [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
bsalomon4061b122015-05-29 10:26:19 -070035GrDrawTarget::GrDrawTarget(GrGpu* gpu, GrResourceProvider* resourceProvider)
36 : fGpu(SkRef(gpu))
37 , fCaps(SkRef(gpu->caps()))
38 , fResourceProvider(resourceProvider)
bsalomon512be532015-09-10 10:42:55 -070039 , fFlushing(false)
40 , fLastFlushToken(0) {
bsalomon4061b122015-05-29 10:26:19 -070041}
42
43GrDrawTarget::~GrDrawTarget() {
44 fGpu->unref();
45 fCaps->unref();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000046}
47
48////////////////////////////////////////////////////////////////////////////////
49
bsalomon50785a32015-02-06 07:02:37 -080050bool GrDrawTarget::setupDstReadIfNecessary(const GrPipelineBuilder& pipelineBuilder,
egdaniele36914c2015-02-13 09:00:33 -080051 const GrProcOptInfo& colorPOI,
52 const GrProcOptInfo& coveragePOI,
bsalomon6a44c6a2015-05-26 09:49:05 -070053 GrXferProcessor::DstTexture* dstTexture,
joshualitt9853cce2014-11-17 14:22:48 -080054 const SkRect* drawBounds) {
bsalomon6a44c6a2015-05-26 09:49:05 -070055 if (!pipelineBuilder.willXPNeedDstTexture(*this->caps(), colorPOI, coveragePOI)) {
bsalomon@google.com26e18b52013-03-29 19:22:36 +000056 return true;
57 }
cdalton9954bc32015-04-29 14:17:00 -070058
bsalomon50785a32015-02-06 07:02:37 -080059 GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
cdalton9954bc32015-04-29 14:17:00 -070060
61 if (this->caps()->textureBarrierSupport()) {
62 if (GrTexture* rtTex = rt->asTexture()) {
bsalomondc47ff72015-05-26 12:16:59 -070063 // The render target is a texture, so we can read from it directly in the shader. The XP
cdalton9954bc32015-04-29 14:17:00 -070064 // will be responsible to detect this situation and request a texture barrier.
bsalomon6a44c6a2015-05-26 09:49:05 -070065 dstTexture->setTexture(rtTex);
66 dstTexture->setOffset(0, 0);
cdalton9954bc32015-04-29 14:17:00 -070067 return true;
68 }
69 }
70
71 SkIRect copyRect;
joshualitt44701df2015-02-23 14:44:57 -080072 pipelineBuilder.clip().getConservativeBounds(rt, &copyRect);
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +000073
bsalomon49f085d2014-09-05 13:34:00 -070074 if (drawBounds) {
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +000075 SkIRect drawIBounds;
76 drawBounds->roundOut(&drawIBounds);
commit-bot@chromium.orgbb5c4652013-04-01 12:49:31 +000077 if (!copyRect.intersect(drawIBounds)) {
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +000078#ifdef SK_DEBUG
bsalomon682c2692015-05-22 14:01:46 -070079 GrCapsDebugf(fCaps, "Missed an early reject. "
80 "Bailing on draw from setupDstReadIfNecessary.\n");
commit-bot@chromium.orgbb5c4652013-04-01 12:49:31 +000081#endif
82 return false;
83 }
84 } else {
commit-bot@chromium.org515dcd32013-08-28 14:17:03 +000085#ifdef SK_DEBUG
tfarina38406c82014-10-31 07:11:12 -070086 //SkDebugf("No dev bounds when dst copy is made.\n");
commit-bot@chromium.orgbb5c4652013-04-01 12:49:31 +000087#endif
88 }
skia.committer@gmail.com05a2ee02013-04-02 07:01:34 +000089
commit-bot@chromium.org63150af2013-04-11 22:00:22 +000090 // MSAA consideration: When there is support for reading MSAA samples in the shader we could
91 // have per-sample dst values by making the copy multisampled.
bsalomonf2703d82014-10-28 14:33:06 -070092 GrSurfaceDesc desc;
bsalomona73239a2015-04-28 13:35:17 -070093 if (!this->getGpu()->initCopySurfaceDstDesc(rt, &desc)) {
94 desc.fOrigin = kDefault_GrSurfaceOrigin;
95 desc.fFlags = kRenderTarget_GrSurfaceFlag;
96 desc.fConfig = rt->config();
97 }
98
99
commit-bot@chromium.orgbb5c4652013-04-01 12:49:31 +0000100 desc.fWidth = copyRect.width();
101 desc.fHeight = copyRect.height();
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000102
bsalomoneae62002015-07-31 13:59:30 -0700103 static const uint32_t kFlags = 0;
104 SkAutoTUnref<GrTexture> copy(fResourceProvider->createApproxTexture(desc, kFlags));
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000105
bsalomone3059732014-10-14 11:47:22 -0700106 if (!copy) {
tfarina38406c82014-10-31 07:11:12 -0700107 SkDebugf("Failed to create temporary copy of destination texture.\n");
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000108 return false;
109 }
bsalomon@google.come4617bf2013-04-03 14:56:40 +0000110 SkIPoint dstPoint = {0, 0};
bsalomon6df86402015-06-01 10:41:49 -0700111 this->copySurface(copy, rt, copyRect, dstPoint);
112 dstTexture->setTexture(copy);
113 dstTexture->setOffset(copyRect.fLeft, copyRect.fTop);
114 return true;
bsalomon@google.com26e18b52013-03-29 19:22:36 +0000115}
116
bsalomona73239a2015-04-28 13:35:17 -0700117void GrDrawTarget::flush() {
118 if (fFlushing) {
119 return;
120 }
121 fFlushing = true;
122
bsalomon512be532015-09-10 10:42:55 -0700123 GrBatchFlushState flushState(fGpu, fResourceProvider, fLastFlushToken);
124
125 // Loop over all batches and generate geometry
126 for (int i = 0; i < fBatches.count(); ++i) {
127 fBatches[i]->prepare(&flushState);
128 }
129
130 // Upload all data to the GPU
131 flushState.preIssueDraws();
132
133 // Draw all the generated geometry.
134 for (int i = 0; i < fBatches.count(); ++i) {
135 fBatches[i]->draw(&flushState);
136 }
137
138 fLastFlushToken = flushState.lastFlushedToken();
bsalomona73239a2015-04-28 13:35:17 -0700139
bsalomona73239a2015-04-28 13:35:17 -0700140 fFlushing = false;
141 this->reset();
142}
143
bsalomon512be532015-09-10 10:42:55 -0700144void GrDrawTarget::reset() {
145 fBatches.reset();
146}
147
bsalomonabd30f52015-08-13 13:34:48 -0700148void GrDrawTarget::drawBatch(const GrPipelineBuilder& pipelineBuilder, GrDrawBatch* batch) {
joshualitt4d8da812015-01-28 12:53:54 -0800149 // Setup clip
150 GrScissorState scissorState;
joshualitt4421a4c2015-07-13 09:36:41 -0700151 GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps;
joshualitt4d8da812015-01-28 12:53:54 -0800152 GrPipelineBuilder::AutoRestoreStencil ars;
joshualitt4421a4c2015-07-13 09:36:41 -0700153 if (!this->setupClip(pipelineBuilder, &arfps, &ars, &scissorState, &batch->bounds())) {
joshualitt4d8da812015-01-28 12:53:54 -0800154 return;
155 }
156
joshualitt99c7c072015-05-01 13:43:30 -0700157 // Batch bounds are tight, so for dev copies
158 // TODO move this into setupDstReadIfNecessary when paths are in batch
159 SkRect bounds = batch->bounds();
160 bounds.outset(0.5f, 0.5f);
161
bsalomona387a112015-08-11 14:47:42 -0700162 GrDrawTarget::PipelineInfo pipelineInfo(&pipelineBuilder, &scissorState, batch, &bounds,
joshualitt99c7c072015-05-01 13:43:30 -0700163 this);
bsalomonadd79ef2015-08-19 13:26:49 -0700164
bsalomona387a112015-08-11 14:47:42 -0700165 if (!pipelineInfo.valid()) {
egdaniele36914c2015-02-13 09:00:33 -0800166 return;
167 }
bsalomona387a112015-08-11 14:47:42 -0700168 if (!batch->installPipeline(pipelineInfo.pipelineCreateArgs())) {
169 return;
170 }
bsalomon512be532015-09-10 10:42:55 -0700171 this->recordBatch(batch);
joshualitt4d8da812015-01-28 12:53:54 -0800172}
173
joshualitt2c93efe2014-11-06 12:57:13 -0800174static const GrStencilSettings& winding_path_stencil_settings() {
175 GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
176 kIncClamp_StencilOp,
177 kIncClamp_StencilOp,
178 kAlwaysIfInClip_StencilFunc,
179 0xFFFF, 0xFFFF, 0xFFFF);
180 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
181}
182
183static const GrStencilSettings& even_odd_path_stencil_settings() {
184 GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
185 kInvert_StencilOp,
186 kInvert_StencilOp,
187 kAlwaysIfInClip_StencilFunc,
188 0xFFFF, 0xFFFF, 0xFFFF);
189 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
190}
191
192void GrDrawTarget::getPathStencilSettingsForFilltype(GrPathRendering::FillType fill,
egdaniel8dc7c3a2015-04-16 11:22:42 -0700193 const GrStencilAttachment* sb,
joshualitt2c93efe2014-11-06 12:57:13 -0800194 GrStencilSettings* outStencilSettings) {
195
196 switch (fill) {
197 default:
198 SkFAIL("Unexpected path fill.");
199 case GrPathRendering::kWinding_FillType:
200 *outStencilSettings = winding_path_stencil_settings();
201 break;
202 case GrPathRendering::kEvenOdd_FillType:
203 *outStencilSettings = even_odd_path_stencil_settings();
204 break;
205 }
joshualitt9853cce2014-11-17 14:22:48 -0800206 this->clipMaskManager()->adjustPathStencilParams(sb, outStencilSettings);
joshualitt2c93efe2014-11-06 12:57:13 -0800207}
208
joshualitt1c735482015-07-13 08:08:25 -0700209void GrDrawTarget::stencilPath(const GrPipelineBuilder& pipelineBuilder,
joshualittf2384692015-09-10 11:00:51 -0700210 const SkMatrix& viewMatrix,
joshualitt9853cce2014-11-17 14:22:48 -0800211 const GrPath* path,
212 GrPathRendering::FillType fill) {
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000213 // TODO: extract portions of checkDraw that are relevant to path stenciling.
bsalomon49f085d2014-09-05 13:34:00 -0700214 SkASSERT(path);
jvanverthe9c0fc62015-04-29 11:18:05 -0700215 SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
joshualitt2c93efe2014-11-06 12:57:13 -0800216
217 // Setup clip
bsalomon3e791242014-12-17 13:43:13 -0800218 GrScissorState scissorState;
joshualitt4421a4c2015-07-13 09:36:41 -0700219 GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps;
egdaniel8dd688b2015-01-22 10:16:09 -0800220 GrPipelineBuilder::AutoRestoreStencil ars;
halcanary96fcdcc2015-08-27 07:41:13 -0700221 if (!this->setupClip(pipelineBuilder, &arfps, &ars, &scissorState, nullptr)) {
joshualitt2c93efe2014-11-06 12:57:13 -0800222 return;
223 }
224
225 // set stencil settings for path
226 GrStencilSettings stencilSettings;
joshualitt1c735482015-07-13 08:08:25 -0700227 GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
egdaniel8dc7c3a2015-04-16 11:22:42 -0700228 GrStencilAttachment* sb = rt->renderTargetPriv().attachStencilAttachment();
bsalomon6bc1b5f2015-02-23 09:06:38 -0800229 this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings);
joshualitt2c93efe2014-11-06 12:57:13 -0800230
joshualittf2384692015-09-10 11:00:51 -0700231 GrBatch* batch = GrStencilPathBatch::Create(viewMatrix,
bsalomona44919e2015-08-18 13:28:19 -0700232 pipelineBuilder.isHWAntialias(),
233 stencilSettings, scissorState,
234 pipelineBuilder.getRenderTarget(),
235 path);
bsalomon512be532015-09-10 10:42:55 -0700236 this->recordBatch(batch);
bsalomona44919e2015-08-18 13:28:19 -0700237 batch->unref();
bsalomon@google.com64aef2b2012-06-11 15:36:13 +0000238}
239
joshualitt1c735482015-07-13 08:08:25 -0700240void GrDrawTarget::drawPath(const GrPipelineBuilder& pipelineBuilder,
joshualittf2384692015-09-10 11:00:51 -0700241 const SkMatrix& viewMatrix,
242 GrColor color,
joshualitt9853cce2014-11-17 14:22:48 -0800243 const GrPath* path,
244 GrPathRendering::FillType fill) {
bsalomon49f085d2014-09-05 13:34:00 -0700245 SkASSERT(path);
jvanverthe9c0fc62015-04-29 11:18:05 -0700246 SkASSERT(this->caps()->shaderCaps()->pathRenderingSupport());
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000247
joshualittf2384692015-09-10 11:00:51 -0700248 GrDrawPathBatchBase* batch = GrDrawPathBatch::Create(viewMatrix, color, path);
bsalomon1fcc01c2015-09-09 09:48:06 -0700249 this->drawPathBatch(pipelineBuilder, batch, fill);
250 batch->unref();
251}
commit-bot@chromium.orgc4dc0ad2013-10-09 14:11:33 +0000252
bsalomon1fcc01c2015-09-09 09:48:06 -0700253void GrDrawTarget::drawPathsFromRange(const GrPipelineBuilder& pipelineBuilder,
joshualittf2384692015-09-10 11:00:51 -0700254 const SkMatrix& viewMatrix,
255 const SkMatrix& localMatrix,
256 GrColor color,
bsalomon1fcc01c2015-09-09 09:48:06 -0700257 GrPathRangeDraw* draw,
258 GrPathRendering::FillType fill) {
joshualittf2384692015-09-10 11:00:51 -0700259 GrDrawPathBatchBase* batch = GrDrawPathRangeBatch::Create(viewMatrix, localMatrix, color, draw);
bsalomon1fcc01c2015-09-09 09:48:06 -0700260 this->drawPathBatch(pipelineBuilder, batch, fill);
261 batch->unref();
262}
263
264void GrDrawTarget::drawPathBatch(const GrPipelineBuilder& pipelineBuilder,
265 GrDrawPathBatchBase* batch,
266 GrPathRendering::FillType fill) {
bsalomonadd79ef2015-08-19 13:26:49 -0700267 // This looks like drawBatch() but there is an added wrinkle that stencil settings get inserted
268 // after setupClip() but before onDrawBatch(). TODO: Figure out a better model for handling
269 // stencil settings WRT interactions between pipeline(builder), clipmaskmanager, and batches.
270
bsalomon3e791242014-12-17 13:43:13 -0800271 GrScissorState scissorState;
joshualitt4421a4c2015-07-13 09:36:41 -0700272 GrPipelineBuilder::AutoRestoreFragmentProcessorState arfps;
egdaniel8dd688b2015-01-22 10:16:09 -0800273 GrPipelineBuilder::AutoRestoreStencil ars;
bsalomonadd79ef2015-08-19 13:26:49 -0700274 if (!this->setupClip(pipelineBuilder, &arfps, &ars, &scissorState, &batch->bounds())) {
275 return;
joshualitt2c93efe2014-11-06 12:57:13 -0800276 }
277
bsalomonadd79ef2015-08-19 13:26:49 -0700278 // Ensure the render target has a stencil buffer and get the stencil settings.
joshualitt2c93efe2014-11-06 12:57:13 -0800279 GrStencilSettings stencilSettings;
joshualitt1c735482015-07-13 08:08:25 -0700280 GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
egdaniel8dc7c3a2015-04-16 11:22:42 -0700281 GrStencilAttachment* sb = rt->renderTargetPriv().attachStencilAttachment();
bsalomon6bc1b5f2015-02-23 09:06:38 -0800282 this->getPathStencilSettingsForFilltype(fill, sb, &stencilSettings);
bsalomonadd79ef2015-08-19 13:26:49 -0700283 batch->setStencilSettings(stencilSettings);
joshualitt2c93efe2014-11-06 12:57:13 -0800284
bsalomon1fcc01c2015-09-09 09:48:06 -0700285 GrDrawTarget::PipelineInfo pipelineInfo(&pipelineBuilder, &scissorState, batch,
286 &batch->bounds(), this);
bsalomonadd79ef2015-08-19 13:26:49 -0700287
bsalomona387a112015-08-11 14:47:42 -0700288 if (!pipelineInfo.valid()) {
egdaniele36914c2015-02-13 09:00:33 -0800289 return;
290 }
bsalomonadd79ef2015-08-19 13:26:49 -0700291 if (!batch->installPipeline(pipelineInfo.pipelineCreateArgs())) {
292 return;
293 }
egdaniele36914c2015-02-13 09:00:33 -0800294
bsalomon512be532015-09-10 10:42:55 -0700295 this->recordBatch(batch);
commit-bot@chromium.org9b62aa12014-03-25 11:59:40 +0000296}
297
joshualittd2b23e02015-08-21 10:53:34 -0700298void GrDrawTarget::drawNonAARect(const GrPipelineBuilder& pipelineBuilder,
joshualitt1c735482015-07-13 08:08:25 -0700299 GrColor color,
300 const SkMatrix& viewMatrix,
joshualittb6b513b2015-08-21 10:25:18 -0700301 const SkRect& rect) {
joshualittd2b23e02015-08-21 10:53:34 -0700302 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, viewMatrix, rect,
303 nullptr, nullptr));
joshualittad17cfc2015-05-05 10:45:57 -0700304 this->drawBatch(pipelineBuilder, batch);
305}
306
joshualittd2b23e02015-08-21 10:53:34 -0700307void GrDrawTarget::drawNonAARect(const GrPipelineBuilder& pipelineBuilder,
joshualittb6b513b2015-08-21 10:25:18 -0700308 GrColor color,
309 const SkMatrix& viewMatrix,
310 const SkRect& rect,
311 const SkMatrix& localMatrix) {
joshualittd2b23e02015-08-21 10:53:34 -0700312 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, viewMatrix, rect,
313 nullptr, &localMatrix));
joshualittb6b513b2015-08-21 10:25:18 -0700314 this->drawBatch(pipelineBuilder, batch);
315}
316
joshualittd2b23e02015-08-21 10:53:34 -0700317void GrDrawTarget::drawNonAARect(const GrPipelineBuilder& pipelineBuilder,
joshualittb6b513b2015-08-21 10:25:18 -0700318 GrColor color,
319 const SkMatrix& viewMatrix,
320 const SkRect& rect,
321 const SkRect& localRect) {
joshualittd2b23e02015-08-21 10:53:34 -0700322 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, viewMatrix, rect,
323 &localRect, nullptr));
joshualittb6b513b2015-08-21 10:25:18 -0700324 this->drawBatch(pipelineBuilder, batch);
325}
326
327
joshualitt1c735482015-07-13 08:08:25 -0700328void GrDrawTarget::drawAARect(const GrPipelineBuilder& pipelineBuilder,
robertphillipsea461502015-05-26 11:38:03 -0700329 GrColor color,
330 const SkMatrix& viewMatrix,
331 const SkRect& rect,
332 const SkRect& devRect) {
joshualittd2b23e02015-08-21 10:53:34 -0700333 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateAAFill(color, viewMatrix, rect,
bsalomonabd30f52015-08-13 13:34:48 -0700334 devRect));
joshualitt14205b12015-08-10 11:40:56 -0700335 this->drawBatch(pipelineBuilder, batch);
robertphillipsea461502015-05-26 11:38:03 -0700336}
337
joshualitt9853cce2014-11-17 14:22:48 -0800338void GrDrawTarget::clear(const SkIRect* rect,
339 GrColor color,
340 bool canIgnoreRect,
bsalomon63b21962014-11-05 07:05:34 -0800341 GrRenderTarget* renderTarget) {
egdaniel51c8d402015-08-06 10:54:13 -0700342 SkIRect rtRect = SkIRect::MakeWH(renderTarget->width(), renderTarget->height());
343 SkIRect clippedRect;
344 if (!rect ||
345 (canIgnoreRect && this->caps()->fullClearIsFree()) ||
346 rect->contains(rtRect)) {
347 rect = &rtRect;
348 } else {
349 clippedRect = *rect;
350 if (!clippedRect.intersect(rtRect)) {
351 return;
352 }
353 rect = &clippedRect;
354 }
355
bsalomon63b21962014-11-05 07:05:34 -0800356 if (fCaps->useDrawInsteadOfClear()) {
357 // This works around a driver bug with clear by drawing a rect instead.
358 // The driver will ignore a clear if it is the only thing rendered to a
359 // target before the target is read.
egdaniel51c8d402015-08-06 10:54:13 -0700360 if (rect == &rtRect) {
bsalomon63b21962014-11-05 07:05:34 -0800361 this->discard(renderTarget);
362 }
bsalomon63b21962014-11-05 07:05:34 -0800363
egdaniel8dd688b2015-01-22 10:16:09 -0800364 GrPipelineBuilder pipelineBuilder;
365 pipelineBuilder.setRenderTarget(renderTarget);
joshualitt9853cce2014-11-17 14:22:48 -0800366
joshualittd2b23e02015-08-21 10:53:34 -0700367 this->drawNonAARect(pipelineBuilder, color, SkMatrix::I(), *rect);
bsalomon53469832015-08-18 09:20:09 -0700368 } else {
halcanary385fe4d2015-08-26 13:07:48 -0700369 GrBatch* batch = new GrClearBatch(*rect, color, renderTarget);
bsalomon512be532015-09-10 10:42:55 -0700370 this->recordBatch(batch);
bsalomon53469832015-08-18 09:20:09 -0700371 batch->unref();
372 }
373}
374
375void GrDrawTarget::discard(GrRenderTarget* renderTarget) {
376 if (this->caps()->discardRenderTargetSupport()) {
halcanary385fe4d2015-08-26 13:07:48 -0700377 GrBatch* batch = new GrDiscardBatch(renderTarget);
bsalomon512be532015-09-10 10:42:55 -0700378 this->recordBatch(batch);
bsalomon53469832015-08-18 09:20:09 -0700379 batch->unref();
bsalomon63b21962014-11-05 07:05:34 -0800380 }
381}
382
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000383////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000384
bsalomon6df86402015-06-01 10:41:49 -0700385void GrDrawTarget::copySurface(GrSurface* dst,
bsalomon@google.com116ad842013-04-09 15:38:19 +0000386 GrSurface* src,
387 const SkIRect& srcRect,
388 const SkIPoint& dstPoint) {
bsalomon872062c2015-08-18 12:12:35 -0700389 GrBatch* batch = GrCopySurfaceBatch::Create(dst, src, srcRect, dstPoint);
390 if (batch) {
bsalomon512be532015-09-10 10:42:55 -0700391 this->recordBatch(batch);
bsalomon872062c2015-08-18 12:12:35 -0700392 batch->unref();
bsalomon@google.come4617bf2013-04-03 14:56:40 +0000393 }
bsalomon@google.comeb851172013-04-15 13:51:00 +0000394}
395
bsalomon512be532015-09-10 10:42:55 -0700396template <class Left, class Right> static bool intersect(const Left& a, const Right& b) {
397 SkASSERT(a.fLeft <= a.fRight && a.fTop <= a.fBottom &&
398 b.fLeft <= b.fRight && b.fTop <= b.fBottom);
399 return a.fLeft < b.fRight && b.fLeft < a.fRight && a.fTop < b.fBottom && b.fTop < a.fBottom;
400}
401
402void GrDrawTarget::recordBatch(GrBatch* batch) {
403 // Check if there is a Batch Draw we can batch with by linearly searching back until we either
404 // 1) check every draw
405 // 2) intersect with something
406 // 3) find a 'blocker'
407 // Experimentally we have found that most batching occurs within the first 10 comparisons.
408 static const int kMaxLookback = 10;
409
410 GrBATCH_INFO("Re-Recording (%s, B%u)\n"
411 "\tBounds (%f, %f, %f, %f)\n",
412 batch->name(),
413 batch->uniqueID(),
414 batch->bounds().fLeft, batch->bounds().fRight,
415 batch->bounds().fTop, batch->bounds().fBottom);
416 GrBATCH_INFO(SkTabString(batch->dumpInfo(), 1).c_str());
417 GrBATCH_INFO("\tOutcome:\n");
418 int maxCandidates = SkTMin(kMaxLookback, fBatches.count());
419 if (maxCandidates) {
420 int i = 0;
421 while (true) {
422 GrBatch* candidate = fBatches.fromBack(i);
423 // We cannot continue to search backwards if the render target changes
424 if (candidate->renderTargetUniqueID() != batch->renderTargetUniqueID()) {
425 GrBATCH_INFO("\t\tBreaking because of (%s, B%u) Rendertarget\n",
426 candidate->name(), candidate->uniqueID());
427 break;
428 }
429 if (candidate->combineIfPossible(batch, *this->caps())) {
430 GrBATCH_INFO("\t\tCombining with (%s, B%u)\n", candidate->name(),
431 candidate->uniqueID());
432 return;
433 }
434 // Stop going backwards if we would cause a painter's order violation.
435 if (intersect(candidate->bounds(), batch->bounds())) {
436 GrBATCH_INFO("\t\tIntersects with (%s, B%u)\n", candidate->name(),
437 candidate->uniqueID());
438 break;
439 }
440 ++i;
441 if (i == maxCandidates) {
442 GrBATCH_INFO("\t\tReached max lookback or beginning of batch array %d\n", i);
443 break;
444 }
445 }
446 } else {
447 GrBATCH_INFO("\t\tFirstBatch\n");
448 }
449 fBatches.push_back().reset(SkRef(batch));
450}
451
egdaniele36914c2015-02-13 09:00:33 -0800452///////////////////////////////////////////////////////////////////////////////
453
bsalomona387a112015-08-11 14:47:42 -0700454GrDrawTarget::PipelineInfo::PipelineInfo(const GrPipelineBuilder* pipelineBuilder,
455 const GrScissorState* scissor,
bsalomonabd30f52015-08-13 13:34:48 -0700456 const GrDrawBatch* batch,
egdaniele36914c2015-02-13 09:00:33 -0800457 const SkRect* devBounds,
bsalomona387a112015-08-11 14:47:42 -0700458 GrDrawTarget* target) {
459 fArgs.fPipelineBuilder = pipelineBuilder;
460 fArgs.fCaps = target->caps();
461 fArgs.fScissor = scissor;
462 fArgs.fColorPOI = fArgs.fPipelineBuilder->colorProcInfo(batch);
463 fArgs.fCoveragePOI = fArgs.fPipelineBuilder->coverageProcInfo(batch);
464 if (!target->setupDstReadIfNecessary(*fArgs.fPipelineBuilder, fArgs.fColorPOI,
465 fArgs.fCoveragePOI, &fArgs.fDstTexture, devBounds)) {
halcanary96fcdcc2015-08-27 07:41:13 -0700466 fArgs.fPipelineBuilder = nullptr;
egdaniele36914c2015-02-13 09:00:33 -0800467 }
468}
469
bsalomon@google.combcce8922013-03-25 15:38:39 +0000470///////////////////////////////////////////////////////////////////////////////
bsalomon4061b122015-05-29 10:26:19 -0700471GrClipTarget::GrClipTarget(GrContext* context)
472 : INHERITED(context->getGpu(), context->resourceProvider())
473 , fContext(context) {
halcanary385fe4d2015-08-26 13:07:48 -0700474 fClipMaskManager.reset(new GrClipMaskManager(this));
bsalomonedd77a12015-05-29 09:45:57 -0700475}
476
bsalomon@google.combcce8922013-03-25 15:38:39 +0000477
joshualitt1c735482015-07-13 08:08:25 -0700478bool GrClipTarget::setupClip(const GrPipelineBuilder& pipelineBuilder,
joshualitt4421a4c2015-07-13 09:36:41 -0700479 GrPipelineBuilder::AutoRestoreFragmentProcessorState* arfps,
egdaniel8dd688b2015-01-22 10:16:09 -0800480 GrPipelineBuilder::AutoRestoreStencil* ars,
joshualitt8059eb92014-12-29 15:10:07 -0800481 GrScissorState* scissorState,
482 const SkRect* devBounds) {
joshualitt1c735482015-07-13 08:08:25 -0700483 return fClipMaskManager->setupClipping(pipelineBuilder,
joshualitt4421a4c2015-07-13 09:36:41 -0700484 arfps,
joshualitt5e6ba212015-07-13 07:35:05 -0700485 ars,
joshualitt5e6ba212015-07-13 07:35:05 -0700486 scissorState,
487 devBounds);
joshualitt2c93efe2014-11-06 12:57:13 -0800488}
bsalomonedd77a12015-05-29 09:45:57 -0700489
490void GrClipTarget::purgeResources() {
491 // The clip mask manager can rebuild all its clip masks so just
492 // get rid of them all.
493 fClipMaskManager->purgeResources();
494};
bsalomon5ea03632015-08-18 10:33:30 -0700495
496void GrClipTarget::clearStencilClip(const SkIRect& rect, bool insideClip, GrRenderTarget* rt) {
halcanary385fe4d2015-08-26 13:07:48 -0700497 GrBatch* batch = new GrClearStencilClipBatch(rect, insideClip, rt);
bsalomon512be532015-09-10 10:42:55 -0700498 this->recordBatch(batch);
bsalomon5ea03632015-08-18 10:33:30 -0700499 batch->unref();
500}