rts/src/gfx/sdl-1.2/src/env.c

196 lines
3.7 KiB
C

#include <gfx.h>
#include <gfx_private.h>
#include <sdl-1.2/gfx_private.h>
#include <SDL.h>
#include <inttypes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
int screen_w = SCREEN_W, screen_h = SCREEN_H;
static bool fullscreen;
static SDL_Surface *screen;
static struct sprite **list;
static size_t list_len;
void gfx_deinit(void)
{
/* screen should be already freed by SDL_Quit. */
free(list);
SDL_QuitSubSystem(SDL_INIT_VIDEO);
}
static struct
{
int w, h;
} display, windowed;
void gfx_register_sprite(struct sprite *const s)
{
list = realloc(list, (list_len + 1) * sizeof *list);
if (list)
list[list_len++] = s;
}
static int resize_screen(int w, int h, const bool full_screen)
{
Uint32 flags = SDL_HWSURFACE | SDL_RESIZABLE | SDL_ANYFORMAT | SDL_DOUBLEBUF;
const SDL_VideoInfo *const info = SDL_GetVideoInfo();
if (!info)
{
fprintf(stderr, "SDL_GetVideoInfo: %s\n", SDL_GetError());
return -1;
}
static bool init;
if (!init)
{
display.w = info->current_w;
display.h = info->current_h;
init = true;
}
if (fullscreen)
{
flags |= SDL_FULLSCREEN;
w = display.w;
h = display.h;
}
else
{
windowed.w = w;
windowed.h = h;
}
int bpp = info->vfmt->BitsPerPixel;
if (screen)
SDL_FreeSurface(screen);
const int max_bpp = SDL_VideoModeOK(w, h, 0, flags);
if (max_bpp < 0)
{
fprintf(stderr, "SDL_VideoModeOK: %s\n", SDL_GetError());
return -1;
}
else if (bpp > max_bpp)
bpp = max_bpp;
if (!(screen = SDL_SetVideoMode(w, h, 0, flags)))
{
fprintf(stderr, "SDL_SetVideoMode: %s\n", SDL_GetError());
return -1;
}
for (size_t i = 0; i < list_len; i++)
if (sprite_screen_resize_ev(list[i]))
return -1;
screen_w = w;
screen_h = h;
fullscreen = full_screen;
return 0;
}
SDL_Surface *gfx_screen(void)
{
return screen;
}
int gfx_init(void)
{
if (SDL_InitSubSystem(SDL_INIT_VIDEO))
{
fprintf(stderr, "%s: SDL_InitSubSystem: %s\n",
__func__, SDL_GetError());
return -1;
}
return resize_screen(screen_w, screen_h, fullscreen);
}
bool gfx_inside_drawenv(const short x, const short y, const short w,
const short h)
{
return (x + w >= 0)
&& x < screen_w
&& (y + h >= 0)
&& y < screen_h;
}
static int get_resize_events(void)
{
int n;
SDL_Event ev;
while ((n = SDL_PeepEvents(&ev, 1, SDL_GETEVENT,
SDL_VIDEORESIZEMASK)) > 0)
{
if (ev.type == SDL_VIDEORESIZE)
{
const SDL_ResizeEvent *const res = &ev.resize;
if (resize_screen(res->w, res->h, false))
return -1;
}
}
if (n < 0)
{
fprintf(stderr, "%s: SDL_PeepEvents: %s\n",
__func__, SDL_GetError());
return -1;
}
return 0;
}
int gfx_toggle_fullscreen(void)
{
fullscreen ^= true;
const int w = fullscreen ? display.w : windowed.w;
const int h = fullscreen ? display.h : windowed.h;
if ((resize_screen(w, h, fullscreen)))
return -1;
return 0;
}
bool gfx_toggle_fullscreen_available(void)
{
return true;
}
bool gfx_fullscreen(void)
{
return fullscreen;
}
int gfx_draw(void)
{
enum {FPS = 50, REFRESH_MS = 1000 / FPS};
static Uint32 prev;
const Uint32 cur = SDL_GetTicks();
if (cur - prev < REFRESH_MS)
SDL_Delay(REFRESH_MS - (cur - prev));
prev = SDL_GetTicks();
if (SDL_Flip(screen))
{
fprintf(stderr, "SDL_Flip: %s\n", SDL_GetError());
return -1;
}
get_resize_events();
return 0;
}