Home | History | Annotate | Download | only in gpu
      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 sk_sp, 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  */
     37 class GrGpuResourceRef : SkNoncopyable {
     38 public:
     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     /** What type of IO does this represent? This is independent of whether a normal ref or a
     47         pending IO is currently held. */
     48     GrIOType ioType() const { return fIOType; }
     49 
     50     /** Shortcut for calling setResource() with NULL. It cannot be called after markingPendingIO
     51         is called. */
     52     void reset();
     53 
     54 protected:
     55     GrGpuResourceRef();
     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     GrGpuResourceRef(GrGpuResource*, GrIOType);
     60 
     61     /** Adopts a ref from the caller. ioType expresses what type of IO operations will be marked as
     62         pending on the resource when markPendingIO is called. */
     63     void setResource(GrGpuResource*, GrIOType);
     64 
     65 private:
     66     /** Called by owning GrProgramElement when the program element is first scheduled for
     67         execution. It can only be called once. */
     68     void markPendingIO() const;
     69 
     70     /** Called when the program element/draw state is no longer owned by GrOpList-client code.
     71         This lets the cache know that the drawing code will no longer schedule additional reads or
     72         writes to the resource using the program element or draw state. It can only be called once.
     73       */
     74     void removeRef() const;
     75 
     76     /** Called to indicate that the previous pending IO is complete. Useful when the owning object
     77         still has refs, so it is not about to destroy this GrGpuResourceRef, but its previously
     78         pending executions have been complete. Can only be called if removeRef() was not previously
     79         called. */
     80     void pendingIOComplete() const;
     81 
     82     friend class GrProcessor;
     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  */
     95 template <typename T> class GrTGpuResourceRef : public GrGpuResourceRef {
     96 public:
     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 
    109 private:
    110     typedef GrGpuResourceRef INHERITED;
    111 };
    112 
    113 // Specializations for GrTexture and GrRenderTarget because they use virtual inheritance.
    114 template<> class GrTGpuResourceRef<GrTexture> : public GrGpuResourceRef {
    115 public:
    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 
    131 private:
    132     typedef GrGpuResourceRef INHERITED;
    133 };
    134 
    135 template<> class GrTGpuResourceRef<GrRenderTarget> : public GrGpuResourceRef {
    136 public:
    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 
    152 private:
    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  */
    160 template <typename T, GrIOType IO_TYPE> class GrPendingIOResource : SkNoncopyable {
    161 public:
    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     explicit operator bool() const { return SkToBool(fResource); }
    190 
    191     bool operator==(const GrPendingIOResource& other) const {
    192         return fResource == other.fResource;
    193     }
    194 
    195     T* get() const { return fResource; }
    196 
    197 private:
    198     void release() {
    199         if (fResource) {
    200             switch (IO_TYPE) {
    201                 case kRead_GrIOType:
    202                     fResource->completedRead();
    203                     break;
    204                 case kWrite_GrIOType:
    205                     fResource->completedWrite();
    206                     break;
    207                 case kRW_GrIOType:
    208                     fResource->completedRead();
    209                     fResource->completedWrite();
    210                     break;
    211             }
    212         }
    213     }
    214 
    215     T* fResource;
    216 };
    217 #endif
    218