| 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 driver_supports_blit()
static gchar * | get_shader_log (GLuint shader)
static gchar * | get_program_log (GLuint program)
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, const FlutterLayer **layers, size_t layers_count)
static void | present_layers_task_cb (gpointer user_data)
static FlutterRendererType | fl_compositor_opengl_get_renderer_type (FlCompositor *compositor)
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, 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, GdkGLContext *context)
void | fl_compositor_opengl_render (FlCompositorOpenGL *self, int width, int height)
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 503 of file fl_compositor_opengl.cc.

503 {
504 FL_COMPOSITOR_CLASS(klass)->get_renderer_type =
505 fl_compositor_opengl_get_renderer_type;
506 FL_COMPOSITOR_CLASS(klass)->wait_for_frame =
507 fl_compositor_opengl_wait_for_frame;
508 FL_COMPOSITOR_CLASS(klass)->present_layers =
509 fl_compositor_opengl_present_layers;
510
511 G_OBJECT_CLASS(klass)->dispose = fl_compositor_opengl_dispose;
512 }
fl_compositor_opengl_dispose
static void fl_compositor_opengl_dispose(GObject *object)
Definition: fl_compositor_opengl.cc:488
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:436
fl_compositor_opengl_present_layers
static gboolean fl_compositor_opengl_present_layers(FlCompositor *compositor, const FlutterLayer **layers, size_t layers_count)
Definition: fl_compositor_opengl.cc:453
fl_compositor_opengl_get_renderer_type
static FlutterRendererType fl_compositor_opengl_get_renderer_type(FlCompositor *compositor)
Definition: fl_compositor_opengl.cc:431

References fl_compositor_opengl_dispose(), fl_compositor_opengl_get_renderer_type(), 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 558 of file fl_compositor_opengl.cc.

558 {
559 g_return_if_fail(FL_IS_COMPOSITOR_OPENGL(self));
560
561 if (self->program != 0) {
562 glDeleteProgram(self->program);
563 }
564 if (self->vertex_buffer != 0) {
565 glDeleteBuffers(1, &self->vertex_buffer);
566 }
567 }

Referenced by unrealize_cb().

## ◆ fl_compositor_opengl_dispose()

static void fl_compositor_opengl_dispose | ( | GObject * | object | ) |
| static

Definition at line 488 of file fl_compositor_opengl.cc.

488 {
489 FlCompositorOpenGL* self = FL_COMPOSITOR_OPENGL(object);
490
491 fl_compositor_opengl_unblock_main_thread(self);
492
493 g_weak_ref_clear(&self->engine);
494 g_clear_object(&self->context);
495 g_clear_object(&self->opengl_manager);
496 g_clear_pointer(&self->framebuffers, g_ptr_array_unref);
497 g_mutex_clear(&self->present_mutex);
498 g_cond_clear(&self->present_condition);
499
500 G_OBJECT_CLASS(fl_compositor_opengl_parent_class)->dispose(object);
501 }
fl_compositor_opengl_unblock_main_thread
static void fl_compositor_opengl_unblock_main_thread(FlCompositorOpenGL *self)
Definition: fl_compositor_opengl.cc:143

References fl_compositor_opengl_unblock_main_thread().

Referenced by fl_compositor_opengl_class_init().

## ◆ fl_compositor_opengl_get_renderer_type()

static FlutterRendererType fl_compositor_opengl_get_renderer_type | ( | FlCompositor * | compositor | ) |
| static

Definition at line 431 of file fl_compositor_opengl.cc.

432 {
433 return kOpenGL;
434 }

Referenced by fl_compositor_opengl_class_init().

## ◆ fl_compositor_opengl_init()

static void fl_compositor_opengl_init | ( | FlCompositorOpenGL * | self | ) |
| static

Definition at line 514 of file fl_compositor_opengl.cc.

514 {
515 self->framebuffers = g_ptr_array_new();
516 g_mutex_init(&self->present_mutex);
517 g_cond_init(&self->present_condition);
518 }

