Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » resize display handling

This thread is locked; no one can reply to it. rss feed Print
 1   2 
resize display handling
shadyvillian
Member #12,426
December 2010

Hey guys I have a question for you. I've got some code that scales my ui when I resize my display. In my program I've noticed the following behaviors: While dragging the window to resize my graphics change size(display not acknowledged yet) then once I let it go, display is acknowledged(it returns to the correct size), then my scaling code kicks in and you can see it change. I'm wondering if there's a way to make this whole process more "smooth". Is there anything I could do in my end or is this all allegro backend stuff? ALLEGRO_EVENT_DISPLAY_RESIZE should be called ALLEGRO_EVENT_DISPLAY_RESIZED because it doesn't seem to call as I'm resizing. Is there a way to automatically acknowledge resize while I'm dragging that window? Or some kind of ALLEGRO_EVENT_DISPLAY_RESIZING kind of event I could use? Here's a snippet of my code for reference:

#SelectExpand
1 while(app.currentEvent.display.type != ALLEGRO_EVENT_DISPLAY_CLOSE) 2 { 3 al_wait_for_event(app.eventQueue, &app.currentEvent); 4 5 if(app.currentEvent.timer.type == ALLEGRO_EVENT_TIMER) 6 { 7 if(app.currentEvent.timer.source == app.bufferTimer) 8 { 9 app.redraw = true; 10 } 11 } 12 13 if(app.currentEvent.display.type == ALLEGRO_EVENT_DISPLAY_RESIZE) 14 { 15 al_acknowledge_resize(app.mainDisplay); 16 app.ScaleUi(); 17 } 18 19 if(app.redraw && al_is_event_queue_empty(app.eventQueue)) 20 { 21 app.Draw(); 22 } 23 }

Software Engineer by day, hacker by night.

Elias
Member #358
May 2000

It's supposed to work continuously... but whoever implemented it in windows messed up. You could file a bug report.

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

shadyvillian
Member #12,426
December 2010

I mean the display does resize but I want the event to keep firing as I drag not just once the mouse button is let off. I'll probably end up poking in the source files tonight and see if I can figure it out I suppose(just for fun)

Software Engineer by day, hacker by night.

Thomas Fjellstrom
Member #476
June 2000
avatar

I don't think you really want that. Every single resize would cause DX and Allegro to have to reinitialize your entire context, including textures. I can't imagine that would perform well at all.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Edgar Reynaldo
Member #8,592
May 2007
avatar

Other applications seem to be able to handle window resizing with no problem (non-allegro apps). I just tried CodeBlocks in a window and it resizes smoothly as butter, with no black or uninitialized areas. So it is possible. I don't know what it would take to do so though.

Thomas, are you sure there's no way to resize a window without reinitializing the entire context?

Thomas Fjellstrom
Member #476
June 2000
avatar

Other applications seem to be able to handle window resizing with no problem (non-allegro apps). I just tried CodeBlocks in a window and it resizes smoothly as butter, with no black or uninitialized areas. So it is possible. I don't know what it would take to do so though.

Windows GDI apps are not equivalent to 3d apps.

Quote:

Thomas, are you sure there's no way to resize a window without reinitializing the entire context?

If they use a 3D surface, you tend to have to reinitialize everything. I could be wrong on that, but D3D at least seems like it'd impose that limitation.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Edgar Reynaldo
Member #8,592
May 2007
avatar

Windows GDI apps are not equivalent to 3d apps.

Okay, this is something I'm not familiar with. Is it possible to make a GDI app with allegro? Would that require another driver for windows?

Quote:

If they use a 3D surface, you tend to have to reinitialize everything. I could be wrong on that, but D3D at least seems like it'd impose that limitation.

What exactly is a 3D surface? Just a D3D context? Or is it substantially different from a GDI context (if there is such a thing)...?

You can tell I know very little about this sort of thing....

Arthur Kalliokoski
Second in Command
February 2005
avatar

Is it possible to make a GDI app with allegro?

A4 can stretch a 2D image with ease.

“Throughout history, poverty is the normal condition of man. Advances which permit this norm to be exceeded — here and there, now and then — are the work of an extremely small minority, frequently despised, often condemned, and almost always opposed by all right-thinking people. Whenever this tiny minority is kept from creating, or (as sometimes happens) is driven out of a society, the people then slip back into abject poverty. This is known as "bad luck.”

― Robert A. Heinlein

Edgar Reynaldo
Member #8,592
May 2007
avatar

Thomas Fjellstrom
Member #476
June 2000
avatar

Okay, this is something I'm not familiar with. Is it possible to make a GDI app with allegro? Would that require another driver for windows?

