tests/benchmarks/declarative/painting/paintbenchmark.cpp
branchGCC_SURGE
changeset 31 5daf16870df6
parent 30 5dc02b23752f
equal deleted inserted replaced
27:93b982ccede2 31:5daf16870df6
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the test suite of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <QApplication>
       
    43 #include <QPixmap>
       
    44 #include <QImage>
       
    45 #include <QPainter>
       
    46 #include <QPainterPath>
       
    47 #include <QGLWidget>
       
    48 #include <QTextLayout>
       
    49 #include <QVBoxLayout>
       
    50 #include <QTime>
       
    51 #include <QDebug>
       
    52 #include <QStaticText>
       
    53 
       
    54 int iterations = 20;
       
    55 const int count = 600;
       
    56 const int lines = 12;
       
    57 const int spacing = 36;
       
    58 QSizeF size(1000, 800);
       
    59 const qreal lineWidth = 1000;
       
    60 QString strings[lines];
       
    61 QGLWidget *testWidget = 0;
       
    62 
       
    63 void paint_QTextLayout(QPainter &p, bool useCache)
       
    64 {
       
    65     static bool first = true;
       
    66     static QTextLayout *textLayout[lines];
       
    67     if (first) {
       
    68         for (int i = 0; i < lines; ++i) {
       
    69             textLayout[i] = new QTextLayout(strings[i]);
       
    70             int leading = p.fontMetrics().leading();
       
    71             qreal height = 0;
       
    72             qreal widthUsed = 0;
       
    73             textLayout[i]->setCacheEnabled(useCache);
       
    74             textLayout[i]->beginLayout();
       
    75             while (1) {
       
    76                 QTextLine line = textLayout[i]->createLine();
       
    77                 if (!line.isValid())
       
    78                         break;
       
    79 
       
    80                 line.setLineWidth(lineWidth);
       
    81                 height += leading;
       
    82                 line.setPosition(QPointF(0, height));
       
    83                 height += line.height();
       
    84                 widthUsed = qMax(widthUsed, line.naturalTextWidth());
       
    85             }
       
    86             textLayout[i]->endLayout();
       
    87         }
       
    88         first = false;
       
    89     }
       
    90     for (int i = 0; i < count; ++i) {
       
    91         for (int j = 0; j < lines; ++j) {
       
    92             textLayout[j]->draw(&p, QPoint(0, j*spacing));
       
    93         }
       
    94     }
       
    95 }
       
    96 
       
    97 void paint_QTextLayout_noCache(QPainter &p)
       
    98 {
       
    99     paint_QTextLayout(p, false);
       
   100 }
       
   101 
       
   102 void paint_QTextLayout_cache(QPainter &p)
       
   103 {
       
   104     paint_QTextLayout(p, true);
       
   105 }
       
   106 
       
   107 void paint_QStaticText(QPainter &p, bool useOptimizations)
       
   108 {
       
   109     static QStaticText *staticText[lines];
       
   110     static bool first = true;
       
   111     if (first) {
       
   112         for (int i = 0; i < lines; ++i) {
       
   113             staticText[i] = new QStaticText(strings[i]);
       
   114             if (useOptimizations)
       
   115                 staticText[i]->setPerformanceHint(QStaticText::AggressiveCaching);
       
   116             else
       
   117                 staticText[i]->setPerformanceHint(QStaticText::ModerateCaching);
       
   118         }
       
   119         first = false;
       
   120     }
       
   121     for (int i = 0; i < count; ++i) {
       
   122         for (int j = 0; j < lines; ++j) {
       
   123             p.drawStaticText(QPointF(0, 30 + j*spacing), *staticText[j]);
       
   124         }
       
   125     }
       
   126 }
       
   127 
       
   128 void paint_QStaticText_noOptimizations(QPainter &p)
       
   129 {
       
   130     paint_QStaticText(p, false);
       
   131 }
       
   132 
       
   133 void paint_QStaticText_optimizations(QPainter &p)
       
   134 {
       
   135     paint_QStaticText(p, true);
       
   136 }
       
   137 
       
   138 void paint_QPixmapCachedText(QPainter &p)
       
   139 {
       
   140     static bool first = true;
       
   141     static QPixmap cacheText[lines];
       
   142     if (first) {
       
   143         for (int i = 0; i < lines; ++i) {
       
   144             QRectF trueSize;
       
   145             trueSize = p.boundingRect(QRectF(QPointF(0,0), size), 0, strings[i]);
       
   146             cacheText[i] = QPixmap(trueSize.size().toSize());
       
   147             cacheText[i].fill(Qt::transparent);
       
   148             QPainter paint(&cacheText[i]);
       
   149             paint.setPen(Qt::black);
       
   150             paint.drawText(QRectF(QPointF(0,0), trueSize.size().toSize()), strings[i]);
       
   151         }
       
   152         first = false;
       
   153     }
       
   154     for (int i = 0; i < count; i++) {
       
   155         for (int j = 0; j < lines; ++j) {
       
   156             p.drawPixmap(0,j*spacing,cacheText[j]);
       
   157         }
       
   158     }
       
   159 }
       
   160 
       
   161 void paint_RoundedRect(QPainter &p)
       
   162 {
       
   163     static bool first = true;
       
   164     if (first) {
       
   165         if (testWidget) {
       
   166             QGLFormat format = testWidget->format();
       
   167             if (!format.sampleBuffers())
       
   168                 qWarning() << "Cannot paint antialiased rounded rect without sampleBuffers";
       
   169         }
       
   170         first = false;
       
   171     }
       
   172     p.setRenderHint(QPainter::Antialiasing, true);
       
   173     p.setPen(Qt::black);
       
   174     p.setBrush(Qt::red);
       
   175     for (int i = 0; i < count; i++) {
       
   176         for (int j = 0; j < lines; ++j) {
       
   177             QSize size((j+1)*50, spacing-1);
       
   178             p.drawRoundedRect(QRectF(QPointF(0,j*spacing), size), 8, 8);
       
   179         }
       
   180     }
       
   181 }
       
   182 
       
   183 void paint_QPixmapCachedRoundedRect(QPainter &p)
       
   184 {
       
   185     static bool first = true;
       
   186     static QPixmap cacheRect;
       
   187     if (first) {
       
   188         const int pw = 0;
       
   189         const int radius = 8;
       
   190         cacheRect = QPixmap(radius*2 + 3 + pw*2, radius*2 + 3 + pw*2);
       
   191         cacheRect.fill(Qt::transparent);
       
   192         QPainter paint(&cacheRect);
       
   193         paint.setRenderHint(QPainter::Antialiasing);
       
   194         paint.setPen(Qt::black);
       
   195         paint.setBrush(Qt::red);
       
   196         if (pw%2)
       
   197             paint.drawRoundedRect(QRectF(qreal(pw)/2+1, qreal(pw)/2+1, cacheRect.width()-(pw+1), cacheRect.height()-(pw+1)), radius, radius);
       
   198         else
       
   199             paint.drawRoundedRect(QRectF(qreal(pw)/2, qreal(pw)/2, cacheRect.width()-pw, cacheRect.height()-pw), radius, radius);
       
   200 
       
   201         first = false;
       
   202     }
       
   203     for (int i = 0; i < count; i++) {
       
   204         for (int j = 0; j < lines; ++j) {
       
   205             QSize size((j+1)*50, spacing-1);
       
   206 
       
   207             p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, true);
       
   208 
       
   209             const int pw = 0;
       
   210 
       
   211             int xOffset = (cacheRect.width()-1)/2;
       
   212             int yOffset = (cacheRect.height()-1)/2;
       
   213 
       
   214             QMargins margins(xOffset, yOffset, xOffset, yOffset);
       
   215             QTileRules rules(Qt::StretchTile, Qt::StretchTile);
       
   216             //NOTE: even though our item may have qreal-based width and height, qDrawBorderPixmap only supports QRects
       
   217             qDrawBorderPixmap(&p, QRect(-pw/2, j*spacing-pw/2, size.width()+pw, size.height()+pw), margins, cacheRect, cacheRect.rect(), margins, rules);
       
   218         }
       
   219     }
       
   220 }
       
   221 
       
   222 void paint_pathCacheRoundedRect(QPainter &p)
       
   223 {
       
   224     static bool first = true;
       
   225     static QPainterPath path[lines];
       
   226     if (first) {
       
   227         for (int j = 0; j < lines; ++j) {
       
   228             path[j].addRoundedRect(QRectF(0,0,(j+1)*50, spacing-1), 8, 8);
       
   229         }
       
   230         first = false;
       
   231     }
       
   232     p.setRenderHint(QPainter::Antialiasing, true);
       
   233     p.setPen(Qt::black);
       
   234     p.setBrush(Qt::red);
       
   235     for (int i = 0; i < count; i++) {
       
   236         for (int j = 0; j < lines; ++j) {
       
   237             p.translate(0,j*spacing);
       
   238             p.drawPath(path[j]);
       
   239             p.translate(0,-j*spacing);
       
   240         }
       
   241     }
       
   242 }
       
   243 
       
   244 void paint_QPixmap63x63_opaque(QPainter &p)
       
   245 {
       
   246     static bool first = true;
       
   247     static QPixmap pm;
       
   248     if (first) {
       
   249         pm.load("data/63x63_opaque.png");
       
   250         first = false;
       
   251     }
       
   252     for (int i = 0; i < count; i++) {
       
   253         for (int j = 0; j < lines; ++j) {
       
   254             p.drawPixmap((i%10) * 64,j*spacing, pm);
       
   255         }
       
   256     }
       
   257 }
       
   258 
       
   259 void paint_QPixmap64x64_opaque(QPainter &p)
       
   260 {
       
   261     static bool first = true;
       
   262     static QPixmap pm;
       
   263     if (first) {
       
   264         pm.load("data/64x64_opaque.png");
       
   265         first = false;
       
   266     }
       
   267     for (int i = 0; i < count; i++) {
       
   268         for (int j = 0; j < lines; ++j) {
       
   269             p.drawPixmap((i%10) * 64,j*spacing, pm);
       
   270         }
       
   271     }
       
   272 }
       
   273 
       
   274 void paint_QPixmap63x63(QPainter &p)
       
   275 {
       
   276     static bool first = true;
       
   277     static QPixmap pm;
       
   278     if (first) {
       
   279         pm.load("data/63x63.png");
       
   280         first = false;
       
   281     }
       
   282     for (int i = 0; i < count; i++) {
       
   283         for (int j = 0; j < lines; ++j) {
       
   284             p.drawPixmap((i%10) * 64,j*spacing, pm);
       
   285         }
       
   286     }
       
   287 }
       
   288 
       
   289 void paint_QPixmap64x64(QPainter &p)
       
   290 {
       
   291     static bool first = true;
       
   292     static QPixmap pm;
       
   293     if (first) {
       
   294         pm.load("data/64x64.png");
       
   295         first = false;
       
   296     }
       
   297     for (int i = 0; i < count; i++) {
       
   298         for (int j = 0; j < lines; ++j) {
       
   299             p.drawPixmap((i%10) * 64,j*spacing, pm);
       
   300         }
       
   301     }
       
   302 }
       
   303 typedef void(*PaintFunc)(QPainter &);
       
   304 
       
   305 struct {
       
   306     const char *name;
       
   307     PaintFunc func;
       
   308 } funcs[] = {
       
   309     { "QTextLayoutNoCache", &paint_QTextLayout_noCache },
       
   310     { "QTextLayoutWithCache", &paint_QTextLayout_cache },
       
   311     { "QStaticTextNoBackendOptimizations", &paint_QStaticText_noOptimizations },
       
   312     { "QStaticTextWithBackendOptimizations", &paint_QStaticText_optimizations },
       
   313     { "CachedText", &paint_QPixmapCachedText },
       
   314     { "RoundedRect", &paint_RoundedRect },
       
   315     { "CachedRoundedRect", &paint_QPixmapCachedRoundedRect },
       
   316     { "PathCacheRoundedRect", &paint_pathCacheRoundedRect },
       
   317     { "QPixmap63x63_opaque", &paint_QPixmap63x63_opaque },
       
   318     { "QPixmap64x64_opaque", &paint_QPixmap64x64_opaque },
       
   319     { "QPixmap63x63", &paint_QPixmap63x63 },
       
   320     { "QPixmap64x64", &paint_QPixmap64x64 },
       
   321     { 0, 0 }
       
   322 };
       
   323 
       
   324 PaintFunc testFunc = 0;
       
   325 
       
   326 class MyGLWidget : public QGLWidget
       
   327 {
       
   328 public:
       
   329     MyGLWidget(const QGLFormat &format) : QGLWidget(format), frames(0) {
       
   330         const char chars[] = "abcd efgh ijkl mnop qrst uvwx yz!$. ABCD 1234";
       
   331         int len = strlen(chars);
       
   332         for (int i = 0; i < lines; ++i) {
       
   333             for (int j = 0; j < 60; j++) {
       
   334                 strings[i] += QChar(chars[rand() % len]);
       
   335             }
       
   336         }
       
   337     }
       
   338 
       
   339     void paintEvent(QPaintEvent *) {
       
   340         static int last = 0;
       
   341         static bool firstRun = true;
       
   342         if (firstRun) {
       
   343             timer.start();
       
   344             firstRun = false;
       
   345         } else {
       
   346             int elapsed = timer.elapsed();
       
   347             qDebug() << "frame elapsed:" << elapsed - last;
       
   348             last = elapsed;
       
   349         }
       
   350         QPainter p(this);
       
   351 	p.fillRect(rect(), Qt::white);
       
   352 	p.setPen(Qt::black);
       
   353         QTime drawTimer;
       
   354         drawTimer.start();
       
   355         testFunc(p);
       
   356         qDebug() << "draw time" << drawTimer.elapsed();
       
   357         if (iterations--)
       
   358             update();
       
   359         else
       
   360             qApp->quit();
       
   361     }
       
   362 
       
   363     QTime timer;
       
   364     int frames;
       
   365 };
       
   366 
       
   367 int main(int argc, char *argv[])
       
   368 {
       
   369     QApplication app(argc, argv);
       
   370 
       
   371     bool sampleBuffers = false;
       
   372 
       
   373     for (int i = 1; i < argc; ++i) {
       
   374         QString arg = argv[i];
       
   375         if (arg == "-test") {
       
   376             arg = argv[++i];
       
   377             int j = 0;
       
   378             while (funcs[j].name) {
       
   379                 if (arg == funcs[j].name) {
       
   380                     testFunc = funcs[j].func;
       
   381                     qDebug() << "Running test" << arg;
       
   382                     break;
       
   383                 }
       
   384                 ++j;
       
   385             }
       
   386         } else if (arg == "-iterations") {
       
   387             arg = argv[++i];
       
   388             iterations = arg.toInt();
       
   389         } else if (arg == "-sampleBuffers") {
       
   390             sampleBuffers = true;
       
   391         }
       
   392     }
       
   393 
       
   394     if (testFunc == 0) {
       
   395         qDebug() << "Usage: textspeed -test <test> [-sampleBuffers] [-iterations n]";
       
   396         qDebug() << "where <test> can be:";
       
   397         int j = 0;
       
   398         while (funcs[j].name) {
       
   399             qDebug() << "  " << funcs[j].name;
       
   400             ++j;
       
   401         }
       
   402         exit(1);
       
   403     }
       
   404 
       
   405     QWidget w;
       
   406     QGLFormat format = QGLFormat::defaultFormat();
       
   407     format.setSampleBuffers(sampleBuffers);
       
   408     testWidget = new MyGLWidget(format);
       
   409     testWidget->setAutoFillBackground(false);
       
   410     QVBoxLayout *layout = new QVBoxLayout(&w);
       
   411     w.setLayout(layout);
       
   412     layout->addWidget(testWidget);
       
   413     w.showFullScreen();
       
   414     app.exec();
       
   415 
       
   416     return 0;
       
   417 }