Video resolution improvements/high-DPI quirks (#204)
This commit is contained in:
parent
a54d1dcf32
commit
77246397c3
5 changed files with 102 additions and 41 deletions
|
@ -26,6 +26,8 @@
|
|||
<string>bundle</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.arcade-games</string>
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<string>YES</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>© 2011-2019, Taisei Project</string>
|
||||
</dict>
|
||||
|
|
|
@ -197,14 +197,15 @@ static OptionBinding* bind_stroption(ConfigIndex cfgentry) {
|
|||
|
||||
// BT_Resolution: super-special binding type for the resolution setting
|
||||
static void bind_resolution_update(OptionBinding *bind) {
|
||||
uint nmodes = video_get_num_modes();
|
||||
bool fullscreen = config_get_int(CONFIG_FULLSCREEN);
|
||||
uint nmodes = video_get_num_modes(fullscreen);
|
||||
VideoMode cur = video_get_current_mode();
|
||||
|
||||
bind->valrange_min = 0;
|
||||
bind->valrange_max = nmodes - 1;
|
||||
|
||||
for(int i = 0; i < nmodes; ++i) {
|
||||
VideoMode m = video_get_mode(i);
|
||||
VideoMode m = video_get_mode(i, fullscreen);
|
||||
if(m.width == cur.width && m.height == cur.height) {
|
||||
bind->selected = i;
|
||||
}
|
||||
|
@ -394,8 +395,9 @@ static bool bind_fullscreen_dependence(void) {
|
|||
}
|
||||
|
||||
static int bind_resolution_set(OptionBinding *b, int v) {
|
||||
bool fullscreen = config_get_int(CONFIG_FULLSCREEN);
|
||||
if(v >= 0) {
|
||||
VideoMode m = video_get_mode(v);
|
||||
VideoMode m = video_get_mode(v, fullscreen);
|
||||
config_set_int(CONFIG_VID_WIDTH, m.width);
|
||||
config_set_int(CONFIG_VID_HEIGHT, m.height);
|
||||
}
|
||||
|
@ -430,7 +432,8 @@ static void destroy_options_menu(MenuData *m) {
|
|||
|
||||
if(bind->type == BT_Resolution && video_query_capability(VIDEO_CAP_CHANGE_RESOLUTION) == VIDEO_AVAILABLE) {
|
||||
if(bind->selected != -1) {
|
||||
VideoMode mode = video_get_mode(bind->selected);
|
||||
bool fullscreen = config_get_int(CONFIG_FULLSCREEN);
|
||||
VideoMode mode = video_get_mode(bind->selected, fullscreen);
|
||||
config_set_int(CONFIG_VID_WIDTH, mode.width);
|
||||
config_set_int(CONFIG_VID_HEIGHT, mode.height);
|
||||
change_vidmode = true;
|
||||
|
@ -1188,7 +1191,8 @@ static void draw_options_menu(MenuData *menu) {
|
|||
if(bind->selected == -1) {
|
||||
m = video_get_current_mode();
|
||||
} else {
|
||||
m = video_get_mode(bind->selected);
|
||||
bool fullscreen = config_get_int(CONFIG_FULLSCREEN);
|
||||
m = video_get_mode(bind->selected, fullscreen);
|
||||
}
|
||||
|
||||
w = m.width;
|
||||
|
|
|
@ -1087,13 +1087,11 @@ static void gl33_swap(SDL_Window *window) {
|
|||
|
||||
gl33_stats_post_frame();
|
||||
|
||||
if(glext.version.is_webgl) {
|
||||
// We can't rely on viewport being preserved across frames,
|
||||
// so force the next frame to set one on the first draw call.
|
||||
// The viewport might get updated externally when e.g. going
|
||||
// fullscreen, and we can't catch that in the resize event.
|
||||
memset(&R.viewport.active, 0, sizeof(R.viewport.active));
|
||||
}
|
||||
// We can't rely on viewport being preserved across frames,
|
||||
// so force the next frame to set one on the first draw call.
|
||||
// The viewport might get updated externally when e.g. going
|
||||
// fullscreen, and we can't catch that in the resize event.
|
||||
memset(&R.viewport.active, 0, sizeof(R.viewport.active));
|
||||
}
|
||||
|
||||
static void gl33_blend(BlendMode mode) {
|
||||
|
|
111
src/video.c
111
src/video.c
|
@ -18,10 +18,15 @@
|
|||
#include "taskmanager.h"
|
||||
#include "video_postprocess.h"
|
||||
|
||||
static struct {
|
||||
VideoMode *modes;
|
||||
SDL_Window *window;
|
||||
typedef struct VideoModeArray {
|
||||
VideoMode *mode;
|
||||
uint mcount;
|
||||
} VideoModeArray;
|
||||
|
||||
static struct {
|
||||
VideoModeArray fs_modes;
|
||||
VideoModeArray win_modes;
|
||||
SDL_Window *window;
|
||||
VideoMode intended;
|
||||
VideoMode current;
|
||||
VideoBackend backend;
|
||||
|
@ -90,10 +95,10 @@ static VideoCapabilityState video_query_capability_webcanvas(VideoCapability cap
|
|||
}
|
||||
}
|
||||
|
||||
static void video_add_mode(int width, int height) {
|
||||
if(video.modes) {
|
||||
for(uint i = 0; i < video.mcount; ++i) {
|
||||
VideoMode *m = video.modes + i;
|
||||
static void video_add_mode_handler(VideoModeArray *mode_array, int width, int height) {
|
||||
if(mode_array->mode) {
|
||||
for(uint i = 0; i < mode_array->mcount; ++i) {
|
||||
VideoMode *m = mode_array->mode + i;
|
||||
|
||||
if(m->width == width && m->height == height) {
|
||||
return;
|
||||
|
@ -101,9 +106,18 @@ static void video_add_mode(int width, int height) {
|
|||
}
|
||||
}
|
||||
|
||||
video.modes = (VideoMode*)realloc(video.modes, (++video.mcount) * sizeof(VideoMode));
|
||||
video.modes[video.mcount-1].width = width;
|
||||
video.modes[video.mcount-1].height = height;
|
||||
mode_array->mode = realloc(mode_array->mode, (++mode_array->mcount) * sizeof(VideoMode));
|
||||
|
||||
mode_array->mode[mode_array->mcount-1].width = width;
|
||||
mode_array->mode[mode_array->mcount-1].height = height;
|
||||
}
|
||||
|
||||
static void video_add_mode_fullscreen(int width, int height) {
|
||||
video_add_mode_handler(&video.fs_modes, width, height);
|
||||
}
|
||||
|
||||
static void video_add_mode_windowed(int width, int height) {
|
||||
video_add_mode_handler(&video.win_modes, width, height);
|
||||
}
|
||||
|
||||
static int video_compare_modes(const void *a, const void *b) {
|
||||
|
@ -112,9 +126,15 @@ static int video_compare_modes(const void *a, const void *b) {
|
|||
return va->width * va->height - vb->width * vb->height;
|
||||
}
|
||||
|
||||
void video_get_viewport_size(float *width, float *height) {
|
||||
float w = video.current.width;
|
||||
float h = video.current.height;
|
||||
static FloatExtent video_get_screen_framebuffer_size(void) {
|
||||
int fb_w, fb_h;
|
||||
SDL_GL_GetDrawableSize(video.window, &fb_w, &fb_h);
|
||||
return (FloatExtent) { fb_w, fb_h };
|
||||
}
|
||||
|
||||
static FloatExtent video_get_viewport_size_for_framebuffer(FloatExtent framebuffer_size) {
|
||||
float w = framebuffer_size.w;
|
||||
float h = framebuffer_size.h;
|
||||
float r = w / h;
|
||||
|
||||
if(r > VIDEO_ASPECT_RATIO) {
|
||||
|
@ -123,14 +143,30 @@ void video_get_viewport_size(float *width, float *height) {
|
|||
h = w / VIDEO_ASPECT_RATIO;
|
||||
}
|
||||
|
||||
*width = w;
|
||||
*height = h;
|
||||
return (FloatExtent) { w, h };
|
||||
}
|
||||
|
||||
void video_get_viewport_size(float *width, float *height) {
|
||||
FloatExtent fb = video_get_screen_framebuffer_size();
|
||||
FloatExtent vp = video_get_viewport_size_for_framebuffer(fb);
|
||||
|
||||
*width = vp.w;
|
||||
*height = vp.h;
|
||||
}
|
||||
|
||||
void video_get_viewport(FloatRect *vp) {
|
||||
video_get_viewport_size(&vp->w, &vp->h);
|
||||
vp->x = (int)((video.current.width - vp->w) / 2);
|
||||
vp->y = (int)((video.current.height - vp->h) / 2);
|
||||
FloatExtent fb = video_get_screen_framebuffer_size();
|
||||
|
||||
// vp->extent aliases vp->w and vp->y; see util/geometry.h
|
||||
vp->extent = video_get_viewport_size_for_framebuffer(fb);
|
||||
|
||||
vp->x = (int)((fb.w - vp->w) * 0.5);
|
||||
vp->y = (int)((fb.h - vp->h) * 0.5);
|
||||
|
||||
// This function can also be changed to return a FloatRect instead
|
||||
log_debug("current w/h: %dx%d", video.current.width, video.current.height);
|
||||
log_debug("viewport x/y: %fx%f", vp->x, vp->y);
|
||||
log_debug("viewport w/h: %fx%f", vp->w, vp->h);
|
||||
}
|
||||
|
||||
static void video_set_viewport(void) {
|
||||
|
@ -321,6 +357,13 @@ void video_set_mode(uint display, uint w, uint h, bool fs, bool resizable) {
|
|||
return;
|
||||
} else {
|
||||
SDL_SetWindowSize(video.window, w, h);
|
||||
// so the user doesn't have to drag the window back
|
||||
// into the middle of the screen after a resolution change
|
||||
SDL_SetWindowPosition(
|
||||
video.window,
|
||||
SDL_WINDOWPOS_CENTERED_DISPLAY(display),
|
||||
SDL_WINDOWPOS_CENTERED_DISPLAY(display)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -683,7 +726,7 @@ void video_init(void) {
|
|||
if(SDL_GetDisplayMode(s, i, &mode) != 0) {
|
||||
log_sdl_error(LOG_WARN, "SDL_GetDisplayMode");
|
||||
} else {
|
||||
video_add_mode(mode.w, mode.h);
|
||||
video_add_mode_fullscreen(mode.w, mode.h);
|
||||
fullscreen_available = true;
|
||||
}
|
||||
}
|
||||
|
@ -707,17 +750,21 @@ void video_init(void) {
|
|||
{1152, 864},
|
||||
{1400, 1050},
|
||||
{1440, 1080},
|
||||
{1600, 1200},
|
||||
{1856, 1392},
|
||||
{1920, 1440},
|
||||
{0, 0},
|
||||
};
|
||||
|
||||
if(video_query_capability(VIDEO_CAP_FULLSCREEN) != VIDEO_ALWAYS_ENABLED) {
|
||||
for(int i = 0; common_modes[i].width; ++i) {
|
||||
video_add_mode(common_modes[i].width, common_modes[i].height);
|
||||
video_add_mode_windowed(common_modes[i].width, common_modes[i].height);
|
||||
}
|
||||
}
|
||||
|
||||
// sort it, mainly for the options menu
|
||||
qsort(video.modes, video.mcount, sizeof(VideoMode), video_compare_modes);
|
||||
qsort(video.fs_modes.mode, video.fs_modes.mcount, sizeof(VideoMode), video_compare_modes);
|
||||
qsort(video.win_modes.mode, video.win_modes.mcount, sizeof(VideoMode), video_compare_modes);
|
||||
|
||||
video_set_mode(
|
||||
config_get_int(CONFIG_VID_DISPLAY),
|
||||
|
@ -755,7 +802,8 @@ void video_shutdown(void) {
|
|||
events_unregister_handler(video_handle_config_event);
|
||||
SDL_DestroyWindow(video.window);
|
||||
r_shutdown();
|
||||
free(video.modes);
|
||||
free(video.win_modes.mode);
|
||||
free(video.fs_modes.mode);
|
||||
SDL_VideoQuit();
|
||||
}
|
||||
|
||||
|
@ -795,13 +843,22 @@ VideoBackend video_get_backend(void) {
|
|||
return video.backend;
|
||||
}
|
||||
|
||||
VideoMode video_get_mode(uint idx) {
|
||||
assert(idx < video.mcount);
|
||||
return video.modes[idx];
|
||||
VideoMode video_get_mode(uint idx, bool fullscreen) {
|
||||
if(fullscreen) {
|
||||
assert(idx < video.fs_modes.mcount);
|
||||
return video.fs_modes.mode[idx];
|
||||
}
|
||||
|
||||
assert(idx < video.win_modes.mcount);
|
||||
return video.win_modes.mode[idx];
|
||||
}
|
||||
|
||||
uint video_get_num_modes(void) {
|
||||
return video.mcount;
|
||||
uint video_get_num_modes(bool fullscreen) {
|
||||
if(fullscreen) {
|
||||
return video.fs_modes.mcount;
|
||||
}
|
||||
|
||||
return video.win_modes.mcount;
|
||||
}
|
||||
|
||||
VideoMode video_get_current_mode(void) {
|
||||
|
|
|
@ -79,8 +79,8 @@ void video_set_display(uint idx);
|
|||
const char *video_display_name(uint id) attr_returns_nonnull;
|
||||
Framebuffer *video_get_screen_framebuffer(void);
|
||||
VideoBackend video_get_backend(void);
|
||||
VideoMode video_get_mode(uint idx);
|
||||
uint video_get_num_modes(void);
|
||||
VideoMode video_get_mode(uint idx, bool fullscreen);
|
||||
uint video_get_num_modes(bool fullscreen);
|
||||
VideoMode video_get_current_mode(void);
|
||||
|
||||
#endif // IGUARD_video_h
|
||||
|
|
Loading…
Reference in a new issue