예제 #1
0
파일: retrace.cpp 프로젝트: kanru/apitrace
void Retracer::retrace(trace::Call &call) {
    call_dumped = false;

    if (verbosity >= 1) {
        dumpCall(call);
    }

    Callback callback = 0;

    trace::Id id = call.sig->id;
    if (id >= callbacks.size()) {
        callbacks.resize(id + 1);
        callback = 0;
    } else {
        callback = callbacks[id];
    }

    if (!callback) {
        Map::const_iterator it = map.find(call.name());
        if (it == map.end()) {
            callback = &unsupported;
        } else {
            callback = it->second;
        }
        callbacks[id] = callback;
    }

    assert(callback);
    assert(callbacks[id] == callback);

    callback(call);
}
예제 #2
0
void
checkGlError(trace::Call &call) {
    GLenum error = glGetError();
    while (error != GL_NO_ERROR) {
        uint64_t errorHash = call.sig->id ^ uint64_t(error) << 32;
        size_t errorCount = errorCounts[errorHash]++;
        if (errorCount <= maxWarningCount) {
            std::ostream & os = retrace::warning(call);

            os << "glGetError(";
            os << call.name();
            os << ") = ";

            switch (error) {
            case GL_INVALID_ENUM:
                os << "GL_INVALID_ENUM";
                break;
            case GL_INVALID_VALUE:
                os << "GL_INVALID_VALUE";
                break;
            case GL_INVALID_OPERATION:
                os << "GL_INVALID_OPERATION";
                break;
            case GL_STACK_OVERFLOW:
                os << "GL_STACK_OVERFLOW";
                break;
            case GL_STACK_UNDERFLOW:
                os << "GL_STACK_UNDERFLOW";
                break;
            case GL_OUT_OF_MEMORY:
                os << "GL_OUT_OF_MEMORY";
                break;
            case GL_INVALID_FRAMEBUFFER_OPERATION:
                os << "GL_INVALID_FRAMEBUFFER_OPERATION";
                break;
            case GL_TABLE_TOO_LARGE:
                os << "GL_TABLE_TOO_LARGE";
                break;
            default:
                os << error;
                break;
            }

            if (errorCount == maxWarningCount) {
                os << ": too many identical messages; ignoring";
            }

            os << std::endl;
        }

        error = glGetError();
    }
}
예제 #3
0
static void display(void) {
    startTime = OS::GetTime();
    Trace::Call *call;

    while ((call = parser.parse_call())) {
        const char *name = call->name();

        if (retrace::verbosity >= 1) {
            std::cout << *call;
            std::cout.flush();
        }

        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 &&
            drawable && context &&
            call->no >= dump_state) {
            glstate::dumpCurrentContext(std::cout);
            exit(0);
        }

        delete call;
    }

    // Reached the end of trace
    glFlush();

    long long endTime = OS::GetTime();
    float timeInterval = (endTime - startTime) * 1.0E-6;

    if (retrace::verbosity >= -1) { 
        std::cout << 
            "Rendered " << frame << " frames"
            " in " <<  timeInterval << " secs,"
            " average of " << (frame/timeInterval) << " fps\n";
    }

    if (wait) {
        while (ws->processEvents()) {}
    } else {
        exit(0);
    }
}
예제 #4
0
void Retracer::retrace(trace::Call &call) {
    call_dumped = false;

    if (verbosity >= 1) {
        if (verbosity >= 2 ||
            !(call.flags & trace::CALL_FLAG_VERBOSE)) {
            dumpCall(call);
        }
    }

    Callback callback = 0;

    trace::Id id = call.sig->id;
    if (id >= callbacks.size()) {
        callbacks.resize(id + 1);
        callback = 0;
    } else {
        callback = callbacks[id];
    }

    if (!callback) {
        Map::const_iterator it = map.find(call.name());
        if (it == map.end()) {
            callback = &unsupported;
        } else {
            callback = it->second;
        }
        callbacks[id] = callback;
    }

    assert(callback);
    assert(callbacks[id] == callback);

    if (retrace::profiling) {
        long long startTime = os::getTime();
        callback(call);
        long long stopTime = os::getTime();
        float timeInterval = (stopTime - startTime) * (1.0E6 / os::timeFrequency);

        std::cout
            << call.no << " "
            << "[" << timeInterval << " usec] "
        ;
        trace::dump(call, std::cout, trace::DUMP_FLAG_NO_CALL_NO | trace::DUMP_FLAG_NO_COLOR);
    } else {
        callback(call);
    }
}
예제 #5
0
void
checkGlError(Trace::Call &call) {
    GLenum error = glGetError();
    if (error == GL_NO_ERROR) {
        return;
    }

    if (retrace::verbosity == 0) {
        std::cout << call;
        std::cout.flush();
    }

    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";
        break;
    case GL_INVALID_VALUE:
        std::cerr << "GL_INVALID_VALUE";
        break;
    case GL_INVALID_OPERATION:
        std::cerr << "GL_INVALID_OPERATION";
        break;
    case GL_STACK_OVERFLOW:
        std::cerr << "GL_STACK_OVERFLOW";
        break;
    case GL_STACK_UNDERFLOW:
        std::cerr << "GL_STACK_UNDERFLOW";
        break;
    case GL_OUT_OF_MEMORY:
        std::cerr << "GL_OUT_OF_MEMORY";
        break;
    case GL_INVALID_FRAMEBUFFER_OPERATION:
        std::cerr << "GL_INVALID_FRAMEBUFFER_OPERATION";
        break;
    case GL_TABLE_TOO_LARGE:
        std::cerr << "GL_TABLE_TOO_LARGE";
        break;
    default:
        std::cerr << error;
        break;
    }
    std::cerr << "\n";
}
예제 #6
0
void
checkGlError(trace::Call &call) {
    GLenum error = glGetError();
    if (error == GL_NO_ERROR) {
        return;
    }

    std::ostream & os = retrace::warning(call);

    os << "glGetError(";
    os << call.name();
    os << ") = ";

    switch (error) {
    case GL_INVALID_ENUM:
        os << "GL_INVALID_ENUM";
        break;
    case GL_INVALID_VALUE:
        os << "GL_INVALID_VALUE";
        break;
    case GL_INVALID_OPERATION:
        os << "GL_INVALID_OPERATION";
        break;
    case GL_STACK_OVERFLOW:
        os << "GL_STACK_OVERFLOW";
        break;
    case GL_STACK_UNDERFLOW:
        os << "GL_STACK_UNDERFLOW";
        break;
    case GL_OUT_OF_MEMORY:
        os << "GL_OUT_OF_MEMORY";
        break;
    case GL_INVALID_FRAMEBUFFER_OPERATION:
        os << "GL_INVALID_FRAMEBUFFER_OPERATION";
        break;
    case GL_TABLE_TOO_LARGE:
        os << "GL_TABLE_TOO_LARGE";
        break;
    default:
        os << error;
        break;
    }
    os << "\n";
}
예제 #7
0
void calcStatistics(trace::Call &call) {
    /* Count the total number of calls */
    nCalls += 1;

    /* Count the rendering calls */
    if(call.flags & trace::CALL_FLAG_RENDER)
        nRenderCalls += 1;

    /* Calculate the uploaded texel size */
    const char* funcName = call.name();
    if(!strcmp(funcName,"glTexImage2D"))
    {
        unsigned width = call.arg(3).toUInt();
        unsigned height = call.arg(4).toUInt();
        texUploads += width*height;
    }
    else if (!strcmp(funcName,"glTexSubImage2D"))
    {
        unsigned width = call.arg(4).toUInt();
        unsigned height = call.arg(5).toUInt();
        texUploads += width*height;
    }

    /* Count the number of vertices and triangles */
    if(call.flags & trace::CALL_FLAG_RENDER)
    {
        // std::cout << funcName << std::endl;
        const trace::FunctionSig* sig = call.sig;
        unsigned nargs = sig->num_args;

        /* See if it has 'count' and/or 'mode' in its arguments */
        int midx = -1;
        int cidx = -1;
        for(int i=0; i<nargs; i++)
        {
            if(!strcmp(sig->arg_names[i], "mode"))
            {
                midx = i;
            }
            else if(!strcmp(sig->arg_names[i], "count"))
            {
                cidx = i;
            }
        }

        if(cidx >= 0)
        {
            int count = call.arg(cidx).toSInt();
            nVertices += count;

            if(midx >= 0)
            {
                int mode = call.arg(midx).toSInt();

                switch(mode)
                {
                    case GL_POINTS:
                        count = count * 2;
                        break;
                    case GL_LINES:
                        count = count;
                        break;
                    case GL_LINE_LOOP:
                        count = count * 2 + 2;
                        break;
                    case GL_LINE_STRIP:
                        count = count * 2;
                        break;
                    case GL_TRIANGLES:
                        count = count / 3;
                        break;
                    case GL_TRIANGLE_STRIP:
                        count = count - 2;
                        break;
                    case GL_TRIANGLE_FAN:
                        count = count - 2;
                        break;
                    default:
                        break;
                }

                nTriangles += count;
            }
        }
    }
}
예제 #8
0
void unsupported(trace::Call &call) {
    warning(call) << "unsupported " << call.name() << " call\n";
}
예제 #9
0
static void display(void) {
    Trace::Call *call;

    while ((call = parser.parse_call())) {
        const std::string &name = call->name();

        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();
                if (double_buffer)
                    drawable->swapBuffers();
                else
                    glFlush();
            } else if (name == "glXMakeCurrent" ||
                       name == "wglMakeCurrent") {
                glFlush();
                if (!double_buffer) {
                    frame_complete();
                }
            } else {
                continue;
            }
        }

        if (name == "glFlush") {
            glFlush();
            if (!double_buffer) {
                frame_complete();
            }
        }
        
        retrace::retrace_call(*call);

        if (!insideGlBeginEnd && call->no >= dump_state) {
            state_dump(std::cout);
            exit(0);
        }

        delete call;
    }

    // Reached the end of trace
    glFlush();

    long long endTime = OS::GetTime();
    float timeInterval = (endTime - startTime) * 1.0E-6;

    if (retrace::verbosity >= -1) { 
        std::cout << 
            "Rendered " << frame << " frames"
            " in " <<  timeInterval << " secs,"
            " average of " << (frame/timeInterval) << " fps\n";
    }

    if (wait) {
        while (ws->processEvents()) {}
    } else {
        exit(0);
    }
}