void QuickSceneGraphModel::populateFromNode(QSGNode *node, bool emitSignals)
{
  if (!node) {
    return;
  }

  QVector<QSGNode*> &childList  = m_parentChildMap[node];
  QVector<QSGNode*> newChildList;

  newChildList.reserve(node->childCount());
  for (QSGNode *childNode = node->firstChild(); childNode; childNode = childNode->nextSibling()) {
    newChildList.append(childNode);
  }

  QModelIndex myIndex; // don't call indexForNode(node) here yet, in the common case of few changes we waste a lot of time here
  bool hasMyIndex = false;

  std::sort(newChildList.begin(), newChildList.end());

  QVector<QSGNode*>::iterator i = childList.begin();
  QVector<QSGNode*>::const_iterator j = newChildList.constBegin();

  while (i != childList.end() && j != newChildList.constEnd()) {
    if (*i < *j) { // handle deleted node
      emit nodeDeleted(*i);
      GET_INDEX
      if (emitSignals) {
        const auto idx = std::distance(childList.begin(), i);
        beginRemoveRows(myIndex, idx, idx);
      }
      pruneSubTree(*i);
      i = childList.erase(i);
      if (emitSignals)
        endRemoveRows();
    } else if (*i > *j) { // handle added node
Example #2
0
void QSGRenderer::removeNodesToPreprocess(QSGNode *node)
{
    for (QSGNode *c = node->firstChild(); c; c = c->nextSibling())
        removeNodesToPreprocess(c);
    if (node->flags() & QSGNode::UsePreprocess)
        m_nodes_to_preprocess.remove(node);
}
Example #3
0
void QSGRenderer::preprocess()
{
    Q_ASSERT(m_root_node);

    // We need to take a copy here, in case any of the preprocess calls deletes a node that
    // is in the preprocess list and thus, changes the m_nodes_to_preprocess behind our backs
    // For the default case, when this does not happen, the cost is neglishible.
    QSet<QSGNode *> items = m_nodes_to_preprocess;

    for (QSet<QSGNode *>::const_iterator it = items.constBegin();
         it != items.constEnd(); ++it) {
        QSGNode *n = *it;
        if (!nodeUpdater()->isNodeBlocked(n, m_root_node)) {
            n->preprocess();
        }
    }

#ifdef QSG_RENDERER_TIMING
    preprocessTime = frameTimer.elapsed();
#endif

    nodeUpdater()->setToplevelOpacity(context()->renderAlpha());
    nodeUpdater()->updateStates(m_root_node);

#ifdef QSG_RENDERER_TIMING
    updatePassTime = frameTimer.elapsed();
#endif

}
Example #4
0
void SatellitesItem::update() {
    if( ! m_satComp->selected() ) {
        hide();
        return;
    }

    QSGNode *n = firstChild();

    while(n != 0) {
        SatelliteNode *satNode = static_cast<SatelliteNode *>(n);
        Satellite *sat = satNode->sat();
        if ( sat->selected() ) {
            if ( Options::showVisibleSatellites() ) {
                if ( sat->isVisible() ) {
                    satNode->update();
                } else {
                    satNode->hide();
                }
            } else {
                satNode->update();
            }
        } else {
            satNode->hide();
        }
        n = n->nextSibling();
    }
}
QVariant QuickSceneGraphModel::data(const QModelIndex &index, int role) const
{
  if (!index.isValid()) {
    return QVariant();
  }

  QSGNode *node = reinterpret_cast<QSGNode*>(index.internalPointer());

  if (role == Qt::DisplayRole) {
    if (index.column() == 0) {
      return Util::addressToString(node);
    } else if (index.column() == 1) {
      switch (node->type()) {
      case QSGNode::BasicNodeType:
        return "Node";
      case QSGNode::GeometryNodeType:
        return "Geometry Node";
      case QSGNode::TransformNodeType:
        return "Transform Node";
      case QSGNode::ClipNodeType:
        return "Clip Node";
      case QSGNode::OpacityNodeType:
        return "Opacity Node";
      case QSGNode::RootNodeType:
        return "Root Node";
      case QSGNode::RenderNodeType:
        return "Render Node";
      }
    }
  } else if (role == ObjectModel::ObjectRole) {
    return QVariant::fromValue(node);
  }

  return QVariant();
}
void QQuickOpacityAnimatorJob::initialize(QQuickAnimatorController *controller)
{
    QQuickAnimatorJob::initialize(controller);
    QQuickItemPrivate *d = QQuickItemPrivate::get(m_target);
    if (d->extra.isAllocated()
            && d->extra->layer
            && d->extra->layer->enabled()) {
        d = QQuickItemPrivate::get(d->extra->layer->m_effectSource);
    }

    m_opacityNode = d->opacityNode();
    if (!m_opacityNode) {
        m_opacityNode = new QSGOpacityNode();
        d->extra.value().opacityNode = m_opacityNode;

        QSGNode *child = d->clipNode();
        if (!child)
            child = d->rootNode();
        if (!child)
            child = d->groupNode;

        if (child) {
            if (child->parent())
                child->parent()->removeChildNode(child);
            m_opacityNode->appendChildNode(child);
        }

        d->itemNode()->appendChildNode(m_opacityNode);
    }
}
Example #7
0
void MultiTrackPlotter::setChannelData( int channel, float *data )
{
    Q_ASSERT(channel >= 0 && channel < m_channel_count);

    QSGNode *transformNode = childAtIndex(channel);
    PlotNode1D *plotNode = static_cast<PlotNode1D*>( transformNode->childAtIndex(0) );
    plotNode->setData(data, m_frame_count);
}
Example #8
0
 void deleteContent()
 {
     QSGNode *subnode = firstChild();
     while (subnode) {
         // We can't delete the node now as it might be in the preprocess list
         // It will be deleted in the next preprocess
         m_nodes_to_delete.append(subnode);
         subnode = subnode->nextSibling();
     }
     removeAllChildNodes();
 }
Example #9
0
void QSGNodeVisitorEx::visitChildren(QSGNode *node)
{
    for (QSGNode *child = node->firstChild(); child; child = child->nextSibling()) {
        switch (child->type()) {
        case QSGNode::ClipNodeType: {
            QSGClipNode *c = static_cast<QSGClipNode*>(child);
            if (visit(c))
                visitChildren(c);
            endVisit(c);
            break;
        }
        case QSGNode::TransformNodeType: {
            QSGTransformNode *c = static_cast<QSGTransformNode*>(child);
            if (visit(c))
                visitChildren(c);
            endVisit(c);
            break;
        }
        case QSGNode::OpacityNodeType: {
            QSGOpacityNode *c = static_cast<QSGOpacityNode*>(child);
            if (visit(c))
                visitChildren(c);
            endVisit(c);
            break;
        }
        case QSGNode::GeometryNodeType: {
            if (child->flags() & QSGNode::IsVisitableNode) {
                QSGVisitableNode *v = static_cast<QSGVisitableNode*>(child);
                v->accept(this);
            } else {
                QSGGeometryNode *c = static_cast<QSGGeometryNode*>(child);
                if (visit(c))
                    visitChildren(c);
                endVisit(c);
            }
            break;
        }
        case QSGNode::RootNodeType: {
            QSGRootNode *root = static_cast<QSGRootNode*>(child);
            if (visit(root))
                visitChildren(root);
            endVisit(root);
            break;
        }
        case QSGNode::BasicNodeType: {
            visitChildren(child);
            break;
        }
        default:
            Q_UNREACHABLE();
            break;
        }
    }
}
BindingLoopsRenderPassState::BindingLoopsRenderPassState(const QmlProfilerRangeModel *model) :
    m_indexFrom(std::numeric_limits<int>::max()), m_indexTo(-1)
{
    m_collapsedOverlay = new QSGNode;
    m_collapsedOverlay->setFlag(QSGNode::OwnedByParent, false);
    m_expandedRows.reserve(model->expandedRowCount());
    for (int i = 0; i < model->expandedRowCount(); ++i) {
        QSGNode *node = new QSGNode;
        node->setFlag(QSGNode::OwnedByParent, false);
        m_expandedRows << node;
    }
}
QSGNode *QuickSceneGraphModel::currentRootNode() const
{
    if (!m_window)
        return nullptr;

    QQuickItem *item = m_window->contentItem();
    QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
    QSGNode *root = itemPriv->itemNode();
    while (root->parent()) // Ensure that we really get the very root node.
        root = root->parent();
    return root;
}
/* Search through the node set and remove nodes that are leaves of other
   nodes in the same set.
 */
QSet<QSGNode *> qsg_simplerenderer_updateRoots(const QSet<QSGNode *> &nodes, QSGRootNode *root)
{
    QSet<QSGNode *> result = nodes;
    foreach (QSGNode *node, nodes) {
        QSGNode *n = node;
        while (n != root) {
            if (result.contains(n)) {
                result.remove(node);
                break;
            }
            n = n->parent();
        }
    }
Example #13
0
void QSGNode::removeAllChildNodes()
{
    while (m_firstChild) {
        QSGNode *node = m_firstChild;
        m_firstChild = node->m_nextSibling;
        node->m_nextSibling = 0;
        if (m_firstChild)
            m_firstChild->m_previousSibling = 0;
        else
            m_lastChild = 0;
        node->markDirty(DirtyNodeRemoved);
        node->m_parent = 0;
    }
}
Example #14
0
QSGNode *QQuickTextField::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
{
    QQuickDefaultClipNode *clipNode = static_cast<QQuickDefaultClipNode *>(oldNode);
    if (!clipNode)
        clipNode = new QQuickDefaultClipNode(QRectF());

    clipNode->setRect(clipRect().adjusted(leftPadding(), topPadding(), -rightPadding(), -bottomPadding()));
    clipNode->update();

    QSGNode *textNode = QQuickTextInput::updatePaintNode(clipNode->firstChild(), data);
    if (!textNode->parent())
        clipNode->appendChildNode(textNode);

    return clipNode;
}
Example #15
0
void QSGNode::destroy()
{
    if (m_parent) {
        m_parent->removeChildNode(this);
        Q_ASSERT(m_parent == 0);
    }
    while (m_firstChild) {
        QSGNode *child = m_firstChild;
        removeChildNode(child);
        Q_ASSERT(child->m_parent == 0);
        if (child->flags() & OwnedByParent)
            delete child;
    }

    Q_ASSERT(m_firstChild == 0 && m_lastChild == 0);
}
QSGNode* Graph::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *data)
{   
    QSGNode* rootNode = QQuickItem::updatePaintNode(oldNode, data);

    if (rootNode == NULL) {
        rootNode = new QSGNode();
        rootNode->setFlag(QSGNode::OwnedByParent, true);
    }
    else {
        rootNode->removeAllChildNodes();
    }

    DrawAxes(rootNode);

    return rootNode;
}
Example #17
0
void SupernovaeItem::update() {
    if( ! m_snovaComp->selected() ) {
        hide();
        return;
    }
    show();

    QSGNode *n = firstChild();

    while(n != 0) {
        SupernovaNode *sNode = static_cast<SupernovaNode *>(n);
        sNode->update();

        n = n->nextSibling();
    }
}
void TimelineRenderState::updateExpandedRowHeights(const TimelineModel *model, int defaultRowHeight,
                                                   int defaultRowOffset)
{
    Q_D(TimelineRenderState);
    int row = 0;
    qreal offset = 0;
    for (QSGNode *rowNode = d->expandedRowRoot->firstChild(); rowNode != 0;
         rowNode = rowNode->nextSibling()) {
        qreal rowHeight = model->expandedRowHeight(row++);
        QMatrix4x4 matrix;
        matrix.translate(0, offset, 0);
        matrix.scale(1, rowHeight / defaultRowHeight, 1);
        offset += defaultRowOffset * rowHeight / defaultRowHeight;
        static_cast<QSGTransformNode *>(rowNode)->setMatrix(matrix);
    }
}
Example #19
0
void QSGNode::markDirty(DirtyState bits)
{
    int renderableCountDiff = 0;
    if (bits & DirtyNodeAdded)
        renderableCountDiff += m_subtreeRenderableCount;
    if (bits & DirtyNodeRemoved)
        renderableCountDiff -= m_subtreeRenderableCount;

    QSGNode *p = m_parent;
    while (p) {
        p->m_subtreeRenderableCount += renderableCountDiff;
        if (p->type() == RootNodeType)
            static_cast<QSGRootNode *>(p)->notifyNodeChange(this, bits);
        p = p->m_parent;
    }
}
void QuickSceneGraphModel::updateSGTree()
{
  QQuickItem *item = m_window->contentItem();
  QQuickItemPrivate *itemPriv = QQuickItemPrivate::get(item);
  QSGNode *rootNode = itemPriv->itemNode();
  while(rootNode->parent()) // Ensure that we really get the very root node.
      rootNode = rootNode->parent();
  m_oldChildParentMap = m_childParentMap;
  m_oldParentChildMap = m_parentChildMap;
  m_childParentMap = QHash<QSGNode*, QSGNode*>();
  m_parentChildMap = QHash<QSGNode*, QVector<QSGNode*> >();
  m_childParentMap[m_rootNode] = 0;
  m_parentChildMap[0].append(m_rootNode);

  populateFromNode(m_rootNode);
  collectItemNodes(m_window->contentItem());
}
Example #21
0
void QQuickTextNode::setColor(const QColor &color)
{
    if (m_usePixmapCache) {
        setUpdateFlag(UpdateNodes);
    } else {
        for (QSGNode *childNode = firstChild(); childNode; childNode = childNode->nextSibling()) {
            if (childNode->subType() == GlyphNodeSubType) {
                QSGGlyphNode *glyphNode = static_cast<QSGGlyphNode *>(childNode);
                if (glyphNode->color() == m_color)
                    glyphNode->setColor(color);
            } else if (childNode->subType() == SolidRectNodeSubType) {
                QSGSimpleRectNode *solidRectNode = static_cast<QSGSimpleRectNode *>(childNode);
                if (solidRectNode->color() == m_color)
                    solidRectNode->setColor(color);
            }
        }
    }
    m_color = color;
}
Example #22
0
void QSGAbstractSoftwareRenderer::nodeRemoved(QSGNode *node)
{
    qCDebug(lc2DRender) << "nodeRemoved" << (void*)node;

    auto renderable = renderableNode(node);
    // remove mapping
    if (renderable != nullptr) {
        // Need to mark this region dirty in the other nodes
        QRegion dirtyRegion = renderable->previousDirtyRegion(true);
        if (dirtyRegion.isEmpty())
            dirtyRegion = renderable->boundingRectMax();
        m_dirtyRegion += dirtyRegion;
        m_nodes.remove(node);
        delete renderable;
    }

    // Remove all children nodes as well
    for (QSGNode *child = node->firstChild(); child; child = child->nextSibling()) {
        nodeRemoved(child);
    }

    m_nodeUpdater->updateNodes(node, true);
}
Example #23
0
QSGNode *Renderer::paintNode(const QRectF& viewport) const {
  if (m_tiles.isEmpty()) {
    return 0;
  }

  QSGNode *parentNode = new QSGNode;

  for (const Tile& tile : m_tiles) {
    if (tile.visible) {
      QRectF rect = m_view->tileRect(tile);
      QSGSimpleTextureNode *node = new SimpleTextureNode;
      node->setFlag(QSGNode::OwnedByParent, true);
      node->setTexture(m_view->window()->createTextureFromImage(tile.image));
      node->setRect(rect);
      node->setFiltering(QSGTexture::Nearest);
      //      node->setOwnsTexture(true); // TODO: Qt 5.4

      qreal dx1 = rect.left() < viewport.left() ? viewport.left() - rect.left() : 0.0f;
      qreal dy1 = 0.0f;
      qreal dx2 = rect.right() > viewport.right() ? viewport.right() - rect.right() : 0.0f;
      qreal dy2 = rect.bottom() > viewport.bottom() ? viewport.bottom() - rect.bottom() : 0.0f;

      if (dx1 != 0.0f || dx2 != 0.0f || dy2 != 0.0f) {
	QSGClipNode *clip = new QSGClipNode;
	clip->setIsRectangular(true);
	clip->setClipRect(rect.adjusted(dx1, dy1, dx2, dy2));
	parentNode->appendChildNode(clip);
	clip->appendChildNode(node);
	//	qDebug() << "Clipping";
      } else {
	parentNode->appendChildNode(node);
      }
    }
  }

  return parentNode;
}
Example #24
0
void MultiTrackPlotter::setChannelColor( int channel, const QColor & color )
{
    QSGNode *transformNode = childAtIndex(channel);
    PlotNode1D *plotNode = static_cast<PlotNode1D*>( transformNode->childAtIndex(0) );
    plotNode->setColor(color);
}
QSGNode* AudioBarSpectrumItem::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData*) {
    if (!m_analyzer) return oldNode;
    if (!isVisible()) return oldNode;

    const std::vector<double>& points = m_analyzer->getSimplifiedSpectrum();
    const double gain = m_agcEnabled ? m_analyzer->getAgcValue() : m_manualGain;
    const int pointCount = points.size();
    if (pointCount < 2) return oldNode;

    // -------------------- Prepare QSG Nodes:
    QSGNode* parentNode = nullptr;
    if (oldNode) {
        parentNode = static_cast<QSGNode*>(oldNode);
    } else {
        parentNode = new QSGNode;
    }
    // adapt child count:
    int childCount = parentNode->childCount();
    if (childCount != 2) {
        parentNode->removeAllChildNodes();
        QSGGeometryNode* node = new QSGGeometryNode;
        QSGGeometry* geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 3);
        geometry->setDrawingMode(GL_TRIANGLE_STRIP);
        node->setGeometry(geometry);
        node->setFlag(QSGNode::OwnsGeometry);
        QSGFlatColorMaterial* material = new QSGFlatColorMaterial;
        material->setColor("#fff");
        node->setMaterial(material);
        node->setFlag(QSGNode::OwnsMaterial);
        parentNode->appendChildNode(node);

        // Attention: TODO: colors are swapped!

        node = new QSGGeometryNode;
        geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 3);
        geometry->setDrawingMode(GL_TRIANGLE_STRIP);
        node->setGeometry(geometry);
        node->setFlag(QSGNode::OwnsGeometry);
        material = new QSGFlatColorMaterial;
        material->setColor(m_color);
        node->setMaterial(material);
        node->setFlag(QSGNode::OwnsMaterial);
        parentNode->appendChildNode(node);
    }

    QSGGeometryNode* const qsgNode = static_cast<QSGGeometryNode*>(parentNode->childAtIndex(0));
    QSGGeometryNode* const qsgNodeOutline = static_cast<QSGGeometryNode*>(parentNode->childAtIndex(1));
    if (!qsgNode || !qsgNodeOutline) {
        qCritical() << "[SpectrumItem] Could not get QSG Node.";
        return nullptr;
    }
    QSGGeometry* const geometry = qsgNode->geometry();
    QSGGeometry* const geometryOutline = qsgNodeOutline->geometry();
    if (!geometry || !geometryOutline) {
        qCritical() << "[SpectrumItem] Could not get QSG Geometry.";
        return nullptr;
    }

    const int verticesCount = pointCount * 7;
    const int outlineVerticesCount = pointCount * 7;

    geometry->allocate(verticesCount);
    geometryOutline->allocate(outlineVerticesCount);
    QSGGeometry::Point2D* const vertices = geometry->vertexDataAsPoint2D();
    QSGGeometry::Point2D* const verticesOutline = geometryOutline->vertexDataAsPoint2D();

    if (! vertices || !verticesOutline) {
        qCritical() << "[SpectrumItem] Could not get QSG vertices.";
        return nullptr;
    }

    const double itemWidth = width();
    const double itemHeight = height();
    const double barWidth = (itemWidth / pointCount) * 0.4;
    const double spaceWidth = (itemWidth / pointCount) * 0.6;
    const double endLineHeight = itemHeight / 100.0;

    // draw spectrum:
    for (int i = 0; i < pointCount; ++i) {
        const float x = itemWidth * (i / float(pointCount));
        const float y = itemHeight * (1 - points[i] * gain);

        vertices[i*7].set(x, itemHeight);
        vertices[i*7+1].set(x, y);
        vertices[i*7+2].set(x + barWidth, itemHeight);
        vertices[i*7+3].set(x + barWidth, y);
        vertices[i*7+4].set(x + barWidth, itemHeight);
        vertices[i*7+5].set(x + barWidth, itemHeight);
        vertices[i*7+6].set(x + barWidth + spaceWidth, itemHeight);

        const float y2 = qMin(itemHeight, itemHeight * (1 - points[i] * gain) + endLineHeight);

        verticesOutline[i*7].set(x, itemHeight);
        verticesOutline[i*7+1].set(x, y2);
        verticesOutline[i*7+2].set(x + barWidth, itemHeight);
        verticesOutline[i*7+3].set(x + barWidth, y2);
        verticesOutline[i*7+4].set(x + barWidth, itemHeight);
        verticesOutline[i*7+5].set(x + barWidth, itemHeight);
        verticesOutline[i*7+6].set(x + barWidth + spaceWidth, itemHeight);
    }

    // tell Scene Graph that this items needs to be drawn:
    qsgNode->markDirty(QSGNode::DirtyGeometry);
    qsgNodeOutline->markDirty(QSGNode::DirtyGeometry);

    return parentNode;
}
void QSGDefaultRenderer::buildLists(QSGNode *node)
{
    if (node->isSubtreeBlocked())
        return;

    if (node->type() == QSGNode::GeometryNodeType) {
        QSGGeometryNode *geomNode = static_cast<QSGGeometryNode *>(node);
        qreal opacity = geomNode->inheritedOpacity();
        QSGMaterial *m = geomNode->activeMaterial();

#ifdef FORCE_NO_REORDER
        if (true) {
#else
        if ((m->flags() & QSGMaterial::Blending) || opacity < 1) {
#endif
            geomNode->setRenderOrder(m_currentRenderOrder - 1);
            m_transparentNodes.add(geomNode);
        } else {
            geomNode->setRenderOrder(m_currentRenderOrder);
            m_opaqueNodes.add(geomNode);
            m_currentRenderOrder += 2;
        }
    }

    if (!node->firstChild())
        return;

#ifdef FORCE_NO_REORDER
    static bool reorder = false;
#else
    static bool reorder = !qApp->arguments().contains(QLatin1String("--no-reorder"));
#endif

    if (reorder && node->firstChild() != node->lastChild() && (node->flags() & QSGNode::ChildrenDoNotOverlap)) {
        QVarLengthArray<int, 16> beginIndices;
        QVarLengthArray<int, 16> endIndices;
        int baseCount = m_transparentNodes.size();
        int count = 0;
        for (QSGNode *c = node->firstChild(); c; c = c->nextSibling()) {
            beginIndices.append(m_transparentNodes.size());
            buildLists(c);
            endIndices.append(m_transparentNodes.size());
            ++count;
        }

        int childNodeCount = m_transparentNodes.size() - baseCount;
        if (childNodeCount) {
            m_tempNodes.reset();
            m_tempNodes.reserve(childNodeCount);
            while (childNodeCount) {
                for (int i = 0; i < count; ++i) {
                    if (beginIndices[i] != endIndices[i])
                        m_heap.insert(IndexGeometryNodePair(i, m_transparentNodes.at(beginIndices[i]++)));
                }
                while (!m_heap.isEmpty()) {
                    IndexGeometryNodePair pair = m_heap.pop();
                    m_tempNodes.add(pair.second);
                    --childNodeCount;
                    int i = pair.first;
                    if (beginIndices[i] != endIndices[i] && !nodeLessThan(m_transparentNodes.at(beginIndices[i]), pair.second))
                        m_heap.insert(IndexGeometryNodePair(i, m_transparentNodes.at(beginIndices[i]++)));
                }
            }
            Q_ASSERT(m_tempNodes.size() == m_transparentNodes.size() - baseCount);

            qMemCopy(&m_transparentNodes.at(baseCount), &m_tempNodes.at(0), m_tempNodes.size() * sizeof(QSGGeometryNode *));
        }
    } else {
        for (QSGNode *c = node->firstChild(); c; c = c->nextSibling())
            buildLists(c);
    }
}

void QSGDefaultRenderer::renderNodes(const QDataBuffer<QSGGeometryNode *> &list)
{
    const float scale = 1.0f / m_currentRenderOrder;
    int count = list.size();
    int currentRenderOrder = 0x80000000;
    m_current_projection_matrix.setColumn(2, scale * projectionMatrix().column(2));

    //int clipChangeCount = 0;
    //int programChangeCount = 0;
    //int materialChangeCount = 0;

    for (int i = 0; i < count; ++i) {
        QSGGeometryNode *geomNode = list.at(i);

        QSGMaterialShader::RenderState::DirtyStates updates;

#if defined (QML_RUNTIME_TESTING)
        static bool dumpTree = qApp->arguments().contains(QLatin1String("--dump-tree"));
        if (dumpTree)
            qDebug() << geomNode;
#endif

        bool changeMatrix = m_currentMatrix != geomNode->matrix();

        if (changeMatrix) {
            m_currentMatrix = geomNode->matrix();
            if (m_currentMatrix)
                m_current_model_view_matrix = *m_currentMatrix;
            else
                m_current_model_view_matrix.setToIdentity();
            updates |= QSGMaterialShader::RenderState::DirtyMatrix;
        }

        bool changeOpacity = m_current_opacity != geomNode->inheritedOpacity();
        if (changeOpacity) {
            updates |= QSGMaterialShader::RenderState::DirtyOpacity;
            m_current_opacity = geomNode->inheritedOpacity();
        }

        Q_ASSERT(geomNode->activeMaterial());

        QSGMaterial *material = geomNode->activeMaterial();
        QSGMaterialShader *program = m_context->prepareMaterial(material);
        Q_ASSERT(program->program()->isLinked());

        bool changeClip = geomNode->clipList() != m_currentClip;
        QSGRenderer::ClipType clipType = QSGRenderer::NoClip;
        if (changeClip) {
            clipType = updateStencilClip(geomNode->clipList());
            m_currentClip = geomNode->clipList();
#ifdef FORCE_NO_REORDER
            glDepthMask(false);
#else
            glDepthMask((material->flags() & QSGMaterial::Blending) == 0 && m_current_opacity == 1);
#endif
            //++clipChangeCount;
        }

        bool changeProgram = (changeClip && clipType == QSGRenderer::StencilClip) || m_currentProgram != program;
        if (changeProgram) {
            if (m_currentProgram)
                m_currentProgram->deactivate();
            m_currentProgram = program;
            m_currentProgram->activate();
            //++programChangeCount;
            updates |= (QSGMaterialShader::RenderState::DirtyMatrix | QSGMaterialShader::RenderState::DirtyOpacity);

#ifdef RENDERER_DEBUG
            materialChanges++;
#endif
        }

        bool changeRenderOrder = currentRenderOrder != geomNode->renderOrder();
        if (changeRenderOrder) {
            currentRenderOrder = geomNode->renderOrder();
            m_current_projection_matrix.setColumn(3, projectionMatrix().column(3)
                                                  + currentRenderOrder
                                                  * m_current_projection_matrix.column(2));
            updates |= QSGMaterialShader::RenderState::DirtyMatrix;
        }

        if (changeProgram || m_currentMaterial != material) {
            program->updateState(state(updates), material, changeProgram ? 0 : m_currentMaterial);
            m_currentMaterial = material;
            //++materialChangeCount;
        }

        //glDepthRange((geomNode->renderOrder() + 0.1) * scale, (geomNode->renderOrder() + 0.9) * scale);

        const QSGGeometry *g = geomNode->geometry();
        bindGeometry(program, g);
        draw(geomNode);

#ifdef RENDERER_DEBUG
        geometryNodesDrawn++;
#endif
    }
    //qDebug("Clip: %i, shader program: %i, material: %i times changed while drawing %s items",
    //    clipChangeCount, programChangeCount, materialChangeCount,
    //    &list == &m_transparentNodes ? "transparent" : "opaque");
}

QT_END_NAMESPACE
QSGNode* BrowserUtils::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData* updatePaintNodeData)
{
	Q_UNUSED(updatePaintNodeData);

	if (!(m_webview && (flags() & QQuickItem::ItemHasContents))) {
		return oldNode;
	}
	setFlag(QQuickItem::ItemHasContents, false);
#if 0
	QQuickWebPage* page = m_webview->page();
	qreal xmin = qMin(page->width(), m_webview->width());
	qreal ymin = qMin(m_webview->height(), page->height());
#else
	// Here the screenshot of the page might be too large if the page is tiny
	qreal xmin = m_webview->width();
	qreal ymin = m_webview->height();
#endif
	ymin = qMin(static_cast<int>(ymin), m_imageSize.height());
	xmin = qMin(static_cast<int>(xmin), m_imageSize.width());

	QSize size(xmin, ymin);

	QSGNode* node = QQuickItemPrivate::get(m_webview)->itemNode();
	QSGNode* parent = node->QSGNode::parent();
	QSGNode* previousSibling = node->previousSibling();
	if (parent) {
		parent->removeChildNode(node);
	}
	QSGRootNode root;
	root.appendChildNode(node);

	QSGRenderer* renderer;
#if QT_VERSION < QT_VERSION_CHECK(5, 2, 0)
	renderer = QQuickItemPrivate::get(this)->sceneGraphContext()->createRenderer();
#else
	renderer = QQuickItemPrivate::get(this)->sceneGraphRenderContext()->createRenderer();
#endif
	renderer->setRootNode(static_cast<QSGRootNode*>(&root));

	QOpenGLFramebufferObject fbo(size);

	renderer->setDeviceRect(size);
	renderer->setViewportRect(size);
	renderer->setProjectionMatrixToRect(QRectF(QPointF(), size));
	renderer->setClearColor(Qt::transparent);

	renderer->renderScene(BindableFbo(&fbo));

	fbo.release();

	QImage image = fbo.toImage().scaled(m_imageSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
	QFileInfo imageInfo(m_outFile);
	QDir imageDir(imageInfo.path());
	if (!imageDir.exists()) {
		imageDir.mkpath(".");
	}

	bool saved = image.save(m_outFile);

	root.removeChildNode(node);
	renderer->setRootNode(0);
	delete renderer;

	if (parent) {
		if (previousSibling) {
			parent->insertChildNodeAfter(node, previousSibling);
		} else {
			parent->prependChildNode(node);
		}
	}

	Q_EMIT webViewSaved(saved, m_outFile);

	return oldNode;
}
Example #28
0
void HsQMLCanvasBackEnd::doRendering()
{
    if (!mGL) {
        mGL = mWindow->openglContext();
        QObject::connect(
            mGL, SIGNAL(aboutToBeDestroyed()), this, SLOT(doCleanup()));
        HsQMLGLCanvasType ctype;
        QSurfaceFormat format = mGL->format();
        switch (format.renderableType()) {
            case QSurfaceFormat::OpenGL: ctype = HSQML_GL_DESKTOP; break;
            case QSurfaceFormat::OpenGLES: ctype = HSQML_GL_ES; break;
            default: setStatus(HsQMLCanvas::BadConfig); return;
        }
        mGLViewportFn = reinterpret_cast<GLViewportFn>(
            mGL->getProcAddress("glViewport"));
        mGLClearColorFn = reinterpret_cast<GLClearColorFn>(
            mGL->getProcAddress("glClearColor"));
        mGLClearFn = reinterpret_cast<GLClearFn>(
            mGL->getProcAddress("glClear"));
        if (!mGLViewportFn || !mGLClearColorFn || !mGLClearFn) {
            setStatus(HsQMLCanvas::BadProcs);
            return;
        }
        mGLCallbacks->mSetupCb(
            ctype, format.majorVersion(), format.minorVersion());
    }

    // Reset OpenGL state before rendering
#if QT_VERSION >= 0x050200
    mWindow->resetOpenGLState();
#else
#warning Resetting OpenGL state requires Qt 5.2 or later
#endif

    // Clear window if painting below the scenegraph
    if (mWinInfo.needsBelowClear()) {
        QColor bg = mWindow->color();
        mGLClearColorFn(bg.redF(), bg.greenF(), bg.blueF(), bg.alphaF());
        mGLClearFn(GL_COLOR_BUFFER_BIT);
    }

    // Setup prior to paint callback
    QMatrix4x4 matrix;
    bool inlineMode = HsQMLCanvas::Inline == mDisplayMode;
    if (inlineMode) {
        if (!mFBO->bind()) {
            setStatus(HsQMLCanvas::BadBind);
            return;
        }
        mGLViewportFn(0, 0, qCeil(mCanvasWidth), qCeil(mCanvasHeight));

        // Clear FBO to transparent
        mGLClearColorFn(0, 0, 0, 0);
        mGLClearFn(GL_COLOR_BUFFER_BIT);
    }
    else {
        // Calculate matrix for non-inline display modes
        QMatrix4x4 smatrix;
        QSGNode* node = mTransformNode;
        while (node) {
            if (QSGNode::TransformNodeType == node->type()) {
                QSGTransformNode* tnode = static_cast<QSGTransformNode*>(node);
                smatrix = tnode->matrix() * smatrix;
            }
            node = node->parent();
        }
        matrix.translate(-1, 1);
        matrix.scale(2.0f/mWindow->width(), -2.0f/mWindow->height());
        matrix *= smatrix;
        matrix.scale(mItemWidth/2.0f, mItemHeight/2.0f);
        matrix.translate(1, 1);

        mGLViewportFn(0, 0, mWindow->width(), mWindow->height());
    }

    setStatus(HsQMLCanvas::Okay);
    mGLCallbacks->mPaintCb(matrix.data(), mItemWidth, mItemHeight);

    if (inlineMode) {
        mFBO->release();
    }
}
Example #29
0
void QSGNodeVisitor::visitChildren(QSGNode *n)
{
    for (QSGNode *c = n->firstChild(); c; c = c->nextSibling())
        visitNode(c);
}
Example #30
0
void SSGQuickLayer::grab()
{
    if (!m_item || m_size.isNull()) {
        delete m_fbo;
        delete m_secondaryFbo;
        m_fbo = m_secondaryFbo = 0;
        m_depthStencilBuffer.clear();
        m_dirtyTexture = false;
        return;
    }
    QSGNode *root = m_item;
    while (root->firstChild() && root->type() != QSGNode::RootNodeType)
        root = root->firstChild();
    if (root->type() != QSGNode::RootNodeType)
        return;

    if (!m_renderer) {
        m_renderer = m_context->createRenderer();
        connect(m_renderer, SIGNAL(sceneGraphChanged()), this, SLOT(markDirtyTexture()));
    }
    m_renderer->setDevicePixelRatio(m_device_pixel_ratio);
    m_renderer->setRootNode(static_cast<QSGRootNode *>(root));

    QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
    bool deleteFboLater = false;
    if (!m_fbo || m_fbo->size() != m_size || m_fbo->format().internalTextureFormat() != m_format
        || (!m_fbo->format().mipmap() && m_mipmap))
    {
        if (!m_multisamplingChecked) {
            if (m_context->openglContext()->format().samples() <= 1) {
                m_multisampling = false;
            } else {
                const QSet<QByteArray> extensions = m_context->openglContext()->extensions();
                m_multisampling = extensions.contains(QByteArrayLiteral("GL_EXT_framebuffer_multisample"))
                    && extensions.contains(QByteArrayLiteral("GL_EXT_framebuffer_blit"));
            }
            m_multisamplingChecked = true;
        }
        if (m_multisampling) {
            // Don't delete the FBO right away in case it is used recursively.
            deleteFboLater = true;
            delete m_secondaryFbo;
            QOpenGLFramebufferObjectFormat format;

            format.setInternalTextureFormat(m_format);
            format.setSamples(m_context->openglContext()->format().samples());
            m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format);
            m_depthStencilBuffer = m_context->depthStencilBufferForFbo(m_secondaryFbo);
        } else {
            QOpenGLFramebufferObjectFormat format;
            format.setInternalTextureFormat(m_format);
            format.setMipmap(m_mipmap);
            if (m_recursive) {
                deleteFboLater = true;
                delete m_secondaryFbo;
                m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format);
                funcs->glBindTexture(GL_TEXTURE_2D, m_secondaryFbo->texture());
                updateBindOptions(true);
                m_depthStencilBuffer = m_context->depthStencilBufferForFbo(m_secondaryFbo);
            } else {
                delete m_fbo;
                delete m_secondaryFbo;
                m_fbo = new QOpenGLFramebufferObject(m_size, format);
                m_secondaryFbo = 0;
                funcs->glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
                updateBindOptions(true);
                m_depthStencilBuffer = m_context->depthStencilBufferForFbo(m_fbo);
            }
        }
    }

    if (m_recursive && !m_secondaryFbo) {
        // m_fbo already created, m_recursive was just set.
        Q_ASSERT(m_fbo);
        Q_ASSERT(!m_multisampling);

        m_secondaryFbo = new QOpenGLFramebufferObject(m_size, m_fbo->format());
        funcs->glBindTexture(GL_TEXTURE_2D, m_secondaryFbo->texture());
        updateBindOptions(true);
    }

    // Render texture.
    root->markDirty(QSGNode::DirtyForceUpdate); // Force matrix, clip and opacity update.
    m_renderer->nodeChanged(root, QSGNode::DirtyForceUpdate); // Force render list update.

