diff --git a/Userland/Libraries/LibGfx/CMakeLists.txt b/Userland/Libraries/LibGfx/CMakeLists.txt index 64dca64083f..6b1929e0d99 100644 --- a/Userland/Libraries/LibGfx/CMakeLists.txt +++ b/Userland/Libraries/LibGfx/CMakeLists.txt @@ -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) diff --git a/Userland/Libraries/LibGfx/SkiaBackendContext.cpp b/Userland/Libraries/LibGfx/SkiaBackendContext.cpp new file mode 100644 index 00000000000..5fa8933cba0 --- /dev/null +++ b/Userland/Libraries/LibGfx/SkiaBackendContext.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2024, Aliaksandr Kalenik + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include + +#include + +#ifdef USE_VULKAN +# include +# include +# include +#endif + +#ifdef AK_OS_MACOS +# include +# include +# include +# include +#endif + +namespace Gfx { + +#ifdef USE_VULKAN +class SkiaVulkanBackendContext final : public SkiaBackendContext { + AK_MAKE_NONCOPYABLE(SkiaVulkanBackendContext); + AK_MAKE_NONMOVABLE(SkiaVulkanBackendContext); + +public: + SkiaVulkanBackendContext(sk_sp context, NonnullOwnPtr 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 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 m_context; + NonnullOwnPtr m_extensions; +}; + +OwnPtr 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(); + backend_context.fVkExtensions = extensions.ptr(); + + sk_sp ctx = GrDirectContexts::MakeVulkan(backend_context); + VERIFY(ctx); + return make(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 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 m_context; +}; + +OwnPtr 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 ctx = GrDirectContexts::MakeMetal(backend_context); + return make(ctx); +} + +#endif + +} diff --git a/Userland/Libraries/LibGfx/SkiaBackendContext.h b/Userland/Libraries/LibGfx/SkiaBackendContext.h new file mode 100644 index 00000000000..af3ecfd6038 --- /dev/null +++ b/Userland/Libraries/LibGfx/SkiaBackendContext.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024, Aliaksandr Kalenik + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +#ifdef AK_OS_MACOS +# include +#endif + +#ifdef USE_VULKAN +# include +#endif + +class GrDirectContext; + +namespace Gfx { + +class SkiaBackendContext { + AK_MAKE_NONCOPYABLE(SkiaBackendContext); + AK_MAKE_NONMOVABLE(SkiaBackendContext); + +public: +#ifdef USE_VULKAN + static OwnPtr create_vulkan_context(Core::VulkanContext&); +#endif + +#ifdef AK_OS_MACOS + static OwnPtr create_metal_context(Core::MetalContext const&); +#endif + + SkiaBackendContext() {}; + virtual ~SkiaBackendContext() {}; + + virtual void flush_and_submit() {}; + virtual GrDirectContext* sk_context() const = 0; +}; + +} diff --git a/Userland/Libraries/LibWeb/HTML/TraversableNavigable.cpp b/Userland/Libraries/LibWeb/HTML/TraversableNavigable.cpp index 8c6fe3e90d3..0a3aeee7590 100644 --- a/Userland/Libraries/LibWeb/HTML/TraversableNavigable.cpp +++ b/Userland/Libraries/LibWeb/HTML/TraversableNavigable.cpp @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -31,7 +32,7 @@ TraversableNavigable::TraversableNavigable(JS::NonnullGCPtr 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) 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()); } diff --git a/Userland/Libraries/LibWeb/HTML/TraversableNavigable.h b/Userland/Libraries/LibWeb/HTML/TraversableNavigable.h index c2cd076e8c0..64bafde80d5 100644 --- a/Userland/Libraries/LibWeb/HTML/TraversableNavigable.h +++ b/Userland/Libraries/LibWeb/HTML/TraversableNavigable.h @@ -144,7 +144,7 @@ private: String m_window_handle; - OwnPtr m_skia_backend_context; + OwnPtr m_skia_backend_context; #ifdef AK_OS_MACOS OwnPtr m_metal_context; diff --git a/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp b/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp index de791f1b6dc..73e08fbf2ad 100644 --- a/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp +++ b/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.cpp @@ -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 context, NonnullOwnPtr 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 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 m_context; - NonnullOwnPtr m_extensions; -}; - -OwnPtr 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(); - backend_context.fVkExtensions = extensions.ptr(); - - sk_sp ctx = GrDirectContexts::MakeVulkan(backend_context); - VERIFY(ctx); - return make(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(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(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 context) - : m_context(move(context)) - { - } - - ~SkiaMetalBackendContext() override {}; - - sk_sp 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 m_context; -}; - -OwnPtr 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 ctx = GrDirectContexts::MakeMetal(backend_context); - return make(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(context)); - auto surface = static_cast(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(); diff --git a/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.h b/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.h index 598b94b2f35..8e5488a825c 100644 --- a/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.h +++ b/Userland/Libraries/LibWeb/Painting/DisplayListPlayerSkia.h @@ -7,42 +7,23 @@ #pragma once #include +#include #include -#ifdef AK_OS_MACOS -# include -# include -#endif - -#ifdef USE_VULKAN -# include -#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 create_vulkan_context(Core::VulkanContext&); - DisplayListPlayerSkia(SkiaBackendContext&, Gfx::Bitmap&); + DisplayListPlayerSkia(Gfx::SkiaBackendContext&, Gfx::Bitmap&); #endif #ifdef AK_OS_MACOS - static OwnPtr create_metal_context(Core::MetalContext const&); - DisplayListPlayerSkia(SkiaBackendContext&, Core::MetalTexture&); + DisplayListPlayerSkia(Gfx::SkiaBackendContext&, Core::MetalTexture&); #endif virtual ~DisplayListPlayerSkia() override;