LibGUI: Window now uses double buffering

This allows data in shared memory object be always up to date. With this
change window server can update lazily, and not necessarily on all
invalidate calls
This commit is contained in:
Bananymous 2024-06-27 00:39:59 +03:00
parent f538dd5276
commit 0c645ba867
2 changed files with 21 additions and 18 deletions

View File

@ -1,5 +1,7 @@
#include "LibGUI/Window.h" #include "LibGUI/Window.h"
#include <BAN/ScopeGuard.h>
#include <LibFont/Font.h> #include <LibFont/Font.h>
#include <fcntl.h> #include <fcntl.h>
@ -16,7 +18,7 @@ namespace LibGUI
Window::~Window() Window::~Window()
{ {
munmap(m_framebuffer, m_width * m_height * 4); munmap(m_framebuffer_smo, m_width * m_height * 4);
close(m_server_fd); close(m_server_fd);
} }
@ -25,9 +27,13 @@ namespace LibGUI
if (title.size() >= sizeof(WindowCreatePacket::title)) if (title.size() >= sizeof(WindowCreatePacket::title))
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
BAN::Vector<uint32_t> framebuffer;
TRY(framebuffer.resize(width * height));
int server_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0); int server_fd = socket(AF_UNIX, SOCK_SEQPACKET, 0);
if (server_fd == -1) if (server_fd == -1)
return BAN::Error::from_errno(errno); return BAN::Error::from_errno(errno);
BAN::ScopeGuard server_closer([server_fd] { close(server_fd); });
if (fcntl(server_fd, F_SETFL, fcntl(server_fd, F_GETFL) | O_CLOEXEC) == -1) if (fcntl(server_fd, F_SETFL, fcntl(server_fd, F_GETFL) | O_CLOEXEC) == -1)
return BAN::Error::from_errno(errno); return BAN::Error::from_errno(errno);
@ -46,11 +52,8 @@ namespace LibGUI
timespec current_time; timespec current_time;
clock_gettime(CLOCK_MONOTONIC, &current_time); clock_gettime(CLOCK_MONOTONIC, &current_time);
time_t duration_s = (current_time.tv_sec - start_time.tv_sec) + (current_time.tv_nsec >= start_time.tv_nsec); time_t duration_s = (current_time.tv_sec - start_time.tv_sec) + (current_time.tv_nsec >= start_time.tv_nsec);
if (duration_s > 10) if (duration_s > 1)
{
close(server_fd);
return BAN::Error::from_errno(ETIMEDOUT); return BAN::Error::from_errno(ETIMEDOUT);
}
timespec sleep_time; timespec sleep_time;
sleep_time.tv_sec = 0; sleep_time.tv_sec = 0;
@ -64,28 +67,22 @@ namespace LibGUI
strncpy(packet.title, title.data(), title.size()); strncpy(packet.title, title.data(), title.size());
packet.title[title.size()] = '\0'; packet.title[title.size()] = '\0';
if (send(server_fd, &packet, sizeof(packet), 0) != sizeof(packet)) if (send(server_fd, &packet, sizeof(packet), 0) != sizeof(packet))
{
close(server_fd);
return BAN::Error::from_errno(errno); return BAN::Error::from_errno(errno);
}
WindowCreateResponse response; WindowCreateResponse response;
if (recv(server_fd, &response, sizeof(response), 0) != sizeof(response)) if (recv(server_fd, &response, sizeof(response), 0) != sizeof(response))
{
close(server_fd);
return BAN::Error::from_errno(errno); return BAN::Error::from_errno(errno);
}
void* framebuffer_addr = smo_map(response.framebuffer_smo_key); void* framebuffer_addr = smo_map(response.framebuffer_smo_key);
if (framebuffer_addr == nullptr) if (framebuffer_addr == nullptr)
{
close(server_fd);
return BAN::Error::from_errno(errno); return BAN::Error::from_errno(errno);
}
server_closer.disable();
return TRY(BAN::UniqPtr<Window>::create( return TRY(BAN::UniqPtr<Window>::create(
server_fd, server_fd,
static_cast<uint32_t*>(framebuffer_addr), static_cast<uint32_t*>(framebuffer_addr),
BAN::move(framebuffer),
width, width,
height height
)); ));
@ -143,8 +140,8 @@ namespace LibGUI
uint32_t amount_abs = BAN::Math::abs(amount); uint32_t amount_abs = BAN::Math::abs(amount);
if (amount_abs == 0 || amount_abs >= height()) if (amount_abs == 0 || amount_abs >= height())
return; return;
uint32_t* dst = (amount > 0) ? m_framebuffer + width() * amount_abs : m_framebuffer; uint32_t* dst = (amount > 0) ? m_framebuffer.data() + width() * amount_abs : m_framebuffer.data();
uint32_t* src = (amount < 0) ? m_framebuffer + width() * amount_abs : m_framebuffer; uint32_t* src = (amount < 0) ? m_framebuffer.data() + width() * amount_abs : m_framebuffer.data();
memmove(dst, src, width() * (height() - amount_abs) * 4); memmove(dst, src, width() * (height() - amount_abs) * 4);
} }
@ -172,6 +169,9 @@ namespace LibGUI
if (!clamp_to_framebuffer(x, y, width, height)) if (!clamp_to_framebuffer(x, y, width, height))
return true; return true;
for (uint32_t i = 0; i < height; i++)
memcpy(&m_framebuffer_smo[(y + i) * m_width + x], &m_framebuffer[(y + i) * m_width + x], width * sizeof(uint32_t));
WindowInvalidatePacket packet; WindowInvalidatePacket packet;
packet.x = x; packet.x = x;
packet.y = y; packet.y = y;

View File

@ -136,9 +136,10 @@ namespace LibGUI
int server_fd() const { return m_server_fd; } int server_fd() const { return m_server_fd; }
private: private:
Window(int server_fd, uint32_t* framebuffer, uint32_t width, uint32_t height) Window(int server_fd, uint32_t* framebuffer_smo, BAN::Vector<uint32_t>&& framebuffer, uint32_t width, uint32_t height)
: m_server_fd(server_fd) : m_server_fd(server_fd)
, m_framebuffer(framebuffer) , m_framebuffer(framebuffer)
, m_framebuffer_smo(framebuffer_smo)
, m_width(width) , m_width(width)
, m_height(height) , m_height(height)
{ } { }
@ -147,7 +148,9 @@ namespace LibGUI
private: private:
int m_server_fd; int m_server_fd;
uint32_t* m_framebuffer;
BAN::Vector<uint32_t> m_framebuffer;
uint32_t* m_framebuffer_smo;
uint32_t m_width; uint32_t m_width;
uint32_t m_height; uint32_t m_height;