summaryrefslogtreecommitdiffstats
path: root/src/core/compositor/compositor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/compositor/compositor.cpp')
-rw-r--r--src/core/compositor/compositor.cpp252
1 files changed, 113 insertions, 139 deletions
diff --git a/src/core/compositor/compositor.cpp b/src/core/compositor/compositor.cpp
index 56693961c..4c0bd4c0d 100644
--- a/src/core/compositor/compositor.cpp
+++ b/src/core/compositor/compositor.cpp
@@ -1,188 +1,162 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 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$
-**
-****************************************************************************/
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "compositor.h"
-#include "compositor_resource_tracker.h"
-#include "delegated_frame_node.h"
+#include "base/memory/ref_counted.h"
+#include "components/viz/common/surfaces/frame_sink_id.h"
-#include "base/task/post_task.h"
-#include "components/viz/common/resources/returned_resource.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-#include "services/viz/public/interfaces/compositing/compositor_frame_sink.mojom.h"
+#include <QHash>
+#include <QMutex>
+#include <QQuickWindow>
namespace QtWebEngineCore {
-Compositor::Compositor(content::RenderWidgetHost *host)
- : m_resourceTracker(new CompositorResourceTracker)
- , m_host(host)
-{
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+// Compositor::Id
- m_taskRunner = base::CreateSingleThreadTaskRunnerWithTraits({content::BrowserThread::UI, base::TaskPriority::USER_VISIBLE});
- m_beginFrameSource =
- std::make_unique<viz::DelayBasedBeginFrameSource>(
- std::make_unique<viz::DelayBasedTimeSource>(m_taskRunner.get()),
- viz::BeginFrameSource::kNotRestartableId);
-}
+Compositor::Id::Id(viz::FrameSinkId fid) : client_id(fid.client_id()), sink_id(fid.sink_id()) { }
-Compositor::~Compositor()
+static size_t qHash(Compositor::Id id, size_t seed = 0)
{
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ QtPrivate::QHashCombine hasher;
+ seed = hasher(seed, id.client_id);
+ seed = hasher(seed, id.sink_id);
+ return seed;
}
-void Compositor::setFrameSinkClient(viz::mojom::CompositorFrameSinkClient *frameSinkClient)
+static bool operator==(Compositor::Id id1, Compositor::Id id2)
{
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
- if (m_frameSinkClient == frameSinkClient)
- return;
-
- // Accumulated resources belong to the old RendererCompositorFrameSink and
- // should not be returned.
- //
- // TODO(juvaldma): Can there be a pending frame from the old client?
- m_resourceTracker->returnResources();
- m_frameSinkClient = frameSinkClient;
+ return id1.client_id == id2.client_id && id1.sink_id == id2.sink_id;
}
-void Compositor::setNeedsBeginFrames(bool needsBeginFrames)
-{
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
- if (m_needsBeginFrames == needsBeginFrames)
- return;
-
- if (needsBeginFrames)
- m_beginFrameSource->AddObserver(this);
- else
- m_beginFrameSource->RemoveObserver(this);
+// Compositor::Binding and Compositor::Bindings
- m_needsBeginFrames = needsBeginFrames;
-}
-
-void Compositor::submitFrame(viz::CompositorFrame frame, base::OnceClosure callback)
+struct Compositor::Binding
{
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- DCHECK(!m_submitCallback);
+ const Id id;
+ Compositor *compositor = nullptr;
+ Observer *observer = nullptr;
- m_pendingFrame = std::move(frame);
- m_submitCallback = std::move(callback);
- m_resourceTracker->submitResources(
- m_pendingFrame,
- base::BindOnce(&Compositor::runSubmitCallback, base::Unretained(this)));
-}
+ Binding(Id id) : id(id) { }
+ ~Binding();
+};
-QSGNode *Compositor::updatePaintNode(QSGNode *oldNode, RenderWidgetHostViewQtDelegate *viewDelegate)
+class Compositor::BindingMap
{
- // DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- //
- // This might be called from a Qt Quick render thread, but the UI thread
- // will still be blocked for the duration of this call.
+public:
+ void lock() { m_mutex.lock(); }
- DelegatedFrameNode *frameNode = static_cast<DelegatedFrameNode *>(oldNode);
- if (!frameNode)
- frameNode = new DelegatedFrameNode;
+ void unlock() { m_mutex.unlock(); }
- if (!m_updatePaintNodeShouldCommit) {
- frameNode->commit(m_committedFrame, viz::CompositorFrame(), m_resourceTracker.get(), viewDelegate);
- return frameNode;
+ 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;
}
- m_updatePaintNodeShouldCommit = false;
- gfx::PresentationFeedback dummyFeedback(base::TimeTicks::Now(), base::TimeDelta(), gfx::PresentationFeedback::Flags::kVSync);
- m_presentations.insert({m_committedFrame.metadata.frame_token, dummyFeedback});
+ void remove(Id id) { m_map.remove(id); }
- m_resourceTracker->commitResources();
- frameNode->commit(m_pendingFrame, m_committedFrame, m_resourceTracker.get(), viewDelegate);
- m_committedFrame = std::move(m_pendingFrame);
- m_pendingFrame = viz::CompositorFrame();
+private:
+ QMutex m_mutex;
+ QHash<Id, Binding *> m_map;
+} static g_bindings;
- m_taskRunner->PostTask(FROM_HERE,
- base::BindOnce(&Compositor::notifyFrameCommitted, m_weakPtrFactory.GetWeakPtr()));
+Compositor::Binding::~Binding()
+{
+ g_bindings.remove(id);
+}
+
+// Compositor::Observer
- return frameNode;
+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::runSubmitCallback()
+void Compositor::Observer::unbind()
{
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ DCHECK(m_binding);
+ g_bindings.lock();
+ m_binding->observer = nullptr;
+ if (m_binding->compositor == nullptr)
+ delete m_binding;
+ m_binding = nullptr;
+ g_bindings.unlock();
+}
- m_updatePaintNodeShouldCommit = true;
- std::move(m_submitCallback).Run();
+Compositor::Handle<Compositor> Compositor::Observer::compositor()
+{
+ g_bindings.lock();
+ if (m_binding && m_binding->compositor)
+ return m_binding->compositor; // delay unlock
+ g_bindings.unlock();
+ return nullptr;
}
-void Compositor::notifyFrameCommitted()
+// Compositor
+
+void Compositor::bind(Id id)
{
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ DCHECK(!m_binding);
+ g_bindings.lock();
+ m_binding = g_bindings.findOrCreate(id);
+ DCHECK(!m_binding->compositor);
+ m_binding->compositor = this;
+ g_bindings.unlock();
+}
- m_beginFrameSource->DidFinishFrame(this);
- if (m_frameSinkClient)
- m_frameSinkClient->DidReceiveCompositorFrameAck(m_resourceTracker->returnResources());
+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();
}
-void Compositor::sendPresentationFeedback(uint frame_token)
+Compositor::Handle<Compositor::Observer> Compositor::observer()
{
- gfx::PresentationFeedback dummyFeedback(base::TimeTicks::Now(), base::TimeDelta(), gfx::PresentationFeedback::Flags::kVSync);
- m_presentations.insert({frame_token, dummyFeedback});
+ g_bindings.lock();
+ if (m_binding && m_binding->observer)
+ return m_binding->observer; // delay unlock
+ g_bindings.unlock();
+ return nullptr;
}
-bool Compositor::OnBeginFrameDerivedImpl(const viz::BeginFrameArgs &args)
+void Compositor::waitForTexture()
{
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+}
- ProgressFlingIfNeeded(m_host, args.frame_time);
- m_beginFrameSource->OnUpdateVSyncParameters(args.frame_time, args.interval);
- if (m_frameSinkClient) {
- m_frameSinkClient->OnBeginFrame(args, m_presentations);
- m_presentations.clear();
- }
+void Compositor::releaseTexture()
+{
+}
- return true;
+QSGTexture *Compositor::texture(QQuickWindow *, uint32_t textureOptions)
+{
+ Q_UNREACHABLE();
+ return nullptr;
}
-void Compositor::OnBeginFrameSourcePausedChanged(bool)
+bool Compositor::textureIsFlipped()
{
- // Ignored for now. If the begin frame source is paused, the renderer
- // doesn't need to be informed about it and will just not receive more
- // begin frames.
+ Q_UNREACHABLE();
+ return false;
}
+void Compositor::releaseResources() { }
+
+// static
+void Compositor::unlockBindings()
+{
+ g_bindings.unlock();
+}
} // namespace QtWebEngineCore