195740981c36266e4595ddde2264aa38e3c7e2d02bsalomon/*
295740981c36266e4595ddde2264aa38e3c7e2d02bsalomon * Copyright 2014 Google Inc.
395740981c36266e4595ddde2264aa38e3c7e2d02bsalomon *
495740981c36266e4595ddde2264aa38e3c7e2d02bsalomon * Use of this source code is governed by a BSD-style license that can be
595740981c36266e4595ddde2264aa38e3c7e2d02bsalomon * found in the LICENSE file.
695740981c36266e4595ddde2264aa38e3c7e2d02bsalomon */
795740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
895740981c36266e4595ddde2264aa38e3c7e2d02bsalomon#ifndef GrProgramElement_DEFINED
995740981c36266e4595ddde2264aa38e3c7e2d02bsalomon#define GrProgramElement_DEFINED
1095740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
1195740981c36266e4595ddde2264aa38e3c7e2d02bsalomon#include "SkRefCnt.h"
1295740981c36266e4595ddde2264aa38e3c7e2d02bsalomon#include "SkTArray.h"
1395740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
14f96ba02513eadd9fa24d75396ec9f2d6682e464cbsalomonclass GrGpuResourceRef;
1595740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
1695740981c36266e4595ddde2264aa38e3c7e2d02bsalomon/**
17b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt * Base class for GrProcessor. GrDrawState uses this to manage
18b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt * transitioning a GrProcessor from being owned by a client to being scheduled for execution. It
1995740981c36266e4595ddde2264aa38e3c7e2d02bsalomon * converts resources owned by the effect from being ref'ed to having pending reads/writes.
2095740981c36266e4595ddde2264aa38e3c7e2d02bsalomon *
2195740981c36266e4595ddde2264aa38e3c7e2d02bsalomon * All GrGpuResource objects owned by a GrProgramElement or derived classes (either directly or
22f96ba02513eadd9fa24d75396ec9f2d6682e464cbsalomon * indirectly) must be wrapped in a GrGpuResourceRef and registered with the GrProgramElement using
23f96ba02513eadd9fa24d75396ec9f2d6682e464cbsalomon * addGpuResource(). This allows the regular refs to be converted to pending IO events
2495740981c36266e4595ddde2264aa38e3c7e2d02bsalomon * when the program element is scheduled for deferred execution.
2595740981c36266e4595ddde2264aa38e3c7e2d02bsalomon */
2695740981c36266e4595ddde2264aa38e3c7e2d02bsalomonclass GrProgramElement : public SkNoncopyable {
2795740981c36266e4595ddde2264aa38e3c7e2d02bsalomonpublic:
286f07665768dc84453316e7b2bbd6049576764cb1mtklein    SK_DECLARE_INST_COUNT(GrProgramElement)
2995740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
3095740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    virtual ~GrProgramElement() {
3195740981c36266e4595ddde2264aa38e3c7e2d02bsalomon        // fRefCnt can be one when an effect is created statically using GR_CREATE_STATIC_EFFECT
3295740981c36266e4595ddde2264aa38e3c7e2d02bsalomon        SkASSERT((0 == fRefCnt || 1 == fRefCnt) && 0 == fPendingExecutions);
3395740981c36266e4595ddde2264aa38e3c7e2d02bsalomon        // Set to invalid values.
3495740981c36266e4595ddde2264aa38e3c7e2d02bsalomon        SkDEBUGCODE(fRefCnt = fPendingExecutions = -10;)
3595740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    }
3695740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
3795740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    void ref() const {
38ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon        this->validate();
3995740981c36266e4595ddde2264aa38e3c7e2d02bsalomon        // Once the ref cnt reaches zero it should never be ref'ed again.
4095740981c36266e4595ddde2264aa38e3c7e2d02bsalomon        SkASSERT(fRefCnt > 0);
4195740981c36266e4595ddde2264aa38e3c7e2d02bsalomon        ++fRefCnt;
42ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon        this->validate();
4395740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    }
4495740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
4595740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    void unref() const {
4695740981c36266e4595ddde2264aa38e3c7e2d02bsalomon        this->validate();
4795740981c36266e4595ddde2264aa38e3c7e2d02bsalomon        --fRefCnt;
48d012877a6d30ae768f9ccf3239ba09d730cbb6a5bsalomon        if (0 == fRefCnt) {
49d012877a6d30ae768f9ccf3239ba09d730cbb6a5bsalomon            if (0 == fPendingExecutions) {
50d012877a6d30ae768f9ccf3239ba09d730cbb6a5bsalomon                SkDELETE(this);
51ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon                return;
52d012877a6d30ae768f9ccf3239ba09d730cbb6a5bsalomon            } else {
53d012877a6d30ae768f9ccf3239ba09d730cbb6a5bsalomon                this->removeRefs();
54d012877a6d30ae768f9ccf3239ba09d730cbb6a5bsalomon            }
5595740981c36266e4595ddde2264aa38e3c7e2d02bsalomon        }
56ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon        this->validate();
5795740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    }
5895740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
5952e9d63f7110ac691609660342cdab32082a4235bsalomon    /**
6052e9d63f7110ac691609660342cdab32082a4235bsalomon     * Gets an id that is unique for this GrProgramElement object. This will never return 0.
6152e9d63f7110ac691609660342cdab32082a4235bsalomon     */
6252e9d63f7110ac691609660342cdab32082a4235bsalomon    uint32_t getUniqueID() const { return fUniqueID; }
6352e9d63f7110ac691609660342cdab32082a4235bsalomon
6495740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    void validate() const {
6595740981c36266e4595ddde2264aa38e3c7e2d02bsalomon#ifdef SK_DEBUG
6695740981c36266e4595ddde2264aa38e3c7e2d02bsalomon        SkASSERT(fRefCnt >= 0);
6795740981c36266e4595ddde2264aa38e3c7e2d02bsalomon        SkASSERT(fPendingExecutions >= 0);
6895740981c36266e4595ddde2264aa38e3c7e2d02bsalomon        SkASSERT(fRefCnt + fPendingExecutions > 0);
6995740981c36266e4595ddde2264aa38e3c7e2d02bsalomon#endif
7095740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    }
7195740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
7295740981c36266e4595ddde2264aa38e3c7e2d02bsalomonprotected:
7352e9d63f7110ac691609660342cdab32082a4235bsalomon    GrProgramElement() : fRefCnt(1), fPendingExecutions(0), fUniqueID(CreateUniqueID()) {}
7495740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
7595740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    /** Subclasses registers their resources using this function. It is assumed the GrProgramResouce
7695740981c36266e4595ddde2264aa38e3c7e2d02bsalomon        is and will remain owned by the subclass and this function will retain a raw ptr. Once a
77f96ba02513eadd9fa24d75396ec9f2d6682e464cbsalomon        GrGpuResourceRef is registered its setResource must not be called.
7895740981c36266e4595ddde2264aa38e3c7e2d02bsalomon     */
79f96ba02513eadd9fa24d75396ec9f2d6682e464cbsalomon    void addGpuResource(const GrGpuResourceRef* res) {
80f96ba02513eadd9fa24d75396ec9f2d6682e464cbsalomon        fGpuResources.push_back(res);
8195740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    }
8295740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
8395740981c36266e4595ddde2264aa38e3c7e2d02bsalomonprivate:
8452e9d63f7110ac691609660342cdab32082a4235bsalomon    static uint32_t CreateUniqueID();
8552e9d63f7110ac691609660342cdab32082a4235bsalomon
86ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon    void addPendingExecution() const {
87ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon        this->validate();
88ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon        SkASSERT(fRefCnt > 0);
89ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon        if (0 == fPendingExecutions) {
90ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon            this->addPendingIOs();
91ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon        }
92ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon        ++fPendingExecutions;
93ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon        this->validate();
94ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon    }
9595740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
96ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon    void completedExecution() const {
97ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon        this->validate();
98ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon        --fPendingExecutions;
99ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon        if (0 == fPendingExecutions) {
100ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon            if (0 == fRefCnt) {
101ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon                SkDELETE(this);
102ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon                return;
103ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon            } else {
104ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon                this->pendingIOComplete();
105ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon            }
106ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon        }
107ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon        this->validate();
108ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon    }
10995740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
110d012877a6d30ae768f9ccf3239ba09d730cbb6a5bsalomon    void removeRefs() const;
111ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon    void addPendingIOs() const;
112ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon    void pendingIOComplete() const;
113d012877a6d30ae768f9ccf3239ba09d730cbb6a5bsalomon
11495740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    mutable int32_t fRefCnt;
11595740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    // Count of deferred executions not yet issued to the 3D API.
11695740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    mutable int32_t fPendingExecutions;
11752e9d63f7110ac691609660342cdab32082a4235bsalomon    uint32_t        fUniqueID;
11895740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
119f96ba02513eadd9fa24d75396ec9f2d6682e464cbsalomon    SkSTArray<4, const GrGpuResourceRef*, true> fGpuResources;
12095740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
121ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon    // Only this class can access addPendingExecution() and completedExecution().
122ae59b77612c42ff6b793dc33e3d115e6a5db34ccbsalomon    template <typename T> friend class GrPendingProgramElement;
12395740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
12495740981c36266e4595ddde2264aa38e3c7e2d02bsalomon    typedef SkNoncopyable INHERITED;
12595740981c36266e4595ddde2264aa38e3c7e2d02bsalomon};
12695740981c36266e4595ddde2264aa38e3c7e2d02bsalomon
12795740981c36266e4595ddde2264aa38e3c7e2d02bsalomon#endif
128