diff options
author | Jüri Valdmann <juri.valdmann@qt.io> | 2019-08-13 14:57:05 +0200 |
---|---|---|
committer | Jüri Valdmann <juri.valdmann@qt.io> | 2019-08-22 12:24:38 +0200 |
commit | f0c471d9e2f3e9808cbf8c57bee533e8254ad1c5 (patch) | |
tree | fb22f4c4713c728821f051be644c2ec898ed7608 | |
parent | e9ed235b9f2cd5987ea24575234fb0ce2b58f753 (diff) |
Use ui::Compositor
Needs corresponding 3rdparty change.
Fixes: QTBUG-71885
Change-Id: I791bc3da5a7a66e03470e9e05bf25a997101b018
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
20 files changed, 1573 insertions, 32 deletions
diff --git a/examples/webengine/minimal/main.cpp b/examples/webengine/minimal/main.cpp index 9db6ea6aa..8bcd0e0e9 100644 --- a/examples/webengine/minimal/main.cpp +++ b/examples/webengine/minimal/main.cpp @@ -56,6 +56,7 @@ int main(int argc, char *argv[]) { QCoreApplication::setOrganizationName("QtExamples"); QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts); QGuiApplication app(argc, argv); QtWebEngine::initialize(); diff --git a/src/3rdparty b/src/3rdparty -Subproject f5613a4bc321972b8f72654d4c4bc9ba0c36ffb +Subproject feccbb4ea7fa685dcd013f5a3f6c14ea768636c diff --git a/src/core/compositor/compositor_resource_fence.cpp b/src/core/compositor/compositor_resource_fence.cpp index 7fc5fbfb2..4179395d6 100644 --- a/src/core/compositor/compositor_resource_fence.cpp +++ b/src/core/compositor/compositor_resource_fence.cpp @@ -146,12 +146,12 @@ void CompositorResourceFence::release() } // static -scoped_refptr<CompositorResourceFence> CompositorResourceFence::create() +scoped_refptr<CompositorResourceFence> CompositorResourceFence::create(std::unique_ptr<gl::GLFence> glFence) { - if (gl::GLContext::GetCurrent() && gl::GLFence::IsSupported()) { - std::unique_ptr<gl::GLFence> glFence{gl::GLFence::Create()}; + if (!glFence && gl::GLContext::GetCurrent() && gl::GLFence::IsSupported()) + glFence = gl::GLFence::Create(); + if (glFence) return base::MakeRefCounted<CompositorResourceFence>(glFence->Transfer()); - } return nullptr; } diff --git a/src/core/compositor/compositor_resource_fence.h b/src/core/compositor/compositor_resource_fence.h index 1c2ea3695..196297f78 100644 --- a/src/core/compositor/compositor_resource_fence.h +++ b/src/core/compositor/compositor_resource_fence.h @@ -60,7 +60,7 @@ public: void release(); // May be used only by GPU thread. - static scoped_refptr<CompositorResourceFence> create(); + static scoped_refptr<CompositorResourceFence> create(std::unique_ptr<gl::GLFence> glFence = nullptr); private: gl::TransferableFence m_sync; diff --git a/src/core/compositor/display_consumer.h b/src/core/compositor/display_consumer.h new file mode 100644 index 000000000..d220088ad --- /dev/null +++ b/src/core/compositor/display_consumer.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DISPLAY_CONSUMER_H +#define DISPLAY_CONSUMER_H + +#include "qtwebenginecoreglobal_p.h" + +namespace QtWebEngineCore { + +// Receives composited frames for display. +class DisplayConsumer +{ +public: + // Schedule a call to updatePaintNode soon. + // + // Called on the consumer thread. + virtual void scheduleUpdate() = 0; + +protected: + ~DisplayConsumer() {} +}; + +} // namespace QtWebEngineCore + +#endif // !DISPLAY_CONSUMER_H diff --git a/src/core/compositor/display_frame_sink.cpp b/src/core/compositor/display_frame_sink.cpp new file mode 100644 index 000000000..945600299 --- /dev/null +++ b/src/core/compositor/display_frame_sink.cpp @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "display_frame_sink.h" + +#include <QMap> + +namespace QtWebEngineCore { + +namespace { + +class DisplayFrameSinkMap +{ +public: + static DisplayFrameSinkMap *instance() + { + static DisplayFrameSinkMap map; + return ↦ + } + + scoped_refptr<DisplayFrameSink> findOrCreate(viz::FrameSinkId frameSinkId) + { + QMutexLocker locker(&m_mutex); + auto it = m_map.find(frameSinkId); + if (it == m_map.end()) + it = m_map.insert(frameSinkId, new DisplayFrameSink(frameSinkId)); + return *it; + } + + void remove(viz::FrameSinkId frameSinkId) + { + QMutexLocker locker(&m_mutex); + m_map.remove(frameSinkId); + } + +private: + mutable QMutex m_mutex; + QMap<viz::FrameSinkId, DisplayFrameSink *> m_map; +}; + +} // namespace + +// static +scoped_refptr<DisplayFrameSink> DisplayFrameSink::findOrCreate(viz::FrameSinkId frameSinkId) +{ + return DisplayFrameSinkMap::instance()->findOrCreate(frameSinkId); +} + +DisplayFrameSink::DisplayFrameSink(viz::FrameSinkId frameSinkId) + : m_frameSinkId(frameSinkId) +{ + DCHECK(m_frameSinkId.is_valid()); +} + +DisplayFrameSink::~DisplayFrameSink() +{ + DisplayFrameSinkMap::instance()->remove(m_frameSinkId); +} + +void DisplayFrameSink::connect(DisplayConsumer *consumer) +{ + QMutexLocker locker(&m_mutex); + DCHECK(m_consumer == nullptr); + m_consumer = consumer; +} + +void DisplayFrameSink::connect(DisplayProducer *producer) +{ + QMutexLocker locker(&m_mutex); + DCHECK(m_producer == nullptr); + m_producer = producer; +} + +void DisplayFrameSink::disconnect(DisplayConsumer *consumer) +{ + QMutexLocker locker(&m_mutex); + DCHECK(m_consumer == consumer); + m_consumer = nullptr; +} + +void DisplayFrameSink::disconnect(DisplayProducer *producer) +{ + QMutexLocker locker(&m_mutex); + DCHECK(m_producer == producer); + m_producer = nullptr; +} + +void DisplayFrameSink::scheduleUpdate() +{ + QMutexLocker locker(&m_mutex); + if (m_consumer) + m_consumer->scheduleUpdate(); +} + +QSGNode *DisplayFrameSink::updatePaintNode(QSGNode *oldNode, RenderWidgetHostViewQtDelegate *delegate) +{ + QMutexLocker locker(&m_mutex); + QSGNode *newNode = oldNode; + if (m_producer) + newNode = m_producer->updatePaintNode(oldNode, delegate); + return newNode; +} + +} // namespace QtWebEngineCore diff --git a/src/core/compositor/display_frame_sink.h b/src/core/compositor/display_frame_sink.h new file mode 100644 index 000000000..f620dc4f2 --- /dev/null +++ b/src/core/compositor/display_frame_sink.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DISPLAY_FRAME_SINK_H +#define DISPLAY_FRAME_SINK_H + +#include "display_consumer.h" +#include "display_producer.h" + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_refptr.h" +#include "components/viz/common/surfaces/frame_sink_id.h" + +#include <QMutex> + +namespace QtWebEngineCore { + +// Connects a DisplayConsumer with a DisplayProducer. +class DisplayFrameSink final : public base::RefCountedThreadSafe<DisplayFrameSink> +{ +public: + static scoped_refptr<DisplayFrameSink> findOrCreate(viz::FrameSinkId frameSinkId); + DisplayFrameSink(viz::FrameSinkId frameSinkId); + ~DisplayFrameSink(); + void connect(DisplayConsumer *consumer); + void connect(DisplayProducer *producer); + void disconnect(DisplayConsumer *consumer); + void disconnect(DisplayProducer *producer); + void scheduleUpdate(); + QSGNode *updatePaintNode(QSGNode *oldNode, RenderWidgetHostViewQtDelegate *delegate); + +private: + const viz::FrameSinkId m_frameSinkId; + mutable QMutex m_mutex; + DisplayProducer *m_producer = nullptr; + DisplayConsumer *m_consumer = nullptr; +}; + +} // namespace QtWebEngineCore + +#endif // !DISPLAY_FRAME_SINK_H diff --git a/src/core/compositor/display_gl_output_surface.cpp b/src/core/compositor/display_gl_output_surface.cpp new file mode 100644 index 000000000..5a78b8322 --- /dev/null +++ b/src/core/compositor/display_gl_output_surface.cpp @@ -0,0 +1,292 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "display_gl_output_surface.h" + +#include "chromium_gpu_helper.h" + +#include "base/threading/thread_task_runner_handle.h" +#include "components/viz/service/display/display.h" +#include "components/viz/service/display/output_surface_frame.h" +#include "gpu/command_buffer/client/gles2_implementation.h" +#include "gpu/command_buffer/client/gles2_interface.h" +#include "gpu/command_buffer/service/mailbox_manager.h" +#include "gpu/command_buffer/service/texture_base.h" +#include "gpu/ipc/in_process_command_buffer.h" +#include "ui/gl/color_space_utils.h" + +namespace QtWebEngineCore { + +DisplayGLOutputSurface::DisplayGLOutputSurface( + scoped_refptr<viz::VizProcessContextProvider> contextProvider, + viz::UpdateVSyncParametersCallback callback) + : OutputSurface(contextProvider) + , m_commandBuffer(contextProvider->command_buffer()) + , m_gl(contextProvider->ContextGL()) +{ + capabilities_.uses_default_gl_framebuffer = false; + m_gl->GenFramebuffers(1, &m_fboId); + contextProvider->SetUpdateVSyncParametersCallback(std::move(callback)); +} + +DisplayGLOutputSurface::~DisplayGLOutputSurface() +{ + m_gl->DeleteFramebuffers(1, &m_fboId); + if (m_sink) + m_sink->disconnect(this); +} + +// Called from viz::Display::Initialize. +void DisplayGLOutputSurface::BindToClient(viz::OutputSurfaceClient *client) +{ + m_display = static_cast<viz::Display *>(client); + m_sink = DisplayFrameSink::findOrCreate(m_display->frame_sink_id()); + m_sink->connect(this); +} + +// Triggered by ui::Compositor::SetVisible(true). +void DisplayGLOutputSurface::EnsureBackbuffer() +{ +} + +// Triggered by ui::Compositor::SetVisible(false). Framebuffer must be cleared. +void DisplayGLOutputSurface::DiscardBackbuffer() +{ + NOTIMPLEMENTED(); + // m_gl->DiscardBackbufferCHROMIUM(); +} + +// Called from viz::DirectRenderer::DrawFrame before rendering starts, but only +// if the parameters differ from the previous Reshape call. +// +// Parameters: +// +// - sizeInPixels comes from ui::Compositor::SetScaleAndSize via +// viz::HostContextFactoryPrivate::ResizeDisplay. +// +// - devicePixelRatio comes from viz::CompositorFrame::device_scale_factor() +// via viz::RootCompositorFrameSinkImpl::SubmitCompositorFrame and +// viz::Display::SetLocalSurfaceId. +// +// - colorSpace and hasAlpha correspond to the color_space and +// has_transparent_background properties of the root viz::RenderPass. +// +// - useStencil should create a stencil buffer, but this is only needed for +// overdraw feedback (--show-overdraw-feedback), so it's safe to ignore. +// Accordingly, capabilities_.supports_stencil should be set to false. +// +void DisplayGLOutputSurface::Reshape(const gfx::Size &sizeInPixels, + float devicePixelRatio, + const gfx::ColorSpace &colorSpace, + bool hasAlpha, + bool /*useStencil*/) +{ + m_currentShape = Shape{sizeInPixels, devicePixelRatio, colorSpace, hasAlpha}; + m_gl->ResizeCHROMIUM(sizeInPixels.width(), sizeInPixels.height(), devicePixelRatio, + gl::ColorSpaceUtils::GetGLColorSpace(colorSpace), hasAlpha); +} + +std::unique_ptr<DisplayGLOutputSurface::Buffer> DisplayGLOutputSurface::makeBuffer(const Shape &shape) +{ + std::unique_ptr<Buffer> buffer = std::make_unique<Buffer>(this); + buffer->shape = shape; + m_gl->GenTextures(1, &buffer->clientId); + m_gl->BindTexture(GL_TEXTURE_2D, buffer->clientId); + m_gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + m_gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + m_gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + m_gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + uint32_t width = shape.sizeInPixels.width(); + uint32_t height = shape.sizeInPixels.height(); + uint32_t format = shape.hasAlpha ? GL_RGBA : GL_RGB; + m_gl->TexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, nullptr); + return buffer; +} + +void DisplayGLOutputSurface::deleteBufferResources(Buffer *buffer) +{ + m_gl->DeleteTextures(1, &buffer->clientId); +} + +// Called by viz::GLRenderer during rendering whenever it switches to the root +// render pass. +void DisplayGLOutputSurface::BindFramebuffer() +{ + if (!m_backBuffer || m_backBuffer->shape != m_currentShape) + m_backBuffer = makeBuffer(m_currentShape); + + m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fboId); + m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_backBuffer->clientId, 0); +} + +// Called from viz::Display::DrawAndSwap after rendering. +// +// Parameters: +// +// - frame.size is the same as the size given to Reshape. +// +// - frame.sub_buffer_rect and frame.content_bounds are never used since these +// are only enabled if gl::GLSurface::SupportsPostSubBuffer() or +// gl::GLSurface::SupportsSwapBuffersWithBounds() are true, respectively, +// but this not the case for any offscreen gl::GLSurface. +// +// - frame.latency_info is viz::CompositorFrame::metadata.latency_info. +void DisplayGLOutputSurface::SwapBuffers(viz::OutputSurfaceFrame frame) +{ + DCHECK(frame.size == m_currentShape.sizeInPixels); + DCHECK(!frame.sub_buffer_rect.has_value()); + DCHECK(frame.content_bounds.empty()); + DCHECK(m_backBuffer); + + m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fboId); + m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + gpu::SyncToken syncToken; + m_gl->GenSyncTokenCHROMIUM(syncToken.GetData()); + + unsigned int clientId = m_backBuffer->clientId; + + // Now some thread-hopping: + // + // - We start here on the viz thread (client side of command buffer). + // + // - Then we'll jump to the gpu thread (service side of command buffer) to + // get the real OpenGL texture id. + // + // - Then we'll get a call from the Qt Quick Scene Graph thread (could be + // a separate thread or the main thread). + // + // - Finally we'll return to the viz thread to acknowledge the swap. + + { + QMutexLocker locker(&m_mutex); + m_taskRunner = base::ThreadTaskRunnerHandle::Get(); + m_middleBuffer = std::move(m_backBuffer); + m_middleBuffer->serviceId = 0; + } + + m_commandBuffer->GetTextureQt( + clientId, + base::BindOnce(&DisplayGLOutputSurface::swapBuffersOnGpuThread, base::Unretained(this)), + std::vector<gpu::SyncToken>{syncToken}); +} + +void DisplayGLOutputSurface::swapBuffersOnGpuThread(unsigned int id, std::unique_ptr<gl::GLFence> fence) +{ + { + QMutexLocker locker(&m_mutex); + m_middleBuffer->serviceId = id; + m_middleBuffer->fence = CompositorResourceFence::create(std::move(fence)); + } + + m_sink->scheduleUpdate(); +} + +void DisplayGLOutputSurface::swapBuffersOnVizThread() +{ + { + QMutexLocker locker(&m_mutex); + m_backBuffer = std::move(m_middleBuffer); + } + + m_display->DidReceiveSwapBuffersAck(); + m_display->DidReceivePresentationFeedback( + gfx::PresentationFeedback(base::TimeTicks::Now(), base::TimeDelta(), + gfx::PresentationFeedback::Flags::kVSync)); +} + +void DisplayGLOutputSurface::SetDrawRectangle(const gfx::Rect &) +{ +} + +// Returning nullptr here effectively disables viz::OverlayProcessor. +viz::OverlayCandidateValidator *DisplayGLOutputSurface::GetOverlayCandidateValidator() const +{ + return nullptr; +} + +// Returning true here will cause viz::GLRenderer to try to render the output +// surface as an overlay plane (see viz::DirectRenderer::DrawFrame and +// viz::GLRenderer::ScheduleOverlays). +bool DisplayGLOutputSurface::IsDisplayedAsOverlayPlane() const +{ + return false; +} + +// Only used if IsDisplayedAsOverlayPlane was true (called from +// viz::GLRenderer::ScheduleOverlays). +unsigned DisplayGLOutputSurface::GetOverlayTextureId() const +{ + return 0; +} + +// Only used if IsDisplayedAsOverlayPlane was true (called from +// viz::DirectRender::DrawFrame). +gfx::BufferFormat DisplayGLOutputSurface::GetOverlayBufferFormat() const +{ + return gfx::BufferFormat(); +} + +// Called by viz::GLRenderer but always false in all implementations except for +// android_webview::ParentOutputSurface. +bool DisplayGLOutputSurface::HasExternalStencilTest() const +{ + return false; +} + +// Only called if HasExternalStencilTest was true. Dead code? +void DisplayGLOutputSurface::ApplyExternalStencil() +{ + NOTREACHED(); +} + +// Called from GLRenderer::GetFramebufferCopyTextureFormat when using +// glCopyTexSubImage2D on our framebuffer. +uint32_t DisplayGLOutputSurface::GetFramebufferCopyTextureFormat() +{ + return GL_RGBA; +} + +// Called from viz::DirectRenderer::DrawFrame, only used for overlays. +unsigned DisplayGLOutputSurface::UpdateGpuFence() +{ + NOTREACHED(); + return 0; +} + +} // namespace QtWebEngineCore diff --git a/src/core/compositor/display_gl_output_surface.h b/src/core/compositor/display_gl_output_surface.h new file mode 100644 index 000000000..c42a6630a --- /dev/null +++ b/src/core/compositor/display_gl_output_surface.h @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DISPLAY_GL_OUTPUT_SURFACE_H +#define DISPLAY_GL_OUTPUT_SURFACE_H + +#include "compositor_resource_fence.h" +#include "display_frame_sink.h" + +#include "components/viz/common/display/update_vsync_parameters_callback.h" +#include "components/viz/service/display/output_surface.h" +#include "components/viz/service/display_embedder/viz_process_context_provider.h" +#include "gpu/command_buffer/common/mailbox.h" +#include "gpu/command_buffer/common/sync_token.h" + +namespace viz { +class Display; +class SyntheticBeginFrameSource; +} // namespace viz + +namespace QtWebEngineCore { + +// NOTE: Some methods are defined in display_gl_output_surface_qsg.cpp due +// to conflicts between Qt & Chromium OpenGL APIs. +class DisplayGLOutputSurface final : public viz::OutputSurface, public DisplayProducer +{ +public: + DisplayGLOutputSurface( + scoped_refptr<viz::VizProcessContextProvider> contextProvider, + viz::UpdateVSyncParametersCallback callback); + ~DisplayGLOutputSurface() override; + + // Overridden from viz::OutputSurface. + void BindToClient(viz::OutputSurfaceClient *client) override; + void EnsureBackbuffer() override; + void DiscardBackbuffer() override; + void BindFramebuffer() override; + void SetDrawRectangle(const gfx::Rect &drawRect) override; + viz::OverlayCandidateValidator *GetOverlayCandidateValidator() const override; + bool IsDisplayedAsOverlayPlane() const override; + unsigned GetOverlayTextureId() const override; + gfx::BufferFormat GetOverlayBufferFormat() const override; + void Reshape(const gfx::Size &size, + float devicePixelRatio, + const gfx::ColorSpace &colorSpace, + bool hasAlpha, + bool useStencil) override; + bool HasExternalStencilTest() const override; + void ApplyExternalStencil() override; + uint32_t GetFramebufferCopyTextureFormat() override; + void SwapBuffers(viz::OutputSurfaceFrame frame) override; + unsigned UpdateGpuFence() override; + + // Overridden from DisplayProducer. + QSGNode *updatePaintNode(QSGNode *oldNode, RenderWidgetHostViewQtDelegate *delegate) override; + +private: + struct Shape + { + gfx::Size sizeInPixels; + float devicePixelRatio; + gfx::ColorSpace colorSpace; + bool hasAlpha; + + bool operator==(const Shape &that) const + { + return (sizeInPixels == that.sizeInPixels && + devicePixelRatio == that.devicePixelRatio && + colorSpace == that.colorSpace && + hasAlpha == that.hasAlpha); + } + bool operator!=(const Shape &that) const { return !(*this == that); } + }; + + struct Buffer + { + DisplayGLOutputSurface *parent; + Shape shape; + uint32_t clientId = 0; + uint32_t serviceId = 0; + scoped_refptr<CompositorResourceFence> fence; + + Buffer(DisplayGLOutputSurface *parent) : parent(parent) {} + ~Buffer() { parent->deleteBufferResources(this); } + }; + + class Texture; + + void swapBuffersOnGpuThread(unsigned int id, std::unique_ptr<gl::GLFence> fence); + void swapBuffersOnVizThread(); + + std::unique_ptr<Buffer> makeBuffer(const Shape &shape); + void deleteBufferResources(Buffer *buffer); + void attachBuffer(); + void detachBuffer(); + + gpu::InProcessCommandBuffer *const m_commandBuffer; + gpu::gles2::GLES2Interface *const m_gl; + mutable QMutex m_mutex; + uint32_t m_fboId = 0; + viz::Display *m_display = nullptr; + scoped_refptr<DisplayFrameSink> m_sink; + Shape m_currentShape; + std::unique_ptr<Buffer> m_backBuffer; + std::unique_ptr<Buffer> m_middleBuffer; + std::unique_ptr<Buffer> m_frontBuffer; + scoped_refptr<base::SingleThreadTaskRunner> m_taskRunner; +}; + +} // namespace QtWebEngineCore + +#endif // !DISPLAY_GL_OUTPUT_SURFACE_H diff --git a/src/core/compositor/display_gl_output_surface_qsg.cpp b/src/core/compositor/display_gl_output_surface_qsg.cpp new file mode 100644 index 000000000..2f7b3de84 --- /dev/null +++ b/src/core/compositor/display_gl_output_surface_qsg.cpp @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "display_gl_output_surface.h" + +#include "compositor_resource_fence.h" +#include "render_widget_host_view_qt_delegate.h" +#include "type_conversion.h" + +#include <QOpenGLFunctions> +#include <QSGImageNode> +#include <QSGTexture> + +namespace QtWebEngineCore { + +class DisplayGLOutputSurface::Texture final : public QSGTexture +{ +public: + Texture(uint32_t id, QSize sizeInPixels, bool hasAlphaChannel, scoped_refptr<CompositorResourceFence> fence) + : m_id(id) + , m_sizeInPixels(sizeInPixels) + , m_hasAlphaChannel(hasAlphaChannel) + , m_fence(std::move(fence)) + { + } + + // QSGTexture: + int textureId() const override { return m_id; } + QSize textureSize() const override { return m_sizeInPixels; } + bool hasAlphaChannel() const override { return m_hasAlphaChannel; } + bool hasMipmaps() const override { return false; } + void bind() override + { + if (m_fence) { + m_fence->wait(); + m_fence.reset(); + } + + QOpenGLContext *context = QOpenGLContext::currentContext(); + QOpenGLFunctions *funcs = context->functions(); + funcs->glBindTexture(GL_TEXTURE_2D, m_id); + } + +private: + uint32_t m_id; + QSize m_sizeInPixels; + bool m_hasAlphaChannel; + scoped_refptr<CompositorResourceFence> m_fence; +}; + +QSGNode *DisplayGLOutputSurface::updatePaintNode(QSGNode *oldNode, RenderWidgetHostViewQtDelegate *delegate) +{ + { + QMutexLocker locker(&m_mutex); + if (m_middleBuffer && m_middleBuffer->serviceId) { + std::swap(m_middleBuffer, m_frontBuffer); + m_taskRunner->PostTask( + FROM_HERE, + base::BindOnce(&DisplayGLOutputSurface::swapBuffersOnVizThread, base::Unretained(this))); + m_taskRunner.reset(); + } + } + + if (!m_frontBuffer) + return oldNode; + + auto node = static_cast<QSGImageNode *>(oldNode); + if (!node) + node = delegate->createImageNode(); + + QSize sizeInPixels = toQt(m_frontBuffer->shape.sizeInPixels); + QSizeF sizeInDips = QSizeF(sizeInPixels) / m_frontBuffer->shape.devicePixelRatio; + QRectF rectInDips(QPointF(0, 0), sizeInDips); + node->setRect(rectInDips); + node->setOwnsTexture(true); + node->setTexture(new Texture(m_frontBuffer->serviceId, + sizeInPixels, + m_frontBuffer->shape.hasAlpha, + m_frontBuffer->fence)); + node->setTextureCoordinatesTransform(QSGImageNode::MirrorVertically); + + return node; +} + +} // namespace QtWebEngineCore diff --git a/src/core/compositor/display_overrides.cpp b/src/core/compositor/display_overrides.cpp new file mode 100644 index 000000000..4547bb04b --- /dev/null +++ b/src/core/compositor/display_overrides.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "display_gl_output_surface.h" +#include "display_software_output_surface.h" + +#include "components/viz/service/display_embedder/gpu_display_provider.h" +#include "gpu/ipc/in_process_command_buffer.h" + +std::unique_ptr<viz::OutputSurface> +viz::GpuDisplayProvider::CreateGLOutputSurface( + scoped_refptr<VizProcessContextProvider> context_provider, + UpdateVSyncParametersCallback update_vsync_callback) +{ + return std::make_unique<QtWebEngineCore::DisplayGLOutputSurface>( + std::move(context_provider), std::move(update_vsync_callback)); +} + +std::unique_ptr<viz::OutputSurface> +viz::GpuDisplayProvider::CreateSoftwareOutputSurface( + UpdateVSyncParametersCallback update_vsync_callback) +{ + return std::make_unique<QtWebEngineCore::DisplaySoftwareOutputSurface>(std::move(update_vsync_callback)); +} + +void gpu::InProcessCommandBuffer::GetTextureQt( + unsigned int client_id, + GetTextureCallback callback, + const std::vector<SyncToken>& sync_token_fences) +{ + ScheduleGpuTask(base::BindOnce(&InProcessCommandBuffer::GetTextureQtOnGpuThread, + gpu_thread_weak_ptr_factory_.GetWeakPtr(), + client_id, + std::move(callback)), + sync_token_fences); +} + +void gpu::InProcessCommandBuffer::GetTextureQtOnGpuThread( + unsigned int client_id, GetTextureCallback callback) +{ + MakeCurrent(); + gpu::TextureBase *texture = decoder_->GetTextureBase(client_id); + std::move(callback).Run(texture ? texture->service_id() : 0, gl::GLFence::Create()); +} diff --git a/src/core/compositor/display_producer.h b/src/core/compositor/display_producer.h new file mode 100644 index 000000000..5de09d2d2 --- /dev/null +++ b/src/core/compositor/display_producer.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DISPLAY_PRODUCER_H +#define DISPLAY_PRODUCER_H + +#include "qtwebenginecoreglobal_p.h" + +QT_BEGIN_NAMESPACE +class QSGNode; +QT_END_NAMESPACE + +namespace QtWebEngineCore { +class RenderWidgetHostViewQtDelegate; + +// Produces composited frames for display. +class DisplayProducer +{ +public: + // Generate scene graph nodes for the current frame. + // + // If this is a scheduled update (that is, scheduleUpdate was called + // earlier), then updatePaintNode will generate nodes for a new frame. + // Otherwise, it will just regenerate nodes for the old frame. + virtual QSGNode *updatePaintNode(QSGNode *oldNode, RenderWidgetHostViewQtDelegate *delegate) = 0; + +protected: + ~DisplayProducer() {} +}; + +} // namespace QtWebEngineCore + +#endif // !DISPLAY_PRODUCER_H diff --git a/src/core/compositor/display_software_output_surface.cpp b/src/core/compositor/display_software_output_surface.cpp new file mode 100644 index 000000000..13f8e8f38 --- /dev/null +++ b/src/core/compositor/display_software_output_surface.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "display_software_output_surface.h" + +#include "display_frame_sink.h" +#include "render_widget_host_view_qt_delegate.h" +#include "type_conversion.h" + +#include "base/threading/thread_task_runner_handle.h" +#include "components/viz/service/display/display.h" +#include "components/viz/service/display/output_surface_frame.h" + +#include <QMutex> +#include <QPainter> +#include <QSGImageNode> + +namespace QtWebEngineCore { + +class DisplaySoftwareOutputSurface::Device final : public viz::SoftwareOutputDevice, public DisplayProducer +{ +public: + ~Device(); + + // Called from DisplaySoftwareOutputSurface. + void bind(viz::FrameSinkId frameSinkId); + + // Overridden from viz::SoftwareOutputDevice. + void Resize(const gfx::Size &sizeInPixels, float devicePixelRatio) override; + void OnSwapBuffers(base::OnceClosure swapCompletionCallback) override; + + // Overridden from DisplayProducer. + QSGNode *updatePaintNode(QSGNode *oldNode, RenderWidgetHostViewQtDelegate *delegate) override; + +private: + mutable QMutex m_mutex; + scoped_refptr<DisplayFrameSink> m_sink; + float m_devicePixelRatio = 1.0; + scoped_refptr<base::SingleThreadTaskRunner> m_taskRunner; + base::OnceClosure m_swapCompletionCallback; + QImage m_image; + float m_imageDevicePixelRatio = 1.0; +}; + +DisplaySoftwareOutputSurface::Device::~Device() +{ + if (m_sink) + m_sink->disconnect(this); +} + +void DisplaySoftwareOutputSurface::Device::bind(viz::FrameSinkId frameSinkId) +{ + m_sink = DisplayFrameSink::findOrCreate(frameSinkId); + m_sink->connect(this); +} + +void DisplaySoftwareOutputSurface::Device::Resize(const gfx::Size &sizeInPixels, float devicePixelRatio) +{ + if (viewport_pixel_size_ == sizeInPixels && m_devicePixelRatio == devicePixelRatio) + return; + m_devicePixelRatio = devicePixelRatio; + viewport_pixel_size_ = sizeInPixels; + surface_ = SkSurface::MakeRaster(SkImageInfo::MakeN32Premul(sizeInPixels.width(), sizeInPixels.height())); +} + +void DisplaySoftwareOutputSurface::Device::OnSwapBuffers(base::OnceClosure swapCompletionCallback) +{ + QMutexLocker locker(&m_mutex); + m_taskRunner = base::ThreadTaskRunnerHandle::Get(); + m_swapCompletionCallback = std::move(swapCompletionCallback); + m_sink->scheduleUpdate(); +} + +inline QImage::Format imageFormat(SkColorType colorType) +{ + switch (colorType) { + case kBGRA_8888_SkColorType: + return QImage::Format_ARGB32_Premultiplied; + case kRGBA_8888_SkColorType: + return QImage::Format_RGBA8888_Premultiplied; + default: + Q_UNREACHABLE(); + return QImage::Format_ARGB32_Premultiplied; + } +} + +QSGNode *DisplaySoftwareOutputSurface::Device::updatePaintNode( + QSGNode *oldNode, RenderWidgetHostViewQtDelegate *delegate) +{ + QMutexLocker locker(&m_mutex); + + // Delete old node to make sure refcount of m_image is at most 1. + delete oldNode; + QSGImageNode *node = delegate->createImageNode(); + + if (m_swapCompletionCallback) { + SkPixmap skPixmap; + surface_->peekPixels(&skPixmap); + QImage image(reinterpret_cast<const uchar *>(skPixmap.addr()), + viewport_pixel_size_.width(), viewport_pixel_size_.height(), + skPixmap.rowBytes(), imageFormat(skPixmap.colorType())); + if (m_image.size() == image.size()) { + QRect damageRect = toQt(damage_rect_); + QPainter(&m_image).drawImage(damageRect, image, damageRect); + } else { + m_image = image; + m_image.detach(); + } + m_imageDevicePixelRatio = m_devicePixelRatio; + m_taskRunner->PostTask(FROM_HERE, std::move(m_swapCompletionCallback)); + m_taskRunner.reset(); + } + + QSizeF sizeInDips = QSizeF(m_image.size()) / m_imageDevicePixelRatio; + node->setRect(QRectF(QPointF(0, 0), sizeInDips)); + node->setOwnsTexture(true); + node->setTexture(delegate->createTextureFromImage(m_image)); + + return node; +} + +DisplaySoftwareOutputSurface::DisplaySoftwareOutputSurface(viz::UpdateVSyncParametersCallback callback) + : SoftwareOutputSurface(std::make_unique<Device>(), std::move(callback)) +{} + +DisplaySoftwareOutputSurface::~DisplaySoftwareOutputSurface() {} + +// Called from viz::Display::Initialize. +void DisplaySoftwareOutputSurface::BindToClient(viz::OutputSurfaceClient *client) +{ + auto display = static_cast<viz::Display *>(client); + auto device = static_cast<Device *>(software_device()); + device->bind(display->frame_sink_id()); + SoftwareOutputSurface::BindToClient(client); +} + +} // namespace QtWebEngineCore diff --git a/src/core/compositor/display_software_output_surface.h b/src/core/compositor/display_software_output_surface.h new file mode 100644 index 000000000..6707c74dc --- /dev/null +++ b/src/core/compositor/display_software_output_surface.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DISPLAY_SOFTWARE_OUTPUT_SURFACE_H +#define DISPLAY_SOFTWARE_OUTPUT_SURFACE_H + +#include "components/viz/service/display_embedder/software_output_surface.h" + +namespace QtWebEngineCore { + +class DisplaySoftwareOutputSurface final : public viz::SoftwareOutputSurface +{ +public: + DisplaySoftwareOutputSurface(viz::UpdateVSyncParametersCallback callback); + ~DisplaySoftwareOutputSurface() override; + + // Overridden from viz::SoftwareOutputSurface. + void BindToClient(viz::OutputSurfaceClient *client) override; + +private: + class Device; +}; + +} // namespace QtWebEngineCore + +#endif // !DISPLAY_SOFTWARE_OUTPUT_SURFACE_H diff --git a/src/core/core_chromium.pri b/src/core/core_chromium.pri index 908387788..bc39f8e15 100644 --- a/src/core/core_chromium.pri +++ b/src/core/core_chromium.pri @@ -59,10 +59,14 @@ SOURCES = \ compositor/compositor_resource_tracker.cpp \ compositor/content_gpu_client_qt.cpp \ compositor/delegated_frame_node.cpp \ + compositor/display_frame_sink.cpp \ + compositor/display_overrides.cpp \ + compositor/display_software_output_surface.cpp \ content_client_qt.cpp \ content_browser_client_qt.cpp \ content_main_delegate_qt.cpp \ content_utility_client_qt.cpp \ + delegated_frame_host_client_qt.cpp \ desktop_screen_qt.cpp \ devtools_frontend_qt.cpp \ devtools_manager_delegate_qt.cpp \ @@ -163,10 +167,13 @@ HEADERS = \ compositor/compositor_resource_tracker.h \ compositor/content_gpu_client_qt.h \ compositor/delegated_frame_node.h \ + compositor/display_frame_sink.h \ + compositor/display_software_output_surface.h \ content_client_qt.h \ content_browser_client_qt.h \ content_main_delegate_qt.h \ content_utility_client_qt.h \ + delegated_frame_host_client_qt.h \ desktop_screen_qt.h \ devtools_frontend_qt.h \ devtools_manager_delegate_qt.h \ @@ -292,11 +299,13 @@ qtConfig(webengine-printing-and-pdf) { contains(QT_CONFIG, opengl) { SOURCES += \ compositor/compositor_resource_fence.cpp \ + compositor/display_gl_output_surface.cpp \ + compositor/display_gl_output_surface_qsg.cpp \ compositor/stream_video_node.cpp \ compositor/yuv_video_node.cpp - HEADERS += \ compositor/compositor_resource_fence.h \ + compositor/display_gl_output_surface.h \ compositor/stream_video_node.h \ compositor/yuv_video_node.h } diff --git a/src/core/delegated_frame_host_client_qt.cpp b/src/core/delegated_frame_host_client_qt.cpp new file mode 100644 index 000000000..d3f5a4ade --- /dev/null +++ b/src/core/delegated_frame_host_client_qt.cpp @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "delegated_frame_host_client_qt.h" + +#include "render_widget_host_view_qt.h" + +namespace QtWebEngineCore { + +ui::Layer *DelegatedFrameHostClientQt::DelegatedFrameHostGetLayer() const +{ + return p->m_rootLayer.get(); +} + +bool DelegatedFrameHostClientQt::DelegatedFrameHostIsVisible() const +{ + return !p->host()->is_hidden(); +} + +SkColor DelegatedFrameHostClientQt::DelegatedFrameHostGetGutterColor() const +{ + return p->GetBackgroundColor().value_or(SK_ColorWHITE); +} + +void DelegatedFrameHostClientQt::OnBeginFrame(base::TimeTicks frame_time) +{ + p->host()->ProgressFlingIfNeeded(frame_time); +} + +void DelegatedFrameHostClientQt::OnFrameTokenChanged(uint32_t frame_token) +{ + p->OnFrameTokenChangedForView(frame_token); +} + +float DelegatedFrameHostClientQt::GetDeviceScaleFactor() const +{ + return p->m_screenInfo.device_scale_factor; +} + +void DelegatedFrameHostClientQt::InvalidateLocalSurfaceIdOnEviction() +{ + p->m_dfhLocalSurfaceIdAllocator.Invalidate(); +} + +std::vector<viz::SurfaceId> DelegatedFrameHostClientQt::CollectSurfaceIdsForEviction() +{ + return p->host()->CollectSurfaceIdsForEviction(); +} + +bool DelegatedFrameHostClientQt::ShouldShowStaleContentOnEviction() +{ + return p->host()->ShouldShowStaleContentOnEviction(); +} + +} // namespace QtWebEngineCore diff --git a/src/core/delegated_frame_host_client_qt.h b/src/core/delegated_frame_host_client_qt.h new file mode 100644 index 000000000..b5dc6eb59 --- /dev/null +++ b/src/core/delegated_frame_host_client_qt.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DELEGATED_FRAME_HOST_CLIENT_QT_H +#define DELEGATED_FRAME_HOST_CLIENT_QT_H + +#include "qtwebenginecoreglobal_p.h" + +#include "content/browser/renderer_host/delegated_frame_host.h" +#include "content/browser/renderer_host/render_widget_host_impl.h" + +namespace QtWebEngineCore { + +class RenderWidgetHostViewQt; +class DelegatedFrameHostClientQt : public content::DelegatedFrameHostClient +{ +public: + explicit DelegatedFrameHostClientQt(RenderWidgetHostViewQt *p) : p(p) {} + + // Overridden from content::DelegatedFrameHostClient + ui::Layer *DelegatedFrameHostGetLayer() const override; + bool DelegatedFrameHostIsVisible() const override; + SkColor DelegatedFrameHostGetGutterColor() const override; + void OnBeginFrame(base::TimeTicks frame_time) override; + void OnFrameTokenChanged(uint32_t frame_token) override; + float GetDeviceScaleFactor() const override; + void InvalidateLocalSurfaceIdOnEviction() override; + std::vector<viz::SurfaceId> CollectSurfaceIdsForEviction() override; + bool ShouldShowStaleContentOnEviction() override; + +private: + RenderWidgetHostViewQt *p; +}; + +} // namespace QtWebEngineCore + +#endif // !DELEGATED_FRAME_HOST_CLIENT_QT_H diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index 21e9e9041..2918fd8bc 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -51,6 +51,9 @@ #include "web_contents_adapter_client.h" #include "web_event_factory.h" +#include "base/threading/thread_task_runner_handle.h" +#include "components/viz/common/features.h" +#include "components/viz/common/frame_sinks/begin_frame_source.h" #include "components/viz/common/surfaces/frame_sink_id_allocator.h" #include "components/viz/host/host_frame_sink_manager.h" #include "content/browser/compositor/surface_utils.h" @@ -271,10 +274,12 @@ static content::ScreenInfo screenInfoFromQScreen(QScreen *screen) RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget) : content::RenderWidgetHostViewBase::RenderWidgetHostViewBase(widget) + , m_taskRunner(base::ThreadTaskRunnerHandle::Get()) , m_gestureProvider(QtGestureProviderConfig(), this) , m_sendMotionActionDown(false) , m_touchMotionStarted(false) - , m_compositor(new Compositor(widget)) + , m_enableViz(features::IsVizDisplayCompositorEnabled()) + , m_visible(false) , m_loadVisuallyCommittedState(NotCommitted) , m_adapterClient(0) , m_imeInProgress(false) @@ -288,14 +293,39 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget , m_mouseWheelPhaseHandler(this) , m_frameSinkId(host()->GetFrameSinkId()) { - host()->SetView(this); - if (GetTextInputManager()) GetTextInputManager()->AddObserver(this); const QPlatformInputContext *context = QGuiApplicationPrivate::platformIntegration()->inputContext(); m_imeHasHiddenTextCapability = context && context->hasCapability(QPlatformInputContext::HiddenTextCapability); + if (m_enableViz) { + m_rootLayer.reset(new ui::Layer(ui::LAYER_SOLID_COLOR)); + m_rootLayer->SetColor(SK_ColorTRANSPARENT); + + m_delegatedFrameHost.reset(new content::DelegatedFrameHost( + host()->GetFrameSinkId(), + &m_delegatedFrameHostClient, + true /* should_register_frame_sink_id */)); + + content::ImageTransportFactory *imageTransportFactory = content::ImageTransportFactory::GetInstance(); + ui::ContextFactory *contextFactory = imageTransportFactory->GetContextFactory(); + ui::ContextFactoryPrivate *contextFactoryPrivate = imageTransportFactory->GetContextFactoryPrivate(); + m_uiCompositor.reset(new ui::Compositor( + contextFactoryPrivate->AllocateFrameSinkId(), + contextFactory, + contextFactoryPrivate, + m_taskRunner, + false /* enable_pixel_canvas */)); + m_uiCompositor->SetAcceleratedWidget(gfx::kNullAcceleratedWidget); // null means offscreen + m_uiCompositor->SetRootLayer(m_rootLayer.get()); + + m_displayFrameSink = DisplayFrameSink::findOrCreate(m_uiCompositor->frame_sink_id()); + m_displayFrameSink->connect(this); + } else { + m_compositor.reset(new Compositor(widget)); + } + if (host()->delegate() && host()->delegate()->GetInputEventRouter()) host()->delegate()->GetInputEventRouter()->AddFrameSinkIdOwner(GetFrameSinkId(), this); @@ -307,12 +337,20 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget m_touchSelectionController.reset(new ui::TouchSelectionController(m_touchSelectionControllerClient.get(), config)); host()->render_frame_metadata_provider()->ReportAllFrameSubmissionsForTesting(true); + + // May call SetNeedsBeginFrames + host()->SetView(this); } RenderWidgetHostViewQt::~RenderWidgetHostViewQt() { + m_delegate.reset(); + QObject::disconnect(m_adapterClientDestroyedConnection); + if (m_enableViz) + m_displayFrameSink->disconnect(this); + if (text_input_manager_) text_input_manager_->RemoveObserver(this); @@ -406,6 +444,8 @@ bool RenderWidgetHostViewQt::HasFocus() bool RenderWidgetHostViewQt::IsSurfaceAvailableForCopy() { + if (m_enableViz) + return m_delegatedFrameHost->CanCopyFromCompositingSurface(); return true; } @@ -413,6 +453,11 @@ void RenderWidgetHostViewQt::CopyFromSurface(const gfx::Rect &src_rect, const gfx::Size &output_size, base::OnceCallback<void(const SkBitmap &)> callback) { + if (m_enableViz) { + m_delegatedFrameHost->CopyFromCompositingSurface(src_rect, output_size, std::move(callback)); + return; + } + QImage image; if (m_delegate->copySurface(toQt(src_rect), toQt(output_size), image)) std::move(callback).Run(toSkBitmap(image)); @@ -443,6 +488,18 @@ gfx::Rect RenderWidgetHostViewQt::GetViewBounds() void RenderWidgetHostViewQt::UpdateBackgroundColor() { + if (m_enableViz) { + DCHECK(GetBackgroundColor()); + SkColor color = *GetBackgroundColor(); + bool opaque = SkColorGetA(color) == SK_AlphaOPAQUE; + m_rootLayer->SetFillsBoundsOpaquely(opaque); + m_rootLayer->SetColor(color); + m_uiCompositor->SetBackgroundColor(color); + m_delegate->setClearColor(toQt(color)); + host()->Send(new RenderViewObserverQt_SetBackgroundColor(host()->GetRoutingID(), color)); + return; + } + auto color = GetBackgroundColor(); if (color) { m_delegate->setClearColor(toQt(*color)); @@ -664,13 +721,16 @@ void RenderWidgetHostViewQt::DisplayTooltipText(const base::string16 &tooltip_te m_adapterClient->setToolTip(toQt(tooltip_text)); } -void RenderWidgetHostViewQt::DidCreateNewRendererCompositorFrameSink(viz::mojom::CompositorFrameSinkClient *frameSink) +void RenderWidgetHostViewQt::DidCreateNewRendererCompositorFrameSink(viz::mojom::CompositorFrameSinkClient *frameSinkClient) { - m_compositor->setFrameSinkClient(frameSink); + DCHECK(!m_enableViz); + m_compositor->setFrameSinkClient(frameSinkClient); } -void RenderWidgetHostViewQt::SubmitCompositorFrame(const viz::LocalSurfaceId &local_surface_id, viz::CompositorFrame frame, base::Optional<viz::HitTestRegionList>) +void RenderWidgetHostViewQt::SubmitCompositorFrame(const viz::LocalSurfaceId &local_surface_id, viz::CompositorFrame frame, base::Optional<viz::HitTestRegionList> hit_test_region_list) { + DCHECK(!m_enableViz); + // Force to process swap messages uint32_t frame_token = frame.metadata.frame_token; if (frame_token) @@ -891,7 +951,7 @@ viz::ScopedSurfaceIdAllocator RenderWidgetHostViewQt::DidUpdateVisualProperties( base::OnceCallback<void()> allocation_task = base::BindOnce(&RenderWidgetHostViewQt::OnDidUpdateVisualPropertiesComplete, base::Unretained(this), metadata); - return viz::ScopedSurfaceIdAllocator(std::move(allocation_task)); + return viz::ScopedSurfaceIdAllocator(&m_dfhLocalSurfaceIdAllocator, std::move(allocation_task)); } void RenderWidgetHostViewQt::OnDidUpdateVisualPropertiesComplete(const cc::RenderFrameMetadata &metadata) @@ -909,6 +969,14 @@ void RenderWidgetHostViewQt::OnDidFirstVisuallyNonEmptyPaint() } } +void RenderWidgetHostViewQt::scheduleUpdate() +{ + DCHECK(m_enableViz); + m_taskRunner->PostTask( + FROM_HERE, + base::BindOnce(&RenderWidgetHostViewQt::callUpdate, m_weakPtrFactory.GetWeakPtr())); +} + void RenderWidgetHostViewQt::callUpdate() { m_delegate->update(); @@ -923,17 +991,39 @@ void RenderWidgetHostViewQt::callUpdate() QSGNode *RenderWidgetHostViewQt::updatePaintNode(QSGNode *oldNode) { + if (m_enableViz) + return m_displayFrameSink->updatePaintNode(oldNode, m_delegate.get()); return m_compositor->updatePaintNode(oldNode, m_delegate.get()); } void RenderWidgetHostViewQt::notifyShown() { - host()->WasShown(false); + if (m_enableViz) { + if (m_visible) + return; + m_visible = true; + m_delegatedFrameHost->AttachToCompositor(m_uiCompositor.get()); + m_delegatedFrameHost->WasShown(GetLocalSurfaceIdAllocation().local_surface_id(), + m_viewRectInDips.size(), + false /* record_presentation_time */); + host()->WasShown(false); + } else { + host()->WasShown(false); + } } void RenderWidgetHostViewQt::notifyHidden() { - host()->WasHidden(); + if (m_enableViz) { + if (!m_visible) + return; + m_visible = false; + host()->WasHidden(); + m_delegatedFrameHost->WasHidden(); + m_delegatedFrameHost->DetachFromCompositor(); + } else { + host()->WasHidden(); + } } void RenderWidgetHostViewQt::visualPropertiesChanged() @@ -1651,6 +1741,7 @@ void RenderWidgetHostViewQt::handleFocusEvent(QFocusEvent *ev) void RenderWidgetHostViewQt::SetNeedsBeginFrames(bool needs_begin_frames) { + DCHECK(!m_enableViz); m_compositor->setNeedsBeginFrames(needs_begin_frames); } @@ -1690,26 +1781,35 @@ void RenderWidgetHostViewQt::SetWantsAnimateOnlyBeginFrames() viz::SurfaceId RenderWidgetHostViewQt::GetCurrentSurfaceId() const { + if (m_enableViz) + return m_delegatedFrameHost->GetCurrentSurfaceId(); return viz::SurfaceId(); } const viz::FrameSinkId &RenderWidgetHostViewQt::GetFrameSinkId() const { + if (m_enableViz) + return m_delegatedFrameHost->frame_sink_id(); return m_frameSinkId; } const viz::LocalSurfaceIdAllocation &RenderWidgetHostViewQt::GetLocalSurfaceIdAllocation() const { - return m_localSurfaceIdAllocator.GetCurrentLocalSurfaceIdAllocation(); + return m_dfhLocalSurfaceIdAllocator.GetCurrentLocalSurfaceIdAllocation(); } void RenderWidgetHostViewQt::TakeFallbackContentFrom(content::RenderWidgetHostView *view) { DCHECK(!static_cast<RenderWidgetHostViewBase*>(view)->IsRenderWidgetHostViewChildFrame()); DCHECK(!static_cast<RenderWidgetHostViewBase*>(view)->IsRenderWidgetHostViewGuest()); - base::Optional<SkColor> color = view->GetBackgroundColor(); + RenderWidgetHostViewQt *viewQt = static_cast<RenderWidgetHostViewQt *>(view); + base::Optional<SkColor> color = viewQt->GetBackgroundColor(); if (color) SetBackgroundColor(*color); + if (m_enableViz) { + m_delegatedFrameHost->TakeFallbackContentFrom(viewQt->m_delegatedFrameHost.get()); + host()->GetContentRenderingTimeoutFrom(viewQt->host()); + } } void RenderWidgetHostViewQt::EnsureSurfaceSynchronizedForWebTest() @@ -1750,9 +1850,24 @@ void RenderWidgetHostViewQt::OnRenderFrameMetadataChangedAfterActivation() void RenderWidgetHostViewQt::synchronizeVisualProperties(const base::Optional<viz::LocalSurfaceIdAllocation> &childSurfaceId) { if (childSurfaceId) - m_localSurfaceIdAllocator.UpdateFromChild(*childSurfaceId); + m_dfhLocalSurfaceIdAllocator.UpdateFromChild(*childSurfaceId); else - m_localSurfaceIdAllocator.GenerateId(); + m_dfhLocalSurfaceIdAllocator.GenerateId(); + + if (m_enableViz) { + gfx::Size viewSizeInDips = GetRequestedRendererSize(); + gfx::Size viewSizeInPixels = GetCompositorViewportPixelSize(); + m_rootLayer->SetBounds(gfx::Rect(gfx::Point(), viewSizeInPixels)); + m_uiCompositorLocalSurfaceIdAllocator.GenerateId(); + m_uiCompositor->SetScaleAndSize( + m_screenInfo.device_scale_factor, + viewSizeInPixels, + m_uiCompositorLocalSurfaceIdAllocator.GetCurrentLocalSurfaceIdAllocation()); + m_delegatedFrameHost->EmbedSurface( + m_dfhLocalSurfaceIdAllocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id(), + viewSizeInDips, + cc::DeadlinePolicy::UseDefaultDeadline()); + } host()->SynchronizeVisualProperties(); } diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h index 50a430d84..5935f477a 100644 --- a/src/core/render_widget_host_view_qt.h +++ b/src/core/render_widget_host_view_qt.h @@ -40,10 +40,11 @@ #ifndef RENDER_WIDGET_HOST_VIEW_QT_H #define RENDER_WIDGET_HOST_VIEW_QT_H +#include "compositor/display_frame_sink.h" +#include "delegated_frame_host_client_qt.h" #include "render_widget_host_view_qt_delegate.h" #include "base/memory/weak_ptr.h" -#include "components/viz/common/frame_sinks/begin_frame_source.h" #include "components/viz/common/resources/transferable_resource.h" #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" #include "components/viz/host/host_frame_sink_client.h" @@ -53,7 +54,7 @@ #include "content/browser/renderer_host/text_input_manager.h" #include "gpu/ipc/common/gpu_messages.h" #include "ui/events/gesture_detection/filtered_gesture_provider.h" -#include "qtwebenginecoreglobal_p.h" + #include <QMap> #include <QPoint> #include <QtGlobal> @@ -104,6 +105,7 @@ class RenderWidgetHostViewQt , public RenderWidgetHostViewQtDelegateClient , public base::SupportsWeakPtr<RenderWidgetHostViewQt> , public content::TextInputManager::Observer + , public DisplayConsumer { public: enum LoadVisuallyCommittedState { @@ -222,6 +224,9 @@ public: // Overridden from content::RenderFrameMetadataProvider::Observer void OnRenderFrameMetadataChangedAfterActivation() override; + // Overridden from DisplayConsumer + void scheduleUpdate() override; + gfx::SizeF lastContentsSize() const { return m_lastContentsSize; } gfx::Vector2dF lastScrollOffset() const { return m_lastScrollOffset; } @@ -231,6 +236,8 @@ public: ui::TextInputType getTextInputType() const; private: + friend class DelegatedFrameHostClientQt; + void processMotionEvent(const ui::MotionEvent &motionEvent); void clearPreviousTouchMotionState(); QList<QTouchEvent::TouchPoint> mapTouchPointIds(const QList<QTouchEvent::TouchPoint> &inputPoints); @@ -250,6 +257,8 @@ private: gfx::Rect m_windowRectInDips; content::ScreenInfo m_screenInfo; + scoped_refptr<base::SingleThreadTaskRunner> m_taskRunner; + ui::FilteredGestureProvider m_gestureProvider; base::TimeDelta m_eventsToNowDelta; bool m_sendMotionActionDown; @@ -258,6 +267,13 @@ private: QList<QTouchEvent::TouchPoint> m_previousTouchPoints; std::unique_ptr<RenderWidgetHostViewQtDelegate> m_delegate; + const bool m_enableViz; + bool m_visible; + DelegatedFrameHostClientQt m_delegatedFrameHostClient{this}; + std::unique_ptr<content::DelegatedFrameHost> m_delegatedFrameHost; + std::unique_ptr<ui::Layer> m_rootLayer; + std::unique_ptr<ui::Compositor> m_uiCompositor; + scoped_refptr<DisplayFrameSink> m_displayFrameSink; std::unique_ptr<Compositor> m_compositor; LoadVisuallyCommittedState m_loadVisuallyCommittedState; @@ -271,7 +287,8 @@ private: gfx::Vector2dF m_lastScrollOffset; gfx::SizeF m_lastContentsSize; - viz::ParentLocalSurfaceIdAllocator m_localSurfaceIdAllocator; + viz::ParentLocalSurfaceIdAllocator m_dfhLocalSurfaceIdAllocator; + viz::ParentLocalSurfaceIdAllocator m_uiCompositorLocalSurfaceIdAllocator; uint m_imState; int m_anchorPositionWithinSelection; @@ -293,6 +310,8 @@ private: std::unique_ptr<ui::TouchSelectionController> m_touchSelectionController; gfx::SelectionBound m_selectionStart; gfx::SelectionBound m_selectionEnd; + + base::WeakPtrFactory<RenderWidgetHostViewQt> m_weakPtrFactory{this}; }; } // namespace QtWebEngineCore diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index a988040ee..a42565c2b 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -488,6 +488,16 @@ WebEngineContext::WebEngineContext() parsedCommandLine->AppendSwitch(switches::kDisableES3GLContext); #endif + bool threadedGpu = true; +#ifndef QT_NO_OPENGL + threadedGpu = QOpenGLContext::supportsThreadedOpenGL(); +#endif + + bool enableViz = ((threadedGpu && !parsedCommandLine->HasSwitch("disable-viz-display-compositor")) + || parsedCommandLine->HasSwitch("enable-viz-display-compositor")); + parsedCommandLine->RemoveSwitch("disable-viz-display-compositor"); + parsedCommandLine->RemoveSwitch("enable-viz-display-compositor"); + std::string disableFeatures; std::string enableFeatures; // Needed to allow navigations within pages that were set using setHtml(). One example is @@ -495,10 +505,6 @@ WebEngineContext::WebEngineContext() // This is deprecated behavior, and will be removed in a future Chromium version, as per // upstream Chromium commit ba52f56207a4b9d70b34880fbff2352e71a06422. appendToFeatureList(enableFeatures, features::kAllowContentInitiatedDataUrlNavigations.name); - // Surface synchronization breaks our current graphics integration (since 65) - appendToFeatureList(disableFeatures, features::kEnableSurfaceSynchronization.name); - // Viz Display Compositor is enabled by default since 73. Doesn't work for us (also implies SurfaceSynchronization) - appendToFeatureList(disableFeatures, features::kVizDisplayCompositor.name); // The video-capture service is not functioning at this moment (since 69) appendToFeatureList(disableFeatures, features::kMojoVideoCapture.name); // Breaks WebEngineNewViewRequest.userInitiated API (since 73) @@ -506,8 +512,6 @@ WebEngineContext::WebEngineContext() // We do not yet support the network-service, but it is enabled by default since 75. appendToFeatureList(disableFeatures, network::features::kNetworkService.name); - // VideoSurfaceLayer is enabled by default since 75. We don't support it. - appendToFeatureList(disableFeatures, media::kUseSurfaceLayerForVideo.name); // BlinkGenPropertyTrees is enabled by default in 75, but causes regressions. appendToFeatureList(disableFeatures, blink::features::kBlinkGenPropertyTrees.name); @@ -531,6 +535,15 @@ WebEngineContext::WebEngineContext() parsedCommandLine->AppendSwitch(cc::switches::kDisableCompositedAntialiasing); } + if (!enableViz) { + // Surface synchronization breaks our current graphics integration (since 65) + appendToFeatureList(disableFeatures, features::kEnableSurfaceSynchronization.name); + // Viz Display Compositor is enabled by default since 73. Doesn't work for us (also implies SurfaceSynchronization) + appendToFeatureList(disableFeatures, features::kVizDisplayCompositor.name); + // VideoSurfaceLayer is enabled by default since 75. We don't support it. + appendToFeatureList(disableFeatures, media::kUseSurfaceLayerForVideo.name); + } + appendToFeatureSwitch(parsedCommandLine, switches::kDisableFeatures, disableFeatures); appendToFeatureSwitch(parsedCommandLine, switches::kEnableFeatures, enableFeatures); base::FeatureList::InitializeInstance( @@ -619,10 +632,6 @@ WebEngineContext::WebEngineContext() parsedCommandLine->AppendSwitch(switches::kDisableGpu); } - bool threadedGpu = true; -#ifndef QT_NO_OPENGL - threadedGpu = QOpenGLContext::supportsThreadedOpenGL(); -#endif registerMainThreadFactories(threadedGpu); SetContentClient(new ContentClientQt); |