summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJocelyn Turcotte <jocelyn.turcotte@digia.com>2013-10-31 13:59:44 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-11-06 17:34:12 +0100
commitfbf3e79512358a3eb1e6589b10ac01917b2e94d0 (patch)
tree37de83061cf9f7c7d7f4f42edf26dde2f05b3ab8
parenta99fdc02797ece15253ff863102d3257945abfab (diff)
Move DelegatedFrameNode and the SG logic to its own file.
This avoids polluting render_widget_host_view_qt_delegate.cpp Change-Id: I06af66f01f842e105bbded75b01f9c8346fd5df9 Reviewed-by: Zeno Albisser <zeno.albisser@digia.com>
-rw-r--r--lib/delegated_frame_node.cpp366
-rw-r--r--lib/delegated_frame_node.h76
-rw-r--r--lib/lib.pro2
-rw-r--r--lib/render_widget_host_view_qt_delegate.cpp318
-rw-r--r--lib/render_widget_host_view_qt_delegate.h9
5 files changed, 447 insertions, 324 deletions
diff --git a/lib/delegated_frame_node.cpp b/lib/delegated_frame_node.cpp
new file mode 100644
index 000000000..dea9605be
--- /dev/null
+++ b/lib/delegated_frame_node.cpp
@@ -0,0 +1,366 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "delegated_frame_node.h"
+
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
+
+// 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 "type_conversion.h"
+
+#include "cc/output/delegated_frame_data.h"
+#include "cc/quads/draw_quad.h"
+#include "cc/quads/render_pass_draw_quad.h"
+#include "cc/quads/texture_draw_quad.h"
+#include "cc/quads/tile_draw_quad.h"
+#include <QOpenGLFramebufferObject>
+#include <QSGSimpleTextureNode>
+#include <QSGTexture>
+#include <QtQuick/private/qquickclipnode_p.h>
+#include <QtQuick/private/qquickwindow_p.h>
+#include <QtQuick/private/qsgcontext_p.h>
+#include <QtQuick/private/qsgrenderer_p.h>
+
+class RenderPassTexture : public QSGTexture
+{
+public:
+ RenderPassTexture(const cc::RenderPass::Id &id, QSGRenderContext *context);
+
+ const cc::RenderPass::Id &id() const { return m_id; }
+ void bind();
+
+ int textureId() const { return m_fbo ? m_fbo->texture() : 0; }
+ QSize textureSize() const { return m_rect.size(); }
+ bool hasAlphaChannel() const { return m_format != GL_RGB; }
+ bool hasMipmaps() const { return false; }
+
+ void setRect(const QRect &rect) { m_rect = rect; }
+ void setFormat(GLenum format) { m_format = format; }
+ void setDevicePixelRatio(qreal ratio) { m_device_pixel_ratio = ratio; }
+ QSGNode *rootNode() { return m_rootNode.data(); }
+
+ void grab();
+
+private:
+ cc::RenderPass::Id m_id;
+ QRect m_rect;
+ qreal m_device_pixel_ratio;
+ GLenum m_format;
+
+ QScopedPointer<QSGRootNode> m_rootNode;
+ QScopedPointer<QSGRenderer> m_renderer;
+ QScopedPointer<QOpenGLFramebufferObject> m_fbo;
+
+ QSGRenderContext *m_context;
+};
+
+class RawTextureNode : public QSGSimpleTextureNode {
+public:
+ RawTextureNode(GLuint textureId, const QSize &textureSize, bool hasAlpha, QQuickWindow *window);
+
+private:
+ QScopedPointer<QSGTexture> m_texture;
+};
+
+
+static inline QSharedPointer<RenderPassTexture> findRenderPassTexture(const cc::RenderPass::Id &id, const QList<QSharedPointer<RenderPassTexture> > &list)
+{
+ Q_FOREACH (const QSharedPointer<RenderPassTexture> &texture, list)
+ if (texture->id() == id)
+ return texture;
+ return QSharedPointer<RenderPassTexture>();
+}
+
+static QSGNode *buildRenderPassChain(QSGNode *chainParent, const cc::RenderPass *renderPass)
+{
+ // 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 finds the z-span of all layers so that we can z-compress them to fit
+ // them between 0.0 and 1.0 on the z axis.
+ double minZ = 0;
+ double maxZ = 1;
+ double src2[8];
+ double dst4[16];
+ // topleft.x, topleft.y, topRight.y and bottomLeft.x
+ src2[0] = src2[1] = src2[3] = src2[4] = 0;
+
+ // Go through each layer in this pass and find out their transformed rect.
+ cc::SharedQuadStateList::const_iterator it = renderPass->shared_quad_state_list.begin();
+ cc::SharedQuadStateList::const_iterator sharedStateEnd = renderPass->shared_quad_state_list.end();
+ for (; it != sharedStateEnd; ++it) {
+ gfx::Size &layerSize = (*it)->content_bounds;
+ // topRight.x
+ src2[2] = layerSize.width();
+ // bottomLeft.y
+ src2[5] = layerSize.height();
+ // bottomRight
+ src2[6] = layerSize.width();
+ src2[7] = layerSize.height();
+ (*it)->content_to_target_transform.matrix().map2(src2, 4, dst4);
+ // Check the mapped corner's z value and track the boundaries.
+ minZ = std::min(std::min(std::min(std::min(minZ, dst4[2]), dst4[6]), dst4[10]), dst4[14]);
+ maxZ = std::max(std::max(std::max(std::max(maxZ, dst4[2]), dst4[6]), dst4[10]), dst4[14]);
+ }
+
+ QSGTransformNode *zCompressNode = new QSGTransformNode;
+ QMatrix4x4 zCompressMatrix;
+ zCompressMatrix.scale(1, 1, 1 / (maxZ - minZ));
+ zCompressMatrix.translate(0, 0, -minZ);
+ zCompressNode->setMatrix(zCompressMatrix);
+ chainParent->appendChildNode(zCompressNode);
+ return zCompressNode;
+}
+
+static QSGNode *buildLayerChain(QSGNode *chainParent, const cc::SharedQuadState *layerState)
+{
+ QSGNode *layerChain = chainParent;
+ if (layerState->is_clipped) {
+ QQuickDefaultClipNode *clipNode = new QQuickDefaultClipNode(toQt(layerState->clip_rect));
+ clipNode->update();
+ layerChain->appendChildNode(clipNode);
+ layerChain = clipNode;
+ }
+ if (!layerState->content_to_target_transform.IsIdentity()) {
+ QSGTransformNode *transformNode = new QSGTransformNode;
+ transformNode->setMatrix(toQt(layerState->content_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;
+}
+
+
+RenderPassTexture::RenderPassTexture(const cc::RenderPass::Id &id, QSGRenderContext *context)
+ : QSGTexture()
+ , m_id(id)
+ , m_device_pixel_ratio(1)
+ , m_format(GL_RGBA)
+ , m_rootNode(new QSGRootNode)
+ , m_context(context)
+{
+}
+
+void RenderPassTexture::bind()
+{
+ glBindTexture(GL_TEXTURE_2D, m_fbo ? m_fbo->texture() : 0);
+ updateBindOptions();
+}
+
+void RenderPassTexture::grab()
+{
+ if (!m_rootNode->firstChild()) {
+ m_renderer.reset();
+ m_fbo.reset();
+ return;
+ }
+ if (!m_renderer) {
+ m_renderer.reset(m_context->createRenderer());
+ m_renderer->setRootNode(m_rootNode.data());
+ }
+ m_renderer->setDevicePixelRatio(m_device_pixel_ratio);
+
+ if (!m_fbo || m_fbo->size() != m_rect.size() || m_fbo->format().internalTextureFormat() != m_format)
+ {
+ QOpenGLFramebufferObjectFormat format;
+ format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
+ format.setInternalTextureFormat(m_format);
+
+ m_fbo.reset(new QOpenGLFramebufferObject(m_rect.size(), format));
+ glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
+ updateBindOptions(true);
+ }
+
+ m_rootNode->markDirty(QSGNode::DirtyForceUpdate); // Force matrix, clip and opacity update.
+ m_renderer->nodeChanged(m_rootNode.data(), QSGNode::DirtyForceUpdate); // Force render list update.
+
+ m_renderer->setDeviceRect(m_rect.size());
+ m_renderer->setViewportRect(m_rect.size());
+ QRectF mirrored(m_rect.left(), m_rect.bottom(), m_rect.width(), -m_rect.height());
+ m_renderer->setProjectionMatrixToRect(mirrored);
+ m_renderer->setClearColor(Qt::transparent);
+
+ m_context->renderNextFrame(m_renderer.data(), m_fbo->handle());
+}
+
+RawTextureNode::RawTextureNode(GLuint textureId, const QSize &textureSize, bool hasAlpha, QQuickWindow *window)
+ : m_texture(window->createTextureFromId(textureId, textureSize, QQuickWindow::CreateTextureOption(hasAlpha ? QQuickWindow::TextureHasAlphaChannel : 0)))
+{
+ setTexture(m_texture.data());
+}
+
+DelegatedFrameNode::DelegatedFrameNode(QQuickWindow *window)
+ : m_window(window)
+ , m_testTexturesSize(sizeof(m_testTextures) / sizeof(GLuint))
+{
+ setFlag(UsePreprocess);
+
+ // Generate plain color textures to be used until we can use the real textures from the ResourceProvider.
+ glGenTextures(m_testTexturesSize, m_testTextures);
+ for (unsigned i = 0; i < m_testTexturesSize; ++i) {
+ QImage image(1, 1, QImage::Format_ARGB32_Premultiplied);
+ image.fill(static_cast<Qt::GlobalColor>(i + Qt::red));
+
+ // Swizzle
+ const int width = image.width();
+ const int height = image.height();
+ for (int j = 0; j < height; ++j) {
+ uint *p = (uint *) image.scanLine(j);
+ for (int x = 0; x < width; ++x)
+ p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
+ }
+
+ glBindTexture(GL_TEXTURE_2D, m_testTextures[i]);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.constBits() );
+ }
+}
+
+DelegatedFrameNode::~DelegatedFrameNode()
+{
+ glDeleteTextures(m_testTexturesSize, m_testTextures);
+}
+
+void DelegatedFrameNode::preprocess()
+{
+ // Render any intermediate RenderPass in order.
+ Q_FOREACH (const QSharedPointer<RenderPassTexture> &texture, m_renderPassTextures)
+ texture->grab();
+}
+
+void DelegatedFrameNode::commit(cc::DelegatedFrameData *frameData)
+{
+ // Keep the old list around to find the ones we can re-use.
+ QList<QSharedPointer<RenderPassTexture> > oldRenderPassTextures;
+ m_renderPassTextures.swap(oldRenderPassTextures);
+
+ // The RenderPasses list is actually a tree where a parent RenderPass is connected
+ // to its dependencies through a RenderPass::Id 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.
+ cc::RenderPass *rootRenderPass = frameData->render_pass_list.back();
+
+ for (unsigned i = 0; i < frameData->render_pass_list.size(); ++i) {
+ cc::RenderPass *pass = frameData->render_pass_list.at(i);
+
+ QSGNode *renderPassParent = 0;
+ if (pass != rootRenderPass) {
+ QSharedPointer<RenderPassTexture> rpTexture = findRenderPassTexture(pass->id, oldRenderPassTextures);
+ if (!rpTexture) {
+ QSGRenderContext *sgrc = QQuickWindowPrivate::get(m_window)->context;
+ rpTexture = QSharedPointer<RenderPassTexture>(new RenderPassTexture(pass->id, sgrc));
+ }
+ m_renderPassTextures.append(rpTexture);
+ rpTexture->setDevicePixelRatio(m_window->devicePixelRatio());
+ rpTexture->setRect(toQt(pass->output_rect));
+ rpTexture->setFormat(pass->has_transparent_background ? GL_RGBA : GL_RGB);
+ renderPassParent = rpTexture->rootNode();
+ } else
+ renderPassParent = this;
+
+ // There is currently no way to know which and how quads changed since the last frame.
+ // We have to reconstruct the node chain with their geometries on every update.
+ while (QSGNode *oldChain = renderPassParent->firstChild())
+ delete oldChain;
+
+ QSGNode *renderPassChain = buildRenderPassChain(renderPassParent, pass);
+ const cc::SharedQuadState *currentLayerState = 0;
+ QSGNode *currentLayerChain = 0;
+
+ cc::QuadList::ConstBackToFrontIterator it = pass->quad_list.BackToFrontBegin();
+ cc::QuadList::ConstBackToFrontIterator end = pass->quad_list.BackToFrontEnd();
+ for (; it != end; ++it) {
+ cc::DrawQuad *quad = *it;
+
+ if (currentLayerState != quad->shared_quad_state) {
+ currentLayerState = quad->shared_quad_state;
+ currentLayerChain = buildLayerChain(renderPassChain, currentLayerState);
+ }
+
+ QSGSimpleTextureNode *textureNode = 0;
+ switch (quad->material) {
+ case cc::DrawQuad::RENDER_PASS: {
+ const cc::RenderPassDrawQuad *renderPassQuad = cc::RenderPassDrawQuad::MaterialCast(quad);
+ QSGTexture *texture = findRenderPassTexture(renderPassQuad->render_pass_id, m_renderPassTextures).data();
+ if (texture) {
+ textureNode = new QSGSimpleTextureNode;
+ textureNode->setTexture(texture);
+ } else {
+ qWarning("Unknown RenderPass layer: Id %d", renderPassQuad->render_pass_id.layer_id);
+ textureNode = new RawTextureNode(0, QSize(1, 1), false, m_window);
+ }
+ break;
+ } case cc::DrawQuad::TEXTURE_CONTENT: {
+ uint32 resourceId = cc::TextureDrawQuad::MaterialCast(quad)->resource_id;
+ textureNode = new RawTextureNode(m_testTextures[resourceId % m_testTexturesSize], QSize(1, 1), false, m_window);
+ break;
+ } case cc::DrawQuad::TILED_CONTENT: {
+ uint32 resourceId = cc::TileDrawQuad::MaterialCast(quad)->resource_id;
+ textureNode = new RawTextureNode(m_testTextures[resourceId % m_testTexturesSize], QSize(1, 1), false, m_window);
+ break;
+ } default:
+ qWarning("Unimplemented quad material: %d", quad->material);
+ textureNode = new RawTextureNode(0, QSize(1, 1), false, m_window);
+ }
+
+ textureNode->setRect(toQt(quad->rect));
+ textureNode->setFiltering(QSGTexture::Linear);
+ currentLayerChain->appendChildNode(textureNode);
+ }
+ }
+}
+
+#endif // QT_VERSION
diff --git a/lib/delegated_frame_node.h b/lib/delegated_frame_node.h
new file mode 100644
index 000000000..9eb9b5c48
--- /dev/null
+++ b/lib/delegated_frame_node.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef DELEGATED_FRAME_NODE_H
+#define DELEGATED_FRAME_NODE_H
+
+#include <QSGNode>
+#include <QSharedPointer>
+
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
+
+QT_BEGIN_NAMESPACE
+class QQuickWindow;
+QT_END_NAMESPACE
+
+namespace cc {
+class DelegatedFrameData;
+}
+
+class RenderPassTexture;
+
+class DelegatedFrameNode : public QSGNode {
+public:
+ DelegatedFrameNode(QQuickWindow *window);
+ ~DelegatedFrameNode();
+ void preprocess();
+ void commit(cc::DelegatedFrameData *frameData);
+
+private:
+ QQuickWindow *m_window;
+ QList<QSharedPointer<RenderPassTexture> > m_renderPassTextures;
+ const size_t m_testTexturesSize;
+ GLuint m_testTextures[Qt::transparent - Qt::red];
+};
+
+#endif // QT_VERSION
+
+#endif // DELEGATED_FRAME_NODE_H
diff --git a/lib/lib.pro b/lib/lib.pro
index a0f4116fe..d6a546597 100644
--- a/lib/lib.pro
+++ b/lib/lib.pro
@@ -37,6 +37,7 @@ SOURCES = \
backing_store_qt.cpp \
content_client_qt.cpp \
content_browser_client_qt.cpp \
+ delegated_frame_node.cpp \
dev_tools_http_handler_delegate_qt.cpp \
download_manager_delegate_qt.cpp \
javascript_dialog_manager_qt.cpp \
@@ -55,6 +56,7 @@ HEADERS = \
browser_context_qt.h \
content_client_qt.h \
content_browser_client_qt.h \
+ delegated_frame_node.h \
dev_tools_http_handler_delegate_qt.h \
download_manager_delegate_qt.h \
javascript_dialog_manager_qt.h \
diff --git a/lib/render_widget_host_view_qt_delegate.cpp b/lib/render_widget_host_view_qt_delegate.cpp
index 8916193cf..25a9e69b0 100644
--- a/lib/render_widget_host_view_qt_delegate.cpp
+++ b/lib/render_widget_host_view_qt_delegate.cpp
@@ -42,6 +42,7 @@
#include "render_widget_host_view_qt_delegate.h"
#include "backing_store_qt.h"
+#include "delegated_frame_node.h"
#include "render_widget_host_view_qt.h"
#include "type_conversion.h"
@@ -49,240 +50,6 @@
#include <QVariant>
-#if (QT_VERSION >= QT_VERSION_CHECK(5, 2, 0))
-#include "cc/quads/draw_quad.h"
-#include "cc/quads/render_pass_draw_quad.h"
-#include "cc/quads/texture_draw_quad.h"
-#include "cc/quads/tile_draw_quad.h"
-#include <QSGNode>
-#include <QSGSimpleTextureNode>
-#include <QSGTexture>
-#include <QtQuick/private/qquickclipnode_p.h>
-#include <QtQuick/private/qquickwindow_p.h>
-#include <QtQuick/private/qsgcontext_p.h>
-#include <QtQuick/private/qsgrenderer_p.h>
-
-class RenderPassTexture : public QSGTexture
-{
-public:
- RenderPassTexture(const cc::RenderPass::Id &id, QSGRenderContext *context);
-
- const cc::RenderPass::Id &id() const { return m_id; }
- void bind();
-
- int textureId() const { return m_fbo ? m_fbo->texture() : 0; }
- QSize textureSize() const { return m_rect.size(); }
- bool hasAlphaChannel() const { return m_format != GL_RGB; }
- bool hasMipmaps() const { return false; }
-
- void setRect(const QRect &rect) { m_rect = rect; }
- void setFormat(GLenum format) { m_format = format; }
- void setDevicePixelRatio(qreal ratio) { m_device_pixel_ratio = ratio; }
- QSGNode *rootNode() { return m_rootNode.data(); }
-
- void grab();
-
-private:
- cc::RenderPass::Id m_id;
- QRect m_rect;
- qreal m_device_pixel_ratio;
- GLenum m_format;
-
- QScopedPointer<QSGRootNode> m_rootNode;
- QScopedPointer<QSGRenderer> m_renderer;
- QScopedPointer<QOpenGLFramebufferObject> m_fbo;
-
- QSGRenderContext *m_context;
-};
-
-RenderPassTexture::RenderPassTexture(const cc::RenderPass::Id &id, QSGRenderContext *context)
- : QSGTexture()
- , m_id(id)
- , m_device_pixel_ratio(1)
- , m_format(GL_RGBA)
- , m_rootNode(new QSGRootNode)
- , m_context(context)
-{
-}
-
-void RenderPassTexture::bind()
-{
- glBindTexture(GL_TEXTURE_2D, m_fbo ? m_fbo->texture() : 0);
- updateBindOptions();
-}
-
-void RenderPassTexture::grab()
-{
- if (!m_rootNode->firstChild()) {
- m_renderer.reset();
- m_fbo.reset();
- return;
- }
- if (!m_renderer) {
- m_renderer.reset(m_context->createRenderer());
- m_renderer->setRootNode(m_rootNode.data());
- }
- m_renderer->setDevicePixelRatio(m_device_pixel_ratio);
-
- if (!m_fbo || m_fbo->size() != m_rect.size() || m_fbo->format().internalTextureFormat() != m_format)
- {
- QOpenGLFramebufferObjectFormat format;
- format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
- format.setInternalTextureFormat(m_format);
-
- m_fbo.reset(new QOpenGLFramebufferObject(m_rect.size(), format));
- glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
- updateBindOptions(true);
- }
-
- m_rootNode->markDirty(QSGNode::DirtyForceUpdate); // Force matrix, clip and opacity update.
- m_renderer->nodeChanged(m_rootNode.data(), QSGNode::DirtyForceUpdate); // Force render list update.
-
- m_renderer->setDeviceRect(m_rect.size());
- m_renderer->setViewportRect(m_rect.size());
- QRectF mirrored(m_rect.left(), m_rect.bottom(), m_rect.width(), -m_rect.height());
- m_renderer->setProjectionMatrixToRect(mirrored);
- m_renderer->setClearColor(Qt::transparent);
-
- m_context->renderNextFrame(m_renderer.data(), m_fbo->handle());
-}
-
-class RawTextureNode : public QSGSimpleTextureNode {
-public:
- RawTextureNode(GLuint textureId, const QSize &textureSize, bool hasAlpha, QQuickWindow *window);
-
-private:
- QScopedPointer<QSGTexture> m_texture;
-};
-
-RawTextureNode::RawTextureNode(GLuint textureId, const QSize &textureSize, bool hasAlpha, QQuickWindow *window)
- : m_texture(window->createTextureFromId(textureId, textureSize, QQuickWindow::CreateTextureOption(hasAlpha ? QQuickWindow::TextureHasAlphaChannel : 0)))
-{
- setTexture(m_texture.data());
-}
-
-class DelegatedFrameNode : public QSGNode {
-public:
- DelegatedFrameNode();
- ~DelegatedFrameNode();
- void preprocess();
- QList<QSharedPointer<RenderPassTexture> > renderPassTextures;
-
- const size_t testTexturesSize;
- GLuint testTextures[Qt::transparent - Qt::red];
-};
-
-DelegatedFrameNode::DelegatedFrameNode()
- : testTexturesSize(sizeof(testTextures) / sizeof(GLuint))
-{
- setFlag(UsePreprocess);
-
- // Generate plain color textures to be used until we can use the real textures from the ResourceProvider.
- glGenTextures(testTexturesSize, testTextures);
- for (unsigned i = 0; i < testTexturesSize; ++i) {
- QImage image(1, 1, QImage::Format_ARGB32_Premultiplied);
- image.fill(static_cast<Qt::GlobalColor>(i + Qt::red));
-
- // Swizzle
- const int width = image.width();
- const int height = image.height();
- for (int j = 0; j < height; ++j) {
- uint *p = (uint *) image.scanLine(j);
- for (int x = 0; x < width; ++x)
- p[x] = ((p[x] << 16) & 0xff0000) | ((p[x] >> 16) & 0xff) | (p[x] & 0xff00ff00);
- }
-
- glBindTexture(GL_TEXTURE_2D, testTextures[i]);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.constBits() );
- }
-}
-
-DelegatedFrameNode::~DelegatedFrameNode()
-{
- glDeleteTextures(testTexturesSize, testTextures);
-}
-
-void DelegatedFrameNode::preprocess()
-{
- // Render any intermediate RenderPass in order.
- Q_FOREACH (const QSharedPointer<RenderPassTexture> &texture, renderPassTextures)
- texture->grab();
-}
-
-static inline QSharedPointer<RenderPassTexture> findRenderPassTexture(const cc::RenderPass::Id &id, const QList<QSharedPointer<RenderPassTexture> > &list)
-{
- Q_FOREACH (const QSharedPointer<RenderPassTexture> &texture, list)
- if (texture->id() == id)
- return texture;
- return QSharedPointer<RenderPassTexture>();
-}
-
-static QSGNode *buildRenderPassChain(QSGNode *chainParent, const cc::RenderPass *renderPass)
-{
- // 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 finds the z-span of all layers so that we can z-compress them to fit
- // them between 0.0 and 1.0 on the z axis.
- double minZ = 0;
- double maxZ = 1;
- double src2[8];
- double dst4[16];
- // topleft.x, topleft.y, topRight.y and bottomLeft.x
- src2[0] = src2[1] = src2[3] = src2[4] = 0;
-
- // Go through each layer in this pass and find out their transformed rect.
- cc::SharedQuadStateList::const_iterator it = renderPass->shared_quad_state_list.begin();
- cc::SharedQuadStateList::const_iterator sharedStateEnd = renderPass->shared_quad_state_list.end();
- for (; it != sharedStateEnd; ++it) {
- gfx::Size &layerSize = (*it)->content_bounds;
- // topRight.x
- src2[2] = layerSize.width();
- // bottomLeft.y
- src2[5] = layerSize.height();
- // bottomRight
- src2[6] = layerSize.width();
- src2[7] = layerSize.height();
- (*it)->content_to_target_transform.matrix().map2(src2, 4, dst4);
- // Check the mapped corner's z value and track the boundaries.
- minZ = std::min(std::min(std::min(std::min(minZ, dst4[2]), dst4[6]), dst4[10]), dst4[14]);
- maxZ = std::max(std::max(std::max(std::max(maxZ, dst4[2]), dst4[6]), dst4[10]), dst4[14]);
- }
-
- QSGTransformNode *zCompressNode = new QSGTransformNode;
- QMatrix4x4 zCompressMatrix;
- zCompressMatrix.scale(1, 1, 1 / (maxZ - minZ));
- zCompressMatrix.translate(0, 0, -minZ);
- zCompressNode->setMatrix(zCompressMatrix);
- chainParent->appendChildNode(zCompressNode);
- return zCompressNode;
-}
-
-static QSGNode *buildLayerChain(QSGNode *chainParent, const cc::SharedQuadState *layerState)
-{
- QSGNode *layerChain = chainParent;
- if (layerState->is_clipped) {
- QQuickDefaultClipNode *clipNode = new QQuickDefaultClipNode(toQt(layerState->clip_rect));
- clipNode->update();
- layerChain->appendChildNode(clipNode);
- layerChain = clipNode;
- }
- if (!layerState->content_to_target_transform.IsIdentity()) {
- QSGTransformNode *transformNode = new QSGTransformNode;
- transformNode->setMatrix(toQt(layerState->content_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;
-}
-#endif // QT_VERSION
-
RenderWidgetHostViewQtDelegate::RenderWidgetHostViewQtDelegate()
: m_view(0), m_backingStore(0)
{
@@ -308,88 +75,9 @@ QSGNode *RenderWidgetHostViewQtDelegate::updatePaintNode(QSGNode *oldNode, QQuic
}
DelegatedFrameNode *frameNode = static_cast<DelegatedFrameNode *>(oldNode);
if (!frameNode)
- frameNode = new DelegatedFrameNode;
-
- // Keep the old list around to find the ones we can re-use.
- QList<QSharedPointer<RenderPassTexture> > oldRenderPassTextures;
- frameNode->renderPassTextures.swap(oldRenderPassTextures);
+ frameNode = new DelegatedFrameNode(window);
- // The RenderPasses list is actually a tree where a parent RenderPass is connected
- // to its dependencies through a RenderPass::Id 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.
- cc::RenderPass *rootRenderPass = frameData->render_pass_list.back();
-
- for (unsigned i = 0; i < frameData->render_pass_list.size(); ++i) {
- cc::RenderPass *pass = frameData->render_pass_list.at(i);
-
- QSGNode *renderPassParent = 0;
- if (pass != rootRenderPass) {
- QSharedPointer<RenderPassTexture> rpTexture = findRenderPassTexture(pass->id, oldRenderPassTextures);
- if (!rpTexture) {
- QSGRenderContext *sgrc = QQuickWindowPrivate::get(window)->context;
- rpTexture = QSharedPointer<RenderPassTexture>(new RenderPassTexture(pass->id, sgrc));
- }
- frameNode->renderPassTextures.append(rpTexture);
- rpTexture->setDevicePixelRatio(window->devicePixelRatio());
- rpTexture->setRect(toQt(pass->output_rect));
- rpTexture->setFormat(pass->has_transparent_background ? GL_RGBA : GL_RGB);
- renderPassParent = rpTexture->rootNode();
- } else
- renderPassParent = frameNode;
-
- // There is currently no way to know which and how quads changed since the last frame.
- // We have to reconstruct the node chain with their geometries on every update.
- while (QSGNode *oldChain = renderPassParent->firstChild())
- delete oldChain;
-
- QSGNode *renderPassChain = buildRenderPassChain(renderPassParent, pass);
- const cc::SharedQuadState *currentLayerState = 0;
- QSGNode *currentLayerChain = 0;
-
- cc::QuadList::ConstBackToFrontIterator it = pass->quad_list.BackToFrontBegin();
- cc::QuadList::ConstBackToFrontIterator end = pass->quad_list.BackToFrontEnd();
- for (; it != end; ++it) {
- cc::DrawQuad *quad = *it;
-
- if (currentLayerState != quad->shared_quad_state) {
- currentLayerState = quad->shared_quad_state;
- currentLayerChain = buildLayerChain(renderPassChain, currentLayerState);
- }
-
- QSGSimpleTextureNode *textureNode = 0;
- switch (quad->material) {
- case cc::DrawQuad::RENDER_PASS: {
- const cc::RenderPassDrawQuad *renderPassQuad = cc::RenderPassDrawQuad::MaterialCast(quad);
- QSGTexture *texture = findRenderPassTexture(renderPassQuad->render_pass_id, frameNode->renderPassTextures).data();
- if (texture) {
- textureNode = new QSGSimpleTextureNode;
- textureNode->setTexture(texture);
- } else {
- qWarning("Unknown RenderPass layer: Id %d", renderPassQuad->render_pass_id.layer_id);
- textureNode = new RawTextureNode(0, QSize(1, 1), false, window);
- }
- break;
- } case cc::DrawQuad::TEXTURE_CONTENT: {
- uint32 resourceId = cc::TextureDrawQuad::MaterialCast(quad)->resource_id;
- textureNode = new RawTextureNode(frameNode->testTextures[resourceId % frameNode->testTexturesSize], QSize(1, 1), false, window);
- break;
- } case cc::DrawQuad::TILED_CONTENT: {
- uint32 resourceId = cc::TileDrawQuad::MaterialCast(quad)->resource_id;
- textureNode = new RawTextureNode(frameNode->testTextures[resourceId % frameNode->testTexturesSize], QSize(1, 1), false, window);
- break;
- } default:
- qWarning("Unimplemented quad material: %d", quad->material);
- textureNode = new RawTextureNode(0, QSize(1, 1), false, window);
- }
-
- textureNode->setRect(toQt(quad->rect));
- textureNode->setFiltering(QSGTexture::Linear);
- currentLayerChain->appendChildNode(textureNode);
- }
- }
+ frameNode->commit(frameData);
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
base::Bind(&RenderWidgetHostViewQt::releaseAndAckDelegatedFrame, m_view->AsWeakPtr()));
diff --git a/lib/render_widget_host_view_qt_delegate.h b/lib/render_widget_host_view_qt_delegate.h
index 36a6ceb9d..3486e3f8d 100644
--- a/lib/render_widget_host_view_qt_delegate.h
+++ b/lib/render_widget_host_view_qt_delegate.h
@@ -42,15 +42,6 @@
#ifndef RENDER_WIDGET_HOST_VIEW_QT_DELEGATE_H
#define RENDER_WIDGET_HOST_VIEW_QT_DELEGATE_H
-// 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 "qtwebengineglobal.h"
#include <QRect>