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 .
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
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
2010-06-05 22:45:36 +00:00
# include "backends/graphics/sdl/sdl-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"
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"
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 " )
2005-02-17 23:01:00 +00:00
// Table of relative scalers magnitudes
2008-11-14 22:08:10 +00:00
// [definedScale - 1][scaleFactor - 1]
2005-02-17 23:01:00 +00:00
static ScalerProc * scalersMagn [ 3 ] [ 3 ] = {
2010-05-10 17:25:12 +00:00
# ifdef USE_SCALERS
2005-02-17 23:01:00 +00:00
{ Normal1x , AdvMame2x , AdvMame3x } ,
{ Normal1x , Normal1x , Normal1o5x } ,
{ Normal1x , Normal1x , Normal1x }
2005-06-21 20:39:09 +00:00
# else // remove dependencies on other scalers
{ Normal1x , Normal1x , Normal1x } ,
{ Normal1x , Normal1x , Normal1x } ,
{ Normal1x , Normal1x , Normal1x }
# 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
2010-10-13 15:42:53 +00:00
SdlGraphicsManager : : SdlGraphicsManager ( SdlEventSource * sdlEventSource )
2010-06-07 03:14:42 +00:00
:
2010-10-13 15:42:53 +00:00
_sdlEventSource ( sdlEventSource ) ,
2010-06-07 03:14:42 +00:00
# ifdef USE_OSD
_osdSurface ( 0 ) , _osdAlpha ( SDL_ALPHA_TRANSPARENT ) , _osdFadeStartTime ( 0 ) ,
# endif
_hwscreen ( 0 ) , _screen ( 0 ) , _tmpscreen ( 0 ) ,
# 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 ) ,
_mouseOrigSurface ( 0 ) , _cursorTargetScale ( 1 ) , _cursorPaletteDisabled ( true ) ,
_currentShakePos ( 0 ) , _newShakePos ( 0 ) ,
_paletteDirtyStart ( 0 ) , _paletteDirtyEnd ( 0 ) ,
_screenIsLocked ( false ) ,
2011-02-24 01:11:16 +01:00
_graphicsMutex ( 0 ) ,
# 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
if ( SDL_InitSubSystem ( SDL_INIT_VIDEO ) = = - 1 ) {
error ( " Could not initialize SDL: %s " , SDL_GetError ( ) ) ;
}
2010-11-28 17:12:43 +00:00
// This is also called in initSDL(), but initializing graphics
// may reset it.
SDL_EnableUNICODE ( 1 ) ;
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
SDL_ShowCursor ( SDL_DISABLE ) ;
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
}
SdlGraphicsManager : : ~ SdlGraphicsManager ( ) {
2010-07-16 23:50:46 +00:00
// Unregister the event observer
if ( g_system - > getEventManager ( ) - > getEventDispatcher ( ) ! = NULL )
g_system - > getEventManager ( ) - > getEventDispatcher ( ) - > unregisterObserver ( this ) ;
2010-06-07 03:14:42 +00:00
unloadGFXMode ( ) ;
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 ) ;
}
2010-09-03 04:23:01 +00:00
void SdlGraphicsManager : : initEventObserver ( ) {
// Register the graphics manager as a event observer
g_system - > getEventManager ( ) - > getEventDispatcher ( ) - > registerObserver ( this , 10 , false ) ;
}
2010-06-07 03:14:42 +00:00
bool SdlGraphicsManager : : hasFeature ( OSystem : : Feature f ) {
return
( f = = OSystem : : kFeatureFullscreenMode ) | |
( f = = OSystem : : kFeatureAspectRatioCorrection ) | |
2011-06-03 23:30:55 +02:00
( f = = OSystem : : kFeatureCursorPalette ) | |
2010-06-07 03:14:42 +00:00
( f = = OSystem : : kFeatureIconifyWindow ) ;
}
void SdlGraphicsManager : : setFeatureState ( OSystem : : Feature f , bool enable ) {
switch ( f ) {
case OSystem : : kFeatureFullscreenMode :
setFullscreenMode ( enable ) ;
break ;
case OSystem : : kFeatureAspectRatioCorrection :
setAspectRatioCorrection ( enable ) ;
break ;
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 )
SDL_WM_IconifyWindow ( ) ;
break ;
default :
break ;
}
}
bool SdlGraphicsManager : : getFeatureState ( OSystem : : Feature f ) {
2011-06-04 00:14:09 +02:00
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 ;
2011-06-04 00:14:09 +02:00
case OSystem : : kFeatureCursorPalette :
return ! _cursorPaletteDisabled ;
2010-06-07 03:14:42 +00:00
default :
return false ;
}
}
2010-07-30 03:31:05 +00:00
const OSystem : : GraphicsMode * SdlGraphicsManager : : supportedGraphicsModes ( ) {
2004-02-29 00:49:40 +00:00
return s_supportedGraphicsModes ;
}
2010-06-05 22:45:36 +00:00
const OSystem : : GraphicsMode * SdlGraphicsManager : : getSupportedGraphicsModes ( ) const {
return s_supportedGraphicsModes ;
}
int SdlGraphicsManager : : getDefaultGraphicsMode ( ) const {
2004-03-15 00:45:45 +00:00
return GFX_DOUBLESIZE ;
}
2010-07-30 03:06:57 +00:00
void SdlGraphicsManager : : resetGraphicsScale ( ) {
setGraphicsMode ( s_gfxModeSwitchTable [ _scalerType ] [ 0 ] ) ;
}
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : 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
_transactionDetails . normal1xScaler = false ;
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
}
2010-06-05 22:45:36 +00:00
OSystem : : TransactionError SdlGraphicsManager : : endGFXTransaction ( ) {
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 ;
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 & &
_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
}
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
2010-07-13 04:31:15 +00:00
Common : : List < Graphics : : PixelFormat > SdlGraphicsManager : : getSupportedFormats ( ) const {
2010-07-12 23:18:44 +00:00
assert ( ! _supportedFormats . empty ( ) ) ;
return _supportedFormats ;
}
2010-07-13 04:31:15 +00:00
void SdlGraphicsManager : : detectSupportedFormats ( ) {
2010-07-12 23:18:44 +00:00
// Clear old list
_supportedFormats . clear ( ) ;
// 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 [ ] = {
2010-09-28 20:29:25 +00:00
# ifdef USE_RGB_COLOR
2010-07-12 23:18:44 +00:00
// 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 ) ,
2009-07-10 06:46:50 +00:00
# endif
2010-07-12 23:18:44 +00:00
// 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 [ ] = {
2010-09-28 20:29:25 +00:00
# ifdef USE_RGB_COLOR
2010-07-12 23:18:44 +00:00
// 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 ) ,
2009-07-10 06:46:50 +00:00
# endif
2010-07-12 23:18:44 +00:00
// 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
Graphics : : PixelFormat format = Graphics : : PixelFormat : : createFormatCLUT8 ( ) ;
if ( _hwscreen ) {
// Get our currently set hardware format
2010-01-25 01:39:44 +00:00
format = Graphics : : PixelFormat ( _hwscreen - > format - > BytesPerPixel ,
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 ) ;
// Workaround to MacOSX SDL not providing an accurate Aloss value.
if ( _hwscreen - > format - > Amask = = 0 )
format . aLoss = 8 ;
// Push it first, as the prefered format.
2010-07-12 23:18:44 +00:00
_supportedFormats . push_back ( format ) ;
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
2010-06-05 22:45:36 +00:00
bool SdlGraphicsManager : : 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 :
newScaleFactor = 2 ;
break ;
case GFX_TRIPLESIZE :
newScaleFactor = 3 ;
break ;
case GFX_2XSAI :
newScaleFactor = 2 ;
break ;
case GFX_SUPER2XSAI :
newScaleFactor = 2 ;
break ;
case GFX_SUPEREAGLE :
newScaleFactor = 2 ;
break ;
case GFX_ADVMAME2X :
newScaleFactor = 2 ;
break ;
case GFX_ADVMAME3X :
newScaleFactor = 3 ;
break ;
2010-05-09 11:00:17 +00:00
# ifdef USE_HQ_SCALERS
2004-02-29 00:49:40 +00:00
case GFX_HQ2X :
newScaleFactor = 2 ;
break ;
case GFX_HQ3X :
newScaleFactor = 3 ;
break ;
2005-05-14 22:56:41 +00:00
# endif
2010-05-10 17:25:12 +00:00
case GFX_TV2X :
newScaleFactor = 2 ;
break ;
case GFX_DOTMATRIX :
newScaleFactor = 2 ;
break ;
# endif // USE_SCALERS
2004-02-29 00:49:40 +00:00
default :
warning ( " unknown gfx mode %d " , mode ) ;
return false ;
}
2005-03-20 16:16:09 +00:00
_transactionDetails . normal1xScaler = ( mode = = GFX_NORMAL ) ;
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
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : setGraphicsModeIntern ( ) {
2008-11-14 22:08:10 +00:00
Common : : StackLock lock ( _graphicsMutex ) ;
ScalerProc * newScalerProc = 0 ;
2005-02-22 01:29:27 +00:00
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
}
2010-06-05 22:45:36 +00:00
int SdlGraphicsManager : : getGraphicsMode ( ) const {
2004-11-23 21:30:38 +00: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
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : 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
// Avoid redundant res changes
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 ;
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
}
2010-06-05 22:45:36 +00:00
int SdlGraphicsManager : : 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 ;
SDL_Rect const * const * availableModes = SDL_ListModes ( NULL , SDL_FULLSCREEN | SDL_SWSURFACE ) ; //TODO : Maybe specify a pixel format
assert ( availableModes ) ;
const SDL_Rect * bestMode = NULL ;
uint bestMetric = ( uint ) - 1 ; // Metric is wasted space
while ( const SDL_Rect * mode = * availableModes + + ) {
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 ;
bestMode = mode ;
}
if ( ! bestMode ) {
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 ;
}
width = bestMode - > w ;
height = bestMode - > h ;
}
2010-06-05 22:45:36 +00:00
bool SdlGraphicsManager : : 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 ( ) ;
2006-06-03 01:05:09 +00:00
# else
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 " ) ;
# 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
//
// 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 ) ;
}
_hwscreen = SDL_SetVideoMode ( _videoMode . hardwareWidth , _videoMode . hardwareHeight , 16 ,
2008-11-14 22:08:10 +00:00
_videoMode . fullscreen ? ( SDL_FULLSCREEN | SDL_SWSURFACE ) : SDL_SWSURFACE
2004-02-29 00:49:40 +00:00
) ;
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 " ) ;
2004-03-13 14:19:15 +00:00
# ifdef USE_OSD
_osdSurface = SDL_CreateRGBSurface ( SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA ,
_hwscreen - > w ,
_hwscreen - > h ,
16 ,
_hwscreen - > format - > Rmask ,
_hwscreen - > format - > Gmask ,
_hwscreen - > format - > Bmask ,
_hwscreen - > format - > Amask ) ;
if ( _osdSurface = = NULL )
error ( " allocating _osdSurface failed " ) ;
SDL_SetColorKey ( _osdSurface , SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA , kOSDColorKey ) ;
# endif
2004-02-29 00:49:40 +00:00
2010-10-13 15:42:53 +00:00
_sdlEventSource - > resetKeyboadEmulation (
2010-06-16 04:34:44 +00:00
_videoMode . screenWidth * _videoMode . scaleFactor - 1 ,
effectiveScreenHeight ( ) - 1 ) ;
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
}
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : 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
}
if ( _hwscreen ) {
2005-07-30 21:11:48 +00: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
if ( _osdSurface ) {
SDL_FreeSurface ( _osdSurface ) ;
_osdSurface = NULL ;
}
# endif
2008-03-26 19:29:33 +00:00
DestroyScalers ( ) ;
2004-02-29 00:49:40 +00:00
}
2010-06-05 22:45:36 +00:00
bool SdlGraphicsManager : : 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
2008-11-14 22:08:10 +00:00
SDL_FreeSurface ( _hwscreen ) ; _hwscreen = NULL ;
2004-02-29 00:49:40 +00:00
2008-11-14 22:08:10 +00:00
SDL_FreeSurface ( _tmpscreen ) ; _tmpscreen = NULL ;
SDL_FreeSurface ( _tmpscreen2 ) ; _tmpscreen2 = NULL ;
2005-03-09 23:07:32 +00:00
2004-03-13 14:19:15 +00:00
# ifdef USE_OSD
// Release the OSD surface
2008-11-14 22:08:10 +00:00
SDL_FreeSurface ( _osdSurface ) ; _osdSurface = NULL ;
2004-03-13 14:19:15 +00:00
# endif
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
}
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : updateScreen ( ) {
2004-11-23 21:30:38 +00:00
assert ( _transactionMode = = kTransactionNone ) ;
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 ( ) ;
}
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : 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?)
# 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 ) ) {
2008-11-14 22:08:10 +00:00
SDL_Rect blackrect = { 0 , 0 , _videoMode . screenWidth * _videoMode . scaleFactor , _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 ;
}
2004-03-13 14:19:15 +00:00
# ifdef USE_OSD
// OSD visible (i.e. non-transparent)?
if ( _osdAlpha ! = SDL_ALPHA_TRANSPARENT ) {
// Updated alpha value
const int diff = SDL_GetTicks ( ) - _osdFadeStartTime ;
if ( diff > 0 ) {
if ( diff > = kOSDFadeOutDuration ) {
// Back to full transparency
_osdAlpha = SDL_ALPHA_TRANSPARENT ;
} else {
// Do a linear fade out...
const int startAlpha = SDL_ALPHA_TRANSPARENT + kOSDInitialAlpha * ( SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT ) / 100 ;
_osdAlpha = startAlpha + diff * ( SDL_ALPHA_TRANSPARENT - startAlpha ) / kOSDFadeOutDuration ;
}
SDL_SetAlpha ( _osdSurface , SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA , _osdAlpha ) ;
_forceFull = true ;
}
}
# endif
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 ( ) ;
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 ;
register int orig_dst_y = 0 ;
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
2007-08-11 08:44:43 +00:00
orig_dst_y = dst_y ;
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
if ( _osdAlpha ! = SDL_ALPHA_TRANSPARENT ) {
SDL_BlitSurface ( _osdSurface , 0 , _hwscreen , 0 ) ;
}
# 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
2004-12-01 21:16:55 +00:00
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
}
2010-06-05 22:45:36 +00:00
bool SdlGraphicsManager : : saveScreenshot ( const char * filename ) {
2004-02-29 00:49:40 +00:00
assert ( _hwscreen ! = NULL ) ;
2004-03-28 20:31:18 +00:00
Common : : StackLock lock ( _graphicsMutex ) ; // Lock the mutex until this function ends
2004-12-01 21:16:55 +00:00
return SDL_SaveBMP ( _hwscreen , filename ) = = 0 ;
2004-02-29 00:49:40 +00:00
}
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : 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
}
}
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : 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
}
}
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : copyRectToScreen ( const byte * src , int pitch , int x , int y , int w , int h ) {
2004-11-23 21:30:38 +00:00
assert ( _transactionMode = = kTransactionNone ) ;
2005-03-12 16:32:32 +00:00
assert ( src ) ;
2004-11-23 21:30:38 +00:00
2006-07-23 06:50:49 +00:00
if ( _screen = = NULL ) {
2010-06-05 22:45:36 +00:00
warning ( " SdlGraphicsManager::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 ) {
memcpy ( dst , src , h * pitch ) ;
2009-06-03 23:36:23 +00:00
} else {
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 ) {
2004-02-29 00:49:40 +00:00
memcpy ( dst , src , h * w ) ;
} else {
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 ) ;
}
2010-06-05 22:45:36 +00:00
Graphics : : Surface * SdlGraphicsManager : : lockScreen ( ) {
2007-06-19 22:39:59 +00: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
2007-06-19 22:39:59 +00:00
_framebuffer . pixels = _screen - > pixels ;
_framebuffer . w = _screen - > w ;
_framebuffer . h = _screen - > h ;
_framebuffer . pitch = _screen - > pitch ;
2009-08-21 18:16:37 +00:00
# ifdef USE_RGB_COLOR
2011-04-17 17:26:04 +02:00
_framebuffer . format = _screenFormat ;
2009-06-10 05:35:18 +00:00
# else
2011-04-17 17:26:04 +02:00
_framebuffer . format = Graphics : : PixelFormat : : createFormatCLUT8 ( ) ;
2009-06-03 23:36:23 +00:00
# endif
2007-06-19 22:39:59 +00:00
return & _framebuffer ;
}
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : unlockScreen ( ) {
2007-06-19 22:39:59 +00:00
assert ( _transactionMode = = kTransactionNone ) ;
// 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
2010-06-08 23:44:05 +00:00
void SdlGraphicsManager : : fillScreen ( uint32 col ) {
Graphics : : Surface * screen = lockScreen ( ) ;
if ( screen & & screen - > pixels )
memset ( screen - > pixels , col , screen - > h * screen - > pitch ) ;
unlockScreen ( ) ;
}
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : 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
}
2010-06-05 22:45:36 +00:00
int16 SdlGraphicsManager : : getHeight ( ) {
2008-11-14 22:08:10 +00:00
return _videoMode . screenHeight ;
2004-02-29 00:49:40 +00:00
}
2010-06-05 22:45:36 +00:00
int16 SdlGraphicsManager : : getWidth ( ) {
2008-11-14 22:08:10 +00:00
return _videoMode . screenWidth ;
2004-02-29 00:49:40 +00:00
}
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : 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 )
2010-06-05 22:45:36 +00:00
warning ( " SdlGraphicsManager::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 ] ;
}
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 ( ) ;
}
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : 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
}
}
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : 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 ] ;
}
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
}
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : setShakePos ( int shake_pos ) {
2004-11-23 21:30:38 +00:00
assert ( _transactionMode = = kTransactionNone ) ;
2004-02-29 00:49:40 +00:00
_newShakePos = shake_pos ;
}
2011-02-24 01:11:16 +01:00
void SdlGraphicsManager : : setFocusRectangle ( const Common : : Rect & rect ) {
# 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 )
warning ( " SdlGraphicsManager::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: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
}
void SdlGraphicsManager : : 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 -
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : showOverlay ( ) {
2004-11-23 21:30:38 +00:00
assert ( _transactionMode = = kTransactionNone ) ;
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
}
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : hideOverlay ( ) {
2004-11-23 21:30:38 +00:00
assert ( _transactionMode = = kTransactionNone ) ;
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 ;
}
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : clearOverlay ( ) {
2005-03-09 23:07:32 +00: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 ;
}
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : grabOverlay ( OverlayColor * buf , int pitch ) {
2004-11-23 21:30:38 +00:00
assert ( _transactionMode = = kTransactionNone ) ;
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 ;
2008-11-14 22:08:10 +00:00
int h = _videoMode . overlayHeight ;
2004-02-29 00:49:40 +00:00
do {
2008-11-14 22:08:10 +00:00
memcpy ( buf , src , _videoMode . overlayWidth * 2 ) ;
2005-03-09 23:07:32 +00:00
src + = _overlayscreen - > pitch ;
2004-02-29 00:49:40 +00:00
buf + = pitch ;
} while ( - - h ) ;
2005-03-09 23:07:32 +00:00
SDL_UnlockSurface ( _overlayscreen ) ;
2004-02-29 00:49:40 +00:00
}
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : copyRectToOverlay ( const OverlayColor * buf , int pitch , int x , int y , int w , int h ) {
2004-11-23 21:30:38 +00:00
assert ( _transactionMode = = kTransactionNone ) ;
2005-03-09 23:07:32 +00:00
if ( _overlayscreen = = NULL )
2004-02-29 00:49:40 +00:00
return ;
// Clip the coordinates
if ( x < 0 ) {
w + = x ;
buf - = x ;
x = 0 ;
}
if ( y < 0 ) {
h + = y ; buf - = y * pitch ;
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 {
memcpy ( dst , buf , w * 2 ) ;
2005-03-09 23:07:32 +00:00
dst + = _overlayscreen - > pitch ;
2004-02-29 00:49:40 +00:00
buf + = pitch ;
} 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 -
2010-06-05 22:45:36 +00:00
bool SdlGraphicsManager : : 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 ;
}
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : 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 ;
}
}
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : warpMouse ( int x , int y ) {
2006-05-17 23:52:45 +00:00
int y1 = 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)
if ( ! ( SDL_GetAppState ( ) & SDL_APPMOUSEFOCUS ) ) {
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
2009-05-01 09:09:07 +00:00
if ( _videoMode . aspectRatioCorrection & & ! _overlayVisible )
2006-05-17 23:52:45 +00:00
y1 = real2Aspect ( y ) ;
2006-02-26 14:31:44 +00:00
2004-02-29 00:49:40 +00:00
if ( _mouseCurState . x ! = x | | _mouseCurState . y ! = y ) {
2008-01-27 19:47:41 +00:00
if ( ! _overlayVisible )
2008-11-14 22:08:10 +00:00
SDL_WarpMouse ( x * _videoMode . scaleFactor , y1 * _videoMode . scaleFactor ) ;
2006-05-27 12:39:55 +00:00
else
SDL_WarpMouse ( x , 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
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : setMouseCursor ( const byte * buf , uint w , uint h , int hotspot_x , int hotspot_y , uint32 keycolor , int cursorTargetScale , 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 ;
_cursorTargetScale = cursorTargetScale ;
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
}
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : 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 ;
2004-02-29 00:49:40 +00:00
2008-11-14 22:08:10 +00:00
if ( _cursorTargetScale > = _videoMode . scaleFactor ) {
2006-06-04 12:38:27 +00:00
// The cursor target scale is greater or equal to the scale at
// which the rest of the screen is drawn. We do not downscale
// the cursor image, we draw it at its original size. It will
// appear too large on screen.
rW = w ;
rH = h ;
_mouseCurState . rHotX = _mouseCurState . hotX ;
_mouseCurState . rHotY = _mouseCurState . hotY ;
// The virtual dimensions may be larger than the original.
2008-11-14 22:08:10 +00:00
_mouseCurState . vW = w * _cursorTargetScale / _videoMode . scaleFactor ;
_mouseCurState . vH = h * _cursorTargetScale / _videoMode . scaleFactor ;
2006-06-04 12:38:27 +00:00
_mouseCurState . vHotX = _mouseCurState . hotX * _cursorTargetScale /
2008-11-14 22:08:10 +00:00
_videoMode . scaleFactor ;
2006-06-04 12:38:27 +00:00
_mouseCurState . vHotY = _mouseCurState . hotY * _cursorTargetScale /
2008-11-14 22:08:10 +00:00
_videoMode . scaleFactor ;
2005-02-17 23:01:00 +00:00
} else {
2006-06-04 12:38:27 +00:00
// The cursor target scale is smaller than the scale at which
// the rest of the screen is drawn. We scale up the cursor
// image to make it appear correct.
2008-11-14 22:08:10 +00:00
rW = w * _videoMode . scaleFactor / _cursorTargetScale ;
rH = h * _videoMode . scaleFactor / _cursorTargetScale ;
_mouseCurState . rHotX = _mouseCurState . hotX * _videoMode . scaleFactor /
2006-05-25 19:43:33 +00:00
_cursorTargetScale ;
2008-11-14 22:08:10 +00:00
_mouseCurState . rHotY = _mouseCurState . hotY * _videoMode . scaleFactor /
2006-05-25 19:43:33 +00:00
_cursorTargetScale ;
2006-06-04 12:38:27 +00:00
// The virtual dimensions will be the same as the original.
_mouseCurState . vW = w ;
_mouseCurState . vH = h ;
_mouseCurState . vHotX = _mouseCurState . hotX ;
_mouseCurState . vHotY = _mouseCurState . hotY ;
2008-01-28 00:14:17 +00:00
}
2005-07-30 21:11:48 +00:00
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
2009-05-01 09:09:07 +00:00
if ( _videoMode . aspectRatioCorrection & & _cursorTargetScale = = 1 ) {
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 ;
// 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, 1.5x, 2x and AdvMame scalers.
2010-05-10 17:25:12 +00:00
if ( _cursorTargetScale = = 1 & & ( _videoMode . mode = = GFX_DOUBLESIZE | | _videoMode . mode = = GFX_TRIPLESIZE ) )
2005-03-17 09:49:22 +00:00
scalerProc = _scalerProc ;
else
2008-11-14 22:08:10 +00:00
scalerProc = scalersMagn [ _cursorTargetScale - 1 ] [ _videoMode . scaleFactor - 1 ] ;
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
2009-05-01 09:09:07 +00:00
if ( _videoMode . aspectRatioCorrection & & _cursorTargetScale = = 1 )
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
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : 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 )
2010-07-23 16:38:31 +00:00
addDirtyRect ( x , y - _currentShakePos , _mouseBackup . w , _mouseBackup . h ) ;
2005-02-17 23:01:00 +00:00
}
2004-03-01 11:20:32 +00:00
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : 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.
if ( ! _overlayVisible ) {
dst . y + = _currentShakePos ;
}
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
2010-06-05 22:45:36 +00:00
void SdlGraphicsManager : : displayMessageOnOSD ( const char * msg ) {
2004-11-23 21:30:38 +00: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
2004-03-15 19:07:56 +00:00
uint i ;
2005-07-30 21:11:48 +00:00
2004-03-15 19:07:56 +00:00
// Lock the OSD surface for drawing
2004-03-13 14:19:15 +00:00
if ( SDL_LockSurface ( _osdSurface ) )
error ( " displayMessageOnOSD: SDL_LockSurface failed: %s " , SDL_GetError ( ) ) ;
2004-03-21 21:20:25 +00:00
Graphics : : Surface dst ;
2004-03-13 14:19:15 +00:00
dst . pixels = _osdSurface - > pixels ;
dst . w = _osdSurface - > w ;
dst . h = _osdSurface - > h ;
dst . pitch = _osdSurface - > pitch ;
2011-04-17 17:26:04 +02:00
dst . format = Graphics : : PixelFormat ( _osdSurface - > format - > BytesPerPixel ,
8 - _osdSurface - > format - > Rloss , 8 - _osdSurface - > format - > Gloss ,
8 - _osdSurface - > format - > Bloss , 8 - _osdSurface - > format - > Aloss ,
_osdSurface - > format - > Rshift , _osdSurface - > format - > Gshift ,
_osdSurface - > format - > Bshift , _osdSurface - > format - > Ashift ) ;
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-13 14:19:15 +00:00
// Clear everything with the "transparent" color, i.e. the colorkey
SDL_FillRect ( _osdSurface , 0 , kOSDColorKey ) ;
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 ;
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
2004-03-13 14:19:15 +00:00
if ( width > dst . w )
width = dst . w ;
if ( height > dst . h )
height = dst . h ;
// Draw a dark gray rect
// TODO: Rounded corners ? Border?
SDL_Rect osdRect ;
osdRect . x = ( dst . w - width ) / 2 ;
osdRect . y = ( dst . h - height ) / 2 ;
osdRect . w = width ;
osdRect . h = height ;
SDL_FillRect ( _osdSurface , & osdRect , SDL_MapRGB ( _osdSurface - > format , 64 , 64 , 64 ) ) ;
// 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 ] ,
osdRect . x , osdRect . y + i * lineHeight + vOffset + lineSpacing , osdRect . w ,
2004-03-13 14:19:15 +00:00
SDL_MapRGB ( _osdSurface - > format , 255 , 255 , 255 ) ,
2004-03-21 21:20:25 +00:00
Graphics : : kTextAlignCenter ) ;
2004-03-15 19:07:56 +00:00
}
2004-03-13 14:19:15 +00:00
2004-03-15 19:07:56 +00:00
// Finished drawing, so unlock the OSD surface again
2004-03-13 14:19:15 +00:00
SDL_UnlockSurface ( _osdSurface ) ;
// Init the OSD display parameters, and the fade out
2010-07-26 06:58:33 +00:00
_osdAlpha = SDL_ALPHA_TRANSPARENT + kOSDInitialAlpha * ( SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT ) / 100 ;
2004-03-13 14:19:15 +00:00
_osdFadeStartTime = SDL_GetTicks ( ) + kOSDFadeOutDelay ;
SDL_SetAlpha ( _osdSurface , SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA , _osdAlpha ) ;
2005-07-30 21:11:48 +00:00
2004-03-13 14:19:15 +00:00
// Ensure a full redraw takes place next time the screen is updated
_forceFull = true ;
}
# endif
2005-07-11 10:54:53 +00:00
2010-07-11 04:32:24 +00:00
bool SdlGraphicsManager : : 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
char buffer [ 128 ] ;
2009-05-01 09:09:07 +00:00
if ( _videoMode . aspectRatioCorrection )
2005-07-11 10:54:53 +00:00
sprintf ( buffer , " Enabled aspect ratio correction \n %d x %d -> %d x %d " ,
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
sprintf ( buffer , " Disabled aspect ratio correction \n %d x %d -> %d x %d " ,
2008-11-14 22:08:10 +00:00
_videoMode . screenWidth , _videoMode . screenHeight ,
2005-07-11 10:54:53 +00:00
_hwscreen - > w , _hwscreen - > h
) ;
displayMessageOnOSD ( buffer ) ;
# 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
}
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
if ( _osdSurface ) {
const char * newScalerName = 0 ;
2010-06-07 03:14:42 +00:00
const OSystem : : GraphicsMode * g = getSupportedGraphicsModes ( ) ;
2005-07-11 10:54:53 +00:00
while ( g - > name ) {
2008-11-14 22:08:10 +00:00
if ( g - > id = = _videoMode . mode ) {
2005-07-11 10:54:53 +00:00
newScalerName = g - > description ;
break ;
}
g + + ;
}
if ( newScalerName ) {
char buffer [ 128 ] ;
sprintf ( buffer , " Active graphics filter: %s \n %d x %d -> %d x %d " ,
newScalerName ,
2008-11-14 22:08:10 +00:00
_videoMode . screenWidth , _videoMode . screenHeight ,
2005-07-11 10:54:53 +00:00
_hwscreen - > w , _hwscreen - > h
) ;
displayMessageOnOSD ( buffer ) ;
}
}
# 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
2010-06-05 22:45:36 +00:00
bool SdlGraphicsManager : : 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 ;
}
return ( isScaleKey | | event . kbd . keycode = = ' a ' ) ;
}
return false ;
}
2010-06-09 05:29:14 +00:00
2010-07-15 01:21:20 +00:00
void SdlGraphicsManager : : adjustMouseEvent ( const Common : : Event & event ) {
if ( ! event . synthetic ) {
Common : : Event newEvent ( event ) ;
newEvent . synthetic = true ;
if ( ! _overlayVisible ) {
newEvent . mouse . x / = _videoMode . scaleFactor ;
newEvent . mouse . y / = _videoMode . scaleFactor ;
if ( _videoMode . aspectRatioCorrection )
newEvent . mouse . y = aspect2Real ( newEvent . mouse . y ) ;
}
g_system - > getEventManager ( ) - > pushEvent ( newEvent ) ;
2010-06-16 04:34:44 +00:00
}
}
void SdlGraphicsManager : : toggleFullScreen ( ) {
beginGFXTransaction ( ) ;
setFullscreenMode ( ! _videoMode . fullscreen ) ;
endGFXTransaction ( ) ;
# ifdef USE_OSD
if ( _videoMode . fullscreen )
displayMessageOnOSD ( " Fullscreen mode " ) ;
else
displayMessageOnOSD ( " Windowed mode " ) ;
# endif
}
2010-07-15 01:21:20 +00:00
bool SdlGraphicsManager : : 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 ' ) {
char filename [ 20 ] ;
for ( int n = 0 ; ; n + + ) {
SDL_RWops * file ;
sprintf ( filename , " scummvm%05d.bmp " , n ) ;
file = SDL_RWFromFile ( filename , " r " ) ;
if ( ! file )
break ;
SDL_RWclose ( file ) ;
}
if ( saveScreenshot ( filename ) )
2011-05-02 14:42:08 +02:00
debug ( " Saved screenshot '%s' " , filename ) ;
2010-07-15 01:21:20 +00:00
else
2011-05-02 14:42:08 +02:00
warning ( " Could not save screenshot " ) ;
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 ;
}
case Common : : EVENT_KEYUP :
return isScalerHotkey ( event ) ;
case Common : : EVENT_MOUSEMOVE :
if ( event . synthetic )
setMousePos ( event . mouse . x , event . mouse . y ) ;
case Common : : EVENT_LBUTTONDOWN :
case Common : : EVENT_RBUTTONDOWN :
case Common : : EVENT_WHEELUP :
case Common : : EVENT_WHEELDOWN :
case Common : : EVENT_MBUTTONDOWN :
case Common : : EVENT_LBUTTONUP :
case Common : : EVENT_RBUTTONUP :
case Common : : EVENT_MBUTTONUP :
adjustMouseEvent ( event ) ;
return ! event . synthetic ;
2010-07-19 05:33:58 +00:00
// HACK: Handle special SDL event
case OSystem_SDL : : kSdlEventExpose :
2010-07-15 01:21:20 +00:00
_forceFull = true ;
2010-07-19 05:33:58 +00:00
return false ;
2010-07-15 01:48:28 +00:00
default :
break ;
2010-07-15 01:21:20 +00:00
}
return false ;
}
2010-06-09 05:29:14 +00:00
# endif