summaryrefslogtreecommitdiffstats
path: root/opengl
diff options
context:
space:
mode:
authorRobert Carr <racarr@google.com>2016-01-26 00:18:42 -0800
committerRob Carr <racarr@google.com>2016-01-26 18:26:46 +0000
commitd4393b28978e45f67ace6530338c01ef647fada6 (patch)
treef00365740f4181a05b9dfcd89517e3006e6050cf /opengl
parent12eef9f18ad752847d4856f1d7841b3e0d329b48 (diff)
downloadandroid_frameworks_base-d4393b28978e45f67ace6530338c01ef647fada6.tar.gz
android_frameworks_base-d4393b28978e45f67ace6530338c01ef647fada6.tar.bz2
android_frameworks_base-d4393b28978e45f67ace6530338c01ef647fada6.zip
Fix reentrant deadlock in GLSurfaceView.
It is possible for clients to call SurfaceView methods e.g. setFormat from the GLSurfaceView#Renderer drawFrame callback. In this case, SurfaceView#updatewindow will understand that a redraw is required, and will request it back to GLSurfaceView. Remember, we are still on the GLThread though (from the drawFrame callback). So these methods (requestRenderAndWait, windowSizeChanged), need to be reentrant. Also fix a data race around mWantRenderNotification, which was accessed out of lock. Bug: 26770615 Change-Id: Ic66a36c886ae0b085dd456a4220f0d4f270fb016
Diffstat (limited to 'opengl')
-rw-r--r--opengl/java/android/opengl/GLSurfaceView.java29
1 files changed, 27 insertions, 2 deletions
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index 9c01f4f4d7a..f37ec58fbe2 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -1291,6 +1291,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
boolean createGlInterface = false;
boolean lostEglContext = false;
boolean sizeChanged = false;
+ boolean wantRenderNotification = false;
boolean doRenderNotification = false;
boolean askedToReleaseEglContext = false;
int w = 0;
@@ -1448,6 +1449,9 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
}
mRequestRender = false;
sGLThreadManager.notifyAll();
+ if (mWantRenderNotification) {
+ wantRenderNotification = true;
+ }
break;
}
}
@@ -1574,8 +1578,9 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
break;
}
- if (mWantRenderNotification) {
+ if (wantRenderNotification) {
doRenderNotification = true;
+ wantRenderNotification = false;
}
}
@@ -1625,11 +1630,21 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
public void requestRenderAndWait() {
synchronized(sGLThreadManager) {
+ // If we are already on the GL thread, this means a client callback
+ // has caused reentrancy, for example via updating the SurfaceView parameters.
+ // We will return to the client rendering code, so here we don't need to
+ // do anything.
+ if (Thread.currentThread() == this) {
+ return;
+ }
+
mWantRenderNotification = true;
mRequestRender = true;
mRenderComplete = false;
+
sGLThreadManager.notifyAll();
- while (!mExited && !mPaused && mRenderComplete == false) {
+
+ while (!mExited && !mPaused && !mRenderComplete && ableToDraw()) {
try {
sGLThreadManager.wait();
} catch (InterruptedException ex) {
@@ -1726,6 +1741,16 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
mSizeChanged = true;
mRequestRender = true;
mRenderComplete = false;
+
+ // If we are already on the GL thread, this means a client callback
+ // has caused reentrancy, for example via updating the SurfaceView parameters.
+ // We need to process the size change eventually though and update our EGLSurface.
+ // So we set the parameters and return so they can be processed on our
+ // next iteration.
+ if (Thread.currentThread() == this) {
+ return;
+ }
+
sGLThreadManager.notifyAll();
// Wait for thread to react to resize and render a frame