Flutter Linux Embedder
fl_compositor_opengl.cc File Reference
#include "fl_compositor_opengl.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  _FlCompositorOpenGL
 
struct  PresentLayersData
 

Functions

 G_DEFINE_TYPE (FlCompositorOpenGL, fl_compositor_opengl, fl_compositor_get_type()) 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 (FlCompositorOpenGL *self)
 
static void fl_compositor_opengl_unblock_main_thread (FlCompositorOpenGL *self)
 
static void setup_shader (FlCompositorOpenGL *self)
 
static void render_with_blit (FlCompositorOpenGL *self, GPtrArray *framebuffers)
 
static void render_with_textures (FlCompositorOpenGL *self, GPtrArray *framebuffers, int width, int height)
 
static void render (FlCompositorOpenGL *self, GPtrArray *framebuffers, int width, int height)
 
static gboolean present_layers (FlCompositorOpenGL *self, FlutterViewId view_id, const FlutterLayer **layers, size_t layers_count)
 
static void present_layers_task_cb (gpointer user_data)
 
static gboolean fl_compositor_opengl_create_backing_store (FlCompositor *compositor, const FlutterBackingStoreConfig *config, FlutterBackingStore *backing_store_out)
 
static gboolean fl_compositor_opengl_collect_backing_store (FlCompositor *compositor, const FlutterBackingStore *backing_store)
 
static void fl_compositor_opengl_wait_for_frame (FlCompositor *compositor, int target_width, int target_height)
 
static gboolean fl_compositor_opengl_present_layers (FlCompositor *compositor, FlutterViewId view_id, const FlutterLayer **layers, size_t layers_count)
 
static void fl_compositor_opengl_dispose (GObject *object)
 
static void fl_compositor_opengl_class_init (FlCompositorOpenGLClass *klass)
 
static void fl_compositor_opengl_init (FlCompositorOpenGL *self)
 
FlCompositorOpenGL * fl_compositor_opengl_new (FlEngine *engine)
 
void fl_compositor_opengl_setup (FlCompositorOpenGL *self)
 
void fl_compositor_opengl_render (FlCompositorOpenGL *self, FlutterViewId view_id, int width, int height, const GdkRGBA *background_color)
 
void fl_compositor_opengl_cleanup (FlCompositorOpenGL *self)
 

Variables

static const char * vertex_shader_src
 
static const char * fragment_shader_src
 

Function Documentation

◆ fl_compositor_opengl_class_init()

static void fl_compositor_opengl_class_init ( FlCompositorOpenGLClass *  klass)
static

Definition at line 550 of file fl_compositor_opengl.cc.

550  {
551  FL_COMPOSITOR_CLASS(klass)->create_backing_store =
553  FL_COMPOSITOR_CLASS(klass)->collect_backing_store =
555  FL_COMPOSITOR_CLASS(klass)->wait_for_frame =
557  FL_COMPOSITOR_CLASS(klass)->present_layers =
559 
560  G_OBJECT_CLASS(klass)->dispose = fl_compositor_opengl_dispose;
561 }
static void fl_compositor_opengl_dispose(GObject *object)
static void fl_compositor_opengl_wait_for_frame(FlCompositor *compositor, int target_width, int target_height)
static gboolean fl_compositor_opengl_create_backing_store(FlCompositor *compositor, const FlutterBackingStoreConfig *config, FlutterBackingStore *backing_store_out)
static gboolean fl_compositor_opengl_present_layers(FlCompositor *compositor, FlutterViewId view_id, const FlutterLayer **layers, size_t layers_count)
static gboolean fl_compositor_opengl_collect_backing_store(FlCompositor *compositor, const FlutterBackingStore *backing_store)

References fl_compositor_opengl_collect_backing_store(), fl_compositor_opengl_create_backing_store(), fl_compositor_opengl_dispose(), fl_compositor_opengl_present_layers(), and fl_compositor_opengl_wait_for_frame().

