src/video/wincommon/SDL_wingl.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 06 Mar 2002 11:23:08 +0000
changeset 297 f6ffac90895c
parent 252 e8157fcb3114
child 327 13fc64213765
permissions -rw-r--r--
Updated copyright information for 2002
     1 /*
     2     SDL - Simple DirectMedia Layer
     3     Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
     4 
     5     This library is free software; you can redistribute it and/or
     6     modify it under the terms of the GNU Library General Public
     7     License as published by the Free Software Foundation; either
     8     version 2 of the License, or (at your option) any later version.
     9 
    10     This library is distributed in the hope that it will be useful,
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    13     Library General Public License for more details.
    14 
    15     You should have received a copy of the GNU Library General Public
    16     License along with this library; if not, write to the Free
    17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    18 
    19     Sam Lantinga
    20     slouken@libsdl.org
    21 */
    22 
    23 #ifdef SAVE_RCSID
    24 static char rcsid =
    25  "@(#) $Id$";
    26 #endif
    27 
    28 /* WGL implementation of SDL OpenGL support */
    29 
    30 #include <windows.h>
    31 
    32 #include "SDL_error.h"
    33 #include "SDL_lowvideo.h"
    34 #include "SDL_wingl_c.h"
    35 
    36 #ifdef HAVE_OPENGL
    37 #define DEFAULT_GL_DRIVER_PATH "OPENGL32.DLL"
    38 #endif
    39 
    40 
    41 int WIN_GL_SetupWindow(_THIS)
    42 {
    43 	int retval;
    44 #ifdef HAVE_OPENGL
    45 	int pixel_format;
    46 
    47 	/* load the gl driver from a default path */
    48 	if ( ! this->gl_config.driver_loaded ) {
    49 		/* no driver has been loaded, use default (ourselves) */
    50 		if ( WIN_GL_LoadLibrary(this, NULL) < 0 ) {
    51 			return(-1);
    52 		}
    53 	}
    54 
    55 	/* Get the window device context for our OpenGL drawing */
    56 	GL_hdc = GetDC(SDL_Window);
    57 	if ( GL_hdc == NULL ) {
    58 		SDL_SetError("Unable to get DC for SDL_Window");
    59 		return(-1);
    60 	}
    61 
    62 	/* Set up the pixel format descriptor with our needed format */
    63 	memset(&GL_pfd, 0, sizeof(GL_pfd));
    64 	GL_pfd.nSize = sizeof(GL_pfd);
    65 	GL_pfd.nVersion = 1;
    66 	GL_pfd.dwFlags = (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL);
    67 	if ( this->gl_config.double_buffer ) {
    68 		GL_pfd.dwFlags |= PFD_DOUBLEBUFFER;
    69 	}
    70 	GL_pfd.iPixelType = PFD_TYPE_RGBA;
    71 	GL_pfd.cColorBits = this->gl_config.buffer_size;
    72 	GL_pfd.cRedBits = this->gl_config.red_size;
    73 	GL_pfd.cGreenBits = this->gl_config.green_size;
    74 	GL_pfd.cBlueBits = this->gl_config.blue_size;
    75 	GL_pfd.cAlphaBits = this->gl_config.alpha_size;
    76 	GL_pfd.cAccumRedBits = this->gl_config.accum_red_size;
    77 	GL_pfd.cAccumGreenBits = this->gl_config.accum_green_size;
    78 	GL_pfd.cAccumBlueBits = this->gl_config.accum_blue_size;
    79 	GL_pfd.cAccumAlphaBits = this->gl_config.accum_alpha_size;
    80 	GL_pfd.cAccumBits =
    81 		(GL_pfd.cAccumRedBits + GL_pfd.cAccumGreenBits +
    82 		 GL_pfd.cAccumBlueBits + GL_pfd.cAccumAlphaBits);
    83 	GL_pfd.cDepthBits = this->gl_config.depth_size;
    84 	GL_pfd.cStencilBits = this->gl_config.stencil_size;
    85 
    86 	/* Choose and set the closest available pixel format */
    87 	pixel_format = ChoosePixelFormat(GL_hdc, &GL_pfd);
    88 	if ( !pixel_format ) {
    89 		SDL_SetError("No matching GL pixel format available");
    90 		return(-1);
    91 	}
    92 	if( !SetPixelFormat(GL_hdc, pixel_format, &GL_pfd) ) {
    93 		SDL_SetError("Unable to set HDC pixel format");
    94 		return(-1);
    95 	}
    96 	DescribePixelFormat(GL_hdc, pixel_format, sizeof(GL_pfd), &GL_pfd);
    97 
    98 	GL_hrc = this->gl_data->wglCreateContext(GL_hdc);
    99 	if( GL_hrc == NULL ) {
   100 		SDL_SetError("Unable to create GL context");
   101 		return(-1);
   102 	}
   103 	gl_active = 1;
   104 #else
   105 	SDL_SetError("WIN driver not configured with OpenGL");
   106 #endif
   107 	if ( gl_active ) {
   108 		retval = 0;
   109 	} else {
   110 		retval = -1;
   111 	}
   112 	return(retval);
   113 }
   114 
   115 void WIN_GL_ShutDown(_THIS)
   116 {
   117 #ifdef HAVE_OPENGL
   118 	/* Clean up OpenGL */
   119 	if ( GL_hrc ) {
   120 		this->gl_data->wglMakeCurrent(NULL, NULL);
   121 		this->gl_data->wglDeleteContext(GL_hrc);
   122 		GL_hrc = NULL;
   123 	}
   124 	if ( GL_hdc ) {
   125 		ReleaseDC(SDL_Window, GL_hdc);
   126 		GL_hdc = NULL;
   127 	}
   128 	gl_active = 0;
   129 
   130 	WIN_GL_UnloadLibrary(this);
   131 #endif /* HAVE_OPENGL */
   132 }
   133 
   134 #ifdef HAVE_OPENGL
   135 
   136 /* Make the current context active */
   137 int WIN_GL_MakeCurrent(_THIS)
   138 {
   139 	int retval;
   140 
   141 	retval = 0;
   142 	if ( ! this->gl_data->wglMakeCurrent(GL_hdc, GL_hrc) ) {
   143 		SDL_SetError("Unable to make GL context current");
   144 		retval = -1;
   145 	}
   146 	return(retval);
   147 }
   148 
   149 /* Get attribute data from glX. */
   150 int WIN_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value)
   151 {
   152 	int retval;
   153 
   154 	retval = 0;
   155 	switch( attrib ) {
   156 	    case SDL_GL_RED_SIZE:
   157 		*value = GL_pfd.cRedBits;
   158 		break;
   159 	    case SDL_GL_GREEN_SIZE:
   160 		*value = GL_pfd.cGreenBits;
   161 		break;
   162 	    case SDL_GL_BLUE_SIZE:
   163 		*value = GL_pfd.cBlueBits;
   164 		break;
   165 	    case SDL_GL_ALPHA_SIZE:
   166 		*value = GL_pfd.cAlphaBits;
   167 		break;
   168 	    case SDL_GL_DOUBLEBUFFER:
   169 		if ( GL_pfd.dwFlags & PFD_DOUBLEBUFFER ) {
   170 			*value = 1;
   171 		} else {
   172 			*value = 0;
   173 		}
   174 		break;
   175 	    case SDL_GL_BUFFER_SIZE:
   176 		*value = GL_pfd.cColorBits;
   177 		break;
   178 	    case SDL_GL_DEPTH_SIZE:
   179 		*value = GL_pfd.cDepthBits;
   180 		break;
   181 	    case SDL_GL_STENCIL_SIZE:
   182 		*value = GL_pfd.cStencilBits;
   183 		break;
   184 	    case SDL_GL_ACCUM_RED_SIZE:
   185 		*value = GL_pfd.cAccumRedBits;
   186 		break;
   187 	    case SDL_GL_ACCUM_GREEN_SIZE:
   188 		*value = GL_pfd.cAccumGreenBits;
   189 		break;
   190 	    case SDL_GL_ACCUM_BLUE_SIZE:
   191 		*value = GL_pfd.cAccumBlueBits;
   192 		break;
   193 	    case SDL_GL_ACCUM_ALPHA_SIZE:
   194 		*value = GL_pfd.cAccumAlphaBits;
   195 		break;
   196 	    default:
   197 		retval = -1;
   198 		break;
   199 	}
   200 	return retval;
   201 }
   202 
   203 void WIN_GL_SwapBuffers(_THIS)
   204 {
   205 	SwapBuffers(GL_hdc);
   206 }
   207 
   208 #endif /* HAVE_OPENGL */
   209 
   210 #ifdef HAVE_OPENGL
   211 
   212 void WIN_GL_UnloadLibrary(_THIS)
   213 {
   214 	if ( this->gl_config.driver_loaded ) {
   215 		FreeLibrary((HMODULE)this->gl_config.dll_handle);
   216 
   217 		this->gl_data->wglGetProcAddress = NULL;
   218 		this->gl_data->wglCreateContext = NULL;
   219 		this->gl_data->wglDeleteContext = NULL;
   220 		this->gl_data->wglMakeCurrent = NULL;
   221 
   222 		this->gl_config.dll_handle = NULL;
   223 		this->gl_config.driver_loaded = 0;
   224 	}
   225 }
   226 
   227 /* Passing a NULL path means load pointers from the application */
   228 int WIN_GL_LoadLibrary(_THIS, const char* path) 
   229 {
   230 	HMODULE handle;
   231 
   232  	if ( gl_active ) {
   233  		SDL_SetError("OpenGL context already created");
   234  		return -1;
   235  	}
   236 
   237 	if ( path == NULL ) {
   238 		path = DEFAULT_GL_DRIVER_PATH;
   239 	}
   240 	handle = LoadLibrary(path);
   241 	if ( handle == NULL ) {
   242 		SDL_SetError("Could not load OpenGL library");
   243 		return -1;
   244 	}
   245 
   246 	/* Unload the old driver and reset the pointers */
   247 	WIN_GL_UnloadLibrary(this);
   248 
   249 	/* Load new function pointers */
   250 	this->gl_data->wglGetProcAddress = (void * (WINAPI *)(const char *))
   251 		GetProcAddress(handle, "wglGetProcAddress");
   252 	this->gl_data->wglCreateContext = (HGLRC (WINAPI *)(HDC))
   253 		GetProcAddress(handle, "wglCreateContext");
   254 	this->gl_data->wglDeleteContext = (BOOL (WINAPI *)(HGLRC))
   255 		GetProcAddress(handle, "wglDeleteContext");
   256 	this->gl_data->wglMakeCurrent = (BOOL (WINAPI *)(HDC, HGLRC))
   257 		GetProcAddress(handle, "wglMakeCurrent");
   258 
   259 	if ( (this->gl_data->wglGetProcAddress == NULL) ||
   260 	     (this->gl_data->wglCreateContext == NULL) ||
   261 	     (this->gl_data->wglDeleteContext == NULL) ||
   262 	     (this->gl_data->wglMakeCurrent == NULL) ) {
   263 		SDL_SetError("Could not retrieve OpenGL functions");
   264 		FreeLibrary(handle);
   265 		return -1;
   266 	}
   267 
   268 	this->gl_config.dll_handle = handle;
   269 	strcpy(this->gl_config.driver_path, path);
   270 	this->gl_config.driver_loaded = 1;
   271 	return 0;
   272 }
   273 
   274 void *WIN_GL_GetProcAddress(_THIS, const char* proc)
   275 {
   276 	void *func;
   277 
   278 	/* This is to pick up extensions */
   279 	func = this->gl_data->wglGetProcAddress(proc);
   280 	if ( ! func ) {
   281 		/* This is probably a normal GL function */
   282 		func = GetProcAddress(this->gl_config.dll_handle, proc);
   283 	}
   284 	return func;
   285 }
   286 
   287 #endif /* HAVE_OPENGL */