summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Lutz <michi@icosahedron.de>2021-05-01 19:55:46 +0200
committerMichael Lutz <michi@icosahedron.de>2021-05-02 17:57:24 +0200
commit1f159f79de7428cbaa6133ec9cf06ce559980ea6 (patch)
treeebdfebfbca17f8ab485198b48c473a1138f3be8f
parent91b8ce073f54dff48cd61186c32d0a720a2abb4d (diff)
downloadopenttd-1f159f79de7428cbaa6133ec9cf06ce559980ea6.tar.xz
Fix #9147: Delay making screenshots until the next draw tick as we may not access the video buffer from the game thread.
-rw-r--r--src/console_cmds.cpp2
-rw-r--r--src/screenshot.cpp38
-rw-r--r--src/screenshot.h2
3 files changed, 32 insertions, 10 deletions
diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp
index 69a44e63d..99b3b5458 100644
--- a/src/console_cmds.cpp
+++ b/src/console_cmds.cpp
@@ -1416,7 +1416,7 @@ DEF_CONSOLE_CMD(ConScreenShot)
ScreenshotType type = SC_VIEWPORT;
uint32 width = 0;
uint32 height = 0;
- const char *name = nullptr;
+ std::string name{};
uint32 arg_index = 1;
if (argc > arg_index) {
diff --git a/src/screenshot.cpp b/src/screenshot.cpp
index dc76996fb..0e3bf3d8e 100644
--- a/src/screenshot.cpp
+++ b/src/screenshot.cpp
@@ -864,7 +864,7 @@ static ScreenshotType _confirmed_screenshot_type; ///< Screenshot type the curre
*/
static void ScreenshotConfirmationCallback(Window *w, bool confirmed)
{
- if (confirmed) MakeScreenshot(_confirmed_screenshot_type, nullptr);
+ if (confirmed) MakeScreenshot(_confirmed_screenshot_type, {});
}
/**
@@ -890,24 +890,20 @@ void MakeScreenshotWithConfirm(ScreenshotType t)
ShowQuery(STR_WARNING_SCREENSHOT_SIZE_CAPTION, STR_WARNING_SCREENSHOT_SIZE_MESSAGE, nullptr, ScreenshotConfirmationCallback);
} else {
/* Less than 64M pixels, just do it */
- MakeScreenshot(t, nullptr);
+ MakeScreenshot(t, {});
}
}
/**
* Make a screenshot.
- * Unconditionally take a screenshot of the requested type.
* @param t the type of screenshot to make.
* @param name the name to give to the screenshot.
* @param width the width of the screenshot of, or 0 for current viewport width (only works for SC_ZOOMEDIN and SC_DEFAULTZOOM).
* @param height the height of the screenshot of, or 0 for current viewport height (only works for SC_ZOOMEDIN and SC_DEFAULTZOOM).
* @return true iff the screenshot was made successfully
- * @see MakeScreenshotWithConfirm
*/
-bool MakeScreenshot(ScreenshotType t, const char *name, uint32 width, uint32 height)
+static bool RealMakeScreenshot(ScreenshotType t, std::string name, uint32 width, uint32 height)
{
- VideoDriver::VideoBufferLocker lock;
-
if (t == SC_VIEWPORT) {
/* First draw the dirty parts of the screen and only then change the name
* of the screenshot. This way the screenshot will always show the name
@@ -918,7 +914,7 @@ bool MakeScreenshot(ScreenshotType t, const char *name, uint32 width, uint32 hei
}
_screenshot_name[0] = '\0';
- if (name != nullptr) strecpy(_screenshot_name, name, lastof(_screenshot_name));
+ if (!name.empty()) strecpy(_screenshot_name, name.c_str(), lastof(_screenshot_name));
bool ret;
switch (t) {
@@ -969,6 +965,32 @@ bool MakeScreenshot(ScreenshotType t, const char *name, uint32 width, uint32 hei
return ret;
}
+/**
+ * Schedule making a screenshot.
+ * Unconditionally take a screenshot of the requested type.
+ * @param t the type of screenshot to make.
+ * @param name the name to give to the screenshot.
+ * @param width the width of the screenshot of, or 0 for current viewport width (only works for SC_ZOOMEDIN and SC_DEFAULTZOOM).
+ * @param height the height of the screenshot of, or 0 for current viewport height (only works for SC_ZOOMEDIN and SC_DEFAULTZOOM).
+ * @return true iff the screenshot was successfully made.
+ * @see MakeScreenshotWithConfirm
+ */
+bool MakeScreenshot(ScreenshotType t, std::string name, uint32 width, uint32 height)
+{
+ if (t == SC_CRASHLOG) {
+ /* Video buffer might or might not be locked. */
+ VideoDriver::VideoBufferLocker lock;
+
+ return RealMakeScreenshot(t, name, width, height);
+ }
+
+ VideoDriver::GetInstance()->QueueOnMainThread([=] { // Capture by value to not break scope.
+ RealMakeScreenshot(t, name, width, height);
+ });
+
+ return true;
+}
+
/**
* Return the owner of a tile to display it with in the small map in mode "Owner".
diff --git a/src/screenshot.h b/src/screenshot.h
index 148c018e1..e65813573 100644
--- a/src/screenshot.h
+++ b/src/screenshot.h
@@ -28,7 +28,7 @@ enum ScreenshotType {
void SetupScreenshotViewport(ScreenshotType t, struct Viewport *vp, uint32 width = 0, uint32 height = 0);
bool MakeHeightmapScreenshot(const char *filename);
void MakeScreenshotWithConfirm(ScreenshotType t);
-bool MakeScreenshot(ScreenshotType t, const char *name, uint32 width = 0, uint32 height = 0);
+bool MakeScreenshot(ScreenshotType t, std::string name, uint32 width = 0, uint32 height = 0);
bool MakeMinimapWorldScreenshot();
extern char _screenshot_format_name[8];