aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp133
-rw-r--r--src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h16
-rw-r--r--src/quick/scenegraph/coreapi/qsgrenderer.cpp135
-rw-r--r--src/quick/scenegraph/coreapi/qsgrenderer_p.h20
4 files changed, 150 insertions, 154 deletions
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
index e68b001ad1..4119dfb530 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp
@@ -750,11 +750,14 @@ Renderer::Renderer(QSGRenderContext *ctx)
, m_renderOrderRebuildUpper(-1)
, m_currentMaterial(0)
, m_currentShader(0)
+ , m_currentStencilValue(0)
+ , m_clipMatrixId(0)
, m_currentClip(0)
, m_currentClipType(NoClip)
, m_vao(0)
, m_visualizeMode(VisualizeNothing)
{
+ initializeOpenGLFunctions();
setNodeUpdater(new Updater(this));
m_shaderManager = ctx->findChild<ShaderManager *>(QStringLiteral("__qt_ShaderManager"), Qt::FindDirectChildrenOnly);
@@ -1912,6 +1915,132 @@ void Renderer::uploadBatch(Batch *b)
b->uploadedThisFrame = true;
}
+/*!
+ * Convenience function to set up the stencil buffer for clipping based on \a clip.
+ *
+ * If the clip is a pixel aligned rectangle, this function will use glScissor instead
+ * of stencil.
+ */
+Renderer::ClipType Renderer::updateStencilClip(const QSGClipNode *clip)
+{
+ if (!clip) {
+ glDisable(GL_STENCIL_TEST);
+ glDisable(GL_SCISSOR_TEST);
+ return NoClip;
+ }
+
+ ClipType clipType = NoClip;
+
+ glDisable(GL_SCISSOR_TEST);
+
+ m_currentStencilValue = 0;
+ m_currentScissorRect = 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);
+
+ QRect deviceRect = this->deviceRect();
+
+ GLint ix1 = qRound((fx1 + 1) * deviceRect.width() * qreal(0.5));
+ GLint iy1 = qRound((fy1 + 1) * deviceRect.height() * qreal(0.5));
+ GLint ix2 = qRound((fx2 + 1) * deviceRect.width() * qreal(0.5));
+ GLint iy2 = qRound((fy2 + 1) * deviceRect.height() * qreal(0.5));
+
+ if (!(clipType & ScissorClip)) {
+ m_currentScissorRect = QRect(ix1, iy1, ix2 - ix1, iy2 - iy1);
+ glEnable(GL_SCISSOR_TEST);
+ clipType |= ScissorClip;
+ } else {
+ m_currentScissorRect &= QRect(ix1, iy1, ix2 - ix1, iy2 - iy1);
+ }
+ glScissor(m_currentScissorRect.x(), m_currentScissorRect.y(),
+ m_currentScissorRect.width(), m_currentScissorRect.height());
+ } else {
+ if (!(clipType & StencilClip)) {
+ if (!m_clipProgram.isLinked()) {
+ QSGShaderSourceBuilder::initializeProgramFromFiles(
+ &m_clipProgram,
+ QStringLiteral(":/scenegraph/shaders/stencilclip.vert"),
+ QStringLiteral(":/scenegraph/shaders/stencilclip.frag"));
+ m_clipProgram.bindAttributeLocation("vCoord", 0);
+ m_clipProgram.link();
+ m_clipMatrixId = m_clipProgram.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);
+
+ m_clipProgram.bind();
+ m_clipProgram.enableAttributeArray(0);
+
+ clipType |= StencilClip;
+ }
+
+ glStencilFunc(GL_EQUAL, m_currentStencilValue, 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_clipProgram.setUniformValue(m_clipMatrixId, m);
+ if (g->indexCount()) {
+ glDrawElements(g->drawingMode(), g->indexCount(), g->indexType(), g->indexData());
+ } else {
+ glDrawArrays(g->drawingMode(), 0, g->vertexCount());
+ }
+
+ ++m_currentStencilValue;
+ }
+
+ clip = clip->clipList();
+ }
+
+ if (clipType & StencilClip) {
+ m_clipProgram.disableAttributeArray(0);
+ glStencilFunc(GL_EQUAL, m_currentStencilValue, 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;
+}
+
void Renderer::updateClip(const QSGClipNode *clipList, const Batch *batch)
{
if (clipList != m_currentClip && Q_LIKELY(!debug_noclip)) {
@@ -2485,8 +2614,8 @@ void Renderer::renderRenderNode(Batch *batch)
state.projectionMatrix = &pm;
state.scissorEnabled = m_currentClipType & ScissorClip;
state.stencilEnabled = m_currentClipType & StencilClip;
- state.scissorRect = m_current_scissor_rect;
- state.stencilValue = m_current_stencil_value;
+ state.scissorRect = m_currentScissorRect;
+ state.stencilValue = m_currentStencilValue;
QSGNode *xform = e->renderNode->parent();
QMatrix4x4 matrix;
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
index 89a33cb8c4..574c6df810 100644
--- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h
@@ -406,7 +406,7 @@ public:
QSGRenderContext *context;
};
-class Q_QUICK_PRIVATE_EXPORT Renderer : public QSGRenderer
+class Q_QUICK_PRIVATE_EXPORT Renderer : public QSGRenderer, public QOpenGLFunctions
{
public:
Renderer(QSGRenderContext *);
@@ -426,6 +426,14 @@ protected:
void render();
private:
+ enum ClipTypeBit
+ {
+ NoClip = 0x00,
+ ScissorClip = 0x01,
+ StencilClip = 0x02
+ };
+ Q_DECLARE_FLAGS(ClipType, ClipTypeBit)
+
enum RebuildFlag {
BuildRenderListsForTaggedRoots = 0x0001,
BuildRenderLists = 0x0002,
@@ -457,6 +465,7 @@ private:
void renderBatches();
void renderMergedBatch(const Batch *batch);
void renderUnmergedBatch(const Batch *batch);
+ ClipType updateStencilClip(const QSGClipNode *clip);
void updateClip(const QSGClipNode *clipList, const Batch *batch);
const QMatrix4x4 &matrixForRoot(Node *node);
void renderRenderNode(Batch *batch);
@@ -518,6 +527,11 @@ private:
QSGMaterial *m_currentMaterial;
QSGMaterialShader *m_currentProgram;
ShaderManager::Shader *m_currentShader;
+
+ QRect m_currentScissorRect;
+ int m_currentStencilValue;
+ QOpenGLShaderProgram m_clipProgram;
+ int m_clipMatrixId;
const QSGClipNode *m_currentClip;
ClipType m_currentClipType;
diff --git a/src/quick/scenegraph/coreapi/qsgrenderer.cpp b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
index 23afba368f..c056507729 100644
--- a/src/quick/scenegraph/coreapi/qsgrenderer.cpp
+++ b/src/quick/scenegraph/coreapi/qsgrenderer.cpp
@@ -48,7 +48,6 @@
#include <private/qsgadaptationlayer_p.h>
#include <private/qsgshadersourcebuilder_p.h>
-#include <QOpenGLShaderProgram>
#include <qopenglframebufferobject.h>
#include <QtGui/qguiapplication.h>
@@ -125,7 +124,6 @@ QSGRenderer::QSGRenderer(QSGRenderContext *context)
, m_current_opacity(1)
, m_current_determinant(1)
, m_device_pixel_ratio(1)
- , m_current_stencil_value(0)
, m_context(context)
, m_root_node(0)
, m_node_updater(0)
@@ -134,7 +132,6 @@ QSGRenderer::QSGRenderer(QSGRenderContext *context)
, m_mirrored(false)
, m_is_rendering(false)
{
- initializeOpenGLFunctions();
}
@@ -224,10 +221,10 @@ void QSGRenderer::renderScene(const QSGBindable &bindable)
// Sanity check that attribute registers are disabled
if (qsg_sanity_check) {
GLint count = 0;
- glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &count);
+ QOpenGLContext::currentContext()->functions()->glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &count);
GLint enabled;
for (int i=0; i<count; ++i) {
- glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled);
+ QOpenGLContext::currentContext()->functions()->glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled);
if (enabled) {
qWarning("QSGRenderer: attribute %d is enabled, this can lead to memory corruption and crashes.", i);
}
@@ -238,7 +235,6 @@ void QSGRenderer::renderScene(const QSGBindable &bindable)
if (profileFrames)
renderTime = frameTimer.nsecsElapsed();
- glDisable(GL_SCISSOR_TEST);
m_is_rendering = false;
m_changed_emitted = false;
m_bindable = 0;
@@ -356,133 +352,6 @@ void QSGRenderer::removeNodesToPreprocess(QSGNode *node)
/*!
- Convenience function to set up the stencil buffer for clipping based on \a clip.
-
- If the clip is a pixel aligned rectangle, this function will use glScissor instead
- of stencil.
- */
-
-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()) {
- QSGShaderSourceBuilder::initializeProgramFromFiles(
- &m_clip_program,
- QStringLiteral(":/scenegraph/shaders/stencilclip.vert"),
- QStringLiteral(":/scenegraph/shaders/stencilclip.frag"));
- 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);
-
- 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;
-}
-
-
-
-/*!
\class QSGNodeDumper
\brief The QSGNodeDumper class provides a way of dumping a scene grahp to the console.
diff --git a/src/quick/scenegraph/coreapi/qsgrenderer_p.h b/src/quick/scenegraph/coreapi/qsgrenderer_p.h
index f0cd06abe9..e24a6b652f 100644
--- a/src/quick/scenegraph/coreapi/qsgrenderer_p.h
+++ b/src/quick/scenegraph/coreapi/qsgrenderer_p.h
@@ -42,13 +42,10 @@
#ifndef QSGRENDERER_P_H
#define QSGRENDERER_P_H
+#include <qcolor.h>
#include <qset.h>
#include <qhash.h>
-#include <qcolor.h>
-#include <qopenglfunctions.h>
-#include <qopenglshaderprogram.h>
-
#include "qsgnode.h"
#include "qsgmaterial.h"
#include <QtQuick/qsgtexture.h>
@@ -67,18 +64,10 @@ class QSGNodeUpdater;
Q_QUICK_PRIVATE_EXPORT bool qsg_test_and_clear_fatal_render_error();
Q_QUICK_PRIVATE_EXPORT void qsg_set_fatal_renderer_error();
-class Q_QUICK_PRIVATE_EXPORT QSGRenderer : public QObject, public QOpenGLFunctions
+class Q_QUICK_PRIVATE_EXPORT QSGRenderer : public QObject
{
Q_OBJECT
public:
- enum ClipTypeBit
- {
- NoClip = 0x00,
- ScissorClip = 0x01,
- StencilClip = 0x02
- };
- Q_DECLARE_FLAGS(ClipType, ClipTypeBit)
-
enum ClearModeBit
{
ClearColorBuffer = 0x0001,
@@ -142,7 +131,6 @@ Q_SIGNALS:
protected:
virtual void render() = 0;
- QSGRenderer::ClipType updateStencilClip(const QSGClipNode *clip);
const QSGBindable *bindable() const { return m_bindable; }
@@ -160,8 +148,6 @@ protected:
qreal m_current_opacity;
qreal m_current_determinant;
qreal m_device_pixel_ratio;
- QRect m_current_scissor_rect;
- int m_current_stencil_value;
QSGRenderContext *m_context;
@@ -175,8 +161,6 @@ private:
QSet<QSGNode *> m_nodes_to_preprocess;
QMatrix4x4 m_projection_matrix;
- QOpenGLShaderProgram m_clip_program;
- int m_clip_matrix_id;
const QSGBindable *m_bindable;