2016-07-25 11:06:27 -05: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 .
*
* 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
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*
*/
2016-09-26 10:37:41 -05:00
# include "sci/console.h"
2016-07-25 11:06:27 -05:00
# include "sci/engine/segment.h"
# include "sci/engine/seg_manager.h"
# include "sci/engine/state.h"
# include "sci/graphics/frameout.h"
# include "sci/graphics/palette32.h"
# include "sci/graphics/text32.h"
# include "sci/graphics/transitions32.h"
# include "sci/sci.h"
namespace Sci {
static int dissolveSequences [ 2 ] [ 20 ] = {
/* SCI2.1early- */ { 3 , 6 , 12 , 20 , 48 , 96 , 184 , 272 , 576 , 1280 , 3232 , 6912 , 13568 , 24576 , 46080 } ,
/* SCI2.1mid+ */ { 0 , 0 , 3 , 6 , 12 , 20 , 48 , 96 , 184 , 272 , 576 , 1280 , 3232 , 6912 , 13568 , 24576 , 46080 , 73728 , 132096 , 466944 }
} ;
static int16 divisionsDefaults [ 2 ] [ 16 ] = {
/* SCI2.1early- */ { 1 , 20 , 20 , 20 , 20 , 20 , 20 , 20 , 20 , 20 , 20 , 40 , 40 , 101 , 101 } ,
/* SCI2.1mid+ */ { 1 , 20 , 20 , 20 , 20 , 10 , 10 , 10 , 10 , 20 , 20 , 6 , 10 , 101 , 101 , 2 }
} ;
GfxTransitions32 : : GfxTransitions32 ( SegManager * segMan ) :
2016-12-12 15:13:36 -06:00
_segMan ( segMan ) {
2016-07-25 11:06:27 -05:00
for ( int i = 0 ; i < 236 ; i + = 2 ) {
_styleRanges [ i ] = 0 ;
_styleRanges [ i + 1 ] = - 1 ;
}
for ( int i = 236 ; i < ARRAYSIZE ( _styleRanges ) ; + + i ) {
_styleRanges [ i ] = 0 ;
}
if ( getSciVersion ( ) < SCI_VERSION_2_1_MIDDLE ) {
_dissolveSequenceSeeds = dissolveSequences [ 0 ] ;
_defaultDivisions = divisionsDefaults [ 0 ] ;
} else {
_dissolveSequenceSeeds = dissolveSequences [ 1 ] ;
_defaultDivisions = divisionsDefaults [ 1 ] ;
}
}
GfxTransitions32 : : ~ GfxTransitions32 ( ) {
2016-07-29 12:31:57 -05:00
for ( ShowStyleList : : iterator it = _showStyles . begin ( ) ;
it ! = _showStyles . end ( ) ;
it = deleteShowStyle ( it ) ) ;
2016-07-25 11:06:27 -05:00
_scrolls . clear ( ) ;
}
2016-12-12 15:13:36 -06:00
void GfxTransitions32 : : throttle ( const uint32 ms ) {
g_sci - > getEngineState ( ) - > speedThrottler ( ms ) ;
2016-07-25 11:06:27 -05:00
g_sci - > getEngineState ( ) - > _throttleTrigger = true ;
}
SCI32: Fix slow SCI2.1mid transitions
SSCI transitions code sends a large number of small show rects
to the graphics manager, one at a time, for each division of a
transition. Each time a rect is submitted, a call to showBits
is made. This design was used when transitions for SCI32 were
first implemented in ScummVM, and it worked OK because the
hardware surface was updated by EventManager::getSciEvent,
not showBits, so the large number of calls to showBits from the
transitions code did not adversely affect engine performance.
Later in SCI32 engine development, hardware surface updates
were changed to occur in showBits so that the hardware surface
would be updated at frame-out time, instead of at input-in time.
This change meant that now the large number of calls to showBits
from transitions became very expensive, and the engine would
stall constantly refreshing the entire hardware surface.
To fix this problem, the transitions code now (1) maximises the
size of rects coming from transitions, when possible, and (2) only
calls showBits when all the rects from one frame of a transition
have been calculated and added to the show rects list.
Additionally, there were some arithmetic errors in the
implementation of pixel dissolve that have been corrected in this
changeset.
Fixes Trac#9614.
2016-10-22 12:41:39 -05:00
void GfxTransitions32 : : clearShowRects ( ) {
g_sci - > _gfxFrameout - > _showList . clear ( ) ;
}
void GfxTransitions32 : : addShowRect ( const Common : : Rect & rect ) {
if ( ! rect . isEmpty ( ) ) {
g_sci - > _gfxFrameout - > _showList . add ( rect ) ;
}
}
void GfxTransitions32 : : sendShowRects ( ) {
g_sci - > _gfxFrameout - > showBits ( ) ;
throttle ( ) ;
}
2016-07-25 11:06:27 -05:00
# pragma mark -
# pragma mark Show styles
void GfxTransitions32 : : processShowStyles ( ) {
uint32 now = g_sci - > getTickCount ( ) ;
bool continueProcessing ;
bool doFrameOut ;
do {
continueProcessing = false ;
doFrameOut = false ;
ShowStyleList : : iterator showStyle = _showStyles . begin ( ) ;
while ( showStyle ! = _showStyles . end ( ) ) {
bool finished = false ;
if ( ! showStyle - > animate ) {
doFrameOut = true ;
}
finished = processShowStyle ( * showStyle , now ) ;
if ( ! finished ) {
continueProcessing = true ;
}
if ( finished & & showStyle - > processed ) {
showStyle = deleteShowStyle ( showStyle ) ;
} else {
showStyle = + + showStyle ;
}
}
if ( g_engine - > shouldQuit ( ) ) {
return ;
}
if ( doFrameOut ) {
g_sci - > _gfxFrameout - > frameOut ( true ) ;
throttle ( ) ;
}
2017-10-05 21:41:29 -05:00
} while ( continueProcessing & & doFrameOut ) ;
2016-07-25 11:06:27 -05:00
}
void GfxTransitions32 : : processEffects ( PlaneShowStyle & showStyle ) {
switch ( showStyle . type ) {
case kShowStyleHShutterOut :
processHShutterOut ( showStyle ) ;
break ;
case kShowStyleHShutterIn :
processHShutterIn ( showStyle ) ;
break ;
case kShowStyleVShutterOut :
processVShutterOut ( showStyle ) ;
break ;
case kShowStyleVShutterIn :
processVShutterIn ( showStyle ) ;
break ;
case kShowStyleWipeLeft :
processWipeLeft ( showStyle ) ;
break ;
case kShowStyleWipeRight :
processWipeRight ( showStyle ) ;
break ;
case kShowStyleWipeUp :
processWipeUp ( showStyle ) ;
break ;
case kShowStyleWipeDown :
processWipeDown ( showStyle ) ;
break ;
case kShowStyleIrisOut :
processIrisOut ( showStyle ) ;
break ;
case kShowStyleIrisIn :
processIrisIn ( showStyle ) ;
break ;
case kShowStyleDissolveNoMorph :
case kShowStyleDissolve :
processPixelDissolve ( showStyle ) ;
break ;
case kShowStyleNone :
case kShowStyleFadeOut :
case kShowStyleFadeIn :
case kShowStyleMorph :
break ;
}
}
// TODO: 10-argument version is only in SCI3; argc checks are currently wrong for this version
// and need to be fixed in future
void GfxTransitions32 : : kernelSetShowStyle ( const uint16 argc , const reg_t planeObj , const ShowStyleType type , const int16 seconds , const int16 back , const int16 priority , const int16 animate , const int16 frameOutNow , reg_t pFadeArray , int16 divisions , const int16 blackScreen ) {
bool hasDivisions = false ;
bool hasFadeArray = false ;
// KQ7 2.0b uses a mismatched version of the Styler script (SCI2.1early script
// for SCI2.1mid engine), so the calls it makes to kSetShowStyle are wrong and
// put `divisions` where `pFadeArray` is supposed to be
if ( getSciVersion ( ) = = SCI_VERSION_2_1_MIDDLE & & g_sci - > getGameId ( ) = = GID_KQ7 ) {
hasDivisions = argc > 7 ;
hasFadeArray = false ;
divisions = argc > 7 ? pFadeArray . toSint16 ( ) : - 1 ;
pFadeArray = NULL_REG ;
} else if ( getSciVersion ( ) < SCI_VERSION_2_1_MIDDLE ) {
hasDivisions = argc > 7 ;
hasFadeArray = false ;
} else if ( getSciVersion ( ) < SCI_VERSION_3 ) {
hasDivisions = argc > 8 ;
hasFadeArray = argc > 7 ;
} else {
hasDivisions = argc > 9 ;
hasFadeArray = argc > 8 ;
}
bool isFadeUp ;
int16 color ;
if ( back ! = - 1 ) {
isFadeUp = false ;
color = back ;
} else {
isFadeUp = true ;
color = 0 ;
}
Plane * plane = g_sci - > _gfxFrameout - > getPlanes ( ) . findByObject ( planeObj ) ;
if ( plane = = nullptr ) {
error ( " Plane %04x:%04x is not present in active planes list " , PRINT_REG ( planeObj ) ) ;
}
bool createNewEntry = true ;
PlaneShowStyle * entry = findShowStyleForPlane ( planeObj ) ;
if ( entry ! = nullptr ) {
bool useExisting = true ;
if ( getSciVersion ( ) < SCI_VERSION_2_1_MIDDLE ) {
useExisting = plane - > _gameRect . width ( ) = = entry - > width & & plane - > _gameRect . height ( ) = = entry - > height ;
}
if ( useExisting ) {
useExisting = entry - > divisions = = ( hasDivisions ? divisions : _defaultDivisions [ type ] ) ;
}
if ( useExisting ) {
createNewEntry = false ;
isFadeUp = true ;
entry - > currentStep = 0 ;
} else {
isFadeUp = true ;
color = entry - > color ;
deleteShowStyle ( findIteratorForPlane ( planeObj ) ) ;
entry = nullptr ;
}
}
2016-08-26 19:49:31 -05:00
if ( type = = kShowStyleNone ) {
if ( createNewEntry = = false ) {
deleteShowStyle ( findIteratorForPlane ( planeObj ) ) ;
}
return ;
}
if ( createNewEntry ) {
entry = new PlaneShowStyle ;
2017-10-05 21:41:29 -05:00
// SSCI2.1 tests if allocation returned a null pointer but then only
// avoids setting currentStep if this is so. Since this nonsensical, we
// do not do that here
2016-08-26 19:49:31 -05:00
entry - > currentStep = 0 ;
entry - > processed = false ;
entry - > divisions = hasDivisions ? divisions : _defaultDivisions [ type ] ;
entry - > plane = planeObj ;
if ( getSciVersion ( ) < SCI_VERSION_2_1_MIDDLE ) {
// for pixel dissolve
entry - > bitmap = NULL_REG ;
entry - > bitmapScreenItem = nullptr ;
// for wipe
entry - > screenItems . clear ( ) ;
entry - > width = plane - > _gameRect . width ( ) ;
entry - > height = plane - > _gameRect . height ( ) ;
2017-10-05 21:41:29 -05:00
} else if ( hasFadeArray ) {
// SSCI2.1mid does no check to verify that an array is successfully
// retrieved
SciArray & table = * _segMan - > lookupArray ( pFadeArray ) ;
const uint32 rangeCount = table . size ( ) ;
// SSCI always allocates memory even if the range table has no
// entries, but this does not really make sense, so we avoid the
// allocation call in this case
if ( rangeCount > 0 ) {
entry - > fadeColorRanges . reserve ( rangeCount ) ;
for ( uint32 i = 0 ; i < rangeCount ; + + i ) {
entry - > fadeColorRanges . push_back ( table . getAsInt16 ( i ) ) ;
2016-07-25 11:06:27 -05:00
}
}
}
2016-08-26 19:49:31 -05:00
}
2016-07-25 11:06:27 -05:00
2017-10-05 21:41:29 -05:00
// SSCI had no nullptr check and would just crash if it got to here
2016-08-26 19:49:31 -05:00
if ( entry = = nullptr ) {
error ( " Cannot edit non-existing ShowStyle entry " ) ;
}
2016-07-25 11:06:27 -05:00
2016-08-26 19:49:31 -05:00
entry - > fadeUp = isFadeUp ;
entry - > color = color ;
entry - > nextTick = g_sci - > getTickCount ( ) ;
entry - > type = type ;
entry - > animate = animate ;
entry - > delay = ( seconds * 60 + entry - > divisions - 1 ) / entry - > divisions ;
2016-07-25 11:06:27 -05:00
2016-08-26 19:49:31 -05:00
if ( entry - > delay = = 0 ) {
error ( " ShowStyle has no duration " ) ;
}
2016-07-25 11:06:27 -05:00
2016-08-26 19:49:31 -05:00
if ( frameOutNow ) {
// Creates a reference frame for the pixel dissolves to use
g_sci - > _gfxFrameout - > frameOut ( false ) ;
}
2016-07-25 11:06:27 -05:00
2016-08-26 19:49:31 -05:00
if ( createNewEntry ) {
if ( getSciVersion ( ) < = SCI_VERSION_2_1_EARLY ) {
switch ( entry - > type ) {
2017-01-12 10:55:13 -06:00
case kShowStyleWipeLeft :
case kShowStyleWipeRight :
configure21EarlyHorizontalWipe ( * entry , priority ) ;
break ;
2017-07-07 21:02:39 -05:00
case kShowStyleHShutterOut :
configure21EarlyHorizontalShutter ( * entry , priority ) ;
break ;
2016-08-26 19:49:31 -05:00
case kShowStyleIrisOut :
case kShowStyleIrisIn :
configure21EarlyIris ( * entry , priority ) ;
2017-01-12 10:55:13 -06:00
break ;
2016-08-26 19:49:31 -05:00
case kShowStyleDissolve :
configure21EarlyDissolve ( * entry , priority , plane - > _gameRect ) ;
2017-01-12 10:55:13 -06:00
break ;
2016-08-26 19:49:31 -05:00
default :
// do nothing
2017-01-12 10:55:13 -06:00
break ;
2016-07-25 11:06:27 -05:00
}
}
2016-08-26 19:49:31 -05:00
_showStyles . push_back ( * entry ) ;
delete entry ;
2016-07-25 11:06:27 -05:00
}
}
void GfxTransitions32 : : kernelSetPalStyleRange ( const uint8 fromColor , const uint8 toColor ) {
if ( toColor > fromColor ) {
return ;
}
for ( int i = fromColor ; i < = toColor ; + + i ) {
_styleRanges [ i ] = 0 ;
}
}
PlaneShowStyle * GfxTransitions32 : : findShowStyleForPlane ( const reg_t planeObj ) {
for ( ShowStyleList : : iterator it = _showStyles . begin ( ) ; it ! = _showStyles . end ( ) ; + + it ) {
if ( it - > plane = = planeObj ) {
return & * it ;
}
}
return nullptr ;
}
ShowStyleList : : iterator GfxTransitions32 : : findIteratorForPlane ( const reg_t planeObj ) {
ShowStyleList : : iterator it ;
for ( it = _showStyles . begin ( ) ; it ! = _showStyles . end ( ) ; + + it ) {
if ( it - > plane = = planeObj ) {
break ;
}
}
return it ;
}
ShowStyleList : : iterator GfxTransitions32 : : deleteShowStyle ( const ShowStyleList : : iterator & showStyle ) {
switch ( showStyle - > type ) {
case kShowStyleDissolveNoMorph :
case kShowStyleDissolve :
if ( getSciVersion ( ) < = SCI_VERSION_2_1_EARLY ) {
2016-07-29 15:48:14 -05:00
_segMan - > freeBitmap ( showStyle - > bitmap ) ;
2016-07-25 11:06:27 -05:00
g_sci - > _gfxFrameout - > deleteScreenItem ( * showStyle - > bitmapScreenItem ) ;
}
break ;
2017-01-12 10:55:13 -06:00
case kShowStyleWipeLeft :
case kShowStyleWipeRight :
2016-07-25 11:06:27 -05:00
case kShowStyleIrisOut :
case kShowStyleIrisIn :
2017-07-07 21:02:39 -05:00
case kShowStyleHShutterOut :
2016-07-25 11:06:27 -05:00
if ( getSciVersion ( ) < = SCI_VERSION_2_1_EARLY ) {
for ( uint i = 0 ; i < showStyle - > screenItems . size ( ) ; + + i ) {
ScreenItem * screenItem = showStyle - > screenItems [ i ] ;
if ( screenItem ! = nullptr ) {
g_sci - > _gfxFrameout - > deleteScreenItem ( * screenItem ) ;
}
}
}
break ;
case kShowStyleFadeIn :
case kShowStyleFadeOut :
2017-10-05 21:41:29 -05:00
// SSCI manually allocated the color ranges for fades and deleted that
// memory here, but we use a container so there is no extra cleanup
// needed
2016-07-25 11:06:27 -05:00
case kShowStyleNone :
case kShowStyleMorph :
2016-10-21 21:03:32 -05:00
case kShowStyleHShutterIn :
2016-07-25 11:06:27 -05:00
// do nothing
break ;
default :
error ( " Unknown delete transition type %d " , showStyle - > type ) ;
}
return _showStyles . erase ( showStyle ) ;
}
2017-01-12 10:55:13 -06:00
void GfxTransitions32 : : configure21EarlyHorizontalWipe ( PlaneShowStyle & showStyle , const int16 priority ) {
showStyle . numEdges = 1 ;
const int divisions = showStyle . divisions ;
showStyle . screenItems . reserve ( divisions ) ;
CelInfo32 celInfo ;
celInfo . type = kCelTypeColor ;
celInfo . color = showStyle . color ;
for ( int i = 0 ; i < divisions ; + + i ) {
Common : : Rect rect ;
rect . left = showStyle . width * i / divisions ;
rect . top = 0 ;
rect . right = showStyle . width * ( i + 1 ) / divisions ;
rect . bottom = showStyle . height ;
showStyle . screenItems . push_back ( new ScreenItem ( showStyle . plane , celInfo , rect ) ) ;
showStyle . screenItems . back ( ) - > _priority = priority ;
showStyle . screenItems . back ( ) - > _fixedPriority = true ;
}
if ( showStyle . fadeUp ) {
for ( int i = 0 ; i < divisions ; + + i ) {
g_sci - > _gfxFrameout - > addScreenItem ( * showStyle . screenItems [ i ] ) ;
}
}
}
2017-07-07 21:02:39 -05:00
void GfxTransitions32 : : configure21EarlyHorizontalShutter ( PlaneShowStyle & showStyle , const int16 priority ) {
showStyle . numEdges = 2 ;
const int numScreenItems = showStyle . numEdges * showStyle . divisions ;
showStyle . screenItems . reserve ( numScreenItems ) ;
CelInfo32 celInfo ;
celInfo . type = kCelTypeColor ;
celInfo . color = showStyle . color ;
const int width = showStyle . width ;
const int divisions = showStyle . divisions ;
for ( int i = 0 ; i < divisions ; + + i ) {
Common : : Rect rect ;
// Left
rect . top = 0 ;
rect . right = ( width + 1 ) * ( i + 1 ) / ( 2 * divisions ) ;
rect . bottom = showStyle . height ;
const int16 leftLeft = rect . left ;
showStyle . screenItems . push_back ( new ScreenItem ( showStyle . plane , celInfo , rect ) ) ;
showStyle . screenItems . back ( ) - > _priority = priority ;
showStyle . screenItems . back ( ) - > _fixedPriority = true ;
// Right
rect . left = width - rect . right ;
rect . right = width - leftLeft ;
showStyle . screenItems . push_back ( new ScreenItem ( showStyle . plane , celInfo , rect ) ) ;
showStyle . screenItems . back ( ) - > _priority = priority ;
showStyle . screenItems . back ( ) - > _fixedPriority = true ;
}
if ( showStyle . fadeUp ) {
for ( int i = 0 ; i < numScreenItems ; + + i ) {
g_sci - > _gfxFrameout - > addScreenItem ( * showStyle . screenItems [ i ] ) ;
}
}
}
2016-07-25 11:06:27 -05:00
void GfxTransitions32 : : configure21EarlyIris ( PlaneShowStyle & showStyle , const int16 priority ) {
showStyle . numEdges = 4 ;
const int numScreenItems = showStyle . numEdges * showStyle . divisions ;
showStyle . screenItems . reserve ( numScreenItems ) ;
CelInfo32 celInfo ;
celInfo . type = kCelTypeColor ;
celInfo . color = showStyle . color ;
const int width = showStyle . width ;
const int height = showStyle . height ;
const int divisions = showStyle . divisions ;
for ( int i = 0 ; i < divisions ; + + i ) {
Common : : Rect rect ;
// Top
rect . left = ( width * i ) / ( 2 * divisions ) ;
rect . top = ( height * i ) / ( 2 * divisions ) ;
rect . right = width - rect . left ;
rect . bottom = ( height + 1 ) * ( i + 1 ) / ( 2 * divisions ) ;
const int16 topTop = rect . top ;
const int16 topBottom = rect . bottom ;
showStyle . screenItems . push_back ( new ScreenItem ( showStyle . plane , celInfo , rect ) ) ;
showStyle . screenItems . back ( ) - > _priority = priority ;
showStyle . screenItems . back ( ) - > _fixedPriority = true ;
// Bottom
rect . top = height - rect . bottom ;
rect . bottom = height - topTop ;
const int16 bottomTop = rect . top ;
showStyle . screenItems . push_back ( new ScreenItem ( showStyle . plane , celInfo , rect ) ) ;
showStyle . screenItems . back ( ) - > _priority = priority ;
showStyle . screenItems . back ( ) - > _fixedPriority = true ;
// Left
rect . top = topBottom ;
rect . right = ( width + 1 ) * ( i + 1 ) / ( 2 * divisions ) ;
rect . bottom = bottomTop ;
const int16 leftLeft = rect . left ;
showStyle . screenItems . push_back ( new ScreenItem ( showStyle . plane , celInfo , rect ) ) ;
showStyle . screenItems . back ( ) - > _priority = priority ;
showStyle . screenItems . back ( ) - > _fixedPriority = true ;
// Right
rect . left = width - rect . right ;
rect . right = width - leftLeft ;
showStyle . screenItems . push_back ( new ScreenItem ( showStyle . plane , celInfo , rect ) ) ;
showStyle . screenItems . back ( ) - > _priority = priority ;
showStyle . screenItems . back ( ) - > _fixedPriority = true ;
}
if ( showStyle . fadeUp ) {
for ( int i = 0 ; i < numScreenItems ; + + i ) {
g_sci - > _gfxFrameout - > addScreenItem ( * showStyle . screenItems [ i ] ) ;
}
}
}
void GfxTransitions32 : : configure21EarlyDissolve ( PlaneShowStyle & showStyle , const int16 priority , const Common : : Rect & gameRect ) {
2016-07-29 15:48:14 -05:00
reg_t bitmapId ;
SciBitmap & bitmap = * _segMan - > allocateBitmap ( & bitmapId , showStyle . width , showStyle . height , kDefaultSkipColor , 0 , 0 , kLowResX , kLowResY , 0 , false , false ) ;
2016-07-25 11:06:27 -05:00
2016-07-29 15:48:14 -05:00
showStyle . bitmap = bitmapId ;
2016-07-25 11:06:27 -05:00
const Buffer & source = g_sci - > _gfxFrameout - > getCurrentBuffer ( ) ;
2017-10-06 22:05:57 -05:00
Buffer target ;
target . init ( showStyle . width , showStyle . height , showStyle . width , bitmap . getPixels ( ) , Graphics : : PixelFormat : : createFormatCLUT8 ( ) ) ;
2016-07-25 11:06:27 -05:00
target . fillRect ( Common : : Rect ( bitmap . getWidth ( ) , bitmap . getHeight ( ) ) , kDefaultSkipColor ) ;
target . copyRectToSurface ( source , 0 , 0 , gameRect ) ;
CelInfo32 celInfo ;
celInfo . type = kCelTypeMem ;
2016-07-29 15:48:14 -05:00
celInfo . bitmap = bitmapId ;
2016-07-25 11:06:27 -05:00
showStyle . bitmapScreenItem = new ScreenItem ( showStyle . plane , celInfo , Common : : Point ( 0 , 0 ) , ScaleInfo ( ) ) ;
showStyle . bitmapScreenItem - > _priority = priority ;
showStyle . bitmapScreenItem - > _fixedPriority = true ;
g_sci - > _gfxFrameout - > addScreenItem ( * showStyle . bitmapScreenItem ) ;
}
bool GfxTransitions32 : : processShowStyle ( PlaneShowStyle & showStyle , uint32 now ) {
if ( showStyle . nextTick > = now & & showStyle . animate ) {
return false ;
}
switch ( showStyle . type ) {
default :
case kShowStyleNone :
return processNone ( showStyle ) ;
case kShowStyleHShutterIn :
case kShowStyleVShutterOut :
case kShowStyleVShutterIn :
case kShowStyleWipeUp :
case kShowStyleWipeDown :
case kShowStyleDissolveNoMorph :
case kShowStyleMorph :
return processMorph ( showStyle ) ;
2017-07-07 21:02:39 -05:00
case kShowStyleHShutterOut :
if ( getSciVersion ( ) > SCI_VERSION_2_1_EARLY ) {
return processMorph ( showStyle ) ;
} else {
return processHShutterOut ( showStyle ) ;
}
2017-01-12 10:55:13 -06:00
case kShowStyleWipeLeft :
if ( getSciVersion ( ) > SCI_VERSION_2_1_EARLY ) {
return processMorph ( showStyle ) ;
} else {
return processWipe ( - 1 , showStyle ) ;
}
case kShowStyleWipeRight :
if ( getSciVersion ( ) > SCI_VERSION_2_1_EARLY ) {
return processMorph ( showStyle ) ;
} else {
return processWipe ( 1 , showStyle ) ;
}
2016-07-25 11:06:27 -05:00
case kShowStyleDissolve :
if ( getSciVersion ( ) > SCI_VERSION_2_1_EARLY ) {
return processMorph ( showStyle ) ;
} else {
return processPixelDissolve ( showStyle ) ;
}
case kShowStyleIrisOut :
if ( getSciVersion ( ) > SCI_VERSION_2_1_EARLY ) {
return processMorph ( showStyle ) ;
} else {
return processIrisOut ( showStyle ) ;
}
case kShowStyleIrisIn :
if ( getSciVersion ( ) > SCI_VERSION_2_1_EARLY ) {
return processMorph ( showStyle ) ;
} else {
return processIrisIn ( showStyle ) ;
}
case kShowStyleFadeOut :
return processFade ( - 1 , showStyle ) ;
case kShowStyleFadeIn :
return processFade ( 1 , showStyle ) ;
}
}
bool GfxTransitions32 : : processNone ( PlaneShowStyle & showStyle ) {
if ( showStyle . fadeUp ) {
g_sci - > _gfxPalette32 - > setFade ( 100 , 0 , 255 ) ;
} else {
g_sci - > _gfxPalette32 - > setFade ( 0 , 0 , 255 ) ;
}
showStyle . processed = true ;
return true ;
}
2017-07-07 21:02:39 -05:00
bool GfxTransitions32 : : processHShutterOut ( PlaneShowStyle & showStyle ) {
if ( getSciVersion ( ) > SCI_VERSION_2_1_EARLY ) {
error ( " HShutterOut is not known to be used by any game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks! " ) ;
}
return processWipe ( - 1 , showStyle ) ;
2016-07-25 11:06:27 -05:00
}
SCI32: Fix slow SCI2.1mid transitions
SSCI transitions code sends a large number of small show rects
to the graphics manager, one at a time, for each division of a
transition. Each time a rect is submitted, a call to showBits
is made. This design was used when transitions for SCI32 were
first implemented in ScummVM, and it worked OK because the
hardware surface was updated by EventManager::getSciEvent,
not showBits, so the large number of calls to showBits from the
transitions code did not adversely affect engine performance.
Later in SCI32 engine development, hardware surface updates
were changed to occur in showBits so that the hardware surface
would be updated at frame-out time, instead of at input-in time.
This change meant that now the large number of calls to showBits
from transitions became very expensive, and the engine would
stall constantly refreshing the entire hardware surface.
To fix this problem, the transitions code now (1) maximises the
size of rects coming from transitions, when possible, and (2) only
calls showBits when all the rects from one frame of a transition
have been calculated and added to the show rects list.
Additionally, there were some arithmetic errors in the
implementation of pixel dissolve that have been corrected in this
changeset.
Fixes Trac#9614.
2016-10-22 12:41:39 -05:00
void GfxTransitions32 : : processHShutterIn ( const PlaneShowStyle & showStyle ) {
2016-10-21 21:03:32 -05:00
if ( getSciVersion ( ) < = SCI_VERSION_2_1_EARLY ) {
error ( " HShutterIn is not known to be used by any SCI2.1early- game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks! " ) ;
}
Plane * plane = g_sci - > _gfxFrameout - > getVisiblePlanes ( ) . findByObject ( showStyle . plane ) ;
const Common : : Rect & screenRect = plane - > _screenRect ;
Common : : Rect rect ;
const int divisions = showStyle . divisions ;
const int width = screenRect . width ( ) ;
const int divisionWidth = width / divisions - 1 ;
SCI32: Fix slow SCI2.1mid transitions
SSCI transitions code sends a large number of small show rects
to the graphics manager, one at a time, for each division of a
transition. Each time a rect is submitted, a call to showBits
is made. This design was used when transitions for SCI32 were
first implemented in ScummVM, and it worked OK because the
hardware surface was updated by EventManager::getSciEvent,
not showBits, so the large number of calls to showBits from the
transitions code did not adversely affect engine performance.
Later in SCI32 engine development, hardware surface updates
were changed to occur in showBits so that the hardware surface
would be updated at frame-out time, instead of at input-in time.
This change meant that now the large number of calls to showBits
from transitions became very expensive, and the engine would
stall constantly refreshing the entire hardware surface.
To fix this problem, the transitions code now (1) maximises the
size of rects coming from transitions, when possible, and (2) only
calls showBits when all the rects from one frame of a transition
have been calculated and added to the show rects list.
Additionally, there were some arithmetic errors in the
implementation of pixel dissolve that have been corrected in this
changeset.
Fixes Trac#9614.
2016-10-22 12:41:39 -05:00
clearShowRects ( ) ;
2016-10-21 21:03:32 -05:00
if ( width % divisions ) {
rect . left = ( divisionWidth + 1 ) * divisions + screenRect . left ;
rect . top = screenRect . top ;
rect . right = ( divisionWidth + 1 ) * divisions + ( width % divisions ) + screenRect . left ;
rect . bottom = screenRect . bottom ;
SCI32: Fix slow SCI2.1mid transitions
SSCI transitions code sends a large number of small show rects
to the graphics manager, one at a time, for each division of a
transition. Each time a rect is submitted, a call to showBits
is made. This design was used when transitions for SCI32 were
first implemented in ScummVM, and it worked OK because the
hardware surface was updated by EventManager::getSciEvent,
not showBits, so the large number of calls to showBits from the
transitions code did not adversely affect engine performance.
Later in SCI32 engine development, hardware surface updates
were changed to occur in showBits so that the hardware surface
would be updated at frame-out time, instead of at input-in time.
This change meant that now the large number of calls to showBits
from transitions became very expensive, and the engine would
stall constantly refreshing the entire hardware surface.
To fix this problem, the transitions code now (1) maximises the
size of rects coming from transitions, when possible, and (2) only
calls showBits when all the rects from one frame of a transition
have been calculated and added to the show rects list.
Additionally, there were some arithmetic errors in the
implementation of pixel dissolve that have been corrected in this
changeset.
Fixes Trac#9614.
2016-10-22 12:41:39 -05:00
addShowRect ( rect ) ;
sendShowRects ( ) ;
2016-10-21 21:03:32 -05:00
}
for ( int i = 0 ; i < width / ( 2 * divisions ) ; + + i ) {
// Left side
rect . left = i * divisions + screenRect . left ;
rect . top = screenRect . top ;
rect . right = i * divisions + divisions + screenRect . left ;
rect . bottom = screenRect . bottom ;
SCI32: Fix slow SCI2.1mid transitions
SSCI transitions code sends a large number of small show rects
to the graphics manager, one at a time, for each division of a
transition. Each time a rect is submitted, a call to showBits
is made. This design was used when transitions for SCI32 were
first implemented in ScummVM, and it worked OK because the
hardware surface was updated by EventManager::getSciEvent,
not showBits, so the large number of calls to showBits from the
transitions code did not adversely affect engine performance.
Later in SCI32 engine development, hardware surface updates
were changed to occur in showBits so that the hardware surface
would be updated at frame-out time, instead of at input-in time.
This change meant that now the large number of calls to showBits
from transitions became very expensive, and the engine would
stall constantly refreshing the entire hardware surface.
To fix this problem, the transitions code now (1) maximises the
size of rects coming from transitions, when possible, and (2) only
calls showBits when all the rects from one frame of a transition
have been calculated and added to the show rects list.
Additionally, there were some arithmetic errors in the
implementation of pixel dissolve that have been corrected in this
changeset.
Fixes Trac#9614.
2016-10-22 12:41:39 -05:00
addShowRect ( rect ) ;
2016-10-21 21:03:32 -05:00
// Right side
rect . left = ( divisionWidth - i ) * divisions + screenRect . left ;
rect . top = screenRect . top ;
rect . right = ( divisionWidth - i ) * divisions + divisions + screenRect . left ;
rect . bottom = screenRect . bottom ;
SCI32: Fix slow SCI2.1mid transitions
SSCI transitions code sends a large number of small show rects
to the graphics manager, one at a time, for each division of a
transition. Each time a rect is submitted, a call to showBits
is made. This design was used when transitions for SCI32 were
first implemented in ScummVM, and it worked OK because the
hardware surface was updated by EventManager::getSciEvent,
not showBits, so the large number of calls to showBits from the
transitions code did not adversely affect engine performance.
Later in SCI32 engine development, hardware surface updates
were changed to occur in showBits so that the hardware surface
would be updated at frame-out time, instead of at input-in time.
This change meant that now the large number of calls to showBits
from transitions became very expensive, and the engine would
stall constantly refreshing the entire hardware surface.
To fix this problem, the transitions code now (1) maximises the
size of rects coming from transitions, when possible, and (2) only
calls showBits when all the rects from one frame of a transition
have been calculated and added to the show rects list.
Additionally, there were some arithmetic errors in the
implementation of pixel dissolve that have been corrected in this
changeset.
Fixes Trac#9614.
2016-10-22 12:41:39 -05:00
addShowRect ( rect ) ;
2016-10-21 21:03:32 -05:00
SCI32: Fix slow SCI2.1mid transitions
SSCI transitions code sends a large number of small show rects
to the graphics manager, one at a time, for each division of a
transition. Each time a rect is submitted, a call to showBits
is made. This design was used when transitions for SCI32 were
first implemented in ScummVM, and it worked OK because the
hardware surface was updated by EventManager::getSciEvent,
not showBits, so the large number of calls to showBits from the
transitions code did not adversely affect engine performance.
Later in SCI32 engine development, hardware surface updates
were changed to occur in showBits so that the hardware surface
would be updated at frame-out time, instead of at input-in time.
This change meant that now the large number of calls to showBits
from transitions became very expensive, and the engine would
stall constantly refreshing the entire hardware surface.
To fix this problem, the transitions code now (1) maximises the
size of rects coming from transitions, when possible, and (2) only
calls showBits when all the rects from one frame of a transition
have been calculated and added to the show rects list.
Additionally, there were some arithmetic errors in the
implementation of pixel dissolve that have been corrected in this
changeset.
Fixes Trac#9614.
2016-10-22 12:41:39 -05:00
sendShowRects ( ) ;
2016-10-21 21:03:32 -05:00
}
SCI32: Fix slow SCI2.1mid transitions
SSCI transitions code sends a large number of small show rects
to the graphics manager, one at a time, for each division of a
transition. Each time a rect is submitted, a call to showBits
is made. This design was used when transitions for SCI32 were
first implemented in ScummVM, and it worked OK because the
hardware surface was updated by EventManager::getSciEvent,
not showBits, so the large number of calls to showBits from the
transitions code did not adversely affect engine performance.
Later in SCI32 engine development, hardware surface updates
were changed to occur in showBits so that the hardware surface
would be updated at frame-out time, instead of at input-in time.
This change meant that now the large number of calls to showBits
from transitions became very expensive, and the engine would
stall constantly refreshing the entire hardware surface.
To fix this problem, the transitions code now (1) maximises the
size of rects coming from transitions, when possible, and (2) only
calls showBits when all the rects from one frame of a transition
have been calculated and added to the show rects list.
Additionally, there were some arithmetic errors in the
implementation of pixel dissolve that have been corrected in this
changeset.
Fixes Trac#9614.
2016-10-22 12:41:39 -05:00
addShowRect ( screenRect ) ;
sendShowRects ( ) ;
2016-07-25 11:06:27 -05:00
}
void GfxTransitions32 : : processVShutterOut ( PlaneShowStyle & showStyle ) {
error ( " VShutterOut is not known to be used by any game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks! " ) ;
}
void GfxTransitions32 : : processVShutterIn ( PlaneShowStyle & showStyle ) {
error ( " VShutterIn is not known to be used by any game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks! " ) ;
}
void GfxTransitions32 : : processWipeLeft ( PlaneShowStyle & showStyle ) {
2017-01-12 10:55:13 -06:00
if ( getSciVersion ( ) > SCI_VERSION_2_1_EARLY ) {
error ( " WipeLeft is not known to be used by any SCI2.1mid+ game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks! " ) ;
}
2016-07-25 11:06:27 -05:00
}
void GfxTransitions32 : : processWipeRight ( PlaneShowStyle & showStyle ) {
2017-01-12 10:55:13 -06:00
if ( getSciVersion ( ) > SCI_VERSION_2_1_EARLY ) {
error ( " WipeRight is not known to be used by any SCI2.1mid+ game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks! " ) ;
}
2016-07-25 11:06:27 -05:00
}
void GfxTransitions32 : : processWipeUp ( PlaneShowStyle & showStyle ) {
error ( " WipeUp is not known to be used by any game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks! " ) ;
}
void GfxTransitions32 : : processWipeDown ( PlaneShowStyle & showStyle ) {
error ( " WipeDown is not known to be used by any game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks! " ) ;
}
bool GfxTransitions32 : : processIrisOut ( PlaneShowStyle & showStyle ) {
if ( getSciVersion ( ) > SCI_VERSION_2_1_EARLY ) {
error ( " IrisOut is not known to be used by any SCI2.1mid+ game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks! " ) ;
}
return processWipe ( - 1 , showStyle ) ;
}
bool GfxTransitions32 : : processIrisIn ( PlaneShowStyle & showStyle ) {
if ( getSciVersion ( ) > SCI_VERSION_2_1_EARLY ) {
error ( " IrisIn is not known to be used by any SCI2.1mid+ game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks! " ) ;
}
return processWipe ( 1 , showStyle ) ;
}
void GfxTransitions32 : : processDissolveNoMorph ( PlaneShowStyle & showStyle ) {
error ( " DissolveNoMorph is not known to be used by any game. Please submit a bug report with details about the game you were playing and what you were doing that triggered this error. Thanks! " ) ;
}
inline int bitWidth ( int number ) {
int width = 0 ;
while ( number ! = 0 ) {
number > > = 1 ;
width + = 1 ;
}
return width ;
}
bool GfxTransitions32 : : processPixelDissolve ( PlaneShowStyle & showStyle ) {
if ( getSciVersion ( ) > SCI_VERSION_2_1_EARLY ) {
return processPixelDissolve21Mid ( showStyle ) ;
} else {
return processPixelDissolve21Early ( showStyle ) ;
}
}
bool GfxTransitions32 : : processPixelDissolve21Early ( PlaneShowStyle & showStyle ) {
bool unchanged = true ;
2016-07-29 15:48:14 -05:00
SciBitmap & bitmap = * _segMan - > lookupBitmap ( showStyle . bitmap ) ;
2017-10-06 22:05:57 -05:00
Buffer buffer ;
buffer . init ( showStyle . width , showStyle . height , showStyle . width , bitmap . getPixels ( ) , Graphics : : PixelFormat : : createFormatCLUT8 ( ) ) ;
2016-07-25 11:06:27 -05:00
uint32 numPixels = showStyle . width * showStyle . height ;
uint32 numPixelsPerDivision = ( numPixels + showStyle . divisions ) / showStyle . divisions ;
uint32 index ;
if ( showStyle . currentStep = = 0 ) {
int i = 0 ;
index = numPixels ;
if ( index ! = 1 ) {
for ( ; ; ) {
index > > = 1 ;
if ( index = = 1 ) {
break ;
}
i + + ;
}
}
showStyle . dissolveMask = _dissolveSequenceSeeds [ i ] ;
index = 53427 ;
showStyle . firstPixel = index ;
showStyle . pixel = index ;
} else {
index = showStyle . pixel ;
for ( ; ; ) {
if ( index & 1 ) {
index > > = 1 ;
index ^ = showStyle . dissolveMask ;
} else {
index > > = 1 ;
}
if ( index < numPixels ) {
break ;
}
}
if ( index = = showStyle . firstPixel ) {
index = 0 ;
}
}
if ( showStyle . currentStep < showStyle . divisions ) {
for ( uint32 i = 0 ; i < numPixelsPerDivision ; + + i ) {
* ( byte * ) buffer . getBasePtr ( index % showStyle . width , index / showStyle . width ) = showStyle . color ;
for ( ; ; ) {
if ( index & 1 ) {
index > > = 1 ;
index ^ = showStyle . dissolveMask ;
} else {
index > > = 1 ;
}
if ( index < numPixels ) {
break ;
}
}
if ( index = = showStyle . firstPixel ) {
buffer . fillRect ( Common : : Rect ( 0 , 0 , showStyle . width , showStyle . height ) , showStyle . color ) ;
break ;
}
}
showStyle . pixel = index ;
showStyle . nextTick + = showStyle . delay ;
+ + showStyle . currentStep ;
unchanged = false ;
if ( showStyle . bitmapScreenItem - > _created = = 0 ) {
showStyle . bitmapScreenItem - > _updated = g_sci - > _gfxFrameout - > getScreenCount ( ) ;
}
}
if ( ( showStyle . currentStep > = showStyle . divisions ) & & unchanged ) {
if ( showStyle . fadeUp ) {
showStyle . processed = true ;
}
return true ;
}
return false ;
}
SCI32: Fix slow SCI2.1mid transitions
SSCI transitions code sends a large number of small show rects
to the graphics manager, one at a time, for each division of a
transition. Each time a rect is submitted, a call to showBits
is made. This design was used when transitions for SCI32 were
first implemented in ScummVM, and it worked OK because the
hardware surface was updated by EventManager::getSciEvent,
not showBits, so the large number of calls to showBits from the
transitions code did not adversely affect engine performance.
Later in SCI32 engine development, hardware surface updates
were changed to occur in showBits so that the hardware surface
would be updated at frame-out time, instead of at input-in time.
This change meant that now the large number of calls to showBits
from transitions became very expensive, and the engine would
stall constantly refreshing the entire hardware surface.
To fix this problem, the transitions code now (1) maximises the
size of rects coming from transitions, when possible, and (2) only
calls showBits when all the rects from one frame of a transition
have been calculated and added to the show rects list.
Additionally, there were some arithmetic errors in the
implementation of pixel dissolve that have been corrected in this
changeset.
Fixes Trac#9614.
2016-10-22 12:41:39 -05:00
bool GfxTransitions32 : : processPixelDissolve21Mid ( const PlaneShowStyle & showStyle ) {
2017-02-08 21:46:28 -06:00
// SQ6 room 530, LSL7 room 130
2016-07-25 11:06:27 -05:00
Plane * plane = g_sci - > _gfxFrameout - > getVisiblePlanes ( ) . findByObject ( showStyle . plane ) ;
const Common : : Rect & screenRect = plane - > _screenRect ;
Common : : Rect rect ;
const int planeWidth = screenRect . width ( ) ;
const int planeHeight = screenRect . height ( ) ;
const int divisions = showStyle . divisions ;
const int width = planeWidth / divisions + ( ( planeWidth % divisions ) ? 1 : 0 ) ;
const int height = planeHeight / divisions + ( ( planeHeight % divisions ) ? 1 : 0 ) ;
const uint32 mask = _dissolveSequenceSeeds [ bitWidth ( width * height - 1 ) ] ;
int seq = 1 ;
uint iteration = 0 ;
2016-10-26 20:49:57 -05:00
const uint numIterationsPerTick = g_sci - > _gfxFrameout - > _showList . max_size ( ) ;
SCI32: Fix slow SCI2.1mid transitions
SSCI transitions code sends a large number of small show rects
to the graphics manager, one at a time, for each division of a
transition. Each time a rect is submitted, a call to showBits
is made. This design was used when transitions for SCI32 were
first implemented in ScummVM, and it worked OK because the
hardware surface was updated by EventManager::getSciEvent,
not showBits, so the large number of calls to showBits from the
transitions code did not adversely affect engine performance.
Later in SCI32 engine development, hardware surface updates
were changed to occur in showBits so that the hardware surface
would be updated at frame-out time, instead of at input-in time.
This change meant that now the large number of calls to showBits
from transitions became very expensive, and the engine would
stall constantly refreshing the entire hardware surface.
To fix this problem, the transitions code now (1) maximises the
size of rects coming from transitions, when possible, and (2) only
calls showBits when all the rects from one frame of a transition
have been calculated and added to the show rects list.
Additionally, there were some arithmetic errors in the
implementation of pixel dissolve that have been corrected in this
changeset.
Fixes Trac#9614.
2016-10-22 12:41:39 -05:00
clearShowRects ( ) ;
2016-07-25 11:06:27 -05:00
do {
int row = seq / width ;
int col = seq % width ;
if ( row < height ) {
SCI32: Fix slow SCI2.1mid transitions
SSCI transitions code sends a large number of small show rects
to the graphics manager, one at a time, for each division of a
transition. Each time a rect is submitted, a call to showBits
is made. This design was used when transitions for SCI32 were
first implemented in ScummVM, and it worked OK because the
hardware surface was updated by EventManager::getSciEvent,
not showBits, so the large number of calls to showBits from the
transitions code did not adversely affect engine performance.
Later in SCI32 engine development, hardware surface updates
were changed to occur in showBits so that the hardware surface
would be updated at frame-out time, instead of at input-in time.
This change meant that now the large number of calls to showBits
from transitions became very expensive, and the engine would
stall constantly refreshing the entire hardware surface.
To fix this problem, the transitions code now (1) maximises the
size of rects coming from transitions, when possible, and (2) only
calls showBits when all the rects from one frame of a transition
have been calculated and added to the show rects list.
Additionally, there were some arithmetic errors in the
implementation of pixel dissolve that have been corrected in this
changeset.
Fixes Trac#9614.
2016-10-22 12:41:39 -05:00
if ( row = = height - 1 & & ( planeHeight % divisions ) ) {
if ( col = = width - 1 & & ( planeWidth % divisions ) ) {
2016-07-25 11:06:27 -05:00
rect . left = col * divisions ;
rect . top = row * divisions ;
rect . right = col * divisions + ( planeWidth % divisions ) ;
rect . bottom = row * divisions + ( planeHeight % divisions ) ;
SCI32: Fix slow SCI2.1mid transitions
SSCI transitions code sends a large number of small show rects
to the graphics manager, one at a time, for each division of a
transition. Each time a rect is submitted, a call to showBits
is made. This design was used when transitions for SCI32 were
first implemented in ScummVM, and it worked OK because the
hardware surface was updated by EventManager::getSciEvent,
not showBits, so the large number of calls to showBits from the
transitions code did not adversely affect engine performance.
Later in SCI32 engine development, hardware surface updates
were changed to occur in showBits so that the hardware surface
would be updated at frame-out time, instead of at input-in time.
This change meant that now the large number of calls to showBits
from transitions became very expensive, and the engine would
stall constantly refreshing the entire hardware surface.
To fix this problem, the transitions code now (1) maximises the
size of rects coming from transitions, when possible, and (2) only
calls showBits when all the rects from one frame of a transition
have been calculated and added to the show rects list.
Additionally, there were some arithmetic errors in the
implementation of pixel dissolve that have been corrected in this
changeset.
Fixes Trac#9614.
2016-10-22 12:41:39 -05:00
addShowRect ( rect ) ;
2016-07-25 11:06:27 -05:00
} else {
rect . left = col * divisions ;
rect . top = row * divisions ;
SCI32: Fix slow SCI2.1mid transitions
SSCI transitions code sends a large number of small show rects
to the graphics manager, one at a time, for each division of a
transition. Each time a rect is submitted, a call to showBits
is made. This design was used when transitions for SCI32 were
first implemented in ScummVM, and it worked OK because the
hardware surface was updated by EventManager::getSciEvent,
not showBits, so the large number of calls to showBits from the
transitions code did not adversely affect engine performance.
Later in SCI32 engine development, hardware surface updates
were changed to occur in showBits so that the hardware surface
would be updated at frame-out time, instead of at input-in time.
This change meant that now the large number of calls to showBits
from transitions became very expensive, and the engine would
stall constantly refreshing the entire hardware surface.
To fix this problem, the transitions code now (1) maximises the
size of rects coming from transitions, when possible, and (2) only
calls showBits when all the rects from one frame of a transition
have been calculated and added to the show rects list.
Additionally, there were some arithmetic errors in the
implementation of pixel dissolve that have been corrected in this
changeset.
Fixes Trac#9614.
2016-10-22 12:41:39 -05:00
rect . right = col * divisions + divisions ;
2016-07-25 11:06:27 -05:00
rect . bottom = row * divisions + ( planeHeight % divisions ) ;
SCI32: Fix slow SCI2.1mid transitions
SSCI transitions code sends a large number of small show rects
to the graphics manager, one at a time, for each division of a
transition. Each time a rect is submitted, a call to showBits
is made. This design was used when transitions for SCI32 were
first implemented in ScummVM, and it worked OK because the
hardware surface was updated by EventManager::getSciEvent,
not showBits, so the large number of calls to showBits from the
transitions code did not adversely affect engine performance.
Later in SCI32 engine development, hardware surface updates
were changed to occur in showBits so that the hardware surface
would be updated at frame-out time, instead of at input-in time.
This change meant that now the large number of calls to showBits
from transitions became very expensive, and the engine would
stall constantly refreshing the entire hardware surface.
To fix this problem, the transitions code now (1) maximises the
size of rects coming from transitions, when possible, and (2) only
calls showBits when all the rects from one frame of a transition
have been calculated and added to the show rects list.
Additionally, there were some arithmetic errors in the
implementation of pixel dissolve that have been corrected in this
changeset.
Fixes Trac#9614.
2016-10-22 12:41:39 -05:00
addShowRect ( rect ) ;
2016-07-25 11:06:27 -05:00
}
} else {
SCI32: Fix slow SCI2.1mid transitions
SSCI transitions code sends a large number of small show rects
to the graphics manager, one at a time, for each division of a
transition. Each time a rect is submitted, a call to showBits
is made. This design was used when transitions for SCI32 were
first implemented in ScummVM, and it worked OK because the
hardware surface was updated by EventManager::getSciEvent,
not showBits, so the large number of calls to showBits from the
transitions code did not adversely affect engine performance.
Later in SCI32 engine development, hardware surface updates
were changed to occur in showBits so that the hardware surface
would be updated at frame-out time, instead of at input-in time.
This change meant that now the large number of calls to showBits
from transitions became very expensive, and the engine would
stall constantly refreshing the entire hardware surface.
To fix this problem, the transitions code now (1) maximises the
size of rects coming from transitions, when possible, and (2) only
calls showBits when all the rects from one frame of a transition
have been calculated and added to the show rects list.
Additionally, there were some arithmetic errors in the
implementation of pixel dissolve that have been corrected in this
changeset.
Fixes Trac#9614.
2016-10-22 12:41:39 -05:00
if ( col = = width - 1 & & ( planeWidth % divisions ) ) {
2016-07-25 11:06:27 -05:00
rect . left = col * divisions ;
rect . top = row * divisions ;
SCI32: Fix slow SCI2.1mid transitions
SSCI transitions code sends a large number of small show rects
to the graphics manager, one at a time, for each division of a
transition. Each time a rect is submitted, a call to showBits
is made. This design was used when transitions for SCI32 were
first implemented in ScummVM, and it worked OK because the
hardware surface was updated by EventManager::getSciEvent,
not showBits, so the large number of calls to showBits from the
transitions code did not adversely affect engine performance.
Later in SCI32 engine development, hardware surface updates
were changed to occur in showBits so that the hardware surface
would be updated at frame-out time, instead of at input-in time.
This change meant that now the large number of calls to showBits
from transitions became very expensive, and the engine would
stall constantly refreshing the entire hardware surface.
To fix this problem, the transitions code now (1) maximises the
size of rects coming from transitions, when possible, and (2) only
calls showBits when all the rects from one frame of a transition
have been calculated and added to the show rects list.
Additionally, there were some arithmetic errors in the
implementation of pixel dissolve that have been corrected in this
changeset.
Fixes Trac#9614.
2016-10-22 12:41:39 -05:00
rect . right = col * divisions + ( planeWidth % divisions ) ;
rect . bottom = row * divisions + divisions ;
addShowRect ( rect ) ;
2016-07-25 11:06:27 -05:00
} else {
rect . left = col * divisions ;
rect . top = row * divisions ;
SCI32: Fix slow SCI2.1mid transitions
SSCI transitions code sends a large number of small show rects
to the graphics manager, one at a time, for each division of a
transition. Each time a rect is submitted, a call to showBits
is made. This design was used when transitions for SCI32 were
first implemented in ScummVM, and it worked OK because the
hardware surface was updated by EventManager::getSciEvent,
not showBits, so the large number of calls to showBits from the
transitions code did not adversely affect engine performance.
Later in SCI32 engine development, hardware surface updates
were changed to occur in showBits so that the hardware surface
would be updated at frame-out time, instead of at input-in time.
This change meant that now the large number of calls to showBits
from transitions became very expensive, and the engine would
stall constantly refreshing the entire hardware surface.
To fix this problem, the transitions code now (1) maximises the
size of rects coming from transitions, when possible, and (2) only
calls showBits when all the rects from one frame of a transition
have been calculated and added to the show rects list.
Additionally, there were some arithmetic errors in the
implementation of pixel dissolve that have been corrected in this
changeset.
Fixes Trac#9614.
2016-10-22 12:41:39 -05:00
rect . right = col * divisions + divisions ;
rect . bottom = row * divisions + divisions ;
addShowRect ( rect ) ;
2016-07-25 11:06:27 -05:00
}
}
}
if ( seq & 1 ) {
seq = ( seq > > 1 ) ^ mask ;
} else {
seq > > = 1 ;
}
if ( + + iteration = = numIterationsPerTick ) {
SCI32: Fix slow SCI2.1mid transitions
SSCI transitions code sends a large number of small show rects
to the graphics manager, one at a time, for each division of a
transition. Each time a rect is submitted, a call to showBits
is made. This design was used when transitions for SCI32 were
first implemented in ScummVM, and it worked OK because the
hardware surface was updated by EventManager::getSciEvent,
not showBits, so the large number of calls to showBits from the
transitions code did not adversely affect engine performance.
Later in SCI32 engine development, hardware surface updates
were changed to occur in showBits so that the hardware surface
would be updated at frame-out time, instead of at input-in time.
This change meant that now the large number of calls to showBits
from transitions became very expensive, and the engine would
stall constantly refreshing the entire hardware surface.
To fix this problem, the transitions code now (1) maximises the
size of rects coming from transitions, when possible, and (2) only
calls showBits when all the rects from one frame of a transition
have been calculated and added to the show rects list.
Additionally, there were some arithmetic errors in the
implementation of pixel dissolve that have been corrected in this
changeset.
Fixes Trac#9614.
2016-10-22 12:41:39 -05:00
sendShowRects ( ) ;
2016-07-25 11:06:27 -05:00
iteration = 0 ;
}
SCI32: Fix slow SCI2.1mid transitions
SSCI transitions code sends a large number of small show rects
to the graphics manager, one at a time, for each division of a
transition. Each time a rect is submitted, a call to showBits
is made. This design was used when transitions for SCI32 were
first implemented in ScummVM, and it worked OK because the
hardware surface was updated by EventManager::getSciEvent,
not showBits, so the large number of calls to showBits from the
transitions code did not adversely affect engine performance.
Later in SCI32 engine development, hardware surface updates
were changed to occur in showBits so that the hardware surface
would be updated at frame-out time, instead of at input-in time.
This change meant that now the large number of calls to showBits
from transitions became very expensive, and the engine would
stall constantly refreshing the entire hardware surface.
To fix this problem, the transitions code now (1) maximises the
size of rects coming from transitions, when possible, and (2) only
calls showBits when all the rects from one frame of a transition
have been calculated and added to the show rects list.
Additionally, there were some arithmetic errors in the
implementation of pixel dissolve that have been corrected in this
changeset.
Fixes Trac#9614.
2016-10-22 12:41:39 -05:00
} while ( seq ! = 1 & & ! g_engine - > shouldQuit ( ) ) ;
2016-07-25 11:06:27 -05:00
rect . left = screenRect . left ;
rect . top = screenRect . top ;
2017-02-08 21:46:28 -06:00
rect . right = screenRect . left + divisions ;
rect . bottom = screenRect . top + divisions ;
SCI32: Fix slow SCI2.1mid transitions
SSCI transitions code sends a large number of small show rects
to the graphics manager, one at a time, for each division of a
transition. Each time a rect is submitted, a call to showBits
is made. This design was used when transitions for SCI32 were
first implemented in ScummVM, and it worked OK because the
hardware surface was updated by EventManager::getSciEvent,
not showBits, so the large number of calls to showBits from the
transitions code did not adversely affect engine performance.
Later in SCI32 engine development, hardware surface updates
were changed to occur in showBits so that the hardware surface
would be updated at frame-out time, instead of at input-in time.
This change meant that now the large number of calls to showBits
from transitions became very expensive, and the engine would
stall constantly refreshing the entire hardware surface.
To fix this problem, the transitions code now (1) maximises the
size of rects coming from transitions, when possible, and (2) only
calls showBits when all the rects from one frame of a transition
have been calculated and added to the show rects list.
Additionally, there were some arithmetic errors in the
implementation of pixel dissolve that have been corrected in this
changeset.
Fixes Trac#9614.
2016-10-22 12:41:39 -05:00
addShowRect ( rect ) ;
sendShowRects ( ) ;
addShowRect ( screenRect ) ;
sendShowRects ( ) ;
2016-07-25 11:06:27 -05:00
return true ;
}
bool GfxTransitions32 : : processFade ( const int8 direction , PlaneShowStyle & showStyle ) {
bool unchanged = true ;
if ( showStyle . currentStep < showStyle . divisions ) {
int percent ;
if ( direction < = 0 ) {
percent = showStyle . divisions - showStyle . currentStep - 1 ;
} else {
percent = showStyle . currentStep ;
}
percent * = 100 ;
percent / = showStyle . divisions - 1 ;
2017-10-05 21:41:29 -05:00
if ( showStyle . fadeColorRanges . size ( ) ) {
for ( uint i = 0 , len = showStyle . fadeColorRanges . size ( ) ; i < len ; i + = 2 ) {
2016-07-25 11:06:27 -05:00
g_sci - > _gfxPalette32 - > setFade ( percent , showStyle . fadeColorRanges [ i ] , showStyle . fadeColorRanges [ i + 1 ] ) ;
}
} else {
g_sci - > _gfxPalette32 - > setFade ( percent , 0 , 255 ) ;
}
+ + showStyle . currentStep ;
showStyle . nextTick + = showStyle . delay ;
unchanged = false ;
}
if ( showStyle . currentStep > = showStyle . divisions & & unchanged ) {
if ( direction > 0 ) {
showStyle . processed = true ;
}
return true ;
}
return false ;
}
bool GfxTransitions32 : : processMorph ( PlaneShowStyle & showStyle ) {
g_sci - > _gfxFrameout - > palMorphFrameOut ( _styleRanges , & showStyle ) ;
showStyle . processed = true ;
return true ;
}
bool GfxTransitions32 : : processWipe ( const int8 direction , PlaneShowStyle & showStyle ) {
bool unchanged = true ;
if ( showStyle . currentStep < showStyle . divisions ) {
int index ;
if ( direction > 0 ) {
index = showStyle . currentStep ;
} else {
index = showStyle . divisions - showStyle . currentStep - 1 ;
}
index * = showStyle . numEdges ;
for ( int i = 0 ; i < showStyle . numEdges ; + + i ) {
ScreenItem * screenItem = showStyle . screenItems [ index + i ] ;
if ( showStyle . fadeUp ) {
g_sci - > _gfxFrameout - > deleteScreenItem ( * screenItem ) ;
showStyle . screenItems [ index + i ] = nullptr ;
} else {
g_sci - > _gfxFrameout - > addScreenItem ( * screenItem ) ;
}
}
+ + showStyle . currentStep ;
showStyle . nextTick + = showStyle . delay ;
unchanged = false ;
}
if ( showStyle . currentStep > = showStyle . divisions & & unchanged ) {
if ( showStyle . fadeUp ) {
showStyle . processed = true ;
}
return true ;
}
return false ;
}
# pragma mark -
# pragma mark Scrolls
void GfxTransitions32 : : processScrolls ( ) {
for ( ScrollList : : iterator it = _scrolls . begin ( ) ; it ! = _scrolls . end ( ) ; ) {
bool finished = processScroll ( * it ) ;
if ( finished ) {
it = _scrolls . erase ( it ) ;
} else {
+ + it ;
}
}
2016-12-12 15:13:36 -06:00
throttle ( 33 ) ;
2016-07-25 11:06:27 -05:00
}
void GfxTransitions32 : : kernelSetScroll ( const reg_t planeId , const int16 deltaX , const int16 deltaY , const GuiResourceId pictureId , const bool animate , const bool mirrorX ) {
for ( ScrollList : : const_iterator it = _scrolls . begin ( ) ; it ! = _scrolls . end ( ) ; + + it ) {
if ( it - > plane = = planeId ) {
error ( " Scroll already exists on plane %04x:%04x " , PRINT_REG ( planeId ) ) ;
}
}
if ( ! deltaX & & ! deltaY ) {
error ( " kSetScroll: Scroll has no movement " ) ;
}
if ( deltaX & & deltaY ) {
error ( " kSetScroll: Cannot scroll in two dimensions " ) ;
}
PlaneScroll * scroll = new PlaneScroll ;
scroll - > plane = planeId ;
scroll - > x = 0 ;
scroll - > y = 0 ;
scroll - > deltaX = deltaX ;
scroll - > deltaY = deltaY ;
scroll - > newPictureId = pictureId ;
scroll - > animate = animate ;
scroll - > startTick = g_sci - > getTickCount ( ) ;
Plane * plane = g_sci - > _gfxFrameout - > getPlanes ( ) . findByObject ( planeId ) ;
if ( plane = = nullptr ) {
error ( " kSetScroll: Plane %04x:%04x not found " , PRINT_REG ( planeId ) ) ;
}
Plane * visiblePlane = g_sci - > _gfxFrameout - > getPlanes ( ) . findByObject ( planeId ) ;
if ( visiblePlane = = nullptr ) {
error ( " kSetScroll: Visible plane %04x:%04x not found " , PRINT_REG ( planeId ) ) ;
}
const Common : : Rect & gameRect = visiblePlane - > _gameRect ;
Common : : Point picOrigin ;
if ( deltaX ) {
picOrigin . y = 0 ;
if ( deltaX > 0 ) {
scroll - > x = picOrigin . x = - gameRect . width ( ) ;
} else {
scroll - > x = picOrigin . x = gameRect . width ( ) ;
}
} else {
picOrigin . x = 0 ;
if ( deltaY > 0 ) {
scroll - > y = picOrigin . y = - gameRect . height ( ) ;
} else {
scroll - > y = picOrigin . y = gameRect . height ( ) ;
}
}
scroll - > oldPictureId = plane - > addPic ( pictureId , picOrigin , mirrorX ) ;
if ( animate ) {
_scrolls . push_front ( * scroll ) ;
} else {
bool finished = false ;
while ( ! finished & & ! g_engine - > shouldQuit ( ) ) {
finished = processScroll ( * scroll ) ;
g_sci - > _gfxFrameout - > frameOut ( true ) ;
2016-12-12 15:13:36 -06:00
throttle ( 33 ) ;
2016-07-25 11:06:27 -05:00
}
}
2016-08-28 20:22:44 -05:00
delete scroll ;
2016-07-25 11:06:27 -05:00
}
bool GfxTransitions32 : : processScroll ( PlaneScroll & scroll ) {
bool finished = false ;
uint32 now = g_sci - > getTickCount ( ) ;
if ( scroll . startTick > = now ) {
return false ;
}
int deltaX = scroll . deltaX ;
int deltaY = scroll . deltaY ;
2016-08-28 20:17:49 -05:00
if ( ( ( scroll . x + deltaX ) * scroll . x ) < = 0 ) {
2016-07-25 11:06:27 -05:00
deltaX = - scroll . x ;
}
if ( ( ( scroll . y + deltaY ) * scroll . y ) < = 0 ) {
deltaY = - scroll . y ;
}
scroll . x + = deltaX ;
scroll . y + = deltaY ;
Plane * plane = g_sci - > _gfxFrameout - > getPlanes ( ) . findByObject ( scroll . plane ) ;
2016-08-28 20:22:29 -05:00
if ( plane = = nullptr ) {
error ( " [GfxTransitions32::processScroll]: Plane %04x:%04x not found " , PRINT_REG ( scroll . plane ) ) ;
}
2016-07-25 11:06:27 -05:00
if ( ( scroll . x = = 0 ) & & ( scroll . y = = 0 ) ) {
plane - > deletePic ( scroll . oldPictureId , scroll . newPictureId ) ;
finished = true ;
}
plane - > scrollScreenItems ( deltaX , deltaY , true ) ;
return finished ;
}
} // End of namespace Sci