Flutter Linux Embedder
fl_renderer.cc File Reference
#include "fl_renderer.h"
#include <epoxy/egl.h>
#include <epoxy/gl.h>
#include "flutter/common/constants.h"
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/linux/fl_engine_private.h"
#include "flutter/shell/platform/linux/fl_framebuffer.h"

Go to the source code of this file.

Classes

struct  FlRendererPrivate
 

Functions

static void free_weak_ref (gpointer value)
 
static gboolean is_nvidia ()
 
static gboolean is_vivante ()
 
static gchar * get_shader_log (GLuint shader)
 
static gchar * get_program_log (GLuint program)
 
static GLfloat pixels_to_gl_coords (GLfloat position, GLfloat pixels)
 Converts a pixel co-ordinate from 0..pixels to OpenGL -1..1. More...
 
static void initialize (FlRenderer *self)
 
static void fl_renderer_unblock_main_thread (FlRenderer *self)
 
static void setup_shader (FlRenderer *self)
 
static void render_with_blit (FlRenderer *self, GPtrArray *framebuffers)
 
static void render_with_textures (FlRenderer *self, GPtrArray *framebuffers, int width, int height)
 
static void render (FlRenderer *self, GPtrArray *framebuffers, int width, int height)
 
static void fl_renderer_dispose (GObject *object)
 
static void fl_renderer_class_init (FlRendererClass *klass)
 
static void fl_renderer_init (FlRenderer *self)
 
void fl_renderer_set_engine (FlRenderer *self, FlEngine *engine)
 
void fl_renderer_add_renderable (FlRenderer *self, FlutterViewId view_id, FlRenderable *renderable)
 
void fl_renderer_remove_view (FlRenderer *self, FlutterViewId view_id)
 
void * fl_renderer_get_proc_address (FlRenderer *self, const char *name)
 
void fl_renderer_make_current (FlRenderer *self)
 
void fl_renderer_make_resource_current (FlRenderer *self)
 
void fl_renderer_clear_current (FlRenderer *self)
 
guint32 fl_renderer_get_fbo (FlRenderer *self)
 
gboolean fl_renderer_create_backing_store (FlRenderer *self, const FlutterBackingStoreConfig *config, FlutterBackingStore *backing_store_out)
 
gboolean fl_renderer_collect_backing_store (FlRenderer *self, const FlutterBackingStore *backing_store)
 
void fl_renderer_wait_for_frame (FlRenderer *self, int target_width, int target_height)
 
gboolean fl_renderer_present_layers (FlRenderer *self, FlutterViewId view_id, const FlutterLayer **layers, size_t layers_count)
 
void fl_renderer_setup (FlRenderer *self)
 
void fl_renderer_render (FlRenderer *self, FlutterViewId view_id, int width, int height, const GdkRGBA *background_color)
 
void fl_renderer_cleanup (FlRenderer *self)
 

Variables

static const char * vertex_shader_src
 
static const char * fragment_shader_src
 

Function Documentation

◆ fl_renderer_add_renderable()

void fl_renderer_add_renderable ( FlRenderer *  renderer,
FlutterViewId  view_id,
FlRenderable *  renderable 
)

fl_renderer_add_renderable: @renderer: an #FlRenderer. @view_id: the ID of the view. @renderable: object that is to be rendered on.

Add a view to render on.

Definition at line 341 of file fl_renderer.cc.

343  {
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 }

References priv.

Referenced by fl_view_new_for_engine(), realize_cb(), and TEST().

◆ fl_renderer_class_init()

static void fl_renderer_class_init ( FlRendererClass *  klass)
static

Definition at line 318 of file fl_renderer.cc.

318  {
319  G_OBJECT_CLASS(klass)->dispose = fl_renderer_dispose;
320 }

References fl_renderer_dispose().

◆ fl_renderer_cleanup()

void fl_renderer_cleanup ( FlRenderer *  renderer)

fl_renderer_cleanup:

Removes OpenGL resources used for rendering. Requires an active OpenGL context.

Definition at line 608 of file fl_renderer.cc.

608  {
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 }

References priv.

Referenced by unrealize_cb().

◆ fl_renderer_clear_current()

void fl_renderer_clear_current ( FlRenderer *  renderer)

fl_renderer_clear_current: @renderer: an #FlRenderer.

Clears the current rendering context.

