PRBool
nsGLPbufferGLX::Resize(PRInt32 width, PRInt32 height)
{
    if (mWidth == width &&
        mHeight == height)
    {
        return PR_TRUE;
    }

    Destroy();

    mThebesSurface = new gfxImageSurface(gfxIntSize(width, height), gfxASurface::ImageFormatARGB32);
    if (mThebesSurface->CairoStatus() != 0) {
        fprintf (stderr, "image surface failed\n");
        return PR_FALSE;
    }

    // clear the surface
    memset (mThebesSurface->Data(),
            0,
            height * mThebesSurface->Stride());

    int attrib[] = { GLX_PBUFFER_WIDTH, width,
                     GLX_PBUFFER_HEIGHT, height,
                     None };

    mPbuffer = gGLXWrap.fCreatePbuffer(mDisplay, mFBConfig, attrib);
    gGLXWrap.fMakeContextCurrent(mDisplay, mPbuffer, mPbuffer, mPbufferContext);

    mWidth = width;
    mHeight = height;

    fprintf (stderr, "Resize: %d %d\n", width, height);
    return PR_TRUE;
}
void
nsGLPbufferGLX::Destroy()
{
    sCurrentContextToken = nsnull;
    mThebesSurface = nsnull;

    if (mPbuffer) {
        gGLXWrap.fDestroyPbuffer(mDisplay, mPbuffer);
        mPbuffer = nsnull;
    }
}
nsGLPbufferGLX::~nsGLPbufferGLX()
{
    MakeContextCurrent();
#ifndef GL_FRAMEBUFFER
#define GL_FRAMEBUFFER 0x8D40
#endif
    // workaround for segfault on glXDestroyContext
    mGLWrap.fBindFramebuffer(GL_FRAMEBUFFER, 0);

    Destroy();

    if (mPbuffer)
        gGLXWrap.fDestroyPbuffer(mDisplay, mPbuffer);
    if (mPbufferContext)
        gGLXWrap.fDestroyContext(mDisplay, mPbufferContext);
#if !(defined(MOZ_WIDGET_GTK2) && defined(MOZ_X11))
    if (mDisplay)
        XCloseDisplay(mDisplay);
#endif

    gActiveBuffers--;
    fprintf (stderr, "nsGLPbufferGLX: gActiveBuffers: %d\n", gActiveBuffers);
    fflush (stderr);
}
nsresult nsSystemInfo::Init()
{
    struct pci_access *pacc;
    struct pci_dev *p;
    pciaddr_t ram = 0;
    char buf[128];
    int i, found, v, n;
    Display *dpy;
    char *display = NULL;
    Window root;
    XVisualInfo *info, templ;
    XWindowAttributes wts;
    XPixmapFormatValues *pf;
    XSetWindowAttributes attr;
    Window win;

    mWidth = 0;
    mHeight = 0;
    mDepth = 0;

    pacc = pci_alloc();
    pci_init(pacc);

    pci_scan_bus(pacc);
    for (p = pacc->devices; p; p=p->next) {
        pci_fill_info(p,
                      PCI_FILL_IDENT | PCI_FILL_CLASS | PCI_FILL_BASES | PCI_FILL_SIZES);
        if (p->device_class == PCI_CLASS_DISPLAY_VGA) {
            pci_lookup_name(pacc, buf, sizeof(buf),
                            PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE,
                            p->vendor_id, p->device_id);
            mDeviceName.AssignLiteral(buf);
            sprintf(buf, "0x%04X", p->vendor_id);
            mVendorID.AssignLiteral(buf);
            sprintf(buf, "0x%04X", p->device_id);
            mDeviceID.AssignLiteral(buf);
            for (i=0; i<6; i++) {
                pciaddr_t len = (p->known_fields & PCI_FILL_SIZES) ? p->size[i] : 0;
                if (len > ram) ram = len;
            }
            vram = ram / 1024 / 1024;
        }
        else {
            Log("Grafx Bot: No PCI VGA device found");
        }
    }

    pci_cleanup(pacc);

    if (NULL != (display = getenv("DISPLAY"))) {
        if (display[0] != ':') {
            display = strchr(display, ':');
            if (NULL == display) {
                Log("Grafx Bot: unable to find display");
                return NS_OK;
            }
        }
        if (NULL == (dpy = XOpenDisplay(display))) {
            Log("Grafx Bot: unable to find X display");
            return NS_OK;
        }
        root = DefaultRootWindow(dpy);
        XGetWindowAttributes(dpy, root, &wts);
        mWidth = wts.width;
        mHeight = wts.height;

        templ.screen = XDefaultScreen(dpy);
        info = XGetVisualInfo(dpy, VisualScreenMask, &templ, &found);
        v = -1;
        for (i = 0; v == -1 && i < found; i++) {
            if (info[i].depth >= 15)
                v = i;
        }
        for (i = 0; v == -1 && i < found; i++) {
            if (info[i].depth == 8)
                v = i;
        }
        if (-1 == v) {
            Log("Grafx Bot: can't find visual");
            return NS_OK;
        }

        pf = XListPixmapFormats(dpy, &n);
        for (i = 0; i < n; i++) {
            if (pf[i].depth == info[v].depth) {
                mDepth = pf[i].depth;
            }
        }

        if (gGLXWrap.OpenLibrary("libGL.so.1") && gGLXWrap.Init()) {
            attr.background_pixel = 0;
            attr.border_pixel = 0;
            attr.colormap  = XCreateColormap(dpy, root, info[v].visual, AllocNone);
            attr.event_mask = StructureNotifyMask | ExposureMask;
            win = XCreateWindow(dpy, root, 0, 0, 100, 100, 0, info[v].depth,
                                InputOutput, info[v].visual,
                                CWBackPixel | CWBorderPixel | CWColormap | CWEventMask, &attr);
            GLXContext ctx = gGLXWrap.fCreateContext(dpy, info, NULL, true);
            if (ctx) {
                if (gGLXWrap.fMakeCurrent(dpy, win, ctx)) {
                    mDriverVersion.AssignLiteral((char*)gGLXWrap.fGetString(LOCAL_GL_VERSION));
                    mDriver.AssignLiteral((char*)gGLXWrap.fGetString(LOCAL_GL_RENDERER));
                    mDriver.AppendLiteral(" (");
                    mDriver.AppendLiteral((char*)gGLXWrap.fGetString(LOCAL_GL_VENDOR));
                    mDriver.AppendLiteral(")");
                }
                else {
                    Log("Grafx Bot: unable to make current");
                }
                gGLXWrap.fDestroyContext(dpy, ctx);
            }
            else {
                Log("Grafx Bot: unable to create context");
            }
            XDestroyWindow(dpy, win);
        }
        else {
            Log("Grafx Bot: can't init libGL.so.1");
        }
    }

    return NS_OK;
}
void
nsGLPbufferGLX::MakeContextCurrent()
{
    if (gGLXWrap.fGetCurrentContext() != mPbufferContext)
        gGLXWrap.fMakeContextCurrent(mDisplay, mPbuffer, mPbuffer, mPbufferContext);
}
PRBool
nsGLPbufferGLX::Init(WebGLContext *priv)
{
    nsresult rv;
    const char *s;

    if (!gGLXWrap.OpenLibrary("libGL.so.1")) {
        LogMessage("Canvas 3D: Couldn't find libGL.so.1");
        return PR_FALSE;
    }

    if (!gGLXWrap.Init()) {
        LogMessage("Canvas 3D: gGLXWrap.Init() failed");
        return PR_FALSE;
    }

#if defined(MOZ_WIDGET_GTK2) && defined(MOZ_X11)
    mDisplay = gdk_x11_get_default_xdisplay();
#else
    mDisplay = XOpenDisplay(NULL);
#endif
    if (!mDisplay) {
        LogMessage("Canvas 3D: XOpenDisplay failed");
        return PR_FALSE;
    }

    // Make sure that everyone agrees that pbuffers are supported
    s = gGLXWrap.fQueryExtensionsString(mDisplay, DefaultScreen(mDisplay));
    if (strstr(s, "GLX_SGIX_pbuffer") == NULL) {
        LogMessage("Canvas 3D: GLX_SGIX_pbuffer not supported");
        return PR_FALSE;
    }

    s = gGLXWrap.fQueryServerString(mDisplay, DefaultScreen(mDisplay), GLX_EXTENSIONS);
    if (strstr(s, "GLX_SGIX_pbuffer") == NULL) {
        LogMessage("Canvas 3D: GLX_SGIX_pbuffer not supported by server");
        return PR_FALSE;
    }

    mPriv = priv;

    nsCOMPtr<nsIPrefService> prefService = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
    NS_ENSURE_SUCCESS(rv, PR_FALSE);

    nsCOMPtr<nsIPrefBranch> prefBranch;
    rv = prefService->GetBranch("extensions.canvas3d.", getter_AddRefs(prefBranch));
    NS_ENSURE_SUCCESS(rv, PR_FALSE);

    PRInt32 prefAntialiasing;
    rv = prefBranch->GetIntPref("antialiasing", &prefAntialiasing);
    if (NS_FAILED(rv))
        prefAntialiasing = 0;
    
    int attrib[] = { GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
                     GLX_RENDER_TYPE,   GLX_RGBA_BIT,
                     GLX_RED_SIZE, 1,
                     GLX_GREEN_SIZE, 1,
                     GLX_BLUE_SIZE, 1,
                     GLX_ALPHA_SIZE, 1,
                     GLX_DEPTH_SIZE, 1,
                     GLX_SAMPLE_BUFFERS, 1,
                     GLX_SAMPLES, 1 << prefAntialiasing,
                     None };
    if (prefAntialiasing <= 0)
      attrib[16] = 0;
    int num;
    GLXFBConfig *configs = gGLXWrap.fChooseFBConfig(mDisplay, DefaultScreen(mDisplay),
                                                    attrib, &num);

    fprintf(stderr, "CANVAS3D FBCONFIG: %d %p\n", num, (void*) configs);
    if (!configs) {
        LogMessage("Canvas 3D: No GLXFBConfig found");
        return PR_FALSE;
    }

    // choose first matching config;
    mFBConfig = *configs;

    XFree(configs);

    mPbufferContext = gGLXWrap.fCreateNewContext(mDisplay, mFBConfig, GLX_RGBA_TYPE,
                                                 nsnull, True);

    PRInt64 t1 = PR_Now();

    Resize(2, 2);
    MakeContextCurrent();

    PRInt64 t2 = PR_Now();

    fprintf (stderr, "nsGLPbufferGLX::Init!\n");

    if (!mGLWrap.OpenLibrary("libGL.so.1")) {
        LogMessage("Canvas 3D: GLWrap init failed, couldn't find libGL.so.1");
        return PR_FALSE;
    }

    mGLWrap.SetLookupFunc((LibrarySymbolLoader::PlatformLookupFunction) gGLXWrap.fGetProcAddress);

    if (!mGLWrap.Init(GLES20Wrap::TRY_NATIVE_GL)) {
        LogMessage("Canvas 3D: GLWrap init failed");
        return PR_FALSE;
    }

    PRInt64 t3 = PR_Now();

    fprintf (stderr, "nsGLPbufferGLX:: Initialization took t2-t1: %f t3-t2: %f\n",
             ((double)(t2-t1))/1000.0, ((double)(t3-t2))/1000.0);
    fflush (stderr);

    return PR_TRUE;
}