Fix the FFB driver for the renderbuffer changes
authorAlan Hourihane <alanh@tungstengraphics.com>
Mon, 18 Jul 2005 13:52:34 +0000 (13:52 +0000)
committerAlan Hourihane <alanh@tungstengraphics.com>
Mon, 18 Jul 2005 13:52:34 +0000 (13:52 +0000)
Support NEW INTERFACE as well

src/mesa/drivers/dri/ffb/ffb_depth.c
src/mesa/drivers/dri/ffb/ffb_depth.h
src/mesa/drivers/dri/ffb/ffb_span.c
src/mesa/drivers/dri/ffb/ffb_span.h
src/mesa/drivers/dri/ffb/ffb_state.c
src/mesa/drivers/dri/ffb/ffb_stencil.c
src/mesa/drivers/dri/ffb/ffb_stencil.h
src/mesa/drivers/dri/ffb/ffb_xmesa.c

index 27f3589d104c695317c9dac6fdd427548b6f13d4..68a2450eb7d0d48c9c2148ea22a6bce54be9cf19 100644 (file)
 
 #undef DEPTH_TRACE
 
-static void 
-FFBWriteDepthSpan(GLcontext *ctx, GLuint n, GLint x, GLint y,
-                 const GLdepth depth[], const GLubyte mask[])
+static void FFBWriteDepthSpan( GLcontext *ctx,
+                                 struct gl_renderbuffer *rb,
+                                 GLuint n, GLint x, GLint y,
+                                const void *values,
+                                const GLubyte mask[] )
 {
+        const GLuint *depth = (const GLuint *) values;
 #ifdef DEPTH_TRACE
        fprintf(stderr, "FFBWriteDepthSpan: n(%d) x(%d) y(%d)\n",
                (int) n, x, y);
@@ -81,10 +84,28 @@ FFBWriteDepthSpan(GLcontext *ctx, GLuint n, GLint x, GLint y,
        }
 }
 
-static void 
-FFBWriteDepthPixels(GLcontext *ctx, GLuint n, const GLint x[], const GLint y[],
-                   const GLdepth depth[], const GLubyte mask[])
+static void FFBWriteMonoDepthSpan( GLcontext *ctx, 
+                                    struct gl_renderbuffer *rb,
+                                    GLuint n, GLint x, GLint y,
+                                    const void *value, const GLubyte mask[] )
 {
+       const GLuint depthVal = *((GLuint *) value);
+       GLuint depths[MAX_WIDTH];
+       GLuint i;
+       for (i = 0; i < n; i++)
+               depths[i] = depthVal;
+       FFBWriteDepthSpan(ctx, rb, n, x, y, depths, mask);
+}
+
+static void FFBWriteDepthPixels( GLcontext *ctx,
+                                   struct gl_renderbuffer *rb,
+                                  GLuint n,
+                                  const GLint x[],
+                                  const GLint y[],
+                                  const void *values,
+                                  const GLubyte mask[] )
+{
+        const GLuint *depth = (const GLuint *) values;
 #ifdef DEPTH_TRACE
        fprintf(stderr, "FFBWriteDepthPixels: n(%d)\n", (int) n);
 #endif
@@ -126,9 +147,12 @@ FFBWriteDepthPixels(GLcontext *ctx, GLuint n, const GLint x[], const GLint y[],
        }
 }
 
-static void 
-FFBReadDepthSpan(GLcontext *ctx, GLuint n, GLint x, GLint y, GLdepth depth[])
+static void FFBReadDepthSpan( GLcontext *ctx,
+                                struct gl_renderbuffer *rb,
+                               GLuint n, GLint x, GLint y,
+                               void *values )
 {
+        GLuint *depth = (GLuint *) values;
        ffbContextPtr fmesa = FFB_CONTEXT(ctx);
        __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
        GLuint *zptr;
@@ -163,10 +187,13 @@ FFBReadDepthSpan(GLcontext *ctx, GLuint n, GLint x, GLint y, GLdepth depth[])
                UNLOCK_HARDWARE(fmesa);
 }
 
-static void 
-FFBReadDepthPixels(GLcontext *ctx, GLuint n, const GLint x[], const GLint y[],
-                  GLdepth depth[])
+static void FFBReadDepthPixels( GLcontext *ctx,
+                                  struct gl_renderbuffer *rb,
+                                  GLuint n,
+                                 const GLint x[], const GLint y[],
+                                 void *values )
 {
+        GLuint *depth = (GLuint *) values;
        ffbContextPtr fmesa = FFB_CONTEXT(ctx);
        __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
        char *zbase;
@@ -202,13 +229,17 @@ FFBReadDepthPixels(GLcontext *ctx, GLuint n, const GLint x[], const GLint y[],
                UNLOCK_HARDWARE(fmesa);
 }
 
-void ffbDDInitDepthFuncs(GLcontext *ctx)
+/**
+ * Plug in the Get/Put routines for the given driRenderbuffer.
+ */
+void
+ffbSetDepthFunctions(driRenderbuffer *drb, const GLvisual *vis)
 {
-       struct swrast_device_driver *swdd = 
-               _swrast_GetDeviceDriverReference(ctx);
-   
-       swdd->WriteDepthSpan    = FFBWriteDepthSpan;
-       swdd->ReadDepthSpan     = FFBReadDepthSpan;
-       swdd->WriteDepthPixels  = FFBWriteDepthPixels;
-       swdd->ReadDepthPixels   = FFBReadDepthPixels;
+       assert(drb->Base.InternalFormat == GL_DEPTH_COMPONENT16);
+       drb->Base.GetRow        = FFBReadDepthSpan;
+       drb->Base.GetValues     = FFBReadDepthPixels;
+       drb->Base.PutRow        = FFBWriteDepthSpan;
+       drb->Base.PutMonoRow    = FFBWriteMonoDepthSpan;
+       drb->Base.PutValues     = FFBWriteDepthPixels;
+       drb->Base.PutMonoValues = NULL;
 }
index a098bfcc2a27548f0ca1559d3802ede6440acb84..db908e7a6359b2a41298dd770f296d24b343456f 100644 (file)
@@ -3,6 +3,6 @@
 #ifndef _FFB_DEPTH_H
 #define _FFB_DEPTH_H
 
-extern void ffbDDInitDepthFuncs(GLcontext *ctx);
+void ffbSetDepthFunctions(driRenderbuffer *drb, const GLvisual *vis);
 
 #endif /* !(_FFB_DEPTH_H) */
index 6927945226b07b0aed407dcbf47442c114bfbda1..f4698c64e4a65104fd4938da6e6220147b0ffff7 100644 (file)
@@ -116,27 +116,20 @@ do {      GLuint p = *(GLuint *)(buf + ((__x)<<2) + ((__y)<<13)); \
 
 #include <spantmp.h>
 
-void ffbDDInitSpanFuncs(GLcontext *ctx)
+/**
+ * Plug in the Get/Put routines for the given driRenderbuffer.
+ */
+void
+ffbSetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis)
 {
-       struct swrast_device_driver *swdd = 
-               _swrast_GetDeviceDriverReference(ctx);
-   
-       swdd->WriteRGBASpan     = ffbWriteRGBASpan_888;
-       swdd->WriteRGBSpan      = ffbWriteRGBSpan_888;
-       swdd->WriteRGBAPixels   = ffbWriteRGBAPixels_888;
-       swdd->WriteMonoRGBASpan = ffbWriteMonoRGBASpan_888;
-       swdd->WriteMonoRGBAPixels       = ffbWriteMonoRGBAPixels_888;
-       swdd->ReadRGBASpan      = ffbReadRGBASpan_888;
-       swdd->ReadRGBAPixels    = ffbReadRGBAPixels_888;
-
-       /* We don't support color index mode yet, but it will be
-        * very easy to do. -DaveM
-        */
-       swdd->WriteCI8Span        = NULL;
-       swdd->WriteCI32Span       = NULL;
-       swdd->WriteMonoCISpan     = NULL;
-       swdd->WriteCI32Pixels     = NULL;
-       swdd->WriteMonoCIPixels   = NULL;
-       swdd->ReadCI32Span        = NULL;
-       swdd->ReadCI32Pixels      = NULL;
+       assert(vis->redBits == 8);
+        assert(vis->greenBits == 8);
+        assert(vis->blueBits == 8);
+        drb->Base.GetRow        = ffbReadRGBASpan_888;
+        drb->Base.GetValues     = ffbReadRGBAPixels_888;
+        drb->Base.PutRow        = ffbWriteRGBASpan_888;
+        drb->Base.PutRowRGB     = ffbWriteRGBSpan_888;
+        drb->Base.PutMonoRow    = ffbWriteMonoRGBASpan_888;
+        drb->Base.PutValues     = ffbWriteRGBAPixels_888;
+        drb->Base.PutMonoValues = ffbWriteMonoRGBAPixels_888;
 }
index 00501e8230c211272380a1fa39030500a41228dd..5ae227910d56b7256c515a989dcc6afc91372d3e 100644 (file)
@@ -3,6 +3,8 @@
 #ifndef _FFB_SPAN_H
 #define _FFB_SPAN_H
 
-extern void ffbDDInitSpanFuncs(GLcontext *ctx);
+#include "drirenderbuffer.h"
+
+void ffbSetSpanFunctions(driRenderbuffer *drb, const GLvisual *vis);
 
 #endif /* !(_FFB_SPAN_H) */
index 48b58e09932fdd9e8722db428a50f2963a124ed7..86df5b4bcac89b7a1ba8e5cdad5f1c1e22d9fc2d 100644 (file)
@@ -592,6 +592,8 @@ static void ffbDDColorMask(GLcontext *ctx,
                new_pmask |= 0x0000ff00;
        if (b)
                new_pmask |= 0x00ff0000;
+       if (a)
+               new_pmask |= 0xff000000;
 
        if (fmesa->pmask != new_pmask) {
                fmesa->pmask = new_pmask;
index a00eb3602ab0439a6dc99203097266324b397c22..2f13ee9210b6ccbb022a03055a6c7aff45065c36 100644 (file)
 
 #undef STENCIL_TRACE
 
-static void 
-FFBWriteStencilSpan(GLcontext *ctx, GLuint n, GLint x, GLint y,
-                   const GLstencil stencil[], const GLubyte mask[])
+static void FFBWriteStencilSpan( GLcontext *ctx,
+                                   struct gl_renderbuffer *rb,
+                                  GLuint n, GLint x, GLint y,
+                                  const void *values, const GLubyte mask[] )
 {
+        const GLubyte *stencil = (const GLubyte *) values;
 #ifdef STENCIL_TRACE
        fprintf(stderr, "FFBWriteStencilSpan: n(%d) x(%d) y(%d)\n",
                (int) n, x, y);
@@ -79,10 +81,13 @@ FFBWriteStencilSpan(GLcontext *ctx, GLuint n, GLint x, GLint y,
        }
 }
 
-static void 
-FFBWriteStencilPixels(GLcontext *ctx, GLuint n, const GLint x[], const GLint y[],
-                     const GLstencil stencil[], const GLubyte mask[])
+static void FFBWriteStencilPixels( GLcontext *ctx,
+                                     struct gl_renderbuffer *rb,
+                                    GLuint n,
+                                    const GLint x[], const GLint y[],
+                                    const void *values, const GLubyte mask[] )
 {
+        const GLubyte *stencil = (const GLubyte *) values;
 #ifdef STENCIL_TRACE
        fprintf(stderr, "FFBWriteStencilPixels: n(%d)\n", (int) n);
 #endif
@@ -124,9 +129,12 @@ FFBWriteStencilPixels(GLcontext *ctx, GLuint n, const GLint x[], const GLint y[]
        }
 }
 
-static void 
-FFBReadStencilSpan(GLcontext *ctx, GLuint n, GLint x, GLint y, GLstencil stencil[])
+static void FFBReadStencilSpan( GLcontext *ctx,
+                                  struct gl_renderbuffer *rb,
+                                 GLuint n, GLint x, GLint y,
+                                 void *values)
 {
+        GLubyte *stencil = (GLubyte *) values;
        ffbContextPtr fmesa = FFB_CONTEXT(ctx);
        __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
        GLuint *zptr;
@@ -161,10 +169,12 @@ FFBReadStencilSpan(GLcontext *ctx, GLuint n, GLint x, GLint y, GLstencil stencil
                UNLOCK_HARDWARE(fmesa);
 }
 
-static void 
-FFBReadStencilPixels(GLcontext *ctx, GLuint n, const GLint x[], const GLint y[],
-                    GLstencil stencil[])
+static void FFBReadStencilPixels( GLcontext *ctx,
+                                    struct gl_renderbuffer *rb,
+                                    GLuint n, const GLint x[], const GLint y[],
+                                   void *values )
 {
+        GLubyte *stencil = (GLubyte *) values;
        ffbContextPtr fmesa = FFB_CONTEXT(ctx);
        __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
        char *zbase;
@@ -200,22 +210,17 @@ FFBReadStencilPixels(GLcontext *ctx, GLuint n, const GLint x[], const GLint y[],
                UNLOCK_HARDWARE(fmesa);
 }
 
-void ffbDDInitStencilFuncs(GLcontext *ctx)
+/**
+ * Plug in the Get/Put routines for the given driRenderbuffer.
+ */
+void
+ffbSetStencilFunctions(driRenderbuffer *drb, const GLvisual *vis)
 {
-       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
-
-       struct swrast_device_driver *swdd = 
-               _swrast_GetDeviceDriverReference(ctx);
-
-       if (fmesa->ffb_sarea->flags & FFB_DRI_FFB2PLUS) {
-               swdd->WriteStencilSpan   = FFBWriteStencilSpan;
-               swdd->ReadStencilSpan    = FFBReadStencilSpan;
-               swdd->WriteStencilPixels = FFBWriteStencilPixels;
-               swdd->ReadStencilPixels  = FFBReadStencilPixels;
-       } else {
-               swdd->WriteStencilSpan   = NULL;
-               swdd->ReadStencilSpan    = NULL;
-               swdd->WriteStencilPixels = NULL;
-               swdd->ReadStencilPixels  = NULL;
-       }
+       assert(drb->Base.InternalFormat == GL_STENCIL_INDEX8_EXT);
+       drb->Base.GetRow        = FFBReadStencilSpan;
+       drb->Base.GetValues     = FFBReadStencilPixels;
+       drb->Base.PutRow        = FFBWriteStencilSpan;
+       /*drb->Base.PutMonoRow    = FFBWriteMonoStencilSpan;*/
+       drb->Base.PutValues     = FFBWriteStencilPixels;
+       drb->Base.PutMonoValues = NULL;
 }
index af161e7c1d19a0b2d6e61e4432f44814ebc55ed3..c7da1ca681f6dee86a9f24c0bfcb2f7b1678afbe 100644 (file)
@@ -3,6 +3,6 @@
 #ifndef _FFB_STENCIL_H
 #define _FFB_STENCIL_H
 
-extern void ffbDDInitStencilFuncs(GLcontext *ctx);
+void ffbSetStencilFunctions(driRenderbuffer *drb, const GLvisual *vis);
 
 #endif /* !(_FFB_STENCIL_H) */
index cdaafac15fbae45c78a011cbd3da9d0eb601f0b7..aced4a9253dec4fe5a5496807070771fe8449d8b 100644 (file)
 
 #include "ffb_xmesa.h"
 #include "context.h"
+#include "framebuffer.h"
 #include "matrix.h"
+#include "renderbuffer.h"
 #include "simple_list.h"
 #include "imports.h"
+#include "utils.h"
 
 #include "swrast/swrast.h"
 #include "swrast_setup/swrast_setup.h"
@@ -276,9 +279,6 @@ ffbCreateContext(const __GLcontextModes *mesaVis,
        ffbDDExtensionsInit(ctx);
        ffbDDInitDriverFuncs(ctx);
        ffbDDInitStateFuncs(ctx);
-       ffbDDInitSpanFuncs(ctx);
-       ffbDDInitDepthFuncs(ctx);
-       ffbDDInitStencilFuncs(ctx);
        ffbDDInitRenderFuncs(ctx);
        /*ffbDDInitTexFuncs(ctx); not needed */
        ffbDDInitBitmapFuncs(ctx);
@@ -322,16 +322,63 @@ ffbCreateBuffer(__DRIscreenPrivate *driScrnPriv,
                 const __GLcontextModes *mesaVis,
                 GLboolean isPixmap )
 {
+   /* Mesa checks for pitch > 0, but ffb doesn't use pitches */
+   int bogusPitch = 1;
+   int bpp = 4; /* we've always got a 32bpp framebuffer */
+   int offset = 0; /* always at 0 for offset */
+
    if (isPixmap) {
       return GL_FALSE; /* not implemented */
-   }
-   else {
+   } else {
+      GLboolean swStencil = (mesaVis->stencilBits > 0 && 
+                            mesaVis->depthBits != 24);
+#if 0
       driDrawPriv->driverPrivate = (void *) 
-         _mesa_create_framebuffer(mesaVis,
-                                  GL_FALSE,  /* software depth buffer? */
+        _mesa_create_framebuffer(mesaVis,
+                                 GL_FALSE,  /* software depth buffer? */
                                   mesaVis->stencilBits > 0,
                                   mesaVis->accumRedBits > 0,
                                   mesaVis->alphaBits > 0);
+#else
+      struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis);
+
+      {
+         driRenderbuffer *frontRb
+            = driNewRenderbuffer(GL_RGBA, bpp, offset, bogusPitch);
+         ffbSetSpanFunctions(frontRb, mesaVis);
+         _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base);
+      }
+
+      if (mesaVis->doubleBufferMode) {
+         driRenderbuffer *backRb
+            = driNewRenderbuffer(GL_RGBA, bpp, offset, bogusPitch);
+         ffbSetSpanFunctions(backRb, mesaVis);
+         _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base);
+      }
+
+      if (mesaVis->depthBits == 16) {
+         driRenderbuffer *depthRb
+            = driNewRenderbuffer(GL_DEPTH_COMPONENT16, bpp, offset, bogusPitch);
+         ffbSetDepthFunctions(depthRb, mesaVis);
+         _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base);
+      }
+
+      if (mesaVis->stencilBits > 0 && !swStencil) {
+         driRenderbuffer *stencilRb
+            = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT, bpp, offset,bogusPitch);
+         ffbSetStencilFunctions(stencilRb, mesaVis);
+         _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base);
+      }
+
+      _mesa_add_soft_renderbuffers(fb,
+                                   GL_FALSE, /* color */
+                                   GL_FALSE, /* depth */
+                                   swStencil,
+                                   mesaVis->accumRedBits > 0,
+                                   GL_FALSE, /* alpha */
+                                   GL_FALSE /* aux */);
+      driDrawPriv->driverPrivate = (void *) fb;
+#endif
       return (driDrawPriv->driverPrivate != NULL);
    }
 }
@@ -488,7 +535,7 @@ ffbMakeCurrent(__DRIcontextPrivate *driContextPriv,
 
                fmesa->driDrawable = driDrawPriv;
 
-               _mesa_make_current2(fmesa->glCtx, 
+               _mesa_make_current(fmesa->glCtx, 
                            (GLframebuffer *) driDrawPriv->driverPrivate, 
                            (GLframebuffer *) driReadPriv->driverPrivate);
 
@@ -520,7 +567,7 @@ ffbMakeCurrent(__DRIcontextPrivate *driContextPriv,
                                   1, 0, 0, 0, 0);
                }
        } else {
-               _mesa_make_current(NULL, NULL);
+               _mesa_make_current(NULL, NULL, NULL);
        }
 
        return GL_TRUE;
@@ -551,30 +598,172 @@ void ffbXMesaUpdateState(ffbContextPtr fmesa)
        }
 }
 
