mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 11:48:10 +00:00
WindowSerer+LibGUI: Send multiple rects in invalidation/flush messages.
This patch moves to sending up to 32 rects at a time when coordinating the painting between WindowServer and its clients. Rects are also merged into a minimal DisjointRectSet on the server side before painting. Interactive resize looks a lot better after this change, since we can usually do all the repainting needed in one go.
This commit is contained in:
parent
ec365b82d5
commit
7efd61fcf5
10 changed files with 74 additions and 29 deletions
|
@ -84,7 +84,8 @@ void GEventLoop::handle_paint_event(const WSAPI_ServerMessage& event, GWindow& w
|
||||||
#ifdef GEVENTLOOP_DEBUG
|
#ifdef GEVENTLOOP_DEBUG
|
||||||
dbgprintf("WID=%x Paint [%d,%d %dx%d]\n", event.window_id, event.paint.rect.location.x, event.paint.rect.location.y, event.paint.rect.size.width, event.paint.rect.size.height);
|
dbgprintf("WID=%x Paint [%d,%d %dx%d]\n", event.window_id, event.paint.rect.location.x, event.paint.rect.location.y, event.paint.rect.size.width, event.paint.rect.size.height);
|
||||||
#endif
|
#endif
|
||||||
post_event(window, make<GPaintEvent>(event.paint.rect, event.paint.window_size));
|
for (int i = 0; i < event.rect_count; ++i)
|
||||||
|
post_event(window, make<GPaintEvent>(event.rects[i], event.paint.window_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GEventLoop::handle_resize_event(const WSAPI_ServerMessage& event, GWindow& window)
|
void GEventLoop::handle_resize_event(const WSAPI_ServerMessage& event, GWindow& window)
|
||||||
|
|
|
@ -302,13 +302,15 @@ void GWindow::update(const Rect& a_rect)
|
||||||
|
|
||||||
if (m_pending_paint_event_rects.is_empty()) {
|
if (m_pending_paint_event_rects.is_empty()) {
|
||||||
deferred_invoke([this] (auto&) {
|
deferred_invoke([this] (auto&) {
|
||||||
for (auto& rect : m_pending_paint_event_rects) {
|
// FIXME: Break it into multiple batches if needed.
|
||||||
WSAPI_ClientMessage request;
|
ASSERT(m_pending_paint_event_rects.size() <= 32);
|
||||||
request.type = WSAPI_ClientMessage::Type::InvalidateRect;
|
WSAPI_ClientMessage request;
|
||||||
request.window_id = m_window_id;
|
request.type = WSAPI_ClientMessage::Type::InvalidateRect;
|
||||||
request.window.rect = rect;
|
request.window_id = m_window_id;
|
||||||
GEventLoop::current().post_message_to_server(request);
|
for (int i = 0; i < m_pending_paint_event_rects.size(); ++i)
|
||||||
}
|
request.rects[i] = m_pending_paint_event_rects[i];
|
||||||
|
request.rect_count = m_pending_paint_event_rects.size();
|
||||||
|
GEventLoop::current().post_message_to_server(request);
|
||||||
m_pending_paint_event_rects.clear_with_capacity();
|
m_pending_paint_event_rects.clear_with_capacity();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,8 +109,16 @@ struct WSAPI_ServerMessage {
|
||||||
};
|
};
|
||||||
Type type { Invalid };
|
Type type { Invalid };
|
||||||
int window_id { -1 };
|
int window_id { -1 };
|
||||||
int text_length { 0 };
|
|
||||||
char text[256];
|
union {
|
||||||
|
int text_length { 0 };
|
||||||
|
int rect_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
union {
|
||||||
|
char text[512];
|
||||||
|
WSAPI_Rect rects[32];
|
||||||
|
};
|
||||||
int value { 0 };
|
int value { 0 };
|
||||||
|
|
||||||
union {
|
union {
|
||||||
|
@ -134,7 +142,6 @@ struct WSAPI_ServerMessage {
|
||||||
WSAPI_Rect old_rect;
|
WSAPI_Rect old_rect;
|
||||||
} window;
|
} window;
|
||||||
struct {
|
struct {
|
||||||
WSAPI_Rect rect;
|
|
||||||
WSAPI_Size window_size;
|
WSAPI_Size window_size;
|
||||||
} paint;
|
} paint;
|
||||||
struct {
|
struct {
|
||||||
|
@ -207,8 +214,14 @@ struct WSAPI_ClientMessage {
|
||||||
};
|
};
|
||||||
Type type { Invalid };
|
Type type { Invalid };
|
||||||
int window_id { -1 };
|
int window_id { -1 };
|
||||||
int text_length { 0 };
|
union {
|
||||||
char text[256];
|
int text_length { 0 };
|
||||||
|
int rect_count;
|
||||||
|
};
|
||||||
|
union {
|
||||||
|
char text[512];
|
||||||
|
WSAPI_Rect rects[32];
|
||||||
|
};
|
||||||
int value { 0 };
|
int value { 0 };
|
||||||
|
|
||||||
union {
|
union {
|
||||||
|
|
|
@ -383,7 +383,7 @@ void WSClientConnection::handle_request(const WSAPISetWindowRectRequest& request
|
||||||
}
|
}
|
||||||
auto& window = *(*it).value;
|
auto& window = *(*it).value;
|
||||||
window.set_rect(request.rect());
|
window.set_rect(request.rect());
|
||||||
post_paint_request(window, request.rect());
|
window.request_update(request.rect());
|
||||||
}
|
}
|
||||||
|
|
||||||
void WSClientConnection::handle_request(const WSAPIGetWindowRectRequest& request)
|
void WSClientConnection::handle_request(const WSAPIGetWindowRectRequest& request)
|
||||||
|
@ -477,14 +477,20 @@ void WSClientConnection::handle_request(const WSAPIDestroyWindowRequest& request
|
||||||
post_message(response);
|
post_message(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WSClientConnection::post_paint_request(const WSWindow& window, const Rect& rect)
|
void WSClientConnection::post_paint_message(WSWindow& window)
|
||||||
{
|
{
|
||||||
WSAPI_ServerMessage response;
|
WSAPI_ServerMessage message;
|
||||||
response.type = WSAPI_ServerMessage::Type::Paint;
|
message.type = WSAPI_ServerMessage::Type::Paint;
|
||||||
response.window_id = window.window_id();
|
message.window_id = window.window_id();
|
||||||
response.paint.rect = rect;
|
auto rect_set = window.take_pending_paint_rects();
|
||||||
response.paint.window_size = window.size();
|
auto& rects = rect_set.rects();
|
||||||
post_message(response);
|
// FIXME: Break it into multiple batches if needed.
|
||||||
|
ASSERT(rects.size() <= 32);
|
||||||
|
message.rect_count = rects.size();
|
||||||
|
for (int i = 0; i < rects.size(); ++i)
|
||||||
|
message.rects[i] = rects[i];
|
||||||
|
message.paint.window_size = window.size();
|
||||||
|
post_message(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WSClientConnection::handle_request(const WSAPIInvalidateRectRequest& request)
|
void WSClientConnection::handle_request(const WSAPIInvalidateRectRequest& request)
|
||||||
|
@ -496,7 +502,8 @@ void WSClientConnection::handle_request(const WSAPIInvalidateRectRequest& reques
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto& window = *(*it).value;
|
auto& window = *(*it).value;
|
||||||
post_paint_request(window, request.rect());
|
for (int i = 0; i < request.rects().size(); ++i)
|
||||||
|
window.request_update(request.rects()[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WSClientConnection::handle_request(const WSAPIDidFinishPaintingNotification& request)
|
void WSClientConnection::handle_request(const WSAPIDidFinishPaintingNotification& request)
|
||||||
|
|
|
@ -37,7 +37,7 @@ public:
|
||||||
template<typename Callback> void for_each_window(Callback);
|
template<typename Callback> void for_each_window(Callback);
|
||||||
|
|
||||||
void notify_about_new_screen_rect(const Rect&);
|
void notify_about_new_screen_rect(const Rect&);
|
||||||
void post_paint_request(const WSWindow&, const Rect&);
|
void post_paint_message(WSWindow&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void event(CEvent&) override;
|
virtual void event(CEvent&) override;
|
||||||
|
|
|
@ -564,19 +564,19 @@ private:
|
||||||
|
|
||||||
class WSAPIInvalidateRectRequest final : public WSAPIClientRequest {
|
class WSAPIInvalidateRectRequest final : public WSAPIClientRequest {
|
||||||
public:
|
public:
|
||||||
explicit WSAPIInvalidateRectRequest(int client_id, int window_id, const Rect& rect)
|
explicit WSAPIInvalidateRectRequest(int client_id, int window_id, const Vector<Rect, 32>& rects)
|
||||||
: WSAPIClientRequest(WSEvent::APIInvalidateRectRequest, client_id)
|
: WSAPIClientRequest(WSEvent::APIInvalidateRectRequest, client_id)
|
||||||
, m_window_id(window_id)
|
, m_window_id(window_id)
|
||||||
, m_rect(rect)
|
, m_rects(rects)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int window_id() const { return m_window_id; }
|
int window_id() const { return m_window_id; }
|
||||||
Rect rect() const { return m_rect; }
|
const Vector<Rect, 32>& rects() const { return m_rects; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_window_id { 0 };
|
int m_window_id { 0 };
|
||||||
Rect m_rect;
|
Vector<Rect, 32> m_rects;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WSAPIGetWindowBackingStoreRequest final : public WSAPIClientRequest {
|
class WSAPIGetWindowBackingStoreRequest final : public WSAPIClientRequest {
|
||||||
|
|
|
@ -191,9 +191,14 @@ void WSEventLoop::on_receive_from_client(int client_id, const WSAPI_ClientMessag
|
||||||
case WSAPI_ClientMessage::Type::GetClipboardContents:
|
case WSAPI_ClientMessage::Type::GetClipboardContents:
|
||||||
post_event(client, make<WSAPIGetClipboardContentsRequest>(client_id));
|
post_event(client, make<WSAPIGetClipboardContentsRequest>(client_id));
|
||||||
break;
|
break;
|
||||||
case WSAPI_ClientMessage::Type::InvalidateRect:
|
case WSAPI_ClientMessage::Type::InvalidateRect: {
|
||||||
post_event(client, make<WSAPIInvalidateRectRequest>(client_id, message.window_id, message.window.rect));
|
Vector<Rect, 32> rects;
|
||||||
|
ASSERT(message.rect_count <= 32);
|
||||||
|
for (int i = 0; i < message.rect_count; ++i)
|
||||||
|
rects.append(message.rects[i]);
|
||||||
|
post_event(client, make<WSAPIInvalidateRectRequest>(client_id, message.window_id, rects));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case WSAPI_ClientMessage::Type::DidFinishPainting:
|
case WSAPI_ClientMessage::Type::DidFinishPainting:
|
||||||
post_event(client, make<WSAPIDidFinishPaintingNotification>(client_id, message.window_id, message.window.rect));
|
post_event(client, make<WSAPIDidFinishPaintingNotification>(client_id, message.window_id, message.window.rect));
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -271,3 +271,13 @@ void WSWindow::set_default_icon()
|
||||||
m_icon = default_window_icon();
|
m_icon = default_window_icon();
|
||||||
m_icon_path = default_window_icon_path();
|
m_icon_path = default_window_icon_path();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WSWindow::request_update(const Rect& rect)
|
||||||
|
{
|
||||||
|
if (m_pending_paint_rects.is_empty()) {
|
||||||
|
deferred_invoke([this] (auto&) {
|
||||||
|
client()->post_paint_message(*this);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
m_pending_paint_rects.add(rect);
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <LibCore/CObject.h>
|
#include <LibCore/CObject.h>
|
||||||
#include <WindowServer/WSWindowType.h>
|
#include <WindowServer/WSWindowType.h>
|
||||||
#include <WindowServer/WSWindowFrame.h>
|
#include <WindowServer/WSWindowFrame.h>
|
||||||
|
#include <SharedGraphics/DisjointRectSet.h>
|
||||||
|
|
||||||
class WSClientConnection;
|
class WSClientConnection;
|
||||||
class WSCursor;
|
class WSCursor;
|
||||||
|
@ -127,6 +128,9 @@ public:
|
||||||
const WSCursor* override_cursor() const { return m_override_cursor.ptr(); }
|
const WSCursor* override_cursor() const { return m_override_cursor.ptr(); }
|
||||||
void set_override_cursor(RetainPtr<WSCursor>&& cursor) { m_override_cursor = move(cursor); }
|
void set_override_cursor(RetainPtr<WSCursor>&& cursor) { m_override_cursor = move(cursor); }
|
||||||
|
|
||||||
|
void request_update(const Rect&);
|
||||||
|
DisjointRectSet take_pending_paint_rects() { return move(m_pending_paint_rects); }
|
||||||
|
|
||||||
// For InlineLinkedList.
|
// For InlineLinkedList.
|
||||||
// FIXME: Maybe make a ListHashSet and then WSWindowManager can just use that.
|
// FIXME: Maybe make a ListHashSet and then WSWindowManager can just use that.
|
||||||
WSWindow* m_next { nullptr };
|
WSWindow* m_next { nullptr };
|
||||||
|
@ -160,4 +164,5 @@ private:
|
||||||
WSWindowFrame m_frame;
|
WSWindowFrame m_frame;
|
||||||
Color m_background_color { Color::LightGray };
|
Color m_background_color { Color::LightGray };
|
||||||
unsigned m_wm_event_mask { 0 };
|
unsigned m_wm_event_mask { 0 };
|
||||||
|
DisjointRectSet m_pending_paint_rects;
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,6 +11,8 @@ public:
|
||||||
|
|
||||||
void add(const Rect&);
|
void add(const Rect&);
|
||||||
|
|
||||||
|
bool is_empty() const { return m_rects.is_empty(); }
|
||||||
|
|
||||||
void clear() { m_rects.clear(); }
|
void clear() { m_rects.clear(); }
|
||||||
void clear_with_capacity() { m_rects.clear_with_capacity(); }
|
void clear_with_capacity() { m_rects.clear_with_capacity(); }
|
||||||
const Vector<Rect, 32>& rects() const { return m_rects; }
|
const Vector<Rect, 32>& rects() const { return m_rects; }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue