1259 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1259 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
//-----------------------------------------------------------------------------
 | 
						|
// Torque Game Engine
 | 
						|
// Copyright (C) GarageGames.com, Inc.
 | 
						|
//-----------------------------------------------------------------------------
 | 
						|
 | 
						|
#include "platformWin32/platformGL.h"
 | 
						|
#include "platformWin32/platformWin32.h"
 | 
						|
#include "platform/platformAudio.h"
 | 
						|
#include "platformWin32/winOGLVideo.h"
 | 
						|
#include "platformWin32/winD3DVideo.h"
 | 
						|
#include "console/console.h"
 | 
						|
#include "math/mPoint.h"
 | 
						|
#include "platform/event.h"
 | 
						|
#include "platform/gameInterface.h"
 | 
						|
#include "console/consoleInternal.h"
 | 
						|
#include "console/ast.h"
 | 
						|
#include "core/fileStream.h"
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
 | 
						|
bool OpenGLDevice::smCanSwitchBitDepth = true;
 | 
						|
 | 
						|
struct CardProfile
 | 
						|
{
 | 
						|
   const char *vendor;     // manufacturer
 | 
						|
   const char *renderer;   // driver name
 | 
						|
 | 
						|
   bool safeMode;          // destroy rendering context for resolution change
 | 
						|
   bool lockArray;         // allow compiled vertex arrays
 | 
						|
   bool subImage;          // allow glTexSubImage*
 | 
						|
   bool fogTexture;        // require bound texture for combine extension
 | 
						|
   bool noEnvColor;        // no texture environment color
 | 
						|
   bool clipHigh;          // clip high resolutions
 | 
						|
	bool deleteContext;		// delete rendering context
 | 
						|
	bool texCompress;			// allow texture compression
 | 
						|
	bool interiorLock;		// lock arrays for Interior render
 | 
						|
	bool skipFirstFog;		// skip first two-pass fogging (dumb 3Dfx hack)
 | 
						|
	bool only16;				// inhibit 32-bit resolutions
 | 
						|
	bool noArraysAlpha;	// don't use glDrawArrays with a GL_ALPHA texture
 | 
						|
 | 
						|
	const char *proFile;		// explicit profile of graphic settings
 | 
						|
};
 | 
						|
 | 
						|
struct OSCardProfile
 | 
						|
{
 | 
						|
   const char *vendor;     // manufacturer
 | 
						|
   const char *renderer;   // driver name
 | 
						|
 | 
						|
   bool allowOpenGL;			// allow OpenGL driver
 | 
						|
	bool allowD3D;				// allow D3D driver
 | 
						|
	bool preferOpenGL;		// prefer OpenGL driver
 | 
						|
};
 | 
						|
 | 
						|
static Vector<CardProfile> sCardProfiles(__FILE__, __LINE__);
 | 
						|
static Vector<OSCardProfile> sOSCardProfiles(__FILE__, __LINE__);
 | 
						|
 | 
						|
struct ProcessorProfile
 | 
						|
{
 | 
						|
    U16 clock;  // clock range max
 | 
						|
    U16 adjust; // CPU adjust
 | 
						|
};
 | 
						|
 | 
						|
static U8 sNumProcessors = 4;
 | 
						|
static ProcessorProfile sProcessorProfiles[] =
 | 
						|
{
 | 
						|
    {  400,  0 },
 | 
						|
    {  600,  5 },
 | 
						|
    {  800, 10 },
 | 
						|
    { 1000, 15 },
 | 
						|
};
 | 
						|
 | 
						|
struct SettingProfile
 | 
						|
{
 | 
						|
    U16 performance;        // metric range max
 | 
						|
    const char *settings;   // default file
 | 
						|
};
 | 
						|
 | 
						|
static U8 sNumSettings = 3;
 | 
						|
static SettingProfile sSettingProfiles[] =
 | 
						|
{
 | 
						|
    {  33, "LowProfile.cs" },
 | 
						|
    {  66, "MediumProfile.cs" },
 | 
						|
    { 100, "HighProfile.cs" },
 | 
						|
};
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
ConsoleFunction( addCardProfile, void, 16, 16, "(string vendor, string renderer,"
 | 
						|
                "bool safeMode, bool lockArray, bool subImage, bool fogTexture,"
 | 
						|
                "bool noEnvColor, bool clipHigh, bool deleteContext, bool texCompress"
 | 
						|
                "bool interiorLock, bool skipFirstFog, bool only16,"
 | 
						|
                "bool noArraysAlpha, string proFile)"
 | 
						|
                ""
 | 
						|
                "Register a card profile with the card profile manager.\n\n"
 | 
						|
                "Most of the parameters are fairly self-explanatory and very internal"
 | 
						|
                " to the rendering code; however there are a few of note:\n"
 | 
						|
                "@param vendor   The vendor string the card claims.\n"
 | 
						|
                "@param renderer The renderer string the card claims.\n"
 | 
						|
                "@param proFile  Name of the file where further configuration information is kept."
 | 
						|
                )
 | 
						|
{
 | 
						|
   CardProfile profile;
 | 
						|
 | 
						|
   profile.vendor = dStrdup(argv[1]);
 | 
						|
   profile.renderer = dStrdup(argv[2]);
 | 
						|
 | 
						|
   profile.safeMode = dAtob(argv[3]);
 | 
						|
   profile.lockArray = dAtob(argv[4]);
 | 
						|
   profile.subImage = dAtob(argv[5]);
 | 
						|
   profile.fogTexture = dAtob(argv[6]);
 | 
						|
   profile.noEnvColor = dAtob(argv[7]);
 | 
						|
   profile.clipHigh = dAtob(argv[8]);
 | 
						|
	profile.deleteContext = dAtob(argv[9]);
 | 
						|
	profile.texCompress = dAtob(argv[10]);
 | 
						|
	profile.interiorLock = dAtob(argv[11]);
 | 
						|
	profile.skipFirstFog = dAtob(argv[12]);
 | 
						|
	profile.only16 = dAtob(argv[13]);
 | 
						|
	profile.noArraysAlpha = dAtob(argv[14]);
 | 
						|
 | 
						|
	if (strcmp(argv[15],""))
 | 
						|
		profile.proFile = dStrdup(argv[15]);
 | 
						|
	else
 | 
						|
		profile.proFile = NULL;
 | 
						|
 | 
						|
   sCardProfiles.push_back(profile);
 | 
						|
}
 | 
						|
 | 
						|
ConsoleFunction( addOSCardProfile, void, 6,6, "(string vendor, string renderer, bool allowOpenGL,"
 | 
						|
                " bool allowD3D, bool preferOpenGL) "
 | 
						|
                "Register with the profile manager what rendering mode is preferred with the "
 | 
						|
                "specified card.")
 | 
						|
{
 | 
						|
   OSCardProfile profile;
 | 
						|
 | 
						|
   profile.vendor = dStrdup(argv[1]);
 | 
						|
   profile.renderer = dStrdup(argv[2]);
 | 
						|
 | 
						|
   profile.allowOpenGL = dAtob(argv[3]);
 | 
						|
	profile.allowD3D = dAtob(argv[4]);
 | 
						|
	profile.preferOpenGL = dAtob(argv[5]);
 | 
						|
 | 
						|
   sOSCardProfiles.push_back(profile);
 | 
						|
}
 | 
						|
 | 
						|
