| 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 "uniform vec2 offset;\n"
20 "uniform vec2 scale;\n"
21 "varying vec2 texcoord;\n"
22 "\n"
23 "void main() {\n"
24 " gl_Position = vec4(offset + position * scale, 0, 1);\n"
25 " texcoord = in_texcoord;\n"
26 "}\n";
27
28 // Fragment shader to draw Flutter window contents.
29 static const char* fragment_shader_src =
30 "#ifdef GL_ES\n"
31 "precision mediump float;\n"
32 "#endif\n"
33 "\n"
34 "uniform sampler2D texture;\n"
35 "varying vec2 texcoord;\n"
36 "\n"
37 "void main() {\n"
38 " gl_FragColor = texture2D(texture, texcoord);\n"
39 "}\n";
40
41 struct _FlCompositorOpenGL {
42 FlCompositor parent_instance;
43
44 // Engine we are rendering.
45 GWeakRef engine;
46
47 // Target OpenGL context;
48 GdkGLContext* context;
49
50 // Flutter OpenGL contexts.
51 FlOpenGLManager* opengl_manager;
52
53 // target dimension for resizing
54 int target_width;
55 int target_height;
56
57 // whether the renderer waits for frame render
58 bool blocking_main_thread;
59
60 // true if frame was completed; resizing is not synchronized until first frame
61 // was rendered
62 bool had_first_frame;
63
64 // True if we can use glBlitFramebuffer.
65 bool has_gl_framebuffer_blit;
66
67 // Shader program.
68 GLuint program;
69
70 // Location of layer offset in [program].
71 GLuint offset_location;
72
73 // Location of layer scale in [program].
74 GLuint scale_location;
75
76 // Verticies for the uniform square.
77 GLuint vertex_buffer;
78
79 // Framebuffers to render.
80 GPtrArray* framebuffers;
81
82 // Mutex used when blocking the raster thread until a task is completed on
83 // platform thread.
84 GMutex present_mutex;
85
86 // Condition to unblock the raster thread after task is completed on platform
87 // thread.
88 GCond present_condition;
89 };
90
91 G_DEFINE_TYPE(FlCompositorOpenGL,
92 fl_compositor_opengl,
93 fl_compositor_get_type())
94
95 // Check if running on driver supporting blit.
96 static gboolean driver_supports_blit() {
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 }
116
117 // Returns the log for the given OpenGL shader. Must be freed by the caller.
118 static gchar* get_shader_log(GLuint shader) {
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 }
129
130 // Returns the log for the given OpenGL program. Must be freed by the caller.
131 static gchar* get_program_log(GLuint program) {
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 }
142
143 static void fl_compositor_opengl_unblock_main_thread(FlCompositorOpenGL* self) {
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 }
153
154 static void setup_shader(FlCompositorOpenGL* self) {
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 }
205
206 static void render_with_blit(FlCompositorOpenGL* self,
207 GPtrArray* framebuffers) {
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 }
226
227 static void render_with_textures(FlCompositorOpenGL* self,
228 GPtrArray* framebuffers,
229 int width,
230 int height) {
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 }
288
289 static void render(FlCompositorOpenGL* self,
290 GPtrArray* framebuffers,
291 int width,
292 int height) {
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 }
299
300 static gboolean present_layers(FlCompositorOpenGL* self,
301 const FlutterLayer** layers,
302 size_t layers_count) {
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 }
403
404 typedef struct {
405 FlCompositorOpenGL* self;
406
407 const FlutterLayer** layers;
408 size_t layers_count;
409
410 gboolean result;
411
412 gboolean finished;
413 } PresentLayersData;
414
415 // Perform the present on the main thread.
416 static void present_layers_task_cb(gpointer user_data) {
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 }
430
431 static FlutterRendererType fl_compositor_opengl_get_renderer_type(
432 FlCompositor* compositor) {
433 return kOpenGL;
434 }
435
436 static void fl_compositor_opengl_wait_for_frame(FlCompositor* compositor,
437 int target_width,
438 int target_height) {
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 }
452
453 static gboolean fl_compositor_opengl_present_layers(FlCompositor* compositor,
454 const FlutterLayer** layers,
455 size_t layers_count) {
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 }
487
488 static void fl_compositor_opengl_dispose(GObject* object) {
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 }
502
503 static void fl_compositor_opengl_class_init(FlCompositorOpenGLClass* klass) {
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 }
513
514 static void fl_compositor_opengl_init(FlCompositorOpenGL* self) {
515 self->framebuffers = g_ptr_array_new();
516 g_mutex_init(&self->present_mutex);
517 g_cond_init(&self->present_condition);
518 }
519
520 FlCompositorOpenGL* fl_compositor_opengl_new(FlEngine* engine,
521 GdkGLContext* context) {
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 }
544
545 void fl_compositor_opengl_render(FlCompositorOpenGL* self,
546 int width,
547 int height) {
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 }
557
558 void fl_compositor_opengl_cleanup(FlCompositorOpenGL* self) {
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 }
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
render_with_textures
static void render_with_textures(FlCompositorOpenGL *self, GPtrArray *framebuffers, int width, int height)
Definition: fl_compositor_opengl.cc:227
get_shader_log
static gchar * get_shader_log(GLuint shader)
Definition: fl_compositor_opengl.cc:118
present_layers
static gboolean present_layers(FlCompositorOpenGL *self, const FlutterLayer **layers, size_t layers_count)
Definition: fl_compositor_opengl.cc:300
fl_compositor_opengl_unblock_main_thread
static void fl_compositor_opengl_unblock_main_thread(FlCompositorOpenGL *self)
Definition: fl_compositor_opengl.cc:143
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
fragment_shader_src
static const char * fragment_shader_src
Definition: fl_compositor_opengl.cc:29
fl_compositor_opengl_init
static void fl_compositor_opengl_init(FlCompositorOpenGL *self)
Definition: fl_compositor_opengl.cc:514
get_program_log
static gchar * get_program_log(GLuint program)
Definition: fl_compositor_opengl.cc:131
setup_shader
static void setup_shader(FlCompositorOpenGL *self)
Definition: fl_compositor_opengl.cc:154
fl_compositor_opengl_get_renderer_type
static FlutterRendererType fl_compositor_opengl_get_renderer_type(FlCompositor *compositor)
Definition: fl_compositor_opengl.cc:431
render
static void render(FlCompositorOpenGL *self, GPtrArray *framebuffers, int width, int height)
Definition: fl_compositor_opengl.cc:289
present_layers_task_cb
static void present_layers_task_cb(gpointer user_data)
Definition: fl_compositor_opengl.cc:416
fl_compositor_opengl_new
FlCompositorOpenGL * fl_compositor_opengl_new(FlEngine *engine, GdkGLContext *context)
Definition: fl_compositor_opengl.cc:520
render_with_blit
static void render_with_blit(FlCompositorOpenGL *self, GPtrArray *framebuffers)
Definition: fl_compositor_opengl.cc:206
fl_compositor_opengl_render
void fl_compositor_opengl_render(FlCompositorOpenGL *self, int width, int height)
Definition: fl_compositor_opengl.cc:545
fl_compositor_opengl_class_init
static void fl_compositor_opengl_class_init(FlCompositorOpenGLClass *klass)
Definition: fl_compositor_opengl.cc:503
G_DEFINE_TYPE
G_DEFINE_TYPE(FlCompositorOpenGL, fl_compositor_opengl, fl_compositor_get_type()) static gboolean driver_supports_blit()
Definition: fl_compositor_opengl.cc:91
fl_compositor_opengl_cleanup
void fl_compositor_opengl_cleanup(FlCompositorOpenGL *self)
Definition: fl_compositor_opengl.cc:558
vertex_shader_src
static const char * vertex_shader_src
Definition: fl_compositor_opengl.cc:16
fl_compositor_opengl.h
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_engine_get_task_runner
FlTaskRunner * fl_engine_get_task_runner(FlEngine *self)
Definition: fl_engine.cc:1419
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: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
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
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
_FlCompositorOpenGL
Definition: fl_compositor_opengl.cc:41
_FlCompositorOpenGL::program
GLuint program
Definition: fl_compositor_opengl.cc:68
_FlCompositorOpenGL::present_mutex
GMutex present_mutex
Definition: fl_compositor_opengl.cc:84
_FlCompositorOpenGL::has_gl_framebuffer_blit
bool has_gl_framebuffer_blit
Definition: fl_compositor_opengl.cc:65
_FlCompositorOpenGL::parent_instance
FlCompositor parent_instance
Definition: fl_compositor_opengl.cc:42
_FlCompositorOpenGL::engine
GWeakRef engine
Definition: fl_compositor_opengl.cc:45
_FlCompositorOpenGL::blocking_main_thread
bool blocking_main_thread
Definition: fl_compositor_opengl.cc:58
_FlCompositorOpenGL::offset_location
GLuint offset_location
Definition: fl_compositor_opengl.cc:71
_FlCompositorOpenGL::context
GdkGLContext * context
Definition: fl_compositor_opengl.cc:48
_FlCompositorOpenGL::opengl_manager
FlOpenGLManager * opengl_manager
Definition: fl_compositor_opengl.cc:51
_FlCompositorOpenGL::scale_location
GLuint scale_location
Definition: fl_compositor_opengl.cc:74
_FlCompositorOpenGL::target_height
int target_height
Definition: fl_compositor_opengl.cc:55
_FlCompositorOpenGL::framebuffers
GPtrArray * framebuffers
Definition: fl_compositor_opengl.cc:80
_FlCompositorOpenGL::present_condition
GCond present_condition
Definition: fl_compositor_opengl.cc:88
_FlCompositorOpenGL::vertex_buffer
GLuint vertex_buffer
Definition: fl_compositor_opengl.cc:77
_FlCompositorOpenGL::had_first_frame
bool had_first_frame
Definition: fl_compositor_opengl.cc:62
_FlCompositorOpenGL::target_width
int target_width
Definition: fl_compositor_opengl.cc:54
PresentLayersData
Definition: fl_compositor_opengl.cc:404
PresentLayersData::self
FlCompositorOpenGL * self
Definition: fl_compositor_opengl.cc:405
PresentLayersData::layers
const FlutterLayer ** layers
Definition: fl_compositor_opengl.cc:407
PresentLayersData::layers_count
size_t layers_count
Definition: fl_compositor_opengl.cc:408
PresentLayersData::finished
gboolean finished
Definition: fl_compositor_opengl.cc:412
PresentLayersData::result
gboolean result
Definition: fl_compositor_opengl.cc:410
texture_id
int64_t texture_id
Definition: texture_registrar_unittests.cc:24