mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-26 12:17:52 +00:00
LibGfx: Allow creating a PaintingSurface from a Vulkan image
This adds a new PaintingSurface creation function, create_from_vkimage, which returns a PaintingSurface backed by a vulkan image. It's analogous to the existing create_from_iosurface function. In both cases the backing object will be imported into Skia as a render target and then an SkSurface will be wrapped around that. In order to ensure that the image will not be freed while still in use by Skia, we will manually bump the refcount of the VulkanImage object before passing it to Skia and then use the releaseCallback parameter of WrapBackendRenderTarget to register a callback that drops this reference.
This commit is contained in:
parent
08343970fb
commit
41f1e920d8
Notes:
github-actions[bot]
2025-08-18 22:31:50 +00:00
Author: https://github.com/erik-kz
Commit: 41f1e920d8
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5864
Reviewed-by: https://github.com/kalenikaliaksandr ✅
2 changed files with 71 additions and 12 deletions
|
@ -17,6 +17,10 @@
|
||||||
#ifdef AK_OS_MACOS
|
#ifdef AK_OS_MACOS
|
||||||
# include <gpu/ganesh/mtl/GrMtlBackendSurface.h>
|
# include <gpu/ganesh/mtl/GrMtlBackendSurface.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef USE_VULKAN
|
||||||
|
# include <gpu/ganesh/vk/GrVkBackendSurface.h>
|
||||||
|
# include <gpu/vk/GrVkTypes.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Gfx {
|
namespace Gfx {
|
||||||
|
|
||||||
|
@ -27,6 +31,68 @@ struct PaintingSurface::Impl {
|
||||||
RefPtr<Bitmap> bitmap;
|
RefPtr<Bitmap> 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<VulkanImage*>(context);
|
||||||
|
image->unref();
|
||||||
|
}
|
||||||
|
|
||||||
|
NonnullRefPtr<PaintingSurface> PaintingSurface::create_from_vkimage(NonnullRefPtr<SkiaBackendContext> context, NonnullRefPtr<VulkanImage> 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<SkSurface> 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<Impl>(context, size, surface, nullptr)));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
NonnullRefPtr<PaintingSurface> PaintingSurface::create_with_size(RefPtr<SkiaBackendContext> context, IntSize size, BitmapFormat color_type, AlphaType alpha_type)
|
NonnullRefPtr<PaintingSurface> PaintingSurface::create_with_size(RefPtr<SkiaBackendContext> context, IntSize size, BitmapFormat color_type, AlphaType alpha_type)
|
||||||
{
|
{
|
||||||
auto sk_color_type = to_skia_color_type(color_type);
|
auto sk_color_type = to_skia_color_type(color_type);
|
||||||
|
@ -71,18 +137,7 @@ NonnullRefPtr<PaintingSurface> PaintingSurface::create_from_iosurface(Core::IOSu
|
||||||
GrMtlTextureInfo mtl_info;
|
GrMtlTextureInfo mtl_info;
|
||||||
mtl_info.fTexture = sk_ret_cfp(metal_texture->texture());
|
mtl_info.fTexture = sk_ret_cfp(metal_texture->texture());
|
||||||
auto backend_render_target = GrBackendRenderTargets::MakeMtl(metal_texture->width(), metal_texture->height(), mtl_info);
|
auto backend_render_target = GrBackendRenderTargets::MakeMtl(metal_texture->width(), metal_texture->height(), mtl_info);
|
||||||
GrSurfaceOrigin sk_origin;
|
auto surface = SkSurfaces::WrapBackendRenderTarget(context->sk_context(), backend_render_target, origin_to_sk_origin(origin), kBGRA_8888_SkColorType, nullptr, nullptr);
|
||||||
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);
|
|
||||||
return adopt_ref(*new PaintingSurface(make<Impl>(context, size, surface, nullptr)));
|
return adopt_ref(*new PaintingSurface(make<Impl>(context, size, surface, nullptr)));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -39,6 +39,10 @@ public:
|
||||||
static NonnullRefPtr<PaintingSurface> create_from_iosurface(Core::IOSurfaceHandle&&, NonnullRefPtr<SkiaBackendContext>, Origin = Origin::TopLeft);
|
static NonnullRefPtr<PaintingSurface> create_from_iosurface(Core::IOSurfaceHandle&&, NonnullRefPtr<SkiaBackendContext>, Origin = Origin::TopLeft);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_VULKAN
|
||||||
|
static NonnullRefPtr<PaintingSurface> create_from_vkimage(NonnullRefPtr<SkiaBackendContext> context, NonnullRefPtr<VulkanImage> vulkan_image, Origin origin);
|
||||||
|
#endif
|
||||||
|
|
||||||
void read_into_bitmap(Bitmap&);
|
void read_into_bitmap(Bitmap&);
|
||||||
void write_from_bitmap(Bitmap const&);
|
void write_from_bitmap(Bitmap const&);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue