Reland "Replace some gradient .fps with runtime FPs"

This reverts commit 16c0791a5a.

Reason for revert: Only errors are AMD+ANGLE+D3D9+ES2

Original change's description:
> Revert "Replace some gradient .fps with runtime FPs"
>
> This reverts commit 68d6983acd.
>
> Reason for revert: Going to investigate some bad ANGLE_D3D_ES2 images.
>
> Original change's description:
> > Replace some gradient .fps with runtime FPs
> >
> > Change-Id: Ia00f88d00c6010d87c775acd32493673020d5ae8
> > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/420577
> > Commit-Queue: Brian Osman <brianosman@google.com>
> > Reviewed-by: Michael Ludwig <michaelludwig@google.com>
>
> TBR=bsalomon@google.com,brianosman@google.com,michaelludwig@google.com
>
> Change-Id: If57772f0e2d5236c5122f3c7fe261c0a59f3b141
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/421920
> Reviewed-by: Brian Osman <brianosman@google.com>
> Commit-Queue: Brian Osman <brianosman@google.com>

# Not skipping CQ checks because this is a reland.

Change-Id: I3903a23ab08c256303ee14814f16b4d2e1cbc642
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/421928
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
Brian Osman 2021-06-25 15:58:43 +00:00 committed by Skia Commit-Bot
parent d253088fc2
commit 65b4597d07
24 changed files with 300 additions and 1915 deletions

View File

