Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit f37f48d

Browse files
Simplify FlView (#39467)
This PR simplifies the FlView GL interactions. It removes some code paths that were never being used (possibly for future use with platform views?) and complex internal APIs that could be done in a single method call. This is motivated in investigating https://github.com/ubuntu-flutter-community/software/issues/868. I plan to take this further, since there doesn't seem to be any reason why multiple FlGLArea widgets are used - we can draw all the layers in one widget. For reviewers - the individual commits aren't particularly interesting, I just did it that way to be sure I wasn't breaking anything along the way and help to diagnose any regressions in the future. The structural changes that this PR is simplifying came in f94cf14.
1 parent 623c935 commit f37f48d

File tree

3 files changed

+69
-203
lines changed

3 files changed

+69
-203
lines changed

shell/platform/linux/fl_renderer_gl.cc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,25 +98,25 @@ static gboolean fl_renderer_gl_present_layers(FlRenderer* renderer,
9898
if (!view || !context) {
9999
return FALSE;
100100
}
101-
fl_view_begin_frame(view);
102101

102+
g_autoptr(GPtrArray) textures = g_ptr_array_new();
103103
for (size_t i = 0; i < layers_count; ++i) {
104104
const FlutterLayer* layer = layers[i];
105105
switch (layer->type) {
106106
case kFlutterLayerContentTypeBackingStore: {
107107
const FlutterBackingStore* backing_store = layer->backing_store;
108108
auto framebuffer = &backing_store->open_gl.framebuffer;
109-
fl_view_add_gl_area(
110-
view, context,
111-
reinterpret_cast<FlBackingStoreProvider*>(framebuffer->user_data));
109+
g_ptr_array_add(textures, reinterpret_cast<FlBackingStoreProvider*>(
110+
framebuffer->user_data));
112111
} break;
113112
case kFlutterLayerContentTypePlatformView: {
114113
// Currently unsupported.
115114
} break;
116115
}
117116
}
118117

119-
fl_view_end_frame(view);
118+
fl_view_set_textures(view, context, textures);
119+
120120
return TRUE;
121121
}
122122

shell/platform/linux/fl_view.cc

Lines changed: 56 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,9 @@ struct _FlView {
5050
FlMouseCursorPlugin* mouse_cursor_plugin;
5151
FlPlatformPlugin* platform_plugin;
5252

53-
GList* gl_area_list;
54-
GList* used_area_list;
55-
5653
GtkWidget* event_box;
5754

5855
GList* children_list;
59-
GList* pending_children_list;
6056

6157
// Tracks whether mouse pointer is inside the view.
6258
gboolean pointer_inside;
@@ -67,11 +63,6 @@ struct _FlView {
6763
gulong keymap_keys_changed_cb_id; // Signal connection ID.
6864
};
6965

70-
typedef struct _FlViewChild {
71-
GtkWidget* widget;
72-
GdkRectangle geometry;
73-
} FlViewChild;
74-
7566
enum { kPropFlutterProject = 1, kPropLast };
7667

7768
static void fl_view_plugin_registry_iface_init(
@@ -213,33 +204,6 @@ static void handle_geometry_changed(FlView* self) {
213204
}
214205
}
215206

216-
// Adds a widget to render in this view.
217-
static void add_pending_child(FlView* self,
218-
GtkWidget* widget,
219-
GdkRectangle* geometry) {
220-
FlViewChild* child = g_new(FlViewChild, 1);
221-
child->widget = widget;
222-
if (geometry) {
223-
child->geometry = *geometry;
224-
} else {
225-
child->geometry = {0, 0, 0, 0};
226-
}
227-
228-
self->pending_children_list =
229-
g_list_append(self->pending_children_list, child);
230-
}
231-
232-
// Finds the node with the specified widget in a list of FlViewChild.
233-
static GList* find_child(GList* list, GtkWidget* widget) {
234-
for (GList* i = list; i; i = i->next) {
235-
FlViewChild* child = reinterpret_cast<FlViewChild*>(i->data);
236-
if (child && child->widget == widget) {
237-
return i;
238-
}
239-
}
240-
return nullptr;
241-
}
242-
243207
// Called when the engine updates accessibility nodes.
244208
static void update_semantics_node_cb(FlEngine* engine,
245209
const FlutterSemanticsNode* node,
@@ -627,8 +591,8 @@ static void fl_view_dispose(GObject* object) {
627591
}
628592
g_clear_object(&self->mouse_cursor_plugin);
629593
g_clear_object(&self->platform_plugin);
630-
g_list_free_full(self->gl_area_list, g_object_unref);
631-
self->gl_area_list = nullptr;
594+
g_list_free_full(self->children_list, g_object_unref);
595+
self->children_list = nullptr;
632596

633597
G_OBJECT_CLASS(fl_view_parent_class)->dispose(object);
634598
}
@@ -686,16 +650,16 @@ static void fl_view_get_preferred_width(GtkWidget* widget,
686650

687651
for (GList* iterator = self->children_list; iterator;
688652
iterator = iterator->next) {
689-
FlViewChild* child = reinterpret_cast<FlViewChild*>(iterator->data);
653+
GtkWidget* w = reinterpret_cast<GtkWidget*>(iterator->data);
690654

691-
if (!gtk_widget_get_visible(child->widget)) {
655+
if (!gtk_widget_get_visible(w)) {
692656
continue;
693657
}
694658

695-
gtk_widget_get_preferred_width(child->widget, &child_min, &child_nat);
659+
gtk_widget_get_preferred_width(w, &child_min, &child_nat);
696660

697-
*minimum = MAX(*minimum, child->geometry.x + child_min);
698-
*natural = MAX(*natural, child->geometry.x + child_nat);
661+
*minimum = MAX(*minimum, child_min);
662+
*natural = MAX(*natural, child_nat);
699663
}
700664
}
701665

@@ -711,16 +675,16 @@ static void fl_view_get_preferred_height(GtkWidget* widget,
711675

712676
for (GList* iterator = self->children_list; iterator;
713677
iterator = iterator->next) {
714-
FlViewChild* child = reinterpret_cast<FlViewChild*>(iterator->data);
678+
GtkWidget* w = reinterpret_cast<GtkWidget*>(iterator->data);
715679

716-
if (!gtk_widget_get_visible(child->widget)) {
680+
if (!gtk_widget_get_visible(w)) {
717681
continue;
718682
}
719683

720-
gtk_widget_get_preferred_height(child->widget, &child_min, &child_nat);
684+
gtk_widget_get_preferred_height(w, &child_min, &child_nat);
721685

722-
*minimum = MAX(*minimum, child->geometry.y + child_min);
723-
*natural = MAX(*natural, child->geometry.y + child_nat);
686+
*minimum = MAX(*minimum, child_min);
687+
*natural = MAX(*natural, child_nat);
724688
}
725689
}
726690

@@ -741,14 +705,14 @@ static void fl_view_size_allocate(GtkWidget* widget,
741705

742706
for (GList* iterator = self->children_list; iterator;
743707
iterator = iterator->next) {
744-
FlViewChild* child = reinterpret_cast<FlViewChild*>(iterator->data);
745-
if (!gtk_widget_get_visible(child->widget)) {
708+
GtkWidget* w = reinterpret_cast<GtkWidget*>(iterator->data);
709+
if (!gtk_widget_get_visible(w)) {
746710
continue;
747711
}
748712

749-
GtkAllocation child_allocation = child->geometry;
713+
GtkAllocation child_allocation = {0, 0, 0, 0};
750714
GtkRequisition child_requisition;
751-
gtk_widget_get_preferred_size(child->widget, &child_requisition, NULL);
715+
gtk_widget_get_preferred_size(w, &child_requisition, nullptr);
752716

753717
if (!gtk_widget_get_has_window(widget)) {
754718
child_allocation.x += allocation->x;
@@ -760,7 +724,7 @@ static void fl_view_size_allocate(GtkWidget* widget,
760724
child_allocation.height = allocation->height;
761725
}
762726

763-
gtk_widget_size_allocate(child->widget, &child_allocation);
727+
gtk_widget_size_allocate(w, &child_allocation);
764728
}
765729

766730
GtkAllocation event_box_allocation = {
@@ -778,22 +742,6 @@ static void fl_view_size_allocate(GtkWidget* widget,
778742
handle_geometry_changed(self);
779743
}
780744

781-
struct _ReorderData {
782-
GdkWindow* parent_window;
783-
GdkWindow* last_window;
784-
};
785-
786-
static void fl_view_reorder_forall(GtkWidget* widget, gpointer user_data) {
787-
_ReorderData* data = reinterpret_cast<_ReorderData*>(user_data);
788-
GdkWindow* window = gtk_widget_get_window(widget);
789-
if (window && window != data->parent_window) {
790-
if (data->last_window) {
791-
gdk_window_restack(window, data->last_window, TRUE);
792-
}
793-
data->last_window = window;
794-
}
795-
}
796-
797745
// Implements GtkWidget::key_press_event.
798746
static gboolean fl_view_key_press_event(GtkWidget* widget, GdkEventKey* event) {
799747
FlView* self = FL_VIEW(widget);
@@ -812,40 +760,25 @@ static gboolean fl_view_key_release_event(GtkWidget* widget,
812760
reinterpret_cast<GdkEvent*>(event))));
813761
}
814762

815-
static void put_widget(FlView* self,
816-
GtkWidget* widget,
817-
GdkRectangle* geometry) {
818-
FlViewChild* child = g_new(FlViewChild, 1);
819-
child->widget = widget;
820-
child->geometry = *geometry;
821-
822-
gtk_widget_set_parent(widget, GTK_WIDGET(self));
823-
self->children_list = g_list_append(self->children_list, child);
824-
}
825-
826763
// Implements GtkContainer::add
827764
static void fl_view_add(GtkContainer* container, GtkWidget* widget) {
828-
GdkRectangle geometry = {
829-
.x = 0,
830-
.y = 0,
831-
.width = 0,
832-
.height = 0,
833-
};
834-
put_widget(FL_VIEW(container), widget, &geometry);
765+
FlView* self = FL_VIEW(container);
766+
767+
gtk_widget_set_parent(widget, GTK_WIDGET(self));
768+
self->children_list = g_list_append(self->children_list, widget);
835769
}
836770

837771
// Implements GtkContainer::remove
838772
static void fl_view_remove(GtkContainer* container, GtkWidget* widget) {
839773
FlView* self = FL_VIEW(container);
840774
for (GList* iterator = self->children_list; iterator;
841775
iterator = iterator->next) {
842-
FlViewChild* child = reinterpret_cast<FlViewChild*>(iterator->data);
843-
if (child->widget == widget) {
776+
GtkWidget* w = reinterpret_cast<GtkWidget*>(iterator->data);
777+
if (w == widget) {
844778
g_object_ref(widget);
845779
gtk_widget_unparent(widget);
846780
self->children_list = g_list_remove_link(self->children_list, iterator);
847781
g_list_free(iterator);
848-
g_free(child);
849782

850783
break;
851784
}
@@ -864,8 +797,8 @@ static void fl_view_forall(GtkContainer* container,
864797
FlView* self = FL_VIEW(container);
865798
for (GList* iterator = self->children_list; iterator;
866799
iterator = iterator->next) {
867-
FlViewChild* child = reinterpret_cast<FlViewChild*>(iterator->data);
868-
(*callback)(child->widget, callback_data);
800+
GtkWidget* w = reinterpret_cast<GtkWidget*>(iterator->data);
801+
(*callback)(w, callback_data);
869802
}
870803

871804
if (include_internals) {
@@ -937,84 +870,47 @@ G_MODULE_EXPORT FlView* fl_view_new(FlDartProject* project) {
937870
g_object_new(fl_view_get_type(), "flutter-project", project, nullptr));
938871
}
939872

940-
G_MODULE_EXPORT FlEngine* fl_view_get_engine(FlView* view) {
941-
g_return_val_if_fail(FL_IS_VIEW(view), nullptr);
942-
return view->engine;
873+
G_MODULE_EXPORT FlEngine* fl_view_get_engine(FlView* self) {
874+
g_return_val_if_fail(FL_IS_VIEW(self), nullptr);
875+
return self->engine;
943876
}
944877

945-
void fl_view_begin_frame(FlView* view) {
946-
g_return_if_fail(FL_IS_VIEW(view));
947-
FlView* self = FL_VIEW(view);
878+
void fl_view_set_textures(FlView* self,
879+
GdkGLContext* context,
880+
GPtrArray* textures) {
881+
g_return_if_fail(FL_IS_VIEW(self));
948882

949-
self->used_area_list = self->gl_area_list;
950-
g_list_free_full(self->pending_children_list, g_free);
951-
self->pending_children_list = nullptr;
952-
}
883+
guint children_length = g_list_length(self->children_list);
953884

954-
void fl_view_add_gl_area(FlView* view,
955-
GdkGLContext* context,
956-
FlBackingStoreProvider* texture) {
957-
g_return_if_fail(FL_IS_VIEW(view));
885+
// Add more GL areas if we need them.
886+
for (guint i = children_length; i < textures->len; i++) {
887+
FlGLArea* area = FL_GL_AREA(fl_gl_area_new(context));
958888

959-
FlGLArea* area;
960-
if (view->used_area_list) {
961-
area = reinterpret_cast<FlGLArea*>(view->used_area_list->data);
962-
view->used_area_list = view->used_area_list->next;
963-
} else {
964-
area = FL_GL_AREA(fl_gl_area_new(context));
965-
view->gl_area_list = g_list_append(view->gl_area_list, area);
966-
}
889+
gtk_widget_set_parent(GTK_WIDGET(area), GTK_WIDGET(self));
890+
gtk_widget_show(GTK_WIDGET(area));
967891

968-
gtk_widget_show(GTK_WIDGET(area));
969-
add_pending_child(view, GTK_WIDGET(area), nullptr);
970-
fl_gl_area_queue_render(area, texture);
971-
}
892+
// Stack above previous areas but below the event box.
893+
gdk_window_restack(gtk_widget_get_window(GTK_WIDGET(area)),
894+
gtk_widget_get_window(self->event_box), FALSE);
972895

973-
void fl_view_add_widget(FlView* view,
974-
GtkWidget* widget,
975-
GdkRectangle* geometry) {
976-
gtk_widget_show(widget);
977-
add_pending_child(view, widget, geometry);
978-
}
979-
980-
void fl_view_end_frame(FlView* view) {
981-
for (GList* pending_child = view->pending_children_list; pending_child;
982-
pending_child = pending_child->next) {
983-
FlViewChild* pending_view_child =
984-
reinterpret_cast<FlViewChild*>(pending_child->data);
985-
GList* child = find_child(view->children_list, pending_view_child->widget);
986-
987-
if (child) {
988-
// existing child
989-
g_free(child->data);
990-
child->data = nullptr;
991-
} else {
992-
// newly added child
993-
gtk_widget_set_parent(pending_view_child->widget, GTK_WIDGET(view));
994-
}
896+
self->children_list = g_list_append(self->children_list, area);
995897
}
996898

997-
for (GList* child = view->children_list; child; child = child->next) {
998-
FlViewChild* view_child = reinterpret_cast<FlViewChild*>(child->data);
999-
if (view_child) {
1000-
// removed child
1001-
g_object_ref(view_child->widget);
1002-
gtk_widget_unparent(view_child->widget);
1003-
g_free(view_child);
1004-
child->data = nullptr;
1005-
}
899+
// Remove unused GL areas.
900+
for (guint i = textures->len; i < children_length; i++) {
901+
FlGLArea* area = FL_GL_AREA(g_list_first(self->children_list)->data);
902+
gtk_widget_unparent(GTK_WIDGET(area));
903+
g_object_unref(area);
904+
self->children_list =
905+
g_list_remove_link(self->children_list, self->children_list);
1006906
}
1007907

1008-
g_list_free(view->children_list);
1009-
view->children_list = view->pending_children_list;
1010-
view->pending_children_list = nullptr;
1011-
1012-
struct _ReorderData data = {
1013-
.parent_window = gtk_widget_get_window(GTK_WIDGET(view)),
1014-
.last_window = nullptr,
1015-
};
1016-
1017-
gtk_container_forall(GTK_CONTAINER(view), fl_view_reorder_forall, &data);
908+
GList* area_link = self->children_list;
909+
for (guint i = 0; i < textures->len; i++, area_link = area_link->next) {
910+
FlBackingStoreProvider* texture =
911+
FL_BACKING_STORE_PROVIDER(g_ptr_array_index(textures, i));
912+
fl_gl_area_queue_render(FL_GL_AREA(area_link->data), texture);
913+
}
1018914

1019-
gtk_widget_queue_draw(GTK_WIDGET(view));
915+
gtk_widget_queue_draw(GTK_WIDGET(self));
1020916
}

0 commit comments

Comments
 (0)