summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2023-03-15 15:07:19 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2023-04-12 12:13:57 +0200
commitcceda0895b3aca208e37669b2acb38c01e9f1774 (patch)
tree1a28f9521c00b1fdb6be66bc7a423b1086ce06bf
parent6cfbef4474d2cb15fec37103c3609da919f8a4ca (diff)
Rework painting integration and support Metal RHI over ANGLE
Move graphics details into compositor, and add support for a native buffer mode uses ANGLE on the Chromium side. The initially support is for Metal. Pick-to: 6.5 Fixes: QTBUG-112282 Task-number: QTBUG-112280 Change-Id: I066ba1d3e72508e047d259ae5797659d45335fb2 Reviewed-by: Peter Varga <pvarga@inf.u-szeged.hu>
-rw-r--r--src/core/CMakeLists.txt8
-rw-r--r--src/core/api/qtwebenginecoreglobal.cpp3
-rw-r--r--src/core/compositor/compositor.cpp21
-rw-r--r--src/core/compositor/compositor.h36
-rw-r--r--src/core/compositor/display_overrides.cpp13
-rw-r--r--src/core/compositor/display_skia_output_device.cpp52
-rw-r--r--src/core/compositor/display_skia_output_device.h7
-rw-r--r--src/core/compositor/display_software_output_surface.cpp13
-rw-r--r--src/core/compositor/native_skia_output_device.cpp391
-rw-r--r--src/core/compositor/native_skia_output_device.h103
-rw-r--r--src/core/compositor/native_skia_output_device_mac.mm30
-rw-r--r--src/core/compositor/native_skia_output_device_mac2.mm25
-rw-r--r--src/core/ozone/gl_share_context_qt.cpp8
-rw-r--r--src/core/ozone/gl_share_context_qt.h2
-rw-r--r--src/core/render_widget_host_view_qt_delegate_item.cpp69
-rw-r--r--src/core/render_widget_host_view_qt_delegate_item.h1
-rw-r--r--src/core/web_engine_context.cpp63
-rw-r--r--src/webenginequick/api/qtwebenginequickglobal.cpp2
18 files changed, 732 insertions, 115 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 0ecdf6c3f..1c9761e89 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -99,6 +99,7 @@ foreach(arch ${archs})
compositor/content_gpu_client_qt.cpp compositor/content_gpu_client_qt.h
compositor/display_overrides.cpp
compositor/display_software_output_surface.cpp compositor/display_software_output_surface.h
+ compositor/native_skia_output_device.cpp compositor/native_skia_output_device.h
content_browser_client_qt.cpp content_browser_client_qt.h
content_client_qt.cpp content_client_qt.h
content_main_delegate_qt.cpp content_main_delegate_qt.h
@@ -219,6 +220,12 @@ foreach(arch ${archs})
compositor/display_skia_output_device.cpp compositor/display_skia_output_device.h
)
+ extend_gn_target(${buildGn} CONDITION MACOS
+ SOURCES
+ compositor/native_skia_output_device_mac.mm
+ compositor/native_skia_output_device_mac2.mm
+ )
+
extend_gn_target(${buildGn} CONDITION MACOS AND QT_FEATURE_opengl
SOURCES
macos_context_type_helper.mm macos_context_type_helper.h
@@ -507,6 +514,7 @@ foreach(arch ${archs})
list(APPEND gnArgArg
use_external_popup_menu=false
angle_enable_vulkan=false
+ use_static_angle=true
)
endif()
diff --git a/src/core/api/qtwebenginecoreglobal.cpp b/src/core/api/qtwebenginecoreglobal.cpp
index 1dded1086..3301695b3 100644
--- a/src/core/api/qtwebenginecoreglobal.cpp
+++ b/src/core/api/qtwebenginecoreglobal.cpp
@@ -212,7 +212,8 @@ static void initialize()
// QCoreApplication is not yet instantiated, ensuring the call will be deferred
qAddPreRoutine(QtWebEngineCore::initialize);
auto api = QQuickWindow::graphicsApi();
- if (api != QSGRendererInterface::OpenGLRhi && api != QSGRendererInterface::VulkanRhi)
+ if (api != QSGRendererInterface::OpenGLRhi && api != QSGRendererInterface::VulkanRhi
+ && api != QSGRendererInterface::MetalRhi)
QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGLRhi);
#endif // QT_CONFIG(opengl)
}
diff --git a/src/core/compositor/compositor.cpp b/src/core/compositor/compositor.cpp
index fed395cb1..c147f988b 100644
--- a/src/core/compositor/compositor.cpp
+++ b/src/core/compositor/compositor.cpp
@@ -137,36 +137,27 @@ Compositor::Handle<Compositor::Observer> Compositor::observer()
return nullptr;
}
-QImage Compositor::image()
-{
- Q_UNREACHABLE();
- return {};
-}
-
void Compositor::waitForTexture()
{
- Q_UNREACHABLE();
}
-int Compositor::textureId()
+void Compositor::releaseTexture()
{
- Q_UNREACHABLE();
- return 0;
}
-#if QT_CONFIG(webengine_vulkan)
-VkImage Compositor::vkImage(QQuickWindow *)
+QSGTexture *Compositor::texture(QQuickWindow *, uint32_t textureOptions)
{
Q_UNREACHABLE();
- return {};
+ return nullptr;
}
-VkImageLayout Compositor::vkImageLayout()
+bool Compositor::textureIsFlipped()
{
Q_UNREACHABLE();
- return {};
+ return false;
}
+#if QT_CONFIG(webengine_vulkan)
void Compositor::releaseVulkanResources(QQuickWindow *)
{
Q_UNREACHABLE();
diff --git a/src/core/compositor/compositor.h b/src/core/compositor/compositor.h
index 21263150b..018d965ba 100644
--- a/src/core/compositor/compositor.h
+++ b/src/core/compositor/compositor.h
@@ -7,14 +7,10 @@
#include <QtGui/qtguiglobal.h>
#include <QtWebEngineCore/private/qtwebenginecoreglobal_p.h>
-#if QT_CONFIG(webengine_vulkan)
-#include <QVulkanInstance>
-#endif
-
QT_BEGIN_NAMESPACE
-class QImage;
class QQuickWindow;
class QSize;
+class QSGTexture;
QT_END_NAMESPACE
namespace viz {
@@ -25,9 +21,8 @@ namespace QtWebEngineCore {
// Produces composited frames for display.
//
-// Used by quick/widgets libraries for accessing the frame and
-// controlling frame swapping. Must be cast to a subclass to access
-// the frame as QImage or OpenGL texture, etc.
+// Used by quick/widgets libraries for accessing the frames and
+// controlling frame swapping.
class Q_WEBENGINECORE_PRIVATE_EXPORT Compositor
{
struct Binding;
@@ -38,6 +33,7 @@ public:
Software,
OpenGL,
Vulkan,
+ NativeBuffer
};
// Identifies a compositor.
@@ -126,27 +122,19 @@ public:
// Whether frame needs an alpha channel.
virtual bool requiresAlphaChannel() = 0;
- // (Software) QImage of the frame.
- //
- // This is a big image so we should try not to make copies of it.
- // In particular, the client should drop its QImage reference
- // before calling swapFrame(), otherwise each swap will cause a
- // detach.
- virtual QImage image();
-
- // (OpenGL) Wait on texture fence in Qt's current OpenGL context.
+ // Wait on texture to be ready aka. sync.
virtual void waitForTexture();
- // (OpenGL) Texture of the frame.
- virtual int textureId();
+ // Release any held texture resources
+ virtual void releaseTexture();
-#if QT_CONFIG(webengine_vulkan)
- // (Vulkan) VkImage of the frame.
- virtual VkImage vkImage(QQuickWindow *win);
+ // QSGTexture of the frame.
+ virtual QSGTexture *texture(QQuickWindow *win, uint32_t textureOptions);
- // (Vulkan) Layout for vkImage().
- virtual VkImageLayout vkImageLayout();
+ // Is the texture produced upside down?
+ virtual bool textureIsFlipped();
+#if QT_CONFIG(webengine_vulkan)
// (Vulkan) Release Vulkan resources created by Qt's Vulkan instance.
virtual void releaseVulkanResources(QQuickWindow *win);
#endif
diff --git a/src/core/compositor/display_overrides.cpp b/src/core/compositor/display_overrides.cpp
index 3b33f5dcc..2baff5d20 100644
--- a/src/core/compositor/display_overrides.cpp
+++ b/src/core/compositor/display_overrides.cpp
@@ -3,10 +3,12 @@
#include "display_skia_output_device.h"
#include "display_software_output_surface.h"
+#include "native_skia_output_device.h"
#include "components/viz/service/display_embedder/output_surface_provider_impl.h"
#include "components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h"
#include "gpu/ipc/in_process_command_buffer.h"
+
#include <qtgui-config.h>
std::unique_ptr<viz::OutputSurface>
@@ -18,6 +20,16 @@ viz::OutputSurfaceProviderImpl::CreateSoftwareOutputSurface(const RendererSettin
std::unique_ptr<viz::SkiaOutputDevice>
viz::SkiaOutputSurfaceImplOnGpu::CreateOutputDevice()
{
+ if (gl::GetGLImplementation() == gl::kGLImplementationEGLANGLE) {
+ return std::make_unique<QtWebEngineCore::NativeSkiaOutputDevice>(
+ context_state_,
+ renderer_settings_.requires_alpha_channel,
+ shared_gpu_deps_->memory_tracker(),
+ dependency_.get(),
+ shared_image_factory_.get(),
+ shared_image_representation_factory_.get(),
+ GetDidSwapBuffersCompleteCallback());
+ }
#if QT_CONFIG(opengl)
return std::make_unique<QtWebEngineCore::DisplaySkiaOutputDevice>(
context_state_,
@@ -28,4 +40,3 @@ viz::SkiaOutputSurfaceImplOnGpu::CreateOutputDevice()
return nullptr;
#endif // QT_CONFIG(opengl)
}
-
diff --git a/src/core/compositor/display_skia_output_device.cpp b/src/core/compositor/display_skia_output_device.cpp
index d2cce14d0..9f9462193 100644
--- a/src/core/compositor/display_skia_output_device.cpp
+++ b/src/core/compositor/display_skia_output_device.cpp
@@ -32,6 +32,8 @@
#include <QVulkanDeviceFunctions>
#endif // QT_CONFIG(webengine_vulkan)
+#include <QSGTexture>
+
namespace QtWebEngineCore {
class DisplaySkiaOutputDevice::Buffer
@@ -41,6 +43,9 @@ public:
: m_parent(parent)
, m_shape(m_parent->m_shape)
{
+ }
+ void initialize()
+ {
const auto &colorType = m_shape.characterization.colorType();
DCHECK(colorType != kUnknown_SkColorType);
@@ -77,8 +82,10 @@ public:
#if QT_CONFIG(webengine_vulkan) && defined(Q_OS_WIN)
CloseHandle(m_win32Handle);
#endif
- DeleteGrBackendTexture(m_parent->m_contextState.get(), &m_texture);
- m_parent->memory_type_tracker_->TrackMemFree(m_estimatedSize);
+ if (m_texture.isValid()) {
+ DeleteGrBackendTexture(m_parent->m_contextState.get(), &m_texture);
+ m_parent->memory_type_tracker_->TrackMemFree(m_estimatedSize);
+ }
}
void createFence()
@@ -267,6 +274,9 @@ DisplaySkiaOutputDevice::DisplaySkiaOutputDevice(
{
capabilities_.uses_default_gl_framebuffer = false;
capabilities_.supports_surfaceless = true;
+ capabilities_.preserve_buffer_content = true;
+ capabilities_.only_invalidates_damage_rect = false;
+ capabilities_.number_of_buffers = 3;
capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::RGBA_8888)] =
kRGBA_8888_SkColorType;
@@ -309,7 +319,7 @@ void DisplaySkiaOutputDevice::SwapBuffers(BufferPresentedCallback feedback,
{
QMutexLocker locker(&m_mutex);
m_taskRunner = base::ThreadTaskRunnerHandle::Get();
- m_middleBuffer = std::move(m_backBuffer);
+ std::swap(m_middleBuffer, m_backBuffer);
m_readyToUpdate = true;
}
@@ -325,10 +335,12 @@ void DisplaySkiaOutputDevice::DiscardBackbuffer()
{
}
-SkSurface *DisplaySkiaOutputDevice::BeginPaint(std::vector<GrBackendSemaphore> *)
+SkSurface *DisplaySkiaOutputDevice::BeginPaint(std::vector<GrBackendSemaphore> *end_semaphores)
{
- if (!m_backBuffer || m_backBuffer->shape() != m_shape)
+ if (!m_backBuffer || m_backBuffer->shape() != m_shape) {
m_backBuffer = std::make_unique<Buffer>(this);
+ m_backBuffer->initialize();
+ }
return m_backBuffer->surface();
}
@@ -355,16 +367,32 @@ void DisplaySkiaOutputDevice::waitForTexture()
m_frontBuffer->consumeFence();
}
-int DisplaySkiaOutputDevice::textureId()
+QSGTexture *DisplaySkiaOutputDevice::texture(QQuickWindow *win, uint32_t textureOptions)
{
if (!m_frontBuffer)
- return 0;
+ return nullptr;
- GrGLTextureInfo info;
- if (!m_frontBuffer->texture().getGLTextureInfo(&info))
- return 0;
+ QQuickWindow::CreateTextureOptions texOpts(textureOptions);
- return info.fID;
+ QSGTexture *texture = nullptr;
+#if QT_CONFIG(webengine_vulkan)
+ if (type() == Type::Vulkan) {
+ VkImage image = vkImage(win);
+ VkImageLayout layout = vkImageLayout();
+ texture = QNativeInterface::QSGVulkanTexture::fromNative(image, layout, win, size(), texOpts);
+ } else
+#endif
+ {
+ GrGLTextureInfo info;
+ if (m_frontBuffer->texture().getGLTextureInfo(&info))
+ texture = QNativeInterface::QSGOpenGLTexture::fromNative(info.fID, win, size(), texOpts);
+ }
+ return texture;
+}
+
+bool DisplaySkiaOutputDevice::textureIsFlipped()
+{
+ return true;
}
QSize DisplaySkiaOutputDevice::size()
@@ -472,7 +500,7 @@ void DisplaySkiaOutputDevice::SwapBuffersFinished()
{
{
QMutexLocker locker(&m_mutex);
- m_backBuffer = std::move(m_middleBuffer);
+ std::swap(m_backBuffer, m_middleBuffer);
}
FinishSwapBuffers(gfx::SwapCompletionResult(gfx::SwapResult::SWAP_ACK),
diff --git a/src/core/compositor/display_skia_output_device.h b/src/core/compositor/display_skia_output_device.h
index 648784f52..27bee2d1d 100644
--- a/src/core/compositor/display_skia_output_device.h
+++ b/src/core/compositor/display_skia_output_device.h
@@ -44,13 +44,14 @@ public:
// Overridden from Compositor.
void swapFrame() override;
void waitForTexture() override;
- int textureId() override;
+ QSGTexture *texture(QQuickWindow *win, uint32_t texOpts) override;
+ bool textureIsFlipped() override;
QSize size() override;
bool requiresAlphaChannel() override;
float devicePixelRatio() override;
#if QT_CONFIG(webengine_vulkan)
- VkImage vkImage(QQuickWindow *win) override;
- VkImageLayout vkImageLayout() override;
+ VkImage vkImage(QQuickWindow *win);
+ VkImageLayout vkImageLayout();
void releaseVulkanResources(QQuickWindow *win) override;
#endif
diff --git a/src/core/compositor/display_software_output_surface.cpp b/src/core/compositor/display_software_output_surface.cpp
index 10872da27..9d6534c28 100644
--- a/src/core/compositor/display_software_output_surface.cpp
+++ b/src/core/compositor/display_software_output_surface.cpp
@@ -13,6 +13,7 @@
#include <QMutex>
#include <QPainter>
+#include <QQuickWindow>
namespace QtWebEngineCore {
@@ -28,7 +29,8 @@ public:
// Overridden from Compositor.
void swapFrame() override;
- QImage image() override;
+ QSGTexture *texture(QQuickWindow *win, uint32_t) override;
+ bool textureIsFlipped() override;
float devicePixelRatio() override;
QSize size() override;
bool requiresAlphaChannel() override;
@@ -110,9 +112,14 @@ void DisplaySoftwareOutputSurface::Device::swapFrame()
m_taskRunner.reset();
}
-QImage DisplaySoftwareOutputSurface::Device::image()
+QSGTexture *DisplaySoftwareOutputSurface::Device::texture(QQuickWindow *win, uint32_t)
{
- return m_image;
+ return win->createTextureFromImage(m_image);
+}
+
+bool DisplaySoftwareOutputSurface::Device::textureIsFlipped()
+{
+ return false;
}
float DisplaySoftwareOutputSurface::Device::devicePixelRatio()
diff --git a/src/core/compositor/native_skia_output_device.cpp b/src/core/compositor/native_skia_output_device.cpp
new file mode 100644
index 000000000..47cbd1981
--- /dev/null
+++ b/src/core/compositor/native_skia_output_device.cpp
@@ -0,0 +1,391 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "native_skia_output_device.h"
+
+#include "type_conversion.h"
+
+#include "components/viz/common/resources/shared_image_format.h"
+#include "components/viz/service/display_embedder/skia_output_surface_dependency.h"
+#include "gpu/command_buffer/common/mailbox.h"
+#include "gpu/command_buffer/common/shared_image_usage.h"
+#include "gpu/command_buffer/service/shared_image/shared_image_factory.h"
+#include "gpu/command_buffer/service/shared_image/shared_image_representation.h"
+#include "gpu/command_buffer/service/skia_utils.h"
+#include "third_party/skia/include/gpu/GrDirectContext.h"
+#include "third_party/skia/include/core/SkSurfaceProps.h"
+#include "ui/gl/gl_fence.h"
+
+#ifdef Q_OS_MACOS
+#include "ui/gl/gl_image_io_surface.h"
+#endif
+
+#include <QQuickWindow>
+
+namespace QtWebEngineCore {
+
+class NativeSkiaOutputDevice::Buffer
+{
+public:
+ Buffer(NativeSkiaOutputDevice *parent)
+ : m_parent(parent)
+ , m_shape(m_parent->m_shape)
+ {
+ }
+ ~Buffer()
+ {
+ if (m_scopedSkiaWriteAccess)
+ endWriteSkia(false);
+
+ if (!m_mailbox.IsZero())
+ m_parent->m_factory->DestroySharedImage(m_mailbox);
+ }
+
+ // The following Buffer methods are based on components/viz/service/display_embedder/output_presenter.cc:
+ // Copyright 2020 The Chromium Authors
+ // Use of this source code is governed by a BSD-style license that can be
+ // found in the LICENSE file.
+ bool initialize()
+ {
+ static const uint32_t kDefaultSharedImageUsage =
+ gpu::SHARED_IMAGE_USAGE_SCANOUT | gpu::SHARED_IMAGE_USAGE_DISPLAY_READ
+ | gpu::SHARED_IMAGE_USAGE_DISPLAY_WRITE | gpu::SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT;
+ auto mailbox = gpu::Mailbox::GenerateForSharedImage();
+
+ if (!m_parent->m_factory->CreateSharedImage(mailbox,
+ viz::SharedImageFormat::SinglePlane(viz::RGBA_8888),
+ {m_parent->m_shape.characterization.width(), m_parent->m_shape.characterization.height()},
+ m_parent->m_shape.colorSpace,
+ m_parent->capabilities_.output_surface_origin == gfx::SurfaceOrigin::kTopLeft
+ ? kTopLeft_GrSurfaceOrigin
+ : kBottomLeft_GrSurfaceOrigin,
+ kPremul_SkAlphaType,
+ m_parent->m_deps->GetSurfaceHandle(), kDefaultSharedImageUsage)) {
+ LOG(ERROR) << "CreateSharedImage failed.";
+ return false;
+ }
+ m_mailbox = mailbox;
+
+ m_skiaRepresentation = m_parent->m_representationFactory->ProduceSkia(m_mailbox, m_parent->m_deps->GetSharedContextState());
+ if (!m_skiaRepresentation) {
+ LOG(ERROR) << "ProduceSkia() failed.";
+ return false;
+ }
+
+ m_overlayRepresentation = m_parent->m_representationFactory->ProduceOverlay(m_mailbox);
+ if (!m_overlayRepresentation) {
+ LOG(ERROR) << "ProduceOverlay() failed";
+ return false;
+ }
+
+ return true;
+ }
+ SkSurface *beginWriteSkia()
+ {
+ DCHECK(!m_scopedSkiaWriteAccess);
+ DCHECK(!m_presentCount);
+ DCHECK(m_endSemaphores.empty());
+
+ std::vector<GrBackendSemaphore> beginSemaphores;
+ SkSurfaceProps surface_props{0, kUnknown_SkPixelGeometry};
+
+ // Buffer queue is internal to GPU proc and handles texture initialization,
+ // so allow uncleared access.
+ m_scopedSkiaWriteAccess = m_skiaRepresentation->BeginScopedWriteAccess(
+ 0 /* sampleCount */, surface_props, &beginSemaphores, &m_endSemaphores,
+ gpu::SharedImageRepresentation::AllowUnclearedAccess::kYes);
+ DCHECK(m_scopedSkiaWriteAccess);
+ if (!beginSemaphores.empty()) {
+ m_scopedSkiaWriteAccess->surface()->wait(
+ beginSemaphores.size(),
+ beginSemaphores.data(),
+ /*deleteSemaphoresAfterWait=*/false);
+ }
+ return m_scopedSkiaWriteAccess->surface();
+ }
+
+ void endWriteSkia(bool force_flush)
+ {
+ // The Flush now takes place in finishPaintCurrentBuffer on the CPU side.
+ // check if end_semaphores is not empty then flush here
+ DCHECK(m_scopedSkiaWriteAccess);
+ auto end_state = m_scopedSkiaWriteAccess->TakeEndState();
+ if (!m_endSemaphores.empty() || end_state || force_flush) {
+ GrFlushInfo flush_info = {};
+ flush_info.fNumSemaphores = m_endSemaphores.size();
+ flush_info.fSignalSemaphores = m_endSemaphores.data();
+ m_scopedSkiaWriteAccess->surface()->flush(flush_info, end_state.get());
+ auto *direct_context = m_scopedSkiaWriteAccess->surface()->recordingContext()->asDirectContext();
+ DCHECK(direct_context);
+ direct_context->submit();
+ }
+ m_scopedSkiaWriteAccess.reset();
+ m_endSemaphores.clear();
+
+ // SkiaRenderer always draws the full frame.
+ m_skiaRepresentation->SetCleared();
+ }
+
+ std::vector<GrBackendSemaphore> takeEndWriteSkiaSemaphores()
+ {
+ return std::exchange(m_endSemaphores, {});
+ }
+
+ void beginPresent()
+ {
+ if (++m_presentCount != 1) {
+ DCHECK(m_scopedOverlayReadAccess);
+ return;
+ }
+
+ DCHECK(!m_scopedSkiaWriteAccess);
+ DCHECK(!m_scopedOverlayReadAccess);
+
+ m_scopedOverlayReadAccess = m_overlayRepresentation->BeginScopedReadAccess(true);
+ DCHECK(m_scopedOverlayReadAccess);
+ m_acquireFence = TakeGpuFence(m_scopedOverlayReadAccess->TakeAcquireFence());
+ }
+
+ void endPresent()
+ {
+ if (!m_presentCount)
+ return;
+ DCHECK(m_scopedOverlayReadAccess);
+ if (--m_presentCount)
+ return;
+
+ m_scopedOverlayReadAccess.reset();
+ }
+ gl::GLImage *glImage()
+ {
+ DCHECK(m_presentCount);
+ return m_scopedOverlayReadAccess->gl_image();
+ }
+
+ void createFence()
+ {
+ // For some reason we still need to create this, but we do not need to wait on it.
+ m_fence = gl::GLFence::Create();
+ }
+
+ void consumeFence()
+ {
+ if (m_acquireFence) {
+ m_acquireFence->Wait();
+ m_acquireFence.reset();
+ }
+ }
+
+ const Shape &shape() const { return m_shape; }
+
+private:
+ NativeSkiaOutputDevice *m_parent;
+ Shape m_shape;
+ uint64_t m_estimatedSize = 0; // FIXME: estimate size
+ static std::unique_ptr<gfx::GpuFence> TakeGpuFence(gfx::GpuFenceHandle fence)
+ {
+ return fence.is_null() ? nullptr
+ : std::make_unique<gfx::GpuFence>(std::move(fence));
+ }
+ std::unique_ptr<gfx::GpuFence> m_acquireFence;
+ std::unique_ptr<gl::GLFence> m_fence;
+ gpu::Mailbox m_mailbox;
+ std::unique_ptr<gpu::SkiaImageRepresentation> m_skiaRepresentation;
+ std::unique_ptr<gpu::SkiaImageRepresentation::ScopedWriteAccess> m_scopedSkiaWriteAccess;
+ std::unique_ptr<gpu::OverlayImageRepresentation> m_overlayRepresentation;
+ std::unique_ptr<gpu::OverlayImageRepresentation::ScopedReadAccess> m_scopedOverlayReadAccess;
+
+ std::vector<GrBackendSemaphore> m_endSemaphores;
+ int m_presentCount = 0;
+};
+
+NativeSkiaOutputDevice::NativeSkiaOutputDevice(
+ scoped_refptr<gpu::SharedContextState> contextState,
+ bool requiresAlpha,
+ gpu::MemoryTracker *memoryTracker,
+ viz::SkiaOutputSurfaceDependency *dependency,
+ gpu::SharedImageFactory *shared_image_factory,
+ gpu::SharedImageRepresentationFactory *shared_image_representation_factory,
+ DidSwapBufferCompleteCallback didSwapBufferCompleteCallback)
+ : SkiaOutputDevice(contextState->gr_context(), memoryTracker, didSwapBufferCompleteCallback)
+ , Compositor(Compositor::Type::NativeBuffer)
+ , m_requiresAlpha(requiresAlpha)
+ , m_factory(shared_image_factory)
+ , m_representationFactory(shared_image_representation_factory)
+ , m_deps(dependency)
+{
+ capabilities_.uses_default_gl_framebuffer = false;
+ capabilities_.supports_surfaceless = true;
+ capabilities_.preserve_buffer_content = true;
+ capabilities_.only_invalidates_damage_rect = false;
+ capabilities_.number_of_buffers = 3;
+
+ capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::RGBA_8888)] =
+ kRGBA_8888_SkColorType;
+ capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::RGBX_8888)] =
+ kRGBA_8888_SkColorType;
+ capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::BGRA_8888)] =
+ kRGBA_8888_SkColorType;
+ capabilities_.sk_color_types[static_cast<int>(gfx::BufferFormat::BGRX_8888)] =
+ kRGBA_8888_SkColorType;
+}
+
+NativeSkiaOutputDevice::~NativeSkiaOutputDevice()
+{
+}
+
+void NativeSkiaOutputDevice::SetFrameSinkId(const viz::FrameSinkId &id)
+{
+ bind(id);
+}
+
+bool NativeSkiaOutputDevice::Reshape(const SkSurfaceCharacterization &characterization,
+ const gfx::ColorSpace &colorSpace,
+ float device_scale_factor,
+ gfx::OverlayTransform transform)
+{
+ m_shape = Shape{characterization, device_scale_factor, colorSpace};
+ DCHECK_EQ(transform, gfx::OVERLAY_TRANSFORM_NONE);
+ return true;
+}
+
+void NativeSkiaOutputDevice::SwapBuffers(BufferPresentedCallback feedback,
+ viz::OutputSurfaceFrame frame)
+{
+ DCHECK(m_backBuffer);
+
+ StartSwapBuffers(std::move(feedback));
+ m_frame = std::move(frame);
+ {
+ QMutexLocker locker(&m_mutex);
+ m_backBuffer->createFence();
+ m_taskRunner = base::ThreadTaskRunnerHandle::Get();
+ std::swap(m_middleBuffer, m_backBuffer);
+ m_readyToUpdate = true;
+ }
+
+ if (auto obs = observer())
+ obs->readyToSwap();
+}
+
+void NativeSkiaOutputDevice::EnsureBackbuffer()
+{
+}
+
+void NativeSkiaOutputDevice::DiscardBackbuffer()
+{
+}
+
+
+SkSurface *NativeSkiaOutputDevice::BeginPaint(std::vector<GrBackendSemaphore> *end_semaphores)
+{
+ {
+ QMutexLocker locker(&m_mutex);
+ if (!m_backBuffer || m_backBuffer->shape() != m_shape) {
+ m_backBuffer = std::make_unique<Buffer>(this);
+ if (!m_backBuffer->initialize())
+ return nullptr;
+ }
+ }
+ auto surface = m_backBuffer->beginWriteSkia();
+ *end_semaphores = m_backBuffer->takeEndWriteSkiaSemaphores();
+ return surface;
+}
+
+void NativeSkiaOutputDevice::EndPaint()
+{
+ m_backBuffer->endWriteSkia(true);
+}
+
+void NativeSkiaOutputDevice::swapFrame()
+{
+ QMutexLocker locker(&m_mutex);
+ if (m_readyToUpdate) {
+ std::swap(m_frontBuffer, m_middleBuffer);
+ m_taskRunner->PostTask(FROM_HERE,
+ base::BindOnce(&NativeSkiaOutputDevice::SwapBuffersFinished,
+ base::Unretained(this)));
+ m_taskRunner.reset();
+ m_readyToUpdate = false;
+ if (m_frontBuffer) {
+ m_readyWithTexture = true;
+ m_frontBuffer->beginPresent();
+ }
+ }
+}
+
+void NativeSkiaOutputDevice::waitForTexture()
+{
+ if (m_readyWithTexture)
+ m_frontBuffer->consumeFence();
+}
+
+void NativeSkiaOutputDevice::releaseTexture()
+{
+ if (m_readyWithTexture) {
+ m_frontBuffer->endPresent();
+ m_readyWithTexture = false;
+ }
+}
+
+#ifdef Q_OS_MACOS
+QSGTexture *makeMetalTexture(QQuickWindow *win, IOSurfaceRef io_surface, uint io_surface_plane, int width, int height, uint32_t textureOptions);
+
+QSGTexture *NativeSkiaOutputDevice::texture(QQuickWindow *win, uint32_t textureOptions)
+{
+ if (!m_frontBuffer || !m_readyWithTexture)
+ return nullptr;
+ gl::GLImageIOSurface *gl_image_iosurface = gl::GLImageIOSurface::FromGLImage(m_frontBuffer->glImage());
+ QSGTexture *texture = nullptr;
+ if (gl_image_iosurface) {
+ texture = makeMetalTexture(win, gl_image_iosurface->io_surface().release(), /* plane */ 0,
+ m_shape.characterization.width(), m_shape.characterization.height(),
+ textureOptions);
+ } else {
+ qWarning() << "GLImage not an IOSURFACE";
+ }
+
+ return texture;
+}
+#else
+QSGTexture *NativeSkiaOutputDevice::texture(QQuickWindow *, uint32_t)
+{
+ // Add Windows and Linux versions.
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+#endif
+
+bool NativeSkiaOutputDevice::textureIsFlipped()
+{
+ return true;
+}
+
+QSize NativeSkiaOutputDevice::size()
+{
+ return m_frontBuffer ? toQt(m_frontBuffer->shape().characterization.dimensions()) : QSize();
+}
+
+bool NativeSkiaOutputDevice::requiresAlphaChannel()
+{
+ return m_requiresAlpha;
+}
+
+float NativeSkiaOutputDevice::devicePixelRatio()
+{
+ return m_frontBuffer ? m_frontBuffer->shape().devicePixelRatio : 1;
+}
+
+void NativeSkiaOutputDevice::SwapBuffersFinished()
+{
+ {
+ QMutexLocker locker(&m_mutex);
+ std::swap(m_backBuffer, m_middleBuffer);
+ }
+
+ FinishSwapBuffers(gfx::SwapCompletionResult(gfx::SwapResult::SWAP_ACK),
+ gfx::Size(m_shape.characterization.width(), m_shape.characterization.height()),
+ std::move(m_frame));
+}
+
+} // namespace QtWebEngineCore
diff --git a/src/core/compositor/native_skia_output_device.h b/src/core/compositor/native_skia_output_device.h
new file mode 100644
index 000000000..450f909b0
--- /dev/null
+++ b/src/core/compositor/native_skia_output_device.h
@@ -0,0 +1,103 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef NATIVE_SKIA_OUTPUT_DEVICE_H
+#define NATIVE_SKIA_OUTPUT_DEVICE_H
+
+#include "compositor.h"
+
+#include "base/threading/thread_task_runner_handle.h"
+#include "components/viz/service/display_embedder/skia_output_device.h"
+#include "gpu/command_buffer/service/shared_context_state.h"
+
+#include <QMutex>
+
+QT_BEGIN_NAMESPACE
+class QQuickWindow;
+QT_END_NAMESPACE
+
+namespace gpu {
+class SharedImageFactory;
+class SharedImageRepresentationFactory;
+}
+
+namespace viz {
+class SkiaOutputSurfaceDependency;
+}
+
+namespace QtWebEngineCore {
+
+class NativeSkiaOutputDevice final : public viz::SkiaOutputDevice, public Compositor
+{
+public:
+ NativeSkiaOutputDevice(scoped_refptr<gpu::SharedContextState> contextState,
+ bool requiresAlpha,
+ gpu::MemoryTracker *memoryTracker,
+ viz::SkiaOutputSurfaceDependency *dependency,
+ gpu::SharedImageFactory *shared_image_factory,
+ gpu::SharedImageRepresentationFactory *shared_image_representation_factory,
+ DidSwapBufferCompleteCallback didSwapBufferCompleteCallback);
+ ~NativeSkiaOutputDevice() override;
+
+ // Overridden from SkiaOutputDevice.
+ void SetFrameSinkId(const viz::FrameSinkId &frame_sink_id) override;
+ bool Reshape(const SkSurfaceCharacterization &characterization,
+ const gfx::ColorSpace& colorSpace,
+ float device_scale_factor,
+ gfx::OverlayTransform transform) override;
+ void SwapBuffers(BufferPresentedCallback feedback,
+ viz::OutputSurfaceFrame frame) override;
+ void EnsureBackbuffer() override;
+ void DiscardBackbuffer() override;
+ SkSurface *BeginPaint(std::vector<GrBackendSemaphore> *semaphores) override;
+ void EndPaint() override;
+
+ // Overridden from Compositor.
+ void swapFrame() override;
+ void waitForTexture() override;
+ void releaseTexture() override;
+ QSGTexture *texture(QQuickWindow *win, uint32_t textureOptions) override;
+ bool textureIsFlipped() override;
+ QSize size() override;
+ bool requiresAlphaChannel() override;
+ float devicePixelRatio() override;
+
+private:
+ struct Shape
+ {
+ SkSurfaceCharacterization characterization;
+ float devicePixelRatio;
+ gfx::ColorSpace colorSpace;
+
+ bool operator==(const Shape &that) const
+ {
+ return (characterization == that.characterization &&
+ devicePixelRatio == that.devicePixelRatio &&
+ colorSpace == that.colorSpace);
+ }
+ bool operator!=(const Shape &that) const { return !(*this == that); }
+ };
+
+ class Buffer;
+ friend class NativeSkiaOutputDevice::Buffer;
+ void SwapBuffersFinished();
+
+ mutable QMutex m_mutex;
+ Shape m_shape;
+ std::unique_ptr<Buffer> m_frontBuffer;
+ std::unique_ptr<Buffer> m_middleBuffer;
+ std::unique_ptr<Buffer> m_backBuffer;
+ viz::OutputSurfaceFrame m_frame;
+ bool m_readyToUpdate = false;
+ bool m_readyWithTexture = false;
+ bool m_requiresAlpha;
+ scoped_refptr<base::SingleThreadTaskRunner> m_taskRunner;
+
+ const raw_ptr<gpu::SharedImageFactory> m_factory;
+ const raw_ptr<gpu::SharedImageRepresentationFactory> m_representationFactory;
+ const raw_ptr<viz::SkiaOutputSurfaceDependency> m_deps;
+};
+
+} // namespace QtWebEngineCore
+
+#endif // !NATIVE_SKIA_OUTPUT_DEVICE_H
diff --git a/src/core/compositor/native_skia_output_device_mac.mm b/src/core/compositor/native_skia_output_device_mac.mm
new file mode 100644
index 000000000..51b11b13f
--- /dev/null
+++ b/src/core/compositor/native_skia_output_device_mac.mm
@@ -0,0 +1,30 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#import <IOSurface/IOSurface.h>
+#import <Metal/Metal.h>
+
+#include <QtCore/qtconfigmacros.h>
+
+QT_BEGIN_NAMESPACE
+class QSGTexture;
+class QQuickWindow;
+QT_END_NAMESPACE
+
+@class MTLDevice;
+
+namespace QtWebEngineCore {
+QSGTexture *makeMetalTexture2(QQuickWindow *win, id<MTLTexture> mtlTexture, int width, int height, uint32_t textureOptions);
+MTLDevice *getRhiDev(QQuickWindow *win);
+
+QSGTexture *makeMetalTexture(QQuickWindow *win, IOSurfaceRef io_surface, uint io_surface_plane, int width, int height, uint32_t textureOptions)
+{
+ auto desc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
+ width:width height:height mipmapped:false];
+
+ auto device = getRhiDev(win);
+ auto texture = [device newTextureWithDescriptor:desc iosurface:io_surface plane:io_surface_plane];
+ return makeMetalTexture2(win, texture, width, height, textureOptions);
+}
+
+} // namespace
diff --git a/src/core/compositor/native_skia_output_device_mac2.mm b/src/core/compositor/native_skia_output_device_mac2.mm
new file mode 100644
index 000000000..645f26c61
--- /dev/null
+++ b/src/core/compositor/native_skia_output_device_mac2.mm
@@ -0,0 +1,25 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <qquickwindow.h>
+#include <qsgrendererinterface.h>
+#include <qsgtexture.h>
+
+@class MTLDevice;
+@protocol MTLTexture;
+
+namespace QtWebEngineCore {
+
+MTLDevice *getRhiDev(QQuickWindow *win)
+{
+ QSGRendererInterface *ri = win->rendererInterface();
+ return static_cast<MTLDevice *>(ri->getResource(win, QSGRendererInterface::DeviceResource));
+}
+
+QSGTexture *makeMetalTexture2(QQuickWindow *win, id<MTLTexture> mtlTexture, int width, int height, uint32_t textureOptions)
+{
+ QQuickWindow::CreateTextureOptions texOpts(textureOptions);
+ return QNativeInterface::QSGMetalTexture::fromNative(mtlTexture, win, {width, height}, texOpts);
+}
+
+} // namespace
diff --git a/src/core/ozone/gl_share_context_qt.cpp b/src/core/ozone/gl_share_context_qt.cpp
index 086317b46..0290d7123 100644
--- a/src/core/ozone/gl_share_context_qt.cpp
+++ b/src/core/ozone/gl_share_context_qt.cpp
@@ -5,6 +5,9 @@
#include <QtGui/qtgui-config.h>
#include <qpa/qplatformnativeinterface.h>
+#include "ui/gl/gl_context_egl.h"
+#include "ui/gl/gl_implementation.h"
+
#if QT_CONFIG(opengl)
#include <QtGui/qopenglcontext_platform.h>
#include <QOpenGLContext>
@@ -59,6 +62,11 @@ unsigned int QtShareGLContext::CheckStickyGraphicsResetStatusImpl()
void ShareGroupQt::AboutToAddFirstContext()
{
+ if (gl::GetGLImplementation() == gl::kGLImplementationEGLANGLE) {
+ m_shareContextQt = new gl::GLContextEGL(nullptr);
+ return;
+ }
+
#if QT_CONFIG(opengl)
// This currently has to be setup by ::main in all applications using QQuickWebEngineView with
// delegated rendering.
diff --git a/src/core/ozone/gl_share_context_qt.h b/src/core/ozone/gl_share_context_qt.h
index ba66b222c..89be00421 100644
--- a/src/core/ozone/gl_share_context_qt.h
+++ b/src/core/ozone/gl_share_context_qt.h
@@ -57,7 +57,7 @@ public:
void AboutToAddFirstContext() override;
private:
- scoped_refptr<QtShareGLContext> m_shareContextQt;
+ scoped_refptr<gl::GLContext> m_shareContextQt;
};
} // namespace
#endif
diff --git a/src/core/render_widget_host_view_qt_delegate_item.cpp b/src/core/render_widget_host_view_qt_delegate_item.cpp
index 2bade607e..8579ce51d 100644
--- a/src/core/render_widget_host_view_qt_delegate_item.cpp
+++ b/src/core/render_widget_host_view_qt_delegate_item.cpp
@@ -321,6 +321,8 @@ void RenderWidgetHostViewQtDelegateItem::itemChange(ItemChange change, const Ite
if (value.window) {
m_windowConnections.append(connect(value.window, &QQuickWindow::beforeRendering,
this, &RenderWidgetHostViewQtDelegateItem::onBeforeRendering, Qt::DirectConnection));
+ m_windowConnections.append(connect(value.window, &QQuickWindow::afterFrameEnd,
+ this, &RenderWidgetHostViewQtDelegateItem::onAfterRendering, Qt::DirectConnection));
m_windowConnections.append(connect(value.window, SIGNAL(xChanged(int)), SLOT(onWindowPosChanged())));
m_windowConnections.append(connect(value.window, SIGNAL(yChanged(int)), SLOT(onWindowPosChanged())));
#if QT_CONFIG(webengine_vulkan)
@@ -348,15 +350,22 @@ QSGNode *RenderWidgetHostViewQtDelegateItem::updatePaintNode(QSGNode *oldNode, U
{
auto comp = compositor();
if (!comp)
- return nullptr;
+ return oldNode;
QQuickWindow *win = QQuickItem::window();
+ QSGImageNode *node = nullptr;
// Delete old node before swapFrame to decrement refcount of
// QImage in software mode.
- delete oldNode;
- QSGImageNode *node = win->createImageNode();
- node->setOwnsTexture(true);
+ if (comp->type() == Compositor::Type::Software)
+ delete oldNode;
+ else
+ node = static_cast<QSGImageNode*>(oldNode);
+
+ if (!node) {
+ node = win->createImageNode();
+ node->setOwnsTexture(true);
+ }
comp->swapFrame();
@@ -364,36 +373,22 @@ QSGNode *RenderWidgetHostViewQtDelegateItem::updatePaintNode(QSGNode *oldNode, U
QSizeF texSizeInDips = QSizeF(texSize) / comp->devicePixelRatio();
node->setRect(QRectF(QPointF(0, 0), texSizeInDips));
- if (comp->type() == Compositor::Type::Software) {
- QImage image = comp->image();
- node->setTexture(win->createTextureFromImage(image));
-#if QT_CONFIG(opengl)
- } else if (comp->type() == Compositor::Type::OpenGL) {
- QQuickWindow::CreateTextureOptions texOpts;
- if (comp->requiresAlphaChannel() || m_clearColor.alpha() < 255)
- texOpts.setFlag(QQuickWindow::TextureHasAlphaChannel);
- else
- texOpts.setFlag(QQuickWindow::TextureIsOpaque);
- int texId = comp->textureId();
- node->setTexture(QNativeInterface::QSGOpenGLTexture::fromNative(texId, win, texSize, texOpts));
- node->setTextureCoordinatesTransform(QSGImageNode::MirrorVertically);
-#endif
-#if QT_CONFIG(webengine_vulkan)
- } else if (comp->type() == Compositor::Type::Vulkan) {
- QQuickWindow::CreateTextureOptions texOpts;
- if (comp->requiresAlphaChannel() || m_clearColor.alpha() < 255)
- texOpts.setFlag(QQuickWindow::TextureHasAlphaChannel);
- else
- texOpts.setFlag(QQuickWindow::TextureIsOpaque);
-
- VkImage image = comp->vkImage(win);
- VkImageLayout layout = comp->vkImageLayout();
- node->setTexture(QNativeInterface::QSGVulkanTexture::fromNative(image, layout, win, texSize,
- texOpts));
- node->setTextureCoordinatesTransform(QSGImageNode::MirrorVertically);
-#endif // QT_CONFIG(webengine_vulkan)
+ QQuickWindow::CreateTextureOptions texOpts;
+ if (comp->requiresAlphaChannel() || m_clearColor.alpha() < 255)
+ texOpts.setFlag(QQuickWindow::TextureHasAlphaChannel);
+ else
+ texOpts.setFlag(QQuickWindow::TextureIsOpaque);
+ QSGTexture *texture = comp->texture(win, texOpts);
+ if (texture) {
+ node->setTexture(texture);
+ if (comp->textureIsFlipped())
+ node->setTextureCoordinatesTransform(QSGImageNode::MirrorVertically);
} else {
- Q_UNREACHABLE();
+ if (!oldNode || comp->type() == Compositor::Type::Software) {
+ qDebug("Compositor returned null texture");
+ delete node;
+ return nullptr;
+ }
}
return node;
@@ -407,6 +402,14 @@ void RenderWidgetHostViewQtDelegateItem::onBeforeRendering()
comp->waitForTexture();
}
+void RenderWidgetHostViewQtDelegateItem::onAfterRendering()
+{
+ auto comp = compositor();
+ if (!comp || comp->type() != Compositor::Type::NativeBuffer)
+ return;
+ comp->releaseTexture();
+}
+
void RenderWidgetHostViewQtDelegateItem::onWindowPosChanged()
{
m_client->visualPropertiesChanged();
diff --git a/src/core/render_widget_host_view_qt_delegate_item.h b/src/core/render_widget_host_view_qt_delegate_item.h
index 6f3289157..6af81fea3 100644
--- a/src/core/render_widget_host_view_qt_delegate_item.h
+++ b/src/core/render_widget_host_view_qt_delegate_item.h
@@ -100,6 +100,7 @@ protected:
private Q_SLOTS:
void onBeforeRendering();
+ void onAfterRendering();
void onWindowPosChanged();
void releaseVulkanResources();
void onHide();
diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp
index 095b0ed50..fc34957b0 100644
--- a/src/core/web_engine_context.cpp
+++ b/src/core/web_engine_context.cpp
@@ -130,7 +130,8 @@ Q_LOGGING_CATEGORY(webEngineContextLog, "qt.webenginecontext")
static bool usingSupportedSGBackend()
{
if (QQuickWindow::graphicsApi() != QSGRendererInterface::OpenGL
- && QQuickWindow::graphicsApi() != QSGRendererInterface::Vulkan)
+ && QQuickWindow::graphicsApi() != QSGRendererInterface::Vulkan
+ && QQuickWindow::graphicsApi() != QSGRendererInterface::Metal)
return false;
const QStringList args = QGuiApplication::arguments();
@@ -190,6 +191,11 @@ static const char *getGLType(bool enableGLSoftwareRendering, bool disableGpu)
if (disableGpu || (!tryGL && !enableGLSoftwareRendering))
return glType;
+#if defined(Q_OS_MACOS)
+ if (QQuickWindow::graphicsApi() == QSGRendererInterface::Metal)
+ return gl::kGLImplementationANGLEName;
+#endif
+
if (!qt_gl_global_share_context() || !qt_gl_global_share_context()->isValid()) {
qWarning("WebEngineContext is used before QtWebEngineQuick::initialize() or OpenGL context "
"creation failed.");
@@ -227,8 +233,14 @@ static const char *getGLType(bool enableGLSoftwareRendering, bool disableGpu)
return glType;
}
#else
-static const char *getGLType(bool enableGLSoftwareRendering, bool disableGpu)
+static const char *getGLType(bool /*enableGLSoftwareRendering*/, bool disableGpu)
{
+ if (disableGpu)
+ return gl::kGLImplementationDisabledName;
+#if defined(Q_OS_MACOS)
+ if (QQuickWindow::graphicsApi() == QSGRendererInterface::Metal)
+ return gl::kGLImplementationANGLEName;
+#endif
return gl::kGLImplementationDisabledName;
}
#endif // QT_CONFIG(opengl)
@@ -242,34 +254,41 @@ void dummyGetPluginCallback(const std::vector<content::WebPluginInfo>&)
static void logContext(const char *glType, base::CommandLine *cmd)
{
if (Q_UNLIKELY(webEngineContextLog().isDebugEnabled())) {
-#if QT_CONFIG(opengl)
- const QSurfaceFormat sharedFormat = qt_gl_global_share_context()->format();
- const auto profile = QMetaEnum::fromType<QSurfaceFormat::OpenGLContextProfile>().valueToKey(
- sharedFormat.profile());
- const auto type = QMetaEnum::fromType<QSurfaceFormat::RenderableType>().valueToKey(
- sharedFormat.renderableType());
const base::CommandLine::SwitchMap switch_map = cmd->GetSwitches();
QStringList params;
for (const auto &pair : switch_map)
params << " * " << toQt(pair.first)
<< toQt(pair.second) << "\n";
+#if QT_CONFIG(opengl)
+ const QSurfaceFormat sharedFormat = qt_gl_global_share_context() ? qt_gl_global_share_context()->format() : QSurfaceFormat::defaultFormat();
+ const auto profile = QMetaEnum::fromType<QSurfaceFormat::OpenGLContextProfile>().valueToKey(
+ sharedFormat.profile());
+ const auto type = QMetaEnum::fromType<QSurfaceFormat::RenderableType>().valueToKey(
+ sharedFormat.renderableType());
qCDebug(webEngineContextLog,
- "\n\nGL Type: %s\n"
+ "\n\nChromium GL Backend: %s\n"
"Surface Type: %s\n"
"Surface Profile: %s\n"
"Surface Version: %d.%d\n"
"QSG RHI Backend: %s\n"
"Using Supported QSG Backend: %s\n"
"Using Software Dynamic GL: %s\n"
+ "Using Shared GL: %s\n"
"Using Multithreaded OpenGL: %s\n\n"
"Init Parameters:\n %s",
glType, type, profile, sharedFormat.majorVersion(), sharedFormat.minorVersion(),
qUtf8Printable(QSGRhiSupport::instance()->rhiBackendName()),
usingSupportedSGBackend() ? "yes" : "no", usingSoftwareDynamicGL() ? "yes" : "no",
+ qt_gl_global_share_context() ? "yes" : "no",
!WebEngineContext::isGpuServiceOnUIThread() ? "yes" : "no",
qPrintable(params.join(" ")));
#else
- qCDebug(webEngineContextLog) << "WebEngine compiled with no opengl enabled.";
+ qCDebug(webEngineContextLog,
+ "\n\nChromium GL Backend: %s\n"
+ "QSG RHI Backend: %s\n\n"
+ "Init Parameters:\n %s",
+ glType, qUtf8Printable(QSGRhiSupport::instance()->rhiBackendName()),
+ qPrintable(params.join(" ")));
#endif //QT_CONFIG(opengl)
}
}
@@ -716,19 +735,21 @@ WebEngineContext::WebEngineContext()
parsedCommandLine->AppendSwitch(switches::kIgnoreGpuBlocklist);
}
#if QT_CONFIG(opengl)
- const QSurfaceFormat sharedFormat = QOpenGLContext::globalShareContext()->format();
- if (sharedFormat.profile() == QSurfaceFormat::CompatibilityProfile)
- parsedCommandLine->AppendSwitch(switches::kCreateDefaultGLContext);
+ if (glType != gl::kGLImplementationANGLEName) {
+ const QSurfaceFormat sharedFormat = QOpenGLContext::globalShareContext()->format();
+ if (sharedFormat.profile() == QSurfaceFormat::CompatibilityProfile)
+ parsedCommandLine->AppendSwitch(switches::kCreateDefaultGLContext);
#if defined(Q_OS_WIN)
- // This switch is used in Chromium's gl_context_wgl.cc file to determine whether to create
- // an OpenGL Core Profile context. If the switch is not set, it would always try to create a
- // Core Profile context, even if Qt uses a legacy profile, which causes
- // "Could not share GL contexts" warnings, because it's not possible to share between Core and
- // legacy profiles. See GLContextWGL::Initialize().
- if (sharedFormat.renderableType() == QSurfaceFormat::OpenGL
- && sharedFormat.profile() != QSurfaceFormat::CoreProfile)
- parsedCommandLine->AppendSwitch(switches::kDisableES3GLContext);
+ // This switch is used in Chromium's gl_context_wgl.cc file to determine whether to create
+ // an OpenGL Core Profile context. If the switch is not set, it would always try to create a
+ // Core Profile context, even if Qt uses a legacy profile, which causes
+ // "Could not share GL contexts" warnings, because it's not possible to share between Core and
+ // legacy profiles. See GLContextWGL::Initialize().
+ if (sharedFormat.renderableType() == QSurfaceFormat::OpenGL
+ && sharedFormat.profile() != QSurfaceFormat::CoreProfile)
+ parsedCommandLine->AppendSwitch(switches::kDisableES3GLContext);
#endif
+ }
#endif //QT_CONFIG(opengl)
} else if (!disableGpu) {
parsedCommandLine->AppendSwitch(switches::kDisableGpu);
diff --git a/src/webenginequick/api/qtwebenginequickglobal.cpp b/src/webenginequick/api/qtwebenginequickglobal.cpp
index b16305dae..60f7991c8 100644
--- a/src/webenginequick/api/qtwebenginequickglobal.cpp
+++ b/src/webenginequick/api/qtwebenginequickglobal.cpp
@@ -47,7 +47,7 @@ void initialize()
// call initialize the same way as widgets do
qAddPreRoutine(QtWebEngineCore::initialize);
auto api = QQuickWindow::graphicsApi();
- if (api != QSGRendererInterface::OpenGLRhi && api != QSGRendererInterface::VulkanRhi)
+ if (api != QSGRendererInterface::OpenGLRhi && api != QSGRendererInterface::VulkanRhi && api != QSGRendererInterface::MetalRhi)
QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGLRhi);
}
} // namespace QtWebEngineQuick