| 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
10 struct _FlFramebuffer {
11 GObject parent_instance;
12
13 // Width of framebuffer in pixels.
14 size_t width;
15
16 // Height of framebuffer in pixels.
17 size_t height;
18
19 // Framebuffer ID.
20 GLuint framebuffer_id;
21
22 // Texture backing framebuffer.
23 GLuint texture_id;
24
25 // Stencil buffer associated with this framebuffer.
26 GLuint depth_stencil;
27
28 // EGL image for this texture.
29 EGLImage image;
30 };
31
32 G_DEFINE_TYPE(FlFramebuffer, fl_framebuffer, G_TYPE_OBJECT)
33
34 static EGLImage create_egl_image(GLuint texture_id) {
35 EGLDisplay egl_display = eglGetCurrentDisplay();
36 if (egl_display == EGL_NO_DISPLAY) {
37 g_warning("Failed to create EGL image: Failed to get current EGL display");
38 return nullptr;
39 }
40
41 EGLContext egl_context = eglGetCurrentContext();
42 if (egl_context == EGL_NO_CONTEXT) {
43 g_warning("Failed to create EGL image: Failed to get current EGL context");
44 return nullptr;
45 }
46
47 return eglCreateImage(
48 egl_display, egl_context, EGL_GL_TEXTURE_2D,
49 reinterpret_cast<EGLClientBuffer>(static_cast<intptr_t>(texture_id)),
50 nullptr);
51 }
52
53 static void fl_framebuffer_dispose(GObject* object) {
54 FlFramebuffer* self = FL_FRAMEBUFFER(object);
55
56 glDeleteFramebuffers(1, &self->framebuffer_id);
57 glDeleteTextures(1, &self->texture_id);
58 glDeleteRenderbuffers(1, &self->depth_stencil);
59
60 G_OBJECT_CLASS(fl_framebuffer_parent_class)->dispose(object);
61 }
62
63 static void fl_framebuffer_class_init(FlFramebufferClass* klass) {
64 G_OBJECT_CLASS(klass)->dispose = fl_framebuffer_dispose;
65 }
66
67 static void fl_framebuffer_init(FlFramebuffer* self) {}
68
69 FlFramebuffer* fl_framebuffer_new(GLint format,
70 size_t width,
71 size_t height,
72 gboolean shareable) {
73 FlFramebuffer* self =
74 FL_FRAMEBUFFER(g_object_new(fl_framebuffer_get_type(), nullptr));
75
76 self->width = width;
77 self->height = height;
78
79 glGenTextures(1, &self->texture_id);
80 glGenFramebuffers(1, &self->framebuffer_id);
81
82 glBindFramebuffer(GL_FRAMEBUFFER, self->framebuffer_id);
83
84 glBindTexture(GL_TEXTURE_2D, self->texture_id);
85 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
86 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
87 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
88 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
89 glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format,
90 GL_UNSIGNED_BYTE, NULL);
91 glBindTexture(GL_TEXTURE_2D, 0);
92
93 if (shareable) {
94 self->image = create_egl_image(self->texture_id);
95 }
96
97 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
98 self->texture_id, 0);
99
100 glGenRenderbuffers(1, &self->depth_stencil);
101 glBindRenderbuffer(GL_RENDERBUFFER, self->depth_stencil);
102 glRenderbufferStorage(GL_RENDERBUFFER, // target
103 GL_DEPTH24_STENCIL8, // internal format
104 width, // width
105 height // height
106 );
107 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
108 GL_RENDERBUFFER, self->depth_stencil);
109 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
110 GL_RENDERBUFFER, self->depth_stencil);
111
112 return self;
113 }
114
115 gboolean fl_framebuffer_get_shareable(FlFramebuffer* self) {
116 g_return_val_if_fail(FL_IS_FRAMEBUFFER(self), FALSE);
117 return self->image != nullptr;
118 }
119
120 FlFramebuffer* fl_framebuffer_create_sibling(FlFramebuffer* self) {
121 g_return_val_if_fail(FL_IS_FRAMEBUFFER(self), nullptr);
122 g_return_val_if_fail(self->image != nullptr, nullptr);
123
124 FlFramebuffer* sibling =
125 FL_FRAMEBUFFER(g_object_new(fl_framebuffer_get_type(), nullptr));
126
127 sibling->width = self->width;
128 sibling->height = self->height;
129 sibling->image = self->image;
130
131 // Make texture from existing image.
132 glGenTextures(1, &sibling->texture_id);
133 glBindTexture(GL_TEXTURE_2D, sibling->texture_id);
134 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, self->image);
135
136 // Make framebuffer that uses this texture.
137 glGenFramebuffers(1, &sibling->framebuffer_id);
138 GLint saved_framebuffer_binding;
139 glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &saved_framebuffer_binding);
140 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, sibling->framebuffer_id);
141 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
142 sibling->texture_id, 0);
143 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, saved_framebuffer_binding);
144
145 return sibling;
146 }
147
148 GLuint fl_framebuffer_get_id(FlFramebuffer* self) {
149 return self->framebuffer_id;
150 }
151
152 GLuint fl_framebuffer_get_texture_id(FlFramebuffer* self) {
153 return self->texture_id;
154 }
155
156 size_t fl_framebuffer_get_width(FlFramebuffer* self) {
157 return self->width;
158 }
159
160 size_t fl_framebuffer_get_height(FlFramebuffer* self) {
161 return self->height;
162 }
G_DEFINE_TYPE
G_DEFINE_TYPE(FlBasicMessageChannelResponseHandle, fl_basic_message_channel_response_handle, G_TYPE_OBJECT) static void fl_basic_message_channel_response_handle_dispose(GObject *object)
Definition: fl_basic_message_channel.cc:37
shareable
G_BEGIN_DECLS FlOpenGLManager gboolean shareable
Definition: fl_compositor_opengl.h:43
height
self height
Definition: fl_compositor_software.cc:43
width
self width
Definition: fl_compositor_software.cc:42
create_egl_image
static EGLImage create_egl_image(GLuint texture_id)
Definition: fl_framebuffer.cc:34
fl_framebuffer_get_height
size_t fl_framebuffer_get_height(FlFramebuffer *self)
Definition: fl_framebuffer.cc:160
fl_framebuffer_init
static void fl_framebuffer_init(FlFramebuffer *self)
Definition: fl_framebuffer.cc:67
fl_framebuffer_get_id
GLuint fl_framebuffer_get_id(FlFramebuffer *self)
Definition: fl_framebuffer.cc:148
fl_framebuffer_class_init
static void fl_framebuffer_class_init(FlFramebufferClass *klass)
Definition: fl_framebuffer.cc:63
fl_framebuffer_dispose
static void fl_framebuffer_dispose(GObject *object)
Definition: fl_framebuffer.cc:53
fl_framebuffer_get_shareable
gboolean fl_framebuffer_get_shareable(FlFramebuffer *self)
Definition: fl_framebuffer.cc:115
fl_framebuffer_get_width
size_t fl_framebuffer_get_width(FlFramebuffer *self)
Definition: fl_framebuffer.cc:156
fl_framebuffer_get_texture_id
GLuint fl_framebuffer_get_texture_id(FlFramebuffer *self)
Definition: fl_framebuffer.cc:152
fl_framebuffer_create_sibling
FlFramebuffer * fl_framebuffer_create_sibling(FlFramebuffer *self)
Definition: fl_framebuffer.cc:120
fl_framebuffer_new
FlFramebuffer * fl_framebuffer_new(GLint format, size_t width, size_t height, gboolean shareable)
Definition: fl_framebuffer.cc:69
fl_framebuffer.h
format
uint32_t uint32_t * format
Definition: fl_texture_registrar_test.cc:42
_FlFramebuffer
Definition: fl_framebuffer.cc:10
_FlFramebuffer::framebuffer_id
GLuint framebuffer_id
Definition: fl_framebuffer.cc:20
_FlFramebuffer::parent_instance
GObject parent_instance
Definition: fl_framebuffer.cc:11
_FlFramebuffer::image
EGLImage image
Definition: fl_framebuffer.cc:29
_FlFramebuffer::width
size_t width
Definition: fl_framebuffer.cc:14
_FlFramebuffer::depth_stencil
GLuint depth_stencil
Definition: fl_framebuffer.cc:26
_FlFramebuffer::texture_id
GLuint texture_id
Definition: fl_framebuffer.cc:23
_FlFramebuffer::height
size_t height
Definition: fl_framebuffer.cc:17
texture_id
int64_t texture_id
Definition: texture_registrar_unittests.cc:24