Flutter Linux Embedder
fl_framebuffer.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "fl_framebuffer.h"
6 
7 #include <epoxy/egl.h>
8 #include <epoxy/gl.h>
9 
11 
13  GObject parent_instance;
14 
15  // Width of framebuffer in pixels.
16  size_t width;
17 
18  // Height of framebuffer in pixels.
19  size_t height;
20 
21  // Framebuffer ID.
23 
24  // Texture backing framebuffer.
25  GLuint texture_id;
26 
27  // Stencil buffer associated with this framebuffer.
28  GLuint depth_stencil;
29 
30  // EGL image for this texture.
31  FlEGLImage* image;
32 };
33 
34 G_DEFINE_TYPE(FlFramebuffer, fl_framebuffer, G_TYPE_OBJECT)
35 
36 static void fl_framebuffer_dispose(GObject* object) {
37  FlFramebuffer* self = FL_FRAMEBUFFER(object);
38 
39  glDeleteFramebuffers(1, &self->framebuffer_id);
40  glDeleteTextures(1, &self->texture_id);
41  glDeleteRenderbuffers(1, &self->depth_stencil);
42  g_clear_object(&self->image);
43 
44  G_OBJECT_CLASS(fl_framebuffer_parent_class)->dispose(object);
45 }
46 
47 static void fl_framebuffer_class_init(FlFramebufferClass* klass) {
48  G_OBJECT_CLASS(klass)->dispose = fl_framebuffer_dispose;
49 }
50 
51 static void fl_framebuffer_init(FlFramebuffer* self) {}
52 
53 FlFramebuffer* fl_framebuffer_new(GLint format,
54  size_t width,
55  size_t height,
56  gboolean shareable) {
57  FlFramebuffer* self =
58  FL_FRAMEBUFFER(g_object_new(fl_framebuffer_get_type(), nullptr));
59 
60  self->width = width;
61  self->height = height;
62 
63  glGenTextures(1, &self->texture_id);
64  glGenFramebuffers(1, &self->framebuffer_id);
65 
66  glBindFramebuffer(GL_FRAMEBUFFER, self->framebuffer_id);
67 
68  glBindTexture(GL_TEXTURE_2D, self->texture_id);
69  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
70  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
71  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
72  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
73  glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format,
74  GL_UNSIGNED_BYTE, NULL);
75  glBindTexture(GL_TEXTURE_2D, 0);
76 
77  if (shareable) {
78  self->image = fl_egl_image_new(self->texture_id);
79  }
80 
81  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
82  self->texture_id, 0);
83 
84  glGenRenderbuffers(1, &self->depth_stencil);
85  glBindRenderbuffer(GL_RENDERBUFFER, self->depth_stencil);
86  glRenderbufferStorage(GL_RENDERBUFFER, // target
87  GL_DEPTH24_STENCIL8, // internal format
88  width, // width
89  height // height
90  );
91  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
92  GL_RENDERBUFFER, self->depth_stencil);
93  glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
94  GL_RENDERBUFFER, self->depth_stencil);
95 
96  return self;
97 }
98 
99 gboolean fl_framebuffer_get_shareable(FlFramebuffer* self) {
100  g_return_val_if_fail(FL_IS_FRAMEBUFFER(self), FALSE);
101  return self->image != nullptr;
102 }
103 
104 FlFramebuffer* fl_framebuffer_create_sibling(FlFramebuffer* self) {
105  g_return_val_if_fail(FL_IS_FRAMEBUFFER(self), nullptr);
106  g_return_val_if_fail(self->image != nullptr, nullptr);
107 
108  FlFramebuffer* sibling =
109  FL_FRAMEBUFFER(g_object_new(fl_framebuffer_get_type(), nullptr));
110 
111  sibling->width = self->width;
112  sibling->height = self->height;
113  sibling->image = FL_EGL_IMAGE(g_object_ref(self->image));
114 
115  // Make texture from existing image.
116  glGenTextures(1, &sibling->texture_id);
117  glBindTexture(GL_TEXTURE_2D, sibling->texture_id);
118  glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
119  fl_egl_image_get_image(self->image));
120 
121  // Make framebuffer that uses this texture.
122  glGenFramebuffers(1, &sibling->framebuffer_id);
123  GLint saved_framebuffer_binding;
124  glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &saved_framebuffer_binding);
125  glBindFramebuffer(GL_DRAW_FRAMEBUFFER, sibling->framebuffer_id);
126  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
127  sibling->texture_id, 0);
128  glBindFramebuffer(GL_DRAW_FRAMEBUFFER, saved_framebuffer_binding);
129 
130  return sibling;
131 }
132 
133 GLuint fl_framebuffer_get_id(FlFramebuffer* self) {
134  return self->framebuffer_id;
135 }
136 
137 GLuint fl_framebuffer_get_texture_id(FlFramebuffer* self) {
138  return self->texture_id;
139 }
140 
141 size_t fl_framebuffer_get_width(FlFramebuffer* self) {
142  return self->width;
143 }
144 
145 size_t fl_framebuffer_get_height(FlFramebuffer* self) {
146  return self->height;
147 }
G_DEFINE_TYPE(FlBasicMessageChannelResponseHandle, fl_basic_message_channel_response_handle, G_TYPE_OBJECT) static void fl_basic_message_channel_response_handle_dispose(GObject *object)
G_BEGIN_DECLS FlOpenGLManager gboolean shareable
self height
self width
FlEGLImage * fl_egl_image_new(GLuint texture)
Definition: fl_egl_image.cc:59
EGLImage fl_egl_image_get_image(FlEGLImage *image)
Definition: fl_egl_image.cc:68
size_t fl_framebuffer_get_height(FlFramebuffer *self)
static void fl_framebuffer_init(FlFramebuffer *self)
GLuint fl_framebuffer_get_id(FlFramebuffer *self)
static void fl_framebuffer_class_init(FlFramebufferClass *klass)
static void fl_framebuffer_dispose(GObject *object)
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)
uint32_t uint32_t * format
GObject parent_instance
FlEGLImage * image