[AD] set_display_mode and screen update handling |
[ Thread Index |
Date Index
| More lists.liballeg.org/allegro-developers Archives
]
As I mentioned before I had a couple functions lying around that would
handle setting a video mode with a screen update method and an
acompanying screen update function. I attached a C source file that has
these functions.
- Kitty Cat
/* The bitmaps we'll be drawing to */
static BITMAP *page[3];
static int current_page;
#define DOUBLE_BUFFER 0x00000001
#define PAGE_FLIP 0x00000002
#define TRIPLE_BUFFER 0x00000004
#define WINDOWED 0x00000008
#define FULLSCREEN 0x00000010
/* Sets the requested mode, returning the bitmap you should start drawing on.
* Pass 0 for all four arguments to properly shutdown the gfx mode.
*/
BITMAP *set_display_mode(int w, int h, int bpp, int flags)
{
int driver = GFX_AUTODETECT;
int vw = 0;
int vh = 0;
if(page[2])
destroy_bitmap(page[2]);
page[2] = NULL;
if(page[1])
destroy_bitmap(page[1]);
page[1] = NULL;
if(page[0])
destroy_bitmap(page[0]);
page[0] = NULL;
if(!w && !h && !bpp && !flags)
{
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
return NULL;
}
/* Only platforms that have single-surface VRAM needs to have
* virtual screen adjustment */
#ifdef ALLEGRO_VRAM_IS_SINGLE_SURFACE
if((flags & TRIPLE_BUFFER))
{
vw = w;
vh = h * 3;
}
else if((flags & PAGE_FLIP))
{
vw = w;
vh = h * 2;
}
#endif
do {
/* Windowed or fullscreen requested? */
if((flags & FULLSCREEN))
{
flags &= ~FULLSCREEN;
driver = GFX_AUTODETECT_FULLSCREEN;
}
else if((flags & WINDOWED))
{
flags &= ~WINDOWED;
driver = GFX_AUTODETECT_WINDOWED;
}
/* Finally, set the mode and first vram page */
set_color_depth(bpp);
if(set_gfx_mode(driver, w, h, vw, vh) != 0)
return NULL;
} while((flags & (FULLSCREEN|WINDOWED)));
page[0] = create_video_bitmap(SCREEN_W, SCREEN_H);
if(!page[0])
{
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
return NULL;
}
/* If no buffering mode is specified, return the screen */
if(!(flags&(DOUBLE_BUFFER|PAGE_FLIP|TRIPLE_BUFFER)))
return page[0];
/* Make sure we can do what's been requested */
if((flags&TRIPLE_BUFFER) && (gfx_capabilities&GFX_CAN_TRIPLE_BUFFER))
{
page[1] = create_video_bitmap(SCREEN_W, SCREEN_H);
page[2] = create_video_bitmap(SCREEN_W, SCREEN_H);
if(page[1] && page[2])
goto done;
}
if((flags&PAGE_FLIP) && (gfx_capabilities&GFX_CAN_SCROLL))
{
if(!page[1])
page[1] = create_video_bitmap(SCREEN_W, SCREEN_H);
if(page[1])
goto done;
}
if(page[1])
destroy_bitmap(page[1]);
page[1] = NULL;
if((flags&DOUBLE_BUFFER))
page[1] = create_bitmap(SCREEN_W, SCREEN_H);
if(!page[1])
{
destroy_bitmap(page[0]);
set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
return NULL;
}
done:
current_page = 1;
return page[current_page];
}
/* Displays what was drawn to the page last returned by this function. If
* vs is true, vsync() will be called before blitting in double buffer
* mode. Returns the next bitmap you should start drawing on.
*/
BITMAP *show_page(int vs)
{
if(page[2])
{
while(poll_scroll())
;
request_video_bitmap(page[current_page]);
current_page = (current_page+1) % 3;
}
else if(is_video_bitmap(page[1]))
{
show_video_bitmap(page[current_page]);
current_page ^= 1;
}
else
{
if(vs) vsync();
blit(page[1], page[0], 0, 0, 0, 0, page[1]->w, page[1]->h);
}
return page[current_page];
}
/* Returns the current screen bitmap buffer. This is not gauranteed to remain
* constant across show_page() calls. */
BITMAP *get_screen(void)
{
if(page[2])
return page[(current_page+2) % 3];
if(!page[1])
return page[0];
if(is_video_bitmap(page[1]))
return page[current_page^1];
return page[1];
}