## ◆ fl_compositor_opengl_new()

FlCompositorOpenGL* fl_compositor_opengl_new | ( | FlEngine * | engine,
|  | GdkGLContext * | context
| ) |  |

Definition at line 520 of file fl_compositor_opengl.cc.

521 {
522 FlCompositorOpenGL* self = FL_COMPOSITOR_OPENGL(
523 g_object_new(fl_compositor_opengl_get_type(), nullptr));
524
525 g_weak_ref_init(&self->engine, engine);
526 self->context =
527 context != nullptr ? GDK_GL_CONTEXT(g_object_ref(context)) : nullptr;
528 self->opengl_manager =
529 FL_OPENGL_MANAGER(g_object_ref(fl_engine_get_opengl_manager(engine)));
530
531 fl_opengl_manager_make_current(self->opengl_manager);
532
533 self->has_gl_framebuffer_blit =
534 driver_supports_blit() &&
535 (epoxy_gl_version() >= 30 ||
536 epoxy_has_gl_extension("GL_EXT_framebuffer_blit"));
537
538 if (!self->has_gl_framebuffer_blit) {
539 setup_shader(self);
540 }
541
542 return self;
543 }
setup_shader
static void setup_shader(FlCompositorOpenGL *self)
Definition: fl_compositor_opengl.cc:154
context
G_BEGIN_DECLS GdkGLContext * context
Definition: fl_compositor_opengl.h:38
fl_engine_get_opengl_manager
FlOpenGLManager * fl_engine_get_opengl_manager(FlEngine *self)
Definition: fl_engine.cc:710
fl_opengl_manager_make_current
void fl_opengl_manager_make_current(FlOpenGLManager *self)
Definition: fl_opengl_manager.cc:82

References context, fl_engine_get_opengl_manager(), fl_opengl_manager_make_current(), and setup_shader().

Referenced by realize_cb(), and TEST().

## ◆ fl_compositor_opengl_present_layers()

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

Definition at line 453 of file fl_compositor_opengl.cc.

455 {
456 FlCompositorOpenGL* self = FL_COMPOSITOR_OPENGL(compositor);
457
458 // Detach the context from raster thread. Needed because blitting
459 // will be done on the main thread, which will make the context current.
460 fl_opengl_manager_clear_current(self->opengl_manager);
461
462 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
463
464 // Schedule the present to run on the main thread.
465 FlTaskRunner* task_runner = fl_engine_get_task_runner(engine);
466 PresentLayersData data = {
467 .self = self,
468 .layers = layers,
469 .layers_count = layers_count,
470 .result = FALSE,
471 .finished = FALSE,
472 };
473 fl_task_runner_post_callback(task_runner, present_layers_task_cb, &data);
474
475 // Block until present completes.
476 g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->present_mutex);
477 while (!data.finished) {
478 g_cond_wait(&self->present_condition, &self->present_mutex);
479 }
480
481 // Restore the context to the raster thread in case the engine needs it
482 // to do some cleanup.
483 fl_opengl_manager_make_current(self->opengl_manager);
484
485 return data.result;
486 }
present_layers_task_cb
static void present_layers_task_cb(gpointer user_data)
Definition: fl_compositor_opengl.cc:416
fl_engine_get_task_runner
FlTaskRunner * fl_engine_get_task_runner(FlEngine *self)
Definition: fl_engine.cc:1419
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
PresentLayersData
Definition: fl_compositor_opengl.cc:404
PresentLayersData::self
FlCompositorOpenGL * self
Definition: fl_compositor_opengl.cc:405
PresentLayersData::finished
gboolean finished
Definition: fl_compositor_opengl.cc:412
PresentLayersData::result
gboolean result
Definition: fl_compositor_opengl.cc:410

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, and PresentLayersData::self.

Referenced by fl_compositor_opengl_class_init().

