diff options
author | reduz <reduzio@gmail.com> | 2021-06-15 17:33:24 -0300 |
---|---|---|
committer | reduz <reduzio@gmail.com> | 2021-06-16 10:48:57 -0300 |
commit | 38d164c74b24f10215312f304ec1b04175989376 (patch) | |
tree | ce2c76d08a3bbc7dfe33994ce3d1b17b9ef03819 /servers | |
parent | badad5343814cb68ec19646067078f241a74071a (diff) |
Refactor VisibilityNotifier
* Works from RenderinServer
* Accurately tells when on or off-scren, its no longer approximate.
* VisibilityEnabler also simplified to use the process mode instead.
Diffstat (limited to 'servers')
-rw-r--r-- | servers/rendering/renderer_canvas_cull.cpp | 125 | ||||
-rw-r--r-- | servers/rendering/renderer_canvas_cull.h | 24 | ||||
-rw-r--r-- | servers/rendering/rendering_server_default.cpp | 3 | ||||
-rw-r--r-- | servers/rendering/rendering_server_default.h | 2 | ||||
-rw-r--r-- | servers/rendering/rendering_server_globals.cpp | 2 | ||||
-rw-r--r-- | servers/rendering/rendering_server_globals.h | 2 | ||||
-rw-r--r-- | servers/rendering_server.h | 2 |
7 files changed, 138 insertions, 22 deletions
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index 6e126ea77e..5703737252 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -104,7 +104,7 @@ void _mark_ysort_dirty(RendererCanvasCull::Item *ysort_owner, RID_PtrOwner<Rende } while (ysort_owner && ysort_owner->sort_y); } -void _attach_canvas_item_for_draw(RendererCanvasCull::Item *ci, RendererCanvasCull::Item *p_canvas_clip, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **z_last_list, const Transform2D &xform, const Rect2 &p_clip_rect, Rect2 global_rect, const Color &modulate, int p_z, RendererCanvasCull::Item *p_material_owner, bool use_canvas_group, RendererCanvasRender::Item *canvas_group_from) { +void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item *ci, RendererCanvasCull::Item *p_canvas_clip, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **z_last_list, const Transform2D &xform, const Rect2 &p_clip_rect, Rect2 global_rect, const Color &modulate, int p_z, RendererCanvasCull::Item *p_material_owner, bool use_canvas_group, RendererCanvasRender::Item *canvas_group_from, const Transform2D &p_xform) { if (ci->copy_back_buffer) { ci->copy_back_buffer->screen_rect = xform.xform(ci->copy_back_buffer->rect).intersection(p_clip_rect); } @@ -173,32 +173,44 @@ void _attach_canvas_item_for_draw(RendererCanvasCull::Item *ci, RendererCanvasCu } } - if (ci->update_when_visible) { - RenderingServerDefault::redraw_request(); - } - - if ((ci->commands != nullptr && p_clip_rect.intersects(global_rect, true)) || ci->vp_render || ci->copy_back_buffer) { + if (((ci->commands != nullptr || ci->visibility_notifier) && p_clip_rect.intersects(global_rect, true)) || ci->vp_render || ci->copy_back_buffer) { //something to draw? - ci->final_transform = xform; - ci->final_modulate = Color(modulate.r * ci->self_modulate.r, modulate.g * ci->self_modulate.g, modulate.b * ci->self_modulate.b, modulate.a * ci->self_modulate.a); - ci->global_rect_cache = global_rect; - ci->global_rect_cache.position -= p_clip_rect.position; - ci->light_masked = false; - int zidx = p_z - RS::CANVAS_ITEM_Z_MIN; + if (ci->update_when_visible) { + RenderingServerDefault::redraw_request(); + } - if (z_last_list[zidx]) { - z_last_list[zidx]->next = ci; - z_last_list[zidx] = ci; + if (ci->commands != nullptr) { + ci->final_transform = xform; + ci->final_modulate = Color(modulate.r * ci->self_modulate.r, modulate.g * ci->self_modulate.g, modulate.b * ci->self_modulate.b, modulate.a * ci->self_modulate.a); + ci->global_rect_cache = global_rect; + ci->global_rect_cache.position -= p_clip_rect.position; + ci->light_masked = false; - } else { - z_list[zidx] = ci; - z_last_list[zidx] = ci; + int zidx = p_z - RS::CANVAS_ITEM_Z_MIN; + + if (z_last_list[zidx]) { + z_last_list[zidx]->next = ci; + z_last_list[zidx] = ci; + + } else { + z_list[zidx] = ci; + z_last_list[zidx] = ci; + } + + ci->z_final = p_z; + + ci->next = nullptr; } - ci->z_final = p_z; + if (ci->visibility_notifier) { + if (!ci->visibility_notifier->visible_element.in_list()) { + visibility_notifier_list.add(&ci->visibility_notifier->visible_element); + ci->visibility_notifier->just_visible = true; + } - ci->next = nullptr; + ci->visibility_notifier->visible_in_frame = RSG::rasterizer->get_frame_number(); + } } } @@ -215,6 +227,13 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 } Rect2 rect = ci->get_rect(); + + if (ci->visibility_notifier) { + if (ci->visibility_notifier->area.size != Vector2()) { + rect = rect.merge(ci->visibility_notifier->area); + } + } + Transform2D xform = ci->xform; if (snapping_2d_transforms_to_pixel) { xform.elements[2] = xform.elements[2].floor(); @@ -289,7 +308,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 canvas_group_from = z_last_list[zidx]; } - _attach_canvas_item_for_draw(ci, p_canvas_clip, z_list, z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from); + _attach_canvas_item_for_draw(ci, p_canvas_clip, z_list, z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from, xform); } } else { RendererCanvasRender::Item *canvas_group_from = nullptr; @@ -305,7 +324,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 } _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true); } - _attach_canvas_item_for_draw(ci, p_canvas_clip, z_list, z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from); + _attach_canvas_item_for_draw(ci, p_canvas_clip, z_list, z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from, xform); for (int i = 0; i < child_item_count; i++) { if (child_items[i]->behind || use_canvas_group) { continue; @@ -1095,6 +1114,26 @@ void RendererCanvasCull::canvas_item_set_use_parent_material(RID p_item, bool p_ canvas_item->use_parent_material = p_enable; } +void RendererCanvasCull::canvas_item_set_visibility_notifier(RID p_item, bool p_enable, const Rect2 &p_area, const Callable &p_enter_callable, const Callable &p_exit_callable) { + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + if (p_enable) { + if (!canvas_item->visibility_notifier) { + canvas_item->visibility_notifier = visibility_notifier_allocator.alloc(); + } + canvas_item->visibility_notifier->area = p_area; + canvas_item->visibility_notifier->enter_callable = p_enter_callable; + canvas_item->visibility_notifier->exit_callable = p_exit_callable; + + } else { + if (canvas_item->visibility_notifier) { + visibility_notifier_allocator.free(canvas_item->visibility_notifier); + canvas_item->visibility_notifier = nullptr; + } + } +} + void RendererCanvasCull::canvas_item_set_canvas_group_mode(RID p_item, RS::CanvasGroupMode p_mode, float p_clear_margin, bool p_fit_empty, float p_fit_margin, bool p_blur_mipmaps) { Item *canvas_item = canvas_item_owner.getornull(p_item); ERR_FAIL_COND(!canvas_item); @@ -1477,6 +1516,44 @@ void RendererCanvasCull::canvas_item_set_default_texture_repeat(RID p_item, RS:: ci->texture_repeat = p_repeat; } +void RendererCanvasCull::update_visibility_notifiers() { + SelfList<Item::VisibilityNotifierData> *E = visibility_notifier_list.first(); + while (E) { + SelfList<Item::VisibilityNotifierData> *N = E->next(); + + Item::VisibilityNotifierData *visibility_notifier = E->self(); + if (visibility_notifier->just_visible) { + visibility_notifier->just_visible = false; + + if (!visibility_notifier->enter_callable.is_null()) { + if (RSG::threaded) { + visibility_notifier->enter_callable.call_deferred(nullptr, 0); + } else { + Callable::CallError ce; + Variant ret; + visibility_notifier->enter_callable.call(nullptr, 0, ret, ce); + } + } + } else { + if (visibility_notifier->visible_in_frame != RSG::rasterizer->get_frame_number()) { + visibility_notifier_list.remove(E); + + if (!visibility_notifier->exit_callable.is_null()) { + if (RSG::threaded) { + visibility_notifier->exit_callable.call_deferred(nullptr, 0); + } else { + Callable::CallError ce; + Variant ret; + visibility_notifier->exit_callable.call(nullptr, 0, ret, ce); + } + } + } + } + + E = N; + } +} + bool RendererCanvasCull::free(RID p_rid) { if (canvas_owner.owns(p_rid)) { Canvas *canvas = canvas_owner.getornull(p_rid); @@ -1531,6 +1608,10 @@ bool RendererCanvasCull::free(RID p_rid) { canvas_item->child_items[i]->parent = RID(); } + if (canvas_item->visibility_notifier != nullptr) { + visibility_notifier_allocator.free(canvas_item->visibility_notifier); + } + /* if (canvas_item->material) { canvas_item->material->owners.erase(canvas_item); diff --git a/servers/rendering/renderer_canvas_cull.h b/servers/rendering/renderer_canvas_cull.h index 37391d7c0e..661216cad3 100644 --- a/servers/rendering/renderer_canvas_cull.h +++ b/servers/rendering/renderer_canvas_cull.h @@ -31,6 +31,7 @@ #ifndef RENDERING_SERVER_CANVAS_CULL_H #define RENDERING_SERVER_CANVAS_CULL_H +#include "core/templates/paged_allocator.h" #include "renderer_compositor.h" #include "renderer_viewport.h" @@ -55,6 +56,20 @@ public: Vector<Item *> child_items; + struct VisibilityNotifierData { + Rect2 area; + Callable enter_callable; + Callable exit_callable; + bool just_visible = false; + uint64_t visible_in_frame = 0; + SelfList<VisibilityNotifierData> visible_element; + VisibilityNotifierData() : + visible_element(this) { + } + }; + + VisibilityNotifierData *visibility_notifier = nullptr; + Item() { children_order_dirty = true; E = nullptr; @@ -156,6 +171,11 @@ public: bool sdf_used = false; bool snapping_2d_transforms_to_pixel = false; + PagedAllocator<Item::VisibilityNotifierData> visibility_notifier_allocator; + SelfList<Item::VisibilityNotifierData>::List visibility_notifier_list; + + _FORCE_INLINE_ void _attach_canvas_item_for_draw(Item *ci, Item *p_canvas_clip, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **z_last_list, const Transform2D &xform, const Rect2 &p_clip_rect, Rect2 global_rect, const Color &modulate, int p_z, RendererCanvasCull::Item *p_material_owner, bool use_canvas_group, RendererCanvasRender::Item *canvas_group_from, const Transform2D &p_xform); + private: void _render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RendererCanvasRender::Light *p_lights, RendererCanvasRender::Light *p_directional_lights, RS::CanvasItemTextureFilter p_default_filter, RS::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel); void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RendererCanvasRender::Item **z_list, RendererCanvasRender::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool allow_y_sort); @@ -224,6 +244,8 @@ public: void canvas_item_set_use_parent_material(RID p_item, bool p_enable); + void canvas_item_set_visibility_notifier(RID p_item, bool p_enable, const Rect2 &p_area, const Callable &p_enter_callable, const Callable &p_exit_callable); + void canvas_item_set_canvas_group_mode(RID p_item, RS::CanvasGroupMode p_mode, float p_clear_margin = 5.0, bool p_fit_empty = false, float p_fit_margin = 0.0, bool p_blur_mipmaps = false); RID canvas_light_allocate(); @@ -283,6 +305,8 @@ public: void canvas_item_set_default_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter); void canvas_item_set_default_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat); + void update_visibility_notifiers(); + bool free(RID p_rid); RendererCanvasCull(); ~RendererCanvasCull(); diff --git a/servers/rendering/rendering_server_default.cpp b/servers/rendering/rendering_server_default.cpp index cd66cd0716..95aa05f6b3 100644 --- a/servers/rendering/rendering_server_default.cpp +++ b/servers/rendering/rendering_server_default.cpp @@ -117,6 +117,8 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) { _draw_margins(); RSG::rasterizer->end_frame(p_swap_buffers); + RSG::canvas->update_visibility_notifiers(); + while (frame_drawn_callbacks.front()) { Object *obj = ObjectDB::get_instance(frame_drawn_callbacks.front()->get().object); if (obj) { @@ -396,6 +398,7 @@ RenderingServerDefault::RenderingServerDefault(bool p_create_thread) : server_thread = 0; } + RSG::threaded = p_create_thread; RSG::canvas = memnew(RendererCanvasCull); RSG::viewport = memnew(RendererViewport); RendererSceneCull *sr = memnew(RendererSceneCull); diff --git a/servers/rendering/rendering_server_default.h b/servers/rendering/rendering_server_default.h index e4d319ed6c..73373c97bb 100644 --- a/servers/rendering/rendering_server_default.h +++ b/servers/rendering/rendering_server_default.h @@ -820,6 +820,8 @@ public: FUNC2(canvas_item_set_use_parent_material, RID, bool) + FUNC5(canvas_item_set_visibility_notifier, RID, bool, const Rect2 &, const Callable &, const Callable &) + FUNC6(canvas_item_set_canvas_group_mode, RID, CanvasGroupMode, float, bool, float, bool) FUNCRIDSPLIT(canvas_light) diff --git a/servers/rendering/rendering_server_globals.cpp b/servers/rendering/rendering_server_globals.cpp index c0d9988e85..2dda506bac 100644 --- a/servers/rendering/rendering_server_globals.cpp +++ b/servers/rendering/rendering_server_globals.cpp @@ -30,6 +30,8 @@ #include "rendering_server_globals.h" +bool RenderingServerGlobals::threaded = false; + RendererStorage *RenderingServerGlobals::storage = nullptr; RendererCanvasRender *RenderingServerGlobals::canvas_render = nullptr; RendererCompositor *RenderingServerGlobals::rasterizer = nullptr; diff --git a/servers/rendering/rendering_server_globals.h b/servers/rendering/rendering_server_globals.h index a28a0f5180..63755e6125 100644 --- a/servers/rendering/rendering_server_globals.h +++ b/servers/rendering/rendering_server_globals.h @@ -41,6 +41,8 @@ class RendererScene; class RenderingServerGlobals { public: + static bool threaded; + static RendererStorage *storage; static RendererCanvasRender *canvas_render; static RendererCompositor *rasterizer; diff --git a/servers/rendering_server.h b/servers/rendering_server.h index 1806f1da18..0cb765ef56 100644 --- a/servers/rendering_server.h +++ b/servers/rendering_server.h @@ -1301,6 +1301,8 @@ public: virtual void canvas_item_set_use_parent_material(RID p_item, bool p_enable) = 0; + virtual void canvas_item_set_visibility_notifier(RID p_item, bool p_enable, const Rect2 &p_area, const Callable &p_enter_callbable, const Callable &p_exit_callable) = 0; + enum CanvasGroupMode { CANVAS_GROUP_MODE_DISABLED, CANVAS_GROUP_MODE_OPAQUE, |