Flutter Linux Embedder
fl_gl_area.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
6 
7 #include <epoxy/gl.h>
8 
9 struct _FlGLArea {
10  GtkWidget parent_instance;
11 
12  GdkGLContext* context;
13 
14  GPtrArray* textures;
15 };
16 
17 G_DEFINE_TYPE(FlGLArea, fl_gl_area, GTK_TYPE_WIDGET)
18 
19 static void fl_gl_area_dispose(GObject* gobject) {
20  FlGLArea* self = FL_GL_AREA(gobject);
21 
22  g_clear_object(&self->context);
23  g_clear_pointer(&self->textures, g_ptr_array_unref);
24 
25  G_OBJECT_CLASS(fl_gl_area_parent_class)->dispose(gobject);
26 }
27 
28 // Implements GtkWidget::realize.
29 static void fl_gl_area_realize(GtkWidget* widget) {
30  GtkAllocation allocation;
31  gtk_widget_get_allocation(widget, &allocation);
32 
33  gtk_widget_set_realized(widget, TRUE);
34 
35  GdkWindowAttr attributes;
36  attributes.window_type = GDK_WINDOW_CHILD;
37  attributes.x = allocation.x;
38  attributes.y = allocation.y;
39  attributes.width = allocation.width;
40  attributes.height = allocation.height;
41  attributes.wclass = GDK_INPUT_OUTPUT;
42  attributes.visual = gtk_widget_get_visual(widget);
43  attributes.event_mask = gtk_widget_get_events(widget);
44  gint attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL;
45  GdkWindow* window = gdk_window_new(gtk_widget_get_parent_window(widget),
46  &attributes, attributes_mask);
47  gtk_widget_set_window(widget, window);
48  gtk_widget_register_window(widget, window);
49 }
50 
51 // Implements GtkWidget::unrealize.
52 static void fl_gl_area_unrealize(GtkWidget* widget) {
53  FlGLArea* self = FL_GL_AREA(widget);
54  gdk_gl_context_make_current(self->context);
55  g_clear_pointer(&self->textures, g_ptr_array_unref);
56 
57  /* Make sure to unset the context if current */
58  if (self->context == gdk_gl_context_get_current()) {
59  gdk_gl_context_clear_current();
60  }
61 
62  GTK_WIDGET_CLASS(fl_gl_area_parent_class)->unrealize(widget);
63 }
64 
65 // Implements GtkWidget::size_allocate.
66 static void fl_gl_area_size_allocate(GtkWidget* widget,
67  GtkAllocation* allocation) {
68  gtk_widget_set_allocation(widget, allocation);
69 
70  if (gtk_widget_get_has_window(widget)) {
71  if (gtk_widget_get_realized(widget)) {
72  gdk_window_move_resize(gtk_widget_get_window(widget), allocation->x,
73  allocation->y, allocation->width,
74  allocation->height);
75  }
76  }
77 }
78 
79 // Implements GtkWidget::draw.
80 static gboolean fl_gl_area_draw(GtkWidget* widget, cairo_t* cr) {
81  FlGLArea* self = FL_GL_AREA(widget);
82 
83  gdk_gl_context_make_current(self->context);
84 
85  gint scale = gtk_widget_get_scale_factor(widget);
86 
87  if (self->textures == nullptr) {
88  return TRUE;
89  }
90 
91  for (guint i = 0; i < self->textures->len; i++) {
92  FlBackingStoreProvider* texture =
93  FL_BACKING_STORE_PROVIDER(g_ptr_array_index(self->textures, i));
95  GdkRectangle geometry = fl_backing_store_provider_get_geometry(texture);
96  gdk_cairo_draw_from_gl(cr, gtk_widget_get_window(widget), texture_id,
97  GL_TEXTURE, scale, geometry.x, geometry.y,
98  geometry.width, geometry.height);
99  }
100 
101  return TRUE;
102 }
103 
104 static void fl_gl_area_class_init(FlGLAreaClass* klass) {
105  GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
106  gobject_class->dispose = fl_gl_area_dispose;
107 
108  GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
109  widget_class->realize = fl_gl_area_realize;
110  widget_class->unrealize = fl_gl_area_unrealize;
111  widget_class->size_allocate = fl_gl_area_size_allocate;
112  widget_class->draw = fl_gl_area_draw;
113 
114  gtk_widget_class_set_accessible_role(widget_class, ATK_ROLE_DRAWING_AREA);
115 }
116 
117 static void fl_gl_area_init(FlGLArea* self) {
118  gtk_widget_set_app_paintable(GTK_WIDGET(self), TRUE);
119 }
120 
121 GtkWidget* fl_gl_area_new(GdkGLContext* context) {
122  g_return_val_if_fail(GDK_IS_GL_CONTEXT(context), nullptr);
123  FlGLArea* area =
124  reinterpret_cast<FlGLArea*>(g_object_new(fl_gl_area_get_type(), nullptr));
125  area->context = GDK_GL_CONTEXT(g_object_ref(context));
126  return GTK_WIDGET(area);
127 }
128 
129 void fl_gl_area_queue_render(FlGLArea* self, GPtrArray* textures) {
130  g_return_if_fail(FL_IS_GL_AREA(self));
131 
132  g_clear_pointer(&self->textures, g_ptr_array_unref);
133  self->textures = g_ptr_array_ref(textures);
134 
135  gtk_widget_queue_draw(GTK_WIDGET(self));
136 }
fl_gl_area_class_init
static void fl_gl_area_class_init(FlGLAreaClass *klass)
Definition: fl_gl_area.cc:104
_FlGLArea
Definition: fl_gl_area.cc:9
fl_gl_area_new
GtkWidget * fl_gl_area_new(GdkGLContext *context)
Definition: fl_gl_area.cc:121
fl_gl_area_unrealize
static void fl_gl_area_unrealize(GtkWidget *widget)
Definition: fl_gl_area.cc:52
_FlGLArea::parent_instance
GtkWidget parent_instance
Definition: fl_gl_area.cc:10
_FlGLArea::context
GdkGLContext * context
Definition: fl_gl_area.cc:12
fl_gl_area_draw
static gboolean fl_gl_area_draw(GtkWidget *widget, cairo_t *cr)
Definition: fl_gl_area.cc:80
fl_backing_store_provider_get_gl_texture_id
uint32_t fl_backing_store_provider_get_gl_texture_id(FlBackingStoreProvider *self)
Definition: fl_backing_store_provider.cc:71
G_DEFINE_TYPE
G_DEFINE_TYPE(FlBasicMessageChannelResponseHandle, fl_basic_message_channel_response_handle, G_TYPE_OBJECT) static void fl_basic_message_channel_response_handle_dispose(GObject *object)
Definition: fl_basic_message_channel.cc:37
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53
_FlGLArea::textures
GPtrArray * textures
Definition: fl_gl_area.cc:14
fl_gl_area.h
self
GdkEvent FlView * self
Definition: fl_view.cc:100
fl_gl_area_queue_render
void fl_gl_area_queue_render(FlGLArea *self, GPtrArray *textures)
Definition: fl_gl_area.cc:129
fl_backing_store_provider_get_geometry
GdkRectangle fl_backing_store_provider_get_geometry(FlBackingStoreProvider *self)
Definition: fl_backing_store_provider.cc:104
fl_gl_area_init
static void fl_gl_area_init(FlGLArea *self)
Definition: fl_gl_area.cc:117
fl_gl_area_realize
static void fl_gl_area_realize(GtkWidget *widget)
Definition: fl_gl_area.cc:29
fl_gl_area_dispose
static void fl_gl_area_dispose(GObject *gobject)
Definition: fl_gl_area.cc:19
texture_id
int64_t texture_id
Definition: texture_registrar_unittests.cc:24
fl_gl_area_size_allocate
static void fl_gl_area_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
Definition: fl_gl_area.cc:66