aboutsummaryrefslogtreecommitdiffhomepage
path: root/include
diff options
context:
space:
mode:
authorGravatar bsalomon <bsalomon@google.com>2014-07-17 07:55:11 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-07-17 07:55:11 -0700
commit929f29a5c1bffa7f7c1b5a376351d0762b8ac561 (patch)
tree19e2f4bedb96946a8190d01864ec687a4d2ca260 /include
parentb959ec7815ae0f65f2aabdeaf280a2a2ee6db955 (diff)
Makes GrGLProgramDesc's key store the lengths as well as offsets of the effect keys.
Makes it possible to use GrBackendEffectFactories other than GrTBEF by moving meta-key generation out of GrTBEF. Cleans up docs around GrBackendEffectFactory. Committed: https://skia.googlesource.com/skia/+/c0ea398aff8254e31152cbb94c9ab6150428e252 R=robertphillips@google.com, jvanverth@google.com Author: bsalomon@google.com Review URL: https://codereview.chromium.org/379113004
Diffstat (limited to 'include')
-rw-r--r--include/gpu/GrBackendEffectFactory.h87
-rw-r--r--include/gpu/GrTBackendEffectFactory.h56
2 files changed, 85 insertions, 58 deletions
diff --git a/include/gpu/GrBackendEffectFactory.h b/include/gpu/GrBackendEffectFactory.h
index 32f14f2746..ef9e436401 100644
--- a/include/gpu/GrBackendEffectFactory.h
+++ b/include/gpu/GrBackendEffectFactory.h
@@ -14,22 +14,12 @@
#include "SkTypes.h"
#include "SkTArray.h"
-/** Given a GrEffect of a particular type, creates the corresponding graphics-backend-specific
- effect object. Also tracks equivalence of shaders generated via a key. Each factory instance
- is assigned a generation ID at construction. The ID of the return of GrEffect::getFactory()
- is used as a type identifier. Thus a GrEffect subclass must return a singleton from
- getFactory(). GrEffect subclasses should use the derived class GrTBackendEffectFactory that is
- templated on the GrEffect subclass as their factory object. It requires that the GrEffect
- subclass has a nested class (or typedef) GLEffect which is its GL implementation and a subclass
- of GrGLEffect.
- */
-
class GrGLEffect;
class GrGLCaps;
class GrDrawEffect;
/**
- * Used by effects to build their keys. It incorpates each per-effect key into a larger shader key.
+ * Used by effects to build their keys. It incorporates each per-effect key into a larger shader key.
*/
class GrEffectKeyBuilder {
public:
@@ -42,6 +32,14 @@ public:
fData->push_back_n(4, reinterpret_cast<uint8_t*>(&v));
}
+ /** Inserts count uint32_ts into the key. The returned pointer is only valid until the next
+ add*() call. */
+ uint32_t* SK_WARN_UNUSED_RESULT add32n(int count) {
+ SkASSERT(count > 0);
+ fCount += count;
+ return reinterpret_cast<uint32_t*>(fData->push_back_n(4 * count));
+ }
+
size_t size() const { return sizeof(uint32_t) * fCount; }
private:
@@ -49,43 +47,74 @@ private:
int fCount; // number of uint32_ts added to fData by the effect.
};
+/**
+ * Given a GrEffect of a particular type, creates the corresponding graphics-backend-specific
+ * effect object. It also tracks equivalence of shaders generated via a key. The factory for an
+ * effect is accessed via GrEffect::getFactory(). Each factory instance is assigned an ID at
+ * construction. The ID of GrEffect::getFactory() is used as a type identifier. Thus, a GrEffect
+ * subclass must always return the same object from getFactory() and that factory object must be
+ * unique to the GrEffect subclass (and unique from any further derived subclasses).
+ *
+ * Rather than subclassing this class themselves, it is recommended that GrEffect authors use
+ * the templated subclass GrTBackendEffectFactory by writing their getFactory() method as:
+ *
+ * const GrBackendEffectFactory& MyEffect::getFactory() const {
+ * return GrTBackendEffectFactory<MyEffect>::getInstance();
+ * }
+ *
+ * Using GrTBackendEffectFactory places a few constraints on the effect. See that class's comments.
+ */
class GrBackendEffectFactory : SkNoncopyable {
public:
typedef uint32_t EffectKey;
- virtual bool getGLEffectKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyBuilder*) const = 0;
+ /**
+ * Generates an effect's key. The key is based on the aspects of the GrEffect object's
+ * configuration that affect GLSL code generation. Two GrEffect instances that would cause
+ * this->createGLInstance()->emitCode() to produce different code must produce different keys.
+ */
+ virtual void getGLEffectKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyBuilder*) const = 0;
+
+ /**
+ * Creates a GrGLEffect instance that is used both to generate code for the GrEffect in a GLSL
+ * program and to manage updating uniforms for the program when it is used.
+ */
virtual GrGLEffect* createGLInstance(const GrDrawEffect&) const = 0;
- bool operator ==(const GrBackendEffectFactory& b) const {
- return fEffectClassID == b.fEffectClassID;
- }
- bool operator !=(const GrBackendEffectFactory& b) const {
- return !(*this == b);
- }
-
+ /**
+ * Produces a human-reable name for the effect.
+ */
virtual const char* name() const = 0;
+ /**
+ * A unique value for every instance of this factory. It is automatically incorporated into the
+ * effect's key. This allows keys generated by getGLEffectKey() to only be unique within a
+ * GrEffect subclass and not necessarily across subclasses.
+ */
+ uint32_t effectClassID() const { return fEffectClassID; }
+
protected:
+ GrBackendEffectFactory() : fEffectClassID(GenID()) {}
+ virtual ~GrBackendEffectFactory() {}
+
+private:
enum {
kIllegalEffectClassID = 0,
};
- GrBackendEffectFactory() {
- fEffectClassID = kIllegalEffectClassID;
- }
- virtual ~GrBackendEffectFactory() {}
-
- static int32_t GenID() {
+ static uint32_t GenID() {
// fCurrEffectClassID has been initialized to kIllegalEffectClassID. The
// atomic inc returns the old value not the incremented value. So we add
// 1 to the returned value.
- int32_t id = sk_atomic_inc(&fCurrEffectClassID) + 1;
+ uint32_t id = static_cast<uint32_t>(sk_atomic_inc(&fCurrEffectClassID)) + 1;
+ if (!id) {
+ SkFAIL("This should never wrap as it should only be called once for each GrEffect "
+ "subclass.");
+ }
return id;
}
- int32_t fEffectClassID;
-
-private:
+ const uint32_t fEffectClassID;
static int32_t fCurrEffectClassID;
};
diff --git a/include/gpu/GrTBackendEffectFactory.h b/include/gpu/GrTBackendEffectFactory.h
index cd4c0a49e9..251e8c7768 100644
--- a/include/gpu/GrTBackendEffectFactory.h
+++ b/include/gpu/GrTBackendEffectFactory.h
@@ -13,7 +13,26 @@
#include "gl/GrGLProgramEffects.h"
/**
- * Implements GrBackendEffectFactory for a GrEffect subclass as a singleton.
+ * Implements GrBackendEffectFactory for a GrEffect subclass as a singleton. This can be used by
+ * most GrEffect subclasses to implement the GrEffect::getFactory() method:
+ *
+ * const GrBackendEffectFactory& MyEffect::getFactory() const {
+ * return GrTBackendEffectFactory<MyEffect>::getInstance();
+ * }
+ *
+ * Using this class requires that the GrEffect subclass always produces the same GrGLEffect
+ * subclass. Additionally, It adds the following requirements to the GrEffect and GrGLEffect
+ * subclasses:
+ *
+ * 1. The GrGLEffect used by GrEffect subclass MyEffect must be named or typedef'ed to
+ * MyEffect::GLEffect.
+ * 2. MyEffect::GLEffect must have a static function:
+ * EffectKey GenKey(const GrDrawEffect, const GrGLCaps&)
+ * which generates a key that maps 1 to 1 with code variations emitted by
+ * MyEffect::GLEffect::emitCode().
+ * 3. MyEffect must have a static function:
+ * const char* Name()
+ * which returns a human-readable name for the effect.
*/
template <typename EffectClass>
class GrTBackendEffectFactory : public GrBackendEffectFactory {
@@ -21,35 +40,17 @@ class GrTBackendEffectFactory : public GrBackendEffectFactory {
public:
typedef typename EffectClass::GLEffect GLEffect;
- /** Returns a human-readable name that is accessible via GrEffect or
- GrGLEffect and is consistent between the two of them.
- */
+ /** Returns a human-readable name for the effect. Implemented using GLEffect::Name as described
+ * in this class's comment. */
virtual const char* name() const SK_OVERRIDE { return EffectClass::Name(); }
- /** Generates an effect's key. This enables caching of generated shaders. Part of the
- id identifies the GrEffect subclass. The remainder is based on the aspects of the
- GrEffect object's configuration that affect GLSL code generation. If this fails
- then program generation should be aborted. Failure occurs if the effect uses more
- transforms, attributes, or textures than the key has space for. */
- virtual bool getGLEffectKey(const GrDrawEffect& drawEffect,
+
+ /** Implemented using GLEffect::GenKey as described in this class's comment. */
+ virtual void getGLEffectKey(const GrDrawEffect& drawEffect,
const GrGLCaps& caps,
GrEffectKeyBuilder* b) const SK_OVERRIDE {
- SkASSERT(kIllegalEffectClassID != fEffectClassID);
EffectKey effectKey = GLEffect::GenKey(drawEffect, caps);
- EffectKey textureKey = GrGLProgramEffects::GenTextureKey(drawEffect, caps);
- EffectKey transformKey = GrGLProgramEffects::GenTransformKey(drawEffect);
- EffectKey attribKey = GrGLProgramEffects::GenAttribKey(drawEffect);
- static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16);
- if ((textureKey | transformKey | attribKey | fEffectClassID) & kMetaKeyInvalidMask) {
- return false;
- }
-
- // effectKey must be first because it is what will be returned by
- // GrGLProgramDesc::EffectKeyProvider and passed to the GrGLEffect as its key.
b->add32(effectKey);
- b->add32(textureKey << 16 | transformKey);
- b->add32(fEffectClassID << 16 | attribKey);
- return true;
}
/** Returns a new instance of the appropriate *GL* implementation class
@@ -59,8 +60,7 @@ public:
return SkNEW_ARGS(GLEffect, (*this, drawEffect));
}
- /** This class is a singleton. This function returns the single instance.
- */
+ /** This class is a singleton. This function returns the single instance. */
static const GrBackendEffectFactory& getInstance() {
static SkAlignedSTStorage<1, GrTBackendEffectFactory> gInstanceMem;
static const GrTBackendEffectFactory* gInstance;
@@ -72,9 +72,7 @@ public:
}
protected:
- GrTBackendEffectFactory() {
- fEffectClassID = GenID();
- }
+ GrTBackendEffectFactory() {}
};
#endif