@ -392,20 +392,8 @@ skia_gpu_sources = [
"$_src/gpu/gradients/GrGradientShader.h",
"$_src/gpu/gradients/generated/GrClampedGradientEffect.cpp",
"$_src/gpu/gradients/generated/GrClampedGradientEffect.h",
"$_src/gpu/gradients/generated/GrDualIntervalGradientColorizer.cpp",
"$_src/gpu/gradients/generated/GrDualIntervalGradientColorizer.h",
"$_src/gpu/gradients/generated/GrLinearGradientLayout.cpp",
"$_src/gpu/gradients/generated/GrLinearGradientLayout.h",
"$_src/gpu/gradients/generated/GrRadialGradientLayout.cpp",
"$_src/gpu/gradients/generated/GrRadialGradientLayout.h",
"$_src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.cpp",
"$_src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.h",
"$_src/gpu/gradients/generated/GrSweepGradientLayout.cpp",
"$_src/gpu/gradients/generated/GrSweepGradientLayout.h",
"$_src/gpu/gradients/generated/GrTiledGradientEffect.cpp",
"$_src/gpu/gradients/generated/GrTiledGradientEffect.h",
"$_src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.cpp",
"$_src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.h",
"$_src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.cpp",
"$_src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.h",

View File

@ -217,12 +217,6 @@ skia_gpu_processor_sources = [
"$_src/gpu/effects/GrRRectBlurEffect.fp",
"$_src/gpu/effects/GrRectBlurEffect.fp",
"$_src/gpu/gradients/GrClampedGradientEffect.fp",
"$_src/gpu/gradients/GrDualIntervalGradientColorizer.fp",
"$_src/gpu/gradients/GrLinearGradientLayout.fp",
"$_src/gpu/gradients/GrRadialGradientLayout.fp",
"$_src/gpu/gradients/GrSingleIntervalGradientColorizer.fp",
"$_src/gpu/gradients/GrSweepGradientLayout.fp",
"$_src/gpu/gradients/GrTiledGradientEffect.fp",
"$_src/gpu/gradients/GrTwoPointConicalGradientLayout.fp",
"$_src/gpu/gradients/GrUnrolledBinaryGradientColorizer.fp",
]

View File

@ -78,13 +78,11 @@ public:
kGrDSLFPTest_Swizzle_ClassID,
kGrDSLFPTest_Ternary_ClassID,
kGrDSLFPTest_WhileStatement_ClassID,
kGrDualIntervalGradientColorizer_ClassID,
kGrEllipseEffect_ClassID,
kGrFillRRectOp_Processor_ClassID,
kGrGaussianConvolutionFragmentProcessor_ClassID,
kGrHighContrastFilterEffect_ClassID,
kGrImprovedPerlinNoiseEffect_ClassID,
kGrLinearGradientLayout_ClassID,
kGrLumaColorFilterEffect_ClassID,
kGrMatrixConvolutionEffect_ClassID,
kGrMatrixEffect_ClassID,
@ -94,18 +92,14 @@ public:
kGrPerlinNoise2Effect_ClassID,
kGrPipelineDynamicStateTestProcessor_ClassID,
kGrQuadEffect_ClassID,
kGrRadialGradientLayout_ClassID,
kGrRectBlurEffect_ClassID,
kGrRRectBlurEffect_ClassID,
kGrRRectShadowGeoProc_ClassID,
kGrSingleIntervalGradientColorizer_ClassID,
kGrSkSLFP_ClassID,
kGrSpecularLightingEffect_ClassID,
kGrSampleMaskProcessor_ClassID,
kGrSweepGradientLayout_ClassID,
kGrTextureEffect_ClassID,
kGrTiledGradientEffect_ClassID,
kGrTwoPointConicalGradientLayout_ClassID,
kGrUnrolledBinaryGradientColorizer_ClassID,
kGrYUVtoRGBEffect_ClassID,
kHighContrastFilterEffect_ClassID,

View File

@ -146,7 +146,7 @@ SkTArray<GrXPFactoryTestFactory*, true>* GrXPFactoryTestFactory::GetFactories()
* we verify the count is as expected. If a new factory is added, then these numbers must be
* manually adjusted.
*/
static constexpr int kFPFactoryCount = 29;
static constexpr int kFPFactoryCount = 25;
static constexpr int kGPFactoryCount = 14;
static constexpr int kXPFactoryCount = 4;

View File

@ -27,17 +27,18 @@ template <typename T> struct GrFPUniformType {
template <typename U> struct add_a_UNIFORM_TYPE_specialization_for {};
static constexpr add_a_UNIFORM_TYPE_specialization_for<T> value = {};
};
#define UNIFORM_TYPE(T, E) \
template <> struct GrFPUniformType<T> { \
#define UNIFORM_TYPE(E, ...) \
template <> struct GrFPUniformType<__VA_ARGS__> { \
static constexpr SkRuntimeEffect::Uniform::Type value = SkRuntimeEffect::Uniform::Type::E; \
}
UNIFORM_TYPE(float, kFloat);
UNIFORM_TYPE(SkV2, kFloat2);
UNIFORM_TYPE(SkPMColor4f, kFloat4);
UNIFORM_TYPE(SkV4, kFloat4);
UNIFORM_TYPE(SkM44, kFloat4x4);
UNIFORM_TYPE(int, kInt);
UNIFORM_TYPE(kFloat, float);
UNIFORM_TYPE(kFloat2, SkV2);
UNIFORM_TYPE(kFloat4, SkPMColor4f);
UNIFORM_TYPE(kFloat4, SkV4);
UNIFORM_TYPE(kFloat4, skvx::Vec<4, float>);
UNIFORM_TYPE(kFloat4x4, SkM44);
UNIFORM_TYPE(kInt, int);
#undef UNIFORM_TYPE
#endif

View File

@ -1,62 +0,0 @@
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// Models two intervals (so 4 colors), that are connected at a specific threshold point.
// Bias and scale for 0 to threshold
layout(ctype=SkPMColor4f) in uniform float4 scale01;
layout(ctype=SkPMColor4f) in uniform float4 bias01;
// Bias and scale for threshold to 1
layout(ctype=SkPMColor4f) in uniform float4 scale23;
layout(ctype=SkPMColor4f) in uniform float4 bias23;
in uniform half threshold;
half4 main(float2 coord) {
half t = half(coord.x);
float4 scale, bias;
if (t < threshold) {
scale = scale01;
bias = bias01;
} else {
scale = scale23;
bias = bias23;
}
return half4(t * scale + bias);
}
//////////////////////////////////////////////////////////////////////////////
@make {
static std::unique_ptr<GrFragmentProcessor> Make(const SkPMColor4f& c0, const SkPMColor4f& c1,
const SkPMColor4f& c2, const SkPMColor4f& c3,
float threshold);
}
@cppEnd {
std::unique_ptr<GrFragmentProcessor> GrDualIntervalGradientColorizer::Make(
const SkPMColor4f& c0, const SkPMColor4f& c1, const SkPMColor4f& c2, const SkPMColor4f& c3, float threshold) {
// Derive scale and biases from the 4 colors and threshold
auto vc0 = Sk4f::Load(c0.vec());
auto vc1 = Sk4f::Load(c1.vec());
auto scale01 = (vc1 - vc0) / threshold;
// bias01 = c0
auto vc2 = Sk4f::Load(c2.vec());
auto vc3 = Sk4f::Load(c3.vec());
auto scale23 = (vc3 - vc2) / (1 - threshold);
auto bias23 = vc2 - threshold * scale23;
return std::unique_ptr<GrFragmentProcessor>(new GrDualIntervalGradientColorizer(
{ scale01[0], scale01[1], scale01[2], scale01[3] }, c0,
{ scale23[0], scale23[1], scale23[2], scale23[3] },
{ bias23[0], bias23[1], bias23[2], bias23[3] }, threshold));
}
}

View File

@ -10,22 +10,18 @@
#include "src/gpu/gradients/generated/GrClampedGradientEffect.h"
#include "src/gpu/gradients/generated/GrTiledGradientEffect.h"
#include "src/gpu/gradients/generated/GrLinearGradientLayout.h"
#include "src/gpu/gradients/generated/GrRadialGradientLayout.h"
#include "src/gpu/gradients/generated/GrSweepGradientLayout.h"
#include "src/gpu/gradients/generated/GrTwoPointConicalGradientLayout.h"
#include "src/gpu/gradients/GrGradientBitmapCache.h"
#include "src/gpu/gradients/generated/GrDualIntervalGradientColorizer.h"
#include "src/gpu/gradients/generated/GrSingleIntervalGradientColorizer.h"
#include "src/gpu/gradients/generated/GrUnrolledBinaryGradientColorizer.h"
#include "include/gpu/GrRecordingContext.h"
#include "src/core/SkRuntimeEffectPriv.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrColor.h"
#include "src/gpu/GrColorInfo.h"
#include "src/gpu/GrRecordingContextPriv.h"
#include "src/gpu/SkGr.h"
#include "src/gpu/effects/GrMatrixEffect.h"
#include "src/gpu/effects/GrSkSLFP.h"
#include "src/gpu/effects/GrTextureEffect.h"
// Intervals smaller than this (that aren't hard stops) on low-precision-only devices force us to
@ -69,6 +65,74 @@ static std::unique_ptr<GrFragmentProcessor> make_textured_colorizer(const SkPMCo
return GrTextureEffect::Make(std::move(view), alphaType, m, GrSamplerState::Filter::kLinear);
}
static std::unique_ptr<GrFragmentProcessor> make_single_interval_colorizer(const SkPMColor4f& start,
const SkPMColor4f& end) {
static auto effect = SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader, R"(
uniform half4 start;
uniform half4 end;
half4 main(float2 coord) {
// Clamping and/or wrapping was already handled by the parent shader so the output
// color is a simple lerp.
return mix(start, end, half(coord.x));
}
)");
return GrSkSLFP::Make(effect, "SingleIntervalColorizer", /*inputFP=*/nullptr,
GrSkSLFP::OptFlags::kNone,
"start", start,
"end", end);
}
static std::unique_ptr<GrFragmentProcessor> make_dual_interval_colorizer(const SkPMColor4f& c0,
const SkPMColor4f& c1,
const SkPMColor4f& c2,
const SkPMColor4f& c3,
float threshold) {
static auto effect = SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader, R"(
uniform float4 scale01;
uniform float4 bias01;
uniform float4 scale23;
uniform float4 bias23;
uniform half threshold;
half4 main(float2 coord) {
half t = half(coord.x);
float4 scale, bias;
if (t < threshold) {
scale = scale01;
bias = bias01;
} else {
scale = scale23;
bias = bias23;
}
return half4(t * scale + bias);
}
)");
using sk4f = skvx::Vec<4, float>;
// Derive scale and biases from the 4 colors and threshold
auto vc0 = sk4f::Load(c0.vec());
auto vc1 = sk4f::Load(c1.vec());
auto scale01 = (vc1 - vc0) / threshold;
// bias01 = c0
auto vc2 = sk4f::Load(c2.vec());
auto vc3 = sk4f::Load(c3.vec());
auto scale23 = (vc3 - vc2) / (1 - threshold);
auto bias23 = vc2 - threshold * scale23;
return GrSkSLFP::Make(effect, "DualIntervalColorizer", /*inputFP=*/nullptr,
GrSkSLFP::OptFlags::kNone,
"scale01", scale01,
"bias01", c0,
"scale23", scale23,
"bias23", bias23,
"threshold", threshold);
}
// Analyze the shader's color stops and positions and chooses an appropriate colorizer to represent
// the gradient.
static std::unique_ptr<GrFragmentProcessor> make_colorizer(const SkPMColor4f* colors,
@ -95,7 +159,7 @@ static std::unique_ptr<GrFragmentProcessor> make_colorizer(const SkPMColor4f* co
// Two remaining colors means a single interval from 0 to 1
// (but it may have originally been a 3 or 4 color gradient with 1-2 hard stops at the ends)
if (count == 2) {
return GrSingleIntervalGradientColorizer::Make(colors[offset], colors[offset + 1]);
return make_single_interval_colorizer(colors[offset], colors[offset + 1]);
}
// Do an early test for the texture fallback to skip all of the other tests for specific
@ -125,15 +189,15 @@ static std::unique_ptr<GrFragmentProcessor> make_colorizer(const SkPMColor4f* co
if (count == 3) {
// Must be a dual interval gradient, where the middle point is at offset+1 and the two
// intervals share the middle color stop.
return GrDualIntervalGradientColorizer::Make(colors[offset], colors[offset + 1],
colors[offset + 1], colors[offset + 2],
positions[offset + 1]);
return make_dual_interval_colorizer(colors[offset], colors[offset + 1],
colors[offset + 1], colors[offset + 2],
positions[offset + 1]);
} else if (count == 4 && SkScalarNearlyEqual(positions[offset + 1],
positions[offset + 2])) {
// Two separate intervals that join at the same threshold position
return GrDualIntervalGradientColorizer::Make(colors[offset], colors[offset + 1],
colors[offset + 2], colors[offset + 3],
positions[offset + 1]);
return make_dual_interval_colorizer(colors[offset], colors[offset + 1],
colors[offset + 2], colors[offset + 3],
positions[offset + 1]);
}
// The single and dual intervals are a specialized case of the unrolled binary search
@ -153,14 +217,26 @@ static std::unique_ptr<GrFragmentProcessor> make_colorizer(const SkPMColor4f* co
// Combines the colorizer and layout with an appropriately configured top-level effect based on the
// gradient's tile mode
static std::unique_ptr<GrFragmentProcessor> make_gradient(const SkGradientShaderBase& shader,
const GrFPArgs& args, std::unique_ptr<GrFragmentProcessor> layout) {
static std::unique_ptr<GrFragmentProcessor> make_gradient(
const SkGradientShaderBase& shader,
const GrFPArgs& args,
std::unique_ptr<GrFragmentProcessor> layout,
const SkMatrix* overrideMatrix = nullptr) {
// No shader is possible if a layout couldn't be created, e.g. a layout-specific Make() returned
// null.
if (layout == nullptr) {
return nullptr;
}
// Wrap the layout in a matrix effect to apply the gradient's matrix:
SkMatrix matrix;
if (!shader.totalLocalMatrix(args.fPreLocalMatrix)->invert(&matrix)) {
return nullptr;
}
// Some two-point conical gradients use a custom matrix here
matrix.postConcat(overrideMatrix ? *overrideMatrix : shader.getGradientMatrix());
layout = GrMatrixEffect::Make(matrix, std::move(layout));
// Convert all colors into destination space and into SkPMColor4fs, and handle
// premul issues depending on the interpolation mode
bool inputPremul = shader.getGradFlags() & SkGradientShader::kInterpolateColorsInPremul_Flag;
@ -257,22 +333,216 @@ namespace GrGradientShader {
std::unique_ptr<GrFragmentProcessor> MakeLinear(const SkLinearGradient& shader,
const GrFPArgs& args) {
return make_gradient(shader, args, GrLinearGradientLayout::Make(shader, args));
// We add a tiny delta to t. When gradient stops are set up so that a hard stop in a vertically
// or horizontally oriented gradient falls exactly at a column or row of pixel centers we can
// we can get slightly different interpolated t values along the column/row. By adding the delta
// we will consistently get the color to the "right" of the stop. Of course if the hard stop
// falls at X.5 - delta then we still could get inconsistent results, but that is much less
// likely. crbug.com/938592
// If/when we add filtering of the gradient this can be removed.
static auto effect = SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader, R"(
half4 main(float2 coord) {
return half4(half(coord.x) + 0.00001, 1, 0, 0); // y = 1 for always valid
}
)");
// The linear gradient never rejects a pixel so it doesn't change opacity
auto fp = GrSkSLFP::Make(effect, "LinearLayout", /*inputFP=*/nullptr,
GrSkSLFP::OptFlags::kPreservesOpaqueInput);
return make_gradient(shader, args, std::move(fp));
}
std::unique_ptr<GrFragmentProcessor> MakeRadial(const SkRadialGradient& shader,
const GrFPArgs& args) {
return make_gradient(shader,args, GrRadialGradientLayout::Make(shader, args));
static auto effect = SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader, R"(
half4 main(float2 coord) {
return half4(half(length(coord)), 1, 0, 0); // y = 1 for always valid
}
)");
// The radial gradient never rejects a pixel so it doesn't change opacity
auto fp = GrSkSLFP::Make(effect, "RadialLayout", /*inputFP=*/nullptr,
GrSkSLFP::OptFlags::kPreservesOpaqueInput);
return make_gradient(shader, args, std::move(fp));
}
std::unique_ptr<GrFragmentProcessor> MakeSweep(const SkSweepGradient& shader,
const GrFPArgs& args) {
return make_gradient(shader,args, GrSweepGradientLayout::Make(shader, args));
// On some devices they incorrectly implement atan2(y,x) as atan(y/x). In actuality it is
// atan2(y,x) = 2 * atan(y / (sqrt(x^2 + y^2) + x)). So to work around this we pass in (sqrt(x^2
// + y^2) + x) as the second parameter to atan2 in these cases. We let the device handle the
// undefined behavior of the second paramenter being 0 instead of doing the divide ourselves and
// using atan instead.
int useAtanWorkaround =
args.fContext->priv().caps()->shaderCaps()->atan2ImplementedAsAtanYOverX();
static auto effect = SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader, R"(
uniform half bias;
uniform half scale;
uniform int useAtanWorkaround; // specialized
half4 main(float2 coord) {
half angle = bool(useAtanWorkaround)
? half(2 * atan(-coord.y, length(coord) - coord.x))
: half(atan(-coord.y, -coord.x));
// 0.1591549430918 is 1/(2*pi), used since atan returns values [-pi, pi]
half t = (angle * 0.1591549430918 + 0.5 + bias) * scale;
return half4(t, 1, 0, 0); // y = 1 for always valid
}
)");
// The sweep gradient never rejects a pixel so it doesn't change opacity
auto fp = GrSkSLFP::Make(effect, "SweepLayout", /*inputFP=*/nullptr,
GrSkSLFP::OptFlags::kPreservesOpaqueInput,
"bias", shader.getTBias(),
"scale", shader.getTScale(),
"useAtanWorkaround", GrSkSLFP::Specialize(useAtanWorkaround));
return make_gradient(shader, args, std::move(fp));
}
std::unique_ptr<GrFragmentProcessor> MakeConical(const SkTwoPointConicalGradient& shader,
const GrFPArgs& args) {
return make_gradient(shader, args, GrTwoPointConicalGradientLayout::Make(shader, args));
// The 2 point conical gradient can reject a pixel so it does change opacity even if the input
// was opaque. Thus, all of these layout FPs disable that optimization.
std::unique_ptr<GrFragmentProcessor> fp;
SkTLazy<SkMatrix> matrix;
switch (shader.getType()) {
case SkTwoPointConicalGradient::Type::kStrip: {
static auto effect = SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader, R"(
uniform half r0_2;
half4 main(float2 p) {
half v = 1; // validation flag, set to negative to discard fragment later
float t = r0_2 - p.y * p.y;
if (t >= 0) {
t = p.x + sqrt(t);
} else {
v = -1;
}
return half4(half(t), v, 0, 0);
}
)");
float r0 = shader.getStartRadius() / shader.getCenterX1();
fp = GrSkSLFP::Make(effect, "TwoPointConicalStripLayout", /*inputFP=*/nullptr,
GrSkSLFP::OptFlags::kNone,
"r0_2", r0 * r0);
} break;
case SkTwoPointConicalGradient::Type::kRadial: {
static auto effect = SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader, R"(
uniform half r0;
uniform half lengthScale;
half4 main(float2 p) {
half v = 1; // validation flag, set to negative to discard fragment later
float t = length(p) * lengthScale - r0;
return half4(half(t), v, 0, 0);
}
)");
float dr = shader.getDiffRadius();
float r0 = shader.getStartRadius() / dr;
bool isRadiusIncreasing = dr >= 0;
fp = GrSkSLFP::Make(effect, "TwoPointConicalRadialLayout", /*inputFP=*/nullptr,
GrSkSLFP::OptFlags::kNone,
"r0", r0,
"lengthScale", isRadiusIncreasing ? 1.0f : -1.0f);
// GPU radial matrix is different from the original matrix, since we map the diff radius
// to have |dr| = 1, so manually compute the final gradient matrix here.
// Map center to (0, 0)
matrix.set(SkMatrix::Translate(-shader.getStartCenter().fX,
-shader.getStartCenter().fY));
// scale |diffRadius| to 1
matrix->postScale(1 / dr, 1 / dr);
} break;
case SkTwoPointConicalGradient::Type::kFocal: {
static auto effect = SkMakeRuntimeEffect(SkRuntimeEffect::MakeForShader, R"(
// Optimization flags, all specialized:
uniform int isRadiusIncreasing;
uniform int isFocalOnCircle;
uniform int isWellBehaved;
uniform int isSwapped;
uniform int isNativelyFocal;
uniform half invR1; // 1/r1
uniform half fx; // focalX = r0/(r0-r1)
half4 main(float2 p) {
float t = -1;
half v = 1; // validation flag, set to negative to discard fragment later
float x_t = -1;
if (bool(isFocalOnCircle)) {
x_t = dot(p, p) / p.x;
} else if (bool(isWellBehaved)) {
x_t = length(p) - p.x * invR1;
} else {
float temp = p.x * p.x - p.y * p.y;
// Only do sqrt if temp >= 0; this is significantly slower than checking
// temp >= 0 in the if statement that checks r(t) >= 0. But GPU may break if
// we sqrt a negative float. (Although I havevn't observed that on any
// devices so far, and the old approach also does sqrt negative value
// without a check.) If the performance is really critical, maybe we should
// just compute the area where temp and x_t are always valid and drop all
// these ifs.
if (temp >= 0) {
if (bool(isSwapped) || !bool(isRadiusIncreasing)) {
x_t = -sqrt(temp) - p.x * invR1;
} else {
x_t = sqrt(temp) - p.x * invR1;
}
}
}
// The final calculation of t from x_t has lots of static optimizations but only
// do them when x_t is positive (which can be assumed true if isWellBehaved is
// true)
if (!bool(isWellBehaved)) {
// This will still calculate t even though it will be ignored later in the
// pipeline to avoid a branch
if (x_t <= 0.0) {
v = -1;
}
}
if (bool(isRadiusIncreasing)) {
if (bool(isNativelyFocal)) {
t = x_t;
} else {
t = x_t + fx;
}
} else {
if (bool(isNativelyFocal)) {
t = -x_t;
} else {
t = -x_t + fx;
}
}
if (bool(isSwapped)) {
t = 1 - t;
}
return half4(half(t), v, 0, 0);
}
)");
const SkTwoPointConicalGradient::FocalData& focalData = shader.getFocalData();
bool isRadiusIncreasing = (1 - focalData.fFocalX) > 0,
isFocalOnCircle = focalData.isFocalOnCircle(),
isWellBehaved = focalData.isWellBehaved(),
isSwapped = focalData.isSwapped(),
isNativelyFocal = focalData.isNativelyFocal();
fp = GrSkSLFP::Make(effect, "TwoPointConicalFocalLayout", /*inputFP=*/nullptr,
GrSkSLFP::OptFlags::kNone,
"isRadiusIncreasing", GrSkSLFP::Specialize<int>(isRadiusIncreasing),
"isFocalOnCircle", GrSkSLFP::Specialize<int>(isFocalOnCircle),
"isWellBehaved", GrSkSLFP::Specialize<int>(isWellBehaved),
"isSwapped", GrSkSLFP::Specialize<int>(isSwapped),
"isNativelyFocal", GrSkSLFP::Specialize<int>(isNativelyFocal),
"invR1", 1.0f / focalData.fR1,
"fx", focalData.fFocalX);
} break;
}
return make_gradient(shader, args, std::move(fp), matrix.getMaybeNull());
}
#if GR_TEST_UTILS

View File

@ -1,70 +0,0 @@
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
half4 main(float2 coord) {
// We add a tiny delta to t. When gradient stops are set up so that a hard stop in a vertically
// or horizontally oriented gradient falls exactly at a column or row of pixel centers we can
// we can get slightly different interpolated t values along the column/row. By adding the delta
// we will consistently get the color to the "right" of the stop. Of course if the hard stop
// falls at X.5 - delta then we still could get inconsistent results, but that is much less
// likely. crbug.com/938592
// If/when we add filtering of the gradient this can be removed.
return half4(half(coord.x) + 0.00001, 1, 0, 0); // y = 1 for always valid
}
//////////////////////////////////////////////////////////////////////////////
@header {
#include "src/gpu/effects/GrMatrixEffect.h"
#include "src/gpu/gradients/GrGradientShader.h"
#include "src/shaders/gradients/SkLinearGradient.h"
}
// The linear gradient never rejects a pixel so it doesn't change opacity
@optimizationFlags {
kPreservesOpaqueInput_OptimizationFlag
}
@make {
static std::unique_ptr<GrFragmentProcessor> Make(const SkLinearGradient& gradient,
const GrFPArgs& args);
}
@cppEnd {
std::unique_ptr<GrFragmentProcessor> GrLinearGradientLayout::Make(
const SkLinearGradient& grad, const GrFPArgs& args) {
SkMatrix matrix;
if (!grad.totalLocalMatrix(args.fPreLocalMatrix)->invert(&matrix)) {
return nullptr;
}
matrix.postConcat(grad.getGradientMatrix());
return GrMatrixEffect::Make(
matrix, std::unique_ptr<GrFragmentProcessor>(new GrLinearGradientLayout()));
}
}
//////////////////////////////////////////////////////////////////////////////
@test(d) {
SkScalar scale = GrGradientShader::RandomParams::kGradientScale;
SkPoint points[2];
points[0].fX = d->fRandom->nextRangeScalar(0.0f, scale);
points[0].fY = d->fRandom->nextRangeScalar(0.0f, scale);
points[1].fX = d->fRandom->nextRangeScalar(0.0f, scale);
points[1].fY = d->fRandom->nextRangeScalar(0.0f, scale);
GrGradientShader::RandomParams params(d->fRandom);
auto shader = params.fUseColors4f ?
SkGradientShader::MakeLinear(points, params.fColors4f, params.fColorSpace, params.fStops,
params.fColorCount, params.fTileMode) :
SkGradientShader::MakeLinear(points, params.fColors, params.fStops,
params.fColorCount, params.fTileMode);
GrTest::TestAsFPArgs asFPArgs(d);
std::unique_ptr<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
SkASSERT_RELEASE(fp);
return fp;
}

View File

@ -1,66 +0,0 @@
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
half4 main(float2 coord) {
return half4(half(length(coord)), 1, 0, 0); // y = 1 for always valid
}
//////////////////////////////////////////////////////////////////////////////
@header {
#include "src/gpu/effects/GrMatrixEffect.h"
#include "src/gpu/gradients/GrGradientShader.h"
#include "src/shaders/gradients/SkRadialGradient.h"
}
// The radial gradient never rejects a pixel so it doesn't change opacity
@optimizationFlags {
kPreservesOpaqueInput_OptimizationFlag
}
@make {
static std::unique_ptr<GrFragmentProcessor> Make(const SkRadialGradient& gradient,
const GrFPArgs& args);
}
@cppEnd {
std::unique_ptr<GrFragmentProcessor> GrRadialGradientLayout::Make(
const SkRadialGradient& grad, const GrFPArgs& args) {
SkMatrix matrix;
if (!grad.totalLocalMatrix(args.fPreLocalMatrix)->invert(&matrix)) {
return nullptr;
}
matrix.postConcat(grad.getGradientMatrix());
return GrMatrixEffect::Make(
matrix, std::unique_ptr<GrFragmentProcessor>(new GrRadialGradientLayout()));
}
}
//////////////////////////////////////////////////////////////////////////////
@test(d) {
SkScalar scale = GrGradientShader::RandomParams::kGradientScale;
std::unique_ptr<GrFragmentProcessor> fp;
GrTest::TestAsFPArgs asFPArgs(d);
do {
GrGradientShader::RandomParams params(d->fRandom);
SkPoint center;
center.fX = d->fRandom->nextRangeScalar(0.0f, scale);
center.fY = d->fRandom->nextRangeScalar(0.0f, scale);
SkScalar radius = d->fRandom->nextRangeScalar(0.0f, scale);
sk_sp<SkShader> shader = params.fUseColors4f
? SkGradientShader::MakeRadial(center, radius, params.fColors4f,
params.fColorSpace, params.fStops,
params.fColorCount, params.fTileMode)
: SkGradientShader::MakeRadial(center, radius, params.fColors,
params.fStops, params.fColorCount,
params.fTileMode);
// Degenerate params can create an Empty (non-null) shader, where fp will be nullptr
fp = shader ? as_SB(shader)->asFragmentProcessor(asFPArgs.args()) : nullptr;
} while (!fp);
return fp;
}

View File

@ -1,19 +0,0 @@
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// This only supports a 2-color single interval so it is a simple linear interpolation between the
// two end points based on t. But it serves as a good test for connecting all of the plumbing into a
// functional gradient shader.
layout(ctype=SkPMColor4f) in uniform half4 start;
layout(ctype=SkPMColor4f) in uniform half4 end;
half4 main(float2 coord) {
// Clamping and/or wrapping was already handled by the parent shader so the output color is a
// simple lerp.
return mix(start, end, half(coord.x));
}

View File

@ -1,76 +0,0 @@
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
in uniform half bias;
in uniform half scale;
half4 main(float2 coord) {
// On some devices they incorrectly implement atan2(y,x) as atan(y/x). In actuality it is
// atan2(y,x) = 2 * atan(y / (sqrt(x^2 + y^2) + x)). So to work around this we pass in (sqrt(x^2
// + y^2) + x) as the second parameter to atan2 in these cases. We let the device handle the
// undefined behavior of the second paramenter being 0 instead of doing the divide ourselves and
// using atan instead.
half angle = sk_Caps.atan2ImplementedAsAtanYOverX
? half(2 * atan(-coord.y, length(coord) - coord.x))
: half(atan(-coord.y, -coord.x));
// 0.1591549430918 is 1/(2*pi), used since atan returns values [-pi, pi]
half t = (angle * 0.1591549430918 + 0.5 + bias) * scale;
return half4(t, 1, 0, 0); // y = 1 for always valid
}
//////////////////////////////////////////////////////////////////////////////
@header {
#include "src/gpu/effects/GrMatrixEffect.h"
#include "src/gpu/gradients/GrGradientShader.h"
#include "src/shaders/gradients/SkSweepGradient.h"
}
// The sweep gradient never rejects a pixel so it doesn't change opacity
@optimizationFlags {
kPreservesOpaqueInput_OptimizationFlag
}
@make {
static std::unique_ptr<GrFragmentProcessor> Make(const SkSweepGradient& gradient,
const GrFPArgs& args);
}
@cppEnd {
std::unique_ptr<GrFragmentProcessor> GrSweepGradientLayout::Make(
const SkSweepGradient& grad, const GrFPArgs& args) {
SkMatrix matrix;
if (!grad.totalLocalMatrix(args.fPreLocalMatrix)->invert(&matrix)) {
return nullptr;
}
matrix.postConcat(grad.getGradientMatrix());
return GrMatrixEffect::Make(
matrix, std::unique_ptr<GrFragmentProcessor>(new GrSweepGradientLayout(
grad.getTBias(), grad.getTScale())));
}
}
//////////////////////////////////////////////////////////////////////////////
@test(d) {
SkScalar scale = GrGradientShader::RandomParams::kGradientScale;
SkPoint center;
center.fX = d->fRandom->nextRangeScalar(0.0f, scale);
center.fY = d->fRandom->nextRangeScalar(0.0f, scale);
GrGradientShader::RandomParams params(d->fRandom);
auto shader = params.fUseColors4f ?
SkGradientShader::MakeSweep(center.fX, center.fY, params.fColors4f, params.fColorSpace,
params.fStops, params.fColorCount) :
SkGradientShader::MakeSweep(center.fX, center.fY, params.fColors,
params.fStops, params.fColorCount);
GrTest::TestAsFPArgs asFPArgs(d);
std::unique_ptr<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
SkASSERT_RELEASE(fp);
return fp;
}

View File

@ -1,292 +0,0 @@
/*
* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
// Equivalent to SkTwoPointConicalGradient::Type
enum class Type {
kRadial, kStrip, kFocal
};
layout(key) in Type type;
layout(key) in bool isRadiusIncreasing;
// Focal-specific optimizations
layout(key) in bool isFocalOnCircle;
layout(key) in bool isWellBehaved;
layout(key) in bool isSwapped;
layout(key) in bool isNativelyFocal;
// focalParams is interpreted differently depending on if type is focal or degenerate when
// degenerate, focalParams = (r0, r0^2), so strips will use .y and kRadial will use .x when focal,
// focalParams = (1/r1, focalX = r0/(r0-r1)) The correct parameters are calculated once in Make for
// each FP
in uniform half2 focalParams;
half4 main(float2 p) {
float t = -1;
half v = 1; // validation flag, set to negative to discard fragment later
@switch (type) {
case Type::kStrip: {
half r0_2 = focalParams.y;
t = r0_2 - p.y * p.y;
if (t >= 0) {
t = p.x + sqrt(t);
} else {
v = -1;
}
}
break;
case Type::kRadial: {
half r0 = focalParams.x;
@if (isRadiusIncreasing) {
t = length(p) - r0;
} else {
t = -length(p) - r0;
}
}
break;
case Type::kFocal: {
half invR1 = focalParams.x;
half fx = focalParams.y;
float x_t = -1;
@if (isFocalOnCircle) {
x_t = dot(p, p) / p.x;
} else if (isWellBehaved) {
x_t = length(p) - p.x * invR1;
} else {
float temp = p.x * p.x - p.y * p.y;
// Only do sqrt if temp >= 0; this is significantly slower than checking temp >= 0
// in the if statement that checks r(t) >= 0. But GPU may break if we sqrt a
// negative float. (Although I havevn't observed that on any devices so far, and the
// old approach also does sqrt negative value without a check.) If the performance
// is really critical, maybe we should just compute the area where temp and x_t are
// always valid and drop all these ifs.
if (temp >= 0) {
@if (isSwapped || !isRadiusIncreasing) {
x_t = -sqrt(temp) - p.x * invR1;
} else {
x_t = sqrt(temp) - p.x * invR1;
}
}
}
// The final calculation of t from x_t has lots of static optimizations but only do them
// when x_t is positive (which can be assumed true if isWellBehaved is true)
@if (!isWellBehaved) {
// This will still calculate t even though it will be ignored later in the pipeline
// to avoid a branch
if (x_t <= 0.0) {
v = -1;
}
}
@if (isRadiusIncreasing) {
@if (isNativelyFocal) {
t = x_t;
} else {
t = x_t + fx;
}
} else {
@if (isNativelyFocal) {
t = -x_t;
} else {
t = -x_t + fx;
}
}
@if (isSwapped) {
t = 1 - t;
}
}
break;
}
return half4(half(t), v, 0, 0);
}
//////////////////////////////////////////////////////////////////////////////
@header {
#include "src/gpu/effects/GrMatrixEffect.h"
#include "src/gpu/gradients/GrGradientShader.h"
#include "src/shaders/gradients/SkTwoPointConicalGradient.h"
}
// The 2 point conical gradient can reject a pixel so it does change opacity
// even if the input was opaque, so disable that optimization
@optimizationFlags {
kNone_OptimizationFlags
}
@make {
static std::unique_ptr<GrFragmentProcessor> Make(const SkTwoPointConicalGradient& gradient,
const GrFPArgs& args);
}
@cppEnd {
// .fp files do not let you reference outside enum definitions, so we have to explicitly map
// between the two compatible enum defs
GrTwoPointConicalGradientLayout::Type convert_type(
SkTwoPointConicalGradient::Type type) {
switch(type) {
case SkTwoPointConicalGradient::Type::kRadial:
return GrTwoPointConicalGradientLayout::Type::kRadial;
case SkTwoPointConicalGradient::Type::kStrip:
return GrTwoPointConicalGradientLayout::Type::kStrip;
case SkTwoPointConicalGradient::Type::kFocal:
return GrTwoPointConicalGradientLayout::Type::kFocal;
}
SkDEBUGFAIL("Should not be reachable");
return GrTwoPointConicalGradientLayout::Type::kRadial;
}
std::unique_ptr<GrFragmentProcessor> GrTwoPointConicalGradientLayout::Make(
const SkTwoPointConicalGradient& grad, const GrFPArgs& args) {
GrTwoPointConicalGradientLayout::Type grType = convert_type(grad.getType());
// The focalData struct is only valid if isFocal is true
const SkTwoPointConicalGradient::FocalData& focalData = grad.getFocalData();
bool isFocal = grType == Type::kFocal;
// Calculate optimization switches from gradient specification
bool isFocalOnCircle = isFocal && focalData.isFocalOnCircle();
bool isWellBehaved = isFocal && focalData.isWellBehaved();
bool isSwapped = isFocal && focalData.isSwapped();
bool isNativelyFocal = isFocal && focalData.isNativelyFocal();
// Type-specific calculations: isRadiusIncreasing, focalParams, and the gradient matrix.
// However, all types start with the total inverse local matrix calculated from the shader
// and args
bool isRadiusIncreasing;
SkPoint focalParams; // really just a 2D tuple
SkMatrix matrix;
// Initialize the base matrix
if (!grad.totalLocalMatrix(args.fPreLocalMatrix)->invert(&matrix)) {
return nullptr;
}
if (isFocal) {
isRadiusIncreasing = (1 - focalData.fFocalX) > 0;
focalParams.set(1.0 / focalData.fR1, focalData.fFocalX);
matrix.postConcat(grad.getGradientMatrix());
} else if (grType == Type::kRadial) {
SkScalar dr = grad.getDiffRadius();
isRadiusIncreasing = dr >= 0;
SkScalar r0 = grad.getStartRadius() / dr;
focalParams.set(r0, r0 * r0);
// GPU radial matrix is different from the original matrix, since we map the diff radius
// to have |dr| = 1, so manually compute the final gradient matrix here.
// Map center to (0, 0)
matrix.postTranslate(-grad.getStartCenter().fX, -grad.getStartCenter().fY);
// scale |diffRadius| to 1
matrix.postScale(1 / dr, 1 / dr);
} else { // kStrip
isRadiusIncreasing = false; // kStrip doesn't use this flag
SkScalar r0 = grad.getStartRadius() / grad.getCenterX1();
focalParams.set(r0, r0 * r0);
matrix.postConcat(grad.getGradientMatrix());
}
return GrMatrixEffect::Make(
matrix, std::unique_ptr<GrFragmentProcessor>(new GrTwoPointConicalGradientLayout(
grType, isRadiusIncreasing, isFocalOnCircle, isWellBehaved,
isSwapped, isNativelyFocal, focalParams)));
}
}
//////////////////////////////////////////////////////////////////////////////
@test(d) {
SkScalar scale = GrGradientShader::RandomParams::kGradientScale;
SkScalar offset = scale / 32.0f;
SkPoint center1, center2;
center1.fX = d->fRandom->nextRangeScalar(0.0f, scale);
center1.fY = d->fRandom->nextRangeScalar(0.0f, scale);
center2.fX = d->fRandom->nextRangeScalar(0.0f, scale);
center2.fY = d->fRandom->nextRangeScalar(0.0f, scale);
SkScalar radius1 = d->fRandom->nextRangeScalar(0.0f, scale);
SkScalar radius2 = d->fRandom->nextRangeScalar(0.0f, scale);
constexpr int kTestTypeMask = (1 << 2) - 1,
kTestNativelyFocalBit = (1 << 2),
kTestFocalOnCircleBit = (1 << 3),
kTestSwappedBit = (1 << 4);
// We won't treat isWellDefined and isRadiusIncreasing specially because they
// should have high probability to be turned on and off as we're getting random
// radii and centers.
int mask = d->fRandom->nextU();
int type = mask & kTestTypeMask;
if (type == static_cast<int>(Type::kRadial)) {
center2 = center1;
// Make sure that the radii are different
if (SkScalarNearlyZero(radius1 - radius2)) {
radius2 += offset;
}
} else if (type == static_cast<int>(Type::kStrip)) {
radius1 = std::max(radius1, .1f); // Make sure that the radius is non-zero
radius2 = radius1;
// Make sure that the centers are different
if (SkScalarNearlyZero(SkPoint::Distance(center1, center2))) {
center2.fX += offset;
}
} else { // kFocal_Type
// Make sure that the centers are different
if (SkScalarNearlyZero(SkPoint::Distance(center1, center2))) {
center2.fX += offset;
}
if (kTestNativelyFocalBit & mask) {
radius1 = 0;
}
if (kTestFocalOnCircleBit & mask) {
radius2 = radius1 + SkPoint::Distance(center1, center2);
}
if (kTestSwappedBit & mask) {
std::swap(radius1, radius2);
radius2 = 0;
}
// Make sure that the radii are different
if (SkScalarNearlyZero(radius1 - radius2)) {
radius2 += offset;
}
}
if (SkScalarNearlyZero(radius1 - radius2) &&
SkScalarNearlyZero(SkPoint::Distance(center1, center2))) {
radius2 += offset; // make sure that we're not degenerated
}
GrGradientShader::RandomParams params(d->fRandom);
auto shader = params.fUseColors4f ?
SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
params.fColors4f, params.fColorSpace, params.fStops,
params.fColorCount, params.fTileMode) :
SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
params.fColors, params.fStops,
params.fColorCount, params.fTileMode);
GrTest::TestAsFPArgs asFPArgs(d);
std::unique_ptr<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
SkASSERT_RELEASE(fp);
return fp;
}

View File

@ -1,166 +0,0 @@
/*
* Copyright 2018 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 GrDualIntervalGradientColorizer.fp; do not modify.
**************************************************************************************************/
#include "GrDualIntervalGradientColorizer.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 GrGLSLDualIntervalGradientColorizer : public GrGLSLFragmentProcessor {
public:
GrGLSLDualIntervalGradientColorizer() {}
void emitCode(EmitArgs& args) override {
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
const GrDualIntervalGradientColorizer& _outer =
args.fFp.cast<GrDualIntervalGradientColorizer>();
(void)_outer;
auto scale01 = _outer.scale01;
(void)scale01;
auto bias01 = _outer.bias01;
(void)bias01;
auto scale23 = _outer.scale23;
(void)scale23;
auto bias23 = _outer.bias23;
(void)bias23;
auto threshold = _outer.threshold;
(void)threshold;
scale01Var = args.fUniformHandler->addUniform(
&_outer, kFragment_GrShaderFlag, kFloat4_GrSLType, "scale01");
bias01Var = args.fUniformHandler->addUniform(
&_outer, kFragment_GrShaderFlag, kFloat4_GrSLType, "bias01");
scale23Var = args.fUniformHandler->addUniform(
&_outer, kFragment_GrShaderFlag, kFloat4_GrSLType, "scale23");
bias23Var = args.fUniformHandler->addUniform(
&_outer, kFragment_GrShaderFlag, kFloat4_GrSLType, "bias23");
thresholdVar = args.fUniformHandler->addUniform(
&_outer, kFragment_GrShaderFlag, kHalf_GrSLType, "threshold");
fragBuilder->codeAppendf(
R"SkSL(half t = half(%s.x);
float4 scale;
float4 bias;
if (t < %s) {
scale = %s;
bias = %s;
} else {
scale = %s;
bias = %s;
}
return half4(float(t) * scale + bias);
)SkSL",
args.fSampleCoord,
args.fUniformHandler->getUniformCStr(thresholdVar),
args.fUniformHandler->getUniformCStr(scale01Var),
args.fUniformHandler->getUniformCStr(bias01Var),
args.fUniformHandler->getUniformCStr(scale23Var),
args.fUniformHandler->getUniformCStr(bias23Var));
}
private:
void onSetData(const GrGLSLProgramDataManager& pdman,
const GrFragmentProcessor& _proc) override {
const GrDualIntervalGradientColorizer& _outer =
_proc.cast<GrDualIntervalGradientColorizer>();
{
pdman.set4fv(scale01Var, 1, _outer.scale01.vec());
pdman.set4fv(bias01Var, 1, _outer.bias01.vec());
pdman.set4fv(scale23Var, 1, _outer.scale23.vec());
pdman.set4fv(bias23Var, 1, _outer.bias23.vec());
pdman.set1f(thresholdVar, _outer.threshold);
}
}
UniformHandle scale01Var;
UniformHandle bias01Var;
UniformHandle scale23Var;
UniformHandle bias23Var;
UniformHandle thresholdVar;
};
std::unique_ptr<GrGLSLFragmentProcessor> GrDualIntervalGradientColorizer::onMakeProgramImpl()
const {
return std::make_unique<GrGLSLDualIntervalGradientColorizer>();
}
void GrDualIntervalGradientColorizer::onGetGLSLProcessorKey(const GrShaderCaps& caps,
GrProcessorKeyBuilder* b) const {}
bool GrDualIntervalGradientColorizer::onIsEqual(const GrFragmentProcessor& other) const {
const GrDualIntervalGradientColorizer& that = other.cast<GrDualIntervalGradientColorizer>();
(void)that;
if (scale01 != that.scale01) return false;
if (bias01 != that.bias01) return false;
if (scale23 != that.scale23) return false;
if (bias23 != that.bias23) return false;
if (threshold != that.threshold) return false;
return true;
}
GrDualIntervalGradientColorizer::GrDualIntervalGradientColorizer(
const GrDualIntervalGradientColorizer& src)
: INHERITED(kGrDualIntervalGradientColorizer_ClassID, src.optimizationFlags())
, scale01(src.scale01)
, bias01(src.bias01)
, scale23(src.scale23)
, bias23(src.bias23)
, threshold(src.threshold) {
this->cloneAndRegisterAllChildProcessors(src);
this->setUsesSampleCoordsDirectly();
}
std::unique_ptr<GrFragmentProcessor> GrDualIntervalGradientColorizer::clone() const {
return std::make_unique<GrDualIntervalGradientColorizer>(*this);
}
#if GR_TEST_UTILS
SkString GrDualIntervalGradientColorizer::onDumpInfo() const {
return SkStringPrintf(
"(scale01=float4(%f, %f, %f, %f), bias01=float4(%f, %f, %f, %f), scale23=float4(%f, "
"%f, %f, %f), bias23=float4(%f, %f, %f, %f), threshold=%f)",
scale01.fR,
scale01.fG,
scale01.fB,
scale01.fA,
bias01.fR,
bias01.fG,
bias01.fB,
bias01.fA,
scale23.fR,
scale23.fG,
scale23.fB,
scale23.fA,
bias23.fR,
bias23.fG,
bias23.fB,
bias23.fA,
threshold);
}
#endif
std::unique_ptr<GrFragmentProcessor> GrDualIntervalGradientColorizer::Make(const SkPMColor4f& c0,
const SkPMColor4f& c1,
const SkPMColor4f& c2,
const SkPMColor4f& c3,
float threshold) {
// Derive scale and biases from the 4 colors and threshold
auto vc0 = Sk4f::Load(c0.vec());
auto vc1 = Sk4f::Load(c1.vec());
auto scale01 = (vc1 - vc0) / threshold;
// bias01 = c0
auto vc2 = Sk4f::Load(c2.vec());
auto vc3 = Sk4f::Load(c3.vec());
auto scale23 = (vc3 - vc2) / (1 - threshold);
auto bias23 = vc2 - threshold * scale23;
return std::unique_ptr<GrFragmentProcessor>(
new GrDualIntervalGradientColorizer({scale01[0], scale01[1], scale01[2], scale01[3]},
c0,
{scale23[0], scale23[1], scale23[2], scale23[3]},
{bias23[0], bias23[1], bias23[2], bias23[3]},
threshold));
}

