245 lines
8.0 KiB
C++
245 lines
8.0 KiB
C++
/*
|
|
* 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;
|
|
};
|
|
|
|
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]);
|
|
}
|
|
|
|
if (data->instance_data) {
|
|
BLI_assert(engine_type->instance_free != nullptr);
|
|
engine_type->instance_free(data->instance_data);
|
|
data->instance_data = nullptr;
|
|
}
|
|
|
|
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;
|
|
}
|