Refactor: DRW: Replace by enabled engine list by static members

Iteration is done through templates.

Removes the need for the enabled engine list/vector.

Reduces API complexity.
This commit is contained in:
Clément Foucault
2025-03-05 19:42:07 +01:00
parent 4f909ba6fd
commit 5a32440edf
6 changed files with 249 additions and 278 deletions

View File

@@ -35,7 +35,6 @@ void DRW_engines_register();
void DRW_engines_free();
bool DRW_engine_render_support(DrawEngineType *draw_engine_type);
void DRW_engine_register(DrawEngineType *draw_engine_type);
void DRW_engine_external_free(RegionView3D *rv3d);

View File

@@ -87,6 +87,7 @@
#include "draw_shader.hh"
#include "draw_subdivision.hh"
#include "draw_view_c.hh"
#include "draw_view_data.hh"
/* only for callbacks */
#include "draw_cache_impl.hh"
@@ -171,11 +172,6 @@ void DRWContext::state_ensure_not_reused()
g_context = nullptr;
}
static struct {
ListBase /*DRWRegisteredDrawEngine*/ engines;
int len;
} g_registered_engines = {{nullptr}};
static bool drw_draw_show_annotation()
{
if (drw_get().draw_ctx.space_data == nullptr) {
@@ -363,7 +359,7 @@ DRWData *DRW_viewport_data_create()
drw_data->default_view = new blender::draw::View("DrawDefaultView");
for (int i = 0; i < 2; i++) {
drw_data->view_data[i] = DRW_view_data_create(&g_registered_engines.engines);
drw_data->view_data[i] = new DRWViewData();
}
return drw_data;
}
@@ -390,7 +386,7 @@ static void drw_viewport_data_reset(DRWData * /*drw_data*/)
void DRW_viewport_data_free(DRWData *drw_data)
{
for (int i = 0; i < 2; i++) {
DRW_view_data_free(drw_data->view_data[i]);
delete drw_data->view_data[i];
}
DRW_volume_module_free(drw_data->volume_module);
DRW_pointcloud_module_free(drw_data->pointcloud_module);
@@ -472,8 +468,7 @@ static void drw_manager_init(DRWContext *dst, GPUViewport *viewport, const int s
dst->inv_size[1] = 1.0f / dst->size[1];
if (do_validation) {
DRW_view_data_texture_list_size_validate(dst->view_data_active,
blender::int2{int(dst->size[0]), int(dst->size[1])});
dst->view_data_active->texture_list_size_validate(int2(dst->size));
}
if (viewport) {
@@ -920,30 +915,34 @@ void DRW_cache_free_old_batches(Main *bmain)
static void drw_engines_init()
{
DRW_ENABLED_ENGINE_ITER (drw_get().view_data_active, engine, data) {
if (engine->engine_init) {
engine->engine_init(data);
}
}
DRWContext &ctx = drw_get();
ctx.view_data_active->foreach_enabled_engine(
[&](ViewportEngineData *data, DrawEngineType *engine) {
if (engine->engine_init) {
engine->engine_init(data);
}
});
}
static void drw_engines_cache_init()
{
DRW_manager_begin_sync();
DRW_ENABLED_ENGINE_ITER (drw_get().view_data_active, engine, data) {
if (data->text_draw_cache) {
DRW_text_cache_destroy(data->text_draw_cache);
data->text_draw_cache = nullptr;
}
if (drw_get().text_store_p == nullptr) {
drw_get().text_store_p = &data->text_draw_cache;
}
DRWContext &ctx = drw_get();
ctx.view_data_active->foreach_enabled_engine(
[&](ViewportEngineData *data, DrawEngineType *engine) {
if (data->text_draw_cache) {
DRW_text_cache_destroy(data->text_draw_cache);
data->text_draw_cache = nullptr;
}
if (drw_get().text_store_p == nullptr) {
drw_get().text_store_p = &data->text_draw_cache;
}
if (engine->cache_init) {
engine->cache_init(data);
}
}
if (engine->cache_init) {
engine->cache_init(data);
}
});
}
static void drw_engines_world_update(Scene *scene)
@@ -952,11 +951,13 @@ static void drw_engines_world_update(Scene *scene)
return;
}
DRW_ENABLED_ENGINE_ITER (drw_get().view_data_active, engine, data) {
if (engine->id_update) {
engine->id_update(data, &scene->world->id);
}
}
DRWContext &ctx = drw_get();
ctx.view_data_active->foreach_enabled_engine(
[&](ViewportEngineData *data, DrawEngineType *engine) {
if (engine->id_update) {
engine->id_update(data, &scene->world->id);
}
});
}
static void drw_engines_cache_populate(blender::draw::ObjectRef &ref)
@@ -972,11 +973,13 @@ static void drw_engines_cache_populate(blender::draw::ObjectRef &ref)
drw_batch_cache_validate(ref.object);
}
DRW_ENABLED_ENGINE_ITER (drw_get().view_data_active, engine, data) {
if (engine->cache_populate) {
engine->cache_populate(data, ref);
}
}
DRWContext &ctx = drw_get();
ctx.view_data_active->foreach_enabled_engine(
[&](ViewportEngineData *data, DrawEngineType *engine) {
if (engine->cache_populate) {
engine->cache_populate(data, ref);
}
});
/* TODO: in the future it would be nice to generate once for all viewports.
* But we need threaded DRW manager first. */
@@ -991,56 +994,63 @@ static void drw_engines_cache_populate(blender::draw::ObjectRef &ref)
static void drw_engines_cache_finish()
{
DRW_ENABLED_ENGINE_ITER (drw_get().view_data_active, engine, data) {
if (engine->cache_finish) {
engine->cache_finish(data);
}
}
DRWContext &ctx = drw_get();
ctx.view_data_active->foreach_enabled_engine(
[&](ViewportEngineData *data, DrawEngineType *engine) {
if (engine->cache_finish) {
engine->cache_finish(data);
}
});
DRW_manager_end_sync();
}
static void drw_engines_draw_scene()
{
DRW_ENABLED_ENGINE_ITER (drw_get().view_data_active, engine, data) {
if (engine->draw_scene) {
GPU_debug_group_begin(engine->idname);
engine->draw_scene(data);
/* Restore for next engine */
if (DRW_state_is_fbo()) {
GPU_framebuffer_bind(drw_get().default_framebuffer());
}
GPU_debug_group_end();
}
}
DRWContext &ctx = drw_get();
ctx.view_data_active->foreach_enabled_engine(
[&](ViewportEngineData *data, DrawEngineType *engine) {
if (engine->draw_scene) {
GPU_debug_group_begin(engine->idname);
engine->draw_scene(data);
/* Restore for next engine */
if (DRW_state_is_fbo()) {
GPU_framebuffer_bind(ctx.default_framebuffer());
}
GPU_debug_group_end();
}
});
/* Reset state after drawing */
blender::draw::command::StateSet::set();
}
static void drw_engines_draw_text()
{
DRW_ENABLED_ENGINE_ITER (drw_get().view_data_active, engine, data) {
if (data->text_draw_cache) {
DRW_text_cache_draw(
data->text_draw_cache, drw_get().draw_ctx.region, drw_get().draw_ctx.v3d);
}
}
DRWContext &ctx = drw_get();
ctx.view_data_active->foreach_enabled_engine(
[&](ViewportEngineData *data, DrawEngineType * /*engine*/) {
if (data->text_draw_cache) {
DRW_text_cache_draw(data->text_draw_cache, ctx.draw_ctx.region, ctx.draw_ctx.v3d);
}
});
}
void DRW_draw_region_engine_info(int xoffset, int *yoffset, int line_height)
{
DRW_ENABLED_ENGINE_ITER (drw_get().view_data_active, engine, data) {
if (data->info[0] != '\0') {
const char *buf_step = IFACE_(data->info);
do {
const char *buf = buf_step;
buf_step = BLI_strchr_or_end(buf, '\n');
const int buf_len = buf_step - buf;
*yoffset -= line_height;
BLF_draw_default(xoffset, *yoffset, 0.0f, buf, buf_len);
} while (*buf_step ? ((void)buf_step++, true) : false);
}
}
DRWContext &ctx = drw_get();
ctx.view_data_active->foreach_enabled_engine(
[&](ViewportEngineData *data, DrawEngineType * /*engine*/) {
if (data->info[0] != '\0') {
const char *buf_step = IFACE_(data->info);
do {
const char *buf = buf_step;
buf_step = BLI_strchr_or_end(buf, '\n');
const int buf_len = buf_step - buf;
*yoffset -= line_height;
BLF_draw_default(xoffset, *yoffset, 0.0f, buf, buf_len);
} while (*buf_step ? ((void)buf_step++, true) : false);
}
});
}
static void use_drw_engine(DrawEngineType *engine)
@@ -1708,6 +1718,7 @@ static void DRW_render_gpencil_to_image(RenderEngine *engine,
const rcti *rect)
{
DrawEngineType *draw_engine = &draw_engine_gpencil_type;
if (draw_engine->render_to_image) {
ViewportEngineData *gpdata = DRW_view_data_engine_data_get_ensure(drw_get().view_data_active,
draw_engine);
@@ -2785,17 +2796,6 @@ bool DRW_engine_render_support(DrawEngineType *draw_engine_type)
return draw_engine_type->render_to_image;
}
void DRW_engine_register(DrawEngineType *draw_engine_type)
{
DRWRegisteredDrawEngine *draw_engine = static_cast<DRWRegisteredDrawEngine *>(
MEM_mallocN(sizeof(DRWRegisteredDrawEngine), __func__));
draw_engine->draw_engine = draw_engine_type;
draw_engine->index = g_registered_engines.len;
BLI_addtail(&g_registered_engines.engines, draw_engine);
g_registered_engines.len = BLI_listbase_count(&g_registered_engines.engines);
}
void DRW_engines_register()
{
using namespace blender::draw;
@@ -2803,19 +2803,6 @@ void DRW_engines_register()
RE_engines_register(&DRW_engine_viewport_workbench_type);
DRW_engine_register(&draw_engine_gpencil_type);
DRW_engine_register(&draw_engine_overlay_next_type);
DRW_engine_register(&draw_engine_select_next_type);
DRW_engine_register(&draw_engine_select_type);
DRW_engine_register(&draw_engine_compositor_type);
#ifdef WITH_DRAW_DEBUG
DRW_engine_register(&draw_engine_debug_select_type);
#endif
DRW_engine_register(&draw_engine_image_type);
DRW_engine_register(DRW_engine_viewport_external_type.draw_engine);
/* setup callbacks */
{
BKE_curve_batch_cache_dirty_tag_cb = DRW_curve_batch_cache_dirty_tag;
@@ -2846,31 +2833,19 @@ void DRW_engines_register()
}
}
static void drw_registered_engines_free()
{
DRWRegisteredDrawEngine *next;
for (DRWRegisteredDrawEngine *type =
static_cast<DRWRegisteredDrawEngine *>(g_registered_engines.engines.first);
type;
type = next)
{
next = static_cast<DRWRegisteredDrawEngine *>(type->next);
BLI_remlink(&R_engines, type);
if (type->draw_engine->engine_free) {
type->draw_engine->engine_free();
}
MEM_freeN(type);
}
BLI_listbase_clear(&g_registered_engines.engines);
g_registered_engines.len = 0;
}
void DRW_engines_free()
{
using namespace blender::draw;
drw_registered_engines_free();
DRW_engine_viewport_eevee_next_type.draw_engine->engine_free();
DRW_engine_viewport_workbench_type.draw_engine->engine_free();
draw_engine_gpencil_type.engine_free();
draw_engine_image_type.engine_free();
draw_engine_overlay_next_type.engine_free();
#ifdef WITH_DRAW_DEBUG
draw_engine_debug_select_type.engine_free();
#endif
draw_engine_select_type.engine_free();
if (system_gpu_context == nullptr) {
/* Nothing has been setup. Nothing to clear.

View File

@@ -40,22 +40,6 @@ class View;
struct GPUMaterial;
struct GSet;
/* -------------------------------------------------------------------- */
/** \name Data Structure
*
* Data structure to for registered draw engines that can store draw manager
* specific data.
* \{ */
typedef struct DRWRegisteredDrawEngine {
void /*DRWRegisteredDrawEngine*/ *next, *prev;
DrawEngineType *draw_engine;
/** Index of the type in the lists. Index is used for dupli data. */
int index;
} DRWRegisteredDrawEngine;
/** \} */
/* -------------------------------------------------------------------- */
/** \name Memory Pools
* \{ */

View File

@@ -23,55 +23,39 @@
#include "draw_manager_c.hh"
#include "draw_view_data.hh"
#include "engines/compositor/compositor_engine.h"
#include "engines/eevee_next/eevee_engine.h"
#include "engines/external/external_engine.h"
#include "engines/gpencil/gpencil_engine.h"
#include "engines/image/image_engine.h"
#include "engines/overlay/overlay_engine.h"
#include "engines/select/select_engine.hh"
#include "engines/workbench/workbench_engine.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. */
int2 texture_list_size = {0, 0};
double cache_time = 0.0;
Vector<ViewportEngineData> engines;
Vector<ViewportEngineData *> enabled_engines;
/* Stores passes needed by the viewport compositor. Engines are expected to populate those in
* every redraw using calls to the DRW_viewport_pass_texture_get function. The compositor can
* then call the same function to retrieve the passes it needs, which are expected to be
* initialized. Those textures are release when view data is reset. */
Map<std::string, std::unique_ptr<draw::TextureFromPool>> viewport_compositor_passes;
/** New per view/viewport manager. Null if not supported by current hardware. */
draw::Manager *manager = nullptr;
DRWViewData()
{
manager = new draw::Manager();
};
~DRWViewData()
{
delete manager;
};
DRWViewData::DRWViewData()
: eevee(DRW_engine_viewport_eevee_next_type.draw_engine),
workbench(DRW_engine_viewport_workbench_type.draw_engine),
external(&draw_engine_external_type),
image(&draw_engine_image_type),
grease_pencil(&draw_engine_gpencil_type),
overlay(&draw_engine_overlay_next_type),
object_select(&draw_engine_select_next_type),
edit_select(&draw_engine_select_type),
#ifdef WITH_DRAW_DEBUG
edit_select_debug(DRW_engine_viewport_select_type.draw_engine),
#endif
compositor(&draw_engine_compositor_type)
{
manager = new draw::Manager();
};
DRWViewData *DRW_view_data_create(ListBase *engine_types)
DRWViewData::~DRWViewData()
{
const int engine_types_len = BLI_listbase_count(engine_types);
DRWViewData *view_data = new DRWViewData();
view_data->engines.reserve(engine_types_len);
LISTBASE_FOREACH (DRWRegisteredDrawEngine *, type, engine_types) {
ViewportEngineData engine = {};
engine.engine_type = type;
view_data->engines.append(engine);
}
return view_data;
}
this->clear(true);
delete manager;
};
draw::TextureFromPool &DRW_view_data_pass_texture_get(DRWViewData *view_data,
const char *pass_name)
@@ -121,7 +105,7 @@ void DRW_view_data_default_lists_from_viewport(DRWViewData *view_data, GPUViewpo
static void draw_viewport_engines_data_clear(ViewportEngineData *data, bool clear_instance_data)
{
DrawEngineType *engine_type = data->engine_type->draw_engine;
DrawEngineType *engine_type = data->draw_engine;
if (clear_instance_data && data->instance_data) {
BLI_assert(engine_type->instance_free != nullptr);
@@ -135,61 +119,57 @@ static void draw_viewport_engines_data_clear(ViewportEngineData *data, bool clea
}
}
static void draw_view_data_clear(DRWViewData *view_data, bool free_instance_data)
void DRWViewData::clear(bool free_instance_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);
GPU_FRAMEBUFFER_FREE_SAFE(this->dfbl.default_fb);
GPU_FRAMEBUFFER_FREE_SAFE(this->dfbl.overlay_fb);
GPU_FRAMEBUFFER_FREE_SAFE(this->dfbl.in_front_fb);
GPU_FRAMEBUFFER_FREE_SAFE(this->dfbl.color_only_fb);
GPU_FRAMEBUFFER_FREE_SAFE(this->dfbl.depth_only_fb);
GPU_FRAMEBUFFER_FREE_SAFE(this->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);
if (!this->from_viewport) {
GPU_TEXTURE_FREE_SAFE(this->dtxl.color);
GPU_TEXTURE_FREE_SAFE(this->dtxl.color_overlay);
GPU_TEXTURE_FREE_SAFE(this->dtxl.depth);
}
GPU_TEXTURE_FREE_SAFE(view_data->dtxl.depth_in_front);
GPU_TEXTURE_FREE_SAFE(this->dtxl.depth_in_front);
for (ViewportEngineData &engine : view_data->engines) {
draw_viewport_engines_data_clear(&engine, free_instance_data);
}
foreach_engine([&](ViewportEngineData *data, DrawEngineType * /*engine*/) {
draw_viewport_engines_data_clear(data, free_instance_data);
});
}
void DRW_view_data_free(DRWViewData *view_data)
void DRWViewData::texture_list_size_validate(const blender::int2 &size)
{
draw_view_data_clear(view_data, true);
delete view_data;
}
void DRW_view_data_texture_list_size_validate(DRWViewData *view_data, const int size[2])
{
if (view_data->texture_list_size != int2(size)) {
draw_view_data_clear(view_data, false);
copy_v2_v2_int(view_data->texture_list_size, size);
if (this->texture_list_size != size) {
this->clear(false);
copy_v2_v2_int(this->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) {
return &engine;
ViewportEngineData *result = nullptr;
view_data->foreach_engine([&](ViewportEngineData *data, DrawEngineType *engine) {
if (engine_type == engine) {
result = data;
}
}
return nullptr;
});
return result;
}
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);
engine->used = true;
}
void DRW_view_data_reset(DRWViewData *view_data)
{
view_data->enabled_engines.clear();
view_data->foreach_enabled_engine(
[&](ViewportEngineData *data, DrawEngineType * /*engine*/) { data->used = false; });
for (std::unique_ptr<draw::TextureFromPool> &texture :
view_data->viewport_compositor_passes.values())
@@ -201,26 +181,20 @@ void DRW_view_data_reset(DRWViewData *view_data)
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, false);
view_data->foreach_engine([&](ViewportEngineData *data, DrawEngineType * /*engine*/) {
if (data->used == false) {
draw_viewport_engines_data_clear(data, false);
}
}
});
}
void DRW_view_data_engines_view_update(DRWViewData *view_data)
{
for (ViewportEngineData &engine_data : view_data->engines) {
DrawEngineType *draw_engine = engine_data.engine_type->draw_engine;
if (draw_engine->view_update) {
draw_engine->view_update(&engine_data);
view_data->foreach_enabled_engine([&](ViewportEngineData *data, DrawEngineType *engine) {
if (engine->view_update) {
engine->view_update(data);
}
}
}
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)
@@ -233,22 +207,6 @@ DefaultTextureList *DRW_view_data_default_texture_list_get(DRWViewData *view_dat
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;
}
draw::Manager *DRW_manager_get()
{
BLI_assert(drw_get().view_data_active->manager);

View File

@@ -11,15 +11,21 @@
#pragma once
#include "BLI_map.hh"
#include "BLI_math_vector_types.hh"
#include "DRW_render.hh"
#include "draw_manager_c.hh"
#define GPU_INFO_SIZE 512 /* IMA_MAX_RENDER_TEXT_SIZE */
namespace blender::draw {
class TextureFromPool;
class Manager;
} // namespace blender::draw
struct DRWRegisteredDrawEngine;
struct DRWTextStore;
struct DrawEngineType;
struct DRWTextStore;
struct GPUFrameBuffer;
struct GPUTexture;
struct GPUViewport;
@@ -27,18 +33,22 @@ struct ListBase;
struct ViewportEngineData {
/* Not owning pointer to the draw engine. */
DRWRegisteredDrawEngine *engine_type;
DrawEngineType *draw_engine;
/**
* \brief Memory block that can be freely used by the draw engine.
* When used the draw engine must implement #DrawEngineType.instance_free callback.
*/
void *instance_data;
void *instance_data = nullptr;
char info[GPU_INFO_SIZE];
char info[GPU_INFO_SIZE] = {'\0'};
/* we may want to put this elsewhere */
DRWTextStore *text_draw_cache;
DRWTextStore *text_draw_cache = nullptr;
bool used = false;
ViewportEngineData(DrawEngineType *engine_type) : draw_engine(engine_type) {}
};
struct ViewportEngineData_Info {
@@ -65,15 +75,84 @@ struct DefaultTextureList {
GPUTexture *depth_in_front;
};
struct DRWViewData;
struct DRWViewData {
public:
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. */
blender::int2 texture_list_size = {0, 0};
/**
* Creates a view data with all possible engines type for this view.
*
* `engine_types` contains #DRWRegisteredDrawEngine.
*/
DRWViewData *DRW_view_data_create(ListBase *engine_types);
void DRW_view_data_free(DRWViewData *view_data);
/* Engines running for this viewport. nullptr if not enabled. */
/* TODO(fclem): Directly use each engine class. */
ViewportEngineData eevee;
ViewportEngineData workbench;
ViewportEngineData external;
ViewportEngineData image;
ViewportEngineData grease_pencil;
ViewportEngineData overlay;
ViewportEngineData object_select;
ViewportEngineData edit_select;
#ifdef WITH_DRAW_DEBUG
ViewportEngineData edit_select_debug;
#endif
ViewportEngineData compositor;
/* Stores passes needed by the viewport compositor. Engines are expected to populate those in
* every redraw using calls to the DRW_viewport_pass_texture_get function. The compositor can
* then call the same function to retrieve the passes it needs, which are expected to be
* initialized. Those textures are release when view data is reset. */
blender::Map<std::string, std::unique_ptr<blender::draw::TextureFromPool>>
viewport_compositor_passes;
/** New per view/viewport manager. Null if not supported by current hardware. */
blender::draw::Manager *manager = nullptr;
public:
DRWViewData();
~DRWViewData();
void texture_list_size_validate(const blender::int2 &size);
template<typename CallbackT> void foreach_engine(CallbackT callback)
{
/* IMPORTANT: Order here defines the draw order. */
/* Render engines. Output to the render result framebuffer. Mutually exclusive. */
callback(&eevee, eevee.draw_engine);
callback(&workbench, workbench.draw_engine);
callback(&external, external.draw_engine);
callback(&image, image.draw_engine);
#ifdef WITH_DRAW_DEBUG
callback(&edit_select_debug, edit_select_debug.draw_engine);
#endif
/* Grease pencil. Merge its output to the render result framebuffer. */
callback(&grease_pencil, grease_pencil.draw_engine);
/* GPU compositor. Processes render result and output to the render result framebuffer. */
callback(&compositor, compositor.draw_engine);
/* Overlays. Draw on a separate overlay framebuffer. Can read render result. */
callback(&overlay, overlay.draw_engine);
/* Selection. Are always enabled alone and have no interaction with other engines. */
callback(&object_select, object_select.draw_engine);
callback(&edit_select, edit_select.draw_engine);
}
template<typename CallbackT> void foreach_enabled_engine(CallbackT callback)
{
foreach_engine([&](ViewportEngineData *data, DrawEngineType *engine) {
if (!data->used) {
return;
}
callback(data, engine);
});
}
private:
void clear(bool free_instance_data);
};
/* Returns a TextureFromPool stored in the given view data for the pass identified by the given
* pass name. Engines should call this function for each of the passes needed by the viewport
@@ -83,32 +162,11 @@ blender::draw::TextureFromPool &DRW_view_data_pass_texture_get(DRWViewData *view
const char *pass_name);
void DRW_view_data_default_lists_from_viewport(DRWViewData *view_data, GPUViewport *viewport);
void DRW_view_data_texture_list_size_validate(DRWViewData *view_data, const int size[2]);
ViewportEngineData *DRW_view_data_engine_data_get_ensure(DRWViewData *view_data,
DrawEngineType *engine_type);
void DRW_view_data_use_engine(DRWViewData *view_data, DrawEngineType *engine_type);
void DRW_view_data_reset(DRWViewData *view_data);
void DRW_view_data_free_unused(DRWViewData *view_data);
void DRW_view_data_engines_view_update(DRWViewData *view_data);
double *DRW_view_data_cache_time_get(DRWViewData *view_data);
DefaultFramebufferList *DRW_view_data_default_framebuffer_list_get(DRWViewData *view_data);
DefaultTextureList *DRW_view_data_default_texture_list_get(DRWViewData *view_data);
struct DRWEngineIterator {
int id, end;
ViewportEngineData **engines;
};
/* Iterate over used engines of this view_data. */
void DRW_view_data_enabled_engine_iter_begin(DRWEngineIterator *iterator, DRWViewData *view_data);
ViewportEngineData *DRW_view_data_enabled_engine_iter_step(DRWEngineIterator *iterator);
#define DRW_ENABLED_ENGINE_ITER(view_data_, engine_, data_) \
DRWEngineIterator iterator; \
ViewportEngineData *data_; \
DrawEngineType *engine_; \
DRW_view_data_enabled_engine_iter_begin(&iterator, view_data_); \
/* WATCH Comma operator trickery ahead! This tests engine_ == nullptr. */ \
while ((data_ = DRW_view_data_enabled_engine_iter_step(&iterator), \
engine_ = (data_ != nullptr) ? (DrawEngineType *)data_->engine_type->draw_engine : \
nullptr))

View File

@@ -81,9 +81,6 @@ void RE_engines_exit()
void RE_engines_register(RenderEngineType *render_type)
{
if (render_type->draw_engine) {
DRW_engine_register(render_type->draw_engine);
}
BLI_addtail(&R_engines, render_type);
}