Problem toggling between Window and Fullscreen
roger levy

Forth code with equivalent psuedocode


: fs?   display al_get_display_flags ALLEGRO_FULLSCREEN_WINDOW and 0<> ;

: w/f
   display ALLEGRO_FULLSCREEN_WINDOW fs? not 
      al_toggle_display_flag 
         0= abort" could not switch to fullscreen"
   fs? 0= if 
      display ALLEGRO_WINDOWED 1 al_toggle_display_flag drop
   then
;

\ ------------

function isfullscreen () { 
   return ( al_get_display_flags(display) & ALLEGRO_FULLSCREEN_WINDOW) != 0 ); 
}

function switchWF() {
   al_toggle_display_flag( display, ALLEGRO_FULLSCREEN_WINDOW, ! isfullscreen() );
   if ( ! isfullscreen() ) {
      al_toggle_display_flag( display, ALLEGRO_WINDOWED, 1 );
   }
}



Switching from windowed to fullscreen in this manner works, but switching back from fullscreen to windowed does not.

I had difficulty taking a screenshot. Basically what happens is the screen goes black and the game displays at the size of the windowed mode in the bottom left corner. I don't see a window or the desktop.

Anyone else have this problem? Is it a bug? Is there something I'm doing wrong? A step I've left out?

Edgar Reynaldo

<code>code goes here...</code> tags work.

See al_toggle_display_flag. It says only ALLEGRO_FULLSCREEN_WINDOW and ALLEGRO_NOFRAME are allowed after display creation. So just toggle ALLEGRO_FULLSCREEN_WINDOW. I just tested it today on Vista and it worked for me.

For example, this code worked just now :

#SelectExpand
1 2#include <stdio.h> 3#include <stdlib.h> 4#include <allegro5/allegro.h> 5 6int main(int argc, char **argv) 7{ 8 ALLEGRO_DISPLAY *display = NULL; 9 10 if(!al_init()) 11 { 12 fprintf(stderr, "failed to initialize allegro!\n"); 13 return -1; 14 } 15 16 17 al_install_keyboard(); 18 19 //al_set_new_display_flags(ALLEGRO_FULLSCREEN); 20 al_set_new_display_option(ALLEGRO_COLOR_SIZE , 32 , ALLEGRO_REQUIRE); 21 const int SCREEN_WIDTH = 800; 22 const int SCREEN_HEIGHT = 600; 23 24 bool fullscreen = false; 25 if (fullscreen) { 26 al_set_new_display_flags(ALLEGRO_FULLSCREEN); 27 } 28 29 display = al_create_display(SCREEN_WIDTH , SCREEN_HEIGHT); 30 if(!display) 31 { 32 fprintf(stderr, "failed to create display!\n"); 33 return -1; 34 } 35 36 ALLEGRO_EVENT_QUEUE* queue = al_create_event_queue(); 37 if (!queue) {printf("failed to create queue\n");} 38 39 al_register_event_source(queue , al_get_keyboard_event_source()); 40 al_register_event_source(queue , al_get_display_event_source(display)); 41 42 bool quit = false; 43 do { 44 45 al_clear_to_color(al_map_rgb(0,0,0)); 46 al_flip_display(); 47 48 do { 49 ALLEGRO_EVENT ev; 50 al_wait_for_event(queue , &ev); 51 52 if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {quit = true;} 53 if ((ev.type == ALLEGRO_EVENT_KEY_DOWN) && (ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE)) {quit = true;} 54 if ((ev.type == ALLEGRO_EVENT_KEY_DOWN) && (ev.keyboard.keycode == ALLEGRO_KEY_F)) { 55 fullscreen = !fullscreen; 56 al_toggle_display_flag(display , ALLEGRO_FULLSCREEN_WINDOW , fullscreen); 57 58 } 59 60 } while (!al_is_event_queue_empty(queue)); 61 } while(!quit); 62 return 0; 63}

roger levy

I took out the line with ALLEGRO_WINDOWED but it's the same as before.

The only difference to your code is that I start the game in windowed mode while your code starts in fullscreen. Does your code still work if you start in windowed?

