aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/gl/builders/GrGLFullProgramBuilder.h
blob: 41da17ff9e9efb654e0bd71624537e424f6a6da2 (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
130
/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef GrGLFullProgramBuilder_DEFINED
#define GrGLFullProgramBuilder_DEFINED

#include "GrGLProgramBuilder.h"
#include "../GrGLGeometryProcessor.h"

class GrGLVertexProgramEffects;

class GrGLFullProgramBuilder : public GrGLProgramBuilder {
public:
    GrGLFullProgramBuilder(GrGpuGL*, const GrGLProgramDesc&);

   /** Add a varying variable to the current program to pass values between vertex and fragment
        shaders. If the last two parameters are non-NULL, they are filled in with the name
        generated. */
    void addVarying(GrSLType type,
                    const char* name,
                    const char** vsOutName = NULL,
                    const char** fsInName = NULL,
                    GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision);

    /** Add a separable varying input variable to the current program.
     * A separable varying (fragment shader input) is a varying that can be used also when vertex
     * shaders are not used. With a vertex shader, the operation is same as with other
     * varyings. Without a vertex shader, such as with NV_path_rendering, GL APIs are used to
     * populate the variable. The APIs can refer to the variable through the returned handle.
     */
    VaryingHandle addSeparableVarying(GrSLType type,
                                      const char* name,
                                      const char** vsOutName,
                                      const char** fsInName);

    GrGLVertexShaderBuilder* getVertexShaderBuilder() { return &fVS; }

    /*
     * This non-virtual call will hide the parent call to prevent GPs from accessing fragment shader
     * functionality they shouldn't be using
     */
    GrGLProcessorFragmentShaderBuilder* getFragmentShaderBuilder() { return &fFS; }

private:
    virtual void createAndEmitEffects(const GrGeometryStage* geometryProcessor,
                                      const GrFragmentStage* colorStages[],
                                      const GrFragmentStage* coverageStages[],
                                      GrGLSLExpr4* inputColor,
                                      GrGLSLExpr4* inputCoverage) SK_OVERRIDE;

    GrGLProgramEffects* onCreateAndEmitEffects(const GrFragmentStage* effectStages[],
                                               int effectCnt,
                                               const GrGLProgramDesc::EffectKeyProvider&,
                                               GrGLSLExpr4* inOutFSColor);

    class GrGLGeometryProcessorEmitter : public GrGLProgramBuilder::GrGLProcessorEmitterInterface {
        public:
            GrGLGeometryProcessorEmitter(GrGLFullProgramBuilder* builder)
                : fBuilder(builder)
                , fGeometryProcessor(NULL)
                , fGLGeometryProcessor(NULL) {}
            virtual ~GrGLGeometryProcessorEmitter() {}
            void set(const GrGeometryProcessor* gp) {
                SkASSERT(NULL == fGeometryProcessor);
                fGeometryProcessor = gp;
            }
            virtual GrGLProcessor* createGLInstance() {
                SkASSERT(fGeometryProcessor);
                SkASSERT(NULL == fGLGeometryProcessor);
                fGLGeometryProcessor =
                        fGeometryProcessor->getFactory().createGLInstance(*fGeometryProcessor);
                return fGLGeometryProcessor;
            }
            virtual void emit(const GrProcessorKey& key,
                              const char* outColor,
                              const char* inColor,
                              const GrGLProcessor::TransformedCoordsArray& coords,
                              const GrGLProcessor::TextureSamplerArray& samplers) {
                SkASSERT(fGeometryProcessor);
                SkASSERT(fGLGeometryProcessor);
                fGLGeometryProcessor->emitCode(fBuilder, *fGeometryProcessor, key, outColor,
                                               inColor, coords, samplers);
                // this will not leak because it has already been used by createGLInstance
                fGLGeometryProcessor = NULL;
                fGeometryProcessor = NULL;
            }
        private:
            GrGLFullProgramBuilder*     fBuilder;
            const GrGeometryProcessor*  fGeometryProcessor;
            GrGLGeometryProcessor*      fGLGeometryProcessor;
        };

    virtual void emitEffect(const GrProcessorStage& stage,
                            const GrProcessorKey& key,
                            const char* outColor,
                            const char* inColor,
                            int stageIndex) SK_OVERRIDE;

    /**
     * Helper for emitEffect(). Emits code to implement an effect's coord transforms in the VS.
     * Varyings are added as an outputs of the VS and inputs to the FS. The varyings may be either a
     * vec2f or vec3f depending upon whether perspective interpolation is required or not. The names
     * of the varyings in the VS and FS as well their types are appended to the
     * TransformedCoordsArray* object, which is in turn passed to the effect's emitCode() function.
     */
    void emitTransforms(const GrProcessorStage& effectStage,
                        GrGLProcessor::TransformedCoordsArray* outCoords);

    virtual bool compileAndAttachShaders(GrGLuint programId,
                                         SkTDArray<GrGLuint>* shaderIds) const SK_OVERRIDE;

    virtual void bindProgramLocations(GrGLuint programId) SK_OVERRIDE;

    virtual GrGLProgramEffects* getProgramEffects() SK_OVERRIDE { return fProgramEffects.get(); }

    typedef GrGLProgramDesc::EffectKeyProvider EffectKeyProvider;

    GrGLGeometryProcessorEmitter fGLGeometryProcessorEmitter;
    GrGLGeometryShaderBuilder fGS;
    GrGLVertexShaderBuilder   fVS;
    SkAutoTDelete<GrGLVertexProgramEffects> fProgramEffects;

    typedef GrGLProgramBuilder INHERITED;
};

#endif