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 /source/blender/gpu/intern
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
Diffstat (limited to 'source/blender/gpu/intern')
-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
4 files changed, 226 insertions, 55 deletions
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);