mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 16:47:42 +00:00
Add ability to switch video modes from the system menu.
I had to change PhysicalPage around a bit for this. Physical pages can now be instantiated for any arbitrary physical address without worrying that such pages end up in the kernel page allocator when released. Most of the pieces were already in place, I just glued everything together.
This commit is contained in:
parent
8321908abe
commit
0730b3c15f
7 changed files with 91 additions and 26 deletions
|
@ -42,7 +42,7 @@ MemoryManager::~MemoryManager()
|
||||||
|
|
||||||
PageDirectory::PageDirectory(PhysicalAddress paddr)
|
PageDirectory::PageDirectory(PhysicalAddress paddr)
|
||||||
{
|
{
|
||||||
m_directory_page = adopt(*new PhysicalPage(paddr, true));
|
m_directory_page = PhysicalPage::create_eternal(paddr, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
PageDirectory::PageDirectory()
|
PageDirectory::PageDirectory()
|
||||||
|
@ -87,11 +87,11 @@ void MemoryManager::initialize_paging()
|
||||||
// 3 MB -> 4 MB Supervisor physical pages (available for allocation!)
|
// 3 MB -> 4 MB Supervisor physical pages (available for allocation!)
|
||||||
// 4 MB -> (max) MB Userspace 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)
|
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);
|
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)
|
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);
|
m_quickmap_addr = LinearAddress((1 * MB) - PAGE_SIZE);
|
||||||
#ifdef MM_DEBUG
|
#ifdef MM_DEBUG
|
||||||
dbgprintf("MM: Quickmap will use P%x\n", m_quickmap_addr.get());
|
dbgprintf("MM: Quickmap will use P%x\n", m_quickmap_addr.get());
|
||||||
|
@ -650,8 +650,23 @@ Region::~Region()
|
||||||
MM.unregister_region(*this);
|
MM.unregister_region(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicalPage::PhysicalPage(PhysicalAddress paddr, bool supervisor)
|
RetainPtr<PhysicalPage> PhysicalPage::create_eternal(PhysicalAddress paddr, bool supervisor)
|
||||||
: m_supervisor(supervisor)
|
{
|
||||||
|
void* slot = kmalloc_eternal(sizeof(PhysicalPage));
|
||||||
|
new (slot) PhysicalPage(paddr, supervisor);
|
||||||
|
return adopt(*(PhysicalPage*)slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
RetainPtr<PhysicalPage> 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)
|
, m_paddr(paddr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -724,7 +739,7 @@ VMObject::VMObject(PhysicalAddress paddr, size_t size)
|
||||||
{
|
{
|
||||||
MM.register_vmo(*this);
|
MM.register_vmo(*this);
|
||||||
for (size_t i = 0; i < size; i += PAGE_SIZE) {
|
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());
|
ASSERT(m_physical_pages.size() == page_count());
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,6 @@ enum class PageFaultResponse {
|
||||||
};
|
};
|
||||||
|
|
||||||
class PhysicalPage {
|
class PhysicalPage {
|
||||||
AK_MAKE_ETERNAL
|
|
||||||
friend class MemoryManager;
|
friend class MemoryManager;
|
||||||
friend class PageDirectory;
|
friend class PageDirectory;
|
||||||
friend class VMObject;
|
friend class VMObject;
|
||||||
|
@ -41,19 +40,27 @@ public:
|
||||||
void release()
|
void release()
|
||||||
{
|
{
|
||||||
ASSERT(m_retain_count);
|
ASSERT(m_retain_count);
|
||||||
if (!--m_retain_count)
|
if (!--m_retain_count) {
|
||||||
return_to_freelist();
|
if (m_may_return_to_freelist)
|
||||||
|
return_to_freelist();
|
||||||
|
else
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static RetainPtr<PhysicalPage> create_eternal(PhysicalAddress, bool supervisor);
|
||||||
|
static RetainPtr<PhysicalPage> create(PhysicalAddress, bool supervisor);
|
||||||
|
|
||||||
unsigned short retain_count() const { return m_retain_count; }
|
unsigned short retain_count() const { return m_retain_count; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PhysicalPage(PhysicalAddress paddr, bool supervisor);
|
PhysicalPage(PhysicalAddress paddr, bool supervisor, bool may_return_to_freelist = true);
|
||||||
~PhysicalPage() = delete;
|
~PhysicalPage() { }
|
||||||
|
|
||||||
void return_to_freelist();
|
void return_to_freelist();
|
||||||
|
|
||||||
unsigned short m_retain_count { 1 };
|
unsigned short m_retain_count { 1 };
|
||||||
|
bool m_may_return_to_freelist { true };
|
||||||
bool m_supervisor { false };
|
bool m_supervisor { false };
|
||||||
PhysicalAddress m_paddr;
|
PhysicalAddress m_paddr;
|
||||||
};
|
};
|
||||||
|
|
|
@ -101,7 +101,7 @@ void* kmalloc_impl(dword size)
|
||||||
real_size = size + sizeof(allocation_t);
|
real_size = size + sizeof(allocation_t);
|
||||||
|
|
||||||
if (sum_free < real_size) {
|
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();
|
hang();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,7 +50,7 @@ void* malloc(size_t size)
|
||||||
size_t real_size = size + sizeof(MallocHeader) + sizeof(MallocFooter);
|
size_t real_size = size + sizeof(MallocHeader) + sizeof(MallocFooter);
|
||||||
|
|
||||||
if (s_malloc_sum_free < real_size) {
|
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);
|
assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,12 +21,19 @@ WSScreen::WSScreen(unsigned width, unsigned height)
|
||||||
{
|
{
|
||||||
ASSERT(!s_the);
|
ASSERT(!s_the);
|
||||||
s_the = this;
|
s_the = this;
|
||||||
|
|
||||||
m_cursor_location = rect().center();
|
m_cursor_location = rect().center();
|
||||||
|
|
||||||
m_framebuffer_fd = open("/dev/bxvga", O_RDWR);
|
m_framebuffer_fd = open("/dev/bxvga", O_RDWR);
|
||||||
ASSERT(m_framebuffer_fd >= 0);
|
ASSERT(m_framebuffer_fd >= 0);
|
||||||
|
|
||||||
|
set_resolution(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
WSScreen::~WSScreen()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void WSScreen::set_resolution(int width, int height)
|
||||||
|
{
|
||||||
struct BXVGAResolution {
|
struct BXVGAResolution {
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
|
@ -35,13 +42,20 @@ WSScreen::WSScreen(unsigned width, unsigned height)
|
||||||
int rc = ioctl(m_framebuffer_fd, 1985, (int)&resolution);
|
int rc = ioctl(m_framebuffer_fd, 1985, (int)&resolution);
|
||||||
ASSERT(rc == 0);
|
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);
|
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);
|
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)
|
void WSScreen::on_receive_mouse_data(int dx, int dy, bool left_button, bool right_button)
|
||||||
|
|
|
@ -187,12 +187,12 @@ WSWindowManager::WSWindowManager()
|
||||||
m_system_menu = make<WSMenu>(nullptr, -1, String((const char*)system_menu_name));
|
m_system_menu = make<WSMenu>(nullptr, -1, String((const char*)system_menu_name));
|
||||||
m_system_menu->add_item(make<WSMenuItem>(0, "Launch Terminal"));
|
m_system_menu->add_item(make<WSMenuItem>(0, "Launch Terminal"));
|
||||||
m_system_menu->add_item(make<WSMenuItem>(WSMenuItem::Separator));
|
m_system_menu->add_item(make<WSMenuItem>(WSMenuItem::Separator));
|
||||||
m_system_menu->add_item(make<WSMenuItem>(1, "Hello again"));
|
m_system_menu->add_item(make<WSMenuItem>(1, "640x480"));
|
||||||
m_system_menu->add_item(make<WSMenuItem>(2, "To all my friends"));
|
m_system_menu->add_item(make<WSMenuItem>(2, "800x600"));
|
||||||
m_system_menu->add_item(make<WSMenuItem>(3, "Together we can play some rock&roll"));
|
m_system_menu->add_item(make<WSMenuItem>(3, "1024x768"));
|
||||||
m_system_menu->add_item(make<WSMenuItem>(WSMenuItem::Separator));
|
m_system_menu->add_item(make<WSMenuItem>(WSMenuItem::Separator));
|
||||||
m_system_menu->add_item(make<WSMenuItem>(4, "About..."));
|
m_system_menu->add_item(make<WSMenuItem>(4, "About..."));
|
||||||
m_system_menu->on_item_activation = [] (WSMenuItem& item) {
|
m_system_menu->on_item_activation = [this] (WSMenuItem& item) {
|
||||||
if (item.identifier() == 0) {
|
if (item.identifier() == 0) {
|
||||||
if (fork() == 0) {
|
if (fork() == 0) {
|
||||||
execl("/bin/Terminal", "/bin/Terminal", nullptr);
|
execl("/bin/Terminal", "/bin/Terminal", nullptr);
|
||||||
|
@ -200,6 +200,11 @@ WSWindowManager::WSWindowManager()
|
||||||
}
|
}
|
||||||
return;
|
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 (item.identifier() == 4) {
|
||||||
if (fork() == 0) {
|
if (fork() == 0) {
|
||||||
execl("/bin/About", "/bin/About", nullptr);
|
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<Painter>(*m_front_bitmap);
|
||||||
|
m_back_painter = make<Painter>(*m_back_bitmap);
|
||||||
|
m_buffers_are_flipped = false;
|
||||||
|
invalidate();
|
||||||
|
compose();
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Callback>
|
template<typename Callback>
|
||||||
void WSWindowManager::for_each_active_menubar_menu(Callback callback)
|
void WSWindowManager::for_each_active_menubar_menu(Callback callback)
|
||||||
{
|
{
|
||||||
|
@ -767,7 +787,13 @@ void WSWindowManager::invalidate()
|
||||||
invalidate(m_screen_rect);
|
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);
|
auto rect = Rect::intersection(a_rect, m_screen_rect);
|
||||||
if (rect.is_empty())
|
if (rect.is_empty())
|
||||||
|
@ -786,7 +812,7 @@ void WSWindowManager::invalidate(const Rect& a_rect)
|
||||||
|
|
||||||
m_dirty_rects.append(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>(WSMessage::WM_DeferredCompose));
|
WSMessageLoop::the().post_message(this, make<WSMessage>(WSMessage::WM_DeferredCompose));
|
||||||
m_pending_compose_event = true;
|
m_pending_compose_event = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,8 +54,9 @@ public:
|
||||||
|
|
||||||
void invalidate(const WSWindow&);
|
void invalidate(const WSWindow&);
|
||||||
void invalidate(const WSWindow&, const Rect&);
|
void invalidate(const WSWindow&, const Rect&);
|
||||||
void invalidate(const Rect&);
|
void invalidate(const Rect&, bool should_schedule_compose_event = true);
|
||||||
void invalidate();
|
void invalidate();
|
||||||
|
void recompose_immediately();
|
||||||
void flush(const Rect&);
|
void flush(const Rect&);
|
||||||
|
|
||||||
Font& font() { return *m_font; }
|
Font& font() { return *m_font; }
|
||||||
|
@ -66,6 +67,8 @@ public:
|
||||||
Color menu_selection_color() const { return m_menu_selection_color; }
|
Color menu_selection_color() const { return m_menu_selection_color; }
|
||||||
int menubar_menu_margin() const;
|
int menubar_menu_margin() const;
|
||||||
|
|
||||||
|
void set_resolution(int width, int height);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void process_mouse_event(WSMouseEvent&);
|
void process_mouse_event(WSMouseEvent&);
|
||||||
void handle_menu_mouse_event(WSMenu&, WSMouseEvent&);
|
void handle_menu_mouse_event(WSMenu&, WSMouseEvent&);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue