Reland "Replace some gradient .fps with runtime FPs"
This reverts commit16c0791a5a
. Reason for revert: Only errors are AMD+ANGLE+D3D9+ES2 Original change's description: > Revert "Replace some gradient .fps with runtime FPs" > > This reverts commit68d6983acd
. > > 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:
parent
d253088fc2
commit
65b4597d07
12
gn/gpu.gni
12
gn/gpu.gni
@ -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",
|
||||
|
||||
|
@ -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",
|
||||
]
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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));
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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));
|
||||
}
|
@ -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
|
@ -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()));
|
||||
}
|
@ -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
|
@ -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()));
|
||||
}
|
@ -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
|
@ -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
|
@ -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
|
@ -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())));
|
||||
}
|
@ -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
|
@ -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)));
|
||||
}
|
@ -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
|
Loading…
Reference in New Issue
Block a user