2007-05-30 21:56:52 +00:00
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers , whose names
* are too numerous to list here . Please refer to the COPYRIGHT
* file distributed with this source distribution .
2004-02-29 00:49:40 +00:00
*
* This program is free software ; you can redistribute it and / or
* 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 .
2014-02-18 02:34:24 +01:00
*
2004-02-29 00:49:40 +00:00
* 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 .
2014-02-18 02:34:24 +01:00
*
2004-02-29 00:49:40 +00:00
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
2005-10-18 01:30:26 +00:00
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
2004-02-29 00:49:40 +00:00
*
*/
2010-11-29 16:18:43 +00:00
# include "common/scummsys.h"
2010-08-12 06:30:26 +00:00
# if defined(SDL_BACKEND)
2010-06-09 05:29:14 +00:00
2011-06-19 20:08:55 +02:00
# include "backends/graphics/surfacesdl/surfacesdl-graphics.h"
2010-07-19 05:33:58 +00:00
# include "backends/events/sdl/sdl-events.h"
2007-08-11 08:44:43 +00:00
# include "backends/platform/sdl/sdl.h"
2010-06-07 03:14:42 +00:00
# include "common/config-manager.h"
2009-01-30 03:35:47 +00:00
# include "common/mutex.h"
2011-04-24 11:34:27 +03:00
# include "common/textconsole.h"
2010-06-26 15:48:03 +00:00
# include "common/translation.h"
2004-02-29 00:49:40 +00:00
# include "common/util.h"
2015-12-13 20:20:23 +01:00
# include "common/frac.h"
2009-08-21 18:16:37 +00:00
# ifdef USE_RGB_COLOR
2009-07-10 06:46:50 +00:00
# include "common/list.h"
# endif
2004-03-21 21:20:25 +00:00
# include "graphics/font.h"
2005-01-06 21:15:52 +00:00
# include "graphics/fontman.h"
2006-02-20 20:29:02 +00:00
# include "graphics/scaler.h"
2010-03-08 10:29:00 +00:00
# include "graphics/scaler/aspect.h"
2005-05-08 21:39:05 +00:00
# include "graphics/surface.h"
2013-05-17 00:18:09 +03:00
# include "gui/EventRecorder.h"
2017-05-12 12:44:44 -05:00
# ifdef USE_PNG
# include "common/file.h"
# include "image/png.h"
# endif
2004-02-29 00:49:40 +00:00
2017-03-01 14:00:17 -06:00
static const OSystem : : GraphicsMode s_supportedShaders [ ] = {
{ " NONE " , " Normal (no shader) " , 0 } ,
{ 0 , 0 , 0 }
} ;
2004-02-29 00:49:40 +00:00
static const OSystem : : GraphicsMode s_supportedGraphicsModes [ ] = {
2010-06-26 15:48:03 +00:00
{ " 1x " , _s ( " Normal (no scaling) " ) , GFX_NORMAL } ,
2010-05-09 11:00:17 +00:00
# ifdef USE_SCALERS
2004-02-29 00:49:40 +00:00
{ " 2x " , " 2x " , GFX_DOUBLESIZE } ,
{ " 3x " , " 3x " , GFX_TRIPLESIZE } ,
{ " 2xsai " , " 2xSAI " , GFX_2XSAI } ,
{ " super2xsai " , " Super2xSAI " , GFX_SUPER2XSAI } ,
{ " supereagle " , " SuperEagle " , GFX_SUPEREAGLE } ,
{ " advmame2x " , " AdvMAME2x " , GFX_ADVMAME2X } ,
{ " advmame3x " , " AdvMAME3x " , GFX_ADVMAME3X } ,
2010-05-09 11:00:17 +00:00
# ifdef USE_HQ_SCALERS
2004-02-29 00:49:40 +00:00
{ " hq2x " , " HQ2x " , GFX_HQ2X } ,
{ " hq3x " , " HQ3x " , GFX_HQ3X } ,
2010-05-10 17:25:12 +00:00
# endif
{ " tv2x " , " TV2x " , GFX_TV2X } ,
{ " dotmatrix " , " DotMatrix " , GFX_DOTMATRIX } ,
2009-11-10 22:12:10 +00:00
# endif
2004-02-29 00:49:40 +00:00
{ 0 , 0 , 0 }
} ;
2010-08-30 22:24:40 +00:00
DECLARE_TRANSLATION_ADDITIONAL_CONTEXT ( " Normal (no scaling) " , " lowres " )
2012-06-03 02:02:57 +02:00
// Table of the cursor scalers [scaleFactor - 1]
static ScalerProc * scalersMagn [ 3 ] = {
2010-05-10 17:25:12 +00:00
# ifdef USE_SCALERS
2012-06-03 02:02:57 +02:00
Normal1x , AdvMame2x , AdvMame3x
2005-06-21 20:39:09 +00:00
# else // remove dependencies on other scalers
2012-06-03 02:02:57 +02:00
Normal1x , Normal1x , Normal1x
2005-06-21 20:39:09 +00:00
# endif
2005-02-17 23:01:00 +00:00
} ;
2005-07-11 10:54:53 +00:00
static const int s_gfxModeSwitchTable [ ] [ 4 ] = {
{ GFX_NORMAL , GFX_DOUBLESIZE , GFX_TRIPLESIZE , - 1 } ,
{ GFX_NORMAL , GFX_ADVMAME2X , GFX_ADVMAME3X , - 1 } ,
{ GFX_NORMAL , GFX_HQ2X , GFX_HQ3X , - 1 } ,
{ GFX_NORMAL , GFX_2XSAI , - 1 , - 1 } ,
{ GFX_NORMAL , GFX_SUPER2XSAI , - 1 , - 1 } ,
{ GFX_NORMAL , GFX_SUPEREAGLE , - 1 , - 1 } ,
{ GFX_NORMAL , GFX_TV2X , - 1 , - 1 } ,
{ GFX_NORMAL , GFX_DOTMATRIX , - 1 , - 1 }
} ;
2010-05-10 17:25:12 +00:00
# ifdef USE_SCALERS
2005-02-17 23:01:00 +00:00
static int cursorStretch200To240 ( uint8 * buf , uint32 pitch , int width , int height , int srcX , int srcY , int origSrcY ) ;
2006-02-20 14:12:59 +00:00
# endif
2005-02-17 23:01:00 +00:00
2010-06-07 03:14:42 +00:00
AspectRatio : : AspectRatio ( int w , int h ) {
// TODO : Validation and so on...
// Currently, we just ensure the program don't instantiate non-supported aspect ratios
_kw = w ;
_kh = h ;
}
# if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) && defined(USE_SCALERS)
static AspectRatio getDesiredAspectRatio ( ) {
2010-07-13 04:31:15 +00:00
const size_t AR_COUNT = 4 ;
2010-07-26 06:58:33 +00:00
const char * desiredAspectRatioAsStrings [ AR_COUNT ] = { " auto " , " 4/3 " , " 16/9 " , " 16/10 " } ;
const AspectRatio desiredAspectRatios [ AR_COUNT ] = { AspectRatio ( 0 , 0 ) , AspectRatio ( 4 , 3 ) , AspectRatio ( 16 , 9 ) , AspectRatio ( 16 , 10 ) } ;
2010-07-13 04:31:15 +00:00
2010-06-07 03:14:42 +00:00
//TODO : We could parse an arbitrary string, if we code enough proper validation
Common : : String desiredAspectRatio = ConfMan . get ( " desired_screen_aspect_ratio " ) ;
for ( size_t i = 0 ; i < AR_COUNT ; i + + ) {
assert ( desiredAspectRatioAsStrings [ i ] ! = NULL ) ;
if ( ! scumm_stricmp ( desiredAspectRatio . c_str ( ) , desiredAspectRatioAsStrings [ i ] ) ) {
return desiredAspectRatios [ i ] ;
}
}
// TODO : Report a warning
return AspectRatio ( 0 , 0 ) ;
}
# endif
2015-02-16 00:49:42 +01:00
SurfaceSdlGraphicsManager : : SurfaceSdlGraphicsManager ( SdlEventSource * sdlEventSource , SdlWindow * window )
2010-06-07 03:14:42 +00:00
:
2015-02-16 00:49:42 +01:00
SdlGraphicsManager ( sdlEventSource , window ) ,
2010-06-07 03:14:42 +00:00
# ifdef USE_OSD
2016-09-13 20:33:42 +02:00
_osdMessageSurface ( nullptr ) , _osdMessageAlpha ( SDL_ALPHA_TRANSPARENT ) , _osdMessageFadeStartTime ( 0 ) ,
_osdIconSurface ( nullptr ) ,
2010-06-07 03:14:42 +00:00
# endif
2015-01-25 01:34:57 +01:00
_hwscreen ( 0 ) ,
# if SDL_VERSION_ATLEAST(2, 0, 0)
_renderer ( nullptr ) , _screenTexture ( nullptr ) ,
2015-12-13 20:20:23 +01:00
_viewport ( ) , _windowWidth ( 1 ) , _windowHeight ( 1 ) ,
2016-02-17 16:17:39 +01:00
# endif
# if defined(WIN32) && !SDL_VERSION_ATLEAST(2, 0, 0)
2015-05-20 00:08:42 +02:00
_originalBitsPerPixel ( 0 ) ,
2015-01-25 01:34:57 +01:00
# endif
_screen ( 0 ) , _tmpscreen ( 0 ) ,
2010-06-07 03:14:42 +00:00
# ifdef USE_RGB_COLOR
_screenFormat ( Graphics : : PixelFormat : : createFormatCLUT8 ( ) ) ,
_cursorFormat ( Graphics : : PixelFormat : : createFormatCLUT8 ( ) ) ,
# endif
_overlayVisible ( false ) ,
_overlayscreen ( 0 ) , _tmpscreen2 ( 0 ) ,
2010-06-11 02:50:25 +00:00
_scalerProc ( 0 ) , _screenChangeCount ( 0 ) ,
2010-06-07 03:14:42 +00:00
_mouseVisible ( false ) , _mouseNeedsRedraw ( false ) , _mouseData ( 0 ) , _mouseSurface ( 0 ) ,
2012-06-03 02:02:57 +02:00
_mouseOrigSurface ( 0 ) , _cursorDontScale ( false ) , _cursorPaletteDisabled ( true ) ,
2010-06-07 03:14:42 +00:00
_currentShakePos ( 0 ) , _newShakePos ( 0 ) ,
_paletteDirtyStart ( 0 ) , _paletteDirtyEnd ( 0 ) ,
_screenIsLocked ( false ) ,
2011-02-24 01:11:16 +01:00
_graphicsMutex ( 0 ) ,
2013-05-17 00:18:09 +03:00
_displayDisabled ( false ) ,
2011-02-24 01:11:16 +01:00
# ifdef USE_SDL_DEBUG_FOCUSRECT
2011-02-24 01:15:27 +01:00
_enableFocusRectDebugCode ( false ) , _enableFocusRect ( false ) , _focusRect ( ) ,
2011-02-24 01:11:16 +01:00
# endif
_transactionMode ( kTransactionNone ) {
2010-06-07 03:14:42 +00:00
// allocate palette storage
_currentPalette = ( SDL_Color * ) calloc ( sizeof ( SDL_Color ) , 256 ) ;
_cursorPalette = ( SDL_Color * ) calloc ( sizeof ( SDL_Color ) , 256 ) ;
_mouseBackup . x = _mouseBackup . y = _mouseBackup . w = _mouseBackup . h = 0 ;
memset ( & _mouseCurState , 0 , sizeof ( _mouseCurState ) ) ;
_graphicsMutex = g_system - > createMutex ( ) ;
2011-02-24 01:15:27 +01:00
# ifdef USE_SDL_DEBUG_FOCUSRECT
if ( ConfMan . hasKey ( " use_sdl_debug_focusrect " ) )
_enableFocusRectDebugCode = ConfMan . getBool ( " use_sdl_debug_focusrect " ) ;
# endif
2010-06-07 03:14:42 +00:00
memset ( & _oldVideoMode , 0 , sizeof ( _oldVideoMode ) ) ;
memset ( & _videoMode , 0 , sizeof ( _videoMode ) ) ;
memset ( & _transactionDetails , 0 , sizeof ( _transactionDetails ) ) ;
# if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) && defined(USE_SCALERS)
_videoMode . mode = GFX_DOUBLESIZE ;
_videoMode . scaleFactor = 2 ;
_videoMode . aspectRatioCorrection = ConfMan . getBool ( " aspect_ratio " ) ;
_videoMode . desiredAspectRatio = getDesiredAspectRatio ( ) ;
_scalerProc = Normal2x ;
# else // for small screen platforms
_videoMode . mode = GFX_NORMAL ;
_videoMode . scaleFactor = 1 ;
_videoMode . aspectRatioCorrection = false ;
_scalerProc = Normal1x ;
# endif
_scalerType = 0 ;
# if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
_videoMode . fullscreen = ConfMan . getBool ( " fullscreen " ) ;
# else
_videoMode . fullscreen = true ;
# endif
2016-10-12 22:38:07 +01:00
# if SDL_VERSION_ATLEAST(2, 0, 0)
_videoMode . filtering = ConfMan . getBool ( " filtering " ) ;
# endif
2017-03-01 14:00:17 -06:00
2017-03-06 08:57:21 -06:00
// the default backend has no shaders
// shader number 0 is the entry NONE (no shader)
// for an example on shader support,
// consult the psp2sdl backend which inherits from this class
_currentShader = 0 ;
_numShaders = 1 ;
2010-06-07 03:14:42 +00:00
}
2011-06-19 20:08:55 +02:00
SurfaceSdlGraphicsManager : : ~ SurfaceSdlGraphicsManager ( ) {
2010-06-07 03:14:42 +00:00
unloadGFXMode ( ) ;
2017-02-12 19:17:33 -06:00
# if SDL_VERSION_ATLEAST(2, 0, 0)
if ( _window )
_window - > destroyWindow ( ) ;
# endif
2010-11-29 18:33:46 +00:00
if ( _mouseSurface )
SDL_FreeSurface ( _mouseSurface ) ;
2010-11-29 18:16:11 +00:00
_mouseSurface = 0 ;
2010-11-29 18:33:46 +00:00
if ( _mouseOrigSurface )
SDL_FreeSurface ( _mouseOrigSurface ) ;
2010-11-29 18:16:11 +00:00
_mouseOrigSurface = 0 ;
2010-06-07 03:14:42 +00:00
g_system - > deleteMutex ( _graphicsMutex ) ;
free ( _currentPalette ) ;
free ( _cursorPalette ) ;
free ( _mouseData ) ;
}
2013-10-20 22:27:50 +02:00
void SurfaceSdlGraphicsManager : : activateManager ( ) {
2013-10-24 00:06:32 +02:00
SdlGraphicsManager : : activateManager ( ) ;
2013-10-20 22:27:50 +02:00
2010-09-03 04:23:01 +00:00
// Register the graphics manager as a event observer
g_system - > getEventManager ( ) - > getEventDispatcher ( ) - > registerObserver ( this , 10 , false ) ;
}
2013-10-20 22:27:50 +02:00
void SurfaceSdlGraphicsManager : : deactivateManager ( ) {
// Unregister the event observer
if ( g_system - > getEventManager ( ) - > getEventDispatcher ( ) ) {
g_system - > getEventManager ( ) - > getEventDispatcher ( ) - > unregisterObserver ( this ) ;
}
2013-10-24 00:06:32 +02:00
SdlGraphicsManager : : deactivateManager ( ) ;
2013-10-20 22:27:50 +02:00
}
2011-06-19 20:08:55 +02:00
bool SurfaceSdlGraphicsManager : : hasFeature ( OSystem : : Feature f ) {
2010-06-07 03:14:42 +00:00
return
( f = = OSystem : : kFeatureFullscreenMode ) | |
( f = = OSystem : : kFeatureAspectRatioCorrection ) | |
2016-10-12 22:38:07 +01:00
# if SDL_VERSION_ATLEAST(2, 0, 0)
( f = = OSystem : : kFeatureFilteringMode ) | |
# endif
2011-06-03 23:30:55 +02:00
( f = = OSystem : : kFeatureCursorPalette ) | |
2010-06-07 03:14:42 +00:00
( f = = OSystem : : kFeatureIconifyWindow ) ;
}
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : setFeatureState ( OSystem : : Feature f , bool enable ) {
2010-06-07 03:14:42 +00:00
switch ( f ) {
case OSystem : : kFeatureFullscreenMode :
setFullscreenMode ( enable ) ;
break ;
case OSystem : : kFeatureAspectRatioCorrection :
setAspectRatioCorrection ( enable ) ;
break ;
2016-10-12 22:38:07 +01:00
# if SDL_VERSION_ATLEAST(2, 0, 0)
case OSystem : : kFeatureFilteringMode :
setFilteringMode ( enable ) ;
break ;
# endif
2011-06-04 00:14:09 +02:00
case OSystem : : kFeatureCursorPalette :
_cursorPaletteDisabled = ! enable ;
blitCursor ( ) ;
break ;
2010-06-07 03:14:42 +00:00
case OSystem : : kFeatureIconifyWindow :
if ( enable )
2015-02-16 00:49:42 +01:00
_window - > iconifyWindow ( ) ;
2010-06-07 03:14:42 +00:00
break ;
default :
break ;
}
}
2011-06-19 20:08:55 +02:00
bool SurfaceSdlGraphicsManager : : getFeatureState ( OSystem : : Feature f ) {
2011-08-11 04:25:46 +02:00
// We need to allow this to be called from within a transaction, since we
// currently use it to retreive the graphics state, when switching from
// SDL->OpenGL mode for example.
//assert(_transactionMode == kTransactionNone);
2010-06-07 03:14:42 +00:00
switch ( f ) {
case OSystem : : kFeatureFullscreenMode :
return _videoMode . fullscreen ;
case OSystem : : kFeatureAspectRatioCorrection :
return _videoMode . aspectRatioCorrection ;
2016-10-12 22:38:07 +01:00
# if SDL_VERSION_ATLEAST(2, 0, 0)
case OSystem : : kFeatureFilteringMode :
return _videoMode . filtering ;
# endif
2011-06-04 00:14:09 +02:00
case OSystem : : kFeatureCursorPalette :
return ! _cursorPaletteDisabled ;
2010-06-07 03:14:42 +00:00
default :
return false ;
}
}
2011-06-19 20:08:55 +02:00
const OSystem : : GraphicsMode * SurfaceSdlGraphicsManager : : getSupportedGraphicsModes ( ) const {
2010-06-05 22:45:36 +00:00
return s_supportedGraphicsModes ;
}
2011-06-19 20:08:55 +02:00
int SurfaceSdlGraphicsManager : : getDefaultGraphicsMode ( ) const {
2014-01-07 01:46:28 +01:00
# ifdef USE_SCALERS
2004-03-15 00:45:45 +00:00
return GFX_DOUBLESIZE ;
2014-01-07 01:46:28 +01:00
# else
return GFX_NORMAL ;
# endif
2004-03-15 00:45:45 +00:00
}
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : resetGraphicsScale ( ) {
2010-07-30 03:06:57 +00:00
setGraphicsMode ( s_gfxModeSwitchTable [ _scalerType ] [ 0 ] ) ;
}
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : beginGFXTransaction ( ) {
2008-11-14 22:08:10 +00:00
assert ( _transactionMode = = kTransactionNone ) ;
2004-11-23 21:30:38 +00:00
_transactionMode = kTransactionActive ;
2005-03-09 23:07:32 +00:00
_transactionDetails . sizeChanged = false ;
2005-02-22 01:29:27 +00:00
_transactionDetails . needHotswap = false ;
_transactionDetails . needUpdatescreen = false ;
2005-03-20 16:16:09 +00:00
2016-10-13 00:19:15 +01:00
# if SDL_VERSION_ATLEAST(2, 0, 0)
_transactionDetails . needTextureUpdate = false ;
# endif
2009-08-21 18:16:37 +00:00
# ifdef USE_RGB_COLOR
2009-06-10 05:35:18 +00:00
_transactionDetails . formatChanged = false ;
# endif
2008-11-14 22:08:10 +00:00
_oldVideoMode = _videoMode ;
2004-11-23 21:30:38 +00:00
}
2011-06-19 20:08:55 +02:00
OSystem : : TransactionError SurfaceSdlGraphicsManager : : endGFXTransaction ( ) {
2010-06-05 22:45:36 +00:00
int errors = OSystem : : kTransactionSuccess ;
2008-11-14 22:08:10 +00:00
assert ( _transactionMode ! = kTransactionNone ) ;
2005-03-20 16:16:09 +00:00
2008-11-14 22:08:10 +00:00
if ( _transactionMode = = kTransactionRollback ) {
if ( _videoMode . fullscreen ! = _oldVideoMode . fullscreen ) {
2010-06-05 22:45:36 +00:00
errors | = OSystem : : kTransactionFullscreenFailed ;
2004-11-23 21:30:38 +00:00
2008-11-14 22:08:10 +00:00
_videoMode . fullscreen = _oldVideoMode . fullscreen ;
2009-05-01 09:09:07 +00:00
} else if ( _videoMode . aspectRatioCorrection ! = _oldVideoMode . aspectRatioCorrection ) {
2010-06-05 22:45:36 +00:00
errors | = OSystem : : kTransactionAspectRatioFailed ;
2005-02-22 01:29:27 +00:00
2009-05-01 09:09:07 +00:00
_videoMode . aspectRatioCorrection = _oldVideoMode . aspectRatioCorrection ;
2008-11-14 22:08:10 +00:00
} else if ( _videoMode . mode ! = _oldVideoMode . mode ) {
2010-06-05 22:45:36 +00:00
errors | = OSystem : : kTransactionModeSwitchFailed ;
2005-02-22 01:29:27 +00:00
2008-11-14 22:08:10 +00:00
_videoMode . mode = _oldVideoMode . mode ;
_videoMode . scaleFactor = _oldVideoMode . scaleFactor ;
2016-10-12 22:38:07 +01:00
# if SDL_VERSION_ATLEAST(2, 0, 0)
} else if ( _videoMode . filtering ! = _oldVideoMode . filtering ) {
errors | = OSystem : : kTransactionFilteringFailed ;
2016-11-13 16:36:18 +01:00
2016-10-12 22:38:07 +01:00
_videoMode . filtering = _oldVideoMode . filtering ;
# endif
2009-08-21 18:16:37 +00:00
# ifdef USE_RGB_COLOR
2009-06-11 05:56:00 +00:00
} else if ( _videoMode . format ! = _oldVideoMode . format ) {
2010-06-05 22:45:36 +00:00
errors | = OSystem : : kTransactionFormatNotSupported ;
2009-06-11 05:56:00 +00:00
_videoMode . format = _oldVideoMode . format ;
2009-06-12 08:49:45 +00:00
_screenFormat = _videoMode . format ;
2009-06-11 05:56:00 +00:00
# endif
2008-11-14 22:08:10 +00:00
} else if ( _videoMode . screenWidth ! = _oldVideoMode . screenWidth | | _videoMode . screenHeight ! = _oldVideoMode . screenHeight ) {
2010-06-05 22:45:36 +00:00
errors | = OSystem : : kTransactionSizeChangeFailed ;
2008-11-14 22:08:10 +00:00
_videoMode . screenWidth = _oldVideoMode . screenWidth ;
_videoMode . screenHeight = _oldVideoMode . screenHeight ;
_videoMode . overlayWidth = _oldVideoMode . overlayWidth ;
_videoMode . overlayHeight = _oldVideoMode . overlayHeight ;
}
if ( _videoMode . fullscreen = = _oldVideoMode . fullscreen & &
2009-05-01 09:09:07 +00:00
_videoMode . aspectRatioCorrection = = _oldVideoMode . aspectRatioCorrection & &
2008-11-14 22:08:10 +00:00
_videoMode . mode = = _oldVideoMode . mode & &
2016-10-12 22:38:07 +01:00
# if SDL_VERSION_ATLEAST(2, 0, 0)
_videoMode . filtering = = _oldVideoMode . filtering & &
# endif
2008-11-14 22:08:10 +00:00
_videoMode . screenWidth = = _oldVideoMode . screenWidth & &
2010-07-26 06:58:33 +00:00
_videoMode . screenHeight = = _oldVideoMode . screenHeight ) {
2008-11-14 22:08:10 +00:00
// Our new video mode would now be exactly the same as the
// old one. Since we still can not assume SDL_SetVideoMode
// to be working fine, we need to invalidate the old video
// mode, so loadGFXMode would error out properly.
_oldVideoMode . setup = false ;
}
}
2005-02-22 01:29:27 +00:00
2009-08-21 18:16:37 +00:00
# ifdef USE_RGB_COLOR
2009-06-11 05:56:00 +00:00
if ( _transactionDetails . sizeChanged | | _transactionDetails . formatChanged ) {
2009-06-15 11:46:28 +00:00
# else
if ( _transactionDetails . sizeChanged ) {
2009-06-10 05:35:18 +00:00
# endif
2005-02-22 01:29:27 +00:00
unloadGFXMode ( ) ;
2008-11-14 22:08:10 +00:00
if ( ! loadGFXMode ( ) ) {
if ( _oldVideoMode . setup ) {
_transactionMode = kTransactionRollback ;
errors | = endGFXTransaction ( ) ;
}
} else {
setGraphicsModeIntern ( ) ;
clearOverlay ( ) ;
_videoMode . setup = true ;
2009-01-02 21:52:32 +00:00
// OSystem_SDL::pollEvent used to update the screen change count,
// but actually it gives problems when a video mode was changed
// but OSystem_SDL::pollEvent was not called. This for example
// caused a crash under certain circumstances when doing an RTL.
// To fix this issue we update the screen change count right here.
_screenChangeCount + + ;
2008-11-14 22:08:10 +00:00
}
} else if ( _transactionDetails . needHotswap ) {
setGraphicsModeIntern ( ) ;
if ( ! hotswapGFXMode ( ) ) {
if ( _oldVideoMode . setup ) {
_transactionMode = kTransactionRollback ;
errors | = endGFXTransaction ( ) ;
}
} else {
_videoMode . setup = true ;
2009-01-02 21:52:32 +00:00
// OSystem_SDL::pollEvent used to update the screen change count,
// but actually it gives problems when a video mode was changed
// but OSystem_SDL::pollEvent was not called. This for example
// caused a crash under certain circumstances when doing an RTL.
// To fix this issue we update the screen change count right here.
_screenChangeCount + + ;
2008-11-14 22:08:10 +00:00
if ( _transactionDetails . needUpdatescreen )
2005-02-22 01:29:27 +00:00
internUpdateScreen ( ) ;
2005-04-18 15:33:02 +00:00
}
2016-10-13 00:19:15 +01:00
# if SDL_VERSION_ATLEAST(2, 0, 0)
} else if ( _transactionDetails . needTextureUpdate ) {
setGraphicsModeIntern ( ) ;
recreateScreenTexture ( ) ;
internUpdateScreen ( ) ;
# endif
2008-12-19 17:54:45 +00:00
} else if ( _transactionDetails . needUpdatescreen ) {
setGraphicsModeIntern ( ) ;
internUpdateScreen ( ) ;
2010-01-25 01:39:44 +00:00
}
2005-02-22 01:29:27 +00:00
2004-11-23 21:30:38 +00:00
_transactionMode = kTransactionNone ;
2010-06-05 22:45:36 +00:00
return ( OSystem : : TransactionError ) errors ;
2004-11-23 21:30:38 +00:00
}
2009-08-21 18:16:37 +00:00
# ifdef USE_RGB_COLOR
2011-06-19 20:08:55 +02:00
Common : : List < Graphics : : PixelFormat > SurfaceSdlGraphicsManager : : getSupportedFormats ( ) const {
2010-07-12 23:18:44 +00:00
assert ( ! _supportedFormats . empty ( ) ) ;
return _supportedFormats ;
}
2017-08-27 16:31:57 -05:00
# if SDL_VERSION_ATLEAST(2, 0, 0)
2017-09-12 11:26:30 -05:00
static void maskToBitCount ( Uint32 mask , uint8 & numBits , uint8 & shift ) {
2017-08-27 16:31:57 -05:00
numBits = 0 ;
shift = 32 ;
for ( int i = 0 ; i < 32 ; + + i ) {
if ( mask & 1 ) {
if ( i < shift ) {
shift = i ;
}
+ + numBits ;
}
mask > > = 1 ;
}
}
# endif
2010-07-12 23:18:44 +00:00
2017-08-27 16:31:57 -05:00
void SurfaceSdlGraphicsManager : : detectSupportedFormats ( ) {
2010-07-12 23:18:44 +00:00
_supportedFormats . clear ( ) ;
2017-08-27 16:31:57 -05:00
Graphics : : PixelFormat format = Graphics : : PixelFormat : : createFormatCLUT8 ( ) ;
# if SDL_VERSION_ATLEAST(2, 0, 0)
{
SDL_Window * window = _window - > getSDLWindow ( ) ;
if ( window = = nullptr ) {
error ( " Could not find ScummVM window for retrieving default display mode " ) ;
}
const int displayIndex = SDL_GetWindowDisplayIndex ( window ) ;
if ( displayIndex < 0 ) {
error ( " Could not find ScummVM window display index " ) ;
}
SDL_DisplayMode defaultMode ;
if ( SDL_GetDesktopDisplayMode ( displayIndex , & defaultMode ) ! = 0 ) {
error ( " Could not get default system display mode " ) ;
}
int bpp ;
2017-09-12 11:26:30 -05:00
Uint32 rMask , gMask , bMask , aMask ;
2017-08-27 16:31:57 -05:00
if ( SDL_PixelFormatEnumToMasks ( defaultMode . format , & bpp , & rMask , & gMask , & bMask , & aMask ) ! = SDL_TRUE ) {
error ( " Could not convert system pixel format %s to masks " , SDL_GetPixelFormatName ( defaultMode . format ) ) ;
}
const uint8 bytesPerPixel = SDL_BYTESPERPIXEL ( defaultMode . format ) ;
uint8 rBits , rShift , gBits , gShift , bBits , bShift , aBits , aShift ;
maskToBitCount ( rMask , rBits , rShift ) ;
maskToBitCount ( gMask , gBits , gShift ) ;
maskToBitCount ( bMask , bBits , bShift ) ;
maskToBitCount ( aMask , aBits , aShift ) ;
format = Graphics : : PixelFormat ( bytesPerPixel , rBits , gBits , bBits , aBits , rShift , gShift , bShift , aShift ) ;
_supportedFormats . push_back ( format ) ;
}
# endif
2010-07-12 23:18:44 +00:00
// Some tables with standard formats that we always list
// as "supported". If frontend code tries to use one of
// these, we will perform the necessary format
// conversion in the background. Of course this incurs a
// performance hit, but on desktop ports this should not
// matter. We still push the currently active format to
// the front, so if frontend code just uses the first
// available format, it will get one that is "cheap" to
// use.
const Graphics : : PixelFormat RGBList [ ] = {
// RGBA8888, ARGB8888, RGB888
Graphics : : PixelFormat ( 4 , 8 , 8 , 8 , 8 , 24 , 16 , 8 , 0 ) ,
Graphics : : PixelFormat ( 4 , 8 , 8 , 8 , 8 , 16 , 8 , 0 , 24 ) ,
Graphics : : PixelFormat ( 3 , 8 , 8 , 8 , 0 , 16 , 8 , 0 , 0 ) ,
// RGB565, XRGB1555, RGB555, RGBA4444, ARGB4444
Graphics : : PixelFormat ( 2 , 5 , 6 , 5 , 0 , 11 , 5 , 0 , 0 ) ,
Graphics : : PixelFormat ( 2 , 5 , 5 , 5 , 1 , 10 , 5 , 0 , 15 ) ,
Graphics : : PixelFormat ( 2 , 5 , 5 , 5 , 0 , 10 , 5 , 0 , 0 ) ,
Graphics : : PixelFormat ( 2 , 4 , 4 , 4 , 4 , 12 , 8 , 4 , 0 ) ,
Graphics : : PixelFormat ( 2 , 4 , 4 , 4 , 4 , 8 , 4 , 0 , 12 )
} ;
const Graphics : : PixelFormat BGRList [ ] = {
// ABGR8888, BGRA8888, BGR888
Graphics : : PixelFormat ( 4 , 8 , 8 , 8 , 8 , 0 , 8 , 16 , 24 ) ,
Graphics : : PixelFormat ( 4 , 8 , 8 , 8 , 8 , 8 , 16 , 24 , 0 ) ,
Graphics : : PixelFormat ( 3 , 8 , 8 , 8 , 0 , 0 , 8 , 16 , 0 ) ,
// BGR565, XBGR1555, BGR555, ABGR4444, BGRA4444
Graphics : : PixelFormat ( 2 , 5 , 6 , 5 , 0 , 0 , 5 , 11 , 0 ) ,
Graphics : : PixelFormat ( 2 , 5 , 5 , 5 , 1 , 0 , 5 , 10 , 15 ) ,
Graphics : : PixelFormat ( 2 , 5 , 5 , 5 , 0 , 0 , 5 , 10 , 0 ) ,
Graphics : : PixelFormat ( 2 , 4 , 4 , 4 , 4 , 0 , 4 , 8 , 12 ) ,
Graphics : : PixelFormat ( 2 , 4 , 4 , 4 , 4 , 4 , 8 , 12 , 0 )
} ;
2009-07-10 19:55:06 +00:00
if ( _hwscreen ) {
// Get our currently set hardware format
2017-08-27 16:31:57 -05:00
Graphics : : PixelFormat hwFormat ( _hwscreen - > format - > BytesPerPixel ,
2010-01-25 01:39:44 +00:00
8 - _hwscreen - > format - > Rloss , 8 - _hwscreen - > format - > Gloss ,
8 - _hwscreen - > format - > Bloss , 8 - _hwscreen - > format - > Aloss ,
_hwscreen - > format - > Rshift , _hwscreen - > format - > Gshift ,
2009-07-10 19:55:06 +00:00
_hwscreen - > format - > Bshift , _hwscreen - > format - > Ashift ) ;
2012-05-31 10:30:29 +02:00
// Workaround to SDL not providing an accurate Aloss value on Mac OS X.
2009-07-10 19:55:06 +00:00
if ( _hwscreen - > format - > Amask = = 0 )
2017-08-27 16:31:57 -05:00
hwFormat . aLoss = 8 ;
2009-07-10 19:55:06 +00:00
2017-08-27 16:31:57 -05:00
_supportedFormats . push_back ( hwFormat ) ;
# if !SDL_VERSION_ATLEAST(2, 0, 0)
format = hwFormat ;
# endif
2009-07-10 19:55:06 +00:00
}
2010-07-12 23:18:44 +00:00
// TODO: prioritize matching alpha masks
2010-07-12 23:19:08 +00:00
int i ;
// Push some RGB formats
for ( i = 0 ; i < ARRAYSIZE ( RGBList ) ; i + + ) {
2010-07-12 23:18:44 +00:00
if ( _hwscreen & & ( RGBList [ i ] . bytesPerPixel > format . bytesPerPixel ) )
2009-07-10 06:46:50 +00:00
continue ;
2010-07-12 23:19:08 +00:00
if ( RGBList [ i ] ! = format )
2010-07-12 23:18:44 +00:00
_supportedFormats . push_back ( RGBList [ i ] ) ;
2010-07-12 23:19:08 +00:00
}
// Push some BGR formats
for ( i = 0 ; i < ARRAYSIZE ( BGRList ) ; i + + ) {
if ( _hwscreen & & ( BGRList [ i ] . bytesPerPixel > format . bytesPerPixel ) )
continue ;
if ( BGRList [ i ] ! = format )
2010-07-12 23:18:44 +00:00
_supportedFormats . push_back ( BGRList [ i ] ) ;
2009-07-10 06:46:50 +00:00
}
2010-07-12 23:19:08 +00:00
// Finally, we always supposed 8 bit palette graphics
2010-07-12 23:18:44 +00:00
_supportedFormats . push_back ( Graphics : : PixelFormat : : createFormatCLUT8 ( ) ) ;
2009-07-10 06:46:50 +00:00
}
# endif
2011-06-19 20:08:55 +02:00
bool SurfaceSdlGraphicsManager : : setGraphicsMode ( int mode ) {
2004-03-28 20:31:18 +00:00
Common : : StackLock lock ( _graphicsMutex ) ;
2004-02-29 00:49:40 +00:00
2008-11-14 22:08:10 +00:00
assert ( _transactionMode = = kTransactionActive ) ;
if ( _oldVideoMode . setup & & _oldVideoMode . mode = = mode )
return true ;
2004-02-29 00:49:40 +00:00
int newScaleFactor = 1 ;
2009-09-30 16:16:53 +00:00
switch ( mode ) {
2004-02-29 00:49:40 +00:00
case GFX_NORMAL :
newScaleFactor = 1 ;
break ;
2010-05-09 11:00:17 +00:00
# ifdef USE_SCALERS
2004-02-29 00:49:40 +00:00
case GFX_DOUBLESIZE :
case GFX_2XSAI :
case GFX_SUPER2XSAI :
case GFX_SUPEREAGLE :
case GFX_ADVMAME2X :
2017-10-01 01:04:24 -05:00
case GFX_TV2X :
case GFX_DOTMATRIX :
2010-05-09 11:00:17 +00:00
# ifdef USE_HQ_SCALERS
2004-02-29 00:49:40 +00:00
case GFX_HQ2X :
2017-10-01 01:04:24 -05:00
# endif
2004-02-29 00:49:40 +00:00
newScaleFactor = 2 ;
break ;
2017-10-01 01:04:24 -05:00
case GFX_TRIPLESIZE :
case GFX_ADVMAME3X :
# ifdef USE_HQ_SCALERS
2004-02-29 00:49:40 +00:00
case GFX_HQ3X :
2017-10-01 01:04:24 -05:00
# endif
2004-02-29 00:49:40 +00:00
newScaleFactor = 3 ;
break ;
2005-05-14 22:56:41 +00:00
# endif
2004-02-29 00:49:40 +00:00
default :
warning ( " unknown gfx mode %d " , mode ) ;
return false ;
}
2008-11-14 22:08:10 +00:00
if ( _oldVideoMode . setup & & _oldVideoMode . scaleFactor ! = newScaleFactor )
_transactionDetails . needHotswap = true ;
2005-03-20 16:16:09 +00:00
2008-11-14 22:08:10 +00:00
_transactionDetails . needUpdatescreen = true ;
2005-02-22 01:29:27 +00:00
2008-11-14 22:08:10 +00:00
_videoMode . mode = mode ;
_videoMode . scaleFactor = newScaleFactor ;
2005-02-22 01:29:27 +00:00
2008-11-14 22:08:10 +00:00
return true ;
}
2005-02-22 01:29:27 +00:00
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : setGraphicsModeIntern ( ) {
2008-11-14 22:08:10 +00:00
Common : : StackLock lock ( _graphicsMutex ) ;
ScalerProc * newScalerProc = 0 ;
2005-02-22 01:29:27 +00:00
2017-03-01 14:00:17 -06:00
updateShader ( ) ;
2008-11-14 22:08:10 +00:00
switch ( _videoMode . mode ) {
case GFX_NORMAL :
newScalerProc = Normal1x ;
break ;
2010-05-09 11:00:17 +00:00
# ifdef USE_SCALERS
2008-11-14 22:08:10 +00:00
case GFX_DOUBLESIZE :
newScalerProc = Normal2x ;
break ;
case GFX_TRIPLESIZE :
newScalerProc = Normal3x ;
break ;
2005-02-22 01:29:27 +00:00
2008-11-14 22:08:10 +00:00
case GFX_2XSAI :
newScalerProc = _2xSaI ;
break ;
case GFX_SUPER2XSAI :
newScalerProc = Super2xSaI ;
break ;
case GFX_SUPEREAGLE :
newScalerProc = SuperEagle ;
break ;
case GFX_ADVMAME2X :
newScalerProc = AdvMame2x ;
break ;
case GFX_ADVMAME3X :
newScalerProc = AdvMame3x ;
break ;
2010-05-09 11:00:17 +00:00
# ifdef USE_HQ_SCALERS
2008-11-14 22:08:10 +00:00
case GFX_HQ2X :
newScalerProc = HQ2x ;
break ;
case GFX_HQ3X :
newScalerProc = HQ3x ;
break ;
# endif
2010-05-10 17:25:12 +00:00
case GFX_TV2X :
newScalerProc = TV2x ;
break ;
case GFX_DOTMATRIX :
newScalerProc = DotMatrix ;
break ;
# endif // USE_SCALERS
2005-02-22 01:29:27 +00:00
2008-11-14 22:08:10 +00:00
default :
error ( " Unknown gfx mode %d " , _videoMode . mode ) ;
2004-03-13 14:19:15 +00:00
}
2004-02-29 00:49:40 +00:00
2008-11-14 22:08:10 +00:00
_scalerProc = newScalerProc ;
2009-01-01 15:06:43 +00:00
2008-11-14 22:08:10 +00:00
if ( _videoMode . mode ! = GFX_NORMAL ) {
2004-10-15 22:28:12 +00:00
for ( int i = 0 ; i < ARRAYSIZE ( s_gfxModeSwitchTable ) ; i + + ) {
2008-11-14 22:08:10 +00:00
if ( s_gfxModeSwitchTable [ i ] [ 1 ] = = _videoMode . mode | | s_gfxModeSwitchTable [ i ] [ 2 ] = = _videoMode . mode ) {
2004-10-15 22:28:12 +00:00
_scalerType = i ;
break ;
}
}
}
2008-11-14 22:08:10 +00:00
if ( ! _screen | | ! _hwscreen )
return ;
2004-03-13 14:19:15 +00:00
// Blit everything to the screen
_forceFull = true ;
2005-02-22 01:29:27 +00:00
2005-04-27 14:47:19 +00:00
// Even if the old and new scale factors are the same, we may have a
// different scaler for the cursor now.
blitCursor ( ) ;
2004-02-29 00:49:40 +00:00
}
2011-06-19 20:08:55 +02:00
int SurfaceSdlGraphicsManager : : getGraphicsMode ( ) const {
2011-06-19 18:49:02 +02:00
assert ( _transactionMode = = kTransactionNone ) ;
2008-11-14 22:08:10 +00:00
return _videoMode . mode ;
2004-02-29 00:49:40 +00:00
}
2009-06-23 02:02:51 +00:00
2017-03-01 14:00:17 -06:00
const OSystem : : GraphicsMode * SurfaceSdlGraphicsManager : : getSupportedShaders ( ) const {
return s_supportedShaders ;
}
2017-03-05 00:56:02 +01:00
int SurfaceSdlGraphicsManager : : getShader ( ) const {
2017-03-01 14:00:17 -06:00
return _currentShader ;
}
bool SurfaceSdlGraphicsManager : : setShader ( int id ) {
assert ( id > = 0 & & id < _numShaders ) ;
_currentShader = id ;
updateShader ( ) ;
return true ;
}
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : initSize ( uint w , uint h , const Graphics : : PixelFormat * format ) {
2009-06-10 05:35:18 +00:00
assert ( _transactionMode = = kTransactionActive ) ;
2009-08-21 18:16:37 +00:00
# ifdef USE_RGB_COLOR
2009-06-10 05:35:18 +00:00
//avoid redundant format changes
2009-06-30 07:30:57 +00:00
Graphics : : PixelFormat newFormat ;
2009-06-27 05:58:44 +00:00
if ( ! format )
2009-07-08 16:07:58 +00:00
newFormat = Graphics : : PixelFormat : : createFormatCLUT8 ( ) ;
2009-06-30 07:30:57 +00:00
else
newFormat = * format ;
2009-06-10 05:35:18 +00:00
2009-06-30 07:30:57 +00:00
assert ( newFormat . bytesPerPixel > 0 ) ;
2009-06-27 05:58:44 +00:00
2009-11-10 22:12:10 +00:00
if ( newFormat ! = _videoMode . format ) {
2009-06-30 07:30:57 +00:00
_videoMode . format = newFormat ;
2009-06-23 02:02:51 +00:00
_transactionDetails . formatChanged = true ;
2009-06-30 07:30:57 +00:00
_screenFormat = newFormat ;
2009-06-23 02:02:51 +00:00
}
2009-06-10 05:35:18 +00:00
# endif
2004-02-29 00:49:40 +00:00
2017-08-27 22:21:05 -05:00
# if !SDL_VERSION_ATLEAST(2, 0, 0)
// Avoid redundant res changes, only in SDL1. In SDL2, redundancies may not
// actually be redundant if ScummVM is switching between game engines and
// the screen dimensions are being reinitialized, since window resizing is
// supposed to reset when this happens
2008-11-14 22:08:10 +00:00
if ( ( int ) w = = _videoMode . screenWidth & & ( int ) h = = _videoMode . screenHeight )
2004-02-29 00:49:40 +00:00
return ;
2017-08-27 22:21:05 -05:00
# endif
2004-02-29 00:49:40 +00:00
2008-11-14 22:08:10 +00:00
_videoMode . screenWidth = w ;
_videoMode . screenHeight = h ;
2004-02-29 00:49:40 +00:00
2008-11-14 22:08:10 +00:00
_transactionDetails . sizeChanged = true ;
2004-02-29 00:49:40 +00:00
}
2011-06-19 20:08:55 +02:00
int SurfaceSdlGraphicsManager : : effectiveScreenHeight ( ) const {
2010-03-08 10:29:00 +00:00
return _videoMode . scaleFactor *
( _videoMode . aspectRatioCorrection
? real2Aspect ( _videoMode . screenHeight )
: _videoMode . screenHeight ) ;
}
2009-08-10 18:03:54 +00:00
static void fixupResolutionForAspectRatio ( AspectRatio desiredAspectRatio , int & width , int & height ) {
assert ( & width ! = & height ) ;
if ( desiredAspectRatio . isAuto ( ) )
return ;
2010-01-25 01:39:44 +00:00
2009-08-10 18:03:54 +00:00
int kw = desiredAspectRatio . kw ( ) ;
int kh = desiredAspectRatio . kh ( ) ;
const int w = width ;
const int h = height ;
2015-01-25 01:34:57 +01:00
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
2009-08-10 18:03:54 +00:00
SDL_Rect const * const * availableModes = SDL_ListModes ( NULL , SDL_FULLSCREEN | SDL_SWSURFACE ) ; //TODO : Maybe specify a pixel format
assert ( availableModes ) ;
while ( const SDL_Rect * mode = * availableModes + + ) {
2015-01-25 01:34:57 +01:00
# endif
2009-08-10 18:03:54 +00:00
if ( mode - > w < w )
continue ;
if ( mode - > h < h )
continue ;
if ( mode - > h * kw ! = mode - > w * kh )
continue ;
uint metric = mode - > w * mode - > h - w * h ;
if ( metric > bestMetric )
continue ;
bestMetric = metric ;
2015-01-25 01:34:57 +01:00
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)
2009-08-10 18:03:54 +00:00
}
2015-01-25 01:34:57 +01:00
# else
}
# endif
2009-08-10 18:03:54 +00:00
2015-01-25 01:34:57 +01:00
if ( ! bestW | | ! bestH ) {
2010-09-18 10:55:16 +00:00
warning ( " Unable to enforce the desired aspect ratio " ) ;
2009-08-10 18:03:54 +00:00
return ;
}
2015-01-25 01:34:57 +01:00
width = bestW ;
height = bestH ;
2009-08-10 18:03:54 +00:00
}
2011-06-19 20:08:55 +02:00
bool SurfaceSdlGraphicsManager : : loadGFXMode ( ) {
2004-02-29 00:49:40 +00:00
_forceFull = true ;
2010-10-20 13:00:58 +00:00
# if !defined(__MAEMO__) && !defined(DINGUX) && !defined(GPH_DEVICE) && !defined(LINUXMOTO) && !defined(OPENPANDORA)
2008-11-14 22:08:10 +00:00
_videoMode . overlayWidth = _videoMode . screenWidth * _videoMode . scaleFactor ;
_videoMode . overlayHeight = _videoMode . screenHeight * _videoMode . scaleFactor ;
2006-05-17 23:52:45 +00:00
2008-11-14 22:08:10 +00:00
if ( _videoMode . screenHeight ! = 200 & & _videoMode . screenHeight ! = 400 )
2009-05-01 09:09:07 +00:00
_videoMode . aspectRatioCorrection = false ;
2005-11-07 08:35:50 +00:00
2009-05-01 09:09:07 +00:00
if ( _videoMode . aspectRatioCorrection )
2008-11-14 22:08:10 +00:00
_videoMode . overlayHeight = real2Aspect ( _videoMode . overlayHeight ) ;
2006-05-17 23:52:45 +00:00
2009-08-10 18:03:54 +00:00
_videoMode . hardwareWidth = _videoMode . screenWidth * _videoMode . scaleFactor ;
_videoMode . hardwareHeight = effectiveScreenHeight ( ) ;
2011-10-03 12:24:25 +01:00
// On GPH devices ALL the _videoMode.hardware... are setup in GPHGraphicsManager::loadGFXMode()
# elif !defined(GPH_DEVICE)
2009-08-10 18:03:54 +00:00
_videoMode . hardwareWidth = _videoMode . overlayWidth ;
_videoMode . hardwareHeight = _videoMode . overlayHeight ;
2006-06-03 01:05:09 +00:00
# endif
2004-02-29 00:49:40 +00:00
//
// Create the surface that contains the 8 bit game data
//
2009-08-21 18:16:37 +00:00
# ifdef USE_RGB_COLOR
2010-01-25 01:39:44 +00:00
_screen = SDL_CreateRGBSurface ( SDL_SWSURFACE , _videoMode . screenWidth , _videoMode . screenHeight ,
_screenFormat . bytesPerPixel < < 3 ,
2009-06-10 05:35:18 +00:00
( ( 1 < < _screenFormat . rBits ( ) ) - 1 ) < < _screenFormat . rShift ,
( ( 1 < < _screenFormat . gBits ( ) ) - 1 ) < < _screenFormat . gShift ,
( ( 1 < < _screenFormat . bBits ( ) ) - 1 ) < < _screenFormat . bShift ,
( ( 1 < < _screenFormat . aBits ( ) ) - 1 ) < < _screenFormat . aShift ) ;
if ( _screen = = NULL )
error ( " allocating _screen failed " ) ;
2014-01-11 16:36:04 +01:00
// Avoid having SDL_SRCALPHA set even if we supplied an alpha-channel in the format.
SDL_SetAlpha ( _screen , 0 , 255 ) ;
2009-06-10 05:35:18 +00:00
# else
2008-11-14 22:08:10 +00:00
_screen = SDL_CreateRGBSurface ( SDL_SWSURFACE , _videoMode . screenWidth , _videoMode . screenHeight , 8 , 0 , 0 , 0 , 0 ) ;
2004-02-29 00:49:40 +00:00
if ( _screen = = NULL )
2004-03-13 14:19:15 +00:00
error ( " allocating _screen failed " ) ;
2009-06-10 05:35:18 +00:00
# endif
2004-02-29 00:49:40 +00:00
2011-07-02 22:14:13 +02:00
// SDL 1.2 palettes default to all black,
// SDL 1.3 palettes default to all white,
// Thus set our own default palette to all black.
// SDL_SetColors does nothing for non indexed surfaces.
2011-06-26 10:35:40 +02:00
SDL_SetColors ( _screen , _currentPalette , 0 , 256 ) ;
2004-02-29 00:49:40 +00:00
//
// Create the surface that contains the scaled graphics in 16 bit mode
//
2009-08-12 04:36:01 +00:00
if ( _videoMode . fullscreen ) {
2009-08-10 18:03:54 +00:00
fixupResolutionForAspectRatio ( _videoMode . desiredAspectRatio , _videoMode . hardwareWidth , _videoMode . hardwareHeight ) ;
}
2013-05-17 00:18:09 +03:00
2013-07-04 14:54:56 +03:00
# ifdef ENABLE_EVENTRECORDER
2013-05-17 00:18:09 +03:00
_displayDisabled = ConfMan . getBool ( " disable_display " ) ;
if ( _displayDisabled ) {
_hwscreen = g_eventRec . getSurface ( _videoMode . hardwareWidth , _videoMode . hardwareHeight ) ;
2013-07-14 19:01:47 +02:00
} else
2013-05-17 00:18:09 +03:00
# endif
2015-05-20 00:08:42 +02:00
{
2016-02-17 16:17:39 +01:00
# if defined(WIN32) && !SDL_VERSION_ATLEAST(2, 0, 0)
// Save the original bpp to be able to restore the video mode on
// unload. See _originalBitsPerPixel documentation.
2015-05-15 23:36:40 -04:00
if ( _originalBitsPerPixel = = 0 ) {
const SDL_VideoInfo * videoInfo = SDL_GetVideoInfo ( ) ;
_originalBitsPerPixel = videoInfo - > vfmt - > BitsPerPixel ;
}
2015-05-20 00:08:42 +02:00
# endif
2015-05-15 23:36:40 -04:00
2013-05-17 00:18:09 +03:00
_hwscreen = SDL_SetVideoMode ( _videoMode . hardwareWidth , _videoMode . hardwareHeight , 16 ,
_videoMode . fullscreen ? ( SDL_FULLSCREEN | SDL_SWSURFACE ) : SDL_SWSURFACE
) ;
}
2010-07-12 23:18:44 +00:00
# ifdef USE_RGB_COLOR
detectSupportedFormats ( ) ;
# endif
2004-02-29 00:49:40 +00:00
if ( _hwscreen = = NULL ) {
// DON'T use error(), as this tries to bring up the debug
// console, which WON'T WORK now that _hwscreen is hosed.
2008-11-14 22:08:10 +00:00
if ( ! _oldVideoMode . setup ) {
warning ( " SDL_SetVideoMode says we can't switch to that mode (%s) " , SDL_GetError ( ) ) ;
2010-06-05 22:45:36 +00:00
g_system - > quit ( ) ;
2008-11-14 22:08:10 +00:00
} else {
return false ;
}
2004-02-29 00:49:40 +00:00
}
//
// Create the surface used for the graphics in 16 bit before scaling, and also the overlay
//
// Need some extra bytes around when using 2xSaI
2008-11-14 22:08:10 +00:00
_tmpscreen = SDL_CreateRGBSurface ( SDL_SWSURFACE , _videoMode . screenWidth + 3 , _videoMode . screenHeight + 3 ,
2005-05-06 10:07:33 +00:00
16 ,
_hwscreen - > format - > Rmask ,
_hwscreen - > format - > Gmask ,
_hwscreen - > format - > Bmask ,
_hwscreen - > format - > Amask ) ;
2004-02-29 00:49:40 +00:00
if ( _tmpscreen = = NULL )
2004-03-13 14:19:15 +00:00
error ( " allocating _tmpscreen failed " ) ;
2005-03-09 23:07:32 +00:00
2008-11-14 22:08:10 +00:00
_overlayscreen = SDL_CreateRGBSurface ( SDL_SWSURFACE , _videoMode . overlayWidth , _videoMode . overlayHeight ,
2005-05-06 10:07:33 +00:00
16 ,
_hwscreen - > format - > Rmask ,
_hwscreen - > format - > Gmask ,
_hwscreen - > format - > Bmask ,
_hwscreen - > format - > Amask ) ;
2005-03-09 23:07:32 +00:00
if ( _overlayscreen = = NULL )
error ( " allocating _overlayscreen failed " ) ;
2008-11-03 13:44:59 +00:00
_overlayFormat . bytesPerPixel = _overlayscreen - > format - > BytesPerPixel ;
_overlayFormat . rLoss = _overlayscreen - > format - > Rloss ;
_overlayFormat . gLoss = _overlayscreen - > format - > Gloss ;
_overlayFormat . bLoss = _overlayscreen - > format - > Bloss ;
_overlayFormat . aLoss = _overlayscreen - > format - > Aloss ;
_overlayFormat . rShift = _overlayscreen - > format - > Rshift ;
_overlayFormat . gShift = _overlayscreen - > format - > Gshift ;
_overlayFormat . bShift = _overlayscreen - > format - > Bshift ;
_overlayFormat . aShift = _overlayscreen - > format - > Ashift ;
2008-11-14 22:08:10 +00:00
_tmpscreen2 = SDL_CreateRGBSurface ( SDL_SWSURFACE , _videoMode . overlayWidth + 3 , _videoMode . overlayHeight + 3 ,
2005-05-06 10:07:33 +00:00
16 ,
_hwscreen - > format - > Rmask ,
_hwscreen - > format - > Gmask ,
_hwscreen - > format - > Bmask ,
_hwscreen - > format - > Amask ) ;
2005-03-09 23:07:32 +00:00
if ( _tmpscreen2 = = NULL )
error ( " allocating _tmpscreen2 failed " ) ;
2015-12-13 20:20:23 +01:00
# if !SDL_VERSION_ATLEAST(2, 0, 0)
// For SDL2 the output resolution might differ from the requested
// resolution. We handle resetting the keyboard emulation properly inside
// our SDL_SetVideoMode wrapper for SDL2.
2016-10-18 19:24:51 +03:00
_eventSource - > resetKeyboardEmulation (
2010-06-16 04:34:44 +00:00
_videoMode . screenWidth * _videoMode . scaleFactor - 1 ,
effectiveScreenHeight ( ) - 1 ) ;
2015-12-13 20:20:23 +01:00
# endif
2008-11-14 22:08:10 +00:00
2009-01-22 04:35:10 +00:00
// Distinguish 555 and 565 mode
if ( _hwscreen - > format - > Rmask = = 0x7C00 )
InitScalers ( 555 ) ;
else
InitScalers ( 565 ) ;
2008-11-14 22:08:10 +00:00
return true ;
2004-02-29 00:49:40 +00:00
}
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : unloadGFXMode ( ) {
2004-02-29 00:49:40 +00:00
if ( _screen ) {
SDL_FreeSurface ( _screen ) ;
2005-07-30 21:11:48 +00:00
_screen = NULL ;
2004-02-29 00:49:40 +00:00
}
2015-01-25 01:34:57 +01:00
# if SDL_VERSION_ATLEAST(2, 0, 0)
deinitializeRenderer ( ) ;
# endif
2004-02-29 00:49:40 +00:00
if ( _hwscreen ) {
2013-07-04 15:41:01 +02:00
SDL_FreeSurface ( _hwscreen ) ;
2004-02-29 00:49:40 +00:00
_hwscreen = NULL ;
}
if ( _tmpscreen ) {
SDL_FreeSurface ( _tmpscreen ) ;
_tmpscreen = NULL ;
}
2004-03-13 14:19:15 +00:00
2005-03-09 23:07:32 +00:00
if ( _tmpscreen2 ) {
SDL_FreeSurface ( _tmpscreen2 ) ;
_tmpscreen2 = NULL ;
}
if ( _overlayscreen ) {
SDL_FreeSurface ( _overlayscreen ) ;
_overlayscreen = NULL ;
}
2004-03-13 14:19:15 +00:00
# ifdef USE_OSD
2016-06-04 18:51:03 +06:00
if ( _osdMessageSurface ) {
SDL_FreeSurface ( _osdMessageSurface ) ;
_osdMessageSurface = NULL ;
}
2016-09-13 20:33:42 +02:00
if ( _osdIconSurface ) {
SDL_FreeSurface ( _osdIconSurface ) ;
_osdIconSurface = NULL ;
}
2004-03-13 14:19:15 +00:00
# endif
2008-03-26 19:29:33 +00:00
DestroyScalers ( ) ;
2015-05-15 23:36:40 -04:00
2016-02-17 16:17:39 +01:00
# if defined(WIN32) && !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. See _originalBitsPerPixel documentation.
2015-05-15 23:36:40 -04:00
if ( _originalBitsPerPixel ! = 0 )
SDL_SetVideoMode ( _videoMode . screenWidth , _videoMode . screenHeight , _originalBitsPerPixel , _videoMode . fullscreen ? ( SDL_FULLSCREEN | SDL_SWSURFACE ) : SDL_SWSURFACE ) ;
2015-05-20 00:08:42 +02:00
# endif
2004-02-29 00:49:40 +00:00
}
2011-06-19 20:08:55 +02:00
bool SurfaceSdlGraphicsManager : : hotswapGFXMode ( ) {
2004-02-29 00:49:40 +00:00
if ( ! _screen )
2008-11-14 22:08:10 +00:00
return false ;
2004-02-29 00:49:40 +00:00
2005-03-09 23:07:32 +00:00
// Keep around the old _screen & _overlayscreen so we can restore the screen data
2004-02-29 00:49:40 +00:00
// after the mode switch.
SDL_Surface * old_screen = _screen ;
2008-11-14 22:08:10 +00:00
_screen = NULL ;
2009-06-03 23:36:23 +00:00
SDL_Surface * old_overlayscreen = _overlayscreen ;
2008-11-14 22:08:10 +00:00
_overlayscreen = NULL ;
2004-02-29 00:49:40 +00:00
// Release the HW screen surface
2017-03-01 14:00:17 -06:00
if ( _hwscreen ) {
SDL_FreeSurface ( _hwscreen ) ;
_hwscreen = NULL ;
}
if ( _tmpscreen ) {
SDL_FreeSurface ( _tmpscreen ) ;
_tmpscreen = NULL ;
}
if ( _tmpscreen2 ) {
SDL_FreeSurface ( _tmpscreen2 ) ;
_tmpscreen2 = NULL ;
}
2005-03-09 23:07:32 +00:00
2004-02-29 00:49:40 +00:00
// Setup the new GFX mode
2008-11-14 22:08:10 +00:00
if ( ! loadGFXMode ( ) ) {
unloadGFXMode ( ) ;
_screen = old_screen ;
_overlayscreen = old_overlayscreen ;
return false ;
}
2004-02-29 00:49:40 +00:00
// reset palette
SDL_SetColors ( _screen , _currentPalette , 0 , 256 ) ;
// Restore old screen content
SDL_BlitSurface ( old_screen , NULL , _screen , NULL ) ;
2005-03-09 23:07:32 +00:00
SDL_BlitSurface ( old_overlayscreen , NULL , _overlayscreen , NULL ) ;
2004-02-29 00:49:40 +00:00
// Free the old surfaces
SDL_FreeSurface ( old_screen ) ;
2005-03-09 23:07:32 +00:00
SDL_FreeSurface ( old_overlayscreen ) ;
2004-02-29 00:49:40 +00:00
2005-02-17 23:01:00 +00:00
// Update cursor to new scale
blitCursor ( ) ;
2004-02-29 00:49:40 +00:00
// Blit everything to the screen
internUpdateScreen ( ) ;
2005-07-30 21:11:48 +00:00
2008-11-14 22:08:10 +00:00
return true ;
2004-02-29 00:49:40 +00:00
}
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : updateScreen ( ) {
2011-06-19 18:49:02 +02:00
assert ( _transactionMode = = kTransactionNone ) ;
2004-11-23 21:30:38 +00:00
2004-03-28 20:31:18 +00:00
Common : : StackLock lock ( _graphicsMutex ) ; // Lock the mutex until this function ends
2004-02-29 00:49:40 +00:00
internUpdateScreen ( ) ;
}
2017-03-01 14:00:17 -06:00
void SurfaceSdlGraphicsManager : : updateShader ( ) {
// shader init code goes here
// currently only used on Vita port
// the user-selected shaderID should be obtained via ConfMan.getInt("shader")
// and the corresponding shader should then be activated here
// this way the user can combine any software scaling (scalers)
// with any hardware shading (shaders). The shaders could provide
// scanline masks, overlays, but could also serve for
// hardware-based up-scaling (sharp-bilinear-simple, etc.)
}
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : internUpdateScreen ( ) {
2005-03-09 23:07:32 +00:00
SDL_Surface * srcSurf , * origSurf ;
int height , width ;
ScalerProc * scalerProc ;
2006-05-17 23:52:45 +00:00
int scale1 ;
2005-03-09 23:07:32 +00:00
2010-07-15 04:01:41 +00:00
// definitions not available for non-DEBUG here. (needed this to compile in SYMBIAN32 & linux?)
2012-03-17 22:02:16 +01:00
# if defined(DEBUG) && !defined(WIN32) && !defined(_WIN32_WCE)
2004-02-29 00:49:40 +00:00
assert ( _hwscreen ! = NULL ) ;
2005-06-21 20:39:09 +00:00
assert ( _hwscreen - > map - > sw_data ! = NULL ) ;
# endif
2004-02-29 00:49:40 +00:00
// If the shake position changed, fill the dirty area with blackness
2010-09-06 17:28:17 +00:00
if ( _currentShakePos ! = _newShakePos | |
2010-07-23 16:38:31 +00:00
( _mouseNeedsRedraw & & _mouseBackup . y < = _currentShakePos ) ) {
2013-01-09 07:00:12 +01:00
SDL_Rect blackrect = { 0 , 0 , ( Uint16 ) ( _videoMode . screenWidth * _videoMode . scaleFactor ) , ( Uint16 ) ( _newShakePos * _videoMode . scaleFactor ) } ;
2004-02-29 00:49:40 +00:00
2009-05-01 09:09:07 +00:00
if ( _videoMode . aspectRatioCorrection & & ! _overlayVisible )
2004-02-29 00:49:40 +00:00
blackrect . h = real2Aspect ( blackrect . h - 1 ) + 1 ;
SDL_FillRect ( _hwscreen , & blackrect , 0 ) ;
_currentShakePos = _newShakePos ;
_forceFull = true ;
}
// Check whether the palette was changed in the meantime and update the
2005-07-30 21:11:48 +00:00
// screen surface accordingly.
2006-07-23 06:50:49 +00:00
if ( _screen & & _paletteDirtyEnd ! = 0 ) {
2005-07-30 21:11:48 +00:00
SDL_SetColors ( _screen , _currentPalette + _paletteDirtyStart ,
2004-02-29 00:49:40 +00:00
_paletteDirtyStart ,
_paletteDirtyEnd - _paletteDirtyStart ) ;
2005-07-30 21:11:48 +00:00
2004-02-29 00:49:40 +00:00
_paletteDirtyEnd = 0 ;
_forceFull = true ;
}
2005-03-09 23:07:32 +00:00
if ( ! _overlayVisible ) {
origSurf = _screen ;
srcSurf = _tmpscreen ;
2008-11-14 22:08:10 +00:00
width = _videoMode . screenWidth ;
height = _videoMode . screenHeight ;
2005-03-09 23:07:32 +00:00
scalerProc = _scalerProc ;
2008-11-14 22:08:10 +00:00
scale1 = _videoMode . scaleFactor ;
2005-03-09 23:07:32 +00:00
} else {
origSurf = _overlayscreen ;
srcSurf = _tmpscreen2 ;
2008-11-14 22:08:10 +00:00
width = _videoMode . overlayWidth ;
height = _videoMode . overlayHeight ;
2006-05-17 23:52:45 +00:00
scalerProc = Normal1x ;
2005-03-09 23:07:32 +00:00
2006-05-17 23:52:45 +00:00
scale1 = 1 ;
2005-03-09 23:07:32 +00:00
}
2005-02-17 23:01:00 +00:00
2009-02-24 21:43:07 +00:00
// Add the area covered by the mouse cursor to the list of dirty rects if
// we have to redraw the mouse.
if ( _mouseNeedsRedraw )
undrawMouse ( ) ;
2016-09-13 20:33:42 +02:00
# ifdef USE_OSD
updateOSD ( ) ;
# endif
2004-02-29 00:49:40 +00:00
// Force a full redraw if requested
if ( _forceFull ) {
2004-12-01 21:16:55 +00:00
_numDirtyRects = 1 ;
_dirtyRectList [ 0 ] . x = 0 ;
_dirtyRectList [ 0 ] . y = 0 ;
2005-03-09 23:07:32 +00:00
_dirtyRectList [ 0 ] . w = width ;
_dirtyRectList [ 0 ] . h = height ;
2009-02-24 21:43:07 +00:00
}
2004-02-29 00:49:40 +00:00
// Only draw anything if necessary
2009-02-26 02:04:30 +00:00
if ( _numDirtyRects > 0 | | _mouseNeedsRedraw ) {
2005-07-30 21:11:48 +00:00
SDL_Rect * r ;
2004-02-29 00:49:40 +00:00
SDL_Rect dst ;
uint32 srcPitch , dstPitch ;
2004-12-01 21:16:55 +00:00
SDL_Rect * lastRect = _dirtyRectList + _numDirtyRects ;
2004-02-29 00:49:40 +00:00
2007-08-11 08:44:43 +00:00
for ( r = _dirtyRectList ; r ! = lastRect ; + + r ) {
dst = * r ;
2009-08-02 21:18:25 +00:00
dst . x + + ; // Shift rect by one since 2xSai needs to access the data around
2007-08-11 08:44:43 +00:00
dst . y + + ; // any pixel to scale it, and we want to avoid mem access crashes.
2005-07-30 21:11:48 +00:00
2007-08-11 08:44:43 +00:00
if ( SDL_BlitSurface ( origSurf , r , srcSurf , & dst ) ! = 0 )
error ( " SDL_BlitSurface failed: %s " , SDL_GetError ( ) ) ;
}
2004-02-29 00:49:40 +00:00
2007-08-11 08:44:43 +00:00
SDL_LockSurface ( srcSurf ) ;
SDL_LockSurface ( _hwscreen ) ;
2004-02-29 00:49:40 +00:00
2007-08-11 08:44:43 +00:00
srcPitch = srcSurf - > pitch ;
dstPitch = _hwscreen - > pitch ;
2004-02-29 00:49:40 +00:00
2007-08-11 08:44:43 +00:00
for ( r = _dirtyRectList ; r ! = lastRect ; + + r ) {
register int dst_y = r - > y + _currentShakePos ;
register int dst_h = 0 ;
2014-01-07 01:47:43 +01:00
# ifdef USE_SCALERS
2007-08-11 08:44:43 +00:00
register int orig_dst_y = 0 ;
2014-01-07 01:47:43 +01:00
# endif
2007-08-11 08:44:43 +00:00
register int rx1 = r - > x * scale1 ;
2004-02-29 00:49:40 +00:00
2007-08-11 08:44:43 +00:00
if ( dst_y < height ) {
dst_h = r - > h ;
if ( dst_h > height - dst_y )
dst_h = height - dst_y ;
2004-02-29 00:49:40 +00:00
2014-01-07 01:47:43 +01:00
# ifdef USE_SCALERS
2007-08-11 08:44:43 +00:00
orig_dst_y = dst_y ;
2014-01-07 01:47:43 +01:00
# endif
2007-08-11 08:44:43 +00:00
dst_y = dst_y * scale1 ;
2004-02-29 00:49:40 +00:00
2009-05-01 09:09:07 +00:00
if ( _videoMode . aspectRatioCorrection & & ! _overlayVisible )
2007-08-11 08:44:43 +00:00
dst_y = real2Aspect ( dst_y ) ;
2005-03-09 23:07:32 +00:00
2007-08-11 08:44:43 +00:00
assert ( scalerProc ! = NULL ) ;
scalerProc ( ( byte * ) srcSurf - > pixels + ( r - > x * 2 + 2 ) + ( r - > y + 1 ) * srcPitch , srcPitch ,
2010-07-26 06:58:33 +00:00
( byte * ) _hwscreen - > pixels + rx1 * 2 + dst_y * dstPitch , dstPitch , r - > w , dst_h ) ;
2007-08-11 08:44:43 +00:00
}
2005-07-30 21:11:48 +00:00
2007-08-11 08:44:43 +00:00
r - > x = rx1 ;
r - > y = dst_y ;
r - > w = r - > w * scale1 ;
r - > h = dst_h * scale1 ;
2004-02-29 00:49:40 +00:00
2010-05-10 17:25:12 +00:00
# ifdef USE_SCALERS
2009-05-01 09:09:07 +00:00
if ( _videoMode . aspectRatioCorrection & & orig_dst_y < height & & ! _overlayVisible )
2007-08-11 08:44:43 +00:00
r - > h = stretch200To240 ( ( uint8 * ) _hwscreen - > pixels , dstPitch , r - > w , r - > h , r - > x , r - > y , orig_dst_y * scale1 ) ;
2005-06-21 20:39:09 +00:00
# endif
2004-02-29 00:49:40 +00:00
}
2007-08-11 08:44:43 +00:00
SDL_UnlockSurface ( srcSurf ) ;
SDL_UnlockSurface ( _hwscreen ) ;
2004-02-29 00:49:40 +00:00
// Readjust the dirty rect list in case we are doing a full update.
// This is necessary if shaking is active.
if ( _forceFull ) {
2004-12-01 21:16:55 +00:00
_dirtyRectList [ 0 ] . y = 0 ;
_dirtyRectList [ 0 ] . h = effectiveScreenHeight ( ) ;
2004-02-29 00:49:40 +00:00
}
2005-02-17 23:01:00 +00:00
drawMouse ( ) ;
2004-03-13 14:19:15 +00:00
# ifdef USE_OSD
2016-09-13 20:33:42 +02:00
drawOSD ( ) ;
2004-03-13 14:19:15 +00:00
# endif
2011-02-24 01:11:16 +01:00
# ifdef USE_SDL_DEBUG_FOCUSRECT
// We draw the focus rectangle on top of everything, to assure it's easily visible.
// Of course when the overlay is visible we do not show it, since it is only for game
// specific focus.
if ( _enableFocusRect & & ! _overlayVisible ) {
int y = _focusRect . top + _currentShakePos ;
int h = 0 ;
int x = _focusRect . left * scale1 ;
int w = _focusRect . width ( ) * scale1 ;
if ( y < height ) {
h = _focusRect . height ( ) ;
if ( h > height - y )
h = height - y ;
y * = scale1 ;
if ( _videoMode . aspectRatioCorrection & & ! _overlayVisible )
y = real2Aspect ( y ) ;
if ( h > 0 & & w > 0 ) {
SDL_LockSurface ( _hwscreen ) ;
// Use white as color for now.
Uint32 rectColor = SDL_MapRGB ( _hwscreen - > format , 0xFF , 0xFF , 0xFF ) ;
// First draw the top and bottom lines
// then draw the left and right lines
if ( _hwscreen - > format - > BytesPerPixel = = 2 ) {
uint16 * top = ( uint16 * ) ( ( byte * ) _hwscreen - > pixels + y * _hwscreen - > pitch + x * 2 ) ;
uint16 * bottom = ( uint16 * ) ( ( byte * ) _hwscreen - > pixels + ( y + h ) * _hwscreen - > pitch + x * 2 ) ;
byte * left = ( ( byte * ) _hwscreen - > pixels + y * _hwscreen - > pitch + x * 2 ) ;
byte * right = ( ( byte * ) _hwscreen - > pixels + y * _hwscreen - > pitch + ( x + w - 1 ) * 2 ) ;
while ( w - - ) {
* top + + = rectColor ;
* bottom + + = rectColor ;
}
while ( h - - ) {
* ( uint16 * ) left = rectColor ;
* ( uint16 * ) right = rectColor ;
left + = _hwscreen - > pitch ;
right + = _hwscreen - > pitch ;
}
} else if ( _hwscreen - > format - > BytesPerPixel = = 4 ) {
uint32 * top = ( uint32 * ) ( ( byte * ) _hwscreen - > pixels + y * _hwscreen - > pitch + x * 4 ) ;
uint32 * bottom = ( uint32 * ) ( ( byte * ) _hwscreen - > pixels + ( y + h ) * _hwscreen - > pitch + x * 4 ) ;
byte * left = ( ( byte * ) _hwscreen - > pixels + y * _hwscreen - > pitch + x * 4 ) ;
byte * right = ( ( byte * ) _hwscreen - > pixels + y * _hwscreen - > pitch + ( x + w - 1 ) * 4 ) ;
while ( w - - ) {
* top + + = rectColor ;
* bottom + + = rectColor ;
}
while ( h - - ) {
* ( uint32 * ) left = rectColor ;
* ( uint32 * ) right = rectColor ;
left + = _hwscreen - > pitch ;
right + = _hwscreen - > pitch ;
}
}
SDL_UnlockSurface ( _hwscreen ) ;
}
}
}
# endif
2004-02-29 00:49:40 +00:00
// Finally, blit all our changes to the screen
2013-05-17 00:18:09 +03:00
if ( ! _displayDisabled ) {
SDL_UpdateRects ( _hwscreen , _numDirtyRects , _dirtyRectList ) ;
}
2004-02-29 00:49:40 +00:00
}
2004-12-01 21:16:55 +00:00
_numDirtyRects = 0 ;
2004-02-29 00:49:40 +00:00
_forceFull = false ;
2009-02-26 11:32:02 +00:00
_mouseNeedsRedraw = false ;
2004-02-29 00:49:40 +00:00
}
2011-06-19 20:08:55 +02:00
bool SurfaceSdlGraphicsManager : : saveScreenshot ( const char * filename ) {
2004-02-29 00:49:40 +00:00
assert ( _hwscreen ! = NULL ) ;
2017-05-12 12:44:44 -05:00
Common : : StackLock lock ( _graphicsMutex ) ;
# ifdef USE_PNG
Common : : DumpFile out ;
if ( ! out . open ( filename ) ) {
return false ;
}
# if SDL_VERSION_ATLEAST(2, 0, 0)
SDL_Surface * rgbScreen = SDL_ConvertSurfaceFormat ( _hwscreen , SDL_PIXELFORMAT_RGB24 , 0 ) ;
# else
// This block of code was taken mostly as-is from SDL 1.2's SDL_SaveBMP_RW
SDL_Surface * rgbScreen = SDL_CreateRGBSurface ( SDL_SWSURFACE ,
_hwscreen - > w ,
_hwscreen - > h ,
24 ,
# ifdef SCUMM_LITTLE_ENDIAN
0x0000FF , 0x00FF00 , 0xFF0000 ,
# else
0xFF0000 , 0x00FF00 , 0x0000FF ,
# endif
0 ) ;
if ( rgbScreen = = nullptr ) {
warning ( " Could not create RGB24 surface " ) ;
return false ;
}
SDL_Rect bounds ;
bounds . x = bounds . y = 0 ;
bounds . w = _hwscreen - > w ;
bounds . h = _hwscreen - > h ;
if ( SDL_LowerBlit ( _hwscreen , & bounds , rgbScreen , & bounds ) < 0 ) {
SDL_FreeSurface ( rgbScreen ) ;
rgbScreen = nullptr ;
}
# endif
if ( rgbScreen = = nullptr ) {
warning ( " Could not convert hardware surface to RGB24 " ) ;
return false ;
}
int result = SDL_LockSurface ( rgbScreen ) ;
if ( result < 0 ) {
warning ( " Could not lock RGB surface " ) ;
SDL_FreeSurface ( rgbScreen ) ;
return false ;
}
const Graphics : : PixelFormat format ( 3 , 8 , 8 , 8 , 0 , 16 , 8 , 0 , 0 ) ;
Graphics : : Surface data ;
data . init ( rgbScreen - > w , rgbScreen - > h , rgbScreen - > pitch , rgbScreen - > pixels , format ) ;
const bool success = Image : : writePNG ( out , data ) ;
SDL_UnlockSurface ( rgbScreen ) ;
SDL_FreeSurface ( rgbScreen ) ;
return success ;
# else
2004-12-01 21:16:55 +00:00
return SDL_SaveBMP ( _hwscreen , filename ) = = 0 ;
2017-05-12 12:44:44 -05:00
# endif
2004-02-29 00:49:40 +00:00
}
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : setFullscreenMode ( bool enable ) {
2004-03-28 20:31:18 +00:00
Common : : StackLock lock ( _graphicsMutex ) ;
2009-01-01 15:06:43 +00:00
2008-11-14 22:08:10 +00:00
if ( _oldVideoMode . setup & & _oldVideoMode . fullscreen = = enable )
2008-09-22 17:33:30 +00:00
return ;
2004-03-01 01:41:22 +00:00
2008-11-14 22:08:10 +00:00
if ( _transactionMode = = kTransactionActive ) {
_videoMode . fullscreen = enable ;
2008-09-22 17:33:30 +00:00
_transactionDetails . needHotswap = true ;
2004-02-29 00:49:40 +00:00
}
}
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : setAspectRatioCorrection ( bool enable ) {
2008-11-14 22:08:10 +00:00
Common : : StackLock lock ( _graphicsMutex ) ;
2005-02-22 01:29:27 +00:00
2009-05-01 09:09:07 +00:00
if ( _oldVideoMode . setup & & _oldVideoMode . aspectRatioCorrection = = enable )
2008-11-14 22:08:10 +00:00
return ;
2005-07-30 21:11:48 +00:00
2008-11-14 22:08:10 +00:00
if ( _transactionMode = = kTransactionActive ) {
2009-05-01 09:09:07 +00:00
_videoMode . aspectRatioCorrection = enable ;
2008-11-14 22:08:10 +00:00
_transactionDetails . needHotswap = true ;
2004-11-23 21:30:38 +00:00
}
}
2016-10-12 22:38:07 +01:00
# if SDL_VERSION_ATLEAST(2, 0, 0)
void SurfaceSdlGraphicsManager : : setFilteringMode ( bool enable ) {
Common : : StackLock lock ( _graphicsMutex ) ;
if ( _oldVideoMode . setup & & _oldVideoMode . filtering = = enable )
return ;
if ( _transactionMode = = kTransactionActive ) {
_videoMode . filtering = enable ;
2016-10-13 00:19:15 +01:00
_transactionDetails . needTextureUpdate = true ;
2016-10-12 22:38:07 +01:00
}
}
# endif
2012-06-16 02:18:01 +02:00
void SurfaceSdlGraphicsManager : : copyRectToScreen ( const void * buf , int pitch , int x , int y , int w , int h ) {
2011-06-19 18:49:02 +02:00
assert ( _transactionMode = = kTransactionNone ) ;
2012-06-16 02:18:01 +02:00
assert ( buf ) ;
2004-11-23 21:30:38 +00:00
2006-07-23 06:50:49 +00:00
if ( _screen = = NULL ) {
2011-06-19 20:08:55 +02:00
warning ( " SurfaceSdlGraphicsManager::copyRectToScreen: _screen == NULL " ) ;
2004-02-29 00:49:40 +00:00
return ;
2006-07-23 06:50:49 +00:00
}
2004-02-29 00:49:40 +00:00
2004-03-28 20:31:18 +00:00
Common : : StackLock lock ( _graphicsMutex ) ; // Lock the mutex until this function ends
2005-07-30 21:11:48 +00:00
2008-11-14 22:08:10 +00:00
assert ( x > = 0 & & x < _videoMode . screenWidth ) ;
assert ( y > = 0 & & y < _videoMode . screenHeight ) ;
assert ( h > 0 & & y + h < = _videoMode . screenHeight ) ;
assert ( w > 0 & & x + w < = _videoMode . screenWidth ) ;
2005-11-08 22:23:09 +00:00
2010-06-02 00:52:57 +00:00
addDirtyRect ( x , y , w , h ) ;
2004-02-29 00:49:40 +00:00
// Try to lock the screen surface
if ( SDL_LockSurface ( _screen ) = = - 1 )
error ( " SDL_LockSurface failed: %s " , SDL_GetError ( ) ) ;
2009-08-21 18:16:37 +00:00
# ifdef USE_RGB_COLOR
2011-02-24 04:24:58 +01:00
byte * dst = ( byte * ) _screen - > pixels + y * _screen - > pitch + x * _screenFormat . bytesPerPixel ;
if ( _videoMode . screenWidth = = w & & pitch = = _screen - > pitch ) {
2012-06-16 02:18:01 +02:00
memcpy ( dst , buf , h * pitch ) ;
2009-06-03 23:36:23 +00:00
} else {
2012-06-16 02:18:01 +02:00
const byte * src = ( const byte * ) buf ;
2009-06-03 23:36:23 +00:00
do {
2009-06-10 05:35:18 +00:00
memcpy ( dst , src , w * _screenFormat . bytesPerPixel ) ;
2009-06-03 23:36:23 +00:00
src + = pitch ;
2011-02-24 04:24:58 +01:00
dst + = _screen - > pitch ;
2009-06-03 23:36:23 +00:00
} while ( - - h ) ;
}
# else
2011-02-24 04:24:58 +01:00
byte * dst = ( byte * ) _screen - > pixels + y * _screen - > pitch + x ;
if ( _screen - > pitch = = pitch & & pitch = = w ) {
2012-06-16 02:18:01 +02:00
memcpy ( dst , buf , h * w ) ;
2004-02-29 00:49:40 +00:00
} else {
2012-06-16 02:18:01 +02:00
const byte * src = ( const byte * ) buf ;
2004-02-29 00:49:40 +00:00
do {
memcpy ( dst , src , w ) ;
src + = pitch ;
2011-02-24 04:24:58 +01:00
dst + = _screen - > pitch ;
2004-02-29 00:49:40 +00:00
} while ( - - h ) ;
}
2009-06-10 05:35:18 +00:00
# endif
2004-02-29 00:49:40 +00:00
// Unlock the screen surface
SDL_UnlockSurface ( _screen ) ;
}
2011-06-19 20:08:55 +02:00
Graphics : : Surface * SurfaceSdlGraphicsManager : : lockScreen ( ) {
2011-06-19 18:49:02 +02:00
assert ( _transactionMode = = kTransactionNone ) ;
2005-07-30 21:11:48 +00:00
2007-06-19 22:39:59 +00:00
// Lock the graphics mutex
2010-06-05 22:45:36 +00:00
g_system - > lockMutex ( _graphicsMutex ) ;
2005-07-30 21:11:48 +00:00
2007-06-19 22:39:59 +00:00
// paranoia check
assert ( ! _screenIsLocked ) ;
_screenIsLocked = true ;
2005-07-30 21:11:48 +00:00
2005-05-08 21:39:05 +00:00
// Try to lock the screen surface
if ( SDL_LockSurface ( _screen ) = = - 1 )
error ( " SDL_LockSurface failed: %s " , SDL_GetError ( ) ) ;
2005-07-30 21:11:48 +00:00
2013-08-03 04:07:44 +02:00
_framebuffer . init ( _screen - > w , _screen - > h , _screen - > pitch , _screen - > pixels ,
2009-08-21 18:16:37 +00:00
# ifdef USE_RGB_COLOR
2013-08-03 04:07:44 +02:00
_screenFormat
2009-06-10 05:35:18 +00:00
# else
2013-08-03 04:07:44 +02:00
Graphics : : PixelFormat : : createFormatCLUT8 ( )
2009-06-03 23:36:23 +00:00
# endif
2013-08-03 04:07:44 +02:00
) ;
2007-06-19 22:39:59 +00:00
return & _framebuffer ;
}
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : unlockScreen ( ) {
2011-06-19 18:49:02 +02:00
assert ( _transactionMode = = kTransactionNone ) ;
2007-06-19 22:39:59 +00:00
// paranoia check
assert ( _screenIsLocked ) ;
_screenIsLocked = false ;
2005-07-30 21:11:48 +00:00
2005-05-08 21:39:05 +00:00
// Unlock the screen surface
SDL_UnlockSurface ( _screen ) ;
2005-07-30 21:11:48 +00:00
2007-06-19 22:39:59 +00:00
// Trigger a full screen update
_forceFull = true ;
// Finally unlock the graphics mutex
2010-06-05 22:45:36 +00:00
g_system - > unlockMutex ( _graphicsMutex ) ;
2005-05-08 21:39:05 +00:00
}
2004-02-29 00:49:40 +00:00
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : fillScreen ( uint32 col ) {
2010-06-08 23:44:05 +00:00
Graphics : : Surface * screen = lockScreen ( ) ;
2013-08-03 02:45:32 +02:00
if ( screen & & screen - > getPixels ( ) )
memset ( screen - > getPixels ( ) , col , screen - > h * screen - > pitch ) ;
2010-06-08 23:44:05 +00:00
unlockScreen ( ) ;
}
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : addDirtyRect ( int x , int y , int w , int h , bool realCoordinates ) {
2004-02-29 00:49:40 +00:00
if ( _forceFull )
return ;
2005-05-01 17:39:38 +00:00
if ( _numDirtyRects = = NUM_DIRTY_RECT ) {
_forceFull = true ;
return ;
}
2005-03-09 23:07:32 +00:00
int height , width ;
2006-05-27 12:55:28 +00:00
if ( ! _overlayVisible & & ! realCoordinates ) {
2008-11-14 22:08:10 +00:00
width = _videoMode . screenWidth ;
height = _videoMode . screenHeight ;
2005-03-09 23:07:32 +00:00
} else {
2008-11-14 22:08:10 +00:00
width = _videoMode . overlayWidth ;
height = _videoMode . overlayHeight ;
2005-03-09 23:07:32 +00:00
}
2005-02-17 23:01:00 +00:00
2005-05-01 17:39:38 +00:00
// Extend the dirty region by 1 pixel for scalers
// that "smear" the screen, e.g. 2xSAI
2007-08-11 08:44:43 +00:00
if ( ! realCoordinates ) {
2005-05-01 17:39:38 +00:00
x - - ;
y - - ;
w + = 2 ;
h + = 2 ;
}
2004-02-29 00:49:40 +00:00
2005-05-01 17:39:38 +00:00
// clip
if ( x < 0 ) {
w + = x ;
x = 0 ;
}
2004-02-29 00:49:40 +00:00
2005-05-01 17:39:38 +00:00
if ( y < 0 ) {
h + = y ;
y = 0 ;
}
2004-02-29 00:49:40 +00:00
2005-05-01 17:39:38 +00:00
if ( w > width - x ) {
w = width - x ;
}
2004-02-29 00:49:40 +00:00
2005-05-01 17:39:38 +00:00
if ( h > height - y ) {
h = height - y ;
}
2004-02-29 00:49:40 +00:00
2010-05-10 17:25:12 +00:00
# ifdef USE_SCALERS
2009-05-01 09:09:07 +00:00
if ( _videoMode . aspectRatioCorrection & & ! _overlayVisible & & ! realCoordinates ) {
2005-05-01 17:39:38 +00:00
makeRectStretchable ( x , y , w , h ) ;
2004-02-29 00:49:40 +00:00
}
2005-06-21 20:39:09 +00:00
# endif
2005-07-30 21:11:48 +00:00
2006-05-24 21:04:44 +00:00
if ( w = = width & & h = = height ) {
_forceFull = true ;
return ;
}
2006-05-19 22:26:07 +00:00
if ( w > 0 & & h > 0 ) {
SDL_Rect * r = & _dirtyRectList [ _numDirtyRects + + ] ;
r - > x = x ;
r - > y = y ;
r - > w = w ;
r - > h = h ;
}
2004-02-29 00:49:40 +00:00
}
2011-06-19 20:08:55 +02:00
int16 SurfaceSdlGraphicsManager : : getHeight ( ) {
2008-11-14 22:08:10 +00:00
return _videoMode . screenHeight ;
2004-02-29 00:49:40 +00:00
}
2011-06-19 20:08:55 +02:00
int16 SurfaceSdlGraphicsManager : : getWidth ( ) {
2008-11-14 22:08:10 +00:00
return _videoMode . screenWidth ;
2004-02-29 00:49:40 +00:00
}
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : setPalette ( const byte * colors , uint start , uint num ) {
2005-03-12 16:32:32 +00:00
assert ( colors ) ;
2006-07-23 06:50:49 +00:00
2009-08-21 18:16:37 +00:00
# ifdef USE_RGB_COLOR
2010-04-20 21:16:58 +00:00
assert ( _screenFormat . bytesPerPixel = = 1 ) ;
2009-06-10 05:35:18 +00:00
# endif
2006-07-23 06:50:49 +00:00
// Setting the palette before _screen is created is allowed - for now -
// since we don't actually set the palette until the screen is updated.
// But it could indicate a programming error, so let's warn about it.
if ( ! _screen )
2011-06-19 20:08:55 +02:00
warning ( " SurfaceSdlGraphicsManager::setPalette: _screen == NULL " ) ;
2006-07-23 06:50:49 +00:00
2004-02-29 00:49:40 +00:00
const byte * b = colors ;
uint i ;
SDL_Color * base = _currentPalette + start ;
2011-02-13 14:37:19 +01:00
for ( i = 0 ; i < num ; i + + , b + = 3 ) {
2004-02-29 00:49:40 +00:00
base [ i ] . r = b [ 0 ] ;
base [ i ] . g = b [ 1 ] ;
base [ i ] . b = b [ 2 ] ;
2015-01-25 01:34:57 +01:00
# if SDL_VERSION_ATLEAST(2, 0, 0)
base [ i ] . a = 255 ;
# endif
2004-02-29 00:49:40 +00:00
}
if ( start < _paletteDirtyStart )
_paletteDirtyStart = start ;
if ( start + num > _paletteDirtyEnd )
_paletteDirtyEnd = start + num ;
2005-02-17 23:01:00 +00:00
// Some games blink cursors with palette
2006-05-20 09:27:56 +00:00
if ( _cursorPaletteDisabled )
2005-02-17 23:01:00 +00:00
blitCursor ( ) ;
}
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : grabPalette ( byte * colors , uint start , uint num ) {
2005-07-30 21:11:48 +00:00
assert ( colors ) ;
2010-04-20 21:16:58 +00:00
# ifdef USE_RGB_COLOR
assert ( _screenFormat . bytesPerPixel = = 1 ) ;
# endif
2005-05-08 21:39:05 +00:00
const SDL_Color * base = _currentPalette + start ;
2005-07-30 21:11:48 +00:00
2005-05-08 21:39:05 +00:00
for ( uint i = 0 ; i < num ; + + i ) {
2011-02-13 14:37:19 +01:00
colors [ i * 3 ] = base [ i ] . r ;
colors [ i * 3 + 1 ] = base [ i ] . g ;
colors [ i * 3 + 2 ] = base [ i ] . b ;
2005-05-08 21:39:05 +00:00
}
}
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : setCursorPalette ( const byte * colors , uint start , uint num ) {
2005-03-12 16:32:32 +00:00
assert ( colors ) ;
2005-02-17 23:01:00 +00:00
const byte * b = colors ;
uint i ;
SDL_Color * base = _cursorPalette + start ;
2011-02-13 14:37:19 +01:00
for ( i = 0 ; i < num ; i + + , b + = 3 ) {
2005-02-17 23:01:00 +00:00
base [ i ] . r = b [ 0 ] ;
base [ i ] . g = b [ 1 ] ;
base [ i ] . b = b [ 2 ] ;
2015-01-25 01:34:57 +01:00
# if SDL_VERSION_ATLEAST(2, 0, 0)
base [ i ] . a = 255 ;
# endif
2005-02-17 23:01:00 +00:00
}
2005-02-20 02:04:45 +00:00
_cursorPaletteDisabled = false ;
2009-06-26 10:37:00 +00:00
blitCursor ( ) ;
2004-02-29 00:49:40 +00:00
}
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : setShakePos ( int shake_pos ) {
2011-06-19 18:49:02 +02:00
assert ( _transactionMode = = kTransactionNone ) ;
2004-11-23 21:30:38 +00:00
2004-02-29 00:49:40 +00:00
_newShakePos = shake_pos ;
}
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : setFocusRectangle ( const Common : : Rect & rect ) {
2011-02-24 01:11:16 +01:00
# ifdef USE_SDL_DEBUG_FOCUSRECT
2011-02-24 01:15:27 +01:00
// Only enable focus rectangle debug code, when the user wants it
if ( ! _enableFocusRectDebugCode )
return ;
2011-02-24 01:11:16 +01:00
_enableFocusRect = true ;
_focusRect = rect ;
2011-02-24 01:19:10 +01:00
if ( rect . left < 0 | | rect . top < 0 | | rect . right > _videoMode . screenWidth | | rect . bottom > _videoMode . screenHeight )
2011-06-19 20:08:55 +02:00
warning ( " SurfaceSdlGraphicsManager::setFocusRectangle: Got a rect which does not fit inside the screen bounds: %d,%d,%d,%d " , rect . left , rect . top , rect . right , rect . bottom ) ;
2011-02-24 01:19:10 +01:00
2011-02-24 01:11:16 +01:00
// It's gross but we actually sometimes get rects, which are not inside the screen bounds,
// thus we need to clip the rect here...
_focusRect . clip ( _videoMode . screenWidth , _videoMode . screenHeight ) ;
// We just fake this as a dirty rect for now, to easily force an screen update whenever
// the rect changes.
addDirtyRect ( _focusRect . left , _focusRect . top , _focusRect . width ( ) , _focusRect . height ( ) ) ;
# endif
2011-02-24 00:09:25 +01:00
}
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : clearFocusRectangle ( ) {
2011-02-24 01:11:16 +01:00
# ifdef USE_SDL_DEBUG_FOCUSRECT
2011-02-24 01:15:27 +01:00
// Only enable focus rectangle debug code, when the user wants it
if ( ! _enableFocusRectDebugCode )
return ;
2011-02-24 01:11:16 +01:00
_enableFocusRect = false ;
// We just fake this as a dirty rect for now, to easily force an screen update whenever
// the rect changes.
addDirtyRect ( _focusRect . left , _focusRect . top , _focusRect . width ( ) , _focusRect . height ( ) ) ;
# endif
2011-02-24 00:09:25 +01:00
}
2004-02-29 00:49:40 +00:00
# pragma mark -
# pragma mark --- Overlays ---
# pragma mark -
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : showOverlay ( ) {
2011-06-19 18:49:02 +02:00
assert ( _transactionMode = = kTransactionNone ) ;
2004-11-23 21:30:38 +00:00
2006-02-26 03:03:59 +00:00
int x , y ;
if ( _overlayVisible )
return ;
2004-02-29 00:49:40 +00:00
_overlayVisible = true ;
2006-02-26 03:03:59 +00:00
// Since resolution could change, put mouse to adjusted position
// Fixes bug #1349059
2008-11-14 22:08:10 +00:00
x = _mouseCurState . x * _videoMode . scaleFactor ;
2009-05-01 09:09:07 +00:00
if ( _videoMode . aspectRatioCorrection )
2008-11-14 22:08:10 +00:00
y = real2Aspect ( _mouseCurState . y ) * _videoMode . scaleFactor ;
2006-05-27 12:39:55 +00:00
else
2008-11-14 22:08:10 +00:00
y = _mouseCurState . y * _videoMode . scaleFactor ;
2006-02-26 03:03:59 +00:00
warpMouse ( x , y ) ;
2004-03-28 16:30:50 +00:00
clearOverlay ( ) ;
2004-02-29 00:49:40 +00:00
}
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : hideOverlay ( ) {
2011-06-19 18:49:02 +02:00
assert ( _transactionMode = = kTransactionNone ) ;
2004-11-23 21:30:38 +00:00
2006-02-26 03:03:59 +00:00
if ( ! _overlayVisible )
return ;
int x , y ;
2004-02-29 00:49:40 +00:00
_overlayVisible = false ;
2006-02-26 03:03:59 +00:00
// Since resolution could change, put mouse to adjusted position
// Fixes bug #1349059
2008-11-14 22:08:10 +00:00
x = _mouseCurState . x / _videoMode . scaleFactor ;
y = _mouseCurState . y / _videoMode . scaleFactor ;
2009-05-01 09:09:07 +00:00
if ( _videoMode . aspectRatioCorrection )
2006-05-27 12:39:55 +00:00
y = aspect2Real ( y ) ;
2006-02-26 03:03:59 +00:00
warpMouse ( x , y ) ;
2005-03-09 23:07:32 +00:00
clearOverlay ( ) ;
2006-02-26 03:03:59 +00:00
2004-02-29 00:49:40 +00:00
_forceFull = true ;
}
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : clearOverlay ( ) {
2011-06-19 18:49:02 +02:00
//assert(_transactionMode == kTransactionNone);
2004-11-23 21:30:38 +00:00
2004-03-28 20:31:18 +00:00
Common : : StackLock lock ( _graphicsMutex ) ; // Lock the mutex until this function ends
2005-07-30 21:11:48 +00:00
2005-03-09 23:07:32 +00:00
if ( ! _overlayVisible )
return ;
2004-02-29 00:49:40 +00:00
// Clear the overlay by making the game screen "look through" everywhere.
SDL_Rect src , dst ;
src . x = src . y = 0 ;
dst . x = dst . y = 1 ;
2008-11-14 22:08:10 +00:00
src . w = dst . w = _videoMode . screenWidth ;
src . h = dst . h = _videoMode . screenHeight ;
2004-02-29 00:49:40 +00:00
if ( SDL_BlitSurface ( _screen , & src , _tmpscreen , & dst ) ! = 0 )
error ( " SDL_BlitSurface failed: %s " , SDL_GetError ( ) ) ;
2005-03-09 23:07:32 +00:00
SDL_LockSurface ( _tmpscreen ) ;
SDL_LockSurface ( _overlayscreen ) ;
2008-01-27 19:47:41 +00:00
_scalerProc ( ( byte * ) ( _tmpscreen - > pixels ) + _tmpscreen - > pitch + 2 , _tmpscreen - > pitch ,
2008-11-14 22:08:10 +00:00
( byte * ) _overlayscreen - > pixels , _overlayscreen - > pitch , _videoMode . screenWidth , _videoMode . screenHeight ) ;
2006-05-17 23:52:45 +00:00
2010-05-10 17:25:12 +00:00
# ifdef USE_SCALERS
2009-05-01 09:09:07 +00:00
if ( _videoMode . aspectRatioCorrection )
2008-01-27 19:47:41 +00:00
stretch200To240 ( ( uint8 * ) _overlayscreen - > pixels , _overlayscreen - > pitch ,
2008-11-14 22:08:10 +00:00
_videoMode . overlayWidth , _videoMode . screenHeight * _videoMode . scaleFactor , 0 , 0 , 0 ) ;
2006-05-20 15:43:27 +00:00
# endif
2005-03-09 23:07:32 +00:00
SDL_UnlockSurface ( _tmpscreen ) ;
SDL_UnlockSurface ( _overlayscreen ) ;
2004-02-29 00:49:40 +00:00
_forceFull = true ;
}
2012-06-16 04:17:14 +02:00
void SurfaceSdlGraphicsManager : : grabOverlay ( void * buf , int pitch ) {
2011-06-19 18:49:02 +02:00
assert ( _transactionMode = = kTransactionNone ) ;
2004-11-23 21:30:38 +00:00
2005-03-09 23:07:32 +00:00
if ( _overlayscreen = = NULL )
2004-02-29 00:49:40 +00:00
return ;
2005-03-09 23:07:32 +00:00
if ( SDL_LockSurface ( _overlayscreen ) = = - 1 )
2004-02-29 00:49:40 +00:00
error ( " SDL_LockSurface failed: %s " , SDL_GetError ( ) ) ;
2005-03-09 23:07:32 +00:00
byte * src = ( byte * ) _overlayscreen - > pixels ;
2012-06-16 04:17:14 +02:00
byte * dst = ( byte * ) buf ;
2008-11-14 22:08:10 +00:00
int h = _videoMode . overlayHeight ;
2004-02-29 00:49:40 +00:00
do {
2012-06-16 04:17:14 +02:00
memcpy ( dst , src , _videoMode . overlayWidth * 2 ) ;
2005-03-09 23:07:32 +00:00
src + = _overlayscreen - > pitch ;
2012-06-16 04:17:14 +02:00
dst + = pitch ;
2004-02-29 00:49:40 +00:00
} while ( - - h ) ;
2005-03-09 23:07:32 +00:00
SDL_UnlockSurface ( _overlayscreen ) ;
2004-02-29 00:49:40 +00:00
}
2012-06-16 04:17:14 +02:00
void SurfaceSdlGraphicsManager : : copyRectToOverlay ( const void * buf , int pitch , int x , int y , int w , int h ) {
2011-06-19 18:49:02 +02:00
assert ( _transactionMode = = kTransactionNone ) ;
2004-11-23 21:30:38 +00:00
2005-03-09 23:07:32 +00:00
if ( _overlayscreen = = NULL )
2004-02-29 00:49:40 +00:00
return ;
2012-06-16 04:17:14 +02:00
const byte * src = ( const byte * ) buf ;
2004-02-29 00:49:40 +00:00
// Clip the coordinates
if ( x < 0 ) {
w + = x ;
2012-06-16 04:17:14 +02:00
src - = x * 2 ;
2004-02-29 00:49:40 +00:00
x = 0 ;
}
if ( y < 0 ) {
2012-06-16 04:17:14 +02:00
h + = y ;
src - = y * pitch ;
2004-02-29 00:49:40 +00:00
y = 0 ;
}
2008-11-14 22:08:10 +00:00
if ( w > _videoMode . overlayWidth - x ) {
w = _videoMode . overlayWidth - x ;
2004-02-29 00:49:40 +00:00
}
2008-11-14 22:08:10 +00:00
if ( h > _videoMode . overlayHeight - y ) {
h = _videoMode . overlayHeight - y ;
2004-02-29 00:49:40 +00:00
}
if ( w < = 0 | | h < = 0 )
return ;
// Mark the modified region as dirty
2004-12-01 21:16:55 +00:00
addDirtyRect ( x , y , w , h ) ;
2004-02-29 00:49:40 +00:00
2005-03-09 23:07:32 +00:00
if ( SDL_LockSurface ( _overlayscreen ) = = - 1 )
2004-02-29 00:49:40 +00:00
error ( " SDL_LockSurface failed: %s " , SDL_GetError ( ) ) ;
2005-03-09 23:07:32 +00:00
byte * dst = ( byte * ) _overlayscreen - > pixels + y * _overlayscreen - > pitch + x * 2 ;
2004-02-29 00:49:40 +00:00
do {
2012-06-16 04:17:14 +02:00
memcpy ( dst , src , w * 2 ) ;
2005-03-09 23:07:32 +00:00
dst + = _overlayscreen - > pitch ;
2012-06-16 04:17:14 +02:00
src + = pitch ;
2004-02-29 00:49:40 +00:00
} while ( - - h ) ;
2005-03-09 23:07:32 +00:00
SDL_UnlockSurface ( _overlayscreen ) ;
2004-02-29 00:49:40 +00:00
}
# pragma mark -
# pragma mark --- Mouse ---
# pragma mark -
2011-06-19 20:08:55 +02:00
bool SurfaceSdlGraphicsManager : : showMouse ( bool visible ) {
2004-02-29 00:49:40 +00:00
if ( _mouseVisible = = visible )
return visible ;
2005-07-30 21:11:48 +00:00
2004-02-29 00:49:40 +00:00
bool last = _mouseVisible ;
_mouseVisible = visible ;
2009-02-27 05:58:08 +00:00
_mouseNeedsRedraw = true ;
2004-02-29 00:49:40 +00:00
return last ;
}
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : setMousePos ( int x , int y ) {
2004-02-29 00:49:40 +00:00
if ( x ! = _mouseCurState . x | | y ! = _mouseCurState . y ) {
2009-02-24 21:43:07 +00:00
_mouseNeedsRedraw = true ;
2004-02-29 00:49:40 +00:00
_mouseCurState . x = x ;
_mouseCurState . y = y ;
}
}
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : warpMouse ( int x , int y ) {
2010-08-31 13:05:15 +00:00
// Don't change actual mouse position, when mouse is outside of our window (in case of windowed mode)
2015-02-16 00:49:42 +01:00
if ( ! _window - > hasMouseFocus ( ) ) {
2010-08-31 13:05:15 +00:00
setMousePos ( x , y ) ; // but change game cursor position
2010-06-15 16:58:03 +00:00
return ;
2010-08-31 13:05:15 +00:00
}
2010-06-15 16:58:03 +00:00
2015-12-13 15:42:11 +01:00
int x1 = x , y1 = y ;
2009-05-01 09:09:07 +00:00
if ( _videoMode . aspectRatioCorrection & & ! _overlayVisible )
2015-12-13 15:42:11 +01:00
y1 = real2Aspect ( y1 ) ;
2006-02-26 14:31:44 +00:00
2004-02-29 00:49:40 +00:00
if ( _mouseCurState . x ! = x | | _mouseCurState . y ! = y ) {
2015-12-13 15:42:11 +01:00
if ( ! _overlayVisible ) {
x1 * = _videoMode . scaleFactor ;
y1 * = _videoMode . scaleFactor ;
}
# if SDL_VERSION_ATLEAST(2, 0, 0)
2015-12-13 20:20:23 +01:00
// Transform our coordinates in "virtual" output coordinate space into
// actual output coordinate space.
x1 = x1 * _windowWidth / _videoMode . hardwareWidth ;
y1 = y1 * _windowHeight / _videoMode . hardwareHeight ;
2015-12-13 15:42:11 +01:00
# endif
_window - > warpMouseInWindow ( x1 , y1 ) ;
2004-02-29 00:49:40 +00:00
// SDL_WarpMouse() generates a mouse movement event, so
2004-12-01 21:16:55 +00:00
// setMousePos() would be called eventually. However, the
2004-02-29 00:49:40 +00:00
// cannon script in CoMI calls this function twice each time
// the cannon is reloaded. Unless we update the mouse position
// immediately the second call is ignored, causing the cannon
// to change its aim.
2004-12-01 21:16:55 +00:00
setMousePos ( x , y ) ;
2004-02-29 00:49:40 +00:00
}
}
2005-07-30 21:11:48 +00:00
2012-06-16 03:10:43 +02:00
void SurfaceSdlGraphicsManager : : setMouseCursor ( const void * buf , uint w , uint h , int hotspot_x , int hotspot_y , uint32 keycolor , bool dontScale , const Graphics : : PixelFormat * format ) {
2009-08-21 18:16:37 +00:00
# ifdef USE_RGB_COLOR
2009-06-26 10:37:00 +00:00
if ( ! format )
2009-07-09 17:25:06 +00:00
_cursorFormat = Graphics : : PixelFormat : : createFormatCLUT8 ( ) ;
2009-06-30 07:30:57 +00:00
else if ( format - > bytesPerPixel < = _screenFormat . bytesPerPixel )
2009-06-26 10:37:00 +00:00
_cursorFormat = * format ;
2010-01-07 15:28:58 +00:00
if ( _cursorFormat . bytesPerPixel < 4 )
assert ( keycolor < ( uint ) ( 1 < < ( _cursorFormat . bytesPerPixel < < 3 ) ) ) ;
2009-06-06 01:16:04 +00:00
# else
2010-01-07 15:28:58 +00:00
assert ( keycolor < = 0xFF ) ;
2009-06-05 08:09:37 +00:00
# endif
if ( w = = 0 | | h = = 0 )
return ;
_mouseCurState . hotX = hotspot_x ;
_mouseCurState . hotY = hotspot_y ;
_mouseKeyColor = keycolor ;
2012-06-03 02:02:57 +02:00
_cursorDontScale = dontScale ;
2009-06-05 08:09:37 +00:00
if ( _mouseCurState . w ! = ( int ) w | | _mouseCurState . h ! = ( int ) h ) {
_mouseCurState . w = w ;
_mouseCurState . h = h ;
if ( _mouseOrigSurface )
SDL_FreeSurface ( _mouseOrigSurface ) ;
// Allocate bigger surface because AdvMame2x adds black pixel at [0,0]
_mouseOrigSurface = SDL_CreateRGBSurface ( SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA ,
_mouseCurState . w + 2 ,
_mouseCurState . h + 2 ,
16 ,
_hwscreen - > format - > Rmask ,
_hwscreen - > format - > Gmask ,
_hwscreen - > format - > Bmask ,
_hwscreen - > format - > Amask ) ;
if ( _mouseOrigSurface = = NULL )
error ( " allocating _mouseOrigSurface failed " ) ;
SDL_SetColorKey ( _mouseOrigSurface , SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA , kMouseColorKey ) ;
}
free ( _mouseData ) ;
2009-08-21 18:16:37 +00:00
# ifdef USE_RGB_COLOR
2009-06-13 10:24:52 +00:00
_mouseData = ( byte * ) malloc ( w * h * _cursorFormat . bytesPerPixel ) ;
memcpy ( _mouseData , buf , w * h * _cursorFormat . bytesPerPixel ) ;
2009-06-06 01:16:04 +00:00
# else
2004-05-05 02:32:46 +00:00
_mouseData = ( byte * ) malloc ( w * h ) ;
memcpy ( _mouseData , buf , w * h ) ;
2009-06-06 08:41:03 +00:00
# endif
2009-06-05 08:09:37 +00:00
2005-02-17 23:01:00 +00:00
blitCursor ( ) ;
2004-02-29 00:49:40 +00:00
}
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : blitCursor ( ) {
2005-02-17 23:01:00 +00:00
byte * dstPtr ;
const byte * srcPtr = _mouseData ;
2009-08-21 18:16:37 +00:00
# ifdef USE_RGB_COLOR
2009-06-11 05:56:00 +00:00
uint32 color ;
# else
2004-02-29 00:49:40 +00:00
byte color ;
2009-06-11 05:56:00 +00:00
# endif
2005-02-19 16:04:03 +00:00
int w , h , i , j ;
2005-07-30 21:11:48 +00:00
2005-02-19 00:24:48 +00:00
if ( ! _mouseOrigSurface | | ! _mouseData )
2008-01-28 00:14:17 +00:00
return ;
2005-07-30 21:11:48 +00:00
2009-02-26 02:04:30 +00:00
_mouseNeedsRedraw = true ;
2005-02-17 23:01:00 +00:00
w = _mouseCurState . w ;
h = _mouseCurState . h ;
2005-07-30 21:11:48 +00:00
2005-02-17 23:01:00 +00:00
SDL_LockSurface ( _mouseOrigSurface ) ;
// Make whole surface transparent
2005-02-19 16:04:03 +00:00
for ( i = 0 ; i < h + 2 ; i + + ) {
2005-02-17 23:01:00 +00:00
dstPtr = ( byte * ) _mouseOrigSurface - > pixels + _mouseOrigSurface - > pitch * i ;
2005-02-19 16:04:03 +00:00
for ( j = 0 ; j < w + 2 ; j + + ) {
2005-02-17 23:01:00 +00:00
* ( uint16 * ) dstPtr = kMouseColorKey ;
dstPtr + = 2 ;
}
2004-02-29 00:49:40 +00:00
}
2005-02-17 23:01:00 +00:00
// Draw from [1,1] since AdvMame2x adds artefact at 0,0
dstPtr = ( byte * ) _mouseOrigSurface - > pixels + _mouseOrigSurface - > pitch + 2 ;
2006-05-20 08:06:21 +00:00
SDL_Color * palette ;
2006-05-20 09:27:56 +00:00
if ( _cursorPaletteDisabled )
2006-05-20 08:06:21 +00:00
palette = _currentPalette ;
2006-05-20 09:27:56 +00:00
else
palette = _cursorPalette ;
2008-01-27 19:47:41 +00:00
2005-02-19 16:04:03 +00:00
for ( i = 0 ; i < h ; i + + ) {
for ( j = 0 ; j < w ; j + + ) {
2009-08-21 18:16:37 +00:00
# ifdef USE_RGB_COLOR
2009-06-13 10:24:52 +00:00
if ( _cursorFormat . bytesPerPixel > 1 ) {
2009-10-31 12:38:08 +00:00
if ( _cursorFormat . bytesPerPixel = = 2 )
2009-12-19 02:03:41 +00:00
color = * ( const uint16 * ) srcPtr ;
2009-10-31 12:38:08 +00:00
else
2009-12-19 02:03:41 +00:00
color = * ( const uint32 * ) srcPtr ;
2009-06-06 01:16:04 +00:00
if ( color ! = _mouseKeyColor ) { // transparent, don't draw
2009-10-31 12:38:08 +00:00
uint8 r , g , b ;
_cursorFormat . colorToRGB ( color , r , g , b ) ;
2009-06-06 01:16:04 +00:00
* ( uint16 * ) dstPtr = SDL_MapRGB ( _mouseOrigSurface - > format ,
r , g , b ) ;
}
dstPtr + = 2 ;
2009-06-13 10:24:52 +00:00
srcPtr + = _cursorFormat . bytesPerPixel ;
2009-06-06 01:16:04 +00:00
} else {
# endif
2009-06-11 05:56:00 +00:00
color = * srcPtr ;
2009-06-06 01:16:04 +00:00
if ( color ! = _mouseKeyColor ) { // transparent, don't draw
* ( uint16 * ) dstPtr = SDL_MapRGB ( _mouseOrigSurface - > format ,
palette [ color ] . r , palette [ color ] . g , palette [ color ] . b ) ;
}
dstPtr + = 2 ;
srcPtr + + ;
2009-08-21 18:16:37 +00:00
# ifdef USE_RGB_COLOR
2004-02-29 00:49:40 +00:00
}
2009-06-05 06:41:04 +00:00
# endif
2004-02-29 00:49:40 +00:00
}
2005-02-17 23:01:00 +00:00
dstPtr + = _mouseOrigSurface - > pitch - w * 2 ;
2008-01-28 00:14:17 +00:00
}
2004-02-29 00:49:40 +00:00
2006-06-04 12:38:27 +00:00
int rW , rH ;
2012-06-03 02:02:57 +02:00
int cursorScale ;
2004-02-29 00:49:40 +00:00
2012-06-03 02:02:57 +02:00
if ( _cursorDontScale ) {
// Don't scale the cursor at all if the user requests this behavior.
cursorScale = 1 ;
2005-02-17 23:01:00 +00:00
} else {
2012-06-03 02:02:57 +02:00
// Scale the cursor with the game screen scale factor.
cursorScale = _videoMode . scaleFactor ;
2008-01-28 00:14:17 +00:00
}
2005-07-30 21:11:48 +00:00
2012-06-03 02:02:57 +02:00
// Adapt the real hotspot according to the scale factor.
rW = w * cursorScale ;
rH = h * cursorScale ;
_mouseCurState . rHotX = _mouseCurState . hotX * cursorScale ;
_mouseCurState . rHotY = _mouseCurState . hotY * cursorScale ;
// The virtual dimensions will be the same as the original.
_mouseCurState . vW = w ;
_mouseCurState . vH = h ;
_mouseCurState . vHotX = _mouseCurState . hotX ;
_mouseCurState . vHotY = _mouseCurState . hotY ;
2010-05-10 17:25:12 +00:00
# ifdef USE_SCALERS
2006-06-04 12:38:27 +00:00
int rH1 = rH ; // store original to pass to aspect-correction function later
2007-12-29 14:11:12 +00:00
# endif
2012-06-03 02:02:57 +02:00
if ( ! _cursorDontScale & & _videoMode . aspectRatioCorrection ) {
2006-06-04 12:38:27 +00:00
rH = real2Aspect ( rH - 1 ) + 1 ;
_mouseCurState . rHotY = real2Aspect ( _mouseCurState . rHotY ) ;
2005-02-17 23:01:00 +00:00
}
2005-07-30 21:11:48 +00:00
2006-06-04 12:38:27 +00:00
if ( _mouseCurState . rW ! = rW | | _mouseCurState . rH ! = rH ) {
_mouseCurState . rW = rW ;
_mouseCurState . rH = rH ;
2005-07-30 21:11:48 +00:00
2005-02-17 23:01:00 +00:00
if ( _mouseSurface )
2005-07-30 21:11:48 +00:00
SDL_FreeSurface ( _mouseSurface ) ;
2005-02-17 23:01:00 +00:00
_mouseSurface = SDL_CreateRGBSurface ( SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA ,
2006-06-04 12:38:27 +00:00
_mouseCurState . rW ,
_mouseCurState . rH ,
2005-02-17 23:01:00 +00:00
16 ,
_hwscreen - > format - > Rmask ,
_hwscreen - > format - > Gmask ,
_hwscreen - > format - > Bmask ,
_hwscreen - > format - > Amask ) ;
2005-07-30 21:11:48 +00:00
2005-02-17 23:01:00 +00:00
if ( _mouseSurface = = NULL )
error ( " allocating _mouseSurface failed " ) ;
SDL_SetColorKey ( _mouseSurface , SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA , kMouseColorKey ) ;
2008-01-28 00:14:17 +00:00
}
2005-07-30 21:11:48 +00:00
2005-02-17 23:01:00 +00:00
SDL_LockSurface ( _mouseSurface ) ;
2005-03-17 09:49:22 +00:00
ScalerProc * scalerProc ;
2012-06-03 02:02:57 +02:00
// Only apply scaling, when the user allows it.
if ( ! _cursorDontScale ) {
// If possible, use the same scaler for the cursor as for the rest of
// the game. This only works well with the non-blurring scalers so we
// actually only use the 1x, 2x and AdvMame scalers.
if ( _videoMode . mode = = GFX_DOUBLESIZE | | _videoMode . mode = = GFX_TRIPLESIZE )
scalerProc = _scalerProc ;
else
scalerProc = scalersMagn [ _videoMode . scaleFactor - 1 ] ;
} else {
scalerProc = Normal1x ;
}
2005-03-17 09:49:22 +00:00
scalerProc ( ( byte * ) _mouseOrigSurface - > pixels + _mouseOrigSurface - > pitch + 2 ,
2005-02-17 23:01:00 +00:00
_mouseOrigSurface - > pitch , ( byte * ) _mouseSurface - > pixels , _mouseSurface - > pitch ,
2005-03-17 09:49:22 +00:00
_mouseCurState . w , _mouseCurState . h ) ;
2005-02-17 23:01:00 +00:00
2010-05-10 17:25:12 +00:00
# ifdef USE_SCALERS
2012-06-03 02:02:57 +02:00
if ( ! _cursorDontScale & & _videoMode . aspectRatioCorrection )
2006-06-04 12:38:27 +00:00
cursorStretch200To240 ( ( uint8 * ) _mouseSurface - > pixels , _mouseSurface - > pitch , rW , rH1 , 0 , 0 , 0 ) ;
2005-09-20 18:16:09 +00:00
# endif
2005-07-30 21:11:48 +00:00
2005-02-17 23:01:00 +00:00
SDL_UnlockSurface ( _mouseSurface ) ;
SDL_UnlockSurface ( _mouseOrigSurface ) ;
2004-02-29 00:49:40 +00:00
}
2010-05-10 17:25:12 +00:00
# ifdef USE_SCALERS
2005-07-30 21:11:48 +00:00
// Basically it is kVeryFastAndUglyAspectMode of stretch200To240 from
2010-05-10 17:25:12 +00:00
// common/scale/aspect.cpp
2005-02-17 23:01:00 +00:00
static int cursorStretch200To240 ( uint8 * buf , uint32 pitch , int width , int height , int srcX , int srcY , int origSrcY ) {
int maxDstY = real2Aspect ( origSrcY + height - 1 ) ;
int y ;
const uint8 * startSrcPtr = buf + srcX * 2 + ( srcY - origSrcY ) * pitch ;
uint8 * dstPtr = buf + srcX * 2 + maxDstY * pitch ;
for ( y = maxDstY ; y > = srcY ; y - - ) {
const uint8 * srcPtr = startSrcPtr + aspect2Real ( y ) * pitch ;
if ( srcPtr = = dstPtr )
break ;
memcpy ( dstPtr , srcPtr , width * 2 ) ;
dstPtr - = pitch ;
}
2004-11-23 21:30:38 +00:00
2005-02-17 23:01:00 +00:00
return 1 + maxDstY - srcY ;
}
2005-09-20 18:16:09 +00:00
# endif
2004-02-29 00:49:40 +00:00
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : undrawMouse ( ) {
2005-07-09 06:44:00 +00:00
const int x = _mouseBackup . x ;
2006-05-19 22:26:07 +00:00
const int y = _mouseBackup . y ;
2005-07-30 21:11:48 +00:00
2005-03-09 23:07:32 +00:00
// When we switch bigger overlay off mouse jumps. Argh!
2005-07-09 06:44:00 +00:00
// This is intended to prevent undrawing offscreen mouse
2009-02-26 02:04:30 +00:00
if ( ! _overlayVisible & & ( x > = _videoMode . screenWidth | | y > = _videoMode . screenHeight ) )
2005-07-09 06:44:00 +00:00
return ;
2005-07-30 21:11:48 +00:00
2006-05-17 23:52:45 +00:00
if ( _mouseBackup . w ! = 0 & & _mouseBackup . h ! = 0 )
2016-06-29 12:59:56 +02:00
addDirtyRect ( x , y , _mouseBackup . w , _mouseBackup . h ) ;
2005-02-17 23:01:00 +00:00
}
2004-03-01 11:20:32 +00:00
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : drawMouse ( ) {
2006-05-21 18:49:26 +00:00
if ( ! _mouseVisible | | ! _mouseSurface ) {
2005-02-17 23:01:00 +00:00
_mouseBackup . x = _mouseBackup . y = _mouseBackup . w = _mouseBackup . h = 0 ;
2008-01-28 00:14:17 +00:00
return ;
2005-02-17 23:01:00 +00:00
}
2006-05-27 12:55:28 +00:00
2006-05-19 22:26:07 +00:00
SDL_Rect dst ;
2006-05-17 23:52:45 +00:00
int scale ;
2006-06-04 12:38:27 +00:00
int hotX , hotY ;
dst . x = _mouseCurState . x ;
dst . y = _mouseCurState . y ;
2005-03-09 23:07:32 +00:00
if ( ! _overlayVisible ) {
2008-11-14 22:08:10 +00:00
scale = _videoMode . scaleFactor ;
2006-06-04 12:38:27 +00:00
dst . w = _mouseCurState . vW ;
dst . h = _mouseCurState . vH ;
hotX = _mouseCurState . vHotX ;
hotY = _mouseCurState . vHotY ;
2005-03-09 23:07:32 +00:00
} else {
2006-05-17 23:52:45 +00:00
scale = 1 ;
2006-06-04 12:38:27 +00:00
dst . w = _mouseCurState . rW ;
dst . h = _mouseCurState . rH ;
hotX = _mouseCurState . rHotX ;
hotY = _mouseCurState . rHotY ;
2006-05-20 07:31:03 +00:00
}
2004-02-29 00:49:40 +00:00
2006-05-27 12:55:28 +00:00
// The mouse is undrawn using virtual coordinates, i.e. they may be
// scaled and aspect-ratio corrected.
2004-02-29 00:49:40 +00:00
2006-06-04 12:38:27 +00:00
_mouseBackup . x = dst . x - hotX ;
_mouseBackup . y = dst . y - hotY ;
2006-05-17 23:52:45 +00:00
_mouseBackup . w = dst . w ;
_mouseBackup . h = dst . h ;
2006-05-19 22:26:07 +00:00
// We draw the pre-scaled cursor image, so now we need to adjust for
// scaling, shake position and aspect ratio correction manually.
2016-06-29 12:59:56 +02:00
dst . y + = _currentShakePos ;
2006-05-19 22:26:07 +00:00
2009-05-01 09:09:07 +00:00
if ( _videoMode . aspectRatioCorrection & & ! _overlayVisible )
2006-05-19 22:26:07 +00:00
dst . y = real2Aspect ( dst . y ) ;
2008-01-27 19:47:41 +00:00
2006-06-04 12:38:27 +00:00
dst . x = scale * dst . x - _mouseCurState . rHotX ;
dst . y = scale * dst . y - _mouseCurState . rHotY ;
dst . w = _mouseCurState . rW ;
dst . h = _mouseCurState . rH ;
2005-03-09 23:07:32 +00:00
2006-05-27 12:55:28 +00:00
// Note that SDL_BlitSurface() and addDirtyRect() will both perform any
// clipping necessary
2006-05-19 22:26:07 +00:00
if ( SDL_BlitSurface ( _mouseSurface , NULL , _hwscreen , & dst ) ! = 0 )
2005-02-17 23:01:00 +00:00
error ( " SDL_BlitSurface failed: %s " , SDL_GetError ( ) ) ;
2006-05-27 12:55:28 +00:00
// The screen will be updated using real surface coordinates, i.e.
// they will not be scaled or aspect-ratio corrected.
addDirtyRect ( dst . x , dst . y , dst . w , dst . h , true ) ;
2004-02-29 00:49:40 +00:00
}
2004-03-13 14:19:15 +00:00
# pragma mark -
2005-07-11 10:54:53 +00:00
# pragma mark --- On Screen Display ---
2004-03-13 14:19:15 +00:00
# pragma mark -
# ifdef USE_OSD
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : displayMessageOnOSD ( const char * msg ) {
2011-06-19 18:49:02 +02:00
assert ( _transactionMode = = kTransactionNone ) ;
2005-03-12 16:32:32 +00:00
assert ( msg ) ;
2004-11-23 21:30:38 +00:00
2007-06-15 21:21:42 +00:00
Common : : StackLock lock ( _graphicsMutex ) ; // Lock the mutex until this function ends
2016-06-04 18:51:03 +06:00
removeOSDMessage ( ) ;
2005-07-30 21:11:48 +00:00
2004-03-15 19:07:56 +00:00
// The font we are going to use:
2011-05-22 21:57:53 +01:00
const Graphics : : Font * font = FontMan . getFontByUsage ( Graphics : : FontManager : : kLocalizedFont ) ;
2005-07-30 21:11:48 +00:00
2004-03-15 19:07:56 +00:00
// Split the message into separate lines.
2010-03-18 15:09:24 +00:00
Common : : Array < Common : : String > lines ;
2004-03-15 19:07:56 +00:00
const char * ptr ;
for ( ptr = msg ; * ptr ; + + ptr ) {
if ( * ptr = = ' \n ' ) {
lines . push_back ( Common : : String ( msg , ptr - msg ) ) ;
msg = ptr + 1 ;
}
}
lines . push_back ( Common : : String ( msg , ptr - msg ) ) ;
2004-03-13 14:19:15 +00:00
// Determine a rect which would contain the message string (clipped to the
// screen dimensions).
2004-03-15 19:07:56 +00:00
const int vOffset = 6 ;
const int lineSpacing = 1 ;
const int lineHeight = font - > getFontHeight ( ) + 2 * lineSpacing ;
int width = 0 ;
int height = lineHeight * lines . size ( ) + 2 * vOffset ;
2016-06-04 18:51:03 +06:00
uint i ;
2004-03-15 19:07:56 +00:00
for ( i = 0 ; i < lines . size ( ) ; i + + ) {
width = MAX ( width , font - > getStringWidth ( lines [ i ] ) + 14 ) ;
}
2005-07-30 21:11:48 +00:00
2004-03-15 19:07:56 +00:00
// Clip the rect
2016-09-13 20:33:42 +02:00
if ( width > _hwscreen - > w )
width = _hwscreen - > w ;
if ( height > _hwscreen - > h )
height = _hwscreen - > h ;
2016-06-04 18:51:03 +06:00
_osdMessageSurface = SDL_CreateRGBSurface (
2016-09-13 20:33:42 +02:00
SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCALPHA ,
width , height , 16 , _hwscreen - > format - > Rmask , _hwscreen - > format - > Gmask , _hwscreen - > format - > Bmask , _hwscreen - > format - > Amask
2016-06-04 18:51:03 +06:00
) ;
2016-09-03 21:20:16 +02:00
2016-06-04 18:51:03 +06:00
// Lock the surface
if ( SDL_LockSurface ( _osdMessageSurface ) )
error ( " displayMessageOnOSD: SDL_LockSurface failed: %s " , SDL_GetError ( ) ) ;
2004-03-13 14:19:15 +00:00
// Draw a dark gray rect
2016-09-03 21:20:16 +02:00
// TODO: Rounded corners ? Border?
2016-06-04 18:51:03 +06:00
SDL_FillRect ( _osdMessageSurface , nullptr , SDL_MapRGB ( _osdMessageSurface - > format , 64 , 64 , 64 ) ) ;
Graphics : : Surface dst ;
dst . init ( _osdMessageSurface - > w , _osdMessageSurface - > h , _osdMessageSurface - > pitch , _osdMessageSurface - > pixels ,
Graphics : : PixelFormat ( _osdMessageSurface - > format - > BytesPerPixel ,
8 - _osdMessageSurface - > format - > Rloss , 8 - _osdMessageSurface - > format - > Gloss ,
8 - _osdMessageSurface - > format - > Bloss , 8 - _osdMessageSurface - > format - > Aloss ,
_osdMessageSurface - > format - > Rshift , _osdMessageSurface - > format - > Gshift ,
_osdMessageSurface - > format - > Bshift , _osdMessageSurface - > format - > Ashift ) ) ;
2004-03-13 14:19:15 +00:00
// Render the message, centered, and in white
2004-03-15 19:07:56 +00:00
for ( i = 0 ; i < lines . size ( ) ; i + + ) {
font - > drawString ( & dst , lines [ i ] ,
2016-06-04 18:51:03 +06:00
0 , 0 + i * lineHeight + vOffset + lineSpacing , width ,
SDL_MapRGB ( _osdMessageSurface - > format , 255 , 255 , 255 ) ,
Graphics : : kTextAlignCenter ) ;
2004-03-15 19:07:56 +00:00
}
2004-03-13 14:19:15 +00:00
2016-06-04 18:51:03 +06:00
// Finished drawing, so unlock the OSD message surface
SDL_UnlockSurface ( _osdMessageSurface ) ;
2004-03-13 14:19:15 +00:00
// Init the OSD display parameters, and the fade out
2016-06-04 18:51:03 +06:00
_osdMessageAlpha = SDL_ALPHA_TRANSPARENT + kOSDInitialAlpha * ( SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT ) / 100 ;
_osdMessageFadeStartTime = SDL_GetTicks ( ) + kOSDFadeOutDelay ;
2016-09-13 20:33:42 +02:00
}
2016-06-03 17:44:26 +06:00
2016-09-13 20:33:42 +02:00
SDL_Rect SurfaceSdlGraphicsManager : : getOSDMessageRect ( ) const {
SDL_Rect rect ;
rect . x = ( _hwscreen - > w - _osdMessageSurface - > w ) / 2 ;
rect . y = ( _hwscreen - > h - _osdMessageSurface - > h ) / 2 ;
rect . w = _osdMessageSurface - > w ;
rect . h = _osdMessageSurface - > h ;
return rect ;
2016-06-03 17:44:26 +06:00
}
2016-09-13 20:33:42 +02:00
void SurfaceSdlGraphicsManager : : displayActivityIconOnOSD ( const Graphics : : Surface * icon ) {
2016-06-03 17:44:26 +06:00
assert ( _transactionMode = = kTransactionNone ) ;
Common : : StackLock lock ( _graphicsMutex ) ; // Lock the mutex until this function ends
2016-09-18 13:44:20 +02:00
if ( _osdIconSurface & & ! icon ) {
2016-10-03 07:16:22 +02:00
// Force a redraw to clear the icon on the next update
_forceFull = true ;
2016-09-18 13:44:20 +02:00
}
2016-09-13 20:33:42 +02:00
if ( _osdIconSurface ) {
SDL_FreeSurface ( _osdIconSurface ) ;
_osdIconSurface = nullptr ;
}
if ( icon ) {
const Graphics : : PixelFormat & iconFormat = icon - > format ;
_osdIconSurface = SDL_CreateRGBSurface (
SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCALPHA ,
icon - > w , icon - > h , iconFormat . bytesPerPixel * 8 ,
( ( 0xFF > > iconFormat . rLoss ) < < iconFormat . rShift ) ,
( ( 0xFF > > iconFormat . gLoss ) < < iconFormat . gShift ) ,
( ( 0xFF > > iconFormat . bLoss ) < < iconFormat . bShift ) ,
( ( 0xFF > > iconFormat . aLoss ) < < iconFormat . aShift )
) ;
// Lock the surface
if ( SDL_LockSurface ( _osdIconSurface ) )
error ( " displayActivityIconOnOSD: SDL_LockSurface failed: %s " , SDL_GetError ( ) ) ;
byte * dst = ( byte * ) _osdIconSurface - > pixels ;
const byte * src = ( const byte * ) icon - > getPixels ( ) ;
for ( uint y = 0 ; y < icon - > h ; y + + ) {
memcpy ( dst , src , icon - > w * iconFormat . bytesPerPixel ) ;
src + = icon - > pitch ;
dst + = _osdIconSurface - > pitch ;
}
2016-06-05 10:56:43 +06:00
2016-09-13 20:33:42 +02:00
// Finished drawing, so unlock the OSD icon surface
SDL_UnlockSurface ( _osdIconSurface ) ;
2016-06-03 17:44:26 +06:00
}
2016-06-03 19:18:01 +06:00
}
2016-09-13 20:33:42 +02:00
SDL_Rect SurfaceSdlGraphicsManager : : getOSDIconRect ( ) const {
SDL_Rect dstRect ;
dstRect . x = _hwscreen - > w - _osdIconSurface - > w - 10 ;
dstRect . y = 10 ;
dstRect . w = _osdIconSurface - > w ;
dstRect . h = _osdIconSurface - > h ;
return dstRect ;
2004-03-13 14:19:15 +00:00
}
2016-06-04 15:56:15 +06:00
2016-06-04 18:51:03 +06:00
void SurfaceSdlGraphicsManager : : removeOSDMessage ( ) {
2016-09-13 20:33:42 +02:00
// Remove the previous message
2016-06-04 18:51:03 +06:00
if ( _osdMessageSurface ) {
2016-09-03 21:20:16 +02:00
SDL_FreeSurface ( _osdMessageSurface ) ;
2016-06-04 18:51:03 +06:00
}
_osdMessageSurface = NULL ;
_osdMessageAlpha = SDL_ALPHA_TRANSPARENT ;
2016-09-13 20:33:42 +02:00
}
2016-06-04 18:51:03 +06:00
2016-09-13 20:33:42 +02:00
void SurfaceSdlGraphicsManager : : updateOSD ( ) {
// OSD message visible (i.e. non-transparent)?
if ( _osdMessageAlpha ! = SDL_ALPHA_TRANSPARENT ) {
// Updated alpha value
const int diff = SDL_GetTicks ( ) - _osdMessageFadeStartTime ;
if ( diff > 0 ) {
if ( diff > = kOSDFadeOutDuration ) {
// Back to full transparency
_osdMessageAlpha = SDL_ALPHA_TRANSPARENT ;
} else {
// Do a linear fade out...
const int startAlpha = SDL_ALPHA_TRANSPARENT + kOSDInitialAlpha * ( SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT ) / 100 ;
_osdMessageAlpha = startAlpha + diff * ( SDL_ALPHA_TRANSPARENT - startAlpha ) / kOSDFadeOutDuration ;
}
SDL_SetAlpha ( _osdMessageSurface , SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA , _osdMessageAlpha ) ;
2016-10-03 07:16:22 +02:00
_forceFull = true ;
2016-09-13 20:33:42 +02:00
}
2016-06-04 18:51:03 +06:00
2016-09-13 20:33:42 +02:00
if ( _osdMessageAlpha = = SDL_ALPHA_TRANSPARENT ) {
removeOSDMessage ( ) ;
}
}
2016-06-04 18:51:03 +06:00
2016-09-13 20:33:42 +02:00
if ( _osdIconSurface ) {
2016-10-03 07:16:22 +02:00
// Redraw the area below the icon for the transparent blit to give correct results.
_forceFull = true ;
2016-06-04 18:51:03 +06:00
}
}
2016-09-13 20:33:42 +02:00
void SurfaceSdlGraphicsManager : : drawOSD ( ) {
if ( _osdMessageSurface ) {
SDL_Rect dstRect = getOSDMessageRect ( ) ;
SDL_BlitSurface ( _osdMessageSurface , 0 , _hwscreen , & dstRect ) ;
}
if ( _osdIconSurface ) {
SDL_Rect dstRect = getOSDIconRect ( ) ;
SDL_BlitSurface ( _osdIconSurface , 0 , _hwscreen , & dstRect ) ;
}
2016-06-04 15:56:15 +06:00
}
2016-09-13 20:33:42 +02:00
2004-03-13 14:19:15 +00:00
# endif
2005-07-11 10:54:53 +00:00
2011-06-19 20:08:55 +02:00
bool SurfaceSdlGraphicsManager : : handleScalerHotkeys ( Common : : KeyCode key ) {
2005-07-11 10:54:53 +00:00
// Ctrl-Alt-a toggles aspect ratio correction
2010-07-11 04:32:24 +00:00
if ( key = = ' a ' ) {
2008-11-14 22:08:10 +00:00
beginGFXTransaction ( ) ;
2010-06-08 23:44:05 +00:00
setFeatureState ( OSystem : : kFeatureAspectRatioCorrection , ! _videoMode . aspectRatioCorrection ) ;
2008-11-14 22:08:10 +00:00
endGFXTransaction ( ) ;
2005-07-11 10:54:53 +00:00
# ifdef USE_OSD
2017-09-03 16:33:22 -05:00
Common : : String message ;
2009-05-01 09:09:07 +00:00
if ( _videoMode . aspectRatioCorrection )
2017-09-03 16:33:22 -05:00
message = Common : : String : : format ( " %s \n %d x %d -> %d x %d " ,
2011-06-06 20:08:28 +01:00
_ ( " Enabled aspect ratio correction " ) ,
2008-11-14 22:08:10 +00:00
_videoMode . screenWidth , _videoMode . screenHeight ,
2005-07-11 10:54:53 +00:00
_hwscreen - > w , _hwscreen - > h
) ;
else
2017-09-03 16:33:22 -05:00
message = Common : : String : : format ( " %s \n %d x %d -> %d x %d " ,
2011-06-06 20:08:28 +01:00
_ ( " Disabled aspect ratio correction " ) ,
2008-11-14 22:08:10 +00:00
_videoMode . screenWidth , _videoMode . screenHeight ,
2005-07-11 10:54:53 +00:00
_hwscreen - > w , _hwscreen - > h
) ;
2017-09-03 16:33:22 -05:00
displayMessageOnOSD ( message . c_str ( ) ) ;
2005-07-11 10:54:53 +00:00
# endif
2009-09-18 12:38:53 +00:00
internUpdateScreen ( ) ;
2009-12-04 19:57:33 +00:00
return true ;
2005-07-11 10:54:53 +00:00
}
2016-11-13 16:36:18 +01:00
2016-10-12 23:33:28 +01:00
# if SDL_VERSION_ATLEAST(2, 0, 0)
// Ctrl-Alt-f toggles filtering
if ( key = = ' f ' ) {
beginGFXTransaction ( ) ;
setFeatureState ( OSystem : : kFeatureFilteringMode , ! _videoMode . filtering ) ;
endGFXTransaction ( ) ;
# ifdef USE_OSD
if ( getFeatureState ( OSystem : : kFeatureFilteringMode ) ) {
displayMessageOnOSD ( _ ( " Filtering enabled " ) ) ;
} else {
displayMessageOnOSD ( _ ( " Filtering disabled " ) ) ;
}
# endif
2016-10-13 00:19:15 +01:00
_forceFull = true ;
2016-10-12 23:33:28 +01:00
internUpdateScreen ( ) ;
return true ;
}
# endif
2005-07-11 10:54:53 +00:00
int newMode = - 1 ;
2008-11-14 22:08:10 +00:00
int factor = _videoMode . scaleFactor - 1 ;
2010-07-11 16:11:28 +00:00
SDLKey sdlKey = ( SDLKey ) key ;
2005-07-30 21:11:48 +00:00
2005-07-11 10:54:53 +00:00
// Increase/decrease the scale factor
2010-07-11 16:11:28 +00:00
if ( sdlKey = = SDLK_EQUALS | | sdlKey = = SDLK_PLUS | | sdlKey = = SDLK_MINUS | |
sdlKey = = SDLK_KP_PLUS | | sdlKey = = SDLK_KP_MINUS ) {
factor + = ( sdlKey = = SDLK_MINUS | | sdlKey = = SDLK_KP_MINUS ) ? - 1 : + 1 ;
2005-07-11 10:54:53 +00:00
if ( 0 < = factor & & factor < = 3 ) {
newMode = s_gfxModeSwitchTable [ _scalerType ] [ factor ] ;
}
}
2005-07-30 21:11:48 +00:00
2010-07-11 16:11:28 +00:00
const bool isNormalNumber = ( SDLK_1 < = sdlKey & & sdlKey < = SDLK_9 ) ;
const bool isKeypadNumber = ( SDLK_KP1 < = sdlKey & & sdlKey < = SDLK_KP9 ) ;
2005-07-11 10:54:53 +00:00
if ( isNormalNumber | | isKeypadNumber ) {
2010-07-11 16:11:28 +00:00
_scalerType = sdlKey - ( isNormalNumber ? SDLK_1 : SDLK_KP1 ) ;
2005-07-11 10:54:53 +00:00
if ( _scalerType > = ARRAYSIZE ( s_gfxModeSwitchTable ) )
2009-12-04 19:57:33 +00:00
return false ;
2005-07-30 21:11:48 +00:00
2005-07-11 10:54:53 +00:00
while ( s_gfxModeSwitchTable [ _scalerType ] [ factor ] < 0 ) {
assert ( factor > 0 ) ;
factor - - ;
}
newMode = s_gfxModeSwitchTable [ _scalerType ] [ factor ] ;
}
2005-07-30 21:11:48 +00:00
2005-07-11 10:54:53 +00:00
if ( newMode > = 0 ) {
2008-11-14 22:08:10 +00:00
beginGFXTransaction ( ) ;
setGraphicsMode ( newMode ) ;
endGFXTransaction ( ) ;
2005-07-11 10:54:53 +00:00
# ifdef USE_OSD
2016-09-13 20:33:42 +02:00
const char * newScalerName = 0 ;
const OSystem : : GraphicsMode * g = getSupportedGraphicsModes ( ) ;
while ( g - > name ) {
if ( g - > id = = _videoMode . mode ) {
newScalerName = g - > description ;
break ;
2005-07-11 10:54:53 +00:00
}
2016-09-13 20:33:42 +02:00
g + + ;
}
if ( newScalerName ) {
2017-09-03 16:33:22 -05:00
const Common : : String message = Common : : String : : format (
" %s %s \n %d x %d -> %d x %d " ,
2016-09-13 20:33:42 +02:00
_ ( " Active graphics filter: " ) ,
newScalerName ,
_videoMode . screenWidth , _videoMode . screenHeight ,
2017-09-03 16:33:22 -05:00
_hwscreen - > w , _hwscreen - > h ) ;
displayMessageOnOSD ( message . c_str ( ) ) ;
2005-07-11 10:54:53 +00:00
}
# endif
2009-09-18 12:38:53 +00:00
internUpdateScreen ( ) ;
2005-07-11 10:54:53 +00:00
2009-12-04 19:57:33 +00:00
return true ;
} else {
return false ;
}
2005-07-11 10:54:53 +00:00
}
2010-04-04 22:08:18 +00:00
2011-06-19 20:08:55 +02:00
bool SurfaceSdlGraphicsManager : : isScalerHotkey ( const Common : : Event & event ) {
2010-04-04 22:08:18 +00:00
if ( ( event . kbd . flags & ( Common : : KBD_CTRL | Common : : KBD_ALT ) ) = = ( Common : : KBD_CTRL | Common : : KBD_ALT ) ) {
const bool isNormalNumber = ( Common : : KEYCODE_1 < = event . kbd . keycode & & event . kbd . keycode < = Common : : KEYCODE_9 ) ;
const bool isKeypadNumber = ( Common : : KEYCODE_KP1 < = event . kbd . keycode & & event . kbd . keycode < = Common : : KEYCODE_KP9 ) ;
const bool isScaleKey = ( event . kbd . keycode = = Common : : KEYCODE_EQUALS | | event . kbd . keycode = = Common : : KEYCODE_PLUS | | event . kbd . keycode = = Common : : KEYCODE_MINUS | |
event . kbd . keycode = = Common : : KEYCODE_KP_PLUS | | event . kbd . keycode = = Common : : KEYCODE_KP_MINUS ) ;
if ( isNormalNumber | | isKeypadNumber ) {
int keyValue = event . kbd . keycode - ( isNormalNumber ? Common : : KEYCODE_1 : Common : : KEYCODE_KP1 ) ;
if ( keyValue > = ARRAYSIZE ( s_gfxModeSwitchTable ) )
return false ;
}
2016-10-12 23:33:28 +01:00
# if SDL_VERSION_ATLEAST(2, 0, 0)
if ( event . kbd . keycode = = ' f ' )
return true ;
# endif
2010-04-04 22:08:18 +00:00
return ( isScaleKey | | event . kbd . keycode = = ' a ' ) ;
}
return false ;
}
2010-06-09 05:29:14 +00:00
2011-06-19 20:08:55 +02:00
void SurfaceSdlGraphicsManager : : toggleFullScreen ( ) {
2010-06-16 04:34:44 +00:00
beginGFXTransaction ( ) ;
setFullscreenMode ( ! _videoMode . fullscreen ) ;
endGFXTransaction ( ) ;
# ifdef USE_OSD
if ( _videoMode . fullscreen )
2011-06-06 20:08:28 +01:00
displayMessageOnOSD ( _ ( " Fullscreen mode " ) ) ;
2010-06-16 04:34:44 +00:00
else
2011-06-06 20:08:28 +01:00
displayMessageOnOSD ( _ ( " Windowed mode " ) ) ;
2010-06-16 04:34:44 +00:00
# endif
}
2011-06-19 20:08:55 +02:00
bool SurfaceSdlGraphicsManager : : notifyEvent ( const Common : : Event & event ) {
2010-07-19 05:33:58 +00:00
switch ( ( int ) event . type ) {
2010-07-15 01:21:20 +00:00
case Common : : EVENT_KEYDOWN :
// Alt-Return and Alt-Enter toggle full screen mode
if ( event . kbd . hasFlags ( Common : : KBD_ALT ) & &
( event . kbd . keycode = = Common : : KEYCODE_RETURN | |
2010-07-15 01:48:28 +00:00
event . kbd . keycode = = ( Common : : KeyCode ) SDLK_KP_ENTER ) ) {
2010-07-15 01:21:20 +00:00
toggleFullScreen ( ) ;
return true ;
}
// Alt-S: Create a screenshot
if ( event . kbd . hasFlags ( Common : : KBD_ALT ) & & event . kbd . keycode = = ' s ' ) {
2017-03-24 22:25:46 +01:00
Common : : String filename ;
2017-04-24 00:28:37 +01:00
Common : : String screenshotsPath ;
OSystem_SDL * sdl_g_system = dynamic_cast < OSystem_SDL * > ( g_system ) ;
if ( sdl_g_system )
screenshotsPath = sdl_g_system - > getScreenshotsPath ( ) ;
2010-07-15 01:21:20 +00:00
for ( int n = 0 ; ; n + + ) {
SDL_RWops * file ;
2017-05-12 12:44:44 -05:00
# ifdef USE_PNG
filename = Common : : String : : format ( " scummvm%05d.png " , n ) ;
# else
2017-03-24 22:25:46 +01:00
filename = Common : : String : : format ( " scummvm%05d.bmp " , n ) ;
2017-05-12 12:44:44 -05:00
# endif
2017-03-24 22:25:46 +01:00
file = SDL_RWFromFile ( ( screenshotsPath + filename ) . c_str ( ) , " r " ) ;
2010-07-15 01:21:20 +00:00
if ( ! file )
break ;
SDL_RWclose ( file ) ;
}
2017-03-24 22:25:46 +01:00
2017-04-24 01:06:03 +01:00
if ( saveScreenshot ( ( screenshotsPath + filename ) . c_str ( ) ) ) {
if ( screenshotsPath . empty ( ) )
debug ( " Saved screenshot '%s' in current directory " , filename . c_str ( ) ) ;
else
debug ( " Saved screenshot '%s' in directory '%s' " , filename . c_str ( ) , screenshotsPath . c_str ( ) ) ;
} else {
if ( screenshotsPath . empty ( ) )
warning ( " Could not save screenshot in current directory " ) ;
else
warning ( " Could not save screenshot in directory '%s' " , screenshotsPath . c_str ( ) ) ;
}
2017-03-24 22:25:46 +01:00
2010-07-15 01:21:20 +00:00
return true ;
}
// Ctrl-Alt-<key> will change the GFX mode
2010-07-27 07:30:56 +00:00
if ( event . kbd . hasFlags ( Common : : KBD_CTRL | Common : : KBD_ALT ) ) {
2010-07-15 01:21:20 +00:00
if ( handleScalerHotkeys ( event . kbd . keycode ) )
return true ;
}
2011-08-08 23:56:54 +02:00
2017-08-11 21:59:59 +02:00
break ;
2010-07-15 01:21:20 +00:00
case Common : : EVENT_KEYUP :
return isScalerHotkey ( event ) ;
2011-08-08 23:56:54 +02:00
2010-07-15 01:48:28 +00:00
default :
break ;
2010-07-15 01:21:20 +00:00
}
return false ;
}
2011-08-08 23:46:05 +02:00
void SurfaceSdlGraphicsManager : : notifyVideoExpose ( ) {
_forceFull = true ;
}
2015-12-18 19:08:26 +01:00
void SurfaceSdlGraphicsManager : : notifyResize ( const uint width , const uint height ) {
# if SDL_VERSION_ATLEAST(2, 0, 0)
setWindowResolution ( width , height ) ;
# endif
}
2011-08-08 23:46:05 +02:00
void SurfaceSdlGraphicsManager : : transformMouseCoordinates ( Common : : Point & point ) {
2015-12-08 15:40:35 +01:00
# if SDL_VERSION_ATLEAST(2, 0, 0)
2015-12-13 20:20:23 +01:00
// In SDL2 the actual output resolution might be different from what we
// requested. Thus, we transform the coordinates from actual output
// coordinate space into the "virtual" output coordinate space.
// Please note that we ignore the possible existence of black bars here,
// this avoids the feeling of stickyness to black bars.
point . x = point . x * _videoMode . hardwareWidth / _windowWidth ;
point . y = point . y * _videoMode . hardwareHeight / _windowHeight ;
2015-12-08 15:40:35 +01:00
# endif
2011-08-08 23:46:05 +02:00
if ( ! _overlayVisible ) {
point . x / = _videoMode . scaleFactor ;
point . y / = _videoMode . scaleFactor ;
if ( _videoMode . aspectRatioCorrection )
point . y = aspect2Real ( point . y ) ;
}
}
void SurfaceSdlGraphicsManager : : notifyMousePos ( Common : : Point mouse ) {
transformMouseCoordinates ( mouse ) ;
setMousePos ( mouse . x , mouse . y ) ;
}
2015-01-25 01:34:57 +01:00
# if SDL_VERSION_ATLEAST(2, 0, 0)
void SurfaceSdlGraphicsManager : : deinitializeRenderer ( ) {
SDL_DestroyTexture ( _screenTexture ) ;
_screenTexture = nullptr ;
SDL_DestroyRenderer ( _renderer ) ;
_renderer = nullptr ;
}
2015-12-18 19:08:26 +01:00
void SurfaceSdlGraphicsManager : : setWindowResolution ( int width , int height ) {
_windowWidth = width ;
_windowHeight = height ;
2015-01-25 01:34:57 +01:00
2015-12-13 20:20:23 +01:00
// We expect full screen resolution as inputs coming from the event system.
2016-10-18 19:24:51 +03:00
_eventSource - > resetKeyboardEmulation ( _windowWidth - 1 , _windowHeight - 1 ) ;
2015-12-13 20:20:23 +01:00
// Calculate the "viewport" for the actual area we draw in. In fullscreen
// we can easily get a different resolution than what we requested. In
// this case, we add black bars if necessary to assure the aspect ratio
// is preserved.
const frac_t outputAspect = intToFrac ( _windowWidth ) / _windowHeight ;
2015-12-18 19:08:26 +01:00
const frac_t desiredAspect = intToFrac ( _videoMode . hardwareWidth ) / _videoMode . hardwareHeight ;
2015-12-08 13:21:05 +01:00
2015-12-13 20:20:23 +01:00
_viewport . w = _windowWidth ;
_viewport . h = _windowHeight ;
2015-12-08 15:40:35 +01:00
2015-12-13 20:20:23 +01:00
// Adjust one dimension for mantaining the aspect ratio.
if ( abs ( outputAspect - desiredAspect ) > = ( int ) ( FRAC_ONE / 1000 ) ) {
if ( outputAspect < desiredAspect ) {
2015-12-18 19:08:26 +01:00
_viewport . h = _videoMode . hardwareHeight * _windowWidth / _videoMode . hardwareWidth ;
2015-12-13 20:20:23 +01:00
} else if ( outputAspect > desiredAspect ) {
2015-12-18 19:08:26 +01:00
_viewport . w = _videoMode . hardwareWidth * _windowHeight / _videoMode . hardwareHeight ;
2015-12-13 20:20:23 +01:00
}
}
2015-12-08 15:40:35 +01:00
2015-12-13 20:20:23 +01:00
_viewport . x = ( _windowWidth - _viewport . w ) / 2 ;
_viewport . y = ( _windowHeight - _viewport . h ) / 2 ;
2015-12-08 15:40:35 +01:00
2015-12-18 19:08:26 +01:00
// Force a full redraw because we changed the viewport.
_forceFull = true ;
}
2016-10-13 00:19:15 +01:00
void SurfaceSdlGraphicsManager : : recreateScreenTexture ( ) {
if ( ! _renderer )
return ;
SDL_SetHint ( SDL_HINT_RENDER_SCALE_QUALITY , _videoMode . filtering ? " linear " : " nearest " ) ;
2016-11-13 16:36:18 +01:00
2016-10-13 00:19:15 +01:00
SDL_Texture * oldTexture = _screenTexture ;
_screenTexture = SDL_CreateTexture ( _renderer , SDL_PIXELFORMAT_RGB565 , SDL_TEXTUREACCESS_STREAMING , _videoMode . hardwareWidth , _videoMode . hardwareHeight ) ;
if ( _screenTexture )
SDL_DestroyTexture ( oldTexture ) ;
else
_screenTexture = oldTexture ;
}
2015-12-18 19:08:26 +01:00
SDL_Surface * SurfaceSdlGraphicsManager : : SDL_SetVideoMode ( int width , int height , int bpp , Uint32 flags ) {
deinitializeRenderer ( ) ;
uint32 createWindowFlags = 0 ;
# ifdef USE_SDL_RESIZABLE_WINDOW
createWindowFlags | = SDL_WINDOW_RESIZABLE ;
# endif
if ( ( flags & SDL_FULLSCREEN ) ! = 0 ) {
createWindowFlags | = SDL_WINDOW_FULLSCREEN_DESKTOP ;
}
2017-08-27 22:21:05 -05:00
if ( ! createOrUpdateWindow ( width , height , createWindowFlags ) ) {
2015-12-18 19:08:26 +01:00
return nullptr ;
}
_renderer = SDL_CreateRenderer ( _window - > getSDLWindow ( ) , - 1 , 0 ) ;
if ( ! _renderer ) {
deinitializeRenderer ( ) ;
return nullptr ;
}
SDL_GetWindowSize ( _window - > getSDLWindow ( ) , & _windowWidth , & _windowHeight ) ;
setWindowResolution ( _windowWidth , _windowHeight ) ;
2016-11-13 16:36:18 +01:00
2016-10-12 22:38:07 +01:00
SDL_SetHint ( SDL_HINT_RENDER_SCALE_QUALITY , _videoMode . filtering ? " linear " : " nearest " ) ;
2015-12-18 19:08:26 +01:00
2015-01-25 01:34:57 +01:00
_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 ) ;
2015-12-13 20:20:23 +01:00
SDL_RenderCopy ( _renderer , _screenTexture , NULL , & _viewport ) ;
2015-01-25 01:34:57 +01:00
SDL_RenderPresent ( _renderer ) ;
}
# endif // SDL_VERSION_ATLEAST(2, 0, 0)
2010-06-09 05:29:14 +00:00
# endif