Compare commits
7 Commits
51bfe4252d
...
36d07065fb
Author | SHA1 | Date |
---|---|---|
Bananymous | 36d07065fb | |
Bananymous | f206e72447 | |
Bananymous | 58e45fb394 | |
Bananymous | 411f32c766 | |
Bananymous | e1b82e4e43 | |
Bananymous | df613775b6 | |
Bananymous | 5e8fdc997a |
|
@ -60,6 +60,7 @@ namespace Kernel
|
|||
static void wait_until_processors_ready();
|
||||
|
||||
static void toggle_should_print_cpu_load() { s_should_print_cpu_load = !s_should_print_cpu_load; }
|
||||
static bool get_should_print_cpu_load() { return s_should_print_cpu_load; }
|
||||
|
||||
static ProcessorID bsb_id() { return s_bsb_id; }
|
||||
static bool current_is_bsb() { return current_id() == bsb_id(); }
|
||||
|
|
|
@ -3,11 +3,14 @@
|
|||
#include <kernel/Device/FramebufferDevice.h>
|
||||
#include <kernel/FS/DevFS/FileSystem.h>
|
||||
#include <kernel/Memory/Heap.h>
|
||||
#include <kernel/Terminal/TerminalDriver.h>
|
||||
|
||||
#include <sys/framebuffer.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/sysmacros.h>
|
||||
|
||||
extern Kernel::TerminalDriver* g_terminal_driver;
|
||||
|
||||
namespace Kernel
|
||||
{
|
||||
|
||||
|
@ -250,16 +253,21 @@ namespace Kernel
|
|||
{
|
||||
if (flags != MS_SYNC)
|
||||
return BAN::Error::from_errno(ENOTSUP);
|
||||
if (vaddr % (BANAN_FB_BPP / 8))
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
if (vaddr < m_vaddr)
|
||||
vaddr = m_vaddr;
|
||||
if (vaddr + size > m_vaddr + m_size)
|
||||
size = (vaddr - m_vaddr) + m_size;
|
||||
if (auto rem = size % (BANAN_FB_BPP / 8))
|
||||
size += (BANAN_FB_BPP / 8) - rem;
|
||||
|
||||
m_framebuffer->sync_pixels_linear(
|
||||
(vaddr - m_vaddr) / (BANAN_FB_BPP / 8),
|
||||
BAN::Math::div_round_up<uint32_t>((vaddr % (BANAN_FB_BPP / 8)) + size, (BANAN_FB_BPP / 8))
|
||||
);
|
||||
const vaddr_t start = BAN::Math::max(vaddr, m_vaddr);
|
||||
const size_t end = BAN::Math::min(vaddr + size, m_vaddr + m_size);
|
||||
if (start < end)
|
||||
{
|
||||
do_msync(
|
||||
(start - m_vaddr) / (BANAN_FB_BPP / 8),
|
||||
(end - start) / (BANAN_FB_BPP / 8)
|
||||
);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
@ -300,6 +308,53 @@ namespace Kernel
|
|||
, m_framebuffer(framebuffer)
|
||||
{ }
|
||||
|
||||
void do_msync(uint32_t first_pixel, uint32_t pixel_count)
|
||||
{
|
||||
if (!Processor::get_should_print_cpu_load())
|
||||
return m_framebuffer->sync_pixels_linear(first_pixel, pixel_count);
|
||||
|
||||
const uint32_t fb_width = m_framebuffer->width();
|
||||
|
||||
const auto& font = g_terminal_driver->font();
|
||||
|
||||
const uint32_t x = first_pixel % fb_width;
|
||||
const uint32_t y = first_pixel / fb_width;
|
||||
|
||||
const uint32_t load_w = 16 * font.width();
|
||||
const uint32_t load_h = Processor::count() * font.height();
|
||||
|
||||
if (y >= load_h || x + pixel_count <= fb_width - load_w)
|
||||
return m_framebuffer->sync_pixels_linear(first_pixel, pixel_count);
|
||||
|
||||
if (x >= fb_width - load_w && x + pixel_count <= fb_width)
|
||||
return;
|
||||
|
||||
if (x < fb_width - load_w)
|
||||
m_framebuffer->sync_pixels_linear(first_pixel, fb_width - load_w - x);
|
||||
|
||||
if (x + pixel_count > fb_width)
|
||||
{
|
||||
const uint32_t past_last_pixel = first_pixel + pixel_count;
|
||||
|
||||
first_pixel = (y + 1) * fb_width;
|
||||
pixel_count = past_last_pixel - first_pixel;
|
||||
|
||||
const uint32_t cpu_load_end = load_h * fb_width;
|
||||
|
||||
while (pixel_count && first_pixel < cpu_load_end)
|
||||
{
|
||||
m_framebuffer->sync_pixels_linear(first_pixel, BAN::Math::min(pixel_count, fb_width - load_w));
|
||||
|
||||
const uint32_t advance = BAN::Math::min(pixel_count, fb_width);
|
||||
pixel_count -= advance;
|
||||
first_pixel += advance;
|
||||
}
|
||||
|
||||
if (pixel_count)
|
||||
m_framebuffer->sync_pixels_linear(first_pixel, pixel_count);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
BAN::RefPtr<FramebufferDevice> m_framebuffer;
|
||||
};
|
||||
|
|
|
@ -179,6 +179,8 @@ namespace Kernel
|
|||
const pid_t tid = Thread::current_tid();
|
||||
const pid_t pid = (tid && Thread::current().has_process()) ? Process::current().pid() : 0;
|
||||
|
||||
const char* process_name = "";
|
||||
|
||||
if (tid)
|
||||
{
|
||||
auto& thread = Thread::current();
|
||||
|
@ -245,15 +247,22 @@ namespace Kernel
|
|||
);
|
||||
}
|
||||
|
||||
if (Thread::current().has_process() && Process::current().is_userspace())
|
||||
{
|
||||
const char* const* argv = Process::current().userspace_info().argv;
|
||||
if (argv && *argv)
|
||||
process_name = *argv;
|
||||
}
|
||||
|
||||
#if ARCH(x86_64)
|
||||
dwarnln(
|
||||
"CPU {}: {} (error code: 0x{8H}), pid {}, tid {}\r\n"
|
||||
"CPU {}: {} (error code: 0x{8H}), pid {}, tid {}: {}\r\n"
|
||||
"Register dump\r\n"
|
||||
"rax=0x{16H}, rbx=0x{16H}, rcx=0x{16H}, rdx=0x{16H}\r\n"
|
||||
"rsp=0x{16H}, rbp=0x{16H}, rdi=0x{16H}, rsi=0x{16H}\r\n"
|
||||
"rip=0x{16H}, rflags=0x{16H}\r\n"
|
||||
"cr0=0x{16H}, cr2=0x{16H}, cr3=0x{16H}, cr4=0x{16H}",
|
||||
Processor::current_id(), isr_exceptions[isr], error, pid, tid,
|
||||
Processor::current_id(), isr_exceptions[isr], error, pid, tid, process_name,
|
||||
regs->rax, regs->rbx, regs->rcx, regs->rdx,
|
||||
interrupt_stack->sp, regs->rbp, regs->rdi, regs->rsi,
|
||||
interrupt_stack->ip, interrupt_stack->flags,
|
||||
|
@ -261,13 +270,13 @@ namespace Kernel
|
|||
);
|
||||
#elif ARCH(i686)
|
||||
dwarnln(
|
||||
"CPU {}: {} (error code: 0x{8H}), pid {}, tid {}\r\n"
|
||||
"CPU {}: {} (error code: 0x{8H}), pid {}, tid {}: {}\r\n"
|
||||
"Register dump\r\n"
|
||||
"eax=0x{8H}, ebx=0x{8H}, ecx=0x{8H}, edx=0x{8H}\r\n"
|
||||
"esp=0x{8H}, ebp=0x{8H}, edi=0x{8H}, esi=0x{8H}\r\n"
|
||||
"eip=0x{8H}, eflags=0x{8H}\r\n"
|
||||
"cr0=0x{8H}, cr2=0x{8H}, cr3=0x{8H}, cr4=0x{8H}",
|
||||
Processor::current_id(), isr_exceptions[isr], error, pid, tid,
|
||||
Processor::current_id(), isr_exceptions[isr], error, pid, tid, process_name,
|
||||
regs->eax, regs->ebx, regs->ecx, regs->edx,
|
||||
interrupt_stack->sp, regs->ebp, regs->edi, regs->esi,
|
||||
interrupt_stack->ip, interrupt_stack->flags,
|
||||
|
|
|
@ -1682,12 +1682,9 @@ namespace Kernel
|
|||
if (flags != MS_SYNC && flags != MS_ASYNC && flags != MS_INVALIDATE)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
vaddr_t vaddr = (vaddr_t)addr;
|
||||
if (vaddr % PAGE_SIZE != 0)
|
||||
return BAN::Error::from_errno(EINVAL);
|
||||
|
||||
LockGuard _(m_process_lock);
|
||||
|
||||
const vaddr_t vaddr = reinterpret_cast<vaddr_t>(addr);
|
||||
for (auto& mapped_region : m_mapped_regions)
|
||||
if (mapped_region->overlaps(vaddr, len))
|
||||
TRY(mapped_region->msync(vaddr, len, flags));
|
||||
|
|
|
@ -80,3 +80,32 @@ struct Circle
|
|||
}
|
||||
|
||||
};
|
||||
|
||||
struct Range
|
||||
{
|
||||
uint32_t start { 0 };
|
||||
uint32_t count { 0 };
|
||||
|
||||
bool is_continuous_with(const Range& range) const
|
||||
{
|
||||
return start <= range.start + range.count && range.start <= start + count;
|
||||
}
|
||||
|
||||
uint32_t distance_between(const Range& range) const
|
||||
{
|
||||
if (is_continuous_with(range))
|
||||
return 0;
|
||||
if (start < range.start)
|
||||
return range.start - (start + count);
|
||||
return start - (range.start + range.count);
|
||||
}
|
||||
|
||||
void merge_with(const Range& range)
|
||||
{
|
||||
const uint32_t new_start = BAN::Math::min(start, range.start);
|
||||
const uint32_t new_end = BAN::Math::max(start + count, range.start + range.count);
|
||||
|
||||
start = new_start;
|
||||
count = new_end - new_start;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -20,7 +20,12 @@ WindowServer::WindowServer(Framebuffer& framebuffer, int32_t corner_radius)
|
|||
, m_cursor({ framebuffer.width / 2, framebuffer.height / 2 })
|
||||
, m_font(MUST(LibFont::Font::load("/usr/share/fonts/lat0-16.psfu"_sv)))
|
||||
{
|
||||
MUST(m_pages_to_sync_bitmap.resize(BAN::Math::div_round_up<size_t>(m_framebuffer.width * m_framebuffer.height * sizeof(uint32_t), 4096 * 8), 0));
|
||||
BAN::Vector<LibImage::Image::Color> bitmap;
|
||||
MUST(bitmap.resize(m_framebuffer.width * m_framebuffer.height, { 0x10, 0x10, 0x10, 0xFF }));
|
||||
m_background_image = MUST(BAN::UniqPtr<LibImage::Image>::create(m_framebuffer.width, m_framebuffer.height, BAN::move(bitmap)));
|
||||
|
||||
MUST(m_pending_syncs.resize(m_framebuffer.height));
|
||||
|
||||
invalidate(m_framebuffer.area());
|
||||
}
|
||||
|
||||
|
@ -535,6 +540,7 @@ void WindowServer::on_mouse_scroll(LibInput::MouseScrollEvent event)
|
|||
|
||||
void WindowServer::set_focused_window(BAN::RefPtr<Window> window)
|
||||
{
|
||||
ASSERT(window->get_attributes().focusable);
|
||||
if (m_focused_window == window)
|
||||
return;
|
||||
|
||||
|
@ -574,6 +580,9 @@ static uint32_t alpha_blend(uint32_t color_a, uint32_t color_b)
|
|||
|
||||
void WindowServer::invalidate(Rectangle area)
|
||||
{
|
||||
ASSERT(m_background_image->width() == (uint64_t)m_framebuffer.width);
|
||||
ASSERT(m_background_image->height() == (uint64_t)m_framebuffer.height);
|
||||
|
||||
const auto get_cursor_pixel =
|
||||
[](int32_t rel_x, int32_t rel_y) -> BAN::Optional<uint32_t>
|
||||
{
|
||||
|
@ -605,11 +614,28 @@ void WindowServer::invalidate(Rectangle area)
|
|||
return;
|
||||
area = focused_overlap.release_value();
|
||||
|
||||
const bool should_alpha_blend = m_focused_window->get_attributes().alpha_channel;
|
||||
|
||||
if (client_area == m_framebuffer.area())
|
||||
{
|
||||
for (int32_t y = area.y; y < area.y + area.height; y++)
|
||||
for (int32_t x = area.x; x < area.x + area.width; x++)
|
||||
m_framebuffer.mmap[y * m_framebuffer.width + x] = m_focused_window->framebuffer()[y * m_focused_window->client_width() + x];
|
||||
if (!should_alpha_blend)
|
||||
{
|
||||
for (int32_t y = area.y; y < area.y + area.height; y++)
|
||||
for (int32_t x = area.x; x < area.x + area.width; x++)
|
||||
m_framebuffer.mmap[y * m_framebuffer.width + x] = m_focused_window->framebuffer()[y * m_focused_window->client_width() + x];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int32_t y = area.y; y < area.y + area.height; y++)
|
||||
{
|
||||
for (int32_t x = area.x; x < area.x + area.width; x++)
|
||||
{
|
||||
const uint32_t src_pixel = m_focused_window->framebuffer()[y * m_focused_window->client_width() + x];
|
||||
const uint32_t bg_pixel = m_background_image->get_color(x, y).as_argb();
|
||||
m_framebuffer.mmap[y * m_framebuffer.width + x] = alpha_blend(src_pixel, bg_pixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
mark_pending_sync(area);
|
||||
}
|
||||
else
|
||||
|
@ -630,7 +656,12 @@ void WindowServer::invalidate(Rectangle area)
|
|||
{
|
||||
const int32_t src_x = BAN::Math::clamp<int32_t>(dst_x * m_focused_window->client_width() / m_framebuffer.width, 0, m_focused_window->client_width());
|
||||
const int32_t src_y = BAN::Math::clamp<int32_t>(dst_y * m_focused_window->client_height() / m_framebuffer.height, 0, m_focused_window->client_height());
|
||||
m_framebuffer.mmap[dst_y * m_framebuffer.width + dst_x] = m_focused_window->framebuffer()[src_y * m_focused_window->client_width() + src_x];
|
||||
|
||||
const uint32_t src_pixel = m_focused_window->framebuffer()[src_y * m_focused_window->client_width() + src_x];
|
||||
const uint32_t bg_pixel = m_background_image->get_color(dst_x, dst_y).as_argb();
|
||||
|
||||
uint32_t& dst_pixel = m_framebuffer.mmap[dst_y * m_framebuffer.width + dst_x];
|
||||
dst_pixel = should_alpha_blend ? alpha_blend(src_pixel, bg_pixel) : src_pixel;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -682,20 +713,9 @@ void WindowServer::invalidate(Rectangle area)
|
|||
return;
|
||||
area = fb_overlap.release_value();
|
||||
|
||||
if (m_background_image)
|
||||
{
|
||||
ASSERT(m_background_image->width() == (uint64_t)m_framebuffer.width);
|
||||
ASSERT(m_background_image->height() == (uint64_t)m_framebuffer.height);
|
||||
for (int32_t y = area.y; y < area.y + area.height; y++)
|
||||
for (int32_t x = area.x; x < area.x + area.width; x++)
|
||||
m_framebuffer.mmap[y * m_framebuffer.width + x] = m_background_image->get_color(x, y).as_argb();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int32_t y = area.y; y < area.y + area.height; y++)
|
||||
for (int32_t x = area.x; x < area.x + area.width; x++)
|
||||
m_framebuffer.mmap[y * m_framebuffer.width + x] = 0xFF101010;
|
||||
}
|
||||
for (int32_t y = area.y; y < area.y + area.height; y++)
|
||||
for (int32_t x = area.x; x < area.x + area.width; x++)
|
||||
m_framebuffer.mmap[y * m_framebuffer.width + x] = m_background_image->get_color(x, y).as_argb();
|
||||
|
||||
// FIXME: this loop should be inverse order and terminate
|
||||
// after window without alpha channel is found
|
||||
|
@ -892,24 +912,71 @@ void WindowServer::invalidate(Rectangle area)
|
|||
mark_pending_sync(area);
|
||||
}
|
||||
|
||||
void WindowServer::mark_pending_sync(Rectangle area)
|
||||
void WindowServer::RangeList::add_range(const Range& range)
|
||||
{
|
||||
// FIXME: this marks too many pages
|
||||
|
||||
const uintptr_t mmap_start = reinterpret_cast<uintptr_t>(m_framebuffer.mmap) + area.y * m_framebuffer.width * 4;
|
||||
const uintptr_t mmap_end = mmap_start + (area.height + 1) * m_framebuffer.width * 4;
|
||||
|
||||
uintptr_t mmap_addr = mmap_start & ~(uintptr_t)0xFFF;
|
||||
while (mmap_addr < mmap_end)
|
||||
if (range_count == 0)
|
||||
{
|
||||
size_t index = (mmap_addr - reinterpret_cast<uintptr_t>(m_framebuffer.mmap)) / 4096;
|
||||
size_t byte = index / 8;
|
||||
size_t bit = index % 8;
|
||||
//dprintln("{}/{}", byte, m_pages_to_sync_bitmap.size());
|
||||
if (byte < m_pages_to_sync_bitmap.size())
|
||||
m_pages_to_sync_bitmap[byte] |= 1 << bit;
|
||||
mmap_addr += 4096;
|
||||
ranges[0] = range;
|
||||
range_count++;
|
||||
return;
|
||||
}
|
||||
|
||||
size_t min_distance_value = SIZE_MAX;
|
||||
size_t min_distance_index = 0;
|
||||
for (size_t i = 0; i < range_count; i++)
|
||||
{
|
||||
if (ranges[i].is_continuous_with(range))
|
||||
{
|
||||
ranges[i].merge_with(range);
|
||||
|
||||
size_t last_continuous = i;
|
||||
for (size_t j = i + 1; j < range_count; j++)
|
||||
{
|
||||
if (!ranges[i].is_continuous_with(ranges[j]))
|
||||
break;
|
||||
last_continuous = j;
|
||||
}
|
||||
|
||||
if (last_continuous != i)
|
||||
{
|
||||
ranges[i].merge_with(ranges[last_continuous]);
|
||||
for (size_t j = 1; last_continuous + j < range_count; j++)
|
||||
ranges[i + j] = ranges[last_continuous + j];
|
||||
range_count -= last_continuous - i;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const auto distance = ranges[i].distance_between(range);
|
||||
if (distance < min_distance_value)
|
||||
{
|
||||
min_distance_value = distance;
|
||||
min_distance_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (range_count >= ranges.size())
|
||||
{
|
||||
ranges[min_distance_index].merge_with(range);
|
||||
return;
|
||||
}
|
||||
|
||||
size_t insert_idx = 0;
|
||||
for (; insert_idx < range_count; insert_idx++)
|
||||
if (range.start < ranges[insert_idx].start)
|
||||
break;
|
||||
for (size_t i = range_count; i > insert_idx; i--)
|
||||
ranges[i] = ranges[i - 1];
|
||||
ranges[insert_idx] = range;
|
||||
range_count++;
|
||||
}
|
||||
|
||||
void WindowServer::mark_pending_sync(Rectangle to_sync)
|
||||
{
|
||||
ASSERT(to_sync == to_sync.get_overlap(m_framebuffer.area()).value());
|
||||
for (int32_t y_off = 0; y_off < to_sync.height; y_off++)
|
||||
m_pending_syncs[to_sync.y + y_off].add_range({ static_cast<uint32_t>(to_sync.x), static_cast<uint32_t>(to_sync.width) });
|
||||
}
|
||||
|
||||
void WindowServer::sync()
|
||||
|
@ -933,33 +1000,44 @@ void WindowServer::sync()
|
|||
dir_y = -dir_y;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < m_pages_to_sync_bitmap.size() * 8; i++)
|
||||
size_t range_start = 0;
|
||||
size_t range_count = 0;
|
||||
for (int32_t y = 0; y < m_framebuffer.height; y++)
|
||||
{
|
||||
size_t byte = i / 8;
|
||||
size_t bit = i % 8;
|
||||
if (!(m_pages_to_sync_bitmap[byte] & (1 << bit)))
|
||||
continue;
|
||||
auto& range_list = m_pending_syncs[y];
|
||||
|
||||
size_t len = 1;
|
||||
while (i + len < m_pages_to_sync_bitmap.size() * 8)
|
||||
for (size_t i = 0; i < range_list.range_count; i++)
|
||||
{
|
||||
size_t byte = (i + len) / 8;
|
||||
size_t bit = (i + len) % 8;
|
||||
if (!(m_pages_to_sync_bitmap[byte] & (1 << bit)))
|
||||
break;
|
||||
len++;
|
||||
const size_t cur_start = y * m_framebuffer.width + range_list.ranges[i].start;
|
||||
const size_t cur_count = range_list.ranges[i].count;
|
||||
|
||||
if (range_count == 0)
|
||||
{
|
||||
range_start = cur_start;
|
||||
range_count = cur_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
const size_t distance = cur_start - (range_start + range_count);
|
||||
|
||||
// combine nearby ranges to reduce msync calls
|
||||
// NOTE: value of 128 is an arbitary constant that *just* felt nice
|
||||
if (distance <= 128)
|
||||
range_count = (cur_start + cur_count) - range_start;
|
||||
else
|
||||
{
|
||||
msync(m_framebuffer.mmap + range_start, range_count * 4, MS_SYNC);
|
||||
range_start = cur_start;
|
||||
range_count = cur_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
msync(
|
||||
reinterpret_cast<uint8_t*>(m_framebuffer.mmap) + i * 4096,
|
||||
len * 4096,
|
||||
MS_SYNC
|
||||
);
|
||||
|
||||
i += len;
|
||||
range_list.range_count = 0;
|
||||
}
|
||||
|
||||
memset(m_pages_to_sync_bitmap.data(), 0, m_pages_to_sync_bitmap.size());
|
||||
if (range_count)
|
||||
msync(m_framebuffer.mmap + range_start, range_count * 4, MS_SYNC);
|
||||
}
|
||||
|
||||
Rectangle WindowServer::cursor_area() const
|
||||
|
@ -1002,8 +1080,14 @@ void WindowServer::remove_client_fd(int fd)
|
|||
if (window == m_focused_window)
|
||||
{
|
||||
m_focused_window = nullptr;
|
||||
if (!m_client_windows.empty())
|
||||
set_focused_window(m_client_windows.back());
|
||||
for (size_t j = m_client_windows.size(); j > 0; j--)
|
||||
{
|
||||
auto& client_window = m_client_windows[j - 1];
|
||||
if (!client_window->get_attributes().focusable)
|
||||
continue;
|
||||
set_focused_window(client_window);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "Framebuffer.h"
|
||||
#include "Window.h"
|
||||
|
||||
#include <BAN/Array.h>
|
||||
#include <BAN/Function.h>
|
||||
#include <BAN/Iteration.h>
|
||||
#include <BAN/Vector.h>
|
||||
|
@ -59,6 +60,14 @@ public:
|
|||
private:
|
||||
void mark_pending_sync(Rectangle area);
|
||||
|
||||
private:
|
||||
struct RangeList
|
||||
{
|
||||
size_t range_count { 0 };
|
||||
BAN::Array<Range, 32> ranges;
|
||||
void add_range(const Range& range);
|
||||
};
|
||||
|
||||
private:
|
||||
Framebuffer& m_framebuffer;
|
||||
BAN::Vector<BAN::RefPtr<Window>> m_client_windows;
|
||||
|
@ -67,7 +76,7 @@ private:
|
|||
|
||||
const int32_t m_corner_radius;
|
||||
|
||||
BAN::Vector<uint8_t> m_pages_to_sync_bitmap;
|
||||
BAN::Vector<RangeList> m_pending_syncs;
|
||||
|
||||
BAN::UniqPtr<LibImage::Image> m_background_image;
|
||||
|
||||
|
|
|
@ -198,19 +198,23 @@ int main()
|
|||
if (auto ret = window_server.set_background_image(BAN::move(config.background_image)); ret.is_error())
|
||||
dwarnln("Could not set background image: {}", ret.error());
|
||||
|
||||
const auto get_current_us =
|
||||
[]() -> uint64_t
|
||||
{
|
||||
timespec current_ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, ¤t_ts);
|
||||
return (current_ts.tv_sec * 1'000'000) + (current_ts.tv_nsec / 1'000);
|
||||
};
|
||||
|
||||
constexpr uint64_t sync_interval_us = 1'000'000 / 60;
|
||||
timespec last_sync { .tv_sec = 0, .tv_nsec = 0 };
|
||||
uint64_t last_sync_us = 0;
|
||||
while (!window_server.is_stopped())
|
||||
{
|
||||
timespec current_ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, ¤t_ts);
|
||||
|
||||
uint64_t us_since_last_sync = (current_ts.tv_sec - last_sync.tv_sec) * 1'000'000 + (current_ts.tv_nsec - last_sync.tv_nsec) / 1000;
|
||||
if (us_since_last_sync > sync_interval_us)
|
||||
const auto current_us = get_current_us();
|
||||
if (current_us - last_sync_us > sync_interval_us)
|
||||
{
|
||||
window_server.sync();
|
||||
us_since_last_sync = 0;
|
||||
last_sync = current_ts;
|
||||
last_sync_us += sync_interval_us;
|
||||
}
|
||||
|
||||
int max_fd = server_fd;
|
||||
|
@ -230,10 +234,10 @@ int main()
|
|||
}
|
||||
max_fd = BAN::Math::max(max_fd, window_server.get_client_fds(fds));
|
||||
|
||||
timeval select_timeout {
|
||||
.tv_sec = 0,
|
||||
.tv_usec = static_cast<long>(sync_interval_us - us_since_last_sync)
|
||||
};
|
||||
timeval select_timeout {};
|
||||
if (auto current_us = get_current_us(); current_us - last_sync_us < sync_interval_us)
|
||||
select_timeout.tv_usec = sync_interval_us - (current_us - last_sync_us);
|
||||
|
||||
int nselect = select(max_fd + 1, &fds, nullptr, nullptr, &select_timeout);
|
||||
if (nselect == 0)
|
||||
continue;
|
||||
|
|
Loading…
Reference in New Issue