A4 has a GDI driver. It's pretty slow, but it works. A5 pretty much wants an accelerated driver, but it isn't required. Someone could implement a GDI driver, but I don't know why you'd want such a thing.

Quote:

What exactly is a 3D surface? Just a D3D context?

Yeah, for the most part. a 3D surface can also be a texture or FBO (Frame Buffer Object. in GL terms).

Quote:

Or is it substantially different from a GDI context (if there is such a thing)...?

Very different. A "GDI Context" i assume is just a regular windows window. I don't think classic GDI has a "context" as such, other than some hidden state associated with a given program.

A4 doesn't and probably never will have resizable windows, so that's kind of moot in this case...

There's a patch for it. That no-one bothered to apply.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Edgar Reynaldo
Member #8,592
May 2007
avatar

There's a patch for it. That no-one bothered to apply.

Lost in the mailing list somewhere? Or is it still floating around?

GDI on Windows with A4 never worked reliably for me.

Allegro 5.1.GIT said:

wwindow.c#SelectExpand
871 case WM_SIZE: 872 if (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED || wParam == SIZE_MINIMIZED) { 873 /* 874 * Delay the resize event so we don't get bogged down with them 875 */ 876 if (!resize_postponed) { 877 resize_postponed = true; 878 _beginthread(postpone_thread_proc, 0, (void *)d); 879 } 880 } 881 return 0; 882 case WM_ENTERSIZEMOVE: 883 /* DefWindowProc for WM_ENTERSIZEMOVE enters a modal loop, which also 884 * ends up blocking the loop in d3d_display_thread_proc (which is 885 * where we are called from, if using D3D). Rather than batching up 886 * intermediate resize events which the user cannot acknowledge in the 887 * meantime anyway, make it so only a single resize event is generated 888 * at WM_EXITSIZEMOVE. 889 */ 890 if (d->flags & ALLEGRO_DIRECT3D_INTERNAL) { 891 resize_postponed = true; 892 } 893 break; 894 case WM_EXITSIZEMOVE: 895 if (resize_postponed) { 896 win_generate_resize_event(win_display); 897 win_display->ignore_resize = false; 898 resize_postponed = false; 899 win_display->can_acknowledge = true; 900 } 901 break; 902 } 903 904 return DefWindowProc(hWnd,message,wParam,lParam); 905}

It looks like everything happens in WM_EXITSIZEMOVE. WM_SIZE messages are mostly ignored, and WM_ENTERSIZEMOVE can't respond if using d3d (according to the comments).

Arthur Kalliokoski
Second in Command
February 2005
avatar

My point was that it's much easier to stretch a 2D image rather than resizing an entire 3D context.

“Throughout history, poverty is the normal condition of man. Advances which permit this norm to be exceeded — here and there, now and then — are the work of an extremely small minority, frequently despised, often condemned, and almost always opposed by all right-thinking people. Whenever this tiny minority is kept from creating, or (as sometimes happens) is driven out of a society, the people then slip back into abject poverty. This is known as "bad luck.”

― Robert A. Heinlein

Edgar Reynaldo
Member #8,592
May 2007
avatar

Yeah, that's fine. I just want to know if we can get a smooth resize and use D3D at the same time....

EDIT
This looks promising :
http://blogs.msdn.com/b/oldnewthing/archive/2008/01/16/7123299.aspx

Seems you can intercept the resize before it actually occurs, using WM_WINDOWPOSCHANGING or WM_SIZING.

Edit
This is the current state of affairs on D3D with Windows :
{"name":"608726","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/f\/9fccccc67c7e58de521fd1dbb9563d89.png","w":877,"h":600,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/9\/f\/9fccccc67c7e58de521fd1dbb9563d89"}608726

The current screen is frozen in place, with black or white filling in the excess area of the window until it is resized. Not very pretty.

shadyvillian
Member #12,426
December 2010

Yeah Edgar is on the same page as to what I mean, but as to a fix I know it can be done I guess implementing it in the correct way is the issue. My program is more of an app than a game(though I understand allegro is for games) I'm sure it would benefit allegro to have it implemented even if its just an optional flag.

Software Engineer by day, hacker by night.

Edgar Reynaldo
Member #8,592
May 2007
avatar

WM_ERASEBKGND might be useful to at least clear the background to a single color when resizing. If you specify a default background brush when creating the window WM_ERASEBKGND should handle it for us.

What would be ideal is to detect WM_SIZING messages and then have the window background be repainted by the user or a default function if not specified.

I will have to hack on Allegro for a while and see what I can come up with.

EDIT

Here are some of the events that are being fired during a window resize :

It starts out with WM_PAINT when the window is opened.
Then WM_WINDOWPOSCHANGING and WM_ENTERSIZEMOVE and WM_SIZING when you grab the handle on the window to resize it. Then a bunch of groups of these :

WM_SIZING
WM_WINDOWPOSCHANGING
WM_ERASEBKGND
WM_WINDOWPOSCHANGED
WM_SIZE
WM_PAINT

and then closes with a group of

WM_SIZING
WM_WINDOWPOSCHANGING
WM_WINDOWPOSCHANGING
WM_EXITSIZEMOVE
WM_WINDOWPOSCHANGING
WM_WINDOWPOSCHANGED

when you let go of the window handle.

So something we could do is provide a default background brush when creating the window handle. Also, we should be able to set a default clear color for the window when resized.

EDIT 2 :
Changing it to window_class.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1); clears the screen to black during each resize, blanking out what was showing. That's not quite what we want, but it is a start.

