10 #include "flutter/common/constants.h"
11 #include "flutter/shell/platform/embedder/embedder.h"
43 fl_compositor_get_type())
45 static
void composite_layer(FlCompositorOpenGL* self,
65 const FlutterLayer**
layers,
67 FlCompositorOpenGL*
self = FL_COMPOSITOR_OPENGL(compositor);
69 g_mutex_lock(&self->frame_mutex);
71 g_mutex_unlock(&self->frame_mutex);
75 GLint general_format = GL_RGBA;
76 if (epoxy_has_gl_extension(
"GL_EXT_texture_format_BGRA8888")) {
77 general_format = GL_BGRA_EXT;
83 GLint saved_texture_binding;
84 glGetIntegerv(GL_TEXTURE_BINDING_2D, &saved_texture_binding);
85 GLint saved_vao_binding;
86 glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &saved_vao_binding);
87 GLint saved_array_buffer_binding;
88 glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &saved_array_buffer_binding);
89 GLint saved_draw_framebuffer_binding;
90 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &saved_draw_framebuffer_binding);
91 GLint saved_read_framebuffer_binding;
92 glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &saved_read_framebuffer_binding);
93 GLint saved_current_program;
94 glGetIntegerv(GL_CURRENT_PROGRAM, &saved_current_program);
95 GLboolean saved_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
96 GLboolean saved_blend = glIsEnabled(GL_BLEND);
98 glGetIntegerv(GL_BLEND_SRC_RGB, &saved_src_rgb);
99 GLint saved_src_alpha;
100 glGetIntegerv(GL_BLEND_SRC_ALPHA, &saved_src_alpha);
102 glGetIntegerv(GL_BLEND_DST_RGB, &saved_dst_rgb);
103 GLint saved_dst_alpha;
104 glGetIntegerv(GL_BLEND_DST_ALPHA, &saved_dst_alpha);
109 if (self->framebuffer ==
nullptr ||
112 g_clear_object(&self->framebuffer);
117 if (!self->shareable) {
120 static_cast<uint8_t*
>(g_realloc(self->pixels, data_length));
127 glGenVertexArrays(1, &vao);
128 glBindVertexArray(vao);
131 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
138 glDisable(GL_SCISSOR_TEST);
140 glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
142 gboolean first_layer =
TRUE;
144 const FlutterLayer* layer =
layers[
i];
145 switch (layer->type) {
146 case kFlutterLayerContentTypeBackingStore: {
147 const FlutterBackingStore* backing_store = layer->backing_store;
149 FL_FRAMEBUFFER(backing_store->open_gl.framebuffer.user_data);
150 glBindFramebuffer(GL_READ_FRAMEBUFFER,
155 glBlitFramebuffer(layer->offset.x, layer->offset.y, layer->size.width,
156 layer->size.height, layer->offset.x,
157 layer->offset.y, layer->size.width,
158 layer->size.height, GL_COLOR_BUFFER_BIT,
162 composite_layer(
self,
framebuffer, layer->offset.x, layer->offset.y,
166 case kFlutterLayerContentTypePlatformView: {
172 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
175 glDeleteVertexArrays(1, &vao);
182 if (saved_scissor_test) {
183 glEnable(GL_SCISSOR_TEST);
185 glDisable(GL_SCISSOR_TEST);
189 glBindVertexArray(saved_vao_binding);
190 glBindBuffer(GL_ARRAY_BUFFER, saved_array_buffer_binding);
191 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, saved_draw_framebuffer_binding);
192 glUseProgram(saved_current_program);
193 glBlendFuncSeparate(saved_src_rgb, saved_dst_rgb, saved_src_alpha,
196 if (!self->shareable) {
197 glBindFramebuffer(GL_READ_FRAMEBUFFER,
199 glReadPixels(0, 0,
width,
height, GL_RGBA, GL_UNSIGNED_BYTE, self->pixels);
200 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
202 glBindFramebuffer(GL_READ_FRAMEBUFFER, saved_read_framebuffer_binding);
204 g_mutex_unlock(&self->frame_mutex);
214 FlCompositorOpenGL*
self = FL_COMPOSITOR_OPENGL(compositor);
216 g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->frame_mutex);
218 if (
width !=
nullptr) {
219 *
width =
self->framebuffer !=
nullptr
224 *
height =
self->framebuffer !=
nullptr
233 gboolean wait_for_frame) {
234 FlCompositorOpenGL*
self = FL_COMPOSITOR_OPENGL(compositor);
236 g_mutex_lock(&self->frame_mutex);
237 if (self->framebuffer ==
nullptr) {
238 g_mutex_unlock(&self->frame_mutex);
243 gint scale_factor = gdk_window_get_scale_factor(window);
248 width = gdk_window_get_width(window) * scale_factor;
249 height = gdk_window_get_height(window) * scale_factor;
250 if (!wait_for_frame) {
256 if (framebuffer_width ==
width && framebuffer_height ==
height) {
260 if (g_get_monotonic_time() > expiry_time) {
262 "Timed out waiting for OpenGL frame of size %zdx%zd (have %zdx%zd)",
263 width,
height, framebuffer_width, framebuffer_height);
267 g_mutex_unlock(&self->frame_mutex);
269 g_mutex_lock(&self->frame_mutex);
278 GLint saved_texture_binding;
279 glGetIntegerv(GL_TEXTURE_BINDING_2D, &saved_texture_binding);
284 GLsizei fb_width = 0;
285 GLsizei fb_height = 0;
286 if (self->framebuffer !=
nullptr) {
292 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fb_width, fb_height, 0, GL_RGBA,
293 GL_UNSIGNED_BYTE, self->pixels);
295 gdk_cairo_draw_from_gl(cr, window,
texture_id, GL_TEXTURE, scale_factor, 0,
305 g_mutex_unlock(&self->frame_mutex);
311 FlCompositorOpenGL*
self = FL_COMPOSITOR_OPENGL(
object);
313 g_clear_object(&self->shader);
315 g_clear_object(&self->task_runner);
316 g_clear_object(&self->opengl_manager);
317 g_clear_object(&self->framebuffer);
318 g_clear_pointer(&self->pixels, g_free);
319 g_mutex_clear(&self->frame_mutex);
321 G_OBJECT_CLASS(fl_compositor_opengl_parent_class)->dispose(
object);
325 FL_COMPOSITOR_CLASS(klass)->present_layers =
327 FL_COMPOSITOR_CLASS(klass)->get_frame_size =
335 g_mutex_init(&self->frame_mutex);
341 FlCompositorOpenGL*
self = FL_COMPOSITOR_OPENGL(
342 g_object_new(fl_compositor_opengl_get_type(),
nullptr));
344 self->task_runner = FL_TASK_RUNNER(g_object_ref(task_runner));
346 self->opengl_manager = FL_OPENGL_MANAGER(g_object_ref(
opengl_manager));
g_autoptr(FlEngine) engine
constexpr G_BEGIN_DECLS gint64 kCompositorRenderTimeoutMicroseconds
static void fl_compositor_opengl_dispose(GObject *object)
FlCompositorOpenGL * fl_compositor_opengl_new(FlTaskRunner *task_runner, FlOpenGLManager *opengl_manager, gboolean shareable)
G_DEFINE_TYPE(FlCompositorOpenGL, fl_compositor_opengl, fl_compositor_get_type()) static void composite_layer(FlCompositorOpenGL *self
FlFramebuffer * framebuffer
static gboolean fl_compositor_opengl_present_layers(FlCompositor *compositor, const FlutterLayer **layers, size_t layers_count)
FlFramebuffer double double int int height
static void fl_compositor_opengl_init(FlCompositorOpenGL *self)
FlFramebuffer double double int width
glDrawArrays(GL_TRIANGLES, 0, 6)
fl_compositor_opengl_shader_set_scale(self->shader, texture_width/width, texture_height/height)
static void fl_compositor_opengl_class_init(FlCompositorOpenGLClass *klass)
glBindTexture(GL_TEXTURE_2D, texture_id)
static gboolean fl_compositor_opengl_render(FlCompositor *compositor, cairo_t *cr, GdkWindow *window, gboolean wait_for_frame)
static void fl_compositor_opengl_get_frame_size(FlCompositor *compositor, size_t *width, size_t *height)
fl_compositor_opengl_shader_set_offset(self->shader,(2 *x/width) - 1.0,(2 *y/height) - 1.0)
FlFramebuffer double double y
G_BEGIN_DECLS FlOpenGLManager gboolean shareable
G_BEGIN_DECLS FlOpenGLManager * opengl_manager
FlCompositorOpenGLShader * fl_compositor_opengl_shader_new(FlOpenGLManager *opengl_manager)
void fl_compositor_opengl_shader_use(FlCompositorOpenGLShader *self)
const FlutterLayer size_t layers_count
const FlutterLayer ** layers
fl_task_runner_stop_wait(self->task_runner)
size_t fl_framebuffer_get_height(FlFramebuffer *self)
GLuint fl_framebuffer_get_id(FlFramebuffer *self)
gboolean fl_framebuffer_get_shareable(FlFramebuffer *self)
size_t fl_framebuffer_get_width(FlFramebuffer *self)
GLuint fl_framebuffer_get_texture_id(FlFramebuffer *self)
FlFramebuffer * fl_framebuffer_create_sibling(FlFramebuffer *self)
FlFramebuffer * fl_framebuffer_new(GLint format, size_t width, size_t height, gboolean shareable)
void fl_task_runner_wait(FlTaskRunner *self, gint64 expiry_time)
FlCompositorOpenGLShader * shader
FlCompositor parent_instance
FlOpenGLManager * opengl_manager
FlFramebuffer * framebuffer
FlTaskRunner * task_runner