Edgar Reynaldo

I don't think you're toggling the actual flag. If you don't toggle the flag it will never change.

Edit
Perhaps I should restate - the semantics of al_toggle_display_flag are not to actually toggle the flag you passed in, but to set that flag to the value you passed to it.

Thomas Fjellstrom

IIRC ALLEGRO_FULLSCREEN_WINDOW is a modifier for ALLEGRO_WINDOWED. I don't think you want to mix ALLEGRO_FULLSCREEN and ALLEGRO_FULLSCREEN_WINDOW.

roger levy

I am definitely using it the way you describe - passing in the state I want. I even made double-sure by using a variable that I toggle myself, just like your code. When I pass in a 0 it becomes a small display in the corner of a black screen, when it is !0 again it becomes fullscreen again.

edit: my bad, looking at your code again i see you set fullscreen to false so your program should be starting in windowed like mine. btw, I am using ALLEGRO_FULLSCREEN_WINDOW and ALLEGRO_WINDOWED only, never ALLEGRO_FULLSCREEN.

Edgar Reynaldo

Well, think you can get a print screen? And you should post your specs - OS, compiler and version of Allegro.

Edit
@Tomasu
Oh yeah! Sorry, that was scraps from an earlier bit of code but it does the right thing even if it looks wrong

roger levy

I cannot take a screenshot. When running the game in fullscreen, CTRL+Printscreen takes a screenshot of a section of a different window for some reason.

It's pretty easy to imagine. Black screen. Game is displayed on bottom left corner, small.

OS: Windows 8, Allegro version 5.1.9

What compiler version do you need? What I used to compile Allegro or my Forth compiler? (Not sure how that would help you)

i made a simulation of how it looks, in mspaint. This is AFTER trying to toggle from fullscreen back to windowed. Fullscreen looks fine.

