From ebaa3fcedd2388c6e1a213911b79bfdc1e49df78 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Mon, 25 Jan 2021 11:17:03 +0100 Subject: Fix T84398: Multiview images show only one view. The `image_get_gpu_texture` didn't use the iuser->view_index but recalculated the requested view again. This lead to inconsistent behavior when switching between multi view textures or stereo textures. This has been fixed by ensuring that the `iuser->view_index` is always used. An Image has only place to store 2 view textures. This is done for right/left eye compositing. A multi view texture can have more views. This would lead to reading and writing to unallocated space. When a multiview texture is requested that is larger than 1. It will always be cached as being the first eye. The `gpu_view` of the Image is also used as a cache key to check this. --- source/blender/blenkernel/intern/image_gpu.c | 18 ++++++++++++++---- source/blender/draw/engines/image/image_engine.c | 4 +--- source/blender/makesdna/DNA_image_types.h | 1 + 3 files changed, 16 insertions(+), 7 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenkernel/intern/image_gpu.c b/source/blender/blenkernel/intern/image_gpu.c index 05aa3c89a84..a6bd65227a0 100644 --- a/source/blender/blenkernel/intern/image_gpu.c +++ b/source/blender/blenkernel/intern/image_gpu.c @@ -271,6 +271,7 @@ static GPUTexture **get_image_gpu_texture_ptr(Image *ima, { const bool in_range = (textarget >= 0) && (textarget < TEXTARGET_COUNT); BLI_assert(in_range); + BLI_assert(multiview_eye == 0 || multiview_eye == 1); if (in_range) { return &(ima->gputexture[textarget][multiview_eye]); @@ -310,9 +311,17 @@ static GPUTexture *image_get_gpu_texture(Image *ima, * the current `pass` and `layer` should be 0. */ short requested_pass = iuser ? iuser->pass : 0; short requested_layer = iuser ? iuser->layer : 0; - if (ima->gpu_pass != requested_pass || ima->gpu_layer != requested_layer) { + short requested_view = iuser ? iuser->multi_index : 0; + /* There is room for 2 multiview textures. When a higher number is requested we should always + * target the first view slot. This is fine as multi view images aren't used together. */ + if (requested_view < 2) { + requested_view = 0; + } + if (ima->gpu_pass != requested_pass || ima->gpu_layer != requested_layer || + ima->gpu_view != requested_view) { ima->gpu_pass = requested_pass; ima->gpu_layer = requested_layer; + ima->gpu_view = requested_view; ima->gpuflag |= IMA_GPU_REFRESH; } @@ -345,9 +354,10 @@ static GPUTexture *image_get_gpu_texture(Image *ima, BKE_image_tag_time(ima); /* Test if we already have a texture. */ - const int current_view = iuser ? ((iuser->flag & IMA_SHOW_STEREO) != 0 ? iuser->multiview_eye : - iuser->view) : - 0; + int current_view = iuser ? iuser->multi_index : 0; + if (current_view >= 2) { + current_view = 0; + } GPUTexture **tex = get_image_gpu_texture_ptr(ima, textarget, current_view); if (*tex) { return *tex; diff --git a/source/blender/draw/engines/image/image_engine.c b/source/blender/draw/engines/image/image_engine.c index 5445685b5ba..04bdee131d7 100644 --- a/source/blender/draw/engines/image/image_engine.c +++ b/source/blender/draw/engines/image/image_engine.c @@ -110,9 +110,7 @@ static void space_image_gpu_texture_get(Image *image, /* update multiindex and pass for the current eye */ BKE_image_multilayer_index(image->rr, &sima->iuser); } - else { - BKE_image_multiview_index(image, &sima->iuser); - } + BKE_image_multiview_index(image, &sima->iuser); if (ibuf) { if (sima->flag & SI_SHOW_ZBUF && (ibuf->zbuf || ibuf->zbuf_float || (ibuf->channels == 1))) { diff --git a/source/blender/makesdna/DNA_image_types.h b/source/blender/makesdna/DNA_image_types.h index eb03e047c90..5db30b70449 100644 --- a/source/blender/makesdna/DNA_image_types.h +++ b/source/blender/makesdna/DNA_image_types.h @@ -157,6 +157,7 @@ typedef struct Image { short gpuflag; short gpu_pass; short gpu_layer; + short gpu_view; char _pad2[6]; /** Deprecated. */ -- cgit v1.2.3