diff options
author | Samuel Rødal <sroedal@trolltech.com> | 2009-09-01 07:55:13 (GMT) |
---|---|---|
committer | Samuel Rødal <sroedal@trolltech.com> | 2009-09-01 08:56:23 (GMT) |
commit | efe61b3b44c0c391d4c11bd061e531f03bf8fb4a (patch) | |
tree | cf03410fd0031a617b23f645a27d953520b1cbf1 /src/opengl | |
parent | a985aaccfcaf2e24b7094875f2e6f51d80c45997 (diff) | |
download | Qt-efe61b3b44c0c391d4c11bd061e531f03bf8fb4a.zip Qt-efe61b3b44c0c391d4c11bd061e531f03bf8fb4a.tar.gz Qt-efe61b3b44c0c391d4c11bd061e531f03bf8fb4a.tar.bz2 |
Fixed poor utilization of depth buffer range in GL 2 paint engine.
Before this patch we were only able to do 20 or so IntersectClips before
failing, this patch instead adapts to the fixed point nature of typical
depth buffer implementations and lets us do ~2^15 IntersectClip
operations before failing, which should be a reasonable limit for any
real-world application.
Using the following mapping of old floating point depths to integer
depths:
-1.0 -> 0, -0.5 -> 1,
0.0 -> 2, 0.25 -> 3,
0.5 -> 4, 0.625 -> 5,
etc..
Reviewed-by: Tom
Diffstat (limited to 'src/opengl')
-rw-r--r-- | src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 51 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h | 19 |
2 files changed, 41 insertions, 29 deletions
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index a976a02..0c01263 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -380,7 +380,7 @@ void QGL2PaintEngineExPrivate::useSimpleShader() } if (simpleShaderDepthUniformDirty) { - shaderManager->simpleProgram()->setUniformValue("depth", (GLfloat)q->state()->currentDepth); + shaderManager->simpleProgram()->setUniformValue("depth", normalizedDeviceDepth(q->state()->currentDepth)); simpleShaderDepthUniformDirty = false; } } @@ -731,7 +731,6 @@ void QGL2PaintEngineExPrivate::resetGLState() glActiveTexture(GL_TEXTURE0); glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); - glDepthFunc(GL_LESS); glDepthMask(true); glClearDepth(1); } @@ -959,7 +958,7 @@ bool QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque) } if (depthUniformDirty) { - shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Depth), (GLfloat)q->state()->currentDepth); + shaderManager->currentProgram()->setUniformValue(location(QGLEngineShaderManager::Depth), normalizedDeviceDepth(q->state()->currentDepth)); depthUniformDirty = false; } @@ -1351,7 +1350,7 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) if (!d->inRenderText) { glDisable(GL_DEPTH_TEST); glDisable(GL_SCISSOR_TEST); - glDepthFunc(GL_LEQUAL); + glDepthFunc(GL_LESS); glDepthMask(false); } @@ -1441,7 +1440,7 @@ void QGL2PaintEngineEx::ensureActive() if (d->needsSync) { glViewport(0, 0, d->width, d->height); glDepthMask(false); - glDepthFunc(GL_LEQUAL); + glDepthFunc(GL_LESS); setState(state()); d->needsSync = false; } @@ -1492,7 +1491,7 @@ void QGL2PaintEngineEx::clipEnabledChanged() d->regenerateDepthClip(); } else { if (d->use_system_clip) { - state()->currentDepth = -0.5f; + state()->currentDepth = 0; } else { state()->depthTestEnabled = false; } @@ -1501,7 +1500,7 @@ void QGL2PaintEngineEx::clipEnabledChanged() } } -void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, float depth) +void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, uint depth) { transferMode(BrushDrawingMode); @@ -1510,7 +1509,7 @@ void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, float depth) if (q->state()->needsDepthBufferClear) { glDepthMask(true); - glClearDepth(0.5); + glClearDepth(rawDepth(2)); glClear(GL_DEPTH_BUFFER_BIT); q->state()->needsDepthBufferClear = false; glDepthMask(false); @@ -1532,7 +1531,7 @@ void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, float depth) glColorMask(false, false, false, false); glDepthMask(true); - shaderManager->simpleProgram()->setUniformValue("depth", depth); + shaderManager->simpleProgram()->setUniformValue("depth", normalizedDeviceDepth(depth)); simpleShaderDepthUniformDirty = true; glEnable(GL_DEPTH_TEST); @@ -1596,12 +1595,12 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) glDepthFunc(GL_ALWAYS); - state()->maxDepth = 0.5f; + state()->maxDepth = 4; d->writeClip(qtVectorPathForPath(path), state()->maxDepth); - state()->currentDepth = 0.25f; + state()->currentDepth = 3; state()->depthTestEnabled = true; - glDepthFunc(GL_LEQUAL); + glDepthFunc(GL_LESS); glEnable(GL_DEPTH_TEST); } @@ -1610,7 +1609,7 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) if (d->use_system_clip) { glEnable(GL_DEPTH_TEST); state()->depthTestEnabled = true; - state()->currentDepth = -0.5; + state()->currentDepth = 0; } else { glDisable(GL_DEPTH_TEST); state()->depthTestEnabled = false; @@ -1618,18 +1617,18 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) state()->canRestoreClip = false; break; case Qt::IntersectClip: - state()->maxDepth = (1.0f + state()->maxDepth) * 0.5; + ++state()->maxDepth; d->writeClip(path, state()->maxDepth); - state()->currentDepth = 1.5 * state()->maxDepth - 0.5f; + state()->currentDepth = state()->maxDepth - 1; state()->depthTestEnabled = true; break; case Qt::ReplaceClip: d->systemStateChanged(); state()->rectangleClip = QRect(); - state()->maxDepth = 0.5f; + state()->maxDepth = 4; glDepthFunc(GL_ALWAYS); d->writeClip(path, state()->maxDepth); - state()->currentDepth = 0.25f; + state()->currentDepth = 3; state()->canRestoreClip = false; state()->depthTestEnabled = true; break; @@ -1641,7 +1640,7 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) break; } - glDepthFunc(GL_LEQUAL); + glDepthFunc(GL_LESS); if (state()->depthTestEnabled) { glEnable(GL_DEPTH_TEST); d->simpleShaderDepthUniformDirty = true; @@ -1672,8 +1671,8 @@ void QGL2PaintEngineExPrivate::systemStateChanged() glDisable(GL_SCISSOR_TEST); - q->state()->currentDepth = -0.5f; - q->state()->maxDepth = 0.5f; + q->state()->currentDepth = 1; + q->state()->maxDepth = 4; q->state()->rectangleClip = QRect(0, 0, width, height); @@ -1708,8 +1707,8 @@ void QGL2PaintEngineExPrivate::systemStateChanged() path.addRegion(systemClip); glDepthFunc(GL_ALWAYS); - writeClip(qtVectorPathForPath(path), 0.0f); - glDepthFunc(GL_LEQUAL); + writeClip(qtVectorPathForPath(path), 2); + glDepthFunc(GL_LESS); glEnable(GL_DEPTH_TEST); q->state()->depthTestEnabled = true; @@ -1718,7 +1717,7 @@ void QGL2PaintEngineExPrivate::systemStateChanged() q->transformChanged(); } - q->state()->currentDepth = -0.5f; + q->state()->currentDepth = 1; simpleShaderDepthUniformDirty = true; depthUniformDirty = true; } @@ -1757,7 +1756,7 @@ void QGL2PaintEngineEx::setState(QPainterState *new_state) if (old_state && old_state != s && old_state->canRestoreClip) { d->updateDepthScissorTest(); glDepthMask(false); - glDepthFunc(GL_LEQUAL); + glDepthFunc(GL_LESS); s->maxDepth = old_state->maxDepth; } else { d->regenerateDepthClip(); @@ -1802,8 +1801,8 @@ QOpenGL2PaintEngineState::QOpenGL2PaintEngineState() needsDepthBufferClear = true; depthTestEnabled = false; scissorTestEnabled = false; - currentDepth = -0.5f; - maxDepth = 0.5f; + currentDepth = 1; + maxDepth = 4; canRestoreClip = true; hasRectangleClip = false; } diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 58fcde1..552e390 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -82,8 +82,8 @@ public: bool depthTestEnabled; bool scissorTestEnabled; - qreal currentDepth; - qreal maxDepth; + uint maxDepth; + uint currentDepth; bool canRestoreClip; QRect rectangleClip; @@ -230,13 +230,26 @@ public: QGLEngineShaderManager* shaderManager; - void writeClip(const QVectorPath &path, float depth); + void writeClip(const QVectorPath &path, uint depth); void updateDepthScissorTest(); void setScissor(const QRect &rect); void regenerateDepthClip(); 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); |