Flutter Engine
fl_renderer.cc File Reference
#include "fl_renderer.h"
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/linux/egl_utils.h"

Go to the source code of this file.

Classes

struct  FlRendererPrivate
 

Functions

static void fl_renderer_class_init (FlRendererClass *klass)
 
static void fl_renderer_init (FlRenderer *self)
 
static gboolean setup_egl_display (FlRenderer *self, GError **error)
 
static gboolean setup_gdk_window (FlRenderer *self, GtkWidget *widget, GError **error)
 
static gboolean setup_egl_surfaces (FlRenderer *self, GtkWidget *widget, GError **error)
 
gboolean fl_renderer_start (FlRenderer *self, GtkWidget *widget, GError **error)
 
void fl_renderer_set_geometry (FlRenderer *self, GdkRectangle *geometry, gint scale)
 
void * fl_renderer_get_proc_address (FlRenderer *self, const char *name)
 
gboolean fl_renderer_make_current (FlRenderer *self, GError **error)
 
gboolean fl_renderer_make_resource_current (FlRenderer *self, GError **error)
 
gboolean fl_renderer_clear_current (FlRenderer *self, GError **error)
 
guint32 fl_renderer_get_fbo (FlRenderer *self)
 
gboolean fl_renderer_present (FlRenderer *self, GError **error)
 

Function Documentation

◆ fl_renderer_class_init()

static void fl_renderer_class_init ( FlRendererClass *  klass)
static

Definition at line 24 of file fl_renderer.cc.

24 {}

◆ fl_renderer_clear_current()

gboolean fl_renderer_clear_current ( FlRenderer *  renderer,
GError **  error 
)

fl_renderer_clear_current: : an #FlRenderer. : (allow-none): #GError location to store the error occurring, or NULL to ignore.

Clears the current rendering context.

Returns TRUE if successful.

Definition at line 261 of file fl_renderer.cc.

References FlRendererPrivate::egl_display, egl_error_to_string(), eglGetError(), eglMakeCurrent(), FL_RENDERER_ERROR_FAILED, fl_renderer_error_quark(), and TRUE.

Referenced by fl_engine_gl_clear_current().

261  {
262  FlRendererPrivate* priv =
263  static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));
264 
265  if (!eglMakeCurrent(priv->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
266  EGL_NO_CONTEXT)) {
268  "Failed to clear EGL context: %s",
270  return FALSE;
271  }
272 
273  return TRUE;
274 }
FlMethodResponse GError ** error
GQuark fl_renderer_error_quark(void) G_GNUC_CONST
EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
Definition: mock_egl.cc:306
EGLint eglGetError()
Definition: mock_egl.cc:252
const gchar * egl_error_to_string(EGLint error)
Definition: egl_utils.cc:89
EGLDisplay egl_display
Definition: fl_renderer.cc:13
return TRUE
Definition: fl_view.cc:107

◆ fl_renderer_get_fbo()

guint32 fl_renderer_get_fbo ( FlRenderer *  renderer)

fl_renderer_get_fbo: : an #FlRenderer.

Gets the frame buffer object to render to.

Returns: a frame buffer object index.

Definition at line 276 of file fl_renderer.cc.

Referenced by fl_engine_gl_get_fbo().

276  {
277  // There is only one frame buffer object - always return that.
278  return 0;
279 }

◆ fl_renderer_get_proc_address()

void* fl_renderer_get_proc_address ( FlRenderer *  self,
const char *  name 
)

Definition at line 212 of file fl_renderer.cc.

References eglGetProcAddress.

Referenced by fl_engine_gl_proc_resolver().

212  {
213  return reinterpret_cast<void*>(eglGetProcAddress(name));
214 }
void(*)(void) eglGetProcAddress(const char *procname)
Definition: mock_egl.cc:258
const char * name
Definition: fuchsia.cc:50

◆ fl_renderer_init()

static void fl_renderer_init ( FlRenderer *  self)
static

