Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
fl_view_renderer_opengl.cc File Reference

Go to the source code of this file.

Classes

struct  _FlViewRendererOpenGL
 

Functions

 G_DEFINE_TYPE (FlViewRendererOpenGL, fl_view_renderer_opengl, fl_view_renderer_get_type()) static gboolean redraw_cb(gpointer user_data)
 
static void wait_for_frame (FlViewRendererOpenGL *self, GdkWindow *window, gint scale_factor)
 
static void fl_view_renderer_opengl_realize (GtkWidget *widget)
 
static gboolean fl_view_renderer_opengl_draw (GtkWidget *widget, cairo_t *cr)
 
static void fl_view_renderer_opengl_present_layers (FlViewRenderer *renderer, const FlutterLayer **layers, size_t layers_count)
 
static void fl_view_renderer_opengl_dispose (GObject *object)
 
static void fl_view_renderer_opengl_finalize (GObject *object)
 
static void fl_view_renderer_opengl_class_init (FlViewRendererOpenGLClass *klass)
 
static void fl_view_renderer_opengl_init (FlViewRendererOpenGL *self)
 
FlViewRendererOpenGL * fl_view_renderer_opengl_new (FlEngine *engine, gboolean sized_to_content)
 

Variables

static constexpr gint64 kRenderTimeoutMicroseconds = 100000
 

Function Documentation

◆ fl_view_renderer_opengl_class_init()

static void fl_view_renderer_opengl_class_init ( FlViewRendererOpenGLClass *  klass)
static

Definition at line 231 of file fl_view_renderer_opengl.cc.

232 {
233 GObjectClass* object_class = G_OBJECT_CLASS(klass);
234 object_class->dispose = fl_view_renderer_opengl_dispose;
235 object_class->finalize = fl_view_renderer_opengl_finalize;
236
237 GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
238 widget_class->realize = fl_view_renderer_opengl_realize;
239 widget_class->draw = fl_view_renderer_opengl_draw;
240
241 FlViewRendererClass* renderer_class = FL_VIEW_RENDERER_CLASS(klass);
242 renderer_class->present_layers = fl_view_renderer_opengl_present_layers;
243}
static void fl_view_renderer_opengl_present_layers(FlViewRenderer *renderer, const FlutterLayer **layers, size_t layers_count)
static gboolean fl_view_renderer_opengl_draw(GtkWidget *widget, cairo_t *cr)
static void fl_view_renderer_opengl_finalize(GObject *object)
static void fl_view_renderer_opengl_dispose(GObject *object)
static void fl_view_renderer_opengl_realize(GtkWidget *widget)

References fl_view_renderer_opengl_dispose(), fl_view_renderer_opengl_draw(), fl_view_renderer_opengl_finalize(), fl_view_renderer_opengl_present_layers(), and fl_view_renderer_opengl_realize().

◆ fl_view_renderer_opengl_dispose()

static void fl_view_renderer_opengl_dispose ( GObject *  object)
static

Definition at line 207 of file fl_view_renderer_opengl.cc.

207 {
208 FlViewRendererOpenGL* self = FL_VIEW_RENDERER_OPENGL(object);
209
210 g_clear_object(&self->engine);
211 g_clear_object(&self->render_context);
212 g_clear_object(&self->task_runner);
213 g_mutex_clear(&self->frame_mutex);
214
215 G_OBJECT_CLASS(fl_view_renderer_opengl_parent_class)->dispose(object);
216}

References self.

Referenced by fl_view_renderer_opengl_class_init().

◆ fl_view_renderer_opengl_draw()

static gboolean fl_view_renderer_opengl_draw ( GtkWidget *  widget,
cairo_t *  cr 
)
static

Definition at line 148 of file fl_view_renderer_opengl.cc.

