From d4008562dd5793c88d2c1879be787d60ca485adc Mon Sep 17 00:00:00 2001 From: Omar Emara Date: Fri, 27 Dec 2024 12:09:41 +0100 Subject: [PATCH] Fix #131552: Backdrop has a wrong size of 256x256 The compositor backdrop in certain files always have a size of 256x256 regardless of the actual size of the viewer image. That's because the compositor writes its result to a different image buffer than the one the image engine reads its image buffer from. And the image engine assumes a default size of 256x256. The reason is a bit involved. For non multi-view images, the image module uses the special cache index value of IMA_NO_INDEX for the compositor backdrop, which works fine if the image was detected as a non multi-view image in the first place. However, this detection fails because the compositor may still write multi-view images even for non multi-view renders. In particular, before the compositor writes its viewer image, it ensures correct views by calling BKE_image_ensure_viewer_views, which first checks if we need to recreate the views of the viewer image if they don't match the render views. And in the case of non multi-view image, that check fails in one case. Functions like BKE_image_is_multiview checks if a single unnamed view exists in the image, unnamed being the keyword here. The root issue is that BKE_image_ensure_viewer_views only checks that a single view exists, while it should also check that it is unnamed. Which happens when the user enabled multi-view, added only one view, then disabled multi-view again. To fix this, we add a check for the name of the view in case of non multi-view images. And additionally pull the view matching code into its own documented utility function for clarity. Pull Request: https://projects.blender.org/blender/blender/pulls/132348 --- source/blender/blenkernel/intern/image.cc | 63 ++++++++++++++++------- 1 file changed, 44 insertions(+), 19 deletions(-) diff --git a/source/blender/blenkernel/intern/image.cc b/source/blender/blenkernel/intern/image.cc index 7cc743c2d1a..3fde8bc99d5 100644 --- a/source/blender/blenkernel/intern/image.cc +++ b/source/blender/blenkernel/intern/image.cc @@ -2813,33 +2813,58 @@ static void image_viewer_create_views(const RenderData *rd, Image *ima) } } +/* Returns true if the views of the given image match the actives views in the given render data. + * Returns false otherwise to indicate that the image views should be recreated to make them match + * the render data. */ +static bool image_views_match_render_views(const Image *image, const RenderData *render_data) +{ + /* The number of views in the image do not match the number of active views in the render + * data. */ + const int number_of_active_views = BKE_scene_multiview_num_views_get(render_data); + if (BLI_listbase_count(&image->views) != number_of_active_views) { + return false; + } + + /* If the render data is not multi-view, then a single unnamed view should exist in the image, + * otherwise, the views don't match. We don't have to check that a single view exist, since this + * is handled by the check above for the number of views. */ + if (!(render_data->scemode & R_MULTIVIEW)) { + const ImageView *image_view = static_cast(image->views.first); + /* If the view is unnamed, the views match, otherwise, they don't. */ + return image_view->name[0] == '\0'; + } + + /* The render data is multi-view, so we need to check that for every view in the image, a + * corresponding active render view with the same name exists, noting that they may not + * necessarily be in the same order. */ + LISTBASE_FOREACH (ImageView *, image_view, &image->views) { + SceneRenderView *scene_render_view = static_cast( + BLI_findstring(&render_data->views, image_view->name, offsetof(SceneRenderView, name))); + /* A render view doesn't exist for that image view with the same name, so the views don't + * match. */ + if (!scene_render_view) { + return false; + } + + /* A render view exists for that image view with the same name, but it is disabled, so the + * views don't match. */ + if (!BKE_scene_multiview_is_render_view_active(render_data, scene_render_view)) { + return false; + } + } + + return true; +} + void BKE_image_ensure_viewer_views(const RenderData *rd, Image *ima, ImageUser *iuser) { - bool do_reset; - const bool is_multiview = (rd->scemode & R_MULTIVIEW) != 0; - BLI_thread_lock(LOCK_DRAW_IMAGE); if (!BKE_scene_multiview_is_stereo3d(rd)) { iuser->flag &= ~IMA_SHOW_STEREO; } - /* see if all scene render views are in the image view list */ - do_reset = (BKE_scene_multiview_num_views_get(rd) != BLI_listbase_count(&ima->views)); - - /* multiview also needs to be sure all the views are synced */ - if (is_multiview && !do_reset) { - LISTBASE_FOREACH (ImageView *, iv, &ima->views) { - SceneRenderView *srv = static_cast( - BLI_findstring(&rd->views, iv->name, offsetof(SceneRenderView, name))); - if ((srv == nullptr) || (BKE_scene_multiview_is_render_view_active(rd, srv) == false)) { - do_reset = true; - break; - } - } - } - - if (do_reset) { + if (!image_views_match_render_views(ima, rd)) { BLI_mutex_lock(static_cast(ima->runtime.cache_mutex)); image_free_cached_frames(ima);