| Index: chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShell.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShell.java b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShell.java
|
| index ec33e4972a6a8af1412457cecd529e25692e8c84..ceeb17eaf2d43b5521c3052008390acc0aeff376 100644
|
| --- a/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShell.java
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/vr_shell/VrShell.java
|
| @@ -4,379 +4,47 @@
|
|
|
| package org.chromium.chrome.browser.vr_shell;
|
|
|
| -import static android.opengl.GLES20.GL_NEAREST;
|
| -import static android.opengl.GLES20.GL_TEXTURE_MAG_FILTER;
|
| -import static android.opengl.GLES20.GL_TEXTURE_MIN_FILTER;
|
| -import static android.opengl.GLES20.glBindTexture;
|
| -import static android.opengl.GLES20.glGenTextures;
|
| -import static android.opengl.GLES20.glTexParameteri;
|
| -
|
| -import android.annotation.SuppressLint;
|
| -import android.app.Activity;
|
| -import android.graphics.SurfaceTexture;
|
| -import android.graphics.SurfaceTexture.OnFrameAvailableListener;
|
| -import android.opengl.GLES11Ext;
|
| -import android.opengl.GLSurfaceView;
|
| -import android.os.StrictMode;
|
| -import android.view.MotionEvent;
|
| -import android.view.Surface;
|
| -import android.view.View;
|
| -import android.view.ViewGroup;
|
| import android.widget.FrameLayout;
|
|
|
| -import com.google.vr.ndk.base.AndroidCompat;
|
| -import com.google.vr.ndk.base.GvrLayout;
|
| -
|
| -import org.chromium.base.CommandLine;
|
| -import org.chromium.base.ThreadUtils;
|
| -import org.chromium.base.annotations.JNINamespace;
|
| -import org.chromium.base.annotations.UsedByReflection;
|
| -import org.chromium.chrome.browser.ChromeSwitches;
|
| -import org.chromium.chrome.browser.ChromeVersionInfo;
|
| -import org.chromium.chrome.browser.WebContentsFactory;
|
| import org.chromium.chrome.browser.tab.Tab;
|
| -import org.chromium.content.browser.ContentView;
|
| -import org.chromium.content.browser.ContentViewCore;
|
| -import org.chromium.content_public.browser.WebContents;
|
| -import org.chromium.ui.base.ViewAndroidDelegate;
|
| -import org.chromium.ui.base.WindowAndroid;
|
| -
|
| -import javax.microedition.khronos.egl.EGLConfig;
|
| -import javax.microedition.khronos.opengles.GL10;
|
|
|
| /**
|
| - * This view extends from GvrLayout which wraps a GLSurfaceView that renders VR shell.
|
| + * Abstracts away the VrShell class, which may or may not be present at runtime depending on
|
| + * compile flags.
|
| */
|
| -@JNINamespace("vr_shell")
|
| -@UsedByReflection("VrShellDelegate.java")
|
| -public class VrShell extends GvrLayout implements GLSurfaceView.Renderer, VrShellInterface {
|
| - private static final String TAG = "VrShell";
|
| -
|
| - @UsedByReflection("VrShellDelegate.java")
|
| - public static final String VR_EXTRA = com.google.vr.sdk.base.Constants.EXTRA_VR_LAUNCH;
|
| -
|
| - private Activity mActivity;
|
| -
|
| - private final GLSurfaceView mGlSurfaceView;
|
| -
|
| - private long mNativeVrShell = 0;
|
| -
|
| - private int mContentTextureHandle;
|
| - private int mUiTextureHandle;
|
| - private FrameListener mContentFrameListener;
|
| - private FrameListener mUiFrameListener;
|
| -
|
| - private FrameLayout mContentViewCoreContainer;
|
| -
|
| - // The tab that holds the main ContentViewCore.
|
| - private Tab mTab;
|
| -
|
| - // The ContentViewCore for the main content rect in VR.
|
| - private ContentViewCore mContentCVC;
|
| -
|
| - // The non-VR container view for mContentCVC.
|
| - private ViewGroup mOriginalContentViewParent;
|
| -
|
| - // TODO(mthiesse): Instead of caching these values, make tab reparenting work for this case.
|
| - private int mOriginalContentViewIndex;
|
| - private ViewGroup.LayoutParams mOriginalLayoutParams;
|
| - private WindowAndroid mOriginalWindowAndroid;
|
| -
|
| - private VrWindowAndroid mContentVrWindowAndroid;
|
| -
|
| - private WebContents mUiContents;
|
| - private ContentViewCore mUiCVC;
|
| - private VrWindowAndroid mUiVrWindowAndroid;
|
| -
|
| - @UsedByReflection("VrShellDelegate.java")
|
| - public VrShell(Activity activity) {
|
| - super(activity);
|
| - mActivity = activity;
|
| - mContentViewCoreContainer = new FrameLayout(getContext()) {
|
| - @Override
|
| - public boolean dispatchTouchEvent(MotionEvent event) {
|
| - return true;
|
| - }
|
| - };
|
| - addView(mContentViewCoreContainer, 0, new FrameLayout.LayoutParams(
|
| - FrameLayout.LayoutParams.MATCH_PARENT,
|
| - FrameLayout.LayoutParams.MATCH_PARENT));
|
| - mGlSurfaceView = new GLSurfaceView(getContext());
|
| - mGlSurfaceView.setEGLContextClientVersion(2);
|
| - mGlSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 0, 0);
|
| - mGlSurfaceView.setPreserveEGLContextOnPause(true);
|
| - mGlSurfaceView.setRenderer(this);
|
| - setPresentationView(mGlSurfaceView);
|
| -
|
| - if (setAsyncReprojectionEnabled(true)) {
|
| - AndroidCompat.setSustainedPerformanceMode(mActivity, true);
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public void initializeNative(Tab currentTab, VrShellDelegate delegate) {
|
| - assert currentTab.getContentViewCore() != null;
|
| - mTab = currentTab;
|
| - mContentCVC = mTab.getContentViewCore();
|
| - mContentVrWindowAndroid = new VrWindowAndroid(mActivity);
|
| -
|
| - mUiVrWindowAndroid = new VrWindowAndroid(mActivity);
|
| - mUiContents = WebContentsFactory.createWebContents(true, false);
|
| - mUiCVC = new ContentViewCore(mActivity, ChromeVersionInfo.getProductVersion());
|
| - ContentView uiContentView = ContentView.createContentView(mActivity, mUiCVC);
|
| - mUiCVC.initialize(ViewAndroidDelegate.createBasicDelegate(uiContentView),
|
| - uiContentView, mUiContents, mUiVrWindowAndroid);
|
| -
|
| - mNativeVrShell = nativeInit(mContentCVC.getWebContents(),
|
| - mContentVrWindowAndroid.getNativePointer(),
|
| - mUiContents, mUiVrWindowAndroid.getNativePointer());
|
| - mGlSurfaceView.setOnTouchListener(new View.OnTouchListener() {
|
| - @Override
|
| - @SuppressLint("ClickableViewAccessibility")
|
| - public boolean onTouch(View v, MotionEvent event) {
|
| - if (!CommandLine.getInstance().hasSwitch(ChromeSwitches.ENABLE_VR_SHELL_DEV)
|
| - && event.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
| - nativeOnTriggerEvent(mNativeVrShell);
|
| - return true;
|
| - }
|
| - return false;
|
| - }
|
| - });
|
| -
|
| - uiContentView.setVisibility(View.VISIBLE);
|
| - mUiCVC.onShow();
|
| - mContentViewCoreContainer.addView(uiContentView, new FrameLayout.LayoutParams(
|
| - FrameLayout.LayoutParams.MATCH_PARENT,
|
| - FrameLayout.LayoutParams.MATCH_PARENT));
|
| - mUiCVC.setBottomControlsHeight(0);
|
| - mUiCVC.setTopControlsHeight(0, false);
|
| - mUiVrWindowAndroid.onVisibilityChanged(true);
|
| -
|
| - nativeSetDelegate(mNativeVrShell, delegate);
|
| -
|
| - reparentContentWindow();
|
| -
|
| - nativeUpdateCompositorLayers(mNativeVrShell);
|
| - }
|
| -
|
| - private void reparentContentWindow() {
|
| - mOriginalWindowAndroid = mContentCVC.getWindowAndroid();
|
| -
|
| - // TODO(mthiesse): Update the WindowAndroid in ChromeActivity too?
|
| - mTab.updateWindowAndroid(null);
|
| - mTab.updateWindowAndroid(mContentVrWindowAndroid);
|
| -
|
| - ViewGroup contentContentView = mContentCVC.getContainerView();
|
| - mOriginalContentViewParent = ((ViewGroup) contentContentView.getParent());
|
| - mOriginalContentViewIndex = mOriginalContentViewParent.indexOfChild(contentContentView);
|
| - mOriginalLayoutParams = contentContentView.getLayoutParams();
|
| - mOriginalContentViewParent.removeView(contentContentView);
|
| -
|
| - mContentViewCoreContainer.addView(contentContentView, new FrameLayout.LayoutParams(
|
| - FrameLayout.LayoutParams.MATCH_PARENT,
|
| - FrameLayout.LayoutParams.MATCH_PARENT));
|
| - }
|
| -
|
| - private void restoreContentWindow() {
|
| - ViewGroup contentContentView = mContentCVC.getContainerView();
|
| - mTab.updateWindowAndroid(null);
|
| - mTab.updateWindowAndroid(mOriginalWindowAndroid);
|
| - mContentViewCoreContainer.removeView(contentContentView);
|
| - mOriginalContentViewParent.addView(contentContentView, mOriginalContentViewIndex,
|
| - mOriginalLayoutParams);
|
| - }
|
| -
|
| - private static class FrameListener implements OnFrameAvailableListener {
|
| - final SurfaceTexture mSurfaceTexture;
|
| - final GLSurfaceView mGlSurfaceView;
|
| - boolean mFirstTex = true;
|
| -
|
| - final Runnable mUpdateTexImage = new Runnable() {
|
| - @Override
|
| - public void run() {
|
| - try {
|
| - mSurfaceTexture.updateTexImage();
|
| - } catch (IllegalStateException e) {
|
| - }
|
| - }
|
| - };
|
| -
|
| - public FrameListener(int textureId, GLSurfaceView glSurfaceView) {
|
| - mSurfaceTexture = new SurfaceTexture(textureId);
|
| - mSurfaceTexture.setOnFrameAvailableListener(this);
|
| - mGlSurfaceView = glSurfaceView;
|
| - }
|
| -
|
| - @Override
|
| - public void onFrameAvailable(SurfaceTexture surfaceTexture) {
|
| - mFirstTex = false;
|
| - mGlSurfaceView.queueEvent(mUpdateTexImage);
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public void onSurfaceCreated(GL10 gl, EGLConfig config) {
|
| - final int width = mContentCVC.getContainerView().getWidth();
|
| - final int height = mContentCVC.getContainerView().getHeight();
|
| - mContentTextureHandle = createExternalTextureHandle();
|
| - mUiTextureHandle = createExternalTextureHandle();
|
| -
|
| - mContentFrameListener = new FrameListener(mContentTextureHandle, mGlSurfaceView);
|
| - mUiFrameListener = new FrameListener(mUiTextureHandle, mGlSurfaceView);
|
| -
|
| - mContentFrameListener.mSurfaceTexture.setDefaultBufferSize(width, height);
|
| - mUiFrameListener.mSurfaceTexture.setDefaultBufferSize(width, height);
|
| -
|
| - ThreadUtils.postOnUiThread(new Runnable() {
|
| - @Override
|
| - public void run() {
|
| - nativeContentSurfaceChanged(mNativeVrShell, width, height,
|
| - new Surface(mContentFrameListener.mSurfaceTexture));
|
| - mContentCVC.onPhysicalBackingSizeChanged(width, height);
|
| - nativeUiSurfaceChanged(mNativeVrShell, width, height,
|
| - new Surface(mUiFrameListener.mSurfaceTexture));
|
| - mUiCVC.onPhysicalBackingSizeChanged(width, height);
|
| - }
|
| - });
|
| -
|
| - nativeGvrInit(mNativeVrShell, getGvrApi().getNativeGvrContext());
|
| - nativeInitializeGl(mNativeVrShell, mContentTextureHandle, mUiTextureHandle);
|
| - }
|
| -
|
| - @Override
|
| - public void onSurfaceChanged(GL10 gl, int width, int height) {}
|
| -
|
| - @Override
|
| - public void onDrawFrame(GL10 gl) {
|
| - // Make sure we've updated the texture at least once. We do this because onFrameAvailable
|
| - // isn't guaranteed to have fired after transitioning to VR. It only fires when the texture
|
| - // is updated either through scrolling, resizing, etc. - none of which we're guaranteed to
|
| - // have done on transition.
|
| - if (mUiFrameListener.mFirstTex) {
|
| - mUiFrameListener.mSurfaceTexture.updateTexImage();
|
| - mUiFrameListener.mFirstTex = false;
|
| - }
|
| - if (mContentFrameListener.mFirstTex) {
|
| - mContentFrameListener.mSurfaceTexture.updateTexImage();
|
| - mContentFrameListener.mFirstTex = false;
|
| - }
|
| -
|
| - nativeDrawFrame(mNativeVrShell);
|
| - }
|
| -
|
| - @Override
|
| - public boolean dispatchTouchEvent(MotionEvent event) {
|
| - // Normally, touch event is dispatched to presentation view only if the phone is paired with
|
| - // a Cardboard viewer. This is annoying when we just want to quickly verify a Cardboard
|
| - // behavior. This allows us to trigger cardboard trigger event without pair to a Cardboard.
|
| - if (CommandLine.getInstance().hasSwitch(ChromeSwitches.ENABLE_VR_SHELL_DEV)
|
| - && event.getActionMasked() == MotionEvent.ACTION_DOWN) {
|
| - nativeOnTriggerEvent(mNativeVrShell);
|
| - }
|
| - return super.dispatchTouchEvent(event);
|
| - }
|
| -
|
| - @Override
|
| - public void onResume() {
|
| - super.onResume();
|
| - if (mNativeVrShell != 0) {
|
| - // Refreshing the viewer profile accesses disk, so we need to temporarily allow disk
|
| - // reads. The GVR team promises this will be fixed when they launch.
|
| - StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
|
| - try {
|
| - nativeOnResume(mNativeVrShell);
|
| - } finally {
|
| - StrictMode.setThreadPolicy(oldPolicy);
|
| - }
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public void onPause() {
|
| - super.onPause();
|
| - if (mNativeVrShell != 0) {
|
| - nativeOnPause(mNativeVrShell);
|
| - }
|
| - }
|
| -
|
| - @Override
|
| - public void shutdown() {
|
| - super.shutdown();
|
| - if (mNativeVrShell != 0) {
|
| - nativeDestroy(mNativeVrShell);
|
| - mNativeVrShell = 0;
|
| - }
|
| - if (mContentFrameListener != null && mContentFrameListener.mSurfaceTexture != null) {
|
| - mContentFrameListener.mSurfaceTexture.release();
|
| - }
|
| - if (mUiFrameListener != null && mUiFrameListener.mSurfaceTexture != null) {
|
| - mUiFrameListener.mSurfaceTexture.release();
|
| - }
|
| - restoreContentWindow();
|
| - }
|
| -
|
| - @Override
|
| - public void pause() {
|
| - onPause();
|
| - }
|
| -
|
| - @Override
|
| - public void resume() {
|
| - onResume();
|
| - }
|
| +public interface VrShell {
|
| + /**
|
| + * Performs native VrShell initialization.
|
| + */
|
| + void initializeNative(Tab currentTab, VrShellDelegate delegate);
|
|
|
| - @Override
|
| - public void teardown() {
|
| - shutdown();
|
| - }
|
| + /**
|
| + * Pauses VrShell.
|
| + */
|
| + void pause();
|
|
|
| - @Override
|
| - public void setVrModeEnabled(boolean enabled) {
|
| - AndroidCompat.setVrModeEnabled(mActivity, enabled);
|
| - }
|
| + /**
|
| + * Resumes VrShell.
|
| + */
|
| + void resume();
|
|
|
| - @Override
|
| - public void setWebVrModeEnabled(boolean enabled) {
|
| - nativeSetWebVrMode(mNativeVrShell, enabled);
|
| - }
|
| + /**
|
| + * Destroys VrShell.
|
| + */
|
| + void teardown();
|
|
|
| - @Override
|
| - public FrameLayout getContainer() {
|
| - return (FrameLayout) this;
|
| - }
|
| + /**
|
| + * Sets Android VR Mode to |enabled|.
|
| + */
|
| + void setVrModeEnabled(boolean enabled);
|
|
|
| /**
|
| - * Create a new GLES11Ext.GL_TEXTURE_EXTERNAL_OES texture handle.
|
| - * @return New texture handle.
|
| + * Sets whether we're presenting WebVR content or not.
|
| */
|
| - private int createExternalTextureHandle() {
|
| - int[] textureDataHandle = new int[1];
|
| - glGenTextures(1, textureDataHandle, 0);
|
| - if (textureDataHandle[0] != 0) {
|
| - glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureDataHandle[0]);
|
| - glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
| - glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
| - return textureDataHandle[0];
|
| - } else {
|
| - throw new RuntimeException("Error generating texture handle.");
|
| - }
|
| - }
|
| + void setWebVrModeEnabled(boolean enabled);
|
|
|
| - private native long nativeInit(WebContents contentWebContents, long nativeContentWindowAndroid,
|
| - WebContents uiWebContents, long nativeUiWindowAndroid);
|
| - private native void nativeSetDelegate(long nativeVrShell, VrShellDelegate delegate);
|
| - private native void nativeGvrInit(long nativeVrShell, long nativeGvrApi);
|
| - private native void nativeDestroy(long nativeVrShell);
|
| - private native void nativeInitializeGl(
|
| - long nativeVrShell, int contentTextureHandle, int uiTextureHandle);
|
| - private native void nativeDrawFrame(long nativeVrShell);
|
| - private native void nativeOnTriggerEvent(long nativeVrShell);
|
| - private native void nativeOnPause(long nativeVrShell);
|
| - private native void nativeOnResume(long nativeVrShell);
|
| - private native void nativeContentSurfaceChanged(
|
| - long nativeVrShell, int width, int height, Surface surface);
|
| - private native void nativeUiSurfaceChanged(
|
| - long nativeVrShell, int width, int height, Surface surface);
|
| - private native void nativeUpdateCompositorLayers(long nativeVrShell);
|
| - private native void nativeSetWebVrMode(long nativeVrShell, boolean enabled);
|
| + /**
|
| + * Returns the GVRLayout as a FrameLayout.
|
| + */
|
| + FrameLayout getContainer();
|
| }
|
|
|