-
-static struct __DriverAPIRec ffbAPI = {
-   ffbInitDriver,
-   ffbDestroyScreen,
-   ffbCreateContext,
-   ffbDestroyContext,
-   ffbCreateBuffer,
-   ffbDestroyBuffer,
-   ffbSwapBuffers,
-   ffbMakeCurrent,
-   ffbUnbindContext
+static const struct __DriverAPIRec ffbAPI = {
+   .InitDriver      = ffbInitDriver,
+   .DestroyScreen   = ffbDestroyScreen,
+   .CreateContext   = ffbCreateContext,
+   .DestroyContext  = ffbDestroyContext,
+   .CreateBuffer    = ffbCreateBuffer,
+   .DestroyBuffer   = ffbDestroyBuffer,
+   .SwapBuffers     = ffbSwapBuffers,
+   .MakeCurrent     = ffbMakeCurrent,
+   .UnbindContext   = ffbUnbindContext,
+   .GetSwapInfo     = NULL,
+   .GetMSC          = NULL,
+   .WaitForMSC      = NULL,
+   .WaitForSBC      = NULL,
+   .SwapBuffersMSC  = NULL
 };
 
 
-
 /*
  * This is the bootstrap function for the driver.
  * The __driCreateScreen name is the symbol that libGL.so fetches.
  * Return:  pointer to a __DRIscreenPrivate.
  */
+#if !defined(DRI_NEW_INTERFACE_ONLY)
 void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
-                        int numConfigs, __GLXvisualConfig *config)
+                       int numConfigs, __GLXvisualConfig *config)
 {
    __DRIscreenPrivate *psp;
    psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &ffbAPI);
    return (void *) psp;
 }
