Merge "Fix issue 2349345: Media sound output stuck on earpiece rather than speaker."
diff --git a/core/java/android/app/BackupAgent.java b/core/java/android/app/BackupAgent.java
index b207998..2a58677 100644
--- a/core/java/android/app/BackupAgent.java
+++ b/core/java/android/app/BackupAgent.java
@@ -21,6 +21,7 @@
import android.backup.BackupDataOutput;
import android.content.Context;
import android.content.ContextWrapper;
+import android.os.Binder;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
@@ -116,7 +117,9 @@
public void doBackup(ParcelFileDescriptor oldState,
ParcelFileDescriptor data,
ParcelFileDescriptor newState) throws RemoteException {
- // !!! TODO - real implementation; for now just invoke the callbacks directly
+ // Ensure that we're running with the app's normal permission level
+ long token = Binder.clearCallingIdentity();
+
if (DEBUG) Log.v(TAG, "doBackup() invoked");
BackupDataOutput output = new BackupDataOutput(data.getFileDescriptor());
try {
@@ -127,12 +130,16 @@
} catch (RuntimeException ex) {
Log.d(TAG, "onBackup (" + BackupAgent.this.getClass().getName() + ") threw", ex);
throw ex;
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
public void doRestore(ParcelFileDescriptor data, int appVersionCode,
ParcelFileDescriptor newState) throws RemoteException {
- // !!! TODO - real implementation; for now just invoke the callbacks directly
+ // Ensure that we're running with the app's normal permission level
+ long token = Binder.clearCallingIdentity();
+
if (DEBUG) Log.v(TAG, "doRestore() invoked");
BackupDataInput input = new BackupDataInput(data.getFileDescriptor());
try {
@@ -143,6 +150,8 @@
} catch (RuntimeException ex) {
Log.d(TAG, "onRestore (" + BackupAgent.this.getClass().getName() + ") threw", ex);
throw ex;
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
}
diff --git a/core/java/android/provider/Calendar.java b/core/java/android/provider/Calendar.java
index 3296bbf..cbd8a26 100644
--- a/core/java/android/provider/Calendar.java
+++ b/core/java/android/provider/Calendar.java
@@ -62,7 +62,7 @@
public static final String EVENT_BEGIN_TIME = "beginTime";
public static final String EVENT_END_TIME = "endTime";
- public static final String AUTHORITY = "calendar";
+ public static final String AUTHORITY = "com.android.calendar";
/**
* The content:// style URL for the top-level calendar authority
@@ -1413,4 +1413,25 @@
// TODO: fill out this class when we actually start utilizing extendedproperties
// in the calendar application.
}
+
+ /**
+ * A table provided for sync adapters to use for storing private sync state data.
+ *
+ * @see SyncStateContract
+ */
+ public static final class SyncState implements SyncStateContract.Columns {
+ /**
+ * This utility class cannot be instantiated
+ */
+ private SyncState() {}
+
+ public static final String CONTENT_DIRECTORY =
+ SyncStateContract.Constants.CONTENT_DIRECTORY;
+
+ /**
+ * The content:// style URI for this table
+ */
+ public static final Uri CONTENT_URI =
+ Uri.withAppendedPath(Calendar.CONTENT_URI, CONTENT_DIRECTORY);
+ }
}
diff --git a/core/java/android/speech/RecognizerIntent.java b/core/java/android/speech/RecognizerIntent.java
index 987e763..6c5f912 100644
--- a/core/java/android/speech/RecognizerIntent.java
+++ b/core/java/android/speech/RecognizerIntent.java
@@ -154,4 +154,12 @@
* {@link #ACTION_RECOGNIZE_SPEECH}. Only present when {@link Activity#RESULT_OK} is returned.
*/
public static final String EXTRA_RESULTS = "android.speech.extra.RESULTS";
+
+ /**
+ * Triggers the voice search settings activity.
+ *
+ * @hide pending API council approval, to be unhidden for Froyo
+ */
+ public static final String ACTION_VOICE_SEARCH_SETTINGS =
+ "android.speech.action.VOICE_SEARCH_SETTINGS";
}
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index d5bb572..35f1ac6 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -412,6 +412,7 @@
*/
public void setSupportZoom(boolean support) {
mSupportZoom = support;
+ mWebView.updateMultiTouchSupport(mContext);
}
/**
@@ -426,6 +427,7 @@
*/
public void setBuiltInZoomControls(boolean enabled) {
mBuiltInZoomControls = enabled;
+ mWebView.updateMultiTouchSupport(mContext);
}
/**
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 2d9b52e..56650a6 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -21,6 +21,7 @@
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;
@@ -48,6 +49,7 @@
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
+import android.view.ScaleGestureDetector;
import android.view.SoundEffectConstants;
import android.view.VelocityTracker;
import android.view.View;
@@ -362,6 +364,7 @@
private static final int TOUCH_DOUBLE_TAP_MODE = 6;
private static final int TOUCH_DONE_MODE = 7;
private static final int TOUCH_SELECT_MODE = 8;
+ private static final int TOUCH_PINCH_DRAG = 9;
// Whether to forward the touch events to WebCore
private boolean mForwardTouchEvents = false;
@@ -460,6 +463,18 @@
private static final int MOTIONLESS_TRUE = 2;
private int mHeldMotionless;
+ // whether support multi-touch
+ private static boolean mSupportMultiTouch;
+ // use the framework's ScaleGestureDetector to handle multi-touch
+ private ScaleGestureDetector mScaleDetector;
+ // minimum scale change during multi-touch zoom
+ private static float PREVIEW_SCALE_INCREMENT = 0.01f;
+
+ // the anchor point in the document space where VIEW_SIZE_CHANGED should
+ // apply to
+ private int mAnchorX;
+ private int mAnchorY;
+
/**
* Private message ids
*/
@@ -469,7 +484,7 @@
private static final int SWITCH_TO_LONGPRESS = 4;
private static final int RELEASE_SINGLE_TAP = 5;
private static final int REQUEST_FORM_DATA = 6;
- private static final int RESUME_WEBCORE_UPDATE = 7;
+ private static final int RESUME_WEBCORE_PRIORITY = 7;
private static final int DRAG_HELD_MOTIONLESS = 8;
private static final int AWAKEN_SCROLL_BARS = 9;
@@ -488,7 +503,7 @@
static final int MOVE_OUT_OF_PLUGIN = 19;
static final int CLEAR_TEXT_ENTRY = 20;
static final int UPDATE_TEXT_SELECTION_MSG_ID = 21;
-
+ static final int SHOW_RECT_MSG_ID = 22;
static final int LONG_PRESS_CENTER = 23;
static final int PREVENT_TOUCH_ID = 24;
static final int WEBCORE_NEED_TOUCH_EVENTS = 25;
@@ -510,7 +525,7 @@
"SWITCH_TO_LONGPRESS", // = 4;
"RELEASE_SINGLE_TAP", // = 5;
"REQUEST_FORM_DATA", // = 6;
- "RESUME_WEBCORE_UPDATE", // = 7;
+ "RESUME_WEBCORE_PRIORITY", // = 7;
"DRAG_HELD_MOTIONLESS", // = 8;
"AWAKEN_SCROLL_BARS", // = 9;
"SCROLL_TO_MSG_ID", // = 10;
@@ -525,7 +540,7 @@
"MOVE_OUT_OF_PLUGIN", // = 19;
"CLEAR_TEXT_ENTRY", // = 20;
"UPDATE_TEXT_SELECTION_MSG_ID", // = 21;
- "22", // = 22;
+ "SHOW_RECT_MSG_ID", // = 22;
"LONG_PRESS_CENTER", // = 23;
"PREVENT_TOUCH_ID", // = 24;
"WEBCORE_NEED_TOUCH_EVENTS", // = 25;
@@ -570,13 +585,13 @@
// ideally mZoomOverviewWidth should be mContentWidth. But sites like espn,
// engadget always have wider mContentWidth no matter what viewport size is.
int mZoomOverviewWidth = DEFAULT_VIEWPORT_WIDTH;
- float mLastScale;
+ float mTextWrapScale;
// default scale. Depending on the display density.
static int DEFAULT_SCALE_PERCENT;
private float mDefaultScale;
- // set to true temporarily while the zoom control is being dragged
+ // set to true temporarily during ScaleGesture triggered zoom
private boolean mPreviewZoomOnly = false;
// computed scale and inverse, from mZoomWidth.
@@ -803,6 +818,20 @@
params;
frameParams.gravity = Gravity.RIGHT;
}
+ updateMultiTouchSupport(context);
+ }
+
+ void updateMultiTouchSupport(Context context) {
+ WebSettings settings = getSettings();
+ mSupportMultiTouch = context.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH)
+ && settings.supportZoom() && settings.getBuiltInZoomControls();
+ if (mSupportMultiTouch && (mScaleDetector == null)) {
+ mScaleDetector = new ScaleGestureDetector(context,
+ new ScaleDetectorListener());
+ } else if (!mSupportMultiTouch && (mScaleDetector != null)) {
+ mScaleDetector = null;
+ }
}
private void updateZoomButtonsEnabled() {
@@ -842,6 +871,7 @@
mDefaultScale = density;
mActualScale = density;
mInvActualScale = 1 / density;
+ mTextWrapScale = density;
DEFAULT_MAX_ZOOM_SCALE = 4.0f * density;
DEFAULT_MIN_ZOOM_SCALE = 0.25f * density;
mMaxZoomScale = DEFAULT_MAX_ZOOM_SCALE;
@@ -862,7 +892,7 @@
mDefaultScale = density;
mMaxZoomScale *= scaleFactor;
mMinZoomScale *= scaleFactor;
- setNewZoomScale(mActualScale * scaleFactor, false);
+ setNewZoomScale(mActualScale * scaleFactor, true, false);
}
}
@@ -1229,9 +1259,8 @@
b.putInt("scrollX", mScrollX);
b.putInt("scrollY", mScrollY);
b.putFloat("scale", mActualScale);
- if (mInZoomOverview) {
- b.putFloat("lastScale", mLastScale);
- }
+ b.putFloat("textwrapScale", mTextWrapScale);
+ b.putBoolean("overview", mInZoomOverview);
return true;
}
return false;
@@ -1276,13 +1305,8 @@
// onSizeChanged() is called, the rest will be set
// correctly
mActualScale = scale;
- float lastScale = b.getFloat("lastScale", -1.0f);
- if (lastScale > 0) {
- mInZoomOverview = true;
- mLastScale = lastScale;
- } else {
- mInZoomOverview = false;
- }
+ mTextWrapScale = b.getFloat("textwrapScale", scale);
+ mInZoomOverview = b.getBoolean("overview");
invalidate();
return true;
}
@@ -2012,12 +2036,18 @@
contentSizeChanged(updateLayout);
}
- private void setNewZoomScale(float scale, boolean force) {
+ private void setNewZoomScale(float scale, boolean updateTextWrapScale,
+ boolean force) {
if (scale < mMinZoomScale) {
scale = mMinZoomScale;
} else if (scale > mMaxZoomScale) {
scale = mMaxZoomScale;
}
+ if (updateTextWrapScale) {
+ mTextWrapScale = scale;
+ // reset mLastHeightSent to force VIEW_SIZE_CHANGED sent to WebKit
+ mLastHeightSent = 0;
+ }
if (scale != mActualScale || force) {
if (mDrawHistory) {
// If history Picture is drawn, don't update scroll. They will
@@ -2027,9 +2057,7 @@
}
mActualScale = scale;
mInvActualScale = 1 / scale;
- if (!mPreviewZoomOnly) {
- sendViewSizeZoom();
- }
+ sendViewSizeZoom();
} else {
// update our scroll so we don't appear to jump
// i.e. keep the center of the doc in the center of the view
@@ -2057,10 +2085,9 @@
mScrollX = pinLocX(Math.round(sx));
mScrollY = pinLocY(Math.round(sy));
- if (!mPreviewZoomOnly) {
- sendViewSizeZoom();
- sendOurVisibleRect();
- }
+ // update webkit
+ sendViewSizeZoom();
+ sendOurVisibleRect();
}
}
}
@@ -2070,6 +2097,8 @@
private Rect mLastGlobalRect;
private Rect sendOurVisibleRect() {
+ if (mPreviewZoomOnly) return mLastVisibleRectSent;
+
Rect rect = new Rect();
calcOurContentVisibleRect(rect);
// Rect.equals() checks for null input.
@@ -2123,6 +2152,8 @@
int mWidth;
int mHeight;
int mTextWrapWidth;
+ int mAnchorX;
+ int mAnchorY;
float mScale;
boolean mIgnoreHeight;
}
@@ -2134,6 +2165,8 @@
* @return true if new values were sent
*/
private boolean sendViewSizeZoom() {
+ if (mPreviewZoomOnly) return false;
+
int viewWidth = getViewWidth();
int newWidth = Math.round(viewWidth * mInvActualScale);
int newHeight = Math.round(getViewHeight() * mInvActualScale);
@@ -2153,16 +2186,15 @@
ViewSizeData data = new ViewSizeData();
data.mWidth = newWidth;
data.mHeight = newHeight;
- // while in zoom overview mode, the text are wrapped to the screen
- // width matching mLastScale. So that we don't trigger re-flow while
- // toggling between overview mode and normal mode.
- data.mTextWrapWidth = mInZoomOverview ? Math.round(viewWidth
- / mLastScale) : newWidth;
+ data.mTextWrapWidth = Math.round(viewWidth / mTextWrapScale);;
data.mScale = mActualScale;
data.mIgnoreHeight = mZoomScale != 0 && !mHeightCanMeasure;
+ data.mAnchorX = mAnchorX;
+ data.mAnchorY = mAnchorY;
mWebViewCore.sendMessage(EventHub.VIEW_SIZE_CHANGED, data);
mLastWidthSent = newWidth;
mLastHeightSent = newHeight;
+ mAnchorX = mAnchorY = 0;
return true;
}
return false;
@@ -3100,13 +3132,13 @@
canvas.scale(mActualScale, mActualScale);
}
- mWebViewCore.drawContentPicture(canvas, color, animateZoom,
- animateScroll);
+ mWebViewCore.drawContentPicture(canvas, color,
+ (animateZoom || mPreviewZoomOnly), animateScroll);
drawLayers(canvas);
if (mNativeClass == 0) return;
- if (mShiftIsPressed && !animateZoom) {
+ if (mShiftIsPressed && !(animateZoom || mPreviewZoomOnly)) {
if (mTouchSelection || mExtendSelection) {
nativeDrawSelectionRegion(canvas);
}
@@ -3227,10 +3259,14 @@
rebuildWebTextView();
if (!inEditingMode()) return;
imm.showSoftInput(mWebTextView, 0);
- if (mInZoomOverview) {
- // if in zoom overview mode, call doDoubleTap() to bring it back
- // to normal mode so that user can enter text.
- doDoubleTap();
+ // bring it back to the default scale so that user can enter text
+ if (mActualScale < mDefaultScale) {
+ mInZoomOverview = false;
+ mZoomCenterX = mLastTouchX;
+ mZoomCenterY = mLastTouchY;
+ // do not change text wrap scale so that there is no reflow
+ setNewZoomScale(mDefaultScale, false, false);
+ didUpdateTextViewBounds(true);
}
}
else { // used by plugins
@@ -3872,6 +3908,25 @@
return changed;
}
+ private static class PostScale implements Runnable {
+ final WebView mWebView;
+ final boolean mUpdateTextWrap;
+
+ public PostScale(WebView webView, boolean updateTextWrap) {
+ mWebView = webView;
+ mUpdateTextWrap = updateTextWrap;
+ }
+
+ public void run() {
+ if (mWebView.mWebViewCore != null) {
+ // we always force, in case our height changed, in which case we
+ // still want to send the notification over to webkit.
+ mWebView.setNewZoomScale(mWebView.mActualScale,
+ mUpdateTextWrap, true);
+ }
+ }
+ }
+
@Override
protected void onSizeChanged(int w, int h, int ow, int oh) {
super.onSizeChanged(w, h, ow, oh);
@@ -3879,6 +3934,8 @@
if (mZoomScale == 0) { // unless we're already zooming
mZoomCenterX = getViewWidth() * .5f;
mZoomCenterY = getViewHeight() * .5f;
+ mAnchorX = viewToContentX((int) mZoomCenterX + mScrollX);
+ mAnchorY = viewToContentY((int) mZoomCenterY + mScrollY);
}
// adjust the max viewport width depending on the view dimensions. This
@@ -3911,15 +3968,9 @@
// requestLayout() is blocked during layout. As setNewZoomScale() will
// call its child View to reposition itself through ViewManager's
// scaleAll(), we need to post a Runnable to ensure requestLayout().
- post(new Runnable() {
- public void run() {
- // we always force, in case our height changed, in which case we
- // still want to send the notification over to webkit
- if (mWebViewCore != null) {
- setNewZoomScale(mActualScale, true);
- }
- }
- });
+ // <b/>
+ // only update the text wrap scale if width changed.
+ post(new PostScale(this, w != ow));
}
@Override
@@ -4127,6 +4178,76 @@
private DragTracker mDragTracker;
private DragTrackerHandler mDragTrackerHandler;
+ private class ScaleDetectorListener implements
+ ScaleGestureDetector.OnScaleGestureListener {
+
+ public boolean onScaleBegin(ScaleGestureDetector detector) {
+ // cancel the single touch handling
+ cancelTouch();
+ if (mZoomButtonsController.isVisible()) {
+ mZoomButtonsController.setVisible(false);
+ }
+ // reset the zoom overview mode so that the page won't auto grow
+ mInZoomOverview = false;
+ // If it is in password mode, turn it off so it does not draw
+ // misplaced.
+ if (inEditingMode() && nativeFocusCandidateIsPassword()) {
+ mWebTextView.setInPassword(false);
+ }
+ return true;
+ }
+
+ public void onScaleEnd(ScaleGestureDetector detector) {
+ if (mPreviewZoomOnly) {
+ mPreviewZoomOnly = false;
+ mAnchorX = viewToContentX((int) mZoomCenterX + mScrollX);
+ mAnchorY = viewToContentY((int) mZoomCenterY + mScrollY);
+ // don't reflow when zoom in; when zoom out, do reflow if the
+ // new scale is almost minimum scale;
+ boolean reflowNow = (mActualScale - mMinZoomScale <= 0.01f)
+ || ((mActualScale <= 0.8 * mTextWrapScale));
+ // force zoom after mPreviewZoomOnly is set to false so that the
+ // new view size will be passed to the WebKit
+ setNewZoomScale(mActualScale, reflowNow, true);
+ // call invalidate() to draw without zoom filter
+ invalidate();
+ }
+ // adjust the edit text view if needed
+ if (inEditingMode() && didUpdateTextViewBounds(false)
+ && nativeFocusCandidateIsPassword()) {
+ // If it is a password field, start drawing the
+ // WebTextView once again.
+ mWebTextView.setInPassword(true);
+ }
+ // start a drag, TOUCH_PINCH_DRAG, can't use TOUCH_INIT_MODE as it
+ // may trigger the unwanted click, can't use TOUCH_DRAG_MODE as it
+ // may trigger the unwanted fling.
+ mTouchMode = TOUCH_PINCH_DRAG;
+ startTouch(detector.getFocusX(), detector.getFocusY(),
+ mLastTouchTime);
+ }
+
+ public boolean onScale(ScaleGestureDetector detector) {
+ float scale = (float) (Math.round(detector.getScaleFactor()
+ * mActualScale * 100) / 100.0);
+ if (Math.abs(scale - mActualScale) >= PREVIEW_SCALE_INCREMENT) {
+ mPreviewZoomOnly = true;
+ // limit the scale change per step
+ if (scale > mActualScale) {
+ scale = Math.min(scale, mActualScale * 1.25f);
+ } else {
+ scale = Math.max(scale, mActualScale * 0.8f);
+ }
+ mZoomCenterX = detector.getFocusX();
+ mZoomCenterY = detector.getFocusY();
+ setNewZoomScale(scale, false, false);
+ invalidate();
+ return true;
+ }
+ return false;
+ }
+ }
+
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (mNativeClass == 0 || !isClickable() || !isLongClickable()) {
@@ -4138,11 +4259,45 @@
+ mTouchMode);
}
- int action = ev.getAction();
- float x = ev.getX();
- float y = ev.getY();
+ int action;
+ float x, y;
long eventTime = ev.getEventTime();
+ // FIXME: we may consider to give WebKit an option to handle multi-touch
+ // events later.
+ if (mSupportMultiTouch && ev.getPointerCount() > 1) {
+ if (mMinZoomScale < mMaxZoomScale) {
+ mScaleDetector.onTouchEvent(ev);
+ if (mScaleDetector.isInProgress()) {
+ mLastTouchTime = eventTime;
+ return true;
+ }
+ x = mScaleDetector.getFocusX();
+ y = mScaleDetector.getFocusY();
+ action = ev.getAction() & MotionEvent.ACTION_MASK;
+ if (action == MotionEvent.ACTION_POINTER_DOWN) {
+ cancelTouch();
+ action = MotionEvent.ACTION_DOWN;
+ } else if (action == MotionEvent.ACTION_POINTER_UP) {
+ // set mLastTouchX/Y to the remaining point
+ mLastTouchX = x;
+ mLastTouchY = y;
+ } else if (action == MotionEvent.ACTION_MOVE) {
+ // negative x or y indicate it is on the edge, skip it.
+ if (x < 0 || y < 0) {
+ return true;
+ }
+ }
+ } else {
+ // if the page disallow zoom, skip multi-pointer action
+ return true;
+ }
+ } else {
+ action = ev.getAction();
+ x = ev.getX();
+ y = ev.getY();
+ }
+
// Due to the touch screen edge effect, a touch closer to the edge
// always snapped to the edge. As getViewWidth() can be different from
// getWidth() due to the scrollbar, adjusting the point to match
@@ -4179,7 +4334,7 @@
// fling's velocity
mScroller.abortAnimation();
mTouchMode = TOUCH_DRAG_START_MODE;
- mPrivateHandler.removeMessages(RESUME_WEBCORE_UPDATE);
+ mPrivateHandler.removeMessages(RESUME_WEBCORE_PRIORITY);
} else if (mShiftIsPressed) {
mSelectX = mScrollX + (int) x;
mSelectY = mScrollY + (int) y;
@@ -4201,6 +4356,7 @@
// continue, mTouchMode should be still TOUCH_INIT_MODE
}
} else {
+ mPreviewZoomOnly = false;
mTouchMode = TOUCH_INIT_MODE;
mPreventDrag = mForwardTouchEvents ? PREVENT_DRAG_MAYBE_YES
: PREVENT_DRAG_NO;
@@ -4219,16 +4375,7 @@
mPrivateHandler.sendMessageDelayed(mPrivateHandler
.obtainMessage(SWITCH_TO_SHORTPRESS), TAP_TIMEOUT);
}
- // Remember where the motion event started
- mLastTouchX = x;
- mLastTouchY = y;
- mLastTouchTime = eventTime;
- mVelocityTracker = VelocityTracker.obtain();
- mSnapScrollMode = SNAP_NONE;
- if (mDragTracker != null) {
- mDragTrackerHandler = new DragTrackerHandler(x, y,
- mDragTracker);
- }
+ startTouch(x, y, eventTime);
break;
}
case MotionEvent.ACTION_MOVE: {
@@ -4291,7 +4438,7 @@
deltaX = 0;
deltaY = 0;
- WebViewCore.pauseUpdate(mWebViewCore);
+ WebViewCore.reducePriority(mWebViewCore);
if (!mDragFromTextInput) {
nativeHideCursor();
}
@@ -4454,7 +4601,7 @@
|| computeVerticalScrollExtent() < computeVerticalScrollRange())) {
// we will not rewrite drag code here, but we
// will try fling if it applies.
- WebViewCore.pauseUpdate(mWebViewCore);
+ WebViewCore.reducePriority(mWebViewCore);
// fall through to TOUCH_DRAG_MODE
} else {
break;
@@ -4494,7 +4641,7 @@
break;
}
mLastVelocity = 0;
- WebViewCore.resumeUpdate(mWebViewCore);
+ WebViewCore.resumePriority(mWebViewCore);
break;
case TOUCH_DRAG_START_MODE:
case TOUCH_DONE_MODE:
@@ -4511,33 +4658,49 @@
break;
}
case MotionEvent.ACTION_CANCEL: {
- if (mDragTrackerHandler != null) {
- mDragTrackerHandler.stopDrag();
- mDragTrackerHandler = null;
- }
- // we also use mVelocityTracker == null to tell us that we are
- // not "moving around", so we can take the slower/prettier
- // mode in the drawing code
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
- mVelocityTracker = null;
- }
- if (mTouchMode == TOUCH_DRAG_MODE) {
- WebViewCore.resumeUpdate(mWebViewCore);
- }
- mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
- mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
- mPrivateHandler.removeMessages(DRAG_HELD_MOTIONLESS);
- mPrivateHandler.removeMessages(AWAKEN_SCROLL_BARS);
- mHeldMotionless = MOTIONLESS_TRUE;
- mTouchMode = TOUCH_DONE_MODE;
- nativeHideCursor();
+ cancelTouch();
break;
}
}
return true;
}
+ private void startTouch(float x, float y, long eventTime) {
+ // Remember where the motion event started
+ mLastTouchX = x;
+ mLastTouchY = y;
+ mLastTouchTime = eventTime;
+ mVelocityTracker = VelocityTracker.obtain();
+ mSnapScrollMode = SNAP_NONE;
+ if (mDragTracker != null) {
+ mDragTrackerHandler = new DragTrackerHandler(x, y, mDragTracker);
+ }
+ }
+
+ private void cancelTouch() {
+ if (mDragTrackerHandler != null) {
+ mDragTrackerHandler.stopDrag();
+ mDragTrackerHandler = null;
+ }
+ // we also use mVelocityTracker == null to tell us that we are
+ // not "moving around", so we can take the slower/prettier
+ // mode in the drawing code
+ if (mVelocityTracker != null) {
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ }
+ if (mTouchMode == TOUCH_DRAG_MODE) {
+ WebViewCore.resumePriority(mWebViewCore);
+ }
+ mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
+ mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
+ mPrivateHandler.removeMessages(DRAG_HELD_MOTIONLESS);
+ mPrivateHandler.removeMessages(AWAKEN_SCROLL_BARS);
+ mHeldMotionless = MOTIONLESS_TRUE;
+ mTouchMode = TOUCH_DONE_MODE;
+ nativeHideCursor();
+ }
+
private long mTrackballFirstTime = 0;
private long mTrackballLastTime = 0;
private float mTrackballRemainsX = 0.0f;
@@ -4853,7 +5016,7 @@
vy = vy * 3 / 4;
}
if ((maxX == 0 && vy == 0) || (maxY == 0 && vx == 0)) {
- WebViewCore.resumeUpdate(mWebViewCore);
+ WebViewCore.resumePriority(mWebViewCore);
return;
}
float currentVelocity = mScroller.getCurrVelocity();
@@ -4887,7 +5050,7 @@
// want to calculate how long the animation is going to run to precisely
// resume the webcore update.
final int time = mScroller.getDuration();
- mPrivateHandler.sendEmptyMessageDelayed(RESUME_WEBCORE_UPDATE, time);
+ mPrivateHandler.sendEmptyMessageDelayed(RESUME_WEBCORE_PRIORITY, time);
awakenScrollBars(time);
invalidate();
}
@@ -4902,7 +5065,7 @@
scale = mDefaultScale;
}
- setNewZoomScale(scale, false);
+ setNewZoomScale(scale, true, false);
if (oldScale != mActualScale) {
// use mZoomPickerScale to see zoom preview first
@@ -4910,9 +5073,6 @@
mInvInitialZoomScale = 1.0f / oldScale;
mInvFinalZoomScale = 1.0f / mActualScale;
mZoomScale = mActualScale;
- if (!mInZoomOverview) {
- mLastScale = scale;
- }
invalidate();
return true;
} else {
@@ -5010,18 +5170,13 @@
public boolean zoomIn() {
// TODO: alternatively we can disallow this during draw history mode
switchOutDrawHistory();
+ mInZoomOverview = false;
// Center zooming to the center of the screen.
- if (mInZoomOverview) {
- // if in overview mode, bring it back to normal mode
- mLastTouchX = getViewWidth() * .5f;
- mLastTouchY = getViewHeight() * .5f;
- doDoubleTap();
- return true;
- } else {
- mZoomCenterX = getViewWidth() * .5f;
- mZoomCenterY = getViewHeight() * .5f;
- return zoomWithPreview(mActualScale * 1.25f);
- }
+ mZoomCenterX = getViewWidth() * .5f;
+ mZoomCenterY = getViewHeight() * .5f;
+ mAnchorX = viewToContentX((int) mZoomCenterX + mScrollX);
+ mAnchorY = viewToContentY((int) mZoomCenterY + mScrollY);
+ return zoomWithPreview(mActualScale * 1.25f);
}
/**
@@ -5031,20 +5186,12 @@
public boolean zoomOut() {
// TODO: alternatively we can disallow this during draw history mode
switchOutDrawHistory();
- float scale = mActualScale * 0.8f;
- if (scale < (mMinZoomScale + 0.1f)
- && mWebViewCore.getSettings().getUseWideViewPort()
- && mZoomOverviewWidth > Math.ceil(getViewWidth()
- * mInvActualScale)) {
- // when zoom out to min scale, switch to overview mode
- doDoubleTap();
- return true;
- } else {
- // Center zooming to the center of the screen.
- mZoomCenterX = getViewWidth() * .5f;
- mZoomCenterY = getViewHeight() * .5f;
- return zoomWithPreview(scale);
- }
+ // Center zooming to the center of the screen.
+ mZoomCenterX = getViewWidth() * .5f;
+ mZoomCenterY = getViewHeight() * .5f;
+ mAnchorX = viewToContentX((int) mZoomCenterX + mScrollX);
+ mAnchorY = viewToContentY((int) mZoomCenterY + mScrollY);
+ return zoomWithPreview(mActualScale * 0.8f);
}
private void updateSelection() {
@@ -5088,7 +5235,7 @@
mLastTouchTime = eventTime;
if (!mScroller.isFinished()) {
abortAnimation();
- mPrivateHandler.removeMessages(RESUME_WEBCORE_UPDATE);
+ mPrivateHandler.removeMessages(RESUME_WEBCORE_PRIORITY);
}
mSnapScrollMode = SNAP_NONE;
mVelocityTracker = VelocityTracker.obtain();
@@ -5168,15 +5315,21 @@
}
}
+ // Rule for double tap:
+ // 1. if the current scale is not same as the text wrap scale and layout
+ // algorithm is NARROW_COLUMNS, fit to column;
+ // 2. if the current state is not overview mode, change to overview mode;
+ // 3. if the current state is overview mode, change to default scale.
private void doDoubleTap() {
if (mWebViewCore.getSettings().getUseWideViewPort() == false) {
return;
}
mZoomCenterX = mLastTouchX;
mZoomCenterY = mLastTouchY;
- mInZoomOverview = !mInZoomOverview;
- // remove the zoom control after double tap
+ mAnchorX = viewToContentX((int) mZoomCenterX + mScrollX);
+ mAnchorY = viewToContentY((int) mZoomCenterY + mScrollY);
WebSettings settings = getSettings();
+ // remove the zoom control after double tap
if (settings.getBuiltInZoomControls()) {
if (mZoomButtonsController.isVisible()) {
mZoomButtonsController.setVisible(false);
@@ -5190,28 +5343,45 @@
}
}
settings.setDoubleTapToastCount(0);
- if (mInZoomOverview) {
+ boolean zoomToDefault = false;
+ if ((settings.getLayoutAlgorithm() == WebSettings.LayoutAlgorithm.NARROW_COLUMNS)
+ && (Math.abs(mActualScale - mTextWrapScale) >= 0.01f)) {
+ setNewZoomScale(mActualScale, true, true);
+ float overviewScale = (float) getViewWidth() / mZoomOverviewWidth;
+ if (Math.abs(mActualScale - overviewScale) < 0.01f) {
+ mInZoomOverview = true;
+ }
+ } else if (!mInZoomOverview) {
float newScale = (float) getViewWidth() / mZoomOverviewWidth;
- if (Math.abs(mActualScale - newScale) < 0.01f) {
- // reset mInZoomOverview to false if scale doesn't change
- mInZoomOverview = false;
- } else {
+ if (Math.abs(mActualScale - newScale) >= 0.01f) {
+ mInZoomOverview = true;
// Force the titlebar fully reveal in overview mode
if (mScrollY < getTitleHeight()) mScrollY = 0;
zoomWithPreview(newScale);
+ } else if (Math.abs(mActualScale - mDefaultScale) >= 0.01f) {
+ zoomToDefault = true;
}
} else {
- // mLastTouchX and mLastTouchY are the point in the current viewport
- int contentX = viewToContentX((int) mLastTouchX + mScrollX);
- int contentY = viewToContentY((int) mLastTouchY + mScrollY);
- int left = nativeGetBlockLeftEdge(contentX, contentY, mActualScale);
+ zoomToDefault = true;
+ }
+ if (zoomToDefault) {
+ mInZoomOverview = false;
+ int left = nativeGetBlockLeftEdge(mAnchorX, mAnchorY, mActualScale);
if (left != NO_LEFTEDGE) {
- // add a 5pt padding to the left edge. Re-calculate the zoom
- // center so that the new scroll x will be on the left edge.
- mZoomCenterX = left < 5 ? 0 : (left - 5) * mLastScale
- * mActualScale / (mLastScale - mActualScale);
+ // add a 5pt padding to the left edge.
+ int viewLeft = contentToViewX(left < 5 ? 0 : (left - 5))
+ - mScrollX;
+ // Re-calculate the zoom center so that the new scroll x will be
+ // on the left edge.
+ if (viewLeft > 0) {
+ mZoomCenterX = viewLeft * mDefaultScale
+ / (mDefaultScale - mActualScale);
+ } else {
+ scrollBy(viewLeft, 0);
+ mZoomCenterX = 0;
+ }
}
- zoomWithPreview(mLastScale);
+ zoomWithPreview(mDefaultScale);
}
}
@@ -5503,9 +5673,6 @@
boolean hasRestoreState = restoreState != null;
if (hasRestoreState) {
mInZoomOverview = false;
- mLastScale = mInitialScaleInPercent > 0
- ? mInitialScaleInPercent / 100.0f
- : restoreState.mTextWrapScale;
if (restoreState.mMinScale == 0) {
if (restoreState.mMobileSite) {
if (draw.mMinPrefWidth >
@@ -5513,6 +5680,8 @@
mMinZoomScale = (float) viewWidth
/ draw.mMinPrefWidth;
mMinZoomScaleFixed = false;
+ mInZoomOverview = useWideViewport &&
+ settings.getLoadWithOverviewMode();
} else {
mMinZoomScale = restoreState.mDefaultScale;
mMinZoomScaleFixed = true;
@@ -5530,17 +5699,29 @@
} else {
mMaxZoomScale = restoreState.mMaxScale;
}
- setNewZoomScale(mLastScale, false);
+ if (mInitialScaleInPercent > 0) {
+ setNewZoomScale(mInitialScaleInPercent / 100.0f,
+ mInitialScaleInPercent != mTextWrapScale * 100,
+ false);
+ } else if (restoreState.mViewScale > 0) {
+ mTextWrapScale = restoreState.mTextWrapScale;
+ setNewZoomScale(restoreState.mViewScale, false,
+ false);
+ } else {
+ mInZoomOverview = useWideViewport
+ && settings.getLoadWithOverviewMode();
+ float scale;
+ if (mInZoomOverview) {
+ scale = (float) viewWidth
+ / DEFAULT_VIEWPORT_WIDTH;
+ } else {
+ scale = restoreState.mTextWrapScale;
+ }
+ setNewZoomScale(scale, Math.abs(scale
+ - mTextWrapScale) >= 0.01f, false);
+ }
setContentScrollTo(restoreState.mScrollX,
restoreState.mScrollY);
- if (useWideViewport
- && settings.getLoadWithOverviewMode()) {
- if (restoreState.mViewScale == 0
- || (restoreState.mMobileSite
- && mMinZoomScale < restoreState.mDefaultScale)) {
- mInZoomOverview = true;
- }
- }
// As we are on a new page, remove the WebTextView. This
// is necessary for page loads driven by webkit, and in
// particular when the user was on a password field, so
@@ -5570,11 +5751,14 @@
mPictureListener.onNewPicture(WebView.this, capturePicture());
}
if (useWideViewport) {
- // limit mZoomOverviewWidth to sMaxViewportWidth so that
- // if the page doesn't behave well, the WebView won't go
- // insane.
+ // limit mZoomOverviewWidth upper bound to
+ // sMaxViewportWidth so that if the page doesn't behave
+ // well, the WebView won't go insane. limit the lower
+ // bound to match the default scale for mobile sites.
mZoomOverviewWidth = Math.min(sMaxViewportWidth, Math
- .max(draw.mMinPrefWidth, draw.mViewPoint.x));
+ .max((int) (viewWidth / mDefaultScale), Math
+ .max(draw.mMinPrefWidth,
+ draw.mViewPoint.x)));
}
if (!mMinZoomScaleFixed) {
mMinZoomScale = (float) viewWidth / mZoomOverviewWidth;
@@ -5585,7 +5769,8 @@
if (Math.abs((viewWidth * mInvActualScale)
- mZoomOverviewWidth) > 1) {
setNewZoomScale((float) viewWidth
- / mZoomOverviewWidth, false);
+ / mZoomOverviewWidth, Math.abs(mActualScale
+ - mTextWrapScale) < 0.01f, false);
}
}
if (draw.mFocusSizeChanged && inEditingMode()) {
@@ -5710,8 +5895,8 @@
mWebTextView.setAdapterCustom(adapter);
}
break;
- case RESUME_WEBCORE_UPDATE:
- WebViewCore.resumeUpdate(mWebViewCore);
+ case RESUME_WEBCORE_PRIORITY:
+ WebViewCore.resumePriority(mWebViewCore);
break;
case LONG_PRESS_CENTER:
@@ -5789,7 +5974,7 @@
doMotionUp(msg.arg1, msg.arg2);
break;
- case SHOW_FULLSCREEN:
+ case SHOW_FULLSCREEN: {
WebViewCore.PluginFullScreenData data
= (WebViewCore.PluginFullScreenData) msg.obj;
if (data.mNpp != 0 && data.mView != null) {
@@ -5837,15 +6022,19 @@
if (width > viewWidth || height > viewHeight) {
mZoomCenterX = viewWidth * .5f;
mZoomCenterY = viewHeight * .5f;
+ // do not change text wrap scale so that there is no
+ // reflow
setNewZoomScale(mActualScale
/ Math.max((float) width / viewWidth,
- (float) height / viewHeight), false);
+ (float) height / viewHeight), false,
+ false);
}
// Now update the bound
mFullScreenHolder.updateBound(contentToViewX(data.mDocX)
- mScrollX, contentToViewY(data.mDocY) - mScrollY,
contentToViewDimension(data.mDocWidth),
contentToViewDimension(data.mDocHeight));
+ }
break;
case HIDE_FULLSCREEN:
@@ -5862,6 +6051,44 @@
}
break;
+ case SHOW_RECT_MSG_ID: {
+ WebViewCore.ShowRectData data = (WebViewCore.ShowRectData) msg.obj;
+ int x = mScrollX;
+ int left = contentToViewDimension(data.mLeft);
+ int width = contentToViewDimension(data.mWidth);
+ int maxWidth = contentToViewDimension(data.mContentWidth);
+ int viewWidth = getViewWidth();
+ if (width < viewWidth) {
+ // center align
+ x += left + width / 2 - mScrollX - viewWidth / 2;
+ } else {
+ x += (int) (left + data.mXPercentInDoc * width
+ - mScrollX - data.mXPercentInView * viewWidth);
+ }
+ // use the passing content width to cap x as the current
+ // mContentWidth may not be updated yet
+ x = Math.max(0,
+ (Math.min(maxWidth, x + viewWidth)) - viewWidth);
+ int y = mScrollY;
+ int top = contentToViewDimension(data.mTop);
+ int height = contentToViewDimension(data.mHeight);
+ int maxHeight = contentToViewDimension(data.mContentHeight);
+ int viewHeight = getViewHeight();
+ if (height < viewHeight) {
+ // middle align
+ y += top + height / 2 - mScrollY - viewHeight / 2;
+ } else {
+ y += (int) (top + data.mYPercentInDoc * height
+ - mScrollY - data.mYPercentInView * viewHeight);
+ }
+ // use the passing content height to cap y as the current
+ // mContentHeight may not be updated yet
+ y = Math.max(0,
+ (Math.min(maxHeight, y + viewHeight) - viewHeight));
+ scrollTo(x, y);
+ }
+ break;
+
default:
super.handleMessage(msg);
break;
diff --git a/core/java/android/webkit/WebViewCore.java b/core/java/android/webkit/WebViewCore.java
index d509bb4..6700d71 100644
--- a/core/java/android/webkit/WebViewCore.java
+++ b/core/java/android/webkit/WebViewCore.java
@@ -482,8 +482,8 @@
should this be called nativeSetViewPortSize?
*/
private native void nativeSetSize(int width, int height, int screenWidth,
- float scale, int realScreenWidth, int screenHeight,
- boolean ignoreHeight);
+ float scale, int realScreenWidth, int screenHeight, int anchorX,
+ int anchorY, boolean ignoreHeight);
private native int nativeGetContentMinPrefWidth();
@@ -1033,6 +1033,7 @@
(WebView.ViewSizeData) msg.obj;
viewSizeChanged(data.mWidth, data.mHeight,
data.mTextWrapWidth, data.mScale,
+ data.mAnchorX, data.mAnchorY,
data.mIgnoreHeight);
break;
}
@@ -1584,7 +1585,7 @@
// notify webkit that our virtual view size changed size (after inv-zoom)
private void viewSizeChanged(int w, int h, int textwrapWidth, float scale,
- boolean ignoreHeight) {
+ int anchorX, int anchorY, boolean ignoreHeight) {
if (DebugFlags.WEB_VIEW_CORE) {
Log.v(LOGTAG, "viewSizeChanged w=" + w + "; h=" + h
+ "; textwrapWidth=" + textwrapWidth + "; scale=" + scale);
@@ -1616,12 +1617,14 @@
Math.max(WebView.DEFAULT_VIEWPORT_WIDTH,
nativeGetContentMinPrefWidth())));
}
- } else {
+ } else if (mViewportWidth > 0) {
width = Math.max(w, mViewportWidth);
+ } else {
+ width = textwrapWidth;
}
}
nativeSetSize(width, width == w ? h : Math.round((float) width * h / w),
- textwrapWidth, scale, w, h, ignoreHeight);
+ textwrapWidth, scale, w, h, anchorX, anchorY, ignoreHeight);
// Remember the current width and height
boolean needInvalidate = (mCurrentViewWidth == 0);
mCurrentViewWidth = w;
@@ -1778,7 +1781,7 @@
return result;
}
- static void pauseUpdate(WebViewCore core) {
+ static void reducePriority(WebViewCore core) {
// remove the pending REDUCE_PRIORITY and RESUME_PRIORITY messages
sWebCoreHandler.removeMessages(WebCoreThread.REDUCE_PRIORITY);
sWebCoreHandler.removeMessages(WebCoreThread.RESUME_PRIORITY);
@@ -1786,7 +1789,7 @@
.obtainMessage(WebCoreThread.REDUCE_PRIORITY));
}
- static void resumeUpdate(WebViewCore core) {
+ static void resumePriority(WebViewCore core) {
// remove the pending REDUCE_PRIORITY and RESUME_PRIORITY messages
sWebCoreHandler.removeMessages(WebCoreThread.REDUCE_PRIORITY);
sWebCoreHandler.removeMessages(WebCoreThread.RESUME_PRIORITY);
@@ -2070,14 +2073,12 @@
mRestoreState.mScrollY = mRestoredY;
mRestoreState.mMobileSite = (0 == mViewportWidth);
if (mRestoredScale > 0) {
+ mRestoreState.mViewScale = mRestoredScale / 100.0f;
if (mRestoredScreenWidthScale > 0) {
mRestoreState.mTextWrapScale =
mRestoredScreenWidthScale / 100.0f;
- // 0 will trigger WebView to turn on zoom overview mode
- mRestoreState.mViewScale = 0;
} else {
- mRestoreState.mViewScale = mRestoreState.mTextWrapScale =
- mRestoredScale / 100.0f;
+ mRestoreState.mTextWrapScale = mRestoreState.mViewScale;
}
} else {
if (mViewportInitialScale > 0) {
@@ -2110,6 +2111,7 @@
data.mTextWrapWidth = data.mWidth;
data.mScale = -1.0f;
data.mIgnoreHeight = false;
+ data.mAnchorX = data.mAnchorY = 0;
// send VIEW_SIZE_CHANGED to the front of the queue so that we can
// avoid pushing the wrong picture to the WebView side. If there is
// a VIEW_SIZE_CHANGED in the queue, probably from WebView side,
@@ -2145,6 +2147,7 @@
data.mTextWrapWidth = Math.round(webViewWidth
/ mRestoreState.mTextWrapScale);
data.mIgnoreHeight = false;
+ data.mAnchorX = data.mAnchorY = 0;
// send VIEW_SIZE_CHANGED to the front of the queue so that we
// can avoid pushing the wrong picture to the WebView side.
mEventHub.removeMessages(EventHub.VIEW_SIZE_CHANGED);
@@ -2364,6 +2367,40 @@
childView.removeView();
}
+ // called by JNI
+ static class ShowRectData {
+ int mLeft;
+ int mTop;
+ int mWidth;
+ int mHeight;
+ int mContentWidth;
+ int mContentHeight;
+ float mXPercentInDoc;
+ float mXPercentInView;
+ float mYPercentInDoc;
+ float mYPercentInView;
+ }
+
+ private void showRect(int left, int top, int width, int height,
+ int contentWidth, int contentHeight, float xPercentInDoc,
+ float xPercentInView, float yPercentInDoc, float yPercentInView) {
+ if (mWebView != null) {
+ ShowRectData data = new ShowRectData();
+ data.mLeft = left;
+ data.mTop = top;
+ data.mWidth = width;
+ data.mHeight = height;
+ data.mContentWidth = contentWidth;
+ data.mContentHeight = contentHeight;
+ data.mXPercentInDoc = xPercentInDoc;
+ data.mXPercentInView = xPercentInView;
+ data.mYPercentInDoc = yPercentInDoc;
+ data.mYPercentInView = yPercentInView;
+ Message.obtain(mWebView.mPrivateHandler, WebView.SHOW_RECT_MSG_ID,
+ data).sendToTarget();
+ }
+ }
+
private native void nativePause();
private native void nativeResume();
private native void nativeFreeMemory();
diff --git a/include/media/IOMX.h b/include/media/IOMX.h
index bb7677df..2f61cbe 100644
--- a/include/media/IOMX.h
+++ b/include/media/IOMX.h
@@ -166,6 +166,7 @@
OMX_U32 flags;
OMX_TICKS timestamp;
OMX_PTR platform_private;
+ OMX_PTR data_ptr;
} extended_buffer_data;
} u;
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index ac2f662..82dd2b5 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -94,6 +94,7 @@
kRequiresFlushCompleteEmulation = 16,
kRequiresAllocateBufferOnOutputPorts = 32,
kRequiresFlushBeforeShutdown = 64,
+ kDefersOutputBufferAllocation = 128,
};
struct BufferInfo {
diff --git a/include/ui/CameraParameters.h b/include/ui/CameraParameters.h
index 9e4e140..a5ea133 100644
--- a/include/ui/CameraParameters.h
+++ b/include/ui/CameraParameters.h
@@ -109,9 +109,10 @@
// The height (in pixels) of EXIF thumbnail in Jpeg picture.
// Example value: "384". Read/write.
static const char KEY_JPEG_THUMBNAIL_HEIGHT[];
- // Supported EXIF thumbnail sizes (width x height).
- // Example value: "512x384,320x240". Read only.
- static const char KEY_SUPPORTED_THUMBNAIL_SIZES[];
+ // Supported EXIF thumbnail sizes (width x height). 0x0 means not thumbnail
+ // in EXIF.
+ // Example value: "512x384,320x240,0x0". Read only.
+ static const char KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES[];
// The quality of the EXIF thumbnail in Jpeg picture. The range is 1 to 100,
// with 100 being the best.
// Example value: "90". Read/write.
diff --git a/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp
index cf6d7fc..2c9bdaa 100644
--- a/libs/rs/rsProgramVertex.cpp
+++ b/libs/rs/rsProgramVertex.cpp
@@ -168,27 +168,27 @@
}
mShader.append(mUserShader);
} else {
+ mShader.append("attribute vec4 ATTRIB_LegacyPosition;\n");
+ mShader.append("attribute vec4 ATTRIB_LegacyColor;\n");
+ mShader.append("attribute vec3 ATTRIB_LegacyNormal;\n");
+ mShader.append("attribute float ATTRIB_LegacyPointSize;\n");
+ mShader.append("attribute vec4 ATTRIB_LegacyTexture;\n");
+
for (uint32_t ct=0; ct < mUniformCount; ct++) {
mShader.append("uniform mat4 ");
mShader.append(mUniformNames[ct]);
mShader.append(";\n");
}
- for (uint32_t ct=VertexArray::POSITION; ct < mAttribCount; ct++) {
- mShader.append("attribute vec4 ");
- mShader.append(mAttribNames[ct]);
- mShader.append(";\n");
- }
-
mShader.append("void main() {\n");
- mShader.append(" gl_Position = UNI_MVP * ATTRIB_Position;\n");
- mShader.append(" gl_PointSize = ATTRIB_PointSize.x;\n");
+ mShader.append(" gl_Position = UNI_MVP * ATTRIB_LegacyPosition;\n");
+ mShader.append(" gl_PointSize = ATTRIB_LegacyPointSize;\n");
- mShader.append(" varColor = ATTRIB_Color;\n");
+ mShader.append(" varColor = ATTRIB_LegacyColor;\n");
if (mTextureMatrixEnable) {
- mShader.append(" varTex0 = UNI_TexMatrix * ATTRIB_Texture;\n");
+ mShader.append(" varTex0 = UNI_TexMatrix * ATTRIB_LegacyTexture;\n");
} else {
- mShader.append(" varTex0 = ATTRIB_Texture;\n");
+ mShader.append(" varTex0 = ATTRIB_LegacyTexture;\n");
}
//mShader.append(" pos.x = pos.x / 480.0;\n");
//mShader.append(" pos.y = pos.y / 800.0;\n");
@@ -326,10 +326,11 @@
}
}
+
void ProgramVertex::init(Context *rsc)
{
+ mAttribCount = 0;
if (mUserShader.size() > 0) {
- mAttribCount = 0;
for (uint32_t ct=0; ct < mInputCount; ct++) {
initAddUserElement(mInputElements[ct].get(), mAttribNames, &mAttribCount, "ATTRIB_");
}
@@ -340,13 +341,6 @@
initAddUserElement(mConstantTypes[ct]->getElement(), mUniformNames, &mUniformCount, "UNI_");
}
} else {
- mAttribCount = 5;
- mAttribNames[0].setTo("ATTRIB_Position");
- mAttribNames[1].setTo("ATTRIB_Color");
- mAttribNames[2].setTo("ATTRIB_Normal");
- mAttribNames[3].setTo("ATTRIB_PointSize");
- mAttribNames[4].setTo("ATTRIB_Texture");
-
mUniformCount = 2;
mUniformNames[0].setTo("UNI_MVP");
mUniformNames[1].setTo("UNI_TexMatrix");
diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp
index eeb9468..6b8ed0d 100644
--- a/libs/rs/rsScriptC_Lib.cpp
+++ b/libs/rs/rsScriptC_Lib.cpp
@@ -687,7 +687,7 @@
float vtx[] = { x1, y1, z1, x2, y2, z2 };
VertexArray va;
- va.setPosition(2, GL_FLOAT, 12, (uint32_t)&vtx);
+ va.addLegacy(GL_FLOAT, 3, 12, RS_KIND_POSITION, false, (uint32_t)vtx);
if (rsc->checkVersion2_0()) {
va.setupGL2(rsc, &rsc->mStateVertexArray, &rsc->mShaderCache);
} else {
@@ -705,7 +705,7 @@
float vtx[] = { x, y, z };
VertexArray va;
- va.setPosition(1, GL_FLOAT, 12, (uint32_t)&vtx);
+ va.addLegacy(GL_FLOAT, 3, 12, RS_KIND_POSITION, false, (uint32_t)vtx);
if (rsc->checkVersion2_0()) {
va.setupGL2(rsc, &rsc->mStateVertexArray, &rsc->mShaderCache);
} else {
@@ -737,8 +737,8 @@
const float tex[] = {u1,v1, u2,v2, u3,v3, u4,v4};
VertexArray va;
- va.setPosition(3, GL_FLOAT, 12, (uint32_t)&vtx);
- va.setTexture(2, GL_FLOAT, 8, (uint32_t)&tex);
+ va.addLegacy(GL_FLOAT, 3, 12, RS_KIND_POSITION, false, (uint32_t)vtx);
+ va.addLegacy(GL_FLOAT, 2, 8, RS_KIND_TEXTURE, false, (uint32_t)tex);
if (rsc->checkVersion2_0()) {
va.setupGL2(rsc, &rsc->mStateVertexArray, &rsc->mShaderCache);
} else {
diff --git a/libs/rs/rsShaderCache.cpp b/libs/rs/rsShaderCache.cpp
index 8ac2487..3a1f370 100644
--- a/libs/rs/rsShaderCache.cpp
+++ b/libs/rs/rsShaderCache.cpp
@@ -86,6 +86,7 @@
e->vtx = vtx->getShaderID();
e->frag = frag->getShaderID();
e->program = glCreateProgram();
+ e->mUserVertexProgram = vtx->isUserProgram();
if (mEntries[mEntryCount].program) {
GLuint pgm = e->program;
glAttachShader(pgm, vtx->getShaderID());
@@ -93,13 +94,16 @@
glAttachShader(pgm, frag->getShaderID());
if (!vtx->isUserProgram()) {
- glBindAttribLocation(pgm, VertexArray::POSITION, "ATTRIB_Position");
- glBindAttribLocation(pgm, VertexArray::COLOR, "ATTRIB_Color");
- glBindAttribLocation(pgm, VertexArray::NORMAL, "ATTRIB_Normal");
- glBindAttribLocation(pgm, VertexArray::POINT_SIZE, "ATTRIB_PointSize");
- glBindAttribLocation(pgm, VertexArray::TEXTURE, "ATTRIB_T0");
- } else {
-
+ glBindAttribLocation(pgm, 0, "ATTRIB_LegacyPosition");
+ glBindAttribLocation(pgm, 1, "ATTRIB_LegacyColor");
+ glBindAttribLocation(pgm, 2, "ATTRIB_LegacyNormal");
+ glBindAttribLocation(pgm, 3, "ATTRIB_LegacyPointSize");
+ glBindAttribLocation(pgm, 4, "ATTRIB_LegacyTexture");
+ e->mVtxAttribSlots[RS_KIND_POSITION] = 0;
+ e->mVtxAttribSlots[RS_KIND_COLOR] = 1;
+ e->mVtxAttribSlots[RS_KIND_NORMAL] = 2;
+ e->mVtxAttribSlots[RS_KIND_POINT_SIZE] = 3;
+ e->mVtxAttribSlots[RS_KIND_TEXTURE] = 4;
}
//LOGE("e2 %x", glGetError());
@@ -120,10 +124,12 @@
}
glDeleteProgram(pgm);
}
- for (uint32_t ct=0; ct < vtx->getAttribCount(); ct++) {
- e->mVtxAttribSlots[ct] = glGetAttribLocation(pgm, vtx->getAttribName(ct));
- if (rsc->props.mLogShaders) {
- LOGV("vtx A %i, %s = %d\n", ct, vtx->getAttribName(ct).string(), e->mVtxAttribSlots[ct]);
+ if (vtx->isUserProgram()) {
+ for (uint32_t ct=0; ct < vtx->getAttribCount(); ct++) {
+ e->mVtxAttribSlots[ct] = glGetAttribLocation(pgm, vtx->getAttribName(ct));
+ if (rsc->props.mLogShaders) {
+ LOGV("vtx A %i, %s = %d\n", ct, vtx->getAttribName(ct).string(), e->mVtxAttribSlots[ct]);
+ }
}
}
for (uint32_t ct=0; ct < vtx->getUniformCount(); ct++) {
diff --git a/libs/rs/rsShaderCache.h b/libs/rs/rsShaderCache.h
index ede3734..7aa8183 100644
--- a/libs/rs/rsShaderCache.h
+++ b/libs/rs/rsShaderCache.h
@@ -44,6 +44,7 @@
int32_t vtxUniformSlot(uint32_t a) const {return mCurrent->mVtxUniformSlots[a];}
int32_t fragAttribSlot(uint32_t a) const {return mCurrent->mFragAttribSlots[a];}
int32_t fragUniformSlot(uint32_t a) const {return mCurrent->mFragUniformSlots[a];}
+ bool isUserVertexProgram() const {return mCurrent->mUserVertexProgram;}
protected:
typedef struct {
@@ -54,6 +55,7 @@
int32_t mVtxUniformSlots[Program::MAX_UNIFORMS];
int32_t mFragAttribSlots[Program::MAX_ATTRIBS];
int32_t mFragUniformSlots[Program::MAX_UNIFORMS];
+ bool mUserVertexProgram;
} entry_t;
entry_t *mEntries;
entry_t *mCurrent;
diff --git a/libs/rs/rsType.cpp b/libs/rs/rsType.cpp
index ddadd9f..22a267a 100644
--- a/libs/rs/rsType.cpp
+++ b/libs/rs/rsType.cpp
@@ -207,36 +207,48 @@
uint32_t stride = mElement->getSizeBytes();
if (mGL.mVtx.size) {
- va->setPosition(mGL.mVtx.size,
- mGL.mVtx.type,
- stride,
- mGL.mVtx.offset);
+ va->addLegacy(mGL.mVtx.type,
+ mGL.mVtx.size,
+ stride,
+ RS_KIND_POSITION,
+ false,
+ mGL.mVtx.offset);
}
if (mGL.mNorm.size) {
- va->setNormal(mGL.mNorm.type,
- stride,
- mGL.mNorm.offset);
+ va->addLegacy(mGL.mNorm.type,
+ 3,
+ stride,
+ RS_KIND_NORMAL,
+ false,
+ mGL.mNorm.offset);
}
if (mGL.mColor.size) {
- va->setColor(mGL.mColor.size,
- mGL.mColor.type,
+ va->addLegacy(mGL.mColor.type,
+ mGL.mColor.size,
stride,
+ RS_KIND_COLOR,
+ true,
mGL.mColor.offset);
}
if (mGL.mTex.size) {
- va->setTexture(mGL.mTex.size,
- mGL.mTex.type,
- stride,
- mGL.mTex.offset);
+ va->addLegacy(mGL.mTex.type,
+ mGL.mTex.size,
+ stride,
+ RS_KIND_TEXTURE,
+ false,
+ mGL.mTex.offset);
}
if (mGL.mPointSize.size) {
- va->setPointSize(mGL.mPointSize.type,
- stride,
- mGL.mPointSize.offset);
+ va->addLegacy(mGL.mPointSize.type,
+ 1,
+ stride,
+ RS_KIND_POINT_SIZE,
+ false,
+ mGL.mPointSize.offset);
}
}
@@ -249,7 +261,7 @@
uint32_t stride = mElement->getSizeBytes();
for (uint32_t ct=0; ct < RS_MAX_ATTRIBS; ct++) {
if (mGL.mUser[ct].size) {
- va->setUser(mGL.mUser[ct], stride);
+ va->addUser(mGL.mUser[ct], stride);
}
}
}
diff --git a/libs/rs/rsVertexArray.cpp b/libs/rs/rsVertexArray.cpp
index 7124eb5..a1fd744 100644
--- a/libs/rs/rsVertexArray.cpp
+++ b/libs/rs/rsVertexArray.cpp
@@ -25,7 +25,7 @@
VertexArray::VertexArray()
{
- mActiveBuffer = 0;
+ clearAll();
}
VertexArray::~VertexArray()
@@ -39,6 +39,7 @@
mAttribs[ct].clear();
}
mActiveBuffer = 0;
+ mCount = 0;
}
VertexArray::Attrib::Attrib()
@@ -54,6 +55,7 @@
size = a.size;
stride = a.stride;
normalized = a.normalized;
+ kind = RS_KIND_USER;
name.setTo(a.name);
}
@@ -68,78 +70,42 @@
name.setTo("");
}
-void VertexArray::clear(AttribName n)
+void VertexArray::clear(uint32_t n)
{
mAttribs[n].clear();
}
-void VertexArray::setPosition(uint32_t size, uint32_t type, uint32_t stride, uint32_t offset)
+void VertexArray::addUser(const Attrib &a, uint32_t stride)
{
- mAttribs[POSITION].buffer = mActiveBuffer;
- mAttribs[POSITION].type = type;
- mAttribs[POSITION].size = size;
- mAttribs[POSITION].offset = offset;
- mAttribs[POSITION].stride = stride;
- mAttribs[POSITION].normalized = false;
+ assert(mCount < RS_MAX_ATTRIBS);
+ mAttribs[mCount].set(a);
+ mAttribs[mCount].buffer = mActiveBuffer;
+ mAttribs[mCount].stride = stride;
+ mAttribs[mCount].kind = RS_KIND_USER;
+ mCount ++;
}
-void VertexArray::setColor(uint32_t size, uint32_t type, uint32_t stride, uint32_t offset)
+void VertexArray::addLegacy(uint32_t type, uint32_t size, uint32_t stride, RsDataKind kind, bool normalized, uint32_t offset)
{
- mAttribs[COLOR].buffer = mActiveBuffer;
- mAttribs[COLOR].type = type;
- mAttribs[COLOR].size = size;
- mAttribs[COLOR].offset = offset;
- mAttribs[COLOR].stride = stride;
- mAttribs[COLOR].normalized = type != GL_FLOAT;
-}
-
-void VertexArray::setNormal(uint32_t type, uint32_t stride, uint32_t offset)
-{
- mAttribs[NORMAL].buffer = mActiveBuffer;
- mAttribs[NORMAL].type = type;
- mAttribs[NORMAL].size = 3;
- mAttribs[NORMAL].offset = offset;
- mAttribs[NORMAL].stride = stride;
- mAttribs[NORMAL].normalized = type != GL_FLOAT;
-}
-
-void VertexArray::setPointSize(uint32_t type, uint32_t stride, uint32_t offset)
-{
- mAttribs[POINT_SIZE].buffer = mActiveBuffer;
- mAttribs[POINT_SIZE].type = type;
- mAttribs[POINT_SIZE].size = 1;
- mAttribs[POINT_SIZE].offset = offset;
- mAttribs[POINT_SIZE].stride = stride;
- mAttribs[POINT_SIZE].normalized = false;
-}
-
-void VertexArray::setTexture(uint32_t size, uint32_t type, uint32_t stride, uint32_t offset)
-{
- mAttribs[TEXTURE].buffer = mActiveBuffer;
- mAttribs[TEXTURE].type = type;
- mAttribs[TEXTURE].size = size;
- mAttribs[TEXTURE].offset = offset;
- mAttribs[TEXTURE].stride = stride;
- mAttribs[TEXTURE].normalized = false;
-}
-
-void VertexArray::setUser(const Attrib &a, uint32_t stride)
-{
- // Find empty slot, some may be taken by legacy 1.1 slots.
- uint32_t slot = 0;
- while (mAttribs[slot].size) slot++;
- rsAssert(slot < RS_MAX_ATTRIBS);
- mAttribs[slot].set(a);
- mAttribs[slot].buffer = mActiveBuffer;
- mAttribs[slot].stride = stride;
+ assert(mCount < RS_MAX_ATTRIBS);
+ mAttribs[mCount].clear();
+ mAttribs[mCount].type = type;
+ mAttribs[mCount].size = size;
+ mAttribs[mCount].offset = offset;
+ mAttribs[mCount].normalized = normalized;
+ mAttribs[mCount].buffer = mActiveBuffer;
+ mAttribs[mCount].stride = stride;
+ mAttribs[mCount].kind = kind;
+ mCount ++;
}
void VertexArray::logAttrib(uint32_t idx, uint32_t slot) const {
- LOGE("va %i: slot=%i name=%s buf=%i size=%i type=0x%x stride=0x%x norm=%i offset=0x%x", idx, slot,
+ LOGE("va %i: slot=%i name=%s buf=%i size=%i type=0x%x kind=%i stride=0x%x norm=%i offset=0x%x", idx, slot,
mAttribs[idx].name.string(),
mAttribs[idx].buffer,
mAttribs[idx].size,
mAttribs[idx].type,
+ mAttribs[idx].kind,
mAttribs[idx].stride,
mAttribs[idx].normalized,
mAttribs[idx].offset);
@@ -147,87 +113,95 @@
void VertexArray::setupGL(const Context *rsc, class VertexArrayState *state) const
{
- if (mAttribs[POSITION].size) {
- //logAttrib(POSITION);
- glEnableClientState(GL_VERTEX_ARRAY);
- glBindBuffer(GL_ARRAY_BUFFER, mAttribs[POSITION].buffer);
- glVertexPointer(mAttribs[POSITION].size,
- mAttribs[POSITION].type,
- mAttribs[POSITION].stride,
- (void *)mAttribs[POSITION].offset);
- } else {
- rsAssert(0);
- }
-
- if (mAttribs[NORMAL].size) {
- //logAttrib(NORMAL);
- glEnableClientState(GL_NORMAL_ARRAY);
- rsAssert(mAttribs[NORMAL].size == 3);
- glBindBuffer(GL_ARRAY_BUFFER, mAttribs[NORMAL].buffer);
- glNormalPointer(mAttribs[NORMAL].type,
- mAttribs[NORMAL].stride,
- (void *)mAttribs[NORMAL].offset);
- } else {
- glDisableClientState(GL_NORMAL_ARRAY);
- }
-
- if (mAttribs[COLOR].size) {
- //logAttrib(COLOR);
- glEnableClientState(GL_COLOR_ARRAY);
- glBindBuffer(GL_ARRAY_BUFFER, mAttribs[COLOR].buffer);
- glColorPointer(mAttribs[COLOR].size,
- mAttribs[COLOR].type,
- mAttribs[COLOR].stride,
- (void *)mAttribs[COLOR].offset);
- } else {
- glDisableClientState(GL_COLOR_ARRAY);
- }
-
glClientActiveTexture(GL_TEXTURE0);
- if (mAttribs[TEXTURE].size) {
- //logAttrib(TEXTURE);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
- glBindBuffer(GL_ARRAY_BUFFER, mAttribs[TEXTURE].buffer);
- glTexCoordPointer(mAttribs[TEXTURE].size,
- mAttribs[TEXTURE].type,
- mAttribs[TEXTURE].stride,
- (void *)mAttribs[TEXTURE].offset);
- } else {
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_NORMAL_ARRAY);
+ glDisableClientState(GL_COLOR_ARRAY);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glDisableClientState(GL_POINT_SIZE_ARRAY_OES);
+
+ for (uint32_t ct=0; ct < mCount; ct++) {
+ switch(mAttribs[ct].kind) {
+ case RS_KIND_POSITION:
+ //logAttrib(POSITION);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glBindBuffer(GL_ARRAY_BUFFER, mAttribs[ct].buffer);
+ glVertexPointer(mAttribs[ct].size,
+ mAttribs[ct].type,
+ mAttribs[ct].stride,
+ (void *)mAttribs[ct].offset);
+ break;
+
+ case RS_KIND_NORMAL:
+ //logAttrib(NORMAL);
+ glEnableClientState(GL_NORMAL_ARRAY);
+ rsAssert(mAttribs[ct].size == 3);
+ glBindBuffer(GL_ARRAY_BUFFER, mAttribs[ct].buffer);
+ glNormalPointer(mAttribs[ct].type,
+ mAttribs[ct].stride,
+ (void *)mAttribs[ct].offset);
+ break;
+
+ case RS_KIND_COLOR:
+ //logAttrib(COLOR);
+ glEnableClientState(GL_COLOR_ARRAY);
+ glBindBuffer(GL_ARRAY_BUFFER, mAttribs[ct].buffer);
+ glColorPointer(mAttribs[ct].size,
+ mAttribs[ct].type,
+ mAttribs[ct].stride,
+ (void *)mAttribs[ct].offset);
+ break;
+
+ case RS_KIND_TEXTURE:
+ //logAttrib(TEXTURE);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glBindBuffer(GL_ARRAY_BUFFER, mAttribs[ct].buffer);
+ glTexCoordPointer(mAttribs[ct].size,
+ mAttribs[ct].type,
+ mAttribs[ct].stride,
+ (void *)mAttribs[ct].offset);
+ break;
+
+ case RS_KIND_POINT_SIZE:
+ //logAttrib(POINT_SIZE);
+ glEnableClientState(GL_POINT_SIZE_ARRAY_OES);
+ glBindBuffer(GL_ARRAY_BUFFER, mAttribs[ct].buffer);
+ glPointSizePointerOES(mAttribs[ct].type,
+ mAttribs[ct].stride,
+ (void *)mAttribs[ct].offset);
+ break;
+
+ default:
+ rsAssert(0);
+ }
}
- if (mAttribs[POINT_SIZE].size) {
- //logAttrib(POINT_SIZE);
- glEnableClientState(GL_POINT_SIZE_ARRAY_OES);
- glBindBuffer(GL_ARRAY_BUFFER, mAttribs[POINT_SIZE].buffer);
- glPointSizePointerOES(mAttribs[POINT_SIZE].type,
- mAttribs[POINT_SIZE].stride,
- (void *)mAttribs[POINT_SIZE].offset);
- } else {
- glDisableClientState(GL_POINT_SIZE_ARRAY_OES);
- }
rsc->checkError("VertexArray::setupGL");
}
void VertexArray::setupGL2(const Context *rsc, class VertexArrayState *state, ShaderCache *sc) const
{
- for (int ct=1; ct < _LAST; ct++) {
+ for (int ct=1; ct < RS_MAX_ATTRIBS; ct++) {
glDisableVertexAttribArray(ct);
}
- for (uint32_t ct=0; ct < RS_MAX_ATTRIBS; ct++) {
- if (mAttribs[ct].size && (sc->vtxAttribSlot(ct) >= 0)) {
- //logAttrib(ct, sc->vtxAttribSlot(ct));
- glEnableVertexAttribArray(sc->vtxAttribSlot(ct));
- glBindBuffer(GL_ARRAY_BUFFER, mAttribs[ct].buffer);
-
- glVertexAttribPointer(sc->vtxAttribSlot(ct),
- mAttribs[ct].size,
- mAttribs[ct].type,
- mAttribs[ct].normalized,
- mAttribs[ct].stride,
- (void *)mAttribs[ct].offset);
+ for (uint32_t ct=0; ct < mCount; ct++) {
+ uint32_t slot = 0;
+ if (sc->isUserVertexProgram()) {
+ slot = sc->vtxAttribSlot(ct);
+ } else {
+ slot = sc->vtxAttribSlot(mAttribs[ct].kind);
}
+
+ //logAttrib(ct, slot);
+ glEnableVertexAttribArray(slot);
+ glBindBuffer(GL_ARRAY_BUFFER, mAttribs[ct].buffer);
+
+ glVertexAttribPointer(slot,
+ mAttribs[ct].size,
+ mAttribs[ct].type,
+ mAttribs[ct].normalized,
+ mAttribs[ct].stride,
+ (void *)mAttribs[ct].offset);
}
rsc->checkError("VertexArray::setupGL2");
}
diff --git a/libs/rs/rsVertexArray.h b/libs/rs/rsVertexArray.h
index 26e6f84..66b3ab00 100644
--- a/libs/rs/rsVertexArray.h
+++ b/libs/rs/rsVertexArray.h
@@ -33,14 +33,6 @@
VertexArray();
virtual ~VertexArray();
- enum AttribName {
- POSITION,
- COLOR,
- NORMAL,
- POINT_SIZE,
- TEXTURE,
- _LAST
- };
class Attrib {
public:
@@ -51,6 +43,7 @@
uint32_t stride;
bool normalized;
String8 name;
+ RsDataKind kind;
Attrib();
void set(const Attrib &);
@@ -59,23 +52,19 @@
void clearAll();
- void clear(AttribName);
-
void setActiveBuffer(uint32_t id) {mActiveBuffer = id;}
-
- void setUser(const Attrib &, uint32_t stride);
- void setPosition(uint32_t size, uint32_t type, uint32_t stride, uint32_t offset);
- void setColor(uint32_t size, uint32_t type, uint32_t stride, uint32_t offset);
- void setNormal(uint32_t type, uint32_t stride, uint32_t offset);
- void setPointSize(uint32_t type, uint32_t stride, uint32_t offset);
- void setTexture(uint32_t size, uint32_t type, uint32_t stride, uint32_t offset);
+ void addUser(const Attrib &, uint32_t stride);
+ void addLegacy(uint32_t type, uint32_t size, uint32_t stride, RsDataKind kind, bool normalized, uint32_t offset);
void setupGL(const Context *rsc, class VertexArrayState *) const;
void setupGL2(const Context *rsc, class VertexArrayState *, ShaderCache *) const;
void logAttrib(uint32_t idx, uint32_t slot) const;
protected:
+ void clear(uint32_t index);
uint32_t mActiveBuffer;
+ uint32_t mCount;
+
Attrib mAttribs[RS_MAX_ATTRIBS];
};
diff --git a/libs/ui/CameraParameters.cpp b/libs/ui/CameraParameters.cpp
index 8f1749d..2e0409b 100644
--- a/libs/ui/CameraParameters.cpp
+++ b/libs/ui/CameraParameters.cpp
@@ -36,7 +36,7 @@
const char CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS[] = "picture-format-values";
const char CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH[] = "jpeg-thumbnail-width";
const char CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT[] = "jpeg-thumbnail-height";
-const char CameraParameters::KEY_SUPPORTED_THUMBNAIL_SIZES[] = "jpeg-thumbnail-size-values";
+const char CameraParameters::KEY_SUPPORTED_JPEG_THUMBNAIL_SIZES[] = "jpeg-thumbnail-size-values";
const char CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY[] = "jpeg-thumbnail-quality";
const char CameraParameters::KEY_JPEG_QUALITY[] = "jpeg-quality";
const char CameraParameters::KEY_ROTATION[] = "rotation";
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 5352234..e1b1776 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -348,6 +348,9 @@
Mutex::Autolock _l(AudioSystem::gLock);
AudioSystem::gAudioFlinger.clear();
+ // clear output handles and stream to output map caches
+ AudioSystem::gStreamOutputMap.clear();
+ AudioSystem::gOutputs.clear();
if (gAudioErrorCallback) {
gAudioErrorCallback(DEAD_OBJECT);
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 2686489..986dcb2 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -301,8 +301,8 @@
quirks |= kRequiresAllocateBufferOnOutputPorts;
}
if (!strncmp(componentName, "OMX.qcom.video.decoder.", 23)) {
- // XXX Required on P....on only.
quirks |= kRequiresAllocateBufferOnOutputPorts;
+ quirks |= kDefersOutputBufferAllocation;
}
if (!strncmp(componentName, "OMX.TI.", 7)) {
@@ -1237,8 +1237,15 @@
info.mMediaBuffer = NULL;
if (portIndex == kPortIndexOutput) {
- info.mMediaBuffer = new MediaBuffer(info.mData, info.mSize);
- info.mMediaBuffer->setObserver(this);
+ if (!(mOMXLivesLocally
+ && (mQuirks & kRequiresAllocateBufferOnOutputPorts)
+ && (mQuirks & kDefersOutputBufferAllocation))) {
+ // If the node does not fill in the buffer ptr at this time,
+ // we will defer creating the MediaBuffer until receiving
+ // the first FILL_BUFFER_DONE notification instead.
+ info.mMediaBuffer = new MediaBuffer(info.mData, info.mSize);
+ info.mMediaBuffer->setObserver(this);
+ }
}
mPortBuffers[portIndex].push(info);
@@ -1346,6 +1353,22 @@
} else if (mPortStatus[kPortIndexOutput] != SHUTTING_DOWN) {
CHECK_EQ(mPortStatus[kPortIndexOutput], ENABLED);
+ if (info->mMediaBuffer == NULL) {
+ CHECK(mOMXLivesLocally);
+ CHECK(mQuirks & kRequiresAllocateBufferOnOutputPorts);
+ CHECK(mQuirks & kDefersOutputBufferAllocation);
+
+ // The qcom video decoders on Nexus don't actually allocate
+ // output buffer memory on a call to OMX_AllocateBuffer
+ // the "pBuffer" member of the OMX_BUFFERHEADERTYPE
+ // structure is only filled in later.
+
+ info->mMediaBuffer = new MediaBuffer(
+ msg.u.extended_buffer_data.data_ptr,
+ info->mSize);
+ info->mMediaBuffer->setObserver(this);
+ }
+
MediaBuffer *buffer = info->mMediaBuffer;
buffer->set_range(
diff --git a/media/libstagefright/SampleIterator.cpp b/media/libstagefright/SampleIterator.cpp
index faad42ba..7155c61 100644
--- a/media/libstagefright/SampleIterator.cpp
+++ b/media/libstagefright/SampleIterator.cpp
@@ -54,6 +54,10 @@
status_t SampleIterator::seekTo(uint32_t sampleIndex) {
LOGV("seekTo(%d)", sampleIndex);
+ if (sampleIndex >= mTable->mNumSampleSizes) {
+ return ERROR_END_OF_STREAM;
+ }
+
if (mTable->mSampleToChunkOffset < 0
|| mTable->mChunkOffsetOffset < 0
|| mTable->mSampleSizeOffset < 0
diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp
index 313a9ed..dfba74f 100644
--- a/media/libstagefright/StagefrightMetadataRetriever.cpp
+++ b/media/libstagefright/StagefrightMetadataRetriever.cpp
@@ -276,8 +276,6 @@
}
const char *StagefrightMetadataRetriever::extractMetadata(int keyCode) {
- LOGV("extractMetadata %d", keyCode);
-
if (mExtractor == NULL) {
return NULL;
}
diff --git a/media/libstagefright/omx/OMX.cpp b/media/libstagefright/omx/OMX.cpp
index 918d055c..9ca060d 100644
--- a/media/libstagefright/omx/OMX.cpp
+++ b/media/libstagefright/omx/OMX.cpp
@@ -365,6 +365,7 @@
msg.u.extended_buffer_data.flags = pBuffer->nFlags;
msg.u.extended_buffer_data.timestamp = pBuffer->nTimeStamp;
msg.u.extended_buffer_data.platform_private = pBuffer->pPlatformPrivate;
+ msg.u.extended_buffer_data.data_ptr = pBuffer->pBuffer;
mDispatcher->post(msg);
diff --git a/opengl/libagl/texture.cpp b/opengl/libagl/texture.cpp
index 13d078e..2875c13 100644
--- a/opengl/libagl/texture.cpp
+++ b/opengl/libagl/texture.cpp
@@ -583,7 +583,7 @@
static __attribute__((noinline))
-void set_depth_and_fog(ogles_context_t* c, GLint z)
+void set_depth_and_fog(ogles_context_t* c, GGLfixed z)
{
const uint32_t enables = c->rasterizer.state.enables;
// we need to compute Zw
@@ -592,8 +592,8 @@
GGLfixed Zw;
GGLfixed n = gglFloatToFixed(c->transforms.vpt.zNear);
GGLfixed f = gglFloatToFixed(c->transforms.vpt.zFar);
- if (z<=0) Zw = n;
- else if (z>=1) Zw = f;
+ if (z<=0) Zw = n;
+ else if (z>=0x10000) Zw = f;
else Zw = gglMulAddx(z, (f-n), n);
if (enables & GGL_ENABLE_FOG) {
// set up fog if needed...
@@ -836,7 +836,7 @@
c->rasterizer.procs.texCoord2i(c, s0, t0);
const uint32_t enables = c->rasterizer.state.enables;
if (ggl_unlikely(enables & (GGL_ENABLE_DEPTH_TEST|GGL_ENABLE_FOG)))
- set_depth_and_fog(c, z);
+ set_depth_and_fog(c, gglIntToFixed(z));
c->rasterizer.procs.color4xv(c, c->currentColorClamped.v);
c->rasterizer.procs.disable(c, GGL_W_LERP);
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index c22c21b..d2f8ced 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -1111,10 +1111,10 @@
if (cur_c == NULL) {
// no current context
if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
- // calling eglMakeCurrent( ..., EGL_NO_CONTEXT, !=0, !=0);
- return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+ // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
+ return setError(EGL_BAD_MATCH, EGL_FALSE);
}
- // not an error, there is just not current context.
+ // not an error, there is just no current context.
return EGL_TRUE;
}
}