aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/gpu/GrBackendEffectFactory.h
blob: 89562d5239546149cc6d51b3354396d89e18e0ba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef GrBackendEffectFactory_DEFINED
#define GrBackendEffectFactory_DEFINED

#include "GrTypes.h"
#include "SkTemplates.h"
#include "GrNoncopyable.h"

/** Given a GrEffect of a particular type, creates the corresponding
    graphics-backend-specific GrGLEffect. Also tracks equivalence
    of shaders generated via a key.
 */

class GrEffect;
class GrGLEffect;
class GrGLCaps;

class GrBackendEffectFactory : public GrNoncopyable {
public:
    typedef uint32_t EffectKey;
    enum {
        kEffectKeyBits = 10,
        /**
         * Some aspects of the generated code may be determined by the particular textures that are
         * associated with the effect. These manipulations are performed by GrGLShaderBuilder beyond
         * GrGLEffects' control. So there is a dedicated part of the key which is combined
         * automatically with the bits produced by GrGLEffect::GenKey().
         */
        kTextureKeyBits = 6
    };

    virtual EffectKey glEffectKey(const GrEffect&, const GrGLCaps&) const = 0;
    virtual GrGLEffect* createGLInstance(const GrEffect&) const = 0;

    bool operator ==(const GrBackendEffectFactory& b) const {
        return fEffectClassID == b.fEffectClassID;
    }
    bool operator !=(const GrBackendEffectFactory& b) const {
        return !(*this == b);
    }

    virtual const char* name() const = 0;

protected:
    enum {
        kIllegalEffectClassID = 0,
    };

    GrBackendEffectFactory() {
        fEffectClassID = kIllegalEffectClassID;
    }

    static EffectKey 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;
        GrAssert(id < (1 << (8 * sizeof(EffectKey) - kEffectKeyBits)));
        return id;
    }

    EffectKey fEffectClassID;

private:
    static int32_t fCurrEffectClassID;
};

template <typename EffectClass>
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.
     */
    virtual const char* name() const SK_OVERRIDE { return EffectClass::Name(); }

    /** Returns a value that identifies the GLSL shader code generated by
        a GrEffect. 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. */
    virtual EffectKey glEffectKey(const GrEffect& effect, const GrGLCaps& caps) const SK_OVERRIDE {
        GrAssert(kIllegalEffectClassID != fEffectClassID);
        EffectKey effectKey = GLEffect::GenKey(effect, caps);
        EffectKey textureKey = GLEffect::GenTextureKey(effect, caps);
#if GR_DEBUG
        static const EffectKey kIllegalIDMask = (uint16_t) (~((1U << kEffectKeyBits) - 1));
        GrAssert(!(kIllegalIDMask & effectKey));

        static const EffectKey kIllegalTextureKeyMask = (uint16_t) (~((1U << kTextureKeyBits) - 1));
        GrAssert(!(kIllegalTextureKeyMask & textureKey));
#endif
        return fEffectClassID | (textureKey << kEffectKeyBits) | effectKey;
    }

    /** Returns a new instance of the appropriate *GL* implementation class
        for the given GrEffect; caller is responsible for deleting
        the object. */
    virtual GLEffect* createGLInstance(const GrEffect& effect) const SK_OVERRIDE {
        return SkNEW_ARGS(GLEffect, (*this, effect));
    }

    /** This class is a singleton. This function returns the single instance.
     */
    static const GrBackendEffectFactory& getInstance() {
        static SkAlignedSTStorage<1, GrTBackendEffectFactory> gInstanceMem;
        static const GrTBackendEffectFactory* gInstance;
        if (!gInstance) {
            gInstance = SkNEW_PLACEMENT(gInstanceMem.get(),
                                        GrTBackendEffectFactory);
        }
        return *gInstance;
    }

protected:
    GrTBackendEffectFactory() {
        fEffectClassID = GenID() << (kEffectKeyBits + kTextureKeyBits) ;
    }
};

#endif