148 {
149 FlViewRendererOpenGL* self = FL_VIEW_RENDERER_OPENGL(widget);
150
151 fl_view_renderer_paint_background(FL_VIEW_RENDERER(self), cr);
152
153 // The compositor is created when the widget is realized; if it is not yet
154 // available there is nothing to render beyond the background.
155 if (self->compositor == nullptr) {
156 return TRUE;
157 }
158
159 GdkWindow* window = gtk_widget_get_window(widget);
160 gint scale_factor = gdk_window_get_scale_factor(window);
161
162 g_mutex_lock(&self->frame_mutex);
163
164 // If frame not ready, then wait for it.
165 if (!self->sized_to_content) {
166 wait_for_frame(self, window, scale_factor);
167 }
168
169 if (self->render_context != nullptr) {
170 gdk_gl_context_make_current(self->render_context);
171 }
172
173 gboolean result = fl_compositor_opengl_render(self->compositor, cr, window);
174
175 if (self->render_context != nullptr) {
177 }
178
179 g_mutex_unlock(&self->frame_mutex);
180
181 return result;
182}
GLFWwindow * window
Definition main.cc:60
gboolean fl_compositor_opengl_render(FlCompositorOpenGL *self, cairo_t *cr, GdkWindow *window)
void fl_view_renderer_paint_background(FlViewRenderer *self, cairo_t *cr)
static void wait_for_frame(FlViewRendererOpenGL *self, GdkWindow *window, gint scale_factor)
void gdk_gl_context_clear_current(GdkGLContext *context)
Definition mock_gtk.cc:162
gint gdk_window_get_scale_factor(GdkWindow *window)
Definition mock_gtk.cc:95
void gdk_gl_context_make_current(GdkGLContext *context)
Definition mock_gtk.cc:166
GdkWindow * gtk_widget_get_window(GtkWidget *widget)
Definition mock_gtk.cc:309

References fl_compositor_opengl_render(), fl_view_renderer_paint_background(), gdk_gl_context_clear_current(), gdk_gl_context_make_current(), gdk_window_get_scale_factor(), gtk_widget_get_window(), self, TRUE, wait_for_frame(), and window.

Referenced by fl_view_renderer_opengl_class_init().

◆ fl_view_renderer_opengl_finalize()

static void fl_view_renderer_opengl_finalize ( GObject *  object)
static

Definition at line 218 of file fl_view_renderer_opengl.cc.

218 {
219 FlViewRendererOpenGL* self = FL_VIEW_RENDERER_OPENGL(object);
220
221 // The compositor is released here rather than in dispose() so it outlives a
222 // forced dispose (e.g. gtk_widget_destroy()) and is only freed once the last
223 // reference is dropped. This keeps it alive for the raster thread, which
224 // holds a strong reference on the view (and thus this renderer) while
225 // presenting.
226 g_clear_object(&self->compositor);
227
228 G_OBJECT_CLASS(fl_view_renderer_opengl_parent_class)->finalize(object);
229}

References self.

Referenced by fl_view_renderer_opengl_class_init().

◆ fl_view_renderer_opengl_init()

static void fl_view_renderer_opengl_init ( FlViewRendererOpenGL *  self)
static

Definition at line 245 of file fl_view_renderer_opengl.cc.

245 {
246 g_mutex_init(&self->frame_mutex);
247}

References self.

◆ fl_view_renderer_opengl_new()

FlViewRendererOpenGL * fl_view_renderer_opengl_new ( FlEngine *  engine,
gboolean  sized_to_content 
)

Definition at line 249 of file fl_view_renderer_opengl.cc.

250 {
251 g_return_val_if_fail(FL_IS_ENGINE(engine), nullptr);
252
253 FlViewRendererOpenGL* self = FL_VIEW_RENDERER_OPENGL(
254 g_object_new(fl_view_renderer_opengl_get_type(), nullptr));
255 self->engine = FL_ENGINE(g_object_ref(engine));
256 self->sized_to_content = sized_to_content;
257 return self;
258}
FlutterEngine engine
Definition main.cc:84
G_BEGIN_DECLS gboolean sized_to_content

References engine, self, and sized_to_content.

Referenced by setup_engine().

◆ fl_view_renderer_opengl_present_layers()

static void fl_view_renderer_opengl_present_layers ( FlViewRenderer *  renderer,
const FlutterLayer **  layers,
size_t  layers_count 
)
static

Definition at line 185 of file fl_view_renderer_opengl.cc.

