Flutter Linux Embedder
fl_compositor_opengl.cc File Reference
#include "fl_compositor_opengl.h"
#include <epoxy/egl.h>
#include <epoxy/gl.h>
#include "flutter/common/constants.h"
#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/linux/fl_engine_private.h"
#include "flutter/shell/platform/linux/fl_framebuffer.h"

Go to the source code of this file.

Classes

struct  _FlCompositorOpenGL
 
struct  PresentLayersData
 

Functions

 G_DEFINE_TYPE (FlCompositorOpenGL, fl_compositor_opengl, fl_compositor_get_type()) static gboolean driver_supports_blit()
 
static gchar * get_shader_log (GLuint shader)
 
static gchar * get_program_log (GLuint program)
 
static void fl_compositor_opengl_unblock_main_thread (FlCompositorOpenGL *self)
 
static void setup_shader (FlCompositorOpenGL *self)
 
static void render_with_blit (FlCompositorOpenGL *self, GPtrArray *framebuffers)
 
static void render_with_textures (FlCompositorOpenGL *self, GPtrArray *framebuffers, int width, int height)
 
static void render (FlCompositorOpenGL *self, GPtrArray *framebuffers, int width, int height)
 
static gboolean present_layers (FlCompositorOpenGL *self, const FlutterLayer **layers, size_t layers_count)
 
static void present_layers_task_cb (gpointer user_data)
 
static FlutterRendererType fl_compositor_opengl_get_renderer_type (FlCompositor *compositor)
 
static void fl_compositor_opengl_wait_for_frame (FlCompositor *compositor, int target_width, int target_height)
 
static gboolean fl_compositor_opengl_present_layers (FlCompositor *compositor, const FlutterLayer **layers, size_t layers_count)
 
static void fl_compositor_opengl_dispose (GObject *object)
 
static void fl_compositor_opengl_class_init (FlCompositorOpenGLClass *klass)
 
static void fl_compositor_opengl_init (FlCompositorOpenGL *self)
 
FlCompositorOpenGL * fl_compositor_opengl_new (FlEngine *engine, GdkGLContext *context)
 
void fl_compositor_opengl_render (FlCompositorOpenGL *self, int width, int height)
 
void fl_compositor_opengl_cleanup (FlCompositorOpenGL *self)
 

Variables

static const char * vertex_shader_src
 
static const char * fragment_shader_src
 

Function Documentation

◆ fl_compositor_opengl_class_init()

static void fl_compositor_opengl_class_init ( FlCompositorOpenGLClass *  klass)
static

Definition at line 503 of file fl_compositor_opengl.cc.

503  {
504  FL_COMPOSITOR_CLASS(klass)->get_renderer_type =
506  FL_COMPOSITOR_CLASS(klass)->wait_for_frame =
508  FL_COMPOSITOR_CLASS(klass)->present_layers =
510 
511  G_OBJECT_CLASS(klass)->dispose = fl_compositor_opengl_dispose;
512 }
static void fl_compositor_opengl_dispose(GObject *object)
static void fl_compositor_opengl_wait_for_frame(FlCompositor *compositor, int target_width, int target_height)
static gboolean fl_compositor_opengl_present_layers(FlCompositor *compositor, const FlutterLayer **layers, size_t layers_count)
static FlutterRendererType fl_compositor_opengl_get_renderer_type(FlCompositor *compositor)

References fl_compositor_opengl_dispose(), fl_compositor_opengl_get_renderer_type(), fl_compositor_opengl_present_layers(), and fl_compositor_opengl_wait_for_frame().

◆ fl_compositor_opengl_cleanup()

void fl_compositor_opengl_cleanup ( FlCompositorOpenGL *  compositor)

fl_compositor_opengl_cleanup: @compositor: an #FlCompositorOpenGL.

Removes OpenGL resources used for rendering. Requires an active context.

Definition at line 558 of file fl_compositor_opengl.cc.

558  {
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 }

Referenced by unrealize_cb().

◆ fl_compositor_opengl_dispose()

static void fl_compositor_opengl_dispose ( GObject *  object)
static

Definition at line 488 of file fl_compositor_opengl.cc.

488  {
489  FlCompositorOpenGL* self = FL_COMPOSITOR_OPENGL(object);
490 
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 }
static void fl_compositor_opengl_unblock_main_thread(FlCompositorOpenGL *self)

References fl_compositor_opengl_unblock_main_thread().

Referenced by fl_compositor_opengl_class_init().

◆ fl_compositor_opengl_get_renderer_type()

static FlutterRendererType fl_compositor_opengl_get_renderer_type ( FlCompositor *  compositor)
static

Definition at line 431 of file fl_compositor_opengl.cc.

432  {
433  return kOpenGL;
434 }

Referenced by fl_compositor_opengl_class_init().

◆ fl_compositor_opengl_init()

static void fl_compositor_opengl_init ( FlCompositorOpenGL *  self)
static

Definition at line 514 of file fl_compositor_opengl.cc.

514  {
515  self->framebuffers = g_ptr_array_new();
516  g_mutex_init(&self->present_mutex);
517  g_cond_init(&self->present_condition);
518 }

◆ fl_compositor_opengl_new()

FlCompositorOpenGL* fl_compositor_opengl_new ( FlEngine *  engine,
GdkGLContext *  context 
)

Definition at line 520 of file fl_compositor_opengl.cc.

521  {
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 }
static void setup_shader(FlCompositorOpenGL *self)
G_BEGIN_DECLS GdkGLContext * context
FlOpenGLManager * fl_engine_get_opengl_manager(FlEngine *self)
Definition: fl_engine.cc:710
void fl_opengl_manager_make_current(FlOpenGLManager *self)

References context, fl_engine_get_opengl_manager(), fl_opengl_manager_make_current(), and setup_shader().

Referenced by realize_cb(), and TEST().

◆ fl_compositor_opengl_present_layers()

static gboolean fl_compositor_opengl_present_layers ( FlCompositor *  compositor,
const FlutterLayer **  layers,
size_t  layers_count 
)
static

Definition at line 453 of file fl_compositor_opengl.cc.

455  {
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  };
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 }
static void present_layers_task_cb(gpointer user_data)
FlTaskRunner * fl_engine_get_task_runner(FlEngine *self)
Definition: fl_engine.cc:1419
void fl_opengl_manager_clear_current(FlOpenGLManager *self)
void fl_task_runner_post_callback(FlTaskRunner *self, void(*callback)(gpointer data), gpointer data)
FlCompositorOpenGL * self

References PresentLayersData::finished, fl_engine_get_task_runner(), fl_opengl_manager_clear_current(), fl_opengl_manager_make_current(), fl_task_runner_post_callback(), present_layers_task_cb(), PresentLayersData::result, and PresentLayersData::self.

Referenced by fl_compositor_opengl_class_init().

◆ fl_compositor_opengl_render()

void fl_compositor_opengl_render ( FlCompositorOpenGL *  compositor,
int  width,
int  height 
)

fl_compositor_opengl_render: @compositor: an #FlCompositorOpenGL. @width: width of the window in pixels. @height: height of the window in pixels.

Performs OpenGL commands to render current Flutter view.

Definition at line 545 of file fl_compositor_opengl.cc.

547  {
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 }
static void render(FlCompositorOpenGL *self, GPtrArray *framebuffers, int width, int height)
const uint8_t uint32_t uint32_t * height
const uint8_t uint32_t * width

References height, render(), and width.

Referenced by render_cb(), and TEST().

◆ fl_compositor_opengl_unblock_main_thread()

static void fl_compositor_opengl_unblock_main_thread ( FlCompositorOpenGL *  self)
static

Definition at line 143 of file fl_compositor_opengl.cc.

143  {
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) {
150  }
151  }
152 }
void fl_task_runner_release_main_thread(FlTaskRunner *self)

References fl_engine_get_task_runner(), and fl_task_runner_release_main_thread().

Referenced by fl_compositor_opengl_dispose(), and present_layers().

◆ fl_compositor_opengl_wait_for_frame()

static void fl_compositor_opengl_wait_for_frame ( FlCompositor *  compositor,
int  target_width,
int  target_height 
)
static

Definition at line 436 of file fl_compositor_opengl.cc.

438  {
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) {
449  }
450  }
451 }
void fl_task_runner_block_main_thread(FlTaskRunner *self)

References fl_engine_get_task_runner(), and fl_task_runner_block_main_thread().

Referenced by fl_compositor_opengl_class_init().

◆ G_DEFINE_TYPE()

G_DEFINE_TYPE ( FlCompositorOpenGL  ,
fl_compositor_opengl  ,
fl_compositor_get_type()   
)

Definition at line 91 of file fl_compositor_opengl.cc.

96  {
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 }

References TRUE.

◆ get_program_log()

static gchar* get_program_log ( GLuint  program)
static

Definition at line 131 of file fl_compositor_opengl.cc.

131  {
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 }

Referenced by setup_shader().

◆ get_shader_log()

static gchar* get_shader_log ( GLuint  shader)
static

