Express (GLSL expression, possibly known value) pairs as a class

Express (GLSL expression, possibly known value) pairs as a class
instead of two variables Introduces GrGLSLExpr<N> to encapsulate
the expression and possibly constant-folded value of the expression.

This simplifies passing of the expressions to functions.

Changes the shaders with following patterns:
        { // Stage 0: Linear Gradient
        vec4 colorTemp = mix(uGradientStartColor_Stage0, uGradientEndColor_Stage0, clamp(vMatrixCoord_Stage0.x, 0.0, 1
        colorTemp.rgb *= colorTemp.a;
-       output_Stage0 = vec4((vColor) * (colorTemp));
+       output_Stage0 = (vColor * colorTemp);
+       }

Previously the vector cast was always added if constant folding was
effective, regardless of the term dimensions. Now the vector upcast is
not inserted in places where it is not needed, ie. when the binary
operator term is of the target dimension.

Also, some parentheses can be omitted. It is assumed that
GrGLSLExpr<N>("string") constructors construct a simple expression or
parenthesized expression.

Otherwise the shader code remains identical.

R=jvanverth@google.com, bsalomon@google.com, robertphillips@google.com

Author: kkinnunen@nvidia.com

Review URL: https://codereview.chromium.org/25048002

git-svn-id: http://skia.googlecode.com/svn/trunk@11690 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
commit-bot@chromium.org 2013-10-10 06:30:18 +00:00
parent ab9d30cb01
commit 824c346b6e
18 changed files with 420 additions and 570 deletions

View File

@ -944,7 +944,7 @@ public:
// We don't try to optimize for this case at all
if (NULL == inputColor) {
builder->fsCodeAppendf("\t\tconst vec4 ones = %s;\n", GrGLSLOnesVecf(4));
builder->fsCodeAppendf("\t\tconst vec4 ones = vec4(1);\n");
inputColor = "ones";
}
builder->fsCodeAppendf("\t\t// SkXfermode::Mode: %s\n", SkXfermode::ModeName(mode));

View File

@ -366,7 +366,7 @@ void GrGLArithmeticEffect::emitCode(GrGLShaderBuilder* builder,
// We don't try to optimize for this case at all
if (NULL == inputColor) {
builder->fsCodeAppendf("\t\tconst vec4 src = %s;\n", GrGLSLOnesVecf(4));
builder->fsCodeAppendf("\t\tconst vec4 src = vec4(1);\n");
} else {
builder->fsCodeAppendf("\t\tvec4 src = %s;\n", inputColor);
if (gUseUnpremul) {

View File

@ -149,12 +149,8 @@ public:
"\t\t\tcolor.a = thresh;\n"
"\t\t}\n");
builder->fsCodeAppend("color = ");
SkString outStr;
outStr.appendf("\t\t%s = ", outputColor);
GrGLSLModulatef<4>(&outStr, inputColor, "color");
outStr.append(";\n");
builder->fsCodeAppend(outStr.c_str());
builder->fsCodeAppendf("color = %s = %s;\n", outputColor,
(GrGLSLExpr<4>(inputColor) * GrGLSLExpr<4>("color")).c_str());
}
virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect& e) SK_OVERRIDE {

View File

@ -410,7 +410,7 @@ public:
if (NULL == inputColor) {
// could optimize this case, but we aren't for now.
inputColor = GrGLSLOnesVecf(4);
inputColor = "vec4(1)";
}
// The max() is to guard against 0 / 0 during unpremul when the incoming color is
// transparent black.

View File

@ -120,7 +120,7 @@ public:
const TransformedCoordsArray&,
const TextureSamplerArray&) SK_OVERRIDE {
if (NULL == inputColor) {
inputColor = GrGLSLOnesVecf(4);
inputColor = "vec4(1)";
}
// The max() is to guard against 0 / 0 during unpremul when the incoming color is

View File

@ -214,7 +214,7 @@ void GrGLLumaMaskEffect::emitCode(GrGLShaderBuilder* builder,
const char* dstColor = builder->dstColor();
SkASSERT(NULL != dstColor);
if (NULL == inputColor) {
inputColor = GrGLSLOnesVecf(4);
inputColor = "vec4(1)";
}
const char *opA = lumaOpA<char>(lumaEffect.getMode(), inputColor, dstColor);

View File

@ -950,11 +950,8 @@ void GrGLGradientEffect::emitColor(GrGLShaderBuilder* builder,
builder->fsCodeAppend("\tcolorTemp.rgb *= colorTemp.a;\n");
}
SkString output;
builder->fsCodeAppendf("\t%s = ", outputColor);
GrGLSLModulatef<4>(&output, inputColor, "colorTemp");
builder->fsCodeAppend(output.c_str());
builder->fsCodeAppend(";\n");
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr<4>(inputColor) * GrGLSLExpr<4>("colorTemp")).c_str());
} else if (GrGradientEffect::kThree_ColorType == ColorTypeFromKey(key)){
builder->fsCodeAppendf("\tfloat oneMinus2t = 1.0 - (2.0 * (%s));\n",
gradientTValue);
@ -977,11 +974,8 @@ void GrGLGradientEffect::emitColor(GrGLShaderBuilder* builder,
builder->fsCodeAppend("\tcolorTemp.rgb *= colorTemp.a;\n");
}
SkString output;
builder->fsCodeAppendf("\t%s = ", outputColor);
GrGLSLModulatef<4>(&output, inputColor, "colorTemp");
builder->fsCodeAppend(output.c_str());
builder->fsCodeAppend(";\n");
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr<4>(inputColor) * GrGLSLExpr<4>("colorTemp")).c_str());
} else {
builder->fsCodeAppendf("\tvec2 coord = vec2(%s, %s);\n",
gradientTValue,

View File

@ -559,9 +559,9 @@ public:
builder->fsCodeAppendf("\t\t\tedgeAlpha = "
"clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);\n\t\t}\n");
SkString modulate;
GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha");
builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("edgeAlpha")).c_str());
builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str());
}

View File

