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:
Diffstat (limited to 'source/blender/gpu')
-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
9 files changed, 285 insertions, 107 deletions
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);
+}