static already_AddRefed<GLContextGLX> CreateOffscreenPixmapContext(CreateContextFlags flags, const IntSize& size, const SurfaceCaps& minCaps, nsACString* const out_failureId, ContextProfile profile = ContextProfile::OpenGLCompatibility) { GLXLibrary* glx = &sGLXLibrary; if (!glx->EnsureInitialized()) return nullptr; Display* display = DefaultXDisplay(); int screen = DefaultScreen(display); ScopedXFree<GLXFBConfig> scopedConfigArr; GLXFBConfig config; int visid; if (!ChooseConfig(glx, display, screen, minCaps, &scopedConfigArr, &config, &visid)) { NS_WARNING("Failed to find a compatible config."); return nullptr; } Visual* visual; int depth; FindVisualAndDepth(display, visid, &visual, &depth); ScopedXErrorHandler xErrorHandler; bool error = false; // Must be declared before goto: Drawable drawable; GLXPixmap pixmap; gfx::IntSize dummySize(16, 16); RefPtr<gfxXlibSurface> surface = gfxXlibSurface::Create(DefaultScreenOfDisplay(display), visual, dummySize); if (surface->CairoStatus() != 0) { error = true; goto DONE_CREATING_PIXMAP; } // Handle slightly different signature between glXCreatePixmap and // its pre-GLX-1.3 extension equivalent (though given the ABI, we // might not need to). drawable = surface->XDrawable(); if (glx->GLXVersionCheck(1, 3)) { pixmap = glx->xCreatePixmap(display, config, drawable, nullptr); } else { pixmap = glx->xCreateGLXPixmapWithConfig(display, config, drawable); } if (pixmap == 0) { error = true; } DONE_CREATING_PIXMAP: bool serverError = xErrorHandler.SyncAndGetError(display); if (error || serverError) return nullptr; GLContextGLX* shareContext = GetGlobalContextGLX(); return GLContextGLX::CreateGLContext(flags, minCaps, shareContext, true, display, pixmap, config, true, surface, profile); }
already_AddRefed<GLContext> GLContextProviderGLX::CreateForWindow(nsIWidget *aWidget) { if (!sGLXLibrary.EnsureInitialized()) { return nullptr; } // Currently, we take whatever Visual the window already has, and // try to create an fbconfig for that visual. This isn't // necessarily what we want in the long run; an fbconfig may not // be available for the existing visual, or if it is, the GL // performance might be suboptimal. But using the existing visual // is a relatively safe intermediate step. Display *display = (Display*)aWidget->GetNativeData(NS_NATIVE_DISPLAY); if (!display) { NS_ERROR("X Display required for GLX Context provider"); return nullptr; } int xscreen = DefaultScreen(display); Window window = GET_NATIVE_WINDOW(aWidget); int numConfigs; ScopedXFree<GLXFBConfig> cfgs; if (sGLXLibrary.IsATI() || !sGLXLibrary.GLXVersionCheck(1, 3)) { const int attribs[] = { LOCAL_GLX_DOUBLEBUFFER, False, 0 }; cfgs = sGLXLibrary.xChooseFBConfig(display, xscreen, attribs, &numConfigs); } else { cfgs = sGLXLibrary.xGetFBConfigs(display, xscreen, &numConfigs); } if (!cfgs) { NS_WARNING("[GLX] glXGetFBConfigs() failed"); return nullptr; } NS_ASSERTION(numConfigs > 0, "No FBConfigs found!"); // XXX the visual ID is almost certainly the LOCAL_GLX_FBCONFIG_ID, so // we could probably do this first and replace the glXGetFBConfigs // with glXChooseConfigs. Docs are sparklingly clear as always. XWindowAttributes widgetAttrs; if (!XGetWindowAttributes(display, window, &widgetAttrs)) { NS_WARNING("[GLX] XGetWindowAttributes() failed"); return nullptr; } const VisualID widgetVisualID = XVisualIDFromVisual(widgetAttrs.visual); #ifdef DEBUG printf("[GLX] widget has VisualID 0x%lx\n", widgetVisualID); #endif int matchIndex = -1; for (int i = 0; i < numConfigs; i++) { int visid = None; sGLXLibrary.xGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID, &visid); if (!visid) { continue; } if (sGLXLibrary.IsATI()) { int depth; Visual *visual; FindVisualAndDepth(display, visid, &visual, &depth); if (depth == widgetAttrs.depth && AreCompatibleVisuals(widgetAttrs.visual, visual)) { matchIndex = i; break; } } else { if (widgetVisualID == static_cast<VisualID>(visid)) { matchIndex = i; break; } } } if (matchIndex == -1) { NS_WARNING("[GLX] Couldn't find a FBConfig matching widget visual"); return nullptr; } GLContextGLX *shareContext = GetGlobalContextGLX(); SurfaceCaps caps = SurfaceCaps::Any(); nsRefPtr<GLContextGLX> glContext = GLContextGLX::CreateGLContext(caps, shareContext, false, display, window, cfgs[matchIndex], false); return glContext.forget(); }
bool GLContextGLX::FindFBConfigForWindow(Display* display, int screen, Window window, ScopedXFree<GLXFBConfig>* const out_scopedConfigArr, GLXFBConfig* const out_config, int* const out_visid) { ScopedXFree<GLXFBConfig>& cfgs = *out_scopedConfigArr; int numConfigs; if (sGLXLibrary.IsATI() || !sGLXLibrary.GLXVersionCheck(1, 3)) { const int attribs[] = { LOCAL_GLX_DOUBLEBUFFER, False, 0 }; cfgs = sGLXLibrary.xChooseFBConfig(display, screen, attribs, &numConfigs); } else { cfgs = sGLXLibrary.xGetFBConfigs(display, screen, &numConfigs); } if (!cfgs) { NS_WARNING("[GLX] glXGetFBConfigs() failed"); return false; } NS_ASSERTION(numConfigs > 0, "No FBConfigs found!"); // XXX the visual ID is almost certainly the LOCAL_GLX_FBCONFIG_ID, so // we could probably do this first and replace the glXGetFBConfigs // with glXChooseConfigs. Docs are sparklingly clear as always. XWindowAttributes windowAttrs; if (!XGetWindowAttributes(display, window, &windowAttrs)) { NS_WARNING("[GLX] XGetWindowAttributes() failed"); return false; } const VisualID windowVisualID = XVisualIDFromVisual(windowAttrs.visual); #ifdef DEBUG printf("[GLX] window %lx has VisualID 0x%lx\n", window, windowVisualID); #endif for (int i = 0; i < numConfigs; i++) { int visid = None; sGLXLibrary.xGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID, &visid); if (!visid) { continue; } if (sGLXLibrary.IsATI()) { int depth; Visual* visual; FindVisualAndDepth(display, visid, &visual, &depth); if (depth == windowAttrs.depth && AreCompatibleVisuals(windowAttrs.visual, visual)) { *out_config = cfgs[i]; *out_visid = visid; return true; } } else { if (windowVisualID == static_cast<VisualID>(visid)) { *out_config = cfgs[i]; *out_visid = visid; return true; } } } NS_WARNING("[GLX] Couldn't find a FBConfig matching window visual"); return false; }