# HG changeset patch # User Sam Lantinga # Date 1146124756 0 # Node ID 3b2a92126f4d73a0fa2568afa3e9ba7b4b2d9635 # Parent dc219ba4cf4590267d787a0c6e4becccbf79c7b6 Implemented bug #2, 117: Date: Mon, 21 Mar 2005 12:06:14 +0100 From: Per Inge Mathisen Subject: Re: [SDL] Outstanding patches? The patch adds support for setting SDL_GL_SWAP_CONTROL to Windows and X11. In Windows you can also query this enum to check that it is working, or see what the default is - such functionality does not exist in GLX. For more information on the standards implemented: http://oss.sgi.com/projects/ogl-sample/registry/SGI/swap_control.txt http://oss.sgi.com/projects/ogl-sample/registry/EXT/wgl_swap_control.txt diff -r dc219ba4cf45 -r 3b2a92126f4d WhatsNew --- a/WhatsNew Wed Apr 26 23:17:39 2006 +0000 +++ b/WhatsNew Thu Apr 27 07:59:16 2006 +0000 @@ -4,6 +4,8 @@ Version 1.0: 1.2.10: + Added SDL_GL_SWAP_CONTROL to wait for vsync in OpenGL applications. + Added current_w and current_h to the SDL_VideoInfo structure, which is set to the desktop resolution during video intialization, and then set to the current resolution when a video mode is set. diff -r dc219ba4cf45 -r 3b2a92126f4d include/SDL_video.h --- a/include/SDL_video.h Wed Apr 26 23:17:39 2006 +0000 +++ b/include/SDL_video.h Thu Apr 27 07:59:16 2006 +0000 @@ -213,7 +213,8 @@ SDL_GL_ACCUM_ALPHA_SIZE, SDL_GL_STEREO, SDL_GL_MULTISAMPLEBUFFERS, - SDL_GL_MULTISAMPLESAMPLES + SDL_GL_MULTISAMPLESAMPLES, + SDL_GL_SWAP_CONTROL } SDL_GLattr; /* flags for SDL_SetPalette() */ diff -r dc219ba4cf45 -r 3b2a92126f4d src/video/SDL_sysvideo.h --- a/src/video/SDL_sysvideo.h Wed Apr 26 23:17:39 2006 +0000 +++ b/src/video/SDL_sysvideo.h Thu Apr 27 07:59:16 2006 +0000 @@ -292,6 +292,7 @@ int stereo; int multisamplebuffers; int multisamplesamples; + int swap_control; int driver_loaded; char driver_path[256]; void* dll_handle; diff -r dc219ba4cf45 -r 3b2a92126f4d src/video/SDL_video.c --- a/src/video/SDL_video.c Wed Apr 26 23:17:39 2006 +0000 +++ b/src/video/SDL_video.c Thu Apr 27 07:59:16 2006 +0000 @@ -233,6 +233,7 @@ video->gl_config.stereo = 0; video->gl_config.multisamplebuffers = 0; video->gl_config.multisamplesamples = 0; + video->gl_config.swap_control = -1; /* not known, don't set */ /* Initialize the video subsystem */ SDL_memset(&vformat, 0, sizeof(vformat)); @@ -1474,6 +1475,9 @@ case SDL_GL_MULTISAMPLESAMPLES: video->gl_config.multisamplesamples = value; break; + case SDL_GL_SWAP_CONTROL: + video->gl_config.swap_control = value; + break; default: SDL_SetError("Unknown OpenGL attribute"); retval = -1; diff -r dc219ba4cf45 -r 3b2a92126f4d src/video/quartz/SDL_QuartzGL.m --- a/src/video/quartz/SDL_QuartzGL.m Wed Apr 26 23:17:39 2006 +0000 +++ b/src/video/quartz/SDL_QuartzGL.m Thu Apr 27 07:59:16 2006 +0000 @@ -132,6 +132,17 @@ return 0; } + /* Synchronize QZ_GL_SwapBuffers() to vertical retrace. + * (Apple's documentation is not completely clear about what this setting + * exactly does, IMHO - for a detailed explanation see + * http://lists.apple.com/archives/mac-opengl/2006/Jan/msg00080.html ) + */ + if ( this->gl_config.swap_control >= 0 ) { + long value; + value = this->gl_config.swap_control; + [ gl_context setValues: &value forParameter: NSOpenGLCPSwapInterval ]; + } + /* * Wisdom from Apple engineer in reference to UT2003's OpenGL performance: * "You are blowing a couple of the internal OpenGL function caches. This diff -r dc219ba4cf45 -r 3b2a92126f4d src/video/wincommon/SDL_wingl.c --- a/src/video/wincommon/SDL_wingl.c Wed Apr 26 23:17:39 2006 +0000 +++ b/src/video/wincommon/SDL_wingl.c Thu Apr 27 07:59:16 2006 +0000 @@ -177,6 +177,7 @@ int iAttribs[64]; int *iAttr; float fAttribs[1] = { 0 }; + const char *wglext; /* load the gl driver from a default path */ if ( ! this->gl_config.driver_loaded ) { @@ -323,7 +324,25 @@ SDL_SetError("Unable to create GL context"); return(-1); } + if ( WIN_GL_MakeCurrent(this) < 0 ) { + return(-1); + } gl_active = 1; + + /* Vsync control under Windows. Checking glGetString here is + * somewhat a documented and reliable hack - it was originally + * as a feature added by mistake, but since so many people rely + * on it, it will not be removed. strstr should be safe here.*/ + wglext = (const char *)this->glGetString(GL_EXTENSIONS); + if ( !SDL_strstr(wglext, "WGL_EXT_swap_control") ) { + this->gl_data->wglSwapIntervalEXT = NULL; + this->gl_data->wglGetSwapIntervalEXT = NULL; + } + if ( this->gl_config.swap_control >= 0 ) { + if ( this->gl_data->wglSwapIntervalEXT ) { + this->gl_data->wglSwapIntervalEXT(this->gl_config.swap_control); + } + } #else SDL_SetError("WIN driver not configured with OpenGL"); #endif @@ -423,6 +442,12 @@ case SDL_GL_MULTISAMPLESAMPLES: wgl_attrib = WGL_SAMPLES_ARB; break; + case SDL_GL_SWAP_CONTROL: + if ( this->gl_data->wglGetSwapIntervalEXT ) { + return this->gl_data->wglGetSwapIntervalEXT(); + } else { + return -1; + } default: return(-1); } @@ -509,6 +534,8 @@ this->gl_data->wglMakeCurrent = NULL; this->gl_data->wglChoosePixelFormatARB = NULL; this->gl_data->wglGetPixelFormatAttribivARB = NULL; + this->gl_data->wglSwapIntervalEXT = NULL; + this->gl_data->wglGetSwapIntervalEXT = NULL; this->gl_config.dll_handle = NULL; this->gl_config.driver_loaded = 0; @@ -547,6 +574,10 @@ GetProcAddress(handle, "wglDeleteContext"); this->gl_data->wglMakeCurrent = (BOOL (WINAPI *)(HDC, HGLRC)) GetProcAddress(handle, "wglMakeCurrent"); + this->gl_data->wglSwapIntervalEXT = (void (WINAPI *)(int)) + GetProcAddress(handle, "wglSwapIntervalEXT"); + this->gl_data->wglGetSwapIntervalEXT = (int (WINAPI *)(void)) + GetProcAddress(handle, "wglGetSwapIntervalEXT"); if ( (this->gl_data->wglGetProcAddress == NULL) || (this->gl_data->wglCreateContext == NULL) || diff -r dc219ba4cf45 -r 3b2a92126f4d src/video/wincommon/SDL_wingl_c.h --- a/src/video/wincommon/SDL_wingl_c.h Wed Apr 26 23:17:39 2006 +0000 +++ b/src/video/wincommon/SDL_wingl_c.h Thu Apr 27 07:59:16 2006 +0000 @@ -53,6 +53,8 @@ UINT nAttributes, const int *piAttributes, int *piValues); + void (WINAPI *wglSwapIntervalEXT)(int interval); + int (WINAPI *wglGetSwapIntervalEXT)(void); #endif /* SDL_VIDEO_OPENGL */ }; diff -r dc219ba4cf45 -r 3b2a92126f4d src/video/x11/SDL_x11gl.c --- a/src/video/x11/SDL_x11gl.c Wed Apr 26 23:17:39 2006 +0000 +++ b/src/video/x11/SDL_x11gl.c Thu Apr 27 07:59:16 2006 +0000 @@ -205,18 +205,39 @@ { int retval; #if SDL_VIDEO_OPENGL_GLX + const char *glXext; + /* We do this to create a clean separation between X and GLX errors. */ XSync( SDL_Display, False ); glx_context = this->gl_data->glXCreateContext(GFX_Display, glx_visualinfo, NULL, True); XSync( GFX_Display, False ); - if (glx_context == NULL) { + if ( glx_context == NULL ) { SDL_SetError("Could not create GL context"); - return -1; + return(-1); + } + if ( X11_GL_MakeCurrent(this) < 0 ) { + return(-1); + } + gl_active = 1; + + /* The use of strstr here should be safe */ + glXext = this->gl_data->glXQueryExtensionsString(GFX_Display, DefaultScreen(GFX_Display)); + if ( !SDL_strstr(glXext, "SGI_swap_control") ) { + this->gl_data->glXSwapIntervalSGI = NULL; } - - gl_active = 1; + if ( !SDL_strstr(glXext, "GLX_MESA_swap_control") ) { + this->gl_data->glXSwapIntervalMESA = NULL; + this->gl_data->glXGetSwapIntervalMESA = NULL; + } + if ( this->gl_config.swap_control >= 0 ) { + if ( this->gl_data->glXSwapIntervalMESA ) { + this->gl_data->glXSwapIntervalMESA(this->gl_config.swap_control); + } else if ( this->gl_data->glXSwapIntervalSGI ) { + this->gl_data->glXSwapIntervalSGI(this->gl_config.swap_control); + } + } #else SDL_SetError("X11 driver not configured with OpenGL"); #endif @@ -319,6 +340,13 @@ case SDL_GL_MULTISAMPLESAMPLES: glx_attrib = GLX_SAMPLES_ARB; break; + case SDL_GL_SWAP_CONTROL: + if ( this->gl_data->glXGetSwapIntervalMESA ) { + return this->gl_data->glXGetSwapIntervalMESA(); + } else { + return -1 /*(this->gl_config.swap_control > 0)*/; + } + break; default: return(-1); } @@ -348,6 +376,9 @@ this->gl_data->glXDestroyContext = NULL; this->gl_data->glXMakeCurrent = NULL; this->gl_data->glXSwapBuffers = NULL; + this->gl_data->glXSwapIntervalSGI = NULL; + this->gl_data->glXSwapIntervalMESA = NULL; + this->gl_data->glXGetSwapIntervalMESA = NULL; this->gl_config.dll_handle = NULL; this->gl_config.driver_loaded = 0; @@ -400,7 +431,12 @@ (int (*)(Display *, XVisualInfo *, int, int *)) SDL_LoadFunction(handle, "glXGetConfig"); this->gl_data->glXQueryExtensionsString = (const char *(*)(Display *, int)) SDL_LoadFunction(handle, "glXQueryExtensionsString"); - + this->gl_data->glXSwapIntervalSGI = + (int (*)(int)) SDL_LoadFunction(handle, "glXSwapIntervalSGI"); + this->gl_data->glXSwapIntervalMESA = + (GLint (*)(unsigned)) SDL_LoadFunction(handle, "glXSwapIntervalMESA"); + this->gl_data->glXGetSwapIntervalMESA = + (GLint (*)(void)) SDL_LoadFunction(handle, "glXGetSwapIntervalMESA"); if ( (this->gl_data->glXChooseVisual == NULL) || (this->gl_data->glXCreateContext == NULL) || diff -r dc219ba4cf45 -r 3b2a92126f4d src/video/x11/SDL_x11gl_c.h --- a/src/video/x11/SDL_x11gl_c.h Wed Apr 26 23:17:39 2006 +0000 +++ b/src/video/x11/SDL_x11gl_c.h Thu Apr 27 07:59:16 2006 +0000 @@ -71,7 +71,10 @@ ( Display* dpy, int screen ); - + int (*glXSwapIntervalSGI) ( int interval ); + GLint (*glXSwapIntervalMESA) ( unsigned interval ); + GLint (*glXGetSwapIntervalMESA) ( void ); + #endif /* SDL_VIDEO_OPENGL_GLX */ }; diff -r dc219ba4cf45 -r 3b2a92126f4d test/testgl.c --- a/test/testgl.c Wed Apr 26 23:17:39 2006 +0000 +++ b/test/testgl.c Thu Apr 27 07:59:16 2006 +0000 @@ -445,7 +445,7 @@ } int RunGLTest( int argc, char* argv[], - int logo, int logocursor, int slowly, int bpp, float gamma, int noframe, int fsaa ) + int logo, int logocursor, int slowly, int bpp, float gamma, int noframe, int fsaa, int sync ) { int i; int rgb_size[3]; @@ -531,6 +531,11 @@ SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 1 ); SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, fsaa ); } + if ( sync ) { + SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, 1 ); + } else { + SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, 0 ); + } if ( SDL_SetVideoMode( w, h, bpp, video_flags ) == NULL ) { fprintf(stderr, "Couldn't set GL mode: %s\n", SDL_GetError()); SDL_Quit(); @@ -557,9 +562,13 @@ printf( "SDL_GL_DOUBLEBUFFER: requested 1, got %d\n", value ); if ( fsaa ) { SDL_GL_GetAttribute( SDL_GL_MULTISAMPLEBUFFERS, &value ); - printf( "SDL_GL_MULTISAMPLEBUFFERS: requested 1, got %d\n", value ); + printf("SDL_GL_MULTISAMPLEBUFFERS: requested 1, got %d\n", value ); SDL_GL_GetAttribute( SDL_GL_MULTISAMPLESAMPLES, &value ); - printf( "SDL_GL_MULTISAMPLESAMPLES: requested %d, got %d\n", fsaa, value ); + printf("SDL_GL_MULTISAMPLESAMPLES: requested %d, got %d\n", fsaa, value ); + } + if ( sync ) { + SDL_GL_GetAttribute( SDL_GL_SWAP_CONTROL, &value ); + printf( "SDL_GL_SWAP_CONTROL: requested 1, got %d\n", value ); } /* Set the window manager title bar */ @@ -770,6 +779,7 @@ float gamma = 0.0; int noframe = 0; int fsaa = 0; + int sync = 0; logo = 0; slowly = 0; @@ -804,6 +814,9 @@ if ( strcmp(argv[i], "-fsaa") == 0 ) { ++fsaa; } + if ( strcmp(argv[i], "-sync") == 0 ) { + ++sync; + } if ( strncmp(argv[i], "-h", 2) == 0 ) { printf( "Usage: %s [-twice] [-logo] [-logocursor] [-slow] [-bpp n] [-gamma n] [-noframe] [-fsaa] [-fullscreen]\n", @@ -812,7 +825,7 @@ } } for ( i=0; i