Commit 625a7865 authored by sievers's avatar sievers Committed by Commit bot

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

Committed previously: https://chromium.googlesource.com/chromium/src/+/09acbf59e7e8f1de574498ee5ba8eae0b0775438

Review URL: https://codereview.chromium.org/414503004

Cr-Commit-Position: refs/heads/master@{#292761}
parent b1394741
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
'libwebviewchromium', 'libwebviewchromium',
'android_webview_java', 'android_webview_java',
'android_webview_pak', 'android_webview_pak',
'libdrawgl',
], ],
'variables': { 'variables': {
'apk_name': 'AndroidWebView', 'apk_name': 'AndroidWebView',
...@@ -17,6 +18,7 @@ ...@@ -17,6 +18,7 @@
'native_lib_target': 'libstandalonelibwebviewchromium', 'native_lib_target': 'libstandalonelibwebviewchromium',
'resource_dir': 'test/shell/res', 'resource_dir': 'test/shell/res',
'extensions_to_not_compress': 'pak', 'extensions_to_not_compress': 'pak',
'extra_native_libs': ['<(SHARED_LIB_DIR)/libdrawgl.>(android_product_extension)'],
'additional_input_paths': [ 'additional_input_paths': [
'<(PRODUCT_DIR)/android_webview_apk/assets/webviewchromium.pak', '<(PRODUCT_DIR)/android_webview_apk/assets/webviewchromium.pak',
'<(PRODUCT_DIR)/android_webview_apk/assets/en-US.pak', '<(PRODUCT_DIR)/android_webview_apk/assets/en-US.pak',
...@@ -162,5 +164,17 @@ ...@@ -162,5 +164,17 @@
], ],
'includes': [ '../build/apk_test.gypi' ], 'includes': [ '../build/apk_test.gypi' ],
}, },
{
'target_name': 'libdrawgl',
'type': 'shared_library',
# Do not depend on any other component here, since this target
# builds a separate shared library!
'include_dirs': [
'..',
],
'sources': [
'../android_webview/test/shell/src/draw_gl/draw_gl.cc',
],
},
], ],
} }
...@@ -65,7 +65,7 @@ public class AndroidScrollIntegrationTest extends AwTestBase { ...@@ -65,7 +65,7 @@ public class AndroidScrollIntegrationTest extends AwTestBase {
new OverScrollByCallbackHelper(); new OverScrollByCallbackHelper();
public ScrollTestContainerView(Context context) { public ScrollTestContainerView(Context context) {
super(context); super(context, false);
} }
public CallbackHelper getOnScrollToCallbackHelper() { public CallbackHelper getOnScrollToCallbackHelper() {
......
...@@ -274,7 +274,7 @@ public class AwTestBase ...@@ -274,7 +274,7 @@ public class AwTestBase
*/ */
public static class TestDependencyFactory extends AwContents.DependencyFactory { public static class TestDependencyFactory extends AwContents.DependencyFactory {
public AwTestContainerView createAwTestContainerView(AwTestRunnerActivity activity) { public AwTestContainerView createAwTestContainerView(AwTestRunnerActivity activity) {
return new AwTestContainerView(activity); return new AwTestContainerView(activity, false);
} }
public AwSettings createAwSettings(Context context, boolean supportsLegacyQuirks) { public AwSettings createAwSettings(Context context, boolean supportsLegacyQuirks) {
return new AwSettings(context, false, supportsLegacyQuirks); return new AwSettings(context, false, supportsLegacyQuirks);
......
...@@ -10,17 +10,19 @@ ...@@ -10,17 +10,19 @@
package="org.chromium.android_webview.shell"> package="org.chromium.android_webview.shell">
<application android:name="org.chromium.android_webview.shell.AwShellApplication" <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" <activity android:name="org.chromium.android_webview.shell.AwShellActivity"
android:label="Android WebView Test Shell" android:label="Android WebView Test Shell"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize"> android:configChanges="orientation|keyboardHidden|keyboard|screenSize"
android:hardwareAccelerated="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name="org.chromium.android_webview.test.AwTestRunnerActivity" <activity android:name="org.chromium.android_webview.test.AwTestRunnerActivity"
android:label="AwTestRunnerActivity"> android:label="AwTestRunnerActivity"
android:hardwareAccelerated="false">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" /> <category android:name="android.intent.category.FRAMEWORK_INSTRUMENTATION_TEST" />
......
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",
]
// 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);
}
}
...@@ -80,7 +80,7 @@ public class AwShellActivity extends Activity { ...@@ -80,7 +80,7 @@ public class AwShellActivity extends Activity {
private AwTestContainerView createAwTestContainerView() { private AwTestContainerView createAwTestContainerView() {
AwBrowserProcess.start(this); AwBrowserProcess.start(this);
AwTestContainerView testContainerView = new AwTestContainerView(this); AwTestContainerView testContainerView = new AwTestContainerView(this, true);
AwContentsClient awContentsClient = new NullContentsClient() { AwContentsClient awContentsClient = new NullContentsClient() {
private View mCustomView; private View mCustomView;
......
// 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);
}
...@@ -7,10 +7,13 @@ package org.chromium.android_webview.test; ...@@ -7,10 +7,13 @@ package org.chromium.android_webview.test;
import android.content.Context; import android.content.Context;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.PixelFormat;
import android.graphics.Rect; import android.graphics.Rect;
import android.opengl.GLSurfaceView;
import android.os.Bundle; import android.os.Bundle;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.View; import android.view.View;
import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo;
...@@ -20,8 +23,12 @@ import android.view.inputmethod.InputConnection; ...@@ -20,8 +23,12 @@ import android.view.inputmethod.InputConnection;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import org.chromium.android_webview.AwContents; import org.chromium.android_webview.AwContents;
import org.chromium.android_webview.shell.DrawGL;
import org.chromium.content.browser.ContentViewCore; 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. * A View used for testing the AwContents internals.
* *
...@@ -32,8 +39,180 @@ public class AwTestContainerView extends FrameLayout { ...@@ -32,8 +39,180 @@ public class AwTestContainerView extends FrameLayout {
private AwContents.NativeGLDelegate mNativeGLDelegate; private AwContents.NativeGLDelegate mNativeGLDelegate;
private AwContents.InternalAccessDelegate mInternalAccessDelegate; 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); super(context);
if (hardwareAccelerated) {
mHardwareView = new HardwareView(context);
addView(mHardwareView,
new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT));
}
mNativeGLDelegate = new NativeGLDelegate(); mNativeGLDelegate = new NativeGLDelegate();
mInternalAccessDelegate = new InternalAccessAdapter(); mInternalAccessDelegate = new InternalAccessAdapter();
setOverScrollMode(View.OVER_SCROLL_ALWAYS); setOverScrollMode(View.OVER_SCROLL_ALWAYS);
...@@ -43,6 +222,10 @@ public class AwTestContainerView extends FrameLayout { ...@@ -43,6 +222,10 @@ public class AwTestContainerView extends FrameLayout {
public void initialize(AwContents awContents) { public void initialize(AwContents awContents) {
mAwContents = awContents; mAwContents = awContents;
if (mHardwareView != null) {
mHardwareView.initialize(
mAwContents.getAwDrawGLFunction(), mAwContents.getAwDrawGLViewContext());
}
} }
public ContentViewCore getContentViewCore() { public ContentViewCore getContentViewCore() {
...@@ -74,13 +257,28 @@ public class AwTestContainerView extends FrameLayout { ...@@ -74,13 +257,28 @@ public class AwTestContainerView extends FrameLayout {
@Override @Override
public void onAttachedToWindow() { public void onAttachedToWindow() {
super.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 @Override
public void onDetachedFromWindow() { public void onDetachedFromWindow() {
super.onDetachedFromWindow(); super.onDetachedFromWindow();
mAwContents.onDetachedFromWindow(); mAwContents.onDetachedFromWindow();
if (mHardwareView != null) {
mHardwareView.setReadyToRenderCallback(null);
}
mAttachedContents = false;
} }
@Override @Override
...@@ -107,6 +305,7 @@ public class AwTestContainerView extends FrameLayout { ...@@ -107,6 +305,7 @@ public class AwTestContainerView extends FrameLayout {
@Override @Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
mAwContents.onMeasure(widthMeasureSpec, heightMeasureSpec); mAwContents.onMeasure(widthMeasureSpec, heightMeasureSpec);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
} }
@Override @Override
...@@ -153,6 +352,9 @@ public class AwTestContainerView extends FrameLayout { ...@@ -153,6 +352,9 @@ public class AwTestContainerView extends FrameLayout {
@Override @Override
public void onDraw(Canvas canvas) { public void onDraw(Canvas canvas) {
if (mHardwareView != null) {
mHardwareView.updateScroll(getScrollX(), getScrollY());
}
mAwContents.onDraw(canvas); mAwContents.onDraw(canvas);
super.onDraw(canvas); super.onDraw(canvas);
} }
...@@ -183,11 +385,13 @@ public class AwTestContainerView extends FrameLayout { ...@@ -183,11 +385,13 @@ public class AwTestContainerView extends FrameLayout {
return mAwContents.performAccessibilityAction(action, arguments); return mAwContents.performAccessibilityAction(action, arguments);
} }
private static class NativeGLDelegate implements AwContents.NativeGLDelegate { private class NativeGLDelegate implements AwContents.NativeGLDelegate {
@Override @Override
public boolean requestDrawGL(Canvas canvas, boolean waitForCompletion, public boolean requestDrawGL(Canvas canvas, boolean waitForCompletion,
View containerview) { View containerview) {
return false; if (mHardwareView == null) return false;
mHardwareView.requestRender(canvas, waitForCompletion);
return true;
} }
@Override @Override
...@@ -234,6 +438,12 @@ public class AwTestContainerView extends FrameLayout { ...@@ -234,6 +438,12 @@ public class AwTestContainerView extends FrameLayout {
public void super_scrollTo(int scrollX, int scrollY) { public void super_scrollTo(int scrollX, int scrollY) {
// We're intentionally not calling super.scrollTo here to make testing easier. // We're intentionally not calling super.scrollTo here to make testing easier.
AwTestContainerView.this.scrollTo(scrollX, scrollY); 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 @Override
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment