already_AddRefed<GLContext> GLContextProviderGLX::CreateWrappingExisting(void* aContext, void* aSurface) { if (!sGLXLibrary.EnsureInitialized()) { return nullptr; } if (aContext && aSurface) { SurfaceCaps caps = SurfaceCaps::Any(); nsRefPtr<GLContextGLX> glContext = new GLContextGLX(caps, nullptr, // SharedContext false, // Offscreen (Display*)DefaultXDisplay(), // Display (GLXDrawable)aSurface, (GLXContext)aContext, false, // aDeleteDrawable, true, (gfxXlibSurface*)nullptr); glContext->mOwnsContext = false; gGlobalContext = glContext; return glContext.forget(); } return nullptr; }
already_AddRefed<GLContext> GLContextProviderGLX::CreateForNativePixmapSurface(gfxASurface *aSurface) { if (!sGLXLibrary.EnsureInitialized()) { return nsnull; } if (aSurface->GetType() != gfxASurface::SurfaceTypeXlib) { NS_WARNING("GLContextProviderGLX::CreateForNativePixmapSurface called with non-Xlib surface"); return nsnull; } nsAutoTArray<int, 20> attribs; #define A1_(_x) do { attribs.AppendElement(_x); } while(0) #define A2_(_x,_y) do { \ attribs.AppendElement(_x); \ attribs.AppendElement(_y); \ } while(0) A2_(GLX_DOUBLEBUFFER, False); A2_(GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT); A1_(0); int numFormats; Display *display = DefaultXDisplay(); int xscreen = DefaultScreen(display); ScopedXFree<GLXFBConfig> cfg(sGLXLibrary.xChooseFBConfig(display, xscreen, attribs.Elements(), &numFormats)); if (!cfg) { return nsnull; } NS_ASSERTION(numFormats > 0, "glXChooseFBConfig() failed to match our requested format and violated its spec (!)"); gfxXlibSurface *xs = static_cast<gfxXlibSurface*>(aSurface); GLXPixmap glxpixmap = sGLXLibrary.xCreatePixmap(display, cfg[0], xs->XDrawable(), NULL); nsRefPtr<GLContextGLX> glContext = GLContextGLX::CreateGLContext(ContextFormat(ContextFormat::BasicRGB24), display, glxpixmap, cfg[0], NULL, NULL, PR_FALSE, xs); if (!glContext->Init()) { return nsnull; } return glContext.forget(); }
already_AddRefed<GLContext> GLContextProviderGLX::CreateForWindow(nsIWidget* aWidget, bool aForceAccelerated) { 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_COMPOSITOR_DISPLAY); if (!display) { NS_ERROR("X Display required for GLX Context provider"); return nullptr; } int xscreen = DefaultScreen(display); Window window = GET_NATIVE_WINDOW(aWidget); ScopedXFree<GLXFBConfig> cfgs; GLXFBConfig config; int visid; if (!GLContextGLX::FindFBConfigForWindow(display, xscreen, window, &cfgs, &config, &visid)) { return nullptr; } SurfaceCaps caps = SurfaceCaps::Any(); GLContextGLX* shareContext = GetGlobalContextGLX(); RefPtr<GLContextGLX> gl = GLContextGLX::CreateGLContext(CreateContextFlags::NONE, caps, shareContext, false, display, window, config, false); return gl.forget(); }
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(); }
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); }
static already_AddRefed<GLContextGLX> CreateOffscreenPixmapContext(const gfxIntSize& aSize, const ContextFormat& aFormat, PRBool aShare) { if (!sGLXLibrary.EnsureInitialized()) { return nsnull; } Display *display = DefaultXDisplay(); int xscreen = DefaultScreen(display); int attribs[] = { GLX_DOUBLEBUFFER, False, GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, GLX_X_RENDERABLE, True, GLX_RED_SIZE, 1, GLX_GREEN_SIZE, 1, GLX_BLUE_SIZE, 1, GLX_ALPHA_SIZE, 0, GLX_DEPTH_SIZE, 0, 0 }; int numConfigs = 0; ScopedXFree<GLXFBConfig> cfgs; cfgs = sGLXLibrary.xChooseFBConfig(display, xscreen, attribs, &numConfigs); if (!cfgs) { return nsnull; } NS_ASSERTION(numConfigs > 0, "glXChooseFBConfig() failed to match our requested format and violated its spec (!)"); ScopedXFree<XVisualInfo> vinfo; int chosenIndex; for (int i = 0; i < numConfigs; ++i) { int dtype, visid; if (sGLXLibrary.xGetFBConfigAttrib(display, cfgs[i], GLX_DRAWABLE_TYPE, &dtype) != Success || !(dtype & GLX_PIXMAP_BIT)) { continue; } if (sGLXLibrary.xGetFBConfigAttrib(display, cfgs[i], GLX_VISUAL_ID, &visid) != Success || visid == 0) { continue; } vinfo = sGLXLibrary.xGetVisualFromFBConfig(display, cfgs[i]); if (vinfo) { chosenIndex = i; break; } } if (!vinfo) { NS_WARNING("glXChooseFBConfig() didn't give us any configs with visuals!"); return nsnull; } nsRefPtr<gfxXlibSurface> xsurface = gfxXlibSurface::Create(DefaultScreenOfDisplay(display), vinfo->visual, gfxIntSize(16, 16)); if (xsurface->CairoStatus() != 0) { return nsnull; } GLXPixmap glxpixmap = sGLXLibrary.xCreatePixmap(display, cfgs[chosenIndex], xsurface->XDrawable(), NULL); if (glxpixmap == 0) { return nsnull; } GLContextGLX *shareContext = aShare ? GetGlobalContextGLX() : nsnull; nsRefPtr<GLContextGLX> glContext = GLContextGLX::CreateGLContext(aFormat, display, glxpixmap, cfgs[chosenIndex], vinfo, shareContext, PR_TRUE, xsurface); return glContext.forget(); }
already_AddRefed<GLContext> GLContextProviderGLX::CreateForWindow(nsIWidget *aWidget) { if (!sGLXLibrary.EnsureInitialized()) { return nsnull; } // 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); int xscreen = DefaultScreen(display); Window window = GET_NATIVE_WINDOW(aWidget); int numConfigs; ScopedXFree<GLXFBConfig> cfgs; if (gIsATI) { const int attribs[] = { 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 nsnull; } NS_ASSERTION(numConfigs > 0, "No FBConfigs found!"); // XXX the visual ID is almost certainly the 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"); XFree(cfgs); return nsnull; } const VisualID widgetVisualID = XVisualIDFromVisual(widgetAttrs.visual); #ifdef DEBUG printf("[GLX] widget has VisualID 0x%lx\n", widgetVisualID); #endif ScopedXFree<XVisualInfo> vi; if (gIsATI) { XVisualInfo vinfo_template; int nvisuals; vinfo_template.visual = widgetAttrs.visual; vinfo_template.visualid = XVisualIDFromVisual(vinfo_template.visual); vinfo_template.depth = widgetAttrs.depth; vinfo_template.screen = xscreen; vi = XGetVisualInfo(display, VisualIDMask|VisualDepthMask|VisualScreenMask, &vinfo_template, &nvisuals); NS_ASSERTION(vi && nvisuals == 1, "Could not locate unique matching XVisualInfo for Visual"); } int matchIndex = -1; ScopedXFree<XVisualInfo> vinfo; for (int i = 0; i < numConfigs; i++) { vinfo = sGLXLibrary.xGetVisualFromFBConfig(display, cfgs[i]); if (!vinfo) { continue; } if (gIsATI) { if (AreCompatibleVisuals(vi, vinfo)) { matchIndex = i; break; } } else { if (widgetVisualID == vinfo->visualid) { matchIndex = i; break; } } } if (matchIndex == -1) { NS_WARNING("[GLX] Couldn't find a FBConfig matching widget visual"); return nsnull; } GLContextGLX *shareContext = GetGlobalContextGLX(); nsRefPtr<GLContextGLX> glContext = GLContextGLX::CreateGLContext(ContextFormat(ContextFormat::BasicRGB24), display, window, cfgs[matchIndex], vinfo, shareContext, PR_FALSE); return glContext.forget(); }