Merge "Add thread cleanup test"
diff --git a/tests/tests/opengl/src/android/opengl/cts/WrapperTest.java b/tests/tests/opengl/src/android/opengl/cts/WrapperTest.java
index 7344b74..acc56fc 100644
--- a/tests/tests/opengl/src/android/opengl/cts/WrapperTest.java
+++ b/tests/tests/opengl/src/android/opengl/cts/WrapperTest.java
@@ -22,7 +22,6 @@
import android.opengl.EGLDisplay;
import android.opengl.EGLSurface;
import android.opengl.GLES10;
-import android.opengl.GLES11Ext;
import android.opengl.GLES20;
import android.test.AndroidTestCase;
import android.util.Log;
@@ -41,8 +40,11 @@
private EGLSurface mEGLSurface;
+ /**
+ * Tests range-checking on glGetIntegerv in GLES 1.x.
+ */
public void testGetIntegerv1() {
- eglSetup(1);
+ eglSetup(1, 1, 1); // GLES 1.x with 1x1 pbuffer
checkGlError("start");
@@ -91,11 +93,14 @@
// good
}
- eglRelease();
+ eglRelease(true);
}
+ /**
+ * Tests range-checking on glGetIntegerv in GLES 2.x.
+ */
public void testGetIntegerv2() {
- eglSetup(2);
+ eglSetup(2, 1, 1); // GLES 2.x with 1x1 pbuffer
checkGlError("start");
@@ -144,7 +149,52 @@
// good
}
- eglRelease();
+ eglRelease(true);
+ }
+
+ /**
+ * Tests whether EGL is releasing resources when the thread exits. If
+ * it doesn't, we'll consume memory rapidly, and will fail or be
+ * killed within a couple hundred iterations.
+ * <p>
+ * It may be worthwhile to watch the memory growth with procrank or showmap
+ * while the test runs to detect smaller leaks.
+ */
+ public void testThreadCleanup() throws Throwable {
+ class WrappedTest implements Runnable {
+ public Throwable mThrowable;
+
+ private static final int WIDTH = 1280;
+ private static final int HEIGHT = 720;
+
+ @Override
+ public void run() {
+ try {
+ eglSetup(2, WIDTH, HEIGHT);
+ if (!EGL14.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext)) {
+ throw new RuntimeException("eglMakeCurrent failed");
+ }
+ eglRelease(false);
+ } catch (Throwable th) {
+ mThrowable = th;
+ }
+ }
+ }
+
+ WrappedTest wrappedTest = new WrappedTest();
+
+ for (int i = 0; i < 1000; i++) {
+ if ((i % 25) == 0) {
+ Log.d(TAG, "iteration " + i);
+ }
+
+ Thread th = new Thread(wrappedTest, "EGL thrash");
+ th.start();
+ th.join();
+ if (wrappedTest.mThrowable != null) {
+ throw wrappedTest.mThrowable;
+ }
+ }
}
/**
@@ -158,11 +208,10 @@
}
}
-
/**
* Prepares EGL. Pass in the desired GLES API version.
*/
- private void eglSetup(int api) {
+ private void eglSetup(int api, int width, int height) {
mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
if (mEGLDisplay == EGL14.EGL_NO_DISPLAY) {
throw new RuntimeException("unable to get EGL14 display");
@@ -215,8 +264,8 @@
// Create a 1x1 pbuffer surface
int[] surfaceAttribs = {
- EGL14.EGL_WIDTH, 1,
- EGL14.EGL_HEIGHT, 1,
+ EGL14.EGL_WIDTH, width,
+ EGL14.EGL_HEIGHT, height,
EGL14.EGL_NONE
};
mEGLSurface = EGL14.eglCreatePbufferSurface(mEGLDisplay, configs[0], surfaceAttribs, 0);
@@ -232,10 +281,11 @@
}
/**
- * Releases EGL goodies.
+ * Releases EGL goodies. If switchCurrent is true, this will use eglMakeCurrent to switch
+ * away from the current surface+context before destroying them.
*/
- private void eglRelease() {
- if (EGL14.eglGetCurrentContext() == mEGLContext) {
+ private void eglRelease(boolean switchCurrent) {
+ if (switchCurrent) {
// Clear the current context and surface to ensure they are discarded immediately.
EGL14.eglMakeCurrent(mEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE,
EGL14.EGL_NO_CONTEXT);