void Renderer::updateMatrices(QSGNode *node, QSGTransformNode *xform)
{
    if (node->isSubtreeBlocked())
        return;

    if (node->type() == QSGNode::TransformNodeType) {
        QSGTransformNode *tn = static_cast<QSGTransformNode *>(node);
        if (xform)
            tn->setCombinedMatrix(xform->combinedMatrix() * tn->matrix());
        else
            tn->setCombinedMatrix(tn->matrix());
        QSGNODE_TRAVERSE(node)
        updateMatrices(child, tn);

    } else {
        if (node->type() == QSGNode::GeometryNodeType || node->type() == QSGNode::ClipNodeType) {
            static_cast<BasicGeometryNode_Accessor *>(node)->m_matrix = xform ? &xform->combinedMatrix() : 0;
        }
        QSGNODE_TRAVERSE(node)
        updateMatrices(child, xform);
    }
}
示例#2
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();
    }
}