From 468113422f2b5fd8702f0e3b3c8588e3955cfa4a Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 16 Feb 2019 10:24:55 +0100 Subject: [PATCH] Kernel: Add ioctls to BochsVGADevice for mode setting and page flipping. Use these in WindowServer instead of poking at the BochsVGADevice directly. --- Kernel/BochsVGADevice.cpp | 26 ++++++++++++++++++++++++++ Kernel/BochsVGADevice.h | 2 +- Kernel/Process.cpp | 4 ++-- WindowServer/WSWindowManager.cpp | 10 +++++----- WindowServer/WSWindowManager.h | 6 ++++-- WindowServer/main.cpp | 18 ++++++++++++------ 6 files changed, 50 insertions(+), 16 deletions(-) diff --git a/Kernel/BochsVGADevice.cpp b/Kernel/BochsVGADevice.cpp index dd11e55fc7..fc163ef333 100644 --- a/Kernel/BochsVGADevice.cpp +++ b/Kernel/BochsVGADevice.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #define VBE_DISPI_IOPORT_INDEX 0x01CE #define VBE_DISPI_IOPORT_DATA 0x01CF @@ -21,6 +22,13 @@ #define VBE_DISPI_ENABLED 0x01 #define VBE_DISPI_LFB_ENABLED 0x40 +#define BXVGA_DEV_IOCTL_SET_Y_OFFSET 1982 +#define BXVGA_DEV_IOCTL_SET_RESOLUTION 1985 +struct BXVGAResolution { + int width; + int height; +}; + static BochsVGADevice* s_the; BochsVGADevice& BochsVGADevice::the() @@ -87,6 +95,24 @@ dword BochsVGADevice::find_framebuffer_address() return framebuffer_address; } +int BochsVGADevice::ioctl(Process& process, unsigned int request, unsigned int arg) +{ + switch (request) { + case BXVGA_DEV_IOCTL_SET_Y_OFFSET: + set_y_offset(arg); + return 0; + case BXVGA_DEV_IOCTL_SET_RESOLUTION: { + auto* resolution = (const BXVGAResolution*)arg; + if (!process.validate_read_typed(resolution)) + return -EFAULT; + set_resolution(resolution->width, resolution->height); + return 0; + } + default: + return -EINVAL; + }; +} + bool BochsVGADevice::can_read(Process&) const { ASSERT_NOT_REACHED(); diff --git a/Kernel/BochsVGADevice.h b/Kernel/BochsVGADevice.h index e1fa72bf8c..8d40841b7a 100644 --- a/Kernel/BochsVGADevice.h +++ b/Kernel/BochsVGADevice.h @@ -17,7 +17,7 @@ public: void set_resolution(int width, int height); void set_y_offset(int); - + virtual int ioctl(Process&, unsigned request, unsigned arg) override; virtual Region* mmap(Process&, LinearAddress preferred_laddr, size_t offset, size_t) override; size_t framebuffer_size_in_bytes() const { return m_framebuffer_size.area() * sizeof(dword) * 2; } diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 51fb588dc3..290c8cf0ae 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -1786,9 +1786,9 @@ int Process::sys$ioctl(int fd, unsigned request, unsigned arg) *pid = descriptor->socket()->origin_pid(); return 0; } - if (!descriptor->is_character_device()) + if (!descriptor->is_device()) return -ENOTTY; - return descriptor->character_device()->ioctl(*this, request, arg); + return descriptor->device()->ioctl(*this, request, arg); } int Process::sys$getdtablesize() diff --git a/WindowServer/WSWindowManager.cpp b/WindowServer/WSWindowManager.cpp index 4fc2f55f50..6d5b19bbed 100644 --- a/WindowServer/WSWindowManager.cpp +++ b/WindowServer/WSWindowManager.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include "WSMenu.h" #include "WSMenuBar.h" @@ -126,10 +125,11 @@ void WSWindowManager::flip_buffers() { swap(m_front_bitmap, m_back_bitmap); swap(m_front_painter, m_back_painter); - if (m_buffers_are_flipped) - BochsVGADevice::the().set_y_offset(0); - else - BochsVGADevice::the().set_y_offset(m_screen_rect.height()); + if (m_framebuffer_fd != -1) { + int new_y_offset = m_buffers_are_flipped ? 0 : m_screen_rect.height(); + int rc = current->sys$ioctl(m_framebuffer_fd, 1982, new_y_offset); + ASSERT(rc == 0); + } m_buffers_are_flipped = !m_buffers_are_flipped; } diff --git a/WindowServer/WSWindowManager.h b/WindowServer/WSWindowManager.h index 91ff9e6967..2c97e09853 100644 --- a/WindowServer/WSWindowManager.h +++ b/WindowServer/WSWindowManager.h @@ -63,8 +63,8 @@ public: Color menu_selection_color() const { return m_menu_selection_color; } int menubar_menu_margin() const; - int api$menu_add_separator(int menu_id); - int api$menu_add_item(int menu_id, unsigned identifier, String&& text); + int framebuffer_fd() const { return m_framebuffer_fd; } + void set_framebuffer_fd(int fd) { m_framebuffer_fd = fd; } private: WSWindowManager(); @@ -151,4 +151,6 @@ private: Color m_menu_selection_color; WeakPtr m_current_menubar; WeakPtr m_current_menu; + + int m_framebuffer_fd { -1 }; }; diff --git a/WindowServer/main.cpp b/WindowServer/main.cpp index 89ea79a5e2..9454b9793f 100644 --- a/WindowServer/main.cpp +++ b/WindowServer/main.cpp @@ -12,27 +12,33 @@ void WindowServer_main() { WSMessageLoop::the().set_server_process(*current); current->set_priority(Process::HighPriority); - auto info = current->set_video_resolution(1024, 768); - - dbgprintf("Screen is %ux%ux%ubpp\n", info.width, info.height, info.bpp); int bxvga_fd = current->sys$open("/dev/bxvga", O_RDWR); ASSERT(bxvga_fd >= 0); + struct BXVGAResolution { + int width; + int height; + }; + BXVGAResolution resolution { 1024, 768 }; + + int rc = current->sys$ioctl(bxvga_fd, 1985, (int)&resolution); + ASSERT(rc == 0); + Syscall::SC_mmap_params params; memset(¶ms, 0, sizeof(params)); params.fd = bxvga_fd; params.prot = PROT_READ | PROT_WRITE; params.flags = MAP_SHARED; - params.size = info.width * info.height * sizeof(RGBA32) * 2; + params.size = resolution.width * resolution.height * sizeof(RGBA32) * 2; params.offset = 0; kprintf("Calling sys$mmap in WS\n"); void* framebuffer = current->sys$mmap(¶ms); ASSERT(framebuffer && framebuffer != (void*)-1); - WSScreen screen((dword*)framebuffer, info.width, info.height); + WSScreen screen((dword*)framebuffer, resolution.width, resolution.height); - WSWindowManager::the(); + WSWindowManager::the().set_framebuffer_fd(bxvga_fd); dbgprintf("Entering WindowServer main loop.\n"); WSMessageLoop::the().exec();