Fix use-after-free when switching blitters in SDL and Win32 modes.
This mostly occurs when disabling pallete animation when fast-forward is enabled.
This commit is contained in:
@@ -23,6 +23,7 @@
|
|||||||
#include "clear_map.h"
|
#include "clear_map.h"
|
||||||
#include "clear_func.h"
|
#include "clear_func.h"
|
||||||
#include "tree_map.h"
|
#include "tree_map.h"
|
||||||
|
#include "scope.h"
|
||||||
#include "table/tree_land.h"
|
#include "table/tree_land.h"
|
||||||
#include "blitter/32bpp_base.hpp"
|
#include "blitter/32bpp_base.hpp"
|
||||||
|
|
||||||
@@ -331,6 +332,11 @@ static bool SwitchNewGRFBlitter()
|
|||||||
const bool animation_wanted = HasBit(_display_opt, DO_FULL_ANIMATION);
|
const bool animation_wanted = HasBit(_display_opt, DO_FULL_ANIMATION);
|
||||||
const char *cur_blitter = BlitterFactory::GetCurrentBlitter()->GetName();
|
const char *cur_blitter = BlitterFactory::GetCurrentBlitter()->GetName();
|
||||||
|
|
||||||
|
VideoDriver::GetInstance()->AcquireBlitterLock();
|
||||||
|
auto guard = scope_guard([&]() {
|
||||||
|
VideoDriver::GetInstance()->ReleaseBlitterLock();
|
||||||
|
});
|
||||||
|
|
||||||
for (uint i = 0; i < lengthof(replacement_blitters); i++) {
|
for (uint i = 0; i < lengthof(replacement_blitters); i++) {
|
||||||
if (animation_wanted && (replacement_blitters[i].animation == 0)) continue;
|
if (animation_wanted && (replacement_blitters[i].animation == 0)) continue;
|
||||||
if (!animation_wanted && (replacement_blitters[i].animation == 1)) continue;
|
if (!animation_wanted && (replacement_blitters[i].animation == 1)) continue;
|
||||||
|
@@ -830,11 +830,18 @@ bool VideoDriver_SDL::ToggleFullscreen(bool fullscreen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool VideoDriver_SDL::AfterBlitterChange()
|
bool VideoDriver_SDL::AfterBlitterChange()
|
||||||
|
{
|
||||||
|
return CreateMainSurface(_screen.width, _screen.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoDriver_SDL::AcquireBlitterLock()
|
||||||
{
|
{
|
||||||
if (_draw_mutex != NULL) _draw_mutex->BeginCritical(true);
|
if (_draw_mutex != NULL) _draw_mutex->BeginCritical(true);
|
||||||
bool ret = CreateMainSurface(_screen.width, _screen.height);
|
}
|
||||||
|
|
||||||
|
void VideoDriver_SDL::ReleaseBlitterLock()
|
||||||
|
{
|
||||||
if (_draw_mutex != NULL) _draw_mutex->EndCritical(true);
|
if (_draw_mutex != NULL) _draw_mutex->EndCritical(true);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* WITH_SDL */
|
#endif /* WITH_SDL */
|
||||||
|
@@ -31,6 +31,10 @@ public:
|
|||||||
|
|
||||||
/* virtual */ bool AfterBlitterChange();
|
/* virtual */ bool AfterBlitterChange();
|
||||||
|
|
||||||
|
/* virtual */ void AcquireBlitterLock();
|
||||||
|
|
||||||
|
/* virtual */ void ReleaseBlitterLock();
|
||||||
|
|
||||||
/* virtual */ bool ClaimMousePointer();
|
/* virtual */ bool ClaimMousePointer();
|
||||||
|
|
||||||
/* virtual */ const char *GetName() const { return "sdl"; }
|
/* virtual */ const char *GetName() const { return "sdl"; }
|
||||||
|
@@ -49,6 +49,7 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback invoked after the blitter was changed.
|
* Callback invoked after the blitter was changed.
|
||||||
|
* This may only be called between AcquireBlitterLock and ReleaseBlitterLock.
|
||||||
* @return True if no error.
|
* @return True if no error.
|
||||||
*/
|
*/
|
||||||
virtual bool AfterBlitterChange()
|
virtual bool AfterBlitterChange()
|
||||||
@@ -56,6 +57,18 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Acquire any lock(s) required to be held when changing blitters.
|
||||||
|
* These lock(s) may not be acquired recursively.
|
||||||
|
*/
|
||||||
|
virtual void AcquireBlitterLock() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release any lock(s) required to be held when changing blitters.
|
||||||
|
* These lock(s) may not be acquired recursively.
|
||||||
|
*/
|
||||||
|
virtual void ReleaseBlitterLock() { }
|
||||||
|
|
||||||
virtual bool ClaimMousePointer()
|
virtual bool ClaimMousePointer()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
@@ -1333,11 +1333,18 @@ bool VideoDriver_Win32::ToggleFullscreen(bool full_screen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool VideoDriver_Win32::AfterBlitterChange()
|
bool VideoDriver_Win32::AfterBlitterChange()
|
||||||
|
{
|
||||||
|
return AllocateDibSection(_screen.width, _screen.height, true) && this->MakeWindow(_fullscreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VideoDriver_Win32::AcquireBlitterLock()
|
||||||
{
|
{
|
||||||
if (_draw_mutex != NULL) _draw_mutex->BeginCritical(true);
|
if (_draw_mutex != NULL) _draw_mutex->BeginCritical(true);
|
||||||
bool ret = AllocateDibSection(_screen.width, _screen.height, true) && this->MakeWindow(_fullscreen);
|
}
|
||||||
|
|
||||||
|
void VideoDriver_Win32::ReleaseBlitterLock()
|
||||||
|
{
|
||||||
if (_draw_mutex != NULL) _draw_mutex->EndCritical(true);
|
if (_draw_mutex != NULL) _draw_mutex->EndCritical(true);
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoDriver_Win32::EditBoxLostFocus()
|
void VideoDriver_Win32::EditBoxLostFocus()
|
||||||
|
@@ -31,6 +31,10 @@ public:
|
|||||||
|
|
||||||
/* virtual */ bool AfterBlitterChange();
|
/* virtual */ bool AfterBlitterChange();
|
||||||
|
|
||||||
|
/* virtual */ void AcquireBlitterLock();
|
||||||
|
|
||||||
|
/* virtual */ void ReleaseBlitterLock();
|
||||||
|
|
||||||
/* virtual */ bool ClaimMousePointer();
|
/* virtual */ bool ClaimMousePointer();
|
||||||
|
|
||||||
/* virtual */ void EditBoxLostFocus();
|
/* virtual */ void EditBoxLostFocus();
|
||||||
|
Reference in New Issue
Block a user