Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Blacking out the display while resizing

This thread is locked; no one can reply to it. rss feed Print
 1   2 
Blacking out the display while resizing
xsquid
Member #16,498
July 2016

I took some time to continue experimenting with it, and I don't think that's what's happening. It crashes right away on the first call when I step through it using a debugger, and I modified the function to only ever call it once, and it still crashes.

I'll keep playing with it to see if I can get it working, but I have no idea what's causing it at this point.

Update #1: I've noticed it doesn't like it when I use any Allegro functions inside of the callback function (drawing or display functions; it might be limited to things that try to modify the backbuffer). Outside is fine. Is that relevant?

Update #2: Yeah, it seems to throw a read access violation error if I try to do anything with the display's backbuffer inside of the callback function (or use any function that touches it).

bamccaig
Member #7,536
July 2006
avatar

If I had to guess I'd say that the callback is likely in a different thread than the main thread that you use with Allegro. That likely means that you cannot use Allegro within the callback because Allegro uses thread-local globals for a lot of state. It's probably a bad practice anyway. Unfortunately, that probably complicates things somewhat. A sensible approach may be to trigger a user-defined event if that is allowed, but I'm not sure if you'll need to somehow lock the queue... /guesses

xsquid
Member #16,498
July 2016

bamccaig said:

If I had to guess I'd say that the callback is likely in a different thread than the main thread that you use with Allegro. That likely means that you cannot use Allegro within the callback because Allegro uses thread-local globals for a lot of state. It's probably a bad practice anyway. Unfortunately, that probably complicates things somewhat. A sensible approach may be to trigger a user-defined event if that is allowed, but I'm not sure if you'll need to somehow lock the queue... /guesses

Tsk, I thought it might be something like that.

Would using a user-defined event make much of a difference compared to just using the ALLEGRO_EVENT_DISPLAY_RESIZE event? One thing I tried was redrawing and flipping the display immediately whenever this event occurs, but it doesn't seem to help (the end result looks just as laggy). If I'm totally on the wrong track with this concept, though, let me know...

Edgar Reynaldo
Member #8,592
May 2007
avatar

Okay, instead of calling al_resize_display inside of the window callback, call it in main. Set a shared variable named resize to true inside the callback, and then monitor it in main. If it's set, call al_resize_display. A mutex would probably be good and you need to store the values of the new dimensions. Allegro provides them for you with the ALLEGRO_MUTEX class. If al_resize_display triggers a WM_SIZING message, you'll probably get stuck inside an infinite loop. You may need to check if the display has already been resized to the proper size. If so, don't call al_resize_display.

xsquid
Member #16,498
July 2016

Based on the recommendations, here is the new code:

#SelectExpand
1#include <allegro5/allegro.h> 2#include <allegro5/allegro_image.h> 3#include <allegro5/allegro_primitives.h> 4#include <allegro5/allegro_windows.h> 5#include <algorithm> 6#include <Windows.h> 7#include <iostream> 8 9static ALLEGRO_MUTEX* mutex; 10static bool resize; 11static int neww, newh; 12 13bool WinProcCallback(ALLEGRO_DISPLAY* d, UINT msg, WPARAM wparam, LPARAM lparam, LRESULT* result, void* userdata) { 14 15 if (msg == WM_SIZING) { 16 17 int oldh = neww; 18 int oldw = newh; 19 20 RECT r = *(RECT*)lparam; 21 int rw = (r.right - r.left) - 21; 22 int rh = (r.bottom - r.top) - 42; 23 24 //al_lock_mutex(mutex); 25 26 if (oldh != rh || oldw != rw) { 27 28 neww = rw; 29 newh = rh; 30 resize = true; 31 32 } 33 //al_unlock_mutex(mutex); 34 35 // Return true, so Allegro knows it doesn't need to do anything for this event. 36 return true; 37 38 } 39 40 // Return false, so Allegro will handle the event on its own. 41 return false; 42 43} 44 45int main() { 46 47 // Initialize Allegro and required add-ons. 48 al_init(); 49 al_init_primitives_addon(); 50 51 // Set display flags and create the display. 52 al_set_new_display_flags(ALLEGRO_OPENGL | ALLEGRO_RESIZABLE); 53 ALLEGRO_DISPLAY *display = al_create_display(640, 480); 54 55 // Create mutex. 56 mutex = al_create_mutex(); 57 58 // Add callback function. 59 al_win_add_window_callback(display, WinProcCallback, 0); 60 61 while (1) { 62 63 //al_lock_mutex(mutex); 64 if (resize) { 65 al_resize_display(display, neww, newh); 66 al_acknowledge_resize(display); 67 resize = false; 68 } 69 //al_unlock_mutex(mutex); 70 71 al_clear_to_color(al_map_rgb(0, 0, 0)); 72 73 float w = (std::min)(al_get_display_width(display), al_get_display_height(display)); 74 float x = al_get_display_width(display) / 2.0f - w / 2.0f; 75 float y = al_get_display_height(display) / 2.0f - w / 2.0f; 76 al_draw_filled_rectangle(x, y, x + w, y + w, al_map_rgb(192, 192, 192)); 77 78 al_flip_display(); 79 80 } 81 82 return 0; 83 84}

I've commented-out the mutex stuff for now because it would randomly cause the display to lock up (I'm not sure why, sorry, this is my first doing this sort of thing; I'm going to keep trying to figure it out on my own).

With the mutex or not, though, it almost looks worse now. That is, it's much more jittery. When I resize it, it will jump to a size larger than I've dragged, jitter between that and size it should be as I move the mouse, and then snaps to where it should be when I release the mouse...

Update #1: The problem was I wasn't accounting for the window borders; I wasn't aware that that counted for the sizing values. Unfortunately, the outcome seems identical to how it was before; the contents of the display still lag behind a little bit showing white lines at the edges.

Maybe I'm not calling al_resize_display and al_acknowledge_resize in the right spot? Other than that I have no idea. Somehow I need to be able to redraw everything at the new size before the window itself is resized (e.g., resizing the buffer, drawing, then resizing the display) to avoid seeing what I assume is junk data at the edges before it's overwritten. I wonder if I can accomplish this by drawing to a different bitmap first instead of drawing directly to the backbuffer, but this is starting to get really hacky.

Is it unreasonable to not want to see junk data when resizing the window? Is there something else people normally do when working with resizable windows (aside from simply not doing that)?

I'm starting to think I might have to switch to another library to accomplish this.

Edgar Reynaldo
Member #8,592
May 2007
avatar

Don't call al_acknowledge_resize without a corresponding ALLEGRO_EVENT_DISPLAY_RESIZE.

I'll try to experiment with this later this week. Maybe this weekend. Did you try setting the background brush? If it matches your background, you probably won't even be able to notice it's resizing.

xsquid
Member #16,498
July 2016

Don't call al_acknowledge_resize without a corresponding ALLEGRO_EVENT_DISPLAY_RESIZE.

I'll try to experiment with this later this week. Maybe this weekend. Did you try setting the background brush? If it matches your background, you probably won't even be able to notice it's resizing.

Noted, I'll rewrite the test code to use an event queue.

I've tried setting the background brush, and you're absolutely right, it helps! The edges don't look ugly anymore. Doing this is a solution to the example problem of blacking out the display, but it doesn't work if I want to continue drawing while the resize is taking place (it's just a black box until I stop moving the mouse).

Maybe this is my fault; as usual I'll update this post once/if I figure out how to solve it...

 1   2 


Go to: