diff options
Diffstat (limited to 'source/blender/draw/intern/draw_manager.c')
-rw-r--r-- | source/blender/draw/intern/draw_manager.c | 382 |
1 files changed, 216 insertions, 166 deletions
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 5ae0351cdd3..45e4c2a575e 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -51,6 +51,8 @@ #include "BKE_pbvh.h" #include "BKE_pointcache.h" #include "BKE_pointcloud.h" +#include "BKE_screen.h" +#include "BKE_subdiv_modifier.h" #include "BKE_volume.h" #include "DNA_camera_types.h" @@ -68,6 +70,7 @@ #include "GPU_framebuffer.h" #include "GPU_immediate.h" #include "GPU_matrix.h" +#include "GPU_shader_shared.h" #include "GPU_state.h" #include "GPU_uniform_buffer.h" #include "GPU_viewport.h" @@ -84,10 +87,12 @@ #include "wm_window.h" #include "draw_color_management.h" +#include "draw_manager.h" #include "draw_manager_profiling.h" #include "draw_manager_testing.h" #include "draw_manager_text.h" #include "draw_shader.h" +#include "draw_subdivision.h" #include "draw_texture_pool.h" /* only for callbacks */ @@ -112,8 +117,10 @@ /** Render State: No persistent data between draw calls. */ DRWManager DST = {NULL}; -static ListBase DRW_engines = {NULL, NULL}; -static int g_registered_engine_len = 0; +static struct { + ListBase /*DRWRegisteredDrawEngine*/ engines; + int len; +} g_registered_engines = {{NULL}}; static void drw_state_prepare_clean_for_draw(DRWManager *dst) { @@ -169,7 +176,8 @@ static void drw_task_graph_deinit(void) { BLI_task_graph_work_and_wait(DST.task_graph); - BLI_gset_free(DST.delayed_extraction, (void (*)(void *key))drw_batch_cache_generate_requested); + BLI_gset_free(DST.delayed_extraction, + (void (*)(void *key))drw_batch_cache_generate_requested_evaluated_mesh); DST.delayed_extraction = NULL; BLI_task_graph_work_and_wait(DST.task_graph); @@ -199,31 +207,12 @@ bool DRW_object_is_renderable(const Object *ob) return true; } -/* Does `ob` needs to be rendered in edit mode. - * - * When using duplicate linked meshes, objects that are not in edit-mode will be drawn as - * it is in edit mode, when another object with the same mesh is in edit mode. - * This will not be the case when one of the objects are influenced by modifiers. */ bool DRW_object_is_in_edit_mode(const Object *ob) { if (BKE_object_is_in_editmode(ob)) { if (ob->type == OB_MESH) { if ((ob->mode & OB_MODE_EDIT) == 0) { - Mesh *me = (Mesh *)ob->data; - BMEditMesh *embm = me->edit_mesh; - /* Sanity check when rendering in multiple windows. */ - if (embm && embm->mesh_eval_final == NULL) { - return false; - } - /* Do not draw ob with edit overlay when edit data is present and is modified. */ - if (embm && embm->mesh_eval_cage && (embm->mesh_eval_cage != embm->mesh_eval_final)) { - return false; - } - /* Check if the object that we are drawing is modified. */ - if (!DEG_is_original_id(&me->id)) { - return false; - } - return true; + return false; } } return true; @@ -231,10 +220,6 @@ bool DRW_object_is_in_edit_mode(const Object *ob) return false; } -/** - * Return whether this object is visible depending if - * we are rendering or drawing in the viewport. - */ int DRW_object_visibility_in_active_context(const Object *ob) { const eEvaluationMode mode = DRW_state_is_scene_render() ? DAG_EVAL_RENDER : DAG_EVAL_VIEWPORT; @@ -317,7 +302,6 @@ struct DupliObject *DRW_object_get_dupli(const Object *UNUSED(ob)) /** \name Viewport (DRW_viewport) * \{ */ -/* WARNING: only use for custom pipeline. 99% of the time, you don't want to use this. */ void DRW_render_viewport_size_set(const int size[2]) { DST.size[0] = size[0]; @@ -439,7 +423,7 @@ DRWData *DRW_viewport_data_create(void) } for (int i = 0; i < 2; i++) { - drw_data->view_data[i] = DRW_view_data_create(&DRW_engines); + drw_data->view_data[i] = DRW_view_data_create(&g_registered_engines.engines); } return drw_data; } @@ -561,8 +545,9 @@ static void drw_manager_init(DRWManager *dst, GPUViewport *viewport, const int s drw_viewport_data_reset(dst->vmempool); + bool do_validation = true; if (size == NULL && viewport == NULL) { - /* Avoid division by 0. Engines will either overide this or not use it. */ + /* Avoid division by 0. Engines will either override this or not use it. */ dst->size[0] = 1.0f; dst->size[1] = 1.0f; } @@ -576,11 +561,15 @@ static void drw_manager_init(DRWManager *dst, GPUViewport *viewport, const int s BLI_assert(size); dst->size[0] = size[0]; dst->size[1] = size[1]; + /* Fix case when used in DRW_cache_restart(). */ + do_validation = false; } dst->inv_size[0] = 1.0f / dst->size[0]; dst->inv_size[1] = 1.0f / dst->size[1]; - DRW_view_data_texture_list_size_validate(dst->view_data_active, (int[2]){UNPACK2(dst->size)}); + if (do_validation) { + DRW_view_data_texture_list_size_validate(dst->view_data_active, (int[2]){UNPACK2(dst->size)}); + } if (viewport) { DRW_view_data_default_lists_from_viewport(dst->view_data_active, viewport); @@ -726,7 +715,7 @@ static void drw_duplidata_load(Object *ob) void **value; if (!BLI_ghash_ensure_p(DST.dupli_ghash, key, &value)) { - *value = MEM_callocN(sizeof(void *) * g_registered_engine_len, __func__); + *value = MEM_callocN(sizeof(void *) * g_registered_engines.len, __func__); /* TODO: Meh a bit out of place but this is nice as it is * only done once per instance type. */ @@ -741,7 +730,7 @@ static void drw_duplidata_load(Object *ob) static void duplidata_value_free(void *val) { void **dupli_datas = val; - for (int i = 0; i < g_registered_engine_len; i++) { + for (int i = 0; i < g_registered_engines.len; i++) { MEM_SAFE_FREE(dupli_datas[i]); } MEM_freeN(val); @@ -755,8 +744,11 @@ static void duplidata_key_free(void *key) } else { Object temp_object = *dupli_key->ob; + /* Do not modify the original bound-box. */ + temp_object.runtime.bb = NULL; BKE_object_replace_data_on_shallow_copy(&temp_object, dupli_key->ob_data); drw_batch_cache_generate_requested(&temp_object); + MEM_SAFE_FREE(temp_object.runtime.bb); } MEM_freeN(key); } @@ -769,14 +761,13 @@ static void drw_duplidata_free(void) } } -/* Return NULL if not a dupli or a pointer of pointer to the engine data */ void **DRW_duplidata_get(void *vedata) { if (DST.dupli_source == NULL) { return NULL; } ViewportEngineData *ved = (ViewportEngineData *)vedata; - DrawEngineType *engine_type = (DrawEngineType *)ved->engine_type; + DRWRegisteredDrawEngine *engine_type = (DRWRegisteredDrawEngine *)ved->engine_type; return &DST.dupli_datas[engine_type->index]; } @@ -865,9 +856,6 @@ static bool id_can_have_drawdata(const ID *id) 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 @@ -1139,7 +1127,6 @@ static void drw_engines_draw_text(void) } } -/* Draw render engine info. */ void DRW_draw_region_engine_info(int xoffset, int *yoffset, int line_height) { DRW_ENABLED_ENGINE_ITER (DST.view_data_active, engine, data) { @@ -1332,7 +1319,7 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx) .object_mode = OB_MODE_OBJECT, }; - /* Custom lightweight init to avoid reseting the mempools. */ + /* Custom lightweight initialize to avoid resetting the memory-pools. */ DST.viewport = viewport; DST.vmempool = drw_viewport_data_ensure(DST.viewport); @@ -1358,6 +1345,61 @@ void DRW_notify_view_update(const DRWUpdateContext *update_ctx) BLI_ticket_mutex_unlock(DST.gl_context_mutex); } +/* update a viewport which belongs to a GPUOffscreen */ +static void drw_notify_view_update_offscreen(struct Depsgraph *depsgraph, + RenderEngineType *engine_type, + ARegion *region, + View3D *v3d, + GPUViewport *viewport) +{ + + if (viewport && GPU_viewport_do_update(viewport)) { + + Scene *scene = DEG_get_evaluated_scene(depsgraph); + ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); + RegionView3D *rv3d = region->regiondata; + + const bool gpencil_engine_needed = drw_gpencil_engine_needed(depsgraph, v3d); + + /* Reset before using it. */ + drw_state_prepare_clean_for_draw(&DST); + + DST.draw_ctx = (DRWContextState){ + .region = region, + .rv3d = rv3d, + .v3d = v3d, + .scene = scene, + .view_layer = view_layer, + .obact = OBACT(view_layer), + .engine_type = engine_type, + .depsgraph = depsgraph, + }; + + /* Custom lightweight initialize to avoid resetting the memory-pools. */ + DST.viewport = viewport; + DST.vmempool = drw_viewport_data_ensure(DST.viewport); + + /* Separate update for each stereo view. */ + int view_count = GPU_viewport_is_stereo_get(viewport) ? 2 : 1; + for (int view = 0; view < view_count; view++) { + DST.view_data_active = DST.vmempool->view_data[view]; + + drw_engines_enable(view_layer, engine_type, gpencil_engine_needed); + drw_engines_data_validate(); + + DRW_ENABLED_ENGINE_ITER (DST.view_data_active, draw_engine, data) { + if (draw_engine->view_update) { + draw_engine->view_update(data); + } + } + + drw_engines_disable(); + } + + drw_manager_exit(&DST); + } +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -1415,6 +1457,27 @@ void DRW_draw_callbacks_post_scene(void) ED_region_draw_cb_draw(DST.draw_ctx.evil_C, DST.draw_ctx.region, REGION_DRAW_POST_VIEW); +#ifdef WITH_XR_OPENXR + /* XR callbacks (controllers, custom draw functions) for session mirror. */ + if ((v3d->flag & V3D_XR_SESSION_MIRROR) != 0) { + if ((v3d->flag2 & V3D_XR_SHOW_CONTROLLERS) != 0) { + ARegionType *art = WM_xr_surface_controller_region_type_get(); + if (art) { + ED_region_surface_draw_cb_draw(art, REGION_DRAW_POST_VIEW); + } + } + if ((v3d->flag2 & V3D_XR_SHOW_CUSTOM_OVERLAYS) != 0) { + SpaceType *st = BKE_spacetype_from_id(SPACE_VIEW3D); + if (st) { + ARegionType *art = BKE_regiontype_from_id(st, RGN_TYPE_XR); + if (art) { + ED_region_surface_draw_cb_draw(art, REGION_DRAW_POST_VIEW); + } + } + } + } +#endif + /* Callback can be nasty and do whatever they want with the state. * Don't trust them! */ DRW_state_reset(); @@ -1461,6 +1524,46 @@ void DRW_draw_callbacks_post_scene(void) ED_annotation_draw_view3d(DEG_get_input_scene(depsgraph), depsgraph, v3d, region, true); GPU_depth_test(GPU_DEPTH_LESS_EQUAL); } + +#ifdef WITH_XR_OPENXR + if ((v3d->flag & V3D_XR_SESSION_SURFACE) != 0) { + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + + DRW_state_reset(); + + GPU_framebuffer_bind(dfbl->overlay_fb); + + GPU_matrix_projection_set(rv3d->winmat); + GPU_matrix_set(rv3d->viewmat); + + /* XR callbacks (controllers, custom draw functions) for session surface. */ + if (((v3d->flag2 & V3D_XR_SHOW_CONTROLLERS) != 0) || + ((v3d->flag2 & V3D_XR_SHOW_CUSTOM_OVERLAYS) != 0)) { + GPU_depth_test(GPU_DEPTH_NONE); + GPU_apply_state(); + + if ((v3d->flag2 & V3D_XR_SHOW_CONTROLLERS) != 0) { + ARegionType *art = WM_xr_surface_controller_region_type_get(); + if (art) { + ED_region_surface_draw_cb_draw(art, REGION_DRAW_POST_VIEW); + } + } + if ((v3d->flag2 & V3D_XR_SHOW_CUSTOM_OVERLAYS) != 0) { + SpaceType *st = BKE_spacetype_from_id(SPACE_VIEW3D); + if (st) { + ARegionType *art = BKE_regiontype_from_id(st, RGN_TYPE_XR); + if (art) { + ED_region_surface_draw_cb_draw(art, REGION_DRAW_POST_VIEW); + } + } + } + + DRW_state_reset(); + } + + GPU_depth_test(GPU_DEPTH_LESS_EQUAL); + } +#endif } } @@ -1479,9 +1582,6 @@ struct DRWTextStore *DRW_text_cache_ensure(void) /** \name Main Draw Loops (DRW_draw) * \{ */ -/* Everything starts here. - * This function takes care of calling all cache and rendering functions - * for each relevant engine / mode engine. */ void DRW_draw_view(const bContext *C) { View3D *v3d = CTX_wm_view3d(C); @@ -1509,10 +1609,6 @@ void DRW_draw_view(const bContext *C) } } -/** - * Used for both regular and off-screen drawing. - * Need to reset DST before calling this function - */ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph, RenderEngineType *engine_type, ARegion *region, @@ -1659,9 +1755,6 @@ void DRW_draw_render_loop(struct Depsgraph *depsgraph, DRW_draw_render_loop_ex(depsgraph, engine_type, region, v3d, viewport, NULL); } -/** - * \param viewport: can be NULL, in this case we create one. - */ void DRW_draw_render_loop_offscreen(struct Depsgraph *depsgraph, RenderEngineType *engine_type, ARegion *region, @@ -1672,11 +1765,14 @@ void DRW_draw_render_loop_offscreen(struct Depsgraph *depsgraph, GPUOffScreen *ofs, GPUViewport *viewport) { - /* Create temporary viewport if needed. */ + /* Create temporary viewport if needed or update the existing viewport. */ GPUViewport *render_viewport = viewport; if (viewport == NULL) { render_viewport = GPU_viewport_create(); } + else { + drw_notify_view_update_offscreen(depsgraph, engine_type, region, v3d, render_viewport); + } GPU_viewport_bind_from_offscreen(render_viewport, ofs); @@ -1690,12 +1786,12 @@ void DRW_draw_render_loop_offscreen(struct Depsgraph *depsgraph, DRW_draw_render_loop_ex(depsgraph, engine_type, region, v3d, render_viewport, NULL); if (draw_background) { - /* HACK(fclem): In this case we need to make sure the final alpha is 1. + /* HACK(@fclem): In this case we need to make sure the final alpha is 1. * We use the blend mode to ensure that. A better way to fix that would * be to do that in the color-management shader. */ GPU_offscreen_bind(ofs, false); GPU_clear_color(0.0f, 0.0f, 0.0f, 1.0f); - /* Premult Alpha over black background. */ + /* Pre-multiply alpha over black background. */ GPU_blend(GPU_BLEND_ALPHA_PREMULT); } @@ -1720,7 +1816,6 @@ void DRW_draw_render_loop_offscreen(struct Depsgraph *depsgraph, } } -/* Helper to check if exit object type to render. */ bool DRW_render_check_grease_pencil(Depsgraph *depsgraph) { if (!drw_gpencil_engine_needed(depsgraph, NULL)) { @@ -1949,9 +2044,6 @@ void DRW_render_object_iter( drw_task_graph_deinit(); } -/* Assume a valid gl context is bound (and that the gl_context_mutex has been acquired). - * This function only setup DST and execute the given function. - * Warning: similar to DRW_render_to_image you cannot use default lists (dfbl & dtxl). */ void DRW_custom_pipeline(DrawEngineType *draw_engine_type, struct Depsgraph *depsgraph, void (*callback)(void *vedata, void *user_data), @@ -1997,8 +2089,6 @@ void DRW_custom_pipeline(DrawEngineType *draw_engine_type, drw_manager_exit(&DST); } -/* Used when the render engine want to redo another cache populate inside the same render frame. - */ void DRW_cache_restart(void) { drw_manager_init(&DST, DST.viewport, (int[2]){UNPACK2(DST.size)}); @@ -2189,7 +2279,6 @@ static void draw_select_framebuffer_depth_only_setup(const int size[2]) } } -/* Must run after all instance datas have been added. */ void DRW_render_instance_buffer_finish(void) { BLI_assert_msg(!DST.buffer_finish_called, "DRW_render_instance_buffer_finish called twice!"); @@ -2198,7 +2287,6 @@ void DRW_render_instance_buffer_finish(void) drw_resource_buffer_finish(DST.vmempool); } -/* WARNING: Changing frame might free the ViewLayerEngineData */ void DRW_render_set_time(RenderEngine *engine, Depsgraph *depsgraph, int frame, float subframe) { RE_engine_frame_set(engine, frame, subframe); @@ -2206,9 +2294,6 @@ void DRW_render_set_time(RenderEngine *engine, Depsgraph *depsgraph, int frame, DST.draw_ctx.view_layer = DEG_get_evaluated_view_layer(depsgraph); } -/** - * object mode select-loop, see: ED_view3d_draw_select_loop (legacy drawing). - */ void DRW_draw_select_loop(struct Depsgraph *depsgraph, ARegion *region, View3D *v3d, @@ -2437,16 +2522,17 @@ static void drw_draw_depth_loop_impl(struct Depsgraph *depsgraph, ARegion *region, View3D *v3d, GPUViewport *viewport, - const bool use_opengl_context) + const bool use_gpencil, + const bool use_basic, + const bool use_overlay) { Scene *scene = DEG_get_evaluated_scene(depsgraph); RenderEngineType *engine_type = ED_view3d_engine_type(scene, v3d->shading.type); ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); RegionView3D *rv3d = region->regiondata; - if (use_opengl_context) { - DRW_opengl_context_enable(); - } + /* Reset before using it. */ + drw_state_prepare_clean_for_draw(&DST); DST.options.is_depth = true; @@ -2462,6 +2548,18 @@ static void drw_draw_depth_loop_impl(struct Depsgraph *depsgraph, .depsgraph = depsgraph, }; drw_context_state_init(); + drw_manager_init(&DST, viewport, NULL); + + if (use_gpencil) { + use_drw_engine(&draw_engine_gpencil_type); + } + if (use_basic) { + drw_engines_enable_basic(); + } + if (use_overlay) { + drw_engines_enable_overlays(); + } + drw_task_graph_init(); /* Setup frame-buffer. */ @@ -2529,62 +2627,23 @@ static void drw_draw_depth_loop_impl(struct Depsgraph *depsgraph, drw_engines_disable(); drw_manager_exit(&DST); - - /* Changing context. */ - if (use_opengl_context) { - DRW_opengl_context_disable(); - } } -/** - * object mode select-loop, see: ED_view3d_draw_depth_loop (legacy drawing). - */ void DRW_draw_depth_loop(struct Depsgraph *depsgraph, ARegion *region, View3D *v3d, GPUViewport *viewport) { - /* Reset before using it. */ - drw_state_prepare_clean_for_draw(&DST); - - /* Required by `drw_manager_init()` */ - DST.draw_ctx.region = region; - DST.draw_ctx.rv3d = region->regiondata; - drw_manager_init(&DST, viewport, NULL); - - /* Get list of enabled engines */ - { - /* Required by `DRW_state_draw_support()` */ - DST.draw_ctx.v3d = v3d; - - drw_engines_enable_basic(); - if (DRW_state_draw_support()) { - drw_engines_enable_overlays(); - } - } - - drw_draw_depth_loop_impl(depsgraph, region, v3d, viewport, false); + drw_draw_depth_loop_impl( + depsgraph, region, v3d, viewport, false, true, DRW_state_draw_support()); } -/** - * Converted from ED_view3d_draw_depth_gpencil (legacy drawing). - */ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph, ARegion *region, View3D *v3d, GPUViewport *viewport) { - /* Reset before using it. */ - drw_state_prepare_clean_for_draw(&DST); - - /* Required by `drw_manager_init()` */ - DST.draw_ctx.region = region; - DST.draw_ctx.rv3d = region->regiondata; - drw_manager_init(&DST, viewport, NULL); - - use_drw_engine(&draw_engine_gpencil_type); - - drw_draw_depth_loop_impl(depsgraph, region, v3d, viewport, false); + drw_draw_depth_loop_impl(depsgraph, region, v3d, viewport, true, false, false); } void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, const rcti *rect) @@ -2661,9 +2720,6 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, cons drw_manager_exit(&DST); } -/** - * Clears the Depth Buffer and draws only the specified object. - */ void DRW_draw_depth_object( Scene *scene, ARegion *region, View3D *v3d, GPUViewport *viewport, Object *object) { @@ -2687,11 +2743,15 @@ void DRW_draw_depth_object( GPU_framebuffer_clear_depth(depth_fb, 1.0f); GPU_depth_test(GPU_DEPTH_LESS_EQUAL); - const float(*world_clip_planes)[4] = NULL; - if (RV3D_CLIPPING_ENABLED(v3d, rv3d)) { + struct GPUClipPlanes planes; + const bool use_clipping_planes = RV3D_CLIPPING_ENABLED(v3d, rv3d); + if (use_clipping_planes) { GPU_clip_distances(6); ED_view3d_clipping_local(rv3d, object->obmat); - world_clip_planes = rv3d->clip_local; + for (int i = 0; i < 6; i++) { + copy_v4_v4(planes.world[i], rv3d->clip_local[i]); + } + copy_m4_m4(planes.ModelMatrix, object->obmat); } drw_batch_cache_validate(object); @@ -2713,14 +2773,19 @@ void DRW_draw_depth_object( BLI_task_graph_work_and_wait(task_graph); BLI_task_graph_free(task_graph); - const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED : - GPU_SHADER_CFG_DEFAULT; + const eGPUShaderConfig sh_cfg = use_clipping_planes ? GPU_SHADER_CFG_CLIPPED : + GPU_SHADER_CFG_DEFAULT; GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_DEPTH_ONLY, sh_cfg); - if (world_clip_planes != NULL) { - GPU_batch_uniform_4fv_array(batch, "WorldClipPlanes", 6, world_clip_planes); + + GPUUniformBuf *ubo = NULL; + if (use_clipping_planes) { + ubo = GPU_uniformbuf_create_ex(sizeof(struct GPUClipPlanes), &planes, __func__); + GPU_batch_uniformbuf_bind(batch, "clipPlanes", ubo); } GPU_batch_draw(batch); + GPU_uniformbuf_free(ubo); + } break; case OB_CURVE: case OB_SURF: @@ -2736,7 +2801,6 @@ void DRW_draw_depth_object( GPU_framebuffer_restore(); GPU_framebuffer_free(depth_fb); - DRW_opengl_context_disable(); } /** \} */ @@ -2745,19 +2809,12 @@ void DRW_draw_depth_object( /** \name Draw Manager State (DRW_state) * \{ */ -/** - * When false, drawing doesn't output to a pixel buffer - * eg: Occlusion queries, or when we have setup a context to draw in already. - */ bool DRW_state_is_fbo(void) { return ((DST.default_framebuffer != NULL) || DST.options.is_image_render) && !DRW_state_is_depth() && !DRW_state_is_select(); } -/** - * For when engines need to know if this is drawing for selection or not. - */ bool DRW_state_is_select(void) { return DST.options.is_select; @@ -2773,27 +2830,17 @@ bool DRW_state_is_depth(void) return DST.options.is_depth; } -/** - * Whether we are rendering for an image - */ bool DRW_state_is_image_render(void) { return DST.options.is_image_render; } -/** - * Whether we are rendering only the render engine, - * or if we should also render the mode engines. - */ bool DRW_state_is_scene_render(void) { BLI_assert(DST.options.is_scene_render ? DST.options.is_image_render : true); return DST.options.is_scene_render; } -/** - * Whether we are rendering simple opengl render - */ bool DRW_state_is_opengl_render(void) { return DST.options.is_image_render && !DST.options.is_scene_render; @@ -2808,28 +2855,18 @@ bool DRW_state_is_playback(void) return false; } -/** - * Is the user navigating the region. - */ bool DRW_state_is_navigating(void) { const RegionView3D *rv3d = DST.draw_ctx.rv3d; return (rv3d) && (rv3d->rflag & (RV3D_NAVIGATING | RV3D_PAINTING)); } -/** - * Should text draw in this mode? - */ bool DRW_state_show_text(void) { return (DST.options.is_select) == 0 && (DST.options.is_depth) == 0 && (DST.options.is_scene_render) == 0 && (DST.options.draw_text) == 0; } -/** - * Should draw support elements - * Objects center, selection outline, probe data, ... - */ bool DRW_state_draw_support(void) { View3D *v3d = DST.draw_ctx.v3d; @@ -2837,9 +2874,6 @@ bool DRW_state_draw_support(void) ((v3d->flag2 & V3D_HIDE_OVERLAYS) == 0); } -/** - * Whether we should render the background - */ bool DRW_state_draw_background(void) { return DST.options.draw_background; @@ -2869,9 +2903,12 @@ bool DRW_engine_render_support(DrawEngineType *draw_engine_type) void DRW_engine_register(DrawEngineType *draw_engine_type) { - BLI_addtail(&DRW_engines, draw_engine_type); - g_registered_engine_len = BLI_listbase_count(&DRW_engines); - draw_engine_type->index = g_registered_engine_len - 1; + DRWRegisteredDrawEngine *draw_engine = 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(void) @@ -2919,11 +2956,32 @@ void DRW_engines_register(void) BKE_volume_batch_cache_dirty_tag_cb = DRW_volume_batch_cache_dirty_tag; BKE_volume_batch_cache_free_cb = DRW_volume_batch_cache_free; + + BKE_subsurf_modifier_free_gpu_cache_cb = DRW_subdiv_cache_free; } } +static void drw_registered_engines_free(void) +{ + DRWRegisteredDrawEngine *next; + for (DRWRegisteredDrawEngine *type = g_registered_engines.engines.first; type; type = next) { + next = 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(void) { + drw_registered_engines_free(); + if (DST.gl_context == NULL) { /* Nothing has been setup. Nothing to clear. * Otherwise, DRW_opengl_context_enable can @@ -2942,16 +3000,6 @@ void DRW_engines_free(void) DRW_stats_free(); DRW_globals_free(); - DrawEngineType *next; - for (DrawEngineType *type = DRW_engines.first; type; type = next) { - next = type->next; - BLI_remlink(&R_engines, type); - - if (type->engine_free) { - type->engine_free(); - } - } - DRW_UBO_FREE_SAFE(G_draw.block_ubo); DRW_UBO_FREE_SAFE(G_draw.view_ubo); DRW_TEXTURE_FREE_SAFE(G_draw.ramp); @@ -3079,6 +3127,8 @@ void DRW_opengl_context_disable_ex(bool restore) void DRW_opengl_context_enable(void) { + /* TODO: should be replace by a more elegant alternative. */ + if (G.background && DST.gl_context == NULL) { WM_init_opengl(); } @@ -3107,7 +3157,6 @@ void DRW_opengl_render_context_disable(void *re_gl_context) BLI_ticket_mutex_unlock(DST.gl_context_mutex); } -/* Needs to be called AFTER DRW_opengl_render_context_enable() */ void DRW_gpu_render_context_enable(void *re_gpu_context) { /* If thread is main you should use DRW_opengl_context_enable(). */ @@ -3116,7 +3165,6 @@ void DRW_gpu_render_context_enable(void *re_gpu_context) GPU_context_active_set(re_gpu_context); } -/* Needs to be called BEFORE DRW_opengl_render_context_disable() */ void DRW_gpu_render_context_disable(void *UNUSED(re_gpu_context)) { GPU_flush(); @@ -3161,6 +3209,8 @@ void DRW_xr_drawing_end(void) #endif +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Internal testing API for gtests * \{ */ |