ogl-sample
[Top] [All Lists]

[ogl-sample] Bug fix for __glXSwapBuffers()

To: "ogl-sample@xxxxxxxxxxx" <ogl-sample@xxxxxxxxxxx>
Subject: [ogl-sample] Bug fix for __glXSwapBuffers()
From: Brian Paul <brianp@xxxxxxxxxxx>
Date: Fri, 27 Apr 2001 14:40:46 -0600
Organization: VA Linux Systems, Inc.
Reply-to: ogl-sample@xxxxxxxxxxx
Sender: owner-ogl-sample@xxxxxxxxxxx
I've found a problem in the server-side swapbuffers code while testing
with the DRI.  Here's the function from the ogl-sample glx/server/glxcmds.c
file:


int __glXSwapBuffers(__GLXclientState *cl, GLbyte *pc)
{
    ClientPtr client = cl->client;
    DrawablePtr pDraw;
    xGLXSwapBuffersReq *req = (xGLXSwapBuffersReq *) pc;
    GLXContextTag tag = req->contextTag;
    XID drawId = req->drawable;
    __GLXpixmap *pGlxPixmap;
    __GLXcontext *glxc = NULL;
    int error;
    
    /*
    ** Check that the GLX drawable is valid.
    */
    pDraw = (DrawablePtr) LookupDrawable(drawId, client);
    if (pDraw) {
        if (pDraw->type == DRAWABLE_WINDOW) {
            /*
            ** Drawable is an X window.
            */
        } else {
            /*
            ** Drawable is an X pixmap, which is not allowed.
            */
            client->errorValue = drawId;
            return __glXBadDrawable;
        }
    } else {
        pGlxPixmap = (__GLXpixmap *) LookupIDByType(drawId,
                                                    __glXPixmapRes);
        if (pGlxPixmap) {
            /*
            ** Drawable is a GLX pixmap.
            */
        } else {
            /*
            ** Drawable is neither a X window nor a GLX pixmap.
            */
            client->errorValue = drawId;
            return __glXBadDrawable;
        }
    }

    if (tag) {
        glxc = __glXLookupContextByTag(cl, tag);
        if (!glxc) {
            return __glXBadContextTag;
        }
        /*
        ** The calling thread is swapping its current drawable.  In this case,
        ** glxSwapBuffers is in both GL and X streams, in terms of
        ** sequentiality.
        */
        if (__glXForceCurrent(cl, tag, &error)) {
            /*
            ** Do whatever is needed to make sure that all preceding requests
            ** in both streams are completed before the swap is executed.
            */
            glFinish();
            __GLX_NOTE_FLUSHED_CMDS(glxc);
        } else {
            return error;
        }
    }

    if (pDraw) {
        __GLXdrawablePrivate *glxPriv;

        glxPriv = __glXGetDrawablePrivate(pDraw, drawId, glxc->modes);
        if (glxPriv == NULL) {
            return __glXBadDrawable;
        }

        if ((*glxPriv->swapBuffers)(glxPriv) == GL_FALSE) {
            return __glXBadDrawable;
        }
    }

    return Success;
}

If <tag> is 0, then <glxc> will be NULL when we reach the call to
__glXGetDrawablePrivate().  Dereferencing glxc->modes causes a segfault.

<tag> can legally be zero.  This happens when the user calls glXSwapBuffers()
for a window which is not currently bound to a rendering context.
The client-side glXSwapBuffers() code explicity sets the context tag to zero
when the user does this.

Replacing the end of the function with this code seems to fix the problem:

    [...]

    if (pDraw) {
        __GLXdrawablePrivate *glxPriv;

        if (glxc) {
            glxPriv = __glXGetDrawablePrivate(pDraw, drawId, glxc->modes);
            if (glxPriv == NULL) {
                return __glXBadDrawable;
            }
        }
        else {
            glxPriv = __glXFindDrawablePrivate(drawId);
            if (glxPriv == NULL) {
                /* This is a window we've never seen before, do nothing */
                return Success;
            }
        }

        if ((*glxPriv->swapBuffers)(glxPriv) == GL_FALSE) {
            return __glXBadDrawable;
        }
    }

    return Success;
}


I'm simply returning Success when attempting to do a swap on a window
which the GLX code has never encountered before.  I'm not sure what
else can be done.

I'm checking this change into the XFree86/DRI code.  If this looks OK
someone should probably update the ogl-sample code too.

-Brian

<Prev in Thread] Current Thread [Next in Thread>
  • [ogl-sample] Bug fix for __glXSwapBuffers(), Brian Paul <=