## ◆ fl_compositor_opengl_render()

void fl_compositor_opengl_render | ( | FlCompositorOpenGL * | compositor,
|  | int | width,
|  | int | height
| ) |  |

fl_compositor_opengl_render: @compositor: an #FlCompositorOpenGL. @width: width of the window in pixels. @height: height of the window in pixels.

Performs OpenGL commands to render current Flutter view.

Definition at line 545 of file fl_compositor_opengl.cc.

547 {
548 g_return_if_fail(FL_IS_COMPOSITOR_OPENGL(self));
549
550 glClearColor(0.0, 0.0, 0.0, 0.0);
551 glClear(GL_COLOR_BUFFER_BIT);
552
553 render(self, self->framebuffers, width, height);
554
555 glFlush();
556 }
render
static void render(FlCompositorOpenGL *self, GPtrArray *framebuffers, int width, int height)
Definition: fl_compositor_opengl.cc:289
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(), and width.

Referenced by render_cb(), and TEST().

## ◆ fl_compositor_opengl_unblock_main_thread()

static void fl_compositor_opengl_unblock_main_thread | ( | FlCompositorOpenGL * | self | ) |
| static

Definition at line 143 of file fl_compositor_opengl.cc.

143 {
144 if (self->blocking_main_thread) {
145 self->blocking_main_thread = false;
146
147 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
148 if (engine != nullptr) {
149 fl_task_runner_release_main_thread(fl_engine_get_task_runner(engine));
150 }
151 }
152 }
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 436 of file fl_compositor_opengl.cc.

438 {
439 FlCompositorOpenGL* self = FL_COMPOSITOR_OPENGL(compositor);
440
441 self->target_width = target_width;
442 self->target_height = target_height;
443
444 if (self->had_first_frame && !self->blocking_main_thread) {
445 self->blocking_main_thread = true;
446 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&self->engine));
447 if (engine != nullptr) {
448 fl_task_runner_block_main_thread(fl_engine_get_task_runner(engine));
449 }
450 }
451 }
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 91 of file fl_compositor_opengl.cc.

96 {
97 const gchar* vendor = reinterpret_cast<const gchar*>(glGetString(GL_VENDOR));
98
99 // Note: List of unsupported vendors due to issue
100 // https://github.com/flutter/flutter/issues/152099
101 const char* unsupported_vendors_exact[] = {"Vivante Corporation", "ARM"};
102 const char* unsupported_vendors_fuzzy[] = {"NVIDIA"};
103
104 for (const char* unsupported : unsupported_vendors_fuzzy) {
105 if (strstr(vendor, unsupported) != nullptr) {
106 return FALSE;
107 }
108 }
109 for (const char* unsupported : unsupported_vendors_exact) {
110 if (strcmp(vendor, unsupported) == 0) {
111 return FALSE;
112 }
113 }
114 return TRUE;
115 }
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53

References TRUE.

## ◆ get_program_log()

static gchar* get_program_log | ( | GLuint | program | ) |
| static

Definition at line 131 of file fl_compositor_opengl.cc.

131 {
132 GLint log_length;
133 gchar* log;
134
135 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
136
137 log = static_cast<gchar*>(g_malloc(log_length + 1));
138 glGetProgramInfoLog(program, log_length, nullptr, log);
139
140 return log;
141 }

Referenced by setup_shader().

## ◆ get_shader_log()

static gchar* get_shader_log | ( | GLuint | shader | ) |
| static

Definition at line 118 of file fl_compositor_opengl.cc.

118 {
119 GLint log_length;
120 gchar* log;
121
122 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
123
124 log = static_cast<gchar*>(g_malloc(log_length + 1));
125 glGetShaderInfoLog(shader, log_length, nullptr, log);
126
127 return log;
128 }

Referenced by setup_shader().

## ◆ present_layers()

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

Definition at line 300 of file fl_compositor_opengl.cc.

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

