From e795ab880cc8c63504a6e1085af79d8100a2f052 Mon Sep 17 00:00:00 2001 From: Jorijn van der Graaf Date: Sun, 16 Nov 2025 20:42:48 +0100 Subject: [PATCH] commit --- examples/HelloDrawing/README.md | 4 +- examples/HelloDrawing/main.cpp | 8 +-- .../Crafter.Graphics-WindowWayland.cpp | 36 +++++++++++- .../Crafter.Graphics-WindowWaylandWayland.cpp | 56 ++++++++++++++----- .../Crafter.Graphics-WindowWayland.cppm | 6 +- ...Crafter.Graphics-WindowWaylandWayland.cppm | 3 +- 6 files changed, 89 insertions(+), 24 deletions(-) diff --git a/examples/HelloDrawing/README.md b/examples/HelloDrawing/README.md index c900a60..3cc3977 100644 --- a/examples/HelloDrawing/README.md +++ b/examples/HelloDrawing/README.md @@ -11,8 +11,8 @@ A window with a red colored square. ## Highlighted Code Snippet ```cpp -for(uint32_t x = 0; x < 1280; x++) { - for(uint32_t y = 0; y < 720; y++) { +for(std::uint_fast32_t x = 0; x < 1280; x++) { + for(std::uint_fast32_t y = 0; y < 720; y++) { window.framebuffer[x*720+y].r = 255; window.framebuffer[x*720+y].g = 0; window.framebuffer[x*720+y].b = 0; diff --git a/examples/HelloDrawing/main.cpp b/examples/HelloDrawing/main.cpp index 1b8a58c..b7113f4 100644 --- a/examples/HelloDrawing/main.cpp +++ b/examples/HelloDrawing/main.cpp @@ -5,8 +5,8 @@ using namespace Crafter; int main() { WindowWaylandWayland window("HelloWindow", 1280, 720); - for(uint32_t x = 0; x < 1280; x++) { - for(uint32_t y = 0; y < 720; y++) { + for(std::uint_fast32_t x = 0; x < 1280; x++) { + for(std::uint_fast32_t y = 0; y < 720; y++) { window.framebuffer[x*720+y].r = 255; window.framebuffer[x*720+y].g = 0; window.framebuffer[x*720+y].b = 0; @@ -15,8 +15,8 @@ int main() { } //Semi transparant version: - // for(uint32_t x = 0; x < 1280; x++) { - // for(uint32_t y = 0; y < 720; y++) { + // for(std::uint_fast32_t x = 0; x < 1280; x++) { + // for(std::uint_fast32_t = 0; y < 720; y++) { // window.framebuffer[x*720+y].r = 128;//alpha channel must be premultiplied // window.framebuffer[x*720+y].g = 0; // window.framebuffer[x*720+y].b = 0; diff --git a/implementations/Crafter.Graphics-WindowWayland.cpp b/implementations/Crafter.Graphics-WindowWayland.cpp index 4de54da..5d89b01 100644 --- a/implementations/Crafter.Graphics-WindowWayland.cpp +++ b/implementations/Crafter.Graphics-WindowWayland.cpp @@ -55,6 +55,34 @@ xdg_wm_base_listener xdgWmBaseListener = { .ping = xdg_wm_base_handle_ping, }; +void WindowWayland::wl_surface_frame_done(void *data, struct wl_callback *cb, uint32_t time) +{ + /* Destroy this callback */ + wl_callback_destroy(cb); + + /* Request another frame */ + struct client_state *state = data; + cb = wl_surface_frame(state->wl_surface); + wl_callback_add_listener(cb, &wl_surface_frame_listener, state); + + /* Update scroll amount at 24 pixels per second */ + if (state->last_frame != 0) { + int elapsed = time - state->last_frame; + state->offset += elapsed / 1000.0 * 24; + } + + /* Submit a frame for this event */ + struct wl_buffer *buffer = draw_frame(state); + wl_surface_attach(state->wl_surface, buffer, 0, 0); + wl_surface_damage_buffer(state->wl_surface, 0, 0, INT32_MAX, INT32_MAX); + wl_surface_commit(state->wl_surface); + + state->last_frame = time; +} + +wl_callback_listener WindowWayland::surface_frame_listener = { + .done = wl_surface_frame_done, +}; void WindowWayland::pointer_handle_button(void* data, wl_pointer* pointer, std::uint32_t serial, std::uint32_t time, std::uint32_t button, std::uint32_t state) { WindowWayland* window = reinterpret_cast(data); @@ -333,12 +361,15 @@ WindowWayland::WindowWayland(std::string name, std::uint32_t width, std::uint32_ surface = wl_compositor_create_surface(compositor); xdgSurface = xdg_wm_base_get_xdg_surface(xdgWmBase, surface); xdgToplevel = xdg_surface_get_toplevel(xdgSurface); + cb = wl_surface_frame(surface); - ++ wl_callback_add_listener(cb, &wl_surface_frame_listener, this); xdg_surface_add_listener(xdgSurface, &xdg_surface_listener, this); xdg_toplevel_add_listener(xdgToplevel, &xdg_toplevel_listener, this); wl_surface_commit(surface); + xdg_toplevel_set_title(xdg_toplevel, name.c_str()); + while (wl_display_dispatch(display) != -1 && !configured) { // This space intentionally left blank } @@ -353,5 +384,6 @@ WindowWayland::~WindowWayland() { xdg_toplevel_destroy(xdgToplevel); xdg_surface_destroy(xdgSurface); wl_surface_destroy(surface); - wl_buffer_destroy(buffer); + wl_buffer_destroy(frontBuffer); + wl_buffer_destroy(backBuffer); } \ No newline at end of file diff --git a/implementations/Crafter.Graphics-WindowWaylandWayland.cpp b/implementations/Crafter.Graphics-WindowWaylandWayland.cpp index 92441e0..9b16501 100644 --- a/implementations/Crafter.Graphics-WindowWaylandWayland.cpp +++ b/implementations/Crafter.Graphics-WindowWaylandWayland.cpp @@ -121,26 +121,32 @@ WindowWaylandWayland::WindowWaylandWayland(std::string name, std::uint32_t width } // Map the shared memory file - framebuffer = reinterpret_cast(mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); - if (framebuffer == MAP_FAILED) { + frontFramebuffer = reinterpret_cast(mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); + if (frontFramebuffer == MAP_FAILED) { + fprintf(stderr, "mmap failed: %m\n"); + close(fd); + } + backFramebuffer = reinterpret_cast(mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); + if (backFramebuffer == MAP_FAILED) { fprintf(stderr, "mmap failed: %m\n"); close(fd); } // Create a wl_buffer from our shared memory file descriptor wl_shm_pool *pool = wl_shm_create_pool(shm, fd, size); - buffer = wl_shm_pool_create_buffer(pool, 0, width, height, stride, WL_SHM_FORMAT_ARGB8888); + frontBuffer = wl_shm_pool_create_buffer(pool, 0, width, height, stride, WL_SHM_FORMAT_ARGB8888); + backBuffer = wl_shm_pool_create_buffer(pool, 0, width, height, stride, WL_SHM_FORMAT_ARGB8888); wl_shm_pool_destroy(pool); // Now that we've mapped the file and created the wl_buffer, we no longer // need to keep file descriptor opened close(fd); - if (buffer == NULL) { + if (frontBuffer == NULL || backBuffer == NULL) { exit(EXIT_FAILURE); } - wl_surface_attach(surface, buffer, 0, 0); + wl_surface_attach(surface, frontBuffer, 0, 0); wl_surface_commit(surface); } @@ -155,20 +161,42 @@ void WindowWaylandWayland::StartAsync() { void WindowWaylandWayland::StartSync() { while (open && wl_display_dispatch(display) != -1) { - wl_surface_attach(surface, buffer, 0, 0); - for(const UiElement& element : elements) { - ScaleData data = ScaleElement(element); + std::vector drawOrder; + drawOrder.reserve(elements.size()); + for (UiElement& e : elements) drawOrder.push_back(&e); + std::sort(drawOrder.begin(), drawOrder.end(), [](UiElement* a, UiElement* b){ return a->z < b->z; }); + + for(const UiElement* element : drawOrder) { + std::cout << element->bufferWidth << std::endl; + ScaleData data = ScaleElement(*element); std::vector scaled(data.width*data.height); - ScaleBitmapR8G8B8(scaled.data(), element.buffer.data(), element.bufferWidth, element.bufferHeight, data.width, data.height); - for(std::int32_t x = data.x; x-data.x < data.width; x++) { - for(std::int32_t y = data.y; y-data.y < data.height; y++) { - if(x > 0 && x < width && y > 0 && y < height) { - framebuffer[y*width+x] = scaled[(y-data.y)*data.width+(x-data.x)]; + ScaleBitmapR8G8B8(scaled.data(), element->buffer.data(), element->bufferWidth, element->bufferHeight, data.width, data.height); + for (std::int32_t x = data.x; x - data.x < data.width; x++) { + for (std::int32_t y = data.y; y - data.y < data.height; y++) { + if (x >= 0 && x < width && y >= 0 && y < height) { + Pixel_BU8_GU8_RU8_AU8& dst = backFramebuffer[y * width + x]; + const Pixel_BU8_GU8_RU8_AU8& src = scaled[(y - data.y) * data.width + (x - data.x)]; + + float srcA = src.a / 255.0f; + float dstA = dst.a / 255.0f; + + float outA = srcA + dstA * (1.0f - srcA); + if (outA > 0.0f) { + dst.r = static_cast((src.r * srcA + dst.r * dstA * (1.0f - srcA)) / outA); + dst.g = static_cast((src.g * srcA + dst.g * dstA * (1.0f - srcA)) / outA); + dst.b = static_cast((src.b * srcA + dst.b * dstA * (1.0f - srcA)) / outA); + dst.a = static_cast(outA * 255); + } } } } - wl_surface_damage(surface, data.x, data.y, data.width, data.height); } + + wl_surface_attach(surface, backBuffer, 0, 0); + wl_surface_damage(surface, 0, 0, width, height); wl_surface_commit(surface); + + std::swap(frontFramebuffer, backFramebuffer); + std::swap(frontBuffer, backBuffer); } } \ No newline at end of file diff --git a/interfaces/Crafter.Graphics-WindowWayland.cppm b/interfaces/Crafter.Graphics-WindowWayland.cppm index ad7b0c2..70fbf05 100644 --- a/interfaces/Crafter.Graphics-WindowWayland.cppm +++ b/interfaces/Crafter.Graphics-WindowWayland.cppm @@ -62,9 +62,11 @@ export namespace Crafter { xdg_wm_base* xdgWmBase = NULL; zxdg_decoration_manager_v1* manager = NULL; wl_surface* surface = NULL; - wl_buffer* buffer = NULL; + wl_buffer* frontBuffer = NULL; + wl_buffer* backBuffer = NULL; xdg_surface* xdgSurface = NULL; wl_display* display = NULL; + wl_callback* cb = nullptr; inline static wl_compositor* compositor = NULL; static wl_pointer_listener pointer_listener; static wl_keyboard_listener keyboard_listener; @@ -72,6 +74,8 @@ export namespace Crafter { static wl_registry_listener registry_listener; static xdg_surface_listener xdg_surface_listener; static xdg_toplevel_listener xdg_toplevel_listener; + static wl_callback_listener surface_frame_listener; + static void wl_surface_frame_done(void *data, wl_callback *cb, uint32_t time); static void PointerListenerHandleMotion(void* data, wl_pointer* wl_pointer, uint time, wl_fixed_t surface_x, wl_fixed_t surface_y); static void PointerListenerHandleAxis(void*, wl_pointer*, std::uint32_t, std::uint32_t, wl_fixed_t value); static void PointerListenerHandleEnter(void* data, wl_pointer* wl_pointer, uint serial, wl_surface* surface, wl_fixed_t surface_x, wl_fixed_t surface_y); diff --git a/interfaces/Crafter.Graphics-WindowWaylandWayland.cppm b/interfaces/Crafter.Graphics-WindowWaylandWayland.cppm index 8316455..d43e111 100644 --- a/interfaces/Crafter.Graphics-WindowWaylandWayland.cppm +++ b/interfaces/Crafter.Graphics-WindowWaylandWayland.cppm @@ -34,7 +34,8 @@ export namespace Crafter { /** * @brief Framebuffer for the window using the BGRA 8-bit unsigned pixel format, use this for direct drawing to the window. */ - Pixel_BU8_GU8_RU8_AU8* framebuffer = nullptr; + Pixel_BU8_GU8_RU8_AU8* frontFramebuffer = nullptr; + Pixel_BU8_GU8_RU8_AU8* backFramebuffer = nullptr; /** * @brief Constructs a new WindowWaylandWayland object. *