summaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers/dri/ffb/ffb_xmesa.c
diff options
context:
space:
mode:
authorAlan Hourihane <[email protected]>2003-12-04 13:38:06 +0000
committerAlan Hourihane <[email protected]>2003-12-04 13:38:06 +0000
commit13e6a4849c6800eac454fd1010cb2320874f2ed6 (patch)
treec311173244771131a63ba18318be645b4534521c /src/mesa/drivers/dri/ffb/ffb_xmesa.c
parent15af25aca0ed6a2390fe9e0d91055cfc01134ce2 (diff)
add SPARC ffb DRI driver
Diffstat (limited to 'src/mesa/drivers/dri/ffb/ffb_xmesa.c')
-rw-r--r--src/mesa/drivers/dri/ffb/ffb_xmesa.c593
1 files changed, 593 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/ffb/ffb_xmesa.c b/src/mesa/drivers/dri/ffb/ffb_xmesa.c
new file mode 100644
index 00000000000..caca9d4384a
--- /dev/null
+++ b/src/mesa/drivers/dri/ffb/ffb_xmesa.c
@@ -0,0 +1,593 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_xmesa.c,v 1.4 2002/02/22 21:32:59 dawes Exp $
+ *
+ * GLX Hardware Device Driver for Sun Creator/Creator3D
+ * Copyright (C) 2000, 2001 David S. Miller
+ *
+ * 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 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
+ * DAVID MILLER, OR ANY OTHER CONTRIBUTORS 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.
+ *
+ *
+ * David S. Miller <[email protected]>
+ */
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include "ffb_xmesa.h"
+#include "context.h"
+#include "matrix.h"
+#include "simple_list.h"
+#include "imports.h"
+
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "tnl/t_pipeline.h"
+#include "array_cache/acache.h"
+
+#include "ffb_context.h"
+#include "ffb_dd.h"
+#include "ffb_span.h"
+#include "ffb_depth.h"
+#include "ffb_stencil.h"
+#include "ffb_clear.h"
+#include "ffb_vb.h"
+#include "ffb_tris.h"
+#include "ffb_lines.h"
+#include "ffb_points.h"
+#include "ffb_state.h"
+#include "ffb_tex.h"
+#include "ffb_lock.h"
+#include "ffb_vtxfmt.h"
+#include "ffb_bitmap.h"
+
+static GLboolean
+ffbInitDriver(__DRIscreenPrivate *sPriv)
+{
+ ffbScreenPrivate *ffbScreen;
+ FFBDRIPtr gDRIPriv = (FFBDRIPtr) sPriv->pDevPriv;
+
+ if (getenv("LIBGL_FORCE_XSERVER"))
+ return GL_FALSE;
+
+ /* Allocate the private area. */
+ ffbScreen = (ffbScreenPrivate *) Xmalloc(sizeof(ffbScreenPrivate));
+ if (!ffbScreen)
+ return GL_FALSE;
+
+ /* Map FBC registers. */
+ if (drmMap(sPriv->fd,
+ gDRIPriv->hFbcRegs,
+ gDRIPriv->sFbcRegs,
+ &gDRIPriv->mFbcRegs)) {
+ Xfree(ffbScreen);
+ return GL_FALSE;
+ }
+ ffbScreen->regs = (ffb_fbcPtr) gDRIPriv->mFbcRegs;
+
+ /* Map ramdac registers. */
+ if (drmMap(sPriv->fd,
+ gDRIPriv->hDacRegs,
+ gDRIPriv->sDacRegs,
+ &gDRIPriv->mDacRegs)) {
+ drmUnmap(gDRIPriv->mFbcRegs, gDRIPriv->sFbcRegs);
+ Xfree(ffbScreen);
+ return GL_FALSE;
+ }
+ ffbScreen->dac = (ffb_dacPtr) gDRIPriv->mDacRegs;
+
+ /* Map "Smart" framebuffer views. */
+ if (drmMap(sPriv->fd,
+ gDRIPriv->hSfb8r,
+ gDRIPriv->sSfb8r,
+ &gDRIPriv->mSfb8r)) {
+ drmUnmap(gDRIPriv->mFbcRegs, gDRIPriv->sFbcRegs);
+ drmUnmap(gDRIPriv->mDacRegs, gDRIPriv->sDacRegs);
+ Xfree(ffbScreen);
+ return GL_FALSE;
+ }
+ ffbScreen->sfb8r = (volatile char *) gDRIPriv->mSfb8r;
+
+ if (drmMap(sPriv->fd,
+ gDRIPriv->hSfb32,
+ gDRIPriv->sSfb32,
+ &gDRIPriv->mSfb32)) {
+ drmUnmap(gDRIPriv->mFbcRegs, gDRIPriv->sFbcRegs);
+ drmUnmap(gDRIPriv->mDacRegs, gDRIPriv->sDacRegs);
+ drmUnmap(gDRIPriv->mSfb8r, gDRIPriv->sSfb8r);
+ Xfree(ffbScreen);
+ return GL_FALSE;
+ }
+ ffbScreen->sfb32 = (volatile char *) gDRIPriv->mSfb32;
+
+ if (drmMap(sPriv->fd,
+ gDRIPriv->hSfb64,
+ gDRIPriv->sSfb64,
+ &gDRIPriv->mSfb64)) {
+ drmUnmap(gDRIPriv->mFbcRegs, gDRIPriv->sFbcRegs);
+ drmUnmap(gDRIPriv->mDacRegs, gDRIPriv->sDacRegs);
+ drmUnmap(gDRIPriv->mSfb8r, gDRIPriv->sSfb8r);
+ drmUnmap(gDRIPriv->mSfb32, gDRIPriv->sSfb32);
+ Xfree(ffbScreen);
+ return GL_FALSE;
+ }
+ ffbScreen->sfb64 = (volatile char *) gDRIPriv->mSfb64;
+
+ ffbScreen->fifo_cache = 0;
+ ffbScreen->rp_active = 0;
+
+ ffbScreen->sPriv = sPriv;
+ sPriv->private = (void *) ffbScreen;
+
+ ffbDDLinefuncInit();
+ ffbDDPointfuncInit();
+
+ return GL_TRUE;
+}
+
+
+static void
+ffbDestroyScreen(__DRIscreenPrivate *sPriv)
+{
+ ffbScreenPrivate *ffbScreen = sPriv->private;
+ FFBDRIPtr gDRIPriv = (FFBDRIPtr) sPriv->pDevPriv;
+
+ drmUnmap(gDRIPriv->mFbcRegs, gDRIPriv->sFbcRegs);
+ drmUnmap(gDRIPriv->mDacRegs, gDRIPriv->sDacRegs);
+ drmUnmap(gDRIPriv->mSfb8r, gDRIPriv->sSfb8r);
+ drmUnmap(gDRIPriv->mSfb32, gDRIPriv->sSfb32);
+ drmUnmap(gDRIPriv->mSfb64, gDRIPriv->sSfb64);
+
+ Xfree(ffbScreen);
+}
+
+static const struct gl_pipeline_stage *ffb_pipeline[] = {
+ &_tnl_vertex_transform_stage,
+ &_tnl_normal_transform_stage,
+ &_tnl_lighting_stage,
+ /* REMOVE: fog coord stage */
+ &_tnl_texgen_stage,
+ &_tnl_texture_transform_stage,
+ /* REMOVE: point attenuation stage */
+ &_tnl_render_stage,
+ 0,
+};
+
+/* Create and initialize the Mesa and driver specific context data */
+static GLboolean
+ffbCreateContext(const __GLcontextModes *mesaVis,
+ __DRIcontextPrivate *driContextPriv,
+ void *sharedContextPrivate)
+{
+ ffbContextPtr fmesa;
+ GLcontext *ctx, *shareCtx;
+ __DRIscreenPrivate *sPriv;
+ ffbScreenPrivate *ffbScreen;
+ char *debug;
+
+ /* Allocate ffb context */
+ fmesa = (ffbContextPtr) CALLOC(sizeof(ffbContextRec));
+ if (!fmesa)
+ return GL_FALSE;
+
+ /* Allocate Mesa context */
+ if (sharedContextPrivate)
+ shareCtx = ((ffbContextPtr) sharedContextPrivate)->glCtx;
+ else
+ shareCtx = NULL;
+ fmesa->glCtx = _mesa_create_context(mesaVis, shareCtx, fmesa, GL_TRUE);
+ if (!fmesa->glCtx) {
+ FREE(fmesa);
+ return GL_FALSE;
+ }
+ driContextPriv->driverPrivate = fmesa;
+ ctx = fmesa->glCtx;
+
+ sPriv = driContextPriv->driScreenPriv;
+ ffbScreen = (ffbScreenPrivate *) sPriv->private;
+
+ /* Dri stuff. */
+ fmesa->hHWContext = driContextPriv->hHWContext;
+ fmesa->driFd = sPriv->fd;
+ fmesa->driHwLock = &sPriv->pSAREA->lock;
+
+ fmesa->ffbScreen = ffbScreen;
+ fmesa->driScreen = sPriv;
+ fmesa->ffb_sarea = FFB_DRISHARE(sPriv->pSAREA);
+
+ /* Register and framebuffer hw pointers. */
+ fmesa->regs = ffbScreen->regs;
+ fmesa->sfb32 = ffbScreen->sfb32;
+
+ ffbDDInitContextHwState(ctx);
+
+ /* Default clear and depth colors. */
+ {
+ GLubyte r = (GLint) (ctx->Color.ClearColor[0] * 255.0F);
+ GLubyte g = (GLint) (ctx->Color.ClearColor[1] * 255.0F);
+ GLubyte b = (GLint) (ctx->Color.ClearColor[2] * 255.0F);
+
+ fmesa->clear_pixel = ((r << 0) |
+ (g << 8) |
+ (b << 16));
+ }
+ fmesa->clear_depth = Z_FROM_MESA(ctx->Depth.Clear * 4294967295.0f);
+ fmesa->clear_stencil = ctx->Stencil.Clear & 0xf;
+
+ /* No wide points. */
+ ctx->Const.MinPointSize = 1.0;
+ ctx->Const.MinPointSizeAA = 1.0;
+ ctx->Const.MaxPointSize = 1.0;
+ ctx->Const.MaxPointSizeAA = 1.0;
+
+ /* Disable wide lines as we can't antialias them correctly in
+ * hardware.
+ */
+ ctx->Const.MinLineWidth = 1.0;
+ ctx->Const.MinLineWidthAA = 1.0;
+ ctx->Const.MaxLineWidth = 1.0;
+ ctx->Const.MaxLineWidthAA = 1.0;
+ ctx->Const.LineWidthGranularity = 1.0;
+
+ /* Instead of having GCC emit these constants a zillion times
+ * everywhere in the driver, put them here.
+ */
+ fmesa->ffb_2_30_fixed_scale = __FFB_2_30_FIXED_SCALE;
+ fmesa->ffb_one_over_2_30_fixed_scale = (1.0 / __FFB_2_30_FIXED_SCALE);
+ fmesa->ffb_16_16_fixed_scale = __FFB_16_16_FIXED_SCALE;
+ fmesa->ffb_one_over_16_16_fixed_scale = (1.0 / __FFB_16_16_FIXED_SCALE);
+ fmesa->ffb_ubyte_color_scale = 255.0f;
+ fmesa->ffb_zero = 0.0f;
+
+ fmesa->debugFallbacks = GL_FALSE;
+ debug = getenv("LIBGL_DEBUG");
+ if (debug && strstr(debug, "fallbacks"))
+ fmesa->debugFallbacks = GL_TRUE;
+
+ /* Initialize the software rasterizer and helper modules. */
+ _swrast_CreateContext( ctx );
+ _ac_CreateContext( ctx );
+ _tnl_CreateContext( ctx );
+ _swsetup_CreateContext( ctx );
+
+ /* All of this need only be done once for a new context. */
+ ffbDDExtensionsInit(ctx);
+ ffbDDInitDriverFuncs(ctx);
+ ffbDDInitStateFuncs(ctx);
+ ffbDDInitSpanFuncs(ctx);
+ ffbDDInitDepthFuncs(ctx);
+ ffbDDInitStencilFuncs(ctx);
+ ffbDDInitRenderFuncs(ctx);
+ ffbDDInitTexFuncs(ctx);
+ ffbDDInitBitmapFuncs(ctx);
+ ffbInitVB(ctx);
+
+ ffbInitTnlModule(ctx);
+
+ _tnl_destroy_pipeline(ctx);
+ _tnl_install_pipeline(ctx, ffb_pipeline);
+
+ return GL_TRUE;
+}
+
+static void
+ffbDestroyContext(__DRIcontextPrivate *driContextPriv)
+{
+ ffbContextPtr fmesa = (ffbContextPtr) driContextPriv->driverPrivate;
+
+ if (fmesa) {
+ ffbFreeVB(fmesa->glCtx);
+
+ _swsetup_DestroyContext( fmesa->glCtx );
+ _tnl_DestroyContext( fmesa->glCtx );
+ _ac_DestroyContext( fmesa->glCtx );
+ _swrast_DestroyContext( fmesa->glCtx );
+
+ /* free the Mesa context */
+ fmesa->glCtx->DriverCtx = NULL;
+ _mesa_destroy_context(fmesa->glCtx);
+
+ FREE(fmesa);
+ }
+}
+
+/* Create and initialize the Mesa and driver specific pixmap buffer data */
+static GLboolean
+ffbCreateBuffer(__DRIscreenPrivate *driScrnPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ const __GLcontextModes *mesaVis,
+ GLboolean isPixmap )
+{
+ if (isPixmap) {
+ return GL_FALSE; /* not implemented */
+ }
+ else {
+ driDrawPriv->driverPrivate = (void *)
+ _mesa_create_framebuffer(mesaVis,
+ GL_FALSE, /* software depth buffer? */
+ mesaVis->stencilBits > 0,
+ mesaVis->accumRedBits > 0,
+ mesaVis->alphaBits > 0);
+ return (driDrawPriv->driverPrivate != NULL);
+ }
+}
+
+
+static void
+ffbDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
+{
+ _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
+}
+
+
+#define USE_FAST_SWAP
+
+static void
+ffbSwapBuffers( __DRIdrawablePrivate *dPriv )
+{
+ ffbContextPtr fmesa = (ffbContextPtr) dPriv->driContextPriv->driverPrivate;
+ unsigned int fbc, wid, wid_reg_val, dac_db_bit;
+ unsigned int shadow_dac_addr, active_dac_addr;
+ ffb_fbcPtr ffb;
+ ffb_dacPtr dac;
+
+ if (fmesa == NULL ||
+ fmesa->glCtx->Visual.doubleBufferMode == 0)
+ return;
+
+ /* Flush pending rendering commands */
+ _mesa_notifySwapBuffers(fmesa->glCtx);
+
+ ffb = fmesa->regs;
+ dac = fmesa->ffbScreen->dac;
+
+ fbc = fmesa->fbc;
+ wid = fmesa->wid;
+
+ /* Swap the buffer we render into and read pixels from. */
+ fmesa->back_buffer ^= 1;
+
+ /* If we are writing into both buffers, don't mess with
+ * the WB setting.
+ */
+ if ((fbc & FFB_FBC_WB_AB) != FFB_FBC_WB_AB) {
+ if ((fbc & FFB_FBC_WB_A) != 0)
+ fbc = (fbc & ~FFB_FBC_WB_A) | FFB_FBC_WB_B;
+ else
+ fbc = (fbc & ~FFB_FBC_WB_B) | FFB_FBC_WB_A;
+ }
+
+ /* But either way, we must flip the read buffer setting. */
+ if ((fbc & FFB_FBC_RB_A) != 0)
+ fbc = (fbc & ~FFB_FBC_RB_A) | FFB_FBC_RB_B;
+ else
+ fbc = (fbc & ~FFB_FBC_RB_B) | FFB_FBC_RB_A;
+
+ LOCK_HARDWARE(fmesa);
+
+ if (fmesa->fbc != fbc) {
+ FFBFifo(fmesa, 1);
+ ffb->fbc = fmesa->fbc = fbc;
+ fmesa->ffbScreen->rp_active = 1;
+ }
+
+ /* And swap the buffer displayed in the WID. */
+ if (fmesa->ffb_sarea->flags & FFB_DRI_PAC1) {
+ shadow_dac_addr = FFBDAC_PAC1_SPWLUT(wid);
+ active_dac_addr = FFBDAC_PAC1_APWLUT(wid);
+ dac_db_bit = FFBDAC_PAC1_WLUT_DB;
+ } else {
+ shadow_dac_addr = FFBDAC_PAC2_SPWLUT(wid);
+ active_dac_addr = FFBDAC_PAC2_APWLUT(wid);
+ dac_db_bit = FFBDAC_PAC2_WLUT_DB;
+ }
+
+ FFBWait(fmesa, ffb);
+
+ wid_reg_val = DACCFG_READ(dac, active_dac_addr);
+ if (fmesa->back_buffer == 0)
+ wid_reg_val |= dac_db_bit;
+ else
+ wid_reg_val &= ~dac_db_bit;
+#ifdef USE_FAST_SWAP
+ DACCFG_WRITE(dac, active_dac_addr, wid_reg_val);
+#else
+ DACCFG_WRITE(dac, shadow_dac_addr, wid_reg_val);
+
+ /* Schedule the window transfer. */
+ DACCFG_WRITE(dac, FFBDAC_CFG_WTCTRL,
+ (FFBDAC_CFG_WTCTRL_TCMD | FFBDAC_CFG_WTCTRL_TE));
+
+ {
+ int limit = 1000000;
+ while (limit--) {
+ unsigned int wtctrl = DACCFG_READ(dac, FFBDAC_CFG_WTCTRL);
+
+ if ((wtctrl & FFBDAC_CFG_WTCTRL_DS) == 0)
+ break;
+ }
+ }
+#endif
+
+ UNLOCK_HARDWARE(fmesa);
+}
+
+static void ffb_init_wid(ffbContextPtr fmesa, unsigned int wid)
+{
+ ffb_dacPtr dac = fmesa->ffbScreen->dac;
+ unsigned int wid_reg_val, dac_db_bit, active_dac_addr;
+ unsigned int shadow_dac_addr;
+
+ if (fmesa->ffb_sarea->flags & FFB_DRI_PAC1) {
+ shadow_dac_addr = FFBDAC_PAC1_SPWLUT(wid);
+ active_dac_addr = FFBDAC_PAC1_APWLUT(wid);
+ dac_db_bit = FFBDAC_PAC1_WLUT_DB;
+ } else {
+ shadow_dac_addr = FFBDAC_PAC2_SPWLUT(wid);
+ active_dac_addr = FFBDAC_PAC2_APWLUT(wid);
+ dac_db_bit = FFBDAC_PAC2_WLUT_DB;
+ }
+
+ wid_reg_val = DACCFG_READ(dac, active_dac_addr);
+ wid_reg_val &= ~dac_db_bit;
+#ifdef USE_FAST_SWAP
+ DACCFG_WRITE(dac, active_dac_addr, wid_reg_val);
+#else
+ DACCFG_WRITE(dac, shadow_dac_addr, wid_reg_val);
+
+ /* Schedule the window transfer. */
+ DACCFG_WRITE(dac, FFBDAC_CFG_WTCTRL,
+ (FFBDAC_CFG_WTCTRL_TCMD | FFBDAC_CFG_WTCTRL_TE));
+
+ {
+ int limit = 1000000;
+ while (limit--) {
+ unsigned int wtctrl = DACCFG_READ(dac, FFBDAC_CFG_WTCTRL);
+
+ if ((wtctrl & FFBDAC_CFG_WTCTRL_DS) == 0)
+ break;
+ }
+ }
+#endif
+}
+
+/* Force the context `c' to be the current context and associate with it
+ buffer `b' */
+static GLboolean
+ffbMakeCurrent(__DRIcontextPrivate *driContextPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ __DRIdrawablePrivate *driReadPriv)
+{
+ if (driContextPriv) {
+ ffbContextPtr fmesa = (ffbContextPtr) driContextPriv->driverPrivate;
+ int first_time;
+
+ fmesa->driDrawable = driDrawPriv;
+
+ _mesa_make_current2(fmesa->glCtx,
+ (GLframebuffer *) driDrawPriv->driverPrivate,
+ (GLframebuffer *) driReadPriv->driverPrivate);
+
+ if (!fmesa->glCtx->Viewport.Width)
+ _mesa_set_viewport(fmesa->glCtx,
+ 0, 0,
+ driDrawPriv->w,
+ driDrawPriv->h);
+
+ first_time = 0;
+ if (fmesa->wid == ~0) {
+ first_time = 1;
+ if (getenv("LIBGL_SOFTWARE_RENDERING"))
+ FALLBACK( fmesa->glCtx, FFB_BADATTR_SWONLY, GL_TRUE );
+ }
+
+ LOCK_HARDWARE(fmesa);
+ if (first_time) {
+ fmesa->wid = fmesa->ffb_sarea->wid_table[driDrawPriv->index];
+ ffb_init_wid(fmesa, fmesa->wid);
+ }
+
+ fmesa->state_dirty |= FFB_STATE_ALL;
+ fmesa->state_fifo_ents = fmesa->state_all_fifo_ents;
+ ffbSyncHardware(fmesa);
+ UNLOCK_HARDWARE(fmesa);
+
+ if (first_time) {
+ /* Also, at the first switch to a new context,
+ * we need to clear all the hw buffers.
+ */
+ ffbDDClear(fmesa->glCtx,
+ (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT |
+ DD_DEPTH_BIT | DD_STENCIL_BIT),
+ 1, 0, 0, 0, 0);
+ }
+ } else {
+ _mesa_make_current(NULL, NULL);
+ }
+
+ return GL_TRUE;
+}
+
+/* Force the context `c' to be unbound from its buffer */
+static GLboolean
+ffbUnbindContext(__DRIcontextPrivate *driContextPriv)
+{
+ return GL_TRUE;
+}
+
+static GLboolean
+ffbOpenFullScreen(__DRIcontextPrivate *driContextPriv)
+{
+ return GL_TRUE;
+}
+
+static GLboolean
+ffbCloseFullScreen(__DRIcontextPrivate *driContextPriv)
+{
+ return GL_TRUE;
+}
+
+void ffbXMesaUpdateState(ffbContextPtr fmesa)
+{
+ __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
+ __DRIscreenPrivate *sPriv = fmesa->driScreen;
+ int stamp = dPriv->lastStamp;
+
+ DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
+
+ if (dPriv->lastStamp != stamp) {
+ GLcontext *ctx = fmesa->glCtx;
+
+ ffbCalcViewport(ctx);
+ if (ctx->Polygon.StippleFlag)
+ ffbXformAreaPattern(fmesa,
+ (const GLubyte *)ctx->PolygonStipple);
+ }
+}
+
+
+static struct __DriverAPIRec ffbAPI = {
+ ffbInitDriver,
+ ffbDestroyScreen,
+ ffbCreateContext,
+ ffbDestroyContext,
+ ffbCreateBuffer,
+ ffbDestroyBuffer,
+ ffbSwapBuffers,
+ ffbMakeCurrent,
+ ffbUnbindContext,
+ ffbOpenFullScreen,
+ ffbCloseFullScreen
+};
+
+
+
+/*
+ * This is the bootstrap function for the driver.
+ * The __driCreateScreen name is the symbol that libGL.so fetches.
+ * Return: pointer to a __DRIscreenPrivate.
+ */
+void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
+ int numConfigs, __GLXvisualConfig *config)
+{
+ __DRIscreenPrivate *psp;
+ psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &ffbAPI);
+ return (void *) psp;
+}
+
+
+#endif /* GLX_DIRECT_RENDERING */