@ -84,9 +84,9 @@ public:
"\tcoverage = coverage*scaleH*clamp((%s.w-abs(%s.y))/spanH, 0.0, 1.0);\n",
fsRectName, fsRectName);
SkString modulate;
GrGLSLModulatef<4>(&modulate, inputColor, "coverage");
builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("coverage")).c_str());
}
static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
@ -217,9 +217,9 @@ public:
"\tcoverage = coverage*scaleH*clamp((%s.y-perpDot)/spanH, 0.0, 1.0);\n",
fsWidthHeightName);
SkString modulate;
GrGLSLModulatef<4>(&modulate, inputColor, "coverage");
builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("coverage")).c_str());
}
static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {

View File

@ -116,9 +116,8 @@ public:
builder->fsCodeAppend("\tedgeAlpha *= innerAlpha;\n");
}
SkString modulate;
GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha");
builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("edgeAlpha")).c_str());
}
static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
@ -249,9 +248,8 @@ public:
builder->fsCodeAppend("\tedgeAlpha *= clamp(0.5+test*invlen, 0.0, 1.0);\n");
}
SkString modulate;
GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha");
builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("edgeAlpha")).c_str());
}
static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
@ -408,9 +406,8 @@ public:
builder->fsCodeAppend("\tedgeAlpha *= clamp(0.5+test*invlen, 0.0, 1.0);\n");
}
SkString modulate;
GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha");
builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("edgeAlpha")).c_str());
}
static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {

View File

@ -110,9 +110,8 @@ void GrGLConicEffect::emitCode(GrGLFullShaderBuilder* builder,
}
}
SkString modulate;
GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha");
builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("edgeAlpha")).c_str());
}
GrGLEffect::EffectKey GrGLConicEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
@ -239,9 +238,9 @@ void GrGLQuadEffect::emitCode(GrGLFullShaderBuilder* builder,
}
}
SkString modulate;
GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha");
builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("edgeAlpha")).c_str());
builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str());
}
@ -383,9 +382,8 @@ void GrGLCubicEffect::emitCode(GrGLFullShaderBuilder* builder,
}
}
SkString modulate;
GrGLSLModulatef<4>(&modulate, inputColor, "edgeAlpha");
builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
builder->fsCodeAppendf("\t%s = %s;\n", outputColor,
(GrGLSLExpr<4>(inputColor) * GrGLSLExpr<1>("edgeAlpha")).c_str());
}
GrGLEffect::EffectKey GrGLCubicEffect::GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {

View File

@ -158,13 +158,13 @@ inline void blend_term_string(SkString* str, SkXfermode::Coeff coeff,
str->printf("(%s * %s)", src, value);
break;
case SkXfermode::kISC_Coeff:
str->printf("((%s - %s) * %s)", GrGLSLOnesVecf(4), src, value);
str->printf("((vec4(1) - %s) * %s)", src, value);
break;
case SkXfermode::kDC_Coeff:
str->printf("(%s * %s)", dst, value);
break;
case SkXfermode::kIDC_Coeff:
str->printf("((%s - %s) * %s)", GrGLSLOnesVecf(4), dst, value);
str->printf("((vec4(1) - %s) * %s)", dst, value);
break;
case SkXfermode::kSA_Coeff: /** src alpha */
str->printf("(%s.a * %s)", src, value);
@ -196,31 +196,20 @@ void add_color_filter(GrGLShaderBuilder* builder,
SkString colorStr, constStr;
blend_term_string(&colorStr, colorCoeff, filterColor, inColor, inColor);
blend_term_string(&constStr, uniformCoeff, filterColor, inColor, filterColor);
SkString sum;
GrGLSLAddf<4>(&sum, colorStr.c_str(), constStr.c_str());
GrGLSLExpr<4> sum;
if (colorStr.isEmpty() && constStr.isEmpty()) {
sum = GrGLSLExpr<4>(0);
} else if (colorStr.isEmpty()) {
sum = constStr;
} else if (constStr.isEmpty()) {
sum = colorStr;
} else {
sum = GrGLSLExpr<4>(colorStr) + GrGLSLExpr<4>(constStr);
}
builder->fsCodeAppendf("\t%s = %s;\n", outputVar, sum.c_str());
}
}
namespace {
void expand_known_value4f(SkString* string, GrSLConstantVec vec) {
SkASSERT(string->isEmpty() == (vec != kNone_GrSLConstantVec));
switch (vec) {
case kNone_GrSLConstantVec:
break;
case kZeros_GrSLConstantVec:
*string = GrGLSLZerosVecf(4);
break;
case kOnes_GrSLConstantVec:
*string = GrGLSLOnesVecf(4);
break;
}
}
}
bool GrGLProgram::genProgram(GrGLShaderBuilder* builder,
const GrEffectStage* colorStages[],
const GrEffectStage* coverageStages[]) {
@ -229,8 +218,7 @@ bool GrGLProgram::genProgram(GrGLShaderBuilder* builder,
const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
// incoming color to current stage being processed.
SkString inColor = builder->getInputColor();
GrSLConstantVec knownColorValue = builder->getKnownColorValue();
GrGLSLExpr<4> inColor = builder->getInputColor();
// Get the coeffs for the Mode-based color filter, determine if color is needed.
SkXfermode::Coeff colorCoeff;
@ -246,8 +234,7 @@ bool GrGLProgram::genProgram(GrGLShaderBuilder* builder,
builder->createAndEmitEffects(colorStages,
fDesc.effectKeys(),
needColor ? fDesc.numColorEffects() : 0,
&inColor,
&knownColorValue));
&inColor));
// Insert the color filter. This will soon be replaced by a color effect.
if (SkXfermode::kDst_Mode != header.fColorFilterXfermode) {
@ -257,35 +244,24 @@ bool GrGLProgram::genProgram(GrGLShaderBuilder* builder,
&colorFilterColorUniName);
builder->fsCodeAppend("\tvec4 filteredColor;\n");
const char* color;
// add_color_filter requires a real input string.
if (knownColorValue == kOnes_GrSLConstantVec) {
color = GrGLSLOnesVecf(4);
} else if (knownColorValue == kZeros_GrSLConstantVec) {
color = GrGLSLZerosVecf(4);
} else {
color = inColor.c_str();
}
add_color_filter(builder, "filteredColor", filterColorCoeff,
colorCoeff, colorFilterColorUniName, color);
colorCoeff, colorFilterColorUniName, inColor.c_str());
inColor = "filteredColor";
}
///////////////////////////////////////////////////////////////////////////
// compute the partial coverage
SkString inCoverage = builder->getInputCoverage();
GrSLConstantVec knownCoverageValue = builder->getKnownCoverageValue();
GrGLSLExpr<4> inCoverage = builder->getInputCoverage();
fCoverageEffects.reset(
builder->createAndEmitEffects(coverageStages,
fDesc.getEffectKeys() + fDesc.numColorEffects(),
fDesc.numCoverageEffects(),
&inCoverage,
&knownCoverageValue));
&inCoverage));
// discard if coverage is zero
if (header.fDiscardIfZeroCoverage && kOnes_GrSLConstantVec != knownCoverageValue) {
if (kZeros_GrSLConstantVec == knownCoverageValue) {
if (header.fDiscardIfZeroCoverage && !inCoverage.isOnes()) {
if (inCoverage.isZeros()) {
// This is unfortunate.
builder->fsCodeAppend("\tdiscard;\n");
} else {
@ -298,79 +274,30 @@ bool GrGLProgram::genProgram(GrGLShaderBuilder* builder,
const char* secondaryOutputName = builder->enableSecondaryOutput();
// default coeff to ones for kCoverage_DualSrcOutput
SkString coeff;
GrSLConstantVec knownCoeffValue = kOnes_GrSLConstantVec;
GrGLSLExpr<4> coeff(1);
if (GrGLProgramDesc::kSecondaryCoverageISA_CoverageOutput == header.fCoverageOutput) {
// Get (1-A) into coeff
SkString inColorAlpha;
GrGLSLGetComponent4f(&inColorAlpha,
inColor.c_str(),
kA_GrColorComponentFlag,
knownColorValue,
true);
knownCoeffValue = GrGLSLSubtractf<1>(&coeff,
NULL,
inColorAlpha.c_str(),
kOnes_GrSLConstantVec,
knownColorValue,
true);
coeff = GrGLSLExprCast4(GrGLSLExpr<1>(1) - GrGLSLExprExtractAlpha(inColor));
} else if (GrGLProgramDesc::kSecondaryCoverageISC_CoverageOutput == header.fCoverageOutput) {
// Get (1-RGBA) into coeff
knownCoeffValue = GrGLSLSubtractf<4>(&coeff,
NULL,
inColor.c_str(),
kOnes_GrSLConstantVec,
knownColorValue,
true);
coeff = GrGLSLExpr<4>(1) - inColor;
}
// Get coeff * coverage into modulate and then write that to the dual source output.
SkString modulate;
GrGLSLModulatef<4>(&modulate,
coeff.c_str(),
inCoverage.c_str(),
knownCoeffValue,
knownCoverageValue,
false);
builder->fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, modulate.c_str());
builder->fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, (coeff * inCoverage).c_str());
}
///////////////////////////////////////////////////////////////////////////
// combine color and coverage as frag color
// Get "color * coverage" into fragColor
SkString fragColor;
GrSLConstantVec knownFragColorValue = GrGLSLModulatef<4>(&fragColor,
inColor.c_str(),
inCoverage.c_str(),
knownColorValue,
knownCoverageValue,
true);
GrGLSLExpr<4> fragColor = inColor * inCoverage;
// Now tack on "+(1-coverage)dst onto the frag color if we were asked to do so.
if (GrGLProgramDesc::kCombineWithDst_CoverageOutput == header.fCoverageOutput) {
SkString dstCoeff;
GrSLConstantVec knownDstCoeffValue = GrGLSLSubtractf<4>(&dstCoeff,
NULL,
inCoverage.c_str(),
kOnes_GrSLConstantVec,
knownCoverageValue,
true);
SkString dstContribution;
GrSLConstantVec knownDstContributionValue = GrGLSLModulatef<4>(&dstContribution,
dstCoeff.c_str(),
builder->dstColor(),
knownDstCoeffValue,
kNone_GrSLConstantVec,
true);
SkString oldFragColor = fragColor;
fragColor.reset();
GrGLSLAddf<4>(&fragColor,
oldFragColor.c_str(),
dstContribution.c_str(),
knownFragColorValue,
knownDstContributionValue,
false);
} else {
expand_known_value4f(&fragColor, knownFragColorValue);
GrGLSLExpr<4> dstCoeff = GrGLSLExpr<4>(1) - inCoverage;
GrGLSLExpr<4> dstContribution = dstCoeff * GrGLSLExpr<4>(builder->dstColor());
fragColor = fragColor + dstContribution;
}
builder->fsCodeAppendf("\t%s = %s;\n", builder->getColorOutputName(), fragColor.c_str());

View File

@ -113,17 +113,6 @@ private:
kColorInputCnt
};
static GrSLConstantVec KnownColorInputValue(ColorInput ci) {
switch (ci) {
case GrGLProgramDesc::kTransBlack_ColorInput:
return kZeros_GrSLConstantVec;
case GrGLProgramDesc::kSolidWhite_ColorInput:
return kOnes_GrSLConstantVec;
default:
return kNone_GrSLConstantVec;
}
}
enum CoverageOutput {
// modulate color and coverage, write result as the color output.
kModulate_CoverageOutput,

View File

@ -63,26 +63,6 @@ const char* GrGetGLSLVersionDecl(const GrGLContextInfo& info) {
}
}
const char* GrGLSLVectorHomogCoord(int count) {
static const char* HOMOGS[] = {"ERROR", "", ".y", ".z", ".w"};
SkASSERT(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"};
SkASSERT(count >= 1 && count < (int)GR_ARRAY_COUNT(NONHOMOGS));
return NONHOMOGS[count];
}
const char* GrGLSLVectorNonhomogCoords(GrSLType type) {
return GrGLSLVectorNonhomogCoords(GrSLTypeToVecLength(type));
}
namespace {
void append_tabs(SkString* outAppend, int tabCnt) {
static const char kTabs[] = "\t\t\t\t\t\t\t\t";
@ -94,50 +74,19 @@ namespace {
}
}
GrSLConstantVec GrGLSLMulVarBy4f(SkString* outAppend,
int tabCnt,
const char* vec4VarName,
const char* mulFactor,
GrSLConstantVec mulFactorDefault) {
bool haveFactor = NULL != mulFactor && '\0' != *mulFactor;
SkASSERT(NULL != outAppend);
SkASSERT(NULL != vec4VarName);
SkASSERT(kNone_GrSLConstantVec != mulFactorDefault || haveFactor);
if (!haveFactor) {
if (kOnes_GrSLConstantVec == mulFactorDefault) {
return kNone_GrSLConstantVec;
} else {
SkASSERT(kZeros_GrSLConstantVec == mulFactorDefault);
append_tabs(outAppend, tabCnt);
outAppend->appendf("%s = vec4(0, 0, 0, 0);\n", vec4VarName);
return kZeros_GrSLConstantVec;
}
void GrGLSLMulVarBy4f(SkString* outAppend,
unsigned tabCnt,
const char* vec4VarName,
const GrGLSLExpr<4>& mulFactor) {
if (mulFactor.isOnes()) {
*outAppend = SkString();
}
append_tabs(outAppend, tabCnt);
outAppend->appendf("%s *= %s;\n", vec4VarName, mulFactor);
return kNone_GrSLConstantVec;
if (mulFactor.isZeros()) {
outAppend->appendf("%s = vec4(0);\n", vec4VarName);
}
outAppend->appendf("%s *= %s;\n", vec4VarName, mulFactor.c_str());
}
GrSLConstantVec GrGLSLGetComponent4f(SkString* outAppend,
const char* expr,
GrColorComponentFlags component,
GrSLConstantVec defaultExpr,
bool omitIfConst) {
if (NULL == expr || '\0' == *expr) {
SkASSERT(defaultExpr != kNone_GrSLConstantVec);
if (!omitIfConst) {
if (kOnes_GrSLConstantVec == defaultExpr) {
outAppend->append("1.0");
} else {
SkASSERT(kZeros_GrSLConstantVec == defaultExpr);
outAppend->append("0.0");
}
}
return defaultExpr;
} else {
outAppend->appendf("(%s).%c", expr, GrColorComponentFlagToChar(component));
return kNone_GrSLConstantVec;
}
}

View File

@ -11,10 +11,10 @@
#include "gl/GrGLInterface.h"
#include "GrColor.h"
#include "GrTypesPriv.h"
#include "SkString.h"
class GrGLContextInfo;
class GrGLShaderVar;
class SkString;
// Limited set of GLSL versions we build shaders for. Caller should round
// down the GLSL version to one of these enums.
@ -37,43 +37,6 @@ enum GrGLSLGeneration {
k150_GrGLSLGeneration,
};
enum GrSLConstantVec {
kZeros_GrSLConstantVec,
kOnes_GrSLConstantVec,
kNone_GrSLConstantVec,
};
namespace {
static inline int GrSLTypeToVecLength(GrSLType type) {
static const int kVecLengths[] = {
0, // kVoid_GrSLType
1, // kFloat_GrSLType
2, // kVec2f_GrSLType
3, // kVec3f_GrSLType
4, // kVec4f_GrSLType
1, // kMat33f_GrSLType
1, // kMat44f_GrSLType
1, // kSampler2D_GrSLType
};
GR_STATIC_ASSERT(kGrSLTypeCount == GR_ARRAY_COUNT(kVecLengths));
return kVecLengths[type];
}
static inline const char* GrGLSLOnesVecf(int count) {
static const char* kONESVEC[] = {"ERROR", "1.0", "vec2(1,1)",
"vec3(1,1,1)", "vec4(1,1,1,1)"};
SkASSERT(count >= 1 && count < (int)GR_ARRAY_COUNT(kONESVEC));
return kONESVEC[count];
}
static inline const char* GrGLSLZerosVecf(int count) {
static const char* kZEROSVEC[] = {"ERROR", "0.0", "vec2(0,0)",
"vec3(0,0,0)", "vec4(0,0,0,0)"};
SkASSERT(count >= 1 && count < (int)GR_ARRAY_COUNT(kZEROSVEC));
return kZEROSVEC[count];
}
}
/**
* Gets the most recent GLSL Generation compatible with the OpenGL context.
*/
@ -89,7 +52,7 @@ const char* GrGetGLSLVersionDecl(const GrGLContextInfo&);
/**
* Converts a GrSLType to a string containing the name of the equivalent GLSL type.
*/
static const char* GrGLSLTypeString(GrSLType t) {
static inline const char* GrGLSLTypeString(GrSLType t) {
switch (t) {
case kVoid_GrSLType:
return "void";
@ -113,101 +76,203 @@ static const char* GrGLSLTypeString(GrSLType t) {
}
}
/** Return the type enum for a vector of floats of length n (1..4),
e.g. 1 -> "float", 2 -> "vec2", ... */
static inline const char* GrGLSLFloatVectorTypeString(int n) {
return GrGLSLTypeString(GrSLFloatVectorType(n));
/** A class representing a GLSL expression.
* The instance can be a variable name, expression or vecN(0) or vecN(1). Does simple constant
* folding with help of 1 and 0.
* Complex expressions can be constructed with operators *, +, -
*/
template <int N>
class GrGLSLExpr {
public:
/** Constructs an invalid expression.
* Useful only as a return value from functions that never actually return
* this and instances that will be assigned to later. */
GrGLSLExpr()
: fType(kFullExpr_ExprType) {
SK_COMPILE_ASSERT(N > 0 && N <= 4, dimensions_not_in_range);
// The only constructor that is allowed to build an empty expression.
SkASSERT(!this->isValid());
}
/** Constructs an expression with all components as value v */
explicit GrGLSLExpr(int v) {
SK_COMPILE_ASSERT(N > 0 && N <= 4, dimensions_not_in_range);
if (v == 0) {
fType = kZeros_ExprType;
} else if (v == 1) {
fType = kOnes_ExprType;
} else {
fType = kFullExpr_ExprType;
fExpr.appendf(CastIntStr(), v);
}
}
/** Constructs an expression from a string.
* Argument expr is a simple expression or a parenthesized expression. */
// TODO: make explicit once effects input Exprs.
GrGLSLExpr(const char expr[]) {
SK_COMPILE_ASSERT(N > 0 && N <= 4, dimensions_not_in_range);
if (NULL == expr) { // TODO: remove this once effects input Exprs.
fType = kOnes_ExprType;
} else {
fType = kFullExpr_ExprType;
fExpr = expr;
}
SkASSERT(this->isValid());
}
/** Constructs an expression from a string.
* Argument expr is a simple expression or a parenthesized expression. */
// TODO: make explicit once effects input Exprs.
GrGLSLExpr(const SkString& expr) {
SK_COMPILE_ASSERT(N > 0 && N <= 4, dimensions_not_in_range);
if (expr.isEmpty()) { // TODO: remove this once effects input Exprs.
fType = kOnes_ExprType;
} else {
fType = kFullExpr_ExprType;
fExpr = expr;
}
SkASSERT(this->isValid());
}
bool isOnes() const { return kOnes_ExprType == fType; }
bool isZeros() const { return kZeros_ExprType == fType; }
const char* c_str() const {
if (kZeros_ExprType == fType) {
return ZerosStr();
} else if (kOnes_ExprType == fType) {
return OnesStr();
}
SkASSERT(!fExpr.isEmpty()); // Empty expressions should not be used.
return fExpr.c_str();
}
private:
GrGLSLExpr(const char format[], const char in0[])
: fType(kFullExpr_ExprType) {
fExpr.appendf(format, in0);
}
GrGLSLExpr(const char format[], const char in0[], const char in1[])
: fType(kFullExpr_ExprType) {
fExpr.appendf(format, in0, in1);
}
GrGLSLExpr(const char format[], const char in0[], char in1)
: fType(kFullExpr_ExprType) {
fExpr.appendf(format, in0, in1);
}
bool isValid() const {
return kFullExpr_ExprType != fType || !fExpr.isEmpty();
}
static const char* ZerosStr();
static const char* OnesStr();
static const char* ExtractAlphaStr();
static const char* CastStr();
static const char* CastIntStr();
/** Casts the expression expr into smaller or bigger expression.
* Casting is done with GLSL rules:
* M==3, N==4 vec3(a, b, c) -> vec4(a, b, c, 0)
* N==4, M==3 vec4(a, b, c, d) -> vec3(a, b, c)
*/
template <int M>
static GrGLSLExpr<N> VectorCast(const GrGLSLExpr<M>& expr);
/** GLSL multiplication: component-wise or multiply each component by a scalar.
* M == N --> vecN(in0.x * in1.x, ...)
* M == 1 --> vecN(in0.x * in1, ...)
* otherwise --> compile-time error
*/
template <int M>
static GrGLSLExpr<N> Mul(const GrGLSLExpr<N>& in0, const GrGLSLExpr<M>& in1);
/** GLSL addition: component-wise or add a scalar to each compoment.
* M == N --> vecN(in0.x + in1.x, ...)
* M == 1 --> vecN(in0.x + in1, ...)
* otherwise --> compile-time error
*/
template <int M>
static GrGLSLExpr<N> Add(const GrGLSLExpr<N>& in0, const GrGLSLExpr<M>& in1);
/** GLSL subtraction: component-wise or subtract compoments by a scalar.
* M == N --> vecN(in0.x - in1.x, ...)
* M == 1 --> vecN(in0.x - in1, ...)
* otherwise --> compile-time error
*/
template <int M>
static GrGLSLExpr<N> Sub(const GrGLSLExpr<N>& in0, const GrGLSLExpr<M>& in1);
enum ExprType {
kZeros_ExprType,
kOnes_ExprType,
kFullExpr_ExprType,
};
ExprType fType;
SkString fExpr;
template <int> friend class GrGLSLExpr;
/** Multiplies two expressions component-wise. */
template <int M> friend GrGLSLExpr<M> operator*(const GrGLSLExpr<M>&, const GrGLSLExpr<M>&);
/** Adds two expressions component-wise. */
template <int M> friend GrGLSLExpr<M> operator+(const GrGLSLExpr<M>&, const GrGLSLExpr<M>&);
/** Subtracts two expressions component-wise. */
template <int M> friend GrGLSLExpr<M> operator-(const GrGLSLExpr<M>&, const GrGLSLExpr<M>&);
/** Multiplies every component of an expression with a scalar expression. */
friend GrGLSLExpr<4> operator*(const GrGLSLExpr<4>&, const GrGLSLExpr<1>&);
/** Adds a scalar expression to every component of an expression. */
friend GrGLSLExpr<4> operator+(const GrGLSLExpr<4>&, const GrGLSLExpr<1>&);
/** Subtracts a scalar expression from every component of an expression. */
friend GrGLSLExpr<4> operator-(const GrGLSLExpr<4>&, const GrGLSLExpr<1>&);
friend GrGLSLExpr<1> GrGLSLExprExtractAlpha(const GrGLSLExpr<4>& expr);
friend GrGLSLExpr<4> GrGLSLExprCast4(const GrGLSLExpr<1>& expr);
};
template <int N>
inline GrGLSLExpr<N> operator*(const GrGLSLExpr<N>& in0, const GrGLSLExpr<N>&in1) {
return GrGLSLExpr<N>::Mul(in0, in1);
}
/** Return the GLSL swizzle operator for a homogenous component of a vector
with the given number of coordinates, e.g. 2 -> ".y", 3 -> ".z" */
const char* GrGLSLVectorHomogCoord(int count);
const char* GrGLSLVectorHomogCoord(GrSLType type);
/** Return the GLSL swizzle operator for a nonhomogenous components of a vector
with the given number of coordinates, e.g. 2 -> ".x", 3 -> ".xy" */
const char* GrGLSLVectorNonhomogCoords(int count);
const char* GrGLSLVectorNonhomogCoords(GrSLType type);
/**
* Produces a string that is the result of modulating two inputs. The inputs must be vecN or
* float. The result is always a vecN. The inputs may be expressions, not just identifier names.
* Either can be NULL or "" in which case the default params control whether a vector of ones or
* zeros. It is an error to pass kNone for default<i> if in<i> is NULL or "". Note that when the
* function determines that the result is a zeros or ones vec then any expression represented by
* or in1 will not be emitted (side effects won't occur). The return value indicates whether a
* known zeros or ones vector resulted. The output can be suppressed when known vector is produced
* by passing true for omitIfConstVec.
*/
template <int N>
GrSLConstantVec GrGLSLModulatef(SkString* outAppend,
const char* in0,
const char* in1,
GrSLConstantVec default0 = kOnes_GrSLConstantVec,
GrSLConstantVec default1 = kOnes_GrSLConstantVec,
bool omitIfConstVec = false);
inline GrGLSLExpr<N> operator+(const GrGLSLExpr<N>& in0, const GrGLSLExpr<N>&in1) {
return GrGLSLExpr<N>::Add(in0, in1);
}
/**
* Produces a string that is the result of adding two inputs. The inputs must be vecN or
* float. The result is always a vecN. The inputs may be expressions, not just identifier names.
* Either can be NULL or "" in which case the default params control whether a vector of ones or
* zeros. It is an error to pass kNone for default<i> if in<i> is NULL or "". Note that when the
* function determines that the result is a zeros or ones vec then any expression represented by
* or in1 will not be emitted (side effects won't occur). The return value indicates whether a
* known zeros or ones vector resulted. The output can be suppressed when known vector is produced
* by passing true for omitIfConstVec.
*/
template <int N>
GrSLConstantVec GrGLSLAddf(SkString* outAppend,
const char* in0,
const char* in1,
GrSLConstantVec default0 = kZeros_GrSLConstantVec,
GrSLConstantVec default1 = kZeros_GrSLConstantVec,
bool omitIfConstVec = false);
inline GrGLSLExpr<N> operator-(const GrGLSLExpr<N>& in0, const GrGLSLExpr<N>&in1) {
return GrGLSLExpr<N>::Sub(in0, in1);
}
inline GrGLSLExpr<4> operator*(const GrGLSLExpr<4>& in0, const GrGLSLExpr<1>& in1) {
return GrGLSLExpr<4>::Mul(in0, in1);
}
inline GrGLSLExpr<4> operator+(const GrGLSLExpr<4>& in0, const GrGLSLExpr<1>& in1) {
return GrGLSLExpr<4>::Add(in0, in1);
}
inline GrGLSLExpr<4> operator-(const GrGLSLExpr<4>& in0, const GrGLSLExpr<1>& in1) {
return GrGLSLExpr<4>::Sub(in0, in1);
}
/** Casts an vec1 expression to vec4 expresison, eg. vec1(v) -> vec4(v,v,v,v). */
GrGLSLExpr<4> GrGLSLExprCast4(const GrGLSLExpr<1>& expr);
/** Extracts alpha component from an expression of vec<4>. */
GrGLSLExpr<1> GrGLSLExprExtractAlpha(const GrGLSLExpr<4>& expr);
/**
* Produces a string that is the result of subtracting two inputs. The inputs must be vecN or
* float. The result is always a vecN. The inputs may be expressions, not just identifier names.
* Either can be NULL or "" in which case the default params control whether a vector of ones or
* zeros. It is an error to pass kNone for default<i> if in<i> is NULL or "". Note that when the
* function determines that the result is a zeros or ones vec then any expression represented by
* or in1 will not be emitted (side effects won't occur). The return value indicates whether a
* known zeros or ones vector resulted. The output can be suppressed when known vector is produced
* by passing true for omitIfConstVec.
* Does an inplace mul, *=, of vec4VarName by mulFactor.
* A semicolon and newline are added after the assignment.
*/
template <int N>
GrSLConstantVec GrGLSLSubtractf(SkString* outAppend,
const char* in0,
const char* in1,
GrSLConstantVec default0 = kZeros_GrSLConstantVec,
GrSLConstantVec default1 = kZeros_GrSLConstantVec,
bool omitIfConstVec = false);
/**
* Does an inplace mul, *=, of vec4VarName by mulFactor. If mulFactorDefault is not kNone then
* mulFactor may be either "" or NULL. In this case either nothing will be appended (kOnes) or an
* assignment of vec(0,0,0,0) will be appended (kZeros). The assignment is prepended by tabCnt tabs.
* A semicolon and newline are added after the assignment. (TODO: Remove tabCnt when we auto-insert
* tabs to GrGLEffect-generated lines.) If a zeros vec is assigned then the return value is
* kZeros, otherwise kNone.
*/
GrSLConstantVec GrGLSLMulVarBy4f(SkString* outAppend,
int tabCnt,
const char* vec4VarName,
const char* mulFactor,
GrSLConstantVec mulFactorDefault = kOnes_GrSLConstantVec);
/**
* Given an expression that evaluates to a GLSL vec4, extract a component. If expr is NULL or ""
* the value of defaultExpr is used. It is an error to pass an empty expr and have set defaultExpr
* to kNone. The return value indicates whether the value is known to be 0 or 1. If omitIfConst is
* set then nothing is appended when the return is not kNone.
*/
GrSLConstantVec GrGLSLGetComponent4f(SkString* outAppend,
const char* expr,
GrColorComponentFlags component,
GrSLConstantVec defaultExpr = kNone_GrSLConstantVec,
bool omitIfConst = false);
void GrGLSLMulVarBy4f(SkString* outAppend, unsigned tabCnt,
const char* vec4VarName, const GrGLSLExpr<4>& mulFactor);
#include "GrGLSL_impl.h"

View File

@ -8,185 +8,133 @@
#ifndef GrGLSL_impl_DEFINED
#define GrGLSL_impl_DEFINED
#include "SkString.h"
template<>
inline const char* GrGLSLExpr<4>::ZerosStr() {
return "vec4(0)";
}
template<>
inline const char* GrGLSLExpr<4>::OnesStr() {
return "vec4(1)";
}
template<>
inline const char* GrGLSLExpr<4>::ExtractAlphaStr() {
return "%s.a";
}
template<>
inline const char* GrGLSLExpr<4>::CastStr() {
return "vec4(%s)";
}
template<>
inline const char* GrGLSLExpr<4>::CastIntStr() {
return "vec4(%d)";
}
template<>
inline const char* GrGLSLExpr<1>::ZerosStr() {
return "0";
}
template<>
inline const char* GrGLSLExpr<1>::OnesStr() {
return "1";
}
// GrGLSLExpr<1>::ExtractAlphaStr() and GrGLSLExpr<1>::CastStr() are
// unimplemented because using them is likely an error. This is now caught
// compile-time.
template<>
inline const char* GrGLSLExpr<1>::CastIntStr() {
return "%d";
}
template<>
template<>
inline GrGLSLExpr<4> GrGLSLExpr<4>::VectorCast(const GrGLSLExpr<4>& expr) {
return expr;
}
template<>
template<>
inline GrGLSLExpr<1> GrGLSLExpr<1>::VectorCast(const GrGLSLExpr<1>& expr) {
return expr;
}
namespace {
template<int N>
GrSLConstantVec return_const_vecf(GrSLConstantVec constVec, SkString* outAppend, bool omitAppend) {
SkASSERT(kNone_GrSLConstantVec != constVec);
if (!omitAppend) {
if (kZeros_GrSLConstantVec == constVec) {
outAppend->append(GrGLSLZerosVecf(N));
} else {
outAppend->append(GrGLSLOnesVecf(N));
}
template<int M>
inline GrGLSLExpr<N> GrGLSLExpr<N>::VectorCast(const GrGLSLExpr<M>& expr) {
if (expr.isZeros()) {
return GrGLSLExpr<N>(0);
}
return constVec;
}
if (expr.isOnes()) {
return GrGLSLExpr<N>(1);
}
return GrGLSLExpr<N>(GrGLSLExpr<N>::CastStr(), expr.c_str());
}
template <int N>
GrSLConstantVec GrGLSLModulatef(SkString* outAppend,
const char* in0,
const char* in1,
GrSLConstantVec default0,
GrSLConstantVec default1,
bool omitIfConstVec) {
SkASSERT(N > 0 && N <= 4);
SkASSERT(NULL != outAppend);
bool has0 = NULL != in0 && '\0' != *in0;
bool has1 = NULL != in1 && '\0' != *in1;
SkASSERT(has0 || kNone_GrSLConstantVec != default0);
SkASSERT(has1 || kNone_GrSLConstantVec != default1);
if (!has0 && !has1) {
SkASSERT(kZeros_GrSLConstantVec == default0 || kOnes_GrSLConstantVec == default0);
SkASSERT(kZeros_GrSLConstantVec == default1 || kOnes_GrSLConstantVec == default1);
if (kZeros_GrSLConstantVec == default0 || kZeros_GrSLConstantVec == default1) {
return return_const_vecf<N>(kZeros_GrSLConstantVec, outAppend, omitIfConstVec);
} else {
// both inputs are ones vectors
return return_const_vecf<N>(kOnes_GrSLConstantVec, outAppend, omitIfConstVec);
}
} else if (!has0) {
SkASSERT(kZeros_GrSLConstantVec == default0 || kOnes_GrSLConstantVec == default0);
if (kZeros_GrSLConstantVec == default0) {
return return_const_vecf<N>(kZeros_GrSLConstantVec, outAppend, omitIfConstVec);
} else {
outAppend->appendf("%s(%s)", GrGLSLFloatVectorTypeString(N), in1);
return kNone_GrSLConstantVec;
}
} else if (!has1) {
SkASSERT(kZeros_GrSLConstantVec == default1 || kOnes_GrSLConstantVec == default1);
if (kZeros_GrSLConstantVec == default1) {
return return_const_vecf<N>(kZeros_GrSLConstantVec, outAppend, omitIfConstVec);
} else {
outAppend->appendf("%s(%s)", GrGLSLFloatVectorTypeString(N), in0);
return kNone_GrSLConstantVec;
}
} else {
outAppend->appendf("%s((%s) * (%s))", GrGLSLFloatVectorTypeString(N), in0, in1);
return kNone_GrSLConstantVec;
template<int N>
template<int M>
inline GrGLSLExpr<N> GrGLSLExpr<N>::Mul(const GrGLSLExpr<N>& in0, const GrGLSLExpr<M>& in1) {
SK_COMPILE_ASSERT(N == M || M == 1, binary_op_dimensions_incompatible);
if (in0.isZeros() || in1.isZeros()) {
return GrGLSLExpr<N>(0);
}
if (in0.isOnes()) {
return VectorCast<M>(in1);
}
if (in1.isOnes()) {
return in0;
}
return GrGLSLExpr<N>("(%s * %s)", in0.c_str(), in1.c_str());
}
template <int N>
GrSLConstantVec GrGLSLAddf(SkString* outAppend,
const char* in0,
const char* in1,
GrSLConstantVec default0,
GrSLConstantVec default1,
bool omitIfConstVec) {
SkASSERT(N > 0 && N <= 4);
SkASSERT(NULL != outAppend);
bool has0 = NULL != in0 && '\0' != *in0;
bool has1 = NULL != in1 && '\0' != *in1;
if (!has0 && !has1) {
SkASSERT(kNone_GrSLConstantVec != default0);
SkASSERT(kNone_GrSLConstantVec != default1);
int sum = (kOnes_GrSLConstantVec == default0) + (kOnes_GrSLConstantVec == default1);
if (0 == sum) {
return return_const_vecf<N>(kZeros_GrSLConstantVec, outAppend, omitIfConstVec);
} else if (1 == sum) {
outAppend->append(GrGLSLOnesVecf(N));
return return_const_vecf<N>(kOnes_GrSLConstantVec, outAppend, omitIfConstVec);
} else {
SkASSERT(2 == sum);
outAppend->appendf("%s(2)", GrGLSLFloatVectorTypeString(N));
return kNone_GrSLConstantVec;
}
} else if (!has0) {
SkASSERT(kNone_GrSLConstantVec != default0);
if (kZeros_GrSLConstantVec == default0) {
outAppend->appendf("%s(%s)", GrGLSLFloatVectorTypeString(N), in1);
} else {
outAppend->appendf("%s(%s) + %s",
GrGLSLFloatVectorTypeString(N),
in1,
GrGLSLOnesVecf(N));
}
return kNone_GrSLConstantVec;
} else if (!has1) {
SkASSERT(kNone_GrSLConstantVec != default1);
if (kZeros_GrSLConstantVec == default1) {
outAppend->appendf("%s(%s)", GrGLSLFloatVectorTypeString(N), in0);
} else {
outAppend->appendf("%s(%s) + %s",
GrGLSLFloatVectorTypeString(N),
in0,
GrGLSLOnesVecf(N));
}
return kNone_GrSLConstantVec;
} else {
outAppend->appendf("(%s(%s) + %s(%s))",
GrGLSLFloatVectorTypeString(N),
in0,
GrGLSLFloatVectorTypeString(N),
in1);
return kNone_GrSLConstantVec;
template<int N>
template<int M>
inline GrGLSLExpr<N> GrGLSLExpr<N>::Add(const GrGLSLExpr<N>& in0, const GrGLSLExpr<M>& in1) {
SK_COMPILE_ASSERT(N == M || M == 1, binary_op_dimensions_incompatible);
if (in1.isZeros()) {
return in0;
}
if (in0.isZeros()) {
return VectorCast<M>(in1);
}
if (in0.isOnes() && in1.isOnes()) {
return GrGLSLExpr<N>(2);
}
return GrGLSLExpr<N>("(%s + %s)", in0.c_str(), in1.c_str());
}
template <int N>
GrSLConstantVec GrGLSLSubtractf(SkString* outAppend,
const char* in0,
const char* in1,
GrSLConstantVec default0,
GrSLConstantVec default1,
bool omitIfConstVec) {
SkASSERT(N > 0 && N <= 4);
SkASSERT(NULL != outAppend);
bool has0 = NULL != in0 && '\0' != *in0;
bool has1 = NULL != in1 && '\0' != *in1;
if (!has0 && !has1) {
SkASSERT(kNone_GrSLConstantVec != default0);
SkASSERT(kNone_GrSLConstantVec != default1);
int diff = (kOnes_GrSLConstantVec == default0) - (kOnes_GrSLConstantVec == default1);
if (-1 == diff) {
outAppend->appendf("%s(-1)", GrGLSLFloatVectorTypeString(N));
return kNone_GrSLConstantVec;
} else if (0 == diff) {
return return_const_vecf<N>(kZeros_GrSLConstantVec, outAppend, omitIfConstVec);
} else {
SkASSERT(1 == diff);
return return_const_vecf<N>(kOnes_GrSLConstantVec, outAppend, omitIfConstVec);
}
} else if (!has0) {
SkASSERT(kNone_GrSLConstantVec != default0);
if (kZeros_GrSLConstantVec == default0) {
outAppend->appendf("-%s(%s)", GrGLSLFloatVectorTypeString(N), in1);
} else {
outAppend->appendf("%s - %s(%s)",
GrGLSLOnesVecf(N),
GrGLSLFloatVectorTypeString(N),
in1);
}
return kNone_GrSLConstantVec;
} else if (!has1) {
SkASSERT(kNone_GrSLConstantVec != default1);
if (kZeros_GrSLConstantVec == default1) {
outAppend->appendf("%s(%s)", GrGLSLFloatVectorTypeString(N), in0);
} else {
outAppend->appendf("%s(%s) - %s",
GrGLSLFloatVectorTypeString(N),
in0,
GrGLSLOnesVecf(N));
}
return kNone_GrSLConstantVec;
} else {
outAppend->appendf("(%s(%s) - %s(%s))",
GrGLSLFloatVectorTypeString(N),
in0,
GrGLSLFloatVectorTypeString(N),
in1);
return kNone_GrSLConstantVec;
template<int N>
template<int M>
inline GrGLSLExpr<N> GrGLSLExpr<N>::Sub(const GrGLSLExpr<N>& in0, const GrGLSLExpr<M>& in1) {
SK_COMPILE_ASSERT(N == M || M == 1, binary_op_dimensions_incompatible);
if (in1.isZeros()) {
return in0;
}
if (in1.isOnes()) {
if (in0.isOnes()) {
return GrGLSLExpr<N>(0);
}
}
return GrGLSLExpr<N>("(%s - %s)", in0.c_str(), in1.c_str());
}
inline GrGLSLExpr<4> GrGLSLExprCast4(const GrGLSLExpr<1>& expr) {
return GrGLSLExpr<4>::VectorCast(expr);
}
inline GrGLSLExpr<1> GrGLSLExprExtractAlpha(const GrGLSLExpr<4>& expr) {
if (expr.isZeros()) {
return GrGLSLExpr<1>(0);
}
if (expr.isOnes()) {
return GrGLSLExpr<1>(1);
}
return GrGLSLExpr<1>(GrGLSLExpr<4>::ExtractAlphaStr(), expr.c_str());
}
#endif

View File

@ -99,8 +99,6 @@ GrGLShaderBuilder::GrGLShaderBuilder(GrGpuGL* gpu,
, fFSOutputs(kMaxFSOutputs)
, fUniforms(kVarsPerBlock)
, fSetupFragPosition(false)
, fKnownColorValue(GrGLProgramDesc::KnownColorInputValue(desc.getHeader().fColorInput))
, fKnownCoverageValue(GrGLProgramDesc::KnownColorInputValue(desc.getHeader().fCoverageInput))
, fHasCustomColorOutput(false)
, fHasSecondaryOutput(false)
, fTopLeftFragPosRead(kTopLeftFragPosRead_FragPosKey == desc.getHeader().fFragPosKey) {
@ -152,6 +150,10 @@ GrGLShaderBuilder::GrGLShaderBuilder(GrGpuGL* gpu,
fColorUniform = this->addUniform(GrGLShaderBuilder::kFragment_Visibility,
kVec4f_GrSLType, "Color", &name);
fInputColor = name;
} else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fColorInput) {
fInputColor = GrGLSLExpr<4>(1);
} else if (GrGLProgramDesc::kTransBlack_ColorInput == header.fColorInput) {
fInputColor = GrGLSLExpr<4>(0);
}
if (GrGLProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
@ -159,6 +161,10 @@ GrGLShaderBuilder::GrGLShaderBuilder(GrGpuGL* gpu,
fCoverageUniform = this->addUniform(GrGLShaderBuilder::kFragment_Visibility,
kVec4f_GrSLType, "Coverage", &name);
fInputCoverage = name;
} else if (GrGLProgramDesc::kSolidWhite_ColorInput == header.fCoverageInput) {
fInputCoverage = GrGLSLExpr<4>(1);
} else if (GrGLProgramDesc::kTransBlack_ColorInput == header.fCoverageInput) {
fInputCoverage = GrGLSLExpr<4>(0);
}
if (k110_GrGLSLGeneration != fGpu->glslGeneration()) {
@ -289,7 +295,7 @@ void GrGLShaderBuilder::fsAppendTextureLookupAndModulate(
GrSLType varyingType) {
SkString lookup;
this->appendTextureLookup(&lookup, sampler, coordName, varyingType);
GrGLSLModulatef<4>(&fFSCode, modulation, lookup.c_str());
fFSCode.append((GrGLSLExpr<4>(modulation) * GrGLSLExpr<4>(lookup)).c_str());
}
GrGLShaderBuilder::DstReadKey GrGLShaderBuilder::KeyForDstRead(const GrTexture* dstCopy,
@ -509,12 +515,11 @@ void GrGLShaderBuilder::createAndEmitEffects(GrGLProgramEffectsBuilder* programE
const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt,
SkString* fsInOutColor,
GrSLConstantVec* fsInOutColorKnownValue) {
GrGLSLExpr<4>* fsInOutColor) {
bool effectEmitted = false;
SkString inColor = *fsInOutColor;
SkString outColor;
GrGLSLExpr<4> inColor = *fsInOutColor;
GrGLSLExpr<4> outColor;
for (int e = 0; e < effectCnt; ++e) {
SkASSERT(NULL != effectStages[e] && NULL != effectStages[e]->getEffect());
@ -522,24 +527,29 @@ void GrGLShaderBuilder::createAndEmitEffects(GrGLProgramEffectsBuilder* programE
CodeStage::AutoStageRestore csar(&fCodeStage, &stage);
if (kZeros_GrSLConstantVec == *fsInOutColorKnownValue) {
if (inColor.isZeros()) {
SkString inColorName;
// Effects have no way to communicate zeros, they treat an empty string as ones.
this->nameVariable(&inColor, '\0', "input");
this->fsCodeAppendf("\tvec4 %s = %s;\n", inColor.c_str(), GrGLSLZerosVecf(4));
this->nameVariable(&inColorName, '\0', "input");
this->fsCodeAppendf("\tvec4 %s = %s;\n", inColorName.c_str(), inColor.c_str());
inColor = inColorName;
}
// create var to hold stage result
this->nameVariable(&outColor, '\0', "output");
this->fsCodeAppendf("\tvec4 %s;\n", outColor.c_str());
SkString outColorName;
this->nameVariable(&outColorName, '\0', "output");
this->fsCodeAppendf("\tvec4 %s;\n", outColorName.c_str());
outColor = outColorName;
programEffectsBuilder->emitEffect(stage,
effectKeys[e],
outColor.c_str(),
inColor.isEmpty() ? NULL : inColor.c_str(),
inColor.isOnes() ? NULL : inColor.c_str(),
fCodeStage.stageIndex());
inColor = outColor;
*fsInOutColorKnownValue = kNone_GrSLConstantVec;
effectEmitted = true;
}
@ -829,16 +839,14 @@ GrGLProgramEffects* GrGLFullShaderBuilder::createAndEmitEffects(
const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt,
SkString* inOutFSColor,
GrSLConstantVec* fsInOutColorKnownValue) {
GrGLSLExpr<4>* inOutFSColor) {
GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, effectCnt);
this->INHERITED::createAndEmitEffects(&programEffectsBuilder,
effectStages,
effectKeys,
effectCnt,
inOutFSColor,
fsInOutColorKnownValue);
inOutFSColor);
return programEffectsBuilder.finish();
}
@ -939,15 +947,13 @@ GrGLProgramEffects* GrGLFragmentOnlyShaderBuilder::createAndEmitEffects(
const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt,
SkString* inOutFSColor,
GrSLConstantVec* fsInOutColorKnownValue) {
GrGLSLExpr<4>* inOutFSColor) {
GrGLTexGenProgramEffectsBuilder texGenEffectsBuilder(this, effectCnt);
this->INHERITED::createAndEmitEffects(&texGenEffectsBuilder,
effectStages,
effectKeys,
effectCnt,
inOutFSColor,
fsInOutColorKnownValue);
inOutFSColor);
return texGenEffectsBuilder.finish();
}

View File

@ -167,40 +167,26 @@ public:
/**
* Interfaces used by GrGLProgram.
* TODO: These are used by GrGLProgram to insert a mode color filter. Remove these when the
* color filter is expressed as a GrEffect.
*/
const SkString& getInputColor() const {
SkASSERT(fInputColor.isEmpty() != (kNone_GrSLConstantVec == fKnownColorValue));
const GrGLSLExpr<4>& getInputColor() const {
return fInputColor;
}
GrSLConstantVec getKnownColorValue() const {
SkASSERT(fInputColor.isEmpty() != (kNone_GrSLConstantVec == fKnownColorValue));
return fKnownColorValue;
}
const SkString& getInputCoverage() const {
SkASSERT(fInputCoverage.isEmpty() != (kNone_GrSLConstantVec == fKnownCoverageValue));
const GrGLSLExpr<4>& getInputCoverage() const {
return fInputCoverage;
}
GrSLConstantVec getKnownCoverageValue() const {
SkASSERT(fInputCoverage.isEmpty() != (kNone_GrSLConstantVec == fKnownCoverageValue));
return fKnownCoverageValue;
}
/**
* Adds code for effects and returns a GrGLProgramEffects* object. The caller is responsible for
* deleting it when finished. effectStages contains the effects to add. effectKeys[i] is the key
* generated from effectStages[i]. inOutFSColor specifies the input color to the first stage and
* is updated to be the output color of the last stage. fsInOutColorKnownValue specifies whether
* the input color has a known constant value and is updated to refer to the status of the
* output color. The handles to texture samplers for effectStage[i] are added to
* is updated to be the output color of the last stage.
* The handles to texture samplers for effectStage[i] are added to
* effectSamplerHandles[i].
*/
virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt,
SkString* inOutFSColor,
GrSLConstantVec* fsInOutColorKnownValue) = 0;
GrGLSLExpr<4>* inOutFSColor) = 0;
const char* getColorOutputName() const;
const char* enableSecondaryOutput();
@ -225,8 +211,8 @@ public:
protected:
GrGpuGL* gpu() const { return fGpu; }
void setInputColor(const char* inputColor) { fInputColor = inputColor; }
void setInputCoverage(const char* inputCoverage) { fInputCoverage = inputCoverage; }
void setInputColor(const GrGLSLExpr<4>& inputColor) { fInputColor = inputColor; }
void setInputCoverage(const GrGLSLExpr<4>& inputCoverage) { fInputCoverage = inputCoverage; }
/** Add input/output variable declarations (i.e. 'varying') to the fragment shader. */
GrGLShaderVar& fsInputAppend() { return fFSInputs.push_back(); }
@ -241,8 +227,7 @@ protected:
const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt,
SkString* inOutFSColor,
GrSLConstantVec* fsInOutColorKnownValue);
GrGLSLExpr<4>* inOutFSColor);
virtual bool compileAndAttachShaders(GrGLuint programId) const;
virtual void bindProgramLocations(GrGLuint programId) const;
@ -344,10 +329,8 @@ private:
bool fSetupFragPosition;
GrGLUniformManager::UniformHandle fDstCopySamplerUniform;
SkString fInputColor;
GrSLConstantVec fKnownColorValue;
SkString fInputCoverage;
GrSLConstantVec fKnownCoverageValue;
GrGLSLExpr<4> fInputColor;
GrGLSLExpr<4> fInputCoverage;
bool fHasCustomColorOutput;
bool fHasSecondaryOutput;
@ -413,8 +396,7 @@ public:
const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt,
SkString* inOutFSColor,
GrSLConstantVec* fsInOutColorKnownValue) SK_OVERRIDE;
GrGLSLExpr<4>* inOutFSColor) SK_OVERRIDE;
GrGLUniformManager::UniformHandle getViewMatrixUniform() const {
return fViewMatrixUniform;
@ -463,8 +445,7 @@ public:
const GrEffectStage* effectStages[],
const EffectKey effectKeys[],
int effectCnt,
SkString* inOutFSColor,
GrSLConstantVec* fsInOutColorKnownValue) SK_OVERRIDE;
GrGLSLExpr<4>* inOutFSColor) SK_OVERRIDE;
private:
int fNumTexCoordSets;