From b6a990da71b5b0947650a50dcf1a083acfce868c Mon Sep 17 00:00:00 2001 From: Erik Reider <35975961+ErikReider@users.noreply.github.com> Date: Sat, 30 Dec 2023 12:45:04 +0100 Subject: Added fx_texture and fx_framebuffer --- render/fx_renderer/fx_framebuffer.c | 136 ++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 render/fx_renderer/fx_framebuffer.c (limited to 'render/fx_renderer/fx_framebuffer.c') diff --git a/render/fx_renderer/fx_framebuffer.c b/render/fx_renderer/fx_framebuffer.c new file mode 100644 index 0000000..4de6439 --- /dev/null +++ b/render/fx_renderer/fx_framebuffer.c @@ -0,0 +1,136 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "render/egl.h" +#include "render/fx_renderer/fx_renderer.h" + +static void handle_buffer_destroy(struct wlr_addon *addon) { + struct fx_framebuffer *buffer = + wl_container_of(addon, buffer, addon); + fx_framebuffer_release(buffer); +} + +static const struct wlr_addon_interface buffer_addon_impl = { + .name = "fx_framebuffer", + .destroy = handle_buffer_destroy, +}; + + +struct fx_framebuffer fx_framebuffer_create(void) { + return (struct fx_framebuffer) { + .initialized = false, + .fbo = -1, + .rbo = -1, + .wlr_buffer = NULL, + .image = NULL, + }; +} + +void fx_framebuffer_bind(struct fx_framebuffer *fx_buffer) { + glBindFramebuffer(GL_FRAMEBUFFER, fx_buffer->fbo); +} + +void fx_framebuffer_bind_wlr_fbo(struct fx_renderer *renderer) { + glBindFramebuffer(GL_FRAMEBUFFER, renderer->wlr_main_buffer_fbo); +} + +void fx_framebuffer_update(struct fx_renderer *fx_renderer, struct fx_framebuffer *fx_buffer, + int width, int height) { + struct wlr_output *output = fx_renderer->wlr_output; + + fx_buffer->renderer = fx_renderer; + + bool first_alloc = false; + + if (!fx_buffer->wlr_buffer || + fx_buffer->wlr_buffer->width != width || + fx_buffer->wlr_buffer->height != height) { + wlr_buffer_drop(fx_buffer->wlr_buffer); + fx_buffer->wlr_buffer = wlr_allocator_create_buffer(output->allocator, + width, height, &output->swapchain->format); + first_alloc = true; + } + + if (fx_buffer->fbo == (uint32_t) -1 || first_alloc) { + glGenFramebuffers(1, &fx_buffer->fbo); + first_alloc = true; + } + + if (fx_buffer->rbo == (uint32_t) -1 || first_alloc) { + struct wlr_dmabuf_attributes dmabuf = {0}; + if (!wlr_buffer_get_dmabuf(fx_buffer->wlr_buffer, &dmabuf)) { + goto error_buffer; + } + + bool external_only; + fx_buffer->image = wlr_egl_create_image_from_dmabuf(fx_renderer->egl, + &dmabuf, &external_only); + if (fx_buffer->image == EGL_NO_IMAGE_KHR) { + goto error_buffer; + } + + glGenRenderbuffers(1, &fx_buffer->rbo); + glBindRenderbuffer(GL_RENDERBUFFER, fx_buffer->rbo); + fx_renderer->procs.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, + fx_buffer->image); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + + glBindFramebuffer(GL_FRAMEBUFFER, fx_buffer->fbo); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, fx_buffer->rbo); + GLenum fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + if (fb_status != GL_FRAMEBUFFER_COMPLETE) { + wlr_log(WLR_ERROR, "Failed to create FBO"); + goto error_image; + } + } + + if (!fx_buffer->initialized) { + fx_buffer->initialized = true; + + wlr_addon_init(&fx_buffer->addon, &fx_buffer->wlr_buffer->addons, fx_renderer, + &buffer_addon_impl); + + wl_list_insert(&fx_renderer->buffers, &fx_buffer->link); + } + + if (first_alloc) { + wlr_log(WLR_DEBUG, "Created GL FBO for buffer %dx%d", + fx_buffer->wlr_buffer->width, fx_buffer->wlr_buffer->height); + } + + return; +error_image: + wlr_egl_destroy_image(fx_renderer->egl, fx_buffer->image); +error_buffer: + wlr_log(WLR_ERROR, "Could not create FX buffer! Aborting..."); + abort(); +} + +void fx_framebuffer_release(struct fx_framebuffer *fx_buffer) { + // Release the framebuffer + wl_list_remove(&fx_buffer->link); + wlr_addon_finish(&fx_buffer->addon); + + struct wlr_egl_context prev_ctx; + wlr_egl_save_context(&prev_ctx); + wlr_egl_make_current(fx_buffer->renderer->egl); + + glDeleteFramebuffers(1, &fx_buffer->fbo); + fx_buffer->fbo = -1; + glDeleteRenderbuffers(1, &fx_buffer->rbo); + fx_buffer->rbo = -1; + + wlr_egl_destroy_image(fx_buffer->renderer->egl, fx_buffer->image); + + wlr_egl_restore_context(&prev_ctx); + + fx_buffer->initialized = false; +} -- cgit v1.2.3 From 51c7078b9ec413ebd8316501f01ccf769a090f64 Mon Sep 17 00:00:00 2001 From: Erik Reider <35975961+ErikReider@users.noreply.github.com> Date: Sun, 31 Dec 2023 00:32:39 +0100 Subject: Converted fx_renderer to impl wlr_renderer Makes the fx_renderer the default renderer for everything, no wlr_gles2 rendering. This includes wlr_render_pass (fx_render_pass in our case) --- render/fx_renderer/fx_framebuffer.c | 140 ++++++++++++++++-------------------- 1 file changed, 61 insertions(+), 79 deletions(-) (limited to 'render/fx_renderer/fx_framebuffer.c') diff --git a/render/fx_renderer/fx_framebuffer.c b/render/fx_renderer/fx_framebuffer.c index 4de6439..3e52f49 100644 --- a/render/fx_renderer/fx_framebuffer.c +++ b/render/fx_renderer/fx_framebuffer.c @@ -12,7 +12,7 @@ static void handle_buffer_destroy(struct wlr_addon *addon) { struct fx_framebuffer *buffer = wl_container_of(addon, buffer, addon); - fx_framebuffer_release(buffer); + fx_framebuffer_destroy(buffer); } static const struct wlr_addon_interface buffer_addon_impl = { @@ -20,101 +20,83 @@ static const struct wlr_addon_interface buffer_addon_impl = { .destroy = handle_buffer_destroy, }; +struct fx_framebuffer *fx_framebuffer_get_or_create(struct fx_renderer *renderer, + struct wlr_buffer *wlr_buffer) { + struct wlr_addon *addon = + wlr_addon_find(&wlr_buffer->addons, renderer, &buffer_addon_impl); + if (addon) { + struct fx_framebuffer *buffer = wl_container_of(addon, buffer, addon); + return buffer; + } -struct fx_framebuffer fx_framebuffer_create(void) { - return (struct fx_framebuffer) { - .initialized = false, - .fbo = -1, - .rbo = -1, - .wlr_buffer = NULL, - .image = NULL, - }; -} - -void fx_framebuffer_bind(struct fx_framebuffer *fx_buffer) { - glBindFramebuffer(GL_FRAMEBUFFER, fx_buffer->fbo); -} + struct fx_framebuffer *buffer = calloc(1, sizeof(*buffer)); + if (buffer == NULL) { + wlr_log_errno(WLR_ERROR, "Allocation failed"); + return NULL; + } + buffer->buffer = wlr_buffer; + buffer->renderer = renderer; -void fx_framebuffer_bind_wlr_fbo(struct fx_renderer *renderer) { - glBindFramebuffer(GL_FRAMEBUFFER, renderer->wlr_main_buffer_fbo); -} + struct wlr_dmabuf_attributes dmabuf = {0}; + if (!wlr_buffer_get_dmabuf(wlr_buffer, &dmabuf)) { + goto error_buffer; + } -void fx_framebuffer_update(struct fx_renderer *fx_renderer, struct fx_framebuffer *fx_buffer, - int width, int height) { - struct wlr_output *output = fx_renderer->wlr_output; + bool external_only; + buffer->image = wlr_egl_create_image_from_dmabuf(renderer->egl, + &dmabuf, &external_only); + if (buffer->image == EGL_NO_IMAGE_KHR) { + goto error_buffer; + } - fx_buffer->renderer = fx_renderer; + push_fx_debug(renderer); - bool first_alloc = false; + glGenRenderbuffers(1, &buffer->rbo); + glBindRenderbuffer(GL_RENDERBUFFER, buffer->rbo); + renderer->procs.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, + buffer->image); + glBindRenderbuffer(GL_RENDERBUFFER, 0); - if (!fx_buffer->wlr_buffer || - fx_buffer->wlr_buffer->width != width || - fx_buffer->wlr_buffer->height != height) { - wlr_buffer_drop(fx_buffer->wlr_buffer); - fx_buffer->wlr_buffer = wlr_allocator_create_buffer(output->allocator, - width, height, &output->swapchain->format); - first_alloc = true; - } + glGenFramebuffers(1, &buffer->fbo); + glBindFramebuffer(GL_FRAMEBUFFER, buffer->fbo); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, buffer->rbo); + GLenum fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + glBindFramebuffer(GL_FRAMEBUFFER, 0); - if (fx_buffer->fbo == (uint32_t) -1 || first_alloc) { - glGenFramebuffers(1, &fx_buffer->fbo); - first_alloc = true; - } + pop_fx_debug(renderer); - if (fx_buffer->rbo == (uint32_t) -1 || first_alloc) { - struct wlr_dmabuf_attributes dmabuf = {0}; - if (!wlr_buffer_get_dmabuf(fx_buffer->wlr_buffer, &dmabuf)) { - goto error_buffer; - } - - bool external_only; - fx_buffer->image = wlr_egl_create_image_from_dmabuf(fx_renderer->egl, - &dmabuf, &external_only); - if (fx_buffer->image == EGL_NO_IMAGE_KHR) { - goto error_buffer; - } - - glGenRenderbuffers(1, &fx_buffer->rbo); - glBindRenderbuffer(GL_RENDERBUFFER, fx_buffer->rbo); - fx_renderer->procs.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, - fx_buffer->image); - glBindRenderbuffer(GL_RENDERBUFFER, 0); - - glBindFramebuffer(GL_FRAMEBUFFER, fx_buffer->fbo); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_RENDERBUFFER, fx_buffer->rbo); - GLenum fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - if (fb_status != GL_FRAMEBUFFER_COMPLETE) { - wlr_log(WLR_ERROR, "Failed to create FBO"); - goto error_image; - } + if (fb_status != GL_FRAMEBUFFER_COMPLETE) { + wlr_log(WLR_ERROR, "Failed to create FBO"); + goto error_image; } - if (!fx_buffer->initialized) { - fx_buffer->initialized = true; + wlr_addon_init(&buffer->addon, &wlr_buffer->addons, renderer, + &buffer_addon_impl); - wlr_addon_init(&fx_buffer->addon, &fx_buffer->wlr_buffer->addons, fx_renderer, - &buffer_addon_impl); + wl_list_insert(&renderer->buffers, &buffer->link); - wl_list_insert(&fx_renderer->buffers, &fx_buffer->link); - } + wlr_log(WLR_DEBUG, "Created GL FBO for buffer %dx%d", + wlr_buffer->width, wlr_buffer->height); - if (first_alloc) { - wlr_log(WLR_DEBUG, "Created GL FBO for buffer %dx%d", - fx_buffer->wlr_buffer->width, fx_buffer->wlr_buffer->height); - } + return buffer; - return; error_image: - wlr_egl_destroy_image(fx_renderer->egl, fx_buffer->image); + wlr_egl_destroy_image(renderer->egl, buffer->image); error_buffer: - wlr_log(WLR_ERROR, "Could not create FX buffer! Aborting..."); - abort(); + free(buffer); + return NULL; +} + +void fx_framebuffer_bind(struct fx_framebuffer *fx_buffer) { + glBindFramebuffer(GL_FRAMEBUFFER, fx_buffer->fbo); +} + +void fx_framebuffer_bind_wlr_fbo(struct fx_renderer *renderer) { + glBindFramebuffer(GL_FRAMEBUFFER, renderer->current_buffer->fbo); } -void fx_framebuffer_release(struct fx_framebuffer *fx_buffer) { +void fx_framebuffer_destroy(struct fx_framebuffer *fx_buffer) { // Release the framebuffer wl_list_remove(&fx_buffer->link); wlr_addon_finish(&fx_buffer->addon); @@ -132,5 +114,5 @@ void fx_framebuffer_release(struct fx_framebuffer *fx_buffer) { wlr_egl_restore_context(&prev_ctx); - fx_buffer->initialized = false; + free(fx_buffer); } -- cgit v1.2.3 From 1a6918f948be034e65c50af8969d090b5e762dc1 Mon Sep 17 00:00:00 2001 From: Erik Reider <35975961+ErikReider@users.noreply.github.com> Date: Tue, 2 Jan 2024 01:15:34 +0100 Subject: Integrated the stencil rb into fx_framebuffer Every fx_framebuffer will now have a stencil buffer --- render/fx_renderer/fx_framebuffer.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'render/fx_renderer/fx_framebuffer.c') diff --git a/render/fx_renderer/fx_framebuffer.c b/render/fx_renderer/fx_framebuffer.c index 3e52f49..fea101b 100644 --- a/render/fx_renderer/fx_framebuffer.c +++ b/render/fx_renderer/fx_framebuffer.c @@ -62,15 +62,32 @@ struct fx_framebuffer *fx_framebuffer_get_or_create(struct fx_renderer *renderer glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, buffer->rbo); GLenum fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - glBindFramebuffer(GL_FRAMEBUFFER, 0); - - pop_fx_debug(renderer); - if (fb_status != GL_FRAMEBUFFER_COMPLETE) { wlr_log(WLR_ERROR, "Failed to create FBO"); + glBindFramebuffer(GL_FRAMEBUFFER, 0); goto error_image; } + // Init stencil buffer + glGenRenderbuffers(1, &buffer->sb); + glBindRenderbuffer(GL_RENDERBUFFER, buffer->sb); + glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, + wlr_buffer->width, wlr_buffer->height); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, buffer->sb); + fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (fb_status != GL_FRAMEBUFFER_COMPLETE) { + wlr_log(WLR_ERROR, + "Stencil buffer incomplete, couldn't create! (FB status: %i)", + fb_status); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + goto error_stencil; + } + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + pop_fx_debug(renderer); + wlr_addon_init(&buffer->addon, &wlr_buffer->addons, renderer, &buffer_addon_impl); @@ -81,6 +98,8 @@ struct fx_framebuffer *fx_framebuffer_get_or_create(struct fx_renderer *renderer return buffer; +error_stencil: + glDeleteRenderbuffers(1, &buffer->sb); error_image: wlr_egl_destroy_image(renderer->egl, buffer->image); error_buffer: -- cgit v1.2.3