diff --git a/Kernel/MemoryManager.cpp b/Kernel/MemoryManager.cpp index a5b63b4388..5443b1acc5 100644 --- a/Kernel/MemoryManager.cpp +++ b/Kernel/MemoryManager.cpp @@ -42,7 +42,7 @@ MemoryManager::~MemoryManager() PageDirectory::PageDirectory(PhysicalAddress paddr) { - m_directory_page = adopt(*new PhysicalPage(paddr, true)); + m_directory_page = PhysicalPage::create_eternal(paddr, true); } PageDirectory::PageDirectory() @@ -87,11 +87,11 @@ void MemoryManager::initialize_paging() // 3 MB -> 4 MB Supervisor physical pages (available for allocation!) // 4 MB -> (max) MB Userspace physical pages (available for allocation!) for (size_t i = (2 * MB); i < (4 * MB); i += PAGE_SIZE) - m_free_supervisor_physical_pages.append(adopt(*new PhysicalPage(PhysicalAddress(i), true))); + m_free_supervisor_physical_pages.append(PhysicalPage::create_eternal(PhysicalAddress(i), true)); dbgprintf("MM: 4MB-%uMB available for allocation\n", m_ram_size / 1048576); for (size_t i = (4 * MB); i < m_ram_size; i += PAGE_SIZE) - m_free_physical_pages.append(adopt(*new PhysicalPage(PhysicalAddress(i), false))); + m_free_physical_pages.append(PhysicalPage::create_eternal(PhysicalAddress(i), false)); m_quickmap_addr = LinearAddress((1 * MB) - PAGE_SIZE); #ifdef MM_DEBUG dbgprintf("MM: Quickmap will use P%x\n", m_quickmap_addr.get()); @@ -650,8 +650,23 @@ Region::~Region() MM.unregister_region(*this); } -PhysicalPage::PhysicalPage(PhysicalAddress paddr, bool supervisor) - : m_supervisor(supervisor) +RetainPtr PhysicalPage::create_eternal(PhysicalAddress paddr, bool supervisor) +{ + void* slot = kmalloc_eternal(sizeof(PhysicalPage)); + new (slot) PhysicalPage(paddr, supervisor); + return adopt(*(PhysicalPage*)slot); +} + +RetainPtr PhysicalPage::create(PhysicalAddress paddr, bool supervisor) +{ + void* slot = kmalloc(sizeof(PhysicalPage)); + new (slot) PhysicalPage(paddr, supervisor, false); + return adopt(*(PhysicalPage*)slot); +} + +PhysicalPage::PhysicalPage(PhysicalAddress paddr, bool supervisor, bool may_return_to_freelist) + : m_may_return_to_freelist(may_return_to_freelist) + , m_supervisor(supervisor) , m_paddr(paddr) { } @@ -724,7 +739,7 @@ VMObject::VMObject(PhysicalAddress paddr, size_t size) { MM.register_vmo(*this); for (size_t i = 0; i < size; i += PAGE_SIZE) { - m_physical_pages.append(adopt(*new PhysicalPage(paddr.offset(i), false))); + m_physical_pages.append(PhysicalPage::create(paddr.offset(i), false)); } ASSERT(m_physical_pages.size() == page_count()); } diff --git a/Kernel/MemoryManager.h b/Kernel/MemoryManager.h index 289baf0675..ccdcf0b6ad 100644 --- a/Kernel/MemoryManager.h +++ b/Kernel/MemoryManager.h @@ -25,7 +25,6 @@ enum class PageFaultResponse { }; class PhysicalPage { - AK_MAKE_ETERNAL friend class MemoryManager; friend class PageDirectory; friend class VMObject; @@ -41,19 +40,27 @@ public: void release() { ASSERT(m_retain_count); - if (!--m_retain_count) - return_to_freelist(); + if (!--m_retain_count) { + if (m_may_return_to_freelist) + return_to_freelist(); + else + delete this; + } } + static RetainPtr create_eternal(PhysicalAddress, bool supervisor); + static RetainPtr create(PhysicalAddress, bool supervisor); + unsigned short retain_count() const { return m_retain_count; } private: - PhysicalPage(PhysicalAddress paddr, bool supervisor); - ~PhysicalPage() = delete; + PhysicalPage(PhysicalAddress paddr, bool supervisor, bool may_return_to_freelist = true); + ~PhysicalPage() { } void return_to_freelist(); unsigned short m_retain_count { 1 }; + bool m_may_return_to_freelist { true }; bool m_supervisor { false }; PhysicalAddress m_paddr; }; diff --git a/Kernel/kmalloc.cpp b/Kernel/kmalloc.cpp index 2447914459..6e564619e0 100644 --- a/Kernel/kmalloc.cpp +++ b/Kernel/kmalloc.cpp @@ -101,7 +101,7 @@ void* kmalloc_impl(dword size) real_size = size + sizeof(allocation_t); if (sum_free < real_size) { - kprintf("%s<%u> kmalloc(): PANIC! Out of memory (sucks, dude)\nsum_free=%u, real_size=%x\n", current->name().characters(), current->pid(), sum_free, real_size); + kprintf("%s<%u> kmalloc(): PANIC! Out of memory (sucks, dude)\nsum_free=%u, real_size=%u\n", current->name().characters(), current->pid(), sum_free, real_size); hang(); } diff --git a/LibC/stdlib.cpp b/LibC/stdlib.cpp index 4adaa0ee81..2b03f9e59b 100644 --- a/LibC/stdlib.cpp +++ b/LibC/stdlib.cpp @@ -50,7 +50,7 @@ void* malloc(size_t size) size_t real_size = size + sizeof(MallocHeader) + sizeof(MallocFooter); if (s_malloc_sum_free < real_size) { - fprintf(stderr, "malloc(): Out of memory\ns_malloc_sum_free=%u, real_size=%x\n", s_malloc_sum_free, real_size); + fprintf(stderr, "malloc(): Out of memory\ns_malloc_sum_free=%u, real_size=%u\n", s_malloc_sum_free, real_size); assert(false); } diff --git a/WindowServer/WSScreen.cpp b/WindowServer/WSScreen.cpp index dbeeeca6b3..e21a227054 100644 --- a/WindowServer/WSScreen.cpp +++ b/WindowServer/WSScreen.cpp @@ -21,12 +21,19 @@ WSScreen::WSScreen(unsigned width, unsigned height) { ASSERT(!s_the); s_the = this; - m_cursor_location = rect().center(); - m_framebuffer_fd = open("/dev/bxvga", O_RDWR); ASSERT(m_framebuffer_fd >= 0); + set_resolution(width, height); +} + +WSScreen::~WSScreen() +{ +} + +void WSScreen::set_resolution(int width, int height) +{ struct BXVGAResolution { int width; int height; @@ -35,13 +42,20 @@ WSScreen::WSScreen(unsigned width, unsigned height) int rc = ioctl(m_framebuffer_fd, 1985, (int)&resolution); ASSERT(rc == 0); - size_t framebuffer_size_in_bytes = resolution.width * resolution.height * sizeof(RGBA32) * 2; + if (m_framebuffer) { + size_t previous_size_in_bytes = m_width * m_height * sizeof(RGBA32) * 2; + int rc = munmap(m_framebuffer, previous_size_in_bytes); + ASSERT(rc == 0); + } + + size_t framebuffer_size_in_bytes = width * height * sizeof(RGBA32) * 2; m_framebuffer = (RGBA32*)mmap(nullptr, framebuffer_size_in_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, m_framebuffer_fd, 0); ASSERT(m_framebuffer && m_framebuffer != (void*)-1); -} -WSScreen::~WSScreen() -{ + m_width = width; + m_height = height; + + m_cursor_location.constrain(rect()); } void WSScreen::on_receive_mouse_data(int dx, int dy, bool left_button, bool right_button) diff --git a/WindowServer/WSWindowManager.cpp b/WindowServer/WSWindowManager.cpp index 6d239a0fc2..bb52b0f15c 100644 --- a/WindowServer/WSWindowManager.cpp +++ b/WindowServer/WSWindowManager.cpp @@ -187,12 +187,12 @@ WSWindowManager::WSWindowManager() m_system_menu = make(nullptr, -1, String((const char*)system_menu_name)); m_system_menu->add_item(make(0, "Launch Terminal")); m_system_menu->add_item(make(WSMenuItem::Separator)); - m_system_menu->add_item(make(1, "Hello again")); - m_system_menu->add_item(make(2, "To all my friends")); - m_system_menu->add_item(make(3, "Together we can play some rock&roll")); + m_system_menu->add_item(make(1, "640x480")); + m_system_menu->add_item(make(2, "800x600")); + m_system_menu->add_item(make(3, "1024x768")); m_system_menu->add_item(make(WSMenuItem::Separator)); m_system_menu->add_item(make(4, "About...")); - m_system_menu->on_item_activation = [] (WSMenuItem& item) { + m_system_menu->on_item_activation = [this] (WSMenuItem& item) { if (item.identifier() == 0) { if (fork() == 0) { execl("/bin/Terminal", "/bin/Terminal", nullptr); @@ -200,6 +200,11 @@ WSWindowManager::WSWindowManager() } return; } + switch (item.identifier()) { + case 1: set_resolution(640, 480); break; + case 2: set_resolution(800, 600); break; + case 3: set_resolution(1024, 768); break; + } if (item.identifier() == 4) { if (fork() == 0) { execl("/bin/About", "/bin/About", nullptr); @@ -231,6 +236,21 @@ WSWindowManager::~WSWindowManager() { } +void WSWindowManager::set_resolution(int width, int height) +{ + if (m_screen_rect.width() == width && m_screen_rect.height() == height) + return; + m_screen.set_resolution(width, height); + m_screen_rect = m_screen.rect(); + m_front_bitmap = GraphicsBitmap::create_wrapper({ width, height }, m_screen.scanline(0)); + m_back_bitmap = GraphicsBitmap::create_wrapper({ width, height }, m_screen.scanline(height)); + m_front_painter = make(*m_front_bitmap); + m_back_painter = make(*m_back_bitmap); + m_buffers_are_flipped = false; + invalidate(); + compose(); +} + template void WSWindowManager::for_each_active_menubar_menu(Callback callback) { @@ -767,7 +787,13 @@ void WSWindowManager::invalidate() invalidate(m_screen_rect); } -void WSWindowManager::invalidate(const Rect& a_rect) +void WSWindowManager::recompose_immediately() +{ + m_dirty_rects.clear_with_capacity(); + invalidate(m_screen_rect, false); +} + +void WSWindowManager::invalidate(const Rect& a_rect, bool should_schedule_compose_event) { auto rect = Rect::intersection(a_rect, m_screen_rect); if (rect.is_empty()) @@ -786,7 +812,7 @@ void WSWindowManager::invalidate(const Rect& a_rect) m_dirty_rects.append(rect); - if (!m_pending_compose_event) { + if (should_schedule_compose_event && !m_pending_compose_event) { WSMessageLoop::the().post_message(this, make(WSMessage::WM_DeferredCompose)); m_pending_compose_event = true; } diff --git a/WindowServer/WSWindowManager.h b/WindowServer/WSWindowManager.h index 7f23b8a334..f2ee1c9c47 100644 --- a/WindowServer/WSWindowManager.h +++ b/WindowServer/WSWindowManager.h @@ -54,8 +54,9 @@ public: void invalidate(const WSWindow&); void invalidate(const WSWindow&, const Rect&); - void invalidate(const Rect&); + void invalidate(const Rect&, bool should_schedule_compose_event = true); void invalidate(); + void recompose_immediately(); void flush(const Rect&); Font& font() { return *m_font; } @@ -66,6 +67,8 @@ public: Color menu_selection_color() const { return m_menu_selection_color; } int menubar_menu_margin() const; + void set_resolution(int width, int height); + private: void process_mouse_event(WSMouseEvent&); void handle_menu_mouse_event(WSMenu&, WSMouseEvent&);