GPU support for SkColorFilters::HSLAMatrix
Change-Id: I5b762811b44861fcedd2fa5c0e48a82718458605 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/232398 Reviewed-by: Brian Salomon <bsalomon@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com> Commit-Queue: Florin Malita <fmalita@chromium.org>
This commit is contained in:
parent
32803ff744
commit
36031207dc
@ -381,6 +381,8 @@ skia_gpu_sources = [
|
||||
"$_src/gpu/effects/generated/GrConstColorProcessor.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/GrLumaColorFilterEffect.cpp",
|
||||
"$_src/gpu/effects/generated/GrLumaColorFilterEffect.h",
|
||||
"$_src/gpu/effects/generated/GrMagnifierEffect.cpp",
|
||||
@ -393,6 +395,8 @@ skia_gpu_sources = [
|
||||
"$_src/gpu/effects/generated/GrPremulInputFragmentProcessor.h",
|
||||
"$_src/gpu/effects/generated/GrRectBlurEffect.cpp",
|
||||
"$_src/gpu/effects/generated/GrRectBlurEffect.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/GrSaturateProcessor.cpp",
|
||||
|
@ -47,12 +47,14 @@ skia_gpu_processor_sources = [
|
||||
"$_src/gpu/effects/GrConstColorProcessor.fp",
|
||||
"$_src/gpu/effects/GrColorMatrixFragmentProcessor.fp",
|
||||
"$_src/gpu/effects/GrEllipseEffect.fp",
|
||||
"$_src/gpu/effects/GrHSLToRGBFilterEffect.fp",
|
||||
"$_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/GrRGBToHSLFilterEffect.fp",
|
||||
"$_src/gpu/effects/GrRRectBlurEffect.fp",
|
||||
"$_src/gpu/effects/GrSaturateProcessor.fp",
|
||||
"$_src/gpu/effects/GrSimpleTextureEffect.fp",
|
||||
|
@ -81,16 +81,30 @@ bool SkColorFilter_Matrix::onAppendStages(const SkStageRec& rec, bool shaderIsOp
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
#include "src/gpu/effects/generated/GrColorMatrixFragmentProcessor.h"
|
||||
#include "src/gpu/effects/generated/GrHSLToRGBFilterEffect.h"
|
||||
#include "src/gpu/effects/generated/GrRGBToHSLFilterEffect.h"
|
||||
std::unique_ptr<GrFragmentProcessor> SkColorFilter_Matrix::asFragmentProcessor(
|
||||
GrRecordingContext*, const GrColorInfo&) const {
|
||||
if (fDomain == Domain::kHSLA) {
|
||||
// TODO
|
||||
return nullptr;
|
||||
}
|
||||
switch (fDomain) {
|
||||
case Domain::kRGBA:
|
||||
return GrColorMatrixFragmentProcessor::Make(fMatrix,
|
||||
/* premulInput = */ true,
|
||||
/* clampRGBOutput = */ true,
|
||||
/* premulOutput = */ true);
|
||||
case Domain::kHSLA: {
|
||||
std::unique_ptr<GrFragmentProcessor> series[] = {
|
||||
GrRGBToHSLFilterEffect::Make(),
|
||||
GrColorMatrixFragmentProcessor::Make(fMatrix,
|
||||
/* premulInput = */ false,
|
||||
/* clampRGBOutput = */ false,
|
||||
/* premulOutput = */ false),
|
||||
GrHSLToRGBFilterEffect::Make(),
|
||||
};
|
||||
return GrFragmentProcessor::RunInSeries(series, SK_ARRAY_COUNT(series));
|
||||
}
|
||||
}
|
||||
|
||||
SkUNREACHABLE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -110,6 +110,7 @@ public:
|
||||
kGrFillRRectOp_Processor_ClassID,
|
||||
kGrGaussianConvolutionFragmentProcessor_ClassID,
|
||||
kGrGSCoverageProcessor_ClassID,
|
||||
kGrHSLToRGBFilterEffect_ClassID,
|
||||
kGrImprovedPerlinNoiseEffect_ClassID,
|
||||
kGrLinearGradientLayout_ClassID,
|
||||
kGrLumaColorFilterEffect_ClassID,
|
||||
@ -126,6 +127,7 @@ public:
|
||||
kGrQuadEffect_ClassID,
|
||||
kGrRadialGradientLayout_ClassID,
|
||||
kGrRectBlurEffect_ClassID,
|
||||
kGrRGBToHSLFilterEffect_ClassID,
|
||||
kGrRRectBlurEffect_ClassID,
|
||||
kGrRRectShadowGeoProc_ClassID,
|
||||
kGrSimpleTextureEffect_ClassID,
|
||||
|
49
src/gpu/effects/GrHSLToRGBFilterEffect.fp
Normal file
49
src/gpu/effects/GrHSLToRGBFilterEffect.fp
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
void main() {
|
||||
half3 hsl = sk_InColor.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;
|
||||
|
||||
sk_OutColor = saturate(half4(rgb, sk_InColor.a));
|
||||
sk_OutColor.rgb *= sk_OutColor.a;
|
||||
}
|
||||
|
||||
@optimizationFlags {
|
||||
(kConstantOutputForConstantInput_OptimizationFlag | kPreservesOpaqueInput_OptimizationFlag)
|
||||
}
|
||||
|
||||
@class {
|
||||
#include "include/private/SkColorData.h"
|
||||
#include "include/private/SkNx.h"
|
||||
|
||||
SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& c) const override {
|
||||
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();
|
||||
}
|
||||
}
|
73
src/gpu/effects/GrRGBToHSLFilterEffect.fp
Normal file
73
src/gpu/effects/GrRGBToHSLFilterEffect.fp
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
void main() {
|
||||
half4 c = sk_InColor;
|
||||
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);
|
||||
|
||||
sk_OutColor = half4(H, S, L, c.a);
|
||||
}
|
||||
|
||||
@optimizationFlags {
|
||||
(kConstantOutputForConstantInput_OptimizationFlag | kPreservesOpaqueInput_OptimizationFlag)
|
||||
}
|
||||
|
||||
@class {
|
||||
#include "include/private/SkColorData.h"
|
||||
|
||||
SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& c) const override {
|
||||
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 };
|
||||
}
|
||||
}
|
53
src/gpu/effects/generated/GrHSLToRGBFilterEffect.cpp
Normal file
53
src/gpu/effects/generated/GrHSLToRGBFilterEffect.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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 "include/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;
|
||||
fragBuilder->codeAppendf(
|
||||
"half3 hsl = %s.xyz;\nhalf C = (1.0 - abs(2.0 * hsl.z - 1.0)) * hsl.y;\nhalf3 p = "
|
||||
"hsl.xxx + half3(0.0, 0.66666666666666663, 0.33333333333333331);\nhalf3 q = "
|
||||
"clamp(abs(fract(p) * 6.0 - 3.0) - 1.0, 0.0, 1.0);\nhalf3 rgb = (q - 0.5) * C + "
|
||||
"hsl.z;\n%s = clamp(half4(rgb, %s.w), 0.0, 1.0);\n%s.xyz *= %s.w;\n",
|
||||
args.fInputColor, args.fOutputColor, args.fInputColor, args.fOutputColor,
|
||||
args.fOutputColor);
|
||||
}
|
||||
|
||||
private:
|
||||
void onSetData(const GrGLSLProgramDataManager& pdman,
|
||||
const GrFragmentProcessor& _proc) override {}
|
||||
};
|
||||
GrGLSLFragmentProcessor* GrHSLToRGBFilterEffect::onCreateGLSLInstance() const {
|
||||
return new 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()) {}
|
||||
std::unique_ptr<GrFragmentProcessor> GrHSLToRGBFilterEffect::clone() const {
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrHSLToRGBFilterEffect(*this));
|
||||
}
|
50
src/gpu/effects/generated/GrHSLToRGBFilterEffect.h
Normal file
50
src/gpu/effects/generated/GrHSLToRGBFilterEffect.h
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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/SkTypes.h"
|
||||
|
||||
#include "src/gpu/GrCoordTransform.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& c) const override {
|
||||
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() {
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrHSLToRGBFilterEffect());
|
||||
}
|
||||
GrHSLToRGBFilterEffect(const GrHSLToRGBFilterEffect& src);
|
||||
std::unique_ptr<GrFragmentProcessor> clone() const override;
|
||||
const char* name() const override { return "HSLToRGBFilterEffect"; }
|
||||
|
||||
private:
|
||||
GrHSLToRGBFilterEffect()
|
||||
: INHERITED(kGrHSLToRGBFilterEffect_ClassID,
|
||||
(OptimizationFlags)(kConstantOutputForConstantInput_OptimizationFlag |
|
||||
kPreservesOpaqueInput_OptimizationFlag)) {}
|
||||
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
|
55
src/gpu/effects/generated/GrRGBToHSLFilterEffect.cpp
Normal file
55
src/gpu/effects/generated/GrRGBToHSLFilterEffect.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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 "include/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;
|
||||
fragBuilder->codeAppendf(
|
||||
"half4 c = %s;\nhalf4 p = c.y < c.z ? half4(c.zy, -1.0, 0.66666666666666663) : "
|
||||
"half4(c.yz, 0.0, -0.33333333333333331);\nhalf4 q = c.x < p.x ? half4(p.x, c.x, "
|
||||
"p.yw) : half4(c.x, p.x, p.yz);\n\nhalf pmV = q.x;\nhalf pmC = pmV - min(q.y, "
|
||||
"q.z);\nhalf pmL = pmV - pmC * 0.5;\nhalf H = abs(q.w + (q.y - q.z) / (pmC * 6.0 + "
|
||||
"9.9999997473787516e-05));\nhalf S = pmC / ((c.w + 9.9999997473787516e-05) - "
|
||||
"abs(pmL * 2.0 - c.w));\nhalf L = pmL / (c.w + 9.9999997473787516e-05);\n%s = "
|
||||
"half4(H, S, L, c.w);\n",
|
||||
args.fInputColor, args.fOutputColor);
|
||||
}
|
||||
|
||||
private:
|
||||
void onSetData(const GrGLSLProgramDataManager& pdman,
|
||||
const GrFragmentProcessor& _proc) override {}
|
||||
};
|
||||
GrGLSLFragmentProcessor* GrRGBToHSLFilterEffect::onCreateGLSLInstance() const {
|
||||
return new 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()) {}
|
||||
std::unique_ptr<GrFragmentProcessor> GrRGBToHSLFilterEffect::clone() const {
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrRGBToHSLFilterEffect(*this));
|
||||
}
|
52
src/gpu/effects/generated/GrRGBToHSLFilterEffect.h
Normal file
52
src/gpu/effects/generated/GrRGBToHSLFilterEffect.h
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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/SkTypes.h"
|
||||
|
||||
#include "src/gpu/GrCoordTransform.h"
|
||||
#include "src/gpu/GrFragmentProcessor.h"
|
||||
class GrRGBToHSLFilterEffect : public GrFragmentProcessor {
|
||||
public:
|
||||
#include "include/private/SkColorData.h"
|
||||
|
||||
SkPMColor4f constantOutputForConstantInput(const SkPMColor4f& c) const override {
|
||||
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() {
|
||||
return std::unique_ptr<GrFragmentProcessor>(new GrRGBToHSLFilterEffect());
|
||||
}
|
||||
GrRGBToHSLFilterEffect(const GrRGBToHSLFilterEffect& src);
|
||||
std::unique_ptr<GrFragmentProcessor> clone() const override;
|
||||
const char* name() const override { return "RGBToHSLFilterEffect"; }
|
||||
|
||||
private:
|
||||
GrRGBToHSLFilterEffect()
|
||||
: INHERITED(kGrRGBToHSLFilterEffect_ClassID,
|
||||
(OptimizationFlags)(kConstantOutputForConstantInput_OptimizationFlag |
|
||||
kPreservesOpaqueInput_OptimizationFlag)) {}
|
||||
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
|
Loading…
Reference in New Issue
Block a user