View File

@ -1,58 +0,0 @@
/*
* Copyright 2018 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 GrDualIntervalGradientColorizer.fp; do not modify.
**************************************************************************************************/
#ifndef GrDualIntervalGradientColorizer_DEFINED
#define GrDualIntervalGradientColorizer_DEFINED
#include "include/core/SkM44.h"
#include "include/core/SkTypes.h"
#include "src/gpu/GrFragmentProcessor.h"
class GrDualIntervalGradientColorizer : public GrFragmentProcessor {
public:
static std::unique_ptr<GrFragmentProcessor> Make(const SkPMColor4f& c0,
const SkPMColor4f& c1,
const SkPMColor4f& c2,
const SkPMColor4f& c3,
float threshold);
GrDualIntervalGradientColorizer(const GrDualIntervalGradientColorizer& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "DualIntervalGradientColorizer"; }
SkPMColor4f scale01;
SkPMColor4f bias01;
SkPMColor4f scale23;
SkPMColor4f bias23;
float threshold;
private:
GrDualIntervalGradientColorizer(SkPMColor4f scale01,
SkPMColor4f bias01,
SkPMColor4f scale23,
SkPMColor4f bias23,
float threshold)
: INHERITED(kGrDualIntervalGradientColorizer_ClassID, kNone_OptimizationFlags)
, scale01(scale01)
, bias01(bias01)
, scale23(scale23)
, bias23(bias23)
, threshold(threshold) {
this->setUsesSampleCoordsDirectly();
}
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

View File

@ -1,96 +0,0 @@
/*
* Copyright 2018 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 GrLinearGradientLayout.fp; do not modify.
**************************************************************************************************/
#include "GrLinearGradientLayout.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 GrGLSLLinearGradientLayout : public GrGLSLFragmentProcessor {
public:
GrGLSLLinearGradientLayout() {}
void emitCode(EmitArgs& args) override {
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
const GrLinearGradientLayout& _outer = args.fFp.cast<GrLinearGradientLayout>();
(void)_outer;
fragBuilder->codeAppendf(
R"SkSL(return half4(half(%s.x) + 9.9999997473787516e-06, 1.0, 0.0, 0.0);
)SkSL",
args.fSampleCoord);
}
private:
void onSetData(const GrGLSLProgramDataManager& pdman,
const GrFragmentProcessor& _proc) override {}
};
std::unique_ptr<GrGLSLFragmentProcessor> GrLinearGradientLayout::onMakeProgramImpl() const {
return std::make_unique<GrGLSLLinearGradientLayout>();
}
void GrLinearGradientLayout::onGetGLSLProcessorKey(const GrShaderCaps& caps,
GrProcessorKeyBuilder* b) const {}
bool GrLinearGradientLayout::onIsEqual(const GrFragmentProcessor& other) const {
const GrLinearGradientLayout& that = other.cast<GrLinearGradientLayout>();
(void)that;
return true;
}
GrLinearGradientLayout::GrLinearGradientLayout(const GrLinearGradientLayout& src)
: INHERITED(kGrLinearGradientLayout_ClassID, src.optimizationFlags()) {
this->cloneAndRegisterAllChildProcessors(src);
this->setUsesSampleCoordsDirectly();
}
std::unique_ptr<GrFragmentProcessor> GrLinearGradientLayout::clone() const {
return std::make_unique<GrLinearGradientLayout>(*this);
}
#if GR_TEST_UTILS
SkString GrLinearGradientLayout::onDumpInfo() const { return SkString(); }
#endif
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrLinearGradientLayout);
#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> GrLinearGradientLayout::TestCreate(GrProcessorTestData* d) {
SkScalar scale = GrGradientShader::RandomParams::kGradientScale;
SkPoint points[2];
points[0].fX = d->fRandom->nextRangeScalar(0.0f, scale);
points[0].fY = d->fRandom->nextRangeScalar(0.0f, scale);
points[1].fX = d->fRandom->nextRangeScalar(0.0f, scale);
points[1].fY = d->fRandom->nextRangeScalar(0.0f, scale);
GrGradientShader::RandomParams params(d->fRandom);
auto shader = params.fUseColors4f ? SkGradientShader::MakeLinear(points,
params.fColors4f,
params.fColorSpace,
params.fStops,
params.fColorCount,
params.fTileMode)
: SkGradientShader::MakeLinear(points,
params.fColors,
params.fStops,
params.fColorCount,
params.fTileMode);
GrTest::TestAsFPArgs asFPArgs(d);
std::unique_ptr<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
SkASSERT_RELEASE(fp);
return fp;
}
#endif
std::unique_ptr<GrFragmentProcessor> GrLinearGradientLayout::Make(const SkLinearGradient& grad,
const GrFPArgs& args) {
SkMatrix matrix;
if (!grad.totalLocalMatrix(args.fPreLocalMatrix)->invert(&matrix)) {
return nullptr;
}
matrix.postConcat(grad.getGradientMatrix());
return GrMatrixEffect::Make(matrix,
std::unique_ptr<GrFragmentProcessor>(new GrLinearGradientLayout()));
}

