aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/shaders/gradients
diff options
context:
space:
mode:
Diffstat (limited to 'src/shaders/gradients')
-rw-r--r--src/shaders/gradients/SkGradientShader.cpp72
-rw-r--r--src/shaders/gradients/SkGradientShaderPriv.h13
-rw-r--r--src/shaders/gradients/SkTwoPointConicalGradient.cpp88
-rw-r--r--src/shaders/gradients/SkTwoPointConicalGradient.h7
-rw-r--r--src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp181
5 files changed, 127 insertions, 234 deletions
diff --git a/src/shaders/gradients/SkGradientShader.cpp b/src/shaders/gradients/SkGradientShader.cpp
index 8eefc81cb6..2925ce14c2 100644
--- a/src/shaders/gradients/SkGradientShader.cpp
+++ b/src/shaders/gradients/SkGradientShader.cpp
@@ -288,26 +288,6 @@ void SkGradientShaderBase::flatten(SkWriteBuffer& buffer) const {
desc.flatten(buffer);
}
-void SkGradientShaderBase::FlipGradientColors(SkColor* colorDst, Rec* recDst,
- SkColor* colorSrc, Rec* recSrc,
- int count) {
- SkAutoSTArray<8, SkColor> colorsTemp(count);
- for (int i = 0; i < count; ++i) {
- int offset = count - i - 1;
- colorsTemp[i] = colorSrc[offset];
- }
- if (count > 2) {
- SkAutoSTArray<8, Rec> recsTemp(count);
- for (int i = 0; i < count; ++i) {
- int offset = count - i - 1;
- recsTemp[i].fPos = SK_Fixed1 - recSrc[offset].fPos;
- recsTemp[i].fScale = recSrc[offset].fScale;
- }
- memcpy(recDst, recsTemp.get(), count * sizeof(Rec));
- }
- memcpy(colorDst, colorsTemp.get(), count * sizeof(SkColor));
-}
-
static void add_stop_color(SkJumper_GradientCtx* ctx, size_t stop, SkPM4f Fs, SkPM4f Bs) {
(ctx->fs[0])[stop] = Fs.r();
(ctx->fs[1])[stop] = Fs.g();
@@ -903,25 +883,11 @@ void SkGradientShaderBase::getGradientTableBitmap(SkBitmap* bitmap,
}
}
-void SkGradientShaderBase::commonAsAGradient(GradientInfo* info, bool flipGrad) const {
+void SkGradientShaderBase::commonAsAGradient(GradientInfo* info) const {
if (info) {
if (info->fColorCount >= fColorCount) {
- SkColor* colorLoc;
- Rec* recLoc;
- SkAutoSTArray<8, SkColor> colorStorage;
- SkAutoSTArray<8, Rec> recStorage;
- if (flipGrad && (info->fColors || info->fColorOffsets)) {
- colorStorage.reset(fColorCount);
- recStorage.reset(fColorCount);
- colorLoc = colorStorage.get();
- recLoc = recStorage.get();
- FlipGradientColors(colorLoc, recLoc, fOrigColors, fRecs, fColorCount);
- } else {
- colorLoc = fOrigColors;
- recLoc = fRecs;
- }
if (info->fColors) {
- memcpy(info->fColors, colorLoc, fColorCount * sizeof(SkColor));
+ memcpy(info->fColors, fOrigColors, fColorCount * sizeof(SkColor));
}
if (info->fColorOffsets) {
if (fColorCount == 2) {
@@ -929,7 +895,7 @@ void SkGradientShaderBase::commonAsAGradient(GradientInfo* info, bool flipGrad)
info->fColorOffsets[1] = SK_Scalar1;
} else if (fColorCount > 2) {
for (int i = 0; i < fColorCount; ++i) {
- info->fColorOffsets[i] = SkFixedToScalar(recLoc[i].fPos);
+ info->fColorOffsets[i] = SkFixedToScalar(fRecs[i].fPos);
}
}
}
@@ -1191,36 +1157,10 @@ sk_sp<SkShader> SkGradientShader::MakeTwoPointConical(const SkPoint& start,
ColorStopOptimizer opt(colors, pos, colorCount, mode);
- bool flipGradient = startRadius > endRadius;
-
SkGradientShaderBase::Descriptor desc;
-
- if (!flipGradient) {
- desc_init(&desc, opt.fColors, std::move(colorSpace), opt.fPos, opt.fCount, mode, flags,
- localMatrix);
- return SkTwoPointConicalGradient::Create(start, startRadius, end, endRadius, flipGradient,
- desc);
- } else {
- SkAutoSTArray<8, SkColor4f> colorsNew(opt.fCount);
- SkAutoSTArray<8, SkScalar> posNew(opt.fCount);
- for (int i = 0; i < opt.fCount; ++i) {
- colorsNew[i] = opt.fColors[opt.fCount - i - 1];
- }
-
- if (pos) {
- for (int i = 0; i < opt.fCount; ++i) {
- posNew[i] = 1 - opt.fPos[opt.fCount - i - 1];
- }
- desc_init(&desc, colorsNew.get(), std::move(colorSpace), posNew.get(), opt.fCount, mode,
- flags, localMatrix);
- } else {
- desc_init(&desc, colorsNew.get(), std::move(colorSpace), nullptr, opt.fCount, mode,
- flags, localMatrix);
- }
-
- return SkTwoPointConicalGradient::Create(end, endRadius, start, startRadius, flipGradient,
- desc);
- }
+ desc_init(&desc, opt.fColors, std::move(colorSpace), opt.fPos, opt.fCount, mode, flags,
+ localMatrix);
+ return SkTwoPointConicalGradient::Create(start, startRadius, end, endRadius, desc);
}
sk_sp<SkShader> SkGradientShader::MakeSweep(SkScalar cx, SkScalar cy,
diff --git a/src/shaders/gradients/SkGradientShaderPriv.h b/src/shaders/gradients/SkGradientShaderPriv.h
index 30e9440816..0abfd35e99 100644
--- a/src/shaders/gradients/SkGradientShaderPriv.h
+++ b/src/shaders/gradients/SkGradientShaderPriv.h
@@ -212,23 +212,12 @@ protected:
void flatten(SkWriteBuffer&) const override;
SK_TO_STRING_OVERRIDE()
- void commonAsAGradient(GradientInfo*, bool flipGrad = false) const;
+ void commonAsAGradient(GradientInfo*) const;
bool onAsLuminanceColor(SkColor*) const override;
void initLinearBitmap(SkBitmap* bitmap) const;
- /*
- * Takes in pointers to gradient color and Rec info as colorSrc and recSrc respectively.
- * Count is the number of colors in the gradient
- * It will then flip all the color and rec information and return in their respective Dst
- * pointers. It is assumed that space has already been allocated for the Dst pointers.
- * The rec src and dst are only assumed to be valid if count > 2
- */
- static void FlipGradientColors(SkColor* colorDst, Rec* recDst,
- SkColor* colorSrc, Rec* recSrc,
- int count);
-
bool onAppendStages(const StageRec&) const override;
virtual void appendGradientStages(SkArenaAlloc* alloc, SkRasterPipeline* tPipeline,
diff --git a/src/shaders/gradients/SkTwoPointConicalGradient.cpp b/src/shaders/gradients/SkTwoPointConicalGradient.cpp
index a1634727a9..04448b45a1 100644
--- a/src/shaders/gradients/SkTwoPointConicalGradient.cpp
+++ b/src/shaders/gradients/SkTwoPointConicalGradient.cpp
@@ -12,14 +12,15 @@
sk_sp<SkShader> SkTwoPointConicalGradient::Create(const SkPoint& c0, SkScalar r0,
const SkPoint& c1, SkScalar r1,
- bool flipped, const Descriptor& desc) {
+ const Descriptor& desc) {
SkMatrix gradientMatrix;
Type gradientType;
if (SkScalarNearlyZero((c0 - c1).length())) {
// Concentric case: we can pretend we're radial (with a tiny twist).
+ const SkScalar scale = 1.0f / SkTMax(r0, r1);
gradientMatrix = SkMatrix::MakeTrans(-c1.x(), -c1.y());
- gradientMatrix.postScale(1 / r1, 1 / r1);
+ gradientMatrix.postScale(scale, scale);
gradientType = Type::kRadial;
} else {
@@ -35,21 +36,19 @@ sk_sp<SkShader> SkTwoPointConicalGradient::Create(const SkPoint& c0, SkScalar r0
gradientType = Type::kTwoPoint;
}
- return sk_sp<SkShader>(new SkTwoPointConicalGradient(c0, r0, c1, r1, flipped, desc,
+ return sk_sp<SkShader>(new SkTwoPointConicalGradient(c0, r0, c1, r1, desc,
gradientType, gradientMatrix));
}
SkTwoPointConicalGradient::SkTwoPointConicalGradient(
const SkPoint& start, SkScalar startRadius,
const SkPoint& end, SkScalar endRadius,
- bool flippedGrad, const Descriptor& desc,
- Type type, const SkMatrix& gradientMatrix)
+ const Descriptor& desc, Type type, const SkMatrix& gradientMatrix)
: SkGradientShaderBase(desc, gradientMatrix)
, fCenter1(start)
, fCenter2(end)
, fRadius1(startRadius)
, fRadius2(endRadius)
- , fFlippedGrad(flippedGrad)
, fType(type)
{
// this is degenerate, and should be caught by our caller
@@ -64,18 +63,13 @@ bool SkTwoPointConicalGradient::isOpaque() const {
}
// Returns the original non-sorted version of the gradient
-SkShader::GradientType SkTwoPointConicalGradient::asAGradient(
- GradientInfo* info) const {
+SkShader::GradientType SkTwoPointConicalGradient::asAGradient(GradientInfo* info) const {
if (info) {
- commonAsAGradient(info, fFlippedGrad);
+ commonAsAGradient(info);
info->fPoint[0] = fCenter1;
info->fPoint[1] = fCenter2;
info->fRadius[0] = fRadius1;
info->fRadius[1] = fRadius2;
- if (fFlippedGrad) {
- SkTSwap(info->fPoint[0], info->fPoint[1]);
- SkTSwap(info->fRadius[0], info->fRadius[1]);
- }
}
return kConical_GradientType;
}
@@ -90,7 +84,8 @@ sk_sp<SkFlattenable> SkTwoPointConicalGradient::CreateProc(SkReadBuffer& buffer)
SkScalar r1 = buffer.readScalar();
SkScalar r2 = buffer.readScalar();
- if (buffer.readBool()) { // flipped
+ if (buffer.isVersionLT(SkReadBuffer::k2PtConicalNoFlip_Version) && buffer.readBool()) {
+ // legacy flipped gradient
SkTSwap(c1, c2);
SkTSwap(r1, r2);
@@ -125,7 +120,6 @@ void SkTwoPointConicalGradient::flatten(SkWriteBuffer& buffer) const {
buffer.writePoint(fCenter2);
buffer.writeScalar(fRadius1);
buffer.writeScalar(fRadius2);
- buffer.writeBool(fFlippedGrad);
}
#if SK_SUPPORT_GPU
@@ -150,29 +144,11 @@ std::unique_ptr<GrFragmentProcessor> SkTwoPointConicalGradient::asFragmentProces
#endif
sk_sp<SkShader> SkTwoPointConicalGradient::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
- SkSTArray<8, SkColor> origColorsStorage(fColorCount);
- SkSTArray<8, SkScalar> origPosStorage(fColorCount);
- SkSTArray<8, SkColor> xformedColorsStorage(fColorCount);
- SkColor* origColors = origColorsStorage.begin();
- SkScalar* origPos = fOrigPos ? origPosStorage.begin() : nullptr;
- SkColor* xformedColors = xformedColorsStorage.begin();
-
- // Flip if necessary
- SkPoint center1 = fFlippedGrad ? fCenter2 : fCenter1;
- SkPoint center2 = fFlippedGrad ? fCenter1 : fCenter2;
- SkScalar radius1 = fFlippedGrad ? fRadius2 : fRadius1;
- SkScalar radius2 = fFlippedGrad ? fRadius1 : fRadius2;
- for (int i = 0; i < fColorCount; i++) {
- origColors[i] = fFlippedGrad ? fOrigColors[fColorCount - i - 1] : fOrigColors[i];
- if (origPos) {
- origPos[i] = fFlippedGrad ? 1.0f - fOrigPos[fColorCount - i - 1] : fOrigPos[i];
- }
- }
-
- xformer->apply(xformedColors, origColors, fColorCount);
- return SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2, xformedColors,
- origPos, fColorCount, fTileMode, fGradFlags,
- &this->getLocalMatrix());
+ SkSTArray<8, SkColor> xformedColors(fColorCount);
+ xformer->apply(xformedColors.begin(), fOrigColors, fColorCount);
+ return SkGradientShader::MakeTwoPointConical(fCenter1, fRadius1, fCenter2, fRadius2,
+ xformedColors.begin(), fOrigPos, fColorCount,
+ fTileMode, fGradFlags, &this->getLocalMatrix());
}
@@ -205,13 +181,12 @@ void SkTwoPointConicalGradient::toString(SkString* str) const {
void SkTwoPointConicalGradient::appendGradientStages(SkArenaAlloc* alloc, SkRasterPipeline* p,
SkRasterPipeline* postPipeline) const {
const auto dRadius = fRadius2 - fRadius1;
- SkASSERT(dRadius >= 0);
if (fType == Type::kRadial) {
p->append(SkRasterPipeline::xy_to_radius);
// Tiny twist: radial computes a t for [0, r2], but we want a t for [r1, r2].
- auto scale = fRadius2 / dRadius;
+ auto scale = SkTMax(fRadius1, fRadius2) / dRadius;
auto bias = -fRadius1 / dRadius;
p->append_matrix(alloc, SkMatrix::Concat(SkMatrix::MakeTrans(bias, 0),
@@ -238,24 +213,21 @@ void SkTwoPointConicalGradient::appendGradientStages(SkArenaAlloc* alloc, SkRast
p->append(SkRasterPipeline::xy_to_2pt_conical_linear, ctx);
isWellBehaved = false;
} else {
- if (dCenter + fRadius1 > fRadius2) {
- // The focal point is outside the end circle.
-
- // We want the larger root, per spec:
- // "For all values of ω where r(ω) > 0, starting with the value of ω nearest
- // to positive infinity and ending with the value of ω nearest to negative
- // infinity, draw the circumference of the circle with radius r(ω) at position
- // (x(ω), y(ω)), with the color at ω, but only painting on the parts of the
- // bitmap that have not yet been painted on by earlier circles in this step for
- // this rendering of the gradient."
- // (https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-createradialgradient)
- p->append(fFlippedGrad ? SkRasterPipeline::xy_to_2pt_conical_quadratic_min
- : SkRasterPipeline::xy_to_2pt_conical_quadratic_max, ctx);
- isWellBehaved = false;
- } else {
- // The focal point is inside (well-behaved case).
- p->append(SkRasterPipeline::xy_to_2pt_conical_quadratic_max, ctx);
- }
+ isWellBehaved = SkScalarAbs(dRadius) >= dCenter;
+ bool isFlipped = isWellBehaved && dRadius < 0;
+
+ // We want the larger root, per spec:
+ // "For all values of ω where r(ω) > 0, starting with the value of ω nearest
+ // to positive infinity and ending with the value of ω nearest to negative
+ // infinity, draw the circumference of the circle with radius r(ω) at position
+ // (x(ω), y(ω)), with the color at ω, but only painting on the parts of the
+ // bitmap that have not yet been painted on by earlier circles in this step for
+ // this rendering of the gradient."
+ // (https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-createradialgradient)
+ //
+ // ... except when the gradient is flipped.
+ p->append(isFlipped ? SkRasterPipeline::xy_to_2pt_conical_quadratic_min
+ : SkRasterPipeline::xy_to_2pt_conical_quadratic_max, ctx);
}
if (!isWellBehaved) {
diff --git a/src/shaders/gradients/SkTwoPointConicalGradient.h b/src/shaders/gradients/SkTwoPointConicalGradient.h
index 4b2827117c..96039e4771 100644
--- a/src/shaders/gradients/SkTwoPointConicalGradient.h
+++ b/src/shaders/gradients/SkTwoPointConicalGradient.h
@@ -15,7 +15,7 @@ class SkTwoPointConicalGradient final : public SkGradientShaderBase {
public:
static sk_sp<SkShader> Create(const SkPoint& start, SkScalar startRadius,
const SkPoint& end, SkScalar endRadius,
- bool flippedGrad, const Descriptor&);
+ const Descriptor&);
SkShader::GradientType asAGradient(GradientInfo* info) const override;
#if SK_SUPPORT_GPU
@@ -29,7 +29,6 @@ public:
const SkPoint& getStartCenter() const { return fCenter1; }
const SkPoint& getEndCenter() const { return fCenter2; }
SkScalar getEndRadius() const { return fRadius2; }
- bool isFlippedGrad() const { return fFlippedGrad; }
SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTwoPointConicalGradient)
@@ -51,14 +50,12 @@ private:
SkTwoPointConicalGradient(const SkPoint& c0, SkScalar r0,
const SkPoint& c1, SkScalar r1,
- bool flippedGrad, const Descriptor&,
- Type, const SkMatrix&);
+ const Descriptor&, Type, const SkMatrix&);
SkPoint fCenter1;
SkPoint fCenter2;
SkScalar fRadius1;
SkScalar fRadius2;
- bool fFlippedGrad;
Type fType;
friend class SkGradientShader;
diff --git a/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp b/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp
index 5743d24b91..a48c8d9d39 100644
--- a/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp
+++ b/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp
@@ -16,6 +16,8 @@
#include "glsl/GrGLSLUniformHandler.h"
#include "SkTwoPointConicalGradient_gpu.h"
+#include <cmath>
+
// For brevity
typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
@@ -379,9 +381,10 @@ class FocalOutside2PtConicalEffect : public GrGradientEffect {
public:
class GLSLFocalOutside2PtConicalProcessor;
- static std::unique_ptr<GrFragmentProcessor> Make(const CreateArgs& args, SkScalar focalX) {
+ static std::unique_ptr<GrFragmentProcessor> Make(const CreateArgs& args, SkScalar focalX,
+ bool isFlipped) {
auto processor = std::unique_ptr<FocalOutside2PtConicalEffect>(
- new FocalOutside2PtConicalEffect(args, focalX));
+ new FocalOutside2PtConicalEffect(args, focalX, isFlipped));
return processor->isValid() ? std::move(processor) : nullptr;
}
@@ -408,17 +411,11 @@ private:
this->fIsFlipped == s.fIsFlipped);
}
- static bool IsFlipped(const CreateArgs& args) {
- // eww.
- return static_cast<const SkTwoPointConicalGradient*>(args.fShader)->isFlippedGrad();
- }
-
- FocalOutside2PtConicalEffect(const CreateArgs& args, SkScalar focalX)
+ FocalOutside2PtConicalEffect(const CreateArgs& args, SkScalar focalX, bool isFlipped)
: INHERITED(kFocalOutside2PtConicalEffect_ClassID, args,
false /* opaque: draws transparent black outside of the cone. */)
, fFocalX(focalX)
- , fIsFlipped(IsFlipped(args)) {
- }
+ , fIsFlipped(isFlipped) {}
explicit FocalOutside2PtConicalEffect(const FocalOutside2PtConicalEffect& that)
: INHERITED(that), fFocalX(that.fFocalX), fIsFlipped(that.fIsFlipped) {
@@ -449,12 +446,11 @@ protected:
const char* fVSVaryingName;
const char* fFSVaryingName;
- bool fIsFlipped;
-
// @{
/// Values last uploaded as uniforms
SkScalar fCachedFocal;
+ SkScalar fCachedFlipSign;
// @}
@@ -513,24 +509,27 @@ FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor
::GLSLFocalOutside2PtConicalProcessor(const GrProcessor& processor)
: fVSVaryingName(nullptr)
, fFSVaryingName(nullptr)
- , fCachedFocal(SK_ScalarMax) {
- const FocalOutside2PtConicalEffect& data = processor.cast<FocalOutside2PtConicalEffect>();
- fIsFlipped = data.isFlipped();
-}
+ , fCachedFocal(SK_ScalarMax)
+ , fCachedFlipSign(SK_ScalarMax) {}
void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::emitCode(EmitArgs& args) {
const FocalOutside2PtConicalEffect& ge = args.fFp.cast<FocalOutside2PtConicalEffect>();
GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
this->emitUniforms(uniformHandler, ge);
- fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
+ fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
"Conical2FSParams");
SkString tName("t");
+ // TODO: get rid of these locals?
SkString p0; // focalX
SkString p1; // 1 - focalX * focalX
-
p0.appendf("%s.x", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
p1.appendf("%s.y", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
+ // params.x = focalX
+ // params.y = 1 - focalX * focalX
+ // params.z = flipSign
+ GrShaderVar params = uniformHandler->getUniformVariable(fParamUni);
+
// if we have a float3 from being in perspective, convert it to a float2 first
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
@@ -545,18 +544,11 @@ void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::emitCode
fragBuilder->codeAppendf("\thalf xs = %s.x * %s.x;\n", coords2D, coords2D);
fragBuilder->codeAppendf("\thalf ys = %s.y * %s.y;\n", coords2D, coords2D);
fragBuilder->codeAppendf("\thalf d = xs + %s * ys;\n", p1.c_str());
+ fragBuilder->codeAppendf("\thalf %s = %s.x * %s + sqrt(d);\n",
+ tName.c_str(), coords2D, p0.c_str());
- // Must check to see if we flipped the circle order (to make sure start radius < end radius)
- // If so we must also flip sign on sqrt
- if (!fIsFlipped) {
- fragBuilder->codeAppendf("\thalf %s = %s.x * %s + sqrt(d);\n", tName.c_str(),
- coords2D, p0.c_str());
- } else {
- fragBuilder->codeAppendf("\thalf %s = %s.x * %s - sqrt(d);\n", tName.c_str(),
- coords2D, p0.c_str());
- }
-
- fragBuilder->codeAppendf("\tif (%s >= 0.0 && d >= 0.0) {\n", tName.c_str());
+ fragBuilder->codeAppendf("\tif (%s.z * %s >= 0.0 && d >= 0.0) {\n",
+ params.c_str(), tName.c_str());
fragBuilder->codeAppend("\t\t");
this->emitColor(fragBuilder,
uniformHandler,
@@ -573,23 +565,22 @@ void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::onSetDat
const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
INHERITED::onSetData(pdman, processor);
const FocalOutside2PtConicalEffect& data = processor.cast<FocalOutside2PtConicalEffect>();
- SkASSERT(data.isFlipped() == fIsFlipped);
SkScalar focal = data.focal();
+ SkScalar flipSign = data.isFlipped() ? -1 : 1;
- if (fCachedFocal != focal) {
+ if (fCachedFocal != focal || fCachedFlipSign != flipSign) {
SkScalar oneMinus2F = 1.f - focal * focal;
- pdman.set2f(fParamUni, SkScalarToFloat(focal), SkScalarToFloat(oneMinus2F));
+ pdman.set3f(fParamUni, focal, oneMinus2F, flipSign);
fCachedFocal = focal;
+ fCachedFlipSign = flipSign;
}
}
void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::GenKey(
const GrProcessor& processor,
const GrShaderCaps&, GrProcessorKeyBuilder* b) {
- uint32_t* key = b->add32n(2);
- key[0] = GenBaseGradientKey(processor);
- key[1] = processor.cast<FocalOutside2PtConicalEffect>().isFlipped();
+ b->add32(GenBaseGradientKey(processor));
}
//////////////////////////////////////////////////////////////////////////////
@@ -781,6 +772,21 @@ struct CircleConicalInfo {
SkScalar fA;
SkScalar fB;
SkScalar fC;
+
+ bool operator==(const CircleConicalInfo& other) const {
+ return fCenterEnd == other.fCenterEnd
+ && fA == other.fA
+ && fB == other.fB
+ && fC == other.fC;
+ }
+
+ bool operator!=(const CircleConicalInfo& other) const { return !(*this == other); }
+
+ // true when endRadius < startRadius
+ bool isFlipped() const {
+ // B = (endRadius/startRadius - 1) * C
+ return std::signbit(fB) != std::signbit(fC);
+ }
};
// Returns focal distance along x-axis in transformed coords
@@ -858,6 +864,7 @@ public:
SkScalar A() const { return fInfo.fA; }
SkScalar B() const { return fInfo.fB; }
SkScalar C() const { return fInfo.fC; }
+ bool isFlipped() const { return fInfo.isFlipped(); }
private:
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
@@ -867,17 +874,12 @@ private:
bool onIsEqual(const GrFragmentProcessor& sBase) const override {
const CircleInside2PtConicalEffect& s = sBase.cast<CircleInside2PtConicalEffect>();
- return (INHERITED::onIsEqual(sBase) &&
- this->fInfo.fCenterEnd == s.fInfo.fCenterEnd &&
- this->fInfo.fA == s.fInfo.fA &&
- this->fInfo.fB == s.fInfo.fB &&
- this->fInfo.fC == s.fInfo.fC);
+ return INHERITED::onIsEqual(sBase) && fInfo == s.fInfo;
}
CircleInside2PtConicalEffect(const CreateArgs& args, const CircleConicalInfo& info)
: INHERITED(kCircleInside2PtConicalEffect_ClassID, args,
- args.fShader->colorsAreOpaque()), fInfo(info) {
- }
+ args.fShader->colorsAreOpaque()), fInfo(info) {}
explicit CircleInside2PtConicalEffect(const CircleInside2PtConicalEffect& that)
: INHERITED(that), fInfo(that.fInfo) {}
@@ -915,6 +917,7 @@ protected:
SkScalar fCachedA;
SkScalar fCachedB;
SkScalar fCachedC;
+ SkScalar fCachedFlipSign;
// @}
@@ -977,7 +980,8 @@ CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor
, fCachedCenterY(SK_ScalarMax)
, fCachedA(SK_ScalarMax)
, fCachedB(SK_ScalarMax)
- , fCachedC(SK_ScalarMax) {}
+ , fCachedC(SK_ScalarMax)
+ , fCachedFlipSign(SK_ScalarMax) {}
void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::emitCode(EmitArgs& args) {
const CircleInside2PtConicalEffect& ge = args.fFp.cast<CircleInside2PtConicalEffect>();
@@ -985,7 +989,7 @@ void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::emitCode
this->emitUniforms(uniformHandler, ge);
fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
"Conical2FSCenter");
- fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
+ fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
"Conical2FSParams");
SkString tName("t");
@@ -993,6 +997,7 @@ void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::emitCode
// params.x = A
// params.y = B
// params.z = C
+ // params.w = flipSign
GrShaderVar params = uniformHandler->getUniformVariable(fParamUni);
// if we have a float3 from being in perspective, convert it to a float2 first
@@ -1011,8 +1016,8 @@ void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::emitCode
fragBuilder->codeAppendf("\thalf pDotp = dot(%s, %s);\n", coords2D, coords2D);
fragBuilder->codeAppendf("\thalf d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(),
params.c_str());
- fragBuilder->codeAppendf("\thalf %s = d + sqrt(d * d - %s.x * pDotp + %s.z);\n",
- tName.c_str(), params.c_str(), params.c_str());
+ fragBuilder->codeAppendf("\thalf %s = d + %s.w * sqrt(d * d - %s.x * pDotp + %s.z);\n",
+ tName.c_str(), params.c_str(), params.c_str(), params.c_str());
this->emitColor(fragBuilder,
uniformHandler,
@@ -1033,18 +1038,20 @@ void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::onSetDat
SkScalar A = data.A();
SkScalar B = data.B();
SkScalar C = data.C();
+ SkScalar flipSign = data.isFlipped() ? -1 : 1;
- if (fCachedCenterX != centerX || fCachedCenterY != centerY ||
- fCachedA != A || fCachedB != B || fCachedC != C) {
-
- pdman.set2f(fCenterUni, SkScalarToFloat(centerX), SkScalarToFloat(centerY));
- pdman.set3f(fParamUni, SkScalarToFloat(A), SkScalarToFloat(B), SkScalarToFloat(C));
-
+ if (fCachedCenterX != centerX || fCachedCenterY != centerY) {
+ pdman.set2f(fCenterUni, centerX, centerY);
fCachedCenterX = centerX;
fCachedCenterY = centerY;
+ }
+
+ if (fCachedA != A || fCachedB != B || fCachedC != C || fCachedFlipSign != flipSign) {
+ pdman.set4f(fParamUni, A, B, C, flipSign);
fCachedA = A;
fCachedB = B;
fCachedC = C;
+ fCachedFlipSign = flipSign;
}
}
@@ -1077,7 +1084,7 @@ public:
SkScalar B() const { return fInfo.fB; }
SkScalar C() const { return fInfo.fC; }
SkScalar tLimit() const { return fTLimit; }
- bool isFlipped() const { return fIsFlipped; }
+ bool isFlipped() const { return fInfo.isFlipped(); }
private:
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
@@ -1086,13 +1093,7 @@ private:
bool onIsEqual(const GrFragmentProcessor& sBase) const override {
const CircleOutside2PtConicalEffect& s = sBase.cast<CircleOutside2PtConicalEffect>();
- return (INHERITED::onIsEqual(sBase) &&
- this->fInfo.fCenterEnd == s.fInfo.fCenterEnd &&
- this->fInfo.fA == s.fInfo.fA &&
- this->fInfo.fB == s.fInfo.fB &&
- this->fInfo.fC == s.fInfo.fC &&
- this->fTLimit == s.fTLimit &&
- this->fIsFlipped == s.fIsFlipped);
+ return INHERITED::onIsEqual(sBase) && fInfo == s.fInfo && fTLimit == s.fTLimit;
}
CircleOutside2PtConicalEffect(const CreateArgs& args, const CircleConicalInfo& info)
@@ -1106,21 +1107,17 @@ private:
} else {
fTLimit = SK_ScalarMin;
}
-
- fIsFlipped = shader.isFlippedGrad();
}
explicit CircleOutside2PtConicalEffect(const CircleOutside2PtConicalEffect& that)
: INHERITED(that)
, fInfo(that.fInfo)
- , fTLimit(that.fTLimit)
- , fIsFlipped(that.fIsFlipped) {}
+ , fTLimit(that.fTLimit) {}
GR_DECLARE_FRAGMENT_PROCESSOR_TEST
const CircleConicalInfo fInfo;
SkScalar fTLimit;
- bool fIsFlipped;
typedef GrGradientEffect INHERITED;
};
@@ -1139,12 +1136,11 @@ protected:
UniformHandle fCenterUni;
UniformHandle fParamUni;
+ UniformHandle fFlipSignUni;
const char* fVSVaryingName;
const char* fFSVaryingName;
- bool fIsFlipped;
-
// @{
/// Values last uploaded as uniforms
@@ -1154,6 +1150,7 @@ protected:
SkScalar fCachedB;
SkScalar fCachedC;
SkScalar fCachedTLimit;
+ SkScalar fCachedFlipSign;
// @}
@@ -1218,10 +1215,8 @@ CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor
, fCachedA(SK_ScalarMax)
, fCachedB(SK_ScalarMax)
, fCachedC(SK_ScalarMax)
- , fCachedTLimit(SK_ScalarMax) {
- const CircleOutside2PtConicalEffect& data = processor.cast<CircleOutside2PtConicalEffect>();
- fIsFlipped = data.isFlipped();
- }
+ , fCachedTLimit(SK_ScalarMax)
+ , fCachedFlipSign(SK_ScalarMax) {}
void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::emitCode(EmitArgs& args) {
const CircleOutside2PtConicalEffect& ge = args.fFp.cast<CircleOutside2PtConicalEffect>();
@@ -1231,6 +1226,8 @@ void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::emitCo
"Conical2FSCenter");
fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
"Conical2FSParams");
+ fFlipSignUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
+ "Conical2FSFlipSign");
SkString tName("t");
GrShaderVar center = uniformHandler->getUniformVariable(fCenterUni);
@@ -1238,6 +1235,7 @@ void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::emitCo
// params.y = B
// params.z = C
GrShaderVar params = uniformHandler->getUniformVariable(fParamUni);
+ GrShaderVar flipsign = uniformHandler->getUniformVariable(fFlipSignUni);
// if we have a float3 from being in perspective, convert it to a float2 first
GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
@@ -1262,17 +1260,11 @@ void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::emitCo
params.c_str());
fragBuilder->codeAppendf("\thalf deter = d * d - %s.x * pDotp + %s.z;\n", params.c_str(),
params.c_str());
+ fragBuilder->codeAppendf("\thalf %s = d + sqrt(deter);\n",
+ tName.c_str());
- // Must check to see if we flipped the circle order (to make sure start radius < end radius)
- // If so we must also flip sign on sqrt
- if (!fIsFlipped) {
- fragBuilder->codeAppendf("\thalf %s = d + sqrt(deter);\n", tName.c_str());
- } else {
- fragBuilder->codeAppendf("\thalf %s = d - sqrt(deter);\n", tName.c_str());
- }
-
- fragBuilder->codeAppendf("\tif (%s >= %s.w && deter >= 0.0) {\n",
- tName.c_str(), params.c_str());
+ fragBuilder->codeAppendf("\tif (%s * (%s - %s.w) >= 0 && deter >= 0.0) {\n",
+ flipsign.c_str(), tName.c_str(), params.c_str());
fragBuilder->codeAppend("\t\t");
this->emitColor(fragBuilder,
uniformHandler,
@@ -1289,36 +1281,38 @@ void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::onSetD
const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
INHERITED::onSetData(pdman, processor);
const CircleOutside2PtConicalEffect& data = processor.cast<CircleOutside2PtConicalEffect>();
- SkASSERT(data.isFlipped() == fIsFlipped);
SkScalar centerX = data.centerX();
SkScalar centerY = data.centerY();
SkScalar A = data.A();
SkScalar B = data.B();
SkScalar C = data.C();
SkScalar tLimit = data.tLimit();
+ SkScalar flipSign = data.isFlipped() ? -1 : 1;
- if (fCachedCenterX != centerX || fCachedCenterY != centerY ||
- fCachedA != A || fCachedB != B || fCachedC != C || fCachedTLimit != tLimit) {
-
- pdman.set2f(fCenterUni, SkScalarToFloat(centerX), SkScalarToFloat(centerY));
- pdman.set4f(fParamUni, SkScalarToFloat(A), SkScalarToFloat(B), SkScalarToFloat(C),
- SkScalarToFloat(tLimit));
-
+ if (fCachedCenterX != centerX || fCachedCenterY != centerY) {
+ pdman.set2f(fCenterUni, centerX, centerY);
fCachedCenterX = centerX;
fCachedCenterY = centerY;
+ }
+
+ if (fCachedA != A || fCachedB != B || fCachedC != C || fCachedTLimit != tLimit) {
+ pdman.set4f(fParamUni, A, B, C, tLimit);
fCachedA = A;
fCachedB = B;
fCachedC = C;
fCachedTLimit = tLimit;
}
+
+ if (fCachedFlipSign != flipSign) {
+ pdman.set1f(fFlipSignUni, flipSign);
+ fCachedFlipSign = flipSign;
+ }
}
void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::GenKey(
const GrProcessor& processor,
const GrShaderCaps&, GrProcessorKeyBuilder* b) {
- uint32_t* key = b->add32n(2);
- key[0] = GenBaseGradientKey(processor);
- key[1] = processor.cast<CircleOutside2PtConicalEffect>().isFlipped();
+ b->add32(GenBaseGradientKey(processor));
}
//////////////////////////////////////////////////////////////////////////////
@@ -1352,7 +1346,8 @@ std::unique_ptr<GrFragmentProcessor> Gr2PtConicalGradientEffect::Make(
set_matrix_edge_conical(shader, &matrix);
return Edge2PtConicalEffect::Make(newArgs);
} else {
- return FocalOutside2PtConicalEffect::Make(newArgs, focalX);
+ const bool isFlipped = shader.getStartRadius() > shader.getEndRadius();
+ return FocalOutside2PtConicalEffect::Make(newArgs, focalX, isFlipped);
}
}