Combine base PictureSet with composite layers into

one SkLayer tree to get ready for GL rendering.

Now UI holds its copy of SkLayer tree. The top node
is BaseLayerAndroid which has the PictureSet as its
content.

There is a matching change in external/webkit.
This commit is contained in:
Grace Kloba
2010-07-08 15:02:14 -07:00
parent 2951c6d057
commit 8abd50b748
2 changed files with 75 additions and 147 deletions

View File

@ -22,14 +22,15 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.DialogInterface.OnCancelListener;
import android.content.pm.PackageManager;
import android.database.DataSetObserver;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.CornerPathEffect;
import android.graphics.DrawFilter;
import android.graphics.Interpolator;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.Picture;
import android.graphics.Point;
import android.graphics.Rect;
@ -454,10 +455,6 @@ public class WebView extends AbsoluteLayout
// true if onPause has been called (and not onResume)
private boolean mIsPaused;
// true if, during a transition to a new page, we're delaying
// deleting a root layer until there's something to draw of the new page.
private boolean mDelayedDeleteRootLayer;
/**
* Customizable constant
*/
@ -584,8 +581,8 @@ public class WebView extends AbsoluteLayout
static final int SHOW_FULLSCREEN = 120;
static final int HIDE_FULLSCREEN = 121;
static final int DOM_FOCUS_CHANGED = 122;
static final int IMMEDIATE_REPAINT_MSG_ID = 123;
static final int SET_ROOT_LAYER_MSG_ID = 124;
static final int REPLACE_BASE_CONTENT = 123;
// 124;
static final int RETURN_LABEL = 125;
static final int FIND_AGAIN = 126;
static final int CENTER_FIT_RECT = 127;
@ -633,8 +630,8 @@ public class WebView extends AbsoluteLayout
"SHOW_FULLSCREEN", // = 120;
"HIDE_FULLSCREEN", // = 121;
"DOM_FOCUS_CHANGED", // = 122;
"IMMEDIATE_REPAINT_MSG_ID", // = 123;
"SET_ROOT_LAYER_MSG_ID", // = 124;
"REPLACE_BASE_CONTENT", // = 123;
"124", // = 124;
"RETURN_LABEL", // = 125;
"FIND_AGAIN", // = 126;
"CENTER_FIT_RECT", // = 127;
@ -1691,6 +1688,7 @@ public class WebView extends AbsoluteLayout
public void clearView() {
mContentWidth = 0;
mContentHeight = 0;
nativeSetBaseLayer(0);
mWebViewCore.sendMessage(EventHub.CLEAR_CONTENT);
}
@ -1704,8 +1702,9 @@ public class WebView extends AbsoluteLayout
* bounds of the view.
*/
public Picture capturePicture() {
if (null == mWebViewCore) return null; // check for out of memory tab
return mWebViewCore.copyContentPicture();
Picture result = new Picture();
nativeCopyBaseContentToPicture(result);
return result;
}
/**
@ -3232,16 +3231,6 @@ public class WebView extends AbsoluteLayout
}
}
private void drawExtras(Canvas canvas, int extras, boolean animationsRunning) {
// If mNativeClass is 0, we should not reach here, so we do not
// need to check it again.
if (animationsRunning) {
canvas.setDrawFilter(mWebViewCore.mZoomFilter);
}
nativeDrawExtras(canvas, extras);
canvas.setDrawFilter(null);
}
private void onZoomAnimationStart() {
// If it is in password mode, turn it off so it does not draw misplaced.
if (inEditingMode() && nativeFocusCandidateIsPassword()) {
@ -3268,6 +3257,18 @@ public class WebView extends AbsoluteLayout
onZoomAnimationEnd();
}
private static final int ZOOM_BITS = Paint.FILTER_BITMAP_FLAG |
Paint.DITHER_FLAG |
Paint.SUBPIXEL_TEXT_FLAG;
private static final int SCROLL_BITS = Paint.FILTER_BITMAP_FLAG |
Paint.DITHER_FLAG;
private final DrawFilter mZoomFilter =
new PaintFlagsDrawFilter(ZOOM_BITS, Paint.LINEAR_TEXT_FLAG);
// If we need to trade better quality for speed, set mScrollFilter to null
private final DrawFilter mScrollFilter =
new PaintFlagsDrawFilter(SCROLL_BITS, 0);
private void drawCoreAndCursorRing(Canvas canvas, int color,
boolean drawCursorRing) {
if (mDrawHistory) {
@ -3275,6 +3276,7 @@ public class WebView extends AbsoluteLayout
canvas.drawPicture(mHistoryPicture);
return;
}
if (mNativeClass == 0) return;
boolean animateZoom = mZoomManager.isFixedLengthAnimationInProgress();
boolean animateScroll = ((!mScroller.isFinished()
@ -3309,10 +3311,7 @@ public class WebView extends AbsoluteLayout
// we ask for a repaint.
invalidate();
}
mWebViewCore.drawContentPicture(canvas, color,
(mZoomManager.isZoomAnimating() || UIAnimationsRunning),
animateScroll);
if (mNativeClass == 0) return;
// decide which adornments to draw
int extras = DRAW_EXTRAS_NONE;
if (DebugFlags.WEB_VIEW) {
@ -3332,7 +3331,18 @@ public class WebView extends AbsoluteLayout
} else if (drawCursorRing) {
extras = DRAW_EXTRAS_CURSOR_RING;
}
drawExtras(canvas, extras, UIAnimationsRunning);
DrawFilter df = null;
if (mZoomManager.isZoomAnimating() || UIAnimationsRunning) {
df = mZoomFilter;
} else if (animateScroll) {
df = mScrollFilter;
}
canvas.setDrawFilter(df);
int content = nativeDraw(canvas, color, extras, true);
canvas.setDrawFilter(null);
if (content != 0) {
mWebViewCore.sendMessage(EventHub.SPLIT_PICTURE_SET, content, 0);
}
if (extras == DRAW_EXTRAS_CURSOR_RING) {
if (mTouchMode == TOUCH_SHORTPRESS_START_MODE) {
@ -3368,7 +3378,7 @@ public class WebView extends AbsoluteLayout
// Should only be called in UI thread
void switchOutDrawHistory() {
if (null == mWebViewCore) return; // CallbackProxy may trigger this
if (mDrawHistory && mWebViewCore.pictureReady()) {
if (mDrawHistory && (getProgress() == 100 || nativeHasContent())) {
mDrawHistory = false;
mHistoryPicture = null;
invalidate();
@ -6036,16 +6046,14 @@ public class WebView extends AbsoluteLayout
mZoomManager.updateZoomRange(viewState, getViewWidth(), viewState.mScrollX);
break;
}
case REPLACE_BASE_CONTENT: {
nativeReplaceBaseContent(msg.arg1);
break;
}
case NEW_PICTURE_MSG_ID: {
// If we've previously delayed deleting a root
// layer, do it now.
if (mDelayedDeleteRootLayer) {
mDelayedDeleteRootLayer = false;
nativeSetRootLayer(0);
}
// called for new content
final WebViewCore.DrawData draw = (WebViewCore.DrawData) msg.obj;
nativeSetBaseLayer(draw.mBaseLayer);
final Point viewSize = draw.mViewPoint;
WebViewCore.ViewState viewState = draw.mViewState;
boolean isPictureAfterFirstLayout = viewState != null;
@ -6166,23 +6174,6 @@ public class WebView extends AbsoluteLayout
}
break;
}
case IMMEDIATE_REPAINT_MSG_ID: {
invalidate();
break;
}
case SET_ROOT_LAYER_MSG_ID: {
if (0 == msg.arg1) {
// Null indicates deleting the old layer, but
// don't actually do so until we've got the
// new page to display.
mDelayedDeleteRootLayer = true;
} else {
mDelayedDeleteRootLayer = false;
nativeSetRootLayer(msg.arg1);
invalidate();
}
break;
}
case REQUEST_FORM_DATA:
AutoCompleteAdapter adapter = (AutoCompleteAdapter) msg.obj;
if (mWebTextView.isSameTextField(msg.arg1)) {
@ -6944,7 +6935,7 @@ public class WebView extends AbsoluteLayout
* @hide only needs to be accessible to Browser and testing
*/
public void drawPage(Canvas canvas) {
mWebViewCore.drawContentPicture(canvas, 0, false, false);
nativeDraw(canvas, 0, 0, false);
}
/**
@ -6988,7 +6979,15 @@ public class WebView extends AbsoluteLayout
private native boolean nativeCursorWantsKeyEvents();
private native void nativeDebugDump();
private native void nativeDestroy();
private native void nativeDrawExtras(Canvas canvas, int extra);
/**
* Draw the picture set with a background color and extra. If
* "splitIfNeeded" is true and the return value is not 0, the return value
* MUST be passed to WebViewCore with SPLIT_PICTURE_SET message so that the
* native allocation can be freed.
*/
private native int nativeDraw(Canvas canvas, int color, int extra,
boolean splitIfNeeded);
private native void nativeDumpDisplayTree(String urlOrNull);
private native boolean nativeEvaluateLayersAnimations();
private native void nativeExtendSelection(int x, int y);
@ -7053,7 +7052,10 @@ public class WebView extends AbsoluteLayout
private native void nativeSetFindIsUp(boolean isUp);
private native void nativeSetFollowedLink(boolean followed);
private native void nativeSetHeightCanMeasure(boolean measure);
private native void nativeSetRootLayer(int layer);
private native void nativeSetBaseLayer(int layer);
private native void nativeReplaceBaseContent(int content);
private native void nativeCopyBaseContentToPicture(Picture pict);
private native boolean nativeHasContent();
private native void nativeSetSelectionPointer(boolean set,
float scale, int x, int y);
private native boolean nativeStartSelection(int x, int y);