◆ fl_compositor_opengl_cleanup()

void fl_compositor_opengl_cleanup ( FlCompositorOpenGL *  compositor)

fl_compositor_opengl_cleanup: @compositor: an #FlCompositorOpenGL.

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

Definition at line 617 of file fl_compositor_opengl.cc.

617  {
618  g_return_if_fail(FL_IS_COMPOSITOR_OPENGL(self));
619 
620  if (self->program != 0) {
621  glDeleteProgram(self->program);
622  }
623 }

Referenced by unrealize_cb().

◆ fl_compositor_opengl_collect_backing_store()

static gboolean fl_compositor_opengl_collect_backing_store ( FlCompositor *  compositor,
const FlutterBackingStore *  backing_store 
)
static

Definition at line 470 of file fl_compositor_opengl.cc.

472  {
473  FlCompositorOpenGL* self = FL_COMPOSITOR_OPENGL(compositor);
474 
475  fl_opengl_manager_make_current(self->opengl_manager);
476 
477  // OpenGL context is required when destroying #FlFramebuffer.
478  g_object_unref(backing_store->open_gl.framebuffer.user_data);
479  return TRUE;
480 }
void fl_opengl_manager_make_current(FlOpenGLManager *self)

References fl_opengl_manager_make_current(), and TRUE.

Referenced by fl_compositor_opengl_class_init().

◆ fl_compositor_opengl_create_backing_store()

static gboolean fl_compositor_opengl_create_backing_store ( FlCompositor *  compositor,
const FlutterBackingStoreConfig *  config,
FlutterBackingStore *  backing_store_out 
)
static

Definition at line 438 of file fl_compositor_opengl.cc.

441  {
442  FlCompositorOpenGL* self = FL_COMPOSITOR_OPENGL(compositor);
443 
444  fl_opengl_manager_make_current(self->opengl_manager);
445 
446  initialize(self);
447 
448  FlFramebuffer* framebuffer = fl_framebuffer_new(
449  self->general_format, config->size.width, config->size.height);
450  if (!framebuffer) {
451  g_warning("Failed to create backing store");
452  return FALSE;
453  }
454 
455  backing_store_out->type = kFlutterBackingStoreTypeOpenGL;
456  backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer;
457  backing_store_out->open_gl.framebuffer.user_data = framebuffer;
458  backing_store_out->open_gl.framebuffer.name =
459  fl_framebuffer_get_id(framebuffer);
460  backing_store_out->open_gl.framebuffer.target = self->sized_format;
461  backing_store_out->open_gl.framebuffer.destruction_callback = [](void* p) {
462  // Backing store destroyed in fl_compositor_opengl_collect_backing_store(),
463  // set on FlutterCompositor.collect_backing_store_callback during engine
464  // start.
465  };
466 
467  return TRUE;
468 }
static void initialize(FlCompositorOpenGL *self)
GLuint fl_framebuffer_get_id(FlFramebuffer *self)
FlFramebuffer * fl_framebuffer_new(GLint format, size_t width, size_t height)

References fl_framebuffer_get_id(), fl_framebuffer_new(), fl_opengl_manager_make_current(), initialize(), and TRUE.

Referenced by fl_compositor_opengl_class_init().

◆ fl_compositor_opengl_dispose()

static void fl_compositor_opengl_dispose ( GObject *  object)
static

Definition at line 536 of file fl_compositor_opengl.cc.

536  {
537  FlCompositorOpenGL* self = FL_COMPOSITOR_OPENGL(object);
538 
540 
541  g_weak_ref_clear(&self->engine);
542  g_clear_object(&self->opengl_manager);
543  g_clear_pointer(&self->framebuffers_by_view_id, g_hash_table_unref);
544  g_mutex_clear(&self->present_mutex);
545  g_cond_clear(&self->present_condition);
546 
547  G_OBJECT_CLASS(fl_compositor_opengl_parent_class)->dispose(object);
548 }
static void fl_compositor_opengl_unblock_main_thread(FlCompositorOpenGL *self)