{"name":"sim.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/e\/aeaf2778e7e21895d1fb0d34a35e9ad1.png","w":1680,"h":1050,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/e\/aeaf2778e7e21895d1fb0d34a35e9ad1"}sim.png

Edgar Reynaldo

Yeah, I mean what compiler did you use to compile allegro? MSVS or MinGW? Which versions?

Neil Roy

I had a similar problem just yesterday. After creating functions that properly destroyed all video memory bitmaps and display, it then sets up a new display and reloads the bitmaps with no problem. I start my game in Windowed mode which is the default if you don't set anything. What happens is that if I switch to either of the two fullscreen modes (which worked fine) then go to switch back, I get the black screen with no window. Well, this was because I never set the windowed mode in the first place because it is the default. The solution is to simply set the mode to windowed mode from the get go, don't assume a default.

I simply added in the line al_set_new_display_flags(ALLEGRO_WINDOWED); so the default mode is set manually, then I switch one of the fullscreen modes if that is what is set up.

If you're like me you probably never bothered with al_set_new_display_flags(ALLEGRO_WINDOWED); because it is the default. Anyhow, that fixed it.

Edit: This is my function (with all the code that loads in bitmaps removed):
WIDTH = 800
HEIGHT = 600
setting.fullscreen = 0 for windowed, 1 for fullscreen window and 2 for fullscreen.
Bitmaps and fonts are normally loaded here as well, I have a separate function for destroying the display and bitmaps which I call when I want to reset the display before calling this.

#SelectExpand
1void init_display() 2{ 3 // Vsync 1 means force on, 2 means forced off. 4 if(setting.vsync) al_set_new_display_option(ALLEGRO_VSYNC, setting.vsync, ALLEGRO_SUGGEST); 5 6 if(setting.opengl) al_set_new_display_flags(ALLEGRO_OPENGL|ALLEGRO_WINDOWED); 7 else al_set_new_display_flags(ALLEGRO_WINDOWED); 8 9 if(setting.fullscreen == 1) { // Regular Fullscreen mode (0 = window) 10 if(setting.opengl) al_set_new_display_flags(ALLEGRO_FULLSCREEN | ALLEGRO_OPENGL); 11 else al_set_new_display_flags(ALLEGRO_FULLSCREEN); 12 13 if(setting.frequency) al_set_new_display_refresh_rate(setting.frequency); 14 } 15 else if(setting.fullscreen == 2) { // Fullscreen Window (0 = window) 16 if(setting.opengl) al_set_new_display_flags(ALLEGRO_FULLSCREEN_WINDOW | ALLEGRO_OPENGL); 17 else al_set_new_display_flags(ALLEGRO_FULLSCREEN_WINDOW); 18 19 if(setting.frequency) al_set_new_display_refresh_rate(setting.frequency); 20 } 21 22 al_set_new_bitmap_flags(ALLEGRO_MAG_LINEAR); 23 al_set_blender(ALLEGRO_ADD, ALLEGRO_ONE, ALLEGRO_INVERSE_ALPHA); 24 25 al_set_new_display_option(ALLEGRO_SINGLE_BUFFER, 1, ALLEGRO_REQUIRE); 26 27 // Allegro picks the desktop resolution automatically with ALLEGRO_FULLSCREEN_WINDOW flag set. 28 setting.screen = al_create_display(WIDTH, HEIGHT); 29 if(!setting.screen) { 30 a5_error(AT, setting.screen, "Create display failed."); 31 shut_down(); 32 exit(1); 33 } 34 35 setting.w = al_get_display_width(setting.screen); 36 setting.h = al_get_display_height(setting.screen); 37 38 // Call scale screen to fit our fullscreen window on screen. 39 if(setting.fullscreen == 2) a5_scale_screen(WIDTH, HEIGHT, setting.w, setting.h); 40 41 // Load fonts and bitmaps here (removed code) 42 43 // reset the target bitmap back to the display 44 al_set_target_bitmap(al_get_backbuffer(setting.screen)); 45}

roger levy

@Edgar MinGW gcc 4.8.1

@NiteHackr The flags I set at program start are:
ALLEGRO_OPENGL
ALLEGRO_WINDOWED
ALLEGRO_RESIZABLE

Neil Roy

I just edited my last post with my code. I don't use "ALLEGRO_RESIZABLE" at all and most of the time I do not use OpenGl, although the option is there for it and it works.

Edit: Oh, and I personally use Allegro 5.1.7 (precompiled) and GCC 4.7.0, as well as Windows 7.

Edgar Reynaldo

I'm not sure what to tell you except to wait for someone who knows more. It could be a change made to Windows 8 that broke something, but I don't know because window creation should be the same on every windows version but somebody correct me if I'm wrong.

roger levy

Indeed I just discovered that by removing ALLEGRO_OPENGL the issue is gone. The game still seems to run at full speed, so I'm guessing it's running in D3D mode? I guess I found a bug in the OpenGL implementation.

This is fine as a temporary fix but I need OpenGL, all my advanced graphics modules are in OpenGL (fast quads, shaders, 3d models, render to texture, etc).

Neil Roy

Ah, yeah, after reading your post I just tried my own game out with OPENGL enabled (OpenGL 4 on my system) and it crashed, where as it works perfectly fine without it.

"Assertion failed: 0, file d:\Libraries\build\allegro\src\allegro-git\allegro-git
\src\opengl\ogl_bitmap.c, line 357"
(I am using Allegro 5.1.7, GCC 4.7.0 on Windows 7)

After further testing, this only happens in ALLEGRO_FULLSCREEN mode, it doesn't happen in an ALLEGRO_WINDOWED or ALLEGRO_FULLSCREEN_WINDOW.

roger levy
Kris Asick

When I first switched to using Windows 8, I noticed that ALLEGRO_WINDOWED and ALLEGRO_FULLSCREEN_WINDOW were producing stuttering in the framerates of the game I'm working on, where the framerate will be fine for a moment, then stutter for a moment, then be fine for a moment, stutter for a moment, fine for a moment, etc. etc.

However, this only affects the first ALLEGRO_DISPLAY object created. Destroying that display and creating another eliminates the stuttering issue, even if the new display is identical to the first one in every way.

As a workaround to this, I'm moving all video configuration options into a startup window running ALLEGRO_WINDOWED, where a little bit of stuttering isn't going to make a huge difference. Not sure if it's strictly OpenGL related or not as my game uses GLSL fragment shaders so I pretty much have to use OpenGL exclusively for the moment.

However...

1. I have not run into the problem described from the start of this thread. I can make multiple screen setting switches without running into a missing desktop. That said...

2. ...if I switch into one video mode then try immediately to switch into another without really doing anything, this causes some extremely nasty glitching to occur, forcing me to perform a hard-reset of the entire system.

For reference, I never use al_toggle_display_flag() as I was taught from the early days of game coding that you NEVER "adjust" existing displays. The best approach is to close out the display completely (loaded textures and all) and start a new one in order to ensure you're not breaking anything in the process, since altering an existing display context can be an extremely temperamental process that is likely going to perform differently on every OS and video card combination out there. :P

Edgar Reynaldo

I can confirm that it doesn't work to change back to windowed mode from a fullscreen window with opengl. I'm using latest 5.1 from GIT, MinGW 4.5.0 and I'm on Vista.

Edit
I can also confirm that completely re-creating the display fixes the problem in both directx and opengl modes.

Neil Roy

I didn't have a problem creating displays for OpenGL, my problem was with the following line totally crashing my game:

al_draw_scaled_bitmap(al_get_backbuffer(setting.screen), offset_x, offset_y, WIDTH*scale_x, HEIGHT*scale_y, 0, 0, WIDTH, HEIGHT, 0);

This line works perfectly with DirectX in Windowed, Fullscreen Windowed and Fullscreen.
It works perfectly with OpenGL in Windowed and Fullscreen Windowed.

It only crashes in OpenGL Fullscreen mode. It copies the game screen to a buffer of size WIDTHxHEIGHT which is created with all error checks in place, so I figure my only option at this point is to remove OpenGL support, at least in that mode anyhow, which will make my game Windows only, or at least not have a fullscreen/OpenGL option on other platforms.

Slartibartfast

It copies the screen to itself as far as I can see which doesn't make a lot of sense to me.

pkrcel

He probably sets a different taget bitmap before the instruction, I guess.

Slartibartfast
pkrcel said:

He probably sets a different taget bitmap before the instruction, I guess.

I see. Still doing it wrong though ;)

Quote:

al_get_backbuffer

ALLEGRO_BITMAP *al_get_backbuffer(ALLEGRO_DISPLAY *display)

Return a special bitmap representing the back-buffer of the display.

Care should be taken when using the backbuffer bitmap (and its sub-bitmaps) as the source bitmap (e.g as the bitmap argument to al_draw_bitmap). Only untransformed operations are hardware accelerated. This consists of al_draw_bitmap and al_draw_bitmap_region when the current transformation is the identity. If the tranformation is not the identity, or some other drawing operation is used, the call will be routed through the memory bitmap routines, which are slow. If you need those operations to be accelerated, then first copy a region of the backbuffer into a temporary bitmap (via the al_draw_bitmap and al_draw_bitmap_region), and then use that temporary bitmap as the source bitmap.

Not sure if that would fix the crash, but it should at least adhere better to the documentation :)

