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 GrProgramElement_DEFINED
      9 #define GrProgramElement_DEFINED
     10 
     11 #include "../private/SkTArray.h"
     12 #include "SkRefCnt.h"
     13 
     14 /**
     15  * Note: We are converting GrProcessor from ref counting to a single owner model using move
     16  * semantics. This class will be removed.
     17  *
     18  * This is used to track "refs" for two separate types GrProcessor ownership. A regular ref is owned
     19  * by any client that may continue to issue draws that use the GrProgramElement. A recorded op or
     20  * GrPipeline uses "pending executions" instead of refs. A pending execution is cleared after the
     21  * draw is executed (or aborted).
     22  *
     23  * While a GrProgramElement is ref'ed any resources it owns are also ref'ed. However, once it gets
     24  * into the state where it has pending executions AND no refs then it converts its ownership of
     25  * its GrGpuResources from refs to pending IOs. The pending IOs allow the cache to track when it is
     26  * safe to recycle a resource even though we still have buffered GrOps that read or write to the
     27  * the resource.
     28  *
     29  * To make this work the subclass GrProcessor implements addPendingIOs, removeRefs, and
     30  * pendingIOComplete. addPendingIOs adds pending reads/writes to GrGpuResources owned by the
     31  * processor as appropriate when the processor is recorded in a GrOpList. removeRefs is called when
     32  * the ref count reaches 0 and the GrProcessor is only owned by "pending executions".
     33  * pendingIOComplete occurs if the resource is still owned by a ref but all recorded draws have been
     34  * completed. Whenever pending executions and refs reach zero the processor is deleted.
     35  *
     36  * The GrProcessor may also implement notifyRefCntIsZero in order to change its ownership of child
     37  * processors from ref to pending execution when the processor is first owned exclusively in pending
     38  * execution mode.
     39  */
     40 class GrProgramElement : public SkNoncopyable {
     41 public:
     42     virtual ~GrProgramElement() {
     43         // fRefCnt can be one when an effect is created statically using GR_CREATE_STATIC_EFFECT
     44         SkASSERT((0 == fRefCnt || 1 == fRefCnt) && 0 == fPendingExecutions);
     45         // Set to invalid values.
     46         SkDEBUGCODE(fRefCnt = fPendingExecutions = -10;)
     47     }
     48 
     49     void ref() const {
     50         this->validate();
     51         // Once the ref cnt reaches zero it should never be ref'ed again.
     52         SkASSERT(fRefCnt > 0);
     53         ++fRefCnt;
     54         this->validate();
     55     }
     56 
     57     void unref() const {
     58         this->validate();
     59         --fRefCnt;
     60         if (0 == fRefCnt) {
     61             this->notifyRefCntIsZero();
     62             if (0 == fPendingExecutions) {
     63                 delete this;
     64                 return;
     65             } else {
     66                 this->removeRefs();
     67             }
     68         }
     69         this->validate();
     70     }
     71 
     72     void validate() const {
     73 #ifdef SK_DEBUG
     74         SkASSERT(fRefCnt >= 0);
     75         SkASSERT(fPendingExecutions >= 0);
     76         SkASSERT(fRefCnt + fPendingExecutions > 0);
     77 #endif
     78     }
     79 
     80 protected:
     81     GrProgramElement() : fRefCnt(1), fPendingExecutions(0) {}
     82 
     83     void addPendingExecution() const {
     84         this->validate();
     85         if (0 == fPendingExecutions) {
     86             this->addPendingIOs();
     87         }
     88         ++fPendingExecutions;
     89         this->validate();
     90     }
     91 
     92     void completedExecution() const {
     93         this->validate();
     94         --fPendingExecutions;
     95         if (0 == fPendingExecutions) {
     96             if (0 == fRefCnt) {
     97                 delete this;
     98                 return;
     99             } else {
    100                 this->pendingIOComplete();
    101             }
    102         }
    103         this->validate();
    104     }
    105 
    106 private:
    107     virtual void addPendingIOs() const = 0;
    108     virtual void removeRefs() const = 0;
    109     virtual void pendingIOComplete() const = 0;
    110 
    111     /** This will be called when the ref cnt is zero. The object may or may not have pending
    112         executions. */
    113     virtual void notifyRefCntIsZero() const = 0;
    114 
    115     mutable int32_t fRefCnt;
    116     // Count of deferred executions not yet issued to the 3D API.
    117     mutable int32_t fPendingExecutions;
    118 
    119     // Only these classes can access addPendingExecution() and completedExecution().
    120     template <typename T> friend class GrPendingProgramElement;
    121     friend class GrProcessorSet;
    122 
    123     typedef SkNoncopyable INHERITED;
    124 };
    125 
    126 #endif
    127