LibGfx+LibWeb: Add Linux dmabuf backing stores to SharedImage
On Linux builds with Vulkan, WebContent already paints into GPU-backed Skia surfaces, but the backing store shared with the UI process was still a CPU ShareableBitmap. That forced every flush to read the GPU image back into a bitmap so the UI could sample it, defeating most of the benefit of GPU painting. Teach SharedImage to carry a LinuxDmaBufHandle alongside ShareableBitmap as a Variant, with a tagged IPC encoding and an fd clone on encode so both processes own an independent handle. When USE_VULKAN_DMABUF_IMAGES is enabled, BackingStoreManager now allocates the front/back buffers as linear-modifier Vulkan images and publishes their dmabuf fds to the UI; the Skia painting surfaces wrap those Vulkan images directly, so no readback is needed. The old shareable-bitmap path is preserved as a fallback for the non-Vulkan case and when image creation fails. On the receive side, SharedImageBuffer::import_from_shared_image mmaps a linear dmabuf to reconstruct a CPU Bitmap, keeping existing consumers that expect CPU access working unchanged. VulkanImage memory type selection is factored into a small helper, and linear images now request host-visible (cached if available) memory rather than device-local, since a linear dmabuf has to be CPU-mappable on the importer side.
This commit is contained in:
parent
0fdafaaf48
commit
9a4e731746
5 changed files with 272 additions and 50 deletions
|
|
@ -8,6 +8,9 @@
|
|||
#include <LibIPC/Attachment.h>
|
||||
#include <LibIPC/Decoder.h>
|
||||
#include <LibIPC/Encoder.h>
|
||||
#ifdef USE_VULKAN_DMABUF_IMAGES
|
||||
# include <LibGfx/VulkanImage.h>
|
||||
#endif
|
||||
|
||||
#ifdef AK_OS_MACOS
|
||||
static Core::MachPort copy_send_right(Core::MachPort const& port)
|
||||
|
|
@ -27,22 +30,97 @@ SharedImage::SharedImage(Core::MachPort&& port)
|
|||
}
|
||||
#else
|
||||
SharedImage::SharedImage(ShareableBitmap shareable_bitmap)
|
||||
: m_shareable_bitmap(move(shareable_bitmap))
|
||||
: m_data(move(shareable_bitmap))
|
||||
{
|
||||
}
|
||||
|
||||
SharedImage::SharedImage(LinuxDmaBufHandle&& dmabuf)
|
||||
: m_data(move(dmabuf))
|
||||
{
|
||||
}
|
||||
|
||||
# ifdef USE_VULKAN_DMABUF_IMAGES
|
||||
static constexpr auto shared_image_bitmap_format = BitmapFormat::BGRA8888;
|
||||
static constexpr auto shared_image_alpha_type = AlphaType::Premultiplied;
|
||||
|
||||
SharedImage duplicate_shared_image(VulkanImage const& vulkan_image)
|
||||
{
|
||||
return SharedImage { duplicate_linux_dmabuf_handle(vulkan_image) };
|
||||
}
|
||||
|
||||
LinuxDmaBufHandle duplicate_linux_dmabuf_handle(VulkanImage const& vulkan_image)
|
||||
{
|
||||
VERIFY(vulkan_image.info.format == VK_FORMAT_B8G8R8A8_UNORM);
|
||||
auto fd = vulkan_image.get_dma_buf_fd();
|
||||
VERIFY(fd >= 0);
|
||||
return LinuxDmaBufHandle {
|
||||
.bitmap_format = shared_image_bitmap_format,
|
||||
.alpha_type = shared_image_alpha_type,
|
||||
.size = IntSize(static_cast<int>(vulkan_image.info.extent.width), static_cast<int>(vulkan_image.info.extent.height)),
|
||||
.drm_format = vk_format_to_drm_format(vulkan_image.info.format),
|
||||
.pitch = static_cast<size_t>(vulkan_image.info.row_pitch),
|
||||
.modifier = vulkan_image.info.modifier,
|
||||
.file = IPC::File::adopt_fd(fd),
|
||||
};
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
namespace IPC {
|
||||
|
||||
#ifndef AK_OS_MACOS
|
||||
enum class SharedImageBackingType : u8 {
|
||||
ShareableBitmap,
|
||||
LinuxDmaBuf,
|
||||
};
|
||||
|
||||
template<>
|
||||
ErrorOr<void> encode(Encoder& encoder, Gfx::LinuxDmaBufHandle const& dmabuf)
|
||||
{
|
||||
TRY(encoder.encode(dmabuf.bitmap_format));
|
||||
TRY(encoder.encode(dmabuf.alpha_type));
|
||||
TRY(encoder.encode(dmabuf.size));
|
||||
TRY(encoder.encode(dmabuf.drm_format));
|
||||
TRY(encoder.encode(dmabuf.pitch));
|
||||
TRY(encoder.encode(dmabuf.modifier));
|
||||
TRY(encoder.encode(TRY(IPC::File::clone_fd(dmabuf.file.fd()))));
|
||||
return {};
|
||||
}
|
||||
|
||||
template<>
|
||||
ErrorOr<Gfx::LinuxDmaBufHandle> decode(Decoder& decoder)
|
||||
{
|
||||
return Gfx::LinuxDmaBufHandle {
|
||||
.bitmap_format = TRY(decoder.decode<Gfx::BitmapFormat>()),
|
||||
.alpha_type = TRY(decoder.decode<Gfx::AlphaType>()),
|
||||
.size = TRY(decoder.decode<Gfx::IntSize>()),
|
||||
.drm_format = TRY(decoder.decode<u32>()),
|
||||
.pitch = TRY(decoder.decode<size_t>()),
|
||||
.modifier = TRY(decoder.decode<u64>()),
|
||||
.file = TRY(decoder.decode<IPC::File>()),
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
template<>
|
||||
ErrorOr<void> encode(Encoder& encoder, Gfx::SharedImage const& shared_image)
|
||||
{
|
||||
#ifdef AK_OS_MACOS
|
||||
TRY(encoder.append_attachment(Attachment::from_mach_port(copy_send_right(shared_image.m_port), Core::MachPort::MessageRight::MoveSend)));
|
||||
#else
|
||||
TRY(encoder.encode(shared_image.m_shareable_bitmap));
|
||||
return shared_image.m_data.visit(
|
||||
[&](Gfx::ShareableBitmap const& shareable_bitmap) -> ErrorOr<void> {
|
||||
TRY(encoder.encode(SharedImageBackingType::ShareableBitmap));
|
||||
TRY(encoder.encode(shareable_bitmap));
|
||||
return {};
|
||||
},
|
||||
[&](Gfx::LinuxDmaBufHandle const& dmabuf) -> ErrorOr<void> {
|
||||
TRY(encoder.encode(SharedImageBackingType::LinuxDmaBuf));
|
||||
TRY(encoder.encode(dmabuf));
|
||||
return {};
|
||||
});
|
||||
#endif
|
||||
return {};
|
||||
}
|
||||
|
|
@ -55,9 +133,14 @@ ErrorOr<Gfx::SharedImage> decode(Decoder& decoder)
|
|||
VERIFY(attachment.message_right() == Core::MachPort::MessageRight::MoveSend);
|
||||
return Gfx::SharedImage { attachment.release_mach_port() };
|
||||
#else
|
||||
auto shareable_bitmap = TRY(decoder.decode<Gfx::ShareableBitmap>());
|
||||
VERIFY(shareable_bitmap.is_valid());
|
||||
return Gfx::SharedImage { move(shareable_bitmap) };
|
||||
switch (TRY(decoder.decode<SharedImageBackingType>())) {
|
||||
case SharedImageBackingType::ShareableBitmap:
|
||||
return Gfx::SharedImage { TRY(decoder.decode<Gfx::ShareableBitmap>()) };
|
||||
case SharedImageBackingType::LinuxDmaBuf:
|
||||
return Gfx::SharedImage { TRY(decoder.decode<Gfx::LinuxDmaBufHandle>()) };
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,18 +8,39 @@
|
|||
|
||||
#include <AK/Error.h>
|
||||
#include <AK/Noncopyable.h>
|
||||
#include <AK/Variant.h>
|
||||
#include <LibGfx/Bitmap.h>
|
||||
#include <LibGfx/Forward.h>
|
||||
#include <LibGfx/ShareableBitmap.h>
|
||||
#include <LibIPC/File.h>
|
||||
#include <LibIPC/Forward.h>
|
||||
|
||||
#ifdef AK_OS_MACOS
|
||||
# include <LibCore/MachPort.h>
|
||||
#else
|
||||
# include <LibGfx/ShareableBitmap.h>
|
||||
#endif
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
class SharedImageBuffer;
|
||||
|
||||
#ifndef AK_OS_MACOS
|
||||
struct LinuxDmaBufHandle {
|
||||
BitmapFormat bitmap_format;
|
||||
AlphaType alpha_type;
|
||||
IntSize size;
|
||||
u32 drm_format;
|
||||
size_t pitch;
|
||||
u64 modifier;
|
||||
IPC::File file;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef USE_VULKAN_DMABUF_IMAGES
|
||||
struct VulkanImage;
|
||||
SharedImage duplicate_shared_image(VulkanImage const&);
|
||||
LinuxDmaBufHandle duplicate_linux_dmabuf_handle(VulkanImage const&);
|
||||
#endif
|
||||
|
||||
class SharedImage {
|
||||
AK_MAKE_NONCOPYABLE(SharedImage);
|
||||
|
||||
|
|
@ -28,13 +49,18 @@ public:
|
|||
SharedImage& operator=(SharedImage&&) = default;
|
||||
~SharedImage() = default;
|
||||
|
||||
private:
|
||||
#ifdef AK_OS_MACOS
|
||||
explicit SharedImage(Core::MachPort&&);
|
||||
Core::MachPort m_port;
|
||||
#else
|
||||
explicit SharedImage(ShareableBitmap);
|
||||
ShareableBitmap m_shareable_bitmap;
|
||||
explicit SharedImage(LinuxDmaBufHandle&&);
|
||||
#endif
|
||||
|
||||
private:
|
||||
#ifdef AK_OS_MACOS
|
||||
Core::MachPort m_port;
|
||||
#else
|
||||
Variant<ShareableBitmap, LinuxDmaBufHandle> m_data;
|
||||
#endif
|
||||
|
||||
friend class SharedImageBuffer;
|
||||
|
|
@ -50,6 +76,14 @@ private:
|
|||
|
||||
namespace IPC {
|
||||
|
||||
#ifndef AK_OS_MACOS
|
||||
template<>
|
||||
ErrorOr<void> encode(Encoder&, Gfx::LinuxDmaBufHandle const&);
|
||||
|
||||
template<>
|
||||
ErrorOr<Gfx::LinuxDmaBufHandle> decode(Decoder&);
|
||||
#endif
|
||||
|
||||
template<>
|
||||
ErrorOr<void> encode(Encoder&, Gfx::SharedImage const&);
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,11 @@
|
|||
#include <LibGfx/Bitmap.h>
|
||||
#include <LibGfx/SharedImageBuffer.h>
|
||||
|
||||
#ifdef USE_VULKAN_DMABUF_IMAGES
|
||||
# include <libdrm/drm_fourcc.h>
|
||||
# include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
#ifdef AK_OS_MACOS
|
||||
|
|
@ -28,6 +33,23 @@ SharedImageBuffer::SharedImageBuffer(Core::IOSurfaceHandle&& iosurface_handle, N
|
|||
#else
|
||||
static constexpr auto shared_image_buffer_format = BitmapFormat::BGRA8888;
|
||||
static constexpr auto shared_image_buffer_alpha_type = AlphaType::Premultiplied;
|
||||
# ifdef USE_VULKAN_DMABUF_IMAGES
|
||||
static constexpr auto shared_image_buffer_drm_format = DRM_FORMAT_ARGB8888;
|
||||
|
||||
static NonnullRefPtr<Bitmap> create_bitmap_from_linux_dmabuf(LinuxDmaBufHandle const& dmabuf)
|
||||
{
|
||||
VERIFY(dmabuf.bitmap_format == shared_image_buffer_format);
|
||||
VERIFY(dmabuf.alpha_type == shared_image_buffer_alpha_type);
|
||||
VERIFY(dmabuf.drm_format == shared_image_buffer_drm_format);
|
||||
VERIFY(dmabuf.modifier == DRM_FORMAT_MOD_LINEAR);
|
||||
auto data_size = Bitmap::size_in_bytes(dmabuf.pitch, dmabuf.size.height());
|
||||
auto* data = ::mmap(nullptr, data_size, PROT_READ | PROT_WRITE, MAP_SHARED, dmabuf.file.fd(), 0);
|
||||
VERIFY(data != MAP_FAILED);
|
||||
return MUST(Bitmap::create_wrapper(dmabuf.bitmap_format, dmabuf.alpha_type, dmabuf.size, dmabuf.pitch, data, [data, data_size] {
|
||||
VERIFY(::munmap(data, data_size) == 0);
|
||||
}));
|
||||
}
|
||||
# endif
|
||||
|
||||
SharedImageBuffer::SharedImageBuffer(NonnullRefPtr<Bitmap> bitmap)
|
||||
: m_bitmap(move(bitmap))
|
||||
|
|
@ -53,9 +75,18 @@ SharedImageBuffer SharedImageBuffer::import_from_shared_image(SharedImage shared
|
|||
auto bitmap = create_bitmap_from_iosurface(iosurface_handle);
|
||||
return SharedImageBuffer(move(iosurface_handle), move(bitmap));
|
||||
#else
|
||||
auto* bitmap = shared_image.m_shareable_bitmap.bitmap();
|
||||
VERIFY(bitmap);
|
||||
return SharedImageBuffer(NonnullRefPtr { *bitmap });
|
||||
return shared_image.m_data.visit(
|
||||
[](ShareableBitmap& shareable_bitmap) -> SharedImageBuffer {
|
||||
return SharedImageBuffer(*shareable_bitmap.bitmap());
|
||||
},
|
||||
[](LinuxDmaBufHandle& dmabuf) -> SharedImageBuffer {
|
||||
# ifdef USE_VULKAN_DMABUF_IMAGES
|
||||
return SharedImageBuffer(create_bitmap_from_linux_dmabuf(dmabuf));
|
||||
# else
|
||||
(void)dmabuf;
|
||||
VERIFY_NOT_REACHED();
|
||||
# endif
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,12 +6,24 @@
|
|||
|
||||
#ifdef USE_VULKAN_DMABUF_IMAGES
|
||||
|
||||
# include <AK/Array.h>
|
||||
# include <AK/Format.h>
|
||||
# include <AK/Vector.h>
|
||||
# include <LibGfx/VulkanImage.h>
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
static uint32_t find_memory_type_index(VkPhysicalDeviceMemoryProperties const& memory_properties, VkMemoryRequirements const& memory_requirements, VkMemoryPropertyFlags required_flags)
|
||||
{
|
||||
for (uint32_t i = 0; i < memory_properties.memoryTypeCount; ++i) {
|
||||
auto const property_flags = memory_properties.memoryTypes[i].propertyFlags;
|
||||
if ((memory_requirements.memoryTypeBits & (1u << i)) && (property_flags & required_flags) == required_flags)
|
||||
return i;
|
||||
}
|
||||
|
||||
return memory_properties.memoryTypeCount;
|
||||
}
|
||||
|
||||
VulkanImage::~VulkanImage()
|
||||
{
|
||||
if (image != VK_NULL_HANDLE) {
|
||||
|
|
@ -151,12 +163,18 @@ ErrorOr<NonnullRefPtr<VulkanImage>> create_shared_vulkan_image(VulkanContext con
|
|||
vkGetImageMemoryRequirements(context.logical_device, image->image, &mem_reqs);
|
||||
VkPhysicalDeviceMemoryProperties mem_props;
|
||||
vkGetPhysicalDeviceMemoryProperties(context.physical_device, &mem_props);
|
||||
uint32_t mem_type_idx;
|
||||
for (mem_type_idx = 0; mem_type_idx < mem_props.memoryTypeCount; ++mem_type_idx) {
|
||||
if ((mem_reqs.memoryTypeBits & (1 << mem_type_idx)) && (mem_props.memoryTypes[mem_type_idx].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)) {
|
||||
break;
|
||||
bool const is_linear_image = format_mods.size() == 1 && format_mods[0] == DRM_FORMAT_MOD_LINEAR;
|
||||
uint32_t mem_type_idx = mem_props.memoryTypeCount;
|
||||
|
||||
if (is_linear_image) {
|
||||
mem_type_idx = find_memory_type_index(mem_props, mem_reqs, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT);
|
||||
if (mem_type_idx == mem_props.memoryTypeCount) {
|
||||
mem_type_idx = find_memory_type_index(mem_props, mem_reqs, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
}
|
||||
} else {
|
||||
mem_type_idx = find_memory_type_index(mem_props, mem_reqs, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
}
|
||||
|
||||
if (mem_type_idx == mem_props.memoryTypeCount) {
|
||||
return Error::from_string_literal("unable to find suitable image memory type");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/Array.h>
|
||||
#include <LibCore/Timer.h>
|
||||
#include <LibGfx/PaintingSurface.h>
|
||||
#include <LibGfx/SharedImageBuffer.h>
|
||||
|
|
@ -12,6 +13,10 @@
|
|||
#include <LibWeb/Painting/BackingStoreManager.h>
|
||||
#include <WebContent/PageClient.h>
|
||||
|
||||
#ifdef USE_VULKAN_DMABUF_IMAGES
|
||||
# include <LibGfx/VulkanImage.h>
|
||||
#endif
|
||||
|
||||
namespace Web::Painting {
|
||||
|
||||
GC_DEFINE_ALLOCATOR(BackingStoreManager);
|
||||
|
|
@ -35,56 +40,107 @@ void BackingStoreManager::restart_resize_timer()
|
|||
m_backing_store_shrink_timer->restart();
|
||||
}
|
||||
|
||||
void BackingStoreManager::reallocate_backing_stores(Gfx::IntSize size)
|
||||
static void publish_backing_store_pair_if_needed(HTML::Navigable& navigable, i32 front_bitmap_id, Gfx::SharedImage front_backing_store, i32 back_bitmap_id, Gfx::SharedImage back_backing_store)
|
||||
{
|
||||
auto skia_backend_context = Gfx::SkiaBackendContext::the();
|
||||
if (!navigable.is_top_level_traversable())
|
||||
return;
|
||||
|
||||
RefPtr<Gfx::PaintingSurface> front_store;
|
||||
RefPtr<Gfx::PaintingSurface> back_store;
|
||||
auto& page_client = navigable.top_level_traversable()->page().client();
|
||||
page_client.page_did_allocate_backing_stores(front_bitmap_id, move(front_backing_store), back_bitmap_id, move(back_backing_store));
|
||||
}
|
||||
|
||||
struct BackingStorePair {
|
||||
RefPtr<Gfx::PaintingSurface> front;
|
||||
RefPtr<Gfx::PaintingSurface> back;
|
||||
};
|
||||
|
||||
#ifdef USE_VULKAN
|
||||
static NonnullRefPtr<Gfx::PaintingSurface> create_gpu_painting_surface_with_bitmap_flush(Gfx::IntSize size, Gfx::SharedImageBuffer& buffer)
|
||||
{
|
||||
auto surface = Gfx::PaintingSurface::create_with_size(size, Gfx::BitmapFormat::BGRA8888, Gfx::AlphaType::Premultiplied);
|
||||
auto bitmap = buffer.bitmap();
|
||||
surface->on_flush = [bitmap = move(bitmap)](auto& surface) {
|
||||
surface.read_into_bitmap(*bitmap);
|
||||
};
|
||||
return surface;
|
||||
}
|
||||
#endif
|
||||
|
||||
static BackingStorePair create_shareable_bitmap_backing_stores(HTML::Navigable& navigable, Gfx::IntSize size, i32 front_bitmap_id, i32 back_bitmap_id, RefPtr<Gfx::SkiaBackendContext> const& skia_backend_context)
|
||||
{
|
||||
auto front_buffer = Gfx::SharedImageBuffer::create(size);
|
||||
auto back_buffer = Gfx::SharedImageBuffer::create(size);
|
||||
|
||||
m_front_bitmap_id = m_next_bitmap_id++;
|
||||
m_back_bitmap_id = m_next_bitmap_id++;
|
||||
|
||||
if (m_navigable->is_top_level_traversable()) {
|
||||
auto& page_client = m_navigable->top_level_traversable()->page().client();
|
||||
page_client.page_did_allocate_backing_stores(m_front_bitmap_id, front_buffer.export_shared_image(), m_back_bitmap_id, back_buffer.export_shared_image());
|
||||
}
|
||||
publish_backing_store_pair_if_needed(navigable, front_bitmap_id, front_buffer.export_shared_image(), back_bitmap_id, back_buffer.export_shared_image());
|
||||
|
||||
#ifdef AK_OS_MACOS
|
||||
if (skia_backend_context) {
|
||||
front_store = Gfx::PaintingSurface::create_from_shared_image_buffer(front_buffer, *skia_backend_context);
|
||||
back_store = Gfx::PaintingSurface::create_from_shared_image_buffer(back_buffer, *skia_backend_context);
|
||||
} else {
|
||||
front_store = Gfx::PaintingSurface::wrap_bitmap(*front_buffer.bitmap());
|
||||
back_store = Gfx::PaintingSurface::wrap_bitmap(*back_buffer.bitmap());
|
||||
return {
|
||||
.front = Gfx::PaintingSurface::create_from_shared_image_buffer(front_buffer, *skia_backend_context),
|
||||
.back = Gfx::PaintingSurface::create_from_shared_image_buffer(back_buffer, *skia_backend_context),
|
||||
};
|
||||
}
|
||||
#else
|
||||
# ifdef USE_VULKAN
|
||||
if (skia_backend_context) {
|
||||
front_store = Gfx::PaintingSurface::create_with_size(size, Gfx::BitmapFormat::BGRA8888, Gfx::AlphaType::Premultiplied);
|
||||
auto front_bitmap = front_buffer.bitmap();
|
||||
front_store->on_flush = [front_bitmap = move(front_bitmap)](auto& surface) {
|
||||
surface.read_into_bitmap(*front_bitmap);
|
||||
};
|
||||
back_store = Gfx::PaintingSurface::create_with_size(size, Gfx::BitmapFormat::BGRA8888, Gfx::AlphaType::Premultiplied);
|
||||
auto back_bitmap = back_buffer.bitmap();
|
||||
back_store->on_flush = [back_bitmap = move(back_bitmap)](auto& surface) {
|
||||
surface.read_into_bitmap(*back_bitmap);
|
||||
return {
|
||||
.front = create_gpu_painting_surface_with_bitmap_flush(size, front_buffer),
|
||||
.back = create_gpu_painting_surface_with_bitmap_flush(size, back_buffer),
|
||||
};
|
||||
}
|
||||
# else
|
||||
(void)skia_backend_context;
|
||||
# endif
|
||||
|
||||
if (!front_store)
|
||||
front_store = Gfx::PaintingSurface::wrap_bitmap(*front_buffer.bitmap());
|
||||
if (!back_store)
|
||||
back_store = Gfx::PaintingSurface::wrap_bitmap(*back_buffer.bitmap());
|
||||
#endif
|
||||
|
||||
m_allocated_size = size;
|
||||
return {
|
||||
.front = Gfx::PaintingSurface::wrap_bitmap(*front_buffer.bitmap()),
|
||||
.back = Gfx::PaintingSurface::wrap_bitmap(*back_buffer.bitmap()),
|
||||
};
|
||||
}
|
||||
|
||||
m_navigable->rendering_thread().update_backing_stores(front_store, back_store, m_front_bitmap_id, m_back_bitmap_id);
|
||||
#ifdef USE_VULKAN_DMABUF_IMAGES
|
||||
static ErrorOr<BackingStorePair> create_linear_dmabuf_backing_stores(HTML::Navigable& navigable, Gfx::IntSize size, i32 front_bitmap_id, i32 back_bitmap_id, Gfx::SkiaBackendContext& skia_backend_context)
|
||||
{
|
||||
VERIFY(navigable.is_top_level_traversable());
|
||||
|
||||
auto const& vulkan_context = skia_backend_context.vulkan_context();
|
||||
static constexpr Array<uint64_t, 1> linear_modifiers = { DRM_FORMAT_MOD_LINEAR };
|
||||
auto front_image_value = TRY(Gfx::create_shared_vulkan_image(vulkan_context, size.width(), size.height(), VK_FORMAT_B8G8R8A8_UNORM, linear_modifiers.span()));
|
||||
auto back_image_value = TRY(Gfx::create_shared_vulkan_image(vulkan_context, size.width(), size.height(), VK_FORMAT_B8G8R8A8_UNORM, linear_modifiers.span()));
|
||||
publish_backing_store_pair_if_needed(navigable, front_bitmap_id, Gfx::duplicate_shared_image(*front_image_value), back_bitmap_id, Gfx::duplicate_shared_image(*back_image_value));
|
||||
|
||||
return BackingStorePair {
|
||||
.front = Gfx::PaintingSurface::create_from_vkimage(skia_backend_context, move(front_image_value), Gfx::PaintingSurface::Origin::TopLeft),
|
||||
.back = Gfx::PaintingSurface::create_from_vkimage(skia_backend_context, move(back_image_value), Gfx::PaintingSurface::Origin::TopLeft),
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
void BackingStoreManager::reallocate_backing_stores(Gfx::IntSize size)
|
||||
{
|
||||
auto skia_backend_context = Gfx::SkiaBackendContext::the();
|
||||
|
||||
m_front_bitmap_id = m_next_bitmap_id++;
|
||||
m_back_bitmap_id = m_next_bitmap_id++;
|
||||
|
||||
auto update_backing_stores = [&](RefPtr<Gfx::PaintingSurface> front_store, RefPtr<Gfx::PaintingSurface> back_store) {
|
||||
m_allocated_size = size;
|
||||
m_navigable->rendering_thread().update_backing_stores(move(front_store), move(back_store), m_front_bitmap_id, m_back_bitmap_id);
|
||||
};
|
||||
|
||||
#ifdef USE_VULKAN_DMABUF_IMAGES
|
||||
if (skia_backend_context && m_navigable->is_top_level_traversable()) {
|
||||
auto backing_stores = create_linear_dmabuf_backing_stores(*m_navigable, size, m_front_bitmap_id, m_back_bitmap_id, *skia_backend_context);
|
||||
if (!backing_stores.is_error()) {
|
||||
auto backing_store_pair = backing_stores.release_value();
|
||||
update_backing_stores(move(backing_store_pair.front), move(backing_store_pair.back));
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
auto backing_stores = create_shareable_bitmap_backing_stores(*m_navigable, size, m_front_bitmap_id, m_back_bitmap_id, skia_backend_context);
|
||||
update_backing_stores(move(backing_stores.front), move(backing_stores.back));
|
||||
}
|
||||
|
||||
void BackingStoreManager::resize_backing_stores_if_needed(WindowResizingInProgress window_resize_in_progress)
|
||||
|
|
|
|||
Loading…
Reference in a new issue