blob: fae45fcea436b0b8b0a84629bec72976016fbbf7 [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:
twiz@google.coma5e65ec2012-08-02 15:15:16 +000026 typedef uint32_t StageKey;
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000027 enum {
28 kProgramStageKeyBits = 10,
twiz@google.coma5e65ec2012-08-02 15:15:16 +000029 kTexturingStageKeyBits = 6
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000030 };
31
bsalomon@google.com021fc732012-10-25 12:47:42 +000032 virtual StageKey glStageKey(const GrEffect&, const GrGLCaps&) const = 0;
bsalomon@google.comd698f772012-10-25 13:22:00 +000033 virtual GrGLEffect* createGLInstance(const GrEffect&) const = 0;
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000034
bsalomon@google.com396e61f2012-10-25 19:00:29 +000035 bool operator ==(const GrBackendEffectFactory& b) const {
bsalomon@google.com021fc732012-10-25 12:47:42 +000036 return fEffectClassID == b.fEffectClassID;
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000037 }
bsalomon@google.com396e61f2012-10-25 19:00:29 +000038 bool operator !=(const GrBackendEffectFactory& b) const {
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000039 return !(*this == b);
40 }
41
bsalomon@google.com289efe02012-05-21 20:57:59 +000042 virtual const char* name() const = 0;
43
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000044protected:
45 enum {
bsalomon@google.com021fc732012-10-25 12:47:42 +000046 kIllegalEffectClassID = 0,
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000047 };
48
bsalomon@google.com396e61f2012-10-25 19:00:29 +000049 GrBackendEffectFactory() {
bsalomon@google.com021fc732012-10-25 12:47:42 +000050 fEffectClassID = kIllegalEffectClassID;
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000051 }
52
53 static StageKey GenID() {
bsalomon@google.com021fc732012-10-25 12:47:42 +000054 // fCurrEffectClassID has been initialized to kIllegalEffectClassID. The
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000055 // atomic inc returns the old value not the incremented value. So we add
56 // 1 to the returned value.
bsalomon@google.com021fc732012-10-25 12:47:42 +000057 int32_t id = sk_atomic_inc(&fCurrEffectClassID) + 1;
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000058 GrAssert(id < (1 << (8 * sizeof(StageKey) - kProgramStageKeyBits)));
59 return id;
60 }
61
bsalomon@google.com021fc732012-10-25 12:47:42 +000062 StageKey fEffectClassID;
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000063
64private:
bsalomon@google.com021fc732012-10-25 12:47:42 +000065 static int32_t fCurrEffectClassID;
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000066};
67
bsalomon@google.com021fc732012-10-25 12:47:42 +000068template <typename EffectClass>
bsalomon@google.com396e61f2012-10-25 19:00:29 +000069class GrTBackendEffectFactory : public GrBackendEffectFactory {
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000070
71public:
bsalomon@google.com422e81a2012-10-25 14:11:03 +000072 typedef typename EffectClass::GLEffect GLEffect;
bsalomon@google.com289efe02012-05-21 20:57:59 +000073
bsalomon@google.coma469c282012-10-24 18:28:34 +000074 /** Returns a human-readable name that is accessible via GrEffect or
bsalomon@google.comd698f772012-10-25 13:22:00 +000075 GrGLEffect and is consistent between the two of them.
bsalomon@google.com289efe02012-05-21 20:57:59 +000076 */
bsalomon@google.com021fc732012-10-25 12:47:42 +000077 virtual const char* name() const SK_OVERRIDE { return EffectClass::Name(); }
bsalomon@google.com289efe02012-05-21 20:57:59 +000078
bsalomon@google.com021fc732012-10-25 12:47:42 +000079 /** Returns a value that identifies the GLSL shader code generated by
bsalomon@google.coma469c282012-10-24 18:28:34 +000080 a GrEffect. This enables caching of generated shaders. Part of the
bsalomon@google.com8ea78d82012-10-24 20:11:30 +000081 id identifies the GrEffect subclass. The remainder is based
bsalomon@google.coma469c282012-10-24 18:28:34 +000082 on the aspects of the GrEffect object's configuration that affect
bsalomon@google.com16fd21b2012-05-21 21:18:13 +000083 GLSL code generation. */
bsalomon@google.com021fc732012-10-25 12:47:42 +000084 virtual StageKey glStageKey(const GrEffect& effect, const GrGLCaps& caps) const SK_OVERRIDE {
85 GrAssert(kIllegalEffectClassID != fEffectClassID);
bsalomon@google.com422e81a2012-10-25 14:11:03 +000086 StageKey stageID = GLEffect::GenKey(effect, caps);
87 StageKey textureKey = GLEffect::GenTextureKey(effect, caps);
bsalomon@google.com7c4d06d2012-05-21 15:31:00 +000088#if GR_DEBUG
bsalomon@google.com021fc732012-10-25 12:47:42 +000089 static const StageKey kIllegalIDMask = (uint16_t) (~((1U << kProgramStageKeyBits) - 1));
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000090 GrAssert(!(kIllegalIDMask & stageID));
twiz@google.coma5e65ec2012-08-02 15:15:16 +000091
92 static const StageKey kIllegalTextureKeyMask =
93 (uint16_t) (~((1U << kTexturingStageKeyBits) - 1));
94 GrAssert(!(kIllegalTextureKeyMask & textureKey));
bsalomon@google.com7c4d06d2012-05-21 15:31:00 +000095#endif
bsalomon@google.com021fc732012-10-25 12:47:42 +000096 return fEffectClassID | (textureKey << kProgramStageKeyBits) | stageID;
bsalomon@google.comae4f96a2012-05-18 19:54:48 +000097 }
98
99 /** Returns a new instance of the appropriate *GL* implementation class
bsalomon@google.coma469c282012-10-24 18:28:34 +0000100 for the given GrEffect; caller is responsible for deleting
twiz@google.coma5e65ec2012-08-02 15:15:16 +0000101 the object. */
bsalomon@google.com422e81a2012-10-25 14:11:03 +0000102 virtual GLEffect* createGLInstance(const GrEffect& effect) const SK_OVERRIDE {
103 return SkNEW_ARGS(GLEffect, (*this, effect));
bsalomon@google.comae4f96a2012-05-18 19:54:48 +0000104 }
105
bsalomon@google.com289efe02012-05-21 20:57:59 +0000106 /** This class is a singleton. This function returns the single instance.
107 */
bsalomon@google.com396e61f2012-10-25 19:00:29 +0000108 static const GrBackendEffectFactory& getInstance() {
109 static SkAlignedSTStorage<1, GrTBackendEffectFactory> gInstanceMem;
110 static const GrTBackendEffectFactory* gInstance;
bsalomon@google.comae4f96a2012-05-18 19:54:48 +0000111 if (!gInstance) {
tomhudson@google.comc377baf2012-07-09 20:17:56 +0000112 gInstance = SkNEW_PLACEMENT(gInstanceMem.get(),
bsalomon@google.com396e61f2012-10-25 19:00:29 +0000113 GrTBackendEffectFactory);
bsalomon@google.comae4f96a2012-05-18 19:54:48 +0000114 }
115 return *gInstance;
116 }
117
118protected:
bsalomon@google.com396e61f2012-10-25 19:00:29 +0000119 GrTBackendEffectFactory() {
bsalomon@google.com021fc732012-10-25 12:47:42 +0000120 fEffectClassID = GenID() << (kProgramStageKeyBits + kTexturingStageKeyBits) ;
bsalomon@google.comae4f96a2012-05-18 19:54:48 +0000121 }
122};
123
124#endif