diff options
Diffstat (limited to 'src/core/compositor')
-rw-r--r-- | src/core/compositor/compositor.cpp | 215 | ||||
-rw-r--r-- | src/core/compositor/compositor.h | 185 | ||||
-rw-r--r-- | src/core/compositor/display_consumer.h | 62 | ||||
-rw-r--r-- | src/core/compositor/display_frame_sink.cpp | 140 | ||||
-rw-r--r-- | src/core/compositor/display_frame_sink.h | 77 | ||||
-rw-r--r-- | src/core/compositor/display_gl_output_surface.cpp | 55 | ||||
-rw-r--r-- | src/core/compositor/display_gl_output_surface.h | 18 | ||||
-rw-r--r-- | src/core/compositor/display_gl_output_surface_qsg.cpp | 122 | ||||
-rw-r--r-- | src/core/compositor/display_producer.h | 69 | ||||
-rw-r--r-- | src/core/compositor/display_software_output_surface.cpp | 91 |
10 files changed, 504 insertions, 530 deletions
diff --git a/src/core/compositor/compositor.cpp b/src/core/compositor/compositor.cpp new file mode 100644 index 000000000..c45c02844 --- /dev/null +++ b/src/core/compositor/compositor.cpp @@ -0,0 +1,215 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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 "compositor.h" + +#include "base/memory/ref_counted.h" +#include "components/viz/common/surfaces/frame_sink_id.h" + +#include <QHash> +#include <QImage> +#include <QMutex> + +namespace QtWebEngineCore { + +// Compositor::Id + +Compositor::Id::Id(viz::FrameSinkId fid) : client_id(fid.client_id()), sink_id(fid.sink_id()) { } + +static size_t qHash(Compositor::Id id, size_t seed = 0) +{ + QtPrivate::QHashCombine hasher; + seed = hasher(seed, id.client_id); + seed = hasher(seed, id.sink_id); + return seed; +} + +static bool operator==(Compositor::Id id1, Compositor::Id id2) +{ + return id1.client_id == id2.client_id && id1.sink_id == id2.sink_id; +} + +// Compositor::Binding and Compositor::Bindings + +struct Compositor::Binding +{ + const Id id; + Compositor *compositor = nullptr; + Observer *observer = nullptr; + + Binding(Id id) : id(id) { } + ~Binding(); +}; + +class Compositor::BindingMap +{ +public: + void lock() { m_mutex.lock(); } + + void unlock() { m_mutex.unlock(); } + + Binding *findOrCreate(Id id) + { + auto it = m_map.find(id); + if (it == m_map.end()) + it = m_map.insert(id, new Binding(id)); + return *it; + } + + void remove(Id id) { m_map.remove(id); } + +private: + QMutex m_mutex; + QHash<Id, Binding *> m_map; +} static g_bindings; + +Compositor::Binding::~Binding() +{ + g_bindings.remove(id); +} + +// Compositor::Observer + +void Compositor::Observer::bind(Id id) +{ + DCHECK(!m_binding); + g_bindings.lock(); + m_binding = g_bindings.findOrCreate(id); + DCHECK(!m_binding->observer); + m_binding->observer = this; + g_bindings.unlock(); +} + +void Compositor::Observer::unbind() +{ + DCHECK(m_binding); + g_bindings.lock(); + m_binding->observer = nullptr; + if (m_binding->compositor == nullptr) + delete m_binding; + m_binding = nullptr; + g_bindings.unlock(); +} + +Compositor::Handle<Compositor> Compositor::Observer::compositor() +{ + if (!m_binding) + return nullptr; + g_bindings.lock(); + if (m_binding->compositor) + return m_binding->compositor; // delay unlock + g_bindings.unlock(); + return nullptr; +} + +// Compositor + +void Compositor::bind(Id id) +{ + DCHECK(!m_binding); + g_bindings.lock(); + m_binding = g_bindings.findOrCreate(id); + DCHECK(!m_binding->compositor); + m_binding->compositor = this; + g_bindings.unlock(); +} + +void Compositor::unbind() +{ + DCHECK(m_binding); + g_bindings.lock(); + m_binding->compositor = nullptr; + if (m_binding->observer == nullptr) + delete m_binding; + m_binding = nullptr; + g_bindings.unlock(); +} + +Compositor::Handle<Compositor::Observer> Compositor::observer() +{ + if (!m_binding) + return nullptr; + g_bindings.lock(); + if (m_binding->observer) + return m_binding->observer; // delay unlock + g_bindings.unlock(); + return nullptr; +} + +float Compositor::devicePixelRatio() +{ + Q_UNREACHABLE(); + return 1; +} + +QImage Compositor::image() +{ + Q_UNREACHABLE(); + return {}; +} + +void Compositor::waitForTexture() +{ + Q_UNREACHABLE(); +} + +int Compositor::textureId() +{ + Q_UNREACHABLE(); + return 0; +} + +QSize Compositor::textureSize() +{ + Q_UNREACHABLE(); + return {}; +} + +bool Compositor::hasAlphaChannel() +{ + Q_UNREACHABLE(); + return false; +} + +// static +void Compositor::unlockBindings() +{ + g_bindings.unlock(); +} +} // namespace QtWebEngineCore diff --git a/src/core/compositor/compositor.h b/src/core/compositor/compositor.h new file mode 100644 index 000000000..d10cf2ef6 --- /dev/null +++ b/src/core/compositor/compositor.h @@ -0,0 +1,185 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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 COMPOSITOR_H +#define COMPOSITOR_H + +#include "qtwebenginecoreglobal_p.h" + +QT_BEGIN_NAMESPACE +class QImage; +class QSize; +QT_END_NAMESPACE + +namespace viz { +class FrameSinkId; +} // namespace viz + +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. +class Q_WEBENGINECORE_PRIVATE_EXPORT Compositor +{ + struct Binding; + +public: + // Identifies the implementation type. + enum class Type { + Software, + OpenGL, + }; + + // Identifies a compositor. + // + // The purpose of assigning ids to compositors is to allow the + // corresponding observer to be registered before the compositor + // itself is created, which is necessary since the creation + // happens on a different thread in the depths of viz. + // + // (Maps to viz::FrameSinkId internally). + struct Id + { + quint32 client_id; + quint32 sink_id; + + Id(viz::FrameSinkId); + }; + + // Pointer to Compositor or Observer that holds a lock to prevent + // either from being unbound and destroyed. + template<typename T> + class Handle + { + public: + Handle(std::nullptr_t) : m_data(nullptr) { } + Handle(T *data) : m_data(data) { } + Handle(Handle &&that) : m_data(that.m_data) { that.m_data = nullptr; } + ~Handle() + { + if (m_data) + Compositor::unlockBindings(); + } + T *operator->() const { return m_data; } + T &operator*() const { return *m_data; } + explicit operator bool() const { return m_data; } + + private: + T *m_data; + }; + + // Observes the compositor corresponding to the given id. + // + // Only one observer can exist per compositor. + class Q_WEBENGINECORE_PRIVATE_EXPORT Observer + { + public: + // Binding to compositor + void bind(Id id); + void unbind(); + + // Compositor if bound + Handle<Compositor> compositor(); + + // There's a new frame ready, time to swapFrame(). + virtual void readyToSwap() = 0; + + protected: + Observer() = default; + ~Observer() = default; + + private: + Binding *m_binding = nullptr; + }; + + // Type determines which methods can be called. + Type type() const { return m_type; } + + // Binding to observer. + void bind(Id id); + void unbind(); + + // Observer if bound. + Handle<Observer> observer(); + + // Update to next frame if possible. + virtual void swapFrame() = 0; + + // Ratio of pixels to DIPs. + // + // Don't use the devicePixelRatio of QImage, it's always 1. + virtual float devicePixelRatio(); + + // (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. + virtual void waitForTexture(); + + // (OpenGL) Properties of the current frame. + virtual int textureId(); + virtual QSize textureSize(); + virtual bool hasAlphaChannel(); + +protected: + Compositor(Type type) : m_type(type) { } + ~Compositor() = default; + +private: + template<typename T> + friend class Handle; + + class BindingMap; + static void unlockBindings(); + + const Type m_type; + Binding *m_binding = nullptr; +}; + +} // namespace QtWebEngineCore + +#endif // !COMPOSITOR_H diff --git a/src/core/compositor/display_consumer.h b/src/core/compositor/display_consumer.h deleted file mode 100644 index d220088ad..000000000 --- a/src/core/compositor/display_consumer.h +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** 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 deleted file mode 100644 index 945600299..000000000 --- a/src/core/compositor/display_frame_sink.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/**************************************************************************** -** -** 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 deleted file mode 100644 index f620dc4f2..000000000 --- a/src/core/compositor/display_frame_sink.h +++ /dev/null @@ -1,77 +0,0 @@ -/**************************************************************************** -** -** 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 index 4f63e5b69..f736bba79 100644 --- a/src/core/compositor/display_gl_output_surface.cpp +++ b/src/core/compositor/display_gl_output_surface.cpp @@ -39,6 +39,8 @@ #include "display_gl_output_surface.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" @@ -51,8 +53,10 @@ namespace QtWebEngineCore { -DisplayGLOutputSurface::DisplayGLOutputSurface(scoped_refptr<viz::VizProcessContextProvider> contextProvider) +DisplayGLOutputSurface::DisplayGLOutputSurface( + scoped_refptr<viz::VizProcessContextProvider> contextProvider) : OutputSurface(contextProvider) + , Compositor(Compositor::Type::OpenGL) , m_commandBuffer(contextProvider->command_buffer()) , m_gl(contextProvider->ContextGL()) , m_vizContextProvider(contextProvider) @@ -63,18 +67,16 @@ DisplayGLOutputSurface::DisplayGLOutputSurface(scoped_refptr<viz::VizProcessCont DisplayGLOutputSurface::~DisplayGLOutputSurface() { + unbind(); m_vizContextProvider->SetUpdateVSyncParametersCallback(viz::UpdateVSyncParametersCallback()); 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); + bind(m_display->frame_sink_id()); } // Triggered by ui::Compositor::SetVisible(true). @@ -211,7 +213,8 @@ void DisplayGLOutputSurface::swapBuffersOnGpuThread(unsigned int id, std::unique m_middleBuffer->fence = CompositorResourceFence::create(std::move(fence)); } - m_sink->scheduleUpdate(); + if (auto obs = observer()) + obs->readyToSwap(); } void DisplayGLOutputSurface::swapBuffersOnVizThread() @@ -295,4 +298,44 @@ gfx::OverlayTransform DisplayGLOutputSurface::GetDisplayTransform() return gfx::OVERLAY_TRANSFORM_NONE; } +void DisplayGLOutputSurface::swapFrame() +{ + 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(); + } +} + +void DisplayGLOutputSurface::waitForTexture() +{ + if (m_frontBuffer && m_frontBuffer->fence) { + m_frontBuffer->fence->wait(); + m_frontBuffer->fence.reset(); + } +} + +int DisplayGLOutputSurface::textureId() +{ + return m_frontBuffer ? m_frontBuffer->serviceId : 0; +} + +QSize DisplayGLOutputSurface::textureSize() +{ + return m_frontBuffer ? toQt(m_frontBuffer->shape.sizeInPixels) : QSize(); +} + +bool DisplayGLOutputSurface::hasAlphaChannel() +{ + return m_frontBuffer ? m_frontBuffer->shape.hasAlpha : false; +} + +float DisplayGLOutputSurface::devicePixelRatio() +{ + return m_frontBuffer ? m_frontBuffer->shape.devicePixelRatio : 1; +} + } // namespace QtWebEngineCore diff --git a/src/core/compositor/display_gl_output_surface.h b/src/core/compositor/display_gl_output_surface.h index 67d987263..678d0cf5c 100644 --- a/src/core/compositor/display_gl_output_surface.h +++ b/src/core/compositor/display_gl_output_surface.h @@ -41,7 +41,7 @@ #define DISPLAY_GL_OUTPUT_SURFACE_H #include "compositor_resource_fence.h" -#include "display_frame_sink.h" +#include "compositor.h" #include "components/viz/common/display/update_vsync_parameters_callback.h" #include "components/viz/service/display/output_surface.h" @@ -49,6 +49,8 @@ #include "gpu/command_buffer/common/mailbox.h" #include "gpu/command_buffer/common/sync_token.h" +#include <QMutex> + namespace viz { class Display; class SyntheticBeginFrameSource; @@ -56,9 +58,7 @@ class SyntheticBeginFrameSource; 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 +class DisplayGLOutputSurface final : public viz::OutputSurface, public Compositor { public: DisplayGLOutputSurface(scoped_refptr<viz::VizProcessContextProvider> contextProvider); @@ -87,8 +87,13 @@ public: void SetDisplayTransformHint(gfx::OverlayTransform transform) override; gfx::OverlayTransform GetDisplayTransform() override; - // Overridden from DisplayProducer. - QSGNode *updatePaintNode(QSGNode *oldNode, RenderWidgetHostViewQtDelegate *delegate) override; + // Overridden from Compositor. + void swapFrame() override; + void waitForTexture() override; + int textureId() override; + QSize textureSize() override; + bool hasAlphaChannel() override; + float devicePixelRatio() override; private: struct Shape @@ -135,7 +140,6 @@ private: 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; diff --git a/src/core/compositor/display_gl_output_surface_qsg.cpp b/src/core/compositor/display_gl_output_surface_qsg.cpp deleted file mode 100644 index 2ed24ef1d..000000000 --- a/src/core/compositor/display_gl_output_surface_qsg.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/**************************************************************************** -** -** 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); - } - int comparisonKey() const override { return 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_producer.h b/src/core/compositor/display_producer.h deleted file mode 100644 index 5de09d2d2..000000000 --- a/src/core/compositor/display_producer.h +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** -** 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 index ba99799f0..b1a357615 100644 --- a/src/core/compositor/display_software_output_surface.cpp +++ b/src/core/compositor/display_software_output_surface.cpp @@ -39,7 +39,7 @@ #include "display_software_output_surface.h" -#include "display_frame_sink.h" +#include "compositor.h" #include "render_widget_host_view_qt_delegate.h" #include "type_conversion.h" @@ -49,28 +49,27 @@ #include <QMutex> #include <QPainter> -#include <QSGImageNode> namespace QtWebEngineCore { -class DisplaySoftwareOutputSurface::Device final : public viz::SoftwareOutputDevice, public DisplayProducer +class DisplaySoftwareOutputSurface::Device final : public viz::SoftwareOutputDevice, + public Compositor { public: + Device(); ~Device(); - // Called from DisplaySoftwareOutputSurface. - void bind(viz::FrameSinkId frameSinkId); - // Overridden from viz::SoftwareOutputDevice. void Resize(const gfx::Size &sizeInPixels, float devicePixelRatio) override; void OnSwapBuffers(SwapBuffersCallback swap_ack_callback) override; - // Overridden from DisplayProducer. - QSGNode *updatePaintNode(QSGNode *oldNode, RenderWidgetHostViewQtDelegate *delegate) override; + // Overridden from Compositor. + void swapFrame() override; + QImage image() override; + float devicePixelRatio() override; private: mutable QMutex m_mutex; - scoped_refptr<DisplayFrameSink> m_sink; float m_devicePixelRatio = 1.0; scoped_refptr<base::SingleThreadTaskRunner> m_taskRunner; SwapBuffersCallback m_swapCompletionCallback; @@ -78,16 +77,13 @@ private: float m_imageDevicePixelRatio = 1.0; }; -DisplaySoftwareOutputSurface::Device::~Device() -{ - if (m_sink) - m_sink->disconnect(this); -} +DisplaySoftwareOutputSurface::Device::Device() + : Compositor(Type::Software) +{} -void DisplaySoftwareOutputSurface::Device::bind(viz::FrameSinkId frameSinkId) +DisplaySoftwareOutputSurface::Device::~Device() { - m_sink = DisplayFrameSink::findOrCreate(frameSinkId); - m_sink->connect(this); + unbind(); } void DisplaySoftwareOutputSurface::Device::Resize(const gfx::Size &sizeInPixels, float devicePixelRatio) @@ -104,7 +100,8 @@ void DisplaySoftwareOutputSurface::Device::OnSwapBuffers(SwapBuffersCallback swa QMutexLocker locker(&m_mutex); m_taskRunner = base::ThreadTaskRunnerHandle::Get(); m_swapCompletionCallback = std::move(swap_ack_callback); - m_sink->scheduleUpdate(); + if (auto obs = observer()) + obs->readyToSwap(); } inline QImage::Format imageFormat(SkColorType colorType) @@ -120,41 +117,41 @@ inline QImage::Format imageFormat(SkColorType colorType) } } -QSGNode *DisplaySoftwareOutputSurface::Device::updatePaintNode( - QSGNode *oldNode, RenderWidgetHostViewQtDelegate *delegate) +void DisplaySoftwareOutputSurface::Device::swapFrame() { 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 painter(&m_image); - painter.setCompositionMode(QPainter::CompositionMode_Source); - painter.drawImage(damageRect, image, damageRect); - } else { - m_image = image; - m_image.detach(); - } - m_imageDevicePixelRatio = m_devicePixelRatio; - m_taskRunner->PostTask(FROM_HERE, base::BindOnce(std::move(m_swapCompletionCallback), toGfx(m_image.size()))); - m_taskRunner.reset(); + if (!m_swapCompletionCallback) + return; + + 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 painter(&m_image); + painter.setCompositionMode(QPainter::CompositionMode_Source); + painter.drawImage(damageRect, image, damageRect); + } else { + m_image = image; + m_image.detach(); } + m_imageDevicePixelRatio = m_devicePixelRatio; + m_taskRunner->PostTask( + FROM_HERE, base::BindOnce(std::move(m_swapCompletionCallback), toGfx(m_image.size()))); + 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)); +QImage DisplaySoftwareOutputSurface::Device::image() +{ + return m_image; +} - return node; +float DisplaySoftwareOutputSurface::Device::devicePixelRatio() +{ + return m_imageDevicePixelRatio; } DisplaySoftwareOutputSurface::DisplaySoftwareOutputSurface() |