Merge branch 'lp-offset-twoside'
[mesa.git] / src / mesa / drivers / dri / nouveau / nouveau_screen.c
index 2cf6f979e406e66fc99fdbf15ff37e97ed946ed0..a6e2186cf4370b9bd92549dea99fc78a9b468aa1 100644 (file)
-/**************************************************************************
-
-Copyright 2006 Stephane Marchesin
-All Rights Reserved.
-
-Permission is hereby granted, free of charge, to any person obtaining a
-copy of this software and associated documentation files (the "Software"),
-to deal in the Software without restriction, including without limitation
-on the rights to use, copy, modify, merge, publish, distribute, sub
-license, and/or sell copies of the Software, and to permit persons to whom
-the Software is furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice (including the next
-paragraph) shall be included in all copies or substantial portions of the
-Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
-ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP BE LIABLE FOR ANY CLAIM,
-DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
-USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-**************************************************************************/
-
-#include "glheader.h"
-#include "imports.h"
-#include "mtypes.h"
-#include "framebuffer.h"
-#include "renderbuffer.h"
+/*
+ * Copyright (C) 2009 Francisco Jerez.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
 
+#include "nouveau_driver.h"
 #include "nouveau_context.h"
-#include "nouveau_screen.h"
-#include "nouveau_object.h"
-#include "nouveau_span.h"
-
-#include "utils.h"
-#include "context.h"
-#include "vblank.h"
-#include "drirenderbuffer.h"
-
-#include "GL/internal/dri_interface.h"
-
-#include "xmlpool.h"
-
-PUBLIC const char __driConfigOptions[] =
-DRI_CONF_BEGIN
-    DRI_CONF_SECTION_DEBUG
-        DRI_CONF_NO_RAST(false)
-    DRI_CONF_SECTION_END
-DRI_CONF_END;
-static const GLuint __driNConfigOptions = 1;
-
-extern const struct dri_extension common_extensions[];
-extern const struct dri_extension nv10_extensions[];
-extern const struct dri_extension nv20_extensions[];
-extern const struct dri_extension nv30_extensions[];
-extern const struct dri_extension nv40_extensions[];
-extern const struct dri_extension nv50_extensions[];
-
-static nouveauScreenPtr nouveauCreateScreen(__DRIscreenPrivate *sPriv)
+#include "nouveau_fbo.h"
+#include "nouveau_texture.h"
+#include "nouveau_drmif.h"
+#include "nv04_driver.h"
+#include "nv10_driver.h"
+#include "nv20_driver.h"
+
+#include "main/framebuffer.h"
+#include "main/renderbuffer.h"
+
+static const __DRIextension *nouveau_screen_extensions[];
+
+static void
+nouveau_destroy_screen(__DRIscreen *dri_screen);
+
+static const __DRIconfig **
+nouveau_get_configs(void)
 {
-       nouveauScreenPtr screen;
-       NOUVEAUDRIPtr dri_priv=(NOUVEAUDRIPtr)sPriv->pDevPriv;
+       __DRIconfig **configs = NULL;
+       int i;
 
-       /* allocate screen */
-       screen = (nouveauScreenPtr) CALLOC( sizeof(*screen) );
-       if ( !screen ) {         
-               __driUtilMessage("%s: Could not allocate memory for screen structure",__FUNCTION__);
-               return NULL;
+       const uint8_t depth_bits[]   = { 0, 16, 24, 24 };
+       const uint8_t stencil_bits[] = { 0,  0,  0,  8 };
+       const uint8_t msaa_samples[] = { 0 };
+
+       const struct {
+               GLenum format;
+               GLenum type;
+       } fb_formats[] = {
+               { GL_RGB , GL_UNSIGNED_SHORT_5_6_5     },
+               { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV },
+               { GL_BGR , GL_UNSIGNED_INT_8_8_8_8_REV },
+       };
+
+       const GLenum back_buffer_modes[] = {
+               GLX_NONE, GLX_SWAP_UNDEFINED_OML
+       };
+
+       for (i = 0; i < Elements(fb_formats); i++) {
+               __DRIconfig **config;
+
+               config = driCreateConfigs(fb_formats[i].format,
+                                         fb_formats[i].type,
+                                         depth_bits, stencil_bits,
+                                         Elements(depth_bits),
+                                         back_buffer_modes,
+                                         Elements(back_buffer_modes),
+                                         msaa_samples,
+                                         Elements(msaa_samples),
+                                         GL_TRUE);
+               assert(config);
+
+               configs = configs ? driConcatConfigs(configs, config)
+                       : config;
        }
-       
-       screen->card=nouveau_card_lookup(dri_priv->device_id);
-       if (!screen->card) {
-               __driUtilMessage("%s: Unknown card type 0x%04x:0x%04x\n",
-                       __func__, dri_priv->device_id >> 16, dri_priv->device_id & 0xFFFF);
-               FREE(screen);
+
+       return (const __DRIconfig **)configs;
+}
+
+static const __DRIconfig **
+nouveau_init_screen2(__DRIscreen *dri_screen)
+{
+       const __DRIconfig **configs;
+       struct nouveau_screen *screen;
+       int ret;
+
+       /* Allocate the screen. */
+       screen = CALLOC_STRUCT(nouveau_screen);
+       if (!screen)
                return NULL;
+
+       dri_screen->private = screen;
+       dri_screen->extensions = nouveau_screen_extensions;
+       screen->dri_screen = dri_screen;
+
+       /* Open the DRM device. */
+       ret = nouveau_device_open_existing(&screen->device, 0, dri_screen->fd,
+                                          0);
+       if (ret) {
+               nouveau_error("Error opening the DRM device.\n");
+               goto fail;
        }
 
-       /* parse information in __driConfigOptions */
-       driParseOptionInfo (&screen->optionCache,__driConfigOptions, __driNConfigOptions);
+       /* Choose the card specific function pointers. */
+       switch (screen->device->chipset & 0xf0) {
+       case 0x00:
+               screen->driver = &nv04_driver;
+               break;
+       case 0x10:
+               screen->driver = &nv10_driver;
+               break;
+       case 0x20:
+               screen->driver = &nv20_driver;
+               break;
+       default:
+               assert(0);
+       }
 
-       screen->fbFormat    = dri_priv->bpp / 8;
-       screen->frontOffset = dri_priv->front_offset;
-       screen->frontPitch  = dri_priv->front_pitch;
-       screen->backOffset  = dri_priv->back_offset;
-       screen->backPitch   = dri_priv->back_pitch;
-       screen->depthOffset = dri_priv->depth_offset;
-       screen->depthPitch  = dri_priv->depth_pitch;
+       configs = nouveau_get_configs();
+       if (!configs)
+               goto fail;
+
+       return configs;
+fail:
+       nouveau_destroy_screen(dri_screen);
+       return NULL;
 
-       screen->driScreen = sPriv;
-       return screen;
 }
 
 static void
-nouveauDestroyScreen(__DRIscreenPrivate *sPriv)
+nouveau_destroy_screen(__DRIscreen *dri_screen)
 {
-       nouveauScreenPtr screen = (nouveauScreenPtr)sPriv->private;
+       struct nouveau_screen *screen = dri_screen->private;
 
-       if (!screen) return;
+       if (!screen)
+               return;
 
-       /* free all option information */
-       driDestroyOptionInfo (&screen->optionCache);
+       if (screen->device)
+               nouveau_device_close(&screen->device);
 
        FREE(screen);
-       sPriv->private = NULL;
+       dri_screen->private = NULL;
 }
 
-static GLboolean nouveauInitDriver(__DRIscreenPrivate *sPriv)
-{
-       sPriv->private = (void *) nouveauCreateScreen( sPriv );
-       if ( !sPriv->private ) {
-               nouveauDestroyScreen( sPriv );
-               return GL_FALSE;
-       }
-
-       return GL_TRUE;
-}
-
-/**
- * Create the Mesa framebuffer and renderbuffers for a given window/drawable.
- *
- * \todo This function (and its interface) will need to be updated to support
- * pbuffers.
- */
 static GLboolean
-nouveauCreateBuffer(__DRIscreenPrivate *driScrnPriv,
-                    __DRIdrawablePrivate *driDrawPriv,
-                    const __GLcontextModes *mesaVis,
-                    GLboolean isPixmap)
+nouveau_create_buffer(__DRIscreen *dri_screen,
+                     __DRIdrawable *drawable,
+                     const struct gl_config *visual,
+                     GLboolean is_pixmap)
 {
-       nouveauScreenPtr screen = (nouveauScreenPtr) driScrnPriv->private;
-       nouveau_renderbuffer  *nrb;
+       struct gl_renderbuffer *rb;
        struct gl_framebuffer *fb;
-       const GLboolean swAccum = mesaVis->accumRedBits > 0;
-       const GLboolean swStencil = mesaVis->stencilBits > 0 && mesaVis->depthBits != 24;
-       GLenum color_format = screen->fbFormat == 4 ? GL_RGBA8 : GL_RGB5;
+       GLenum color_format;
 
-       if (isPixmap)
+       if (is_pixmap)
                return GL_FALSE; /* not implemented */
 
-       fb = _mesa_create_framebuffer(mesaVis);
+       if (visual->redBits == 5)
+               color_format = GL_RGB5;
+       else if (visual->alphaBits == 0)
+               color_format = GL_RGB8;
+       else
+               color_format = GL_RGBA8;
+
+       fb = nouveau_framebuffer_dri_new(visual);
        if (!fb)
                return GL_FALSE;
 
-       /* Front buffer */
-       nrb = nouveau_renderbuffer_new(color_format,
-                                      driScrnPriv->pFB + screen->frontOffset,
-                                      screen->frontOffset,
-                                      screen->frontPitch * screen->fbFormat,
-                                      driDrawPriv);
-       nouveauSpanSetFunctions(nrb, mesaVis);
-       _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &nrb->mesa);
-
-       if (0 /* unified buffers if we choose to support them.. */) {
-       } else {
-               if (mesaVis->doubleBufferMode) {
-                       nrb = nouveau_renderbuffer_new(color_format, NULL,
-                                                      0, 0,
-                                                      NULL);
-                       nouveauSpanSetFunctions(nrb, mesaVis);
-                       _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &nrb->mesa);
-               }
-
-               if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) {
-                       nrb = nouveau_renderbuffer_new(GL_DEPTH24_STENCIL8_EXT, NULL,
-                                                      0, 0,
-                                                      NULL);
-                       nouveauSpanSetFunctions(nrb, mesaVis);
-                       _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa);
-                       _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &nrb->mesa);
-               } else if (mesaVis->depthBits == 24) {
-                       nrb = nouveau_renderbuffer_new(GL_DEPTH_COMPONENT24, NULL,
-                                                      0, 0,
-                                                      NULL);
-                       nouveauSpanSetFunctions(nrb, mesaVis);
-                       _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa);
-               } else if (mesaVis->depthBits == 16) {
-                       nrb = nouveau_renderbuffer_new(GL_DEPTH_COMPONENT16, NULL,
-                                                      0, 0,
-                                                      NULL);
-                       nouveauSpanSetFunctions(nrb, mesaVis);
-                       _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa);
-               }
+       /* Front buffer. */
+       rb = nouveau_renderbuffer_dri_new(color_format, drawable);
+       _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, rb);
+
+       /* Back buffer */
+       if (visual->doubleBufferMode) {
+               rb = nouveau_renderbuffer_dri_new(color_format, drawable);
+               _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, rb);
        }
 
-       _mesa_add_soft_renderbuffers(fb,
-                                    GL_FALSE, /* color */
-                                    GL_FALSE, /* depth */
-                                    swStencil,
-                                    swAccum,
-                                    GL_FALSE, /* alpha */
-                                    GL_FALSE  /* aux */);
+       /* Depth/stencil buffer. */
+       if (visual->depthBits == 24 && visual->stencilBits == 8) {
+               rb = nouveau_renderbuffer_dri_new(GL_DEPTH24_STENCIL8_EXT, drawable);
+               _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
+               _mesa_add_renderbuffer(fb, BUFFER_STENCIL, rb);
 
-       driDrawPriv->driverPrivate = (void *) fb;
-       return (driDrawPriv->driverPrivate != NULL);
-}
+       } else if (visual->depthBits == 24) {
+               rb = nouveau_renderbuffer_dri_new(GL_DEPTH_COMPONENT24, drawable);
+               _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
 
+       } else if (visual->depthBits == 16) {
+               rb = nouveau_renderbuffer_dri_new(GL_DEPTH_COMPONENT16, drawable);
+               _mesa_add_renderbuffer(fb, BUFFER_DEPTH, rb);
+       }
 
-static void
-nouveauDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
-{
-       _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate)));
+       /* Software renderbuffers. */
+       _mesa_add_soft_renderbuffers(fb, GL_FALSE, GL_FALSE, GL_FALSE,
+                                    visual->accumRedBits > 0,
+                                    GL_FALSE, GL_FALSE);
+
+       drawable->driverPrivate = fb;
+
+       return GL_TRUE;
 }
 
