diff --git a/Servers/WindowServer/WSCompositor.cpp b/Servers/WindowServer/WSCompositor.cpp index 4540d3eabb..d819fcfdb7 100644 --- a/Servers/WindowServer/WSCompositor.cpp +++ b/Servers/WindowServer/WSCompositor.cpp @@ -31,16 +31,9 @@ WallpaperMode mode_to_enum(const String& name) WSCompositor::WSCompositor() { - auto size = WSScreen::the().size(); - m_front_bitmap = GraphicsBitmap::create_wrapper(GraphicsBitmap::Format::RGB32, size, WSScreen::the().scanline(0)); + m_screen_can_set_buffer = WSScreen::the().can_set_buffer(); - if (can_flip_buffers()) - m_back_bitmap = GraphicsBitmap::create_wrapper(GraphicsBitmap::Format::RGB32, size, WSScreen::the().scanline(size.height())); - else - m_back_bitmap = GraphicsBitmap::create(GraphicsBitmap::Format::RGB32, size); - - m_front_painter = make(*m_front_bitmap); - m_back_painter = make(*m_back_bitmap); + init_bitmaps(); m_wallpaper_path = "/res/wallpapers/retro.rgb"; m_wallpaper = GraphicsBitmap::load_from_file(GraphicsBitmap::Format::RGBA32, m_wallpaper_path, { 1024, 768 }); @@ -63,6 +56,25 @@ WSCompositor::WSCompositor() m_immediate_compose_timer.set_interval(0); } +void WSCompositor::init_bitmaps() +{ + auto size = WSScreen::the().size(); + + m_front_bitmap = GraphicsBitmap::create_wrapper(GraphicsBitmap::Format::RGB32, size, WSScreen::the().scanline(0)); + + if (m_screen_can_set_buffer) + m_back_bitmap = GraphicsBitmap::create_wrapper(GraphicsBitmap::Format::RGB32, size, WSScreen::the().scanline(size.height())); + else + m_back_bitmap = GraphicsBitmap::create(GraphicsBitmap::Format::RGB32, size); + + m_front_painter = make(*m_front_bitmap); + m_back_painter = make(*m_back_bitmap); + + m_buffers_are_flipped = false; + + invalidate(); +} + void WSCompositor::compose() { auto& wm = WSWindowManager::the(); @@ -172,7 +184,7 @@ void WSCompositor::compose() m_front_painter->fill_rect(rect, Color::Yellow); } - if (can_flip_buffers()) + if (m_screen_can_set_buffer) flip_buffers(); for (auto& r : dirty_rects.rects()) @@ -203,7 +215,7 @@ void WSCompositor::flush(const Rect& a_rect) RGBA32* to_ptr; const RGBA32* from_ptr; - if (can_flip_buffers()) { + if (m_screen_can_set_buffer) { to_ptr = back_ptr; from_ptr = front_ptr; } else { @@ -289,28 +301,22 @@ void WSCompositor::finish_setting_wallpaper(const String& path, NonnullRefPtr(*m_front_bitmap); - m_back_painter = make(*m_back_bitmap); - m_buffers_are_flipped = false; - invalidate(); + WSScreen::the().set_resolution(desired_width, desired_height); + init_bitmaps(); compose(); } diff --git a/Servers/WindowServer/WSCompositor.h b/Servers/WindowServer/WSCompositor.h index dd4075b2cc..7f7e02f091 100644 --- a/Servers/WindowServer/WSCompositor.h +++ b/Servers/WindowServer/WSCompositor.h @@ -27,7 +27,7 @@ public: void invalidate(); void invalidate(const Rect&); - void set_resolution(int width, int height); + void set_resolution(int desired_width, int desired_height); bool set_wallpaper(const String& path, Function&& callback); String wallpaper_path() const { return m_wallpaper_path; } @@ -35,10 +35,9 @@ public: void invalidate_cursor(); Rect current_cursor_rect() const; - bool can_flip_buffers() const { return false; } - private: WSCompositor(); + void init_bitmaps(); void flip_buffers(); void flush(const Rect&); void draw_cursor(); @@ -52,6 +51,7 @@ private: CTimer m_immediate_compose_timer; bool m_flash_flush { false }; bool m_buffers_are_flipped { false }; + bool m_screen_can_set_buffer { false }; RefPtr m_front_bitmap; RefPtr m_back_bitmap; diff --git a/Servers/WindowServer/WSScreen.cpp b/Servers/WindowServer/WSScreen.cpp index e7456b4e41..d0c0ead15b 100644 --- a/Servers/WindowServer/WSScreen.cpp +++ b/Servers/WindowServer/WSScreen.cpp @@ -3,8 +3,8 @@ #include "WSEvent.h" #include "WSEventLoop.h" #include "WSWindowManager.h" +#include #include -#include #include #include @@ -16,9 +16,7 @@ WSScreen& WSScreen::the() return *s_the; } -WSScreen::WSScreen(unsigned width, unsigned height) - : m_width(width) - , m_height(height) +WSScreen::WSScreen(unsigned desired_width, unsigned desired_height) { ASSERT(!s_the); s_the = this; @@ -26,7 +24,11 @@ WSScreen::WSScreen(unsigned width, unsigned height) m_framebuffer_fd = open("/dev/fb0", O_RDWR); ASSERT(m_framebuffer_fd >= 0); - set_resolution(width, height); + if (fb_set_buffer(m_framebuffer_fd, 0) == 0) { + m_can_set_buffer = true; + } + + set_resolution(desired_width, desired_height); } WSScreen::~WSScreen() @@ -35,30 +37,40 @@ WSScreen::~WSScreen() void WSScreen::set_resolution(int width, int height) { - struct BXVGAResolution { - int width; - int height; - }; - BXVGAResolution resolution { (int)width, (int)height }; - int rc = ioctl(m_framebuffer_fd, 1985, (int)&resolution); + FBResolution resolution { 0, (int)width, (int)height }; + int rc = fb_set_resolution(m_framebuffer_fd, &resolution); ASSERT(rc == 0); + on_change_resolution(resolution.pitch, resolution.width, resolution.height); +} +void WSScreen::on_change_resolution(int pitch, int width, int height) +{ if (m_framebuffer) { - size_t previous_size_in_bytes = m_width * m_height * sizeof(RGBA32) * 2; + size_t previous_size_in_bytes = m_size_in_bytes; 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); + int rc = fb_get_size_in_bytes(m_framebuffer_fd, &m_size_in_bytes); + ASSERT(rc == 0); + + m_framebuffer = (RGBA32*)mmap(nullptr, m_size_in_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, m_framebuffer_fd, 0); ASSERT(m_framebuffer && m_framebuffer != (void*)-1); + m_pitch = pitch; m_width = width; m_height = height; m_cursor_location.constrain(rect()); } +void WSScreen::set_buffer(int index) +{ + ASSERT(m_can_set_buffer); + int rc = fb_set_buffer(m_framebuffer_fd, index); + ASSERT(rc == 0); +} + void WSScreen::on_receive_mouse_data(int dx, int dy, int dz, unsigned buttons) { auto prev_location = m_cursor_location; @@ -96,9 +108,3 @@ void WSScreen::on_receive_keyboard_data(KeyEvent kernel_event) auto message = make(kernel_event.is_press() ? WSEvent::KeyDown : WSEvent::KeyUp, kernel_event.key, kernel_event.character, kernel_event.modifiers()); CEventLoop::current().post_event(WSWindowManager::the(), move(message)); } - -void WSScreen::set_y_offset(int offset) -{ - int rc = ioctl(m_framebuffer_fd, 1982, offset); - ASSERT(rc == 0); -} diff --git a/Servers/WindowServer/WSScreen.h b/Servers/WindowServer/WSScreen.h index 59ef14456c..e5ff7451f4 100644 --- a/Servers/WindowServer/WSScreen.h +++ b/Servers/WindowServer/WSScreen.h @@ -11,6 +11,8 @@ public: ~WSScreen(); void set_resolution(int width, int height); + bool can_set_buffer() { return m_can_set_buffer; } + void set_buffer(int index); int width() const { return m_width; } int height() const { return m_height; } @@ -21,8 +23,6 @@ public: Size size() const { return { width(), height() }; } Rect rect() const { return { 0, 0, width(), height() }; } - void set_y_offset(int); - Point cursor_location() const { return m_cursor_location; } unsigned mouse_button_state() const { return m_mouse_button_state; } @@ -30,8 +30,14 @@ public: void on_receive_keyboard_data(KeyEvent); private: - RGBA32* m_framebuffer { nullptr }; + void on_change_resolution(int pitch, int width, int height); + size_t m_size_in_bytes; + + RGBA32* m_framebuffer { nullptr }; + bool m_can_set_buffer { false }; + + int m_pitch { 0 }; int m_width { 0 }; int m_height { 0 }; int m_framebuffer_fd { -1 }; @@ -43,6 +49,5 @@ private: inline RGBA32* WSScreen::scanline(int y) { - size_t pitch = sizeof(RGBA32) * width(); - return reinterpret_cast(((u8*)m_framebuffer) + (y * pitch)); + return reinterpret_cast(((u8*)m_framebuffer) + (y * m_pitch)); }