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(); }