diff options
| -rw-r--r-- | servers/rendering/renderer_viewport.cpp | 52 | ||||
| -rw-r--r-- | servers/rendering/renderer_viewport.h | 15 | 
2 files changed, 49 insertions, 18 deletions
diff --git a/servers/rendering/renderer_viewport.cpp b/servers/rendering/renderer_viewport.cpp index 7c9b2567d6..ac92f01449 100644 --- a/servers/rendering/renderer_viewport.cpp +++ b/servers/rendering/renderer_viewport.cpp @@ -72,6 +72,41 @@ static Transform2D _canvas_get_transform(RendererViewport::Viewport *p_viewport,  	return xf;  } +Vector<RendererViewport::Viewport *> RendererViewport::_sort_active_viewports() { +	// We need to sort the viewports in a "topological order", +	// children first and parents last, we use the Kahn's algorithm to achieve that. + +	Vector<Viewport *> result; +	List<Viewport *> nodes; + +	for (Viewport *viewport : active_viewports) { +		if (viewport->parent.is_valid()) { +			continue; +		} + +		nodes.push_back(viewport); +	} + +	while (!nodes.is_empty()) { +		Viewport *node = nodes[0]; +		nodes.pop_front(); + +		result.insert(0, node); + +		for (Viewport *child : active_viewports) { +			if (child->parent != node->self) { +				continue; +			} + +			if (!nodes.find(child)) { +				nodes.push_back(child); +			} +		} +	} + +	return result; +} +  void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {  	if (p_viewport->render_buffers.is_valid()) {  		if (p_viewport->size.width == 0 || p_viewport->size.height == 0) { @@ -544,8 +579,10 @@ void RendererViewport::draw_viewports() {  		set_default_clear_color(GLOBAL_GET("rendering/environment/defaults/default_clear_color"));  	} -	//sort viewports -	active_viewports.sort_custom<ViewportSort>(); +	if (sorted_active_viewports_dirty) { +		sorted_active_viewports = _sort_active_viewports(); +		sorted_active_viewports_dirty = false; +	}  	HashMap<DisplayServer::WindowID, Vector<BlitToScreen>> blit_to_screen_list;  	//draw viewports @@ -554,9 +591,9 @@ void RendererViewport::draw_viewports() {  	//determine what is visible  	draw_viewports_pass++; -	for (int i = active_viewports.size() - 1; i >= 0; i--) { //to compute parent dependency, must go in reverse draw order +	for (int i = sorted_active_viewports.size() - 1; i >= 0; i--) { //to compute parent dependency, must go in reverse draw order -		Viewport *vp = active_viewports[i]; +		Viewport *vp = sorted_active_viewports[i];  		if (vp->update_mode == RS::VIEWPORT_UPDATE_DISABLED) {  			continue; @@ -617,8 +654,8 @@ void RendererViewport::draw_viewports() {  	int objects_drawn = 0;  	int draw_calls_used = 0; -	for (int i = 0; i < active_viewports.size(); i++) { -		Viewport *vp = active_viewports[i]; +	for (int i = 0; i < sorted_active_viewports.size(); i++) { +		Viewport *vp = sorted_active_viewports[i];  		if (vp->last_pass != draw_viewports_pass) {  			continue; //should not draw @@ -810,6 +847,8 @@ void RendererViewport::viewport_set_active(RID p_viewport, bool p_active) {  	} else {  		active_viewports.erase(viewport);  	} + +	sorted_active_viewports_dirty = true;  }  void RendererViewport::viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) { @@ -1239,6 +1278,7 @@ bool RendererViewport::free(RID p_rid) {  		viewport_set_scenario(p_rid, RID());  		active_viewports.erase(viewport); +		sorted_active_viewports_dirty = true;  		if (viewport->use_occlusion_culling) {  			RendererSceneOcclusionCull::get_singleton()->remove_buffer(p_rid); diff --git a/servers/rendering/renderer_viewport.h b/servers/rendering/renderer_viewport.h index 027f2dfad6..d5e0d3f151 100644 --- a/servers/rendering/renderer_viewport.h +++ b/servers/rendering/renderer_viewport.h @@ -184,25 +184,16 @@ public:  	mutable RID_Owner<Viewport, true> viewport_owner; -	struct ViewportSort { -		_FORCE_INLINE_ bool operator()(const Viewport *p_left, const Viewport *p_right) const { -			bool left_to_screen = p_left->viewport_to_screen_rect.size != Size2(); -			bool right_to_screen = p_right->viewport_to_screen_rect.size != Size2(); - -			if (left_to_screen == right_to_screen) { -				return p_right->parent == p_left->self; -			} -			return (right_to_screen ? 0 : 1) < (left_to_screen ? 0 : 1); -		} -	}; -  	Vector<Viewport *> active_viewports; +	Vector<Viewport *> sorted_active_viewports; +	bool sorted_active_viewports_dirty = false;  	int total_objects_drawn = 0;  	int total_vertices_drawn = 0;  	int total_draw_calls_used = 0;  private: +	Vector<Viewport *> _sort_active_viewports();  	void _configure_3d_render_buffers(Viewport *p_viewport);  	void _draw_3d(Viewport *p_viewport);  	void _draw_viewport(Viewport *p_viewport);  |