Skip to content

Commit dbff6df

Browse files
authored
UPBGE: Fix bge.render.[get/set]Vsync. (#834)
Previously bge.render.getVsync wasn't returning the value set by setVsync when VSYNC_ADAPTIVE was used. It can be justified by the fact that adaptive is set by using a negative swap interval value but the GLX get function still returns a positive swap interval value and the flag GLX_LATE_SWAPS_TEAR_EXT meaning adaptive is enabled. In any case GLX could refuse a swap interval and the user should be able to do setVsync(getVsync()) with no change on the swap control. To achieve this behaviour RAS_ICanvas store the current swap control in a enum variable m_controlSwap, this variable is used in getter GetSwapControl used by bge.render.getVsync(). The setter is virtual and overloaded in each canvas implementation, they use a common table to find the swap interval associated to the swap control mode: RAS_ICanvas::swapInterval. Finally KX_PythonInit is using swap control enum value from RAS_ICanvas instead of the one from DNA to avoid conversions. Fix issue #820.
1 parent e1b316a commit dbff6df

File tree

10 files changed

+57
-53
lines changed

10 files changed

+57
-53
lines changed

source/blender/makesdna/DNA_scene_types.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -900,9 +900,11 @@ typedef struct GameData {
900900
#define OBSTSIMULATION_TOI_cells 2
901901

902902
/* GameData.vsync */
903-
#define VSYNC_ON 0
904-
#define VSYNC_OFF 1
905-
#define VSYNC_ADAPTIVE 2
903+
enum {
904+
VSYNC_ON = 0,
905+
VSYNC_OFF,
906+
VSYNC_ADAPTIVE
907+
};
906908

907909
/* GameData.flag */
908910
#define GAME_RESTRICT_ANIM_UPDATES (1 << 0)

source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,10 @@ void KX_BlenderCanvas::SwapBuffers()
7575
wm_window_swap_buffers(m_win);
7676
}
7777

78-
void KX_BlenderCanvas::SetSwapInterval(int interval)
78+
void KX_BlenderCanvas::SetSwapControl(SwapControl control)
7979
{
80-
wm_window_set_swap_interval(m_win, interval);
81-
}
82-
83-
bool KX_BlenderCanvas::GetSwapInterval(int &intervalOut)
84-
{
85-
return wm_window_get_swap_interval(m_win, &intervalOut);
80+
wm_window_set_swap_interval(m_win, swapInterval[control]);
81+
RAS_ICanvas::SetSwapControl(control);
8682
}
8783

8884
void KX_BlenderCanvas::GetDisplayDimensions(int &width, int &height)

source/gameengine/BlenderRoutines/KX_BlenderCanvas.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,7 @@ class KX_BlenderCanvas : public RAS_ICanvas
6363
virtual void Init();
6464

6565
virtual void SwapBuffers();
66-
virtual void SetSwapInterval(int interval);
67-
virtual bool GetSwapInterval(int &intervalOut);
66+
virtual void SetSwapControl(SwapControl control);
6867

6968
virtual void GetDisplayDimensions(int &width, int &height);
7069
virtual void ResizeWindow(int width, int height);

source/gameengine/GamePlayer/GPG_Canvas.cpp

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -211,20 +211,12 @@ void GPG_Canvas::SwapBuffers()
211211
}
212212
}
213213

214-
void GPG_Canvas::SetSwapInterval(int interval)
214+
void GPG_Canvas::SetSwapControl(SwapControl control)
215215
{
216216
if (m_window) {
217-
m_window->setSwapInterval(interval);
217+
m_window->setSwapInterval(swapInterval[control]);
218218
}
219-
}
220-
221-
bool GPG_Canvas::GetSwapInterval(int& intervalOut)
222-
{
223-
if (m_window) {
224-
return (bool)m_window->getSwapInterval(intervalOut);
225-
}
226-
227-
return false;
219+
RAS_ICanvas::SetSwapControl(control);
228220
}
229221

230222
void GPG_Canvas::GetDisplayDimensions(int &width, int &height)

source/gameengine/GamePlayer/GPG_Canvas.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,7 @@ class GPG_Canvas : public RAS_ICanvas
8787
virtual void SetMousePosition(int x, int y);
8888
virtual void SetMouseState(RAS_MouseState mousestate);
8989
virtual void SwapBuffers();
90-
virtual void SetSwapInterval(int interval);
91-
virtual bool GetSwapInterval(int& intervalOut);
90+
virtual void SetSwapControl(SwapControl control);
9291

