summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfrosch <frosch@openttd.org>2017-03-11 13:05:54 +0000
committerfrosch <frosch@openttd.org>2017-03-11 13:05:54 +0000
commitb1fe837b8ea3b42ab062ed1856d7bed53d5a2473 (patch)
treef3d63ee5f9d9a35d1790e35efc47afb7b56b2eb1
parentd5f82bf55b8a0e4c522066118a6e0d980651ae92 (diff)
downloadopenttd-b1fe837b8ea3b42ab062ed1856d7bed53d5a2473.tar.xz
(svn r27775) -Fix [FS#6510]: Insufficient thread synchronisation when switching blitters. (JGR)
-rw-r--r--src/gfxinit.cpp9
-rw-r--r--src/video/sdl_v.cpp11
-rw-r--r--src/video/sdl_v.h4
-rw-r--r--src/video/video_driver.hpp13
-rw-r--r--src/video/win32_v.cpp11
-rw-r--r--src/video/win32_v.h4
6 files changed, 47 insertions, 5 deletions
diff --git a/src/gfxinit.cpp b/src/gfxinit.cpp
index 6dea627dd..06534ad29 100644
--- a/src/gfxinit.cpp
+++ b/src/gfxinit.cpp
@@ -290,6 +290,8 @@ static bool SwitchNewGRFBlitter()
const bool animation_wanted = HasBit(_display_opt, DO_FULL_ANIMATION);
const char *cur_blitter = BlitterFactory::GetCurrentBlitter()->GetName();
+ VideoDriver::GetInstance()->AcquireBlitterLock();
+
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 == 1)) continue;
@@ -298,7 +300,10 @@ static bool SwitchNewGRFBlitter()
if (!IsInsideMM(depth_wanted_by_grf, replacement_blitters[i].min_grf_depth, replacement_blitters[i].max_grf_depth + 1)) continue;
const char *repl_blitter = replacement_blitters[i].name;
- if (strcmp(repl_blitter, cur_blitter) == 0) return false;
+ if (strcmp(repl_blitter, cur_blitter) == 0) {
+ VideoDriver::GetInstance()->ReleaseBlitterLock();
+ return false;
+ }
if (BlitterFactory::GetBlitterFactory(repl_blitter) == NULL) continue;
DEBUG(misc, 1, "Switching blitter from '%s' to '%s'... ", cur_blitter, repl_blitter);
@@ -313,6 +318,8 @@ static bool SwitchNewGRFBlitter()
if (BlitterFactory::SelectBlitter(cur_blitter) == NULL || !VideoDriver::GetInstance()->AfterBlitterChange()) usererror("Failed to reinitialize video driver. Specify a fixed blitter in the config");
}
+ VideoDriver::GetInstance()->ReleaseBlitterLock();
+
return true;
}
diff --git a/src/video/sdl_v.cpp b/src/video/sdl_v.cpp
index 4bb44c9d7..3668f8602 100644
--- a/src/video/sdl_v.cpp
+++ b/src/video/sdl_v.cpp
@@ -818,10 +818,17 @@ bool VideoDriver_SDL::ToggleFullscreen(bool fullscreen)
bool VideoDriver_SDL::AfterBlitterChange()
{
+ return CreateMainSurface(_screen.width, _screen.height);
+}
+
+void VideoDriver_SDL::AcquireBlitterLock()
+{
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);
- return ret;
}
#endif /* WITH_SDL */
diff --git a/src/video/sdl_v.h b/src/video/sdl_v.h
index 730f82b93..8855c3566 100644
--- a/src/video/sdl_v.h
+++ b/src/video/sdl_v.h
@@ -31,6 +31,10 @@ public:
/* virtual */ bool AfterBlitterChange();
+ /* virtual */ void AcquireBlitterLock();
+
+ /* virtual */ void ReleaseBlitterLock();
+
/* virtual */ bool ClaimMousePointer();
/* virtual */ const char *GetName() const { return "sdl"; }
diff --git a/src/video/video_driver.hpp b/src/video/video_driver.hpp
index 916044d35..5cb3c6cc3 100644
--- a/src/video/video_driver.hpp
+++ b/src/video/video_driver.hpp
@@ -49,6 +49,7 @@ public:
/**
* Callback invoked after the blitter was changed.
+ * This may only be called between AcquireBlitterLock and ReleaseBlitterLock.
* @return True if no error.
*/
virtual bool AfterBlitterChange()
@@ -56,6 +57,18 @@ public:
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()
{
return true;
diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp
index c37ebd7dd..e536ae8e5 100644
--- a/src/video/win32_v.cpp
+++ b/src/video/win32_v.cpp
@@ -1334,10 +1334,17 @@ bool VideoDriver_Win32::ToggleFullscreen(bool full_screen)
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);
- bool ret = AllocateDibSection(_screen.width, _screen.height, true) && this->MakeWindow(_fullscreen);
+}
+
+void VideoDriver_Win32::ReleaseBlitterLock()
+{
if (_draw_mutex != NULL) _draw_mutex->EndCritical(true);
- return ret;
}
void VideoDriver_Win32::EditBoxLostFocus()
diff --git a/src/video/win32_v.h b/src/video/win32_v.h
index 21d59185b..7609d0422 100644
--- a/src/video/win32_v.h
+++ b/src/video/win32_v.h
@@ -31,6 +31,10 @@ public:
/* virtual */ bool AfterBlitterChange();
+ /* virtual */ void AcquireBlitterLock();
+
+ /* virtual */ void ReleaseBlitterLock();
+
/* virtual */ bool ClaimMousePointer();
/* virtual */ void EditBoxLostFocus();