diff options
author | Johannes Schickel | 2013-10-18 00:17:46 +0200 |
---|---|---|
committer | Johannes Schickel | 2013-10-19 22:18:15 +0200 |
commit | bb1d49ba9cbdb5b50cbce0c6d714d2fd2e3c6da9 (patch) | |
tree | 2b877979d9b454d450d248cb5f4d7f3387f4e193 | |
parent | 53f9c0d69b96a6394aa90caf437d3a90b0affd3e (diff) | |
download | scummvm-rg350-bb1d49ba9cbdb5b50cbce0c6d714d2fd2e3c6da9.tar.gz scummvm-rg350-bb1d49ba9cbdb5b50cbce0c6d714d2fd2e3c6da9.tar.bz2 scummvm-rg350-bb1d49ba9cbdb5b50cbce0c6d714d2fd2e3c6da9.zip |
OPENGL: Limit maximum Surface size to maximum texture size.
This is mostly aimed at old graphics chips. For example, wjp's old laptop
only supports 1024x1024 textures but has a 1280x800 screen. Switching to
fullscreen would create a bigger overlay than supported. Now it will get
limited to an smaller resolution and then scaled too.
Alternatively we could think of tiling surfaces into textures. But then
handling scaling would be more complicated since it might result in
artifacts on texture tile borders.
-rw-r--r-- | backends/graphics/opengl/opengl-graphics.cpp | 60 | ||||
-rw-r--r-- | backends/graphics/opengl/texture.cpp | 7 | ||||
-rw-r--r-- | backends/graphics/opengl/texture.h | 12 |
3 files changed, 64 insertions, 15 deletions
diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp index 3223075fbd..e3c56dccca 100644 --- a/backends/graphics/opengl/opengl-graphics.cpp +++ b/backends/graphics/opengl/opengl-graphics.cpp @@ -145,19 +145,10 @@ bool OpenGLGraphicsManager::setGraphicsMode(int mode) { _gameScreen->enableLinearFiltering(mode == GFX_LINEAR); } - if (_overlay) { - _overlay->enableLinearFiltering(mode == GFX_LINEAR); - } - if (_cursor) { _cursor->enableLinearFiltering(mode == GFX_LINEAR); } -#ifdef USE_OSD - if (_osd) { - _osd->enableLinearFiltering(mode == GFX_LINEAR); - } -#endif return true; default: @@ -221,7 +212,13 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() { #else Graphics::PixelFormat::createFormatCLUT8() #endif - )) { + ) + // HACK: This is really nasty but we don't have any guarantees of + // a context existing before, which means we don't know the maximum + // supported texture size before this. Thus, we check whether the + // requested game resolution is supported over here. + || ( _currentState.gameWidth > (uint)Texture::getMaximumTextureSize() + || _currentState.gameHeight > (uint)Texture::getMaximumTextureSize())) { if (_transactionMode == kTransactionActive) { // Try to setup the old state in case its valid and is // actually different from the new one. @@ -754,12 +751,34 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { GLCALL(glMatrixMode(GL_MODELVIEW)); GLCALL(glLoadIdentity()); + uint overlayWidth = width; + uint overlayHeight = height; + + // WORKAROUND: We can only support surfaces up to the maximum supported + // texture size. Thus, in case we encounter a physical size bigger than + // this maximum texture size we will simply use an overlay as big as + // possible and then scale it to the physical display size. This sounds + // bad but actually all recent chips should support full HD resolution + // anyway. Thus, it should not be a real issue for modern hardware. + if ( overlayWidth > (uint)Texture::getMaximumTextureSize() + || overlayHeight > (uint)Texture::getMaximumTextureSize()) { + const frac_t outputAspect = intToFrac(_outputScreenWidth) / _outputScreenHeight; + + if (outputAspect > (frac_t)FRAC_ONE) { + overlayWidth = Texture::getMaximumTextureSize(); + overlayHeight = intToFrac(overlayWidth) / outputAspect; + } else { + overlayHeight = Texture::getMaximumTextureSize(); + overlayWidth = fracToInt(overlayHeight * outputAspect); + } + } + // HACK: We limit the minimal overlay size to 256x200, which is the // minimum of the dimensions of the two resolutions 256x240 (NES) and // 320x200 (many DOS games use this). This hopefully assure that our // GUI has working layouts. - const uint overlayWidth = MAX<uint>(width, 256); - const uint overlayHeight = MAX<uint>(height, 200); + overlayWidth = MAX<uint>(overlayWidth, 256); + overlayHeight = MAX<uint>(overlayHeight, 200); if (!_overlay || _overlay->getFormat() != _defaultFormatAlpha) { delete _overlay; @@ -769,7 +788,10 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { const bool supported = getGLPixelFormat(_defaultFormatAlpha, glIntFormat, glFormat, glType); assert(supported); _overlay = new Texture(glIntFormat, glFormat, glType, _defaultFormatAlpha); - _overlay->enableLinearFiltering(_currentState.graphicsMode == GFX_LINEAR); + // We always filter the overlay with GL_LINEAR. This assures it's + // readable in case it needs to be scaled and does not affect it + // otherwise. + _overlay->enableLinearFiltering(true); } _overlay->allocate(overlayWidth, overlayHeight); _overlay->fill(0); @@ -783,9 +805,12 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) { const bool supported = getGLPixelFormat(_defaultFormatAlpha, glIntFormat, glFormat, glType); assert(supported); _osd = new Texture(glIntFormat, glFormat, glType, _defaultFormatAlpha); - _osd->enableLinearFiltering(_currentState.graphicsMode == GFX_LINEAR); + // We always filter the osd with GL_LINEAR. This assures it's + // readable in case it needs to be scaled and does not affect it + // otherwise. + _osd->enableLinearFiltering(true); } - _osd->allocate(_outputScreenWidth, _outputScreenHeight); + _osd->allocate(_overlay->getWidth(), _overlay->getHeight()); _osd->fill(0); #endif @@ -824,6 +849,9 @@ void OpenGLGraphicsManager::notifyContextChange(const Graphics::PixelFormat &def GLCALL(glEnable(GL_TEXTURE_2D)); + // Query information needed by textures. + Texture::queryTextureInformation(); + // Refresh the output screen dimensions if some are set up. if (_outputScreenWidth != 0 && _outputScreenHeight != 0) { setActualScreenSize(_outputScreenWidth, _outputScreenHeight); @@ -860,6 +888,8 @@ void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) { // here when the overlay is visible. This is because for very small // resolutions we have a minimal overlay size and have to adjust // for that. + // This can also happen when the overlay is smaller than the actual + // display size because of texture size limitations. if (_overlay) { x = (x * _overlay->getWidth()) / _outputScreenWidth; y = (y * _overlay->getHeight()) / _outputScreenHeight; diff --git a/backends/graphics/opengl/texture.cpp b/backends/graphics/opengl/texture.cpp index d89bd00ac4..917bf70534 100644 --- a/backends/graphics/opengl/texture.cpp +++ b/backends/graphics/opengl/texture.cpp @@ -41,6 +41,13 @@ static GLuint nextHigher2(GLuint v) { return ++v; } +GLint Texture::_maxTextureSize = 0; + +void Texture::queryTextureInformation() { + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &_maxTextureSize); + debug(5, "OpenGL maximum texture size: %d", _maxTextureSize); +} + Texture::Texture(GLenum glIntFormat, GLenum glFormat, GLenum glType, const Graphics::PixelFormat &format) : _glIntFormat(glIntFormat), _glFormat(glFormat), _glType(glType), _format(format), _glFilter(GL_NEAREST), _glTexture(0), _textureData(), _userPixelData(), _allDirty(false) { diff --git a/backends/graphics/opengl/texture.h b/backends/graphics/opengl/texture.h index 273e7b7319..e28d980de4 100644 --- a/backends/graphics/opengl/texture.h +++ b/backends/graphics/opengl/texture.h @@ -110,6 +110,16 @@ public: virtual void *getPalette() { return 0; } virtual const void *getPalette() const { return 0; } + /** + * Query texture related OpenGL information from the context. This only + * queries the maximum texture size for now. + */ + static void queryTextureInformation(); + + /** + * @return Return the maximum texture dimensions supported. + */ + static GLint getMaximumTextureSize() { return _maxTextureSize; } protected: virtual void updateTexture(); @@ -129,6 +139,8 @@ private: bool _allDirty; Common::Rect _dirtyArea; void clearDirty() { _allDirty = false; _dirtyArea = Common::Rect(); } + + static GLint _maxTextureSize; }; class TextureCLUT8 : public Texture { |