[A5] Fullscreen + keep 4:3 ratio
anto80

Hello all,

I’m using Allegro 5.0.10 and I have some problems when setting up fullscreen displays on « some configurations » (actually I was not able to detect which configuration makes it work)
I would like the keep the 4:3 ratio but nowadays most desktop monitors and laptop monitor are 16:9 (or even 16:10).

Here s my code:

al_set_new_display_option(ALLEGRO_DEPTH_SIZE, 32, ALLEGRO_REQUIRE);
al_set_new_display_flags(ALLEGRO_DIRECT3D| ALLEGRO_FULLSCREEN);
ALLEGRO_DISPLAY* _display = al_create_display(640, 480);

  • On a desktop PC [A] / Monitor [A] / Videocard [1] : It works like I want = It displays fullscreen and the 4:3 is kept, showing black rectangles on the sides.

  • On a desktop PC [A] / Monitor [A] / Videocard [2] : It works like I want = It displays fullscreen and the 4:3 is kept, showing black rectangles on the sides.

  • On a laptop PC [B] / Videocard [3] : It doesn’t works like I want = It displays fullscreen but the ratio is altered (stretched)

  • On a laptop PC [B] / Videocard [3] connected to an External Monitor [C] : It doesn’t works like I want = It displays fullscreen but the ratio is altered (stretched)

My questions:
Is there a way to force the ratio to be kept when creating display?
Is ALLEGRO_DIRECT3D a good choice? I can switch my code to ALLEGRO_OPENGL. I can also make the user choose which one to use.

Thank you

RPG Hacker

From my own experience, I can say that this behavior seems to depend mostly on your graphics card and/or monitor, sometimes even on the video cable you use to connect both. Yeah, no joke. Once I was playing around with a SNES emulator in fullscreen mode, where I had set the resolution to 640x480. When I was using a DVI cable to connect my graphics card to my monitor, it would always stretch the image to the full screen, no matter the actual resolution, so a 4:3 screen was effectively stetched to 16:9. Once I switched to HDMI, though, the same combination of graphics card and monitor actually started accounting for the aspect ratio. So now, when I start the emulator (still with the same resolution), the aspect ratio is actually kept and I get black bars to the left and right.

One thing you might want to try: Instead of using ALLEGRO_FULLSCREEN, try using ALLEGRO_FULLSCREEN_WINDOW (or whatever it was called). That option is actually less dependent on the graphics card, so that one might be better at keeping the aspect ratio.

Erin Maus

I would suggest using the native resolution and implementing the letterboxing and scaling yourself. Running any non-native resolution on flat-screen monitors generally looks terrible, especially if the aspect ratios don't match.

Thomas Fjellstrom

Some cards (nvidia at least) will support faking the mode you want, by scaling and centering the display.

Some monitors have scalers that support a bunch of different modes, and will center+scale smaller modes. Some don't support old modes, and some that do, will stretch.

Basically, you want to emulate it yourself. Set the mode to the monitor's native mode. Use an ALLEGRO_TRANSFORM to scale up the image to fit within the native mode size, and translate over. May want to clip (`al_set_clipping_rectangle`) drawing to the emulated mode rectangle.

Mark Oates

Yea, hardware is consistently inconsistent. You should get and use the native resolution of the display and then scale, stretch, and/or letterbox in your software.

anto80

Thanks.

If I use bigger (yet native) display, without altering the scene bitmap dimensions, will I have severe performance decrease (FPS drops) ?

Mark Oates

Uhm, you might, but if you set things up correctly it shouldn't make a difference.

What I do is draw everything to a separate ALLEGRO_BITMAP, then scale/stretch to the display on the final pass. So essentially everything in your code is the same as before, except you're drawing to a separate ALLEGRO_BITMAP instead of the bitmap of the ALLEGRO_DISPLAY.

Then, all your scaling and stretching and letter boxing and whatnots are of concern only when you draw that bitmap to the display before flipping.

I'm not sure if that's the best way, but that's what I'm doing now and it keeps things easy and compartmentalized in my code. There might be equally good alternative solutions.

Thomas Fjellstrom

I think if you make sure your drawing isn't hitting more than the area you're wanting, then it'll work the same as drawing to an offscreen buffer and then copying that to the screen.

anto80

Thanks for your answers.

Btw how do I detect the fullscreen display size using Allegro 5.0 routines?
Is there a way to detect all "possible" fullscreen display sizes for this video card?

As for my code:

ALLEGRO_DISPLAY* _display; // The display (size: SCREEN_W*SCREEN_H 
                           //                    = Allegro constants)      
ALLEGRO_BITMAP* _bufferDisplay;  // My "scene" (size BITMAP_W*BITMAP_H = 640*480)

// ...

int nFullScreenH = SCREEN_H;
int nFullScreenW = 4*SCREEN_H/3;
int nFullScreenOffsetX = (SCREEN_W - nFullScreenW)/2;

My Loop :

al_set_target_bitmap(_bufferDisplay);
al_clear_to_color(COL_BACKGROUND); // equals to color(0,0,0,0)
_pGameHelper->Draw(); // all my draws

al_set_target_backbuffer(_display); 

