diff options
author | Samuel Rødal <sroedal@trolltech.com> | 2009-09-17 08:52:05 (GMT) |
---|---|---|
committer | Samuel Rødal <sroedal@trolltech.com> | 2009-09-21 14:37:50 (GMT) |
commit | 32c3de3d02193c994c701f085cd64d864563bac0 (patch) | |
tree | 3f763c49f5e8f1bb3949abd45d139216d927f649 /tests | |
parent | c6d2ec67384d5b0a4f9108277888d4aaf0e2f6d2 (diff) | |
download | Qt-32c3de3d02193c994c701f085cd64d864563bac0.zip Qt-32c3de3d02193c994c701f085cd64d864563bac0.tar.gz Qt-32c3de3d02193c994c701f085cd64d864563bac0.tar.bz2 |
Optimized GL2 engine to use scissor clipping more aggressively.
There's no reason to stop using a scissor clip when a more complex clip
is set. Instead, we can use a combination of scissoring and depth
clipping to represent the final clip. When intersecting with a new clip
path, if the clip path is a rectangle we simply intersect it against the
scissor clip, and otherwise we intersect its bounding rect against the
scissor clip and write the actual path to the depth buffer.
The patch simplifies the logic in clip() quite a bit, except in the
UniteClip case in which we don't care about performance anyways.
It also fixes a bug which could cause rendering errors if the stencil
buffer contains junk before painting.
Reviewed-by: Gunnar Sletta
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/qgl/tst_qgl.cpp | 184 |
1 files changed, 183 insertions, 1 deletions
diff --git a/tests/auto/qgl/tst_qgl.cpp b/tests/auto/qgl/tst_qgl.cpp index 21f7359..999d119 100644 --- a/tests/auto/qgl/tst_qgl.cpp +++ b/tests/auto/qgl/tst_qgl.cpp @@ -81,8 +81,9 @@ private slots: void stackedFBOs(); void colormap(); void fboFormat(); - void testDontCrashOnDanglingResources(); + void replaceClipping(); + void clipTest(); }; tst_QGL::tst_QGL() @@ -1539,5 +1540,186 @@ void tst_QGL::testDontCrashOnDanglingResources() widget->hide(); } +class ReplaceClippingGLWidget : public QGLWidget +{ +public: + void paint(QPainter *painter) + { + painter->fillRect(rect(), Qt::white); + + QPainterPath path; + path.addRect(0, 0, 100, 100); + path.addRect(50, 50, 100, 100); + + painter->setClipRect(0, 0, 150, 150); + painter->fillPath(path, Qt::red); + + painter->translate(150, 150); + painter->setClipRect(0, 0, 150, 150); + painter->fillPath(path, Qt::red); + } + +protected: + void paintEvent(QPaintEvent*) + { + // clear the stencil with junk + glStencilMask(0xFFFF); + glClearStencil(0xFFFF); + glDisable(GL_STENCIL_TEST); + glDisable(GL_SCISSOR_TEST); + glClear(GL_STENCIL_BUFFER_BIT); + + QPainter painter(this); + paint(&painter); + } +}; + +void tst_QGL::replaceClipping() +{ + ReplaceClippingGLWidget glw; + glw.resize(300, 300); + glw.show(); + +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&glw); +#endif + QTest::qWait(200); + + QImage reference(300, 300, QImage::Format_RGB32); + QPainter referencePainter(&reference); + glw.paint(&referencePainter); + referencePainter.end(); + + const QImage widgetFB = glw.grabFrameBuffer(false).convertToFormat(QImage::Format_RGB32); + + QCOMPARE(widgetFB, reference); +} + +class ClipTestGLWidget : public QGLWidget +{ +public: + void paint(QPainter *painter) + { + painter->fillRect(rect(), Qt::white); + painter->setClipRect(10, 10, width()-20, height()-20); + painter->fillRect(rect(), Qt::cyan); + + painter->save(); + painter->setClipRect(10, 10, 100, 100, Qt::IntersectClip); + + painter->fillRect(rect(), Qt::blue); + + painter->save(); + painter->setClipRect(10, 10, 50, 50, Qt::IntersectClip); + painter->fillRect(rect(), Qt::red); + painter->restore(); + painter->fillRect(0, 0, 40, 40, Qt::white); + painter->save(); + + painter->setClipRect(0, 0, 35, 35, Qt::IntersectClip); + painter->fillRect(rect(), Qt::black); + painter->restore(); + + painter->fillRect(0, 0, 30, 30, Qt::magenta); + + painter->save(); + painter->setClipRect(60, 10, 50, 50, Qt::ReplaceClip); + painter->fillRect(rect(), Qt::green); + painter->restore(); + + painter->save(); + painter->setClipRect(0, 60, 60, 25, Qt::IntersectClip); + painter->setClipRect(60, 60, 50, 25, Qt::UniteClip); + painter->fillRect(rect(), Qt::yellow); + painter->restore(); + + painter->restore(); + + painter->translate(100, 100); + + { + QPainterPath path; + path.addRect(10, 10, 100, 100); + path.addRect(10, 10, 10, 10); + painter->setClipPath(path, Qt::IntersectClip); + } + + painter->fillRect(rect(), Qt::blue); + + painter->save(); + { + QPainterPath path; + path.addRect(10, 10, 50, 50); + path.addRect(10, 10, 10, 10); + painter->setClipPath(path, Qt::IntersectClip); + } + painter->fillRect(rect(), Qt::red); + painter->restore(); + painter->fillRect(0, 0, 40, 40, Qt::white); + painter->save(); + + { + QPainterPath path; + path.addRect(0, 0, 35, 35); + path.addRect(10, 10, 10, 10); + painter->setClipPath(path, Qt::IntersectClip); + } + painter->fillRect(rect(), Qt::black); + painter->restore(); + + painter->fillRect(0, 0, 30, 30, Qt::magenta); + + painter->save(); + { + QPainterPath path; + path.addRect(60, 10, 50, 50); + path.addRect(10, 10, 10, 10); + painter->setClipPath(path, Qt::ReplaceClip); + } + painter->fillRect(rect(), Qt::green); + painter->restore(); + + painter->save(); + { + QPainterPath path; + path.addRect(0, 60, 60, 25); + path.addRect(10, 10, 10, 10); + painter->setClipPath(path, Qt::IntersectClip); + } + painter->setClipRect(60, 60, 50, 25, Qt::UniteClip); + painter->fillRect(rect(), Qt::yellow); + painter->restore(); + } + +protected: + void paintEvent(QPaintEvent*) + { + QPainter painter(this); + paint(&painter); + } +}; + +void tst_QGL::clipTest() +{ + ClipTestGLWidget glw; + glw.resize(220, 220); + glw.show(); + +#ifdef Q_WS_X11 + qt_x11_wait_for_window_manager(&glw); +#endif + QTest::qWait(200); + + QImage reference(glw.size(), QImage::Format_RGB32); + QPainter referencePainter(&reference); + glw.paint(&referencePainter); + referencePainter.end(); + + const QImage widgetFB = glw.grabFrameBuffer(false).convertToFormat(QImage::Format_RGB32); + + QCOMPARE(widgetFB, reference); +} + + QTEST_MAIN(tst_QGL) #include "tst_qgl.moc" |