C++程序  |  216行  |  7.61 KB

/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrGLSL.h"
#include "GrGLShaderVar.h"
#include "SkString.h"

GrGLSLGeneration GrGetGLSLGeneration(GrGLBinding binding,
                                   const GrGLInterface* gl) {
    GrGLSLVersion ver = GrGLGetGLSLVersion(gl);
    switch (binding) {
        case kDesktop_GrGLBinding:
            GrAssert(ver >= GR_GLSL_VER(1,10));
            if (ver >= GR_GLSL_VER(1,50)) {
                return k150_GrGLSLGeneration;
            } else if (ver >= GR_GLSL_VER(1,40)) {
                return k140_GrGLSLGeneration;
            } else if (ver >= GR_GLSL_VER(1,30)) {
                return k130_GrGLSLGeneration;
            } else {
                return k110_GrGLSLGeneration;
            }
        case kES2_GrGLBinding:
            // version 1.00 of ES GLSL based on ver 1.20 of desktop GLSL
            GrAssert(ver >= GR_GL_VER(1,00));
            return k110_GrGLSLGeneration;
        default:
            GrCrash("Unknown GL Binding");
            return k110_GrGLSLGeneration; // suppress warning
    }
}

const char* GrGetGLSLVersionDecl(GrGLBinding binding,
                                   GrGLSLGeneration gen) {
    switch (gen) {
        case k110_GrGLSLGeneration:
            if (kES2_GrGLBinding == binding) {
                // ES2s shader language is based on version 1.20 but is version
                // 1.00 of the ES language.
                return "#version 100\n";
            } else {
                GrAssert(kDesktop_GrGLBinding == binding);
                return "#version 110\n";
            }
        case k130_GrGLSLGeneration:
            GrAssert(kDesktop_GrGLBinding == binding);
            return "#version 130\n";
        case k140_GrGLSLGeneration:
            GrAssert(kDesktop_GrGLBinding == binding);
            return "#version 140\n";
        case k150_GrGLSLGeneration:
            GrAssert(kDesktop_GrGLBinding == binding);
            return "#version 150\n";
        default:
            GrCrash("Unknown GL version.");
            return ""; // suppress warning
    }
}

bool GrGLSLSetupFSColorOuput(GrGLSLGeneration gen,
                             const char* nameIfDeclared,
                             GrGLShaderVar* var) {
    bool declaredOutput = k110_GrGLSLGeneration != gen;
    var->set(kVec4f_GrSLType,
             GrGLShaderVar::kOut_TypeModifier,
             declaredOutput ? nameIfDeclared : "gl_FragColor");
    return declaredOutput;
}

GrSLType GrSLFloatVectorType (int count) {
    GR_STATIC_ASSERT(kFloat_GrSLType == 1);
    GR_STATIC_ASSERT(kVec2f_GrSLType == 2);
    GR_STATIC_ASSERT(kVec3f_GrSLType == 3);
    GR_STATIC_ASSERT(kVec4f_GrSLType == 4);
    GrAssert(count > 0 && count <= 4);
    return (GrSLType)(count);
}

const char* GrGLSLVectorHomogCoord(int count) {
    static const char* HOMOGS[] = {"ERROR", "", ".y", ".z", ".w"};
    GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(HOMOGS));
    return HOMOGS[count];
}

const char* GrGLSLVectorHomogCoord(GrSLType type) {
    return GrGLSLVectorHomogCoord(GrSLTypeToVecLength(type));
}

const char* GrGLSLVectorNonhomogCoords(int count) {
    static const char* NONHOMOGS[] = {"ERROR", "", ".x", ".xy", ".xyz"};
    GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(NONHOMOGS));
    return NONHOMOGS[count];
}

const char* GrGLSLVectorNonhomogCoords(GrSLType type) {
    return GrGLSLVectorNonhomogCoords(GrSLTypeToVecLength(type));
}

