| Flutter Linux Embedder |

Classes | Functions | Variables
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 =
552 fl_compositor_opengl_create_backing_store;
553 FL_COMPOSITOR_CLASS(klass)->collect_backing_store =
554 fl_compositor_opengl_collect_backing_store;
555 FL_COMPOSITOR_CLASS(klass)->wait_for_frame =
556 fl_compositor_opengl_wait_for_frame;
557 FL_COMPOSITOR_CLASS(klass)->present_layers =
558 fl_compositor_opengl_present_layers;
559
560 G_OBJECT_CLASS(klass)->dispose = fl_compositor_opengl_dispose;
561 }
fl_compositor_opengl_dispose
static void fl_compositor_opengl_dispose(GObject *object)
Definition: fl_compositor_opengl.cc:536
fl_compositor_opengl_wait_for_frame
static void fl_compositor_opengl_wait_for_frame(FlCompositor *compositor, int target_width, int target_height)
Definition: fl_compositor_opengl.cc:482
fl_compositor_opengl_create_backing_store
static gboolean fl_compositor_opengl_create_backing_store(FlCompositor *compositor, const FlutterBackingStoreConfig *config, FlutterBackingStore *backing_store_out)
Definition: fl_compositor_opengl.cc:438
fl_compositor_opengl_present_layers
static gboolean fl_compositor_opengl_present_layers(FlCompositor *compositor, FlutterViewId view_id, const FlutterLayer **layers, size_t layers_count)
Definition: fl_compositor_opengl.cc:499
fl_compositor_opengl_collect_backing_store
static gboolean fl_compositor_opengl_collect_backing_store(FlCompositor *compositor, const FlutterBackingStore *backing_store)
Definition: fl_compositor_opengl.cc:470

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 }
fl_opengl_manager_make_current
void fl_opengl_manager_make_current(FlOpenGLManager *self)
Definition: fl_opengl_manager.cc:82
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53

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 }
initialize
static void initialize(FlCompositorOpenGL *self)
Definition: fl_compositor_opengl.cc:134
fl_framebuffer_get_id
GLuint fl_framebuffer_get_id(FlFramebuffer *self)
Definition: fl_framebuffer.cc:82
fl_framebuffer_new
FlFramebuffer * fl_framebuffer_new(GLint format, size_t width, size_t height)
Definition: fl_framebuffer.cc:42

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
539 fl_compositor_opengl_unblock_main_thread(self);
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 }
fl_compositor_opengl_unblock_main_thread
static void fl_compositor_opengl_unblock_main_thread(FlCompositorOpenGL *self)
Definition: fl_compositor_opengl.cc:149

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 }
fl_engine_get_opengl_manager
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 };
521 fl_task_runner_post_callback(task_runner, present_layers_task_cb, &data);
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 }
present_layers_task_cb
static void present_layers_task_cb(gpointer user_data)
Definition: fl_compositor_opengl.cc:422
fl_engine_get_task_runner
FlTaskRunner * fl_engine_get_task_runner(FlEngine *self)
Definition: fl_engine.cc:1287
fl_opengl_manager_clear_current
void fl_opengl_manager_clear_current(FlOpenGLManager *self)
Definition: fl_opengl_manager.cc:90
fl_task_runner_post_callback
void fl_task_runner_post_callback(FlTaskRunner *self, void(*callback)(gpointer data), gpointer data)
Definition: fl_task_runner.cc:189
view_id
G_BEGIN_DECLS FlutterViewId view_id
Definition: fl_view_accessible.h:49
PresentLayersData
Definition: fl_compositor_opengl.cc:408
PresentLayersData::self
FlCompositorOpenGL * self
Definition: fl_compositor_opengl.cc:409
PresentLayersData::finished
gboolean finished
Definition: fl_compositor_opengl.cc:418
PresentLayersData::result
gboolean result
Definition: fl_compositor_opengl.cc:416

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 }
render
static void render(FlCompositorOpenGL *self, GPtrArray *framebuffers, int width, int height)
Definition: fl_compositor_opengl.cc:284
height
const uint8_t uint32_t uint32_t * height
Definition: fl_pixel_buffer_texture_test.cc:39
width
const uint8_t uint32_t * width
Definition: fl_pixel_buffer_texture_test.cc:38

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 }
setup_shader
static void setup_shader(FlCompositorOpenGL *self)
Definition: fl_compositor_opengl.cc:160
is_vivante
static gboolean is_vivante()
Definition: fl_compositor_opengl.cc:97

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) {
155 fl_task_runner_release_main_thread(fl_engine_get_task_runner(engine));
156 }
157 }
158 }
fl_task_runner_release_main_thread
void fl_task_runner_release_main_thread(FlTaskRunner *self)
Definition: fl_task_runner.cc:224

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) {
494 fl_task_runner_block_main_thread(fl_engine_get_task_runner(engine));
495 }
496 }
497 }
fl_task_runner_block_main_thread
void fl_task_runner_block_main_thread(FlTaskRunner *self)
Definition: fl_task_runner.cc:203

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
312 fl_compositor_opengl_unblock_main_thread(self);
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 =
337 fl_engine_get_renderable(engine, view_id);
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 }
fl_engine_get_renderable
FlRenderable * fl_engine_get_renderable(FlEngine *self, FlutterViewId view_id)
Definition: fl_engine.cc:806
fl_framebuffer_get_height
size_t fl_framebuffer_get_height(FlFramebuffer *self)
Definition: fl_framebuffer.cc:98
fl_framebuffer_get_width
size_t fl_framebuffer_get_width(FlFramebuffer *self)
Definition: fl_framebuffer.cc:94
fl_framebuffer_get_texture_id
GLuint fl_framebuffer_get_texture_id(FlFramebuffer *self)
Definition: fl_framebuffer.cc:86
fl_renderable_make_current
void fl_renderable_make_current(FlRenderable *self)
Definition: fl_renderable.cc:17
fl_renderable_redraw
void fl_renderable_redraw(FlRenderable *self)
Definition: fl_renderable.cc:11
i
int i
Definition: fl_socket_accessible.cc:18

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 }
present_layers
static gboolean present_layers(FlCompositorOpenGL *self, FlutterViewId view_id, const FlutterLayer **layers, size_t layers_count)
Definition: fl_compositor_opengl.cc:295
user_data
G_BEGIN_DECLS G_MODULE_EXPORT FlValue gpointer user_data
Definition: fl_event_channel.h:90
PresentLayersData::layers
const FlutterLayer ** layers
Definition: fl_compositor_opengl.cc:413
PresentLayersData::layers_count
size_t layers_count
Definition: fl_compositor_opengl.cc:414
PresentLayersData::view_id
FlutterViewId view_id
Definition: fl_compositor_opengl.cc:411

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 }
render_with_textures
static void render_with_textures(FlCompositorOpenGL *self, GPtrArray *framebuffers, int width, int height)
Definition: fl_compositor_opengl.cc:218
render_with_blit
static void render_with_blit(FlCompositorOpenGL *self, GPtrArray *framebuffers)
Definition: fl_compositor_opengl.cc:197

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 }
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_compositor_opengl.cc:129
texture_id
int64_t texture_id
Definition: texture_registrar_unittests.cc:24

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 }
get_shader_log
static gchar * get_shader_log(GLuint shader)
Definition: fl_compositor_opengl.cc:103
fragment_shader_src
static const char * fragment_shader_src
Definition: fl_compositor_opengl.cc:27
get_program_log
static gchar * get_program_log(GLuint program)
Definition: fl_compositor_opengl.cc:116
vertex_shader_src
static const char * vertex_shader_src
Definition: fl_compositor_opengl.cc:16

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().