Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeroen Bakker <jbakker>2020-03-19 10:06:49 +0300
committerJeroen Bakker <jeroen@blender.org>2020-03-19 10:26:48 +0300
commitfd48ff1296f45b32bffeca2c60dca2a12bb84229 (patch)
tree250137802d4bed0628a7926df724227349320757
parentfe045b2b77dc6d7f0b552619fe824b496d34db6c (diff)
Fix T73931: Stereo Viewport Color Management
Stereoscopic viewport didn't support Color Manangement due recent changes in the color management pipeline. In order to solve the issue we will migrate the strereo rendering into the GPUViewport. This will share some textures and reduce required GPU memory. Reviewed By: fclem, dfelinto Differential Revision: https://developer.blender.org/D6922
-rw-r--r--source/blender/draw/DRW_engine_types.h3
-rw-r--r--source/blender/draw/intern/draw_manager.c6
-rw-r--r--source/blender/editors/space_image/space_image.c3
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c10
-rw-r--r--source/blender/gpu/CMakeLists.txt2
-rw-r--r--source/blender/gpu/GPU_shader.h14
-rw-r--r--source/blender/gpu/GPU_viewport.h13
-rw-r--r--source/blender/gpu/intern/gpu_framebuffer.c1
-rw-r--r--source/blender/gpu/intern/gpu_shader.c12
-rw-r--r--source/blender/gpu/intern/gpu_state.c3
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c265
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl35
-rw-r--r--source/blender/gpu/shaders/gpu_shader_image_overlays_stereo_merge_frag.glsl47
-rw-r--r--source/blender/windowmanager/WM_api.h2
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c73
-rw-r--r--source/blender/windowmanager/intern/wm_stereo.c94
-rw-r--r--source/blender/windowmanager/intern/wm_xr.c2
-rw-r--r--source/blender/windowmanager/wm.h2
-rw-r--r--source/blender/windowmanager/wm_draw.h2
19 files changed, 332 insertions, 257 deletions
diff --git a/source/blender/draw/DRW_engine_types.h b/source/blender/draw/DRW_engine_types.h
index dd56f87182c..d31bab5a1b5 100644
--- a/source/blender/draw/DRW_engine_types.h
+++ b/source/blender/draw/DRW_engine_types.h
@@ -35,11 +35,14 @@ typedef struct DefaultFramebufferList {
struct GPUFrameBuffer *color_only_fb;
struct GPUFrameBuffer *depth_only_fb;
struct GPUFrameBuffer *overlay_only_fb;
+ struct GPUFrameBuffer *stereo_comp_fb;
} DefaultFramebufferList;
typedef struct DefaultTextureList {
struct GPUTexture *color;
struct GPUTexture *color_overlay;
+ struct GPUTexture *color_stereo;
+ struct GPUTexture *color_overlay_stereo;
struct GPUTexture *depth;
struct GPUTexture *depth_in_front;
} DefaultTextureList;
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index df3a1e3da79..0c049e030b1 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -1218,7 +1218,7 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx)
/* Separate update for each stereo view. */
for (int view = 0; view < 2; view++) {
- GPUViewport *viewport = WM_draw_region_get_viewport(region, view);
+ GPUViewport *viewport = WM_draw_region_get_viewport(region);
if (!viewport) {
continue;
}
@@ -1232,6 +1232,7 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx)
drw_state_prepare_clean_for_draw(&DST);
DST.viewport = viewport;
+ GPU_viewport_active_view_set(viewport, view);
DST.draw_ctx = (DRWContextState){
.region = region,
.rv3d = rv3d,
@@ -1416,7 +1417,6 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
DST.draw_ctx.evil_C = evil_C;
DST.viewport = viewport;
-
/* Setup viewport */
DST.draw_ctx = (DRWContextState){
.region = region,
@@ -2374,7 +2374,7 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, cons
drw_context_state_init();
/* Setup viewport */
- DST.viewport = WM_draw_region_get_viewport(region, 0);
+ DST.viewport = WM_draw_region_get_viewport(region);
drw_viewport_var_init();
/* Update ubos */
diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c
index 42a8a746eef..1fff40ab73a 100644
--- a/source/blender/editors/space_image/space_image.c
+++ b/source/blender/editors/space_image/space_image.c
@@ -646,8 +646,7 @@ static void image_main_region_draw(const bContext *C, ARegion *region)
* old context since we now use it for drawing the entire area. */
gpu_batch_presets_reset();
- GPUViewport *viewport =
- region->draw_buffer->viewport[region->draw_buffer->stereo ? sima->iuser.multiview_eye : 0];
+ GPUViewport *viewport = region->draw_buffer->viewport;
DefaultFramebufferList *fbl = GPU_viewport_framebuffer_list_get(viewport);
GPU_framebuffer_bind(fbl->default_fb);
GPU_clear_color(0.0f, 0.0f, 0.0f, 0.0f);
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 78d053c36a7..75865bc50e1 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -855,7 +855,7 @@ void ED_view3d_draw_depth(Depsgraph *depsgraph, ARegion *region, View3D *v3d, bo
WM_draw_region_viewport_ensure(region, SPACE_VIEW3D);
WM_draw_region_viewport_bind(region);
- GPUViewport *viewport = WM_draw_region_get_viewport(region, 0);
+ GPUViewport *viewport = WM_draw_region_get_viewport(region);
/* When Blender is starting, a click event can trigger a depth test while the viewport is not
* yet available. */
if (viewport != NULL) {
@@ -2216,7 +2216,7 @@ void ED_view3d_backbuf_depth_validate(ViewContext *vc)
Object *obact_eval = DEG_get_evaluated_object(vc->depsgraph, vc->obact);
if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE_DEPSGRAPH) != 0)) {
- GPUViewport *viewport = WM_draw_region_get_viewport(region, 0);
+ GPUViewport *viewport = WM_draw_region_get_viewport(region);
DRW_draw_depth_object(vc->region, vc->v3d, viewport, obact_eval);
}
@@ -2279,7 +2279,7 @@ void view3d_update_depths_rect(ARegion *region, ViewDepths *d, rcti *rect)
}
if (d->damaged) {
- GPUViewport *viewport = WM_draw_region_get_viewport(region, 0);
+ GPUViewport *viewport = WM_draw_region_get_viewport(region);
view3d_opengl_read_Z_pixels(viewport, rect, d->depths);
glGetDoublev(GL_DEPTH_RANGE, d->depth_range);
d->damaged = false;
@@ -2308,7 +2308,7 @@ void ED_view3d_depth_update(ARegion *region)
}
if (d->damaged) {
- GPUViewport *viewport = WM_draw_region_get_viewport(region, 0);
+ GPUViewport *viewport = WM_draw_region_get_viewport(region);
rcti r = {
.xmin = 0,
.xmax = d->w,
@@ -2355,7 +2355,7 @@ void ED_view3d_draw_depth_gpencil(Depsgraph *depsgraph, Scene *scene, ARegion *r
GPU_depth_test(true);
- GPUViewport *viewport = WM_draw_region_get_viewport(region, 0);
+ GPUViewport *viewport = WM_draw_region_get_viewport(region);
DRW_draw_depth_loop_gpencil(depsgraph, region, v3d, viewport);
GPU_depth_test(false);
diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt
index 8a900938d2a..cf1d449ad3b 100644
--- a/source/blender/gpu/CMakeLists.txt
+++ b/source/blender/gpu/CMakeLists.txt
@@ -172,6 +172,7 @@ data_to_c_simple(shaders/gpu_shader_2D_image_multi_rect_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_desaturate_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_overlays_merge_frag.glsl SRC)
+data_to_c_simple(shaders/gpu_shader_image_overlays_stereo_merge_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_shuffle_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_mask_uniform_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_modulate_alpha_frag.glsl SRC)
@@ -180,7 +181,6 @@ data_to_c_simple(shaders/gpu_shader_image_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_varying_color_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_depth_linear_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_depth_copy_frag.glsl SRC)
-data_to_c_simple(shaders/gpu_shader_image_interlace_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_image_multisample_resolve_frag.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_image_vert.glsl SRC)
data_to_c_simple(shaders/gpu_shader_3D_vert.glsl SRC)
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index d5716cd1b31..334e295c636 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -184,6 +184,7 @@ typedef enum eGPUBuiltinShader {
GPU_SHADER_3D_CLIPPED_UNIFORM_COLOR,
/* basic image drawing */
GPU_SHADER_2D_IMAGE_OVERLAYS_MERGE,
+ GPU_SHADER_2D_IMAGE_OVERLAYS_STEREO_MERGE,
GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR,
GPU_SHADER_2D_IMAGE_MASK_UNIFORM_COLOR,
/**
@@ -207,8 +208,6 @@ typedef enum eGPUBuiltinShader {
*/
GPU_SHADER_3D_IMAGE_DEPTH,
GPU_SHADER_3D_IMAGE_DEPTH_COPY,
- /* stereo 3d */
- GPU_SHADER_2D_IMAGE_INTERLACE,
/* points */
/**
* Draw round points with a hardcoded size.
@@ -353,17 +352,6 @@ typedef struct GPUShaderConfigData {
/* gpu_shader.c */
extern const GPUShaderConfigData GPU_shader_cfg_data[GPU_SHADER_CFG_LEN];
-/**
- * Keep these in sync with:
- * - `gpu_shader_image_interlace_frag.glsl`
- * - `gpu_shader_image_rect_interlace_frag.glsl`
- */
-typedef enum eGPUInterlaceShader {
- GPU_SHADER_INTERLACE_ROW = 0,
- GPU_SHADER_INTERLACE_COLUMN = 1,
- GPU_SHADER_INTERLACE_CHECKER = 2,
-} eGPUInterlaceShader;
-
GPUShader *GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader,
eGPUShaderConfig sh_cfg);
GPUShader *GPU_shader_get_builtin_shader(eGPUBuiltinShader shader);
diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h
index 848da778d1c..b7b8af9f90a 100644
--- a/source/blender/gpu/GPU_viewport.h
+++ b/source/blender/gpu/GPU_viewport.h
@@ -27,6 +27,7 @@
#include <stdbool.h>
#include "DNA_vec_types.h"
+#include "DNA_scene_types.h"
#include "GPU_framebuffer.h"
#include "GPU_texture.h"
@@ -84,6 +85,8 @@ typedef struct ViewportEngineData {
StorageList *stl;
char info[GPU_INFO_SIZE];
+ TextureList *txl_stereo;
+ StorageList *stl_stereo;
/* we may want to put this elsewhere */
struct DRWTextStore *text_draw_cache;
@@ -101,10 +104,12 @@ typedef struct ViewportEngineData_Info {
} ViewportEngineData_Info;
GPUViewport *GPU_viewport_create(void);
-void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect);
+GPUViewport *GPU_viewport_stereo_create(void);
+void GPU_viewport_bind(GPUViewport *viewport, int view, const rcti *rect);
void GPU_viewport_unbind(GPUViewport *viewport);
-void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect);
+void GPU_viewport_draw_to_screen(GPUViewport *viewport, int view, const rcti *rect);
void GPU_viewport_draw_to_screen_ex(GPUViewport *viewport,
+ int view,
const rcti *rect,
bool display_colorspace);
void GPU_viewport_free(GPUViewport *viewport);
@@ -125,9 +130,11 @@ struct DRWInstanceDataList *GPU_viewport_instance_data_list_get(GPUViewport *vie
void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type);
void *GPU_viewport_engine_data_get(GPUViewport *viewport, void *engine_type);
void *GPU_viewport_framebuffer_list_get(GPUViewport *viewport);
+void GPU_viewport_stereo_composite(GPUViewport *viewport, Stereo3dFormat *stereo_format);
void *GPU_viewport_texture_list_get(GPUViewport *viewport);
void GPU_viewport_size_get(const GPUViewport *viewport, int size[2]);
void GPU_viewport_size_set(GPUViewport *viewport, const int size[2]);
+void GPU_viewport_active_view_set(GPUViewport *viewport, int view);
/* Profiling */
double *GPU_viewport_cache_time_get(GPUViewport *viewport);
@@ -135,7 +142,7 @@ double *GPU_viewport_cache_time_get(GPUViewport *viewport);
void GPU_viewport_tag_update(GPUViewport *viewport);
bool GPU_viewport_do_update(GPUViewport *viewport);
-GPUTexture *GPU_viewport_color_texture(GPUViewport *viewport);
+GPUTexture *GPU_viewport_color_texture(GPUViewport *viewport, int view);
/* Texture pool */
GPUTexture *GPU_viewport_texture_pool_query(
diff --git a/source/blender/gpu/intern/gpu_framebuffer.c b/source/blender/gpu/intern/gpu_framebuffer.c
index 6197d5f99b8..f254cce25e4 100644
--- a/source/blender/gpu/intern/gpu_framebuffer.c
+++ b/source/blender/gpu/intern/gpu_framebuffer.c
@@ -943,6 +943,7 @@ void GPU_offscreen_bind(GPUOffScreen *ofs, bool save)
glDisable(GL_SCISSOR_TEST);
GPUFrameBuffer *ofs_fb = gpu_offscreen_fb_get(ofs);
GPU_framebuffer_bind(ofs_fb);
+ glDisable(GL_FRAMEBUFFER_SRGB);
}
void GPU_offscreen_unbind(GPUOffScreen *UNUSED(ofs), bool restore)
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index 0993d69e14d..620f18629b5 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -81,12 +81,12 @@ extern char datatoc_gpu_shader_2D_nodelink_vert_glsl[];
extern char datatoc_gpu_shader_3D_image_vert_glsl[];
extern char datatoc_gpu_shader_image_frag_glsl[];
extern char datatoc_gpu_shader_image_overlays_merge_frag_glsl[];
+extern char datatoc_gpu_shader_image_overlays_stereo_merge_frag_glsl[];
extern char datatoc_gpu_shader_image_color_frag_glsl[];
extern char datatoc_gpu_shader_image_desaturate_frag_glsl[];
extern char datatoc_gpu_shader_image_varying_color_frag_glsl[];
extern char datatoc_gpu_shader_image_alpha_color_frag_glsl[];
extern char datatoc_gpu_shader_image_shuffle_color_frag_glsl[];
-extern char datatoc_gpu_shader_image_interlace_frag_glsl[];
extern char datatoc_gpu_shader_image_mask_uniform_color_frag_glsl[];
extern char datatoc_gpu_shader_image_modulate_alpha_frag_glsl[];
extern char datatoc_gpu_shader_image_depth_linear_frag_glsl[];
@@ -975,11 +975,6 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = {
"#define USE_DEPTH\n",
},
- [GPU_SHADER_2D_IMAGE_INTERLACE] =
- {
- .vert = datatoc_gpu_shader_2D_image_vert_glsl,
- .frag = datatoc_gpu_shader_image_interlace_frag_glsl,
- },
[GPU_SHADER_2D_CHECKER] =
{
.vert = datatoc_gpu_shader_2D_vert_glsl,
@@ -1017,6 +1012,11 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = {
.vert = datatoc_gpu_shader_2D_image_vert_glsl,
.frag = datatoc_gpu_shader_image_overlays_merge_frag_glsl,
},
+ [GPU_SHADER_2D_IMAGE_OVERLAYS_STEREO_MERGE] =
+ {
+ .vert = datatoc_gpu_shader_2D_image_vert_glsl,
+ .frag = datatoc_gpu_shader_image_overlays_stereo_merge_frag_glsl,
+ },
[GPU_SHADER_2D_IMAGE] =
{
.vert = datatoc_gpu_shader_2D_image_vert_glsl,
diff --git a/source/blender/gpu/intern/gpu_state.c b/source/blender/gpu/intern/gpu_state.c
index 9ff518aec1b..6fd9b167599 100644
--- a/source/blender/gpu/intern/gpu_state.c
+++ b/source/blender/gpu/intern/gpu_state.c
@@ -218,6 +218,7 @@ typedef struct {
uint is_sample_alpha_to_coverage : 1;
uint is_scissor_test : 1;
uint is_stencil_test : 1;
+ uint is_framebuffer_srgb : 1;
bool is_clip_plane[6];
@@ -294,6 +295,7 @@ void gpuPushAttr(eGPUAttrMask mask)
if ((mask & GPU_VIEWPORT_BIT) != 0) {
glGetDoublev(GL_DEPTH_RANGE, (GLdouble *)&Attr.near_far);
glGetIntegerv(GL_VIEWPORT, (GLint *)&Attr.viewport);
+ Attr.is_framebuffer_srgb = glIsEnabled(GL_FRAMEBUFFER_SRGB);
}
if ((mask & GPU_BLEND_BIT) != 0) {
@@ -352,6 +354,7 @@ void gpuPopAttr(void)
if ((mask & GPU_VIEWPORT_BIT) != 0) {
glViewport(Attr.viewport[0], Attr.viewport[1], Attr.viewport[2], Attr.viewport[3]);
glDepthRange(Attr.near_far[0], Attr.near_far[1]);
+ restore_mask(GL_FRAMEBUFFER_SRGB, Attr.is_framebuffer_srgb);
}
if ((mask & GPU_SCISSOR_BIT) != 0) {
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index e4fd5d3f122..750db39d908 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -40,6 +40,7 @@
#include "GPU_framebuffer.h"
#include "GPU_glew.h"
#include "GPU_immediate.h"
+#include "GPU_matrix.h"
#include "GPU_texture.h"
#include "GPU_viewport.h"
#include "GPU_uniformbuffer.h"
@@ -68,7 +69,10 @@ struct GPUViewport {
int size[2];
int flag;
- /* If engine_handles mismatch we free all ViewportEngineData in this viewport */
+ /* Set the active view (for stereoscoptic viewport rendering). */
+ int active_view;
+
+ /* If engine_handles mismatch we free all ViewportEngineData in this viewport. */
struct {
void *handle;
ViewportEngineData *data;
@@ -80,9 +84,10 @@ struct GPUViewport {
ViewportMemoryPool vmempool; /* Used for rendering data structure. */
struct DRWInstanceDataList *idatalist; /* Used for rendering data structure. */
- ListBase tex_pool; /* ViewportTempTexture list : Temporary textures shared across draw engines */
+ ListBase
+ tex_pool; /* ViewportTempTexture list : Temporary textures shared across draw engines. */
- /* Profiling data */
+ /* Profiling data. */
double cache_time;
/* Color management. */
@@ -96,12 +101,11 @@ struct GPUViewport {
enum {
DO_UPDATE = (1 << 0),
+ GPU_VIEWPORT_STEREO = (1 << 1),
};
-static void gpu_viewport_buffers_free(FramebufferList *fbl,
- int fbl_len,
- TextureList *txl,
- int txl_len);
+static void gpu_viewport_buffers_free(
+ FramebufferList *fbl, int fbl_len, TextureList *txl, TextureList *txl_stereo, int txl_len);
static void gpu_viewport_storage_free(StorageList *stl, int stl_len);
static void gpu_viewport_passes_free(PassList *psl, int psl_len);
static void gpu_viewport_texture_pool_free(GPUViewport *viewport);
@@ -125,12 +129,89 @@ GPUViewport *GPU_viewport_create(void)
viewport->txl = MEM_callocN(sizeof(DefaultTextureList), "TextureList");
viewport->idatalist = DRW_instance_data_list_create();
viewport->do_color_management = false;
-
viewport->size[0] = viewport->size[1] = -1;
+ viewport->active_view = -1;
+ return viewport;
+}
+GPUViewport *GPU_viewport_stereo_create(void)
+{
+ GPUViewport *viewport = GPU_viewport_create();
+ viewport->flag = GPU_VIEWPORT_STEREO;
return viewport;
}
+static void gpu_viewport_framebuffer_view_set(GPUViewport *viewport, int view)
+{
+ /* Early check if the view is the latest requested. */
+ if (viewport->active_view == view) {
+ return;
+ }
+ DefaultFramebufferList *dfbl = viewport->fbl;
+ DefaultTextureList *dtxl = viewport->txl;
+
+ /* Only swap the texture when this is a Stereo Viewport. */
+ if (((viewport->flag & GPU_VIEWPORT_STEREO) != 0)) {
+ SWAP(GPUTexture *, dtxl->color, dtxl->color_stereo);
+ SWAP(GPUTexture *, dtxl->color_overlay, dtxl->color_overlay_stereo);
+
+ for (int i = 0; i < MAX_ENABLE_ENGINE; i++) {
+ if (viewport->engine_data[i].handle != NULL) {
+ ViewportEngineData *data = viewport->engine_data[i].data;
+ SWAP(StorageList *, data->stl, data->stl_stereo);
+ SWAP(TextureList *, data->txl, data->txl_stereo);
+ }
+ else {
+ break;
+ }
+ }
+ }
+
+ GPU_framebuffer_ensure_config(&dfbl->default_fb,
+ {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_TEXTURE(dtxl->color),
+ });
+
+ GPU_framebuffer_ensure_config(&dfbl->overlay_fb,
+ {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_TEXTURE(dtxl->color_overlay),
+ });
+
+ GPU_framebuffer_ensure_config(&dfbl->depth_only_fb,
+ {
+ GPU_ATTACHMENT_TEXTURE(dtxl->depth),
+ GPU_ATTACHMENT_NONE,
+ });
+
+ GPU_framebuffer_ensure_config(&dfbl->color_only_fb,
+ {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(dtxl->color),
+ });
+
+ GPU_framebuffer_ensure_config(&dfbl->overlay_only_fb,
+ {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(dtxl->color_overlay),
+ });
+
+ if (((viewport->flag & GPU_VIEWPORT_STEREO) != 0)) {
+ GPU_framebuffer_ensure_config(&dfbl->stereo_comp_fb,
+ {
+ GPU_ATTACHMENT_NONE,
+ GPU_ATTACHMENT_TEXTURE(dtxl->color),
+ GPU_ATTACHMENT_TEXTURE(dtxl->color_overlay),
+ });
+ }
+ else {
+ dfbl->stereo_comp_fb = NULL;
+ }
+
+ viewport->active_view = view;
+}
+
void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type)
{
ViewportEngineData *data = MEM_callocN(sizeof(ViewportEngineData), "ViewportEngineData");
@@ -145,6 +226,13 @@ void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type)
data->psl = MEM_callocN((sizeof(void *) * psl_len) + sizeof(PassList), "PassList");
data->stl = MEM_callocN((sizeof(void *) * stl_len) + sizeof(StorageList), "StorageList");
+ if ((viewport->flag & GPU_VIEWPORT_STEREO) != 0) {
+ data->txl_stereo = MEM_callocN((sizeof(void *) * txl_len) + sizeof(TextureList),
+ "TextureList");
+ data->stl_stereo = MEM_callocN((sizeof(void *) * stl_len) + sizeof(StorageList),
+ "StorageList");
+ }
+
for (int i = 0; i < MAX_ENABLE_ENGINE; i++) {
if (viewport->engine_data[i].handle == NULL) {
viewport->engine_data[i].handle = engine_type;
@@ -166,7 +254,7 @@ static void gpu_viewport_engines_data_free(GPUViewport *viewport)
DRW_engine_viewport_data_size_get(data->engine_type, &fbl_len, &txl_len, &psl_len, &stl_len);
- gpu_viewport_buffers_free(data->fbl, fbl_len, data->txl, txl_len);
+ gpu_viewport_buffers_free(data->fbl, fbl_len, data->txl, data->txl_stereo, txl_len);
gpu_viewport_passes_free(data->psl, psl_len);
gpu_viewport_storage_free(data->stl, stl_len);
@@ -175,6 +263,11 @@ static void gpu_viewport_engines_data_free(GPUViewport *viewport)
MEM_freeN(data->psl);
MEM_freeN(data->stl);
+ if ((viewport->flag & GPU_VIEWPORT_STEREO) != 0) {
+ gpu_viewport_storage_free(data->stl_stereo, stl_len);
+ MEM_freeN(data->txl_stereo);
+ MEM_freeN(data->stl_stereo);
+ }
/* We could handle this in the DRW module */
if (data->text_draw_cache) {
extern void DRW_text_cache_destroy(struct DRWTextStore * dt);
@@ -213,6 +306,16 @@ struct DRWInstanceDataList *GPU_viewport_instance_data_list_get(GPUViewport *vie
return viewport->idatalist;
}
+/* Note this function is only allowed to be called from `DRW_notify_view_update`. The rest
+ * should bind the correct viewport.
+ *
+ * The reason is that DRW_notify_view_update can be called from a different thread, but needs
+ * access to the engine data. */
+void GPU_viewport_active_view_set(GPUViewport *viewport, int view)
+{
+ gpu_viewport_framebuffer_view_set(viewport, view);
+}
+
void *GPU_viewport_framebuffer_list_get(GPUViewport *viewport)
{
return viewport->fbl;
@@ -347,6 +450,10 @@ static void gpu_viewport_default_fb_create(GPUViewport *viewport)
dtxl->color = GPU_texture_create_2d(size[0], size[1], GPU_RGBA16F, NULL, NULL);
dtxl->color_overlay = GPU_texture_create_2d(size[0], size[1], GPU_SRGB8_A8, NULL, NULL);
+ if (((viewport->flag & GPU_VIEWPORT_STEREO) != 0)) {
+ dtxl->color_stereo = GPU_texture_create_2d(size[0], size[1], GPU_RGBA16F, NULL, NULL);
+ dtxl->color_overlay_stereo = GPU_texture_create_2d(size[0], size[1], GPU_SRGB8_A8, NULL, NULL);
+ }
/* Can be shared with GPUOffscreen. */
if (dtxl->depth == NULL) {
@@ -358,42 +465,16 @@ static void gpu_viewport_default_fb_create(GPUViewport *viewport)
goto cleanup;
}
- GPU_framebuffer_ensure_config(&dfbl->default_fb,
- {
- GPU_ATTACHMENT_TEXTURE(dtxl->depth),
- GPU_ATTACHMENT_TEXTURE(dtxl->color),
- });
-
- GPU_framebuffer_ensure_config(&dfbl->overlay_fb,
- {
- GPU_ATTACHMENT_TEXTURE(dtxl->depth),
- GPU_ATTACHMENT_TEXTURE(dtxl->color_overlay),
- });
-
- GPU_framebuffer_ensure_config(&dfbl->depth_only_fb,
- {
- GPU_ATTACHMENT_TEXTURE(dtxl->depth),
- GPU_ATTACHMENT_NONE,
- });
-
- GPU_framebuffer_ensure_config(&dfbl->color_only_fb,
- {
- GPU_ATTACHMENT_NONE,
- GPU_ATTACHMENT_TEXTURE(dtxl->color),
- });
-
- GPU_framebuffer_ensure_config(&dfbl->overlay_only_fb,
- {
- GPU_ATTACHMENT_NONE,
- GPU_ATTACHMENT_TEXTURE(dtxl->color_overlay),
- });
+ gpu_viewport_framebuffer_view_set(viewport, 0);
ok = ok && GPU_framebuffer_check_valid(dfbl->default_fb, NULL);
ok = ok && GPU_framebuffer_check_valid(dfbl->overlay_fb, NULL);
ok = ok && GPU_framebuffer_check_valid(dfbl->color_only_fb, NULL);
ok = ok && GPU_framebuffer_check_valid(dfbl->depth_only_fb, NULL);
ok = ok && GPU_framebuffer_check_valid(dfbl->overlay_only_fb, NULL);
-
+ if (((viewport->flag & GPU_VIEWPORT_STEREO) != 0)) {
+ ok = ok && GPU_framebuffer_check_valid(dfbl->stereo_comp_fb, NULL);
+ }
cleanup:
if (!ok) {
GPU_viewport_free(viewport);
@@ -404,7 +485,7 @@ cleanup:
GPU_framebuffer_restore();
}
-void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect)
+void GPU_viewport_bind(GPUViewport *viewport, int view, const rcti *rect)
{
DefaultFramebufferList *dfbl = viewport->fbl;
int fbl_len, txl_len;
@@ -421,15 +502,17 @@ void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect)
gpu_viewport_buffers_free((FramebufferList *)viewport->fbl,
default_fbl_len,
(TextureList *)viewport->txl,
+ NULL,
default_txl_len);
for (int i = 0; i < MAX_ENABLE_ENGINE && viewport->engine_data[i].handle; i++) {
ViewportEngineData *data = viewport->engine_data[i].data;
DRW_engine_viewport_data_size_get(data->engine_type, &fbl_len, &txl_len, NULL, NULL);
- gpu_viewport_buffers_free(data->fbl, fbl_len, data->txl, txl_len);
+ gpu_viewport_buffers_free(data->fbl, fbl_len, data->txl, data->txl_stereo, txl_len);
}
gpu_viewport_texture_pool_free(viewport);
+ viewport->active_view = -1;
}
}
@@ -440,6 +523,7 @@ void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect)
if (!dfbl->default_fb) {
gpu_viewport_default_fb_create(viewport);
}
+ gpu_viewport_framebuffer_view_set(viewport, view);
}
void GPU_viewport_bind_from_offscreen(GPUViewport *viewport, struct GPUOffScreen *ofs)
@@ -474,6 +558,74 @@ void GPU_viewport_colorspace_set(GPUViewport *viewport,
viewport->do_color_management = true;
}
+/* Merge the stereo textures. `color` and `overlay` texture will be modified. */
+void GPU_viewport_stereo_composite(GPUViewport *viewport, Stereo3dFormat *stereo_format)
+{
+ if (!ELEM(stereo_format->display_mode, S3D_DISPLAY_ANAGLYPH, S3D_DISPLAY_INTERLACE)) {
+ /* Early Exit: the other display modes need access to the full screen and cannot be
+ * done from a single viewport. See `wm_stereo.c` */
+ return;
+ }
+ gpu_viewport_framebuffer_view_set(viewport, 0);
+ DefaultTextureList *dtxl = viewport->txl;
+ DefaultFramebufferList *dfbl = viewport->fbl;
+
+ GPUVertFormat *vert_format = immVertexFormat();
+ uint pos = GPU_vertformat_attr_add(vert_format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+ GPU_framebuffer_bind(dfbl->stereo_comp_fb);
+ GPU_matrix_push();
+ GPU_matrix_push_projection();
+ GPU_matrix_identity_set();
+ GPU_matrix_identity_projection_set();
+ immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_OVERLAYS_STEREO_MERGE);
+ immUniform1i("imageTexture", 0);
+ immUniform1i("overlayTexture", 1);
+ int settings = stereo_format->display_mode;
+ if (settings == S3D_DISPLAY_ANAGLYPH) {
+ switch (stereo_format->anaglyph_type) {
+ case S3D_ANAGLYPH_REDCYAN:
+ glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE);
+ break;
+ case S3D_ANAGLYPH_GREENMAGENTA:
+ glColorMask(GL_TRUE, GL_FALSE, GL_TRUE, GL_TRUE);
+ break;
+ case S3D_ANAGLYPH_YELLOWBLUE:
+ glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE);
+ break;
+ }
+ }
+ else if (settings == S3D_DISPLAY_INTERLACE) {
+ settings |= stereo_format->interlace_type << 3;
+ SET_FLAG_FROM_TEST(settings, stereo_format->flag & S3D_INTERLACE_SWAP, 1 << 6);
+ }
+ immUniform1i("stereoDisplaySettings", settings);
+
+ GPU_texture_bind(dtxl->color_stereo, 0);
+ GPU_texture_bind(dtxl->color_overlay_stereo, 1);
+
+ immBegin(GPU_PRIM_TRI_STRIP, 4);
+
+ immVertex2f(pos, -1.0f, -1.0f);
+ immVertex2f(pos, 1.0f, -1.0f);
+ immVertex2f(pos, -1.0f, 1.0f);
+ immVertex2f(pos, 1.0f, 1.0f);
+
+ immEnd();
+
+ GPU_texture_unbind(dtxl->color_stereo);
+ GPU_texture_unbind(dtxl->color_overlay_stereo);
+
+ immUnbindProgram();
+ GPU_matrix_pop_projection();
+ GPU_matrix_pop();
+
+ if (settings == S3D_DISPLAY_ANAGLYPH) {
+ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ }
+
+ GPU_framebuffer_restore();
+}
+
static void gpu_viewport_draw_colormanaged(GPUViewport *viewport,
const rctf *rect_pos,
const rctf *rect_uv,
@@ -537,9 +689,11 @@ static void gpu_viewport_draw_colormanaged(GPUViewport *viewport,
* transform should be performed.
*/
void GPU_viewport_draw_to_screen_ex(GPUViewport *viewport,
+ int view,
const rcti *rect,
bool display_colorspace)
{
+ gpu_viewport_framebuffer_view_set(viewport, view);
DefaultFramebufferList *dfbl = viewport->fbl;
DefaultTextureList *dtxl = viewport->txl;
GPUTexture *color = dtxl->color;
@@ -594,9 +748,9 @@ void GPU_viewport_draw_to_screen_ex(GPUViewport *viewport,
* \param rect: Coordinates to draw into. By swapping min and max values, drawing can be done with
* inversed axis coordinates (upside down or sideways).
*/
-void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect)
+void GPU_viewport_draw_to_screen(GPUViewport *viewport, int view, const rcti *rect)
{
- GPU_viewport_draw_to_screen_ex(viewport, rect, true);
+ GPU_viewport_draw_to_screen_ex(viewport, view, rect, true);
}
/**
@@ -642,22 +796,25 @@ void GPU_viewport_unbind(GPUViewport *UNUSED(viewport))
DRW_opengl_context_disable();
}
-GPUTexture *GPU_viewport_color_texture(GPUViewport *viewport)
+GPUTexture *GPU_viewport_color_texture(GPUViewport *viewport, int view)
{
DefaultFramebufferList *dfbl = viewport->fbl;
if (dfbl->default_fb) {
DefaultTextureList *dtxl = viewport->txl;
- return dtxl->color;
+ if (viewport->active_view == view) {
+ return dtxl->color;
+ }
+ else {
+ return dtxl->color_stereo;
+ }
}
return NULL;
}
-static void gpu_viewport_buffers_free(FramebufferList *fbl,
- int fbl_len,
- TextureList *txl,
- int txl_len)
+static void gpu_viewport_buffers_free(
+ FramebufferList *fbl, int fbl_len, TextureList *txl, TextureList *txl_stereo, int txl_len)
{
for (int i = 0; i < fbl_len; i++) {
GPUFrameBuffer *fb = fbl->framebuffers[i];
@@ -673,6 +830,15 @@ static void gpu_viewport_buffers_free(FramebufferList *fbl,
txl->textures[i] = NULL;
}
}
+ if (txl_stereo != NULL) {
+ for (int i = 0; i < txl_len; i++) {
+ GPUTexture *tex = txl_stereo->textures[i];
+ if (tex) {
+ GPU_texture_free(tex);
+ txl_stereo->textures[i] = NULL;
+ }
+ }
+ }
}
static void gpu_viewport_storage_free(StorageList *stl, int stl_len)
@@ -699,6 +865,7 @@ void GPU_viewport_free(GPUViewport *viewport)
gpu_viewport_buffers_free((FramebufferList *)viewport->fbl,
default_fbl_len,
(TextureList *)viewport->txl,
+ NULL,
default_txl_len);
gpu_viewport_texture_pool_free(viewport);
diff --git a/source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl
deleted file mode 100644
index 9b9d8149e09..00000000000
--- a/source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl
+++ /dev/null
@@ -1,35 +0,0 @@
-
-/* Keep these in sync with GPU_shader.h */
-#define INTERLACE_ROW 0
-#define INTERLACE_COLUMN 1
-#define INTERLACE_CHECKERBOARD 2
-
-in vec2 texCoord_interp;
-out vec4 fragColor;
-
-uniform int interlace_id;
-uniform sampler2D image_a;
-uniform sampler2D image_b;
-
-bool interlace()
-{
- if (interlace_id == INTERLACE_CHECKERBOARD) {
- return (int(gl_FragCoord.x + gl_FragCoord.y) & 1) != 0;
- }
- else if (interlace_id == INTERLACE_ROW) {
- return (int(gl_FragCoord.y) & 1) != 0;
- }
- else if (interlace_id == INTERLACE_COLUMN) {
- return (int(gl_FragCoord.x) & 1) != 0;
- }
-}
-
-void main()
-{
- if (interlace()) {
- fragColor = texture(image_a, texCoord_interp);
- }
- else {
- fragColor = texture(image_b, texCoord_interp);
- }
-}
diff --git a/source/blender/gpu/shaders/gpu_shader_image_overlays_stereo_merge_frag.glsl b/source/blender/gpu/shaders/gpu_shader_image_overlays_stereo_merge_frag.glsl
new file mode 100644
index 00000000000..c6e9860d940
--- /dev/null
+++ b/source/blender/gpu/shaders/gpu_shader_image_overlays_stereo_merge_frag.glsl
@@ -0,0 +1,47 @@
+#define S3D_DISPLAY_ANAGLYPH 0
+#define S3D_DISPLAY_INTERLACE 1
+
+#define S3D_INTERLACE_ROW 0
+#define S3D_INTERLACE_COLUMN 1
+#define S3D_INTERLACE_CHECKERBOARD 2
+
+/* Composite stereo textures */
+
+uniform sampler2D imageTexture;
+uniform sampler2D overlayTexture;
+
+uniform int stereoDisplaySettings;
+
+#define stereo_display_mode (stereoDisplaySettings & ((1 << 3) - 1))
+#define stereo_interlace_mode ((stereoDisplaySettings >> 3) & ((1 << 3) - 1))
+#define stereo_interlace_swap bool(stereoDisplaySettings >> 6)
+
+layout(location = 0) out vec4 imageColor;
+layout(location = 1) out vec4 overlayColor;
+
+bool interlace(ivec2 texel)
+{
+ int interlace_mode = stereo_interlace_mode;
+ if (interlace_mode == S3D_INTERLACE_CHECKERBOARD) {
+ return ((texel.x + texel.y) & 1) != 0;
+ }
+ else if (interlace_mode == S3D_INTERLACE_ROW) {
+ return (texel.y & 1) != 0;
+ }
+ else if (interlace_mode == S3D_INTERLACE_COLUMN) {
+ return (texel.x & 1) != 0;
+ }
+}
+
+void main()
+{
+ ivec2 texel = ivec2(gl_FragCoord.xy);
+
+ if (stereo_display_mode == S3D_DISPLAY_INTERLACE &&
+ (interlace(texel) == stereo_interlace_swap)) {
+ discard;
+ }
+
+ imageColor = texelFetch(imageTexture, texel, 0);
+ overlayColor = texelFetch(overlayTexture, texel, 0);
+}
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 1be7a8679c4..7426d64c769 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -778,7 +778,7 @@ void WM_draw_region_viewport_unbind(struct ARegion *region);
/* Region drawing */
void WM_draw_region_free(struct ARegion *region);
-struct GPUViewport *WM_draw_region_get_viewport(struct ARegion *region, int view);
+struct GPUViewport *WM_draw_region_get_viewport(struct ARegion *region);
struct GPUViewport *WM_draw_region_get_bound_viewport(struct ARegion *region);
void WM_main_playanim(int argc, const char **argv);
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 5289b747f05..38cd667c422 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -235,7 +235,7 @@ static void wm_region_test_render_do_draw(const Scene *scene,
if (sa->spacetype == SPACE_VIEW3D && region->regiontype == RGN_TYPE_WINDOW) {
RegionView3D *rv3d = region->regiondata;
RenderEngine *engine = rv3d->render_engine;
- GPUViewport *viewport = WM_draw_region_get_viewport(region, 0);
+ GPUViewport *viewport = WM_draw_region_get_viewport(region);
if (engine && (engine->flag & RE_ENGINE_DO_DRAW)) {
View3D *v3d = sa->spacedata.first;
@@ -332,10 +332,8 @@ static void wm_draw_callbacks(wmWindow *win)
static void wm_draw_region_buffer_free(ARegion *region)
{
if (region->draw_buffer) {
- for (int view = 0; view < 2; view++) {
- if (region->draw_buffer->viewport[view]) {
- GPU_viewport_free(region->draw_buffer->viewport[view]);
- }
+ if (region->draw_buffer->viewport) {
+ GPU_viewport_free(region->draw_buffer->viewport);
}
if (region->draw_buffer->offscreen) {
GPU_offscreen_free(region->draw_buffer->offscreen);
@@ -361,7 +359,6 @@ static void wm_draw_offscreen_texture_parameters(GPUOffScreen *offscreen)
/* GL_TEXTURE_BASE_LEVEL = 0 by default */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
glBindTexture(GL_TEXTURE_2D, 0);
}
@@ -387,8 +384,8 @@ static void wm_draw_region_buffer_create(ARegion *region, bool stereo, bool use_
/* Allocate viewport which includes an offscreen buffer with depth
* multisample, etc. */
region->draw_buffer = MEM_callocN(sizeof(wmDrawBuffer), "wmDrawBuffer");
- region->draw_buffer->viewport[0] = GPU_viewport_create();
- region->draw_buffer->viewport[1] = (stereo) ? GPU_viewport_create() : NULL;
+ region->draw_buffer->viewport = stereo ? GPU_viewport_stereo_create() :
+ GPU_viewport_create();
}
else {
/* Allocate offscreen buffer if it does not exist. This one has no
@@ -417,8 +414,8 @@ static void wm_draw_region_bind(ARegion *region, int view)
return;
}
- if (region->draw_buffer->viewport[view]) {
- GPU_viewport_bind(region->draw_buffer->viewport[view], &region->winrct);
+ if (region->draw_buffer->viewport) {
+ GPU_viewport_bind(region->draw_buffer->viewport, view, &region->winrct);
}
else {
GPU_offscreen_bind(region->draw_buffer->offscreen, false);
@@ -432,7 +429,7 @@ static void wm_draw_region_bind(ARegion *region, int view)
region->draw_buffer->bound_view = view;
}
-static void wm_draw_region_unbind(ARegion *region, int view)
+static void wm_draw_region_unbind(ARegion *region)
{
if (!region->draw_buffer) {
return;
@@ -440,8 +437,8 @@ static void wm_draw_region_unbind(ARegion *region, int view)
region->draw_buffer->bound_view = -1;
- if (region->draw_buffer->viewport[view]) {
- GPU_viewport_unbind(region->draw_buffer->viewport[view]);
+ if (region->draw_buffer->viewport) {
+ GPU_viewport_unbind(region->draw_buffer->viewport);
}
else {
glDisable(GL_SCISSOR_TEST);
@@ -460,14 +457,14 @@ static void wm_draw_region_blit(ARegion *region, int view)
view = 0;
}
else if (view > 0) {
- if (region->draw_buffer->viewport[view] == NULL) {
+ if (region->draw_buffer->viewport == NULL) {
/* Region does not need stereo or failed to allocate stereo buffers. */
view = 0;
}
}
- if (region->draw_buffer->viewport[view]) {
- GPU_viewport_draw_to_screen(region->draw_buffer->viewport[view], &region->winrct);
+ if (region->draw_buffer->viewport) {
+ GPU_viewport_draw_to_screen(region->draw_buffer->viewport, view, &region->winrct);
}
else {
GPU_offscreen_draw_to_screen(
@@ -481,8 +478,9 @@ GPUTexture *wm_draw_region_texture(ARegion *region, int view)
return NULL;
}
- if (region->draw_buffer->viewport[view]) {
- return GPU_viewport_color_texture(region->draw_buffer->viewport[view]);
+ GPUViewport *viewport = region->draw_buffer->viewport;
+ if (viewport) {
+ return GPU_viewport_color_texture(viewport, view);
}
else {
return GPU_offscreen_color_texture(region->draw_buffer->offscreen);
@@ -573,13 +571,14 @@ void wm_draw_region_blend(ARegion *region, int view, bool blend)
}
}
-GPUViewport *WM_draw_region_get_viewport(ARegion *region, int view)
+GPUViewport *WM_draw_region_get_viewport(ARegion *region)
{
if (!region->draw_buffer) {
return NULL;
}
- return region->draw_buffer->viewport[view];
+ GPUViewport *viewport = region->draw_buffer->viewport;
+ return viewport;
}
GPUViewport *WM_draw_region_get_bound_viewport(ARegion *region)
@@ -588,8 +587,8 @@ GPUViewport *WM_draw_region_get_bound_viewport(ARegion *region)
return NULL;
}
- int view = region->draw_buffer->bound_view;
- return region->draw_buffer->viewport[view];
+ GPUViewport *viewport = region->draw_buffer->viewport;
+ return viewport;
}
static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo)
@@ -650,14 +649,18 @@ static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo)
wm_draw_region_bind(region, view);
ED_region_do_draw(C, region);
- wm_draw_region_unbind(region, view);
+ wm_draw_region_unbind(region);
+ }
+ if (use_viewport) {
+ GPUViewport *viewport = region->draw_buffer->viewport;
+ GPU_viewport_stereo_composite(viewport, win->stereo3d_format);
}
}
else {
wm_draw_region_buffer_create(region, false, use_viewport);
wm_draw_region_bind(region, 0);
ED_region_do_draw(C, region);
- wm_draw_region_unbind(region, 0);
+ wm_draw_region_unbind(region);
}
region->do_draw = false;
@@ -686,7 +689,7 @@ static void wm_draw_window_offscreen(bContext *C, wmWindow *win, bool stereo)
glClearColor(0, 0, 0, 0);
glClear(GL_COLOR_BUFFER_BIT);
ED_region_do_draw(C, region);
- wm_draw_region_unbind(region, 0);
+ wm_draw_region_unbind(region);
region->do_draw = false;
CTX_wm_menu_set(C, NULL);
@@ -715,19 +718,8 @@ static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view)
{
for (ARegion *region = sa->regionbase.first; region; region = region->next) {
if (region->visible && region->overlap == false) {
- if (view == -1 && region->draw_buffer && region->draw_buffer->stereo) {
- /* Stereo drawing from textures. */
- if (win->stereo3d_format->display_mode == S3D_DISPLAY_ANAGLYPH) {
- wm_stereo3d_draw_anaglyph(win, region);
- }
- else {
- wm_stereo3d_draw_interlace(win, region);
- }
- }
- else {
- /* Blit from offscreen buffer. */
- wm_draw_region_blit(region, view);
- }
+ /* Blit from offscreen buffer. */
+ wm_draw_region_blit(region, view);
}
}
}
@@ -789,7 +781,6 @@ static void wm_draw_window(bContext *C, wmWindow *win)
{
bScreen *screen = WM_window_get_active_screen(win);
bool stereo = WM_stereo3d_enabled(win, false);
-
/* Draw area regions into their own framebuffer. This way we can redraw
* the areas that need it, and blit the rest from existing framebuffers. */
wm_draw_window_offscreen(C, win, stereo);
@@ -1028,7 +1019,7 @@ void wm_draw_region_test(bContext *C, ScrArea *sa, ARegion *region)
wm_draw_region_buffer_create(region, false, use_viewport);
wm_draw_region_bind(region, 0);
ED_region_do_draw(C, region);
- wm_draw_region_unbind(region, 0);
+ wm_draw_region_unbind(region);
region->do_draw = false;
}
@@ -1068,7 +1059,7 @@ void WM_draw_region_viewport_bind(ARegion *region)
void WM_draw_region_viewport_unbind(ARegion *region)
{
- wm_draw_region_unbind(region, 0);
+ wm_draw_region_unbind(region);
}
/** \} */
diff --git a/source/blender/windowmanager/intern/wm_stereo.c b/source/blender/windowmanager/intern/wm_stereo.c
index c5f8fb71b60..8ae343d5eb5 100644
--- a/source/blender/windowmanager/intern/wm_stereo.c
+++ b/source/blender/windowmanager/intern/wm_stereo.c
@@ -53,100 +53,6 @@
#include "UI_interface.h"
#include "UI_resources.h"
-static eGPUInterlaceShader interlace_gpu_id_from_type(eStereo3dInterlaceType interlace_type)
-{
- switch (interlace_type) {
- case S3D_INTERLACE_ROW:
- return GPU_SHADER_INTERLACE_ROW;
- case S3D_INTERLACE_COLUMN:
- return GPU_SHADER_INTERLACE_COLUMN;
- case S3D_INTERLACE_CHECKERBOARD:
- default:
- return GPU_SHADER_INTERLACE_CHECKER;
- }
-}
-
-void wm_stereo3d_draw_interlace(wmWindow *win, ARegion *region)
-{
- bool swap = (win->stereo3d_format->flag & S3D_INTERLACE_SWAP) != 0;
- enum eStereo3dInterlaceType interlace_type = win->stereo3d_format->interlace_type;
-
- /* wmOrtho for the screen has this same offset */
- float halfx = GLA_PIXEL_OFS / region->winx;
- float halfy = GLA_PIXEL_OFS / region->winy;
-
- GPUVertFormat *format = immVertexFormat();
- uint texcoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
- uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
- /* leave GL_TEXTURE0 as the latest active texture */
- for (int view = 1; view >= 0; view--) {
- GPUTexture *texture = wm_draw_region_texture(region, view);
- glActiveTexture(GL_TEXTURE0 + view);
- glBindTexture(GL_TEXTURE_2D, GPU_texture_opengl_bindcode(texture));
- }
-
- immBindBuiltinProgram(GPU_SHADER_2D_IMAGE_INTERLACE);
- immUniform1i("image_a", (swap) ? 1 : 0);
- immUniform1i("image_b", (swap) ? 0 : 1);
-
- immUniform1i("interlace_id", interlace_gpu_id_from_type(interlace_type));
-
- immBegin(GPU_PRIM_TRI_FAN, 4);
-
- immAttr2f(texcoord, halfx, halfy);
- immVertex2f(pos, region->winrct.xmin, region->winrct.ymin);
-
- immAttr2f(texcoord, 1.0f + halfx, halfy);
- immVertex2f(pos, region->winrct.xmax + 1, region->winrct.ymin);
-
- immAttr2f(texcoord, 1.0f + halfx, 1.0f + halfy);
- immVertex2f(pos, region->winrct.xmax + 1, region->winrct.ymax + 1);
-
- immAttr2f(texcoord, halfx, 1.0f + halfy);
- immVertex2f(pos, region->winrct.xmin, region->winrct.ymax + 1);
-
- immEnd();
- immUnbindProgram();
-
- for (int view = 1; view >= 0; view--) {
- glActiveTexture(GL_TEXTURE0 + view);
- glBindTexture(GL_TEXTURE_2D, 0);
- }
-}
-
-void wm_stereo3d_draw_anaglyph(wmWindow *win, ARegion *region)
-{
- for (int view = 0; view < 2; view++) {
- int bit = view + 1;
-
- switch (win->stereo3d_format->anaglyph_type) {
- case S3D_ANAGLYPH_REDCYAN:
- glColorMask((1 & bit) ? GL_TRUE : GL_FALSE,
- (2 & bit) ? GL_TRUE : GL_FALSE,
- (2 & bit) ? GL_TRUE : GL_FALSE,
- GL_FALSE);
- break;
- case S3D_ANAGLYPH_GREENMAGENTA:
- glColorMask((2 & bit) ? GL_TRUE : GL_FALSE,
- (1 & bit) ? GL_TRUE : GL_FALSE,
- (2 & bit) ? GL_TRUE : GL_FALSE,
- GL_FALSE);
- break;
- case S3D_ANAGLYPH_YELLOWBLUE:
- glColorMask((1 & bit) ? GL_TRUE : GL_FALSE,
- (1 & bit) ? GL_TRUE : GL_FALSE,
- (2 & bit) ? GL_TRUE : GL_FALSE,
- GL_FALSE);
- break;
- }
-
- wm_draw_region_blend(region, view, false);
- }
-
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-}
-
void wm_stereo3d_draw_sidebyside(wmWindow *win, int view)
{
bool cross_eyed = (win->stereo3d_format->flag & S3D_SIDEBYSIDE_CROSSEYED) != 0;
diff --git a/source/blender/windowmanager/intern/wm_xr.c b/source/blender/windowmanager/intern/wm_xr.c
index 4c770834f14..ef6fa6d28f2 100644
--- a/source/blender/windowmanager/intern/wm_xr.c
+++ b/source/blender/windowmanager/intern/wm_xr.c
@@ -685,7 +685,7 @@ static void wm_xr_draw_viewport_buffers_to_active_framebuffer(
if (is_upside_down) {
SWAP(int, rect.ymin, rect.ymax);
}
- GPU_viewport_draw_to_screen_ex(surface_data->viewport, &rect, draw_view->expects_srgb_buffer);
+ GPU_viewport_draw_to_screen_ex(surface_data->viewport, 0, &rect, draw_view->expects_srgb_buffer);
}
/**
diff --git a/source/blender/windowmanager/wm.h b/source/blender/windowmanager/wm.h
index 22c01df5d3b..97403a0315a 100644
--- a/source/blender/windowmanager/wm.h
+++ b/source/blender/windowmanager/wm.h
@@ -82,8 +82,6 @@ void wm_autosave_location(char *filepath);
void WM_OT_splash(wmOperatorType *ot);
/* wm_stereo.c */
-void wm_stereo3d_draw_interlace(wmWindow *win, struct ARegion *region);
-void wm_stereo3d_draw_anaglyph(wmWindow *win, struct ARegion *region);
void wm_stereo3d_draw_sidebyside(wmWindow *win, int view);
void wm_stereo3d_draw_topbottom(wmWindow *win, int view);
diff --git a/source/blender/windowmanager/wm_draw.h b/source/blender/windowmanager/wm_draw.h
index 4ebf2c820cd..b19fdf97569 100644
--- a/source/blender/windowmanager/wm_draw.h
+++ b/source/blender/windowmanager/wm_draw.h
@@ -32,7 +32,7 @@ struct GPUViewport;
typedef struct wmDrawBuffer {
struct GPUOffScreen *offscreen;
- struct GPUViewport *viewport[2];
+ struct GPUViewport *viewport;
bool stereo;
int bound_view;
} wmDrawBuffer;