From e4cb9b298579cbb8274dd9f32dd730b7249d025b Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 13 Jan 2019 00:04:23 +0100 Subject: [PATCH] Have WindowManager::invalidate() unite dirty rects that intersect each other. This is kinda primitive but it avoids double-draw when slowly dragging stuff. --- Widgets/Rect.cpp | 10 ++++++++++ Widgets/Rect.h | 6 ++++-- Widgets/WindowManager.cpp | 13 +++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/Widgets/Rect.cpp b/Widgets/Rect.cpp index 4656a82f0f..95704357dc 100644 --- a/Widgets/Rect.cpp +++ b/Widgets/Rect.cpp @@ -20,3 +20,13 @@ void Rect::intersect(const Rect& other) m_size.setWidth((r - l) + 1); m_size.setHeight((b - t) + 1); } + +Rect Rect::united(const Rect& other) const +{ + Rect rect; + rect.set_left(min(left(), other.left())); + rect.set_top(min(top(), other.top())); + rect.set_right(max(right(), other.right())); + rect.set_bottom(max(bottom(), other.bottom())); + return rect; +} diff --git a/Widgets/Rect.h b/Widgets/Rect.h index 6e6ef85c76..95f98dd1c7 100644 --- a/Widgets/Rect.h +++ b/Widgets/Rect.h @@ -88,12 +88,12 @@ public: void set_right(int right) { - setWidth(right - x()); + setWidth(right - x() + 1); } void set_bottom(int bottom) { - setHeight(bottom - y()); + setHeight(bottom - y() + 1); } bool intersects(const Rect& other) const @@ -132,6 +132,8 @@ public: return r; } + Rect united(const Rect&) const; + private: Point m_location; Size m_size; diff --git a/Widgets/WindowManager.cpp b/Widgets/WindowManager.cpp index 3f6ec1ef5a..7ac80bf269 100644 --- a/Widgets/WindowManager.cpp +++ b/Widgets/WindowManager.cpp @@ -8,6 +8,8 @@ #include "Process.h" #include "MemoryManager.h" +//#define DEBUG_FLUSH_YELLOW + static const int windowTitleBarHeight = 16; static inline Rect titleBarRectForWindow(const Rect& window) @@ -327,6 +329,12 @@ void WindowManager::invalidate(const Rect& a_rect) for (auto& r : m_invalidated_rects) { if (r.contains(rect)) return; + if (r.intersects(rect)) { + // Unite with the existing dirty rect. + // FIXME: It would be much nicer to compute the exact rects needing repaint. + r = r.united(rect); + return; + } } m_invalidated_rects.append(rect); @@ -350,6 +358,11 @@ void WindowManager::flush(const Rect& a_rect) const RGBA32* back_ptr = m_back_bitmap->scanline(rect.y()) + rect.x(); size_t pitch = m_back_bitmap->pitch(); +#ifdef DEBUG_FLUSH_YELLOW + Painter p(*m_front_bitmap); + p.fill_rect(rect, Color::Yellow); +#endif + for (int y = 0; y < rect.height(); ++y) { fast_dword_copy(front_ptr, back_ptr, rect.width()); front_ptr = (RGBA32*)((byte*)front_ptr + pitch);