mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-25 00:50:22 +00:00
LibWeb+LibGfx: Move class that represents Skia GPU context to LibGfx
This is required to share GPU context creation code between display list player, which resides in LibWeb, and PainterSkia, which handles <canvas> painting.
This commit is contained in:
parent
29f419d637
commit
1688cbc991
Notes:
github-actions[bot]
2024-11-07 12:49:46 +00:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/LadybirdBrowser/ladybird/commit/1688cbc9918 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/1532 Reviewed-by: https://github.com/ADKaster
7 changed files with 186 additions and 126 deletions
|
@ -1,4 +1,5 @@
|
|||
include(skia)
|
||||
include(vulkan)
|
||||
|
||||
set(SOURCES
|
||||
AffineTransform.cpp
|
||||
|
@ -65,6 +66,7 @@ set(SOURCES
|
|||
TextLayout.cpp
|
||||
Triangle.cpp
|
||||
VectorGraphic.cpp
|
||||
SkiaBackendContext.cpp
|
||||
)
|
||||
|
||||
serenity_lib(LibGfx gfx)
|
||||
|
|
125
Userland/Libraries/LibGfx/SkiaBackendContext.cpp
Normal file
125
Userland/Libraries/LibGfx/SkiaBackendContext.cpp
Normal file
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <AK/NonnullOwnPtr.h>
|
||||
#include <AK/OwnPtr.h>
|
||||
#include <AK/Platform.h>
|
||||
#include <LibGfx/SkiaBackendContext.h>
|
||||
|
||||
#include <gpu/GrDirectContext.h>
|
||||
|
||||
#ifdef USE_VULKAN
|
||||
# include <gpu/ganesh/vk/GrVkDirectContext.h>
|
||||
# include <gpu/vk/VulkanBackendContext.h>
|
||||
# include <gpu/vk/VulkanExtensions.h>
|
||||
#endif
|
||||
|
||||
#ifdef AK_OS_MACOS
|
||||
# include <gpu/GrBackendSurface.h>
|
||||
# include <gpu/ganesh/mtl/GrMtlBackendContext.h>
|
||||
# include <gpu/ganesh/mtl/GrMtlBackendSurface.h>
|
||||
# include <gpu/ganesh/mtl/GrMtlDirectContext.h>
|
||||
#endif
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
#ifdef USE_VULKAN
|
||||
class SkiaVulkanBackendContext final : public SkiaBackendContext {
|
||||
AK_MAKE_NONCOPYABLE(SkiaVulkanBackendContext);
|
||||
AK_MAKE_NONMOVABLE(SkiaVulkanBackendContext);
|
||||
|
||||
public:
|
||||
SkiaVulkanBackendContext(sk_sp<GrDirectContext> context, NonnullOwnPtr<skgpu::VulkanExtensions> extensions)
|
||||
: m_context(move(context))
|
||||
, m_extensions(move(extensions))
|
||||
{
|
||||
}
|
||||
|
||||
~SkiaVulkanBackendContext() override { }
|
||||
|
||||
void flush_and_submit() override
|
||||
{
|
||||
m_context->flush();
|
||||
m_context->submit(GrSyncCpu::kYes);
|
||||
}
|
||||
|
||||
sk_sp<SkSurface> create_surface(int width, int height)
|
||||
{
|
||||
auto image_info = SkImageInfo::Make(width, height, kBGRA_8888_SkColorType, kPremul_SkAlphaType);
|
||||
return SkSurfaces::RenderTarget(m_context.get(), skgpu::Budgeted::kYes, image_info);
|
||||
}
|
||||
|
||||
skgpu::VulkanExtensions const* extensions() const { return m_extensions.ptr(); }
|
||||
|
||||
GrDirectContext* sk_context() const override { return m_context.get(); }
|
||||
|
||||
private:
|
||||
sk_sp<GrDirectContext> m_context;
|
||||
NonnullOwnPtr<skgpu::VulkanExtensions> m_extensions;
|
||||
};
|
||||
|
||||
OwnPtr<SkiaBackendContext> SkiaBackendContext::create_vulkan_context(Core::VulkanContext& vulkan_context)
|
||||
{
|
||||
skgpu::VulkanBackendContext backend_context;
|
||||
|
||||
backend_context.fInstance = vulkan_context.instance;
|
||||
backend_context.fDevice = vulkan_context.logical_device;
|
||||
backend_context.fQueue = vulkan_context.graphics_queue;
|
||||
backend_context.fPhysicalDevice = vulkan_context.physical_device;
|
||||
backend_context.fMaxAPIVersion = vulkan_context.api_version;
|
||||
backend_context.fGetProc = [](char const* proc_name, VkInstance instance, VkDevice device) {
|
||||
if (device != VK_NULL_HANDLE) {
|
||||
return vkGetDeviceProcAddr(device, proc_name);
|
||||
}
|
||||
return vkGetInstanceProcAddr(instance, proc_name);
|
||||
};
|
||||
|
||||
auto extensions = make<skgpu::VulkanExtensions>();
|
||||
backend_context.fVkExtensions = extensions.ptr();
|
||||
|
||||
sk_sp<GrDirectContext> ctx = GrDirectContexts::MakeVulkan(backend_context);
|
||||
VERIFY(ctx);
|
||||
return make<SkiaVulkanBackendContext>(ctx, move(extensions));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef AK_OS_MACOS
|
||||
class SkiaMetalBackendContext final : public SkiaBackendContext {
|
||||
AK_MAKE_NONCOPYABLE(SkiaMetalBackendContext);
|
||||
AK_MAKE_NONMOVABLE(SkiaMetalBackendContext);
|
||||
|
||||
public:
|
||||
SkiaMetalBackendContext(sk_sp<GrDirectContext> context)
|
||||
: m_context(move(context))
|
||||
{
|
||||
}
|
||||
|
||||
~SkiaMetalBackendContext() override { }
|
||||
|
||||
void flush_and_submit() override
|
||||
{
|
||||
m_context->flush();
|
||||
m_context->submit(GrSyncCpu::kYes);
|
||||
}
|
||||
|
||||
GrDirectContext* sk_context() const override { return m_context.get(); }
|
||||
|
||||
private:
|
||||
sk_sp<GrDirectContext> m_context;
|
||||
};
|
||||
|
||||
OwnPtr<SkiaBackendContext> SkiaBackendContext::create_metal_context(Core::MetalContext const& metal_context)
|
||||
{
|
||||
GrMtlBackendContext backend_context;
|
||||
backend_context.fDevice.retain((GrMTLHandle)metal_context.device());
|
||||
backend_context.fQueue.retain((GrMTLHandle)metal_context.queue());
|
||||
sk_sp<GrDirectContext> ctx = GrDirectContexts::MakeMetal(backend_context);
|
||||
return make<SkiaMetalBackendContext>(ctx);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
43
Userland/Libraries/LibGfx/SkiaBackendContext.h
Normal file
43
Userland/Libraries/LibGfx/SkiaBackendContext.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Noncopyable.h>
|
||||
|
||||
#ifdef AK_OS_MACOS
|
||||
# include <LibCore/MetalContext.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_VULKAN
|
||||
# include <LibCore/VulkanContext.h>
|
||||
#endif
|
||||
|
||||
class GrDirectContext;
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
class SkiaBackendContext {
|
||||
AK_MAKE_NONCOPYABLE(SkiaBackendContext);
|
||||
AK_MAKE_NONMOVABLE(SkiaBackendContext);
|
||||
|
||||
public:
|
||||
#ifdef USE_VULKAN
|
||||
static OwnPtr<SkiaBackendContext> create_vulkan_context(Core::VulkanContext&);
|
||||
#endif
|
||||
|
||||
#ifdef AK_OS_MACOS
|
||||
static OwnPtr<Gfx::SkiaBackendContext> create_metal_context(Core::MetalContext const&);
|
||||
#endif
|
||||
|
||||
SkiaBackendContext() {};
|
||||
virtual ~SkiaBackendContext() {};
|
||||
|
||||
virtual void flush_and_submit() {};
|
||||
virtual GrDirectContext* sk_context() const = 0;
|
||||
};
|
||||
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
#include <AK/QuickSort.h>
|
||||
#include <LibGfx/SkiaBackendContext.h>
|
||||
#include <LibWeb/Bindings/MainThreadVM.h>
|
||||
#include <LibWeb/DOM/Document.h>
|
||||
#include <LibWeb/HTML/BrowsingContextGroup.h>
|
||||
|
@ -31,7 +32,7 @@ TraversableNavigable::TraversableNavigable(JS::NonnullGCPtr<Page> page)
|
|||
auto display_list_player_type = page->client().display_list_player_type();
|
||||
if (display_list_player_type == DisplayListPlayerType::SkiaGPUIfAvailable) {
|
||||
m_metal_context = Core::get_metal_context();
|
||||
m_skia_backend_context = Painting::DisplayListPlayerSkia::create_metal_context(*m_metal_context);
|
||||
m_skia_backend_context = Gfx::SkiaBackendContext::create_metal_context(*m_metal_context);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -41,7 +42,7 @@ TraversableNavigable::TraversableNavigable(JS::NonnullGCPtr<Page> page)
|
|||
auto maybe_vulkan_context = Core::create_vulkan_context();
|
||||
if (!maybe_vulkan_context.is_error()) {
|
||||
auto vulkan_context = maybe_vulkan_context.release_value();
|
||||
m_skia_backend_context = Painting::DisplayListPlayerSkia::create_vulkan_context(vulkan_context);
|
||||
m_skia_backend_context = Gfx::SkiaBackendContext::create_vulkan_context(vulkan_context);
|
||||
} else {
|
||||
dbgln("Vulkan context creation failed: {}", maybe_vulkan_context.error());
|
||||
}
|
||||
|
|
|
@ -144,7 +144,7 @@ private:
|
|||
|
||||
String m_window_handle;
|
||||
|
||||
OwnPtr<Web::Painting::SkiaBackendContext> m_skia_backend_context;
|
||||
OwnPtr<Gfx::SkiaBackendContext> m_skia_backend_context;
|
||||
|
||||
#ifdef AK_OS_MACOS
|
||||
OwnPtr<Core::MetalContext> m_metal_context;
|
||||
|
|
|
@ -71,66 +71,11 @@ private:
|
|||
};
|
||||
|
||||
#ifdef USE_VULKAN
|
||||
class SkiaVulkanBackendContext final : public SkiaBackendContext {
|
||||
AK_MAKE_NONCOPYABLE(SkiaVulkanBackendContext);
|
||||
AK_MAKE_NONMOVABLE(SkiaVulkanBackendContext);
|
||||
|
||||
public:
|
||||
SkiaVulkanBackendContext(sk_sp<GrDirectContext> context, NonnullOwnPtr<skgpu::VulkanExtensions> extensions)
|
||||
: m_context(move(context))
|
||||
, m_extensions(move(extensions))
|
||||
{
|
||||
}
|
||||
|
||||
~SkiaVulkanBackendContext() override {};
|
||||
|
||||
void flush_and_submit() override
|
||||
{
|
||||
m_context->flush();
|
||||
m_context->submit(GrSyncCpu::kYes);
|
||||
}
|
||||
|
||||
sk_sp<SkSurface> create_surface(int width, int height)
|
||||
{
|
||||
auto image_info = SkImageInfo::Make(width, height, kBGRA_8888_SkColorType, kPremul_SkAlphaType);
|
||||
return SkSurfaces::RenderTarget(m_context.get(), skgpu::Budgeted::kYes, image_info);
|
||||
}
|
||||
|
||||
skgpu::VulkanExtensions const* extensions() const { return m_extensions.ptr(); }
|
||||
|
||||
private:
|
||||
sk_sp<GrDirectContext> m_context;
|
||||
NonnullOwnPtr<skgpu::VulkanExtensions> m_extensions;
|
||||
};
|
||||
|
||||
OwnPtr<SkiaBackendContext> DisplayListPlayerSkia::create_vulkan_context(Core::VulkanContext& vulkan_context)
|
||||
{
|
||||
skgpu::VulkanBackendContext backend_context;
|
||||
|
||||
backend_context.fInstance = vulkan_context.instance;
|
||||
backend_context.fDevice = vulkan_context.logical_device;
|
||||
backend_context.fQueue = vulkan_context.graphics_queue;
|
||||
backend_context.fPhysicalDevice = vulkan_context.physical_device;
|
||||
backend_context.fMaxAPIVersion = vulkan_context.api_version;
|
||||
backend_context.fGetProc = [](char const* proc_name, VkInstance instance, VkDevice device) {
|
||||
if (device != VK_NULL_HANDLE) {
|
||||
return vkGetDeviceProcAddr(device, proc_name);
|
||||
}
|
||||
return vkGetInstanceProcAddr(instance, proc_name);
|
||||
};
|
||||
|
||||
auto extensions = make<skgpu::VulkanExtensions>();
|
||||
backend_context.fVkExtensions = extensions.ptr();
|
||||
|
||||
sk_sp<GrDirectContext> ctx = GrDirectContexts::MakeVulkan(backend_context);
|
||||
VERIFY(ctx);
|
||||
return make<SkiaVulkanBackendContext>(ctx, move(extensions));
|
||||
}
|
||||
|
||||
DisplayListPlayerSkia::DisplayListPlayerSkia(SkiaBackendContext& context, Gfx::Bitmap& bitmap)
|
||||
DisplayListPlayerSkia::DisplayListPlayerSkia(Gfx::SkiaBackendContext& context, Gfx::Bitmap& bitmap)
|
||||
{
|
||||
VERIFY(bitmap.format() == Gfx::BitmapFormat::BGRA8888);
|
||||
auto surface = static_cast<SkiaVulkanBackendContext&>(context).create_surface(bitmap.width(), bitmap.height());
|
||||
auto image_info = SkImageInfo::Make(bitmap.width(), bitmap.height(), kBGRA_8888_SkColorType, kPremul_SkAlphaType);
|
||||
auto surface = SkSurfaces::RenderTarget(context.sk_context(), skgpu::Budgeted::kYes, image_info);
|
||||
m_surface = make<SkiaSurface>(surface);
|
||||
m_flush_context = [&bitmap, &surface = m_surface, &context] {
|
||||
context.flush_and_submit();
|
||||
|
@ -140,50 +85,13 @@ DisplayListPlayerSkia::DisplayListPlayerSkia(SkiaBackendContext& context, Gfx::B
|
|||
#endif
|
||||
|
||||
#ifdef AK_OS_MACOS
|
||||
class SkiaMetalBackendContext final : public SkiaBackendContext {
|
||||
AK_MAKE_NONCOPYABLE(SkiaMetalBackendContext);
|
||||
AK_MAKE_NONMOVABLE(SkiaMetalBackendContext);
|
||||
|
||||
public:
|
||||
SkiaMetalBackendContext(sk_sp<GrDirectContext> context)
|
||||
: m_context(move(context))
|
||||
{
|
||||
}
|
||||
|
||||
~SkiaMetalBackendContext() override {};
|
||||
|
||||
sk_sp<SkSurface> wrap_metal_texture(Core::MetalTexture& metal_texture)
|
||||
{
|
||||
GrMtlTextureInfo mtl_info;
|
||||
mtl_info.fTexture = sk_ret_cfp(metal_texture.texture());
|
||||
auto backend_render_target = GrBackendRenderTargets::MakeMtl(metal_texture.width(), metal_texture.height(), mtl_info);
|
||||
return SkSurfaces::WrapBackendRenderTarget(m_context.get(), backend_render_target, kTopLeft_GrSurfaceOrigin, kBGRA_8888_SkColorType, nullptr, nullptr);
|
||||
}
|
||||
|
||||
void flush_and_submit() override
|
||||
{
|
||||
m_context->flush();
|
||||
m_context->submit(GrSyncCpu::kYes);
|
||||
}
|
||||
|
||||
private:
|
||||
sk_sp<GrDirectContext> m_context;
|
||||
};
|
||||
|
||||
OwnPtr<SkiaBackendContext> DisplayListPlayerSkia::create_metal_context(Core::MetalContext const& metal_context)
|
||||
{
|
||||
GrMtlBackendContext backend_context;
|
||||
backend_context.fDevice.retain((GrMTLHandle)metal_context.device());
|
||||
backend_context.fQueue.retain((GrMTLHandle)metal_context.queue());
|
||||
sk_sp<GrDirectContext> ctx = GrDirectContexts::MakeMetal(backend_context);
|
||||
return make<SkiaMetalBackendContext>(ctx);
|
||||
}
|
||||
|
||||
DisplayListPlayerSkia::DisplayListPlayerSkia(SkiaBackendContext& context, Core::MetalTexture& metal_texture)
|
||||
DisplayListPlayerSkia::DisplayListPlayerSkia(Gfx::SkiaBackendContext& context, Core::MetalTexture& metal_texture)
|
||||
{
|
||||
auto image_info = SkImageInfo::Make(metal_texture.width(), metal_texture.height(), kBGRA_8888_SkColorType, kPremul_SkAlphaType);
|
||||
VERIFY(is<SkiaMetalBackendContext>(context));
|
||||
auto surface = static_cast<SkiaMetalBackendContext&>(context).wrap_metal_texture(metal_texture);
|
||||
GrMtlTextureInfo mtl_info;
|
||||
mtl_info.fTexture = sk_ret_cfp(metal_texture.texture());
|
||||
auto backend_render_target = GrBackendRenderTargets::MakeMtl(metal_texture.width(), metal_texture.height(), mtl_info);
|
||||
auto surface = SkSurfaces::WrapBackendRenderTarget(context.sk_context(), backend_render_target, kTopLeft_GrSurfaceOrigin, kBGRA_8888_SkColorType, nullptr, nullptr);
|
||||
if (!surface) {
|
||||
dbgln("Failed to create Skia surface from Metal texture");
|
||||
VERIFY_NOT_REACHED();
|
||||
|
|
|
@ -7,42 +7,23 @@
|
|||
#pragma once
|
||||
|
||||
#include <LibGfx/Bitmap.h>
|
||||
#include <LibGfx/SkiaBackendContext.h>
|
||||
#include <LibWeb/Painting/DisplayListRecorder.h>
|
||||
|
||||
#ifdef AK_OS_MACOS
|
||||
# include <LibCore/IOSurface.h>
|
||||
# include <LibCore/MetalContext.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_VULKAN
|
||||
# include <LibCore/VulkanContext.h>
|
||||
#endif
|
||||
class GrDirectContext;
|
||||
|
||||
namespace Web::Painting {
|
||||
|
||||
class SkiaBackendContext {
|
||||
AK_MAKE_NONCOPYABLE(SkiaBackendContext);
|
||||
AK_MAKE_NONMOVABLE(SkiaBackendContext);
|
||||
|
||||
public:
|
||||
SkiaBackendContext() {};
|
||||
virtual ~SkiaBackendContext() {};
|
||||
|
||||
virtual void flush_and_submit() {};
|
||||
};
|
||||
|
||||
class DisplayListPlayerSkia : public DisplayListPlayer {
|
||||
public:
|
||||
DisplayListPlayerSkia(Gfx::Bitmap&);
|
||||
|
||||
#ifdef USE_VULKAN
|
||||
static OwnPtr<SkiaBackendContext> create_vulkan_context(Core::VulkanContext&);
|
||||
DisplayListPlayerSkia(SkiaBackendContext&, Gfx::Bitmap&);
|
||||
DisplayListPlayerSkia(Gfx::SkiaBackendContext&, Gfx::Bitmap&);
|
||||
#endif
|
||||
|
||||
#ifdef AK_OS_MACOS
|
||||
static OwnPtr<SkiaBackendContext> create_metal_context(Core::MetalContext const&);
|
||||
DisplayListPlayerSkia(SkiaBackendContext&, Core::MetalTexture&);
|
||||
DisplayListPlayerSkia(Gfx::SkiaBackendContext&, Core::MetalTexture&);
|
||||
#endif
|
||||
|
||||
virtual ~DisplayListPlayerSkia() override;
|
||||
|
|
Loading…
Reference in a new issue