diff --git a/include/render/gles2.h b/include/render/gles2.h index a472ee9c..0f24ae38 100644 --- a/include/render/gles2.h +++ b/include/render/gles2.h @@ -138,6 +138,8 @@ struct wlr_gles2_render_pass { float projection_matrix[9]; struct wlr_egl_context prev_ctx; struct wlr_gles2_render_timer *timer; + struct wlr_drm_syncobj_timeline *signal_timeline; + uint64_t signal_point; }; bool is_gles2_pixel_format_supported(const struct wlr_gles2_renderer *renderer, @@ -169,6 +171,7 @@ void push_gles2_debug_(struct wlr_gles2_renderer *renderer, void pop_gles2_debug(struct wlr_gles2_renderer *renderer); struct wlr_gles2_render_pass *begin_gles2_buffer_pass(struct wlr_gles2_buffer *buffer, - struct wlr_egl_context *prev_ctx, struct wlr_gles2_render_timer *timer); + struct wlr_egl_context *prev_ctx, struct wlr_gles2_render_timer *timer, + struct wlr_drm_syncobj_timeline *signal_timeline, uint64_t signal_point); #endif diff --git a/render/gles2/pass.c b/render/gles2/pass.c index 9177b0a1..2942ab58 100644 --- a/render/gles2/pass.c +++ b/render/gles2/pass.c @@ -2,8 +2,11 @@ #include #include #include +#include +#include #include #include +#include "render/egl.h" #include "render/gles2.h" #include "types/wlr_matrix.h" @@ -21,6 +24,7 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) { struct wlr_gles2_render_pass *pass = get_render_pass(wlr_pass); struct wlr_gles2_renderer *renderer = pass->buffer->renderer; struct wlr_gles2_render_timer *timer = pass->timer; + bool ok = false; push_gles2_debug(renderer); @@ -36,16 +40,40 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) { clock_gettime(CLOCK_MONOTONIC, &timer->cpu_end); } - glFlush(); + if (pass->signal_timeline != NULL) { + EGLSyncKHR sync = wlr_egl_create_sync(renderer->egl, -1); + if (sync == EGL_NO_SYNC_KHR) { + goto out; + } + + int sync_file_fd = wlr_egl_dup_fence_fd(renderer->egl, sync); + wlr_egl_destroy_sync(renderer->egl, sync); + if (sync_file_fd < 0) { + goto out; + } + + bool ok = wlr_drm_syncobj_timeline_import_sync_file(pass->signal_timeline, pass->signal_point, sync_file_fd); + close(sync_file_fd); + if (!ok) { + goto out; + } + } else { + glFlush(); + } + + ok = true; + +out: glBindFramebuffer(GL_FRAMEBUFFER, 0); pop_gles2_debug(renderer); wlr_egl_restore_context(&pass->prev_ctx); + wlr_drm_syncobj_timeline_unref(pass->signal_timeline); wlr_buffer_unlock(pass->buffer->buffer); free(pass); - return true; + return ok; } static void render(const struct wlr_box *box, const pixman_region32_t *clip, GLint attrib) { @@ -175,6 +203,27 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass, src_fbox.height /= options->texture->height; push_gles2_debug(renderer); + + if (options->wait_timeline != NULL) { + int sync_file_fd = + wlr_drm_syncobj_timeline_export_sync_file(options->wait_timeline, options->wait_point); + if (sync_file_fd < 0) { + return; + } + + EGLSyncKHR sync = wlr_egl_create_sync(renderer->egl, sync_file_fd); + close(sync_file_fd); + if (sync == EGL_NO_SYNC_KHR) { + return; + } + + bool ok = wlr_egl_wait_sync(renderer->egl, sync); + wlr_egl_destroy_sync(renderer->egl, sync); + if (!ok) { + return; + } + } + setup_blending(!texture->has_alpha && alpha == 1.0 ? WLR_RENDER_BLEND_MODE_NONE : options->blend_mode); @@ -247,7 +296,8 @@ static const char *reset_status_str(GLenum status) { } struct wlr_gles2_render_pass *begin_gles2_buffer_pass(struct wlr_gles2_buffer *buffer, - struct wlr_egl_context *prev_ctx, struct wlr_gles2_render_timer *timer) { + struct wlr_egl_context *prev_ctx, struct wlr_gles2_render_timer *timer, + struct wlr_drm_syncobj_timeline *signal_timeline, uint64_t signal_point) { struct wlr_gles2_renderer *renderer = buffer->renderer; struct wlr_buffer *wlr_buffer = buffer->buffer; @@ -275,6 +325,10 @@ struct wlr_gles2_render_pass *begin_gles2_buffer_pass(struct wlr_gles2_buffer *b pass->buffer = buffer; pass->timer = timer; pass->prev_ctx = *prev_ctx; + if (signal_timeline != NULL) { + pass->signal_timeline = wlr_drm_syncobj_timeline_ref(signal_timeline); + pass->signal_point = signal_point; + } matrix_projection(pass->projection_matrix, wlr_buffer->width, wlr_buffer->height, WL_OUTPUT_TRANSFORM_FLIPPED_180); diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index 4694b2a8..3eeb1ba9 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -259,7 +259,8 @@ static struct wlr_render_pass *gles2_begin_buffer_pass(struct wlr_renderer *wlr_ return NULL; } - struct wlr_gles2_render_pass *pass = begin_gles2_buffer_pass(buffer, &prev_ctx, timer); + struct wlr_gles2_render_pass *pass = begin_gles2_buffer_pass(buffer, + &prev_ctx, timer, options->signal_timeline, options->signal_point); if (!pass) { return NULL; } @@ -683,6 +684,9 @@ struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_egl *egl) { get_gles2_shm_formats(renderer, &renderer->shm_texture_formats); + renderer->wlr_renderer.features.timeline = + egl->procs.eglDupNativeFenceFDANDROID && egl->procs.eglWaitSyncKHR; + return &renderer->wlr_renderer; error: