mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2026-05-24 16:58:17 +02:00
gl-renderer: Add FBO handling utilities
Add generic gl_fbo_init(), gl_fbo_image_init() and gl_fbo_fini() utilities to the GL renderer and make use of these in the renderbuffer creation functions. This also fixes a framebuffer object leak on dma-buf renderbuffer creation when the EGLImageTargetRenderbufferStorageOES() call fails. Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
This commit is contained in:
parent
1c7274deed
commit
0688343dec
1 changed files with 121 additions and 86 deletions
|
|
@ -637,6 +637,95 @@ timeline_submit_render_sync(struct gl_renderer *gr,
|
|||
wl_list_insert(&go->timeline_render_point_list, &trp->link);
|
||||
}
|
||||
|
||||
/* Initialise a pair of framebuffer and renderbuffer objects. Use gl_fbo_fini()
|
||||
* to finalise.
|
||||
*/
|
||||
static bool
|
||||
gl_fbo_init(GLenum internal_format,
|
||||
int width,
|
||||
int height,
|
||||
GLuint *fb_out,
|
||||
GLuint *rb_out)
|
||||
{
|
||||
GLuint fb, rb;
|
||||
GLenum status;
|
||||
|
||||
glGenFramebuffers(1, &fb);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb);
|
||||
glGenRenderbuffers(1, &rb);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rb);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, internal_format, width, height);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
GL_RENDERBUFFER, rb);
|
||||
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
weston_log("Error: FBO incomplete.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
*fb_out = fb;
|
||||
*rb_out = rb;
|
||||
return true;
|
||||
|
||||
error:
|
||||
glDeleteFramebuffers(1, &fb);
|
||||
glDeleteRenderbuffers(1, &rb);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Finalise a pair of framebuffer and renderbuffer objects.
|
||||
*/
|
||||
static void
|
||||
gl_fbo_fini(GLuint *fb,
|
||||
GLuint *rb)
|
||||
{
|
||||
glDeleteFramebuffers(1, fb);
|
||||
glDeleteRenderbuffers(1, rb);
|
||||
*fb = 0;
|
||||
*rb = 0;
|
||||
}
|
||||
|
||||
/* Initialise a pair of framebuffer and renderbuffer objects to render into an
|
||||
* EGL image. Use gl_fbo_fini() to finalise.
|
||||
*/
|
||||
static bool
|
||||
gl_fbo_image_init(struct gl_renderer *gr,
|
||||
EGLImageKHR image,
|
||||
GLuint *fb_out,
|
||||
GLuint *rb_out)
|
||||
{
|
||||
GLuint fb, rb;
|
||||
GLenum status;
|
||||
|
||||
glGenFramebuffers(1, &fb);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb);
|
||||
glGenRenderbuffers(1, &rb);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rb);
|
||||
gr->image_target_renderbuffer_storage(GL_RENDERBUFFER, image);
|
||||
if (glGetError() == GL_INVALID_OPERATION)
|
||||
goto error;
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
GL_RENDERBUFFER, rb);
|
||||
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
weston_log("Error: FBO incomplete.\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
*fb_out = fb;
|
||||
*rb_out = rb;
|
||||
return true;
|
||||
|
||||
error:
|
||||
glDeleteFramebuffers(1, &fb);
|
||||
glDeleteRenderbuffers(1, &rb);
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Create a texture and a framebuffer object
|
||||
*
|
||||
* \param fbotex To be initialized.
|
||||
|
|
@ -725,12 +814,11 @@ gl_renderbuffer_fini(struct gl_renderbuffer *renderbuffer)
|
|||
assert(!renderbuffer->stale);
|
||||
|
||||
pixman_region32_fini(&renderbuffer->damage);
|
||||
glDeleteFramebuffers(1, &renderbuffer->fb);
|
||||
|
||||
if (renderbuffer->type == RENDERBUFFER_FBO) {
|
||||
glDeleteRenderbuffers(1, &renderbuffer->fbo.rb);
|
||||
gl_fbo_fini(&renderbuffer->fb, &renderbuffer->fbo.rb);
|
||||
} else if (renderbuffer->type == RENDERBUFFER_DMABUF) {
|
||||
glDeleteRenderbuffers(1, &renderbuffer->dmabuf.rb);
|
||||
gl_fbo_fini(&renderbuffer->fb, &renderbuffer->dmabuf.rb);
|
||||
renderbuffer->dmabuf.gr->destroy_image(renderbuffer->dmabuf.gr->egl_display,
|
||||
renderbuffer->dmabuf.image);
|
||||
}
|
||||
|
|
@ -802,8 +890,7 @@ gl_renderer_create_fbo(struct weston_output *output,
|
|||
{
|
||||
struct gl_renderer *gr = get_renderer(output->compositor);
|
||||
struct gl_renderbuffer *renderbuffer;
|
||||
int fb_status;
|
||||
GLuint fb;
|
||||
GLuint fb, rb;
|
||||
|
||||
switch (format->gl_internalformat) {
|
||||
case GL_RGB8:
|
||||
|
|
@ -822,29 +909,14 @@ gl_renderer_create_fbo(struct weston_output *output,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
renderbuffer = xzalloc(sizeof(*renderbuffer));
|
||||
|
||||
glGenFramebuffers(1, &fb);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb);
|
||||
|
||||
glGenRenderbuffers(1, &renderbuffer->fbo.rb);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer->fbo.rb);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, format->gl_internalformat,
|
||||
width, height);
|
||||
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
GL_RENDERBUFFER, renderbuffer->fbo.rb);
|
||||
|
||||
fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
if (fb_status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
glDeleteFramebuffers(1, &fb);
|
||||
glDeleteRenderbuffers(1, &renderbuffer->fbo.rb);
|
||||
free(renderbuffer);
|
||||
if (!gl_fbo_init(format->gl_internalformat, width, height, &fb, &rb)) {
|
||||
weston_log("Failed to init renderbuffer\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
renderbuffer = xzalloc(sizeof(*renderbuffer));
|
||||
|
||||
renderbuffer->fbo.rb = rb;
|
||||
renderbuffer->fbo.pixels = pixels;
|
||||
gl_renderbuffer_init(renderbuffer, RENDERBUFFER_FBO,
|
||||
BORDER_STATUS_CLEAN, fb, discarded_cb, user_data,
|
||||
|
|
@ -865,51 +937,25 @@ gl_renderer_create_renderbuffer_dmabuf(struct weston_output *output,
|
|||
struct gl_renderer *gr = get_renderer(output->compositor);
|
||||
struct dmabuf_attributes *attributes = dmabuf->attributes;
|
||||
struct gl_renderbuffer *renderbuffer;
|
||||
int fb_status;
|
||||
GLuint fb;
|
||||
EGLImageKHR image;
|
||||
GLuint fb, rb;
|
||||
|
||||
image = import_simple_dmabuf(gr, attributes);
|
||||
if (image == EGL_NO_IMAGE_KHR) {
|
||||
weston_log("Failed to import dmabuf\n");
|
||||
return NULL;
|
||||
}
|
||||
if (!gl_fbo_image_init(gr, image, &fb, &rb)) {
|
||||
weston_log("Failed to init renderbuffer from dmabuf\n");
|
||||
gr->destroy_image(gr->egl_display, image);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
renderbuffer = xzalloc(sizeof(*renderbuffer));
|
||||
|
||||
renderbuffer->dmabuf.image = import_simple_dmabuf(gr, attributes);
|
||||
if (renderbuffer->dmabuf.image == EGL_NO_IMAGE_KHR) {
|
||||
weston_log("Failed to import dmabuf renderbuffer\n");
|
||||
free(renderbuffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
glGenFramebuffers(1, &fb);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb);
|
||||
|
||||
glGenRenderbuffers(1, &renderbuffer->dmabuf.rb);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer->dmabuf.rb);
|
||||
gr->image_target_renderbuffer_storage(GL_RENDERBUFFER,
|
||||
renderbuffer->dmabuf.image);
|
||||
if (glGetError() == GL_INVALID_OPERATION) {
|
||||
weston_log("Failed to create renderbuffer\n");
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
glDeleteRenderbuffers(1, &renderbuffer->dmabuf.rb);
|
||||
gr->destroy_image(gr->egl_display, renderbuffer->dmabuf.image);
|
||||
free(renderbuffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
GL_RENDERBUFFER, renderbuffer->dmabuf.rb);
|
||||
|
||||
fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||
if (fb_status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
weston_log("failed to bind renderbuffer to fbo\n");
|
||||
glDeleteFramebuffers(1, &fb);
|
||||
glDeleteRenderbuffers(1, &renderbuffer->dmabuf.rb);
|
||||
gr->destroy_image(gr->egl_display, renderbuffer->dmabuf.image);
|
||||
free(renderbuffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
renderbuffer->dmabuf.gr = gr;
|
||||
renderbuffer->dmabuf.memory = dmabuf;
|
||||
renderbuffer->dmabuf.image = image;
|
||||
gl_renderbuffer_init(renderbuffer, RENDERBUFFER_DMABUF,
|
||||
BORDER_STATUS_CLEAN, fb, discarded_cb, user_data,
|
||||
output);
|
||||
|
|
@ -3903,9 +3949,7 @@ gl_renderer_surface_copy_content(struct weston_surface *surface,
|
|||
struct gl_buffer_state *gb;
|
||||
struct weston_buffer *buffer;
|
||||
int cw, ch;
|
||||
GLuint fbo;
|
||||
GLuint rb;
|
||||
GLenum status;
|
||||
GLuint fbo, rb;
|
||||
int ret = -1;
|
||||
|
||||
gs = get_surface_state(surface);
|
||||
|
|
@ -3930,20 +3974,12 @@ gl_renderer_surface_copy_content(struct weston_surface *surface,
|
|||
|
||||
gl_shader_config_set_input_textures(&sconf, gs);
|
||||
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glGenRenderbuffers(1, &rb);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rb);
|
||||
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, cw, ch);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
GL_RENDERBUFFER, rb);
|
||||
|
||||
status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
if (status != GL_FRAMEBUFFER_COMPLETE) {
|
||||
weston_log("%s: fbo error: %#x\n", __func__, status);
|
||||
goto out;
|
||||
if (!gl_fbo_init(GL_RGBA, cw, ch, &fbo, &rb)) {
|
||||
weston_log("Failed to init FBO\n");
|
||||
goto fbo_init_error;
|
||||
}
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rb);
|
||||
|
||||
glViewport(0, 0, cw, ch);
|
||||
glDisable(GL_BLEND);
|
||||
|
|
@ -3955,7 +3991,7 @@ gl_renderer_surface_copy_content(struct weston_surface *surface,
|
|||
WESTON_MATRIX_TRANSFORM_TRANSLATE;
|
||||
|
||||
if (!gl_renderer_use_program(gr, &sconf))
|
||||
goto out;
|
||||
goto use_program_error;
|
||||
|
||||
glEnableVertexAttribArray(SHADER_ATTRIB_LOC_POSITION);
|
||||
glEnableVertexAttribArray(SHADER_ATTRIB_LOC_TEXCOORD);
|
||||
|
|
@ -3971,10 +4007,9 @@ gl_renderer_surface_copy_content(struct weston_surface *surface,
|
|||
GL_UNSIGNED_BYTE, target);
|
||||
ret = 0;
|
||||
|
||||
out:
|
||||
glDeleteFramebuffers(1, &fbo);
|
||||
glDeleteRenderbuffers(1, &rb);
|
||||
|
||||
use_program_error:
|
||||
gl_fbo_fini(&fbo, &rb);
|
||||
fbo_init_error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue