summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.xml2
-rw-r--r--core/java/android/animation/LayoutTransition.java19
-rw-r--r--core/java/android/view/DisplayList.java6
-rw-r--r--core/java/android/view/GLES20Canvas.java15
-rw-r--r--core/java/android/view/GLES20DisplayList.java14
-rw-r--r--core/java/android/view/HardwareCanvas.java23
-rw-r--r--core/java/android/view/HardwareRenderer.java29
-rw-r--r--core/java/android/view/View.java159
-rw-r--r--core/java/android/view/ViewDebug.java17
-rw-r--r--core/java/android/view/ViewGroup.java66
-rw-r--r--core/java/android/view/ViewRoot.java2
-rw-r--r--core/java/android/webkit/WebView.java34
-rw-r--r--core/java/android/widget/AbsListView.java4
-rw-r--r--core/java/android/widget/AutoCompleteTextView.java28
-rw-r--r--core/java/android/widget/HorizontalScrollView.java1
-rw-r--r--core/java/android/widget/ScrollView.java1
-rw-r--r--core/java/android/widget/TextView.java1
-rw-r--r--core/jni/android_view_GLES20Canvas.cpp13
-rw-r--r--include/utils/Functor.h33
-rw-r--r--libs/hwui/DisplayListRenderer.cpp246
-rw-r--r--libs/hwui/DisplayListRenderer.h10
-rw-r--r--libs/hwui/OpenGLDebugRenderer.cpp4
-rw-r--r--libs/hwui/OpenGLDebugRenderer.h2
-rw-r--r--libs/hwui/OpenGLRenderer.cpp12
-rw-r--r--libs/hwui/OpenGLRenderer.h8
-rwxr-xr-xmedia/java/android/media/videoeditor/MediaArtistNativeHelper.java4
-rw-r--r--packages/SystemUI/res/layout-xlarge/status_bar_notification_panel.xml1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java67
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java2
29 files changed, 669 insertions, 154 deletions
diff --git a/api/current.xml b/api/current.xml
index b3f03a6..3bcac93 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -215899,8 +215899,6 @@
deprecated="not deprecated"
visibility="public"
>
-<parameter name="visibility" type="int">
-</parameter>
</method>
<method name="getTag"
return="java.lang.Object"
diff --git a/core/java/android/animation/LayoutTransition.java b/core/java/android/animation/LayoutTransition.java
index e405df5..f13d940 100644
--- a/core/java/android/animation/LayoutTransition.java
+++ b/core/java/android/animation/LayoutTransition.java
@@ -34,15 +34,16 @@ import java.util.List;
* custom animations, use the {@link LayoutTransition#setAnimator(int, Animator)
* setAnimator()} method.
*
- * <p>One of the core concepts of these transition animations is that there are two core
+ * <p>One of the core concepts of these transition animations is that there are two types of
* changes that cause the transition and four different animations that run because of
* those changes. The changes that trigger the transition are items being added to a container
* (referred to as an "appearing" transition) or removed from a container (also known as
- * "disappearing"). The animations that run due to those events are one that animates
+ * "disappearing"). Setting the visibility of views (between GONE and VISIBLE) will trigger
+ * the same add/remove logic. The animations that run due to those events are one that animates
* items being added, one that animates items being removed, and two that animate the other
* items in the container that change due to the add/remove occurrence. Users of
* the transition may want different animations for the changing items depending on whether
- * they are changing due to anappearing or disappearing event, so there is one animation for
+ * they are changing due to an appearing or disappearing event, so there is one animation for
* each of these variations of the changing event. Most of the API of this class is concerned
* with setting up the basic properties of the animations used in these four situations,
* or with setting up custom animations for any or all of the four.</p>
@@ -62,6 +63,18 @@ import java.util.List;
* values when the transition begins. Custom animations will be similarly populated with
* the target and values being animated, assuming they use ObjectAnimator objects with
* property names that are known on the target object.</p>
+ *
+ * <p>This class, and the associated XML flag for containers, animateLayoutChanges="true",
+ * provides a simple utility meant for automating changes in straightforward situations.
+ * Using LayoutTransition at multiple levels of a nested view hierarchy may not work due to the
+ * interrelationship of the various levels of layout. Also, a container that is being scrolled
+ * at the same time as items are being added or removed is probably not a good candidate for
+ * this utility, because the before/after locations calculated by LayoutTransition
+ * may not match the actual locations when the animations finish due to the container
+ * being scrolled as the animations are running. You can work around that
+ * particular issue by disabling the 'changing' animations by setting the CHANGE_APPEARING
+ * and CHANGE_DISAPPEARING animations to null, and setting the startDelay of the
+ * other animations appropriately.</p>
*/
public class LayoutTransition {
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java
index 959fae4..4484d59 100644
--- a/core/java/android/view/DisplayList.java
+++ b/core/java/android/view/DisplayList.java
@@ -21,9 +21,11 @@ package android.view;
* them later. Display lists are usually built by recording operations on a
* {@link android.graphics.Canvas}. Replaying the operations from a display list
* avoids executing views drawing code on every frame, and is thus much more
- * efficient.
+ * efficient.
+ *
+ * @hide
*/
-abstract class DisplayList {
+public abstract class DisplayList {
/**
* Starts recording the display list. All operations performed on the
* returned canvas are recorded and stored in this display list.
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index f6c5e0b..dce1a6c 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -220,6 +220,13 @@ class GLES20Canvas extends HardwareCanvas {
private native void nAcquireContext(int renderer);
@Override
+ public boolean callDrawGLFunction(int drawGLFunction) {
+ return nCallDrawGLFunction(mRenderer, drawGLFunction);
+ }
+
+ private native boolean nCallDrawGLFunction(int renderer, int drawGLFunction);
+
+ @Override
public void releaseContext() {
if (mContextLocked) {
nReleaseContext(mRenderer);
@@ -246,11 +253,11 @@ class GLES20Canvas extends HardwareCanvas {
private static native void nDestroyDisplayList(int displayList);
@Override
- public void drawDisplayList(DisplayList displayList) {
- nDrawDisplayList(mRenderer, ((GLES20DisplayList) displayList).mNativeDisplayList);
+ public boolean drawDisplayList(DisplayList displayList) {
+ return nDrawDisplayList(mRenderer, ((GLES20DisplayList) displayList).mNativeDisplayList);
}
- private native void nDrawDisplayList(int renderer, int displayList);
+ private native boolean nDrawDisplayList(int renderer, int displayList);
///////////////////////////////////////////////////////////////////////////
// Hardware layer
@@ -306,7 +313,7 @@ class GLES20Canvas extends HardwareCanvas {
@Override
public boolean clipRect(int left, int top, int right, int bottom) {
- return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
+ return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
}
private native boolean nClipRect(int renderer, int left, int top, int right, int bottom, int op);
diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java
index e813bc9..262eb81 100644
--- a/core/java/android/view/GLES20DisplayList.java
+++ b/core/java/android/view/GLES20DisplayList.java
@@ -16,6 +16,8 @@
package android.view;
+import java.lang.ref.WeakReference;
+
/**
* An implementation of display list for OpenGL ES 2.0.
*/
@@ -27,12 +29,24 @@ class GLES20DisplayList extends DisplayList {
private boolean mValid = false;
int mNativeDisplayList;
+ WeakReference<View> hostView;
// The native display list will be destroyed when this object dies.
// DO NOT overwrite this reference once it is set.
@SuppressWarnings("unused")
private DisplayListFinalizer mFinalizer;
+ public GLES20DisplayList(View view) {
+ hostView = new WeakReference<View>(view);
+ }
+
+ public void invalidateView() {
+ View v = hostView.get();
+ if (v != null) {
+ v.invalidate();
+ }
+ }
+
@Override
HardwareCanvas start() {
if (mStarted) {
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
index 2273238..a4d36b7 100644
--- a/core/java/android/view/HardwareCanvas.java
+++ b/core/java/android/view/HardwareCanvas.java
@@ -21,9 +21,11 @@ import android.graphics.Canvas;
import android.graphics.Paint;
/**
- * Hardware accelerated canvas.
+ * Hardware accelerated canvas.
+ *
+ * @hide
*/
-abstract class HardwareCanvas extends Canvas {
+public abstract class HardwareCanvas extends Canvas {
@Override
public boolean isHardwareAccelerated() {
return true;
@@ -49,7 +51,7 @@ abstract class HardwareCanvas extends Canvas {
*
* @param displayList The display list to replay.
*/
- abstract void drawDisplayList(DisplayList displayList);
+ abstract boolean drawDisplayList(DisplayList displayList);
/**
* Draws the specified layer onto this canvas.
@@ -59,5 +61,18 @@ abstract class HardwareCanvas extends Canvas {
* @param y The top coordinate of the layer
* @param paint The paint used to draw the layer
*/
- abstract void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint);
+ abstract void drawHardwareLayer(HardwareLayer layer, float x, float y, Paint paint);
+
+ /**
+ * Calls the function specified with the drawGLFunction function pointer. This is
+ * functionality used by webkit for calling into their renderer from our display lists.
+ * This function may return true if an invalidation is needed after the call.
+ *
+ * @param drawGLFunction A native function pointer
+ * @return true if an invalidate is needed after the call, false otherwise
+ */
+ public boolean callDrawGLFunction(int drawGLFunction) {
+ // Noop - this is done in the display list recorder subclass
+ return false;
+ }
}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index addd1b3..c82184a 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -120,7 +120,7 @@ public abstract class HardwareRenderer {
*
* @return A new display list.
*/
- abstract DisplayList createDisplayList();
+ abstract DisplayList createDisplayList(View v);
/**
* Creates a new hardware layer.
@@ -506,19 +506,32 @@ public abstract class HardwareRenderer {
if (checkCurrent()) {
onPreDraw();
- Canvas canvas = mCanvas;
+ HardwareCanvas canvas = mCanvas;
+ attachInfo.mHardwareCanvas = canvas;
int saveCount = canvas.save();
callbacks.onHardwarePreDraw(canvas);
-
+
try {
- view.draw(canvas);
+ view.mRecreateDisplayList =
+ (view.mPrivateFlags & View.INVALIDATED) == View.INVALIDATED;
+ view.mPrivateFlags &= ~View.INVALIDATED;
+ DisplayList displayList = view.getDisplayList();
+ if (displayList != null) {
+ if (canvas.drawDisplayList(displayList)) {
+ view.invalidate();
+ }
+ } else {
+ // Shouldn't reach here
+ view.draw(canvas);
+ }
} finally {
callbacks.onHardwarePostDraw(canvas);
canvas.restoreToCount(saveCount);
+ view.mRecreateDisplayList = false;
}
-
+
onPostDraw();
-
+
if (ViewDebug.DEBUG_PROFILE_DRAWING) {
EventLog.writeEvent(60000, SystemClock.elapsedRealtime() - startTime);
}
@@ -704,8 +717,8 @@ public abstract class HardwareRenderer {
}
@Override
- DisplayList createDisplayList() {
- return new GLES20DisplayList();
+ DisplayList createDisplayList(View v) {
+ return new GLES20DisplayList(v);
}
@Override
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 6d5fd2c..8af2549 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1509,6 +1509,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
/*package*/ int mMeasuredHeight;
/**
+ * Flag to indicate that this view was marked INVALIDATED, or had its display list
+ * invalidated, prior to the current drawing iteration. If true, the view must re-draw
+ * its display list. This flag, used only when hw accelerated, allows us to clear the
+ * flag while retaining this information until it's needed (at getDisplayList() time and
+ * in drawChild(), when we decide to draw a view's children's display lists into our own).
+ *
+ * {@hide}
+ */
+ boolean mRecreateDisplayList = false;
+
+ /**
* The view's identifier.
* {@hide}
*
@@ -1672,6 +1683,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
static final int ACTIVATED = 0x40000000;
/**
+ * Indicates that this view was specifically invalidated, not just dirtied because some
+ * child view was invalidated. The flag is used to determine when we need to recreate
+ * a view's display list (as opposed to just returning a reference to its existing
+ * display list).
+ *
+ * @hide
+ */
+ static final int INVALIDATED = 0x80000000;
+
+ /**
* Always allow a user to over-scroll this view, provided it is a
* view that can scroll.
*
@@ -5295,6 +5316,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
if ((changed & VISIBILITY_MASK) != 0) {
if (mParent instanceof ViewGroup) {
((ViewGroup)mParent).onChildVisibilityChanged(this, (flags & VISIBILITY_MASK));
+ ((View) mParent).invalidate();
}
dispatchVisibilityChanged(this, (flags & VISIBILITY_MASK));
}
@@ -5306,6 +5328,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
if ((changed & DRAWING_CACHE_ENABLED) != 0) {
destroyDrawingCache();
mPrivateFlags &= ~DRAWING_CACHE_VALID;
+ invalidateParentIfAccelerated();
}
if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
@@ -5666,6 +5689,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mMatrixDirty = true;
mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
invalidate(false);
+ invalidateParentIfAccelerated();
}
}
@@ -5699,6 +5723,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mMatrixDirty = true;
mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
invalidate(false);
+ invalidateParentIfAccelerated();
}
}
@@ -5732,6 +5757,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mMatrixDirty = true;
mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
invalidate(false);
+ invalidateParentIfAccelerated();
}
}
@@ -5767,6 +5793,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mMatrixDirty = true;
mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
invalidate(false);
+ invalidateParentIfAccelerated();
}
}
@@ -5802,6 +5829,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mMatrixDirty = true;
mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
invalidate(false);
+ invalidateParentIfAccelerated();
}
}
@@ -5843,6 +5871,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mMatrixDirty = true;
mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
invalidate(false);
+ invalidateParentIfAccelerated();
}
}
@@ -5883,6 +5912,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mMatrixDirty = true;
mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
invalidate(false);
+ invalidateParentIfAccelerated();
}
}
@@ -5922,6 +5952,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mPrivateFlags &= ~ALPHA_SET;
invalidate(false);
}
+ invalidateParentIfAccelerated();
}
/**
@@ -6241,6 +6272,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mMatrixDirty = true;
mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
invalidate(false);
+ invalidateParentIfAccelerated();
}
}
@@ -6274,6 +6306,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mMatrixDirty = true;
mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
invalidate(false);
+ invalidateParentIfAccelerated();
}
}
@@ -6490,6 +6523,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
int oldY = mScrollY;
mScrollX = x;
mScrollY = y;
+ invalidateParentIfAccelerated();
onScrollChanged(mScrollX, mScrollY, oldX, oldY);
if (!awakenScrollBars()) {
invalidate();
@@ -6690,8 +6724,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
}
if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
- (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {
+ (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
+ (mPrivateFlags & INVALIDATED) != INVALIDATED) {
mPrivateFlags &= ~DRAWING_CACHE_VALID;
+ mPrivateFlags |= INVALIDATED;
final ViewParent p = mParent;
final AttachInfo ai = mAttachInfo;
if (p != null && ai != null && ai.mHardwareAccelerated) {
@@ -6728,8 +6764,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
}
if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
- (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {
+ (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID ||
+ (mPrivateFlags & INVALIDATED) != INVALIDATED) {
mPrivateFlags &= ~DRAWING_CACHE_VALID;
+ mPrivateFlags |= INVALIDATED;
final ViewParent p = mParent;
final AttachInfo ai = mAttachInfo;
if (p != null && ai != null && ai.mHardwareAccelerated) {
@@ -6776,10 +6814,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
boolean opaque = isOpaque();
if ((mPrivateFlags & (DRAWN | HAS_BOUNDS)) == (DRAWN | HAS_BOUNDS) ||
(invalidateCache && (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) ||
- opaque != mLastIsOpaque) {
+ opaque != mLastIsOpaque || (mPrivateFlags & INVALIDATED) != INVALIDATED) {
mLastIsOpaque = opaque;
mPrivateFlags &= ~DRAWN;
if (invalidateCache) {
+ mPrivateFlags |= INVALIDATED;
mPrivateFlags &= ~DRAWING_CACHE_VALID;
}
final AttachInfo ai = mAttachInfo;
@@ -6802,6 +6841,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
}
/**
+ * Used to indicate that the parent of this view should be invalidated. This functionality
+ * is used to force the parent to rebuild its display list (when hardware-accelerated),
+ * which is necessary when various parent-managed properties of the view change, such as
+ * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y.
+ *
+ * @hide
+ */
+ protected void invalidateParentIfAccelerated() {
+ if (isHardwareAccelerated() && mParent instanceof View) {
+ ((View) mParent).invalidate();
+ }
+ }
+
+ /**
* Indicates whether this View is opaque. An opaque View guarantees that it will
* draw all the pixels overlapping its bounds using a fully opaque color.
*
@@ -7630,6 +7683,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mHardwareLayer = null;
}
+ if (mDisplayList != null) {
+ mDisplayList.invalidate();
+ }
+
if (mAttachInfo != null) {
mAttachInfo.mHandler.removeMessages(AttachInfo.INVALIDATE_MSG, this);
mAttachInfo.mHandler.removeMessages(AttachInfo.INVALIDATE_RECT_MSG, this);
@@ -7953,7 +8010,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
+ "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
}
-
+
if (layerType == mLayerType) {
if (layerType != LAYER_TYPE_NONE && paint != mLayerPaint) {
mLayerPaint = paint == null ? new Paint() : paint;
@@ -8041,7 +8098,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mHardwareLayer.resize(width, height);
}
- final HardwareCanvas canvas = mHardwareLayer.start(currentCanvas);
+ final HardwareCanvas canvas = mHardwareLayer.start(mAttachInfo.mHardwareCanvas);
try {
canvas.setViewport(width, height);
canvas.onPreDraw();
@@ -8064,7 +8121,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
canvas.restoreToCount(restoreCount);
} finally {
canvas.onPostDraw();
- mHardwareLayer.end(currentCanvas);
+ mHardwareLayer.end(mAttachInfo.mHardwareCanvas);
}
}
@@ -8081,9 +8138,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
*
* <p>Enabling the drawing cache is similar to
* {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
- * acceleration is turned off. When hardware acceleration is turned on enabling the
- * drawing cache has either no effect or the cache used at drawing time is not a bitmap.
- * This API can however be used to manually generate a bitmap copy of this view.</p>
+ * acceleration is turned off. When hardware acceleration is turned on, enabling the
+ * drawing cache has no effect on rendering because the system uses a different mechanism
+ * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
+ * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
+ * for information on how to enable software and hardware layers.</p>
+ *
+ * <p>This API can be used to manually generate
+ * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
+ * {@link #getDrawingCache()}.</p>
*
* @param enabled true to enable the drawing cache, false otherwise
*
@@ -8110,25 +8173,76 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
}
/**
+ * Debugging utility which recursively outputs the dirty state of a view and its
+ * descendants.
+ *
+ * @hide
+ */
+ public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
+ Log.d("View", indent + this + " DIRTY(" + (mPrivateFlags & View.DIRTY_MASK) +
+ ") DRAWN(" + (mPrivateFlags & DRAWN) + ")" + " CACHE_VALID(" +
+ (mPrivateFlags & View.DRAWING_CACHE_VALID) +
+ ") INVALIDATED(" + (mPrivateFlags & INVALIDATED) + ")");
+ if (clear) {
+ mPrivateFlags &= clearMask;
+ }
+ if (this instanceof ViewGroup) {
+ ViewGroup parent = (ViewGroup) this;
+ final int count = parent.getChildCount();
+ for (int i = 0; i < count; i++) {
+ final View child = (View) parent.getChildAt(i);
+ child.outputDirtyFlags(indent + " ", clear, clearMask);
+ }
+ }
+ }
+
+ /**
+ * This method is used by ViewGroup to cause its children to restore or recreate their
+ * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
+ * to recreate its own display list, which would happen if it went through the normal
+ * draw/dispatchDraw mechanisms.
+ *
+ * @hide
+ */
+ protected void dispatchGetDisplayList() {}
+
+ /**
* <p>Returns a display list that can be used to draw this view again
* without executing its draw method.</p>
*
* @return A DisplayList ready to replay, or null if caching is not enabled.
+ *
+ * @hide
*/
- DisplayList getDisplayList() {
- if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
- return null;
- }
+ public DisplayList getDisplayList() {
if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
return null;
}
- if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED &&
- ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 ||
- mDisplayList == null || !mDisplayList.isValid())) {
+ if (((mPrivateFlags & DRAWING_CACHE_VALID) == 0 ||
+ mDisplayList == null || !mDisplayList.isValid() ||
+ mRecreateDisplayList)) {
+ // Don't need to recreate the display list, just need to tell our
+ // children to restore/recreate theirs
+ if (mDisplayList != null && mDisplayList.isValid() &&
+ !mRecreateDisplayList) {
+ mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
+ mPrivateFlags &= ~DIRTY_MASK;
+ dispatchGetDisplayList();
+
+ return mDisplayList;
+ }
+
+ // If we got here, we're recreating it. Mark it as such to ensure that
+ // we copy in child display lists into ours in drawChild()
+ mRecreateDisplayList = true;
if (mDisplayList == null) {
- mDisplayList = mAttachInfo.mHardwareRenderer.createDisplayList();
+ mDisplayList = mAttachInfo.mHardwareRenderer.createDisplayList(this);
+ // If we're creating a new display list, make sure our parent gets invalidated
+ // since they will need to recreate their display list to account for this
+ // new child display list.
+ invalidateParentIfAccelerated();
}
final HardwareCanvas canvas = mDisplayList.start();
@@ -8141,6 +8255,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
final int restoreCount = canvas.save();
+ computeScroll();
+ canvas.translate(-mScrollX, -mScrollY);
mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
// Fast path for layouts with no backgrounds
@@ -8229,9 +8345,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mUnscaledDrawingCache.recycle();
mUnscaledDrawingCache = null;
}
- if (mDisplayList != null) {
- mDisplayList.invalidate();
- }
}
/**
@@ -10480,6 +10593,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
animation.setStartTime(Animation.START_ON_FIRST_FRAME);
setAnimation(animation);
invalidate();
+ invalidateParentIfAccelerated();
}
/**
@@ -10490,6 +10604,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
mCurrentAnimation.detach();
}
mCurrentAnimation = null;
+ invalidateParentIfAccelerated();
}
/**
@@ -10660,7 +10775,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
/**
* Returns the status bar visibility that this view has requested.
*/
- public int getSystemUiVisibility(int visibility) {
+ public int getSystemUiVisibility() {
return mSystemUiVisibility;
}
@@ -11495,6 +11610,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
final Callbacks mRootCallbacks;
+ Canvas mHardwareCanvas;
+
/**
* The top view of the hierarchy.
*/
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index d5c440c..c19a107 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -998,22 +998,27 @@ public class ViewDebug {
new ViewOperation<Object>() {
public Object[] pre() {
final DisplayMetrics metrics =
- view.getResources().getDisplayMetrics();
- final Bitmap bitmap =
+ (view != null && view.getResources() != null) ?
+ view.getResources().getDisplayMetrics() : null;
+ final Bitmap bitmap = metrics != null ?
Bitmap.createBitmap(metrics.widthPixels,
- metrics.heightPixels, Bitmap.Config.RGB_565);
- final Canvas canvas = new Canvas(bitmap);
+ metrics.heightPixels, Bitmap.Config.RGB_565) : null;
+ final Canvas canvas = bitmap != null ? new Canvas(bitmap) : null;
return new Object[] {
bitmap, canvas
};
}
public void run(Object... data) {
- view.draw((Canvas) data[1]);
+ if (data[1] != null) {
+ view.draw((Canvas) data[1]);
+ }
}
public void post(Object... data) {
- ((Bitmap) data[0]).recycle();
+ if (data[0] != null) {
+ ((Bitmap) data[0]).recycle();
+ }
}
}) : 0;
out.write(String.valueOf(durationMeasure));
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index d6c8ad6..c73cbe6 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2206,6 +2206,27 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
/**
+ * This method is used to cause children of this ViewGroup to restore or recreate their
+ * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
+ * to recreate its own display list, which would happen if it went through the normal
+ * draw/dispatchDraw mechanisms.
+ *
+ * @hide
+ */
+ @Override
+ protected void dispatchGetDisplayList() {
+ final int count = mChildrenCount;
+ final View[] children = mChildren;
+ for (int i = 0; i < count; i++) {
+ final View child = children[i];
+ child.mRecreateDisplayList = (child.mPrivateFlags & INVALIDATED) == INVALIDATED;
+ child.mPrivateFlags &= ~INVALIDATED;
+ child.getDisplayList();
+ child.mRecreateDisplayList = false;
+ }
+ }
+
+ /**
* Draw one child of this View Group. This method is responsible for getting
* the canvas in the right state. This includes clipping, translating so
* that the child's scrolled origin is at 0, 0, and applying any animation
@@ -2247,7 +2268,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
caching = true;
if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
} else {
- caching = layerType != LAYER_TYPE_NONE;
+ caching = (layerType != LAYER_TYPE_NONE) || canvas.isHardwareAccelerated();
}
if (a != null) {
@@ -2329,6 +2350,13 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
return more;
}
+ if (canvas.isHardwareAccelerated()) {
+ // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
+ // retain the flag's value temporarily in the mRecreateDisplayList flag
+ child.mRecreateDisplayList = (child.mPrivateFlags & INVALIDATED) == INVALIDATED;
+ child.mPrivateFlags &= ~INVALIDATED;
+ }
+
child.computeScroll();
final int sx = child.mScrollX;
@@ -2347,7 +2375,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
if (layerType == LAYER_TYPE_SOFTWARE) {
child.buildDrawingCache(true);
cache = child.getDrawingCache(true);
- } else {
+ } else if (layerType == LAYER_TYPE_NONE) {
displayList = child.getDisplayList();
}
}
@@ -2357,7 +2385,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final boolean hasNoCache = cache == null || hasDisplayList;
final int restoreTo = canvas.save();
- if (hasNoCache) {
+ if (cache == null && !hasDisplayList) {
canvas.translate(cl - sx, ct - sy);
} else {
canvas.translate(cl, ct);
@@ -2375,7 +2403,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
int transX = 0;
int transY = 0;
- if (hasNoCache) {
+ if (cache == null && !hasDisplayList) {
transX = -sx;
transY = -sy;
}
@@ -2435,10 +2463,10 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
if ((flags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN) {
- if (hasNoCache) {
+ if (cache == null && !hasDisplayList) {
canvas.clipRect(sx, sy, sx + (cr - cl), sy + (cb - ct));
} else {
- if (!scalingRequired) {
+ if (!scalingRequired || cache == null) {
canvas.clipRect(0, 0, cr - cl, cb - ct);
} else {
canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
@@ -2473,7 +2501,11 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
} else {
child.mPrivateFlags &= ~DIRTY_MASK;
- ((HardwareCanvas) canvas).drawDisplayList(displayList);
+ // Skip drawing the display list into ours if we were just refreshing
+ // it's content; we already have a reference to it in our display list
+ if (mRecreateDisplayList || mLayerType != LAYER_TYPE_NONE) {
+ ((HardwareCanvas) canvas).drawDisplayList(displayList);
+ }
}
}
} else if (cache != null) {
@@ -2503,6 +2535,15 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
finishAnimatingView(child, a);
}
+ if (more && canvas.isHardwareAccelerated()) {
+ // invalidation is the trigger to recreate display lists, so if we're using
+ // display lists to render, force an invalidate to allow the animation to
+ // continue drawing another frame
+ invalidate();
+ }
+
+ child.mRecreateDisplayList = false;
+
return more;
}
@@ -2743,7 +2784,6 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
// addViewInner() will call child.requestLayout() when setting the new LayoutParams
// therefore, we call requestLayout() on ourselves before, so that the child's request
// will be blocked at our level
- child.mPrivateFlags &= ~DIRTY_MASK;
requestLayout();
invalidate();
addViewInner(child, index, params, false);
@@ -3425,10 +3465,20 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
final boolean drawAnimation = (child.mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION;
if (dirty == null) {
+ if (child.mLayerType != LAYER_TYPE_NONE) {
+ mPrivateFlags |= INVALIDATED;
+ mPrivateFlags &= ~DRAWING_CACHE_VALID;
+ }
do {
View view = null;
if (parent instanceof View) {
view = (View) parent;
+ if (view.mLayerType != LAYER_TYPE_NONE &&
+ view.getParent() instanceof View) {
+ final View grandParent = (View) view.getParent();
+ grandParent.mPrivateFlags |= INVALIDATED;
+ grandParent.mPrivateFlags &= ~DRAWING_CACHE_VALID;
+ }
if ((view.mPrivateFlags & DIRTY_MASK) != 0) {
// already marked dirty - we're done
break;
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index d932141..ba671c0 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -597,7 +597,7 @@ public final class ViewRoot extends Handler implements ViewParent,
dirty.inset(-1, -1);
}
}
- if (!mDirty.isEmpty()) {
+ if (!mDirty.isEmpty() && !mDirty.contains(dirty)) {
mAttachInfo.mIgnoreDirtyState = true;
}
mDirty.union(dirty);
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 3102ee9..83061ec 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -16,6 +16,7 @@
package android.webkit;
+import android.view.HardwareCanvas;
import com.android.internal.R;
import android.annotation.Widget;
@@ -353,7 +354,7 @@ public class WebView extends AbsoluteLayout
private ZoomManager mZoomManager;
- private Rect mGLRectViewport;
+ private Rect mGLRectViewport = new Rect();
/**
* Transportation object for returning WebView across thread boundaries.
@@ -4079,20 +4080,8 @@ public class WebView extends AbsoluteLayout
}
if (canvas.isHardwareAccelerated()) {
- try {
- if (canvas.acquireContext()) {
- Rect rect = new Rect(mGLRectViewport.left,
- mGLRectViewport.top,
- mGLRectViewport.right,
- mGLRectViewport.bottom
- - getVisibleTitleHeight());
- if (nativeDrawGL(rect, getScale(), extras)) {
- invalidate();
- }
- }
- } finally {
- canvas.releaseContext();
- }
+ int functor = nativeGetDrawGLFunction(mGLRectViewport, getScale(), extras);
+ ((HardwareCanvas) canvas).callDrawGLFunction(functor);
} else {
DrawFilter df = null;
if (mZoomManager.isZoomAnimating() || UIAnimationsRunning) {
@@ -5163,7 +5152,6 @@ public class WebView extends AbsoluteLayout
if (mNativeClass != 0) {
nativeRecordButtons(false, false, true);
}
- setFocusControllerActive(false);
}
mGotKeyDown = false;
}
@@ -5173,18 +5161,16 @@ public class WebView extends AbsoluteLayout
void setGLRectViewport() {
// Use the getGlobalVisibleRect() to get the intersection among the parents
- Rect webViewRect = new Rect();
- boolean visible = getGlobalVisibleRect(webViewRect);
+ getGlobalVisibleRect(mGLRectViewport);
// Then need to invert the Y axis, just for GL
View rootView = getRootView();
int rootViewHeight = rootView.getHeight();
- int savedWebViewBottom = webViewRect.bottom;
- webViewRect.bottom = rootViewHeight - webViewRect.top;
- webViewRect.top = rootViewHeight - savedWebViewBottom;
+ int savedWebViewBottom = mGLRectViewport.bottom;
+ mGLRectViewport.bottom = rootViewHeight - mGLRectViewport.top - getVisibleTitleHeight();
+ mGLRectViewport.top = rootViewHeight - savedWebViewBottom;
- // Store the viewport
- mGLRectViewport = webViewRect;
+ nativeUpdateDrawGLFunction(mGLRectViewport);
}
/**
@@ -8239,6 +8225,8 @@ public class WebView extends AbsoluteLayout
boolean splitIfNeeded);
private native void nativeDumpDisplayTree(String urlOrNull);
private native boolean nativeEvaluateLayersAnimations();
+ private native int nativeGetDrawGLFunction(Rect rect, float scale, int extras);
+ private native void nativeUpdateDrawGLFunction(Rect rect);
private native boolean nativeDrawGL(Rect rect, float scale, int extras);
private native void nativeExtendSelection(int x, int y);
private native int nativeFindAll(String findLower, String findUpper,
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 665f9e7..fc5c893 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2357,6 +2357,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
if (mScrollY != 0) {
mScrollY = 0;
+ invalidateParentIfAccelerated();
finishGlows();
invalidate();
}
@@ -2733,6 +2734,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
if (mScrollY != 0) {
mScrollY = 0;
+ invalidateParentIfAccelerated();
finishGlows();
invalidate();
}
@@ -2951,6 +2953,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
// Coming back to 'real' list scrolling
incrementalDeltaY = -newScroll;
mScrollY = 0;
+ invalidateParentIfAccelerated();
// No need to do all this work if we're not going to move anyway
if (incrementalDeltaY != 0) {
@@ -3244,6 +3247,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
protected void onOverScrolled(int scrollX, int scrollY,
boolean clampedX, boolean clampedY) {
mScrollY = scrollY;
+ invalidateParentIfAccelerated();
if (clampedY) {
// Velocity is broken by hitting the limit; don't start a fling off of this.
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index 707b92d..e8ce4e9 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -116,6 +116,10 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
// Set to true when text is set directly and no filtering shall be performed
private boolean mBlockCompletion;
+ // When set, an update in the underlying adapter will update the result list popup.
+ // Set to false when the list is hidden to prevent asynchronous updates to popup the list again.
+ private boolean mPopupCanBeUpdated = true;
+
private PassThroughClickListener mPassThroughClickListener;
private PopupDataSetObserver mObserver;
@@ -722,21 +726,20 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
return;
}
- updateList();
- }
-
- private void updateList() {
// the drop down is shown only when a minimum number of characters
// was typed in the text view
if (enoughToFilter()) {
if (mFilter != null) {
+ mPopupCanBeUpdated = true;
performFiltering(getText(), mLastKeyCode);
buildImeCompletions();
}
} else {
// drop down is automatically dismissed when enough characters
// are deleted from the text view
- if (!mPopup.isDropDownAlwaysVisible()) dismissDropDown();
+ if (!mPopup.isDropDownAlwaysVisible()) {
+ dismissDropDown();
+ }
if (mFilter != null) {
mFilter.filter(null);
}
@@ -908,10 +911,10 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
/** {@inheritDoc} */
public void onFilterComplete(int count) {
- updateDropDownForFilter(count, true);
+ updateDropDownForFilter(count);
}
- private void updateDropDownForFilter(int count, boolean forceShow) {
+ private void updateDropDownForFilter(int count) {
// Not attached to window, don't update drop-down
if (getWindowVisibility() == View.GONE) return;
@@ -924,11 +927,15 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
final boolean dropDownAlwaysVisible = mPopup.isDropDownAlwaysVisible();
if ((count > 0 || dropDownAlwaysVisible) && enoughToFilter()) {
- if (hasFocus() && hasWindowFocus() && (forceShow || isPopupShowing())) {
+ if (hasFocus() && hasWindowFocus() && mPopupCanBeUpdated) {
showDropDown();
}
- } else if (!dropDownAlwaysVisible) {
+ } else if (!dropDownAlwaysVisible && isPopupShowing()) {
dismissDropDown();
+ // When the filter text is changed, the first update from the adapter may show an empty
+ // count (when the query is being performed on the network). Future updates when some
+ // content has been retrieved should still be able to update the list.
+ mPopupCanBeUpdated = true;
}
}
@@ -984,6 +991,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
imm.displayCompletions(this, null);
}
mPopup.dismiss();
+ mPopupCanBeUpdated = false;
}
@Override
@@ -1194,7 +1202,7 @@ public class AutoCompleteTextView extends EditText implements Filter.FilterListe
if (adapter != null) {
// This will re-layout, thus resetting mDataChanged, so that the
// listView click listener stays responsive
- updateDropDownForFilter(adapter.getCount(), false);
+ updateDropDownForFilter(adapter.getCount());
}
}
});
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index db22a0c..ff6677f 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -647,6 +647,7 @@ public class HorizontalScrollView extends FrameLayout {
if (!mScroller.isFinished()) {
mScrollX = scrollX;
mScrollY = scrollY;
+ invalidateParentIfAccelerated();
if (clampedX) {
mScroller.springBack(mScrollX, mScrollY, 0, getScrollRange(), 0, 0);
}
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index ce6da72..fc049cc 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -644,6 +644,7 @@ public class ScrollView extends FrameLayout {
if (!mScroller.isFinished()) {
mScrollX = scrollX;
mScrollY = scrollY;
+ invalidateParentIfAccelerated();
if (clampedY) {
mScroller.springBack(mScrollX, mScrollY, 0, 0, 0, getScrollRange());
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index aac57ed..a0a615a 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -6272,6 +6272,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
if (mScroller.computeScrollOffset()) {
mScrollX = mScroller.getCurrX();
mScrollY = mScroller.getCurrY();
+ invalidateParentIfAccelerated();
postInvalidate(); // So we draw again
}
}
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 8d074af..e4a89d7 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -117,6 +117,11 @@ static void android_view_GLES20Canvas_acquireContext(JNIEnv* env, jobject canvas
renderer->acquireContext();
}
+static bool android_view_GLES20Canvas_callDrawGLFunction(JNIEnv* env, jobject canvas,
+ OpenGLRenderer* renderer, Functor *functor) {
+ return renderer->callDrawGLFunction(functor);
+}
+
static void android_view_GLES20Canvas_releaseContext(JNIEnv* env, jobject canvas,
OpenGLRenderer* renderer) {
renderer->releaseContext();
@@ -482,9 +487,9 @@ static void android_view_GLES20Canvas_destroyDisplayList(JNIEnv* env,
delete displayList;
}
-static void android_view_GLES20Canvas_drawDisplayList(JNIEnv* env,
+static bool android_view_GLES20Canvas_drawDisplayList(JNIEnv* env,
jobject canvas, OpenGLRenderer* renderer, DisplayList* displayList) {
- renderer->drawDisplayList(displayList);
+ return renderer->drawDisplayList(displayList);
}
// ----------------------------------------------------------------------------
@@ -577,6 +582,8 @@ static JNINativeMethod gMethods[] = {
{ "nPrepare", "(IZ)V", (void*) android_view_GLES20Canvas_prepare },
{ "nFinish", "(I)V", (void*) android_view_GLES20Canvas_finish },
{ "nAcquireContext", "(I)V", (void*) android_view_GLES20Canvas_acquireContext },
+ { "nCallDrawGLFunction", "(II)Z",
+ (void*) android_view_GLES20Canvas_callDrawGLFunction },
{ "nReleaseContext", "(I)V", (void*) android_view_GLES20Canvas_releaseContext },
{ "nSave", "(II)I", (void*) android_view_GLES20Canvas_save },
@@ -639,7 +646,7 @@ static JNINativeMethod gMethods[] = {
{ "nGetDisplayList", "(I)I", (void*) android_view_GLES20Canvas_getDisplayList },
{ "nDestroyDisplayList", "(I)V", (void*) android_view_GLES20Canvas_destroyDisplayList },
{ "nGetDisplayListRenderer", "(I)I", (void*) android_view_GLES20Canvas_getDisplayListRenderer },
- { "nDrawDisplayList", "(II)V", (void*) android_view_GLES20Canvas_drawDisplayList },
+ { "nDrawDisplayList", "(II)Z", (void*) android_view_GLES20Canvas_drawDisplayList },
{ "nInterrupt", "(I)V", (void*) android_view_GLES20Canvas_interrupt },
{ "nResume", "(I)V", (void*) android_view_GLES20Canvas_resume },
diff --git a/include/utils/Functor.h b/include/utils/Functor.h
new file mode 100644
index 0000000..3955bc3
--- /dev/null
+++ b/include/utils/Functor.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_FUNCTOR_H
+#define ANDROID_FUNCTOR_H
+
+#include <utils/Errors.h>
+
+namespace android {
+
+class Functor {
+public:
+ Functor() {}
+ virtual ~Functor() {}
+ virtual status_t operator ()() { return true; }
+};
+
+}; // namespace android
+
+#endif // ANDROID_FUNCTOR_H
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index ffd3be4..a768efe 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -117,7 +117,8 @@ const char* DisplayList::OP_NAMES[] = {
"ResetColorFilter",
"SetupColorFilter",
"ResetShadow",
- "SetupShadow"
+ "SetupShadow",
+ "DrawGLFunction"
};
DisplayList::DisplayList(const DisplayListRenderer& recorder) {
@@ -212,7 +213,8 @@ void DisplayList::init() {
mPathHeap = NULL;
}
-void DisplayList::replay(OpenGLRenderer& renderer, uint32_t level) {
+bool DisplayList::replay(OpenGLRenderer& renderer, uint32_t level) {
+ bool needsInvalidate = false;
TextContainer text;
mReader.rewind();
@@ -229,87 +231,165 @@ void DisplayList::replay(OpenGLRenderer& renderer, uint32_t level) {
int saveCount = renderer.getSaveCount() - 1;
while (!mReader.eof()) {
int op = mReader.readInt();
- DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
switch (op) {
+ case DrawGLFunction: {
+ Functor *functor = (Functor *) getInt();
+ DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], functor);
+ needsInvalidate |= renderer.callDrawGLFunction(functor);
+ }
+ break;
case AcquireContext: {
+ DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
renderer.acquireContext();
}
break;
case ReleaseContext: {
+ DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
renderer.releaseContext();
}
break;
case Save: {
- renderer.save(getInt());
+ int rendererNum = getInt();
+ DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, OP_NAMES[op], rendererNum);
+ renderer.save(rendererNum);
}
break;
case Restore: {
+ DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
renderer.restore();
}
break;
case RestoreToCount: {
- renderer.restoreToCount(saveCount + getInt());
+ int restoreCount = saveCount + getInt();
+ DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, OP_NAMES[op], restoreCount);
+ renderer.restoreToCount(restoreCount);
}
break;
case SaveLayer: {
- renderer.saveLayer(getFloat(), getFloat(), getFloat(), getFloat(),
- getPaint(), getInt());
+ float f1 = getFloat();
+ float f2 = getFloat();
+ float f3 = getFloat();
+ float f4 = getFloat();
+ SkPaint* paint = getPaint();
+ int flags = getInt();
+ DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p, 0x%x", (char*) indent,
+ OP_NAMES[op], f1, f2, f3, f4, paint, flags);
+ renderer.saveLayer(f1, f2, f3, f4, paint, flags);
}
break;
case SaveLayerAlpha: {
- renderer.saveLayerAlpha(getFloat(), getFloat(), getFloat(), getFloat(),
- getInt(), getInt());
+ float f1 = getFloat();
+ float f2 = getFloat();
+ float f3 = getFloat();
+ float f4 = getFloat();
+ int alpha = getInt();
+ int flags = getInt();
+ DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", (char*) indent,
+ OP_NAMES[op], f1, f2, f3, f4, alpha, flags);
+ renderer.saveLayerAlpha(f1, f2, f3, f4, alpha, flags);
}
break;
case Translate: {
- renderer.translate(getFloat(), getFloat());
+ float f1 = getFloat();
+ float f2 = getFloat();
+ DISPLAY_LIST_LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], f1, f2);
+ renderer.translate(f1, f2);
}
break;
case Rotate: {
- renderer.rotate(getFloat());
+ float rotation = getFloat();
+ DISPLAY_LIST_LOGD("%s%s %.2f", (char*) indent, OP_NAMES[op], rotation);
+ renderer.rotate(rotation);
}
break;
case Scale: {
- renderer.scale(getFloat(), getFloat());
+ float sx = getFloat();
+ float sy = getFloat();
+ DISPLAY_LIST_LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], sx, sy);
+ renderer.scale(sx, sy);
}
break;
case Skew: {
- renderer.skew(getFloat(), getFloat());
+ float sx = getFloat();
+ float sy = getFloat();
+ DISPLAY_LIST_LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], sx, sy);
+ renderer.skew(sx, sy);
}
break;
case SetMatrix: {
- renderer.setMatrix(getMatrix());
+ SkMatrix* matrix = getMatrix();
+ DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], matrix);
+ renderer.setMatrix(matrix);
}
break;
case ConcatMatrix: {
- renderer.concatMatrix(getMatrix());
+ SkMatrix* matrix = getMatrix();
+ DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], matrix);
+ renderer.concatMatrix(matrix);
}
break;
case ClipRect: {
- renderer.clipRect(getFloat(), getFloat(), getFloat(), getFloat(),
- (SkRegion::Op) getInt());
+ float f1 = getFloat();
+ float f2 = getFloat();
+ float f3 = getFloat();
+ float f4 = getFloat();
+ int regionOp = getInt();
+ DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d", (char*) indent, OP_NAMES[op],
+ f1, f2, f3, f4, regionOp);
+ renderer.clipRect(f1, f2, f3, f4, (SkRegion::Op) regionOp);
}
break;
case DrawDisplayList: {
- renderer.drawDisplayList(getDisplayList(), level + 1);
+ DisplayList* displayList = getDisplayList();
+ DISPLAY_LIST_LOGD("%s%s %p, %d", (char*) indent, OP_NAMES[op],
+ displayList, level + 1);
+ needsInvalidate |= renderer.drawDisplayList(displayList, level + 1);
}
break;
case DrawLayer: {
- renderer.drawLayer((Layer*) getInt(), getFloat(), getFloat(), getPaint());
+ Layer* layer = (Layer*) getInt();
+ float x = getFloat();
+ float y = getFloat();
+ SkPaint* paint = getPaint();
+ DISPLAY_LIST_LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
+ layer, x, y, paint);
+ renderer.drawLayer(layer, x, y, paint);
}
break;
case DrawBitmap: {
- renderer.drawBitmap(getBitmap(), getFloat(), getFloat(), getPaint());
+ SkBitmap* bitmap = getBitmap();
+ float x = getFloat();
+ float y = getFloat();
+ SkPaint* paint = getPaint();
+ DISPLAY_LIST_LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
+ bitmap, x, y, paint);
+ renderer.drawBitmap(bitmap, x, y, paint);
}
break;
case DrawBitmapMatrix: {
- renderer.drawBitmap(getBitmap(), getMatrix(), getPaint());
+ SkBitmap* bitmap = getBitmap();
+ SkMatrix* matrix = getMatrix();
+ SkPaint* paint = getPaint();
+ DISPLAY_LIST_LOGD("%s%s %p, %p, %p", (char*) indent, OP_NAMES[op],
+ bitmap, matrix, paint);
+ renderer.drawBitmap(bitmap, matrix, paint);
}
break;
case DrawBitmapRect: {
- renderer.drawBitmap(getBitmap(), getFloat(), getFloat(), getFloat(), getFloat(),
- getFloat(), getFloat(), getFloat(), getFloat(), getPaint());
+ SkBitmap* bitmap = getBitmap();
+ float f1 = getFloat();
+ float f2 = getFloat();
+ float f3 = getFloat();
+ float f4 = getFloat();
+ float f5 = getFloat();
+ float f6 = getFloat();
+ float f7 = getFloat();
+ float f8 = getFloat();
+ SkPaint* paint = getPaint();
+ DISPLAY_LIST_LOGD("%s%s %p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p",
+ (char*) indent, OP_NAMES[op], bitmap, f1, f2, f3, f4, f5, f6, f7, f8, paint);
+ renderer.drawBitmap(bitmap, f1, f2, f3, f4, f5, f6, f7, f8, paint);
}
break;
case DrawBitmapMesh: {
@@ -323,6 +403,7 @@ void DisplayList::replay(OpenGLRenderer& renderer, uint32_t level) {
bool hasColors = getInt();
int* colors = hasColors ? getInts(colorsCount) : NULL;
+ DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
renderer.drawBitmapMesh(bitmap, meshWidth, meshHeight, vertices, colors, getPaint());
}
break;
@@ -340,80 +421,148 @@ void DisplayList::replay(OpenGLRenderer& renderer, uint32_t level) {
yDivs = getInts(yDivsCount);
colors = getUInts(numColors);
+ DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
renderer.drawPatch(bitmap, xDivs, yDivs, colors, xDivsCount, yDivsCount,
numColors, getFloat(), getFloat(), getFloat(), getFloat(), getPaint());
}
break;
case DrawColor: {
- renderer.drawColor(getInt(), (SkXfermode::Mode) getInt());
+ int color = getInt();
+ int xferMode = getInt();
+ DISPLAY_LIST_LOGD("%s%s 0x%x %d", (char*) indent, OP_NAMES[op], color, xferMode);
+ renderer.drawColor(color, (SkXfermode::Mode) xferMode);
}
break;
case DrawRect: {
- renderer.drawRect(getFloat(), getFloat(), getFloat(), getFloat(), getPaint());
+ float f1 = getFloat();
+ float f2 = getFloat();
+ float f3 = getFloat();
+ float f4 = getFloat();
+ SkPaint* paint = getPaint();
+ DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
+ f1, f2, f3, f4, paint);
+ renderer.drawRect(f1, f2, f3, f4, paint);
}
break;
case DrawRoundRect: {
- renderer.drawRoundRect(getFloat(), getFloat(), getFloat(), getFloat(),
- getFloat(), getFloat(), getPaint());
+ float f1 = getFloat();
+ float f2 = getFloat();
+ float f3 = getFloat();
+ float f4 = getFloat();
+ float f5 = getFloat();
+ float f6 = getFloat();
+ SkPaint* paint = getPaint();
+ DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p",
+ (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, paint);
+ renderer.drawRoundRect(f1, f2, f3, f4, f5, f6, paint);
}
break;
case DrawCircle: {
- renderer.drawCircle(getFloat(), getFloat(), getFloat(), getPaint());
+ float f1 = getFloat();
+ float f2 = getFloat();
+ float f3 = getFloat();
+ SkPaint* paint = getPaint();
+ DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %p",
+ (char*) indent, OP_NAMES[op], f1, f2, f3, paint);
+ renderer.drawCircle(f1, f2, f3, paint);
}
break;
case DrawOval: {
- renderer.drawOval(getFloat(), getFloat(), getFloat(), getFloat(), getPaint());
+ float f1 = getFloat();
+ float f2 = getFloat();
+ float f3 = getFloat();
+ float f4 = getFloat();
+ SkPaint* paint = getPaint();
+ DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p",
+ (char*) indent, OP_NAMES[op], f1, f2, f3, f4, paint);
+ renderer.drawOval(f1, f2, f3, f4, paint);
}
break;
case DrawArc: {
- renderer.drawArc(getFloat(), getFloat(), getFloat(), getFloat(),
- getFloat(), getFloat(), getInt() == 1, getPaint());
+ float f1 = getFloat();
+ float f2 = getFloat();
+ float f3 = getFloat();
+ float f4 = getFloat();
+ float f5 = getFloat();
+ float f6 = getFloat();
+ int i1 = getInt();
+ SkPaint* paint = getPaint();
+ DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %d, %p",
+ (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, i1, paint);
+ renderer.drawArc(f1, f2, f3, f4, f5, f6, i1 == 1, paint);
}
break;
case DrawPath: {
- renderer.drawPath(getPath(), getPaint());
+ SkPath* path = getPath();
+ SkPaint* paint = getPaint();
+ DISPLAY_LIST_LOGD("%s%s %p, %p", (char*) indent, OP_NAMES[op], path, paint);
+ renderer.drawPath(path, paint);
}
break;
case DrawLines: {
int count = 0;
float* points = getFloats(count);
+ DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
renderer.drawLines(points, count, getPaint());
}
break;
case DrawText: {
getText(&text);
- renderer.drawText(text.text(), text.length(), getInt(),
- getFloat(), getFloat(), getPaint());
+ int count = getInt();
+ float x = getFloat();
+ float y = getFloat();
+ SkPaint* paint = getPaint();
+ DISPLAY_LIST_LOGD("%s%s %s, %d, %d, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
+ text.text(), text.length(), count, x, y, paint);
+ renderer.drawText(text.text(), text.length(), count, x, y, paint);
}
break;
case ResetShader: {
+ DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
renderer.resetShader();
}
break;
case SetupShader: {
- renderer.setupShader(getShader());
+ SkiaShader* shader = getShader();
+ DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], shader);
+ renderer.setupShader(shader);
}
break;
case ResetColorFilter: {
+ DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
renderer.resetColorFilter();
}
break;
case SetupColorFilter: {
- renderer.setupColorFilter(getColorFilter());
+ SkiaColorFilter *colorFilter = getColorFilter();
+ DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], colorFilter);
+ renderer.setupColorFilter(colorFilter);
}
break;
case ResetShadow: {
+ DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
renderer.resetShadow();
}
break;
case SetupShadow: {
- renderer.setupShadow(getFloat(), getFloat(), getFloat(), getInt());
- }
- break;
+ float radius = getFloat();
+ float dx = getFloat();
+ float dy = getFloat();
+ int color = getInt();
+ DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, 0x%x", (char*) indent, OP_NAMES[op],
+ radius, dx, dy, color);
+ renderer.setupShadow(radius, dx, dy, color);
+ }
+ break;
+ default:
+ DISPLAY_LIST_LOGD("Display List error: op not handled: %s%s",
+ (char*) indent, OP_NAMES[op]);
+ break;
}
}
- DISPLAY_LIST_LOGD("%sDone", (char*) indent + 2);
+ DISPLAY_LIST_LOGD("%sDone, returning %d", (char*) indent + 2, needsInvalidate);
+ return needsInvalidate;
}
///////////////////////////////////////////////////////////////////////////////
@@ -493,12 +642,26 @@ void DisplayListRenderer::finish() {
OpenGLRenderer::finish();
}
+void DisplayListRenderer::interrupt() {
+
+}
+void DisplayListRenderer::resume() {
+
+}
void DisplayListRenderer::acquireContext() {
+ // TODO: probably noop instead of calling super
addOp(DisplayList::AcquireContext);
OpenGLRenderer::acquireContext();
}
+bool DisplayListRenderer::callDrawGLFunction(Functor *functor) {
+ addOp(DisplayList::DrawGLFunction);
+ addInt((int) functor);
+ return false; // No invalidate needed at record-time
+}
+
void DisplayListRenderer::releaseContext() {
+ // TODO: probably noop instead of calling super
addOp(DisplayList::ReleaseContext);
OpenGLRenderer::releaseContext();
}
@@ -581,9 +744,10 @@ bool DisplayListRenderer::clipRect(float left, float top, float right, float bot
return OpenGLRenderer::clipRect(left, top, right, bottom, op);
}
-void DisplayListRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) {
+bool DisplayListRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) {
addOp(DisplayList::DrawDisplayList);
addDisplayList(displayList);
+ return false;
}
void DisplayListRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 35bb163..6c8e8f5 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -28,6 +28,7 @@
#include <SkTSearch.h>
#include "OpenGLRenderer.h"
+#include "Functor.h"
namespace android {
namespace uirenderer {
@@ -124,13 +125,14 @@ public:
SetupColorFilter,
ResetShadow,
SetupShadow,
+ DrawGLFunction,
};
static const char* OP_NAMES[];
void initFromDisplayListRenderer(const DisplayListRenderer& recorder);
- void replay(OpenGLRenderer& renderer, uint32_t level = 0);
+ bool replay(OpenGLRenderer& renderer, uint32_t level = 0);
private:
void init();
@@ -242,9 +244,13 @@ public:
void prepare(bool opaque);
void finish();
+ bool callDrawGLFunction(Functor *functor);
void acquireContext();
void releaseContext();
+ void interrupt();
+ void resume();
+
int save(int flags);
void restore();
void restoreToCount(int saveCount);
@@ -264,7 +270,7 @@ public:
bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
- void drawDisplayList(DisplayList* displayList, uint32_t level = 0);
+ bool drawDisplayList(DisplayList* displayList, uint32_t level = 0);
void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
diff --git a/libs/hwui/OpenGLDebugRenderer.cpp b/libs/hwui/OpenGLDebugRenderer.cpp
index 29bcde8..58d6c26 100644
--- a/libs/hwui/OpenGLDebugRenderer.cpp
+++ b/libs/hwui/OpenGLDebugRenderer.cpp
@@ -48,10 +48,10 @@ int OpenGLDebugRenderer::saveLayer(float left, float top, float right, float bot
return OpenGLRenderer::saveLayer(left, top, right, bottom, p, flags);
}
-void OpenGLDebugRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) {
+bool OpenGLDebugRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) {
mPrimitivesCount++;
StopWatch w("drawDisplayList");
- OpenGLRenderer::drawDisplayList(displayList);
+ return OpenGLRenderer::drawDisplayList(displayList);
}
void OpenGLDebugRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
diff --git a/libs/hwui/OpenGLDebugRenderer.h b/libs/hwui/OpenGLDebugRenderer.h
index aefa7bf..76e6a2e 100644
--- a/libs/hwui/OpenGLDebugRenderer.h
+++ b/libs/hwui/OpenGLDebugRenderer.h
@@ -40,7 +40,7 @@ public:
int saveLayer(float left, float top, float right, float bottom,
SkPaint* p, int flags);
- void drawDisplayList(DisplayList* displayList, uint32_t level = 0);
+ bool drawDisplayList(DisplayList* displayList, uint32_t level = 0);
void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index e8dc9f6..98f8fc5 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -213,6 +213,13 @@ void OpenGLRenderer::releaseContext() {
resume();
}
+bool OpenGLRenderer::callDrawGLFunction(Functor *functor) {
+ interrupt();
+ status_t result = (*functor)();
+ resume();
+ return (result == 0) ? false : true;
+}
+
///////////////////////////////////////////////////////////////////////////////
// State management
///////////////////////////////////////////////////////////////////////////////
@@ -1031,12 +1038,13 @@ void OpenGLRenderer::finishDrawTexture() {
// Drawing
///////////////////////////////////////////////////////////////////////////////
-void OpenGLRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) {
+bool OpenGLRenderer::drawDisplayList(DisplayList* displayList, uint32_t level) {
// All the usual checks and setup operations (quickReject, setupDraw, etc.)
// will be performed by the display list itself
if (displayList) {
- displayList->replay(*this, level);
+ return displayList->replay(*this, level);
}
+ return false;
}
void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint) {
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index eec3750..bd29609 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -27,6 +27,7 @@
#include <SkShader.h>
#include <SkXfermode.h>
+#include <utils/Functor.h>
#include <utils/RefBase.h>
#include <utils/Vector.h>
@@ -65,9 +66,10 @@ public:
virtual void finish();
// These two calls must not be recorded in display lists
- void interrupt();
- void resume();
+ virtual void interrupt();
+ virtual void resume();
+ virtual bool callDrawGLFunction(Functor *functor);
virtual void acquireContext();
virtual void releaseContext();
@@ -95,7 +97,7 @@ public:
bool quickReject(float left, float top, float right, float bottom);
virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
- virtual void drawDisplayList(DisplayList* displayList, uint32_t level = 0);
+ virtual bool drawDisplayList(DisplayList* displayList, uint32_t level = 0);
virtual void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
virtual void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
virtual void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
index b0d29a1..54db8cd 100755
--- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
+++ b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
@@ -1896,7 +1896,9 @@ class MediaArtistNativeHelper {
private void onPreviewProgressUpdate(int progress, boolean isFinished) {
if (mPreviewProgressListener != null) {
mPreviewProgressListener.onProgress(mVideoEditor, progress, isFinished);
- mPreviewProgress = progress;
+ if (progress != 0) {
+ mPreviewProgress = progress;
+ }
}
}
diff --git a/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel.xml b/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel.xml
index 4cf28ee..821cf6a 100644
--- a/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel.xml
+++ b/packages/SystemUI/res/layout-xlarge/status_bar_notification_panel.xml
@@ -31,6 +31,7 @@
android:layout_width="match_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
+ android:layout_marginBottom="-27dip"
>
<include layout="@layout/status_bar_notification_panel_title"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
index 9f48b48..092f0b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/NotificationPanel.java
@@ -46,7 +46,10 @@ public class NotificationPanel extends RelativeLayout implements StatusBarPanel,
static final String TAG = "Tablet/NotificationPanel";
static final boolean DEBUG = false;
+ final static int PANEL_FADE_DURATION = 150;
+
boolean mShowing;
+ int mNotificationCount = 0;
View mTitleArea;
View mModeToggle;
View mSettingsButton;
@@ -90,6 +93,10 @@ public class NotificationPanel extends RelativeLayout implements StatusBarPanel,
}
public void show(boolean show, boolean animate) {
+ if (show && !mShowing) {
+ setContentFrameVisible(mNotificationCount > 0, false);
+ }
+
if (animate) {
if (mShowing != show) {
mShowing = show;
@@ -150,7 +157,43 @@ public class NotificationPanel extends RelativeLayout implements StatusBarPanel,
}
}
- final static int PANEL_FADE_DURATION = 150;
+ public void setNotificationCount(int n) {
+ Slog.d(TAG, "notificationCount=" + n);
+ if (!mShowing) {
+ // just do it, already
+ setContentFrameVisible(n > 0, false);
+ } else if (mSettingsView == null) {
+ // we're looking at the notifications; time to maybe make some changes
+ if (mNotificationCount == 0 && n > 0) {
+ setContentFrameVisible(true, true);
+ } else if (mNotificationCount > 0 && n == 0) {
+ setContentFrameVisible(false, true);
+ }
+ }
+ mNotificationCount = n;
+ }
+
+ public void setContentFrameVisible(final boolean showing, boolean animate) {
+ if (!animate) {
+ mContentFrame.setVisibility(showing ? View.VISIBLE : View.GONE);
+ mContentParent.setTranslationY(showing ? 0f : 100f);
+ return;
+ }
+
+ mContentFrame.setVisibility(showing ? View.VISIBLE : View.GONE);
+ AnimatorSet set = new AnimatorSet();
+ float adjust = mContentFrame.getBackground().getMinimumHeight() + 8; // fudge factor
+ set.play(ObjectAnimator.ofFloat(
+ mContentFrame, "alpha",
+ showing ? 0f : 1f,
+ showing ? 1f : 0f))
+ .with(ObjectAnimator.ofFloat(
+ mContentParent, "translationY",
+ showing ? adjust : 0f,
+ showing ? 0f : adjust));
+ set.setDuration(200);
+ set.start();
+ }
public void swapPanels() {
final View toShow, toHide;
@@ -168,12 +211,22 @@ public class NotificationPanel extends RelativeLayout implements StatusBarPanel,
@Override
public void onAnimationEnd(Animator _a) {
toHide.setVisibility(View.GONE);
- toShow.setVisibility(View.VISIBLE);
- ObjectAnimator.ofFloat(toShow, "alpha", 0f, 1f)
- .setDuration(PANEL_FADE_DURATION)
- .start();
- if (toHide == mSettingsView) {
- removeSettingsView();
+ if (toShow != null) {
+ if (mNotificationCount == 0) {
+ // show the frame for settings, hide for notifications
+ setContentFrameVisible(toShow == mSettingsView, true);
+ }
+
+ toShow.setVisibility(View.VISIBLE);
+ if (toShow == mSettingsView || mNotificationCount > 0) {
+ ObjectAnimator.ofFloat(toShow, "alpha", 0f, 1f)
+ .setDuration(PANEL_FADE_DURATION)
+ .start();
+ }
+
+ if (toHide == mSettingsView) {
+ removeSettingsView();
+ }
}
updatePanelModeButtons();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
index c2f74f0..e26b8ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tablet/TabletStatusBar.java
@@ -1219,6 +1219,8 @@ public class TabletStatusBar extends StatusBar implements
mPile.addView(toShow.get(i));
}
}
+
+ mNotificationPanel.setNotificationCount(N);
}
void workAroundBadLayerDrawableOpacity(View v) {