Definition at line 26 of file fl_renderer.cc.

26 {}

◆ fl_renderer_make_current()

gboolean fl_renderer_make_current ( FlRenderer *  renderer,
GError **  error 
)

fl_renderer_make_current: : an #FlRenderer. : (allow-none): #GError location to store the error occurring, or NULL to ignore.

Makes the rendering context current.

Returns TRUE if successful.

Definition at line 216 of file fl_renderer.cc.

References FlRendererPrivate::egl_context, FlRendererPrivate::egl_display, egl_error_to_string(), FlRendererPrivate::egl_surface, eglGetError(), eglMakeCurrent(), FL_RENDERER_ERROR_FAILED, fl_renderer_error_quark(), and TRUE.

Referenced by fl_engine_gl_make_current().

216  {
217  FlRendererPrivate* priv =
218  static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));
219 
220  if (priv->egl_surface == EGL_NO_SURFACE ||
221  priv->egl_context == EGL_NO_CONTEXT) {
223  "Failed to make EGL context current: No surface created");
224  return FALSE;
225  }
226 
227  if (!eglMakeCurrent(priv->egl_display, priv->egl_surface, priv->egl_surface,
228  priv->egl_context)) {
230  "Failed to make EGL context current: %s",
232  return FALSE;
233  }
234 
235  return TRUE;
236 }
FlMethodResponse GError ** error
EGLSurface egl_surface
Definition: fl_renderer.cc:15
GQuark fl_renderer_error_quark(void) G_GNUC_CONST
EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
Definition: mock_egl.cc:306
EGLint eglGetError()
Definition: mock_egl.cc:252
const gchar * egl_error_to_string(EGLint error)
Definition: egl_utils.cc:89
EGLDisplay egl_display
Definition: fl_renderer.cc:13
EGLContext egl_context
Definition: fl_renderer.cc:16
return TRUE
Definition: fl_view.cc:107

◆ fl_renderer_make_resource_current()

gboolean fl_renderer_make_resource_current ( FlRenderer *  renderer,
GError **  error 
)

fl_renderer_make_resource_current: : an #FlRenderer. : (allow-none): #GError location to store the error occurring, or NULL to ignore.

Makes the resource rendering context current.

Returns TRUE if successful.

Definition at line 238 of file fl_renderer.cc.

References FlRendererPrivate::egl_display, egl_error_to_string(), eglGetError(), eglMakeCurrent(), FL_RENDERER_ERROR_FAILED, fl_renderer_error_quark(), FlRendererPrivate::resource_context, FlRendererPrivate::resource_surface, and TRUE.

Referenced by fl_engine_gl_make_resource_current().

238  {
239  FlRendererPrivate* priv =
240  static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));
241 
242  if (priv->resource_surface == EGL_NO_SURFACE ||
243  priv->resource_context == EGL_NO_CONTEXT) {
244  g_set_error(
246  "Failed to make EGL resource context current: No surface created");
247  return FALSE;
248  }
249 
250  if (!eglMakeCurrent(priv->egl_display, priv->resource_surface,
251  priv->resource_surface, priv->resource_context)) {
253  "Failed to make EGL resource context current: %s",
255  return FALSE;
256  }
257 
258  return TRUE;
259 }
EGLContext resource_context
Definition: fl_renderer.cc:19
FlMethodResponse GError ** error
GQuark fl_renderer_error_quark(void) G_GNUC_CONST
EGLBoolean eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
Definition: mock_egl.cc:306
EGLint eglGetError()
Definition: mock_egl.cc:252
const gchar * egl_error_to_string(EGLint error)
Definition: egl_utils.cc:89
EGLDisplay egl_display
Definition: fl_renderer.cc:13
EGLSurface resource_surface
Definition: fl_renderer.cc:18
return TRUE
Definition: fl_view.cc:107

◆ fl_renderer_present()

gboolean fl_renderer_present ( FlRenderer *  renderer,
GError **  error 
)

