Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Blit to Android display

This thread is locked; no one can reply to it. rss feed Print
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:

#SelectExpand
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...

Elias
Member #358
May 2000

I use ALLEGRO_FULLSCREEN_WINDOW in my Android game and let Android pick the resolution for me.

--
"Either help out or stop whining" - Evert

SiegeLord
Member #7,827
October 2006
avatar

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
[SiegeLord's Abode][Codes]:[DAllegro5]:[RustAllegro]

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.

#SelectExpand
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
avatar

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
avatar

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:

#SelectExpand
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
avatar

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
avatar

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!
I hope it will also work with my library.

#SelectExpand
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}

Go to: