diff --git a/Kernel/BochsVGADevice.cpp b/Kernel/BochsVGADevice.cpp index 58c94a17fc..ca3efec7f1 100644 --- a/Kernel/BochsVGADevice.cpp +++ b/Kernel/BochsVGADevice.cpp @@ -13,6 +13,8 @@ #define VBE_DISPI_INDEX_BANK 0x5 #define VBE_DISPI_INDEX_VIRT_WIDTH 0x6 #define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7 +#define VBE_DISPI_INDEX_X_OFFSET 0x8 +#define VBE_DISPI_INDEX_Y_OFFSET 0x9 #define VBE_DISPI_DISABLED 0x00 #define VBE_DISPI_ENABLED 0x01 #define VBE_DISPI_LFB_ENABLED 0x40 @@ -42,12 +44,17 @@ void BochsVGADevice::set_resolution(int width, int height) set_register(VBE_DISPI_INDEX_XRES, width); set_register(VBE_DISPI_INDEX_YRES, height); set_register(VBE_DISPI_INDEX_VIRT_WIDTH, width); - set_register(VBE_DISPI_INDEX_VIRT_HEIGHT, height); + set_register(VBE_DISPI_INDEX_VIRT_HEIGHT, height * 2); set_register(VBE_DISPI_INDEX_BPP, 32); set_register(VBE_DISPI_INDEX_ENABLE, VBE_DISPI_ENABLED | VBE_DISPI_LFB_ENABLED); set_register(VBE_DISPI_INDEX_BANK, 0); } +void BochsVGADevice::set_y_offset(int offset) +{ + set_register(VBE_DISPI_INDEX_Y_OFFSET, offset); +} + dword BochsVGADevice::find_framebuffer_address() { static const PCI::ID bochs_vga_id = { 0x1234, 0x1111 }; diff --git a/Kernel/BochsVGADevice.h b/Kernel/BochsVGADevice.h index ab5bf503f2..87cd9a1075 100644 --- a/Kernel/BochsVGADevice.h +++ b/Kernel/BochsVGADevice.h @@ -15,6 +15,7 @@ public: PhysicalAddress framebuffer_address() const { return m_framebuffer_address; } void set_resolution(int width, int height); + void set_y_offset(int); private: void set_register(word index, word value); diff --git a/Kernel/ProcessGUI.cpp b/Kernel/ProcessGUI.cpp index d93c7079fa..e830dfb0fa 100644 --- a/Kernel/ProcessGUI.cpp +++ b/Kernel/ProcessGUI.cpp @@ -276,7 +276,7 @@ DisplayInfo Process::set_video_resolution(int width, int height) info.height = height; info.bpp = 32; info.pitch = width * 4; - size_t framebuffer_size = width * height * 4; + size_t framebuffer_size = width * height * 4 * 2; if (!m_display_framebuffer_region) { auto framebuffer_vmo = VMObject::create_framebuffer_wrapper(BochsVGADevice::the().framebuffer_address(), framebuffer_size); m_display_framebuffer_region = allocate_region_with_vmo(LinearAddress(0xe0000000), framebuffer_size, move(framebuffer_vmo), 0, "framebuffer", true, true); diff --git a/WindowServer/WSScreen.cpp b/WindowServer/WSScreen.cpp index 5e48e16a6f..940f6d61fe 100644 --- a/WindowServer/WSScreen.cpp +++ b/WindowServer/WSScreen.cpp @@ -59,7 +59,7 @@ void WSScreen::on_receive_mouse_data(int dx, int dy, bool left_button, bool righ WSMessageLoop::the().post_message(&WSWindowManager::the(), move(message)); } if (m_cursor_location != prev_location || prev_left_button != left_button) - WSWindowManager::the().draw_cursor(); + WSWindowManager::the().invalidate_cursor(); } void WSScreen::on_receive_keyboard_data(Keyboard::Event kernel_event) diff --git a/WindowServer/WSWindowManager.cpp b/WindowServer/WSWindowManager.cpp index 6b5b4b2a8a..0999ccde73 100644 --- a/WindowServer/WSWindowManager.cpp +++ b/WindowServer/WSWindowManager.cpp @@ -9,6 +9,7 @@ #include #include #include +#include //#define DEBUG_COUNTERS //#define DEBUG_WID_IN_TITLE_BAR @@ -115,6 +116,17 @@ static const char* cursor_bitmap_outer_ascii = { " ## " }; +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()); + m_buffers_are_flipped = !m_buffers_are_flipped; +} + WSWindowManager::WSWindowManager() : m_screen(WSScreen::the()) , m_screen_rect(m_screen.rect()) @@ -125,8 +137,7 @@ WSWindowManager::WSWindowManager() #endif auto size = m_screen_rect.size(); m_front_bitmap = GraphicsBitmap::create_wrapper(size, m_screen.scanline(0)); - auto* region = current->allocate_region(LinearAddress(), size.width() * size.height() * sizeof(RGBA32), "BackBitmap", true, true, true); - m_back_bitmap = GraphicsBitmap::create_wrapper(m_screen_rect.size(), (RGBA32*)region->laddr().get()); + m_back_bitmap = GraphicsBitmap::create_wrapper(size, m_screen.scanline(size.height())); m_front_painter = make(*m_front_bitmap); m_back_painter = make(*m_back_bitmap); @@ -389,6 +400,9 @@ void WSWindowManager::compose() { LOCKER(m_lock); auto dirty_rects = move(m_dirty_rects); + auto cursor_location = m_screen.cursor_location(); + dirty_rects.append(m_last_cursor_rect); + dirty_rects.append({ cursor_location.x(), cursor_location.y(), (int)m_cursor_bitmap_inner->width(), (int)m_cursor_bitmap_inner->height() }); #ifdef DEBUG_COUNTERS dbgprintf("[WM] compose #%u (%u rects)\n", ++m_compose_count, dirty_rects.size()); dbgprintf("kmalloc stats: alloc:%u free:%u eternal:%u\n", sum_alloc, sum_free, kmalloc_sum_eternal); @@ -440,9 +454,24 @@ void WSWindowManager::compose() } m_back_painter->clear_clip_rect(); } + draw_cursor(); + + if (m_flash_flush) { + for (auto& rect : dirty_rects) + m_front_painter->fill_rect(rect, Color::Yellow); + } + + flip_buffers(); for (auto& r : dirty_rects) flush(r); - draw_cursor(); +} + +void WSWindowManager::invalidate_cursor() +{ + LOCKER(m_lock); + auto cursor_location = m_screen.cursor_location(); + Rect cursor_rect { cursor_location.x(), cursor_location.y(), (int)m_cursor_bitmap_inner->width(), (int)m_cursor_bitmap_inner->height() }; + invalidate(cursor_rect); } void WSWindowManager::draw_cursor() @@ -451,13 +480,12 @@ void WSWindowManager::draw_cursor() LOCKER(m_lock); auto cursor_location = m_screen.cursor_location(); Rect cursor_rect { cursor_location.x(), cursor_location.y(), (int)m_cursor_bitmap_inner->width(), (int)m_cursor_bitmap_inner->height() }; - flush(m_last_cursor_rect.united(cursor_rect)); Color inner_color = Color::White; Color outer_color = Color::Black; if (m_screen.left_mouse_button_pressed()) swap(inner_color, outer_color); - m_front_painter->draw_bitmap(cursor_location, *m_cursor_bitmap_inner, inner_color); - m_front_painter->draw_bitmap(cursor_location, *m_cursor_bitmap_outer, outer_color); + m_back_painter->draw_bitmap(cursor_location, *m_cursor_bitmap_inner, inner_color); + m_back_painter->draw_bitmap(cursor_location, *m_cursor_bitmap_outer, outer_color); m_last_cursor_rect = cursor_rect; } @@ -565,15 +593,12 @@ void WSWindowManager::flush(const Rect& a_rect) #endif RGBA32* front_ptr = m_front_bitmap->scanline(rect.y()) + rect.x(); - const RGBA32* back_ptr = m_back_bitmap->scanline(rect.y()) + rect.x(); + RGBA32* back_ptr = m_back_bitmap->scanline(rect.y()) + rect.x(); size_t pitch = m_back_bitmap->pitch(); - if (m_flash_flush) - m_front_painter->fill_rect(rect, Color::Yellow); - for (int y = 0; y < rect.height(); ++y) { - fast_dword_copy(front_ptr, back_ptr, rect.width()); + fast_dword_copy(back_ptr, front_ptr, rect.width()); front_ptr = (RGBA32*)((byte*)front_ptr + pitch); - back_ptr = (const RGBA32*)((const byte*)back_ptr + pitch); + back_ptr = (RGBA32*)((byte*)back_ptr + pitch); } } diff --git a/WindowServer/WSWindowManager.h b/WindowServer/WSWindowManager.h index 328ba3d897..4ba747e5fd 100644 --- a/WindowServer/WSWindowManager.h +++ b/WindowServer/WSWindowManager.h @@ -7,6 +7,7 @@ #include #include #include +#include #include "WSMessageReceiver.h" class WSScreen; @@ -29,6 +30,7 @@ public: void move_to_front(WSWindow&); + void invalidate_cursor(); void draw_cursor(); void invalidate(const WSWindow&); @@ -54,6 +56,7 @@ private: void compose(); void paint_window_frame(WSWindow&); + void flip_buffers(); WSScreen& m_screen; Rect m_screen_rect; @@ -105,4 +108,5 @@ private: mutable Lock m_lock; bool m_flash_flush { false }; + bool m_buffers_are_flipped { false }; };