diff options
Diffstat (limited to 'source/blender/draw/intern/draw_manager.c')
-rw-r--r-- | source/blender/draw/intern/draw_manager.c | 142 |
1 files changed, 120 insertions, 22 deletions
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index a1e44e479d4..311a223dcdd 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -44,6 +44,7 @@ #include "DNA_camera_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +#include "DNA_world_types.h" #include "ED_space_api.h" #include "ED_screen.h" @@ -696,34 +697,96 @@ void **DRW_view_layer_engine_data_ensure(DrawEngineType *engine_type, void (*cal /* -------------------------------------------------------------------- */ -/** \name Objects (DRW_object) +/** \name Draw Data (DRW_drawdata) * \{ */ -ObjectEngineData *DRW_object_engine_data_get(Object *ob, DrawEngineType *engine_type) +/* Used for DRW_drawdata_from_id() + * All ID-datablocks which have their own 'local' DrawData + * should have the same arrangement in their structs. + */ +typedef struct IdDdtTemplate { + ID id; + struct AnimData *adt; + DrawDataList drawdata; +} IdDdtTemplate; + +/* Check if ID can have AnimData */ +static bool id_type_can_have_drawdata(const short id_type) +{ + /* Only some ID-blocks have this info for now */ + /* TODO: finish adding this for the other blocktypes */ + switch (id_type) { + /* has DrawData */ + case ID_OB: + case ID_WO: + return true; + + /* no DrawData */ + default: + return false; + } +} + +static bool id_can_have_drawdata(const ID *id) +{ + /* sanity check */ + if (id == NULL) + return false; + + return id_type_can_have_drawdata(GS(id->name)); +} + +/* Get DrawData from the given ID-block. In order for this to work, we assume that + * the DrawData pointer is stored in the struct in the same fashion as in IdDdtTemplate. + */ +DrawDataList *DRW_drawdatalist_from_id(ID *id) +{ + /* only some ID-blocks have this info for now, so we cast the + * types that do to be of type IdDdtTemplate, and extract the + * DrawData that way + */ + if (id_can_have_drawdata(id)) { + IdDdtTemplate *idt = (IdDdtTemplate *)id; + return &idt->drawdata; + } + else + return NULL; +} + +DrawData *DRW_drawdata_get(ID *id, DrawEngineType *engine_type) { - for (ObjectEngineData *oed = ob->drawdata.first; oed; oed = oed->next) { - if (oed->engine_type == engine_type) { - return oed; + DrawDataList *drawdata = DRW_drawdatalist_from_id(id); + + if (drawdata == NULL) + return NULL; + + LISTBASE_FOREACH(DrawData *, dd, drawdata) { + if (dd->engine_type == engine_type) { + return dd; } } return NULL; } -ObjectEngineData *DRW_object_engine_data_ensure( - Object *ob, +DrawData *DRW_drawdata_ensure( + ID *id, DrawEngineType *engine_type, size_t size, - ObjectEngineDataInitCb init_cb, - ObjectEngineDataFreeCb free_cb) + DrawDataInitCb init_cb, + DrawDataFreeCb free_cb) { - BLI_assert(size >= sizeof(ObjectEngineData)); + BLI_assert(size >= sizeof(DrawData)); + BLI_assert(id_can_have_drawdata(id)); /* Try to re-use existing data. */ - ObjectEngineData *oed = DRW_object_engine_data_get(ob, engine_type); - if (oed != NULL) { - return oed; + DrawData *dd = DRW_drawdata_get(id, engine_type); + if (dd != NULL) { + return dd; } + + DrawDataList *drawdata = DRW_drawdatalist_from_id(id); + /* Allocate new data. */ - if ((ob->base_flag & BASE_FROMDUPLI) != 0) { + if ((GS(id->name) == ID_OB) && (((Object *)id)->base_flag & BASE_FROMDUPLI) != 0) { /* NOTE: data is not persistent in this case. It is reset each redraw. */ BLI_assert(free_cb == NULL); /* No callback allowed. */ /* Round to sizeof(float) for DRW_instance_data_request(). */ @@ -734,21 +797,37 @@ ObjectEngineData *DRW_object_engine_data_ensure( if (DST.object_instance_data[fsize] == NULL) { DST.object_instance_data[fsize] = DRW_instance_data_request(DST.idatalist, fsize); } - oed = (ObjectEngineData *)DRW_instance_data_next(DST.object_instance_data[fsize]); - memset(oed, 0, size); + dd = (DrawData *)DRW_instance_data_next(DST.object_instance_data[fsize]); + memset(dd, 0, size); } else { - oed = MEM_callocN(size, "ObjectEngineData"); + dd = MEM_callocN(size, "DrawData"); } - oed->engine_type = engine_type; - oed->free = free_cb; + dd->engine_type = engine_type; + dd->free = free_cb; /* Perform user-side initialization, if needed. */ if (init_cb != NULL) { - init_cb(oed); + init_cb(dd); } /* Register in the list. */ - BLI_addtail(&ob->drawdata, oed); - return oed; + BLI_addtail((ListBase *)drawdata, dd); + return dd; +} + +void DRW_drawdata_free(ID *id) +{ + DrawDataList *drawdata = DRW_drawdatalist_from_id(id); + + if (drawdata == NULL) + return; + + LISTBASE_FOREACH(DrawData *, dd, drawdata) { + if (dd->free != NULL) { + dd->free(dd); + } + } + + BLI_freelistN((ListBase *)drawdata); } /** \} */ @@ -794,6 +873,22 @@ static void drw_engines_cache_init(void) } } +static void drw_engines_world_update(Scene *scene) +{ + if (scene->world == NULL) { + return; + } + + for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { + DrawEngineType *engine = link->data; + ViewportEngineData *data = drw_viewport_engine_data_ensure(engine); + + if (engine->id_update) { + engine->id_update(data, &scene->world->id); + } + } +} + static void drw_engines_cache_populate(Object *ob) { DST.ob_state = NULL; @@ -1273,6 +1368,7 @@ void DRW_draw_render_loop_ex( { PROFILE_START(stime); drw_engines_cache_init(); + drw_engines_world_update(scene); const int object_type_exclude_viewport = v3d->object_type_exclude_viewport; DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN(depsgraph, ob) @@ -1697,6 +1793,7 @@ void DRW_draw_select_loop( { drw_engines_cache_init(); + drw_engines_world_update(scene); if (use_obedit) { #if 0 @@ -1891,6 +1988,7 @@ void DRW_draw_depth_loop( { drw_engines_cache_init(); + drw_engines_world_update(scene); const int object_type_exclude_viewport = v3d->object_type_exclude_viewport; DEG_OBJECT_ITER_FOR_RENDER_ENGINE_BEGIN(depsgraph, ob) |