al_draw_scaled_bitmap(_bufferDisplay, 
  0+nShakeScreenX, 0+nShakeScreenY, // the current screen-shake values
  BITMAP_W, BITMAP_H,  // The size of my "scene" 
  nFullScreenOffsetX, 0, 
  nFullScreenW, nFullScreenH,  
  0x00);

al_flip_display();

Is this what you suggest?

@Thomas , you said to use ALLEGRO_TRANSFORM and al_set_clipping_rectangle
Will that be faster?

Thanks again

Thomas Fjellstrom
anto80 said:

@Thomas , you said to use ALLEGRO_TRANSFORM and al_set_clipping_rectangle
Will that be faster?

Theoretically it should be yes.

anto80
Thomas said:

Theoretically it should be yes.

OK Then, if it's possible for you to give me an example, I would appreciate.
Thank you.

And it is possible to get all fullscreen display sizes for the current video card, using Allegro routines?

Thomas Fjellstrom
anto80 said:

OK Then, if it's possible for you to give me an example, I would appreciate.

Hmm.. Well using the transform api isn't too difficult. You'd just calculate the scaling, and call al_scale_transform to scale drawing with that transform. You'd also want to al_translate_transform to move the origin such that the area you want to draw in is centered in the display. after that you'd al_use_transform. And after that, you just make sure not to draw outside your preferred screen size to cut down on wasted draw calls. (even if you do use clipping)

I don't have an example of this handy, and I'm a little busy for the next little while :( might be able to whip something up later, but don't hold your breath ;)

Quote:

And it is possible to get all fullscreen display sizes for the current video card, using Allegro routines?

Yup. Theres a whole api to query the available display modes. see al_get_display_mode

These days, you may actually just want to use the ALLEGRO_FULLSCREEN_WINDOW display driver, and it'll just set the current desktop resolution size. Afterwards you can just use al_get_display_width/height etc.

Chris Katko

Definitely do it in software (GPU) not on the TV/monitor. Cheap TVs support very little in terms of letter boxing. My current one (which is cheap) supports centered pixel-for-pixel, or stretched... that's it. There are no boxing modes.

[edit] Woah, that's creepy. Someone must have hit send to top, but because my post was last yesterday, it says "Last post was by Chris Katko ~40 minutes ago."

Elias

Here's an example using the transform API. For pixel art you may want to only use integer scaling and then possibly use 4 black bars instead of just two.

#SelectExpand
1#include <allegro5/allegro.h> 2#include <allegro5/allegro_primitives.h> 3#include <allegro5/allegro_color.h> 4#include <math.h> 5 6void redraw() { 7 al_clear_to_color(al_color_name("black")); 8 9 // actual fullscreen dimensions 10 auto w = al_get_display_width(al_get_current_display()); 11 auto h = al_get_display_height(al_get_current_display()); 12 13 // dimensions we use for the game 14 auto want_w = 640; 15 auto want_h = 480; 16 17 // scale as big as possible and center 18 auto scale = (double)w / want_w; 19 auto scale_y = (double)h / want_h; 20 if (scale_y < scale) 21 scale = scale_y; 22 auto offset_x = (w - want_w * scale) / 2; 23 auto offset_y = (h - want_h * scale) / 2; 24 ALLEGRO_TRANSFORM transform; 25 al_build_transform(&transform, offset_x, offset_y, scale, scale, 0); 26 al_use_transform(&transform); 27 28 al_set_clipping_rectangle(offset_x, offset_y, want_w * scale, 29 want_h * scale); 30 31 // We can now draw like normal, but 0/0 is the upper left corner 32 // of our virtual boxed screen and want_w/want_h the lower right 33 // corner. 34 al_draw_filled_rectangle(0, 0, want_w, want_h, 35 al_color_name("indigo")); 36 for (int i = 0; i < 100; i++) { 37 int x = (al_get_time() + i) * 120; 38 int y = sin(al_get_time() * 5 + i) * 30 + want_h * i / 100; 39 al_draw_filled_circle(x % (want_w + 20) - 10, y, 40 10, al_color_name("pink")); 41 } 42 43 al_flip_display(); 44} 45int main() { 46 al_init(); 47 al_init_primitives_addon(); 48 al_install_keyboard(); 49 al_set_new_display_flags(ALLEGRO_FULLSCREEN_WINDOW); 50 auto display = al_create_display(1, 1); 51 auto queue = al_create_event_queue(); 52 auto timer = al_create_timer(1 / 60.0); 53 al_register_event_source(queue, al_get_keyboard_event_source()); 54 al_register_event_source(queue, al_get_display_event_source(display)); 55 al_register_event_source(queue, al_get_timer_event_source(timer)); 56 al_start_timer(timer); 57 auto quit = false; 58 while (!quit) { 59 redraw(); 60 auto wait = true; 61 while (wait) { 62 ALLEGRO_EVENT event; 63 al_wait_for_event(queue, &event); 64 if (event.type == ALLEGRO_EVENT_KEY_DOWN) { 65 if (event.keyboard.keycode == ALLEGRO_KEY_ESCAPE) 66 quit = true; 67 } 68 if (event.type == ALLEGRO_EVENT_TIMER) { 69 wait = false; 70 } 71 } 72 } 73}

anto80

Thanks very much to all of you.

And very good point Elias about the integer scaling when doing pixel art. :)

Thread #615786. Printed from Allegro.cc