Drawing onto bitmap crashes when resizing the display
roger levy

Hi all,

When I resize the display I acknowledge it with al_acknowledge_resize but if I try to draw to a bitmap I created at the start of the program again it crashes. If I try to recreate this bitmap it still crashes. I have already narrowed it down to this; when the al_set_target_bitmap( bitmap ) is removed it doesn't crash.

Was this a known bug and has it been fixed?

I'm on Allegro 5.2.0. Windows 10, DirectX driver (I assume)

It's been a while since I attempted to build Allegro or anything written in C++ for that matter (I work in SwiftForth). I'd prefer not to go down that rabbit hole again... (though I might finally get on the contributor train, since I'm pretty good at git now...)

I found a 5.2.1 DLL Siegelord posted but it fails to load; I suspect due to missing dependencies (which is odd because it was the monolith build...) The thread was about a bug with the builtin font after resizing so it could be related. (https://www.allegro.cc/forums/thread/616340)

UPDATE:

I found the 5.2.2 release and fixed the loading problem. Looks like the bitmap bug was fixed.

After confirming that, I thought of an alternative approach; create the window at the native resolution and DON'T acknowledge resizes. Immediately resize it to the desired size. There'll be a blip where you see a big window but this is minor. This way contents of bitmaps are not lost and there will be no delay when resizing or fullscreening.

Neil Roy

In my own game, when I change the display, I call a function to shut down the current display; shutdown_display(true), which involves destroying all bitmaps that were loaded (as if the game was shutting down), I then call an init_display() function which is called when the game starts, it has a flag to reset the display which is passed to it, and it then loads all the graphics back in.

It works just fine that way without problems. (see my Deluxe Pacman 2 game in the link below, it is free, if you run it and change the display you will see it works perfectly).

I've never tried to do it differently. If it works, I don't mess with it. ;)

My functions I use below... I call shutdown_display() then init_display(true) when it is resized...

void shutdown_display(void)
{
   /* Destroy loaded bitmaps here */

   al_unregister_event_source(event_queue, al_get_display_event_source(setting.screen));

   if(setting.screen) { // setting.screen = the allegro display
      al_destroy_display(setting.screen);
      setting.screen = NULL;
   }
}

#SelectExpand
1void init_display(bool reset_display) 2{ 3 char s[TEXT_BUFFER] = ""; 4 ALLEGRO_BITMAP *tempBitmap = NULL; 5 6 if(!reset_display) { // These will already be NULL'd out if this is a reset 7 // Initialize pointer arrays to zero before anything else so that if we 8 // have to call shutdown() they can be checked without problems 9 memset(background, 0, sizeof(background)); 10 memset(pills, 0, sizeof(pills)); 11 memset(lines, 0, sizeof(lines)); 12 13 setting.screen = NULL; 14 pickup.sheet = NULL; 15 tool.sheet = NULL; 16 shield = NULL; 17 bullet.bitmap = NULL; 18 pacman.sheet = NULL; 19 } 20 21 // Vsync 1 means force on, 2 means forced off. 22 if(setting.vsync) 23 al_set_new_display_option(ALLEGRO_VSYNC, setting.vsync, ALLEGRO_SUGGEST); 24 25 switch(setting.fullscreen) { 26 case 0: // Windowed 27 if(setting.opengl) al_set_new_display_flags(ALLEGRO_OPENGL | ALLEGRO_WINDOWED); 28 else al_set_new_display_flags(ALLEGRO_WINDOWED); 29 break; 30 case 1: // Fullscreen Window (0 = window) 31 if(setting.opengl) al_set_new_display_flags(ALLEGRO_FULLSCREEN_WINDOW | ALLEGRO_OPENGL); 32 else al_set_new_display_flags(ALLEGRO_FULLSCREEN_WINDOW); 33 if(setting.frequency) al_set_new_display_refresh_rate(setting.frequency); 34 break; 35 case 2: // Regular Fullscreen (0 = window) 36 if(setting.opengl) al_set_new_display_flags(ALLEGRO_FULLSCREEN | ALLEGRO_OPENGL); 37 else al_set_new_display_flags(ALLEGRO_FULLSCREEN); 38 if(setting.frequency) al_set_new_display_refresh_rate(setting.frequency); 39 break; 40 default: // invalid mode, we'll select windowed by default and reset the fullscreen variable 41 if(setting.opengl) al_set_new_display_flags(ALLEGRO_OPENGL | ALLEGRO_WINDOWED); 42 else al_set_new_display_flags(ALLEGRO_WINDOWED); 43 setting.fullscreen = 0; 44 } 45 46 al_set_new_bitmap_flags(ALLEGRO_MAG_LINEAR); // | ALLEGRO_NO_PRESERVE_TEXTURE); 47 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA); 48 49 al_set_new_display_option(ALLEGRO_SINGLE_BUFFER, 1, ALLEGRO_REQUIRE); 50 51 // Allegro picks the desktop resolution automatically with ALLEGRO_FULLSCREEN_WINDOW flag set. 52 setting.screen = al_create_display(WIDTH, HEIGHT); 53 if(!setting.screen) { 54 a5_error(AT, setting.screen, "Create display failed."); 55 shut_down(); 56 exit(1); 57 } 58 59 setting.w = al_get_display_width(setting.screen); 60 setting.h = al_get_display_height(setting.screen); 61 62 if(setting.opengl) printf("OpenGL version: 0x%08X\n", al_get_opengl_version()); 63 64 // Call scale screen for all modes to correct mouse movement in certain mode changes 65 a5_scale_screen(WIDTH, HEIGHT, setting.w, setting.h); 66 67 al_clear_to_color(al_map_rgb_f(0, 0, 0)); 68 al_flip_display(); 69 70 icon = al_load_bitmap("Graphics/Deluxe_Pacman_2_Icon.png"); 71 if(!icon) { 72 a5_error(AT, setting.screen, "Error loading Deluxe_Pacman_2_Icon.png."); 73 shut_down(); 74 exit(1); 75 } 76 al_set_display_icon(setting.screen, icon); 77 78 al_set_window_title(setting.screen, "Deluxe Pacman 2"); 79 80 /// ****** Load Fonts ******* 81 /// ****** Load background tiles ******* 82 /// ****** Load pills ******* 83 /// ******* Load lines ******* 84 /// ******* Load Pickups ******* 85 /// ******* Load Tools ******* 86 /// ******* Load hearts ******* 87 /// ******* Load Ghost Spawn ******* 88 /// ******* Load Pickup Spawn ******* 89 /// ******* Create bitmap for drawing the level on ******* 90 /// ******* Initialize Pacman ******* 91 /// ****** Initialize Ghosts ******* 92 93 // reset the target bitmap back to the display 94 al_set_target_bitmap(al_get_backbuffer(setting.screen)); 95 96 // register the new display in the event_queue 97 al_register_event_source(event_queue, al_get_display_event_source(setting.screen)); 98}

roger levy

Bitmaps that weren't loaded from files aren't preserved. Their contents are erased.

Also, reloading all bitmaps isn't realistic when your game reaches over 100 MB ...

I just saw you update your post. That is an insane amount of code to resize the display...

Neil Roy

Also, reloading all bitmaps isn't realistic when your game reaches over 100 MB ...

I just saw you update your post. That is an insane amount of code to resize the display...

Try my game out (link in my sig), it works fine, and it works fast. It's not like a person is sitting there resizing the display 10 times a second. They generally resize it ONCE when they first install it and never touch that option again, or rarely. It's much faster than you imagine.

Also, that code is code I use when I initialize the game and destroy it. I redesigned the functions to easily use them when a screen mode is changed. No sense re-inventing the wheel. Works like a charm.

BUT... if there is a way I can skip reloading bitmaps, I will gladly adopt it. I never thought to look into it as this works well as is.

roger levy

My bad on the bitmap contents being lost. I was recreating a bitmap as one attempt to stop the crashing. Took that out and the bitmap contents are unaffected now.

Thread #616905. Printed from Allegro.cc