References fl_compositor_opengl_unblock_main_thread().

Referenced by fl_compositor_opengl_class_init().

◆ fl_compositor_opengl_init()

static void fl_compositor_opengl_init ( FlCompositorOpenGL *  self)
static

Definition at line 563 of file fl_compositor_opengl.cc.

563  {
564  self->framebuffers_by_view_id = g_hash_table_new_full(
565  g_direct_hash, g_direct_equal, nullptr,
566  reinterpret_cast<GDestroyNotify>(g_ptr_array_unref));
567  g_mutex_init(&self->present_mutex);
568  g_cond_init(&self->present_condition);
569 }

◆ fl_compositor_opengl_new()

FlCompositorOpenGL* fl_compositor_opengl_new ( FlEngine *  engine)

Definition at line 571 of file fl_compositor_opengl.cc.

571  {
572  FlCompositorOpenGL* self = FL_COMPOSITOR_OPENGL(
573  g_object_new(fl_compositor_opengl_get_type(), nullptr));
574 
575  g_weak_ref_init(&self->engine, engine);
576  self->opengl_manager =
577  FL_OPENGL_MANAGER(g_object_ref(fl_engine_get_opengl_manager(engine)));
578 
579  return self;
580 }
FlOpenGLManager * fl_engine_get_opengl_manager(FlEngine *self)
Definition: fl_engine.cc:603

References fl_engine_get_opengl_manager().

Referenced by fl_engine_new_full(), and TEST().

◆ fl_compositor_opengl_present_layers()

static gboolean fl_compositor_opengl_present_layers ( FlCompositor *  compositor,
FlutterViewId  view_id,
const FlutterLayer **  layers,
size_t  layers_count 
)
static

Definition at line 499 of file fl_compositor_opengl.cc.

502  {
503  FlCompositorOpenGL* self = FL_COMPOSITOR_OPENGL(compositor);
504 
505  // Detach the context from raster thread. Needed because blitting
506  // will be done on the main thread, which will make the context current.
507  fl_opengl_manager_clear_current(self->opengl_manager);
508 
509  g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
510 
511  // Schedule the present to run on the main thread.
512  FlTaskRunner* task_runner = fl_engine_get_task_runner(engine);
513  PresentLayersData data = {
514  .self = self,
515  .view_id = view_id,
516  .layers = layers,
517  .layers_count = layers_count,
518  .result = FALSE,
519  .finished = FALSE,
520  };
522 
523  // Block until present completes.
524  g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->present_mutex);
525  while (!data.finished) {
526  g_cond_wait(&self->present_condition, &self->present_mutex);
527  }
528 
529  // Restore the context to the raster thread in case the engine needs it
530  // to do some cleanup.
531  fl_opengl_manager_make_current(self->opengl_manager);
532 
533  return data.result;
534 }
static void present_layers_task_cb(gpointer user_data)
FlTaskRunner * fl_engine_get_task_runner(FlEngine *self)
Definition: fl_engine.cc:1287
void fl_opengl_manager_clear_current(FlOpenGLManager *self)
void fl_task_runner_post_callback(FlTaskRunner *self, void(*callback)(gpointer data), gpointer data)
G_BEGIN_DECLS FlutterViewId view_id
FlCompositorOpenGL * self

References PresentLayersData::finished, fl_engine_get_task_runner(), fl_opengl_manager_clear_current(), fl_opengl_manager_make_current(), fl_task_runner_post_callback(), present_layers_task_cb(), PresentLayersData::result, PresentLayersData::self, and view_id.

Referenced by fl_compositor_opengl_class_init().

◆ fl_compositor_opengl_render()

void fl_compositor_opengl_render ( FlCompositorOpenGL *  compositor,
FlutterViewId  view_id,
int  width,
int  height,
const GdkRGBA *  background_color 
)

