BGE: Adding vsync control. Users can enable vsync, disable vsync, or use adaptive vsync via UI options in the render properties, or by using the new Python method bge.render.setVsync(). Win32 and X11 support are done via EXT_swap_control. Support for using EXT_swap_control on OS X still needs to be added to Ghost.

This commit is contained in:
Mitchell Stokes
2013-07-29 22:31:32 +00:00
parent 2840edba84
commit 29f8dfd37a
22 changed files with 266 additions and 1 deletions

View File

@@ -1324,6 +1324,16 @@ void wm_window_swap_buffers(wmWindow *win)
#endif
}
void wm_window_set_swap_interval (wmWindow *win, int interval)
{
GHOST_SetSwapInterval(win->ghostwin, interval);
}
int wm_window_get_swap_interval (wmWindow *win)
{
return GHOST_GetSwapInterval(win->ghostwin);
}
/* ******************* exported api ***************** */

View File

@@ -58,6 +58,8 @@ void wm_window_lower (wmWindow *win);
void wm_window_set_size (wmWindow *win, int width, int height);
void wm_window_get_position (wmWindow *win, int *posx_r, int *posy_r);
void wm_window_swap_buffers (wmWindow *win);
void wm_window_set_swap_interval (wmWindow *win, int interval);
int wm_window_get_swap_interval (wmWindow *win);
void wm_get_cursor_position (wmWindow *win, int *x, int *y);

View File

@@ -284,6 +284,14 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL);
else
canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE);
// Setup vsync
int previous_vsync = canvas->GetSwapInterval();
if (startscene->gm.vsync == VSYNC_ADAPTIVE)
canvas->SetSwapInterval(-1);
else
canvas->SetSwapInterval(startscene->gm.vsync); // VSYNC_OFF == 0, VSYNC_ON == 1, so this works
RAS_IRenderTools* rendertools = new KX_BlenderRenderTools();
RAS_IRasterizer* rasterizer = NULL;
//Don't use displaylists with VBOs
@@ -663,6 +671,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c
}
if (canvas)
{
canvas->SetSwapInterval(previous_vsync); // Set the swap interval back
delete canvas;
canvas = NULL;
}

View File

@@ -66,6 +66,16 @@ void KX_BlenderCanvas::SwapBuffers()
BL_SwapBuffers(m_win);
}
void KX_BlenderCanvas::SetSwapInterval(int interval)
{
BL_SetSwapInterval(m_win, interval);
}
int KX_BlenderCanvas::GetSwapInterval()
{
return BL_GetSwapInterval(m_win);
}
void KX_BlenderCanvas::ResizeWindow(int width, int height)
{
// Not implemented for the embedded player

View File

@@ -80,6 +80,16 @@ public:
void
SwapBuffers(
);
void
SetSwapInterval(
int interval
);
int
GetSwapInterval(
);
void
ResizeWindow(
int width,

View File

@@ -98,6 +98,16 @@ void BL_MakeDrawable(wmWindowManager *wm, wmWindow *win)
wm_window_make_drawable(wm, win);
}
void BL_SetSwapInterval(struct wmWindow *win, int interval)
{
wm_window_set_swap_interval(win, interval);
}
int BL_GetSwapInterval(struct wmWindow *win)
{
return wm_window_get_swap_interval(win);
}
static void DisableForText()
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); /* needed for texture fonts otherwise they render as wireframe */

View File

@@ -43,6 +43,8 @@ struct wmWindowManager;
// special swapbuffers, that takes care of which area (viewport) needs to be swapped
void BL_SwapBuffers(struct wmWindow *win);
void BL_SetSwapInterval(struct wmWindow *win, int interval);
int BL_GetSwapInterval(struct wmWindow *win);
void BL_MakeDrawable(struct wmWindowManager *wm, struct wmWindow *win);

View File

