diff --git a/include/window/wayland.h b/include/window/wayland.h index 0ab69b1..23e2010 100644 --- a/include/window/wayland.h +++ b/include/window/wayland.h @@ -16,6 +16,9 @@ public: size_t GetHeight() const override; private: + void render_frame(); + +private: // wayland listeners static void handle_frame_callback(void *data, struct wl_callback *cb, uint32_t time); static void xsurface_handle_configure(void *data, struct xdg_surface *surface, @@ -32,7 +35,7 @@ private: struct xdg_toplevel *toplevel, struct wl_array *capabilities); -private: +private: // wayland internals EGLSurface m_egl_surface; EGLContext m_egl_context; GLuint m_program; @@ -44,9 +47,13 @@ private: struct xdg_surface_listener m_xsurface_listener; struct xdg_toplevel_listener m_toplevel_listener; +private: bool m_running = false; size_t m_width, m_height; IFrameListener m_on_frame; + + bool m_frame_cb_pending = false; + bool m_redraw_requested = false; }; diff --git a/src/window/wayland.cpp b/src/window/wayland.cpp index 1ee5612..e2e03c8 100644 --- a/src/window/wayland.cpp +++ b/src/window/wayland.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "state/wayland.h" #include "window.h" @@ -9,7 +10,7 @@ #include "shader.h" WaylandWindowImpl::WaylandWindowImpl(size_t width, size_t height) - : m_frame_listener({0}), m_width(width), m_height(height) { + : m_frame_listener({0}), m_width(width), m_height(height), m_frame_cb_pending(false), m_redraw_requested(false) { m_wsurface = wl_compositor_create_surface(WaylandState::GetInstance()->m_compositor); if (m_wsurface == NULL) { @@ -90,30 +91,52 @@ WaylandWindowImpl::WaylandWindowImpl(size_t width, size_t height) m_toplevel_listener.close = xtoplevel_handle_close; m_toplevel_listener.wm_capabilities = xtoplevel_handle_wm_capabilities; xdg_toplevel_add_listener(m_toplevel, &m_toplevel_listener, this); + + wl_surface_commit(m_wsurface); } WaylandWindowImpl::~WaylandWindowImpl() { m_running = false; } -void WaylandWindowImpl::OnFrame(IFrameListener fn) { - m_on_frame = fn; -} +void WaylandWindowImpl::OnFrame(IFrameListener fn) { m_on_frame = fn; } bool WaylandWindowImpl::Dispatch() { - wl_surface_commit(m_wsurface); + auto display = WaylandState::GetInstance()->m_display; - m_running = true; + printf("[DEBUG-WAYLAND]: checking if redraw needed, cb_pending = %d, " + "redraw_req = %d\n", + m_frame_cb_pending, m_redraw_requested); - auto display = WaylandState::GetInstance()->m_display; + if (!m_frame_cb_pending && m_redraw_requested) { + printf("[DEBUG-WAYLAND]: redraw requested\n"); + render_frame(); + auto frame_callback = wl_surface_frame(m_wsurface); + m_frame_listener.done = handle_frame_callback; + wl_callback_add_listener(frame_callback, &m_frame_listener, this); + m_frame_cb_pending = true; + m_redraw_requested = false; + wl_surface_commit(m_wsurface); + } - // wl_display_dispatch_pending(display); - return wl_display_dispatch(display) != -1; } - -size_t WaylandWindowImpl::GetWidth() const { - return m_width; + // wl_display_dispatch_pending(display); + return wl_display_dispatch(display) != -1; } -size_t WaylandWindowImpl::GetHeight() const { - return m_height; +size_t WaylandWindowImpl::GetWidth() const { return m_width; } + +size_t WaylandWindowImpl::GetHeight() const { return m_height; } + +void WaylandWindowImpl::render_frame() { + GLint angle_loc = glGetUniformLocation(m_program, "angle"); + + static float angle = 0.0f; + angle += 0.02f; + + glClear(GL_COLOR_BUFFER_BIT); + + glUniform1f(angle_loc, angle); + glDrawArrays(GL_TRIANGLES, 0, 3); + + Renderer::GetInstance()->SwapBuffers(m_egl_surface); } void WaylandWindowImpl::handle_frame_callback(void *data, @@ -126,46 +149,26 @@ void WaylandWindowImpl::handle_frame_callback(void *data, return; wl_callback_destroy(cb); - auto frame_callback = wl_surface_frame(window->m_wsurface); - window->m_frame_listener.done = handle_frame_callback; + if (window->m_on_frame) + window->m_on_frame(); - wl_callback_add_listener(frame_callback, &window->m_frame_listener, window); - - if (window->m_on_frame) window->m_on_frame(); - - GLint angle_loc = glGetUniformLocation(window->m_program, "angle"); - - static float angle = 0.0f; - angle += 0.02f; - - glClear(GL_COLOR_BUFFER_BIT); - - glUniform1f(angle_loc, angle); - glDrawArrays(GL_TRIANGLES, 0, 3); - - Renderer::GetInstance()->SwapBuffers(window->m_egl_surface); + window->m_frame_cb_pending = false; } void WaylandWindowImpl::xsurface_handle_configure(void *data, struct xdg_surface *surface, uint32_t serial) { + printf("[DEBUG] xsurface_handle_configure event triggered\n"); + auto window = reinterpret_cast(data); xdg_surface_ack_configure(surface, serial); - auto frame_callback = wl_surface_frame(window->m_wsurface); - printf("frame cb: %p\n", frame_callback); + window->m_running = true; + window->m_redraw_requested = true; - window->m_frame_listener.done = handle_frame_callback; - - int cb_res = wl_callback_add_listener(frame_callback, - &window->m_frame_listener, window); - - printf("mount callback listener: %d\n", cb_res); - - glClear(GL_COLOR_BUFFER_BIT); - Renderer::GetInstance()->SwapBuffers(window->m_egl_surface); + wl_surface_commit(window->m_wsurface); } void WaylandWindowImpl::xtoplevel_handle_configure( @@ -182,6 +185,8 @@ void WaylandWindowImpl::xtoplevel_handle_configure( xdg_surface_set_window_geometry(window->m_xsurface, 0, 0, width, height); window->m_width = width; window->m_height = height; + + window->m_redraw_requested = true; } void WaylandWindowImpl::xtoplevel_handle_close(void *data, @@ -197,27 +202,23 @@ void WaylandWindowImpl::xtoplevel_handle_close(void *data, xdg_toplevel_destroy(window->m_toplevel); xdg_surface_destroy(window->m_xsurface); wl_surface_destroy(window->m_wsurface); - // if (window->m_program) { - // eglMakeCurrent(renderer_display, m_egl_surface, m_egl_surface, - // m_egl_context); glDeleteProgram(m_program); glDeleteBuffers(1, &m_vbo); - // // if used eglMakeCurrent(renderer_display, EGL_NO_SURFACE, - // EGL_NO_SURFACE, EGL_NO_CONTEXT); m_program = 0; - // } Renderer::GetInstance()->DestroyContext(window->m_egl_context); } void WaylandWindowImpl::xtoplevel_handle_configure_bounds( void *data, struct xdg_toplevel *toplevel, int32_t width, int32_t height) { - UNUSED(data); UNUSED(toplevel); printf("[DEBUG] window configure bounds, width = %d, height = %d\n", width, height); + auto window = reinterpret_cast(data); + window->m_redraw_requested = true; } void WaylandWindowImpl::xtoplevel_handle_wm_capabilities( void *data, struct xdg_toplevel *toplevel, struct wl_array *capabilities) { - UNUSED(data); UNUSED(toplevel); UNUSED(capabilities); printf("[DEBUG] window wm_capabilities event received\n"); + auto window = reinterpret_cast(data); + window->m_redraw_requested = true; }