static void clearCardProfiles()
 | 
						|
{
 | 
						|
   while (sCardProfiles.size())
 | 
						|
   {
 | 
						|
      dFree((char *) sCardProfiles.last().vendor);
 | 
						|
      dFree((char *) sCardProfiles.last().renderer);
 | 
						|
 | 
						|
		dFree((char *) sCardProfiles.last().proFile);
 | 
						|
 | 
						|
      sCardProfiles.decrement();
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
static void clearOSCardProfiles()
 | 
						|
{
 | 
						|
   while (sOSCardProfiles.size())
 | 
						|
   {
 | 
						|
      dFree((char *) sOSCardProfiles.last().vendor);
 | 
						|
      dFree((char *) sOSCardProfiles.last().renderer);
 | 
						|
 | 
						|
      sOSCardProfiles.decrement();
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
static void execScript(const char *scriptFile)
 | 
						|
{
 | 
						|
	// execute the script
 | 
						|
   FileStream str;
 | 
						|
 | 
						|
   if (!str.open(scriptFile, FileStream::Read))
 | 
						|
      return;
 | 
						|
 | 
						|
   U32 size = str.getStreamSize();
 | 
						|
   char *script = new char[size + 1];
 | 
						|
 | 
						|
   str.read(size, script);
 | 
						|
   str.close();
 | 
						|
 | 
						|
   script[size] = 0;
 | 
						|
   Con::executef(2, "eval", script);
 | 
						|
   delete[] script;
 | 
						|
}
 | 
						|
 | 
						|
static void profileSystem(const char *vendor, const char *renderer)
 | 
						|
{
 | 
						|
 | 
						|
   //Con::executef(2, "exec", "scripts/CardProfiles.cs");
 | 
						|
	execScript("CardProfiles.cs");
 | 
						|
 | 
						|
	const char *arch;
 | 
						|
	OSVERSIONINFO OSVersionInfo;
 | 
						|
	const char *os = NULL;
 | 
						|
	char osProfiles[64];
 | 
						|
 | 
						|
	if (dStrstr(Platform::SystemInfo.processor.name,"AMD") != NULL)
 | 
						|
		arch = "AMD";
 | 
						|
	else
 | 
						|
		arch = "Intel";
 | 
						|
 | 
						|
	
 | 
						|
	dMemset( &OSVersionInfo, 0, sizeof( OSVERSIONINFO ) );
 | 
						|
   OSVersionInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
 | 
						|
   if ( GetVersionEx( &OSVersionInfo )	)
 | 
						|
	{
 | 
						|
		if (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
 | 
						|
			if ( OSVersionInfo.dwMinorVersion == 0 )
 | 
						|
			{
 | 
						|
				if (dStrcmp(arch,"Intel") == 0)
 | 
						|
					os = "W95";
 | 
						|
			}
 | 
						|
			else if ( OSVersionInfo.dwMinorVersion == 10 )	
 | 
						|
				if ( OSVersionInfo.szCSDVersion[1] != 'A' )
 | 
						|
					os = "W98";
 | 
						|
				else
 | 
						|
					os = "W98SE";
 | 
						|
			else
 | 
						|
				os = "WME";
 | 
						|
		else
 | 
						|
			if ( OSVersionInfo.dwMajorVersion >= 5 )
 | 
						|
				os = "W2K";
 | 
						|
		
 | 
						|
		if ( os != NULL )
 | 
						|
		{
 | 
						|
			dSprintf(osProfiles,64,"%s%sCardProfiles.cs",arch,os);
 | 
						|
			//Con::executef(2, "exec", osProfiles);
 | 
						|
			execScript(osProfiles);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	const char *proFile = NULL;
 | 
						|
   U32 i;
 | 
						|
 | 
						|
   for (i = 0; i < sCardProfiles.size(); ++i)
 | 
						|
      if (dStrstr(vendor, sCardProfiles[i].vendor) &&
 | 
						|
          (!dStrcmp(sCardProfiles[i].renderer, "*") ||
 | 
						|
           dStrstr(renderer, sCardProfiles[i].renderer)))
 | 
						|
      {
 | 
						|
         Con::setBoolVariable("$pref::Video::safeModeOn", sCardProfiles[i].safeMode);
 | 
						|
         Con::setBoolVariable("$pref::OpenGL::disableEXTCompiledVertexArray", !sCardProfiles[i].lockArray);
 | 
						|
         Con::setBoolVariable("$pref::OpenGL::disableSubImage", !sCardProfiles[i].subImage);
 | 
						|
         Con::setBoolVariable("$pref::TS::fogTexture", sCardProfiles[i].fogTexture);
 | 
						|
         Con::setBoolVariable("$pref::OpenGL::noEnvColor", sCardProfiles[i].noEnvColor);
 | 
						|
         Con::setBoolVariable("$pref::Video::clipHigh", sCardProfiles[i].clipHigh);
 | 
						|
			if (!sCardProfiles[i].deleteContext)
 | 
						|
			{
 | 
						|
				OSVERSIONINFO OSVersionInfo;
 | 
						|
 | 
						|
   			// HACK: The Voodoo3/5 on W2K crash when deleting a rendering context
 | 
						|
				// So we're not deleting it.
 | 
						|
				// Oh, and the Voodoo3 returns a Banshee renderer string under W2K
 | 
						|
   			dMemset( &OSVersionInfo, 0, sizeof( OSVERSIONINFO ) );
 | 
						|
   			OSVersionInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
 | 
						|
   			if ( GetVersionEx( &OSVersionInfo ) &&
 | 
						|
					  OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
 | 
						|
					  OSVersionInfo.dwMajorVersion == 5)
 | 
						|
					Con::setBoolVariable("$pref::Video::deleteContext", false);
 | 
						|
				else
 | 
						|
					Con::setBoolVariable("$pref::Video::deleteContext", true);
 | 
						|
			}
 | 
						|
			else
 | 
						|
				Con::setBoolVariable("$pref::Video::deleteContext", true);
 | 
						|
			Con::setBoolVariable("$pref::OpenGL::disableARBTextureCompression", !sCardProfiles[i].texCompress);
 | 
						|
			Con::setBoolVariable("$pref::Interior::lockArrays", sCardProfiles[i].interiorLock);
 | 
						|
			Con::setBoolVariable("$pref::TS::skipFirstFog", sCardProfiles[i].skipFirstFog);
 | 
						|
			Con::setBoolVariable("$pref::Video::only16", sCardProfiles[i].only16);
 | 
						|
			Con::setBoolVariable("$pref::OpenGL::noDrawArraysAlpha", sCardProfiles[i].noArraysAlpha);
 | 
						|
 | 
						|
			proFile = sCardProfiles[i].proFile;
 | 
						|
 | 
						|
         break;
 | 
						|
      }
 | 
						|
 | 
						|
   // defaults
 | 
						|
	U16 glProfile;
 | 
						|
 | 
						|
   if (!proFile)
 | 
						|
   {
 | 
						|
      // no driver GL profile -- make one via weighting GL extensions
 | 
						|
      glProfile = 25;
 | 
						|
 | 
						|
      glProfile += gGLState.suppARBMultitexture * 25;
 | 
						|
      glProfile += gGLState.suppLockedArrays * 15;
 | 
						|
      glProfile += gGLState.suppVertexArrayRange * 10;
 | 
						|
      glProfile += gGLState.suppTextureEnvCombine * 5;
 | 
						|
      glProfile += gGLState.suppPackedPixels * 5;
 | 
						|
      glProfile += gGLState.suppTextureCompression * 5;
 | 
						|
      glProfile += gGLState.suppS3TC * 5;
 | 
						|
      glProfile += gGLState.suppFXT1 * 5;
 | 
						|
 | 
						|
      Con::setBoolVariable("$pref::Video::safeModeOn", true);
 | 
						|
      Con::setBoolVariable("$pref::OpenGL::disableEXTCompiledVertexArray", false);
 | 
						|
      Con::setBoolVariable("$pref::OpenGL::disableSubImage", false);
 | 
						|
      Con::setBoolVariable("$pref::TS::fogTexture", false);
 | 
						|
      Con::setBoolVariable("$pref::OpenGL::noEnvColor", false);
 | 
						|
      Con::setBoolVariable("$pref::Video::clipHigh", false);
 | 
						|
		Con::setBoolVariable("$pref::Video::deleteContext", true);
 | 
						|
		Con::setBoolVariable("$pref::OpenGL::disableARBTextureCompression", false);
 | 
						|
		Con::setBoolVariable("$pref::Interior::lockArrays", true);
 | 
						|
		Con::setBoolVariable("$pref::TS::skipFirstFog", false);
 | 
						|
		Con::setBoolVariable("$pref::Video::only16", false);
 | 
						|
		Con::setBoolVariable("$pref::OpenGL::noDrawArraysAlpha", false);
 | 
						|
   }
 | 
						|
 | 
						|
	Con::setVariable("$pref::Video::profiledVendor", vendor);
 | 
						|
   Con::setVariable("$pref::Video::profiledRenderer", renderer);
 | 
						|
 | 
						|
	if (!Con::getBoolVariable("$DisableSystemProfiling") &&
 | 
						|
		 ( dStrcmp(vendor, Con::getVariable("$pref::Video::defaultsVendor")) ||
 | 
						|
       	dStrcmp(renderer, Con::getVariable("$pref::Video::defaultsRenderer")) ))
 | 
						|
	{
 | 
						|
		if (proFile)
 | 
						|
		{
 | 
						|
			char settings[64];
 | 
						|
 | 
						|
			dSprintf(settings,64,"%s.cs",proFile);
 | 
						|
			//Con::executef(2, "exec", settings);
 | 
						|
			execScript(settings);
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
   		U16 adjust;
 | 
						|
 | 
						|
   		// match clock with profile
 | 
						|
   		for (i = 0; i < sNumProcessors; ++i)
 | 
						|
   		{
 | 
						|
      		adjust = sProcessorProfiles[i].adjust;
 | 
						|
 | 
						|
      		if (Platform::SystemInfo.processor.mhz < sProcessorProfiles[i].clock) break;
 | 
						|
   		}
 | 
						|
 | 
						|
   		const char *settings;
 | 
						|
 | 
						|
   		// match performance metric with profile
 | 
						|
   		for (i = 0; i < sNumSettings; ++i)
 | 
						|
   		{
 | 
						|
      		settings = sSettingProfiles[i].settings;
 | 
						|
 | 
						|
      		if (glProfile+adjust <= sSettingProfiles[i].performance) break;
 | 
						|
   		}
 | 
						|
 | 
						|
   		//Con::executef(2, "exec", settings);
 | 
						|
			execScript(settings);
 | 
						|
		}
 | 
						|
 | 
						|
		bool match = false;
 | 
						|
 | 
						|
		for (i = 0; i < sOSCardProfiles.size(); ++i)
 | 
						|
			if (dStrstr(vendor, sOSCardProfiles[i].vendor) &&
 | 
						|
				 (!dStrcmp(sOSCardProfiles[i].renderer, "*") ||
 | 
						|
         	  dStrstr(renderer, sOSCardProfiles[i].renderer)))
 | 
						|
			{
 | 
						|
				Con::setBoolVariable("$pref::Video::allowOpenGL", sOSCardProfiles[i].allowOpenGL);
 | 
						|
				Con::setBoolVariable("$pref::Video::allowD3D", sOSCardProfiles[i].allowD3D);
 | 
						|
				Con::setBoolVariable("$pref::Video::preferOpenGL", sOSCardProfiles[i].preferOpenGL);
 | 
						|
			
 | 
						|
				match = true;
 | 
						|
 | 
						|
				break;
 | 
						|
			}
 | 
						|
 | 
						|
		if (!match)
 | 
						|
		{
 | 
						|
			Con::setBoolVariable("$pref::Video::allowOpenGL", true);
 | 
						|
			Con::setBoolVariable("$pref::Video::allowD3D", true);
 | 
						|
			Con::setBoolVariable("$pref::Video::preferOpenGL", true);
 | 
						|
		}
 | 
						|
 | 
						|
		Con::setVariable("$pref::Video::defaultsVendor", vendor);
 | 
						|
   	Con::setVariable("$pref::Video::defaultsRenderer", renderer);
 | 
						|
	}
 | 
						|
 | 
						|
   clearCardProfiles();
 | 
						|
	clearOSCardProfiles();
 | 
						|
}
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
OpenGLDevice::OpenGLDevice()
 | 
						|
{
 | 
						|
   initDevice();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
void OpenGLDevice::initDevice()
 | 
						|
{
 | 
						|
   // Set the device name:
 | 
						|
   mDeviceName = "OpenGL";
 | 
						|
 | 
						|
   // Set some initial conditions:
 | 
						|
   mResolutionList.clear();
 | 
						|
 | 
						|
   // 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
 | 
						|
      if ( devMode.dmPelsWidth >= 480 && devMode.dmPelsHeight >= 360
 | 
						|
           && ( devMode.dmBitsPerPel == 16 || devMode.dmBitsPerPel == 32 ) &&
 | 
						|
           ( smCanSwitchBitDepth || devMode.dmBitsPerPel == winState.desktopBitsPixel ) )
 | 
						|
      {
 | 
						|
         // 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( U32 width, U32 height, U32 bpp, bool fullScreen )
 | 
						|
{
 | 
						|
   Con::printf( "Activating the OpenGL display device..." );
 | 
						|
 | 
						|
   bool needResurrect = false;
 | 
						|
 | 
						|
   // If the rendering context exists, delete it:
 | 
						|
   if ( winState.hGLRC )
 | 
						|
   {
 | 
						|
      Con::printf( "Killing the texture manager..." );
 | 
						|
      Game->textureKill();
 | 
						|
      needResurrect = true;
 | 
						|
 | 
						|
      Con::printf( "Making the rendering context not current..." );
 | 
						|
      if ( !dwglMakeCurrent( NULL, NULL ) )
 | 
						|
      {
 | 
						|
         AssertFatal( false, "OpenGLDevice::activate\ndwglMakeCurrent( NULL, NULL ) failed!" );
 | 
						|
         return false;
 | 
						|
      }
 | 
						|
 | 
						|
      Con::printf( "Deleting the rendering context ..." );
 | 
						|
      if ( !dwglDeleteContext( winState.hGLRC ) )
 | 
						|
      {
 | 
						|
         AssertFatal( false, "OpenGLDevice::activate\ndwglDeleteContext failed!" );
 | 
						|
         return false;
 | 
						|
      }
 | 
						|
      winState.hGLRC = NULL;
 | 
						|
   }
 | 
						|
 | 
						|
   // If the window already exists, kill it so we can start fresh:
 | 
						|
   if ( winState.appWindow )
 | 
						|
   {
 | 
						|
      if ( winState.appDC )
 | 
						|
      {
 | 
						|
         Con::printf( "Releasing the device context..." );
 | 
						|
         ReleaseDC( winState.appWindow, winState.appDC );
 | 
						|
         winState.appDC = NULL;
 | 
						|
      }
 | 
						|
 | 
						|
      Con::printf( "Destroying the window..." );
 | 
						|
      DestroyWindow( winState.appWindow );
 | 
						|
      winState.appWindow = NULL;
 | 
						|
   }
 | 
						|
 | 
						|
   // If OpenGL library already loaded, shut it down and reload it:
 | 
						|
   if ( winState.hinstOpenGL )
 | 
						|
      GL_Shutdown();
 | 
						|
 | 
						|
   GL_Init( "opengl32", "glu32" );
 | 
						|
 | 
						|
	static bool onceAlready = false;
 | 
						|
	bool profiled = false;
 | 
						|
 | 
						|
	if ( !mFullScreenOnly && fullScreen && !onceAlready )
 | 
						|
	{	
 | 
						|
		OSVERSIONINFO OSVersionInfo;
 | 
						|
 | 
						|
		// HACK: The Voodoo5 on W2K will only work if the initial rendering
 | 
						|
		// context is windowed.  Can you believe this crap?
 | 
						|
		dMemset( &OSVersionInfo, 0, sizeof( OSVERSIONINFO ) );
 | 
						|
		OSVersionInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
 | 
						|
		if ( GetVersionEx( &OSVersionInfo ) &&
 | 
						|
		  	  OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
 | 
						|
		  	  OSVersionInfo.dwMajorVersion == 5 )
 | 
						|
			if ( !setScreenMode(	640, 480, bpp, false, true, false ) )
 | 
						|
				return false;
 | 
						|
			else
 | 
						|
			{
 | 
						|
				const char* vendorString   = (const char*) glGetString( GL_VENDOR );
 | 
						|
				const char* rendererString = (const char*) glGetString( GL_RENDERER );
 | 
						|
 | 
						|
				// only do this for the first session
 | 
						|
				if (!Con::getBoolVariable("$DisableSystemProfiling") &&
 | 
						|
					 ( dStrcmp(vendorString, Con::getVariable("$pref::Video::profiledVendor")) ||
 | 
						|
       				dStrcmp(rendererString, Con::getVariable("$pref::Video::profiledRenderer")) ))
 | 
						|
				{
 | 
						|
       			profileSystem(vendorString, rendererString);
 | 
						|
					profiled = true;
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
		onceAlready = true;
 | 
						|
	}
 | 
						|
	// Set the resolution:
 | 
						|
   if ( !setScreenMode( width, height, bpp, ( fullScreen || mFullScreenOnly ), true, false ) )
 | 
						|
      return false;
 | 
						|
 | 
						|
   // Get original gamma ramp
 | 
						|
   mRestoreGamma = GetDeviceGammaRamp(winState.appDC, mOriginalRamp);
 | 
						|
 | 
						|
   // Output some driver info to the console:
 | 
						|
   const char* vendorString   = (const char*) glGetString( GL_VENDOR );
 | 
						|
   const char* rendererString = (const char*) glGetString( GL_RENDERER );
 | 
						|
   const char* versionString  = (const char*) glGetString( GL_VERSION );
 | 
						|
   Con::printf( "OpenGL driver information:" );
 | 
						|
   if ( vendorString )
 | 
						|
      Con::printf( "  Vendor: %s", vendorString );
 | 
						|
   if ( rendererString )
 | 
						|
      Con::printf( "  Renderer: %s", rendererString );
 | 
						|
   if ( versionString )
 | 
						|
      Con::printf( "  Version: %s", versionString );
 | 
						|
 | 
						|
   if ( needResurrect )
 | 
						|
   {
 | 
						|
      // Reload the textures:
 | 
						|
      Con::printf( "Resurrecting the texture manager..." );
 | 
						|
      Game->textureResurrect();
 | 
						|
   }
 | 
						|
 | 
						|
   GL_EXT_Init();
 | 
						|
 | 
						|
   Con::setVariable( "$pref::Video::displayDevice", mDeviceName );
 | 
						|
 | 
						|
   // only do this for the first session
 | 
						|
   if (!profiled &&
 | 
						|
   	 !Con::getBoolVariable("$DisableSystemProfiling") &&
 | 
						|
   	 (	dStrcmp(vendorString, Con::getVariable("$pref::Video::profiledVendor")) ||
 | 
						|
       	dStrcmp(rendererString, Con::getVariable("$pref::Video::profiledRenderer")) ))
 | 
						|
   {
 | 
						|
      profileSystem(vendorString, rendererString);
 | 
						|
		profiled = true;
 | 
						|
	}
 | 
						|
 | 
						|
	if (profiled)
 | 
						|
	{
 | 
						|
      U32 width, height, bpp;
 | 
						|
 | 
						|
		if (Con::getBoolVariable("$pref::Video::clipHigh", false))
 | 
						|
			for (S32 i = mResolutionList.size()-1; i >= 0; --i)
 | 
						|
				if (mResolutionList[i].w > 1152 || mResolutionList[i].h > 864)
 | 
						|
					mResolutionList.erase(i);
 | 
						|
 | 
						|
		if (Con::getBoolVariable("$pref::Video::only16", false))
 | 
						|
			for (S32 i = mResolutionList.size()-1; i >= 0; --i)
 | 
						|
				if (mResolutionList[i].bpp == 32)
 | 
						|
					mResolutionList.erase(i);
 | 
						|
 | 
						|
      dSscanf(Con::getVariable("$pref::Video::resolution"), "%d %d %d", &width, &height, &bpp);
 | 
						|
      setScreenMode(width, height, bpp,
 | 
						|
                    Con::getBoolVariable("$pref::Video::fullScreen", true), false, false);
 | 
						|
   }
 | 
						|
 | 
						|
   // Do this here because we now know about the extensions:
 | 
						|
   if ( gGLState.suppSwapInterval )
 | 
						|
      setVerticalSync( !Con::getBoolVariable( "$pref::Video::disableVerticalSync" ) );
 | 
						|
	Con::setBoolVariable("$pref::OpenGL::allowTexGen", true);
 | 
						|
 | 
						|
   return true;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
void OpenGLDevice::shutdown()
 | 
						|
{
 | 
						|
   Con::printf( "Shutting down the OpenGL display device..." );
 | 
						|
 | 
						|
   if ( winState.hGLRC )
 | 
						|
   {
 | 
						|
      if (mRestoreGamma)
 | 
						|
         SetDeviceGammaRamp(winState.appDC, mOriginalRamp);
 | 
						|
 | 
						|
      Con::printf( "Making the GL rendering context not current..." );
 | 
						|
      dwglMakeCurrent( NULL, NULL );
 | 
						|
		if ( Con::getBoolVariable("$pref::Video::deleteContext", true) )
 | 
						|
      {
 | 
						|
         Con::printf( "Deleting the GL rendering context..." );
 | 
						|
			dwglDeleteContext( winState.hGLRC );
 | 
						|
      }
 | 
						|
      winState.hGLRC = NULL;
 | 
						|
   }
 | 
						|
 | 
						|
   if ( winState.appDC )
 | 
						|
   {
 | 
						|
      Con::printf( "Releasing the device context..." );
 | 
						|
      ReleaseDC( winState.appWindow, winState.appDC );
 | 
						|
      winState.appDC = NULL;
 | 
						|
   }
 | 
						|
 | 
						|
   if ( smIsFullScreen )
 | 
						|
   {
 | 
						|
      Con::printf( "Restoring the desktop display settings (%dx%dx%d)...", winState.desktopWidth, winState.desktopHeight, winState.desktopBitsPixel );
 | 
						|
      ChangeDisplaySettings( NULL, 0 );
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
// This is the real workhorse function of the DisplayDevice...
 | 
						|
//
 | 
						|
bool OpenGLDevice::setScreenMode( U32 width, U32 height, U32 bpp, bool fullScreen, bool forceIt, bool repaint )
 | 
						|
{
 | 
						|
   HWND curtain = NULL;
 | 
						|
   char errorMessage[256];
 | 
						|
   Resolution newRes( width, height, bpp );
 | 
						|
   bool newFullScreen = fullScreen;
 | 
						|
   bool safeModeOn = Con::getBoolVariable( "$pref::Video::safeModeOn" );
 | 
						|
 | 
						|
   if ( !newFullScreen && mFullScreenOnly )
 | 
						|
   {
 | 
						|
      Con::warnf( ConsoleLogEntry::General, "OpenGLDevice::setScreenMode - device or desktop color depth does not allow windowed mode!" );
 | 
						|
      newFullScreen = true;
 | 
						|
   }
 | 
						|
 | 
						|
   if ( !newFullScreen && ( newRes.w >= winState.desktopWidth || newRes.h >= winState.desktopHeight ) )
 | 
						|
   {
 | 
						|
      Con::warnf( ConsoleLogEntry::General, "OpenGLDevice::setScreenMode -- can't switch to resolution larger than desktop in windowed mode!" );
 | 
						|
      // Find the largest standard resolution that will fit on the desktop:
 | 
						|
      U32 resIndex;
 | 
						|
      for ( resIndex = mResolutionList.size() - 1; resIndex > 0; resIndex-- )
 | 
						|
      {
 | 
						|
         if ( mResolutionList[resIndex].w < winState.desktopWidth
 | 
						|
           && mResolutionList[resIndex].h < winState.desktopHeight )
 | 
						|
            break;
 | 
						|
      }
 | 
						|
      newRes = mResolutionList[resIndex];
 | 
						|
   }
 | 
						|
 | 
						|
   if ( newRes.w < 480 || newRes.h < 360 )
 | 
						|
   {
 | 
						|
      Con::warnf( ConsoleLogEntry::General, "OpenGLDevice::setScreenMode -- can't go smaller than 480x360!" );
 | 
						|
      return false;
 | 
						|
   }
 | 
						|
 | 
						|
   if ( newFullScreen )
 | 
						|
   {
 | 
						|
      if (newRes.bpp != 16 && mFullScreenOnly)
 | 
						|
         newRes.bpp = 32;
 | 
						|
 | 
						|
      // Match the new resolution to one in the list:
 | 
						|
      U32 resIndex = 0;
 | 
						|
      U32 bestScore = 0, thisScore = 0;
 | 
						|
      for ( int i = 0; i < mResolutionList.size(); i++ )
 | 
						|
      {
 | 
						|
         if ( newRes == mResolutionList[i] )
 | 
						|
         {
 | 
						|
            resIndex = i;
 | 
						|
            break;
 | 
						|
         }
 | 
						|
         else
 | 
						|
         {
 | 
						|
            thisScore = abs( S32( newRes.w ) - S32( mResolutionList[i].w ) )
 | 
						|
                      + abs( S32( newRes.h ) - S32( mResolutionList[i].h ) )
 | 
						|
                      + ( newRes.bpp == mResolutionList[i].bpp ? 0 : 1 );
 | 
						|
 | 
						|
            if ( !bestScore || ( thisScore < bestScore ) )
 | 
						|
            {
 | 
						|
               bestScore = thisScore;
 | 
						|
               resIndex = i;
 | 
						|
            }
 | 
						|
         }
 | 
						|
      }
 | 
						|
 | 
						|
      newRes = mResolutionList[resIndex];
 | 
						|
   }
 | 
						|
   else
 | 
						|
   {
 | 
						|
      // Basically ignore the bit depth parameter:
 | 
						|
      newRes.bpp = winState.desktopBitsPixel;
 | 
						|
   }
 | 
						|
 | 
						|
   // Return if already at this resolution:
 | 
						|
   if ( !forceIt && newRes == smCurrentRes && newFullScreen == smIsFullScreen )
 | 
						|
      return true;
 | 
						|
 | 
						|
   Con::printf( "Setting screen mode to %dx%dx%d (%s)...", newRes.w, newRes.h, newRes.bpp, ( newFullScreen ? "fs" : "w" ) );
 | 
						|
 | 
						|
   bool needResurrect = false;
 | 
						|
 | 
						|
   if ( ( newRes.bpp != smCurrentRes.bpp ) || ( safeModeOn && ( ( smIsFullScreen != newFullScreen ) || newFullScreen ) ) )
 | 
						|
   {
 | 
						|
      // Delete the rendering context:
 | 
						|
      if ( winState.hGLRC )
 | 
						|
      {
 | 
						|
         if (!Video::smNeedResurrect)
 | 
						|
			{
 | 
						|
         	Con::printf( "Killing the texture manager..." );
 | 
						|
         	Game->textureKill();
 | 
						|
         	needResurrect = true;
 | 
						|
			}
 | 
						|
 | 
						|
         Con::printf( "Making the rendering context not current..." );
 | 
						|
         if ( !dwglMakeCurrent( NULL, NULL ) )
 | 
						|
         {
 | 
						|
            AssertFatal( false, "OpenGLDevice::setScreenMode\ndwglMakeCurrent( NULL, NULL ) failed!" );
 | 
						|
            return false;
 | 
						|
         }
 | 
						|
 | 
						|
         Con::printf( "Deleting the rendering context..." );
 | 
						|
         if ( Con::getBoolVariable("$pref::Video::deleteContext",true) &&
 | 
						|
         	  !dwglDeleteContext( winState.hGLRC ) )
 | 
						|
         {
 | 
						|
            AssertFatal( false, "OpenGLDevice::setScreenMode\ndwglDeleteContext failed!" );
 | 
						|
            return false;
 | 
						|
         }
 | 
						|
         winState.hGLRC = NULL;
 | 
						|
      }
 | 
						|
 | 
						|
      // Release the device context:
 | 
						|
      if ( winState.appDC )
 | 
						|
      {
 | 
						|
         Con::printf( "Releasing the device context..." );
 | 
						|
         ReleaseDC( winState.appWindow, winState.appDC );
 | 
						|
         winState.appDC = NULL;
 | 
						|
      }
 | 
						|
 | 
						|
      // Destroy the window:
 | 
						|
      if ( winState.appWindow )
 | 
						|
      {
 | 
						|
         Con::printf( "Destroying the window..." );
 | 
						|
         DestroyWindow( winState.appWindow );
 | 
						|
         winState.appWindow = NULL;
 | 
						|
      }
 | 
						|
   }
 | 
						|
   else if ( smIsFullScreen != newFullScreen )
 | 
						|
   {
 | 
						|
      // Change the window style:
 | 
						|
      Con::printf( "Changing the window style..." );
 | 
						|
      S32 windowStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
 | 
						|
      if ( newFullScreen )
 | 
						|
         windowStyle |= ( WS_MAXIMIZE | WS_VISIBLE);
 | 
						|
      else
 | 
						|
         windowStyle |= ( WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX );
 | 
						|
 | 
						|
      if ( winState.appWindow && !SetWindowLong( winState.appWindow, GWL_STYLE, windowStyle ) )
 | 
						|
         Con::errorf( "SetWindowLong failed to change the window style!" );
 | 
						|
   }
 | 
						|
 | 
						|
   if( winState.appWindow && !newFullScreen )
 | 
						|
      ShowWindow( winState.appWindow, SW_NORMAL );
 | 
						|
   else
 | 
						|
      ShowWindow( winState.appWindow, SW_MAXIMIZE );
 | 
						|
 | 
						|
 | 
						|
   U32 test;
 | 
						|
   if ( newFullScreen )
 | 
						|
   {
 | 
						|
      // Change the display settings:
 | 
						|
      DEVMODE devMode;
 | 
						|
      dMemset( &devMode, 0, sizeof( devMode ) );
 | 
						|
      devMode.dmSize       = sizeof( devMode );
 | 
						|
      devMode.dmPelsWidth  = newRes.w;
 | 
						|
      devMode.dmPelsHeight = newRes.h;
 | 
						|
      devMode.dmBitsPerPel = newRes.bpp;
 | 
						|
      devMode.dmFields     = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
 | 
						|
 | 
						|
      Con::printf( "Changing the display settings to %dx%dx%d...", newRes.w, newRes.h, newRes.bpp );
 | 
						|
      curtain = CreateCurtain( newRes.w, newRes.h );
 | 
						|
      test = ChangeDisplaySettings( &devMode, CDS_FULLSCREEN );
 | 
						|
      if ( test != DISP_CHANGE_SUCCESSFUL )
 | 
						|
      {
 | 
						|
         smIsFullScreen = false;
 | 
						|
         Con::setBoolVariable( "$pref::Video::fullScreen", false );
 | 
						|
         ChangeDisplaySettings( NULL, 0 );
 | 
						|
         Con::errorf( ConsoleLogEntry::General, "OpenGLDevice::setScreenMode - ChangeDisplaySettings failed." );
 | 
						|
         switch( test )
 | 
						|
         {
 | 
						|
            case DISP_CHANGE_RESTART:
 | 
						|
               Platform::AlertOK( "Display Change Failed", "You must restart your machine to get the specified mode." );
 | 
						|
               break;
 | 
						|
 | 
						|
            case DISP_CHANGE_BADMODE:
 | 
						|
               Platform::AlertOK( "Display Change Failed", "The specified mode is not supported by this device." );
 | 
						|
               break;
 | 
						|
 | 
						|
            default:
 | 
						|
               Platform::AlertOK( "Display Change Failed", "Hardware failed to switch to the specified mode." );
 | 
						|
               break;
 | 
						|
         };
 | 
						|
         DestroyWindow( curtain );
 | 
						|
         return false;
 | 
						|
      }
 | 
						|
      else
 | 
						|
         smIsFullScreen = true;
 | 
						|
   }
 | 
						|
   else if ( smIsFullScreen )
 | 
						|
   {
 | 
						|
      Con::printf( "Changing to the desktop display settings (%dx%dx%d)...", winState.desktopWidth, winState.desktopHeight, winState.desktopBitsPixel );
 | 
						|
      ChangeDisplaySettings( NULL, 0 );
 | 
						|
      smIsFullScreen = false;
 | 
						|
   }
 | 
						|
   Con::setBoolVariable( "$pref::Video::fullScreen", smIsFullScreen );
 | 
						|
 | 
						|
   bool newWindow = false;
 | 
						|
   if ( !winState.appWindow )
 | 
						|
   {
 | 
						|
      Con::printf( "Creating a new %swindow...", ( fullScreen ? "full-screen " : "" ) );
 | 
						|
      winState.appWindow = CreateOpenGLWindow( newRes.w, newRes.h, newFullScreen );
 | 
						|
      if ( !winState.appWindow )
 | 
						|
      {
 | 
						|
         AssertFatal( false, "OpenGLDevice::setScreenMode\nFailed to create a new window!" );
 | 
						|
         return false;
 | 
						|
      }
 | 
						|
      newWindow = true;
 | 
						|
   }
 | 
						|
 | 
						|
   // Move the window:
 | 
						|
   if ( !newFullScreen )
 | 
						|
   {
 | 
						|
      // Adjust the window rect to compensate for the window style:
 | 
						|
      RECT windowRect;
 | 
						|
      windowRect.left = windowRect.top = 0;
 | 
						|
      windowRect.right = newRes.w;
 | 
						|
      windowRect.bottom = newRes.h;
 | 
						|
 | 
						|
      AdjustWindowRect( &windowRect, GetWindowLong( winState.appWindow, GWL_STYLE ), false );
 | 
						|
      U32 adjWidth = windowRect.right - windowRect.left;
 | 
						|
      U32 adjHeight = windowRect.bottom - windowRect.top;
 | 
						|
 | 
						|
      // Center the window on the desktop:
 | 
						|
      U32 xPos = 0, yPos = 0;
 | 
						|
      
 | 
						|
      if(adjWidth < winState.desktopWidth)
 | 
						|
         xPos = ( winState.desktopWidth - adjWidth ) / 2;
 | 
						|
 | 
						|
      if(adjHeight < winState.desktopHeight)
 | 
						|
         yPos = ( winState.desktopHeight - adjHeight ) / 2;
 | 
						|
 | 
						|
      test = SetWindowPos( winState.appWindow, 0, xPos, yPos, adjWidth, adjHeight, SWP_NOZORDER );
 | 
						|
      if ( !test )
 | 
						|
      {
 | 
						|
         dSprintf( errorMessage, 255, "OpenGLDevice::setScreenMode\nSetWindowPos failed trying to move the window to (%d,%d) and size it to %dx%d.", xPos, yPos, newRes.w, newRes.h );
 | 
						|
         AssertFatal( false, errorMessage );
 | 
						|
         return false;
 | 
						|
      }
 | 
						|
   }
 | 
						|
   else if ( !newWindow )
 | 
						|
   {
 | 
						|
      // Move and size the window to take up the whole screen:
 | 
						|
      if ( !SetWindowPos( winState.appWindow, HWND_TOPMOST, 0, 0, newRes.w, newRes.h, SWP_NOACTIVATE)
 | 
						|
        || !SetWindowPos( winState.appWindow, HWND_TOPMOST, 0, 0, newRes.w, newRes.h, SWP_NOZORDER) )
 | 
						|
      {
 | 
						|
         dSprintf( errorMessage, 255, "OpenGLDevice::setScreenMode\nSetWindowPos failed to move the window to (0,0) and size it to %dx%d.", newRes.w, newRes.h );
 | 
						|
         AssertFatal( false, errorMessage );
 | 
						|
         return false;
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   bool newDeviceContext = false;
 | 
						|
   if ( !winState.appDC )
 | 
						|
   {
 | 
						|
      // Get a new device context:
 | 
						|
      Con::printf( "Acquiring a new device context..." );
 | 
						|
      winState.appDC = GetDC( winState.appWindow );
 | 
						|
      if ( !winState.appDC )
 | 
						|
      {
 | 
						|
         AssertFatal( false, "OpenGLDevice::setScreenMode\nGetDC failed to get a valid device context!" );
 | 
						|
         return false;
 | 
						|
      }
 | 
						|
      newDeviceContext = true;
 | 
						|
   }
 | 
						|
 | 
						|
   if ( newWindow )
 | 
						|
   {
 | 
						|
      // Set the pixel format of the new window:
 | 
						|
      PIXELFORMATDESCRIPTOR pfd;
 | 
						|
      CreatePixelFormat( &pfd, newRes.bpp, 24, 8, false );
 | 
						|
      S32 chosenFormat = ChooseBestPixelFormat( winState.appDC, &pfd );
 | 
						|
      if ( !chosenFormat )
 | 
						|
      {
 | 
						|
         AssertFatal( false, "OpenGLDevice::setScreenMode\nNo valid pixel formats found!" );
 | 
						|
         return false;
 | 
						|
      }
 | 
						|
      dwglDescribePixelFormat( winState.appDC, chosenFormat, sizeof( pfd ), &pfd );
 | 
						|
      if ( !SetPixelFormat( winState.appDC, chosenFormat, &pfd ) )
 | 
						|
      {
 | 
						|
         AssertFatal( false, "OpenGLDevice::setScreenMode\nFailed to set the pixel format!" );
 | 
						|
         return false;
 | 
						|
      }
 | 
						|
      Con::printf( "Pixel format set:" );
 | 
						|
      Con::printf( "  %d color bits, %d depth bits, %d stencil bits", pfd.cColorBits, pfd.cDepthBits, pfd.cStencilBits );
 | 
						|
   }
 | 
						|
 | 
						|
   if ( !winState.hGLRC )
 | 
						|
   {
 | 
						|
      // Create a new rendering context:
 | 
						|
      Con::printf( "Creating a new rendering context..." );
 | 
						|
      winState.hGLRC = dwglCreateContext( winState.appDC );
 | 
						|
      if ( !winState.hGLRC )
 | 
						|
      {
 | 
						|
         AssertFatal( false, "OpenGLDevice::setScreenMode\ndwglCreateContext failed to create an OpenGL rendering context!" );
 | 
						|
         return false;
 | 
						|
      }
 | 
						|
 | 
						|
      // Make the new rendering context current:
 | 
						|
      Con::printf( "Making the new rendering context current..." );
 | 
						|
      if ( !dwglMakeCurrent( winState.appDC, winState.hGLRC ) )
 | 
						|
      {
 | 
						|
			AssertFatal( false, "OpenGLDevice::setScreenMode\ndwglMakeCurrent failed to make the rendering context current!" );
 | 
						|
			return false;
 | 
						|
      }
 | 
						|
 | 
						|
      // Just for kicks.  Seems a relatively central place to put this...
 | 
						|
      glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 | 
						|
 | 
						|
      if ( needResurrect )
 | 
						|
      {
 | 
						|
         // Reload the textures:
 | 
						|
         Con::printf( "Resurrecting the texture manager..." );
 | 
						|
         Game->textureResurrect();
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   // Just for kicks.  Seems a relatively central place to put this...
 | 
						|
   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 | 
						|
 | 
						|
   if ( newDeviceContext && gGLState.suppSwapInterval )
 | 
						|
      setVerticalSync( !Con::getBoolVariable( "$pref::Video::disableVerticalSync" ) );
 | 
						|
 | 
						|
   smCurrentRes = newRes;
 | 
						|
   Platform::setWindowSize( newRes.w, newRes.h );
 | 
						|
   char tempBuf[15];
 | 
						|
   dSprintf( tempBuf, sizeof( tempBuf ), "%d %d %d", smCurrentRes.w, smCurrentRes.h, smCurrentRes.bpp );
 | 
						|
   Con::setVariable( "$pref::Video::resolution", tempBuf );
 | 
						|
 | 
						|
   if ( curtain )
 | 
						|
      DestroyWindow( curtain );
 | 
						|
 | 
						|
   // Doesn't hurt to do this even it isn't necessary:
 | 
						|
   ShowWindow( winState.appWindow, SW_SHOW );
 | 
						|
   SetForegroundWindow( winState.appWindow );
 | 
						|
   SetFocus( winState.appWindow );
 | 
						|
 | 
						|
   if (newFullScreen)
 | 
						|
   {
 | 
						|
      // Doesn't hurt to do this an extra time, and seems to help in some cases
 | 
						|
      if ( !SetWindowPos( winState.appWindow, HWND_TOPMOST, 0, 0, newRes.w, newRes.h, SWP_NOACTIVATE)
 | 
						|
        || !SetWindowPos( winState.appWindow, HWND_TOPMOST, 0, 0, newRes.w, newRes.h, SWP_NOZORDER) )
 | 
						|
      {
 | 
						|
         dSprintf( errorMessage, 255, "OpenGLDevice::setScreenMode\nSetWindowPos failed to move the window to (0,0) and size it to %dx%d.", newRes.w, newRes.h );
 | 
						|
         AssertFatal( false, errorMessage );
 | 
						|
         return false;
 | 
						|
      }
 | 
						|
   }
 | 
						|
 | 
						|
   if ( repaint )
 | 
						|
      Con::evaluate( "resetCanvas();" );
 | 
						|
 | 
						|
   return true;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
void OpenGLDevice::swapBuffers()
 | 
						|
{
 | 
						|
   dwglSwapBuffers( winState.appDC );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
const char* OpenGLDevice::getDriverInfo()
 | 
						|
{
 | 
						|
   // Output some driver info to the console:
 | 
						|
   const char* vendorString   = (const char*) glGetString( GL_VENDOR );
 | 
						|
   const char* rendererString = (const char*) glGetString( GL_RENDERER );
 | 
						|
   const char* versionString  = (const char*) glGetString( GL_VERSION );
 | 
						|
   const char* extensionsString = (const char*) glGetString( GL_EXTENSIONS );
 | 
						|
 | 
						|
   U32 bufferLen = ( vendorString ? dStrlen( vendorString ) : 0 )
 | 
						|
                 + ( rendererString ? dStrlen( rendererString ) : 0 )
 | 
						|
                 + ( versionString  ? dStrlen( versionString ) : 0 )
 | 
						|
                 + ( extensionsString ? dStrlen( extensionsString ) : 0 )
 | 
						|
                 + 4;
 | 
						|
 | 
						|
   char* returnString = Con::getReturnBuffer( bufferLen );
 | 
						|
   dSprintf( returnString, bufferLen, "%s\t%s\t%s\t%s",
 | 
						|
         ( vendorString ? vendorString : "" ),
 | 
						|
         ( rendererString ? rendererString : "" ),
 | 
						|
         ( versionString ? versionString : "" ),
 | 
						|
         ( extensionsString ? extensionsString : "" ) );
 | 
						|
 | 
						|
   return( returnString );
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
bool OpenGLDevice::getGammaCorrection(F32 &g)
 | 
						|
{
 | 
						|
   U16 ramp[256*3];
 | 
						|
 | 
						|
   if (!GetDeviceGammaRamp(winState.appDC, ramp))
 | 
						|
      return false;
 | 
						|
 | 
						|
   F32 csum = 0.0;
 | 
						|
   U32 ccount = 0;
 | 
						|
 | 
						|
   for (U16 i = 0; i < 256; ++i)
 | 
						|
   {
 | 
						|
      if (i != 0 && ramp[i] != 0 && ramp[i] != 65535)
 | 
						|
      {
 | 
						|
         F64 b = (F64) i/256.0;
 | 
						|
         F64 a = (F64) ramp[i]/65535.0;
 | 
						|
         F32 c = (F32) (mLog(a)/mLog(b));
 | 
						|
 | 
						|
         csum += c;
 | 
						|
         ++ccount;
 | 
						|
      }
 | 
						|
   }
 | 
						|
   g = csum/ccount;
 | 
						|
 | 
						|
   return true;
 | 
						|
}
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
bool OpenGLDevice::setGammaCorrection(F32 g)
 | 
						|
{
 | 
						|
   U16 ramp[256*3];
 | 
						|
 | 
						|
   for (U16 i = 0; i < 256; ++i)
 | 
						|
      ramp[i] = mPow((F32) i/256.0f, g) * 65535.0f;
 | 
						|
   dMemcpy(&ramp[256],ramp,256*sizeof(U16));
 | 
						|
   dMemcpy(&ramp[512],ramp,256*sizeof(U16));
 | 
						|
 | 
						|
   return SetDeviceGammaRamp(winState.appDC, ramp);
 | 
						|
}
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
bool OpenGLDevice::setVerticalSync( bool on )
 | 
						|
{
 | 
						|
   if ( !gGLState.suppSwapInterval )
 | 
						|
      return( false );
 | 
						|
 | 
						|
   return( dwglSwapIntervalEXT( on ? 1 : 0 ) );
 | 
						|
}
 | 
						|
 | 
						|
//------------------------------------------------------------------------------
 | 
						|
DisplayDevice* OpenGLDevice::create()
 | 
						|
{
 | 
						|
   bool result = false;
 | 
						|
   bool fullScreenOnly = false;
 | 
						|
 | 
						|
   OSVERSIONINFO OSVersionInfo;
 | 
						|
	U32 switchedNT = false;
 | 
						|
 | 
						|
   dMemset( &OSVersionInfo, 0, sizeof( OSVERSIONINFO ) );
 | 
						|
   OSVersionInfo.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
 | 
						|
   if ( GetVersionEx( &OSVersionInfo ) &&
 | 
						|
        OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
 | 
						|
   {
 | 
						|
      DEVMODE devMode;
 | 
						|
 | 
						|
      dMemset( &devMode, 0, sizeof( devMode ) );
 | 
						|
      devMode.dmSize = sizeof( devMode );
 | 
						|
      devMode.dmBitsPerPel = winState.desktopBitsPixel == 16 ? 32 : 16;
 | 
						|
      devMode.dmFields = DM_BITSPERPEL;
 | 
						|
 | 
						|
      // attempt bit-depth change to test Windows 95B
 | 
						|
      if ( ChangeDisplaySettings( &devMode, CDS_TEST ) != DISP_CHANGE_SUCCESSFUL )
 | 
						|
         smCanSwitchBitDepth = false;
 | 
						|
   }
 | 
						|
	// switching NT to 32-bit desktop to determine if we have a 16-bit card
 | 
						|
	else if (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
 | 
						|
				OSVersionInfo.dwMajorVersion == 4 &&
 | 
						|
				winState.desktopBitsPixel != 32)
 | 
						|
	{
 | 
						|
		DEVMODE devMode;
 | 
						|
 | 
						|
		dMemset( &devMode, 0, sizeof( devMode ) );
 | 
						|
		devMode.dmSize       = sizeof( devMode );
 | 
						|
		devMode.dmBitsPerPel = 32;
 | 
						|
		devMode.dmFields     = DM_BITSPERPEL;
 | 
						|
 | 
						|
		switchedNT = ChangeDisplaySettings( &devMode, 0 ) == DISP_CHANGE_SUCCESSFUL;
 | 
						|
	}
 | 
						|
 | 
						|
   // This shouldn't happen, but just to be safe...
 | 
						|
   //------------------------------------------------------------------------------
 | 
						|
   if ( winState.hinstOpenGL )
 | 
						|
      GL_Shutdown();
 | 
						|
 | 
						|
   //------------------------------------------------------------------------------
 | 
						|
   // Initialize GL
 | 
						|
   //------------------------------------------------------------------------------
 | 
						|
   if (!GL_Init( "opengl32", "glu32" ))
 | 
						|
	{
 | 
						|
		if (switchedNT)
 | 
						|
			ChangeDisplaySettings( NULL, 0 );
 | 
						|
 | 
						|
		return NULL;
 | 
						|
	}
 | 
						|
 | 
						|
   //------------------------------------------------------------------------------
 | 
						|
   // Create a test window to see if OpenGL hardware acceleration is available:
 | 
						|
   //------------------------------------------------------------------------------
 | 
						|
   WNDCLASS wc;
 | 
						|
   dMemset(&wc, 0, sizeof(wc));
 | 
						|
   wc.style         = CS_OWNDC;
 | 
						|
   wc.lpfnWndProc   = DefWindowProc;
 | 
						|
   wc.hInstance     = winState.appInstance;
 | 
						|
   wc.lpszClassName = dT("OGLTest");
 | 
						|
   RegisterClass( &wc );
 | 
						|
 | 
						|
   HWND testWindow = CreateWindow(
 | 
						|
      dT("OGLTest"),
 | 
						|
      dT(""),
 | 
						|
      WS_POPUP,
 | 
						|
      0, 0, 640, 480,
 | 
						|
      NULL,
 | 
						|
      NULL,
 | 
						|
      winState.appInstance,
 | 
						|
      NULL );
 | 
						|
 | 
						|
   if ( testWindow )
 | 
						|
   {
 | 
						|
      HDC testDC = GetDC( testWindow );
 | 
						|
      if ( testDC )
 | 
						|
      {
 | 
						|
         PIXELFORMATDESCRIPTOR pfd;
 | 
						|
         CreatePixelFormat( &pfd, 16, 16, 8, false );
 | 
						|
         U32 chosenFormat = ChooseBestPixelFormat( testDC, &pfd );
 | 
						|
         if ( chosenFormat != 0 )
 | 
						|
         {
 | 
						|
            dwglDescribePixelFormat( testDC, chosenFormat, sizeof( pfd ), &pfd );
 | 
						|
 | 
						|
            result = !( pfd.dwFlags & PFD_GENERIC_FORMAT );
 | 
						|
 | 
						|
  				if ( result && (winState.desktopBitsPixel == 16 || pfd.cColorBits == 16) )
 | 
						|
					D3DDevice::smStay16 = true;
 | 
						|
 | 
						|
            if ( result && winState.desktopBitsPixel != 16 && !smCanSwitchBitDepth)
 | 
						|
            {
 | 
						|
               // If Windows 95 cannot switch bit depth, it should only attempt 16-bit cards
 | 
						|
               // with a 16-bit desktop
 | 
						|
 | 
						|
               // See if we can get a 32-bit pixel format:
 | 
						|
               PIXELFORMATDESCRIPTOR pfd;
 | 
						|
 | 
						|
               CreatePixelFormat( &pfd, 32, 24, 8, false );
 | 
						|
               S32 chosenFormat = ChooseBestPixelFormat( testDC, &pfd );
 | 
						|
               if ( chosenFormat != 0 )
 | 
						|
               {
 | 
						|
                  dwglDescribePixelFormat( winState.appDC, chosenFormat, sizeof( pfd ), &pfd );
 | 
						|
 | 
						|
                  if (pfd.cColorBits == 16)
 | 
						|
                  {
 | 
						|
                     Platform::AlertOK("Requires 16-Bit Desktop",
 | 
						|
                                       "You must run in 16-bit color to run a Torque game.\nPlease quit the game, set your desktop color depth to 16-bit\nand then restart the application.");
 | 
						|
 | 
						|
                     result = false;
 | 
						|
                  }
 | 
						|
               }
 | 
						|
            }
 | 
						|
            // Don't allow 16-bit cards to do windowed mode on NT
 | 
						|
            else if (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT &&
 | 
						|
                     OSVersionInfo.dwMajorVersion == 4 &&
 | 
						|
                     result && pfd.cColorBits == 16)
 | 
						|
               fullScreenOnly = true;
 | 
						|
         }
 | 
						|
         else if ( (winState.desktopBitsPixel != 16 || switchedNT) && smCanSwitchBitDepth )
 | 
						|
         {
 | 
						|
            // Try again after changing the display to 16-bit:
 | 
						|
            ReleaseDC( testWindow, testDC );
 | 
						|
            DestroyWindow( testWindow );
 | 
						|
 | 
						|
            DEVMODE devMode;
 | 
						|
            dMemset( &devMode, 0, sizeof( devMode ) );
 | 
						|
            devMode.dmSize       = sizeof( devMode );
 | 
						|
            devMode.dmBitsPerPel = 16;
 | 
						|
            devMode.dmFields     = DM_BITSPERPEL;
 | 
						|
 | 
						|
            U32 test = ChangeDisplaySettings( &devMode, 0 );
 | 
						|
            if ( test == DISP_CHANGE_SUCCESSFUL )
 | 
						|
            {
 | 
						|
               testWindow = CreateWindow(
 | 
						|
                  dT("OGLTest"), 
 | 
						|
                  dT(""), 
 | 
						|
                  WS_OVERLAPPED | WS_CAPTION,
 | 
						|
                  0, 0, 640, 480,
 | 
						|
                  NULL,
 | 
						|
                  NULL,
 | 
						|
                  winState.appInstance,
 | 
						|
                  NULL );
 | 
						|
 | 
						|
               if ( testWindow )
 | 
						|
               {
 | 
						|
                  testDC = GetDC( testWindow );
 | 
						|
                  if ( testDC )
 | 
						|
                  {
 | 
						|
                     CreatePixelFormat( &pfd, 16, 16, 8, false );
 | 
						|
                     chosenFormat = ChooseBestPixelFormat( testDC, &pfd );
 | 
						|
                     if ( chosenFormat != 0 )
 | 
						|
                     {
 | 
						|
                        dwglDescribePixelFormat( testDC, chosenFormat, sizeof( pfd ), &pfd );
 | 
						|
 | 
						|
                        result = !( pfd.dwFlags & PFD_GENERIC_FORMAT );
 | 
						|
                        if ( result )
 | 
						|
                           fullScreenOnly = true;
 | 
						|
                     }
 | 
						|
                  }
 | 
						|
               }
 | 
						|
            }
 | 
						|
            ChangeDisplaySettings( NULL, 0 );
 | 
						|
				switchedNT = false;
 | 
						|
         }
 | 
						|
         else if ( winState.desktopBitsPixel != 16 && !smCanSwitchBitDepth )
 | 
						|
            Platform::AlertOK("Requires 16-Bit Desktop",
 | 
						|
                              "You must run in 16-bit color to run a Torque game.\nPlease quit the game, set your desktop color depth to 16-bit\nand then restart the application.");
 | 
						|
 | 
						|
         ReleaseDC( testWindow, testDC );
 | 
						|
      }
 | 
						|
      DestroyWindow( testWindow );
 | 
						|
   }
 | 
						|
 | 
						|
   UnregisterClass( dT("OGLTest"), winState.appInstance );
 | 
						|
 | 
						|
   GL_Shutdown();
 | 
						|
 | 
						|
	// Return NT to previous desktop bit depth
 | 
						|
	if (switchedNT)
 | 
						|
		ChangeDisplaySettings( NULL, 0 );
 | 
						|
 | 
						|
   if ( result )
 | 
						|
   {
 | 
						|
      OpenGLDevice* newOGLDevice = new OpenGLDevice();
 | 
						|
      if ( newOGLDevice )
 | 
						|
      {
 | 
						|
         newOGLDevice->mFullScreenOnly = fullScreenOnly;
 | 
						|
         return (DisplayDevice*) newOGLDevice;
 | 
						|
      }
 | 
						|
      else
 | 
						|
         return NULL;
 | 
						|
   }
 | 
						|
   else
 | 
						|
      return NULL;
 | 
						|
}
 |