mirror of https://github.com/encounter/SDL.git
Fixed bug 3943 - General SDL_HINT_VIDEO_DOUBLE_BUFFER hint support
This commit is contained in:
parent
5cc46f3d30
commit
9f4e4be8e0
|
@ -798,14 +798,22 @@ extern "C" {
|
|||
#define SDL_HINT_RPI_VIDEO_LAYER "SDL_RPI_VIDEO_LAYER"
|
||||
|
||||
/**
|
||||
* \brief Tell SDL the KMS/DRM video driver that we want double buffer only.
|
||||
* \brief Tell the video driver that we only want a double buffer.
|
||||
*
|
||||
* By default KMS/DRM will use a triple buffer solution that wastes no CPU
|
||||
* time on waiting for vsync after issuing a flip, but introduces a frame of
|
||||
* latency. Waiting for vsync immediately after issuing a flip on the other
|
||||
* hand is recommended for cases where low latency is an important factor.
|
||||
* By default, most lowlevel 2D APIs will use a triple buffer scheme that
|
||||
* wastes no CPU time on waiting for vsync after issuing a flip, but
|
||||
* introduces a frame of latency. On the other hand, using a double buffer
|
||||
* scheme instead is recommended for cases where low latency is an important
|
||||
* factor because we save a whole frame of latency.
|
||||
* We do so by waiting for vsync immediately after issuing a flip, usually just
|
||||
* after eglSwapBuffers call in the backend's *_SwapWindow function.
|
||||
*
|
||||
* Since it's driver-specific, it's only supported where possible and
|
||||
* implemented. Currently supported the following drivers:
|
||||
* - KMSDRM (kmsdrm)
|
||||
* - Raspberry Pi (raspberrypi)
|
||||
*/
|
||||
#define SDL_HINT_KMSDRM_DOUBLE_BUFFER "SDL_KMSDRM_DOUBLE_BUFFER"
|
||||
#define SDL_HINT_VIDEO_DOUBLE_BUFFER "SDL_VIDEO_DOUBLE_BUFFER"
|
||||
|
||||
/**
|
||||
* \brief A variable controlling what driver to use for OpenGL ES contexts.
|
||||
|
|
|
@ -525,7 +525,7 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
|
|||
|
||||
/* In case we want low-latency, double-buffer video, we take note here */
|
||||
wdata->double_buffer = SDL_FALSE;
|
||||
if (SDL_GetHintBoolean(SDL_HINT_KMSDRM_DOUBLE_BUFFER, SDL_FALSE)) {
|
||||
if (SDL_GetHintBoolean(SDL_HINT_VIDEO_DOUBLE_BUFFER, SDL_FALSE)) {
|
||||
wdata->double_buffer = SDL_TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "../../SDL_internal.h"
|
||||
#include "SDL_hints.h"
|
||||
#include "SDL_log.h"
|
||||
|
||||
#if SDL_VIDEO_DRIVER_RPI && SDL_VIDEO_OPENGL_EGL
|
||||
|
||||
|
@ -40,8 +42,27 @@ RPI_GLES_LoadLibrary(_THIS, const char *path) {
|
|||
return SDL_EGL_LoadLibrary(_this, path, EGL_DEFAULT_DISPLAY, 0);
|
||||
}
|
||||
|
||||
int
|
||||
RPI_GLES_SwapWindow(_THIS, SDL_Window * window) {
|
||||
SDL_WindowData *wdata = ((SDL_WindowData *) window->driverdata);
|
||||
|
||||
if (!(_this->egl_data->eglSwapBuffers(_this->egl_data->egl_display, wdata->egl_surface))) {
|
||||
SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "eglSwapBuffers failed.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Wait immediately for vsync (as if we only had two buffers), for low input-lag scenarios.
|
||||
* Run your SDL2 program with "SDL_RPI_DOUBLE_BUFFER=1 <program_name>" to enable this. */
|
||||
if (wdata->double_buffer) {
|
||||
SDL_LockMutex(wdata->vsync_cond_mutex);
|
||||
SDL_CondWait(wdata->vsync_cond, wdata->vsync_cond_mutex);
|
||||
SDL_UnlockMutex(wdata->vsync_cond_mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SDL_EGL_CreateContext_impl(RPI)
|
||||
SDL_EGL_SwapWindow_impl(RPI)
|
||||
SDL_EGL_MakeCurrent_impl(RPI)
|
||||
|
||||
#endif /* SDL_VIDEO_DRIVER_RPI && SDL_VIDEO_OPENGL_EGL */
|
||||
|
|
|
@ -214,6 +214,16 @@ RPI_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
RPI_vsync_callback(DISPMANX_UPDATE_HANDLE_T u, void *data)
|
||||
{
|
||||
SDL_WindowData *wdata = ((SDL_WindowData *) data);
|
||||
|
||||
SDL_LockMutex(wdata->vsync_cond_mutex);
|
||||
SDL_CondSignal(wdata->vsync_cond);
|
||||
SDL_UnlockMutex(wdata->vsync_cond_mutex);
|
||||
}
|
||||
|
||||
int
|
||||
RPI_CreateWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
|
@ -289,9 +299,18 @@ RPI_CreateWindow(_THIS, SDL_Window * window)
|
|||
return SDL_SetError("Could not create GLES window surface");
|
||||
}
|
||||
|
||||
/* Start generating vsync callbacks if necesary */
|
||||
wdata->double_buffer = SDL_FALSE;
|
||||
if (SDL_GetHintBoolean(SDL_HINT_VIDEO_DOUBLE_BUFFER, SDL_FALSE)) {
|
||||
wdata->vsync_cond = SDL_CreateCond();
|
||||
wdata->vsync_cond_mutex = SDL_CreateMutex();
|
||||
wdata->double_buffer = SDL_TRUE;
|
||||
vc_dispmanx_vsync_callback(displaydata->dispman_display, RPI_vsync_callback, (void*)wdata);
|
||||
}
|
||||
|
||||
/* Setup driver data for this window */
|
||||
window->driverdata = wdata;
|
||||
|
||||
|
||||
/* One window, it always has focus */
|
||||
SDL_SetMouseFocus(window);
|
||||
SDL_SetKeyboardFocus(window);
|
||||
|
@ -304,7 +323,22 @@ void
|
|||
RPI_DestroyWindow(_THIS, SDL_Window * window)
|
||||
{
|
||||
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
|
||||
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
|
||||
SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
|
||||
|
||||
if(data) {
|
||||
if (data->double_buffer) {
|
||||
/* Wait for vsync, and then stop vsync callbacks and destroy related stuff, if needed */
|
||||
SDL_LockMutex(data->vsync_cond_mutex);
|
||||
SDL_CondWait(data->vsync_cond, data->vsync_cond_mutex);
|
||||
SDL_UnlockMutex(data->vsync_cond_mutex);
|
||||
|
||||
vc_dispmanx_vsync_callback(displaydata->dispman_display, NULL, NULL);
|
||||
|
||||
SDL_DestroyCond(data->vsync_cond);
|
||||
SDL_DestroyMutex(data->vsync_cond_mutex);
|
||||
}
|
||||
|
||||
#if SDL_VIDEO_OPENGL_EGL
|
||||
if (data->egl_surface != EGL_NO_SURFACE) {
|
||||
SDL_EGL_DestroySurface(_this, data->egl_surface);
|
||||
|
|
|
@ -48,6 +48,12 @@ typedef struct SDL_WindowData
|
|||
#if SDL_VIDEO_OPENGL_EGL
|
||||
EGLSurface egl_surface;
|
||||
#endif
|
||||
|
||||
/* Vsync callback cond and mutex */
|
||||
SDL_cond *vsync_cond;
|
||||
SDL_mutex *vsync_cond_mutex;
|
||||
SDL_bool double_buffer;
|
||||
|
||||
} SDL_WindowData;
|
||||
|
||||
#define SDL_RPI_VIDEOLAYER 10000 /* High enough so to occlude everything */
|
||||
|
|
Loading…
Reference in New Issue