fl_compositor_opengl_render: @compositor: an #FlCompositorOpenGL. @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 597 of file fl_compositor_opengl.cc.

601  {
602  g_return_if_fail(FL_IS_COMPOSITOR_OPENGL(self));
603 
604  glClearColor(background_color->red, background_color->green,
605  background_color->blue, background_color->alpha);
606  glClear(GL_COLOR_BUFFER_BIT);
607 
608  GPtrArray* framebuffers = reinterpret_cast<GPtrArray*>((g_hash_table_lookup(
609  self->framebuffers_by_view_id, GINT_TO_POINTER(view_id))));
610  if (framebuffers != nullptr) {
611  render(self, framebuffers, width, height);
612  }
613 
614  glFlush();
615 }
static void render(FlCompositorOpenGL *self, GPtrArray *framebuffers, int width, int height)
const uint8_t uint32_t uint32_t * height
const uint8_t uint32_t * width

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

Referenced by render_cb(), and TEST().

◆ fl_compositor_opengl_setup()

void fl_compositor_opengl_setup ( FlCompositorOpenGL *  compositor)

fl_compositor_opengl_setup: @compositor: an #FlCompositorOpenGL.

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

Definition at line 582 of file fl_compositor_opengl.cc.

582  {
583  g_return_if_fail(FL_IS_COMPOSITOR_OPENGL(self));
584 
585  // Note: NVIDIA and Vivante are temporarily disabled due to
586  // https://github.com/flutter/flutter/issues/152099
587  self->has_gl_framebuffer_blit =
588  !is_nvidia() && !is_vivante() &&
589  (epoxy_gl_version() >= 30 ||
590  epoxy_has_gl_extension("GL_EXT_framebuffer_blit"));
591 
592  if (!self->has_gl_framebuffer_blit) {
593  setup_shader(self);
594  }
595 }
static void setup_shader(FlCompositorOpenGL *self)
static gboolean is_vivante()

References is_vivante(), and setup_shader().

Referenced by realize_cb(), and TEST().

◆ fl_compositor_opengl_unblock_main_thread()

static void fl_compositor_opengl_unblock_main_thread ( FlCompositorOpenGL *  self)
static

Definition at line 149 of file fl_compositor_opengl.cc.

149  {
150  if (self->blocking_main_thread) {
151  self->blocking_main_thread = false;
152 
153  g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
154  if (engine != nullptr) {
156  }
157  }
158 }
void fl_task_runner_release_main_thread(FlTaskRunner *self)

References fl_engine_get_task_runner(), and fl_task_runner_release_main_thread().

Referenced by fl_compositor_opengl_dispose(), and present_layers().

◆ fl_compositor_opengl_wait_for_frame()

static void fl_compositor_opengl_wait_for_frame ( FlCompositor *  compositor,
int  target_width,
int  target_height 
)
static

Definition at line 482 of file fl_compositor_opengl.cc.

484  {
485  FlCompositorOpenGL* self = FL_COMPOSITOR_OPENGL(compositor);
486 
487  self->target_width = target_width;
488  self->target_height = target_height;
489 
490  if (self->had_first_frame && !self->blocking_main_thread) {
491  self->blocking_main_thread = true;
492  g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
493  if (engine != nullptr) {
495  }
496  }
497 }
void fl_task_runner_block_main_thread(FlTaskRunner *self)

References fl_engine_get_task_runner(), and fl_task_runner_block_main_thread().

Referenced by fl_compositor_opengl_class_init().

◆ G_DEFINE_TYPE()

G_DEFINE_TYPE ( FlCompositorOpenGL  ,
fl_compositor_opengl  ,
fl_compositor_get_type()   
)

Definition at line 86 of file fl_compositor_opengl.cc.

91  {
92  const gchar* vendor = reinterpret_cast<const gchar*>(glGetString(GL_VENDOR));
93  return strstr(vendor, "NVIDIA") != nullptr;
94 }

◆ get_program_log()

static gchar* get_program_log ( GLuint  program)
static

