summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rwxr-xr-xCMakeLists.txt1
-rw-r--r--README.markdown6
-rw-r--r--glretrace_main.cpp17
-rw-r--r--image.hpp20
-rw-r--r--image_pnm.cpp67
6 files changed, 107 insertions, 5 deletions
diff --git a/.gitignore b/.gitignore
index 5b141147..b2dda424 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,6 +16,7 @@
*.obj
*.pdb
*.png
+*.pnm
*.pyc
*.pyo
*.so
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c015d67b..c731a360 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -162,6 +162,7 @@ add_library (common
trace_model_writer.cpp
image.cpp
image_bmp.cpp
+ image_pnm.cpp
image_png.cpp
${os}
)
diff --git a/README.markdown b/README.markdown
index 790407d4..cbacc0d1 100644
--- a/README.markdown
+++ b/README.markdown
@@ -129,6 +129,12 @@ to trace by using `glxtrace.so` as an ordinary `libGL.so` and injecting into
See the 'ld.so' man page for more information about `LD_PRELOAD` and
`LD_LIBRARY_PATH` environment flags.
+You can make a video of the output by doing
+
+ /path/to/glretrace -s - application.trace \
+ | ffmpeg -r 30 -f image2pipe -vcodec ppm -i pipe: -vcodec mpeg4 -y output.mp4
+
+
Mac OS X
--------
diff --git a/glretrace_main.cpp b/glretrace_main.cpp
index beaac82d..56ee7632 100644
--- a/glretrace_main.cpp
+++ b/glretrace_main.cpp
@@ -130,10 +130,14 @@ void snapshot(unsigned call_no) {
}
if (snapshot_prefix) {
- char filename[PATH_MAX];
- snprintf(filename, sizeof filename, "%s%010u.png", snapshot_prefix, call_no);
- if (src->writePNG(filename) && retrace::verbosity >= 0) {
- std::cout << "Wrote " << filename << "\n";
+ if (snapshot_prefix[0] == '-' && snapshot_prefix[1] == 0) {
+ src->writePNM(std::cout);
+ } else {
+ char filename[PATH_MAX];
+ snprintf(filename, sizeof filename, "%s%010u.png", snapshot_prefix, call_no);
+ if (src->writePNG(filename) && retrace::verbosity >= 0) {
+ std::cout << "Wrote " << filename << "\n";
+ }
}
}
@@ -220,7 +224,7 @@ static void usage(void) {
" -c PREFIX compare against snapshots\n"
" -db use a double buffer visual (default)\n"
" -sb use a single buffer visual\n"
- " -s PREFIX take snapshots\n"
+ " -s PREFIX take snapshots; `-` for PNM stdout output\n"
" -S FREQUENCY snapshot frequency: frame (default), framebuffer, or draw\n"
" -v verbose output\n"
" -D CALLNO dump state at specific call no\n"
@@ -264,6 +268,9 @@ int main(int argc, char **argv)
if (snapshot_frequency == FREQUENCY_NEVER) {
snapshot_frequency = FREQUENCY_FRAME;
}
+ if (snapshot_prefix[0] == '-' && snapshot_prefix[1] == 0) {
+ retrace::verbosity = -2;
+ }
} else if (!strcmp(arg, "-S")) {
arg = argv[++i];
if (!strcmp(arg, "frame")) {
diff --git a/image.hpp b/image.hpp
index e02abed0..44fc4f43 100644
--- a/image.hpp
+++ b/image.hpp
@@ -65,15 +65,35 @@ public:
return flipped ? pixels + (height - 1)*width*channels : pixels;
}
+ inline const unsigned char *start(void) const {
+ return flipped ? pixels + (height - 1)*width*channels : pixels;
+ }
+
inline unsigned char *end(void) {
return flipped ? pixels - width*channels : pixels + height*width*channels;
}
+ inline const unsigned char *end(void) const {
+ return flipped ? pixels - width*channels : pixels + height*width*channels;
+ }
+
inline signed stride(void) const {
return flipped ? -width*channels : width*channels;
}
bool writeBMP(const char *filename) const;
+
+ void writePNM(std::ostream &os) const;
+
+ inline bool writePNM(const char *filename) const {
+ std::ofstream os(filename, std::ofstream::binary);
+ if (!os) {
+ return false;
+ }
+ writePNM(os);
+ return true;
+ }
+
bool writePNG(const char *filename) const;
double compare(Image &ref);
diff --git a/image_pnm.cpp b/image_pnm.cpp
new file mode 100644
index 00000000..6625f3dd
--- /dev/null
+++ b/image_pnm.cpp
@@ -0,0 +1,67 @@
+/**************************************************************************
+ *
+ * Copyright 2011 Jose Fonseca
+ * Copyright 2008-2010 VMware, Inc.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#include <assert.h>
+#include <stdint.h>
+
+#include "image.hpp"
+
+
+namespace Image {
+
+/**
+ * http://en.wikipedia.org/wiki/Netpbm_format
+ */
+void
+Image::writePNM(std::ostream &os) const {
+ assert(channels == 1 || channels >= 3);
+
+ os << (channels == 1 ? "P5" : "P6") << "\n";
+ os << width << " " << height << "\n";
+ os << "255" << "\n";
+
+ const unsigned char *row;
+
+ if (channels == 1 || channels == 3) {
+ for (row = start(); row != end(); row += stride()) {
+ os.write((const char *)row, width*channels);
+ }
+ } else {
+ unsigned char pixel[3] = {0, 0, 0};
+ for (row = start(); row != end(); row += stride()) {
+ for (unsigned x = 0; x < width; ++x) {
+ for (unsigned channel = 0; channel < channels; ++channel) {
+ pixel[channel] = row[x*channels + channel];
+ }
+ os.write((const char *)pixel, sizeof pixel);
+ }
+ }
+ }
+}
+
+
+} /* namespace Image */