View File

@ -19,11 +19,6 @@ package android.webkit;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.database.Cursor;
import android.graphics.Canvas;
import android.graphics.DrawFilter;
import android.graphics.Paint;
import android.graphics.PaintFlagsDrawFilter;
import android.graphics.Picture;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
@ -33,7 +28,6 @@ import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.provider.MediaStore;
import android.provider.MediaStore.Images.Media;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.view.KeyEvent;
@ -442,36 +436,19 @@ final class WebViewCore {
*/
private native void nativeClearContent();
/**
* Create a flat picture from the set of pictures.
*/
private native void nativeCopyContentToPicture(Picture picture);
/**
* Draw the picture set with a background color. Returns true
* if some individual picture took too long to draw and can be
* split into parts. Called from the UI thread.
*/
private native boolean nativeDrawContent(Canvas canvas, int color);
/**
* check to see if picture is blank and in progress
*/
private native boolean nativePictureReady();
/**
* Redraw a portion of the picture set. The Point wh returns the
* width and height of the overall picture.
*/
private native boolean nativeRecordContent(Region invalRegion, Point wh);
private native int nativeRecordContent(Region invalRegion, Point wh);
private native boolean nativeFocusBoundsChanged();
/**
* Splits slow parts of the picture set. Called from the webkit
* thread after nativeDrawContent returns true.
* Splits slow parts of the picture set. Called from the webkit thread after
* WebView.nativeDraw() returns content to be split.
*/
private native void nativeSplitContent();
private native void nativeSplitContent(int content);
private native boolean nativeKey(int keyCode, int unichar,
int repeatCount, boolean isShift, boolean isAlt, boolean isSym,
@ -1336,7 +1313,9 @@ final class WebViewCore {
break;
case SPLIT_PICTURE_SET:
nativeSplitContent();
nativeSplitContent(msg.arg1);
mWebView.mPrivateHandler.obtainMessage(
WebView.REPLACE_BASE_CONTENT, msg.arg1, 0);
mSplitPictureIsScheduled = false;
break;
@ -1736,6 +1715,14 @@ final class WebViewCore {
return usedQuota;
}
// called from UI thread
void splitContent(int content) {
if (!mSplitPictureIsScheduled) {
mSplitPictureIsScheduled = true;
sendMessage(EventHub.SPLIT_PICTURE_SET, content, 0);
}
}
// Used to avoid posting more than one draw message.
private boolean mDrawIsScheduled;
@ -1762,9 +1749,11 @@ final class WebViewCore {
static class DrawData {
DrawData() {
mBaseLayer = 0;
mInvalRegion = new Region();
mWidthHeight = new Point();
}
int mBaseLayer;
Region mInvalRegion;
Point mViewPoint;
Point mWidthHeight;
@ -1778,8 +1767,8 @@ final class WebViewCore {
mDrawIsScheduled = false;
DrawData draw = new DrawData();
if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw start");
if (nativeRecordContent(draw.mInvalRegion, draw.mWidthHeight)
== false) {
draw.mBaseLayer = nativeRecordContent(draw.mInvalRegion, draw.mWidthHeight);
if (draw.mBaseLayer == 0) {
if (DebugFlags.WEB_VIEW_CORE) Log.v(LOGTAG, "webkitDraw abort");
return;
}
@ -1812,51 +1801,6 @@ final class WebViewCore {
}
}
///////////////////////////////////////////////////////////////////////////
// These are called from the UI thread, not our thread
static final int ZOOM_BITS = Paint.FILTER_BITMAP_FLAG |
Paint.DITHER_FLAG |
Paint.SUBPIXEL_TEXT_FLAG;
static final int SCROLL_BITS = Paint.FILTER_BITMAP_FLAG |
Paint.DITHER_FLAG;
final DrawFilter mZoomFilter =
new PaintFlagsDrawFilter(ZOOM_BITS, Paint.LINEAR_TEXT_FLAG);
// If we need to trade better quality for speed, set mScrollFilter to null
final DrawFilter mScrollFilter =
new PaintFlagsDrawFilter(SCROLL_BITS, 0);
/* package */ void drawContentPicture(Canvas canvas, int color,
boolean animatingZoom,
boolean animatingScroll) {
DrawFilter df = null;
if (animatingZoom) {
df = mZoomFilter;
} else if (animatingScroll) {
df = mScrollFilter;
}
canvas.setDrawFilter(df);
boolean tookTooLong = nativeDrawContent(canvas, color);
canvas.setDrawFilter(null);
if (tookTooLong && mSplitPictureIsScheduled == false) {
mSplitPictureIsScheduled = true;
sendMessage(EventHub.SPLIT_PICTURE_SET);
}
}
/* package */ synchronized boolean pictureReady() {
return 0 != mNativeClass ? nativePictureReady() : false;
}
/*package*/ synchronized Picture copyContentPicture() {
Picture result = new Picture();
if (0 != mNativeClass) {
nativeCopyContentToPicture(result);
}
return result;
}
static void reducePriority() {
// remove the pending REDUCE_PRIORITY and RESUME_PRIORITY messages
sWebCoreHandler.removeMessages(WebCoreThread.REDUCE_PRIORITY);
@ -2038,24 +1982,6 @@ final class WebViewCore {
mRepaintScheduled = false;
}
// called by JNI
private void sendImmediateRepaint() {
if (mWebView != null && !mRepaintScheduled) {
mRepaintScheduled = true;
Message.obtain(mWebView.mPrivateHandler,
WebView.IMMEDIATE_REPAINT_MSG_ID).sendToTarget();
}
}
// called by JNI
private void setRootLayer(int layer) {
if (mWebView != null) {
Message.obtain(mWebView.mPrivateHandler,
WebView.SET_ROOT_LAYER_MSG_ID,
layer, 0).sendToTarget();
}
}
/* package */ WebView getWebView() {
return mWebView;
}