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

View File

@ -136,9 +136,10 @@ namespace LibGUI
int server_fd() const { return m_server_fd; }
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_framebuffer(framebuffer)
, m_framebuffer_smo(framebuffer_smo)
, m_width(width)
, m_height(height)
{ }
@ -147,7 +148,9 @@ namespace LibGUI
private:
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_height;