10 #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"
82 const gchar* vendor =
reinterpret_cast<const gchar*
>(glGetString(GL_VENDOR));
83 return strstr(vendor,
"NVIDIA") !=
nullptr;
91 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length);
93 log =
static_cast<gchar*
>(g_malloc(log_length + 1));
94 glGetShaderInfoLog(shader, log_length,
nullptr, log);
104 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length);
106 log =
static_cast<gchar*
>(g_malloc(log_length + 1));
107 glGetProgramInfoLog(program, log_length,
nullptr, log);
114 return (2.0 * position / pixels) - 1.0;
120 fl_renderer_get_instance_private(
self));
122 if (
priv->initialized) {
127 if (epoxy_has_gl_extension(
"GL_EXT_texture_format_BGRA8888")) {
128 priv->sized_format = GL_BGRA8_EXT;
129 priv->general_format = GL_BGRA_EXT;
131 priv->sized_format = GL_RGBA8;
132 priv->general_format = GL_RGBA;
138 fl_renderer_get_instance_private(
self));
139 if (
priv->blocking_main_thread) {
140 priv->blocking_main_thread =
false;
142 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&
priv->engine));
143 if (engine !=
nullptr) {
151 fl_renderer_get_instance_private(
self));
153 GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
155 glCompileShader(vertex_shader);
156 GLint vertex_compile_status;
157 glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &vertex_compile_status);
158 if (vertex_compile_status == GL_FALSE) {
160 g_warning(
"Failed to compile vertex shader: %s", shader_log);
163 GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
165 glCompileShader(fragment_shader);
166 GLint fragment_compile_status;
167 glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &fragment_compile_status);
168 if (fragment_compile_status == GL_FALSE) {
170 g_warning(
"Failed to compile fragment shader: %s", shader_log);
173 priv->program = glCreateProgram();
174 glAttachShader(
priv->program, vertex_shader);
175 glAttachShader(
priv->program, fragment_shader);
176 glLinkProgram(
priv->program);
179 glGetProgramiv(
priv->program, GL_LINK_STATUS, &link_status);
180 if (link_status == GL_FALSE) {
182 g_warning(
"Failed to link program: %s", program_log);
185 glDeleteShader(vertex_shader);
186 glDeleteShader(fragment_shader);
193 glDisable(GL_SCISSOR_TEST);
195 for (guint
i = 0;
i < framebuffers->len;
i++) {
196 FlFramebuffer* framebuffer =
197 FL_FRAMEBUFFER(g_ptr_array_index(framebuffers,
i));
200 glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer_id);
204 GL_COLOR_BUFFER_BIT, GL_NEAREST);
206 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
210 GPtrArray* framebuffers,
214 fl_renderer_get_instance_private(
self));
219 GLint saved_texture_binding;
220 glGetIntegerv(GL_TEXTURE_BINDING_2D, &saved_texture_binding);
221 GLint saved_vao_binding;
222 glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &saved_vao_binding);
223 GLint saved_array_buffer_binding;
224 glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &saved_array_buffer_binding);
227 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
229 glUseProgram(
priv->program);
231 for (guint
i = 0;
i < framebuffers->len;
i++) {
232 FlFramebuffer* framebuffer =
233 FL_FRAMEBUFFER(g_ptr_array_index(framebuffers,
i));
245 GLfloat vertex_data[] = {x0, y0, 0, 0, x1, y1, 1, 1, x0, y1, 0, 1,
246 x0, y0, 0, 0, x1, y0, 1, 0, x1, y1, 1, 1};
248 GLuint vao, vertex_buffer;
249 glGenVertexArrays(1, &vao);
250 glBindVertexArray(vao);
251 glGenBuffers(1, &vertex_buffer);
252 glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
253 glBufferData(GL_ARRAY_BUFFER,
sizeof(vertex_data), vertex_data,
255 GLint position_index = glGetAttribLocation(
priv->program,
"position");
256 glEnableVertexAttribArray(position_index);
257 glVertexAttribPointer(position_index, 2, GL_FLOAT, GL_FALSE,
258 sizeof(GLfloat) * 4, 0);
259 GLint texcoord_index = glGetAttribLocation(
priv->program,
"in_texcoord");
260 glEnableVertexAttribArray(texcoord_index);
261 glVertexAttribPointer(texcoord_index, 2, GL_FLOAT, GL_FALSE,
262 sizeof(GLfloat) * 4, (
void*)(
sizeof(GLfloat) * 2));
264 glDrawArrays(GL_TRIANGLES, 0, 6);
266 glDeleteVertexArrays(1, &vao);
267 glDeleteBuffers(1, &vertex_buffer);
272 glBindTexture(GL_TEXTURE_2D, saved_texture_binding);
273 glBindVertexArray(saved_vao_binding);
274 glBindBuffer(GL_ARRAY_BUFFER, saved_array_buffer_binding);
278 FlRenderer*
self = FL_RENDERER(
object);
280 fl_renderer_get_instance_private(
self));
284 g_weak_ref_clear(&
priv->engine);
285 g_clear_pointer(&
priv->views, g_hash_table_unref);
286 g_clear_pointer(&
priv->framebuffers_by_view_id, g_hash_table_unref);
288 G_OBJECT_CLASS(fl_renderer_parent_class)->dispose(
object);
297 fl_renderer_get_instance_private(
self));
299 g_hash_table_new_full(g_direct_hash, g_direct_equal,
nullptr,
nullptr);
300 priv->framebuffers_by_view_id =
301 g_hash_table_new_full(g_direct_hash, g_direct_equal,
nullptr,
302 (GDestroyNotify)g_ptr_array_unref);
307 fl_renderer_get_instance_private(
self));
309 g_return_if_fail(FL_IS_RENDERER(
self));
311 g_weak_ref_init(&
priv->engine, engine);
315 FlutterViewId view_id,
318 fl_renderer_get_instance_private(
self));
320 g_return_if_fail(FL_IS_RENDERER(
self));
322 g_hash_table_insert(
priv->views, GINT_TO_POINTER(view_id),
view);
327 fl_renderer_get_instance_private(
self));
329 g_return_if_fail(FL_IS_RENDERER(
self));
331 g_hash_table_remove(
priv->views, GINT_TO_POINTER(view_id));
335 g_return_val_if_fail(FL_IS_RENDERER(
self), NULL);
337 return reinterpret_cast<void*
>(eglGetProcAddress(name));
341 g_return_if_fail(FL_IS_RENDERER(
self));
342 FL_RENDERER_GET_CLASS(
self)->make_current(
self);
346 g_return_if_fail(FL_IS_RENDERER(
self));
347 FL_RENDERER_GET_CLASS(
self)->make_resource_current(
self);
351 g_return_if_fail(FL_IS_RENDERER(
self));
352 FL_RENDERER_GET_CLASS(
self)->clear_current(
self);
356 g_return_val_if_fail(FL_IS_RENDERER(
self), -1.0);
357 return FL_RENDERER_GET_CLASS(
self)->get_refresh_rate(
self);
361 g_return_val_if_fail(FL_IS_RENDERER(
self), 0);
369 const FlutterBackingStoreConfig* config,
370 FlutterBackingStore* backing_store_out) {
372 fl_renderer_get_instance_private(
self));
379 priv->general_format, config->size.width, config->size.height);
381 g_warning(
"Failed to create backing store");
385 backing_store_out->type = kFlutterBackingStoreTypeOpenGL;
386 backing_store_out->open_gl.type = kFlutterOpenGLTargetTypeFramebuffer;
387 backing_store_out->open_gl.framebuffer.user_data = framebuffer;
388 backing_store_out->open_gl.framebuffer.name =
390 backing_store_out->open_gl.framebuffer.target =
priv->sized_format;
391 backing_store_out->open_gl.framebuffer.destruction_callback = [](
void* p) {
401 const FlutterBackingStore* backing_store) {
405 g_object_unref(backing_store->open_gl.framebuffer.user_data);
413 fl_renderer_get_instance_private(
self));
415 g_return_if_fail(FL_IS_RENDERER(
self));
417 priv->target_width = target_width;
418 priv->target_height = target_height;
420 if (
priv->had_first_frame && !
priv->blocking_main_thread) {
421 priv->blocking_main_thread =
true;
422 g_autoptr(FlEngine) engine = FL_ENGINE(g_weak_ref_get(&
priv->engine));
423 if (engine !=
nullptr) {
430 FlutterViewId view_id,
431 const FlutterLayer** layers,
432 size_t layers_count) {
434 fl_renderer_get_instance_private(
self));
436 g_return_val_if_fail(FL_IS_RENDERER(
self), FALSE);
440 if (
priv->blocking_main_thread && layers_count == 1 &&
441 layers[0]->offset.x == 0 && layers[0]->offset.y == 0 &&
442 (layers[0]->size.width !=
priv->target_width ||
443 layers[0]->size.height !=
priv->target_height)) {
447 priv->had_first_frame =
true;
451 GPtrArray* framebuffers =
reinterpret_cast<GPtrArray*
>((g_hash_table_lookup(
452 priv->framebuffers_by_view_id, GINT_TO_POINTER(view_id))));
453 if (framebuffers ==
nullptr) {
454 framebuffers = g_ptr_array_new_with_free_func(g_object_unref);
455 g_hash_table_insert(
priv->framebuffers_by_view_id, GINT_TO_POINTER(view_id),
458 g_ptr_array_set_size(framebuffers, 0);
459 for (
size_t i = 0;
i < layers_count; ++
i) {
460 const FlutterLayer* layer = layers[
i];
461 switch (layer->type) {
462 case kFlutterLayerContentTypeBackingStore: {
463 const FlutterBackingStore* backing_store = layer->backing_store;
464 FlFramebuffer* framebuffer =
465 FL_FRAMEBUFFER(backing_store->open_gl.framebuffer.user_data);
466 g_ptr_array_add(framebuffers, g_object_ref(framebuffer));
468 case kFlutterLayerContentTypePlatformView: {
476 FL_VIEW(g_hash_table_lookup(
priv->views, GINT_TO_POINTER(view_id)));
477 if (
view !=
nullptr) {
486 fl_renderer_get_instance_private(
self));
488 g_return_if_fail(FL_IS_RENDERER(
self));
492 priv->has_gl_framebuffer_blit =
493 !
is_nvidia() && (epoxy_gl_version() >= 30 ||
494 epoxy_has_gl_extension(
"GL_EXT_framebuffer_blit"));
496 if (!
priv->has_gl_framebuffer_blit) {
502 FlutterViewId view_id,
505 const GdkRGBA* background_color) {
507 fl_renderer_get_instance_private(
self));
509 g_return_if_fail(FL_IS_RENDERER(
self));
511 glClearColor(background_color->red, background_color->green,
512 background_color->blue, background_color->alpha);
513 glClear(GL_COLOR_BUFFER_BIT);
515 GPtrArray* framebuffers =
reinterpret_cast<GPtrArray*
>((g_hash_table_lookup(
516 priv->framebuffers_by_view_id, GINT_TO_POINTER(view_id))));
517 if (framebuffers !=
nullptr) {
518 if (
priv->has_gl_framebuffer_blit) {
530 fl_renderer_get_instance_private(
self));
532 g_return_if_fail(FL_IS_RENDERER(
self));
534 if (
priv->program != 0) {
535 glDeleteProgram(
priv->program);