View File

@ -1,46 +0,0 @@
/*
* Copyright 2018 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 GrLinearGradientLayout.fp; do not modify.
**************************************************************************************************/
#ifndef GrLinearGradientLayout_DEFINED
#define GrLinearGradientLayout_DEFINED
#include "include/core/SkM44.h"
#include "include/core/SkTypes.h"
#include "src/gpu/effects/GrMatrixEffect.h"
#include "src/gpu/gradients/GrGradientShader.h"
#include "src/shaders/gradients/SkLinearGradient.h"
#include "src/gpu/GrFragmentProcessor.h"
class GrLinearGradientLayout : public GrFragmentProcessor {
public:
static std::unique_ptr<GrFragmentProcessor> Make(const SkLinearGradient& gradient,
const GrFPArgs& args);
GrLinearGradientLayout(const GrLinearGradientLayout& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "LinearGradientLayout"; }
private:
GrLinearGradientLayout()
: INHERITED(kGrLinearGradientLayout_ClassID,
(OptimizationFlags)kPreservesOpaqueInput_OptimizationFlag) {
this->setUsesSampleCoordsDirectly();
}
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

View File

@ -1,100 +0,0 @@
/*
* Copyright 2018 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 GrRadialGradientLayout.fp; do not modify.
**************************************************************************************************/
#include "GrRadialGradientLayout.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 GrGLSLRadialGradientLayout : public GrGLSLFragmentProcessor {
public:
GrGLSLRadialGradientLayout() {}
void emitCode(EmitArgs& args) override {
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
const GrRadialGradientLayout& _outer = args.fFp.cast<GrRadialGradientLayout>();
(void)_outer;
fragBuilder->codeAppendf(
R"SkSL(return half4(half(length(%s)), 1.0, 0.0, 0.0);
)SkSL",
args.fSampleCoord);
}
private:
void onSetData(const GrGLSLProgramDataManager& pdman,
const GrFragmentProcessor& _proc) override {}
};
std::unique_ptr<GrGLSLFragmentProcessor> GrRadialGradientLayout::onMakeProgramImpl() const {
return std::make_unique<GrGLSLRadialGradientLayout>();
}
void GrRadialGradientLayout::onGetGLSLProcessorKey(const GrShaderCaps& caps,
GrProcessorKeyBuilder* b) const {}
bool GrRadialGradientLayout::onIsEqual(const GrFragmentProcessor& other) const {
const GrRadialGradientLayout& that = other.cast<GrRadialGradientLayout>();
(void)that;
return true;
}
GrRadialGradientLayout::GrRadialGradientLayout(const GrRadialGradientLayout& src)
: INHERITED(kGrRadialGradientLayout_ClassID, src.optimizationFlags()) {
this->cloneAndRegisterAllChildProcessors(src);
this->setUsesSampleCoordsDirectly();
}
std::unique_ptr<GrFragmentProcessor> GrRadialGradientLayout::clone() const {
return std::make_unique<GrRadialGradientLayout>(*this);
}
#if GR_TEST_UTILS
SkString GrRadialGradientLayout::onDumpInfo() const { return SkString(); }
#endif
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrRadialGradientLayout);
#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> GrRadialGradientLayout::TestCreate(GrProcessorTestData* d) {
SkScalar scale = GrGradientShader::RandomParams::kGradientScale;
std::unique_ptr<GrFragmentProcessor> fp;
GrTest::TestAsFPArgs asFPArgs(d);
do {
GrGradientShader::RandomParams params(d->fRandom);
SkPoint center;
center.fX = d->fRandom->nextRangeScalar(0.0f, scale);
center.fY = d->fRandom->nextRangeScalar(0.0f, scale);
SkScalar radius = d->fRandom->nextRangeScalar(0.0f, scale);
sk_sp<SkShader> shader = params.fUseColors4f
? SkGradientShader::MakeRadial(center,
radius,
params.fColors4f,
params.fColorSpace,
params.fStops,
params.fColorCount,
params.fTileMode)
: SkGradientShader::MakeRadial(center,
radius,
params.fColors,
params.fStops,
params.fColorCount,
params.fTileMode);
// Degenerate params can create an Empty (non-null) shader, where fp will be nullptr
fp = shader ? as_SB(shader)->asFragmentProcessor(asFPArgs.args()) : nullptr;
} while (!fp);
return fp;
}
#endif
std::unique_ptr<GrFragmentProcessor> GrRadialGradientLayout::Make(const SkRadialGradient& grad,
const GrFPArgs& args) {
SkMatrix matrix;
if (!grad.totalLocalMatrix(args.fPreLocalMatrix)->invert(&matrix)) {
return nullptr;
}
matrix.postConcat(grad.getGradientMatrix());
return GrMatrixEffect::Make(matrix,
std::unique_ptr<GrFragmentProcessor>(new GrRadialGradientLayout()));
}

