|
Blit to Android display |
georg53
Member #16,054
August 2015
|
I have written a small test program. This generates a red background and a blue rectangle of pixels to be drawn on top of it. My question is: Why does the red background cover the entire Android screen although the display is set to 800:600 while the rectangle of the same size stays at that size and is not zoomed accordingly? Further, how do I set the ALLEGRO_PIXEL_FORMAT so the colors are written on top of each other with XOR? Here is the code: 1#include <allegro5/allegro.h>
2#include <allegro5/allegro_ttf.h>
3#include <allegro5/allegro_primitives.h>
4#include <allegro5/allegro_android.h> /* al_android_set_apk_file_interface */
5
6#include <android/log.h>
7
8int main(int argc,char **argv)
9{
10 ALLEGRO_DISPLAY *display;
11 ALLEGRO_BITMAP *display_bitmap, *membuffer;
12 ALLEGRO_LOCKED_REGION *locked_region;
13 int lock_flags = ALLEGRO_LOCK_READWRITE;
14
15 al_init();
16 display = al_create_display(800, 400);
17
18 al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
19 //al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
20 membuffer = al_create_bitmap(800, 400);
21
22/* access display(i.e. its backbuffer) as ALLEGRO bitmap */
23 display_bitmap = al_get_backbuffer(display);
24
25/* clear display_bitmap to red color */
26 al_set_target_bitmap(display_bitmap);
27 al_clear_to_color(al_map_rgb_f(0xFF, 0, 0));
28 al_set_target_backbuffer(display);
29
30/* generate flat 32 bit pixel buffer for testing */
31 char buf[800*4*200] = { 0, };
32 uint32_t * buffer = (uint32_t *) buf, i;
33 for(i = 0; i < sizeof(buf) / sizeof(* buffer); ++i) {
34 buffer[i] = 0x0000FF00; //fill with blue
35 }
36
37/* Locking the bitmap means, we work directly with pixel data. */
38 locked_region = al_lock_bitmap(membuffer, ALLEGRO_PIXEL_FORMAT_RGBA_8888, lock_flags);
39
40 uint8_t *ptr = (uint8_t*)locked_region->data;
41 uint32_t *cptr = (uint32_t*)ptr;
42 memcpy(cptr,buffer,800*4*200); /* blit pixels into locked memory bitmap */
43
44 al_unlock_bitmap(membuffer);
45
46 al_set_target_bitmap(display_bitmap);
47 al_draw_bitmap(membuffer, 0, 0, 0);
48
49 al_flip_display();
50
51 sleep(10); /* let user gasp in awe */
52
53 return 0;
54}
|
jmasterx
Member #11,410
October 2009
|
Android does not listen to your preferred screen resolution... Agui GUI API -> https://github.com/jmasterx/Agui |
Elias
Member #358
May 2000
|
I use ALLEGRO_FULLSCREEN_WINDOW in my Android game and let Android pick the resolution for me. -- |
SiegeLord
Member #7,827
October 2006
|
For iOS, no matter what you do, you get a display with the size set by the system. I think Android should probably do the same (i.e. it should have the behavior implemented for ALLEGRO_FULLSCREEN_WINDOW for every flag). "For in much wisdom is much grief: and he that increases knowledge increases sorrow."-Ecclesiastes 1:18 |
georg53
Member #16,054
August 2015
|
Thank you for your posts. Yes, it seems that Android always uses the full screen of the current device. I got into a further problem. When I try to write two bitmaps to the screen using al_draw_bitmap_region() the first one is cleared to background color. Any idea why this happens and what should be done to have both bitmaps on the screen? I have this problem in my large program too but I demonstrate it here with this demo program.My tablet has a 2560, 1600 pixel screen size. 1#include <allegro5/allegro.h>
2#include <allegro5/allegro_ttf.h>
3#include <allegro5/allegro_primitives.h>
4#include <allegro5/allegro_android.h> /* al_android_set_apk_file_interface */
5
6#include <android/log.h>
7
8int main(int argc,char **argv)
9{
10 ALLEGRO_DISPLAY *display;
11 ALLEGRO_BITMAP *display_bitmap, *membuffer;
12 ALLEGRO_LOCKED_REGION *locked_region;
13 int lock_flags = ALLEGRO_LOCK_READWRITE;
14
15 al_init();
16 //al_set_new_display_flags(ALLEGRO_FULLSCREEN_WINDOW);
17 display = al_create_display(800,600); //(2560, 1600);
18
19 al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
20 membuffer = al_create_bitmap(2560, 1600);
21
22 display_bitmap = al_get_backbuffer(display);
23
24/* clear display_bitmap to red color */
25 al_set_target_bitmap(display_bitmap);
26 al_clear_to_color(al_map_rgb_f(0xFF, 0, 0));
27
28 al_set_target_backbuffer(display);
29
30/* generate flat 32 bit pixel buffer for testing */
31 char buf[800*4*200] = { 0, };
32 uint32_t * buffer = (uint32_t *) buf, i;
33 for(i = 0; i < sizeof(buf) / sizeof(* buffer); ++i) {
34 buffer[i] = 0x0000FF00; //fill with blue
35 }
36
37/* Locking the bitmap means, we work directly with pixel data. */
38 locked_region = al_lock_bitmap(membuffer, ALLEGRO_PIXEL_FORMAT_RGBA_8888, lock_flags);
39 uint8_t *ptr = (uint8_t*)locked_region->data;
40 uint32_t *cptr = (uint32_t*)ptr;
41 memcpy(cptr,buffer,800*4*200); /* blit pixels into locked memory bitmap */
42 al_unlock_bitmap(membuffer);
43
44/* write pixels to display at position 0,0 */
45 al_set_target_bitmap(display_bitmap);
46 al_draw_bitmap_region(membuffer, 0, 0, 800, 50, 0, 0, 0);
47 al_flip_display();
48
49/* write pixels to display at position 0,200 */
50 al_set_target_bitmap(display_bitmap);
51 al_draw_bitmap_region(membuffer, 0, 0, 800, 50, 0 ,200, 0);
52 al_flip_display();
53
54 sleep(15); /* let user gasp in awe */
55
56 return 0;
57}
|
RPG Hacker
Member #12,492
January 2011
|
Why are you flipping the display twice? You're only supposed to flip the display once per frame, after all your drawing is done.
|
georg53
Member #16,054
August 2015
|
I thought I can flip as often as I like. If I have drawn the first pixel block and the user makes an input, I want to draw the second pixel block at a different location on the screen and leave the first as it is. How should I implement that then? I guess I have to make two al_flips then. |
RPG Hacker
Member #12,492
January 2011
|
A flip always switches between multiple backbuffers, so it certainly can't work that way (with the second flip you'd always dispose the effects of the first flip). You need to make sure to draw everything you want on the screen for one frame between your calls to al_clear_to_color() and al_flip_display(), both of which should only be called once per frame (with a few exceptions for al_clear_to_color(), but let's ignore that here). Normally, when programming a game, you have some kind of game loop, which makes implementing the kind of behavior you want easier. It's still possible to implement with your current version, but you'll have to copy the drawing of the first rectangle, which of course makes the code a bit messier. You'd want something similar to this then: 1/* clear display_bitmap to red color */
2al_set_target_backbuffer(display);
3al_clear_to_color(al_map_rgb_f(0xFF, 0, 0));
4
5/* generate flat 32 bit pixel buffer for testing */
6char buf[800*4*200] = { 0, };
7uint32_t * buffer = (uint32_t *) buf, i;
8
9for(i = 0; i < sizeof(buf) / sizeof(* buffer); ++i)
10{
11 buffer[i] = 0x0000FF00; //fill with blue
12}
13
14/* Locking the bitmap means, we work directly with pixel data. */
15locked_region = al_lock_bitmap(membuffer, ALLEGRO_PIXEL_FORMAT_RGBA_8888, lock_flags);
16uint8_t *ptr = (uint8_t*)locked_region->data;
17uint32_t *cptr = (uint32_t*)ptr;
18memcpy(cptr,buffer,800*4*200);
19
20/* blit pixels into locked memory bitmap */
21al_unlock_bitmap(membuffer);
22
23/* write pixels to display at position 0,0 */
24al_draw_bitmap_region(membuffer, 0, 0, 800, 50, 0, 0, 0);
25al_flip_display();
26
27// v ----- NEW CODE ------ v
28
29// <- I suppose here is where you want to wait for user input, so read user input here
30
31/* We're on another backbuffer since the last flip, so clear the new backbuffer */
32al_clear_to_color(al_map_rgb_f(0xFF, 0, 0));
33
34/* Now draw the first rectangle again, because it is gone by now */
35al_draw_bitmap_region(membuffer, 0, 0, 800, 50, 0, 0, 0);
36
37// ^ ----- NEW CODE ------ ^
38
39/* write pixels to display at position 0,200 */
40al_draw_bitmap_region(membuffer, 0, 0, 800, 50, 0 ,200, 0);
41al_flip_display();
42
43sleep(15);
I also simplified your code a bit, there is really no need to set the target bitmap before every draw call when you're always drawing to the same bitmap.
|
George24
Member #14,359
June 2012
|
Sorry for using my outdated ID from this PC. I am georg53 Thank you for providing a modified version of my program. I would prefer to have one buffer in memory and partially modify that as needed after a user input and then write that modified buffer to the screen using al_draw_bitmap_region. I guess if I do not al_flip the result of al_draw_bitmap_region will not appear on the screen. I do not want to build up the entire screen contents each time before al_flip if it can be avoided. My program is currently designed differently. I am trying to use Allegro as a graphics backend to a library. That library passses me blocks of pixels which shall modify part of the current screen contents. If the block of raw pixels I get would be an Allegro bitmap I could just use al_draw_bitmap_region. They are just a block of 4 byte truecolor pixels. |
RPG Hacker
Member #12,492
January 2011
|
Alright, got it. Then this might be a better solution for you: Instead of rendering to the display directly, create a screen-sized bitmap at the start of your app, set this bitmap as your target bitmap, clear it once and then perform all your subsequent drawing operations on this one bitmap without ever clearing it again. When you do this, you only have to blit this bitmap to the display backbuffer before every call to al_flip_display(). In this case, you don't even have to clear the backbuffer each frame because you're completely overwriting the whole backbuffer contents each frame, anyways. I'd give you some example code, but I don't have much time right now. I hope my explanation was helpful enough.
|
Bruce Pascoe
Member #15,931
April 2015
|
The main takeaway here is, you have to assume the contents of the backbuffer are undefined (in the programming sense of undefined behavior) after a flip. It could be garbage pixels, a render from 3 frames ago, black, etc. There's no way to tell. Best not to assume anything.
|
georg53
Member #16,054
August 2015
|
I followed RPG Hacker's outline and came up with the following example which seems to work. Thank you very much! 1#include <allegro5/allegro.h>
2
3int main(int argc,char **argv)
4{
5 ALLEGRO_DISPLAY *display;
6 ALLEGRO_BITMAP *membuffer;
7 ALLEGRO_LOCKED_REGION *locked_region;
8 int lock_flags = ALLEGRO_LOCK_READWRITE;
9 double zoom = 1.5;
10
11 al_init();
12 display = al_create_display(800,600);
13
14 al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP);
15 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_ZERO);
16 membuffer = al_create_bitmap(800,600); //(2560, 1600);
17
18/* clear display_bitmap to red color */
19 al_set_target_bitmap(membuffer);
20 al_clear_to_color(al_map_rgb_f(0xFF, 0, 0));
21
22/* generate flat 32 bit pixel buffer for testing */
23 char buf[800*4*200] = { 0, };
24 uint32_t * buffer = (uint32_t *) buf, i;
25 for(i = 0; i < sizeof(buf) / sizeof(* buffer); ++i) {
26 buffer[i] = 0x0000FF00; //fill with blue
27 }
28
29/* Locking the bitmap means, we work directly with pixel data. */
30 locked_region = al_lock_bitmap(membuffer, ALLEGRO_PIXEL_FORMAT_RGBA_8888, lock_flags);
31 uint8_t *ptr = (uint8_t*)locked_region->data;
32 uint32_t *cptr = (uint32_t*)ptr;
33 memcpy(cptr,buffer,800*4*200); /* blit pixels into locked memory bitmap */
34 al_unlock_bitmap(membuffer);
35
36/* write pixels to display */
37 al_set_target_backbuffer(display);
38 al_draw_scaled_rotated_bitmap(membuffer, 0, 0, 0, 0, zoom, zoom, 0, 0);
39 al_flip_display();
40 sleep(2);
41
42/* add pixelblock at different position */
43 locked_region = al_lock_bitmap(membuffer, ALLEGRO_PIXEL_FORMAT_RGBA_8888, lock_flags);
44 *ptr = (uint8_t*)locked_region->data;
45 *cptr = (uint32_t*)ptr;
46 memcpy(cptr+800*4*60,buffer,800*4*200); /* blit pixels into locked memory bitmap */
47 al_unlock_bitmap(membuffer);
48
49/* write pixels to display */
50 al_set_target_backbuffer(display);
51 //rotate to landscape
52 al_draw_scaled_rotated_bitmap(membuffer, 0, 800, 0, 0, zoom, zoom, ALLEGRO_PI/2, 0);
53 al_flip_display();
54
55 sleep(15); /* let user gasp in awe */
56
57 return 0;
58}
|
|