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 "SkRefCnt.h" 13 14 /** 15 * This class is intended only for internal use in core Gr code. 16 * 17 * Class that wraps a resource referenced by a GrProgramElement or GrDrawState. It manages 18 * converting refs to pending IO operations. It allows a resource ownership to be in three 19 * states: 20 * 1. Owns a single ref 21 * 2. Owns a single ref and a pending IO operation (read, write, or read-write) 22 * 3. Owns a single pending IO operation. 23 * 24 * It is legal to destroy the GrGpuResourceRef in any of these states. It starts in state 25 * 1. Calling markPendingIO() converts it from state 1 to state 2. Calling removeRef() goes from 26 * state 2 to state 3. Calling pendingIOComplete() moves from state 2 to state 1. There is no 27 * valid way of going from state 3 back to 2 or 1. 28 * 29 * Like SkAutoTUnref, its constructor and setter adopt a ref from their caller. 30 * 31 * TODO: Once GrDODrawState no longer exists and therefore GrDrawState and GrOptDrawState no 32 * longer share an instance of this class, attempt to make the resource owned by GrGpuResourceRef 33 * only settable via the constructor. 34 */ 35 class GrGpuResourceRef : SkNoncopyable { 36 public: 37 SK_DECLARE_INST_COUNT_ROOT(GrGpuResourceRef); 38 39 ~GrGpuResourceRef(); 40 41 GrGpuResource* getResource() const { return fResource; } 42 43 /** Does this object own a pending read or write on the resource it is wrapping. */ 44 bool ownsPendingIO() const { return fPendingIO; } 45 46 /** Shortcut for calling setResource() with NULL. It cannot be called after markingPendingIO 47 is called. */ 48 void reset(); 49 50 protected: 51 GrGpuResourceRef(); 52 53 /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as 54 pending on the resource when markPendingIO is called. */ 55 GrGpuResourceRef(GrGpuResource*, GrIORef::IOType); 56 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. */ 59 void setResource(GrGpuResource*, GrIORef::IOType); 60 61 private: 62 /** Called by owning GrProgramElement when the program element is first scheduled for 63 execution. It can only be called once. */ 64 void markPendingIO() const; 65 66 /** Called when the program element/draw state is no longer owned by GrDrawTarget-client code. 67 This lets the cache know that the drawing code will no longer schedule additional reads or 68 writes to the resource using the program element or draw state. It can only be called once. 69 */ 70 void removeRef() const; 71 72 /** Called to indicate that the previous pending IO is complete. Useful when the owning object 73 still has refs, so it is not about to destroy this GrGpuResourceRef, but its previously 74 pending executions have been complete. Can only be called if removeRef() was not previously 75 called. */ 76 void pendingIOComplete() const; 77 78 friend class GrRODrawState; 79 friend class GrProgramElement; 80 81 GrGpuResource* fResource; 82 mutable bool fOwnRef; 83 mutable bool fPendingIO; 84 GrIORef::IOType fIOType; 85 86 typedef SkNoncopyable INHERITED; 87 }; 88 89 /** 90 * Templated version of GrGpuResourceRef to enforce type safety. 91 */ 92 template <typename T> class GrTGpuResourceRef : public GrGpuResourceRef { 93 public: 94 GrTGpuResourceRef() {} 95 96 /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as 97 pending on the resource when markPendingIO is called. */ 98 GrTGpuResourceRef(T* resource, GrIORef::IOType ioType) : INHERITED(resource, ioType) {} 99 100 T* get() const { return static_cast<T*>(this->getResource()); } 101 102 /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as 103 pending on the resource when markPendingIO is called. */ 104 void set(T* resource, GrIORef::IOType ioType) { this->setResource(resource, ioType); } 105 106 private: 107 typedef GrGpuResourceRef INHERITED; 108 }; 109 110 /** 111 * This is similar to GrTGpuResourceRef but can only be in the pending IO state. It never owns a 112 * ref. 113 */ 114 template <typename T, GrIORef::IOType IO_TYPE> class GrPendingIOResource : SkNoncopyable { 115 public: 116 GrPendingIOResource(T* resource) : fResource(resource) { 117 if (NULL != fResource) { 118 switch (IO_TYPE) { 119 case GrIORef::kRead_IOType: 120 fResource->addPendingRead(); 121 break; 122 case GrIORef::kWrite_IOType: 123 fResource->addPendingWrite(); 124 break; 125 case GrIORef::kRW_IOType: 126 fResource->addPendingRead(); 127 fResource->addPendingWrite(); 128 break; 129 } 130 } 131 } 132 133 ~GrPendingIOResource() { 134 if (NULL != fResource) { 135 switch (IO_TYPE) { 136 case GrIORef::kRead_IOType: 137 fResource->completedRead(); 138 break; 139 case GrIORef::kWrite_IOType: 140 fResource->completedWrite(); 141 break; 142 case GrIORef::kRW_IOType: 143 fResource->completedRead(); 144 fResource->completedWrite(); 145 break; 146 } 147 } 148 } 149 150 T* get() const { return fResource; } 151 152 private: 153 T* fResource; 154 }; 155 #endif 156