summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/delegated_frame_node.cpp532
-rw-r--r--src/core/delegated_frame_node.h2
-rw-r--r--src/core/render_widget_host_view_qt.cpp2
3 files changed, 438 insertions, 98 deletions
diff --git a/src/core/delegated_frame_node.cpp b/src/core/delegated_frame_node.cpp
index baf064025..4bc83163f 100644
--- a/src/core/delegated_frame_node.cpp
+++ b/src/core/delegated_frame_node.cpp
@@ -171,6 +171,245 @@ private:
QSGGeometry m_geometry;
};
+class DelegatedNodeTreeHandler
+{
+public:
+ DelegatedNodeTreeHandler(QVector<QSGNode*> *sceneGraphNodes)
+ : m_sceneGraphNodes(sceneGraphNodes)
+ {
+ }
+
+ virtual ~DelegatedNodeTreeHandler(){}
+
+ virtual void setupRenderPassNode(QSGTexture *, const QRect &, QSGNode *) = 0;
+ virtual void setupTextureContentNode(QSGTexture *, const QRect &, QSGTexture::Filtering,
+ QSGTextureNode::TextureCoordinatesTransformMode,
+ QSGNode *) = 0;
+ virtual void setupTiledContentNode(QSGTexture *, const QRect &, const QRectF &,
+ QSGTexture::Filtering, QSGNode *) = 0;
+ virtual void setupSolidColorNode(const QRect &, const QColor &, QSGNode *) = 0;
+ virtual void setupDebugBorderNode(QSGGeometry *, QSGFlatColorMaterial *, QSGNode *) = 0;
+
+#ifndef QT_NO_OPENGL
+ virtual void setupYUVVideoNode(QSGTexture *, QSGTexture *, QSGTexture *, QSGTexture *,
+ const QRectF &, const QRectF &, const QSizeF &, const QSizeF &,
+ YUVVideoMaterial::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, QSGNode *) Q_DECL_OVERRIDE
+ {
+ QSGInternalImageNode *imageNode = static_cast<QSGInternalImageNode*>(*m_nodeIterator++);
+ imageNode->setTargetRect(rect);
+ imageNode->setInnerTargetRect(rect);
+ imageNode->setTexture(layer);
+ imageNode->update();
+ }
+
+ void setupTextureContentNode(QSGTexture *texture, const QRect &rect,
+ QSGTexture::Filtering filtering,
+ QSGTextureNode::TextureCoordinatesTransformMode texCoordTransForm,
+ QSGNode *) Q_DECL_OVERRIDE
+ {
+ QSGTextureNode *textureNode = static_cast<QSGTextureNode*>(*m_nodeIterator++);
+ if (textureNode->texture() != texture)
+ textureNode->setTexture(texture);
+ if (textureNode->textureCoordinatesTransform() != texCoordTransForm)
+ textureNode->setTextureCoordinatesTransform(texCoordTransForm);
+ if (textureNode->rect() != rect)
+ textureNode->setRect(rect);
+ if (textureNode->filtering() != filtering)
+ textureNode->setFiltering(filtering);
+ }
+ void setupTiledContentNode(QSGTexture *texture, const QRect &rect, const QRectF &sourceRect,
+ QSGTexture::Filtering filtering, QSGNode *) Q_DECL_OVERRIDE
+ {
+ QSGTextureNode *textureNode = static_cast<QSGTextureNode*>(*m_nodeIterator++);
+
+ if (textureNode->rect() != rect)
+ textureNode->setRect(rect);
+ if (textureNode->sourceRect() != sourceRect)
+ textureNode->setSourceRect(sourceRect);
+ if (textureNode->filtering() != filtering)
+ textureNode->setFiltering(filtering);
+ if (textureNode->texture() != texture)
+ textureNode->setTexture(texture);
+ }
+ void setupSolidColorNode(const QRect &rect, const QColor &color, QSGNode *) Q_DECL_OVERRIDE
+ {
+ QSGRectangleNode *rectangleNode = static_cast<QSGRectangleNode*>(*m_nodeIterator++);
+
+ if (rectangleNode->rect() != rect)
+ rectangleNode->setRect(rect);
+ if (rectangleNode->color() != color)
+ rectangleNode->setColor(color);
+ }
+
+ void setupDebugBorderNode(QSGGeometry *geometry, QSGFlatColorMaterial *material,
+ QSGNode *) Q_DECL_OVERRIDE
+ {
+ QSGGeometryNode *geometryNode = static_cast<QSGGeometryNode*>(*m_nodeIterator++);
+
+ geometryNode->setGeometry(geometry);
+ geometryNode->setMaterial(material);
+ }
+#ifndef QT_NO_OPENGL
+ void setupYUVVideoNode(QSGTexture *, QSGTexture *, QSGTexture *, QSGTexture *,
+ const QRectF &, const QRectF &, const QSizeF &, const QSizeF &,
+ YUVVideoMaterial::ColorSpace, float, float, const QRectF &,
+ QSGNode *) Q_DECL_OVERRIDE
+ {
+ Q_UNREACHABLE();
+ }
+#ifdef GL_OES_EGL_image_external
+ void setupStreamVideoNode(MailboxTexture *, const QRectF &,
+ const QMatrix4x4 &, QSGNode *) Q_DECL_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,
+ QSGNode *layerChain) Q_DECL_OVERRIDE
+ {
+ // Only QSGInternalImageNode currently supports QSGLayer textures.
+ QSGInternalImageNode *imageNode = m_apiDelegate->createImageNode();
+ imageNode->setTargetRect(rect);
+ imageNode->setInnerTargetRect(rect);
+ imageNode->setTexture(layer);
+ imageNode->update();
+
+ layerChain->appendChildNode(imageNode);
+ m_sceneGraphNodes->append(imageNode);
+ }
+
+ void setupTextureContentNode(QSGTexture *texture, const QRect &rect,
+ QSGTexture::Filtering filtering,
+ QSGTextureNode::TextureCoordinatesTransformMode texCoordTransForm,
+ QSGNode *layerChain) Q_DECL_OVERRIDE
+ {
+ QSGTextureNode *textureNode = m_apiDelegate->createTextureNode();
+ textureNode->setTextureCoordinatesTransform(texCoordTransForm);
+ textureNode->setRect(rect);
+ textureNode->setTexture(texture);
+ textureNode->setFiltering(filtering);
+
+ layerChain->appendChildNode(textureNode);
+ m_sceneGraphNodes->append(textureNode);
+ }
+
+ void setupTiledContentNode(QSGTexture *texture, const QRect &rect, const QRectF &sourceRect,
+ QSGTexture::Filtering filtering,
+ QSGNode *layerChain) Q_DECL_OVERRIDE
+ {
+ QSGTextureNode *textureNode = m_apiDelegate->createTextureNode();
+ textureNode->setRect(rect);
+ textureNode->setSourceRect(sourceRect);
+ textureNode->setFiltering(filtering);
+ textureNode->setTexture(texture);
+
+ layerChain->appendChildNode(textureNode);
+ m_sceneGraphNodes->append(textureNode);
+ }
+
+ void setupSolidColorNode(const QRect &rect, const QColor &color,
+ QSGNode *layerChain) Q_DECL_OVERRIDE
+ {
+ QSGRectangleNode *rectangleNode = m_apiDelegate->createRectangleNode();
+ rectangleNode->setRect(rect);
+ rectangleNode->setColor(color);
+
+ layerChain->appendChildNode(rectangleNode);
+ m_sceneGraphNodes->append(rectangleNode);
+ }
+
+ void setupDebugBorderNode(QSGGeometry *geometry, QSGFlatColorMaterial *material,
+ QSGNode *layerChain) Q_DECL_OVERRIDE
+ {
+ QSGGeometryNode *geometryNode = new QSGGeometryNode;
+ geometryNode->setFlags(QSGNode::OwnsGeometry | QSGNode::OwnsMaterial);
+
+ geometryNode->setGeometry(geometry);
+ geometryNode->setMaterial(material);
+
+ layerChain->appendChildNode(geometryNode);
+ m_sceneGraphNodes->append(geometryNode);
+ }
+
+#ifndef QT_NO_OPENGL
+ void setupYUVVideoNode(QSGTexture *yTexture, QSGTexture *uTexture, QSGTexture *vTexture,
+ QSGTexture *aTexture, const QRectF &yaTexCoordRect,
+ const QRectF &uvTexCoordRect, const QSizeF &yaTexSize,
+ const QSizeF &uvTexSize, YUVVideoMaterial::ColorSpace colorspace,
+ float rMul, float rOff, const QRectF &rect,
+ QSGNode *layerChain) Q_DECL_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) Q_DECL_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 cc::RenderPassId &id, const QVector<QPair<cc::RenderPassId, QSharedPointer<QSGLayer> > > &list)
{
typedef QPair<cc::RenderPassId, QSharedPointer<QSGLayer> > Pair;
@@ -513,7 +752,67 @@ static YUVVideoMaterial::ColorSpace toQt(cc::YUVVideoDrawQuad::ColorSpace color_
return YUVVideoMaterial::REC_601;
}
-void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData, cc::ReturnedResourceArray *resourcesToRelease, RenderWidgetHostViewQtDelegate *apiDelegate)
+static bool areSharedQuadStatesEqual(const cc::SharedQuadState *layerState,
+ const cc::SharedQuadState *prevLayerState)
+{
+ 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(cc::DelegatedFrameData *frameData,
+ cc::DelegatedFrameData *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) {
+ cc::RenderPass *newPass = frameData->render_pass_list.at(i).get();
+ cc::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;
+
+ cc::QuadList::ConstBackToFrontIterator it = newPass->quad_list.BackToFrontBegin();
+ cc::QuadList::ConstBackToFrontIterator end = newPass->quad_list.BackToFrontEnd();
+ cc::QuadList::ConstBackToFrontIterator prevIt = prevPass->quad_list.BackToFrontBegin();
+ cc::QuadList::ConstBackToFrontIterator prevEnd = prevPass->quad_list.BackToFrontEnd();
+ for (; it != end && prevIt != prevEnd; ++it, ++prevIt) {
+ const cc::DrawQuad *quad = *it;
+ const cc::DrawQuad *prevQuad = *prevIt;
+ if (!areSharedQuadStatesEqual(quad->shared_quad_state, prevQuad->shared_quad_state))
+ return false;
+ if (quad->material != prevQuad->material)
+ return false;
+#ifndef QT_NO_OPENGL
+ if (quad->material == cc::DrawQuad::YUV_VIDEO_CONTENT)
+ return false;
+#ifdef GL_OES_EGL_image_external
+ if (quad->material == cc::DrawQuad::STREAM_VIDEO_CONTENT)
+ return false;
+#endif // GL_OES_EGL_image_external
+#endif // QT_NO_OPENGL
+
+ }
+ }
+ return true;
+}
+
+void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
+ cc::ReturnedResourceArray *resourcesToRelease,
+ RenderWidgetHostViewQtDelegate *apiDelegate)
{
m_chromiumCompositorData = chromiumCompositorData;
cc::DelegatedFrameData* frameData = m_chromiumCompositorData->frameData.get();
@@ -524,13 +823,11 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
// countering the scale of devicePixel-scaled tiles when rendering them
// to the final surface.
QMatrix4x4 matrix;
- matrix.scale(1 / m_chromiumCompositorData->frameDevicePixelRatio, 1 / m_chromiumCompositorData->frameDevicePixelRatio);
- setMatrix(matrix);
+ matrix.scale(1 / m_chromiumCompositorData->frameDevicePixelRatio,
+ 1 / m_chromiumCompositorData->frameDevicePixelRatio);
+ if (QSGTransformNode::matrix() != matrix)
+ setMatrix(matrix);
- // 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.
- SGObjects previousSGObjects;
- qSwap(m_sgObjects, previousSGObjects);
QHash<unsigned, QSharedPointer<ResourceHolder> > resourceCandidates;
qSwap(m_chromiumCompositorData->resourceHolders, resourceCandidates);
@@ -547,14 +844,32 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
}
frameData->resource_list.clear();
+ QScopedPointer<DelegatedNodeTreeHandler> nodeHandler;
- // 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.
- // Intermediate render pass node chains are going to be destroyed when previousSGObjects
- // goes out of scope together with any QSGLayer that could reference them.
- while (QSGNode *oldChain = firstChild())
- delete oldChain;
+ // 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.
+ cc::DelegatedFrameData *previousFrameData = m_chromiumCompositorData->previousFrameData.get();
+ const bool buildNewTree = !areRenderPassStructuresEqual(frameData, previousFrameData);
+ m_chromiumCompositorData->previousFrameData = nullptr;
+ 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
@@ -568,149 +883,168 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
QSGNode *renderPassParent = 0;
if (pass != rootRenderPass) {
- QSharedPointer<QSGLayer> 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);
+ 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<cc::RenderPassId,
+ 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->setItem(rootNode.data());
- m_sgObjects.renderPassLayers.append(QPair<cc::RenderPassId, QSharedPointer<QSGLayer> >(pass->id, rpLayer));
- m_sgObjects.renderPassRootNodes.append(rootNode);
- renderPassParent = rootNode.data();
} else
renderPassParent = this;
- QSGNode *renderPassChain = buildRenderPassChain(renderPassParent);
- const cc::SharedQuadState *currentLayerState = 0;
- QSGNode *currentLayerChain = 0;
+ const cc::SharedQuadState *currentLayerState = nullptr;
+ QSGNode *currentLayerChain = nullptr;
+
+ QSGNode *renderPassChain = nullptr;
+ if (buildNewTree)
+ renderPassChain = buildRenderPassChain(renderPassParent);
cc::QuadList::ConstBackToFrontIterator it = pass->quad_list.BackToFrontBegin();
cc::QuadList::ConstBackToFrontIterator end = pass->quad_list.BackToFrontEnd();
for (; it != end; ++it) {
const cc::DrawQuad *quad = *it;
- if (currentLayerState != quad->shared_quad_state) {
+ if (buildNewTree && currentLayerState != quad->shared_quad_state) {
currentLayerState = quad->shared_quad_state;
currentLayerChain = buildLayerChain(renderPassChain, currentLayerState);
}
switch (quad->material) {
case cc::DrawQuad::RENDER_PASS: {
- const cc::RenderPassDrawQuad *renderPassQuad = cc::RenderPassDrawQuad::MaterialCast(quad);
- QSGTexture *layer = findRenderPassLayer(renderPassQuad->render_pass_id, m_sgObjects.renderPassLayers).data();
+ const cc::RenderPassDrawQuad *renderPassQuad
+ = cc::RenderPassDrawQuad::MaterialCast(quad);
+ QSGTexture *layer = findRenderPassLayer(renderPassQuad->render_pass_id,
+ m_sgObjects.renderPassLayers).data();
+
// cc::GLRenderer::DrawRenderPassQuad silently ignores missing render passes.
if (!layer)
continue;
-
- // Only QSGInternalImageNode currently supports QSGLayer textures.
- QSGInternalImageNode *imageNode = apiDelegate->createImageNode();
- imageNode->setTargetRect(toQt(quad->rect));
- imageNode->setInnerTargetRect(toQt(quad->rect));
- imageNode->setTexture(layer);
- imageNode->update();
- currentLayerChain->appendChildNode(imageNode);
+ nodeHandler->setupRenderPassNode(layer, toQt(quad->rect), currentLayerChain);
break;
} case cc::DrawQuad::TEXTURE_CONTENT: {
const cc::TextureDrawQuad *tquad = cc::TextureDrawQuad::MaterialCast(quad);
- ResourceHolder *resource = findAndHoldResource(tquad->resource_id(), resourceCandidates);
-
- QSGTextureNode *textureNode = apiDelegate->createTextureNode();
- textureNode->setTextureCoordinatesTransform(tquad->y_flipped ? QSGTextureNode::MirrorVertically : QSGTextureNode::NoTransform);
- textureNode->setRect(toQt(quad->rect));
- textureNode->setFiltering(resource->transferableResource().filter == GL_LINEAR ? QSGTexture::Linear : QSGTexture::Nearest);
- textureNode->setTexture(initAndHoldTexture(resource, quad->ShouldDrawWithBlending(), apiDelegate));
- currentLayerChain->appendChildNode(textureNode);
+ ResourceHolder *resource = findAndHoldResource(tquad->resource_id(),
+ resourceCandidates);
+
+ nodeHandler->setupTextureContentNode(
+ initAndHoldTexture(resource,
+ quad->ShouldDrawWithBlending(),
+ apiDelegate),
+ toQt(quad->rect),
+ resource->transferableResource().filter == GL_LINEAR
+ ? QSGTexture::Linear
+ : QSGTexture::Nearest,
+ tquad->y_flipped ? QSGTextureNode::MirrorVertically
+ : QSGTextureNode::NoTransform,
+ currentLayerChain);
break;
} case cc::DrawQuad::SOLID_COLOR: {
const cc::SolidColorDrawQuad *scquad = cc::SolidColorDrawQuad::MaterialCast(quad);
- QSGRectangleNode *rectangleNode = apiDelegate->createRectangleNode();
-
// 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);
-
- rectangleNode->setRect(toQt(quad->rect));
- rectangleNode->setColor(toQt(scquad->color));
- currentLayerChain->appendChildNode(rectangleNode);
+ nodeHandler->setupSolidColorNode(toQt(quad->rect), toQt(scquad->color),
+ currentLayerChain);
break;
#ifndef QT_NO_OPENGL
} case cc::DrawQuad::DEBUG_BORDER: {
- const cc::DebugBorderDrawQuad *dbquad = cc::DebugBorderDrawQuad::MaterialCast(quad);
- QSGGeometryNode *geometryNode = new QSGGeometryNode;
+ const cc::DebugBorderDrawQuad *dbquad
+ = cc::DebugBorderDrawQuad::MaterialCast(quad);
- QSGGeometry *geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 4);
+ 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.
+ // 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());
- geometryNode->setGeometry(geometry);
QSGFlatColorMaterial *material = new QSGFlatColorMaterial;
material->setColor(toQt(dbquad->color));
- geometryNode->setMaterial(material);
- geometryNode->setFlags(QSGNode::OwnsGeometry | QSGNode::OwnsMaterial);
- currentLayerChain->appendChildNode(geometryNode);
+ nodeHandler->setupDebugBorderNode(geometry, material, currentLayerChain);
break;
#endif
} case cc::DrawQuad::TILED_CONTENT: {
const cc::TileDrawQuad *tquad = cc::TileDrawQuad::MaterialCast(quad);
- ResourceHolder *resource = findAndHoldResource(tquad->resource_id(), resourceCandidates);
-
- QSGTextureNode *textureNode = apiDelegate->createTextureNode();
- textureNode->setRect(toQt(quad->rect));
- textureNode->setSourceRect(toQt(tquad->tex_coord_rect));
- textureNode->setFiltering(resource->transferableResource().filter == GL_LINEAR ? QSGTexture::Linear : QSGTexture::Nearest);
- textureNode->setTexture(initAndHoldTexture(resource, quad->ShouldDrawWithBlending(), apiDelegate));
- currentLayerChain->appendChildNode(textureNode);
+ ResourceHolder *resource
+ = findAndHoldResource(tquad->resource_id(), resourceCandidates);
+ nodeHandler->setupTiledContentNode(
+ initAndHoldTexture(resource,
+ quad->ShouldDrawWithBlending(),
+ apiDelegate),
+ toQt(quad->rect), toQt(tquad->tex_coord_rect),
+ resource->transferableResource().filter
+ == GL_LINEAR ? QSGTexture::Linear
+ : QSGTexture::Nearest,
+ currentLayerChain);
break;
#ifndef QT_NO_OPENGL
} case cc::DrawQuad::YUV_VIDEO_CONTENT: {
const cc::YUVVideoDrawQuad *vquad = cc::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 *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.
+ // 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);
-
- YUVVideoNode *videoNode = new YUVVideoNode(
- 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),
- toQt(vquad->color_space),
- vquad->resource_multiplier, vquad->resource_offset);
- videoNode->setRect(toQt(quad->rect));
- currentLayerChain->appendChildNode(videoNode);
+ 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),
+ toQt(vquad->color_space),
+ vquad->resource_multiplier, vquad->resource_offset,
+ toQt(quad->rect),
+ currentLayerChain);
break;
#ifdef GL_OES_EGL_image_external
} case cc::DrawQuad::STREAM_VIDEO_CONTENT: {
const cc::StreamVideoDrawQuad *squad = cc::StreamVideoDrawQuad::MaterialCast(quad);
- ResourceHolder *resource = findAndHoldResource(squad->resource_id(), resourceCandidates);
- MailboxTexture *texture = static_cast<MailboxTexture *>(initAndHoldTexture(resource, quad->ShouldDrawWithBlending()));
- texture->setTarget(GL_TEXTURE_EXTERNAL_OES); // since this is not default TEXTURE_2D type
-
- StreamVideoNode *svideoNode = new StreamVideoNode(texture, false, ExternalTarget);
- svideoNode->setRect(toQt(squad->rect));
- svideoNode->setTextureMatrix(toQt(squad->matrix.matrix()));
- currentLayerChain->appendChildNode(svideoNode);
+ 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
@@ -721,9 +1055,11 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
}
}
}
+ // 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;
- // 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());
diff --git a/src/core/delegated_frame_node.h b/src/core/delegated_frame_node.h
index 36ec20f1d..6178bd232 100644
--- a/src/core/delegated_frame_node.h
+++ b/src/core/delegated_frame_node.h
@@ -74,6 +74,7 @@ public:
ChromiumCompositorData() : frameDevicePixelRatio(1) { }
QHash<unsigned, QSharedPointer<ResourceHolder> > resourceHolders;
std::unique_ptr<cc::DelegatedFrameData> frameData;
+ std::unique_ptr<cc::DelegatedFrameData> previousFrameData;
qreal frameDevicePixelRatio;
};
@@ -100,6 +101,7 @@ private:
QVector<QSharedPointer<QSGRootNode> > renderPassRootNodes;
QVector<QSharedPointer<QSGTexture> > textureStrongRefs;
} m_sgObjects;
+ QVector<QSGNode*> m_sceneGraphNodes;
int m_numPendingSyncPoints;
QWaitCondition m_mailboxesFetchedWaitCond;
QMutex m_mutex;
diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp
index 70ffe0dcb..fef3831e3 100644
--- a/src/core/render_widget_host_view_qt.cpp
+++ b/src/core/render_widget_host_view_qt.cpp
@@ -666,6 +666,8 @@ void RenderWidgetHostViewQt::OnSwapCompositorFrame(uint32_t output_surface_id, c
m_pendingOutputSurfaceId = output_surface_id;
Q_ASSERT(frame.delegated_frame_data);
Q_ASSERT(!m_chromiumCompositorData->frameData || m_chromiumCompositorData->frameData->resource_list.empty());
+ if (m_chromiumCompositorData->frameData.get())
+ m_chromiumCompositorData->previousFrameData = std::move(m_chromiumCompositorData->frameData);
m_chromiumCompositorData->frameData = std::move(frame.delegated_frame_data);
m_chromiumCompositorData->frameDevicePixelRatio = frame.metadata.device_scale_factor;