Implemented bug #2, 117:
authorSam Lantinga <slouken@libsdl.org>
Thu, 27 Apr 2006 07:59:16 +0000
changeset 17363b2a92126f4d
parent 1652 dc219ba4cf45
child 1737 eacc5bc01d1c
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
WhatsNew
include/SDL_video.h
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/quartz/SDL_QuartzGL.m
src/video/wincommon/SDL_wingl.c
src/video/wincommon/SDL_wingl_c.h
src/video/x11/SDL_x11gl.c
src/video/x11/SDL_x11gl_c.h
test/testgl.c
     1.1 --- a/WhatsNew	Wed Apr 26 23:17:39 2006 +0000
     1.2 +++ b/WhatsNew	Thu Apr 27 07:59:16 2006 +0000
     1.3 @@ -4,6 +4,8 @@
     1.4  Version 1.0:
     1.5  
     1.6  1.2.10:
     1.7 +	Added SDL_GL_SWAP_CONTROL to wait for vsync in OpenGL applications.
     1.8 +
     1.9  	Added current_w and current_h to the SDL_VideoInfo structure,
    1.10  	which is set to the desktop resolution during video intialization,
    1.11  	and then set to the current resolution when a video mode is set.
     2.1 --- a/include/SDL_video.h	Wed Apr 26 23:17:39 2006 +0000
     2.2 +++ b/include/SDL_video.h	Thu Apr 27 07:59:16 2006 +0000
     2.3 @@ -213,7 +213,8 @@
     2.4      SDL_GL_ACCUM_ALPHA_SIZE,
     2.5      SDL_GL_STEREO,
     2.6      SDL_GL_MULTISAMPLEBUFFERS,
     2.7 -    SDL_GL_MULTISAMPLESAMPLES
     2.8 +    SDL_GL_MULTISAMPLESAMPLES,
     2.9 +    SDL_GL_SWAP_CONTROL
    2.10  } SDL_GLattr;
    2.11  
    2.12  /* flags for SDL_SetPalette() */
     3.1 --- a/src/video/SDL_sysvideo.h	Wed Apr 26 23:17:39 2006 +0000
     3.2 +++ b/src/video/SDL_sysvideo.h	Thu Apr 27 07:59:16 2006 +0000
     3.3 @@ -292,6 +292,7 @@
     3.4  		int stereo;
     3.5  		int multisamplebuffers;
     3.6  		int multisamplesamples;
     3.7 +		int swap_control;
     3.8  		int driver_loaded;
     3.9  		char driver_path[256];
    3.10  		void* dll_handle;
     4.1 --- a/src/video/SDL_video.c	Wed Apr 26 23:17:39 2006 +0000
     4.2 +++ b/src/video/SDL_video.c	Thu Apr 27 07:59:16 2006 +0000
     4.3 @@ -233,6 +233,7 @@
     4.4  	video->gl_config.stereo = 0;
     4.5  	video->gl_config.multisamplebuffers = 0;
     4.6  	video->gl_config.multisamplesamples = 0;
     4.7 +	video->gl_config.swap_control = -1; /* not known, don't set */
     4.8  	
     4.9  	/* Initialize the video subsystem */
    4.10  	SDL_memset(&vformat, 0, sizeof(vformat));
    4.11 @@ -1474,6 +1475,9 @@
    4.12  		case SDL_GL_MULTISAMPLESAMPLES:
    4.13  			video->gl_config.multisamplesamples = value;
    4.14  			break;
    4.15 +		case SDL_GL_SWAP_CONTROL:
    4.16 +			video->gl_config.swap_control = value;
    4.17 +			break;
    4.18  		default:
    4.19  			SDL_SetError("Unknown OpenGL attribute");
    4.20  			retval = -1;
     5.1 --- a/src/video/quartz/SDL_QuartzGL.m	Wed Apr 26 23:17:39 2006 +0000
     5.2 +++ b/src/video/quartz/SDL_QuartzGL.m	Thu Apr 27 07:59:16 2006 +0000
     5.3 @@ -132,6 +132,17 @@
     5.4          return 0;
     5.5      }
     5.6  
     5.7 +    /* Synchronize QZ_GL_SwapBuffers() to vertical retrace.
     5.8 +     * (Apple's documentation is not completely clear about what this setting
     5.9 +     * exactly does, IMHO - for a detailed explanation see
    5.10 +     * http://lists.apple.com/archives/mac-opengl/2006/Jan/msg00080.html )
    5.11 +     */
    5.12 +    if ( this->gl_config.swap_control >= 0 ) {
    5.13 +        long value;
    5.14 +        value = this->gl_config.swap_control;
    5.15 +        [ gl_context setValues: &value forParameter: NSOpenGLCPSwapInterval ];
    5.16 +    }
    5.17 +
    5.18      /*
    5.19       * Wisdom from Apple engineer in reference to UT2003's OpenGL performance:
    5.20       *  "You are blowing a couple of the internal OpenGL function caches. This
     6.1 --- a/src/video/wincommon/SDL_wingl.c	Wed Apr 26 23:17:39 2006 +0000
     6.2 +++ b/src/video/wincommon/SDL_wingl.c	Thu Apr 27 07:59:16 2006 +0000
     6.3 @@ -177,6 +177,7 @@
     6.4  	int iAttribs[64];
     6.5  	int *iAttr;
     6.6  	float fAttribs[1] = { 0 };
     6.7 +	const char *wglext;
     6.8  
     6.9  	/* load the gl driver from a default path */
    6.10  	if ( ! this->gl_config.driver_loaded ) {
    6.11 @@ -323,7 +324,25 @@
    6.12  		SDL_SetError("Unable to create GL context");
    6.13  		return(-1);
    6.14  	}
    6.15 +	if ( WIN_GL_MakeCurrent(this) < 0 ) {
    6.16 +		return(-1);
    6.17 +	}
    6.18  	gl_active = 1;
    6.19 +
    6.20 +	/* Vsync control under Windows.  Checking glGetString here is
    6.21 +	 * somewhat a documented and reliable hack - it was originally
    6.22 +	 * as a feature added by mistake, but since so many people rely
    6.23 +	 * on it, it will not be removed.  strstr should be safe here.*/
    6.24 +	wglext = (const char *)this->glGetString(GL_EXTENSIONS);
    6.25 +	if ( !SDL_strstr(wglext, "WGL_EXT_swap_control") ) {
    6.26 +		this->gl_data->wglSwapIntervalEXT = NULL;
    6.27 +		this->gl_data->wglGetSwapIntervalEXT = NULL;
    6.28 +	}
    6.29 +	if ( this->gl_config.swap_control >= 0 ) {
    6.30 +		if ( this->gl_data->wglSwapIntervalEXT ) {
    6.31 +			this->gl_data->wglSwapIntervalEXT(this->gl_config.swap_control);
    6.32 +		}
    6.33 +	}
    6.34  #else
    6.35  	SDL_SetError("WIN driver not configured with OpenGL");
    6.36  #endif
    6.37 @@ -423,6 +442,12 @@
    6.38  		    case SDL_GL_MULTISAMPLESAMPLES:
    6.39  			wgl_attrib = WGL_SAMPLES_ARB;
    6.40  			break;
    6.41 +		    case SDL_GL_SWAP_CONTROL:
    6.42 +			if ( this->gl_data->wglGetSwapIntervalEXT ) {
    6.43 +				return this->gl_data->wglGetSwapIntervalEXT();
    6.44 +			} else {
    6.45 +				return -1;
    6.46 +			}
    6.47  		    default:
    6.48  			return(-1);
    6.49  		}
    6.50 @@ -509,6 +534,8 @@
    6.51  		this->gl_data->wglMakeCurrent = NULL;
    6.52  		this->gl_data->wglChoosePixelFormatARB = NULL;
    6.53  		this->gl_data->wglGetPixelFormatAttribivARB = NULL;
    6.54 +		this->gl_data->wglSwapIntervalEXT = NULL;
    6.55 +		this->gl_data->wglGetSwapIntervalEXT = NULL;
    6.56  
    6.57  		this->gl_config.dll_handle = NULL;
    6.58  		this->gl_config.driver_loaded = 0;
    6.59 @@ -547,6 +574,10 @@
    6.60  		GetProcAddress(handle, "wglDeleteContext");
    6.61  	this->gl_data->wglMakeCurrent = (BOOL (WINAPI *)(HDC, HGLRC))
    6.62  		GetProcAddress(handle, "wglMakeCurrent");
    6.63 +	this->gl_data->wglSwapIntervalEXT = (void (WINAPI *)(int))
    6.64 +		GetProcAddress(handle, "wglSwapIntervalEXT");
    6.65 +	this->gl_data->wglGetSwapIntervalEXT = (int (WINAPI *)(void))
    6.66 +		GetProcAddress(handle, "wglGetSwapIntervalEXT");
    6.67  
    6.68  	if ( (this->gl_data->wglGetProcAddress == NULL) ||
    6.69  	     (this->gl_data->wglCreateContext == NULL) ||
     7.1 --- a/src/video/wincommon/SDL_wingl_c.h	Wed Apr 26 23:17:39 2006 +0000
     7.2 +++ b/src/video/wincommon/SDL_wingl_c.h	Thu Apr 27 07:59:16 2006 +0000
     7.3 @@ -53,6 +53,8 @@
     7.4                                                  UINT nAttributes, 
     7.5                                                  const int *piAttributes,
     7.6                                                  int *piValues);
     7.7 +    void (WINAPI *wglSwapIntervalEXT)(int interval);
     7.8 +    int (WINAPI *wglGetSwapIntervalEXT)(void);
     7.9  #endif /* SDL_VIDEO_OPENGL */
    7.10  };
    7.11  
     8.1 --- a/src/video/x11/SDL_x11gl.c	Wed Apr 26 23:17:39 2006 +0000
     8.2 +++ b/src/video/x11/SDL_x11gl.c	Thu Apr 27 07:59:16 2006 +0000
     8.3 @@ -205,18 +205,39 @@
     8.4  {
     8.5  	int retval;
     8.6  #if SDL_VIDEO_OPENGL_GLX
     8.7 +	const char *glXext;
     8.8 +
     8.9  	/* We do this to create a clean separation between X and GLX errors. */
    8.10  	XSync( SDL_Display, False );
    8.11  	glx_context = this->gl_data->glXCreateContext(GFX_Display, 
    8.12  				     glx_visualinfo, NULL, True);
    8.13  	XSync( GFX_Display, False );
    8.14  
    8.15 -	if (glx_context == NULL) {
    8.16 +	if ( glx_context == NULL ) {
    8.17  		SDL_SetError("Could not create GL context");
    8.18 -		return -1;
    8.19 +		return(-1);
    8.20  	}
    8.21 +	if ( X11_GL_MakeCurrent(this) < 0 ) {
    8.22 +		return(-1);
    8.23 +	}
    8.24 +	gl_active = 1;
    8.25  
    8.26 -	gl_active = 1;
    8.27 +	/* The use of strstr here should be safe */
    8.28 +	glXext = this->gl_data->glXQueryExtensionsString(GFX_Display, DefaultScreen(GFX_Display));
    8.29 +	if ( !SDL_strstr(glXext, "SGI_swap_control") ) {
    8.30 +		this->gl_data->glXSwapIntervalSGI = NULL;
    8.31 +	}
    8.32 +	if ( !SDL_strstr(glXext, "GLX_MESA_swap_control") ) {
    8.33 +		this->gl_data->glXSwapIntervalMESA = NULL;
    8.34 +		this->gl_data->glXGetSwapIntervalMESA = NULL;
    8.35 +	}
    8.36 +	if ( this->gl_config.swap_control >= 0 ) {
    8.37 +		if ( this->gl_data->glXSwapIntervalMESA ) {
    8.38 +			this->gl_data->glXSwapIntervalMESA(this->gl_config.swap_control);
    8.39 +		} else if ( this->gl_data->glXSwapIntervalSGI ) {
    8.40 +			this->gl_data->glXSwapIntervalSGI(this->gl_config.swap_control);
    8.41 +		}
    8.42 +	}
    8.43  #else
    8.44  	SDL_SetError("X11 driver not configured with OpenGL");
    8.45  #endif
    8.46 @@ -319,6 +340,13 @@
    8.47   	    case SDL_GL_MULTISAMPLESAMPLES:
    8.48   		glx_attrib = GLX_SAMPLES_ARB;
    8.49   		break;
    8.50 +	    case SDL_GL_SWAP_CONTROL:
    8.51 +		if ( this->gl_data->glXGetSwapIntervalMESA ) {
    8.52 +			return this->gl_data->glXGetSwapIntervalMESA();
    8.53 +		} else {
    8.54 +			return -1 /*(this->gl_config.swap_control > 0)*/;
    8.55 +		}
    8.56 +		break;
    8.57  	    default:
    8.58  		return(-1);
    8.59  	}
    8.60 @@ -348,6 +376,9 @@
    8.61  		this->gl_data->glXDestroyContext = NULL;
    8.62  		this->gl_data->glXMakeCurrent = NULL;
    8.63  		this->gl_data->glXSwapBuffers = NULL;
    8.64 +		this->gl_data->glXSwapIntervalSGI = NULL;
    8.65 +		this->gl_data->glXSwapIntervalMESA = NULL;
    8.66 +		this->gl_data->glXGetSwapIntervalMESA = NULL;
    8.67  
    8.68  		this->gl_config.dll_handle = NULL;
    8.69  		this->gl_config.driver_loaded = 0;
    8.70 @@ -400,7 +431,12 @@
    8.71  		(int (*)(Display *, XVisualInfo *, int, int *)) SDL_LoadFunction(handle, "glXGetConfig");
    8.72  	this->gl_data->glXQueryExtensionsString =
    8.73  		(const char *(*)(Display *, int)) SDL_LoadFunction(handle, "glXQueryExtensionsString");
    8.74 -	
    8.75 +	this->gl_data->glXSwapIntervalSGI =
    8.76 +		(int (*)(int)) SDL_LoadFunction(handle, "glXSwapIntervalSGI");
    8.77 +	this->gl_data->glXSwapIntervalMESA =
    8.78 +		(GLint (*)(unsigned)) SDL_LoadFunction(handle, "glXSwapIntervalMESA");
    8.79 +	this->gl_data->glXGetSwapIntervalMESA =
    8.80 +		(GLint (*)(void)) SDL_LoadFunction(handle, "glXGetSwapIntervalMESA");
    8.81  
    8.82  	if ( (this->gl_data->glXChooseVisual == NULL) || 
    8.83  	     (this->gl_data->glXCreateContext == NULL) ||
     9.1 --- a/src/video/x11/SDL_x11gl_c.h	Wed Apr 26 23:17:39 2006 +0000
     9.2 +++ b/src/video/x11/SDL_x11gl_c.h	Thu Apr 27 07:59:16 2006 +0000
     9.3 @@ -71,7 +71,10 @@
     9.4  	    ( Display* dpy,
     9.5  	      int screen );
     9.6  
     9.7 -    
     9.8 +    int (*glXSwapIntervalSGI) ( int interval );
     9.9 +    GLint (*glXSwapIntervalMESA) ( unsigned interval );
    9.10 +    GLint (*glXGetSwapIntervalMESA) ( void );
    9.11 +
    9.12  #endif /* SDL_VIDEO_OPENGL_GLX */
    9.13  };
    9.14  
    10.1 --- a/test/testgl.c	Wed Apr 26 23:17:39 2006 +0000
    10.2 +++ b/test/testgl.c	Thu Apr 27 07:59:16 2006 +0000
    10.3 @@ -445,7 +445,7 @@
    10.4  }
    10.5  
    10.6  int RunGLTest( int argc, char* argv[],
    10.7 -               int logo, int logocursor, int slowly, int bpp, float gamma, int noframe, int fsaa )
    10.8 +               int logo, int logocursor, int slowly, int bpp, float gamma, int noframe, int fsaa, int sync )
    10.9  {
   10.10  	int i;
   10.11  	int rgb_size[3];
   10.12 @@ -531,6 +531,11 @@
   10.13  		SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 1 );
   10.14  		SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, fsaa );
   10.15  	}
   10.16 +	if ( sync ) {
   10.17 +		SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, 1 );
   10.18 +	} else {
   10.19 +		SDL_GL_SetAttribute( SDL_GL_SWAP_CONTROL, 0 );
   10.20 +	}
   10.21  	if ( SDL_SetVideoMode( w, h, bpp, video_flags ) == NULL ) {
   10.22  		fprintf(stderr, "Couldn't set GL mode: %s\n", SDL_GetError());
   10.23  		SDL_Quit();
   10.24 @@ -557,9 +562,13 @@
   10.25  	printf( "SDL_GL_DOUBLEBUFFER: requested 1, got %d\n", value );
   10.26  	if ( fsaa ) {
   10.27  		SDL_GL_GetAttribute( SDL_GL_MULTISAMPLEBUFFERS, &value );
   10.28 -		printf( "SDL_GL_MULTISAMPLEBUFFERS: requested 1, got %d\n", value );
   10.29 +		printf("SDL_GL_MULTISAMPLEBUFFERS: requested 1, got %d\n", value );
   10.30  		SDL_GL_GetAttribute( SDL_GL_MULTISAMPLESAMPLES, &value );
   10.31 -		printf( "SDL_GL_MULTISAMPLESAMPLES: requested %d, got %d\n", fsaa, value );
   10.32 +		printf("SDL_GL_MULTISAMPLESAMPLES: requested %d, got %d\n", fsaa, value );
   10.33 +	}
   10.34 +	if ( sync ) {
   10.35 +		SDL_GL_GetAttribute( SDL_GL_SWAP_CONTROL, &value );
   10.36 +		printf( "SDL_GL_SWAP_CONTROL: requested 1, got %d\n", value );
   10.37  	}
   10.38  
   10.39  	/* Set the window manager title bar */
   10.40 @@ -770,6 +779,7 @@
   10.41  	float gamma = 0.0;
   10.42  	int noframe = 0;
   10.43  	int fsaa = 0;
   10.44 +	int sync = 0;
   10.45  
   10.46  	logo = 0;
   10.47  	slowly = 0;
   10.48 @@ -804,6 +814,9 @@
   10.49  		if ( strcmp(argv[i], "-fsaa") == 0 ) {
   10.50   		       ++fsaa;
   10.51  		}
   10.52 +		if ( strcmp(argv[i], "-sync") == 0 ) {
   10.53 + 		       ++sync;
   10.54 +		}
   10.55  		if ( strncmp(argv[i], "-h", 2) == 0 ) {
   10.56   		       printf(
   10.57  "Usage: %s [-twice] [-logo] [-logocursor] [-slow] [-bpp n] [-gamma n] [-noframe] [-fsaa] [-fullscreen]\n",
   10.58 @@ -812,7 +825,7 @@
   10.59  		}
   10.60  	}
   10.61  	for ( i=0; i<numtests; ++i ) {
   10.62 - 		RunGLTest(argc, argv, logo, logocursor, slowly, bpp, gamma, noframe, fsaa);
   10.63 + 		RunGLTest(argc, argv, logo, logocursor, slowly, bpp, gamma, noframe, fsaa, sync);
   10.64  	}
   10.65  	return 0;
   10.66  }