SDL-trunk-1.3-merge-1 SDL-1.3
authorSam Lantinga <slouken@libsdl.org>
Thu, 27 Apr 2006 09:09:48 +0000
branchSDL-1.3
changeset 1656 96c2f89cc7e1
parent 1655 59227394023d
child 1657 5b0805ceb50f
SDL-trunk-1.3-merge-1
WhatsNew
include/SDL_video.h
src/video/SDL_sysvideo.h
src/video/SDL_video.c
src/video/maccommon/SDL_macgl.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
--- a/WhatsNew	Thu Apr 27 05:49:51 2006 +0000
+++ b/WhatsNew	Thu Apr 27 09:09:48 2006 +0000
@@ -4,6 +4,10 @@
 Version 1.0:
 
 1.2.10:
+	Added SDL_GL_SWAP_CONTROL to wait for vsync in OpenGL applications.
+
+	Added SDL_GL_ACCELERATED_VISUAL to guarantee hardware acceleration.
+
 	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.
--- a/include/SDL_video.h	Thu Apr 27 05:49:51 2006 +0000
+++ b/include/SDL_video.h	Thu Apr 27 09:09:48 2006 +0000
@@ -213,7 +213,9 @@
     SDL_GL_ACCUM_ALPHA_SIZE,
     SDL_GL_STEREO,
     SDL_GL_MULTISAMPLEBUFFERS,
-    SDL_GL_MULTISAMPLESAMPLES
+    SDL_GL_MULTISAMPLESAMPLES,
+    SDL_GL_ACCELERATED_VISUAL,
+    SDL_GL_SWAP_CONTROL
 } SDL_GLattr;
 
 /* flags for SDL_SetPalette() */
--- a/src/video/SDL_sysvideo.h	Thu Apr 27 05:49:51 2006 +0000
+++ b/src/video/SDL_sysvideo.h	Thu Apr 27 09:09:48 2006 +0000
@@ -292,6 +292,8 @@
 		int stereo;
 		int multisamplebuffers;
 		int multisamplesamples;
+		int accelerated;
+		int swap_control;
 		int driver_loaded;
 		char driver_path[256];
 		void* dll_handle;
--- a/src/video/SDL_video.c	Thu Apr 27 05:49:51 2006 +0000
+++ b/src/video/SDL_video.c	Thu Apr 27 09:09:48 2006 +0000
@@ -229,6 +229,8 @@
 	video->gl_config.stereo = 0;
 	video->gl_config.multisamplebuffers = 0;
 	video->gl_config.multisamplesamples = 0;
+	video->gl_config.accelerated = -1; /* not known, don't set */
+	video->gl_config.swap_control = -1; /* not known, don't set */
 	
 	/* Initialize the video subsystem */
 	SDL_memset(&vformat, 0, sizeof(vformat));
@@ -1393,6 +1395,12 @@
 		case SDL_GL_MULTISAMPLESAMPLES:
 			video->gl_config.multisamplesamples = value;
 			break;
+		case SDL_GL_ACCELERATED_VISUAL:
+			video->gl_config.accelerated = value;
+			break;
+		case SDL_GL_SWAP_CONTROL:
+			video->gl_config.swap_control = value;
+			break;
 		default:
 			SDL_SetError("Unknown OpenGL attribute");
 			retval = -1;
--- a/src/video/maccommon/SDL_macgl.c	Thu Apr 27 05:49:51 2006 +0000
+++ b/src/video/maccommon/SDL_macgl.c	Thu Apr 27 09:09:48 2006 +0000
@@ -34,7 +34,7 @@
 #if SDL_VIDEO_OPENGL
 	AGLPixelFormat format;
    	int i = 0;
-	GLint attributes [ 24 ]; /* 24 is max possible in this setup */
+	GLint attributes [ 26 ]; /* 26 is max possible in this setup */
 	GLboolean noerr;
    
 	/* load the gl driver from a default path */
@@ -95,6 +95,11 @@
 		attributes[i++] = this->gl_config.multisamplesamples;
 	}	
 #endif
+	if ( this->gl_config.accelerated > 0 ) {
+		attributes[i++] = AGL_ACCELERATED;
+		attributes[i++] = AGL_NO_RECOVERY;
+	}
+
 	attributes[i++] = AGL_ALL_RENDERERS;
 	attributes[i]	= AGL_NONE;
 
--- a/src/video/quartz/SDL_QuartzGL.m	Thu Apr 27 05:49:51 2006 +0000
+++ b/src/video/quartz/SDL_QuartzGL.m	Thu Apr 27 09:09:48 2006 +0000
@@ -112,6 +112,10 @@
         attr[i++] = NSOpenGLPFANoRecovery;
     }
 
