diff --git a/Userland/Libraries/LibGUI/Window.cpp b/Userland/Libraries/LibGUI/Window.cpp index 5fd2625dc4..e89bfffce6 100644 --- a/Userland/Libraries/LibGUI/Window.cpp +++ b/Userland/Libraries/LibGUI/Window.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -48,10 +49,13 @@ namespace GUI { +static i32 s_next_backing_store_serial; + class WindowBackingStore { public: WindowBackingStore(NonnullRefPtr bitmap) : m_bitmap(bitmap) + , m_serial(++s_next_backing_store_serial) { } @@ -60,8 +64,11 @@ public: Gfx::IntSize size() const { return m_bitmap->size(); } + i32 serial() const { return m_serial; } + private: NonnullRefPtr m_bitmap; + const i32 m_serial; }; static NeverDestroyed> all_windows; @@ -351,7 +358,7 @@ void Window::handle_multi_paint_event(MultiPaintEvent& event) m_back_store = create_backing_store(event.window_size()); ASSERT(m_back_store); } else if (m_double_buffering_enabled) { - bool still_has_pixels = m_back_store->bitmap().shared_buffer()->set_nonvolatile(); + bool still_has_pixels = m_back_store->bitmap().set_nonvolatile(); if (!still_has_pixels) { m_back_store = create_backing_store(event.window_size()); ASSERT(m_back_store); @@ -678,7 +685,7 @@ void Window::set_hovered_widget(Widget* widget) void Window::set_current_backing_store(WindowBackingStore& backing_store, bool flush_immediately) { auto& bitmap = backing_store.bitmap(); - WindowServerConnection::the().send_sync(m_window_id, 32, bitmap.pitch(), bitmap.shbuf_id(), bitmap.has_alpha_channel(), bitmap.size(), flush_immediately); + WindowServerConnection::the().send_sync(m_window_id, 32, bitmap.pitch(), bitmap.anon_fd(), backing_store.serial(), bitmap.has_alpha_channel(), bitmap.size(), flush_immediately); } void Window::flip(const Vector& dirty_rects) @@ -691,7 +698,7 @@ void Window::flip(const Vector& dirty_rects) m_back_store = create_backing_store(m_front_store->size()); ASSERT(m_back_store); memcpy(m_back_store->bitmap().scanline(0), m_front_store->bitmap().scanline(0), m_front_store->bitmap().size_in_bytes()); - m_back_store->bitmap().shared_buffer()->set_volatile(); + m_back_store->bitmap().set_volatile(); return; } @@ -700,7 +707,7 @@ void Window::flip(const Vector& dirty_rects) for (auto& dirty_rect : dirty_rects) painter.blit(dirty_rect.location(), m_front_store->bitmap(), dirty_rect); - m_back_store->bitmap().shared_buffer()->set_volatile(); + m_back_store->bitmap().set_volatile(); } RefPtr Window::create_shared_bitmap(Gfx::BitmapFormat format, const Gfx::IntSize& size) @@ -718,7 +725,18 @@ RefPtr Window::create_shared_bitmap(Gfx::BitmapFormat format, const OwnPtr Window::create_backing_store(const Gfx::IntSize& size) { auto format = m_has_alpha_channel ? Gfx::BitmapFormat::RGBA32 : Gfx::BitmapFormat::RGB32; - auto bitmap = create_shared_bitmap(format, size); + + ASSERT(!size.is_empty()); + size_t pitch = Gfx::Bitmap::minimum_pitch(size.width(), format); + size_t size_in_bytes = size.height() * pitch; + + auto anon_fd = anon_create(round_up_to_power_of_two(size_in_bytes, PAGE_SIZE), O_CLOEXEC); + if (anon_fd < 0) { + perror("anon_create"); + return {}; + } + + auto bitmap = Gfx::Bitmap::create_with_anon_fd(format, anon_fd, size, Gfx::Bitmap::ShouldCloseAnonymousFile::No); if (!bitmap) return {}; return make(bitmap.release_nonnull()); @@ -870,9 +888,9 @@ void Window::notify_state_changed(Badge, bool minimized, if (!store) return; if (minimized || occluded) { - store->bitmap().shared_buffer()->set_volatile(); + store->bitmap().set_volatile(); } else { - if (!store->bitmap().shared_buffer()->set_nonvolatile()) { + if (!store->bitmap().set_nonvolatile()) { store = nullptr; update(); } diff --git a/Userland/Services/WindowServer/ClientConnection.cpp b/Userland/Services/WindowServer/ClientConnection.cpp index f0e4402d81..33ce6e9bcb 100644 --- a/Userland/Services/WindowServer/ClientConnection.cpp +++ b/Userland/Services/WindowServer/ClientConnection.cpp @@ -571,17 +571,15 @@ OwnPtr ClientConnection:: return {}; } auto& window = *(*it).value; - if (window.last_backing_store() && window.last_backing_store()->shbuf_id() == message.shbuf_id()) { + if (window.last_backing_store() && window.last_backing_store_serial() == message.serial()) { window.swap_backing_stores(); } else { - auto shared_buffer = SharedBuffer::create_from_shbuf_id(message.shbuf_id()); - if (!shared_buffer) - return make(); - auto backing_store = Gfx::Bitmap::create_with_shared_buffer( + auto backing_store = Gfx::Bitmap::create_with_anon_fd( message.has_alpha_channel() ? Gfx::BitmapFormat::RGBA32 : Gfx::BitmapFormat::RGB32, - *shared_buffer, - message.size()); - window.set_backing_store(move(backing_store)); + message.anon_file().take_fd(), + message.size(), + Gfx::Bitmap::ShouldCloseAnonymousFile::Yes); + window.set_backing_store(move(backing_store), message.serial()); } if (message.flush_immediately()) diff --git a/Userland/Services/WindowServer/Window.h b/Userland/Services/WindowServer/Window.h index 286d543cc4..c2c54311d5 100644 --- a/Userland/Services/WindowServer/Window.h +++ b/Userland/Services/WindowServer/Window.h @@ -190,18 +190,23 @@ public: const Gfx::Bitmap* backing_store() const { return m_backing_store.ptr(); } Gfx::Bitmap* backing_store() { return m_backing_store.ptr(); } - void set_backing_store(RefPtr&& backing_store) + void set_backing_store(RefPtr backing_store, i32 serial) { m_last_backing_store = move(m_backing_store); m_backing_store = move(backing_store); + + m_last_backing_store_serial = m_backing_store_serial; + m_backing_store_serial = serial; } void swap_backing_stores() { swap(m_backing_store, m_last_backing_store); + swap(m_backing_store_serial, m_last_backing_store_serial); } Gfx::Bitmap* last_backing_store() { return m_last_backing_store.ptr(); } + i32 last_backing_store_serial() const { return m_last_backing_store_serial; } void set_global_cursor_tracking_enabled(bool); void set_automatic_cursor_tracking_enabled(bool enabled) { m_automatic_cursor_tracking_enabled = enabled; } @@ -340,6 +345,8 @@ private: bool m_occluded { false }; RefPtr m_backing_store; RefPtr m_last_backing_store; + i32 m_backing_store_serial { -1 }; + i32 m_last_backing_store_serial { -1 }; int m_window_id { -1 }; i32 m_client_id { -1 }; float m_opacity { 1 }; diff --git a/Userland/Services/WindowServer/WindowServer.ipc b/Userland/Services/WindowServer/WindowServer.ipc index 72399de1db..20f4d946bd 100644 --- a/Userland/Services/WindowServer/WindowServer.ipc +++ b/Userland/Services/WindowServer/WindowServer.ipc @@ -68,7 +68,7 @@ endpoint WindowServer = 2 SetGlobalCursorTracking(i32 window_id, bool enabled) => () SetWindowOpacity(i32 window_id, float opacity) => () - SetWindowBackingStore(i32 window_id, i32 bpp, i32 pitch, i32 shbuf_id, bool has_alpha_channel, Gfx::IntSize size, bool flush_immediately) => () + SetWindowBackingStore(i32 window_id, i32 bpp, i32 pitch, IPC::File anon_file, i32 serial, bool has_alpha_channel, Gfx::IntSize size, bool flush_immediately) => () WM_SetActiveWindow(i32 client_id, i32 window_id) =| WM_SetWindowMinimized(i32 client_id, i32 window_id, bool minimized) =| diff --git a/Userland/Services/WindowServer/main.cpp b/Userland/Services/WindowServer/main.cpp index ca8d997f0d..917db89646 100644 --- a/Userland/Services/WindowServer/main.cpp +++ b/Userland/Services/WindowServer/main.cpp @@ -39,7 +39,7 @@ int main(int, char**) { - if (pledge("stdio video thread shared_buffer accept rpath wpath cpath unix proc fattr sigaction", nullptr) < 0) { + if (pledge("stdio video thread recvfd shared_buffer accept rpath wpath cpath unix proc fattr sigaction", nullptr) < 0) { perror("pledge"); return 1; } @@ -84,7 +84,7 @@ int main(int, char**) WindowServer::EventLoop loop; - if (pledge("stdio video thread shared_buffer accept rpath wpath cpath proc", nullptr) < 0) { + if (pledge("stdio video thread recvfd shared_buffer accept rpath wpath cpath proc", nullptr) < 0) { perror("pledge"); return 1; }