View File

@ -1,46 +0,0 @@
/*
* Copyright 2018 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 GrRadialGradientLayout.fp; do not modify.
**************************************************************************************************/
#ifndef GrRadialGradientLayout_DEFINED
#define GrRadialGradientLayout_DEFINED
#include "include/core/SkM44.h"
#include "include/core/SkTypes.h"
#include "src/gpu/effects/GrMatrixEffect.h"
#include "src/gpu/gradients/GrGradientShader.h"
#include "src/shaders/gradients/SkRadialGradient.h"
#include "src/gpu/GrFragmentProcessor.h"
class GrRadialGradientLayout : public GrFragmentProcessor {
public:
static std::unique_ptr<GrFragmentProcessor> Make(const SkRadialGradient& gradient,
const GrFPArgs& args);
GrRadialGradientLayout(const GrRadialGradientLayout& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "RadialGradientLayout"; }
private:
GrRadialGradientLayout()
: INHERITED(kGrRadialGradientLayout_ClassID,
(OptimizationFlags)kPreservesOpaqueInput_OptimizationFlag) {
this->setUsesSampleCoordsDirectly();
}
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

View File

@ -1,93 +0,0 @@
/*
* Copyright 2018 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 GrSingleIntervalGradientColorizer.fp; do not modify.
**************************************************************************************************/
#include "GrSingleIntervalGradientColorizer.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 GrGLSLSingleIntervalGradientColorizer : public GrGLSLFragmentProcessor {
public:
GrGLSLSingleIntervalGradientColorizer() {}
void emitCode(EmitArgs& args) override {
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
const GrSingleIntervalGradientColorizer& _outer =
args.fFp.cast<GrSingleIntervalGradientColorizer>();
(void)_outer;
auto start = _outer.start;
(void)start;
auto end = _outer.end;
(void)end;
startVar = args.fUniformHandler->addUniform(
&_outer, kFragment_GrShaderFlag, kHalf4_GrSLType, "start");
endVar = args.fUniformHandler->addUniform(
&_outer, kFragment_GrShaderFlag, kHalf4_GrSLType, "end");
fragBuilder->codeAppendf(
R"SkSL(return mix(%s, %s, half(%s.x));
)SkSL",
args.fUniformHandler->getUniformCStr(startVar),
args.fUniformHandler->getUniformCStr(endVar),
args.fSampleCoord);
}
private:
void onSetData(const GrGLSLProgramDataManager& pdman,
const GrFragmentProcessor& _proc) override {
const GrSingleIntervalGradientColorizer& _outer =
_proc.cast<GrSingleIntervalGradientColorizer>();
{
pdman.set4fv(startVar, 1, _outer.start.vec());
pdman.set4fv(endVar, 1, _outer.end.vec());
}
}
UniformHandle startVar;
UniformHandle endVar;
};
std::unique_ptr<GrGLSLFragmentProcessor> GrSingleIntervalGradientColorizer::onMakeProgramImpl()
const {
return std::make_unique<GrGLSLSingleIntervalGradientColorizer>();
}
void GrSingleIntervalGradientColorizer::onGetGLSLProcessorKey(const GrShaderCaps& caps,
GrProcessorKeyBuilder* b) const {}
bool GrSingleIntervalGradientColorizer::onIsEqual(const GrFragmentProcessor& other) const {
const GrSingleIntervalGradientColorizer& that = other.cast<GrSingleIntervalGradientColorizer>();
(void)that;
if (start != that.start) return false;
if (end != that.end) return false;
return true;
}
GrSingleIntervalGradientColorizer::GrSingleIntervalGradientColorizer(
const GrSingleIntervalGradientColorizer& src)
: INHERITED(kGrSingleIntervalGradientColorizer_ClassID, src.optimizationFlags())
, start(src.start)
, end(src.end) {
this->cloneAndRegisterAllChildProcessors(src);
this->setUsesSampleCoordsDirectly();
}
std::unique_ptr<GrFragmentProcessor> GrSingleIntervalGradientColorizer::clone() const {
return std::make_unique<GrSingleIntervalGradientColorizer>(*this);
}
#if GR_TEST_UTILS
SkString GrSingleIntervalGradientColorizer::onDumpInfo() const {
return SkStringPrintf("(start=half4(%f, %f, %f, %f), end=half4(%f, %f, %f, %f))",
start.fR,
start.fG,
start.fB,
start.fA,
end.fR,
end.fG,
end.fB,
end.fA);
}
#endif