pkrcel

I see, that "scaled" is a major issue then, surely a crash is STILL a downer since it was only expected to be "slow".

Slartibartfast
pkrcel said:

I see, that "scaled" is a major issue then, surely a crash is STILL a downer since it was only expected to be "slow".

Indeed, though it is likely that the crash is caused because of a bug leading to the "fast" code path being used when the "slow" code path should be used, thus fixing that call to be fast may just fix the crash for his current code and version of allegro.

pkrcel

Now, NH should answer, but I got the impression that the scaled version is fundamental in maintaining the aspect ratio?

Slartibartfast
pkrcel said:

Now, NH should answer, but I got the impression that the scaled version is fundamental in maintaining the aspect ratio?

Sure, but as per documentation - he can still write from the screen to another bitmap without scaling and then write from the bitmap to the screen with scaling.
And if he does that, then wouldn't it be better to just do all drawing to that temporary bitmap and then just draw that bitmap scaled?

Neil Roy

It copies the screen to itself as far as I can see which doesn't make a lot of sense to me.

I left out the code which sets up another bitmap. Which should be obvious given that I already stated that works in all DirectX modes and all Windowed OpenGL modes. It only doesn't work in OpenGL Fullscreen.

pkrcel said:

He probably sets a different taget bitmap before the instruction, I guess.

