src/video/wincommon/SDL_wingl.c
author Sam Lantinga <slouken@libsdl.org>
Sun, 04 Jan 2004 15:48:44 +0000
changeset 766 ed57c876700d
parent 677 92a933bf2f0f
child 769 b8d311d90021
permissions -rw-r--r--
Date: Wed, 26 Nov 2003 01:52:02 +0800
From: "Andy Pfiffer"
Subject: [SDL] patch: PocketPC 2000 diffs for release_1_2_6

I was making a backup of my current workspace of SDL for PocketPC,
and thought I would send out my diffs.

Apologies in advance if the patch has become whitespace mangled.

These diffs are relative to CVS tag release_1_2_6, and contain (I think)
all changes that have been mentioned on the mailing list in the last
few months.

I only have PocketPC 2000 & an ARM-based device (iPaq 3635), and I
only use Embedded Visual Tools 3.0, so I can't say for sure if it
breaks other PocketPC 200[023] builds.
     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 #include <string.h>
    29 
    30 /* WGL implementation of SDL OpenGL support */
    31 
    32 #ifdef HAVE_OPENGL
    33 #include "SDL_opengl.h"
    34 #endif
    35 #include "SDL_error.h"
    36 #include "SDL_lowvideo.h"
    37 #include "SDL_wingl_c.h"
    38 
    39 #ifdef HAVE_OPENGL
    40 #define DEFAULT_GL_DRIVER_PATH "OPENGL32.DLL"
    41 #endif
    42 
    43 /* If setting the HDC fails, we may need to recreate the window (MSDN) */
    44 static int WIN_GL_ResetWindow(_THIS)
    45 {
    46 	int status = 0;
    47 	int can_reset = 1;
    48 
    49 	/* If we were passed a window, then we can't create a new one */
    50 	if ( SDL_windowid ) {
    51 		can_reset = 0;
    52 	}
    53 #ifndef _WIN32_WCE /* FIXME WinCE needs the UNICODE version of CreateWindow() */
    54 	if ( can_reset ) {
    55 		/* Save the existing window attributes */
    56 		LONG style;
    57 		RECT rect = { 0, 0, 0, 0 };
    58 		style = GetWindowLong(SDL_Window, GWL_STYLE);
    59 		GetWindowRect(SDL_Window, &rect);
    60 		DestroyWindow(SDL_Window);
    61 		SDL_Window = CreateWindow(SDL_Appname, SDL_Appname,
    62 		                          style,
    63 					  rect.left, rect.top,
    64                                           (rect.right-rect.left)+1,
    65                                           (rect.top-rect.bottom)+1,
    66 		                          NULL, NULL, SDL_Instance, NULL);
    67 		if ( SDL_Window ) {
    68 			this->SetCaption(this, this->wm_title, this->wm_icon);
    69 		} else {
    70 			SDL_SetError("Couldn't create window");
    71 			status = -1;
    72 		}
    73 	} else
    74 #endif /* !_WIN32_WCE */
    75 	{
    76 		SDL_SetError("Unable to reset window for OpenGL context");
    77 		status = -1;
    78 	}
    79 	return(status);
    80 }
    81 
    82 #ifdef HAVE_OPENGL
    83 static void Init_WGL_ARB_extensions(_THIS)
    84 {
    85 	HWND hwnd;
    86 	HDC hdc;
    87 	HGLRC hglrc;
    88 	int pformat;
    89 	const char * (WINAPI *wglGetExtensionsStringARB)(HDC) = 0;
    90 	
    91 	hwnd = CreateWindow(SDL_Appname, SDL_Appname, WS_POPUP | WS_DISABLED,
    92 	                    0, 0, 10, 10,
    93 	                    NULL, NULL, SDL_Instance,NULL);
    94 	hdc = GetDC(hwnd);
    95 
    96 	pformat = ChoosePixelFormat(hdc, &GL_pfd);
    97 	SetPixelFormat(hdc, pformat, &GL_pfd);
    98 
    99 	hglrc = this->gl_data->wglCreateContext(hdc);
   100 	if ( hglrc ) {
   101 		this->gl_data->wglMakeCurrent(hdc, hglrc);
   102 	}
   103 
   104 	wglGetExtensionsStringARB = (const char * (WINAPI *)(HDC))
   105 		this->gl_data->wglGetProcAddress("wglGetExtensionsStringARB");
   106 
   107 	if(wglGetExtensionsStringARB && strstr(wglGetExtensionsStringARB(hdc),"WGL_ARB_pixel_format")) {
   108 		this->gl_data->wglChoosePixelFormatARB =
   109 			(BOOL (WINAPI *)(HDC, const int *, const FLOAT *, UINT, int *, UINT *))
   110 			this->gl_data->wglGetProcAddress("wglChoosePixelFormatARB");
   111 		this->gl_data->wglGetPixelFormatAttribivARB =
   112 			(BOOL (WINAPI *)(HDC, int, int, UINT, const int *, int *))
   113 			this->gl_data->wglGetProcAddress("wglGetPixelFormatAttribivARB");
   114 
   115 		if( (this->gl_data->wglChoosePixelFormatARB != NULL) &&
   116 		    (this->gl_data->wglGetPixelFormatAttribivARB != NULL) )
   117 			this->gl_data->wgl_arb_pixel_format = 1;
   118 		else 
   119 			this->gl_data->wgl_arb_pixel_format = 0;
   120 	} else {
   121 		this->gl_data->wgl_arb_pixel_format = 0;
   122 	}
   123 	
   124 	if ( hglrc ) {
   125 		this->gl_data->wglMakeCurrent(NULL, NULL);
   126 		this->gl_data->wglDeleteContext(hglrc);
   127 	}
   128 	ReleaseDC(hwnd, hdc);
   129 	DestroyWindow(hwnd);
   130 }
   131 #endif /* !HAVE_OPENGL */
   132 
   133 int WIN_GL_SetupWindow(_THIS)
   134 {
   135 	int retval;
   136 #ifdef HAVE_OPENGL
   137 	int i;
   138 	unsigned int matching;
   139 	int iAttribs[64];
   140 	int *iAttr;
   141 	float fAttribs[1] = { 0 };
   142 
   143 	/* load the gl driver from a default path */
   144 	if ( ! this->gl_config.driver_loaded ) {
   145 		/* no driver has been loaded, use default (ourselves) */
   146 		if ( WIN_GL_LoadLibrary(this, NULL) < 0 ) {
   147 			return(-1);
   148 		}
   149 	}
   150 
   151 	for ( i=0; ; ++i ) {
   152 		/* Get the window device context for our OpenGL drawing */
   153 		GL_hdc = GetDC(SDL_Window);
   154 		if ( GL_hdc == NULL ) {
   155 			SDL_SetError("Unable to get DC for SDL_Window");
   156 			return(-1);
   157 		}
   158 
   159 		/* Set up the pixel format descriptor with our needed format */
   160 		memset(&GL_pfd, 0, sizeof(GL_pfd));
   161 		GL_pfd.nSize = sizeof(GL_pfd);
   162 		GL_pfd.nVersion = 1;
   163 		GL_pfd.dwFlags = (PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL);
   164 		if ( this->gl_config.double_buffer ) {
   165 			GL_pfd.dwFlags |= PFD_DOUBLEBUFFER;
   166 		}
   167 		if ( this->gl_config.stereo ) {
   168 			GL_pfd.dwFlags |= PFD_STEREO;
   169 		}
   170 		GL_pfd.iPixelType = PFD_TYPE_RGBA;
   171 		GL_pfd.cColorBits = this->gl_config.buffer_size;
   172 		GL_pfd.cRedBits = this->gl_config.red_size;
   173 		GL_pfd.cGreenBits = this->gl_config.green_size;
   174 		GL_pfd.cBlueBits = this->gl_config.blue_size;
   175 		GL_pfd.cAlphaBits = this->gl_config.alpha_size;
   176 		GL_pfd.cAccumRedBits = this->gl_config.accum_red_size;
   177 		GL_pfd.cAccumGreenBits = this->gl_config.accum_green_size;
   178 		GL_pfd.cAccumBlueBits = this->gl_config.accum_blue_size;
   179 		GL_pfd.cAccumAlphaBits = this->gl_config.accum_alpha_size;
   180 		GL_pfd.cAccumBits =
   181 			(GL_pfd.cAccumRedBits + GL_pfd.cAccumGreenBits +
   182 			 GL_pfd.cAccumBlueBits + GL_pfd.cAccumAlphaBits);
   183 		GL_pfd.cDepthBits = this->gl_config.depth_size;
   184 		GL_pfd.cStencilBits = this->gl_config.stencil_size;
   185 
   186 		/* initialize WGL_ARB_pixel_format */
   187 		Init_WGL_ARB_extensions(this);
   188 
   189 		/* setup WGL_ARB_pixel_format attribs */
   190 		iAttr = &iAttribs[0];
   191 
   192 		*iAttr++ = WGL_DRAW_TO_WINDOW_ARB;
   193 		*iAttr++ = GL_TRUE;
   194 		*iAttr++ = WGL_ACCELERATION_ARB;
   195 		*iAttr++ = WGL_FULL_ACCELERATION_ARB;
   196 		*iAttr++ = WGL_RED_BITS_ARB;
   197 		*iAttr++ = this->gl_config.red_size;
   198 		*iAttr++ = WGL_GREEN_BITS_ARB;
   199 		*iAttr++ = this->gl_config.green_size;
   200 		*iAttr++ = WGL_BLUE_BITS_ARB;
   201 		*iAttr++ = this->gl_config.blue_size;
   202 		
   203 		if ( this->gl_config.alpha_size ) {
   204 			*iAttr++ = WGL_ALPHA_BITS_ARB;
   205 			*iAttr++ = this->gl_config.alpha_size;
   206 		}
   207 
   208 		if ( this->gl_config.double_buffer ) {
   209 			*iAttr ++ = WGL_DOUBLE_BUFFER_ARB;
   210 			*iAttr ++ = GL_TRUE;
   211 		}
   212 
   213 		*iAttr++ = WGL_DEPTH_BITS_ARB;
   214 		*iAttr++ = this->gl_config.depth_size;
   215 
   216 		if ( this->gl_config.stencil_size ) {
   217 			*iAttr++ = WGL_STENCIL_BITS_ARB;
   218 			*iAttr++ = this->gl_config.stencil_size;
   219 		}
   220 
   221 		if ( this->gl_config.accum_red_size ) {
   222 			*iAttr++ = WGL_ACCUM_RED_BITS_ARB;
   223 			*iAttr++ = this->gl_config.accum_red_size;
   224 		}
   225 
   226 		if ( this->gl_config.accum_green_size ) {
   227 			*iAttr++ = WGL_ACCUM_GREEN_BITS_ARB;
   228 			*iAttr++ = this->gl_config.accum_green_size;
   229 		}
   230 
   231 		if ( this->gl_config.accum_blue_size ) {
   232 			*iAttr++ = WGL_ACCUM_BLUE_BITS_ARB;
   233 			*iAttr++ = this->gl_config.accum_blue_size;
   234 		}
   235 
   236 		if ( this->gl_config.accum_alpha_size ) {
   237 			*iAttr++ = WGL_ACCUM_ALPHA_BITS_ARB;
   238 			*iAttr++ = this->gl_config.accum_alpha_size;
   239 		}
   240 
   241 		if ( this->gl_config.stereo ) {
   242 			*iAttr++ = WGL_STEREO_ARB;
   243 			*iAttr++ = this->gl_config.stereo;
   244 		}
   245 
   246 		if ( this->gl_config.multisamplebuffers ) {
   247 			*iAttr++ = WGL_SAMPLE_BUFFERS_ARB;
   248 			*iAttr++ = this->gl_config.multisamplebuffers;
   249 		}
   250 
   251 		if ( this->gl_config.multisamplesamples ) {
   252 			*iAttr++ = WGL_SAMPLES_ARB;
   253 			*iAttr++ = this->gl_config.multisamplesamples;
   254 		}
   255 
   256 		*iAttr = 0;
   257 
   258 		/* Choose and set the closest available pixel format */
   259 		if ( !this->gl_data->wgl_arb_pixel_format ||
   260 		     !this->gl_data->wglChoosePixelFormatARB(GL_hdc, iAttribs, fAttribs, 1, &pixel_format, &matching) ||
   261 		     !matching ) {
   262 			pixel_format = ChoosePixelFormat(GL_hdc, &GL_pfd);
   263 			this->gl_data->wgl_arb_pixel_format = 0;
   264 		}
   265 		if ( !pixel_format ) {
   266 			SDL_SetError("No matching GL pixel format available");
   267 			return(-1);
   268 		}
   269 		if ( !SetPixelFormat(GL_hdc, pixel_format, &GL_pfd) ) {
   270 			if ( i == 0 ) {
   271 				/* First time through, try resetting the window */
   272 				if ( WIN_GL_ResetWindow(this) < 0 ) {
   273 					return(-1);
   274 				}
   275 				continue;
   276 			}
   277 			SDL_SetError("Unable to set HDC pixel format");
   278 			return(-1);
   279 		}
   280 		/* We either succeeded or failed by this point */
   281 		break;
   282 	}
   283 	DescribePixelFormat(GL_hdc, pixel_format, sizeof(GL_pfd), &GL_pfd);
   284 
   285 	GL_hrc = this->gl_data->wglCreateContext(GL_hdc);
   286 	if ( GL_hrc == NULL ) {
   287 		SDL_SetError("Unable to create GL context");
   288 		return(-1);
   289 	}
   290 	gl_active = 1;
   291 #else
   292 	SDL_SetError("WIN driver not configured with OpenGL");
   293 #endif
   294 	if ( gl_active ) {
   295 		retval = 0;
   296 	} else {
   297 		retval = -1;
   298 	}
   299 	return(retval);
   300 }
   301 
   302 void WIN_GL_ShutDown(_THIS)
   303 {
   304 #ifdef HAVE_OPENGL
   305 	/* Clean up OpenGL */
   306 	if ( GL_hrc ) {
   307 		this->gl_data->wglMakeCurrent(NULL, NULL);
   308 		this->gl_data->wglDeleteContext(GL_hrc);
   309 		GL_hrc = NULL;
   310 	}
   311 	if ( GL_hdc ) {
   312 		ReleaseDC(SDL_Window, GL_hdc);
   313 		GL_hdc = NULL;
   314 	}
   315 	gl_active = 0;
   316 
   317 	WIN_GL_UnloadLibrary(this);
   318 #endif /* HAVE_OPENGL */
   319 }
   320 
   321 #ifdef HAVE_OPENGL
   322 
   323 /* Make the current context active */
   324 int WIN_GL_MakeCurrent(_THIS)
   325 {
   326 	int retval;
   327 
   328 	retval = 0;
   329 	if ( ! this->gl_data->wglMakeCurrent(GL_hdc, GL_hrc) ) {
   330 		SDL_SetError("Unable to make GL context current");
   331 		retval = -1;
   332 	}
   333 	return(retval);
   334 }
   335 
   336 /* Get attribute data from glX. */
   337 int WIN_GL_GetAttribute(_THIS, SDL_GLattr attrib, int* value)
   338 {
   339 	int retval;
   340 	
   341 	if ( this->gl_data->wgl_arb_pixel_format ) {
   342 		int wgl_attrib;
   343 
   344 		switch(attrib) {
   345 		    case SDL_GL_RED_SIZE:
   346 			wgl_attrib = WGL_RED_BITS_ARB;
   347 			break;
   348 		    case SDL_GL_GREEN_SIZE:
   349 			wgl_attrib = WGL_GREEN_BITS_ARB;
   350 			break;
   351 		    case SDL_GL_BLUE_SIZE:
   352 			wgl_attrib = WGL_BLUE_BITS_ARB;
   353 			break;
   354 		    case SDL_GL_ALPHA_SIZE:
   355 			wgl_attrib = WGL_ALPHA_BITS_ARB;
   356 			break;
   357 		    case SDL_GL_DOUBLEBUFFER:
   358 			wgl_attrib = WGL_DOUBLE_BUFFER_ARB;
   359 			break;
   360 		    case SDL_GL_BUFFER_SIZE:
   361 			wgl_attrib = WGL_COLOR_BITS_ARB;
   362 			break;
   363 		    case SDL_GL_DEPTH_SIZE:
   364 			wgl_attrib = WGL_DEPTH_BITS_ARB;
   365 			break;
   366 		    case SDL_GL_STENCIL_SIZE:
   367 			wgl_attrib = WGL_STENCIL_BITS_ARB;
   368 			break;
   369 		    case SDL_GL_ACCUM_RED_SIZE:
   370 			wgl_attrib = WGL_ACCUM_RED_BITS_ARB;
   371 			break;
   372 		    case SDL_GL_ACCUM_GREEN_SIZE:
   373 			wgl_attrib = WGL_ACCUM_GREEN_BITS_ARB;
   374 			break;
   375 		    case SDL_GL_ACCUM_BLUE_SIZE:
   376 			wgl_attrib = WGL_ACCUM_BLUE_BITS_ARB;
   377 			break;
   378 		    case SDL_GL_ACCUM_ALPHA_SIZE:
   379 			wgl_attrib = WGL_ACCUM_ALPHA_BITS_ARB;
   380 			break;
   381 		    case SDL_GL_STEREO:
   382 			wgl_attrib = WGL_STEREO_ARB;
   383 			break;
   384 		    case SDL_GL_MULTISAMPLEBUFFERS:
   385 			wgl_attrib = WGL_SAMPLE_BUFFERS_ARB;
   386 			break;
   387 		    case SDL_GL_MULTISAMPLESAMPLES:
   388 			wgl_attrib = WGL_SAMPLES_ARB;
   389 			break;
   390 		    default:
   391 			return(-1);
   392 		}
   393 		this->gl_data->wglGetPixelFormatAttribivARB(GL_hdc, pixel_format, 0, 1, &wgl_attrib, value);
   394 
   395 		return 0;
   396 	}
   397 
   398 	retval = 0;
   399 	switch ( attrib ) {
   400 	    case SDL_GL_RED_SIZE:
   401 		*value = GL_pfd.cRedBits;
   402 		break;
   403 	    case SDL_GL_GREEN_SIZE:
   404 		*value = GL_pfd.cGreenBits;
   405 		break;
   406 	    case SDL_GL_BLUE_SIZE:
   407 		*value = GL_pfd.cBlueBits;
   408 		break;
   409 	    case SDL_GL_ALPHA_SIZE:
   410 		*value = GL_pfd.cAlphaBits;
   411 		break;
   412 	    case SDL_GL_DOUBLEBUFFER:
   413 		if ( GL_pfd.dwFlags & PFD_DOUBLEBUFFER ) {
   414 			*value = 1;
   415 		} else {
   416 			*value = 0;
   417 		}
   418 		break;
   419 	    case SDL_GL_BUFFER_SIZE:
   420 		*value = GL_pfd.cColorBits;
   421 		break;
   422 	    case SDL_GL_DEPTH_SIZE:
   423 		*value = GL_pfd.cDepthBits;
   424 		break;
   425 	    case SDL_GL_STENCIL_SIZE:
   426 		*value = GL_pfd.cStencilBits;
   427 		break;
   428 	    case SDL_GL_ACCUM_RED_SIZE:
   429 		*value = GL_pfd.cAccumRedBits;
   430 		break;
   431 	    case SDL_GL_ACCUM_GREEN_SIZE:
   432 		*value = GL_pfd.cAccumGreenBits;
   433 		break;
   434 	    case SDL_GL_ACCUM_BLUE_SIZE:
   435 		*value = GL_pfd.cAccumBlueBits;
   436 		break;
   437 	    case SDL_GL_ACCUM_ALPHA_SIZE:
   438 		*value = GL_pfd.cAccumAlphaBits;
   439 		break;
   440 	    case SDL_GL_STEREO:
   441 		if ( GL_pfd.dwFlags & PFD_STEREO ) {
   442 			*value = 1;
   443 		} else {
   444 			*value = 0;
   445 		}
   446 		break;
   447 	    default:
   448 		retval = -1;
   449 		break;
   450 	}
   451 	return retval;
   452 }
   453 
   454 void WIN_GL_SwapBuffers(_THIS)
   455 {
   456 	SwapBuffers(GL_hdc);
   457 }
   458 
   459 void WIN_GL_UnloadLibrary(_THIS)
   460 {
   461 	if ( this->gl_config.driver_loaded ) {
   462 		FreeLibrary((HMODULE)this->gl_config.dll_handle);
   463 
   464 		this->gl_data->wglGetProcAddress = NULL;
   465 		this->gl_data->wglCreateContext = NULL;
   466 		this->gl_data->wglDeleteContext = NULL;
   467 		this->gl_data->wglMakeCurrent = NULL;
   468 		this->gl_data->wglChoosePixelFormatARB = NULL;
   469 		this->gl_data->wglGetPixelFormatAttribivARB = NULL;
   470 
   471 		this->gl_config.dll_handle = NULL;
   472 		this->gl_config.driver_loaded = 0;
   473 	}
   474 }
   475 
   476 /* Passing a NULL path means load pointers from the application */
   477 int WIN_GL_LoadLibrary(_THIS, const char* path) 
   478 {
   479 	HMODULE handle;
   480 
   481  	if ( gl_active ) {
   482  		SDL_SetError("OpenGL context already created");
   483  		return -1;
   484  	}
   485 
   486 	if ( path == NULL ) {
   487 		path = DEFAULT_GL_DRIVER_PATH;
   488 	}
   489 	handle = LoadLibrary(path);
   490 	if ( handle == NULL ) {
   491 		SDL_SetError("Could not load OpenGL library");
   492 		return -1;
   493 	}
   494 
   495 	/* Unload the old driver and reset the pointers */
   496 	WIN_GL_UnloadLibrary(this);
   497 
   498 	/* Load new function pointers */
   499 	memset(this->gl_data, 0, sizeof(*this->gl_data));
   500 	this->gl_data->wglGetProcAddress = (void * (WINAPI *)(const char *))
   501 		GetProcAddress(handle, "wglGetProcAddress");
   502 	this->gl_data->wglCreateContext = (HGLRC (WINAPI *)(HDC))
   503 		GetProcAddress(handle, "wglCreateContext");
   504 	this->gl_data->wglDeleteContext = (BOOL (WINAPI *)(HGLRC))
   505 		GetProcAddress(handle, "wglDeleteContext");
   506 	this->gl_data->wglMakeCurrent = (BOOL (WINAPI *)(HDC, HGLRC))
   507 		GetProcAddress(handle, "wglMakeCurrent");
   508 
   509 	if ( (this->gl_data->wglGetProcAddress == NULL) ||
   510 	     (this->gl_data->wglCreateContext == NULL) ||
   511 	     (this->gl_data->wglDeleteContext == NULL) ||
   512 	     (this->gl_data->wglMakeCurrent == NULL) ) {
   513 		SDL_SetError("Could not retrieve OpenGL functions");
   514 		FreeLibrary(handle);
   515 		return -1;
   516 	}
   517 
   518 	this->gl_config.dll_handle = handle;
   519 	strcpy(this->gl_config.driver_path, path);
   520 	this->gl_config.driver_loaded = 1;
   521 	return 0;
   522 }
   523 
   524 void *WIN_GL_GetProcAddress(_THIS, const char* proc)
   525 {
   526 	void *func;
   527 
   528 	/* This is to pick up extensions */
   529 	func = this->gl_data->wglGetProcAddress(proc);
   530 	if ( ! func ) {
   531 		/* This is probably a normal GL function */
   532 		func = GetProcAddress(this->gl_config.dll_handle, proc);
   533 	}
   534 	return func;
   535 }
   536 
   537 #endif /* HAVE_OPENGL */