mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-04 05:20:30 +00:00
Everywhere: Use IOSurface as backing store on macOS
Using mmap-allocated memory for backing stores does not allow us to benefit from using GPU-accelerated painting, because all the performance increase we get is mostly negated by reading the GPU-allocated texture back into RAM, so it can be shared with the browser process. With IOSurface, we get a framebuffer that is both shareable between processes and can be used as underlying memory for an OpenGL/Metal texture. This change does not yet benefit from using IOSurface and merely wraps them into Gfx::Bitmap to be used by the CPU painter.
This commit is contained in:
parent
e37071ae05
commit
c92f8ab1ea
Notes:
sideshowbarker
2024-07-16 20:51:53 +09:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/LadybirdBrowser/ladybird/commit/c92f8ab1ea Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/233 Reviewed-by: https://github.com/ADKaster Reviewed-by: https://github.com/bugaevc
15 changed files with 266 additions and 56 deletions
|
@ -18,6 +18,8 @@
|
|||
#include <LibWebView/Database.h>
|
||||
#include <LibWebView/ProcessManager.h>
|
||||
#include <LibWebView/URL.h>
|
||||
#include <LibWebView/ViewImplementation.h>
|
||||
#include <LibWebView/WebContentClient.h>
|
||||
|
||||
#import <Application/Application.h>
|
||||
#import <Application/ApplicationDelegate.h>
|
||||
|
@ -123,6 +125,10 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
mach_port_server->on_receive_child_mach_port = [](auto pid, auto port) {
|
||||
WebView::ProcessManager::the().add_process(pid, move(port));
|
||||
};
|
||||
mach_port_server->on_receive_backing_stores = [](Ladybird::MachPortServer::BackingStoresMessage message) {
|
||||
auto view = WebView::WebContentClient::view_for_pid_and_page_id(message.pid, message.page_id);
|
||||
view->did_allocate_iosurface_backing_stores(message.front_backing_store_id, move(message.front_backing_store_port), message.back_backing_store_id, move(message.back_backing_store_port));
|
||||
};
|
||||
|
||||
auto database = TRY(WebView::Database::create());
|
||||
auto cookie_jar = TRY(WebView::CookieJar::create(*database));
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "MachPortServer.h"
|
||||
#include <AK/Debug.h>
|
||||
#include <LibCore/Platform/MachMessageTypes.h>
|
||||
#include <LibCore/Platform/ProcessStatisticsMach.h>
|
||||
|
||||
namespace Ladybird {
|
||||
|
@ -55,8 +56,7 @@ ErrorOr<void> MachPortServer::allocate_server_port()
|
|||
void MachPortServer::thread_loop()
|
||||
{
|
||||
while (!m_should_stop.load(MemoryOrder::memory_order_acquire)) {
|
||||
|
||||
Core::Platform::ParentPortMessage message {};
|
||||
Core::Platform::ReceivedMachMessage message {};
|
||||
|
||||
// Get the pid of the child from the audit trailer so we can associate the port w/it
|
||||
mach_msg_options_t const options = MACH_RCV_MSG | MACH_RCV_TRAILER_TYPE(MACH_RCV_TRAILER_AUDIT) | MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT);
|
||||
|
@ -68,23 +68,38 @@ void MachPortServer::thread_loop()
|
|||
break;
|
||||
}
|
||||
|
||||
if (message.header.msgh_id != Core::Platform::SELF_TASK_PORT_MESSAGE_ID) {
|
||||
dbgln("Received message with id {}, ignoring", message.header.msgh_id);
|
||||
if (message.header.msgh_id == Core::Platform::BACKING_STORE_IOSURFACES_MESSAGE_ID) {
|
||||
auto pid = static_cast<pid_t>(message.body.parent_iosurface.trailer.msgh_audit.val[5]);
|
||||
auto const& backing_stores_message = message.body.parent_iosurface;
|
||||
auto front_child_port = Core::MachPort::adopt_right(backing_stores_message.front_descriptor.name, Core::MachPort::PortRight::Send);
|
||||
auto back_child_port = Core::MachPort::adopt_right(backing_stores_message.back_descriptor.name, Core::MachPort::PortRight::Send);
|
||||
auto const& metadata = backing_stores_message.metadata;
|
||||
if (on_receive_backing_stores)
|
||||
on_receive_backing_stores({ .pid = pid,
|
||||
.page_id = metadata.page_id,
|
||||
.front_backing_store_id = metadata.front_backing_store_id,
|
||||
.back_backing_store_id = metadata.back_backing_store_id,
|
||||
.front_backing_store_port = move(front_child_port),
|
||||
.back_backing_store_port = move(back_child_port) });
|
||||
continue;
|
||||
}
|
||||
|
||||
if (MACH_MSGH_BITS_LOCAL(message.header.msgh_bits) != MACH_MSG_TYPE_MOVE_SEND) {
|
||||
dbgln("Received message with invalid local port rights {}, ignoring", MACH_MSGH_BITS_LOCAL(message.header.msgh_bits));
|
||||
if (message.header.msgh_id == Core::Platform::SELF_TASK_PORT_MESSAGE_ID) {
|
||||
if (MACH_MSGH_BITS_LOCAL(message.header.msgh_bits) != MACH_MSG_TYPE_MOVE_SEND) {
|
||||
dbgln("Received message with invalid local port rights {}, ignoring", MACH_MSGH_BITS_LOCAL(message.header.msgh_bits));
|
||||
continue;
|
||||
}
|
||||
|
||||
auto const& task_port_message = message.body.parent;
|
||||
auto pid = static_cast<pid_t>(task_port_message.trailer.msgh_audit.val[5]);
|
||||
auto child_port = Core::MachPort::adopt_right(task_port_message.port_descriptor.name, Core::MachPort::PortRight::Send);
|
||||
dbgln_if(MACH_PORT_DEBUG, "Received child port {:x} from pid {}", child_port.port(), pid);
|
||||
if (on_receive_child_mach_port)
|
||||
on_receive_child_mach_port(pid, move(child_port));
|
||||
continue;
|
||||
}
|
||||
|
||||
auto pid = static_cast<pid_t>(message.trailer.msgh_audit.val[5]);
|
||||
auto child_port = Core::MachPort::adopt_right(message.port_descriptor.name, Core::MachPort::PortRight::Send);
|
||||
dbgln_if(MACH_PORT_DEBUG, "Received child port {:x} from pid {}", child_port.port(), pid);
|
||||
|
||||
if (on_receive_child_mach_port)
|
||||
on_receive_child_mach_port(pid, move(child_port));
|
||||
dbgln("Received message with id {}, ignoring", message.header.msgh_id);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,6 +31,15 @@ public:
|
|||
bool is_initialized();
|
||||
|
||||
Function<void(pid_t, Core::MachPort)> on_receive_child_mach_port;
|
||||
struct BackingStoresMessage {
|
||||
pid_t pid { -1 };
|
||||
u64 page_id { 0 };
|
||||
i32 front_backing_store_id { 0 };
|
||||
i32 back_backing_store_id { 0 };
|
||||
Core::MachPort front_backing_store_port;
|
||||
Core::MachPort back_backing_store_port;
|
||||
};
|
||||
Function<void(BackingStoresMessage)> on_receive_backing_stores;
|
||||
|
||||
ByteString const& server_port_name() const { return m_server_port_name; }
|
||||
|
||||
|
|
|
@ -150,6 +150,10 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
mach_port_server->on_receive_child_mach_port = [](auto pid, auto port) {
|
||||
WebView::ProcessManager::the().add_process(pid, move(port));
|
||||
};
|
||||
mach_port_server->on_receive_backing_stores = [](Ladybird::MachPortServer::BackingStoresMessage message) {
|
||||
auto view = WebView::WebContentClient::view_for_pid_and_page_id(message.pid, message.page_id);
|
||||
view->did_allocate_iosurface_backing_stores(message.front_backing_store_id, move(message.front_backing_store_port), message.back_backing_store_id, move(message.back_backing_store_port));
|
||||
};
|
||||
#endif
|
||||
|
||||
RefPtr<WebView::Database> database;
|
||||
|
|
|
@ -148,7 +148,8 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
|
||||
#if defined(AK_OS_MACOS)
|
||||
if (!mach_server_name.is_empty()) {
|
||||
Core::Platform::register_with_mach_server(mach_server_name);
|
||||
auto server_port = Core::Platform::register_with_mach_server(mach_server_name);
|
||||
WebContent::BackingStoreManager::set_browser_mach_port(move(server_port));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -49,4 +49,8 @@ class UDPSocket;
|
|||
|
||||
enum class TimerShouldFireWhenNotVisible;
|
||||
|
||||
#ifdef AK_OS_MACH
|
||||
class MachPort;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
65
Userland/Libraries/LibCore/Platform/MachMessageTypes.h
Normal file
65
Userland/Libraries/LibCore/Platform/MachMessageTypes.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Andrew Kaster <akaster@serenityos.org>
|
||||
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Platform.h>
|
||||
|
||||
#if !defined(AK_OS_MACH)
|
||||
# error "This file is only available on Mach platforms"
|
||||
#endif
|
||||
|
||||
#include <mach/mach.h>
|
||||
|
||||
namespace Core::Platform {
|
||||
|
||||
struct MessageBodyWithSelfTaskPort {
|
||||
mach_msg_body_t body;
|
||||
mach_msg_port_descriptor_t port_descriptor;
|
||||
mach_msg_audit_trailer_t trailer;
|
||||
};
|
||||
|
||||
struct MessageWithSelfTaskPort {
|
||||
mach_msg_header_t header;
|
||||
mach_msg_body_t body;
|
||||
mach_msg_port_descriptor_t port_descriptor;
|
||||
};
|
||||
|
||||
struct BackingStoreMetadata {
|
||||
u64 page_id { 0 };
|
||||
i32 back_backing_store_id { 0 };
|
||||
i32 front_backing_store_id { 0 };
|
||||
};
|
||||
|
||||
struct MessageBodyWithBackingStores {
|
||||
mach_msg_body_t body;
|
||||
mach_msg_port_descriptor_t front_descriptor;
|
||||
mach_msg_port_descriptor_t back_descriptor;
|
||||
BackingStoreMetadata metadata;
|
||||
mach_msg_audit_trailer_t trailer;
|
||||
};
|
||||
|
||||
struct MessageWithBackingStores {
|
||||
mach_msg_header_t header;
|
||||
mach_msg_body_t body;
|
||||
mach_msg_port_descriptor_t front_descriptor;
|
||||
mach_msg_port_descriptor_t back_descriptor;
|
||||
BackingStoreMetadata metadata;
|
||||
};
|
||||
|
||||
struct ReceivedMachMessage {
|
||||
mach_msg_header_t header;
|
||||
union {
|
||||
MessageBodyWithSelfTaskPort parent;
|
||||
MessageBodyWithBackingStores parent_iosurface;
|
||||
} body;
|
||||
};
|
||||
|
||||
static constexpr mach_msg_id_t SELF_TASK_PORT_MESSAGE_ID = 0x1234CAFE;
|
||||
static constexpr mach_msg_id_t BACKING_STORE_IOSURFACES_MESSAGE_ID = 0x1234CAFF;
|
||||
|
||||
}
|
|
@ -13,6 +13,7 @@
|
|||
#include <AK/ByteString.h>
|
||||
#include <AK/Time.h>
|
||||
#include <LibCore/MachPort.h>
|
||||
#include <LibCore/Platform/MachMessageTypes.h>
|
||||
#include <LibCore/Platform/ProcessStatisticsMach.h>
|
||||
|
||||
namespace Core::Platform {
|
||||
|
@ -75,17 +76,17 @@ ErrorOr<void> update_process_statistics(ProcessStatistics& statistics)
|
|||
return {};
|
||||
}
|
||||
|
||||
void register_with_mach_server(ByteString const& server_name)
|
||||
MachPort register_with_mach_server(ByteString const& server_name)
|
||||
{
|
||||
auto server_port_or_error = Core::MachPort::look_up_from_bootstrap_server(server_name);
|
||||
if (server_port_or_error.is_error()) {
|
||||
dbgln("Failed to lookup server port: {}", server_port_or_error.error());
|
||||
return;
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
auto server_port = server_port_or_error.release_value();
|
||||
|
||||
// Send our own task port to the server so they can query statistics about us
|
||||
ChildPortMessage message {};
|
||||
MessageWithSelfTaskPort message {};
|
||||
message.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSGH_BITS_ZERO) | MACH_MSGH_BITS_COMPLEX;
|
||||
message.header.msgh_size = sizeof(message);
|
||||
message.header.msgh_remote_port = server_port.port();
|
||||
|
@ -101,8 +102,10 @@ void register_with_mach_server(ByteString const& server_name)
|
|||
auto const send_result = mach_msg(&message.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, message.header.msgh_size, 0, MACH_PORT_NULL, timeout, MACH_PORT_NULL);
|
||||
if (send_result != KERN_SUCCESS) {
|
||||
dbgln("Failed to send message to server: {}", mach_error_string(send_result));
|
||||
return;
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
return server_port;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,21 +17,6 @@
|
|||
|
||||
namespace Core::Platform {
|
||||
|
||||
struct ChildPortMessage {
|
||||
mach_msg_header_t header;
|
||||
mach_msg_body_t body;
|
||||
mach_msg_port_descriptor_t port_descriptor;
|
||||
};
|
||||
|
||||
struct ParentPortMessage {
|
||||
mach_msg_header_t header;
|
||||
mach_msg_body_t body;
|
||||
mach_msg_port_descriptor_t port_descriptor;
|
||||
mach_msg_audit_trailer_t trailer; // for the child's pid
|
||||
};
|
||||
|
||||
static constexpr mach_msg_id_t SELF_TASK_PORT_MESSAGE_ID = 0x1234CAFE;
|
||||
|
||||
void register_with_mach_server(ByteString const& server_name);
|
||||
MachPort register_with_mach_server(ByteString const& server_name);
|
||||
|
||||
}
|
||||
|
|
|
@ -12,6 +12,11 @@
|
|||
#include <LibWeb/Infra/Strings.h>
|
||||
#include <LibWebView/ViewImplementation.h>
|
||||
|
||||
#ifdef AK_OS_MACOS
|
||||
# include <LibCore/IOSurface.h>
|
||||
# include <LibCore/MachPort.h>
|
||||
#endif
|
||||
|
||||
namespace WebView {
|
||||
|
||||
ViewImplementation::ViewImplementation()
|
||||
|
@ -397,6 +402,32 @@ void ViewImplementation::did_allocate_backing_stores(Badge<WebContentClient>, i3
|
|||
m_client_state.back_bitmap.id = back_bitmap_id;
|
||||
}
|
||||
|
||||
#ifdef AK_OS_MACOS
|
||||
void ViewImplementation::did_allocate_iosurface_backing_stores(i32 front_id, Core::MachPort&& front_port, i32 back_id, Core::MachPort&& back_port)
|
||||
{
|
||||
if (m_client_state.has_usable_bitmap) {
|
||||
// NOTE: We keep the outgoing front bitmap as a backup so we have something to paint until we get a new one.
|
||||
m_backup_bitmap = m_client_state.front_bitmap.bitmap;
|
||||
m_backup_bitmap_size = m_client_state.front_bitmap.last_painted_size;
|
||||
}
|
||||
m_client_state.has_usable_bitmap = false;
|
||||
|
||||
auto front_iosurface = Core::IOSurfaceHandle::from_mach_port(move(front_port));
|
||||
auto back_iosurface = Core::IOSurfaceHandle::from_mach_port(move(back_port));
|
||||
|
||||
auto front_size = Gfx::IntSize { front_iosurface.width(), front_iosurface.height() };
|
||||
auto back_size = Gfx::IntSize { back_iosurface.width(), back_iosurface.height() };
|
||||
|
||||
auto front_bitmap = Gfx::Bitmap::create_wrapper(Gfx::BitmapFormat::BGRA8888, front_size, front_size.width() * front_iosurface.bytes_per_element(), front_iosurface.data(), [handle = move(front_iosurface)] {});
|
||||
auto back_bitmap = Gfx::Bitmap::create_wrapper(Gfx::BitmapFormat::BGRA8888, back_size, back_size.width() * back_iosurface.bytes_per_element(), back_iosurface.data(), [handle = move(back_iosurface)] {});
|
||||
|
||||
m_client_state.front_bitmap.bitmap = front_bitmap.release_value_but_fixme_should_propagate_errors();
|
||||
m_client_state.front_bitmap.id = front_id;
|
||||
m_client_state.back_bitmap.bitmap = back_bitmap.release_value_but_fixme_should_propagate_errors();
|
||||
m_client_state.back_bitmap.id = back_id;
|
||||
}
|
||||
#endif
|
||||
|
||||
void ViewImplementation::handle_resize()
|
||||
{
|
||||
client().async_set_viewport_size(page_id(), this->viewport_size());
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <AK/LexicalPath.h>
|
||||
#include <AK/Queue.h>
|
||||
#include <AK/String.h>
|
||||
#include <LibCore/Forward.h>
|
||||
#include <LibCore/Promise.h>
|
||||
#include <LibGfx/Forward.h>
|
||||
#include <LibGfx/StandardCursor.h>
|
||||
|
@ -118,6 +119,9 @@ public:
|
|||
void did_update_navigation_buttons_state(Badge<WebContentClient>, bool back_enabled, bool forward_enabled) const;
|
||||
|
||||
void did_allocate_backing_stores(Badge<WebContentClient>, i32 front_bitmap_id, Gfx::ShareableBitmap const&, i32 back_bitmap_id, Gfx::ShareableBitmap const&);
|
||||
#ifdef AK_OS_MACOS
|
||||
void did_allocate_iosurface_backing_stores(i32 front_bitmap_id, Core::MachPort&&, i32 back_bitmap_id, Core::MachPort&&);
|
||||
#endif
|
||||
|
||||
enum class ScreenshotType {
|
||||
Visible,
|
||||
|
|
|
@ -11,12 +11,29 @@
|
|||
|
||||
namespace WebView {
|
||||
|
||||
static HashTable<WebContentClient*> s_clients;
|
||||
|
||||
Optional<ViewImplementation&> WebContentClient::view_for_pid_and_page_id(pid_t pid, u64 page_id)
|
||||
{
|
||||
for (auto* client : s_clients) {
|
||||
if (client->m_process_handle.pid == pid)
|
||||
return client->view_for_page_id(page_id);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
WebContentClient::WebContentClient(NonnullOwnPtr<Core::LocalSocket> socket, ViewImplementation& view)
|
||||
: IPC::ConnectionToServer<WebContentClientEndpoint, WebContentServerEndpoint>(*this, move(socket))
|
||||
{
|
||||
s_clients.set(this);
|
||||
m_views.set(0, &view);
|
||||
}
|
||||
|
||||
WebContentClient::~WebContentClient()
|
||||
{
|
||||
s_clients.remove(this);
|
||||
}
|
||||
|
||||
void WebContentClient::die()
|
||||
{
|
||||
VERIFY(on_web_content_process_crash);
|
||||
|
|
|
@ -26,7 +26,10 @@ class WebContentClient final
|
|||
IPC_CLIENT_CONNECTION(WebContentClient, "/tmp/session/%sid/portal/webcontent"sv);
|
||||
|
||||
public:
|
||||
static Optional<ViewImplementation&> view_for_pid_and_page_id(pid_t pid, u64 page_id);
|
||||
|
||||
WebContentClient(NonnullOwnPtr<Core::LocalSocket>, ViewImplementation&);
|
||||
~WebContentClient();
|
||||
|
||||
void register_view(u64 page_id, ViewImplementation&);
|
||||
void unregister_view(u64 page_id);
|
||||
|
|
|
@ -9,8 +9,22 @@
|
|||
#include <WebContent/BackingStoreManager.h>
|
||||
#include <WebContent/PageClient.h>
|
||||
|
||||
#ifdef AK_OS_MACOS
|
||||
# include <LibCore/IOSurface.h>
|
||||
# include <LibCore/MachPort.h>
|
||||
# include <LibCore/Platform/MachMessageTypes.h>
|
||||
#endif
|
||||
|
||||
namespace WebContent {
|
||||
|
||||
#ifdef AK_OS_MACOS
|
||||
static Optional<Core::MachPort> s_browser_mach_port;
|
||||
void BackingStoreManager::set_browser_mach_port(Core::MachPort&& port)
|
||||
{
|
||||
s_browser_mach_port = move(port);
|
||||
}
|
||||
#endif
|
||||
|
||||
BackingStoreManager::BackingStoreManager(PageClient& page_client)
|
||||
: m_page_client(page_client)
|
||||
{
|
||||
|
@ -24,10 +38,71 @@ void BackingStoreManager::restart_resize_timer()
|
|||
m_backing_store_shrink_timer->restart();
|
||||
}
|
||||
|
||||
void BackingStoreManager::reallocate_backing_stores(Gfx::IntSize size)
|
||||
{
|
||||
#ifdef AK_OS_MACOS
|
||||
if (s_browser_mach_port.has_value()) {
|
||||
auto back_iosurface = Core::IOSurfaceHandle::create(size.width(), size.height());
|
||||
auto back_iosurface_port = back_iosurface.create_mach_port();
|
||||
|
||||
auto front_iosurface = Core::IOSurfaceHandle::create(size.width(), size.height());
|
||||
auto front_iosurface_port = front_iosurface.create_mach_port();
|
||||
|
||||
m_front_bitmap_id = m_next_bitmap_id++;
|
||||
m_back_bitmap_id = m_next_bitmap_id++;
|
||||
|
||||
m_front_bitmap = Gfx::Bitmap::create_wrapper(Gfx::BitmapFormat::BGRA8888, size, size.width() * front_iosurface.bytes_per_element(), front_iosurface.data(), [handle = move(front_iosurface)] {}).release_value();
|
||||
m_back_bitmap = Gfx::Bitmap::create_wrapper(Gfx::BitmapFormat::BGRA8888, size, size.width() * back_iosurface.bytes_per_element(), back_iosurface.data(), [handle = move(back_iosurface)] {}).release_value();
|
||||
|
||||
Core::Platform::BackingStoreMetadata metadata;
|
||||
metadata.page_id = m_page_client.m_id;
|
||||
metadata.front_backing_store_id = m_front_bitmap_id;
|
||||
metadata.back_backing_store_id = m_back_bitmap_id;
|
||||
|
||||
Core::Platform::MessageWithBackingStores message;
|
||||
|
||||
message.header.msgh_remote_port = s_browser_mach_port->port();
|
||||
message.header.msgh_local_port = MACH_PORT_NULL;
|
||||
message.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0) | MACH_MSGH_BITS_COMPLEX;
|
||||
message.header.msgh_size = sizeof(message);
|
||||
message.header.msgh_id = Core::Platform::BACKING_STORE_IOSURFACES_MESSAGE_ID;
|
||||
|
||||
message.body.msgh_descriptor_count = 2;
|
||||
|
||||
message.front_descriptor.name = front_iosurface_port.release();
|
||||
message.front_descriptor.disposition = MACH_MSG_TYPE_MOVE_SEND;
|
||||
message.front_descriptor.type = MACH_MSG_PORT_DESCRIPTOR;
|
||||
|
||||
message.back_descriptor.name = back_iosurface_port.release();
|
||||
message.back_descriptor.disposition = MACH_MSG_TYPE_MOVE_SEND;
|
||||
message.back_descriptor.type = MACH_MSG_PORT_DESCRIPTOR;
|
||||
|
||||
message.metadata = metadata;
|
||||
|
||||
mach_msg_timeout_t const timeout = 100; // milliseconds
|
||||
auto const send_result = mach_msg(&message.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, message.header.msgh_size, 0, MACH_PORT_NULL, timeout, MACH_PORT_NULL);
|
||||
if (send_result != KERN_SUCCESS) {
|
||||
dbgln("Failed to send message to server: {}", mach_error_string(send_result));
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
m_front_bitmap_id = m_next_bitmap_id++;
|
||||
m_back_bitmap_id = m_next_bitmap_id++;
|
||||
|
||||
m_front_bitmap = Gfx::Bitmap::create_shareable(Gfx::BitmapFormat::BGRA8888, size).release_value();
|
||||
m_back_bitmap = Gfx::Bitmap::create_shareable(Gfx::BitmapFormat::BGRA8888, size).release_value();
|
||||
|
||||
m_page_client.page_did_allocate_backing_stores(m_front_bitmap_id, m_front_bitmap->to_shareable_bitmap(), m_back_bitmap_id, m_back_bitmap->to_shareable_bitmap());
|
||||
}
|
||||
|
||||
void BackingStoreManager::resize_backing_stores_if_needed(WindowResizingInProgress window_resize_in_progress)
|
||||
{
|
||||
auto css_pixels_viewport_rect = m_page_client.page().top_level_traversable()->viewport_rect();
|
||||
auto viewport_size = m_page_client.page().css_to_device_rect(css_pixels_viewport_rect).size();
|
||||
auto css_pixels_viewpor_rect = m_page_client.page().top_level_traversable()->viewport_rect();
|
||||
auto viewport_size = m_page_client.page().css_to_device_rect(css_pixels_viewpor_rect).size();
|
||||
|
||||
if (viewport_size.is_empty())
|
||||
return;
|
||||
|
@ -43,26 +118,8 @@ void BackingStoreManager::resize_backing_stores_if_needed(WindowResizingInProgre
|
|||
m_back_bitmap.clear();
|
||||
}
|
||||
|
||||
auto old_front_bitmap_id = m_front_bitmap_id;
|
||||
auto old_back_bitmap_id = m_back_bitmap_id;
|
||||
|
||||
auto reallocate_backing_store_if_needed = [&](RefPtr<Gfx::Bitmap>& bitmap, int& id) {
|
||||
if (!bitmap || !bitmap->size().contains(minimum_needed_size.to_type<int>())) {
|
||||
if (auto new_bitmap_or_error = Gfx::Bitmap::create_shareable(Gfx::BitmapFormat::BGRA8888, minimum_needed_size.to_type<int>()); !new_bitmap_or_error.is_error()) {
|
||||
bitmap = new_bitmap_or_error.release_value();
|
||||
id = m_next_bitmap_id++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
reallocate_backing_store_if_needed(m_front_bitmap, m_front_bitmap_id);
|
||||
reallocate_backing_store_if_needed(m_back_bitmap, m_back_bitmap_id);
|
||||
|
||||
auto& front_bitmap = m_front_bitmap;
|
||||
auto& back_bitmap = m_back_bitmap;
|
||||
|
||||
if (m_front_bitmap_id != old_front_bitmap_id || m_back_bitmap_id != old_back_bitmap_id) {
|
||||
m_page_client.page_did_allocate_backing_stores(m_front_bitmap_id, front_bitmap->to_shareable_bitmap(), m_back_bitmap_id, back_bitmap->to_shareable_bitmap());
|
||||
if (!m_front_bitmap || !m_back_bitmap || !m_front_bitmap->size().contains(minimum_needed_size.to_type<int>())) {
|
||||
reallocate_backing_stores(minimum_needed_size.to_type<int>());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <LibCore/Forward.h>
|
||||
#include <LibWeb/Page/Page.h>
|
||||
#include <WebContent/Forward.h>
|
||||
|
||||
|
@ -13,11 +14,16 @@ namespace WebContent {
|
|||
|
||||
class BackingStoreManager {
|
||||
public:
|
||||
#ifdef AK_OS_MACOS
|
||||
static void set_browser_mach_port(Core::MachPort&&);
|
||||
#endif
|
||||
|
||||
enum class WindowResizingInProgress {
|
||||
No,
|
||||
Yes
|
||||
};
|
||||
void resize_backing_stores_if_needed(WindowResizingInProgress window_resize_in_progress);
|
||||
void reallocate_backing_stores(Gfx::IntSize);
|
||||
void restart_resize_timer();
|
||||
|
||||
RefPtr<Gfx::Bitmap> back_bitmap() { return m_back_bitmap; }
|
||||
|
|
Loading…
Reference in a new issue