Exemplo n.º 1
0
void QSGContext::renderNextFrame(QSGRenderer *renderer, GLuint fboId)
{
    if (fboId) {
        QSGBindableFboId bindable(fboId);
        renderer->renderScene(bindable);
    } else {
        renderer->renderScene();
    }

}
Exemplo n.º 2
0
bool SemanticsVisitor::applicable(TypeDescriptorList formalParams, TypeDescriptorList actualParams) {
	if (formalParams.size() == 0 && actualParams.size() == 0) return true;
	else if (formalParams.size() == 0 || actualParams.size() == 0) return false;
	else {
		if (bindable(formalParams.front(), actualParams.front()))
			return applicable(
					TypeDescriptorList(++formalParams.begin(), formalParams.end()),
					TypeDescriptorList(++actualParams.begin(), actualParams.end())
			);
		return false;
	}
}
Exemplo n.º 3
0
QSGRenderer::ClipType QSGRenderer::updateStencilClip(const QSGClipNode *clip)
{
    if (!clip) {
        glDisable(GL_STENCIL_TEST);
        glDisable(GL_SCISSOR_TEST);
        return NoClip;
    }

    bool stencilEnabled = false;
    bool scissorEnabled = false;

    glDisable(GL_SCISSOR_TEST);

    int clipDepth = 0;
    QRect clipRect;
    while (clip) {
        QMatrix4x4 m = m_current_projection_matrix;
        if (clip->matrix())
            m *= *clip->matrix();

        // TODO: Check for multisampling and pixel grid alignment.
        bool canUseScissor = clip->isRectangular()
                           && qFuzzyIsNull(m(0, 1)) && qFuzzyIsNull(m(0, 2))
                           && qFuzzyIsNull(m(1, 0)) && qFuzzyIsNull(m(1, 2));

        if (canUseScissor) {
            QRectF bbox = clip->clipRect();
            qreal invW = 1 / m(3, 3);
            qreal fx1 = (bbox.left() * m(0, 0) + m(0, 3)) * invW;
            qreal fy1 = (bbox.bottom() * m(1, 1) + m(1, 3)) * invW;
            qreal fx2 = (bbox.right() * m(0, 0) + m(0, 3)) * invW;
            qreal fy2 = (bbox.top() * m(1, 1) + m(1, 3)) * invW;

            GLint ix1 = qRound((fx1 + 1) * m_device_rect.width() * qreal(0.5));
            GLint iy1 = qRound((fy1 + 1) * m_device_rect.height() * qreal(0.5));
            GLint ix2 = qRound((fx2 + 1) * m_device_rect.width() * qreal(0.5));
            GLint iy2 = qRound((fy2 + 1) * m_device_rect.height() * qreal(0.5));

            if (!scissorEnabled) {
                clipRect = QRect(ix1, iy1, ix2 - ix1, iy2 - iy1);
                glEnable(GL_SCISSOR_TEST);
                scissorEnabled = true;
            } else {
                clipRect &= QRect(ix1, iy1, ix2 - ix1, iy2 - iy1);
            }

            clipRect = clipRect.normalized();
            glScissor(clipRect.x(), clipRect.y(), clipRect.width(), clipRect.height());
        } else {
            if (!stencilEnabled) {
                if (!m_clip_program.isLinked()) {
                    m_clip_program.addShaderFromSourceCode(QGLShader::Vertex,
                        "attribute highp vec4 vCoord;       \n"
                        "uniform highp mat4 matrix;         \n"
                        "void main() {                      \n"
                        "    gl_Position = matrix * vCoord; \n"
                        "}");
                    m_clip_program.addShaderFromSourceCode(QGLShader::Fragment,
                        "void main() {                                   \n"
                        "    gl_FragColor = vec4(0.81, 0.83, 0.12, 1.0); \n" // Trolltech green ftw!
                        "}");
                    m_clip_program.bindAttributeLocation("vCoord", 0);
                    m_clip_program.link();
                    m_clip_matrix_id = m_clip_program.uniformLocation("matrix");
                }

                glStencilMask(0xff); // write mask
                glClearStencil(0);
                glClear(GL_STENCIL_BUFFER_BIT);
                glEnable(GL_STENCIL_TEST);
                glDisable(GL_DEPTH_TEST);
                glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
                glDepthMask(GL_FALSE);

                m_clip_program.bind();
                m_clip_program.enableAttributeArray(0);

                stencilEnabled = true;
            }

            glStencilFunc(GL_EQUAL, clipDepth, 0xff); // stencil test, ref, test mask
            glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); // stencil fail, z fail, z pass

            const QSGGeometry *geometry = clip->geometry();
            Q_ASSERT(geometry->attributeCount() > 0);
            const QSGGeometry::Attribute *a = geometry->attributes();

            glVertexAttribPointer(0, a->tupleSize, a->type, GL_FALSE, geometry->stride(), geometry->vertexData());

            m_clip_program.setUniformValue(m_clip_matrix_id, m);
            draw(clip);

            ++clipDepth;
        }

        clip = clip->clipList();
    }

    if (stencilEnabled) {
        m_clip_program.disableAttributeArray(0);
        glEnable(GL_DEPTH_TEST);
        glStencilFunc(GL_EQUAL, clipDepth, 0xff); // stencil test, ref, test mask
        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // stencil fail, z fail, z pass
        glStencilMask(0); // write mask
        bindable()->reactivate();
        //glDepthMask(GL_TRUE); // must be reset correctly by caller.
    } else {
        glDisable(GL_STENCIL_TEST);
    }

    if (!scissorEnabled)
        glDisable(GL_SCISSOR_TEST);

    return stencilEnabled ? StencilClip : ScissorClip;
}
void QSGDefaultRenderer::render()
{
#if defined (QML_RUNTIME_TESTING)
    static bool dumpTree = qApp->arguments().contains(QLatin1String("--dump-tree"));
    if (dumpTree) {
        printf("\n\n");
        QSGNodeDumper::dump(rootNode());
    }
#endif

#ifdef RENDERER_DEBUG
    debugTimer.invalidate();
    debugTimer.start();
    geometryNodesDrawn = 0;
    materialChanges = 0;
#endif

    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    glDisable(GL_BLEND);

    glFrontFace(isMirrored() ? GL_CW : GL_CCW);
    glDisable(GL_CULL_FACE);

    glEnable(GL_DEPTH_TEST);
    glDepthMask(true);
    glDepthFunc(GL_GREATER);
#if defined(QT_OPENGL_ES)
    glClearDepthf(0);
#else
    glClearDepth(0);
#endif

    glDisable(GL_SCISSOR_TEST);
    glClearColor(m_clear_color.redF(), m_clear_color.greenF(), m_clear_color.blueF(), m_clear_color.alphaF());

#ifdef RENDERER_DEBUG
    int debugtimeSetup = debugTimer.elapsed();
#endif

    bindable()->clear(clearMode());

#ifdef RENDERER_DEBUG
    int debugtimeClear = debugTimer.elapsed();
#endif

    QRect r = viewportRect();
    glViewport(r.x(), deviceRect().bottom() - r.bottom(), r.width(), r.height());
    m_current_projection_matrix = projectionMatrix();
    m_current_model_view_matrix.setToIdentity();

    m_currentClip = 0;
    glDisable(GL_STENCIL_TEST);

    m_currentMaterial = 0;
    m_currentProgram = 0;
    m_currentMatrix = 0;

    if (m_rebuild_lists) {
        m_opaqueNodes.reset();
        m_transparentNodes.reset();
        m_currentRenderOrder = 1;
        buildLists(rootNode());
        m_rebuild_lists = false;
    }

#ifdef RENDERER_DEBUG
    int debugtimeLists = debugTimer.elapsed();
#endif


    if (m_needs_sorting) {
        if (!m_opaqueNodes.isEmpty()) {
            qSort(&m_opaqueNodes.first(), &m_opaqueNodes.first() + m_opaqueNodes.size(),
                  m_sort_front_to_back
                  ? nodeLessThanWithRenderOrder
                  : nodeLessThan);
        }
        m_needs_sorting = false;
    }

#ifdef RENDERER_DEBUG
    int debugtimeSorting = debugTimer.elapsed();
#endif

    m_renderOrderMatrix.setToIdentity();
    m_renderOrderMatrix.scale(1, 1, qreal(1) / m_currentRenderOrder);

    glDisable(GL_BLEND);
    glDepthMask(true);
#ifdef QML_RUNTIME_TESTING
    if (m_render_opaque_nodes)
#endif
    {
#if defined (QML_RUNTIME_TESTING)
        if (dumpTree)
            qDebug() << "Opaque Nodes:";
#endif
        renderNodes(m_opaqueNodes);
    }

#ifdef RENDERER_DEBUG
    int debugtimeOpaque = debugTimer.elapsed();
    int opaqueNodes = geometryNodesDrawn;
    int opaqueMaterialChanges = materialChanges;
#endif

    glEnable(GL_BLEND);
    glDepthMask(false);
#ifdef QML_RUNTIME_TESTING
    if (m_render_alpha_nodes)
#endif
    {
#if defined (QML_RUNTIME_TESTING)
        if (dumpTree)
            qDebug() << "Alpha Nodes:";
#endif
        renderNodes(m_transparentNodes);
    }

#ifdef RENDERER_DEBUG
    int debugtimeAlpha = debugTimer.elapsed();
#endif


    if (m_currentProgram)
        m_currentProgram->deactivate();

#ifdef RENDERER_DEBUG
    if (debugTimer.elapsed() > DEBUG_THRESHOLD) {
        printf(" --- Renderer breakdown:\n"
               "     - setup=%d, clear=%d, building=%d, sorting=%d, opaque=%d, alpha=%d\n"
               "     - material changes: opaque=%d, alpha=%d, total=%d\n"
               "     - geometry ndoes: opaque=%d, alpha=%d, total=%d\n",
               debugtimeSetup,
               debugtimeClear - debugtimeSetup,
               debugtimeLists - debugtimeClear,
               debugtimeSorting - debugtimeLists,
               debugtimeOpaque - debugtimeSorting,
               debugtimeAlpha - debugtimeOpaque,
               opaqueMaterialChanges, materialChanges - opaqueMaterialChanges, materialChanges,
               opaqueNodes, geometryNodesDrawn - opaqueNodes, geometryNodesDrawn);
    }
#endif

}
Exemplo n.º 5
0
QSGRenderer::ClipType QSGRenderer::updateStencilClip(const QSGClipNode *clip)
{
    if (!clip) {
        glDisable(GL_STENCIL_TEST);
        glDisable(GL_SCISSOR_TEST);
        return NoClip;
    }

    ClipType clipType = NoClip;

    glDisable(GL_SCISSOR_TEST);

    m_current_stencil_value = 0;
    m_current_scissor_rect = QRect();
    while (clip) {
        QMatrix4x4 m = m_current_projection_matrix;
        if (clip->matrix())
            m *= *clip->matrix();

        // TODO: Check for multisampling and pixel grid alignment.
        bool isRectangleWithNoPerspective = clip->isRectangular()
                && qFuzzyIsNull(m(3, 0)) && qFuzzyIsNull(m(3, 1));
        bool noRotate = qFuzzyIsNull(m(0, 1)) && qFuzzyIsNull(m(1, 0));
        bool isRotate90 = qFuzzyIsNull(m(0, 0)) && qFuzzyIsNull(m(1, 1));

        if (isRectangleWithNoPerspective && (noRotate || isRotate90)) {
            QRectF bbox = clip->clipRect();
            qreal invW = 1 / m(3, 3);
            qreal fx1, fy1, fx2, fy2;
            if (noRotate) {
                fx1 = (bbox.left() * m(0, 0) + m(0, 3)) * invW;
                fy1 = (bbox.bottom() * m(1, 1) + m(1, 3)) * invW;
                fx2 = (bbox.right() * m(0, 0) + m(0, 3)) * invW;
                fy2 = (bbox.top() * m(1, 1) + m(1, 3)) * invW;
            } else {
                Q_ASSERT(isRotate90);
                fx1 = (bbox.bottom() * m(0, 1) + m(0, 3)) * invW;
                fy1 = (bbox.left() * m(1, 0) + m(1, 3)) * invW;
                fx2 = (bbox.top() * m(0, 1) + m(0, 3)) * invW;
                fy2 = (bbox.right() * m(1, 0) + m(1, 3)) * invW;
            }

            if (fx1 > fx2)
                qSwap(fx1, fx2);
            if (fy1 > fy2)
                qSwap(fy1, fy2);

            GLint ix1 = qRound((fx1 + 1) * m_device_rect.width() * qreal(0.5));
            GLint iy1 = qRound((fy1 + 1) * m_device_rect.height() * qreal(0.5));
            GLint ix2 = qRound((fx2 + 1) * m_device_rect.width() * qreal(0.5));
            GLint iy2 = qRound((fy2 + 1) * m_device_rect.height() * qreal(0.5));

            if (!(clipType & ScissorClip)) {
                m_current_scissor_rect = QRect(ix1, iy1, ix2 - ix1, iy2 - iy1);
                glEnable(GL_SCISSOR_TEST);
                clipType |= ScissorClip;
            } else {
                m_current_scissor_rect &= QRect(ix1, iy1, ix2 - ix1, iy2 - iy1);
            }
            glScissor(m_current_scissor_rect.x(), m_current_scissor_rect.y(),
                      m_current_scissor_rect.width(), m_current_scissor_rect.height());
        } else {
            if (!(clipType & StencilClip)) {
                if (!m_clip_program.isLinked()) {
                    m_clip_program.addShaderFromSourceCode(QOpenGLShader::Vertex,
                        "attribute highp vec4 vCoord;       \n"
                        "uniform highp mat4 matrix;         \n"
                        "void main() {                      \n"
                        "    gl_Position = matrix * vCoord; \n"
                        "}");
                    m_clip_program.addShaderFromSourceCode(QOpenGLShader::Fragment,
                        "void main() {                                   \n"
                        "    gl_FragColor = vec4(0.81, 0.83, 0.12, 1.0); \n" // Trolltech green ftw!
                        "}");
                    m_clip_program.bindAttributeLocation("vCoord", 0);
                    m_clip_program.link();
                    m_clip_matrix_id = m_clip_program.uniformLocation("matrix");
                }

                glClearStencil(0);
                glClear(GL_STENCIL_BUFFER_BIT);
                glEnable(GL_STENCIL_TEST);
                glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
                glDepthMask(GL_FALSE);

                if (m_vertex_buffer_bound) {
                    glBindBuffer(GL_ARRAY_BUFFER, 0);
                    m_vertex_buffer_bound = false;
                }
                if (m_index_buffer_bound) {
                    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
                    m_index_buffer_bound = false;
                }

                m_clip_program.bind();
                m_clip_program.enableAttributeArray(0);

                clipType |= StencilClip;
            }

            glStencilFunc(GL_EQUAL, m_current_stencil_value, 0xff); // stencil test, ref, test mask
            glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); // stencil fail, z fail, z pass

            const QSGGeometry *g = clip->geometry();
            Q_ASSERT(g->attributeCount() > 0);
            const QSGGeometry::Attribute *a = g->attributes();
            glVertexAttribPointer(0, a->tupleSize, a->type, GL_FALSE, g->sizeOfVertex(), g->vertexData());

            m_clip_program.setUniformValue(m_clip_matrix_id, m);
            if (g->indexCount()) {
                glDrawElements(g->drawingMode(), g->indexCount(), g->indexType(), g->indexData());
            } else {
                glDrawArrays(g->drawingMode(), 0, g->vertexCount());
            }

            ++m_current_stencil_value;
        }

        clip = clip->clipList();
    }

    if (clipType & StencilClip) {
        m_clip_program.disableAttributeArray(0);
        glStencilFunc(GL_EQUAL, m_current_stencil_value, 0xff); // stencil test, ref, test mask
        glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // stencil fail, z fail, z pass
        bindable()->reactivate();
    } else {
        glDisable(GL_STENCIL_TEST);
    }

    return clipType;
}