Definition at line 116 of file fl_compositor_opengl.cc.

116  {
117  GLint log_length;
118  gchar* log;
119 
120  glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
121 
122  log = static_cast<gchar*>(g_malloc(log_length + 1));
123  glGetProgramInfoLog(program, log_length, nullptr, log);
124 
125  return log;
126 }

Referenced by setup_shader().

◆ get_shader_log()

static gchar* get_shader_log ( GLuint  shader)
static

Definition at line 103 of file fl_compositor_opengl.cc.

103  {
104  GLint log_length;
105  gchar* log;
106 
107  glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
108 
109  log = static_cast<gchar*>(g_malloc(log_length + 1));
110  glGetShaderInfoLog(shader, log_length, nullptr, log);
111 
112  return log;
113 }

Referenced by setup_shader().

◆ initialize()

static void initialize ( FlCompositorOpenGL *  self)
static

Definition at line 134 of file fl_compositor_opengl.cc.

134  {
135  if (self->initialized) {
136  return;
137  }
138  self->initialized = TRUE;
139 
140  if (epoxy_has_gl_extension("GL_EXT_texture_format_BGRA8888")) {
141  self->sized_format = GL_BGRA8_EXT;
142  self->general_format = GL_BGRA_EXT;
143  } else {
144  self->sized_format = GL_RGBA8;
145  self->general_format = GL_RGBA;
146  }
147 }

References TRUE.

Referenced by fl_compositor_opengl_create_backing_store().

◆ is_vivante()

static gboolean is_vivante ( )
static

Definition at line 97 of file fl_compositor_opengl.cc.

97  {
98  const gchar* vendor = reinterpret_cast<const gchar*>(glGetString(GL_VENDOR));
99  return strstr(vendor, "Vivante Corporation") != nullptr;
100 }

Referenced by fl_compositor_opengl_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 129 of file fl_compositor_opengl.cc.

129  {
130  return (2.0 * position / pixels) - 1.0;
131 }

Referenced by render_with_textures().

◆ present_layers()

static gboolean present_layers ( FlCompositorOpenGL *  self,
FlutterViewId  view_id,
const FlutterLayer **  layers,
size_t  layers_count 
)
static

Definition at line 295 of file fl_compositor_opengl.cc.

