From 650dd901e1b9d4e2016eea234cb392830b10c416 Mon Sep 17 00:00:00 2001 From: Yuqian Li Date: Mon, 19 Mar 2018 14:23:48 -0400 Subject: [PATCH] Fix concentric 2pt conical gradient in GPU where r1 < r0 Bug: skia:7683 Change-Id: I6608e72fa695c855af6a6a447885c4889b09fc1d Reviewed-on: https://skia-review.googlesource.com/115042 Commit-Queue: Yuqian Li Reviewed-by: Greg Daniel --- gm/gradients_2pt_conical.cpp | 16 ++++++++++++--- .../SkTwoPointConicalGradient_gpu.cpp | 20 ++++++++++++------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/gm/gradients_2pt_conical.cpp b/gm/gradients_2pt_conical.cpp index 8a6b19a8f2..f2e2d1810e 100644 --- a/gm/gradients_2pt_conical.cpp +++ b/gm/gradients_2pt_conical.cpp @@ -98,17 +98,26 @@ static sk_sp Make2ConicalInsideFlip(const SkPoint pts[2], const GradDa static sk_sp Make2ConicalInsideCenter(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm, const SkMatrix& localMatrix) { - SkPoint center0, center1; + SkPoint center0; center0.set(SkScalarAve(pts[0].fX, pts[1].fX), SkScalarAve(pts[0].fY, pts[1].fY)); - center1.set(SkScalarInterp(pts[0].fX, pts[1].fX, SkIntToScalar(3)/5), - SkScalarInterp(pts[0].fY, pts[1].fY, SkIntToScalar(1)/4)); return SkGradientShader::MakeTwoPointConical(center0, (pts[1].fX - pts[0].fX) / 7, center0, (pts[1].fX - pts[0].fX) / 2, data.fColors, data.fPos, data.fCount, tm, 0, &localMatrix); } +static sk_sp Make2ConicalInsideCenterReversed(const SkPoint pts[2], const GradData& data, + SkShader::TileMode tm, const SkMatrix& localMatrix) { + SkPoint center0; + center0.set(SkScalarAve(pts[0].fX, pts[1].fX), + SkScalarAve(pts[0].fY, pts[1].fY)); + return SkGradientShader::MakeTwoPointConical(center0, (pts[1].fX - pts[0].fX) / 2, + center0, (pts[1].fX - pts[0].fX) / 7, + data.fColors, data.fPos, data.fCount, tm, + 0, &localMatrix); +} + static sk_sp Make2ConicalZeroRad(const SkPoint pts[2], const GradData& data, SkShader::TileMode tm, const SkMatrix& localMatrix) { SkPoint center0, center1; @@ -270,6 +279,7 @@ constexpr GradMaker gGradMakersOutside[] = { constexpr GradMaker gGradMakersInside[] = { Make2ConicalInside, Make2ConicalInsideFlip, Make2ConicalInsideCenter, Make2ConicalZeroRad, Make2ConicalZeroRadFlip, Make2ConicalZeroRadCenter, + Make2ConicalInsideCenterReversed }; constexpr GradMaker gGradMakersEdgeCases[] = { diff --git a/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp b/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp index 38e4495c84..6956fa22aa 100644 --- a/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp +++ b/src/shaders/gradients/SkTwoPointConicalGradient_gpu.cpp @@ -92,7 +92,9 @@ public: bool isNativelyFocal() const { return this->isFocal() && fData.fFocalData.isNativelyFocal(); } // Note that focalX = f = r0 / (r0 - r1), so 1 - focalX > 0 == r0 < r1 - bool isRadiusIncreasing() const { return this->isFocal() && 1 - fData.fFocalData.fFocalX > 0; } + bool isRadiusIncreasing() const { + return this->isFocal() ? 1 - fData.fFocalData.fFocalX > 0 : this->diffRadius() > 0; + } protected: void onGetGLSLProcessorKey(const GrShaderCaps& c, GrProcessorKeyBuilder* b) const override { @@ -237,7 +239,8 @@ protected: const char* p = coords2D.c_str(); if (effect.getType() == Type::kRadial) { - fragBuilder->codeAppendf("half %s = length(%s) - %s;", tName, p, p0.c_str()); + char sign = effect.diffRadius() < 0 ? '-' : '+'; + fragBuilder->codeAppendf("half %s = %clength(%s) - %s;", tName, sign, p, p0.c_str()); } else { // output will default to transparent black (we simply won't write anything // else to it if invalid, instead of discarding or returning prematurely) @@ -263,8 +266,9 @@ protected: void onSetData(const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& p) override { INHERITED::onSetData(pdman, p); const TwoPointConicalEffect& effect = p.cast(); - // kRadialType should imply r1 - r0 = 1 (after our transformation) so r0 = r0 / (r1 - r0) - SkASSERT(effect.getType() == Type::kStrip || SkScalarNearlyZero(effect.diffRadius() - 1)); + // kRadialType should imply |r1 - r0| = 1 (after our transformation) + SkASSERT(effect.getType() == Type::kStrip || + SkScalarNearlyZero(SkTAbs(effect.diffRadius()) - 1)); pdman.set1f(fParamUni, effect.getType() == Type::kRadial ? effect.r0() : effect.r0() * effect.r0()); } @@ -407,12 +411,14 @@ std::unique_ptr Gr2PtConicalGradientEffect::Make( TwoPointConicalEffect::Data::Data(const SkTwoPointConicalGradient& shader, SkMatrix& matrix) { fType = shader.getType(); if (fType == Type::kRadial) { - SkScalar dr = shader.getDiffRadius(); - // Map center to (0, 0) and scale dr to 1 + // Map center to (0, 0) matrix.postTranslate(-shader.getStartCenter().fX, -shader.getStartCenter().fY); + + // scale |fDiffRadius| to 1 + SkScalar dr = shader.getDiffRadius(); matrix.postScale(1 / dr, 1 / dr); fRadius0 = shader.getStartRadius() / dr; - fDiffRadius = 1; + fDiffRadius = dr < 0 ? -1 : 1; } else if (fType == Type::kStrip) { fRadius0 = shader.getStartRadius() / shader.getCenterX1(); fDiffRadius = 0;