blob: 425f57a59d5f6679fd4bc7f617061cb6f796bd83 [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
bsalomonf96ba022014-09-17 08:05:40 -070014class GrGpuResourceRef;
bsalomon95740982014-09-04 13:12:37 -070015
16/**
Brian Salomone57194f2017-01-09 15:30:02 -050017 * Note: We are converting GrProcessor from ref counting to a single owner model using move
18 * semantics. This class will be removed.
19 *
Brian Salomond61c9d92017-04-10 10:54:25 -040020 * This is used to track "refs" for two separate types GrProcessor ownership. A regular ref is owned
21 * by any client that may continue to issue draws that use the GrProgramElement. A recorded op or
22 * GrPipeline uses "pending executions" instead of refs. A pending execution is cleared after the
23 * draw is executed (or aborted).
bsalomon42048002015-08-27 16:43:48 -070024 *
25 * While a GrProgramElement is ref'ed any resources it owns are also ref'ed. However, once it gets
26 * into the state where it has pending executions AND no refs then it converts its ownership of
27 * 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 -050028 * safe to recycle a resource even though we still have buffered GrOps that read or write to the
bsalomon42048002015-08-27 16:43:48 -070029 * the resource.
30 *
Brian Salomond61c9d92017-04-10 10:54:25 -040031 * To make this work the subclass GrProcessor implements addPendingIOs, removeRefs, and
32 * pendingIOComplete. addPendingIOs adds pending reads/writes to GrGpuResources owned by the
33 * processor as appropriate when the processor is recorded in a GrOpList. removeRefs is called when
34 * the ref count reaches 0 and the GrProcessor is only owned by "pending executions".
35 * pendingIOComplete occurs if the resource is still owned by a ref but all recorded draws have been
36 * completed. Whenever pending executions and refs reach zero the processor is deleted.
37 *
38 * The GrProcessor may also implement notifyRefCntIsZero in order to change its ownership of child
39 * processors from ref to pending execution when the processor is first owned exclusively in pending
40 * execution mode.
bsalomon95740982014-09-04 13:12:37 -070041 */
Brian Salomond61c9d92017-04-10 10:54:25 -040042class GrProgramElement : public SkNoncopyable {
bsalomon95740982014-09-04 13:12:37 -070043public:
bsalomon95740982014-09-04 13:12:37 -070044 virtual ~GrProgramElement() {
45 // fRefCnt can be one when an effect is created statically using GR_CREATE_STATIC_EFFECT
46 SkASSERT((0 == fRefCnt || 1 == fRefCnt) && 0 == fPendingExecutions);
47 // Set to invalid values.
48 SkDEBUGCODE(fRefCnt = fPendingExecutions = -10;)
49 }
50
51 void ref() const {
bsalomonae59b772014-11-19 08:23:49 -080052 this->validate();
bsalomon95740982014-09-04 13:12:37 -070053 // Once the ref cnt reaches zero it should never be ref'ed again.
54 SkASSERT(fRefCnt > 0);
bsalomon95740982014-09-04 13:12:37 -070055 ++fRefCnt;
bsalomonae59b772014-11-19 08:23:49 -080056 this->validate();
bsalomon95740982014-09-04 13:12:37 -070057 }
58
59 void unref() const {
60 this->validate();
61 --fRefCnt;
bsalomond0128772014-10-03 05:31:41 -070062 if (0 == fRefCnt) {
bsalomon42048002015-08-27 16:43:48 -070063 this->notifyRefCntIsZero();
bsalomond0128772014-10-03 05:31:41 -070064 if (0 == fPendingExecutions) {
halcanary385fe4d2015-08-26 13:07:48 -070065 delete this;
bsalomonae59b772014-11-19 08:23:49 -080066 return;
bsalomond0128772014-10-03 05:31:41 -070067 } else {
Brian Salomond61c9d92017-04-10 10:54:25 -040068 this->removeRefs();
bsalomond0128772014-10-03 05:31:41 -070069 }
bsalomon95740982014-09-04 13:12:37 -070070 }
bsalomonae59b772014-11-19 08:23:49 -080071 this->validate();
bsalomon95740982014-09-04 13:12:37 -070072 }
73
74 void validate() const {
75#ifdef SK_DEBUG
76 SkASSERT(fRefCnt >= 0);
77 SkASSERT(fPendingExecutions >= 0);
78 SkASSERT(fRefCnt + fPendingExecutions > 0);
79#endif
80 }
81
82protected:
Brian Salomon19ae1382017-01-09 10:14:34 -050083 GrProgramElement() : fRefCnt(1), fPendingExecutions(0) {}
bsalomon95740982014-09-04 13:12:37 -070084
bsalomonae59b772014-11-19 08:23:49 -080085 void addPendingExecution() const {
86 this->validate();
bsalomonae59b772014-11-19 08:23:49 -080087 if (0 == fPendingExecutions) {
Brian Salomond61c9d92017-04-10 10:54:25 -040088 this->addPendingIOs();
bsalomonae59b772014-11-19 08:23:49 -080089 }
90 ++fPendingExecutions;
91 this->validate();
92 }
bsalomon95740982014-09-04 13:12:37 -070093
bsalomonae59b772014-11-19 08:23:49 -080094 void completedExecution() const {
95 this->validate();
96 --fPendingExecutions;
97 if (0 == fPendingExecutions) {
98 if (0 == fRefCnt) {
halcanary385fe4d2015-08-26 13:07:48 -070099 delete this;
bsalomonae59b772014-11-19 08:23:49 -0800100 return;
101 } else {
Brian Salomond61c9d92017-04-10 10:54:25 -0400102 this->pendingIOComplete();
bsalomonae59b772014-11-19 08:23:49 -0800103 }
104 }
105 this->validate();
106 }
bsalomon95740982014-09-04 13:12:37 -0700107
bsalomon42048002015-08-27 16:43:48 -0700108private:
Brian Salomond61c9d92017-04-10 10:54:25 -0400109 virtual void addPendingIOs() const = 0;
110 virtual void removeRefs() const = 0;
111 virtual void pendingIOComplete() const = 0;
112
bsalomon42048002015-08-27 16:43:48 -0700113 /** This will be called when the ref cnt is zero. The object may or may not have pending
114 executions. */
115 virtual void notifyRefCntIsZero() const = 0;
116
bsalomon95740982014-09-04 13:12:37 -0700117 mutable int32_t fRefCnt;
118 // Count of deferred executions not yet issued to the 3D API.
119 mutable int32_t fPendingExecutions;
bsalomon95740982014-09-04 13:12:37 -0700120
Brian Salomond61c9d92017-04-10 10:54:25 -0400121 // Only these classes can access addPendingExecution() and completedExecution().
bsalomonae59b772014-11-19 08:23:49 -0800122 template <typename T> friend class GrPendingProgramElement;
Brian Salomon92ce5942017-01-18 11:01:10 -0500123 friend class GrProcessorSet;
bsalomon95740982014-09-04 13:12:37 -0700124
125 typedef SkNoncopyable INHERITED;
126};
127
128#endif