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(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 GrProgramElement; 81 82 GrGpuResource* fResource; 83 mutable bool fOwnRef; 84 mutable bool fPendingIO; 85 GrIOType fIOType; 86 87 typedef SkNoncopyable INHERITED; 88}; 89 90/** 91 * Templated version of GrGpuResourceRef to enforce type safety. 92 */ 93template <typename T> class GrTGpuResourceRef : public GrGpuResourceRef { 94public: 95 GrTGpuResourceRef() {} 96 97 /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as 98 pending on the resource when markPendingIO is called. */ 99 GrTGpuResourceRef(T* resource, GrIOType ioType) : INHERITED(resource, ioType) { } 100 101 T* get() const { return static_cast<T*>(this->getResource()); } 102 103 /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as 104 pending on the resource when markPendingIO is called. */ 105 void set(T* resource, GrIOType ioType) { this->setResource(resource, ioType); } 106 107private: 108 typedef GrGpuResourceRef INHERITED; 109}; 110 111// Specializations for GrTexture and GrRenderTarget because they use virtual inheritance. 112template<> class GrTGpuResourceRef<GrTexture> : public GrGpuResourceRef { 113public: 114 GrTGpuResourceRef() {} 115 116 GrTGpuResourceRef(GrTexture* texture, GrIOType ioType) : INHERITED(texture, ioType) { } 117 118 GrTexture* get() const { 119 GrSurface* surface = static_cast<GrSurface*>(this->getResource()); 120 if (surface) { 121 return surface->asTexture(); 122 } else { 123 return NULL; 124 } 125 } 126 127 void set(GrTexture* texture, GrIOType ioType) { this->setResource(texture, ioType); } 128 129private: 130 typedef GrGpuResourceRef INHERITED; 131}; 132 133template<> class GrTGpuResourceRef<GrRenderTarget> : public GrGpuResourceRef { 134public: 135 GrTGpuResourceRef() {} 136 137 GrTGpuResourceRef(GrRenderTarget* rt, GrIOType ioType) : INHERITED(rt, ioType) { } 138 139 GrRenderTarget* get() const { 140 GrSurface* surface = static_cast<GrSurface*>(this->getResource()); 141 if (surface) { 142 return surface->asRenderTarget(); 143 } else { 144 return NULL; 145 } 146 } 147 148 void set(GrRenderTarget* rt, GrIOType ioType) { this->setResource(rt, ioType); } 149 150private: 151 typedef GrGpuResourceRef INHERITED; 152}; 153 154/** 155 * This is similar to GrTGpuResourceRef but can only be in the pending IO state. It never owns a 156 * ref. 157 */ 158template <typename T, GrIOType IO_TYPE> class GrPendingIOResource : SkNoncopyable { 159public: 160 GrPendingIOResource(T* resource = NULL) : fResource(NULL) { 161 this->reset(resource); 162 } 163 164 void reset(T* resource) { 165 if (resource) { 166 switch (IO_TYPE) { 167 case kRead_GrIOType: 168 resource->addPendingRead(); 169 break; 170 case kWrite_GrIOType: 171 resource->addPendingWrite(); 172 break; 173 case kRW_GrIOType: 174 resource->addPendingRead(); 175 resource->addPendingWrite(); 176 break; 177 } 178 } 179 this->release(); 180 fResource = resource; 181 } 182 183 ~GrPendingIOResource() { 184 this->release(); 185 } 186 187 operator bool() const { return SkToBool(fResource); } 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