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

#include "GrGLFragmentOnlyProgramBuilder.h"
#include "../GrGpuGL.h"

GrGLFragmentOnlyProgramBuilder::GrGLFragmentOnlyProgramBuilder(GrGpuGL* gpu,
                                                               const GrOptDrawState& optState,
                                                               const GrGLProgramDesc& desc)
    : INHERITED(gpu, optState, desc) {
    SkASSERT(desc.getHeader().fUseFragShaderOnly);
    SkASSERT(gpu->glCaps().pathRenderingSupport());
    SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput);
    SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput);
}

int GrGLFragmentOnlyProgramBuilder::addTexCoordSets(int count) {
    int firstFreeCoordSet = fTexCoordSetCnt;
    fTexCoordSetCnt += count;
    SkASSERT(gpu()->glCaps().maxFixedFunctionTextureCoords() >= fTexCoordSetCnt);
    return firstFreeCoordSet;
}

void
GrGLFragmentOnlyProgramBuilder::createAndEmitEffects(const GrGeometryStage* geometryProcessor,
                                                     const GrFragmentStage* colorStages[],
                                                     const GrFragmentStage* coverageStages[],
                                                     GrGLSLExpr4* inputColor,
                                                     GrGLSLExpr4* inputCoverage) {
    ///////////////////////////////////////////////////////////////////////////
    // emit the per-effect code for both color and coverage effects

    EffectKeyProvider colorKeyProvider(&this->desc(), EffectKeyProvider::kColor_EffectType);
    fColorEffects.reset(this->onCreateAndEmitEffects(colorStages,
                                                     this->desc().numColorEffects(),
                                                     colorKeyProvider,
                                                     inputColor));

    EffectKeyProvider coverageKeyProvider(&this->desc(), EffectKeyProvider::kCoverage_EffectType);
    fCoverageEffects.reset(this->onCreateAndEmitEffects(coverageStages,
                                                        this->desc().numCoverageEffects(),
                                                        coverageKeyProvider,
                                                        inputCoverage));
}

GrGLProgramEffects* GrGLFragmentOnlyProgramBuilder::onCreateAndEmitEffects(
        const GrFragmentStage* effectStages[], int effectCnt,
        const GrGLProgramDesc::EffectKeyProvider& keyProvider, GrGLSLExpr4* inOutFSColor) {
    fProgramEffects.reset(SkNEW_ARGS(GrGLPathTexGenProgramEffects, (effectCnt)));
    this->INHERITED::createAndEmitEffects(effectStages,
                                          effectCnt,
                                          keyProvider,
                                          inOutFSColor);
    return fProgramEffects.detach();
}

void GrGLFragmentOnlyProgramBuilder::emitEffect(const GrProcessorStage& stage,
                                                const GrProcessorKey& key,
                                                const char* outColor,
                                                const char* inColor,
                                                int stageIndex) {
    SkASSERT(fProgramEffects.get());
    const GrProcessor& effect = *stage.getProcessor();

    SkSTArray<2, GrGLProcessor::TransformedCoords> coords(effect.numTransforms());
    SkSTArray<4, GrGLProcessor::TextureSampler> samplers(effect.numTextures());

    this->setupPathTexGen(stage, &coords);
    this->emitSamplers(effect, &samplers);

    SkASSERT(fEffectEmitter);
    GrGLProcessor* glEffect = fEffectEmitter->createGLInstance();
    fProgramEffects->addEffect(glEffect);

    GrGLFragmentShaderBuilder* fsBuilder = this->getFragmentShaderBuilder();
    // Enclose custom code in a block to avoid namespace conflicts
    SkString openBrace;
    openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
    fsBuilder->codeAppend(openBrace.c_str());

    fEffectEmitter->emit(key, outColor, inColor, coords, samplers);

    fsBuilder->codeAppend("\t}\n");
}

void GrGLFragmentOnlyProgramBuilder::setupPathTexGen(
        const GrProcessorStage& effectStage, GrGLProcessor::TransformedCoordsArray* outCoords) {
    int numTransforms = effectStage.getProcessor()->numTransforms();
    int texCoordIndex = this->addTexCoordSets(numTransforms);

    fProgramEffects->addTransforms(texCoordIndex);

    SkString name;
    for (int t = 0; t < numTransforms; ++t) {
        GrSLType type =
                effectStage.isPerspectiveCoordTransform(t, false) ?
                        kVec3f_GrSLType :
                        kVec2f_GrSLType;

        name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
        SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords, (name, type));
    }
}