298  {
299  g_return_val_if_fail(FL_IS_COMPOSITOR_OPENGL(self), FALSE);
300 
301  // ignore incoming frame with wrong dimensions in trivial case with just one
302  // layer
303  if (self->blocking_main_thread && layers_count == 1 &&
304  layers[0]->offset.x == 0 && layers[0]->offset.y == 0 &&
305  (layers[0]->size.width != self->target_width ||
306  layers[0]->size.height != self->target_height)) {
307  return TRUE;
308  }
309 
310  self->had_first_frame = true;
311 
313 
314  g_autoptr(GPtrArray) framebuffers =
315  g_ptr_array_new_with_free_func(g_object_unref);
316  for (size_t i = 0; i < layers_count; ++i) {
317  const FlutterLayer* layer = layers[i];
318  switch (layer->type) {
319  case kFlutterLayerContentTypeBackingStore: {
320  const FlutterBackingStore* backing_store = layer->backing_store;
321  FlFramebuffer* framebuffer =
322  FL_FRAMEBUFFER(backing_store->open_gl.framebuffer.user_data);
323  g_ptr_array_add(framebuffers, g_object_ref(framebuffer));
324  } break;
325  case kFlutterLayerContentTypePlatformView: {
326  // TODO(robert-ancell) Not implemented -
327  // https://github.com/flutter/flutter/issues/41724
328  } break;
329  }
330  }
331 
332  g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
333  if (engine == nullptr) {
334  return TRUE;
335  }
336  g_autoptr(FlRenderable) renderable =
338  if (renderable == nullptr) {
339  return TRUE;
340  }
341 
342  if (view_id == flutter::kFlutterImplicitViewId) {
343  // Store for rendering later
344  g_hash_table_insert(self->framebuffers_by_view_id, GINT_TO_POINTER(view_id),
345  g_ptr_array_ref(framebuffers));
346  } else {
347  // Composite into a single framebuffer.
348  if (framebuffers->len > 1) {
349  size_t width = 0, height = 0;
350 
351  for (guint i = 0; i < framebuffers->len; i++) {
352  FlFramebuffer* framebuffer =
353  FL_FRAMEBUFFER(g_ptr_array_index(framebuffers, i));
354 
355  size_t w = fl_framebuffer_get_width(framebuffer);
356  size_t h = fl_framebuffer_get_height(framebuffer);
357  if (w > width) {
358  width = w;
359  }
360  if (h > height) {
361  height = h;
362  }
363  }
364 
365  FlFramebuffer* view_framebuffer =
366  fl_framebuffer_new(self->general_format, width, height);
367  glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
368  fl_framebuffer_get_id(view_framebuffer));
369  render(self, framebuffers, width, height);
370  g_ptr_array_set_size(framebuffers, 0);
371  g_ptr_array_add(framebuffers, view_framebuffer);
372  }
373 
374  // Read back pixel values.
375  FlFramebuffer* framebuffer =
376  FL_FRAMEBUFFER(g_ptr_array_index(framebuffers, 0));
377  size_t width = fl_framebuffer_get_width(framebuffer);
378  size_t height = fl_framebuffer_get_height(framebuffer);
379  size_t data_length = width * height * 4;
380  g_autofree uint8_t* data = static_cast<uint8_t*>(malloc(data_length));
381  glBindFramebuffer(GL_READ_FRAMEBUFFER, fl_framebuffer_get_id(framebuffer));
382  glReadPixels(0, 0, width, height, self->general_format, GL_UNSIGNED_BYTE,
383  data);
384 
385  // Write into a texture in the views context.
386  fl_renderable_make_current(renderable);
387  FlFramebuffer* view_framebuffer =
388  fl_framebuffer_new(self->general_format, width, height);
389  glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
390  fl_framebuffer_get_id(view_framebuffer));
391  glBindTexture(GL_TEXTURE_2D,
392  fl_framebuffer_get_texture_id(view_framebuffer));
393  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
394  GL_UNSIGNED_BYTE, data);
395 
396  g_autoptr(GPtrArray) secondary_framebuffers =
397  g_ptr_array_new_with_free_func(g_object_unref);
398  g_ptr_array_add(secondary_framebuffers, g_object_ref(view_framebuffer));
399  g_hash_table_insert(self->framebuffers_by_view_id, GINT_TO_POINTER(view_id),
400  g_ptr_array_ref(secondary_framebuffers));
401  }
402 
403  fl_renderable_redraw(renderable);
404 
405  return TRUE;
406 }
FlRenderable * fl_engine_get_renderable(FlEngine *self, FlutterViewId view_id)
Definition: fl_engine.cc:806
size_t fl_framebuffer_get_height(FlFramebuffer *self)
size_t fl_framebuffer_get_width(FlFramebuffer *self)
GLuint fl_framebuffer_get_texture_id(FlFramebuffer *self)
void fl_renderable_make_current(FlRenderable *self)
void fl_renderable_redraw(FlRenderable *self)

References fl_compositor_opengl_unblock_main_thread(), fl_engine_get_renderable(), 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(), height, i, render(), TRUE, view_id, and width.

Referenced by present_layers_task_cb().

◆ present_layers_task_cb()

static void present_layers_task_cb ( gpointer  user_data)
static

Definition at line 422 of file fl_compositor_opengl.cc.

