parent
6e6fa26620
commit
ef0155a50c
8 changed files with 134 additions and 147 deletions
|
@ -151,16 +151,15 @@ void OpenGLSdlGraphicsManager::setupScreen(uint gameWidth, uint gameHeight, bool
|
||||||
void OpenGLSdlGraphicsManager::createOrUpdateScreen() {
|
void OpenGLSdlGraphicsManager::createOrUpdateScreen() {
|
||||||
closeOverlay();
|
closeOverlay();
|
||||||
|
|
||||||
bool engineSupportsArbitraryResolutions = g_engine && g_engine->hasFeature(Engine::kSupportsArbitraryResolutions);
|
// If the game can't adapt to any resolution, render it to a framebuffer
|
||||||
|
// so it can be scaled to fill the available space.
|
||||||
// Select how the game screen is going to be drawn
|
bool engineSupportsArbitraryResolutions = !g_engine || g_engine->hasFeature(Engine::kSupportsArbitraryResolutions);
|
||||||
GameRenderTarget gameRenderTarget = selectGameRenderTarget(_fullscreen, true, engineSupportsArbitraryResolutions,
|
bool renderToFrameBuffer = !engineSupportsArbitraryResolutions && _capabilities.openGLFrameBuffer;
|
||||||
_capabilities.openGLFrameBuffer, _lockAspectRatio);
|
|
||||||
|
|
||||||
// Choose the effective window size or fullscreen mode
|
// Choose the effective window size or fullscreen mode
|
||||||
uint effectiveWidth;
|
uint effectiveWidth;
|
||||||
uint effectiveHeight;
|
uint effectiveHeight;
|
||||||
if (_fullscreen && canUsePreferredResolution(gameRenderTarget, engineSupportsArbitraryResolutions)) {
|
if (_fullscreen && !renderToFrameBuffer) {
|
||||||
Common::Rect fullscreenResolution = getPreferredFullscreenResolution();
|
Common::Rect fullscreenResolution = getPreferredFullscreenResolution();
|
||||||
effectiveWidth = fullscreenResolution.width();
|
effectiveWidth = fullscreenResolution.width();
|
||||||
effectiveHeight = fullscreenResolution.height();
|
effectiveHeight = fullscreenResolution.height();
|
||||||
|
@ -169,10 +168,8 @@ void OpenGLSdlGraphicsManager::createOrUpdateScreen() {
|
||||||
effectiveHeight = _engineRequestedHeight;
|
effectiveHeight = _engineRequestedHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the rectangle where to draw the game inside the effective screen
|
if (!createOrUpdateGLContext(_engineRequestedWidth, _engineRequestedHeight,
|
||||||
_gameRect = computeGameRect(gameRenderTarget, _engineRequestedWidth, _engineRequestedHeight, effectiveWidth, effectiveHeight);
|
effectiveWidth, effectiveHeight, renderToFrameBuffer)) {
|
||||||
|
|
||||||
if (!createOrUpdateGLContext(effectiveWidth, effectiveHeight, gameRenderTarget)) {
|
|
||||||
warning("SDL Error: %s", SDL_GetError());
|
warning("SDL Error: %s", SDL_GetError());
|
||||||
g_system->quit();
|
g_system->quit();
|
||||||
}
|
}
|
||||||
|
@ -185,22 +182,32 @@ void OpenGLSdlGraphicsManager::createOrUpdateScreen() {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if SDL_VERSION_ATLEAST(2, 0, 1)
|
||||||
|
int obtainedWidth = 0, obtainedHeight = 0;
|
||||||
|
SDL_GL_GetDrawableSize(_window->getSDLWindow(), &obtainedWidth, &obtainedHeight);
|
||||||
|
#else
|
||||||
|
int obtainedWidth = effectiveWidth;
|
||||||
|
int obtainedHeight = effectiveHeight;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Compute the rectangle where to draw the game inside the effective screen
|
||||||
|
_gameRect = computeGameRect(renderToFrameBuffer, _engineRequestedWidth, _engineRequestedHeight,
|
||||||
|
obtainedWidth, obtainedHeight);
|
||||||
|
|
||||||
initializeOpenGLContext();
|
initializeOpenGLContext();
|
||||||
_surfaceRenderer = OpenGL::createBestSurfaceRenderer();
|
_surfaceRenderer = OpenGL::createBestSurfaceRenderer();
|
||||||
|
|
||||||
_overlayFormat = OpenGL::Texture::getRGBAPixelFormat();
|
_overlayFormat = OpenGL::Texture::getRGBAPixelFormat();
|
||||||
_overlayScreen = new OpenGL::TiledSurface(effectiveWidth, effectiveHeight, _overlayFormat);
|
_overlayScreen = new OpenGL::TiledSurface(obtainedWidth, obtainedHeight, _overlayFormat);
|
||||||
|
|
||||||
_overlayWidth = effectiveWidth;
|
|
||||||
_overlayHeight = effectiveHeight;
|
|
||||||
_screenFormat = _overlayFormat;
|
_screenFormat = _overlayFormat;
|
||||||
|
|
||||||
_screenChangeCount++;
|
_screenChangeCount++;
|
||||||
|
|
||||||
_eventSource->resetKeyboardEmulation(effectiveWidth - 1, effectiveHeight - 1);
|
_eventSource->resetKeyboardEmulation(obtainedWidth - 1, obtainedHeight - 1);
|
||||||
|
|
||||||
#if !defined(AMIGAOS)
|
#if !defined(AMIGAOS)
|
||||||
if (gameRenderTarget == kFramebuffer) {
|
if (renderToFrameBuffer) {
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||||
_frameBuffer = createFramebuffer(_engineRequestedWidth, _engineRequestedHeight);
|
_frameBuffer = createFramebuffer(_engineRequestedWidth, _engineRequestedHeight);
|
||||||
_frameBuffer->attach();
|
_frameBuffer->attach();
|
||||||
|
@ -208,6 +215,57 @@ void OpenGLSdlGraphicsManager::createOrUpdateScreen() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Math::Rect2d OpenGLSdlGraphicsManager::computeGameRect(bool renderToFrameBuffer, uint gameWidth, uint gameHeight,
|
||||||
|
uint screenWidth, uint screenHeight) {
|
||||||
|
if (renderToFrameBuffer) {
|
||||||
|
if (_lockAspectRatio) {
|
||||||
|
// The game is scaled to fit the screen, keeping the same aspect ratio
|
||||||
|
float scale = MIN(screenHeight / float(gameHeight), screenWidth / float(gameWidth));
|
||||||
|
float scaledW = scale * (gameWidth / float(screenWidth));
|
||||||
|
float scaledH = scale * (gameHeight / float(screenHeight));
|
||||||
|
return Math::Rect2d(
|
||||||
|
Math::Vector2d(0.5 - (0.5 * scaledW), 0.5 - (0.5 * scaledH)),
|
||||||
|
Math::Vector2d(0.5 + (0.5 * scaledW), 0.5 + (0.5 * scaledH))
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// The game occupies the whole screen
|
||||||
|
return Math::Rect2d(Math::Vector2d(0, 0), Math::Vector2d(1, 1));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Math::Rect2d(Math::Vector2d(0, 0), Math::Vector2d(1, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLSdlGraphicsManager::notifyResize(const uint width, const uint height) {
|
||||||
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
|
// Get the updated size directly from SDL, in case there are multiple
|
||||||
|
// resize events in the message queue.
|
||||||
|
int newWidth = 0, newHeight = 0;
|
||||||
|
SDL_GL_GetDrawableSize(_window->getSDLWindow(), &newWidth, &newHeight);
|
||||||
|
|
||||||
|
if (newWidth == _overlayScreen->getWidth() && newHeight == _overlayScreen->getHeight()) {
|
||||||
|
return; // nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute the rectangle where to draw the game inside the effective screen
|
||||||
|
_gameRect = computeGameRect(_frameBuffer != nullptr,
|
||||||
|
_engineRequestedWidth, _engineRequestedHeight,
|
||||||
|
newWidth, newHeight);
|
||||||
|
|
||||||
|
// Update the overlay
|
||||||
|
delete _overlayScreen;
|
||||||
|
_overlayScreen = new OpenGL::TiledSurface(newWidth, newHeight, _overlayFormat);
|
||||||
|
|
||||||
|
// Clear the overlay background so it is not displayed distorted while resizing
|
||||||
|
delete _overlayBackground;
|
||||||
|
_overlayBackground = nullptr;
|
||||||
|
|
||||||
|
_screenChangeCount++;
|
||||||
|
|
||||||
|
_eventSource->resetKeyboardEmulation(newWidth - 1, newHeight- 1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
Graphics::PixelBuffer OpenGLSdlGraphicsManager::getScreenPixelBuffer() {
|
Graphics::PixelBuffer OpenGLSdlGraphicsManager::getScreenPixelBuffer() {
|
||||||
error("Direct screen buffer access is not allowed when using OpenGL");
|
error("Direct screen buffer access is not allowed when using OpenGL");
|
||||||
}
|
}
|
||||||
|
@ -240,11 +298,12 @@ OpenGLSdlGraphicsManager::OpenGLPixelFormat::OpenGLPixelFormat(uint screenBytesP
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenGLSdlGraphicsManager::createOrUpdateGLContext(uint effectiveWidth, uint effectiveHeight,
|
bool OpenGLSdlGraphicsManager::createOrUpdateGLContext(uint gameWidth, uint gameHeight,
|
||||||
GameRenderTarget gameRenderTarget) {
|
uint effectiveWidth, uint effectiveHeight,
|
||||||
|
bool renderToFramebuffer) {
|
||||||
// Build a list of OpenGL pixel formats usable by ResidualVM
|
// Build a list of OpenGL pixel formats usable by ResidualVM
|
||||||
Common::Array<OpenGLPixelFormat> pixelFormats;
|
Common::Array<OpenGLPixelFormat> pixelFormats;
|
||||||
if (_antialiasing > 0 && gameRenderTarget == kScreen) {
|
if (_antialiasing > 0 && !renderToFramebuffer) {
|
||||||
// Don't enable screen level multisampling when rendering to a framebuffer
|
// Don't enable screen level multisampling when rendering to a framebuffer
|
||||||
pixelFormats.push_back(OpenGLPixelFormat(32, 8, 8, 8, 8, _antialiasing));
|
pixelFormats.push_back(OpenGLPixelFormat(32, 8, 8, 8, 8, _antialiasing));
|
||||||
pixelFormats.push_back(OpenGLPixelFormat(16, 5, 5, 5, 1, _antialiasing));
|
pixelFormats.push_back(OpenGLPixelFormat(16, 5, 5, 5, 1, _antialiasing));
|
||||||
|
@ -295,7 +354,7 @@ bool OpenGLSdlGraphicsManager::createOrUpdateGLContext(uint effectiveWidth, uint
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
uint32 sdlflags = SDL_WINDOW_OPENGL;
|
uint32 sdlflags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
|
||||||
if (_fullscreen) {
|
if (_fullscreen) {
|
||||||
// On Linux/X11, when toggling to fullscreen, the window manager saves
|
// On Linux/X11, when toggling to fullscreen, the window manager saves
|
||||||
// the window size to be able to restore it when going back to windowed mode.
|
// the window size to be able to restore it when going back to windowed mode.
|
||||||
|
@ -305,7 +364,7 @@ bool OpenGLSdlGraphicsManager::createOrUpdateGLContext(uint effectiveWidth, uint
|
||||||
// to windowed mode, the window manager has a window size to apply instead
|
// to windowed mode, the window manager has a window size to apply instead
|
||||||
// of leaving the window at the fullscreen resolution size.
|
// of leaving the window at the fullscreen resolution size.
|
||||||
if (!_window->getSDLWindow()) {
|
if (!_window->getSDLWindow()) {
|
||||||
_window->createOrUpdateWindow(effectiveWidth, effectiveHeight, sdlflags);
|
_window->createOrUpdateWindow(gameWidth, gameHeight, sdlflags);
|
||||||
}
|
}
|
||||||
|
|
||||||
sdlflags |= SDL_WINDOW_FULLSCREEN;
|
sdlflags |= SDL_WINDOW_FULLSCREEN;
|
||||||
|
@ -364,7 +423,7 @@ bool OpenGLSdlGraphicsManager::isVSyncEnabled() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLSdlGraphicsManager::drawOverlay() {
|
void OpenGLSdlGraphicsManager::drawOverlay() {
|
||||||
glViewport(0, 0, _overlayWidth, _overlayHeight);
|
glViewport(0, 0, _overlayScreen->getWidth(), _overlayScreen->getHeight());
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||||
|
|
||||||
_surfaceRenderer->prepareState();
|
_surfaceRenderer->prepareState();
|
||||||
|
@ -384,15 +443,15 @@ void OpenGLSdlGraphicsManager::drawSideTextures() {
|
||||||
if (_fullscreen && _lockAspectRatio) {
|
if (_fullscreen && _lockAspectRatio) {
|
||||||
_surfaceRenderer->setFlipY(true);
|
_surfaceRenderer->setFlipY(true);
|
||||||
|
|
||||||
const Math::Vector2d nudge(1.0 / float(_overlayWidth), 0);
|
const Math::Vector2d nudge(1.0 / float(_overlayScreen->getWidth()), 0);
|
||||||
if (_sideTextures[0] != nullptr) {
|
if (_sideTextures[0] != nullptr) {
|
||||||
float left = _gameRect.getBottomLeft().getX() - (float(_overlayHeight) / float(_sideTextures[0]->getHeight())) * _sideTextures[0]->getWidth() / float(_overlayWidth);
|
float left = _gameRect.getBottomLeft().getX() - (float(_overlayScreen->getHeight()) / float(_sideTextures[0]->getHeight())) * _sideTextures[0]->getWidth() / float(_overlayScreen->getWidth());
|
||||||
Math::Rect2d leftRect(Math::Vector2d(left, 0.0), _gameRect.getBottomLeft() + nudge);
|
Math::Rect2d leftRect(Math::Vector2d(left, 0.0), _gameRect.getBottomLeft() + nudge);
|
||||||
_surfaceRenderer->render(_sideTextures[0], leftRect);
|
_surfaceRenderer->render(_sideTextures[0], leftRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_sideTextures[1] != nullptr) {
|
if (_sideTextures[1] != nullptr) {
|
||||||
float right = _gameRect.getTopRight().getX() + (float(_overlayHeight) / float(_sideTextures[1]->getHeight())) * _sideTextures[1]->getWidth() / float(_overlayWidth);
|
float right = _gameRect.getTopRight().getX() + (float(_overlayScreen->getHeight()) / float(_sideTextures[1]->getHeight())) * _sideTextures[1]->getWidth() / float(_overlayScreen->getWidth());
|
||||||
Math::Rect2d rightRect(_gameRect.getTopRight() - nudge, Math::Vector2d(right, 1.0));
|
Math::Rect2d rightRect(_gameRect.getTopRight() - nudge, Math::Vector2d(right, 1.0));
|
||||||
_surfaceRenderer->render(_sideTextures[1], rightRect);
|
_surfaceRenderer->render(_sideTextures[1], rightRect);
|
||||||
}
|
}
|
||||||
|
@ -417,7 +476,7 @@ OpenGL::FrameBuffer *OpenGLSdlGraphicsManager::createFramebuffer(uint width, uin
|
||||||
void OpenGLSdlGraphicsManager::updateScreen() {
|
void OpenGLSdlGraphicsManager::updateScreen() {
|
||||||
if (_frameBuffer) {
|
if (_frameBuffer) {
|
||||||
_frameBuffer->detach();
|
_frameBuffer->detach();
|
||||||
glViewport(0, 0, _overlayWidth, _overlayHeight);
|
glViewport(0, 0, _overlayScreen->getWidth(), _overlayScreen->getHeight());
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||||
_surfaceRenderer->prepareState();
|
_surfaceRenderer->prepareState();
|
||||||
drawSideTextures();
|
drawSideTextures();
|
||||||
|
@ -451,7 +510,7 @@ int16 OpenGLSdlGraphicsManager::getHeight() const {
|
||||||
if (_frameBuffer)
|
if (_frameBuffer)
|
||||||
return _frameBuffer->getHeight();
|
return _frameBuffer->getHeight();
|
||||||
else
|
else
|
||||||
return _overlayHeight;
|
return _overlayScreen->getHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
int16 OpenGLSdlGraphicsManager::getWidth() const {
|
int16 OpenGLSdlGraphicsManager::getWidth() const {
|
||||||
|
@ -459,7 +518,7 @@ int16 OpenGLSdlGraphicsManager::getWidth() const {
|
||||||
if (_frameBuffer)
|
if (_frameBuffer)
|
||||||
return _frameBuffer->getWidth();
|
return _frameBuffer->getWidth();
|
||||||
else
|
else
|
||||||
return _overlayWidth;
|
return _overlayScreen->getWidth();
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
@ -492,7 +551,7 @@ void OpenGLSdlGraphicsManager::showOverlay() {
|
||||||
if (_frameBuffer)
|
if (_frameBuffer)
|
||||||
_frameBuffer->detach();
|
_frameBuffer->detach();
|
||||||
// If there is a game running capture the screen, so that it can be shown "below" the overlay.
|
// If there is a game running capture the screen, so that it can be shown "below" the overlay.
|
||||||
_overlayBackground = new OpenGL::TiledSurface(_overlayWidth, _overlayHeight, _overlayFormat);
|
_overlayBackground = new OpenGL::TiledSurface(_overlayScreen->getWidth(), _overlayScreen->getHeight(), _overlayFormat);
|
||||||
Graphics::Surface *background = _overlayBackground->getBackingSurface();
|
Graphics::Surface *background = _overlayBackground->getBackingSurface();
|
||||||
glReadPixels(0, 0, background->w, background->h, GL_RGBA, GL_UNSIGNED_BYTE, background->getPixels());
|
glReadPixels(0, 0, background->w, background->h, GL_RGBA, GL_UNSIGNED_BYTE, background->getPixels());
|
||||||
if (_frameBuffer)
|
if (_frameBuffer)
|
||||||
|
@ -550,15 +609,23 @@ void OpenGLSdlGraphicsManager::closeOverlay() {
|
||||||
OpenGL::Context::destroy();
|
OpenGL::Context::destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int16 OpenGLSdlGraphicsManager::getOverlayHeight() const {
|
||||||
|
return _overlayScreen->getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
int16 OpenGLSdlGraphicsManager::getOverlayWidth() const {
|
||||||
|
return _overlayScreen->getWidth();
|
||||||
|
}
|
||||||
|
|
||||||
void OpenGLSdlGraphicsManager::warpMouse(int x, int y) {
|
void OpenGLSdlGraphicsManager::warpMouse(int x, int y) {
|
||||||
//ResidualVM specific
|
//ResidualVM specific
|
||||||
if (_frameBuffer) {
|
if (_frameBuffer) {
|
||||||
// Scale from game coordinates to screen coordinates
|
// Scale from game coordinates to screen coordinates
|
||||||
x = (x * _gameRect.getWidth() * _overlayWidth) / _frameBuffer->getWidth();
|
x = (x * _gameRect.getWidth() * _overlayScreen->getWidth()) / _frameBuffer->getWidth();
|
||||||
y = (y * _gameRect.getHeight() * _overlayHeight) / _frameBuffer->getHeight();
|
y = (y * _gameRect.getHeight() * _overlayScreen->getHeight()) / _frameBuffer->getHeight();
|
||||||
|
|
||||||
x += _gameRect.getTopLeft().getX() * _overlayWidth;
|
x += _gameRect.getTopLeft().getX() * _overlayScreen->getWidth();
|
||||||
y += _gameRect.getTopLeft().getY() * _overlayHeight;
|
y += _gameRect.getTopLeft().getY() * _overlayScreen->getHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
_window->warpMouseInWindow(x, y);
|
_window->warpMouseInWindow(x, y);
|
||||||
|
@ -569,11 +636,11 @@ void OpenGLSdlGraphicsManager::transformMouseCoordinates(Common::Point &point) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Scale from screen coordinates to game coordinates
|
// Scale from screen coordinates to game coordinates
|
||||||
point.x -= _gameRect.getTopLeft().getX() * _overlayWidth;
|
point.x -= _gameRect.getTopLeft().getX() * _overlayScreen->getWidth();
|
||||||
point.y -= _gameRect.getTopLeft().getY() * _overlayHeight;
|
point.y -= _gameRect.getTopLeft().getY() * _overlayScreen->getHeight();
|
||||||
|
|
||||||
point.x = (point.x * _frameBuffer->getWidth()) / (_gameRect.getWidth() * _overlayWidth);
|
point.x = (point.x * _frameBuffer->getWidth()) / (_gameRect.getWidth() * _overlayScreen->getWidth());
|
||||||
point.y = (point.y * _frameBuffer->getHeight()) / (_gameRect.getHeight() * _overlayHeight);
|
point.y = (point.y * _frameBuffer->getHeight()) / (_gameRect.getHeight() * _overlayScreen->getHeight());
|
||||||
|
|
||||||
// Make sure we only supply valid coordinates.
|
// Make sure we only supply valid coordinates.
|
||||||
point.x = CLIP<int16>(point.x, 0, _frameBuffer->getWidth() - 1);
|
point.x = CLIP<int16>(point.x, 0, _frameBuffer->getWidth() - 1);
|
||||||
|
|
|
@ -62,6 +62,8 @@ public:
|
||||||
virtual void clearOverlay() override;
|
virtual void clearOverlay() override;
|
||||||
virtual void grabOverlay(void *buf, int pitch) const override;
|
virtual void grabOverlay(void *buf, int pitch) const override;
|
||||||
virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override;
|
virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override;
|
||||||
|
int16 getOverlayWidth() const override;
|
||||||
|
int16 getOverlayHeight() const override;
|
||||||
|
|
||||||
/* Render the passed Surfaces besides the game texture.
|
/* Render the passed Surfaces besides the game texture.
|
||||||
* This is used for widescreen support in the Grim engine.
|
* This is used for widescreen support in the Grim engine.
|
||||||
|
@ -75,6 +77,8 @@ public:
|
||||||
// SdlGraphicsManager API
|
// SdlGraphicsManager API
|
||||||
virtual void transformMouseCoordinates(Common::Point &point) override;
|
virtual void transformMouseCoordinates(Common::Point &point) override;
|
||||||
|
|
||||||
|
void notifyResize(const uint width, const uint height) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
SDL_GLContext _glContext;
|
SDL_GLContext _glContext;
|
||||||
|
@ -100,10 +104,14 @@ protected:
|
||||||
* When unable to create a context with anti-aliasing this tries without.
|
* When unable to create a context with anti-aliasing this tries without.
|
||||||
* When unable to create a context with the desired pixel depth this tries lower values.
|
* When unable to create a context with the desired pixel depth this tries lower values.
|
||||||
*/
|
*/
|
||||||
bool createOrUpdateGLContext(uint effectiveWidth, uint effectiveHeight, GameRenderTarget gameRenderTarget);
|
bool createOrUpdateGLContext(uint gameWidth, uint gameHeight, uint effectiveWidth, uint effectiveHeight, bool renderToFramebuffer);
|
||||||
|
|
||||||
void createOrUpdateScreen();
|
void createOrUpdateScreen();
|
||||||
|
|
||||||
|
/** Compute the size and position of the game rectangle in the screen */
|
||||||
|
Math::Rect2d computeGameRect(bool renderToFrameBuffer, uint gameWidth, uint gameHeight,
|
||||||
|
uint screenWidth, uint screenHeight);
|
||||||
|
|
||||||
int _antialiasing;
|
int _antialiasing;
|
||||||
bool _vsync;
|
bool _vsync;
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,6 @@ ResVmSdlGraphicsManager::ResVmSdlGraphicsManager(SdlEventSource *source, SdlWind
|
||||||
_fullscreen(false),
|
_fullscreen(false),
|
||||||
_lockAspectRatio(true),
|
_lockAspectRatio(true),
|
||||||
_overlayVisible(false),
|
_overlayVisible(false),
|
||||||
_overlayWidth(0),
|
|
||||||
_overlayHeight(0),
|
|
||||||
_screenChangeCount(0),
|
_screenChangeCount(0),
|
||||||
_capabilities(capabilities),
|
_capabilities(capabilities),
|
||||||
_engineRequestedWidth(0),
|
_engineRequestedWidth(0),
|
||||||
|
@ -67,71 +65,6 @@ void ResVmSdlGraphicsManager::deactivateManager() {
|
||||||
SdlGraphicsManager::deactivateManager();
|
SdlGraphicsManager::deactivateManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
ResVmSdlGraphicsManager::GameRenderTarget ResVmSdlGraphicsManager::selectGameRenderTarget(bool fullscreen,
|
|
||||||
bool accel3d,
|
|
||||||
bool engineSupportsArbitraryResolutions,
|
|
||||||
bool framebufferSupported,
|
|
||||||
bool lockAspectRatio) {
|
|
||||||
if (!fullscreen) {
|
|
||||||
return kScreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!accel3d && lockAspectRatio) {
|
|
||||||
return kSubScreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!engineSupportsArbitraryResolutions && framebufferSupported) {
|
|
||||||
return kFramebuffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
return kScreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
Math::Rect2d ResVmSdlGraphicsManager::computeGameRect(GameRenderTarget gameRenderTarget, uint gameWidth, uint gameHeight,
|
|
||||||
uint effectiveWidth, uint effectiveHeight) {
|
|
||||||
switch (gameRenderTarget) {
|
|
||||||
case kScreen:
|
|
||||||
// The game occupies the whole screen
|
|
||||||
return Math::Rect2d(Math::Vector2d(0, 0), Math::Vector2d(1, 1));
|
|
||||||
case kSubScreen:
|
|
||||||
// The game is centered on the screen
|
|
||||||
return Math::Rect2d(
|
|
||||||
Math::Vector2d((effectiveWidth - gameWidth) / 2, (effectiveHeight - gameHeight) / 2),
|
|
||||||
Math::Vector2d((effectiveWidth + gameWidth) / 2, (effectiveHeight + gameHeight) / 2)
|
|
||||||
);
|
|
||||||
case kFramebuffer:
|
|
||||||
if (_lockAspectRatio) {
|
|
||||||
// The game is scaled to fit the screen, keeping the same aspect ratio
|
|
||||||
float scale = MIN(effectiveHeight / float(gameHeight), effectiveWidth / float(gameWidth));
|
|
||||||
float scaledW = scale * (gameWidth / float(effectiveWidth));
|
|
||||||
float scaledH = scale * (gameHeight / float(effectiveHeight));
|
|
||||||
return Math::Rect2d(
|
|
||||||
Math::Vector2d(0.5 - (0.5 * scaledW), 0.5 - (0.5 * scaledH)),
|
|
||||||
Math::Vector2d(0.5 + (0.5 * scaledW), 0.5 + (0.5 * scaledH))
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// The game occupies the whole screen
|
|
||||||
return Math::Rect2d(Math::Vector2d(0, 0), Math::Vector2d(1, 1));
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
error("Unhandled game render target '%d'", gameRenderTarget);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ResVmSdlGraphicsManager::canUsePreferredResolution(GameRenderTarget gameRenderTarget,
|
|
||||||
bool engineSupportsArbitraryResolutions) {
|
|
||||||
switch (gameRenderTarget) {
|
|
||||||
case kScreen:
|
|
||||||
// If the game supports arbitrary resolutions, use the preferred mode as the game mode
|
|
||||||
return engineSupportsArbitraryResolutions;
|
|
||||||
case kSubScreen:
|
|
||||||
case kFramebuffer:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
error("Unhandled game render target '%d'", gameRenderTarget);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Common::Rect ResVmSdlGraphicsManager::getPreferredFullscreenResolution() {
|
Common::Rect ResVmSdlGraphicsManager::getPreferredFullscreenResolution() {
|
||||||
// Default to the desktop resolution ...
|
// Default to the desktop resolution ...
|
||||||
uint preferredWidth = _capabilities.desktopWidth;
|
uint preferredWidth = _capabilities.desktopWidth;
|
||||||
|
@ -318,7 +251,7 @@ bool ResVmSdlGraphicsManager::notifyEvent(const Common::Event &event) {
|
||||||
|
|
||||||
void ResVmSdlGraphicsManager::notifyVideoExpose() {
|
void ResVmSdlGraphicsManager::notifyVideoExpose() {
|
||||||
//ResidualVM specific:
|
//ResidualVM specific:
|
||||||
updateScreen();
|
//updateScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ResVmSdlGraphicsManager::notifyMousePosition(Common::Point mouse) {
|
bool ResVmSdlGraphicsManager::notifyMousePosition(Common::Point mouse) {
|
||||||
|
|
|
@ -105,8 +105,6 @@ public:
|
||||||
virtual void clearFocusRectangle() override;
|
virtual void clearFocusRectangle() override;
|
||||||
|
|
||||||
// GraphicsManager API - Overlay
|
// GraphicsManager API - Overlay
|
||||||
virtual int16 getOverlayHeight() const override { return _overlayHeight; }
|
|
||||||
virtual int16 getOverlayWidth() const override { return _overlayWidth; }
|
|
||||||
virtual Graphics::PixelFormat getOverlayFormat() const override { return _overlayFormat; }
|
virtual Graphics::PixelFormat getOverlayFormat() const override { return _overlayFormat; }
|
||||||
|
|
||||||
// GraphicsManager API - Mouse
|
// GraphicsManager API - Mouse
|
||||||
|
@ -139,35 +137,12 @@ protected:
|
||||||
|
|
||||||
bool _overlayVisible;
|
bool _overlayVisible;
|
||||||
Graphics::PixelFormat _overlayFormat;
|
Graphics::PixelFormat _overlayFormat;
|
||||||
int _overlayWidth, _overlayHeight;
|
|
||||||
|
|
||||||
#ifdef USE_RGB_COLOR
|
#ifdef USE_RGB_COLOR
|
||||||
Graphics::PixelFormat _screenFormat;
|
Graphics::PixelFormat _screenFormat;
|
||||||
Common::List<Graphics::PixelFormat> _supportedFormats;
|
Common::List<Graphics::PixelFormat> _supportedFormats;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
* Places where the game can be drawn
|
|
||||||
*/
|
|
||||||
enum GameRenderTarget {
|
|
||||||
kScreen, /** The game is drawn directly on the screen */
|
|
||||||
kSubScreen, /** The game is drawn to a surface, which is centered on the screen */
|
|
||||||
kFramebuffer /** The game is drawn to a framebuffer, which is scaled to fit the screen */
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Select the best draw target according to the specified parameters */
|
|
||||||
GameRenderTarget selectGameRenderTarget(bool fullscreen, bool accel3d,
|
|
||||||
bool engineSupportsArbitraryResolutions,
|
|
||||||
bool framebufferSupported,
|
|
||||||
bool lockAspectRatio);
|
|
||||||
|
|
||||||
/** Compute the size and position of the game rectangle in the screen */
|
|
||||||
Math::Rect2d computeGameRect(GameRenderTarget gameRenderTarget, uint gameWidth, uint gameHeight,
|
|
||||||
uint effectiveWidth, uint effectiveHeight);
|
|
||||||
|
|
||||||
/** Checks if the render target supports drawing at arbitrary resolutions */
|
|
||||||
bool canUsePreferredResolution(GameRenderTarget gameRenderTarget, bool engineSupportsArbitraryResolutions);
|
|
||||||
|
|
||||||
/** Obtain the user configured fullscreen resolution, or default to the desktop resolution */
|
/** Obtain the user configured fullscreen resolution, or default to the desktop resolution */
|
||||||
Common::Rect getPreferredFullscreenResolution();
|
Common::Rect getPreferredFullscreenResolution();
|
||||||
};
|
};
|
||||||
|
|
|
@ -155,8 +155,6 @@ void SurfaceSdlGraphicsManager::createOrUpdateScreen() {
|
||||||
SDL_SetSurfaceBlendMode(_overlayscreen, SDL_BLENDMODE_NONE);
|
SDL_SetSurfaceBlendMode(_overlayscreen, SDL_BLENDMODE_NONE);
|
||||||
#endif // SDL_VERSION_ATLEAST(2, 0, 0)
|
#endif // SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
|
|
||||||
_overlayWidth = effectiveWidth;
|
|
||||||
_overlayHeight = effectiveHeight;
|
|
||||||
_screenFormat = _overlayFormat;
|
_screenFormat = _overlayFormat;
|
||||||
|
|
||||||
_screenChangeCount++;
|
_screenChangeCount++;
|
||||||
|
@ -269,7 +267,7 @@ void SurfaceSdlGraphicsManager::showOverlay() {
|
||||||
|
|
||||||
clearOverlay();
|
clearOverlay();
|
||||||
|
|
||||||
_eventSource->resetKeyboardEmulation(_overlayWidth - 1, _overlayHeight - 1);
|
_eventSource->resetKeyboardEmulation(getOverlayWidth() - 1, getOverlayHeight() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceSdlGraphicsManager::hideOverlay() {
|
void SurfaceSdlGraphicsManager::hideOverlay() {
|
||||||
|
@ -292,9 +290,9 @@ void SurfaceSdlGraphicsManager::grabOverlay(void *buf, int pitch) const {
|
||||||
|
|
||||||
byte *src = (byte *)_overlayscreen->pixels;
|
byte *src = (byte *)_overlayscreen->pixels;
|
||||||
byte *dst = (byte *)buf;
|
byte *dst = (byte *)buf;
|
||||||
int h = _overlayHeight;
|
int h = _overlayscreen->h;
|
||||||
do {
|
do {
|
||||||
memcpy(dst, src, _overlayWidth * _overlayscreen->format->BytesPerPixel);
|
memcpy(dst, src, _overlayscreen->w * _overlayscreen->format->BytesPerPixel);
|
||||||
src += _overlayscreen->pitch;
|
src += _overlayscreen->pitch;
|
||||||
dst += pitch;
|
dst += pitch;
|
||||||
} while (--h);
|
} while (--h);
|
||||||
|
@ -321,12 +319,12 @@ void SurfaceSdlGraphicsManager::copyRectToOverlay(const void *buf, int pitch, in
|
||||||
y = 0;
|
y = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (w > _overlayWidth - x) {
|
if (w > _overlayscreen->w - x) {
|
||||||
w = _overlayWidth - x;
|
w = _overlayscreen->w - x;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h > _overlayHeight - y) {
|
if (h > _overlayscreen->h - y) {
|
||||||
h = _overlayHeight - y;
|
h = _overlayscreen->h - y;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (w <= 0 || h <= 0)
|
if (w <= 0 || h <= 0)
|
||||||
|
|
|
@ -54,6 +54,8 @@ public:
|
||||||
virtual void clearOverlay() override;
|
virtual void clearOverlay() override;
|
||||||
virtual void grabOverlay(void *buf, int pitch) const override;
|
virtual void grabOverlay(void *buf, int pitch) const override;
|
||||||
virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override;
|
virtual void copyRectToOverlay(const void *buf, int pitch, int x, int y, int w, int h) override;
|
||||||
|
virtual int16 getOverlayWidth() const override { return _overlayscreen->w; }
|
||||||
|
virtual int16 getOverlayHeight() const override { return _overlayscreen->h; }
|
||||||
|
|
||||||
/* Render the passed Surfaces besides the game texture.
|
/* Render the passed Surfaces besides the game texture.
|
||||||
* This is used for widescreen support in the Grim engine.
|
* This is used for widescreen support in the Grim engine.
|
||||||
|
|
|
@ -48,7 +48,7 @@ public:
|
||||||
*
|
*
|
||||||
* The format of the input data needs to match the format returned by
|
* The format of the input data needs to match the format returned by
|
||||||
* getFormat.
|
* getFormat.
|
||||||
* This does not immediatly updates the textures.
|
* This does not immediately updates the textures.
|
||||||
*
|
*
|
||||||
* @param x X coordinate of upper left corner to copy data to.
|
* @param x X coordinate of upper left corner to copy data to.
|
||||||
* @param y Y coordinate of upper left corner to copy data to.
|
* @param y Y coordinate of upper left corner to copy data to.
|
||||||
|
@ -98,6 +98,15 @@ public:
|
||||||
*/
|
*/
|
||||||
const Graphics::Surface *getBackingSurface() const;
|
const Graphics::Surface *getBackingSurface() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the dimensions in pixels of the surface
|
||||||
|
*
|
||||||
|
* This does not include the unused area in the textures at the edges
|
||||||
|
* of the grid.
|
||||||
|
*/
|
||||||
|
uint16 getWidth() const { return _backingSurface.w; }
|
||||||
|
uint16 getHeight() const { return _backingSurface.h; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const uint maxTextureSize = 256;
|
static const uint maxTextureSize = 256;
|
||||||
|
|
||||||
|
|
|
@ -330,7 +330,7 @@ void OptionsDialog::build() {
|
||||||
_filteringCheckbox->setVisible(false);
|
_filteringCheckbox->setVisible(false);
|
||||||
|
|
||||||
// Aspect ratio setting
|
// Aspect ratio setting
|
||||||
if (_guioptions.contains(GUIO_NOASPECT) || !_fullscreenCheckbox->getState()) { // ResidualVM specific change
|
if (_guioptions.contains(GUIO_NOASPECT)) { // ResidualVM specific change
|
||||||
_aspectCheckbox->setState(true); // ResidualVM specific change
|
_aspectCheckbox->setState(true); // ResidualVM specific change
|
||||||
_aspectCheckbox->setEnabled(false);
|
_aspectCheckbox->setEnabled(false);
|
||||||
} else {
|
} else {
|
||||||
|
@ -870,11 +870,6 @@ void OptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data
|
||||||
case kGraphicsTabContainerReflowCmd:
|
case kGraphicsTabContainerReflowCmd:
|
||||||
setupGraphicsTab();
|
setupGraphicsTab();
|
||||||
break;
|
break;
|
||||||
// ResidualVM specific
|
|
||||||
case kFullscreenToggled:
|
|
||||||
_aspectCheckbox->setEnabled(_fullscreenCheckbox->getState());
|
|
||||||
g_gui.scheduleTopDialogRedraw();
|
|
||||||
break;
|
|
||||||
case kApplyCmd:
|
case kApplyCmd:
|
||||||
apply();
|
apply();
|
||||||
break;
|
break;
|
||||||
|
@ -905,7 +900,7 @@ void OptionsDialog::setGraphicSettingsState(bool enabled) {
|
||||||
#ifndef GUI_ENABLE_KEYSDIALOG
|
#ifndef GUI_ENABLE_KEYSDIALOG
|
||||||
#ifndef GUI_ONLY_FULLSCREEN
|
#ifndef GUI_ONLY_FULLSCREEN
|
||||||
_fullscreenCheckbox->setEnabled(enabled);
|
_fullscreenCheckbox->setEnabled(enabled);
|
||||||
if (_guioptions.contains(GUIO_NOASPECT) || !_fullscreenCheckbox->getState())
|
if (_guioptions.contains(GUIO_NOASPECT))
|
||||||
#endif // !GUI_ONLY_FULLSCREEN
|
#endif // !GUI_ONLY_FULLSCREEN
|
||||||
_aspectCheckbox->setEnabled(false);
|
_aspectCheckbox->setEnabled(false);
|
||||||
else
|
else
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue