diff options
Diffstat (limited to 'source/blender/gpu')
-rw-r--r-- | source/blender/gpu/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/gpu/GPU_shader.h | 14 | ||||
-rw-r--r-- | source/blender/gpu/GPU_viewport.h | 13 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_framebuffer.c | 1 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_shader.c | 12 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_state.c | 3 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_viewport.c | 265 | ||||
-rw-r--r-- | source/blender/gpu/shaders/gpu_shader_image_interlace_frag.glsl | 35 | ||||
-rw-r--r-- | source/blender/gpu/shaders/gpu_shader_image_overlays_stereo_merge_frag.glsl | 47 |
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); +} |