void QSGNode::insertChildNodeBefore(QSGNode *node, QSGNode *before) { //Q_ASSERT_X(!m_children.contains(node), "QSGNode::insertChildNodeBefore", "QSGNode is already a child!"); Q_ASSERT_X(!node->m_parent, "QSGNode::insertChildNodeBefore", "QSGNode already has a parent"); Q_ASSERT_X(before && before->m_parent == this, "QSGNode::insertChildNodeBefore", "The parent of \'before\' is wrong"); #ifndef QT_NO_DEBUG if (node->type() == QSGNode::GeometryNodeType) { QSGGeometryNode *g = static_cast<QSGGeometryNode *>(node); Q_ASSERT_X(g->material(), "QSGNode::insertChildNodeBefore", "QSGGeometryNode is missing material"); Q_ASSERT_X(g->geometry(), "QSGNode::insertChildNodeBefore", "QSGGeometryNode is missing geometry"); } #endif QSGNode *previous = before->m_previousSibling; if (previous) previous->m_nextSibling = node; else m_firstChild = node; node->m_previousSibling = previous; node->m_nextSibling = before; before->m_previousSibling = node; node->m_parent = this; node->markDirty(DirtyNodeAdded); }
void compareSelectionNode(QSGNode *node, const QRectF &rect, int selectionId) { QSGGeometryNode *geometryNode = static_cast<QSGGeometryNode *>(node); QSGGeometry *geometry = geometryNode->geometry(); QCOMPARE(geometry->vertexCount(), 4); QCOMPARE(geometry->drawingMode(), (GLenum)GL_TRIANGLE_STRIP); OpaqueColoredPoint2DWithSize *data = static_cast<OpaqueColoredPoint2DWithSize *>(geometry->vertexData()); float *lowerLeft = reinterpret_cast<float *>(data); float *lowerRight = reinterpret_cast<float *>(++data); float *upperLeft = reinterpret_cast<float *>(++data); float *upperRight = reinterpret_cast<float *>(++data); QCOMPARE(QRectF(QPointF(upperLeft[0], upperLeft[1]), QPointF(lowerRight[0], lowerRight[1])), rect); QCOMPARE(lowerRight[0], upperRight[0]); QCOMPARE(lowerRight[1], lowerLeft[1]); QCOMPARE(upperLeft[0], lowerLeft[0]); QCOMPARE(upperLeft[1], upperRight[1]); QCOMPARE(int(lowerLeft[4]), selectionId); QCOMPARE(int(lowerRight[4]), selectionId); QCOMPARE(int(upperLeft[4]), selectionId); QCOMPARE(int(upperRight[4]), selectionId); TimelineItemsMaterial *material = static_cast<TimelineItemsMaterial *>( geometryNode->material()); QVERIFY(!(material->flags() & QSGMaterial::Blending)); }
void QSGNode::insertChildNodeAfter(QSGNode *node, QSGNode *after) { //Q_ASSERT_X(!m_children.contains(node), "QSGNode::insertChildNodeAfter", "QSGNode is already a child!"); Q_ASSERT_X(!node->m_parent, "QSGNode::insertChildNodeAfter", "QSGNode already has a parent"); Q_ASSERT_X(after && after->m_parent == this, "QSGNode::insertChildNodeAfter", "The parent of \'after\' is wrong"); #ifndef QT_NO_DEBUG if (node->type() == QSGNode::GeometryNodeType) { QSGGeometryNode *g = static_cast<QSGGeometryNode *>(node); Q_ASSERT_X(g->material(), "QSGNode::insertChildNodeAfter", "QSGGeometryNode is missing material"); Q_ASSERT_X(g->geometry(), "QSGNode::insertChildNodeAfter", "QSGGeometryNode is missing geometry"); } #endif QSGNode *next = after->m_nextSibling; if (next) next->m_previousSibling = node; else m_lastChild = node; node->m_nextSibling = next; node->m_previousSibling = after; after->m_nextSibling = node; node->m_parent = this; node->markDirty(DirtyNodeAdded); }
QSGNode *PhosphorRender::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) { if (!m_ybuffer) { return 0; } QSGGeometryNode *node = 0; QSGGeometry *geometry = 0; Material *material = 0; unsigned n_points; if (m_xbuffer) { n_points = std::min(m_xbuffer->size(), m_ybuffer->size()); } else { n_points = m_ybuffer->countPointsBetween(m_xmin, m_xmax); } n_points = std::min(n_points,(unsigned) 65767); if (!oldNode) { node = new QSGGeometryNode; geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), n_points); geometry->setDrawingMode(GL_POINTS); node->setGeometry(geometry); node->setFlag(QSGNode::OwnsGeometry); material = new Material; material->setFlag(QSGMaterial::Blending); node->setMaterial(material); node->setFlag(QSGNode::OwnsMaterial); } else { node = static_cast<QSGGeometryNode *>(oldNode); geometry = node->geometry(); geometry->allocate(n_points); geometry->setLineWidth(m_pointSize); material = static_cast<Material*>(node->material()); } QRectF bounds = boundingRect(); material->transformation.setToIdentity(); material->transformation.scale(bounds.width()/(m_xmax - m_xmin), bounds.height()/(m_ymin - m_ymax)); material->transformation.translate(-m_xmin, -m_ymax); material->pointSize = m_pointSize; material->color = m_color; auto verticies = geometry->vertexDataAsPoint2D(); if (m_xbuffer) { for (unsigned i=0; i<n_points; i++) { verticies[i].set(m_xbuffer->get(i), m_ybuffer->get(i)); } } else { m_ybuffer->toVertexData(m_xmin, m_xmax, verticies, n_points); } node->markDirty(QSGNode::DirtyGeometry | QSGNode::DirtyMaterial); return node; }
/*------------------------------------------------------------------------------ | OMX_CameraSurfaceElement::updatePaintNode +-----------------------------------------------------------------------------*/ QSGNode* OMX_CameraSurfaceElement::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData*) { QSGGeometryNode* node = 0; QSGGeometry* geometry = 0; if (!oldNode) { // Create the node. node = new QSGGeometryNode; geometry = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4); geometry->setDrawingMode(GL_TRIANGLE_STRIP); node->setGeometry(geometry); node->setFlag(QSGNode::OwnsGeometry); // TODO: Who is freeing this? // TODO: I cannot know the texture size here. QSGOpaqueTextureMaterial* material = new QSGOpaqueTextureMaterial; m_sgtexture = new OMX_SGTexture(0, QSize(640, 480)); material->setTexture(m_sgtexture); node->setMaterial(material); node->setFlag(QSGNode::OwnsMaterial); QtConcurrent::run(this, &OMX_CameraSurfaceElement::videoAcquire); } else { node = static_cast<QSGGeometryNode*>(oldNode); geometry = node->geometry(); geometry->allocate(4); // Update texture in the node if needed. QSGOpaqueTextureMaterial* material = (QSGOpaqueTextureMaterial*)node->material(); QElapsedTimer timer; timer.start(); QSGTexture* texture = window()->createTextureFromImage(m_frame); LOG_VERBOSE(LOG_TAG, "Timer tex: %lld.", timer.elapsed()); material->setTexture(texture); m_semAcquire.release(); #if 0 if (m_texture != (GLuint)material->texture()->textureId()) { // TODO: Does setTextureId frees the prev texture? // TODO: I should the given the texture size. LOG_ERROR(LOG_TAG, "Updating texture to %u!", m_texture); material = new QSGOpaqueTextureMaterial; m_sgtexture->setTexture(m_texture, QSize(1920, 1080)); } #endif } // Create the vertices and map to texture. QRectF bounds = boundingRect(); QSGGeometry::TexturedPoint2D* vertices = geometry->vertexDataAsTexturedPoint2D(); vertices[0].set(bounds.x(), bounds.y() + bounds.height(), 0.0f, 0.0f); vertices[1].set(bounds.x() + bounds.width(), bounds.y() + bounds.height(), 1.0f, 0.0f); vertices[2].set(bounds.x(), bounds.y(), 0.0f, 1.0f); vertices[3].set(bounds.x() + bounds.width(), bounds.y(), 1.0f, 1.0f); return node; }
QSGNode * QQuickLineItem::updatePaintNode(QSGNode *prev_node, UpdatePaintNodeData *upd_data) { Q_UNUSED(upd_data); QSGGeometryNode * node = static_cast<QSGGeometryNode*>(prev_node); QSGGeometry * geometry = NULL; QSGFlatColorMaterial * material = NULL; if(!node) { // http://qt-project.org/doc/qt-5/qsggeometrynode.html node = new QSGGeometryNode; geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(),4); 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); } else { geometry = node->geometry(); geometry->allocate(4); // we have to call allocate to invalidate // the older vertex buffer material = static_cast<QSGFlatColorMaterial*>(node->material()); } // geometry std::vector<QPointF> list_vx; if(!calcTriStrip(list_vx)) { list_vx.clear(); list_vx.push_back(QPointF(0,0)); list_vx.push_back(QPointF(0,0)); list_vx.push_back(QPointF(0,0)); list_vx.push_back(QPointF(0,0)); } QSGGeometry::Point2D * vertices = geometry->vertexDataAsPoint2D(); for(size_t i=0; i < list_vx.size(); i++) { vertices[i].set(list_vx[i].x(), list_vx[i].y()); } node->markDirty(QSGNode::DirtyGeometry); // material material->setColor(m_color); node->markDirty(QSGNode::DirtyMaterial); return node; }
//! [4] QSGNode *BezierCurve::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) { QSGGeometryNode *node = 0; QSGGeometry *geometry = 0; if (!oldNode) { node = new QSGGeometryNode; //! [4] //! [5] geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), m_segmentCount); geometry->setLineWidth(2); geometry->setDrawingMode(GL_LINE_STRIP); node->setGeometry(geometry); node->setFlag(QSGNode::OwnsGeometry); //! [5] //! [6] QSGFlatColorMaterial *material = new QSGFlatColorMaterial; material->setColor(QColor(255, 0, 0)); node->setMaterial(material); node->setFlag(QSGNode::OwnsMaterial); //! [6] //! [7] } else { node = static_cast<QSGGeometryNode *>(oldNode); geometry = node->geometry(); geometry->allocate(m_segmentCount); } //! [7] //! [8] QRectF bounds = boundingRect(); QSGGeometry::Point2D *vertices = geometry->vertexDataAsPoint2D(); for (int i = 0; i < m_segmentCount; ++i) { qreal t = i / qreal(m_segmentCount - 1); qreal invt = 1 - t; QPointF pos = invt * invt * invt * m_p1 + 3 * invt * invt * t * m_p2 + 3 * invt * t * t * m_p3 + t * t * t * m_p4; float x = bounds.x() + pos.x() * bounds.width(); float y = bounds.y() + pos.y() * bounds.height(); vertices[i].set(x, y); } node->markDirty(QSGNode::DirtyGeometry); //! [8] //! [9] return node; }
Point2DWithOffset *BindlingLoopsGeometry::vertexData() { QSGGeometry *geometry = node->geometry(); Q_ASSERT(geometry->attributeCount() == 2); Q_ASSERT(geometry->sizeOfVertex() == sizeof(Point2DWithOffset)); const QSGGeometry::Attribute *attributes = geometry->attributes(); Q_ASSERT(attributes[0].position == 0); Q_ASSERT(attributes[0].tupleSize == 2); Q_ASSERT(attributes[0].type == GL_FLOAT); Q_ASSERT(attributes[1].position == 1); Q_ASSERT(attributes[1].tupleSize == 2); Q_ASSERT(attributes[1].type == GL_FLOAT); Q_UNUSED(attributes); return static_cast<Point2DWithOffset *>(geometry->vertexData()); }
QSGNode *QPScrollingCurve::updatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *) { QSGGeometryNode *node = 0; QSGGeometry *geometry = 0; QSGFlatColorMaterial *material = 0; if (!oldNode) { node = new QSGGeometryNode; geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), m_data.size()); geometry->setLineWidth(2); geometry->setDrawingMode(GL_LINE_STRIP); node->setGeometry(geometry); node->setFlag(QSGNode::OwnsGeometry); material = new QSGFlatColorMaterial; material->setColor(m_color); node->setMaterial(material); node->setFlag(QSGNode::OwnsMaterial); node->markDirty(QSGNode::DirtyMaterial); } else { node = static_cast<QSGGeometryNode *>(oldNode); geometry = node->geometry(); geometry->allocate(m_data.size()); material = static_cast<QSGFlatColorMaterial*>(node->material()); if (material->color() != m_color) { material->setColor(m_color); node->markDirty(QSGNode::DirtyMaterial); } } QSGGeometry::Point2D *vertices = geometry->vertexDataAsPoint2D(); for (uint i = 0; i < m_data.size(); ++i) { QPointF p(i, m_data[i]); vertices[i].set(p.x(), p.y()); } node->markDirty(QSGNode::DirtyGeometry); return node; }
QSGNode* drawRect(const QRect& rect, QSGNode* oldNode) { QSGGeometryNode* node; if (oldNode == nullptr) { node = new QSGGeometryNode; QSGGeometry* geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 8); geometry->setDrawingMode(GL_LINES); geometry->setLineWidth(1); QSGFlatColorMaterial* material = new QSGFlatColorMaterial; material->setColor(QGuiApplication::palette().color(QPalette::Normal, QPalette::WindowText)); node->setGeometry(geometry); node->setFlag(QSGNode::OwnsGeometry); node->setMaterial(material); node->setFlag(QSGNode::OwnsMaterial); } else { node = static_cast<QSGGeometryNode*>(oldNode); } QSGGeometry* geometry = node->geometry(); // FIXME: check if these really have to be updated geometry->vertexDataAsPoint2D()[0].set(rect.topLeft().x(), rect.topLeft().y()); geometry->vertexDataAsPoint2D()[1].set(rect.topRight().x(), rect.topRight().y()); geometry->vertexDataAsPoint2D()[2].set(rect.topRight().x(), rect.topRight().y()); geometry->vertexDataAsPoint2D()[3].set(rect.bottomRight().x(), rect.bottomRight().y()); geometry->vertexDataAsPoint2D()[4].set(rect.bottomRight().x(), rect.bottomRight().y()); geometry->vertexDataAsPoint2D()[5].set(rect.bottomLeft().x(), rect.bottomLeft().y()); geometry->vertexDataAsPoint2D()[6].set(rect.bottomLeft().x(), rect.bottomLeft().y()); geometry->vertexDataAsPoint2D()[7].set(rect.topLeft().x(), rect.topLeft().y()); node->markDirty(QSGNode::DirtyGeometry); return node; }
void QSGNode::appendChildNode(QSGNode *node) { //Q_ASSERT_X(!m_children.contains(node), "QSGNode::appendChildNode", "QSGNode is already a child!"); Q_ASSERT_X(!node->m_parent, "QSGNode::appendChildNode", "QSGNode already has a parent"); #ifndef QT_NO_DEBUG if (node->type() == QSGNode::GeometryNodeType) { QSGGeometryNode *g = static_cast<QSGGeometryNode *>(node); Q_ASSERT_X(g->material(), "QSGNode::appendChildNode", "QSGGeometryNode is missing material"); Q_ASSERT_X(g->geometry(), "QSGNode::appendChildNode", "QSGGeometryNode is missing geometry"); } #endif if (m_lastChild) m_lastChild->m_nextSibling = node; else m_firstChild = node; node->m_previousSibling = m_lastChild; m_lastChild = node; node->m_parent = this; node->markDirty(DirtyNodeAdded); }
TimelineRenderPass::State *TimelineSelectionRenderPass::update( const TimelineAbstractRenderer *renderer, const TimelineRenderState *parentState, State *oldState, int firstIndex, int lastIndex, bool stateChanged, qreal spacing) const { Q_UNUSED(stateChanged); const TimelineModel *model = renderer->model(); if (!model || model->isEmpty()) return oldState; TimelineSelectionRenderPassState *state; if (oldState == 0) state = new TimelineSelectionRenderPassState; else state = static_cast<TimelineSelectionRenderPassState *>(oldState); int selectedItem = renderer->selectedItem(); QSGGeometryNode *node = static_cast<QSGGeometryNode *>(model->expanded() ? state->expandedOverlay() : state->collapsedOverlay()); if (selectedItem != -1 && selectedItem >= firstIndex && selectedItem < lastIndex) { qreal top = 0; qreal height = 0; if (model->expanded()) { int row = model->expandedRow(selectedItem); int rowHeight = model->expandedRowHeight(row); height = rowHeight * model->relativeHeight(selectedItem); top = (model->expandedRowOffset(row) + rowHeight) - height; } else { int row = model->collapsedRow(selectedItem); height = TimelineModel::defaultRowHeight() * model->relativeHeight(selectedItem); top = TimelineModel::defaultRowHeight() * (row + 1) - height; } qint64 startTime = qBound(parentState->start(), model->startTime(selectedItem), parentState->end()); qint64 endTime = qBound(parentState->start(), model->endTime(selectedItem), parentState->end()); qint64 left = startTime - parentState->start(); qint64 width = endTime - startTime; // Construct from upper left and lower right for better precision. When constructing from // left and width the error on the left border is inherited by the right border. Like this // they're independent. QRectF position(left * parentState->scale(), top, width * parentState->scale(), height); QColor itemColor = model->color(selectedItem); uchar red = itemColor.red(); uchar green = itemColor.green(); uchar blue = itemColor.blue(); int selectionId = model->selectionId(selectedItem); OpaqueColoredPoint2DWithSize *v = OpaqueColoredPoint2DWithSize::fromVertexData( node->geometry()); v[0].set(position.left(), position.bottom(), -position.width(), -position.height(), selectionId, red, green, blue); v[1].set(position.right(), position.bottom(), position.width(), -position.height(), selectionId, red, green, blue); v[2].set(position.left(), position.top(), -position.width(), position.height(), selectionId, red, green, blue); v[3].set(position.right(), position.top(), position.width(), position.height(), selectionId, red, green, blue); state->material()->setSelectionColor(renderer->selectionLocked() ? QColor(96,0,255) : Qt::blue); state->material()->setSelectedItem(selectionId); state->material()->setScale(QVector2D(spacing / parentState->scale(), 1)); node->markDirty(QSGNode::DirtyMaterial | QSGNode::DirtyGeometry); } else { OpaqueColoredPoint2DWithSize *v = OpaqueColoredPoint2DWithSize::fromVertexData( node->geometry()); for (int i = 0; i < 4; ++i) v[i].set(0, 0, 0, 0, 0, 0, 0, 0); node->markDirty(QSGNode::DirtyGeometry); } return state; }
QSGNode *GraphConnection::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) { if (m_source == m_sink) return oldNode; QSGGeometryNode *node = 0; QSGGeometry *geometry = 0; QPointF p1, p2, p3, p4; p1.setX(m_source.x()); p1.setY(m_source.y()); p4.setX(m_sink.x()); p4.setY(m_sink.y()); p2.setX(p1.x()); p3.setX(p4.x()); if (p1.y() < p4.y()) { p2.setY(p1.y() * 0.75 + p4.y() * 0.25); p3.setY(p4.y() * 0.75 + p1.y() * 0.25); } else { p2.setY(p1.y() - (p4.y()-p1.y())*0.25); p3.setY(p4.y() + (p4.y()-p1.y())*0.25); } // quick 'n' dirty estimation of bezier length // http://steve.hollasch.net/cgindex/curves/cbezarclen.html qreal l1 = (QVector2D(p2)-QVector2D(p1)).length() + (QVector2D(p3)-QVector2D(p2)).length() + (QVector2D(p4)-QVector2D(p3)).length(); qreal l0 = (QVector2D(p4)-QVector2D(p1)).length(); qreal length = 0.5*l0 + 0.5*l1; int segmentCount = length; if (!oldNode) { node = new QSGGeometryNode; geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), segmentCount); geometry->setLineWidth(2); geometry->setDrawingMode(GL_LINE_STRIP); node->setGeometry(geometry); node->setFlag(QSGNode::OwnsGeometry); QSGFlatColorMaterial *material = new QSGFlatColorMaterial; material->setColor(QColor(0, 0, 0)); node->setMaterial(material); node->setFlag(QSGNode::OwnsMaterial); } else { node = static_cast<QSGGeometryNode *>(oldNode); geometry = node->geometry(); geometry->allocate(segmentCount); } QRectF bounds = boundingRect(); QSGGeometry::Point2D *vertices = geometry->vertexDataAsPoint2D(); for (int i = 0; i < segmentCount; ++i) { qreal t = i / qreal(segmentCount - 1); qreal invt = 1 - t; // Bezier QPointF pos = invt * invt * invt * p1 + 3 * invt * invt * t * p2 + 3 * invt * t * t * p3 + t * t * t * p4; float x = pos.x(); float y = pos.y(); vertices[i].set(x, y); } return node; }
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* MDeclarativeStatusBar::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData*) { QSGGeometryNode* node = static_cast<QSGGeometryNode*>(oldNode); if (!node) { node = new QSGGeometryNode; node->setFlags(QSGNode::OwnsGeometry | QSGNode::OwnsMaterial | QSGNode::OwnsOpaqueMaterial); node->setGeometry(new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)); } if (!sharedPixmapHandle) { node->setMaterial(new QSGFlatColorMaterial); node->setOpaqueMaterial(new QSGFlatColorMaterial); node->markDirty(QSGNode::DirtyMaterial); return node; } if (!sharedTexture || updateSharedTexture) { node->setMaterial(new QSGTextureMaterial); node->setOpaqueMaterial(new QSGTextureMaterial); #if defined(HAVE_XLIB) MDeclarativeScreen* screen = MDeclarativeScreen::instance(); #if defined(QT_OPENGL_ES_2) static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES"); static PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress("eglCreateImageKHR"); static PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress("eglDestroyImageKHR"); static PFNEGLQUERYIMAGENOKPROC eglQueryImageNOK = (PFNEGLQUERYIMAGENOKPROC) eglGetProcAddress("eglQueryImageNOK"); const EGLint attribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE }; EGLDisplay eglDpy = eglGetDisplay((EGLNativeDisplayType)screen->display()); EGLImageKHR img = eglCreateImageKHR(eglDpy, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, (EGLClientBuffer)sharedPixmapHandle, attribs); GLuint textureId; glGenTextures(1, &textureId); glBindTexture(GL_TEXTURE_2D, textureId); glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)img); GLint width = 0; GLint height = 0; eglQueryImageNOK(eglDpy, img, EGL_WIDTH, &width); eglQueryImageNOK(eglDpy, img, EGL_HEIGHT, &height); sharedTexture.reset(canvas()->createTextureFromId(textureId, QSize(width, height), QQuickCanvas::TextureOwnsGLTexture)); eglDestroyImageKHR(eglDpy, img); #else Display* dpy = screen->display(); Window dummy1; int x, y; unsigned int width, height, borderwidth, depth; XGetGeometry(dpy, sharedPixmapHandle, &dummy1, &x, &y, &width, &height, &borderwidth, &depth); XImage* xi = XGetImage(dpy, sharedPixmapHandle, 0, 0, width, height, ULONG_MAX, ZPixmap); QImage img = MX11Wrapper::qimageFromXImage(xi); XDestroyImage(xi); sharedTexture.reset(canvas()->createTextureFromImage(img)); #endif #endif // HAVE_XLIB static_cast<QSGTextureMaterial*>(node->material())->setTexture(sharedTexture.data()); static_cast<QSGOpaqueTextureMaterial*>(node->opaqueMaterial())->setTexture(sharedTexture.data()); node->markDirty(QSGNode::DirtyMaterial); updateSharedTexture = false; } QRectF sourceRect; sourceRect = QRectF(0, 0, width(), height()); if (mOrientation == MDeclarativeScreen::Portrait || mOrientation == MDeclarativeScreen::PortraitInverted) sourceRect.moveTop(height()); sourceRect = sharedTexture.data()->convertToNormalizedSourceRect(sourceRect); QRect targetRect(x(), y(), width(), height()); QSGGeometry::updateTexturedRectGeometry(node->geometry(), targetRect, sourceRect); node->markDirty(QSGNode::DirtyGeometry); return node; }
void tst_TimelineNotesRenderPass::update() { const TimelineNotesRenderPass *inst = TimelineNotesRenderPass::instance(); TimelineAbstractRenderer renderer; TimelineRenderState parentState(0, 8, 1, 1); TimelineRenderPass::State *nullState = 0; QSGNode *nullNode = 0; TimelineRenderPass::State *result = inst->update(&renderer, &parentState, 0, 0, 0, true, 1); QCOMPARE(result, nullState); DummyModel model; DummyModel otherModel(13); TimelineNotesModel notes; notes.addTimelineModel(&model); notes.addTimelineModel(&otherModel); result = inst->update(&renderer, &parentState, 0, 0, 0, true, 1); QCOMPARE(result, nullState); renderer.setModel(&model); result = inst->update(&renderer, &parentState, 0, 0, 0, true, 1); QCOMPARE(result, nullState); renderer.setNotes(¬es); model.loadData(); result = inst->update(&renderer, &parentState, 0, 0, 0, true, 1); QVERIFY(result != nullState); // The notes renderer creates a collapsed overlay and expanded nodes per row. QVERIFY(result->collapsedOverlay() != nullNode); QCOMPARE(result->expandedOverlay(), nullNode); QCOMPARE(result->expandedRows().count(), 1); QCOMPARE(result->collapsedRows().count(), 0); TimelineRenderPass::State *result2 = inst->update(&renderer, &parentState, result, 0, 0, false, 1); QCOMPARE(result2, result); notes.add(12, 0, QLatin1String("x")); notes.add(12, 9, QLatin1String("xx")); notes.add(13, 0, QLatin1String("y")); QVERIFY(renderer.notesDirty()); result = inst->update(&renderer, &parentState, result, 0, 0, true, 1); QVERIFY(result != nullState); QSGGeometryNode *node = static_cast<QSGGeometryNode *>(result->expandedRows()[0]); QSGMaterial *material1 = node->material(); QVERIFY(material1 != 0); QCOMPARE(node->geometry()->vertexCount(), 2); node = static_cast<QSGGeometryNode *>(result->collapsedOverlay()); QSGMaterial *material2 = node->material(); QCOMPARE(node->geometry()->vertexCount(), 2); QVERIFY(material2 != 0); QCOMPARE(material1->type(), material2->type()); QSGMaterialShader *shader1 = material1->createShader(); QVERIFY(shader1 != 0); QSGMaterialShader *shader2 = material2->createShader(); QVERIFY(shader2 != 0); QCOMPARE(shader1->attributeNames(), shader2->attributeNames()); delete shader1; delete shader2; parentState.setPassState(0, result); parentState.assembleNodeTree(&model, 1, 1); runSceneGraphTest(parentState.collapsedOverlayRoot()); runSceneGraphTest(parentState.expandedRowRoot()); }
QSGNode* OMX_MediaProcessorElement::updatePaintNode(QSGNode*, UpdatePaintNodeData*) { if (!m_texProvider) { m_texProvider = new OMX_TextureProviderQQuickItem(this); m_mediaProc = new OMX_MediaProcessor(m_texProvider); connect(m_mediaProc, SIGNAL(playbackCompleted()), this, SIGNAL(playbackCompleted())); connect(m_mediaProc, SIGNAL(playbackStarted()), this, SIGNAL(playbackStarted())); // Open if filepath is set. // TODO: Handle errors. if (!m_source.isNull()) { //if (QFile(m_source).exists()) { if (openMedia(m_source)) m_mediaProc->play(); //} //else { LOG_WARNING(LOG_TAG, "File does not exist."); //} } } return NULL; #if 0 QSGGeometryNode* node = 0; QSGGeometry* geometry = 0; if (!oldNode) { // Create the node. node = new QSGGeometryNode; geometry = new QSGGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4); geometry->setDrawingMode(GL_TRIANGLE_STRIP); node->setGeometry(geometry); node->setFlag(QSGNode::OwnsGeometry); // TODO: Who is freeing this? // TODO: I cannot know the texture size here. QSGOpaqueTextureMaterial* material = new QSGOpaqueTextureMaterial; m_sgtexture = new OMX_SGTexture(m_texture, QSize(1920, 1080)); material->setTexture(m_sgtexture); node->setMaterial(material); node->setFlag(QSGNode::OwnsMaterial); #ifdef ENABLE_VIDEO_PROCESSOR QPlatformNativeInterface* nativeInterface = QGuiApplicationPrivate::platformIntegration()->nativeInterface(); Q_ASSERT(nativeInterface); EGLDisplay eglDisplay = nativeInterface->nativeResourceForIntegration("egldisplay"); EGLContext eglContext = nativeInterface->nativeResourceForContext( "eglcontext", QOpenGLContext::currentContext() ); #endif // Provider MUST be built in this thread. m_provider = new OMX_TextureProviderQQuickItem(this); #ifdef ENABLE_VIDEO_PROCESSOR m_videoProc = new OMX_VideoProcessor(eglDisplay, eglContext, m_provider); connect(m_videoProc, SIGNAL(textureReady(uint)), this, SLOT(onTextureChanged(uint))); if (!m_source.isNull()) m_videoProc->setVideoPath(m_source); if (m_playScheduled) { m_timer->start(30); m_videoProc->play(); } #elif ENABLE_MEDIA_PROCESSOR LOG_VERBOSE(LOG_TAG, "Starting video using media processor..."); m_mediaProc = new OMX_MediaProcessor(m_provider); m_mediaProc->setFilename("/home/pi/usb/Cars2.mkv", m_texture); //if (m_playScheduled) { m_timer->start(40); m_mediaProc->play(); //} #else LOG_VERBOSE(LOG_TAG, "Starting video..."); QtConcurrent::run(&startVideo, m_provider, this); m_timer->start(30); #endif } else { node = static_cast<QSGGeometryNode*>(oldNode); geometry = node->geometry(); geometry->allocate(4); // Update texture in the node if needed. QSGOpaqueTextureMaterial* material = (QSGOpaqueTextureMaterial*)node->material(); if (m_texture != (GLuint)material->texture()->textureId()) { // TODO: Does setTextureId frees the prev texture? // TODO: I should the given the texture size. LOG_ERROR(LOG_TAG, "Updating texture to %u!", m_texture); material = new QSGOpaqueTextureMaterial; m_sgtexture->setTexture(m_texture, QSize(1920, 1080)); } } // Create the vertices and map to texture. QRectF bounds = boundingRect(); QSGGeometry::TexturedPoint2D* vertices = geometry->vertexDataAsTexturedPoint2D(); vertices[0].set(bounds.x(), bounds.y() + bounds.height(), 0.0f, 0.0f); vertices[1].set(bounds.x() + bounds.width(), bounds.y() + bounds.height(), 1.0f, 0.0f); vertices[2].set(bounds.x(), bounds.y(), 0.0f, 1.0f); vertices[3].set(bounds.x() + bounds.width(), bounds.y(), 1.0f, 1.0f); return node; #endif }
QSGNode* NodeConnectionLines::updatePaintNode(QSGNode* oldNode, UpdatePaintNodeData*) { if (!m_nodeObject) return nullptr; const QVector<QPointer<NodeBase>>& connectedNodes = m_nodeObject->getConnectedNodes(); int connectionCount = connectedNodes.size(); // -------------------- Prepare QSG Nodes: QSGNode* parentNode = oldNode; if (!oldNode) { parentNode = new QSGNode(); } else { // update color in case it changed: // FIXME: is there a more efficient way to do this? for (int i=0; i<parentNode->childCount(); ++i) { QSGGeometryNode* childNode = static_cast<QSGGeometryNode*>(parentNode->childAtIndex(i)); if (!childNode) continue; QSGFlatColorMaterial* material = static_cast<QSGFlatColorMaterial*>(childNode->material()); if (!material) continue; material->setColor(m_color); } } // adapt child count: int childCount = parentNode->childCount(); if (childCount < connectionCount) { for (int i=0; i<(connectionCount - childCount); ++i) { 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(m_color); node->setMaterial(material); node->setFlag(QSGNode::OwnsMaterial); parentNode->appendChildNode(node); } } else if (childCount > connectionCount) { for (int i=0; i<(childCount - connectionCount); ++i) { parentNode->removeChildNode(parentNode->childAtIndex(0)); } } Q_ASSERT(parentNode->childCount() == connectionCount); // calculate common start point: const QPointF p0(width(), height() / 2); double widthOffset = m_lineWidth / 2; //const QPointF posInScene = mapToScene(QPointF(0, 0)); for (int i=0; i<connectionCount; ++i) { NodeBase* otherNode = connectedNodes[i]; if (!otherNode) continue; QQuickItem* otherGuiItem = otherNode->getGuiItem(); if (!otherGuiItem) continue; const QPointF p3 = mapFromItem(otherGuiItem, QPointF(-otherGuiItem->width() / 2, otherGuiItem->height() / 2)); int handleLength = std::max(50, std::min(int(p3.x() - p0.x()), 80)); const QPointF p1(p0.x() + handleLength, p0.y()); const QPointF p2(p3.x() - handleLength, p3.y()); // calculate reasonable segment count: int segmentCount = qMax(16.0, qMin(qAbs(p3.y() - p0.y()) / 25, 50.0)); int verticesCount = segmentCount * 2; QSGGeometryNode* qsgNode = static_cast<QSGGeometryNode*>(parentNode->childAtIndex(i)); if (!qsgNode) continue; QSGGeometry* geometry = qsgNode->geometry(); if (!geometry) continue; geometry->allocate(verticesCount); QSGGeometry::Point2D* vertices = geometry->vertexDataAsPoint2D(); // triangulate cubic bezier curve: for (int i = 0; i < segmentCount; ++i) { // t is the position on the line: const qreal t = i / qreal(segmentCount - 1); // pos is the point on the curve at "t": const QPointF pos = calculateBezierPoint(t, p0, p1, p2, p3); // normal is the normal vector at that point const QPointF normal = normalFromTangent(calculateBezierTangent(t, p0, p1, p2, p3)); // first is a point offsetted in the normal direction by lineWidth / 2 from pos const QPointF first = pos - normal * widthOffset; // ssecond is a point offsetted in the negative normal direction by lineWidth / 2 from pos const QPointF second = pos + normal * widthOffset; // add first and second as vertices to this geometry: vertices[i*2].set(first.x(), first.y()); vertices[i*2+1].set(second.x(), second.y()); } // tell Scene Graph that this items needs to be drawn: qsgNode->markDirty(QSGNode::DirtyGeometry); } return parentNode; }