| /* | |
| * Copyright 2014 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #ifndef GrGpuResourceRef_DEFINED | |
| #define GrGpuResourceRef_DEFINED | |
| #include "GrGpuResource.h" | |
| #include "GrRenderTarget.h" | |
| #include "GrTexture.h" | |
| #include "SkRefCnt.h" | |
| /** | |
| * This class is intended only for internal use in core Gr code. | |
| * | |
| * Class that wraps a resource referenced by a GrProgramElement or GrDrawState. It manages | |
| * converting refs to pending IO operations. It allows a resource ownership to be in three | |
| * states: | |
| * 1. Owns a single ref | |
| * 2. Owns a single ref and a pending IO operation (read, write, or read-write) | |
| * 3. Owns a single pending IO operation. | |
| * | |
| * It is legal to destroy the GrGpuResourceRef in any of these states. It starts in state | |
| * 1. Calling markPendingIO() converts it from state 1 to state 2. Calling removeRef() goes from | |
| * state 2 to state 3. Calling pendingIOComplete() moves from state 2 to state 1. There is no | |
| * valid way of going from state 3 back to 2 or 1. | |
| * | |
| * Like SkAutoTUnref, its constructor and setter adopt a ref from their caller. | |
| * | |
| * TODO: Once GrDODrawState no longer exists and therefore GrDrawState and GrOptDrawState no | |
| * longer share an instance of this class, attempt to make the resource owned by GrGpuResourceRef | |
| * only settable via the constructor. | |
| */ | |
| class GrGpuResourceRef : SkNoncopyable { | |
| public: | |
| SK_DECLARE_INST_COUNT_ROOT(GrGpuResourceRef); | |
| ~GrGpuResourceRef(); | |
| GrGpuResource* getResource() const { return fResource; } | |
| /** Does this object own a pending read or write on the resource it is wrapping. */ | |
| bool ownsPendingIO() const { return fPendingIO; } | |
| /** Shortcut for calling setResource() with NULL. It cannot be called after markingPendingIO | |
| is called. */ | |
| void reset(); | |
| protected: | |
| GrGpuResourceRef(); | |
| /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as | |
| pending on the resource when markPendingIO is called. */ | |
| GrGpuResourceRef(GrGpuResource*, GrIOType); | |
| /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as | |
| pending on the resource when markPendingIO is called. */ | |
| void setResource(GrGpuResource*, GrIOType); | |
| private: | |
| /** Called by owning GrProgramElement when the program element is first scheduled for | |
| execution. It can only be called once. */ | |
| void markPendingIO() const; | |
| /** Called when the program element/draw state is no longer owned by GrDrawTarget-client code. | |
| This lets the cache know that the drawing code will no longer schedule additional reads or | |
| writes to the resource using the program element or draw state. It can only be called once. | |
| */ | |
| void removeRef() const; | |
| /** Called to indicate that the previous pending IO is complete. Useful when the owning object | |
| still has refs, so it is not about to destroy this GrGpuResourceRef, but its previously | |
| pending executions have been complete. Can only be called if removeRef() was not previously | |
| called. */ | |
| void pendingIOComplete() const; | |
| friend class GrProgramElement; | |
| GrGpuResource* fResource; | |
| mutable bool fOwnRef; | |
| mutable bool fPendingIO; | |
| GrIOType fIOType; | |
| typedef SkNoncopyable INHERITED; | |
| }; | |
| /** | |
| * Templated version of GrGpuResourceRef to enforce type safety. | |
| */ | |
| template <typename T> class GrTGpuResourceRef : public GrGpuResourceRef { | |
| public: | |
| GrTGpuResourceRef() {} | |
| /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as | |
| pending on the resource when markPendingIO is called. */ | |
| GrTGpuResourceRef(T* resource, GrIOType ioType) : INHERITED(resource, ioType) { } | |
| T* get() const { return static_cast<T*>(this->getResource()); } | |
| /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as | |
| pending on the resource when markPendingIO is called. */ | |
| void set(T* resource, GrIOType ioType) { this->setResource(resource, ioType); } | |
| private: | |
| typedef GrGpuResourceRef INHERITED; | |
| }; | |
| // Specializations for GrTexture and GrRenderTarget because they use virtual inheritance. | |
| template<> class GrTGpuResourceRef<GrTexture> : public GrGpuResourceRef { | |
| public: | |
| GrTGpuResourceRef() {} | |
| GrTGpuResourceRef(GrTexture* texture, GrIOType ioType) : INHERITED(texture, ioType) { } | |
| GrTexture* get() const { | |
| GrSurface* surface = static_cast<GrSurface*>(this->getResource()); | |
| if (surface) { | |
| return surface->asTexture(); | |
| } else { | |
| return NULL; | |
| } | |
| } | |
| void set(GrTexture* texture, GrIOType ioType) { this->setResource(texture, ioType); } | |
| private: | |
| typedef GrGpuResourceRef INHERITED; | |
| }; | |
| template<> class GrTGpuResourceRef<GrRenderTarget> : public GrGpuResourceRef { | |
| public: | |
| GrTGpuResourceRef() {} | |
| GrTGpuResourceRef(GrRenderTarget* rt, GrIOType ioType) : INHERITED(rt, ioType) { } | |
| GrRenderTarget* get() const { | |
| GrSurface* surface = static_cast<GrSurface*>(this->getResource()); | |
| if (surface) { | |
| return surface->asRenderTarget(); | |
| } else { | |
| return NULL; | |
| } | |
| } | |
| void set(GrRenderTarget* rt, GrIOType ioType) { this->setResource(rt, ioType); } | |
| private: | |
| typedef GrGpuResourceRef INHERITED; | |
| }; | |
| /** | |
| * This is similar to GrTGpuResourceRef but can only be in the pending IO state. It never owns a | |
| * ref. | |
| */ | |
| template <typename T, GrIOType IO_TYPE> class GrPendingIOResource : SkNoncopyable { | |
| public: | |
| GrPendingIOResource(T* resource = NULL) : fResource(NULL) { | |
| this->reset(resource); | |
| } | |
| void reset(T* resource) { | |
| if (resource) { | |
| switch (IO_TYPE) { | |
| case kRead_GrIOType: | |
| resource->addPendingRead(); | |
| break; | |
| case kWrite_GrIOType: | |
| resource->addPendingWrite(); | |
| break; | |
| case kRW_GrIOType: | |
| resource->addPendingRead(); | |
| resource->addPendingWrite(); | |
| break; | |
| } | |
| } | |
| this->release(); | |
| fResource = resource; | |
| } | |
| ~GrPendingIOResource() { | |
| this->release(); | |
| } | |
| operator bool() const { return SkToBool(fResource); } | |
| T* get() const { return fResource; } | |
| private: | |
| void release() { | |
| if (fResource) { | |
| switch (IO_TYPE) { | |
| case kRead_GrIOType: | |
| fResource->completedRead(); | |
| break; | |
| case kWrite_GrIOType: | |
| fResource->completedWrite(); | |
| break; | |
| case kRW_GrIOType: | |
| fResource->completedRead(); | |
| fResource->completedWrite(); | |
| break; | |
| } | |
| } | |
| } | |
| T* fResource; | |
| }; | |
| #endif |