422  {
423  PresentLayersData* data = static_cast<PresentLayersData*>(user_data);
424  FlCompositorOpenGL* self = data->self;
425 
426  // Perform the present.
427  fl_opengl_manager_make_current(self->opengl_manager);
428  data->result =
429  present_layers(self, data->view_id, data->layers, data->layers_count);
430  fl_opengl_manager_clear_current(self->opengl_manager);
431 
432  // Complete fl_compositor_opengl_present_layers().
433  g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->present_mutex);
434  data->finished = TRUE;
435  g_cond_signal(&self->present_condition);
436 }
static gboolean present_layers(FlCompositorOpenGL *self, FlutterViewId view_id, const FlutterLayer **layers, size_t layers_count)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue gpointer user_data
const FlutterLayer ** layers

References PresentLayersData::finished, fl_opengl_manager_clear_current(), fl_opengl_manager_make_current(), PresentLayersData::layers, PresentLayersData::layers_count, present_layers(), PresentLayersData::result, PresentLayersData::self, TRUE, user_data, and PresentLayersData::view_id.

Referenced by fl_compositor_opengl_present_layers().

◆ render()

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

Definition at line 284 of file fl_compositor_opengl.cc.

287  {
288  if (self->has_gl_framebuffer_blit) {
289  render_with_blit(self, framebuffers);
290  } else {
291  render_with_textures(self, framebuffers, width, height);
292  }
293 }
static void render_with_textures(FlCompositorOpenGL *self, GPtrArray *framebuffers, int width, int height)
static void render_with_blit(FlCompositorOpenGL *self, GPtrArray *framebuffers)

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

Referenced by fl_compositor_opengl_render(), and present_layers().

◆ render_with_blit()

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

Definition at line 197 of file fl_compositor_opengl.cc.

198  {
199  // Disable the scissor test as it can affect blit operations.
200  // Prevents regressions like: https://github.com/flutter/flutter/issues/140828
201  // See OpenGL specification version 4.6, section 18.3.1.
202  glDisable(GL_SCISSOR_TEST);
203 
204  for (guint i = 0; i < framebuffers->len; i++) {
205  FlFramebuffer* framebuffer =
206  FL_FRAMEBUFFER(g_ptr_array_index(framebuffers, i));
207 
208  GLuint framebuffer_id = fl_framebuffer_get_id(framebuffer);
209  glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer_id);
210  size_t width = fl_framebuffer_get_width(framebuffer);
211  size_t height = fl_framebuffer_get_height(framebuffer);
212  glBlitFramebuffer(0, 0, width, height, 0, 0, width, height,
213  GL_COLOR_BUFFER_BIT, GL_NEAREST);
214  }
215  glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
216 }

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 ( FlCompositorOpenGL *  self,
GPtrArray *  framebuffers,
int  width,
int  height 
)
static

Definition at line 218 of file fl_compositor_opengl.cc.

