1
/****************************************************************************
2
**
3
** Copyright (C) 2012 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
** GNU Lesser General Public License Usage
11
** This file may be used under the terms of the GNU Lesser General Public
12
** License version 2.1 as published by the Free Software Foundation and
13
** appearing in the file LICENSE.LGPL included in the packaging of this
14
** file. Please review the following information to ensure the GNU Lesser
15
** General Public License version 2.1 requirements will be met:
16
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17
**
18
** In addition, as a special exception, Nokia gives you certain additional
19
** rights. These rights are described in the Nokia Qt LGPL Exception
20
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21
**
22
** GNU General Public License Usage
23
** Alternatively, this file may be used under the terms of the GNU General
24
** Public License version 3.0 as published by the Free Software Foundation
25
** and appearing in the file LICENSE.GPL included in the packaging of this
26
** file. Please review the following information to ensure the GNU General
27
** Public License version 3.0 requirements will be met:
28
** http://www.gnu.org/copyleft/gpl.html.
29
**
30
** Other Usage
31
** Alternatively, this file may be used in accordance with the terms and
32
** conditions contained in a signed written agreement between you and Nokia.
33
**
34
**
35
**
36
**
37
**
38
** $QT_END_LICENSE$
39
**
40
****************************************************************************/
41
#include <QtGui>
42
#include <QtOpenGL>
43
44
#include <qtest.h>
45
46
#include <private/qpaintengine_opengl_p.h>
47
48
class OpenGLBench : public QObject
49
{
50
    Q_OBJECT
51
52
private slots:
53
    void initTestCase();
54
    void cleanupTestCase();
55
56
    void imageDrawing_data();
57
    void imageDrawing();
58
59
    void pathDrawing_data();
60
    void pathDrawing();
61
62
    void painterOverhead();
63
64
    void startupCost_data();
65
    void startupCost();
66
67
    void lineDrawing();
68
69
    void textDrawing_data();
70
    void textDrawing();
71
72
    void clippedPainting_data();
73
    void clippedPainting();
74
75
    void gradients_data();
76
    void gradients();
77
78
    void textureUpload_data();
79
    void textureUpload();
80
81
82
private:
83
    QGLPixelBuffer *pb;
84
};
85
86
void OpenGLBench::initTestCase()
87
{
88
    pb = new QGLPixelBuffer(512, 512);
89
90
    QPainter p(pb);
91
    p.setRenderHint(QPainter::Antialiasing);
92
    p.setRenderHint(QPainter::HighQualityAntialiasing);
93
94
    p.drawImage(0, 0, QImage(256, 256, QImage::Format_ARGB32_Premultiplied));
95
}
96
97
void OpenGLBench::cleanupTestCase()
98
{
99
    delete pb;
100
}
101
102
void OpenGLBench::imageDrawing_data()
103
{
104
    QTest::addColumn<bool>("smoothPixmapTransform");
105
    QTest::addColumn<bool>("highQualityAntialiasing");
106
    QTest::addColumn<bool>("pixmap");
107
108
    for (int i = 0; i < (1 << 3); ++i) {
109
        bool smoothPixmapTransform = i & 1;
110
        bool highQualityAntialiasing = i & 2;
111
        bool pixmap = i & 4;
112
113
        QTest::newRow(QString("pixmap=%1 highQualityAntialiasing=%2 smoothPixmapTransform=%3")
114
                      .arg(pixmap).arg(highQualityAntialiasing).arg(smoothPixmapTransform).toAscii().data())
115
            << pixmap << highQualityAntialiasing << smoothPixmapTransform;
116
    }
117
}
118
119
void OpenGLBench::imageDrawing()
120
{
121
    QFETCH(bool, smoothPixmapTransform);
122
    QFETCH(bool, highQualityAntialiasing);
123
    QFETCH(bool, pixmap);
124
125
    QImage img;
126
    QPixmap pm;
127
128
    if (pixmap)
129
        pm = QPixmap(800, 800);
130
    else
131
        img = QImage(800, 800, QImage::Format_ARGB32_Premultiplied);
132
133
    QPainter p(pb);
134
    p.setRenderHint(QPainter::SmoothPixmapTransform, smoothPixmapTransform);
135
    p.setRenderHint(QPainter::Antialiasing, highQualityAntialiasing);
136
    p.setRenderHint(QPainter::HighQualityAntialiasing, highQualityAntialiasing);
137
138
    QBENCHMARK {
139
        if (pixmap) {
140
            pm.detach();
141
            p.drawPixmap(0, 0, pm);
142
        } else {
143
            img.detach();
144
            p.drawImage(0, 0, img);
145
        }
146
    }
147
}
148
149
Q_DECLARE_METATYPE(QPainterPath)
150
151
void OpenGLBench::pathDrawing_data()
152
{
153
    QTest::addColumn<QPainterPath>("path");
154
    QTest::addColumn<bool>("highQualityAntialiasing");
155
156
    QList<QPair<QPainterPath, QLatin1String> > paths;
157
158
    {
159
        QPainterPath path;
160
        path.addRect(-100, -100, 200, 200);
161
        paths << qMakePair(path, QLatin1String("plain rect"));
162
    }
163
164
    {
165
        QPainterPath path;
166
        path.addRoundedRect(-100, -100, 200, 200, 50, 50);
167
        paths << qMakePair(path, QLatin1String("rounded rect"));
168
    }
169
170
    {
171
        QPainterPath path;
172
        path.addEllipse(-100, -100, 200, 200);
173
        paths << qMakePair(path, QLatin1String("ellipse"));
174
    }
175
176
    for (int j = 0; j < (1 << 1); ++j) {
177
        bool highQualityAntialiasing = j & 1;
178
179
        for (int i = 0; i < paths.size(); ++i) {
180
            QTest::newRow(QString("path=%1 highQualityAntialiasing=%2")
181
                    .arg(paths[i].second).arg(highQualityAntialiasing).toAscii().data())
182
                << paths[i].first << highQualityAntialiasing;
183
        }
184
    }
185
}
186
187
void OpenGLBench::pathDrawing()
188
{
189
    QFETCH(QPainterPath, path);
190
    QFETCH(bool, highQualityAntialiasing);
191
192
    // warm-up
193
    {
194
        QPainterPath dummy;
195
        dummy.addRect(-1, -1, 2, 2);
196
        QPainter p(pb);
197
        p.setRenderHint(QPainter::Antialiasing, highQualityAntialiasing);
198
        p.setRenderHint(QPainter::HighQualityAntialiasing, highQualityAntialiasing);
199
        p.translate(pb->width() / 2, pb->height() / 2);
200
        p.rotate(30);
201
        p.drawPath(dummy);
202
        p.end();
203
    }
204
205
    QPainter p(pb);
206
    p.setPen(Qt::NoPen);
207
    p.setBrush(Qt::black);
208
    p.translate(pb->width() / 2, pb->height() / 2);
209
210
    QBENCHMARK {
211
        p.setRenderHint(QPainter::Antialiasing, highQualityAntialiasing);
212
        p.setRenderHint(QPainter::HighQualityAntialiasing, highQualityAntialiasing);
213
214
        p.rotate(0.01);
215
        p.drawPath(path);
216
    }
217
}
218
219
void OpenGLBench::painterOverhead()
220
{
221
    QBENCHMARK {
222
        QPainter p(pb);
223
    }
224
}
225
226
void OpenGLBench::startupCost_data()
227
{
228
    QTest::addColumn<bool>("highQualityAntialiasing");
229
230
    QTest::newRow("highQualityAntialiasing=0") << false;
231
    QTest::newRow("highQualityAntialiasing=1") << true;
232
}
233
234
void OpenGLBench::startupCost()
235
{
236
    QFETCH(bool, highQualityAntialiasing);
237
    QPainterPath path;
238
    path.addRoundedRect(-100, -100, 200, 200, 20, 20);
239
    QBENCHMARK {
240
        QGLPixelBuffer buffer(512, 512);
241
        QPainter p(&buffer);
242
        p.setRenderHint(QPainter::Antialiasing, highQualityAntialiasing);
243
        p.setRenderHint(QPainter::HighQualityAntialiasing, highQualityAntialiasing);
244
245
        p.translate(buffer.width() / 2, buffer.height() / 2);
246
        p.drawPath(path);
247
    }
248
}
249
250
void OpenGLBench::lineDrawing()
251
{
252
    QPainter p(pb);
253
254
    QBENCHMARK {
255
        p.drawLine(10, 10, 500, 500);
256
    }
257
}
258
259
void OpenGLBench::textDrawing_data()
260
{
261
    QTest::addColumn<int>("lines");
262
263
    int lines[] = { 1, 2, 4, 8, 16, 32, 64, 128 };
264
265
    QTest::newRow("text lines=1 (warmup run)") << 1;
266
    for (unsigned int i = 0; i < sizeof(lines) / sizeof(int); ++i)
267
        QTest::newRow(QString("text lines=%0").arg(lines[i]).toAscii().data()) << lines[i];
268
}
269
270
void OpenGLBench::textDrawing()
271
{
272
    QPainter p(pb);
273
274
    QFETCH(int, lines);
275
276
    p.translate(0, 16);
277
    QBENCHMARK {
278
        for (int i = 0; i < lines; ++i)
279
            p.drawText(0, i, "Hello World!");
280
    }
281
}
282
283
void OpenGLBench::clippedPainting_data()
284
{
285
    QTest::addColumn<QPainterPath>("path");
286
287
    QRectF rect = QRectF(0, 0, pb->width(), pb->height()).adjusted(5, 5, -5, -5);
288
289
    {
290
        QPainterPath path;
291
        path.addRect(rect);
292
        QTest::newRow("rect path") << path;
293
    }
294
295
    {
296
        QPainterPath path;
297
        path.addRoundedRect(rect, 5, 5);
298
        QTest::newRow("rounded rect path") << path;
299
    }
300
301
    {
302
        QPainterPath path;
303
        path.addEllipse(rect);
304
        QTest::newRow("ellipse path") << path;
305
    }
306
}
307
308
void OpenGLBench::clippedPainting()
309
{
310
    QFETCH(QPainterPath, path);
311
312
    QBENCHMARK {
313
        QPainter p(pb);
314
        p.setPen(Qt::NoPen);
315
        p.setBrush(Qt::black);
316
317
        p.setClipPath(path);
318
        p.drawRect(0, 0, pb->width(), pb->height());
319
    }
320
}
321
322
Q_DECLARE_METATYPE(QGradient::Type)
323
324
void OpenGLBench::gradients_data()
325
{
326
    QTest::addColumn<QGradient::Type>("gradientType");
327
    QTest::addColumn<bool>("objectBoundingMode");
328
329
    QTest::newRow("warmup run") << QGradient::LinearGradient << false;
330
331
    QTest::newRow("linear gradient") << QGradient::LinearGradient << false;
332
    QTest::newRow("radial gradient") << QGradient::RadialGradient << false;
333
    QTest::newRow("conical gradient") << QGradient::ConicalGradient << false;
334
335
    QTest::newRow("linear gradient, object bounding mode") << QGradient::LinearGradient << true;
336
    QTest::newRow("radial gradient, object bounding mode") << QGradient::RadialGradient << true;
337
    QTest::newRow("conical gradient, object bounding mode") << QGradient::ConicalGradient << true;
338
}
339
340
void OpenGLBench::gradients()
341
{
342
    QFETCH(QGradient::Type, gradientType);
343
    QFETCH(bool, objectBoundingMode);
344
345
    QPointF a;
346
    QPointF b = objectBoundingMode ? QPointF(1, 1) : QPointF(pb->width(), pb->height());
347
348
    QGradient gradient;
349
    switch (gradientType) {
350
    case QGradient::LinearGradient:
351
        gradient = QLinearGradient(a, b);
352
        break;
353
    case QGradient::RadialGradient:
354
        gradient = QRadialGradient(a, b.x() / 2, b);
355
        break;
356
    case QGradient::ConicalGradient:
357
        gradient = QConicalGradient((a + b)/2, 0);
358
        break;
359
    default:
360
        break;
361
    }
362
363
    if (objectBoundingMode)
364
        gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
365
366
    gradient.setColorAt(0, Qt::red);
367
    gradient.setColorAt(0.2, Qt::blue);
368
    gradient.setColorAt(0.4, Qt::transparent);
369
    gradient.setColorAt(0.6, Qt::green);
370
    gradient.setColorAt(0.8, Qt::black);
371
    gradient.setColorAt(1, Qt::white);
372
373
    QPainter p(pb);
374
375
    QBENCHMARK {
376
        p.fillRect(0, 0, pb->width(), pb->height(), gradient);
377
        glFinish();
378
    }
379
}
380
381
void OpenGLBench::textureUpload_data()
382
{
383
    QTest::addColumn<int>("size");
384
    QTest::addColumn<int>("flags");
385
    QTest::addColumn<int>("format");
386
387
    int sizes[] = { 8, 10, 16, 20, 32, 50, 64, 100, 128, 200, 256, 500, 512, 1000, 1024, 2000, 2048, -1 };
388
    int flags[] = { QGLContext::InternalBindOption,
389
                  QGLContext::DefaultBindOption,
390
                  -1 };
391
    int formats[] = { GL_RGB, GL_RGBA, -1 };
392
393
    for (int s = 0; sizes[s] != -1; ++s) {
394
        for (int f = 0; flags[f] != -1; ++f) {
395
            for (int a = 0; formats[a] != -1; ++a) {
396
                QByteArray name;
397
                name.append("size=").append(QByteArray::number(sizes[s]));
398
                name.append(", flags=").append(f == 0 ? "internal" : "default");
399
                name.append(", format=").append(a == 0 ? "RGB" : "RGBA");
400
                QTest::newRow(name.constData()) << sizes[s] << flags[f] << formats[a];
401
            }
402
        }
403
    }
404
}
405
406
void OpenGLBench::textureUpload()
407
{
408
    QFETCH(int, size);
409
    QFETCH(int, flags);
410
    QFETCH(int, format);
411
412
    QPixmap pixmap(size, size);
413
414
    if (format == GL_RGB)
415
        pixmap.fill(Qt::red);
416
    else
417
        pixmap.fill(Qt::transparent);
418
419
    pb->makeCurrent();
420
    QGLContext *context = const_cast<QGLContext *>(QGLContext::currentContext());
421
    QTime time;
422
423
    time.start();
424
    context->bindTexture(pixmap, GL_TEXTURE_2D, format, (QGLContext::BindOptions) flags);
425
    QTest::setBenchmarkResult(time.elapsed(), QTest::WalltimeMilliseconds);
426
}
427
428
QTEST_MAIN(OpenGLBench)
429
430
#include "main.moc"