+#endif /* !defined(DRI_NEW_INTERFACE_ONLY) */
+            
+
+#ifdef USE_NEW_INTERFACE
+static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
+
+static __GLcontextModes *
+ffbFillInModes( unsigned pixel_bits, unsigned depth_bits,
+                unsigned stencil_bits, GLboolean have_back_buffer )
+{
+   __GLcontextModes * modes;
+   __GLcontextModes * m;
+   unsigned num_modes;
+   unsigned depth_buffer_factor;
+   unsigned back_buffer_factor;
+   GLenum fb_format;
+   GLenum fb_type;
+
+   /* GLX_SWAP_COPY_OML is only supported because the FFB driver doesn't
+    * support pageflipping at all.
+    */
+   static const GLenum back_buffer_modes[] = {
+      GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
+   };
+
+   u_int8_t depth_bits_array[3];
+   u_int8_t stencil_bits_array[3];
+
+
+   depth_bits_array[0] = 0;
+   depth_bits_array[1] = depth_bits;
+   depth_bits_array[2] = depth_bits;
+
+   /* Just like with the accumulation buffer, always provide some modes
+    * with a stencil buffer.  It will be a sw fallback, but some apps won't
+    * care about that.
+    */
+   stencil_bits_array[0] = 0;
+   stencil_bits_array[1] = 0;
+   stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
+
+   depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
+   back_buffer_factor  = (have_back_buffer) ? 3 : 1;
+
+   num_modes = depth_buffer_factor * back_buffer_factor * 4;
+
+    if ( pixel_bits == 16 ) {
+        fb_format = GL_RGB;
+        fb_type = GL_UNSIGNED_SHORT_5_6_5;
+    }
+    else {
+        fb_format = GL_BGRA;
+        fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+    }
+
+   modes = (*create_context_modes)( num_modes, sizeof( __GLcontextModes ) );
+   m = modes;
+   if ( ! driFillInModes( & m, fb_format, fb_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, fb_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;
+   }
+
+
+   /* Mark the visual as slow if there are "fake" stencil bits.
+    */
+   for ( m = modes ; m != NULL ; m = m->next ) {
+      if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) {
+        m->visualRating = GLX_SLOW_CONFIG;
+      }
+   }
+
+   return modes;
+}
+#endif /* USE_NEW_INTERFACE */
+
+
+/**
+ * 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.
+ */
+#ifdef USE_NEW_INTERFACE
+PUBLIC
+void * __driCreateNewScreen( __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,
+                            __GLcontextModes ** driver_modes )
+                            
+{
+   __DRIscreenPrivate *psp;
+   static const __DRIversion ddx_expected = { 0, 0, 1 };
+   static const __DRIversion dri_expected = { 4, 0, 0 };
+   static const __DRIversion drm_expected = { 0, 0, 1 };
+
+   if ( ! driCheckDriDdxDrmVersions2( "ffb",
+                                     dri_version, & dri_expected,
+                                     ddx_version, & ddx_expected,
+                                     drm_version, & drm_expected ) ) {
+      return NULL;
+   }
+
+   psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
+                                 ddx_version, dri_version, drm_version,
+                                 frame_buffer, pSAREA, fd,
+                                 internal_api_version, &ffbAPI);
+   if ( psp != NULL ) {
+      create_context_modes = (PFNGLXCREATECONTEXTMODES)
+         glXGetProcAddress( (const GLubyte *) "__glXCreateContextModes" );
+      if ( create_context_modes != NULL ) {
+        *driver_modes = ffbFillInModes( 32, 16, 0, GL_TRUE );
+      }
+   }
+
+   return (void *) psp;
+}
+#endif /* USE_NEW_INTERFACE */