diff src/video/wincommon/SDL_wingl.c @ 0:74212992fb08

Initial revision
author Sam Lantinga <slouken@lokigames.com>
date Thu, 26 Apr 2001 16:45:43 +0000
parents
children e8157fcb3114
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/video/wincommon/SDL_wingl.c	Thu Apr 26 16:45:43 2001 +0000
@@ -0,0 +1,287 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    Sam Lantinga
+    slouken@devolution.com
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id$";
+#endif
+
+/* WGL implementation of SDL OpenGL support */
+
+#include <windows.h>
+
+#include "SDL_error.h"
+#include "SDL_lowvideo.h"
+#include "SDL_wingl_c.h"
+
+#ifdef HAVE_OPENGL
+#define DEFAULT_GL_DRIVER_PATH "OPENGL32.DLL"
+#endif
+
+
+int WIN_GL_SetupWindow(_THIS)
+{
+	int retval;
+#ifdef HAVE_OPENGL
+	int pixel_format;
+
+	/* load the gl driver from a default path */
+	if ( ! this->gl_config.driver_loaded ) {
+		/* no driver has been loaded, use default (ourselves) */
+		if ( WIN_GL_LoadLibrary(this, NULL) < 0 ) {
+			return(-1);
+		}
+	}
+
+	/* Get the window device context for our OpenGL drawing */
+	GL_hdc = GetDC(SDL_Window);
+	if ( GL_hdc == NULL ) {
+		SDL_SetError("Unable to get DC for SDL_Window");
+		return(-1);
+	}
+
+	/* Set up the pixel format descriptor with our needed format */
+	memset(&GL_pfd, 0, sizeof(GL_pfd));
+	GL_pfd.nSize = sizeof(GL_pfd);
+	GL_pfd.nVersion = 1;
+	GL_pfd.dwFlags = (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL);
+	if ( this->gl_config.double_buffer ) {
+		GL_pfd.dwFlags |= PFD_DOUBLEBUFFER;
+	}
+	GL_pfd.iPixelType = PFD_TYPE_RGBA;
+	GL_pfd.cColorBits = this->gl_config.buffer_size;
+	GL_pfd.cRedBits = this->gl_config.red_size;
+	GL_pfd.cGreenBits = this->gl_config.green_size;
+	GL_pfd.cBlueBits = this->gl_config.blue_size;
+	GL_pfd.cAlphaBits = this->gl_config.alpha_size;
+	GL_pfd.cAccumRedBits = this->gl_config.accum_red_size;
+	GL_pfd.cAccumGreenBits = this->gl_config.accum_green_size;
+	GL_pfd.cAccumBlueBits = this->gl_config.accum_blue_size;
+	GL_pfd.cAccumAlphaBits = this->gl_config.accum_alpha_size;
+	GL_pfd.cAccumBits =
+		(GL_pfd.cAccumRedBits + GL_pfd.cAccumGreenBits +
+		 GL_pfd.cAccumBlueBits + GL_pfd.cAccumAlphaBits);
+	GL_pfd.cDepthBits = this->gl_config.depth_size;
+	GL_pfd.cStencilBits = this->gl_config.stencil_size;
+
+	/* Choose and set the closest available pixel format */
+	pixel_format = ChoosePixelFormat(GL_hdc, &GL_pfd);
+	if ( !pixel_format ) {
+		SDL_SetError("No matching GL pixel format available");
+		return(-1);
+	}
+	if( !SetPixelFormat(GL_hdc, pixel_format, &GL_pfd) ) {
+		SDL_SetError("Unable to set HDC pixel format");
+		return(-1);
+	}
+	DescribePixelFormat(GL_hdc, pixel_format, sizeof(GL_pfd), &GL_pfd);
+
+	GL_hrc = this->gl_data->wglCreateContext(GL_hdc);
+	if( GL_hrc == NULL ) {
+		SDL_SetError("Unable to create GL context");
+		return(-1);
+	}
+	gl_active = 1;
+#else
+	SDL_SetError("WIN driver not configured with OpenGL");
+#endif
+	if ( gl_active ) {
+		retval = 0;
+	} else {
+		retval = -1;
+	}
+	return(retval);
+}
+
+void WIN_GL_ShutDown(_THIS)
+{
+#ifdef HAVE_OPENGL
+	/* Clean up OpenGL */
+	if ( GL_hrc ) {
+		this->gl_data->wglMakeCurrent(NULL, NULL);
+		this->gl_data->wglDeleteContext(GL_hrc);
+		GL_hrc = NULL;
+	}
+	if ( GL_hdc ) {
+		ReleaseDC(SDL_Window, GL_hdc);
+		GL_hdc = NULL;
+	}
+	gl_active = 0;
+
+	WIN_GL_UnloadLibrary(this);
+#endif /* HAVE_OPENGL */
+}
+
+#ifdef HAVE_OPENGL
+
+/* Make the current context active */
+int WIN_GL_MakeCurrent(_THIS)
+{
+	int retval;
+
+	retval = 0;
+	if ( ! this->gl_data->wglMakeCurrent(GL_hdc, GL_hrc) ) {
+		SDL_SetError("Unable to make GL context current");
+		retval = -1;
+	}
+	return(retval);
+}
+
+/* Get attribute data from glX. */
+int WIN_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value)
+{
+	int retval;
+
+	retval = 0;
+	switch( attrib ) {
+	    case SDL_GL_RED_SIZE:
+		*value = GL_pfd.cRedBits;
+		break;
+	    case SDL_GL_GREEN_SIZE:
+		*value = GL_pfd.cGreenBits;
+		break;
+	    case SDL_GL_BLUE_SIZE:
+		*value = GL_pfd.cBlueBits;
+		break;
+	    case SDL_GL_ALPHA_SIZE:
+		*value = GL_pfd.cAlphaBits;
+		break;
+	    case SDL_GL_DOUBLEBUFFER:
+		if ( GL_pfd.dwFlags & PFD_DOUBLEBUFFER ) {
+			*value = 1;
+		} else {
+			*value = 0;
+		}
+		break;
+	    case SDL_GL_BUFFER_SIZE:
+		*value = GL_pfd.cColorBits;
+		break;
+	    case SDL_GL_DEPTH_SIZE:
+		*value = GL_pfd.cDepthBits;
+		break;
+	    case SDL_GL_STENCIL_SIZE:
+		*value = GL_pfd.cStencilBits;
+		break;
+	    case SDL_GL_ACCUM_RED_SIZE:
+		*value = GL_pfd.cAccumRedBits;
+		break;
+	    case SDL_GL_ACCUM_GREEN_SIZE:
+		*value = GL_pfd.cAccumGreenBits;
+		break;
+	    case SDL_GL_ACCUM_BLUE_SIZE:
+		*value = GL_pfd.cAccumBlueBits;
+		break;
+	    case SDL_GL_ACCUM_ALPHA_SIZE:
+		*value = GL_pfd.cAccumAlphaBits;
+		break;
+	    default:
+		retval = -1;
+		break;
+	}
+	return retval;
+}
+
+void WIN_GL_SwapBuffers(_THIS)
+{
+	SwapBuffers(GL_hdc);
+}
+
+#endif /* HAVE_OPENGL */
+
+#ifdef HAVE_OPENGL
+
+void WIN_GL_UnloadLibrary(_THIS)
+{
+	if ( this->gl_config.driver_loaded ) {
+		FreeLibrary((HMODULE)this->gl_config.dll_handle);
+
+		this->gl_data->wglGetProcAddress = NULL;
+		this->gl_data->wglCreateContext = NULL;
+		this->gl_data->wglDeleteContext = NULL;
+		this->gl_data->wglMakeCurrent = NULL;
+
+		this->gl_config.dll_handle = NULL;
+		this->gl_config.driver_loaded = 0;
+	}
+}
+
+/* Passing a NULL path means load pointers from the application */
+int WIN_GL_LoadLibrary(_THIS, const char* path) 
+{
+	HMODULE handle;
+
+ 	if ( gl_active ) {
+ 		SDL_SetError("OpenGL context already created");
+ 		return -1;
+ 	}
+
+	if ( path == NULL ) {
+		path = DEFAULT_GL_DRIVER_PATH;
+	}
+	handle = LoadLibrary(path);
+	if ( handle == NULL ) {
+		SDL_SetError("Could not load OpenGL library");
+		return -1;
+	}
+
+	/* Unload the old driver and reset the pointers */
+	WIN_GL_UnloadLibrary(this);
+
+	/* Load new function pointers */
+	this->gl_data->wglGetProcAddress = (void * (WINAPI *)(const char *))
+		GetProcAddress(handle, "wglGetProcAddress");
+	this->gl_data->wglCreateContext = (HGLRC (WINAPI *)(HDC))
+		GetProcAddress(handle, "wglCreateContext");
+	this->gl_data->wglDeleteContext = (BOOL (WINAPI *)(HGLRC))
+		GetProcAddress(handle, "wglDeleteContext");
+	this->gl_data->wglMakeCurrent = (BOOL (WINAPI *)(HDC, HGLRC))
+		GetProcAddress(handle, "wglMakeCurrent");
+
+	if ( (this->gl_data->wglGetProcAddress == NULL) ||
+	     (this->gl_data->wglCreateContext == NULL) ||
+	     (this->gl_data->wglDeleteContext == NULL) ||
+	     (this->gl_data->wglMakeCurrent == NULL) ) {
+		SDL_SetError("Could not retrieve OpenGL functions");
+		FreeLibrary(handle);
+		return -1;
+	}
+
+	this->gl_config.dll_handle = handle;
+	strcpy(this->gl_config.driver_path, path);
+	this->gl_config.driver_loaded = 1;
+	return 0;
+}
+
+void *WIN_GL_GetProcAddress(_THIS, const char* proc)
+{
+	void *func;
+
+	/* This is to pick up extensions */
+	func = this->gl_data->wglGetProcAddress(proc);
+	if ( ! func ) {
+		/* This is probably a normal GL function */
+		func = GetProcAddress(this->gl_config.dll_handle, proc);
+	}
+	return func;
+}
+
+#endif /* HAVE_OPENGL */