tools/qttracereplay/main.cpp
branchGCC_SURGE
changeset 31 5daf16870df6
parent 30 5dc02b23752f
equal deleted inserted replaced
27:93b982ccede2 31:5daf16870df6
    47 
    47 
    48 class ReplayWidget : public QWidget
    48 class ReplayWidget : public QWidget
    49 {
    49 {
    50     Q_OBJECT
    50     Q_OBJECT
    51 public:
    51 public:
    52     ReplayWidget(const QString &filename);
    52     ReplayWidget(const QString &filename, int from, int to, bool single, int frame);
    53 
    53 
    54     void paintEvent(QPaintEvent *event);
    54     void paintEvent(QPaintEvent *event);
    55     void resizeEvent(QResizeEvent *event);
    55     void resizeEvent(QResizeEvent *event);
    56 
    56 
    57 public slots:
    57 public slots:
    64     int currentFrame;
    64     int currentFrame;
    65     int currentIteration;
    65     int currentIteration;
    66     QTime timer;
    66     QTime timer;
    67 
    67 
    68     QList<uint> visibleUpdates;
    68     QList<uint> visibleUpdates;
    69     QList<uint> iterationTimes;
    69 
       
    70     QVector<uint> iterationTimes;
    70     QString filename;
    71     QString filename;
       
    72 
       
    73     int from;
       
    74     int to;
       
    75 
       
    76     bool single;
       
    77 
       
    78     int frame;
       
    79     int currentCommand;
    71 };
    80 };
    72 
    81 
    73 void ReplayWidget::updateRect()
    82 void ReplayWidget::updateRect()
    74 {
    83 {
    75     if (!visibleUpdates.isEmpty())
    84     if (frame >= 0 && !updates.isEmpty())
       
    85         update(updates.at(frame));
       
    86     else if (!visibleUpdates.isEmpty())
    76         update(updates.at(visibleUpdates.at(currentFrame)));
    87         update(updates.at(visibleUpdates.at(currentFrame)));
    77 }
    88 }
    78 
    89 
       
    90 const int singleFrameRepeatsPerCommand = 100;
       
    91 const int singleFrameIterations = 4;
       
    92 
    79 void ReplayWidget::paintEvent(QPaintEvent *)
    93 void ReplayWidget::paintEvent(QPaintEvent *)
    80 {
    94 {
    81     QPainter p(this);
    95     QPainter p(this);
    82 
    96 
       
    97     QTimer::singleShot(0, this, SLOT(updateRect()));
       
    98 
    83 //    p.setClipRegion(frames.at(currentFrame).updateRegion);
    99 //    p.setClipRegion(frames.at(currentFrame).updateRegion);
       
   100 
       
   101     if (frame >= 0) {
       
   102         int start = buffer.frameStartIndex(frame);
       
   103         int end = buffer.frameEndIndex(frame);
       
   104 
       
   105         iterationTimes.resize(end - start);
       
   106 
       
   107         int saveRestoreStackDepth = buffer.processCommands(&p, start, start + currentCommand);
       
   108 
       
   109         for (int i = 0; i < saveRestoreStackDepth; ++i)
       
   110             p.restore();
       
   111 
       
   112         const int repeats = currentIteration >= 3 ? singleFrameRepeatsPerCommand : 1;
       
   113 
       
   114         ++currentFrame;
       
   115         if (currentFrame == repeats) {
       
   116             currentFrame = 0;
       
   117             if (currentIteration >= 3) {
       
   118                 iterationTimes[currentCommand - 1] = qMin(iterationTimes[currentCommand - 1], uint(timer.elapsed()));
       
   119                 timer.restart();
       
   120             }
       
   121 
       
   122             if (currentIteration >= singleFrameIterations + 3) {
       
   123                 printf(" #    | ms      | description\n");
       
   124                 printf("------+---------+------------------------------------------------------------\n");
       
   125 
       
   126 		qSort(iterationTimes);
       
   127 
       
   128 		int sum = 0;
       
   129                 for (int i = 0; i < iterationTimes.size(); ++i) {
       
   130                     int delta = iterationTimes.at(i);
       
   131                     if (i > 0)
       
   132                         delta -= iterationTimes.at(i-1);
       
   133 		    sum += delta;
       
   134                     qreal deltaF = delta / qreal(repeats);
       
   135                     printf("%.5d | %.5f | %s\n", i, deltaF, qPrintable(buffer.commandDescription(start + i)));
       
   136                 }
       
   137                 printf("Total | %.5f | Total frame time\n", sum / qreal(repeats));
       
   138                 deleteLater();
       
   139                 return;
       
   140             }
       
   141 
       
   142             if (start + currentCommand >= end) {
       
   143                 currentCommand = 1;
       
   144 		++currentIteration;
       
   145                 if (currentIteration == 3) {
       
   146                     timer.start();
       
   147                     iterationTimes.fill(uint(-1));
       
   148                 }
       
   149 		if (currentIteration >= 3 && currentIteration < singleFrameIterations + 3)
       
   150                     printf("Profiling iteration %d of %d\n", currentIteration - 2, singleFrameIterations);
       
   151             } else {
       
   152                 ++currentCommand;
       
   153 	    }
       
   154         }
       
   155 
       
   156         return;
       
   157     }
    84 
   158 
    85     buffer.draw(&p, visibleUpdates.at(currentFrame));
   159     buffer.draw(&p, visibleUpdates.at(currentFrame));
    86 
   160 
    87     ++currentFrame;
   161     ++currentFrame;
    88     if (currentFrame >= visibleUpdates.size()) {
   162     if (currentFrame >= visibleUpdates.size()) {
    89         currentFrame = 0;
   163         currentFrame = 0;
    90         ++currentIteration;
   164         ++currentIteration;
       
   165 
       
   166         if (single) {
       
   167             deleteLater();
       
   168             return;
       
   169         }
    91 
   170 
    92         if (currentIteration == 3)
   171         if (currentIteration == 3)
    93             timer.start();
   172             timer.start();
    94         else if (currentIteration > 3) {
   173         else if (currentIteration > 3) {
    95             iterationTimes << timer.elapsed();
   174             iterationTimes << timer.elapsed();
   126                     return;
   205                     return;
   127                 }
   206                 }
   128             }
   207             }
   129         }
   208         }
   130     }
   209     }
   131 
   210 }
   132     QTimer::singleShot(0, this, SLOT(updateRect()));
   211 
   133 }
   212 void ReplayWidget::resizeEvent(QResizeEvent *)
   134 
       
   135 void ReplayWidget::resizeEvent(QResizeEvent *event)
       
   136 {
   213 {
   137     visibleUpdates.clear();
   214     visibleUpdates.clear();
   138 
   215 
   139     QRect bounds = rect();
   216     QRect bounds = rect();
   140     for (int i = 0; i < updates.size(); ++i) {
   217 
       
   218     int first = qMax(0, from);
       
   219     int last = qMin(unsigned(to), unsigned(updates.size()));
       
   220     for (int i = first; i < last; ++i) {
   141         if (updates.at(i).intersects(bounds))
   221         if (updates.at(i).intersects(bounds))
   142             visibleUpdates << i;
   222             visibleUpdates << i;
   143     }
   223     }
   144 
   224 
   145     if (visibleUpdates.size() != updates.size())
   225     int range = last - first;
   146         printf("Warning: skipped %d frames due to limited resolution\n", updates.size() - visibleUpdates.size());
   226 
   147 
   227     if (visibleUpdates.size() != range)
   148 }
   228         printf("Warning: skipped %d frames due to limited resolution\n", range - visibleUpdates.size());
   149 
   229 
   150 ReplayWidget::ReplayWidget(const QString &filename_)
   230 }
       
   231 
       
   232 ReplayWidget::ReplayWidget(const QString &filename_, int from_, int to_, bool single_, int frame_)
   151     : currentFrame(0)
   233     : currentFrame(0)
   152     , currentIteration(0)
   234     , currentIteration(0)
   153     , filename(filename_)
   235     , filename(filename_)
       
   236     , from(from_)
       
   237     , to(to_)
       
   238     , single(single_)
       
   239     , frame(frame_)
       
   240     , currentCommand(1)
   154 {
   241 {
   155     setWindowTitle(filename);
   242     setWindowTitle(filename);
   156     QFile file(filename);
   243     QFile file(filename);
   157 
   244 
   158     if (!file.open(QIODevice::ReadOnly)) {
   245     if (!file.open(QIODevice::ReadOnly)) {
   163     QDataStream in(&file);
   250     QDataStream in(&file);
   164 
   251 
   165     char *data;
   252     char *data;
   166     uint size;
   253     uint size;
   167     in.readBytes(data, size);
   254     in.readBytes(data, size);
   168     bool isTraceFile = size == 7 && qstrncmp(data, "qttrace", 7) == 0;
   255     bool isTraceFile = size >= 7 && qstrncmp(data, "qttrace", 7) == 0;
   169     delete [] data;
   256 
       
   257     uint version = 0;
       
   258     if (size == 9 && qstrncmp(data, "qttraceV2", 9) == 0) {
       
   259         in.setFloatingPointPrecision(QDataStream::SinglePrecision);
       
   260         in >> version;
       
   261     }
       
   262 
   170     if (!isTraceFile) {
   263     if (!isTraceFile) {
   171         printf("File '%s' is not a trace file\n", qPrintable(filename_));
   264         printf("File '%s' is not a trace file\n", qPrintable(filename_));
   172         return;
   265         return;
   173     }
   266     }
   174 
   267 
   175     in >> buffer >> updates;
   268     in >> buffer >> updates;
   176     printf("Read paint buffer with %d frames\n", buffer.numFrames());
   269     printf("Read paint buffer version %d with %d frames\n", version, buffer.numFrames());
   177 
   270 
   178     resize(buffer.boundingRect().size().toSize());
   271     resize(buffer.boundingRect().size().toSize());
   179 
   272 
   180     setAutoFillBackground(false);
   273     setAutoFillBackground(false);
   181     setAttribute(Qt::WA_NoSystemBackground);
   274     setAttribute(Qt::WA_NoSystemBackground);
   187 {
   280 {
   188     QApplication app(argc, argv);
   281     QApplication app(argc, argv);
   189 
   282 
   190     if (argc <= 1 || qstrcmp(argv[1], "-h") == 0 || qstrcmp(argv[1], "--help") == 0) {
   283     if (argc <= 1 || qstrcmp(argv[1], "-h") == 0 || qstrcmp(argv[1], "--help") == 0) {
   191         printf("Replays a tracefile generated with '-graphicssystem trace'\n");
   284         printf("Replays a tracefile generated with '-graphicssystem trace'\n");
   192         printf("Usage:\n  > %s [traceFile]\n", argv[0]);
   285         printf("Usage:\n  > %s [OPTIONS] [traceFile]\n", argv[0]);
       
   286         printf("OPTIONS\n"
       
   287                "   --range=from-to to specify a frame range.\n"
       
   288                "   --singlerun to do only one run (without statistics)\n"
       
   289                "   --instrumentframe=frame to instrument a single frame\n");
   193         return 1;
   290         return 1;
   194     }
   291     }
   195 
   292 
   196     QFile file(argv[1]);
   293     QFile file(app.arguments().last());
   197     if (!file.exists()) {
   294     if (!file.exists()) {
   198         printf("%s does not exist\n", argv[1]);
   295         printf("%s does not exist\n", qPrintable(app.arguments().last()));
   199         return 1;
   296         return 1;
   200     }
   297     }
   201 
   298 
   202     ReplayWidget *widget = new ReplayWidget(argv[1]);
   299     bool single = false;
       
   300 
       
   301     int frame = -1;
       
   302 
       
   303     int from = 0;
       
   304     int to = -1;
       
   305     for (int i = 1; i < app.arguments().size() - 1; ++i) {
       
   306         QString arg = app.arguments().at(i);
       
   307         if (arg.startsWith(QLatin1String("--range="))) {
       
   308             QString rest = arg.mid(8);
       
   309             QStringList components = rest.split(QLatin1Char('-'));
       
   310 
       
   311             bool ok1 = false;
       
   312             bool ok2 = false;
       
   313             int fromCandidate = 0;
       
   314             int toCandidate = 0;
       
   315             if (components.size() == 2) {
       
   316                 fromCandidate = components.first().toInt(&ok1);
       
   317                 toCandidate = components.last().toInt(&ok2);
       
   318             }
       
   319 
       
   320             if (ok1 && ok2) {
       
   321                 from = fromCandidate;
       
   322                 to = toCandidate;
       
   323             } else {
       
   324                 printf("ERROR: malformed syntax in argument %s\n", qPrintable(arg));
       
   325             }
       
   326         } else if (arg == QLatin1String("--singlerun")) {
       
   327             single = true;
       
   328         } else if (arg.startsWith(QLatin1String("--instrumentframe="))) {
       
   329             QString rest = arg.mid(18);
       
   330             bool ok = false;
       
   331             int frameCandidate = rest.toInt(&ok);
       
   332             if (ok) {
       
   333                 frame = frameCandidate;
       
   334             } else {
       
   335                 printf("ERROR: malformed syntax in argument %s\n", qPrintable(arg));
       
   336             }
       
   337         } else {
       
   338             printf("Unrecognized argument: %s\n", qPrintable(arg));
       
   339             return 1;
       
   340         }
       
   341     }
       
   342 
       
   343     ReplayWidget *widget = new ReplayWidget(app.arguments().last(), from, to, single, frame);
   203 
   344 
   204     if (!widget->updates.isEmpty()) {
   345     if (!widget->updates.isEmpty()) {
   205         widget->show();
   346         widget->show();
   206         return app.exec();
   347         return app.exec();
   207     }
   348     }