References fl_compositor_opengl_unblock_main_thread(), fl_framebuffer_get_height(), fl_framebuffer_get_id(), fl_framebuffer_get_texture_id(), fl_framebuffer_get_width(), fl_framebuffer_new(), height, i, render(), TRUE, 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 416 of file fl_compositor_opengl.cc.

416 {
417 PresentLayersData* data = static_cast<PresentLayersData*>(user_data);
418 FlCompositorOpenGL* self = data->self;
419
420 // Perform the present.
421 fl_opengl_manager_make_current(self->opengl_manager);
422 data->result = present_layers(self, data->layers, data->layers_count);
423 fl_opengl_manager_clear_current(self->opengl_manager);
424
425 // Complete fl_compositor_opengl_present_layers().
426 g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->present_mutex);
427 data->finished = TRUE;
428 g_cond_signal(&self->present_condition);
429 }
present_layers
static gboolean present_layers(FlCompositorOpenGL *self, const FlutterLayer **layers, size_t layers_count)
Definition: fl_compositor_opengl.cc:300
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:407
PresentLayersData::layers_count
size_t layers_count
Definition: fl_compositor_opengl.cc:408

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, and user_data.

Referenced by fl_compositor_opengl_present_layers().

## ◆ render()

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

Definition at line 289 of file fl_compositor_opengl.cc.

292 {
293 if (self->has_gl_framebuffer_blit) {
294 render_with_blit(self, framebuffers);
295 } else {
296 render_with_textures(self, framebuffers, width, height);
297 }
298 }
render_with_textures
static void render_with_textures(FlCompositorOpenGL *self, GPtrArray *framebuffers, int width, int height)
Definition: fl_compositor_opengl.cc:227
render_with_blit
static void render_with_blit(FlCompositorOpenGL *self, GPtrArray *framebuffers)
Definition: fl_compositor_opengl.cc:206

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 206 of file fl_compositor_opengl.cc.

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

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 227 of file fl_compositor_opengl.cc.

230 {
231 // Save bindings that are set by this function. All bindings must be restored
232 // to their original values because Skia expects that its bindings have not
233 // been altered.
234 GLint saved_texture_binding;
235 glGetIntegerv(GL_TEXTURE_BINDING_2D, &saved_texture_binding);
236 GLint saved_vao_binding;
237 glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &saved_vao_binding);
238 GLint saved_array_buffer_binding;
239 glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &saved_array_buffer_binding);
240
241 // FIXME(robert-ancell): The vertex array is the same for all views, but
242 // cannot be shared in OpenGL. Find a way to not generate this every time.
243 GLuint vao;
244 glGenVertexArrays(1, &vao);
245 glBindVertexArray(vao);
246 glBindBuffer(GL_ARRAY_BUFFER, self->vertex_buffer);
247 GLint position_location = glGetAttribLocation(self->program, "position");
248 glEnableVertexAttribArray(position_location);
249 glVertexAttribPointer(position_location, 2, GL_FLOAT, GL_FALSE,
250 sizeof(GLfloat) * 4, 0);
251 GLint texcoord_location = glGetAttribLocation(self->program, "in_texcoord");
252 glEnableVertexAttribArray(texcoord_location);
253 glVertexAttribPointer(texcoord_location, 2, GL_FLOAT, GL_FALSE,
254 sizeof(GLfloat) * 4,
255 reinterpret_cast<void*>(sizeof(GLfloat) * 2));
256
257 glEnable(GL_BLEND);
258 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
259
260 glUseProgram(self->program);
261
262 for (guint i = 0; i < framebuffers->len; i++) {
263 FlFramebuffer* framebuffer =
264 FL_FRAMEBUFFER(g_ptr_array_index(framebuffers, i));
265
266 // FIXME(robert-ancell): The offset from present_layers() is not here, needs
267 // to be updated.
268 size_t texture_width = fl_framebuffer_get_width(framebuffer);
269 size_t texture_height = fl_framebuffer_get_height(framebuffer);
270 glUniform2f(self->offset_location, 0, 0);
271 glUniform2f(self->scale_location, texture_width / width,
272 texture_height / height);
273
274 GLuint texture_id = fl_framebuffer_get_texture_id(framebuffer);
275 glBindTexture(GL_TEXTURE_2D, texture_id);
276
277 glDrawArrays(GL_TRIANGLES, 0, 6);
278 }
279
280 glDeleteVertexArrays(1, &vao);
281
282 glDisable(GL_BLEND);
283
284 glBindTexture(GL_TEXTURE_2D, saved_texture_binding);
285 glBindVertexArray(saved_vao_binding);
286 glBindBuffer(GL_ARRAY_BUFFER, saved_array_buffer_binding);
287 }
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, texture_id, and width.