9392
virtual void ConvertMousePosition(int x, int y, int &r_x, int &r_y, bool screen);
9493
virtual float GetMouseNormalizedX(int x);

source/gameengine/Ketsji/KX_PythonInit.cpp

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1298,29 +1298,24 @@ static PyObject *gPyGetMipmapping(PyObject *)
12981298

12991299
static PyObject *gPySetVsync(PyObject *, PyObject *args)
13001300
{
1301-
int interval;
1301+
int control;
13021302

1303-
if (!PyArg_ParseTuple(args, "i:setVsync", &interval)) {
1303+
if (!PyArg_ParseTuple(args, "i:setVsync", &control)) {
13041304
return nullptr;
13051305
}
13061306

1307-
if (interval < 0 || interval > VSYNC_ADAPTIVE) {
1307+
if (control < 0 || control >= RAS_ICanvas::SWAP_CONTROL_MAX) {
13081308
PyErr_SetString(PyExc_ValueError, "Rasterizer.setVsync(value): value must be VSYNC_OFF, VSYNC_ON, or VSYNC_ADAPTIVE");
13091309
return nullptr;
13101310
}
13111311

1312-
if (interval == VSYNC_ADAPTIVE) {
1313-
interval = -1;
1314-
}
1315-
KX_GetActiveEngine()->GetCanvas()->SetSwapInterval((interval == VSYNC_ON) ? 1 : 0);
1312+
KX_GetActiveEngine()->GetCanvas()->SetSwapControl((RAS_ICanvas::SwapControl)control);
13161313
Py_RETURN_NONE;
13171314
}
13181315

13191316
static PyObject *gPyGetVsync(PyObject *)
13201317
{
1321-
int interval = 0;
1322-
KX_GetActiveEngine()->GetCanvas()->GetSwapInterval(interval);
1323-
return PyLong_FromLong(interval);
1318+
return PyLong_FromLong(KX_GetActiveEngine()->GetCanvas()->GetSwapControl());
13241319
}
13251320

13261321
static PyObject *gPyShowFramerate(PyObject *, PyObject *args)
@@ -2200,9 +2195,9 @@ PyMODINIT_FUNC initRasterizerPythonBinding()
22002195
KX_MACRO_addTypesToDict(d, RAS_MIPMAP_LINEAR, RAS_Rasterizer::RAS_MIPMAP_LINEAR);
22012196

22022197
/* for get/setVsync */
2203-
KX_MACRO_addTypesToDict(d, VSYNC_OFF, VSYNC_OFF);
2204-
KX_MACRO_addTypesToDict(d, VSYNC_ON, VSYNC_ON);
2205-
KX_MACRO_addTypesToDict(d, VSYNC_ADAPTIVE, VSYNC_ADAPTIVE);
2198+
KX_MACRO_addTypesToDict(d, VSYNC_OFF, RAS_ICanvas::VSYNC_OFF);
2199+
KX_MACRO_addTypesToDict(d, VSYNC_ON, RAS_ICanvas::VSYNC_ON);
2200+
KX_MACRO_addTypesToDict(d, VSYNC_ADAPTIVE, RAS_ICanvas::VSYNC_ADAPTIVE);
22062201

22072202
/* stereoscopy */
22082203
KX_MACRO_addTypesToDict(d, LEFT_EYE, RAS_Rasterizer::RAS_STEREO_LEFTEYE);

source/gameengine/Launcher/LA_Launcher.cpp

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -190,15 +190,13 @@ void LA_Launcher::InitEngine()
190190
// Create the canvas, rasterizer and rendertools.
191191
m_canvas = CreateCanvas(m_rasterizer);
192192

193-
// Copy current vsync mode to restore at the game end.
194-
m_canvas->GetSwapInterval(m_savedData.vsync);
193+
static const RAS_ICanvas::SwapControl swapControlTable[] = {
194+
RAS_ICanvas::VSYNC_ON, // VSYNC_ON
195+
RAS_ICanvas::VSYNC_OFF, // VSYNC_OFF
196+
RAS_ICanvas::VSYNC_ADAPTIVE // VSYNC_ADAPTIVE
197+
};
195198

196-
if (gm.vsync == VSYNC_ADAPTIVE) {
197-
m_canvas->SetSwapInterval(-1);
198-
}
199-
else {
200-
m_canvas->SetSwapInterval((gm.vsync == VSYNC_ON) ? 1 : 0);
201-
}
199+
m_canvas->SetSwapControl(swapControlTable[gm.vsync]);
202200

203201
// Set canvas multisamples.
204202
m_canvas->SetSamples(m_samples);
@@ -326,13 +324,9 @@ void LA_Launcher::ExitEngine()
326324

327325
// Set anisotropic settign back to its original value.
328326
m_rasterizer->SetAnisotropicFiltering(m_savedData.anisotropic);
329-
330327
// Set mipmap setting back to its original value.
331328
m_rasterizer->SetMipmapping(m_savedData.mipmap);
332329

333-
// Set vsync mode back to original value.
334-
m_canvas->SetSwapInterval(m_savedData.vsync);
335-
336330
if (m_converter) {
337331
delete m_converter;
338332
m_converter = nullptr;

source/gameengine/Launcher/LA_Launcher.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ class LA_Launcher
9292

9393
/// Saved data to restore at the game end.
9494
struct SavedData {
95-
int vsync;
9695
RAS_Rasterizer::MipmapOption mipmap;
9796
int anisotropic;
9897
} m_savedData;

source/gameengine/Rasterizer/RAS_ICanvas.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,16 @@ struct ScreenshotTaskData {
6262
*/
6363
void save_screenshot_thread_func(TaskPool *__restrict pool, void *taskdata, int threadid);
6464

65+
const int RAS_ICanvas::swapInterval[RAS_ICanvas::SWAP_CONTROL_MAX] = {
66+
0, // VSYNC_OFF
67+
1, // VSYNC_ON
68+
-1 // VSYNC_ADAPTIVE
69+
};
6570

6671
RAS_ICanvas::RAS_ICanvas(RAS_Rasterizer *rasty)
6772
:m_samples(0),
6873
m_hdrType(RAS_Rasterizer::RAS_HDR_NONE),
74+
m_swapControl(VSYNC_OFF),
6975
m_frame(1)
7076
{
7177
m_taskscheduler = BLI_task_scheduler_create(TASK_SCHEDULER_AUTO_THREADS);
@@ -87,6 +93,16 @@ RAS_ICanvas::~RAS_ICanvas()
8793
}
8894
}
8995

96+
void RAS_ICanvas::SetSwapControl(SwapControl control)
97+
{
98+
m_swapControl = control;
99+
}
100+
101+
RAS_ICanvas::SwapControl RAS_ICanvas::GetSwapControl() const
102+
{
103+
return m_swapControl;
104+
}
105+
90106
void RAS_ICanvas::SetSamples(int samples)
91107
{
92108
m_samples = samples;

source/gameengine/Rasterizer/RAS_ICanvas.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ class RAS_ICanvas
5252
MOUSE_NORMAL
5353
};
5454

55+
enum SwapControl
56+
{
57+
VSYNC_OFF = 0,
58+
VSYNC_ON,
59+
VSYNC_ADAPTIVE,
60+
SWAP_CONTROL_MAX
61+
};
62+
5563
RAS_ICanvas(RAS_Rasterizer *rasty);
5664
virtual ~RAS_ICanvas();
5765

@@ -77,8 +85,8 @@ class RAS_ICanvas
7785

7886
/// probably needs some arguments for PS2 in future
7987
virtual void SwapBuffers() = 0;
80-
virtual void SetSwapInterval(int interval) = 0;
81-
virtual bool GetSwapInterval(int& intervalOut) = 0;
88+
virtual void SetSwapControl(SwapControl control);
89+
SwapControl GetSwapControl() const;
8290

8391
void SetSamples(int samples);
8492
int GetSamples() const;
@@ -152,6 +160,9 @@ class RAS_ICanvas
152160
}
153161

154162
protected:
163+
/// Swap interval value of each swap control mode.
164+
static const int swapInterval[SWAP_CONTROL_MAX];
165+
155166
struct Screenshot
156167
{
157168
std::string path;
@@ -167,6 +178,7 @@ class RAS_ICanvas
167178
int m_samples;
168179
RAS_Rasterizer::HdrType m_hdrType;
169180

181+
SwapControl m_swapControl;
170182
RAS_MouseState m_mousestate;
171183
/// frame number for screenshots.
172184
int m_frame;

0 commit comments

Comments
 (0)