diff options
Diffstat (limited to 'backends/graphics/surfacesdl/surfacesdl-graphics.cpp')
-rw-r--r-- | backends/graphics/surfacesdl/surfacesdl-graphics.cpp | 220 |
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 |