I am using OpenGL ES 1.1 with the NDK and occasionally when I call glGenTextures it does not change the value of name holder that I pass in (doesn't even set it to 0).
glGetError returns 0, no error.
All GL code is in a JNI method called from onDrawFrame of the surface renderer so the context shouldn't be a problem. (edit: this was a wrong assumption and was the cause of the problem)
The code works in some cases and not others. If I repeat the call each frame it works after about 5 tries. (I am generating glyphs on request).
The first lot of textures get created up to at least #32 but after that it is hit and miss.
Does anyone know of a reason why glGenTextures would appear to do nothing?
Is glGenTextures called with a valid OpenGL(-ES) context being active? If you're using multiple threads: A OpenGL(-ES) context can be active in only one thread at a time. But each thread may have a different context active.
Related
I'm currently searching for a bug which is based on a OpenGL program being invalid. But it is difficult to find the source of the problem without knowing where it might come from.
When I create the program it is valid. Furthermore I don't use glDeleteProgram().
To determine wether my program is valid or not I use glIsProgram().
Generally in OpenGL, objects are not created until they are first bound.
glGenTextures (...) for instance, reserves and returns one or more names for texture objects but those names do not become actual textures until bound to something like glBindTexture (GL_TEXUTRE_2D, ...). In other words, the names are reserved but what they reference is not instantiated/initialized yet.
What glIs* (...) actually returns is whether the name you pass it is the name of a created object. Thus, if you never bind an object it is never created, and this function will return GL_FALSE.
glUseProgram (...) is the function that OpenGL uses to bind GLSL program objects. Even though GLSL program and shader objects work differently from all other types of OpenGL objects it is very likely that glIsProgram (...) is not going to return GL_TRUE until sometime after you have called glUseProgram (...) on it at least once.
Incidentally, to validate a program I would suggest you use glValidateProgram (...) instead.
Here is some C pseudo-code that demonstrates how to use glValidateProgram:
GLint valid = GL_FALSE;
glValidateProgram (program);
glGetProgramiv (program, GL_VALIDATE_STATUS, &valid);
If valid is GL_TRUE after this, your program is valid (e.g. it was successfully linked).
Hi Android Developers,
What is the best way to interrupt a current rendering phase of GLSurfaceView and start a new one when mode is equal to "Render_when_dirty"? I artificially stop rendering in "onDraw" method by checking a flag and returning from actual rendering method which is called in "onDraw" method; then, in main thread's context i call "requestRender()" to refresh the scene. However, due to a reason that i am not aware of, some of the intermediary old frames are displayed for a very very short period of time(on the other hand, they endure for so long period of time that users can realize the transition); before actual scene is rendered by opengl es 2.x engine. It doesn't affect anything at all; but troublesome to be fixed. What do you suggest?
P.S. Throwing InterruptedException within onDraw method is useless due to the destruction of actual rendering thread of GLSurfaveView.
Kind Regards.
When you say some of the old frames are drawn - do you mean part of the frame that is drawn is old or multiple calls of onDraw() still lead to some of the old information being shown on the display.
There are a few things I can see happening here. If you have a onDraw() like this:
onDrawFrame(){
... stuff ...
if (stateVariableSet)
return;
... stuff ...
my understanding is that when the function is done being run, that the back/front buffer get swapped and drawn. One thing that could be happening here is that you see a few calls of onDrawFrame() being rendered while you try to update the state/State variable.
On the other hand, if you have something like this:
onDrawFrame(){
... stuff..
semaphore.acquire(); // lock the thread waiting for the state to update
... stuff ...
then the things that have been drawn before the lock will be stale (for that frame only though - at least that's what I'd anticipate).
Also are you running on a multi-core system?
I have got some strange and unexpected results from my program in OpenGL ES for android for example in the code below:
matrix = ThisRot.get();
gl.glMultMatrixf(matrix, 0);
currentRotation.toMatrix(matrix);
temp.set(matrix);
I set the matrix value before I use it as an argument for gl.glMultMatrixf and after that I change the value of matrix and use it for another purpose, but it has effect an the way the object rotate so it should have effect on gl.glMultMatrixf(). and that's not the only one, some other places in my code I had this unexpected results. so I have thought maybe these happen due to mutual exclusion and multitreading and those kind of things.
am I right? should we worry about multithreading when we code in Opengl ES for android? How can I avoid these kind of problems.
Of course you should worry about multithreading. In particular, Android creates its own GLThread for rendering, when you attach a GLRenderer-derived class to a GLSurfaceView using the setRenderer() function.
In fact, multithreading can cause crashes (not only unexpected behavior) in your programs especially when you loop through arrays adding/removing objects and such.
Check if you are modifying the same data inside the onDrawFrame function of your GLRenderer and your own thread. If you are, try adding the following around the modified code (in both threads):
synchronize(variable) {
modify(variable);
}
This will lock the variable throughout the modify() function until it ends the block. Try not to overuse it, though, only in places where you need it. One thread will block the other one until it's finished!
After creating textures in Android OpenGL ES, do I have to explicitly delete these textures later using glDeleteTextures()? If so, how would I set up a callback to do this?
Thanks in advance
If you are no longer using a texture, then you should call glDeleteTextures() so that the underlying hardware resources can be freed up.
But as EboMike said, you have to be careful about using a texture that was created from a previous context instance; to expand on that answer, I like to create a texture-wrangling class which wraps the texture's ID and which calls glDeleteTextures() from its finalize() method, but then also have an app-static int named "contextId" which gets incremented every time the GL context is created (i.e. in onSurfaceCreated); the texture wrangler should track the value of contextId when it's instantiated, and if the value changes on it, that means it should reload its textures (keeping in mind that the old texture IDs were already discarded along with the old context).
No, they are automatically deleted once you move away from your app. The greater pitfall actually is to disregard the texture IDs if your app becomes active again - keep that in mind when your onSurfaceChanged is called again.
I'm trying to find a way to check to see if a current EGLContext exists and is ready to use on Android. By specification, I've tried using
((EGL10)EGLContext.getEGL()).eglGetCurrentContext()
and then comparing it to EGL10.EGL_NO_CONTEXT (tried .equals() and != ). However, even though through debugging it 'seems' that it is returning an instance of 'EGL_NO_CONTEXT' (seems meaning all the internal values are uninitialized) however no matter what comparison I do I can't get it to work.
Anyone know of another/proper method to get this done? I don't want to do it by throwing a random GL call and catching the EGLError...
I ran into the problem of not being able to re-use the current EGLContext when trying to render what was on screen in a GLSurfaceView to an offscreen EGLPixelBufferSurface. From what I can tell, the problem with using the static method
EGLContext.getEgl()
is that it creates a default EGL instance - this would mean that the EGLContext associated with it is equivalent to EGL10.EGL_NO_CONTEXT.
Also, in Android the EGLContext can only be associated with one thread (Android developer Romain Guy says so here). So in order to properly use
EGL.getCurrentContext()
you would have to have a pre-existing EGL instance and call the getCurrentContext() method in the thread that created the EGLContext.
NOTE: Android now handles saving the EGLContext when the GLThread is paused/resumed in the GLSurfaceView class (take a look at the setPreserveEGLContextOnPause(boolean preserveOnPause) method).
There seems to be a bug in Android's implementation of EGL10.eglGetCurrentContext(), where the result of eglGetCurrentContxt() has to be compared using
result.equals(EGL10.EGL_NO_CONTEXT)
rather than
result == EGL10.EGL_NO_CONTEXT
For example:
if (((EGL10) EGLContext.getEGL()).eglGetCurrentContext().equals(EGL10.EGL_NO_CONTEXT)) {
// no current context.
}
You could try testing it to see if it is null, rather than equal to a given context. This is what I would do in a standard opengl program.
[EDIT] There's an example here which uses it as follows:
if ((eglGetCurrentContext () != context->egl_context) ||
(eglGetCurrentSurface ( EGL_READ ) != drawable->egl_surface))
I don't know if that's any help.