Fix crash saving blend files in background mode

Reading the windows pixels was attempted in background mode.
This commit is contained in:
Campbell Barton 2021-11-12 17:35:22 +11:00
parent d612d92630
commit f133c6b094
1 changed files with 50 additions and 44 deletions

View File

@ -1558,15 +1558,16 @@ static void wm_history_file_update(void)
* Screen-shot the active window.
* \{ */
static ImBuf *blend_file_thumb_from_screenshot(bContext *C, BlendThumbnail **thumb_pt)
static ImBuf *blend_file_thumb_from_screenshot(bContext *C, BlendThumbnail **r_thumb)
{
if (*thumb_pt) {
/* We are given a valid thumbnail data, so just generate image from it. */
return BKE_main_thumbnail_to_imbuf(NULL, *thumb_pt);
*r_thumb = NULL;
wmWindow *win = CTX_wm_window(C);
if (G.background || (win == NULL)) {
return NULL;
}
/* The window to capture should be a main window (without parent). */
wmWindow *win = CTX_wm_window(C);
while (win && win->parent) {
win = win->parent;
}
@ -1595,7 +1596,7 @@ static ImBuf *blend_file_thumb_from_screenshot(bContext *C, BlendThumbnail **thu
BlendThumbnail *thumb = BKE_main_thumbnail_from_imbuf(NULL, thumb_ibuf);
IMB_freeImBuf(thumb_ibuf);
*thumb_pt = thumb;
*r_thumb = thumb;
}
/* Must be freed by caller. */
@ -1614,8 +1615,15 @@ static ImBuf *blend_file_thumb_from_screenshot(bContext *C, BlendThumbnail **thu
static ImBuf *blend_file_thumb_from_camera(const bContext *C,
Scene *scene,
bScreen *screen,
BlendThumbnail **thumb_pt)
BlendThumbnail **r_thumb)
{
*r_thumb = NULL;
/* Scene can be NULL if running a script at startup and calling the save operator. */
if (G.background || scene == NULL) {
return NULL;
}
/* will be scaled down, but gives some nice oversampling */
ImBuf *ibuf;
BlendThumbnail *thumb;
@ -1629,17 +1637,6 @@ static ImBuf *blend_file_thumb_from_camera(const bContext *C,
ARegion *region = NULL;
View3D *v3d = NULL;
/* In case we are given a valid thumbnail data, just generate image from it. */
if (*thumb_pt) {
thumb = *thumb_pt;
return BKE_main_thumbnail_to_imbuf(NULL, thumb);
}
/* scene can be NULL if running a script at startup and calling the save operator */
if (G.background || scene == NULL) {
return NULL;
}
if (screen != NULL) {
area = BKE_screen_find_big_area(screen, SPACE_VIEW3D, 0);
if (area) {
@ -1713,13 +1710,13 @@ static ImBuf *blend_file_thumb_from_camera(const bContext *C,
IMB_scaleImBuf(ibuf, PREVIEW_RENDER_LARGE_HEIGHT, PREVIEW_RENDER_LARGE_HEIGHT);
}
else {
/* '*thumb_pt' needs to stay NULL to prevent a bad thumbnail from being handled */
/* '*r_thumb' needs to stay NULL to prevent a bad thumbnail from being handled. */
CLOG_WARN(&LOG, "failed to create thumbnail: %s", err_out);
thumb = NULL;
}
/* must be freed by caller */
*thumb_pt = thumb;
*r_thumb = thumb;
return ibuf;
}
@ -1752,7 +1749,7 @@ static bool wm_file_write(bContext *C,
Main *bmain = CTX_data_main(C);
int len;
int ok = false;
BlendThumbnail *thumb, *main_thumb;
BlendThumbnail *thumb = NULL, *main_thumb = NULL;
ImBuf *ibuf_thumb = NULL;
len = strlen(filepath);
@ -1802,33 +1799,42 @@ static bool wm_file_write(bContext *C,
/* don't forget not to return without! */
WM_cursor_wait(true);
/* blend file thumbnail */
/* Save before exit_editmode, otherwise derivedmeshes for shared data corrupt T27765. */
/* Main now can store a '.blend' thumbnail, useful for background mode
* or thumbnail customization. */
main_thumb = thumb = bmain->blen_thumb;
if (BLI_thread_is_main() && U.file_preview_type != USER_FILE_PREVIEW_NONE) {
int file_preview_type = U.file_preview_type;
if (file_preview_type == USER_FILE_PREVIEW_AUTO) {
Scene *scene = CTX_data_scene(C);
bool do_render = (scene != NULL && scene->camera != NULL &&
(BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_VIEW3D, 0) != NULL));
file_preview_type = do_render ? USER_FILE_PREVIEW_CAMERA : USER_FILE_PREVIEW_SCREENSHOT;
if (U.file_preview_type != USER_FILE_PREVIEW_NONE) {
/* Blend file thumbnail.
*
* - Save before exiting edit-mode, otherwise evaluated-mesh for shared data gets corrupted.
* See T27765.
* - Main can store a '.blend' thumbnail,
* useful for background-mode or thumbnail customization.
*/
main_thumb = thumb = bmain->blen_thumb;
if (thumb != NULL) {
/* In case we are given a valid thumbnail data, just generate image from it. */
ibuf_thumb = BKE_main_thumbnail_to_imbuf(NULL, thumb);
}
else if (BLI_thread_is_main()) {
int file_preview_type = U.file_preview_type;
switch (file_preview_type) {
case USER_FILE_PREVIEW_SCREENSHOT: {
ibuf_thumb = blend_file_thumb_from_screenshot(C, &thumb);
break;
if (file_preview_type == USER_FILE_PREVIEW_AUTO) {
Scene *scene = CTX_data_scene(C);
bool do_render = (scene != NULL && scene->camera != NULL &&
(BKE_screen_find_big_area(CTX_wm_screen(C), SPACE_VIEW3D, 0) != NULL));
file_preview_type = do_render ? USER_FILE_PREVIEW_CAMERA : USER_FILE_PREVIEW_SCREENSHOT;
}
case USER_FILE_PREVIEW_CAMERA: {
ibuf_thumb = blend_file_thumb_from_camera(C, CTX_data_scene(C), CTX_wm_screen(C), &thumb);
break;
switch (file_preview_type) {
case USER_FILE_PREVIEW_SCREENSHOT: {
ibuf_thumb = blend_file_thumb_from_screenshot(C, &thumb);
break;
}
case USER_FILE_PREVIEW_CAMERA: {
ibuf_thumb = blend_file_thumb_from_camera(
C, CTX_data_scene(C), CTX_wm_screen(C), &thumb);
break;
}
default:
BLI_assert_unreachable();
}
default:
BLI_assert_unreachable();
}
}