aboutsummaryrefslogtreecommitdiff
path: root/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'backends/graphics/surfacesdl/surfacesdl-graphics.cpp')
-rw-r--r--backends/graphics/surfacesdl/surfacesdl-graphics.cpp220
1 files changed, 165 insertions, 55 deletions
diff --git a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
index 02e58ab319..9cb14525ee 100644
--- a/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
+++ b/backends/graphics/surfacesdl/surfacesdl-graphics.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -40,6 +40,7 @@
#include "graphics/scaler.h"
#include "graphics/scaler/aspect.h"
#include "graphics/surface.h"
+#include "gui/EventRecorder.h"
static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
{"1x", _s("Normal (no scaling)"), GFX_NORMAL},
@@ -115,13 +116,19 @@ static AspectRatio getDesiredAspectRatio() {
}
#endif
-SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSource)
+SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window)
:
- SdlGraphicsManager(sdlEventSource),
+ SdlGraphicsManager(sdlEventSource, window),
#ifdef USE_OSD
_osdSurface(0), _osdAlpha(SDL_ALPHA_TRANSPARENT), _osdFadeStartTime(0),
#endif
- _hwscreen(0), _screen(0), _tmpscreen(0),
+ _hwscreen(0),
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ _renderer(nullptr), _screenTexture(nullptr),
+#else
+ _originalBitsPerPixel(0),
+#endif
+ _screen(0), _tmpscreen(0),
#ifdef USE_RGB_COLOR
_screenFormat(Graphics::PixelFormat::createFormatCLUT8()),
_cursorFormat(Graphics::PixelFormat::createFormatCLUT8()),
@@ -135,19 +142,12 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou
_paletteDirtyStart(0), _paletteDirtyEnd(0),
_screenIsLocked(false),
_graphicsMutex(0),
+ _displayDisabled(false),
#ifdef USE_SDL_DEBUG_FOCUSRECT
_enableFocusRectDebugCode(false), _enableFocusRect(false), _focusRect(),
#endif
_transactionMode(kTransactionNone) {
- if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1) {
- error("Could not initialize SDL: %s", SDL_GetError());
- }
-
- // This is also called in initSDL(), but initializing graphics
- // may reset it.
- SDL_EnableUNICODE(1);
-
// allocate palette storage
_currentPalette = (SDL_Color *)calloc(sizeof(SDL_Color), 256);
_cursorPalette = (SDL_Color *)calloc(sizeof(SDL_Color), 256);
@@ -163,8 +163,6 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou
_enableFocusRectDebugCode = ConfMan.getBool("use_sdl_debug_focusrect");
#endif
- SDL_ShowCursor(SDL_DISABLE);
-
memset(&_oldVideoMode, 0, sizeof(_oldVideoMode));
memset(&_videoMode, 0, sizeof(_videoMode));
memset(&_transactionDetails, 0, sizeof(_transactionDetails));
@@ -191,10 +189,6 @@ SurfaceSdlGraphicsManager::SurfaceSdlGraphicsManager(SdlEventSource *sdlEventSou
}
SurfaceSdlGraphicsManager::~SurfaceSdlGraphicsManager() {
- // Unregister the event observer
- if (g_system->getEventManager()->getEventDispatcher() != NULL)
- g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this);
-
unloadGFXMode();
if (_mouseSurface)
SDL_FreeSurface(_mouseSurface);
@@ -209,11 +203,22 @@ SurfaceSdlGraphicsManager::~SurfaceSdlGraphicsManager() {
free(_mouseData);
}
-void SurfaceSdlGraphicsManager::initEventObserver() {
+void SurfaceSdlGraphicsManager::activateManager() {
+ SdlGraphicsManager::activateManager();
+
// Register the graphics manager as a event observer
g_system->getEventManager()->getEventDispatcher()->registerObserver(this, 10, false);
}
+void SurfaceSdlGraphicsManager::deactivateManager() {
+ // Unregister the event observer
+ if (g_system->getEventManager()->getEventDispatcher()) {
+ g_system->getEventManager()->getEventDispatcher()->unregisterObserver(this);
+ }
+
+ SdlGraphicsManager::deactivateManager();
+}
+
bool SurfaceSdlGraphicsManager::hasFeature(OSystem::Feature f) {
return
(f == OSystem::kFeatureFullscreenMode) ||
@@ -236,7 +241,7 @@ void SurfaceSdlGraphicsManager::setFeatureState(OSystem::Feature f, bool enable)
break;
case OSystem::kFeatureIconifyWindow:
if (enable)
- SDL_WM_IconifyWindow();
+ _window->iconifyWindow();
break;
default:
break;
@@ -261,16 +266,16 @@ bool SurfaceSdlGraphicsManager::getFeatureState(OSystem::Feature f) {
}
}
-const OSystem::GraphicsMode *SurfaceSdlGraphicsManager::supportedGraphicsModes() {
- return s_supportedGraphicsModes;
-}
-
const OSystem::GraphicsMode *SurfaceSdlGraphicsManager::getSupportedGraphicsModes() const {
return s_supportedGraphicsModes;
}
int SurfaceSdlGraphicsManager::getDefaultGraphicsMode() const {
+#ifdef USE_SCALERS
return GFX_DOUBLESIZE;
+#else
+ return GFX_NORMAL;
+#endif
}
void SurfaceSdlGraphicsManager::resetGraphicsScale() {
@@ -682,12 +687,22 @@ static void fixupResolutionForAspectRatio(AspectRatio desiredAspectRatio, int &w
const int w = width;
const int h = height;
+ int bestW = 0, bestH = 0;
+ uint bestMetric = (uint)-1; // Metric is wasted space
+
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ const int numModes = SDL_GetNumDisplayModes(0);
+ SDL_DisplayMode modeData, *mode = &modeData;
+ for (int i = 0; i < numModes; ++i) {
+ if (SDL_GetDisplayMode(0, i, &modeData)) {
+ continue;
+ }
+#else
SDL_Rect const* const*availableModes = SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_SWSURFACE); //TODO : Maybe specify a pixel format
assert(availableModes);
- const SDL_Rect *bestMode = NULL;
- uint bestMetric = (uint)-1; // Metric is wasted space
while (const SDL_Rect *mode = *availableModes++) {
+#endif
if (mode->w < w)
continue;
if (mode->h < h)
@@ -700,15 +715,23 @@ static void fixupResolutionForAspectRatio(AspectRatio desiredAspectRatio, int &w
continue;
bestMetric = metric;
- bestMode = mode;
+ bestW = mode->w;
+ bestH = mode->h;
+
+ // Make editors a bit more happy by having the same amount of closing as
+ // opening curley braces.
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ }
+#else
}
+#endif
- if (!bestMode) {
+ if (!bestW || !bestH) {
warning("Unable to enforce the desired aspect ratio");
return;
}
- width = bestMode->w;
- height = bestMode->h;
+ width = bestW;
+ height = bestH;
}
bool SurfaceSdlGraphicsManager::loadGFXMode() {
@@ -745,6 +768,8 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() {
if (_screen == NULL)
error("allocating _screen failed");
+ // Avoid having SDL_SRCALPHA set even if we supplied an alpha-channel in the format.
+ SDL_SetAlpha(_screen, 0, 255);
#else
_screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth, _videoMode.screenHeight, 8, 0, 0, 0, 0);
if (_screen == NULL)
@@ -765,9 +790,28 @@ bool SurfaceSdlGraphicsManager::loadGFXMode() {
fixupResolutionForAspectRatio(_videoMode.desiredAspectRatio, _videoMode.hardwareWidth, _videoMode.hardwareHeight);
}
- _hwscreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 16,
- _videoMode.fullscreen ? (SDL_FULLSCREEN|SDL_SWSURFACE) : SDL_SWSURFACE
- );
+
+#ifdef ENABLE_EVENTRECORDER
+ _displayDisabled = ConfMan.getBool("disable_display");
+
+ if (_displayDisabled) {
+ _hwscreen = g_eventRec.getSurface(_videoMode.hardwareWidth, _videoMode.hardwareHeight);
+ } else
+#endif
+ {
+ // Save the original bpp to be able to restore the video mode on unload
+#if !SDL_VERSION_ATLEAST(2, 0, 0)
+ if (_originalBitsPerPixel == 0) {
+ const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();
+ _originalBitsPerPixel = videoInfo->vfmt->BitsPerPixel;
+ }
+#endif
+
+ _hwscreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 16,
+ _videoMode.fullscreen ? (SDL_FULLSCREEN|SDL_SWSURFACE) : SDL_SWSURFACE
+ );
+ }
+
#ifdef USE_RGB_COLOR
detectSupportedFormats();
#endif
@@ -864,6 +908,10 @@ void SurfaceSdlGraphicsManager::unloadGFXMode() {
_screen = NULL;
}
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ deinitializeRenderer();
+#endif
+
if (_hwscreen) {
SDL_FreeSurface(_hwscreen);
_hwscreen = NULL;
@@ -891,6 +939,13 @@ void SurfaceSdlGraphicsManager::unloadGFXMode() {
}
#endif
DestroyScalers();
+
+#if !SDL_VERSION_ATLEAST(2, 0, 0)
+ // Reset video mode to original
+ // This will ensure that any new graphic manager will use the initial BPP when listing available modes
+ if (_originalBitsPerPixel != 0)
+ SDL_SetVideoMode(_videoMode.screenWidth, _videoMode.screenHeight, _originalBitsPerPixel, _videoMode.fullscreen ? (SDL_FULLSCREEN | SDL_SWSURFACE) : SDL_SWSURFACE);
+#endif
}
bool SurfaceSdlGraphicsManager::hotswapGFXMode() {
@@ -1068,7 +1123,9 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
for (r = _dirtyRectList; r != lastRect; ++r) {
register int dst_y = r->y + _currentShakePos;
register int dst_h = 0;
+#ifdef USE_SCALERS
register int orig_dst_y = 0;
+#endif
register int rx1 = r->x * scale1;
if (dst_y < height) {
@@ -1076,7 +1133,9 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
if (dst_h > height - dst_y)
dst_h = height - dst_y;
+#ifdef USE_SCALERS
orig_dst_y = dst_y;
+#endif
dst_y = dst_y * scale1;
if (_videoMode.aspectRatioCorrection && !_overlayVisible)
@@ -1188,7 +1247,9 @@ void SurfaceSdlGraphicsManager::internUpdateScreen() {
#endif
// Finally, blit all our changes to the screen
- SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList);
+ if (!_displayDisabled) {
+ SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList);
+ }
}
_numDirtyRects = 0;
@@ -1293,15 +1354,13 @@ Graphics::Surface *SurfaceSdlGraphicsManager::lockScreen() {
if (SDL_LockSurface(_screen) == -1)
error("SDL_LockSurface failed: %s", SDL_GetError());
- _framebuffer.pixels = _screen->pixels;
- _framebuffer.w = _screen->w;
- _framebuffer.h = _screen->h;
- _framebuffer.pitch = _screen->pitch;
+ _framebuffer.init(_screen->w, _screen->h, _screen->pitch, _screen->pixels,
#ifdef USE_RGB_COLOR
- _framebuffer.format = _screenFormat;
+ _screenFormat
#else
- _framebuffer.format = Graphics::PixelFormat::createFormatCLUT8();
+ Graphics::PixelFormat::createFormatCLUT8()
#endif
+ );
return &_framebuffer;
}
@@ -1325,8 +1384,8 @@ void SurfaceSdlGraphicsManager::unlockScreen() {
void SurfaceSdlGraphicsManager::fillScreen(uint32 col) {
Graphics::Surface *screen = lockScreen();
- if (screen && screen->pixels)
- memset(screen->pixels, col, screen->h * screen->pitch);
+ if (screen && screen->getPixels())
+ memset(screen->getPixels(), col, screen->h * screen->pitch);
unlockScreen();
}
@@ -1427,6 +1486,9 @@ void SurfaceSdlGraphicsManager::setPalette(const byte *colors, uint start, uint
base[i].r = b[0];
base[i].g = b[1];
base[i].b = b[2];
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ base[i].a = 255;
+#endif
}
if (start < _paletteDirtyStart)
@@ -1465,6 +1527,9 @@ void SurfaceSdlGraphicsManager::setCursorPalette(const byte *colors, uint start,
base[i].r = b[0];
base[i].g = b[1];
base[i].b = b[2];
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+ base[i].a = 255;
+#endif
}
_cursorPaletteDisabled = false;
@@ -1694,7 +1759,7 @@ void SurfaceSdlGraphicsManager::warpMouse(int x, int y) {
int y1 = y;
// Don't change actual mouse position, when mouse is outside of our window (in case of windowed mode)
- if (!(SDL_GetAppState( ) & SDL_APPMOUSEFOCUS)) {
+ if (!_window->hasMouseFocus()) {
setMousePos(x, y); // but change game cursor position
return;
}
@@ -1704,9 +1769,9 @@ void SurfaceSdlGraphicsManager::warpMouse(int x, int y) {
if (_mouseCurState.x != x || _mouseCurState.y != y) {
if (!_overlayVisible)
- SDL_WarpMouse(x * _videoMode.scaleFactor, y1 * _videoMode.scaleFactor);
+ _window->warpMouseInWindow(x * _videoMode.scaleFactor, y1 * _videoMode.scaleFactor);
else
- SDL_WarpMouse(x, y1);
+ _window->warpMouseInWindow(x, y1);
// SDL_WarpMouse() generates a mouse movement event, so
// setMousePos() would be called eventually. However, the
@@ -2047,15 +2112,12 @@ void SurfaceSdlGraphicsManager::displayMessageOnOSD(const char *msg) {
error("displayMessageOnOSD: SDL_LockSurface failed: %s", SDL_GetError());
Graphics::Surface dst;
- dst.pixels = _osdSurface->pixels;
- dst.w = _osdSurface->w;
- dst.h = _osdSurface->h;
- dst.pitch = _osdSurface->pitch;
- dst.format = Graphics::PixelFormat(_osdSurface->format->BytesPerPixel,
- 8 - _osdSurface->format->Rloss, 8 - _osdSurface->format->Gloss,
- 8 - _osdSurface->format->Bloss, 8 - _osdSurface->format->Aloss,
- _osdSurface->format->Rshift, _osdSurface->format->Gshift,
- _osdSurface->format->Bshift, _osdSurface->format->Ashift);
+ dst.init(_osdSurface->w, _osdSurface->h, _osdSurface->pitch, _osdSurface->pixels,
+ Graphics::PixelFormat(_osdSurface->format->BytesPerPixel,
+ 8 - _osdSurface->format->Rloss, 8 - _osdSurface->format->Gloss,
+ 8 - _osdSurface->format->Bloss, 8 - _osdSurface->format->Aloss,
+ _osdSurface->format->Rshift, _osdSurface->format->Gshift,
+ _osdSurface->format->Bshift, _osdSurface->format->Ashift));
// The font we are going to use:
const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kLocalizedFont);
@@ -2304,4 +2366,52 @@ void SurfaceSdlGraphicsManager::notifyMousePos(Common::Point mouse) {
setMousePos(mouse.x, mouse.y);
}
+#if SDL_VERSION_ATLEAST(2, 0, 0)
+void SurfaceSdlGraphicsManager::deinitializeRenderer() {
+ SDL_DestroyTexture(_screenTexture);
+ _screenTexture = nullptr;
+
+ SDL_DestroyRenderer(_renderer);
+ _renderer = nullptr;
+
+ _window->destroyWindow();
+}
+
+SDL_Surface *SurfaceSdlGraphicsManager::SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) {
+ deinitializeRenderer();
+
+ if (!_window->createWindow(width, height, (flags & SDL_FULLSCREEN) ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0)) {
+ return nullptr;
+ }
+
+ _renderer = SDL_CreateRenderer(_window->getSDLWindow(), -1, 0);
+ if (!_renderer) {
+ deinitializeRenderer();
+ return nullptr;
+ }
+
+ _screenTexture = SDL_CreateTexture(_renderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_STREAMING, width, height);
+ if (!_screenTexture) {
+ deinitializeRenderer();
+ return nullptr;
+ }
+
+ SDL_Surface *screen = SDL_CreateRGBSurface(0, width, height, 16, 0xF800, 0x7E0, 0x1F, 0);
+ if (!screen) {
+ deinitializeRenderer();
+ return nullptr;
+ } else {
+ return screen;
+ }
+}
+
+void SurfaceSdlGraphicsManager::SDL_UpdateRects(SDL_Surface *screen, int numrects, SDL_Rect *rects) {
+ SDL_UpdateTexture(_screenTexture, nullptr, screen->pixels, screen->pitch);
+
+ SDL_RenderClear(_renderer);
+ SDL_RenderCopy(_renderer, _screenTexture, NULL, NULL);
+ SDL_RenderPresent(_renderer);
+}
+#endif // SDL_VERSION_ATLEAST(2, 0, 0)
+
#endif