diff --git a/Libraries/LibGfx/PaintingSurface.cpp b/Libraries/LibGfx/PaintingSurface.cpp index f645dbeaa03..bf1528da481 100644 --- a/Libraries/LibGfx/PaintingSurface.cpp +++ b/Libraries/LibGfx/PaintingSurface.cpp @@ -17,6 +17,10 @@ #ifdef AK_OS_MACOS # include #endif +#ifdef USE_VULKAN +# include +# include +#endif namespace Gfx { @@ -27,6 +31,68 @@ struct PaintingSurface::Impl { RefPtr bitmap; }; +static GrSurfaceOrigin origin_to_sk_origin(PaintingSurface::Origin origin) +{ + switch (origin) { + case PaintingSurface::Origin::BottomLeft: + return kBottomLeft_GrSurfaceOrigin; + default: + VERIFY_NOT_REACHED(); + case PaintingSurface::Origin::TopLeft: + return kTopLeft_GrSurfaceOrigin; + } +} + +#ifdef USE_VULKAN +static SkColorType vk_format_to_sk_color_type(VkFormat format) +{ + switch (format) { + case VK_FORMAT_B8G8R8A8_UNORM: + return kBGRA_8888_SkColorType; + // add more as needed + default: + VERIFY_NOT_REACHED(); + return kUnknown_SkColorType; + } +} + +static void release_vulkan_image(void* context) +{ + VulkanImage* image = static_cast(context); + image->unref(); +} + +NonnullRefPtr PaintingSurface::create_from_vkimage(NonnullRefPtr context, NonnullRefPtr vulkan_image, Origin origin) +{ + context->lock(); + ScopeGuard unlock_guard([&context] { + context->unlock(); + }); + + IntSize size(vulkan_image->info.extent.width, vulkan_image->info.extent.height); + GrVkImageInfo info = { + .fImage = vulkan_image->image, + .fAlloc = {}, // we're managing the memory ourselves + .fImageTiling = vulkan_image->info.tiling, + .fImageLayout = vulkan_image->info.layout, + .fFormat = vulkan_image->info.format, + .fImageUsageFlags = vulkan_image->info.usage, + .fSampleCount = 1, + .fLevelCount = 1, + .fCurrentQueueFamily = VK_QUEUE_FAMILY_IGNORED, + .fProtected = skgpu::Protected::kNo, + .fYcbcrConversionInfo = {}, + .fSharingMode = vulkan_image->info.sharing_mode, + }; + GrBackendRenderTarget rt = GrBackendRenderTargets::MakeVk(size.width(), size.height(), info); + // Note, we're implicitly giving Skia a reference to vulkan_image. It will eventually be released by the callback function. + vulkan_image->ref(); + sk_sp surface = SkSurfaces::WrapBackendRenderTarget(context->sk_context(), rt, origin_to_sk_origin(origin), vk_format_to_sk_color_type(vulkan_image->info.format), + nullptr, nullptr, release_vulkan_image, vulkan_image.ptr()); + return adopt_ref(*new PaintingSurface(make(context, size, surface, nullptr))); +} +#endif + NonnullRefPtr PaintingSurface::create_with_size(RefPtr context, IntSize size, BitmapFormat color_type, AlphaType alpha_type) { auto sk_color_type = to_skia_color_type(color_type); @@ -71,18 +137,7 @@ NonnullRefPtr PaintingSurface::create_from_iosurface(Core::IOSu 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); - GrSurfaceOrigin sk_origin; - switch (origin) { - case Origin::TopLeft: - sk_origin = kTopLeft_GrSurfaceOrigin; - break; - case Origin::BottomLeft: - sk_origin = kBottomLeft_GrSurfaceOrigin; - break; - default: - VERIFY_NOT_REACHED(); - } - auto surface = SkSurfaces::WrapBackendRenderTarget(context->sk_context(), backend_render_target, sk_origin, kBGRA_8888_SkColorType, nullptr, nullptr); + auto surface = SkSurfaces::WrapBackendRenderTarget(context->sk_context(), backend_render_target, origin_to_sk_origin(origin), kBGRA_8888_SkColorType, nullptr, nullptr); return adopt_ref(*new PaintingSurface(make(context, size, surface, nullptr))); } #endif diff --git a/Libraries/LibGfx/PaintingSurface.h b/Libraries/LibGfx/PaintingSurface.h index a2890d74694..db22cd92a5c 100644 --- a/Libraries/LibGfx/PaintingSurface.h +++ b/Libraries/LibGfx/PaintingSurface.h @@ -39,6 +39,10 @@ public: static NonnullRefPtr create_from_iosurface(Core::IOSurfaceHandle&&, NonnullRefPtr, Origin = Origin::TopLeft); #endif +#ifdef USE_VULKAN + static NonnullRefPtr create_from_vkimage(NonnullRefPtr context, NonnullRefPtr vulkan_image, Origin origin); +#endif + void read_into_bitmap(Bitmap&); void write_from_bitmap(Bitmap const&);