summaryrefslogtreecommitdiffstats
path: root/src/core/delegated_frame_node.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/delegated_frame_node.cpp')
-rw-r--r--src/core/delegated_frame_node.cpp1404
1 files changed, 0 insertions, 1404 deletions
diff --git a/src/core/delegated_frame_node.cpp b/src/core/delegated_frame_node.cpp
deleted file mode 100644
index 8ac82dbf1..000000000
--- a/src/core/delegated_frame_node.cpp
+++ /dev/null
@@ -1,1404 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 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$
-**
-****************************************************************************/
-
-// On Mac we need to reset this define in order to prevent definition
-// of "check" macros etc. The "check" macro collides with a member function name in QtQuick.
-// See AssertMacros.h in the Mac SDK.
-#include <QtGlobal> // We need this for the Q_OS_MAC define.
-#if defined(Q_OS_MAC)
-#undef __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES
-#define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0
-#endif
-
-#include "delegated_frame_node.h"
-
-#include "chromium_gpu_helper.h"
-#include "ozone/gl_surface_qt.h"
-#include "stream_video_node.h"
-#include "type_conversion.h"
-#include "yuv_video_node.h"
-
-#include "base/bind.h"
-#include "base/message_loop/message_loop.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "cc/base/math_util.h"
-#include "components/viz/common/quads/compositor_frame.h"
-#include "components/viz/common/quads/compositor_frame_metadata.h"
-#include "components/viz/common/quads/debug_border_draw_quad.h"
-#include "components/viz/common/quads/draw_quad.h"
-#include "components/viz/common/quads/render_pass_draw_quad.h"
-#include "components/viz/common/quads/solid_color_draw_quad.h"
-#include "components/viz/common/quads/stream_video_draw_quad.h"
-#include "components/viz/common/quads/texture_draw_quad.h"
-#include "components/viz/common/quads/tile_draw_quad.h"
-#include "components/viz/common/quads/yuv_video_draw_quad.h"
-#include "components/viz/common/resources/returned_resource.h"
-#include "components/viz/common/resources/transferable_resource.h"
-#include "components/viz/service/display/bsp_tree.h"
-#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
-#include "content/browser/browser_main_loop.h"
-#include "gpu/command_buffer/service/mailbox_manager.h"
-#include "ui/gl/gl_context.h"
-#include "ui/gl/gl_fence.h"
-
-#ifndef QT_NO_OPENGL
-# include <QOpenGLContext>
-# include <QOpenGLFunctions>
-# include <QSGFlatColorMaterial>
-#endif
-#include <QSGTexture>
-#include <private/qsgadaptationlayer_p.h>
-
-#include <QSGImageNode>
-#include <QSGRectangleNode>
-
-#if !defined(QT_NO_EGL)
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#endif
-
-#ifndef GL_TIMEOUT_IGNORED
-#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull
-#endif
-
-#ifndef GL_TEXTURE_RECTANGLE
-#define GL_TEXTURE_RECTANGLE 0x84F5
-#endif
-
-#ifndef GL_NEAREST
-#define GL_NEAREST 0x2600
-#endif
-
-#ifndef GL_LINEAR
-#define GL_LINEAR 0x2601
-#endif
-
-#ifndef GL_RGBA
-#define GL_RGBA 0x1908
-#endif
-
-#ifndef GL_RGB
-#define GL_RGB 0x1907
-#endif
-
-#ifndef GL_LINE_LOOP
-#define GL_LINE_LOOP 0x0002
-#endif
-
-#ifndef QT_NO_OPENGL
-QT_BEGIN_NAMESPACE
-Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context();
-QT_END_NAMESPACE
-#endif
-
-namespace QtWebEngineCore {
-#ifndef QT_NO_OPENGL
-class MailboxTexture : public QSGTexture, protected QOpenGLFunctions {
-public:
- MailboxTexture(const gpu::MailboxHolder &mailboxHolder, const QSize textureSize);
- ~MailboxTexture();
- // QSGTexture:
- int textureId() const override { return m_textureId; }
- QSize textureSize() const override { return m_textureSize; }
- bool hasAlphaChannel() const override { return m_hasAlpha; }
- bool hasMipmaps() const override { return false; }
- void bind() override;
-
- void setHasAlphaChannel(bool hasAlpha) { m_hasAlpha = hasAlpha; }
- gpu::MailboxHolder &mailboxHolder() { return m_mailboxHolder; }
- void fetchTexture(gpu::MailboxManager *mailboxManager);
- void setTarget(GLenum target);
-
-private:
- gpu::MailboxHolder m_mailboxHolder;
- int m_textureId;
- QSize m_textureSize;
- bool m_hasAlpha;
- GLenum m_target;
-#if defined(USE_OZONE)
- bool m_ownsTexture;
-#endif
-#ifdef Q_OS_QNX
- EGLStreamData m_eglStreamData;
-#endif
- friend class DelegatedFrameNode;
-};
-#endif // QT_NO_OPENGL
-class ResourceHolder {
-public:
- ResourceHolder(const viz::TransferableResource &resource);
- QSharedPointer<QSGTexture> initTexture(bool quadIsAllOpaque, RenderWidgetHostViewQtDelegate *apiDelegate = 0);
- QSGTexture *texture() const { return m_texture.data(); }
- viz::ReturnedResource returnResource();
- void incImportCount() { ++m_importCount; }
- bool needsToFetch() const { return !m_resource.is_software && m_texture && !m_texture.data()->textureId(); }
-
-private:
- QWeakPointer<QSGTexture> m_texture;
- viz::TransferableResource m_resource;
- int m_importCount;
-};
-
-class RectClipNode : public QSGClipNode
-{
-public:
- RectClipNode(const QRectF &);
-private:
- QSGGeometry m_geometry;
-};
-
-class DelegatedNodeTreeHandler
-{
-public:
- DelegatedNodeTreeHandler(QVector<QSGNode*> *sceneGraphNodes)
- : m_sceneGraphNodes(sceneGraphNodes)
- {
- }
-
- virtual ~DelegatedNodeTreeHandler(){}
-
- virtual void setupRenderPassNode(QSGTexture *, const QRect &, const QRectF &, QSGNode *) = 0;
- virtual void setupTextureContentNode(QSGTexture *, const QRect &, const QRectF &,
- QSGImageNode::TextureCoordinatesTransformMode,
- QSGNode *) = 0;
- virtual void setupSolidColorNode(const QRect &, const QColor &, QSGNode *) = 0;
-
-#ifndef QT_NO_OPENGL
- virtual void setupDebugBorderNode(QSGGeometry *, QSGFlatColorMaterial *, QSGNode *) = 0;
- virtual void setupYUVVideoNode(QSGTexture *, QSGTexture *, QSGTexture *, QSGTexture *,
- const QRectF &, const QRectF &, const QSizeF &, const QSizeF &,
- gfx::ColorSpace, float, float, const QRectF &,
- QSGNode *) = 0;
-#ifdef GL_OES_EGL_image_external
- virtual void setupStreamVideoNode(MailboxTexture *, const QRectF &,
- const QMatrix4x4 &, QSGNode *) = 0;
-#endif // GL_OES_EGL_image_external
-#endif // QT_NO_OPENGL
-protected:
- QVector<QSGNode*> *m_sceneGraphNodes;
-};
-
-class DelegatedNodeTreeUpdater : public DelegatedNodeTreeHandler
-{
-public:
- DelegatedNodeTreeUpdater(QVector<QSGNode*> *sceneGraphNodes)
- : DelegatedNodeTreeHandler(sceneGraphNodes)
- , m_nodeIterator(sceneGraphNodes->begin())
- {
- }
-
- void setupRenderPassNode(QSGTexture *layer, const QRect &rect, const QRectF &sourceRect, QSGNode *) override
- {
- Q_ASSERT(layer);
- Q_ASSERT(m_nodeIterator != m_sceneGraphNodes->end());
- QSGInternalImageNode *imageNode = static_cast<QSGInternalImageNode*>(*m_nodeIterator++);
- imageNode->setTargetRect(rect);
- imageNode->setInnerTargetRect(rect);
- imageNode->setSubSourceRect(layer->convertToNormalizedSourceRect(sourceRect));
- imageNode->setTexture(layer);
- imageNode->update();
- }
-
- void setupTextureContentNode(QSGTexture *texture, const QRect &rect, const QRectF &sourceRect,
- QSGImageNode::TextureCoordinatesTransformMode texCoordTransForm,
- QSGNode *) override
- {
- Q_ASSERT(m_nodeIterator != m_sceneGraphNodes->end());
- QSGImageNode *textureNode = static_cast<QSGImageNode*>(*m_nodeIterator++);
- if (textureNode->texture() != texture) {
- // Chromium sometimes uses textures that doesn't completely fit
- // in which case the geometry needs to be recalculated even if
- // rect and src-rect matches.
- if (textureNode->texture()->textureSize() != texture->textureSize())
- textureNode->markDirty(QSGImageNode::DirtyGeometry);
- textureNode->setTexture(texture);
- }
- if (textureNode->textureCoordinatesTransform() != texCoordTransForm)
- textureNode->setTextureCoordinatesTransform(texCoordTransForm);
- if (textureNode->rect() != rect)
- textureNode->setRect(rect);
- if (textureNode->sourceRect() != sourceRect)
- textureNode->setSourceRect(sourceRect);
- if (textureNode->filtering() != texture->filtering())
- textureNode->setFiltering(texture->filtering());
- }
- void setupSolidColorNode(const QRect &rect, const QColor &color, QSGNode *) override
- {
- Q_ASSERT(m_nodeIterator != m_sceneGraphNodes->end());
- QSGRectangleNode *rectangleNode = static_cast<QSGRectangleNode*>(*m_nodeIterator++);
-
- if (rectangleNode->rect() != rect)
- rectangleNode->setRect(rect);
- if (rectangleNode->color() != color)
- rectangleNode->setColor(color);
- }
-#ifndef QT_NO_OPENGL
- void setupDebugBorderNode(QSGGeometry *geometry, QSGFlatColorMaterial *material,
- QSGNode *) override
- {
- Q_ASSERT(m_nodeIterator != m_sceneGraphNodes->end());
- QSGGeometryNode *geometryNode = static_cast<QSGGeometryNode*>(*m_nodeIterator++);
-
- geometryNode->setGeometry(geometry);
- geometryNode->setMaterial(material);
- }
-
- void setupYUVVideoNode(QSGTexture *, QSGTexture *, QSGTexture *, QSGTexture *,
- const QRectF &, const QRectF &, const QSizeF &, const QSizeF &,
- gfx::ColorSpace, float, float, const QRectF &,
- QSGNode *) override
- {
- Q_UNREACHABLE();
- }
-#ifdef GL_OES_EGL_image_external
- void setupStreamVideoNode(MailboxTexture *, const QRectF &,
- const QMatrix4x4 &, QSGNode *) override
- {
- Q_UNREACHABLE();
- }
-#endif // GL_OES_EGL_image_external
-#endif // QT_NO_OPENGL
-
-private:
- QVector<QSGNode*>::iterator m_nodeIterator;
-};
-
-class DelegatedNodeTreeCreator : public DelegatedNodeTreeHandler
-{
-public:
- DelegatedNodeTreeCreator(QVector<QSGNode*> *sceneGraphNodes,
- RenderWidgetHostViewQtDelegate *apiDelegate)
- : DelegatedNodeTreeHandler(sceneGraphNodes)
- , m_apiDelegate(apiDelegate)
- {
- }
-
- void setupRenderPassNode(QSGTexture *layer, const QRect &rect, const QRectF &sourceRect,
- QSGNode *layerChain) override
- {
- Q_ASSERT(layer);
- // Only QSGInternalImageNode currently supports QSGLayer textures.
- QSGInternalImageNode *imageNode = m_apiDelegate->createInternalImageNode();
- imageNode->setTargetRect(rect);
- imageNode->setInnerTargetRect(rect);
- imageNode->setSubSourceRect(layer->convertToNormalizedSourceRect(sourceRect));
- imageNode->setTexture(layer);
- imageNode->update();
-
- layerChain->appendChildNode(imageNode);
- m_sceneGraphNodes->append(imageNode);
- }
-
- void setupTextureContentNode(QSGTexture *texture, const QRect &rect, const QRectF &sourceRect,
- QSGImageNode::TextureCoordinatesTransformMode texCoordTransForm,
- QSGNode *layerChain) override
- {
- QSGImageNode *textureNode = m_apiDelegate->createImageNode();
- textureNode->setTextureCoordinatesTransform(texCoordTransForm);
- textureNode->setRect(rect);
- textureNode->setSourceRect(sourceRect);
- textureNode->setTexture(texture);
- textureNode->setFiltering(texture->filtering());
-
- layerChain->appendChildNode(textureNode);
- m_sceneGraphNodes->append(textureNode);
- }
-
- void setupSolidColorNode(const QRect &rect, const QColor &color,
- QSGNode *layerChain) override
- {
- QSGRectangleNode *rectangleNode = m_apiDelegate->createRectangleNode();
- rectangleNode->setRect(rect);
- rectangleNode->setColor(color);
-
- layerChain->appendChildNode(rectangleNode);
- m_sceneGraphNodes->append(rectangleNode);
- }
-
-#ifndef QT_NO_OPENGL
- void setupDebugBorderNode(QSGGeometry *geometry, QSGFlatColorMaterial *material,
- QSGNode *layerChain) override
- {
- QSGGeometryNode *geometryNode = new QSGGeometryNode;
- geometryNode->setFlags(QSGNode::OwnsGeometry | QSGNode::OwnsMaterial);
-
- geometryNode->setGeometry(geometry);
- geometryNode->setMaterial(material);
-
- layerChain->appendChildNode(geometryNode);
- m_sceneGraphNodes->append(geometryNode);
- }
-
- void setupYUVVideoNode(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture,
- QSGTexture *aTexture, const QRectF &yaTexCoordRect,
- const QRectF &uvTexCoordRect, const QSizeF &yaTexSize,
- const QSizeF &uvTexSize, gfx::ColorSpace colorspace,
- float rMul, float rOff, const QRectF &rect,
- QSGNode *layerChain) override
- {
- YUVVideoNode *videoNode = new YUVVideoNode(
- yTexture,
- uTexture,
- vTexture,
- aTexture,
- yaTexCoordRect,
- uvTexCoordRect,
- yaTexSize,
- uvTexSize,
- colorspace,
- rMul,
- rOff);
- videoNode->setRect(rect);
-
- layerChain->appendChildNode(videoNode);
- m_sceneGraphNodes->append(videoNode);
- }
-#ifdef GL_OES_EGL_image_external
- void setupStreamVideoNode(MailboxTexture *texture, const QRectF &rect,
- const QMatrix4x4 &textureMatrix, QSGNode *layerChain) override
- {
- StreamVideoNode *svideoNode = new StreamVideoNode(texture, false, ExternalTarget);
- svideoNode->setRect(rect);
- svideoNode->setTextureMatrix(textureMatrix);
- layerChain->appendChildNode(svideoNode);
- m_sceneGraphNodes->append(svideoNode);
- }
-#endif // GL_OES_EGL_image_external
-#endif // QT_NO_OPENGL
-
-private:
- RenderWidgetHostViewQtDelegate *m_apiDelegate;
-};
-
-
-static inline QSharedPointer<QSGLayer> findRenderPassLayer(const int &id, const QVector<QPair<int, QSharedPointer<QSGLayer> > > &list)
-{
- typedef QPair<int, QSharedPointer<QSGLayer> > Pair;
- for (const Pair &pair : list)
- if (pair.first == id)
- return pair.second;
- return QSharedPointer<QSGLayer>();
-}
-
-static QSGNode *buildRenderPassChain(QSGNode *chainParent)
-{
- // Chromium already ordered the quads from back to front for us, however the
- // Qt scene graph layers individual geometries in their own z-range and uses
- // the depth buffer to visually stack nodes according to their item tree order.
-
- // This gets rid of the z component of all quads, once any x and y perspective
- // transformation has been applied to vertices not on the z=0 plane. Qt will
- // use an orthographic projection to render them.
- QSGTransformNode *zCompressNode = new QSGTransformNode;
- QMatrix4x4 zCompressMatrix;
- zCompressMatrix.scale(1, 1, 0);
- zCompressNode->setMatrix(zCompressMatrix);
- chainParent->appendChildNode(zCompressNode);
- return zCompressNode;
-}
-
-static QSGNode *buildLayerChain(QSGNode *chainParent, const viz::SharedQuadState *layerState)
-{
- QSGNode *layerChain = chainParent;
- if (layerState->is_clipped) {
- RectClipNode *clipNode = new RectClipNode(toQt(layerState->clip_rect));
- layerChain->appendChildNode(clipNode);
- layerChain = clipNode;
- }
- if (!layerState->quad_to_target_transform.IsIdentity()) {
- QSGTransformNode *transformNode = new QSGTransformNode;
- transformNode->setMatrix(toQt(layerState->quad_to_target_transform.matrix()));
- layerChain->appendChildNode(transformNode);
- layerChain = transformNode;
- }
- if (layerState->opacity < 1.0) {
- QSGOpacityNode *opacityNode = new QSGOpacityNode;
- opacityNode->setOpacity(layerState->opacity);
- layerChain->appendChildNode(opacityNode);
- layerChain = opacityNode;
- }
- return layerChain;
-}
-
-#ifndef QT_NO_OPENGL
-static void waitChromiumSync(gl::TransferableFence *sync)
-{
- // Chromium uses its own GL bindings and stores in in thread local storage.
- // For that reason, let chromium_gpu_helper.cpp contain the producing code that will run in the Chromium
- // GPU thread, and put the sync consuming code here that will run in the QtQuick SG or GUI thread.
- switch (sync->type) {
- case gl::TransferableFence::NoSync:
- break;
- case gl::TransferableFence::EglSync:
-#ifdef EGL_KHR_reusable_sync
- {
- static bool resolved = false;
- static PFNEGLCLIENTWAITSYNCKHRPROC eglClientWaitSyncKHR = 0;
-
- if (!resolved) {
- if (gl::GLSurfaceQt::HasEGLExtension("EGL_KHR_fence_sync")) {
- QOpenGLContext *context = QOpenGLContext::currentContext();
- eglClientWaitSyncKHR = (PFNEGLCLIENTWAITSYNCKHRPROC)context->getProcAddress("eglClientWaitSyncKHR");
- }
- resolved = true;
- }
-
- if (eglClientWaitSyncKHR)
- // FIXME: Use the less wasteful eglWaitSyncKHR once we have a device that supports EGL_KHR_wait_sync.
- eglClientWaitSyncKHR(sync->egl.display, sync->egl.sync, 0, EGL_FOREVER_KHR);
- }
-#endif
- break;
- case gl::TransferableFence::ArbSync:
- typedef void (QOPENGLF_APIENTRYP WaitSyncPtr)(GLsync sync, GLbitfield flags, GLuint64 timeout);
- static WaitSyncPtr glWaitSync_ = 0;
- if (!glWaitSync_) {
- QOpenGLContext *context = QOpenGLContext::currentContext();
- glWaitSync_ = (WaitSyncPtr)context->getProcAddress("glWaitSync");
- Q_ASSERT(glWaitSync_);
- }
- glWaitSync_(sync->arb.sync, 0, GL_TIMEOUT_IGNORED);
- break;
- }
-}
-
-static void deleteChromiumSync(gl::TransferableFence *sync)
-{
- // Chromium uses its own GL bindings and stores in in thread local storage.
- // For that reason, let chromium_gpu_helper.cpp contain the producing code that will run in the Chromium
- // GPU thread, and put the sync consuming code here that will run in the QtQuick SG or GUI thread.
- switch (sync->type) {
- case gl::TransferableFence::NoSync:
- break;
- case gl::TransferableFence::EglSync:
-#ifdef EGL_KHR_reusable_sync
- {
- static bool resolved = false;
- static PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR = 0;
-
- if (!resolved) {
- if (gl::GLSurfaceQt::HasEGLExtension("EGL_KHR_fence_sync")) {
- QOpenGLContext *context = QOpenGLContext::currentContext();
- eglDestroySyncKHR = (PFNEGLDESTROYSYNCKHRPROC)context->getProcAddress("eglDestroySyncKHR");
- }
- resolved = true;
- }
-
- if (eglDestroySyncKHR) {
- // FIXME: Use the less wasteful eglWaitSyncKHR once we have a device that supports EGL_KHR_wait_sync.
- eglDestroySyncKHR(sync->egl.display, sync->egl.sync);
- sync->reset();
- }
- }
-#endif
- break;
- case gl::TransferableFence::ArbSync:
- typedef void (QOPENGLF_APIENTRYP DeleteSyncPtr)(GLsync sync);
- static DeleteSyncPtr glDeleteSync_ = 0;
- if (!glDeleteSync_) {
- QOpenGLContext *context = QOpenGLContext::currentContext();
- glDeleteSync_ = (DeleteSyncPtr)context->getProcAddress("glDeleteSync");
- Q_ASSERT(glDeleteSync_);
- }
- glDeleteSync_(sync->arb.sync);
- sync->reset();
- break;
- }
- // If Chromium was able to create a sync, we should have been able to handle its type here too.
- Q_ASSERT(!*sync);
-}
-
-MailboxTexture::MailboxTexture(const gpu::MailboxHolder &mailboxHolder, const QSize textureSize)
- : m_mailboxHolder(mailboxHolder)
- , m_textureId(0)
- , m_textureSize(textureSize)
- , m_hasAlpha(false)
- , m_target(GL_TEXTURE_2D)
-#if defined(USE_OZONE)
- , m_ownsTexture(false)
-#endif
-{
- initializeOpenGLFunctions();
-
- // Assume that resources without a size will be used with a full source rect.
- // Setting a size of 1x1 will let any texture node compute a normalized source
- // rect of (0, 0) to (1, 1) while an empty texture size would set (0, 0) on all corners.
- if (m_textureSize.isEmpty())
- m_textureSize = QSize(1, 1);
-}
-
-MailboxTexture::~MailboxTexture()
-{
-#if defined(USE_OZONE)
- // This is rare case, where context is not shared
- // we created extra texture in current context, so
- // delete it now
- if (m_ownsTexture) {
- QOpenGLContext *currentContext = QOpenGLContext::currentContext() ;
- QOpenGLFunctions *funcs = currentContext->functions();
- GLuint id(m_textureId);
- funcs->glDeleteTextures(1, &id);
- }
-#endif
-}
-
-void MailboxTexture::bind()
-{
- glBindTexture(m_target, m_textureId);
-#ifdef Q_OS_QNX
- if (m_target == GL_TEXTURE_EXTERNAL_OES) {
- static bool resolved = false;
- static PFNEGLSTREAMCONSUMERACQUIREKHRPROC eglStreamConsumerAcquire = 0;
-
- if (!resolved) {
- QOpenGLContext *context = QOpenGLContext::currentContext();
- eglStreamConsumerAcquire = (PFNEGLSTREAMCONSUMERACQUIREKHRPROC)context->getProcAddress("eglStreamConsumerAcquireKHR");
- resolved = true;
- }
- if (eglStreamConsumerAcquire)
- eglStreamConsumerAcquire(m_eglStreamData.egl_display, m_eglStreamData.egl_str_handle);
- }
-#endif
-}
-
-void MailboxTexture::setTarget(GLenum target)
-{
- m_target = target;
-}
-
-void MailboxTexture::fetchTexture(gpu::MailboxManager *mailboxManager)
-{
- gpu::TextureBase *tex = ConsumeTexture(mailboxManager, m_target, m_mailboxHolder.mailbox);
-
- // The texture might already have been deleted (e.g. when navigating away from a page).
- if (tex) {
- m_textureId = service_id(tex);
-#ifdef Q_OS_QNX
- if (m_target == GL_TEXTURE_EXTERNAL_OES) {
- m_eglStreamData = eglstream_connect_consumer(tex);
- }
-#endif
- }
-}
-#endif //QT_NO_OPENGL
-
-ResourceHolder::ResourceHolder(const viz::TransferableResource &resource)
- : m_resource(resource)
- , m_importCount(1)
-{
-}
-
-QSharedPointer<QSGTexture> ResourceHolder::initTexture(bool quadNeedsBlending, RenderWidgetHostViewQtDelegate *apiDelegate)
-{
- QSharedPointer<QSGTexture> texture = m_texture.toStrongRef();
- if (!texture) {
- if (m_resource.is_software) {
- Q_ASSERT(apiDelegate);
- std::unique_ptr<viz::SharedBitmap> sharedBitmap =
- content::BrowserMainLoop::GetInstance()->GetServerSharedBitmapManager()->GetSharedBitmapFromId(
- m_resource.size, viz::BGRA_8888, m_resource.mailbox_holder.mailbox);
- // QSG interprets QImage::hasAlphaChannel meaning that a node should enable blending
- // to draw it but Chromium keeps this information in the quads.
- // The input format is currently always Format_ARGB32_Premultiplied, so assume that all
- // alpha bytes are 0xff if quads aren't requesting blending and avoid the conversion
- // from Format_ARGB32_Premultiplied to Format_RGB32 just to get hasAlphaChannel to
- // return false.
- QImage::Format format = quadNeedsBlending ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32;
- QImage image = sharedBitmap
- ? QImage(sharedBitmap->pixels(), m_resource.size.width(), m_resource.size.height(), format)
- : QImage(m_resource.size.width(), m_resource.size.height(), format);
- texture.reset(apiDelegate->createTextureFromImage(image.copy()));
- } else {
-#ifndef QT_NO_OPENGL
- texture.reset(new MailboxTexture(m_resource.mailbox_holder, toQt(m_resource.size)));
- static_cast<MailboxTexture *>(texture.data())->setHasAlphaChannel(quadNeedsBlending);
-#else
- Q_UNREACHABLE();
-#endif
- }
- if (m_resource.filter == GL_NEAREST)
- texture->setFiltering(QSGTexture::Nearest);
- else if (m_resource.filter == GL_LINEAR)
- texture->setFiltering(QSGTexture::Linear);
- else {
- // Depends on qtdeclarative fix, see QTBUG-71322
-#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 1)
- texture->setFiltering(QSGTexture::Linear);
-#else
- texture->setFiltering(QSGTexture::Nearest);
-#endif
- }
- m_texture = texture;
- }
- // All quads using a resource should request the same blending state.
- Q_ASSERT(texture->hasAlphaChannel() || !quadNeedsBlending);
- return texture;
-}
-
-viz::ReturnedResource ResourceHolder::returnResource()
-{
- viz::ReturnedResource returned;
- // The ResourceProvider ensures that the resource isn't used by the parent compositor's GL
- // context in the GPU process by inserting a sync point to be waited for by the child
- // compositor's GL context. We don't need this since we are triggering the delegated frame
- // ack directly from our rendering thread. At this point (in updatePaintNode) we know that
- // a frame that was compositing any of those resources has already been swapped and we thus
- // don't need to use this mechanism.
- returned.id = m_resource.id;
- returned.count = m_importCount;
- m_importCount = 0;
- return returned;
-}
-
-
-RectClipNode::RectClipNode(const QRectF &rect)
- : m_geometry(QSGGeometry::defaultAttributes_Point2D(), 4)
-{
- QSGGeometry::updateRectGeometry(&m_geometry, rect);
- setGeometry(&m_geometry);
- setClipRect(rect);
- setIsRectangular(true);
-}
-
-DelegatedFrameNode::DelegatedFrameNode()
- : m_numPendingSyncPoints(0)
-#if defined(USE_OZONE) && !defined(QT_NO_OPENGL)
- , m_contextShared(true)
-#endif
-{
- setFlag(UsePreprocess);
-#if defined(USE_OZONE) && !defined(QT_NO_OPENGL)
- QOpenGLContext *currentContext = QOpenGLContext::currentContext() ;
- QOpenGLContext *sharedContext = qt_gl_global_share_context();
- if (currentContext && sharedContext && !QOpenGLContext::areSharing(currentContext, sharedContext)) {
- static bool allowNotSharedContextWarningShown = true;
- if (allowNotSharedContextWarningShown) {
- allowNotSharedContextWarningShown = false;
- qWarning("Context is not shared, textures will be copied between contexts.");
- }
- m_offsurface.reset(new QOffscreenSurface);
- m_offsurface->create();
- m_contextShared = false;
- }
-#endif
-}
-
-DelegatedFrameNode::~DelegatedFrameNode()
-{
-}
-
-void DelegatedFrameNode::preprocess()
-{
-#ifndef QT_NO_OPENGL
- // With the threaded render loop the GUI thread has been unlocked at this point.
- // We can now wait for the Chromium GPU thread to produce textures that will be
- // rendered on our quads and fetch the IDs from the mailboxes we were given.
- QList<MailboxTexture *> mailboxesToFetch;
- typedef QHash<unsigned, QSharedPointer<ResourceHolder> >::const_iterator ResourceHolderIterator;
- ResourceHolderIterator end = m_chromiumCompositorData->resourceHolders.constEnd();
- for (ResourceHolderIterator it = m_chromiumCompositorData->resourceHolders.constBegin(); it != end ; ++it) {
- if ((*it)->needsToFetch())
- mailboxesToFetch.append(static_cast<MailboxTexture *>((*it)->texture()));
- }
-
- if (!mailboxesToFetch.isEmpty())
- fetchAndSyncMailboxes(mailboxesToFetch);
-#endif
-
- // Then render any intermediate RenderPass in order.
- typedef QPair<int, QSharedPointer<QSGLayer> > Pair;
- for (const Pair &pair : qAsConst(m_sgObjects.renderPassLayers)) {
- // The layer is non-live, request a one-time update here.
- pair.second->scheduleUpdate();
- // Proceed with the actual update.
- pair.second->updateTexture();
- }
-}
-
-static bool areSharedQuadStatesEqual(const viz::SharedQuadState *layerState,
- const viz::SharedQuadState *prevLayerState)
-{
- if (layerState->sorting_context_id != 0 || prevLayerState->sorting_context_id != 0)
- return false;
- if (layerState->is_clipped != prevLayerState->is_clipped
- || layerState->clip_rect != prevLayerState->clip_rect)
- return false;
- if (layerState->quad_to_target_transform != prevLayerState->quad_to_target_transform)
- return false;
- return qFuzzyCompare(layerState->opacity, prevLayerState->opacity);
-}
-
-// Compares if the frame data that we got from the Chromium Compositor is
-// *structurally* equivalent to the one of the previous frame.
-// If it is, we will just reuse and update the old nodes where necessary.
-static bool areRenderPassStructuresEqual(viz::CompositorFrame *frameData,
- viz::CompositorFrame *previousFrameData)
-{
- if (!previousFrameData)
- return false;
-
- if (previousFrameData->render_pass_list.size() != frameData->render_pass_list.size())
- return false;
-
- for (unsigned i = 0; i < frameData->render_pass_list.size(); ++i) {
- viz::RenderPass *newPass = frameData->render_pass_list.at(i).get();
- viz::RenderPass *prevPass = previousFrameData->render_pass_list.at(i).get();
-
- if (newPass->id != prevPass->id)
- return false;
-
- if (newPass->quad_list.size() != prevPass->quad_list.size())
- return false;
-
- viz::QuadList::ConstBackToFrontIterator it = newPass->quad_list.BackToFrontBegin();
- viz::QuadList::ConstBackToFrontIterator end = newPass->quad_list.BackToFrontEnd();
- viz::QuadList::ConstBackToFrontIterator prevIt = prevPass->quad_list.BackToFrontBegin();
- viz::QuadList::ConstBackToFrontIterator prevEnd = prevPass->quad_list.BackToFrontEnd();
- for (; it != end && prevIt != prevEnd; ++it, ++prevIt) {
- const viz::DrawQuad *quad = *it;
- const viz::DrawQuad *prevQuad = *prevIt;
- if (quad->material != prevQuad->material)
- return false;
-#ifndef QT_NO_OPENGL
- if (quad->material == viz::DrawQuad::YUV_VIDEO_CONTENT)
- return false;
-#ifdef GL_OES_EGL_image_external
- if (quad->material == viz::DrawQuad::STREAM_VIDEO_CONTENT)
- return false;
-#endif // GL_OES_EGL_image_external
-#endif // QT_NO_OPENGL
- if (!areSharedQuadStatesEqual(quad->shared_quad_state, prevQuad->shared_quad_state))
- return false;
- if (quad->shared_quad_state->is_clipped && quad->visible_rect != prevQuad->visible_rect) {
- gfx::Rect targetRect1 =
- cc::MathUtil::MapEnclosingClippedRect(quad->shared_quad_state->quad_to_target_transform, quad->visible_rect);
- gfx::Rect targetRect2 =
- cc::MathUtil::MapEnclosingClippedRect(quad->shared_quad_state->quad_to_target_transform, prevQuad->visible_rect);
- targetRect1.Intersect(quad->shared_quad_state->clip_rect);
- targetRect2.Intersect(quad->shared_quad_state->clip_rect);
- if (targetRect1.IsEmpty() != targetRect2.IsEmpty())
- return false;
- }
- }
- }
- return true;
-}
-
-void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
- std::vector<viz::ReturnedResource> *resourcesToRelease,
- RenderWidgetHostViewQtDelegate *apiDelegate)
-{
- m_chromiumCompositorData = chromiumCompositorData;
- viz::CompositorFrame* frameData = &m_chromiumCompositorData->frameData;
- if (frameData->render_pass_list.empty())
- return;
-
- // DelegatedFrameNode is a transform node only for the purpose of
- // countering the scale of devicePixel-scaled tiles when rendering them
- // to the final surface.
- QMatrix4x4 matrix;
- const float devicePixelRatio = m_chromiumCompositorData->frameDevicePixelRatio;
- matrix.scale(1 / devicePixelRatio, 1 / devicePixelRatio);
- if (QSGTransformNode::matrix() != matrix)
- setMatrix(matrix);
-
- QHash<unsigned, QSharedPointer<ResourceHolder> > resourceCandidates;
- qSwap(m_chromiumCompositorData->resourceHolders, resourceCandidates);
-
- // A frame's resource_list only contains the new resources to be added to the scene. Quads can
- // still reference resources that were added in previous frames. Add them to the list of
- // candidates to be picked up by quads, it's then our responsibility to return unused resources
- // to the producing child compositor.
- for (unsigned i = 0; i < frameData->resource_list.size(); ++i) {
- const viz::TransferableResource &res = frameData->resource_list.at(i);
- if (QSharedPointer<ResourceHolder> resource = resourceCandidates.value(res.id))
- resource->incImportCount();
- else
- resourceCandidates[res.id] = QSharedPointer<ResourceHolder>(new ResourceHolder(res));
- }
-
- frameData->resource_list.clear();
- QScopedPointer<DelegatedNodeTreeHandler> nodeHandler;
-
- const QSizeF viewportSizeInPt = apiDelegate->screenRect().size();
- const QSizeF viewportSizeF = viewportSizeInPt * devicePixelRatio;
- const QSize viewportSize(std::ceil(viewportSizeF.width()), std::ceil(viewportSizeF.height()));
-
- // We first compare if the render passes from the previous frame data are structurally
- // equivalent to the render passes in the current frame data. If they are, we are going
- // to reuse the old nodes. Otherwise, we will delete the old nodes and build a new tree.
- //
- // Additionally, because we clip (i.e. don't build scene graph nodes for) quads outside
- // of the visible area, we also have to rebuild the tree whenever the window is resized.
- const bool buildNewTree =
- !areRenderPassStructuresEqual(frameData, &m_chromiumCompositorData->previousFrameData) ||
- m_sceneGraphNodes.empty() ||
- viewportSize != m_previousViewportSize;
-
- m_chromiumCompositorData->previousFrameData = viz::CompositorFrame();
- SGObjects previousSGObjects;
- QVector<QSharedPointer<QSGTexture> > textureStrongRefs;
- if (buildNewTree) {
- // Keep the old objects in scope to hold a ref on layers, resources and textures
- // that we can re-use. Destroy the remaining objects before returning.
- qSwap(m_sgObjects, previousSGObjects);
- // Discard the scene graph nodes from the previous frame.
- while (QSGNode *oldChain = firstChild())
- delete oldChain;
- m_sceneGraphNodes.clear();
- nodeHandler.reset(new DelegatedNodeTreeCreator(&m_sceneGraphNodes, apiDelegate));
- } else {
- // Save the texture strong refs so they only go out of scope when the method returns and
- // the new vector of texture strong refs has been filled.
- qSwap(m_sgObjects.textureStrongRefs, textureStrongRefs);
- nodeHandler.reset(new DelegatedNodeTreeUpdater(&m_sceneGraphNodes));
- }
- // The RenderPasses list is actually a tree where a parent RenderPass is connected
- // to its dependencies through a RenderPassId reference in one or more RenderPassQuads.
- // The list is already ordered with intermediate RenderPasses placed before their
- // parent, with the last one in the list being the root RenderPass, the one
- // that we displayed to the user.
- // All RenderPasses except the last one are rendered to an FBO.
- viz::RenderPass *rootRenderPass = frameData->render_pass_list.back().get();
-
- gfx::Rect viewportRect(toGfx(viewportSize));
- for (unsigned i = 0; i < frameData->render_pass_list.size(); ++i) {
- viz::RenderPass *pass = frameData->render_pass_list.at(i).get();
-
- QSGNode *renderPassParent = 0;
- gfx::Rect scissorRect;
- if (pass != rootRenderPass) {
- QSharedPointer<QSGLayer> rpLayer;
- if (buildNewTree) {
- rpLayer = findRenderPassLayer(pass->id, previousSGObjects.renderPassLayers);
- if (!rpLayer) {
- rpLayer = QSharedPointer<QSGLayer>(apiDelegate->createLayer());
- // Avoid any premature texture update since we need to wait
- // for the GPU thread to produce the dependent resources first.
- rpLayer->setLive(false);
- }
- QSharedPointer<QSGRootNode> rootNode(new QSGRootNode);
- rpLayer->setItem(rootNode.data());
- m_sgObjects.renderPassLayers.append(QPair<int,
- QSharedPointer<QSGLayer> >(pass->id, rpLayer));
- m_sgObjects.renderPassRootNodes.append(rootNode);
- renderPassParent = rootNode.data();
- } else
- rpLayer = findRenderPassLayer(pass->id, m_sgObjects.renderPassLayers);
-
- rpLayer->setRect(toQt(pass->output_rect));
- rpLayer->setSize(toQt(pass->output_rect.size()));
- rpLayer->setFormat(pass->has_transparent_background ? GL_RGBA : GL_RGB);
- rpLayer->setHasMipmaps(pass->generate_mipmap);
- rpLayer->setMirrorVertical(true);
- scissorRect = pass->output_rect;
- } else {
- renderPassParent = this;
- scissorRect = viewportRect;
- scissorRect += rootRenderPass->output_rect.OffsetFromOrigin();
- }
-
- if (scissorRect.IsEmpty()) {
- holdResources(pass, resourceCandidates);
- continue;
- }
-
- QSGNode *renderPassChain = nullptr;
- if (buildNewTree)
- renderPassChain = buildRenderPassChain(renderPassParent);
-
- base::circular_deque<std::unique_ptr<viz::DrawPolygon>> polygonQueue;
- int nextPolygonId = 0;
- int currentSortingContextId = 0;
- const viz::SharedQuadState *currentLayerState = nullptr;
- QSGNode *currentLayerChain = nullptr;
- const auto quadListBegin = pass->quad_list.BackToFrontBegin();
- const auto quadListEnd = pass->quad_list.BackToFrontEnd();
- for (auto it = quadListBegin; it != quadListEnd; ++it) {
- const viz::DrawQuad *quad = *it;
- const viz::SharedQuadState *quadState = quad->shared_quad_state;
-
- gfx::Rect targetRect =
- cc::MathUtil::MapEnclosingClippedRect(quadState->quad_to_target_transform,
- quad->visible_rect);
- if (quadState->is_clipped)
- targetRect.Intersect(quadState->clip_rect);
- targetRect.Intersect(scissorRect);
- if (targetRect.IsEmpty()) {
- holdResources(quad, resourceCandidates);
- continue;
- }
-
- if (quadState->sorting_context_id != currentSortingContextId) {
- flushPolygons(&polygonQueue, renderPassChain,
- nodeHandler.data(), resourceCandidates, apiDelegate);
- currentSortingContextId = quadState->sorting_context_id;
- }
-
- if (currentSortingContextId != 0) {
- std::unique_ptr<viz::DrawPolygon> polygon(
- new viz::DrawPolygon(
- quad,
- gfx::RectF(quad->visible_rect),
- quadState->quad_to_target_transform,
- nextPolygonId++));
- if (polygon->points().size() > 2u)
- polygonQueue.push_back(std::move(polygon));
- continue;
- }
-
- if (renderPassChain && currentLayerState != quadState) {
- currentLayerState = quadState;
- currentLayerChain = buildLayerChain(renderPassChain, quadState);
- }
-
- handleQuad(quad, currentLayerChain,
- nodeHandler.data(), resourceCandidates, apiDelegate);
- }
- flushPolygons(&polygonQueue, renderPassChain,
- nodeHandler.data(), resourceCandidates, apiDelegate);
- }
- // Send resources of remaining candidates back to the child compositors so that
- // they can be freed or reused.
- typedef QHash<unsigned, QSharedPointer<ResourceHolder> >::const_iterator
- ResourceHolderIterator;
-
- ResourceHolderIterator end = resourceCandidates.constEnd();
- for (ResourceHolderIterator it = resourceCandidates.constBegin(); it != end ; ++it)
- resourcesToRelease->push_back((*it)->returnResource());
-
- m_previousViewportSize = viewportSize;
-}
-
-void DelegatedFrameNode::flushPolygons(
- base::circular_deque<std::unique_ptr<viz::DrawPolygon>> *polygonQueue,
- QSGNode *renderPassChain,
- DelegatedNodeTreeHandler *nodeHandler,
- QHash<unsigned, QSharedPointer<ResourceHolder> > &resourceCandidates,
- RenderWidgetHostViewQtDelegate *apiDelegate)
-{
- if (polygonQueue->empty())
- return;
-
- const auto actionHandler = [&](viz::DrawPolygon *polygon) {
- const viz::DrawQuad *quad = polygon->original_ref();
- const viz::SharedQuadState *quadState = quad->shared_quad_state;
-
- QSGNode *currentLayerChain = nullptr;
- if (renderPassChain)
- currentLayerChain = buildLayerChain(renderPassChain, quad->shared_quad_state);
-
- gfx::Transform inverseTransform;
- bool invertible = quadState->quad_to_target_transform.GetInverse(&inverseTransform);
- DCHECK(invertible);
- polygon->TransformToLayerSpace(inverseTransform);
-
- handlePolygon(polygon, currentLayerChain,
- nodeHandler, resourceCandidates, apiDelegate);
- };
-
- viz::BspTree(polygonQueue).TraverseWithActionHandler(&actionHandler);
-}
-
-void DelegatedFrameNode::handlePolygon(
- const viz::DrawPolygon *polygon,
- QSGNode *currentLayerChain,
- DelegatedNodeTreeHandler *nodeHandler,
- QHash<unsigned, QSharedPointer<ResourceHolder> > &resourceCandidates,
- RenderWidgetHostViewQtDelegate *apiDelegate)
-{
- const viz::DrawQuad *quad = polygon->original_ref();
-
- if (!polygon->is_split()) {
- handleQuad(quad, currentLayerChain,
- nodeHandler, resourceCandidates, apiDelegate);
- } else {
- std::vector<gfx::QuadF> clipRegionList;
- polygon->ToQuads2D(&clipRegionList);
- for (const auto & clipRegion : clipRegionList)
- handleClippedQuad(quad, clipRegion, currentLayerChain,
- nodeHandler, resourceCandidates, apiDelegate);
- }
-}
-
-void DelegatedFrameNode::handleClippedQuad(
- const viz::DrawQuad *quad,
- const gfx::QuadF &clipRegion,
- QSGNode *currentLayerChain,
- DelegatedNodeTreeHandler *nodeHandler,
- QHash<unsigned, QSharedPointer<ResourceHolder> > &resourceCandidates,
- RenderWidgetHostViewQtDelegate *apiDelegate)
-{
- if (currentLayerChain) {
- auto clipGeometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 4);
- auto clipGeometryVertices = clipGeometry->vertexDataAsPoint2D();
- clipGeometryVertices[0].set(clipRegion.p1().x(), clipRegion.p1().y());
- clipGeometryVertices[1].set(clipRegion.p2().x(), clipRegion.p2().y());
- clipGeometryVertices[2].set(clipRegion.p4().x(), clipRegion.p4().y());
- clipGeometryVertices[3].set(clipRegion.p3().x(), clipRegion.p3().y());
- auto clipNode = new QSGClipNode;
- clipNode->setGeometry(clipGeometry);
- clipNode->setIsRectangular(false);
- clipNode->setFlag(QSGNode::OwnsGeometry);
- currentLayerChain->appendChildNode(clipNode);
- currentLayerChain = clipNode;
- }
- handleQuad(quad, currentLayerChain,
- nodeHandler, resourceCandidates, apiDelegate);
-}
-
-void DelegatedFrameNode::handleQuad(
- const viz::DrawQuad *quad,
- QSGNode *currentLayerChain,
- DelegatedNodeTreeHandler *nodeHandler,
- QHash<unsigned, QSharedPointer<ResourceHolder> > &resourceCandidates,
- RenderWidgetHostViewQtDelegate *apiDelegate)
-{
- switch (quad->material) {
- case viz::DrawQuad::RENDER_PASS: {
- const viz::RenderPassDrawQuad *renderPassQuad = viz::RenderPassDrawQuad::MaterialCast(quad);
- if (!renderPassQuad->mask_texture_size.IsEmpty()) {
- ResourceHolder *resource = findAndHoldResource(renderPassQuad->mask_resource_id(), resourceCandidates);
- Q_UNUSED(resource); // FIXME: QTBUG-67652
- }
- QSGLayer *layer =
- findRenderPassLayer(renderPassQuad->render_pass_id, m_sgObjects.renderPassLayers).data();
-
- if (layer)
- nodeHandler->setupRenderPassNode(layer, toQt(quad->rect), toQt(renderPassQuad->tex_coord_rect), currentLayerChain);
-
- break;
- }
- case viz::DrawQuad::TEXTURE_CONTENT: {
- const viz::TextureDrawQuad *tquad = viz::TextureDrawQuad::MaterialCast(quad);
- ResourceHolder *resource = findAndHoldResource(tquad->resource_id(), resourceCandidates);
- QSGTexture *texture =
- initAndHoldTexture(resource, quad->ShouldDrawWithBlending(), apiDelegate);
- QSizeF textureSize;
- if (texture)
- textureSize = texture->textureSize();
- gfx::RectF uv_rect =
- gfx::ScaleRect(gfx::BoundingRect(tquad->uv_top_left, tquad->uv_bottom_right),
- textureSize.width(), textureSize.height());
-
- nodeHandler->setupTextureContentNode(
- texture, toQt(quad->rect), toQt(uv_rect),
- tquad->y_flipped ? QSGImageNode::MirrorVertically : QSGImageNode::NoTransform,
- currentLayerChain);
- break;
- }
- case viz::DrawQuad::SOLID_COLOR: {
- const viz::SolidColorDrawQuad *scquad = viz::SolidColorDrawQuad::MaterialCast(quad);
- // Qt only supports MSAA and this flag shouldn't be needed.
- // If we ever want to use QSGRectangleNode::setAntialiasing for this we should
- // try to see if we can do something similar for tile quads first.
- Q_UNUSED(scquad->force_anti_aliasing_off);
- nodeHandler->setupSolidColorNode(toQt(quad->rect), toQt(scquad->color), currentLayerChain);
- break;
-#ifndef QT_NO_OPENGL
- }
- case viz::DrawQuad::DEBUG_BORDER: {
- const viz::DebugBorderDrawQuad *dbquad = viz::DebugBorderDrawQuad::MaterialCast(quad);
-
- QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 4);
- geometry->setDrawingMode(GL_LINE_LOOP);
- geometry->setLineWidth(dbquad->width);
- // QSGGeometry::updateRectGeometry would actually set the
- // corners in the following order:
- // top-left, bottom-left, top-right, bottom-right, leading to a nice criss cross,
- // instead of having a closed loop.
- const gfx::Rect &r(dbquad->rect);
- geometry->vertexDataAsPoint2D()[0].set(r.x(), r.y());
- geometry->vertexDataAsPoint2D()[1].set(r.x() + r.width(), r.y());
- geometry->vertexDataAsPoint2D()[2].set(r.x() + r.width(), r.y() + r.height());
- geometry->vertexDataAsPoint2D()[3].set(r.x(), r.y() + r.height());
-
- QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
- material->setColor(toQt(dbquad->color));
-
- nodeHandler->setupDebugBorderNode(geometry, material, currentLayerChain);
- break;
-#endif
- }
- case viz::DrawQuad::TILED_CONTENT: {
- const viz::TileDrawQuad *tquad = viz::TileDrawQuad::MaterialCast(quad);
- ResourceHolder *resource = findAndHoldResource(tquad->resource_id(), resourceCandidates);
- nodeHandler->setupTextureContentNode(
- initAndHoldTexture(resource, quad->ShouldDrawWithBlending(), apiDelegate),
- toQt(quad->rect), toQt(tquad->tex_coord_rect),
- QSGImageNode::NoTransform, currentLayerChain);
- break;
-#ifndef QT_NO_OPENGL
- }
- case viz::DrawQuad::YUV_VIDEO_CONTENT: {
- const viz::YUVVideoDrawQuad *vquad = viz::YUVVideoDrawQuad::MaterialCast(quad);
- ResourceHolder *yResource =
- findAndHoldResource(vquad->y_plane_resource_id(), resourceCandidates);
- ResourceHolder *uResource =
- findAndHoldResource(vquad->u_plane_resource_id(), resourceCandidates);
- ResourceHolder *vResource =
- findAndHoldResource(vquad->v_plane_resource_id(), resourceCandidates);
- ResourceHolder *aResource = 0;
- // This currently requires --enable-vp8-alpha-playback and
- // needs a video with alpha data to be triggered.
- if (vquad->a_plane_resource_id())
- aResource = findAndHoldResource(vquad->a_plane_resource_id(), resourceCandidates);
-
- nodeHandler->setupYUVVideoNode(
- initAndHoldTexture(yResource, quad->ShouldDrawWithBlending()),
- initAndHoldTexture(uResource, quad->ShouldDrawWithBlending()),
- initAndHoldTexture(vResource, quad->ShouldDrawWithBlending()),
- aResource ? initAndHoldTexture(aResource, quad->ShouldDrawWithBlending()) : 0,
- toQt(vquad->ya_tex_coord_rect), toQt(vquad->uv_tex_coord_rect),
- toQt(vquad->ya_tex_size), toQt(vquad->uv_tex_size), vquad->video_color_space,
- vquad->resource_multiplier, vquad->resource_offset, toQt(quad->rect),
- currentLayerChain);
- break;
-#ifdef GL_OES_EGL_image_external
- }
- case viz::DrawQuad::STREAM_VIDEO_CONTENT: {
- const viz::StreamVideoDrawQuad *squad = viz::StreamVideoDrawQuad::MaterialCast(quad);
- ResourceHolder *resource = findAndHoldResource(squad->resource_id(), resourceCandidates);
- MailboxTexture *texture = static_cast<MailboxTexture *>(
- initAndHoldTexture(resource, quad->ShouldDrawWithBlending()));
- // since this is not default TEXTURE_2D type
- texture->setTarget(GL_TEXTURE_EXTERNAL_OES);
-
- nodeHandler->setupStreamVideoNode(texture, toQt(squad->rect), toQt(squad->matrix.matrix()),
- currentLayerChain);
- break;
-#endif // GL_OES_EGL_image_external
-#endif // QT_NO_OPENGL
- }
- case viz::DrawQuad::SURFACE_CONTENT:
- Q_UNREACHABLE();
- default:
- qWarning("Unimplemented quad material: %d", quad->material);
- }
-}
-
-ResourceHolder *DelegatedFrameNode::findAndHoldResource(unsigned resourceId, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates)
-{
- // ResourceHolders must survive when the scene graph destroys our node branch
- QSharedPointer<ResourceHolder> &resource = m_chromiumCompositorData->resourceHolders[resourceId];
- if (!resource)
- resource = candidates.take(resourceId);
- Q_ASSERT(resource);
- return resource.data();
-}
-
-void DelegatedFrameNode::holdResources(const viz::DrawQuad *quad, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates)
-{
- for (auto resource : quad->resources)
- findAndHoldResource(resource, candidates);
-}
-
-void DelegatedFrameNode::holdResources(const viz::RenderPass *pass, QHash<unsigned, QSharedPointer<ResourceHolder> > &candidates)
-{
- for (const auto &quad : pass->quad_list)
- holdResources(quad, candidates);
-}
-
-QSGTexture *DelegatedFrameNode::initAndHoldTexture(ResourceHolder *resource, bool quadIsAllOpaque, RenderWidgetHostViewQtDelegate *apiDelegate)
-{
- // QSGTextures must be destroyed in the scene graph thread as part of the QSGNode tree,
- // so we can't store them with the ResourceHolder in m_chromiumCompositorData.
- // Hold them through a QSharedPointer solely on the root DelegatedFrameNode of the web view
- // and access them through a QWeakPointer from the resource holder to find them later.
- m_sgObjects.textureStrongRefs.append(resource->initTexture(quadIsAllOpaque, apiDelegate));
- return m_sgObjects.textureStrongRefs.last().data();
-}
-
-void DelegatedFrameNode::fetchAndSyncMailboxes(QList<MailboxTexture *> &mailboxesToFetch)
-{
-#ifndef QT_NO_OPENGL
- QList<gl::TransferableFence> transferredFences;
- {
- QMutexLocker lock(&m_mutex);
- QVector<MailboxTexture *> mailboxesToPull;
- mailboxesToPull.reserve(mailboxesToFetch.size());
-
- gpu::SyncPointManager *syncPointManager = sync_point_manager();
- scoped_refptr<base::SingleThreadTaskRunner> gpuTaskRunner = gpu_task_runner();
- Q_ASSERT(m_numPendingSyncPoints == 0);
- m_numPendingSyncPoints = mailboxesToFetch.count();
- for (MailboxTexture *mailboxTexture : qAsConst(mailboxesToFetch)) {
- gpu::SyncToken &syncToken = mailboxTexture->mailboxHolder().sync_token;
- const auto task = base::Bind(&DelegatedFrameNode::pullTexture, this, mailboxTexture);
- if (!syncPointManager->WaitOutOfOrder(syncToken, std::move(task)))
- mailboxesToPull.append(mailboxTexture);
- }
- if (!mailboxesToPull.isEmpty()) {
- auto task = base::BindOnce(&DelegatedFrameNode::pullTextures, this, std::move(mailboxesToPull));
- gpuTaskRunner->PostTask(FROM_HERE, std::move(task));
- }
-
- m_mailboxesFetchedWaitCond.wait(&m_mutex);
- m_textureFences.swap(transferredFences);
- }
-
- for (gl::TransferableFence sync : qAsConst(transferredFences)) {
- // We need to wait on the fences on the Qt current context, and
- // can therefore not use GLFence routines that uses a different
- // concept of current context.
- waitChromiumSync(&sync);
- deleteChromiumSync(&sync);
- }
-
-#if defined(USE_OZONE) && !defined(QT_NO_OPENGL)
- // Workaround when context is not shared QTBUG-48969
- // Make slow copy between two contexts.
- if (!m_contextShared) {
- QOpenGLContext *currentContext = QOpenGLContext::currentContext() ;
- QOpenGLContext *sharedContext = qt_gl_global_share_context();
-
- QSurface *surface = currentContext->surface();
- Q_ASSERT(m_offsurface);
- sharedContext->makeCurrent(m_offsurface.data());
- QOpenGLFunctions *funcs = sharedContext->functions();
-
- GLuint fbo = 0;
- funcs->glGenFramebuffers(1, &fbo);
-
- for (MailboxTexture *mailboxTexture : qAsConst(mailboxesToFetch)) {
- // Read texture into QImage from shared context.
- // Switch to shared context.
- sharedContext->makeCurrent(m_offsurface.data());
- funcs = sharedContext->functions();
- QImage img(mailboxTexture->textureSize(), QImage::Format_RGBA8888_Premultiplied);
- funcs->glBindFramebuffer(GL_FRAMEBUFFER, fbo);
- funcs->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mailboxTexture->m_textureId, 0);
- GLenum status = funcs->glCheckFramebufferStatus(GL_FRAMEBUFFER);
- if (status != GL_FRAMEBUFFER_COMPLETE) {
- qWarning("fbo error, skipping slow copy...");
- continue;
- }
- funcs->glReadPixels(0, 0, mailboxTexture->textureSize().width(), mailboxTexture->textureSize().height(),
- GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
-
- // Restore current context.
- // Create texture from QImage in current context.
- currentContext->makeCurrent(surface);
- GLuint texture = 0;
- funcs = currentContext->functions();
- funcs->glGenTextures(1, &texture);
- funcs->glBindTexture(GL_TEXTURE_2D, texture);
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mailboxTexture->textureSize().width(), mailboxTexture->textureSize().height(), 0,
- GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
- mailboxTexture->m_textureId = texture;
- mailboxTexture->m_ownsTexture = true;
- }
- // Cleanup allocated resources
- sharedContext->makeCurrent(m_offsurface.data());
- funcs = sharedContext->functions();
- funcs->glBindFramebuffer(GL_FRAMEBUFFER, 0);
- funcs->glDeleteFramebuffers(1, &fbo);
- currentContext->makeCurrent(surface);
- }
-#endif
-#else
- Q_UNUSED(mailboxesToFetch)
-#endif //QT_NO_OPENGL
-}
-
-
-void DelegatedFrameNode::pullTextures(DelegatedFrameNode *frameNode, const QVector<MailboxTexture *> textures)
-{
-#ifndef QT_NO_OPENGL
- gpu::MailboxManager *mailboxManager = mailbox_manager();
- for (MailboxTexture *texture : textures) {
- gpu::SyncToken &syncToken = texture->mailboxHolder().sync_token;
- if (syncToken.HasData())
- mailboxManager->PullTextureUpdates(syncToken);
- texture->fetchTexture(mailboxManager);
- --frameNode->m_numPendingSyncPoints;
- }
-
- fenceAndUnlockQt(frameNode);
-#else
- Q_UNUSED(frameNode)
- Q_UNUSED(textures)
-#endif
-}
-
-void DelegatedFrameNode::pullTexture(DelegatedFrameNode *frameNode, MailboxTexture *texture)
-{
-#ifndef QT_NO_OPENGL
- gpu::MailboxManager *mailboxManager = mailbox_manager();
- gpu::SyncToken &syncToken = texture->mailboxHolder().sync_token;
- if (syncToken.HasData())
- mailboxManager->PullTextureUpdates(syncToken);
- texture->fetchTexture(mailboxManager);
- --frameNode->m_numPendingSyncPoints;
-
- fenceAndUnlockQt(frameNode);
-#else
- Q_UNUSED(frameNode)
- Q_UNUSED(texture)
-#endif
-}
-
-void DelegatedFrameNode::fenceAndUnlockQt(DelegatedFrameNode *frameNode)
-{
-#ifndef QT_NO_OPENGL
- if (!!gl::GLContext::GetCurrent() && gl::GLFence::IsSupported()) {
- // Create a fence on the Chromium GPU-thread and context
- std::unique_ptr<gl::GLFence> fence = gl::GLFence::Create();
- // But transfer it to something generic since we need to read it using Qt's OpenGL.
- frameNode->m_textureFences.append(fence->Transfer());
- }
- if (frameNode->m_numPendingSyncPoints == 0)
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::Bind(&DelegatedFrameNode::unlockQt, frameNode));
-#else
- Q_UNUSED(frameNode)
-#endif
-}
-
-void DelegatedFrameNode::unlockQt(DelegatedFrameNode *frameNode)
-{
- QMutexLocker lock(&frameNode->m_mutex);
- // Signal preprocess() the textures are ready
- frameNode->m_mailboxesFetchedWaitCond.wakeOne();
-}
-
-} // namespace QtWebEngineCore