@@ -582,7 +582,12 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode)
m_canvas = new GPG_Canvas(window);
if (!m_canvas)
return false;
if (gm->vsync == VSYNC_ADAPTIVE)
m_canvas->SetSwapInterval(-1);
else
m_canvas->SetSwapInterval(gm->vsync); // VSYNC_OFF == 0, VSYNC_ON == 1, so this works
m_canvas->Init();
if (gm->flag & GAME_SHOW_MOUSE)
m_canvas->SetMouseState(RAS_ICanvas::MOUSE_NORMAL);

View File

@@ -107,6 +107,20 @@ void GPG_Canvas::SwapBuffers()
}
}
void GPG_Canvas::SetSwapInterval(int interval)
{
if (m_window)
m_window->setSwapInterval(interval);
}
int GPG_Canvas::GetSwapInterval()
{
if (m_window)
return m_window->getSwapInterval();
return 0;
}
void GPG_Canvas::ResizeWindow(int width, int height)
{
if (m_window->getState() == GHOST_kWindowStateFullScreen)

View File

@@ -55,6 +55,9 @@ public:
virtual void SetMousePosition(int x, int y);
virtual void SetMouseState(RAS_MouseState mousestate);
virtual void SwapBuffers();
virtual void SetSwapInterval(int interval);
virtual int GetSwapInterval();
virtual int GetMouseX(int x) { return x; }
virtual int GetMouseY(int y) { return y; }
virtual float GetMouseNormalizedX(int x);

View File

@@ -1372,6 +1372,29 @@ static PyObject *gPyGetMipmapping(PyObject *)
return PyLong_FromLong(gp_Rasterizer->GetMipmapping());
}
static PyObject *gPySetVsync(PyObject *, PyObject *args)
{
int interval;
if (!PyArg_ParseTuple(args, "i:setVsync", &interval))
return NULL;
if (interval < VSYNC_OFF || interval > VSYNC_ADAPTIVE) {
PyErr_SetString(PyExc_ValueError, "Rasterizer.setVsync(value): value must be VSYNC_OFF, VSYNC_ON, or VSYNC_ADAPTIVE");
return NULL;
}
if (interval == VSYNC_ADAPTIVE)
interval = -1;
gp_Canvas->SetSwapInterval(interval);
Py_RETURN_NONE;
}
static PyObject *gPyGetVsync(PyObject *)
{
return PyLong_FromLong(gp_Canvas->GetSwapInterval());
}
static struct PyMethodDef rasterizer_methods[] = {
{"getWindowWidth",(PyCFunction) gPyGetWindowWidth,
METH_VARARGS, "getWindowWidth doc"},
@@ -1417,6 +1440,8 @@ static struct PyMethodDef rasterizer_methods[] = {
{"getFullScreen", (PyCFunction) gPyGetFullScreen, METH_NOARGS, ""},
{"setMipmapping", (PyCFunction) gPySetMipmapping, METH_VARARGS, ""},
{"getMipmapping", (PyCFunction) gPyGetMipmapping, METH_NOARGS, ""},
{"setVsync", (PyCFunction) gPySetVsync, METH_VARARGS, ""},
{"getVsync", (PyCFunction) gPyGetVsync, METH_NOARGS, ""},
{ NULL, (PyCFunction) NULL, 0, NULL }
};
@@ -2189,6 +2214,11 @@ PyObject *initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas)
KX_MACRO_addTypesToDict(d, RAS_MIPMAP_NEAREST, RAS_IRasterizer::RAS_MIPMAP_NEAREST);
KX_MACRO_addTypesToDict(d, RAS_MIPMAP_LINEAR, RAS_IRasterizer::RAS_MIPMAP_LINEAR);
/* for get/setVsync */
KX_MACRO_addTypesToDict(d, VSYNC_OFF, VSYNC_OFF);
KX_MACRO_addTypesToDict(d, VSYNC_ON, VSYNC_ON);
KX_MACRO_addTypesToDict(d, VSYNC_ADAPTIVE, VSYNC_ADAPTIVE);
// XXXX Add constants here
// Check for errors

View File

@@ -105,6 +105,17 @@ public:
void
SwapBuffers(
)=0;
virtual
void
SetSwapInterval(
int interval
)=0;
virtual
int
GetSwapInterval(
)=0;
virtual
void