| /* |
| * 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: |
| ~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(); |
| } |
| |
| explicit operator bool() const { return SkToBool(fResource); } |
| |
| bool operator==(const GrPendingIOResource& other) const { |
| return fResource == other.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 |