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