blob: a51d8148e75e06b97146a3967f33be7ed602c75b [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
bsalomonf96ba022014-09-17 08:05:40 -07008#ifndef GrGpuResourceRef_DEFINED
9#define GrGpuResourceRef_DEFINED
bsalomon95740982014-09-04 13:12:37 -070010
bsalomon45725db2014-09-19 11:48:02 -070011#include "GrGpuResource.h"
bsalomon37dd3312014-11-03 08:47:23 -080012#include "GrRenderTarget.h"
13#include "GrTexture.h"
bsalomon95740982014-09-04 13:12:37 -070014#include "SkRefCnt.h"
15
bsalomon95740982014-09-04 13:12:37 -070016/**
bsalomonb3e3a952014-09-19 11:10:40 -070017 * This class is intended only for internal use in core Gr code.
18 *
bsalomon95740982014-09-04 13:12:37 -070019 * Class that wraps a resource referenced by a GrProgramElement or GrDrawState. It manages
bsalomonb3e3a952014-09-19 11:10:40 -070020 * converting refs to pending IO operations. It allows a resource ownership to be in three
21 * states:
22 * 1. Owns a single ref
23 * 2. Owns a single ref and a pending IO operation (read, write, or read-write)
24 * 3. Owns a single pending IO operation.
25 *
26 * It is legal to destroy the GrGpuResourceRef in any of these states. It starts in state
27 * 1. Calling markPendingIO() converts it from state 1 to state 2. Calling removeRef() goes from
28 * state 2 to state 3. Calling pendingIOComplete() moves from state 2 to state 1. There is no
29 * valid way of going from state 3 back to 2 or 1.
30 *
bungeman6bd52842016-10-27 09:30:08 -070031 * Like sk_sp, its constructor and setter adopt a ref from their caller.
bsalomonb3e3a952014-09-19 11:10:40 -070032 *
33 * TODO: Once GrDODrawState no longer exists and therefore GrDrawState and GrOptDrawState no
34 * longer share an instance of this class, attempt to make the resource owned by GrGpuResourceRef
35 * only settable via the constructor.
bsalomon95740982014-09-04 13:12:37 -070036 */
bsalomonf96ba022014-09-17 08:05:40 -070037class GrGpuResourceRef : SkNoncopyable {
bsalomon95740982014-09-04 13:12:37 -070038public:
bsalomonf96ba022014-09-17 08:05:40 -070039 ~GrGpuResourceRef();
bsalomon95740982014-09-04 13:12:37 -070040
41 GrGpuResource* getResource() const { return fResource; }
42
bsalomon95740982014-09-04 13:12:37 -070043 /** Does this object own a pending read or write on the resource it is wrapping. */
44 bool ownsPendingIO() const { return fPendingIO; }
45
Brian Salomonf9f45122016-11-29 11:59:17 -050046 /** What type of IO does this represent? This is independent of whether a normal ref or a
47 pending IO is currently held. */
48 GrIOType ioType() const { return fIOType; }
49
bsalomon95740982014-09-04 13:12:37 -070050 /** Shortcut for calling setResource() with NULL. It cannot be called after markingPendingIO
51 is called. */
52 void reset();
53
bsalomonc4923342014-09-16 13:54:53 -070054protected:
bsalomonf96ba022014-09-17 08:05:40 -070055 GrGpuResourceRef();
bsalomonc4923342014-09-16 13:54:53 -070056
57 /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as
58 pending on the resource when markPendingIO is called. */
bsalomonbcf0a522014-10-08 08:40:09 -070059 GrGpuResourceRef(GrGpuResource*, GrIOType);
bsalomonc4923342014-09-16 13:54:53 -070060
61 /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as
62 pending on the resource when markPendingIO is called. */
bsalomonbcf0a522014-10-08 08:40:09 -070063 void setResource(GrGpuResource*, GrIOType);
bsalomonc4923342014-09-16 13:54:53 -070064
bsalomon95740982014-09-04 13:12:37 -070065private:
66 /** Called by owning GrProgramElement when the program element is first scheduled for
bsalomonb3e3a952014-09-19 11:10:40 -070067 execution. It can only be called once. */
bsalomon95740982014-09-04 13:12:37 -070068 void markPendingIO() const;
69
Robert Phillipsf2361d22016-10-25 14:20:06 -040070 /** Called when the program element/draw state is no longer owned by GrOpList-client code.
bsalomon95740982014-09-04 13:12:37 -070071 This lets the cache know that the drawing code will no longer schedule additional reads or
bsalomonb3e3a952014-09-19 11:10:40 -070072 writes to the resource using the program element or draw state. It can only be called once.
73 */
bsalomon95740982014-09-04 13:12:37 -070074 void removeRef() const;
75
bsalomonac8d6192014-09-04 14:13:44 -070076 /** Called to indicate that the previous pending IO is complete. Useful when the owning object
bsalomonf96ba022014-09-17 08:05:40 -070077 still has refs, so it is not about to destroy this GrGpuResourceRef, but its previously
bsalomonb3e3a952014-09-19 11:10:40 -070078 pending executions have been complete. Can only be called if removeRef() was not previously
79 called. */
bsalomonac8d6192014-09-04 14:13:44 -070080 void pendingIOComplete() const;
81
bsalomon95740982014-09-04 13:12:37 -070082 friend class GrProgramElement;
83
bsalomonbcf0a522014-10-08 08:40:09 -070084 GrGpuResource* fResource;
85 mutable bool fOwnRef;
86 mutable bool fPendingIO;
87 GrIOType fIOType;
bsalomon95740982014-09-04 13:12:37 -070088
89 typedef SkNoncopyable INHERITED;
90};
91
mtklein6f076652015-01-13 08:22:43 -080092/**
bsalomonb3e3a952014-09-19 11:10:40 -070093 * Templated version of GrGpuResourceRef to enforce type safety.
94 */
bsalomonf96ba022014-09-17 08:05:40 -070095template <typename T> class GrTGpuResourceRef : public GrGpuResourceRef {
bsalomonc4923342014-09-16 13:54:53 -070096public:
bsalomonf96ba022014-09-17 08:05:40 -070097 GrTGpuResourceRef() {}
bsalomonc4923342014-09-16 13:54:53 -070098
99 /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as
100 pending on the resource when markPendingIO is called. */
bsalomon37dd3312014-11-03 08:47:23 -0800101 GrTGpuResourceRef(T* resource, GrIOType ioType) : INHERITED(resource, ioType) { }
bsalomonc4923342014-09-16 13:54:53 -0700102
103 T* get() const { return static_cast<T*>(this->getResource()); }
104
105 /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as
106 pending on the resource when markPendingIO is called. */
bsalomonbcf0a522014-10-08 08:40:09 -0700107 void set(T* resource, GrIOType ioType) { this->setResource(resource, ioType); }
bsalomonf96ba022014-09-17 08:05:40 -0700108
109private:
110 typedef GrGpuResourceRef INHERITED;
bsalomonc4923342014-09-16 13:54:53 -0700111};
112
bsalomon37dd3312014-11-03 08:47:23 -0800113// Specializations for GrTexture and GrRenderTarget because they use virtual inheritance.
114template<> class GrTGpuResourceRef<GrTexture> : public GrGpuResourceRef {
115public:
116 GrTGpuResourceRef() {}
117
118 GrTGpuResourceRef(GrTexture* texture, GrIOType ioType) : INHERITED(texture, ioType) { }
119
120 GrTexture* get() const {
121 GrSurface* surface = static_cast<GrSurface*>(this->getResource());
122 if (surface) {
123 return surface->asTexture();
124 } else {
125 return NULL;
126 }
127 }
128
129 void set(GrTexture* texture, GrIOType ioType) { this->setResource(texture, ioType); }
130
131private:
132 typedef GrGpuResourceRef INHERITED;
133};
134
135template<> class GrTGpuResourceRef<GrRenderTarget> : public GrGpuResourceRef {
136public:
137 GrTGpuResourceRef() {}
138
139 GrTGpuResourceRef(GrRenderTarget* rt, GrIOType ioType) : INHERITED(rt, ioType) { }
140
141 GrRenderTarget* get() const {
142 GrSurface* surface = static_cast<GrSurface*>(this->getResource());
143 if (surface) {
144 return surface->asRenderTarget();
145 } else {
146 return NULL;
147 }
148 }
149
150 void set(GrRenderTarget* rt, GrIOType ioType) { this->setResource(rt, ioType); }
151
152private:
153 typedef GrGpuResourceRef INHERITED;
154};
155
bsalomonb3e3a952014-09-19 11:10:40 -0700156/**
157 * This is similar to GrTGpuResourceRef but can only be in the pending IO state. It never owns a
158 * ref.
159 */
bsalomonbcf0a522014-10-08 08:40:09 -0700160template <typename T, GrIOType IO_TYPE> class GrPendingIOResource : SkNoncopyable {
bsalomonb3e3a952014-09-19 11:10:40 -0700161public:
joshualitt7eb8c7b2014-11-18 14:24:27 -0800162 GrPendingIOResource(T* resource = NULL) : fResource(NULL) {
163 this->reset(resource);
164 }
165
166 void reset(T* resource) {
167 if (resource) {
bsalomon45725db2014-09-19 11:48:02 -0700168 switch (IO_TYPE) {
bsalomonbcf0a522014-10-08 08:40:09 -0700169 case kRead_GrIOType:
joshualitt7eb8c7b2014-11-18 14:24:27 -0800170 resource->addPendingRead();
bsalomonb3e3a952014-09-19 11:10:40 -0700171 break;
bsalomonbcf0a522014-10-08 08:40:09 -0700172 case kWrite_GrIOType:
joshualitt7eb8c7b2014-11-18 14:24:27 -0800173 resource->addPendingWrite();
bsalomonb3e3a952014-09-19 11:10:40 -0700174 break;
bsalomonbcf0a522014-10-08 08:40:09 -0700175 case kRW_GrIOType:
joshualitt7eb8c7b2014-11-18 14:24:27 -0800176 resource->addPendingRead();
177 resource->addPendingWrite();
bsalomonb3e3a952014-09-19 11:10:40 -0700178 break;
179 }
180 }
joshualitt7eb8c7b2014-11-18 14:24:27 -0800181 this->release();
182 fResource = resource;
bsalomonb3e3a952014-09-19 11:10:40 -0700183 }
bsalomonc4923342014-09-16 13:54:53 -0700184
bsalomonb3e3a952014-09-19 11:10:40 -0700185 ~GrPendingIOResource() {
joshualitt7eb8c7b2014-11-18 14:24:27 -0800186 this->release();
bsalomonb3e3a952014-09-19 11:10:40 -0700187 }
188
reedd9ffaed2015-11-10 04:55:08 -0800189 explicit operator bool() const { return SkToBool(fResource); }
190
191 bool operator==(const GrPendingIOResource& other) const {
192 return fResource == other.fResource;
193 }
bsalomonb03c4a32014-11-20 09:56:11 -0800194
bsalomonb3e3a952014-09-19 11:10:40 -0700195 T* get() const { return fResource; }
196
197private:
joshualitt7eb8c7b2014-11-18 14:24:27 -0800198 void release() {
199 if (fResource) {
200 switch (IO_TYPE) {
201 case kRead_GrIOType:
202 fResource->completedRead();
203 break;
204 case kWrite_GrIOType:
205 fResource->completedWrite();
206 break;
207 case kRW_GrIOType:
208 fResource->completedRead();
209 fResource->completedWrite();
210 break;
211 }
212 }
213 }
214
bsalomonbcf0a522014-10-08 08:40:09 -0700215 T* fResource;
bsalomonb3e3a952014-09-19 11:10:40 -0700216};
bsalomon95740982014-09-04 13:12:37 -0700217#endif