blob: 89562d5239546149cc6d51b3354396d89e18e0ba [file] [log] [blame]
bsalomon@google.comae4f96a2012-05-18 19:54:48 +00001/*
2 * Copyright 2012 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
bsalomon@google.com396e61f2012-10-25 19:00:29 +00008#ifndef GrBackendEffectFactory_DEFINED
9#define GrBackendEffectFactory_DEFINED
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000010
11#include "GrTypes.h"
bsalomon@google.com8e520fc2012-05-18 20:06:45 +000012#include "SkTemplates.h"
senorblanco@chromium.org894790d2012-07-11 16:01:22 +000013#include "GrNoncopyable.h"
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000014
bsalomon@google.coma469c282012-10-24 18:28:34 +000015/** Given a GrEffect of a particular type, creates the corresponding
bsalomon@google.comd698f772012-10-25 13:22:00 +000016 graphics-backend-specific GrGLEffect. Also tracks equivalence
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000017 of shaders generated via a key.
18 */
19
bsalomon@google.coma469c282012-10-24 18:28:34 +000020class GrEffect;
bsalomon@google.comd698f772012-10-25 13:22:00 +000021class GrGLEffect;
twiz@google.coma5e65ec2012-08-02 15:15:16 +000022class GrGLCaps;
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000023
bsalomon@google.com396e61f2012-10-25 19:00:29 +000024class GrBackendEffectFactory : public GrNoncopyable {
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000025public:
bsalomon@google.com46fba0d2012-10-25 21:42:05 +000026 typedef uint32_t EffectKey;
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000027 enum {
bsalomon@google.com46fba0d2012-10-25 21:42:05 +000028 kEffectKeyBits = 10,
29 /**
30 * Some aspects of the generated code may be determined by the particular textures that are
31 * associated with the effect. These manipulations are performed by GrGLShaderBuilder beyond
32 * GrGLEffects' control. So there is a dedicated part of the key which is combined
33 * automatically with the bits produced by GrGLEffect::GenKey().
34 */
35 kTextureKeyBits = 6
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000036 };
37
bsalomon@google.com46fba0d2012-10-25 21:42:05 +000038 virtual EffectKey glEffectKey(const GrEffect&, const GrGLCaps&) const = 0;
bsalomon@google.comd698f772012-10-25 13:22:00 +000039 virtual GrGLEffect* createGLInstance(const GrEffect&) const = 0;
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000040
bsalomon@google.com396e61f2012-10-25 19:00:29 +000041 bool operator ==(const GrBackendEffectFactory& b) const {
bsalomon@google.com021fc732012-10-25 12:47:42 +000042 return fEffectClassID == b.fEffectClassID;
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000043 }
bsalomon@google.com396e61f2012-10-25 19:00:29 +000044 bool operator !=(const GrBackendEffectFactory& b) const {
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000045 return !(*this == b);
46 }
47
bsalomon@google.com289efe02012-05-21 20:57:59 +000048 virtual const char* name() const = 0;
49
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000050protected:
51 enum {
bsalomon@google.com021fc732012-10-25 12:47:42 +000052 kIllegalEffectClassID = 0,
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000053 };
54
bsalomon@google.com396e61f2012-10-25 19:00:29 +000055 GrBackendEffectFactory() {
bsalomon@google.com021fc732012-10-25 12:47:42 +000056 fEffectClassID = kIllegalEffectClassID;
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000057 }
58
bsalomon@google.com46fba0d2012-10-25 21:42:05 +000059 static EffectKey GenID() {
bsalomon@google.com021fc732012-10-25 12:47:42 +000060 // fCurrEffectClassID has been initialized to kIllegalEffectClassID. The
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000061 // atomic inc returns the old value not the incremented value. So we add
62 // 1 to the returned value.
bsalomon@google.com021fc732012-10-25 12:47:42 +000063 int32_t id = sk_atomic_inc(&fCurrEffectClassID) + 1;
bsalomon@google.com46fba0d2012-10-25 21:42:05 +000064 GrAssert(id < (1 << (8 * sizeof(EffectKey) - kEffectKeyBits)));
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000065 return id;
66 }
67
bsalomon@google.com46fba0d2012-10-25 21:42:05 +000068 EffectKey fEffectClassID;
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000069
70private:
bsalomon@google.com021fc732012-10-25 12:47:42 +000071 static int32_t fCurrEffectClassID;
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000072};
73
bsalomon@google.com021fc732012-10-25 12:47:42 +000074template <typename EffectClass>
bsalomon@google.com396e61f2012-10-25 19:00:29 +000075class GrTBackendEffectFactory : public GrBackendEffectFactory {
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000076
77public:
bsalomon@google.com422e81a2012-10-25 14:11:03 +000078 typedef typename EffectClass::GLEffect GLEffect;
bsalomon@google.com289efe02012-05-21 20:57:59 +000079
bsalomon@google.coma469c282012-10-24 18:28:34 +000080 /** Returns a human-readable name that is accessible via GrEffect or
bsalomon@google.comd698f772012-10-25 13:22:00 +000081 GrGLEffect and is consistent between the two of them.
bsalomon@google.com289efe02012-05-21 20:57:59 +000082 */
bsalomon@google.com021fc732012-10-25 12:47:42 +000083 virtual const char* name() const SK_OVERRIDE { return EffectClass::Name(); }
bsalomon@google.com289efe02012-05-21 20:57:59 +000084
bsalomon@google.com021fc732012-10-25 12:47:42 +000085 /** Returns a value that identifies the GLSL shader code generated by
bsalomon@google.coma469c282012-10-24 18:28:34 +000086 a GrEffect. This enables caching of generated shaders. Part of the
bsalomon@google.com8ea78d82012-10-24 20:11:30 +000087 id identifies the GrEffect subclass. The remainder is based
bsalomon@google.coma469c282012-10-24 18:28:34 +000088 on the aspects of the GrEffect object's configuration that affect
bsalomon@google.com16fd21b2012-05-21 21:18:13 +000089 GLSL code generation. */
bsalomon@google.com46fba0d2012-10-25 21:42:05 +000090 virtual EffectKey glEffectKey(const GrEffect& effect, const GrGLCaps& caps) const SK_OVERRIDE {
bsalomon@google.com021fc732012-10-25 12:47:42 +000091 GrAssert(kIllegalEffectClassID != fEffectClassID);
bsalomon@google.com46fba0d2012-10-25 21:42:05 +000092 EffectKey effectKey = GLEffect::GenKey(effect, caps);
93 EffectKey textureKey = GLEffect::GenTextureKey(effect, caps);
bsalomon@google.com7c4d06d2012-05-21 15:31:00 +000094#if GR_DEBUG
bsalomon@google.com46fba0d2012-10-25 21:42:05 +000095 static const EffectKey kIllegalIDMask = (uint16_t) (~((1U << kEffectKeyBits) - 1));
96 GrAssert(!(kIllegalIDMask & effectKey));
twiz@google.coma5e65ec2012-08-02 15:15:16 +000097
bsalomon@google.com46fba0d2012-10-25 21:42:05 +000098 static const EffectKey kIllegalTextureKeyMask = (uint16_t) (~((1U << kTextureKeyBits) - 1));
twiz@google.coma5e65ec2012-08-02 15:15:16 +000099 GrAssert(!(kIllegalTextureKeyMask & textureKey));
bsalomon@google.com7c4d06d2012-05-21 15:31:00 +0000100#endif
bsalomon@google.com46fba0d2012-10-25 21:42:05 +0000101 return fEffectClassID | (textureKey << kEffectKeyBits) | effectKey;
bsalomon@google.comae4f96a2012-05-18 19:54:48 +0000102 }
103
104 /** Returns a new instance of the appropriate *GL* implementation class
bsalomon@google.coma469c282012-10-24 18:28:34 +0000105 for the given GrEffect; caller is responsible for deleting
twiz@google.coma5e65ec2012-08-02 15:15:16 +0000106 the object. */
bsalomon@google.com422e81a2012-10-25 14:11:03 +0000107 virtual GLEffect* createGLInstance(const GrEffect& effect) const SK_OVERRIDE {
108 return SkNEW_ARGS(GLEffect, (*this, effect));
bsalomon@google.comae4f96a2012-05-18 19:54:48 +0000109 }
110
bsalomon@google.com289efe02012-05-21 20:57:59 +0000111 /** This class is a singleton. This function returns the single instance.
112 */
bsalomon@google.com396e61f2012-10-25 19:00:29 +0000113 static const GrBackendEffectFactory& getInstance() {
114 static SkAlignedSTStorage<1, GrTBackendEffectFactory> gInstanceMem;
115 static const GrTBackendEffectFactory* gInstance;
bsalomon@google.comae4f96a2012-05-18 19:54:48 +0000116 if (!gInstance) {
tomhudson@google.comc377baf2012-07-09 20:17:56 +0000117 gInstance = SkNEW_PLACEMENT(gInstanceMem.get(),
bsalomon@google.com396e61f2012-10-25 19:00:29 +0000118 GrTBackendEffectFactory);
bsalomon@google.comae4f96a2012-05-18 19:54:48 +0000119 }
120 return *gInstance;
121 }
122
123protected:
bsalomon@google.com396e61f2012-10-25 19:00:29 +0000124 GrTBackendEffectFactory() {
bsalomon@google.com46fba0d2012-10-25 21:42:05 +0000125 fEffectClassID = GenID() << (kEffectKeyBits + kTextureKeyBits) ;
bsalomon@google.comae4f96a2012-05-18 19:54:48 +0000126 }
127};
128
129#endif