blob: fb63e768bd29c257cbc609cc43ea6ea83122a003 [file] [log] [blame]
Brian Osman62e7b5f2016-10-26 12:02:18 -04001/*
2 * Copyright 2016 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.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "src/gpu/GrTextureOpList.h"
Brian Osman62e7b5f2016-10-26 12:02:18 -04009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/gpu/GrContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/private/GrRecordingContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "src/core/SkStringUtils.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040013#include "src/gpu/GrAuditTrail.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050014#include "src/gpu/GrContextPriv.h"
15#include "src/gpu/GrGpu.h"
16#include "src/gpu/GrMemoryPool.h"
17#include "src/gpu/GrRecordingContextPriv.h"
18#include "src/gpu/GrResourceAllocator.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040019#include "src/gpu/GrTextureProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050020#include "src/gpu/ops/GrCopySurfaceOp.h"
Brian Osman62e7b5f2016-10-26 12:02:18 -040021
22////////////////////////////////////////////////////////////////////////////////
23
Robert Phillips12c46292019-04-23 07:36:17 -040024GrTextureOpList::GrTextureOpList(sk_sp<GrOpMemoryPool> opMemoryPool,
Robert Phillips831a2932019-04-12 17:18:39 -040025 sk_sp<GrTextureProxy> proxy,
Robert Phillips5efd5ea2017-05-30 13:47:32 -040026 GrAuditTrail* auditTrail)
Robert Phillips12c46292019-04-23 07:36:17 -040027 : INHERITED(std::move(opMemoryPool), proxy, auditTrail) {
Robert Phillipsc994a932018-06-19 13:09:54 -040028 SkASSERT(fOpMemoryPool);
Brian Salomonc67c31c2018-12-06 10:00:03 -050029 SkASSERT(!proxy->readOnly());
Robert Phillipsc994a932018-06-19 13:09:54 -040030}
31
32void GrTextureOpList::deleteOp(int index) {
33 SkASSERT(index >= 0 && index < fRecordedOps.count());
34 fOpMemoryPool->release(std::move(fRecordedOps[index]));
35}
36
37void GrTextureOpList::deleteOps() {
38 for (int i = 0; i < fRecordedOps.count(); ++i) {
Robert Phillipsd46f0092018-07-12 11:49:25 -040039 if (fRecordedOps[i]) {
40 fOpMemoryPool->release(std::move(fRecordedOps[i]));
41 }
Robert Phillipsc994a932018-06-19 13:09:54 -040042 }
43 fRecordedOps.reset();
44 fOpMemoryPool = nullptr;
Brian Osman62e7b5f2016-10-26 12:02:18 -040045}
46
47GrTextureOpList::~GrTextureOpList() {
Robert Phillipsc994a932018-06-19 13:09:54 -040048 this->deleteOps();
Brian Osman62e7b5f2016-10-26 12:02:18 -040049}
50
51////////////////////////////////////////////////////////////////////////////////
52
53#ifdef SK_DEBUG
Robert Phillips27483912018-04-20 12:43:18 -040054void GrTextureOpList::dump(bool printDependencies) const {
55 INHERITED::dump(printDependencies);
Brian Osman62e7b5f2016-10-26 12:02:18 -040056
Brian Salomon1e41f4a2016-12-07 15:05:04 -050057 SkDebugf("ops (%d):\n", fRecordedOps.count());
58 for (int i = 0; i < fRecordedOps.count(); ++i) {
Greg Danielaa3dfbe2018-01-29 10:34:25 -050059 if (!fRecordedOps[i]) {
60 SkDebugf("%d: <failed instantiation>\n", i);
61 } else {
62 SkDebugf("*******************************\n");
63 SkDebugf("%d: %s\n", i, fRecordedOps[i]->name());
64 SkString str = fRecordedOps[i]->dumpInfo();
65 SkDebugf("%s\n", str.c_str());
66 const SkRect& clippedBounds = fRecordedOps[i]->bounds();
67 SkDebugf("ClippedBounds: [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
68 clippedBounds.fLeft, clippedBounds.fTop, clippedBounds.fRight,
69 clippedBounds.fBottom);
70 }
Brian Osman62e7b5f2016-10-26 12:02:18 -040071 }
72}
Robert Phillipsc589b0b2017-04-17 07:53:07 -040073
Brian Osman62e7b5f2016-10-26 12:02:18 -040074#endif
75
Brian Osman407b3422017-08-22 15:01:32 -040076void GrTextureOpList::onPrepare(GrOpFlushState* flushState) {
Robert Phillipsb5204762019-06-19 14:12:13 -040077 SkASSERT(fTarget->peekTexture());
Robert Phillips6cdc22c2017-05-11 16:29:14 -040078 SkASSERT(this->isClosed());
Brian Osman62e7b5f2016-10-26 12:02:18 -040079
Brian Salomon1e41f4a2016-12-07 15:05:04 -050080 // Loop over the ops that haven't yet generated their geometry
81 for (int i = 0; i < fRecordedOps.count(); ++i) {
82 if (fRecordedOps[i]) {
Brian Salomond25f5bc2018-08-08 11:25:17 -040083 SkASSERT(fRecordedOps[i]->isChainHead());
Brian Salomon29b60c92017-10-31 14:42:10 -040084 GrOpFlushState::OpArgs opArgs = {
85 fRecordedOps[i].get(),
86 nullptr,
87 nullptr,
Greg Daniel2c3398d2019-06-19 11:58:01 -040088 GrSwizzle(),
Brian Salomon29b60c92017-10-31 14:42:10 -040089 GrXferProcessor::DstProxy()
90 };
91 flushState->setOpArgs(&opArgs);
Brian Salomon1e41f4a2016-12-07 15:05:04 -050092 fRecordedOps[i]->prepare(flushState);
Brian Salomon29b60c92017-10-31 14:42:10 -040093 flushState->setOpArgs(nullptr);
Brian Osman62e7b5f2016-10-26 12:02:18 -040094 }
95 }
96}
97
Brian Osman407b3422017-08-22 15:01:32 -040098bool GrTextureOpList::onExecute(GrOpFlushState* flushState) {
Brian Salomon1e41f4a2016-12-07 15:05:04 -050099 if (0 == fRecordedOps.count()) {
Brian Osman62e7b5f2016-10-26 12:02:18 -0400100 return false;
101 }
102
Robert Phillipsb5204762019-06-19 14:12:13 -0400103 SkASSERT(fTarget->peekTexture());
Robert Phillips3a9710b2018-03-27 17:51:55 -0400104
Robert Phillips5b5d84c2018-08-09 15:12:18 -0400105 GrGpuTextureCommandBuffer* commandBuffer(
Robert Phillipsb5204762019-06-19 14:12:13 -0400106 flushState->gpu()->getCommandBuffer(fTarget->peekTexture(),
107 fTarget->origin()));
Robert Phillips5b5d84c2018-08-09 15:12:18 -0400108 flushState->setCommandBuffer(commandBuffer);
Greg Daniel500d58b2017-08-24 15:59:33 -0400109
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500110 for (int i = 0; i < fRecordedOps.count(); ++i) {
Robert Phillips3a9710b2018-03-27 17:51:55 -0400111 if (!fRecordedOps[i]) {
112 continue;
113 }
Brian Salomond25f5bc2018-08-08 11:25:17 -0400114 SkASSERT(fRecordedOps[i]->isChainHead());
Brian Salomon29b60c92017-10-31 14:42:10 -0400115 GrOpFlushState::OpArgs opArgs = {
116 fRecordedOps[i].get(),
117 nullptr,
118 nullptr,
Greg Daniel2c3398d2019-06-19 11:58:01 -0400119 GrSwizzle(),
Brian Salomon29b60c92017-10-31 14:42:10 -0400120 GrXferProcessor::DstProxy()
121 };
122 flushState->setOpArgs(&opArgs);
Brian Salomon588cec72018-11-14 13:56:37 -0500123 fRecordedOps[i]->execute(flushState, fRecordedOps[i].get()->bounds());
Brian Salomon29b60c92017-10-31 14:42:10 -0400124 flushState->setOpArgs(nullptr);
Brian Osman62e7b5f2016-10-26 12:02:18 -0400125 }
126
Robert Phillips5b5d84c2018-08-09 15:12:18 -0400127 flushState->gpu()->submit(commandBuffer);
Greg Daniel500d58b2017-08-24 15:59:33 -0400128 flushState->setCommandBuffer(nullptr);
129
Brian Osman62e7b5f2016-10-26 12:02:18 -0400130 return true;
131}
132
Chris Daltona84cacf2017-10-04 10:30:29 -0600133void GrTextureOpList::endFlush() {
Robert Phillipsc994a932018-06-19 13:09:54 -0400134 this->deleteOps();
Chris Daltona84cacf2017-10-04 10:30:29 -0600135 INHERITED::endFlush();
Brian Osman62e7b5f2016-10-26 12:02:18 -0400136}
137
138////////////////////////////////////////////////////////////////////////////////
139
Robert Phillips81dd3e02017-06-23 11:59:24 -0400140// This closely parallels GrRenderTargetOpList::copySurface but renderTargetOpList
141// stores extra data with the op
Robert Phillipsbe9aff22019-02-15 11:33:22 -0500142bool GrTextureOpList::copySurface(GrRecordingContext* context,
Robert Phillipsbf25d432017-04-07 10:08:53 -0400143 GrSurfaceProxy* dst,
144 GrSurfaceProxy* src,
Brian Osman62e7b5f2016-10-26 12:02:18 -0400145 const SkIRect& srcRect,
146 const SkIPoint& dstPoint) {
Robert Phillipsa16f6cb2017-06-01 11:06:13 -0400147 SkASSERT(dst == fTarget.get());
148
Robert Phillips7c525e62018-06-12 10:11:12 -0400149 std::unique_ptr<GrOp> op = GrCopySurfaceOp::Make(context, dst, src, srcRect, dstPoint);
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500150 if (!op) {
Brian Osman62e7b5f2016-10-26 12:02:18 -0400151 return false;
152 }
Robert Phillips9d6c64f2017-09-14 10:56:45 -0400153
Robert Phillips9da87e02019-02-04 13:26:26 -0500154 const GrCaps* caps = context->priv().caps();
Chris Dalton7eb5c0f2019-05-23 15:15:47 -0600155 auto addDependency = [ caps, this ] (GrSurfaceProxy* p, GrMipMapped) {
Robert Phillips7c525e62018-06-12 10:11:12 -0400156 this->addDependency(p, *caps);
Robert Phillips9d6c64f2017-09-14 10:56:45 -0400157 };
158 op->visitProxies(addDependency);
Brian Osman62e7b5f2016-10-26 12:02:18 -0400159
Robert Phillips318c4192017-05-17 09:36:38 -0400160 this->recordOp(std::move(op));
Brian Osman62e7b5f2016-10-26 12:02:18 -0400161 return true;
162}
163
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500164void GrTextureOpList::purgeOpsWithUninstantiatedProxies() {
165 bool hasUninstantiatedProxy = false;
Chris Dalton7eb5c0f2019-05-23 15:15:47 -0600166 auto checkInstantiation = [&hasUninstantiatedProxy](GrSurfaceProxy* p, GrMipMapped) {
Brian Salomonfd98c2c2018-07-31 17:25:29 -0400167 if (!p->isInstantiated()) {
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500168 hasUninstantiatedProxy = true;
169 }
170 };
171 for (int i = 0; i < fRecordedOps.count(); ++i) {
172 const GrOp* op = fRecordedOps[i].get(); // only diff from the GrRenderTargetOpList version
173 hasUninstantiatedProxy = false;
174 if (op) {
175 op->visitProxies(checkInstantiation);
176 }
177 if (hasUninstantiatedProxy) {
178 // When instantiation of the proxy fails we drop the Op
Robert Phillipsc994a932018-06-19 13:09:54 -0400179 this->deleteOp(i);
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500180 }
181 }
182}
183
Robert Phillips9313aa72019-04-09 18:41:27 -0400184bool GrTextureOpList::onIsUsed(GrSurfaceProxy* proxyToCheck) const {
185 bool used = false;
186
Chris Dalton7eb5c0f2019-05-23 15:15:47 -0600187 auto visit = [ proxyToCheck, &used ] (GrSurfaceProxy* p, GrMipMapped) {
Robert Phillips9313aa72019-04-09 18:41:27 -0400188 if (p == proxyToCheck) {
189 used = true;
190 }
191 };
192 for (int i = 0; i < fRecordedOps.count(); ++i) {
193 const GrOp* op = fRecordedOps[i].get();
194 if (op) {
Chris Dalton1706cbf2019-05-21 19:35:29 -0600195 op->visitProxies(visit);
Robert Phillips9313aa72019-04-09 18:41:27 -0400196 }
197 }
198
199 return used;
200}
201
Robert Phillipsd375dbf2017-09-14 12:45:25 -0400202void GrTextureOpList::gatherProxyIntervals(GrResourceAllocator* alloc) const {
Robert Phillipsd375dbf2017-09-14 12:45:25 -0400203
204 // Add the interval for all the writes to this opList's target
Robert Phillipsf8e25022017-11-08 15:24:31 -0500205 if (fRecordedOps.count()) {
Robert Phillips3bf3d4a2019-03-27 07:09:09 -0400206 unsigned int cur = alloc->curOp();
207
Robert Phillipsc73666f2019-04-24 08:49:48 -0400208 alloc->addInterval(fTarget.get(), cur, cur+fRecordedOps.count()-1,
209 GrResourceAllocator::ActualUse::kYes);
Robert Phillipsf8e25022017-11-08 15:24:31 -0500210 } else {
211 // This can happen if there is a loadOp (e.g., a clear) but no other draws. In this case we
212 // still need to add an interval for the destination so we create a fake op# for
213 // the missing clear op.
Robert Phillipsc73666f2019-04-24 08:49:48 -0400214 alloc->addInterval(fTarget.get(), alloc->curOp(), alloc->curOp(),
215 GrResourceAllocator::ActualUse::kYes);
Robert Phillipsf8e25022017-11-08 15:24:31 -0500216 alloc->incOps();
217 }
Robert Phillipsd375dbf2017-09-14 12:45:25 -0400218
Chris Dalton7eb5c0f2019-05-23 15:15:47 -0600219 auto gather = [ alloc SkDEBUGCODE(, this) ] (GrSurfaceProxy* p, GrMipMapped) {
Robert Phillipsc73666f2019-04-24 08:49:48 -0400220 alloc->addInterval(p, alloc->curOp(), alloc->curOp(), GrResourceAllocator::ActualUse::kYes
221 SkDEBUGCODE(, p == fTarget.get()));
Robert Phillipsd375dbf2017-09-14 12:45:25 -0400222 };
223 for (int i = 0; i < fRecordedOps.count(); ++i) {
Robert Phillipsd375dbf2017-09-14 12:45:25 -0400224 const GrOp* op = fRecordedOps[i].get(); // only diff from the GrRenderTargetOpList version
Robert Phillips8186cbe2017-11-01 17:32:39 -0400225 if (op) {
Chris Dalton1706cbf2019-05-21 19:35:29 -0600226 op->visitProxies(gather);
Greg Daniel065b41d2017-11-08 19:58:51 +0000227 }
Robert Phillipsf8e25022017-11-08 15:24:31 -0500228
Robert Phillips3bf3d4a2019-03-27 07:09:09 -0400229 // Even though the op may have been (re)moved we still need to increment the op count to
Robert Phillipsf8e25022017-11-08 15:24:31 -0500230 // keep all the math consistent.
231 alloc->incOps();
Robert Phillipsd375dbf2017-09-14 12:45:25 -0400232 }
233}
234
Robert Phillips318c4192017-05-17 09:36:38 -0400235void GrTextureOpList::recordOp(std::unique_ptr<GrOp> op) {
Robert Phillipsb5204762019-06-19 14:12:13 -0400236 SkASSERT(fTarget);
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500237 // A closed GrOpList should never receive new/more ops
Brian Osman62e7b5f2016-10-26 12:02:18 -0400238 SkASSERT(!this->isClosed());
239
Robert Phillipsb5204762019-06-19 14:12:13 -0400240 GR_AUDIT_TRAIL_ADD_OP(fAuditTrail, op.get(), fTarget->uniqueID());
Robert Phillipsf5442bb2017-04-17 14:18:34 -0400241 GrOP_INFO("Re-Recording (%s, opID: %u)\n"
Brian Osman62e7b5f2016-10-26 12:02:18 -0400242 "\tBounds LRTB (%f, %f, %f, %f)\n",
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500243 op->name(),
244 op->uniqueID(),
245 op->bounds().fLeft, op->bounds().fRight,
246 op->bounds().fTop, op->bounds().fBottom);
247 GrOP_INFO(SkTabString(op->dumpInfo(), 1).c_str());
Brian Osman62e7b5f2016-10-26 12:02:18 -0400248
Brian Salomon2790c522016-12-09 16:32:23 -0500249 fRecordedOps.emplace_back(std::move(op));
Brian Osman62e7b5f2016-10-26 12:02:18 -0400250}