From 3fb903d991fde0dc8a43f8670cea8ac097f49299 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Mon, 6 Apr 2026 18:07:39 +0300 Subject: [PATCH] LibGUI: Optimize invalidate and set alpha channel If the window does not have an alpha channel, we now set every pixel's alpha to 0xFF. This is needed by the WindowServer when it does alpha blending, there used to be some weird stuff happening on overlapping windows. Also when we are invalidating a region with width of the whole window, we can do a single memcpy instead of a memcpy for each row separately. --- userspace/libraries/LibGUI/Window.cpp | 40 +++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/userspace/libraries/LibGUI/Window.cpp b/userspace/libraries/LibGUI/Window.cpp index 5357ab7e..b77c10ed 100644 --- a/userspace/libraries/LibGUI/Window.cpp +++ b/userspace/libraries/LibGUI/Window.cpp @@ -11,6 +11,8 @@ #include #include +#include + namespace LibGUI { @@ -137,13 +139,47 @@ namespace LibGUI return {}; } + static void* copy_pixels_and_set_max_alpha(void* dst, const void* src, size_t bytes) + { + size_t pixels = bytes / sizeof(uint32_t); + + __m128i* dst128 = static_cast< __m128i*>(dst); + const __m128i* src128 = static_cast(src); + const __m128i alpha_mask = _mm_set1_epi32(0xFF000000); + for (; pixels >= 4; pixels -= 4) + _mm_storeu_si128(dst128++, _mm_or_si128(_mm_loadu_si128(src128++), alpha_mask)); + + uint32_t* dst32 = reinterpret_cast< uint32_t*>(dst128); + const uint32_t* src32 = reinterpret_cast(src128); + for (; pixels; pixels--) + *dst32++ = *src32++ | 0xFF000000; + + return nullptr; + } + void Window::invalidate(int32_t x, int32_t y, uint32_t width, uint32_t height) { if (!m_texture.clamp_to_texture(x, y, width, height)) return; - for (uint32_t i = 0; i < height; i++) - memcpy(&m_framebuffer_smo[(y + i) * m_width + x], &m_texture.pixels()[(y + i) * m_width + x], width * sizeof(uint32_t)); + const auto copy_func = m_attributes.alpha_channel ? memcpy : copy_pixels_and_set_max_alpha; + + if (width == m_width) + { + copy_func( + &m_framebuffer_smo[y * m_width], + &m_texture.pixels()[y * m_width], + width * height * sizeof(uint32_t) + ); + } + else for (uint32_t y_off = 0; y_off < height; y_off++) + { + copy_func( + &m_framebuffer_smo[(y + y_off) * m_width + x], + &m_texture.pixels()[(y + y_off) * m_width + x], + width * sizeof(uint32_t) + ); + } WindowPacket::WindowInvalidate packet; packet.x = x;