aboutsummaryrefslogtreecommitdiff
path: root/backends/graphics/opengl/opengl-graphics.cpp
diff options
context:
space:
mode:
authorColin Snover2017-10-15 13:26:39 -0500
committerColin Snover2017-10-15 13:26:39 -0500
commit7d8d2f80fbc9cf96b3bd03b85a9722b576d23adc (patch)
treea35cf3cd386219e8c945ba8aacc3e20c442fbf69 /backends/graphics/opengl/opengl-graphics.cpp
parent7fc86195343adf962054fd52605c3a3cc8b501e9 (diff)
parent4757c24c683c2f2b8e3b55aa8d7a767aad9e947e (diff)
downloadscummvm-rg350-7d8d2f80fbc9cf96b3bd03b85a9722b576d23adc.tar.gz
scummvm-rg350-7d8d2f80fbc9cf96b3bd03b85a9722b576d23adc.tar.bz2
scummvm-rg350-7d8d2f80fbc9cf96b3bd03b85a9722b576d23adc.zip
Merge branch 'graphics-backends-improvements'
Diffstat (limited to 'backends/graphics/opengl/opengl-graphics.cpp')
-rw-r--r--backends/graphics/opengl/opengl-graphics.cpp248
1 files changed, 64 insertions, 184 deletions
diff --git a/backends/graphics/opengl/opengl-graphics.cpp b/backends/graphics/opengl/opengl-graphics.cpp
index 28ca110d91..7bac4c85cb 100644
--- a/backends/graphics/opengl/opengl-graphics.cpp
+++ b/backends/graphics/opengl/opengl-graphics.cpp
@@ -53,14 +53,12 @@ namespace OpenGL {
OpenGLGraphicsManager::OpenGLGraphicsManager()
: _currentState(), _oldState(), _transactionMode(kTransactionNone), _screenChangeID(1 << (sizeof(int) * 8 - 2)),
_pipeline(nullptr),
- _outputScreenWidth(0), _outputScreenHeight(0), _displayX(0), _displayY(0),
- _displayWidth(0), _displayHeight(0), _defaultFormat(), _defaultFormatAlpha(),
+ _defaultFormat(), _defaultFormatAlpha(),
_gameScreen(nullptr), _gameScreenShakeOffset(0), _overlay(nullptr),
- _overlayVisible(false), _cursor(nullptr),
- _cursorX(0), _cursorY(0), _cursorDisplayX(0),_cursorDisplayY(0), _cursorHotspotX(0), _cursorHotspotY(0),
+ _cursor(nullptr),
+ _cursorHotspotX(0), _cursorHotspotY(0),
_cursorHotspotXScaled(0), _cursorHotspotYScaled(0), _cursorWidthScaled(0), _cursorHeightScaled(0),
- _cursorKeyColor(0), _cursorVisible(false), _cursorDontScale(false), _cursorPaletteEnabled(false),
- _forceRedraw(false)
+ _cursorKeyColor(0), _cursorDontScale(false), _cursorPaletteEnabled(false)
#ifdef USE_OSD
, _osdMessageChangeRequest(false), _osdMessageAlpha(0), _osdMessageFadeStartTime(0), _osdMessageSurface(nullptr),
_osdIconSurface(nullptr)
@@ -83,7 +81,7 @@ OpenGLGraphicsManager::~OpenGLGraphicsManager() {
#endif
}
-bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) {
+bool OpenGLGraphicsManager::hasFeature(OSystem::Feature f) const {
switch (f) {
case OSystem::kFeatureAspectRatioCorrection:
case OSystem::kFeatureCursorPalette:
@@ -129,7 +127,7 @@ void OpenGLGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) {
}
}
-bool OpenGLGraphicsManager::getFeatureState(OSystem::Feature f) {
+bool OpenGLGraphicsManager::getFeatureState(OSystem::Feature f) const {
switch (f) {
case OSystem::kFeatureAspectRatioCorrection:
return _currentState.aspectRatioCorrection;
@@ -220,10 +218,9 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
#endif
do {
- uint requestedWidth = _currentState.gameWidth;
- uint requestedHeight = _currentState.gameHeight;
- const uint desiredAspect = getDesiredGameScreenAspect();
- requestedHeight = intToFrac(requestedWidth) / desiredAspect;
+ const uint desiredAspect = getDesiredGameAspectRatio();
+ const uint requestedWidth = _currentState.gameWidth;
+ const uint requestedHeight = intToFrac(requestedWidth) / desiredAspect;
if (!loadVideoMode(requestedWidth, requestedHeight,
#ifdef USE_RGB_COLOR
@@ -317,7 +314,7 @@ OSystem::TransactionError OpenGLGraphicsManager::endGFXTransaction() {
// Update our display area and cursor scaling. This makes sure we pick up
// aspect ratio correction and game screen changes correctly.
- recalculateDisplayArea();
+ recalculateDisplayAreas();
recalculateCursorScaling();
// Something changed, so update the screen change ID.
@@ -347,11 +344,11 @@ void OpenGLGraphicsManager::initSize(uint width, uint height, const Graphics::Pi
_currentState.gameHeight = height;
}
-int16 OpenGLGraphicsManager::getWidth() {
+int16 OpenGLGraphicsManager::getWidth() const {
return _currentState.gameWidth;
}
-int16 OpenGLGraphicsManager::getHeight() {
+int16 OpenGLGraphicsManager::getHeight() const {
return _currentState.gameHeight;
}
@@ -392,6 +389,7 @@ void OpenGLGraphicsManager::updateScreen() {
// We only update the screen when there actually have been any changes.
if ( !_forceRedraw
+ && !_cursorNeedsRedraw
&& !_gameScreen->isDirty()
&& !(_overlayVisible && _overlay->isDirty())
&& !(_cursorVisible && _cursor && _cursor->isDirty())
@@ -401,7 +399,6 @@ void OpenGLGraphicsManager::updateScreen() {
) {
return;
}
- _forceRedraw = false;
// Update changes to textures.
_gameScreen->updateGLTexture();
@@ -420,14 +417,14 @@ void OpenGLGraphicsManager::updateScreen() {
_backBuffer.enableScissorTest(true);
}
- const GLfloat shakeOffset = _gameScreenShakeOffset * (GLfloat)_displayHeight / _gameScreen->getHeight();
+ const GLfloat shakeOffset = _gameScreenShakeOffset * (GLfloat)_gameDrawRect.height() / _gameScreen->getHeight();
// First step: Draw the (virtual) game screen.
- g_context.getActivePipeline()->drawTexture(_gameScreen->getGLTexture(), _displayX, _displayY + shakeOffset, _displayWidth, _displayHeight);
+ g_context.getActivePipeline()->drawTexture(_gameScreen->getGLTexture(), _gameDrawRect.left, _gameDrawRect.top + shakeOffset, _gameDrawRect.width(), _gameDrawRect.height());
// Second step: Draw the overlay if visible.
if (_overlayVisible) {
- g_context.getActivePipeline()->drawTexture(_overlay->getGLTexture(), 0, 0, _outputScreenWidth, _outputScreenHeight);
+ g_context.getActivePipeline()->drawTexture(_overlay->getGLTexture(), 0, 0, _overlayDrawRect.width(), _overlayDrawRect.height());
}
// Third step: Draw the cursor if visible.
@@ -437,8 +434,8 @@ void OpenGLGraphicsManager::updateScreen() {
const GLfloat cursorOffset = _overlayVisible ? 0 : shakeOffset;
g_context.getActivePipeline()->drawTexture(_cursor->getGLTexture(),
- _cursorDisplayX - _cursorHotspotXScaled,
- _cursorDisplayY - _cursorHotspotYScaled + cursorOffset,
+ _cursorX - _cursorHotspotXScaled,
+ _cursorY - _cursorHotspotYScaled + cursorOffset,
_cursorWidthScaled, _cursorHeightScaled);
}
@@ -464,8 +461,8 @@ void OpenGLGraphicsManager::updateScreen() {
// Set the OSD transparency.
g_context.getActivePipeline()->setColor(1.0f, 1.0f, 1.0f, _osdMessageAlpha / 100.0f);
- int dstX = (_outputScreenWidth - _osdMessageSurface->getWidth()) / 2;
- int dstY = (_outputScreenHeight - _osdMessageSurface->getHeight()) / 2;
+ int dstX = (_windowWidth - _osdMessageSurface->getWidth()) / 2;
+ int dstY = (_windowHeight - _osdMessageSurface->getHeight()) / 2;
// Draw the OSD texture.
g_context.getActivePipeline()->drawTexture(_osdMessageSurface->getGLTexture(),
@@ -481,7 +478,7 @@ void OpenGLGraphicsManager::updateScreen() {
}
if (_osdIconSurface) {
- int dstX = _outputScreenWidth - _osdIconSurface->getWidth() - kOSDIconRightMargin;
+ int dstX = _windowWidth - _osdIconSurface->getWidth() - kOSDIconRightMargin;
int dstY = kOSDIconTopMargin;
// Draw the OSD icon texture.
@@ -490,6 +487,8 @@ void OpenGLGraphicsManager::updateScreen() {
}
#endif
+ _cursorNeedsRedraw = false;
+ _forceRedraw = false;
refreshScreen();
}
@@ -507,7 +506,7 @@ void OpenGLGraphicsManager::setFocusRectangle(const Common::Rect& rect) {
void OpenGLGraphicsManager::clearFocusRectangle() {
}
-int16 OpenGLGraphicsManager::getOverlayWidth() {
+int16 OpenGLGraphicsManager::getOverlayWidth() const {
if (_overlay) {
return _overlay->getWidth();
} else {
@@ -515,7 +514,7 @@ int16 OpenGLGraphicsManager::getOverlayWidth() {
}
}
-int16 OpenGLGraphicsManager::getOverlayHeight() {
+int16 OpenGLGraphicsManager::getOverlayHeight() const {
if (_overlay) {
return _overlay->getHeight();
} else {
@@ -523,22 +522,6 @@ int16 OpenGLGraphicsManager::getOverlayHeight() {
}
}
-void OpenGLGraphicsManager::showOverlay() {
- _overlayVisible = true;
- _forceRedraw = true;
-
- // Update cursor position.
- setMousePosition(_cursorX, _cursorY);
-}
-
-void OpenGLGraphicsManager::hideOverlay() {
- _overlayVisible = false;
- _forceRedraw = true;
-
- // Update cursor position.
- setMousePosition(_cursorX, _cursorY);
-}
-
Graphics::PixelFormat OpenGLGraphicsManager::getOverlayFormat() const {
return _overlay->getFormat();
}
@@ -551,7 +534,7 @@ void OpenGLGraphicsManager::clearOverlay() {
_overlay->fill(0);
}
-void OpenGLGraphicsManager::grabOverlay(void *buf, int pitch) {
+void OpenGLGraphicsManager::grabOverlay(void *buf, int pitch) const {
const Graphics::Surface *overlayData = _overlay->getSurface();
const byte *src = (const byte *)overlayData->getPixels();
@@ -564,55 +547,6 @@ void OpenGLGraphicsManager::grabOverlay(void *buf, int pitch) {
}
}
-bool OpenGLGraphicsManager::showMouse(bool visible) {
- // In case the mouse cursor visibility changed we need to redraw the whole
- // screen even when nothing else changed.
- if (_cursorVisible != visible) {
- _forceRedraw = true;
- }
-
- bool last = _cursorVisible;
- _cursorVisible = visible;
- return last;
-}
-
-void OpenGLGraphicsManager::warpMouse(int x, int y) {
- int16 currentX = _cursorX;
- int16 currentY = _cursorY;
- adjustMousePosition(currentX, currentY);
-
- // Check whether the (virtual) coordinate actually changed. If not, then
- // simply do nothing. This avoids ugly "jittering" due to the actual
- // output screen having a bigger resolution than the virtual coordinates.
- if (currentX == x && currentY == y) {
- return;
- }
-
- // Scale the virtual coordinates into actual physical coordinates.
- if (_overlayVisible) {
- if (!_overlay) {
- return;
- }
-
- // It might be confusing that we actually have to handle something
- // 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.
- x = (x * _outputScreenWidth) / _overlay->getWidth();
- y = (y * _outputScreenHeight) / _overlay->getHeight();
- } else {
- if (!_gameScreen) {
- return;
- }
-
- x = (x * _outputScreenWidth) / _gameScreen->getWidth();
- y = (y * _outputScreenHeight) / _gameScreen->getHeight();
- }
-
- setMousePosition(x, y);
- setInternalMousePosition(x, y);
-}
-
namespace {
template<typename DstPixel, typename SrcPixel>
void applyColorKey(DstPixel *dst, const SrcPixel *src, uint w, uint h, uint dstPitch, uint srcPitch, SrcPixel keyColor, DstPixel alphaMask) {
@@ -633,6 +567,18 @@ void applyColorKey(DstPixel *dst, const SrcPixel *src, uint w, uint h, uint dstP
} // End of anonymous namespace
void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, bool dontScale, const Graphics::PixelFormat *format) {
+
+ _cursorKeyColor = keycolor;
+ _cursorHotspotX = hotspotX;
+ _cursorHotspotY = hotspotY;
+ _cursorDontScale = dontScale;
+
+ if (!w || !h) {
+ delete _cursor;
+ _cursor = nullptr;
+ return;
+ }
+
Graphics::PixelFormat inputFormat;
#ifdef USE_RGB_COLOR
if (format) {
@@ -668,11 +614,6 @@ void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int
_cursor->enableLinearFiltering(_currentState.filtering);
}
- _cursorKeyColor = keycolor;
- _cursorHotspotX = hotspotX;
- _cursorHotspotY = hotspotY;
- _cursorDontScale = dontScale;
-
_cursor->allocate(w, h);
if (inputFormat.bytesPerPixel == 1) {
// For CLUT8 cursors we can simply copy the input data into the
@@ -720,7 +661,6 @@ void OpenGLGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int
updateCursorPalette();
}
- // Update the scaling.
recalculateCursorScaling();
}
@@ -765,8 +705,8 @@ void OpenGLGraphicsManager::osdMessageUpdateSurface() {
}
// Clip the rect
- width = MIN<uint>(width, _displayWidth);
- height = MIN<uint>(height, _displayHeight);
+ width = MIN<uint>(width, _gameDrawRect.width());
+ height = MIN<uint>(height, _gameDrawRect.height());
delete _osdMessageSurface;
_osdMessageSurface = nullptr;
@@ -849,16 +789,13 @@ void OpenGLGraphicsManager::setPalette(const byte *colors, uint start, uint num)
updateCursorPalette();
}
-void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) {
+void OpenGLGraphicsManager::grabPalette(byte *colors, uint start, uint num) const {
assert(_gameScreen->hasPalette());
memcpy(colors, _gamePalette + start * 3, num * 3);
}
-void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) {
- _outputScreenWidth = width;
- _outputScreenHeight = height;
-
+void OpenGLGraphicsManager::handleResizeImpl(const int width, const int height) {
// Setup backbuffer size.
_backBuffer.setDimensions(width, height);
@@ -873,7 +810,7 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) {
// anyway. Thus, it should not be a real issue for modern hardware.
if ( overlayWidth > (uint)g_context.maxTextureSize
|| overlayHeight > (uint)g_context.maxTextureSize) {
- const frac_t outputAspect = intToFrac(_outputScreenWidth) / _outputScreenHeight;
+ const frac_t outputAspect = intToFrac(_windowWidth) / _windowHeight;
if (outputAspect > (frac_t)FRAC_ONE) {
overlayWidth = g_context.maxTextureSize;
@@ -906,7 +843,7 @@ void OpenGLGraphicsManager::setActualScreenSize(uint width, uint height) {
_overlay->fill(0);
// Re-setup the scaling for the screen and cursor
- recalculateDisplayArea();
+ recalculateDisplayAreas();
recalculateCursorScaling();
// Something changed, so update the screen change ID.
@@ -960,8 +897,8 @@ void OpenGLGraphicsManager::notifyContextCreate(const Graphics::PixelFormat &def
GL_CALL(glPixelStorei(GL_PACK_ALIGNMENT, 4));
// Refresh the output screen dimensions if some are set up.
- if (_outputScreenWidth != 0 && _outputScreenHeight != 0) {
- setActualScreenSize(_outputScreenWidth, _outputScreenHeight);
+ if (_windowWidth != 0 && _windowHeight != 0) {
+ handleResize(_windowWidth, _windowHeight);
}
// TODO: Should we try to convert textures into one of those formats if
@@ -1031,46 +968,6 @@ void OpenGLGraphicsManager::notifyContextDestroy() {
g_context.reset();
}
-void OpenGLGraphicsManager::adjustMousePosition(int16 &x, int16 &y) {
- if (_overlayVisible) {
- // It might be confusing that we actually have to handle something
- // 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;
- }
- } else if (_gameScreen) {
- const int16 width = _gameScreen->getWidth();
- const int16 height = _gameScreen->getHeight();
-
- x = (x * width) / (int)_outputScreenWidth;
- y = (y * height) / (int)_outputScreenHeight;
- }
-}
-
-void OpenGLGraphicsManager::setMousePosition(int x, int y) {
- // Whenever the mouse position changed we force a screen redraw to reflect
- // changes properly.
- if (_cursorX != x || _cursorY != y) {
- _forceRedraw = true;
- }
-
- _cursorX = x;
- _cursorY = y;
-
- if (_overlayVisible) {
- _cursorDisplayX = x;
- _cursorDisplayY = y;
- } else {
- _cursorDisplayX = _displayX + (x * _displayWidth) / _outputScreenWidth;
- _cursorDisplayY = _displayY + (y * _displayHeight) / _outputScreenHeight;
- }
-}
-
Surface *OpenGLGraphicsManager::createSurface(const Graphics::PixelFormat &format, bool wantAlpha) {
GLenum glIntFormat, glFormat, glType;
if (format.bytesPerPixel == 1) {
@@ -1191,51 +1088,34 @@ bool OpenGLGraphicsManager::getGLPixelFormat(const Graphics::PixelFormat &pixelF
}
}
-frac_t OpenGLGraphicsManager::getDesiredGameScreenAspect() const {
- const uint width = _currentState.gameWidth;
- const uint height = _currentState.gameHeight;
-
+bool OpenGLGraphicsManager::gameNeedsAspectRatioCorrection() const {
if (_currentState.aspectRatioCorrection) {
+ const uint width = getWidth();
+ const uint height = getHeight();
+
// In case we enable aspect ratio correction we force a 4/3 ratio.
// But just for 320x200 and 640x400 games, since other games do not need
// this.
- if ((width == 320 && height == 200) || (width == 640 && height == 400)) {
- return intToFrac(4) / 3;
- }
+ return (width == 320 && height == 200) || (width == 640 && height == 400);
}
- return intToFrac(width) / height;
+ return false;
}
-void OpenGLGraphicsManager::recalculateDisplayArea() {
- if (!_gameScreen || _outputScreenHeight == 0) {
+void OpenGLGraphicsManager::recalculateDisplayAreas() {
+ if (!_gameScreen) {
return;
}
- const frac_t outputAspect = intToFrac(_outputScreenWidth) / _outputScreenHeight;
- const frac_t desiredAspect = getDesiredGameScreenAspect();
-
- _displayWidth = _outputScreenWidth;
- _displayHeight = _outputScreenHeight;
-
- // Adjust one dimension for mantaining the aspect ratio.
- if (outputAspect < desiredAspect) {
- _displayHeight = intToFrac(_displayWidth) / desiredAspect;
- } else if (outputAspect > desiredAspect) {
- _displayWidth = fracToInt(_displayHeight * desiredAspect);
- }
-
- // We center the screen in the middle for now.
- _displayX = (_outputScreenWidth - _displayWidth ) / 2;
- _displayY = (_outputScreenHeight - _displayHeight) / 2;
+ WindowedGraphicsManager::recalculateDisplayAreas();
// Setup drawing limitation for game graphics.
// This involves some trickery because OpenGL's viewport coordinate system
// is upside down compared to ours.
- _backBuffer.setScissorBox(_displayX,
- _outputScreenHeight - _displayHeight - _displayY,
- _displayWidth,
- _displayHeight);
+ _backBuffer.setScissorBox(_gameDrawRect.left,
+ _windowHeight - _gameDrawRect.height() - _gameDrawRect.top,
+ _gameDrawRect.width(),
+ _gameDrawRect.height());
// Update the cursor position to adjust for new display area.
setMousePosition(_cursorX, _cursorY);
@@ -1272,8 +1152,8 @@ void OpenGLGraphicsManager::recalculateCursorScaling() {
// In case scaling is actually enabled we will scale the cursor according
// to the game screen.
if (!_cursorDontScale) {
- const frac_t screenScaleFactorX = intToFrac(_displayWidth) / _gameScreen->getWidth();
- const frac_t screenScaleFactorY = intToFrac(_displayHeight) / _gameScreen->getHeight();
+ const frac_t screenScaleFactorX = intToFrac(_gameDrawRect.width()) / _gameScreen->getWidth();
+ const frac_t screenScaleFactorY = intToFrac(_gameDrawRect.height()) / _gameScreen->getHeight();
_cursorHotspotXScaled = fracToInt(_cursorHotspotXScaled * screenScaleFactorX);
_cursorWidthScaled = fracToInt(_cursorWidthScaled * screenScaleFactorX);
@@ -1284,14 +1164,14 @@ void OpenGLGraphicsManager::recalculateCursorScaling() {
}
#ifdef USE_OSD
-const Graphics::Font *OpenGLGraphicsManager::getFontOSD() {
+const Graphics::Font *OpenGLGraphicsManager::getFontOSD() const {
return FontMan.getFontByUsage(Graphics::FontManager::kLocalizedFont);
}
#endif
bool OpenGLGraphicsManager::saveScreenshot(const Common::String &filename) const {
- const uint width = _outputScreenWidth;
- const uint height = _outputScreenHeight;
+ const uint width = _windowWidth;
+ const uint height = _windowHeight;
// A line of a BMP image must have a size divisible by 4.
// We calculate the padding bytes needed here.