engine/platformPPC/ppcOGLVideo.cc
2024-01-07 04:36:33 +00:00

423 lines
13 KiB
C++

//-----------------------------------------------------------------------------
// V12 Engine
//
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------
#include "PlatformWin32/platformGL.h"
#include "PlatformPPC/platformPPC.h"
#include "PlatformPPC/ppcOGLVideo.h"
#include "console/console.h"
#include <math.h>
//extern Win32PlatState winState;
extern PPCPlatState ppcState;
//------------------------------------------------------------------------------
OpenGLDevice::OpenGLDevice()
{
initDevice();
}
OpenGLDevice::~OpenGLDevice()
{
}
//------------------------------------------------------------------------------
void OpenGLDevice::initDevice()
{
#pragma message("todo: enumerate available display modes");
// Set the device name:
mDeviceName = "OpenGL";
// Set some initial conditions:
mResolutionList.clear();
Resolution newRes( 640, 480, 32 );
mResolutionList.push_back( newRes );
return;
/*
// Enumerate all available resolutions:
DEVMODE devMode;
U32 modeNum = 0;
U32 stillGoing = true;
while ( stillGoing )
{
dMemset( &devMode, 0, sizeof( devMode ) );
devMode.dmSize = sizeof( devMode );
stillGoing = EnumDisplaySettings( NULL, modeNum++, &devMode );
if ( devMode.dmPelsWidth >= 640 && devMode.dmPelsHeight >= 480
&& ( devMode.dmBitsPerPel == 16 || devMode.dmBitsPerPel == 32 ) )
{
// Only add this resolution if it is not already in the list:
bool alreadyInList = false;
for ( U32 i = 0; i < mResolutionList.size(); i++ )
{
if ( devMode.dmPelsWidth == mResolutionList[i].w
&& devMode.dmPelsHeight == mResolutionList[i].h
&& devMode.dmBitsPerPel == mResolutionList[i].bpp )
{
alreadyInList = true;
break;
}
}
if ( !alreadyInList )
{
Resolution newRes( devMode.dmPelsWidth, devMode.dmPelsHeight, devMode.dmBitsPerPel );
mResolutionList.push_back( newRes );
}
}
}
*/
}
//------------------------------------------------------------------------------
bool OpenGLDevice::activate()
{
// If the rendering context exists, delete it:
if (ppcState.ctx)
{
Con::printf( "Making the rendering context not current..." );
aglSetCurrentContext(NULL);
aglSetDrawable(ppcState.ctx, NULL);
Con::printf( "Deleting the rendering context..." );
aglDestroyContext(ppcState.ctx);
ppcState.ctx = NULL;
}
//if ( winState.hGLRC )
//{
// qwglMakeCurrent( NULL, NULL );
// qwglDeleteContext( winState.hGLRC );
// winState.hGLRC = NULL;
//}
// If OpenGL library already loaded, shut it down:
//if ( winState.hinstOpenGL )
// QGL_Shutdown();
//if ( 0 /* TODO -- figure out when we will need to get a new window */ )
//{
// // Release the device context and kill the window:
// ReleaseDC( winState.appWindow, winState.appDC );
// winState.appDC = NULL;
// DestroyWindow( winState.appWindow );
//}
// If the app window does not exist, create it:
/*
if ( ppcState.appWindow == NULL )
{
// Create the new window:
ppcState.appWindow = CreateOpenGLWindow( smIsFullScreen );
if ( ppcState.appWindow == NULL )
{
Platform::AlertOK( "OpenGLDevice::activate", "Failed to create a window!" );
return false;
}
setResolution( smCurrentRes, true );
// Set the new window to the foreground:
ShowWindow( ppcState.appWindow );
//ShowWindow( winState.appWindow, SW_SHOW );
//SetForegroundWindow( winState.appWindow );
//SetFocus( winState.appWindow );
}
*/
GLint attrib[] = { AGL_RGBA, AGL_DOUBLEBUFFER, AGL_DEPTH_SIZE, 16, AGL_NONE };
// Never unload a code module
aglConfigure(AGL_RETAIN_RENDERERS, GL_TRUE);
ppcState.fmt = aglChoosePixelFormat(NULL, 0, attrib);
if(ppcState.fmt == NULL)
{
Platform::AlertOK( "OpenGLDevice::activate", "Failed to set the pixel format of the device context!" );
return false;
}
// Con::printf( ??? ); // Spit out pixel format details?
//QGL_Init( "opengl32", "glu32" );
//PIXELFORMATDESCRIPTOR pfd;
//CreatePixelFormat( &pfd, smCurrentRes.bpp, 24, 8, false );
//S32 pixelFormat = ChooseBestPixelFormat( winState.appDC, &pfd );
//qwglDescribePixelFormat( winState.appDC, pixelFormat, sizeof( pfd ), &pfd );
//if ( !SetPixelFormat( winState.appDC, pixelFormat, &pfd ) )
//{
// Platform::AlertOK( "OpenGLDevice::activate", "Failed to set the pixel format of the device context!" );
// return false;
//}
// Create an AGL context
Con::printf( "Creating a new rendering context..." );
ppcState.ctx = aglCreateContext(ppcState.fmt, NULL);
if(ppcState.ctx == NULL)
{
Platform::AlertOK( "OpenGLDevice::activate", "Failed to create a GL rendering context!" );
return false;
}
//winState.hGLRC = qwglCreateContext( winState.appDC );
//if ( winState.hGLRC == NULL )
//{
// Platform::AlertOK( "OpenGLDevice::activate", "Failed to create a GL rendering context!" );
// return false;
//}
// Attach the context to the window
Con::printf( "Attaching the rendering context to the window..." );
if( !aglSetDrawable(ppcState.ctx, (CGrafPtr) ppcState.appWindow) )
{
Platform::AlertOK( "OpenGLDevice::activate", "Failed to make the rendering context current!" );
return false;
}
// Make this context current
aglSetCurrentContext(ppcState.ctx);
//if ( !qwglMakeCurrent( winState.appDC, winState.hGLRC ) )
//{
// Platform::AlertOK( "OpenGLDevice::activate", "Failed to make the rendering context current!" );
// return false;
//}
// Output some driver info to the console?
QGL_EXT_Init();
return true;
}
//------------------------------------------------------------------------------
void OpenGLDevice::shutdown()
{
/*if (ppcState.ctx)
{
aglSetCurrentContext(NULL);
aglSetDrawable(ppcState.ctx, NULL);
aglDestroyContext(ppcState.ctx);
ppcState.ctx = NULL;
}*/
// if ( smIsFullScreen )
// ChangeDisplaySettings( NULL, 0 );
}
//------------------------------------------------------------------------------
bool OpenGLDevice::setResolution( Resolution &res, bool forceIt )
{
if ( !smIsFullScreen && ( res.w >= ppcState.desktopWidth || res.h >= ppcState.desktopHeight ) )
{
Con::printf( "OpenGLDevice::setResolution -- can't switch to resolution larger than desktop in windowed mode!" );
return false;
}
if ( res.w < 640 || res.h < 480 )
{
Con::printf( "OpenGLDevice::setResolution -- can't go smaller than 640x480!" );
return false;
}
// If full-screen, make the new resolution match one of the ones in the list:
if ( smIsFullScreen )
{
U32 resIndex = 0;
U32 bestScore = 0, thisScore = 0;
for ( int i = 0; i < mResolutionList.size(); i++ )
{
if ( res == mResolutionList[i] )
{
resIndex = i;
break;
}
else
{
thisScore = (int) res.h - (int) mResolutionList[i].h;
if (thisScore < 0) thisScore = -thisScore;
thisScore = (int) res.w - (int) mResolutionList[i].w + thisScore;
if (thisScore < 0) thisScore = -thisScore;
//thisScore = abs( (int) res.w - (int) mResolutionList[i].w ) + abs( (int) res.h - (int) mResolutionList[i].h );
if ( ( !bestScore || thisScore < bestScore ) && res.bpp == mResolutionList[i].bpp )
{
bestScore = thisScore;
resIndex = i;
}
}
}
res = mResolutionList[resIndex];
}
// Return if already at this resolution:
if ( !forceIt && res == smCurrentRes )
return true;
Con::printf( "Changing resolution to %dx%dx%d", res.w, res.h, res.bpp );
U32 test;
if ( smIsFullScreen )
{
// aglSetFullScreen( neds to know monitor freq...
#if 0
// Change the display settings:
DEVMODE devMode;
dMemset( &devMode, 0, sizeof( devMode ) );
devMode.dmSize = sizeof( devMode );
devMode.dmPelsWidth = res.w;
devMode.dmPelsHeight = res.h;
// TODO: whatever it takes to make bit depth switching work.
//devMode.dmBitsPerPel = res.bpp
devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT/* | DM_BITSPERPEL*/;
if ( ChangeDisplaySettings( &devMode, CDS_FULLSCREEN ) != DISP_CHANGE_SUCCESSFUL )
{
ChangeDisplaySettings( NULL, 0 );
Con::printf( "OpenGLDevice::setResolution -- ChangeDisplaySettings to %dx%dx%d failed.", res.w, res.h, res.bpp );
return;
}
test = SetWindowPos( ppcState.appWindow, 0, 0, 0, res.w, res.h, SWP_NOZORDER );
if ( !test )
{
Con::printf( "OpenGLDevice::setResolution -- SetWindowPos moving to ( 0, 0 ) and sizing to %dx%d failed.", res.w, res.h );
return;
}
#endif
}
else
{
//SizeWindow(ppcState.appWindow, res.w, res.h, true); // change the window size
#pragma message("todo: center window on resize");
U32 xPos = 0;
U32 yPos = 0;
if (!aglSetDrawable(ppcState.ctx, (CGrafPtr) ppcState.appWindow))
{
Con::printf( "OpenGLDevice::setResolution: SizeWindow moving to ( %d, %d ) and sizing to %dx%d failed.", xPos, yPos, res.w, res.h );
return false;
}
if (!aglUpdateContext(ppcState.ctx)) // tell OpenGL the window changed
{
Con::printf("OpenGLDevice::setResolution: Unable to resize render buffer");
return false;
}
// // Adjust the window rect to compensate for the window style:
//
// RECT windowRect;
// windowRect.left = windowRect.top = 0;
// windowRect.right = res.w;
// windowRect.bottom = res.h;
//
// AdjustWindowRect( &windowRect, GetWindowLong( ppcState.appWindow, GWL_STYLE ), false );
// U32 adjWidth = windowRect.right - windowRect.left;
// U32 adjHeight = windowRect.bottom - windowRect.top;
//
// // Center the window again:
// U32 xPos = ( ppcState.desktopWidth - adjWidth ) / 2;
// U32 yPos = ( ppcState.desktopHeight - adjHeight ) / 2;
// test = SetWindowPos( ppcState.appWindow, 0, xPos, yPos, adjWidth, adjHeight, SWP_NOZORDER );
// if ( !test )
// {
// Con::printf( "OpenGLDevice::setResolution -- SetWindowPos moving to ( %d, %d ) and sizing to %dx%d failed.", xPos, yPos, res.w, res.h );
// return;
// }
}
smCurrentRes = res;
Platform::setWindowSize( res.w, res.h );
char tempBuf[15];
dSprintf( tempBuf, sizeof( tempBuf ), "%dx%dx%d", smCurrentRes.w, smCurrentRes.h, smCurrentRes.bpp );
Con::setVariable( "$pref::Video::resolution", tempBuf );
return true;
}
//------------------------------------------------------------------------------
bool OpenGLDevice::toggleFullScreen()
{
// Change the window style:
// U32 style = WS_VISIBLE;
// if ( smIsFullScreen )
// style |= ( WS_OVERLAPPED | WS_BORDER | WS_CAPTION );
// else
// style |= ( WS_POPUP | WS_MAXIMIZE );
// SetWindowLong( ppcState.appWindow, GWL_STYLE, style );
//
// U32 test = SetWindowPos( ppcState.appWindow, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED );
// if ( !test )
// {
// Con::printf( "OpenGLDevice::toggleFullScreen -- SetWindowPos changing window style failed." );
// return false;
// }
smIsFullScreen = !smIsFullScreen;
Con::setVariable( "$pref::Video::fullScreen", ( smIsFullScreen ? "true" : "false" ) );
if ( !smIsFullScreen )
{
// Change to windowed mode:
// ChangeDisplaySettings( NULL, 0 );
// Make sure the window size is not too big for the desktop:
if ( smCurrentRes.w >= ppcState.desktopWidth || smCurrentRes.h >= ppcState.desktopHeight )
{
S32 resIndex;
for ( resIndex = 0; resIndex < mResolutionList.size(); resIndex++ )
{
if ( smCurrentRes == mResolutionList[resIndex] )
break;
}
if ( resIndex < mResolutionList.size() )
{
// Walk back in the list until we get to a res smaller than the desktop:
while ( resIndex >= 0 && ( mResolutionList[resIndex].w >= ppcState.desktopWidth || mResolutionList[resIndex].h >= ppcState.desktopHeight ) )
resIndex--;
if ( resIndex >= 0 )
{
setResolution( mResolutionList[resIndex], true );
return true;
}
}
// Something is really screwy if you ever get to here, but let it fall through anyways.
Con::printf( "OpenGLDevice::toggleFullScreen -- a suitable resolution could not be found!" );
}
}
// Force the resolution change:
if (setResolution( smCurrentRes, true ))
return true;
return false;
}
//------------------------------------------------------------------------------
void OpenGLDevice::swapBuffers()
{
aglSwapBuffers(aglGetCurrentContext());
}
//------------------------------------------------------------------------------
DisplayDevice* OpenGLDevice::create()
{
return new OpenGLDevice();
}