use OpenGL swap interval on Windows and X11
This commit is contained in:
parent
f9aa6acb7a
commit
815fa2f255
@ -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
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
|
@ -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
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
@ -67,12 +110,17 @@ create_GL_context(SWindowData *window_data) {
|
|||||||
#if defined(_WIN32) || defined(WIN32)
|
#if defined(_WIN32) || defined(WIN32)
|
||||||
SWindowData_Win *window_data_win = (SWindowData_Win *) window_data->specific;
|
SWindowData_Win *window_data_win = (SWindowData_Win *) window_data->specific;
|
||||||
|
|
||||||
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
|
||||||
}
|
}
|
||||||
@ -202,7 +235,7 @@ init_GL(SWindowData *window_data) {
|
|||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
void
|
void
|
||||||
resize_GL(SWindowData *window_data) {
|
resize_GL(SWindowData *window_data) {
|
||||||
if(window_data->is_initialized) {
|
if (window_data->is_initialized) {
|
||||||
#if defined(_WIN32) || defined(WIN32)
|
#if defined(_WIN32) || defined(WIN32)
|
||||||
|
|
||||||
SWindowData_Win *window_data_ex = (SWindowData_Win *) window_data->specific;
|
SWindowData_Win *window_data_ex = (SWindowData_Win *) window_data->specific;
|
||||||
@ -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, ¤tInterval);
|
||||||
|
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
|
@ -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,9 +661,14 @@ 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;
|
||||||
while (1) {
|
while (1) {
|
||||||
current = mfb_timer_now(window_data_win->timer);
|
current = mfb_timer_now(window_data_win->timer);
|
||||||
if (current >= g_time_for_frame * 0.96) {
|
if (current >= g_time_for_frame * 0.96) {
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user