187 {
188 FlViewRendererOpenGL* self = FL_VIEW_RENDERER_OPENGL(renderer);
189
190 // Frames may be presented before the widget is realized and the compositor
191 // is set up; ignore them.
192 if (self->compositor == nullptr) {
193 return;
194 }
195
196 g_mutex_lock(&self->frame_mutex);
198 g_mutex_unlock(&self->frame_mutex);
199
200 // Wake up the GTK thread if it is waiting for this frame.
201 fl_task_runner_stop_wait(self->task_runner);
202
203 // Perform the redraw in the GTK thread.
204 g_idle_add(redraw_cb, g_object_ref(self));
205}
gboolean fl_compositor_opengl_composite_layers(FlCompositorOpenGL *self, const FlutterLayer **layers, size_t layers_count)
void fl_task_runner_stop_wait(FlTaskRunner *self)
const FlutterLayer size_t layers_count
const FlutterLayer ** layers

References fl_compositor_opengl_composite_layers(), fl_task_runner_stop_wait(), layers, layers_count, and self.

Referenced by fl_view_renderer_opengl_class_init().

◆ fl_view_renderer_opengl_realize()

static void fl_view_renderer_opengl_realize ( GtkWidget *  widget)
static

Definition at line 117 of file fl_view_renderer_opengl.cc.

117 {
118 FlViewRendererOpenGL* self = FL_VIEW_RENDERER_OPENGL(widget);
119
120 GTK_WIDGET_CLASS(fl_view_renderer_opengl_parent_class)->realize(widget);
121
122 g_autoptr(GError) error = nullptr;
123 self->render_context = gdk_window_create_gl_context(
124 gtk_widget_get_window(GTK_WIDGET(self)), &error);
125 if (self->render_context == nullptr) {
126 g_warning("Failed to create OpenGL context: %s", error->message);
127 return;
128 }
129
130 if (!gdk_gl_context_realize(self->render_context, &error)) {
131 g_warning("Failed to realize OpenGL context: %s", error->message);
132 g_clear_object(&self->render_context);
133 return;
134 }
135
136 // If using Wayland, then EGL is in use and we can access the frame
137 // from the Flutter context using EGLImage. If not (i.e. X11 using GLX)
138 // then we have to copy the texture via the CPU.
139 gboolean shareable =
140 GDK_IS_WAYLAND_DISPLAY(gtk_widget_get_display(GTK_WIDGET(self)));
141 self->task_runner =
142 FL_TASK_RUNNER(g_object_ref(fl_engine_get_task_runner(self->engine)));
143 self->compositor = fl_compositor_opengl_new(
145}
g_autoptr(FlEngine) engine
FlCompositorOpenGL * fl_compositor_opengl_new(FlOpenGLManager *opengl_manager, gboolean shareable)
G_BEGIN_DECLS gboolean shareable
FlTaskRunner * fl_engine_get_task_runner(FlEngine *self)
FlOpenGLManager * fl_engine_get_opengl_manager(FlEngine *self)
Definition fl_engine.cc:749
const uint8_t uint32_t uint32_t GError ** error
GdkDisplay * gtk_widget_get_display(GtkWidget *widget)
Definition mock_gtk.cc:253
GdkGLContext * gdk_window_create_gl_context(GdkWindow *window, GError **error)
Definition mock_gtk.cc:149
void gdk_gl_context_realize(GdkGLContext *context)
Definition mock_gtk.cc:158

References error, fl_compositor_opengl_new(), fl_engine_get_opengl_manager(), fl_engine_get_task_runner(), g_autoptr(), gdk_gl_context_realize(), gdk_window_create_gl_context(), gtk_widget_get_display(), gtk_widget_get_window(), self, and shareable.

Referenced by fl_view_renderer_opengl_class_init().

◆ G_DEFINE_TYPE()

G_DEFINE_TYPE ( FlViewRendererOpenGL  ,
fl_view_renderer_opengl  ,
fl_view_renderer_get_type()   
)

Definition at line 39 of file fl_view_renderer_opengl.cc.

44 {
45 g_autoptr(FlViewRendererOpenGL) self = FL_VIEW_RENDERER_OPENGL(user_data);
46
47 if (self->compositor == nullptr) {
48 return G_SOURCE_REMOVE;
49 }
50
51 fl_view_renderer_notify_frame(FL_VIEW_RENDERER(self));
52
53 // If Flutter is controlling the window size, then resize the view if
54 // necessary.
55 GtkWidget* render_widget = GTK_WIDGET(self);
56 GtkAllocation allocation;
57 gtk_widget_get_allocation(render_widget, &allocation);
58 gint scale_factor = gtk_widget_get_scale_factor(render_widget);
59 size_t width = allocation.width * scale_factor;
60 size_t height = allocation.height * scale_factor;
61 size_t frame_width, frame_height;
62 {
63 g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->frame_mutex);
64 fl_compositor_opengl_get_frame_size(self->compositor, &frame_width,
65 &frame_height);
66 }
67 gboolean frame_size_matches = width == frame_width && height == frame_height;
68 if (self->sized_to_content && !frame_size_matches) {
69 gtk_widget_set_size_request(render_widget, frame_width / scale_factor,
70 frame_height / scale_factor);
71 GtkWidget* toplevel = gtk_widget_get_toplevel(render_widget);
72 if (GTK_IS_WINDOW(toplevel)) {
73 // Resize to smallest size, so that the window will shrink to fit the new
74 // size of the render area.
75 gtk_window_resize(GTK_WINDOW(toplevel), 1, 1);
76 }
77 return G_SOURCE_REMOVE;
78 }
79
80 gtk_widget_queue_draw(render_widget);
81
82 return G_SOURCE_REMOVE;
83}
void fl_compositor_opengl_get_frame_size(FlCompositorOpenGL *self, size_t *width, size_t *height)
void fl_view_renderer_notify_frame(FlViewRenderer *self)
void gtk_widget_queue_draw(GtkWidget *widget)
Definition mock_gtk.cc:271
void gtk_window_resize(GtkWindow *window, gint width, gint height)
Definition mock_gtk.cc:207
void gtk_widget_get_allocation(GtkWidget *widget, GtkAllocation *allocation)
Definition mock_gtk.cc:245
GtkWidget * gtk_widget_get_toplevel(GtkWidget *widget)
Definition mock_gtk.cc:304
gint gtk_widget_get_scale_factor(GtkWidget *widget)
Definition mock_gtk.cc:258
int32_t height
int32_t width

