static PyObject *meth_QSGMaterialShader_program(PyObject *sipSelf, PyObject *sipArgs) { PyObject *sipParseErr = NULL; { QSGMaterialShader *sipCpp; if (sipParseArgs(&sipParseErr, sipArgs, "B", &sipSelf, sipType_QSGMaterialShader, &sipCpp)) { QOpenGLShaderProgram*sipRes; sipRes = sipCpp->program(); return sipConvertFromType(sipRes,sipType_QOpenGLShaderProgram,NULL); } } /* Raise an exception if the arguments couldn't be parsed. */ sipNoMethod(sipParseErr, sipName_QSGMaterialShader, sipName_program, doc_QSGMaterialShader_program); return NULL; }
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