jedioutcast/code/mac/mac_glimp.c

830 lines
21 KiB
C
Raw Normal View History

2013-04-04 14:52:42 +00:00
typedef int sysEventType_t; // FIXME...
#include "../renderer/tr_local.h"
#include "mac_local.h"
#include <glm.h>
#include <DrawSprocket.h>
#include "MacGamma.h"
#define MAX_DEVICES 32
typedef struct {
GDHandle devices[MAX_DEVICES];
int numDevices;
Ptr systemGammas;
GDHandle device;
AGLContext context;
AGLDrawable drawable;
AGLPixelFormat fmt;
GLint textureMemory;
GLint videoMemory;
DSpContextReference DSpContext;
} macGlInfo;
cvar_t *r_device;
cvar_t *r_ext_transform_hint;
glHardwareType_t sys_hardwareType;
macGlInfo sys_gl;
void GLimp_EndFrame( void );
static void GLimp_Extensions( void );
void CToPStr(char *cs, Str255 ps)
{
GLint i, l;
l = strlen(cs);
if(l > 255) l = 255;
ps[0] = l;
for(i = 0; i < l; i++) ps[i + 1] = cs[i];
}
/*
============
CheckErrors
============
*/
void CheckErrors( void ) {
GLenum err;
err = aglGetError();
if( err != AGL_NO_ERROR ) {
ri.Error( ERR_FATAL, "aglGetError: %s",
aglErrorString( err ) );
}
}
//=======================================================================
/*
=====================
GLimp_ResetDisplay
=====================
*/
void GLimp_ResetDisplay( void ) {
if ( !glConfig.isFullscreen ) {
return;
}
glConfig.isFullscreen = qfalse;
// put the context into the inactive state
DSpContext_SetState( sys_gl.DSpContext, kDSpContextState_Inactive );
// release the context
DSpContext_Release( sys_gl.DSpContext );
// shutdown draw sprockets
DSpShutdown();
}
/*
=====================
GLimp_ChangeDisplay
=====================
*/
void GLimp_ChangeDisplay( int *actualWidth, int *actualHeight ) {
OSStatus theError;
DSpContextAttributes inAttributes;
int colorBits;
// startup DrawSprocket
theError = DSpStartup();
if( theError ) {
ri.Printf( PRINT_ALL, "DSpStartup() failed: %i\n", theError );
*actualWidth = 640;
*actualHeight = 480;
return;
}
if ( r_colorbits->integer == 24 || r_colorbits->integer == 32 ) {
colorBits = kDSpDepthMask_32;
} else {
colorBits = kDSpDepthMask_16;
}
memset( &inAttributes, 0, sizeof( inAttributes ) );
inAttributes.frequency = 0;
inAttributes.displayWidth = glConfig.vidWidth;
inAttributes.displayHeight = glConfig.vidHeight;
inAttributes.reserved1 = 0;
inAttributes.reserved2 = 0;
inAttributes.colorNeeds = kDSpColorNeeds_Require;
inAttributes.colorTable = NULL;
inAttributes.contextOptions = 0;
inAttributes.backBufferDepthMask = colorBits;
inAttributes.displayDepthMask = colorBits;
inAttributes.backBufferBestDepth = colorBits;
inAttributes.displayBestDepth = colorBits;
inAttributes.pageCount = 1;
inAttributes.gameMustConfirmSwitch = false;
inAttributes.reserved3[0] = 0;
inAttributes.reserved3[1] = 0;
inAttributes.reserved3[2] = 0;
inAttributes.reserved3[3] = 0;
theError = DSpFindBestContext( &inAttributes, &sys_gl.DSpContext );
inAttributes.displayWidth = glConfig.vidWidth;
inAttributes.displayHeight = glConfig.vidHeight;
inAttributes.backBufferDepthMask = colorBits;
inAttributes.displayDepthMask = colorBits;
inAttributes.backBufferBestDepth = colorBits;
inAttributes.displayBestDepth = colorBits;
inAttributes.pageCount = 1;
theError = DSpContext_Reserve( sys_gl.DSpContext, &inAttributes );
// find out what res we actually got
theError = DSpContext_GetAttributes( sys_gl.DSpContext, &inAttributes );
*actualWidth = inAttributes.displayWidth;
*actualHeight = inAttributes.displayHeight;
// put the context into the active state
theError = DSpContext_SetState( sys_gl.DSpContext, kDSpContextState_Active );
// fade back in
theError = DSpContext_FadeGammaIn( NULL, NULL );
glConfig.isFullscreen = qtrue;
}
//=======================================================================
/*
===================
GLimp_AglDescribe_f
===================
*/
void GLimp_AglDescribe_f( void ) {
long value;
long r,g,b,a;
long stencil, depth;
ri.Printf( PRINT_ALL, "Selected pixel format 0x%x\n", (int)sys_gl.fmt );
ri.Printf( PRINT_ALL, "TEXTURE_MEMORY: %i\n", sys_gl.textureMemory );
ri.Printf( PRINT_ALL, "VIDEO_MEMORY: %i\n", sys_gl.videoMemory );
aglDescribePixelFormat(sys_gl.fmt, AGL_RED_SIZE, &r);
aglDescribePixelFormat(sys_gl.fmt, AGL_GREEN_SIZE, &g);
aglDescribePixelFormat(sys_gl.fmt, AGL_BLUE_SIZE, &b);
aglDescribePixelFormat(sys_gl.fmt, AGL_ALPHA_SIZE, &a);
aglDescribePixelFormat(sys_gl.fmt, AGL_STENCIL_SIZE, &stencil);
aglDescribePixelFormat(sys_gl.fmt, AGL_DEPTH_SIZE, &depth);
ri.Printf( PRINT_ALL, "red:%i green:%i blue:%i alpha:%i depth:%i stencil:%i\n",
r, g, b, a, depth, stencil );
aglDescribePixelFormat(sys_gl.fmt, AGL_BUFFER_SIZE, &value);
ri.Printf( PRINT_ALL, "BUFFER_SIZE: %i\n", value );
aglDescribePixelFormat(sys_gl.fmt, AGL_PIXEL_SIZE, &value);
ri.Printf( PRINT_ALL, "PIXEL_SIZE: %i\n", value );
aglDescribePixelFormat(sys_gl.fmt, AGL_RENDERER_ID, &value);
ri.Printf( PRINT_ALL, "RENDERER_ID: %i\n", value );
// memory functions
value = glmGetInteger( GLM_PAGE_SIZE );
ri.Printf( PRINT_ALL, "GLM_PAGE_SIZE: %i\n", value );
value = glmGetInteger( GLM_NUMBER_PAGES );
ri.Printf( PRINT_ALL, "GLM_NUMBER_PAGES: %i\n", value );
value = glmGetInteger( GLM_CURRENT_MEMORY );
ri.Printf( PRINT_ALL, "GLM_CURRENT_MEMORY: %i\n", value );
value = glmGetInteger( GLM_MAXIMUM_MEMORY );
ri.Printf( PRINT_ALL, "GLM_MAXIMUM_MEMORY: %i\n", value );
}
/*
===================
GLimp_AglState_f
===================
*/
void GLimp_AglState_f( void ) {
char *cmd;
int state, value;
if ( ri.Cmd_Argc() != 3 ) {
ri.Printf( PRINT_ALL, "Usage: aglstate <parameter> <0/1>\n" );
return;
}
cmd = ri.Cmd_Argv( 1 );
if ( !Q_stricmp( cmd, "rasterization" ) ) {
state = AGL_RASTERIZATION;
} else {
ri.Printf( PRINT_ALL, "Unknown agl state: %s\n", cmd );
return;
}
cmd = ri.Cmd_Argv( 2 );
value = atoi( cmd );
if ( value ) {
aglEnable( sys_gl.context, state );
} else {
aglDisable( sys_gl.context, state );
}
}
/*
===================
GLimp_Extensions
===================
*/
static void GLimp_Extensions( void ) {
const char *extensions;
// get our config strings
Q_strncpyz( glConfig.vendor_string, (const char *)qglGetString (GL_VENDOR), sizeof( glConfig.vendor_string ) );
Q_strncpyz( glConfig.renderer_string, (const char *)qglGetString (GL_RENDERER), sizeof( glConfig.renderer_string ) );
Q_strncpyz( glConfig.version_string, (const char *)qglGetString (GL_VERSION), sizeof( glConfig.version_string ) );
Q_strncpyz( glConfig.extensions_string, (const char *)qglGetString (GL_EXTENSIONS), sizeof( glConfig.extensions_string ) );
extensions = glConfig.extensions_string;
// GL_ARB_multitexture
qglMultiTexCoord2fARB = NULL;
qglActiveTextureARB = NULL;
qglClientActiveTextureARB = NULL;
if ( strstr( extensions, "GL_ARB_multitexture" ) ) {
if ( r_ext_multitexture->integer && r_allowExtensions->integer ) {
qglMultiTexCoord2fARB = glMultiTexCoord2fARB;
qglActiveTextureARB = glActiveTextureARB;
qglClientActiveTextureARB = glClientActiveTextureARB;
ri.Printf( PRINT_ALL, "...using GL_ARB_multitexture\n" );
} else {
ri.Printf( PRINT_ALL, "...ignoring GL_ARB_multitexture\n" );
}
} else {
ri.Printf( PRINT_ALL, "...GL_ARB_multitexture not found\n" );
}
// GL_EXT_compiled_vertex_array
qglLockArraysEXT = NULL;
qglUnlockArraysEXT = NULL;
if ( strstr( extensions, "GL_EXT_compiled_vertex_array" ) ) {
if ( r_ext_compiled_vertex_array->integer && r_allowExtensions->integer ) {
qglLockArraysEXT = glLockArraysEXT;
qglUnlockArraysEXT = glUnlockArraysEXT;
ri.Printf( PRINT_ALL, "...using GL_EXT_compiled_vertex_array\n" );
} else {
ri.Printf( PRINT_ALL, "...ignoring GL_EXT_compiled_vertex_array\n" );
}
} else {
ri.Printf( PRINT_ALL, "...GL_EXT_compiled_vertex_array not found\n" );
}
// GL_EXT_texture_env_add
glConfig.textureEnvAddAvailable = qfalse;
if ( strstr( glConfig.extensions_string, "EXT_texture_env_add" ) ) {
if ( r_ext_texture_env_add->integer ) {
glConfig.textureEnvAddAvailable = qtrue;
ri.Printf( PRINT_ALL, "...using GL_EXT_texture_env_add\n" );
} else {
glConfig.textureEnvAddAvailable = qfalse;
ri.Printf( PRINT_ALL, "...ignoring GL_EXT_texture_env_add\n" );
}
} else {
ri.Printf( PRINT_ALL, "...GL_EXT_texture_env_add not found\n" );
}
// GL_EXT_texture_filter_anisotropic
glConfig.textureFilterAnisotropicAvailable = qfalse;
if ( strstr( glConfig.extensions_string, "EXT_texture_filter_anisotropic" ) )
{
glConfig.textureFilterAnisotropicAvailable = qtrue;
ri.Printf( PRINT_ALL, "...GL_EXT_texture_filter_anisotropic available\n" );
if ( r_ext_texture_filter_anisotropic->integer )
{
ri.Printf( PRINT_ALL, "...using GL_EXT_texture_filter_anisotropic\n" );
}
else
{
ri.Printf( PRINT_ALL, "...ignoring GL_EXT_texture_filter_anisotropic\n" );
}
ri.Cvar_Set( "r_ext_texture_filter_anisotropic_avail", "1" );
}
else
{
ri.Printf( PRINT_ALL, "...GL_EXT_texture_filter_anisotropic not found\n" );
ri.Cvar_Set( "r_ext_texture_filter_anisotropic_avail", "0" );
}
// apple transform hint
if ( strstr( extensions, "GL_APPLE_transform_hint" ) ) {
if ( r_ext_compiled_vertex_array->integer && r_allowExtensions->integer ) {
glHint( GL_TRANSFORM_HINT_APPLE, GL_FASTEST );
ri.Printf( PRINT_ALL, "...using GL_APPLE_transform_hint\n" );
} else {
ri.Printf( PRINT_ALL, "...ignoring GL_APPLE_transform_hint\n" );
}
} else {
ri.Printf( PRINT_ALL, "...GL_APPLE_transform_hint not found\n" );
}
}
/*
============================
GLimp_SufficientVideoMemory
============================
*/
#if 0
qboolean GLimp_SufficientVideoMemory( void ) {
AGLRendererInfo head_info, info;
GLint accelerated;
AGLDevice *device;
GLint i, ndevs;
device = aglDevicesOfPixelFormat( sys_gl.fmt, &ndevs);
if (!device || ndevs < 1) {
ri.Printf( PRINT_ALL, "aglDevicesOfPixelFormat failed.\n" );
return 0;
}
ri.Printf( PRINT_ALL, "%i rendering devices\n", ndevs );
head_info = aglQueryRendererInfo( device, 1 );
info = head_info;
if (!info) {
ri.Printf( PRINT_ALL, "aglQueryRendererInfo failed.\n" );
return 0;
}
for ( i = 0 ; i < ndevs ; i++ ) {
// ignore the software renderer listing
aglDescribeRenderer( info, AGL_ACCELERATED, &accelerated );
if ( accelerated ) {
aglDescribeRenderer( info, AGL_TEXTURE_MEMORY, &sys_gl.textureMemory );
aglDescribeRenderer( info, AGL_VIDEO_MEMORY, &sys_gl.videoMemory );
}
info = aglNextRendererInfo(info);
}
aglDestroyRendererInfo(head_info);
#if 0
if ( sys_gl.videoMemory < 16000000 ) {
glConfig.hardwareType = GLHW_RAGEPRO; // FIXME when voodoo is available
} else {
glConfig.isRagePro = GLHW_GENERIC; // FIXME when voodoo is available
}
#endif
ri.Printf( PRINT_ALL, "%i texture memory, %i video memory\n", sys_gl.textureMemory, sys_gl.videoMemory );
return qtrue;
}
#endif
/*
=======================
CheckDeviceRenderers
========================
*/
static void CheckDeviceRenderers( GDHandle device ) {
AGLRendererInfo info, head_info;
GLint inum;
GLint accelerated;
GLint textureMemory, videoMemory;
head_info = aglQueryRendererInfo(&device, 1);
if( !head_info ) {
ri.Printf( PRINT_ALL, "aglQueryRendererInfo : Info Error\n");
return;
}
info = head_info;
inum = 0;
while( info ) {
ri.Printf( PRINT_ALL, " Renderer : %d\n", inum);
aglDescribeRenderer( info, AGL_ACCELERATED, &accelerated );
if ( accelerated ) {
aglDescribeRenderer( info, AGL_TEXTURE_MEMORY, &textureMemory );
aglDescribeRenderer( info, AGL_VIDEO_MEMORY, &videoMemory );
ri.Printf( PRINT_ALL, " AGL_VIDEO_MEMORY: %i\n", textureMemory );
ri.Printf( PRINT_ALL, " AGL_TEXTURE_MEMORY: %i\n", videoMemory );
// save the device with the most texture memory
if ( sys_gl.textureMemory < textureMemory ) {
sys_gl.textureMemory = textureMemory;
sys_gl.device = device;
}
} else {
ri.Printf( PRINT_ALL, " Not accelerated.\n" );
}
info = aglNextRendererInfo(info);
inum++;
}
aglDestroyRendererInfo(head_info);
}
/*
=======================
CheckDevices
Make sure there is a device with enough video memory to play
=======================
*/
static void CheckDevices( void ) {
GDHandle device;
static qboolean checkedFullscreen;
if ( checkedFullscreen ) {
return;
}
if ( glConfig.isFullscreen ) {
checkedFullscreen = qtrue;
}
device = GetDeviceList();
sys_gl.numDevices = 0;
while( device && sys_gl.numDevices < MAX_DEVICES ) {
sys_gl.devices[ sys_gl.numDevices ] = device;
ri.Printf( PRINT_ALL, "Device : %d\n", sys_gl.numDevices);
CheckDeviceRenderers(device);
device = GetNextDevice(device);
sys_gl.numDevices++;
}
CheckErrors();
if ( sys_gl.textureMemory < 4000000 ) {
ri.Error( ERR_FATAL, "You must have at least four megs of video memory to play" );
}
if ( sys_gl.textureMemory < 16000000 ) {
sys_hardwareType = GLHW_RAGEPRO; // this will have to change with voodoo
} else {
sys_hardwareType = GLHW_GENERIC;
}
}
/*
=================
CreateGameWindow
=================
*/
static qboolean CreateGameWindow( void ) {
cvar_t *vid_xpos;
cvar_t *vid_ypos;
int mode;
int x, y;
Str255 pstr;
vid_xpos = ri.Cvar_Get( "vid_xpos", "30", 0 );
vid_ypos = ri.Cvar_Get( "vid_ypos", "30", 0 );
// get mode info
mode = r_mode->integer;
ri.Printf( PRINT_ALL, "...setting mode %d:", mode );
if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect, mode ) ) {
ri.Printf( PRINT_ALL, " invalid mode\n" );
return false;
}
ri.Printf( PRINT_ALL, " %d %d\n", glConfig.vidWidth, glConfig.vidHeight );
/* Create window */
if ( r_fullscreen->integer ) {
int actualWidth, actualHeight;
// change display resolution
GLimp_ChangeDisplay( &actualWidth, &actualHeight );
x = ( actualWidth - glConfig.vidWidth ) / 2;
y = ( actualHeight - glConfig.vidHeight ) / 2;
sys_gl.drawable = (AGLDrawable) GetNewCWindow(kFullScreenWindow,nil,(WindowPtr)-1L);
} else {
x = vid_xpos->integer;
y = vid_ypos->integer;
sys_gl.drawable = (AGLDrawable) GetNewCWindow(kMainWindow,nil,(WindowPtr)-1L);
}
if( !sys_gl.drawable ) {
return qfalse;
}
SizeWindow((GrafPort *) sys_gl.drawable, glConfig.vidWidth, glConfig.vidHeight,GL_FALSE);
MoveWindow((GrafPort *) sys_gl.drawable,x, y, GL_FALSE);
ShowWindow((GrafPort *) sys_gl.drawable);
SetPort((GrafPort *) sys_gl.drawable);
CToPStr("Quake3: Arena", pstr);
SetWTitle((GrafPort *) sys_gl.drawable, pstr);
HiliteWindow((GrafPort *) sys_gl.drawable, 1);
return qtrue;
}
/*
===================
GLimp_SetMode
Returns false if the mode / fullscrenn / options combination failed,
so another fallback can be tried
===================
*/
qboolean GLimp_SetMode( void ) {
GLint value;
GLint attrib[64];
int i;
if ( !CreateGameWindow() ) {
ri.Printf( PRINT_ALL, "GLimp_Init: window could not be created" );
return qfalse;
}
// check devices now that the game has set the display mode,
// because RAVE devices don't get reported if in an 8 bit desktop
CheckDevices();
// set up the attribute list
i = 0;
attrib[i++] = AGL_RGBA;
attrib[i++] = AGL_DOUBLEBUFFER;
attrib[i++] = AGL_NO_RECOVERY;
attrib[i++] = AGL_ACCELERATED;
if ( r_colorbits->integer >= 16 ) {
attrib[i++] = AGL_RED_SIZE;
attrib[i++] = 8;
attrib[i++] = AGL_GREEN_SIZE;
attrib[i++] = 8;
attrib[i++] = AGL_BLUE_SIZE;
attrib[i++] = 8;
attrib[i++] = AGL_ALPHA_SIZE;
attrib[i++] = 0;
} else {
attrib[i++] = AGL_RED_SIZE;
attrib[i++] = 5;
attrib[i++] = AGL_GREEN_SIZE;
attrib[i++] = 5;
attrib[i++] = AGL_BLUE_SIZE;
attrib[i++] = 5;
attrib[i++] = AGL_ALPHA_SIZE;
attrib[i++] = 0;
}
attrib[i++] = AGL_STENCIL_SIZE;
if ( r_stencilbits->integer ) {
attrib[i++] = r_stencilbits->integer;
} else {
attrib[i++] = 0;
}
attrib[i++] = AGL_DEPTH_SIZE;
if ( r_depthbits->integer ) {
attrib[i++] = r_depthbits->integer;
} else {
attrib[i++] = 16;
}
attrib[i++] = 0;
/* Choose pixel format */
ri.Printf( PRINT_ALL, "aglChoosePixelFormat\n" );
if ( r_device->integer < 0 || r_device->integer >= sys_gl.numDevices ) {
ri.Cvar_Set( "r_device", "0" );
}
sys_gl.fmt = aglChoosePixelFormat( &sys_gl.devices[ r_device->integer ], 1, attrib);
if(!sys_gl.fmt) {
ri.Printf( PRINT_ALL, "GLimp_Init: Pixel format could not be achieved\n");
return qfalse;
}
ri.Printf( PRINT_ALL, "Selected pixel format 0x%x\n", (int)sys_gl.fmt );
aglDescribePixelFormat(sys_gl.fmt, AGL_RED_SIZE, &value);
glConfig.colorBits = value * 3;
aglDescribePixelFormat(sys_gl.fmt, AGL_STENCIL_SIZE, &value);
glConfig.stencilBits = value;
aglDescribePixelFormat(sys_gl.fmt, AGL_DEPTH_SIZE, &value);
glConfig.depthBits = value;
CheckErrors();
/* Create context */
sys_gl.context = aglCreateContext(sys_gl.fmt, NULL);
if(!sys_gl.context) {
ri.Printf( PRINT_ALL, "GLimp_init: Context could not be created\n");
return qfalse;
}
CheckErrors();
/* Make context current */
if(!aglSetDrawable(sys_gl.context, sys_gl.drawable)) {
ri.Printf( PRINT_ALL, "GLimp_Init: Could not attach to context\n" );
return qfalse;
}
CheckErrors();
if( !aglSetCurrentContext(sys_gl.context) ) {
ri.Printf( PRINT_ALL, "GLimp_Init: Could not attach to context");
return qfalse;
}
CheckErrors();
// check video memory and determine ragePro status
#if 0
if ( !GLimp_SufficientVideoMemory() ) {
return qfalse;
}
#endif
glConfig.hardwareType = sys_hardwareType; // FIXME: this isn't really right
// draw something to show that GL is alive
qglClearColor( 1, 0.5, 0.2, 0 );
qglClear( GL_COLOR_BUFFER_BIT );
GLimp_EndFrame();
CheckErrors();
// get the extensions
GLimp_Extensions();
CheckErrors();
return qtrue;
}
/*
===================
GLimp_Init
Don't return unless OpenGL has been properly initialized
===================
*/
void GLimp_Init( void ) {
GLint major, minor;
static qboolean registered;
ri.Printf( PRINT_ALL, "--- GLimp_Init ---\n" );
aglGetVersion( &major, &minor );
ri.Printf( PRINT_ALL, "aglVersion: %i.%i\n", (int)major, (int)minor );
r_device = ri.Cvar_Get( "r_device", "0", CVAR_LATCH | CVAR_ARCHIVE );
r_ext_transform_hint = ri.Cvar_Get( "r_ext_transform_hint", "1", CVAR_LATCH | CVAR_ARCHIVE );
if ( !registered ) {
ri.Cmd_AddCommand( "aglDescribe", GLimp_AglDescribe_f );
ri.Cmd_AddCommand( "aglState", GLimp_AglState_f );
}
memset( &glConfig, 0, sizeof( glConfig ) );
r_swapInterval->modified = qtrue; // force a set next frame
glConfig.deviceSupportsGamma = qtrue;
// FIXME: try for a voodoo first
sys_gl.systemGammas = GetSystemGammas();
if ( GLimp_SetMode() ) {
ri.Printf( PRINT_ALL, "------------------\n" );
return;
}
// fall back to the known-good mode
ri.Cvar_Set( "r_fullscreen", "1" );
ri.Cvar_Set( "r_mode", "3" );
ri.Cvar_Set( "r_stereo", "0" );
ri.Cvar_Set( "r_depthBits", "16" );
ri.Cvar_Set( "r_colorBits", "16" );
ri.Cvar_Set( "r_stencilBits", "0" );
if ( GLimp_SetMode() ) {
ri.Printf( PRINT_ALL, "------------------\n" );
return;
}
ri.Error( ERR_FATAL, "Could not initialize OpenGL" );
}
/*
===============
GLimp_EndFrame
===============
*/
void GLimp_EndFrame( void ) {
// check for variable changes
if ( r_swapInterval->modified ) {
r_swapInterval->modified = qfalse;
ri.Printf( PRINT_ALL, "Changing AGL_SWAP_INTERVAL\n" );
aglSetInteger( sys_gl.context, AGL_SWAP_INTERVAL, (long *)&r_swapInterval->integer );
}
// make sure the event loop is pumped
Sys_SendKeyEvents();
aglSwapBuffers( sys_gl.context );
}
/*
===============
GLimp_Shutdown
===============
*/
void GLimp_Shutdown( void ) {
if ( sys_gl.systemGammas ) {
RestoreSystemGammas( sys_gl.systemGammas );
DisposeSystemGammas( &sys_gl.systemGammas );
sys_gl.systemGammas = 0;
}
if ( sys_gl.context ) {
aglDestroyContext(sys_gl.context);
sys_gl.context = 0;
}
if ( sys_gl.fmt ) {
aglDestroyPixelFormat(sys_gl.fmt);
sys_gl.fmt = 0;
}
if ( sys_gl.drawable ) {
DisposeWindow((GrafPort *) sys_gl.drawable);
sys_gl.drawable = 0;
}
GLimp_ResetDisplay();
memset( &glConfig, 0, sizeof( glConfig ) );
}
void GLimp_LogComment( char *comment ) {
}
qboolean GLimp_SpawnRenderThread( void (*function)( void ) ) {
}
void *GLimp_RendererSleep( void ) {
}
void GLimp_FrontEndSleep( void ) {
}
void GLimp_WakeRenderer( void * data ) {
}
/*
===============
GLimp_SetGamma
===============
*/
void GLimp_SetGamma( unsigned char red[256],
unsigned char green[256],
unsigned char blue[256] ) {
char color[3][256];
int i;
for ( i = 0 ; i < 256 ; i++ ) {
color[0][i] = red[i];
color[1][i] = green[i];
color[2][i] = blue[i];
}
SetDeviceGammaRampGD( sys_gl.device, color[0] );
}