Replace RGB <-> HSL FPs with runtime FPs
Awkwardly, there is still two copies of (some of) this SkSL. We have helper functions in SkRuntimeEffectPriv.h that implement these transformations, and those are used by the high contrast color filter. However: The RGB to HSL code is fairly different, and produces results that are visibly different. For this CL, I didn't want to impact either use case, so this is just a migration of the existing .fp code (only used by HSLA color matrices). We can/should look at merging the implementation in the future. Change-Id: I8a9aa6a2d8563ab4333af79a528e406c08b0e1ba Reviewed-on: https://skia-review.googlesource.com/c/skia/+/419497 Commit-Queue: Brian Osman <brianosman@google.com> Reviewed-by: John Stiles <johnstiles@google.com>
This commit is contained in:
parent
311010405e
commit
71bf78604b
@ -324,12 +324,8 @@ skia_gpu_sources = [
|
||||
"$_src/gpu/effects/generated/GrDitherEffect.h",
|
||||
"$_src/gpu/effects/generated/GrEllipseEffect.cpp",
|
||||
"$_src/gpu/effects/generated/GrEllipseEffect.h",
|
||||
"$_src/gpu/effects/generated/GrHSLToRGBFilterEffect.cpp",
|
||||
"$_src/gpu/effects/generated/GrHSLToRGBFilterEffect.h",
|
||||
"$_src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp",
|
||||
"$_src/gpu/effects/generated/GrOverrideInputFragmentProcessor.h",
|
||||
"$_src/gpu/effects/generated/GrRGBToHSLFilterEffect.cpp",
|
||||
"$_src/gpu/effects/generated/GrRGBToHSLFilterEffect.h",
|
||||
"$_src/gpu/effects/generated/GrRRectBlurEffect.cpp",
|
||||
"$_src/gpu/effects/generated/GrRRectBlurEffect.h",
|
||||
"$_src/gpu/effects/generated/GrRectBlurEffect.cpp",
|
||||
|
@ -215,9 +215,7 @@ skia_gpu_processor_sources = [
|
||||
"$_src/gpu/effects/GrDeviceSpaceEffect.fp",
|
||||
"$_src/gpu/effects/GrDitherEffect.fp",
|
||||
"$_src/gpu/effects/GrEllipseEffect.fp",
|
||||
"$_src/gpu/effects/GrHSLToRGBFilterEffect.fp",
|
||||
"$_src/gpu/effects/GrOverrideInputFragmentProcessor.fp",
|
||||
"$_src/gpu/effects/GrRGBToHSLFilterEffect.fp",
|
||||
"$_src/gpu/effects/GrRRectBlurEffect.fp",
|
||||
"$_src/gpu/effects/GrRectBlurEffect.fp",
|
||||
"$_src/gpu/gradients/GrClampedGradientEffect.fp",
|
||||
|
@ -120,8 +120,80 @@ skvm::Color SkColorFilter_Matrix::onProgram(skvm::Builder* p, skvm::Color c,
|
||||
}
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
#include "src/gpu/effects/generated/GrHSLToRGBFilterEffect.h"
|
||||
#include "src/gpu/effects/generated/GrRGBToHSLFilterEffect.h"
|
||||
#include "src/gpu/effects/GrSkSLFP.h"
|
||||
|
||||
// Convert RGBA -> HSLA (including unpremul).
|
||||
//
|
||||
// Based on work by Sam Hocevar, Emil Persson, and Ian Taylor [1][2][3]. High-level ideas:
|
||||
//
|
||||
// - minimize the number of branches by sorting and computing the hue phase in parallel (vec4s)
|
||||
//
|
||||
// - trade the third sorting branch for a potentially faster std::min and leaving 2nd/3rd
|
||||
// channels unsorted (based on the observation that swapping both the channels and the bias sign
|
||||
// has no effect under abs)
|
||||
//
|
||||
// - use epsilon offsets for denominators, to avoid explicit zero-checks
|
||||
//
|
||||
// An additional trick we employ is deferring premul->unpremul conversion until the very end: the
|
||||
// alpha factor gets naturally simplified for H and S, and only L requires a dedicated unpremul
|
||||
// division (so we trade three divs for one).
|
||||
//
|
||||
// [1] http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv
|
||||
// [2] http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl
|
||||
// [3] http://www.chilliant.com/rgb2hsv.html
|
||||
static std::unique_ptr<GrFragmentProcessor> rgb_to_hsl(std::unique_ptr<GrFragmentProcessor> child) {
|
||||
static auto effect = SkMakeRuntimeEffect(SkRuntimeEffect::MakeForColorFilter, R"(
|
||||
half4 main(half4 c) {
|
||||
half4 p = (c.g < c.b) ? half4(c.bg, -1, 2/3.0)
|
||||
: half4(c.gb, 0, -1/3.0);
|
||||
half4 q = (c.r < p.x) ? half4(p.x, c.r, p.yw)
|
||||
: half4(c.r, p.x, p.yz);
|
||||
|
||||
// q.x -> max channel value
|
||||
// q.yz -> 2nd/3rd channel values (unsorted)
|
||||
// q.w -> bias value dependent on max channel selection
|
||||
|
||||
half eps = 0.0001;
|
||||
half pmV = q.x;
|
||||
half pmC = pmV - min(q.y, q.z);
|
||||
half pmL = pmV - pmC * 0.5;
|
||||
half H = abs(q.w + (q.y - q.z) / (pmC * 6 + eps));
|
||||
half S = pmC / (c.a + eps - abs(pmL * 2 - c.a));
|
||||
half L = pmL / (c.a + eps);
|
||||
|
||||
return half4(H, S, L, c.a);
|
||||
}
|
||||
)");
|
||||
return GrSkSLFP::Make(
|
||||
effect, "RgbToHsl", std::move(child), GrSkSLFP::OptFlags::kPreservesOpaqueInput);
|
||||
}
|
||||
|
||||
// Convert HSLA -> RGBA (including clamp and premul).
|
||||
//
|
||||
// Based on work by Sam Hocevar, Emil Persson, and Ian Taylor [1][2][3].
|
||||
//
|
||||
// [1] http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv
|
||||
// [2] http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl
|
||||
// [3] http://www.chilliant.com/rgb2hsv.html
|
||||
static std::unique_ptr<GrFragmentProcessor> hsl_to_rgb(std::unique_ptr<GrFragmentProcessor> child) {
|
||||
static auto effect = SkMakeRuntimeEffect(SkRuntimeEffect::MakeForColorFilter, R"(
|
||||
half4 main(half4 color) {
|
||||
half3 hsl = color.rgb;
|
||||
|
||||
half C = (1 - abs(2 * hsl.z - 1)) * hsl.y;
|
||||
half3 p = hsl.xxx + half3(0, 2/3.0, 1/3.0);
|
||||
half3 q = saturate(abs(fract(p) * 6 - 3) - 1);
|
||||
half3 rgb = (q - 0.5) * C + hsl.z;
|
||||
|
||||
color = saturate(half4(rgb, color.a));
|
||||
color.rgb *= color.a;
|
||||
return color;
|
||||
}
|
||||
)");
|
||||
return GrSkSLFP::Make(
|
||||
effect, "HslToRgb", std::move(child), GrSkSLFP::OptFlags::kPreservesOpaqueInput);
|
||||
}
|
||||
|
||||
GrFPResult SkColorFilter_Matrix::asFragmentProcessor(std::unique_ptr<GrFragmentProcessor> fp,
|
||||
GrRecordingContext*,
|
||||
const GrColorInfo&) const {
|
||||
@ -134,12 +206,12 @@ GrFPResult SkColorFilter_Matrix::asFragmentProcessor(std::unique_ptr<GrFragmentP
|
||||
break;
|
||||
|
||||
case Domain::kHSLA:
|
||||
fp = GrRGBToHSLFilterEffect::Make(std::move(fp));
|
||||
fp = rgb_to_hsl(std::move(fp));
|
||||
fp = GrFragmentProcessor::ColorMatrix(std::move(fp), fMatrix,
|
||||
/* unpremulInput = */ false,
|
||||
/* clampRGBOutput = */ false,
|
||||
/* premulOutput = */ false);
|
||||
fp = GrHSLToRGBFilterEffect::Make(std::move(fp));
|
||||
fp = hsl_to_rgb(std::move(fp));
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,6 @@ public:
|
||||
kGrFillRRectOp_Processor_ClassID,
|
||||
kGrGaussianConvolutionFragmentProcessor_ClassID,
|
||||
kGrHighContrastFilterEffect_ClassID,
|
||||
kGrHSLToRGBFilterEffect_ClassID,
|
||||
kGrImprovedPerlinNoiseEffect_ClassID,
|
||||
kGrLinearGradientLayout_ClassID,
|
||||
kGrLumaColorFilterEffect_ClassID,
|
||||
@ -101,7 +100,6 @@ public:
|
||||
kGrQuadEffect_ClassID,
|
||||
kGrRadialGradientLayout_ClassID,
|
||||
kGrRectBlurEffect_ClassID,
|
||||
kGrRGBToHSLFilterEffect_ClassID,
|
||||
kGrRRectBlurEffect_ClassID,
|
||||
kGrRRectShadowGeoProc_ClassID,
|
||||
kGrSingleIntervalGradientColorizer_ClassID,
|
||||
|
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
// Convert HSLA -> RGBA (including clamp and premul).
|
||||
//
|
||||
// Based on work by Sam Hocevar, Emil Persson, and Ian Taylor [1][2][3].
|
||||
//
|
||||
// [1] http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv
|
||||
// [2] http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl
|
||||
// [3] http://www.chilliant.com/rgb2hsv.html
|
||||
|
||||
in fragmentProcessor inputFP;
|
||||
|
||||
half4 main() {
|
||||
half4 color = sample(inputFP);
|
||||
half3 hsl = color.rgb;
|
||||
|
||||
half C = (1 - abs(2 * hsl.z - 1)) * hsl.y;
|
||||
half3 p = hsl.xxx + half3(0, 2/3.0, 1/3.0);
|
||||
half3 q = saturate(abs(fract(p) * 6 - 3) - 1);
|
||||
half3 rgb = (q - 0.5) * C + hsl.z;
|
||||
|
||||
color = saturate(half4(rgb, color.a));
|
||||
color.rgb *= color.a;
|
||||
return color;
|
||||
}
|
||||
|
||||
@optimizationFlags {
|
||||
ProcessorOptimizationFlags(inputFP.get()) & (kConstantOutputForConstantInput_OptimizationFlag |
|
||||
kPreservesOpaqueInput_OptimizationFlag)
|
||||
}
|
||||
|
||||
@class {
|
||||
#include "include/private/SkColorData.h"
|
||||
#include "include/private/SkNx.h"
|
||||
|
||||
SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
|
||||
SkPMColor4f c = ConstantOutputForConstantInput(this->childProcessor(0), inColor);
|
||||
const auto H = c[0],
|
||||
S = c[1],
|
||||
L = c[2],
|
||||
C = (1 - std::abs(2 * L - 1)) * S;
|
||||
|
||||
const auto p = H + Sk4f(0, 2/3.f, 1/3.f, 0),
|
||||
q = Sk4f::Min(Sk4f::Max(((p - p.floor()) * 6 - 3).abs() - 1, 0), 1),
|
||||
rgb = (q - 0.5f) * C + L,
|
||||
rgba = Sk4f::Min(Sk4f::Max(Sk4f(rgb[0], rgb[1], rgb[2], c.fA), 0), 1);
|
||||
|
||||
return SkColor4f{rgba[0], rgba[1], rgba[2], rgba[3]}.premul();
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 Google LLC
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
// Convert RGBA -> HSLA (including unpremul).
|
||||
//
|
||||
// Based on work by Sam Hocevar, Emil Persson, and Ian Taylor [1][2][3]. High-level ideas:
|
||||
//
|
||||
// - minimize the number of branches by sorting and computing the hue phase in parallel (vec4s)
|
||||
//
|
||||
// - trade the third sorting branch for a potentially faster std::min and leaving 2nd/3rd
|
||||
// channels unsorted (based on the observation that swapping both the channels and the bias sign
|
||||
// has no effect under abs)
|
||||
//
|
||||
// - use epsilon offsets for denominators, to avoid explicit zero-checks
|
||||
//
|
||||
// An additional trick we employ is deferring premul->unpremul conversion until the very end: the
|
||||
// alpha factor gets naturally simplified for H and S, and only L requires a dedicated unpremul
|
||||
// division (so we trade three divs for one).
|
||||
//
|
||||
// [1] http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv
|
||||
// [2] http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl
|
||||
// [3] http://www.chilliant.com/rgb2hsv.html
|
||||
|
||||
in fragmentProcessor inputFP;
|
||||
|
||||
half4 main() {
|
||||
half4 c = sample(inputFP);
|
||||
half4 p = (c.g < c.b) ? half4(c.bg, -1, 2/3.0)
|
||||
: half4(c.gb, 0, -1/3.0);
|
||||
half4 q = (c.r < p.x) ? half4(p.x, c.r, p.yw)
|
||||
: half4(c.r, p.x, p.yz);
|
||||
|
||||
// q.x -> max channel value
|
||||
// q.yz -> 2nd/3rd channel values (unsorted)
|
||||
// q.w -> bias value dependent on max channel selection
|
||||
|
||||
half eps = 0.0001;
|
||||
half pmV = q.x;
|
||||
half pmC = pmV - min(q.y, q.z);
|
||||
half pmL = pmV - pmC * 0.5;
|
||||
half H = abs(q.w + (q.y - q.z) / (pmC * 6 + eps));
|
||||
half S = pmC / (c.a + eps - abs(pmL * 2 - c.a));
|
||||
half L = pmL / (c.a + eps);
|
||||
|
||||
return half4(H, S, L, c.a);
|
||||
}
|
||||
|
||||
@optimizationFlags {
|
||||
ProcessorOptimizationFlags(inputFP.get()) & (kConstantOutputForConstantInput_OptimizationFlag |
|
||||
kPreservesOpaqueInput_OptimizationFlag)
|
||||
}
|
||||
|
||||
@class {
|
||||
#include "include/private/SkColorData.h"
|
||||
|
||||
SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
|
||||
SkPMColor4f c = ConstantOutputForConstantInput(this->childProcessor(0), inColor);
|
||||
const auto p = (c.fG < c.fB) ? SkPMColor4f{ c.fB, c.fG, -1, 2/3.f }
|
||||
: SkPMColor4f{ c.fG, c.fB, 0, -1/3.f },
|
||||
q = (c.fR < p[0]) ? SkPMColor4f{ p[0], c.fR, p[1], p[3] }
|
||||
: SkPMColor4f{ c.fR, p[0], p[1], p[2] };
|
||||
|
||||
const auto eps = 0.0001f, // matching SkSL/ColorMatrix half4 epsilon
|
||||
pmV = q[0],
|
||||
pmC = pmV - std::min(q[1], q[2]),
|
||||
pmL = pmV - pmC * 0.5f,
|
||||
H = std::abs(q[3] + (q[1] - q[2]) / (pmC * 6 + eps)),
|
||||
S = pmC / (c.fA + eps - std::abs(pmL * 2 - c.fA)),
|
||||
L = pmL / (c.fA + eps);
|
||||
|
||||
return { H, S, L, c.fA };
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 Google LLC
|
||||
*
|
||||
* 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 GrHSLToRGBFilterEffect.fp; do not modify.
|
||||
**************************************************************************************************/
|
||||
#include "GrHSLToRGBFilterEffect.h"
|
||||
|
||||
#include "src/core/SkUtils.h"
|
||||
#include "src/gpu/GrTexture.h"
|
||||
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
|
||||
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
|
||||
#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
|
||||
#include "src/sksl/SkSLCPP.h"
|
||||
#include "src/sksl/SkSLUtil.h"
|
||||
class GrGLSLHSLToRGBFilterEffect : public GrGLSLFragmentProcessor {
|
||||
public:
|
||||
GrGLSLHSLToRGBFilterEffect() {}
|
||||
void emitCode(EmitArgs& args) override {
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
const GrHSLToRGBFilterEffect& _outer = args.fFp.cast<GrHSLToRGBFilterEffect>();
|
||||
(void)_outer;
|
||||
SkString _sample0 = this->invokeChild(0, args);
|
||||
fragBuilder->codeAppendf(
|
||||
R"SkSL(half4 color = %s;
|
||||
half3 hsl = color.xyz;
|
||||
half C = (1.0 - abs(2.0 * hsl.z - 1.0)) * hsl.y;
|
||||
half3 p = hsl.xxx + half3(0.0, 0.66666668653488159, 0.3333333432674408);
|
||||
half3 q = clamp(abs(fract(p) * 6.0 - 3.0) - 1.0, 0.0, 1.0);
|
||||
half3 rgb = (q - 0.5) * C + hsl.z;
|
||||
color = clamp(half4(rgb, color.w), 0.0, 1.0);
|
||||
color.xyz *= color.w;
|
||||
return color;
|
||||
)SkSL",
|
||||
_sample0.c_str());
|
||||
}
|
||||
|
||||
private:
|
||||
void onSetData(const GrGLSLProgramDataManager& pdman,
|
||||
const GrFragmentProcessor& _proc) override {}
|
||||
};
|
||||
std::unique_ptr<GrGLSLFragmentProcessor> GrHSLToRGBFilterEffect::onMakeProgramImpl() const {
|
||||
return std::make_unique<GrGLSLHSLToRGBFilterEffect>();
|
||||
}
|
||||
void GrHSLToRGBFilterEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
|
||||
GrProcessorKeyBuilder* b) const {}
|
||||
bool GrHSLToRGBFilterEffect::onIsEqual(const GrFragmentProcessor& other) const {
|
||||
const GrHSLToRGBFilterEffect& that = other.cast<GrHSLToRGBFilterEffect>();
|
||||
(void)that;
|
||||
return true;
|
||||
}
|
||||
GrHSLToRGBFilterEffect::GrHSLToRGBFilterEffect(const GrHSLToRGBFilterEffect& src)
|
||||
: INHERITED(kGrHSLToRGBFilterEffect_ClassID, src.optimizationFlags()) {
|
||||
this->cloneAndRegisterAllChildProcessors(src);
|
||||
}
|
||||
std::unique_ptr<GrFragmentProcessor> GrHSLToRGBFilterEffect::clone() const {
|
||||
return std::make_unique<GrHSLToRGBFilterEffect>(*this);
|
||||
}
|
||||
#if GR_TEST_UTILS
|
||||
SkString GrHSLToRGBFilterEffect::onDumpInfo() const { return SkString(); }
|
||||
#endif
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 Google LLC
|
||||
*
|
||||
* 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 GrHSLToRGBFilterEffect.fp; do not modify.
|
||||
**************************************************************************************************/
|
||||
#ifndef GrHSLToRGBFilterEffect_DEFINED
|
||||
#define GrHSLToRGBFilterEffect_DEFINED
|
||||
|
||||
#include "include/core/SkM44.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
#include "src/gpu/GrFragmentProcessor.h"
|
||||
|
||||
class GrHSLToRGBFilterEffect : public GrFragmentProcessor {
|
||||
public:
|
||||
#include "include/private/SkColorData.h"
|
||||
#include "include/private/SkNx.h"
|
||||
|
||||
SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
|
||||
SkPMColor4f c = ConstantOutputForConstantInput(this->childProcessor(0), inColor);
|
||||
const auto H = c[0], S = c[1], L = c[2], C = (1 - std::abs(2 * L - 1)) * S;
|
||||
|
||||
const auto p = H + Sk4f(0, 2 / 3.f, 1 / 3.f, 0),
|
||||
q = Sk4f::Min(Sk4f::Max(((p - p.floor()) * 6 - 3).abs() - 1, 0), 1),
|
||||
rgb = (q - 0.5f) * C + L,
|
||||
rgba = Sk4f::Min(Sk4f::Max(Sk4f(rgb[0], rgb[1], rgb[2], c.fA), 0), 1);
|
||||
|
||||
return SkColor4f{rgba[0], rgba[1], rgba[2], rgba[3]}.premul();
|
||||
}
|
||||
static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP) {
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrHSLToRGBFilterEffect(std::move(inputFP)));
|
||||
}
|
||||
GrHSLToRGBFilterEffect(const GrHSLToRGBFilterEffect& src);
|
||||
std::unique_ptr<GrFragmentProcessor> clone() const override;
|
||||
const char* name() const override { return "HSLToRGBFilterEffect"; }
|
||||
|
||||
private:
|
||||
GrHSLToRGBFilterEffect(std::unique_ptr<GrFragmentProcessor> inputFP)
|
||||
: INHERITED(kGrHSLToRGBFilterEffect_ClassID,
|
||||
(OptimizationFlags)ProcessorOptimizationFlags(inputFP.get()) &
|
||||
(kConstantOutputForConstantInput_OptimizationFlag |
|
||||
kPreservesOpaqueInput_OptimizationFlag)) {
|
||||
this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
|
||||
}
|
||||
std::unique_ptr<GrGLSLFragmentProcessor> onMakeProgramImpl() const override;
|
||||
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
|
||||
bool onIsEqual(const GrFragmentProcessor&) const override;
|
||||
#if GR_TEST_UTILS
|
||||
SkString onDumpInfo() const override;
|
||||
#endif
|
||||
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
|
||||
using INHERITED = GrFragmentProcessor;
|
||||
};
|
||||
#endif
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 Google LLC
|
||||
*
|
||||
* 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 GrRGBToHSLFilterEffect.fp; do not modify.
|
||||
**************************************************************************************************/
|
||||
#include "GrRGBToHSLFilterEffect.h"
|
||||
|
||||
#include "src/core/SkUtils.h"
|
||||
#include "src/gpu/GrTexture.h"
|
||||
#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
|
||||
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
|
||||
#include "src/gpu/glsl/GrGLSLProgramBuilder.h"
|
||||
#include "src/sksl/SkSLCPP.h"
|
||||
#include "src/sksl/SkSLUtil.h"
|
||||
class GrGLSLRGBToHSLFilterEffect : public GrGLSLFragmentProcessor {
|
||||
public:
|
||||
GrGLSLRGBToHSLFilterEffect() {}
|
||||
void emitCode(EmitArgs& args) override {
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
const GrRGBToHSLFilterEffect& _outer = args.fFp.cast<GrRGBToHSLFilterEffect>();
|
||||
(void)_outer;
|
||||
SkString _sample0 = this->invokeChild(0, args);
|
||||
fragBuilder->codeAppendf(
|
||||
R"SkSL(half4 c = %s;
|
||||
half4 p = c.y < c.z ? half4(c.zy, -1.0, 0.66666668653488159) : half4(c.yz, 0.0, -0.3333333432674408);
|
||||
half4 q = c.x < p.x ? half4(p.x, c.x, p.yw) : half4(c.x, p.x, p.yz);
|
||||
half eps = 9.9999997473787516e-05;
|
||||
half pmV = q.x;
|
||||
half pmC = pmV - min(q.y, q.z);
|
||||
half pmL = pmV - pmC * 0.5;
|
||||
half H = abs(q.w + (q.y - q.z) / (pmC * 6.0 + eps));
|
||||
half S = pmC / ((c.w + eps) - abs(pmL * 2.0 - c.w));
|
||||
half L = pmL / (c.w + eps);
|
||||
return half4(H, S, L, c.w);
|
||||
)SkSL",
|
||||
_sample0.c_str());
|
||||
}
|
||||
|
||||
private:
|
||||
void onSetData(const GrGLSLProgramDataManager& pdman,
|
||||
const GrFragmentProcessor& _proc) override {}
|
||||
};
|
||||
std::unique_ptr<GrGLSLFragmentProcessor> GrRGBToHSLFilterEffect::onMakeProgramImpl() const {
|
||||
return std::make_unique<GrGLSLRGBToHSLFilterEffect>();
|
||||
}
|
||||
void GrRGBToHSLFilterEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
|
||||
GrProcessorKeyBuilder* b) const {}
|
||||
bool GrRGBToHSLFilterEffect::onIsEqual(const GrFragmentProcessor& other) const {
|
||||
const GrRGBToHSLFilterEffect& that = other.cast<GrRGBToHSLFilterEffect>();
|
||||
(void)that;
|
||||
return true;
|
||||
}
|
||||
GrRGBToHSLFilterEffect::GrRGBToHSLFilterEffect(const GrRGBToHSLFilterEffect& src)
|
||||
: INHERITED(kGrRGBToHSLFilterEffect_ClassID, src.optimizationFlags()) {
|
||||
this->cloneAndRegisterAllChildProcessors(src);
|
||||
}
|
||||
std::unique_ptr<GrFragmentProcessor> GrRGBToHSLFilterEffect::clone() const {
|
||||
return std::make_unique<GrRGBToHSLFilterEffect>(*this);
|
||||
}
|
||||
#if GR_TEST_UTILS
|
||||
SkString GrRGBToHSLFilterEffect::onDumpInfo() const { return SkString(); }
|
||||
#endif
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 Google LLC
|
||||
*
|
||||
* 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 GrRGBToHSLFilterEffect.fp; do not modify.
|
||||
**************************************************************************************************/
|
||||
#ifndef GrRGBToHSLFilterEffect_DEFINED
|
||||
#define GrRGBToHSLFilterEffect_DEFINED
|
||||
|
||||
#include "include/core/SkM44.h"
|
||||
#include "include/core/SkTypes.h"
|
||||
|
||||
#include "src/gpu/GrFragmentProcessor.h"
|
||||
|
||||
class GrRGBToHSLFilterEffect : public GrFragmentProcessor {
|
||||
public:
|
||||
#include "include/private/SkColorData.h"
|
||||
|
||||
SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& inColor) const override {
|
||||
SkPMColor4f c = ConstantOutputForConstantInput(this->childProcessor(0), inColor);
|
||||
const auto p = (c.fG < c.fB) ? SkPMColor4f{c.fB, c.fG, -1, 2 / 3.f}
|
||||
: SkPMColor4f{c.fG, c.fB, 0, -1 / 3.f},
|
||||
q = (c.fR < p[0]) ? SkPMColor4f{p[0], c.fR, p[1], p[3]}
|
||||
: SkPMColor4f{c.fR, p[0], p[1], p[2]};
|
||||
|
||||
const auto eps = 0.0001f, // matching SkSL/ColorMatrix half4 epsilon
|
||||
pmV = q[0], pmC = pmV - std::min(q[1], q[2]), pmL = pmV - pmC * 0.5f,
|
||||
H = std::abs(q[3] + (q[1] - q[2]) / (pmC * 6 + eps)),
|
||||
S = pmC / (c.fA + eps - std::abs(pmL * 2 - c.fA)), L = pmL / (c.fA + eps);
|
||||
|
||||
return {H, S, L, c.fA};
|
||||
}
|
||||
static std::unique_ptr<GrFragmentProcessor> Make(std::unique_ptr<GrFragmentProcessor> inputFP) {
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrRGBToHSLFilterEffect(std::move(inputFP)));
|
||||
}
|
||||
GrRGBToHSLFilterEffect(const GrRGBToHSLFilterEffect& src);
|
||||
std::unique_ptr<GrFragmentProcessor> clone() const override;
|
||||
const char* name() const override { return "RGBToHSLFilterEffect"; }
|
||||
|
||||
private:
|
||||
GrRGBToHSLFilterEffect(std::unique_ptr<GrFragmentProcessor> inputFP)
|
||||
: INHERITED(kGrRGBToHSLFilterEffect_ClassID,
|
||||
(OptimizationFlags)ProcessorOptimizationFlags(inputFP.get()) &
|
||||
(kConstantOutputForConstantInput_OptimizationFlag |
|
||||
kPreservesOpaqueInput_OptimizationFlag)) {
|
||||
this->registerChild(std::move(inputFP), SkSL::SampleUsage::PassThrough());
|
||||
}
|
||||
std::unique_ptr<GrGLSLFragmentProcessor> onMakeProgramImpl() const override;
|
||||
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
|
||||
bool onIsEqual(const GrFragmentProcessor&) const override;
|
||||
#if GR_TEST_UTILS
|
||||
SkString onDumpInfo() const override;
|
||||
#endif
|
||||
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
|
||||
using INHERITED = GrFragmentProcessor;
|
||||
};
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user