| Index: include/gpu/GrProgramElement.h
|
| diff --git a/include/gpu/GrProgramElement.h b/include/gpu/GrProgramElement.h
|
| index e788486b5cc74d0d4c898268d7754d3e3628b3ac..8305c5027b0f17a3decb86049169b896583ba8fe 100644
|
| --- a/include/gpu/GrProgramElement.h
|
| +++ b/include/gpu/GrProgramElement.h
|
| @@ -14,14 +14,32 @@
|
| class GrGpuResourceRef;
|
|
|
| /**
|
| - * Base class for GrProcessor. GrDrawState uses this to manage
|
| - * transitioning a GrProcessor from being owned by a client to being scheduled for execution. It
|
| - * converts resources owned by the effect from being ref'ed to having pending reads/writes.
|
| + * Base class for GrProcessor. This exists to manage transitioning a GrProcessor from being owned by
|
| + * a client to being scheduled for execution. While a GrProcessor is ref'ed by drawing code its
|
| + * GrGpu resources must also be ref'ed to prevent incorrectly recycling them through the cache.
|
| + * However, once the GrProcessor is baked into a GrPipeline and the drawing code has stopped ref'ing
|
| + * it, it's internal resources can be recycled in some cases.
|
| *
|
| - * All GrGpuResource objects owned by a GrProgramElement or derived classes (either directly or
|
| - * indirectly) must be wrapped in a GrGpuResourceRef and registered with the GrProgramElement using
|
| - * addGpuResource(). This allows the regular refs to be converted to pending IO events
|
| - * when the program element is scheduled for deferred execution.
|
| + * We track this using two types of refs on GrProgramElement. A regular ref is owned by any client
|
| + * that may continue to issue draws that use the GrProgramElement. The GrPipeline owns "pending
|
| + * executions" instead of refs. A pending execution is cleared by ~GrPipeline().
|
| + *
|
| + * While a GrProgramElement is ref'ed any resources it owns are also ref'ed. However, once it gets
|
| + * into the state where it has pending executions AND no refs then it converts its ownership of
|
| + * its GrGpuResources from refs to pending IOs. The pending IOs allow the cache to track when it is
|
| + * safe to recycle a resource even though we still have buffered GrBatches that read or write to the
|
| + * the resource.
|
| + *
|
| + * To make this work all GrGpuResource objects owned by a GrProgramElement or derived classes
|
| + * (either directly or indirectly) must be wrapped in a GrGpuResourceRef and registered with the
|
| + * GrProgramElement using addGpuResource(). This allows the regular refs to be converted to pending
|
| + * IO events when the program element is scheduled for deferred execution.
|
| + *
|
| + * Moreover, a GrProgramElement that in turn owns other GrProgramElements must convert its ownership
|
| + * of its children to pending executions when its ref count reaches zero so that the GrGpuResources
|
| + * owned by the children GrProgramElements are correctly converted from ownership by ref to
|
| + * ownership by pending IO. Any GrProgramElement hierarchy is managed by subclasses which must
|
| + * implement notifyRefCntIsZero() in order to convert refs of children to pending executions.
|
| */
|
| class GrProgramElement : public SkNoncopyable {
|
| public:
|
| @@ -44,6 +62,7 @@ public:
|
| this->validate();
|
| --fRefCnt;
|
| if (0 == fRefCnt) {
|
| + this->notifyRefCntIsZero();
|
| if (0 == fPendingExecutions) {
|
| delete this;
|
| return;
|
| @@ -78,9 +97,6 @@ protected:
|
| fGpuResources.push_back(res);
|
| }
|
|
|
| -private:
|
| - static uint32_t CreateUniqueID();
|
| -
|
| void addPendingExecution() const {
|
| this->validate();
|
| SkASSERT(fRefCnt > 0);
|
| @@ -105,6 +121,13 @@ private:
|
| this->validate();
|
| }
|
|
|
| +private:
|
| + /** This will be called when the ref cnt is zero. The object may or may not have pending
|
| + executions. */
|
| + virtual void notifyRefCntIsZero() const = 0;
|
| +
|
| + static uint32_t CreateUniqueID();
|
| +
|
| void removeRefs() const;
|
| void addPendingIOs() const;
|
| void pendingIOComplete() const;
|
|
|