use OpenGL swap interval on Windows and X11

This commit is contained in:
Carlos Aragones 2021-04-28 12:34:20 +02:00
parent f9aa6acb7a
commit 815fa2f255
6 changed files with 139 additions and 42 deletions

View File

@ -102,3 +102,12 @@ resize_dst(SWindowData *window_data, uint32_t width, uint32_t height) {
window_data->dst_width = (uint32_t) (width * window_data->factor_width); window_data->dst_width = (uint32_t) (width * window_data->factor_width);
window_data->dst_height = (uint32_t) (height * window_data->factor_height); window_data->dst_height = (uint32_t) (height * window_data->factor_height);
} }
#if !defined(USE_OPENGL_API)
//-------------------------------------
void
set_target_fps_aux() {
}
#endif

View File

@ -20,6 +20,7 @@ extern "C" {
void calc_dst_factor(SWindowData *window_data, uint32_t width, uint32_t height); void calc_dst_factor(SWindowData *window_data, uint32_t width, uint32_t height);
void resize_dst(SWindowData *window_data, uint32_t width, uint32_t height); void resize_dst(SWindowData *window_data, uint32_t width, uint32_t height);
void set_target_fps_aux();
#if defined(__cplusplus) #if defined(__cplusplus)
} }

View File

@ -6,6 +6,7 @@
double g_timer_frequency; double g_timer_frequency;
double g_timer_resolution; double g_timer_resolution;
double g_time_for_frame = 1.0 / 60.0; double g_time_for_frame = 1.0 / 60.0;
bool g_use_hardware_sync = false;
//------------------------------------- //-------------------------------------
extern uint64_t mfb_timer_tick(void); extern uint64_t mfb_timer_tick(void);
@ -20,6 +21,7 @@ mfb_set_target_fps(uint32_t fps) {
else { else {
g_time_for_frame = 1.0 / fps; g_time_for_frame = 1.0 / fps;
} }
set_target_fps_aux();
} }
//------------------------------------- //-------------------------------------

View File

@ -1,6 +1,7 @@
#if defined(USE_OPENGL_API) #if defined(USE_OPENGL_API)
#include "MiniFB_GL.h" #include "MiniFB_GL.h"
#include "MiniFB_internal.h"
#if defined(_WIN32) || defined(WIN32) #if defined(_WIN32) || defined(WIN32)
#include <windows/WindowData_Win.h> #include <windows/WindowData_Win.h>
#include <gl/gl.h> #include <gl/gl.h>
@ -19,6 +20,10 @@
#define UseCleanUp(x) #define UseCleanUp(x)
#endif #endif
extern double g_time_for_frame;
extern bool g_use_hardware_sync;
//------------------------------------- //-------------------------------------
#if defined(_WIN32) || defined(WIN32) #if defined(_WIN32) || defined(WIN32)
bool bool
@ -59,6 +64,44 @@ setup_pixel_format(HDC hDC) {
return true; return true;
} }
typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int);
typedef int (WINAPI * PFNWGLGETSWAPINTERVALEXTPROC)(void);
PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT = 0x0;
PFNWGLGETSWAPINTERVALEXTPROC GetSwapIntervalEXT = 0x0;
#elif defined(linux)
bool
setup_pixel_format(SWindowData_X11 *window_data_x11) {
GLint glxAttribs[] = {
GLX_RGBA,
GLX_DOUBLEBUFFER,
GLX_DEPTH_SIZE, 24,
GLX_STENCIL_SIZE, 8,
GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_DEPTH_SIZE, 24,
GLX_STENCIL_SIZE, 8,
GLX_SAMPLE_BUFFERS, 0,
GLX_SAMPLES, 0,
None
};
XVisualInfo* visualInfo = glXChooseVisual(window_data_x11->display, window_data_x11->screen, glxAttribs);
if (visualInfo == 0) {
fprintf(stderr, "Could not create correct visual window.\n");
XCloseDisplay(window_data_x11->display);
return false;
}
return true;
}
typedef void (*PFNGLXSWAPINTERVALEXTPROC)(Display*,GLXDrawable,int);
PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT = 0x0;
#endif #endif
//------------------------------------- //-------------------------------------
@ -69,10 +112,15 @@ create_GL_context(SWindowData *window_data) {
if (setup_pixel_format(window_data_win->hdc) == false) if (setup_pixel_format(window_data_win->hdc) == false)
return false; return false;
window_data_win->hGLRC = wglCreateContext(window_data_win->hdc); window_data_win->hGLRC = wglCreateContext(window_data_win->hdc);
wglMakeCurrent(window_data_win->hdc, window_data_win->hGLRC); wglMakeCurrent(window_data_win->hdc, window_data_win->hGLRC);
init_GL(window_data); init_GL(window_data);
SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC) wglGetProcAddress("wglSwapIntervalEXT");
GetSwapIntervalEXT = (PFNWGLGETSWAPINTERVALEXTPROC) wglGetProcAddress("wglGetSwapIntervalEXT");
set_target_fps_aux();
return true; return true;
#elif defined(linux) #elif defined(linux)
@ -89,26 +137,8 @@ create_GL_context(SWindowData *window_data) {
//fprintf(stdout, "GLX version: %d.%d\n", majorGLX, minorGLX); //fprintf(stdout, "GLX version: %d.%d\n", majorGLX, minorGLX);
} }
GLint glxAttribs[] = { if (setup_pixel_format(window_data_x11) == false)
GLX_RGBA,
GLX_DOUBLEBUFFER,
GLX_DEPTH_SIZE, 24,
GLX_STENCIL_SIZE, 8,
GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_DEPTH_SIZE, 24,
GLX_STENCIL_SIZE, 8,
GLX_SAMPLE_BUFFERS, 0,
GLX_SAMPLES, 0,
None
};
XVisualInfo* visualInfo = glXChooseVisual(window_data_x11->display, window_data_x11->screen, glxAttribs);
if (visualInfo == 0) {
fprintf(stderr, "Could not create correct visual window.\n");
XCloseDisplay(window_data_x11->display);
return false; return false;
}
window_data_x11->context = glXCreateContext(window_data_x11->display, visualInfo, NULL, GL_TRUE); window_data_x11->context = glXCreateContext(window_data_x11->display, visualInfo, NULL, GL_TRUE);
glXMakeCurrent(window_data_x11->display, window_data_x11->window, window_data_x11->context); glXMakeCurrent(window_data_x11->display, window_data_x11->window, window_data_x11->context);
@ -120,6 +150,9 @@ create_GL_context(SWindowData *window_data) {
init_GL(window_data); init_GL(window_data);
SwapIntervalEXT = (PFNGLXSWAPINTERVALEXTPROC) getProcAddressGLX("glXSwapIntervalEXT");
set_target_fps_aux();
return true; return true;
#endif #endif
} }
@ -289,4 +322,47 @@ redraw_GL(SWindowData *window_data, const void *pixels) {
#endif #endif
} }
//-------------------------------------
void
set_target_fps_aux() {
// Assuming the monitor refresh rate is 60 hz
int interval = (int) ((60.0 * g_time_for_frame) + 0.5);
#if defined(_WIN32) || defined(WIN32)
if (SwapIntervalEXT != 0x0) {
bool success = SwapIntervalEXT(interval);
if (GetSwapIntervalEXT != 0x0) {
int currentInterval = GetSwapIntervalEXT();
if (interval != currentInterval) {
fprintf(stderr, "Cannot set target swap interval. Current swap interval is %d\n", currentInterval);
}
}
else if (success == false) {
fprintf(stderr, "Cannot set target swap interval.\n");
}
g_use_hardware_sync = true;
}
#elif defined(linux)
#define kGLX_SWAP_INTERVAL_EXT 0x20F1
#define kGLX_MAX_SWAP_INTERVAL_EXT 0x20F2
if (SwapIntervalEXT != 0x0) {
Display *dpy = glXGetCurrentDisplay();
GLXDrawable drawable = glXGetCurrentDrawable();
unsigned int currentInterval, maxInterval;
SwapIntervalEXT(dpy, drawable, interval);
glXQueryDrawable(dpy, drawable, kGLX_SWAP_INTERVAL_EXT, &currentInterval);
if (interval != currentInterval) {
glXQueryDrawable(dpy, drawable, kGLX_MAX_SWAP_INTERVAL_EXT, &maxInterval);
fprintf(stderr, "Cannot set target swap interval. Current swap interval is %d (max: %d)\n", currentInterval, maxInterval);
}
g_use_hardware_sync = true;
}
#endif
}
#endif #endif

