OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #ifndef GrProgramElement_DEFINED | 8 #ifndef GrProgramElement_DEFINED |
9 #define GrProgramElement_DEFINED | 9 #define GrProgramElement_DEFINED |
10 | 10 |
11 #include "SkRefCnt.h" | 11 #include "SkRefCnt.h" |
12 #include "SkTArray.h" | 12 #include "SkTArray.h" |
13 | 13 |
14 class GrGpuResourceRef; | 14 class GrGpuResourceRef; |
15 | 15 |
16 /** | 16 /** |
17 * Base class for GrProcessor. GrDrawState uses this to manage | 17 * Base class for GrProcessor. This exists to manage transitioning a GrProcessor
from being owned by |
18 * transitioning a GrProcessor from being owned by a client to being scheduled f
or execution. It | 18 * a client to being scheduled for execution. While a GrProcessor is ref'ed by d
rawing code its |
19 * converts resources owned by the effect from being ref'ed to having pending re
ads/writes. | 19 * GrGpu resources must also be ref'ed to prevent incorrectly recycling them thr
ough the cache. |
| 20 * However, once the GrProcessor is baked into a GrPipeline and the drawing code
has stopped ref'ing |
| 21 * it, it's internal resources can be recycled in some cases. |
20 * | 22 * |
21 * All GrGpuResource objects owned by a GrProgramElement or derived classes (eit
her directly or | 23 * We track this using two types of refs on GrProgramElement. A regular ref is o
wned by any client |
22 * indirectly) must be wrapped in a GrGpuResourceRef and registered with the GrP
rogramElement using | 24 * that may continue to issue draws that use the GrProgramElement. The GrPipelin
e owns "pending |
23 * addGpuResource(). This allows the regular refs to be converted to pending IO
events | 25 * executions" instead of refs. A pending execution is cleared by ~GrPipeline(). |
24 * when the program element is scheduled for deferred execution. | 26 * |
| 27 * While a GrProgramElement is ref'ed any resources it owns are also ref'ed. How
ever, once it gets |
| 28 * into the state where it has pending executions AND no refs then it converts i
ts ownership of |
| 29 * its GrGpuResources from refs to pending IOs. The pending IOs allow the cache
to track when it is |
| 30 * safe to recycle a resource even though we still have buffered GrBatches that
read or write to the |
| 31 * the resource. |
| 32 * |
| 33 * To make this work all GrGpuResource objects owned by a GrProgramElement or de
rived classes |
| 34 * (either directly or indirectly) must be wrapped in a GrGpuResourceRef and reg
istered with the |
| 35 * GrProgramElement using addGpuResource(). This allows the regular refs to be c
onverted to pending |
| 36 * IO events when the program element is scheduled for deferred execution. |
| 37 * |
| 38 * Moreover, a GrProgramElement that in turn owns other GrProgramElements must c
onvert its ownership |
| 39 * of its children to pending executions when its ref count reaches zero so that
the GrGpuResources |
| 40 * owned by the children GrProgramElements are correctly converted from ownershi
p by ref to |
| 41 * ownership by pending IO. Any GrProgramElement hierarchy is managed by subclas
ses which must |
| 42 * implement notifyRefCntIsZero() in order to convert refs of children to pendin
g executions. |
25 */ | 43 */ |
26 class GrProgramElement : public SkNoncopyable { | 44 class GrProgramElement : public SkNoncopyable { |
27 public: | 45 public: |
28 virtual ~GrProgramElement() { | 46 virtual ~GrProgramElement() { |
29 // fRefCnt can be one when an effect is created statically using GR_CREA
TE_STATIC_EFFECT | 47 // fRefCnt can be one when an effect is created statically using GR_CREA
TE_STATIC_EFFECT |
30 SkASSERT((0 == fRefCnt || 1 == fRefCnt) && 0 == fPendingExecutions); | 48 SkASSERT((0 == fRefCnt || 1 == fRefCnt) && 0 == fPendingExecutions); |
31 // Set to invalid values. | 49 // Set to invalid values. |
32 SkDEBUGCODE(fRefCnt = fPendingExecutions = -10;) | 50 SkDEBUGCODE(fRefCnt = fPendingExecutions = -10;) |
33 } | 51 } |
34 | 52 |
35 void ref() const { | 53 void ref() const { |
36 this->validate(); | 54 this->validate(); |
37 // Once the ref cnt reaches zero it should never be ref'ed again. | 55 // Once the ref cnt reaches zero it should never be ref'ed again. |
38 SkASSERT(fRefCnt > 0); | 56 SkASSERT(fRefCnt > 0); |
39 ++fRefCnt; | 57 ++fRefCnt; |
40 this->validate(); | 58 this->validate(); |
41 } | 59 } |
42 | 60 |
43 void unref() const { | 61 void unref() const { |
44 this->validate(); | 62 this->validate(); |
45 --fRefCnt; | 63 --fRefCnt; |
46 if (0 == fRefCnt) { | 64 if (0 == fRefCnt) { |
| 65 this->notifyRefCntIsZero(); |
47 if (0 == fPendingExecutions) { | 66 if (0 == fPendingExecutions) { |
48 delete this; | 67 delete this; |
49 return; | 68 return; |
50 } else { | 69 } else { |
51 this->removeRefs(); | 70 this->removeRefs(); |
52 } | 71 } |
53 } | 72 } |
54 this->validate(); | 73 this->validate(); |
55 } | 74 } |
56 | 75 |
(...skipping 14 matching lines...) Expand all Loading... |
71 GrProgramElement() : fRefCnt(1), fPendingExecutions(0), fUniqueID(CreateUniq
ueID()) {} | 90 GrProgramElement() : fRefCnt(1), fPendingExecutions(0), fUniqueID(CreateUniq
ueID()) {} |
72 | 91 |
73 /** Subclasses registers their resources using this function. It is assumed
the GrProgramResouce | 92 /** Subclasses registers their resources using this function. It is assumed
the GrProgramResouce |
74 is and will remain owned by the subclass and this function will retain a
raw ptr. Once a | 93 is and will remain owned by the subclass and this function will retain a
raw ptr. Once a |
75 GrGpuResourceRef is registered its setResource must not be called. | 94 GrGpuResourceRef is registered its setResource must not be called. |
76 */ | 95 */ |
77 void addGpuResource(const GrGpuResourceRef* res) { | 96 void addGpuResource(const GrGpuResourceRef* res) { |
78 fGpuResources.push_back(res); | 97 fGpuResources.push_back(res); |
79 } | 98 } |
80 | 99 |
81 private: | |
82 static uint32_t CreateUniqueID(); | |
83 | |
84 void addPendingExecution() const { | 100 void addPendingExecution() const { |
85 this->validate(); | 101 this->validate(); |
86 SkASSERT(fRefCnt > 0); | 102 SkASSERT(fRefCnt > 0); |
87 if (0 == fPendingExecutions) { | 103 if (0 == fPendingExecutions) { |
88 this->addPendingIOs(); | 104 this->addPendingIOs(); |
89 } | 105 } |
90 ++fPendingExecutions; | 106 ++fPendingExecutions; |
91 this->validate(); | 107 this->validate(); |
92 } | 108 } |
93 | 109 |
94 void completedExecution() const { | 110 void completedExecution() const { |
95 this->validate(); | 111 this->validate(); |
96 --fPendingExecutions; | 112 --fPendingExecutions; |
97 if (0 == fPendingExecutions) { | 113 if (0 == fPendingExecutions) { |
98 if (0 == fRefCnt) { | 114 if (0 == fRefCnt) { |
99 delete this; | 115 delete this; |
100 return; | 116 return; |
101 } else { | 117 } else { |
102 this->pendingIOComplete(); | 118 this->pendingIOComplete(); |
103 } | 119 } |
104 } | 120 } |
105 this->validate(); | 121 this->validate(); |
106 } | 122 } |
107 | 123 |
| 124 private: |
| 125 /** This will be called when the ref cnt is zero. The object may or may not
have pending |
| 126 executions. */ |
| 127 virtual void notifyRefCntIsZero() const = 0; |
| 128 |
| 129 static uint32_t CreateUniqueID(); |
| 130 |
108 void removeRefs() const; | 131 void removeRefs() const; |
109 void addPendingIOs() const; | 132 void addPendingIOs() const; |
110 void pendingIOComplete() const; | 133 void pendingIOComplete() const; |
111 | 134 |
112 mutable int32_t fRefCnt; | 135 mutable int32_t fRefCnt; |
113 // Count of deferred executions not yet issued to the 3D API. | 136 // Count of deferred executions not yet issued to the 3D API. |
114 mutable int32_t fPendingExecutions; | 137 mutable int32_t fPendingExecutions; |
115 uint32_t fUniqueID; | 138 uint32_t fUniqueID; |
116 | 139 |
117 SkSTArray<4, const GrGpuResourceRef*, true> fGpuResources; | 140 SkSTArray<4, const GrGpuResourceRef*, true> fGpuResources; |
118 | 141 |
119 // Only this class can access addPendingExecution() and completedExecution()
. | 142 // Only this class can access addPendingExecution() and completedExecution()
. |
120 template <typename T> friend class GrPendingProgramElement; | 143 template <typename T> friend class GrPendingProgramElement; |
121 | 144 |
122 typedef SkNoncopyable INHERITED; | 145 typedef SkNoncopyable INHERITED; |
123 }; | 146 }; |
124 | 147 |
125 #endif | 148 #endif |
OLD | NEW |