diff --git a/src/libs/tgf/tgf.cpp b/src/libs/tgf/tgf.cpp index 738fc305b..36a03a159 100644 --- a/src/libs/tgf/tgf.cpp +++ b/src/libs/tgf/tgf.cpp @@ -465,20 +465,24 @@ void GfInit(void) */ void GfShutdown(void) { + GfLogDebug("Shutting down gaming framework.\n"); + // Shudown SDL. SDL_Quit(); // Shutdown the active profilers and dump the report if any. GfProfStopActiveProfiles(); - GfProfPrintReport(); + GfProfPrintReport(); } /** Restart the gaming framework (restart the current process). @ingroup tgf @param bHardwareMouse If true, use hardware mouse cursor @return None - @warning Never returns (restart the process). + @warning GfShutdown should be called before ; never returns (restart the process). */ + +// TODO: Move this to the GfApplication/GfuiApplication separate scheme. void GfRestart(bool bHardwareMouse) { int retcode = 0; @@ -549,7 +553,7 @@ void GfRestart(bool bHardwareMouse) // Finally, last null arg. args[argInd] = 0; - + // Exec the command : restart the game (simply replacing current process) GfLogInfo("Restarting "); for (i = 0; args[i]; i++) diff --git a/src/libs/tgfclient/glfeatures.cpp b/src/libs/tgfclient/glfeatures.cpp index 5e5c020d8..a3f4c6cde 100644 --- a/src/libs/tgfclient/glfeatures.cpp +++ b/src/libs/tgfclient/glfeatures.cpp @@ -18,12 +18,17 @@ #include +#include #include +//#include "guiscreen.h" #include "glfeatures.h" +static const char* pszNoUnit = 0; + + /** Report if a given OpenGL extension is supported Warning: Should not be called before any successfull call to SDL_SetVideoMode() @@ -36,7 +41,7 @@ static bool gfglIsOpenGLExtensionSupported(const char* extension) const char *extensions, *start; const int len = strlen(extension); - /* TODO: Make sure there is a current window, and thus a current context available */ + // TODO: Make sure there is a current window, and thus a current context available if (strchr(extension, ' ')) return false; @@ -46,15 +51,17 @@ static bool gfglIsOpenGLExtensionSupported(const char* extension) if (!extensions) return false; - while (1) + while (true) { const char *p = strstr(extensions, extension); if (!p) - return 0; /* not found */ - /* check that the match isn't a super string */ + return 0; // Not found + + // Check that the match isn't a super string if ((p == start || p[-1] == ' ') && (p[len] == ' ' || p[len] == 0)) return true; - /* skip the false match and continue */ + + // Skip the false match and continue extensions = p + len; } @@ -63,14 +70,14 @@ static bool gfglIsOpenGLExtensionSupported(const char* extension) // GfglFeatures singleton -------------------------------------------------------- +// Initialization. GfglFeatures* GfglFeatures::_pSelf = 0; -// Initialization. GfglFeatures::GfglFeatures() +//: hparmConfig(0) { } -// Initialization. GfglFeatures& GfglFeatures::self() { if (!_pSelf) @@ -79,66 +86,58 @@ GfglFeatures& GfglFeatures::self() return *_pSelf; } -// Warning: Should not be called before any successfull call to SDL_SetVideoMode() -void GfglFeatures::checkSupport() +// Values for the "not supported" / "not selected" numerical cases. +int GfglFeatures::InvalidInt = std::numeric_limits::min(); + +// Config file management. +void* GfglFeatures::openConfigFile() { - int nValue; - bool bValue; + std::ostringstream ossParm; + ossParm << GfLocalDir() << GFSCR_CONF_FILE; + + return GfParmReadFile(ossParm.str().c_str(), GFPARM_RMODE_STD | GFPARM_RMODE_CREAT); +} + +void GfglFeatures::closeConfigFile(void* hparmConfig, bool bWrite) +{ + // Write if specified. + if (bWrite) + GfParmWriteFile(NULL, hparmConfig, "Screen"); - GfLogInfo("Video hardware info :\n"); - GfLogInfo(" Vendor : %s\n", glGetString(GL_VENDOR)); - GfLogInfo(" Renderer : %s\n", glGetString(GL_RENDERER)); - GfLogInfo(" Version : %s\n", glGetString(GL_VERSION)); + // Close. + GfParmReleaseHandle(hparmConfig); +} - GfLogInfo("Supported OpenGL features :\n"); - - // 1) Double-buffer : if it is supported, it is set, so we simply read it (see GfScrInit). +// Standard supported features detection. +void GfglFeatures::detectStandardSupport() +{ + // 1) Double-buffer. + int nValue; SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &nValue); _mapSupportedBool[DoubleBuffer] = nValue ? true : false; - GfLogInfo(" Double buffer : %s\n", nValue ? "Yes" : "No"); - - // Update selection if needed. - if (!nValue) - _mapSelectedBool[DoubleBuffer] = false; // 2) Color buffer depth. - glGetIntegerv(GL_DEPTH_BITS, &nValue); + SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &nValue); + //glGetIntegerv(GL_DEPTH_BITS, &nValue); _mapSupportedInt[ColorDepth] = nValue; - GfLogInfo(" Color depth : %d bits\n", nValue); - - // Update selection if needed. - if (getSelected(ColorDepth) > nValue) - _mapSelectedInt[ColorDepth] = nValue; // 3) Alpha channel depth. - glGetIntegerv(GL_ALPHA_BITS, &nValue); + SDL_GL_GetAttribute(SDL_GL_ALPHA_SIZE, &nValue); + //glGetIntegerv(GL_ALPHA_BITS, &nValue); _mapSupportedInt[AlphaDepth] = nValue; - GfLogInfo(" Alpha channel : %s", nValue > 0 ? "Yes" : "No"); - if (nValue > 0) - GfLogInfo(" (%d bits)", nValue); - GfLogInfo("\n"); - - // Update selection if needed. - if (getSelected(AlphaDepth) > nValue) - _mapSelectedInt[AlphaDepth] = nValue; // 4) Max texture size. glGetIntegerv(GL_MAX_TEXTURE_SIZE, &nValue); if (nValue > 16384) // Max in-game supported value (must be consistent with openglconfig.cpp) nValue = 16384; _mapSupportedInt[TextureMaxSize] = nValue; - GfLogInfo(" Max texture size : %d\n", nValue); - // Update selection if needed. - if (getSelected(TextureMaxSize) > nValue) - _mapSelectedInt[TextureMaxSize] = nValue; - // 5) Texture compression. // Note: Check if at least one internal format is available. This is a workaround for // driver problems and not a bugfix. According to the specification OpenGL should // choose an uncompressed alternate format if it can't provide the requested // compressed one... but it does not on all cards/drivers. - bValue = gfglIsOpenGLExtensionSupported("GL_ARB_texture_compression"); + bool bValue = gfglIsOpenGLExtensionSupported("GL_ARB_texture_compression"); if (bValue) { int nFormats; @@ -147,155 +146,594 @@ void GfglFeatures::checkSupport() bValue = false; } _mapSupportedBool[TextureCompression] = bValue; - GfLogInfo(" Texture compression : %s\n", bValue ? "Yes" : "No"); - // Update selection if needed. - if (!bValue) - _mapSelectedBool[TextureCompression] = false; - // 6) Multi-texturing (automatically select all the texturing units). bValue = gfglIsOpenGLExtensionSupported("GL_ARB_multitexture"); glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &nValue); if (nValue < 2) bValue = false; _mapSupportedBool[MultiTexturing] = bValue; - _mapSupportedInt[MultiTexturingUnits] = nValue; - GfLogInfo(" Multi-texturing : %s", bValue ? "Yes" : "No", nValue); if (bValue) - GfLogInfo(" (%d units)", nValue); - GfLogInfo("\n"); + _mapSupportedInt[MultiTexturingUnits] = nValue; - // Update selection if needed. - if (!bValue) - _mapSelectedBool[MultiTexturing] = false; - _mapSelectedInt[MultiTexturingUnits] = nValue; // Auto-select. - // 7) Rectangle textures. - bValue = gfglIsOpenGLExtensionSupported("GL_ARB_texture_rectangle"); - _mapSupportedBool[TextureRectangle] = bValue; - GfLogInfo(" Rectangle textures : %s\n", bValue ? "Yes" : "No"); - - // Force selection. - _mapSelectedBool[TextureRectangle] = bValue; + _mapSupportedBool[TextureRectangle] = + gfglIsOpenGLExtensionSupported("GL_ARB_texture_rectangle"); // 8) Non-power-of-2 textures. - bValue = gfglIsOpenGLExtensionSupported("GL_ARB_texture_non_power_of_two"); - _mapSupportedBool[TextureNonPowerOf2] = bValue; - GfLogInfo(" Non power-of-2 textures : %s\n", bValue ? "Yes" : "No"); + _mapSupportedBool[TextureNonPowerOf2] = + gfglIsOpenGLExtensionSupported("GL_ARB_texture_non_power_of_two"); +} + +// Best supported features detection for the given specs of the frame buffer. +bool GfglFeatures::detectBestSupport(int& nWidth, int& nHeight, int& nDepth, + bool& bAlpha, bool& bFullScreen) +{ + GfLogInfo("Detecting best supported features for a %dx%dx%d%s frame buffer.\n", + nWidth, nHeight, nDepth, bFullScreen ? " full-screen" : ""); + + // I) Detection of the max possible values for requested features. + // (to do that, we need to try setting up the video modes for real). + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + + SDL_Surface* pWinSurface = 0; + + int nAlphaChannel; + int nCurrDepth; + int nFullScreen = bFullScreen ? 1 : 0; + while (!pWinSurface && nFullScreen >= 0) + { + GfLogTrace("Trying %s mode\n", nFullScreen ? "full-screen" : "windowed"); + const int bfVideoMode = SDL_OPENGL | (nFullScreen ? SDL_FULLSCREEN : 0); + + nAlphaChannel = bAlpha ? 1 : 0; + while (!pWinSurface && nAlphaChannel >= 0) + { + GfLogTrace("Trying with%s alpha channel\n", nAlphaChannel ? "" : "out"); + nCurrDepth = nDepth; + while (!pWinSurface && nCurrDepth >= 16) + { + GfLogTrace("Trying %d bits RVB+A color depth\n", nCurrDepth); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, nCurrDepth/4); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, nCurrDepth/4); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, nCurrDepth/4); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, (3*nCurrDepth)/4); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, nAlphaChannel ? nCurrDepth/4 : 0); + + // Anti-aliasing : detect the max supported number of samples + // (assumed to be <= 32). + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); + int nMaxMultiSamples = 32; // Hard coded max value for the moment. + while (!pWinSurface && nMaxMultiSamples > 1) + { + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, nMaxMultiSamples); + pWinSurface = SDL_SetVideoMode(nWidth, nHeight, nCurrDepth, bfVideoMode); + if (!pWinSurface) + { + GfLogTrace("%d+%d bit %dx anti-aliased double-buffer not supported\n", + 3*nCurrDepth/4, nCurrDepth/4, nMaxMultiSamples); + nMaxMultiSamples /= 2; + } + } + + // Failed : try without anti-aliasing. + if (!pWinSurface) + { + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0); + pWinSurface = SDL_SetVideoMode(nWidth, nHeight, nCurrDepth, bfVideoMode); + if (!pWinSurface) + GfLogTrace("%d+%d bit double-buffer not supported\n", + 3*nCurrDepth/4, nCurrDepth/4); + } + + // Failed : try with lower color depth. + if (!pWinSurface) + nCurrDepth -= 8; + } + + // Failed : try without alpha channel if not already done + // (Note: it this really relevant ?). + if (!pWinSurface) + nAlphaChannel--; + } + + // Failed : try a windowed mode if not already done. + if (!pWinSurface) + nFullScreen--; + } + + // Failed : no more idea :-( + if (!pWinSurface) + { + // Reset support data (will result in emptying the section when storing, + // thus forcing new detection when checkSupport will be called again). + _mapSupportedBool.clear(); + _mapSupportedInt.clear(); + + GfLogError("No supported 'best' video mode found for a %dx%dx%d%s frame buffer.\n", + nWidth, nHeight, nDepth, bFullScreen ? " full-screen" : ""); + + return false; + } - // Force selection. - _mapSelectedBool[TextureNonPowerOf2] = bValue; + // II) Read-out what we have from the up-and-running frame buffer + // and set "supported" values accordingly. + + // 1) Standard features. + detectStandardSupport(); + + // 2) Multi-sampling = anti-aliasing + int nValue; + SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &nValue); + _mapSupportedBool[MultiSampling] = nValue != 0; + if (nValue) + { + SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &nValue); + if (nValue > 1) + _mapSupportedInt[MultiSamplingSamples] = nValue; + else + _mapSupportedBool[MultiSampling] = false; + } - // 9) Multi-sampling = anti-aliasing - // Warning: Detection not done here (too late) : - // should already have been stored through setSupported calls. - // bValue = gfglIsOpenGLExtensionSupported("GL_ARB_multisample"); - // if (bValue) - // { - // // Check if it is enabled. - // glGetIntegerv(GL_SAMPLE_BUFFERS, &nValue); - // bValue = nValue == 1; - // bool bTryForced = false; - // if (!bValue) - // { - // // Not enabled : try to enable to see if possible. - // bTryForced = true; - // bValue = SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1) != -1; - // } - // if (bValue) - // { - // // After forcing MULTISAMPLEBUFFERS, can't get the real SAMPLES ... - // if (bTryForced) - // nValue = 2; // ... so can't do better than minimum. - // else - // glGetIntegerv(GL_SAMPLES, &nValue); - // if (nValue < 2) - // bValue = false; - // } + // III) Return the updated frame buffer specs. + //nWidth = nWidth; // Unchanged. + //nHeight = nHeight; // Unchanged. + nDepth = nCurrDepth; + bFullScreen = nFullScreen ? true : false; + bAlpha = nAlphaChannel ? true : false; + + return true; +} - // // Disable it if was not selected and we had to try it. - // if (bTryForced && !isSelected(MultiSampling)) - // SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); - // } - // _mapSupportedBool[MultiSampling] = bValue; - // _mapSupportedInt[MultiSamplingSamples] = nValue; - bValue = _mapSupportedBool[MultiSampling]; - nValue = _mapSupportedInt[MultiSamplingSamples]; - GfLogInfo(" Multi-sampling : %s", bValue ? "Yes" : "No"); - if (bValue && nValue > 1) - GfLogInfo(" (%d samples)", nValue); +bool GfglFeatures::loadSupport(int &nWidth, int &nHeight, int &nDepth, + bool &bAlpha, bool &bFullScreen, void* hparmConfig) +{ + // Clear support data. + _mapSupportedBool.clear(); + _mapSupportedInt.clear(); + + // Open the config file if not already done. + void* hparm = hparmConfig ? hparmConfig : openConfigFile(); + + // Load the frame buffer specs for the stored supported features. + nWidth = + (int)GfParmGetNum(hparm, GFSCR_SECT_GLDETSPECS, GFSCR_ATT_WIN_X, pszNoUnit, 0); + nHeight = + (int)GfParmGetNum(hparm, GFSCR_SECT_GLDETSPECS, GFSCR_ATT_WIN_Y, pszNoUnit, 0); + nDepth = + (int)GfParmGetNum(hparm, GFSCR_SECT_GLDETSPECS, GFSCR_ATT_BPP, pszNoUnit, 0); + bAlpha = + std::string(GfParmGetStr(hparm, GFSCR_SECT_GLDETSPECS, GFSCR_ATT_ALPHACHANNEL, GFSCR_VAL_NO)) + == GFSCR_VAL_YES; + bFullScreen = + std::string(GfParmGetStr(hparm, GFSCR_SECT_GLDETSPECS, GFSCR_ATT_FSCR, GFSCR_VAL_NO)) + == GFSCR_VAL_YES; + + // Check that we have something supported, and return if not. + if (nWidth == 0 || nHeight == 0 || nDepth == 0) + { + GfLogTrace("No info found about best supported features for these specs ; " + "will need a detection pass.\n"); + + // Close config file if we open it. + if (!hparmConfig) + closeConfigFile(hparm); + + return false; + } + + + // Here, we only update _mapSupportedXXX only if something relevant in the config file + // If there's nothing or something not expected, it means no support. + + // 1) Double-buffer. + const std::string strDoubleBuffer = + GfParmGetStr(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_DOUBLEBUFFER, ""); + if (strDoubleBuffer == GFSCR_VAL_YES) + _mapSupportedBool[DoubleBuffer] = true; + else if (strDoubleBuffer == GFSCR_VAL_NO) + _mapSupportedBool[DoubleBuffer] = false; + + // 2) Color buffer depth. + const int nColorDepth = + (int)GfParmGetNum(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_COLORDEPTH, + pszNoUnit, (tdble)0); + if (nColorDepth > 0) + _mapSupportedInt[ColorDepth] = nColorDepth; + + // 3) Alpha-channel depth. + const int nAlphaDepth = + (int)GfParmGetNum(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_ALPHADEPTH, + pszNoUnit, (tdble)-1); + if (nAlphaDepth >= 0) + _mapSupportedInt[AlphaDepth] = nAlphaDepth; + + // 4) Max texture size. + const int nMaxTexSize = + (int)GfParmGetNum(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_MAXTEXTURESIZE, + pszNoUnit, (tdble)0); + if (nMaxTexSize > 0) + _mapSupportedInt[TextureMaxSize] = nMaxTexSize; + + // 5) Texture compression. + const std::string strTexComp = + GfParmGetStr(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_TEXTURECOMPRESSION, ""); + if (strTexComp == GFSCR_VAL_YES) + _mapSupportedBool[TextureCompression] = true; + else if (strTexComp == GFSCR_VAL_NO) + _mapSupportedBool[TextureCompression] = false; + + // 6) Multi-texturing. + const std::string strMultiTex = + GfParmGetStr(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_MULTITEXTURING, ""); + if (strMultiTex == GFSCR_VAL_YES) + _mapSupportedBool[MultiTexturing] = true; + else if (strMultiTex == GFSCR_VAL_NO) + _mapSupportedBool[MultiTexturing] = false; + + const int nMultiTexUnits = + (int)GfParmGetNum(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_MULTITEXTURINGUNITS, + pszNoUnit, (tdble)0); + if (nMultiTexUnits > 0) + _mapSupportedInt[MultiTexturingUnits] = nMultiTexUnits; + + // 7) Rectangle textures). + const std::string strRectTex = + GfParmGetStr(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_RECTANGLETEXTURES, ""); + if (strRectTex == GFSCR_VAL_YES) + _mapSupportedBool[TextureRectangle] = true; + else if (strRectTex == GFSCR_VAL_NO) + _mapSupportedBool[TextureRectangle] = false; + + // 8) Non-power-of-2 textures. + const std::string strNonPoTTex = + GfParmGetStr(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_NONPOTTEXTURES, ""); + if (strNonPoTTex == GFSCR_VAL_YES) + _mapSupportedBool[TextureNonPowerOf2] = true; + else if (strNonPoTTex == GFSCR_VAL_NO) + _mapSupportedBool[TextureNonPowerOf2] = false; + + // 9) Multi-sampling. + const std::string strMultiSamp = + GfParmGetStr(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_MULTISAMPLING, ""); + if (strMultiSamp == GFSCR_VAL_YES) + _mapSupportedBool[MultiSampling] = true; + else if (strMultiSamp == GFSCR_VAL_NO) + _mapSupportedBool[MultiSampling] = false; + + const int nMultiSampSamples = + (int)GfParmGetNum(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_MULTISAMPLINGSAMPLES, + pszNoUnit, (tdble)0); + if (nMultiSampSamples > 0) + _mapSupportedInt[MultiSamplingSamples] = nMultiSampSamples; + + // Close config file if we open it. + if (!hparmConfig) + closeConfigFile(hparm); + + // Trace best supported features. + dumpSupport(); + + return true; +} + +void GfglFeatures::storeSupport(int nWidth, int nHeight, int nDepth, + bool bAlpha, bool bFullScreen, void* hparmConfig) +{ + // Open the config file if not already done. + void* hparm = hparmConfig ? hparmConfig : openConfigFile(); + + // If there's support for nothing, remove all. + if (_mapSupportedBool.empty() && _mapSupportedInt.empty()) + { + // Frame buffer specs. + GfParmRemove(hparm, GFSCR_SECT_GLDETSPECS, GFSCR_ATT_WIN_X); + GfParmRemove(hparm, GFSCR_SECT_GLDETSPECS, GFSCR_ATT_WIN_Y); + GfParmRemove(hparm, GFSCR_SECT_GLDETSPECS, GFSCR_ATT_BPP); + GfParmRemove(hparm, GFSCR_SECT_GLDETSPECS, GFSCR_ATT_ALPHACHANNEL); + GfParmRemove(hparm, GFSCR_SECT_GLDETSPECS, GFSCR_ATT_FSCR); + + // Supported values. + // 1) Double-buffer. + GfParmRemove(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_DOUBLEBUFFER); + + // 2) Color buffer depth. + GfParmRemove(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_COLORDEPTH); + + // 3) Alpha-channel depth. + GfParmRemove(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_ALPHADEPTH); + + // 4) Max texture size. + GfParmRemove(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_MAXTEXTURESIZE); + + // 5) Texture compression. + GfParmRemove(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_TEXTURECOMPRESSION); + + // 6) Multi-texturing. + GfParmRemove(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_MULTITEXTURING); + GfParmRemove(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_MULTITEXTURINGUNITS); + + // 7) Rectangle textures). + GfParmRemove(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_RECTANGLETEXTURES); + + // 8) Non-power-of-2 textures. + GfParmRemove(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_NONPOTTEXTURES); + + // 9) Multi-sampling. + GfParmRemove(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_MULTISAMPLING); + GfParmRemove(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_MULTISAMPLINGSAMPLES); + } + + // If there's support for anything, store it. + else + { + // Write new frame buffer specs for the stored supported features. + GfParmSetNum(hparm, GFSCR_SECT_GLDETSPECS, GFSCR_ATT_WIN_X, pszNoUnit, + (tdble)nWidth); + GfParmSetNum(hparm, GFSCR_SECT_GLDETSPECS, GFSCR_ATT_WIN_Y, pszNoUnit, + (tdble)nHeight); + GfParmSetNum(hparm, GFSCR_SECT_GLDETSPECS, GFSCR_ATT_BPP, pszNoUnit, + (tdble)nDepth); + GfParmSetStr(hparm, GFSCR_SECT_GLDETSPECS, GFSCR_ATT_ALPHACHANNEL, + bAlpha ? GFSCR_VAL_YES : GFSCR_VAL_NO); + GfParmSetStr(hparm, GFSCR_SECT_GLDETSPECS, GFSCR_ATT_FSCR, + bFullScreen ? GFSCR_VAL_YES : GFSCR_VAL_NO); + + // Write new values (remove the ones with no value supported). + // 1) Double-buffer. + GfParmSetStr(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_DOUBLEBUFFER, + isSupported(DoubleBuffer) ? GFSCR_VAL_YES : GFSCR_VAL_NO); + + // 2) Color buffer depth. + if (getSupported(ColorDepth) != InvalidInt) + GfParmSetNum(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_COLORDEPTH, pszNoUnit, + (tdble)getSupported(ColorDepth)); + else + GfParmRemove(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_COLORDEPTH); + + // 3) Alpha-channel depth. + if (getSupported(AlphaDepth) != InvalidInt) + GfParmSetNum(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_ALPHADEPTH, pszNoUnit, + (tdble)getSupported(AlphaDepth)); + else + GfParmRemove(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_ALPHADEPTH); + + // 4) Max texture size. + if (getSupported(TextureMaxSize) != InvalidInt) + GfParmSetNum(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_MAXTEXTURESIZE, pszNoUnit, + (tdble)getSupported(TextureMaxSize)); + else + GfParmRemove(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_MAXTEXTURESIZE); + + // 5) Texture compression. + GfParmSetStr(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_TEXTURECOMPRESSION, + isSupported(TextureCompression) ? GFSCR_VAL_YES : GFSCR_VAL_NO); + + // 6) Multi-texturing. + GfParmSetStr(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_MULTITEXTURING, + isSupported(MultiTexturing) ? GFSCR_VAL_YES : GFSCR_VAL_NO); + if (getSupported(MultiTexturingUnits) != InvalidInt) + GfParmSetNum(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_MULTITEXTURINGUNITS, pszNoUnit, + (tdble)getSupported(MultiTexturingUnits)); + else + GfParmRemove(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_MULTITEXTURINGUNITS); + + // 7) Rectangle textures). + GfParmSetStr(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_RECTANGLETEXTURES, + isSupported(TextureRectangle) ? GFSCR_VAL_YES : GFSCR_VAL_NO); + + // 8) Non-power-of-2 textures. + GfParmSetStr(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_NONPOTTEXTURES, + isSupported(TextureNonPowerOf2) ? GFSCR_VAL_YES : GFSCR_VAL_NO); + + // 9) Multi-sampling. + GfParmSetStr(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_MULTISAMPLING, + isSupported(MultiSampling) ? GFSCR_VAL_YES : GFSCR_VAL_NO); + + if (getSupported(MultiSamplingSamples) != InvalidInt) + GfParmSetNum(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_MULTISAMPLINGSAMPLES, pszNoUnit, + (tdble)getSupported(MultiSamplingSamples)); + else + GfParmRemove(hparm, GFSCR_SECT_GLDETFEATURES, GFSCR_ATT_MULTISAMPLINGSAMPLES); + } + + // Write new params to config file. + GfParmWriteFile(NULL, hparm, "Screen"); + + // Close config file if we open it. + if (!hparmConfig) + closeConfigFile(hparm); + + // Trace resulting best supported features. + dumpSupport(); +} + +bool GfglFeatures::checkBestSupport(int nWidth, int nHeight, int nDepth, + bool bAlpha, bool bFullScreen, void* hparmConfig) +{ + // Open the config file if not already done. + void* hparm = hparmConfig ? hparmConfig : openConfigFile(); + + // Get the frame buffer specs that are associated with the detected + // Open GL features in the config file, if any. + int nDetWidth, nDetHeight, nDetDepth; + bool bDetFullScreen, bDetAlpha; + bool bPrevSupportFound = + loadSupport(nDetWidth, nDetHeight, nDetDepth, bDetAlpha, bDetFullScreen, hparm); + + // Compare with the requested frame buffer specs + // and run a new supported feature detection if any diffference. + bool bSupportFound = true; + if (!bPrevSupportFound || nWidth != nDetWidth || nHeight != nDetHeight || nDepth != nDetDepth + || bAlpha != bDetAlpha || bFullScreen != bDetFullScreen) + { + nDetWidth = nWidth; + nDetHeight = nHeight; + nDetDepth = nDepth; + bDetFullScreen = bFullScreen; + bDetAlpha = bAlpha; + bSupportFound = + detectBestSupport(nDetWidth, nDetHeight, nDetDepth, bDetAlpha, bDetFullScreen); + + // Store support data in any case. + storeSupport(nDetWidth, nDetHeight, nDetDepth, bDetAlpha, bDetFullScreen, hparm); + + // If frame buffer specs supported, update relevant user settings and restart. + if (bSupportFound) + { + // Write new user settings about the frame buffer specs + // (the detection process might have down-casted them ...). + GfParmSetNum(hparm, GFSCR_SECT_PROP, GFSCR_ATT_WIN_X, pszNoUnit, + (tdble)nDetWidth); + GfParmSetNum(hparm, GFSCR_SECT_PROP, GFSCR_ATT_WIN_Y, pszNoUnit, + (tdble)nDetHeight); + GfParmSetNum(hparm, GFSCR_SECT_PROP, GFSCR_ATT_BPP, pszNoUnit, + (tdble)nDetDepth); + GfParmSetStr(hparm, GFSCR_SECT_PROP, GFSCR_ATT_ALPHACHANNEL, + bDetAlpha ? GFSCR_VAL_YES : GFSCR_VAL_NO); + GfParmSetStr(hparm, GFSCR_SECT_PROP, GFSCR_ATT_FSCR, + bDetFullScreen ? GFSCR_VAL_YES : GFSCR_VAL_NO); + + // Write new params to config file. + GfParmWriteFile(NULL, hparm, "Screen"); + + // Close the config file ... + closeConfigFile(hparm); + + // ... as we are restarting ... + GfuiApp().restart(); + + // Next time we pass in this function, loadSupport() will give + // the right values for all features ... + } + } + + if (!hparmConfig) + closeConfigFile(hparm); + + return bSupportFound; +} + +void GfglFeatures::dumpHardwareInfo() const +{ + GfLogInfo("Video hardware info :\n"); + GfLogInfo(" Vendor : %s\n", glGetString(GL_VENDOR)); + GfLogInfo(" Renderer : %s\n", glGetString(GL_RENDERER)); + GfLogInfo(" Version : %s\n", glGetString(GL_VERSION)); +} + +void GfglFeatures::dumpSupport() const +{ + GfLogInfo("Supported OpenGL features :\n"); + + if (_mapSupportedBool.empty() && _mapSupportedInt.empty()) + { + GfLogInfo(" Unknown (detection failed).\n"); + return; + } + + GfLogInfo(" Double buffer : %s\n", + isSupported(DoubleBuffer) ? "Yes" : "No"); + GfLogInfo(" Color depth : %d bits\n", + getSupported(ColorDepth)); + GfLogInfo(" Alpha channel : %s", + getSupported(AlphaDepth) > 0 ? "Yes" : "No"); + if (getSupported(AlphaDepth) > 0) + GfLogInfo(" (%d bits)", getSupported(AlphaDepth)); + GfLogInfo("\n"); + GfLogInfo(" Max texture size : %d\n", + getSupported(TextureMaxSize)); + GfLogInfo(" Texture compression : %s\n", + isSupported(TextureCompression) ? "Yes" : "No"); + GfLogInfo(" Multi-texturing : %s", + isSupported(MultiTexturing) ? "Yes" : "No"); + if (isSupported(MultiTexturing)) + GfLogInfo(" (%d units)", getSupported(MultiTexturingUnits)); + GfLogInfo("\n"); + GfLogInfo(" Rectangle textures : %s\n", + isSupported(TextureRectangle) ? "Yes" : "No"); + GfLogInfo(" Non power-of-2 textures : %s\n", + isSupported(TextureNonPowerOf2) ? "Yes" : "No"); + GfLogInfo(" Multi-sampling : %s", + isSupported(MultiSampling) ? "Yes" : "No"); + if (isSupported(MultiSampling) && getSupported(MultiSamplingSamples) > 1) + GfLogInfo(" (%d samples)", getSupported(MultiSamplingSamples)); GfLogInfo("\n"); - - // Update selection if needed. - if (!bValue) - _mapSelectedBool[MultiSampling] = false; } // Load the selected OpenGL features from the config file. void GfglFeatures::loadSelection(void* hparmConfig) { // Open the config file if not already done. - void* hparm; - if (!hparmConfig) - { - std::ostringstream ossParm; - ossParm << GfLocalDir() << GFSCR_CONF_FILE; - hparm = GfParmReadFile(ossParm.str().c_str(), GFPARM_RMODE_STD | GFPARM_RMODE_CREAT); - } - else - { - hparm = hparmConfig; - } + void* hparm = hparmConfig ? hparmConfig : openConfigFile(); - // Read the OpenGL configuration from screen.xml (or hard coded values). - // and select the OpenGL features accordingly - // (by default, select the max possible values ; we'll see later through checkSupport - // if we really can). + // Select the OpenGL features according to the user settings (when relevant) + // or/and to the supported values (by default, select the max supported values). - // 1) Double-buffer : no choice, hard-coded. - _mapSelectedBool[DoubleBuffer] = true; + // 1) Double-buffer : not user-customizable. + _mapSelectedBool[DoubleBuffer] = isSupported(DoubleBuffer); - // 2) Color buffer depth : no choice, hard-coded. - _mapSelectedInt[ColorDepth] = 24; + // 2) Color buffer depth : not user-customizable. + _mapSelectedInt[ColorDepth] = getSupported(ColorDepth); - // 3) Alpha-channel depth : no choice, hard-coded. - _mapSelectedInt[AlphaDepth] = 8; + // 3) Alpha-channel depth : not user-customizable. + _mapSelectedInt[AlphaDepth] = getSupported(AlphaDepth); // 4) Max texture size : load from config file. - const int nTSize = - (int)GfParmGetNum(hparm, GfSCR_SECT_GLFEATURES, GfSCR_ATT_MAXTEXTURESIZE, - (char*)NULL, (tdble)1024); - _mapSelectedInt[TextureMaxSize] = nTSize; + _mapSelectedInt[TextureMaxSize] = + (int)GfParmGetNum(hparm, GFSCR_SECT_GLSELFEATURES, GFSCR_ATT_MAXTEXTURESIZE, + pszNoUnit, (tdble)getSupported(TextureMaxSize)); + if (_mapSelectedInt[TextureMaxSize] > getSupported(TextureMaxSize)) + _mapSelectedInt[TextureMaxSize] = getSupported(TextureMaxSize); // 5) Texture compression : load from config file. - const std::string strTexComp = - GfParmGetStr(hparm, GfSCR_SECT_GLFEATURES, GfSCR_ATT_TEXTURECOMPRESSION, - GfSCR_ATT_TEXTURECOMPRESSION_ENABLED); - _mapSelectedBool[TextureCompression] = strTexComp == GfSCR_ATT_TEXTURECOMPRESSION_ENABLED; + _mapSelectedBool[TextureCompression] = + isSupported(TextureCompression) + && std::string(GfParmGetStr(hparm, GFSCR_SECT_GLSELFEATURES, GFSCR_ATT_TEXTURECOMPRESSION, + GFSCR_ATT_TEXTURECOMPRESSION_ENABLED)) + == GFSCR_ATT_TEXTURECOMPRESSION_ENABLED; // 6) Multi-texturing : load from config file. - const std::string strMultiTex = - GfParmGetStr(hparm, GfSCR_SECT_GLFEATURES, GfSCR_ATT_MULTITEXTURING, - GfSCR_ATT_MULTITEXTURING_ENABLED); - _mapSelectedBool[MultiTexturing] = strMultiTex == GfSCR_ATT_MULTITEXTURING_ENABLED; + _mapSelectedBool[MultiTexturing] = + isSupported(MultiTexturing) + && std::string(GfParmGetStr(hparm, GFSCR_SECT_GLSELFEATURES, GFSCR_ATT_MULTITEXTURING, + GFSCR_ATT_MULTITEXTURING_ENABLED)) + == GFSCR_ATT_MULTITEXTURING_ENABLED; + _mapSelectedInt[MultiTexturingUnits] = + (int)GfParmGetNum(hparm, GFSCR_SECT_GLSELFEATURES, GFSCR_ATT_MULTITEXTURINGUNITS, + pszNoUnit, (tdble)getSupported(TextureMaxSize)); + if (_mapSelectedInt[MultiTexturingUnits] > getSupported(MultiTexturingUnits)) + _mapSelectedInt[MultiTexturingUnits] = getSupported(MultiTexturingUnits); - // 7) Rectangle textures : no choice, selected = supported (see checkSupport). + // 7) Rectangle textures : not user-customizable. + _mapSelectedBool[TextureRectangle] = isSupported(TextureRectangle); - // 8) Non-power-of-2 textures : no choice, selected = supported (see checkSupport). + // 8) Non-power-of-2 textures : not user-customizable. + _mapSelectedBool[TextureNonPowerOf2] = isSupported(TextureNonPowerOf2); - // 9) Multi-sampling : load from config file (but Buffers from actually supported value). + // 9) Multi-sampling : load from config file. const std::string strMultiSamp = - GfParmGetStr(hparm, GfSCR_SECT_GLFEATURES, GfSCR_ATT_MULTISAMPLING, - GfSCR_ATT_MULTISAMPLING_ENABLED); - _mapSelectedBool[MultiSampling] = strMultiSamp == GfSCR_ATT_MULTISAMPLING_ENABLED; - const int nSamples = - (int)GfParmGetNum(hparm, GfSCR_SECT_GLFEATURES, GfSCR_ATT_MULTISAMPLING_SAMPLES, - (char*)NULL, (tdble)8); // Good but reasonable value. - _mapSelectedInt[MultiSamplingSamples] = nSamples; + GfParmGetStr(hparm, GFSCR_SECT_GLSELFEATURES, GFSCR_ATT_MULTISAMPLING, + GFSCR_ATT_MULTISAMPLING_ENABLED); + _mapSelectedBool[MultiSampling] = + isSupported(MultiSampling) + && std::string(GfParmGetStr(hparm, GFSCR_SECT_GLSELFEATURES, GFSCR_ATT_MULTISAMPLING, + GFSCR_ATT_MULTISAMPLING_ENABLED)) + == GFSCR_ATT_MULTISAMPLING_ENABLED; + + _mapSelectedInt[MultiSamplingSamples] = + (int)GfParmGetNum(hparm, GFSCR_SECT_GLSELFEATURES, GFSCR_ATT_MULTISAMPLINGSAMPLES, + pszNoUnit, (tdble)8); // Good but reasonable value. + if (_mapSelectedInt[MultiSamplingSamples] > getSupported(MultiSamplingSamples)) + _mapSelectedInt[MultiSamplingSamples] = getSupported(MultiSamplingSamples); - // Close params. + // Close config file if we open it. if (!hparmConfig) - GfParmReleaseHandle(hparm); + closeConfigFile(hparm); + + // Display what we have selected. + dumpSelection(); } @@ -306,57 +744,59 @@ void GfglFeatures::storeSelection(void* hparmConfig) const dumpSelection(); // Open the config file if not already done. - void* hparm; - if (!hparmConfig) - { - std::ostringstream ossParm; - ossParm << GfLocalDir() << GFSCR_CONF_FILE; - hparm = GfParmReadFile(ossParm.str().c_str(), GFPARM_RMODE_STD | GFPARM_RMODE_CREAT); - } - else - { - hparm = hparmConfig; - } + void* hparm = hparmConfig ? hparmConfig : openConfigFile(); // Write new values. - GfParmSetStr(hparm, GfSCR_SECT_GLFEATURES, GfSCR_ATT_TEXTURECOMPRESSION, + GfParmSetStr(hparm, GFSCR_SECT_GLSELFEATURES, GFSCR_ATT_TEXTURECOMPRESSION, isSelected(TextureCompression) - ? GfSCR_ATT_TEXTURECOMPRESSION_ENABLED : GfSCR_ATT_TEXTURECOMPRESSION_DISABLED); - GfParmSetNum(hparm, GfSCR_SECT_GLFEATURES, GfSCR_ATT_MAXTEXTURESIZE, (char*)NULL, - (tdble)getSelected(TextureMaxSize)); - GfParmSetStr(hparm, GfSCR_SECT_GLFEATURES, GfSCR_ATT_MULTITEXTURING, + ? GFSCR_ATT_TEXTURECOMPRESSION_ENABLED : GFSCR_ATT_TEXTURECOMPRESSION_DISABLED); + if (getSupported(TextureMaxSize) != InvalidInt) + GfParmSetNum(hparm, GFSCR_SECT_GLSELFEATURES, GFSCR_ATT_MAXTEXTURESIZE, pszNoUnit, + (tdble)getSelected(TextureMaxSize)); + else + GfParmRemove(hparm, GFSCR_SECT_GLSELFEATURES, GFSCR_ATT_MAXTEXTURESIZE); + + GfParmSetStr(hparm, GFSCR_SECT_GLSELFEATURES, GFSCR_ATT_MULTITEXTURING, isSelected(MultiTexturing) - ? GfSCR_ATT_MULTITEXTURING_ENABLED : GfSCR_ATT_MULTITEXTURING_DISABLED); - GfParmSetStr(hparm, GfSCR_SECT_GLFEATURES, GfSCR_ATT_MULTISAMPLING, + ? GFSCR_ATT_MULTITEXTURING_ENABLED : GFSCR_ATT_MULTITEXTURING_DISABLED); + GfParmSetStr(hparm, GFSCR_SECT_GLSELFEATURES, GFSCR_ATT_MULTISAMPLING, isSelected(MultiSampling) - ? GfSCR_ATT_MULTISAMPLING_ENABLED : GfSCR_ATT_MULTISAMPLING_DISABLED); - GfParmSetNum(hparm, GfSCR_SECT_GLFEATURES, GfSCR_ATT_MULTISAMPLING_SAMPLES, (char*)NULL, - (tdble)getSelected(MultiSamplingSamples)); + ? GFSCR_ATT_MULTISAMPLING_ENABLED : GFSCR_ATT_MULTISAMPLING_DISABLED); + if (getSupported(MultiSamplingSamples) != InvalidInt) + GfParmSetNum(hparm, GFSCR_SECT_GLSELFEATURES, GFSCR_ATT_MULTISAMPLINGSAMPLES, pszNoUnit, + (tdble)getSelected(MultiSamplingSamples)); + else + GfParmRemove(hparm, GFSCR_SECT_GLSELFEATURES, GFSCR_ATT_MULTISAMPLINGSAMPLES); // Force 'best possible' mode for video initialization when anti-aliasing selected - // (we can only activate this at GfScrInit time, and only this mode try and activates it). if (isSelected(MultiSampling)) - GfParmSetStr(hparm, GFSCR_SECT_PROP, GFSCR_ATT_VINIT, GFSCR_VAL_VINIT_BEST); + GfParmSetStr(hparm, GFSCR_SECT_PROP, GFSCR_ATT_VINIT, GFSCR_VAL_VINIT_BEST); - // Write new params to disk. + // Write new params to config file. GfParmWriteFile(NULL, hparm, "Screen"); - // Close params. + // Close config file if we open it. if (!hparmConfig) - GfParmReleaseHandle(hparm); + closeConfigFile(hparm); } void GfglFeatures::dumpSelection() const { GfLogInfo("Selected OpenGL features :\n"); GfLogInfo(" Double buffer : %s\n", isSelected(DoubleBuffer) ? "On" : "Off"); - GfLogInfo(" Color depth : %d bits\n", getSelected(ColorDepth)); + if (getSelected(ColorDepth) != InvalidInt) + GfLogInfo(" Color depth : %d bits\n", getSelected(ColorDepth)); + else + GfLogInfo(" Color depth : no selection\n"); GfLogInfo(" Alpha channel : %s", getSelected(AlphaDepth) > 0 ? "On" : "Off"); if (getSelected(AlphaDepth) > 0) GfLogInfo(" (%d bits)", getSelected(AlphaDepth)); GfLogInfo("\n"); - GfLogInfo(" Max texture size : %d\n", getSelected(TextureMaxSize)); + if (getSelected(TextureMaxSize) != InvalidInt) + GfLogInfo(" Max texture size : %d\n", getSelected(TextureMaxSize)); + else + GfLogInfo(" Max texture size : no selection\n"); GfLogInfo(" Texture compression : %s\n", isSelected(TextureCompression) ? "On" : "Off"); GfLogInfo(" Multi-texturing : %s", isSelected(MultiTexturing) ? "On" : "Off"); if (isSelected(MultiTexturing)) @@ -370,6 +810,7 @@ void GfglFeatures::dumpSelection() const GfLogInfo("\n"); } +// Bool features management. bool GfglFeatures::isSelected(EFeatureBool eFeature) const { const std::map::const_iterator itFeature = @@ -377,12 +818,12 @@ bool GfglFeatures::isSelected(EFeatureBool eFeature) const return itFeature == _mapSelectedBool.end() ? false : itFeature->second; } -void GfglFeatures::setSupported(EFeatureBool eFeature, bool bSupported) -{ - _mapSupportedBool[eFeature] = bSupported; - if (!bSupported && isSelected(eFeature)) - _mapSelectedBool[eFeature] = bSupported; -} +// void GfglFeatures::setSupported(EFeatureBool eFeature, bool bSupported) +// { +// _mapSupportedBool[eFeature] = bSupported; +// if (!bSupported && isSelected(eFeature)) +// _mapSelectedBool[eFeature] = false; // Deselect if selected and not supported. +// } bool GfglFeatures::isSupported(EFeatureBool eFeature) const { @@ -401,25 +842,26 @@ void GfglFeatures::select(EFeatureBool eFeature, bool bSelected) // _mapSelectedBool[eFeature] ? "true" : "false"); } +// Int features management. int GfglFeatures::getSelected(EFeatureInt eFeature) const { const std::map::const_iterator itFeature = _mapSelectedInt.find(eFeature); - return itFeature == _mapSelectedInt.end() ? -1 : itFeature->second; + return itFeature == _mapSelectedInt.end() ? InvalidInt : itFeature->second; } -void GfglFeatures::setSupported(EFeatureInt eFeature, int nSupportedValue) -{ - _mapSupportedInt[eFeature] = nSupportedValue; - if (nSupportedValue < getSelected(eFeature)) - _mapSelectedInt[eFeature] = nSupportedValue; -} +// void GfglFeatures::setSupported(EFeatureInt eFeature, int nSupportedValue) +// { +// _mapSupportedInt[eFeature] = nSupportedValue; +// if (getSelected(eFeature) > nSupportedValue) // Selected can't be greater than supported. +// _mapSelectedInt[eFeature] = nSupportedValue; +// } int GfglFeatures::getSupported(EFeatureInt eFeature) const { const std::map::const_iterator itFeature = _mapSupportedInt.find(eFeature); - return itFeature == _mapSupportedInt.end() ? -1 : itFeature->second; + return itFeature == _mapSupportedInt.end() ? InvalidInt : itFeature->second; } void GfglFeatures::select(EFeatureInt eFeature, int nSelectedValue) @@ -432,6 +874,7 @@ void GfglFeatures::select(EFeatureInt eFeature, int nSelectedValue) // _mapSelectedInt[eFeature]); } +// Other services. void* GfglFeatures::getProcAddress(const char* pszName) { return SDL_GL_GetProcAddress(pszName); diff --git a/src/libs/tgfclient/glfeatures.h b/src/libs/tgfclient/glfeatures.h index d9e65c422..08a81b298 100644 --- a/src/libs/tgfclient/glfeatures.h +++ b/src/libs/tgfclient/glfeatures.h @@ -52,9 +52,8 @@ A feature that is not supported can not be selected (or enabled). A feature that is selected is not necessarily enabled (not done here). - - Warning: GfglFeatures::checkSupport() mustn't be used before the 1st successfull call - to SDL_SetVideoMode() (needs an up-and-running frame buffer). + Integer features must follow an "increasing order" : a value better value is greater, + and thus a selected value can't be greater than a supported one. */ class TGFCLIENT_API GfglFeatures @@ -64,19 +63,33 @@ class TGFCLIENT_API GfglFeatures // Access to the unique instance. static GfglFeatures& self(); - // Load selected features from the config file (default = GFSCR_CONF_FILE). + // Check best supported OpenGL features, and store report to the config file + // (default = GFSCR_CONF_FILE). May restart the game. + bool checkBestSupport(int nWidth, int nHeight, int nDepth, + bool bAlpha, bool bFullScreen, void* hparmConfig = 0); + + // Detect standard supported features. Don't restart the game. + // Precondiftion: SDL_setVideoMode(...) + void detectStandardSupport(); + + // Dump detected supported features (in the current trace stream). + void dumpSupport() const; + + // Load user-selected features from the config file (default = GFSCR_CONF_FILE). + // Precondiftion: checkBestSupport() or checkStandardSupport(). void loadSelection(void* hparmConfig = 0); - // Check supported features (ask OpenGL), and update selection as needed. - // Warning: Must not be called before any successfull call to SDL_SetVideoMode() - void checkSupport(); - - // Store selected features to the config file (default = GFSCR_CONF_FILE). + // Store user-selected features to the config file (default = GFSCR_CONF_FILE). + // Precondiftion: loadSelection() void storeSelection(void* hparmConfig = 0) const; - // Dump selected features (in the current trace stream). + // Dump user-selected features (in the current trace stream). void dumpSelection() const; - + + // Dump info about the underlying hardware + // Precondiftion: SDL_setVideoMode(...) + void dumpHardwareInfo() const; + // Bool-valued features. enum EFeatureBool { @@ -90,9 +103,10 @@ class TGFCLIENT_API GfglFeatures void select(EFeatureBool eFeature, bool bSelected); bool isSelected(EFeatureBool eFeature) const; bool isSupported(EFeatureBool eFeature) const; - void setSupported(EFeatureBool eFeature, bool bSupported); + //void setSupported(EFeatureBool eFeature, bool bSupported); - // Integer-valued features (WARNING: For the moment, -1 means "not supported"). + // Integer-valued features (use InvalidInt for the "not supported" / "not selected" cases). + static int InvalidInt; enum EFeatureInt { ColorDepth, AlphaDepth, @@ -103,25 +117,42 @@ class TGFCLIENT_API GfglFeatures void select(EFeatureInt eFeature, int nSelectedValue); int getSelected(EFeatureInt eFeature) const; int getSupported(EFeatureInt eFeature) const; - void setSupported(EFeatureInt eFeature, int nSupportedValue); + //void setSupported(EFeatureInt eFeature, int nSupportedValue); // Get the pointer to the named OpenGL extension function. static void* getProcAddress(const char* pszName); private: - GfglFeatures(); // Singleton pattern => private constructor. + //! Singleton pattern => private constructor. + GfglFeatures(); + // Update supported OpenGL features according to the given frame buffer specs. + bool detectBestSupport(int& nWidth, int& nHeight, int& nDepth, + bool& bAlpha, bool& bFullScreen); + + bool loadSupport(int &nWidth, int &nHeight, int &nDepth, + bool &bAlpha, bool &bFullScreen, void* hparmConfig = 0); + + void storeSupport(int nWidth, int nHeight, int nDepth, + bool bAlpha, bool bFullScreen, void* hparmConfig = 0); + + static void* openConfigFile(); + static void closeConfigFile(void* hparmConfig, bool bWrite = false); + private: - // The unique instance. + //! The unique instance (singleton pattern). static GfglFeatures* _pSelf; - // Maps of supported features (bool and int-valued). + //! The config files params pointer. + //void* hparmConfig; + + //! Maps of supported features (bool and int-valued). std::map _mapSupportedBool; std::map _mapSupportedInt; - // Maps of selected features (bool and int-valued). + //! Maps of selected features (bool and int-valued). std::map _mapSelectedBool; std::map _mapSelectedInt; }; diff --git a/src/libs/tgfclient/guieventloop.cpp b/src/libs/tgfclient/guieventloop.cpp index 1bd8bbc00..80acdda5e 100644 --- a/src/libs/tgfclient/guieventloop.cpp +++ b/src/libs/tgfclient/guieventloop.cpp @@ -72,8 +72,8 @@ void GfuiEventLoop::injectKeyboardEvent(int code, int modifier, int state, // its WM keyboard shortcuts (didn't find any other way yet). if (code == SDLK_RETURN && (modifier & KMOD_ALT) && state == 0) { - if (!SDL_WM_ToggleFullScreen(gfScrGetScreenSurface())) - GfLogError("SDL_WM_ToggleFullScreen failed\n"); + if (!GfScrToggleFullScreen()) + GfLogError("Failed to toggle on/off the full-screen mode\n"); } else #endif diff --git a/src/libs/tgfclient/guiscreen.cpp b/src/libs/tgfclient/guiscreen.cpp index f38859a86..2e230175a 100644 --- a/src/libs/tgfclient/guiscreen.cpp +++ b/src/libs/tgfclient/guiscreen.cpp @@ -40,6 +40,7 @@ #endif #include +#include #ifdef HAVE_CONFIG_H #include "config.h" @@ -62,7 +63,7 @@ static int GfScrCenX; static int GfScrCenY; // The screen surface. -SDL_Surface *ScreenSurface = NULL; +static SDL_Surface *PScreenSurface = NULL; /* Default list of screen color depths (bits per pixel, alpha included) in case something went wrong during hardware / driver capabilities detection */ @@ -311,11 +312,11 @@ int* GfScrGetSupportedColorDepths(int* pnDepths) static void gfScrReshapeViewport(int width, int height) { - glViewport( (width-GfViewWidth)/2, (height-GfViewHeight)/2, GfViewWidth, GfViewHeight); - glMatrixMode( GL_PROJECTION ); + glViewport((width-GfViewWidth)/2, (height-GfViewHeight)/2, GfViewWidth, GfViewHeight); + glMatrixMode(GL_PROJECTION ); glLoadIdentity(); - glOrtho( 0.0, 640.0, 0.0, 480.0, -1.0, 1.0 ); - glMatrixMode( GL_MODELVIEW ); + glOrtho(0.0, 640.0, 0.0, 480.0, -1.0, 1.0); + glMatrixMode(GL_MODELVIEW); glLoadIdentity(); GfScrWidth = width; @@ -337,6 +338,23 @@ bool GfScrInit(void) // (SDL_InitSubSystem(SDL_INIT_VIDEO) seems to break it). SDL_EnableUNICODE(/*enable=*/1); + // Set window/icon captions + char pszCaption[64]; + sprintf(pszCaption, "Speed Dreams %s", VERSION_LONG); + SDL_WM_SetCaption(pszCaption, pszCaption); + + // Set window icon (MUST be a 32x32 icon for Windows, and with black pixels as alpha ones, + // as BMP doesn't support transparency). + char pszIconFilename[256]; + sprintf(pszIconFilename, "%sdata/icons/icon.bmp", GfDataDir()); + SDL_Surface* surfIcon = SDL_LoadBMP(pszIconFilename); + if (surfIcon) + { + SDL_SetColorKey(surfIcon, SDL_SRCCOLORKEY, SDL_MapRGB(surfIcon->format, 0, 0, 0)); + SDL_WM_SetIcon(surfIcon, 0); + SDL_FreeSurface(surfIcon); + } + // Query system video capabilities. // Note: Does not work very well as long as you don't force SDL to use // a special hardware driver ... which we don't want at all (the default is the one). @@ -369,253 +387,151 @@ bool GfScrInit(void) // GfLogInfo(" Hardware acceleration : %s\n", sdlVideoInfo->hw_available ? "Yes" : "No"); // GfLogInfo(" Total video memory : %u Kb\n", sdlVideoInfo->video_mem); - // Get graphical settings from config file. - char buf[512]; - sprintf(buf, "%s%s", GfLocalDir(), GFSCR_CONF_FILE); - void* hparmScreen = GfParmReadFile(buf, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT); + // Get selected frame buffer specs from config file. + char pszConfigFilename[256]; + sprintf(pszConfigFilename, "%s%s", GfLocalDir(), GFSCR_CONF_FILE); + void* hparmScreen = GfParmReadFile(pszConfigFilename, GFPARM_RMODE_STD | GFPARM_RMODE_CREAT); - int winX = (int)GfParmGetNum(hparmScreen, GFSCR_SECT_PROP, GFSCR_ATT_WIN_X, (char*)NULL, 800); - int winY = (int)GfParmGetNum(hparmScreen, GFSCR_SECT_PROP, GFSCR_ATT_WIN_Y, (char*)NULL, 600); - int depth = (int)GfParmGetNum(hparmScreen, GFSCR_SECT_PROP, GFSCR_ATT_BPP, (char*)NULL, 32); - //int maxfreq = (int)GfParmGetNum(hparmScreen, GFSCR_SECT_PROP, GFSCR_ATT_MAXREFRESH, (char*)NULL, 160); - const std::string strFullScreen = - GfParmGetStr(hparmScreen, GFSCR_SECT_PROP, GFSCR_ATT_FSCR, GFSCR_VAL_NO); - const std::string strVideoInit = - GfParmGetStr(hparmScreen, GFSCR_SECT_PROP, GFSCR_ATT_VINIT, GFSCR_VAL_VINIT_COMPATIBLE); + int nWinWidth = + (int)GfParmGetNum(hparmScreen, GFSCR_SECT_PROP, GFSCR_ATT_WIN_X, (char*)NULL, 800); + int nWinHeight = + (int)GfParmGetNum(hparmScreen, GFSCR_SECT_PROP, GFSCR_ATT_WIN_Y, (char*)NULL, 600); + int nTotalDepth = + (int)GfParmGetNum(hparmScreen, GFSCR_SECT_PROP, GFSCR_ATT_BPP, (char*)NULL, 32); + bool bAlphaChannel = + std::string(GfParmGetStr(hparmScreen, GFSCR_SECT_PROP, GFSCR_ATT_ALPHACHANNEL, + GFSCR_VAL_YES)) + == GFSCR_VAL_YES; + bool bFullScreen = + std::string(GfParmGetStr(hparmScreen, GFSCR_SECT_PROP, GFSCR_ATT_FSCR, GFSCR_VAL_NO)) + == GFSCR_VAL_YES; + bool bBestVideoInitMode = + std::string(GfParmGetStr(hparmScreen, GFSCR_SECT_PROP, GFSCR_ATT_VINIT, + GFSCR_VAL_VINIT_BEST)) + == GFSCR_VAL_VINIT_BEST; - // Load Open GL settings from config file. - GfglFeatures::self().loadSelection(); + // Prepare video mode. + int bfVideoMode = SDL_OPENGL; + if (bFullScreen) + bfVideoMode |= SDL_FULLSCREEN; + + // If specified, try best possible settings. + PScreenSurface = 0; + if (bBestVideoInitMode) + { + GfLogInfo("Trying 'best possible mode' for video initialization.\n"); + + // Detect best supported features for the specified frame buffer specs. + // Warning: Restarts the game if the frame buffer specs changed since last call. + bBestVideoInitMode = + GfglFeatures::self().checkBestSupport(nWinWidth, nWinHeight, nTotalDepth, + bAlphaChannel, bFullScreen, hparmScreen); + + // If successfull detection, setup the user-selected mode. + if (bBestVideoInitMode) + { + // Load Open GL user settings from the config file. + GfglFeatures::self().loadSelection(); - // Set window/icon captions - sprintf(buf, "Speed Dreams %s", VERSION_LONG); - SDL_WM_SetCaption(buf, buf); - - // Set window icon (MUST be a 32x32 icon for Windows, and with black pixels as alpha ones, - // as BMP doesn't support transparency). - sprintf(buf, "%sdata/icons/icon.bmp", GfDataDir()); - SDL_Surface* surfIcon = SDL_LoadBMP(buf); - if (surfIcon) - { - SDL_SetColorKey(surfIcon, SDL_SRCCOLORKEY, SDL_MapRGB(surfIcon->format, 0, 0, 0)); - SDL_WM_SetIcon(surfIcon, 0); - SDL_FreeSurface(surfIcon); - } - - // Set full screen mode if selected. - int videomode = SDL_OPENGL; // What about SDL_DOUBLEBUFFER ? - if (strFullScreen == "yes") - videomode |= SDL_FULLSCREEN; - - // Video initialization with best possible settings. - ScreenSurface = 0; - if (strVideoInit == GFSCR_VAL_VINIT_BEST) - { - GfLogInfo("Detecting 'best possible mode' for video initialization.\n"); - - // Set the minimum requirements for the OpenGL window - SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - - // Try to get "best" videomode with maximum anti-aliasing support : - // 24 bit z-buffer with alpha channel - // (even if not selected : we 1st detect what we can do at most). - SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); - - // Detect the max supported number of samples. - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); - int nSamples = 32; // Hard coded max value for the moment. - while (!ScreenSurface && nSamples > 1) - { - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, nSamples); - ScreenSurface = SDL_SetVideoMode(winX, winY, depth, videomode); - if (!ScreenSurface) - { - GfLogTrace("Can't get a video mode for a 24+8 bit " - "%dx anti-aliased double-buffer\n", nSamples); - nSamples /= 2; - } - } - - // Store the detected anti-aliasing supported features. - GfglFeatures::self().setSupported(GfglFeatures::MultiSampling, ScreenSurface != 0); - if (ScreenSurface) - GfglFeatures::self().setSupported(GfglFeatures::MultiSamplingSamples, nSamples); - - if (ScreenSurface) - SDL_FreeSurface(ScreenSurface); - - // Then, back to the user selection (may have been updated by the detection above). - GfLogInfo("Trying user selected 'best possible mode' for video initialization.\n"); - - if (GfglFeatures::self().isSelected(GfglFeatures::MultiSampling)) - { - nSamples = GfglFeatures::self().getSelected(GfglFeatures::MultiSamplingSamples); - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, nSamples); - ScreenSurface = SDL_SetVideoMode(winX, winY, depth, videomode); - if (!ScreenSurface) - GfLogTrace("Can't get a video mode for a 24+8 bit " - "%dx anti-aliased double-buffer\n", nSamples); - } - else - { - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 1); - ScreenSurface = SDL_SetVideoMode(winX, winY, depth, videomode); - if (!ScreenSurface) - GfLogTrace("Can't get a video mode for a 24+8 bit double-buffer\n"); - } - - // Failed : try with anti-aliasing if selected, but without alpha channel. - if (!ScreenSurface) - { - SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0); - if (GfglFeatures::self().isSelected(GfglFeatures::MultiSampling)) - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); - ScreenSurface = SDL_SetVideoMode(winX, winY, depth, videomode); - if (!ScreenSurface) - GfLogTrace("Can't get a video mode for a 24 bit anti-aliased double-buffer\n"); - } - - // Failed : try without anti-aliasing if selected, and without alpha channel. - if (!ScreenSurface && GfglFeatures::self().isSelected(GfglFeatures::MultiSampling)) - { - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); - ScreenSurface = SDL_SetVideoMode(winX, winY, depth, videomode); - if (!ScreenSurface) - GfLogTrace("Can't get a video mode for a 24 bit double-buffer\n"); - } - - // Failed : try 16 bit z-buffer and back with alpha channel and anti-aliasing if selected. - if (!ScreenSurface) - { - SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); - if (GfglFeatures::self().isSelected(GfglFeatures::MultiSampling)) - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); - ScreenSurface = SDL_SetVideoMode(winX, winY, depth, videomode); - if (!ScreenSurface) - GfLogTrace("Can't get a video mode for a 16+8 bit anti-aliased double-buffer\n"); - } - - // Failed : try without anti-aliasing if selected. - if (!ScreenSurface && GfglFeatures::self().isSelected(GfglFeatures::MultiSampling)) - { - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); - ScreenSurface = SDL_SetVideoMode(winX, winY, depth, videomode); - if (!ScreenSurface) - GfLogTrace("Can't get a video mode for a 16+8 bit double-buffer\n"); - } - - // Failed : try with anti-aliasing if selected, but without alpha channel. - if (!ScreenSurface) - { - SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 0); - if (GfglFeatures::self().isSelected(GfglFeatures::MultiSampling)) - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); - ScreenSurface = SDL_SetVideoMode(winX, winY, depth, videomode); - if (!ScreenSurface) - GfLogTrace("Can't get a video mode for a 16 bit anti-aliased double-buffer\n"); - } - - // Failed : try without anti-aliasing if selected, and without alpha channel. - if (!ScreenSurface && GfglFeatures::self().isSelected(GfglFeatures::MultiSampling)) - { - SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0); - ScreenSurface = SDL_SetVideoMode(winX, winY, depth, videomode); - if (!ScreenSurface) - GfLogTrace("Can't get a video mode for a 16 bit double-buffer\n"); - } - - // Failed : Change display / Open GL settings and restart. - if (!ScreenSurface) - { - // Retry without anti-aliasing if selected if it was requested. - if (GfglFeatures::self().isSelected(GfglFeatures::MultiSampling)) - { - GfLogWarning("Failed to setup best supported video mode : " - "retrying without anti-aliasing at all ...\n"); - GfglFeatures::self().select(GfglFeatures::MultiSampling, false); - GfglFeatures::self().storeSelection(hparmScreen); - } + // Setup the video mode parameters. + const int nColorDepth = + GfglFeatures::self().getSelected(GfglFeatures::ColorDepth); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, nColorDepth/3); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, nColorDepth/3); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, nColorDepth/3); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, nColorDepth); - // Otherwise, retry a "compatible" = "all defaults" initialization mode. - else if (strFullScreen == "yes") - { - - GfLogWarning("Failed to setup full-screen best supported video mode : " - "retrying in windowed mode ...\n"); - GfParmSetStr(hparmScreen, GFSCR_SECT_PROP, GFSCR_ATT_FSCR, GFSCR_VAL_NO); - GfParmWriteFile(NULL, hparmScreen, "Screen"); - } + const int nAlphaDepth = + GfglFeatures::self().getSelected(GfglFeatures::AlphaDepth); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, nAlphaDepth); - // Otherwise, retry a "compatible" = "all defaults" initialization mode. - else + const int nDoubleBuffer = + GfglFeatures::self().isSelected(GfglFeatures::DoubleBuffer) ? 1 : 0; + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, nDoubleBuffer); + + const int nMultiSampling = + GfglFeatures::self().isSelected(GfglFeatures::MultiSampling) ? 1 : 0; + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, nMultiSampling); + if (nMultiSampling) { - - GfLogWarning("Failed to setup best supported video mode : " - "falling back to a more compatible default mode ...\n"); + const int nMaxMultiSamples = + GfglFeatures::self().getSelected(GfglFeatures::MultiSamplingSamples); + SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, nMaxMultiSamples); + } + + // Try the video mode with these parameters : should always work + // (unless you upgraded you hardware / OS and didn't clear your config file). + PScreenSurface = SDL_SetVideoMode(nWinWidth, nWinHeight, nTotalDepth, bfVideoMode); + + if (!PScreenSurface) + { + // Should not happen, as we tested it in checkBestSupport ... + GfLogWarning("Failed to setup best supported video mode " + "whereas previously detected !\n"); + GfLogWarning("Falling back to a more compatible default mode ...\n"); + GfLogInfo("Tip: You should remove your %s%s file and restart,\n", + GfLocalDir(), GFSCR_CONF_FILE); + GfLogInfo(" if something changed in your OS" + " or video hardware/driver configuration.\n"); + + // Forcing compatible video init. mode. GfParmSetStr(hparmScreen, GFSCR_SECT_PROP, GFSCR_ATT_VINIT, GFSCR_VAL_VINIT_COMPATIBLE); GfParmWriteFile(NULL, hparmScreen, "Screen"); + GfParmReleaseHandle(hparmScreen); + + // And restart the game. + GfuiApp().restart(); // Never returns. } - - GfParmReleaseHandle(hparmScreen); - GfRestart(); // Never returns. } } - else - { - // Store the detected anti-aliasing supported features. - GfglFeatures::self().setSupported(GfglFeatures::MultiSampling, false); - GfglFeatures::self().setSupported(GfglFeatures::MultiSamplingSamples, -1); - } - + + // No more need for the config file. GfParmReleaseHandle(hparmScreen); // Video initialization with generic compatible settings. - if (!ScreenSurface) + if (!PScreenSurface) { GfLogInfo("Trying 'default compatible' mode for video initialization.\n"); - ScreenSurface = SDL_SetVideoMode(winX, winY, depth, videomode); - if (!ScreenSurface) + PScreenSurface = SDL_SetVideoMode(nWinWidth, nWinHeight, nTotalDepth, bfVideoMode); + if (!PScreenSurface) GfLogTrace("Can't get a %s%dx%dx%d compatible video mode\n", - strFullScreen == "yes" ? "full-screen " : "", winX, winY, depth); + bFullScreen ? "full-screen " : "", nWinWidth, nWinHeight, nTotalDepth); } // Failed : Try and remove the full-screen requirement if present ... - if (!ScreenSurface && strFullScreen == "yes") + if (!PScreenSurface && bFullScreen) { - videomode &= ~SDL_FULLSCREEN; - ScreenSurface = SDL_SetVideoMode(winX, winY, depth, videomode); - if (!ScreenSurface) + bfVideoMode &= ~SDL_FULLSCREEN; + PScreenSurface = SDL_SetVideoMode(nWinWidth, nWinHeight, nTotalDepth, bfVideoMode); + if (!PScreenSurface) GfLogTrace("Can't get a non-full-screen %dx%dx%d compatible video mode\n", - winX, winY, depth); + nWinWidth, nWinHeight, nTotalDepth); } // Failed : Try with a lower fallback size : should be supported everywhere ... - if (!ScreenSurface) + if (!PScreenSurface) { - winX = ADefScreenSizes[0].width; - winY = ADefScreenSizes[0].height; - ScreenSurface = SDL_SetVideoMode(winX, winY, depth, videomode); - if (!ScreenSurface) - GfLogTrace("Can't get a %dx%dx%d compatible video mode\n", winX, winY, depth); + nWinWidth = ADefScreenSizes[0].width; + nWinHeight = ADefScreenSizes[0].height; + PScreenSurface = SDL_SetVideoMode(nWinWidth, nWinHeight, nTotalDepth, bfVideoMode); + if (!PScreenSurface) + GfLogTrace("Can't get a %dx%dx%d compatible video mode\n", + nWinWidth, nWinHeight, nTotalDepth); } // Failed : Try with a lower fallback color depth : should be supported everywhere ... - if (!ScreenSurface) + if (!PScreenSurface) { - depth = ADefScreenColorDepths[0]; - ScreenSurface = SDL_SetVideoMode(winX, winY, depth, videomode); - if (!ScreenSurface) - GfLogTrace("Can't get a %dx%dx%d compatible video mode\n", winX, winY, depth); + nTotalDepth = ADefScreenColorDepths[0]; + PScreenSurface = SDL_SetVideoMode(nWinWidth, nWinHeight, nTotalDepth, bfVideoMode); + if (!PScreenSurface) + GfLogTrace("Can't get a %dx%dx%d compatible video mode\n", + nWinWidth, nWinHeight, nTotalDepth); } // Failed : No way ... no more ideas ! - if (!ScreenSurface) + if (!PScreenSurface) { GfLogError("Unable to get any compatible video mode" " (fallback resolution / color depth not supported) : giving up !\n\n"); @@ -624,43 +540,51 @@ bool GfScrInit(void) // If we get here, that's because we succeeded in getting a valid video mode :-) + // If 'compatible mode' selected, detect only standard Open GL features + // and load settings from the config file. + if (!bBestVideoInitMode) + { + GfglFeatures::self().detectStandardSupport(); + + GfglFeatures::self().dumpSupport(); + + GfglFeatures::self().loadSelection(); + } + // Save view geometry and screen center. - GfViewWidth = winX; - GfViewHeight = winY; - GfScrCenX = winX / 2; - GfScrCenY = winY / 2; + GfViewWidth = nWinWidth; + GfViewHeight = nWinHeight; + GfScrCenX = nWinWidth / 2; + GfScrCenY = nWinHeight / 2; // Report about selected SDL video mode. GfLogInfo("Selected SDL video mode :\n"); - GfLogInfo(" Full screen : %s\n", (videomode & SDL_FULLSCREEN) ? "Yes" : "No"); - GfLogInfo(" Size : %dx%d\n", winX, winY); - GfLogInfo(" Color depth : %d bits\n", depth); + GfLogInfo(" Full screen : %s\n", (bfVideoMode & SDL_FULLSCREEN) ? "Yes" : "No"); + GfLogInfo(" Size : %dx%d\n", nWinWidth, nWinHeight); + GfLogInfo(" Color depth : %d bits\n", nTotalDepth); + + // Report about underlying hardware (needs a running frame buffer). + GfglFeatures::self().dumpHardwareInfo(); - // Initialize the Open GL feature management layer and report about the supported features - // (may appear double work for anti-aliasing support - see above - - // but we can't check such support before a successfull call to SDL_SetVideoMode()). - GfglFeatures::self().checkSupport(); - - // Report about the actually selected support, after checking support. - GfglFeatures::self().dumpSelection(); - #ifdef WIN32 // Under Windows, give an initial position to the window if not full-screen mode // (under Linux/Mac OS X, no need, the window manager smartly takes care of this). - if (!(videomode & SDL_FULLSCREEN)) + if (!(bfVideoMode & SDL_FULLSCREEN)) { // Try to center the game Window on the desktop, but keep the title bar visible if any. const HWND hDesktop = GetDesktopWindow(); RECT rectDesktop; GetWindowRect(hDesktop, &rectDesktop); - const int nWMWinXPos = winX >= rectDesktop.right ? 0 : (rectDesktop.right - winX) / 2; - const int nWMWinYPos = winY >= rectDesktop.bottom ? 0 : (rectDesktop.bottom - winY) / 2; - GfuiInitWindowPositionAndSize(nWMWinXPos, nWMWinYPos, winX, winY); + const int nWMWinXPos = + nWinWidth >= rectDesktop.right ? 0 : (rectDesktop.right - nWinWidth) / 2; + const int nWMWinYPos = + nWinHeight >= rectDesktop.bottom ? 0 : (rectDesktop.bottom - nWinHeight) / 2; + GfuiInitWindowPositionAndSize(nWMWinXPos, nWMWinYPos, nWinWidth, nWinHeight); } #endif // Initialize the Open GL viewport. - gfScrReshapeViewport(winX, winY); + gfScrReshapeViewport(nWinWidth, nWinHeight); // Setup the event loop about the new display. GfuiApp().eventLoop().setReshapeCB(gfScrReshapeViewport); @@ -675,6 +599,9 @@ bool GfScrInit(void) */ void GfScrShutdown(void) { + GfLogTrace("Shutting down screen.\n"); + + SDL_QuitSubSystem(SDL_INIT_VIDEO); } @@ -694,6 +621,11 @@ void GfScrGetSize(int *scrW, int *scrH, int *viewW, int *viewH) *viewH = GfViewHeight; } +bool GfScrToggleFullScreen() +{ + return SDL_WM_ToggleFullScreen(PScreenSurface) != 0; +} + /** Capture screen pixels into an RGB buffer (caller must free the here-allocated buffer). @ingroup screen @param scrw address of screen with @@ -755,9 +687,3 @@ int GfScrCaptureAsPNG(const char *filename) return nStatus; } - -// Accessor to the SDL screen surface. -SDL_Surface* gfScrGetScreenSurface() -{ - return ScreenSurface; -} diff --git a/src/libs/tgfclient/guiscreen.h b/src/libs/tgfclient/guiscreen.h index 0bf01d918..bd6d998f4 100644 --- a/src/libs/tgfclient/guiscreen.h +++ b/src/libs/tgfclient/guiscreen.h @@ -18,7 +18,7 @@ ***************************************************************************/ /** @file - + Constants for screen / Open GL features config file @author Eric Espie @version $Id$ */ @@ -26,9 +26,6 @@ #ifndef _GUISCREEN_H_ #define _GUISCREEN_H_ -#include - - #define GFSCR_CONF_FILE "config/screen.xml" #define GFSCR_SECT_PROP "Screen Properties" @@ -37,10 +34,11 @@ #define GFSCR_ATT_WIN_X "window width" #define GFSCR_ATT_WIN_Y "window height" #define GFSCR_ATT_MAXREFRESH "maximum refresh frequency" -#define GFSCR_ATT_FSCR "fullscreen" +#define GFSCR_ATT_FSCR "full-screen" #define GFSCR_VAL_YES "yes" #define GFSCR_VAL_NO "no" #define GFSCR_ATT_GAMMA "gamma" +#define GFSCR_ATT_ALPHACHANNEL "alpha channel" #define GFSCR_ATT_VDETECT "video mode detect" #define GFSCR_VAL_VDETECT_AUTO "auto" @@ -86,25 +84,37 @@ #define GFSCR_ATTR_BLUE "blue" #define GFSCR_ATTR_ALPHA "alpha" -#define GfSCR_SECT_GLFEATURES "OpenGL Features" +// Open GL user-selected features +#define GFSCR_SECT_GLSELFEATURES "OpenGL Selected Features" -#define GfSCR_ATT_TEXTURECOMPRESSION "texture compression" -#define GfSCR_ATT_TEXTURECOMPRESSION_ENABLED "enabled" -#define GfSCR_ATT_TEXTURECOMPRESSION_DISABLED "disabled" +#define GFSCR_ATT_TEXTURECOMPRESSION "texture compression" +#define GFSCR_ATT_TEXTURECOMPRESSION_ENABLED "enabled" +#define GFSCR_ATT_TEXTURECOMPRESSION_DISABLED "disabled" -#define GfSCR_ATT_MAXTEXTURESIZE "max texture size" +#define GFSCR_ATT_MAXTEXTURESIZE "max texture size" -#define GfSCR_ATT_MULTITEXTURING "multi-texturing" -#define GfSCR_ATT_MULTITEXTURING_ENABLED "enabled" -#define GfSCR_ATT_MULTITEXTURING_DISABLED "disabled" +#define GFSCR_ATT_MULTITEXTURING "multi-texturing" +#define GFSCR_ATT_MULTITEXTURING_ENABLED "enabled" +#define GFSCR_ATT_MULTITEXTURING_DISABLED "disabled" -#define GfSCR_ATT_MULTISAMPLING "multi-sampling" -#define GfSCR_ATT_MULTISAMPLING_ENABLED "enabled" -#define GfSCR_ATT_MULTISAMPLING_DISABLED "disabled" +#define GFSCR_ATT_MULTISAMPLING "multi-sampling" +#define GFSCR_ATT_MULTISAMPLING_ENABLED "enabled" +#define GFSCR_ATT_MULTISAMPLING_DISABLED "disabled" -#define GfSCR_ATT_MULTISAMPLING_SAMPLES "multi-sampling samples" +#define GFSCR_ATT_MULTISAMPLINGSAMPLES "multi-sampling samples" -SDL_Surface* gfScrGetScreenSurface(); +// Open GL auto-detected features +#define GFSCR_SECT_GLDETFEATURES "OpenGL Detected Features" + +#define GFSCR_ATT_DOUBLEBUFFER "double buffer" +#define GFSCR_ATT_COLORDEPTH "color depth" +#define GFSCR_ATT_ALPHADEPTH "alpha depth" +#define GFSCR_ATT_RECTANGLETEXTURES "rectangle textures" +#define GFSCR_ATT_NONPOTTEXTURES "non-pot textures" +#define GFSCR_ATT_MULTITEXTURINGUNITS "multi-texturing units" + +// Open GL detection specs +#define GFSCR_SECT_GLDETSPECS "OpenGL Detection Specs" #endif /* _GUISCREEN_H_ */ diff --git a/src/libs/tgfclient/screen.xml b/src/libs/tgfclient/screen.xml index 12f6d0552..750afb4d7 100644 --- a/src/libs/tgfclient/screen.xml +++ b/src/libs/tgfclient/screen.xml @@ -16,13 +16,14 @@ - +
- - + + + @@ -238,11 +239,12 @@
-
+
+
diff --git a/src/modules/userinterface/legacymenu/confscreens/displayconfig.cpp b/src/modules/userinterface/legacymenu/confscreens/displayconfig.cpp index a3f5bc888..1951e7ec4 100755 --- a/src/modules/userinterface/legacymenu/confscreens/displayconfig.cpp +++ b/src/modules/userinterface/legacymenu/confscreens/displayconfig.cpp @@ -115,13 +115,11 @@ void DisplayMenu::onAccept(void *pDisplayMenu) // Save display settings. pMenu->storeSettings(); - // TODO: Simply call GfuiApp().restart() (when it is implemented ;-). - // Shutdown the user interface. LegacyMenu::self().shutdown(); // Restart the game. - GfRestart(GfuiMouseIsHWPresent()); + GfuiApp().restart(); // TODO: A nice system to get back to previous display settings if the chosen ones // keep the game from really restarting (ex: unsupported full screen size) ? @@ -238,8 +236,8 @@ void DisplayMenu::storeSettings() const // Deselect anti-aliasing from the Open GL settings if 'compatible' mode // selected for the video initialization (anti-aliasing not supported in this mode). if (_eVideoInitMode == eCompatible) - GfParmSetStr(hScrConfParams, GfSCR_SECT_GLFEATURES, GfSCR_ATT_MULTISAMPLING, - GfSCR_ATT_MULTISAMPLING_DISABLED); + GfParmSetStr(hScrConfParams, GFSCR_SECT_GLSELFEATURES, GFSCR_ATT_MULTISAMPLING, + GFSCR_ATT_MULTISAMPLING_DISABLED); // Write and release screen config params file. GfParmWriteFile(NULL, hScrConfParams, "Screen"); diff --git a/src/modules/userinterface/legacymenu/confscreens/openglconfig.cpp b/src/modules/userinterface/legacymenu/confscreens/openglconfig.cpp index 4cda7614e..d65d332b4 100644 --- a/src/modules/userinterface/legacymenu/confscreens/openglconfig.cpp +++ b/src/modules/userinterface/legacymenu/confscreens/openglconfig.cpp @@ -39,7 +39,7 @@ // Texture compression. static const char *ATextureCompTexts[] = - {GfSCR_ATT_TEXTURECOMPRESSION_DISABLED, GfSCR_ATT_TEXTURECOMPRESSION_ENABLED}; + {GFSCR_ATT_TEXTURECOMPRESSION_DISABLED, GFSCR_ATT_TEXTURECOMPRESSION_ENABLED}; static const int NTextureComps = sizeof(ATextureCompTexts) / sizeof(ATextureCompTexts[0]); static int NCurTextureCompIndex = 0; @@ -57,7 +57,7 @@ static const int NDefaultTextureSize = 64; // In case everything goes wrong. // Multi-texturing. static const char *AMultiTextureTexts[] = - {GfSCR_ATT_MULTITEXTURING_DISABLED, GfSCR_ATT_MULTITEXTURING_ENABLED}; + {GFSCR_ATT_MULTITEXTURING_DISABLED, GFSCR_ATT_MULTITEXTURING_ENABLED}; static const int NMultiTextures = sizeof(AMultiTextureTexts) / sizeof(AMultiTextureTexts[0]); static int NCurMultiTextureIndex = 0; @@ -87,16 +87,16 @@ static void onAccept(void *) // Store current state of settings to the GL features layer. GfglFeatures::self().select(GfglFeatures::TextureCompression, strcmp(ATextureCompTexts[NCurTextureCompIndex], - GfSCR_ATT_TEXTURECOMPRESSION_ENABLED) ? false : true); + GFSCR_ATT_TEXTURECOMPRESSION_ENABLED) ? false : true); GfglFeatures::self().select(GfglFeatures::TextureMaxSize, AMaxTextureSizeTexts[NCurMaxTextureSizeIndex]); GfglFeatures::self().select(GfglFeatures::MultiTexturing, strcmp(AMultiTextureTexts[NCurMultiTextureIndex], - GfSCR_ATT_MULTITEXTURING_ENABLED) ? false : true); + GFSCR_ATT_MULTITEXTURING_ENABLED) ? false : true); GfglFeatures::self().select(GfglFeatures::MultiSampling, VecMultiSampleTexts[NCurMultiSampleIndex] - != GfSCR_ATT_MULTISAMPLING_DISABLED); - if (VecMultiSampleTexts[NCurMultiSampleIndex] != GfSCR_ATT_MULTISAMPLING_DISABLED) + != GFSCR_ATT_MULTISAMPLING_DISABLED); + if (VecMultiSampleTexts[NCurMultiSampleIndex] != GFSCR_ATT_MULTISAMPLING_DISABLED) GfglFeatures::self().select(GfglFeatures::MultiSamplingSamples, (int)pow(2.0, (double)NCurMultiSampleIndex)); @@ -111,14 +111,12 @@ static void onAccept(void *) if (GfglFeatures::self().isSelected(GfglFeatures::MultiSampling) != BMultiSamplingWasSelected || GfglFeatures::self().getSelected(GfglFeatures::MultiSamplingSamples) != BPrevMultiSamplingSamples) { - // TODO: Simply call GfuiApp().restart() (when it is implemented ;-). - // Shutdown the user interface. LegacyMenu::self().shutdown(); // Restart the game. - GfRestart(GfuiMouseIsHWPresent()); - + GfuiApp().restart(); + // TODO: A nice system to get back to previous display settings if the chosen ones // keep the game from really restarting (ex: unsupported full screen size) ? } @@ -178,7 +176,7 @@ static void onActivate(void * /* dummy */) { const char *pszTexComp = GfglFeatures::self().isSelected(GfglFeatures::TextureCompression) - ? GfSCR_ATT_TEXTURECOMPRESSION_ENABLED : GfSCR_ATT_TEXTURECOMPRESSION_DISABLED; + ? GFSCR_ATT_TEXTURECOMPRESSION_ENABLED : GFSCR_ATT_TEXTURECOMPRESSION_DISABLED; for (i = 0; i < NTextureComps; i++) { if (!strcmp(pszTexComp, ATextureCompTexts[i])) @@ -251,7 +249,7 @@ static void onActivate(void * /* dummy */) { const char *pszMultiTex = GfglFeatures::self().isSelected(GfglFeatures::MultiTexturing) - ? GfSCR_ATT_MULTITEXTURING_ENABLED : GfSCR_ATT_MULTITEXTURING_DISABLED; + ? GFSCR_ATT_MULTITEXTURING_ENABLED : GFSCR_ATT_MULTITEXTURING_DISABLED; for (i = 0; i < NMultiTextures; i++) { if (!strcmp(pszMultiTex, AMultiTextureTexts[i])) @@ -365,7 +363,7 @@ void* OpenGLMenuInit(void *prevMenu) // Initialize multi-sampling levels. NMultiSamples = 1; - VecMultiSampleTexts.push_back(GfSCR_ATT_MULTISAMPLING_DISABLED); + VecMultiSampleTexts.push_back(GFSCR_ATT_MULTISAMPLING_DISABLED); if (GfglFeatures::self().isSupported(GfglFeatures::MultiSampling) && GfglFeatures::self().getSupported(GfglFeatures::MultiSamplingSamples) > 1) {