summaryrefslogtreecommitdiff
path: root/WindowServer
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-02-07 08:53:57 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-02-07 08:56:26 +0100
commit443d1c2237d63e99bae9f20450769670a3490eb2 (patch)
treea7c377590f165feb48e9240990ed46097b4e0871 /WindowServer
parent1f159eaab0ad6791f35842eb3e6f3c746f3101aa (diff)
downloadserenity-443d1c2237d63e99bae9f20450769670a3490eb2.zip
WindowServer: Coordinate double-buffering with the BochsVGA card.
Use the BochsVGA card's virtual-height + virtual-y features to implement a "hardware double buffering" type scheme. This is a performance degradation since we now draw a bunch more than before. But there's also no tearing or cursor flickering. I'm gonna commit this and try to improve upon it. :^)
Diffstat (limited to 'WindowServer')
-rw-r--r--WindowServer/WSScreen.cpp2
-rw-r--r--WindowServer/WSWindowManager.cpp49
-rw-r--r--WindowServer/WSWindowManager.h4
3 files changed, 42 insertions, 13 deletions
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 <SharedGraphics/Painter.h>
#include <SharedGraphics/CharacterBitmap.h>
#include <AK/StdLibExtras.h>
+#include <Kernel/BochsVGADevice.h>
//#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<Painter>(*m_front_bitmap);
m_back_painter = make<Painter>(*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 <AK/InlineLinkedList.h>
#include <AK/WeakPtr.h>
#include <AK/Lock.h>
+#include <AK/CircularQueue.h>
#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 };
};