View File

@ -1,47 +0,0 @@
/*
* Copyright 2018 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 GrSingleIntervalGradientColorizer.fp; do not modify.
**************************************************************************************************/
#ifndef GrSingleIntervalGradientColorizer_DEFINED
#define GrSingleIntervalGradientColorizer_DEFINED
#include "include/core/SkM44.h"
#include "include/core/SkTypes.h"
#include "src/gpu/GrFragmentProcessor.h"
class GrSingleIntervalGradientColorizer : public GrFragmentProcessor {
public:
static std::unique_ptr<GrFragmentProcessor> Make(SkPMColor4f start, SkPMColor4f end) {
return std::unique_ptr<GrFragmentProcessor>(
new GrSingleIntervalGradientColorizer(start, end));
}
GrSingleIntervalGradientColorizer(const GrSingleIntervalGradientColorizer& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "SingleIntervalGradientColorizer"; }
SkPMColor4f start;
SkPMColor4f end;
private:
GrSingleIntervalGradientColorizer(SkPMColor4f start, SkPMColor4f end)
: INHERITED(kGrSingleIntervalGradientColorizer_ClassID, kNone_OptimizationFlags)
, start(start)
, end(end) {
this->setUsesSampleCoordsDirectly();
}
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

View File

@ -1,125 +0,0 @@
/*
* Copyright 2018 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 GrSweepGradientLayout.fp; do not modify.
**************************************************************************************************/
#include "GrSweepGradientLayout.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 GrGLSLSweepGradientLayout : public GrGLSLFragmentProcessor {
public:
GrGLSLSweepGradientLayout() {}
void emitCode(EmitArgs& args) override {
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
const GrSweepGradientLayout& _outer = args.fFp.cast<GrSweepGradientLayout>();
(void)_outer;
auto bias = _outer.bias;
(void)bias;
auto scale = _outer.scale;
(void)scale;
biasVar = args.fUniformHandler->addUniform(
&_outer, kFragment_GrShaderFlag, kHalf_GrSLType, "bias");
scaleVar = args.fUniformHandler->addUniform(
&_outer, kFragment_GrShaderFlag, kHalf_GrSLType, "scale");
fragBuilder->codeAppendf(
R"SkSL(half angle = sk_Caps.atan2ImplementedAsAtanYOverX ? half(2.0 * atan(-%s.y, length(%s) - %s.x)) : half(atan(-%s.y, -%s.x));
half t = ((angle * 0.15915493667125702 + 0.5) + %s) * %s;
return half4(t, 1.0, 0.0, 0.0);
)SkSL",
args.fSampleCoord,
args.fSampleCoord,
args.fSampleCoord,
args.fSampleCoord,
args.fSampleCoord,
args.fUniformHandler->getUniformCStr(biasVar),
args.fUniformHandler->getUniformCStr(scaleVar));
}
private:
void onSetData(const GrGLSLProgramDataManager& pdman,
const GrFragmentProcessor& _proc) override {
const GrSweepGradientLayout& _outer = _proc.cast<GrSweepGradientLayout>();
{
pdman.set1f(biasVar, _outer.bias);
pdman.set1f(scaleVar, _outer.scale);
}
}
UniformHandle biasVar;
UniformHandle scaleVar;
};
std::unique_ptr<GrGLSLFragmentProcessor> GrSweepGradientLayout::onMakeProgramImpl() const {
return std::make_unique<GrGLSLSweepGradientLayout>();
}
void GrSweepGradientLayout::onGetGLSLProcessorKey(const GrShaderCaps& caps,
GrProcessorKeyBuilder* b) const {}
bool GrSweepGradientLayout::onIsEqual(const GrFragmentProcessor& other) const {
const GrSweepGradientLayout& that = other.cast<GrSweepGradientLayout>();
(void)that;
if (bias != that.bias) return false;
if (scale != that.scale) return false;
return true;
}
GrSweepGradientLayout::GrSweepGradientLayout(const GrSweepGradientLayout& src)
: INHERITED(kGrSweepGradientLayout_ClassID, src.optimizationFlags())
, bias(src.bias)
, scale(src.scale) {
this->cloneAndRegisterAllChildProcessors(src);
this->setUsesSampleCoordsDirectly();
}
std::unique_ptr<GrFragmentProcessor> GrSweepGradientLayout::clone() const {
return std::make_unique<GrSweepGradientLayout>(*this);
}
#if GR_TEST_UTILS
SkString GrSweepGradientLayout::onDumpInfo() const {
return SkStringPrintf("(bias=%f, scale=%f)", bias, scale);
}
#endif
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSweepGradientLayout);
#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> GrSweepGradientLayout::TestCreate(GrProcessorTestData* d) {
SkScalar scale = GrGradientShader::RandomParams::kGradientScale;
SkPoint center;
center.fX = d->fRandom->nextRangeScalar(0.0f, scale);
center.fY = d->fRandom->nextRangeScalar(0.0f, scale);
GrGradientShader::RandomParams params(d->fRandom);
auto shader = params.fUseColors4f ? SkGradientShader::MakeSweep(center.fX,
center.fY,
params.fColors4f,
params.fColorSpace,
params.fStops,
params.fColorCount)
: SkGradientShader::MakeSweep(center.fX,
center.fY,
params.fColors,
params.fStops,
params.fColorCount);
GrTest::TestAsFPArgs asFPArgs(d);
std::unique_ptr<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
SkASSERT_RELEASE(fp);
return fp;
}
#endif
std::unique_ptr<GrFragmentProcessor> GrSweepGradientLayout::Make(const SkSweepGradient& grad,
const GrFPArgs& args) {
SkMatrix matrix;
if (!grad.totalLocalMatrix(args.fPreLocalMatrix)->invert(&matrix)) {
return nullptr;
}
matrix.postConcat(grad.getGradientMatrix());
return GrMatrixEffect::Make(matrix,
std::unique_ptr<GrFragmentProcessor>(new GrSweepGradientLayout(
grad.getTBias(), grad.getTScale())));
}

