Merge commit 'origin/master' into gallium-0.2
[mesa.git] / src / mesa / drivers / dri / common / dri_util.c
index daf1d56feb9ac691f03d8f3a7e73b9fd9cea361d..a2316e2662ba24e2c2224cb2aef571b2cba443eb 100644 (file)
 #define MAP_FAILED ((void *)-1)
 #endif
 
-#include "imports.h"
+#include "main/imports.h"
 #define None 0
 
 #include "dri_util.h"
 #include "drm_sarea.h"
+#include "utils.h"
 
 #ifndef GLX_OML_sync_control
 typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC) (__DRIdrawable *drawable, int32_t *numerator, int32_t *denominator);
@@ -66,6 +67,18 @@ __driUtilMessage(const char *f, ...)
     }
 }
 
+GLint
+driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 )
+{
+   if (rect2.x1 > rect1.x1) rect1.x1 = rect2.x1;
+   if (rect2.x2 < rect1.x2) rect1.x2 = rect2.x2;
+   if (rect2.y1 > rect1.y1) rect1.y1 = rect2.y1;
+   if (rect2.y2 < rect1.y2) rect1.y2 = rect2.y2;
+
+   if (rect1.x1 > rect1.x2 || rect1.y1 > rect1.y2) return 0;
+
+   return (rect1.x2 - rect1.x1) * (rect1.y2 - rect1.y1);
+}
 
 /*****************************************************************/
 /** \name Context (un)binding functions                          */
@@ -139,7 +152,6 @@ static int driUnbindContext(__DRIcontext *pcp)
     return GL_TRUE;
 }
 
-
 /**
  * This function takes both a read buffer and a draw buffer.  This is needed
  * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
@@ -173,10 +185,7 @@ static int driBindContext(__DRIcontext *pcp,
     ** initialize the drawable information if has not been done before.
     */
 
