diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2023-03-15 15:07:19 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2023-04-12 12:13:57 +0200 |
commit | cceda0895b3aca208e37669b2acb38c01e9f1774 (patch) | |
tree | 1a28f9521c00b1fdb6be66bc7a423b1086ce06bf /src | |
parent | 6cfbef4474d2cb15fec37103c3609da919f8a4ca (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>
Diffstat (limited to 'src')
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 |