1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-06-01 09:28:13 +00:00

Rework the rendering model so that clients instantiate backing stores.

This makes interactive resizing work a lot better, althought it's still not
perfect. There are still glitches and unpleasant flashes of zeroed memory.
This commit is contained in:
Andreas Kling 2019-02-20 21:59:13 +01:00
parent e0b81ee4c9
commit fa02d2a39b
17 changed files with 185 additions and 46 deletions

View file

@ -78,8 +78,11 @@ int GEventLoop::exec()
for (;;) {
if (m_exit_requested)
return m_exit_code;
if (m_queued_events.is_empty())
process_unprocessed_messages();
if (m_queued_events.is_empty()) {
wait_for_event();
process_unprocessed_messages();
}
Vector<QueuedEvent> events = move(m_queued_events);
for (auto& queued_event : events) {
auto* receiver = queued_event.receiver;
@ -223,6 +226,7 @@ void GEventLoop::wait_for_event()
struct timeval timeout = { 0, 0 };
if (!m_timers.is_empty())
get_next_timer_expiration(timeout);
ASSERT(m_unprocessed_messages.is_empty());
int rc = select(max_fd + 1, &rfds, &wfds, nullptr, (m_queued_events.is_empty() && m_timers.is_empty()) ? nullptr : &timeout);
if (rc < 0) {
ASSERT_NOT_REACHED();
@ -260,9 +264,16 @@ void GEventLoop::wait_for_event()
bool success = drain_messages_from_server();
ASSERT(success);
}
void GEventLoop::process_unprocessed_messages()
{
auto unprocessed_events = move(m_unprocessed_messages);
for (auto& event : unprocessed_events) {
if (event.type == WSAPI_ServerMessage::Type::Greeting) {
m_server_pid = event.greeting.server_pid;
continue;
}
if (event.type == WSAPI_ServerMessage::Error) {
dbgprintf("GEventLoop got error message from server\n");
@ -315,6 +326,9 @@ void GEventLoop::wait_for_event()
break;
}
}
if (!m_unprocessed_messages.is_empty())
process_unprocessed_messages();
}
bool GEventLoop::drain_messages_from_server()

View file

@ -39,9 +39,12 @@ public:
WSAPI_ServerMessage sync_request(const WSAPI_ClientMessage& request, WSAPI_ServerMessage::Type response_type);
pid_t server_pid() const { return m_server_pid; }
private:
void wait_for_event();
bool drain_messages_from_server();
void process_unprocessed_messages();
void handle_paint_event(const WSAPI_ServerMessage&, GWindow&);
void handle_resize_event(const WSAPI_ServerMessage&, GWindow&);
void handle_mouse_event(const WSAPI_ServerMessage&, GWindow&);
@ -64,8 +67,8 @@ private:
bool m_running { false };
bool m_exit_requested { false };
int m_exit_code { 0 };
int m_next_timer_id { 1 };
pid_t m_server_pid { 0 };
struct EventLoopTimer {
int timer_id { 0 };

View file

@ -28,11 +28,14 @@ void GWidget::set_relative_rect(const Rect& rect)
{
if (rect == m_relative_rect)
return;
if (m_relative_rect.size() != rect.size()) {
auto event = make<GResizeEvent>(m_relative_rect.size(), rect.size());
GEventLoop::main().post_event(this, move(event));
}
bool size_changed = m_relative_rect.size() != rect.size();
m_relative_rect = rect;
if (size_changed) {
GResizeEvent resize_event(m_relative_rect.size(), rect.size());
event(resize_event);
}
update();
}

View file

@ -169,9 +169,36 @@ void GWindow::event(GEvent& event)
return;
auto& paint_event = static_cast<GPaintEvent&>(event);
auto rect = paint_event.rect();
if (rect.is_empty())
bool created_new_backing_store = !m_backing;
if (!m_backing) {
// NOTE: size() may change at any time since it's synchronously retrieved from the WindowServer.
ASSERT(GEventLoop::main().server_pid());
Size new_backing_store_size = size();
size_t size_in_bytes = new_backing_store_size.area() * sizeof(RGBA32);
void* buffer;
int shared_buffer_id = create_shared_buffer(GEventLoop::main().server_pid(), size_in_bytes, (void**)&buffer);
ASSERT(shared_buffer_id >= 0);
ASSERT(buffer);
ASSERT(buffer != (void*)-1);
m_backing = GraphicsBitmap::create_with_shared_buffer(
m_has_alpha_channel ? GraphicsBitmap::Format::RGBA32 : GraphicsBitmap::Format::RGB32,
shared_buffer_id,
new_backing_store_size, (RGBA32*)buffer);
}
if (rect.is_empty() || created_new_backing_store)
rect = m_main_widget->rect();
m_main_widget->event(*make<GPaintEvent>(rect));
if (created_new_backing_store) {
WSAPI_ClientMessage message;
message.type = WSAPI_ClientMessage::Type::SetWindowBackingStore;
message.window_id = m_window_id;
message.backing.bpp = 32;
message.backing.pitch = m_backing->pitch();
message.backing.shared_buffer_id = m_backing->shared_buffer_id();
message.backing.has_alpha_channel = m_backing->has_alpha_channel();
message.backing.size = m_backing->size();
GEventLoop::main().post_message_to_server(message);
}
if (m_window_id) {
WSAPI_ClientMessage message;
message.type = WSAPI_ClientMessage::Type::DidFinishPainting;
@ -210,6 +237,7 @@ void GWindow::event(GEvent& event)
}
if (event.type() == GEvent::Resize) {
m_backing = nullptr;
m_pending_paint_event_rects.clear();
m_rect_when_windowless = { { }, static_cast<GResizeEvent&>(event).size() };
m_main_widget->set_relative_rect({ { }, static_cast<GResizeEvent&>(event).size() });
@ -233,7 +261,7 @@ void GWindow::update(const Rect& a_rect)
#ifdef UPDATE_COALESCING_DEBUG
dbgprintf("Ignoring %s since it's contained by pending rect %s\n", a_rect.to_string().characters(), pending_rect.to_string().characters());
#endif
return;
//return;
}
}
m_pending_paint_event_rects.append(a_rect);

View file

@ -68,6 +68,8 @@ public:
const GWidget* hovered_widget() const { return m_hovered_widget.ptr(); }
void set_hovered_widget(GWidget*);
GraphicsBitmap* backing() { return m_backing.ptr(); }
private:
virtual const char* class_name() const override { return "GWindow"; }