aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-07-02 16:56:26 +0200
committerJocelyn Turcotte <jocelyn.turcotte@digia.com>2014-07-29 17:54:43 +0200
commit9c67029ee5aca18ae02e740afbf6d0f883799ebd (patch)
tree76479e72ce3b9b0f993ddbc8a11c0d02775cbcc6 /src
parent4c58d2a83736545f473559cb3e04133343b6194a (diff)
Move QSGRenderer::updateStencilClip down to QSGBatchRenderer
This convenience method is currently only used by the batch renderer. Moving it allows removing the QOpenGLFunction inheritance of QSGRenderer and unbinding it slightly from the rendering implementation. Change-Id: I4322952f843de8d950ced32885feee8d6c4a2730 Reviewed-by: Gunnar Sletta <gunnar.sletta@jollamobile.com>
Diffstat (limited to 'src')
-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;