View File

@ -192,7 +192,7 @@ WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
if(mfb_EnableNonClientDpiScaling) if(mfb_EnableNonClientDpiScaling)
mfb_EnableNonClientDpiScaling(hWnd); mfb_EnableNonClientDpiScaling(hWnd);
return DefWindowProc(hWnd, message, wParam, lParam);; return DefWindowProc(hWnd, message, wParam, lParam);
} }
// TODO // TODO
@ -647,11 +647,10 @@ mfb_update_events(struct mfb_window *window) {
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
extern double g_time_for_frame; extern double g_time_for_frame;
extern bool g_use_hardware_sync;
bool bool
mfb_wait_sync(struct mfb_window *window) { mfb_wait_sync(struct mfb_window *window) {
MSG msg;
if (window == 0x0) { if (window == 0x0) {
return false; return false;
} }
@ -662,6 +661,11 @@ mfb_wait_sync(struct mfb_window *window) {
return false; return false;
} }
if(g_use_hardware_sync) {
return true;
}
MSG msg;
SWindowData_Win *window_data_win = (SWindowData_Win *) window_data->specific; SWindowData_Win *window_data_win = (SWindowData_Win *) window_data->specific;
double current; double current;
uint32_t millis = 1; uint32_t millis = 1;

View File

@ -433,6 +433,7 @@ mfb_update_events(struct mfb_window *window) {
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
extern double g_time_for_frame; extern double g_time_for_frame;
extern bool g_use_hardware_sync;
bool bool
mfb_wait_sync(struct mfb_window *window) { mfb_wait_sync(struct mfb_window *window) {
@ -446,6 +447,10 @@ mfb_wait_sync(struct mfb_window *window) {
return false; return false;
} }
if(g_use_hardware_sync) {
return true;
}
SWindowData_X11 *window_data_x11 = (SWindowData_X11 *) window_data->specific; SWindowData_X11 *window_data_x11 = (SWindowData_X11 *) window_data->specific;
XFlush(window_data_x11->display); XFlush(window_data_x11->display);
XEvent event; XEvent event;