fl_renderer_present: : an #FlRenderer. : (allow-none): #GError location to store the error occurring, or NULL to ignore.

Presents the current frame.

Returns TRUE if successful.

Definition at line 281 of file fl_renderer.cc.

References FlRendererPrivate::egl_display, egl_error_to_string(), FlRendererPrivate::egl_surface, eglGetError(), eglSwapBuffers(), FL_RENDERER_ERROR_FAILED, fl_renderer_error_quark(), and TRUE.

Referenced by fl_engine_gl_present().

281  {
282  FlRendererPrivate* priv =
283  static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));
284 
285  if (!eglSwapBuffers(priv->egl_display, priv->egl_surface)) {
287  "Failed to swap EGL buffers: %s",
289  return FALSE;
290  }
291 
292  return TRUE;
293 }
FlMethodResponse GError ** error
EGLSurface egl_surface
Definition: fl_renderer.cc:15
GQuark fl_renderer_error_quark(void) G_GNUC_CONST
EGLint eglGetError()
Definition: mock_egl.cc:252
const gchar * egl_error_to_string(EGLint error)
Definition: egl_utils.cc:89
EGLDisplay egl_display
Definition: fl_renderer.cc:13
return TRUE
Definition: fl_view.cc:107
EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
Definition: mock_egl.cc:316

◆ fl_renderer_set_geometry()

void fl_renderer_set_geometry ( FlRenderer *  renderer,
GdkRectangle *  geometry,
gint  scale 
)

fl_renderer_set_geometry: : an #FlRenderer. : New size and position (unscaled) of the EGL window. : Scale of the window.

Definition at line 202 of file fl_renderer.cc.

Referenced by fl_view_geometry_changed().

204  {
205  g_return_if_fail(FL_IS_RENDERER(self));
206 
207  if (FL_RENDERER_GET_CLASS(self)->set_geometry) {
208  FL_RENDERER_GET_CLASS(self)->set_geometry(self, geometry, scale);
209  }
210 }

◆ fl_renderer_start()

gboolean fl_renderer_start ( FlRenderer *  renderer,
GtkWidget *  widget,
GError **  error 
)

fl_renderer_start: : an #FlRenderer. : the widget Flutter is renderering to. : (allow-none): #GError location to store the error occurring, or NULL to ignore.

Start the renderer.

Returns: TRUE if successfully started.

Definition at line 182 of file fl_renderer.cc.

References setup_egl_display(), setup_egl_surfaces(), setup_gdk_window(), and TRUE.

Referenced by fl_view_realize().

184  {
185  g_return_val_if_fail(FL_IS_RENDERER(self), FALSE);
186 
187  if (!setup_egl_display(self, error)) {
188  return FALSE;
189  }
190 
191  if (!setup_gdk_window(self, widget, error)) {
192  return FALSE;
193  }
194 
195  if (!setup_egl_surfaces(self, widget, error)) {
196  return FALSE;
197  }
198 
199  return TRUE;
200 }
FlMethodResponse GError ** error
static gboolean setup_egl_display(FlRenderer *self, GError **error)
Definition: fl_renderer.cc:29
static gboolean setup_gdk_window(FlRenderer *self, GtkWidget *widget, GError **error)
Definition: fl_renderer.cc:94
return TRUE
Definition: fl_view.cc:107
static gboolean setup_egl_surfaces(FlRenderer *self, GtkWidget *widget, GError **error)
Definition: fl_renderer.cc:142

◆ setup_egl_display()

static gboolean setup_egl_display ( FlRenderer *  self,
GError **  error 
)
static

Definition at line 29 of file fl_renderer.cc.

References FlRendererPrivate::egl_config, egl_config_to_string(), FlRendererPrivate::egl_display, egl_error_to_string(), eglBindAPI(), eglChooseConfig(), eglGetError(), eglInitialize(), FL_RENDERER_ERROR_FAILED, fl_renderer_error_quark(), and TRUE.

