static void retrace_eglChooseConfig(trace::Call &call) { if (!call.ret->toSInt()) { return; } trace::Array *attrib_array = call.arg(1).toArray(); trace::Array *config_array = call.arg(2).toArray(); trace::Array *num_config_ptr = call.arg(4).toArray(); if (!attrib_array || !config_array || !num_config_ptr) { return; } glprofile::Profile profile; unsigned renderableType = parseAttrib(attrib_array, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT); std::cerr << "renderableType = " << renderableType << "\n"; if (renderableType & EGL_OPENGL_BIT) { profile = glprofile::Profile(glprofile::API_GL, 1, 0); } else { profile.api = glprofile::API_GLES; if (renderableType & EGL_OPENGL_ES3_BIT) { profile.major = 3; } else if (renderableType & EGL_OPENGL_ES2_BIT) { profile.major = 2; } else { profile.major = 1; } } unsigned num_config = num_config_ptr->values[0]->toUInt(); for (unsigned i = 0; i < num_config; ++i) { unsigned long long orig_config = config_array->values[i]->toUIntPtr(); profile_map[orig_config] = profile; } }
static void retrace_memcpy(trace::Call &call) { void * destPtr; size_t destLen; retrace::toRange(call.arg(0), destPtr, destLen); void * srcPtr; size_t srcLen; retrace::toRange(call.arg(1), srcPtr, srcLen); size_t n = call.arg(2).toUInt(); if (!destPtr || !srcPtr || !n) { return; } if (n > destLen) { retrace::warning(call) << "dest buffer overflow of " << n - destLen << " bytes\n"; } if (n > srcLen) { retrace::warning(call) << "src buffer overflow of " << n - srcLen << " bytes\n"; } n = std::min(n, destLen); n = std::min(n, srcLen); memcpy(destPtr, srcPtr, n); }
static void retrace_wglUseFontBitmapsAW(trace::Call &call) { bool ret = call.ret->toBool(); if (!ret) { return; } uint32_t first = call.arg(1).toUInt(); uint32_t count = call.arg(2).toUInt(); uint32_t listBase = call.arg(3).toUInt(); GLint row_length = 0; GLint alignment = 4; _glGetIntegerv(GL_UNPACK_ROW_LENGTH, &row_length); _glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); for (uint32_t i = 0; i < count; ++i) { uint32_t dwChar = (first + i) % 256; const Bitmap *bm = &wglSystemFontBitmaps[dwChar]; glPixelStorei(GL_UNPACK_ROW_LENGTH, bm->width); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glNewList(listBase + i, GL_COMPILE); glBitmap(bm->width, bm->height, bm->xorig, bm->yorig, bm->xmove, bm->ymove, (const GLubyte *)bm->pixels); glEndList(); } glPixelStorei(GL_UNPACK_ROW_LENGTH, row_length); glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); }
static void retrace_glXMakeCurrent(Trace::Call &call) { glws::Drawable *new_drawable = getDrawable(call.arg(1).toUInt()); glws::Context *new_context = getContext(call.arg(2).toUIntPtr()); if (new_drawable == drawable && new_context == context) { return; } if (drawable && context) { glFlush(); if (!double_buffer) { frame_complete(call.no); } } bool result = ws->makeCurrent(new_drawable, new_context); if (new_drawable && new_context && result) { drawable = new_drawable; context = new_context; } else { drawable = NULL; context = NULL; } }
static void retrace_wglCreatePbufferARB(trace::Call &call) { unsigned long long orig_pbuffer = call.ret->toUIntPtr(); if (!orig_pbuffer) { return; } int iWidth = call.arg(2).toUInt(); int iHeight = call.arg(3).toUInt(); const trace::Value *attribs = &call.arg(4); glws::pbuffer_info pbInfo = {0, 0, false}; // XXX parse attrib list to populate pbInfo int k; k = parseAttrib(attribs, WGL_TEXTURE_FORMAT_ARB, WGL_NO_TEXTURE_ARB); switch (k) { case WGL_TEXTURE_RGB_ARB: pbInfo.texFormat = GL_RGB; break; case WGL_TEXTURE_RGBA_ARB: pbInfo.texFormat = GL_RGBA; break; case WGL_NO_TEXTURE_ARB: pbInfo.texFormat = GL_NONE; break; default: std::cerr << "error: invalid value for WGL_TEXTURE_FORMAT_ARB\n"; pbInfo.texFormat = GL_NONE; } k = parseAttrib(attribs, WGL_TEXTURE_TARGET_ARB, WGL_NO_TEXTURE_ARB); switch (k) { case WGL_TEXTURE_CUBE_MAP_ARB: pbInfo.texTarget = GL_TEXTURE_CUBE_MAP; break; case WGL_TEXTURE_1D_ARB: pbInfo.texTarget = GL_TEXTURE_1D; break; case WGL_TEXTURE_2D_ARB: pbInfo.texTarget = GL_TEXTURE_2D; break; case WGL_NO_TEXTURE_ARB: pbInfo.texTarget = GL_NONE; break; default: std::cerr << "error: invalid value for WGL_TEXTURE_TARGET_ARB\n"; pbInfo.texTarget = GL_NONE; } pbInfo.texMipmap = !!parseAttrib(attribs, WGL_MIPMAP_TEXTURE_ARB, 0); // WGL interface needs the HDC pbInfo.hdc_drawable = getDrawable(call.arg(0).toUInt()); glws::Drawable *drawable = glretrace::createPbuffer(iWidth, iHeight, &pbInfo); pbuffer_map[orig_pbuffer] = drawable; }
static void retrace_glXCopySubBufferMESA(trace::Call &call) { glws::Drawable *drawable = getDrawable(call.arg(1).toUInt()); int x = call.arg(2).toSInt(); int y = call.arg(3).toSInt(); int width = call.arg(4).toSInt(); int height = call.arg(5).toSInt(); drawable->copySubBuffer(x, y, width, height); }
static void retrace_memcpy(trace::Call &call) { void * dest = toPointer(call.arg(0)); void * src = toPointer(call.arg(1)); size_t n = call.arg(2).toUInt(); if (!dest || !src || !n) { return; } memcpy(dest, src, n); }
static void retrace_glXMakeCurrent(trace::Call &call) { if (call.ret && !call.ret->toBool()) { // If false was returned then any previously current rendering context // and drawable remain unchanged. return; } glws::Drawable *new_drawable = getDrawable(call.arg(1).toUInt()); Context *new_context = getContext(call.arg(2).toUIntPtr()); glretrace::makeCurrent(call, new_drawable, new_context); }
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); } }
static void retrace_wglCreatePbufferARB(trace::Call &call) { unsigned long long orig_pbuffer = call.ret->toUIntPtr(); if (!orig_pbuffer) { return; } int iWidth = call.arg(2).toUInt(); int iHeight = call.arg(3).toUInt(); glws::Drawable *drawable = glretrace::createPbuffer(iWidth, iHeight); pbuffer_map[orig_pbuffer] = drawable; }
static void retrace_wglCreateContextAttribsARB(trace::Call &call) { unsigned long long orig_context = call.ret->toUIntPtr(); if (!orig_context) { return; } Context *share_context = getContext(call.arg(1).toUIntPtr()); const trace::Value * attribList = &call.arg(2); glfeatures::Profile profile = parseContextAttribList(attribList); Context *context = glretrace::createContext(share_context, profile); context_map[orig_context] = context; }
static void retrace_wglMakeCurrent(trace::Call &call) { bool ret = call.ret->toBool(); glws::Drawable *new_drawable = NULL; Context *new_context = NULL; if (ret) { unsigned long long hglrc = call.arg(1).toUIntPtr(); if (hglrc) { new_drawable = getDrawable(call.arg(0).toUIntPtr()); new_context = getContext(hglrc); } } glretrace::makeCurrent(call, new_drawable, new_context); }
static void retrace_eglBindAPI(trace::Call &call) { if (!call.ret->toBool()) { return; } current_api = call.arg(0).toUInt(); }
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); }
static void retrace_glXCreateContextAttribsARB(Trace::Call &call) { unsigned long long orig_context = call.ret->toUIntPtr(); glws::Context *share_context = getContext(call.arg(2).toUIntPtr()); glws::Context *context = ws->createContext(glretrace::visual, share_context); context_map[orig_context] = context; }
static void retrace_wglShareLists(trace::Call &call) { bool ret = call.ret->toBool(); if (!ret) { return; } unsigned long long hglrc1 = call.arg(0).toUIntPtr(); unsigned long long hglrc2 = call.arg(1).toUIntPtr(); Context *share_context = getContext(hglrc1); Context *old_context = getContext(hglrc2); glfeatures::Profile profile = old_context->profile(); Context *new_context = glretrace::createContext(share_context, profile); if (new_context) { glretrace::Context *currentContext = glretrace::getCurrentContext(); if (currentContext == old_context) { glretrace::makeCurrent(call, currentContext->drawable, new_context); } context_map[hglrc2] = new_context; old_context->release(); } }
static void retrace_wglSetPbufferAttribARB(trace::Call &call) { glws::Drawable *pbuffer = pbuffer_map[call.arg(0).toUIntPtr()]; const trace::Value * attribList = &call.arg(1); // call the window system's setPbufferAttrib function. { int attribs[100], j = 0; const trace::Array *attribs_ = attribList ? attribList->toArray() : NULL; for (size_t i = 0; i + 1 < attribs_->values.size(); i += 2) { int param_i = attribs_->values[i]->toSInt(); if (param_i == 0) { attribs[j] = 0; } attribs[j] = param_i; attribs[j+1] = attribs_->values[i+1]->toSInt(); } glretrace::setPbufferAttrib(pbuffer, attribs); } if (!pbuffer || !attribList) return; // Update the glws::Drawable's fields const int undefined = -99999; int val; val = parseAttrib(attribList, WGL_MIPMAP_LEVEL_ARB, undefined); if (val != undefined) { pbuffer->mipmapLevel = val; } val = parseAttrib(attribList, WGL_CUBE_MAP_FACE_ARB, undefined); if (val != undefined) { // Drawable::cubeFace is integer in [0..5] val -= WGL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB; if (val < 0 || val > 5) { fprintf(stderr, "Invalid WGL_CUBE_MAP_FACE_ARB value!\n"); } else { pbuffer->cubeFace = val; } } }
static void retrace_CGLSetSurface(trace::Call &call) { if (call.ret->toUInt() != kCGLNoError) { return; } unsigned long long ctx = call.arg(0).toUIntPtr(); unsigned long long cid = call.arg(1).toUInt(); int wid = call.arg(2).toUInt(); int sid = call.arg(3).toUInt(); (void)cid; (void)wid; glws::Drawable *drawable = getDrawable(sid); context_drawable_map[ctx] = drawable; }
static void retrace_CGLClearDrawable(trace::Call &call) { if (call.ret->toUInt() != kCGLNoError) { return; } unsigned long long ctx = call.arg(0).toUIntPtr(); context_drawable_map[ctx] = NULL; }
static void retrace_glXDestroyPbuffer(trace::Call &call) { glws::Drawable *drawable = getDrawable(call.arg(1).toUInt()); if (!drawable) { return; } delete drawable; }
static void retrace_wglUseFontOutlinesAW(trace::Call &call) { bool ret = call.ret->toBool(); if (!ret) { return; } uint32_t first = call.arg(1).toUInt(); uint32_t count = call.arg(2).toUInt(); uint32_t listBase = call.arg(3).toUInt(); float extrusion = call.arg(5).toFloat(); for (uint32_t i = 0; i < count; ++i) { glNewList(listBase + i, GL_COMPILE); wglSystemFontOutlines(first + i, extrusion); glEndList(); } }
static void retrace_CGLSetSurface(trace::Call &call) { if (call.ret->toUInt() != kCGLNoError) { return; } unsigned long long ctx = call.arg(0).toUIntPtr(); unsigned long long cid = call.arg(1).toUInt(); int wid = call.arg(2).toUInt(); int sid = call.arg(3).toUInt(); (void)cid; (void)wid; Context *context = getContext(ctx); if (context) { glws::Drawable *drawable = getDrawable(sid, context->profile()); context->drawable = drawable; } }
static void retrace_CGLCreateContext(trace::Call &call) { if (call.ret->toUInt() != kCGLNoError) { return; } trace::Value & pix = call.argByName("pix"); const PixelFormat *pixelFormat = retrace::asObjPointer<PixelFormat>(call, pix); glprofile::Profile profile = pixelFormat ? pixelFormat->profile : glretrace::defaultProfile; unsigned long long share = call.arg(1).toUIntPtr(); Context *sharedContext = getContext(share); const trace::Array *ctx_ptr = call.arg(2).toArray(); assert(ctx_ptr); unsigned long long ctx = ctx_ptr->values[0]->toUIntPtr(); Context *context = glretrace::createContext(sharedContext, profile); context_map[ctx] = context; }
static void retrace_CGLSetVirtualScreen(trace::Call &call) { if (call.ret->toUInt() != kCGLNoError) { return; } GLint screen = call.arg(1).toSInt(); if (screen != 0) { retrace::warning(call) << "multiple virtual screens unsupported\n"; } }
static void retrace_wglGetPbufferDCARB(trace::Call &call) { unsigned long long orig_hdc = call.ret->toUIntPtr(); if (!orig_hdc) { return; } glws::Drawable *pbuffer = pbuffer_map[call.arg(0).toUIntPtr()]; drawable_map[orig_hdc] = pbuffer; }
static void retrace_glXDestroyContext(trace::Call &call) { ContextMap::iterator it; it = context_map.find(call.arg(1).toUIntPtr()); if (it == context_map.end()) { return; } it->second->release(); context_map.erase(it); }
static void retrace_CGLClearDrawable(trace::Call &call) { if (call.ret->toUInt() != kCGLNoError) { return; } unsigned long long ctx = call.arg(0).toUIntPtr(); Context *context = getContext(ctx); if (context) { context->drawable = NULL; } }
static void retrace_glXCreateContext(trace::Call &call) { unsigned long long orig_context = call.ret->toUIntPtr(); if (!orig_context) { return; } Context *share_context = getContext(call.arg(2).toUIntPtr()); Context *context = glretrace::createContext(share_context); context_map[orig_context] = context; }
static void retrace_eglMakeCurrent(trace::Call &call) { if (!call.ret->toSInt()) { // Previously current rendering context and surfaces (if any) remain // unchanged. return; } glws::Drawable *new_drawable = getDrawable(call.arg(1).toUIntPtr()); Context *new_context = getContext(call.arg(3).toUIntPtr()); // Try to support GL_OES_surfaceless_context by creating a dummy drawable. if (new_context && !new_drawable) { if (!null_drawable) { null_drawable = glretrace::createDrawable(last_profile); } new_drawable = null_drawable; } glretrace::makeCurrent(call, new_drawable, new_context); }
static void retrace_CGLDestroyPixelFormat(trace::Call &call) { if (call.ret->toUInt() != kCGLNoError) { return; } trace::Value & pix = call.argByName("pix"); PixelFormat *pixelFormat = retrace::asObjPointer<PixelFormat>(call, pix); delete pixelFormat; retrace::delObj(pix); }