aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/core/SkString.cpp2
-rw-r--r--src/core/SkXfermode.cpp183
-rw-r--r--src/gpu/gl/GrGLShaderBuilder.cpp12
-rw-r--r--src/gpu/gl/GrGLShaderVar.h17
4 files changed, 196 insertions, 18 deletions
diff --git a/src/core/SkString.cpp b/src/core/SkString.cpp
index 3f9a99ff07..aee3de5dd8 100644
--- a/src/core/SkString.cpp
+++ b/src/core/SkString.cpp
@@ -15,7 +15,7 @@
#include <stdio.h>
// number of bytes (on the stack) to receive the printf result
-static const size_t kBufferSize = 512;
+static const size_t kBufferSize = 1024;
#ifdef SK_BUILD_FOR_WIN
#define VSNPRINTF(buffer, size, format, args) \
diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp
index da6d15e43e..5c752049f9 100644
--- a/src/core/SkXfermode.cpp
+++ b/src/core/SkXfermode.cpp
@@ -955,7 +955,7 @@ void SkProcXfermode::toString(SkString* str) const {
class XferEffect : public GrEffect {
public:
static bool IsSupportedMode(SkXfermode::Mode mode) {
- return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastSeparableMode;
+ return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode;
}
static GrEffectRef* Create(SkXfermode::Mode mode) {
@@ -1000,11 +1000,14 @@ public:
inputColor = "ones";
}
+ SkXfermode::Mode mode = drawEffect.castEffect<XferEffect>().mode();
+ builder->fsCodeAppendf("\t\t// SkXfermode::Mode: %s\n", SkXfermode::ModeName(mode));
+
// These all perform src-over on the alpha channel.
builder->fsCodeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n",
outputColor, inputColor, inputColor, dstColor);
- switch (drawEffect.castEffect<XferEffect>().mode()) {
+ switch (mode) {
case SkXfermode::kOverlay_Mode:
// Overlay is Hard-Light with the src and dst reversed
HardLight(builder, outputColor, dstColor, inputColor);
@@ -1063,12 +1066,58 @@ public:
outputColor, inputColor, dstColor, dstColor, inputColor,
inputColor, dstColor);
break;
- case SkXfermode::kHue_Mode:
- case SkXfermode::kSaturation_Mode:
- case SkXfermode::kColor_Mode:
- case SkXfermode::kLuminosity_Mode:
- GrCrash("Unimplemented XferEffect mode.");
+ case SkXfermode::kHue_Mode: {
+ // SetLum(SetSat(S * Da, Sat(D * Sa)), Sa*Da, D*Sa) + (1 - Sa) * D + (1 - Da) * S
+ SkString setSat, setLum;
+ AddSatFunction(builder, &setSat);
+ AddLumFunction(builder, &setLum);
+ builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n",
+ dstColor, inputColor);
+ builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rgb), dstSrcAlpha.a, dstSrcAlpha.rgb);\n",
+ outputColor, setLum.c_str(), setSat.c_str(), inputColor,
+ dstColor);
+ builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
+ outputColor, inputColor, dstColor, dstColor, inputColor);
+ break;
+ }
+ case SkXfermode::kSaturation_Mode: {
+ // SetLum(SetSat(D * Sa, Sat(S * Da)), Sa*Da, D*Sa)) + (1 - Sa) * D + (1 - Da) * S
+ SkString setSat, setLum;
+ AddSatFunction(builder, &setSat);
+ AddLumFunction(builder, &setLum);
+ builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n",
+ dstColor, inputColor);
+ builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a), dstSrcAlpha.a, dstSrcAlpha.rgb);\n",
+ outputColor, setLum.c_str(), setSat.c_str(), inputColor,
+ dstColor);
+ builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
+ outputColor, inputColor, dstColor, dstColor, inputColor);
break;
+ }
+ case SkXfermode::kColor_Mode: {
+ // SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S
+ SkString setLum;
+ AddLumFunction(builder, &setLum);
+ builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n",
+ inputColor, dstColor);
+ builder->fsCodeAppendf("\t\t%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a, %s.rgb * %s.a);\n",
+ outputColor, setLum.c_str(), dstColor, inputColor);
+ builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
+ outputColor, inputColor, dstColor, dstColor, inputColor);
+ break;
+ }
+ case SkXfermode::kLuminosity_Mode: {
+ // SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S
+ SkString setLum;
+ AddLumFunction(builder, &setLum);
+ builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n",
+ inputColor, dstColor);
+ builder->fsCodeAppendf("\t\t%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, srcDstAlpha.rgb);\n",
+ outputColor, setLum.c_str(), dstColor, inputColor);
+ builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
+ outputColor, inputColor, dstColor, dstColor, inputColor);
+ break;
+ }
default:
GrCrash("Unknown XferEffect mode.");
break;
@@ -1178,6 +1227,126 @@ public:
builder->fsCodeAppendf("\t\t\t}\n");
}
+ // Adds a function that takes two colors and an alpha as input. It produces a color with the
+ // hue and saturation of the first color, the luminosity of the second color, and the input
+ // alpha. It has this signature:
+ // vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor).
+ static void AddLumFunction(GrGLShaderBuilder* builder, SkString* setLumFunction) {
+ // Emit a helper that gets the luminance of a color.
+ SkString getFunction;
+ GrGLShaderVar getLumArgs[] = {
+ GrGLShaderVar("color", kVec3f_GrSLType),
+ };
+ SkString getLumBody("\treturn dot(vec3(0.3, 0.59, 0.11), color);\n");
+ builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
+ kFloat_GrSLType,
+ "luminance",
+ SK_ARRAY_COUNT(getLumArgs), getLumArgs,
+ getLumBody.c_str(),
+ &getFunction);
+
+ // Emit the set luminance function.
+ GrGLShaderVar setLumArgs[] = {
+ GrGLShaderVar("hueSat", kVec3f_GrSLType),
+ GrGLShaderVar("alpha", kFloat_GrSLType),
+ GrGLShaderVar("lumColor", kVec3f_GrSLType),
+ };
+ SkString setLumBody;
+ setLumBody.printf("\tfloat diff = %s(lumColor - hueSat);\n", getFunction.c_str());
+ setLumBody.append("\tvec3 outColor = hueSat + diff;\n");
+ setLumBody.appendf("\tfloat outLum = %s(outColor);\n", getFunction.c_str());
+ setLumBody.append("\tfloat minComp = min(min(outColor.r, outColor.g), outColor.b);\n"
+ "\tfloat maxComp = max(max(outColor.r, outColor.g), outColor.b);\n"
+ "\tif (minComp < 0.0) {\n"
+ "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * outLum) / (outLum - minComp);\n"
+ "\t}\n"
+ "\tif (maxComp > alpha) {\n"
+ "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) / (maxComp - outLum);\n"
+ "\t}\n"
+ "\treturn outColor;\n");
+ builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
+ kVec3f_GrSLType,
+ "set_luminance",
+ SK_ARRAY_COUNT(setLumArgs), setLumArgs,
+ setLumBody.c_str(),
+ setLumFunction);
+ }
+
+ // Adds a function that creates a color with the hue and luminosity of one input color and
+ // the saturation of another color. It will have this signature:
+ // float set_saturation(vec3 hueLumColor, vec3 satColor)
+ static void AddSatFunction(GrGLShaderBuilder* builder, SkString* setSatFunction) {
+ // Emit a helper that gets the saturation of a color
+ SkString getFunction;
+ GrGLShaderVar getSatArgs[] = { GrGLShaderVar("color", kVec3f_GrSLType) };
+ SkString getSatBody;
+ getSatBody.printf("\treturn max(max(color.r, color.g), color.b) - "
+ "min(min(color.r, color.g), color.b);\n");
+ builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
+ kFloat_GrSLType,
+ "saturation",
+ SK_ARRAY_COUNT(getSatArgs), getSatArgs,
+ getSatBody.c_str(),
+ &getFunction);
+
+ // Emit a helper that sets the saturation given sorted input channels
+ SkString helperFunction;
+ GrGLShaderVar helperArgs[] = {
+ GrGLShaderVar("minComp", kFloat_GrSLType),
+ GrGLShaderVar("midComp", kFloat_GrSLType),
+ GrGLShaderVar("maxComp", kFloat_GrSLType),
+ GrGLShaderVar("sat", kFloat_GrSLType),
+ };
+ helperArgs[0].setTypeModifier(GrGLShaderVar::kInOut_TypeModifier);
+ helperArgs[1].setTypeModifier(GrGLShaderVar::kInOut_TypeModifier);
+ helperArgs[2].setTypeModifier(GrGLShaderVar::kInOut_TypeModifier);
+ SkString helperBody;
+ helperBody.append("\tif (minComp < maxComp) {\n"
+ "\t\tmidComp = sat * (midComp - minComp) / (maxComp - minComp);\n"
+ "\t\tmaxComp = sat;\n"
+ "\t} else {\n"
+ "\t\tmidComp = midComp = 0.0;\n"
+ "\t}\n"
+ "\tminComp = 0.0;\n");
+ builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
+ kVoid_GrSLType,
+ "set_saturation_helper",
+ SK_ARRAY_COUNT(helperArgs), helperArgs,
+ helperBody.c_str(),
+ &helperFunction);
+
+ GrGLShaderVar setSatArgs[] = {
+ GrGLShaderVar("hueLumColor", kVec3f_GrSLType),
+ GrGLShaderVar("satColor", kVec3f_GrSLType),
+ };
+ const char* helpFunc = helperFunction.c_str();
+ SkString setSatBody;
+ setSatBody.appendf("\tfloat sat = %s(satColor);\n"
+ "\tif (hueLumColor.r <= hueLumColor.g) {\n"
+ "\t\tif (hueLumColor.g <= hueLumColor.b) {\n"
+ "\t\t\t%s(hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);\n"
+ "\t\t} else {\n"
+ "\t\t\t%s(hueLumColor.r, hueLumColor.b, hueLumColor.g, sat);\n"
+ "\t\t}\n"
+ "\t} else if (hueLumColor.r <= hueLumColor.b) {\n"
+ "\t\t%s(hueLumColor.g, hueLumColor.r, hueLumColor.b, sat);\n"
+ "\t} else if (hueLumColor.g <= hueLumColor.b) {\n"
+ "\t\t%s(hueLumColor.g, hueLumColor.b, hueLumColor.r, sat);\n"
+ "\t} else {\n"
+ "\t\t%s(hueLumColor.b, hueLumColor.g, hueLumColor.r, sat);\n"
+ "\t}\n"
+ "\treturn hueLumColor;",
+ getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFunc,\
+ helpFunc);
+ builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
+ kVec3f_GrSLType,
+ "set_saturation",
+ SK_ARRAY_COUNT(setSatArgs), setSatArgs,
+ setSatBody.c_str(),
+ setSatFunction);
+
+ }
+
typedef GrGLEffect INHERITED;
};
diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp
index 60e9188252..752464cf4a 100644
--- a/src/gpu/gl/GrGLShaderBuilder.cpp
+++ b/src/gpu/gl/GrGLShaderBuilder.cpp
@@ -386,7 +386,7 @@ void GrGLShaderBuilder::addVarying(GrSLType type,
const char** fsInName) {
fVSOutputs.push_back();
fVSOutputs.back().setType(type);
- fVSOutputs.back().setTypeModifier(GrGLShaderVar::kOut_TypeModifier);
+ fVSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
if (kNonStageIdx == fCurrentStageIdx) {
fVSOutputs.back().accessName()->printf("v%s", name);
} else {
@@ -402,12 +402,12 @@ void GrGLShaderBuilder::addVarying(GrSLType type,
// and output as non-array.
fGSInputs.push_back();
fGSInputs.back().setType(type);
- fGSInputs.back().setTypeModifier(GrGLShaderVar::kIn_TypeModifier);
+ fGSInputs.back().setTypeModifier(GrGLShaderVar::kVaryingIn_TypeModifier);
fGSInputs.back().setUnsizedArray();
*fGSInputs.back().accessName() = fVSOutputs.back().getName();
fGSOutputs.push_back();
fGSOutputs.back().setType(type);
- fGSOutputs.back().setTypeModifier(GrGLShaderVar::kOut_TypeModifier);
+ fGSOutputs.back().setTypeModifier(GrGLShaderVar::kVaryingOut_TypeModifier);
if (kNonStageIdx == fCurrentStageIdx) {
fGSOutputs.back().accessName()->printf("g%s", name);
} else {
@@ -419,7 +419,7 @@ void GrGLShaderBuilder::addVarying(GrSLType type,
}
fFSInputs.push_back();
fFSInputs.back().setType(type);
- fFSInputs.back().setTypeModifier(GrGLShaderVar::kIn_TypeModifier);
+ fFSInputs.back().setTypeModifier(GrGLShaderVar::kVaryingIn_TypeModifier);
fFSInputs.back().setName(*fsName);
if (fsInName) {
*fsInName = fsName->c_str();
@@ -487,11 +487,11 @@ void GrGLShaderBuilder::emitFunction(ShaderType shader,
GrAssert(kFragment_ShaderType == shader);
fFSFunctions.append(GrGLSLTypeString(returnType));
if (kNonStageIdx != fCurrentStageIdx) {
- outName->printf(" %s_%d", name, fCurrentStageIdx);
+ outName->printf("%s_%d", name, fCurrentStageIdx);
} else {
*outName = name;
}
- fFSFunctions.append(*outName);
+ fFSFunctions.appendf(" %s", outName->c_str());
fFSFunctions.append("(");
for (int i = 0; i < argCnt; ++i) {
args[i].appendDecl(fCtxInfo, &fFSFunctions);
diff --git a/src/gpu/gl/GrGLShaderVar.h b/src/gpu/gl/GrGLShaderVar.h
index 7f2bf458a8..c79589772a 100644
--- a/src/gpu/gl/GrGLShaderVar.h
+++ b/src/gpu/gl/GrGLShaderVar.h
@@ -29,8 +29,11 @@ public:
kNone_TypeModifier,
kOut_TypeModifier,
kIn_TypeModifier,
+ kInOut_TypeModifier,
kUniform_TypeModifier,
- kAttribute_TypeModifier
+ kAttribute_TypeModifier,
+ kVaryingIn_TypeModifier,
+ kVaryingOut_TypeModifier
};
enum Precision {
@@ -303,14 +306,20 @@ private:
switch (t) {
case kNone_TypeModifier:
return "";
- case kOut_TypeModifier:
- return k110_GrGLSLGeneration == gen ? "varying" : "out";
case kIn_TypeModifier:
- return k110_GrGLSLGeneration == gen ? "varying" : "in";
+ return "in";
+ case kInOut_TypeModifier:
+ return "inout";
+ case kOut_TypeModifier:
+ return "out";
case kUniform_TypeModifier:
return "uniform";
case kAttribute_TypeModifier:
return k110_GrGLSLGeneration == gen ? "attribute" : "in";
+ case kVaryingIn_TypeModifier:
+ return k110_GrGLSLGeneration == gen ? "varying" : "in";
+ case kVaryingOut_TypeModifier:
+ return k110_GrGLSLGeneration == gen ? "varying" : "out";
default:
GrCrash("Unknown shader variable type modifier.");
return ""; // suppress warning