diff options
author | Chris Craik <ccraik@google.com> | 2014-07-29 12:50:14 -0700 |
---|---|---|
committer | Chris Craik <ccraik@google.com> | 2014-07-30 17:15:50 +0000 |
commit | af4d04cab6d48ae0d6a5e79bd30f679af87abaad (patch) | |
tree | b1fe9d83f5ccc32b1e0db8f002d2d3035368dfac /libs | |
parent | 3d1856f4449f02a9a3bda06738c3eb83df96f88b (diff) | |
download | frameworks_base-af4d04cab6d48ae0d6a5e79bd30f679af87abaad.zip frameworks_base-af4d04cab6d48ae0d6a5e79bd30f679af87abaad.tar.gz frameworks_base-af4d04cab6d48ae0d6a5e79bd30f679af87abaad.tar.bz2 |
Use RoundRect clipping for circle reveal animation
bug:16630975
Also, remove inverse clipping feature from reveal animator.
Change-Id: I770a4eb48cd123b0ca0f39d16a0f3eefd1be3653
Diffstat (limited to 'libs')
-rw-r--r-- | libs/hwui/Animator.cpp | 9 | ||||
-rw-r--r-- | libs/hwui/Animator.h | 2 | ||||
-rw-r--r-- | libs/hwui/DisplayListOp.h | 8 | ||||
-rwxr-xr-x | libs/hwui/OpenGLRenderer.cpp | 8 | ||||
-rw-r--r-- | libs/hwui/RenderNode.cpp | 32 | ||||
-rw-r--r-- | libs/hwui/RenderProperties.h | 13 | ||||
-rw-r--r-- | libs/hwui/RevealClip.h | 19 | ||||
-rw-r--r-- | libs/hwui/Snapshot.cpp | 29 | ||||
-rw-r--r-- | libs/hwui/Snapshot.h | 6 | ||||
-rw-r--r-- | libs/hwui/StatefulBaseRenderer.cpp | 19 | ||||
-rw-r--r-- | libs/hwui/StatefulBaseRenderer.h | 2 |
11 files changed, 63 insertions, 84 deletions
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp index 24ed6cd..dd2e2fd 100644 --- a/libs/hwui/Animator.cpp +++ b/libs/hwui/Animator.cpp @@ -288,21 +288,20 @@ void CanvasPropertyPaintAnimator::setValue(RenderNode* target, float value) { LOG_ALWAYS_FATAL("Unknown field %d", (int) mField); } -RevealAnimator::RevealAnimator(int centerX, int centerY, bool inverseClip, +RevealAnimator::RevealAnimator(int centerX, int centerY, float startValue, float finalValue) : BaseRenderNodeAnimator(finalValue) , mCenterX(centerX) - , mCenterY(centerY) - , mInverseClip(inverseClip) { + , mCenterY(centerY) { setStartValue(startValue); } float RevealAnimator::getValue(RenderNode* target) const { - return target->properties().getRevealClip().radius(); + return target->properties().getRevealClip().getRadius(); } void RevealAnimator::setValue(RenderNode* target, float value) { - target->animatorProperties().mutableRevealClip().set(true, mInverseClip, + target->animatorProperties().mutableRevealClip().set(true, mCenterX, mCenterY, value); } diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h index 9a080a7..b0dcf2d 100644 --- a/libs/hwui/Animator.h +++ b/libs/hwui/Animator.h @@ -171,7 +171,7 @@ private: class RevealAnimator : public BaseRenderNodeAnimator { public: - ANDROID_API RevealAnimator(int centerX, int centerY, bool inverseClip, + ANDROID_API RevealAnimator(int centerX, int centerY, float startValue, float finalValue); protected: virtual float getValue(RenderNode* target) const; diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h index 9f66904..777a35a 100644 --- a/libs/hwui/DisplayListOp.h +++ b/libs/hwui/DisplayListOp.h @@ -1535,10 +1535,9 @@ private: class DrawShadowOp : public DrawOp { public: DrawShadowOp(const mat4& transformXY, const mat4& transformZ, - float casterAlpha, bool casterUnclipped, - const SkPath* casterOutline, const SkPath* revealClip) + float casterAlpha, const SkPath* casterOutline, const SkPath* revealClip) : DrawOp(NULL), mTransformXY(transformXY), mTransformZ(transformZ), - mCasterAlpha(casterAlpha), mCasterUnclipped(casterUnclipped) { + mCasterAlpha(casterAlpha) { mOutline = *casterOutline; if (revealClip) { // intersect the outline with the convex reveal clip @@ -1572,12 +1571,11 @@ public: virtual const char* name() { return "DrawShadow"; } private: - bool isCasterOpaque() { return mCasterAlpha >= 1.0f && mCasterUnclipped; } + bool isCasterOpaque() { return mCasterAlpha >= 1.0f; } const mat4 mTransformXY; const mat4 mTransformZ; const float mCasterAlpha; - const bool mCasterUnclipped; SkPath mOutline; }; diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index de777f0..5e6ae3f 100755 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -1742,12 +1742,12 @@ void OpenGLRenderer::setupDrawProgram() { if (mDescription.hasRoundRectClip) { // TODO: avoid doing this repeatedly, stashing state pointer in program const RoundRectClipState* state = mSnapshot->roundRectClipState; - const Rect& innerRect = state->outlineInnerRect; + const Rect& innerRect = state->innerRect; glUniform4f(mCaches.currentProgram->getUniform("roundRectInnerRectLTRB"), - innerRect.left, innerRect.top, - innerRect.right, innerRect.bottom); + innerRect.left, innerRect.top, + innerRect.right, innerRect.bottom); glUniform1f(mCaches.currentProgram->getUniform("roundRectRadius"), - state->outlineRadius); + state->radius); glUniformMatrix4fv(mCaches.currentProgram->getUniform("roundRectInvTransform"), 1, GL_FALSE, &state->matrix.data[0]); } diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 1df2055..0662ca2 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -384,11 +384,15 @@ void RenderNode::setViewProperties(OpenGLRenderer& renderer, T& handler) { handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds()); } - if (CC_UNLIKELY(properties().hasClippingPath())) { - ClipPathOp* op = new (handler.allocator()) ClipPathOp( - properties().getClippingPath(), properties().getClippingPathOp()); - handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds()); + // TODO: support both reveal clip and outline clip simultaneously + if (mProperties.getRevealClip().willClip()) { + Rect bounds; + mProperties.getRevealClip().getBounds(&bounds); + renderer.setClippingRoundRect(handler.allocator(), bounds, mProperties.getRevealClip().getRadius()); + } else if (mProperties.getOutline().willClip()) { + renderer.setClippingOutline(handler.allocator(), &(mProperties.getOutline())); } + } /** @@ -600,23 +604,11 @@ void RenderNode::issueDrawShadowOperation(const Matrix4& transformFromParent, T& applyViewPropertyTransforms(shadowMatrixZ, true); const SkPath* outlinePath = properties().getOutline().getPath(); - const RevealClip& revealClip = properties().getRevealClip(); - const SkPath* revealClipPath = revealClip.hasConvexClip() - ? revealClip.getPath() : NULL; // only pass the reveal clip's path if it's convex - + const SkPath* revealClipPath = properties().getRevealClip().getPath(); if (revealClipPath && revealClipPath->isEmpty()) return; - /** - * The drawing area of the caster is always the same as the its perimeter (which - * the shadow system uses) *except* in the inverse clip case. Inform the shadow - * system that the caster's drawing area (as opposed to its perimeter) has been - * clipped, so that it knows the caster can't be opaque. - */ - bool casterUnclipped = !revealClip.willClip() || revealClip.hasConvexClip(); - DisplayListOp* shadowOp = new (handler.allocator()) DrawShadowOp( - shadowMatrixXY, shadowMatrixZ, - properties().getAlpha(), casterUnclipped, + shadowMatrixXY, shadowMatrixZ, properties().getAlpha(), outlinePath, revealClipPath); handler(shadowOp, PROPERTY_SAVECOUNT, properties().getClipToBounds()); } @@ -828,10 +820,6 @@ void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) { bool quickRejected = properties().getClipToBounds() && renderer.quickRejectConservative(0, 0, properties().getWidth(), properties().getHeight()); if (!quickRejected) { - if (mProperties.getOutline().willClip()) { - renderer.setClippingOutline(alloc, &(mProperties.getOutline())); - } - if (drawLayer) { handler(new (alloc) DrawLayerOp(mLayer, 0, 0), renderer.getSaveCount() - 1, properties().getClipToBounds()); diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h index f50e514..9898bde 100644 --- a/libs/hwui/RenderProperties.h +++ b/libs/hwui/RenderProperties.h @@ -546,19 +546,6 @@ public: void updateMatrix(); - bool hasClippingPath() const { - return mPrimitiveFields.mRevealClip.willClip(); - } - - const SkPath* getClippingPath() const { - return mPrimitiveFields.mRevealClip.getPath(); - } - - SkRegion::Op getClippingPathOp() const { - return mPrimitiveFields.mRevealClip.isInverseClip() - ? SkRegion::kDifference_Op : SkRegion::kIntersect_Op; - } - Outline& mutableOutline() { return mPrimitiveFields.mOutline; } diff --git a/libs/hwui/RevealClip.h b/libs/hwui/RevealClip.h index 07404cb..a9600f1 100644 --- a/libs/hwui/RevealClip.h +++ b/libs/hwui/RevealClip.h @@ -27,14 +27,12 @@ class RevealClip { public: RevealClip() : mShouldClip(false) - , mInverseClip(false) , mX(0) , mY(0) , mRadius(0) {} - void set(bool shouldClip, bool inverseClip, float x, float y, float radius) { + void set(bool shouldClip, float x, float y, float radius) { mShouldClip = shouldClip; - mInverseClip = inverseClip; mX = x; mY = y; mRadius = radius; @@ -45,21 +43,15 @@ public: } } - bool hasConvexClip() const { - return mShouldClip && !mInverseClip; - } - - bool isInverseClip() const { - return mInverseClip; - } - bool willClip() const { return mShouldClip; } - float radius() const { - return mRadius; + void getBounds(Rect* outBounds) const { + outBounds->set(mX - mRadius, mY - mRadius, + mX + mRadius, mY + mRadius); } + float getRadius() const { return mRadius; } const SkPath* getPath() const { if (!mShouldClip) return NULL; @@ -69,7 +61,6 @@ public: private: bool mShouldClip; - bool mInverseClip; float mX; float mY; float mRadius; diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp index 80f7eca..6f19275 100644 --- a/libs/hwui/Snapshot.cpp +++ b/libs/hwui/Snapshot.cpp @@ -20,8 +20,6 @@ #include <SkCanvas.h> -#include "utils/MathUtils.h" - namespace android { namespace uirenderer { @@ -207,23 +205,22 @@ void Snapshot::resetTransform(float x, float y, float z) { } /////////////////////////////////////////////////////////////////////////////// -// Clipping outline +// Clipping round rect /////////////////////////////////////////////////////////////////////////////// -void Snapshot::setClippingOutline(LinearAllocator& allocator, const Outline* outline) { - Rect bounds; - float radius; - if (!outline->getAsRoundRect(&bounds, &radius)) return; // only RR supported - - if (!MathUtils::isPositive(radius)) return; // leave clipping up to rect clipping +void Snapshot::setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds, float radius) { + if (bounds.isEmpty()) { + clipRect->setEmpty(); + return; + } RoundRectClipState* state = new (allocator) RoundRectClipState; // store the inverse drawing matrix - Matrix4 outlineDrawingMatrix; - outlineDrawingMatrix.load(getOrthoMatrix()); - outlineDrawingMatrix.multiply(*transform); - state->matrix.loadInverse(outlineDrawingMatrix); + Matrix4 roundRectDrawingMatrix; + roundRectDrawingMatrix.load(getOrthoMatrix()); + roundRectDrawingMatrix.multiply(*transform); + state->matrix.loadInverse(roundRectDrawingMatrix); // compute area under rounded corners - only draws overlapping these rects need to be clipped for (int i = 0 ; i < 4; i++) { @@ -241,9 +238,9 @@ void Snapshot::setClippingOutline(LinearAllocator& allocator, const Outline* out } // store RR area - bounds.inset(radius); - state->outlineInnerRect = bounds; - state->outlineRadius = radius; + state->innerRect = bounds; + state->innerRect.inset(radius); + state->radius = radius; // store as immutable so, for this frame, pointer uniquely identifies this bundle of shader info roundRectClipState = state; diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h index 5426e89..98e2440 100644 --- a/libs/hwui/Snapshot.h +++ b/libs/hwui/Snapshot.h @@ -57,8 +57,8 @@ public: Matrix4 matrix; Rect dangerRects[4]; - Rect outlineInnerRect; - float outlineRadius; + Rect innerRect; + float radius; }; /** @@ -164,7 +164,7 @@ public: /** * Sets (and replaces) the current clipping outline */ - void setClippingOutline(LinearAllocator& allocator, const Outline* outline); + void setClippingRoundRect(LinearAllocator& allocator, const Rect& bounds, float radius); /** * Indicates whether this snapshot should be ignored. A snapshot diff --git a/libs/hwui/StatefulBaseRenderer.cpp b/libs/hwui/StatefulBaseRenderer.cpp index 473005c..dc41157 100644 --- a/libs/hwui/StatefulBaseRenderer.cpp +++ b/libs/hwui/StatefulBaseRenderer.cpp @@ -20,6 +20,8 @@ #include "StatefulBaseRenderer.h" +#include "utils/MathUtils.h" + namespace android { namespace uirenderer { @@ -189,9 +191,24 @@ bool StatefulBaseRenderer::clipRegion(const SkRegion* region, SkRegion::Op op) { } void StatefulBaseRenderer::setClippingOutline(LinearAllocator& allocator, const Outline* outline) { - mSnapshot->setClippingOutline(allocator, outline); + Rect bounds; + float radius; + if (!outline->getAsRoundRect(&bounds, &radius)) return; // only RR supported + + if (!MathUtils::isPositive(radius)) { + // TODO: consider storing this rect separately, so that this can't be replaced with clip ops + clipRect(bounds.left, bounds.top, bounds.right, bounds.bottom, SkRegion::kIntersect_Op); + return; + } + setClippingRoundRect(allocator, bounds, radius); } +void StatefulBaseRenderer::setClippingRoundRect(LinearAllocator& allocator, + const Rect& rect, float radius) { + mSnapshot->setClippingRoundRect(allocator, rect, radius); +} + + /////////////////////////////////////////////////////////////////////////////// // Quick Rejection /////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/StatefulBaseRenderer.h b/libs/hwui/StatefulBaseRenderer.h index 25cc832..6d83b4c 100644 --- a/libs/hwui/StatefulBaseRenderer.h +++ b/libs/hwui/StatefulBaseRenderer.h @@ -96,6 +96,8 @@ public: * The clipping outline is independent from the regular clip. */ void setClippingOutline(LinearAllocator& allocator, const Outline* outline); + void setClippingRoundRect(LinearAllocator& allocator, + const Rect& rect, float radius); protected: const Rect& getRenderTargetClipBounds() const { return mSnapshot->getRenderTargetClip(); } |