10 #include "flutter/common/constants.h"
11 #include "flutter/shell/platform/embedder/embedder.h"
17 "attribute vec2 position;\n"
18 "attribute vec2 in_texcoord;\n"
19 "varying vec2 texcoord;\n"
22 " gl_Position = vec4(position, 0, 1);\n"
23 " texcoord = in_texcoord;\n"
29 "precision mediump float;\n"
32 "uniform sampler2D texture;\n"
33 "varying vec2 texcoord;\n"
36 " gl_FragColor = texture2D(texture, texcoord);\n"
78 G_DEFINE_TYPE_WITH_PRIVATE(FlRenderer, fl_renderer, G_TYPE_OBJECT)
81 GWeakRef* ref =
static_cast<GWeakRef*
>(
value);
82 g_weak_ref_clear(ref);
88 const gchar* vendor =
reinterpret_cast<const gchar*
>(glGetString(GL_VENDOR));
89 return strstr(vendor,
"NVIDIA") !=
nullptr;
94 const gchar* vendor =
reinterpret_cast<const gchar*
>(glGetString(GL_VENDOR));
95 return strstr(vendor,
"Vivante Corporation") !=
nullptr;
103 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
105 log =
static_cast<gchar*
>(g_malloc(log_length + 1));
106 glGetShaderInfoLog(shader, log_length,
nullptr, log);
116 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
118 log =
static_cast<gchar*
>(g_malloc(log_length + 1));
119 glGetProgramInfoLog(program, log_length,
nullptr, log);
126 return (2.0 * position / pixels) - 1.0;
132 fl_renderer_get_instance_private(
self));
134 if (
priv->initialized) {
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;
143 priv->sized_format = GL_RGBA8;
144 priv->general_format = GL_RGBA;
150 fl_renderer_get_instance_private(
self));
151 if (
priv->blocking_main_thread) {
152 priv->blocking_main_thread =
false;
154 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&
priv->engine));
155 if (engine !=
nullptr) {
163 fl_renderer_get_instance_private(
self));
165 GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
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) {
172 g_warning(
"Failed to compile vertex shader: %s", shader_log);
175 GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
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) {
182 g_warning(
"Failed to compile fragment shader: %s", shader_log);
185 priv->program = glCreateProgram();
186 glAttachShader(
priv->program, vertex_shader);
187 glAttachShader(
priv->program, fragment_shader);
188 glLinkProgram(
priv->program);
191 glGetProgramiv(
priv->program, GL_LINK_STATUS, &link_status);
192 if (link_status == GL_FALSE) {
194 g_warning(
"Failed to link program: %s", program_log);
197 glDeleteShader(vertex_shader);
198 glDeleteShader(fragment_shader);
205 glDisable(GL_SCISSOR_TEST);
207 for (guint
i = 0;
i < framebuffers->len;
i++) {
208 FlFramebuffer* framebuffer =
209 FL_FRAMEBUFFER(g_ptr_array_index(framebuffers,
i));
212 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer_id);
216 GL_COLOR_BUFFER_BIT, GL_NEAREST);
218 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
222 GPtrArray* framebuffers,
226 fl_renderer_get_instance_private(
self));
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);
239 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
241 glUseProgram(
priv->program);
243 for (guint
i = 0;
i < framebuffers->len;
i++) {
244 FlFramebuffer* framebuffer =
245 FL_FRAMEBUFFER(g_ptr_array_index(framebuffers,
i));
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};
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,
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,
275 reinterpret_cast<void*
>(
sizeof(GLfloat) * 2));
277 glDrawArrays(GL_TRIANGLES, 0, 6);
279 glDeleteVertexArrays(1, &vao);
280 glDeleteBuffers(1, &vertex_buffer);
285 glBindTexture(GL_TEXTURE_2D, saved_texture_binding);
286 glBindVertexArray(saved_vao_binding);
287 glBindBuffer(GL_ARRAY_BUFFER, saved_array_buffer_binding);
291 GPtrArray* framebuffers,
295 fl_renderer_get_instance_private(
self));
297 if (
priv->has_gl_framebuffer_blit) {
305 FlRenderer*
self = FL_RENDERER(
object);
307 fl_renderer_get_instance_private(
self));
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);
315 G_OBJECT_CLASS(fl_renderer_parent_class)->dispose(
object);
324 fl_renderer_get_instance_private(
self));
325 priv->views = g_hash_table_new_full(g_direct_hash, g_direct_equal,
nullptr,
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));
334 fl_renderer_get_instance_private(
self));
336 g_return_if_fail(FL_IS_RENDERER(
self));
338 g_weak_ref_init(&
priv->engine, engine);
342 FlutterViewId view_id,
343 FlRenderable* renderable) {
345 fl_renderer_get_instance_private(
self));
347 g_return_if_fail(FL_IS_RENDERER(
self));
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);
356 fl_renderer_get_instance_private(
self));
358 g_return_if_fail(FL_IS_RENDERER(
self));
360 g_hash_table_remove(
priv->views, GINT_TO_POINTER(view_id));
364 g_return_val_if_fail(FL_IS_RENDERER(
self), NULL);
366 return reinterpret_cast<void*
>(eglGetProcAddress(name));
370 g_return_if_fail(FL_IS_RENDERER(
self));
371 FL_RENDERER_GET_CLASS(
self)->make_current(
self);
375 g_return_if_fail(FL_IS_RENDERER(
self));
376 FL_RENDERER_GET_CLASS(
self)->make_resource_current(
self);
380 g_return_if_fail(FL_IS_RENDERER(
self));
381 FL_RENDERER_GET_CLASS(
self)->clear_current(
self);
385 g_return_val_if_fail(FL_IS_RENDERER(
self), 0);
393 const FlutterBackingStoreConfig* config,
394 FlutterBackingStore* backing_store_out) {
396 fl_renderer_get_instance_private(
self));
403 priv->general_format, config->size.width, config->size.height);
405 g_warning(
"Failed to create backing store");
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 =
414 backing_store_out->open_gl.framebuffer.target =
priv->sized_format;
415 backing_store_out->open_gl.framebuffer.destruction_callback = [](
void* p) {
425 const FlutterBackingStore* backing_store) {
429 g_object_unref(backing_store->open_gl.framebuffer.user_data);
437 fl_renderer_get_instance_private(
self));
439 g_return_if_fail(FL_IS_RENDERER(
self));
441 priv->target_width = target_width;
442 priv->target_height = target_height;
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) {
454 FlutterViewId view_id,
455 const FlutterLayer** layers,
456 size_t layers_count) {
458 fl_renderer_get_instance_private(
self));
460 g_return_val_if_fail(FL_IS_RENDERER(
self), FALSE);
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)) {
471 priv->had_first_frame =
true;
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));
486 case kFlutterLayerContentTypePlatformView: {
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) {
501 if (view_id == flutter::kFlutterImplicitViewId) {
503 g_hash_table_insert(
priv->framebuffers_by_view_id, GINT_TO_POINTER(view_id),
504 g_ptr_array_ref(framebuffers));
507 if (framebuffers->len > 1) {
510 for (guint
i = 0;
i < framebuffers->len;
i++) {
511 FlFramebuffer* framebuffer =
512 FL_FRAMEBUFFER(g_ptr_array_index(framebuffers,
i));
524 FlFramebuffer* view_framebuffer =
526 glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
529 g_ptr_array_set_size(framebuffers, 0);
530 g_ptr_array_add(framebuffers, view_framebuffer);
534 FlFramebuffer* framebuffer =
535 FL_FRAMEBUFFER(g_ptr_array_index(framebuffers, 0));
539 g_autofree uint8_t* data =
static_cast<uint8_t*
>(malloc(data_length));
541 glReadPixels(0, 0,
width,
height,
priv->general_format, GL_UNSIGNED_BYTE,
546 FlFramebuffer* view_framebuffer =
548 glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
550 glBindTexture(GL_TEXTURE_2D,
552 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
width,
height, 0, GL_RGBA,
553 GL_UNSIGNED_BYTE, data);
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));
569 fl_renderer_get_instance_private(
self));
571 g_return_if_fail(FL_IS_RENDERER(
self));
575 priv->has_gl_framebuffer_blit =
577 (epoxy_gl_version() >= 30 ||
578 epoxy_has_gl_extension(
"GL_EXT_framebuffer_blit"));
580 if (!
priv->has_gl_framebuffer_blit) {
586 FlutterViewId view_id,
589 const GdkRGBA* background_color) {
591 fl_renderer_get_instance_private(
self));
593 g_return_if_fail(FL_IS_RENDERER(
self));
595 glClearColor(background_color->red, background_color->green,
596 background_color->blue, background_color->alpha);
597 glClear(GL_COLOR_BUFFER_BIT);
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) {
610 fl_renderer_get_instance_private(
self));
612 g_return_if_fail(FL_IS_RENDERER(
self));
614 if (
priv->program != 0) {
615 glDeleteProgram(
priv->program);