Bug 844275 - Drive the layer manager creation from the GLController rather than GetLayerManager. r=Cwiiis
This commit is contained in:
@@ -5,8 +5,12 @@
|
||||
|
||||
package org.mozilla.gecko.gfx;
|
||||
|
||||
import org.mozilla.gecko.GeckoApp;
|
||||
import org.mozilla.gecko.GeckoAppShell;
|
||||
import org.mozilla.gecko.GeckoEvent;
|
||||
import org.mozilla.gecko.GeckoThread;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import javax.microedition.khronos.egl.EGL10;
|
||||
import javax.microedition.khronos.egl.EGLConfig;
|
||||
@@ -41,6 +45,7 @@ public class GLController {
|
||||
private EGL10 mEGL;
|
||||
private EGLDisplay mEGLDisplay;
|
||||
private EGLConfig mEGLConfig;
|
||||
private EGLSurface mEGLSurface;
|
||||
|
||||
private static final int LOCAL_EGL_OPENGL_ES2_BIT = 4;
|
||||
|
||||
@@ -64,22 +69,11 @@ public class GLController {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
/* Wait until we are allowed to use EGL functions on the Surface backing
|
||||
* this window.
|
||||
* This function is invoked by JNI */
|
||||
synchronized void waitForValidSurface() {
|
||||
while (!mSurfaceValid) {
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
synchronized void surfaceDestroyed() {
|
||||
GeckoApp.assertOnUiThread();
|
||||
|
||||
mSurfaceValid = false;
|
||||
notifyAll();
|
||||
mEGLSurface = null;
|
||||
|
||||
// We need to coordinate with Gecko when pausing composition, to ensure
|
||||
// that Gecko never executes a draw event while the compositor is paused.
|
||||
@@ -95,13 +89,85 @@ public class GLController {
|
||||
}
|
||||
|
||||
synchronized void surfaceChanged(int newWidth, int newHeight) {
|
||||
GeckoApp.assertOnUiThread();
|
||||
|
||||
mWidth = newWidth;
|
||||
mHeight = newHeight;
|
||||
|
||||
if (mSurfaceValid) {
|
||||
// We need to make this call even when the compositor isn't currently
|
||||
// paused (e.g. during an orientation change), to make the compositor
|
||||
// aware of the changed surface.
|
||||
resumeCompositor(mWidth, mHeight);
|
||||
return;
|
||||
}
|
||||
mSurfaceValid = true;
|
||||
notifyAll();
|
||||
|
||||
// If we get here, we supposedly have a valid surface where previously we
|
||||
// did not. So we're going to create the window surface and hold on to it
|
||||
// until the compositor comes asking for it. However, we can't call
|
||||
// eglCreateWindowSurface right away because the UI thread isn't *actually*
|
||||
// done setting up - for some reason Android will send us a surfaceChanged
|
||||
// notification before the surface is actually ready. So, we need to do the
|
||||
// call to eglCreateWindowSurface in a runnable posted back to the UI thread
|
||||
// that will run once this call unwinds all the way out and Android finishes
|
||||
// doing its thing.
|
||||
|
||||
mView.post(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
// Re-check mSurfaceValid in case the surface was destroyed between
|
||||
// where we set it to true above and this runnable getting run.
|
||||
// If mSurfaceValid is still true, try to create mEGLSurface. If
|
||||
// mSurfaceValid is false, leave mEGLSurface as null. So at the end
|
||||
// of this block mEGLSurface will be null (or EGL_NO_SURFACE) if
|
||||
// eglCreateWindowSurface failed or if mSurfaceValid changed to false.
|
||||
if (mSurfaceValid) {
|
||||
if (mEGL == null) {
|
||||
initEGL();
|
||||
}
|
||||
|
||||
mEGLSurface = mEGL.eglCreateWindowSurface(mEGLDisplay, mEGLConfig, mView.getNativeWindow(), null);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, "Unable to create window surface", e);
|
||||
}
|
||||
if (mEGLSurface == null || mEGLSurface == EGL10.EGL_NO_SURFACE) {
|
||||
mSurfaceValid = false;
|
||||
mEGLSurface = null; // normalize EGL_NO_SURFACE to null to simplify later checks
|
||||
Log.e(LOGTAG, "EGL window surface could not be created: " + getEGLError());
|
||||
return;
|
||||
}
|
||||
// At this point mSurfaceValid is true and mEGLSurface is a valid surface. Try
|
||||
// to create the compositor if it hasn't been created already.
|
||||
createCompositor();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void createCompositor() {
|
||||
GeckoApp.assertOnUiThread();
|
||||
|
||||
if (mCompositorCreated) {
|
||||
// If the compositor has already been created, just resume it instead. We don't need
|
||||
// to block here because if the surface is destroyed before the compositor grabs it,
|
||||
// we can handle that gracefully (i.e. the compositor will remain paused).
|
||||
resumeCompositor(mWidth, mHeight);
|
||||
return;
|
||||
}
|
||||
|
||||
// Only try to create the compositor if we have a valid surface and gecko is up. When these
|
||||
// two conditions are satisfied, we can be relatively sure that the compositor creation will
|
||||
// happen without needing to block anyhwere. Do it with a sync gecko event so that the
|
||||
// android doesn't have a chance to destroy our surface in between.
|
||||
if (mEGLSurface != null && GeckoThread.checkLaunchState(GeckoThread.LaunchState.GeckoRunning)) {
|
||||
GeckoAppShell.sendEventToGeckoSync(GeckoEvent.createCompositorResumeEvent());
|
||||
}
|
||||
}
|
||||
|
||||
void compositorCreated() {
|
||||
// This is invoked on the compositor thread, while the java UI thread
|
||||
// is blocked on the gecko sync event in createCompositor() above
|
||||
mCompositorCreated = true;
|
||||
}
|
||||
|
||||
@@ -148,30 +214,9 @@ public class GLController {
|
||||
throw new GLControllerException("No suitable EGL configuration found");
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides an EGLSurface without assuming ownership of this surface.
|
||||
* This class does not keep a reference to the provided EGL surface; the
|
||||
* caller assumes ownership of the surface once it is returned.
|
||||
* This function is invoked by JNI */
|
||||
/* This function is invoked by JNI on the compositor thread */
|
||||
private EGLSurface provideEGLSurface() {
|
||||
synchronized (this) {
|
||||
if (!mSurfaceValid) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (mEGL == null) {
|
||||
initEGL();
|
||||
}
|
||||
|
||||
Object window = mView.getNativeWindow();
|
||||
EGLSurface surface = mEGL.eglCreateWindowSurface(mEGLDisplay, mEGLConfig, window, null);
|
||||
if (surface == null || surface == EGL10.EGL_NO_SURFACE) {
|
||||
throw new GLControllerException("EGL window surface could not be created! " +
|
||||
getEGLError());
|
||||
}
|
||||
|
||||
return surface;
|
||||
return mEGLSurface;
|
||||
}
|
||||
|
||||
private String getEGLError() {
|
||||
|
||||
Reference in New Issue
Block a user