Flutter Linux Embedder
fl_view_renderer.cc File Reference

Go to the source code of this file.

Classes

struct  _FlViewRenderer
 

Enumerations

enum  {
  SIGNAL_FIRST_FRAME ,
  LAST_SIGNAL
}
 

Functions

static gboolean redraw_cb (gpointer user_data)
 
static void setup_opengl (FlViewRenderer *self)
 
static void setup_software (FlViewRenderer *self)
 
static void paint_background (FlViewRenderer *self, cairo_t *cr)
 
static void fl_view_renderer_realize (GtkWidget *widget)
 
static gboolean fl_view_renderer_draw (GtkWidget *widget, cairo_t *cr)
 
static void fl_view_renderer_dispose (GObject *object)
 
static void fl_view_renderer_finalize (GObject *object)
 
static void fl_view_renderer_class_init (FlViewRendererClass *klass)
 
static void fl_view_renderer_init (FlViewRenderer *self)
 
FlViewRenderer * fl_view_renderer_new (FlEngine *engine, gboolean sized_to_content)
 
void fl_view_renderer_set_background_color (FlViewRenderer *self, const GdkRGBA *color)
 
void fl_view_renderer_present_layers (FlViewRenderer *self, const FlutterLayer **layers, size_t layers_count)
 

Variables

static guint fl_view_renderer_signals [LAST_SIGNAL]
 

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
SIGNAL_FIRST_FRAME 
LAST_SIGNAL 

Definition at line 37 of file fl_view_renderer.cc.

@ LAST_SIGNAL
@ SIGNAL_FIRST_FRAME

Function Documentation

◆ fl_view_renderer_class_init()

static void fl_view_renderer_class_init ( FlViewRendererClass *  klass)
static

Definition at line 194 of file fl_view_renderer.cc.

