X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=glretrace_main.cpp;h=3a900927a128a3d6d46ec0055002d03f964f7fe6;hb=447f4a55a01e82b0265f44212b8d439fa83750d7;hp=922ec303b01e0f72e7976a3aaa5d90ef45868baa;hpb=e4999b9a9f28c62cc3cc809131fc7a1099b10e68;p=apitrace diff --git a/glretrace_main.cpp b/glretrace_main.cpp index 922ec30..3a90092 100644 --- a/glretrace_main.cpp +++ b/glretrace_main.cpp @@ -29,12 +29,13 @@ #include "image.hpp" #include "retrace.hpp" #include "glproc.hpp" +#include "glstate.hpp" #include "glretrace.hpp" namespace glretrace { -bool double_buffer = false; +bool double_buffer = true; bool insideGlBeginEnd = false; Trace::Parser parser; glws::WindowSystem *ws = NULL; @@ -42,8 +43,6 @@ glws::Visual *visual = NULL; glws::Drawable *drawable = NULL; glws::Context *context = NULL; -int window_width = 256, window_height = 256; - unsigned frame = 0; long long startTime = 0; bool wait = false; @@ -51,25 +50,27 @@ bool wait = false; bool benchmark = false; const char *compare_prefix = NULL; const char *snapshot_prefix = NULL; +enum frequency snapshot_frequency = FREQUENCY_NEVER; unsigned dump_state = ~0; void -checkGlError(int callIdx) { - if (benchmark || insideGlBeginEnd) { - return; - } - +checkGlError(Trace::Call &call) { GLenum error = glGetError(); if (error == GL_NO_ERROR) { return; } - if (callIdx >= 0) { - std::cerr << callIdx << ": "; + if (retrace::verbosity == 0) { + std::cout << call; + std::cout.flush(); } - std::cerr << "warning: glGetError() = "; + std::cerr << call.no << ": "; + std::cerr << "warning: glGetError("; + std::cerr << call.name(); + std::cerr << ") = "; + switch (error) { case GL_INVALID_ENUM: std::cerr << "GL_INVALID_ENUM"; @@ -103,91 +104,92 @@ checkGlError(int callIdx) { } -static void snapshot(Image::Image &image) { - GLint drawbuffer = double_buffer ? GL_BACK : GL_FRONT; - GLint readbuffer = double_buffer ? GL_BACK : GL_FRONT; - glGetIntegerv(GL_DRAW_BUFFER, &drawbuffer); - glGetIntegerv(GL_READ_BUFFER, &readbuffer); - glReadBuffer(drawbuffer); - glReadPixels(0, 0, image.width, image.height, GL_RGBA, GL_UNSIGNED_BYTE, image.pixels); - checkGlError(); - glReadBuffer(readbuffer); -} +void snapshot(unsigned call_no) { + if (!drawable || + (!snapshot_prefix && !compare_prefix)) { + return; + } + Image::Image *ref = NULL; -void frame_complete(unsigned call_no) { - ++frame; - - if (snapshot_prefix || compare_prefix) { - Image::Image *ref = NULL; - if (compare_prefix) { - char filename[PATH_MAX]; - snprintf(filename, sizeof filename, "%s%010u.png", compare_prefix, call_no); - ref = Image::readPNG(filename); - if (!ref) { - return; - } - if (retrace::verbosity >= 0) - std::cout << "Read " << filename << "\n"; + if (compare_prefix) { + char filename[PATH_MAX]; + snprintf(filename, sizeof filename, "%s%010u.png", compare_prefix, call_no); + ref = Image::readPNG(filename); + if (!ref) { + return; + } + if (retrace::verbosity >= 0) { + std::cout << "Read " << filename << "\n"; } - - Image::Image src(window_width, window_height, true); - snapshot(src); + } + + Image::Image *src = glstate::getDrawBufferImage(GL_RGBA); + if (!src) { + return; + } - if (snapshot_prefix) { + if (snapshot_prefix) { + if (snapshot_prefix[0] == '-' && snapshot_prefix[1] == 0) { + char comment[21]; + snprintf(comment, sizeof comment, "%u", call_no); + src->writePNM(std::cout, comment); + } else { char filename[PATH_MAX]; snprintf(filename, sizeof filename, "%s%010u.png", snapshot_prefix, call_no); - if (src.writePNG(filename) && retrace::verbosity >= 0) { + if (src->writePNG(filename) && retrace::verbosity >= 0) { std::cout << "Wrote " << filename << "\n"; } } + } - if (ref) { - std::cout << "Snapshot " << call_no << " average precision of " << src.compare(*ref) << " bits\n"; - delete ref; - } + if (ref) { + std::cout << "Snapshot " << call_no << " average precision of " << src->compare(*ref) << " bits\n"; + delete ref; } + delete src; +} + + +void frame_complete(unsigned call_no) { + ++frame; + + if (snapshot_frequency == FREQUENCY_FRAME || + snapshot_frequency == FREQUENCY_FRAMEBUFFER) { + snapshot(call_no); + } } static void display(void) { + startTime = OS::GetTime(); Trace::Call *call; while ((call = parser.parse_call())) { - const std::string &name = call->name(); - bool skipCall = false; - - if ((name[0] == 'w' && name[1] == 'g' && name[2] == 'l') || - (name[0] == 'g' && name[1] == 'l' && name[2] == 'X')) { - // XXX: We ignore the majority of the OS-specific calls for now - if (name == "glXSwapBuffers" || - name == "wglSwapBuffers") { - if (retrace::verbosity >= 1) { - std::cout << *call; - std::cout.flush(); - }; - frame_complete(call->no); - if (double_buffer) - drawable->swapBuffers(); - else - glFlush(); - } else if (name == "glXMakeCurrent" || - name == "wglMakeCurrent") { - glFlush(); - if (!double_buffer) { - frame_complete(call->no); - } - } - skipCall = true; + const char *name = call->name(); + + if (retrace::verbosity >= 1) { + std::cout << *call; + std::cout.flush(); } - if (!skipCall) { + if (name[0] == 'C' && name[1] == 'G' && name[2] == 'L') { + glretrace::retrace_call_cgl(*call); + } + else if (name[0] == 'w' && name[1] == 'g' && name[2] == 'l') { + glretrace::retrace_call_wgl(*call); + } + else if (name[0] == 'g' && name[1] == 'l' && name[2] == 'X') { + glretrace::retrace_call_glx(*call); + } else { retrace::retrace_call(*call); } - if (!insideGlBeginEnd && call->no >= dump_state) { - state_dump(std::cout); + if (!insideGlBeginEnd && + drawable && context && + call->no >= dump_state) { + glstate::dumpCurrentContext(std::cout); exit(0); } @@ -220,10 +222,12 @@ static void usage(void) { "Usage: glretrace [OPTION] TRACE\n" "Replay TRACE.\n" "\n" - " -b benchmark (no glgeterror; no messages)\n" + " -b benchmark mode (no error checking or warning messages)\n" " -c PREFIX compare against snapshots\n" - " -db use a double buffer visual\n" - " -s PREFIX take snapshots\n" + " -db use a double buffer visual (default)\n" + " -sb use a single buffer visual\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" " -w wait on final frame\n"; @@ -248,16 +252,43 @@ int main(int argc, char **argv) retrace::verbosity = -1; } else if (!strcmp(arg, "-c")) { compare_prefix = argv[++i]; + if (snapshot_frequency == FREQUENCY_NEVER) { + snapshot_frequency = FREQUENCY_FRAME; + } } else if (!strcmp(arg, "-D")) { dump_state = atoi(argv[++i]); retrace::verbosity = -2; } else if (!strcmp(arg, "-db")) { double_buffer = true; + } else if (!strcmp(arg, "-sb")) { + double_buffer = false; } else if (!strcmp(arg, "--help")) { usage(); return 0; } else if (!strcmp(arg, "-s")) { snapshot_prefix = argv[++i]; + 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")) { + snapshot_frequency = FREQUENCY_FRAME; + } else if (!strcmp(arg, "framebuffer")) { + snapshot_frequency = FREQUENCY_FRAMEBUFFER; + } else if (!strcmp(arg, "draw")) { + snapshot_frequency = FREQUENCY_DRAW; + } else { + std::cerr << "error: unknown frequency " << arg << "\n"; + usage(); + return 1; + } + if (snapshot_prefix == NULL) { + snapshot_prefix = ""; + } } else if (!strcmp(arg, "-v")) { ++retrace::verbosity; } else if (!strcmp(arg, "-w")) { @@ -271,17 +302,16 @@ int main(int argc, char **argv) ws = glws::createNativeWindowSystem(); visual = ws->createVisual(double_buffer); - drawable = ws->createDrawable(visual); - drawable->resize(window_width, window_height); - context = ws->createContext(visual); - ws->makeCurrent(drawable, context); for ( ; i < argc; ++i) { - if (parser.open(argv[i])) { - startTime = OS::GetTime(); - display(); - parser.close(); + if (!parser.open(argv[i])) { + std::cerr << "error: failed to open " << argv[i] << "\n"; + return 1; } + + display(); + + parser.close(); } return 0;