![]() |
|
Allegro 5 - Bitmap Deferred Corruption(?) |
Kev Callahan
Member #6,022
July 2005
![]() |
Hi, 1old_target = al_get_target_bitmap(); // keep old destination
2
3image = al_load_bitmap2("test.png"); // load default pic
4
5al_save_bitmap("1.png",image); // this image is as expected
6
7al_set_target_bitmap(image);
8al_draw_filled_rectangle(0, 0, 16, 16, al_map_rgb(255,0,0)); // draw rectangle on image
9
10al_set_target_bitmap(old_target); // restore destination
11
12al_save_bitmap("2.png",image); // this image is unchanged (ie no square drawn)
13
14al_draw_bitmap(image, 0, 0, 0); // draw image to destination
15
16al_save_bitmap("3.png",image); // square is shown, rest of image is corrupt
My questions consist of: Why is the rectangle not shown in 2.png (deferred drawing isn't enabled) ? Kev |
Elias
Member #358
May 2000
|
Could be some kind of bug in Allegro, but 5.1.9 is a rather old version so might have been fixed since. Does it work in Allegro 5.1.11? Also, does it work if you use normal OpenGL instead of GLES? -- |
Kev Callahan
Member #6,022
July 2005
![]() |
I've moved to 5.1.11 - same issues - I think they're specific to the platform I'm on.. temp1 = al_load_bitmap2("test24.png"); // ** this doesn't fix anything //image = al_clone_bitmap(temp1); // ** // ** but this does image = al_create_bitmap(al_get_bitmap_width(temp1), al_get_bitmap_height(temp1)); al_set_target_bitmap(image); al_draw_bitmap(temp1, 0, 0, 0); // ** // 'image' is now accessible and drawn on screen correctly.. (ie no corruption)
But (what I've been trying to do is use So I tried: al_draw_filled_rectangle(3, 3, 8, 8, al_map_rgb(255,255,255)); // white rectangle col = al_get_pixel(image, 5,5) but it returns r,g,b,a values of 0.000,0.000,0.000,0.000 - I expected 1.0,1.0,1.0,?.? Return values from al_get_bitmap_format/flags(image) return H'11 & H'4E0 format = ALLEGRO_PIXEL_FORMAT_ABGR_8888 flags = ALLEGRO_VIDEO_BITMAP ALLEGRO_MAG/MIN_LINEAR ALLEGRO_INTERNAL_OPENGL Any ideas on where I go from here? Is there a way of getting to the pixel data specifically (ie as hex) as we did on Allegro 4 with 'line'..? That may give me some idea what's going on (possibly). I'm suspicious that Allegro thinks the display is in a different RGB(A) format to what it actually is.. Kev |
Thomas Fjellstrom
Member #476
June 2000
![]() |
Kev Callahan said: Is there a way of getting to the pixel data specifically (ie as hex) as we did on Allegro 4 with 'line'..? That may give me some idea what's going on (possibly). Take a look at al_lock_bitmap. -- |
Kev Callahan
Member #6,022
July 2005
![]() |
On the same topic I've found this issue - al_clear_to_color(al_map_rgba_f(1.0, 1.0, 1.0, 1.0)); col = al_get_pixel(logo, 5, 5); printf("WHT: %f, %f, %f, %f\n", col.r, col.g, col.b, col.a); al_clear_to_color(al_map_rgba_f(1.0, 0, 0, 1.0)); col = al_get_pixel(logo, 5, 5); printf("RED: %f, %f, %f, %f\n", col.r, col.g, col.b, col.a); al_clear_to_color(al_map_rgba_f(1.0, 1.0, 1.0, 1.0)); col = al_get_pixel(logo, 5, 5); printf("WHT: %f, %f, %f, %f\n", col.r, col.g, col.b, col.a); al_clear_to_color(al_map_rgba_f(0, 1.0, 0, 1.0)); col = al_get_pixel(logo, 5, 5); printf("GRN: %f, %f, %f, %f\n", col.r, col.g, col.b, col.a); al_clear_to_color(al_map_rgba_f(1.0, 1.0, 1.0, 1.0)); col = al_get_pixel(logo, 5, 5); printf("WHT: %f, %f, %f, %f\n", col.r, col.g, col.b, col.a); al_clear_to_color(al_map_rgba_f(0, 0, 0, 1.0)); col = al_get_pixel(logo, 5, 5); printf("BLK: %f, %f, %f, %f\n", col.r, col.g, col.b, col.a); al_clear_to_color(al_map_rgba_f(1.0, 1.0, 1.0, 1.0)); col = al_get_pixel(logo, 5, 5); printf("WHT: %f, %f, %f, %f\n", col.r, col.g, col.b, col.a); al_clear_to_color(al_map_rgba_f(0, 0, 1.0, 1.0)); col = al_get_pixel(logo, 5, 5); printf("BLU: %f, %f, %f, %f\n", col.r, col.g, col.b, col.a); al_clear_to_color(al_map_rgba_f(1.0, 1.0, 1.0, 1.0)); col = al_get_pixel(logo, 5, 5); printf("WHT: %f, %f, %f, %f\n", col.r, col.g, col.b, col.a); This outputs: WHT: 0.870588, 0.082353, 0.188235, 0.462745 RED: 0.000000, 0.000000, 0.000000, 0.000000 WHT: 0.000000, 0.000000, 0.000000, 0.000000 GRN: 0.000000, 0.000000, 0.000000, 0.000000 WHT: 0.000000, 0.000000, 0.000000, 0.000000 BLK: 0.000000, 0.000000, 0.000000, 0.000000 WHT: 0.000000, 0.000000, 0.000000, 0.000000 BLU: 0.000000, 0.000000, 0.000000, 0.000000 WHT: 0.000000, 0.000000, 0.000000, 0.000000
Although what is displayed is correct.. |
Elias
Member #358
May 2000
|
It may not be implemented for GLES at all, maybe not even possible... reading back from a texture is not something you'd usually do. You can use a memory bitmap, then it will always work (you shouldn't draw those of course as it would be extremely slow). Hm, and just a thought, if you call al_flip_display before al_get_pixel, does that make any difference? -- |
Kev Callahan
Member #6,022
July 2005
![]() |
Thanks for the speedy reply Elias. Just rebuilding Allegro at the moment - will have a try flipping the display in a moment in case that helps/flushes something. With video bitmaps, are there two copies of the bitmap? Did consider also, when I draw to display, to also draw to a temporary bitmap and see what values that has. Reason I'm going down this line of investigation is that I'm trying to use al_convert_mask_to_color() btw and it doesn't work. Maybe for that I need to use a (system) memory bitmap and then copy that to a video bitmap once parsed. EDIT: Also tried calling al_flip_display() and again no change. EDIT2: |
Chris Katko
Member #1,881
January 2002
![]() |
Elias said: Could be some kind of bug in Allegro, but 5.1.9 is a rather old version so might have been fixed since.
I find it funny that 2 steps on a minor, minor version number constitute "a rather old version." -----sig: |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
Are you sure your format flags are right? Ie - is col.r really a float? I thought you were supposed to use al_unmap_rgba_f for floats. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Elias
Member #358
May 2000
|
Kev Callahan said: Added, before I create the bitmap A memory bitmap means it just is a buffer with RGBA values, so I don't see how this would be possible. Quote: Adding ALLEGRO_KEEP_BITMAP_FORMAT to the flags (with ALLEGRO_MEMORY_BITMAP) actually meant the values read back are correct ie 1.0 where expected).. but the displayed images are corrupt..! This flag is not actually implemented, so this is impossible to make any difference whatsoever. Make sure you are not mixing 5.1.9 and 5.1.11 libraries and headers, none of the 5.1.x versions are compatible with each other. -- |
Kev Callahan
Member #6,022
July 2005
![]() |
This is a fresh install of the O/S - just installed 5.1.11. Appears memory bitmaps don't appear to work at all..! I had hoped I could call (where image is a system bitmap) al_convert_mask_to_alpha(image, al_map_rgb(255,0,255)) and then copy to a video bitmap - no luck. For example running ex_rotate - switching to memory bitmaps displays nothing, video bitmap is okay.. EDIT: |
Michael Moffitt
Member #15,246
July 2013
|
FWIW I am using 5.1.9 on iOS and memory bitmaps are working fine ( I need them for some pre-game blitting to generate some images, and it's much faster with the memory bitmaps to do pixel drawing on it) ). |
Kev Callahan
Member #6,022
July 2005
![]() |
Yeah thanks for that - I have run this code on the RPi (imx6 is also ARM) and an Intel platform with no issues as well, so don't suspect it's Allegro, just hoping for some workarounds of the problems.. I'm now suspecting that Allegro hasn't detected the bit depth of the display correctly, so I'm investigating that at the moment. I think there are 2 or 3 issues confusing the analysis - will stick at it for a while yet. EDIT: Looking through al_put/draw_pixel() shows that 'draw' uses OPENGL and 'put' uses direct memory access.. Question is.. |
SiegeLord
Member #7,827
October 2006
![]() |
al_put_pixel works by first locking the bitmap and then using memory access to that locked memory. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Kev Callahan
Member #6,022
July 2005
![]() |
What appears to be the problem is related to direct memory access to the bitmaps. Using the OPENGL based 'functions', everything appears to work. I'm not at all knowledgeable about how OPENGL works (pipelines, etc?).. I have had the same sort of issue just loading an image from a file - the resultant image was empty, but if I loaded it twice and used al_draw_bitmap() to overwrite the image, it's fine. |
Chris Katko
Member #1,881
January 2002
![]() |
SiegeLord said: al_put_pixel works by first locking the bitmap and then using memory access to that locked memory. That sounds insanely slow (which is in line with my experience doing simple pixel rain in a5). I don't remember... is there a way to defer calls and do them in one lock? Also, is "blit to memory, draw, blit to VRAM" really the only way to do things? Is direct VRAM access completely gone in newer OpenGL/etc? -----sig: |
Kev Callahan
Member #6,022
July 2005
![]() |
Actually unless the target bitmap is locked already, al_put_pixel() will individually lock/unlock each pixel. So.. Should this be done automatically by the driver? Or am I completely off in my understanding (very likely!) |
beoran
Member #12,636
March 2011
|
I would assume the solution is to use the primitives add on and draw very small triangles in stead of pixels. Like that the draws will be hardware accelerated. |
Kev Callahan
Member #6,022
July 2005
![]() |
SiegeLord
Member #7,827
October 2006
![]() |
Chris Katko said: That sounds insanely slow It's not really meant to be used outside of memory bitmaps. al_draw_pixel is a little faster, but if you really want a ton of pixels, you use al_draw_prim. Quote: direct VRAM access There's a locking API that Allegro wraps. On system with APUs, it's essentially direct DRAM acces. "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
Kev Callahan
Member #6,022
July 2005
![]() |
I feel I almost have a fix for this, but I seem to have hit a snag.. How can I use al_draw_prim() function to actually write in the 'alpha' value rather than use it? Or is there another function (obviously not al_put_pixel()) that I could use to store all 4 (RGBA) values in the target image..? Turning off the blender with ADD, ONE, ZERO as I guess it just ignores the alpha parameter. Maybe something to do with _al_ogl_update_render_state() .. ?? ______________ Okay - code below works as an alternative to al_convert_mask_to_alpha().. 1#define NUMVC 1024
2void kcal_convert_mask_to_alpha(ALLEGRO_BITMAP *bitmap, ALLEGRO_COLOR mask_color)
3{
4 int i=0, x=0, y=0, w, h, vc=0;
5
6 ALLEGRO_LOCKED_REGION *lr;
7
8 ALLEGRO_VERTEX pix[NUMVC+1];
9 ALLEGRO_COLOR alpha_pixel = al_map_rgba( 0,0,0, 0); // output value
10 ALLEGRO_BITMAP *old_target = al_get_target_bitmap();
11
12 //if (!(lr = al_lock_bitmap(bitmap, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READWRITE))) { printf("Couldn't lock bitmap."); return; }
13
14 w = al_get_bitmap_width (bitmap);
15 h = al_get_bitmap_height(bitmap);
16
17 al_set_target_bitmap(bitmap);
18
19 for (y=0; y<h; y++)
20 {
21 printf("%d / %d\r", y, h); fflush(stdout);
22
23 for (x=0; x<w; x++)
24 {
25 ALLEGRO_COLOR read_pixel = al_get_pixel(bitmap, x, y); // input value
26
27 pix[vc].x = x;
28 pix[vc].y = y;
29 pix[vc].z = 0;
30
31 if (memcmp(&read_pixel, &mask_color, sizeof(ALLEGRO_COLOR)) == 0)
32 {
33 pix[vc].color = alpha_pixel; // transparent pixel
34 }
35 else
36 {
37 pix[vc].color = read_pixel; // copied source pixel
38 }
39
40 vc++;
41
42 if (vc == NUMVC) { al_draw_prim(pix, NULL, NULL, 0, vc, ALLEGRO_PRIM_POINT_LIST); vc=0; } // batch points - may be faster than individual access(?)
43 }
44 }
45
46 if (vc > 0) { al_draw_prim(pix, NULL, NULL, 0, vc, ALLEGRO_PRIM_POINT_LIST); } // flush final set of points..
47
48 //al_unlock_bitmap(bitmap);
49
50 al_set_target_bitmap(old_target);
51
52 return;
53}
UPDATE: Still don't understand where the issue is - probably an incompatibility between the driver and Allegro. (Do I need to unlock a bitmap if I'm about to destroy it?). 1#define NUMVC 1024
2void kcal_convert_mask_to_alpha(ALLEGRO_BITMAP *bitmap, ALLEGRO_COLOR mask_color)
3{
4 int i=0, x=0, y=0, w, h, vc=0;
5
6 ALLEGRO_LOCKED_REGION *lr;
7 ALLEGRO_VERTEX pix[NUMVC+1];
8 ALLEGRO_COLOR alpha_pixel = al_map_rgba( 0,0,0, 0); // output value
9 ALLEGRO_BITMAP *old_target = al_get_target_bitmap();
10 ALLEGRO_BITMAP *readbmp;
11
12 w = al_get_bitmap_width (bitmap);
13 h = al_get_bitmap_height(bitmap);
14
15 // create lockable SYSTEM MEMORY bitmap clone
16 al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
17 readbmp = al_clone_bitmap(bitmap);
18
19 if (!(lr = al_lock_bitmap(readbmp, ALLEGRO_PIXEL_FORMAT_ANY, ALLEGRO_LOCK_READONLY))) { printf("Couldn't lock bitmap."); return; }
20
21 // target is VIDEO bitmap
22 al_set_target_bitmap(bitmap);
23
24 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO); // no blending
25
26 for (y=0; y<h; y++)
27 {
28 for (x=0; x<w; x++)
29 {
30 ALLEGRO_COLOR read_pixel = al_get_pixel(readbmp, x, y); // input value from locked clone
31
32 pix[vc].x = x;
33 pix[vc].y = y;
34 pix[vc].z = 0;
35
36 if (memcmp(&read_pixel, &mask_color, sizeof(ALLEGRO_COLOR)) == 0)
37 {
38 pix[vc].color = alpha_pixel; // transparent pixel
39 }
40 else
41 {
42 pix[vc].color = read_pixel; // copy pixel - shouldn't be required, but it is.
43 }
44
45 if (++vc == NUMVC) { al_draw_prim(pix, NULL, NULL, 0, vc+1, ALLEGRO_PRIM_POINT_LIST); vc=0; } // batch pixel writes
46 }
47 }
48
49 if (vc > 0) { al_draw_prim(pix, NULL, NULL, 0, vc+1, ALLEGRO_PRIM_POINT_LIST); } // final pixel flush
50
51 al_unlock_bitmap (readbmp);
52 al_destroy_bitmap(readbmp);
53
54 // reset parameters
55 al_set_target_bitmap(old_target);
56 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA); // DEFAULT
57 al_set_new_bitmap_flags (ALLEGRO_VIDEO_BITMAP | ALLEGRO_MIN_LINEAR | ALLEGRO_MAG_LINEAR); // | ALLEGRO_MIPMAP); // mipmap breaks opengl
58
59 return;
60}
|
Thomas Fjellstrom
Member #476
June 2000
![]() |
Kev Callahan said: Have sped this up by cloning the 'video' bitmap to a 'system' bitmap and lock that one for ALLEGRO_LOCK_READONLY That makes little sense, because locking a video bitmap will download the texture, and then any drawing on it will be done on the cpu in software like it would with a system bitmap. Cloning does essentially the same thing, it would download the data from the video bitmap to put in the system bitmap. Puzzling. -- |
Kev Callahan
Member #6,022
July 2005
![]() |
I'm glad someone else thinks it's weird Problem is, there's not really any documentation I can find (apart from trudging through the source code) that explains how this all works. If you come up with any ideas that may help track down the issue, I'm keen to try it(!) |
|