-static int
-nouveauGetSwapInfo(__DRIdrawablePrivate *dpriv, __DRIswapInfo *sInfo)
+static void
+nouveau_destroy_buffer(__DRIdrawable *drawable)
 {
-       return -1;
+       _mesa_reference_framebuffer(
+               (struct gl_framebuffer **)&drawable->driverPrivate, NULL);
 }
 
-static const struct __DriverAPIRec nouveauAPI = {
-       .InitDriver      = nouveauInitDriver,
-       .DestroyScreen   = nouveauDestroyScreen,
-       .CreateContext   = nouveauCreateContext,
-       .DestroyContext  = nouveauDestroyContext,
-       .CreateBuffer    = nouveauCreateBuffer,
-       .DestroyBuffer   = nouveauDestroyBuffer,
-       .SwapBuffers     = nouveauSwapBuffers,
-       .MakeCurrent     = nouveauMakeCurrent,
-       .UnbindContext   = nouveauUnbindContext,
-       .GetSwapInfo     = nouveauGetSwapInfo,
-       .GetMSC          = driGetMSC32,
-       .WaitForMSC      = driWaitForMSC32,
-       .WaitForSBC      = NULL,
-       .SwapBuffersMSC  = NULL,
-       .CopySubBuffer   = nouveauCopySubBuffer
-};
-
-
-static __GLcontextModes *
-nouveauFillInModes( unsigned pixel_bits, unsigned depth_bits,
-                unsigned stencil_bits, GLboolean have_back_buffer )
+static void
+nouveau_drawable_flush(__DRIdrawable *draw)
 {
-       __GLcontextModes * modes;
-       __GLcontextModes * m;
-       unsigned num_modes;
-       unsigned depth_buffer_factor;
-       unsigned back_buffer_factor;
-       int i;
-
-       static const struct {
-               GLenum format;
-               GLenum type;
-       } fb_format_array[] = {
-               { GL_RGB , GL_UNSIGNED_SHORT_5_6_5     },
-               { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV },
-               { GL_BGR , GL_UNSIGNED_INT_8_8_8_8_REV },
-       };
-
-       /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
-        * support pageflipping at all.
-        */
-       static const GLenum back_buffer_modes[] = {
-               GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
-       };
-
-       uint8_t depth_bits_array[4]   = { 0, 16, 24, 24 };
-       uint8_t stencil_bits_array[4] = { 0,  0,  0,  8 };
-
-       depth_buffer_factor = 4;
-       back_buffer_factor  = (have_back_buffer) ? 3 : 1;
-
-       num_modes = ((pixel_bits==16) ? 1 : 2) *
-               depth_buffer_factor * back_buffer_factor * 4;
-       modes = (*dri_interface->createContextModes)(num_modes,
-                                                    sizeof(__GLcontextModes));
-       m = modes;
-
-       for (i=((pixel_bits==16)?0:1);i<((pixel_bits==16)?1:3);i++) {
-               if (!driFillInModes(&m, fb_format_array[i].format,
-                                       fb_format_array[i].type,
-                                       depth_bits_array,
-                                       stencil_bits_array,
-                                       depth_buffer_factor,
-                                       back_buffer_modes,
-                                       back_buffer_factor,
-                                       GLX_TRUE_COLOR)) {
-               fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
-                               __func__, __LINE__ );
-               return NULL;
-               }
-
-               if (!driFillInModes(&m, fb_format_array[i].format,
-                                       fb_format_array[i].type,
-                                       depth_bits_array,
-                                       stencil_bits_array,
-                                       depth_buffer_factor,
-                                       back_buffer_modes,
-                                       back_buffer_factor,
-                                       GLX_DIRECT_COLOR)) {
-               fprintf( stderr, "[%s:%u] Error creating FBConfig!\n",
-                               __func__, __LINE__ );
-               return NULL;
-               }
-       }
-
-       return modes;
 }
 