Definition at line 379 of file fl_renderer.cc.

379  {
380  g_return_if_fail(FL_IS_RENDERER(self));
381  FL_RENDERER_GET_CLASS(self)->clear_current(self);
382 }

Referenced by fl_engine_gl_clear_current().

◆ fl_renderer_collect_backing_store()

gboolean fl_renderer_collect_backing_store ( FlRenderer *  renderer,
const FlutterBackingStore *  backing_store 
)

fl_renderer_collect_backing_store: @renderer: an #FlRenderer. @backing_store: backing store to be released.

A callback invoked by the engine to release the backing store. The embedder may collect any resources associated with the backing store.

Returns TRUE if successful.

Definition at line 423 of file fl_renderer.cc.

425  {
427 
428  // OpenGL context is required when destroying #FlFramebuffer.
429  g_object_unref(backing_store->open_gl.framebuffer.user_data);
430  return TRUE;
431 }

References fl_renderer_make_current(), and TRUE.

Referenced by compositor_collect_backing_store_callback().

◆ fl_renderer_create_backing_store()

gboolean fl_renderer_create_backing_store ( FlRenderer *  renderer,
const FlutterBackingStoreConfig *  config,
FlutterBackingStore *  backing_store_out 
)

fl_renderer_create_backing_store: @renderer: an #FlRenderer. @config: backing store config. @backing_store_out: saves created backing store.

Obtain a backing store for a specific #FlutterLayer.

Returns TRUE if successful.

Definition at line 391 of file fl_renderer.cc.

394  {
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 }

References fl_framebuffer_get_id(), fl_framebuffer_new(), fl_renderer_make_current(), initialize(), priv, and TRUE.

Referenced by compositor_create_backing_store_callback(), and TEST().

◆ fl_renderer_dispose()

static void fl_renderer_dispose ( GObject *  object)
static

Definition at line 304 of file fl_renderer.cc.

304  {
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 }

References fl_renderer_unblock_main_thread(), and priv.

Referenced by fl_renderer_class_init().

◆ fl_renderer_get_fbo()

guint32 fl_renderer_get_fbo ( FlRenderer *  renderer)

fl_renderer_get_fbo: @renderer: an #FlRenderer.

Gets the frame buffer object to render to.

Returns: a frame buffer object index.

Definition at line 384 of file fl_renderer.cc.

384  {
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 }

Referenced by fl_engine_gl_get_fbo().

◆ fl_renderer_get_proc_address()

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

Definition at line 363 of file fl_renderer.cc.

363  {
364  g_return_val_if_fail(FL_IS_RENDERER(self), NULL);
365 
366  return reinterpret_cast<void*>(eglGetProcAddress(name));
367 }

Referenced by fl_engine_gl_proc_resolver().

◆ fl_renderer_init()

static void fl_renderer_init ( FlRenderer *  self)
static

Definition at line 322 of file fl_renderer.cc.

322  {
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 }

References free_weak_ref(), and priv.

◆ fl_renderer_make_current()

void fl_renderer_make_current ( FlRenderer *  renderer)

fl_renderer_make_current: @renderer: an #FlRenderer.

Makes the rendering context current.

Definition at line 369 of file fl_renderer.cc.

369  {
370  g_return_if_fail(FL_IS_RENDERER(self));
371  FL_RENDERER_GET_CLASS(self)->make_current(self);
372 }

Referenced by fl_engine_gl_make_current(), fl_renderer_collect_backing_store(), fl_renderer_create_backing_store(), realize_cb(), and unrealize_cb().

◆ fl_renderer_make_resource_current()

void fl_renderer_make_resource_current ( FlRenderer *  renderer)

fl_renderer_make_resource_current: @renderer: an #FlRenderer.

Makes the resource rendering context current.

Definition at line 374 of file fl_renderer.cc.

374  {
375  g_return_if_fail(FL_IS_RENDERER(self));
376  FL_RENDERER_GET_CLASS(self)->make_resource_current(self);
377 }

Referenced by fl_engine_gl_make_resource_current().

◆ fl_renderer_present_layers()

gboolean fl_renderer_present_layers ( FlRenderer *  renderer,
FlutterViewId  view_id,
const FlutterLayer **  layers,
size_t  layers_count 
)

fl_renderer_present_layers: @renderer: an #FlRenderer. @view_id: view to present. @layers: layers to be composited. @layers_count: number of layers.