Yup.

Here's the relevant code:

ALLEGRO_BITMAP *menuback = NULL;

menuback = al_create_bitmap(WIDTH, HEIGHT);
al_set_target_bitmap(menuback);
al_draw_scaled_bitmap(al_get_backbuffer(setting.screen), offset_x, offset_y, WIDTH*scale_x, HEIGHT*scale_y, 0, 0, WIDTH, HEIGHT, 0);
al_set_target_bitmap(al_get_backbuffer(setting.screen));

I left out error checking code and other nonrelavent code, but I do check all return values. Anyhow, t his works perfectly fine in ALL modes except OpenGL Fullscreen. So it is not my code.

pkrcel said:

Now, NH should answer, but I got the impression that the scaled version is fundamental in maintaining the aspect ratio?

Yup. That is exactly why I did this. But I suppose I could try creating a larger buffer then copying the full screen to it, that takes up much more memory though and still doesn't explain why it works in all other modes.

I don't have a problem when using DirectX with this code at all. I don't have a problem when using this code in any of the Windowed modes with OpenGL (ALLEGRO_WINDOWED & ALLEGRO_FULLSCREEN_WINDOW work fine) only with OpenGL and ALLEGRO_FULLSCREEN does this happen.

If it was a problem, than why am I not seeing it in DirectX? I'll try your fix out anyhow and see how that goes. It would be a good temporary (albeit, memory hogging) solution, but this should be looked into.

Edit: Okay, I changed that to...

al_set_target_bitmap(menuback);
al_draw_bitmap(al_get_backbuffer(setting.screen), 0, 0, 0);

...and it is drawn with..

al_set_target_bitmap(al_get_backbuffer(setting.screen));
al_draw_bitmap(menuback, 0, 0, 0);

And it works fine, no errors AND the game screen looks just as it should, but what bothers me now is, IT SHOULD NOT WORK! That is, the game screen, which is an 800x600 screen that is transformed and clipped to fit on the player's desktop resolution, in my case, 1920x1080, should not be displaying properly at all with the code I use, but it is, meaning that OpenGL in Fullscreen mode is ignoring the transforms and clipping that was set up. When I draw the bitmap to 0,0, that should be 0,0 of the clipped region, not 0,0 of my actual screen, if you see what I mean.

(I don't know if I mentioned this, but I am using a precompiled Allegro 5.1.7 and my OpenGL is version 4 all on Windows 7 with up to date nVidia drivers).

Edit: Okay, so now it looks fine in ALLEGRO_FULLSCREEN but not ALLEGRO_FULLSCREEN_WINDOW, so I guess my problem is I need to check which mode the game is in and then either drawn normally (because FULLSCREEN uses 800x600) or draw a stretched image (which may be a problem, I don't know) if it is a FULLSCREEN_WINDOW.

EDIT2:

I changed my code so the following works...

For copying the background...

al_set_target_bitmap(menuback);
al_draw_bitmap(al_get_backbuffer(setting.screen), 0, 0, 0);

When drawing (fullscreen == 2 for ALLEGRO_FULLSCREEN_WINDOW)

if(setting.fullscreen == 2) al_draw_scaled_bitmap(menuback, offset_x, offset_y, WIDTH*scale_x, HEIGHT*scale_y, 0, 0, WIDTH, HEIGHT, 0);
else al_draw_bitmap(menuback, 0, 0, 0);

<cheer> I tested this thoroughly, in all modes, in DirectX and OpenGL, switching from both Fullscreen modes back to Windowed etc... no problems... yay! \o/ ;)

It's funny that I have to actually scale the background DOWN to 800x600 in ALLEGRO_FULLSCREEN_WINDOW before I draw it, which will then get it transformed and scaled back up again... but... it works. It's a menu screen and not speed dependant at all so.

Thread #614227. Printed from Allegro.cc