diff options
Diffstat (limited to 'source/blender/draw/intern/draw_view_data.cc')
-rw-r--r-- | source/blender/draw/intern/draw_view_data.cc | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/source/blender/draw/intern/draw_view_data.cc b/source/blender/draw/intern/draw_view_data.cc new file mode 100644 index 00000000000..55ebbf82c29 --- /dev/null +++ b/source/blender/draw/intern/draw_view_data.cc @@ -0,0 +1,243 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright 2021, Blender Foundation. + */ + +/** \file + * \ingroup draw + */ + +#include "BLI_vector.hh" + +#include "GPU_viewport.h" + +#include "DRW_render.h" + +#include "draw_instance_data.h" + +#include "draw_manager_text.h" + +#include "draw_manager.h" +#include "draw_view_data.h" + +using namespace blender; + +struct DRWViewData { + DefaultFramebufferList dfbl = {}; + DefaultTextureList dtxl = {}; + /** True indicates the textures inside dtxl are from the viewport and should not be freed. */ + bool from_viewport = false; + /** Common size for texture in the engines texture list. + * We free all texture lists if it changes. */ + int texture_list_size[2] = {0, 0}; + + double cache_time = 0.0; + + Vector<ViewportEngineData> engines; + Vector<ViewportEngineData *> enabled_engines; +}; + +/** + * Creates a view data with all possible engines type for this view. + * + * `engine_types` contains `DRWRegisteredDrawEngine`. + * */ +DRWViewData *DRW_view_data_create(ListBase *engine_types) +{ + DRWViewData *view_data = new DRWViewData(); + LISTBASE_FOREACH (DRWRegisteredDrawEngine *, type, engine_types) { + ViewportEngineData engine = {}; + engine.engine_type = type; + view_data->engines.append(engine); + } + return view_data; +} + +void DRW_view_data_default_lists_from_viewport(DRWViewData *view_data, GPUViewport *viewport) +{ + int active_view = GPU_viewport_active_view_get(viewport); + view_data->from_viewport = true; + + DefaultFramebufferList *dfbl = &view_data->dfbl; + DefaultTextureList *dtxl = &view_data->dtxl; + /* Depth texture is shared between both stereo views. */ + dtxl->depth = GPU_viewport_depth_texture(viewport); + dtxl->color = GPU_viewport_color_texture(viewport, active_view); + dtxl->color_overlay = GPU_viewport_overlay_texture(viewport, active_view); + + 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), + }); +} + +static void draw_viewport_engines_data_clear(ViewportEngineData *data) +{ + DrawEngineType *engine_type = data->engine_type->draw_engine; + const DrawEngineDataSize *data_size = engine_type->vedata_size; + + for (int i = 0; data->fbl && i < data_size->fbl_len; i++) { + GPU_FRAMEBUFFER_FREE_SAFE(data->fbl->framebuffers[i]); + } + for (int i = 0; data->txl && i < data_size->txl_len; i++) { + GPU_TEXTURE_FREE_SAFE(data->txl->textures[i]); + } + for (int i = 0; data->stl && i < data_size->stl_len; i++) { + MEM_SAFE_FREE(data->stl->storage[i]); + } + + MEM_SAFE_FREE(data->fbl); + MEM_SAFE_FREE(data->txl); + MEM_SAFE_FREE(data->psl); + MEM_SAFE_FREE(data->stl); + + if (data->text_draw_cache) { + DRW_text_cache_destroy(data->text_draw_cache); + data->text_draw_cache = nullptr; + } +} + +static void draw_view_data_clear(DRWViewData *view_data) +{ + GPU_FRAMEBUFFER_FREE_SAFE(view_data->dfbl.default_fb); + GPU_FRAMEBUFFER_FREE_SAFE(view_data->dfbl.overlay_fb); + GPU_FRAMEBUFFER_FREE_SAFE(view_data->dfbl.in_front_fb); + GPU_FRAMEBUFFER_FREE_SAFE(view_data->dfbl.color_only_fb); + GPU_FRAMEBUFFER_FREE_SAFE(view_data->dfbl.depth_only_fb); + GPU_FRAMEBUFFER_FREE_SAFE(view_data->dfbl.overlay_only_fb); + + if (!view_data->from_viewport) { + GPU_TEXTURE_FREE_SAFE(view_data->dtxl.color); + GPU_TEXTURE_FREE_SAFE(view_data->dtxl.color_overlay); + GPU_TEXTURE_FREE_SAFE(view_data->dtxl.depth); + } + GPU_TEXTURE_FREE_SAFE(view_data->dtxl.depth_in_front); + + for (ViewportEngineData &engine : view_data->engines) { + draw_viewport_engines_data_clear(&engine); + } + + view_data->texture_list_size[0] = view_data->texture_list_size[1] = 0; + view_data->cache_time = 0.0f; +} + +void DRW_view_data_free(DRWViewData *view_data) +{ + draw_view_data_clear(view_data); + delete view_data; +} + +void DRW_view_data_texture_list_size_validate(DRWViewData *view_data, const int size[2]) +{ + if (!equals_v2v2_int(view_data->texture_list_size, size)) { + draw_view_data_clear(view_data); + copy_v2_v2_int(view_data->texture_list_size, size); + } +} + +ViewportEngineData *DRW_view_data_engine_data_get_ensure(DRWViewData *view_data, + DrawEngineType *engine_type) +{ + for (ViewportEngineData &engine : view_data->engines) { + if (engine.engine_type->draw_engine == engine_type) { + if (engine.fbl == nullptr) { + const DrawEngineDataSize *data_size = engine_type->vedata_size; + engine.fbl = (FramebufferList *)MEM_calloc_arrayN( + data_size->fbl_len, sizeof(GPUFrameBuffer *), "FramebufferList"); + engine.txl = (TextureList *)MEM_calloc_arrayN( + data_size->txl_len, sizeof(GPUTexture *), "TextureList"); + engine.psl = (PassList *)MEM_calloc_arrayN( + data_size->psl_len, sizeof(DRWPass *), "PassList"); + engine.stl = (StorageList *)MEM_calloc_arrayN( + data_size->stl_len, sizeof(void *), "StorageList"); + } + return &engine; + } + } + return nullptr; +} + +void DRW_view_data_use_engine(DRWViewData *view_data, DrawEngineType *engine_type) +{ + ViewportEngineData *engine = DRW_view_data_engine_data_get_ensure(view_data, engine_type); + view_data->enabled_engines.append(engine); +} + +void DRW_view_data_reset(DRWViewData *view_data) +{ + view_data->enabled_engines.clear(); +} + +void DRW_view_data_free_unused(DRWViewData *view_data) +{ + for (ViewportEngineData &engine : view_data->engines) { + if (view_data->enabled_engines.first_index_of_try(&engine) == -1) { + draw_viewport_engines_data_clear(&engine); + } + } +} + +double *DRW_view_data_cache_time_get(DRWViewData *view_data) +{ + return &view_data->cache_time; +} + +DefaultFramebufferList *DRW_view_data_default_framebuffer_list_get(DRWViewData *view_data) +{ + return &view_data->dfbl; +} + +DefaultTextureList *DRW_view_data_default_texture_list_get(DRWViewData *view_data) +{ + return &view_data->dtxl; +} + +void DRW_view_data_enabled_engine_iter_begin(DRWEngineIterator *iterator, DRWViewData *view_data) +{ + iterator->id = 0; + iterator->end = view_data->enabled_engines.size(); + iterator->engines = view_data->enabled_engines.data(); +} + +ViewportEngineData *DRW_view_data_enabled_engine_iter_step(DRWEngineIterator *iterator) +{ + if (iterator->id >= iterator->end) { + return nullptr; + } + ViewportEngineData *engine = iterator->engines[iterator->id++]; + return engine; +} |