194  {
195  G_OBJECT_CLASS(klass)->dispose = fl_view_renderer_dispose;
196  G_OBJECT_CLASS(klass)->finalize = fl_view_renderer_finalize;
197 
198  GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
199  widget_class->realize = fl_view_renderer_realize;
200  widget_class->draw = fl_view_renderer_draw;
201 
203  g_signal_new("first-frame", fl_view_renderer_get_type(),
204  G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
205 }
static gboolean fl_view_renderer_draw(GtkWidget *widget, cairo_t *cr)
static void fl_view_renderer_dispose(GObject *object)
static void fl_view_renderer_realize(GtkWidget *widget)
static void fl_view_renderer_finalize(GObject *object)
static guint fl_view_renderer_signals[LAST_SIGNAL]

References fl_view_renderer_dispose(), fl_view_renderer_draw(), fl_view_renderer_finalize(), fl_view_renderer_realize(), fl_view_renderer_signals, and SIGNAL_FIRST_FRAME.

◆ fl_view_renderer_dispose()

static void fl_view_renderer_dispose ( GObject *  object)
static

Definition at line 171 of file fl_view_renderer.cc.

171  {
172  FlViewRenderer* self = FL_VIEW_RENDERER(object);
173 
174  g_clear_object(&self->render_context);
175  g_clear_object(&self->engine);
176  g_clear_pointer(&self->background_color, gdk_rgba_free);
177 
178  G_OBJECT_CLASS(fl_view_renderer_parent_class)->dispose(object);
179 }

Referenced by fl_view_renderer_class_init().

◆ fl_view_renderer_draw()

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

Definition at line 145 of file fl_view_renderer.cc.

145  {
146  FlViewRenderer* self = FL_VIEW_RENDERER(widget);
147 
148  paint_background(self, cr);
149 
150  // The compositor is created when the widget is realized; if it is not yet
151  // available there is nothing to render beyond the background.
152  if (self->compositor == nullptr) {
153  return TRUE;
154  }
155 
156  if (self->render_context) {
157  gdk_gl_context_make_current(self->render_context);
158  }
159 
160  gboolean wait_for_frame = !self->sized_to_content;
161  gboolean result = fl_compositor_render(
162  self->compositor, cr, gtk_widget_get_window(widget), wait_for_frame);
163 
164  if (self->render_context) {
165  gdk_gl_context_clear_current();
166  }
167 
168  return result;
169 }
gboolean fl_compositor_render(FlCompositor *self, cairo_t *cr, GdkWindow *window, gboolean wait_for_frame)
return TRUE
static void paint_background(FlViewRenderer *self, cairo_t *cr)

References fl_compositor_render(), paint_background(), and TRUE.

Referenced by fl_view_renderer_class_init().

◆ fl_view_renderer_finalize()

static void fl_view_renderer_finalize ( GObject *  object)
static

Definition at line 181 of file fl_view_renderer.cc.

181  {
182  FlViewRenderer* self = FL_VIEW_RENDERER(object);
183 
184  // The compositor is released here rather than in dispose() so it outlives a
185  // forced dispose (e.g. gtk_widget_destroy()) and is only freed once the last
186  // reference is dropped. This keeps it alive for the raster thread, which
187  // holds a strong reference on the view (and thus this renderer) while
188  // presenting.
189  g_clear_object(&self->compositor);
190 
191  G_OBJECT_CLASS(fl_view_renderer_parent_class)->finalize(object);
192 }

Referenced by fl_view_renderer_class_init().

◆ fl_view_renderer_init()

static void fl_view_renderer_init ( FlViewRenderer *  self)
static

Definition at line 207 of file fl_view_renderer.cc.

207  {
208  GdkRGBA default_background = {
209  .red = 0.0, .green = 0.0, .blue = 0.0, .alpha = 1.0};
210  self->background_color = gdk_rgba_copy(&default_background);
211 }

◆ fl_view_renderer_new()

FlViewRenderer* fl_view_renderer_new ( FlEngine *  engine,
gboolean  sized_to_content 
)

Definition at line 213 of file fl_view_renderer.cc.

214  {
215  g_return_val_if_fail(FL_IS_ENGINE(engine), nullptr);
216 
217  FlViewRenderer* self =
218  FL_VIEW_RENDERER(g_object_new(fl_view_renderer_get_type(), nullptr));
219 
220  self->engine = FL_ENGINE(g_object_ref(engine));
221  self->sized_to_content = sized_to_content;
222 
223  return self;
224 }
G_BEGIN_DECLS gboolean sized_to_content

References sized_to_content.

Referenced by setup_engine().

◆ fl_view_renderer_present_layers()

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

fl_view_renderer_present_layers: @renderer: an #FlViewRenderer. @layers: layers to draw. @layers_count: number of layers.

Composites a frame into the renderer. This method can be called from any thread.

Definition at line 233 of file fl_view_renderer.cc.

235  {
236  g_return_if_fail(FL_IS_VIEW_RENDERER(self));
237 
238  // Frames may be presented before the widget is realized and the compositor
239  // is set up; ignore them.
240  if (self->compositor == nullptr) {
241  return;
242  }
243 
245 
246  // Perform the redraw in the GTK thread.
247  g_idle_add(redraw_cb, g_object_ref(self));
248 }
gboolean fl_compositor_present_layers(FlCompositor *self, const FlutterLayer **layers, size_t layers_count)
const FlutterLayer size_t layers_count
const FlutterLayer ** layers
static gboolean redraw_cb(gpointer user_data)

References fl_compositor_present_layers(), layers, layers_count, and redraw_cb().

Referenced by fl_view_present_layers().

◆ fl_view_renderer_realize()

static void fl_view_renderer_realize ( GtkWidget *  widget)
static

Definition at line 127 of file fl_view_renderer.cc.

127  {
128  FlViewRenderer* self = FL_VIEW_RENDERER(widget);
129 
130  GTK_WIDGET_CLASS(fl_view_renderer_parent_class)->realize(widget);
131 
132  switch (fl_engine_get_renderer_type(self->engine)) {
133  case kOpenGL:
134  setup_opengl(self);
135  break;
136  case kSoftware:
137  setup_software(self);
138  break;
139  default:
140  break;
141  }
142 }
FlutterRendererType fl_engine_get_renderer_type(FlEngine *self)
Definition: fl_engine.cc:744
static void setup_software(FlViewRenderer *self)
static void setup_opengl(FlViewRenderer *self)

References fl_engine_get_renderer_type(), setup_opengl(), and setup_software().

Referenced by fl_view_renderer_class_init().

◆ fl_view_renderer_set_background_color()

void fl_view_renderer_set_background_color ( FlViewRenderer *  renderer,
const GdkRGBA *  color 
)

fl_view_renderer_set_background_color: @renderer: an #FlViewRenderer. @color: the background color.

Sets the background color drawn behind the Flutter frame.

Definition at line 226 of file fl_view_renderer.cc.

227  {
228  g_return_if_fail(FL_IS_VIEW_RENDERER(self));
229  gdk_rgba_free(self->background_color);
230  self->background_color = gdk_rgba_copy(color);
231 }

Referenced by fl_view_set_background_color().

◆ paint_background()

static void paint_background ( FlViewRenderer *  self,
cairo_t *  cr 
)
static

Definition at line 114 of file fl_view_renderer.cc.

114  {
115  // Don't bother drawing if fully transparent - the widget above this will
116  // already be drawn by GTK.
117  if (self->background_color->red == 0 && self->background_color->green == 0 &&
118  self->background_color->blue == 0 && self->background_color->alpha == 0) {
119  return;
120  }
121 
122  gdk_cairo_set_source_rgba(cr, self->background_color);
123  cairo_paint(cr);
124 }

Referenced by fl_view_renderer_draw().

◆ redraw_cb()

static gboolean redraw_cb ( gpointer  user_data)
static

Definition at line 44 of file fl_view_renderer.cc.

44  {
45  g_autoptr(FlViewRenderer) self = FL_VIEW_RENDERER(user_data);
46 
47  if (self->compositor == nullptr) {
48  return G_SOURCE_REMOVE;
49  }
50 
51  if (!self->have_first_frame) {
52  self->have_first_frame = TRUE;
53  g_signal_emit(self, fl_view_renderer_signals[SIGNAL_FIRST_FRAME], 0);
54  }
55 
56  // If Flutter is controlling the window size, then resize the view if
57  // necessary.
58  GtkWidget* render_widget = GTK_WIDGET(self);
59  GtkAllocation allocation;
60  gtk_widget_get_allocation(render_widget, &allocation);
61  gint scale_factor = gtk_widget_get_scale_factor(render_widget);
62  size_t width = allocation.width * scale_factor;
63  size_t height = allocation.height * scale_factor;
64  size_t frame_width, frame_height;
65  fl_compositor_get_frame_size(self->compositor, &frame_width, &frame_height);
66  gboolean frame_size_matches = width == frame_width && height == frame_height;
67  if (self->sized_to_content && !frame_size_matches) {
68  gtk_widget_set_size_request(render_widget, frame_width / scale_factor,
69  frame_height / scale_factor);
70  GtkWidget* toplevel = gtk_widget_get_toplevel(render_widget);
71  if (GTK_IS_WINDOW(toplevel)) {
72  // Resize to smallest size, so that the window will shrink to fit the new
73  // size of the render area.
74  gtk_window_resize(GTK_WINDOW(toplevel), 1, 1);
75  }
76  return G_SOURCE_REMOVE;
77  }
78 
79  gtk_widget_queue_draw(render_widget);
80 
81  return G_SOURCE_REMOVE;
82 }
g_autoptr(FlEngine) engine
const char FlTextDirection FlAssertiveness gpointer user_data
void fl_compositor_get_frame_size(FlCompositor *self, size_t *width, size_t *height)
FlFramebuffer double double int int height
FlFramebuffer double double int width

References fl_compositor_get_frame_size(), fl_view_renderer_signals, g_autoptr(), height, SIGNAL_FIRST_FRAME, TRUE, user_data, and width.

Referenced by fl_view_renderer_present_layers().

◆ setup_opengl()

static void setup_opengl ( FlViewRenderer *  self)
static

Definition at line 84 of file fl_view_renderer.cc.

84  {
85  g_autoptr(GError) error = nullptr;
86 
87  self->render_context = gdk_window_create_gl_context(
88  gtk_widget_get_window(GTK_WIDGET(self)), &error);
89  if (self->render_context == nullptr) {
90  g_warning("Failed to create OpenGL context: %s", error->message);
91  return;
92  }
93 
94  if (!gdk_gl_context_realize(self->render_context, &error)) {
95  g_warning("Failed to realize OpenGL context: %s", error->message);
96  return;
97  }
98 
99  // If using Wayland, then EGL is in use and we can access the frame
100  // from the Flutter context using EGLImage. If not (i.e. X11 using GLX)
101  // then we have to copy the texture via the CPU.
102  gboolean shareable =
103  GDK_IS_WAYLAND_DISPLAY(gtk_widget_get_display(GTK_WIDGET(self)));
104  self->compositor = FL_COMPOSITOR(fl_compositor_opengl_new(
105  fl_engine_get_task_runner(self->engine),
106  fl_engine_get_opengl_manager(self->engine), shareable));
107 }
FlCompositorOpenGL * fl_compositor_opengl_new(FlTaskRunner *task_runner, FlOpenGLManager *opengl_manager, gboolean shareable)
G_BEGIN_DECLS FlOpenGLManager gboolean shareable
FlOpenGLManager * fl_engine_get_opengl_manager(FlEngine *self)
Definition: fl_engine.cc:749
FlTaskRunner * fl_engine_get_task_runner(FlEngine *self)
Definition: fl_engine.cc:1528
const uint8_t uint32_t uint32_t GError ** error

References error, fl_compositor_opengl_new(), fl_engine_get_opengl_manager(), fl_engine_get_task_runner(), g_autoptr(), and shareable.

Referenced by fl_view_renderer_realize().

◆ setup_software()

static void setup_software ( FlViewRenderer *  self)
static

Definition at line 109 of file fl_view_renderer.cc.

109  {
110  self->compositor = FL_COMPOSITOR(
112 }
FlCompositorSoftware * fl_compositor_software_new(FlTaskRunner *task_runner)

References fl_compositor_software_new(), and fl_engine_get_task_runner().

Referenced by fl_view_renderer_realize().

Variable Documentation

◆ fl_view_renderer_signals

guint fl_view_renderer_signals[LAST_SIGNAL]
static

Definition at line 39 of file fl_view_renderer.cc.

Referenced by fl_view_renderer_class_init(), and redraw_cb().