+    if ( this->gl_config.accelerated > 0 ) {
+        attr[i++] = NSOpenGLPFAAccelerated;
+    }
+
     attr[i++] = NSOpenGLPFAScreenMask;
     attr[i++] = CGDisplayIDToOpenGLDisplayMask (display_id);
     attr[i] = 0;
@@ -132,6 +136,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
@@ -231,8 +246,25 @@
             glGetIntegerv (GL_ALPHA_BITS, &component); bits += component;
 
             *value = bits;
+            return 0;
         }
-        return 0;
+        case SDL_GL_ACCELERATED_VISUAL:
+        {
+            long val;
+	    /* FIXME: How do we get this information here?
+            [fmt getValues: &val forAttribute: NSOpenGLPFAAccelerated attr forVirtualScreen: 0];
+	    */
+	    val = (this->gl_config.accelerated != 0);;
+            *value = val;
+            return 0;
+        }
+        case SDL_GL_SWAP_CONTROL:
+        {
+            long val;
+            [ gl_context getValues: &val forParameter: NSOpenGLCPSwapInterval ];
+            *value = val;
+            return 0;
+        }
     }
 
     glGetIntegerv (attr, (GLint *)value);
--- a/src/video/wincommon/SDL_wingl.c	Thu Apr 27 05:49:51 2006 +0000
+++ b/src/video/wincommon/SDL_wingl.c	Thu Apr 27 09:09:48 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 ) {
@@ -289,6 +290,11 @@
 			*iAttr++ = this->gl_config.multisamplesamples;
 		}
 
+		if ( this->gl_config.accelerated >= 0 ) {
+			*iAttr++ = WGL_ACCELERATION_ARB;
+			*iAttr++ = (this->gl_config.accelerated ? WGL_GENERIC_ACCELERATION_ARB : WGL_NO_ACCELERATION_ARB);
+		}
+
 		*iAttr = 0;
 
 		/* Choose and set the closest available pixel format */
@@ -323,7 +329,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 +447,22 @@
 		    case SDL_GL_MULTISAMPLESAMPLES:
 			wgl_attrib = WGL_SAMPLES_ARB;
 			break;
+		    case SDL_GL_ACCELERATED_VISUAL:
+			wgl_attrib = WGL_ACCELERATION_ARB;
+			this->gl_data->wglGetPixelFormatAttribivARB(GL_hdc, pixel_format, 0, 1, &wgl_attrib, value);
+			if ( *value == WGL_NO_ACCELERATION_ARB ) {
+				*value = SDL_FALSE;
+			} else {
+				*value = SDL_TRUE;
+			}
+			return 0;
+			break;
+		    case SDL_GL_SWAP_CONTROL:
+			if ( this->gl_data->wglGetSwapIntervalEXT ) {
+				return this->gl_data->wglGetSwapIntervalEXT();
+			} else {
+				return -1;
+			}
 		    default:
 			return(-1);
 		}
@@ -509,6 +549,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 +589,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) ||
--- a/src/video/wincommon/SDL_wingl_c.h	Thu Apr 27 05:49:51 2006 +0000
+++ b/src/video/wincommon/SDL_wingl_c.h	Thu Apr 27 09:09:48 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 */
 };
 
--- a/src/video/x11/SDL_x11gl.c	Thu Apr 27 05:49:51 2006 +0000
+++ b/src/video/x11/SDL_x11gl.c	Thu Apr 27 09:09:48 2006 +0000
@@ -43,6 +43,47 @@
 #define GLX_SAMPLES_ARB                    100001
 #endif
 
+#ifndef GLX_EXT_visual_rating
+#define GLX_EXT_visual_rating
+#define GLX_VISUAL_CAVEAT_EXT              0x20
+#define GLX_SLOW_VISUAL_EXT                0x8001
+#define GLX_NON_CONFORMANT_VISUAL_EXT      0x800D
+#endif
+
+#if SDL_VIDEO_OPENGL_GLX
+static int glXExtensionSupported(_THIS, const char *extension)
+{
+	const char *extensions;
+	const char *start;
+	const char *where, *terminator;
+
+	/* Extension names should not have spaces. */
+	where = SDL_strchr(extension, ' ');
+	if ( where || *extension == '\0' ) {
+	      return 0;
+	}
+
+	extensions = this->gl_data->glXQueryExtensionsString(GFX_Display,SDL_Screen);
+	/* It takes a bit of care to be fool-proof about parsing the
+	 * OpenGL extensions string. Don't be fooled by sub-strings, etc.
+	 */
+	
+	start = extensions;
+	
+	for (;;) {
+		where = SDL_strstr(start, extension);
+		if (!where) break;
+		
+		terminator = where + strlen(extension);
+		if (where == start || *(where - 1) == ' ')
+	        if (*terminator == ' ' || *terminator == '\0') return 1;
+						  
+		start = terminator;
+	}
+	return 0;
+}
+#endif /* SDL_VIDEO_OPENGL_GLX */
+
 XVisualInfo *X11_GL_GetVisual(_THIS)
 {
 #if SDL_VIDEO_OPENGL_GLX
@@ -138,6 +179,12 @@
 		attribs[i++] = this->gl_config.multisamplesamples;
 	}
 
