summaryrefslogtreecommitdiffstats
path: root/opengl/java
diff options
context:
space:
mode:
Diffstat (limited to 'opengl/java')
-rw-r--r--opengl/java/android/opengl/ETC1Util.java2
-rw-r--r--opengl/java/android/opengl/GLSurfaceView.java329
-rw-r--r--opengl/java/android/opengl/GLUtils.java13
-rw-r--r--opengl/java/android/opengl/Group.java155
-rw-r--r--opengl/java/android/opengl/Material.java120
-rw-r--r--opengl/java/android/opengl/Object3D.java245
-rw-r--r--opengl/java/android/opengl/Texture.java135
-rw-r--r--opengl/java/com/google/android/gles_jni/GLImpl.java3
8 files changed, 222 insertions, 780 deletions
diff --git a/opengl/java/android/opengl/ETC1Util.java b/opengl/java/android/opengl/ETC1Util.java
index 3629d41..e343c97 100644
--- a/opengl/java/android/opengl/ETC1Util.java
+++ b/opengl/java/android/opengl/ETC1Util.java
@@ -193,7 +193,7 @@ public class ETC1Util {
int encodedImageSize = ETC1.getEncodedDataSize(width, height);
ByteBuffer compressedImage = ByteBuffer.allocateDirect(encodedImageSize).
order(ByteOrder.nativeOrder());
- ETC1.encodeImage(input, width, height, 3, stride, compressedImage);
+ ETC1.encodeImage(input, width, height, pixelSize, stride, compressedImage);
return new ETC1Texture(width, height, compressedImage);
}
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index 8fd866c..8acbae3 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -17,6 +17,7 @@
package android.opengl;
import java.io.Writer;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import javax.microedition.khronos.egl.EGL10;
@@ -30,7 +31,6 @@ import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.content.pm.ConfigurationInfo;
-import android.graphics.PixelFormat;
import android.os.SystemProperties;
import android.util.AttributeSet;
import android.util.Log;
@@ -169,8 +169,6 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
private final static boolean LOG_RENDERER = false;
private final static boolean LOG_RENDERER_DRAW_FRAME = false;
private final static boolean LOG_EGL = false;
- // Work-around for bug 2263168
- private final static boolean DRAW_TWICE_AFTER_SIZE_CHANGED = true;
/**
* The renderer only renders
* when the surface is created, or when {@link #requestRender} is called.
@@ -225,6 +223,19 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
init();
}
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ if (mGLThread != null) {
+ // GLThread may still be running if this view was never
+ // attached to a window.
+ mGLThread.requestExitAndWait();
+ }
+ } finally {
+ super.finalize();
+ }
+ }
+
private void init() {
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed
@@ -344,7 +355,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory();
}
mRenderer = renderer;
- mGLThread = new GLThread(renderer);
+ mGLThread = new GLThread(mThisWeakRef);
mGLThread.start();
}
@@ -575,7 +586,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
if (mGLThread != null) {
renderMode = mGLThread.getRenderMode();
}
- mGLThread = new GLThread(mRenderer);
+ mGLThread = new GLThread(mThisWeakRef);
if (renderMode != RENDERMODE_CONTINUOUSLY) {
mGLThread.setRenderMode(renderMode);
}
@@ -768,8 +779,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
if (LOG_THREADS) {
Log.i("DefaultContextFactory", "tid=" + Thread.currentThread().getId());
}
- throw new RuntimeException("eglDestroyContext failed: "
- + EGLLogWrapper.getErrorString(egl.eglGetError()));
+ EglHelper.throwEglException("eglDestroyContex", egl.eglGetError());
}
}
}
@@ -972,9 +982,9 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
* An EGL helper class.
*/
- private class EglHelper {
- public EglHelper() {
-
+ private static class EglHelper {
+ public EglHelper(WeakReference<GLSurfaceView> glSurfaceViewWeakRef) {
+ mGLSurfaceViewWeakRef = glSurfaceViewWeakRef;
}
/**
@@ -1006,13 +1016,19 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
if(!mEgl.eglInitialize(mEglDisplay, version)) {
throw new RuntimeException("eglInitialize failed");
}
- mEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);
+ GLSurfaceView view = mGLSurfaceViewWeakRef.get();
+ if (view == null) {
+ mEglConfig = null;
+ mEglContext = null;
+ } else {
+ mEglConfig = view.mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);
- /*
- * Create an EGL context. We want to do this as rarely as we can, because an
- * EGL context is a somewhat heavy object.
- */
- mEglContext = mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig);
+ /*
+ * Create an EGL context. We want to do this as rarely as we can, because an
+ * EGL context is a somewhat heavy object.
+ */
+ mEglContext = view.mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig);
+ }
if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) {
mEglContext = null;
throwEglException("createContext");
@@ -1024,11 +1040,13 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
mEglSurface = null;
}
- /*
- * React to the creation of a new surface by creating and returning an
- * OpenGL interface that renders to that surface.
+ /**
+ * Create an egl surface for the current SurfaceHolder surface. If a surface
+ * already exists, destroy it before creating the new surface.
+ *
+ * @return true if the surface was created successfully.
*/
- public GL createSurface(SurfaceHolder holder) {
+ public boolean createSurface() {
if (LOG_EGL) {
Log.w("EglHelper", "createSurface() tid=" + Thread.currentThread().getId());
}
@@ -1044,33 +1062,30 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
if (mEglConfig == null) {
throw new RuntimeException("mEglConfig not initialized");
}
+
/*
* The window size has changed, so we need to create a new
* surface.
*/
- if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) {
-
- /*
- * Unbind and destroy the old EGL surface, if
- * there is one.
- */
- mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
- EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
- mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface);
- }
+ destroySurfaceImp();
/*
* Create an EGL surface we can render into.
*/
- mEglSurface = mEGLWindowSurfaceFactory.createWindowSurface(mEgl,
- mEglDisplay, mEglConfig, holder);
+ GLSurfaceView view = mGLSurfaceViewWeakRef.get();
+ if (view != null) {
+ mEglSurface = view.mEGLWindowSurfaceFactory.createWindowSurface(mEgl,
+ mEglDisplay, mEglConfig, view.getHolder());
+ } else {
+ mEglSurface = null;
+ }
if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {
int error = mEgl.eglGetError();
if (error == EGL10.EGL_BAD_NATIVE_WINDOW) {
Log.e("EglHelper", "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
}
- return null;
+ return false;
}
/*
@@ -1078,76 +1093,72 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
* the context is current and bound to a surface.
*/
if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
- throwEglException("eglMakeCurrent");
+ /*
+ * Could not make the context current, probably because the underlying
+ * SurfaceView surface has been destroyed.
+ */
+ logEglErrorAsWarning("EGLHelper", "eglMakeCurrent", mEgl.eglGetError());
+ return false;
}
- GL gl = mEglContext.getGL();
- if (mGLWrapper != null) {
- gl = mGLWrapper.wrap(gl);
- }
+ return true;
+ }
+
+ /**
+ * Create a GL object for the current EGL context.
+ * @return
+ */
+ GL createGL() {
- if ((mDebugFlags & (DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS)) != 0) {
- int configFlags = 0;
- Writer log = null;
- if ((mDebugFlags & DEBUG_CHECK_GL_ERROR) != 0) {
- configFlags |= GLDebugHelper.CONFIG_CHECK_GL_ERROR;
+ GL gl = mEglContext.getGL();
+ GLSurfaceView view = mGLSurfaceViewWeakRef.get();
+ if (view != null) {
+ if (view.mGLWrapper != null) {
+ gl = view.mGLWrapper.wrap(gl);
}
- if ((mDebugFlags & DEBUG_LOG_GL_CALLS) != 0) {
- log = new LogWriter();
+
+ if ((view.mDebugFlags & (DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS)) != 0) {
+ int configFlags = 0;
+ Writer log = null;
+ if ((view.mDebugFlags & DEBUG_CHECK_GL_ERROR) != 0) {
+ configFlags |= GLDebugHelper.CONFIG_CHECK_GL_ERROR;
+ }
+ if ((view.mDebugFlags & DEBUG_LOG_GL_CALLS) != 0) {
+ log = new LogWriter();
+ }
+ gl = GLDebugHelper.wrap(gl, configFlags, log);
}
- gl = GLDebugHelper.wrap(gl, configFlags, log);
}
return gl;
}
- public void purgeBuffers() {
- mEgl.eglMakeCurrent(mEglDisplay,
- EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE,
- EGL10.EGL_NO_CONTEXT);
- mEgl.eglMakeCurrent(mEglDisplay,
- mEglSurface, mEglSurface,
- mEglContext);
- }
-
/**
* Display the current render surface.
- * @return false if the context has been lost.
+ * @return the EGL error code from eglSwapBuffers.
*/
- public boolean swap() {
+ public int swap() {
if (! mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
-
- /*
- * Check for EGL_CONTEXT_LOST, which means the context
- * and all associated data were lost (For instance because
- * the device went to sleep). We need to sleep until we
- * get a new surface.
- */
- int error = mEgl.eglGetError();
- switch(error) {
- case EGL11.EGL_CONTEXT_LOST:
- return false;
- case EGL10.EGL_BAD_NATIVE_WINDOW:
- // The native window is bad, probably because the
- // window manager has closed it. Ignore this error,
- // on the expectation that the application will be closed soon.
- Log.e("EglHelper", "eglSwapBuffers returned EGL_BAD_NATIVE_WINDOW. tid=" + Thread.currentThread().getId());
- break;
- default:
- throwEglException("eglSwapBuffers", error);
- }
+ return mEgl.eglGetError();
}
- return true;
+ return EGL10.EGL_SUCCESS;
}
public void destroySurface() {
if (LOG_EGL) {
Log.w("EglHelper", "destroySurface() tid=" + Thread.currentThread().getId());
}
+ destroySurfaceImp();
+ }
+
+ private void destroySurfaceImp() {
if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) {
mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_CONTEXT);
- mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface);
+ GLSurfaceView view = mGLSurfaceViewWeakRef.get();
+ if (view != null) {
+ view.mEGLWindowSurfaceFactory.destroySurface(mEgl, mEglDisplay, mEglSurface);
+ }
mEglSurface = null;
}
}
@@ -1157,7 +1168,10 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
Log.w("EglHelper", "finish() tid=" + Thread.currentThread().getId());
}
if (mEglContext != null) {
- mEGLContextFactory.destroyContext(mEgl, mEglDisplay, mEglContext);
+ GLSurfaceView view = mGLSurfaceViewWeakRef.get();
+ if (view != null) {
+ view.mEGLContextFactory.destroyContext(mEgl, mEglDisplay, mEglContext);
+ }
mEglContext = null;
}
if (mEglDisplay != null) {
@@ -1170,14 +1184,24 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
throwEglException(function, mEgl.eglGetError());
}
- private void throwEglException(String function, int error) {
- String message = function + " failed: " + EGLLogWrapper.getErrorString(error);
+ public static void throwEglException(String function, int error) {
+ String message = formatEglError(function, error);
if (LOG_THREADS) {
- Log.e("EglHelper", "throwEglException tid=" + Thread.currentThread().getId() + " " + message);
+ Log.e("EglHelper", "throwEglException tid=" + Thread.currentThread().getId() + " "
+ + message);
}
throw new RuntimeException(message);
}
+ public static void logEglErrorAsWarning(String tag, String function, int error) {
+ Log.w(tag, formatEglError(function, error));
+ }
+
+ public static String formatEglError(String function, int error) {
+ return function + " failed: " + EGLLogWrapper.getErrorString(error);
+ }
+
+ private WeakReference<GLSurfaceView> mGLSurfaceViewWeakRef;
EGL10 mEgl;
EGLDisplay mEglDisplay;
EGLSurface mEglSurface;
@@ -1195,14 +1219,14 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
* sGLThreadManager object. This avoids multiple-lock ordering issues.
*
*/
- class GLThread extends Thread {
- GLThread(Renderer renderer) {
+ static class GLThread extends Thread {
+ GLThread(WeakReference<GLSurfaceView> glSurfaceViewWeakRef) {
super();
mWidth = 0;
mHeight = 0;
mRequestRender = true;
mRenderMode = RENDERMODE_CONTINUOUSLY;
- mRenderer = renderer;
+ mGLSurfaceViewWeakRef = glSurfaceViewWeakRef;
}
@Override
@@ -1244,13 +1268,14 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
}
}
private void guardedRun() throws InterruptedException {
- mEglHelper = new EglHelper();
+ mEglHelper = new EglHelper(mGLSurfaceViewWeakRef);
mHaveEglContext = false;
mHaveEglSurface = false;
try {
GL10 gl = null;
boolean createEglContext = false;
boolean createEglSurface = false;
+ boolean createGlInterface = false;
boolean lostEglContext = false;
boolean sizeChanged = false;
boolean wantRenderNotification = false;
@@ -1273,7 +1298,9 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
}
// Update the pause state.
+ boolean pausing = false;
if (mPaused != mRequestPaused) {
+ pausing = mRequestPaused;
mPaused = mRequestPaused;
sGLThreadManager.notifyAll();
if (LOG_PAUSE_RESUME) {
@@ -1299,18 +1326,29 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
lostEglContext = false;
}
- // Do we need to release the EGL surface?
- if (mHaveEglSurface && mPaused) {
+ // When pausing, release the EGL surface:
+ if (pausing && mHaveEglSurface) {
if (LOG_SURFACE) {
Log.i("GLThread", "releasing EGL surface because paused tid=" + getId());
}
stopEglSurfaceLocked();
- if (!mPreserveEGLContextOnPause || sGLThreadManager.shouldReleaseEGLContextWhenPausing()) {
+ }
+
+ // When pausing, optionally release the EGL Context:
+ if (pausing && mHaveEglContext) {
+ GLSurfaceView view = mGLSurfaceViewWeakRef.get();
+ boolean preserveEglContextOnPause = view == null ?
+ false : view.mPreserveEGLContextOnPause;
+ if (!preserveEglContextOnPause || sGLThreadManager.shouldReleaseEGLContextWhenPausing()) {
stopEglContextLocked();
if (LOG_SURFACE) {
Log.i("GLThread", "releasing EGL context because paused tid=" + getId());
}
}
+ }
+
+ // When pausing, optionally terminate EGL:
+ if (pausing) {
if (sGLThreadManager.shouldTerminateEGLWhenPausing()) {
mEglHelper.finish();
if (LOG_SURFACE) {
@@ -1319,7 +1357,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
}
}
- // Have we lost the surface view surface?
+ // Have we lost the SurfaceView surface?
if ((! mHasSurface) && (! mWaitingForSurface)) {
if (LOG_SURFACE) {
Log.i("GLThread", "noticed surfaceView surface lost tid=" + getId());
@@ -1328,6 +1366,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
stopEglSurfaceLocked();
}
mWaitingForSurface = true;
+ mSurfaceIsBad = false;
sGLThreadManager.notifyAll();
}
@@ -1374,6 +1413,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
if (mHaveEglContext && !mHaveEglSurface) {
mHaveEglSurface = true;
createEglSurface = true;
+ createGlInterface = true;
sizeChanged = true;
}
@@ -1384,20 +1424,17 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
h = mHeight;
wantRenderNotification = true;
if (LOG_SURFACE) {
- Log.i("GLThread", "noticing that we want render notification tid=" + getId());
+ Log.i("GLThread",
+ "noticing that we want render notification tid="
+ + getId());
}
- if (DRAW_TWICE_AFTER_SIZE_CHANGED) {
- // We keep mRequestRender true so that we draw twice after the size changes.
- // (Once because of mSizeChanged, the second time because of mRequestRender.)
- // This forces the updated graphics onto the screen.
- } else {
- mRequestRender = false;
- }
+ // Destroy and recreate the EGL surface.
+ createEglSurface = true;
+
mSizeChanged = false;
- } else {
- mRequestRender = false;
}
+ mRequestRender = false;
sGLThreadManager.notifyAll();
break;
}
@@ -1410,6 +1447,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
+ " mHaveEglSurface: " + mHaveEglSurface
+ " mPaused: " + mPaused
+ " mHasSurface: " + mHasSurface
+ + " mSurfaceIsBad: " + mSurfaceIsBad
+ " mWaitingForSurface: " + mWaitingForSurface
+ " mWidth: " + mWidth
+ " mHeight: " + mHeight
@@ -1430,20 +1468,31 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
if (LOG_SURFACE) {
Log.w("GLThread", "egl createSurface");
}
- gl = (GL10) mEglHelper.createSurface(getHolder());
- if (gl == null) {
- // Couldn't create a surface. Quit quietly.
- break;
+ if (!mEglHelper.createSurface()) {
+ synchronized(sGLThreadManager) {
+ mSurfaceIsBad = true;
+ sGLThreadManager.notifyAll();
+ }
+ continue;
}
- sGLThreadManager.checkGLDriver(gl);
createEglSurface = false;
}
+ if (createGlInterface) {
+ gl = (GL10) mEglHelper.createGL();
+
+ sGLThreadManager.checkGLDriver(gl);
+ createGlInterface = false;
+ }
+
if (createEglContext) {
if (LOG_RENDERER) {
Log.w("GLThread", "onSurfaceCreated");
}
- mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);
+ GLSurfaceView view = mGLSurfaceViewWeakRef.get();
+ if (view != null) {
+ view.mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);
+ }
createEglContext = false;
}
@@ -1451,20 +1500,44 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
if (LOG_RENDERER) {
Log.w("GLThread", "onSurfaceChanged(" + w + ", " + h + ")");
}
- mEglHelper.purgeBuffers();
- mRenderer.onSurfaceChanged(gl, w, h);
+ GLSurfaceView view = mGLSurfaceViewWeakRef.get();
+ if (view != null) {
+ view.mRenderer.onSurfaceChanged(gl, w, h);
+ }
sizeChanged = false;
}
if (LOG_RENDERER_DRAW_FRAME) {
Log.w("GLThread", "onDrawFrame tid=" + getId());
}
- mRenderer.onDrawFrame(gl);
- if (!mEglHelper.swap()) {
- if (LOG_SURFACE) {
- Log.i("GLThread", "egl context lost tid=" + getId());
+ {
+ GLSurfaceView view = mGLSurfaceViewWeakRef.get();
+ if (view != null) {
+ view.mRenderer.onDrawFrame(gl);
}
- lostEglContext = true;
+ }
+ int swapError = mEglHelper.swap();
+ switch (swapError) {
+ case EGL10.EGL_SUCCESS:
+ break;
+ case EGL11.EGL_CONTEXT_LOST:
+ if (LOG_SURFACE) {
+ Log.i("GLThread", "egl context lost tid=" + getId());
+ }
+ lostEglContext = true;
+ break;
+ default:
+ // Other errors typically mean that the current surface is bad,
+ // probably because the SurfaceView surface has been destroyed,
+ // but we haven't been notified yet.
+ // Log the error to help developers understand why rendering stopped.
+ EglHelper.logEglErrorAsWarning("GLThread", "eglSwapBuffers", swapError);
+
+ synchronized(sGLThreadManager) {
+ mSurfaceIsBad = true;
+ sGLThreadManager.notifyAll();
+ }
+ break;
}
if (wantRenderNotification) {
@@ -1488,7 +1561,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
}
private boolean readyToDraw() {
- return (!mPaused) && mHasSurface
+ return (!mPaused) && mHasSurface && (!mSurfaceIsBad)
&& (mWidth > 0) && (mHeight > 0)
&& (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY));
}
@@ -1603,9 +1676,9 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
// Wait for thread to react to resize and render a frame
while (! mExited && !mPaused && !mRenderComplete
- && (mGLThread != null && mGLThread.ableToDraw())) {
+ && ableToDraw()) {
if (LOG_SURFACE) {
- Log.i("Main thread", "onWindowResize waiting for render complete from tid=" + mGLThread.getId());
+ Log.i("Main thread", "onWindowResize waiting for render complete from tid=" + getId());
}
try {
sGLThreadManager.wait();
@@ -1658,6 +1731,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
private boolean mRequestPaused;
private boolean mPaused;
private boolean mHasSurface;
+ private boolean mSurfaceIsBad;
private boolean mWaitingForSurface;
private boolean mHaveEglContext;
private boolean mHaveEglSurface;
@@ -1668,11 +1742,19 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
private boolean mRequestRender;
private boolean mRenderComplete;
private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>();
+ private boolean mSizeChanged = true;
// End of member variables protected by the sGLThreadManager monitor.
- private Renderer mRenderer;
private EglHelper mEglHelper;
+
+ /**
+ * Set once at thread construction time, nulled out when the parent view is garbage
+ * called. This weak reference allows the GLSurfaceView to be garbage collected while
+ * the GLThread is still alive.
+ */
+ private WeakReference<GLSurfaceView> mGLSurfaceViewWeakRef;
+
}
static class LogWriter extends Writer {
@@ -1788,7 +1870,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
! renderer.startsWith(kMSM7K_RENDERER_PREFIX);
notifyAll();
}
- mLimitedGLESContexts = !mMultipleGLESContextsAllowed || renderer.startsWith(kADRENO);
+ mLimitedGLESContexts = !mMultipleGLESContextsAllowed;
if (LOG_SURFACE) {
Log.w(TAG, "checkGLDriver renderer = \"" + renderer + "\" multipleContextsAllowed = "
+ mMultipleGLESContextsAllowed
@@ -1814,6 +1896,11 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
}
}
+ /**
+ * This check was required for some pre-Android-3.0 hardware. Android 3.0 provides
+ * support for hardware-accelerated views, therefore multiple EGL contexts are
+ * supported on all Android 3.0+ EGL drivers.
+ */
private boolean mGLESVersionCheckComplete;
private int mGLESVersion;
private boolean mGLESDriverCheckComplete;
@@ -1822,13 +1909,13 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
private static final int kGLES_20 = 0x20000;
private static final String kMSM7K_RENDERER_PREFIX =
"Q3Dimension MSM7500 ";
- private static final String kADRENO = "Adreno";
private GLThread mEglOwner;
}
private static final GLThreadManager sGLThreadManager = new GLThreadManager();
- private boolean mSizeChanged = true;
+ private final WeakReference<GLSurfaceView> mThisWeakRef =
+ new WeakReference<GLSurfaceView>(this);
private GLThread mGLThread;
private Renderer mRenderer;
private boolean mDetached;
diff --git a/opengl/java/android/opengl/GLUtils.java b/opengl/java/android/opengl/GLUtils.java
index 125c56e..1527f22 100644
--- a/opengl/java/android/opengl/GLUtils.java
+++ b/opengl/java/android/opengl/GLUtils.java
@@ -227,9 +227,9 @@ public final class GLUtils {
/**
* Return a string for the EGL error code, or the hex representation
* if the error is unknown.
- *
+ *
* @param error The EGL error to convert into a String.
- *
+ *
* @return An error string corresponding to the EGL error code.
*/
public static String getEGLErrorString(int error) {
@@ -269,6 +269,14 @@ public final class GLUtils {
}
}
+ /**
+ * Enable tracing of OpenGL functions for this application.
+ * @hide
+ */
+ public static void enableTracing() {
+ native_enableTracing();
+ }
+
native private static void nativeClassInit();
native private static int native_getInternalFormat(Bitmap bitmap);
@@ -277,4 +285,5 @@ public final class GLUtils {
Bitmap bitmap, int type, int border);
native private static int native_texSubImage2D(int target, int level, int xoffset, int yoffset,
Bitmap bitmap, int format, int type);
+ native private static void native_enableTracing();
}
diff --git a/opengl/java/android/opengl/Group.java b/opengl/java/android/opengl/Group.java
deleted file mode 100644
index 1ef2953..0000000
--- a/opengl/java/android/opengl/Group.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.opengl;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.ShortBuffer;
-import java.io.DataInputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Iterator;
-import javax.microedition.khronos.opengles.*;
-
-class MaterialIndices {
-
- private Material material = null;
- private ShortBuffer indexBuffer = null;
-
- public MaterialIndices(Material material, ShortBuffer indexBuffer) {
- this.material = material;
- this.indexBuffer = indexBuffer;
- }
-
- public Material getMaterial() {
- return material;
- }
-
- public ShortBuffer getIndexBuffer() {
- return indexBuffer;
- }
-}
-
-/**
- * {@hide}
- */
-public class Group {
-
- private Object3D parent;
- private String name;
-
- private List<MaterialIndices> materialIndices =
- new ArrayList<MaterialIndices>();
-
- public Group(Object3D parent) {
- this.parent = parent;
- }
-
- public String getName() {
- return name;
- }
-
- public void load(DataInputStream dis) throws IOException {
- dis.readInt(); // name length
- this.name = dis.readUTF();
-
- int numMaterials = dis.readInt();
-
- for (int i = 0; i < numMaterials; i++) {
- dis.readInt(); // material name length
- String matName = dis.readUTF();
- Material material = parent.getMaterial(matName);
-
- int numIndices = dis.readInt();
- byte[] indicesBytes = new byte[numIndices * 2];
- dis.readFully(indicesBytes);
-
- // Swap bytes from network to native order if necessary
- if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) {
- int idx = 0;
- for (int j = 0; j < numIndices; j++) {
- byte b0 = indicesBytes[idx];
- byte b1 = indicesBytes[idx + 1];
- indicesBytes[idx] = b1;
- indicesBytes[idx + 1] = b0;
- idx += 2;
- }
- }
-
- ByteBuffer ibb = ByteBuffer.allocateDirect(2*numIndices);
- ibb.order(ByteOrder.nativeOrder());
- ibb.put(indicesBytes);
- ibb.position(0);
-
- ShortBuffer sb = ibb.asShortBuffer();
- materialIndices.add(new MaterialIndices(material, sb));
- }
- }
-
- public int getNumTriangles() {
- int numTriangles = 0;
- Iterator<MaterialIndices> iter = materialIndices.iterator();
- while (iter.hasNext()) {
- MaterialIndices matIdx = iter.next();
- ShortBuffer indexBuffer = matIdx.getIndexBuffer();
- numTriangles += indexBuffer.capacity()/3;
- }
- return numTriangles;
- }
-
- public void draw(GL10 gl) {
- gl.glDisableClientState(gl.GL_COLOR_ARRAY);
-
- gl.glVertexPointer(3, gl.GL_FIXED, 0, parent.getVertexBuffer());
- gl.glEnableClientState(gl.GL_VERTEX_ARRAY);
-
- gl.glNormalPointer(gl.GL_FIXED, 0, parent.getNormalBuffer());
- gl.glEnableClientState(gl.GL_NORMAL_ARRAY);
-
- if (parent.hasTexcoords()) {
- gl.glTexCoordPointer(2, gl.GL_FIXED, 0, parent.getTexcoordBuffer());
- gl.glEnableClientState(gl.GL_TEXTURE_COORD_ARRAY);
- gl.glEnable(gl.GL_TEXTURE_2D);
- } else {
- gl.glDisable(gl.GL_TEXTURE_2D);
- }
-
- Iterator<MaterialIndices> iter = materialIndices.iterator();
- while (iter.hasNext()) {
- MaterialIndices matIdx = iter.next();
- ShortBuffer indexBuffer = matIdx.getIndexBuffer();
- Material mat = matIdx.getMaterial();
- mat.setMaterialParameters(gl);
- if (parent.hasTexcoords() && mat.getMap_Kd().length() > 0) {
- Texture texture = parent.getTexture(mat.getMap_Kd());
- texture.setTextureParameters(gl);
- }
-
- gl.glDrawElements(gl.GL_TRIANGLES,
- indexBuffer.capacity(),
- gl.GL_UNSIGNED_SHORT,
- indexBuffer);
- }
- }
-
- public String toString() {
- return "Group[" +
- "name=" + name +
- "]";
- }
-}
diff --git a/opengl/java/android/opengl/Material.java b/opengl/java/android/opengl/Material.java
deleted file mode 100644
index 60a3e72..0000000
--- a/opengl/java/android/opengl/Material.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.opengl;
-
-import java.io.DataInputStream;
-import java.io.IOException;
-import javax.microedition.khronos.opengles.GL10;
-
-/**
- * {@hide}
- */
-public class Material {
-
- private Object3D parent;
- private String name;
- private String map_kd;
- private float[] ka = new float[4];
- private float[] kd = new float[4];
- private float[] ks = new float[4];
- private float ns;
- private int illum;
- private float d;
-
- private static float[] black = { 0.0f, 0.0f, 0.0f, 1.0f };
-
- public Material(Object3D parent) {
- this.parent = parent;
- }
-
- public String getName() {
- return name;
- }
-
- public String getMap_Kd() {
- return map_kd;
- }
-
- public void setMaterialParameters(GL10 gl) {
- gl.glMaterialfv(gl.GL_FRONT_AND_BACK, gl.GL_AMBIENT, kd, 0);
- gl.glMaterialfv(gl.GL_FRONT_AND_BACK, gl.GL_DIFFUSE, kd, 0);
- gl.glMaterialfv(gl.GL_FRONT_AND_BACK, gl.GL_SPECULAR, ks, 0);
- gl.glMaterialf(gl.GL_FRONT_AND_BACK, gl.GL_SHININESS,
- Math.min(Math.max(ns, 0), 128));
-
-// if (illum == 0) {
-// gl.glMaterialfv(gl.GL_FRONT_AND_BACK, gl.GL_AMBIENT, kd, 0);
-// } else {
-// gl.glMaterialfv(gl.GL_FRONT_AND_BACK, gl.GL_AMBIENT, ka, 0);
-// gl.glMaterialfv(gl.GL_FRONT_AND_BACK, gl.GL_DIFFUSE, kd, 0);
-// }
-
-// if (illum > 1) {
-// gl.glMaterialfv(gl.GL_FRONT_AND_BACK, gl.GL_SPECULAR, ks, 0);
-// gl.glMaterialf(gl.GL_FRONT_AND_BACK, gl.GL_SHININESS,
-// Math.min(Math.max(ns, 0), 128));
-// } else {
-// gl.glMaterialfv(gl.GL_FRONT_AND_BACK, gl.GL_SPECULAR, black, 0);
-// }
- }
-
- public void load(DataInputStream dis) throws IOException {
- dis.readInt(); // name length
- this.name = dis.readUTF();
-
- dis.readInt(); // map_kdLength
- this.map_kd = dis.readUTF();
-
- if (parent.hasTexcoords() && map_kd.length() > 0) {
- parent.loadTexture(map_kd);
- }
-
- this.ka[0] = dis.readFloat();
- this.ka[1] = dis.readFloat();
- this.ka[2] = dis.readFloat();
- this.ka[3] = dis.readFloat();
-
- this.kd[0] = dis.readFloat();
- this.kd[1] = dis.readFloat();
- this.kd[2] = dis.readFloat();
- this.kd[3] = dis.readFloat();
-
- this.ks[0] = dis.readFloat();
- this.ks[1] = dis.readFloat();
- this.ks[2] = dis.readFloat();
- this.ks[3] = dis.readFloat();
-
- this.ns = dis.readFloat();
- this.illum = dis.readInt();
- this.d = dis.readFloat();
- }
-
- public String toString() {
- return "Material[" +
- "name=\"" + name + "\"," +
- "ka={" + ka[0] + "," + ka[1] + "," + ka[2] + "}," +
- "kd={" + kd[0] + "," + kd[1] + "," + kd[2] + "}," +
- "ks={" + ks[0] + "," + ks[1] + "," + ks[2] + "}," +
- "ns=" + ns + "," +
- "map_kd=\"" +
- (map_kd == null ? "" : map_kd) +
- "\"," +
- "illum=" + illum + "," +
- "d=" + d +
- "]";
- }
-}
diff --git a/opengl/java/android/opengl/Object3D.java b/opengl/java/android/opengl/Object3D.java
deleted file mode 100644
index 340c6a7..0000000
--- a/opengl/java/android/opengl/Object3D.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.opengl;
-
-import java.io.BufferedReader;
-import java.io.DataInputStream;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.IntBuffer;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import javax.microedition.khronos.opengles.*;
-
-/**
- * {@hide}
- */
-public abstract class Object3D {
-
- private boolean mHasTexcoords = false;
-
- private float mBoundsMinX = Float.MAX_VALUE;
- private float mBoundsMaxX = Float.MIN_VALUE;
- private float mBoundsMinY = Float.MAX_VALUE;
- private float mBoundsMaxY = Float.MIN_VALUE;
- private float mBoundsMinZ = Float.MAX_VALUE;
- private float mBoundsMaxZ = Float.MIN_VALUE;
-
- private IntBuffer mVertexBuffer;
- private IntBuffer mNormalBuffer;
- private IntBuffer mTexcoordBuffer;
-
- // All groups, by name
- private Map<String, Group> mGroups;
-
- // All materials, by name
- private Map<String, Material> mMaterials;
-
- // All texture maps, by name
- private Map<String, Texture> mTextures;
-
- public Object3D() {
- reset();
- }
-
- /**
- * Override this method with an implementation that contructs
- * and InputStream from the given filename. For example, if the
- * source files are to be retrieved using an AssetManager,
- * the implementation would use AssetManager.load() to
- * get the input stream.
- */
- public abstract InputStream readFile(String filename) throws IOException;
-
- private void reset() {
- mVertexBuffer = mNormalBuffer = mTexcoordBuffer = null;
-
- mGroups = new HashMap<String,Group>();
- mMaterials = new HashMap<String,Material>();
- mTextures = new HashMap<String,Texture>();
- }
-
- public Material getMaterial(String name) {
- Material mat = mMaterials.get(name);
- return mat;
- }
-
- public Texture getTexture(String name) {
- return mTextures.get(name);
- }
-
- public IntBuffer getVertexBuffer() {
- return mVertexBuffer;
- }
-
- public IntBuffer getNormalBuffer() {
- return mNormalBuffer;
- }
-
- public IntBuffer getTexcoordBuffer() {
- return mTexcoordBuffer;
- }
-
- public int getNumTriangles() {
- int numTriangles = 0;
- Iterator<Group> iter = mGroups.values().iterator();
- while (iter.hasNext()) {
- numTriangles += iter.next().getNumTriangles();
- }
- return numTriangles;
- }
-
- public boolean hasTexcoords() {
- return mHasTexcoords;
- }
-
- public float getBoundsMinX() {
- return mBoundsMinX;
- }
-
- public float getBoundsMaxX() {
- return mBoundsMaxX;
- }
-
- public float getBoundsMinY() {
- return mBoundsMinY;
- }
-
- public float getBoundsMaxY() {
- return mBoundsMaxY;
- }
-
- public float getBoundsMinZ() {
- return mBoundsMinZ;
- }
-
- public float getBoundsMaxZ() {
- return mBoundsMaxZ;
- }
-
- public void loadTexture(String name) throws IOException {
- InputStream is = readFile(name + ".raw");
- Texture texture = new Texture(is);
- mTextures.put(name, texture);
- }
-
- private static void verifyByte(DataInputStream dis, int b)
- throws IOException {
- int x = dis.read() & 0xff;
- if (x != b) {
- throw new RuntimeException("Bad byte: " +
- x +
- " (expected " + b + ")");
- }
- }
-
- public void load(String filename) throws IOException {
- reset();
-
- DataInputStream dis = new DataInputStream(readFile(filename));
- verifyByte(dis, 'g' + 128);
- verifyByte(dis, 'l');
- verifyByte(dis, 'e');
- verifyByte(dis, 's');
-
- int numTuples = dis.readInt();
-
- this.mBoundsMinX = dis.readFloat();
- this.mBoundsMaxX = dis.readFloat();
- this.mBoundsMinY = dis.readFloat();
- this.mBoundsMaxY = dis.readFloat();
- this.mBoundsMinZ = dis.readFloat();
- this.mBoundsMaxZ = dis.readFloat();
-
- this.mHasTexcoords = dis.readInt() == 1;
-
- int intsPerTuple = mHasTexcoords ? 8 : 6;
- int numInts = numTuples*intsPerTuple;
-
- int len = 4*numTuples*(mHasTexcoords ? 8 : 6);
-
- byte[] tmp = new byte[len];
- int tidx = 0;
- while (tidx < len) {
- tidx += dis.read(tmp, tidx, len - tidx);
- }
- if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) {
- for (int i = 0; i < len; i += 4) {
- byte tmp0 = tmp[i];
- byte tmp1 = tmp[i + 1];
- byte tmp2 = tmp[i + 2];
- byte tmp3 = tmp[i + 3];
- tmp[i] = tmp3;
- tmp[i + 1] = tmp2;
- tmp[i + 2] = tmp1;
- tmp[i + 3] = tmp0;
- }
- }
-
- ByteBuffer allbb = ByteBuffer.allocateDirect(len);
- allbb.order(ByteOrder.nativeOrder());
- allbb.put(tmp);
-
- allbb.position(0);
- allbb.limit(4*3*numTuples);
- ByteBuffer vbb = allbb.slice();
- this.mVertexBuffer = vbb.asIntBuffer();
- mVertexBuffer.position(0);
-
- if (mHasTexcoords) {
- allbb.position(allbb.limit());
- allbb.limit(allbb.position() + 4*2*numTuples);
- ByteBuffer tbb = allbb.slice();
- this.mTexcoordBuffer = tbb.asIntBuffer();
- mTexcoordBuffer.position(0);
- }
-
- allbb.position(allbb.limit());
- allbb.limit(allbb.position() + 4*3*numTuples);
- ByteBuffer nbb = allbb.slice();
- this.mNormalBuffer = nbb.asIntBuffer();
- mNormalBuffer.position(0);
-
- int numMaterials = dis.readInt();
- for (int i = 0; i < numMaterials; i++) {
- Material mat = new Material(this);
- mat.load(dis);
- mMaterials.put(mat.getName(), mat);
- }
-
- int numGroups = dis.readInt();
- for (int i = 0; i < numGroups; i++) {
- Group g = new Group(this);
- g.load(dis);
- mGroups.put(g.getName(), g);
- }
- }
-
- public void draw(GL10 gl) {
- Iterator<Group> iter = mGroups.values().iterator();
- while (iter.hasNext()) {
- iter.next().draw(gl);
- }
- }
-}
-
diff --git a/opengl/java/android/opengl/Texture.java b/opengl/java/android/opengl/Texture.java
deleted file mode 100644
index dcd894d..0000000
--- a/opengl/java/android/opengl/Texture.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 2006 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.opengl;
-
-import java.io.InputStream;
-import java.io.IOException;
-import java.nio.Buffer;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import javax.microedition.khronos.opengles.GL10;
-
-import android.content.res.AssetManager;
-
-/**
- * {@hide}
- */
-public class Texture {
-
- private int width, height, bpp;
- private ByteBuffer data;
- private int name = -1;
-
- // Texture maps have the following format. All integers
- // are 16 bits, high byte first. Pixels are in 5/6/5
- // RGB format, low byte first.
- //
- // width
- // height
- // pixel (0, 0)
- // pixel (1, 0)
- // ...
- // pixel (width - 1, height - 1)
-
- private int readInt16(InputStream is) throws IOException {
- return is.read() | (is.read() << 8);
- }
-
- public Texture(InputStream is) throws IOException {
- this.width = readInt16(is);
- this.height = readInt16(is);
- this.bpp = 2;
-
- int npixels = width*height;
- int nbytes = npixels*bpp;
- byte[] arr = new byte[nbytes];
-
- int idx = 0;
- while (idx < nbytes) {
- int nread = is.read(arr, idx, nbytes - idx);
- idx += nread;
- }
-
- if (ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN) {
- // Swap pairs of bytes on big-endian platforms
- for (int i = 0; i < npixels; i++) {
- int j = i*2;
- int k = j + 1;
-
- byte tmp = arr[j];
- arr[j] = arr[k];
- arr[k] = tmp;
- }
- }
-
- this.data = ByteBuffer.allocateDirect(arr.length);
- this.data.order(ByteOrder.nativeOrder());
- data.put(arr);
- data.position(0);
- }
-
- private int loadTexture(GL10 gl,
- int textureUnit,
- int minFilter, int magFilter,
- int wrapS, int wrapT,
- int mode,
- int width, int height,
- int dataType,
- Buffer data) {
- int[] texture = new int[1];
- gl.glGenTextures(1, texture, 0);
-
- gl.glEnable(gl.GL_TEXTURE_2D);
- gl.glClientActiveTexture(textureUnit);
- gl.glBindTexture(gl.GL_TEXTURE_2D, texture[0]);
- gl.glTexParameterf(gl.GL_TEXTURE_2D,
- gl.GL_TEXTURE_MIN_FILTER,
- minFilter);
- gl.glTexParameterf(gl.GL_TEXTURE_2D,
- gl.GL_TEXTURE_MAG_FILTER,
- magFilter);
- gl.glTexParameterf(gl.GL_TEXTURE_2D,
- gl.GL_TEXTURE_WRAP_S,
- wrapS);
- gl.glTexParameterf(gl.GL_TEXTURE_2D,
- gl.GL_TEXTURE_WRAP_T,
- wrapT);
- gl.glTexEnvf(gl.GL_TEXTURE_ENV, gl.GL_TEXTURE_ENV_MODE, mode);
-
- gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, gl.GL_RGB,
- width, height,
- 0, gl.GL_RGB, dataType,
- data);
-
- return texture[0];
- }
-
- public void setTextureParameters(GL10 gl) {
- if (name < 0) {
- name = loadTexture(gl,
- gl.GL_TEXTURE0,
- gl.GL_NEAREST, gl.GL_NEAREST,
- gl.GL_REPEAT, gl.GL_REPEAT,
- gl.GL_MODULATE,
- width, height,
- gl.GL_UNSIGNED_SHORT_5_6_5,
- data);
- }
-
- gl.glBindTexture(gl.GL_TEXTURE_2D, name);
- }
-}
diff --git a/opengl/java/com/google/android/gles_jni/GLImpl.java b/opengl/java/com/google/android/gles_jni/GLImpl.java
index 090c0cb..07f9e91 100644
--- a/opengl/java/com/google/android/gles_jni/GLImpl.java
+++ b/opengl/java/com/google/android/gles_jni/GLImpl.java
@@ -23,6 +23,7 @@ import android.app.AppGlobals;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.os.Build;
+import android.os.UserId;
import android.util.Log;
import java.nio.Buffer;
@@ -67,7 +68,7 @@ public class GLImpl implements GL10, GL10Ext, GL11, GL11Ext, GL11ExtensionPack {
int version = 0;
IPackageManager pm = AppGlobals.getPackageManager();
try {
- ApplicationInfo applicationInfo = pm.getApplicationInfo(appName, 0);
+ ApplicationInfo applicationInfo = pm.getApplicationInfo(appName, 0, UserId.myUserId());
if (applicationInfo != null) {
version = applicationInfo.targetSdkVersion;
}