summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRomain Guy <romainguy@google.com>2011-07-11 15:33:51 -0700
committerRomain Guy <romainguy@google.com>2011-07-11 15:33:51 -0700
commit039857520b1a03a52051b966d87d587225bdfcc3 (patch)
tree1c37c30821d896b2b831f4324219926ca039a801
parentaa695940327f3d4dd48f29fd1c099b5f7f9fa23c (diff)
downloadframeworks_base-039857520b1a03a52051b966d87d587225bdfcc3.zip
frameworks_base-039857520b1a03a52051b966d87d587225bdfcc3.tar.gz
frameworks_base-039857520b1a03a52051b966d87d587225bdfcc3.tar.bz2
Always make GL calls with a valid EGL context.
Bug #5010760 Change-Id: If7500ef69683948e727df1406f458f18b11259d1
-rw-r--r--core/java/android/view/HardwareRenderer.java43
-rw-r--r--core/java/android/view/ViewAncestor.java5
-rw-r--r--opengl/libs/EGL/egl.cpp5
3 files changed, 42 insertions, 11 deletions
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 1638c74..011e44c 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -128,10 +128,19 @@ public abstract class HardwareRenderer {
abstract void updateSurface(SurfaceHolder holder) throws Surface.OutOfResourcesException;
/**
- * Invoked whenever the size of the target surface changes. This will
- * not be invoked when the surface is first created.
+ * This method should be invoked whenever the current hardware renderer
+ * context should be reset.
*/
- abstract void preapareSurfaceForResize();
+ abstract void invalidate();
+
+ /**
+ * This method should be invoked to ensure the hardware renderer is in
+ * valid state (for instance, to ensure the correct EGL context is bound
+ * to the current thread.)
+ *
+ * @return true if the renderer is now valid, false otherwise
+ */
+ abstract boolean validate();
/**
* Setup the hardware renderer for drawing. This is called whenever the
@@ -629,11 +638,16 @@ public abstract class HardwareRenderer {
}
@Override
- void preapareSurfaceForResize() {
+ void invalidate() {
// Cancels any existing buffer to ensure we'll get a buffer
// of the right size before we call eglSwapBuffers
sEgl.eglMakeCurrent(sEglDisplay, EGL10.EGL_NO_SURFACE,
- EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
+ EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
+ }
+
+ @Override
+ boolean validate() {
+ return checkCurrent() != SURFACE_STATE_ERROR;
}
@Override
@@ -662,7 +676,7 @@ public abstract class HardwareRenderer {
attachInfo.mDrawingTime = SystemClock.uptimeMillis();
view.mPrivateFlags |= View.DRAWN;
-
+
final int surfaceState = checkCurrent();
if (surfaceState != SURFACE_STATE_ERROR) {
// We had to change the current surface and/or context, redraw everything
@@ -723,10 +737,21 @@ public abstract class HardwareRenderer {
}
}
}
-
+
+ /**
+ * Ensures the currnet EGL context is the one we expect.
+ *
+ * @return {@link #SURFACE_STATE_ERROR} if the correct EGL context cannot be made current,
+ * {@link #SURFACE_STATE_UPDATED} if the EGL context was changed or
+ * {@link #SURFACE_STATE_SUCCESS} if the EGL context was the correct one
+ */
private int checkCurrent() {
- // TODO: Don't check the current context when we have one per UI thread
- // TODO: Use a threadlocal flag to know whether the surface has changed
+ if (sEglThread != Thread.currentThread()) {
+ throw new IllegalStateException("Hardware acceleration can only be used with a " +
+ "single UI thread.\nOriginal thread: " + sEglThread + "\n" +
+ "Current thread: " + Thread.currentThread());
+ }
+
if (!sEglContext.equals(sEgl.eglGetCurrentContext()) ||
!mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL10.EGL_DRAW))) {
if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, sEglContext)) {
diff --git a/core/java/android/view/ViewAncestor.java b/core/java/android/view/ViewAncestor.java
index c0619a5..b7aea20 100644
--- a/core/java/android/view/ViewAncestor.java
+++ b/core/java/android/view/ViewAncestor.java
@@ -901,6 +901,7 @@ public final class ViewAncestor extends Handler implements ViewParent,
!mAttachInfo.mTurnOffWindowResizeAnim &&
mAttachInfo.mHardwareRenderer != null &&
mAttachInfo.mHardwareRenderer.isEnabled() &&
+ mAttachInfo.mHardwareRenderer.validate() &&
lp != null && !PixelFormat.formatHasAlpha(lp.format)) {
disposeResizeBuffer();
@@ -1314,10 +1315,10 @@ public final class ViewAncestor extends Handler implements ViewParent,
if (hwInitialized || ((windowShouldResize || params != null) &&
mAttachInfo.mHardwareRenderer != null &&
mAttachInfo.mHardwareRenderer.isEnabled())) {
+ mAttachInfo.mHardwareRenderer.setup(mWidth, mHeight);
if (!hwInitialized) {
- mAttachInfo.mHardwareRenderer.preapareSurfaceForResize();
+ mAttachInfo.mHardwareRenderer.invalidate();
}
- mAttachInfo.mHardwareRenderer.setup(mWidth, mHeight);
}
if (!mStopped) {
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index b11db32..ddad2d3 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -31,6 +31,7 @@
#include <cutils/properties.h>
#include <cutils/memory.h>
+#include <utils/CallStack.h>
#include <utils/String8.h>
#include "egldefs.h"
@@ -147,6 +148,10 @@ static int gl_no_context() {
if (egl_tls_t::logNoContextCall()) {
LOGE("call to OpenGL ES API with no current context "
"(logged once per thread)");
+ LOGE("call stack before error:");
+ CallStack stack;
+ stack.update();
+ stack.dump();
}
return 0;
}