summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/DisplayList.java28
-rw-r--r--core/java/android/view/View.java34
-rw-r--r--core/jni/android_view_DisplayList.cpp8
-rw-r--r--libs/hwui/DisplayList.cpp10
-rw-r--r--libs/hwui/DisplayList.h9
-rw-r--r--libs/hwui/DisplayListOp.h28
-rw-r--r--libs/hwui/OpenGLRenderer.cpp5
7 files changed, 100 insertions, 22 deletions
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java
index 5f6e7cf4bf77..8b6335918ab9 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/view/DisplayList.java
@@ -17,6 +17,7 @@
package android.view;
import android.graphics.Matrix;
+import android.graphics.Path;
import java.util.ArrayList;
@@ -151,7 +152,7 @@ public class DisplayList {
/**
* Indicates that the display list is done drawing.
- *
+ *
* @see HardwareCanvas#drawDisplayList(DisplayList, android.graphics.Rect, int)
*
* @hide
@@ -160,7 +161,7 @@ public class DisplayList {
/**
* Indicates that the display list needs another drawing pass.
- *
+ *
* @see HardwareCanvas#drawDisplayList(DisplayList, android.graphics.Rect, int)
*
* @hide
@@ -169,9 +170,9 @@ public class DisplayList {
/**
* Indicates that the display list needs to re-execute its GL functors.
- *
- * @see HardwareCanvas#drawDisplayList(DisplayList, android.graphics.Rect, int)
- * @see HardwareCanvas#callDrawGLFunction(int)
+ *
+ * @see HardwareCanvas#drawDisplayList(DisplayList, android.graphics.Rect, int)
+ * @see HardwareCanvas#callDrawGLFunction(long)
*
* @hide
*/
@@ -406,7 +407,7 @@ public class DisplayList {
* Set whether the display list should collect and Z order all 3d composited descendents, and
* draw them in order with the default Z=0 content.
*
- * @param isolateZVolume true if the display list should collect and Z order descendents.
+ * @param isolatedZVolume true if the display list should collect and Z order descendents.
*/
public void setIsolatedZVolume(boolean isolatedZVolume) {
if (hasNativeDisplayList()) {
@@ -430,6 +431,20 @@ public class DisplayList {
}
/**
+ * Sets the outline, defining the shape that casts a shadow.
+ *
+ * Deep copies the native path to simplify reference ownership.
+ *
+ * @param outline Convex, CW Path to store in the DisplayList. May be null.
+ */
+ public void setOutline(Path outline) {
+ if (hasNativeDisplayList()) {
+ long nativePath = (outline == null) ? 0 : outline.mNativePath;
+ nSetOutline(mFinalizer.mNativeDisplayList, nativePath);
+ }
+ }
+
+ /**
* Set the static matrix on the display list. The specified matrix is combined with other
* transforms (such as {@link #setScaleX(float)}, {@link #setRotation(float)}, etc.)
*
@@ -1051,6 +1066,7 @@ public class DisplayList {
private static native void nSetClipToBounds(long displayList, boolean clipToBounds);
private static native void nSetProjectBackwards(long displayList, boolean shouldProject);
private static native void nSetIsolatedZVolume(long displayList, boolean isolateZVolume);
+ private static native void nSetOutline(long displayList, long nativePath);
private static native void nSetAlpha(long displayList, float alpha);
private static native void nSetHasOverlappingRendering(long displayList,
boolean hasOverlappingRendering);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 9576602b1f6a..239eda44f3a2 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -32,6 +32,7 @@ import android.graphics.Interpolator;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
+import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.PorterDuff;
@@ -3295,6 +3296,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
private int[] mDrawableState = null;
/**
+ * Stores the outline of the view, passed down to the DisplayList level for shadow shape.
+ */
+ private Path mOutline;
+
+ /**
* When this view has focus and the next focus is {@link #FOCUS_LEFT},
* the user may specify which view to go to next.
*/
@@ -10624,6 +10630,33 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * @hide
+ */
+ public final void getOutline(Path outline) {
+ if (mOutline == null) {
+ outline.reset();
+ } else {
+ outline.set(mOutline);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ public void setOutline(Path path) {
+ // always copy the path since caller may reuse
+ if (mOutline == null) {
+ mOutline = new Path(path);
+ } else {
+ mOutline.set(path);
+ }
+
+ if (mDisplayList != null) {
+ mDisplayList.setOutline(path);
+ }
+ }
+
+ /**
* Hit rectangle in parent's coordinates
*
* @param outRect The hit rectangle of the view.
@@ -14266,6 +14299,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
displayList.setIsolatedZVolume(
(((ViewGroup) this).mGroupFlags & ViewGroup.FLAG_ISOLATED_Z_VOLUME) != 0);
}
+ displayList.setOutline(mOutline);
float alpha = 1;
if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
diff --git a/core/jni/android_view_DisplayList.cpp b/core/jni/android_view_DisplayList.cpp
index 61d2a5eec3e4..9379375108be 100644
--- a/core/jni/android_view_DisplayList.cpp
+++ b/core/jni/android_view_DisplayList.cpp
@@ -117,6 +117,13 @@ static void android_view_DisplayList_setProjectBackwards(JNIEnv* env,
displayList->setProjectBackwards(shouldProject);
}
+static void android_view_DisplayList_setOutline(JNIEnv* env,
+ jobject clazz, jlong displayListPtr, jlong outlinePathPtr) {
+ DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
+ SkPath* outline = reinterpret_cast<SkPath*>(outlinePathPtr);
+ displayList->setOutline(outline);
+}
+
static void android_view_DisplayList_setAlpha(JNIEnv* env,
jobject clazz, jlong displayListPtr, float alpha) {
DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
@@ -385,6 +392,7 @@ static JNINativeMethod gMethods[] = {
{ "nSetClipToBounds", "(JZ)V", (void*) android_view_DisplayList_setClipToBounds },
{ "nSetIsolatedZVolume", "(JZ)V", (void*) android_view_DisplayList_setIsolatedZVolume },
{ "nSetProjectBackwards", "(JZ)V", (void*) android_view_DisplayList_setProjectBackwards },
+ { "nSetOutline", "(JJ)V", (void*) android_view_DisplayList_setOutline },
{ "nSetAlpha", "(JF)V", (void*) android_view_DisplayList_setAlpha },
{ "nSetHasOverlappingRendering", "(JZ)V",
(void*) android_view_DisplayList_setHasOverlappingRendering },
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 66a526a7a2e6..fd3dae7dfd71 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -240,6 +240,7 @@ void DisplayList::init() {
mClipToBounds = true;
mIsolatedZVolume = true;
mProjectBackwards = false;
+ mOutline.rewind();
mAlpha = 1;
mHasOverlappingRendering = true;
mTranslationX = 0;
@@ -654,16 +655,15 @@ void DisplayList::iterate3dChildren(ChildrenSelectMode mode, OpenGLRenderer& ren
/* draw shadow with parent matrix applied, passing in the child's total matrix
*
* TODO:
- * -determine and pass background shape (and possibly drawable alpha)
* -view must opt-in to shadows
- * -consider shadows for other content
- * -inform shadow system of ancestor transform (for use in lighting)
+ * -consider depth in more complex scenarios (neg z, added shadow depth)
*/
mat4 shadowMatrix(childOp->mTransformFromCompositingAncestor);
childOp->mDisplayList->applyViewPropertyTransforms(shadowMatrix);
+ DisplayList* child = childOp->mDisplayList;
+
DisplayListOp* shadowOp = new (alloc) DrawShadowOp(shadowMatrix,
- childOp->mDisplayList->mAlpha,
- childOp->mDisplayList->getWidth(), childOp->mDisplayList->getHeight());
+ child->mAlpha, &(child->mOutline), child->mWidth, child->mHeight);
handler(shadowOp, PROPERTY_SAVECOUNT, mClipToBounds);
}
diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h
index 6d9a8c125de4..8622d619629e 100644
--- a/libs/hwui/DisplayList.h
+++ b/libs/hwui/DisplayList.h
@@ -198,6 +198,14 @@ public:
mProjectBackwards = shouldProject;
}
+ void setOutline(const SkPath* outline) {
+ if (!outline) {
+ mOutline.reset();
+ } else {
+ mOutline = *outline;
+ }
+ }
+
void setStaticMatrix(SkMatrix* matrix) {
delete mStaticMatrix;
mStaticMatrix = new SkMatrix(*matrix);
@@ -592,6 +600,7 @@ private:
bool mClipToBounds;
bool mIsolatedZVolume;
bool mProjectBackwards;
+ SkPath mOutline;
float mAlpha;
bool mHasOverlappingRendering;
float mTranslationX, mTranslationY, mTranslationZ;
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 5024880889de..20bc93d39626 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -1584,27 +1584,33 @@ private:
*/
class DrawShadowOp : public DrawOp {
public:
- DrawShadowOp(const mat4& casterTransform, float casterAlpha, float width, float height)
- : DrawOp(NULL), mCasterTransform(casterTransform), mCasterAlpha(casterAlpha),
- mWidth(width), mHeight(height) {}
+ DrawShadowOp(const mat4& transform, float alpha, const SkPath* outline,
+ float fallbackWidth, float fallbackHeight)
+ : DrawOp(NULL), mTransform(transform), mAlpha(alpha), mOutline(outline),
+ mFallbackWidth(fallbackWidth), mFallbackHeight(fallbackHeight) {}
virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
- SkPath casterOutline; // TODO: drive with path from view
- casterOutline.addRect(0, 0, mWidth, mHeight);
- return renderer.drawShadow(mCasterTransform, mCasterAlpha, &casterOutline);
+ if (!mOutline->isEmpty()) {
+ return renderer.drawShadow(mTransform, mAlpha, mOutline);
+ }
+
+ SkPath fakeOutline;
+ fakeOutline.addRect(0, 0, mFallbackWidth, mFallbackHeight);
+ return renderer.drawShadow(mTransform, mAlpha, &fakeOutline);
}
virtual void output(int level, uint32_t logFlags) const {
- OP_LOG("DrawShadow of width %.2f, height %.2f", mWidth, mHeight);
+ OP_LOG("DrawShadow of outline %p", mOutline);
}
virtual const char* name() { return "DrawShadow"; }
private:
- const mat4 mCasterTransform;
- const float mCasterAlpha;
- const float mWidth;
- const float mHeight;
+ const mat4 mTransform;
+ const float mAlpha;
+ const SkPath* mOutline;
+ const float mFallbackWidth;
+ const float mFallbackHeight;
};
class DrawLayerOp : public DrawOp {
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 7a1194870d57..b71082572ce2 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -3199,6 +3199,11 @@ status_t OpenGLRenderer::drawShadow(const mat4& casterTransform, float casterAlp
PathTessellator::approximatePathOutlineVertices(*casterOutline,
casterRefinementThresholdSquared, casterVertices2d);
+ if (casterVertices2d.size() == 0) {
+ // empty caster polygon computed from path
+ return DrawGlInfo::kStatusDone;
+ }
+
// map 2d caster poly into 3d
const int casterVertexCount = casterVertices2d.size();
Vector3 casterPolygon[casterVertexCount];