Flutter Linux Embedder
fl_renderer.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 
5 #include "fl_renderer.h"
6 
7 #include <epoxy/egl.h>
8 #include <epoxy/gl.h>
9 
10 #include "flutter/common/constants.h"
11 #include "flutter/shell/platform/embedder/embedder.h"
14 
15 // Vertex shader to draw Flutter window contents.
16 static const char* vertex_shader_src =
17  "attribute vec2 position;\n"
18  "attribute vec2 in_texcoord;\n"
19  "varying vec2 texcoord;\n"
20  "\n"
21  "void main() {\n"
22  " gl_Position = vec4(position, 0, 1);\n"
23  " texcoord = in_texcoord;\n"
24  "}\n";
25 
26 // Fragment shader to draw Flutter window contents.
27 static const char* fragment_shader_src =
28  "#ifdef GL_ES\n"
29  "precision mediump float;\n"
30  "#endif\n"
31  "\n"
32  "uniform sampler2D texture;\n"
33  "varying vec2 texcoord;\n"
34  "\n"
35  "void main() {\n"
36  " gl_FragColor = texture2D(texture, texcoord);\n"
37  "}\n";
38 
39 G_DEFINE_QUARK(fl_renderer_error_quark, fl_renderer_error)
40 
41 typedef struct {
42  // Engine we are rendering.
43  GWeakRef engine;
44 
45  // Flag to track lazy initialization.
46  gboolean initialized;
47 
48  // The pixel format passed to the engine.
49  GLint sized_format;
50 
51  // The format used to create textures.
53 
54  // Views being rendered.
55  GHashTable* views;
56 
57  // target dimension for resizing
60 
61  // whether the renderer waits for frame render
63 
64  // true if frame was completed; resizing is not synchronized until first frame
65  // was rendered
67 
68  // True if we can use glBlitFramebuffer.
70 
71  // Shader program.
72  GLuint program;
73 
74  // Framebuffers to render keyed by view ID.
77 
78 G_DEFINE_TYPE_WITH_PRIVATE(FlRenderer, fl_renderer, G_TYPE_OBJECT)
79 
80 static void free_weak_ref(gpointer value) {
81  GWeakRef* ref = static_cast<GWeakRef*>(value);
82  g_weak_ref_clear(ref);
83  free(ref);
84 }
85 
86 // Check if running on an NVIDIA driver.
87 static gboolean is_nvidia() {
88  const gchar* vendor = reinterpret_cast<const gchar*>(glGetString(GL_VENDOR));
89  return strstr(vendor, "NVIDIA") != nullptr;
90 }
91 
92 // Check if running on an Vivante Corporation driver.
93 static gboolean is_vivante() {
94  const gchar* vendor = reinterpret_cast<const gchar*>(glGetString(GL_VENDOR));
95  return strstr(vendor, "Vivante Corporation") != nullptr;
96 }
97 
98 // Returns the log for the given OpenGL shader. Must be freed by the caller.
99 static gchar* get_shader_log(GLuint shader) {
100  GLint log_length;
101  gchar* log;
102 
103  glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
104 
105  log = static_cast<gchar*>(g_malloc(log_length + 1));
106  glGetShaderInfoLog(shader, log_length, nullptr, log);
107 
108  return log;
109 }
110 
111 // Returns the log for the given OpenGL program. Must be freed by the caller.
112 static gchar* get_program_log(GLuint program) {
113  GLint log_length;
114  gchar* log;
115 
116  glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
117 
118  log = static_cast<gchar*>(g_malloc(log_length + 1));
119  glGetProgramInfoLog(program, log_length, nullptr, log);
120 
121  return log;
122 }
123 
124 /// Converts a pixel co-ordinate from 0..pixels to OpenGL -1..1.
125 static GLfloat pixels_to_gl_coords(GLfloat position, GLfloat pixels) {
126  return (2.0 * position / pixels) - 1.0;
127 }
128 
129 // Perform single run OpenGL initialization.
130 static void initialize(FlRenderer* self) {
131  FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
132  fl_renderer_get_instance_private(self));
133 
134  if (priv->initialized) {
135  return;
136  }
137  priv->initialized = TRUE;
138 
139  if (epoxy_has_gl_extension("GL_EXT_texture_format_BGRA8888")) {
140  priv->sized_format = GL_BGRA8_EXT;
141  priv->general_format = GL_BGRA_EXT;
142  } else {
143  priv->sized_format = GL_RGBA8;
144  priv->general_format = GL_RGBA;
145  }
146 }
147 
148 static void fl_renderer_unblock_main_thread(FlRenderer* self) {
149  FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
150  fl_renderer_get_instance_private(self));
151  if (priv->blocking_main_thread) {
152  priv->blocking_main_thread = false;
153 
154  g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&priv->engine));
155  if (engine != nullptr) {
157  }
158  }
159 }
160 
161 static void setup_shader(FlRenderer* self) {
162  FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
163  fl_renderer_get_instance_private(self));
164 
165  GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
166  glShaderSource(vertex_shader, 1, &vertex_shader_src, nullptr);
167  glCompileShader(vertex_shader);
168  GLint vertex_compile_status;
169  glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &vertex_compile_status);
170  if (vertex_compile_status == GL_FALSE) {
171  g_autofree gchar* shader_log = get_shader_log(vertex_shader);
172  g_warning("Failed to compile vertex shader: %s", shader_log);
173  }
174 
175  GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
176  glShaderSource(fragment_shader, 1, &fragment_shader_src, nullptr);
177  glCompileShader(fragment_shader);
178  GLint fragment_compile_status;
179  glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &fragment_compile_status);
180  if (fragment_compile_status == GL_FALSE) {
181  g_autofree gchar* shader_log = get_shader_log(fragment_shader);
182  g_warning("Failed to compile fragment shader: %s", shader_log);
183  }
184 
185  priv->program = glCreateProgram();
186  glAttachShader(priv->program, vertex_shader);
187  glAttachShader(priv->program, fragment_shader);
188  glLinkProgram(priv->program);
189 
190  GLint link_status;
191  glGetProgramiv(priv->program, GL_LINK_STATUS, &link_status);
192  if (link_status == GL_FALSE) {
193  g_autofree gchar* program_log = get_program_log(priv->program);
194  g_warning("Failed to link program: %s", program_log);
195  }
196 
197  glDeleteShader(vertex_shader);
198  glDeleteShader(fragment_shader);
199 }
200 
201 static void render_with_blit(FlRenderer* self, GPtrArray* framebuffers) {
202  // Disable the scissor test as it can affect blit operations.
203  // Prevents regressions like: https://github.com/flutter/flutter/issues/140828
204  // See OpenGL specification version 4.6, section 18.3.1.
205  glDisable(GL_SCISSOR_TEST);
206 
207  for (guint i = 0; i < framebuffers->len; i++) {
208  FlFramebuffer* framebuffer =
209  FL_FRAMEBUFFER(g_ptr_array_index(framebuffers, i));
210 
211  GLuint framebuffer_id = fl_framebuffer_get_id(framebuffer);
212  glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer_id);
213  size_t width = fl_framebuffer_get_width(framebuffer);
214  size_t height = fl_framebuffer_get_height(framebuffer);
215  glBlitFramebuffer(0, 0, width, height, 0, 0, width, height,
216  GL_COLOR_BUFFER_BIT, GL_NEAREST);
217  }
218  glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
219 }
220 
221 static void render_with_textures(FlRenderer* self,
222  GPtrArray* framebuffers,
223  int width,
224  int height) {
225  FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
226  fl_renderer_get_instance_private(self));
227 
228  // Save bindings that are set by this function. All bindings must be restored
229  // to their original values because Skia expects that its bindings have not
230  // been altered.
231  GLint saved_texture_binding;
232  glGetIntegerv(GL_TEXTURE_BINDING_2D, &saved_texture_binding);
233  GLint saved_vao_binding;
234  glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &saved_vao_binding);
235  GLint saved_array_buffer_binding;
236  glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &saved_array_buffer_binding);
237 
238  glEnable(GL_BLEND);
239  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
240 
241  glUseProgram(priv->program);
242 
243  for (guint i = 0; i < framebuffers->len; i++) {
244  FlFramebuffer* framebuffer =
245  FL_FRAMEBUFFER(g_ptr_array_index(framebuffers, i));
246 
247  GLuint texture_id = fl_framebuffer_get_texture_id(framebuffer);
248  glBindTexture(GL_TEXTURE_2D, texture_id);
249 
250  // Translate into OpenGL co-ordinates
251  size_t texture_width = fl_framebuffer_get_width(framebuffer);
252  size_t texture_height = fl_framebuffer_get_height(framebuffer);
253  GLfloat x0 = pixels_to_gl_coords(0, width);
254  GLfloat y0 = pixels_to_gl_coords(height - texture_height, height);
255  GLfloat x1 = pixels_to_gl_coords(texture_width, width);
256  GLfloat y1 = pixels_to_gl_coords(height, height);
257  GLfloat vertex_data[] = {x0, y0, 0, 0, x1, y1, 1, 1, x0, y1, 0, 1,
258  x0, y0, 0, 0, x1, y0, 1, 0, x1, y1, 1, 1};
259 
260  GLuint vao, vertex_buffer;
261  glGenVertexArrays(1, &vao);
262  glBindVertexArray(vao);
263  glGenBuffers(1, &vertex_buffer);
264  glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
265  glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data,
266  GL_STATIC_DRAW);
267  GLint position_index = glGetAttribLocation(priv->program, "position");
268  glEnableVertexAttribArray(position_index);
269  glVertexAttribPointer(position_index, 2, GL_FLOAT, GL_FALSE,
270  sizeof(GLfloat) * 4, 0);
271  GLint texcoord_index = glGetAttribLocation(priv->program, "in_texcoord");
272  glEnableVertexAttribArray(texcoord_index);
273  glVertexAttribPointer(texcoord_index, 2, GL_FLOAT, GL_FALSE,
274  sizeof(GLfloat) * 4,
275  reinterpret_cast<void*>(sizeof(GLfloat) * 2));
276 
277  glDrawArrays(GL_TRIANGLES, 0, 6);
278 
279  glDeleteVertexArrays(1, &vao);
280  glDeleteBuffers(1, &vertex_buffer);
281  }
282 
283  glDisable(GL_BLEND);
284 
285  glBindTexture(GL_TEXTURE_2D, saved_texture_binding);
286  glBindVertexArray(saved_vao_binding);
287  glBindBuffer(GL_ARRAY_BUFFER, saved_array_buffer_binding);
288 }
289 
290 static void render(FlRenderer* self,
291  GPtrArray* framebuffers,
292  int width,
293  int height) {
294  FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
295  fl_renderer_get_instance_private(self));
296 
297  if (priv->has_gl_framebuffer_blit) {
298  render_with_blit(self, framebuffers);
299  } else {
300  render_with_textures(self, framebuffers, width, height);
301  }
302 }
303 
304 static void fl_renderer_dispose(GObject* object) {
305  FlRenderer* self = FL_RENDERER(object);
306  FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
307  fl_renderer_get_instance_private(self));
308 
310 
311  g_weak_ref_clear(&priv->engine);
312  g_clear_pointer(&priv->views, g_hash_table_unref);
313  g_clear_pointer(&priv->framebuffers_by_view_id, g_hash_table_unref);
314 
315  G_OBJECT_CLASS(fl_renderer_parent_class)->dispose(object);
316 }
317 
318 static void fl_renderer_class_init(FlRendererClass* klass) {
319  G_OBJECT_CLASS(klass)->dispose = fl_renderer_dispose;
320 }
321 
322 static void fl_renderer_init(FlRenderer* self) {
323  FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
324  fl_renderer_get_instance_private(self));
325  priv->views = g_hash_table_new_full(g_direct_hash, g_direct_equal, nullptr,
326  free_weak_ref);
327  priv->framebuffers_by_view_id = g_hash_table_new_full(
328  g_direct_hash, g_direct_equal, nullptr,
329  reinterpret_cast<GDestroyNotify>(g_ptr_array_unref));
330 }
331 
332 void fl_renderer_set_engine(FlRenderer* self, FlEngine* engine) {
333  FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
334  fl_renderer_get_instance_private(self));
335 
336  g_return_if_fail(FL_IS_RENDERER(self));
337 
338  g_weak_ref_init(&priv->engine, engine);
339 }
340 
341 void fl_renderer_add_renderable(FlRenderer* self,
342  FlutterViewId view_id,
343  FlRenderable* renderable) {
344  FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
345  fl_renderer_get_instance_private(self));
346 
347  g_return_if_fail(FL_IS_RENDERER(self));
348 
349  GWeakRef* ref = g_new(GWeakRef, 1);
350  g_weak_ref_init(ref, G_OBJECT(renderable));
351  g_hash_table_insert(priv->views, GINT_TO_POINTER(view_id), ref);
352 }
353 
354 void fl_renderer_remove_view(FlRenderer* self, FlutterViewId view_id) {
355  FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
356  fl_renderer_get_instance_private(self));
357 
358  g_return_if_fail(FL_IS_RENDERER(self));
359 
360  g_hash_table_remove(priv->views, GINT_TO_POINTER(view_id));
361 }
362 
363 void* fl_renderer_get_proc_address(FlRenderer* self, const char* name) {
364  g_return_val_if_fail(FL_IS_RENDERER(self), NULL);
365 
366  return reinterpret_cast<void*>(eglGetProcAddress(name));
367 }
368 
369 void fl_renderer_make_current(FlRenderer* self) {
370  g_return_if_fail(FL_IS_RENDERER(self));
371  FL_RENDERER_GET_CLASS(self)->make_current(self);
372 }
373 
374 void fl_renderer_make_resource_current(FlRenderer* self) {
375  g_return_if_fail(FL_IS_RENDERER(self));
376  FL_RENDERER_GET_CLASS(self)->make_resource_current(self);
377 }
378 
379 void fl_renderer_clear_current(FlRenderer* self) {
380  g_return_if_fail(FL_IS_RENDERER(self));
381  FL_RENDERER_GET_CLASS(self)->clear_current(self);
382 }
383 
384 guint32 fl_renderer_get_fbo(FlRenderer* self) {
385  g_return_val_if_fail(FL_IS_RENDERER(self), 0);
386 
387  // There is only one frame buffer object - always return that.
388  return 0;
389 }
390 
392  FlRenderer* self,
393  const FlutterBackingStoreConfig* config,
394  FlutterBackingStore* backing_store_out) {
395  FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
396  fl_renderer_get_instance_private(self));
397 
399 
400  initialize(self);
401 
402  FlFramebuffer* framebuffer = fl_framebuffer_new(
403  priv->general_format, config->size.width, config->size.height);
404  if (!framebuffer) {
405  g_warning("Failed to create backing store");
406  return FALSE;
407  }
408 
409  backing_store_out->type = kFlutterBackingStoreTypeOpenGL;
410  backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer;
411  backing_store_out->open_gl.framebuffer.user_data = framebuffer;
412  backing_store_out->open_gl.framebuffer.name =
413  fl_framebuffer_get_id(framebuffer);
414  backing_store_out->open_gl.framebuffer.target = priv->sized_format;
415  backing_store_out->open_gl.framebuffer.destruction_callback = [](void* p) {
416  // Backing store destroyed in fl_renderer_collect_backing_store(), set
417  // on FlutterCompositor.collect_backing_store_callback during engine start.
418  };
419 
420  return TRUE;
421 }
422 
424  FlRenderer* self,
425  const FlutterBackingStore* backing_store) {
427 
428  // OpenGL context is required when destroying #FlFramebuffer.
429  g_object_unref(backing_store->open_gl.framebuffer.user_data);
430  return TRUE;
431 }
432 
433 void fl_renderer_wait_for_frame(FlRenderer* self,
434  int target_width,
435  int target_height) {
436  FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
437  fl_renderer_get_instance_private(self));
438 
439  g_return_if_fail(FL_IS_RENDERER(self));
440 
441  priv->target_width = target_width;
442  priv->target_height = target_height;
443 
444  if (priv->had_first_frame && !priv->blocking_main_thread) {
445  priv->blocking_main_thread = true;
446  g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&priv->engine));
447  if (engine != nullptr) {
449  }
450  }
451 }
452 
453 gboolean fl_renderer_present_layers(FlRenderer* self,
454  FlutterViewId view_id,
455  const FlutterLayer** layers,
456  size_t layers_count) {
457  FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
458  fl_renderer_get_instance_private(self));
459 
460  g_return_val_if_fail(FL_IS_RENDERER(self), FALSE);
461 
462  // ignore incoming frame with wrong dimensions in trivial case with just one
463  // layer
464  if (priv->blocking_main_thread && layers_count == 1 &&
465  layers[0]->offset.x == 0 && layers[0]->offset.y == 0 &&
466  (layers[0]->size.width != priv->target_width ||
467  layers[0]->size.height != priv->target_height)) {
468  return TRUE;
469  }
470 
471  priv->had_first_frame = true;
472 
474 
475  g_autoptr(GPtrArray) framebuffers =
476  g_ptr_array_new_with_free_func(g_object_unref);
477  for (size_t i = 0; i < layers_count; ++i) {
478  const FlutterLayer* layer = layers[i];
479  switch (layer->type) {
480  case kFlutterLayerContentTypeBackingStore: {
481  const FlutterBackingStore* backing_store = layer->backing_store;
482  FlFramebuffer* framebuffer =
483  FL_FRAMEBUFFER(backing_store->open_gl.framebuffer.user_data);
484  g_ptr_array_add(framebuffers, g_object_ref(framebuffer));
485  } break;
486  case kFlutterLayerContentTypePlatformView: {
487  // TODO(robert-ancell) Not implemented -
488  // https://github.com/flutter/flutter/issues/41724
489  } break;
490  }
491  }
492 
493  GWeakRef* ref = static_cast<GWeakRef*>(
494  g_hash_table_lookup(priv->views, GINT_TO_POINTER(view_id)));
495  g_autoptr(FlRenderable) renderable =
496  ref != nullptr ? FL_RENDERABLE(g_weak_ref_get(ref)) : nullptr;
497  if (renderable == nullptr) {
498  return TRUE;
499  }
500 
501  if (view_id == flutter::kFlutterImplicitViewId) {
502  // Store for rendering later
503  g_hash_table_insert(priv->framebuffers_by_view_id, GINT_TO_POINTER(view_id),
504  g_ptr_array_ref(framebuffers));
505  } else {
506  // Composite into a single framebuffer.
507  if (framebuffers->len > 1) {
508  size_t width = 0, height = 0;
509 
510  for (guint i = 0; i < framebuffers->len; i++) {
511  FlFramebuffer* framebuffer =
512  FL_FRAMEBUFFER(g_ptr_array_index(framebuffers, i));
513 
514  size_t w = fl_framebuffer_get_width(framebuffer);
515  size_t h = fl_framebuffer_get_height(framebuffer);
516  if (w > width) {
517  width = w;
518  }
519  if (h > height) {
520  height = h;
521  }
522  }
523 
524  FlFramebuffer* view_framebuffer =
525  fl_framebuffer_new(priv->general_format, width, height);
526  glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
527  fl_framebuffer_get_id(view_framebuffer));
528  render(self, framebuffers, width, height);
529  g_ptr_array_set_size(framebuffers, 0);
530  g_ptr_array_add(framebuffers, view_framebuffer);
531  }
532 
533  // Read back pixel values.
534  FlFramebuffer* framebuffer =
535  FL_FRAMEBUFFER(g_ptr_array_index(framebuffers, 0));
536  size_t width = fl_framebuffer_get_width(framebuffer);
537  size_t height = fl_framebuffer_get_height(framebuffer);
538  size_t data_length = width * height * 4;
539  g_autofree uint8_t* data = static_cast<uint8_t*>(malloc(data_length));
540  glBindFramebuffer(GL_READ_FRAMEBUFFER, fl_framebuffer_get_id(framebuffer));
541  glReadPixels(0, 0, width, height, priv->general_format, GL_UNSIGNED_BYTE,
542  data);
543 
544  // Write into a texture in the views context.
545  fl_renderable_make_current(renderable);
546  FlFramebuffer* view_framebuffer =
547  fl_framebuffer_new(priv->general_format, width, height);
548  glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
549  fl_framebuffer_get_id(view_framebuffer));
550  glBindTexture(GL_TEXTURE_2D,
551  fl_framebuffer_get_texture_id(view_framebuffer));
552  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
553  GL_UNSIGNED_BYTE, data);
554 
555  g_autoptr(GPtrArray) secondary_framebuffers =
556  g_ptr_array_new_with_free_func(g_object_unref);
557  g_ptr_array_add(secondary_framebuffers, g_object_ref(view_framebuffer));
558  g_hash_table_insert(priv->framebuffers_by_view_id, GINT_TO_POINTER(view_id),
559  g_ptr_array_ref(secondary_framebuffers));
560  }
561 
562  fl_renderable_redraw(renderable);
563 
564  return TRUE;
565 }
566 
567 void fl_renderer_setup(FlRenderer* self) {
568  FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
569  fl_renderer_get_instance_private(self));
570 
571  g_return_if_fail(FL_IS_RENDERER(self));
572 
573  // Note: NVIDIA and Vivante are temporarily disabled due to
574  // https://github.com/flutter/flutter/issues/152099
575  priv->has_gl_framebuffer_blit =
576  !is_nvidia() && !is_vivante() &&
577  (epoxy_gl_version() >= 30 ||
578  epoxy_has_gl_extension("GL_EXT_framebuffer_blit"));
579 
580  if (!priv->has_gl_framebuffer_blit) {
581  setup_shader(self);
582  }
583 }
584 
585 void fl_renderer_render(FlRenderer* self,
586  FlutterViewId view_id,
587  int width,
588  int height,
589  const GdkRGBA* background_color) {
590  FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
591  fl_renderer_get_instance_private(self));
592 
593  g_return_if_fail(FL_IS_RENDERER(self));
594 
595  glClearColor(background_color->red, background_color->green,
596  background_color->blue, background_color->alpha);
597  glClear(GL_COLOR_BUFFER_BIT);
598 
599  GPtrArray* framebuffers = reinterpret_cast<GPtrArray*>((g_hash_table_lookup(
600  priv->framebuffers_by_view_id, GINT_TO_POINTER(view_id))));
601  if (framebuffers != nullptr) {
602  render(self, framebuffers, width, height);
603  }
604 
605  glFlush();
606 }
607 
608 void fl_renderer_cleanup(FlRenderer* self) {
609  FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
610  fl_renderer_get_instance_private(self));
611 
612  g_return_if_fail(FL_IS_RENDERER(self));
613 
614  if (priv->program != 0) {
615  glDeleteProgram(priv->program);
616  }
617 }
fl_renderer_remove_view
void fl_renderer_remove_view(FlRenderer *self, FlutterViewId view_id)
Definition: fl_renderer.cc:354
fl_renderer_wait_for_frame
void fl_renderer_wait_for_frame(FlRenderer *self, int target_width, int target_height)
Definition: fl_renderer.cc:433
fl_renderer_present_layers
gboolean fl_renderer_present_layers(FlRenderer *self, FlutterViewId view_id, const FlutterLayer **layers, size_t layers_count)
Definition: fl_renderer.cc:453
fl_renderer_error_quark
GQuark fl_renderer_error_quark(void) G_GNUC_CONST
fl_renderer_init
static void fl_renderer_init(FlRenderer *self)
Definition: fl_renderer.cc:322
FlRendererPrivate::has_gl_framebuffer_blit
bool has_gl_framebuffer_blit
Definition: fl_renderer.cc:69
vertex_shader_src
static const char * vertex_shader_src
Definition: fl_renderer.cc:16
i
int i
Definition: fl_socket_accessible.cc:18
priv
FlPixelBufferTexturePrivate * priv
Definition: fl_pixel_buffer_texture.cc:30
FlRendererPrivate::engine
GWeakRef engine
Definition: fl_renderer.cc:43
FlRendererPrivate::target_width
int target_width
Definition: fl_renderer.cc:58
fl_framebuffer_get_texture_id
GLuint fl_framebuffer_get_texture_id(FlFramebuffer *self)
Definition: fl_framebuffer.cc:86
fl_framebuffer_get_height
size_t fl_framebuffer_get_height(FlFramebuffer *self)
Definition: fl_framebuffer.cc:98
fl_renderer_clear_current
void fl_renderer_clear_current(FlRenderer *self)
Definition: fl_renderer.cc:379
FlRendererPrivate::initialized
gboolean initialized
Definition: fl_renderer.cc:46
fl_renderer_get_proc_address
void * fl_renderer_get_proc_address(FlRenderer *self, const char *name)
Definition: fl_renderer.cc:363
is_vivante
static gboolean is_vivante()
Definition: fl_renderer.cc:93
setup_shader
static void setup_shader(FlRenderer *self)
Definition: fl_renderer.cc:161
fl_framebuffer_new
FlFramebuffer * fl_framebuffer_new(GLint format, size_t width, size_t height)
Definition: fl_framebuffer.cc:42
fl_renderer_set_engine
void fl_renderer_set_engine(FlRenderer *self, FlEngine *engine)
Definition: fl_renderer.cc:332
fl_framebuffer.h
FlRendererPrivate::blocking_main_thread
bool blocking_main_thread
Definition: fl_renderer.cc:62
G_DEFINE_QUARK
G_DEFINE_QUARK(fl_binary_messenger_codec_error_quark, fl_binary_messenger_codec_error) G_DECLARE_FINAL_TYPE(FlBinaryMessengerImpl
fl_renderer_class_init
static void fl_renderer_class_init(FlRendererClass *klass)
Definition: fl_renderer.cc:318
fragment_shader_src
static const char * fragment_shader_src
Definition: fl_renderer.cc:27
fl_renderer_collect_backing_store
gboolean fl_renderer_collect_backing_store(FlRenderer *self, const FlutterBackingStore *backing_store)
Definition: fl_renderer.cc:423
fl_renderer_dispose
static void fl_renderer_dispose(GObject *object)
Definition: fl_renderer.cc:304
initialize
static void initialize(FlRenderer *self)
Definition: fl_renderer.cc:130
free_weak_ref
static void free_weak_ref(gpointer value)
Definition: fl_renderer.cc:80
fl_engine_private.h
fl_framebuffer_get_width
size_t fl_framebuffer_get_width(FlFramebuffer *self)
Definition: fl_framebuffer.cc:94
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53
FlRendererPrivate::framebuffers_by_view_id
GHashTable * framebuffers_by_view_id
Definition: fl_renderer.cc:75
FlRendererPrivate::general_format
GLint general_format
Definition: fl_renderer.cc:52
fl_renderer.h
fl_renderer_make_resource_current
void fl_renderer_make_resource_current(FlRenderer *self)
Definition: fl_renderer.cc:374
FlRendererPrivate::sized_format
GLint sized_format
Definition: fl_renderer.cc:49
get_shader_log
static gchar * get_shader_log(GLuint shader)
Definition: fl_renderer.cc:99
fl_renderer_unblock_main_thread
static void fl_renderer_unblock_main_thread(FlRenderer *self)
Definition: fl_renderer.cc:148
fl_task_runner_release_main_thread
void fl_task_runner_release_main_thread(FlTaskRunner *self)
Definition: fl_task_runner.cc:197
height
const uint8_t uint32_t uint32_t * height
Definition: fl_pixel_buffer_texture_test.cc:39
render
static void render(FlRenderer *self, GPtrArray *framebuffers, int width, int height)
Definition: fl_renderer.cc:290
fl_renderer_cleanup
void fl_renderer_cleanup(FlRenderer *self)
Definition: fl_renderer.cc:608
get_program_log
static gchar * get_program_log(GLuint program)
Definition: fl_renderer.cc:112
fl_renderer_make_current
void fl_renderer_make_current(FlRenderer *self)
Definition: fl_renderer.cc:369
fl_engine_get_task_runner
FlTaskRunner * fl_engine_get_task_runner(FlEngine *self)
Definition: fl_engine.cc:1209
fl_renderer_render
void fl_renderer_render(FlRenderer *self, FlutterViewId view_id, int width, int height, const GdkRGBA *background_color)
Definition: fl_renderer.cc:585
FlRendererPrivate::views
GHashTable * views
Definition: fl_renderer.cc:55
fl_renderable_redraw
void fl_renderable_redraw(FlRenderable *self)
Definition: fl_renderable.cc:11
fl_renderer_create_backing_store
gboolean fl_renderer_create_backing_store(FlRenderer *self, const FlutterBackingStoreConfig *config, FlutterBackingStore *backing_store_out)
Definition: fl_renderer.cc:391
FlRendererPrivate::target_height
int target_height
Definition: fl_renderer.cc:59
fl_renderable_make_current
void fl_renderable_make_current(FlRenderable *self)
Definition: fl_renderable.cc:17
fl_renderer_add_renderable
void fl_renderer_add_renderable(FlRenderer *self, FlutterViewId view_id, FlRenderable *renderable)
Definition: fl_renderer.cc:341
render_with_textures
static void render_with_textures(FlRenderer *self, GPtrArray *framebuffers, int width, int height)
Definition: fl_renderer.cc:221
pixels_to_gl_coords
static GLfloat pixels_to_gl_coords(GLfloat position, GLfloat pixels)
Converts a pixel co-ordinate from 0..pixels to OpenGL -1..1.
Definition: fl_renderer.cc:125
render_with_blit
static void render_with_blit(FlRenderer *self, GPtrArray *framebuffers)
Definition: fl_renderer.cc:201
is_nvidia
static gboolean is_nvidia()
Definition: fl_renderer.cc:87
texture_id
int64_t texture_id
Definition: texture_registrar_unittests.cc:24
width
const uint8_t uint32_t * width
Definition: fl_pixel_buffer_texture_test.cc:38
FlRendererPrivate
Definition: fl_renderer.cc:41
FlRendererPrivate::had_first_frame
bool had_first_frame
Definition: fl_renderer.cc:66
fl_renderer_get_fbo
guint32 fl_renderer_get_fbo(FlRenderer *self)
Definition: fl_renderer.cc:384
fl_task_runner_block_main_thread
void fl_task_runner_block_main_thread(FlTaskRunner *self)
Definition: fl_task_runner.cc:176
value
uint8_t value
Definition: fl_standard_message_codec.cc:36
FlRendererPrivate::program
GLuint program
Definition: fl_renderer.cc:72
fl_framebuffer_get_id
GLuint fl_framebuffer_get_id(FlFramebuffer *self)
Definition: fl_framebuffer.cc:82
fl_renderer_setup
void fl_renderer_setup(FlRenderer *self)
Definition: fl_renderer.cc:567