From e8a3b49d6d42b213fd4fd55837f6180935a8a603 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Fri, 25 Sep 2009 17:12:42 +0200 Subject: Fixed missing stencil buffer clear when scissor testing is disabled. --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 7cd5aa4..242d02d 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1645,7 +1645,9 @@ void QGL2PaintEngineExPrivate::updateDepthScissorTest() else glDisable(GL_DEPTH_TEST); -#ifndef QT_GL_NO_SCISSOR_TEST +#ifdef QT_GL_NO_SCISSOR_TEST + currentScissorBounds = QRect(0, 0, width, height); +#else QRect bounds = q->state()->rectangleClip; if (!q->state()->clipEnabled) { if (use_system_clip) -- cgit v0.12 From 6372c2865ab6924127b78f968bdd41f8d3f9c637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Fri, 25 Sep 2009 17:02:53 +0200 Subject: Moved maxDepth out of state object and got rid of unused state members. --- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 19 ++++++++----------- .../gl2paintengineex/qpaintengineex_opengl2_p.h | 4 +--- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 242d02d..197c7a9 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1796,21 +1796,21 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) case Qt::IntersectClip: state()->rectangleClip = state()->rectangleClip.intersected(pathRect); d->updateDepthScissorTest(); - ++state()->maxDepth; - d->writeClip(path, state()->maxDepth); - state()->currentDepth = state()->maxDepth - 1; + ++d->maxDepth; + d->writeClip(path, d->maxDepth); + state()->currentDepth = d->maxDepth - 1; state()->depthTestEnabled = true; break; case Qt::UniteClip: { #ifndef QT_GL_NO_SCISSOR_TEST if (state()->rectangleClip.isValid()) { - ++state()->maxDepth; + d->maxDepth; QPainterPath path; path.addRect(state()->rectangleClip); // flush the existing clip rectangle to the depth buffer - d->writeClip(qtVectorPathForPath(state()->matrix.inverted().map(path)), state()->maxDepth); + d->writeClip(qtVectorPathForPath(state()->matrix.inverted().map(path)), d->maxDepth); } QRect oldRectangleClip = state()->rectangleClip; @@ -1831,9 +1831,9 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) #endif glDepthFunc(GL_ALWAYS); // now write the clip path - d->writeClip(path, state()->maxDepth); + d->writeClip(path, d->maxDepth); state()->canRestoreClip = false; - state()->currentDepth = state()->maxDepth - 1; + state()->currentDepth = d->maxDepth - 1; state()->depthTestEnabled = true; break; } @@ -1874,7 +1874,7 @@ void QGL2PaintEngineExPrivate::systemStateChanged() q->state()->needsDepthBufferClear = true; q->state()->currentDepth = 1; - q->state()->maxDepth = 4; + maxDepth = 4; q->state()->rectangleClip = use_system_clip ? systemClip.boundingRect() : QRect(0, 0, width, height); updateDepthScissorTest(); @@ -1945,7 +1945,6 @@ void QGL2PaintEngineEx::setState(QPainterState *new_state) d->updateDepthScissorTest(); glDepthMask(false); glDepthFunc(GL_LESS); - s->maxDepth = old_state->maxDepth; } else { d->regenerateDepthClip(); } @@ -1981,7 +1980,6 @@ QOpenGL2PaintEngineState::QOpenGL2PaintEngineState(QOpenGL2PaintEngineState &oth depthTestEnabled = other.depthTestEnabled; scissorTestEnabled = other.scissorTestEnabled; currentDepth = other.currentDepth; - maxDepth = other.maxDepth; canRestoreClip = other.canRestoreClip; rectangleClip = other.rectangleClip; } @@ -1991,7 +1989,6 @@ QOpenGL2PaintEngineState::QOpenGL2PaintEngineState() needsDepthBufferClear = true; depthTestEnabled = false; currentDepth = 1; - maxDepth = 4; canRestoreClip = true; } diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 12123f3..189d5be 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -83,16 +83,13 @@ public: ~QOpenGL2PaintEngineState(); bool needsDepthBufferClear; - qreal depthBufferClearValue; bool depthTestEnabled; bool scissorTestEnabled; - uint maxDepth; uint currentDepth; bool canRestoreClip; QRect rectangleClip; - bool hasRectangleClip; }; class Q_OPENGL_EXPORT QGL2PaintEngineEx : public QPaintEngineEx @@ -226,6 +223,7 @@ public: QRegion dirtyStencilRegion; QRect currentScissorBounds; + uint maxDepth; const QBrush* currentBrush; // May not be the state's brush! -- cgit v0.12 From af8ff76bf25b6b4d01d89bea42baab65ed7e09ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Fri, 25 Sep 2009 17:22:48 +0200 Subject: Refactored GL 2 engine UniteClip to always increase max depth. --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 197c7a9..17b4808 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1802,10 +1802,8 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) state()->depthTestEnabled = true; break; case Qt::UniteClip: { -#ifndef QT_GL_NO_SCISSOR_TEST + ++d->maxDepth; if (state()->rectangleClip.isValid()) { - d->maxDepth; - QPainterPath path; path.addRect(state()->rectangleClip); @@ -1813,6 +1811,7 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) d->writeClip(qtVectorPathForPath(state()->matrix.inverted().map(path)), d->maxDepth); } +#ifndef QT_GL_NO_SCISSOR_TEST QRect oldRectangleClip = state()->rectangleClip; state()->rectangleClip = state()->rectangleClip.united(pathRect); -- cgit v0.12 From aaf695a3fad8d84f3d9483a573732350445d453a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Fri, 25 Sep 2009 17:20:50 +0200 Subject: Made GL 2 paint engine waste less bits in clipping algorithm. --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 17b4808..c0959ae 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1710,7 +1710,7 @@ void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, uint depth) updateMatrix(); if (q->state()->needsDepthBufferClear) { glDepthMask(true); - glClearDepth(rawDepth(2)); + glClearDepth(rawDepth(1)); glClear(GL_DEPTH_BUFFER_BIT); q->state()->needsDepthBufferClear = false; glDepthMask(false); @@ -1872,8 +1872,8 @@ void QGL2PaintEngineExPrivate::systemStateChanged() q->state()->depthTestEnabled = false; q->state()->needsDepthBufferClear = true; - q->state()->currentDepth = 1; - maxDepth = 4; + q->state()->currentDepth = 0; + maxDepth = 1; q->state()->rectangleClip = use_system_clip ? systemClip.boundingRect() : QRect(0, 0, width, height); updateDepthScissorTest(); @@ -1901,7 +1901,7 @@ void QGL2PaintEngineExPrivate::systemStateChanged() path.addRegion(systemClip); glDepthFunc(GL_ALWAYS); - writeClip(qtVectorPathForPath(q->state()->matrix.inverted().map(path)), 2); + writeClip(qtVectorPathForPath(q->state()->matrix.inverted().map(path)), 1); glDepthFunc(GL_LESS); glEnable(GL_DEPTH_TEST); @@ -1987,7 +1987,6 @@ QOpenGL2PaintEngineState::QOpenGL2PaintEngineState() { needsDepthBufferClear = true; depthTestEnabled = false; - currentDepth = 1; canRestoreClip = true; } -- cgit v0.12 From 2f268b40b290c4513d2d06b75ad681b5550eeaa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Fri, 25 Sep 2009 17:30:56 +0200 Subject: Switched to using GL_LEQUAL instead of GL_LESS in GL 2 engine. --- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index c0959ae..602754c 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -774,6 +774,7 @@ void QGL2PaintEngineExPrivate::resetGLState() glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); glDepthMask(true); + glDepthFunc(GL_LESS); glClearDepth(1); } @@ -1565,7 +1566,7 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) if (!d->inRenderText) { glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); - glDepthFunc(GL_LESS); + glDepthFunc(GL_LEQUAL); glDepthMask(false); } @@ -1631,7 +1632,7 @@ void QGL2PaintEngineEx::ensureActive() d->transferMode(BrushDrawingMode); glViewport(0, 0, d->width, d->height); glDepthMask(false); - glDepthFunc(GL_LESS); + glDepthFunc(GL_LEQUAL); d->needsSync = false; setState(state()); } @@ -1693,7 +1694,7 @@ void QGL2PaintEngineEx::clipEnabledChanged() d->regenerateDepthClip(); } else { if (d->use_system_clip) { - state()->currentDepth = 0; + state()->currentDepth = 1; } else { state()->depthTestEnabled = false; } @@ -1785,7 +1786,7 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) case Qt::NoClip: if (d->use_system_clip) { state()->depthTestEnabled = true; - state()->currentDepth = 0; + state()->currentDepth = 1; } else { state()->depthTestEnabled = false; } @@ -1798,7 +1799,7 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) d->updateDepthScissorTest(); ++d->maxDepth; d->writeClip(path, d->maxDepth); - state()->currentDepth = d->maxDepth - 1; + state()->currentDepth = d->maxDepth; state()->depthTestEnabled = true; break; case Qt::UniteClip: { @@ -1832,7 +1833,7 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) // now write the clip path d->writeClip(path, d->maxDepth); state()->canRestoreClip = false; - state()->currentDepth = d->maxDepth - 1; + state()->currentDepth = d->maxDepth; state()->depthTestEnabled = true; break; } @@ -1840,7 +1841,7 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) break; } - glDepthFunc(GL_LESS); + glDepthFunc(GL_LEQUAL); if (state()->depthTestEnabled) { glEnable(GL_DEPTH_TEST); d->simpleShaderDepthUniformDirty = true; @@ -1872,7 +1873,7 @@ void QGL2PaintEngineExPrivate::systemStateChanged() q->state()->depthTestEnabled = false; q->state()->needsDepthBufferClear = true; - q->state()->currentDepth = 0; + q->state()->currentDepth = 1; maxDepth = 1; q->state()->rectangleClip = use_system_clip ? systemClip.boundingRect() : QRect(0, 0, width, height); @@ -1902,7 +1903,7 @@ void QGL2PaintEngineExPrivate::systemStateChanged() glDepthFunc(GL_ALWAYS); writeClip(qtVectorPathForPath(q->state()->matrix.inverted().map(path)), 1); - glDepthFunc(GL_LESS); + glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); q->state()->depthTestEnabled = true; @@ -1943,7 +1944,7 @@ void QGL2PaintEngineEx::setState(QPainterState *new_state) if (old_state && old_state != s && old_state->canRestoreClip) { d->updateDepthScissorTest(); glDepthMask(false); - glDepthFunc(GL_LESS); + glDepthFunc(GL_LEQUAL); } else { d->regenerateDepthClip(); } -- cgit v0.12 From e8c73ac916ce5cb0492c1d1ba817e59b8df34158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Fri, 25 Sep 2009 17:36:46 +0200 Subject: Renamed GL 2 engine variables to be clip buffer agnostic. --- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 90 +++++++++++----------- .../gl2paintengineex/qpaintengineex_opengl2_p.h | 14 ++-- 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 602754c..7eb9afc 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -276,7 +276,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo); glViewport(0, 0, pex->width, pex->height); - pex->updateDepthScissorTest(); + pex->updateClipScissorTest(); #ifndef QT_OPENGL_ES_2 if (pex->inRenderText) @@ -404,7 +404,7 @@ void QGL2PaintEngineExPrivate::useSimpleShader() } if (simpleShaderDepthUniformDirty) { - shaderManager->simpleProgram()->setUniformValue("depth", normalizedDeviceDepth(q->state()->currentDepth)); + shaderManager->simpleProgram()->setUniformValue("depth", normalizedDeviceDepth(q->state()->currentClip)); simpleShaderDepthUniformDirty = false; } } @@ -1018,7 +1018,7 @@ bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque) } if (depthUniformDirty) { - shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Depth), normalizedDeviceDepth(q->state()->currentDepth)); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Depth), normalizedDeviceDepth(q->state()->currentClip)); depthUniformDirty = false; } @@ -1638,10 +1638,10 @@ void QGL2PaintEngineEx::ensureActive() } } -void QGL2PaintEngineExPrivate::updateDepthScissorTest() +void QGL2PaintEngineExPrivate::updateClipScissorTest() { Q_Q(QGL2PaintEngineEx); - if (q->state()->depthTestEnabled) + if (q->state()->clipTestEnabled) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST); @@ -1691,29 +1691,29 @@ void QGL2PaintEngineEx::clipEnabledChanged() d->depthUniformDirty = true; if (painter()->hasClipping()) { - d->regenerateDepthClip(); + d->regenerateClip(); } else { if (d->use_system_clip) { - state()->currentDepth = 1; + state()->currentClip = 1; } else { - state()->depthTestEnabled = false; + state()->clipTestEnabled = false; } - d->updateDepthScissorTest(); + d->updateClipScissorTest(); } } -void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, uint depth) +void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, uint value) { transferMode(BrushDrawingMode); if (matrixDirty) updateMatrix(); - if (q->state()->needsDepthBufferClear) { + if (q->state()->needsClipBufferClear) { glDepthMask(true); glClearDepth(rawDepth(1)); glClear(GL_DEPTH_BUFFER_BIT); - q->state()->needsDepthBufferClear = false; + q->state()->needsClipBufferClear = false; glDepthMask(false); } @@ -1733,7 +1733,7 @@ void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, uint depth) glColorMask(false, false, false, false); glDepthMask(true); - shaderManager->simpleProgram()->setUniformValue("depth", normalizedDeviceDepth(depth)); + shaderManager->simpleProgram()->setUniformValue("depth", normalizedDeviceDepth(value)); simpleShaderDepthUniformDirty = true; glEnable(GL_DEPTH_TEST); @@ -1774,7 +1774,7 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) if (state()->matrix.type() <= QTransform::TxScale) { state()->rectangleClip = state()->rectangleClip.intersected(state()->matrix.mapRect(rect).toRect()); - d->updateDepthScissorTest(); + d->updateClipScissorTest(); return; } } @@ -1785,38 +1785,38 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) switch (op) { case Qt::NoClip: if (d->use_system_clip) { - state()->depthTestEnabled = true; - state()->currentDepth = 1; + state()->clipTestEnabled = true; + state()->currentClip = 1; } else { - state()->depthTestEnabled = false; + state()->clipTestEnabled = false; } state()->rectangleClip = QRect(0, 0, d->width, d->height); state()->canRestoreClip = false; - d->updateDepthScissorTest(); + d->updateClipScissorTest(); break; case Qt::IntersectClip: state()->rectangleClip = state()->rectangleClip.intersected(pathRect); - d->updateDepthScissorTest(); - ++d->maxDepth; - d->writeClip(path, d->maxDepth); - state()->currentDepth = d->maxDepth; - state()->depthTestEnabled = true; + d->updateClipScissorTest(); + ++d->maxClip; + d->writeClip(path, d->maxClip); + state()->currentClip = d->maxClip; + state()->clipTestEnabled = true; break; case Qt::UniteClip: { - ++d->maxDepth; + ++d->maxClip; if (state()->rectangleClip.isValid()) { QPainterPath path; path.addRect(state()->rectangleClip); // flush the existing clip rectangle to the depth buffer - d->writeClip(qtVectorPathForPath(state()->matrix.inverted().map(path)), d->maxDepth); + d->writeClip(qtVectorPathForPath(state()->matrix.inverted().map(path)), d->maxClip); } #ifndef QT_GL_NO_SCISSOR_TEST QRect oldRectangleClip = state()->rectangleClip; state()->rectangleClip = state()->rectangleClip.united(pathRect); - d->updateDepthScissorTest(); + d->updateClipScissorTest(); QRegion extendRegion = QRegion(state()->rectangleClip) - oldRectangleClip; @@ -1831,10 +1831,10 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) #endif glDepthFunc(GL_ALWAYS); // now write the clip path - d->writeClip(path, d->maxDepth); + d->writeClip(path, d->maxClip); state()->canRestoreClip = false; - state()->currentDepth = d->maxDepth; - state()->depthTestEnabled = true; + state()->currentClip = d->maxClip; + state()->clipTestEnabled = true; break; } default: @@ -1842,14 +1842,14 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) } glDepthFunc(GL_LEQUAL); - if (state()->depthTestEnabled) { + if (state()->clipTestEnabled) { glEnable(GL_DEPTH_TEST); d->simpleShaderDepthUniformDirty = true; d->depthUniformDirty = true; } } -void QGL2PaintEngineExPrivate::regenerateDepthClip() +void QGL2PaintEngineExPrivate::regenerateClip() { systemStateChanged(); replayClipOperations(); @@ -1870,14 +1870,14 @@ void QGL2PaintEngineExPrivate::systemStateChanged() } } - q->state()->depthTestEnabled = false; - q->state()->needsDepthBufferClear = true; + q->state()->clipTestEnabled = false; + q->state()->needsClipBufferClear = true; - q->state()->currentDepth = 1; - maxDepth = 1; + q->state()->currentClip = 1; + maxClip = 1; q->state()->rectangleClip = use_system_clip ? systemClip.boundingRect() : QRect(0, 0, width, height); - updateDepthScissorTest(); + updateClipScissorTest(); if (use_system_clip) { #ifndef QT_GL_NO_SCISSOR_TEST @@ -1891,7 +1891,7 @@ void QGL2PaintEngineExPrivate::systemStateChanged() return; } #endif - q->state()->needsDepthBufferClear = false; + q->state()->needsClipBufferClear = false; glDepthMask(true); @@ -1906,7 +1906,7 @@ void QGL2PaintEngineExPrivate::systemStateChanged() glDepthFunc(GL_LEQUAL); glEnable(GL_DEPTH_TEST); - q->state()->depthTestEnabled = true; + q->state()->clipTestEnabled = true; simpleShaderDepthUniformDirty = true; depthUniformDirty = true; @@ -1942,11 +1942,11 @@ void QGL2PaintEngineEx::setState(QPainterState *new_state) d->shaderManager->setDirty(); if (old_state && old_state != s && old_state->canRestoreClip) { - d->updateDepthScissorTest(); + d->updateClipScissorTest(); glDepthMask(false); glDepthFunc(GL_LEQUAL); } else { - d->regenerateDepthClip(); + d->regenerateClip(); } } @@ -1976,18 +1976,18 @@ void QGL2PaintEngineEx::setRenderTextActive(bool active) QOpenGL2PaintEngineState::QOpenGL2PaintEngineState(QOpenGL2PaintEngineState &other) : QPainterState(other) { - needsDepthBufferClear = other.needsDepthBufferClear; - depthTestEnabled = other.depthTestEnabled; + needsClipBufferClear = other.needsClipBufferClear; + clipTestEnabled = other.clipTestEnabled; scissorTestEnabled = other.scissorTestEnabled; - currentDepth = other.currentDepth; + currentClip = other.currentClip; canRestoreClip = other.canRestoreClip; rectangleClip = other.rectangleClip; } QOpenGL2PaintEngineState::QOpenGL2PaintEngineState() { - needsDepthBufferClear = true; - depthTestEnabled = false; + needsClipBufferClear = true; + clipTestEnabled = false; canRestoreClip = true; } diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 189d5be..fc61905 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -82,11 +82,11 @@ public: QOpenGL2PaintEngineState(); ~QOpenGL2PaintEngineState(); - bool needsDepthBufferClear; + bool needsClipBufferClear; - bool depthTestEnabled; + bool clipTestEnabled; bool scissorTestEnabled; - uint currentDepth; + uint currentClip; bool canRestoreClip; QRect rectangleClip; @@ -223,7 +223,7 @@ public: QRegion dirtyStencilRegion; QRect currentScissorBounds; - uint maxDepth; + uint maxClip; const QBrush* currentBrush; // May not be the state's brush! @@ -240,10 +240,10 @@ public: QGLEngineShaderManager* shaderManager; - void writeClip(const QVectorPath &path, uint depth); - void updateDepthScissorTest(); + void writeClip(const QVectorPath &path, uint value); + void updateClipScissorTest(); void setScissor(const QRect &rect); - void regenerateDepthClip(); + void regenerateClip(); void systemStateChanged(); uint use_system_clip : 1; -- cgit v0.12 From a815840a7f2272b128de4a52497626c49373c8c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 28 Sep 2009 10:24:09 +0200 Subject: Got rid of some redundant state changes regarding GL depth state. --- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 23 +++++++++------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 7eb9afc..b7f9e2c 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1566,8 +1566,6 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) if (!d->inRenderText) { glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); - glDepthFunc(GL_LEQUAL); - glDepthMask(false); } #if !defined(QT_OPENGL_ES_2) @@ -1631,8 +1629,6 @@ void QGL2PaintEngineEx::ensureActive() if (d->needsSync) { d->transferMode(BrushDrawingMode); glViewport(0, 0, d->width, d->height); - glDepthMask(false); - glDepthFunc(GL_LEQUAL); d->needsSync = false; setState(state()); } @@ -1714,18 +1710,23 @@ void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, uint value) glClearDepth(rawDepth(1)); glClear(GL_DEPTH_BUFFER_BIT); q->state()->needsClipBufferClear = false; - glDepthMask(false); } + glDepthMask(false); + if (path.isEmpty()) return; glDisable(GL_BLEND); - glDepthMask(false); vertexCoordinateArray.clear(); vertexCoordinateArray.addPath(path, inverseScale); + if (q->state()->clipTestEnabled) + glDepthFunc(GL_LEQUAL); + else + glDepthFunc(GL_ALWAYS); + glDepthMask(GL_FALSE); fillStencilWithVertexArray(vertexCoordinateArray, path.hasWindingFill()); @@ -1746,6 +1747,7 @@ void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, uint value) composite(vertexCoordinateArray.boundingRect()); glDisable(GL_STENCIL_TEST); + glDepthFunc(GL_LEQUAL); glStencilMask(0); glColorMask(true, true, true, true); @@ -1812,6 +1814,7 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) d->writeClip(qtVectorPathForPath(state()->matrix.inverted().map(path)), d->maxClip); } + state()->clipTestEnabled = false; #ifndef QT_GL_NO_SCISSOR_TEST QRect oldRectangleClip = state()->rectangleClip; @@ -1820,7 +1823,6 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) QRegion extendRegion = QRegion(state()->rectangleClip) - oldRectangleClip; - glDepthFunc(GL_ALWAYS); if (!extendRegion.isEmpty()) { QPainterPath extendPath; extendPath.addRegion(extendRegion); @@ -1829,7 +1831,6 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) d->writeClip(qtVectorPathForPath(state()->matrix.inverted().map(extendPath)), 0); } #endif - glDepthFunc(GL_ALWAYS); // now write the clip path d->writeClip(path, d->maxClip); state()->canRestoreClip = false; @@ -1841,9 +1842,7 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) break; } - glDepthFunc(GL_LEQUAL); if (state()->clipTestEnabled) { - glEnable(GL_DEPTH_TEST); d->simpleShaderDepthUniformDirty = true; d->depthUniformDirty = true; } @@ -1901,11 +1900,8 @@ void QGL2PaintEngineExPrivate::systemStateChanged() QPainterPath path; path.addRegion(systemClip); - glDepthFunc(GL_ALWAYS); writeClip(qtVectorPathForPath(q->state()->matrix.inverted().map(path)), 1); - glDepthFunc(GL_LEQUAL); - glEnable(GL_DEPTH_TEST); q->state()->clipTestEnabled = true; simpleShaderDepthUniformDirty = true; @@ -1943,7 +1939,6 @@ void QGL2PaintEngineEx::setState(QPainterState *new_state) if (old_state && old_state != s && old_state->canRestoreClip) { d->updateClipScissorTest(); - glDepthMask(false); glDepthFunc(GL_LEQUAL); } else { d->regenerateClip(); -- cgit v0.12 From 6d17e09c274803d324e8a8db579aaafaefaab33f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 28 Sep 2009 10:31:46 +0200 Subject: Moved GL 2 clip clearing code into a common function. --- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 28 +++++++++++----------- .../gl2paintengineex/qpaintengineex_opengl2_p.h | 1 + 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index b7f9e2c..13f0079 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1699,25 +1699,30 @@ void QGL2PaintEngineEx::clipEnabledChanged() } } +void QGL2PaintEngineExPrivate::clearClip(uint value) +{ + glDepthMask(true); + glClearDepth(rawDepth(value)); + glClear(GL_DEPTH_BUFFER_BIT); + glDepthMask(false); + + q->state()->needsClipBufferClear = false; +} + void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, uint value) { transferMode(BrushDrawingMode); if (matrixDirty) updateMatrix(); - if (q->state()->needsClipBufferClear) { - glDepthMask(true); - glClearDepth(rawDepth(1)); - glClear(GL_DEPTH_BUFFER_BIT); - q->state()->needsClipBufferClear = false; - } - - glDepthMask(false); + if (q->state()->needsClipBufferClear) + clearClip(1); if (path.isEmpty()) return; glDisable(GL_BLEND); + glDepthMask(false); vertexCoordinateArray.clear(); vertexCoordinateArray.addPath(path, inverseScale); @@ -1890,12 +1895,7 @@ void QGL2PaintEngineExPrivate::systemStateChanged() return; } #endif - q->state()->needsClipBufferClear = false; - - glDepthMask(true); - - glClearDepth(0); - glClear(GL_DEPTH_BUFFER_BIT); + clearClip(0); QPainterPath path; path.addRegion(systemClip); diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index fc61905..dd5f4fc 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -240,6 +240,7 @@ public: QGLEngineShaderManager* shaderManager; + void clearClip(uint value); void writeClip(const QVectorPath &path, uint value); void updateClipScissorTest(); void setScissor(const QRect &rect); -- cgit v0.12 From 6b623c04060d274c048c0d4c6dbc5a90d1c31604 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 6 Oct 2009 15:38:54 +0200 Subject: Switched to using stencil instead of depth buffer for clipping. Based on Aaron Kennedy's patch. All tests are green, but when enabling scissoring UniteClip seems to be broken atm. --- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 277 +++++++++++++-------- .../gl2paintengineex/qpaintengineex_opengl2_p.h | 17 +- 2 files changed, 173 insertions(+), 121 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 13f0079..0af8e71 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -87,6 +87,7 @@ QT_BEGIN_NAMESPACE //#define QT_GL_NO_SCISSOR_TEST +static const GLuint GL_STENCIL_HIGH_BIT = 0x80; static const GLuint QT_BRUSH_TEXTURE_UNIT = 0; static const GLuint QT_IMAGE_TEXTURE_UNIT = 0; //Can be the same as brush texture unit static const GLuint QT_MASK_TEXTURE_UNIT = 1; @@ -227,6 +228,7 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height) glPushAttrib(GL_ENABLE_BIT | GL_VIEWPORT_BIT | GL_SCISSOR_BIT); #endif + glDisable(GL_STENCIL_TEST); glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); glDisable(GL_BLEND); @@ -402,11 +404,6 @@ void QGL2PaintEngineExPrivate::useSimpleShader() shaderManager->simpleProgram()->setUniformValue("pmvMatrix", pmvMatrix); simpleShaderMatrixUniformDirty = false; } - - if (simpleShaderDepthUniformDirty) { - shaderManager->simpleProgram()->setUniformValue("depth", normalizedDeviceDepth(q->state()->currentClip)); - simpleShaderDepthUniformDirty = false; - } } void QGL2PaintEngineExPrivate::updateBrushTexture() @@ -771,6 +768,7 @@ void QGL2PaintEngineExPrivate::resetGLState() { glDisable(GL_BLEND); glActiveTexture(GL_TEXTURE0); + glDisable(GL_STENCIL_TEST); glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); glDepthMask(true); @@ -895,10 +893,10 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) fillStencilWithVertexArray(vertexCoordinateArray, path.hasWindingFill()); // Stencil the brush onto the dest buffer - glStencilFunc(GL_NOTEQUAL, 0, 0xFFFF); // Pass if stencil buff value != 0 - glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); + glStencilFunc(GL_EQUAL, GL_STENCIL_HIGH_BIT, GL_STENCIL_HIGH_BIT); // Pass if stencil buff value != 0 + glStencilOp(GL_KEEP, GL_ZERO, GL_ZERO); + glStencilMask(GL_STENCIL_HIGH_BIT); - glEnable(GL_STENCIL_TEST); prepareForDraw(currentBrush->isOpaque()); #ifndef QT_OPENGL_ES_2 @@ -906,58 +904,137 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Depth), zValueForRenderText()); #endif composite(vertexCoordinateArray.boundingRect()); - glDisable(GL_STENCIL_TEST); - glStencilMask(0); + + updateClipScissorTest(); } } void QGL2PaintEngineExPrivate::fillStencilWithVertexArray(QGL2PEXVertexArray& vertexArray, bool useWindingFill) { +#ifndef QT_OPENGL_ES_2 + if (inRenderText) { + glPushAttrib(GL_ENABLE_BIT); + glDisable(GL_DEPTH_TEST); + } +#endif + // qDebug("QGL2PaintEngineExPrivate::fillStencilWithVertexArray()"); - glStencilMask(0xFFFF); // Enable stencil writes + glStencilMask(0xffff); // Enable stencil writes if (dirtyStencilRegion.intersects(currentScissorBounds)) { - // Clear the stencil buffer to zeros - glDisable(GL_STENCIL_TEST); + QVector clearRegion = dirtyStencilRegion.intersected(currentScissorBounds).rects(); glClearStencil(0); // Clear to zero - glClear(GL_STENCIL_BUFFER_BIT); + for (int i = 0; i < clearRegion.size(); ++i) { +#ifndef QT_GL_NO_SCISSOR_TEST + setScissor(clearRegion.at(i)); +#endif + glClear(GL_STENCIL_BUFFER_BIT); + } + dirtyStencilRegion -= currentScissorBounds; + +#ifndef QT_GL_NO_SCISSOR_TEST + updateClipScissorTest(); +#endif } glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // Disable color writes - glStencilFunc(GL_ALWAYS, 0, 0xFFFF); // Always pass the stencil test + useSimpleShader(); + glEnable(GL_STENCIL_TEST); // For some reason, this has to happen _after_ the simple shader is use()'d - // Setup the stencil op: if (useWindingFill) { - glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_KEEP, GL_INCR_WRAP); // Inc. for front-facing triangle - glStencilOpSeparate(GL_BACK, GL_KEEP, GL_KEEP, GL_DECR_WRAP); //Dec. for back-facing "holes" - } else - glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); // Simply invert the stencil bit + if (q->state()->clipTestEnabled) { + glStencilFunc(GL_LEQUAL, GL_STENCIL_HIGH_BIT | q->state()->currentClip, ~GL_STENCIL_HIGH_BIT); + glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE); + composite(vertexArray.boundingRect()); - // No point in using a fancy gradient shader for writing into the stencil buffer! - useSimpleShader(); - - glEnable(GL_STENCIL_TEST); // For some reason, this has to happen _after_ the simple shader is use()'d - glDisable(GL_BLEND); + glStencilFunc(GL_EQUAL, GL_STENCIL_HIGH_BIT, GL_STENCIL_HIGH_BIT); + } else { + glStencilFunc(GL_ALWAYS, 0, 0xffff); + glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); + composite(vertexArray.boundingRect()); + } -#ifndef QT_OPENGL_ES_2 - if (inRenderText) { - glPushAttrib(GL_ENABLE_BIT); - glDisable(GL_DEPTH_TEST); + // Inc. for front-facing triangle + glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR_WRAP, GL_INCR_WRAP); + //Dec. for back-facing "holes" + glStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR_WRAP, GL_DECR_WRAP); + glStencilMask(~GL_STENCIL_HIGH_BIT); + drawVertexArrays(vertexArray, GL_TRIANGLE_FAN); + + if (q->state()->clipTestEnabled) { + // clear high bit of stencil outside of path + glStencilFunc(GL_EQUAL, GL_STENCIL_HIGH_BIT | q->state()->currentClip, ~GL_STENCIL_HIGH_BIT); + glStencilOp(GL_KEEP, GL_INVERT, GL_INVERT); + glStencilMask(GL_STENCIL_HIGH_BIT); + composite(vertexArray.boundingRect()); + // reset lower bits of stencil inside path to current clip + glStencilFunc(GL_EQUAL, GL_STENCIL_HIGH_BIT | q->state()->currentClip, GL_STENCIL_HIGH_BIT); + glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE); + glStencilMask(~GL_STENCIL_HIGH_BIT); + composite(vertexArray.boundingRect()); + } else { + // set high bit of stencil inside path + glStencilFunc(GL_NOTEQUAL, 0, 0xffff); + glStencilOp(GL_KEEP, GL_INVERT, GL_INVERT); + glStencilMask(GL_STENCIL_HIGH_BIT); + composite(vertexArray.boundingRect()); + } + } else { + glStencilMask(GL_STENCIL_HIGH_BIT); + glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); // Simply invert the stencil bit + drawVertexArrays(vertexArray, GL_TRIANGLE_FAN); } -#endif - // Draw the vertecies into the stencil buffer: - drawVertexArrays(vertexArray, GL_TRIANGLE_FAN); + // Enable color writes & disable stencil writes + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); #ifndef QT_OPENGL_ES_2 if (inRenderText) glPopAttrib(); #endif - // Enable color writes & disable stencil writes +} + +/* + If the maximum value in the stencil buffer is GL_STENCIL_HIGH_BIT - 1, + restore the stencil buffer to a pristine state. The current clip region + is set to 1, and the rest to 0. +*/ +void QGL2PaintEngineExPrivate::resetClipIfNeeded() +{ + if (maxClip != (GL_STENCIL_HIGH_BIT - 1)) + return; + + Q_Q(QGL2PaintEngineEx); + + useSimpleShader(); + glEnable(GL_STENCIL_TEST); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + + QRectF bounds = q->state()->matrix.inverted().mapRect(QRectF(0, 0, width, height)); + QGLRect rect(bounds.left(), bounds.top(), bounds.right(), bounds.bottom()); + + // Set high bit on clip region + glStencilFunc(GL_LEQUAL, q->state()->currentClip, 0xffff); + glStencilOp(GL_KEEP, GL_INVERT, GL_INVERT); + glStencilMask(GL_STENCIL_HIGH_BIT); + composite(rect); + + // Reset clipping to 1 and everything else to zero + glStencilFunc(GL_NOTEQUAL, 0x01, GL_STENCIL_HIGH_BIT); + glStencilOp(GL_ZERO, GL_REPLACE, GL_REPLACE); + glStencilMask(0xFFFF); + composite(rect); + + q->state()->currentClip = 1; + q->state()->canRestoreClip = false; + + maxClip = 1; + + glStencilMask(0x0); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } @@ -1005,7 +1082,6 @@ bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque) // The shader program has changed so mark all uniforms as dirty: brushUniformsDirty = true; shaderMatrixUniformDirty = true; - depthUniformDirty = true; opacityUniformDirty = true; } @@ -1017,11 +1093,6 @@ bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque) shaderMatrixUniformDirty = false; } - if (depthUniformDirty) { - shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Depth), normalizedDeviceDepth(q->state()->currentClip)); - depthUniformDirty = false; - } - if (opacityMode == QGLEngineShaderManager::UniformOpacity && opacityUniformDirty) { shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::GlobalOpacity), (GLfloat)q->state()->opacity); opacityUniformDirty = false; @@ -1542,8 +1613,6 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) d->brushUniformsDirty = true; d->matrixDirty = true; d->compositionModeDirty = true; - d->simpleShaderDepthUniformDirty = true; - d->depthUniformDirty = true; d->opacityUniformDirty = true; d->needsSync = true; d->use_system_clip = !systemClip().isEmpty(); @@ -1564,6 +1633,7 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) d->shaderManager = new QGLEngineShaderManager(d->ctx); if (!d->inRenderText) { + glDisable(GL_STENCIL_TEST); glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); } @@ -1637,10 +1707,13 @@ void QGL2PaintEngineEx::ensureActive() void QGL2PaintEngineExPrivate::updateClipScissorTest() { Q_Q(QGL2PaintEngineEx); - if (q->state()->clipTestEnabled) - glEnable(GL_DEPTH_TEST); - else - glDisable(GL_DEPTH_TEST); + if (q->state()->clipTestEnabled) { + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_LEQUAL, q->state()->currentClip, ~GL_STENCIL_HIGH_BIT); + } else { + glDisable(GL_STENCIL_TEST); + glStencilFunc(GL_ALWAYS, 0, 0xffff); + } #ifdef QT_GL_NO_SCISSOR_TEST currentScissorBounds = QRect(0, 0, width, height); @@ -1683,28 +1756,20 @@ void QGL2PaintEngineEx::clipEnabledChanged() { Q_D(QGL2PaintEngineEx); - d->simpleShaderDepthUniformDirty = true; - d->depthUniformDirty = true; - - if (painter()->hasClipping()) { + if (painter()->hasClipping()) d->regenerateClip(); - } else { - if (d->use_system_clip) { - state()->currentClip = 1; - } else { - state()->clipTestEnabled = false; - } - - d->updateClipScissorTest(); - } + else + d->systemStateChanged(); } void QGL2PaintEngineExPrivate::clearClip(uint value) { - glDepthMask(true); - glClearDepth(rawDepth(value)); - glClear(GL_DEPTH_BUFFER_BIT); - glDepthMask(false); + dirtyStencilRegion -= currentScissorBounds; + + glStencilMask(0xffff); + glClearStencil(value); + glClear(GL_STENCIL_BUFFER_BIT); + glStencilMask(0x0); q->state()->needsClipBufferClear = false; } @@ -1715,48 +1780,57 @@ void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, uint value) if (matrixDirty) updateMatrix(); + + const bool singlePass = !path.hasWindingFill() + && (((q->state()->currentClip == maxClip - 1) && q->state()->clipTestEnabled) + || q->state()->needsClipBufferClear); + const uint referenceClipValue = q->state()->needsClipBufferClear ? 1 : q->state()->currentClip; + if (q->state()->needsClipBufferClear) clearClip(1); - if (path.isEmpty()) + if (path.isEmpty()) { + glEnable(GL_STENCIL_TEST); + glStencilFunc(GL_LEQUAL, value, ~GL_STENCIL_HIGH_BIT); return; + } - glDisable(GL_BLEND); - glDepthMask(false); + if (q->state()->clipTestEnabled) + glStencilFunc(GL_LEQUAL, q->state()->currentClip, ~GL_STENCIL_HIGH_BIT); + else + glStencilFunc(GL_ALWAYS, 0, 0xffff); vertexCoordinateArray.clear(); vertexCoordinateArray.addPath(path, inverseScale); - if (q->state()->clipTestEnabled) - glDepthFunc(GL_LEQUAL); - else - glDepthFunc(GL_ALWAYS); - - glDepthMask(GL_FALSE); - fillStencilWithVertexArray(vertexCoordinateArray, path.hasWindingFill()); + if (!singlePass) + fillStencilWithVertexArray(vertexCoordinateArray, path.hasWindingFill()); - // Stencil the clip onto the clip buffer glColorMask(false, false, false, false); - glDepthMask(true); + glEnable(GL_STENCIL_TEST); + useSimpleShader(); - shaderManager->simpleProgram()->setUniformValue("depth", normalizedDeviceDepth(value)); - simpleShaderDepthUniformDirty = true; + if (singlePass) { + // Under these conditions we can set the new stencil value in a single + // pass, by using the current value and the "new value" as the toggles - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_ALWAYS); + glStencilFunc(GL_LEQUAL, referenceClipValue, ~GL_STENCIL_HIGH_BIT); + glStencilOp(GL_KEEP, GL_INVERT, GL_INVERT); + glStencilMask(value ^ referenceClipValue); - glStencilFunc(GL_NOTEQUAL, 0, 0xFFFF); // Pass if stencil buff value != 0 - glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); + drawVertexArrays(vertexCoordinateArray, GL_TRIANGLE_FAN); + } else { + glStencilFunc(GL_NOTEQUAL, value, GL_STENCIL_HIGH_BIT); + glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE); + glStencilMask(0xffff); - glEnable(GL_STENCIL_TEST); - composite(vertexCoordinateArray.boundingRect()); - glDisable(GL_STENCIL_TEST); + composite(vertexCoordinateArray.boundingRect()); + } - glDepthFunc(GL_LEQUAL); + glStencilFunc(GL_LEQUAL, value, ~GL_STENCIL_HIGH_BIT); glStencilMask(0); glColorMask(true, true, true, true); - glDepthMask(false); } void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) @@ -1804,12 +1878,14 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) case Qt::IntersectClip: state()->rectangleClip = state()->rectangleClip.intersected(pathRect); d->updateClipScissorTest(); + d->resetClipIfNeeded(); ++d->maxClip; d->writeClip(path, d->maxClip); state()->currentClip = d->maxClip; state()->clipTestEnabled = true; break; case Qt::UniteClip: { + d->resetClipIfNeeded(); ++d->maxClip; if (state()->rectangleClip.isValid()) { QPainterPath path; @@ -1846,11 +1922,6 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) default: break; } - - if (state()->clipTestEnabled) { - d->simpleShaderDepthUniformDirty = true; - d->depthUniformDirty = true; - } } void QGL2PaintEngineExPrivate::regenerateClip() @@ -1883,29 +1954,25 @@ void QGL2PaintEngineExPrivate::systemStateChanged() q->state()->rectangleClip = use_system_clip ? systemClip.boundingRect() : QRect(0, 0, width, height); updateClipScissorTest(); - if (use_system_clip) { + if (systemClip.numRects() == 1) { + if (systemClip.boundingRect() == QRect(0, 0, width, height)) + use_system_clip = false; #ifndef QT_GL_NO_SCISSOR_TEST - if (systemClip.numRects() == 1) { - if (q->state()->rectangleClip == QRect(0, 0, width, height)) { - use_system_clip = false; - } else { - simpleShaderDepthUniformDirty = true; - depthUniformDirty = true; - } - return; - } + // scissoring takes care of the system clip + return; #endif + } + + if (use_system_clip) { clearClip(0); QPainterPath path; path.addRegion(systemClip); + q->state()->currentClip = 0; writeClip(qtVectorPathForPath(q->state()->matrix.inverted().map(path)), 1); - + q->state()->currentClip = 1; q->state()->clipTestEnabled = true; - - simpleShaderDepthUniformDirty = true; - depthUniformDirty = true; } } @@ -1929,8 +1996,6 @@ void QGL2PaintEngineEx::setState(QPainterState *new_state) d->matrixDirty = true; d->compositionModeDirty = true; - d->simpleShaderDepthUniformDirty = true; - d->depthUniformDirty = true; d->simpleShaderMatrixUniformDirty = true; d->shaderMatrixUniformDirty = true; d->opacityUniformDirty = true; diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index dd5f4fc..bfc6a3f 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -217,8 +217,6 @@ public: bool brushUniformsDirty; bool simpleShaderMatrixUniformDirty; bool shaderMatrixUniformDirty; - bool depthUniformDirty; - bool simpleShaderDepthUniformDirty; bool opacityUniformDirty; QRegion dirtyStencilRegion; @@ -242,25 +240,14 @@ public: void clearClip(uint value); void writeClip(const QVectorPath &path, uint value); + void resetClipIfNeeded(); + void updateClipScissorTest(); void setScissor(const QRect &rect); void regenerateClip(); void systemStateChanged(); uint use_system_clip : 1; - static inline GLfloat rawDepth(uint depth) - { - // assume at least 16 bits in the depth buffer, and - // use 2^15 depth levels to be safe with regard to - // rounding issues etc - return depth * (1.0f / GLfloat((1 << 15) - 1)); - } - - static inline GLfloat normalizedDeviceDepth(uint depth) - { - return 2.0f * rawDepth(depth) - 1.0f; - } - uint location(QGLEngineShaderManager::Uniform uniform) { return shaderManager->getUniformLocation(uniform); -- cgit v0.12 From d846af0de2ee2b3b76f81f2c0fd3ccceb645b511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 28 Sep 2009 18:37:15 +0200 Subject: Added convex polygon optimization to QGL2PaintEngineExPrivate::fill(). --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 0af8e71..70d1ae9 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -876,16 +876,15 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) if (path.shape() == QVectorPath::RectangleHint) { QGLRect rect(points[0].x(), points[0].y(), points[2].x(), points[2].y()); prepareForDraw(currentBrush->isOpaque()); - composite(rect); - } - else if (path.shape() == QVectorPath::EllipseHint) { + } else if (path.shape() == QVectorPath::EllipseHint + || path.shape() == QVectorPath::ConvexPolygonHint) + { vertexCoordinateArray.clear(); vertexCoordinateArray.addPath(path, inverseScale); prepareForDraw(currentBrush->isOpaque()); drawVertexArrays(vertexCoordinateArray, GL_TRIANGLE_FAN); - } - else { + } else { // The path is too complicated & needs the stencil technique vertexCoordinateArray.clear(); vertexCoordinateArray.addPath(path, inverseScale); -- cgit v0.12 From 9dbcdc00239abbaf899f04fc5ecc2bdb885ad08d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 29 Sep 2009 09:03:19 +0200 Subject: Made depth tested renderText() work after stencil clipping change. Also we should force Raster_A8 glyph format in renderText(). --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 70d1ae9..ab38c24 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -912,13 +912,6 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) void QGL2PaintEngineExPrivate::fillStencilWithVertexArray(QGL2PEXVertexArray& vertexArray, bool useWindingFill) { -#ifndef QT_OPENGL_ES_2 - if (inRenderText) { - glPushAttrib(GL_ENABLE_BIT); - glDisable(GL_DEPTH_TEST); - } -#endif - // qDebug("QGL2PaintEngineExPrivate::fillStencilWithVertexArray()"); glStencilMask(0xffff); // Enable stencil writes @@ -943,6 +936,13 @@ void QGL2PaintEngineExPrivate::fillStencilWithVertexArray(QGL2PEXVertexArray& ve useSimpleShader(); glEnable(GL_STENCIL_TEST); // For some reason, this has to happen _after_ the simple shader is use()'d +#ifndef QT_OPENGL_ES_2 + if (inRenderText) { + glPushAttrib(GL_ENABLE_BIT); + glDisable(GL_DEPTH_TEST); + } +#endif + if (useWindingFill) { if (q->state()->clipTestEnabled) { glStencilFunc(GL_LEQUAL, GL_STENCIL_HIGH_BIT | q->state()->currentClip, ~GL_STENCIL_HIGH_BIT); @@ -1331,6 +1331,9 @@ void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem ? QFontEngineGlyphCache::Type(ti.fontEngine->glyphFormat) : d->glyphCacheType; + if (d->inRenderText) + glyphType = QFontEngineGlyphCache::Raster_A8; + if (glyphType == QFontEngineGlyphCache::Raster_RGBMask && state()->composition_mode != QPainter::CompositionMode_Source && state()->composition_mode != QPainter::CompositionMode_SourceOver) -- cgit v0.12 From 27c2df52128e32c785239dbc9322a4b7beb0078c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 29 Sep 2009 11:00:57 +0200 Subject: Changed GL 2 engine render text implementation to use glDepthRange(). This frees all the current dependencies on the depth uniform. --- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 41 ++++++++++++++-------- .../gl2paintengineex/qpaintengineex_opengl2_p.h | 5 ++- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index ab38c24..859ffe1 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -898,11 +898,14 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path) prepareForDraw(currentBrush->isOpaque()); -#ifndef QT_OPENGL_ES_2 if (inRenderText) - shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Depth), zValueForRenderText()); -#endif + prepareDepthRangeForRenderText(); + composite(vertexCoordinateArray.boundingRect()); + + if (inRenderText) + restoreDepthRangeForRenderText(); + glStencilMask(0); updateClipScissorTest(); @@ -1138,7 +1141,7 @@ void QGL2PaintEngineExPrivate::drawVertexArrays(QGL2PEXVertexArray& vertexArray, glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR); } -float QGL2PaintEngineExPrivate::zValueForRenderText() const +void QGL2PaintEngineExPrivate::prepareDepthRangeForRenderText() { #ifndef QT_OPENGL_ES_2 // Get the z translation value from the model view matrix and @@ -1146,9 +1149,19 @@ float QGL2PaintEngineExPrivate::zValueForRenderText() const // and z-far = 1, which is used in QGLWidget::renderText() GLdouble model[4][4]; glGetDoublev(GL_MODELVIEW_MATRIX, &model[0][0]); - return -2 * model[3][2] - 1; -#else - return 0; + float deviceZ = -2 * model[3][2] - 1; + + glGetFloatv(GL_DEPTH_RANGE, depthRange); + float windowZ = depthRange[0] + (deviceZ + 1) * 0.5 * (depthRange[1] - depthRange[0]); + + glDepthRange(windowZ, windowZ); +#endif +} + +void QGL2PaintEngineExPrivate::restoreDepthRangeForRenderText() +{ +#ifndef QT_OPENGL_ES_2 + glDepthRange(depthRange[0], depthRange[1]); #endif } @@ -1406,6 +1419,9 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly QBrush pensBrush = q->state()->pen.brush(); setBrush(&pensBrush); + if (inRenderText) + prepareDepthRangeForRenderText(); + if (glyphType == QFontEngineGlyphCache::Raster_RGBMask) { // Subpixel antialiasing without gamma correction @@ -1458,10 +1474,6 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly glBindTexture(GL_TEXTURE_2D, cache->texture()); updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false); -#ifndef QT_OPENGL_ES_2 - if (inRenderText) - shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Depth), zValueForRenderText()); -#endif shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::MaskTexture), QT_MASK_TEXTURE_UNIT); glDrawArrays(GL_TRIANGLES, 0, 6 * glyphs.size()); @@ -1492,12 +1504,11 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, QFontEngineGly glBindTexture(GL_TEXTURE_2D, cache->texture()); updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false); -#ifndef QT_OPENGL_ES_2 - if (inRenderText) - shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Depth), zValueForRenderText()); -#endif shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::MaskTexture), QT_MASK_TEXTURE_UNIT); glDrawArrays(GL_TRIANGLES, 0, 6 * glyphs.size()); + + if (inRenderText) + restoreDepthRangeForRenderText(); } void QGL2PaintEngineEx::drawPixmaps(const QDrawPixmaps::Data *drawingData, int dataCount, const QPixmap &pixmap, QDrawPixmaps::DrawingHints hints) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index bfc6a3f..662911f 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -197,7 +197,8 @@ public: inline void useSimpleShader(); - float zValueForRenderText() const; + void prepareDepthRangeForRenderText(); + void restoreDepthRangeForRenderText(); static QGLEngineShaderManager* shaderManagerForEngine(QGL2PaintEngineEx *engine) { return engine->d_func()->shaderManager; } @@ -258,6 +259,8 @@ public: bool needsSync; bool inRenderText; + GLfloat depthRange[2]; + float textureInvertedY; QScopedPointer convolutionFilter; -- cgit v0.12