diff options
Diffstat (limited to 'src/gpu/glsl')
-rw-r--r-- | src/gpu/glsl/GrGLSLColorSpaceXformHelper.h | 8 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLShaderBuilder.cpp | 77 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLShaderBuilder.h | 18 |
3 files changed, 92 insertions, 11 deletions
diff --git a/src/gpu/glsl/GrGLSLColorSpaceXformHelper.h b/src/gpu/glsl/GrGLSLColorSpaceXformHelper.h index 940be57126..cd516e8c89 100644 --- a/src/gpu/glsl/GrGLSLColorSpaceXformHelper.h +++ b/src/gpu/glsl/GrGLSLColorSpaceXformHelper.h @@ -8,12 +8,13 @@ #ifndef GrGLSLColorSpaceXformHelper_DEFINED #define GrGLSLColorSpaceXformHelper_DEFINED +#include "GrColorSpaceXform.h" #include "GrGLSLUniformHandler.h" -class GrColorSpaceXform; - /** * Stack helper class to assist with using GrColorSpaceXform within an FP's emitCode function. + * This injects the uniform declaration, and stores the information needed to generate correct + * gamut-transformation shader code. */ class GrGLSLColorSpaceXformHelper : public SkNoncopyable { public: @@ -25,15 +26,18 @@ public: *handle = uniformHandler->addUniform(kFragment_GrShaderFlag, kMat44f_GrSLType, kDefault_GrSLPrecision, "ColorXform", &fXformMatrix); + fAlphaType = colorSpaceXform->alphaType(); } else { fXformMatrix = nullptr; } } const char* getXformMatrix() const { return fXformMatrix; } + SkAlphaType alphaType() const { return fAlphaType; } private: const char* fXformMatrix; + SkAlphaType fAlphaType; }; #endif diff --git a/src/gpu/glsl/GrGLSLShaderBuilder.cpp b/src/gpu/glsl/GrGLSLShaderBuilder.cpp index 1e52a11013..8b004b265f 100644 --- a/src/gpu/glsl/GrGLSLShaderBuilder.cpp +++ b/src/gpu/glsl/GrGLSLShaderBuilder.cpp @@ -8,6 +8,7 @@ #include "GrSwizzle.h" #include "glsl/GrGLSLShaderBuilder.h" #include "glsl/GrGLSLCaps.h" +#include "glsl/GrGLSLColorSpaceXformHelper.h" #include "glsl/GrGLSLShaderVar.h" #include "glsl/GrGLSLSampler.h" #include "glsl/GrGLSLProgramBuilder.h" @@ -98,17 +99,79 @@ void GrGLSLShaderBuilder::appendTextureLookup(SkString* out, void GrGLSLShaderBuilder::appendTextureLookup(SamplerHandle samplerHandle, const char* coordName, - GrSLType varyingType) { - this->appendTextureLookup(&this->code(), samplerHandle, coordName, varyingType); + GrSLType varyingType, + GrGLSLColorSpaceXformHelper* colorXformHelper) { + if (colorXformHelper && colorXformHelper->getXformMatrix()) { + // With a color gamut transform, we need to wrap the lookup in another function call + SkString lookup; + this->appendTextureLookup(&lookup, samplerHandle, coordName, varyingType); + this->appendColorGamutXform(lookup.c_str(), colorXformHelper); + } else { + this->appendTextureLookup(&this->code(), samplerHandle, coordName, varyingType); + } } -void GrGLSLShaderBuilder::appendTextureLookupAndModulate(const char* modulation, - SamplerHandle samplerHandle, - const char* coordName, - GrSLType varyingType) { +void GrGLSLShaderBuilder::appendTextureLookupAndModulate( + const char* modulation, + SamplerHandle samplerHandle, + const char* coordName, + GrSLType varyingType, + GrGLSLColorSpaceXformHelper* colorXformHelper) { SkString lookup; this->appendTextureLookup(&lookup, samplerHandle, coordName, varyingType); - this->codeAppend((GrGLSLExpr4(modulation) * GrGLSLExpr4(lookup)).c_str()); + if (colorXformHelper && colorXformHelper->getXformMatrix()) { + SkString xform; + this->appendColorGamutXform(&xform, lookup.c_str(), colorXformHelper); + this->codeAppend((GrGLSLExpr4(modulation) * GrGLSLExpr4(xform)).c_str()); + } else { + this->codeAppend((GrGLSLExpr4(modulation) * GrGLSLExpr4(lookup)).c_str()); + } +} + +void GrGLSLShaderBuilder::appendColorGamutXform(SkString* out, + const char* srcColor, + GrGLSLColorSpaceXformHelper* colorXformHelper) { + // Our color is (r, g, b, a), but we want to multiply (r, g, b, 1) by our matrix, then + // re-insert the original alpha. The supplied srcColor is likely to be of the form + // "texture(...)", and we don't want to evaluate that twice. + // + // Worse: We can't do the transformation on premultiplied colors, so if the source is premul, + // we need to unpremul, transform, then multiply again. Anyways, we wrap all of the work in a + // function. + static const GrGLSLShaderVar gColorGamutXformArgs[] = { + GrGLSLShaderVar("color", kVec4f_GrSLType), + GrGLSLShaderVar("xform", kMat44f_GrSLType), + }; + SkString functionBody; + if (kPremul_SkAlphaType == colorXformHelper->alphaType()) { + // Unpremultiply + functionBody.append("\tfloat nonZeroAlpha = max(color.a, 0.00001);\n" + "\tcolor.rgb = color.rgb / nonZeroAlpha;\n"); + } + // Gamut xform, clamp to destination gamut + functionBody.append("\tcolor.rgb = clamp((vec4(color.rgb, 1.0) * xform).rgb, 0.0, 1.0);\n"); + if (kPremul_SkAlphaType == colorXformHelper->alphaType()) { + // Re-multiply by alpha + functionBody.append("\tcolor.rgb = color.rgb * nonZeroAlpha;\n"); + } + functionBody.append("\treturn color;"); + SkString colorGamutXformFuncName; + this->emitFunction(kVec4f_GrSLType, + "colorGamutXform", + SK_ARRAY_COUNT(gColorGamutXformArgs), + gColorGamutXformArgs, + functionBody.c_str(), + &colorGamutXformFuncName); + + out->appendf("%s(%s, %s)", colorGamutXformFuncName.c_str(), srcColor, + colorXformHelper->getXformMatrix()); +} + +void GrGLSLShaderBuilder::appendColorGamutXform(const char* srcColor, + GrGLSLColorSpaceXformHelper* colorXformHelper) { + SkString xform; + this->appendColorGamutXform(&xform, srcColor, colorXformHelper); + this->codeAppend(xform.c_str()); } void GrGLSLShaderBuilder::appendTexelFetch(SkString* out, diff --git a/src/gpu/glsl/GrGLSLShaderBuilder.h b/src/gpu/glsl/GrGLSLShaderBuilder.h index ea36a56a7a..a6ff96dd1b 100644 --- a/src/gpu/glsl/GrGLSLShaderBuilder.h +++ b/src/gpu/glsl/GrGLSLShaderBuilder.h @@ -15,6 +15,8 @@ #include <stdarg.h> +class GrGLSLColorSpaceXformHelper; + /** base class for all shaders builders */ @@ -37,7 +39,8 @@ public: /** Version of above that appends the result to the shader code instead.*/ void appendTextureLookup(SamplerHandle, const char* coordName, - GrSLType coordType = kVec2f_GrSLType); + GrSLType coordType = kVec2f_GrSLType, + GrGLSLColorSpaceXformHelper* colorXformHelper = nullptr); /** Does the work of appendTextureLookup and modulates the result by modulation. The result is @@ -47,7 +50,18 @@ public: void appendTextureLookupAndModulate(const char* modulation, SamplerHandle, const char* coordName, - GrSLType coordType = kVec2f_GrSLType); + GrSLType coordType = kVec2f_GrSLType, + GrGLSLColorSpaceXformHelper* colorXformHelper = nullptr); + + /** Adds a helper function to facilitate color gamut transformation, and produces code that + returns the srcColor transformed into a new gamut (via multiplication by the xform from + colorXformHelper). Premultiplied sources are also handled correctly (colorXformHelper + determines if the source is premultipled or not). */ + void appendColorGamutXform(SkString* out, const char* srcColor, + GrGLSLColorSpaceXformHelper* colorXformHelper); + + /** Version of above that appends the result to the shader code instead. */ + void appendColorGamutXform(const char* srcColor, GrGLSLColorSpaceXformHelper* colorXformHelper); /** Fetches an unfiltered texel from a sampler at integer coordinates. coordExpr must match the dimensionality of the sampler and must be within the sampler's range. coordExpr is emitted |