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