summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Cooksey <thomas.cooksey@nokia.com>2009-09-02 11:45:45 (GMT)
committerTom Cooksey <thomas.cooksey@nokia.com>2009-09-02 12:03:36 (GMT)
commit5871ed63be9dae9543fa0b715d593365bd1d2a7c (patch)
tree6516a3008f1abd9159c81ba955c02c3a2e5c65de
parentfa048c81e4b9bfd1ab05940a59735d7a536669f0 (diff)
downloadQt-5871ed63be9dae9543fa0b715d593365bd1d2a7c.zip
Qt-5871ed63be9dae9543fa0b715d593365bd1d2a7c.tar.gz
Qt-5871ed63be9dae9543fa0b715d593365bd1d2a7c.tar.bz2
Add autotests for FBO stacking and interleaved painting
Reviewed-By: Samuel
-rw-r--r--tests/auto/qgl/tst_qgl.cpp211
1 files changed, 211 insertions, 0 deletions
diff --git a/tests/auto/qgl/tst_qgl.cpp b/tests/auto/qgl/tst_qgl.cpp
index f979174..d87a29c 100644
--- a/tests/auto/qgl/tst_qgl.cpp
+++ b/tests/auto/qgl/tst_qgl.cpp
@@ -73,9 +73,11 @@ private slots:
void partialGLWidgetUpdates();
void glWidgetRendering();
void glFBORendering();
+ void multipleFBOInterleavedRendering();
void glFBOUseInGLWidget();
void glPBufferRendering();
void glWidgetReparent();
+ void stackedFBOs();
void colormap();
};
@@ -770,6 +772,113 @@ void tst_QGL::glFBORendering()
QCOMPARE(fb.pixel(192, 64), QColor(Qt::green).rgb());
}
+
+// Tests multiple QPainters active on different FBOs at the same time, with
+// interleaving painting. Performance-wise, this is sub-optimal, but it still
+// has to work flawlessly
+void tst_QGL::multipleFBOInterleavedRendering()
+{
+ if (!QGLFramebufferObject::hasOpenGLFramebufferObjects())
+ QSKIP("QGLFramebufferObject not supported on this platform", SkipSingle);
+
+ QGLWidget glw;
+ glw.makeCurrent();
+
+ // No multisample with combined depth/stencil attachment:
+ QGLFramebufferObjectFormat fboFormat(0, QGLFramebufferObject::CombinedDepthStencil);
+
+ QGLFramebufferObject *fbo1 = new QGLFramebufferObject(256, 128, fboFormat);
+ QGLFramebufferObject *fbo2 = new QGLFramebufferObject(256, 128, fboFormat);
+ QGLFramebufferObject *fbo3 = new QGLFramebufferObject(256, 128, fboFormat);
+
+ QPainter fbo1Painter;
+ QPainter fbo2Painter;
+ QPainter fbo3Painter;
+
+ QVERIFY(fbo1Painter.begin(fbo1));
+ QVERIFY(fbo2Painter.begin(fbo2));
+ QVERIFY(fbo3Painter.begin(fbo3));
+
+ QPainterPath intersectingPath;
+ intersectingPath.moveTo(0, 0);
+ intersectingPath.lineTo(100, 0);
+ intersectingPath.lineTo(0, 100);
+ intersectingPath.lineTo(100, 100);
+ intersectingPath.closeSubpath();
+
+ QPainterPath trianglePath;
+ trianglePath.moveTo(50, 0);
+ trianglePath.lineTo(100, 100);
+ trianglePath.lineTo(0, 100);
+ trianglePath.closeSubpath();
+
+ fbo1Painter.fillRect(0, 0, fbo1->width(), fbo1->height(), Qt::red); // Background
+ fbo2Painter.fillRect(0, 0, fbo2->width(), fbo2->height(), Qt::green); // Background
+ fbo3Painter.fillRect(0, 0, fbo3->width(), fbo3->height(), Qt::blue); // Background
+
+ fbo1Painter.translate(14, 14);
+ fbo2Painter.translate(14, 14);
+ fbo3Painter.translate(14, 14);
+
+ fbo1Painter.fillPath(intersectingPath, Qt::blue); // Test stencil buffer works
+ fbo2Painter.fillPath(intersectingPath, Qt::red); // Test stencil buffer works
+ fbo3Painter.fillPath(intersectingPath, Qt::green); // Test stencil buffer works
+
+ fbo1Painter.translate(128, 0);
+ fbo2Painter.translate(128, 0);
+ fbo3Painter.translate(128, 0);
+
+ fbo1Painter.setClipPath(trianglePath);
+ fbo2Painter.setClipPath(trianglePath);
+ fbo3Painter.setClipPath(trianglePath);
+
+ fbo1Painter.setTransform(QTransform()); // reset xform
+ fbo2Painter.setTransform(QTransform()); // reset xform
+ fbo3Painter.setTransform(QTransform()); // reset xform
+
+ fbo1Painter.fillRect(0, 0, fbo1->width(), fbo1->height(), Qt::green);
+ fbo2Painter.fillRect(0, 0, fbo2->width(), fbo2->height(), Qt::blue);
+ fbo3Painter.fillRect(0, 0, fbo3->width(), fbo3->height(), Qt::red);
+
+ fbo1Painter.end();
+ fbo2Painter.end();
+ fbo3Painter.end();
+
+ QImage fb1 = fbo1->toImage().convertToFormat(QImage::Format_RGB32);
+ QImage fb2 = fbo2->toImage().convertToFormat(QImage::Format_RGB32);
+ QImage fb3 = fbo3->toImage().convertToFormat(QImage::Format_RGB32);
+ delete fbo1;
+ delete fbo2;
+ delete fbo3;
+
+ // As we're doing more than trivial painting, we can't just compare to
+ // an image rendered with raster. Instead, we sample at well-defined
+ // test-points:
+ QCOMPARE(fb1.pixel(39, 64), QColor(Qt::red).rgb());
+ QCOMPARE(fb1.pixel(89, 64), QColor(Qt::red).rgb());
+ QCOMPARE(fb1.pixel(64, 39), QColor(Qt::blue).rgb());
+ QCOMPARE(fb1.pixel(64, 89), QColor(Qt::blue).rgb());
+ QCOMPARE(fb1.pixel(167, 39), QColor(Qt::red).rgb());
+ QCOMPARE(fb1.pixel(217, 39), QColor(Qt::red).rgb());
+ QCOMPARE(fb1.pixel(192, 64), QColor(Qt::green).rgb());
+
+ QCOMPARE(fb2.pixel(39, 64), QColor(Qt::green).rgb());
+ QCOMPARE(fb2.pixel(89, 64), QColor(Qt::green).rgb());
+ QCOMPARE(fb2.pixel(64, 39), QColor(Qt::red).rgb());
+ QCOMPARE(fb2.pixel(64, 89), QColor(Qt::red).rgb());
+ QCOMPARE(fb2.pixel(167, 39), QColor(Qt::green).rgb());
+ QCOMPARE(fb2.pixel(217, 39), QColor(Qt::green).rgb());
+ QCOMPARE(fb2.pixel(192, 64), QColor(Qt::blue).rgb());
+
+ QCOMPARE(fb3.pixel(39, 64), QColor(Qt::blue).rgb());
+ QCOMPARE(fb3.pixel(89, 64), QColor(Qt::blue).rgb());
+ QCOMPARE(fb3.pixel(64, 39), QColor(Qt::green).rgb());
+ QCOMPARE(fb3.pixel(64, 89), QColor(Qt::green).rgb());
+ QCOMPARE(fb3.pixel(167, 39), QColor(Qt::blue).rgb());
+ QCOMPARE(fb3.pixel(217, 39), QColor(Qt::blue).rgb());
+ QCOMPARE(fb3.pixel(192, 64), QColor(Qt::red).rgb());
+}
+
class FBOUseInGLWidget : public QGLWidget
{
public:
@@ -890,6 +999,108 @@ void tst_QGL::glWidgetReparent()
delete widget;
}
+// When using multiple FBOs at the same time, unbinding one FBO should re-bind the
+// previous. I.e. It should be possible to have a stack of FBOs where pop'ing there
+// top re-binds the one underneeth.
+void tst_QGL::stackedFBOs()
+{
+ if (!QGLFramebufferObject::hasOpenGLFramebufferObjects())
+ QSKIP("QGLFramebufferObject not supported on this platform", SkipSingle);
+
+ QGLWidget glw;
+ glw.show();
+
+#ifdef Q_WS_X11
+ qt_x11_wait_for_window_manager(&glw);
+#endif
+ QTest::qWait(200);
+
+ glw.makeCurrent();
+
+ // No multisample with combined depth/stencil attachment:
+ QGLFramebufferObjectFormat fboFormat(0, QGLFramebufferObject::CombinedDepthStencil);
+
+ // Don't complicate things by using NPOT:
+ QGLFramebufferObject *fbo1 = new QGLFramebufferObject(128, 128, fboFormat);
+ QGLFramebufferObject *fbo2 = new QGLFramebufferObject(128, 128, fboFormat);
+ QGLFramebufferObject *fbo3 = new QGLFramebufferObject(128, 128, fboFormat);
+
+ glClearColor(1.0, 0.0, 1.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ fbo1->bind();
+ glClearColor(1.0, 0.0, 0.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ fbo2->bind();
+ glClearColor(0.0, 1.0, 0.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ fbo3->bind();
+ glClearColor(0.0, 0.0, 1.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glScissor(32, 32, 64, 64);
+ glEnable(GL_SCISSOR_TEST);
+ glClearColor(0.0, 1.0, 1.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ fbo3->release();
+
+ // Scissor rect & test should be left untouched by the fbo release...
+ glClearColor(0.0, 0.0, 0.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ fbo2->release();
+
+ glClearColor(1.0, 1.0, 1.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ fbo1->release();
+
+ glClearColor(1.0, 1.0, 0.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ glw.swapBuffers();
+
+ QImage widgetFB = glw.grabFrameBuffer(false).convertToFormat(QImage::Format_RGB32);
+ QImage fb1 = fbo1->toImage().convertToFormat(QImage::Format_RGB32);
+ QImage fb2 = fbo2->toImage().convertToFormat(QImage::Format_RGB32);
+ QImage fb3 = fbo3->toImage().convertToFormat(QImage::Format_RGB32);
+
+ delete fbo1;
+ delete fbo2;
+ delete fbo3;
+
+ QImage widgetReference(widgetFB.size(), widgetFB.format());
+ QImage fb1Reference(fb1.size(), fb1.format());
+ QImage fb2Reference(fb2.size(), fb2.format());
+ QImage fb3Reference(fb3.size(), fb3.format());
+
+ QPainter widgetReferencePainter(&widgetReference);
+ QPainter fb1ReferencePainter(&fb1Reference);
+ QPainter fb2ReferencePainter(&fb2Reference);
+ QPainter fb3ReferencePainter(&fb3Reference);
+
+ widgetReferencePainter.fillRect(0, 0, widgetReference.width(), widgetReference.height(), Qt::magenta);
+ fb1ReferencePainter.fillRect(0, 0, fb1Reference.width(), fb1Reference.height(), Qt::red);
+ fb2ReferencePainter.fillRect(0, 0, fb2Reference.width(), fb2Reference.height(), Qt::green);
+ fb3ReferencePainter.fillRect(0, 0, fb3Reference.width(), fb3Reference.height(), Qt::blue);
+
+ // Flip y-coords to match GL for the widget (which can be any size)
+ widgetReferencePainter.fillRect(32, glw.height() - 96, 64, 64, Qt::yellow);
+ fb1ReferencePainter.fillRect(32, 32, 64, 64, Qt::white);
+ fb2ReferencePainter.fillRect(32, 32, 64, 64, Qt::black);
+ fb3ReferencePainter.fillRect(32, 32, 64, 64, Qt::cyan);
+
+ widgetReferencePainter.end();
+ fb1ReferencePainter.end();
+ fb2ReferencePainter.end();
+ fb3ReferencePainter.end();
+
+ QCOMPARE(widgetFB, widgetReference);
+ QCOMPARE(fb1, fb1Reference);
+ QCOMPARE(fb2, fb2Reference);
+ QCOMPARE(fb3, fb3Reference);
+}
+
+
class ColormapExtended : public QGLColormap
{
public: