diff options
Diffstat (limited to 'servers/rendering/renderer_canvas_cull.cpp')
-rw-r--r-- | servers/rendering/renderer_canvas_cull.cpp | 86 |
1 files changed, 55 insertions, 31 deletions
diff --git a/servers/rendering/renderer_canvas_cull.cpp b/servers/rendering/renderer_canvas_cull.cpp index cc51d44042..caeac5cd95 100644 --- a/servers/rendering/renderer_canvas_cull.cpp +++ b/servers/rendering/renderer_canvas_cull.cpp @@ -37,17 +37,17 @@ #include "rendering_server_globals.h" #include "servers/rendering/storage/texture_storage.h" -void RendererCanvasCull::_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, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t canvas_cull_mask, RenderingMethod::RenderInfo *r_render_info) { +void RendererCanvasCull::_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, RenderingServer::CanvasItemTextureFilter p_default_filter, RenderingServer::CanvasItemTextureRepeat p_default_repeat, bool p_snap_2d_vertices_to_pixel, uint32_t p_canvas_cull_mask, RenderingMethod::RenderInfo *r_render_info) { RENDER_TIMESTAMP("Cull CanvasItem Tree"); memset(z_list, 0, z_range * sizeof(RendererCanvasRender::Item *)); memset(z_last_list, 0, z_range * sizeof(RendererCanvasRender::Item *)); for (int i = 0; i < p_child_item_count; i++) { - _cull_canvas_item(p_child_items[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true, canvas_cull_mask); + _cull_canvas_item(p_child_items[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true, p_canvas_cull_mask); } if (p_canvas_item) { - _cull_canvas_item(p_canvas_item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true, canvas_cull_mask); + _cull_canvas_item(p_canvas_item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, nullptr, nullptr, true, p_canvas_cull_mask); } RendererCanvasRender::Item *list = nullptr; @@ -114,29 +114,29 @@ void _mark_ysort_dirty(RendererCanvasCull::Item *ysort_owner, RID_Owner<Renderer } while (ysort_owner && ysort_owner->sort_y); } -void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item *ci, RendererCanvasCull::Item *p_canvas_clip, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_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 p_use_canvas_group, RendererCanvasRender::Item *canvas_group_from, const Transform2D &p_xform) { +void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item *ci, RendererCanvasCull::Item *p_canvas_clip, RendererCanvasRender::Item **r_z_list, RendererCanvasRender::Item **r_z_last_list, const Transform2D &p_transform, const Rect2 &p_clip_rect, Rect2 p_global_rect, const Color &p_modulate, int p_z, RendererCanvasCull::Item *p_material_owner, bool p_use_canvas_group, RendererCanvasRender::Item *r_canvas_group_from) { if (ci->copy_back_buffer) { - ci->copy_back_buffer->screen_rect = xform.xform(ci->copy_back_buffer->rect).intersection(p_clip_rect); + ci->copy_back_buffer->screen_rect = p_transform.xform(ci->copy_back_buffer->rect).intersection(p_clip_rect); } if (p_use_canvas_group) { int zidx = p_z - RS::CANVAS_ITEM_Z_MIN; - if (canvas_group_from == nullptr) { + if (r_canvas_group_from == nullptr) { // no list before processing this item, means must put stuff in group from the beginning of list. - canvas_group_from = r_z_list[zidx]; + r_canvas_group_from = r_z_list[zidx]; } else { // there was a list before processing, so begin group from this one. - canvas_group_from = canvas_group_from->next; + r_canvas_group_from = r_canvas_group_from->next; } - if (canvas_group_from) { + if (r_canvas_group_from) { // Has a place to begin the group from! //compute a global rect (in global coords) for children in the same z layer Rect2 rect_accum; - RendererCanvasRender::Item *c = canvas_group_from; + RendererCanvasRender::Item *c = r_canvas_group_from; while (c) { - if (c == canvas_group_from) { + if (c == r_canvas_group_from) { rect_accum = c->global_rect_cache; } else { rect_accum = rect_accum.merge(c->global_rect_cache); @@ -161,28 +161,28 @@ void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item * RendererCanvasRender::Item::CommandRect *crect = ci->alloc_command<RendererCanvasRender::Item::CommandRect>(); crect->flags = RendererCanvasRender::CANVAS_RECT_IS_GROUP; // so we can recognize it later - crect->rect = xform.affine_inverse().xform(rect_accum); + crect->rect = p_transform.affine_inverse().xform(rect_accum); crect->modulate = Color(1, 1, 1, 1); //the global rect is used to do the copying, so update it - global_rect = rect_accum.grow(ci->canvas_group->clear_margin); //grow again by clear margin - global_rect.position += p_clip_rect.position; + p_global_rect = rect_accum.grow(ci->canvas_group->clear_margin); //grow again by clear margin + p_global_rect.position += p_clip_rect.position; } else { - global_rect.position -= p_clip_rect.position; + p_global_rect.position -= p_clip_rect.position; - global_rect = global_rect.merge(rect_accum); //must use both rects for this - global_rect = global_rect.grow(ci->canvas_group->clear_margin); //grow by clear margin + p_global_rect = p_global_rect.merge(rect_accum); //must use both rects for this + p_global_rect = p_global_rect.grow(ci->canvas_group->clear_margin); //grow by clear margin - global_rect.position += p_clip_rect.position; + p_global_rect.position += p_clip_rect.position; } // Very important that this is cleared after used in RendererCanvasRender to avoid // potential crashes. - canvas_group_from->canvas_group_owner = ci; + r_canvas_group_from->canvas_group_owner = ci; } } - if (((ci->commands != nullptr || ci->visibility_notifier) && 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(p_global_rect, true)) || ci->vp_render || ci->copy_back_buffer) { //something to draw? if (ci->update_when_visible) { @@ -190,9 +190,9 @@ void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item * } if (ci->commands != nullptr || ci->copy_back_buffer) { - ci->final_transform = xform; - ci->final_modulate = modulate * ci->self_modulate; - ci->global_rect_cache = global_rect; + ci->final_transform = p_transform; + ci->final_modulate = p_modulate * ci->self_modulate; + ci->global_rect_cache = p_global_rect; ci->global_rect_cache.position -= p_clip_rect.position; ci->light_masked = false; @@ -223,14 +223,14 @@ void RendererCanvasCull::_attach_canvas_item_for_draw(RendererCanvasCull::Item * } } -void RendererCanvasCull::_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 **r_z_list, RendererCanvasRender::Item **r_z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool allow_y_sort, uint32_t canvas_cull_mask) { +void RendererCanvasCull::_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 **r_z_list, RendererCanvasRender::Item **r_z_last_list, Item *p_canvas_clip, Item *p_material_owner, bool p_allow_y_sort, uint32_t p_canvas_cull_mask) { Item *ci = p_canvas_item; if (!ci->visible) { return; } - if (!(ci->visibility_layer & canvas_cull_mask)) { + if (!(ci->visibility_layer & p_canvas_cull_mask)) { return; } @@ -298,7 +298,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 } if (ci->sort_y) { - if (allow_y_sort) { + if (p_allow_y_sort) { if (ci->ysort_children_count == -1) { ci->ysort_children_count = 0; _collect_ysort_children(ci, Transform2D(), p_material_owner, Color(1, 1, 1, 1), nullptr, ci->ysort_children_count, p_z); @@ -318,7 +318,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 sorter.sort(child_items, child_item_count); for (i = 0; i < child_item_count; i++) { - _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate * child_items[i]->ysort_modulate, child_items[i]->ysort_parent_abs_z_index, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner, false, canvas_cull_mask); + _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate * child_items[i]->ysort_modulate, child_items[i]->ysort_parent_abs_z_index, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner, false, p_canvas_cull_mask); } } else { RendererCanvasRender::Item *canvas_group_from = nullptr; @@ -328,7 +328,7 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 canvas_group_from = r_z_last_list[zidx]; } - _attach_canvas_item_for_draw(ci, p_canvas_clip, r_z_list, r_z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from, xform); + _attach_canvas_item_for_draw(ci, p_canvas_clip, r_z_list, r_z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from); } } else { RendererCanvasRender::Item *canvas_group_from = nullptr; @@ -342,14 +342,14 @@ void RendererCanvasCull::_cull_canvas_item(Item *p_canvas_item, const Transform2 if (!child_items[i]->behind && !use_canvas_group) { continue; } - _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true, canvas_cull_mask); + _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true, p_canvas_cull_mask); } - _attach_canvas_item_for_draw(ci, p_canvas_clip, r_z_list, r_z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from, xform); + _attach_canvas_item_for_draw(ci, p_canvas_clip, r_z_list, r_z_last_list, xform, p_clip_rect, global_rect, modulate, p_z, p_material_owner, use_canvas_group, canvas_group_from); for (int i = 0; i < child_item_count; i++) { if (child_items[i]->behind || use_canvas_group) { continue; } - _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true, canvas_cull_mask); + _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, r_z_list, r_z_last_list, (Item *)ci->final_clip_owner, p_material_owner, true, p_canvas_cull_mask); } } } @@ -2165,6 +2165,30 @@ bool RendererCanvasCull::free(RID p_rid) { return true; } +template <class T> +void RendererCanvasCull::_free_rids(T &p_owner, const char *p_type) { + List<RID> owned; + p_owner.get_owned_list(&owned); + if (owned.size()) { + if (owned.size() == 1) { + WARN_PRINT(vformat("1 RID of type \"%s\" was leaked.", p_type)); + } else { + WARN_PRINT(vformat("%d RIDs of type \"%s\" were leaked.", owned.size(), p_type)); + } + for (const RID &E : owned) { + free(E); + } + } +} + +void RendererCanvasCull::finalize() { + _free_rids(canvas_owner, "Canvas"); + _free_rids(canvas_item_owner, "CanvasItem"); + _free_rids(canvas_light_owner, "CanvasLight"); + _free_rids(canvas_light_occluder_owner, "CanvasLightOccluder"); + _free_rids(canvas_light_occluder_polygon_owner, "CanvasLightOccluderPolygon"); +} + RendererCanvasCull::RendererCanvasCull() { z_list = (RendererCanvasRender::Item **)memalloc(z_range * sizeof(RendererCanvasRender::Item *)); z_last_list = (RendererCanvasRender::Item **)memalloc(z_range * sizeof(RendererCanvasRender::Item *)); |