GrGpuResourceRef.h revision 7eb8c7b00a5d776bebaf33a8687357df95c1aa43
1/* 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 GrGpuResourceRef_DEFINED 9#define GrGpuResourceRef_DEFINED 10 11#include "GrGpuResource.h" 12#include "GrRenderTarget.h" 13#include "GrTexture.h" 14#include "SkRefCnt.h" 15 16/** 17 * This class is intended only for internal use in core Gr code. 18 * 19 * Class that wraps a resource referenced by a GrProgramElement or GrDrawState. It manages 20 * 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 * 31 * Like SkAutoTUnref, its constructor and setter adopt a ref from their caller. 32 * 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. 36 */ 37class GrGpuResourceRef : SkNoncopyable { 38public: 39 SK_DECLARE_INST_COUNT_ROOT(GrGpuResourceRef); 40 41 ~GrGpuResourceRef(); 42 43 GrGpuResource* getResource() const { return fResource; } 44 45 /** Does this object own a pending read or write on the resource it is wrapping. */ 46 bool ownsPendingIO() const { return fPendingIO; } 47 48 /** Shortcut for calling setResource() with NULL. It cannot be called after markingPendingIO 49 is called. */ 50 void reset(); 51 52protected: 53 GrGpuResourceRef(); 54 55 /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as 56 pending on the resource when markPendingIO is called. */ 57 GrGpuResourceRef(GrGpuResource*, GrIOType); 58 59 /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as 60 pending on the resource when markPendingIO is called. */ 61 void setResource(GrGpuResource*, GrIOType); 62 63private: 64 /** Called by owning GrProgramElement when the program element is first scheduled for 65 execution. It can only be called once. */ 66 void markPendingIO() const; 67 68 /** Called when the program element/draw state is no longer owned by GrDrawTarget-client code. 69 This lets the cache know that the drawing code will no longer schedule additional reads or 70 writes to the resource using the program element or draw state. It can only be called once. 71 */ 72 void removeRef() const; 73 74 /** Called to indicate that the previous pending IO is complete. Useful when the owning object 75 still has refs, so it is not about to destroy this GrGpuResourceRef, but its previously 76 pending executions have been complete. Can only be called if removeRef() was not previously 77 called. */ 78 void pendingIOComplete() const; 79 80 friend class GrDrawState; 81 friend class GrOptDrawState; 82 friend class GrProgramElement; 83 84 GrGpuResource* fResource; 85 mutable bool fOwnRef; 86 mutable bool fPendingIO; 87 GrIOType fIOType; 88 89 typedef SkNoncopyable INHERITED; 90}; 91 92/** 93 * Templated version of GrGpuResourceRef to enforce type safety. 94 */ 95template <typename T> class GrTGpuResourceRef : public GrGpuResourceRef { 96public: 97 GrTGpuResourceRef() {} 98 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. */ 101 GrTGpuResourceRef(T* resource, GrIOType ioType) : INHERITED(resource, ioType) { } 102 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. */ 107 void set(T* resource, GrIOType ioType) { this->setResource(resource, ioType); } 108 109private: 110 typedef GrGpuResourceRef INHERITED; 111}; 112 113// 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 156/** 157 * This is similar to GrTGpuResourceRef but can only be in the pending IO state. It never owns a 158 * ref. 159 */ 160template <typename T, GrIOType IO_TYPE> class GrPendingIOResource : SkNoncopyable { 161public: 162 GrPendingIOResource(T* resource = NULL) : fResource(NULL) { 163 this->reset(resource); 164 } 165 166 void reset(T* resource) { 167 if (resource) { 168 switch (IO_TYPE) { 169 case kRead_GrIOType: 170 resource->addPendingRead(); 171 break; 172 case kWrite_GrIOType: 173 resource->addPendingWrite(); 174 break; 175 case kRW_GrIOType: 176 resource->addPendingRead(); 177 resource->addPendingWrite(); 178 break; 179 } 180 } 181 this->release(); 182 fResource = resource; 183 } 184 185 ~GrPendingIOResource() { 186 this->release(); 187 } 188 189 T* get() const { return fResource; } 190 191private: 192 void release() { 193 if (fResource) { 194 switch (IO_TYPE) { 195 case kRead_GrIOType: 196 fResource->completedRead(); 197 break; 198 case kWrite_GrIOType: 199 fResource->completedWrite(); 200 break; 201 case kRW_GrIOType: 202 fResource->completedRead(); 203 fResource->completedWrite(); 204 break; 205 } 206 } 207 } 208 209 T* fResource; 210}; 211#endif 212