| Flutter Linux Embedder |

fl_compositor_opengl.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "fl_compositor_opengl.h"
6
7 #include <epoxy/egl.h>
8 #include <epoxy/gl.h>
9
10 #include "flutter/common/constants.h"
11 #include "flutter/shell/platform/embedder/embedder.h"
12 #include "flutter/shell/platform/linux/fl_engine_private.h"
13 #include "flutter/shell/platform/linux/fl_framebuffer.h"
14
15 // Vertex shader to draw Flutter window contents.
16 static const char* vertex_shader_src =
17 "attribute vec2 position;\n"
18 "attribute vec2 in_texcoord;\n"
19 "varying vec2 texcoord;\n"
20 "\n"
21 "void main() {\n"
22 " gl_Position = vec4(position, 0, 1);\n"
23 " texcoord = in_texcoord;\n"
24 "}\n";
25
26 // Fragment shader to draw Flutter window contents.
27 static const char* fragment_shader_src =
28 "#ifdef GL_ES\n"
29 "precision mediump float;\n"
30 "#endif\n"
31 "\n"
32 "uniform sampler2D texture;\n"
33 "varying vec2 texcoord;\n"
34 "\n"
35 "void main() {\n"
36 " gl_FragColor = texture2D(texture, texcoord);\n"
37 "}\n";
38
39 struct _FlCompositorOpenGL {
40 FlCompositor parent_instance;
41
42 // Engine we are rendering.
43 GWeakRef engine;
44
45 // OpenGL contexts.
46 FlOpenGLManager* opengl_manager;
47
48 // Flag to track lazy initialization.
49 gboolean initialized;
50
51 // The pixel format passed to the engine.
52 GLint sized_format;
53
54 // The format used to create textures.
55 GLint general_format;
56
57 // target dimension for resizing
58 int target_width;
59 int target_height;
60
61 // whether the renderer waits for frame render
62 bool blocking_main_thread;
63
64 // true if frame was completed; resizing is not synchronized until first frame
65 // was rendered
66 bool had_first_frame;
67
68 // True if we can use glBlitFramebuffer.
69 bool has_gl_framebuffer_blit;
70
71 // Shader program.
72 GLuint program;
73
74 // Framebuffers to render keyed by view ID.
75 GHashTable* framebuffers_by_view_id;
76
77 // Mutex used when blocking the raster thread until a task is completed on
78 // platform thread.
79 GMutex present_mutex;
80
81 // Condition to unblock the raster thread after task is completed on platform
82 // thread.
83 GCond present_condition;
84 };
85
86 G_DEFINE_TYPE(FlCompositorOpenGL,
87 fl_compositor_opengl,
88 fl_compositor_get_type())
89
90 // Check if running on an NVIDIA driver.
91 static gboolean is_nvidia() {
92 const gchar* vendor = reinterpret_cast<const gchar*>(glGetString(GL_VENDOR));
93 return strstr(vendor, "NVIDIA") != nullptr;
94 }
95
96 // Check if running on an Vivante Corporation driver.
97 static gboolean is_vivante() {
98 const gchar* vendor = reinterpret_cast<const gchar*>(glGetString(GL_VENDOR));
99 return strstr(vendor, "Vivante Corporation") != nullptr;
100 }
101
102 // Returns the log for the given OpenGL shader. Must be freed by the caller.
103 static gchar* get_shader_log(GLuint shader) {
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 }
114
115 // Returns the log for the given OpenGL program. Must be freed by the caller.
116 static gchar* get_program_log(GLuint program) {
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 }
127
128 /// Converts a pixel co-ordinate from 0..pixels to OpenGL -1..1.
129 static GLfloat pixels_to_gl_coords(GLfloat position, GLfloat pixels) {
130 return (2.0 * position / pixels) - 1.0;
131 }
132
133 // Perform single run OpenGL initialization.
134 static void initialize(FlCompositorOpenGL* self) {
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 }
148
149 static void fl_compositor_opengl_unblock_main_thread(FlCompositorOpenGL* self) {
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 }
159
160 static void setup_shader(FlCompositorOpenGL* self) {
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 }
196
197 static void render_with_blit(FlCompositorOpenGL* self,
198 GPtrArray* framebuffers) {
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 }
217
218 static void render_with_textures(FlCompositorOpenGL* self,
219 GPtrArray* framebuffers,
220 int width,
221 int height) {
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 }
283
284 static void render(FlCompositorOpenGL* self,
285 GPtrArray* framebuffers,
286 int width,
287 int height) {
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 }
294
295 static gboolean present_layers(FlCompositorOpenGL* self,
296 FlutterViewId view_id,
297 const FlutterLayer** layers,
298 size_t layers_count) {
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 }
407
408 typedef struct {
409 FlCompositorOpenGL* self;
410
411 FlutterViewId view_id;
412
413 const FlutterLayer** layers;
414 size_t layers_count;
415
416 gboolean result;
417
418 gboolean finished;
419 } PresentLayersData;
420
421 // Perform the present on the main thread.
422 static void present_layers_task_cb(gpointer user_data) {
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 }
437
438 static gboolean fl_compositor_opengl_create_backing_store(
439 FlCompositor* compositor,
440 const FlutterBackingStoreConfig* config,
441 FlutterBackingStore* backing_store_out) {
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 }
469
470 static gboolean fl_compositor_opengl_collect_backing_store(
471 FlCompositor* compositor,
472 const FlutterBackingStore* backing_store) {
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 }
481
482 static void fl_compositor_opengl_wait_for_frame(FlCompositor* compositor,
483 int target_width,
484 int target_height) {
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 }
498
499 static gboolean fl_compositor_opengl_present_layers(FlCompositor* compositor,
500 FlutterViewId view_id,
501 const FlutterLayer** layers,
502 size_t layers_count) {
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 }
535
536 static void fl_compositor_opengl_dispose(GObject* object) {
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 }
549
550 static void fl_compositor_opengl_class_init(FlCompositorOpenGLClass* klass) {
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 }
562
563 static void fl_compositor_opengl_init(FlCompositorOpenGL* self) {
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 }
570
571 FlCompositorOpenGL* fl_compositor_opengl_new(FlEngine* engine) {
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 }
581
582 void fl_compositor_opengl_setup(FlCompositorOpenGL* self) {
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 }
596
597 void fl_compositor_opengl_render(FlCompositorOpenGL* self,
598 FlutterViewId view_id,
599 int width,
600 int height,
601 const GdkRGBA* background_color) {
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 }
616
617 void fl_compositor_opengl_cleanup(FlCompositorOpenGL* self) {
618 g_return_if_fail(FL_IS_COMPOSITOR_OPENGL(self));
619
620 if (self->program != 0) {
621 glDeleteProgram(self->program);
622 }
623 }
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
render_with_textures
static void render_with_textures(FlCompositorOpenGL *self, GPtrArray *framebuffers, int width, int height)
Definition: fl_compositor_opengl.cc:218
fl_compositor_opengl_setup
void fl_compositor_opengl_setup(FlCompositorOpenGL *self)
Definition: fl_compositor_opengl.cc:582
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
get_shader_log
static gchar * get_shader_log(GLuint shader)
Definition: fl_compositor_opengl.cc:103
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_unblock_main_thread
static void fl_compositor_opengl_unblock_main_thread(FlCompositorOpenGL *self)
Definition: fl_compositor_opengl.cc:149
G_DEFINE_TYPE
G_DEFINE_TYPE(FlCompositorOpenGL, fl_compositor_opengl, fl_compositor_get_type()) static gboolean is_nvidia()
Definition: fl_compositor_opengl.cc:86
fragment_shader_src
static const char * fragment_shader_src
Definition: fl_compositor_opengl.cc:27
present_layers
static gboolean present_layers(FlCompositorOpenGL *self, FlutterViewId view_id, const FlutterLayer **layers, size_t layers_count)
Definition: fl_compositor_opengl.cc:295
fl_compositor_opengl_init
static void fl_compositor_opengl_init(FlCompositorOpenGL *self)
Definition: fl_compositor_opengl.cc:563
get_program_log
static gchar * get_program_log(GLuint program)
Definition: fl_compositor_opengl.cc:116
setup_shader
static void setup_shader(FlCompositorOpenGL *self)
Definition: fl_compositor_opengl.cc:160
render
static void render(FlCompositorOpenGL *self, GPtrArray *framebuffers, int width, int height)
Definition: fl_compositor_opengl.cc:284
is_vivante
static gboolean is_vivante()
Definition: fl_compositor_opengl.cc:97
present_layers_task_cb
static void present_layers_task_cb(gpointer user_data)
Definition: fl_compositor_opengl.cc:422
render_with_blit
static void render_with_blit(FlCompositorOpenGL *self, GPtrArray *framebuffers)
Definition: fl_compositor_opengl.cc:197
fl_compositor_opengl_new
FlCompositorOpenGL * fl_compositor_opengl_new(FlEngine *engine)
Definition: fl_compositor_opengl.cc:571
fl_compositor_opengl_class_init
static void fl_compositor_opengl_class_init(FlCompositorOpenGLClass *klass)
Definition: fl_compositor_opengl.cc:550
fl_compositor_opengl_render
void fl_compositor_opengl_render(FlCompositorOpenGL *self, FlutterViewId view_id, int width, int height, const GdkRGBA *background_color)
Definition: fl_compositor_opengl.cc:597
fl_compositor_opengl_cleanup
void fl_compositor_opengl_cleanup(FlCompositorOpenGL *self)
Definition: fl_compositor_opengl.cc:617
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
vertex_shader_src
static const char * vertex_shader_src
Definition: fl_compositor_opengl.cc:16
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
initialize
static void initialize(FlCompositorOpenGL *self)
Definition: fl_compositor_opengl.cc:134
fl_compositor_opengl.h
fl_engine_get_opengl_manager
FlOpenGLManager * fl_engine_get_opengl_manager(FlEngine *self)
Definition: fl_engine.cc:603
fl_engine_get_task_runner
FlTaskRunner * fl_engine_get_task_runner(FlEngine *self)
Definition: fl_engine.cc:1287
fl_engine_get_renderable
FlRenderable * fl_engine_get_renderable(FlEngine *self, FlutterViewId view_id)
Definition: fl_engine.cc:806
fl_engine_private.h
user_data
G_BEGIN_DECLS G_MODULE_EXPORT FlValue gpointer user_data
Definition: fl_event_channel.h:90
fl_framebuffer_get_height
size_t fl_framebuffer_get_height(FlFramebuffer *self)
Definition: fl_framebuffer.cc:98
fl_framebuffer_get_id
GLuint fl_framebuffer_get_id(FlFramebuffer *self)
Definition: fl_framebuffer.cc:82
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_framebuffer_new
FlFramebuffer * fl_framebuffer_new(GLint format, size_t width, size_t height)
Definition: fl_framebuffer.cc:42
fl_framebuffer.h
fl_opengl_manager_clear_current
void fl_opengl_manager_clear_current(FlOpenGLManager *self)
Definition: fl_opengl_manager.cc:90
fl_opengl_manager_make_current
void fl_opengl_manager_make_current(FlOpenGLManager *self)
Definition: fl_opengl_manager.cc:82
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
TRUE
return TRUE
Definition: fl_pixel_buffer_texture_test.cc:53
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
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
fl_task_runner_release_main_thread
void fl_task_runner_release_main_thread(FlTaskRunner *self)
Definition: fl_task_runner.cc:224
fl_task_runner_block_main_thread
void fl_task_runner_block_main_thread(FlTaskRunner *self)
Definition: fl_task_runner.cc:203
view_id
G_BEGIN_DECLS FlutterViewId view_id
Definition: fl_view_accessible.h:49
_FlCompositorOpenGL
Definition: fl_compositor_opengl.cc:39
_FlCompositorOpenGL::program
GLuint program
Definition: fl_compositor_opengl.cc:72
_FlCompositorOpenGL::present_mutex
GMutex present_mutex
Definition: fl_compositor_opengl.cc:79
_FlCompositorOpenGL::sized_format
GLint sized_format
Definition: fl_compositor_opengl.cc:52
_FlCompositorOpenGL::has_gl_framebuffer_blit
bool has_gl_framebuffer_blit
Definition: fl_compositor_opengl.cc:69
_FlCompositorOpenGL::initialized
gboolean initialized
Definition: fl_compositor_opengl.cc:49
_FlCompositorOpenGL::parent_instance
FlCompositor parent_instance
Definition: fl_compositor_opengl.cc:40
_FlCompositorOpenGL::engine
GWeakRef engine
Definition: fl_compositor_opengl.cc:43
_FlCompositorOpenGL::blocking_main_thread
bool blocking_main_thread
Definition: fl_compositor_opengl.cc:62
_FlCompositorOpenGL::opengl_manager
FlOpenGLManager * opengl_manager
Definition: fl_compositor_opengl.cc:46
_FlCompositorOpenGL::target_height
int target_height
Definition: fl_compositor_opengl.cc:59
_FlCompositorOpenGL::present_condition
GCond present_condition
Definition: fl_compositor_opengl.cc:83
_FlCompositorOpenGL::general_format
GLint general_format
Definition: fl_compositor_opengl.cc:55
_FlCompositorOpenGL::had_first_frame
bool had_first_frame
Definition: fl_compositor_opengl.cc:66
_FlCompositorOpenGL::framebuffers_by_view_id
GHashTable * framebuffers_by_view_id
Definition: fl_compositor_opengl.cc:75
_FlCompositorOpenGL::target_width
int target_width
Definition: fl_compositor_opengl.cc:58
PresentLayersData
Definition: fl_compositor_opengl.cc:408
PresentLayersData::self
FlCompositorOpenGL * self
Definition: fl_compositor_opengl.cc:409
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::finished
gboolean finished
Definition: fl_compositor_opengl.cc:418
PresentLayersData::view_id
FlutterViewId view_id
Definition: fl_compositor_opengl.cc:411
PresentLayersData::result
gboolean result
Definition: fl_compositor_opengl.cc:416
texture_id
int64_t texture_id
Definition: texture_registrar_unittests.cc:24