al_clone_bitmap() of backbuffer gives bad results with OGL
Bruce Pascoe

I have a screenshot feature in my minisphere game engine, so that when you press F12, it takes a screenshot and saves it in the user's home directory. When I was using DX for rendering, this worked fine. Now that I'm using OpenGL, however, it doesn't work so well. Here's the code for screenshots in minisphere:

#SelectExpand
406snapshot = al_clone_bitmap(al_get_backbuffer(g_display)); 407path = al_get_standard_path(ALLEGRO_USER_DOCUMENTS_PATH); 408al_append_path_component(path, "Sphere Files"); 409al_append_path_component(path, "Screenshots"); 410al_make_directory(al_path_cstr(path, ALLEGRO_NATIVE_PATH_SEP)); 411do { 412 sprintf(filename, "SS_%s.png", rng_name(10)); 413 al_set_path_filename(path, filename); 414 pathstr = al_path_cstr(path, ALLEGRO_NATIVE_PATH_SEP); 415} while (al_filename_exists(pathstr)); 416al_save_bitmap(pathstr, snapshot); 417al_destroy_bitmap(snapshot); 418al_destroy_path(path);

Here are the screenshots side-by-side, one taken using the above code, and the other using PrintScreen and then pasted into MS Paint:
{"name":"actual.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/1\/e\/1ebd62af7149d8dc5919d444f146eaca.png","w":640,"h":480,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/1\/e\/1ebd62af7149d8dc5919d444f146eaca"}actual.png{"name":"expected.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/f\/8\/f89f7a92448bb4c87a217ba7ad169172.png","w":656,"h":519,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/f\/8\/f89f7a92448bb4c87a217ba7ad169172"}expected.png

Make sure to enlarge them because the thumbnails are identical for some reason. ???

What it looks like is that al_clone_bitmap() is preserving the backbuffer alpha channel even though it's ignored for actual rendering. That's just a guess though.

Elias

If the back buffer has an alpha channel, I think it should be preserved. What you should do is create a new bitmap with the display size then al_draw_bitmap the back buffer into that bitmap.

Bruce Pascoe

The alpha channel has no effect on rendering, though, so for all intents and purposes it doesn't exist. And since the backbuffer serves no other purpose than to stage for rendering, it's not intuitive that if I grab its contents I get a different image than what is visible to the user.

Even so, creating a new bitmap won't help me, will it? I'll still end up copying the alpha channel over to the new image. Unless there's a way to create bitmap with no alpha channel. I never remember seeing such an option.

Elias

If you draw the bitmap the alpha channel is blended, so you just have to use a blend mode where the output is not affected. You also can create a bitmap without alpha, and also a back buffer without alpha.

I don't know why opengl uses a back buffer with alpha by default - that probably should be changed.

Bruce Pascoe

Okay, interesting thing I found, I think I discovered a bug.

Grabbing the backbuffer like this didn't fix it:

al_store_state(&old_state, ALLEGRO_STATE_NEW_BITMAP_PARAMETERS);
al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_ANY_NO_ALPHA);
snapshot = al_clone_bitmap(al_get_backbuffer(g_display));
al_restore_state(&old_state);

However, this worked:

al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_RGB_888);

So it looks like ALLEGRO_PIXEL_FORMAT_ANY_NO_ALPHA is not being honored?

SiegeLord

Can you check what the format of the bitmap created by ALLEGRO_PIXEL_FORMAT_ANY_NO_ALPHA is?

Bruce Pascoe
#SelectExpand
1al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_ANY_NO_ALPHA); 2ALLEGRO_BITMAP* snapshot = al_clone_bitmap(al_get_backbuffer(g_display)); 3int pf = al_get_bitmap_format(snapshot);

pf == 9 (ALLEGRO_PIXEL_FORMAT_ARGB_8888)

For RGB_888, I got back 12, i.e. exactly what I requested.

SiegeLord

Looks like in multiple locations in Allegro's code NO_ALPHA actually means, "don't care if it has alpha or not". Sounds like changing this will require a bit of testing.

Bruce Pascoe

So basically it's just an alias for PIXEL_FORMAT_ANY. Seems... redundant.

SiegeLord

It's subtly different. Either way, even if it did select the right format (XRGB_8888), it still wouldn't quite work, as XRGB means don't care whether X is alpha or not :P. The real format you want in this situation is ALLEGRO_PIXEL_FORMAT_ANY_24_NO_ALPHA, which should resolve to ALLEGRO_PIXEL_FORMAT_RGB_888. I'll probably fix the NO_ALPHA not picking XRGB, but this caveat will continue to remain.

Bruce Pascoe

Just for the record, the documentation says this:

ALLEGRO_PIXEL_FORMAT_ANY_NO_ALPHA - Let the driver choose a format without alpha.

I'm fine with it if Allegro itself treats the flag differently, but the documentation should probably be updated in that case. ;)

Thread #615516. Printed from Allegro.cc