tests/auto/qgl/tst_qgl.cpp
changeset 3 41300fa6a67c
parent 0 1918ee327afb
child 4 3b1da2848fc7
child 7 f7bc934e204c
child 18 2f34d5167611
equal deleted inserted replaced
2:56cd8111b7f7 3:41300fa6a67c
    73     void getSetCheck();
    73     void getSetCheck();
    74     void openGLVersionCheck();
    74     void openGLVersionCheck();
    75     void graphicsViewClipping();
    75     void graphicsViewClipping();
    76     void partialGLWidgetUpdates_data();
    76     void partialGLWidgetUpdates_data();
    77     void partialGLWidgetUpdates();
    77     void partialGLWidgetUpdates();
       
    78     void glWidgetWithAlpha();
    78     void glWidgetRendering();
    79     void glWidgetRendering();
       
    80     void glFBOSimpleRendering();
    79     void glFBORendering();
    81     void glFBORendering();
    80     void multipleFBOInterleavedRendering();
    82     void multipleFBOInterleavedRendering();
    81     void glFBOUseInGLWidget();
    83     void glFBOUseInGLWidget();
    82     void glPBufferRendering();
    84     void glPBufferRendering();
    83     void glWidgetReparent();
    85     void glWidgetReparent();
    84     void glWidgetRenderPixmap();
    86     void glWidgetRenderPixmap();
    85     void stackedFBOs();
       
    86     void colormap();
    87     void colormap();
    87     void fboFormat();
    88     void fboFormat();
    88     void testDontCrashOnDanglingResources();
    89     void testDontCrashOnDanglingResources();
    89     void replaceClipping();
    90     void replaceClipping();
    90     void clipTest();
    91     void clipTest();
   115 public:
   116 public:
   116     MyGLWidget() : QGLWidget() {}
   117     MyGLWidget() : QGLWidget() {}
   117     bool autoBufferSwap() const { return QGLWidget::autoBufferSwap(); }
   118     bool autoBufferSwap() const { return QGLWidget::autoBufferSwap(); }
   118     void setAutoBufferSwap(bool on) { QGLWidget::setAutoBufferSwap(on); }
   119     void setAutoBufferSwap(bool on) { QGLWidget::setAutoBufferSwap(on); }
   119 };
   120 };
       
   121 
       
   122 static int appDefaultDepth()
       
   123 {
       
   124     static int depth = 0;
       
   125     if (depth == 0) {
       
   126         QPixmap pm(1, 1);
       
   127         depth = pm.depth();
       
   128     }
       
   129     return depth;
       
   130 }
   120 
   131 
   121 // Using INT_MIN and INT_MAX will cause failures on systems
   132 // Using INT_MIN and INT_MAX will cause failures on systems
   122 // where "int" is 64-bit, so use the explicit values instead.
   133 // where "int" is 64-bit, so use the explicit values instead.
   123 #define TEST_INT_MIN    (-2147483647 - 1)
   134 #define TEST_INT_MIN    (-2147483647 - 1)
   124 #define TEST_INT_MAX    2147483647
   135 #define TEST_INT_MAX    2147483647
   239     obj1.setStencilBufferSize(TEST_INT_MAX);
   250     obj1.setStencilBufferSize(TEST_INT_MAX);
   240     QCOMPARE(TEST_INT_MAX, obj1.stencilBufferSize());
   251     QCOMPARE(TEST_INT_MAX, obj1.stencilBufferSize());
   241 
   252 
   242     // bool QGLFormat::sampleBuffers()
   253     // bool QGLFormat::sampleBuffers()
   243     // void QGLFormat::setSampleBuffers(bool)
   254     // void QGLFormat::setSampleBuffers(bool)
   244 #if !defined(QT_OPENGL_ES_2)
       
   245     QCOMPARE(false, obj1.sampleBuffers());
   255     QCOMPARE(false, obj1.sampleBuffers());
   246     QVERIFY(!obj1.testOption(QGL::SampleBuffers));
   256     QVERIFY(!obj1.testOption(QGL::SampleBuffers));
   247     QVERIFY(obj1.testOption(QGL::NoSampleBuffers));
   257     QVERIFY(obj1.testOption(QGL::NoSampleBuffers));
   248 #else
   258 
   249     QCOMPARE(true, obj1.sampleBuffers());
       
   250     QVERIFY(obj1.testOption(QGL::SampleBuffers));
       
   251     QVERIFY(!obj1.testOption(QGL::NoSampleBuffers));
       
   252 #endif
       
   253     obj1.setSampleBuffers(false);
   259     obj1.setSampleBuffers(false);
   254     QCOMPARE(false, obj1.sampleBuffers());
   260     QCOMPARE(false, obj1.sampleBuffers());
   255     QVERIFY(obj1.testOption(QGL::NoSampleBuffers));
   261     QVERIFY(obj1.testOption(QGL::NoSampleBuffers));
   256     obj1.setSampleBuffers(true);
   262     obj1.setSampleBuffers(true);
   257     QCOMPARE(true, obj1.sampleBuffers());
   263     QCOMPARE(true, obj1.sampleBuffers());
   700     QVERIFY(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_1);
   706     QVERIFY(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_1_1);
   701 #endif //defined(QT_OPENGL_ES_1)
   707 #endif //defined(QT_OPENGL_ES_1)
   702 #endif //QT_BUILD_INTERNAL
   708 #endif //QT_BUILD_INTERNAL
   703 }
   709 }
   704 
   710 
       
   711 static bool fuzzyComparePixels(const QRgb testPixel, const QRgb refPixel, const char* file, int line, int x = -1, int y = -1)
       
   712 {
       
   713     static int maxFuzz = 1;
       
   714     static bool maxFuzzSet = false;
       
   715 
       
   716     // On 16 bpp systems, we need to allow for more fuzz:
       
   717     if (!maxFuzzSet) {
       
   718         maxFuzzSet = true;
       
   719         if (appDefaultDepth() < 24)
       
   720             maxFuzz = 32;
       
   721     }
       
   722 
       
   723     int redFuzz = qAbs(qRed(testPixel) - qRed(refPixel));
       
   724     int greenFuzz = qAbs(qGreen(testPixel) - qGreen(refPixel));
       
   725     int blueFuzz = qAbs(qBlue(testPixel) - qBlue(refPixel));
       
   726     int alphaFuzz = qAbs(qAlpha(testPixel) - qAlpha(refPixel));
       
   727 
       
   728     if (refPixel != 0 && testPixel == 0) {
       
   729         QString msg;
       
   730         if (x >= 0) {
       
   731             msg = QString("Test pixel [%1, %2] is null (black) when it should be (%3,%4,%5,%6)")
       
   732                             .arg(x).arg(y)
       
   733                             .arg(qRed(refPixel)).arg(qGreen(refPixel)).arg(qBlue(refPixel)).arg(qAlpha(refPixel));
       
   734         } else {
       
   735             msg = QString("Test pixel is null (black) when it should be (%2,%3,%4,%5)")
       
   736                             .arg(qRed(refPixel)).arg(qGreen(refPixel)).arg(qBlue(refPixel)).arg(qAlpha(refPixel));
       
   737         }
       
   738 
       
   739         QTest::qFail(msg.toLatin1(), file, line);
       
   740         return false;
       
   741     }
       
   742 
       
   743     if (redFuzz > maxFuzz || greenFuzz > maxFuzz || blueFuzz > maxFuzz || alphaFuzz > maxFuzz) {
       
   744         QString msg;
       
   745 
       
   746         if (x >= 0)
       
   747             msg = QString("Pixel [%1,%2]: ").arg(x).arg(y);
       
   748         else
       
   749             msg = QString("Pixel ");
       
   750 
       
   751         msg += QString("Max fuzz (%1) exceeded: (%2,%3,%4,%5) vs (%6,%7,%8,%9)")
       
   752                       .arg(maxFuzz)
       
   753                       .arg(qRed(testPixel)).arg(qGreen(testPixel)).arg(qBlue(testPixel)).arg(qAlpha(testPixel))
       
   754                       .arg(qRed(refPixel)).arg(qGreen(refPixel)).arg(qBlue(refPixel)).arg(qAlpha(refPixel));
       
   755         QTest::qFail(msg.toLatin1(), file, line);
       
   756         return false;
       
   757     }
       
   758     return true;
       
   759 }
       
   760 
       
   761 static void fuzzyCompareImages(const QImage &testImage, const QImage &referenceImage, const char* file, int line)
       
   762 {
       
   763     QCOMPARE(testImage.width(), referenceImage.width());
       
   764     QCOMPARE(testImage.height(), referenceImage.height());
       
   765 
       
   766     for (int y = 0; y < testImage.height(); y++) {
       
   767         for (int x = 0; x < testImage.width(); x++) {
       
   768             if (!fuzzyComparePixels(testImage.pixel(x, y), referenceImage.pixel(x, y), file, line, x, y)) {
       
   769                 // Might as well save the images for easier debugging:
       
   770                 referenceImage.save("referenceImage.png");
       
   771                 testImage.save("testImage.png");
       
   772                 return;
       
   773             }
       
   774         }
       
   775     }
       
   776 }
       
   777 
       
   778 #define QFUZZY_COMPARE_IMAGES(A,B) \
       
   779             fuzzyCompareImages(A, B, __FILE__, __LINE__)
       
   780 
       
   781 #define QFUZZY_COMPARE_PIXELS(A,B) \
       
   782             fuzzyComparePixels(A, B, __FILE__, __LINE__)
       
   783 
   705 class UnclippedWidget : public QWidget
   784 class UnclippedWidget : public QWidget
   706 {
   785 {
   707 public:
   786 public:
   708     void paintEvent(QPaintEvent *)
   787     void paintEvent(QPaintEvent *)
   709     {
   788     {
   721     QGraphicsScene scene;
   800     QGraphicsScene scene;
   722 
   801 
   723     scene.addWidget(widget)->setPos(0, 0);
   802     scene.addWidget(widget)->setPos(0, 0);
   724 
   803 
   725     QGraphicsView view(&scene);
   804     QGraphicsView view(&scene);
       
   805 #ifdef Q_WS_QWS
       
   806     view.setWindowFlags(Qt::FramelessWindowHint);
       
   807 #endif
   726     view.resize(2*size, 2*size);
   808     view.resize(2*size, 2*size);
   727 
   809 
   728     QGLWidget *viewport = new QGLWidget;
   810     QGLWidget *viewport = new QGLWidget;
   729     view.setViewport(viewport);
   811     view.setViewport(viewport);
   730     view.show();
   812     view.show();
   745     QPainter p(&expected);
   827     QPainter p(&expected);
   746     p.fillRect(expected.rect(), Qt::white);
   828     p.fillRect(expected.rect(), Qt::white);
   747     p.fillRect(QRect(0, 0, size, size), Qt::black);
   829     p.fillRect(QRect(0, 0, size, size), Qt::black);
   748     p.end();
   830     p.end();
   749 
   831 
   750     QCOMPARE(image, expected);
   832     QFUZZY_COMPARE_IMAGES(image, expected);
   751 }
   833 }
   752 
   834 
   753 void tst_QGL::partialGLWidgetUpdates_data()
   835 void tst_QGL::partialGLWidgetUpdates_data()
   754 {
   836 {
   755     QTest::addColumn<bool>("doubleBufferedContext");
   837     QTest::addColumn<bool>("doubleBufferedContext");
   836     p.begin(&reference);
   918     p.begin(&reference);
   837     p.fillRect(0, 0, 128, 128, Qt::red);
   919     p.fillRect(0, 0, 128, 128, Qt::red);
   838     p.fillRect(32, 32, 64, 64, Qt::blue);
   920     p.fillRect(32, 32, 64, 64, Qt::blue);
   839     p.end();
   921     p.end();
   840 
   922 
   841     QCOMPARE(fb, reference);
   923     QFUZZY_COMPARE_IMAGES(fb, reference);
       
   924 }
       
   925 
       
   926 void tst_QGL::glWidgetWithAlpha()
       
   927 {
       
   928     QGLWidget* w = new QGLWidget(QGLFormat(QGL::AlphaChannel));
       
   929     w->show();
       
   930 #ifdef Q_WS_X11
       
   931     qt_x11_wait_for_window_manager(w);
       
   932 #endif
       
   933 
       
   934     delete w;
   842 }
   935 }
   843 
   936 
   844 class GLWidget : public QGLWidget
   937 class GLWidget : public QGLWidget
   845 {
   938 {
   846 public:
   939 public:
   855         QPaintEngine* pe = p.paintEngine();
   948         QPaintEngine* pe = p.paintEngine();
   856         engineType = pe->type();
   949         engineType = pe->type();
   857 
   950 
   858         // This test only ensures it's possible to paint onto a QGLWidget. Full
   951         // This test only ensures it's possible to paint onto a QGLWidget. Full
   859         // paint engine feature testing is way out of scope!
   952         // paint engine feature testing is way out of scope!
   860 
   953         p.fillRect(-1, -1, width()+2, height()+2, Qt::red);
   861         p.fillRect(0, 0, width(), height(), Qt::red);
   954 
   862         // No p.end() or swap buffers, should be done automatically
   955         // No p.end() or swap buffers, should be done automatically
   863     }
   956     }
   864 
   957 
   865 };
   958 };
   866 
   959 
   867 void tst_QGL::glWidgetRendering()
   960 void tst_QGL::glWidgetRendering()
   868 {
   961 {
   869     GLWidget w;
   962     GLWidget w;
       
   963 #ifdef Q_WS_QWS
       
   964     w.setWindowFlags(Qt::FramelessWindowHint);
       
   965 #endif
       
   966     w.setGeometry(100, 100, 200, 200);
   870     w.show();
   967     w.show();
   871 
   968 
   872 #ifdef Q_WS_X11
   969 #ifdef Q_WS_X11
   873     qt_x11_wait_for_window_manager(&w);
   970     qt_x11_wait_for_window_manager(&w);
   874 #endif
   971 #endif
   879 
   976 
   880     QImage fb = w.grabFrameBuffer(false).convertToFormat(QImage::Format_RGB32);
   977     QImage fb = w.grabFrameBuffer(false).convertToFormat(QImage::Format_RGB32);
   881     QImage reference(fb.size(), QImage::Format_RGB32);
   978     QImage reference(fb.size(), QImage::Format_RGB32);
   882     reference.fill(0xffff0000);
   979     reference.fill(0xffff0000);
   883 
   980 
   884     QCOMPARE(fb, reference);
   981     QFUZZY_COMPARE_IMAGES(fb, reference);
       
   982 }
       
   983 
       
   984 void tst_QGL::glFBOSimpleRendering()
       
   985 {
       
   986     if (!QGLFramebufferObject::hasOpenGLFramebufferObjects())
       
   987         QSKIP("QGLFramebufferObject not supported on this platform", SkipSingle);
       
   988 
       
   989     QGLWidget glw;
       
   990     glw.makeCurrent();
       
   991 
       
   992     // No multisample with combined depth/stencil attachment:
       
   993     QGLFramebufferObjectFormat fboFormat;
       
   994     fboFormat.setAttachment(QGLFramebufferObject::NoAttachment);
       
   995 
       
   996     // Don't complicate things by using NPOT:
       
   997     QGLFramebufferObject *fbo = new QGLFramebufferObject(256, 128, fboFormat);
       
   998 
       
   999     fbo->bind();
       
  1000 
       
  1001     glClearColor(1.0, 0.0, 0.0, 1.0);
       
  1002     glClear(GL_COLOR_BUFFER_BIT);
       
  1003     glFinish();
       
  1004 
       
  1005     QImage fb = fbo->toImage().convertToFormat(QImage::Format_RGB32);
       
  1006     QImage reference(fb.size(), QImage::Format_RGB32);
       
  1007     reference.fill(0xffff0000);
       
  1008 
       
  1009     QFUZZY_COMPARE_IMAGES(fb, reference);
       
  1010 
       
  1011     delete fbo;
   885 }
  1012 }
   886 
  1013 
   887 // NOTE: This tests that CombinedDepthStencil attachment works by assuming the
  1014 // NOTE: This tests that CombinedDepthStencil attachment works by assuming the
   888 //       GL2 engine is being used and is implemented the same way as it was when
  1015 //       GL2 engine is being used and is implemented the same way as it was when
   889 //       this autotest was written. If this is not the case, there may be some
  1016 //       this autotest was written. If this is not the case, there may be some
   934     delete fbo;
  1061     delete fbo;
   935 
  1062 
   936     // As we're doing more than trivial painting, we can't just compare to
  1063     // As we're doing more than trivial painting, we can't just compare to
   937     // an image rendered with raster. Instead, we sample at well-defined
  1064     // an image rendered with raster. Instead, we sample at well-defined
   938     // test-points:
  1065     // test-points:
   939     QCOMPARE(fb.pixel(39, 64), QColor(Qt::red).rgb());
  1066     QFUZZY_COMPARE_PIXELS(fb.pixel(39, 64), QColor(Qt::red).rgb());
   940     QCOMPARE(fb.pixel(89, 64), QColor(Qt::red).rgb());
  1067     QFUZZY_COMPARE_PIXELS(fb.pixel(89, 64), QColor(Qt::red).rgb());
   941     QCOMPARE(fb.pixel(64, 39), QColor(Qt::blue).rgb());
  1068     QFUZZY_COMPARE_PIXELS(fb.pixel(64, 39), QColor(Qt::blue).rgb());
   942     QCOMPARE(fb.pixel(64, 89), QColor(Qt::blue).rgb());
  1069     QFUZZY_COMPARE_PIXELS(fb.pixel(64, 89), QColor(Qt::blue).rgb());
   943 
  1070 
   944     QCOMPARE(fb.pixel(167, 39), QColor(Qt::red).rgb());
  1071     QFUZZY_COMPARE_PIXELS(fb.pixel(167, 39), QColor(Qt::red).rgb());
   945     QCOMPARE(fb.pixel(217, 39), QColor(Qt::red).rgb());
  1072     QFUZZY_COMPARE_PIXELS(fb.pixel(217, 39), QColor(Qt::red).rgb());
   946     QCOMPARE(fb.pixel(192, 64), QColor(Qt::green).rgb());
  1073     QFUZZY_COMPARE_PIXELS(fb.pixel(192, 64), QColor(Qt::green).rgb());
   947 }
  1074 }
   948 
  1075 
   949 
  1076 
   950 // Tests multiple QPainters active on different FBOs at the same time, with
  1077 // Tests multiple QPainters active on different FBOs at the same time, with
   951 // interleaving painting. Performance-wise, this is sub-optimal, but it still
  1078 // interleaving painting. Performance-wise, this is sub-optimal, but it still
  1032     delete fbo3;
  1159     delete fbo3;
  1033 
  1160 
  1034     // As we're doing more than trivial painting, we can't just compare to
  1161     // As we're doing more than trivial painting, we can't just compare to
  1035     // an image rendered with raster. Instead, we sample at well-defined
  1162     // an image rendered with raster. Instead, we sample at well-defined
  1036     // test-points:
  1163     // test-points:
  1037     QCOMPARE(fb1.pixel(39, 64), QColor(Qt::red).rgb());
  1164     QFUZZY_COMPARE_PIXELS(fb1.pixel(39, 64), QColor(Qt::red).rgb());
  1038     QCOMPARE(fb1.pixel(89, 64), QColor(Qt::red).rgb());
  1165     QFUZZY_COMPARE_PIXELS(fb1.pixel(89, 64), QColor(Qt::red).rgb());
  1039     QCOMPARE(fb1.pixel(64, 39), QColor(Qt::blue).rgb());
  1166     QFUZZY_COMPARE_PIXELS(fb1.pixel(64, 39), QColor(Qt::blue).rgb());
  1040     QCOMPARE(fb1.pixel(64, 89), QColor(Qt::blue).rgb());
  1167     QFUZZY_COMPARE_PIXELS(fb1.pixel(64, 89), QColor(Qt::blue).rgb());
  1041     QCOMPARE(fb1.pixel(167, 39), QColor(Qt::red).rgb());
  1168     QFUZZY_COMPARE_PIXELS(fb1.pixel(167, 39), QColor(Qt::red).rgb());
  1042     QCOMPARE(fb1.pixel(217, 39), QColor(Qt::red).rgb());
  1169     QFUZZY_COMPARE_PIXELS(fb1.pixel(217, 39), QColor(Qt::red).rgb());
  1043     QCOMPARE(fb1.pixel(192, 64), QColor(Qt::green).rgb());
  1170     QFUZZY_COMPARE_PIXELS(fb1.pixel(192, 64), QColor(Qt::green).rgb());
  1044 
  1171 
  1045     QCOMPARE(fb2.pixel(39, 64), QColor(Qt::green).rgb());
  1172     QFUZZY_COMPARE_PIXELS(fb2.pixel(39, 64), QColor(Qt::green).rgb());
  1046     QCOMPARE(fb2.pixel(89, 64), QColor(Qt::green).rgb());
  1173     QFUZZY_COMPARE_PIXELS(fb2.pixel(89, 64), QColor(Qt::green).rgb());
  1047     QCOMPARE(fb2.pixel(64, 39), QColor(Qt::red).rgb());
  1174     QFUZZY_COMPARE_PIXELS(fb2.pixel(64, 39), QColor(Qt::red).rgb());
  1048     QCOMPARE(fb2.pixel(64, 89), QColor(Qt::red).rgb());
  1175     QFUZZY_COMPARE_PIXELS(fb2.pixel(64, 89), QColor(Qt::red).rgb());
  1049     QCOMPARE(fb2.pixel(167, 39), QColor(Qt::green).rgb());
  1176     QFUZZY_COMPARE_PIXELS(fb2.pixel(167, 39), QColor(Qt::green).rgb());
  1050     QCOMPARE(fb2.pixel(217, 39), QColor(Qt::green).rgb());
  1177     QFUZZY_COMPARE_PIXELS(fb2.pixel(217, 39), QColor(Qt::green).rgb());
  1051     QCOMPARE(fb2.pixel(192, 64), QColor(Qt::blue).rgb());
  1178     QFUZZY_COMPARE_PIXELS(fb2.pixel(192, 64), QColor(Qt::blue).rgb());
  1052 
  1179 
  1053     QCOMPARE(fb3.pixel(39, 64), QColor(Qt::blue).rgb());
  1180     QFUZZY_COMPARE_PIXELS(fb3.pixel(39, 64), QColor(Qt::blue).rgb());
  1054     QCOMPARE(fb3.pixel(89, 64), QColor(Qt::blue).rgb());
  1181     QFUZZY_COMPARE_PIXELS(fb3.pixel(89, 64), QColor(Qt::blue).rgb());
  1055     QCOMPARE(fb3.pixel(64, 39), QColor(Qt::green).rgb());
  1182     QFUZZY_COMPARE_PIXELS(fb3.pixel(64, 39), QColor(Qt::green).rgb());
  1056     QCOMPARE(fb3.pixel(64, 89), QColor(Qt::green).rgb());
  1183     QFUZZY_COMPARE_PIXELS(fb3.pixel(64, 89), QColor(Qt::green).rgb());
  1057     QCOMPARE(fb3.pixel(167, 39), QColor(Qt::blue).rgb());
  1184     QFUZZY_COMPARE_PIXELS(fb3.pixel(167, 39), QColor(Qt::blue).rgb());
  1058     QCOMPARE(fb3.pixel(217, 39), QColor(Qt::blue).rgb());
  1185     QFUZZY_COMPARE_PIXELS(fb3.pixel(217, 39), QColor(Qt::blue).rgb());
  1059     QCOMPARE(fb3.pixel(192, 64), QColor(Qt::red).rgb());
  1186     QFUZZY_COMPARE_PIXELS(fb3.pixel(192, 64), QColor(Qt::red).rgb());
  1060 }
  1187 }
  1061 
  1188 
  1062 class FBOUseInGLWidget : public QGLWidget
  1189 class FBOUseInGLWidget : public QGLWidget
  1063 {
  1190 {
  1064 public:
  1191 public:
  1074         fboFormat.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
  1201         fboFormat.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
  1075         QGLFramebufferObject *fbo = new QGLFramebufferObject(128, 128, fboFormat);
  1202         QGLFramebufferObject *fbo = new QGLFramebufferObject(128, 128, fboFormat);
  1076 
  1203 
  1077         QPainter fboPainter;
  1204         QPainter fboPainter;
  1078         fboPainterBeginOk = fboPainter.begin(fbo);
  1205         fboPainterBeginOk = fboPainter.begin(fbo);
  1079         fboPainter.fillRect(0, 0, 128, 128, Qt::red);
  1206         fboPainter.fillRect(-1, -1, 130, 130, Qt::red);
  1080         fboPainter.end();
  1207         fboPainter.end();
  1081         fboImage = fbo->toImage();
  1208         fboImage = fbo->toImage();
  1082 
  1209 
  1083         widgetPainter.fillRect(rect(), Qt::blue);
  1210         widgetPainter.fillRect(-1, -1, width()+2, width()+2, Qt::blue);
  1084 
  1211 
  1085         delete fbo;
  1212         delete fbo;
  1086     }
  1213     }
  1087 
  1214 
  1088 };
  1215 };
  1091 {
  1218 {
  1092     if (!QGLFramebufferObject::hasOpenGLFramebufferObjects())
  1219     if (!QGLFramebufferObject::hasOpenGLFramebufferObjects())
  1093         QSKIP("QGLFramebufferObject not supported on this platform", SkipSingle);
  1220         QSKIP("QGLFramebufferObject not supported on this platform", SkipSingle);
  1094 
  1221 
  1095     FBOUseInGLWidget w;
  1222     FBOUseInGLWidget w;
       
  1223 #ifdef Q_WS_QWS
       
  1224     w.setWindowFlags(Qt::FramelessWindowHint);
       
  1225 #endif
  1096     w.resize(128, 128);
  1226     w.resize(128, 128);
  1097     w.show();
  1227     w.show();
  1098 
  1228 
  1099 #ifdef Q_WS_X11
  1229 #ifdef Q_WS_X11
  1100     qt_x11_wait_for_window_manager(&w);
  1230     qt_x11_wait_for_window_manager(&w);
  1105     QVERIFY(w.fboPainterBeginOk);
  1235     QVERIFY(w.fboPainterBeginOk);
  1106 
  1236 
  1107     QImage widgetFB = w.grabFrameBuffer(false);
  1237     QImage widgetFB = w.grabFrameBuffer(false);
  1108     QImage widgetReference(widgetFB.size(), widgetFB.format());
  1238     QImage widgetReference(widgetFB.size(), widgetFB.format());
  1109     widgetReference.fill(0xff0000ff);
  1239     widgetReference.fill(0xff0000ff);
  1110     QCOMPARE(widgetFB, widgetReference);
  1240     QFUZZY_COMPARE_IMAGES(widgetFB, widgetReference);
  1111 
  1241 
  1112     QImage fboReference(w.fboImage.size(), w.fboImage.format());
  1242     QImage fboReference(w.fboImage.size(), w.fboImage.format());
  1113     fboReference.fill(0xffff0000);
  1243     fboReference.fill(0xffff0000);
  1114     QCOMPARE(w.fboImage, fboReference);
  1244     QFUZZY_COMPARE_IMAGES(w.fboImage, fboReference);
  1115 }
  1245 }
  1116 
  1246 
  1117 void tst_QGL::glWidgetReparent()
  1247 void tst_QGL::glWidgetReparent()
  1118 {
  1248 {
  1119     // Try it as a top-level first:
  1249     // Try it as a top-level first:
  1203 
  1333 
  1204     QImage fb = pm.toImage().convertToFormat(QImage::Format_RGB32);
  1334     QImage fb = pm.toImage().convertToFormat(QImage::Format_RGB32);
  1205     QImage reference(fb.size(), QImage::Format_RGB32);
  1335     QImage reference(fb.size(), QImage::Format_RGB32);
  1206     reference.fill(0xffff0000);
  1336     reference.fill(0xffff0000);
  1207 
  1337 
  1208     QCOMPARE(fb, reference);
  1338     QFUZZY_COMPARE_IMAGES(fb, reference);
  1209 }
  1339 }
  1210 
       
  1211 
       
  1212 // When using multiple FBOs at the same time, unbinding one FBO should re-bind the
       
  1213 // previous. I.e. It should be possible to have a stack of FBOs where pop'ing there
       
  1214 // top re-binds the one underneeth.
       
  1215 void tst_QGL::stackedFBOs()
       
  1216 {
       
  1217     if (!QGLFramebufferObject::hasOpenGLFramebufferObjects())
       
  1218         QSKIP("QGLFramebufferObject not supported on this platform", SkipSingle);
       
  1219 
       
  1220     QGLWidget glw;
       
  1221     glw.show();
       
  1222 
       
  1223 #ifdef Q_WS_X11
       
  1224     qt_x11_wait_for_window_manager(&glw);
       
  1225 #endif
       
  1226     QTest::qWait(200);
       
  1227 
       
  1228     glw.makeCurrent();
       
  1229 
       
  1230     // No multisample with combined depth/stencil attachment:
       
  1231     QGLFramebufferObjectFormat fboFormat;
       
  1232     fboFormat.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
       
  1233 
       
  1234     // Don't complicate things by using NPOT:
       
  1235     QGLFramebufferObject *fbo1 = new QGLFramebufferObject(128, 128, fboFormat);
       
  1236     QGLFramebufferObject *fbo2 = new QGLFramebufferObject(128, 128, fboFormat);
       
  1237     QGLFramebufferObject *fbo3 = new QGLFramebufferObject(128, 128, fboFormat);
       
  1238 
       
  1239     glClearColor(1.0, 0.0, 1.0, 1.0);
       
  1240     glClear(GL_COLOR_BUFFER_BIT);
       
  1241 
       
  1242     fbo1->bind();
       
  1243         glClearColor(1.0, 0.0, 0.0, 1.0);
       
  1244         glClear(GL_COLOR_BUFFER_BIT);
       
  1245 
       
  1246         fbo2->bind();
       
  1247             glClearColor(0.0, 1.0, 0.0, 1.0);
       
  1248             glClear(GL_COLOR_BUFFER_BIT);
       
  1249 
       
  1250             fbo3->bind();
       
  1251                 glClearColor(0.0, 0.0, 1.0, 1.0);
       
  1252                 glClear(GL_COLOR_BUFFER_BIT);
       
  1253                 glScissor(32, 32, 64, 64);
       
  1254                 glEnable(GL_SCISSOR_TEST);
       
  1255                 glClearColor(0.0, 1.0, 1.0, 1.0);
       
  1256                 glClear(GL_COLOR_BUFFER_BIT);
       
  1257             fbo3->release();
       
  1258 
       
  1259             // Scissor rect & test should be left untouched by the fbo release...
       
  1260             glClearColor(0.0, 0.0, 0.0, 1.0);
       
  1261             glClear(GL_COLOR_BUFFER_BIT);
       
  1262         fbo2->release();
       
  1263 
       
  1264         glClearColor(1.0, 1.0, 1.0, 1.0);
       
  1265         glClear(GL_COLOR_BUFFER_BIT);
       
  1266     fbo1->release();
       
  1267 
       
  1268     glClearColor(1.0, 1.0, 0.0, 1.0);
       
  1269     glClear(GL_COLOR_BUFFER_BIT);
       
  1270 
       
  1271     glw.swapBuffers();
       
  1272 
       
  1273     QImage widgetFB = glw.grabFrameBuffer(false).convertToFormat(QImage::Format_RGB32);
       
  1274     QImage fb1 = fbo1->toImage().convertToFormat(QImage::Format_RGB32);
       
  1275     QImage fb2 = fbo2->toImage().convertToFormat(QImage::Format_RGB32);
       
  1276     QImage fb3 = fbo3->toImage().convertToFormat(QImage::Format_RGB32);
       
  1277 
       
  1278     delete fbo1;
       
  1279     delete fbo2;
       
  1280     delete fbo3;
       
  1281 
       
  1282     QImage widgetReference(widgetFB.size(), widgetFB.format());
       
  1283     QImage fb1Reference(fb1.size(), fb1.format());
       
  1284     QImage fb2Reference(fb2.size(), fb2.format());
       
  1285     QImage fb3Reference(fb3.size(), fb3.format());
       
  1286 
       
  1287     QPainter widgetReferencePainter(&widgetReference);
       
  1288     QPainter fb1ReferencePainter(&fb1Reference);
       
  1289     QPainter fb2ReferencePainter(&fb2Reference);
       
  1290     QPainter fb3ReferencePainter(&fb3Reference);
       
  1291 
       
  1292     widgetReferencePainter.fillRect(0, 0, widgetReference.width(), widgetReference.height(), Qt::magenta);
       
  1293     fb1ReferencePainter.fillRect(0, 0, fb1Reference.width(), fb1Reference.height(), Qt::red);
       
  1294     fb2ReferencePainter.fillRect(0, 0, fb2Reference.width(), fb2Reference.height(), Qt::green);
       
  1295     fb3ReferencePainter.fillRect(0, 0, fb3Reference.width(), fb3Reference.height(), Qt::blue);
       
  1296 
       
  1297     // Flip y-coords to match GL for the widget (which can be any size)
       
  1298     widgetReferencePainter.fillRect(32, glw.height() - 96, 64, 64, Qt::yellow);
       
  1299     fb1ReferencePainter.fillRect(32, 32, 64, 64, Qt::white);
       
  1300     fb2ReferencePainter.fillRect(32, 32, 64, 64, Qt::black);
       
  1301     fb3ReferencePainter.fillRect(32, 32, 64, 64, Qt::cyan);
       
  1302 
       
  1303     widgetReferencePainter.end();
       
  1304     fb1ReferencePainter.end();
       
  1305     fb2ReferencePainter.end();
       
  1306     fb3ReferencePainter.end();
       
  1307 
       
  1308     QCOMPARE(widgetFB, widgetReference);
       
  1309     QCOMPARE(fb1, fb1Reference);
       
  1310     QCOMPARE(fb2, fb2Reference);
       
  1311     QCOMPARE(fb3, fb3Reference);
       
  1312 }
       
  1313 
       
  1314 
  1340 
  1315 class ColormapExtended : public QGLColormap
  1341 class ColormapExtended : public QGLColormap
  1316 {
  1342 {
  1317 public:
  1343 public:
  1318     ColormapExtended() {}
  1344     ColormapExtended() {}
  1581 };
  1607 };
  1582 
  1608 
  1583 void tst_QGL::replaceClipping()
  1609 void tst_QGL::replaceClipping()
  1584 {
  1610 {
  1585     ReplaceClippingGLWidget glw;
  1611     ReplaceClippingGLWidget glw;
       
  1612 #ifdef Q_WS_QWS
       
  1613     glw.setWindowFlags(Qt::FramelessWindowHint);
       
  1614 #endif
  1586     glw.resize(300, 300);
  1615     glw.resize(300, 300);
  1587     glw.show();
  1616     glw.show();
  1588 
  1617 
  1589 #ifdef Q_WS_X11
  1618 #ifdef Q_WS_X11
  1590     qt_x11_wait_for_window_manager(&glw);
  1619     qt_x11_wait_for_window_manager(&glw);
  1596     glw.paint(&referencePainter);
  1625     glw.paint(&referencePainter);
  1597     referencePainter.end();
  1626     referencePainter.end();
  1598 
  1627 
  1599     const QImage widgetFB = glw.grabFrameBuffer(false).convertToFormat(QImage::Format_RGB32);
  1628     const QImage widgetFB = glw.grabFrameBuffer(false).convertToFormat(QImage::Format_RGB32);
  1600 
  1629 
  1601     QCOMPARE(widgetFB, reference);
  1630     // Sample pixels in a grid pattern which avoids false failures due to
       
  1631     // off-by-one pixel errors on some buggy GL implementations
       
  1632     for (int x = 25; x < reference.width(); x += 50) {
       
  1633         for (int y = 25; y < reference.width(); y += 50) {
       
  1634             QFUZZY_COMPARE_PIXELS(widgetFB.pixel(x, y), reference.pixel(x, y));
       
  1635         }
       
  1636     }
  1602 }
  1637 }
  1603 
  1638 
  1604 class ClipTestGLWidget : public QGLWidget
  1639 class ClipTestGLWidget : public QGLWidget
  1605 {
  1640 {
  1606 public:
  1641 public:
  1607     void paint(QPainter *painter)
  1642     void paint(QPainter *painter)
  1608     {
  1643     {
  1609         painter->fillRect(rect(), Qt::white);
  1644         painter->fillRect(-1, -1, width()+2, height()+2, Qt::white);
  1610         painter->setClipRect(10, 10, width()-20, height()-20);
  1645         painter->setClipRect(10, 10, width()-20, height()-20);
  1611         painter->fillRect(rect(), Qt::cyan);
  1646         painter->fillRect(rect(), Qt::cyan);
  1612 
  1647 
  1613         painter->save();
  1648         painter->save();
  1614         painter->setClipRect(10, 10, 100, 100, Qt::IntersectClip);
  1649         painter->setClipRect(10, 10, 100, 100, Qt::IntersectClip);
  1706 };
  1741 };
  1707 
  1742 
  1708 void tst_QGL::clipTest()
  1743 void tst_QGL::clipTest()
  1709 {
  1744 {
  1710     ClipTestGLWidget glw;
  1745     ClipTestGLWidget glw;
       
  1746 #ifdef Q_WS_QWS
       
  1747     glw.setWindowFlags(Qt::FramelessWindowHint);
       
  1748 #endif
  1711     glw.resize(220, 220);
  1749     glw.resize(220, 220);
  1712     glw.show();
  1750     glw.show();
  1713 
  1751 
  1714 #ifdef Q_WS_X11
  1752 #ifdef Q_WS_X11
  1715     qt_x11_wait_for_window_manager(&glw);
  1753     qt_x11_wait_for_window_manager(&glw);
  1721     glw.paint(&referencePainter);
  1759     glw.paint(&referencePainter);
  1722     referencePainter.end();
  1760     referencePainter.end();
  1723 
  1761 
  1724     const QImage widgetFB = glw.grabFrameBuffer(false).convertToFormat(QImage::Format_RGB32);
  1762     const QImage widgetFB = glw.grabFrameBuffer(false).convertToFormat(QImage::Format_RGB32);
  1725 
  1763 
  1726     QCOMPARE(widgetFB, reference);
  1764     // Sample pixels in a grid pattern which avoids false failures due to
       
  1765     // off-by-one pixel errors on some buggy GL implementations
       
  1766     for (int x = 2; x < reference.width(); x += 5) {
       
  1767         for (int y = 2; y < reference.width(); y += 5) {
       
  1768             QFUZZY_COMPARE_PIXELS(widgetFB.pixel(x, y), reference.pixel(x, y));
       
  1769         }
       
  1770     }
  1727 }
  1771 }
  1728 
  1772 
  1729 void tst_QGL::destroyFBOAfterContext()
  1773 void tst_QGL::destroyFBOAfterContext()
  1730 {
  1774 {
  1731     if (!QGLFramebufferObject::hasOpenGLFramebufferObjects())
  1775     if (!QGLFramebufferObject::hasOpenGLFramebufferObjects())
  1803     QVERIFY(!qt_shared_test()->value(glw1->context()));
  1847     QVERIFY(!qt_shared_test()->value(glw1->context()));
  1804     qt_shared_test()->insert(glw1->context(), res1);
  1848     qt_shared_test()->insert(glw1->context(), res1);
  1805     QVERIFY(qt_shared_test()->value(glw1->context()) == res1);
  1849     QVERIFY(qt_shared_test()->value(glw1->context()) == res1);
  1806 
  1850 
  1807     // Create another context that shares with the first.
  1851     // Create another context that shares with the first.
       
  1852     QVERIFY(!glw1->isSharing());
  1808     QGLWidget *glw2 = new QGLWidget(0, glw1);
  1853     QGLWidget *glw2 = new QGLWidget(0, glw1);
  1809     if (!glw2->isSharing()) {
  1854     if (!glw2->isSharing()) {
  1810         delete glw2;
  1855         delete glw2;
  1811         delete glw1;
  1856         delete glw1;
  1812         QSKIP("Context sharing is not supported", SkipSingle);
  1857         QSKIP("Context sharing is not supported", SkipSingle);
  1813     }
  1858     }
       
  1859     QVERIFY(glw1->isSharing());
  1814     QVERIFY(glw1->context() != glw2->context());
  1860     QVERIFY(glw1->context() != glw2->context());
  1815 
  1861 
  1816     // Check that the first context's resource is also on the second.
  1862     // Check that the first context's resource is also on the second.
  1817     QVERIFY(qt_shared_test()->value(glw1->context()) == res1);
  1863     QVERIFY(qt_shared_test()->value(glw1->context()) == res1);
  1818     QVERIFY(qt_shared_test()->value(glw2->context()) == res1);
  1864     QVERIFY(qt_shared_test()->value(glw2->context()) == res1);
  1840     QVERIFY(!QGLContext::areSharing(glw1->context(), 0));
  1886     QVERIFY(!QGLContext::areSharing(glw1->context(), 0));
  1841     QVERIFY(!QGLContext::areSharing(0, 0));
  1887     QVERIFY(!QGLContext::areSharing(0, 0));
  1842 
  1888 
  1843     // Create a third context, not sharing with the others.
  1889     // Create a third context, not sharing with the others.
  1844     QGLWidget *glw3 = new QGLWidget();
  1890     QGLWidget *glw3 = new QGLWidget();
       
  1891     QVERIFY(!glw3->isSharing());
  1845 
  1892 
  1846     // Create a guard on the standalone context.
  1893     // Create a guard on the standalone context.
  1847     QGLSharedResourceGuard guard3(glw3->context());
  1894     QGLSharedResourceGuard guard3(glw3->context());
  1848     guard3.setId(5);
  1895     guard3.setId(5);
  1849 
  1896 
  1888     QVERIFY(guard.id() == 3);
  1935     QVERIFY(guard.id() == 3);
  1889 
  1936 
  1890     // Delete the first context.
  1937     // Delete the first context.
  1891     delete glw1;
  1938     delete glw1;
  1892 
  1939 
       
  1940     // The second context should no longer register as sharing.
       
  1941     QVERIFY(!glw2->isSharing());
       
  1942 
  1893     // The first context's resource should transfer to the second context.
  1943     // The first context's resource should transfer to the second context.
  1894     QCOMPARE(tst_QGLResource::deletions, 0);
  1944     QCOMPARE(tst_QGLResource::deletions, 0);
  1895     QVERIFY(qt_shared_test()->value(glw2->context()) == res1);
  1945     QVERIFY(qt_shared_test()->value(glw2->context()) == res1);
  1896     QVERIFY(qt_shared_test()->value(glw3->context()) == res3);
  1946     QVERIFY(qt_shared_test()->value(glw3->context()) == res3);
  1897 
  1947