]> git.cworth.org Git - apitrace/blobdiff - gui/retracer.cpp
qapitrace: Adjust PATH only once and for all.
[apitrace] / gui / retracer.cpp
index d0e07ef9f4d54066e56042ed8df7ae16fd036427..2928ed63f321f31e34667e2448e1b8f765f2fdbf 100644 (file)
@@ -3,7 +3,9 @@
 #include "apitracecall.h"
 #include "thumbnail.h"
 
-#include "image.hpp"
+#include "image/image.hpp"
+
+#include "trace_profiler.hpp"
 
 #include <QDebug>
 #include <QVariant>
@@ -129,22 +131,12 @@ Retracer::Retracer(QObject *parent)
       m_benchmarking(false),
       m_doubleBuffered(true),
       m_captureState(false),
-      m_captureCall(0)
+      m_captureCall(0),
+      m_profileGpu(false),
+      m_profileCpu(false),
+      m_profilePixels(false)
 {
     qRegisterMetaType<QList<ApiTraceError> >();
-
-#ifdef Q_OS_WIN
-    QString format = QLatin1String("%1;");
-#else
-    QString format = QLatin1String("%1:");
-#endif
-    QString buildPath = format.arg(APITRACE_BINARY_DIR);
-    m_processEnvironment = QProcessEnvironment::systemEnvironment();
-    m_processEnvironment.insert("PATH", buildPath +
-                                m_processEnvironment.value("PATH"));
-
-    qputenv("PATH",
-            m_processEnvironment.value("PATH").toLatin1());
 }
 
 QString Retracer::fileName() const
@@ -182,6 +174,33 @@ void Retracer::setDoubleBuffered(bool db)
     m_doubleBuffered = db;
 }
 
+bool Retracer::isProfilingGpu() const
+{
+    return m_profileGpu;
+}
+
+bool Retracer::isProfilingCpu() const
+{
+    return m_profileCpu;
+}
+
+bool Retracer::isProfilingPixels() const
+{
+    return m_profilePixels;
+}
+
+bool Retracer::isProfiling() const
+{
+    return m_profileGpu || m_profileCpu || m_profilePixels;
+}
+
+void Retracer::setProfiling(bool gpu, bool cpu, bool pixels)
+{
+    m_profileGpu = gpu;
+    m_profileCpu = cpu;
+    m_profilePixels = pixels;
+}
+
 void Retracer::setCaptureAtCallNumber(qlonglong num)
 {
     m_captureCall = num;
@@ -212,7 +231,6 @@ void Retracer::setCaptureThumbnails(bool enable)
     m_captureThumbnails = enable;
 }
 
