blob: a003c121d1a063115454889953a11e045cc27337 [file] [log] [blame]
reed@google.comac10a2d2010-12-22 21:39:39 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2010 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
reed@google.comac10a2d2010-12-22 21:39:39 +00006 */
7
Robert Phillipsf2361d22016-10-25 14:20:06 -04008#include "GrRenderTargetOpList.h"
joshualitt086cee12016-01-12 06:45:24 -08009#include "GrAuditTrail.h"
bsalomoneb1cb5c2015-05-22 08:01:09 -070010#include "GrCaps.h"
bsalomon4061b122015-05-29 10:26:19 -070011#include "GrGpu.h"
egdaniel9cb63402016-06-23 08:37:05 -070012#include "GrGpuCommandBuffer.h"
bsalomon@google.com8f9cbd62011-12-09 15:55:34 +000013#include "GrRenderTarget.h"
Brian Salomon467921e2017-03-06 16:17:12 -050014#include "GrRenderTargetContext.h"
bsalomon4061b122015-05-29 10:26:19 -070015#include "GrResourceProvider.h"
Brian Salomon89527432016-12-16 09:52:16 -050016#include "ops/GrClearOp.h"
17#include "ops/GrClearStencilClipOp.h"
18#include "ops/GrCopySurfaceOp.h"
19#include "ops/GrDiscardOp.h"
csmartdaltona7f29642016-07-07 08:49:11 -070020#include "instanced/InstancedRendering.h"
21
Robert Phillipsf2361d22016-10-25 14:20:06 -040022using gr_instanced::InstancedRendering;
23
reed@google.comac10a2d2010-12-22 21:39:39 +000024////////////////////////////////////////////////////////////////////////////////
25
Brian Salomon09d994e2016-12-21 11:14:46 -050026// Experimentally we have found that most combining occurs within the first 10 comparisons.
27static const int kDefaultMaxOpLookback = 10;
28static const int kDefaultMaxOpLookahead = 10;
bsalomon489147c2015-12-14 12:13:09 -080029
Robert Phillipsc7635fa2016-10-28 13:25:24 -040030GrRenderTargetOpList::GrRenderTargetOpList(GrRenderTargetProxy* rtp, GrGpu* gpu,
Robert Phillipsf2361d22016-10-25 14:20:06 -040031 GrResourceProvider* resourceProvider,
32 GrAuditTrail* auditTrail, const Options& options)
Brian Salomon54d212e2017-03-21 14:22:38 -040033 : INHERITED(rtp, auditTrail)
34 , fGpu(SkRef(gpu))
35 , fResourceProvider(resourceProvider)
36 , fLastClipStackGenID(SK_InvalidUniqueID)
37 , fClipAllocator(fClipAllocatorStorage, sizeof(fClipAllocatorStorage),
38 sizeof(fClipAllocatorStorage)) {
robertphillips4beb5c12015-10-20 07:50:00 -070039
Brian Salomon09d994e2016-12-21 11:14:46 -050040 fMaxOpLookback = (options.fMaxOpCombineLookback < 0) ? kDefaultMaxOpLookback
41 : options.fMaxOpCombineLookback;
42 fMaxOpLookahead = (options.fMaxOpCombineLookahead < 0) ? kDefaultMaxOpLookahead
43 : options.fMaxOpCombineLookahead;
bsalomon6dea83f2015-12-03 12:58:06 -080044
csmartdaltone0d36292016-07-29 08:14:20 -070045 if (GrCaps::InstancedSupport::kNone != this->caps()->instancedSupport()) {
46 fInstancedRendering.reset(fGpu->createInstancedRendering());
47 }
bsalomon4061b122015-05-29 10:26:19 -070048}
49
Robert Phillipsf2361d22016-10-25 14:20:06 -040050GrRenderTargetOpList::~GrRenderTargetOpList() {
bsalomon4061b122015-05-29 10:26:19 -070051 fGpu->unref();
bsalomon@google.com25fb21f2011-06-21 18:17:25 +000052}
53
54////////////////////////////////////////////////////////////////////////////////
55
robertphillips4beb5c12015-10-20 07:50:00 -070056#ifdef SK_DEBUG
Robert Phillipsf2361d22016-10-25 14:20:06 -040057void GrRenderTargetOpList::dump() const {
58 INHERITED::dump();
59
Brian Salomon1e41f4a2016-12-07 15:05:04 -050060 SkDebugf("ops (%d):\n", fRecordedOps.count());
61 for (int i = 0; i < fRecordedOps.count(); ++i) {
robertphillips4beb5c12015-10-20 07:50:00 -070062 SkDebugf("*******************************\n");
Brian Salomon1e41f4a2016-12-07 15:05:04 -050063 if (!fRecordedOps[i].fOp) {
bsalomonaecc0182016-03-07 11:50:44 -080064 SkDebugf("%d: <combined forward>\n", i);
65 } else {
Brian Salomon1e41f4a2016-12-07 15:05:04 -050066 SkDebugf("%d: %s\n", i, fRecordedOps[i].fOp->name());
67 SkString str = fRecordedOps[i].fOp->dumpInfo();
bsalomonaecc0182016-03-07 11:50:44 -080068 SkDebugf("%s\n", str.c_str());
Brian Salomon9e50f7b2017-03-06 12:02:34 -050069 const SkRect& bounds = fRecordedOps[i].fOp->bounds();
70 SkDebugf("ClippedBounds: [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n", bounds.fLeft,
71 bounds.fTop, bounds.fRight, bounds.fBottom);
bsalomonaecc0182016-03-07 11:50:44 -080072 }
robertphillips4beb5c12015-10-20 07:50:00 -070073 }
74}
Robert Phillipseb35f4d2017-03-21 07:56:47 -040075
76void GrRenderTargetOpList::validateTargetsSingleRenderTarget() const {
77 GrRenderTarget* rt = nullptr;
78 for (int i = 0; i < fRecordedOps.count(); ++i) {
79 if (!fRecordedOps[i].fOp) {
80 continue; // combined forward
81 }
82
83 if (!rt) {
84 rt = fRecordedOps[i].fRenderTarget.get();
85 } else {
86 SkASSERT(fRecordedOps[i].fRenderTarget.get() == rt);
87 }
88 }
89}
robertphillips4beb5c12015-10-20 07:50:00 -070090#endif
91
Brian Salomon742e31d2016-12-07 17:06:19 -050092void GrRenderTargetOpList::prepareOps(GrOpFlushState* flushState) {
Robert Phillipseb35f4d2017-03-21 07:56:47 -040093 // MDB TODO: add SkASSERT(this->isClosed());
robertphillipsa106c622015-10-16 09:07:06 -070094
Brian Salomon1e41f4a2016-12-07 15:05:04 -050095 // Loop over the ops that haven't yet been prepared.
96 for (int i = 0; i < fRecordedOps.count(); ++i) {
97 if (fRecordedOps[i].fOp) {
Brian Salomon54d212e2017-03-21 14:22:38 -040098 GrOpFlushState::DrawOpArgs opArgs;
99 if (fRecordedOps[i].fRenderTarget) {
100 opArgs = {
101 fRecordedOps[i].fRenderTarget.get(),
102 fRecordedOps[i].fAppliedClip,
103 fRecordedOps[i].fDstTexture
104 };
105 }
106 flushState->setDrawOpArgs(&opArgs);
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500107 fRecordedOps[i].fOp->prepare(flushState);
Brian Salomon54d212e2017-03-21 14:22:38 -0400108 flushState->setDrawOpArgs(nullptr);
bsalomonaecc0182016-03-07 11:50:44 -0800109 }
bsalomon512be532015-09-10 10:42:55 -0700110 }
csmartdaltona7f29642016-07-07 08:49:11 -0700111
112 if (fInstancedRendering) {
113 fInstancedRendering->beginFlush(flushState->resourceProvider());
114 }
robertphillipsa13e2022015-11-11 12:01:09 -0800115}
bsalomon512be532015-09-10 10:42:55 -0700116
Brian Salomon25a88092016-12-01 09:36:50 -0500117// TODO: this is where GrOp::renderTarget is used (which is fine since it
Robert Phillips294870f2016-11-11 12:38:40 -0500118// is at flush time). However, we need to store the RenderTargetProxy in the
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500119// Ops and instantiate them here.
Brian Salomon742e31d2016-12-07 17:06:19 -0500120bool GrRenderTargetOpList::executeOps(GrOpFlushState* flushState) {
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500121 if (0 == fRecordedOps.count()) {
bsalomondc438982016-08-31 11:53:49 -0700122 return false;
egdanielb4021cf2016-07-28 08:53:07 -0700123 }
bsalomon512be532015-09-10 10:42:55 -0700124 // Draw all the generated geometry.
bsalomon6dea83f2015-12-03 12:58:06 -0800125 SkRandom random;
Brian Salomoncdcc33f2017-02-21 09:49:20 -0500126 const GrRenderTarget* currentRenderTarget = nullptr;
Ben Wagner145dbcd2016-11-03 14:40:50 -0400127 std::unique_ptr<GrGpuCommandBuffer> commandBuffer;
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500128 for (int i = 0; i < fRecordedOps.count(); ++i) {
129 if (!fRecordedOps[i].fOp) {
bsalomonaecc0182016-03-07 11:50:44 -0800130 continue;
131 }
Brian Salomoncdcc33f2017-02-21 09:49:20 -0500132 if (fRecordedOps[i].fRenderTarget.get() != currentRenderTarget) {
egdaniel9cb63402016-06-23 08:37:05 -0700133 if (commandBuffer) {
134 commandBuffer->end();
Greg Daniel36a77ee2016-10-18 10:33:25 -0400135 commandBuffer->submit();
egdaniel9cb63402016-06-23 08:37:05 -0700136 commandBuffer.reset();
137 }
Brian Salomoncdcc33f2017-02-21 09:49:20 -0500138 currentRenderTarget = fRecordedOps[i].fRenderTarget.get();
139 if (currentRenderTarget) {
egdaniel9cb63402016-06-23 08:37:05 -0700140 static const GrGpuCommandBuffer::LoadAndStoreInfo kBasicLoadStoreInfo
141 { GrGpuCommandBuffer::LoadOp::kLoad,GrGpuCommandBuffer::StoreOp::kStore,
142 GrColor_ILLEGAL };
Brian Salomonc293a292016-11-30 13:38:32 -0500143 commandBuffer.reset(fGpu->createCommandBuffer(kBasicLoadStoreInfo, // Color
egdaniel9cb63402016-06-23 08:37:05 -0700144 kBasicLoadStoreInfo)); // Stencil
145 }
Ben Wagner145dbcd2016-11-03 14:40:50 -0400146 flushState->setCommandBuffer(commandBuffer.get());
egdaniel9cb63402016-06-23 08:37:05 -0700147 }
Brian Salomon54d212e2017-03-21 14:22:38 -0400148 GrOpFlushState::DrawOpArgs opArgs;
149 if (fRecordedOps[i].fRenderTarget) {
150 opArgs = {
151 fRecordedOps[i].fRenderTarget.get(),
152 fRecordedOps[i].fAppliedClip,
153 fRecordedOps[i].fDstTexture
154 };
155 flushState->setDrawOpArgs(&opArgs);
156 }
Brian Salomon9e50f7b2017-03-06 12:02:34 -0500157 fRecordedOps[i].fOp->execute(flushState);
Brian Salomon54d212e2017-03-21 14:22:38 -0400158 flushState->setDrawOpArgs(nullptr);
bsalomon512be532015-09-10 10:42:55 -0700159 }
egdaniel9cb63402016-06-23 08:37:05 -0700160 if (commandBuffer) {
161 commandBuffer->end();
Greg Daniel36a77ee2016-10-18 10:33:25 -0400162 commandBuffer->submit();
egdaniel9cb63402016-06-23 08:37:05 -0700163 flushState->setCommandBuffer(nullptr);
164 }
ethannicholas22793252016-01-30 09:59:10 -0800165
Robert Phillipsf2361d22016-10-25 14:20:06 -0400166 fGpu->finishOpList();
bsalomondc438982016-08-31 11:53:49 -0700167 return true;
bsalomona73239a2015-04-28 13:35:17 -0700168}
169
Robert Phillipsf2361d22016-10-25 14:20:06 -0400170void GrRenderTargetOpList::reset() {
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500171 fLastFullClearOp = nullptr;
Robert Phillipsf7a72612017-03-31 10:03:45 -0400172 fLastFullClearResourceID.makeInvalid();
173 fLastFullClearProxyID.makeInvalid();
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500174 fRecordedOps.reset();
csmartdaltona7f29642016-07-07 08:49:11 -0700175 if (fInstancedRendering) {
176 fInstancedRendering->endFlush();
177 }
bsalomon512be532015-09-10 10:42:55 -0700178}
179
Robert Phillipsf2361d22016-10-25 14:20:06 -0400180void GrRenderTargetOpList::abandonGpuResources() {
Brian Salomon467921e2017-03-06 16:17:12 -0500181 if (GrCaps::InstancedSupport::kNone != this->caps()->instancedSupport()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400182 InstancedRendering* ir = this->instancedRendering();
183 ir->resetGpuResources(InstancedRendering::ResetType::kAbandon);
184 }
185}
186
187void GrRenderTargetOpList::freeGpuResources() {
Brian Salomon467921e2017-03-06 16:17:12 -0500188 if (GrCaps::InstancedSupport::kNone != this->caps()->instancedSupport()) {
Robert Phillipsf2361d22016-10-25 14:20:06 -0400189 InstancedRendering* ir = this->instancedRendering();
190 ir->resetGpuResources(InstancedRendering::ResetType::kDestroy);
191 }
192}
193
Brian Salomon69868af2016-12-22 15:42:51 -0500194void GrRenderTargetOpList::fullClear(GrRenderTargetContext* renderTargetContext, GrColor color) {
Robert Phillipsf7a72612017-03-31 10:03:45 -0400195 // MDB TODO: remove this. Right now we need the renderTargetContext for the
196 // accessRenderTarget call. This method should just take the renderTargetProxy.
Brian Salomon69868af2016-12-22 15:42:51 -0500197 GrRenderTarget* renderTarget = renderTargetContext->accessRenderTarget();
Robert Phillipsf7a72612017-03-31 10:03:45 -0400198 if (!renderTarget) {
199 return;
200 }
201
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500202 // Currently this just inserts or updates the last clear op. However, once in MDB this can
203 // remove all the previously recorded ops and change the load op to clear with supplied
bsalomonfd8d0132016-08-11 11:25:33 -0700204 // color.
Robert Phillips294870f2016-11-11 12:38:40 -0500205 // TODO: this needs to be updated to use GrSurfaceProxy::UniqueID
Robert Phillipsf7a72612017-03-31 10:03:45 -0400206 SkASSERT((fLastFullClearResourceID == renderTarget->uniqueID()) ==
207 (fLastFullClearProxyID == renderTargetContext->asRenderTargetProxy()->uniqueID()));
208 if (fLastFullClearResourceID == renderTarget->uniqueID()) {
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500209 // As currently implemented, fLastFullClearOp should be the last op because we would
210 // have cleared it when another op was recorded.
211 SkASSERT(fRecordedOps.back().fOp.get() == fLastFullClearOp);
212 fLastFullClearOp->setColor(color);
bsalomonfd8d0132016-08-11 11:25:33 -0700213 return;
214 }
Robert Phillipsf7a72612017-03-31 10:03:45 -0400215 std::unique_ptr<GrClearOp> op(GrClearOp::Make(GrFixedClip::Disabled(), color,
216 renderTargetContext));
217 if (!op) {
218 return;
219 }
Brian Salomon69868af2016-12-22 15:42:51 -0500220 if (GrOp* clearOp = this->recordOp(std::move(op), renderTargetContext)) {
Brian Salomon2790c522016-12-09 16:32:23 -0500221 // This is either the clear op we just created or another one that it combined with.
Brian Salomon7dae46a2016-12-14 16:21:37 -0500222 fLastFullClearOp = static_cast<GrClearOp*>(clearOp);
Robert Phillipsf7a72612017-03-31 10:03:45 -0400223 fLastFullClearResourceID = renderTarget->uniqueID();
224 fLastFullClearProxyID = renderTargetContext->asRenderTargetProxy()->uniqueID();
bsalomonfd8d0132016-08-11 11:25:33 -0700225 }
bsalomon9f129de2016-08-10 16:31:05 -0700226}
227
Brian Salomon69868af2016-12-22 15:42:51 -0500228void GrRenderTargetOpList::discard(GrRenderTargetContext* renderTargetContext) {
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500229 // Currently this just inserts a discard op. However, once in MDB this can remove all the
230 // previously recorded ops and change the load op to discard.
bsalomon53469832015-08-18 09:20:09 -0700231 if (this->caps()->discardRenderTargetSupport()) {
Brian Salomon69868af2016-12-22 15:42:51 -0500232 this->recordOp(GrDiscardOp::Make(renderTargetContext->accessRenderTarget()),
233 renderTargetContext);
bsalomon63b21962014-11-05 07:05:34 -0800234 }
235}
236
bsalomon@google.com25fb21f2011-06-21 18:17:25 +0000237////////////////////////////////////////////////////////////////////////////////
bsalomon@google.com86afc2a2011-02-16 16:12:19 +0000238
Robert Phillipsbf25d432017-04-07 10:08:53 -0400239bool GrRenderTargetOpList::copySurface(GrResourceProvider* resourceProvider,
240 GrSurfaceProxy* dst,
241 GrSurfaceProxy* src,
Robert Phillipsf2361d22016-10-25 14:20:06 -0400242 const SkIRect& srcRect,
243 const SkIPoint& dstPoint) {
Robert Phillipsbf25d432017-04-07 10:08:53 -0400244 std::unique_ptr<GrOp> op = GrCopySurfaceOp::Make(resourceProvider, dst, src, srcRect, dstPoint);
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500245 if (!op) {
bsalomonb8fea972016-02-16 07:34:17 -0800246 return false;
247 }
robertphillips498d7ac2015-10-30 10:11:30 -0700248#ifdef ENABLE_MDB
bsalomonb8fea972016-02-16 07:34:17 -0800249 this->addDependency(src);
robertphillips498d7ac2015-10-30 10:11:30 -0700250#endif
251
Brian Salomon69868af2016-12-22 15:42:51 -0500252 // Copy surface doesn't work through a GrGpuCommandBuffer. By passing nullptr for the context we
253 // force this to occur between command buffers and execute directly on GrGpu. This workaround
254 // goes away with MDB.
255 this->recordOp(std::move(op), nullptr);
bsalomonb8fea972016-02-16 07:34:17 -0800256 return true;
bsalomon@google.comeb851172013-04-15 13:51:00 +0000257}
258
bsalomon6cc90062016-07-08 11:31:22 -0700259static inline bool can_reorder(const SkRect& a, const SkRect& b) {
bsalomon88cf17d2016-07-08 06:40:56 -0700260 return a.fRight <= b.fLeft || a.fBottom <= b.fTop ||
261 b.fRight <= a.fLeft || b.fBottom <= a.fTop;
262}
263
Brian Salomon54d212e2017-03-21 14:22:38 -0400264bool GrRenderTargetOpList::combineIfPossible(const RecordedOp& a, GrOp* b,
265 const GrAppliedClip* bClip,
266 const DstTexture* bDstTexture) {
267 if (a.fAppliedClip) {
268 if (!bClip) {
269 return false;
270 }
271 if (*a.fAppliedClip != *bClip) {
272 return false;
273 }
274 } else if (bClip) {
275 return false;
276 }
277 if (bDstTexture) {
278 if (a.fDstTexture != *bDstTexture) {
279 return false;
280 }
281 } else if (a.fDstTexture.texture()) {
282 return false;
283 }
284 return a.fOp->combineIfPossible(b, *this->caps());
285}
286
Brian Salomonf8334782017-01-03 09:42:58 -0500287GrOp* GrRenderTargetOpList::recordOp(std::unique_ptr<GrOp> op,
Brian Salomon54d212e2017-03-21 14:22:38 -0400288 GrRenderTargetContext* renderTargetContext,
289 GrAppliedClip* clip,
290 const DstTexture* dstTexture) {
Brian Salomoncdcc33f2017-02-21 09:49:20 -0500291 GrRenderTarget* renderTarget =
292 renderTargetContext ? renderTargetContext->accessRenderTarget()
293 : nullptr;
Brian Salomon69868af2016-12-22 15:42:51 -0500294
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500295 // A closed GrOpList should never receive new/more ops
robertphillips6a186652015-10-20 07:37:58 -0700296 SkASSERT(!this->isClosed());
robertphillipsa106c622015-10-16 09:07:06 -0700297
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500298 // Check if there is an op we can combine with by linearly searching back until we either
299 // 1) check every op
bsalomon512be532015-09-10 10:42:55 -0700300 // 2) intersect with something
301 // 3) find a 'blocker'
Robert Phillipsf7a72612017-03-31 10:03:45 -0400302 GR_AUDIT_TRAIL_ADD_OP(fAuditTrail, op.get(), renderTarget->uniqueID(),
303 renderTargetContext->asRenderTargetProxy()->uniqueID());
Brian Salomon199fb872017-02-06 09:41:10 -0500304 GrOP_INFO("Recording (%s, B%u)\n"
Brian Salomon25a88092016-12-01 09:36:50 -0500305 "\tBounds LRTB (%f, %f, %f, %f)\n",
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500306 op->name(),
307 op->uniqueID(),
308 op->bounds().fLeft, op->bounds().fRight,
309 op->bounds().fTop, op->bounds().fBottom);
310 GrOP_INFO(SkTabString(op->dumpInfo(), 1).c_str());
Brian Salomon9e50f7b2017-03-06 12:02:34 -0500311 GrOP_INFO("\tClipped Bounds: [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n", op->bounds().fLeft,
312 op->bounds().fTop, op->bounds().fRight, op->bounds().fBottom);
Brian Salomon25a88092016-12-01 09:36:50 -0500313 GrOP_INFO("\tOutcome:\n");
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500314 int maxCandidates = SkTMin(fMaxOpLookback, fRecordedOps.count());
Brian Salomoncdcc33f2017-02-21 09:49:20 -0500315 // If we don't have a valid destination render target then we cannot reorder.
316 if (maxCandidates && renderTarget) {
bsalomon512be532015-09-10 10:42:55 -0700317 int i = 0;
318 while (true) {
Brian Salomon69868af2016-12-22 15:42:51 -0500319 const RecordedOp& candidate = fRecordedOps.fromBack(i);
bsalomon512be532015-09-10 10:42:55 -0700320 // We cannot continue to search backwards if the render target changes
Brian Salomoncdcc33f2017-02-21 09:49:20 -0500321 if (candidate.fRenderTarget.get() != renderTarget) {
Brian Salomon69868af2016-12-22 15:42:51 -0500322 GrOP_INFO("\t\tBreaking because of (%s, B%u) Rendertarget\n", candidate.fOp->name(),
323 candidate.fOp->uniqueID());
bsalomon512be532015-09-10 10:42:55 -0700324 break;
325 }
Brian Salomon54d212e2017-03-21 14:22:38 -0400326 if (this->combineIfPossible(candidate, op.get(), clip, dstTexture)) {
Brian Salomon69868af2016-12-22 15:42:51 -0500327 GrOP_INFO("\t\tCombining with (%s, B%u)\n", candidate.fOp->name(),
328 candidate.fOp->uniqueID());
Brian Salomon199fb872017-02-06 09:41:10 -0500329 GrOP_INFO("\t\t\tCombined op info:\n");
330 GrOP_INFO(SkTabString(candidate.fOp->dumpInfo(), 4).c_str());
Brian Salomon69868af2016-12-22 15:42:51 -0500331 GR_AUDIT_TRAIL_OPS_RESULT_COMBINED(fAuditTrail, candidate.fOp.get(), op.get());
Brian Salomon69868af2016-12-22 15:42:51 -0500332 return candidate.fOp.get();
bsalomon512be532015-09-10 10:42:55 -0700333 }
334 // Stop going backwards if we would cause a painter's order violation.
Brian Salomon9e50f7b2017-03-06 12:02:34 -0500335 if (!can_reorder(fRecordedOps.fromBack(i).fOp->bounds(), op->bounds())) {
Brian Salomon69868af2016-12-22 15:42:51 -0500336 GrOP_INFO("\t\tIntersects with (%s, B%u)\n", candidate.fOp->name(),
337 candidate.fOp->uniqueID());
bsalomon512be532015-09-10 10:42:55 -0700338 break;
339 }
340 ++i;
341 if (i == maxCandidates) {
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500342 GrOP_INFO("\t\tReached max lookback or beginning of op array %d\n", i);
bsalomon512be532015-09-10 10:42:55 -0700343 break;
344 }
345 }
346 } else {
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500347 GrOP_INFO("\t\tFirstOp\n");
bsalomon512be532015-09-10 10:42:55 -0700348 }
Brian Salomon42ad83a2016-12-20 16:14:45 -0500349 GR_AUDIT_TRAIL_OP_RESULT_NEW(fAuditTrail, op);
Brian Salomon54d212e2017-03-21 14:22:38 -0400350 if (clip) {
351 clip = fClipAllocator.make<GrAppliedClip>(std::move(*clip));
352 }
353 fRecordedOps.emplace_back(std::move(op), renderTarget, clip, dstTexture);
Brian Salomond543e0a2017-03-06 16:36:49 -0500354 fRecordedOps.back().fOp->wasRecorded();
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500355 fLastFullClearOp = nullptr;
Robert Phillipsf7a72612017-03-31 10:03:45 -0400356 fLastFullClearResourceID.makeInvalid();
357 fLastFullClearProxyID.makeInvalid();
Brian Salomon2790c522016-12-09 16:32:23 -0500358 return fRecordedOps.back().fOp.get();
bsalomon512be532015-09-10 10:42:55 -0700359}
360
Robert Phillipsf2361d22016-10-25 14:20:06 -0400361void GrRenderTargetOpList::forwardCombine() {
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500362 if (fMaxOpLookahead <= 0) {
bsalomondb27fc52016-08-29 12:43:27 -0700363 return;
364 }
Brian Salomon337432d2017-03-21 17:36:10 -0400365 for (int i = 0; i < fRecordedOps.count() - 1; ++i) {
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500366 GrOp* op = fRecordedOps[i].fOp.get();
Brian Salomoncdcc33f2017-02-21 09:49:20 -0500367 GrRenderTarget* renderTarget = fRecordedOps[i].fRenderTarget.get();
Brian Salomon69868af2016-12-22 15:42:51 -0500368 // If we don't have a valid destination render target ID then we cannot reorder.
Brian Salomoncdcc33f2017-02-21 09:49:20 -0500369 if (!renderTarget) {
Brian Salomon69868af2016-12-22 15:42:51 -0500370 continue;
371 }
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500372 int maxCandidateIdx = SkTMin(i + fMaxOpLookahead, fRecordedOps.count() - 1);
bsalomonaecc0182016-03-07 11:50:44 -0800373 int j = i + 1;
374 while (true) {
Brian Salomon69868af2016-12-22 15:42:51 -0500375 const RecordedOp& candidate = fRecordedOps[j];
bsalomonaecc0182016-03-07 11:50:44 -0800376 // We cannot continue to search if the render target changes
Brian Salomoncdcc33f2017-02-21 09:49:20 -0500377 if (candidate.fRenderTarget.get() != renderTarget) {
Brian Salomon69868af2016-12-22 15:42:51 -0500378 GrOP_INFO("\t\tBreaking because of (%s, B%u) Rendertarget\n", candidate.fOp->name(),
379 candidate.fOp->uniqueID());
bsalomonaecc0182016-03-07 11:50:44 -0800380 break;
381 }
Brian Salomon54d212e2017-03-21 14:22:38 -0400382 if (this->combineIfPossible(fRecordedOps[i], candidate.fOp.get(),
383 candidate.fAppliedClip, &candidate.fDstTexture)) {
Brian Salomon69868af2016-12-22 15:42:51 -0500384 GrOP_INFO("\t\tCombining with (%s, B%u)\n", candidate.fOp->name(),
385 candidate.fOp->uniqueID());
386 GR_AUDIT_TRAIL_OPS_RESULT_COMBINED(fAuditTrail, op, candidate.fOp.get());
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500387 fRecordedOps[j].fOp = std::move(fRecordedOps[i].fOp);
bsalomonaecc0182016-03-07 11:50:44 -0800388 break;
389 }
390 // Stop going traversing if we would cause a painter's order violation.
Brian Salomon9e50f7b2017-03-06 12:02:34 -0500391 if (!can_reorder(fRecordedOps[j].fOp->bounds(), op->bounds())) {
Brian Salomon69868af2016-12-22 15:42:51 -0500392 GrOP_INFO("\t\tIntersects with (%s, B%u)\n", candidate.fOp->name(),
393 candidate.fOp->uniqueID());
bsalomonaecc0182016-03-07 11:50:44 -0800394 break;
395 }
396 ++j;
397 if (j > maxCandidateIdx) {
Brian Salomon09d994e2016-12-21 11:14:46 -0500398 GrOP_INFO("\t\tReached max lookahead or end of op array %d\n", i);
bsalomonaecc0182016-03-07 11:50:44 -0800399 break;
400 }
401 }
402 }
403}
404