diff options
author | Jim Van Verth <jvanverth@google.com> | 2018-06-28 10:46:05 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-06-28 15:27:37 +0000 |
commit | b1b87d9df81eb4ddb25fc76a2a2a6664fc4ef0ec (patch) | |
tree | 428718a8bf8719b12c2405a205e13918b5e914c8 | |
parent | b06be0e8b909f7237dda6817bc6301826f7ede3f (diff) |
Reland "Improve precision and speed of oval rendering."
This reverts commit cd2253d07f246b8da2f88cde39a6adab5e5021de.
Reason for revert: Tweaks for Adreno.
Original change's description:
> Revert "Improve precision and speed of oval rendering."
>
> This reverts commit 551dc3e911438afb7c0ab28b1060a9480a4debd3.
>
> Reason for revert: Centers of ovals are dropping out on Adreno330
>
> Original change's description:
> > Improve precision and speed of oval rendering.
> >
> > Reduces computations, and fixes some issues with large ovals.
> >
> > Change-Id: I2a961f2115e4e5fcb756714dd7e45c7528ed679a
> > Reviewed-on: https://skia-review.googlesource.com/136229
> > Reviewed-by: Brian Osman <brianosman@google.com>
> > Commit-Queue: Jim Van Verth <jvanverth@google.com>
>
> TBR=jvanverth@google.com,brianosman@google.com
>
> Change-Id: I704dcd591217f04cedb5b6c5c5ade3df928f8249
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Reviewed-on: https://skia-review.googlesource.com/138040
> Reviewed-by: Jim Van Verth <jvanverth@google.com>
> Commit-Queue: Jim Van Verth <jvanverth@google.com>
TBR=jvanverth@google.com,brianosman@google.com
Change-Id: I710b79376dfd75b718fd867b149b28faebd1946a
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://skia-review.googlesource.com/138180
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
-rw-r--r-- | src/gpu/ops/GrOvalOpFactory.cpp | 60 |
1 files changed, 45 insertions, 15 deletions
diff --git a/src/gpu/ops/GrOvalOpFactory.cpp b/src/gpu/ops/GrOvalOpFactory.cpp index ca209e02fe..975c856f57 100644 --- a/src/gpu/ops/GrOvalOpFactory.cpp +++ b/src/gpu/ops/GrOvalOpFactory.cpp @@ -578,25 +578,37 @@ private: egp.kInPosition.asShaderVar(), egp.fLocalMatrix, args.fFPCoordTransformHandler); + // For stroked ellipses, we use the full ellipse equation (x^2/a^2 + y^2/b^2 = 1) + // to compute both the edges because we need two separate test equations for + // the single offset. + // For filled ellipses we can use a unit circle equation (x^2 + y^2 = 1), and warp + // the distance by the gradient, non-uniformly scaled by the inverse of the + // ellipse size. // for outer curve - fragBuilder->codeAppendf("half2 scaledOffset = %s*%s.xy;", ellipseOffsets.fsIn(), - ellipseRadii.fsIn()); - fragBuilder->codeAppend("half test = dot(scaledOffset, scaledOffset) - 1.0;"); - fragBuilder->codeAppendf("half2 grad = 2.0*scaledOffset*%s.xy;", ellipseRadii.fsIn()); + fragBuilder->codeAppendf("half2 offset = %s;", ellipseOffsets.fsIn()); + if (egp.fStroke) { + fragBuilder->codeAppendf("offset *= %s.xy;", ellipseRadii.fsIn()); + } + fragBuilder->codeAppend("half test = dot(offset, offset) - 1.0;"); + fragBuilder->codeAppendf("half2 grad = 2.0*offset*%s.xy;", ellipseRadii.fsIn()); fragBuilder->codeAppend("half grad_dot = dot(grad, grad);"); // avoid calling inversesqrt on zero. - fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);"); + if (args.fShaderCaps->halfIs32Bits()) { + fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-6);"); + } else { + fragBuilder->codeAppend("grad_dot = max(grad_dot, 3.1e-5);"); + } fragBuilder->codeAppend("half invlen = inversesqrt(grad_dot);"); fragBuilder->codeAppend("half edgeAlpha = clamp(0.5-test*invlen, 0.0, 1.0);"); // for inner curve if (egp.fStroke) { - fragBuilder->codeAppendf("scaledOffset = %s*%s.zw;", ellipseOffsets.fsIn(), + fragBuilder->codeAppendf("offset = %s*%s.zw;", ellipseOffsets.fsIn(), ellipseRadii.fsIn()); - fragBuilder->codeAppend("test = dot(scaledOffset, scaledOffset) - 1.0;"); - fragBuilder->codeAppendf("grad = 2.0*scaledOffset*%s.zw;", ellipseRadii.fsIn()); + fragBuilder->codeAppend("test = dot(offset, offset) - 1.0;"); + fragBuilder->codeAppendf("grad = 2.0*offset*%s.zw;", ellipseRadii.fsIn()); fragBuilder->codeAppend("invlen = inversesqrt(dot(grad, grad));"); fragBuilder->codeAppend("edgeAlpha *= clamp(0.5+test*invlen, 0.0, 1.0);"); } @@ -739,7 +751,11 @@ private: fragBuilder->codeAppend("half grad_dot = dot(grad, grad);"); // avoid calling inversesqrt on zero. - fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);"); + if (args.fShaderCaps->halfIs32Bits()) { + fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-6);"); + } else { + fragBuilder->codeAppend("grad_dot = max(grad_dot, 3.1e-5);"); + } fragBuilder->codeAppend("half invlen = inversesqrt(grad_dot);"); if (DIEllipseStyle::kHairline == diegp.fStyle) { // can probably do this with one step @@ -1975,11 +1991,16 @@ private: SkScalar yRadRecip = SkScalarInvert(yRadius); SkScalar xInnerRadRecip = SkScalarInvert(ellipse.fInnerXRadius); SkScalar yInnerRadRecip = SkScalarInvert(ellipse.fInnerYRadius); - - // fOffsets are expanded from xyRadii to include the half-pixel antialiasing width. SkScalar xMaxOffset = xRadius + SK_ScalarHalf; SkScalar yMaxOffset = yRadius + SK_ScalarHalf; + if (!fStroked) { + // For filled ellipses we map a unit circle in the vertex attributes rather than + // computing an ellipse and modifying that distance, so we normalize to 1 + xMaxOffset /= xRadius; + yMaxOffset /= yRadius; + } + // The inner radius in the vertex data must be specified in normalized space. verts[0].fPos = SkPoint::Make(ellipse.fDevBounds.fLeft, ellipse.fDevBounds.fTop); verts[0].fColor = color; @@ -2919,19 +2940,28 @@ private: SkScalar xOuterRadius = rrect.fXRadius + SK_ScalarHalf; SkScalar yOuterRadius = rrect.fYRadius + SK_ScalarHalf; + SkScalar xMaxOffset = xOuterRadius; + SkScalar yMaxOffset = yOuterRadius; + if (!fStroked) { + // For filled rrects we map a unit circle in the vertex attributes rather than + // computing an ellipse and modifying that distance, so we normalize to 1. + xMaxOffset /= rrect.fXRadius; + yMaxOffset /= rrect.fYRadius; + } + const SkRect& bounds = rrect.fDevBounds; SkScalar yCoords[4] = {bounds.fTop, bounds.fTop + yOuterRadius, bounds.fBottom - yOuterRadius, bounds.fBottom}; - SkScalar yOuterOffsets[4] = {yOuterRadius, + SkScalar yOuterOffsets[4] = {yMaxOffset, SK_ScalarNearlyZero, // we're using inversesqrt() in // shader, so can't be exactly 0 - SK_ScalarNearlyZero, yOuterRadius}; + SK_ScalarNearlyZero, yMaxOffset}; for (int i = 0; i < 4; ++i) { verts->fPos = SkPoint::Make(bounds.fLeft, yCoords[i]); verts->fColor = color; - verts->fOffset = SkPoint::Make(xOuterRadius, yOuterOffsets[i]); + verts->fOffset = SkPoint::Make(xMaxOffset, yOuterOffsets[i]); verts->fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); verts->fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip); verts++; @@ -2952,7 +2982,7 @@ private: verts->fPos = SkPoint::Make(bounds.fRight, yCoords[i]); verts->fColor = color; - verts->fOffset = SkPoint::Make(xOuterRadius, yOuterOffsets[i]); + verts->fOffset = SkPoint::Make(xMaxOffset, yOuterOffsets[i]); verts->fOuterRadii = SkPoint::Make(xRadRecip, yRadRecip); verts->fInnerRadii = SkPoint::Make(xInnerRadRecip, yInnerRadRecip); verts++; |