-
 /**
  * Starting point for the retracing thread.
  *
@@ -220,7 +238,7 @@ void Retracer::setCaptureThumbnails(bool enable)
  */
 void Retracer::run()
 {
-    QString msg;
+    QString msg = QLatin1String("Replay finished!");
 
     /*
      * Construct command line
@@ -229,29 +247,58 @@ void Retracer::run()
     QString prog;
     QStringList arguments;
 
-    if (m_api == trace::API_GL) {
+    switch (m_api) {
+    case trace::API_GL:
         prog = QLatin1String("glretrace");
-    } else if (m_api == trace::API_EGL) {
+        break;
+    case trace::API_EGL:
         prog = QLatin1String("eglretrace");
-    } else {
+        break;
+    case trace::API_DX:
+    case trace::API_D3D7:
+    case trace::API_D3D8:
+    case trace::API_D3D9:
+    case trace::API_DXGI:
+#ifdef Q_OS_WIN
+        prog = QLatin1String("d3dretrace");
+#else
+        prog = QLatin1String("wine");
+        arguments << QLatin1String("d3dretrace.exe");
+#endif
+        break;
+    default:
         emit finished(QLatin1String("Unsupported API"));
         return;
     }
 
-    if (m_doubleBuffered) {
-        arguments << QLatin1String("-db");
-    } else {
-        arguments << QLatin1String("-sb");
-    }
-
     if (m_captureState) {
         arguments << QLatin1String("-D");
         arguments << QString::number(m_captureCall);
     } else if (m_captureThumbnails) {
         arguments << QLatin1String("-s"); // emit snapshots
         arguments << QLatin1String("-"); // emit to stdout
-    } else if (m_benchmarking) {
-        arguments << QLatin1String("-b");
+    } else if (isProfiling()) {
+        if (m_profileGpu) {
+            arguments << QLatin1String("--pgpu");
+        }
+
+        if (m_profileCpu) {
+            arguments << QLatin1String("--pcpu");
+        }
+
+        if (m_profilePixels) {
+            arguments << QLatin1String("--ppd");
+        }
+    } else {
+        if (m_doubleBuffered) {
+            arguments << QLatin1String("--db");
+        } else {
+            arguments << QLatin1String("--sb");
+        }
+
+        if (m_benchmarking) {
+            arguments << QLatin1String("-b");
+        }
     }
 
     arguments << m_fileName;
@@ -274,6 +321,7 @@ void Retracer::run()
 
     QList<QImage> thumbnails;
     QVariantMap parsedJson;
+    trace::Profile* profile = NULL;
 
     process.setReadChannel(QProcess::StandardOutput);
     if (process.waitForReadyRead(-1)) {
@@ -283,8 +331,6 @@ void Retracer::run()
             /*
              * Parse JSON from the output.
              *
-             * XXX: QJSON expects blocking IO.
-             *
              * XXX: QJSON's scanner is inneficient as it abuses single
              * character QIODevice::peek (not cheap), instead of maintaining a
              * lookahead character on its own.
@@ -292,7 +338,19 @@ void Retracer::run()
 
             bool ok = false;
             QJson::Parser jsonParser;
+
+            // Allow Nan/Infinity
+            jsonParser.allowSpecialNumbers(true);
+#if 0
             parsedJson = jsonParser.parse(&io, &ok).toMap();
+#else
+            /*
+             * XXX: QJSON expects blocking IO, and it looks like
+             * BlockingIODevice does not work reliably in all cases.
+             */
+            process.waitForFinished(-1);
+            parsedJson = jsonParser.parse(&process, &ok).toMap();
+#endif
             if (!ok) {
                 msg = QLatin1String("failed to parse JSON");
             }
@@ -338,6 +396,7 @@ void Retracer::run()
                     unsigned char *scanLine = snapshot.scanLine(y);
                     qint64 readBytes = io.read((char *) scanLine, rowBytes);
                     Q_ASSERT(readBytes == rowBytes);
+                    (void)readBytes;
                 }
 
                 QImage thumb = thumbnail(snapshot);
@@ -345,11 +404,26 @@ void Retracer::run()
             }
 
             Q_ASSERT(process.state() != QProcess::Running);
+        } else if (isProfiling()) {
+            profile = new trace::Profile();
 
+            while (!io.atEnd()) {
+                char line[256];
+                qint64 lineLength;
+
+                lineLength = io.readLine(line, 256);
+
+                if (lineLength == -1)
+                    break;
+
+                trace::Profiler::parseLine(line, profile);
+            }
         } else {
             QByteArray output;
             output = process.readAllStandardOutput();
-            msg = QString::fromUtf8(output);
+            if (output.length() < 80) {
+                msg = QString::fromUtf8(output);
+            }
         }
     }
 
@@ -380,6 +454,14 @@ void Retracer::run()
             error.type = regexp.cap(2);
             error.message = regexp.cap(3);
             errors.append(error);
+        } else if (!errors.isEmpty()) {
+            // Probably a multiligne message
+            ApiTraceError &previous = errors.last();
+            if (line.endsWith("\n")) {
+                line.chop(1);
+            }
+            previous.message.append('\n');
+            previous.message.append(line);
         }
     }
 
@@ -397,6 +479,10 @@ void Retracer::run()
         emit foundThumbnails(thumbnails);
     }
 
+    if (isProfiling() && profile) {
+        emit foundProfile(profile);
+    }
+
     if (!errors.isEmpty()) {
         emit retraceErrors(errors);
     }