+	if( this->gl_config.accelerated >= 0 &&
+	    glXExtensionSupported(this, "GLX_EXT_visual_rating") ) {
+		attribs[i++] = GLX_VISUAL_CAVEAT_EXT;
+		attribs[i++] = this->gl_config.accelerated ? GLX_NONE : GLX_DONT_CARE;
+	}
+
 #ifdef GLX_DIRECT_COLOR /* Try for a DirectColor visual for gamma support */
 	if ( !SDL_getenv("SDL_VIDEO_X11_NODIRECTCOLOR") ) {
 		attribs[i++] = GLX_X_VISUAL_TYPE;
@@ -205,18 +252,36 @@
 {
 	int retval;
 #if SDL_VIDEO_OPENGL_GLX
+
 	/* 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;
+
+	if ( !glXExtensionSupported(this, "SGI_swap_control") ) {
+		this->gl_data->glXSwapIntervalSGI = NULL;
 	}
-
-	gl_active = 1;
+	if ( !glXExtensionSupported(this, "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 +384,27 @@
  	    case SDL_GL_MULTISAMPLESAMPLES:
  		glx_attrib = GLX_SAMPLES_ARB;
  		break;
+ 	    case SDL_GL_ACCELERATED_VISUAL:
+		if ( glXExtensionSupported(this, "GLX_EXT_visual_rating") ) {
+			glx_attrib = GLX_VISUAL_CAVEAT_EXT;
+			retval = this->gl_data->glXGetConfig(GFX_Display, glx_visualinfo, glx_attrib, value);
+			if ( *value == GLX_SLOW_VISUAL_EXT ) {
+				*value = SDL_FALSE;
+			} else {
+				*value = SDL_TRUE;
+			}
+			return retval;
+		} else {
+			return(-1);
+		}
+		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 +434,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 +489,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) ||
--- a/src/video/x11/SDL_x11gl_c.h	Thu Apr 27 05:49:51 2006 +0000
+++ b/src/video/x11/SDL_x11gl_c.h	Thu Apr 27 09:09:48 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 */
 };
 
--- a/test/testgl.c	Thu Apr 27 05:49:51 2006 +0000
+++ b/test/testgl.c	Thu Apr 27 09:09:48 2006 +0000
@@ -361,7 +361,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 accel )
 {
 	int i;
 	int rgb_size[3];
@@ -443,6 +443,14 @@
 		SDL_GL_SetAttribute( SDL_GL_MULTISAMPLEBUFFERS, 1 );
 		SDL_GL_SetAttribute( SDL_GL_MULTISAMPLESAMPLES, fsaa );
 	}
+	if ( accel ) {
+		SDL_GL_SetAttribute( SDL_GL_ACCELERATED_VISUAL, 1 );
+	}
+	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();
@@ -469,9 +477,17 @@
 	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 ( accel ) {
+		SDL_GL_GetAttribute( SDL_GL_ACCELERATED_VISUAL, &value );
+		printf( "SDL_GL_ACCELERATED_VISUAL: requested 1, got %d\n", 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 */
@@ -678,6 +694,8 @@
 	float gamma = 0.0;
 	int noframe = 0;
 	int fsaa = 0;
+	int accel = 0;
+	int sync = 0;
 
 	logo = 0;
 	slowly = 0;
@@ -707,6 +725,12 @@
 		if ( strcmp(argv[i], "-fsaa") == 0 ) {
  		       ++fsaa;
 		}
+		if ( strcmp(argv[i], "-accel") == 0 ) {
+ 		       ++accel;
+		}
+		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",
@@ -715,7 +739,7 @@
 		}
 	}
 	for ( i=0; i<numtests; ++i ) {
- 		RunGLTest(argc, argv, logo, logocursor, slowly, bpp, gamma, noframe, fsaa);
+ 		RunGLTest(argc, argv, logo, logocursor, slowly, bpp, gamma, noframe, fsaa, sync, accel);
 	}
 	return 0;
 }