converted EllipseEffect to sksl
Bug: skia: Change-Id: Id089b9ead7a21e903b001006dffff2381efd4ba3 Reviewed-on: https://skia-review.googlesource.com/23582 Reviewed-by: Brian Osman <brianosman@google.com> Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
This commit is contained in:
parent
f2c901474c
commit
420f1565e9
@ -316,6 +316,8 @@ skia_gpu_sources = [
|
||||
"$_src/gpu/effects/GrDistanceFieldGeoProc.h",
|
||||
"$_src/gpu/effects/GrDitherEffect.cpp",
|
||||
"$_src/gpu/effects/GrDitherEffect.h",
|
||||
"$_src/gpu/effects/GrEllipseEffect.cpp",
|
||||
"$_src/gpu/effects/GrEllipseEffect.h",
|
||||
"$_src/gpu/effects/GrGaussianConvolutionFragmentProcessor.cpp",
|
||||
"$_src/gpu/effects/GrGaussianConvolutionFragmentProcessor.h",
|
||||
"$_src/gpu/effects/GrMatrixConvolutionEffect.cpp",
|
||||
|
@ -28,5 +28,6 @@ skia_gpu_processor_sources = [
|
||||
"$_src/effects/GrCircleBlurFragmentProcessor.fp",
|
||||
"$_src/gpu/effects/GrCircleEffect.fp",
|
||||
"$_src/gpu/effects/GrDitherEffect.fp",
|
||||
"$_src/gpu/effects/GrEllipseEffect.fp",
|
||||
"$_src/gpu/effects/GrSimpleTextureEffect.fp",
|
||||
]
|
||||
|
110
src/gpu/effects/GrEllipseEffect.cpp
Normal file
110
src/gpu/effects/GrEllipseEffect.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2017 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 GrEllipseEffect.fp; do not modify.
|
||||
*/
|
||||
#include "GrEllipseEffect.h"
|
||||
#if SK_SUPPORT_GPU
|
||||
#include "glsl/GrGLSLColorSpaceXformHelper.h"
|
||||
#include "glsl/GrGLSLFragmentProcessor.h"
|
||||
#include "glsl/GrGLSLFragmentShaderBuilder.h"
|
||||
#include "glsl/GrGLSLProgramBuilder.h"
|
||||
#include "SkSLCPP.h"
|
||||
#include "SkSLUtil.h"
|
||||
class GrGLSLEllipseEffect : public GrGLSLFragmentProcessor {
|
||||
public:
|
||||
GrGLSLEllipseEffect() {}
|
||||
void emitCode(EmitArgs& args) override {
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
const GrEllipseEffect& _outer = args.fFp.cast<GrEllipseEffect>();
|
||||
(void) _outer;
|
||||
prevRadii = vec2(-1.0);
|
||||
useScale = sk_Caps.floatPrecisionVaries;
|
||||
fEllipseVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec4f_GrSLType, kHigh_GrSLPrecision, "ellipse");
|
||||
if (useScale) {
|
||||
fScaleVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kVec2f_GrSLType, kDefault_GrSLPrecision, "scale");
|
||||
}
|
||||
fragBuilder->codeAppendf("vec2 prevCenter;\nvec2 prevRadii = vec2(%f, %f);\nbool useScale = %s;\nvec2 d = sk_FragCoord.xy - %s.xy;\n@if (useScale) {\n d *= %s.y;\n}\nvec2 Z = d * %s.zw;\nfloat implicit = dot(Z, d) - 1.0;\nfloat grad_dot = 4.0 * dot(Z, Z);\ngrad_dot = max(grad_dot, 0.0001);\nfloat approx_dist = implicit * inversesqrt(grad_dot);\n@if (useScale) {\n approx_dist *= %s.x;\n}\nfloat alpha;\n@switch (%d) {\n case 0:\n alpha = approx_dist > 0.0 ? 0.0 : 1.0;\n break;\n case 1:\n alpha = clamp(0.5 - approx_dist, 0.0, 1.0);\n break;\n case 2:\n alpha = approx_dist > 0.0 ? 1.0 : 0.0;\n break;\n case 3:\n alpha = clamp(0.5 + approx_dist, 0.0, 1.0);\n break;\n default:\n discard;\n}\n%s = %s * alpha;\n", prevRadii.fX, prevRadii.fY, (useScale ? "true" : "false"), args.fUniformHandler->getUniformCStr(fEllipseVar), fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) : "vec2(0.0)", args.fUniformHandler->getUniformCStr(fEllipseVar), fScaleVar.isValid() ? args.fUniformHandler->getUniformCStr(fScaleVar) : "vec2(0.0)", _outer.edgeType(), args.fOutputColor, args.fInputColor ? args.fInputColor : "vec4(1)");
|
||||
}
|
||||
private:
|
||||
void onSetData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& _proc) override {
|
||||
const GrEllipseEffect& _outer = _proc.cast<GrEllipseEffect>();
|
||||
auto edgeType = _outer.edgeType();
|
||||
(void) edgeType;
|
||||
auto center = _outer.center();
|
||||
(void) center;
|
||||
auto radii = _outer.radii();
|
||||
(void) radii;
|
||||
UniformHandle& ellipse = fEllipseVar;
|
||||
(void) ellipse;
|
||||
UniformHandle& scale = fScaleVar;
|
||||
(void) scale;
|
||||
|
||||
if (radii != prevRadii || center != prevCenter) {
|
||||
float invRXSqd;
|
||||
float invRYSqd;
|
||||
|
||||
|
||||
if (scale.isValid()) {
|
||||
if (radii.fX > radii.fY) {
|
||||
invRXSqd = 1.f;
|
||||
invRYSqd = (radii.fX * radii.fX) /
|
||||
(radii.fY * radii.fY);
|
||||
pdman.set2f(scale, radii.fX, 1.f / radii.fX);
|
||||
} else {
|
||||
invRXSqd = (radii.fY * radii.fY) /
|
||||
(radii.fX * radii.fX);
|
||||
invRYSqd = 1.f;
|
||||
pdman.set2f(scale, radii.fY, 1.f / radii.fY);
|
||||
}
|
||||
} else {
|
||||
invRXSqd = 1.f / (radii.fX * radii.fX);
|
||||
invRYSqd = 1.f / (radii.fY * radii.fY);
|
||||
}
|
||||
pdman.set4f(ellipse, center.fX, center.fY, invRXSqd, invRYSqd);
|
||||
prevCenter = center;
|
||||
prevRadii = radii;
|
||||
}
|
||||
}
|
||||
SkPoint prevCenter;
|
||||
SkPoint prevRadii;
|
||||
bool useScale;
|
||||
UniformHandle fEllipseVar;
|
||||
UniformHandle fScaleVar;
|
||||
};
|
||||
GrGLSLFragmentProcessor* GrEllipseEffect::onCreateGLSLInstance() const {
|
||||
return new GrGLSLEllipseEffect();
|
||||
}
|
||||
void GrEllipseEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const {
|
||||
b->add32(fEdgeType);
|
||||
}
|
||||
bool GrEllipseEffect::onIsEqual(const GrFragmentProcessor& other) const {
|
||||
const GrEllipseEffect& that = other.cast<GrEllipseEffect>();
|
||||
(void) that;
|
||||
if (fEdgeType != that.fEdgeType) return false;
|
||||
if (fCenter != that.fCenter) return false;
|
||||
if (fRadii != that.fRadii) return false;
|
||||
return true;
|
||||
}
|
||||
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrEllipseEffect);
|
||||
#if GR_TEST_UTILS
|
||||
sk_sp<GrFragmentProcessor> GrEllipseEffect::TestCreate(GrProcessorTestData* testData) {
|
||||
|
||||
SkPoint center;
|
||||
center.fX = testData->fRandom->nextRangeScalar(0.f, 1000.f);
|
||||
center.fY = testData->fRandom->nextRangeScalar(0.f, 1000.f);
|
||||
SkScalar rx = testData->fRandom->nextRangeF(0.f, 1000.f);
|
||||
SkScalar ry = testData->fRandom->nextRangeF(0.f, 1000.f);
|
||||
GrPrimitiveEdgeType et;
|
||||
do {
|
||||
et = (GrPrimitiveEdgeType) testData->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt);
|
||||
} while (kHairlineAA_GrProcessorEdgeType == et);
|
||||
return GrEllipseEffect::Make(et, center, SkPoint::Make(rx, ry));
|
||||
}
|
||||
#endif
|
||||
#endif
|
105
src/gpu/effects/GrEllipseEffect.fp
Normal file
105
src/gpu/effects/GrEllipseEffect.fp
Normal file
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 2017 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
layout(key) in int edgeType;
|
||||
in vec2 center;
|
||||
in vec2 radii;
|
||||
|
||||
vec2 prevCenter;
|
||||
vec2 prevRadii = vec2(-1);
|
||||
// The ellipse uniform is (center.x, center.y, 1 / rx^2, 1 / ry^2)
|
||||
// The last two terms can underflow on mediump, so we use highp.
|
||||
uniform highp vec4 ellipse;
|
||||
|
||||
bool useScale = sk_Caps.floatPrecisionVaries;
|
||||
layout(when=useScale) uniform vec2 scale;
|
||||
|
||||
@optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag }
|
||||
|
||||
@setData(pdman) {
|
||||
if (radii != prevRadii || center != prevCenter) {
|
||||
float invRXSqd;
|
||||
float invRYSqd;
|
||||
// If we're using a scale factor to work around precision issues, choose the larger radius
|
||||
// as the scale factor. The inv radii need to be pre-adjusted by the scale factor.
|
||||
if (scale.isValid()) {
|
||||
if (radii.fX > radii.fY) {
|
||||
invRXSqd = 1.f;
|
||||
invRYSqd = (radii.fX * radii.fX) /
|
||||
(radii.fY * radii.fY);
|
||||
pdman.set2f(scale, radii.fX, 1.f / radii.fX);
|
||||
} else {
|
||||
invRXSqd = (radii.fY * radii.fY) /
|
||||
(radii.fX * radii.fX);
|
||||
invRYSqd = 1.f;
|
||||
pdman.set2f(scale, radii.fY, 1.f / radii.fY);
|
||||
}
|
||||
} else {
|
||||
invRXSqd = 1.f / (radii.fX * radii.fX);
|
||||
invRYSqd = 1.f / (radii.fY * radii.fY);
|
||||
}
|
||||
pdman.set4f(ellipse, center.fX, center.fY, invRXSqd, invRYSqd);
|
||||
prevCenter = center;
|
||||
prevRadii = radii;
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
// d is the offset to the ellipse center
|
||||
vec2 d = sk_FragCoord.xy - ellipse.xy;
|
||||
// If we're on a device with a "real" mediump then we'll do the distance computation in a space
|
||||
// that is normalized by the larger radius. The scale uniform will be scale, 1/scale. The
|
||||
// inverse squared radii uniform values are already in this normalized space. The center is
|
||||
// not.
|
||||
@if (useScale) {
|
||||
d *= scale.y;
|
||||
}
|
||||
vec2 Z = d * ellipse.zw;
|
||||
// implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1.
|
||||
float implicit = dot(Z, d) - 1;
|
||||
// grad_dot is the squared length of the gradient of the implicit.
|
||||
float grad_dot = 4 * dot(Z, Z);
|
||||
// Avoid calling inversesqrt on zero.
|
||||
grad_dot = max(grad_dot, 1e-4);
|
||||
float approx_dist = implicit * inversesqrt(grad_dot);
|
||||
@if (useScale) {
|
||||
approx_dist *= scale.x;
|
||||
}
|
||||
|
||||
float alpha;
|
||||
@switch (edgeType) {
|
||||
case 0 /* kFillBW_GrProcessorEdgeType */:
|
||||
alpha = approx_dist > 0.0 ? 0.0 : 1.0;
|
||||
break;
|
||||
case 1 /* kFillAA_GrProcessorEdgeType */:
|
||||
alpha = clamp(0.5 - approx_dist, 0.0, 1.0);
|
||||
break;
|
||||
case 2 /* kInverseFillBW_GrProcessorEdgeType */:
|
||||
alpha = approx_dist > 0.0 ? 1.0 : 0.0;
|
||||
break;
|
||||
case 3 /* kInverseFillAA_GrProcessorEdgeType */:
|
||||
alpha = clamp(0.5 + approx_dist, 0.0, 1.0);
|
||||
break;
|
||||
default:
|
||||
// hairline not supported
|
||||
discard;
|
||||
}
|
||||
sk_OutColor = sk_InColor * alpha;
|
||||
}
|
||||
|
||||
@test(testData) {
|
||||
SkPoint center;
|
||||
center.fX = testData->fRandom->nextRangeScalar(0.f, 1000.f);
|
||||
center.fY = testData->fRandom->nextRangeScalar(0.f, 1000.f);
|
||||
SkScalar rx = testData->fRandom->nextRangeF(0.f, 1000.f);
|
||||
SkScalar ry = testData->fRandom->nextRangeF(0.f, 1000.f);
|
||||
GrPrimitiveEdgeType et;
|
||||
do {
|
||||
et = (GrPrimitiveEdgeType) testData->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt);
|
||||
} while (kHairlineAA_GrProcessorEdgeType == et);
|
||||
return GrEllipseEffect::Make(et, center, SkPoint::Make(rx, ry));
|
||||
}
|
46
src/gpu/effects/GrEllipseEffect.h
Normal file
46
src/gpu/effects/GrEllipseEffect.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2017 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 GrEllipseEffect.fp; do not modify.
|
||||
*/
|
||||
#ifndef GrEllipseEffect_DEFINED
|
||||
#define GrEllipseEffect_DEFINED
|
||||
#include "SkTypes.h"
|
||||
#if SK_SUPPORT_GPU
|
||||
#include "GrFragmentProcessor.h"
|
||||
#include "GrCoordTransform.h"
|
||||
#include "GrColorSpaceXform.h"
|
||||
#include "effects/GrProxyMove.h"
|
||||
class GrEllipseEffect : public GrFragmentProcessor {
|
||||
public:
|
||||
int edgeType() const { return fEdgeType; }
|
||||
SkPoint center() const { return fCenter; }
|
||||
SkPoint radii() const { return fRadii; }
|
||||
static sk_sp<GrFragmentProcessor> Make(int edgeType, SkPoint center, SkPoint radii) {
|
||||
return sk_sp<GrFragmentProcessor>(new GrEllipseEffect(edgeType, center, radii));
|
||||
}
|
||||
const char* name() const override { return "EllipseEffect"; }
|
||||
private:
|
||||
GrEllipseEffect(int edgeType, SkPoint center, SkPoint radii)
|
||||
: INHERITED((OptimizationFlags) kCompatibleWithCoverageAsAlpha_OptimizationFlag )
|
||||
, fEdgeType(edgeType)
|
||||
, fCenter(center)
|
||||
, fRadii(radii) {
|
||||
this->initClassID<GrEllipseEffect>();
|
||||
}
|
||||
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
|
||||
void onGetGLSLProcessorKey(const GrShaderCaps&,GrProcessorKeyBuilder*) const override;
|
||||
bool onIsEqual(const GrFragmentProcessor&) const override;
|
||||
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
|
||||
int fEdgeType;
|
||||
SkPoint fCenter;
|
||||
SkPoint fRadii;
|
||||
typedef GrFragmentProcessor INHERITED;
|
||||
};
|
||||
#endif
|
||||
#endif
|
@ -8,221 +8,8 @@
|
||||
#include "GrOvalEffect.h"
|
||||
|
||||
#include "GrCircleEffect.h"
|
||||
#include "GrFragmentProcessor.h"
|
||||
#include "GrEllipseEffect.h"
|
||||
#include "SkRect.h"
|
||||
#include "GrShaderCaps.h"
|
||||
#include "glsl/GrGLSLFragmentProcessor.h"
|
||||
#include "glsl/GrGLSLFragmentShaderBuilder.h"
|
||||
#include "glsl/GrGLSLProgramDataManager.h"
|
||||
#include "glsl/GrGLSLUniformHandler.h"
|
||||
#include "../private/GrGLSL.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class EllipseEffect : public GrFragmentProcessor {
|
||||
public:
|
||||
static sk_sp<GrFragmentProcessor> Make(GrPrimitiveEdgeType, const SkPoint& center,
|
||||
SkScalar rx, SkScalar ry);
|
||||
|
||||
~EllipseEffect() override {}
|
||||
|
||||
const char* name() const override { return "Ellipse"; }
|
||||
|
||||
const SkPoint& getCenter() const { return fCenter; }
|
||||
SkVector getRadii() const { return fRadii; }
|
||||
|
||||
GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
|
||||
|
||||
private:
|
||||
EllipseEffect(GrPrimitiveEdgeType, const SkPoint& center, SkScalar rx, SkScalar ry);
|
||||
|
||||
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
|
||||
|
||||
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
|
||||
|
||||
bool onIsEqual(const GrFragmentProcessor&) const override;
|
||||
|
||||
SkPoint fCenter;
|
||||
SkVector fRadii;
|
||||
GrPrimitiveEdgeType fEdgeType;
|
||||
|
||||
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
|
||||
|
||||
typedef GrFragmentProcessor INHERITED;
|
||||
};
|
||||
|
||||
sk_sp<GrFragmentProcessor> EllipseEffect::Make(GrPrimitiveEdgeType edgeType,
|
||||
const SkPoint& center,
|
||||
SkScalar rx,
|
||||
SkScalar ry) {
|
||||
SkASSERT(rx >= 0 && ry >= 0);
|
||||
return sk_sp<GrFragmentProcessor>(new EllipseEffect(edgeType, center, rx, ry));
|
||||
}
|
||||
|
||||
EllipseEffect::EllipseEffect(GrPrimitiveEdgeType edgeType, const SkPoint& c, SkScalar rx,
|
||||
SkScalar ry)
|
||||
: INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
|
||||
, fCenter(c)
|
||||
, fRadii(SkVector::Make(rx, ry))
|
||||
, fEdgeType(edgeType) {
|
||||
this->initClassID<EllipseEffect>();
|
||||
}
|
||||
|
||||
bool EllipseEffect::onIsEqual(const GrFragmentProcessor& other) const {
|
||||
const EllipseEffect& ee = other.cast<EllipseEffect>();
|
||||
return fEdgeType == ee.fEdgeType && fCenter == ee.fCenter && fRadii == ee.fRadii;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GR_DEFINE_FRAGMENT_PROCESSOR_TEST(EllipseEffect);
|
||||
|
||||
#if GR_TEST_UTILS
|
||||
sk_sp<GrFragmentProcessor> EllipseEffect::TestCreate(GrProcessorTestData* d) {
|
||||
SkPoint center;
|
||||
center.fX = d->fRandom->nextRangeScalar(0.f, 1000.f);
|
||||
center.fY = d->fRandom->nextRangeScalar(0.f, 1000.f);
|
||||
SkScalar rx = d->fRandom->nextRangeF(0.f, 1000.f);
|
||||
SkScalar ry = d->fRandom->nextRangeF(0.f, 1000.f);
|
||||
GrPrimitiveEdgeType et;
|
||||
do {
|
||||
et = (GrPrimitiveEdgeType)d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt);
|
||||
} while (kHairlineAA_GrProcessorEdgeType == et);
|
||||
return EllipseEffect::Make(et, center, rx, ry);
|
||||
}
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class GLEllipseEffect : public GrGLSLFragmentProcessor {
|
||||
public:
|
||||
GLEllipseEffect() {
|
||||
fPrevRadii.fX = -1.0f;
|
||||
}
|
||||
|
||||
void emitCode(EmitArgs&) override;
|
||||
|
||||
static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
|
||||
|
||||
protected:
|
||||
void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
|
||||
|
||||
private:
|
||||
GrGLSLProgramDataManager::UniformHandle fEllipseUniform;
|
||||
GrGLSLProgramDataManager::UniformHandle fScaleUniform;
|
||||
SkPoint fPrevCenter;
|
||||
SkVector fPrevRadii;
|
||||
|
||||
typedef GrGLSLFragmentProcessor INHERITED;
|
||||
};
|
||||
|
||||
void GLEllipseEffect::emitCode(EmitArgs& args) {
|
||||
const EllipseEffect& ee = args.fFp.cast<EllipseEffect>();
|
||||
const char *ellipseName;
|
||||
// The ellipse uniform is (center.x, center.y, 1 / rx^2, 1 / ry^2)
|
||||
// The last two terms can underflow on mediump, so we use highp.
|
||||
fEllipseUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
|
||||
kVec4f_GrSLType, kHigh_GrSLPrecision,
|
||||
"ellipse",
|
||||
&ellipseName);
|
||||
// If we're on a device with a "real" mediump then we'll do the distance computation in a space
|
||||
// that is normalized by the larger radius. The scale uniform will be scale, 1/scale. The
|
||||
// inverse squared radii uniform values are already in this normalized space. The center is
|
||||
// not.
|
||||
const char* scaleName = nullptr;
|
||||
if (args.fShaderCaps->floatPrecisionVaries()) {
|
||||
fScaleUniform = args.fUniformHandler->addUniform(
|
||||
kFragment_GrShaderFlag, kVec2f_GrSLType, kDefault_GrSLPrecision,
|
||||
"scale", &scaleName);
|
||||
}
|
||||
|
||||
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
|
||||
|
||||
// d is the offset to the ellipse center
|
||||
fragBuilder->codeAppendf("vec2 d = sk_FragCoord.xy - %s.xy;", ellipseName);
|
||||
if (scaleName) {
|
||||
fragBuilder->codeAppendf("d *= %s.y;", scaleName);
|
||||
}
|
||||
fragBuilder->codeAppendf("vec2 Z = d * %s.zw;", ellipseName);
|
||||
// implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1.
|
||||
fragBuilder->codeAppend("float implicit = dot(Z, d) - 1.0;");
|
||||
// grad_dot is the squared length of the gradient of the implicit.
|
||||
fragBuilder->codeAppendf("float grad_dot = 4.0 * dot(Z, Z);");
|
||||
// Avoid calling inversesqrt on zero.
|
||||
fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);");
|
||||
fragBuilder->codeAppendf("float approx_dist = implicit * inversesqrt(grad_dot);");
|
||||
if (scaleName) {
|
||||
fragBuilder->codeAppendf("approx_dist *= %s.x;", scaleName);
|
||||
}
|
||||
|
||||
switch (ee.getEdgeType()) {
|
||||
case kFillAA_GrProcessorEdgeType:
|
||||
fragBuilder->codeAppend("float alpha = clamp(0.5 - approx_dist, 0.0, 1.0);");
|
||||
break;
|
||||
case kInverseFillAA_GrProcessorEdgeType:
|
||||
fragBuilder->codeAppend("float alpha = clamp(0.5 + approx_dist, 0.0, 1.0);");
|
||||
break;
|
||||
case kFillBW_GrProcessorEdgeType:
|
||||
fragBuilder->codeAppend("float alpha = approx_dist > 0.0 ? 0.0 : 1.0;");
|
||||
break;
|
||||
case kInverseFillBW_GrProcessorEdgeType:
|
||||
fragBuilder->codeAppend("float alpha = approx_dist > 0.0 ? 1.0 : 0.0;");
|
||||
break;
|
||||
case kHairlineAA_GrProcessorEdgeType:
|
||||
SkFAIL("Hairline not expected here.");
|
||||
}
|
||||
|
||||
fragBuilder->codeAppendf("%s = %s * alpha;", args.fOutputColor, args.fInputColor);
|
||||
}
|
||||
|
||||
void GLEllipseEffect::GenKey(const GrProcessor& effect, const GrShaderCaps&,
|
||||
GrProcessorKeyBuilder* b) {
|
||||
const EllipseEffect& ee = effect.cast<EllipseEffect>();
|
||||
b->add32(ee.getEdgeType());
|
||||
}
|
||||
|
||||
void GLEllipseEffect::onSetData(const GrGLSLProgramDataManager& pdman,
|
||||
const GrFragmentProcessor& effect) {
|
||||
const EllipseEffect& ee = effect.cast<EllipseEffect>();
|
||||
if (ee.getRadii() != fPrevRadii || ee.getCenter() != fPrevCenter) {
|
||||
float invRXSqd;
|
||||
float invRYSqd;
|
||||
// If we're using a scale factor to work around precision issues, choose the larger radius
|
||||
// as the scale factor. The inv radii need to be pre-adjusted by the scale factor.
|
||||
if (fScaleUniform.isValid()) {
|
||||
if (ee.getRadii().fX > ee.getRadii().fY) {
|
||||
invRXSqd = 1.f;
|
||||
invRYSqd = (ee.getRadii().fX * ee.getRadii().fX) /
|
||||
(ee.getRadii().fY * ee.getRadii().fY);
|
||||
pdman.set2f(fScaleUniform, ee.getRadii().fX, 1.f / ee.getRadii().fX);
|
||||
} else {
|
||||
invRXSqd = (ee.getRadii().fY * ee.getRadii().fY) /
|
||||
(ee.getRadii().fX * ee.getRadii().fX);
|
||||
invRYSqd = 1.f;
|
||||
pdman.set2f(fScaleUniform, ee.getRadii().fY, 1.f / ee.getRadii().fY);
|
||||
}
|
||||
} else {
|
||||
invRXSqd = 1.f / (ee.getRadii().fX * ee.getRadii().fX);
|
||||
invRYSqd = 1.f / (ee.getRadii().fY * ee.getRadii().fY);
|
||||
}
|
||||
pdman.set4f(fEllipseUniform, ee.getCenter().fX, ee.getCenter().fY, invRXSqd, invRYSqd);
|
||||
fPrevCenter = ee.getCenter();
|
||||
fPrevRadii = ee.getRadii();
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void EllipseEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
|
||||
GrProcessorKeyBuilder* b) const {
|
||||
GLEllipseEffect::GenKey(*this, caps, b);
|
||||
}
|
||||
|
||||
GrGLSLFragmentProcessor* EllipseEffect::onCreateGLSLInstance() const {
|
||||
return new GLEllipseEffect;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
sk_sp<GrFragmentProcessor> GrOvalEffect::Make(GrPrimitiveEdgeType edgeType, const SkRect& oval) {
|
||||
if (kHairlineAA_GrProcessorEdgeType == edgeType) {
|
||||
@ -236,7 +23,8 @@ sk_sp<GrFragmentProcessor> GrOvalEffect::Make(GrPrimitiveEdgeType edgeType, cons
|
||||
} else {
|
||||
w /= 2;
|
||||
h /= 2;
|
||||
return EllipseEffect::Make(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + h), w, h);
|
||||
return GrEllipseEffect::Make(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + h),
|
||||
SkPoint::Make(w, h));
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
Loading…
Reference in New Issue
Block a user