Referenced by fl_renderer_start().

29  {
30  FlRendererPrivate* priv =
31  static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));
32 
33  if (priv->egl_display != EGL_NO_DISPLAY) {
35  "EGL display already set up");
36  return FALSE;
37  }
38 
39  priv->egl_display = FL_RENDERER_GET_CLASS(self)->create_display(self);
40 
41  if (priv->egl_display == EGL_NO_DISPLAY) {
43  "Failed to create EGL display");
44  return FALSE;
45  }
46 
47  if (!eglInitialize(priv->egl_display, nullptr, nullptr)) {
49  "Failed to initialze EGL");
50  return FALSE;
51  }
52 
53  EGLint attributes[] = {EGL_RENDERABLE_TYPE,
54  EGL_OPENGL_ES2_BIT,
55  EGL_RED_SIZE,
56  8,
57  EGL_GREEN_SIZE,
58  8,
59  EGL_BLUE_SIZE,
60  8,
61  EGL_ALPHA_SIZE,
62  8,
63  EGL_NONE};
64  EGLint n_config;
65  if (!eglChooseConfig(priv->egl_display, attributes, &priv->egl_config, 1,
66  &n_config)) {
68  "Failed to choose EGL config: %s",
70  return FALSE;
71  }
72 
73  if (n_config == 0) {
75  "Failed to find appropriate EGL config: %s",
77  return FALSE;
78  }
79 
80  if (!eglBindAPI(EGL_OPENGL_ES_API)) {
81  EGLint egl_error = eglGetError(); // Must be before egl_config_to_string().
82  g_autofree gchar* config_string =
85  "Failed to bind EGL OpenGL ES API using configuration (%s): %s",
86  config_string, egl_error_to_string(egl_error));
87  return FALSE;
88  }
89 
90  return TRUE;
91 }
FlMethodResponse GError ** error
EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
Definition: mock_egl.cc:263
EGLConfig egl_config
Definition: fl_renderer.cc:14
EGLBoolean eglBindAPI(EGLenum api)
Definition: mock_egl.cc:91
GQuark fl_renderer_error_quark(void) G_GNUC_CONST
EGLint eglGetError()
Definition: mock_egl.cc:252
gchar * egl_config_to_string(EGLDisplay display, EGLConfig config)
Definition: egl_utils.cc:126
const gchar * egl_error_to_string(EGLint error)
Definition: egl_utils.cc:89
EGLDisplay egl_display
Definition: fl_renderer.cc:13
return TRUE
Definition: fl_view.cc:107
EGLBoolean eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
Definition: mock_egl.cc:95

◆ setup_egl_surfaces()

static gboolean setup_egl_surfaces ( FlRenderer *  self,
GtkWidget *  widget,
GError **  error 
)
static

Definition at line 142 of file fl_renderer.cc.

References FlRendererPrivate::egl_config, egl_config_to_string(), FlRendererPrivate::egl_context, FlRendererPrivate::egl_display, egl_error_to_string(), FlRendererPrivate::egl_surface, eglCreateContext(), eglGetError(), FL_RENDERER_ERROR_FAILED, fl_renderer_error_quark(), FlRendererPrivate::resource_context, FlRendererPrivate::resource_surface, and TRUE.

Referenced by fl_renderer_start().

