2001-04-26 16:45:43 +00:00
|
|
|
/*
|
|
|
|
SDL - Simple DirectMedia Layer
|
2002-03-06 11:23:08 +00:00
|
|
|
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
|
2001-04-26 16:45:43 +00:00
|
|
|
|
|
|
|
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
|
2001-12-14 12:38:15 +00:00
|
|
|
slouken@libsdl.org
|
2001-04-26 16:45:43 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#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 */
|