Callback invoked by the engine to composite the contents of each layer onto the screen.

Returns TRUE if successful.

Definition at line 453 of file fl_renderer.cc.

456  {
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 }

References fl_framebuffer_get_height(), fl_framebuffer_get_id(), fl_framebuffer_get_texture_id(), fl_framebuffer_get_width(), fl_framebuffer_new(), fl_renderable_make_current(), fl_renderable_redraw(), fl_renderer_unblock_main_thread(), height, i, priv, render(), TRUE, and width.

Referenced by compositor_present_view_callback(), and TEST().

◆ fl_renderer_remove_view()

void fl_renderer_remove_view ( FlRenderer *  renderer,
FlutterViewId  view_id 
)

fl_renderer_remove_view: @renderer: an #FlRenderer. @view_id: the ID of the view.

Remove a view from the renderer.

Definition at line 354 of file fl_renderer.cc.

354  {
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 }

References priv.

Referenced by fl_view_dispose().

◆ fl_renderer_render()

void fl_renderer_render ( FlRenderer *  renderer,
FlutterViewId  view_id,
int  width,
int  height,
const GdkRGBA *  background_color 
)

fl_renderer_render: @renderer: an #FlRenderer. @view_id: view to render. @width: width of the window in pixels. @height: height of the window in pixels. @background_color: color to use for background.

Performs OpenGL commands to render current Flutter view.

Definition at line 585 of file fl_renderer.cc.

589  {
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 }

References height, priv, render(), and width.

Referenced by render_cb(), and TEST().

◆ fl_renderer_set_engine()

void fl_renderer_set_engine ( FlRenderer *  renderer,
FlEngine *  engine 
)

fl_renderer_set_engine: @renderer: an #FlRenderer. @engine: an #FlEngine.

Called when the renderer is connected to an engine.

Definition at line 332 of file fl_renderer.cc.

332  {
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 }

References priv.

Referenced by fl_engine_new_with_renderer().

◆ fl_renderer_setup()

void fl_renderer_setup ( FlRenderer *  renderer)

fl_renderer_setup: @renderer: an #FlRenderer.

Creates OpenGL resources required before rendering. Requires an active OpenGL context.

Definition at line 567 of file fl_renderer.cc.

567  {
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 }

References is_nvidia(), is_vivante(), priv, and setup_shader().

Referenced by realize_cb(), and TEST().

◆ fl_renderer_unblock_main_thread()

static void fl_renderer_unblock_main_thread ( FlRenderer *  self)
static

Definition at line 148 of file fl_renderer.cc.

148  {
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 }

References fl_engine_get_task_runner(), fl_task_runner_release_main_thread(), and priv.

Referenced by fl_renderer_dispose(), and fl_renderer_present_layers().

◆ fl_renderer_wait_for_frame()

void fl_renderer_wait_for_frame ( FlRenderer *  renderer,
int  target_width,
int  target_height 
)

fl_renderer_wait_for_frame: @renderer: an #FlRenderer. @target_width: width of frame being waited for @target_height: height of frame being waited for

Holds the thread until frame with requested dimensions is presented. While waiting for frame Flutter platform and raster tasks are being processed.

Definition at line 433 of file fl_renderer.cc.

435  {
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 }

References fl_engine_get_task_runner(), fl_task_runner_block_main_thread(), and priv.

Referenced by handle_geometry_changed(), and TEST().

◆ free_weak_ref()

static void free_weak_ref ( gpointer  value)
static

Definition at line 80 of file fl_renderer.cc.

80  {
81  GWeakRef* ref = static_cast<GWeakRef*>(value);
82  g_weak_ref_clear(ref);
83  free(ref);
84 }

References value.

Referenced by fl_renderer_init().

◆ get_program_log()

static gchar* get_program_log ( GLuint  program)
static

Definition at line 112 of file fl_renderer.cc.

112  {
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 }

Referenced by setup_shader().

◆ get_shader_log()

static gchar* get_shader_log ( GLuint  shader)
static

Definition at line 99 of file fl_renderer.cc.

99  {
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 }

Referenced by setup_shader().

◆ initialize()

static void initialize ( FlRenderer *  self)
static

Definition at line 130 of file fl_renderer.cc.

130  {
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 }

References priv, and TRUE.

Referenced by fl_renderer_create_backing_store().