221  {
222  // Save bindings that are set by this function. All bindings must be restored
223  // to their original values because Skia expects that its bindings have not
224  // been altered.
225  GLint saved_texture_binding;
226  glGetIntegerv(GL_TEXTURE_BINDING_2D, &saved_texture_binding);
227  GLint saved_vao_binding;
228  glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &saved_vao_binding);
229  GLint saved_array_buffer_binding;
230  glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &saved_array_buffer_binding);
231 
232  glEnable(GL_BLEND);
233  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
234 
235  glUseProgram(self->program);
236 
237  for (guint i = 0; i < framebuffers->len; i++) {
238  FlFramebuffer* framebuffer =
239  FL_FRAMEBUFFER(g_ptr_array_index(framebuffers, i));
240 
241  GLuint texture_id = fl_framebuffer_get_texture_id(framebuffer);
242  glBindTexture(GL_TEXTURE_2D, texture_id);
243 
244  // Translate into OpenGL co-ordinates
245  size_t texture_width = fl_framebuffer_get_width(framebuffer);
246  size_t texture_height = fl_framebuffer_get_height(framebuffer);
247  GLfloat x0 = pixels_to_gl_coords(0, width);
248  GLfloat y0 = pixels_to_gl_coords(height - texture_height, height);
249  GLfloat x1 = pixels_to_gl_coords(texture_width, width);
250  GLfloat y1 = pixels_to_gl_coords(height, height);
251  GLfloat vertex_data[] = {x0, y0, 0, 0, x1, y1, 1, 1, x0, y1, 0, 1,
252  x0, y0, 0, 0, x1, y0, 1, 0, x1, y1, 1, 1};
253 
254  GLuint vao, vertex_buffer;
255  glGenVertexArrays(1, &vao);
256  glBindVertexArray(vao);
257  glGenBuffers(1, &vertex_buffer);
258  glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
259  glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data,
260  GL_STATIC_DRAW);
261  GLint position_index = glGetAttribLocation(self->program, "position");
262  glEnableVertexAttribArray(position_index);
263  glVertexAttribPointer(position_index, 2, GL_FLOAT, GL_FALSE,
264  sizeof(GLfloat) * 4, 0);
265  GLint texcoord_index = glGetAttribLocation(self->program, "in_texcoord");
266  glEnableVertexAttribArray(texcoord_index);
267  glVertexAttribPointer(texcoord_index, 2, GL_FLOAT, GL_FALSE,
268  sizeof(GLfloat) * 4,
269  reinterpret_cast<void*>(sizeof(GLfloat) * 2));
270 
271  glDrawArrays(GL_TRIANGLES, 0, 6);
272 
273  glDeleteVertexArrays(1, &vao);
274  glDeleteBuffers(1, &vertex_buffer);
275  }
276 
277  glDisable(GL_BLEND);
278 
279  glBindTexture(GL_TEXTURE_2D, saved_texture_binding);
280  glBindVertexArray(saved_vao_binding);
281  glBindBuffer(GL_ARRAY_BUFFER, saved_array_buffer_binding);
282 }
static GLfloat pixels_to_gl_coords(GLfloat position, GLfloat pixels)
Converts a pixel co-ordinate from 0..pixels to OpenGL -1..1.
int64_t texture_id

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

Referenced by render().

◆ setup_shader()

static void setup_shader ( FlCompositorOpenGL *  self)
static

Definition at line 160 of file fl_compositor_opengl.cc.

160  {
161  GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
162  glShaderSource(vertex_shader, 1, &vertex_shader_src, nullptr);
163  glCompileShader(vertex_shader);
164  GLint vertex_compile_status;
165  glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &vertex_compile_status);
166  if (vertex_compile_status == GL_FALSE) {
167  g_autofree gchar* shader_log = get_shader_log(vertex_shader);
168  g_warning("Failed to compile vertex shader: %s", shader_log);
169  }
170 
171  GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
172  glShaderSource(fragment_shader, 1, &fragment_shader_src, nullptr);
173  glCompileShader(fragment_shader);
174  GLint fragment_compile_status;
175  glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &fragment_compile_status);
176  if (fragment_compile_status == GL_FALSE) {
177  g_autofree gchar* shader_log = get_shader_log(fragment_shader);
178  g_warning("Failed to compile fragment shader: %s", shader_log);
179  }
180 
181  self->program = glCreateProgram();
182  glAttachShader(self->program, vertex_shader);
183  glAttachShader(self->program, fragment_shader);
184  glLinkProgram(self->program);
185 
186  GLint link_status;
187  glGetProgramiv(self->program, GL_LINK_STATUS, &link_status);
188  if (link_status == GL_FALSE) {
189  g_autofree gchar* program_log = get_program_log(self->program);
190  g_warning("Failed to link program: %s", program_log);
191  }
192 
193  glDeleteShader(vertex_shader);
194  glDeleteShader(fragment_shader);
195 }
static gchar * get_shader_log(GLuint shader)
static const char * fragment_shader_src
static gchar * get_program_log(GLuint program)
static const char * vertex_shader_src

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

Referenced by fl_compositor_opengl_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_compositor_opengl.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_compositor_opengl.cc.

Referenced by setup_shader().