Referenced by render().

## ◆ setup_shader()

static void setup_shader | ( | FlCompositorOpenGL * | self | ) |
| static

Definition at line 154 of file fl_compositor_opengl.cc.

154 {
155 GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
156 glShaderSource(vertex_shader, 1, &vertex_shader_src, nullptr);
157 glCompileShader(vertex_shader);
158 GLint vertex_compile_status;
159 glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &vertex_compile_status);
160 if (vertex_compile_status == GL_FALSE) {
161 g_autofree gchar* shader_log = get_shader_log(vertex_shader);
162 g_warning("Failed to compile vertex shader: %s", shader_log);
163 }
164
165 GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
166 glShaderSource(fragment_shader, 1, &fragment_shader_src, nullptr);
167 glCompileShader(fragment_shader);
168 GLint fragment_compile_status;
169 glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &fragment_compile_status);
170 if (fragment_compile_status == GL_FALSE) {
171 g_autofree gchar* shader_log = get_shader_log(fragment_shader);
172 g_warning("Failed to compile fragment shader: %s", shader_log);
173 }
174
175 self->program = glCreateProgram();
176 glAttachShader(self->program, vertex_shader);
177 glAttachShader(self->program, fragment_shader);
178 glLinkProgram(self->program);
179
180 GLint link_status;
181 glGetProgramiv(self->program, GL_LINK_STATUS, &link_status);
182 if (link_status == GL_FALSE) {
183 g_autofree gchar* program_log = get_program_log(self->program);
184 g_warning("Failed to link program: %s", program_log);
185 }
186
187 self->offset_location = glGetUniformLocation(self->program, "offset");
188 self->scale_location = glGetUniformLocation(self->program, "scale");
189
190 glDeleteShader(vertex_shader);
191 glDeleteShader(fragment_shader);
192
193 // The uniform square abcd in two triangles cba + cdb
194 // a--b
195 // | |
196 // c--d
197 GLfloat vertex_data[] = {-1, -1, 0, 0, 1, 1, 1, 1, -1, 1, 0, 1,
198 -1, -1, 0, 0, 1, -1, 1, 0, 1, 1, 1, 1};
199
200 glGenBuffers(1, &self->vertex_buffer);
201 glBindBuffer(GL_ARRAY_BUFFER, self->vertex_buffer);
202 glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data,
203 GL_STATIC_DRAW);
204 }
get_shader_log
static gchar * get_shader_log(GLuint shader)
Definition: fl_compositor_opengl.cc:118
fragment_shader_src
static const char * fragment_shader_src
Definition: fl_compositor_opengl.cc:29
get_program_log
static gchar * get_program_log(GLuint program)
Definition: fl_compositor_opengl.cc:131
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_new().

## 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 29 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"
"uniform vec2 offset;\n"
"uniform vec2 scale;\n"
"varying vec2 texcoord;\n"
"\n"
"void main() {\n"
" gl_Position = vec4(offset + position * scale, 0, 1);\n"
" texcoord = in_texcoord;\n"
"}\n"

Definition at line 16 of file fl_compositor_opengl.cc.

Referenced by setup_shader().