View File

@ -1,50 +0,0 @@
/*
* Copyright 2018 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 GrSweepGradientLayout.fp; do not modify.
**************************************************************************************************/
#ifndef GrSweepGradientLayout_DEFINED
#define GrSweepGradientLayout_DEFINED
#include "include/core/SkM44.h"
#include "include/core/SkTypes.h"
#include "src/gpu/effects/GrMatrixEffect.h"
#include "src/gpu/gradients/GrGradientShader.h"
#include "src/shaders/gradients/SkSweepGradient.h"
#include "src/gpu/GrFragmentProcessor.h"
class GrSweepGradientLayout : public GrFragmentProcessor {
public:
static std::unique_ptr<GrFragmentProcessor> Make(const SkSweepGradient& gradient,
const GrFPArgs& args);
GrSweepGradientLayout(const GrSweepGradientLayout& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "SweepGradientLayout"; }
float bias;
float scale;
private:
GrSweepGradientLayout(float bias, float scale)
: INHERITED(kGrSweepGradientLayout_ClassID,
(OptimizationFlags)kPreservesOpaqueInput_OptimizationFlag)
, bias(bias)
, scale(scale) {
this->setUsesSampleCoordsDirectly();
}
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

View File

@ -1,382 +0,0 @@
/*
* Copyright 2018 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 GrTwoPointConicalGradientLayout.fp; do not modify.
**************************************************************************************************/
#include "GrTwoPointConicalGradientLayout.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 GrGLSLTwoPointConicalGradientLayout : public GrGLSLFragmentProcessor {
public:
GrGLSLTwoPointConicalGradientLayout() {}
void emitCode(EmitArgs& args) override {
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
const GrTwoPointConicalGradientLayout& _outer =
args.fFp.cast<GrTwoPointConicalGradientLayout>();
(void)_outer;
auto type = _outer.type;
(void)type;
auto isRadiusIncreasing = _outer.isRadiusIncreasing;
(void)isRadiusIncreasing;
auto isFocalOnCircle = _outer.isFocalOnCircle;
(void)isFocalOnCircle;
auto isWellBehaved = _outer.isWellBehaved;
(void)isWellBehaved;
auto isSwapped = _outer.isSwapped;
(void)isSwapped;
auto isNativelyFocal = _outer.isNativelyFocal;
(void)isNativelyFocal;
auto focalParams = _outer.focalParams;
(void)focalParams;
focalParamsVar = args.fUniformHandler->addUniform(
&_outer, kFragment_GrShaderFlag, kHalf2_GrSLType, "focalParams");
fragBuilder->codeAppendf(
R"SkSL(float t = -1.0;
half v = 1.0;
@switch (%d) {
case 1:
{
half r0_2 = %s.y;
t = float(r0_2) - %s.y * %s.y;
if (t >= 0.0) {
t = %s.x + sqrt(t);
} else {
v = -1.0;
}
}
break;
case 0:
{
half r0 = %s.x;
@if (%s) {
t = length(%s) - float(r0);
} else {
t = -length(%s) - float(r0);
}
}
break;
case 2:
{
half invR1 = %s.x;
half fx = %s.y;
float x_t = -1.0;
@if (%s) {
x_t = dot(%s, %s) / %s.x;
} else if (%s) {
x_t = length(%s) - %s.x * float(invR1);
} else {
float temp = %s.x * %s.x - %s.y * %s.y;
if (temp >= 0.0) {
@if (%s || !%s) {
x_t = -sqrt(temp) - %s.x * float(invR1);
} else {
x_t = sqrt(temp) - %s.x * float(invR1);
}
}
}
@if (!%s) {
if (x_t <= 0.0) {
v = -1.0;
}
}
@if (%s) {
@if (%s) {
t = x_t;
} else {
t = x_t + float(fx);
}
} else {
@if (%s) {
t = -x_t;
} else {
t = -x_t + float(fx);
}
}
@if (%s) {
t = 1.0 - t;
}
}
break;
}
return half4(half(t), v, 0.0, 0.0);
)SkSL",
(int)_outer.type,
args.fUniformHandler->getUniformCStr(focalParamsVar),
args.fSampleCoord,
args.fSampleCoord,
args.fSampleCoord,
args.fUniformHandler->getUniformCStr(focalParamsVar),
(_outer.isRadiusIncreasing ? "true" : "false"),
args.fSampleCoord,
args.fSampleCoord,
args.fUniformHandler->getUniformCStr(focalParamsVar),
args.fUniformHandler->getUniformCStr(focalParamsVar),
(_outer.isFocalOnCircle ? "true" : "false"),
args.fSampleCoord,
args.fSampleCoord,
args.fSampleCoord,
(_outer.isWellBehaved ? "true" : "false"),
args.fSampleCoord,
args.fSampleCoord,
args.fSampleCoord,
args.fSampleCoord,
args.fSampleCoord,
args.fSampleCoord,
(_outer.isSwapped ? "true" : "false"),
(_outer.isRadiusIncreasing ? "true" : "false"),
args.fSampleCoord,
args.fSampleCoord,
(_outer.isWellBehaved ? "true" : "false"),
(_outer.isRadiusIncreasing ? "true" : "false"),
(_outer.isNativelyFocal ? "true" : "false"),
(_outer.isNativelyFocal ? "true" : "false"),
(_outer.isSwapped ? "true" : "false"));
}
private:
void onSetData(const GrGLSLProgramDataManager& pdman,
const GrFragmentProcessor& _proc) override {
const GrTwoPointConicalGradientLayout& _outer =
_proc.cast<GrTwoPointConicalGradientLayout>();
{ pdman.set2f(focalParamsVar, _outer.focalParams.fX, _outer.focalParams.fY); }
}
UniformHandle focalParamsVar;
};
std::unique_ptr<GrGLSLFragmentProcessor> GrTwoPointConicalGradientLayout::onMakeProgramImpl()
const {
return std::make_unique<GrGLSLTwoPointConicalGradientLayout>();
}
void GrTwoPointConicalGradientLayout::onGetGLSLProcessorKey(const GrShaderCaps& caps,
GrProcessorKeyBuilder* b) const {
b->addBits(2, (uint32_t)type, "type");
b->addBool(isRadiusIncreasing, "isRadiusIncreasing");
b->addBool(isFocalOnCircle, "isFocalOnCircle");
b->addBool(isWellBehaved, "isWellBehaved");
b->addBool(isSwapped, "isSwapped");
b->addBool(isNativelyFocal, "isNativelyFocal");
}
bool GrTwoPointConicalGradientLayout::onIsEqual(const GrFragmentProcessor& other) const {
const GrTwoPointConicalGradientLayout& that = other.cast<GrTwoPointConicalGradientLayout>();
(void)that;
if (type != that.type) return false;
if (isRadiusIncreasing != that.isRadiusIncreasing) return false;
if (isFocalOnCircle != that.isFocalOnCircle) return false;
if (isWellBehaved != that.isWellBehaved) return false;
if (isSwapped != that.isSwapped) return false;
if (isNativelyFocal != that.isNativelyFocal) return false;
if (focalParams != that.focalParams) return false;
return true;
}
GrTwoPointConicalGradientLayout::GrTwoPointConicalGradientLayout(
const GrTwoPointConicalGradientLayout& src)
: INHERITED(kGrTwoPointConicalGradientLayout_ClassID, src.optimizationFlags())
, type(src.type)
, isRadiusIncreasing(src.isRadiusIncreasing)
, isFocalOnCircle(src.isFocalOnCircle)
, isWellBehaved(src.isWellBehaved)
, isSwapped(src.isSwapped)
, isNativelyFocal(src.isNativelyFocal)
, focalParams(src.focalParams) {
this->cloneAndRegisterAllChildProcessors(src);
this->setUsesSampleCoordsDirectly();
}
std::unique_ptr<GrFragmentProcessor> GrTwoPointConicalGradientLayout::clone() const {
return std::make_unique<GrTwoPointConicalGradientLayout>(*this);
}
#if GR_TEST_UTILS
SkString GrTwoPointConicalGradientLayout::onDumpInfo() const {
return SkStringPrintf(
"(type=%d, isRadiusIncreasing=%s, isFocalOnCircle=%s, isWellBehaved=%s, isSwapped=%s, "
"isNativelyFocal=%s, focalParams=half2(%f, %f))",
(int)type,
(isRadiusIncreasing ? "true" : "false"),
(isFocalOnCircle ? "true" : "false"),
(isWellBehaved ? "true" : "false"),
(isSwapped ? "true" : "false"),
(isNativelyFocal ? "true" : "false"),
focalParams.fX,
focalParams.fY);
}
#endif
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrTwoPointConicalGradientLayout);
#if GR_TEST_UTILS
std::unique_ptr<GrFragmentProcessor> GrTwoPointConicalGradientLayout::TestCreate(
GrProcessorTestData* d) {
SkScalar scale = GrGradientShader::RandomParams::kGradientScale;
SkScalar offset = scale / 32.0f;
SkPoint center1, center2;
center1.fX = d->fRandom->nextRangeScalar(0.0f, scale);
center1.fY = d->fRandom->nextRangeScalar(0.0f, scale);
center2.fX = d->fRandom->nextRangeScalar(0.0f, scale);
center2.fY = d->fRandom->nextRangeScalar(0.0f, scale);
SkScalar radius1 = d->fRandom->nextRangeScalar(0.0f, scale);
SkScalar radius2 = d->fRandom->nextRangeScalar(0.0f, scale);
constexpr int kTestTypeMask = (1 << 2) - 1, kTestNativelyFocalBit = (1 << 2),
kTestFocalOnCircleBit = (1 << 3), kTestSwappedBit = (1 << 4);
// We won't treat isWellDefined and isRadiusIncreasing specially because they
// should have high probability to be turned on and off as we're getting random
// radii and centers.
int mask = d->fRandom->nextU();
int type = mask & kTestTypeMask;
if (type == static_cast<int>(Type::kRadial)) {
center2 = center1;
// Make sure that the radii are different
if (SkScalarNearlyZero(radius1 - radius2)) {
radius2 += offset;
}
} else if (type == static_cast<int>(Type::kStrip)) {
radius1 = std::max(radius1, .1f); // Make sure that the radius is non-zero
radius2 = radius1;
// Make sure that the centers are different
if (SkScalarNearlyZero(SkPoint::Distance(center1, center2))) {
center2.fX += offset;
}
} else { // kFocal_Type
// Make sure that the centers are different
if (SkScalarNearlyZero(SkPoint::Distance(center1, center2))) {
center2.fX += offset;
}
if (kTestNativelyFocalBit & mask) {
radius1 = 0;
}
if (kTestFocalOnCircleBit & mask) {
radius2 = radius1 + SkPoint::Distance(center1, center2);
}
if (kTestSwappedBit & mask) {
std::swap(radius1, radius2);
radius2 = 0;
}
// Make sure that the radii are different
if (SkScalarNearlyZero(radius1 - radius2)) {
radius2 += offset;
}
}
if (SkScalarNearlyZero(radius1 - radius2) &&
SkScalarNearlyZero(SkPoint::Distance(center1, center2))) {
radius2 += offset; // make sure that we're not degenerated
}
GrGradientShader::RandomParams params(d->fRandom);
auto shader = params.fUseColors4f ? SkGradientShader::MakeTwoPointConical(center1,
radius1,
center2,
radius2,
params.fColors4f,
params.fColorSpace,
params.fStops,
params.fColorCount,
params.fTileMode)
: SkGradientShader::MakeTwoPointConical(center1,
radius1,
center2,
radius2,
params.fColors,
params.fStops,
params.fColorCount,
params.fTileMode);
GrTest::TestAsFPArgs asFPArgs(d);
std::unique_ptr<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
SkASSERT_RELEASE(fp);
return fp;
}
#endif
// .fp files do not let you reference outside enum definitions, so we have to explicitly map
// between the two compatible enum defs
GrTwoPointConicalGradientLayout::Type convert_type(SkTwoPointConicalGradient::Type type) {
switch (type) {
case SkTwoPointConicalGradient::Type::kRadial:
return GrTwoPointConicalGradientLayout::Type::kRadial;
case SkTwoPointConicalGradient::Type::kStrip:
return GrTwoPointConicalGradientLayout::Type::kStrip;
case SkTwoPointConicalGradient::Type::kFocal:
return GrTwoPointConicalGradientLayout::Type::kFocal;
}
SkDEBUGFAIL("Should not be reachable");
return GrTwoPointConicalGradientLayout::Type::kRadial;
}
std::unique_ptr<GrFragmentProcessor> GrTwoPointConicalGradientLayout::Make(
const SkTwoPointConicalGradient& grad, const GrFPArgs& args) {
GrTwoPointConicalGradientLayout::Type grType = convert_type(grad.getType());
// The focalData struct is only valid if isFocal is true
const SkTwoPointConicalGradient::FocalData& focalData = grad.getFocalData();
bool isFocal = grType == Type::kFocal;
// Calculate optimization switches from gradient specification
bool isFocalOnCircle = isFocal && focalData.isFocalOnCircle();
bool isWellBehaved = isFocal && focalData.isWellBehaved();
bool isSwapped = isFocal && focalData.isSwapped();
bool isNativelyFocal = isFocal && focalData.isNativelyFocal();
// Type-specific calculations: isRadiusIncreasing, focalParams, and the gradient matrix.
// However, all types start with the total inverse local matrix calculated from the shader
// and args
bool isRadiusIncreasing;
SkPoint focalParams; // really just a 2D tuple
SkMatrix matrix;
// Initialize the base matrix
if (!grad.totalLocalMatrix(args.fPreLocalMatrix)->invert(&matrix)) {
return nullptr;
}
if (isFocal) {
isRadiusIncreasing = (1 - focalData.fFocalX) > 0;
focalParams.set(1.0 / focalData.fR1, focalData.fFocalX);
matrix.postConcat(grad.getGradientMatrix());
} else if (grType == Type::kRadial) {
SkScalar dr = grad.getDiffRadius();
isRadiusIncreasing = dr >= 0;
SkScalar r0 = grad.getStartRadius() / dr;
focalParams.set(r0, r0 * r0);
// GPU radial matrix is different from the original matrix, since we map the diff radius
// to have |dr| = 1, so manually compute the final gradient matrix here.
// Map center to (0, 0)
matrix.postTranslate(-grad.getStartCenter().fX, -grad.getStartCenter().fY);
// scale |diffRadius| to 1
matrix.postScale(1 / dr, 1 / dr);
} else { // kStrip
isRadiusIncreasing = false; // kStrip doesn't use this flag
SkScalar r0 = grad.getStartRadius() / grad.getCenterX1();
focalParams.set(r0, r0 * r0);
matrix.postConcat(grad.getGradientMatrix());
}
return GrMatrixEffect::Make(matrix,
std::unique_ptr<GrFragmentProcessor>(
new GrTwoPointConicalGradientLayout(grType,
isRadiusIncreasing,
isFocalOnCircle,
isWellBehaved,
isSwapped,
isNativelyFocal,
focalParams)));
}