Elias
Member #358
May 2000

I think we should just continuously fire events. The resizing only happens after the user acknowledges it anyway. Maybe we could also have a different event used during the resize, so the current behavior stays for those who prefer it (I don't see why anyone would though). The Windows behavior is also not what we do on other platforms as far as I know.

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

Gideon Weems
Member #3,925
October 2003

Here's what I'm getting on Linux. Is this what it looks like in motion on Windows?

{"name":"608730","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/3\/7\/37b1646e7cad640d428a07942ac9fcdf.gif","w":687,"h":333,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/3\/7\/37b1646e7cad640d428a07942ac9fcdf"}608730

Everything goes immediately back to normal after releasing the, err... mouse.

Thomas Fjellstrom
Member #476
June 2000
avatar

Is your WM set to show contents while resizing? If not, we'll never get a resize event until the resize is done.

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Edgar Reynaldo
Member #8,592
May 2007
avatar

Gideon Weems
Member #3,925
October 2003

Is your WM set to show contents while resizing?

Hehe, I'm not that archaic.

As far as I can tell, this sort of resize behavior only occurs with Allegro programs--though to be honest, I never considered it much of a problem.

Thomas Fjellstrom
Member #476
June 2000
avatar

When resizing a window you can (and will) get hundreds of resize events if you don't batch them. I don't think you want to be trying to resize the GL/D3D backbuffer for every one. But if we can tell the context to maybe stretch the backbuffer when resizing, or at least clear the empty area, that would look better.

We had stretching at one point I think but people complained :D

--
Thomas Fjellstrom - [website] - [email] - [Allegro Wiki] - [Allegro TODO]
"If you can't think of a better solution, don't try to make a better solution." -- weapon_S
"The less evidence we have for what we believe is certain, the more violently we defend beliefs against those who don't agree" -- https://twitter.com/neiltyson/status/592870205409353730

Edgar Reynaldo
Member #8,592
May 2007
avatar

The problem with using a HBRUSH for the hbrBackground is that during WM_ERASEBKGND it covers the entire surface of the window with whatever brush you use. I tried (NULL_BRUSH) and (COLOR_BACKGROUND + 1), which resulted in white and black using D3D. With OpenGL the window resizes the backbuffer each time its size is changed, almost immediately, with only a brief flash of black or white along the border. If we handle WM_WINDOWPOSCHANGED and send an event then we could repaint the border or provide a way for the user to do so. The user probably knows what he wants to draw with a larger window there. So why not let him acknowledge the resize right away if they want to?

Elias
Member #358
May 2000

I'm with Edgar. Let the user decide. If they want to redraw 100s of times, let them (I for one want to). If they only want to redraw once, that's also fine. But Allegro shouldn't force to draw only once by hiding the other events.

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

Gideon Weems
Member #3,925
October 2003

As a user, I'm with Edgar as well. Processing a batch of resize events every tick of the main loop would be easy. Am I correct in thinking it would look like the following?

#SelectExpand
1/* Event handler. */ 2switch (event.type) { 3 case ALLEGRO_EVENT_TIMER: 4 bUpdate = true; 5 break; 6 case ALLEGRO_EVENT_DISPLAY_RESIZE: 7 bHandleResize = true; 8 break; 9} 10 11/* Logic updater. */ 12if (bUpdate) { 13 bUpdate = false; 14 if (bHandleResize == true) { 15 bHandleResize = false; 16 bDraw = true; 17 } 18} 19 20if (bDraw) { 21 bDraw = false; 22 // Draw. 23}

beoran
Member #12,636
March 2011

For backwards compatibility I'd keep the ALLEGRO_EVENT_DISPLAY_RESIZE as it is, and add a ALLEGRO_EVENT_DISPLAY_RESIZING event that is sent while the resize is going on. Like that, people can choose whether to continuously resize or only once.

 1   2 


Go to: