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 "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