blob: ef96738aded2f3354d85a888ab85e2ef2f5acbf6 [file] [log] [blame]
bsalomon95740982014-09-04 13:12:37 -07001/*
2 * Copyright 2014 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#ifndef GrProgramElement_DEFINED
9#define GrProgramElement_DEFINED
10
bungemanbf521ff2016-02-17 13:13:44 -080011#include "../private/SkTArray.h"
bsalomon95740982014-09-04 13:12:37 -070012#include "SkRefCnt.h"
bsalomon95740982014-09-04 13:12:37 -070013
bsalomon95740982014-09-04 13:12:37 -070014/**
Brian Salomone57194f2017-01-09 15:30:02 -050015 * Note: We are converting GrProcessor from ref counting to a single owner model using move
16 * semantics. This class will be removed.
17 *
Brian Salomond61c9d92017-04-10 10:54:25 -040018 * This is used to track "refs" for two separate types GrProcessor ownership. A regular ref is owned
19 * by any client that may continue to issue draws that use the GrProgramElement. A recorded op or
20 * GrPipeline uses "pending executions" instead of refs. A pending execution is cleared after the
21 * draw is executed (or aborted).
bsalomon42048002015-08-27 16:43:48 -070022 *
23 * While a GrProgramElement is ref'ed any resources it owns are also ref'ed. However, once it gets
24 * into the state where it has pending executions AND no refs then it converts its ownership of
25 * its GrGpuResources from refs to pending IOs. The pending IOs allow the cache to track when it is
Brian Salomon09d994e2016-12-21 11:14:46 -050026 * safe to recycle a resource even though we still have buffered GrOps that read or write to the
bsalomon42048002015-08-27 16:43:48 -070027 * the resource.
28 *
Brian Salomond61c9d92017-04-10 10:54:25 -040029 * To make this work the subclass GrProcessor implements addPendingIOs, removeRefs, and
30 * pendingIOComplete. addPendingIOs adds pending reads/writes to GrGpuResources owned by the
31 * processor as appropriate when the processor is recorded in a GrOpList. removeRefs is called when
32 * the ref count reaches 0 and the GrProcessor is only owned by "pending executions".
33 * pendingIOComplete occurs if the resource is still owned by a ref but all recorded draws have been
34 * completed. Whenever pending executions and refs reach zero the processor is deleted.
35 *
36 * The GrProcessor may also implement notifyRefCntIsZero in order to change its ownership of child
37 * processors from ref to pending execution when the processor is first owned exclusively in pending
38 * execution mode.
bsalomon95740982014-09-04 13:12:37 -070039 */
Brian Salomond61c9d92017-04-10 10:54:25 -040040class GrProgramElement : public SkNoncopyable {
bsalomon95740982014-09-04 13:12:37 -070041public:
bsalomon95740982014-09-04 13:12:37 -070042 virtual ~GrProgramElement() {
43 // fRefCnt can be one when an effect is created statically using GR_CREATE_STATIC_EFFECT
44 SkASSERT((0 == fRefCnt || 1 == fRefCnt) && 0 == fPendingExecutions);
45 // Set to invalid values.
46 SkDEBUGCODE(fRefCnt = fPendingExecutions = -10;)
47 }
48
49 void ref() const {
bsalomonae59b772014-11-19 08:23:49 -080050 this->validate();
bsalomon95740982014-09-04 13:12:37 -070051 // Once the ref cnt reaches zero it should never be ref'ed again.
52 SkASSERT(fRefCnt > 0);
bsalomon95740982014-09-04 13:12:37 -070053 ++fRefCnt;
bsalomonae59b772014-11-19 08:23:49 -080054 this->validate();
bsalomon95740982014-09-04 13:12:37 -070055 }
56
57 void unref() const {
58 this->validate();
59 --fRefCnt;
bsalomond0128772014-10-03 05:31:41 -070060 if (0 == fRefCnt) {
bsalomon42048002015-08-27 16:43:48 -070061 this->notifyRefCntIsZero();
bsalomond0128772014-10-03 05:31:41 -070062 if (0 == fPendingExecutions) {
halcanary385fe4d2015-08-26 13:07:48 -070063 delete this;
bsalomonae59b772014-11-19 08:23:49 -080064 return;
bsalomond0128772014-10-03 05:31:41 -070065 } else {
Brian Salomond61c9d92017-04-10 10:54:25 -040066 this->removeRefs();
bsalomond0128772014-10-03 05:31:41 -070067 }
bsalomon95740982014-09-04 13:12:37 -070068 }
bsalomonae59b772014-11-19 08:23:49 -080069 this->validate();
bsalomon95740982014-09-04 13:12:37 -070070 }
71
72 void validate() const {
73#ifdef SK_DEBUG
74 SkASSERT(fRefCnt >= 0);
75 SkASSERT(fPendingExecutions >= 0);
76 SkASSERT(fRefCnt + fPendingExecutions > 0);
77#endif
78 }
79
80protected:
Brian Salomon19ae1382017-01-09 10:14:34 -050081 GrProgramElement() : fRefCnt(1), fPendingExecutions(0) {}
bsalomon95740982014-09-04 13:12:37 -070082
bsalomonae59b772014-11-19 08:23:49 -080083 void addPendingExecution() const {
84 this->validate();
bsalomonae59b772014-11-19 08:23:49 -080085 if (0 == fPendingExecutions) {
Brian Salomond61c9d92017-04-10 10:54:25 -040086 this->addPendingIOs();
bsalomonae59b772014-11-19 08:23:49 -080087 }
88 ++fPendingExecutions;
89 this->validate();
90 }
bsalomon95740982014-09-04 13:12:37 -070091
bsalomonae59b772014-11-19 08:23:49 -080092 void completedExecution() const {
93 this->validate();
94 --fPendingExecutions;
95 if (0 == fPendingExecutions) {
96 if (0 == fRefCnt) {
halcanary385fe4d2015-08-26 13:07:48 -070097 delete this;
bsalomonae59b772014-11-19 08:23:49 -080098 return;
99 } else {
Brian Salomond61c9d92017-04-10 10:54:25 -0400100 this->pendingIOComplete();
bsalomonae59b772014-11-19 08:23:49 -0800101 }
102 }
103 this->validate();
104 }
bsalomon95740982014-09-04 13:12:37 -0700105
bsalomon42048002015-08-27 16:43:48 -0700106private:
Brian Salomond61c9d92017-04-10 10:54:25 -0400107 virtual void addPendingIOs() const = 0;
108 virtual void removeRefs() const = 0;
109 virtual void pendingIOComplete() const = 0;
110
bsalomon42048002015-08-27 16:43:48 -0700111 /** This will be called when the ref cnt is zero. The object may or may not have pending
112 executions. */
113 virtual void notifyRefCntIsZero() const = 0;
114
bsalomon95740982014-09-04 13:12:37 -0700115 mutable int32_t fRefCnt;
116 // Count of deferred executions not yet issued to the 3D API.
117 mutable int32_t fPendingExecutions;
bsalomon95740982014-09-04 13:12:37 -0700118
Brian Salomond61c9d92017-04-10 10:54:25 -0400119 // Only these classes can access addPendingExecution() and completedExecution().
bsalomonae59b772014-11-19 08:23:49 -0800120 template <typename T> friend class GrPendingProgramElement;
Brian Salomon92ce5942017-01-18 11:01:10 -0500121 friend class GrProcessorSet;
bsalomon95740982014-09-04 13:12:37 -0700122
123 typedef SkNoncopyable INHERITED;
124};
125
126#endif