144  {
145  FlRendererPrivate* priv =
146  static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));
147 
148  if (priv->egl_surface != EGL_NO_SURFACE ||
149  priv->resource_surface != EGL_NO_SURFACE) {
151  "setup_egl_surfaces() called after surfaces already created");
152  return FALSE;
153  }
154 
155  if (!FL_RENDERER_GET_CLASS(self)->create_surfaces(
156  self, widget, priv->egl_display, priv->egl_config, &priv->egl_surface,
157  &priv->resource_surface, error)) {
158  return FALSE;
159  }
160 
161  EGLint context_attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
162 
163  priv->egl_context = eglCreateContext(priv->egl_display, priv->egl_config,
164  EGL_NO_CONTEXT, context_attributes);
165  priv->resource_context =
167  context_attributes);
168  if (priv->egl_context == EGL_NO_CONTEXT ||
169  priv->resource_context == EGL_NO_CONTEXT) {
170  EGLint egl_error = eglGetError(); // Must be before egl_config_to_string().
171  g_autofree gchar* config_string =
174  "Failed to create EGL contexts using configuration (%s): %s",
175  config_string, egl_error_to_string(egl_error));
176  return FALSE;
177  }
178 
179  return TRUE;
180 }
EGLContext resource_context
Definition: fl_renderer.cc:19
FlMethodResponse GError ** error
EGLSurface egl_surface
Definition: fl_renderer.cc:15
EGLConfig egl_config
Definition: fl_renderer.cc:14
EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
Definition: mock_egl.cc:121
GQuark fl_renderer_error_quark(void) G_GNUC_CONST
EGLint eglGetError()
Definition: mock_egl.cc:252
gchar * egl_config_to_string(EGLDisplay display, EGLConfig config)
Definition: egl_utils.cc:126
const gchar * egl_error_to_string(EGLint error)
Definition: egl_utils.cc:89
EGLDisplay egl_display
Definition: fl_renderer.cc:13
EGLSurface resource_surface
Definition: fl_renderer.cc:18
EGLContext egl_context
Definition: fl_renderer.cc:16
return TRUE
Definition: fl_view.cc:107

◆ setup_gdk_window()

static gboolean setup_gdk_window ( FlRenderer *  self,
GtkWidget *  widget,
GError **  error 
)
static

Definition at line 94 of file fl_renderer.cc.

References FlRendererPrivate::egl_config, FlRendererPrivate::egl_display, FL_RENDERER_ERROR_FAILED, fl_renderer_error_quark(), and TRUE.

Referenced by fl_renderer_start().

96  {
97  FlRendererPrivate* priv =
98  static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));
99 
100  if (priv->egl_display == EGL_NO_DISPLAY) {
102  "Can not set up GDK window: EGL display not created");
103  return FALSE;
104  }
105 
106  GtkAllocation allocation;
107  gtk_widget_get_allocation(widget, &allocation);
108 
109  GdkWindowAttr window_attributes;
110  window_attributes.window_type = GDK_WINDOW_CHILD;
111  window_attributes.x = allocation.x;
112  window_attributes.y = allocation.y;
113  window_attributes.width = allocation.width;
114  window_attributes.height = allocation.height;
115  window_attributes.wclass = GDK_INPUT_OUTPUT;
116  window_attributes.event_mask =
117  gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK |
118  GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK |
119  GDK_BUTTON_RELEASE_MASK | GDK_SCROLL_MASK | GDK_SMOOTH_SCROLL_MASK |
120  GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK;
121 
122  gint window_attributes_mask = GDK_WA_X | GDK_WA_Y;
123 
124  if (FL_RENDERER_GET_CLASS(self)->setup_window_attr) {
125  if (!FL_RENDERER_GET_CLASS(self)->setup_window_attr(
126  self, widget, priv->egl_display, priv->egl_config,
127  &window_attributes, &window_attributes_mask, error)) {
128  return FALSE;
129  }
130  }
131 
132  GdkWindow* window =
133  gdk_window_new(gtk_widget_get_parent_window(widget), &window_attributes,
134  window_attributes_mask);
135  gtk_widget_register_window(widget, window);
136  gtk_widget_set_window(widget, window);
137 
138  return TRUE;
139 }
FlMethodResponse GError ** error
EGLConfig egl_config
Definition: fl_renderer.cc:14
GQuark fl_renderer_error_quark(void) G_GNUC_CONST
EGLDisplay egl_display
Definition: fl_renderer.cc:13
return TRUE
Definition: fl_view.cc:107