Merge "Use optimized display lists for all hwaccelerated rendering" into honeycomb

This commit is contained in:
Chet Haase
2011-01-24 09:24:59 -08:00
committed by Android (Google) Code Review
23 changed files with 582 additions and 131 deletions

View File

@@ -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 {

View File

@@ -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.

View File

@@ -219,6 +219,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) {
@@ -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);

View File

@@ -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) {

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -1508,6 +1508,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
@ViewDebug.ExportedProperty(category = "measurement")
/*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}
@@ -1671,6 +1682,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
/** {@hide} */
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;
@@ -6801,6 +6840,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
*
@@ -8109,26 +8172,77 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
}
/**
* 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();
}
/**
@@ -11495,6 +11610,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, Accessibility
final Callbacks mRootCallbacks;
Canvas mHardwareCanvas;
/**
* The top view of the hierarchy.
*/

View File

@@ -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));

View File

@@ -2205,6 +2205,27 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
invalidate();
}
/**
* 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
@@ -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;

View File

@@ -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);

View File

@@ -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,

View File

@@ -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.

View File

@@ -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);
}

View File

@@ -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());
}

View File

@@ -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
}
}

View File

@@ -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 },

33
include/utils/Functor.h Normal file
View File

@@ -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

View File

@@ -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());
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) {

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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) {

View File

@@ -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);