View File

@ -1,68 +0,0 @@
/*
* Copyright 2018 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 GrTwoPointConicalGradientLayout.fp; do not modify.
**************************************************************************************************/
#ifndef GrTwoPointConicalGradientLayout_DEFINED
#define GrTwoPointConicalGradientLayout_DEFINED
#include "include/core/SkM44.h"
#include "include/core/SkTypes.h"
#include "src/gpu/effects/GrMatrixEffect.h"
#include "src/gpu/gradients/GrGradientShader.h"
#include "src/shaders/gradients/SkTwoPointConicalGradient.h"
#include "src/gpu/GrFragmentProcessor.h"
class GrTwoPointConicalGradientLayout : public GrFragmentProcessor {
public:
enum class Type { kRadial = 0, kStrip = 1, kFocal = 2 };
static std::unique_ptr<GrFragmentProcessor> Make(const SkTwoPointConicalGradient& gradient,
const GrFPArgs& args);
GrTwoPointConicalGradientLayout(const GrTwoPointConicalGradientLayout& src);
std::unique_ptr<GrFragmentProcessor> clone() const override;
const char* name() const override { return "TwoPointConicalGradientLayout"; }
Type type;
bool isRadiusIncreasing;
bool isFocalOnCircle;
bool isWellBehaved;
bool isSwapped;
bool isNativelyFocal;
SkPoint focalParams;
private:
GrTwoPointConicalGradientLayout(Type type,
bool isRadiusIncreasing,
bool isFocalOnCircle,
bool isWellBehaved,
bool isSwapped,
bool isNativelyFocal,
SkPoint focalParams)
: INHERITED(kGrTwoPointConicalGradientLayout_ClassID,
(OptimizationFlags)kNone_OptimizationFlags)
, type(type)
, isRadiusIncreasing(isRadiusIncreasing)
, isFocalOnCircle(isFocalOnCircle)
, isWellBehaved(isWellBehaved)
, isSwapped(isSwapped)
, isNativelyFocal(isNativelyFocal)
, focalParams(focalParams) {
this->setUsesSampleCoordsDirectly();
}
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