-    if (psp->dri2.enabled) {
-       __driParseEvents(pcp, pdp);
-       __driParseEvents(pcp, prp);
-    } else {
+    if (!psp->dri2.enabled) {
        if (!pdp->pStamp || *pdp->pStamp != pdp->lastStamp) {
            DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
            __driUtilUpdateDrawableInfo(pdp);
@@ -264,139 +273,6 @@ __driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp)
        pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);
 
     DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
-
-}
-
-int
-__driParseEvents(__DRIcontextPrivate *pcp, __DRIdrawablePrivate *pdp)
-{
-    __DRIscreenPrivate *psp = pcp->driScreenPriv;
-    __DRIDrawableConfigEvent *dc, *last_dc;
-    __DRIBufferAttachEvent *ba, *last_ba;
-    unsigned int tail, mask, *p, end, total, size, changed;
-    unsigned char *data;
-    size_t rect_size;
-
-    /* Check for wraparound. */
-    if (psp->dri2.buffer->prealloc - pdp->dri2.tail > psp->dri2.buffer->size) {
-       /* If prealloc overlaps into what we just parsed, the
-       * server overwrote it and we have to reset our tail
-       * pointer. */
-       DRM_UNLOCK(psp->fd, psp->lock, pcp->hHWContext);
-       (*psp->dri2.loader->reemitDrawableInfo)(pdp, &pdp->dri2.tail,
-                                               pdp->loaderPrivate);
-       DRM_LIGHT_LOCK(psp->fd, psp->lock, pcp->hHWContext);
-    }
-
-    total = psp->dri2.buffer->head - pdp->dri2.tail;
-    mask = psp->dri2.buffer->size - 1;
-    end = psp->dri2.buffer->head;
-    data = psp->dri2.buffer->data;
-
-    changed = 0;
-    last_dc = NULL;
-    last_ba = NULL;
-
-    for (tail = pdp->dri2.tail; tail != end; tail += size) {
-       p = (unsigned int *) (data + (tail & mask));
-       size = DRI2_EVENT_SIZE(*p);
-       if (size > total || (tail & mask) + size > psp->dri2.buffer->size) {
-         /* illegal data, bail out. */
-         fprintf(stderr, "illegal event size\n");
-         break;
-       }
-
-       switch (DRI2_EVENT_TYPE(*p)) {
-       case DRI2_EVENT_DRAWABLE_CONFIG:
-         dc = (__DRIDrawableConfigEvent *) p;
-         if (dc->drawable == pdp->dri2.drawable_id)
-            last_dc = dc;
-         break;
-
-       case DRI2_EVENT_BUFFER_ATTACH:
-         ba = (__DRIBufferAttachEvent *) p;
-         if (ba->drawable == pdp->dri2.drawable_id && 
-             ba->buffer.attachment == DRI_DRAWABLE_BUFFER_FRONT_LEFT)
-            last_ba = ba;
-         break;
-       }
-    }
-         
-    if (last_dc) {
-       if (pdp->w != last_dc->width || pdp->h != last_dc->height)
-         changed = 1;
-
-       pdp->x = last_dc->x;
-       pdp->y = last_dc->y;
-       pdp->w = last_dc->width;
-       pdp->h = last_dc->height;
-
-       pdp->backX = 0;
-       pdp->backY = 0;
-       pdp->numBackClipRects = 1;
-       pdp->pBackClipRects[0].x1 = 0;
-       pdp->pBackClipRects[0].y1 = 0;
-       pdp->pBackClipRects[0].x2 = pdp->w;
-       pdp->pBackClipRects[0].y2 = pdp->h;
-
-       pdp->numClipRects = last_dc->num_rects;
-       _mesa_free(pdp->pClipRects);
-       rect_size = last_dc->num_rects * sizeof last_dc->rects[0];
-       pdp->pClipRects = _mesa_malloc(rect_size);
-       memcpy(pdp->pClipRects, last_dc->rects, rect_size);
-    }
-
-    /* We only care about the most recent drawable config. */
-    if (last_dc && changed)
-       (*psp->DriverAPI.HandleDrawableConfig)(pdp, pcp, last_dc);
-
-    /* Front buffer attachments are special, they typically mean that
-     * we're rendering to a redirected window (or a child window of a
-     * redirected window) and that it got resized.  Resizing the root
-     * window on randr events is a special case of this.  Other causes
-     * may be a window transitioning between redirected and
-     * non-redirected, or a window getting reparented between parents
-     * with different window pixmaps (eg two redirected windows).
-     * These events are special in that the X server allocates the
-     * buffer and that the buffer may be shared by other child
-     * windows.  When our window share the window pixmap with its
-     * parent, drawable config events doesn't affect the front buffer.
-     * We only care about the last such event in the buffer; in fact,
-     * older events will refer to invalid buffer objects.*/
-    if (last_ba)
-       (*psp->DriverAPI.HandleBufferAttach)(pdp, pcp, last_ba);
-
-    /* If there was a drawable config event in the buffer and it
-     * changed the size of the window, all buffer auxillary buffer
-     * attachments prior to that are invalid (as opposed to the front
-     * buffer case discussed above).  In that case we can start
-     * looking for buffer attachment after the last drawable config
-     * event.  If there is no drawable config event in this batch of
-     * events, we have to assume that the last batch might have had
-     * one and process all buffer attach events.*/
-    if (last_dc && changed)
-       tail = (unsigned char *) last_dc - data;
-    else
-       tail = pdp->dri2.tail;
-
-    for ( ; tail != end; tail += size) {
-       ba = (__DRIBufferAttachEvent *) (data + (tail & mask));
-       size = DRI2_EVENT_SIZE(ba->event_header);
-
-       if (DRI2_EVENT_TYPE(ba->event_header) != DRI2_EVENT_BUFFER_ATTACH)
-         continue;
-       if (ba->drawable != pdp->dri2.drawable_id)
-         continue;
-       if (last_ba == ba)
-         continue;
-
-       (*psp->DriverAPI.HandleBufferAttach)(pdp, pcp, ba);
-       changed = 1;
-    }
-
-    pdp->dri2.tail = tail;
-
-    return changed || last_ba;
 }
 
 /*@}*/