#ifdef QSG_DEBUG_FBO_OVERLAY
    if (qmlFboOverlay()) {
        if (!m_debugOverlay)
            m_debugOverlay = new QSGSimpleRectNode();
        m_debugOverlay->setRect(QRectF(0, 0, m_size.width(), m_size.height()));
        m_debugOverlay->setColor(QColor(0xff, 0x00, 0x80, 0x40));
        root->appendChildNode(m_debugOverlay);
    }
#endif

    m_dirtyTexture = false;

    m_renderer->setDeviceRect(m_size);
    m_renderer->setViewportRect(m_size);
    QRectF mirrored(m_mirrorHorizontal ? m_rect.right() : m_rect.left(),
                    m_mirrorVertical ? m_rect.bottom() : m_rect.top(),
                    m_mirrorHorizontal ? -m_rect.width() : m_rect.width(),
                    m_mirrorVertical ? -m_rect.height() : m_rect.height());
    m_renderer->setProjectionMatrixToRect(mirrored);
    m_renderer->setClearColor(Qt::transparent);

    if (m_multisampling) {
        m_renderer->renderScene(BindableFbo(m_secondaryFbo, m_depthStencilBuffer.data()));

        if (deleteFboLater) {
            delete m_fbo;
            QOpenGLFramebufferObjectFormat format;
            format.setInternalTextureFormat(m_format);
            format.setAttachment(QOpenGLFramebufferObject::NoAttachment);
            format.setMipmap(m_mipmap);
            format.setSamples(0);
            m_fbo = new QOpenGLFramebufferObject(m_size, format);
            funcs->glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
            updateBindOptions(true);
        }

        QRect r(QPoint(), m_size);
        QOpenGLFramebufferObject::blitFramebuffer(m_fbo, r, m_secondaryFbo, r);
    } else {
        if (m_recursive) {
            m_renderer->renderScene(BindableFbo(m_secondaryFbo, m_depthStencilBuffer.data()));

            if (deleteFboLater) {
                delete m_fbo;
                QOpenGLFramebufferObjectFormat format;
                format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
                format.setInternalTextureFormat(m_format);
                format.setMipmap(m_mipmap);
                m_fbo = new QOpenGLFramebufferObject(m_size, format);
                funcs->glBindTexture(GL_TEXTURE_2D, m_fbo->texture());
                updateBindOptions(true);
            }
            qSwap(m_fbo, m_secondaryFbo);
        } else {
            m_renderer->renderScene(BindableFbo(m_fbo, m_depthStencilBuffer.data()));
        }
    }

    if (m_mipmap) {
        funcs->glBindTexture(GL_TEXTURE_2D, textureId());
        funcs->glGenerateMipmap(GL_TEXTURE_2D);
    }

    root->markDirty(QSGNode::DirtyForceUpdate); // Force matrix, clip, opacity and render list update.

#ifdef QSG_DEBUG_FBO_OVERLAY
    if (qmlFboOverlay())
        root->removeChildNode(m_debugOverlay);
#endif
    if (m_recursive)
        markDirtyTexture(); // Continuously update if 'live' and 'recursive'.
}