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_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_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_eglBindAPI(trace::Call &call) { if (!call.ret->toBool()) { return; } current_api = call.arg(0).toUInt(); }
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_wglMakeContextCurrentARB(trace::Call &call) { bool ret = call.ret->toBool(); glws::Drawable *new_drawable = NULL; glws::Drawable *new_readable = NULL; Context *new_context = NULL; if (ret) { unsigned long long hglrc = call.arg(2).toUIntPtr(); if (hglrc) { new_drawable = getDrawable(call.arg(0).toUIntPtr()); new_readable = getDrawable(call.arg(1).toUIntPtr()); new_context = getContext(hglrc); } } glretrace::makeCurrent(call, new_drawable, new_readable, new_context); }
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_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_glXDestroyPbuffer(trace::Call &call) { glws::Drawable *drawable = getDrawable(call.arg(1).toUInt()); if (!drawable) { return; } delete drawable; }
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_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_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_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_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_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_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_CGLSetCurrentContext(trace::Call &call) { if (call.ret->toUInt() != kCGLNoError) { return; } unsigned long long ctx = call.arg(0).toUIntPtr(); glws::Drawable *new_drawable = getDrawableFromContext(ctx); Context *new_context = getContext(ctx); glretrace::makeCurrent(call, new_drawable, new_context); }
static void retrace_glXSwapBuffers(trace::Call &call) { glws::Drawable *drawable = getDrawable(call.arg(1).toUInt()); frame_complete(call); if (retrace::doubleBuffer) { if (drawable) { drawable->swapBuffers(); } } else { glFlush(); } }
static void retrace_eglCreateContext(trace::Call &call) { unsigned long long orig_context = call.ret->toUIntPtr(); unsigned long long orig_config = call.arg(1).toUIntPtr(); Context *share_context = getContext(call.arg(2).toUIntPtr()); trace::Array *attrib_array = call.arg(3).toArray(); glprofile::Profile profile; switch (current_api) { case EGL_OPENGL_API: profile.api = glprofile::API_GL; profile.major = parseAttrib(attrib_array, EGL_CONTEXT_MAJOR_VERSION, 1); profile.minor = parseAttrib(attrib_array, EGL_CONTEXT_MINOR_VERSION, 0); if (profile.versionGreaterOrEqual(3,2)) { int profileMask = parseAttrib(attrib_array, EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR); if (profileMask & EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR) { profile.core = true; } int contextFlags = parseAttrib(attrib_array, EGL_CONTEXT_FLAGS_KHR, 0); if (contextFlags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) { profile.forwardCompatible = true; } } break; case EGL_OPENGL_ES_API: default: profile.api = glprofile::API_GLES; profile.major = parseAttrib(attrib_array, EGL_CONTEXT_MAJOR_VERSION, 1); profile.minor = parseAttrib(attrib_array, EGL_CONTEXT_MINOR_VERSION, 0); break; } Context *context = glretrace::createContext(share_context, profile); assert(context); context_map[orig_context] = context; profile_map[orig_config] = profile; last_profile = profile; }
static void retrace_wglDeleteContext(trace::Call &call) { unsigned long long hglrc = call.arg(0).toUIntPtr(); ContextMap::iterator it; it = context_map.find(hglrc); if (it == context_map.end()) { return; } it->second->release(); context_map.erase(it); }
static void retrace_eglDestroyContext(trace::Call &call) { unsigned long long orig_context = call.arg(1).toUIntPtr(); ContextMap::iterator it; it = context_map.find(orig_context); if (it != context_map.end()) { glretrace::Context *currentContext = glretrace::getCurrentContext(); if (it->second != currentContext) { // TODO: reference count delete it->second; } context_map.erase(it); } }
static void retrace_glXCreatePbuffer(trace::Call &call) { unsigned long long orig_drawable = call.ret->toUInt(); if (!orig_drawable) { return; } const trace::Value *attrib_list = &call.arg(2); int width = glretrace::parseAttrib(attrib_list, GLX_PBUFFER_WIDTH, 0); int height = glretrace::parseAttrib(attrib_list, GLX_PBUFFER_HEIGHT, 0); glws::pbuffer_info pbInfo = {0, 0, false}; glws::Drawable *drawable = glretrace::createPbuffer(width, height, &pbInfo); drawable_map[orig_drawable] = drawable; }
static void retrace_eglDestroySurface(trace::Call &call) { unsigned long long orig_surface = call.arg(1).toUIntPtr(); DrawableMap::iterator it; it = drawable_map.find(orig_surface); if (it != drawable_map.end()) { glretrace::Context *currentContext = glretrace::getCurrentContext(); if (!currentContext || it->second != currentContext->drawable) { // TODO: reference count delete it->second; } drawable_map.erase(it); } }
static void retrace_CGLSetCurrentContext(trace::Call &call) { unsigned long long ctx = call.arg(0).toUIntPtr(); glws::Drawable *new_drawable = getDrawable(ctx); glws::Context *new_context = getContext(ctx); bool result = glws::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_malloc(trace::Call &call) { size_t size = call.arg(0).toUInt(); unsigned long long address = call.ret->toUIntPtr(); if (!address) { return; } void *buffer = malloc(size); if (!buffer) { std::cerr << "error: failed to allocate " << size << " bytes."; return; } retrace::addRegion(call, address, buffer, size); }
static void retrace_CGLDestroyContext(trace::Call &call) { if (call.ret->toUInt() != kCGLNoError) { return; } unsigned long long ctx = call.arg(0).toUIntPtr(); ContextMap::iterator it; it = context_map.find(ctx); if (it == context_map.end()) { return; } delete it->second; context_map.erase(it); }
/** * We can't fully reimplement CGLTexImageIOSurface2D, as external IOSurface are * no longer present. Simply emit a glTexImage2D to ensure the texture storage * is present. * * See also: * - /System/Library/Frameworks/OpenGL.framework/Headers/CGLIOSurface.h */ static void retrace_CGLTexImageIOSurface2D(trace::Call &call) { if (call.ret->toUInt() != kCGLNoError) { return; } if (retrace::debug) { retrace::warning(call) << "external IOSurface not supported\n"; } unsigned long long ctx = call.arg(0).toUIntPtr(); Context *context = getContext(ctx); GLenum target; target = static_cast<GLenum>((call.arg(1)).toSInt()); GLint level = 0; GLint internalformat; internalformat = static_cast<GLenum>((call.arg(2)).toSInt()); GLsizei width; width = (call.arg(3)).toSInt(); GLsizei height; height = (call.arg(4)).toSInt(); GLint border = 0; GLenum format; format = static_cast<GLenum>((call.arg(5)).toSInt()); GLenum type; type = static_cast<GLenum>((call.arg(6)).toSInt()); GLvoid * pixels = NULL; if (glretrace::getCurrentContext() != context) { if (retrace::debug) { retrace::warning(call) << "current context mismatch\n"; } } glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels); if (retrace::debug && !glretrace::insideGlBeginEnd) { glretrace::checkGlError(call); } }
static void retrace_CGLSetCurrentContext(trace::Call &call) { if (call.ret->toUInt() != kCGLNoError) { return; } unsigned long long ctx = call.arg(0).toUIntPtr(); Context *new_context = getContext(ctx); glws::Drawable *new_drawable = NULL; if (new_context) { if (!new_context->drawable) { glprofile::Profile profile = new_context->profile(); new_context->drawable = glretrace::createDrawable(profile); } new_drawable = new_context->drawable; } glretrace::makeCurrent(call, new_drawable, new_context); }