GLContext *
GLContextProviderWGL::GetGlobalContext(const ContextFlags aFlags)
{
    LibType libToUse = WGLLibrary::SelectLibrary(aFlags);
    
    if (!sWGLLib[libToUse].EnsureInitialized(libToUse == WGLLibrary::MESA_LLVMPIPE_LIB)) {
        return nullptr;
    }

    static bool triedToCreateContext[WGLLibrary::LIBS_MAX] = {false, false};

    if (!triedToCreateContext[libToUse] && !gGlobalContext[libToUse]) {
        triedToCreateContext[libToUse] = true;

        // conveniently, we already have what we need...
        gGlobalContext[libToUse] = new GLContextWGL(ContextFormat(ContextFormat::BasicRGB24), 
                                          nullptr,
                                          sWGLLib[libToUse].GetWindowDC(), 
                                          sWGLLib[libToUse].GetWindowGLContext(),
                                          libToUse);
        if (!gGlobalContext[libToUse]->Init()) {
            NS_WARNING("Global context GLContext initialization failed?");
            gGlobalContext[libToUse] = nullptr;
            return false;
        }

        gGlobalContext[libToUse]->SetIsGlobalSharedContext(true);
    }

    return static_cast<GLContext*>(gGlobalContext[libToUse]);
}
GLContext *
GLContextProviderWGL::GetGlobalContext()
{
    if (!sWGLLibrary.EnsureInitialized()) {
        return nsnull;
    }

    static bool triedToCreateContext = false;

    if (!triedToCreateContext && !gGlobalContext) {
        triedToCreateContext = true;

        // conveniently, we already have what we need...
        gGlobalContext = new GLContextWGL(ContextFormat(ContextFormat::BasicRGB24), nsnull,
                                          gSharedWindowDC, gSharedWindowGLContext);
        if (!gGlobalContext->Init()) {
            NS_WARNING("Global context GLContext initialization failed?");
            gGlobalContext = nsnull;
            return false;
        }

        gGlobalContext->SetIsGlobalSharedContext(true);
    }

    return static_cast<GLContext*>(gGlobalContext);
}
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();
}
GLContext *
GLContextProviderGLX::GetGlobalContext()
{
    static bool triedToCreateContext = false;
    if (!triedToCreateContext && !gGlobalContext) {
        triedToCreateContext = true;
        gGlobalContext = CreateOffscreenPixmapContext(gfxIntSize(1, 1),
                                                      ContextFormat(ContextFormat::BasicRGB24),
                                                      PR_FALSE);
        if (gGlobalContext)
            gGlobalContext->SetIsGlobalSharedContext(PR_TRUE);
    }

    return gGlobalContext;
}
already_AddRefed<GLContext>
GLContextProviderWGL::CreateForWindow(nsIWidget *aWidget)
{
    if (!sWGLLibrary.EnsureInitialized()) {
        return nsnull;
    }

    /**
       * We need to make sure we call SetPixelFormat -after- calling 
       * EnsureInitialized, otherwise it can load/unload the dll and 
       * wglCreateContext will fail.
       */

    HDC dc = (HDC)aWidget->GetNativeData(NS_NATIVE_GRAPHIC);

    SetPixelFormat(dc, gSharedWindowPixelFormat, NULL);
    HGLRC context = sWGLLibrary.fCreateContext(dc);
    if (!context) {
        return nsnull;
    }

    GLContextWGL *shareContext = GetGlobalContextWGL();
    if (shareContext &&
        !sWGLLibrary.fShareLists(shareContext->Context(), context))
    {
        shareContext = nsnull;
    }

    nsRefPtr<GLContextWGL> glContext = new GLContextWGL(ContextFormat(ContextFormat::BasicRGB24),
                                                        shareContext, dc, context);
    if (!glContext->Init()) {
        return nsnull;
    }

    return glContext.forget();
}
already_AddRefed<GLContext>
GLContextProviderWGL::CreateForWindow(nsIWidget *aWidget)
{
    if (!sWGLLibrary.EnsureInitialized()) {
        return nsnull;
    }

    /**
       * We need to make sure we call SetPixelFormat -after- calling 
       * EnsureInitialized, otherwise it can load/unload the dll and 
       * wglCreateContext will fail.
       */

    HDC dc = (HDC)aWidget->GetNativeData(NS_NATIVE_GRAPHIC);

    SetPixelFormat(dc, gSharedWindowPixelFormat, NULL);
    HGLRC context;

    GLContextWGL *shareContext = GetGlobalContextWGL();

    if (sWGLLibrary.HasRobustness()) {
        int attribs[] = {
            LOCAL_WGL_CONTEXT_FLAGS_ARB, LOCAL_WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB,
            LOCAL_WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB, LOCAL_WGL_LOSE_CONTEXT_ON_RESET_ARB,
            NULL
        };

        context = sWGLLibrary.fCreateContextAttribs(dc,
                                                    shareContext ? shareContext->Context() : nsnull,
                                                    attribs);
        if (!context && shareContext) {
            context = sWGLLibrary.fCreateContextAttribs(dc, nsnull, attribs);
            if (context) {
                shareContext = nsnull;
            }
        } else {
            context = sWGLLibrary.fCreateContext(dc);
            if (context && shareContext && !sWGLLibrary.fShareLists(shareContext->Context(), context)) {
                shareContext = nsnull;
            }
        }
    } else {
        context = sWGLLibrary.fCreateContext(dc);
        if (context &&
            shareContext &&
            !sWGLLibrary.fShareLists(shareContext->Context(), context))
        {
            shareContext = nsnull;
        }
    }

    if (!context) {
        return nsnull;
    }

    nsRefPtr<GLContextWGL> glContext = new GLContextWGL(ContextFormat(ContextFormat::BasicRGB24),
                                                        shareContext, dc, context);
    if (!glContext->Init()) {
        return nsnull;
    }

    glContext->SetIsDoubleBuffered(gUseDoubleBufferedWindows);

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