blob: 6af9588fdf0d389343cdc2a366868ed8cdca469c [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
8#include "GrTextureOpList.h"
9
10#include "GrAuditTrail.h"
Robert Phillips7c525e62018-06-12 10:11:12 -040011#include "GrContext.h"
12#include "GrContextPriv.h"
Brian Osman62e7b5f2016-10-26 12:02:18 -040013#include "GrGpu.h"
Robert Phillipsc994a932018-06-19 13:09:54 -040014#include "GrMemoryPool.h"
Robert Phillipsd375dbf2017-09-14 12:45:25 -040015#include "GrResourceAllocator.h"
Robert Phillipsc7635fa2016-10-28 13:25:24 -040016#include "GrTextureProxy.h"
Brian Salomon69868af2016-12-22 15:42:51 -050017#include "SkStringUtils.h"
Brian Salomon89527432016-12-16 09:52:16 -050018#include "ops/GrCopySurfaceOp.h"
Brian Osman62e7b5f2016-10-26 12:02:18 -040019
20////////////////////////////////////////////////////////////////////////////////
21
Robert Phillips5efd5ea2017-05-30 13:47:32 -040022GrTextureOpList::GrTextureOpList(GrResourceProvider* resourceProvider,
Robert Phillipsc994a932018-06-19 13:09:54 -040023 sk_sp<GrOpMemoryPool> opMemoryPool,
Robert Phillips5efd5ea2017-05-30 13:47:32 -040024 GrTextureProxy* proxy,
25 GrAuditTrail* auditTrail)
Robert Phillipsc994a932018-06-19 13:09:54 -040026 : INHERITED(resourceProvider, std::move(opMemoryPool), proxy, auditTrail) {
27 SkASSERT(fOpMemoryPool);
28}
29
30void GrTextureOpList::deleteOp(int index) {
31 SkASSERT(index >= 0 && index < fRecordedOps.count());
32 fOpMemoryPool->release(std::move(fRecordedOps[index]));
33}
34
35void GrTextureOpList::deleteOps() {
36 for (int i = 0; i < fRecordedOps.count(); ++i) {
Robert Phillipsd46f0092018-07-12 11:49:25 -040037 if (fRecordedOps[i]) {
38 fOpMemoryPool->release(std::move(fRecordedOps[i]));
39 }
Robert Phillipsc994a932018-06-19 13:09:54 -040040 }
41 fRecordedOps.reset();
42 fOpMemoryPool = nullptr;
Brian Osman62e7b5f2016-10-26 12:02:18 -040043}
44
45GrTextureOpList::~GrTextureOpList() {
Robert Phillipsc994a932018-06-19 13:09:54 -040046 this->deleteOps();
Brian Osman62e7b5f2016-10-26 12:02:18 -040047}
48
49////////////////////////////////////////////////////////////////////////////////
50
51#ifdef SK_DEBUG
Robert Phillips27483912018-04-20 12:43:18 -040052void GrTextureOpList::dump(bool printDependencies) const {
53 INHERITED::dump(printDependencies);
Brian Osman62e7b5f2016-10-26 12:02:18 -040054
Brian Salomon1e41f4a2016-12-07 15:05:04 -050055 SkDebugf("ops (%d):\n", fRecordedOps.count());
56 for (int i = 0; i < fRecordedOps.count(); ++i) {
Greg Danielaa3dfbe2018-01-29 10:34:25 -050057 if (!fRecordedOps[i]) {
58 SkDebugf("%d: <failed instantiation>\n", i);
59 } else {
60 SkDebugf("*******************************\n");
61 SkDebugf("%d: %s\n", i, fRecordedOps[i]->name());
62 SkString str = fRecordedOps[i]->dumpInfo();
63 SkDebugf("%s\n", str.c_str());
64 const SkRect& clippedBounds = fRecordedOps[i]->bounds();
65 SkDebugf("ClippedBounds: [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
66 clippedBounds.fLeft, clippedBounds.fTop, clippedBounds.fRight,
67 clippedBounds.fBottom);
68 }
Brian Osman62e7b5f2016-10-26 12:02:18 -040069 }
70}
Robert Phillipsc589b0b2017-04-17 07:53:07 -040071
Brian Osman62e7b5f2016-10-26 12:02:18 -040072#endif
73
Brian Osman407b3422017-08-22 15:01:32 -040074void GrTextureOpList::onPrepare(GrOpFlushState* flushState) {
Robert Phillips3a9710b2018-03-27 17:51:55 -040075 SkASSERT(fTarget.get()->priv().peekTexture());
Robert Phillips6cdc22c2017-05-11 16:29:14 -040076 SkASSERT(this->isClosed());
Brian Osman62e7b5f2016-10-26 12:02:18 -040077
Brian Salomon1e41f4a2016-12-07 15:05:04 -050078 // Loop over the ops that haven't yet generated their geometry
79 for (int i = 0; i < fRecordedOps.count(); ++i) {
80 if (fRecordedOps[i]) {
Brian Salomon29b60c92017-10-31 14:42:10 -040081 GrOpFlushState::OpArgs opArgs = {
82 fRecordedOps[i].get(),
83 nullptr,
84 nullptr,
85 GrXferProcessor::DstProxy()
86 };
87 flushState->setOpArgs(&opArgs);
Brian Salomon1e41f4a2016-12-07 15:05:04 -050088 fRecordedOps[i]->prepare(flushState);
Brian Salomon29b60c92017-10-31 14:42:10 -040089 flushState->setOpArgs(nullptr);
Brian Osman62e7b5f2016-10-26 12:02:18 -040090 }
91 }
92}
93
Brian Osman407b3422017-08-22 15:01:32 -040094bool GrTextureOpList::onExecute(GrOpFlushState* flushState) {
Brian Salomon1e41f4a2016-12-07 15:05:04 -050095 if (0 == fRecordedOps.count()) {
Brian Osman62e7b5f2016-10-26 12:02:18 -040096 return false;
97 }
98
Robert Phillips3a9710b2018-03-27 17:51:55 -040099 SkASSERT(fTarget.get()->priv().peekTexture());
100
Greg Daniel500d58b2017-08-24 15:59:33 -0400101 std::unique_ptr<GrGpuTextureCommandBuffer> commandBuffer(
102 flushState->gpu()->createCommandBuffer(fTarget.get()->priv().peekTexture(),
103 fTarget.get()->origin()));
104 flushState->setCommandBuffer(commandBuffer.get());
105
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500106 for (int i = 0; i < fRecordedOps.count(); ++i) {
Robert Phillips3a9710b2018-03-27 17:51:55 -0400107 if (!fRecordedOps[i]) {
108 continue;
109 }
110
Brian Salomon29b60c92017-10-31 14:42:10 -0400111 GrOpFlushState::OpArgs opArgs = {
112 fRecordedOps[i].get(),
113 nullptr,
114 nullptr,
115 GrXferProcessor::DstProxy()
116 };
117 flushState->setOpArgs(&opArgs);
Brian Salomon9e50f7b2017-03-06 12:02:34 -0500118 fRecordedOps[i]->execute(flushState);
Brian Salomon29b60c92017-10-31 14:42:10 -0400119 flushState->setOpArgs(nullptr);
Brian Osman62e7b5f2016-10-26 12:02:18 -0400120 }
121
Greg Daniel500d58b2017-08-24 15:59:33 -0400122 commandBuffer->submit();
123 flushState->setCommandBuffer(nullptr);
124
Brian Osman62e7b5f2016-10-26 12:02:18 -0400125 return true;
126}
127
Chris Daltona84cacf2017-10-04 10:30:29 -0600128void GrTextureOpList::endFlush() {
Robert Phillipsc994a932018-06-19 13:09:54 -0400129 this->deleteOps();
Chris Daltona84cacf2017-10-04 10:30:29 -0600130 INHERITED::endFlush();
Brian Osman62e7b5f2016-10-26 12:02:18 -0400131}
132
133////////////////////////////////////////////////////////////////////////////////
134
Robert Phillips81dd3e02017-06-23 11:59:24 -0400135// This closely parallels GrRenderTargetOpList::copySurface but renderTargetOpList
136// stores extra data with the op
Robert Phillips7c525e62018-06-12 10:11:12 -0400137bool GrTextureOpList::copySurface(GrContext* context,
Robert Phillipsbf25d432017-04-07 10:08:53 -0400138 GrSurfaceProxy* dst,
139 GrSurfaceProxy* src,
Brian Osman62e7b5f2016-10-26 12:02:18 -0400140 const SkIRect& srcRect,
141 const SkIPoint& dstPoint) {
Robert Phillipsa16f6cb2017-06-01 11:06:13 -0400142 SkASSERT(dst == fTarget.get());
143
Robert Phillips7c525e62018-06-12 10:11:12 -0400144 std::unique_ptr<GrOp> op = GrCopySurfaceOp::Make(context, dst, src, srcRect, dstPoint);
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500145 if (!op) {
Brian Osman62e7b5f2016-10-26 12:02:18 -0400146 return false;
147 }
Robert Phillips9d6c64f2017-09-14 10:56:45 -0400148
Robert Phillips7c525e62018-06-12 10:11:12 -0400149 const GrCaps* caps = context->contextPriv().caps();
150 auto addDependency = [ caps, this ] (GrSurfaceProxy* p) {
151 this->addDependency(p, *caps);
Robert Phillips9d6c64f2017-09-14 10:56:45 -0400152 };
153 op->visitProxies(addDependency);
Brian Osman62e7b5f2016-10-26 12:02:18 -0400154
Robert Phillips318c4192017-05-17 09:36:38 -0400155 this->recordOp(std::move(op));
Brian Osman62e7b5f2016-10-26 12:02:18 -0400156 return true;
157}
158
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500159void GrTextureOpList::purgeOpsWithUninstantiatedProxies() {
160 bool hasUninstantiatedProxy = false;
161 auto checkInstantiation = [ &hasUninstantiatedProxy ] (GrSurfaceProxy* p) {
162 if (!p->priv().isInstantiated()) {
163 hasUninstantiatedProxy = true;
164 }
165 };
166 for (int i = 0; i < fRecordedOps.count(); ++i) {
167 const GrOp* op = fRecordedOps[i].get(); // only diff from the GrRenderTargetOpList version
168 hasUninstantiatedProxy = false;
169 if (op) {
170 op->visitProxies(checkInstantiation);
171 }
172 if (hasUninstantiatedProxy) {
173 // When instantiation of the proxy fails we drop the Op
Robert Phillipsc994a932018-06-19 13:09:54 -0400174 this->deleteOp(i);
Greg Danielaa3dfbe2018-01-29 10:34:25 -0500175 }
176 }
177}
178
Robert Phillipsd375dbf2017-09-14 12:45:25 -0400179void GrTextureOpList::gatherProxyIntervals(GrResourceAllocator* alloc) const {
180 unsigned int cur = alloc->numOps();
181
182 // Add the interval for all the writes to this opList's target
Robert Phillipsf8e25022017-11-08 15:24:31 -0500183 if (fRecordedOps.count()) {
184 alloc->addInterval(fTarget.get(), cur, cur+fRecordedOps.count()-1);
185 } else {
186 // This can happen if there is a loadOp (e.g., a clear) but no other draws. In this case we
187 // still need to add an interval for the destination so we create a fake op# for
188 // the missing clear op.
189 alloc->addInterval(fTarget.get());
190 alloc->incOps();
191 }
Robert Phillipsd375dbf2017-09-14 12:45:25 -0400192
Chris Dalton8816b932017-11-29 16:48:25 -0700193 auto gather = [ alloc SkDEBUGCODE(, this) ] (GrSurfaceProxy* p) {
194 alloc->addInterval(p SkDEBUGCODE(, p == fTarget.get()));
Robert Phillipsd375dbf2017-09-14 12:45:25 -0400195 };
196 for (int i = 0; i < fRecordedOps.count(); ++i) {
Robert Phillipsd375dbf2017-09-14 12:45:25 -0400197 const GrOp* op = fRecordedOps[i].get(); // only diff from the GrRenderTargetOpList version
Robert Phillips8186cbe2017-11-01 17:32:39 -0400198 if (op) {
199 op->visitProxies(gather);
Greg Daniel065b41d2017-11-08 19:58:51 +0000200 }
Robert Phillipsf8e25022017-11-08 15:24:31 -0500201
202 // Even though the op may have been moved we still need to increment the op count to
203 // keep all the math consistent.
204 alloc->incOps();
Robert Phillipsd375dbf2017-09-14 12:45:25 -0400205 }
206}
207
Robert Phillips318c4192017-05-17 09:36:38 -0400208void GrTextureOpList::recordOp(std::unique_ptr<GrOp> op) {
209 SkASSERT(fTarget.get());
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500210 // A closed GrOpList should never receive new/more ops
Brian Osman62e7b5f2016-10-26 12:02:18 -0400211 SkASSERT(!this->isClosed());
212
Robert Phillips318c4192017-05-17 09:36:38 -0400213 GR_AUDIT_TRAIL_ADD_OP(fAuditTrail, op.get(), fTarget.get()->uniqueID());
Robert Phillipsf5442bb2017-04-17 14:18:34 -0400214 GrOP_INFO("Re-Recording (%s, opID: %u)\n"
Brian Osman62e7b5f2016-10-26 12:02:18 -0400215 "\tBounds LRTB (%f, %f, %f, %f)\n",
Brian Salomon1e41f4a2016-12-07 15:05:04 -0500216 op->name(),
217 op->uniqueID(),
218 op->bounds().fLeft, op->bounds().fRight,
219 op->bounds().fTop, op->bounds().fBottom);
220 GrOP_INFO(SkTabString(op->dumpInfo(), 1).c_str());
Brian Salomon42ad83a2016-12-20 16:14:45 -0500221 GR_AUDIT_TRAIL_OP_RESULT_NEW(fAuditTrail, op.get());
Brian Osman62e7b5f2016-10-26 12:02:18 -0400222
Brian Salomon2790c522016-12-09 16:32:23 -0500223 fRecordedOps.emplace_back(std::move(op));
Brian Osman62e7b5f2016-10-26 12:02:18 -0400224}