/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include class OpenGLBench : public QObject { Q_OBJECT private slots: void initTestCase(); void cleanupTestCase(); void imageDrawing_data(); void imageDrawing(); void pathDrawing_data(); void pathDrawing(); void painterOverhead(); void startupCost_data(); void startupCost(); void lineDrawing(); void textDrawing_data(); void textDrawing(); void clippedPainting_data(); void clippedPainting(); void gradients_data(); void gradients(); void textureUpload_data(); void textureUpload(); private: QGLPixelBuffer *pb; }; void OpenGLBench::initTestCase() { pb = new QGLPixelBuffer(512, 512); QPainter p(pb); p.setRenderHint(QPainter::Antialiasing); p.drawImage(0, 0, QImage(256, 256, QImage::Format_ARGB32_Premultiplied)); } void OpenGLBench::cleanupTestCase() { delete pb; } void OpenGLBench::imageDrawing_data() { QTest::addColumn("smoothPixmapTransform"); QTest::addColumn("highQualityAntialiasing"); QTest::addColumn("pixmap"); for (int i = 0; i < (1 << 3); ++i) { bool smoothPixmapTransform = i & 1; bool highQualityAntialiasing = i & 2; bool pixmap = i & 4; QTest::newRow(QString("pixmap=%1 highQualityAntialiasing=%2 smoothPixmapTransform=%3") .arg(pixmap).arg(highQualityAntialiasing).arg(smoothPixmapTransform).toLatin1().data()) << pixmap << highQualityAntialiasing << smoothPixmapTransform; } } void OpenGLBench::imageDrawing() { QFETCH(bool, smoothPixmapTransform); QFETCH(bool, highQualityAntialiasing); QFETCH(bool, pixmap); QImage img; QPixmap pm; if (pixmap) pm = QPixmap(800, 800); else img = QImage(800, 800, QImage::Format_ARGB32_Premultiplied); QPainter p(pb); p.setRenderHint(QPainter::SmoothPixmapTransform, smoothPixmapTransform); p.setRenderHint(QPainter::Antialiasing, highQualityAntialiasing); QBENCHMARK { if (pixmap) { pm.detach(); p.drawPixmap(0, 0, pm); } else { img.detach(); p.drawImage(0, 0, img); } } } Q_DECLARE_METATYPE(QPainterPath) void OpenGLBench::pathDrawing_data() { QTest::addColumn("path"); QTest::addColumn("highQualityAntialiasing"); QList > paths; { QPainterPath path; path.addRect(-100, -100, 200, 200); paths << qMakePair(path, QLatin1String("plain rect")); } { QPainterPath path; path.addRoundedRect(-100, -100, 200, 200, 50, 50); paths << qMakePair(path, QLatin1String("rounded rect")); } { QPainterPath path; path.addEllipse(-100, -100, 200, 200); paths << qMakePair(path, QLatin1String("ellipse")); } for (int j = 0; j < (1 << 1); ++j) { bool highQualityAntialiasing = j & 1; for (int i = 0; i < paths.size(); ++i) { QTest::newRow(QString("path=%1 highQualityAntialiasing=%2") .arg(paths[i].second).arg(highQualityAntialiasing).toLatin1().data()) << paths[i].first << highQualityAntialiasing; } } } void OpenGLBench::pathDrawing() { QFETCH(QPainterPath, path); QFETCH(bool, highQualityAntialiasing); // warm-up { QPainterPath dummy; dummy.addRect(-1, -1, 2, 2); QPainter p(pb); p.setRenderHint(QPainter::Antialiasing, highQualityAntialiasing); p.translate(pb->width() / 2, pb->height() / 2); p.rotate(30); p.drawPath(dummy); p.end(); } QPainter p(pb); p.setPen(Qt::NoPen); p.setBrush(Qt::black); p.translate(pb->width() / 2, pb->height() / 2); QBENCHMARK { p.setRenderHint(QPainter::Antialiasing, highQualityAntialiasing); p.rotate(0.01); p.drawPath(path); } } void OpenGLBench::painterOverhead() { QBENCHMARK { QPainter p(pb); } } void OpenGLBench::startupCost_data() { QTest::addColumn("highQualityAntialiasing"); QTest::newRow("highQualityAntialiasing=0") << false; QTest::newRow("highQualityAntialiasing=1") << true; } void OpenGLBench::startupCost() { QFETCH(bool, highQualityAntialiasing); QPainterPath path; path.addRoundedRect(-100, -100, 200, 200, 20, 20); QBENCHMARK { QGLPixelBuffer buffer(512, 512); QPainter p(&buffer); p.setRenderHint(QPainter::Antialiasing, highQualityAntialiasing); p.translate(buffer.width() / 2, buffer.height() / 2); p.drawPath(path); } } void OpenGLBench::lineDrawing() { QPainter p(pb); QBENCHMARK { p.drawLine(10, 10, 500, 500); } } void OpenGLBench::textDrawing_data() { QTest::addColumn("lines"); int lines[] = { 1, 2, 4, 8, 16, 32, 64, 128 }; QTest::newRow("text lines=1 (warmup run)") << 1; for (unsigned int i = 0; i < sizeof(lines) / sizeof(int); ++i) QTest::newRow(QString("text lines=%0").arg(lines[i]).toLatin1().data()) << lines[i]; } void OpenGLBench::textDrawing() { QPainter p(pb); QFETCH(int, lines); p.translate(0, 16); QBENCHMARK { for (int i = 0; i < lines; ++i) p.drawText(0, i, "Hello World!"); } } void OpenGLBench::clippedPainting_data() { QTest::addColumn("path"); QRectF rect = QRectF(0, 0, pb->width(), pb->height()).adjusted(5, 5, -5, -5); { QPainterPath path; path.addRect(rect); QTest::newRow("rect path") << path; } { QPainterPath path; path.addRoundedRect(rect, 5, 5); QTest::newRow("rounded rect path") << path; } { QPainterPath path; path.addEllipse(rect); QTest::newRow("ellipse path") << path; } } void OpenGLBench::clippedPainting() { QFETCH(QPainterPath, path); QBENCHMARK { QPainter p(pb); p.setPen(Qt::NoPen); p.setBrush(Qt::black); p.setClipPath(path); p.drawRect(0, 0, pb->width(), pb->height()); } } Q_DECLARE_METATYPE(QGradient::Type) void OpenGLBench::gradients_data() { QTest::addColumn("gradientType"); QTest::addColumn("objectBoundingMode"); QTest::newRow("warmup run") << QGradient::LinearGradient << false; QTest::newRow("linear gradient") << QGradient::LinearGradient << false; QTest::newRow("radial gradient") << QGradient::RadialGradient << false; QTest::newRow("conical gradient") << QGradient::ConicalGradient << false; QTest::newRow("linear gradient, object bounding mode") << QGradient::LinearGradient << true; QTest::newRow("radial gradient, object bounding mode") << QGradient::RadialGradient << true; QTest::newRow("conical gradient, object bounding mode") << QGradient::ConicalGradient << true; } void OpenGLBench::gradients() { QFETCH(QGradient::Type, gradientType); QFETCH(bool, objectBoundingMode); QPointF a; QPointF b = objectBoundingMode ? QPointF(1, 1) : QPointF(pb->width(), pb->height()); QGradient gradient; switch (gradientType) { case QGradient::LinearGradient: gradient = QLinearGradient(a, b); break; case QGradient::RadialGradient: gradient = QRadialGradient(a, b.x() / 2, b); break; case QGradient::ConicalGradient: gradient = QConicalGradient((a + b)/2, 0); break; default: break; } if (objectBoundingMode) gradient.setCoordinateMode(QGradient::ObjectBoundingMode); gradient.setColorAt(0, Qt::red); gradient.setColorAt(0.2, Qt::blue); gradient.setColorAt(0.4, Qt::transparent); gradient.setColorAt(0.6, Qt::green); gradient.setColorAt(0.8, Qt::black); gradient.setColorAt(1, Qt::white); QPainter p(pb); QBENCHMARK { p.fillRect(0, 0, pb->width(), pb->height(), gradient); glFinish(); } } void OpenGLBench::textureUpload_data() { QTest::addColumn("size"); QTest::addColumn("flags"); QTest::addColumn("format"); int sizes[] = { 8, 10, 16, 20, 32, 50, 64, 100, 128, 200, 256, 500, 512, 1000, 1024, 2000, 2048, -1 }; int flags[] = { QGLContext::InternalBindOption, QGLContext::DefaultBindOption, -1 }; int formats[] = { GL_RGB, GL_RGBA, -1 }; for (int s = 0; sizes[s] != -1; ++s) { for (int f = 0; flags[f] != -1; ++f) { for (int a = 0; formats[a] != -1; ++a) { QByteArray name; name.append("size=").append(QByteArray::number(sizes[s])); name.append(", flags=").append(f == 0 ? "internal" : "default"); name.append(", format=").append(a == 0 ? "RGB" : "RGBA"); QTest::newRow(name.constData()) << sizes[s] << flags[f] << formats[a]; } } } } void OpenGLBench::textureUpload() { QFETCH(int, size); QFETCH(int, flags); QFETCH(int, format); QPixmap pixmap(size, size); if (format == GL_RGB) pixmap.fill(Qt::red); else pixmap.fill(Qt::transparent); pb->makeCurrent(); QGLContext *context = const_cast(QGLContext::currentContext()); QTime time; time.start(); context->bindTexture(pixmap, GL_TEXTURE_2D, format, (QGLContext::BindOptions) flags); QTest::setBenchmarkResult(time.elapsed(), QTest::WalltimeMilliseconds); } QTEST_MAIN(OpenGLBench) #include "main.moc"