Definition at line 118 of file fl_compositor_opengl.cc.

118  {
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 }

Referenced by setup_shader().

◆ present_layers()

static gboolean present_layers ( FlCompositorOpenGL *  self,
const FlutterLayer **  layers,
size_t  layers_count 
)
static

Definition at line 300 of file fl_compositor_opengl.cc.

302  {
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 
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 }
size_t fl_framebuffer_get_height(FlFramebuffer *self)
GLuint fl_framebuffer_get_id(FlFramebuffer *self)
size_t fl_framebuffer_get_width(FlFramebuffer *self)
GLuint fl_framebuffer_get_texture_id(FlFramebuffer *self)
FlFramebuffer * fl_framebuffer_new(GLint format, size_t width, size_t height)

References fl_compositor_opengl_unblock_main_thread(), fl_framebuffer_get_height(), fl_framebuffer_get_id(), fl_framebuffer_get_texture_id(), fl_framebuffer_get_width(), fl_framebuffer_new(), height, i, render(), TRUE, and width.

Referenced by present_layers_task_cb().

◆ present_layers_task_cb()

static void present_layers_task_cb ( gpointer  user_data)
static

Definition at line 416 of file fl_compositor_opengl.cc.

416  {
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 }
static gboolean present_layers(FlCompositorOpenGL *self, const FlutterLayer **layers, size_t layers_count)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue gpointer user_data
const FlutterLayer ** layers

References PresentLayersData::finished, fl_opengl_manager_clear_current(), fl_opengl_manager_make_current(), PresentLayersData::layers, PresentLayersData::layers_count, present_layers(), PresentLayersData::result, PresentLayersData::self, TRUE, and user_data.

Referenced by fl_compositor_opengl_present_layers().

◆ render()

static void render ( FlCompositorOpenGL *  self,
GPtrArray *  framebuffers,
int  width,
int  height 
)
static

Definition at line 289 of file fl_compositor_opengl.cc.

292  {
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 }
static void render_with_textures(FlCompositorOpenGL *self, GPtrArray *framebuffers, int width, int height)
static void render_with_blit(FlCompositorOpenGL *self, GPtrArray *framebuffers)

References height, render_with_blit(), render_with_textures(), and width.

Referenced by fl_compositor_opengl_render(), and present_layers().

◆ render_with_blit()

static void render_with_blit ( FlCompositorOpenGL *  self,
GPtrArray *  framebuffers 
)
static

Definition at line 206 of file fl_compositor_opengl.cc.

207  {
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 }

References fl_framebuffer_get_height(), fl_framebuffer_get_id(), fl_framebuffer_get_width(), height, i, and width.

Referenced by render().

◆ render_with_textures()

static void render_with_textures ( FlCompositorOpenGL *  self,
GPtrArray *  framebuffers,
int  width,
int  height 
)
static

Definition at line 227 of file fl_compositor_opengl.cc.

230  {
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 }
int64_t texture_id

References fl_framebuffer_get_height(), fl_framebuffer_get_texture_id(), fl_framebuffer_get_width(), height, i, texture_id, and width.

Referenced by render().

◆ setup_shader()

static void setup_shader ( FlCompositorOpenGL *  self)
static

Definition at line 154 of file fl_compositor_opengl.cc.

154  {
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 }
static gchar * get_shader_log(GLuint shader)
static const char * fragment_shader_src
static gchar * get_program_log(GLuint program)
static const char * vertex_shader_src

References fragment_shader_src, get_program_log(), get_shader_log(), and vertex_shader_src.

Referenced by fl_compositor_opengl_new().

Variable Documentation

◆ fragment_shader_src

const char* fragment_shader_src
static
Initial value:
=
"#ifdef GL_ES\n"
"precision mediump float;\n"
"#endif\n"
"\n"
"uniform sampler2D texture;\n"
"varying vec2 texcoord;\n"
"\n"
"void main() {\n"
" gl_FragColor = texture2D(texture, texcoord);\n"
"}\n"

Definition at line 29 of file fl_compositor_opengl.cc.

Referenced by setup_shader().

◆ vertex_shader_src

const char* vertex_shader_src
static
Initial value:
=
"attribute vec2 position;\n"
"attribute vec2 in_texcoord;\n"
"uniform vec2 offset;\n"
"uniform vec2 scale;\n"
"varying vec2 texcoord;\n"
"\n"
"void main() {\n"
" gl_Position = vec4(offset + position * scale, 0, 1);\n"
" texcoord = in_texcoord;\n"
"}\n"

Definition at line 16 of file fl_compositor_opengl.cc.

Referenced by setup_shader().