diff options
author | sievers <sievers@chromium.org> | 2014-08-29 16:32:28 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-08-29 23:45:19 +0000 |
commit | 386f9301889efde34b202a4600496b1e10aa06c8 (patch) | |
tree | 0afea8a65c625eb7eefdf7bd2e8c60ce5f6b9ab9 /android_webview/test | |
parent | e79241d8e2f7f17ea1c55fbb3c26674527bd58cd (diff) | |
download | chromium_src-386f9301889efde34b202a4600496b1e10aa06c8.zip chromium_src-386f9301889efde34b202a4600496b1e10aa06c8.tar.gz chromium_src-386f9301889efde34b202a4600496b1e10aa06c8.tar.bz2 |
android: Use hw acceleration in android_webview_shell
This creates a (GL)SurfaceView overlay on top of the shell
container view which runs its own thread for rendering.
It calls into the native draw functor through a small
dynamic library (drawgl.so).
NOTRY=True
Review URL: https://codereview.chromium.org/414503004
Cr-Commit-Position: refs/heads/master@{#292718}
Diffstat (limited to 'android_webview/test')
6 files changed, 307 insertions, 8 deletions
diff --git a/android_webview/test/shell/AndroidManifest.xml b/android_webview/test/shell/AndroidManifest.xml index 3c21ab8..5b3bf94 100644 --- a/android_webview/test/shell/AndroidManifest.xml +++ b/android_webview/test/shell/AndroidManifest.xml @@ -10,17 +10,19 @@ package="org.chromium.android_webview.shell"> <application android:name="org.chromium.android_webview.shell.AwShellApplication" - android:label="AwShellApplication" android:hardwareAccelerated="false"> + android:label="AwShellApplication"> <activity android:name="org.chromium.android_webview.shell.AwShellActivity" android:label="Android WebView Test Shell" - android:configChanges="orientation|keyboardHidden|keyboard|screenSize"> + android:configChanges="orientation|keyboardHidden|keyboard|screenSize" + android:hardwareAccelerated="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="org.chromium.android_webview.test.AwTestRunnerActivity" - android:label="AwTestRunnerActivity"> + android:label="AwTestRunnerActivity" + android:hardwareAccelerated="false"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" /> diff --git a/android_webview/test/shell/src/draw_gl/DEPS b/android_webview/test/shell/src/draw_gl/DEPS new file mode 100644 index 0000000..c55f31a --- /dev/null +++ b/android_webview/test/shell/src/draw_gl/DEPS @@ -0,0 +1,7 @@ +include_rules = [ + # draw_gl compiles its own shared library for a single entry point + # for testing. Therefore it cannot depend on any other module, + # except for shared definitions. + "-android_webview", + "+android_webview/public/browser", +] diff --git a/android_webview/test/shell/src/draw_gl/draw_gl.cc b/android_webview/test/shell/src/draw_gl/draw_gl.cc new file mode 100644 index 0000000..260a3f5 --- /dev/null +++ b/android_webview/test/shell/src/draw_gl/draw_gl.cc @@ -0,0 +1,61 @@ +// Copyright (c) 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <jni.h> + +#include "android_webview/public/browser/draw_gl.h" + +extern "C" { + +JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) { + return JNI_VERSION_1_4; +} + +// This code goes into its own dynamic library, so we cannot depend on +// any other components like base. +JNIEXPORT void JNICALL + Java_org_chromium_android_1webview_shell_DrawGL_nativeDrawGL( + JNIEnv*, + jclass, + jlong draw_gl, + jlong view, + jint width, + jint height, + jint scroll_x, + jint scroll_y, + jint mode) { + AwDrawGLInfo draw_info; + draw_info.mode = static_cast<AwDrawGLInfo::Mode>(mode); + draw_info.version = kAwDrawGLInfoVersion; + draw_info.is_layer = false; + draw_info.width = width; + draw_info.height = height; + draw_info.clip_left = 0; + draw_info.clip_top = 0; + draw_info.clip_bottom = height; + draw_info.clip_right = width; + draw_info.transform[0] = 1.0; + draw_info.transform[1] = 0.0; + draw_info.transform[2] = 0.0; + draw_info.transform[3] = 0.0; + + draw_info.transform[4] = 0.0; + draw_info.transform[5] = 1.0; + draw_info.transform[6] = 0.0; + draw_info.transform[7] = 0.0; + + draw_info.transform[8] = 0.0; + draw_info.transform[9] = 0.0; + draw_info.transform[10] = 1.0; + draw_info.transform[11] = 0.0; + + draw_info.transform[12] = -scroll_x; + draw_info.transform[13] = -scroll_y; + draw_info.transform[14] = 0.0; + draw_info.transform[15] = 1.0; + AwDrawGLFunction* draw_func = reinterpret_cast<AwDrawGLFunction*>(draw_gl); + draw_func(view, &draw_info, 0); +} + +} diff --git a/android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java b/android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java index 8c9cf82..0e6070b 100644 --- a/android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java +++ b/android_webview/test/shell/src/org/chromium/android_webview/shell/AwShellActivity.java @@ -80,7 +80,7 @@ public class AwShellActivity extends Activity { private AwTestContainerView createAwTestContainerView() { AwBrowserProcess.start(this); - AwTestContainerView testContainerView = new AwTestContainerView(this); + AwTestContainerView testContainerView = new AwTestContainerView(this, true); AwContentsClient awContentsClient = new NullContentsClient() { private View mCustomView; diff --git a/android_webview/test/shell/src/org/chromium/android_webview/shell/DrawGL.java b/android_webview/test/shell/src/org/chromium/android_webview/shell/DrawGL.java new file mode 100644 index 0000000..ee0d395 --- /dev/null +++ b/android_webview/test/shell/src/org/chromium/android_webview/shell/DrawGL.java @@ -0,0 +1,18 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.android_webview.shell; + +/** + * Provides an entry point to the native draw functor. + */ +public class DrawGL { + public static void drawGL(long drawGL, long viewContext, int width, int height, + int scrollX, int scrollY, int mode) { + nativeDrawGL(drawGL, viewContext, width, height, scrollX, scrollY, mode); + } + + private static native void nativeDrawGL(long drawGL, long viewContext, + int width, int height, int scrollX, int scrollY, int mode); +} 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 153a280..e853957 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; @@ -20,8 +23,12 @@ import android.view.inputmethod.InputConnection; import android.widget.FrameLayout; import org.chromium.android_webview.AwContents; +import org.chromium.android_webview.shell.DrawGL; import org.chromium.content.browser.ContentViewCore; +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; + /** * A View used for testing the AwContents internals. * @@ -32,8 +39,180 @@ 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; + + // mSyncLock is used to synchronized requestRender on the UI thread + // and drawGL on the rendering thread. The variables following + // are protected by it. + private final Object mSyncLock = new Object(); + private boolean mNeedsProcessGL = false; + private boolean mNeedsDrawGL = false; + private boolean mWaitForCompletion = false; + 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() || runner == null; + 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, boolean waitForCompletion) { + synchronized (mSyncLock) { + super.requestRender(); + mWaitForCompletion = waitForCompletion; + if (canvas == null) { + mNeedsProcessGL = true; + } else { + mNeedsDrawGL = true; + if (!waitForCompletion) { + // Wait until SYNC is complete only. + // Do this every time there was a new frame. + try { + while (mNeedsDrawGL) { + mSyncLock.wait(); + } + } catch (InterruptedException e) { + // ... + } + } + } + if (waitForCompletion) { + try { + while (mWaitForCompletion) { + mSyncLock.wait(); + } + } catch (InterruptedException e) { + // ... + } + } + } + } + + public void drawGL(int width, int height) { + final boolean draw; + final boolean process; + final boolean waitForCompletion; + + synchronized (mSyncLock) { + draw = mNeedsDrawGL; + process = mNeedsProcessGL; + waitForCompletion = mWaitForCompletion; + + if (draw) { + DrawGL.drawGL(mDrawGL, mViewContext, width, height, 0, 0, MODE_SYNC); + mCommittedScrollX = mLastScrollX; + mCommittedScrollY = mLastScrollY; + } + mNeedsDrawGL = false; + mNeedsProcessGL = false; + if (!waitForCompletion) { + mSyncLock.notifyAll(); + } + } + 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); + } + + if (waitForCompletion) { + synchronized (mSyncLock) { + mWaitForCompletion = false; + mSyncLock.notifyAll(); + } + } + } + } + + 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 +222,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 +258,28 @@ 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; + mAwContents.onAttachedToWindow(); + mAttachedContents = true; + } + }); + } } @Override public void onDetachedFromWindow() { super.onDetachedFromWindow(); mAwContents.onDetachedFromWindow(); + if (mHardwareView != null) { + mHardwareView.setReadyToRenderCallback(null); + } + mAttachedContents = false; } @Override @@ -107,6 +306,7 @@ public class AwTestContainerView extends FrameLayout { @Override public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { mAwContents.onMeasure(widthMeasureSpec, heightMeasureSpec); + super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override @@ -153,6 +353,9 @@ public class AwTestContainerView extends FrameLayout { @Override public void onDraw(Canvas canvas) { + if (mHardwareView != null) { + mHardwareView.updateScroll(getScrollX(), getScrollY()); + } mAwContents.onDraw(canvas); super.onDraw(canvas); } @@ -183,11 +386,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, waitForCompletion); + return true; } @Override @@ -234,6 +439,12 @@ 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) { + // Undo the scroll that will be applied because of mHardwareView + // being a child of |this|. + mHardwareView.setTranslationX(scrollX); + mHardwareView.setTranslationY(scrollY); + } } @Override |