Avoid multiplication by alpha in fragment shader when known to be 1.
Implemented for image shaders, image draws, and gradient shaders.
Reimplement GrFragmentProcessor::OverrideInput as GrOverrideInputFragmentProcessor.fp.
It allows specification of whether the replacement input color should be
a literal in the shader code or a uniform. For above use case use with literal white.
Make key in variables in fp files work for 4f colors.
Fix issue in CPP code gen from .fp where when + key vars that pushed multiple values
into the shader key only skipped the first key value when the when condition is not
true.
Bug: skia:7722
Change-Id: Id7c865132d620e8cdea8b00f2a627103eef171ac
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/201985
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
diff --git a/gn/gpu.gni b/gn/gpu.gni
index 3f8a8f9..1e4f50c 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -372,6 +372,8 @@
"$_src/gpu/effects/generated/GrMagnifierEffect.h",
"$_src/gpu/effects/generated/GrMixerEffect.cpp",
"$_src/gpu/effects/generated/GrMixerEffect.h",
+ "$_src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp",
+ "$_src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h",
"$_src/gpu/effects/generated/GrPremulInputFragmentProcessor.cpp",
"$_src/gpu/effects/generated/GrPremulInputFragmentProcessor.h",
"$_src/gpu/effects/generated/GrRectBlurEffect.cpp",
diff --git a/gn/sksl.gni b/gn/sksl.gni
index 50ec8e7..891b84c 100644
--- a/gn/sksl.gni
+++ b/gn/sksl.gni
@@ -45,6 +45,7 @@
"$_src/gpu/effects/GrLumaColorFilterEffect.fp",
"$_src/gpu/effects/GrMagnifierEffect.fp",
"$_src/gpu/effects/GrMixerEffect.fp",
+ "$_src/gpu/effects/GrOverrideInputFragmentProcessor.fp",
"$_src/gpu/effects/GrPremulInputFragmentProcessor.fp",
"$_src/gpu/effects/GrRectBlurEffect.fp",
"$_src/gpu/effects/GrRRectBlurEffect.fp",
diff --git a/src/gpu/GrFPArgs.h b/src/gpu/GrFPArgs.h
index 94b26e6..43f2868 100644
--- a/src/gpu/GrFPArgs.h
+++ b/src/gpu/GrFPArgs.h
@@ -42,6 +42,9 @@
const SkMatrix* fPreLocalMatrix = nullptr;
const SkMatrix* fPostLocalMatrix = nullptr;
+ // Make this SkAlphaType?
+ bool fInputColorIsOpaque = false;
+
SkFilterQuality fFilterQuality;
const GrColorSpaceInfo* fDstColorSpaceInfo;
};
diff --git a/src/gpu/GrFragmentProcessor.cpp b/src/gpu/GrFragmentProcessor.cpp
index 3d6ec03..4a4c4cb 100644
--- a/src/gpu/GrFragmentProcessor.cpp
+++ b/src/gpu/GrFragmentProcessor.cpp
@@ -9,9 +9,10 @@
#include "GrCoordTransform.h"
#include "GrPipeline.h"
#include "GrProcessorAnalysis.h"
-#include "effects/generated/GrConstColorProcessor.h"
-#include "effects/generated/GrPremulInputFragmentProcessor.h"
#include "effects/GrXfermodeFragmentProcessor.h"
+#include "effects/generated/GrConstColorProcessor.h"
+#include "effects/generated/GrOverrideInputFragmentProcessor.h"
+#include "effects/generated/GrPremulInputFragmentProcessor.h"
#include "glsl/GrGLSLFragmentProcessor.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLProgramDataManager.h"
@@ -282,93 +283,11 @@
//////////////////////////////////////////////////////////////////////////////
std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::OverrideInput(
- std::unique_ptr<GrFragmentProcessor> fp, const SkPMColor4f& color) {
- class ReplaceInputFragmentProcessor : public GrFragmentProcessor {
- public:
- static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> child,
- const SkPMColor4f& color) {
- return std::unique_ptr<GrFragmentProcessor>(
- new ReplaceInputFragmentProcessor(std::move(child), color));
- }
-
- const char* name() const override { return "Replace Color"; }
-
- std::unique_ptr<GrFragmentProcessor> clone() const override {
- return Make(this->childProcessor(0).clone(), fColor);
- }
-
- private:
- GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
- class GLFP : public GrGLSLFragmentProcessor {
- public:
- GLFP() : fHaveSetColor(false) {}
- void emitCode(EmitArgs& args) override {
- const char* colorName;
- fColorUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
- kHalf4_GrSLType,
- "Color", &colorName);
- this->emitChild(0, colorName, args);
- }
-
- private:
- void onSetData(const GrGLSLProgramDataManager& pdman,
- const GrFragmentProcessor& fp) override {
- SkPMColor4f color = fp.cast<ReplaceInputFragmentProcessor>().fColor;
- if (!fHaveSetColor || color != fPreviousColor) {
- pdman.set4fv(fColorUni, 1, color.vec());
- fPreviousColor = color;
- fHaveSetColor = true;
- }
- }
-
- GrGLSLProgramDataManager::UniformHandle fColorUni;
- bool fHaveSetColor;
- SkPMColor4f fPreviousColor;
- };
-
- return new GLFP;
- }
-
- ReplaceInputFragmentProcessor(std::unique_ptr<GrFragmentProcessor> child,
- const SkPMColor4f& color)
- : INHERITED(kReplaceInputFragmentProcessor_ClassID, OptFlags(child.get(), color))
- , fColor(color) {
- this->registerChildProcessor(std::move(child));
- }
-
- static OptimizationFlags OptFlags(const GrFragmentProcessor* child,
- const SkPMColor4f& color) {
- OptimizationFlags childFlags = child->optimizationFlags();
- OptimizationFlags flags = kNone_OptimizationFlags;
- if (childFlags & kConstantOutputForConstantInput_OptimizationFlag) {
- flags |= kConstantOutputForConstantInput_OptimizationFlag;
- }
- if ((childFlags & kPreservesOpaqueInput_OptimizationFlag) && color.isOpaque()) {
- flags |= kPreservesOpaqueInput_OptimizationFlag;
- }
- return flags;
- }
-
- void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override
- {}
-
- bool onIsEqual(const GrFragmentProcessor& that) const override {
- return fColor == that.cast<ReplaceInputFragmentProcessor>().fColor;
- }
-
- SkPMColor4f constantOutputForConstantInput(const SkPMColor4f&) const override {
- return ConstantOutputForConstantInput(this->childProcessor(0), fColor);
- }
-
- SkPMColor4f fColor;
-
- typedef GrFragmentProcessor INHERITED;
- };
-
+ std::unique_ptr<GrFragmentProcessor> fp, const SkPMColor4f& color, bool useUniform) {
if (!fp) {
return nullptr;
}
- return ReplaceInputFragmentProcessor::Make(std::move(fp), color);
+ return GrOverrideInputFragmentProcessor::Make(std::move(fp), color, useUniform);
}
std::unique_ptr<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(
diff --git a/src/gpu/GrFragmentProcessor.h b/src/gpu/GrFragmentProcessor.h
index 5136243..fb8126e 100644
--- a/src/gpu/GrFragmentProcessor.h
+++ b/src/gpu/GrFragmentProcessor.h
@@ -63,7 +63,8 @@
* child.
*/
static std::unique_ptr<GrFragmentProcessor> OverrideInput(std::unique_ptr<GrFragmentProcessor>,
- const SkPMColor4f&);
+ const SkPMColor4f&,
+ bool useUniform = true);
/**
* Returns a fragment processor that premuls the input before calling the passed in fragment
@@ -293,6 +294,11 @@
return static_cast<OptimizationFlags>(kAll_OptimizationFlags & fFlags);
}
+ /** Useful when you can't call fp->optimizationFlags() on a base class object from a subclass.*/
+ static OptimizationFlags ProcessorOptimizationFlags(const GrFragmentProcessor* fp) {
+ return fp->optimizationFlags();
+ }
+
/**
* This allows one subclass to access another subclass's implementation of
* constantOutputForConstantInput. It must only be called when
diff --git a/src/gpu/GrProcessor.h b/src/gpu/GrProcessor.h
index 0e6d7bc..3c3a9ad 100644
--- a/src/gpu/GrProcessor.h
+++ b/src/gpu/GrProcessor.h
@@ -124,6 +124,7 @@
kGrMorphologyEffect_ClassID,
kGrMixerEffect_ClassID,
kGrOverdrawFragmentProcessor_ClassID,
+ kGrOverrideInputFragmentProcessor_ClassID,
kGrPathProcessor_ClassID,
kGrPerlinNoise2Effect_ClassID,
kGrPipelineDynamicStateTestProcessor_ClassID,
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 388450f..e04c567 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1061,7 +1061,11 @@
if (GrPixelConfigIsAlphaOnly(config)) {
fp = GrFragmentProcessor::MakeInputPremulAndMulByOutput(std::move(fp));
} else {
- fp = GrFragmentProcessor::MulChildByInputAlpha(std::move(fp));
+ if (paint.getColor4f().isOpaque()) {
+ fp = GrFragmentProcessor::OverrideInput(std::move(fp), SK_PMColor4fWHITE, false);
+ } else {
+ fp = GrFragmentProcessor::MulChildByInputAlpha(std::move(fp));
+ }
}
GrPaint grPaint;
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 5fc363b..ac195bb 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -355,12 +355,13 @@
// Convert SkPaint color to 4f format in the destination color space
SkColor4f origColor = SkColor4fPrepForDst(skPaint.getColor4f(), colorSpaceInfo);
- const GrFPArgs fpArgs(context, &viewM, skPaint.getFilterQuality(), &colorSpaceInfo);
+ GrFPArgs fpArgs(context, &viewM, skPaint.getFilterQuality(), &colorSpaceInfo);
// Setup the initial color considering the shader, the SkPaint color, and the presence or not
// of per-vertex colors.
std::unique_ptr<GrFragmentProcessor> shaderFP;
if (!primColorMode || blend_requires_shader(*primColorMode)) {
+ fpArgs.fInputColorIsOpaque = origColor.isOpaque();
if (shaderProcessor) {
shaderFP = std::move(*shaderProcessor);
} else if (const auto* shader = as_SB(skPaint.getShader())) {
@@ -457,6 +458,8 @@
SkMaskFilterBase* maskFilter = as_MFB(skPaint.getMaskFilter());
if (maskFilter) {
+ // We may have set this before passing to the SkShader.
+ fpArgs.fInputColorIsOpaque = false;
if (auto mfFP = maskFilter->asFragmentProcessor(fpArgs)) {
grPaint->addCoverageFragmentProcessor(std::move(mfFP));
}
@@ -551,7 +554,11 @@
shaderFP = GrFragmentProcessor::MakeInputPremulAndMulByOutput(std::move(fp));
}
} else {
- shaderFP = GrFragmentProcessor::MulChildByInputAlpha(std::move(fp));
+ if (paint.getColor4f().isOpaque()) {
+ shaderFP = GrFragmentProcessor::OverrideInput(std::move(fp), SK_PMColor4fWHITE, false);
+ } else {
+ shaderFP = GrFragmentProcessor::MulChildByInputAlpha(std::move(fp));
+ }
}
return SkPaintToGrPaintReplaceShader(context, colorSpaceInfo, paint, std::move(shaderFP),
diff --git a/src/gpu/effects/GrMixerEffect.fp b/src/gpu/effects/GrMixerEffect.fp
index cb0c979..9b6acf7 100644
--- a/src/gpu/effects/GrMixerEffect.fp
+++ b/src/gpu/effects/GrMixerEffect.fp
@@ -15,27 +15,11 @@
static OptimizationFlags OptFlags(const std::unique_ptr<GrFragmentProcessor>& fp0,
const std::unique_ptr<GrFragmentProcessor>& fp1) {
- auto get_flags = [](const std::unique_ptr<GrFragmentProcessor>& fp) {
- auto flags = kNone_OptimizationFlags;
-
- if (fp->compatibleWithCoverageAsAlpha()) {
- flags |= kCompatibleWithCoverageAsAlpha_OptimizationFlag;
- }
-
- if (fp->preservesOpaqueInput()) {
- flags |= kPreservesOpaqueInput_OptimizationFlag;
- }
-
- if (fp->hasConstantOutputForConstantInput()) {
- flags |= kConstantOutputForConstantInput_OptimizationFlag;
- }
-
- return flags;
- };
-
- const auto fp0_flags = get_flags(fp0);
-
- return fp1 ? (fp0_flags & get_flags(fp1)) : fp0_flags;
+ auto flags = ProcessorOptimizationFlags(fp0.get());
+ if (fp1) {
+ flags &= ProcessorOptimizationFlags(fp1.get());
+ }
+ return flags;
}
SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
diff --git a/src/gpu/effects/GrOverrideInputFragmentProcessor.fp b/src/gpu/effects/GrOverrideInputFragmentProcessor.fp
new file mode 100644
index 0000000..9f7ee9e
--- /dev/null
+++ b/src/gpu/effects/GrOverrideInputFragmentProcessor.fp
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// Ignores its own input color and invokes 'fp' with a constant color
+// The constant color can either be specified as a literal or as a
+// uniform, controlled by useUniform.
+
+in fragmentProcessor fp;
+layout(key) in bool useUniform;
+layout(when=useUniform, ctype=SkPMColor4f) in uniform half4 uniformColor;
+layout(when=!useUniform, key, ctype=SkPMColor4f) in half4 literalColor;
+
+@make {
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp,
+ const SkPMColor4f& color,
+ bool useUniform = true) {
+ return std::unique_ptr<GrFragmentProcessor>(
+ new GrOverrideInputFragmentProcessor(std::move(fp), useUniform, color, color));
+ }
+}
+
+@class {
+ static OptimizationFlags OptFlags(const std::unique_ptr<GrFragmentProcessor>& fp,
+ const SkPMColor4f& color) {
+ auto childFlags = ProcessorOptimizationFlags(fp.get());
+ auto flags = kNone_OptimizationFlags;
+ if (childFlags & kConstantOutputForConstantInput_OptimizationFlag) {
+ flags |= kConstantOutputForConstantInput_OptimizationFlag;
+ }
+ if ((childFlags & kPreservesOpaqueInput_OptimizationFlag) && color.isOpaque()) {
+ flags |= kPreservesOpaqueInput_OptimizationFlag;
+ }
+ return flags;
+ }
+
+ SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
+ return ConstantOutputForConstantInput(this->childProcessor(0), uniformColor);
+ }
+}
+
+@optimizationFlags { OptFlags(fp, useUniform ? uniformColor : literalColor) }
+
+void main() {
+ half4 constColor;
+ @if(useUniform) {
+ constColor = uniformColor;
+ } else {
+ constColor = literalColor;
+ }
+ sk_OutColor = process(fp, constColor);
+}
diff --git a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
index e3064bf..b5730fb 100644
--- a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
+++ b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
@@ -326,17 +326,8 @@
case SkBlendMode::kSrcIn:
case SkBlendMode::kDstIn:
case SkBlendMode::kModulate:
- if (fp->compatibleWithCoverageAsAlpha()) {
- if (fp->preservesOpaqueInput()) {
- flags = kPreservesOpaqueInput_OptimizationFlag |
- kCompatibleWithCoverageAsAlpha_OptimizationFlag;
- } else {
- flags = kCompatibleWithCoverageAsAlpha_OptimizationFlag;
- }
- } else {
- flags = fp->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
- : kNone_OptimizationFlags;
- }
+ flags = ProcessorOptimizationFlags(fp) &
+ ~kConstantOutputForConstantInput_OptimizationFlag;
break;
// Produces zero when both are opaque, indeterminate if one is opaque.
diff --git a/src/gpu/effects/generated/GrMixerEffect.h b/src/gpu/effects/generated/GrMixerEffect.h
index d318285..4c30fba 100644
--- a/src/gpu/effects/generated/GrMixerEffect.h
+++ b/src/gpu/effects/generated/GrMixerEffect.h
@@ -17,27 +17,11 @@
public:
static OptimizationFlags OptFlags(const std::unique_ptr<GrFragmentProcessor>& fp0,
const std::unique_ptr<GrFragmentProcessor>& fp1) {
- auto get_flags = [](const std::unique_ptr<GrFragmentProcessor>& fp) {
- auto flags = kNone_OptimizationFlags;
-
- if (fp->compatibleWithCoverageAsAlpha()) {
- flags |= kCompatibleWithCoverageAsAlpha_OptimizationFlag;
- }
-
- if (fp->preservesOpaqueInput()) {
- flags |= kPreservesOpaqueInput_OptimizationFlag;
- }
-
- if (fp->hasConstantOutputForConstantInput()) {
- flags |= kConstantOutputForConstantInput_OptimizationFlag;
- }
-
- return flags;
- };
-
- const auto fp0_flags = get_flags(fp0);
-
- return fp1 ? (fp0_flags & get_flags(fp1)) : fp0_flags;
+ auto flags = ProcessorOptimizationFlags(fp0.get());
+ if (fp1) {
+ flags &= ProcessorOptimizationFlags(fp1.get());
+ }
+ return flags;
}
SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
diff --git a/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp b/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp
new file mode 100644
index 0000000..c3d2d27
--- /dev/null
+++ b/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/**************************************************************************************************
+ *** This file was autogenerated from GrOverrideInputFragmentProcessor.fp; do not modify.
+ **************************************************************************************************/
+#include "GrOverrideInputFragmentProcessor.h"
+#include "glsl/GrGLSLFragmentProcessor.h"
+#include "glsl/GrGLSLFragmentShaderBuilder.h"
+#include "glsl/GrGLSLProgramBuilder.h"
+#include "GrTexture.h"
+#include "SkSLCPP.h"
+#include "SkSLUtil.h"
+class GrGLSLOverrideInputFragmentProcessor : public GrGLSLFragmentProcessor {
+public:
+ GrGLSLOverrideInputFragmentProcessor() {}
+ void emitCode(EmitArgs& args) override {
+ GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
+ const GrOverrideInputFragmentProcessor& _outer =
+ args.fFp.cast<GrOverrideInputFragmentProcessor>();
+ (void)_outer;
+ auto useUniform = _outer.useUniform;
+ (void)useUniform;
+ auto uniformColor = _outer.uniformColor;
+ (void)uniformColor;
+ auto literalColor = _outer.literalColor;
+ (void)literalColor;
+ if (useUniform) {
+ uniformColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
+ kHalf4_GrSLType, "uniformColor");
+ }
+ fragBuilder->codeAppendf(
+ "half4 constColor;\n@if (%s) {\n constColor = %s;\n} else {\n constColor = "
+ "half4(%f, %f, %f, %f);\n}",
+ (_outer.useUniform ? "true" : "false"),
+ uniformColorVar.isValid() ? args.fUniformHandler->getUniformCStr(uniformColorVar)
+ : "half4(0)",
+ _outer.literalColor.fR, _outer.literalColor.fG, _outer.literalColor.fB,
+ _outer.literalColor.fA);
+ SkString _input0("constColor");
+ SkString _child0("_child0");
+ this->emitChild(_outer.fp_index, _input0.c_str(), &_child0, args);
+ fragBuilder->codeAppendf("\n%s = %s;\n", args.fOutputColor, _child0.c_str());
+ }
+
+private:
+ void onSetData(const GrGLSLProgramDataManager& pdman,
+ const GrFragmentProcessor& _proc) override {
+ const GrOverrideInputFragmentProcessor& _outer =
+ _proc.cast<GrOverrideInputFragmentProcessor>();
+ {
+ if (uniformColorVar.isValid()) {
+ pdman.set4fv(uniformColorVar, 1, (_outer.uniformColor).vec());
+ }
+ }
+ }
+ UniformHandle uniformColorVar;
+};
+GrGLSLFragmentProcessor* GrOverrideInputFragmentProcessor::onCreateGLSLInstance() const {
+ return new GrGLSLOverrideInputFragmentProcessor();
+}
+void GrOverrideInputFragmentProcessor::onGetGLSLProcessorKey(const GrShaderCaps& caps,
+ GrProcessorKeyBuilder* b) const {
+ b->add32((int32_t)useUniform);
+ if (!useUniform) {
+ uint16_t red = SkFloatToHalf(literalColor.fR);
+ uint16_t green = SkFloatToHalf(literalColor.fG);
+ uint16_t blue = SkFloatToHalf(literalColor.fB);
+ uint16_t alpha = SkFloatToHalf(literalColor.fA);
+ b->add32(((uint32_t)red << 16) | green);
+ b->add32(((uint32_t)blue << 16) | alpha);
+ }
+}
+bool GrOverrideInputFragmentProcessor::onIsEqual(const GrFragmentProcessor& other) const {
+ const GrOverrideInputFragmentProcessor& that = other.cast<GrOverrideInputFragmentProcessor>();
+ (void)that;
+ if (useUniform != that.useUniform) return false;
+ if (uniformColor != that.uniformColor) return false;
+ if (literalColor != that.literalColor) return false;
+ return true;
+}
+GrOverrideInputFragmentProcessor::GrOverrideInputFragmentProcessor(
+ const GrOverrideInputFragmentProcessor& src)
+ : INHERITED(kGrOverrideInputFragmentProcessor_ClassID, src.optimizationFlags())
+ , fp_index(src.fp_index)
+ , useUniform(src.useUniform)
+ , uniformColor(src.uniformColor)
+ , literalColor(src.literalColor) {
+ this->registerChildProcessor(src.childProcessor(fp_index).clone());
+}
+std::unique_ptr<GrFragmentProcessor> GrOverrideInputFragmentProcessor::clone() const {
+ return std::unique_ptr<GrFragmentProcessor>(new GrOverrideInputFragmentProcessor(*this));
+}
diff --git a/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h b/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h
new file mode 100644
index 0000000..d7cacee
--- /dev/null
+++ b/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2019 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/**************************************************************************************************
+ *** This file was autogenerated from GrOverrideInputFragmentProcessor.fp; do not modify.
+ **************************************************************************************************/
+#ifndef GrOverrideInputFragmentProcessor_DEFINED
+#define GrOverrideInputFragmentProcessor_DEFINED
+#include "SkTypes.h"
+#include "GrFragmentProcessor.h"
+#include "GrCoordTransform.h"
+class GrOverrideInputFragmentProcessor : public GrFragmentProcessor {
+public:
+ static OptimizationFlags OptFlags(const std::unique_ptr<GrFragmentProcessor>& fp,
+ const SkPMColor4f& color) {
+ auto childFlags = ProcessorOptimizationFlags(fp.get());
+ auto flags = kNone_OptimizationFlags;
+ if (childFlags & kConstantOutputForConstantInput_OptimizationFlag) {
+ flags |= kConstantOutputForConstantInput_OptimizationFlag;
+ }
+ if ((childFlags & kPreservesOpaqueInput_OptimizationFlag) && color.isOpaque()) {
+ flags |= kPreservesOpaqueInput_OptimizationFlag;
+ }
+ return flags;
+ }
+
+ SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& input) const override {
+ return ConstantOutputForConstantInput(this->childProcessor(0), uniformColor);
+ }
+
+ static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> fp,
+ const SkPMColor4f& color,
+ bool useUniform = true) {
+ return std::unique_ptr<GrFragmentProcessor>(
+ new GrOverrideInputFragmentProcessor(std::move(fp), useUniform, color, color));
+ }
+ GrOverrideInputFragmentProcessor(const GrOverrideInputFragmentProcessor& src);
+ std::unique_ptr<GrFragmentProcessor> clone() const override;
+ const char* name() const override { return "OverrideInputFragmentProcessor"; }
+ int fp_index = -1;
+ bool useUniform;
+ SkPMColor4f uniformColor;
+ SkPMColor4f literalColor;
+
+private:
+ GrOverrideInputFragmentProcessor(std::unique_ptr<GrFragmentProcessor> fp,
+ bool useUniform,
+ SkPMColor4f uniformColor,
+ SkPMColor4f literalColor)
+ : INHERITED(kGrOverrideInputFragmentProcessor_ClassID,
+ (OptimizationFlags)OptFlags(fp, useUniform ? uniformColor : literalColor))
+ , useUniform(useUniform)
+ , uniformColor(uniformColor)
+ , literalColor(literalColor) {
+ SkASSERT(fp);
+ fp_index = this->numChildProcessors();
+ this->registerChildProcessor(std::move(fp));
+ }
+ GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
+ void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
+ bool onIsEqual(const GrFragmentProcessor&) const override;
+ GR_DECLARE_FRAGMENT_PROCESSOR_TEST
+ typedef GrFragmentProcessor INHERITED;
+};
+#endif
diff --git a/src/gpu/gradients/GrGradientShader.cpp b/src/gpu/gradients/GrGradientShader.cpp
index ac60b21..d204f97 100644
--- a/src/gpu/gradients/GrGradientShader.cpp
+++ b/src/gpu/gradients/GrGradientShader.cpp
@@ -236,7 +236,9 @@
// Unexpected tile mode
return nullptr;
}
-
+ if (args.fInputColorIsOpaque) {
+ return GrFragmentProcessor::OverrideInput(std::move(master), SK_PMColor4fWHITE, false);
+ }
return GrFragmentProcessor::MulChildByInputAlpha(std::move(master));
}
diff --git a/src/shaders/SkImageShader.cpp b/src/shaders/SkImageShader.cpp
index 581a310..c2e146c 100644
--- a/src/shaders/SkImageShader.cpp
+++ b/src/shaders/SkImageShader.cpp
@@ -257,6 +257,8 @@
args.fDstColorSpaceInfo->colorSpace());
if (isAlphaOnly) {
return inner;
+ } else if (args.fInputColorIsOpaque) {
+ return GrFragmentProcessor::OverrideInput(std::move(inner), SK_PMColor4fWHITE, false);
}
return GrFragmentProcessor::MulChildByInputAlpha(std::move(inner));
}
diff --git a/src/sksl/SkSLCPPCodeGenerator.cpp b/src/sksl/SkSLCPPCodeGenerator.cpp
index 570c5e8..c4f56b5 100644
--- a/src/sksl/SkSLCPPCodeGenerator.cpp
+++ b/src/sksl/SkSLCPPCodeGenerator.cpp
@@ -1106,7 +1106,7 @@
switch (param->fModifiers.fLayout.fKey) {
case Layout::kKey_Key:
if (param->fModifiers.fLayout.fWhen.size()) {
- this->writef("if (%s) ", param->fModifiers.fLayout.fWhen.c_str());
+ this->writef("if (%s) {", param->fModifiers.fLayout.fWhen.c_str());
}
if (param->fType == *fContext.fFloat4x4_Type) {
ABORT("no automatic key handling for float4x4\n");
@@ -1124,10 +1124,24 @@
HCodeGenerator::FieldName(name).c_str());
this->writef(" b->add32(%s.height());\n",
HCodeGenerator::FieldName(name).c_str());
+ } else if (param->fType == *fContext.fHalf4_Type) {
+ this->writef(" uint16_t red = SkFloatToHalf(%s.fR);\n",
+ HCodeGenerator::FieldName(name).c_str());
+ this->writef(" uint16_t green = SkFloatToHalf(%s.fG);\n",
+ HCodeGenerator::FieldName(name).c_str());
+ this->writef(" uint16_t blue = SkFloatToHalf(%s.fB);\n",
+ HCodeGenerator::FieldName(name).c_str());
+ this->writef(" uint16_t alpha = SkFloatToHalf(%s.fA);\n",
+ HCodeGenerator::FieldName(name).c_str());
+ this->write(" b->add32(((uint32_t)red << 16) | green);\n");
+ this->write(" b->add32(((uint32_t)blue << 16) | alpha);\n");
} else {
this->writef(" b->add32((int32_t) %s);\n",
HCodeGenerator::FieldName(name).c_str());
}
+ if (param->fModifiers.fLayout.fWhen.size()) {
+ this->write("}");
+ }
break;
case Layout::kIdentity_Key:
if (param->fType.kind() != Type::kMatrix_Kind) {