@@ -412,12 +288,7 @@ static void driReportDamage(__DRIdrawable *pdp,
     __DRIscreen *psp = pdp->driScreenPriv;
 
     /* Check that we actually have the new damage report method */
-    if (psp->dri2.enabled) {
-       (*psp->dri2.loader->postDamage)(pdp,
-                                       pClipRects,
-                                       numClipRects,
-                                       pdp->loaderPrivate);
-    } else if (psp->damage) {
+    if (psp->damage) {
        /* Report the damage.  Currently, all our drivers draw
         * directly to the front buffer, so we report the damage there
         * rather than to the backing storein (if any).
@@ -444,9 +315,6 @@ static void driSwapBuffers(__DRIdrawable *dPriv)
 {
     __DRIscreen *psp = dPriv->driScreenPriv;
 
-    if (!dPriv->numClipRects)
-        return;
-
     psp->DriverAPI.SwapBuffers(dPriv);
 
     driReportDamage(dPriv, dPriv->pClipRects, dPriv->numClipRects);
@@ -458,6 +326,7 @@ static int driDrawableGetMSC( __DRIscreen *sPriv, __DRIdrawable *dPriv,
     return sPriv->DriverAPI.GetDrawableMSC(sPriv, dPriv, msc);
 }
 
+
 static int driWaitForMSC(__DRIdrawable *dPriv, int64_t target_msc,
                         int64_t divisor, int64_t remainder,
                         int64_t * msc, int64_t * sbc)
@@ -465,7 +334,6 @@ static int driWaitForMSC(__DRIdrawable *dPriv, int64_t target_msc,
     __DRIswapInfo  sInfo;
     int  status;
 
-
     status = dPriv->driScreenPriv->DriverAPI.WaitForMSC( dPriv, target_msc,
                                                          divisor, remainder,
                                                          msc );
@@ -483,24 +351,26 @@ static int driWaitForMSC(__DRIdrawable *dPriv, int64_t target_msc,
     return status;
 }
 
+
 const __DRImediaStreamCounterExtension driMediaStreamCounterExtension = {
     { __DRI_MEDIA_STREAM_COUNTER, __DRI_MEDIA_STREAM_COUNTER_VERSION },
     driWaitForMSC,
     driDrawableGetMSC,
 };
 
+
 static void driCopySubBuffer(__DRIdrawable *dPriv,
                              int x, int y, int w, int h)
 {
     drm_clip_rect_t rect;
 
-    dPriv->driScreenPriv->DriverAPI.CopySubBuffer(dPriv, x, y, w, h);
-
     rect.x1 = x;
-    rect.y1 = y;
+    rect.y1 = dPriv->h - y - h;
     rect.x2 = x + w;
-    rect.y2 = y + w;
+    rect.y2 = rect.y1 + h;
     driReportDamage(dPriv, &rect, 1);
+
+    dPriv->driScreenPriv->DriverAPI.CopySubBuffer(dPriv, x, y, w, h);
 }
 
 const __DRIcopySubBufferExtension driCopySubBufferExtension = {
@@ -582,16 +452,19 @@ driCreateNewDrawable(__DRIscreen *psp, const __DRIconfig *config,
     return pdp;
 }
 
+
 static __DRIdrawable *
-dri2CreateNewDrawable(__DRIscreen *screen, const __DRIconfig *config,
-                     unsigned int drawable_id, unsigned int head, void *data)
+dri2CreateNewDrawable(__DRIscreen *screen,
+                     const __DRIconfig *config,
+                     void *loaderPrivate)
 {
     __DRIdrawable *pdraw;
 
-    pdraw = driCreateNewDrawable(screen, config, 0, 0, NULL, data);
+    pdraw = driCreateNewDrawable(screen, config, 0, 0, NULL, loaderPrivate);
+    if (!pdraw)
+       return NULL;
 
-    pdraw->dri2.drawable_id = drawable_id;
-    pdraw->dri2.tail = head;
+    pdraw->pClipRects = _mesa_malloc(sizeof *pdraw->pBackClipRects);
     pdraw->pBackClipRects = _mesa_malloc(sizeof *pdraw->pBackClipRects);
 
     return pdraw;
@@ -629,8 +502,6 @@ driDestroyDrawable(__DRIdrawable *pdp)
 /**
  * Destroy the per-context private information.
  * 
- * \param contextPrivate opaque pointer to the per-drawable private info.
- *
  * \internal
  * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
  * drmDestroyContext(), and finally frees \p contextPrivate.
@@ -648,13 +519,9 @@ driDestroyContext(__DRIcontext *pcp)
 /**
  * Create the per-drawable private driver information.
  * 
- * \param dpy           The display handle.
- * \param modes         Mode used to create the new context.
  * \param render_type   Type of rendering target.  \c GLX_RGBA is the only
  *                      type likely to ever be supported for direct-rendering.
- * \param shared        The shared context dependent methods or \c NULL if
- *                      non-existent.
- * \param pctx          DRI context to receive the context dependent methods.
+ * \param shared        Context with which to share textures, etc. or NULL
  *
  * \returns An opaque pointer to the per-context private information on
  *          success, or \c NULL on failure.
@@ -703,24 +570,15 @@ driCreateNewContext(__DRIscreen *psp, const __DRIconfig *config,
     return pcp;
 }
 
+
 static __DRIcontext *
 dri2CreateNewContext(__DRIscreen *screen, const __DRIconfig *config,
                      __DRIcontext *shared, void *data)
 {
-    drm_context_t hwContext;
-    DRM_CAS_RESULT(ret);
-
-    /* DRI2 doesn't use kernel with context IDs, we just need an ID that's
-     * different from the kernel context ID to make drmLock() happy. */
-
-    do {
-       hwContext = screen->dri2.lock->next_id;
-       DRM_CAS(&screen->dri2.lock->next_id, hwContext, hwContext + 1, ret);
-    } while (ret);
-
-    return driCreateNewContext(screen, config, 0, shared, hwContext, data);
+    return driCreateNewContext(screen, config, 0, shared, 0, data);
 }
 
+
 static int
 driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask)
 {
@@ -738,10 +596,6 @@ driCopyContext(__DRIcontext *dest, __DRIcontext *src, unsigned long mask)
 /**
  * Destroy the per-screen private information.
  * 
- * \param dpy the display handle.
- * \param scrn the screen number.
- * \param screenPrivate opaque pointer to the per-screen private information.
- *
  * \internal
  * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
  * drmClose(), and finally frees \p screenPrivate.
@@ -757,10 +611,7 @@ static void driDestroyScreen(__DRIscreen *psp)
        if (psp->DriverAPI.DestroyScreen)
            (*psp->DriverAPI.DestroyScreen)(psp);
 
-       if (psp->dri2.enabled) {
-           drmBOUnmap(psp->fd, &psp->dri2.sareaBO);
-           drmBOUnreference(psp->fd, &psp->dri2.sareaBO);
-       } else {
+       if (!psp->dri2.enabled) {
           (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
           (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
           (void)drmCloseOnce(psp->fd);
@@ -783,8 +634,8 @@ setupLoaderExtensions(__DRIscreen *psp,
            psp->damage = (__DRIdamageExtension *) extensions[i];
        if (strcmp(extensions[i]->name, __DRI_SYSTEM_TIME) == 0)
            psp->systemTime = (__DRIsystemTimeExtension *) extensions[i];
-       if (strcmp(extensions[i]->name, __DRI_LOADER) == 0)
-           psp->dri2.loader = (__DRIloaderExtension *) extensions[i];
+       if (strcmp(extensions[i]->name, __DRI_DRI2_LOADER) == 0)
+           psp->dri2.loader = (__DRIdri2LoaderExtension *) extensions[i];
     }
 }
 
@@ -794,15 +645,10 @@ setupLoaderExtensions(__DRIscreen *psp,
  * This routine also fills in the linked list pointed to by \c driver_modes
  * with the \c __GLcontextModes that the driver can support for windows or
  * pbuffers.
+ *
+ * For legacy DRI.
  * 
  * \param scrn  Index of the screen
- * \param psc   DRI screen data (not driver private)
- * \param modes Linked list of known display modes.  This list is, at a
- *              minimum, a list of modes based on the current display mode.
- *              These roughly match the set of available X11 visuals, but it
- *              need not be limited to X11!  The calling libGL should create
- *              a list that will inform the driver of the current display
- *              mode (i.e., color buffer depth, depth buffer depth, etc.).
  * \param ddx_version Version of the 2D DDX.  This may not be meaningful for
  *                    all drivers.
  * \param dri_version Version of the "server-side" DRI.
@@ -811,9 +657,9 @@ setupLoaderExtensions(__DRIscreen *psp,
  *                     framebuffer.
  * \param pSAREA       Pointer the the SAREA.
  * \param fd           Device handle for the DRM.
- * \param internal_api_version  Version of the internal interface between the
- *                              driver and libGL.
- * \param driverAPI Driver API functions used by other routines in dri_util.c.
+ * \param extensions   ??
+ * \param driver_modes  Returns modes suppoted by the driver
+ * \param loaderPrivate  ??
  * 
  * \note There is no need to check the minimum API version in this
  * function.  Since the name of this function is versioned, it is
@@ -833,7 +679,7 @@ driCreateNewScreen(int scrn,
     static const __DRIextension *emptyExtensionList[] = { NULL };
     __DRIscreen *psp;
 
-    psp = _mesa_malloc(sizeof *psp);
+    psp = _mesa_calloc(sizeof *psp);
     if (!psp)
        return NULL;
 
@@ -885,15 +731,16 @@ driCreateNewScreen(int scrn,
     return psp;
 }
 
-
+/**
+ * DRI2
+ */
 static __DRIscreen *
-dri2CreateNewScreen(int scrn, int fd, unsigned int sarea_handle,
+dri2CreateNewScreen(int scrn, int fd,
                    const __DRIextension **extensions,
                    const __DRIconfig ***driver_configs, void *data)
 {
     static const __DRIextension *emptyExtensionList[] = { NULL };
     __DRIscreen *psp;
-    unsigned int *p;
     drmVersionPtr version;
 
     if (driDriverAPI.InitScreen2 == NULL)
@@ -918,39 +765,9 @@ dri2CreateNewScreen(int scrn, int fd, unsigned int sarea_handle,
     psp->myNum = scrn;
     psp->dri2.enabled = GL_TRUE;
 
-    if (drmBOReference(psp->fd, sarea_handle, &psp->dri2.sareaBO)) {
-       fprintf(stderr, "Failed to reference DRI2 sarea BO\n");
-       _mesa_free(psp);
-       return NULL;
-    }
-
-    if (drmBOMap(psp->fd, &psp->dri2.sareaBO,
-                DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &psp->dri2.sarea)) {
-       drmBOUnreference(psp->fd, &psp->dri2.sareaBO);
-       _mesa_free(psp);
-       return NULL;
-    }
-
-    p = psp->dri2.sarea;
-    while (DRI2_SAREA_BLOCK_TYPE(*p)) {
-       switch (DRI2_SAREA_BLOCK_TYPE(*p)) {
-       case DRI2_SAREA_BLOCK_LOCK:
-           psp->dri2.lock = (__DRILock *) p;
-           break;
-       case DRI2_SAREA_BLOCK_EVENT_BUFFER:
-           psp->dri2.buffer = (__DRIEventBuffer *) p;
-           break;
-       }
-       p = DRI2_SAREA_BLOCK_NEXT(p);
-    }
-
-    psp->lock = (drmLock *) &psp->dri2.lock->lock;
-
     psp->DriverAPI = driDriverAPI;
     *driver_configs = driDriverAPI.InitScreen2(psp);
     if (*driver_configs == NULL) {
-       drmBOUnmap(psp->fd, &psp->dri2.sareaBO);
-       drmBOUnreference(psp->fd, &psp->dri2.sareaBO);
        _mesa_free(psp);
        return NULL;
     }
@@ -965,154 +782,45 @@ static const __DRIextension **driGetExtensions(__DRIscreen *psp)
     return psp->extensions;
 }
 
-#define __ATTRIB(attrib, field) \
-    { attrib, offsetof(__GLcontextModes, field) }
-
-static const struct { unsigned int attrib, offset; } attribMap[] = {
-    __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE,                 rgbBits),
-    __ATTRIB(__DRI_ATTRIB_LEVEL,                       level),
-    __ATTRIB(__DRI_ATTRIB_RED_SIZE,                    redBits),
-    __ATTRIB(__DRI_ATTRIB_GREEN_SIZE,                  greenBits),
-    __ATTRIB(__DRI_ATTRIB_BLUE_SIZE,                   blueBits),
-    __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE,                  alphaBits),
-    __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE,                  depthBits),
-    __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE,                        stencilBits),
-    __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE,              accumRedBits),
-    __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE,            accumGreenBits),
-    __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE,             accumBlueBits),
-    __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE,            accumAlphaBits),
-    __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS,              sampleBuffers),
-    __ATTRIB(__DRI_ATTRIB_SAMPLES,                     samples),
-    __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER,               doubleBufferMode),
-    __ATTRIB(__DRI_ATTRIB_STEREO,                      stereoMode),
-    __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS,                 numAuxBuffers),
-    __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE,            transparentPixel),
-    __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE,     transparentPixel),
-    __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE,       transparentRed),
-    __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE,     transparentGreen),
-    __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE,      transparentBlue),
-    __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE,     transparentAlpha),
-    __ATTRIB(__DRI_ATTRIB_FLOAT_MODE,                  floatMode),
-    __ATTRIB(__DRI_ATTRIB_RED_MASK,                    redMask),
-    __ATTRIB(__DRI_ATTRIB_GREEN_MASK,                  greenMask),
-    __ATTRIB(__DRI_ATTRIB_BLUE_MASK,                   blueMask),
-    __ATTRIB(__DRI_ATTRIB_ALPHA_MASK,                  alphaMask),
-    __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH,           maxPbufferWidth),
-    __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT,          maxPbufferHeight),
-    __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS,          maxPbufferPixels),
-    __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH,       optimalPbufferWidth),
-    __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT,      optimalPbufferHeight),
-    __ATTRIB(__DRI_ATTRIB_SWAP_METHOD,                 swapMethod),
-    __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB,         bindToTextureRgb),
-    __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA,                bindToTextureRgba),
-    __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE,      bindToMipmapTexture),
-    __ATTRIB(__DRI_ATTRIB_YINVERTED,                   yInverted),
-
-    /* The struct field doesn't matter here, these are handled by the
-     * switch in driGetConfigAttribIndex.  We need them in the array
-     * so the iterator includes them though.*/
-    __ATTRIB(__DRI_ATTRIB_RENDER_TYPE,                 level),
-    __ATTRIB(__DRI_ATTRIB_CONFIG_CAVEAT,               level),
-    __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS,     level),
-    __ATTRIB(__DRI_ATTRIB_SWAP_METHOD,                 level)
-};
-
-#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
-
-static int
-driGetConfigAttribIndex(const __DRIconfig *config,
-                       unsigned int index, unsigned int *value)
-{
-    switch (attribMap[index].attrib) {
-    case __DRI_ATTRIB_RENDER_TYPE:
-       if (config->modes.rgbMode)
-           *value = __DRI_ATTRIB_RGBA_BIT;
-       else
-           *value = __DRI_ATTRIB_COLOR_INDEX_BIT;
-       break;
-    case __DRI_ATTRIB_CONFIG_CAVEAT:
-       if (config->modes.visualRating == GLX_NON_CONFORMANT_CONFIG)
-           *value = __DRI_ATTRIB_NON_CONFORMANT_CONFIG;
-       else if (config->modes.visualRating == GLX_SLOW_CONFIG)
-           *value = __DRI_ATTRIB_SLOW_BIT;
-       else
-           *value = 0;
-       break;
-    case __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS:
-       *value = 0;
-       if (config->modes.bindToTextureTargets & GLX_TEXTURE_1D_BIT_EXT)
-           *value |= __DRI_ATTRIB_TEXTURE_1D_BIT;
-       if (config->modes.bindToTextureTargets & GLX_TEXTURE_2D_BIT_EXT)
-           *value |= __DRI_ATTRIB_TEXTURE_2D_BIT;
-       if (config->modes.bindToTextureTargets & GLX_TEXTURE_RECTANGLE_BIT_EXT)
-           *value |= __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT;
-       break;
-    case __DRI_ATTRIB_SWAP_METHOD:
-       break;
-
-    default:
-       *value = *(unsigned int *)
-           ((char *) &config->modes + attribMap[index].offset);
-       
-       break;
-    }
-
-    return GL_TRUE;
-}
-
-static int
-driGetConfigAttrib(const __DRIconfig *config,
-                  unsigned int attrib, unsigned int *value)
-{
-    int i;
-
-    for (i = 0; i < ARRAY_SIZE(attribMap); i++)
-       if (attribMap[i].attrib == attrib)
-           return driGetConfigAttribIndex(config, i, value);
-
-    return GL_FALSE;
-}
-
-static int
-driIndexConfigAttrib(const __DRIconfig *config, int index,
-                    unsigned int *attrib, unsigned int *value)
-{
-    if (index >= 0 && index < ARRAY_SIZE(attribMap)) {
-       *attrib = attribMap[index].attrib;
-       return driGetConfigAttribIndex(config, index, value);
-    }
-
-    return GL_FALSE;
-}
-
-const __DRIlegacyExtension driLegacyExtension = {
-    { __DRI_LEGACY, __DRI_LEGACY_VERSION },
-    driCreateNewScreen,
-    driCreateNewDrawable,
-    driCreateNewContext
-};
-
+/** Core interface */
 const __DRIcoreExtension driCoreExtension = {
     { __DRI_CORE, __DRI_CORE_VERSION },
-    dri2CreateNewScreen,
+    NULL,
     driDestroyScreen,
     driGetExtensions,
     driGetConfigAttrib,
     driIndexConfigAttrib,
-    dri2CreateNewDrawable,
+    NULL,
     driDestroyDrawable,
     driSwapBuffers,
-    dri2CreateNewContext,
+    NULL,
     driCopyContext,
     driDestroyContext,
     driBindContext,
     driUnbindContext
 };
 
+/** Legacy DRI interface */
+const __DRIlegacyExtension driLegacyExtension = {
+    { __DRI_LEGACY, __DRI_LEGACY_VERSION },
+    driCreateNewScreen,
+    driCreateNewDrawable,
+    driCreateNewContext,
+};
+
+/** Legacy DRI interface */
+const __DRIdri2Extension driDRI2Extension = {
+    { __DRI_DRI2, __DRI_DRI2_VERSION },
+    dri2CreateNewScreen,
+    dri2CreateNewDrawable,
+    dri2CreateNewContext,
+};
+
 /* This is the table of extensions that the loader will dlsym() for. */
 PUBLIC const __DRIextension *__driDriverExtensions[] = {
     &driCoreExtension.base,
     &driLegacyExtension.base,
+    &driDRI2Extension.base,
     NULL
 };