mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-20 16:28:54 +00:00
LibGfx+LibWeb: Only compile dma-buf-related code on Linux
Shareable Vulkan image allocation on Linux relies on the dma-buf interface, which is a Linux-specific thing. Therefore, we should only be compiling it (and any code that uses it) on Linux. This change adds preprocessor guards to do that. Enabling similar functionality on other operating systems will need to leverage analogous interfaces on those platforms, e.g. win32 handles on Windows. All Vulkan image code will now be guarded by the USE_VULKAN_IMAGES preprocessor definition, currently enabled on Linux if Vulkan is available. Additionally, we shuffle around some code in OpenGLContext.cpp to simplify the preprocessor conditionals.
This commit is contained in:
parent
871838dda3
commit
ce03b8b3b1
Notes:
github-actions[bot]
2025-08-21 12:43:46 +00:00
Author: https://github.com/erik-kz
Commit: ce03b8b3b1
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5914
Reviewed-by: https://github.com/kalenikaliaksandr ✅
6 changed files with 143 additions and 73 deletions
|
@ -16,8 +16,7 @@
|
|||
|
||||
#ifdef AK_OS_MACOS
|
||||
# include <gpu/ganesh/mtl/GrMtlBackendSurface.h>
|
||||
#endif
|
||||
#ifdef USE_VULKAN
|
||||
#elif defined(USE_VULKAN_IMAGES)
|
||||
# include <gpu/ganesh/vk/GrVkBackendSurface.h>
|
||||
# include <gpu/vk/GrVkTypes.h>
|
||||
#endif
|
||||
|
@ -31,6 +30,7 @@ struct PaintingSurface::Impl {
|
|||
RefPtr<Bitmap> bitmap;
|
||||
};
|
||||
|
||||
#if defined(AK_OS_MACOS) || defined(USE_VULKAN_IMAGES)
|
||||
static GrSurfaceOrigin origin_to_sk_origin(PaintingSurface::Origin origin)
|
||||
{
|
||||
switch (origin) {
|
||||
|
@ -42,8 +42,9 @@ static GrSurfaceOrigin origin_to_sk_origin(PaintingSurface::Origin origin)
|
|||
return kTopLeft_GrSurfaceOrigin;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_VULKAN
|
||||
#ifdef USE_VULKAN_IMAGES
|
||||
static SkColorType vk_format_to_sk_color_type(VkFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
|
|
|
@ -39,7 +39,7 @@ public:
|
|||
static NonnullRefPtr<PaintingSurface> create_from_iosurface(Core::IOSurfaceHandle&&, NonnullRefPtr<SkiaBackendContext>, Origin = Origin::TopLeft);
|
||||
#endif
|
||||
|
||||
#ifdef USE_VULKAN
|
||||
#ifdef USE_VULKAN_IMAGES
|
||||
static NonnullRefPtr<PaintingSurface> create_from_vkimage(NonnullRefPtr<SkiaBackendContext> context, NonnullRefPtr<VulkanImage> vulkan_image, Origin origin);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -99,17 +99,22 @@ static ErrorOr<VkDevice> create_logical_device(VkPhysicalDevice physical_device,
|
|||
queue_create_info.pQueuePriorities = &queue_priority;
|
||||
|
||||
VkPhysicalDeviceFeatures deviceFeatures {};
|
||||
#ifdef USE_VULKAN_IMAGES
|
||||
char const* device_extensions[] = {
|
||||
VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME,
|
||||
VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME
|
||||
};
|
||||
|
||||
uint32_t device_extension_count = array_size(device_extensions);
|
||||
#else
|
||||
const char** device_extensions = nullptr;
|
||||
uint32_t device_extension_count = 0;
|
||||
#endif
|
||||
VkDeviceCreateInfo create_device_info {};
|
||||
create_device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
create_device_info.pQueueCreateInfos = &queue_create_info;
|
||||
create_device_info.queueCreateInfoCount = 1;
|
||||
create_device_info.pEnabledFeatures = &deviceFeatures;
|
||||
create_device_info.enabledExtensionCount = array_size(device_extensions);
|
||||
create_device_info.enabledExtensionCount = device_extension_count;
|
||||
create_device_info.ppEnabledExtensionNames = device_extensions;
|
||||
|
||||
if (vkCreateDevice(physical_device, &create_device_info, nullptr, &device) != VK_SUCCESS) {
|
||||
|
@ -119,6 +124,7 @@ static ErrorOr<VkDevice> create_logical_device(VkPhysicalDevice physical_device,
|
|||
return device;
|
||||
}
|
||||
|
||||
#ifdef USE_VULKAN_IMAGES
|
||||
static ErrorOr<VkCommandPool> create_command_pool(VkDevice logical_device, uint32_t queue_family_index)
|
||||
{
|
||||
VkCommandPoolCreateInfo command_pool_info = {
|
||||
|
@ -153,6 +159,7 @@ static ErrorOr<VkCommandBuffer> allocate_command_buffer(VkDevice logical_device,
|
|||
}
|
||||
return command_buffer;
|
||||
}
|
||||
#endif
|
||||
|
||||
ErrorOr<VulkanContext> create_vulkan_context()
|
||||
{
|
||||
|
@ -165,6 +172,7 @@ ErrorOr<VulkanContext> create_vulkan_context()
|
|||
VkQueue graphics_queue;
|
||||
vkGetDeviceQueue(logical_device, graphics_queue_family, 0, &graphics_queue);
|
||||
|
||||
#ifdef USE_VULKAN_IMAGES
|
||||
VkCommandPool command_pool = TRY(create_command_pool(logical_device, graphics_queue_family));
|
||||
VkCommandBuffer command_buffer = TRY(allocate_command_buffer(logical_device, command_pool));
|
||||
|
||||
|
@ -176,6 +184,7 @@ ErrorOr<VulkanContext> create_vulkan_context()
|
|||
if (pfn_vk_get_image_drm_format_modifier_properties_khr == nullptr) {
|
||||
return Error::from_string_literal("vkGetImageDrmFormatModifierPropertiesEXT unavailable");
|
||||
}
|
||||
#endif
|
||||
|
||||
return VulkanContext {
|
||||
.api_version = api_version,
|
||||
|
@ -184,15 +193,18 @@ ErrorOr<VulkanContext> create_vulkan_context()
|
|||
.logical_device = logical_device,
|
||||
.graphics_queue = graphics_queue,
|
||||
.graphics_queue_family = graphics_queue_family,
|
||||
#ifdef USE_VULKAN_IMAGES
|
||||
.command_pool = command_pool,
|
||||
.command_buffer = command_buffer,
|
||||
.ext_procs = {
|
||||
.get_memory_fd = pfn_vk_get_memory_fd_khr,
|
||||
.get_image_drm_format_modifier_properties = pfn_vk_get_image_drm_format_modifier_properties_khr,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
#ifdef USE_VULKAN_IMAGES
|
||||
VulkanImage::~VulkanImage()
|
||||
{
|
||||
if (image != VK_NULL_HANDLE) {
|
||||
|
@ -398,5 +410,6 @@ ErrorOr<NonnullRefPtr<VulkanImage>> create_shared_vulkan_image(VulkanContext con
|
|||
};
|
||||
return image;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
|
@ -11,8 +11,12 @@
|
|||
# include <AK/Assertions.h>
|
||||
# include <AK/NonnullRefPtr.h>
|
||||
# include <AK/RefCounted.h>
|
||||
# include <libdrm/drm_fourcc.h>
|
||||
# include <vulkan/vulkan.h>
|
||||
# ifdef AK_OS_LINUX
|
||||
# include <libdrm/drm_fourcc.h>
|
||||
// Sharable Vulkan images are currently only implemented on Linux
|
||||
# define USE_VULKAN_IMAGES 1
|
||||
# endif
|
||||
|
||||
namespace Gfx {
|
||||
|
||||
|
@ -23,6 +27,7 @@ struct VulkanContext {
|
|||
VkDevice logical_device { VK_NULL_HANDLE };
|
||||
VkQueue graphics_queue { VK_NULL_HANDLE };
|
||||
uint32_t graphics_queue_family { 0 };
|
||||
# ifdef USE_VULKAN_IMAGES
|
||||
VkCommandPool command_pool { VK_NULL_HANDLE };
|
||||
VkCommandBuffer command_buffer { VK_NULL_HANDLE };
|
||||
struct
|
||||
|
@ -30,8 +35,12 @@ struct VulkanContext {
|
|||
PFN_vkGetMemoryFdKHR get_memory_fd { nullptr };
|
||||
PFN_vkGetImageDrmFormatModifierPropertiesEXT get_image_drm_format_modifier_properties { nullptr };
|
||||
} ext_procs;
|
||||
# endif
|
||||
};
|
||||
|
||||
ErrorOr<VulkanContext> create_vulkan_context();
|
||||
|
||||
# ifdef USE_VULKAN_IMAGES
|
||||
struct VulkanImage : public RefCounted<VulkanImage> {
|
||||
VkImage image { VK_NULL_HANDLE };
|
||||
VkDeviceMemory memory { VK_NULL_HANDLE };
|
||||
|
@ -68,8 +77,8 @@ static inline uint32_t vk_format_to_drm_format(VkFormat format)
|
|||
}
|
||||
}
|
||||
|
||||
ErrorOr<VulkanContext> create_vulkan_context();
|
||||
ErrorOr<NonnullRefPtr<VulkanImage>> create_shared_vulkan_image(VulkanContext const& context, uint32_t width, uint32_t height, VkFormat format, uint32_t num_modifiers, uint64_t const* modifiers);
|
||||
# endif
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,11 @@ extern "C" {
|
|||
#include <GLES2/gl2ext_angle.h>
|
||||
}
|
||||
|
||||
// Enable WebGL if we're on MacOS and can use Metal or if we can use shareable Vulkan images
|
||||
#if defined(AK_OS_MACOS) || defined(USE_VULKAN_IMAGES)
|
||||
# define ENABLE_WEBGL 1
|
||||
#endif
|
||||
|
||||
namespace Web::WebGL {
|
||||
|
||||
struct OpenGLContext::Impl {
|
||||
|
@ -34,8 +39,9 @@ struct OpenGLContext::Impl {
|
|||
GLuint framebuffer { 0 };
|
||||
GLuint color_buffer { 0 };
|
||||
GLuint depth_buffer { 0 };
|
||||
EGLint texture_target { 0 };
|
||||
|
||||
#ifdef USE_VULKAN
|
||||
#ifdef USE_VULKAN_IMAGES
|
||||
EGLImage egl_image { EGL_NO_IMAGE };
|
||||
struct {
|
||||
PFNEGLQUERYDMABUFFORMATSEXTPROC query_dma_buf_formats { nullptr };
|
||||
|
@ -53,13 +59,16 @@ OpenGLContext::OpenGLContext(NonnullRefPtr<Gfx::SkiaBackendContext> skia_backend
|
|||
|
||||
OpenGLContext::~OpenGLContext()
|
||||
{
|
||||
#ifdef ENABLE_WEBGL
|
||||
free_surface_resources();
|
||||
eglMakeCurrent(m_impl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
eglDestroyContext(m_impl->display, m_impl->context);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenGLContext::free_surface_resources()
|
||||
{
|
||||
#ifdef ENABLE_WEBGL
|
||||
if (m_impl->framebuffer) {
|
||||
glDeleteFramebuffers(1, &m_impl->framebuffer);
|
||||
m_impl->framebuffer = 0;
|
||||
|
@ -75,22 +84,24 @@ void OpenGLContext::free_surface_resources()
|
|||
m_impl->depth_buffer = 0;
|
||||
}
|
||||
|
||||
#ifdef USE_VULKAN
|
||||
# ifdef USE_VULKAN_IMAGES
|
||||
if (m_impl->egl_image != EGL_NO_IMAGE) {
|
||||
eglDestroyImage(m_impl->display, m_impl->egl_image);
|
||||
m_impl->egl_image = EGL_NO_IMAGE;
|
||||
}
|
||||
#endif
|
||||
# endif
|
||||
|
||||
if (m_impl->surface != EGL_NO_SURFACE) {
|
||||
#ifdef AK_OS_MACOS
|
||||
# ifdef AK_OS_MACOS
|
||||
eglReleaseTexImage(m_impl->display, m_impl->surface, EGL_BACK_BUFFER);
|
||||
#endif
|
||||
# endif
|
||||
eglDestroySurface(m_impl->display, m_impl->surface);
|
||||
m_impl->surface = EGL_NO_SURFACE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef ENABLE_WEBGL
|
||||
static EGLConfig get_egl_config(EGLDisplay display)
|
||||
{
|
||||
EGLint const config_attribs[] = {
|
||||
|
@ -113,24 +124,20 @@ static EGLConfig get_egl_config(EGLDisplay display)
|
|||
eglChooseConfig(display, config_attribs, configs.data(), number_of_configs, &number_of_configs);
|
||||
return number_of_configs > 0 ? configs[0] : EGL_NO_CONFIG_KHR;
|
||||
}
|
||||
#endif
|
||||
|
||||
OwnPtr<OpenGLContext> OpenGLContext::create(NonnullRefPtr<Gfx::SkiaBackendContext> skia_backend_context, WebGLVersion webgl_version)
|
||||
{
|
||||
#if !defined(AK_OS_MACOS) && !defined(USE_VULKAN)
|
||||
(void)skia_backend_context;
|
||||
(void)webgl_version;
|
||||
return {};
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_WEBGL
|
||||
EGLAttrib display_attributes[] = {
|
||||
EGL_PLATFORM_ANGLE_TYPE_ANGLE,
|
||||
#if defined(AK_OS_MACOS)
|
||||
# if defined(AK_OS_MACOS)
|
||||
EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE,
|
||||
#elif defined(USE_VULKAN)
|
||||
# elif defined(USE_VULKAN_IMAGES)
|
||||
EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE,
|
||||
EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE,
|
||||
EGL_PLATFORM_SURFACELESS_MESA,
|
||||
#endif
|
||||
# endif
|
||||
EGL_NONE,
|
||||
};
|
||||
|
||||
|
@ -152,6 +159,14 @@ OwnPtr<OpenGLContext> OpenGLContext::create(NonnullRefPtr<Gfx::SkiaBackendContex
|
|||
return {};
|
||||
}
|
||||
|
||||
EGLint texture_target;
|
||||
# if defined(AK_OS_MACOS)
|
||||
eglGetConfigAttrib(display, config, EGL_BIND_TO_TEXTURE_TARGET_ANGLE, &texture_target);
|
||||
VERIFY(texture_target == EGL_TEXTURE_RECTANGLE_ANGLE || texture_target == EGL_TEXTURE_2D);
|
||||
# elif defined(USE_VULKAN_IMAGES)
|
||||
texture_target = EGL_TEXTURE_2D;
|
||||
# endif
|
||||
|
||||
EGLint context_attributes[] = {
|
||||
EGL_CONTEXT_CLIENT_VERSION,
|
||||
webgl_version == WebGLVersion::WebGL1 ? 2 : 3,
|
||||
|
@ -161,11 +176,11 @@ OwnPtr<OpenGLContext> OpenGLContext::create(NonnullRefPtr<Gfx::SkiaBackendContex
|
|||
EGL_TRUE,
|
||||
EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE,
|
||||
EGL_FALSE,
|
||||
#ifdef USE_VULKAN
|
||||
# ifdef USE_VULKAN_IMAGES
|
||||
// we need GL_OES_EGL_image
|
||||
EGL_EXTENSIONS_ENABLED_ANGLE,
|
||||
EGL_TRUE,
|
||||
#endif
|
||||
# endif
|
||||
EGL_NONE,
|
||||
EGL_NONE,
|
||||
};
|
||||
|
@ -175,7 +190,7 @@ OwnPtr<OpenGLContext> OpenGLContext::create(NonnullRefPtr<Gfx::SkiaBackendContex
|
|||
return {};
|
||||
}
|
||||
|
||||
#ifdef USE_VULKAN
|
||||
# ifdef USE_VULKAN_IMAGES
|
||||
auto pfn_egl_query_dma_buf_formats_ext = reinterpret_cast<PFNEGLQUERYDMABUFFORMATSEXTPROC>(eglGetProcAddress("eglQueryDmaBufFormatsEXT"));
|
||||
if (!pfn_egl_query_dma_buf_formats_ext) {
|
||||
dbgln("eglQueryDmaBufFormatsEXT unavailable");
|
||||
|
@ -187,29 +202,38 @@ OwnPtr<OpenGLContext> OpenGLContext::create(NonnullRefPtr<Gfx::SkiaBackendContex
|
|||
dbgln("eglQueryDmaBufModifiersEXT unavailable");
|
||||
return {};
|
||||
}
|
||||
#endif
|
||||
# endif
|
||||
|
||||
return make<OpenGLContext>(skia_backend_context, Impl {
|
||||
.display = display,
|
||||
.config = config,
|
||||
.context = context,
|
||||
#ifdef USE_VULKAN
|
||||
.texture_target = texture_target,
|
||||
# ifdef USE_VULKAN_IMAGES
|
||||
.ext_procs = {
|
||||
.query_dma_buf_formats = pfn_egl_query_dma_buf_formats_ext,
|
||||
.query_dma_buf_modifiers = pfn_egl_query_dma_buf_modifiers_ext,
|
||||
},
|
||||
#endif
|
||||
# endif
|
||||
},
|
||||
webgl_version);
|
||||
#else
|
||||
(void)skia_backend_context;
|
||||
(void)webgl_version;
|
||||
return {};
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenGLContext::notify_content_will_change()
|
||||
{
|
||||
#ifdef ENABLE_WEBGL
|
||||
m_painting_surface->notify_content_will_change();
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenGLContext::clear_buffer_to_default_values()
|
||||
{
|
||||
#ifdef ENABLE_WEBGL
|
||||
Array<GLfloat, 4> current_clear_color;
|
||||
glGetFloatv(GL_COLOR_CLEAR_VALUE, current_clear_color.data());
|
||||
|
||||
|
@ -234,41 +258,24 @@ void OpenGLContext::clear_buffer_to_default_values()
|
|||
glClearColor(current_clear_color[0], current_clear_color[1], current_clear_color[2], current_clear_color[3]);
|
||||
glClearDepthf(current_clear_depth);
|
||||
glClearStencil(current_clear_stencil);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenGLContext::allocate_painting_surface_if_needed()
|
||||
#ifdef AK_OS_MACOS
|
||||
void OpenGLContext::allocate_iosurface_painting_surface()
|
||||
{
|
||||
if (m_painting_surface)
|
||||
return;
|
||||
|
||||
free_surface_resources();
|
||||
|
||||
VERIFY(!m_size.is_empty());
|
||||
|
||||
auto width = m_size.width();
|
||||
auto height = m_size.height();
|
||||
|
||||
auto* display = m_impl->display;
|
||||
|
||||
EGLint texture_target_name = 0;
|
||||
|
||||
#if defined(AK_OS_MACOS)
|
||||
auto iosurface = Core::IOSurfaceHandle::create(m_size.width(), m_size.height());
|
||||
m_painting_surface = Gfx::PaintingSurface::create_from_iosurface(move(iosurface), m_skia_backend_context, Gfx::PaintingSurface::Origin::BottomLeft);
|
||||
|
||||
auto* config = m_impl->config;
|
||||
EGLint target = 0;
|
||||
eglGetConfigAttrib(display, config, EGL_BIND_TO_TEXTURE_TARGET_ANGLE, &target);
|
||||
|
||||
EGLint const surface_attributes[] = {
|
||||
EGL_WIDTH,
|
||||
width,
|
||||
m_size.width(),
|
||||
EGL_HEIGHT,
|
||||
height,
|
||||
m_size.height(),
|
||||
EGL_IOSURFACE_PLANE_ANGLE,
|
||||
0,
|
||||
EGL_TEXTURE_TARGET,
|
||||
target,
|
||||
m_impl->texture_target,
|
||||
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE,
|
||||
GL_BGRA_EXT,
|
||||
EGL_TEXTURE_FORMAT,
|
||||
|
@ -278,37 +285,39 @@ void OpenGLContext::allocate_painting_surface_if_needed()
|
|||
EGL_NONE,
|
||||
EGL_NONE,
|
||||
};
|
||||
m_impl->surface = eglCreatePbufferFromClientBuffer(display, EGL_IOSURFACE_ANGLE, iosurface.core_foundation_pointer(), config, surface_attributes);
|
||||
m_impl->surface = eglCreatePbufferFromClientBuffer(m_impl->display, EGL_IOSURFACE_ANGLE, iosurface.core_foundation_pointer(), m_impl->config, surface_attributes);
|
||||
|
||||
eglMakeCurrent(m_impl->display, m_impl->surface, m_impl->surface, m_impl->context);
|
||||
|
||||
eglGetConfigAttrib(display, config, EGL_BIND_TO_TEXTURE_TARGET_ANGLE, &texture_target_name);
|
||||
VERIFY(texture_target_name == EGL_TEXTURE_RECTANGLE_ANGLE || texture_target_name == EGL_TEXTURE_2D);
|
||||
|
||||
glGenTextures(1, &m_impl->color_buffer);
|
||||
glBindTexture(texture_target_name == EGL_TEXTURE_RECTANGLE_ANGLE ? GL_TEXTURE_RECTANGLE_ANGLE : GL_TEXTURE_2D, m_impl->color_buffer);
|
||||
auto result = eglBindTexImage(display, m_impl->surface, EGL_BACK_BUFFER);
|
||||
glBindTexture(m_impl->texture_target == EGL_TEXTURE_RECTANGLE_ANGLE ? GL_TEXTURE_RECTANGLE_ANGLE : GL_TEXTURE_2D, m_impl->color_buffer);
|
||||
auto result = eglBindTexImage(m_impl->display, m_impl->surface, EGL_BACK_BUFFER);
|
||||
VERIFY(result == EGL_TRUE);
|
||||
#elif defined(USE_VULKAN)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_VULKAN_IMAGES
|
||||
void OpenGLContext::allocate_vkimage_painting_surface()
|
||||
{
|
||||
VkFormat vulkan_format = VK_FORMAT_B8G8R8A8_UNORM;
|
||||
uint32_t drm_format = Gfx::vk_format_to_drm_format(vulkan_format);
|
||||
|
||||
// Ensure that our format is supported by the implementation.
|
||||
// FIXME: try other formats if not?
|
||||
EGLint num_formats = 0;
|
||||
m_impl->ext_procs.query_dma_buf_formats(display, 0, nullptr, &num_formats);
|
||||
m_impl->ext_procs.query_dma_buf_formats(m_impl->display, 0, nullptr, &num_formats);
|
||||
Vector<EGLint> egl_formats;
|
||||
egl_formats.resize(num_formats);
|
||||
m_impl->ext_procs.query_dma_buf_formats(display, num_formats, egl_formats.data(), &num_formats);
|
||||
m_impl->ext_procs.query_dma_buf_formats(m_impl->display, num_formats, egl_formats.data(), &num_formats);
|
||||
VERIFY(egl_formats.find(drm_format) != egl_formats.end());
|
||||
|
||||
EGLint num_modifiers = 0;
|
||||
m_impl->ext_procs.query_dma_buf_modifiers(display, drm_format, 0, nullptr, nullptr, &num_modifiers);
|
||||
m_impl->ext_procs.query_dma_buf_modifiers(m_impl->display, drm_format, 0, nullptr, nullptr, &num_modifiers);
|
||||
Vector<uint64_t> egl_modifiers;
|
||||
egl_modifiers.resize(num_modifiers);
|
||||
Vector<EGLBoolean> external_only;
|
||||
external_only.resize(num_modifiers);
|
||||
m_impl->ext_procs.query_dma_buf_modifiers(display, drm_format, num_modifiers, egl_modifiers.data(), external_only.data(), &num_modifiers);
|
||||
m_impl->ext_procs.query_dma_buf_modifiers(m_impl->display, drm_format, num_modifiers, egl_modifiers.data(), external_only.data(), &num_modifiers);
|
||||
Vector<uint64_t> renderable_modifiers;
|
||||
for (int i = 0; i < num_modifiers; ++i) {
|
||||
if (!external_only[i]) {
|
||||
|
@ -316,14 +325,14 @@ void OpenGLContext::allocate_painting_surface_if_needed()
|
|||
}
|
||||
}
|
||||
|
||||
auto vulkan_image = MUST(Gfx::create_shared_vulkan_image(m_skia_backend_context->vulkan_context(), width, height, vulkan_format, renderable_modifiers.size(), renderable_modifiers.data()));
|
||||
auto vulkan_image = MUST(Gfx::create_shared_vulkan_image(m_skia_backend_context->vulkan_context(), m_size.width(), m_size.height(), vulkan_format, renderable_modifiers.size(), renderable_modifiers.data()));
|
||||
m_painting_surface = Gfx::PaintingSurface::create_from_vkimage(m_skia_backend_context, vulkan_image, Gfx::PaintingSurface::Origin::BottomLeft);
|
||||
|
||||
EGLAttrib attribs[] = {
|
||||
EGL_WIDTH,
|
||||
width,
|
||||
m_size.width(),
|
||||
EGL_HEIGHT,
|
||||
height,
|
||||
m_size.height(),
|
||||
EGL_LINUX_DRM_FOURCC_EXT,
|
||||
drm_format,
|
||||
EGL_DMA_BUF_PLANE0_FD_EXT,
|
||||
|
@ -338,7 +347,7 @@ void OpenGLContext::allocate_painting_surface_if_needed()
|
|||
static_cast<uint32_t>(vulkan_image->info.modifier >> 32),
|
||||
EGL_NONE,
|
||||
};
|
||||
m_impl->egl_image = eglCreateImage(display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, attribs);
|
||||
m_impl->egl_image = eglCreateImage(m_impl->display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, nullptr, attribs);
|
||||
VERIFY(m_impl->egl_image != EGL_NO_IMAGE);
|
||||
|
||||
m_impl->surface = EGL_NO_SURFACE;
|
||||
|
@ -347,22 +356,40 @@ void OpenGLContext::allocate_painting_surface_if_needed()
|
|||
glGenTextures(1, &m_impl->color_buffer);
|
||||
glBindTexture(GL_TEXTURE_2D, m_impl->color_buffer);
|
||||
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_impl->egl_image);
|
||||
texture_target_name = EGL_TEXTURE_2D;
|
||||
|
||||
glViewport(0, 0, width, height);
|
||||
glViewport(0, 0, m_size.width(), m_size.height());
|
||||
}
|
||||
#endif
|
||||
|
||||
void OpenGLContext::allocate_painting_surface_if_needed()
|
||||
{
|
||||
#ifdef ENABLE_WEBGL
|
||||
if (m_painting_surface)
|
||||
return;
|
||||
|
||||
free_surface_resources();
|
||||
|
||||
VERIFY(!m_size.is_empty());
|
||||
|
||||
# if defined(AK_OS_MACOS)
|
||||
allocate_iosurface_painting_surface();
|
||||
# elif defined(USE_VULKAN_IMAGES)
|
||||
allocate_vkimage_painting_surface();
|
||||
# endif
|
||||
VERIFY(m_painting_surface);
|
||||
|
||||
glGenFramebuffers(1, &m_impl->framebuffer);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_impl->framebuffer);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture_target_name == EGL_TEXTURE_RECTANGLE_ANGLE ? GL_TEXTURE_RECTANGLE_ANGLE : GL_TEXTURE_2D, m_impl->color_buffer, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_impl->texture_target == EGL_TEXTURE_RECTANGLE_ANGLE ? GL_TEXTURE_RECTANGLE_ANGLE : GL_TEXTURE_2D, m_impl->color_buffer, 0);
|
||||
|
||||
// NOTE: ANGLE doesn't allocate depth buffer for us, so we need to do it manually
|
||||
// FIXME: Depth buffer only needs to be allocated if it's configured in WebGL context attributes
|
||||
glGenRenderbuffers(1, &m_impl->depth_buffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, m_impl->depth_buffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, m_size.width(), m_size.height());
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_impl->depth_buffer);
|
||||
VERIFY(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenGLContext::set_size(Gfx::IntSize const& size)
|
||||
|
@ -375,24 +402,27 @@ void OpenGLContext::set_size(Gfx::IntSize const& size)
|
|||
|
||||
void OpenGLContext::make_current()
|
||||
{
|
||||
#ifdef ENABLE_WEBGL
|
||||
allocate_painting_surface_if_needed();
|
||||
eglMakeCurrent(m_impl->display, m_impl->surface, m_impl->surface, m_impl->context);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenGLContext::present(bool preserve_drawing_buffer)
|
||||
{
|
||||
#ifdef ENABLE_WEBGL
|
||||
make_current();
|
||||
|
||||
// "Before the drawing buffer is presented for compositing the implementation shall ensure that all rendering operations have been flushed to the drawing buffer."
|
||||
// With Metal, glFlush flushes the command buffer, but without waiting for it to be scheduled or completed.
|
||||
// eglWaitUntilWorkScheduledANGLE flushes the command buffer, and waits until it has been scheduled, hence the name.
|
||||
// eglWaitUntilWorkScheduledANGLE only has an effect on CGL and Metal backends, so we only use it on macOS.
|
||||
#if defined(AK_OS_MACOS)
|
||||
# if defined(AK_OS_MACOS)
|
||||
eglWaitUntilWorkScheduledANGLE(m_impl->display);
|
||||
#elif defined(USE_VULKAN)
|
||||
# elif defined(USE_VULKAN_IMAGES)
|
||||
// FIXME: CPU sync for now, but it would be better to export a fence and have Skia wait for it before reading from the surface
|
||||
glFinish();
|
||||
#endif
|
||||
# endif
|
||||
|
||||
// "By default, after compositing the contents of the drawing buffer shall be cleared to their default values, as shown in the table above.
|
||||
// This default behavior can be changed by setting the preserveDrawingBuffer attribute of the WebGLContextAttributes object.
|
||||
|
@ -401,6 +431,9 @@ void OpenGLContext::present(bool preserve_drawing_buffer)
|
|||
// FIXME: we're assuming the clear operation won't actually be submitted to the GPU
|
||||
clear_buffer_to_default_values();
|
||||
}
|
||||
#else
|
||||
(void)preserve_drawing_buffer;
|
||||
#endif
|
||||
}
|
||||
|
||||
RefPtr<Gfx::PaintingSurface> OpenGLContext::surface()
|
||||
|
@ -485,6 +518,7 @@ Vector<Extension> s_available_webgl_extensions {
|
|||
|
||||
Vector<String> OpenGLContext::get_supported_extensions()
|
||||
{
|
||||
#ifdef ENABLE_WEBGL
|
||||
if (m_requestable_extensions.has_value())
|
||||
return m_requestable_extensions.value();
|
||||
|
||||
|
@ -521,12 +555,20 @@ Vector<String> OpenGLContext::get_supported_extensions()
|
|||
// been requested.
|
||||
m_requestable_extensions = extensions;
|
||||
return extensions;
|
||||
#else
|
||||
(void)m_webgl_version;
|
||||
return {};
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenGLContext::request_extension(char const* extension_name)
|
||||
{
|
||||
#ifdef ENABLE_WEBGL
|
||||
make_current();
|
||||
glRequestExtensionANGLE(extension_name);
|
||||
#else
|
||||
(void)extension_name;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -52,6 +52,11 @@ private:
|
|||
WebGLVersion m_webgl_version;
|
||||
|
||||
void free_surface_resources();
|
||||
#if defined(AK_OS_MACOS)
|
||||
void allocate_iosurface_painting_surface();
|
||||
#elif defined(USE_VULKAN_IMAGES)
|
||||
void allocate_vkimage_painting_surface();
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue