feat: add borderless fullscreen option
This commit is contained in:
@@ -11,10 +11,16 @@ extern "C" {
|
|||||||
#define SKELE_VIDEO_BORDERLESS 0x02
|
#define SKELE_VIDEO_BORDERLESS 0x02
|
||||||
#define SKELE_VIDEO_RESIZABLE 0x04
|
#define SKELE_VIDEO_RESIZABLE 0x04
|
||||||
#define SKELE_VIDEO_HIGHDPI 0x08
|
#define SKELE_VIDEO_HIGHDPI 0x08
|
||||||
|
#define SKELE_VIDEO_FULLSCREEN_EXCLUSIVE 0x10
|
||||||
|
|
||||||
#define SKELE_DEFAULT_RENDER_WIDTH 320
|
#define SKELE_DEFAULT_RENDER_WIDTH 320
|
||||||
#define SKELE_DEFAULT_RENDER_HEIGHT 200
|
#define SKELE_DEFAULT_RENDER_HEIGHT 200
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SKELE_FULLSCREEN_BORDERLESS,
|
||||||
|
SKELE_FULLSCREEN_EXCLUSIVE
|
||||||
|
} skele_fullscreen_kind_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t render_width;
|
uint16_t render_width;
|
||||||
uint16_t render_height;
|
uint16_t render_height;
|
||||||
@@ -28,6 +34,7 @@ void skele_video_shutdown(void);
|
|||||||
void skele_video_present(void);
|
void skele_video_present(void);
|
||||||
void skele_video_set_title(const char *title);
|
void skele_video_set_title(const char *title);
|
||||||
void skele_video_toggle_fullscreen(void);
|
void skele_video_toggle_fullscreen(void);
|
||||||
|
void skele_video_set_fullscreen_kind(skele_fullscreen_kind_t kind);
|
||||||
void skele_video_cycle_scale(void);
|
void skele_video_cycle_scale(void);
|
||||||
void skele_video_set_mouse_grab(uint8_t grab);
|
void skele_video_set_mouse_grab(uint8_t grab);
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ static SDL_GLContext gl_ctx = NULL;
|
|||||||
static uint16_t vid_w = 0;
|
static uint16_t vid_w = 0;
|
||||||
static uint16_t vid_h = 0;
|
static uint16_t vid_h = 0;
|
||||||
static uint8_t cur_scale = 1;
|
static uint8_t cur_scale = 1;
|
||||||
static uint8_t fullscreen = 0;
|
static uint8_t is_fullscreen = 0;
|
||||||
|
static skele_fullscreen_kind_t last_fullscreen_kind =
|
||||||
|
SKELE_FULLSCREEN_EXCLUSIVE;
|
||||||
|
|
||||||
static uint8_t max_scale(uint16_t rw, uint16_t rh)
|
static uint8_t max_scale(uint16_t rw, uint16_t rh)
|
||||||
{
|
{
|
||||||
@@ -42,16 +44,23 @@ static void set_scale(uint8_t scale)
|
|||||||
SDL_WINDOWPOS_CENTERED_DISPLAY(display));
|
SDL_WINDOWPOS_CENTERED_DISPLAY(display));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void toggle_fullscreen(void)
|
static void apply_fullscreen_kind(skele_fullscreen_kind_t kind)
|
||||||
{
|
{
|
||||||
fullscreen = !fullscreen;
|
if (kind == SKELE_FULLSCREEN_EXCLUSIVE) {
|
||||||
SDL_SetWindowFullscreen(window, fullscreen);
|
SDL_DisplayID display;
|
||||||
|
const SDL_DisplayMode *mode;
|
||||||
|
display = SDL_GetDisplayForWindow(window);
|
||||||
|
mode = SDL_GetCurrentDisplayMode(display);
|
||||||
|
SDL_SetWindowFullscreenMode(window, mode);
|
||||||
|
} else {
|
||||||
|
SDL_SetWindowFullscreenMode(window, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cycle_scale(void)
|
static void cycle_scale(void)
|
||||||
{
|
{
|
||||||
uint8_t next;
|
uint8_t next;
|
||||||
if (fullscreen)
|
if (is_fullscreen)
|
||||||
return;
|
return;
|
||||||
next = cur_scale + 1;
|
next = cur_scale + 1;
|
||||||
if (next > max_scale(vid_w, vid_h))
|
if (next > max_scale(vid_w, vid_h))
|
||||||
@@ -88,6 +97,11 @@ uint8_t skele_video_init(skele_video_config_t cfg)
|
|||||||
if (cfg.flags & SKELE_VIDEO_HIGHDPI)
|
if (cfg.flags & SKELE_VIDEO_HIGHDPI)
|
||||||
flags |= SDL_WINDOW_HIGH_PIXEL_DENSITY;
|
flags |= SDL_WINDOW_HIGH_PIXEL_DENSITY;
|
||||||
|
|
||||||
|
if (cfg.flags & SKELE_VIDEO_FULLSCREEN_EXCLUSIVE)
|
||||||
|
last_fullscreen_kind = SKELE_FULLSCREEN_EXCLUSIVE;
|
||||||
|
else
|
||||||
|
last_fullscreen_kind = SKELE_FULLSCREEN_BORDERLESS;
|
||||||
|
|
||||||
display = SDL_GetPrimaryDisplay();
|
display = SDL_GetPrimaryDisplay();
|
||||||
vid_w =
|
vid_w =
|
||||||
cfg.render_width ? cfg.render_width : SKELE_DEFAULT_RENDER_WIDTH;
|
cfg.render_width ? cfg.render_width : SKELE_DEFAULT_RENDER_WIDTH;
|
||||||
@@ -131,8 +145,10 @@ uint8_t skele_video_init(skele_video_config_t cfg)
|
|||||||
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED_DISPLAY(display),
|
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED_DISPLAY(display),
|
||||||
SDL_WINDOWPOS_CENTERED_DISPLAY(display));
|
SDL_WINDOWPOS_CENTERED_DISPLAY(display));
|
||||||
|
|
||||||
if (cfg.flags & SKELE_VIDEO_FULLSCREEN)
|
if (cfg.flags & SKELE_VIDEO_FULLSCREEN) {
|
||||||
fullscreen = 1;
|
apply_fullscreen_kind(last_fullscreen_kind);
|
||||||
|
is_fullscreen = 1;
|
||||||
|
}
|
||||||
|
|
||||||
gl_ctx = SDL_GL_CreateContext(window);
|
gl_ctx = SDL_GL_CreateContext(window);
|
||||||
if (!gl_ctx) {
|
if (!gl_ctx) {
|
||||||
@@ -160,13 +176,31 @@ void skele_video_shutdown(void)
|
|||||||
vid_w = 0;
|
vid_w = 0;
|
||||||
vid_h = 0;
|
vid_h = 0;
|
||||||
cur_scale = 1;
|
cur_scale = 1;
|
||||||
fullscreen = 0;
|
is_fullscreen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void skele_video_present(void) { SDL_GL_SwapWindow(window); }
|
void skele_video_present(void) { SDL_GL_SwapWindow(window); }
|
||||||
void skele_video_toggle_fullscreen(void) { toggle_fullscreen(); }
|
|
||||||
void skele_video_cycle_scale(void) { cycle_scale(); }
|
void skele_video_cycle_scale(void) { cycle_scale(); }
|
||||||
|
|
||||||
|
void skele_video_toggle_fullscreen(void)
|
||||||
|
{
|
||||||
|
if (is_fullscreen) {
|
||||||
|
SDL_SetWindowFullscreen(window, false);
|
||||||
|
is_fullscreen = 0;
|
||||||
|
} else {
|
||||||
|
apply_fullscreen_kind(last_fullscreen_kind);
|
||||||
|
SDL_SetWindowFullscreen(window, true);
|
||||||
|
is_fullscreen = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void skele_video_set_fullscreen_kind(skele_fullscreen_kind_t kind)
|
||||||
|
{
|
||||||
|
last_fullscreen_kind = kind;
|
||||||
|
if (is_fullscreen)
|
||||||
|
apply_fullscreen_kind(kind);
|
||||||
|
}
|
||||||
|
|
||||||
void skele_video_set_mouse_grab(uint8_t grab)
|
void skele_video_set_mouse_grab(uint8_t grab)
|
||||||
{
|
{
|
||||||
SDL_SetWindowMouseGrab(window, grab ? true : false);
|
SDL_SetWindowMouseGrab(window, grab ? true : false);
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ static uint16_t vid_w = 0;
|
|||||||
static uint16_t vid_h = 0;
|
static uint16_t vid_h = 0;
|
||||||
static uint32_t vid_total = 0;
|
static uint32_t vid_total = 0;
|
||||||
static uint8_t cur_scale = 1;
|
static uint8_t cur_scale = 1;
|
||||||
static uint8_t fullscreen = 0;
|
static uint8_t is_fullscreen = 0;
|
||||||
|
static skele_fullscreen_kind_t last_fullscreen_kind =
|
||||||
|
SKELE_FULLSCREEN_EXCLUSIVE;
|
||||||
|
|
||||||
static uint8_t max_scale(uint16_t rw, uint16_t rh)
|
static uint8_t max_scale(uint16_t rw, uint16_t rh)
|
||||||
{
|
{
|
||||||
@@ -51,16 +53,23 @@ static void set_scale(uint8_t scale)
|
|||||||
SDL_WINDOWPOS_CENTERED_DISPLAY(display));
|
SDL_WINDOWPOS_CENTERED_DISPLAY(display));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void toggle_fullscreen(void)
|
static void apply_fullscreen_kind(skele_fullscreen_kind_t kind)
|
||||||
{
|
{
|
||||||
fullscreen = !fullscreen;
|
if (kind == SKELE_FULLSCREEN_EXCLUSIVE) {
|
||||||
SDL_SetWindowFullscreen(window, fullscreen);
|
SDL_DisplayID display;
|
||||||
|
const SDL_DisplayMode *mode;
|
||||||
|
display = SDL_GetDisplayForWindow(window);
|
||||||
|
mode = SDL_GetCurrentDisplayMode(display);
|
||||||
|
SDL_SetWindowFullscreenMode(window, mode);
|
||||||
|
} else {
|
||||||
|
SDL_SetWindowFullscreenMode(window, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cycle_scale(void)
|
static void cycle_scale(void)
|
||||||
{
|
{
|
||||||
uint8_t next;
|
uint8_t next;
|
||||||
if (fullscreen)
|
if (is_fullscreen)
|
||||||
return;
|
return;
|
||||||
next = cur_scale + 1;
|
next = cur_scale + 1;
|
||||||
if (next > max_scale(vid_w, vid_h))
|
if (next > max_scale(vid_w, vid_h))
|
||||||
@@ -74,7 +83,6 @@ uint8_t skele_video_init(skele_video_config_t cfg)
|
|||||||
SDL_WindowFlags flags = 0;
|
SDL_WindowFlags flags = 0;
|
||||||
const SDL_DisplayMode *mode;
|
const SDL_DisplayMode *mode;
|
||||||
uint16_t window_w, window_h, aw, ah;
|
uint16_t window_w, window_h, aw, ah;
|
||||||
uint16_t i;
|
|
||||||
|
|
||||||
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) {
|
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) {
|
||||||
stk_log(STK_LOG_ERROR, "video: SDL_Init failed: %s",
|
stk_log(STK_LOG_ERROR, "video: SDL_Init failed: %s",
|
||||||
@@ -91,6 +99,11 @@ uint8_t skele_video_init(skele_video_config_t cfg)
|
|||||||
if (cfg.flags & SKELE_VIDEO_HIGHDPI)
|
if (cfg.flags & SKELE_VIDEO_HIGHDPI)
|
||||||
flags |= SDL_WINDOW_HIGH_PIXEL_DENSITY;
|
flags |= SDL_WINDOW_HIGH_PIXEL_DENSITY;
|
||||||
|
|
||||||
|
if (cfg.flags & SKELE_VIDEO_FULLSCREEN_EXCLUSIVE)
|
||||||
|
last_fullscreen_kind = SKELE_FULLSCREEN_EXCLUSIVE;
|
||||||
|
else
|
||||||
|
last_fullscreen_kind = SKELE_FULLSCREEN_BORDERLESS;
|
||||||
|
|
||||||
display = SDL_GetPrimaryDisplay();
|
display = SDL_GetPrimaryDisplay();
|
||||||
vid_w =
|
vid_w =
|
||||||
cfg.render_width ? cfg.render_width : SKELE_DEFAULT_RENDER_WIDTH;
|
cfg.render_width ? cfg.render_width : SKELE_DEFAULT_RENDER_WIDTH;
|
||||||
@@ -123,11 +136,6 @@ uint8_t skele_video_init(skele_video_config_t cfg)
|
|||||||
window_h = vid_h * cur_scale;
|
window_h = vid_h * cur_scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* default palette: all black */
|
|
||||||
memset(palette, 0, sizeof(palette));
|
|
||||||
for (i = 0; i < SKELE_PALETTE_COLORS; i++)
|
|
||||||
palette[i] = 0xFF000000;
|
|
||||||
|
|
||||||
rgba_buf = malloc(vid_total * sizeof(uint32_t));
|
rgba_buf = malloc(vid_total * sizeof(uint32_t));
|
||||||
if (!rgba_buf) {
|
if (!rgba_buf) {
|
||||||
stk_log(STK_LOG_ERROR, "video: out of memory");
|
stk_log(STK_LOG_ERROR, "video: out of memory");
|
||||||
@@ -150,8 +158,10 @@ uint8_t skele_video_init(skele_video_config_t cfg)
|
|||||||
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED_DISPLAY(display),
|
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED_DISPLAY(display),
|
||||||
SDL_WINDOWPOS_CENTERED_DISPLAY(display));
|
SDL_WINDOWPOS_CENTERED_DISPLAY(display));
|
||||||
|
|
||||||
if (cfg.flags & SKELE_VIDEO_FULLSCREEN)
|
if (cfg.flags & SKELE_VIDEO_FULLSCREEN) {
|
||||||
fullscreen = 1;
|
apply_fullscreen_kind(last_fullscreen_kind);
|
||||||
|
is_fullscreen = 1;
|
||||||
|
}
|
||||||
|
|
||||||
renderer = SDL_CreateRenderer(window, NULL);
|
renderer = SDL_CreateRenderer(window, NULL);
|
||||||
if (!renderer) {
|
if (!renderer) {
|
||||||
@@ -179,6 +189,7 @@ uint8_t skele_video_init(skele_video_config_t cfg)
|
|||||||
|
|
||||||
SDL_SetTextureScaleMode(texture, SDL_SCALEMODE_NEAREST);
|
SDL_SetTextureScaleMode(texture, SDL_SCALEMODE_NEAREST);
|
||||||
SDL_SetRenderVSync(renderer, 1);
|
SDL_SetRenderVSync(renderer, 1);
|
||||||
|
memset(palette, 0, sizeof(palette));
|
||||||
SDL_ShowWindow(window);
|
SDL_ShowWindow(window);
|
||||||
return SKELE_INIT_SUCCESS;
|
return SKELE_INIT_SUCCESS;
|
||||||
}
|
}
|
||||||
@@ -206,13 +217,41 @@ void skele_video_shutdown(void)
|
|||||||
vid_h = 0;
|
vid_h = 0;
|
||||||
vid_total = 0;
|
vid_total = 0;
|
||||||
cur_scale = 1;
|
cur_scale = 1;
|
||||||
fullscreen = 0;
|
is_fullscreen = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void skele_video_blit(uint8_t *pixels)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
for (i = 0; i < vid_total; i++)
|
||||||
|
rgba_buf[i] = palette[pixels[i]];
|
||||||
|
SDL_UpdateTexture(texture, NULL, rgba_buf,
|
||||||
|
vid_w * (int)sizeof(uint32_t));
|
||||||
|
SDL_RenderTexture(renderer, texture, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void skele_video_present(void) { SDL_RenderPresent(renderer); }
|
void skele_video_present(void) { SDL_RenderPresent(renderer); }
|
||||||
void skele_video_toggle_fullscreen(void) { toggle_fullscreen(); }
|
|
||||||
void skele_video_cycle_scale(void) { cycle_scale(); }
|
void skele_video_cycle_scale(void) { cycle_scale(); }
|
||||||
|
|
||||||
|
void skele_video_toggle_fullscreen(void)
|
||||||
|
{
|
||||||
|
if (is_fullscreen) {
|
||||||
|
SDL_SetWindowFullscreen(window, false);
|
||||||
|
is_fullscreen = 0;
|
||||||
|
} else {
|
||||||
|
apply_fullscreen_kind(last_fullscreen_kind);
|
||||||
|
SDL_SetWindowFullscreen(window, true);
|
||||||
|
is_fullscreen = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void skele_video_set_fullscreen_kind(skele_fullscreen_kind_t kind)
|
||||||
|
{
|
||||||
|
last_fullscreen_kind = kind;
|
||||||
|
if (is_fullscreen)
|
||||||
|
apply_fullscreen_kind(kind);
|
||||||
|
}
|
||||||
|
|
||||||
void skele_video_set_mouse_grab(uint8_t grab)
|
void skele_video_set_mouse_grab(uint8_t grab)
|
||||||
{
|
{
|
||||||
SDL_SetWindowMouseGrab(window, grab ? true : false);
|
SDL_SetWindowMouseGrab(window, grab ? true : false);
|
||||||
@@ -235,13 +274,3 @@ void skele_palette_set_index(uint8_t index, uint32_t color)
|
|||||||
{
|
{
|
||||||
palette[index] = color | 0xFF000000;
|
palette[index] = color | 0xFF000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
void skele_video_blit(uint8_t *pixels)
|
|
||||||
{
|
|
||||||
uint32_t i;
|
|
||||||
for (i = 0; i < vid_total; i++)
|
|
||||||
rgba_buf[i] = palette[pixels[i]];
|
|
||||||
SDL_UpdateTexture(texture, NULL, rgba_buf,
|
|
||||||
vid_w * (int)sizeof(uint32_t));
|
|
||||||
SDL_RenderTexture(renderer, texture, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user