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
This commit is contained in:
Omar Emara
2024-12-27 12:09:41 +01:00
committed by Omar Emara
parent b3762d5820
commit d4008562dd

View File

@@ -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<ImageView *>(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<SceneRenderView *>(
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<SceneRenderView *>(
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<ThreadMutex *>(ima->runtime.cache_mutex));
image_free_cached_frames(ima);