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"
24 " gl_Position = vec4(offset + position * scale, 0, 1);\n"
25 " texcoord = in_texcoord;\n"
31 "precision mediump float;\n"
34 "uniform sampler2D texture;\n"
35 "varying vec2 texcoord;\n"
38 " gl_FragColor = texture2D(texture, texcoord);\n"
84 fl_compositor_get_type())
87static gchar* get_shader_log(GLuint shader) {
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);
115 "Failed to setup compositor shaders, unable to make OpenGL context "
120 GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
122 glCompileShader(vertex_shader);
123 GLint vertex_compile_status;
124 glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &vertex_compile_status);
125 if (vertex_compile_status == GL_FALSE) {
126 g_autofree gchar* shader_log = get_shader_log(vertex_shader);
127 g_warning(
"Failed to compile vertex shader: %s", shader_log);
130 GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
132 glCompileShader(fragment_shader);
133 GLint fragment_compile_status;
134 glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &fragment_compile_status);
135 if (fragment_compile_status == GL_FALSE) {
136 g_autofree gchar* shader_log = get_shader_log(fragment_shader);
137 g_warning(
"Failed to compile fragment shader: %s", shader_log);
140 self->program = glCreateProgram();
141 glAttachShader(
self->program, vertex_shader);
142 glAttachShader(
self->program, fragment_shader);
143 glLinkProgram(
self->program);
146 glGetProgramiv(
self->program, GL_LINK_STATUS, &link_status);
147 if (link_status == GL_FALSE) {
149 g_warning(
"Failed to link program: %s", program_log);
152 self->offset_location = glGetUniformLocation(
self->program,
"offset");
153 self->scale_location = glGetUniformLocation(
self->program,
"scale");
155 glDeleteShader(vertex_shader);
156 glDeleteShader(fragment_shader);
162 GLfloat vertex_data[] = {-1, -1, 0, 0, 1, 1, 1, 1, -1, 1, 0, 1,
163 -1, -1, 0, 0, 1, -1, 1, 0, 1, 1, 1, 1};
165 glGenBuffers(1, &
self->vertex_buffer);
166 glBindBuffer(GL_ARRAY_BUFFER,
self->vertex_buffer);
167 glBufferData(GL_ARRAY_BUFFER,
sizeof(vertex_data), vertex_data,
174 "Failed to cleanup compositor shaders, unable to make OpenGL context "
179 if (
self->program != 0) {
180 glDeleteProgram(
self->program);
182 if (
self->vertex_buffer != 0) {
183 glDeleteBuffers(1, &
self->vertex_buffer);
188 FlFramebuffer* framebuffer,
195 glUniform2f(
self->offset_location, (2 *
x /
width) - 1.0,
197 glUniform2f(
self->scale_location, texture_width /
width,
203 glDrawArrays(GL_TRIANGLES, 0, 6);
209 FlCompositorOpenGL*
self = FL_COMPOSITOR_OPENGL(compositor);
211 g_mutex_lock(&
self->frame_mutex);
213 g_mutex_unlock(&
self->frame_mutex);
217 GLint general_format = GL_RGBA;
219 general_format = GL_BGRA_EXT;
225 GLint saved_texture_binding;
226 glGetIntegerv(GL_TEXTURE_BINDING_2D, &saved_texture_binding);
227 GLint saved_vao_binding;
228 glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &saved_vao_binding);
229 GLint saved_array_buffer_binding;
230 glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &saved_array_buffer_binding);
231 GLint saved_framebuffer_binding;
232 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &saved_framebuffer_binding);
237 if (
self->framebuffer ==
nullptr ||
240 g_clear_object(&
self->framebuffer);
245 if (!
self->shareable) {
247 self->pixels =
static_cast<uint8_t*
>(realloc(
self->pixels, data_length));
251 self->had_first_frame =
true;
256 glGenVertexArrays(1, &vao);
257 glBindVertexArray(vao);
258 glBindBuffer(GL_ARRAY_BUFFER,
self->vertex_buffer);
259 GLint position_location = glGetAttribLocation(
self->program,
"position");
260 glEnableVertexAttribArray(position_location);
261 glVertexAttribPointer(position_location, 2, GL_FLOAT, GL_FALSE,
262 sizeof(GLfloat) * 4, 0);
263 GLint texcoord_location = glGetAttribLocation(
self->program,
"in_texcoord");
264 glEnableVertexAttribArray(texcoord_location);
265 glVertexAttribPointer(texcoord_location, 2, GL_FLOAT, GL_FALSE,
267 reinterpret_cast<void*
>(
sizeof(GLfloat) * 2));
270 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
272 glUseProgram(
self->program);
277 glDisable(GL_SCISSOR_TEST);
279 glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
281 gboolean first_layer =
TRUE;
284 switch (layer->
type) {
287 FlFramebuffer* framebuffer =
289 glBindFramebuffer(GL_READ_FRAMEBUFFER,
311 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
314 glDeleteVertexArrays(1, &vao);
318 glBindTexture(GL_TEXTURE_2D, saved_texture_binding);
319 glBindVertexArray(saved_vao_binding);
320 glBindBuffer(GL_ARRAY_BUFFER, saved_array_buffer_binding);
321 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, saved_framebuffer_binding);
323 if (!
self->shareable) {
324 glBindFramebuffer(GL_READ_FRAMEBUFFER,
326 glReadPixels(0, 0,
width,
height, GL_RGBA, GL_UNSIGNED_BYTE,
self->pixels);
327 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
330 g_mutex_unlock(&
self->frame_mutex);
340 FlCompositorOpenGL*
self = FL_COMPOSITOR_OPENGL(compositor);
342 g_mutex_lock(&
self->frame_mutex);
343 if (
self->framebuffer ==
nullptr) {
344 g_mutex_unlock(&
self->frame_mutex);
354 g_mutex_unlock(&
self->frame_mutex);
356 g_mutex_lock(&
self->frame_mutex);
365 GLint saved_texture_binding;
366 glGetIntegerv(GL_TEXTURE_BINDING_2D, &saved_texture_binding);
371 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
width,
height, 0, GL_RGBA,
372 GL_UNSIGNED_BYTE,
self->pixels);
379 glBindTexture(GL_TEXTURE_2D, saved_texture_binding);
384 g_mutex_unlock(&
self->frame_mutex);
390 FlCompositorOpenGL*
self = FL_COMPOSITOR_OPENGL(
object);
394 g_clear_object(&
self->task_runner);
395 g_clear_object(&
self->opengl_manager);
396 g_clear_object(&
self->framebuffer);
397 g_clear_pointer(&
self->pixels, g_free);
398 g_mutex_clear(&
self->frame_mutex);
400 G_OBJECT_CLASS(fl_compositor_opengl_parent_class)->dispose(
object);
404 FL_COMPOSITOR_CLASS(klass)->present_layers =
412 g_mutex_init(&
self->frame_mutex);
418 FlCompositorOpenGL*
self = FL_COMPOSITOR_OPENGL(
419 g_object_new(fl_compositor_opengl_get_type(),
nullptr));
421 self->task_runner = FL_TASK_RUNNER(g_object_ref(task_runner));
@ kFlutterLayerContentTypePlatformView
Indicates that the contents of this layer are determined by the embedder.
@ kFlutterLayerContentTypeBackingStore
static void fl_compositor_opengl_dispose(GObject *object)
static gboolean fl_compositor_opengl_present_layers(FlCompositor *compositor, const FlutterLayer **layers, size_t layers_count)
static const char * fragment_shader_src
static void fl_compositor_opengl_init(FlCompositorOpenGL *self)
static void cleanup_shader(FlCompositorOpenGL *self)
static void setup_shader(FlCompositorOpenGL *self)
G_DEFINE_TYPE(FlCompositorOpenGL, fl_compositor_opengl, fl_compositor_get_type()) static gchar *get_shader_log(GLuint shader)
static void fl_compositor_opengl_class_init(FlCompositorOpenGLClass *klass)
static void composite_layer(FlCompositorOpenGL *self, FlFramebuffer *framebuffer, double x, double y, int width, int height)
static gchar * get_program_log(GLuint program)
static const char * vertex_shader_src
FlCompositorOpenGL * fl_compositor_opengl_new(FlTaskRunner *task_runner, FlOpenGLManager *opengl_manager, gboolean shareable)
static gboolean fl_compositor_opengl_render(FlCompositor *compositor, cairo_t *cr, GdkWindow *window)
G_BEGIN_DECLS FlOpenGLManager gboolean shareable
G_BEGIN_DECLS FlOpenGLManager * opengl_manager
const FlutterLayer size_t layers_count
const FlutterLayer ** layers
g_autoptr(GMutexLocker) locker
fl_task_runner_stop_wait(self->task_runner)
size_t fl_framebuffer_get_height(FlFramebuffer *self)
FlFramebuffer * fl_framebuffer_new(GLint format, size_t width, size_t height, gboolean shareable)
GLuint fl_framebuffer_get_id(FlFramebuffer *self)
FlFramebuffer * fl_framebuffer_create_sibling(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)
gboolean fl_opengl_manager_make_current(FlOpenGLManager *self)
void fl_task_runner_wait(FlTaskRunner *self)
bool epoxy_has_gl_extension(const char *extension)
void gdk_cairo_draw_from_gl(cairo_t *cr, GdkWindow *window, int source, int source_type, int buffer_scale, int x, int y, int width, int height)
int gdk_window_get_width(GdkWindow *window)
gint gdk_window_get_scale_factor(GdkWindow *window)
int gdk_window_get_height(GdkWindow *window)
FlCompositor parent_instance
bool blocking_main_thread
FlOpenGLManager * opengl_manager
FlFramebuffer * framebuffer
FlTaskRunner * task_runner
FlutterOpenGLBackingStore open_gl
The description of the OpenGL backing store.
FlutterLayerContentType type
const FlutterBackingStore * backing_store
FlutterSize size
The size of the layer (in physical pixels).
FlutterOpenGLFramebuffer framebuffer
void * user_data
User data to be returned on the invocation of the destruction callback.