OSDN Git Service

Not-quite-functional swrast-only dri driver
authorKeith Whitwell <keith@tungstengraphics.com>
Wed, 6 Aug 2003 18:11:57 +0000 (18:11 +0000)
committerKeith Whitwell <keith@tungstengraphics.com>
Wed, 6 Aug 2003 18:11:57 +0000 (18:11 +0000)
src/mesa/drivers/dri/fb/Doxyfile [new file with mode: 0644]
src/mesa/drivers/dri/fb/Makefile.X11 [new file with mode: 0644]
src/mesa/drivers/dri/fb/fb_dri.c [new file with mode: 0644]

diff --git a/src/mesa/drivers/dri/fb/Doxyfile b/src/mesa/drivers/dri/fb/Doxyfile
new file mode 100644 (file)
index 0000000..31256db
--- /dev/null
@@ -0,0 +1,232 @@
+# Doxyfile 1.3.2-Gideon
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME           = fb
+PROJECT_NUMBER         = $VERSION$
+OUTPUT_DIRECTORY       = 
+OUTPUT_LANGUAGE        = English
+USE_WINDOWS_ENCODING   = NO
+EXTRACT_ALL            = NO
+EXTRACT_PRIVATE        = NO
+EXTRACT_STATIC         = NO
+EXTRACT_LOCAL_CLASSES  = YES
+HIDE_UNDOC_MEMBERS     = NO
+HIDE_UNDOC_CLASSES     = NO
+HIDE_FRIEND_COMPOUNDS  = NO
+HIDE_IN_BODY_DOCS      = NO
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ALWAYS_DETAILED_SEC    = NO
+INLINE_INHERITED_MEMB  = NO
+FULL_PATH_NAMES        = NO
+STRIP_FROM_PATH        = 
+INTERNAL_DOCS          = NO
+CASE_SENSE_NAMES       = YES
+SHORT_NAMES            = NO
+HIDE_SCOPE_NAMES       = NO
+SHOW_INCLUDE_FILES     = YES
+JAVADOC_AUTOBRIEF      = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP         = NO
+INHERIT_DOCS           = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = YES
+DISTRIBUTE_GROUP_DOC   = NO
+TAB_SIZE               = 8
+GENERATE_TODOLIST      = YES
+GENERATE_TESTLIST      = YES
+GENERATE_BUGLIST       = YES
+GENERATE_DEPRECATEDLIST= YES
+ALIASES                = 
+ENABLED_SECTIONS       = 
+MAX_INITIALIZER_LINES  = 30
+OPTIMIZE_OUTPUT_FOR_C  = NO
+OPTIMIZE_OUTPUT_JAVA   = NO
+SHOW_USED_FILES        = YES
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = NO
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_IF_DOC_ERROR      = YES
+WARN_FORMAT            = "$file:$line: $text"
+WARN_LOGFILE           = 
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT                  = /home/temp/Mesa/src/drv/fb
+FILE_PATTERNS          = *.c \
+                         *.cc \
+                         *.cxx \
+                         *.cpp \
+                         *.c++ \
+                         *.java \
+                         *.ii \
+                         *.ixx \
+                         *.ipp \
+                         *.i++ \
+                         *.inl \
+                         *.h \
+                         *.hh \
+                         *.hxx \
+                         *.hpp \
+                         *.h++ \
+                         *.idl \
+                         *.odl \
+                         *.cs \
+                         *.C \
+                         *.H \
+                         *.tlh \
+                         *.diff \
+                         *.patch \
+                         *.moc \
+                         *.xpm
+RECURSIVE              = yes
+EXCLUDE                = 
+EXCLUDE_SYMLINKS       = NO
+EXCLUDE_PATTERNS       = 
+EXAMPLE_PATH           = 
+EXAMPLE_PATTERNS       = *
+EXAMPLE_RECURSIVE      = NO
+IMAGE_PATH             = 
+INPUT_FILTER           = 
+FILTER_SOURCE_FILES    = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER         = NO
+INLINE_SOURCES         = NO
+STRIP_CODE_COMMENTS    = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION    = YES
+VERBATIM_HEADERS       = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = NO
+COLS_IN_ALPHA_INDEX    = 5
+IGNORE_PREFIX          = 
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML          = YES
+HTML_OUTPUT            = html
+HTML_FILE_EXTENSION    = .html
+HTML_HEADER            = 
+HTML_FOOTER            = 
+HTML_STYLESHEET        = 
+HTML_ALIGN_MEMBERS     = YES
+GENERATE_HTMLHELP      = NO
+CHM_FILE               = 
+HHC_LOCATION           = 
+GENERATE_CHI           = NO
+BINARY_TOC             = NO
+TOC_EXPAND             = NO
+DISABLE_INDEX          = NO
+ENUM_VALUES_PER_LINE   = 4
+GENERATE_TREEVIEW      = NO
+TREEVIEW_WIDTH         = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX         = YES
+LATEX_OUTPUT           = latex
+LATEX_CMD_NAME         = latex
+MAKEINDEX_CMD_NAME     = makeindex
+COMPACT_LATEX          = NO
+PAPER_TYPE             = a4wide
+EXTRA_PACKAGES         = 
+LATEX_HEADER           = 
+PDF_HYPERLINKS         = NO
+USE_PDFLATEX           = NO
+LATEX_BATCHMODE        = NO
+LATEX_HIDE_INDICES     = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF           = NO
+RTF_OUTPUT             = rtf
+COMPACT_RTF            = NO
+RTF_HYPERLINKS         = NO
+RTF_STYLESHEET_FILE    = 
+RTF_EXTENSIONS_FILE    = 
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = NO
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3
+MAN_LINKS              = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML           = yes
+XML_OUTPUT             = xml
+XML_SCHEMA             = 
+XML_DTD                = 
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF   = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD       = NO
+PERLMOD_LATEX          = NO
+PERLMOD_PRETTY         = YES
+PERLMOD_MAKEVAR_PREFIX = 
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = NO
+EXPAND_ONLY_PREDEF     = NO
+SEARCH_INCLUDES        = YES
+INCLUDE_PATH           = 
+INCLUDE_FILE_PATTERNS  = 
+PREDEFINED             = 
+EXPAND_AS_DEFINED      = 
+SKIP_FUNCTION_MACROS   = YES
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references   
+#---------------------------------------------------------------------------
+TAGFILES               = 
+GENERATE_TAGFILE       = 
+ALLEXTERNALS           = NO
+EXTERNAL_GROUPS        = YES
+PERL_PATH              = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS         = YES
+HIDE_UNDOC_RELATIONS   = YES
+HAVE_DOT               = NO
+CLASS_GRAPH            = YES
+COLLABORATION_GRAPH    = YES
+UML_LOOK               = NO
+TEMPLATE_RELATIONS     = NO
+INCLUDE_GRAPH          = YES
+INCLUDED_BY_GRAPH      = YES
+CALL_GRAPH             = NO
+GRAPHICAL_HIERARCHY    = YES
+DOT_IMAGE_FORMAT       = png
+DOT_PATH               = 
+DOTFILE_DIRS           = 
+MAX_DOT_GRAPH_WIDTH    = 1024
+MAX_DOT_GRAPH_HEIGHT   = 1024
+MAX_DOT_GRAPH_DEPTH    = 1000
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine   
+#---------------------------------------------------------------------------
+SEARCHENGINE           = NO
+CGI_NAME               = search.cgi
+CGI_URL                = 
+DOC_URL                = 
+DOC_ABSPATH            = 
+BIN_ABSPATH            = /usr/local/bin/
+EXT_DOC_PATHS          = 
diff --git a/src/mesa/drivers/dri/fb/Makefile.X11 b/src/mesa/drivers/dri/fb/Makefile.X11
new file mode 100644 (file)
index 0000000..feca4e9
--- /dev/null
@@ -0,0 +1,83 @@
+# $Id: Makefile.X11,v 1.1 2003/08/06 18:11:57 keithw Exp $
+
+# Mesa 3-D graphics library
+# Version:  5.0
+# Copyright (C) 1995-2002  Brian Paul
+
+TOP = ../../../../..
+
+SHARED_INCLUDES = $(INCLUDE_DIRS) -I. -I../common -Iserver
+MINIGLX_INCLUDES = -I$(TOP)/src/miniglx 
+
+MESA_MODULES = $(TOP)/src/mesa/mesa.a
+
+DRIVER_SOURCES = fb_dri.c
+
+
+C_SOURCES = $(DRIVER_SOURCES) \
+           $(DRI_SOURCES) 
+
+ASM_SOURCES = 
+
+OBJECTS = $(C_SOURCES:.c=.o) \
+         $(ASM_SOURCES:.S=.o) 
+
+
+ifeq ($(WINDOW_SYSTEM),dri)
+default2: clean
+else
+default2: fb_dri.so
+endif
+
+
+### Include directories
+
+INCLUDE_DIRS = \
+       -I$(TOP)/include \
+       -I$(TOP)/src/mesa \
+       -I$(TOP)/src/mesa/main \
+       -I$(TOP)/src/mesa/glapi \
+       -I$(TOP)/src/mesa/math \
+       -I$(TOP)/src/mesa/transform \
+       -I$(TOP)/src/mesa/swrast \
+       -I$(TOP)/src/mesa/swrast_setup
+
+
+##### RULES #####
+
+.c.o:
+       $(CC) -c $(SHARED_INCLUDES) $(MINIGLX_INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
+
+.S.o:
+       $(CC) -c $(SHARED_INCLUDES) $(MINIGLX_INCLUDES) $(CFLAGS) $(DEFINES)  $< -o $@
+
+
+##### TARGETS #####
+
+targets: fb_dri.so
+
+fb_dri.so:  $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile.X11
+       rm -f $@ && gcc -o $@ -shared $(OBJECTS) $(MESA_MODULES) $(WINOBJ) $(WINLIB) -lc -lm
+       rm -f $(TOP)/lib/fb_dri.so && \
+       install fb_dri.so $(TOP)/lib/fb_dri.so
+
+# Run 'make -f Makefile.X11 dep' to update the dependencies if you change
+# what's included by any source file.
+dep: $(C_SOURCES) $(ASM_SOURCES)
+       makedepend -fdepend -Y $(SHARED_INCLUDES) \
+               $(C_SOURCES) $(ASM_SOURCES)
+
+
+# Emacs tags
+tags:
+       etags `find . -name \*.[ch]` `find ../include`
+
+
+# Remove .o and backup files
+clean:
+       -rm -f *.o *~ *.o *~ *.so
+
+
+include $(TOP)/Make-config
+
+include depend
diff --git a/src/mesa/drivers/dri/fb/fb_dri.c b/src/mesa/drivers/dri/fb/fb_dri.c
new file mode 100644 (file)
index 0000000..945a78f
--- /dev/null
@@ -0,0 +1,729 @@
+/* $Id: fb_dri.c,v 1.1 2003/08/06 18:11:57 keithw Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  4.1
+ *
+ * Copyright (C) 1999-2002  Brian Paul   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 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
+ * BRIAN PAUL 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.
+ */
+
+
+/* Minimal swrast-based dri loadable driver.
+ *
+ * Todo:
+ *   -- Use malloced (rather than framebuffer) memory for backbuffer
+ *   -- 32bpp is hardwared -- fix
+ *
+ * NOTES:
+ *   -- No mechanism for cliprects or resize notification --
+ *      assumes this is a fullscreen device.  
+ *   -- No locking -- assumes this is the only driver accessing this 
+ *      device.
+ *   -- Doesn't (yet) make use of any acceleration or other interfaces
+ *      provided by fb.  Would be entirely happy working against any 
+ *     fullscreen interface.
+ *   -- HOWEVER: only a small number of pixelformats are supported, and
+ *      the mechanism for choosing between them makes some assumptions
+ *      that may not be valid everywhere.
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+#include <linux/kd.h>
+#include <linux/vt.h>
+
+#include "GL/miniglx.h"         /* window-system-specific */
+#include "miniglxP.h"          /* window-system-specific */
+#include "dri_util.h"          /* window-system-specific-ish */
+
+#include "context.h"
+#include "extensions.h"
+#include "imports.h"
+#include "matrix.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "teximage.h"
+#include "array_cache/acache.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+
+
+typedef struct {
+   GLcontext *glCtx;           /* Mesa context */
+
+   struct {
+      __DRIcontextPrivate *context;    
+      __DRIscreenPrivate *screen;      
+      __DRIdrawablePrivate *drawable; /* drawable bound to this ctx */
+   } dri;
+} fbContext, *fbContextPtr;
+
+
+#define FB_CONTEXT(ctx)                ((fbContextPtr)(ctx->DriverCtx))
+
+
+static const GLubyte *
+get_string(GLcontext *ctx, GLenum pname)
+{
+   (void) ctx;
+   switch (pname) {
+      case GL_RENDERER:
+         return (const GLubyte *) "Mesa dumb framebuffer";
+      default:
+         return NULL;
+   }
+}
+
+
+static void
+update_state( GLcontext *ctx, GLuint new_state )
+{
+   /* not much to do here - pass it on */
+   _swrast_InvalidateState( ctx, new_state );
+   _swsetup_InvalidateState( ctx, new_state );
+   _ac_InvalidateState( ctx, new_state );
+   _tnl_InvalidateState( ctx, new_state );
+}
+
+
+static void
+get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   fbContextPtr fbmesa = FB_CONTEXT(ctx);
+
+   *width  = fbmesa->dri.drawable->w;
+   *height = fbmesa->dri.drawable->h;
+}
+
+
+/* specifies the buffer for swrast span rendering/reading */
+static void
+set_buffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit )
+{
+   fbContextPtr fbdevctx = FB_CONTEXT(ctx);
+   __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable;
+    
+   /* What a twisted mess of private structs
+    */
+   assert(buffer == dPriv->driverPrivate);
+
+
+   switch (bufferBit) {
+   case FRONT_LEFT_BIT:
+      dPriv->currentBuffer = dPriv->frontBuffer;
+      break;
+   case BACK_LEFT_BIT:
+      dPriv->currentBuffer = dPriv->backBuffer;
+      break;
+   default:
+      /* This happens a lot if the client renders to the frontbuffer */
+      if (0) _mesa_problem(ctx, "bad bufferBit in set_buffer()");
+   }
+}
+
+
+static void
+init_core_functions( GLcontext *ctx )
+{
+   ctx->Driver.GetString = get_string;
+   ctx->Driver.UpdateState = update_state;
+   ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
+   ctx->Driver.GetBufferSize = get_buffer_size;
+
+   ctx->Driver.Accum = _swrast_Accum;
+   ctx->Driver.Bitmap = _swrast_Bitmap;
+   ctx->Driver.Clear = _swrast_Clear;  /* could accelerate with blits */
+   ctx->Driver.CopyPixels = _swrast_CopyPixels;
+   ctx->Driver.DrawPixels = _swrast_DrawPixels;
+   ctx->Driver.ReadPixels = _swrast_ReadPixels;
+   ctx->Driver.DrawBuffer = _swrast_DrawBuffer;
+
+   ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format;
+   ctx->Driver.TexImage1D = _mesa_store_teximage1d;
+   ctx->Driver.TexImage2D = _mesa_store_teximage2d;
+   ctx->Driver.TexImage3D = _mesa_store_teximage3d;
+   ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
+   ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d;
+   ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
+   ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
+
+   ctx->Driver.CompressedTexImage1D = _mesa_store_compressed_teximage1d;
+   ctx->Driver.CompressedTexImage2D = _mesa_store_compressed_teximage2d;
+   ctx->Driver.CompressedTexImage3D = _mesa_store_compressed_teximage3d;
+   ctx->Driver.CompressedTexSubImage1D = _mesa_store_compressed_texsubimage1d;
+   ctx->Driver.CompressedTexSubImage2D = _mesa_store_compressed_texsubimage2d;
+   ctx->Driver.CompressedTexSubImage3D = _mesa_store_compressed_texsubimage3d;
+
+   ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
+   ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
+   ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
+   ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
+   ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
+   ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
+   ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
+   ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
+   ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
+}
+
+
+/*
+ * Generate code for span functions.
+ */
+
+/* 24-bit BGR */
+#define NAME(PREFIX) PREFIX##_B8G8R8
+#define SPAN_VARS \
+   const fbContextPtr fbdevctx = FB_CONTEXT(ctx); \
+   __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable; 
+#define INIT_PIXEL_PTR(P, X, Y) \
+   GLubyte *P = (char *)dPriv->currentBuffer + (Y) * dPriv->currentPitch + (X) * 3
+#define INC_PIXEL_PTR(P) P += 3
+#define STORE_RGB_PIXEL(P, R, G, B) \
+   P[0] = B;  P[1] = G;  P[2] = R
+#define STORE_RGBA_PIXEL(P, R, G, B, A) \
+   P[0] = B;  P[1] = G;  P[2] = R
+#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
+   R = P[2];  G = P[1];  B = P[0];  A = CHAN_MAX
+
+#include "swrast/s_spantemp.h"
+
+
+/* 32-bit BGRA */
+#define NAME(PREFIX) PREFIX##_B8G8R8A8
+#define SPAN_VARS \
+   const fbContextPtr fbdevctx = FB_CONTEXT(ctx); \
+   __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable; 
+#define INIT_PIXEL_PTR(P, X, Y) \
+   GLubyte *P = (char *)dPriv->currentBuffer + (Y) * dPriv->currentPitch + (X) * 4;
+#define INC_PIXEL_PTR(P) P += 4
+#define STORE_RGB_PIXEL(P, R, G, B) \
+   P[0] = B;  P[1] = G;  P[2] = R;  P[3] = 255
+#define STORE_RGBA_PIXEL(P, R, G, B, A) \
+   P[0] = B;  P[1] = G;  P[2] = R;  P[3] = A
+#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
+   R = P[2];  G = P[1];  B = P[0];  A = P[3]
+
+#include "swrast/s_spantemp.h"
+
+
+/* 16-bit BGR (XXX implement dithering someday) */
+#define NAME(PREFIX) PREFIX##_B5G6R5
+#define SPAN_VARS \
+   const fbContextPtr fbdevctx = FB_CONTEXT(ctx); \
+   __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable;
+#define INIT_PIXEL_PTR(P, X, Y) \
+   GLushort *P = (GLushort *) ((char *)dPriv->currentBuffer + (Y) * dPriv->currentPitch + (X) * 2)
+#define INC_PIXEL_PTR(P) P += 1
+#define STORE_RGB_PIXEL(P, R, G, B) \
+   *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
+#define STORE_RGBA_PIXEL(P, R, G, B, A) \
+   *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
+#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
+   R = ( (((*P) >> 8) & 0xf8) | (((*P) >> 11) & 0x7) ); \
+   G = ( (((*P) >> 3) & 0xfc) | (((*P) >>  5) & 0x3) ); \
+   B = ( (((*P) << 3) & 0xf8) | (((*P)      ) & 0x7) ); \
+   A = CHAN_MAX
+
+#include "swrast/s_spantemp.h"
+
+
+/* 15-bit BGR (XXX implement dithering someday) */
+#define NAME(PREFIX) PREFIX##_B5G5R5
+#define SPAN_VARS \
+   const fbContextPtr fbdevctx = FB_CONTEXT(ctx); \
+   __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable;
+#define INIT_PIXEL_PTR(P, X, Y) \
+   GLushort *P = (GLushort *) ((char *)dPriv->currentBuffer + (Y) * dPriv->currentPitch + (X) * 2)
+#define INC_PIXEL_PTR(P) P += 1
+#define STORE_RGB_PIXEL(P, R, G, B) \
+   *P = ( (((R) & 0xf8) << 7) | (((G) & 0xf8) << 2) | ((B) >> 3) )
+#define STORE_RGBA_PIXEL(P, R, G, B, A) \
+   *P = ( (((R) & 0xf8) << 7) | (((G) & 0xf8) << 2) | ((B) >> 3) )
+#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
+   R = ( (((*P) >> 7) & 0xf8) | (((*P) >> 10) & 0x7) ); \
+   G = ( (((*P) >> 2) & 0xf8) | (((*P) >>  5) & 0x7) ); \
+   B = ( (((*P) << 3) & 0xf8) | (((*P)      ) & 0x7) ); \
+   A = CHAN_MAX
+
+#include "swrast/s_spantemp.h"
+
+
+/* 8-bit color index */
+#define NAME(PREFIX) PREFIX##_CI8
+#define SPAN_VARS \
+   const fbContextPtr fbdevctx = FB_CONTEXT(ctx); \
+   __DRIdrawablePrivate *dPriv = fbdevctx->dri.drawable;
+#define INIT_PIXEL_PTR(P, X, Y) \
+   GLubyte *P = (char *)dPriv->currentBuffer + (Y) * dPriv->currentPitch + (X)
+#define INC_PIXEL_PTR(P) P += 1
+#define STORE_CI_PIXEL(P, CI) \
+   P[0] = CI
+#define FETCH_CI_PIXEL(CI, P) \
+   CI = P[0]
+
+#include "swrast/s_spantemp.h"
+
+
+
+/* Initialize the driver specific screen private data.
+ */
+static GLboolean
+fbInitDriver( __DRIscreenPrivate *sPriv )
+{
+   sPriv->private = NULL;
+   return GL_TRUE;
+}
+
+static void
+fbDestroyScreen( __DRIscreenPrivate *sPriv )
+{
+}
+
+/* Create the device specific context.
+ */
+static GLboolean
+fbCreateContext( const __GLcontextModes *glVisual,
+                __DRIcontextPrivate *driContextPriv,
+                void *sharedContextPrivate)
+{
+   fbContextPtr fbmesa;
+   GLcontext *ctx, *shareCtx;
+
+   assert(glVisual);
+   assert(driContextPriv);
+
+   /* Allocate the Fb context */
+   fbmesa = (fbContextPtr) CALLOC( sizeof(*fbmesa) );
+   if ( !fbmesa )
+      return GL_FALSE;
+
+   /* Allocate the Mesa context */
+   if (sharedContextPrivate)
+      shareCtx = ((fbContextPtr) sharedContextPrivate)->glCtx;
+   else
+      shareCtx = NULL;
+
+   ctx = fbmesa->glCtx = _mesa_create_context(glVisual, shareCtx, 
+                                             (void *) fbmesa, 
+                                             GL_TRUE);
+   if (!fbmesa->glCtx) {
+      FREE(fbmesa);
+      return GL_FALSE;
+   }
+   driContextPriv->driverPrivate = fbmesa;
+
+   /* Create module contexts */
+   init_core_functions( ctx );
+   _swrast_CreateContext( ctx );
+   _ac_CreateContext( ctx );
+   _tnl_CreateContext( ctx );
+   _swsetup_CreateContext( ctx );
+   _swsetup_Wakeup( ctx );
+
+
+
+   /* swrast init -- need to verify these tests - I just plucked the
+    * numbers out of the air.  (KW)
+    */
+   {
+      struct swrast_device_driver *swdd;
+      swdd = _swrast_GetDeviceDriverReference( ctx );
+      swdd->SetBuffer = set_buffer;
+      if (!glVisual->rgbMode) {
+         swdd->WriteCI32Span = write_index32_span_CI8;
+         swdd->WriteCI8Span = write_index8_span_CI8;
+         swdd->WriteMonoCISpan = write_monoindex_span_CI8;
+         swdd->WriteCI32Pixels = write_index_pixels_CI8;
+         swdd->WriteMonoCIPixels = write_monoindex_pixels_CI8;
+         swdd->ReadCI32Span = read_index_span_CI8;
+         swdd->ReadCI32Pixels = read_index_pixels_CI8;
+      }
+      else if (glVisual->rgbBits == 24 &&
+              glVisual->alphaBits == 0) {
+         swdd->WriteRGBASpan = write_rgba_span_B8G8R8;
+         swdd->WriteRGBSpan = write_rgb_span_B8G8R8;
+         swdd->WriteMonoRGBASpan = write_monorgba_span_B8G8R8;
+         swdd->WriteRGBAPixels = write_rgba_pixels_B8G8R8;
+         swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B8G8R8;
+         swdd->ReadRGBASpan = read_rgba_span_B8G8R8;
+         swdd->ReadRGBAPixels = read_rgba_pixels_B8G8R8;
+      }
+      else if (glVisual->rgbBits == 32 &&
+              glVisual->alphaBits == 8) {
+         swdd->WriteRGBASpan = write_rgba_span_B8G8R8A8;
+         swdd->WriteRGBSpan = write_rgb_span_B8G8R8A8;
+         swdd->WriteMonoRGBASpan = write_monorgba_span_B8G8R8A8;
+         swdd->WriteRGBAPixels = write_rgba_pixels_B8G8R8A8;
+         swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B8G8R8A8;
+         swdd->ReadRGBASpan = read_rgba_span_B8G8R8A8;
+         swdd->ReadRGBAPixels = read_rgba_pixels_B8G8R8A8;
+      }
+      else if (glVisual->rgbBits == 16 &&
+              glVisual->alphaBits == 0) {
+         swdd->WriteRGBASpan = write_rgba_span_B5G6R5;
+         swdd->WriteRGBSpan = write_rgb_span_B5G6R5;
+         swdd->WriteMonoRGBASpan = write_monorgba_span_B5G6R5;
+         swdd->WriteRGBAPixels = write_rgba_pixels_B5G6R5;
+         swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B5G6R5;
+         swdd->ReadRGBASpan = read_rgba_span_B5G6R5;
+         swdd->ReadRGBAPixels = read_rgba_pixels_B5G6R5;
+      }
+      else if (glVisual->rgbBits == 15 &&
+              glVisual->alphaBits == 0) {
+         swdd->WriteRGBASpan = write_rgba_span_B5G5R5;
+         swdd->WriteRGBSpan = write_rgb_span_B5G5R5;
+         swdd->WriteMonoRGBASpan = write_monorgba_span_B5G5R5;
+         swdd->WriteRGBAPixels = write_rgba_pixels_B5G5R5;
+         swdd->WriteMonoRGBAPixels = write_monorgba_pixels_B5G5R5;
+         swdd->ReadRGBASpan = read_rgba_span_B5G5R5;
+         swdd->ReadRGBAPixels = read_rgba_pixels_B5G5R5;
+      }
+      else {
+         _mesa_printf("bad pixelformat rgb %d alpha %d\n",
+                     glVisual->rgbBits, 
+                     glVisual->alphaBits );
+      }
+   }
+
+   /* use default TCL pipeline */
+   {
+      TNLcontext *tnl = TNL_CONTEXT(ctx);
+      tnl->Driver.RunPipeline = _tnl_run_pipeline;
+   }
+
+   _mesa_enable_sw_extensions(ctx);
+
+   return GL_TRUE;
+}
+
+
+static void
+fbDestroyContext( __DRIcontextPrivate *driContextPriv )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   fbContextPtr fbmesa = (fbContextPtr) driContextPriv->driverPrivate;
+   fbContextPtr current = ctx ? FB_CONTEXT(ctx) : NULL;
+
+   /* check if we're deleting the currently bound context */
+   if (fbmesa == current) {
+      _mesa_make_current2(NULL, NULL, NULL);
+   }
+
+   /* Free fb context resources */
+   if ( fbmesa ) {
+      _swsetup_DestroyContext( fbmesa->glCtx );
+      _tnl_DestroyContext( fbmesa->glCtx );
+      _ac_DestroyContext( fbmesa->glCtx );
+      _swrast_DestroyContext( fbmesa->glCtx );
+
+      /* free the Mesa context */
+      fbmesa->glCtx->DriverCtx = NULL;
+      _mesa_destroy_context( fbmesa->glCtx );
+
+      FREE( fbmesa );
+   }
+}
+
+
+/* Create and initialize the Mesa and driver specific pixmap buffer
+ * data.
+ */
+static GLboolean
+fbCreateBuffer( __DRIscreenPrivate *driScrnPriv,
+               __DRIdrawablePrivate *driDrawPriv,
+               const __GLcontextModes *mesaVis,
+               GLboolean isPixmap )
+{
+   if (isPixmap) {
+      return GL_FALSE; /* not implemented */
+   }
+   else {
+      const GLboolean swDepth = mesaVis->depthBits > 0;
+      const GLboolean swAlpha = mesaVis->alphaBits > 0;
+      const GLboolean swAccum = mesaVis->accumRedBits > 0;
+      const GLboolean swStencil = mesaVis->stencilBits > 0;
+      driDrawPriv->driverPrivate = (void *)
+         _mesa_create_framebuffer( mesaVis,
+                                   swDepth,
+                                   swStencil,
+                                   swAccum,
+                                   swAlpha );
+
+      if (!driDrawPriv->driverPrivate)
+        return 0;
+      
+      /* Replace the framebuffer back buffer with a malloc'ed one --
+       * big speedup.
+       */
+      if (driDrawPriv->backBuffer)
+        driDrawPriv->backBuffer = malloc(driDrawPriv->currentPitch * driDrawPriv->h);
+
+      return 1;
+   }
+}
+
+
+
+
+static void
+fbDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
+{
+   _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
+   free(driDrawPriv->backBuffer);
+}
+
+
+
+/* If the backbuffer is on a videocard, this is extraordinarily slow!
+ */
+static void
+fbSwapBuffers( __DRIdrawablePrivate *dPriv )
+{
+
+   if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+      fbContextPtr fbmesa;
+      GLcontext *ctx;
+      fbmesa = (fbContextPtr) dPriv->driContextPriv->driverPrivate;
+      ctx = fbmesa->glCtx;
+      if (ctx->Visual.doubleBufferMode) {
+        int i;
+        int offset = 0;
+        char *tmp = malloc( dPriv->currentPitch );
+
+         _mesa_notifySwapBuffers( ctx );  /* flush pending rendering comands */
+
+        ASSERT(dPriv->frontBuffer);
+        ASSERT(dPriv->backBuffer);
+
+
+        for (i = 0 ; i < dPriv->h ; i++ ) {
+           memcpy( tmp, (char *)dPriv->frontBuffer + offset, dPriv->currentPitch );
+           memcpy( (char *)dPriv->backBuffer + offset, tmp, dPriv->currentPitch );
+           offset += dPriv->currentPitch;
+        }
+           
+        free( tmp );
+      }
+   }
+   else {
+      /* XXX this shouldn't be an error but we can't handle it for now */
+      _mesa_problem(NULL, "fbSwapBuffers: drawable has no context!\n");
+   }
+}
+
+
+/* Force the context `c' to be the current context and associate with it
+ * buffer `b'.
+ */
+static GLboolean
+fbMakeCurrent( __DRIcontextPrivate *driContextPriv,
+              __DRIdrawablePrivate *driDrawPriv,
+              __DRIdrawablePrivate *driReadPriv )
+{
+   if ( driContextPriv ) {
+      fbContextPtr newFbCtx = 
+        (fbContextPtr) driContextPriv->driverPrivate;
+
+      newFbCtx->dri.drawable = driDrawPriv;
+
+      _mesa_make_current2( newFbCtx->glCtx,
+                          (GLframebuffer *) driDrawPriv->driverPrivate,
+                          (GLframebuffer *) driReadPriv->driverPrivate );
+
+      if ( !newFbCtx->glCtx->Viewport.Width ) {
+        _mesa_set_viewport( newFbCtx->glCtx, 0, 0,
+                            driDrawPriv->w, driDrawPriv->h );
+      }
+   } else {
+      _mesa_make_current( 0, 0 );
+   }
+
+   return GL_TRUE;
+}
+
+
+/* Force the context `c' to be unbound from its buffer.
+ */
+static GLboolean
+fbUnbindContext( __DRIcontextPrivate *driContextPriv )
+{
+   return GL_TRUE;
+}
+
+static GLboolean
+fbOpenCloseFullScreen( __DRIcontextPrivate *driContextPriv )
+{
+   return GL_TRUE;
+}
+
+static struct __DriverAPIRec fbAPI = {
+   fbInitDriver,
+   fbDestroyScreen,
+   fbCreateContext,
+   fbDestroyContext,
+   fbCreateBuffer,
+   fbDestroyBuffer,
+   fbSwapBuffers,
+   fbMakeCurrent,
+   fbUnbindContext,
+   fbOpenCloseFullScreen,
+   fbOpenCloseFullScreen
+};
+
+
+void
+__driRegisterExtensions( void )
+{
+}
+
+
+
+
+/*
+ * 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(struct DRIDriverRec *driver,
+                        struct DRIDriverContextRec *driverContext)
+{
+   __DRIscreenPrivate *psp;
+   psp = __driUtilCreateScreenNoDRM(driver, driverContext, &fbAPI);
+   return (void *) psp;
+}
+
+
+/**
+ * \brief Establish the set of modes available for the display.
+ *
+ * \param ctx display handle.
+ * \param numModes will receive the number of supported modes.
+ * \param modes will point to the list of supported modes.
+ *
+ * \return one on success, or zero on failure.
+ * 
+ * Allocates a single visual and fills it with information according to the
+ * display bit depth. Supports only 16 and 32 bpp bit depths, aborting
+ * otherwise.
+ */
+const __GLcontextModes __glModes[] = {
+    
+    /* 32 bit, RGBA Depth=24 Stencil=8 */
+    {.rgbMode = GL_TRUE, .colorIndexMode = GL_FALSE, .doubleBufferMode = GL_TRUE, .stereoMode = GL_FALSE,
+     .haveAccumBuffer = GL_FALSE, .haveDepthBuffer = GL_TRUE, .haveStencilBuffer = GL_TRUE,
+     .redBits = 8, .greenBits = 8, .blueBits = 8, .alphaBits = 8,
+     .redMask = 0xff0000, .greenMask = 0xff00, .blueMask = 0xff, .alphaMask = 0xff000000,
+     .rgbBits = 32, .indexBits = 0,
+     .accumRedBits = 0, .accumGreenBits = 0, .accumBlueBits = 0, .accumAlphaBits = 0,
+     .depthBits = 24, .stencilBits = 8,
+     .numAuxBuffers= 0, .level = 0, .pixmapMode = GL_FALSE, },
+
+    /* 16 bit, RGB Depth=16 */
+    {.rgbMode = GL_TRUE, .colorIndexMode = GL_FALSE, .doubleBufferMode = GL_TRUE, .stereoMode = GL_FALSE,
+     .haveAccumBuffer = GL_FALSE, .haveDepthBuffer = GL_TRUE, .haveStencilBuffer = GL_FALSE,
+     .redBits = 5, .greenBits = 6, .blueBits = 5, .alphaBits = 0,
+     .redMask = 0xf800, .greenMask = 0x07e0, .blueMask = 0x001f, .alphaMask = 0x0,
+     .rgbBits = 16, .indexBits = 0,
+     .accumRedBits = 0, .accumGreenBits = 0, .accumBlueBits = 0, .accumAlphaBits = 0,
+     .depthBits = 16, .stencilBits = 0,
+     .numAuxBuffers= 0, .level = 0, .pixmapMode = GL_FALSE, },
+};
+static int __driInitScreenModes( const DRIDriverContext *ctx,
+                                  int *numModes, const __GLcontextModes **modes)
+{
+   *numModes = sizeof(__glModes)/sizeof(__GLcontextModes *);
+   *modes = &__glModes[0];
+   return 1;
+}
+
+
+
+static int __driValidateMode(const DRIDriverContext *ctx )
+{
+   return 1;
+}
+
+/* HACK - for now, put this here... */
+/* Alpha - this may need to be a variable to handle UP1x00 vs TITAN */
+#if defined(__alpha__)
+# define DRM_PAGE_SIZE 8192
+#elif defined(__ia64__)
+# define DRM_PAGE_SIZE getpagesize()
+#else
+# define DRM_PAGE_SIZE 4096
+#endif
+                                                                                                                    
+
+static int __driInitFBDev( struct DRIDriverContextRec *ctx )
+{
+   int id;
+   ctx->shared.hFrameBuffer = ctx->FBStart;
+   ctx->shared.fbSize = ctx->FBSize;
+   ctx->shared.hSAREA = 0xB37D;
+   ctx->shared.SAREASize = DRM_PAGE_SIZE;
+   id = shmget(ctx->shared.hSAREA, ctx->shared.SAREASize, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR);
+   if (id == -1) {
+       /* segment will already exist if previous server segfaulted */
+       id = shmget(ctx->shared.hSAREA, ctx->shared.SAREASize, 0);
+       if (id == -1) {
+          fprintf(stderr, "fb: shmget failed\n");
+          return 0;
+       }
+   }
+   ctx->pSAREA = shmat(id, NULL, 0);
+   if (ctx->pSAREA == (void *)-1) {
+       fprintf(stderr, "fb: shmat failed\n");
+       return 0;
+   }
+   memset(ctx->pSAREA, 0, DRM_PAGE_SIZE);
+   return 1;
+}
+
+static void __driHaltFBDev( struct DRIDriverContextRec *ctx )
+{
+}
+
+
+
+struct DRIDriverRec __driDriver = {
+   __driInitScreenModes,
+   __driValidateMode,
+   __driValidateMode,
+   __driInitFBDev,
+   __driHaltFBDev
+};
+