GrSLConstantVec GrGLSLModulate4f(SkString* outAppend,
                                 const char* in0,
                                 const char* in1,
                                 GrSLConstantVec default0,
                                 GrSLConstantVec default1) {
    GrAssert(NULL != outAppend);

    bool has0 = NULL != in0 && '\0' != *in0;
    bool has1 = NULL != in1 && '\0' != *in1;

    GrAssert(has0 || kNone_GrSLConstantVec != default0);
    GrAssert(has1 || kNone_GrSLConstantVec != default1);

    if (!has0 && !has1) {
        GrAssert(kZeros_GrSLConstantVec == default0 || kOnes_GrSLConstantVec == default0);
        GrAssert(kZeros_GrSLConstantVec == default1 || kOnes_GrSLConstantVec == default1);
        if (kZeros_GrSLConstantVec == default0 || kZeros_GrSLConstantVec == default1) {
            outAppend->append(GrGLSLZerosVecf(4));
            return kZeros_GrSLConstantVec;
        } else {
            // both inputs are ones vectors
            outAppend->append(GrGLSLOnesVecf(4));
            return kOnes_GrSLConstantVec;
        }
    } else if (!has0) {
        GrAssert(kZeros_GrSLConstantVec == default0 || kOnes_GrSLConstantVec == default0);
        if (kZeros_GrSLConstantVec == default0) {
            outAppend->append(GrGLSLZerosVecf(4));
            return kZeros_GrSLConstantVec;
        } else {
            outAppend->appendf("vec4(%s)", in1);
            return kNone_GrSLConstantVec;
        }
    } else if (!has1) {
        GrAssert(kZeros_GrSLConstantVec == default1 || kOnes_GrSLConstantVec == default1);
        if (kZeros_GrSLConstantVec == default1) {
            outAppend->append(GrGLSLZerosVecf(4));
            return kZeros_GrSLConstantVec;
        } else {
            outAppend->appendf("vec4(%s)", in0);
            return kNone_GrSLConstantVec;
        }
    } else {
        outAppend->appendf("vec4(%s * %s)", in0, in1);
        return kNone_GrSLConstantVec;
    }
}

namespace {
void append_tabs(SkString* outAppend, int tabCnt) {
    static const char kTabs[] = "\t\t\t\t\t\t\t\t";
    while (tabCnt) {
        int cnt = GrMin((int)GR_ARRAY_COUNT(kTabs), tabCnt);
        outAppend->append(kTabs, cnt);
        tabCnt -= cnt;
    }
}
}

GrSLConstantVec GrGLSLMulVarBy4f(SkString* outAppend,
                                 int tabCnt,
                                 const char* vec4VarName,
                                 const char* mulFactor,
                                 GrSLConstantVec mulFactorDefault) {
    bool haveFactor = NULL != mulFactor && '\0' != *mulFactor;

    GrAssert(NULL != outAppend);
    GrAssert(NULL != vec4VarName);
    GrAssert(kNone_GrSLConstantVec != mulFactorDefault || haveFactor);

    if (!haveFactor) {
        if (kOnes_GrSLConstantVec == mulFactorDefault) {
            return kNone_GrSLConstantVec;
        } else {
            GrAssert(kZeros_GrSLConstantVec == mulFactorDefault);
            append_tabs(outAppend, tabCnt);
            outAppend->appendf("%s = vec4(0, 0, 0, 0);\n", vec4VarName);
            return kZeros_GrSLConstantVec;
        }
    }
    append_tabs(outAppend, tabCnt);
    outAppend->appendf("%s *= %s;\n", vec4VarName, mulFactor);
    return kNone_GrSLConstantVec;
}

GrSLConstantVec GrGLSLAdd4f(SkString* outAppend,
                            const char* in0,
                            const char* in1,
                            GrSLConstantVec default0,
                            GrSLConstantVec default1) {
    GrAssert(NULL != outAppend);

    bool has0 = NULL != in0 && '\0' != *in0;
    bool has1 = NULL != in1 && '\0' != *in1;

    if (!has0 && !has1) {
        GrAssert(kZeros_GrSLConstantVec == default0);
        GrAssert(kZeros_GrSLConstantVec == default1);
        outAppend->append(GrGLSLZerosVecf(4));
        return kZeros_GrSLConstantVec;
    } else if (!has0) {
        GrAssert(kZeros_GrSLConstantVec == default0);
        outAppend->appendf("vec4(%s)", in1);
        return kNone_GrSLConstantVec;
    } else if (!has1) {
        GrAssert(kZeros_GrSLConstantVec == default1);
        outAppend->appendf("vec4(%s)", in0);
        return kNone_GrSLConstantVec;
    } else {
        outAppend->appendf("(vec4(%s) + vec4(%s))", in0, in1);
        return kNone_GrSLConstantVec;
    }
}