Android shader GL_INVALID_OPERATION after 2-11 nightly

Hello all,



I started using jME3 on Android with the 2-11 nightly and things were working fine, but when I’ve tried to use later versions I get a GL_INVALID_OPERATION (1282) error on glCreateShader:



I/OGLESShaderRenderer( 8466): GLES20.glEnable(GLES20.GL_BLEND)

I/OGLESShaderRenderer( 8466): GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA)

I/OGLESShaderRenderer( 8466): GLES20.glGenTexture(1, buffer)

I/OGLESShaderRenderer( 8466): GLES20.glBindTexture(3553, 1)

I/OGLESShaderRenderer( 8466): GLES20.glTexParameteri(3553GLES11.GL_GENERATE_MIMAP, GLES20.GL_TRUE)

I/OGLESShaderRenderer( 8466): GLES20.glTexParameteri(3553, GLES20.GL_TEXTURE_MIN_FILTER, 9729)

I/OGLESShaderRenderer( 8466): GLES20.glTexParameteri(3553, GLES20.GL_TEXTURE_MAG_FILTER, 9729)

I/OGLESShaderRenderer( 8466): GLES20.glTexParameteri(3553, GLES20.GL_TEXTURE_WRAP_T, 33071

I/OGLESShaderRenderer( 8466): GLES20.glTexParameteri(3553, GLES20.GL_TEXTURE_WRAP_S, 33071

I/OGLESShaderRenderer( 8466): setShader(Shader[language=GLSL100, numSources=2, numUniforms=16, shaderSources=[ShaderSource[name=Common/MatDefs/Light/Lighting.vert, defines, type=Vertex], ShaderSource[name=Common/MatDefs/Light/Lighting.frag, defines, type=Fragment]]])

I/OGLESShaderRenderer( 8466): GLES20.glCreateProgram()

I/OGLESShaderRenderer( 8466): GLES20.glCreateShader(Vertex)

W/dalvikvm( 8466): threadid=30: thread exiting with uncaught exception (group=0x40ecb228)

D/ ( 8466): [482] Exception thrown in Thread[GLThread 482,5,main]: at com.jme3.renderer.android.OGLESShaderRenderer.checkGLError(141)

D/ ( 8466): at com.jme3.renderer.android.OGLESShaderRenderer.updateShaderSourceData(990)

D/ ( 8466): at com.jme3.renderer.android.OGLESShaderRenderer.updateShaderData(1121)

D/ ( 8466): at com.jme3.renderer.android.OGLESShaderRenderer.setShader(1226)

D/ ( 8466): at com.jme3.material.Material.renderMultipassLighting(799)

D/ ( 8466): at com.jme3.material.Material.render(1028)

D/ ( 8466): at com.jme3.renderer.RenderManager.renderGeometry(649)

D/ ( 8466): at com.jme3.renderer.queue.RenderQueue.renderGeometryList(299)

D/ ( 8466): at com.jme3.renderer.queue.RenderQueue.renderQueue(351)

D/ ( 8466): at com.jme3.renderer.RenderManager.renderViewPortQueues(886)

D/ ( 8466): at com.jme3.renderer.RenderManager.flushQueue(842)

D/ ( 8466): at com.jme3.renderer.RenderManager.renderViewPort(1118)

D/ ( 8466): at com.jme3.renderer.RenderManager.render(1160)

D/ ( 8466): at [redacted].update(400)

D/ ( 8466): at com.jme3.system.android.OGLESContext.onDrawFrame(371)

D/ ( 8466): at android.opengl.GLSurfaceView$GLThread.guardedRun(1505)

D/ ( 8466): at android.opengl.GLSurfaceView$GLThread.run(1246)



Looking at the diffs in the code, I see that the error checking code is new, so I tried disabling it and my app kinda works, but the bitmap textures (which use the Lighted material – this is the material whose shader is getting updated in the above exception) are all hosed. Solid textures that use the Unshaded material seem fine.



I’m just using the supplied textures in the library; I’m not creating custom ones. I can attach snippets of source if it’s helpful.



Any ideas?

yep a test case could be helpful.

Also on what device do you run the app?

Actually a simple test case is going to be difficult. I tried to compile the Android demo app but the resources are missing in the source and it’d take a while to get it going. Sorry, I know I’m not being very helpful here.



This is running on a Motorola Xoom, If I run it on a Galaxy Nexus I don’t get the GL_INVALID_OPERATION error but I do see the same texture corruption.

I figured it out. I narrowed the change that was causing the problem to r9144, and saw that the change to storing an AndroidImageInfo in Image’s efficientData instead of a platform Bitmap. I had code that obtained a Bitmap by other means and was stuffing it into there to set it as the texture for the material, but the change in type wasn’t detected at compile time because setEfficientData just takes a raw Object type. (Presumably this gets handed off to OpenGL which deferences weird pointers and loads garbage up to texture RAM on the GPU).



What would be useful is to add a constructor to AndroidImageInfo to feed it a native Bitmap if you’ve got one; I hacked that in and it’s working for me.

@sbarta said:
I figured it out. I narrowed the change that was causing the problem to r9144, and saw that the change to storing an AndroidImageInfo in Image's efficientData instead of a platform Bitmap. I had code that obtained a Bitmap by other means and was stuffing it into there to set it as the texture for the material, but the change in type wasn't detected at compile time because setEfficientData just takes a raw Object type. (Presumably this gets handed off to OpenGL which deferences weird pointers and loads garbage up to texture RAM on the GPU).

What would be useful is to add a constructor to AndroidImageInfo to feed it a native Bitmap if you've got one; I hacked that in and it's working for me.

We can't allow you to put a native bitmap into it because it will get deleted when the app is minimized. You will need to store the image directly without using the efficient data.

I’m using jME3 as a rendering engine for an Android-only app. I’ve obtained a native Bitmap (via a network request using Android SDK calls) and would like to use it as a texture. How do I do that? I don’t see a way to throw it over to an Image. I can’t rewrite my networking layer to use jME’s paradigms; that’s a deal-breaker for me.

@sbarta said:
I'm using jME3 as a rendering engine for an Android-only app. I've obtained a native Bitmap (via a network request using Android SDK calls) and would like to use it as a texture. How do I do that? I don't see a way to throw it over to an Image. I can't rewrite my networking layer to use jME's paradigms; that's a deal-breaker for me.

Let me explain the issue better for you. When you create a Bitmap object in Android, there's no guarantee it will remain in memory. This means that at some point or another, that bitmap will become recycled and there will not be a way to get it back, without regenerating it again somehow. Any textures that you have that are based on this bitmap will become invalid.

Anyway based on your concerns I've changed the fields and methods in AndroidImageInfo to be protected, so now you can extend it and implement the loadBitmap() method by your own means.

Looks good, thanks!

@Momoko_Fan, the changes to AndroidImageInfo are working well for me, but bitmaps are getting recycled in TextureUtil after being uploaded to the GPU. I’d prefer to keep track of the Bitmap lifecycle myself and hang on to them after jME is done with them (I’m keeping a object pool of them to prevent heap thrashing and garbage collection).



Are those recycle calls in there necessary, or is it good enough to let them get garbage collected normally? If the recycle calls are still needed, would it be possible to refactor them into AndroidImageInfo? From an architecture standpoint that might make more sense anyway.



Thanks!