◆ is_nvidia()

static gboolean is_nvidia ( )
static

Definition at line 87 of file fl_renderer.cc.

87  {
88  const gchar* vendor = reinterpret_cast<const gchar*>(glGetString(GL_VENDOR));
89  return strstr(vendor, "NVIDIA") != nullptr;
90 }

Referenced by fl_renderer_setup().

◆ is_vivante()

static gboolean is_vivante ( )
static

Definition at line 93 of file fl_renderer.cc.

93  {
94  const gchar* vendor = reinterpret_cast<const gchar*>(glGetString(GL_VENDOR));
95  return strstr(vendor, "Vivante Corporation") != nullptr;
96 }

Referenced by fl_renderer_setup().

◆ pixels_to_gl_coords()

static GLfloat pixels_to_gl_coords ( GLfloat  position,
GLfloat  pixels 
)
static

Converts a pixel co-ordinate from 0..pixels to OpenGL -1..1.

Definition at line 125 of file fl_renderer.cc.

125  {
126  return (2.0 * position / pixels) - 1.0;
127 }

Referenced by render_with_textures().

◆ render()

static void render ( FlRenderer *  self,
GPtrArray *  framebuffers,
int  width,
int  height 
)
static

Definition at line 290 of file fl_renderer.cc.

293  {
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 }

References height, priv, render_with_blit(), render_with_textures(), and width.

Referenced by fl_renderer_present_layers(), and fl_renderer_render().

◆ render_with_blit()

static void render_with_blit ( FlRenderer *  self,
GPtrArray *  framebuffers 
)
static

Definition at line 201 of file fl_renderer.cc.

201  {
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 }

References fl_framebuffer_get_height(), fl_framebuffer_get_id(), fl_framebuffer_get_width(), height, i, and width.

Referenced by render().

◆ render_with_textures()

static void render_with_textures ( FlRenderer *  self,
GPtrArray *  framebuffers,
int  width,
int  height 
)
static

Definition at line 221 of file fl_renderer.cc.

224  {
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 }

References fl_framebuffer_get_height(), fl_framebuffer_get_texture_id(), fl_framebuffer_get_width(), height, i, pixels_to_gl_coords(), priv, texture_id, and width.

Referenced by render().

◆ setup_shader()

static void setup_shader ( FlRenderer *  self)
static

Definition at line 161 of file fl_renderer.cc.

161  {
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 }

References fragment_shader_src, get_program_log(), get_shader_log(), priv, and vertex_shader_src.

Referenced by fl_renderer_setup().

Variable Documentation

◆ fragment_shader_src

const char* fragment_shader_src
static
Initial value:
=
"#ifdef GL_ES\n"
"precision mediump float;\n"
"#endif\n"
"\n"
"uniform sampler2D texture;\n"
"varying vec2 texcoord;\n"
"\n"
"void main() {\n"
" gl_FragColor = texture2D(texture, texcoord);\n"
"}\n"

Definition at line 27 of file fl_renderer.cc.

Referenced by setup_shader().

◆ vertex_shader_src

const char* vertex_shader_src
static
Initial value:
=
"attribute vec2 position;\n"
"attribute vec2 in_texcoord;\n"
"varying vec2 texcoord;\n"
"\n"
"void main() {\n"
" gl_Position = vec4(position, 0, 1);\n"
" texcoord = in_texcoord;\n"
"}\n"

Definition at line 16 of file fl_renderer.cc.

Referenced by setup_shader().

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
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
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
fragment_shader_src
static const char * fragment_shader_src
Definition: fl_renderer.cc:27
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_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
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
get_program_log
static gchar * get_program_log(GLuint program)
Definition: fl_renderer.cc:112
fl_engine_get_task_runner
FlTaskRunner * fl_engine_get_task_runner(FlEngine *self)
Definition: fl_engine.cc:1209
fl_renderer_make_current
void fl_renderer_make_current(FlRenderer *self)
Definition: fl_renderer.cc:369
fl_renderable_redraw
void fl_renderable_redraw(FlRenderable *self)
Definition: fl_renderable.cc:11
fl_renderable_make_current
void fl_renderable_make_current(FlRenderable *self)
Definition: fl_renderable.cc:17
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
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
fl_framebuffer_get_id
GLuint fl_framebuffer_get_id(FlFramebuffer *self)
Definition: fl_framebuffer.cc:82