| Flutter Linux Embedder |

fl_renderer.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_renderer.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 G_DEFINE_QUARK(fl_renderer_error_quark, fl_renderer_error)
40
41 typedef struct {
42 // Engine we are rendering.
43 GWeakRef engine;
44
45 // Flag to track lazy initialization.
46 gboolean initialized;
47
48 // The pixel format passed to the engine.
49 GLint sized_format;
50
51 // The format used to create textures.
52 GLint general_format;
53
54 // Views being rendered.
55 GHashTable* views;
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 } FlRendererPrivate;
77
78 G_DEFINE_TYPE_WITH_PRIVATE(FlRenderer, fl_renderer, G_TYPE_OBJECT)
79
80 static void free_weak_ref(gpointer value) {
81 GWeakRef* ref = static_cast<GWeakRef*>(value);
82 g_weak_ref_clear(ref);
83 free(ref);
84 }
85
86 // Check if running on an NVIDIA driver.
87 static gboolean is_nvidia() {
88 const gchar* vendor = reinterpret_cast<const gchar*>(glGetString(GL_VENDOR));
89 return strstr(vendor, "NVIDIA") != nullptr;
90 }
91
92 // Check if running on an Vivante Corporation driver.
93 static gboolean is_vivante() {
94 const gchar* vendor = reinterpret_cast<const gchar*>(glGetString(GL_VENDOR));
95 return strstr(vendor, "Vivante Corporation") != nullptr;
96 }
97
98 // Returns the log for the given OpenGL shader. Must be freed by the caller.
99 static gchar* get_shader_log(GLuint shader) {
100 GLint log_length;
101 gchar* log;
102
103 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
104
105 log = static_cast<gchar*>(g_malloc(log_length + 1));
106 glGetShaderInfoLog(shader, log_length, nullptr, log);
107
108 return log;
109 }
110
111 // Returns the log for the given OpenGL program. Must be freed by the caller.
112 static gchar* get_program_log(GLuint program) {
113 GLint log_length;
114 gchar* log;
115
116 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
117
118 log = static_cast<gchar*>(g_malloc(log_length + 1));
119 glGetProgramInfoLog(program, log_length, nullptr, log);
120
121 return log;
122 }
123
124 /// Converts a pixel co-ordinate from 0..pixels to OpenGL -1..1.
125 static GLfloat pixels_to_gl_coords(GLfloat position, GLfloat pixels) {
126 return (2.0 * position / pixels) - 1.0;
127 }
128
129 // Perform single run OpenGL initialization.
130 static void initialize(FlRenderer* self) {
131 FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
132 fl_renderer_get_instance_private(self));
133
134 if (priv->initialized) {
135 return;
136 }
137 priv->initialized = TRUE;
138
139 if (epoxy_has_gl_extension("GL_EXT_texture_format_BGRA8888")) {
140 priv->sized_format = GL_BGRA8_EXT;
141 priv->general_format = GL_BGRA_EXT;
142 } else {
143 priv->sized_format = GL_RGBA8;
144 priv->general_format = GL_RGBA;
145 }
146 }
147
148 static void fl_renderer_unblock_main_thread(FlRenderer* self) {
149 FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
150 fl_renderer_get_instance_private(self));
151 if (priv->blocking_main_thread) {
152 priv->blocking_main_thread = false;
153
154 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&priv->engine));
155 if (engine != nullptr) {
156 fl_task_runner_release_main_thread(fl_engine_get_task_runner(engine));
157 }
158 }
159 }
160
161 static void setup_shader(FlRenderer* self) {
162 FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
163 fl_renderer_get_instance_private(self));
164
165 GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
166 glShaderSource(vertex_shader, 1, &vertex_shader_src, nullptr);
167 glCompileShader(vertex_shader);
168 GLint vertex_compile_status;
169 glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &vertex_compile_status);
170 if (vertex_compile_status == GL_FALSE) {
171 g_autofree gchar* shader_log = get_shader_log(vertex_shader);
172 g_warning("Failed to compile vertex shader: %s", shader_log);
173 }
174
175 GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
176 glShaderSource(fragment_shader, 1, &fragment_shader_src, nullptr);
177 glCompileShader(fragment_shader);
178 GLint fragment_compile_status;
179 glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &fragment_compile_status);
180 if (fragment_compile_status == GL_FALSE) {
181 g_autofree gchar* shader_log = get_shader_log(fragment_shader);
182 g_warning("Failed to compile fragment shader: %s", shader_log);
183 }
184
185 priv->program = glCreateProgram();
186 glAttachShader(priv->program, vertex_shader);
187 glAttachShader(priv->program, fragment_shader);
188 glLinkProgram(priv->program);
189
190 GLint link_status;
191 glGetProgramiv(priv->program, GL_LINK_STATUS, &link_status);
192 if (link_status == GL_FALSE) {
193 g_autofree gchar* program_log = get_program_log(priv->program);
194 g_warning("Failed to link program: %s", program_log);
195 }
196
197 glDeleteShader(vertex_shader);
198 glDeleteShader(fragment_shader);
199 }
200
201 static void render_with_blit(FlRenderer* self, GPtrArray* framebuffers) {
202 // Disable the scissor test as it can affect blit operations.
203 // Prevents regressions like: https://github.com/flutter/flutter/issues/140828
204 // See OpenGL specification version 4.6, section 18.3.1.
205 glDisable(GL_SCISSOR_TEST);
206
207 for (guint i = 0; i < framebuffers->len; i++) {
208 FlFramebuffer* framebuffer =
209 FL_FRAMEBUFFER(g_ptr_array_index(framebuffers, i));
210
211 GLuint framebuffer_id = fl_framebuffer_get_id(framebuffer);
212 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer_id);
213 size_t width = fl_framebuffer_get_width(framebuffer);
214 size_t height = fl_framebuffer_get_height(framebuffer);
215 glBlitFramebuffer(0, 0, width, height, 0, 0, width, height,
216 GL_COLOR_BUFFER_BIT, GL_NEAREST);
217 }
218 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
219 }
220
221 static void render_with_textures(FlRenderer* self,
222 GPtrArray* framebuffers,
223 int width,
224 int height) {
225 FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
226 fl_renderer_get_instance_private(self));
227
228 // Save bindings that are set by this function. All bindings must be restored
229 // to their original values because Skia expects that its bindings have not
230 // been altered.
231 GLint saved_texture_binding;
232 glGetIntegerv(GL_TEXTURE_BINDING_2D, &saved_texture_binding);
233 GLint saved_vao_binding;
234 glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &saved_vao_binding);
235 GLint saved_array_buffer_binding;
236 glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &saved_array_buffer_binding);
237
238 glEnable(GL_BLEND);
239 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
240
241 glUseProgram(priv->program);
242
243 for (guint i = 0; i < framebuffers->len; i++) {
244 FlFramebuffer* framebuffer =
245 FL_FRAMEBUFFER(g_ptr_array_index(framebuffers, i));
246
247 GLuint texture_id = fl_framebuffer_get_texture_id(framebuffer);
248 glBindTexture(GL_TEXTURE_2D, texture_id);
249
250 // Translate into OpenGL co-ordinates
251 size_t texture_width = fl_framebuffer_get_width(framebuffer);
252 size_t texture_height = fl_framebuffer_get_height(framebuffer);
253 GLfloat x0 = pixels_to_gl_coords(0, width);
254 GLfloat y0 = pixels_to_gl_coords(height - texture_height, height);
255 GLfloat x1 = pixels_to_gl_coords(texture_width, width);
256 GLfloat y1 = pixels_to_gl_coords(height, height);
257 GLfloat vertex_data[] = {x0, y0, 0, 0, x1, y1, 1, 1, x0, y1, 0, 1,
258 x0, y0, 0, 0, x1, y0, 1, 0, x1, y1, 1, 1};
259
260 GLuint vao, vertex_buffer;
261 glGenVertexArrays(1, &vao);
262 glBindVertexArray(vao);
263 glGenBuffers(1, &vertex_buffer);
264 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
265 glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data,
266 GL_STATIC_DRAW);
267 GLint position_index = glGetAttribLocation(priv->program, "position");
268 glEnableVertexAttribArray(position_index);
269 glVertexAttribPointer(position_index, 2, GL_FLOAT, GL_FALSE,
270 sizeof(GLfloat) * 4, 0);
271 GLint texcoord_index = glGetAttribLocation(priv->program, "in_texcoord");
272 glEnableVertexAttribArray(texcoord_index);
273 glVertexAttribPointer(texcoord_index, 2, GL_FLOAT, GL_FALSE,
274 sizeof(GLfloat) * 4,
275 reinterpret_cast<void*>(sizeof(GLfloat) * 2));
276
277 glDrawArrays(GL_TRIANGLES, 0, 6);
278
279 glDeleteVertexArrays(1, &vao);
280 glDeleteBuffers(1, &vertex_buffer);
281 }
282
283 glDisable(GL_BLEND);
284
285 glBindTexture(GL_TEXTURE_2D, saved_texture_binding);
286 glBindVertexArray(saved_vao_binding);
287 glBindBuffer(GL_ARRAY_BUFFER, saved_array_buffer_binding);
288 }
289
290 static void render(FlRenderer* self,
291 GPtrArray* framebuffers,
292 int width,
293 int height) {
294 FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
295 fl_renderer_get_instance_private(self));
296
297 if (priv->has_gl_framebuffer_blit) {
298 render_with_blit(self, framebuffers);
299 } else {
300 render_with_textures(self, framebuffers, width, height);
301 }
302 }
303
304 static void fl_renderer_dispose(GObject* object) {
305 FlRenderer* self = FL_RENDERER(object);
306 FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
307 fl_renderer_get_instance_private(self));
308
309 fl_renderer_unblock_main_thread(self);
310
311 g_weak_ref_clear(&priv->engine);
312 g_clear_pointer(&priv->views, g_hash_table_unref);
313 g_clear_pointer(&priv->framebuffers_by_view_id, g_hash_table_unref);
314
315 G_OBJECT_CLASS(fl_renderer_parent_class)->dispose(object);
316 }
317
318 static void fl_renderer_class_init(FlRendererClass* klass) {
319 G_OBJECT_CLASS(klass)->dispose = fl_renderer_dispose;
320 }
321
322 static void fl_renderer_init(FlRenderer* self) {
323 FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
324 fl_renderer_get_instance_private(self));
325 priv->views = g_hash_table_new_full(g_direct_hash, g_direct_equal, nullptr,
326 free_weak_ref);
327 priv->framebuffers_by_view_id = g_hash_table_new_full(
328 g_direct_hash, g_direct_equal, nullptr,
329 reinterpret_cast<GDestroyNotify>(g_ptr_array_unref));
330 }
331
332 void fl_renderer_set_engine(FlRenderer* self, FlEngine* engine) {
333 FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
334 fl_renderer_get_instance_private(self));
335
336 g_return_if_fail(FL_IS_RENDERER(self));
337
338 g_weak_ref_init(&priv->engine, engine);
339 }
340
341 void fl_renderer_add_renderable(FlRenderer* self,
342 FlutterViewId view_id,
343 FlRenderable* renderable) {
344 FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
345 fl_renderer_get_instance_private(self));
346
347 g_return_if_fail(FL_IS_RENDERER(self));
348
349 GWeakRef* ref = g_new(GWeakRef, 1);
350 g_weak_ref_init(ref, G_OBJECT(renderable));
351 g_hash_table_insert(priv->views, GINT_TO_POINTER(view_id), ref);
352 }
353
354 void fl_renderer_remove_view(FlRenderer* self, FlutterViewId view_id) {
355 FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
356 fl_renderer_get_instance_private(self));
357
358 g_return_if_fail(FL_IS_RENDERER(self));
359
360 g_hash_table_remove(priv->views, GINT_TO_POINTER(view_id));
361 }
362
363 void* fl_renderer_get_proc_address(FlRenderer* self, const char* name) {
364 g_return_val_if_fail(FL_IS_RENDERER(self), NULL);
365
366 return reinterpret_cast<void*>(eglGetProcAddress(name));
367 }
368
369 void fl_renderer_make_current(FlRenderer* self) {
370 g_return_if_fail(FL_IS_RENDERER(self));
371 FL_RENDERER_GET_CLASS(self)->make_current(self);
372 }
373
374 void fl_renderer_make_resource_current(FlRenderer* self) {
375 g_return_if_fail(FL_IS_RENDERER(self));
376 FL_RENDERER_GET_CLASS(self)->make_resource_current(self);
377 }
378
379 void fl_renderer_clear_current(FlRenderer* self) {
380 g_return_if_fail(FL_IS_RENDERER(self));
381 FL_RENDERER_GET_CLASS(self)->clear_current(self);
382 }
383
384 guint32 fl_renderer_get_fbo(FlRenderer* self) {
385 g_return_val_if_fail(FL_IS_RENDERER(self), 0);
386
387 // There is only one frame buffer object - always return that.
388 return 0;
389 }
390
391 gboolean fl_renderer_create_backing_store(
392 FlRenderer* self,
393 const FlutterBackingStoreConfig* config,
394 FlutterBackingStore* backing_store_out) {
395 FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
396 fl_renderer_get_instance_private(self));
397
398 fl_renderer_make_current(self);
399
400 initialize(self);
401
402 FlFramebuffer* framebuffer = fl_framebuffer_new(
403 priv->general_format, config->size.width, config->size.height);
404 if (!framebuffer) {
405 g_warning("Failed to create backing store");
406 return FALSE;
407 }
408
409 backing_store_out->type = kFlutterBackingStoreTypeOpenGL;
410 backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer;
411 backing_store_out->open_gl.framebuffer.user_data = framebuffer;
412 backing_store_out->open_gl.framebuffer.name =
413 fl_framebuffer_get_id(framebuffer);
414 backing_store_out->open_gl.framebuffer.target = priv->sized_format;
415 backing_store_out->open_gl.framebuffer.destruction_callback = [](void* p) {
416 // Backing store destroyed in fl_renderer_collect_backing_store(), set
417 // on FlutterCompositor.collect_backing_store_callback during engine start.
418 };
419
420 return TRUE;
421 }
422
423 gboolean fl_renderer_collect_backing_store(
424 FlRenderer* self,
425 const FlutterBackingStore* backing_store) {
426 fl_renderer_make_current(self);
427
428 // OpenGL context is required when destroying #FlFramebuffer.
429 g_object_unref(backing_store->open_gl.framebuffer.user_data);
430 return TRUE;
431 }
432
433 void fl_renderer_wait_for_frame(FlRenderer* self,
434 int target_width,
435 int target_height) {
436 FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
437 fl_renderer_get_instance_private(self));
438
439 g_return_if_fail(FL_IS_RENDERER(self));
440
441 priv->target_width = target_width;
442 priv->target_height = target_height;
443
444 if (priv->had_first_frame && !priv->blocking_main_thread) {
445 priv->blocking_main_thread = true;
446 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&priv->engine));
447 if (engine != nullptr) {
448 fl_task_runner_block_main_thread(fl_engine_get_task_runner(engine));
449 }
450 }
451 }
452
453 gboolean fl_renderer_present_layers(FlRenderer* self,
454 FlutterViewId view_id,
455 const FlutterLayer** layers,
456 size_t layers_count) {
457 FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
458 fl_renderer_get_instance_private(self));
459
460 g_return_val_if_fail(FL_IS_RENDERER(self), FALSE);
461
462 // ignore incoming frame with wrong dimensions in trivial case with just one
463 // layer
464 if (priv->blocking_main_thread && layers_count == 1 &&
465 layers[0]->offset.x == 0 && layers[0]->offset.y == 0 &&
466 (layers[0]->size.width != priv->target_width ||
467 layers[0]->size.height != priv->target_height)) {
468 return TRUE;
469 }
470
471 priv->had_first_frame = true;
472
473 fl_renderer_unblock_main_thread(self);
474
475 g_autoptr(GPtrArray) framebuffers =
476 g_ptr_array_new_with_free_func(g_object_unref);
477 for (size_t i = 0; i < layers_count; ++i) {
478 const FlutterLayer* layer = layers[i];
479 switch (layer->type) {
480 case kFlutterLayerContentTypeBackingStore: {
481 const FlutterBackingStore* backing_store = layer->backing_store;
482 FlFramebuffer* framebuffer =
483 FL_FRAMEBUFFER(backing_store->open_gl.framebuffer.user_data);
484 g_ptr_array_add(framebuffers, g_object_ref(framebuffer));
485 } break;
486 case kFlutterLayerContentTypePlatformView: {
487 // TODO(robert-ancell) Not implemented -
488 // https://github.com/flutter/flutter/issues/41724
489 } break;
490 }
491 }
492
493 GWeakRef* ref = static_cast<GWeakRef*>(
494 g_hash_table_lookup(priv->views, GINT_TO_POINTER(view_id)));
495 g_autoptr(FlRenderable) renderable =
496 ref != nullptr ? FL_RENDERABLE(g_weak_ref_get(ref)) : nullptr;
497 if (renderable == nullptr) {
498 return TRUE;
499 }
500
501 if (view_id == flutter::kFlutterImplicitViewId) {
502 // Store for rendering later
503 g_hash_table_insert(priv->framebuffers_by_view_id, GINT_TO_POINTER(view_id),
504 g_ptr_array_ref(framebuffers));
505 } else {
506 // Composite into a single framebuffer.
507 if (framebuffers->len > 1) {
508 size_t width = 0, height = 0;
509
510 for (guint i = 0; i < framebuffers->len; i++) {
511 FlFramebuffer* framebuffer =
512 FL_FRAMEBUFFER(g_ptr_array_index(framebuffers, i));
513
514 size_t w = fl_framebuffer_get_width(framebuffer);
515 size_t h = fl_framebuffer_get_height(framebuffer);
516 if (w > width) {
517 width = w;
518 }
519 if (h > height) {
520 height = h;
521 }
522 }
523
524 FlFramebuffer* view_framebuffer =
525 fl_framebuffer_new(priv->general_format, width, height);
526 glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
527 fl_framebuffer_get_id(view_framebuffer));
528 render(self, framebuffers, width, height);
529 g_ptr_array_set_size(framebuffers, 0);
530 g_ptr_array_add(framebuffers, view_framebuffer);
531 }
532
533 // Read back pixel values.
534 FlFramebuffer* framebuffer =
535 FL_FRAMEBUFFER(g_ptr_array_index(framebuffers, 0));
536 size_t width = fl_framebuffer_get_width(framebuffer);
537 size_t height = fl_framebuffer_get_height(framebuffer);
538 size_t data_length = width * height * 4;
539 g_autofree uint8_t* data = static_cast<uint8_t*>(malloc(data_length));
540 glBindFramebuffer(GL_READ_FRAMEBUFFER, fl_framebuffer_get_id(framebuffer));
541 glReadPixels(0, 0, width, height, priv->general_format, GL_UNSIGNED_BYTE,
542 data);
543
544 // Write into a texture in the views context.
545 fl_renderable_make_current(renderable);
546 FlFramebuffer* view_framebuffer =
547 fl_framebuffer_new(priv->general_format, width, height);
548 glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
549 fl_framebuffer_get_id(view_framebuffer));
550 glBindTexture(GL_TEXTURE_2D,
551 fl_framebuffer_get_texture_id(view_framebuffer));
552 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
553 GL_UNSIGNED_BYTE, data);
554
555 g_autoptr(GPtrArray) secondary_framebuffers =
556 g_ptr_array_new_with_free_func(g_object_unref);
557 g_ptr_array_add(secondary_framebuffers, g_object_ref(view_framebuffer));
558 g_hash_table_insert(priv->framebuffers_by_view_id, GINT_TO_POINTER(view_id),
559 g_ptr_array_ref(secondary_framebuffers));
560 }
561
562 fl_renderable_redraw(renderable);
563
564 return TRUE;
565 }
566
567 void fl_renderer_setup(FlRenderer* self) {
568 FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
569 fl_renderer_get_instance_private(self));
570
571 g_return_if_fail(FL_IS_RENDERER(self));
572
573 // Note: NVIDIA and Vivante are temporarily disabled due to
574 // https://github.com/flutter/flutter/issues/152099
575 priv->has_gl_framebuffer_blit =
576 !is_nvidia() && !is_vivante() &&
577 (epoxy_gl_version() >= 30 ||
578 epoxy_has_gl_extension("GL_EXT_framebuffer_blit"));
579
580 if (!priv->has_gl_framebuffer_blit) {
581 setup_shader(self);
582 }
583 }
584
585 void fl_renderer_render(FlRenderer* self,
586 FlutterViewId view_id,
587 int width,
588 int height,
589 const GdkRGBA* background_color) {
590 FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
591 fl_renderer_get_instance_private(self));
592
593 g_return_if_fail(FL_IS_RENDERER(self));
594
595 glClearColor(background_color->red, background_color->green,
596 background_color->blue, background_color->alpha);
597 glClear(GL_COLOR_BUFFER_BIT);
598
599 GPtrArray* framebuffers = reinterpret_cast<GPtrArray*>((g_hash_table_lookup(
600 priv->framebuffers_by_view_id, GINT_TO_POINTER(view_id))));
601 if (framebuffers != nullptr) {
602 render(self, framebuffers, width, height);
603 }
604
605 glFlush();
606 }
607
608 void fl_renderer_cleanup(FlRenderer* self) {
609 FlRendererPrivate* priv = reinterpret_cast<FlRendererPrivate*>(
610 fl_renderer_get_instance_private(self));
611
612 g_return_if_fail(FL_IS_RENDERER(self));
613
614 if (priv->program != 0) {
615 glDeleteProgram(priv->program);
616 }
617 }
G_DEFINE_QUARK
G_DEFINE_QUARK(fl_binary_messenger_codec_error_quark, fl_binary_messenger_codec_error) G_DECLARE_FINAL_TYPE(FlBinaryMessengerImpl
fl_engine_get_task_runner
FlTaskRunner * fl_engine_get_task_runner(FlEngine *self)
Definition: fl_engine.cc:1209
fl_engine_private.h
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
priv
FlPixelBufferTexturePrivate * priv
Definition: fl_pixel_buffer_texture.cc:30
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
fl_renderer_get_fbo
guint32 fl_renderer_get_fbo(FlRenderer *self)
Definition: fl_renderer.cc:384
fl_renderer_add_renderable
void fl_renderer_add_renderable(FlRenderer *self, FlutterViewId view_id, FlRenderable *renderable)
Definition: fl_renderer.cc:341
setup_shader
static void setup_shader(FlRenderer *self)
Definition: fl_renderer.cc:161
fl_renderer_make_resource_current
void fl_renderer_make_resource_current(FlRenderer *self)
Definition: fl_renderer.cc:374
fl_renderer_remove_view
void fl_renderer_remove_view(FlRenderer *self, FlutterViewId view_id)
Definition: fl_renderer.cc:354
pixels_to_gl_coords
static GLfloat pixels_to_gl_coords(GLfloat position, GLfloat pixels)
Converts a pixel co-ordinate from 0..pixels to OpenGL -1..1.
Definition: fl_renderer.cc:125
get_shader_log
static gchar * get_shader_log(GLuint shader)
Definition: fl_renderer.cc:99
fl_renderer_make_current
void fl_renderer_make_current(FlRenderer *self)
Definition: fl_renderer.cc:369
fl_renderer_unblock_main_thread
static void fl_renderer_unblock_main_thread(FlRenderer *self)
Definition: fl_renderer.cc:148
fl_renderer_dispose
static void fl_renderer_dispose(GObject *object)
Definition: fl_renderer.cc:304
render_with_textures
static void render_with_textures(FlRenderer *self, GPtrArray *framebuffers, int width, int height)
Definition: fl_renderer.cc:221
fragment_shader_src
static const char * fragment_shader_src
Definition: fl_renderer.cc:27
initialize
static void initialize(FlRenderer *self)
Definition: fl_renderer.cc:130
get_program_log
static gchar * get_program_log(GLuint program)
Definition: fl_renderer.cc:112
fl_renderer_create_backing_store
gboolean fl_renderer_create_backing_store(FlRenderer *self, const FlutterBackingStoreConfig *config, FlutterBackingStore *backing_store_out)
Definition: fl_renderer.cc:391
fl_renderer_cleanup
void fl_renderer_cleanup(FlRenderer *self)
Definition: fl_renderer.cc:608
is_vivante
static gboolean is_vivante()
Definition: fl_renderer.cc:93
fl_renderer_class_init
static void fl_renderer_class_init(FlRendererClass *klass)
Definition: fl_renderer.cc:318
fl_renderer_present_layers
gboolean fl_renderer_present_layers(FlRenderer *self, FlutterViewId view_id, const FlutterLayer **layers, size_t layers_count)
Definition: fl_renderer.cc:453
render_with_blit
static void render_with_blit(FlRenderer *self, GPtrArray *framebuffers)
Definition: fl_renderer.cc:201
fl_renderer_init
static void fl_renderer_init(FlRenderer *self)
Definition: fl_renderer.cc:322
fl_renderer_clear_current
void fl_renderer_clear_current(FlRenderer *self)
Definition: fl_renderer.cc:379
fl_renderer_set_engine
void fl_renderer_set_engine(FlRenderer *self, FlEngine *engine)
Definition: fl_renderer.cc:332
fl_renderer_render
void fl_renderer_render(FlRenderer *self, FlutterViewId view_id, int width, int height, const GdkRGBA *background_color)
Definition: fl_renderer.cc:585
render
static void render(FlRenderer *self, GPtrArray *framebuffers, int width, int height)
Definition: fl_renderer.cc:290
fl_renderer_get_proc_address
void * fl_renderer_get_proc_address(FlRenderer *self, const char *name)
Definition: fl_renderer.cc:363
fl_renderer_collect_backing_store
gboolean fl_renderer_collect_backing_store(FlRenderer *self, const FlutterBackingStore *backing_store)
Definition: fl_renderer.cc:423
vertex_shader_src
static const char * vertex_shader_src
Definition: fl_renderer.cc:16
fl_renderer_setup
void fl_renderer_setup(FlRenderer *self)
Definition: fl_renderer.cc:567
is_nvidia
static gboolean is_nvidia()
Definition: fl_renderer.cc:87
free_weak_ref
static void free_weak_ref(gpointer value)
Definition: fl_renderer.cc:80
fl_renderer_wait_for_frame
void fl_renderer_wait_for_frame(FlRenderer *self, int target_width, int target_height)
Definition: fl_renderer.cc:433
fl_renderer.h
fl_renderer_error_quark
GQuark fl_renderer_error_quark(void) G_GNUC_CONST
i
int i
Definition: fl_socket_accessible.cc:18
value
uint8_t value
Definition: fl_standard_message_codec.cc:36
fl_task_runner_release_main_thread
void fl_task_runner_release_main_thread(FlTaskRunner *self)
Definition: fl_task_runner.cc:197
fl_task_runner_block_main_thread
void fl_task_runner_block_main_thread(FlTaskRunner *self)
Definition: fl_task_runner.cc:176
FlRendererPrivate
Definition: fl_renderer.cc:41
FlRendererPrivate::sized_format
GLint sized_format
Definition: fl_renderer.cc:49
FlRendererPrivate::general_format
GLint general_format
Definition: fl_renderer.cc:52
FlRendererPrivate::target_height
int target_height
Definition: fl_renderer.cc:59
FlRendererPrivate::initialized
gboolean initialized
Definition: fl_renderer.cc:46
FlRendererPrivate::engine
GWeakRef engine
Definition: fl_renderer.cc:43
FlRendererPrivate::program
GLuint program
Definition: fl_renderer.cc:72
FlRendererPrivate::views
GHashTable * views
Definition: fl_renderer.cc:55
FlRendererPrivate::blocking_main_thread
bool blocking_main_thread
Definition: fl_renderer.cc:62
FlRendererPrivate::had_first_frame
bool had_first_frame
Definition: fl_renderer.cc:66
FlRendererPrivate::framebuffers_by_view_id
GHashTable * framebuffers_by_view_id
Definition: fl_renderer.cc:75
FlRendererPrivate::target_width
int target_width
Definition: fl_renderer.cc:58
FlRendererPrivate::has_gl_framebuffer_blit
bool has_gl_framebuffer_blit
Definition: fl_renderer.cc:69
texture_id
int64_t texture_id
Definition: texture_registrar_unittests.cc:24