Wrap GrEffects in GrEffectPtr.
This is the first step towards automatic recycling of scratch resouces in the cache via ref-cnts.
R=robertphillips@google.com
Review URL: https://codereview.appspot.com/7092061
git-svn-id: http://skia.googlecode.com/svn/trunk@7222 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/gpu/GrEffect.h b/include/gpu/GrEffect.h
index 5fca4b2..431159c 100644
--- a/include/gpu/GrEffect.h
+++ b/include/gpu/GrEffect.h
@@ -17,19 +17,52 @@
class GrBackendEffectFactory;
class GrContext;
+class GrEffect;
class SkString;
+/**
+ * A Wrapper class for GrEffect. Its ref-count will track owners that may use effects to enqueue
+ * new draw operations separately from ownership within a deferred drawing queue. When the
+ * GrEffectRef ref count reaches zero the scratch GrResources owned by the effect can be recycled
+ * in service of later draws. However, the deferred draw queue may still own direct references to
+ * the underlying GrEffect.
+ */
+class GrEffectRef : public SkRefCnt {
+public:
+ SK_DECLARE_INST_COUNT(GrEffectRef);
+
+ GrEffect* get() { return fEffect; }
+ const GrEffect* get() const { return fEffect; }
+
+ void* operator new(size_t size);
+ void operator delete(void* target);
+
+private:
+ friend GrEffect; // to construct these
+
+ explicit GrEffectRef(GrEffect* effect);
+
+ virtual ~GrEffectRef();
+
+ GrEffect* fEffect;
+
+ typedef SkRefCnt INHERITED;
+};
+
/** Provides custom vertex shader, fragment shader, uniform data for a particular stage of the
Ganesh shading pipeline.
Subclasses must have a function that produces a human-readable name:
static const char* Name();
GrEffect objects *must* be immutable: after being constructed, their fields may not change.
+
+ GrEffect subclass objects should be created by factory functions that return GrEffectRef.
+ There is no public way to wrap a GrEffect in a GrEffectRef. Thus, a factory should be a static
+ member function of a GrEffect subclass.
*/
class GrEffect : public GrRefCnt {
public:
SK_DECLARE_INST_COUNT(GrEffect)
- GrEffect() {};
virtual ~GrEffect();
/**
@@ -120,9 +153,36 @@
*/
void addTextureAccess(const GrTextureAccess* textureAccess);
+ GrEffect() : fEffectPtr(NULL) {};
+
+ /** This should be called by GrEffect subclass factories */
+ static GrEffectRef* CreateEffectPtr(GrEffect* effect) {
+ if (NULL == effect->fEffectPtr) {
+ effect->fEffectPtr = SkNEW_ARGS(GrEffectRef, (effect));
+ } else {
+ effect->fEffectPtr->ref();
+ GrCrash("This function should only be called once per effect currently.");
+ }
+ return effect->fEffectPtr;
+ }
+
private:
- SkSTArray<4, const GrTextureAccess*, true> fTextureAccesses;
+ void effectPtrDestroyed() {
+ fEffectPtr = NULL;
+ }
+
+ friend GrEffectRef; // to call GrEffectRef destroyed
+
+ SkSTArray<4, const GrTextureAccess*, true> fTextureAccesses;
+ GrEffectRef* fEffectPtr;
+
typedef GrRefCnt INHERITED;
};
+inline GrEffectRef::GrEffectRef(GrEffect* effect) {
+ GrAssert(NULL != effect);
+ effect->ref();
+ fEffect = effect;
+}
+
#endif
diff --git a/include/gpu/GrEffectStage.h b/include/gpu/GrEffectStage.h
index e42f198..0b532d6 100644
--- a/include/gpu/GrEffectStage.h
+++ b/include/gpu/GrEffectStage.h
@@ -22,28 +22,28 @@
public:
GrEffectStage()
- : fEffect (NULL) {
+ : fEffectPtr (NULL) {
GR_DEBUGCODE(fSavedCoordChangeCnt = 0;)
}
~GrEffectStage() {
- GrSafeUnref(fEffect);
+ GrSafeUnref(fEffectPtr);
GrAssert(0 == fSavedCoordChangeCnt);
}
bool operator ==(const GrEffectStage& other) const {
// first handle cases where one or the other has no effect
- if (NULL == fEffect) {
- return NULL == other.fEffect;
- } else if (NULL == other.fEffect) {
+ if (NULL == fEffectPtr) {
+ return NULL == other.fEffectPtr;
+ } else if (NULL == other.fEffectPtr) {
return false;
}
- if (fEffect->getFactory() != other.fEffect->getFactory()) {
+ if (this->getEffect()->getFactory() != other.getEffect()->getFactory()) {
return false;
}
- if (!fEffect->isEqual(*other.fEffect)) {
+ if (!this->getEffect()->isEqual(*other.getEffect())) {
return false;
}
@@ -53,8 +53,8 @@
bool operator !=(const GrEffectStage& s) const { return !(*this == s); }
GrEffectStage& operator =(const GrEffectStage& other) {
- GrSafeAssign(fEffect, other.fEffect);
- if (NULL != fEffect) {
+ GrSafeAssign(fEffectPtr, other.fEffectPtr);
+ if (NULL != fEffectPtr) {
fCoordChangeMatrix = other.fCoordChangeMatrix;
}
return *this;
@@ -70,7 +70,7 @@
class SavedCoordChange {
private:
SkMatrix fCoordChangeMatrix;
- GR_DEBUGCODE(mutable SkAutoTUnref<const GrEffect> fEffect;)
+ GR_DEBUGCODE(mutable SkAutoTUnref<const GrEffectRef> fEffectPtr;)
friend class GrEffectStage;
};
@@ -83,9 +83,9 @@
*/
void saveCoordChange(SavedCoordChange* savedCoordChange) const {
savedCoordChange->fCoordChangeMatrix = fCoordChangeMatrix;
- GrAssert(NULL == savedCoordChange->fEffect.get());
- GR_DEBUGCODE(GrSafeRef(fEffect);)
- GR_DEBUGCODE(savedCoordChange->fEffect.reset(fEffect);)
+ GrAssert(NULL == savedCoordChange->fEffectPtr.get());
+ GR_DEBUGCODE(GrSafeRef(fEffectPtr);)
+ GR_DEBUGCODE(savedCoordChange->fEffectPtr.reset(fEffectPtr);)
GR_DEBUGCODE(++fSavedCoordChangeCnt);
}
@@ -94,9 +94,9 @@
*/
void restoreCoordChange(const SavedCoordChange& savedCoordChange) {
fCoordChangeMatrix = savedCoordChange.fCoordChangeMatrix;
- GrAssert(savedCoordChange.fEffect.get() == fEffect);
+ GrAssert(savedCoordChange.fEffectPtr.get() == fEffectPtr);
GR_DEBUGCODE(--fSavedCoordChangeCnt);
- GR_DEBUGCODE(savedCoordChange.fEffect.reset(NULL);)
+ GR_DEBUGCODE(savedCoordChange.fEffectPtr.reset(NULL);)
}
/**
@@ -106,21 +106,28 @@
const SkMatrix& getCoordChangeMatrix() const { return fCoordChangeMatrix; }
void reset() {
- GrSafeSetNull(fEffect);
+ GrSafeSetNull(fEffectPtr);
}
- const GrEffect* setEffect(const GrEffect* effect) {
+ const GrEffectRef* setEffect(const GrEffectRef* effectPtr) {
GrAssert(0 == fSavedCoordChangeCnt);
- GrSafeAssign(fEffect, effect);
+ GrSafeAssign(fEffectPtr, effectPtr);
fCoordChangeMatrix.reset();
- return effect;
+ return effectPtr;
}
- const GrEffect* getEffect() const { return fEffect; }
+ // TODO: Push GrEffectRef deeper and make this getter return it rather than GrEffect.
+ const GrEffect* getEffect() const {
+ if (NULL != fEffectPtr) {
+ return fEffectPtr->get();
+ } else {
+ return NULL;
+ }
+ }
private:
SkMatrix fCoordChangeMatrix;
- const GrEffect* fEffect;
+ const GrEffectRef* fEffectPtr;
GR_DEBUGCODE(mutable int fSavedCoordChangeCnt;)
};
diff --git a/include/gpu/GrEffectUnitTest.h b/include/gpu/GrEffectUnitTest.h
index 8cc2689..51fa637 100644
--- a/include/gpu/GrEffectUnitTest.h
+++ b/include/gpu/GrEffectUnitTest.h
@@ -31,22 +31,22 @@
#if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
class GrContext;
-class GrEffect;
+class GrEffectRef;
class GrTexture;
class GrEffectTestFactory : GrNoncopyable {
public:
- typedef GrEffect* (*CreateProc)(SkRandom*, GrContext*, GrTexture* dummyTextures[]);
+ typedef GrEffectRef* (*CreateProc)(SkRandom*, GrContext*, GrTexture* dummyTextures[]);
GrEffectTestFactory(CreateProc createProc) {
fCreateProc = createProc;
GetFactories()->push_back(this);
}
- static GrEffect* CreateStage(SkRandom* random,
- GrContext* context,
- GrTexture* dummyTextures[]) {
+ static GrEffectRef* CreateStage(SkRandom* random,
+ GrContext* context,
+ GrTexture* dummyTextures[]) {
uint32_t idx = random->nextRangeU(0, GetFactories()->count() - 1);
GrEffectTestFactory* factory = (*GetFactories())[idx];
return factory->fCreateProc(random, context, dummyTextures);
@@ -62,7 +62,7 @@
*/
#define GR_DECLARE_EFFECT_TEST \
static GrEffectTestFactory gTestFactory; \
- static GrEffect* TestCreate(SkRandom*, GrContext*, GrTexture* dummyTextures[2])
+ static GrEffectRef* TestCreate(SkRandom*, GrContext*, GrTexture* dummyTextures[2])
/** GrEffect subclasses should insert this macro in their implementation file. They must then
* also implement this static function: