diff options
Diffstat (limited to 'source/blender/gpu')
-rw-r--r-- | source/blender/gpu/GPU_texture.h | 8 | ||||
-rw-r--r-- | source/blender/gpu/GPU_viewport.h | 95 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_viewport.c | 626 |
3 files changed, 107 insertions, 622 deletions
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h index 9a1885160b6..deff9e47871 100644 --- a/source/blender/gpu/GPU_texture.h +++ b/source/blender/gpu/GPU_texture.h @@ -52,6 +52,14 @@ typedef enum eGPUSamplerState { GPU_SAMPLER_REPEAT = (GPU_SAMPLER_REPEAT_S | GPU_SAMPLER_REPEAT_T | GPU_SAMPLER_REPEAT_R), } eGPUSamplerState; +#define GPU_TEXTURE_FREE_SAFE(texture) \ + do { \ + if (texture != NULL) { \ + GPU_texture_free(texture); \ + texture = NULL; \ + } \ + } while (0) + /* `GPU_SAMPLER_MAX` is not a valid enum value, but only a limit. * It also creates a bad mask for the `NOT` operator in `ENUM_OPERATORS`. */ diff --git a/source/blender/gpu/GPU_viewport.h b/source/blender/gpu/GPU_viewport.h index 0ecd5f3eb7b..4d9970dac90 100644 --- a/source/blender/gpu/GPU_viewport.h +++ b/source/blender/gpu/GPU_viewport.h @@ -35,76 +35,15 @@ extern "C" { #endif -#define GPU_INFO_SIZE 512 /* IMA_MAX_RENDER_TEXT */ #define GLA_PIXEL_OFS 0.375f typedef struct GHash GHash; typedef struct GPUViewport GPUViewport; struct GPUFrameBuffer; - -/* Contains memory pools information. */ -typedef struct ViewportMemoryPool { - struct BLI_memblock *commands; - struct BLI_memblock *commands_small; - struct BLI_memblock *callbuffers; - struct BLI_memblock *obmats; - struct BLI_memblock *obinfos; - struct BLI_memblock *cullstates; - struct BLI_memblock *shgroups; - struct BLI_memblock *uniforms; - struct BLI_memblock *views; - struct BLI_memblock *passes; - struct BLI_memblock *images; - struct GPUUniformBuf **matrices_ubo; - struct GPUUniformBuf **obinfos_ubo; - struct GHash *obattrs_ubo_pool; - uint ubo_len; -} ViewportMemoryPool; - -/* All FramebufferLists are just the same pointers with different names. */ -typedef struct FramebufferList { - struct GPUFrameBuffer *framebuffers[1]; -} FramebufferList; - -typedef struct TextureList { - struct GPUTexture *textures[1]; -} TextureList; - -typedef struct PassList { - struct DRWPass *passes[1]; -} PassList; - -typedef struct StorageList { - void *storage[1]; /* Custom structs from the engine. */ -} StorageList; - -typedef struct ViewportEngineData { - void *engine_type; - - FramebufferList *fbl; - TextureList *txl; - PassList *psl; - 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; - - /* Profiling data. */ - double init_time; - double render_time; - double background_time; -} ViewportEngineData; - -typedef struct ViewportEngineData_Info { - int fbl_len; - int txl_len; - int psl_len; - int stl_len; -} ViewportEngineData_Info; +struct DefaultFramebufferList; +struct DefaultTextureList; +struct DRWData; GPUViewport *GPU_viewport_create(void); GPUViewport *GPU_viewport_stereo_create(void); @@ -129,35 +68,21 @@ void GPU_viewport_unbind_from_offscreen(GPUViewport *viewport, bool display_colorspace, bool do_overlay_merge); -ViewportMemoryPool *GPU_viewport_mempool_get(GPUViewport *viewport); -struct DRWInstanceDataList *GPU_viewport_instance_data_list_get(GPUViewport *viewport); +struct DRWData **GPU_viewport_data_get(GPUViewport *viewport); -void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type); -void *GPU_viewport_engine_data_get(GPUViewport *viewport, void *engine_handle); -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); void GPU_viewport_tag_update(GPUViewport *viewport); bool GPU_viewport_do_update(GPUViewport *viewport); -GPUTexture *GPU_viewport_color_texture(GPUViewport *viewport, int view); +int GPU_viewport_active_view_get(GPUViewport *viewport); +bool GPU_viewport_is_stereo_get(GPUViewport *viewport); -/* Texture pool. */ -GPUTexture *GPU_viewport_texture_pool_query( - GPUViewport *viewport, void *engine, int width, int height, int format); - -bool GPU_viewport_engines_data_validate(GPUViewport *viewport, void **engine_handle_array); -void GPU_viewport_cache_release(GPUViewport *viewport); +GPUTexture *GPU_viewport_color_texture(GPUViewport *viewport, int view); +GPUTexture *GPU_viewport_overlay_texture(GPUViewport *viewport, int view); +GPUTexture *GPU_viewport_depth_texture(GPUViewport *viewport); -struct GPUFrameBuffer *GPU_viewport_framebuffer_default_get(GPUViewport *viewport); -struct GPUFrameBuffer *GPU_viewport_framebuffer_overlay_get(GPUViewport *viewport); +GPUFrameBuffer *GPU_viewport_framebuffer_overlay_get(GPUViewport *viewport); #ifdef __cplusplus } diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c index dd63edea0db..ccd9a4c061b 100644 --- a/source/blender/gpu/intern/gpu_viewport.c +++ b/source/blender/gpu/intern/gpu_viewport.c @@ -48,22 +48,6 @@ #include "MEM_guardedalloc.h" -static const int default_fbl_len = (sizeof(DefaultFramebufferList)) / sizeof(void *); -static const int default_txl_len = (sizeof(DefaultTextureList)) / sizeof(void *); - -#define MAX_ENABLE_ENGINE 8 - -/* Maximum number of simultaneous engine enabled at the same time. - * Setting it lower than the real number will do lead to - * higher VRAM usage due to sub-efficient buffer reuse. */ -#define MAX_ENGINE_BUFFER_SHARING 5 - -typedef struct ViewportTempTexture { - struct ViewportTempTexture *next, *prev; - void *user[MAX_ENGINE_BUFFER_SHARING]; - GPUTexture *texture; -} ViewportTempTexture; - /* Struct storing a viewport specific GPUBatch. * The end-goal is to have a single batch shared across viewport and use a model matrix to place * the batch. Due to OCIO and Image/UV editor we are not able to use an model matrix yet. */ @@ -89,23 +73,17 @@ struct GPUViewport { /* Set the active view (for stereoscopic viewport rendering). */ int active_view; - /* If engine_handles mismatch we free all #ViewportEngineData in this viewport. */ - struct { - void *handle; - ViewportEngineData *data; - } engine_data[MAX_ENABLE_ENGINE]; - - DefaultFramebufferList *fbl; - DefaultTextureList *txl; - - 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. */ - - /* Profiling data. */ - double cache_time; + /* Viewport Resources. */ + struct DRWData *draw_data; + /** Color buffers, one for each stereo view. Only one if not stereo viewport. */ + GPUTexture *color_render_tx[2]; + GPUTexture *color_overlay_tx[2]; + /** Depth buffer. Can be shared with GPUOffscreen. */ + GPUTexture *depth_tx; + /** Compositing framebuffer for stereo viewport. */ + GPUFrameBuffer *stereo_comp_fb; + /** Overlay framebuffer for drawing outside of DRW module. */ + GPUFrameBuffer *overlay_fb; /* Color management. */ ColorManagedViewSettings view_settings; @@ -123,12 +101,6 @@ enum { GPU_VIEWPORT_STEREO = (1 << 1), }; -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); - void GPU_viewport_tag_update(GPUViewport *viewport) { viewport->flag |= DO_UPDATE; @@ -144,12 +116,9 @@ bool GPU_viewport_do_update(GPUViewport *viewport) GPUViewport *GPU_viewport_create(void) { GPUViewport *viewport = MEM_callocN(sizeof(GPUViewport), "GPUViewport"); - viewport->fbl = MEM_callocN(sizeof(DefaultFramebufferList), "FramebufferList"); - 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; + viewport->active_view = 0; return viewport; } @@ -160,343 +129,55 @@ GPUViewport *GPU_viewport_stereo_create(void) 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), - }); - - viewport->active_view = view; -} - -void *GPU_viewport_engine_data_create(GPUViewport *viewport, void *engine_type) -{ - ViewportEngineData *data = MEM_callocN(sizeof(ViewportEngineData), "ViewportEngineData"); - int fbl_len, txl_len, psl_len, stl_len; - - DRW_engine_viewport_data_size_get(engine_type, &fbl_len, &txl_len, &psl_len, &stl_len); - - data->engine_type = engine_type; - - data->fbl = MEM_callocN((sizeof(void *) * fbl_len) + sizeof(FramebufferList), "FramebufferList"); - data->txl = MEM_callocN((sizeof(void *) * txl_len) + sizeof(TextureList), "TextureList"); - 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; - viewport->engine_data[i].data = data; - return data; - } - } - - BLI_assert_msg(0, "Too many draw engines enabled at the same time"); - return NULL; -} - -static void gpu_viewport_engines_data_free(GPUViewport *viewport) +struct DRWData **GPU_viewport_data_get(GPUViewport *viewport) { - int fbl_len, txl_len, psl_len, stl_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, &psl_len, &stl_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); - - MEM_freeN(data->fbl); - MEM_freeN(data->txl); - 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); - DRW_text_cache_destroy(data->text_draw_cache); - data->text_draw_cache = NULL; - } - - MEM_freeN(data); - - /* Mark as unused. */ - viewport->engine_data[i].handle = NULL; - } - - gpu_viewport_texture_pool_free(viewport); -} - -void *GPU_viewport_engine_data_get(GPUViewport *viewport, void *engine_handle) -{ - BLI_assert(engine_handle != NULL); - - for (int i = 0; i < MAX_ENABLE_ENGINE; i++) { - if (viewport->engine_data[i].handle == engine_handle) { - return viewport->engine_data[i].data; - } - } - return NULL; -} - -ViewportMemoryPool *GPU_viewport_mempool_get(GPUViewport *viewport) -{ - return &viewport->vmempool; + return &viewport->draw_data; } -struct DRWInstanceDataList *GPU_viewport_instance_data_list_get(GPUViewport *viewport) -{ - 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; -} - -void *GPU_viewport_texture_list_get(GPUViewport *viewport) -{ - return viewport->txl; -} - -void GPU_viewport_size_get(const GPUViewport *viewport, int size[2]) -{ - copy_v2_v2_int(size, viewport->size); -} - -/** - * Special case, this is needed for when we have a viewport without a frame-buffer output - * (occlusion queries for eg) - * but still need to set the size since it may be used for other calculations. - */ -void GPU_viewport_size_set(GPUViewport *viewport, const int size[2]) -{ - copy_v2_v2_int(viewport->size, size); -} - -double *GPU_viewport_cache_time_get(GPUViewport *viewport) -{ - return &viewport->cache_time; -} - -/** - * Try to find a texture corresponding to params into the texture pool. - * If no texture was found, create one and add it to the pool. - */ -GPUTexture *GPU_viewport_texture_pool_query( - GPUViewport *viewport, void *engine, int width, int height, int format) +static void gpu_viewport_textures_create(GPUViewport *viewport) { - GPUTexture *tex; - - LISTBASE_FOREACH (ViewportTempTexture *, tmp_tex, &viewport->tex_pool) { - if ((GPU_texture_format(tmp_tex->texture) == format) && - (GPU_texture_width(tmp_tex->texture) == width) && - (GPU_texture_height(tmp_tex->texture) == height)) { - /* Search if the engine is not already using this texture */ - for (int i = 0; i < MAX_ENGINE_BUFFER_SHARING; i++) { - if (tmp_tex->user[i] == engine) { - break; - } - - if (tmp_tex->user[i] == NULL) { - tmp_tex->user[i] = engine; - return tmp_tex->texture; - } - } - } - } - - tex = GPU_texture_create_2d("temp_from_pool", width, height, 1, format, NULL); - /* Doing filtering for depth does not make sense when not doing shadow mapping, - * and enabling texture filtering on integer texture make them unreadable. */ - bool do_filter = !GPU_texture_depth(tex) && !GPU_texture_integer(tex); - GPU_texture_filter_mode(tex, do_filter); - - ViewportTempTexture *tmp_tex = MEM_callocN(sizeof(ViewportTempTexture), "ViewportTempTexture"); - tmp_tex->texture = tex; - tmp_tex->user[0] = engine; - BLI_addtail(&viewport->tex_pool, tmp_tex); - - return tex; -} - -static void gpu_viewport_texture_pool_clear_users(GPUViewport *viewport) -{ - ViewportTempTexture *tmp_tex_next; - - for (ViewportTempTexture *tmp_tex = viewport->tex_pool.first; tmp_tex; tmp_tex = tmp_tex_next) { - tmp_tex_next = tmp_tex->next; - bool no_user = true; - for (int i = 0; i < MAX_ENGINE_BUFFER_SHARING; i++) { - if (tmp_tex->user[i] != NULL) { - tmp_tex->user[i] = NULL; - no_user = false; - } - } - - if (no_user) { - GPU_texture_free(tmp_tex->texture); - BLI_freelinkN(&viewport->tex_pool, tmp_tex); - } - } -} - -static void gpu_viewport_texture_pool_free(GPUViewport *viewport) -{ - LISTBASE_FOREACH (ViewportTempTexture *, tmp_tex, &viewport->tex_pool) { - GPU_texture_free(tmp_tex->texture); - } - - BLI_freelistN(&viewport->tex_pool); -} - -/* Takes an NULL terminated array of engine_handle. Returns true is data is still valid. */ -bool GPU_viewport_engines_data_validate(GPUViewport *viewport, void **engine_handle_array) -{ - for (int i = 0; i < MAX_ENABLE_ENGINE && engine_handle_array[i]; i++) { - if (viewport->engine_data[i].handle != engine_handle_array[i]) { - gpu_viewport_engines_data_free(viewport); - return false; - } - } - return true; -} - -void GPU_viewport_cache_release(GPUViewport *viewport) -{ - for (int i = 0; i < MAX_ENABLE_ENGINE && viewport->engine_data[i].handle; i++) { - ViewportEngineData *data = viewport->engine_data[i].data; - int psl_len; - DRW_engine_viewport_data_size_get(data->engine_type, NULL, NULL, &psl_len, NULL); - gpu_viewport_passes_free(data->psl, psl_len); - } -} - -static void gpu_viewport_default_fb_create(GPUViewport *viewport) -{ - DefaultFramebufferList *dfbl = viewport->fbl; - DefaultTextureList *dtxl = viewport->txl; int *size = viewport->size; - bool ok = true; - dtxl->color = GPU_texture_create_2d("dtxl_color", UNPACK2(size), 1, GPU_RGBA16F, NULL); - dtxl->color_overlay = GPU_texture_create_2d( - "dtxl_color_overlay", UNPACK2(size), 1, GPU_SRGB8_A8, NULL); + if (viewport->color_render_tx[0] == NULL) { + viewport->color_render_tx[0] = GPU_texture_create_2d( + "dtxl_color", UNPACK2(size), 1, GPU_RGBA16F, NULL); + viewport->color_overlay_tx[0] = GPU_texture_create_2d( + "dtxl_color_overlay", UNPACK2(size), 1, GPU_SRGB8_A8, NULL); + } - if (viewport->flag & GPU_VIEWPORT_STEREO) { - dtxl->color_stereo = GPU_texture_create_2d( + if ((viewport->flag & GPU_VIEWPORT_STEREO) != 0 && viewport->color_render_tx[1] == NULL) { + viewport->color_render_tx[1] = GPU_texture_create_2d( "dtxl_color_stereo", UNPACK2(size), 1, GPU_RGBA16F, NULL); - dtxl->color_overlay_stereo = GPU_texture_create_2d( + viewport->color_overlay_tx[1] = GPU_texture_create_2d( "dtxl_color_overlay_stereo", UNPACK2(size), 1, GPU_SRGB8_A8, NULL); } /* Can be shared with GPUOffscreen. */ - if (dtxl->depth == NULL) { - dtxl->depth = GPU_texture_create_2d( + if (viewport->depth_tx == NULL) { + viewport->depth_tx = GPU_texture_create_2d( "dtxl_depth", UNPACK2(size), 1, GPU_DEPTH24_STENCIL8, NULL); } - if (!dtxl->depth || !dtxl->color) { - ok = false; - goto cleanup; + if (!viewport->depth_tx || !viewport->color_render_tx[0] || !viewport->color_overlay_tx[0]) { + GPU_viewport_free(viewport); } +} - gpu_viewport_framebuffer_view_set(viewport, 0); +static void gpu_viewport_textures_free(GPUViewport *viewport) +{ + GPU_FRAMEBUFFER_FREE_SAFE(viewport->stereo_comp_fb); + GPU_FRAMEBUFFER_FREE_SAFE(viewport->overlay_fb); - 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); -cleanup: - if (!ok) { - GPU_viewport_free(viewport); - DRW_opengl_context_disable(); - return; + for (int i = 0; i < 2; i++) { + GPU_TEXTURE_FREE_SAFE(viewport->color_render_tx[i]); + GPU_TEXTURE_FREE_SAFE(viewport->color_overlay_tx[i]); } - GPU_framebuffer_restore(); + GPU_TEXTURE_FREE_SAFE(viewport->depth_tx); } void GPU_viewport_bind(GPUViewport *viewport, int view, const rcti *rect) { - DefaultFramebufferList *dfbl = viewport->fbl; - int fbl_len, txl_len; - int rect_size[2]; /* add one pixel because of scissor test */ rect_size[0] = BLI_rcti_size_x(rect) + 1; @@ -504,39 +185,18 @@ void GPU_viewport_bind(GPUViewport *viewport, int view, const rcti *rect) DRW_opengl_context_enable(); - if (dfbl->default_fb) { - if (!equals_v2v2_int(viewport->size, rect_size)) { - 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, data->txl_stereo, txl_len); - } - - gpu_viewport_texture_pool_free(viewport); - viewport->active_view = -1; - } + if (!equals_v2v2_int(viewport->size, rect_size)) { + copy_v2_v2_int(viewport->size, rect_size); + gpu_viewport_textures_free(viewport); + gpu_viewport_textures_create(viewport); } - copy_v2_v2_int(viewport->size, rect_size); - - gpu_viewport_texture_pool_clear_users(viewport); - - if (!dfbl->default_fb) { - gpu_viewport_default_fb_create(viewport); - } - gpu_viewport_framebuffer_view_set(viewport, view); + viewport->active_view = view; } +/* Should be called from DRW after DRW_opengl_context_enable. */ void GPU_viewport_bind_from_offscreen(GPUViewport *viewport, struct GPUOffScreen *ofs) { - DefaultFramebufferList *dfbl = viewport->fbl; - DefaultTextureList *dtxl = viewport->txl; GPUTexture *color, *depth; GPUFrameBuffer *fb; viewport->size[0] = GPU_offscreen_width(ofs); @@ -544,14 +204,12 @@ void GPU_viewport_bind_from_offscreen(GPUViewport *viewport, struct GPUOffScreen GPU_offscreen_viewport_data_get(ofs, &fb, &color, &depth); - /* This is the only texture we can share. */ - dtxl->depth = depth; + gpu_viewport_textures_free(viewport); - gpu_viewport_texture_pool_clear_users(viewport); + /* This is the only texture we can share. */ + viewport->depth_tx = depth; - if (!dfbl->default_fb) { - gpu_viewport_default_fb_create(viewport); - } + gpu_viewport_textures_create(viewport); } void GPU_viewport_colorspace_set(GPUViewport *viewport, @@ -608,21 +266,17 @@ void GPU_viewport_stereo_composite(GPUViewport *viewport, Stereo3dFormat *stereo * 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; - /* The composite framebuffer object needs to be created in the window context. */ - GPU_framebuffer_ensure_config(&dfbl->stereo_comp_fb, + GPU_framebuffer_ensure_config(&viewport->stereo_comp_fb, { GPU_ATTACHMENT_NONE, - GPU_ATTACHMENT_TEXTURE(dtxl->color_overlay), - GPU_ATTACHMENT_TEXTURE(dtxl->color), + GPU_ATTACHMENT_TEXTURE(viewport->color_overlay_tx[0]), + GPU_ATTACHMENT_TEXTURE(viewport->color_render_tx[0]), }); 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_framebuffer_bind(viewport->stereo_comp_fb); GPU_matrix_push(); GPU_matrix_push_projection(); GPU_matrix_identity_set(); @@ -650,8 +304,8 @@ void GPU_viewport_stereo_composite(GPUViewport *viewport, Stereo3dFormat *stereo } immUniform1i("stereoDisplaySettings", settings); - GPU_texture_bind(dtxl->color_stereo, 0); - GPU_texture_bind(dtxl->color_overlay_stereo, 1); + GPU_texture_bind(viewport->color_render_tx[1], 0); + GPU_texture_bind(viewport->color_overlay_tx[1], 1); immBegin(GPU_PRIM_TRI_STRIP, 4); @@ -662,8 +316,8 @@ void GPU_viewport_stereo_composite(GPUViewport *viewport, Stereo3dFormat *stereo immEnd(); - GPU_texture_unbind(dtxl->color_stereo); - GPU_texture_unbind(dtxl->color_overlay_stereo); + GPU_texture_unbind(viewport->color_render_tx[1]); + GPU_texture_unbind(viewport->color_overlay_tx[1]); immUnbindProgram(); GPU_matrix_pop_projection(); @@ -747,14 +401,14 @@ static void gpu_viewport_batch_free(GPUViewport *viewport) /** \} */ static void gpu_viewport_draw_colormanaged(GPUViewport *viewport, + int view, const rctf *rect_pos, const rctf *rect_uv, bool display_colorspace, bool do_overlay_merge) { - DefaultTextureList *dtxl = viewport->txl; - GPUTexture *color = dtxl->color; - GPUTexture *color_overlay = dtxl->color_overlay; + GPUTexture *color = viewport->color_render_tx[view]; + GPUTexture *color_overlay = viewport->color_overlay_tx[view]; bool use_ocio = false; @@ -808,12 +462,9 @@ void GPU_viewport_draw_to_screen_ex(GPUViewport *viewport, bool display_colorspace, bool do_overlay_merge) { - gpu_viewport_framebuffer_view_set(viewport, view); - DefaultFramebufferList *dfbl = viewport->fbl; - DefaultTextureList *dtxl = viewport->txl; - GPUTexture *color = dtxl->color; + GPUTexture *color = viewport->color_render_tx[view]; - if (dfbl->default_fb == NULL) { + if (color == NULL) { return; } @@ -854,7 +505,7 @@ void GPU_viewport_draw_to_screen_ex(GPUViewport *viewport, } gpu_viewport_draw_colormanaged( - viewport, &pos_rect, &uv_rect, display_colorspace, do_overlay_merge); + viewport, view, &pos_rect, &uv_rect, display_colorspace, do_overlay_merge); } /** @@ -877,10 +528,7 @@ void GPU_viewport_unbind_from_offscreen(GPUViewport *viewport, bool display_colorspace, bool do_overlay_merge) { - DefaultFramebufferList *dfbl = viewport->fbl; - DefaultTextureList *dtxl = viewport->txl; - - if (dfbl->default_fb == NULL) { + if (viewport->color_render_tx == NULL) { return; } @@ -902,10 +550,10 @@ void GPU_viewport_unbind_from_offscreen(GPUViewport *viewport, }; gpu_viewport_draw_colormanaged( - viewport, &pos_rect, &uv_rect, display_colorspace, do_overlay_merge); + viewport, 0, &pos_rect, &uv_rect, display_colorspace, do_overlay_merge); /* This one is from the offscreen. Don't free it with the viewport. */ - dtxl->depth = NULL; + viewport->depth_tx = NULL; } void GPU_viewport_unbind(GPUViewport *UNUSED(viewport)) @@ -914,149 +562,53 @@ void GPU_viewport_unbind(GPUViewport *UNUSED(viewport)) DRW_opengl_context_disable(); } -GPUTexture *GPU_viewport_color_texture(GPUViewport *viewport, int view) +int GPU_viewport_active_view_get(GPUViewport *viewport) { - DefaultFramebufferList *dfbl = viewport->fbl; - - if (dfbl->default_fb) { - DefaultTextureList *dtxl = viewport->txl; - if (viewport->active_view == view) { - return dtxl->color; - } + return viewport->active_view; +} - return dtxl->color_stereo; - } +bool GPU_viewport_is_stereo_get(GPUViewport *viewport) +{ + return (viewport->flag & GPU_VIEWPORT_STEREO) != 0; +} - return NULL; +GPUTexture *GPU_viewport_color_texture(GPUViewport *viewport, int view) +{ + return viewport->color_render_tx[view]; } -static void gpu_viewport_buffers_free( - FramebufferList *fbl, int fbl_len, TextureList *txl, TextureList *txl_stereo, int txl_len) +GPUTexture *GPU_viewport_overlay_texture(GPUViewport *viewport, int view) { - for (int i = 0; i < fbl_len; i++) { - GPUFrameBuffer *fb = fbl->framebuffers[i]; - if (fb) { - GPU_framebuffer_free(fb); - fbl->framebuffers[i] = NULL; - } - } - for (int i = 0; i < txl_len; i++) { - GPUTexture *tex = txl->textures[i]; - if (tex) { - GPU_texture_free(tex); - 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; - } - } - } + return viewport->color_overlay_tx[view]; } -static void gpu_viewport_storage_free(StorageList *stl, int stl_len) +GPUTexture *GPU_viewport_depth_texture(GPUViewport *viewport) { - for (int i = 0; i < stl_len; i++) { - void *storage = stl->storage[i]; - if (storage) { - MEM_freeN(storage); - stl->storage[i] = NULL; - } - } + return viewport->depth_tx; } -static void gpu_viewport_passes_free(PassList *psl, int psl_len) +/* Overlay framebuffer for drawing outside of DRW module. */ +GPUFrameBuffer *GPU_viewport_framebuffer_overlay_get(GPUViewport *viewport) { - memset(psl->passes, 0, sizeof(*psl->passes) * psl_len); + GPU_framebuffer_ensure_config(&viewport->overlay_fb, + { + GPU_ATTACHMENT_TEXTURE(viewport->depth_tx), + GPU_ATTACHMENT_TEXTURE(viewport->color_overlay_tx[0]), + }); + return viewport->overlay_fb; } /* Must be executed inside Draw-manager OpenGL Context. */ void GPU_viewport_free(GPUViewport *viewport) { - gpu_viewport_engines_data_free(viewport); - - gpu_viewport_buffers_free((FramebufferList *)viewport->fbl, - default_fbl_len, - (TextureList *)viewport->txl, - NULL, - default_txl_len); - - gpu_viewport_texture_pool_free(viewport); - - MEM_freeN(viewport->fbl); - MEM_freeN(viewport->txl); - - if (viewport->vmempool.commands != NULL) { - BLI_memblock_destroy(viewport->vmempool.commands, NULL); - } - if (viewport->vmempool.commands_small != NULL) { - BLI_memblock_destroy(viewport->vmempool.commands_small, NULL); - } - if (viewport->vmempool.callbuffers != NULL) { - BLI_memblock_destroy(viewport->vmempool.callbuffers, NULL); - } - if (viewport->vmempool.obmats != NULL) { - BLI_memblock_destroy(viewport->vmempool.obmats, NULL); - } - if (viewport->vmempool.obinfos != NULL) { - BLI_memblock_destroy(viewport->vmempool.obinfos, NULL); - } - if (viewport->vmempool.cullstates != NULL) { - BLI_memblock_destroy(viewport->vmempool.cullstates, NULL); - } - if (viewport->vmempool.shgroups != NULL) { - BLI_memblock_destroy(viewport->vmempool.shgroups, NULL); - } - if (viewport->vmempool.uniforms != NULL) { - BLI_memblock_destroy(viewport->vmempool.uniforms, NULL); - } - if (viewport->vmempool.views != NULL) { - BLI_memblock_destroy(viewport->vmempool.views, NULL); - } - if (viewport->vmempool.passes != NULL) { - BLI_memblock_destroy(viewport->vmempool.passes, NULL); - } - if (viewport->vmempool.images != NULL) { - BLI_memblock_iter iter; - GPUTexture **tex; - BLI_memblock_iternew(viewport->vmempool.images, &iter); - while ((tex = BLI_memblock_iterstep(&iter))) { - GPU_texture_free(*tex); - } - BLI_memblock_destroy(viewport->vmempool.images, NULL); - } - if (viewport->vmempool.obattrs_ubo_pool != NULL) { - DRW_uniform_attrs_pool_free(viewport->vmempool.obattrs_ubo_pool); + if (viewport->draw_data) { + DRW_viewport_data_free(viewport->draw_data); } - for (int i = 0; i < viewport->vmempool.ubo_len; i++) { - GPU_uniformbuf_free(viewport->vmempool.matrices_ubo[i]); - GPU_uniformbuf_free(viewport->vmempool.obinfos_ubo[i]); - } - MEM_SAFE_FREE(viewport->vmempool.matrices_ubo); - MEM_SAFE_FREE(viewport->vmempool.obinfos_ubo); - - DRW_instance_data_list_free(viewport->idatalist); - MEM_freeN(viewport->idatalist); + gpu_viewport_textures_free(viewport); BKE_color_managed_view_settings_free(&viewport->view_settings); gpu_viewport_batch_free(viewport); MEM_freeN(viewport); } - -GPUFrameBuffer *GPU_viewport_framebuffer_default_get(GPUViewport *viewport) -{ - DefaultFramebufferList *fbl = GPU_viewport_framebuffer_list_get(viewport); - return fbl->default_fb; -} - -GPUFrameBuffer *GPU_viewport_framebuffer_overlay_get(GPUViewport *viewport) -{ - DefaultFramebufferList *fbl = GPU_viewport_framebuffer_list_get(viewport); - return fbl->overlay_fb; -} |