static already_AddRefed<GLContextGLX> CreateOffscreenPixmapContext(const gfxIntSize& size, LibType libToUse) { GLXLibrary& glx = sGLXLibrary[libToUse]; if (!glx.EnsureInitialized(libToUse)) { return nullptr; } Display *display = DefaultXDisplay(); int xscreen = DefaultScreen(display); int attribs[] = { LOCAL_GLX_DRAWABLE_TYPE, LOCAL_GLX_PIXMAP_BIT, LOCAL_GLX_X_RENDERABLE, True, 0 }; int numConfigs = 0; ScopedXFree<GLXFBConfig> cfgs; cfgs = glx.xChooseFBConfig(display, xscreen, attribs, &numConfigs); if (!cfgs) { return nullptr; } MOZ_ASSERT(numConfigs > 0, "glXChooseFBConfig() failed to match our requested format and violated its spec!"); int visid = None; int chosenIndex = 0; for (int i = 0; i < numConfigs; ++i) { int dtype; if (glx.xGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_DRAWABLE_TYPE, &dtype) != Success || !(dtype & LOCAL_GLX_PIXMAP_BIT)) { continue; } if (glx.xGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID, &visid) != Success || visid == 0) { continue; } chosenIndex = i; break; } if (!visid) { NS_WARNING("glXChooseFBConfig() didn't give us any configs with visuals!"); return nullptr; } Visual *visual; int depth; FindVisualAndDepth(display, visid, &visual, &depth); ScopedXErrorHandler xErrorHandler; GLXPixmap glxpixmap = 0; bool error = false; gfxIntSize dummySize(16, 16); nsRefPtr<gfxXlibSurface> xsurface = gfxXlibSurface::Create(DefaultScreenOfDisplay(display), visual, dummySize); if (xsurface->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). if (glx.GLXVersionCheck(1, 3)) { glxpixmap = glx.xCreatePixmap(display, cfgs[chosenIndex], xsurface->XDrawable(), nullptr); } else { glxpixmap = glx.xCreateGLXPixmapWithConfig(display, cfgs[chosenIndex], xsurface-> XDrawable()); } if (glxpixmap == 0) { error = true; } DONE_CREATING_PIXMAP: nsRefPtr<GLContextGLX> glContext; bool serverError = xErrorHandler.SyncAndGetError(display); if (!error && // earlier recorded error !serverError) { ContextFlags flag = libToUse == GLXLibrary::MESA_LLVMPIPE_LIB ? ContextFlagsMesaLLVMPipe : ContextFlagsNone; // We might have an alpha channel, but it doesn't matter. SurfaceCaps dummyCaps = SurfaceCaps::Any(); GLContextGLX* shareContext = GetGlobalContextGLX(flag); glContext = GLContextGLX::CreateGLContext(dummyCaps, shareContext, true, display, glxpixmap, cfgs[chosenIndex], true, libToUse, xsurface); } return glContext.forget(); }
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) { const LibType libType = GLXLibrary::OPENGL_LIB; if (!sDefGLXLib.EnsureInitialized(libType)) { 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); int xscreen = DefaultScreen(display); Window window = GET_NATIVE_WINDOW(aWidget); int numConfigs; ScopedXFree<GLXFBConfig> cfgs; if (sDefGLXLib.IsATI() || !sDefGLXLib.GLXVersionCheck(1, 3)) { const int attribs[] = { LOCAL_GLX_DOUBLEBUFFER, False, 0 }; cfgs = sDefGLXLib.xChooseFBConfig(display, xscreen, attribs, &numConfigs); } else { cfgs = sDefGLXLib.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; sDefGLXLib.xGetFBConfigAttrib(display, cfgs[i], LOCAL_GLX_VISUAL_ID, &visid); if (!visid) { continue; } if (sDefGLXLib.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, libType); 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(); }