blob: 2736629a2e99d973b9238a63a7c9ad19c62afd33 [file] [log] [blame]
/*
* 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)));
}