summaryrefslogtreecommitdiffstats
path: root/src/opengl
diff options
context:
space:
mode:
authorSamuel Rødal <sroedal@trolltech.com>2009-09-01 07:55:13 (GMT)
committerSamuel Rødal <sroedal@trolltech.com>2009-09-01 08:56:23 (GMT)
commitefe61b3b44c0c391d4c11bd061e531f03bf8fb4a (patch)
treecf03410fd0031a617b23f645a27d953520b1cbf1 /src/opengl
parenta985aaccfcaf2e24b7094875f2e6f51d80c45997 (diff)
downloadQt-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.cpp51
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h19
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);