References fl_compositor_opengl_get_frame_size(), fl_view_renderer_notify_frame(), g_autoptr(), gtk_widget_get_allocation(), gtk_widget_get_scale_factor(), gtk_widget_get_toplevel(), gtk_widget_queue_draw(), gtk_window_resize(), height, self, user_data, and width.

◆ wait_for_frame()

static void wait_for_frame ( FlViewRendererOpenGL *  self,
GdkWindow *  window,
gint  scale_factor 
)
static

Definition at line 88 of file fl_view_renderer_opengl.cc.

90 {
91 gint64 expiry_time = g_get_monotonic_time() + kRenderTimeoutMicroseconds;
92 while (true) {
93 size_t width = gdk_window_get_width(window) * scale_factor;
94 size_t height = gdk_window_get_height(window) * scale_factor;
95 size_t frame_width, frame_height;
96 fl_compositor_opengl_get_frame_size(self->compositor, &frame_width,
97 &frame_height);
98 if (frame_width == width && frame_height == height) {
99 break;
100 }
101
102 if (g_get_monotonic_time() > expiry_time) {
103 g_warning(
104 "Timed out waiting for OpenGL frame of size %zdx%zd (have "
105 "%zdx%zd)",
106 width, height, frame_width, frame_height);
107 break;
108 }
109
110 g_mutex_unlock(&self->frame_mutex);
111 fl_task_runner_wait(self->task_runner, expiry_time);
112 g_mutex_lock(&self->frame_mutex);
113 }
114}
void fl_task_runner_wait(FlTaskRunner *self, gint64 expiry_time)
static constexpr gint64 kRenderTimeoutMicroseconds
int gdk_window_get_width(GdkWindow *window)
Definition mock_gtk.cc:79
int gdk_window_get_height(GdkWindow *window)
Definition mock_gtk.cc:87

References fl_compositor_opengl_get_frame_size(), fl_task_runner_wait(), gdk_window_get_height(), gdk_window_get_width(), height, kRenderTimeoutMicroseconds, self, width, and window.

Referenced by fl_view_renderer_opengl_draw().

Variable Documentation

◆ kRenderTimeoutMicroseconds

constexpr gint64 kRenderTimeoutMicroseconds = 100000
staticconstexpr

Definition at line 15 of file fl_view_renderer_opengl.cc.

Referenced by wait_for_frame().