GrGLShaderBuilder.h revision 26e18b593ab65e4d92dfbce92579d8bc180d4c2c
1f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com/*
2f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com * Copyright 2012 Google Inc.
3f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com *
4f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com * Use of this source code is governed by a BSD-style license that can be
5f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com * found in the LICENSE file.
6f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com */
7f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com
8f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com#ifndef GrGLShaderBuilder_DEFINED
9f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com#define GrGLShaderBuilder_DEFINED
10f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com
11f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com#include "GrAllocator.h"
122eaaefd7e6a58339b3f93333f1e9cc92252cc303bsalomon@google.com#include "GrBackendEffectFactory.h"
13b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com#include "GrColor.h"
14a469c28c3c16214733a25201a286970f57b3d944bsalomon@google.com#include "GrEffect.h"
15f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com#include "gl/GrGLSL.h"
16dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com#include "gl/GrGLUniformManager.h"
17f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com
18f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com#include <stdarg.h>
19f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com
20ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.comclass GrGLContextInfo;
21c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.comclass GrEffectStage;
2226e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.comclass GrGLProgramDesc;
23dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com
24f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com/**
25eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com  Contains all the incremental state of a shader as it is being built,as well as helpers to
26eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com  manipulate that state.
27f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com*/
28f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.comclass GrGLShaderBuilder {
29f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.compublic:
30f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com    /**
3134cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com     * Passed to GrGLEffects to add texture reads to their shader code.
32f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com     */
33f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com    class TextureSampler {
34f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com    public:
35f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com        TextureSampler()
36b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com            : fConfigComponentMask(0)
37b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com            , fSamplerUniform(GrGLUniformManager::kInvalidUniformHandle) {
38b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com            // we will memcpy the first 4 bytes from passed in swizzle. This ensures the string is
39b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com            // terminated.
40b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com            fSwizzle[4] = '\0';
41b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com        }
42f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com
43f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com        TextureSampler(const TextureSampler& other) { *this = other; }
44f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com
45f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com        TextureSampler& operator= (const TextureSampler& other) {
46b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com            GrAssert(0 == fConfigComponentMask);
47f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com            GrAssert(GrGLUniformManager::kInvalidUniformHandle == fSamplerUniform);
48f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com
49b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com            fConfigComponentMask = other.fConfigComponentMask;
50f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com            fSamplerUniform = other.fSamplerUniform;
51f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com            return *this;
52f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com        }
53f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com
54b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com        // bitfield of GrColorComponentFlags present in the texture's config.
55b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com        uint32_t configComponentMask() const { return fConfigComponentMask; }
56b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com
57b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com        const char* swizzle() const { return fSwizzle; }
58f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com
5926e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com        bool isInitialized() const { return 0 != fConfigComponentMask; }
6026e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
61f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com    private:
6234cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com        // The idx param is used to ensure multiple samplers within a single effect have unique
63b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com        // uniform names. swizzle is a four char max string made up of chars 'r', 'g', 'b', and 'a'.
64b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com        void init(GrGLShaderBuilder* builder,
65b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com                  uint32_t configComponentMask,
66b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com                  const char* swizzle,
67b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com                  int idx) {
6826e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com            GrAssert(!this->isInitialized());
6926e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com            GrAssert(0 != configComponentMask);
70f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com            GrAssert(GrGLUniformManager::kInvalidUniformHandle == fSamplerUniform);
71f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com
72f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com            GrAssert(NULL != builder);
7334cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com            SkString name;
7434cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com            name.printf("Sampler%d_", idx);
75f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com            fSamplerUniform = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
76f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com                                                  kSampler2D_GrSLType,
7734cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com                                                  name.c_str());
78f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com            GrAssert(GrGLUniformManager::kInvalidUniformHandle != fSamplerUniform);
79f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com
80b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com            fConfigComponentMask = configComponentMask;
81b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com            memcpy(fSwizzle, swizzle, 4);
82b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com        }
83b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com
84b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com        void init(GrGLShaderBuilder* builder, const GrTextureAccess* access, int idx) {
85b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com            GrAssert(NULL != access);
86b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com            this->init(builder,
87b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com                       GrPixelConfigComponentMask(access->getTexture()->config()),
88b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com                       access->getSwizzle(),
89b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com                       idx);
90f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com        }
91f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com
92b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com        uint32_t                          fConfigComponentMask;
93b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com        char                              fSwizzle[5];
94f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com        GrGLUniformManager::UniformHandle fSamplerUniform;
95f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com
96b8eb2e89edf914caf5479baeffcb670d3e93f496bsalomon@google.com        friend class GrGLShaderBuilder; // to call init().
97f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com    };
98f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com
99f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com    typedef SkTArray<TextureSampler> TextureSamplerArray;
100f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com
101eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com    enum ShaderType {
102eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com        kVertex_ShaderType   = 0x1,
103eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com        kGeometry_ShaderType = 0x2,
104eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com        kFragment_ShaderType = 0x4,
105eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com    };
106eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com
10726e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    GrGLShaderBuilder(const GrGLContextInfo&, GrGLUniformManager&, const GrGLProgramDesc&);
108f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com
109f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    /**
110f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com     * Called by GrGLEffects to add code to one of the shaders.
111f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com     */
112f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    void vsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
113f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        va_list args;
114f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        va_start(args, format);
115f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        this->codeAppendf(kVertex_ShaderType, format, args);
116f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        va_end(args);
117f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    }
118f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com
119f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    void gsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
120f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        va_list args;
121f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        va_start(args, format);
122f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        this->codeAppendf(kGeometry_ShaderType, format, args);
123f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        va_end(args);
124f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    }
125f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com
126f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    void fsCodeAppendf(const char format[], ...) SK_PRINTF_LIKE(2, 3) {
127f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        va_list args;
128f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        va_start(args, format);
129f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        this->codeAppendf(kFragment_ShaderType, format, args);
130f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        va_end(args);
131f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    }
132f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com
133f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    void vsCodeAppend(const char* str) { this->codeAppend(kVertex_ShaderType, str); }
134f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    void gsCodeAppend(const char* str) { this->codeAppend(kGeometry_ShaderType, str); }
135f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    void fsCodeAppend(const char* str) { this->codeAppend(kFragment_ShaderType, str); }
136f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com
137dbe49f735484f8862e378b63d0a074a301093dd0bsalomon@google.com    /** Appends a 2D texture sample with projection if necessary. coordType must either be Vec2f or
138dbe49f735484f8862e378b63d0a074a301093dd0bsalomon@google.com        Vec3f. The latter is interpreted as projective texture coords. The vec length and swizzle
139dbe49f735484f8862e378b63d0a074a301093dd0bsalomon@google.com        order of the result depends on the GrTextureAccess associated with the TextureSampler. */
140868a8e7fc83e9ac6ee1418e75b84a0595605626cbsalomon@google.com    void appendTextureLookup(SkString* out,
141f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com                             const TextureSampler&,
142dbe49f735484f8862e378b63d0a074a301093dd0bsalomon@google.com                             const char* coordName,
143868a8e7fc83e9ac6ee1418e75b84a0595605626cbsalomon@google.com                             GrSLType coordType = kVec2f_GrSLType) const;
144868a8e7fc83e9ac6ee1418e75b84a0595605626cbsalomon@google.com
145f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    /** Version of above that appends the result to the shader code rather than an SkString.
146f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com        Currently the shader type must be kFragment */
147f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    void appendTextureLookup(ShaderType,
148f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com                             const TextureSampler&,
149f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com                             const char* coordName,
150f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com                             GrSLType coordType = kVec2f_GrSLType);
151f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com
152f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com
1532d8edaf17510e50261b8a4e2a0daf7e617674999bsalomon@google.com    /** Does the work of appendTextureLookup and modulates the result by modulation. The result is
1542d8edaf17510e50261b8a4e2a0daf7e617674999bsalomon@google.com        always a vec4. modulation and the swizzle specified by TextureSampler must both be vec4 or
1552d8edaf17510e50261b8a4e2a0daf7e617674999bsalomon@google.com        float. If modulation is "" or NULL it this function acts as though appendTextureLookup were
1562d8edaf17510e50261b8a4e2a0daf7e617674999bsalomon@google.com        called. */
157f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    void appendTextureLookupAndModulate(ShaderType,
158868a8e7fc83e9ac6ee1418e75b84a0595605626cbsalomon@google.com                                        const char* modulation,
159f06df1bb9ab201a78bfc906a9e95326c6e15a119bsalomon@google.com                                        const TextureSampler&,
160dbe49f735484f8862e378b63d0a074a301093dd0bsalomon@google.com                                        const char* coordName,
161f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com                                        GrSLType coordType = kVec2f_GrSLType);
16234bcb9f80336fe0dc56ad5f67aeb0859bf84d92ebsalomon@google.com
163a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    /** Emits a helper function outside of main(). Currently ShaderType must be
164a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com        kFragment_ShaderType. */
165a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com    void emitFunction(ShaderType shader,
166a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                      GrSLType returnType,
167a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                      const char* name,
168a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                      int argCnt,
169a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                      const GrGLShaderVar* args,
170a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                      const char* body,
171a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com                      SkString* outName);
172a1bf0fffff821d9c11809c89bd98d4ced480421absalomon@google.com
17346fba0d79335f17429bb71d87a04d93fb2ee992bbsalomon@google.com    /** Generates a EffectKey for the shader code based on the texture access parameters and the
174a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com        capabilities of the GL context.  This is useful for keying the shader programs that may
175a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com        have multiple representations, based on the type/format of textures used. */
1762eaaefd7e6a58339b3f93333f1e9cc92252cc303bsalomon@google.com    static GrBackendEffectFactory::EffectKey KeyForTextureAccess(const GrTextureAccess&,
1772eaaefd7e6a58339b3f93333f1e9cc92252cc303bsalomon@google.com                                                                 const GrGLCaps&);
178a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com
17926e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    typedef uint8_t DstReadKey;
18026e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
18126e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    /**  Returns a key for adding code to read the copy-of-dst color in service of effects that
18226e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com         require reading the dst. It must not return 0 because 0 indicates that there is no dst
18326e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com         copy read at all. */
18426e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    static DstReadKey KeyForDstRead(const GrTexture* dstCopy, const GrGLCaps&);
18526e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
1866d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com    /** If texture swizzling is available using tex parameters then it is preferred over mangling
1876d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com        the generated shader code. This potentially allows greater reuse of cached shaders. */
1886d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com    static const GrGLenum* GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps);
1896d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com
190706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com    /** Add a uniform variable to the current program, that has visibility in one or more shaders.
191777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com        visibility is a bitfield of ShaderType values indicating from which shaders the uniform
192777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com        should be accessible. At least one bit must be set. Geometry shader uniforms are not
193777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com        supported at this time. The actual uniform name will be mangled. If outName is not NULL then
194777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com        it will refer to the final uniform name after return. Use the addUniformArray variant to add
195777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com        an array of uniforms.
196242ed6fb6c3c0dff780ed3bef47d36a3b34a352ctomhudson@google.com    */
197dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com    GrGLUniformManager::UniformHandle addUniform(uint32_t visibility,
198dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com                                                 GrSLType type,
199dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com                                                 const char* name,
200777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com                                                 const char** outName = NULL) {
201777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com        return this->addUniformArray(visibility, type, name, GrGLShaderVar::kNonArray, outName);
202777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com    }
203777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com    GrGLUniformManager::UniformHandle addUniformArray(uint32_t visibility,
204777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com                                                      GrSLType type,
205777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com                                                      const char* name,
206777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com                                                      int arrayCount,
207777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com                                                      const char** outName = NULL);
208032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com
209dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com    const GrGLShaderVar& getUniformVariable(GrGLUniformManager::UniformHandle) const;
210032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com
211032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    /**
212706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com     * Shortcut for getUniformVariable(u).c_str()
213032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com     */
214dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com    const char* getUniformCStr(GrGLUniformManager::UniformHandle u) const {
215032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com        return this->getUniformVariable(u).c_str();
216032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    }
217eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com
218ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org   /** Add a vertex attribute to the current program that is passed in from the vertex data.
219ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org       Returns false if the attribute was already there, true otherwise. */
220ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    bool addAttribute(GrSLType type, const char* name);
221ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org
222ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org   /** Add a varying variable to the current program to pass values between vertex and fragment
223eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com        shaders. If the last two parameters are non-NULL, they are filled in with the name
224eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com        generated. */
22523cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com    void addVarying(GrSLType type,
22623cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com                    const char* name,
22723cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com                    const char** vsOutName = NULL,
22823cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com                    const char** fsInName = NULL);
22923cb2299ddf8fc87df0d3f9bda78934382cf714dtomhudson@google.com
230706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com    /** Returns a variable name that represents the position of the fragment in the FS. The position
231706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com        is in device space (e.g. 0,0 is the top left and pixel centers are at half-integers). */
232706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com    const char* fragmentPosition();
233706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com
23417504f5d5ea2550d29d2118193627129beb7f8b2bsalomon@google.com    /** Returns a vertex attribute that represents the vertex position in the VS. This is the
23517504f5d5ea2550d29d2118193627129beb7f8b2bsalomon@google.com        pre-matrix position and is commonly used by effects to compute texture coords via a matrix.
23617504f5d5ea2550d29d2118193627129beb7f8b2bsalomon@google.com      */
23717504f5d5ea2550d29d2118193627129beb7f8b2bsalomon@google.com    const GrGLShaderVar& positionAttribute() const { return *fPositionVar; }
23817504f5d5ea2550d29d2118193627129beb7f8b2bsalomon@google.com
239c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com    /** Returns a vertex attribute that represents the local coords in the VS. This may be the same
240c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com        as positionAttribute() or it may not be. It depends upon whether the rendering code
241c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com        specified explicit local coords or not in the GrDrawState. */
242c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com    const GrGLShaderVar& localCoordsAttribute() const { return *fLocalCoordsVar; }
243c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com
24426e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    /** Returns the color of the destination pixel. This may be NULL if no effect advertised
24526e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com        that it will read the destination. */
24626e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    const char* dstColor() const;
24726e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
248c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com    /**
249c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com     * Are explicit local coordinates provided as input to the vertex shader.
250c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com     */
251c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com    bool hasExplicitLocalCoords() const { return (fLocalCoordsVar != fPositionVar); }
252c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com
253dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com    /**
25434cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com     * Interfaces used by GrGLProgram.
25534cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com     * TODO: Hide these from the GrEffects using friend or splitting this into two related classes.
25634cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com     * Also, GrGLProgram's shader string construction should be moved to this class.
257dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com     */
258dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com
25934cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com    /** Called after building is complete to get the final shader string. */
26034cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com    void getShader(ShaderType, SkString*) const;
26134cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com
26208283afc265f1153834256fc1012519813ba6b73bsalomon@google.com    void setCurrentStage(int stageIdx) { fCurrentStageIdx = stageIdx; }
26308283afc265f1153834256fc1012519813ba6b73bsalomon@google.com    void setNonStage() { fCurrentStageIdx = kNonStageIdx; }
26434cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com    // TODO: move remainder of shader code generation to this class and call this privately
26534cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com    // Handles of sampler uniforms generated for the effect are appended to samplerHandles.
26634cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com    GrGLEffect* createAndEmitGLEffect(
26734cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com                                const GrEffectStage& stage,
26834cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com                                GrBackendEffectFactory::EffectKey key,
26934cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com                                const char* fsInColor, // NULL means no incoming color
27034cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com                                const char* fsOutColor,
27134cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com                                SkTArray<GrGLUniformManager::UniformHandle, true>* samplerHandles);
27226e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
273706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com    GrGLUniformManager::UniformHandle getRTHeightUniform() const { return fRTHeightUniform; }
27426e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    GrGLUniformManager::UniformHandle getDstCopyTopLeftUniform() const {
27526e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com        return fDstCopyTopLeftUniform;
27626e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    }
27726e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    GrGLUniformManager::UniformHandle getDstCopyScaleUniform() const {
27826e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com        return fDstCopyScaleUniform;
27926e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    }
28026e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    GrGLUniformManager::UniformHandle getDstCopySamplerUniform() const {
28126e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com        return fDstCopySampler.fSamplerUniform;
28226e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    }
283ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org
284ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    struct AttributePair {
285ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org        void set(int index, const SkString& name) {
286ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org            fIndex = index; fName = name;
287ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org        }
288ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org        int      fIndex;
289ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org        SkString fName;
290ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    };
29126e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    const SkTArray<AttributePair, true>& getEffectAttributes() const {
292ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org        return fEffectAttributes;
293ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    }
294ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    const SkString* getEffectAttributeName(int attributeIndex) const;
295ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org
29634cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com    // TODO: Make this do all the compiling, linking, etc.
29734cccde630fc618649b9737bee464203d042bfbbbsalomon@google.com    void finished(GrGLuint programID);
298706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com
29913f181f28f4336adcc93b7297b6d16503f4c323crobertphillips@google.com    const GrGLContextInfo& ctxInfo() const { return fCtxInfo; }
30013f181f28f4336adcc93b7297b6d16503f4c323crobertphillips@google.com
301032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.comprivate:
302f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    void codeAppendf(ShaderType type, const char format[], va_list args);
303f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    void codeAppend(ShaderType type, const char* str);
304f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com
305dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com    typedef GrTAllocator<GrGLShaderVar> VarArray;
306032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com
307032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    void appendDecls(const VarArray&, SkString*) const;
308032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com    void appendUniformDecls(ShaderType, SkString*) const;
309032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com
310dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com    typedef GrGLUniformManager::BuilderUniform BuilderUniform;
311dbbc4e2da93cef5c0cfb0b3c92ff6c2c80f6e67absalomon@google.com    GrGLUniformManager::BuilderUniformArray fUniforms;
312032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.com
313eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com    // TODO: Everything below here private.
314032b221dadb6eb8283ac2d1bc8913ee7bb5cfe7absalomon@google.compublic:
315eb715c8d5caa2191d611c4f9cfb22b4afc6c8d02bsalomon@google.com
316f0a104e6f16dc095286d32f1e104894ae0b2b19fbsalomon@google.com    SkString    fHeader; // VS+FS, GLSL version, etc
317f0a104e6f16dc095286d32f1e104894ae0b2b19fbsalomon@google.com    VarArray    fVSAttrs;
318f0a104e6f16dc095286d32f1e104894ae0b2b19fbsalomon@google.com    VarArray    fVSOutputs;
319f0a104e6f16dc095286d32f1e104894ae0b2b19fbsalomon@google.com    VarArray    fGSInputs;
320f0a104e6f16dc095286d32f1e104894ae0b2b19fbsalomon@google.com    VarArray    fGSOutputs;
321f0a104e6f16dc095286d32f1e104894ae0b2b19fbsalomon@google.com    VarArray    fFSInputs;
322f0a104e6f16dc095286d32f1e104894ae0b2b19fbsalomon@google.com    SkString    fGSHeader; // layout qualifiers specific to GS
323f0a104e6f16dc095286d32f1e104894ae0b2b19fbsalomon@google.com    VarArray    fFSOutputs;
324040c41a97c58b069015be3f5062eeb6ffe5adbfdtomhudson@google.com
325ad5e937c110efaf9630159d2859fabc4f38f7ab2bsalomon@google.comprivate:
326777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com    enum {
327777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com        kNonStageIdx = -1,
328777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com    };
329777c3aab0a902b0917871080d99b0a249ec06298bsalomon@google.com
33026e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    // Interpretation of DstReadKey when generating code
33126e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    enum {
33226e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com        kNoDstRead_DstReadKey         = 0,
33326e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com        kYesDstRead_DstReadKeyBit     = 0x1, // Set if we do a dst-copy-read.
33426e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com        kUseAlphaConfig_DstReadKeyBit = 0x2, // Set if dst-copy config is alpha only.
33526e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com        kTopLeftOrigin_DstReadKeyBit  = 0x4, // Set if dst-copy origin is top-left.
33626e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    };
33726e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
3386177e6999d23a4268ffd98dedfb1da00e272a89brobertphillips@google.com    const GrGLContextInfo&              fCtxInfo;
339706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com    GrGLUniformManager&                 fUniformManager;
34008283afc265f1153834256fc1012519813ba6b73bsalomon@google.com    int                                 fCurrentStageIdx;
341706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com    SkString                            fFSFunctions;
342706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com    SkString                            fFSHeader;
343706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com
34426e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    bool                                fUsesGS;
34526e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
346f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    SkString                            fFSCode;
347f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    SkString                            fVSCode;
348f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com    SkString                            fGSCode;
349f910d3b23bcf590ee937628dbab8e39a98ee5860bsalomon@google.com
350706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com    bool                                fSetupFragPosition;
35126e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    TextureSampler                      fDstCopySampler;
35226e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com
353706f66831a575bdc2b1ab1331b48b793cd487356bsalomon@google.com    GrGLUniformManager::UniformHandle   fRTHeightUniform;
35426e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    GrGLUniformManager::UniformHandle   fDstCopyTopLeftUniform;
35526e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com    GrGLUniformManager::UniformHandle   fDstCopyScaleUniform;
35634bcb9f80336fe0dc56ad5f67aeb0859bf84d92ebsalomon@google.com
357ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org    SkSTArray<10, AttributePair, true>  fEffectAttributes;
358ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org
35917504f5d5ea2550d29d2118193627129beb7f8b2bsalomon@google.com    GrGLShaderVar*                      fPositionVar;
360c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com    GrGLShaderVar*                      fLocalCoordsVar;
361c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com
362f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com};
363f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com
364f9ad8867f2bcd8563862b0a5a90b473ad020d465tomhudson@google.com#endif
365