Android ImageView overlay over Opengl ES unexpected behavior
I'm attempting to add an overlay to an Android opengl ES application, and am currently specifying an ImageView and working off code from SurfaceViewOverlay API Demo, effectively merging two applications I wrote, one that was canvas based and one with opengl ES.
Due to merging two projects there was a large amount of copy paste involved and which lead to me accidentally using a null surface holder. Surprisingly this worked but threw a large number of warnings. Changing it开发者_高级运维 to the surface holder of the opengl panel however causes the application to hang and not display either content from opengl or ImageView.
I played around with the code to make sure I wasn't initializing anything else where and confirmed the behavior on both a HTC Desire and Samsung Galaxy (both running 2.2)
Canvas c = null;
SurfaceHolder surfaceHolder2D = null; // this works but throws occational Null Pointer exceptions on the first canvas.drawText
//SurfaceHolder surfaceHolder2D = rsurfaceHolder; // this locks the application.
//rsurfaceHolder is initialized with getHolder() in the opengl class and this worked with both when they where separate.
//The change to ImageView was to get around issues with multiple SurfaceViews in an application having indeterminate Z order
try
{
if (Global.RUNNING == 1)
{
c = surfaceHolder2D.lockCanvas(null); // when canvas is null this line can be ommited and it still works
synchronized (surfaceHolder2D)
{
rpanel2D.onDraw(c);
}
}
else
sleep(1000);
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
if (c != null)
{
surfaceHolder2D.unlockCanvasAndPost(c);
}
}
So what on earth is going on and what would be the correct way of performing this? I'm assuming that when I'm writing to a null canvas the compiler is doing something and sending it to the correct location regardless.
Leaving it as is, is not really an option, for several reason including not trusting that this will work across multiple versions of android, it flooding the logs with a constant stream of warnings with a significant frame rate drop and it only works if onDraw is invalidated on each call.
As for the onDraw function this simply is using canvas.drawText with a this.invalidate()
Curiously creating a new canvas and drawing to that and trying to invalidate or using setImageResource (either with a new or null) throws a "CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views" but not when drawing to a null canvas. In response I moved this to be called from the openGL thread however although this works for a few seconds, soon after the ImageView stops updating. It's on draw is still being called since a counter I placed in there to confirm it is incremented even though the display isn't. Hiding and unhiding the overlay results in it working again for a few seconds.
Any help would be greatly appreciated. If I'm on the wrong track completely please let me know. My alternative is to render this to BMP, create a new texture and draw it to a quad, but I imagine that would cause issues with thousands of textures created a minute.
Thanks in advance. -K
I am not sure what you are trying to achieve - wouldn't it be better if both renderings were done using OpenGL? Assuming that there is no other way, I would advice to create a FrameLayout and add the two views to it (GLSurfaceView
and ImageView
). If you need to change UI elements you have to do it from the UI Thread, changing elements ftom the GL Thread would cause an error; so be sure and do any change inside runOnUiThread Runnable.
精彩评论