+static const struct __DRI2flushExtensionRec nouveau_flush_extension = {
+    { __DRI2_FLUSH, __DRI2_FLUSH_VERSION },
+    nouveau_drawable_flush,
+    dri2InvalidateDrawable,
+};
 
-/**
- * This is the bootstrap function for the driver.  libGL supplies all of the
- * requisite information about the system, and the driver initializes itself.
- * 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.
- * 
- * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on 
- *         failure.
- */
-PUBLIC
-void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc,
-                                    const __GLcontextModes * modes,
-                                    const __DRIversion * ddx_version,
-                                    const __DRIversion * dri_version,
-                                    const __DRIversion * drm_version,
-                                    const __DRIframebuffer * frame_buffer,
-                                    drmAddress pSAREA, int fd, 
-                                    int internal_api_version,
-                                    const __DRIinterfaceMethods * interface,
-                                    __GLcontextModes ** driver_modes)
-                            
-{
-       __DRIscreenPrivate *psp;
-       static const __DRIversion ddx_expected = { 1, 2, 0 };
-       static const __DRIversion dri_expected = { 4, 0, 0 };
-       static const __DRIversion drm_expected = { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL };
-#if NOUVEAU_DRM_HEADER_PATCHLEVEL != 9
-#error nouveau_drm.h version doesn't match expected version
-#endif
-       dri_interface = interface;
-
-       if (!driCheckDriDdxDrmVersions2("nouveau",
-                                       dri_version, & dri_expected,
-                                       ddx_version, & ddx_expected,
-                                       drm_version, & drm_expected)) {
-               return NULL;
-       }
-
-       // temporary lock step versioning
-       if (drm_expected.patch!=drm_version->patch) {
-               __driUtilMessage("%s: wrong DRM version, expected %d, got %d\n",
-                               __func__,
-                               drm_expected.patch, drm_version->patch);
-               return NULL;
-       }
+static const struct __DRItexBufferExtensionRec nouveau_texbuffer_extension = {
+    { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION },
+    NULL,
+    nouveau_set_texbuffer,
+};
 
-       psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
-                                      ddx_version, dri_version, drm_version,
-                                      frame_buffer, pSAREA, fd,
-                                      internal_api_version, &nouveauAPI);
-       if ( psp != NULL ) {
-               NOUVEAUDRIPtr dri_priv = (NOUVEAUDRIPtr)psp->pDevPriv;
-
-               *driver_modes = nouveauFillInModes(dri_priv->bpp,
-                                                  (dri_priv->bpp == 16) ? 16 : 24,
-                                                  (dri_priv->bpp == 16) ? 0  : 8,
-                                                  1
-                                                  );
-
-               /* Calling driInitExtensions here, with a NULL context pointer, does not actually
-                * enable the extensions.  It just makes sure that all the dispatch offsets for all
-                * the extensions that *might* be enables are known.  This is needed because the
-                * dispatch offsets need to be known when _mesa_context_create is called, but we can't
-                * enable the extensions until we have a context pointer.
-                * 
-                * Hello chicken.  Hello egg.  How are you two today?
-                */
-               driInitExtensions( NULL, common_extensions, GL_FALSE );
-               driInitExtensions( NULL,   nv10_extensions, GL_FALSE );
-               driInitExtensions( NULL,   nv10_extensions, GL_FALSE );
-               driInitExtensions( NULL,   nv30_extensions, GL_FALSE );
-               driInitExtensions( NULL,   nv40_extensions, GL_FALSE );
-               driInitExtensions( NULL,   nv50_extensions, GL_FALSE );
-       }
+static const __DRIextension *nouveau_screen_extensions[] = {
+    &nouveau_flush_extension.base,
+    &nouveau_texbuffer_extension.base,
+    &dri2ConfigQueryExtension.base,
+    NULL
+};
 
-       return (void *) psp;
-}
+const struct __DriverAPIRec driDriverAPI = {
+       .InitScreen2     = nouveau_init_screen2,
+       .DestroyScreen   = nouveau_destroy_screen,
+       .CreateBuffer    = nouveau_create_buffer,
+       .DestroyBuffer   = nouveau_destroy_buffer,
+       .CreateContext   = nouveau_context_create,
+       .DestroyContext  = nouveau_context_destroy,
+       .MakeCurrent     = nouveau_context_make_current,
+       .UnbindContext   = nouveau_context_unbind,
+};
 
+/* This is the table of extensions that the loader will dlsym() for. */
+PUBLIC const __DRIextension *__driDriverExtensions[] = {
+       &driCoreExtension.base,
+       &driDRI2Extension.base,
+       NULL
+};