When using the mipmap bitmap flag on the iOS simulator and ALLEGRO_PROGRAMABLE_PIPELINE is set, then no bitmaps load. I tried ex_shader and got the same results, works without the flag, but does not work with it.
Has anyone been able to get it to work this way on a real iOS device, or seen this failure case on simulator?
Even bitmaps not used for shader purposes do not load, and I even tried a small 64x64 bitmap.
It seems to be that this:
ALLEGRO_LOCKED_REGION *lock = al_lock_bitmap(bmp,
ALLEGRO_PIXEL_FORMAT_ABGR_8888, ALLEGRO_LOCK_WRITEONLY);
returns NULL.
There shouldn't be any problems in locking a memory bitmap in that format... are you sure it returns NULL and that it's a memory bitmap? Wouldn't it just crash?
Also, check your allegro.log (it'll probably just tell you that it can't create a particular bitmap format).
The lock fails here:
ok becomes false, pixel alignment = 4
and it does crash when it tries to access the lock since loading a bitmap seems to assume the lock will succeed.
Looking at the gl docs, I see that this really should not fail, but somehow it does... GL_INVALID_ENUM is generated if pname is not an accepted value. But it is...
Could you stick a glGetError code before glPixelStorei? Perhaps the error happens earlier and just happens to be ignored.
It looks like you are correct, glGetLastError() has a value the moment before the call to glPixelStorei
Now for the fun part... tracking down which gl call is responsible :O
Update:
Allegro is not catching the issue, the issue happens here:
ogl_bitmap.c
The glTexParameteri call fails and returns GL_INVALID_ENUM
gl docs say: GL_INVALID_ENUM is generated if target or pname is not one of the accepted defined values.
GL_INVALID_ENUM is generated if params should have a defined symbolic constant value (based on the value of pname) and does not.
Hopefully this gives more insight into the problem.
I wonder if it is a simulator-only issue...
Hmm, that can't be right since e = glGetError(); is right after it, which should clear the error flag.
No, I added that error checking code in, I modified allegro and added error checks everywhere where there was a gl call and recompiled and this is the first one that triggers and it makes sense because adding the mipmap flag when shaders are enabled triggers the problem.
Ah, I see! Great work! Sounds like that function might be deprecated in some contexts, so perhaps that's why it fails. Could you stick a post_generate_mipmap = true; inside that error handling branch and see if the other mipmap generation option succeeds?
Well, the good news is that it worked, though I had to add a call to glgeterror in the OpenGL_ES case:
else { unsigned char *buf; int pix_size = al_get_pixel_size(bitmap_format); buf = al_calloc(pix_size, ogl_bitmap->true_h * ogl_bitmap->true_w); glPixelStorei(GL_UNPACK_ALIGNMENT, pix_size); glTexImage2D(GL_TEXTURE_2D, 0, get_glformat(bitmap_format, 0), ogl_bitmap->true_w, ogl_bitmap->true_h, 0, get_glformat(bitmap_format, 2), get_glformat(bitmap_format, 1), buf); e = glGetError(); //here al_free(buf); }
and the call here succeeds:
if (post_generate_mipmap) { glGenerateMipmapEXT(GL_TEXTURE_2D); e = glGetError(); if (e) { ALLEGRO_ERROR("glGenerateMipmapEXT for texture %d failed (%s).\n", ogl_bitmap->texture, _al_gl_error_string(e)); printf("glGenerateMipmapEXT for texture %d failed (%s).\n", ogl_bitmap->texture, _al_gl_error_string(e)); } }
But for some reason, the alpha of many of my textures is rendering incorrectly. It's as if, on select textures I decided to draw a tinted bitmap where alpha< 1. The alpha varies from about 0.5 to 0 on several textures. It creates some funny effects.
Any insight on what could cause that?
If I take off mipmapping all alphas are happy.
Shotting a bit in the dark here, but how about trying this patch? It merely forces the OpenGL to rebuild the mipmaps after every unlock operation.
I should note that it's a little bizzare how there's no FBO extension...
Woo, that completely solved the problem!
So now the question is, how can this be implemented elegantly enough to be pushed to Allegro?
If you have some suggestions I'll be happy to send you a patch. In the state that it is in, it doesn't seem right because of the FBO stuff.
Though, if you made the patch and I tested it that would probably be better because the ide I use adds all kinds of tabs and such and I remember last time I contributed to Allegro this was a problem since Allegro uses space indentation.
I suspect what happens is, when GL_ES goes into PROGRAMMABLE_PIPELINE mode, then perhaps the old way of generating mipmaps becomes deprecated and it must go through the FBO extension method. Whereas when not using programmable pipeline, the GL_ES context is fine with using the old way of generating mipmaps.
Yeah, so it's a little strange how you don't seem to have the FBO extension, yet the glGenerateMipmapEXT is loaded fine... I guess what could be done is to alter the check in `ogl_bitmap.c` from `if (post_generate_mipmap)` to `if (post_generate_mipmap && glGenerateMipmapExt != NULL)`. Then, if that call succeeds we could set a variable called generate_mipmaps_manually in ALLEGRO_BITMAP_EXTRA_OPENGL and then check that variable inside the unlocking code (and if its true, we call glGenerateMipmapExt again).
EDIT:
Actually, it occurs to me that the extension name might be different on GLES. Try this code:
if (al_get_opengl_extension_list()->ALLEGRO_GL_EXT_framebuffer_object || al_get_opengl_extension_list()->ALLEGRO_GL_OES_framebuffer_object) { post_generate_mipmap = true; }
This is inside ogl_bitmap.c. This should trigger on the simulator and set post_generate_mipmap correctly.
EDIT2:
In fact, try the attached patch. If that works, then a combination of that patch and all the extra error checks you added would be great.
Unfortunately that extension does not appear to be = to 1.
Here is the extension list:
If you see a 1 then it has it.
The extension we desire says 0:
ALLEGRO_GL_OES_framebuffer_object int 0 0
I wonder if this is an allegro problem or a simulator problem... it clearly has the extension but it says it does not....
This guy here uses the simulator and oes_framebuffer is supported for him on simulator... http://forum.openscenegraph.org/viewtopic.php?t=9063
Which leads me to think maybe allegro is not reporting correctly...
EDIT:
The extension string returns this:
which has GL_OES_fbo_render_mipmap ...
It looks like Allegro does not check for that extension but I bet that's the one we need to use...
Edit:
actually GL_OES_fbo_render_mipmap does not do what I thought it did... but it's weird that the simulator is not saying it supports fbos
Can you check what GLES version you have? Perhaps printing the output of glGetString(GL_VERSION)? What I think might be happening is that you have a relatively new version of GLES that has the extension built into the core API.
OpenGL ES 2.0 APPLE-10.1.5
I'm using xcode 6.1 and the ios 7 and ios 8 simulator on mac os x 10.9.4
Where should I check for the core api thing?
No, the 2.0 gave me all the information I needed. If you look in the specification, GLES 2.0 has the frame buffer objects included in the core API. Allegro's extension loading mechanism, however, doesn't realize that and still tries to load it. The code for all of this is in opengl/extensions.c but it's not super-simple.
What is done for desktop GL, is that we parse the GL_VERSION string and get the version number. Then whenever checking for an extension, we check to see if its version is below the OpenGL version, and if so we just return true. The version parsing is not implemented for the GLES, and so if you look at all the GLES extensions (allegro5/opengl/GLext/gl_ext_list.h), they'll have a bogus OpenGL version (e.g. AGL_EXT(OES_framebuffer_object, 0)).
So what would need to be done is for all of those extensions to get proper versions (I'm not sure where to find that information) and for the GLES version parsing to be implemented as well.
Is my best bet to recompile allegro for GLES1 or is there some way we could 'fix' the mipmapping issue for now the way things currently work?
I guess we could do:
if mipmap fails, check to see if glGenerateMipmap is not null, if it is not null then we set post_gen_mipmap to true and if that is true we have an ogl_extra flag for needs_to_regen_mipmap and rather than check for the extension in gles_lock we check this flag.
I think that would work in theory. If adding a flag sound like a bad idea then in gles_lock we add || glGenerateMipmap != NULL or something...
The 'proper' hack right now would be to apply the same patch as I made a post before but add a IS_OPENGLES || condition to it, as is done in a few other spots already (and please add a /* FIXME */ comment above ).
I have attached 2 patches. The first is the fix as you described. I tested it as much as I could on the simulator and everything seems to be working correctly. I have not tested with GL_ES_1 but I do not see why that would not work.
The second patch fixes the iOS port crashing when iOS terminates your app. Trent in this commit https://github.com/liballeg/allegro5/commit/f6d9508941fab628c210007d23a55acdfdc821cf removed a selector called remove_observers, but it was still being called when the app is terminated.
Edit:
I bought an iPad 4th gen, and tested these changes. Everything works great on a real iPad.
Awesome! I'm a bit busy right now, but I'll definitely take care of these patches this weekend. Thanks for your help!
EDIT: Now commited with one (hopefully) minor fix.
Thanks, that change is fine, no issues. My reason for keeping it in there was thinking maybe eventually when allegro correctly detects the es version, it can work that way but I guess the ext version will pick up the slack in that case.