void init(void) { load("libEGL.so.1"); initX(); eglExtensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS); if (eglExtensions && checkExtension("EGL_EXT_platform_x11", eglExtensions)) { Attributes<EGLint> attribs; attribs.add(EGL_PLATFORM_X11_SCREEN_EXT, screen); attribs.add(EGL_NONE); eglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_X11_EXT, display, attribs); } else { eglDisplay = eglGetDisplay((EGLNativeDisplayType)display); } if (eglDisplay == EGL_NO_DISPLAY) { std::cerr << "error: unable to get EGL display\n"; XCloseDisplay(display); exit(1); } EGLint major, minor; if (!eglInitialize(eglDisplay, &major, &minor)) { std::cerr << "error: unable to initialize EGL display\n"; XCloseDisplay(display); exit(1); } eglExtensions = eglQueryString(eglDisplay, EGL_EXTENSIONS); has_EGL_KHR_create_context = checkExtension("EGL_KHR_create_context", eglExtensions); }
Context * createContext(const Visual *_visual, Context *shareContext, Profile profile) { const GlxVisual *visual = static_cast<const GlxVisual *>(_visual); GLXContext share_context = NULL; GLXContext context; if (profile != PROFILE_COMPAT) { return NULL; } if (shareContext) { share_context = static_cast<GlxContext*>(shareContext)->context; } if (glxVersion >= 0x0104 && has_GLX_ARB_create_context) { Attributes<int> attribs; attribs.add(GLX_RENDER_TYPE, GLX_RGBA_TYPE); if (debug) { attribs.add(GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB); } attribs.end(); context = glXCreateContextAttribsARB(display, visual->fbconfig, share_context, True, attribs); } else if (glxVersion >= 0x103) { context = glXCreateNewContext(display, visual->fbconfig, GLX_RGBA_TYPE, share_context, True); } else { context = glXCreateContext(display, visual->visinfo, share_context, True); } return new GlxContext(visual, profile, context); }
virtual Result<Attributes> slaveAttributesDecorator( const SlaveInfo& slaveInfo) { LOG(INFO) << "Executing 'slaveAttributesDecorator' hook"; Attributes attributes = slaveInfo.attributes(); attributes.add(Attributes::parse("rack", "rack1")); return attributes; }
Context * createContext(const Visual *_visual, Context *shareContext, Profile profile, bool debug) { const EglVisual *visual = static_cast<const EglVisual *>(_visual); EGLContext share_context = EGL_NO_CONTEXT; EGLContext context; Attributes<EGLint> attribs; if (shareContext) { share_context = static_cast<EglContext*>(shareContext)->context; } EGLint api = eglQueryAPI(); switch (profile) { case PROFILE_COMPAT: load("libGL.so.1"); eglBindAPI(EGL_OPENGL_API); break; case PROFILE_CORE: assert(0); return NULL; case PROFILE_ES1: load("libGLESv1_CM.so.1"); eglBindAPI(EGL_OPENGL_ES_API); break; case PROFILE_ES2: load("libGLESv2.so.2"); eglBindAPI(EGL_OPENGL_ES_API); attribs.add(EGL_CONTEXT_CLIENT_VERSION, 2); break; default: return NULL; } attribs.end(EGL_NONE); context = eglCreateContext(eglDisplay, visual->config, share_context, attribs); if (!context) return NULL; eglBindAPI(api); return new EglContext(visual, profile, context); }
Attributes Attributes::parse(const string& s) { // Tokenize and parse the value of "attributes". Attributes attributes; vector<string> tokens = strings::tokenize(s, ";\n"); for (size_t i = 0; i < tokens.size(); i++) { const vector<string>& pairs = strings::tokenize(tokens[i], ":"); if (pairs.size() != 2) { LOG(FATAL) << "Bad value for attributes, missing ':' within " << pairs[0]; } attributes.add(parse(pairs[0], pairs[1])); } return attributes; }
Visual * createVisual(bool doubleBuffer, Profile profile) { EglVisual *visual = new EglVisual(); // possible combinations const EGLint api_bits_gl[7] = { EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT, EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT, EGL_OPENGL_BIT | EGL_OPENGL_ES2_BIT, EGL_OPENGL_BIT, EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT, EGL_OPENGL_ES2_BIT, EGL_OPENGL_ES_BIT, }; const EGLint api_bits_gles1[7] = { EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT, EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT, EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT, EGL_OPENGL_ES_BIT, EGL_OPENGL_BIT | EGL_OPENGL_ES2_BIT, EGL_OPENGL_BIT, EGL_OPENGL_ES2_BIT, }; const EGLint api_bits_gles2[7] = { EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT, EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT, EGL_OPENGL_BIT | EGL_OPENGL_ES2_BIT, EGL_OPENGL_ES2_BIT, EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT, EGL_OPENGL_BIT, EGL_OPENGL_ES_BIT, }; const EGLint *api_bits; switch(profile) { case PROFILE_COMPAT: api_bits = api_bits_gl; break; case PROFILE_ES1: api_bits = api_bits_gles1; break; case PROFILE_ES2: api_bits = api_bits_gles2; break; default: return NULL; }; for (int i = 0; i < 7; i++) { Attributes<EGLint> attribs; attribs.add(EGL_SURFACE_TYPE, EGL_WINDOW_BIT); attribs.add(EGL_RED_SIZE, 1); attribs.add(EGL_GREEN_SIZE, 1); attribs.add(EGL_BLUE_SIZE, 1); attribs.add(EGL_ALPHA_SIZE, 1); attribs.add(EGL_DEPTH_SIZE, 1); attribs.add(EGL_STENCIL_SIZE, 1); attribs.add(EGL_RENDERABLE_TYPE, api_bits[i]); attribs.end(EGL_NONE); EGLint num_configs, vid; if (eglChooseConfig(eglDisplay, attribs, &visual->config, 1, &num_configs) && num_configs == 1 && eglGetConfigAttrib(eglDisplay, visual->config, EGL_NATIVE_VISUAL_ID, &vid)) { XVisualInfo templ; int num_visuals; templ.visualid = vid; visual->visinfo = XGetVisualInfo(display, VisualIDMask, &templ, &num_visuals); break; } } assert(visual->visinfo); return visual; }
Window GlxDrawable::createPbuffer(Display *dpy, const GlxVisual *visinfo, const glws::pbuffer_info *pbInfo, int w, int h) { int samples = 0; // XXX ideally, we'd populate these attributes according to the Visual info Attributes<int> attribs; attribs.add(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT); attribs.add(GLX_RENDER_TYPE, GLX_RGBA_BIT); attribs.add(GLX_RED_SIZE, 1); attribs.add(GLX_GREEN_SIZE, 1); attribs.add(GLX_BLUE_SIZE, 1); attribs.add(GLX_ALPHA_SIZE, 1); //attribs.add(GLX_DOUBLEBUFFER, doubleBuffer ? GL_TRUE : GL_FALSE); attribs.add(GLX_DEPTH_SIZE, 1); attribs.add(GLX_STENCIL_SIZE, 1); if (samples > 1) { attribs.add(GLX_SAMPLE_BUFFERS, 1); attribs.add(GLX_SAMPLES_ARB, samples); } attribs.end(); int num_configs = 0; GLXFBConfig *fbconfigs; fbconfigs = glXChooseFBConfig(dpy, screen, attribs, &num_configs); if (!num_configs || !fbconfigs) { std::cerr << "error: glXChooseFBConfig for pbuffer failed.\n"; exit(1); } Attributes<int> pbAttribs; pbAttribs.add(GLX_PBUFFER_WIDTH, w); pbAttribs.add(GLX_PBUFFER_HEIGHT, h); pbAttribs.add(GLX_PRESERVED_CONTENTS, True); pbAttribs.end(); GLXDrawable pbuffer = glXCreatePbuffer(dpy, fbconfigs[0], pbAttribs); if (!pbuffer) { std::cerr << "error: glXCreatePbuffer() failed\n"; exit(1); } return pbuffer; }
Context * createContext(const Visual *_visual, Context *shareContext, bool debug) { const GlxVisual *visual = static_cast<const GlxVisual *>(_visual); Profile profile = visual->profile; GLXContext share_context = NULL; GLXContext context; if (shareContext) { share_context = static_cast<GlxContext*>(shareContext)->context; } if (has_GLX_ARB_create_context) { Attributes<int> attribs; attribs.add(GLX_RENDER_TYPE, GLX_RGBA_TYPE); int contextFlags = 0; if (profile.api == glfeatures::API_GL) { attribs.add(GLX_CONTEXT_MAJOR_VERSION_ARB, profile.major); attribs.add(GLX_CONTEXT_MINOR_VERSION_ARB, profile.minor); if (profile.versionGreaterOrEqual(3, 2)) { if (!has_GLX_ARB_create_context_profile) { std::cerr << "error: GLX_ARB_create_context_profile not supported\n"; return NULL; } int profileMask = profile.core ? GLX_CONTEXT_CORE_PROFILE_BIT_ARB : GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; attribs.add(GLX_CONTEXT_PROFILE_MASK_ARB, profileMask); if (profile.forwardCompatible) { contextFlags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; } } } else if (profile.api == glfeatures::API_GLES) { if (has_GLX_EXT_create_context_es_profile) { attribs.add(GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES_PROFILE_BIT_EXT); attribs.add(GLX_CONTEXT_MAJOR_VERSION_ARB, profile.major); attribs.add(GLX_CONTEXT_MINOR_VERSION_ARB, profile.minor); } else if (profile.major < 2) { std::cerr << "error: " << profile << " requested but GLX_EXT_create_context_es_profile not supported\n"; return NULL; } else if (has_GLX_EXT_create_context_es2_profile) { assert(profile.major >= 2); if (profile.major != 2 || profile.minor != 0) { // We might still get a ES 3.0 context later (in particular Mesa does this) std::cerr << "warning: " << profile << " requested but GLX_EXT_create_context_es_profile not supported\n"; } attribs.add(GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES2_PROFILE_BIT_EXT); attribs.add(GLX_CONTEXT_MAJOR_VERSION_ARB, 2); attribs.add(GLX_CONTEXT_MINOR_VERSION_ARB, 0); } else { std::cerr << "warning: " << profile << " requested but GLX_EXT_create_context_es_profile or GLX_EXT_create_context_es2_profile not supported\n"; } } else { assert(0); } if (debug) { contextFlags |= GLX_CONTEXT_DEBUG_BIT_ARB; } if (contextFlags) { attribs.add(GLX_CONTEXT_FLAGS_ARB, contextFlags); } attribs.end(); context = glXCreateContextAttribsARB(display, visual->fbconfig, share_context, True, attribs); if (!context && debug) { // XXX: Mesa has problems with GLX_CONTEXT_DEBUG_BIT_ARB with // OpenGL ES contexts, so retry without it return createContext(_visual, shareContext, false); } } else { if (profile.api != glfeatures::API_GL || profile.core) { return NULL; } context = glXCreateNewContext(display, visual->fbconfig, GLX_RGBA_TYPE, share_context, True); } if (!context) { return NULL; } return new GlxContext(visual, context); }
Visual * createVisual(bool doubleBuffer, unsigned samples, Profile profile) { GlxVisual *visual = new GlxVisual(profile); Attributes<int> attribs; attribs.add(GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT); attribs.add(GLX_RENDER_TYPE, GLX_RGBA_BIT); attribs.add(GLX_RED_SIZE, 1); attribs.add(GLX_GREEN_SIZE, 1); attribs.add(GLX_BLUE_SIZE, 1); attribs.add(GLX_ALPHA_SIZE, 1); attribs.add(GLX_DOUBLEBUFFER, doubleBuffer ? GL_TRUE : GL_FALSE); attribs.add(GLX_DEPTH_SIZE, 1); attribs.add(GLX_STENCIL_SIZE, 1); if (samples > 1) { attribs.add(GLX_SAMPLE_BUFFERS, 1); attribs.add(GLX_SAMPLES_ARB, samples); } attribs.end(); int num_configs = 0; GLXFBConfig * fbconfigs; fbconfigs = glXChooseFBConfig(display, screen, attribs, &num_configs); if (!num_configs || !fbconfigs) { return NULL; } visual->fbconfig = fbconfigs[0]; assert(visual->fbconfig); visual->visinfo = glXGetVisualFromFBConfig(display, visual->fbconfig); assert(visual->visinfo); return visual; }
Visual * createVisual(bool doubleBuffer) { GlxVisual *visual = new GlxVisual; if (glxVersion >= 0x0103) { Attributes<int> attribs; attribs.add(GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT); attribs.add(GLX_RENDER_TYPE, GLX_RGBA_BIT); attribs.add(GLX_RED_SIZE, 1); attribs.add(GLX_GREEN_SIZE, 1); attribs.add(GLX_BLUE_SIZE, 1); attribs.add(GLX_ALPHA_SIZE, 1); attribs.add(GLX_DOUBLEBUFFER, doubleBuffer ? GL_TRUE : GL_FALSE); attribs.add(GLX_DEPTH_SIZE, 1); attribs.add(GLX_STENCIL_SIZE, 1); attribs.end(); int num_configs = 0; GLXFBConfig * fbconfigs; fbconfigs = glXChooseFBConfig(display, screen, attribs, &num_configs); assert(num_configs && fbconfigs); visual->fbconfig = fbconfigs[0]; assert(visual->fbconfig); visual->visinfo = glXGetVisualFromFBConfig(display, visual->fbconfig); assert(visual->visinfo); } else { Attributes<int> attribs; attribs.add(GLX_RGBA); attribs.add(GLX_RED_SIZE, 1); attribs.add(GLX_GREEN_SIZE, 1); attribs.add(GLX_BLUE_SIZE, 1); attribs.add(GLX_ALPHA_SIZE, 1); if (doubleBuffer) { attribs.add(GLX_DOUBLEBUFFER); } attribs.add(GLX_DEPTH_SIZE, 1); attribs.add(GLX_STENCIL_SIZE, 1); attribs.end(); visual->visinfo = glXChooseVisual(display, screen, attribs); } return visual; }
Context * createContext(const Visual *_visual, Context *shareContext, bool debug) { Profile profile = _visual->profile; const EglVisual *visual = static_cast<const EglVisual *>(_visual); EGLContext share_context = EGL_NO_CONTEXT; EGLContext context; Attributes<EGLint> attribs; if (shareContext) { share_context = static_cast<EglContext*>(shareContext)->context; } int contextFlags = 0; if (profile.api == glprofile::API_GL) { if (has_EGL_KHR_create_context) { attribs.add(EGL_CONTEXT_MAJOR_VERSION_KHR, profile.major); attribs.add(EGL_CONTEXT_MINOR_VERSION_KHR, profile.minor); int profileMask = profile.core ? EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR : EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; attribs.add(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, profileMask); if (profile.forwardCompatible) { contextFlags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; } } else if (profile.versionGreaterOrEqual(3, 2)) { std::cerr << "error: EGL_KHR_create_context not supported\n"; return NULL; } } else if (profile.api == glprofile::API_GLES) { if (has_EGL_KHR_create_context) { attribs.add(EGL_CONTEXT_MAJOR_VERSION_KHR, profile.major); attribs.add(EGL_CONTEXT_MINOR_VERSION_KHR, profile.minor); } else { attribs.add(EGL_CONTEXT_CLIENT_VERSION, profile.major); } } else { assert(0); return NULL; } if (debug) { contextFlags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR; } if (contextFlags && has_EGL_KHR_create_context) { attribs.add(EGL_CONTEXT_FLAGS_KHR, contextFlags); } attribs.end(EGL_NONE); EGLenum api = translateAPI(profile); bindAPI(api); context = eglCreateContext(eglDisplay, visual->config, share_context, attribs); if (!context) { if (debug) { // XXX: Mesa has problems with EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR // with OpenGL ES contexts, so retry without it return createContext(_visual, shareContext, false); } return NULL; } return new EglContext(visual, context); }
Visual * createVisual(bool doubleBuffer, unsigned samples, Profile profile) { EGLint api_bits; if (profile.api == glprofile::API_GL) { api_bits = EGL_OPENGL_BIT; if (profile.core && !has_EGL_KHR_create_context) { return NULL; } } else if (profile.api == glprofile::API_GLES) { switch (profile.major) { case 1: api_bits = EGL_OPENGL_ES_BIT; break; case 3: if (has_EGL_KHR_create_context) { api_bits = EGL_OPENGL_ES3_BIT; break; } /* fall-through */ case 2: api_bits = EGL_OPENGL_ES2_BIT; break; default: return NULL; } } else { assert(0); return NULL; } Attributes<EGLint> attribs; attribs.add(EGL_SURFACE_TYPE, EGL_WINDOW_BIT); attribs.add(EGL_RED_SIZE, 1); attribs.add(EGL_GREEN_SIZE, 1); attribs.add(EGL_BLUE_SIZE, 1); attribs.add(EGL_ALPHA_SIZE, 1); attribs.add(EGL_DEPTH_SIZE, 1); attribs.add(EGL_STENCIL_SIZE, 1); attribs.add(EGL_RENDERABLE_TYPE, api_bits); attribs.end(EGL_NONE); EGLint num_configs = 0; if (!eglGetConfigs(eglDisplay, NULL, 0, &num_configs) || num_configs <= 0) { return NULL; } std::vector<EGLConfig> configs(num_configs); if (!eglChooseConfig(eglDisplay, attribs, &configs[0], num_configs, &num_configs) || num_configs <= 0) { return NULL; } // We can't tell what other APIs the trace will use afterwards, therefore // try to pick a config which supports the widest set of APIs. int bestScore = -1; EGLConfig config = configs[0]; for (EGLint i = 0; i < num_configs; ++i) { EGLint renderable_type = EGL_NONE; eglGetConfigAttrib(eglDisplay, configs[i], EGL_RENDERABLE_TYPE, &renderable_type); int score = 0; assert(renderable_type & api_bits); renderable_type &= ~api_bits; if (renderable_type & EGL_OPENGL_ES2_BIT) { score += 1 << 4; } if (renderable_type & EGL_OPENGL_ES3_BIT) { score += 1 << 3; } if (renderable_type & EGL_OPENGL_ES_BIT) { score += 1 << 2; } if (renderable_type & EGL_OPENGL_BIT) { score += 1 << 1; } if (score > bestScore) { config = configs[i]; bestScore = score; } } assert(bestScore >= 0); EGLint visual_id = -1; if (!eglGetConfigAttrib(eglDisplay, config, EGL_NATIVE_VISUAL_ID, &visual_id)) { assert(0); return NULL; } assert(visual_id != -1); EglVisual *visual = new EglVisual(profile); visual->config = config; visual->format = visual_id; return visual; }
Context * createContext(const Visual *_visual, Context *shareContext, bool debug) { const GlxVisual *visual = static_cast<const GlxVisual *>(_visual); Profile profile = visual->profile; GLXContext share_context = NULL; GLXContext context; if (shareContext) { share_context = static_cast<GlxContext*>(shareContext)->context; } if (glxVersion >= 0x0104 && has_GLX_ARB_create_context) { Attributes<int> attribs; attribs.add(GLX_RENDER_TYPE, GLX_RGBA_TYPE); if (debug) { attribs.add(GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB); } ProfileDesc desc; getProfileDesc(profile, desc); switch (profile) { case PROFILE_COMPAT: break; case PROFILE_ES1: if (!has_GLX_EXT_create_context_es_profile) { return NULL; } attribs.add(GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES_PROFILE_BIT_EXT); attribs.add(GLX_CONTEXT_MAJOR_VERSION_ARB, 1); break; case PROFILE_ES2: if (!has_GLX_EXT_create_context_es_profile && !has_GLX_EXT_create_context_es2_profile) { return NULL; } attribs.add(GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES_PROFILE_BIT_EXT); attribs.add(GLX_CONTEXT_MAJOR_VERSION_ARB, 2); break; default: { attribs.add(GLX_CONTEXT_MAJOR_VERSION_ARB, desc.major); attribs.add(GLX_CONTEXT_MINOR_VERSION_ARB, desc.minor); if (desc.versionGreaterOrEqual(3, 2)) { if (!has_GLX_ARB_create_context_profile) { return NULL; } int profileMask = desc.core ? GLX_CONTEXT_CORE_PROFILE_BIT_ARB : GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; attribs.add(GLX_CONTEXT_PROFILE_MASK_ARB, profileMask); } break; } } attribs.end(); context = glXCreateContextAttribsARB(display, visual->fbconfig, share_context, True, attribs); if (!context && debug) { // XXX: Mesa has problems with GLX_CONTEXT_DEBUG_BIT_ARB with // OpenGL ES contexts, so retry without it return createContext(_visual, shareContext, false); } } else { if (profile != PROFILE_COMPAT) { return NULL; } if (glxVersion >= 0x103) { context = glXCreateNewContext(display, visual->fbconfig, GLX_RGBA_TYPE, share_context, True); } else { context = glXCreateContext(display, visual->visinfo, share_context, True); } } if (!context) { return NULL; } return new GlxContext(visual, context); }
bool createARB(HDC hDC) { bool required = profile.api != glfeatures::API_GL || profile.versionGreaterOrEqual(3, 1); // We need to create context through WGL_ARB_create_context. This // implies binding a temporary context to get the extensions strings // and function pointers. // This function is only called inside makeCurrent, so we don't need // to save and restore the previous current context/drawable. BOOL bRet = wglMakeCurrent(hDC, hglrc); if (!bRet) { std::cerr << "error: wglMakeCurrent failed\n"; exit(1); } pfnWglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) wglGetProcAddress("wglGetExtensionsStringARB"); if (!pfnWglGetExtensionsStringARB) { if (required) { std::cerr << "error: WGL_ARB_extensions_string not supported\n"; exit(1); } else { return false; } } const char * extensionsString = pfnWglGetExtensionsStringARB(hDC); assert(extensionsString); if (checkExtension("WGL_ARB_pbuffer", extensionsString)) { has_WGL_ARB_pbuffer = true; WGL_PROC(PFNWGLCREATEPBUFFERARBPROC, pfnWglCreatePbufferARB, "wglCreatePbufferARB"); WGL_PROC(PFNWGLGETPBUFFERDCARBPROC, pfnWglGetPbufferDCARB, "wglGetPbufferDCARB"); WGL_PROC(PFNWGLCHOOSEPIXELFORMATARBPROC, pfnWglChoosePixelFormatARB, "wglChoosePixelFormatARB"); WGL_PROC(PFNWGLDESTROYPBUFFERARBPROC, pfnWglDestroyPbufferARB, "wglDestroyPbufferARB"); WGL_PROC(PFNWGLRELEASEPBUFFERDCARBPROC, pfnWglReleasePbufferDCARB, "wglReleasePbufferDCARB"); } if (checkExtension("WGL_ARB_render_texture", extensionsString)) { assert(has_WGL_ARB_pbuffer); has_WGL_ARB_render_texture = true; WGL_PROC(PFNWGLBINDTEXIMAGEARBPROC, pfnWglBindTexImageARB, "wglBindTexImageARB"); WGL_PROC(PFNWGLRELEASETEXIMAGEARBPROC, pfnWglReleaseTexImageARB, "wglReleaseTexImageARB"); WGL_PROC(PFNWGLSETPBUFFERATTRIBARBPROC, pfnWglSetPbufferAttribARB, "wglSetPbufferAttribARB"); } if (!checkExtension("WGL_ARB_create_context", extensionsString)) { if (required) { std::cerr << "error: WGL_ARB_create_context not supported\n"; exit(1); } else { return false; } } PFNWGLCREATECONTEXTATTRIBSARBPROC pfnWglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress("wglCreateContextAttribsARB"); if (!pfnWglCreateContextAttribsARB) { if (required) { std::cerr << "error: failed to get pointer to wglCreateContextAttribsARB\n"; exit(1); } else { return false; } } wglMakeCurrent(hDC, NULL); Attributes<int> attribs; int contextFlags = 0; if (profile.api == glfeatures::API_GL) { attribs.add(WGL_CONTEXT_MAJOR_VERSION_ARB, profile.major); attribs.add(WGL_CONTEXT_MINOR_VERSION_ARB, profile.minor); if (profile.versionGreaterOrEqual(3, 2)) { if (!checkExtension("WGL_ARB_create_context_profile", extensionsString)) { assert(required); std::cerr << "error: WGL_ARB_create_context_profile not supported\n"; exit(1); } int profileMask = profile.core ? WGL_CONTEXT_CORE_PROFILE_BIT_ARB : WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; attribs.add(WGL_CONTEXT_PROFILE_MASK_ARB, profileMask); if (profile.forwardCompatible) { contextFlags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; } } } else if (profile.api == glfeatures::API_GLES) { if (checkExtension("WGL_EXT_create_context_es_profile", extensionsString)) { attribs.add(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_ES_PROFILE_BIT_EXT); attribs.add(WGL_CONTEXT_MAJOR_VERSION_ARB, profile.major); attribs.add(WGL_CONTEXT_MINOR_VERSION_ARB, profile.minor); } else if (profile.major != 2) { std::cerr << "warning: OpenGL ES " << profile.major << " requested but WGL_EXT_create_context_es_profile not supported\n"; } else if (checkExtension("WGL_EXT_create_context_es2_profile", extensionsString)) { assert(profile.major == 2); attribs.add(WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_ES2_PROFILE_BIT_EXT); attribs.add(WGL_CONTEXT_MAJOR_VERSION_ARB, profile.major); attribs.add(WGL_CONTEXT_MINOR_VERSION_ARB, profile.minor); } else { std::cerr << "warning: OpenGL ES " << profile.major << " requested but WGL_EXT_create_context_es_profile or WGL_EXT_create_context_es2_profile not supported\n"; } } else { assert(0); } if (debug) { contextFlags |= WGL_CONTEXT_DEBUG_BIT_ARB; } if (contextFlags) { attribs.add(WGL_CONTEXT_FLAGS_ARB, contextFlags); } attribs.end(); HGLRC new_hglrc; new_hglrc = pfnWglCreateContextAttribsARB(hDC, shareContext ? shareContext->hglrc : 0, attribs); if (!new_hglrc) { if (required) { std::cerr << "error: wglCreateContextAttribsARB failed\n"; exit(1); } else { return false; } } wglDeleteContext(hglrc); hglrc = new_hglrc; return true; }
Context * createContext(const Visual *_visual, Context *shareContext, bool debug) { const GlxVisual *visual = static_cast<const GlxVisual *>(_visual); Profile profile = visual->profile; GLXContext share_context = NULL; GLXContext context; if (shareContext) { share_context = static_cast<GlxContext*>(shareContext)->context; } if (glxVersion >= 0x0104 && has_GLX_ARB_create_context) { Attributes<int> attribs; attribs.add(GLX_RENDER_TYPE, GLX_RGBA_TYPE); if (debug) { attribs.add(GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_DEBUG_BIT_ARB); } switch (profile) { case PROFILE_COMPAT: break; case PROFILE_ES1: return NULL; case PROFILE_ES2: attribs.add(GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_ES2_PROFILE_BIT_EXT); break; default: { unsigned major, minor; bool core; getProfileVersion(profile, major, minor, core); attribs.add(GLX_CONTEXT_MAJOR_VERSION_ARB, major); attribs.add(GLX_CONTEXT_MINOR_VERSION_ARB, minor); if (core) { attribs.add(GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB); } break; } } attribs.end(); context = glXCreateContextAttribsARB(display, visual->fbconfig, share_context, True, attribs); } else { if (profile != PROFILE_COMPAT) { return NULL; } if (glxVersion >= 0x103) { context = glXCreateNewContext(display, visual->fbconfig, GLX_RGBA_TYPE, share_context, True); } else { context = glXCreateContext(display, visual->visinfo, share_context, True); } } if (!context) { return NULL; } return new GlxContext(visual, context); }
bool glws::WglDrawable::createPbuffer(const Visual *vis, const glws::pbuffer_info *pbInfo, int width, int height) { if (!has_WGL_ARB_pbuffer) { std::cerr << "error: WGL_ARB_pbuffer extension is unsupported\n"; exit(1); return false; } // choose pixel format Attributes<int> attribs; attribs.add(WGL_DRAW_TO_PBUFFER_ARB, true); attribs.add(WGL_DEPTH_BITS_ARB, 24); attribs.add(WGL_STENCIL_BITS_ARB, 8); attribs.add(WGL_RED_BITS_ARB, 8); attribs.add(WGL_GREEN_BITS_ARB, 8); attribs.add(WGL_BLUE_BITS_ARB, 8); attribs.add(WGL_ALPHA_BITS_ARB, 8); attribs.add(WGL_COLOR_BITS_ARB, 32); if (pbInfo->texFormat) { if (pbInfo->texFormat == GL_RGBA) attribs.add(WGL_BIND_TO_TEXTURE_RGBA_ARB, true); else if (pbInfo->texFormat == GL_RGB) attribs.add(WGL_BIND_TO_TEXTURE_RGB_ARB, true); else { std::cerr << "error: unexpected texture format.\n"; exit(1); } } attribs.end(); int pixelFormats[20]; UINT numPixelFormats; WglDrawable *wgl_draw = static_cast<WglDrawable *>(pbInfo->hdc_drawable); HDC hdc = wgl_draw->hDC; assert(hdc); if (!pfnWglChoosePixelFormatARB(hdc, attribs, NULL, 20, pixelFormats, &numPixelFormats)) { std::cerr << "error: wglChoosePixelFormatARB failed.\n"; exit(1); } // create pbuffer Attributes<int> pbAttribs; if (pbInfo->texFormat) { if (pbInfo->texFormat == GL_RGBA) { pbAttribs.add(WGL_TEXTURE_FORMAT_ARB, WGL_TEXTURE_RGBA_ARB); } else if (pbInfo->texFormat == GL_RGB) { pbAttribs.add(WGL_TEXTURE_FORMAT_ARB, WGL_TEXTURE_RGB_ARB); } else { std::cerr << "error: unexpected texture format.\n"; exit(1); } } if (pbInfo->texTarget) { if (pbInfo->texTarget == GL_TEXTURE_1D) { pbAttribs.add(WGL_TEXTURE_TARGET_ARB, WGL_TEXTURE_1D_ARB); } else if (pbInfo->texTarget == GL_TEXTURE_2D) { pbAttribs.add(WGL_TEXTURE_TARGET_ARB, WGL_TEXTURE_2D_ARB); } else if (pbInfo->texTarget == GL_TEXTURE_CUBE_MAP) { pbAttribs.add(WGL_TEXTURE_TARGET_ARB, WGL_TEXTURE_CUBE_MAP_ARB); } else { std::cerr << "error: unexpected texture targett.\n"; exit(1); } } if (pbInfo->texMipmap) { pbAttribs.add(WGL_MIPMAP_TEXTURE_ARB, pbInfo->texMipmap); } pbAttribs.end(); hPBuffer = pfnWglCreatePbufferARB(hdc, pixelFormats[0], width, height, pbAttribs); if (!hPBuffer) { std::cerr << "error: wglCreatePbufferARB failed (format " << pixelFormats[0] << ")\n"; DWORD er = GetLastError(); std::cerr << "error code " << er << "\n"; exit(1); } hDC = pfnWglGetPbufferDCARB(hPBuffer); if (!hDC) { std::cerr << "error: wglGetPbufferDCARB failed\n"; exit(1); } return true; }
void ModuleSummaryIndex::exportToDot(raw_ostream& OS) const { std::vector<Edge> CrossModuleEdges; DenseMap<GlobalValue::GUID, std::vector<uint64_t>> NodeMap; StringMap<GVSummaryMapTy> ModuleToDefinedGVS; collectDefinedGVSummariesPerModule(ModuleToDefinedGVS); // Get node identifier in form MXXX_<GUID>. The MXXX prefix is required, // because we may have multiple linkonce functions summaries. auto NodeId = [](uint64_t ModId, GlobalValue::GUID Id) { return ModId == (uint64_t)-1 ? std::to_string(Id) : std::string("M") + std::to_string(ModId) + "_" + std::to_string(Id); }; auto DrawEdge = [&](const char *Pfx, int SrcMod, GlobalValue::GUID SrcId, int DstMod, GlobalValue::GUID DstId, int TypeOrHotness) { // 0 corresponds to alias edge, 1 to ref edge, 2 to call with unknown // hotness, ... TypeOrHotness += 2; static const char *EdgeAttrs[] = { " [style=dotted]; // alias", " [style=dashed]; // ref", " // call (hotness : Unknown)", " [color=blue]; // call (hotness : Cold)", " // call (hotness : None)", " [color=brown]; // call (hotness : Hot)", " [style=bold,color=red]; // call (hotness : Critical)"}; assert(static_cast<size_t>(TypeOrHotness) < sizeof(EdgeAttrs) / sizeof(EdgeAttrs[0])); OS << Pfx << NodeId(SrcMod, SrcId) << " -> " << NodeId(DstMod, DstId) << EdgeAttrs[TypeOrHotness] << "\n"; }; OS << "digraph Summary {\n"; for (auto &ModIt : ModuleToDefinedGVS) { auto ModId = getModuleId(ModIt.first()); OS << " // Module: " << ModIt.first() << "\n"; OS << " subgraph cluster_" << std::to_string(ModId) << " {\n"; OS << " style = filled;\n"; OS << " color = lightgrey;\n"; OS << " label = \"" << sys::path::filename(ModIt.first()) << "\";\n"; OS << " node [style=filled,fillcolor=lightblue];\n"; auto &GVSMap = ModIt.second; auto Draw = [&](GlobalValue::GUID IdFrom, GlobalValue::GUID IdTo, int Hotness) { if (!GVSMap.count(IdTo)) { CrossModuleEdges.push_back({ModId, Hotness, IdFrom, IdTo}); return; } DrawEdge(" ", ModId, IdFrom, ModId, IdTo, Hotness); }; for (auto &SummaryIt : GVSMap) { NodeMap[SummaryIt.first].push_back(ModId); auto Flags = SummaryIt.second->flags(); Attributes A; if (isa<FunctionSummary>(SummaryIt.second)) { A.add("shape", "record", "function"); } else if (isa<AliasSummary>(SummaryIt.second)) { A.add("style", "dotted,filled", "alias"); A.add("shape", "box"); } else { A.add("shape", "Mrecord", "variable"); } auto VI = getValueInfo(SummaryIt.first); A.add("label", getNodeLabel(VI, SummaryIt.second)); if (!Flags.Live) A.add("fillcolor", "red", "dead"); else if (Flags.NotEligibleToImport) A.add("fillcolor", "yellow", "not eligible to import"); OS << " " << NodeId(ModId, SummaryIt.first) << " " << A.getAsString() << "\n"; } OS << " // Edges:\n"; for (auto &SummaryIt : GVSMap) { auto *GVS = SummaryIt.second; for (auto &R : GVS->refs()) Draw(SummaryIt.first, R.getGUID(), -1); if (auto *AS = dyn_cast_or_null<AliasSummary>(SummaryIt.second)) { auto AliaseeOrigId = AS->getAliasee().getOriginalName(); auto AliaseeId = getGUIDFromOriginalID(AliaseeOrigId); Draw(SummaryIt.first, AliaseeId ? AliaseeId : AliaseeOrigId, -2); continue; } if (auto *FS = dyn_cast_or_null<FunctionSummary>(SummaryIt.second)) for (auto &CGEdge : FS->calls()) Draw(SummaryIt.first, CGEdge.first.getGUID(), static_cast<int>(CGEdge.second.Hotness)); } OS << " }\n"; } OS << " // Cross-module edges:\n"; for (auto &E : CrossModuleEdges) { auto &ModList = NodeMap[E.Dst]; if (ModList.empty()) { defineExternalNode(OS, " ", getValueInfo(E.Dst)); // Add fake module to the list to draw an edge to an external node // in the loop below. ModList.push_back(-1); } for (auto DstMod : ModList) // The edge representing call or ref is drawn to every module where target // symbol is defined. When target is a linkonce symbol there can be // multiple edges representing a single call or ref, both intra-module and // cross-module. As we've already drawn all intra-module edges before we // skip it here. if (DstMod != E.SrcMod) DrawEdge(" ", E.SrcMod, E.Src, DstMod, E.Dst, E.Hotness); } OS << "}"; }