aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/glsl
diff options
context:
space:
mode:
authorGravatar Brian Osman <brianosman@google.com>2018-06-18 10:20:32 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-06-18 14:55:48 +0000
commit3567c14a41cd55860fcc836af32d8748c1e3c856 (patch)
tree8a9428dd0c25e3dcee1ccf2e6008c1f665dcaa26 /src/gpu/glsl
parent1bb47df4fc8edf62b0463d088214ed1ffb909ca9 (diff)
Implement nonlinear (as-encoded) blending in GrColorSpaceXform
Make GrColorSpaceXform a wrapper over SkColorSpaceXformSteps, and removed the xform cache. The shader code does up to five steps to correctly transform (unpremul, linearize, gamut, encode, premul). Remove all clamping, so we can support sRGB encoded F16. Most of https://skia-review.googlesource.com/c/skia/+/132090, except that GrNonlinearColorSpaceXformEffect is still used for SkColorSpaceXformCanvas and a few other places. As a result, this doesn't trigger any layout test failures. Change-Id: I789a5e327a419b5f7634c00d1b355912046c07b7 Reviewed-on: https://skia-review.googlesource.com/135326 Reviewed-by: Brian Salomon <bsalomon@google.com> Reviewed-by: Mike Klein <mtklein@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
Diffstat (limited to 'src/gpu/glsl')
-rw-r--r--src/gpu/glsl/GrGLSLColorSpaceXformHelper.h56
-rw-r--r--src/gpu/glsl/GrGLSLShaderBuilder.cpp66
2 files changed, 67 insertions, 55 deletions
diff --git a/src/gpu/glsl/GrGLSLColorSpaceXformHelper.h b/src/gpu/glsl/GrGLSLColorSpaceXformHelper.h
index 0cc9da1012..397a656c88 100644
--- a/src/gpu/glsl/GrGLSLColorSpaceXformHelper.h
+++ b/src/gpu/glsl/GrGLSLColorSpaceXformHelper.h
@@ -10,6 +10,7 @@
#include "GrColorSpaceXform.h"
#include "GrGLSLUniformHandler.h"
+#include "SkColorSpaceXformSteps.h"
/**
* Helper class to assist with using GrColorSpaceXform within an FP. This manages all of the
@@ -18,56 +19,61 @@
*/
class GrGLSLColorSpaceXformHelper : public SkNoncopyable {
public:
- GrGLSLColorSpaceXformHelper() : fFlags(0) {}
+ GrGLSLColorSpaceXformHelper() {
+ memset(&fFlags, 0, sizeof(fFlags));
+ }
void emitCode(GrGLSLUniformHandler* uniformHandler, const GrColorSpaceXform* colorSpaceXform,
uint32_t visibility = kFragment_GrShaderFlag) {
SkASSERT(uniformHandler);
if (colorSpaceXform) {
- fFlags = colorSpaceXform->fFlags;
+ fFlags = colorSpaceXform->fSteps.flags;
+ if (this->applySrcTF()) {
+ fSrcTFVar = uniformHandler->addUniformArray(visibility, kHalf_GrSLType,
+ "SrcTF", kNumTransferFnCoeffs);
+ }
if (this->applyGamutXform()) {
- fGamutXformVar = uniformHandler->addUniform(visibility,
- kHalf4x4_GrSLType,
+ fGamutXformVar = uniformHandler->addUniform(visibility, kHalf3x3_GrSLType,
"ColorXform");
}
- if (this->applyTransferFn()) {
- fTransferFnVar = uniformHandler->addUniformArray(visibility,
- kHalf_GrSLType,
- "TransferFn",
- kNumTransferFnCoeffs);
+ if (this->applyDstTF()) {
+ fDstTFVar = uniformHandler->addUniformArray(visibility, kHalf_GrSLType,
+ "DstTF", kNumTransferFnCoeffs);
}
}
}
void setData(const GrGLSLProgramDataManager& pdman, const GrColorSpaceXform* colorSpaceXform) {
+ if (this->applySrcTF()) {
+ pdman.set1fv(fSrcTFVar, kNumTransferFnCoeffs, &colorSpaceXform->fSteps.srcTF.fG);
+ }
if (this->applyGamutXform()) {
- pdman.setSkMatrix44(fGamutXformVar, colorSpaceXform->gamutXform());
+ pdman.setMatrix3f(fGamutXformVar, colorSpaceXform->fSteps.src_to_dst_matrix);
}
- if (this->applyTransferFn()) {
- pdman.set1fv(fTransferFnVar, kNumTransferFnCoeffs, colorSpaceXform->transferFnCoeffs());
+ if (this->applyDstTF()) {
+ pdman.set1fv(fDstTFVar, kNumTransferFnCoeffs, &colorSpaceXform->fSteps.dstTFInv.fG);
}
}
- bool isNoop() const { return (0 == fFlags); }
- bool applyInverseSRGB() const {
- return SkToBool(fFlags & GrColorSpaceXform::kApplyInverseSRGB_Flag);
- }
- bool applyTransferFn() const {
- return SkToBool(fFlags & GrColorSpaceXform::kApplyTransferFn_Flag);
- }
- bool applyGamutXform() const {
- return SkToBool(fFlags & GrColorSpaceXform::kApplyGamutXform_Flag);
- }
+ bool isNoop() const { return (0 == fFlags.mask()); }
+
+ bool applyUnpremul() const { return fFlags.unpremul; }
+ bool applySrcTF() const { return fFlags.linearize; }
+ bool applyGamutXform() const { return fFlags.gamut_transform; }
+ bool applyDstTF() const { return fFlags.encode; }
+ bool applyPremul() const { return fFlags.premul; }
+ GrGLSLProgramDataManager::UniformHandle srcTFUniform() const { return fSrcTFVar; }
GrGLSLProgramDataManager::UniformHandle gamutXformUniform() const { return fGamutXformVar; }
- GrGLSLProgramDataManager::UniformHandle transferFnUniform() const { return fTransferFnVar; }
+ GrGLSLProgramDataManager::UniformHandle dstTFUniform() const { return fDstTFVar; }
private:
static const int kNumTransferFnCoeffs = 7;
+ GrGLSLProgramDataManager::UniformHandle fSrcTFVar;
GrGLSLProgramDataManager::UniformHandle fGamutXformVar;
- GrGLSLProgramDataManager::UniformHandle fTransferFnVar;
- uint32_t fFlags;
+ GrGLSLProgramDataManager::UniformHandle fDstTFVar;
+ SkColorSpaceXformSteps::Flags fFlags;
};
#endif
diff --git a/src/gpu/glsl/GrGLSLShaderBuilder.cpp b/src/gpu/glsl/GrGLSLShaderBuilder.cpp
index db0be21f01..e2b1c559bc 100644
--- a/src/gpu/glsl/GrGLSLShaderBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLShaderBuilder.cpp
@@ -109,24 +109,13 @@ void GrGLSLShaderBuilder::appendColorGamutXform(SkString* out,
GrGLSLUniformHandler* uniformHandler = fProgramBuilder->uniformHandler();
- // We define up to three helper functions, to keep things clearer. One does inverse sRGB,
- // one does an arbitrary transfer function, and the last does gamut xform. Any combination of
- // these may be present, although some configurations are much more likely.
+ // We define up to three helper functions, to keep things clearer. One for the source transfer
+ // function, one for the (inverse) destination transfer function, and one for the gamut xform.
+ // Any combination of these may be present, although some configurations are much more likely.
- SkString inverseSrgbFuncName;
- if (colorXformHelper->applyInverseSRGB()) {
- static const GrShaderVar gInverseSRGBArgs[] = { GrShaderVar("x", kHalf_GrSLType) };
- SkString body;
- body.append("return (x <= 0.0031308) ? (x * 12.92) : (1.055 * pow(x, 0.4166667) - 0.055);");
- this->emitFunction(kHalf_GrSLType, "inverse_srgb", SK_ARRAY_COUNT(gInverseSRGBArgs),
- gInverseSRGBArgs, body.c_str(), &inverseSrgbFuncName);
-
- }
-
- SkString transferFnFuncName;
- if (colorXformHelper->applyTransferFn()) {
- static const GrShaderVar gTransferFnArgs[] = { GrShaderVar("x", kHalf_GrSLType) };
- const char* coeffs = uniformHandler->getUniformCStr(colorXformHelper->transferFnUniform());
+ auto emitTFFunc = [=](const char* name, GrGLSLProgramDataManager::UniformHandle uniform) {
+ static const GrShaderVar gTFArgs[] = { GrShaderVar("x", kHalf_GrSLType) };
+ const char* coeffs = uniformHandler->getUniformCStr(uniform);
SkString body;
// Temporaries to make evaluation line readable
body.appendf("half G = %s[0];", coeffs);
@@ -139,18 +128,28 @@ void GrGLSLShaderBuilder::appendColorGamutXform(SkString* out,
body.append("half s = sign(x);");
body.append("x = abs(x);");
body.appendf("return s * ((x < D) ? (C * x) + F : pow(A * x + B, G) + E);");
- this->emitFunction(kHalf_GrSLType, "transfer_fn", SK_ARRAY_COUNT(gTransferFnArgs),
- gTransferFnArgs, body.c_str(), &transferFnFuncName);
+ SkString funcName;
+ this->emitFunction(kHalf_GrSLType, name, SK_ARRAY_COUNT(gTFArgs), gTFArgs, body.c_str(),
+ &funcName);
+ return funcName;
+ };
+
+ SkString srcTFFuncName;
+ if (colorXformHelper->applySrcTF()) {
+ srcTFFuncName = emitTFFunc("src_tf", colorXformHelper->srcTFUniform());
+ }
+
+ SkString dstTFFuncName;
+ if (colorXformHelper->applyDstTF()) {
+ dstTFFuncName = emitTFFunc("dst_tf", colorXformHelper->dstTFUniform());
}
SkString gamutXformFuncName;
if (colorXformHelper->applyGamutXform()) {
- // 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.
static const GrShaderVar gGamutXformArgs[] = { GrShaderVar("color", kHalf4_GrSLType) };
const char* xform = uniformHandler->getUniformCStr(colorXformHelper->gamutXformUniform());
SkString body;
- body.appendf("color.rgb = clamp((%s * half4(color.rgb, 1.0)).rgb, 0.0, color.a);", xform);
+ body.appendf("color.rgb = (%s * color.rgb);", xform);
body.append("return color;");
this->emitFunction(kHalf4_GrSLType, "gamut_xform", SK_ARRAY_COUNT(gGamutXformArgs),
gGamutXformArgs, body.c_str(), &gamutXformFuncName);
@@ -160,19 +159,26 @@ void GrGLSLShaderBuilder::appendColorGamutXform(SkString* out,
{
static const GrShaderVar gColorXformArgs[] = { GrShaderVar("color", kHalf4_GrSLType) };
SkString body;
- if (colorXformHelper->applyInverseSRGB()) {
- body.appendf("color.r = %s(color.r);", inverseSrgbFuncName.c_str());
- body.appendf("color.g = %s(color.g);", inverseSrgbFuncName.c_str());
- body.appendf("color.b = %s(color.b);", inverseSrgbFuncName.c_str());
+ if (colorXformHelper->applyUnpremul()) {
+ body.append("half nonZeroAlpha = max(color.a, 0.00001);");
+ body.append("color = half4(color.rgb / nonZeroAlpha, nonZeroAlpha);");
}
- if (colorXformHelper->applyTransferFn()) {
- body.appendf("color.r = %s(color.r);", transferFnFuncName.c_str());
- body.appendf("color.g = %s(color.g);", transferFnFuncName.c_str());
- body.appendf("color.b = %s(color.b);", transferFnFuncName.c_str());
+ if (colorXformHelper->applySrcTF()) {
+ body.appendf("color.r = %s(color.r);", srcTFFuncName.c_str());
+ body.appendf("color.g = %s(color.g);", srcTFFuncName.c_str());
+ body.appendf("color.b = %s(color.b);", srcTFFuncName.c_str());
}
if (colorXformHelper->applyGamutXform()) {
body.appendf("color = %s(color);", gamutXformFuncName.c_str());
}
+ if (colorXformHelper->applyDstTF()) {
+ body.appendf("color.r = %s(color.r);", dstTFFuncName.c_str());
+ body.appendf("color.g = %s(color.g);", dstTFFuncName.c_str());
+ body.appendf("color.b = %s(color.b);", dstTFFuncName.c_str());
+ }
+ if (colorXformHelper->applyPremul()) {
+ body.append("color.rgb *= color.a;");
+ }
body.append("return color;");
SkString colorXformFuncName;
this->emitFunction(kHalf4_GrSLType, "color_xform", SK_ARRAY_COUNT(gColorXformArgs),