Chromium Code Reviews| Index: android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java |
| diff --git a/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java b/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java |
| index 153a280afe4adb5b86cad42a44a64cd77ea21e42..a45dec464bda753d1ae6475404e4f6f811b7e978 100644 |
| --- a/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java |
| +++ b/android_webview/test/shell/src/org/chromium/android_webview/test/AwTestContainerView.java |
| @@ -7,10 +7,13 @@ package org.chromium.android_webview.test; |
| import android.content.Context; |
| import android.content.res.Configuration; |
| import android.graphics.Canvas; |
| +import android.graphics.PixelFormat; |
| import android.graphics.Rect; |
| +import android.opengl.GLSurfaceView; |
| import android.os.Bundle; |
| import android.view.KeyEvent; |
| import android.view.MotionEvent; |
| +import android.view.SurfaceHolder; |
| import android.view.View; |
| import android.view.accessibility.AccessibilityEvent; |
| import android.view.accessibility.AccessibilityNodeInfo; |
| @@ -19,7 +22,11 @@ import android.view.inputmethod.EditorInfo; |
| import android.view.inputmethod.InputConnection; |
| import android.widget.FrameLayout; |
| +import javax.microedition.khronos.egl.EGLConfig; |
| +import javax.microedition.khronos.opengles.GL10; |
| + |
| import org.chromium.android_webview.AwContents; |
| +import org.chromium.android_webview.shell.DrawGL; |
| import org.chromium.content.browser.ContentViewCore; |
| /** |
| @@ -32,8 +39,149 @@ public class AwTestContainerView extends FrameLayout { |
| private AwContents.NativeGLDelegate mNativeGLDelegate; |
| private AwContents.InternalAccessDelegate mInternalAccessDelegate; |
| - public AwTestContainerView(Context context) { |
| + HardwareView mHardwareView = null; |
| + private boolean mAttachedContents = false; |
| + |
| + private class HardwareView extends GLSurfaceView { |
| + private static final int MODE_DRAW = 0; |
| + private static final int MODE_PROCESS = 1; |
| + private static final int MODE_PROCESS_NO_CONTEXT = 2; |
| + private static final int MODE_SYNC = 3; |
| + |
| + private boolean mNeedsProcessGL = false; |
| + private boolean mNeedsDrawGL = false; |
| + private final Object mSyncLock = new Object(); |
| + private int mLastScrollX = 0; |
| + private int mLastScrollY = 0; |
| + private int mCommittedScrollX = 0; |
| + private int mCommittedScrollY = 0; |
| + private boolean mHaveSurface = false; |
| + private Runnable mReadyToRenderCallback = null; |
| + |
| + private long mDrawGL = 0; |
| + private long mViewContext = 0; |
| + |
| + public HardwareView(Context context) { |
| + super(context); |
| + setEGLContextClientVersion(2); // GLES2 |
| + getHolder().setFormat(PixelFormat.OPAQUE); |
| + setPreserveEGLContextOnPause(true); |
| + setRenderer(new Renderer() { |
| + private int mWidth = 0; |
| + private int mHeight = 0; |
| + |
| + @Override |
| + public void onDrawFrame(GL10 gl) { |
| + HardwareView.this.drawGL(mWidth, mHeight); |
| + } |
| + |
| + @Override |
| + public void onSurfaceChanged(GL10 gl, int width, int height) { |
| + gl.glViewport(0, 0, width, height); |
| + gl.glScissor(0, 0, width, height); |
| + mWidth = width; |
| + mHeight = height; |
| + } |
| + |
| + @Override |
| + public void onSurfaceCreated(GL10 gl, EGLConfig config) { |
| + } |
| + }); |
| + |
| + setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); |
| + } |
| + |
| + public void initialize(long drawGL, long viewContext) { |
| + mDrawGL = drawGL; |
| + mViewContext = viewContext; |
| + } |
| + |
| + public boolean isReadyToRender() { |
| + return mHaveSurface; |
| + } |
| + |
| + public void setReadyToRenderCallback(Runnable runner) { |
| + assert !isReadyToRender(); |
| + mReadyToRenderCallback = runner; |
| + } |
| + |
| + @Override |
| + public void surfaceCreated(SurfaceHolder holder) { |
| + boolean didHaveSurface = mHaveSurface; |
| + mHaveSurface = true; |
| + if (!didHaveSurface && mReadyToRenderCallback != null) { |
| + mReadyToRenderCallback.run(); |
| + mReadyToRenderCallback = null; |
| + } |
| + super.surfaceCreated(holder); |
| + } |
| + |
| + @Override |
| + public void surfaceDestroyed(SurfaceHolder holder) { |
| + mHaveSurface = false; |
| + super.surfaceDestroyed(holder); |
| + } |
| + |
| + public void updateScroll(int x, int y) { |
| + synchronized (mSyncLock) { |
| + mLastScrollX = x; |
| + mLastScrollY = y; |
| + } |
| + } |
| + |
| + public void requestRender(Canvas canvas) { |
| + synchronized (mSyncLock) { |
| + super.requestRender(); |
| + if (canvas == null) { |
| + mNeedsProcessGL = true; |
| + } else { |
| + mNeedsDrawGL = true; |
| + try { |
| + while (mNeedsDrawGL) { |
|
boliu
2014/08/28 23:15:06
We can pass waitForCompletion to here, and only do
no sievers
2014/08/29 01:30:44
Don't we only request draw after we have committed
|
| + mSyncLock.wait(); |
| + } |
| + } catch (InterruptedException e) { |
| + // ... |
| + } |
| + } |
| + } |
| + } |
| + |
| + public void drawGL(int width, int height) { |
| + final boolean draw; |
| + final boolean process; |
| + |
| + synchronized (mSyncLock) { |
| + draw = mNeedsDrawGL; |
| + process = mNeedsProcessGL; |
| + |
| + if (draw) { |
| + DrawGL.drawGL(mDrawGL, mViewContext, width, height, 0, 0, MODE_SYNC); |
| + mCommittedScrollX = mLastScrollX; |
| + mCommittedScrollY = mLastScrollY; |
| + } |
| + mNeedsDrawGL = false; |
| + mNeedsProcessGL = false; |
| + mSyncLock.notifyAll(); |
|
boliu
2014/08/28 23:15:06
MODE_SYNC doesn't run GL. You want to move this to
no sievers
2014/08/29 01:30:44
The lock was only meant to block the UI thread unt
|
| + } |
| + if (draw) { |
| + DrawGL.drawGL(mDrawGL, mViewContext, width, height, |
| + mCommittedScrollX, mCommittedScrollY, MODE_DRAW); |
| + } else if (process) { |
| + DrawGL.drawGL(mDrawGL, mViewContext, width, height, 0, 0, MODE_PROCESS); |
| + } |
| + } |
| + } |
| + |
| + public AwTestContainerView(Context context, boolean hardwareAccelerated) { |
| super(context); |
| + if (hardwareAccelerated) { |
| + mHardwareView = new HardwareView(context); |
| + addView(mHardwareView, |
| + new FrameLayout.LayoutParams( |
| + FrameLayout.LayoutParams.MATCH_PARENT, |
| + FrameLayout.LayoutParams.MATCH_PARENT)); |
| + } |
| mNativeGLDelegate = new NativeGLDelegate(); |
| mInternalAccessDelegate = new InternalAccessAdapter(); |
| setOverScrollMode(View.OVER_SCROLL_ALWAYS); |
| @@ -43,6 +191,11 @@ public class AwTestContainerView extends FrameLayout { |
| public void initialize(AwContents awContents) { |
| mAwContents = awContents; |
| + if (mHardwareView != null) { |
| + System.loadLibrary("drawgl"); |
| + mHardwareView.initialize( |
| + mAwContents.getAwDrawGLFunction(), mAwContents.getAwDrawGLViewContext()); |
| + } |
| } |
| public ContentViewCore getContentViewCore() { |
| @@ -74,13 +227,25 @@ public class AwTestContainerView extends FrameLayout { |
| @Override |
| public void onAttachedToWindow() { |
| super.onAttachedToWindow(); |
| - mAwContents.onAttachedToWindow(); |
| + if (mHardwareView == null || mHardwareView.isReadyToRender()) { |
| + mAwContents.onAttachedToWindow(); |
| + mAttachedContents = true; |
| + } else { |
| + mHardwareView.setReadyToRenderCallback(new Runnable() { |
| + public void run() { |
| + assert !mAttachedContents; |
|
boliu
2014/08/28 23:15:06
Hmm, what if onDetachedFromWindow is called before
no sievers
2014/08/29 01:30:44
Ok, added a call to reset the callback in onDetach
|
| + mAwContents.onAttachedToWindow(); |
| + mAttachedContents = true; |
| + } |
| + }); |
| + } |
| } |
| @Override |
| public void onDetachedFromWindow() { |
| super.onDetachedFromWindow(); |
| mAwContents.onDetachedFromWindow(); |
| + mAttachedContents = false; |
| } |
| @Override |
| @@ -107,6 +272,7 @@ public class AwTestContainerView extends FrameLayout { |
| @Override |
| public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { |
| mAwContents.onMeasure(widthMeasureSpec, heightMeasureSpec); |
| + super.onMeasure(widthMeasureSpec, heightMeasureSpec); |
| } |
| @Override |
| @@ -153,12 +319,18 @@ public class AwTestContainerView extends FrameLayout { |
| @Override |
| public void onDraw(Canvas canvas) { |
| + if (mHardwareView != null) { |
|
boliu
2014/08/28 23:15:06
More of a question for Martin I guess. I'm not sur
|
| + mHardwareView.updateScroll(getScrollX(), getScrollY()); |
| + } |
| mAwContents.onDraw(canvas); |
| super.onDraw(canvas); |
| } |
| @Override |
| public AccessibilityNodeProvider getAccessibilityNodeProvider() { |
| + // Huh? |
|
boliu
2014/08/28 23:15:06
Me too, huh?
no sievers
2014/08/29 01:30:44
Removed. This happened somewhere to me, maybe on K
|
| + if (mAwContents == null) |
| + return super.getAccessibilityNodeProvider(); |
| AccessibilityNodeProvider provider = |
| mAwContents.getAccessibilityNodeProvider(); |
| return provider == null ? super.getAccessibilityNodeProvider() : provider; |
| @@ -183,11 +355,13 @@ public class AwTestContainerView extends FrameLayout { |
| return mAwContents.performAccessibilityAction(action, arguments); |
| } |
| - private static class NativeGLDelegate implements AwContents.NativeGLDelegate { |
| + private class NativeGLDelegate implements AwContents.NativeGLDelegate { |
| @Override |
| public boolean requestDrawGL(Canvas canvas, boolean waitForCompletion, |
| View containerview) { |
| - return false; |
| + if (mHardwareView == null) return false; |
| + mHardwareView.requestRender(canvas); |
| + return true; |
| } |
| @Override |
| @@ -234,6 +408,10 @@ public class AwTestContainerView extends FrameLayout { |
| public void super_scrollTo(int scrollX, int scrollY) { |
| // We're intentionally not calling super.scrollTo here to make testing easier. |
| AwTestContainerView.this.scrollTo(scrollX, scrollY); |
| + if (mHardwareView != null) { |
|
boliu
2014/08/28 23:54:32
So this is a pretty big-ish hack to counter-act th
no sievers
2014/08/29 01:30:44
Done.
|
| + mHardwareView.setTranslationX(scrollX); |
| + mHardwareView.setTranslationY(scrollY); |
| + } |
| } |
| @Override |