|
@@ -237,6 +237,8 @@ int X11_GL_LoadLibrary(SDL_VideoDevice *_this, const char *path)
|
|
|
return SDL_SetError("GLX is not supported");
|
|
|
}
|
|
|
|
|
|
+ _this->gl_data->swap_interval_tear_behavior = SDL_SWAPINTERVALTEAR_UNTESTED;
|
|
|
+
|
|
|
/* Initialize extensions */
|
|
|
/* See lengthy comment about the inc/dec in
|
|
|
../windows/SDL_windowsopengl.c. */
|
|
@@ -902,7 +904,6 @@ int X11_GL_SetSwapInterval(SDL_VideoDevice *_this, int interval)
|
|
|
X11_GL_GetSwapInterval(_this, ¤tInterval);
|
|
|
_this->gl_data->glXSwapIntervalEXT(display, drawable, currentInterval);
|
|
|
_this->gl_data->glXSwapIntervalEXT(display, drawable, interval);
|
|
|
-
|
|
|
status = 0;
|
|
|
swapinterval = interval;
|
|
|
} else if (_this->gl_data->glXSwapIntervalMESA) {
|
|
@@ -925,6 +926,53 @@ int X11_GL_SetSwapInterval(SDL_VideoDevice *_this, int interval)
|
|
|
return status;
|
|
|
}
|
|
|
|
|
|
+static SDL_GLSwapIntervalTearBehavior CheckSwapIntervalTearBehavior(SDL_VideoDevice *_this, Window drawable, unsigned int current_val, unsigned int current_allow_late)
|
|
|
+{
|
|
|
+ /* Mesa and Nvidia interpret GLX_EXT_swap_control_tear differently, as of this writing, so
|
|
|
+ figure out which behavior we have.
|
|
|
+ Technical details: https://github.com/libsdl-org/SDL/issues/8004#issuecomment-1819603282 */
|
|
|
+ if (_this->gl_data->swap_interval_tear_behavior == SDL_SWAPINTERVALTEAR_UNTESTED) {
|
|
|
+ if (!_this->gl_data->HAS_GLX_EXT_swap_control_tear) {
|
|
|
+ _this->gl_data->swap_interval_tear_behavior = SDL_SWAPINTERVALTEAR_UNKNOWN;
|
|
|
+ } else {
|
|
|
+ Display *display = _this->driverdata->display;
|
|
|
+ unsigned int allow_late_swap_tearing = 22;
|
|
|
+ int original_val = (int) current_val;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * This is a workaround for a bug in NVIDIA drivers. Bug has been reported
|
|
|
+ * and will be fixed in a future release (probably 319.xx).
|
|
|
+ *
|
|
|
+ * There's a bug where glXSetSwapIntervalEXT ignores updates because
|
|
|
+ * it has the wrong value cached. To work around it, we just run a no-op
|
|
|
+ * update to the current value.
|
|
|
+ */
|
|
|
+ _this->gl_data->glXSwapIntervalEXT(display, drawable, current_val);
|
|
|
+
|
|
|
+ /* set it to no swap interval and see how it affects GLX_LATE_SWAPS_TEAR_EXT... */
|
|
|
+ _this->gl_data->glXSwapIntervalEXT(display, drawable, 0);
|
|
|
+ _this->gl_data->glXQueryDrawable(display, drawable, GLX_LATE_SWAPS_TEAR_EXT, &allow_late_swap_tearing);
|
|
|
+
|
|
|
+ if (allow_late_swap_tearing == 0) { /* GLX_LATE_SWAPS_TEAR_EXT says whether late swapping is currently in use */
|
|
|
+ _this->gl_data->swap_interval_tear_behavior = SDL_SWAPINTERVALTEAR_NVIDIA;
|
|
|
+ if (current_allow_late) {
|
|
|
+ original_val = -original_val;
|
|
|
+ }
|
|
|
+ } else if (allow_late_swap_tearing == 1) { /* GLX_LATE_SWAPS_TEAR_EXT says whether the Drawable can use late swapping at all */
|
|
|
+ _this->gl_data->swap_interval_tear_behavior = SDL_SWAPINTERVALTEAR_MESA;
|
|
|
+ } else { /* unexpected outcome! */
|
|
|
+ _this->gl_data->swap_interval_tear_behavior = SDL_SWAPINTERVALTEAR_UNKNOWN;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* set us back to what it was originally... */
|
|
|
+ _this->gl_data->glXSwapIntervalEXT(display, drawable, original_val);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return _this->gl_data->swap_interval_tear_behavior;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
int X11_GL_GetSwapInterval(SDL_VideoDevice *_this, int *interval)
|
|
|
{
|
|
|
if (_this->gl_data->glXSwapIntervalEXT) {
|
|
@@ -935,6 +983,7 @@ int X11_GL_GetSwapInterval(SDL_VideoDevice *_this, int *interval)
|
|
|
unsigned int val = 0;
|
|
|
|
|
|
if (_this->gl_data->HAS_GLX_EXT_swap_control_tear) {
|
|
|
+ allow_late_swap_tearing = 22; /* set this to nonsense. */
|
|
|
_this->gl_data->glXQueryDrawable(display, drawable,
|
|
|
GLX_LATE_SWAPS_TEAR_EXT,
|
|
|
&allow_late_swap_tearing);
|
|
@@ -943,12 +992,21 @@ int X11_GL_GetSwapInterval(SDL_VideoDevice *_this, int *interval)
|
|
|
_this->gl_data->glXQueryDrawable(display, drawable,
|
|
|
GLX_SWAP_INTERVAL_EXT, &val);
|
|
|
|
|
|
- if ((allow_late_swap_tearing) && (val > 0)) {
|
|
|
- *interval = -((int)val);
|
|
|
- return 0;
|
|
|
+ *interval = (int)val;
|
|
|
+
|
|
|
+ switch (CheckSwapIntervalTearBehavior(_this, drawable, val, allow_late_swap_tearing)) {
|
|
|
+ case SDL_SWAPINTERVALTEAR_MESA:
|
|
|
+ *interval = (int)val; /* unsigned int cast to signed that generates negative value if necessary. */
|
|
|
+ break;
|
|
|
+
|
|
|
+ case SDL_SWAPINTERVALTEAR_NVIDIA:
|
|
|
+ default:
|
|
|
+ if ((allow_late_swap_tearing) && (val > 0)) {
|
|
|
+ *interval = -((int)val);
|
|
|
+ }
|
|
|
+ break;
|
|
|
}
|
|
|
|
|
|
- *interval = (int)val;
|
|
|
return 0;
|
|
|
} else if (_this->gl_data->glXGetSwapIntervalMESA) {
|
|
|
int val = _this->gl_data->glXGetSwapIntervalMESA();
|