add SPARC ffb DRI driver
authorAlan Hourihane <alanh@tungstengraphics.com>
Thu, 4 Dec 2003 13:38:06 +0000 (13:38 +0000)
committerAlan Hourihane <alanh@tungstengraphics.com>
Thu, 4 Dec 2003 13:38:06 +0000 (13:38 +0000)
38 files changed:
src/mesa/drivers/dri/ffb/Makefile.X11 [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_bitmap.c [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_bitmap.h [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_clear.c [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_clear.h [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_context.h [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_dd.c [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_dd.h [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_depth.c [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_depth.h [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_fifo.h [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_fog.c [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_lines.c [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_lines.h [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_linetmp.h [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_lock.h [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_points.c [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_points.h [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_pointtmp.h [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_rendertmp.h [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_span.c [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_span.h [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_state.c [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_state.h [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_stencil.c [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_stencil.h [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_tex.c [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_tex.h [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_tris.c [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_tris.h [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_tritmp.h [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_vb.c [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_vb.h [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_vbtmp.h [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_vtxfmt.c [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_vtxfmt.h [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_xmesa.c [new file with mode: 0644]
src/mesa/drivers/dri/ffb/ffb_xmesa.h [new file with mode: 0644]

diff --git a/src/mesa/drivers/dri/ffb/Makefile.X11 b/src/mesa/drivers/dri/ffb/Makefile.X11
new file mode 100644 (file)
index 0000000..3e87f9b
--- /dev/null
@@ -0,0 +1,130 @@
+
+# Mesa 3-D graphics library
+# Version:  5.0
+# Copyright (C) 1995-2002  Brian Paul
+
+TOP = ../../../../..
+
+default: linux-solo
+
+SHARED_INCLUDES = $(INCLUDE_DIRS) -I. -I../common -Iserver
+MINIGLX_INCLUDES = -I$(TOP)/src/glx/mini
+
+DEFINES += \
+       -D_HAVE_SWRAST=1 \
+       -D_HAVE_SWTNL=1 \
+       -D_HAVE_SANITY=1 \
+       -D_HAVE_CODEGEN=1 \
+       -D_HAVE_LIGHTING=1 \
+       -D_HAVE_TEXGEN=1 \
+       -D_HAVE_USERCLIP=1 \
+       -DGLX_DIRECT_RENDERING 
+
+# not yet
+# MINIGLX_SOURCES = server/ffb_dri.c 
+
+DRIVER_SOURCES = ffb_bitmap.c \
+                ../common/mm.c \
+                ../common/utils.c \
+                ../common/texmem.c \
+                ../common/vblank.c \
+                ../common/xmlconfig.c \
+                ffb_clear.c \
+                ffb_dd.c \
+                ffb_depth.c \
+                ffb_fog.c \
+                ffb_lines.c \
+                ffb_points.c \
+                ffb_span.c \
+                ffb_state.c \
+                ffb_stencil.c \
+                ffb_tex.c \
+                ffb_tris.c \
+                ffb_vb.c \
+                ffb_vtxfmt.c \
+                ffb_xmesa.c
+
+INCLUDES = $(MINIGLX_INCLUDES) \
+          $(SHARED_INCLUDES)
+
+
+C_SOURCES = $(DRIVER_SOURCES) \
+           $(MINIGLX_SOURCES) 
+
+MESA_MODULES = $(TOP)/src/mesa/mesa.a
+
+
+ifeq ($(WINDOW_SYSTEM),dri)
+WINOBJ=$(MESABUILDDIR)/dri/dri.a
+WINLIB=
+else
+WINOBJ=
+WINLIB=-L$(MESA)/src/glx/mini
+endif
+
+ASM_SOURCES = 
+OBJECTS = $(C_SOURCES:.c=.o) \
+         $(ASM_SOURCES:.S=.o) 
+
+$(SYMLINKS):
+       mkdir -p server
+       cd server
+       rm -f $@ && ln -s ../../radeon/$@ $@
+
+
+### 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: depend ffb_dri.so
+
+ffb_dri.so:  $(SYMLINKS) $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile.X11
+       rm -f $@ && gcc -o $@ -shared $(OBJECTS) $(MESA_MODULES) $(WINOBJ) $(WINLIB) -lc $(GL_LIB_DEPS)
+       rm -f $(TOP)/lib/ffb_dri.so && \
+       install ffb_dri.so $(TOP)/lib/ffb_dri.so
+
+$(TOP)/lib/ffb_dri.so: ffb_dri.so
+       rm -f $(TOP)/lib/ffb_dri.so && \
+       install ffb_dri.so $(TOP)/lib/ffb_dri.so
+
+# Run 'make -f Makefile.X11 dep' to update the dependencies if you change
+# what's included by any source file.
+depend: $(C_SOURCES) $(ASM_SOURCES)
+       makedepend -fdepend -Y $(SHARED_INCLUDES) $(MINIGLX_INCLUDES) \
+               $(C_SOURCES) $(ASM_SOURCES)
+
+
+# Emacs tags
+tags:
+       etags `find . -name \*.[ch]` `find ../include`
+
+
+# Remove .o and backup files
+clean:
+       -rm -f *.o */*.o *~ *.o *~ *.so server/*.o
+       -rm -f $(SYMLINKS)
+
+
+include $(TOP)/Make-config
+
+include depend
diff --git a/src/mesa/drivers/dri/ffb/ffb_bitmap.c b/src/mesa/drivers/dri/ffb/ffb_bitmap.c
new file mode 100644 (file)
index 0000000..8c94bde
--- /dev/null
@@ -0,0 +1,156 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_bitmap.c,v 1.1 2002/02/22 21:32:58 dawes Exp $
+ *
+ * GLX Hardware Device Driver for Sun Creator/Creator3D
+ * Copyright (C) 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 <davem@redhat.com>
+ */
+
+#include "ffb_context.h"
+#include "ffb_state.h"
+#include "ffb_lock.h"
+#include "ffb_bitmap.h"
+#include "swrast/swrast.h"
+#include "image.h"
+#include "macros.h"
+
+#undef FFB_BITMAP_TRACE
+
+static void
+ffb_bitmap(GLcontext *ctx, GLint px, GLint py,
+          GLsizei width, GLsizei height,
+          const struct gl_pixelstore_attrib *unpack,
+          const GLubyte *bitmap)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       ffb_fbcPtr ffb = fmesa->regs;
+       __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
+       unsigned int ppc, pixel;
+       GLint row, col, row_stride;
+       const GLubyte *src;
+       char *buf;
+
+       if (fmesa->bad_fragment_attrs != 0)
+               _swrast_Bitmap(ctx, px, py, width,
+                              height, unpack, bitmap);
+
+       pixel = (((((GLuint)(ctx->Current.RasterColor[0] * 255.0f)) & 0xff) <<  0) |
+                ((((GLuint)(ctx->Current.RasterColor[1] * 255.0f)) & 0xff) <<  8) |
+                ((((GLuint)(ctx->Current.RasterColor[2] * 255.0f)) & 0xff) << 16) |
+                ((((GLuint)(ctx->Current.RasterColor[3] * 255.0f)) & 0xff) << 24));
+
+#ifdef FFB_BITMAP_TRACE
+       fprintf(stderr, "ffb_bitmap: ppc(%08x) fbc(%08x) cmp(%08x) pixel(%08x)\n",
+               fmesa->ppc, fmesa->fbc, fmesa->cmp, pixel);
+#endif
+
+       LOCK_HARDWARE(fmesa);
+       fmesa->hw_locked = 1;
+
+       if (fmesa->state_dirty)
+               ffbSyncHardware(fmesa);
+
+       ppc = fmesa->ppc;
+
+       FFBFifo(fmesa, 4);
+       ffb->ppc = ((ppc &
+                    ~(FFB_PPC_TBE_MASK | FFB_PPC_ZS_MASK | FFB_PPC_CS_MASK | FFB_PPC_XS_MASK))
+                   | (FFB_PPC_TBE_TRANSPARENT | FFB_PPC_ZS_CONST | FFB_PPC_CS_CONST |
+                      (ctx->Color.BlendEnabled ? FFB_PPC_XS_CONST : FFB_PPC_XS_WID)));
+       ffb->constz = ((GLuint) (ctx->Current.RasterPos[2] * 0x0fffffff));
+       ffb->fg = pixel;
+       ffb->fontinc = (0 << 16) | 32;
+
+       buf = (char *)(fmesa->sfb32 + (dPriv->x << 2) + (dPriv->y << 13));
+
+       row_stride = (unpack->Alignment * CEILING(width, 8 * unpack->Alignment));
+       src = (const GLubyte *) (bitmap +
+                                (unpack->SkipRows * row_stride) +
+                                (unpack->SkipPixels / 8));
+       if (unpack->LsbFirst == GL_TRUE) {
+               for (row = 0; row < height; row++, src += row_stride) {
+                       const GLubyte *row_src = src;
+                       GLuint base_x, base_y;
+
+                       base_x = dPriv->x + px;
+                       base_y = dPriv->y + (dPriv->h - (py + row));
+
+                       FFBFifo(fmesa, 1);
+                       ffb->fontxy = (base_y << 16) | base_x;
+
+                       for (col = 0; col < width; col += 32, row_src += 4) {
+                               GLint bitnum, font_w = (width - col);
+                               GLuint font_data;
+
+                               if (font_w > 32)
+                                       font_w = 32;
+                               font_data = 0;
+                               for (bitnum = 0; bitnum < 32; bitnum++) {
+                                       const GLubyte val = row_src[bitnum >> 3];
+
+                                       if (val & (1 << (bitnum & (8 - 1))))
+                                               font_data |= (1 << (31 - bitnum));
+                               }
+
+                               FFBFifo(fmesa, 2);
+                               ffb->fontw = font_w;
+                               ffb->font = font_data;
+                       }
+               }
+       } else {
+               for (row = 0; row < height; row++, src += row_stride) {
+                       const GLubyte *row_src = src;
+                       GLuint base_x, base_y;
+
+                       base_x = dPriv->x + px;
+                       base_y = dPriv->y + (dPriv->h - (py + row));
+
+                       FFBFifo(fmesa, 1);
+                       ffb->fontxy = (base_y << 16) | base_x;
+
+                       for (col = 0; col < width; col += 32, row_src += 4) {
+                               GLint font_w = (width - col);
+
+                               if (font_w > 32)
+                                       font_w = 32;
+                               FFBFifo(fmesa, 2);
+                               ffb->fontw = font_w;
+                               ffb->font = (((unsigned int)row_src[0]) << 24 |
+                                            ((unsigned int)row_src[1]) << 16 |
+                                            ((unsigned int)row_src[2]) <<  8 |
+                                            ((unsigned int)row_src[3]) <<  0);
+                       }
+               }
+       }
+
+       FFBFifo(fmesa, 1);
+       ffb->ppc = ppc;
+       fmesa->ffbScreen->rp_active = 1;
+
+       UNLOCK_HARDWARE(fmesa);
+       fmesa->hw_locked = 0;
+}
+
+void ffbDDInitBitmapFuncs(GLcontext *ctx)
+{
+       ctx->Driver.Bitmap = ffb_bitmap;
+}
diff --git a/src/mesa/drivers/dri/ffb/ffb_bitmap.h b/src/mesa/drivers/dri/ffb/ffb_bitmap.h
new file mode 100644 (file)
index 0000000..4f8d2ea
--- /dev/null
@@ -0,0 +1,8 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_bitmap.h,v 1.1 2002/02/22 21:32:58 dawes Exp $ */
+
+#ifndef _FFB_BITMAP_H
+#define _FFB_BITMAP_H
+
+extern void ffbDDInitBitmapFuncs(GLcontext *);
+
+#endif /* !(_FFB_BITMAP_H) */
diff --git a/src/mesa/drivers/dri/ffb/ffb_clear.c b/src/mesa/drivers/dri/ffb/ffb_clear.c
new file mode 100644 (file)
index 0000000..5285774
--- /dev/null
@@ -0,0 +1,354 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_clear.c,v 1.2 2002/02/22 21:32:58 dawes Exp $
+ *
+ * GLX Hardware Device Driver for Sun Creator/Creator3D
+ * Copyright (C) 2000 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 <davem@redhat.com>
+ */
+
+#include "mtypes.h"
+#include "extensions.h"
+
+#include "mm.h"
+#include "ffb_dd.h"
+#include "ffb_span.h"
+#include "ffb_depth.h"
+#include "ffb_context.h"
+#include "ffb_vb.h"
+#include "ffb_tris.h"
+#include "ffb_clear.h"
+#include "ffb_lock.h"
+
+#undef CLEAR_TRACE
+
+#define BOX_AREA(__w, __h)     ((int)(__w) * (int)(__h))
+
+/* Compute the page aligned box for a page mode fast fill.
+ * In 'ework' this returns greater than zero if there are some odd
+ * edges to take care of which are outside of the page aligned area.
+ * It will place less than zero there if the box is too small,
+ * indicating that a different method must be used to fill it.
+ */
+#define CreatorPageFillParms(ffp, x, y, w, h, px, py, pw, ph, ework) \
+do {   int xdiff, ydiff; \
+       int pf_bh = ffp->pagefill_height; \
+       int pf_bw = ffp->pagefill_width; \
+       py = ((y + (pf_bh - 1)) & ~(pf_bh - 1)); \
+       ydiff = py - y; \
+       px = ffp->Pf_AlignTab[x + (pf_bw - 1)]; \
+       xdiff = px - x; \
+       ph = ((h - ydiff) & ~(pf_bh - 1)); \
+       if(ph <= 0) \
+               ework = -1; \
+       else { \
+               pw = ffp->Pf_AlignTab[w - xdiff]; \
+               if(pw <= 0) { \
+                       ework = -1; \
+               } else { \
+                       ework = (((xdiff > 0)           || \
+                                 (ydiff > 0)           || \
+                                 ((w - pw) > 0)        || \
+                                 ((h - ph) > 0))) ? 1 : 0; \
+               } \
+       } \
+} while(0);
+
+struct ff_fixups {
+       int x, y, width, height;
+};
+
+/* Compute fixups of non-page aligned areas after a page fill.
+ * Return the number of fixups needed.
+ */
+static __inline__ int
+CreatorComputePageFillFixups(struct ff_fixups *fixups,
+                            int x, int y, int w, int h,
+                            int paligned_x, int paligned_y,
+                            int paligned_w, int paligned_h)
+{
+       int nfixups = 0;
+
+       /* FastFill Left */
+       if(paligned_x != x) {
+               fixups[nfixups].x = x;
+               fixups[nfixups].y = paligned_y;
+               fixups[nfixups].width = paligned_x - x;
+               fixups[nfixups].height = paligned_h;
+               nfixups++;
+       }
+       /* FastFill Top */
+       if(paligned_y != y) {
+               fixups[nfixups].x = x;
+               fixups[nfixups].y = y;
+               fixups[nfixups].width = w;
+               fixups[nfixups].height = paligned_y - y;
+               nfixups++;
+       }
+       /* FastFill Right */
+       if((x+w) != (paligned_x+paligned_w)) {
+               fixups[nfixups].x = (paligned_x+paligned_w);
+               fixups[nfixups].y = paligned_y;
+               fixups[nfixups].width = (x+w) - fixups[nfixups].x;
+               fixups[nfixups].height = paligned_h;
+               nfixups++;
+       }
+       /* FastFill Bottom */
+       if((y+h) != (paligned_y+paligned_h)) {
+               fixups[nfixups].x = x;
+               fixups[nfixups].y = (paligned_y+paligned_h);
+               fixups[nfixups].width = w;
+               fixups[nfixups].height = (y+h) - fixups[nfixups].y;
+               nfixups++;
+       }
+       return nfixups;
+}
+
+static void
+ffb_do_clear(ffbContextPtr fmesa, __DRIdrawablePrivate *dPriv,
+            GLboolean all, GLint cx, GLint cy, GLint cwidth,
+            GLint cheight)
+{
+       FFBDRIPtr gDRIPriv = (FFBDRIPtr) fmesa->driScreen->pDevPriv;
+       ffb_fbcPtr ffb = fmesa->regs;
+       XF86DRIClipRectPtr box = dPriv->pClipRects;
+       int nc = dPriv->numClipRects;
+
+       cy  = dPriv->h - cy - cheight;
+       cx += dPriv->x;
+       cy += dPriv->y;
+
+       while (nc--) {
+               GLint x = box[nc].x1;
+               GLint y = box[nc].y1;
+               GLint width = box[nc].x2 - x;
+               GLint height = box[nc].y2 - y;
+               int paligned_y, paligned_x;
+               int paligned_h, paligned_w = 0;
+               int extra_work;
+
+               if (!all) {
+                       if (x < cx) {
+                               width -= cx - x;
+                               x = cx;
+                       }
+                       if (y < cy) {
+                               height -= cy - y;
+                               y = cy;
+                       }
+                       if (x + width > cx + cwidth)
+                               width = cx + cwidth - x;
+                       if (y + height > cy + cheight)
+                               height = cy + cheight - y;
+                       if (width <= 0)
+                               continue;
+                       if (height <= 0)
+                               continue;
+               }
+
+               if (BOX_AREA(width, height) < gDRIPriv->fastfill_small_area) {
+                       FFBFifo(fmesa, 5);
+                       ffb->drawop = FFB_DRAWOP_RECTANGLE;
+                       ffb->by = y;
+                       ffb->bx = x;
+                       ffb->bh = height;
+                       ffb->bw = width;
+                       continue;
+               }
+
+               FFBFifo(fmesa, 1);
+               ffb->drawop = FFB_DRAWOP_FASTFILL;
+
+               if (gDRIPriv->disable_pagefill ||
+                   (width < (gDRIPriv->pagefill_width<<1)) ||
+                   (height < (gDRIPriv->pagefill_height<<1)))
+                       goto do_fastfill;
+
+               CreatorPageFillParms(gDRIPriv,
+                                    x, y, width, height,
+                                    paligned_x, paligned_y,
+                                    paligned_w, paligned_h, extra_work);
+
+               if (extra_work < 0 ||
+                   BOX_AREA(paligned_w, paligned_h) < gDRIPriv->pagefill_small_area) {
+               do_fastfill:
+                       FFBFifo(fmesa, 10);
+                       ffb->by = FFB_FASTFILL_COLOR_BLK;
+                       ffb->dy = 0;
+                       ffb->dx = 0;
+                       ffb->bh = gDRIPriv->fastfill_height;
+                       ffb->bw = (gDRIPriv->fastfill_width * 4);
+                       ffb->by = FFB_FASTFILL_BLOCK;
+                       ffb->dy = y;
+                       ffb->dx = x;
+                       ffb->bh = (height + (y & (gDRIPriv->fastfill_height - 1)));
+                       ffb->bx = (width + (x & (gDRIPriv->fastfill_width - 1)));
+                       continue;
+               }
+
+               /* Ok, page fill is possible and worth it. */
+               FFBFifo(fmesa, 15);
+               ffb->by = FFB_FASTFILL_COLOR_BLK;
+               ffb->dy = 0;
+               ffb->dx = 0;
+               ffb->bh = gDRIPriv->fastfill_height;
+               ffb->bw = gDRIPriv->fastfill_width * 4;
+               ffb->by = FFB_FASTFILL_BLOCK_X;
+               ffb->dy = 0;
+               ffb->dx = 0;
+               ffb->bh = gDRIPriv->pagefill_height;
+               ffb->bw = gDRIPriv->pagefill_width * 4;
+               ffb->by = FFB_FASTFILL_PAGE;
+               ffb->dy = paligned_y;
+               ffb->dx = paligned_x;
+               ffb->bh = paligned_h;
+               ffb->bx = paligned_w;
+
+               if (extra_work) {
+                       struct ff_fixups local_fixups[4];
+                       int nfixups;
+
+                       nfixups = CreatorComputePageFillFixups(local_fixups,
+                                                              x, y, width, height,
+                                                              paligned_x, paligned_y,
+                                                              paligned_w, paligned_h);
+                       FFBFifo(fmesa, 5 + (nfixups * 5));
+                       ffb->by = FFB_FASTFILL_COLOR_BLK;
+                       ffb->dy = 0;
+                       ffb->dx = 0;
+                       ffb->bh = gDRIPriv->fastfill_height;
+                       ffb->bw = gDRIPriv->fastfill_width * 4;
+
+                       while (--nfixups >= 0) {
+                               int xx, yy, ww, hh;
+
+                               xx = local_fixups[nfixups].x;
+                               yy = local_fixups[nfixups].y;
+                               ffb->dy = yy;
+                               ffb->dx = xx;
+                               ww = (local_fixups[nfixups].width +
+                                     (xx & (gDRIPriv->fastfill_width - 1)));
+                               hh = (local_fixups[nfixups].height +
+                                     (yy & (gDRIPriv->fastfill_height - 1)));
+                               if (nfixups != 0) {
+                                       ffb->by = FFB_FASTFILL_BLOCK;
+                                       ffb->bh = hh;
+                                       ffb->bw = ww;
+                               } else {
+                                       ffb->bh = hh;
+                                       ffb->by = FFB_FASTFILL_BLOCK;
+                                       ffb->bx = ww;
+                               }
+                       }
+               }
+       }
+}
+
+void ffbDDClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
+               GLint cx, GLint cy, GLint cwidth, GLint cheight)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
+       unsigned int stcmask = DD_STENCIL_BIT;
+
+#ifdef CLEAR_TRACE
+       fprintf(stderr, "ffbDDClear: mask(%08x) all(%d) "
+               "[x(%x)y(%x)w(%x)h(%x)]\n",
+               mask, (int) all, cx, cy, cwidth, cheight);
+#endif
+       if (!(fmesa->ffb_sarea->flags & FFB_DRI_FFB2PLUS))
+               stcmask = 0;
+
+       if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT | DD_DEPTH_BIT | stcmask)) {
+               ffb_fbcPtr ffb = fmesa->regs;
+               unsigned int fbc, ppc;
+
+               fbc = (FFB_FBC_XE_ON);
+               ppc = (FFB_PPC_ACE_DISABLE | FFB_PPC_DCE_DISABLE |
+                      FFB_PPC_ABE_DISABLE | FFB_PPC_VCE_DISABLE |
+                      FFB_PPC_APE_DISABLE | FFB_PPC_XS_WID |
+                      FFB_PPC_ZS_CONST | FFB_PPC_CS_CONST);
+
+               /* Y/X enables must be both on or both off. */
+               if (mask & (DD_DEPTH_BIT | stcmask)) {
+                       fbc |= (FFB_FBC_ZE_ON | FFB_FBC_YE_ON | FFB_FBC_WB_C);
+               } else
+                       fbc |= FFB_FBC_ZE_OFF | FFB_FBC_YE_OFF;
+
+               /* All RGB enables must be both on or both off. */
+               if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) {
+                       if (mask & DD_FRONT_LEFT_BIT) {
+                               if (fmesa->back_buffer == 0)
+                                       fbc |= FFB_FBC_WB_B;
+                               else
+                                       fbc |= FFB_FBC_WB_A;
+                       }
+                       if (mask & DD_BACK_LEFT_BIT) {
+                               if (fmesa->back_buffer == 0)
+                                       fbc |= FFB_FBC_WB_A;
+                               else
+                                       fbc |= FFB_FBC_WB_B;
+                       }
+                       fbc |= FFB_FBC_RGBE_ON;
+               } else
+                       fbc |= FFB_FBC_RGBE_OFF;
+
+               LOCK_HARDWARE(fmesa);
+
+               if (dPriv->numClipRects) {
+                       FFBFifo(fmesa, 8);
+                       ffb->fbc = fbc;
+                       ffb->ppc = ppc;
+                       ffb->xclip = FFB_XCLIP_TEST_ALWAYS;
+                       ffb->cmp = 0x80808080;
+                       ffb->rop = FFB_ROP_NEW;
+
+                       if (mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT))
+                               ffb->fg = fmesa->clear_pixel;
+                       if (mask & DD_DEPTH_BIT)
+                               ffb->constz = fmesa->clear_depth;
+                       if (mask & stcmask)
+                               ffb->consty = fmesa->clear_stencil;
+
+                       ffb_do_clear(fmesa, dPriv, all, cx, cy, cwidth, cheight);
+
+                       FFBFifo(fmesa, 6);
+                       ffb->ppc = fmesa->ppc;
+                       ffb->fbc = fmesa->fbc;
+                       ffb->xclip = fmesa->xclip;
+                       ffb->cmp = fmesa->cmp;
+                       ffb->rop = fmesa->rop;
+                       ffb->drawop = fmesa->drawop;
+                       if (mask & stcmask)
+                               ffb->consty = fmesa->consty;
+                       fmesa->ffbScreen->rp_active = 1;
+               }
+
+               UNLOCK_HARDWARE(fmesa);
+
+               mask &= ~(DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT |
+                         DD_DEPTH_BIT | stcmask);
+       }
+
+       if (mask) 
+               _swrast_Clear(ctx, mask, all, cx, cy, cwidth, cheight);
+}
+
diff --git a/src/mesa/drivers/dri/ffb/ffb_clear.h b/src/mesa/drivers/dri/ffb/ffb_clear.h
new file mode 100644 (file)
index 0000000..4b707f1
--- /dev/null
@@ -0,0 +1,9 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_clear.h,v 1.2 2002/02/22 21:32:58 dawes Exp $ */
+
+#ifndef _FFB_CLEAR_H
+#define _FFB_CLEAR_H
+
+extern void ffbDDClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
+                      GLint cx, GLint cy, GLint cwidth, GLint cheight);
+
+#endif /* !(_FFB_CLEAR_H) */
diff --git a/src/mesa/drivers/dri/ffb/ffb_context.h b/src/mesa/drivers/dri/ffb/ffb_context.h
new file mode 100644 (file)
index 0000000..6e68b6d
--- /dev/null
@@ -0,0 +1,309 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_context.h,v 1.2 2002/02/22 21:32:58 dawes Exp $ */
+
+#ifndef _FFB_CONTEXT_H
+#define _FFB_CONTEXT_H
+
+#include "dri_util.h"
+
+#include "mtypes.h"
+
+#include "ffb_xmesa.h"
+
+typedef struct {
+       GLfloat alpha;
+       GLfloat red;
+       GLfloat green;
+       GLfloat blue;
+} ffb_color;
+
+#define FFB_GET_ALPHA(VTX)     \
+       FFB_COLOR_FROM_FLOAT((VTX)->color[0].alpha)
+#define FFB_GET_RED(VTX)       \
+       FFB_COLOR_FROM_FLOAT((VTX)->color[0].red)
+#define FFB_GET_GREEN(VTX)     \
+       FFB_COLOR_FROM_FLOAT((VTX)->color[0].green)
+#define FFB_GET_BLUE(VTX)      \
+       FFB_COLOR_FROM_FLOAT((VTX)->color[0].blue)
+
+typedef struct {
+       GLfloat x, y, z;
+       ffb_color       color[2];
+} ffb_vertex;
+
+#define FFB_DELAYED_VIEWPORT_VARS                              \
+       GLfloat         VP_SX = fmesa->hw_viewport[MAT_SX];     \
+       GLfloat         VP_TX = fmesa->hw_viewport[MAT_TX];     \
+       GLfloat         VP_SY = fmesa->hw_viewport[MAT_SY];     \
+       GLfloat         VP_TY = fmesa->hw_viewport[MAT_TY];     \
+       GLfloat         VP_SZ = fmesa->hw_viewport[MAT_SZ];     \
+       GLfloat         VP_TZ = fmesa->hw_viewport[MAT_TZ];     \
+       (void) VP_SX; (void) VP_SY; (void) VP_SZ;               \
+       (void) VP_TX; (void) VP_TY; (void) VP_TZ
+
+#define FFB_GET_Z(VTX)                 \
+       FFB_Z_FROM_FLOAT(VP_SZ * (VTX)->z + VP_TZ)
+#define FFB_GET_Y(VTX)                 \
+       FFB_XY_FROM_FLOAT(VP_SY * (VTX)->y + VP_TY)
+#define FFB_GET_X(VTX)                 \
+       FFB_XY_FROM_FLOAT(VP_SX * (VTX)->x + VP_TX)
+
+typedef void (*ffb_point_func)(GLcontext *, ffb_vertex *);
+typedef void (*ffb_line_func)(GLcontext *, ffb_vertex *, ffb_vertex *);
+typedef void (*ffb_tri_func)(GLcontext *, ffb_vertex *, ffb_vertex *,
+                            ffb_vertex *);
+typedef void (*ffb_quad_func)(GLcontext *, ffb_vertex *, ffb_vertex *,
+                             ffb_vertex *, ffb_vertex *);
+
+/* Immediate mode fast-path support. */
+typedef struct {
+       GLfloat         obj[4];
+       GLfloat         normal[4];
+       GLfloat         clip[4];
+       GLuint          mask;
+       GLfloat         color[4];
+       GLfloat         win[4];
+       GLfloat         eye[4];
+} ffbTnlVertex, *ffbTnlVertexPtr;
+
+typedef void (*ffb_interp_func)(GLfloat t,
+                               ffbTnlVertex *O,
+                               const ffbTnlVertex *I,
+                               const ffbTnlVertex *J);
+
+struct ffb_current_state {
+       GLfloat color[4];
+       GLfloat normal[4];
+       GLfloat specular[4];
+};
+
+struct ffb_light_state {
+       GLfloat base_color[3];
+       GLfloat base_alpha;
+};
+
+struct ffb_vertex_state {
+       struct ffb_current_state        current;
+       struct ffb_light_state          light;
+};
+
+struct ffb_imm_vertex {
+       ffbTnlVertex    vertices[8];
+       ffbTnlVertex    *v0;
+       ffbTnlVertex    *v1;
+       ffbTnlVertex    *v2;
+       ffbTnlVertex    *v3;
+
+       void (*save_vertex)(GLcontext *ctx, ffbTnlVertex *v);
+       void (*flush_vertex)(GLcontext *ctx, ffbTnlVertex *v);
+
+       ffb_interp_func interp;
+
+       GLuint prim, format;
+
+       GLvertexformat vtxfmt;
+};
+
+typedef struct ffb_context_t {
+       GLcontext               *glCtx;
+       GLframebuffer           *glBuffer;
+
+        /* Temporaries for translating to float colors. */
+        struct gl_client_array FloatColor;
+        struct gl_client_array FloatSecondaryColor;
+
+       ffb_fbcPtr              regs;
+       volatile char           *sfb32;
+
+       int                     hw_locked;
+
+       int                     back_buffer;    /* 0 = bufferA, 1 = bufferB */
+
+       /* Viewport matrix. */
+       GLfloat                 hw_viewport[16];
+#define SUBPIXEL_X (-0.5F)
+#define SUBPIXEL_Y (-0.5F + 0.125)
+
+       /* Vertices in driver format. */
+       ffb_vertex              *verts;
+
+       /* Rasterization functions. */
+       ffb_point_func draw_point;
+       ffb_line_func draw_line;
+       ffb_tri_func draw_tri;
+       ffb_quad_func draw_quad;
+
+       GLenum raster_primitive;
+       GLenum render_primitive;
+
+       GLfloat backface_sign;
+       GLfloat depth_scale;
+
+       GLfloat ffb_2_30_fixed_scale;
+       GLfloat ffb_one_over_2_30_fixed_scale;
+       GLfloat ffb_16_16_fixed_scale;
+       GLfloat ffb_one_over_16_16_fixed_scale;
+       GLfloat ffb_ubyte_color_scale;
+       GLfloat ffb_zero;
+
+       /* Immediate mode state. */
+       struct ffb_vertex_state vtx_state;
+       struct ffb_imm_vertex   imm;
+
+       /* Debugging knobs. */
+       GLboolean debugFallbacks;
+
+       /* This records state bits when a per-fragment attribute has
+        * been set which prevents us from rendering in hardware.
+        *
+        * As attributes change, some of these bits may clear as
+        * we move back within the chips capabilities.  If they
+        * all clear, we return to full hw rendering.
+        */
+       unsigned int            bad_fragment_attrs;
+#define FFB_BADATTR_FOG                0x00000001      /* Bad fog possible only when < FFB2 */
+#define FFB_BADATTR_BLENDFUNC  0x00000002      /* Any non-const func based upon dst alpha */
+#define FFB_BADATTR_BLENDROP   0x00000004      /* Blend enabled and LogicOP != GL_COPY */
+#define FFB_BADATTR_BLENDEQN   0x00000008      /* Blend equation other than ADD */
+#define FFB_BADATTR_STENCIL    0x00000010      /* Stencil enabled when < FFB2+ */
+#define FFB_BADATTR_TEXTURE    0x00000020      /* Texture enabled */
+#define FFB_BADATTR_SWONLY     0x00000040      /* Environment var set */
+
+       unsigned int            state_dirty;
+       unsigned int            state_fifo_ents;
+#define FFB_STATE_FBC          0x00000001
+#define FFB_STATE_PPC          0x00000002
+#define FFB_STATE_DRAWOP       0x00000004
+#define FFB_STATE_ROP          0x00000008
+#define FFB_STATE_LPAT         0x00000010
+#define FFB_STATE_PMASK                0x00000020
+#define FFB_STATE_XPMASK       0x00000040
+#define FFB_STATE_YPMASK       0x00000080
+#define FFB_STATE_ZPMASK       0x00000100
+#define FFB_STATE_XCLIP                0x00000200
+#define FFB_STATE_CMP          0x00000400
+#define FFB_STATE_MATCHAB      0x00000800
+#define FFB_STATE_MAGNAB       0x00001000
+#define FFB_STATE_MATCHC       0x00002000
+#define FFB_STATE_MAGNC                0x00004000
+#define FFB_STATE_DCUE         0x00008000
+#define FFB_STATE_BLEND                0x00010000
+#define FFB_STATE_CLIP         0x00020000
+#define FFB_STATE_STENCIL      0x00040000
+#define FFB_STATE_APAT         0x00080000
+#define FFB_STATE_WID          0x00100000
+#define FFB_STATE_ALL          0x001fffff
+
+       unsigned int            state_all_fifo_ents;
+
+#define FFB_MAKE_DIRTY(FMESA, STATE_MASK, FIFO_ENTS)   \
+do {   if ((STATE_MASK) & ~((FMESA)->state_dirty)) {   \
+               (FMESA)->state_dirty |= (STATE_MASK);   \
+               (FMESA)->state_fifo_ents += FIFO_ENTS;  \
+       }                                               \
+} while (0)
+
+       /* General hw reg state. */
+       unsigned int            fbc;
+       unsigned int            ppc;
+       unsigned int            drawop;
+       unsigned int            rop;
+
+       unsigned int            lpat;
+#define FFB_LPAT_BAD           0xffffffff
+       unsigned int            wid;
+       unsigned int            pmask;
+       unsigned int            xpmask;
+       unsigned int            ypmask;
+       unsigned int            zpmask;
+       unsigned int            xclip;
+       unsigned int            cmp;
+       unsigned int            matchab;
+       unsigned int            magnab;
+       unsigned int            matchc;
+       unsigned int            magnc;
+
+       /* Depth cue unit hw reg state. */
+       unsigned int            dcss;   /* All FFB              */
+       unsigned int            dcsf;   /* All FFB              */
+       unsigned int            dcsb;   /* All FFB              */
+       unsigned int            dczf;   /* All FFB              */
+       unsigned int            dczb;   /* All FFB              */
+       unsigned int            dcss1;  /* >=FFB2 only          */
+       unsigned int            dcss2;  /* >=FFB2 only          */
+       unsigned int            dcss3;  /* >=FFB2 only          */
+       unsigned int            dcs2;   /* >=FFB2 only          */
+       unsigned int            dcs3;   /* >=FFB2 only          */
+       unsigned int            dcs4;   /* >=FFB2 only          */
+       unsigned int            dcd2;   /* >=FFB2 only          */
+       unsigned int            dcd3;   /* >=FFB2 only          */
+       unsigned int            dcd4;   /* >=FFB2 only          */
+
+       /* Blend unit hw reg state. */
+       unsigned int            blendc;
+       unsigned int            blendc1;
+       unsigned int            blendc2;
+
+       /* ViewPort clipping hw reg state. */
+       unsigned int            vclipmin;
+       unsigned int            vclipmax;
+       unsigned int            vclipzmin;
+       unsigned int            vclipzmax;
+       struct {
+               unsigned int    min;
+               unsigned int    max;
+       } aux_clips[4];
+
+       /* Stencil control hw reg state.  >=FFB2+ only. */
+       unsigned int            stencil;
+       unsigned int            stencilctl;
+       unsigned int            consty;         /* Stencil Ref */
+
+       /* Area pattern (used for polygon stipples). */
+       unsigned int            pattern[32];
+
+       /* Fog state. */
+       float                   Znear, Zfar;
+
+       drmContext              hHWContext;
+       drmLock                 *driHwLock;
+       int                     driFd;
+
+       unsigned int            clear_pixel;
+       unsigned int            clear_depth;
+       unsigned int            clear_stencil;
+
+       unsigned int            setupindex;
+       unsigned int            setupnewinputs;
+       unsigned int            new_gl_state;
+
+       __DRIdrawablePrivate    *driDrawable;
+       __DRIscreenPrivate      *driScreen;
+       ffbScreenPrivate        *ffbScreen;
+       ffb_dri_state_t         *ffb_sarea;
+} ffbContextRec, *ffbContextPtr;
+
+#define FFB_CONTEXT(ctx)       ((ffbContextPtr)((ctx)->DriverCtx))
+
+/* We want the depth values written during software rendering
+ * to match what the hardware is going to put there when we
+ * hw render.
+ *
+ * The Z buffer is 28 bits deep.  Smooth shaded primitives
+ * specify a 2:30 signed fixed point Z value in the range 0.0
+ * to 1.0 inclusive.
+ *
+ * So for example, when hw rendering, the largest Z value of
+ * 1.0 would produce a value of 0x0fffffff in the actual Z
+ * buffer, which is the maximum value.
+ *
+ * Mesa's depth type is a 32-bit int, so we use the following macro
+ * to convert to/from FFB hw Z values.  Note we also have to clear
+ * out the top bits as that is where the Y (stencil) buffer is stored
+ * and during hw Z buffer reads it is always there. (During writes
+ * we tell the hw to discard those top 4 bits).
+ */
+#define Z_TO_MESA(VAL)         ((GLdepth)(((VAL) & 0x0fffffff) << (32 - 28)))
+#define Z_FROM_MESA(VAL)       (((GLuint)((GLdouble)(VAL))) >> (32 - 28))
+
+#endif /* !(_FFB_CONTEXT_H) */
diff --git a/src/mesa/drivers/dri/ffb/ffb_dd.c b/src/mesa/drivers/dri/ffb/ffb_dd.c
new file mode 100644 (file)
index 0000000..d013700
--- /dev/null
@@ -0,0 +1,116 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_dd.c,v 1.4 2002/09/11 19:49:07 tsi 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 <davem@redhat.com>
+ */
+
+#include "mtypes.h"
+#include "mm.h"
+#include "ffb_dd.h"
+#include "ffb_span.h"
+#include "ffb_depth.h"
+#include "ffb_context.h"
+#include "ffb_vb.h"
+#include "ffb_tris.h"
+#include "ffb_clear.h"
+#include "ffb_lock.h"
+#include "extensions.h"
+
+#define FFB_DATE       "20021125"
+
+/* Mesa's Driver Functions */
+
+static const GLubyte *ffbDDGetString(GLcontext *ctx, GLenum name)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       static char buffer[128];
+
+       switch (name) {
+       case GL_VENDOR:
+               return (GLubyte *) "David S. Miller";
+
+       case GL_RENDERER:
+               sprintf(buffer, "Mesa DRI FFB " FFB_DATE);
+
+               if (fmesa->ffb_sarea->flags & FFB_DRI_FFB2)
+                       strncat(buffer, " FFB2", 5);
+               if (fmesa->ffb_sarea->flags & FFB_DRI_FFB2PLUS)
+                       strncat(buffer, " FFB2PLUS", 9);
+               if (fmesa->ffb_sarea->flags & FFB_DRI_PAC1)
+                       strncat(buffer, " PAC1", 5);
+               if (fmesa->ffb_sarea->flags & FFB_DRI_PAC2)
+                       strncat(buffer, " PAC2", 5);
+
+#ifdef USE_SPARC_ASM
+               strncat(buffer, " Sparc", 6);
+#endif
+
+               return (GLubyte *) buffer;
+
+       default:
+               return NULL;
+       };
+}
+
+
+static void ffbBufferSize(GLframebuffer *buffer, GLuint *width, GLuint *height)
+{
+       GET_CURRENT_CONTEXT(ctx);
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+
+       LOCK_HARDWARE(fmesa);
+       *width = fmesa->driDrawable->w;
+       *height = fmesa->driDrawable->h;
+       UNLOCK_HARDWARE(fmesa);
+}
+
+void ffbDDExtensionsInit(GLcontext *ctx)
+{
+       /* Nothing for now until we start to add
+        * real acceleration. -DaveM
+        */
+
+       /* XXX Need to turn off GL_EXT_blend_func_separate for one.
+        * XXX Also BlendEquation should be turned off too, what
+        * XXX EXT is that assosciated with?
+        */
+}
+
+static void ffbDDFinish(GLcontext *ctx)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+
+       LOCK_HARDWARE(fmesa);
+       FFBWait(fmesa, fmesa->regs);
+       UNLOCK_HARDWARE(fmesa);
+}
+
+void ffbDDInitDriverFuncs(GLcontext *ctx)
+{
+       ctx->Driver.GetBufferSize        = ffbBufferSize;
+       ctx->Driver.GetString            = ffbDDGetString;
+       ctx->Driver.Clear                = ffbDDClear;
+
+       ctx->Driver.Finish               = ffbDDFinish;
+}
diff --git a/src/mesa/drivers/dri/ffb/ffb_dd.h b/src/mesa/drivers/dri/ffb/ffb_dd.h
new file mode 100644 (file)
index 0000000..4ffcbe6
--- /dev/null
@@ -0,0 +1,36 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_dd.h,v 1.1 2000/06/20 05:08:38 dawes Exp $
+ *
+ * GLX Hardware Device Driver for Sun Creator/Creator3D.
+ * Copyright (C) 2000 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 <davem@redhat.com>
+ */
+
+#ifndef _FFB_DD_H
+#define _FFB_DD_H
+
+#include "context.h"
+
+void ffbDDInitDriverFuncs(GLcontext *ctx);
+void ffbDDExtensionsInit(GLcontext *ctx);
+
+#endif /* !(_FFB_DD_H) */
diff --git a/src/mesa/drivers/dri/ffb/ffb_depth.c b/src/mesa/drivers/dri/ffb/ffb_depth.c
new file mode 100644 (file)
index 0000000..27f3589
--- /dev/null
@@ -0,0 +1,214 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_depth.c,v 1.2 2002/02/22 21:32:58 dawes Exp $
+ *
+ * GLX Hardware Device Driver for Sun Creator/Creator3D
+ * Copyright (C) 2000 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 <davem@redhat.com>
+ */
+
+#include "mtypes.h"
+#include "swrast/swrast.h"
+#include "ffb_dd.h"
+#include "ffb_span.h"
+#include "ffb_context.h"
+#include "ffb_depth.h"
+#include "ffb_lock.h"
+
+#include "swrast/swrast.h"
+
+#undef DEPTH_TRACE
+
+static void 
+FFBWriteDepthSpan(GLcontext *ctx, GLuint n, GLint x, GLint y,
+                 const GLdepth depth[], const GLubyte mask[])
+{
+#ifdef DEPTH_TRACE
+       fprintf(stderr, "FFBWriteDepthSpan: n(%d) x(%d) y(%d)\n",
+               (int) n, x, y);
+#endif
+       if (ctx->Depth.Mask) {
+               ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+               __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
+               GLuint *zptr;
+               GLuint i;
+
+               if (!fmesa->hw_locked)
+                       LOCK_HARDWARE(fmesa);
+               FFBFifo(fmesa, 2);
+               fmesa->regs->fbc = (FFB_FBC_WB_C | FFB_FBC_ZE_ON |
+                                   FFB_FBC_YE_OFF | FFB_FBC_RGBE_OFF);
+               fmesa->regs->ppc = FFB_PPC_ZS_VAR;
+               FFBWait(fmesa, fmesa->regs);
+
+               y = (dPriv->h - y);
+               zptr = (GLuint *)
+                       ((char *)fmesa->sfb32 +
+                        ((dPriv->x + x) << 2) +
+                        ((dPriv->y + y) << 13));
+               
+               for (i = 0; i < n; i++) {
+                       if (mask[i]) {
+                               *zptr = Z_FROM_MESA(depth[i]);
+                       }
+                       zptr++;
+               }
+
+               FFBFifo(fmesa, 2);
+               fmesa->regs->fbc = fmesa->fbc;
+               fmesa->regs->ppc = fmesa->ppc;
+               fmesa->ffbScreen->rp_active = 1;
+               if (!fmesa->hw_locked)
+                       UNLOCK_HARDWARE(fmesa);
+       }
+}
+
+static void 
+FFBWriteDepthPixels(GLcontext *ctx, GLuint n, const GLint x[], const GLint y[],
+                   const GLdepth depth[], const GLubyte mask[])
+{
+#ifdef DEPTH_TRACE
+       fprintf(stderr, "FFBWriteDepthPixels: n(%d)\n", (int) n);
+#endif
+       if (ctx->Depth.Mask) {
+               ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+               __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
+               char *zbase;
+               GLuint i;
+
+               if (!fmesa->hw_locked)
+                       LOCK_HARDWARE(fmesa);
+               FFBFifo(fmesa, 2);
+               fmesa->regs->fbc = (FFB_FBC_WB_C | FFB_FBC_ZE_ON |
+                                   FFB_FBC_YE_OFF | FFB_FBC_RGBE_OFF);
+               fmesa->regs->ppc = FFB_PPC_ZS_VAR;
+               fmesa->ffbScreen->rp_active = 1;
+               FFBWait(fmesa, fmesa->regs);
+
+               zbase = ((char *)fmesa->sfb32 +
+                        (dPriv->x << 2) + (dPriv->y << 13));
+               
+               for (i = 0; i < n; i++) {
+                       GLint y1 = (dPriv->h - y[i]);
+                       GLint x1 = x[i];
+                       GLuint *zptr;
+
+                       zptr = (GLuint *)
+                               (zbase + (x1 << 2) + (y1 << 13));
+                       if (mask[i])
+                               *zptr = Z_FROM_MESA(depth[i]);
+               }
+
+               FFBFifo(fmesa, 2);
+               fmesa->regs->fbc = fmesa->fbc;
+               fmesa->regs->ppc = fmesa->ppc;
+               fmesa->ffbScreen->rp_active = 1;
+               if (!fmesa->hw_locked)
+                       UNLOCK_HARDWARE(fmesa);
+       }
+}
+
+static void 
+FFBReadDepthSpan(GLcontext *ctx, GLuint n, GLint x, GLint y, GLdepth depth[])
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
+       GLuint *zptr;
+       GLuint i;
+
+#ifdef DEPTH_TRACE
+       fprintf(stderr, "FFBReadDepthSpan: n(%d) x(%d) y(%d)\n",
+               (int) n, x, y);
+#endif
+       if (!fmesa->hw_locked)
+               LOCK_HARDWARE(fmesa);
+       FFBFifo(fmesa, 1);
+       fmesa->regs->fbc = FFB_FBC_RB_C;
+       fmesa->ffbScreen->rp_active = 1;
+       FFBWait(fmesa, fmesa->regs);
+
+       y = (dPriv->h - y);
+       zptr = (GLuint *)
+               ((char *)fmesa->sfb32 +
+                ((dPriv->x + x) << 2) +
+                ((dPriv->y + y) << 13));
+               
+       for (i = 0; i < n; i++) {
+               depth[i] = Z_TO_MESA(*zptr);
+               zptr++;
+       }
+
+       FFBFifo(fmesa, 1);
+       fmesa->regs->fbc = fmesa->fbc;
+       fmesa->ffbScreen->rp_active = 1;
+       if (!fmesa->hw_locked)
+               UNLOCK_HARDWARE(fmesa);
+}
+
+static void 
+FFBReadDepthPixels(GLcontext *ctx, GLuint n, const GLint x[], const GLint y[],
+                  GLdepth depth[])
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
+       char *zbase;
+       GLuint i;
+
+#ifdef DEPTH_TRACE
+       fprintf(stderr, "FFBReadDepthPixels: n(%d)\n", (int) n);
+#endif
+       if (!fmesa->hw_locked)
+               LOCK_HARDWARE(fmesa);
+       FFBFifo(fmesa, 1);
+       fmesa->regs->fbc = FFB_FBC_RB_C;
+       fmesa->ffbScreen->rp_active = 1;
+       FFBWait(fmesa, fmesa->regs);
+
+       zbase = ((char *)fmesa->sfb32 +
+                (dPriv->x << 2) + (dPriv->y << 13));
+               
+       for (i = 0; i < n; i++) {
+               GLint y1 = (dPriv->h - y[i]);
+               GLint x1 = x[i];
+               GLuint *zptr;
+
+               zptr = (GLuint *)
+                       (zbase + (x1 << 2) + (y1 << 13));
+               depth[i] = Z_TO_MESA(*zptr);
+       }
+
+       FFBFifo(fmesa, 1);
+       fmesa->regs->fbc = fmesa->fbc;
+       fmesa->ffbScreen->rp_active = 1;
+       if (!fmesa->hw_locked)
+               UNLOCK_HARDWARE(fmesa);
+}
+
+void ffbDDInitDepthFuncs(GLcontext *ctx)
+{
+       struct swrast_device_driver *swdd = 
+               _swrast_GetDeviceDriverReference(ctx);
+   
+       swdd->WriteDepthSpan    = FFBWriteDepthSpan;
+       swdd->ReadDepthSpan     = FFBReadDepthSpan;
+       swdd->WriteDepthPixels  = FFBWriteDepthPixels;
+       swdd->ReadDepthPixels   = FFBReadDepthPixels;
+}
diff --git a/src/mesa/drivers/dri/ffb/ffb_depth.h b/src/mesa/drivers/dri/ffb/ffb_depth.h
new file mode 100644 (file)
index 0000000..a098bfc
--- /dev/null
@@ -0,0 +1,8 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_depth.h,v 1.1 2000/06/20 05:08:38 dawes Exp $ */
+
+#ifndef _FFB_DEPTH_H
+#define _FFB_DEPTH_H
+
+extern void ffbDDInitDepthFuncs(GLcontext *ctx);
+
+#endif /* !(_FFB_DEPTH_H) */
diff --git a/src/mesa/drivers/dri/ffb/ffb_fifo.h b/src/mesa/drivers/dri/ffb/ffb_fifo.h
new file mode 100644 (file)
index 0000000..886d71b
--- /dev/null
@@ -0,0 +1,28 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_fifo.h,v 1.2 2002/02/22 21:32:58 dawes Exp $ */
+
+#ifndef _FFB_FIFO_H
+#define _FFB_FIFO_H
+
+#define FFBFifo(__fmesa, __n) \
+do {   ffbScreenPrivate *__fScrn = (__fmesa)->ffbScreen; \
+       int __cur_slots = __fScrn->fifo_cache; \
+       if ((__cur_slots - (__n)) < 0) { \
+               ffb_fbcPtr __ffb = __fmesa->regs; \
+               do { __cur_slots = (((int)__ffb->ucsr & FFB_UCSR_FIFO_MASK) - 4); \
+               } while ((__cur_slots - (__n)) < 0); \
+       } (__fScrn)->fifo_cache = (__cur_slots - (__n)); \
+} while(0)
+
+#define FFBWait(__fmesa, __ffb) \
+do {   ffbScreenPrivate *__fScrn = (__fmesa)->ffbScreen; \
+       if (__fScrn->rp_active) { \
+               unsigned int __regval = (__ffb)->ucsr; \
+               while((__regval & FFB_UCSR_ALL_BUSY) != 0) { \
+                       __regval = (__ffb)->ucsr; \
+               } \
+               __fScrn->fifo_cache = ((int)(__regval & FFB_UCSR_FIFO_MASK)) - 4; \
+               __fScrn->rp_active = 0; \
+       } \
+} while(0)
+
+#endif /* !(_FFB_FIFO_H) */
diff --git a/src/mesa/drivers/dri/ffb/ffb_fog.c b/src/mesa/drivers/dri/ffb/ffb_fog.c
new file mode 100644 (file)
index 0000000..e6eca23
--- /dev/null
@@ -0,0 +1,73 @@
+
+/* FFB fog support:
+ *
+ * There are two levels of support for FOG in the Creator3D series.
+ * Both involve a depth cue unit and 1 or 4 slope factors and scales
+ * for varying the pixel intensity.
+ *
+ * Chips prior to FFB2 only have a single set of such settings, FFB2
+ * and later have 4 settings.
+ *
+ * The basic depth cueing equation is:
+ *
+ *     C_final = dcsf(z) * C_orig + (1 - dcsf(z)) * C_fog
+ *
+ *     C_final --      The final color passed to blend unit or frame
+ *                     buffer (if blending is disabled).
+ *
+ *     C_orig  --      The color we start with, which comes either from
+ *                     the raster processor or cpu writes to the smart
+ *                     framebuffer aperture.
+ *
+ *     C_fog   --      This is the "fog" color, ie. the desired color
+ *                     at the deepest Z.
+ *
+ *     dcsf(z) --      The depth cue scale as a function of Z.
+ *
+ * With pre-FFB2 chips there are four parameters to control the depth
+ * cue scaling.  Here is a diagram:
+ *
+ *                1.0  -------------
+ *                     |   |   |   |
+ *                     |   |   |   |
+ *             Sfront  XXXXX---+---+
+ *                     |   |X  |   |
+ *     dcsf(z)         |   | X |   |
+ *                     |   |  X|   |
+ *             Sback   +---+---XXXXX
+ *                     |   |   |   |
+ *                0.0  -------------
+ *                     0.0 Zf  Zb 1.0
+ *
+ *                           z
+ * Therefore:
+ *
+ *     for Zf < z < Zb
+ *
+ *             dcsf(z) = Sback + ((Sfront - Sback) / (Zf - Zb)) * (Zb - z)
+ *
+ *     for z <= Zf
+ *
+ *             dcsf(z) = Sfront
+ *
+ *     for z >= Zb
+ *
+ *             dcsf(z) = Sback
+ *
+ * With FFB2 and later, 3 more slope regions are provided, the first of
+ * them starts at the end of the region defined above and ends at a
+ * specified depth value, the next slop region starts there and ends
+ * at the next specified depth value, and so on.  Each of the 3 slope
+ * regions also have scale and slope settings of their own.
+ *
+ * The C_fog color is programmed into the alpha blending unit color1
+ * and color2 registers as follows:
+ *
+ *     color1:         -(C_fog)
+ *     color2:         C_fog - bg
+ *
+ * If alpha blending is disabled, the bg factor is zero.  Note that
+ * the alpha blending color registers specify each of the RGB values
+ * as 9 bit 1:8 signed numbers in the range -1.00 to 0.ff inclusive.
+ * (ie. 0x100 == -1.00 and 0x0ff == +0.ff)
+ */
diff --git a/src/mesa/drivers/dri/ffb/ffb_lines.c b/src/mesa/drivers/dri/ffb/ffb_lines.c
new file mode 100644 (file)
index 0000000..fec6b93
--- /dev/null
@@ -0,0 +1,112 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_lines.c,v 1.2 2002/02/22 21:32:58 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 <davem@redhat.com>
+ */
+
+#include "mtypes.h"
+#include "mm.h"
+#include "mmath.h"
+#include "ffb_dd.h"
+#include "ffb_span.h"
+#include "ffb_depth.h"
+#include "ffb_context.h"
+#include "ffb_vb.h"
+#include "ffb_lines.h"
+#include "ffb_tris.h"
+#include "ffb_lock.h"
+#include "extensions.h"
+
+#undef FFB_LINE_TRACE
+
+#define FFB_LINE_FLAT_BIT      0x01
+#define FFB_LINE_ALPHA_BIT     0x02
+#define MAX_FFB_LINE_FUNCS      0x04
+
+static ffb_line_func ffb_line_tab[MAX_FFB_LINE_FUNCS];
+
+/* If the line is not wide, we can support all of the line
+ * patterning and smooth shading features of OpenGL fully.
+ */
+
+#define IND (0)
+#define TAG(x) x
+#include "ffb_linetmp.h"
+
+#define IND (FFB_LINE_FLAT_BIT)
+#define TAG(x) x##_flat
+#include "ffb_linetmp.h"
+
+#define IND (FFB_LINE_ALPHA_BIT)
+#define TAG(x) x##_alpha
+#include "ffb_linetmp.h"
+
+#define IND (FFB_LINE_ALPHA_BIT|FFB_LINE_FLAT_BIT)
+#define TAG(x) x##_alpha_flat
+#include "ffb_linetmp.h"
+
+void ffbDDLinefuncInit(void)
+{
+       init();
+       init_flat();
+       init_alpha();
+       init_alpha_flat();
+}
+
+static void ffb_dd_line( GLcontext *ctx, GLuint e0, GLuint e1 )
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       ffb_vertex *v0 = &fmesa->verts[e0];
+       ffb_vertex *v1 = &fmesa->verts[e1];
+       fmesa->draw_line( ctx, v0, v1 );
+}
+
+void ffbChooseLineState(GLcontext *ctx)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       TNLcontext *tnl = TNL_CONTEXT(ctx);
+       GLuint flags = ctx->_TriangleCaps;
+       GLuint ind = 0;
+
+       tnl->Driver.Render.Line = ffb_dd_line;
+
+       if (flags & DD_FLATSHADE)
+               ind |= FFB_LINE_FLAT_BIT;
+
+       if ((flags & DD_LINE_STIPPLE) != 0 &&
+           fmesa->lpat == FFB_LPAT_BAD) {
+               fmesa->draw_line = ffb_fallback_line;
+               return;
+       }
+
+       /* If blending or the alpha test is enabled we need to
+        * provide alpha components to the chip, else we can
+        * do without it and thus feed vertex data to the chip
+        * more efficiently.
+        */
+       if (ctx->Color.BlendEnabled || ctx->Color.AlphaEnabled)
+               ind |= FFB_LINE_ALPHA_BIT;
+
+       fmesa->draw_line = ffb_line_tab[ind];
+}
diff --git a/src/mesa/drivers/dri/ffb/ffb_lines.h b/src/mesa/drivers/dri/ffb/ffb_lines.h
new file mode 100644 (file)
index 0000000..d508c24
--- /dev/null
@@ -0,0 +1,18 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_lines.h,v 1.2 2002/02/22 21:32:58 dawes Exp $ */
+
+#ifndef _FFB_LINES_H
+#define _FFB_LINES_H
+
+#include "ffb_context.h"
+
+#define _FFB_NEW_LINE (_DD_NEW_FLATSHADE |     \
+                      _DD_NEW_LINE_WIDTH |     \
+                      _DD_NEW_LINE_STIPPLE |   \
+                      _DD_NEW_LINE_SMOOTH |    \
+                      _NEW_COLOR)
+
+extern void ffbDDLinefuncInit(void);
+extern void ffbChooseLineState(GLcontext *);
+extern void ffb_fallback_line( GLcontext *ctx, ffb_vertex *v0, ffb_vertex *v1 );
+
+#endif /* !(_FFB_LINES_H) */
diff --git a/src/mesa/drivers/dri/ffb/ffb_linetmp.h b/src/mesa/drivers/dri/ffb/ffb_linetmp.h
new file mode 100644 (file)
index 0000000..0951513
--- /dev/null
@@ -0,0 +1,81 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_linetmp.h,v 1.2 2002/02/22 21:32:58 dawes Exp $ */
+
+static __inline void TAG(ffb_line)(GLcontext *ctx, ffb_vertex *v0, 
+                                  ffb_vertex *v1 )
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       ffb_fbcPtr ffb = fmesa->regs;
+#if (IND & FFB_LINE_FLAT_BIT)
+       const GLuint const_fg = FFB_PACK_CONST_UBYTE_ARGB_COLOR( v1->color[0] );
+#endif
+       FFB_DELAYED_VIEWPORT_VARS;
+
+#ifdef FFB_LINE_TRACE
+       fprintf(stderr, "FFB: ffb_line ["
+#if (IND & FFB_LINE_FLAT_BIT)
+               " FLAT"
+#endif
+#if (IND & FFB_LINE_ALPHA_BIT)
+               " ALPHA"
+#endif
+               " ]\n");
+#endif
+
+#if (IND & FFB_LINE_FLAT_BIT)
+       FFBFifo(fmesa, 1);
+       ffb->fg = const_fg;
+#ifdef FFB_LINE_TRACE
+       fprintf(stderr, "FFB: ffb_line confg_fg[%08x]\n", const_fg);
+#endif
+#endif
+
+#if (IND & FFB_LINE_FLAT_BIT)
+       /* (2 * 3) + 1 */
+       FFBFifo(fmesa, 7);
+#else
+#if (IND & FFB_LINE_ALPHA_BIT)
+       /* (2 * 7) + 1 */
+       FFBFifo(fmesa, 15);
+#else
+       /* (2 * 6) + 1 */
+       FFBFifo(fmesa, 13);
+#endif
+#endif
+
+       /* Using DDLINE or AALINE, init the line pattern state. */
+       ffb->lpat = fmesa->lpat;
+
+#if !(IND & FFB_LINE_FLAT_BIT)
+#if (IND & FFB_LINE_ALPHA_BIT)
+       ffb->alpha      = FFB_GET_ALPHA(v0);
+#endif
+       ffb->red        = FFB_GET_RED(v0);
+       ffb->green      = FFB_GET_GREEN(v0);
+       ffb->blue       = FFB_GET_BLUE(v0);
+#endif
+       ffb->z          = FFB_GET_Z(v0);
+       ffb->ryf        = FFB_GET_Y(v0);
+       ffb->rxf        = FFB_GET_X(v0);
+
+#if !(IND & FFB_LINE_FLAT_BIT)
+#if (IND & FFB_LINE_ALPHA_BIT)
+       ffb->alpha      = FFB_GET_ALPHA(v1);
+#endif
+       ffb->red        = FFB_GET_RED(v1);
+       ffb->green      = FFB_GET_GREEN(v1);
+       ffb->blue       = FFB_GET_BLUE(v1);
+#endif
+       ffb->z          = FFB_GET_Z(v1);
+       ffb->y          = FFB_GET_Y(v1);
+       ffb->x          = FFB_GET_X(v1);
+
+       fmesa->ffbScreen->rp_active = 1;
+}
+
+static void TAG(init)(void)
+{
+       ffb_line_tab[IND] = TAG(ffb_line);
+}
+
+#undef IND
+#undef TAG
diff --git a/src/mesa/drivers/dri/ffb/ffb_lock.h b/src/mesa/drivers/dri/ffb/ffb_lock.h
new file mode 100644 (file)
index 0000000..e6295dc
--- /dev/null
@@ -0,0 +1,33 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_lock.h,v 1.2 2002/02/22 21:32:59 dawes Exp $ */
+
+#ifndef _FFB_LOCK_H
+#define _FFB_LOCK_H
+
+#include "ffb_context.h"
+
+extern void ffbXMesaUpdateState(ffbContextPtr fmesa);
+#define FFB_UPDATE_STATE(fmesa)        ffbXMesaUpdateState(fmesa)
+
+/* Lock the hardware and validate our state. */
+#if defined(__i386__) 
+#define LOCK_HARDWARE(fmesa)                   
+#define UNLOCK_HARDWARE(fmesa)                 
+#else
+#define LOCK_HARDWARE(fmesa)                           \
+  do {                                                 \
+    int __ret=0;                                       \
+    DRM_CAS(fmesa->driHwLock, fmesa->hHWContext,       \
+           (DRM_LOCK_HELD | fmesa->hHWContext), __ret);\
+    if (__ret) {                                       \
+        drmGetLock(fmesa->driFd, fmesa->hHWContext, 0);        \
+       FFB_UPDATE_STATE(fmesa);                        \
+    }                                                  \
+  } while (0)
+
+
+/* Unlock the hardware. */
+#define UNLOCK_HARDWARE(fmesa)                                 \
+    DRM_UNLOCK(fmesa->driFd, fmesa->driHwLock, fmesa->hHWContext);     
+#endif
+
+#endif /* !(_FFB_LOCK_H) */
diff --git a/src/mesa/drivers/dri/ffb/ffb_points.c b/src/mesa/drivers/dri/ffb/ffb_points.c
new file mode 100644 (file)
index 0000000..6505530
--- /dev/null
@@ -0,0 +1,94 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_points.c,v 1.2 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 <davem@redhat.com>
+ */
+
+#include "mtypes.h"
+#include "mmath.h"
+#include "ffb_dd.h"
+#include "ffb_context.h"
+#include "ffb_vb.h"
+#include "ffb_points.h"
+#include "ffb_tris.h"
+#include "ffb_lock.h"
+
+
+#undef FFB_POINT_TRACE
+
+#define FFB_POINT_AA_BIT       0x01
+
+static ffb_point_func ffb_point_tab[0x08];
+
+#define IND (0)
+#define TAG(x) x
+#include "ffb_pointtmp.h"
+
+#define IND (FFB_POINT_AA_BIT)
+#define TAG(x) x##_aa
+#include "ffb_pointtmp.h"
+
+void ffbDDPointfuncInit(void)
+{
+       init();
+       init_aa();
+}
+
+static void ffb_dd_points( GLcontext *ctx, GLuint first, GLuint last )
+{
+       struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb;
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       ffb_vertex *fverts = fmesa->verts;
+       int i;
+
+       if (VB->Elts == 0) {
+               for ( i = first ; i < last ; i++ ) {
+                       if ( VB->ClipMask[i] == 0 ) {
+                               fmesa->draw_point( ctx, &fverts[i] );
+                       }
+               }
+       } else {
+               for ( i = first ; i < last ; i++ ) {
+                       GLuint e = VB->Elts[i];
+                       if ( VB->ClipMask[e] == 0 ) {
+                               fmesa->draw_point( ctx, &fverts[e] );
+                       }
+               }
+       }
+}
+
+void ffbChoosePointState(GLcontext *ctx)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       TNLcontext *tnl = TNL_CONTEXT(ctx);
+       GLuint flags = ctx->_TriangleCaps;
+       GLuint ind = 0;
+
+       tnl->Driver.Render.Points = ffb_dd_points;
+
+       if (flags & DD_POINT_SMOOTH)
+               ind |= FFB_POINT_AA_BIT;
+
+       fmesa->draw_point = ffb_point_tab[ind];
+}
diff --git a/src/mesa/drivers/dri/ffb/ffb_points.h b/src/mesa/drivers/dri/ffb/ffb_points.h
new file mode 100644 (file)
index 0000000..7d5c1f8
--- /dev/null
@@ -0,0 +1,15 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_points.h,v 1.2 2002/02/22 21:32:59 dawes Exp $ */
+
+#ifndef _FFB_POINTS_H
+#define _FFB_POINTS_H
+
+extern void ffbDDPointfuncInit(void);
+
+#define _FFB_NEW_POINT (_DD_NEW_POINT_SIZE |   \
+                       _DD_NEW_POINT_SMOOTH |  \
+                       _NEW_COLOR)
+
+extern void ffbChoosePointState(GLcontext *);
+extern void ffb_fallback_point( GLcontext *ctx, ffb_vertex *v0 );
+
+#endif /* !(_FFB_POINTS_H) */
diff --git a/src/mesa/drivers/dri/ffb/ffb_pointtmp.h b/src/mesa/drivers/dri/ffb/ffb_pointtmp.h
new file mode 100644 (file)
index 0000000..310c95d
--- /dev/null
@@ -0,0 +1,55 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_pointtmp.h,v 1.3 2002/02/22 21:32:59 dawes Exp $ */
+
+static __inline void TAG(ffb_draw_point)(GLcontext *ctx, ffb_vertex *tmp )
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       ffb_fbcPtr ffb = fmesa->regs;
+       FFB_DELAYED_VIEWPORT_VARS;
+
+#ifdef FFB_POINT_TRACE
+       fprintf(stderr, "FFB: ffb_point ["
+#if (IND & FFB_POINT_AA_BIT)
+               "AA"
+#endif
+               "] X(%f) Y(%f) Z(%f)\n",
+               tmp->x, tmp->y, tmp->z);
+#endif
+
+#if (IND & FFB_POINT_AA_BIT)
+       FFBFifo(fmesa, 4);
+                       
+       ffb->fg = FFB_PACK_CONST_UBYTE_ARGB_COLOR( tmp->color[0] );
+       ffb->z = FFB_GET_Z(tmp);
+       ffb->y = FFB_GET_Y(tmp) + 0x8000 /* FIX ME */;
+       ffb->x = FFB_GET_X(tmp) + 0x8000 /* FIX ME */;
+#else
+       {
+               unsigned int const_fg, const_z, h, w;
+
+               const_fg = FFB_PACK_CONST_UBYTE_ARGB_COLOR( tmp->color[0] );
+               const_z = Z_FROM_MESA(FFB_Z_TO_FLOAT(FFB_GET_Z(tmp)));
+               h = FFB_GET_Y(tmp) >> 16;
+               w = FFB_GET_X(tmp) >> 16;
+#ifdef FFB_POINT_TRACE
+               fprintf(stderr, "FFB: ffb_point fg(%08x) z(%08x) h(%08x) w(%08x)\n",
+                       const_fg, const_z, h, w);
+#endif
+               FFBFifo(fmesa, 4);
+               ffb->fg = const_fg;
+               ffb->constz = const_z;
+               ffb->bh = h;
+               ffb->bw = w;
+       }
+#endif
+
+       fmesa->ffbScreen->rp_active = 1;
+}
+
+
+static void TAG(init)(void)
+{
+       ffb_point_tab[IND] = TAG(ffb_draw_point);
+}
+
+#undef IND
+#undef TAG
diff --git a/src/mesa/drivers/dri/ffb/ffb_rendertmp.h b/src/mesa/drivers/dri/ffb/ffb_rendertmp.h
new file mode 100644 (file)
index 0000000..9d18db5
--- /dev/null
@@ -0,0 +1,648 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_rendertmp.h,v 1.2 2003/01/29 23:00:40 dawes Exp $ */
+
+#define IMPL_LOCAL_VARS                                                \
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);                 \
+       ffb_fbcPtr ffb = fmesa->regs;                           \
+       const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;   \
+       FFB_DELAYED_VIEWPORT_VARS;                              \
+       (void) fmesa; (void) ffb; (void) elt
+
+#if (IND & FFB_FLAT_BIT)
+#define FFB_DECLARE_CACHED_COLOR(NAME)         \
+       unsigned int NAME;
+#define FFB_COMPUTE_CACHED_COLOR(NAME, VTX)    \
+       NAME = FFB_PACK_CONST_UBYTE_ARGB_COLOR((VTX)->color[0])
+#define FFB_CACHED_COLOR_SAME(NAME1, NAME2)    \
+       ((NAME1) == (NAME2))
+#define FFB_CACHED_COLOR_SET(NAME)             \
+       ffb->fg = (NAME)
+#define FFB_CACHED_COLOR_UPDATE(NAME1, NAME2)  \
+       ffb->fg = (NAME1) = (NAME2)
+#define FFB_SET_PRIM_COLOR(COLOR_VERTEX)       \
+       ffb->fg = FFB_PACK_CONST_UBYTE_ARGB_COLOR((COLOR_VERTEX)->color[0])
+#define FFB_PRIM_COLOR_COST                    1
+#define FFB_SET_VERTEX_COLOR(VTX)              /**/
+#define FFB_VERTEX_COLOR_COST                  0
+#else
+#define FFB_DECLARE_CACHED_COLOR(NAME)         /**/
+#define FFB_COMPUTE_CACHED_COLOR(NAME, VTX)    /**/
+#define FFB_CACHED_COLOR_SAME(NAME1, NAME2)    0
+#define FFB_CACHED_COLOR_SET(NAME1)            /**/
+#define FFB_CACHED_COLOR_UPDATE(NAME1, NAME2)  /**/
+#define FFB_SET_PRIM_COLOR(COLOR_VERTEX)       /**/
+#define FFB_PRIM_COLOR_COST                    0
+#if (IND & FFB_ALPHA_BIT)
+#define FFB_SET_VERTEX_COLOR(VTX)              \
+       ffb->alpha = FFB_GET_ALPHA(VTX);        \
+       ffb->red   = FFB_GET_RED(VTX);          \
+       ffb->green = FFB_GET_GREEN(VTX);        \
+       ffb->blue  = FFB_GET_BLUE(VTX)
+#define FFB_VERTEX_COLOR_COST                  4
+#else
+#define FFB_SET_VERTEX_COLOR(VTX)              \
+       ffb->red   = FFB_GET_RED(VTX);          \
+       ffb->green = FFB_GET_GREEN(VTX);        \
+       ffb->blue  = FFB_GET_BLUE(VTX)
+#define FFB_VERTEX_COLOR_COST                  3
+#endif
+#endif
+
+#define RESET_STIPPLE  ffb->lpat = fmesa->lpat;
+
+#if !(IND & (FFB_TRI_CULL_BIT))
+static void TAG(ffb_vb_points)(GLcontext *ctx, GLuint start, GLuint count, GLuint flags)
+{
+       GLint i;
+       IMPL_LOCAL_VARS;
+
+#ifdef FFB_RENDER_TRACE
+       fprintf(stderr, "%s: start(%d) count(%d) flags(%x)\n",
+               __FUNCTION__, start, count, flags);
+#endif
+       ffbRenderPrimitive(ctx, GL_POINTS);
+       if (ctx->_TriangleCaps & DD_POINT_SMOOTH) {
+               for (i = start; i < count; i++) {
+                       ffb_vertex *v0 = &fmesa->verts[ELT(i)];
+
+                       FFBFifo(fmesa, 4);
+                       ffb->fg = FFB_PACK_CONST_UBYTE_ARGB_COLOR(v0->color[0]);
+                       ffb->z = FFB_GET_Z(v0);
+                       ffb->y = FFB_GET_Y(v0) + 0x8000 /* FIX ME */;
+                       ffb->x = FFB_GET_X(v0) + 0x8000 /* FIX ME */;
+               }
+       } else {
+               for (i = start; i < count; i++) {
+                       ffb_vertex *v0 = &fmesa->verts[ELT(i)];
+                       FFBFifo(fmesa, 4);
+                       ffb->fg = FFB_PACK_CONST_UBYTE_ARGB_COLOR(v0->color[0]);
+                       ffb->constz = Z_FROM_MESA(FFB_Z_TO_FLOAT(FFB_GET_Z(v0)));
+                       ffb->bh = FFB_GET_Y(v0) >> 16;
+                       ffb->bw = FFB_GET_X(v0) >> 16;
+               }
+       }
+
+       fmesa->ffbScreen->rp_active = 1;
+}
+
+static void TAG(ffb_vb_lines)(GLcontext *ctx, GLuint start, GLuint count, GLuint flags)
+{
+       GLint i;
+       IMPL_LOCAL_VARS;
+
+#ifdef FFB_RENDER_TRACE
+       fprintf(stderr, "%s: start(%d) count(%d) flags(%x)\n",
+               __FUNCTION__, start, count, flags);
+#endif
+       ffbRenderPrimitive(ctx, GL_LINES);
+       for (i = start + 1; i < count; i += 2) {
+               ffb_vertex *v0 = &fmesa->verts[i - 1];
+               ffb_vertex *v1 = &fmesa->verts[i - 0];
+
+               FFBFifo(fmesa, (1 + FFB_PRIM_COLOR_COST +
+                               (FFB_VERTEX_COLOR_COST * 2) + 6));
+
+               RESET_STIPPLE;
+
+               FFB_SET_PRIM_COLOR(v1);
+
+               FFB_SET_VERTEX_COLOR(v0);
+               ffb->z   = FFB_GET_Z(v0);
+               ffb->ryf = FFB_GET_Y(v0);
+               ffb->rxf = FFB_GET_X(v0);
+
+               FFB_SET_VERTEX_COLOR(v1);
+               ffb->z   = FFB_GET_Z(v1);
+               ffb->y   = FFB_GET_Y(v1);
+               ffb->x   = FFB_GET_X(v1);
+       }
+}
+
+static void TAG(ffb_vb_line_loop)(GLcontext *ctx, GLuint start, GLuint count, GLuint flags)
+{
+       GLint i;
+       IMPL_LOCAL_VARS;
+
+#ifdef FFB_RENDER_TRACE
+       fprintf(stderr, "%s: start(%d) count(%d) flags(%x)\n",
+               __FUNCTION__, start, count, flags);
+#endif
+       ffbRenderPrimitive(ctx, GL_LINE_LOOP);
+       if ((flags & PRIM_BEGIN) != 0) {
+               ffb_vertex *v0 = &fmesa->verts[ELT(start + 0)];
+               ffb_vertex *v1 = &fmesa->verts[ELT(start + 1)];
+
+               FFBFifo(fmesa, (1 + FFB_PRIM_COLOR_COST +
+                               ((FFB_VERTEX_COLOR_COST * 2) + (3 * 2))));
+
+               RESET_STIPPLE;
+
+               FFB_SET_PRIM_COLOR(v1);
+
+               FFB_SET_VERTEX_COLOR(v0);
+               ffb->z   = FFB_GET_Z(v0);
+               ffb->ryf = FFB_GET_Y(v0);
+               ffb->rxf = FFB_GET_X(v0);
+
+               FFB_SET_VERTEX_COLOR(v1);
+               ffb->z   = FFB_GET_Z(v1);
+               ffb->y   = FFB_GET_Y(v1);
+               ffb->x   = FFB_GET_X(v1);
+       }
+       for (i = start + 2; i < count; i++) {
+               ffb_vertex *v0 = &fmesa->verts[ELT(i)];
+
+               FFBFifo(fmesa, (FFB_PRIM_COLOR_COST +
+                               (FFB_VERTEX_COLOR_COST + 3)));
+
+               FFB_SET_PRIM_COLOR(v0);
+
+               FFB_SET_VERTEX_COLOR(v0);
+               ffb->z   = FFB_GET_Z(v0);
+               ffb->y   = FFB_GET_Y(v0);
+               ffb->x   = FFB_GET_X(v0);
+       }
+       if ((flags & PRIM_END) != 0) {
+               ffb_vertex *v0 = &fmesa->verts[ELT(start)];
+
+               FFBFifo(fmesa, (FFB_PRIM_COLOR_COST +
+                               (FFB_VERTEX_COLOR_COST + 3)));
+
+               FFB_SET_PRIM_COLOR(v0);
+
+               FFB_SET_VERTEX_COLOR(v0);
+               ffb->z   = FFB_GET_Z(v0);
+               ffb->y   = FFB_GET_Y(v0);
+               ffb->x   = FFB_GET_X(v0);
+       }
+
+       fmesa->ffbScreen->rp_active = 1;
+}
+
+static void TAG(ffb_vb_line_strip)(GLcontext *ctx, GLuint start, GLuint count, GLuint flags)
+{
+       GLint i;
+       FFB_DECLARE_CACHED_COLOR(cached_fg)
+       IMPL_LOCAL_VARS;
+
+#ifdef FFB_RENDER_TRACE
+       fprintf(stderr, "%s: start(%d) count(%d) flags(%x)\n",
+               __FUNCTION__, start, count, flags);
+#endif
+       ffbRenderPrimitive(ctx, GL_LINE_STRIP);
+       FFBFifo(fmesa, (1 + FFB_PRIM_COLOR_COST +
+                       ((FFB_VERTEX_COLOR_COST * 2) + (3 * 2))));
+
+       RESET_STIPPLE;
+
+       {
+               ffb_vertex *v0 = &fmesa->verts[ELT(start + 0)];
+               ffb_vertex *v1 = &fmesa->verts[ELT(start + 1)];
+
+               FFB_COMPUTE_CACHED_COLOR(cached_fg, v0);
+               FFB_CACHED_COLOR_SET(cached_fg);
+
+               FFB_SET_VERTEX_COLOR(v0);
+               ffb->z = FFB_GET_Z(v0);
+               ffb->ryf = FFB_GET_Y(v0);
+               ffb->rxf = FFB_GET_X(v0);
+
+               FFB_SET_VERTEX_COLOR(v1);
+               ffb->z = FFB_GET_Z(v1);
+               ffb->y = FFB_GET_Y(v1);
+               ffb->x = FFB_GET_X(v1);
+       }
+
+       for (i = start + 2; i < count; i++) {
+               ffb_vertex *v1 = &fmesa->verts[ELT(i - 0)];
+               FFB_DECLARE_CACHED_COLOR(new_fg)
+
+               FFB_COMPUTE_CACHED_COLOR(new_fg, v1);
+               if (FFB_CACHED_COLOR_SAME(cached_fg, new_fg)) {
+                       FFBFifo(fmesa, ((FFB_VERTEX_COLOR_COST * 1) + (3 * 1)));
+               } else {
+                       FFBFifo(fmesa, (FFB_PRIM_COLOR_COST +
+                                       (FFB_VERTEX_COLOR_COST * 1) + (3 * 1)));
+                       FFB_CACHED_COLOR_UPDATE(cached_fg, new_fg);
+               }
+
+               FFB_SET_VERTEX_COLOR(v1);
+               ffb->z   = FFB_GET_Z(v1);
+               ffb->y   = FFB_GET_Y(v1);
+               ffb->x   = FFB_GET_X(v1);
+       }
+
+       fmesa->ffbScreen->rp_active = 1;
+}
+#endif /* !(IND & (FFB_TRI_CULL_BIT)) */
+
+/* OK, now things start getting fun :-) */
+#if (IND & (FFB_TRI_CULL_BIT))
+#define FFB_AREA_DECLARE       GLfloat cc, ex, ey, fx, fy;
+#define FFB_COMPUTE_AREA_TRI(V0, V1, V2)       \
+{      ex = (V1)->x - (V0)->x;                 \
+       ey = (V1)->y - (V0)->y;                 \
+       fx = (V2)->x - (V0)->x;                 \
+       fy = (V2)->y - (V0)->y;                 \
+       cc = ex*fy-ey*fx;                       \
+}
+#define FFB_COMPUTE_AREA_QUAD(V0, V1, V2, V3)  \
+{      ex = (V2)->x - (V0)->x;                 \
+       ey = (V2)->y - (V0)->y;                 \
+       fx = (V3)->x - (V1)->x;                 \
+       fy = (V3)->y - (V1)->y;                 \
+       cc = ex*fy-ey*fx;                       \
+}
+#else
+#define FFB_AREA_DECLARE                       /**/
+#define FFB_COMPUTE_AREA_TRI(V0, V1, V2)       do { } while(0)
+#define FFB_COMPUTE_AREA_QUAD(V0, V1, V2, V3)  do { } while(0)
+#endif
+
+#if (IND & FFB_TRI_CULL_BIT)
+#define FFB_CULL_TRI(CULL_ACTION)              \
+       if (cc * fmesa->backface_sign > fmesa->ffb_zero) {      \
+               CULL_ACTION                     \
+       }
+#define FFB_CULL_QUAD(CULL_ACTION)             \
+       if (cc * fmesa->backface_sign > fmesa->ffb_zero) {      \
+               CULL_ACTION                     \
+       }
+#else
+#define FFB_CULL_TRI(CULL_ACTION)      do { } while (0)
+#define FFB_CULL_QUAD(CULL_ACTION)     do { } while (0)
+#endif
+
+static void TAG(ffb_vb_triangles)(GLcontext *ctx, GLuint start, GLuint count, GLuint flags)
+{
+       GLint i;
+       IMPL_LOCAL_VARS;
+
+#ifdef FFB_RENDER_TRACE
+       fprintf(stderr, "%s: start(%d) count(%d) flags(%x)\n",
+               __FUNCTION__, start, count, flags);
+#endif
+       ffbRenderPrimitive(ctx, GL_TRIANGLES);
+       for (i = start + 2; i < count; i += 3) {
+               ffb_vertex *v0 = &fmesa->verts[ELT(i - 2)];
+               ffb_vertex *v1 = &fmesa->verts[ELT(i - 1)];
+               ffb_vertex *v2 = &fmesa->verts[ELT(i - 0)];
+               FFB_AREA_DECLARE
+
+               FFB_COMPUTE_AREA_TRI(v0, v1, v2);
+               FFB_CULL_TRI(continue;);
+
+               FFBFifo(fmesa, (FFB_PRIM_COLOR_COST +
+                               (FFB_VERTEX_COLOR_COST * 3) + 9));
+               FFB_SET_PRIM_COLOR(v2);
+
+               FFB_SET_VERTEX_COLOR(v0);
+               ffb->z   = FFB_GET_Z(v0);
+               ffb->ryf = FFB_GET_Y(v0);
+               ffb->rxf = FFB_GET_X(v0);
+
+               FFB_SET_VERTEX_COLOR(v1);
+               ffb->z   = FFB_GET_Z(v1);
+               ffb->y   = FFB_GET_Y(v1);
+               ffb->x   = FFB_GET_X(v1);
+
+               FFB_SET_VERTEX_COLOR(v2);
+               ffb->z   = FFB_GET_Z(v2);
+               ffb->y   = FFB_GET_Y(v2);
+               ffb->x   = FFB_GET_X(v2);
+       }
+
+       fmesa->ffbScreen->rp_active = 1;
+}
+
+static void TAG(ffb_vb_tri_strip)(GLcontext *ctx, GLuint start, GLuint count, GLuint flags)
+{
+       GLint i;
+       GLint parity = 0;
+       IMPL_LOCAL_VARS;
+
+#ifdef FFB_RENDER_TRACE
+       fprintf(stderr, "%s: start(%d) count(%d) flags(%x)\n",
+               __FUNCTION__, start, count, flags);
+#endif
+       ffbRenderPrimitive(ctx, GL_TRIANGLE_STRIP);
+       if ((flags & PRIM_PARITY) != 0)
+               parity = 1;
+
+       i = start + 2;
+       goto something_clipped;
+
+ something_clipped:
+       for (; i < count; i++, parity ^= 1) {
+               ffb_vertex *v0 = &fmesa->verts[ELT(i - 2 + parity)];
+               ffb_vertex *v1 = &fmesa->verts[ELT(i - 1 - parity)];
+               ffb_vertex *v2 = &fmesa->verts[ELT(i - 0)];
+               FFB_AREA_DECLARE
+
+               FFB_COMPUTE_AREA_TRI(v0, v1, v2);
+               FFB_CULL_TRI(continue;);
+
+               FFBFifo(fmesa, (FFB_PRIM_COLOR_COST +
+                               (FFB_VERTEX_COLOR_COST * 3) + 9));
+               FFB_SET_PRIM_COLOR(v2);
+
+               FFB_SET_VERTEX_COLOR(v0);
+               ffb->z   = FFB_GET_Z(v0);
+               ffb->ryf = FFB_GET_Y(v0);
+               ffb->rxf = FFB_GET_X(v0);
+
+               FFB_SET_VERTEX_COLOR(v1);
+               ffb->z   = FFB_GET_Z(v1);
+               ffb->y   = FFB_GET_Y(v1);
+               ffb->x   = FFB_GET_X(v1);
+
+               FFB_SET_VERTEX_COLOR(v2);
+               ffb->z   = FFB_GET_Z(v2);
+               ffb->y   = FFB_GET_Y(v2);
+               ffb->x   = FFB_GET_X(v2);
+
+               i++;
+               parity ^= 1;
+               break;
+       }
+
+       for (; i < count; i++, parity ^= 1) {
+               ffb_vertex *v0 = &fmesa->verts[ELT(i - 2 + parity)];
+               ffb_vertex *v1 = &fmesa->verts[ELT(i - 1 - parity)];
+               ffb_vertex *v2 = &fmesa->verts[ELT(i - 0)];
+               FFB_AREA_DECLARE
+               (void) v0; (void) v1;
+
+               FFB_COMPUTE_AREA_TRI(v0, v1, v2);
+               FFB_CULL_TRI(i++; parity^=1; goto something_clipped;);
+
+               FFBFifo(fmesa, (FFB_PRIM_COLOR_COST +
+                               (FFB_VERTEX_COLOR_COST * 1) + 3));
+               FFB_SET_PRIM_COLOR(v2);
+
+               FFB_SET_VERTEX_COLOR(v2);
+               ffb->z   = FFB_GET_Z(v2);
+               ffb->y   = FFB_GET_Y(v2);
+               ffb->x   = FFB_GET_X(v2);
+       }
+
+       fmesa->ffbScreen->rp_active = 1;
+}
+
+static void TAG(ffb_vb_tri_fan)(GLcontext *ctx, GLuint start, GLuint count, GLuint flags)
+{
+       GLint i;
+       IMPL_LOCAL_VARS;
+
+#ifdef FFB_RENDER_TRACE
+       fprintf(stderr, "%s: start(%d) count(%d) flags(%x)\n",
+               __FUNCTION__, start, count, flags);
+#endif
+       ffbRenderPrimitive(ctx, GL_TRIANGLE_FAN);
+
+       i = start + 2;
+       goto something_clipped;
+
+ something_clipped:
+       for ( ; i < count; i++) {
+               ffb_vertex *v0 = &fmesa->verts[ELT(start)];
+               ffb_vertex *v1 = &fmesa->verts[ELT(i - 1)];
+               ffb_vertex *v2 = &fmesa->verts[ELT(i - 0)];
+               FFB_AREA_DECLARE
+
+               FFB_COMPUTE_AREA_TRI(v0, v1, v2);
+               FFB_CULL_TRI(continue;);
+
+               FFBFifo(fmesa, (FFB_PRIM_COLOR_COST +
+                               (FFB_VERTEX_COLOR_COST * 3) + 9));
+               FFB_SET_PRIM_COLOR(v2);
+
+               FFB_SET_VERTEX_COLOR(v0);
+               ffb->z   = FFB_GET_Z(v0);
+               ffb->ryf = FFB_GET_Y(v0);
+               ffb->rxf = FFB_GET_X(v0);
+
+               FFB_SET_VERTEX_COLOR(v1);
+               ffb->z   = FFB_GET_Z(v1);
+               ffb->y   = FFB_GET_Y(v1);
+               ffb->x   = FFB_GET_X(v1);
+
+               FFB_SET_VERTEX_COLOR(v2);
+               ffb->z   = FFB_GET_Z(v2);
+               ffb->y   = FFB_GET_Y(v2);
+               ffb->x   = FFB_GET_X(v2);
+
+               i++;
+               break;
+       }
+
+       for (; i < count; i++) {
+               ffb_vertex *v0 = &fmesa->verts[ELT(start)];
+               ffb_vertex *v1 = &fmesa->verts[ELT(i - 1)];
+               ffb_vertex *v2 = &fmesa->verts[ELT(i - 0)];
+               FFB_AREA_DECLARE
+               (void) v0; (void) v1;
+
+               FFB_COMPUTE_AREA_TRI(v0, v1, v2);
+               FFB_CULL_TRI(i++; goto something_clipped;);
+
+               FFBFifo(fmesa, (FFB_PRIM_COLOR_COST +
+                               (FFB_VERTEX_COLOR_COST * 1) + 3));
+               FFB_SET_PRIM_COLOR(v2);
+
+               FFB_SET_VERTEX_COLOR(v2);
+               ffb->z    = FFB_GET_Z(v2);
+               ffb->dmyf = FFB_GET_Y(v2);
+               ffb->dmxf = FFB_GET_X(v2);
+       }
+
+       fmesa->ffbScreen->rp_active = 1;
+}
+
+static void TAG(ffb_vb_poly)(GLcontext *ctx, GLuint start, GLuint count, GLuint flags)
+{
+       GLint i;
+       IMPL_LOCAL_VARS;
+
+#ifdef FFB_RENDER_TRACE
+       fprintf(stderr, "%s: start(%d) count(%d) flags(%x)\n",
+               __FUNCTION__, start, count, flags);
+#endif
+       ffbRenderPrimitive(ctx, GL_POLYGON);
+
+       /* XXX Optimize XXX */
+       for (i = start + 2; i < count; i++) {
+               ffb_vertex *v0 = &fmesa->verts[ELT(i - 1)];
+               ffb_vertex *v1 = &fmesa->verts[ELT(i)];
+               ffb_vertex *v2 = &fmesa->verts[ELT(start)];
+               FFB_AREA_DECLARE
+
+               FFB_COMPUTE_AREA_TRI(v0, v1, v2);
+               FFB_CULL_TRI(continue;);
+
+               FFBFifo(fmesa, (FFB_PRIM_COLOR_COST +
+                               (FFB_VERTEX_COLOR_COST * 3) + 9));
+               FFB_SET_PRIM_COLOR(v2);
+
+               FFB_SET_VERTEX_COLOR(v0);
+               ffb->z   = FFB_GET_Z(v0);
+               ffb->ryf = FFB_GET_Y(v0);
+               ffb->rxf = FFB_GET_X(v0);
+
+               FFB_SET_VERTEX_COLOR(v1);
+               ffb->z   = FFB_GET_Z(v1);
+               ffb->y   = FFB_GET_Y(v1);
+               ffb->x   = FFB_GET_X(v1);
+
+               FFB_SET_VERTEX_COLOR(v2);
+               ffb->z   = FFB_GET_Z(v2);
+               ffb->y   = FFB_GET_Y(v2);
+               ffb->x   = FFB_GET_X(v2);
+       }
+
+       fmesa->ffbScreen->rp_active = 1;
+}
+
+static void TAG(ffb_vb_quads)(GLcontext *ctx, GLuint start, GLuint count, GLuint flags)
+{
+       GLint i;
+       IMPL_LOCAL_VARS;
+
+#ifdef FFB_RENDER_TRACE
+       fprintf(stderr, "%s: start(%d) count(%d) flags(%x)\n",
+               __FUNCTION__, start, count, flags);
+#endif
+       ffbRenderPrimitive(ctx, GL_QUADS);
+
+       for (i = start + 3; i < count; i += 4) {
+               ffb_vertex *v0 = &fmesa->verts[ELT(i - 3)];
+               ffb_vertex *v1 = &fmesa->verts[ELT(i - 2)];
+               ffb_vertex *v2 = &fmesa->verts[ELT(i - 1)];
+               ffb_vertex *v3 = &fmesa->verts[ELT(i - 0)];
+               FFB_AREA_DECLARE
+
+               FFB_COMPUTE_AREA_QUAD(v0, v1, v2, v3);
+               FFB_CULL_QUAD(continue;);
+
+               FFBFifo(fmesa, (FFB_PRIM_COLOR_COST +
+                               (FFB_VERTEX_COLOR_COST * 4) + 12));
+               FFB_SET_PRIM_COLOR(v3);
+
+               FFB_SET_VERTEX_COLOR(v0);
+               ffb->z    = FFB_GET_Z(v0);
+               ffb->ryf  = FFB_GET_Y(v0);
+               ffb->rxf  = FFB_GET_X(v0);
+
+               FFB_SET_VERTEX_COLOR(v1);
+               ffb->z    = FFB_GET_Z(v1);
+               ffb->y    = FFB_GET_Y(v1);
+               ffb->x    = FFB_GET_X(v1);
+
+               FFB_SET_VERTEX_COLOR(v2);
+               ffb->z    = FFB_GET_Z(v2);
+               ffb->y    = FFB_GET_Y(v2);
+               ffb->x    = FFB_GET_X(v2);
+
+               FFB_SET_VERTEX_COLOR(v3);
+               ffb->z    = FFB_GET_Z(v3);
+               ffb->dmyf = FFB_GET_Y(v3);
+               ffb->dmxf = FFB_GET_X(v3);
+       }
+
+       fmesa->ffbScreen->rp_active = 1;
+}
+
+static void TAG(ffb_vb_quad_strip)(GLcontext *ctx, GLuint start, GLuint count, GLuint flags)
+{
+       GLint i;
+       IMPL_LOCAL_VARS;
+
+#ifdef FFB_RENDER_TRACE
+       fprintf(stderr, "%s: start(%d) count(%d) flags(%x)\n",
+               __FUNCTION__, start, count, flags);
+#endif
+       ffbRenderPrimitive(ctx, GL_QUAD_STRIP);
+
+       /* XXX Optimize XXX */
+       for (i = start + 3; i < count; i += 2) {
+               ffb_vertex *v0 = &fmesa->verts[ELT(i - 1)];
+               ffb_vertex *v1 = &fmesa->verts[ELT(i - 3)];
+               ffb_vertex *v2 = &fmesa->verts[ELT(i - 2)];
+               ffb_vertex *v3 = &fmesa->verts[ELT(i - 0)];
+               FFB_AREA_DECLARE
+
+               FFB_COMPUTE_AREA_QUAD(v0, v1, v2, v3);
+               FFB_CULL_QUAD(continue;);
+
+               FFBFifo(fmesa, (FFB_PRIM_COLOR_COST +
+                               (FFB_VERTEX_COLOR_COST * 4) + 12));
+               FFB_SET_PRIM_COLOR(v3);
+
+               FFB_DUMP_VERTEX(v0);
+               FFB_SET_VERTEX_COLOR(v0);
+               ffb->z    = FFB_GET_Z(v0);
+               ffb->ryf  = FFB_GET_Y(v0);
+               ffb->rxf  = FFB_GET_X(v0);
+
+               FFB_DUMP_VERTEX(v1);
+               FFB_SET_VERTEX_COLOR(v1);
+               ffb->z    = FFB_GET_Z(v1);
+               ffb->y    = FFB_GET_Y(v1);
+               ffb->x    = FFB_GET_X(v1);
+
+               FFB_DUMP_VERTEX(v2);
+               FFB_SET_VERTEX_COLOR(v2);
+               ffb->z    = FFB_GET_Z(v2);
+               ffb->y    = FFB_GET_Y(v2);
+               ffb->x    = FFB_GET_X(v2);
+
+               FFB_DUMP_VERTEX(v3);
+               FFB_SET_VERTEX_COLOR(v3);
+               ffb->z    = FFB_GET_Z(v3);
+               ffb->dmyf = FFB_GET_Y(v3);
+               ffb->dmxf = FFB_GET_X(v3);
+       }
+
+       fmesa->ffbScreen->rp_active = 1;
+}
+
+static void (*TAG(render_tab)[GL_POLYGON + 2])(GLcontext *, GLuint, GLuint, GLuint) =
+{
+#if !(IND & (FFB_TRI_CULL_BIT))
+       TAG(ffb_vb_points),
+       TAG(ffb_vb_lines),
+       TAG(ffb_vb_line_loop),
+       TAG(ffb_vb_line_strip),
+#else
+       NULL,
+       NULL,
+       NULL,
+       NULL,
+#endif
+       TAG(ffb_vb_triangles),
+       TAG(ffb_vb_tri_strip),
+       TAG(ffb_vb_tri_fan),
+       TAG(ffb_vb_quads),
+       TAG(ffb_vb_quad_strip),
+       TAG(ffb_vb_poly),
+       ffb_vb_noop,
+};
+
+#undef IND
+#undef TAG
+
+#undef IMPL_LOCAL_VARS
+#undef FFB_DECLARE_CACHED_COLOR
+#undef FFB_COMPUTE_CACHED_COLOR
+#undef FFB_CACHED_COLOR_SAME
+#undef FFB_CACHED_COLOR_SET
+#undef FFB_CACHED_COLOR_UPDATE
+#undef FFB_SET_PRIM_COLOR
+#undef FFB_PRIM_COLOR_COST
+#undef FFB_SET_VERTEX_COLOR
+#undef FFB_VERTEX_COLOR_COST
+#undef RESET_STIPPLE
+#undef FFB_AREA_DECLARE
+#undef FFB_COMPUTE_AREA_TRI
+#undef FFB_COMPUTE_AREA_QUAD
+#undef FFB_CULL_TRI
+#undef FFB_CULL_QUAD
diff --git a/src/mesa/drivers/dri/ffb/ffb_span.c b/src/mesa/drivers/dri/ffb/ffb_span.c
new file mode 100644 (file)
index 0000000..6927945
--- /dev/null
@@ -0,0 +1,142 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_span.c,v 1.2 2002/02/22 21:32:59 dawes Exp $
+ *
+ * GLX Hardware Device Driver for Sun Creator/Creator3D
+ * Copyright (C) 2000 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 <davem@redhat.com>
+ */
+
+#include "mtypes.h"
+#include "ffb_dd.h"
+#include "ffb_span.h"
+#include "ffb_context.h"
+#include "ffb_lock.h"
+
+#include "swrast/swrast.h"
+
+#define DBG 0
+
+#define HW_LOCK()                                              \
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);                 \
+       if (!fmesa->hw_locked)                                  \
+               LOCK_HARDWARE(fmesa);
+
+#define HW_UNLOCK()                    \
+       if (!fmesa->hw_locked)          \
+               UNLOCK_HARDWARE(fmesa); \
+
+#define LOCAL_VARS                                             \
+       __DRIdrawablePrivate *dPriv = fmesa->driDrawable;       \
+       GLuint height = dPriv->h;                               \
+        GLuint p;                                              \
+       char *buf;                                              \
+        (void) p
+
+#define INIT_MONO_PIXEL(p, color)              \
+        p = ((color[0] <<  0) |                        \
+            (color[1] << 8) |                  \
+            (color[2] << 16))
+
+/* We use WID clipping, so this test always passes. */
+#define CLIPPIXEL(__x, __y)    (1)
+
+/* And also, due to WID clipping, we need not do anything
+ * special here.
+ */
+#define CLIPSPAN(__x,__y,__n,__x1,__n1,__i)            \
+       __n1 = __n;                                     \
+       __x1 = __x;                                     \
+
+#define HW_CLIPLOOP()                                                  \
+do {   unsigned int fbc, ppc, cmp;                                     \
+       FFBWait(fmesa, fmesa->regs);                                    \
+       fbc = fmesa->regs->fbc; ppc = fmesa->regs->ppc; cmp = fmesa->regs->cmp; \
+       fmesa->regs->fbc = ((fbc &                                      \
+                            ~(FFB_FBC_WB_C | FFB_FBC_ZE_MASK | FFB_FBC_RGBE_MASK)) \
+                           | (FFB_FBC_ZE_OFF | FFB_FBC_RGBE_MASK));    \
+       fmesa->regs->ppc = ((ppc &                                      \
+                            ~(FFB_PPC_XS_MASK | FFB_PPC_ABE_MASK | FFB_PPC_DCE_MASK | \
+                              FFB_PPC_APE_MASK | FFB_PPC_CS_MASK))     \
+                           | (FFB_PPC_XS_WID | FFB_PPC_ABE_DISABLE |   \
+                              FFB_PPC_DCE_DISABLE | FFB_PPC_APE_DISABLE | \
+                              FFB_PPC_CS_VAR));                        \
+       fmesa->regs->cmp = ((cmp & ~(0xff << 16)) | (0x80 << 16));      \
+       fmesa->ffbScreen->rp_active = 1;                                \
+       FFBWait(fmesa, fmesa->regs);                                    \
+       buf = (char *)(fmesa->sfb32 + (dPriv->x << 2) + (dPriv->y << 13));\
+       if (dPriv->numClipRects) {
+
+#define HW_ENDCLIPLOOP()       \
+       }                       \
+       fmesa->regs->fbc = fbc; \
+       fmesa->regs->ppc = ppc; \
+       fmesa->regs->cmp = cmp; \
+       fmesa->ffbScreen->rp_active = 1; \
+} while(0)
+
+#define Y_FLIP(__y)            (height - __y)
+
+#define READ_RGBA(rgba,__x,__y)                                        \
+do {   GLuint p = *(GLuint *)(buf + ((__x)<<2) + ((__y)<<13)); \
+       rgba[0] = (p >>  0) & 0xff;                             \
+       rgba[1] = (p >>  8) & 0xff;                             \
+       rgba[2] = (p >> 16) & 0xff;                             \
+       rgba[3] = 0xff;                                         \
+} while(0)
+
+#define WRITE_RGBA(__x, __y, __r, __g, __b, __a)               \
+       *(GLuint *)(buf + ((__x)<<2) + ((__y)<<13)) =           \
+               ((((__r) & 0xff) <<  0) |                       \
+                (((__g) & 0xff) <<  8) |                       \
+                (((__b) & 0xff) << 16))
+
+#define WRITE_PIXEL(__x, __y, __p) \
+       *(GLuint *)(buf + ((__x)<<2) + ((__y)<<13)) = (__p)
+
+#define TAG(x) ffb##x##_888
+
+#include <spantmp.h>
+
+void ffbDDInitSpanFuncs(GLcontext *ctx)
+{
+       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;
+}
diff --git a/src/mesa/drivers/dri/ffb/ffb_span.h b/src/mesa/drivers/dri/ffb/ffb_span.h
new file mode 100644 (file)
index 0000000..00501e8
--- /dev/null
@@ -0,0 +1,8 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_span.h,v 1.1 2000/06/20 05:08:39 dawes Exp $ */
+
+#ifndef _FFB_SPAN_H
+#define _FFB_SPAN_H
+
+extern void ffbDDInitSpanFuncs(GLcontext *ctx);
+
+#endif /* !(_FFB_SPAN_H) */
diff --git a/src/mesa/drivers/dri/ffb/ffb_state.c b/src/mesa/drivers/dri/ffb/ffb_state.c
new file mode 100644 (file)
index 0000000..ba9bab9
--- /dev/null
@@ -0,0 +1,1247 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_state.c,v 1.5 2002/10/30 12:51:27 alanh 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 <davem@redhat.com>
+ */
+
+#include "mtypes.h"
+#include "colormac.h"
+#include "mm.h"
+#include "ffb_dd.h"
+#include "ffb_span.h"
+#include "ffb_depth.h"
+#include "ffb_context.h"
+#include "ffb_vb.h"
+#include "ffb_tris.h"
+#include "ffb_state.h"
+#include "ffb_lock.h"
+#include "extensions.h"
+#include "enums.h"
+
+#include "swrast/swrast.h"
+#include "array_cache/acache.h"
+#include "tnl/tnl.h"
+#include "swrast_setup/swrast_setup.h"
+
+#include "tnl/t_pipeline.h"
+
+#undef STATE_TRACE
+
+static unsigned int ffbComputeAlphaFunc(GLcontext *ctx)
+{
+       unsigned int xclip;
+       GLubyte alphaRef;
+
+#ifdef STATE_TRACE
+       fprintf(stderr, "ffbDDAlphaFunc: func(%s) ref(%02x)\n",
+               _mesa_lookup_enum_by_nr(ctx->Color.AlphaFunc),
+               ctx->Color.AlphaRef & 0xff);
+#endif
+
+       switch (ctx->Color.AlphaFunc) {
+       case GL_NEVER: xclip = FFB_XCLIP_TEST_NEVER; break;
+       case GL_LESS: xclip = FFB_XCLIP_TEST_LT; break;
+       case GL_EQUAL: xclip = FFB_XCLIP_TEST_EQ; break;
+       case GL_LEQUAL: xclip = FFB_XCLIP_TEST_LE; break;
+       case GL_GREATER: xclip = FFB_XCLIP_TEST_GT; break;
+       case GL_NOTEQUAL: xclip = FFB_XCLIP_TEST_NE; break;
+       case GL_GEQUAL: xclip = FFB_XCLIP_TEST_GE; break;
+       case GL_ALWAYS: xclip = FFB_XCLIP_TEST_ALWAYS; break;
+
+       default:
+               return FFB_XCLIP_TEST_ALWAYS | 0x00;
+       }
+
+       CLAMPED_FLOAT_TO_UBYTE(alphaRef, ctx->Color.AlphaRef);
+       xclip |= (alphaRef & 0xff);
+
+       return xclip;
+}
+
+static void ffbDDAlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+
+       if (ctx->Color.AlphaEnabled) {
+               unsigned int xclip = ffbComputeAlphaFunc(ctx);
+
+               if (fmesa->xclip != xclip) {
+                       fmesa->xclip = xclip;
+                       FFB_MAKE_DIRTY(fmesa, FFB_STATE_XCLIP, 1);
+               }
+       }
+}
+
+static void ffbDDBlendEquation(GLcontext *ctx, GLenum mode)
+{
+
+#ifdef STATE_TRACE
+       fprintf(stderr, "ffbDDBlendEquation: mode(%s)\n", _mesa_lookup_enum_by_nr(mode));
+#endif
+       FALLBACK( ctx, (mode != GL_FUNC_ADD_EXT), FFB_BADATTR_BLENDEQN);
+}
+
+static void ffbDDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       unsigned int blendc = 1 << 4;
+
+#ifdef STATE_TRACE
+       fprintf(stderr, "ffbDDBlendFunc: sfactor(%s) dfactor(%s)\n",
+               _mesa_lookup_enum_by_nr(sfactor), _mesa_lookup_enum_by_nr(dfactor));
+#endif
+       switch (ctx->Color.BlendSrcRGB) {
+       case GL_ZERO:
+               blendc |= (0 << 0);
+               break;
+
+       case GL_ONE:
+               blendc |= (1 << 0);
+               break;
+
+       case GL_ONE_MINUS_SRC_ALPHA:
+               blendc |= (2 << 0);
+               break;
+
+       case GL_SRC_ALPHA:
+               blendc |= (3 << 0);
+               break;
+
+       default:
+               if (ctx->Color.BlendEnabled)
+                       FALLBACK( ctx, FFB_BADATTR_BLENDFUNC, GL_TRUE );
+               return;
+       };
+
+       switch (ctx->Color.BlendDstRGB) {
+       case GL_ZERO:
+               blendc |= (0 << 2);
+               break;
+
+       case GL_ONE:
+               blendc |= (1 << 2);
+               break;
+
+       case GL_ONE_MINUS_SRC_ALPHA:
+               blendc |= (2 << 2);
+               break;
+
+       case GL_SRC_ALPHA:
+               blendc |= (3 << 2);
+               break;
+
+       default:
+               if (ctx->Color.BlendEnabled)
+                       FALLBACK( ctx, FFB_BADATTR_BLENDFUNC, GL_TRUE );
+               return;
+       };
+
+       if (ctx->Color.BlendEnabled &&
+           ctx->Color.ColorLogicOpEnabled &&
+           ctx->Color.LogicOp != GL_COPY) {
+               /* We could avoid this if sfactor is GL_ONE and
+                * dfactor is GL_ZERO.  I do not think that is even
+                * worthwhile to check because if someone is using
+                * blending they use more interesting settings and
+                * also it would add more state tracking to a lot
+                * of the code in this file.
+                */
+               FALLBACK(ctx, FFB_BADATTR_BLENDROP, GL_TRUE);
+               return;
+       }
+
+       FALLBACK( ctx, (FFB_BADATTR_BLENDFUNC|FFB_BADATTR_BLENDROP), GL_FALSE );
+
+       if (blendc != fmesa->blendc) {
+               fmesa->blendc = blendc;
+               FFB_MAKE_DIRTY(fmesa, FFB_STATE_BLEND, 1);
+       }
+}
+
+static void ffbDDBlendFuncSeparate(GLcontext *ctx, GLenum sfactorRGB,
+                                  GLenum dfactorRGB, GLenum sfactorA,
+                                  GLenum dfactorA)
+{
+#ifdef STATE_TRACE
+       fprintf(stderr, "ffbDDBlendFuncSeparate: sRGB(%s) dRGB(%s) sA(%s) dA(%s)\n",
+               _mesa_lookup_enum_by_nr(sfactorRGB),
+               _mesa_lookup_enum_by_nr(dfactorRGB),
+               _mesa_lookup_enum_by_nr(sfactorA),
+               _mesa_lookup_enum_by_nr(dfactorA));
+#endif
+
+       ffbDDBlendFunc(ctx, sfactorRGB, dfactorRGB);
+}
+
+static void ffbDDDepthFunc(GLcontext *ctx, GLenum func)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       GLuint cmp;
+
+#ifdef STATE_TRACE
+       fprintf(stderr, "ffbDDDepthFunc: func(%s)\n",
+               _mesa_lookup_enum_by_nr(func));
+#endif
+
+       switch (func) {
+       case GL_NEVER:
+               cmp = FFB_CMP_MAGN_NEVER;
+               break;
+       case GL_ALWAYS:
+               cmp = FFB_CMP_MAGN_ALWAYS;
+               break;
+       case GL_LESS:
+               cmp = FFB_CMP_MAGN_LT;
+               break;
+       case GL_LEQUAL:
+               cmp = FFB_CMP_MAGN_LE;
+               break;
+       case GL_EQUAL:
+               cmp = FFB_CMP_MAGN_EQ;
+               break;
+       case GL_GREATER:
+               cmp = FFB_CMP_MAGN_GT;
+               break;
+       case GL_GEQUAL:
+               cmp = FFB_CMP_MAGN_GE;
+               break;
+       case GL_NOTEQUAL:
+               cmp = FFB_CMP_MAGN_NE;
+               break;
+       default:
+               return;
+       };
+
+       if (! ctx->Depth.Test)
+               cmp = FFB_CMP_MAGN_ALWAYS;
+
+       cmp <<= 16;
+       cmp = (fmesa->cmp & ~(0xff<<16)) | cmp;
+       if (cmp != fmesa->cmp) {
+               fmesa->cmp = cmp;
+               FFB_MAKE_DIRTY(fmesa, FFB_STATE_CMP, 1);
+       }
+}
+
+static void ffbDDDepthMask(GLcontext *ctx, GLboolean flag)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       GLuint fbc = fmesa->fbc;
+       GLboolean enabled_now;
+
+#ifdef STATE_TRACE
+       fprintf(stderr, "ffbDDDepthMask: flag(%d)\n", flag);
+#endif
+
+       if ((fbc & FFB_FBC_ZE_MASK) == FFB_FBC_ZE_OFF)
+               enabled_now = GL_FALSE;
+       else
+               enabled_now = GL_TRUE;
+
+       if (flag != enabled_now) {
+               fbc &= ~FFB_FBC_ZE_MASK;
+               if (flag) {
+                       fbc |= FFB_FBC_WB_C | FFB_FBC_ZE_ON;
+               } else {
+                       fbc |= FFB_FBC_ZE_OFF;
+                       fbc &= ~FFB_FBC_WB_C;
+               }
+               fmesa->fbc = fbc;
+               FFB_MAKE_DIRTY(fmesa, FFB_STATE_FBC, 1);
+       }
+}
+
+static void ffbDDStencilFunc(GLcontext *ctx, GLenum func, GLint ref, GLuint mask)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       unsigned int stencil, stencilctl, consty;
+
+       /* We will properly update sw/hw state when stenciling is
+        * enabled.
+        */
+       if (! ctx->Stencil.Enabled)
+               return;
+
+       stencilctl = fmesa->stencilctl;
+       stencilctl &= ~(7 << 16);
+
+       switch (func) {
+       case GL_ALWAYS:         stencilctl |= (0 << 16); break;
+       case GL_GREATER:        stencilctl |= (1 << 16); break;
+       case GL_EQUAL:          stencilctl |= (2 << 16); break;
+       case GL_GEQUAL:         stencilctl |= (3 << 16); break;
+       case GL_NEVER:          stencilctl |= (4 << 16); break;
+       case GL_LEQUAL:         stencilctl |= (5 << 16); break;
+       case GL_NOTEQUAL:       stencilctl |= (6 << 16); break;
+       case GL_LESS:           stencilctl |= (7 << 16); break;
+
+       default:
+               return;
+       };
+
+       consty = ref & 0xf;
+
+       stencil = fmesa->stencil;
+       stencil &= ~(0xf << 20);
+       stencil |= (mask & 0xf) << 20;
+
+       if (fmesa->stencil != stencil ||
+           fmesa->stencilctl != stencilctl ||
+           fmesa->consty != consty) {
+               fmesa->stencil = stencil;
+               fmesa->stencilctl = stencilctl;
+               fmesa->consty = consty;
+               FFB_MAKE_DIRTY(fmesa, FFB_STATE_STENCIL, 6);
+       }
+}
+
+static void ffbDDStencilMask(GLcontext *ctx, GLuint mask)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+
+       mask &= 0xf;
+       if (fmesa->ypmask != mask) {
+               fmesa->ypmask = mask;
+               FFB_MAKE_DIRTY(fmesa, FFB_STATE_YPMASK, 1);
+       }
+}
+
+static void ffbDDStencilOp(GLcontext *ctx, GLenum fail, GLenum zfail, GLenum zpass)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       unsigned int stencilctl;
+
+       /* We will properly update sw/hw state when stenciling is
+        * enabled.
+        */
+       if (! ctx->Stencil.Enabled)
+               return;
+
+       stencilctl = fmesa->stencilctl;
+       stencilctl &= ~(0xfff00000);
+
+       switch (fail) {
+       case GL_ZERO:           stencilctl |= (0 << 28); break;
+       case GL_KEEP:           stencilctl |= (1 << 28); break;
+       case GL_INVERT:         stencilctl |= (2 << 28); break;
+       case GL_REPLACE:        stencilctl |= (3 << 28); break;
+       case GL_INCR:           stencilctl |= (4 << 28); break;
+       case GL_DECR:           stencilctl |= (5 << 28); break;
+
+       default:
+               return;
+       };
+
+       switch (zfail) {
+       case GL_ZERO:           stencilctl |= (0 << 24); break;
+       case GL_KEEP:           stencilctl |= (1 << 24); break;
+       case GL_INVERT:         stencilctl |= (2 << 24); break;
+       case GL_REPLACE:        stencilctl |= (3 << 24); break;
+       case GL_INCR:           stencilctl |= (4 << 24); break;
+       case GL_DECR:           stencilctl |= (5 << 24); break;
+
+       default:
+               return;
+       };
+
+       switch (zpass) {
+       case GL_ZERO:           stencilctl |= (0 << 20); break;
+       case GL_KEEP:           stencilctl |= (1 << 20); break;
+       case GL_INVERT:         stencilctl |= (2 << 20); break;
+       case GL_REPLACE:        stencilctl |= (3 << 20); break;
+       case GL_INCR:           stencilctl |= (4 << 20); break;
+       case GL_DECR:           stencilctl |= (5 << 20); break;
+
+       default:
+               return;
+       };
+
+       if (fmesa->stencilctl != stencilctl) {
+               fmesa->stencilctl = stencilctl;
+               FFB_MAKE_DIRTY(fmesa, FFB_STATE_STENCIL, 6);
+       }
+}
+
+static void ffbCalcViewportRegs(GLcontext *ctx)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
+       GLuint xmin, xmax, ymin, ymax, zmin, zmax;
+       unsigned int vcmin, vcmax;
+
+       xmin = ctx->Viewport.X + dPriv->x;
+       xmax = xmin + ctx->Viewport.Width;
+       ymax = dPriv->y + dPriv->h - ctx->Viewport.Y;
+       ymin = ymax - ctx->Viewport.Height;
+       if (ctx->Scissor.Enabled) {
+               GLuint sc_xmin, sc_xmax, sc_ymin, sc_ymax;
+
+               sc_xmin = ctx->Viewport.X + dPriv->x;
+               sc_xmax = sc_xmin + ctx->Viewport.Width;
+               sc_ymax = dPriv->y + dPriv->h - ctx->Viewport.Y;
+               sc_ymin = sc_ymax - ctx->Viewport.Height;
+               if (sc_xmin > xmin)
+                       xmin = sc_xmin;
+               if (sc_xmax < xmax)
+                       xmax = sc_xmax;
+               if (sc_ymin > ymin)
+                       ymin = sc_ymin;
+               if (sc_ymax < ymax)
+                       ymax = sc_ymax;
+       }
+       zmin = ((GLdouble)ctx->Viewport.Near * 0x0fffffff);
+       zmax = ((GLdouble)ctx->Viewport.Far  * 0x0fffffff);
+
+       vcmin = ((ymin & 0xffff) << 16) | (xmin & 0xffff);
+       vcmax = ((ymax & 0xffff) << 16) | (xmax & 0xffff);
+       if (fmesa->vclipmin != vcmin ||
+           fmesa->vclipmax != vcmax ||
+           fmesa->vclipzmin != zmin ||
+           fmesa->vclipzmax != zmax) {
+               fmesa->vclipmin = vcmin;
+               fmesa->vclipmax = vcmax;
+               fmesa->vclipzmin = zmin;
+               fmesa->vclipzmax = zmax;
+               FFB_MAKE_DIRTY(fmesa, FFB_STATE_CLIP, (4 + (4 * 2)));
+       }
+}
+
+void ffbCalcViewport(GLcontext *ctx)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       const GLfloat *v = ctx->Viewport._WindowMap.m;
+       GLfloat *m = fmesa->hw_viewport;
+       __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
+
+       m[MAT_SX] =   v[MAT_SX];
+       m[MAT_TX] =   v[MAT_TX] + dPriv->x + SUBPIXEL_X;
+       m[MAT_SY] = - v[MAT_SY];
+       m[MAT_TY] = - v[MAT_TY] + dPriv->h + dPriv->y + SUBPIXEL_Y;
+       m[MAT_SZ] =   v[MAT_SZ] * ((GLdouble)1.0 / (GLdouble)0x0fffffff);
+       m[MAT_TZ] =   v[MAT_TZ] * ((GLdouble)1.0 / (GLdouble)0x0fffffff);
+
+       fmesa->depth_scale = ((GLdouble)1.0 / (GLdouble)0x0fffffff);
+
+       ffbCalcViewportRegs(ctx);
+
+       fmesa->setupnewinputs |= VERT_BIT_CLIP;
+}
+
+static void ffbDDViewport(GLcontext *ctx, GLint x, GLint y,
+                         GLsizei width, GLsizei height)
+{
+       ffbCalcViewport(ctx);
+}
+
+static void ffbDDDepthRange(GLcontext *ctx, GLclampd nearval, GLclampd farval)
+{
+       ffbCalcViewport(ctx);
+}
+
+static void ffbDDScissor(GLcontext *ctx, GLint cx, GLint cy,
+                 GLsizei cw, GLsizei ch)
+{
+       ffbCalcViewport(ctx);
+}
+
+static void ffbDDDrawBuffer(GLcontext *ctx, GLenum buffer)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       unsigned int fbc = fmesa->fbc;
+
+#ifdef STATE_TRACE
+       fprintf(stderr, "ffbDDDrawBuffer: mode(%s)\n",
+               _mesa_lookup_enum_by_nr(buffer));
+#endif
+       fbc &= ~(FFB_FBC_WB_AB | FFB_FBC_RB_MASK);
+       switch (buffer) {
+       case FRONT_LEFT_BIT:
+               if (fmesa->back_buffer == 0)
+                       fbc |= FFB_FBC_WB_B | FFB_FBC_RB_B;
+               else
+                       fbc |= FFB_FBC_WB_A | FFB_FBC_RB_A;
+               break;
+
+       case BACK_LEFT_BIT:
+               if (fmesa->back_buffer == 0)
+                       fbc |= FFB_FBC_WB_A | FFB_FBC_RB_A;
+               else
+                       fbc |= FFB_FBC_WB_B | FFB_FBC_RB_B;
+               break;
+
+       case BACK_LEFT_BIT | FRONT_LEFT_BIT:
+               fbc |= FFB_FBC_WB_AB;
+               break;
+
+       default:
+               return;
+       };
+
+       if (fbc != fmesa->fbc) {
+               fmesa->fbc = fbc;
+               FFB_MAKE_DIRTY(fmesa, FFB_STATE_FBC, 1);
+       }
+}
+
+
+static void ffbDDReadBuffer(GLcontext *ctx, GLenum buffer)
+{
+   /* no-op, unless you implement h/w glRead/CopyPixels */
+}
+
+
+/*
+ * Specifies buffer for sw fallbacks (spans)
+ */
+static void ffbDDSetBuffer(GLcontext *ctx, GLframebuffer *colorBuffer,
+                          GLuint bufferBit)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       unsigned int fbc = fmesa->fbc;
+
+#ifdef STATE_TRACE
+       fprintf(stderr, "ffbDDSetReadBuffer: mode(%s)\n",
+               _mesa_lookup_enum_by_nr(buffer));
+#endif
+       fbc &= ~(FFB_FBC_RB_MASK);
+       switch (bufferBit) {
+       case FRONT_LEFT_BIT:
+               if (fmesa->back_buffer == 0)
+                       fbc |= FFB_FBC_RB_B;
+               else
+                       fbc |= FFB_FBC_RB_A;
+               break;
+
+       case BACK_LEFT_BIT:
+               if (fmesa->back_buffer == 0)
+                       fbc |= FFB_FBC_RB_A;
+               else
+                       fbc |= FFB_FBC_RB_B;
+               break;
+
+       default:
+               return;
+       };
+
+       if (fbc != fmesa->fbc) {
+               fmesa->fbc = fbc;
+               FFB_MAKE_DIRTY(fmesa, FFB_STATE_FBC, 1);
+       }
+}
+
+static void ffbDDClearColor(GLcontext *ctx, const GLfloat color[4])
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       GLubyte c[4];
+       CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
+       CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
+       CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
+
+       fmesa->clear_pixel = ((c[0] << 0) |
+                             (c[1] << 8) |
+                             (c[2] << 16));
+}
+
+static void ffbDDClearDepth(GLcontext *ctx, GLclampd depth)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+
+       fmesa->clear_depth = Z_FROM_MESA(depth * 4294967295.0f);
+}
+
+static void ffbDDClearStencil(GLcontext *ctx, GLint stencil)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+
+       fmesa->clear_stencil = stencil & 0xf;
+}
+
+/* XXX Actually, should I be using FBC controls for this? -DaveM */
+static void ffbDDColorMask(GLcontext *ctx,
+                          GLboolean r, GLboolean g,
+                          GLboolean b, GLboolean a)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       unsigned int new_pmask = 0x0;
+
+#ifdef STATE_TRACE
+       fprintf(stderr, "ffbDDColorMask: r(%d) g(%d) b(%d) a(%d)\n",
+               r, g, b, a);
+#endif
+       if (r)
+               new_pmask |= 0x000000ff;
+       if (g)
+               new_pmask |= 0x0000ff00;
+       if (b)
+               new_pmask |= 0x00ff0000;
+
+       if (fmesa->pmask != new_pmask) {
+               fmesa->pmask = new_pmask;
+               FFB_MAKE_DIRTY(fmesa, FFB_STATE_PMASK, 1);
+       }
+}
+
+static void ffbDDLogicOp(GLcontext *ctx, GLenum op)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       unsigned int rop;
+
+#ifdef STATE_TRACE
+       fprintf(stderr, "ffbDDLogicOp: op(%s)\n",
+               _mesa_lookup_enum_by_nr(op));
+#endif
+       switch (op) {
+       case GL_CLEAR: rop = FFB_ROP_ZERO; break;
+       case GL_SET: rop = FFB_ROP_ONES; break;
+       case GL_COPY: rop = FFB_ROP_NEW; break;
+       case GL_AND: rop = FFB_ROP_NEW_AND_OLD; break;
+       case GL_NAND: rop = FFB_ROP_NEW_AND_NOLD; break;
+       case GL_OR: rop = FFB_ROP_NEW_OR_OLD; break;
+       case GL_NOR: rop = FFB_ROP_NEW_OR_NOLD; break;
+       case GL_XOR: rop = FFB_ROP_NEW_XOR_OLD; break;
+       case GL_NOOP: rop = FFB_ROP_OLD; break;
+       case GL_COPY_INVERTED: rop = FFB_ROP_NNEW; break;
+       case GL_INVERT: rop = FFB_ROP_NOLD; break;
+       case GL_EQUIV: rop = FFB_ROP_NNEW_XOR_NOLD; break;
+       case GL_AND_REVERSE: rop = FFB_ROP_NEW_AND_NOLD; break;
+       case GL_AND_INVERTED: rop = FFB_ROP_NNEW_AND_OLD; break;
+       case GL_OR_REVERSE: rop = FFB_ROP_NEW_OR_NOLD; break;
+       case GL_OR_INVERTED: rop = FFB_ROP_NNEW_OR_OLD; break;
+
+       default:
+               return;
+       };
+
+       rop |= fmesa->rop & ~0xff;
+       if (rop != fmesa->rop) {
+               fmesa->rop = rop;
+               FFB_MAKE_DIRTY(fmesa, FFB_STATE_ROP, 1);
+
+               if (op == GL_COPY)
+                       FALLBACK( ctx, FFB_BADATTR_BLENDROP, GL_FALSE );
+       }
+}
+
+#if 0
+/* XXX Also need to track near/far just like 3dfx driver.
+ * XXX
+ * XXX Actually, that won't work, because the 3dfx chip works by
+ * XXX having 1/w coordinates fed to it for each primitive, and
+ * XXX it uses this to index it's 64 entry fog table.
+ */
+static void ffb_fog_linear(GLcontext *ctx, ffbContextPtr fmesa)
+{
+       GLfloat c = ctx->ProjectionMatrix.m[10];
+       GLfloat d = ctx->ProjectionMatrix.m[14];
+       GLfloat tz = ctx->Viewport.WindowMap.m[MAT_TZ];
+       GLfloat szInv = 1.0F / ctx->Viewport.WindowMap.m[MAT_SZ];
+       GLfloat fogEnd = ctx->Fog.End;
+       GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
+       GLfloat ndcz;
+       GLfloat eyez;
+       GLfloat Zzero, Zone;
+       unsigned int zb, zf;
+
+       /* Compute the Z at which f reaches 0.0, this is the full
+        * saturation point.
+        *
+        * Thus compute Z (as seen by the chip during rendering),
+        * such that:
+        *
+        *      0.0 = (fogEnd - eyez) * fogScale
+        *
+        * fogScale is usually not zero, thus we are looking for:
+        *
+        *      fogEnd = eyez
+        *
+        *      fogEnd = -d / (c + ((Z - tz) * szInv))
+        *      fogEnd * (c + ((Z - tz) * szInv)) = -d
+        *      (c + ((Z - tz) * szInv)) = -d / fogEnd
+        *      (Z - tz) * szInv = (-d / fogEnd) - c
+        *      (Z - tz) = ((-d / fogEnd) - c) / szInv
+        *      Z = (((-d / fogEnd) - c) / szInv) + tz
+        */
+       Zzero = (((-d / fogEnd) - c) / szInv) + tz;
+
+       /* Compute the Z at which f reaches 1.0, this is where
+        * the incoming frag's full intensity is shown.  This
+        * equation is:
+        *
+        *      1.0 = (fogEnd - eyez)
+        *
+        * We are looking for:
+        *
+        *      1.0 + eyez = fogEnd
+        *
+        *      1.0 + (-d / (c + ((Z - tz) * szInv))) = fogEnd
+        *      -d / (c + ((Z - tz) * szInv)) = fogEnd - 1.0
+        *      -d / (FogEnd - 1.0) = (c + ((Z - tz) * szInv))
+        *      (-d / (fogEnd - 1.0)) - c = ((Z - tz) * szInv)
+        *      ((-d / (fogEnd - 1.0)) - c) / szInv = (Z - tz)
+        *      (((-d / (fogEnd - 1.0)) - c) / szInv) + tz = Z
+        */
+       Zone = (((-d / (fogEnd - 1.0)) - c) / szInv) + tz;
+
+       /* FFB's Zfront must be less than Zback, thus we may have
+        * to invert Sf/Sb to satisfy this constraint.
+        */
+       if (Zzero < Zone) {
+               sf = 0.0;
+               sb = 1.0;
+               zf = Z_FROM_MESA(Zzero);
+               zb = Z_FROM_MESA(Zone);
+       } else {
+               sf = 1.0;
+               sb = 0.0;
+               zf = Z_FROM_MESA(Zone);
+               zb = Z_FROM_MESA(Zzero);
+       }
+}
+#endif
+
+static void ffbDDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
+{
+#ifdef STATE_TRACE
+       fprintf(stderr, "ffbDDFogfv: pname(%s)\n", _mesa_lookup_enum_by_nr(pname));
+#endif
+}
+
+static void ffbDDLineStipple(GLcontext *ctx, GLint factor, GLushort pattern)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+
+#ifdef STATE_TRACE
+       fprintf(stderr, "ffbDDLineStipple: factor(%d) pattern(%04x)\n",
+               factor, pattern);
+#endif
+       if (ctx->Line.StippleFlag) {
+               factor = ctx->Line.StippleFactor;
+               pattern = ctx->Line.StipplePattern;
+               if ((GLuint) factor > 15) {                     
+                       fmesa->lpat = FFB_LPAT_BAD;
+               } else {
+                       fmesa->lpat = ((factor << FFB_LPAT_SCALEVAL_SHIFT) |
+                                      (0 << FFB_LPAT_PATLEN_SHIFT) |
+                                      ((pattern & 0xffff) << FFB_LPAT_PATTERN_SHIFT));
+               }
+       } else {
+               fmesa->lpat = 0;
+       }
+}
+
+void ffbXformAreaPattern(ffbContextPtr fmesa, const GLubyte *mask)
+{
+       __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
+       int i, lines, xoff;
+
+       lines = 0;
+       i = (dPriv->y + dPriv->h) & (32 - 1);
+       xoff = dPriv->x & (32 - 1);
+       while (lines++ < 32) {
+               GLuint raw =
+                       (((GLuint)mask[0] << 24) |
+                        ((GLuint)mask[1] << 16) |
+                        ((GLuint)mask[2] <<  8) |
+                        ((GLuint)mask[3] <<  0));
+
+               fmesa->pattern[i] =
+                       (raw << xoff) | (raw >> (32 - xoff));
+               i = (i - 1) & (32 - 1);
+               mask += 4;
+       }
+
+       FFB_MAKE_DIRTY(fmesa, FFB_STATE_APAT, 32);
+}
+
+static void ffbDDPolygonStipple(GLcontext *ctx, const GLubyte *mask)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+
+#ifdef STATE_TRACE
+       fprintf(stderr, "ffbDDPolygonStipple: state(%d)\n",
+               ctx->Polygon.StippleFlag);
+#endif
+       ffbXformAreaPattern(fmesa, mask);
+}
+
+static void ffbDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       unsigned int tmp;
+
+#ifdef STATE_TRACE
+       fprintf(stderr, "ffbDDEnable: %s state(%d)\n",
+               _mesa_lookup_enum_by_nr(cap), state);
+#endif
+       switch (cap) {
+       case GL_ALPHA_TEST:
+               if (state)
+                       tmp = ffbComputeAlphaFunc(ctx);
+               else
+                       tmp = FFB_XCLIP_TEST_ALWAYS;
+
+               if (tmp != fmesa->xclip) {
+                       fmesa->xclip = tmp;
+                       FFB_MAKE_DIRTY(fmesa, FFB_STATE_XCLIP, 1);
+               }
+               break;
+
+       case GL_BLEND:
+               tmp = (fmesa->ppc & ~FFB_PPC_ABE_MASK);
+               if (state) {
+                       tmp |= FFB_PPC_ABE_ENABLE;
+               } else {
+                       tmp |= FFB_PPC_ABE_DISABLE;
+               }
+               if (fmesa->ppc != tmp) {
+                       fmesa->ppc = tmp;
+                       FFB_MAKE_DIRTY(fmesa, FFB_STATE_PPC, 1);
+                       ffbDDBlendFunc(ctx, 0, 0);
+               }
+               break;
+
+       case GL_DEPTH_TEST:
+               if (state)
+                       tmp = 0x0fffffff;
+               else
+                       tmp = 0x00000000;
+               if (tmp != fmesa->magnc) {
+                       unsigned int fbc = fmesa->fbc;
+                       fbc &= ~FFB_FBC_ZE_MASK;
+                       if (state)
+                               fbc |= FFB_FBC_ZE_ON;
+                       else
+                               fbc |= FFB_FBC_ZE_OFF;
+                       fmesa->fbc = fbc;
+                       ffbDDDepthFunc(ctx, ctx->Depth.Func);
+                       fmesa->magnc = tmp;
+                       FFB_MAKE_DIRTY(fmesa, (FFB_STATE_MAGNC | FFB_STATE_FBC), 2);
+               }
+               break;
+
+       case GL_SCISSOR_TEST:
+               ffbDDScissor(ctx, ctx->Scissor.X, ctx->Scissor.Y,
+                            ctx->Scissor.Width, ctx->Scissor.Height);
+               break;
+
+       case GL_STENCIL_TEST:
+               if (!(fmesa->ffb_sarea->flags & FFB_DRI_FFB2PLUS)) {
+                       FALLBACK( ctx, FFB_BADATTR_STENCIL, state );
+               }
+
+               tmp = fmesa->fbc & ~FFB_FBC_YE_MASK;
+               if (state) {
+                       ffbDDStencilFunc(ctx,
+                                        ctx->Stencil.Function[0],
+                                        ctx->Stencil.Ref[0],
+                                        ctx->Stencil.ValueMask[0]);
+                       ffbDDStencilMask(ctx, ctx->Stencil.WriteMask[0]);
+                       ffbDDStencilOp(ctx,
+                                      ctx->Stencil.FailFunc[0],
+                                      ctx->Stencil.ZFailFunc[0],
+                                      ctx->Stencil.ZPassFunc[0]);
+                       tmp |= FFB_FBC_YE_MASK;
+               } else {
+                       fmesa->stencil          = 0xf0000000;
+                       fmesa->stencilctl       = 0x33300000;
+                       FFB_MAKE_DIRTY(fmesa, FFB_STATE_STENCIL, 6);
+                       tmp |= FFB_FBC_YE_OFF;
+               }
+               if (tmp != fmesa->fbc) {
+                       fmesa->fbc = tmp;
+                       FFB_MAKE_DIRTY(fmesa, FFB_STATE_FBC, 1);
+               }
+               break;
+
+       case GL_FOG:
+               /* Until I implement the fog support... */
+               FALLBACK( ctx, FFB_BADATTR_FOG, state );
+               break;
+
+       case GL_LINE_STIPPLE:
+               if (! state)
+                       fmesa->lpat = 0;
+               else
+                       ffbDDLineStipple(ctx,
+                                        ctx->Line.StippleFactor,
+                                        ctx->Line.StipplePattern);
+               break;
+
+       case GL_POLYGON_STIPPLE:
+               /* Do nothing, we interrogate the state during
+                * reduced primitive changes.  Since our caller
+                * will set NEW_POLYGON in the ctx NewState this
+                * will cause the driver rasterization functions
+                * to be reevaluated, which will cause us to force
+                * a reduced primitive change next rendering pass
+                * and it all works out.
+                */
+               break;
+
+       default:
+               break;
+       };
+}
+
+void ffbSyncHardware(ffbContextPtr fmesa)
+{
+       ffb_fbcPtr ffb = fmesa->regs;
+       unsigned int dirty;
+       int i;
+
+       FFBFifo(fmesa, fmesa->state_fifo_ents);
+
+       dirty = fmesa->state_dirty;
+       if (dirty & (FFB_STATE_FBC | FFB_STATE_PPC | FFB_STATE_DRAWOP |
+                    FFB_STATE_ROP | FFB_STATE_LPAT | FFB_STATE_WID)) {
+               if (dirty & FFB_STATE_FBC)
+                       ffb->fbc = fmesa->fbc;
+               if (dirty & FFB_STATE_PPC)
+                       ffb->ppc = fmesa->ppc;
+               if (dirty & FFB_STATE_DRAWOP)
+                       ffb->drawop = fmesa->drawop;
+               if (dirty & FFB_STATE_ROP)
+                       ffb->rop = fmesa->rop;
+               if (dirty & FFB_STATE_LPAT)
+                       ffb->rop = fmesa->lpat;
+               if (dirty & FFB_STATE_WID)
+                       ffb->wid = fmesa->wid;
+       }
+       if (dirty & (FFB_STATE_PMASK | FFB_STATE_XPMASK | FFB_STATE_YPMASK |
+                    FFB_STATE_ZPMASK | FFB_STATE_XCLIP | FFB_STATE_CMP |
+                    FFB_STATE_MATCHAB | FFB_STATE_MAGNAB | FFB_STATE_MATCHC |
+                    FFB_STATE_MAGNC)) {
+               if (dirty & FFB_STATE_PMASK)
+                       ffb->pmask = fmesa->pmask;
+               if (dirty & FFB_STATE_XPMASK)
+                       ffb->xpmask = fmesa->xpmask;
+               if (dirty & FFB_STATE_YPMASK)
+                       ffb->ypmask = fmesa->ypmask;
+               if (dirty & FFB_STATE_ZPMASK)
+                       ffb->zpmask = fmesa->zpmask;
+               if (dirty & FFB_STATE_XCLIP)
+                       ffb->xclip = fmesa->xclip;
+               if (dirty & FFB_STATE_CMP)
+                       ffb->cmp = fmesa->cmp;
+               if (dirty & FFB_STATE_MATCHAB)
+                       ffb->matchab = fmesa->matchab;
+               if (dirty & FFB_STATE_MAGNAB)
+                       ffb->magnab = fmesa->magnab;
+               if (dirty & FFB_STATE_MATCHC)
+                       ffb->matchc = fmesa->matchc;
+               if (dirty & FFB_STATE_MAGNC)
+                       ffb->magnc = fmesa->magnc;
+       }
+
+       if (dirty & FFB_STATE_DCUE) {
+               ffb->dcss = fmesa->dcss;
+               ffb->dcsf = fmesa->dcsf;
+               ffb->dcsb = fmesa->dcsb;
+               ffb->dczf = fmesa->dczf;
+               ffb->dczb = fmesa->dczb;
+               if (fmesa->ffb_sarea->flags & (FFB_DRI_FFB2 | FFB_DRI_FFB2PLUS)) {
+                       ffb->dcss1 = fmesa->dcss1;
+                       ffb->dcss2 = fmesa->dcss2;
+                       ffb->dcss3 = fmesa->dcss3;
+                       ffb->dcs2  = fmesa->dcs2;
+                       ffb->dcs3  = fmesa->dcs3;
+                       ffb->dcs4  = fmesa->dcs4;
+                       ffb->dcd2  = fmesa->dcd2;
+                       ffb->dcd3  = fmesa->dcd3;
+                       ffb->dcd4  = fmesa->dcd4;
+               }
+       }
+
+       if (dirty & FFB_STATE_BLEND) {
+               ffb->blendc  = fmesa->blendc;
+               ffb->blendc1 = fmesa->blendc1;
+               ffb->blendc2 = fmesa->blendc2;
+       }
+
+       if (dirty & FFB_STATE_CLIP) {
+               ffb->vclipmin  = fmesa->vclipmin;
+               ffb->vclipmax  = fmesa->vclipmax;
+               ffb->vclipzmin = fmesa->vclipzmin;
+               ffb->vclipzmax = fmesa->vclipzmax;
+               for (i = 0; i < 4; i++) {
+                       ffb->auxclip[i].min = fmesa->aux_clips[i].min;
+                       ffb->auxclip[i].max = fmesa->aux_clips[i].max;
+               }
+       }
+
+       if ((dirty & FFB_STATE_STENCIL) &&
+           (fmesa->ffb_sarea->flags & FFB_DRI_FFB2PLUS)) {
+               ffb->stencil    = fmesa->stencil;
+               ffb->stencilctl = fmesa->stencilctl;
+               ffb->fbc = FFB_FBC_WB_C;
+               ffb->rawstencilctl = (fmesa->stencilctl | (1 << 19));
+               ffb->fbc = fmesa->fbc;
+               ffb->consty = fmesa->consty;
+       }
+
+       if (dirty & FFB_STATE_APAT) {
+               for (i = 0; i < 32; i++)
+                       ffb->pattern[i] = fmesa->pattern[i];
+       }
+
+       fmesa->state_dirty = 0;
+       fmesa->state_fifo_ents = 0;
+       fmesa->ffbScreen->rp_active = 1;
+}
+
+static void ffbDDUpdateState(GLcontext *ctx, GLuint newstate)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+
+       /* When we are hw rendering, changing certain kinds of
+        * state does not require flushing all of our context.
+        */
+       if (fmesa->bad_fragment_attrs == 0 &&
+           (newstate & ~_NEW_COLOR) == 0)
+               return;
+
+       _swrast_InvalidateState( ctx, newstate );
+       _swsetup_InvalidateState( ctx, newstate );
+       _ac_InvalidateState( ctx, newstate );
+       _tnl_InvalidateState( ctx, newstate );
+
+       if (newstate & _NEW_TEXTURE)
+          FALLBACK( ctx, FFB_BADATTR_TEXTURE, 
+                    (ctx->Texture._EnabledUnits != 0));
+
+#ifdef STATE_TRACE
+       fprintf(stderr, "ffbDDUpdateState: newstate(%08x)\n", newstate);
+#endif
+
+       fmesa->new_gl_state |= newstate;
+
+       /* Force a reduced primitive change next rendering
+        * pass.
+        */
+       fmesa->raster_primitive = GL_POLYGON + 1;
+
+#if 0
+       /* When the modelview matrix changes, this changes what
+        * the eye coordinates will be so we have to recompute
+        * the depth cueing parameters.
+        *
+        * XXX DD_HAVE_HARDWARE_FOG.
+        */
+       if (ctx->Fog.Enabled && (newstate & _NEW_MODELVIEW))
+               ffb_update_fog();
+#endif
+}
+
+
+void ffbDDInitStateFuncs(GLcontext *ctx)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+
+       ctx->Driver.UpdateState = ffbDDUpdateState;
+
+       ctx->Driver.Enable = ffbDDEnable;
+       ctx->Driver.LightModelfv = NULL;
+       ctx->Driver.AlphaFunc = ffbDDAlphaFunc;
+       ctx->Driver.BlendEquation = ffbDDBlendEquation;
+       ctx->Driver.BlendFunc = ffbDDBlendFunc;
+       ctx->Driver.BlendFuncSeparate = ffbDDBlendFuncSeparate;
+       ctx->Driver.DepthFunc = ffbDDDepthFunc;
+       ctx->Driver.DepthMask = ffbDDDepthMask;
+       ctx->Driver.Fogfv = ffbDDFogfv;
+       ctx->Driver.LineStipple = ffbDDLineStipple;
+       ctx->Driver.PolygonStipple = ffbDDPolygonStipple;
+       ctx->Driver.Scissor = ffbDDScissor;
+       ctx->Driver.CullFace = NULL;
+       ctx->Driver.FrontFace = NULL;
+       ctx->Driver.ColorMask = ffbDDColorMask;
+       ctx->Driver.LogicOpcode = ffbDDLogicOp;
+       ctx->Driver.Viewport = ffbDDViewport;
+       ctx->Driver.DepthRange = ffbDDDepthRange;
+
+       if (fmesa->ffb_sarea->flags & FFB_DRI_FFB2PLUS) {
+               ctx->Driver.StencilFunc = ffbDDStencilFunc;
+               ctx->Driver.StencilMask = ffbDDStencilMask;
+               ctx->Driver.StencilOp = ffbDDStencilOp;
+       } else {
+               ctx->Driver.StencilFunc = NULL;
+               ctx->Driver.StencilMask = NULL;
+               ctx->Driver.StencilOp = NULL;
+       }
+
+       ctx->Driver.DrawBuffer = ffbDDDrawBuffer;
+       ctx->Driver.ReadBuffer = ffbDDReadBuffer;
+       ctx->Driver.ClearColor = ffbDDClearColor;
+       ctx->Driver.ClearDepth = ffbDDClearDepth;
+       ctx->Driver.ClearStencil = ffbDDClearStencil;
+
+       /* We will support color index modes later... -DaveM */
+       ctx->Driver.ClearIndex = 0;
+       ctx->Driver.IndexMask = 0;
+
+
+
+       /* Pixel path fallbacks.
+        */
+       ctx->Driver.Accum = _swrast_Accum;
+       ctx->Driver.CopyPixels = _swrast_CopyPixels;
+       ctx->Driver.DrawPixels = _swrast_DrawPixels;
+       ctx->Driver.ReadPixels = _swrast_ReadPixels;
+       ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
+
+       /* Swrast hooks for imaging extensions:
+        */
+       ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
+       ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
+       ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
+       ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
+
+       {
+               struct swrast_device_driver *swdd = 
+                       _swrast_GetDeviceDriverReference(ctx);
+               swdd->SetBuffer = ffbDDSetBuffer;
+       }
+   
+
+}
+
+void ffbDDInitContextHwState(GLcontext *ctx)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       int fifo_count = 0;
+       int i;
+
+       fmesa->hw_locked = 0;
+
+       fmesa->bad_fragment_attrs = 0;
+       fmesa->state_dirty = FFB_STATE_ALL;
+       fmesa->new_gl_state = ~0;
+
+       fifo_count = 1;
+       fmesa->fbc = (FFB_FBC_WE_FORCEON | FFB_FBC_WM_COMBINED |
+                     FFB_FBC_SB_BOTH | FFB_FBC_ZE_MASK |
+                     FFB_FBC_YE_OFF | FFB_FBC_XE_OFF |
+                     FFB_FBC_RGBE_MASK);
+       if (ctx->Visual.doubleBufferMode) {
+               /* Buffer B is the initial back buffer. */
+               fmesa->back_buffer = 1;
+               fmesa->fbc |= FFB_FBC_WB_BC | FFB_FBC_RB_B;
+       } else {
+               fmesa->back_buffer = 0;
+               fmesa->fbc |= FFB_FBC_WB_A | FFB_FBC_RB_A;
+       }
+
+       fifo_count += 1;
+       fmesa->ppc = (FFB_PPC_ACE_DISABLE | FFB_PPC_DCE_DISABLE |
+                     FFB_PPC_ABE_DISABLE | FFB_PPC_VCE_3D |
+                     FFB_PPC_APE_DISABLE | FFB_PPC_TBE_OPAQUE |
+                     FFB_PPC_ZS_CONST | FFB_PPC_YS_CONST |
+                     FFB_PPC_XS_WID | FFB_PPC_CS_VAR);
+
+       fifo_count += 3;
+       fmesa->drawop = FFB_DRAWOP_RECTANGLE;
+
+       /* GL_COPY is the default LogicOp. */
+       fmesa->rop = (FFB_ROP_NEW << 16) | (FFB_ROP_NEW << 8) | FFB_ROP_NEW;
+
+       /* No line patterning enabled. */
+       fmesa->lpat = 0x00000000;
+
+       /* We do not know the WID value until the first context switch. */
+       fifo_count += 1;
+       fmesa->wid = ~0;
+
+       fifo_count += 5;
+
+       /* ColorMask, all enabled. */
+       fmesa->pmask  = 0xffffffff;
+
+       fmesa->xpmask = 0x000000ff;
+       fmesa->ypmask = 0x0000000f;
+       fmesa->zpmask = 0x0fffffff;
+
+       /* AlphaFunc GL_ALWAYS, AlphaRef 0 */
+       fmesa->xclip  = FFB_XCLIP_TEST_ALWAYS | 0x00;
+
+       /* This sets us up to use WID clipping (so the DRI clipping
+        * rectangle is unneeded by us).  All other match and magnitude
+        * tests are set to pass.
+        */
+       fifo_count += 5;
+       fmesa->cmp = ((FFB_CMP_MATCH_ALWAYS << 24) |    /* MATCH C  */
+                     (FFB_CMP_MAGN_ALWAYS  << 16) |    /* MAGN  C  */
+                     (FFB_CMP_MATCH_EQ     <<  8) |    /* MATCH AB */
+                     (FFB_CMP_MAGN_ALWAYS  <<  0));    /* MAGN  AB */
+       fmesa->matchab = 0xff000000;
+       fmesa->magnab  = 0x00000000;
+       fmesa->matchc  = 0x00000000;
+       fmesa->magnc   = 0x00000000;
+
+       /* Depth cue parameters, all zeros to start. */
+       fifo_count += 14;
+       fmesa->dcss  = 0x00000000;
+       fmesa->dcsf  = 0x00000000;
+       fmesa->dcsb  = 0x00000000;
+       fmesa->dczf  = 0x00000000;
+       fmesa->dczb  = 0x00000000;
+       fmesa->dcss1 = 0x00000000;
+       fmesa->dcss2 = 0x00000000;
+       fmesa->dcss3 = 0x00000000;
+       fmesa->dcs2  = 0x00000000;
+       fmesa->dcs3  = 0x00000000;
+       fmesa->dcs4  = 0x00000000;
+       fmesa->dcd2  = 0x00000000;
+       fmesa->dcd3  = 0x00000000;
+       fmesa->dcd4  = 0x00000000;
+
+       /* Alpha blending unit state. */
+       fifo_count += 3;
+       fmesa->blendc  = (1 << 0) | (0 << 2);  /* src(GL_ONE) | dst(GL_ZERO) */
+       fmesa->blendc1 = 0x00000000;
+       fmesa->blendc2 = 0x00000000;
+
+       /* ViewPort clip state. */
+       fifo_count += 4 + (4 * 2);
+       fmesa->vclipmin  = 0x00000000;
+       fmesa->vclipmax  = 0xffffffff;
+       fmesa->vclipzmin = 0x00000000;
+       fmesa->vclipzmax = 0x0fffffff;
+       for (i = 0; i < 4; i++) {
+               fmesa->aux_clips[0].min = 0x00000000;
+               fmesa->aux_clips[0].max = 0x00000000;
+       }
+
+       /* Stenciling state. */
+       fifo_count += 6;
+       fmesa->stencil    = 0xf0000000; /* Stencil MASK, Y plane */
+       fmesa->stencilctl = 0x33300000; /* All stencil tests disabled */
+       fmesa->consty     = 0x0;
+
+       /* Area pattern, used for polygon stipples. */
+       fifo_count += 32;
+       for (i = 0; i < 32; i++)
+               fmesa->pattern[i] = 0x00000000;
+
+       fmesa->state_fifo_ents = fifo_count;
+       fmesa->state_all_fifo_ents = fifo_count;
+}
diff --git a/src/mesa/drivers/dri/ffb/ffb_state.h b/src/mesa/drivers/dri/ffb/ffb_state.h
new file mode 100644 (file)
index 0000000..17b6fa2
--- /dev/null
@@ -0,0 +1,13 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_state.h,v 1.2 2002/02/22 21:32:59 dawes Exp $ */
+
+#ifndef _FFB_STATE_H
+#define _FFB_STATE_H
+
+extern void ffbDDInitStateFuncs(GLcontext *);
+extern void ffbDDInitContextHwState(GLcontext *);
+
+extern void ffbCalcViewport(GLcontext *);
+extern void ffbXformAreaPattern(ffbContextPtr, const GLubyte *);
+extern void ffbSyncHardware(ffbContextPtr fmesa);
+
+#endif /* !(_FFB_STATE_H) */
diff --git a/src/mesa/drivers/dri/ffb/ffb_stencil.c b/src/mesa/drivers/dri/ffb/ffb_stencil.c
new file mode 100644 (file)
index 0000000..a00eb36
--- /dev/null
@@ -0,0 +1,221 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_stencil.c,v 1.2 2002/02/22 21:32:59 dawes Exp $
+ *
+ * GLX Hardware Device Driver for Sun Creator/Creator3D
+ * Copyright (C) 2000 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 <davem@redhat.com>
+ */
+
+#include "mtypes.h"
+#include "ffb_dd.h"
+#include "ffb_span.h"
+#include "ffb_context.h"
+#include "ffb_stencil.h"
+#include "ffb_lock.h"
+
+#include "swrast/swrast.h"
+
+#undef STENCIL_TRACE
+
+static void 
+FFBWriteStencilSpan(GLcontext *ctx, GLuint n, GLint x, GLint y,
+                   const GLstencil stencil[], const GLubyte mask[])
+{
+#ifdef STENCIL_TRACE
+       fprintf(stderr, "FFBWriteStencilSpan: n(%d) x(%d) y(%d)\n",
+               (int) n, x, y);
+#endif
+       if (ctx->Depth.Mask) {
+               ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+               __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
+               GLuint *zptr;
+               GLuint i;
+
+               if (!fmesa->hw_locked)
+                       LOCK_HARDWARE(fmesa);
+               FFBFifo(fmesa, 2);
+               fmesa->regs->fbc = (FFB_FBC_WB_C | FFB_FBC_ZE_OFF |
+                                   FFB_FBC_YE_ON | FFB_FBC_RGBE_OFF);
+               fmesa->regs->ppc = FFB_PPC_YS_VAR;
+               FFBWait(fmesa, fmesa->regs);
+
+               y = (dPriv->h - y);
+               zptr = (GLuint *)
+                       ((char *)fmesa->sfb32 +
+                        ((dPriv->x + x) << 2) +
+                        ((dPriv->y + y) << 13));
+               
+               for (i = 0; i < n; i++) {
+                       if (mask[i])
+                               *zptr = (stencil[i] & 0xf) << 28;
+                       zptr++;
+               }
+
+               FFBFifo(fmesa, 2);
+               fmesa->regs->fbc = fmesa->fbc;
+               fmesa->regs->ppc = fmesa->ppc;
+               fmesa->ffbScreen->rp_active = 1;
+               if (!fmesa->hw_locked)
+                       UNLOCK_HARDWARE(fmesa);
+       }
+}
+
+static void 
+FFBWriteStencilPixels(GLcontext *ctx, GLuint n, const GLint x[], const GLint y[],
+                     const GLstencil stencil[], const GLubyte mask[])
+{
+#ifdef STENCIL_TRACE
+       fprintf(stderr, "FFBWriteStencilPixels: n(%d)\n", (int) n);
+#endif
+       if (ctx->Depth.Mask) {
+               ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+               __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
+               char *zbase;
+               GLuint i;
+
+               if (!fmesa->hw_locked)
+                       LOCK_HARDWARE(fmesa);
+               FFBFifo(fmesa, 2);
+               fmesa->regs->fbc = (FFB_FBC_WB_C | FFB_FBC_ZE_OFF |
+                                   FFB_FBC_YE_ON | FFB_FBC_RGBE_OFF);
+               fmesa->regs->ppc = FFB_PPC_YS_VAR;
+               fmesa->ffbScreen->rp_active = 1;
+               FFBWait(fmesa, fmesa->regs);
+
+               zbase = ((char *)fmesa->sfb32 +
+                        (dPriv->x << 2) + (dPriv->y << 13));
+               
+               for (i = 0; i < n; i++) {
+                       GLint y1 = (dPriv->h - y[i]);
+                       GLint x1 = x[i];
+                       GLuint *zptr;
+
+                       zptr = (GLuint *)
+                               (zbase + (x1 << 2) + (y1 << 13));
+                       if (mask[i])
+                               *zptr = (stencil[i] & 0xf) << 28;
+               }
+
+               FFBFifo(fmesa, 2);
+               fmesa->regs->fbc = fmesa->fbc;
+               fmesa->regs->ppc = fmesa->ppc;
+               fmesa->ffbScreen->rp_active = 1;
+               if (!fmesa->hw_locked)
+                       UNLOCK_HARDWARE(fmesa);
+       }
+}
+
+static void 
+FFBReadStencilSpan(GLcontext *ctx, GLuint n, GLint x, GLint y, GLstencil stencil[])
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
+       GLuint *zptr;
+       GLuint i;
+
+#ifdef STENCIL_TRACE
+       fprintf(stderr, "FFBReadStencilSpan: n(%d) x(%d) y(%d)\n",
+               (int) n, x, y);
+#endif
+       if (!fmesa->hw_locked)
+               LOCK_HARDWARE(fmesa);
+       FFBFifo(fmesa, 1);
+       fmesa->regs->fbc = FFB_FBC_RB_C;
+       fmesa->ffbScreen->rp_active = 1;
+       FFBWait(fmesa, fmesa->regs);
+
+       y = (dPriv->h - y);
+       zptr = (GLuint *)
+               ((char *)fmesa->sfb32 +
+                ((dPriv->x + x) << 2) +
+                ((dPriv->y + y) << 13));
+               
+       for (i = 0; i < n; i++) {
+               stencil[i] = (*zptr >> 28) & 0xf;
+               zptr++;
+       }
+
+       FFBFifo(fmesa, 1);
+       fmesa->regs->fbc = fmesa->fbc;
+       fmesa->ffbScreen->rp_active = 1;
+       if (!fmesa->hw_locked)
+               UNLOCK_HARDWARE(fmesa);
+}
+
+static void 
+FFBReadStencilPixels(GLcontext *ctx, GLuint n, const GLint x[], const GLint y[],
+                    GLstencil stencil[])
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       __DRIdrawablePrivate *dPriv = fmesa->driDrawable;
+       char *zbase;
+       GLuint i;
+
+#ifdef STENCIL_TRACE
+       fprintf(stderr, "FFBReadStencilPixels: n(%d)\n", (int) n);
+#endif
+       if (!fmesa->hw_locked)
+               LOCK_HARDWARE(fmesa);
+       FFBFifo(fmesa, 1);
+       fmesa->regs->fbc = FFB_FBC_RB_C;
+       fmesa->ffbScreen->rp_active = 1;
+       FFBWait(fmesa, fmesa->regs);
+
+       zbase = ((char *)fmesa->sfb32 +
+                (dPriv->x << 2) + (dPriv->y << 13));
+               
+       for (i = 0; i < n; i++) {
+               GLint y1 = (dPriv->h - y[i]);
+               GLint x1 = x[i];
+               GLuint *zptr;
+
+               zptr = (GLuint *)
+                       (zbase + (x1 << 2) + (y1 << 13));
+               stencil[i] = (*zptr >> 28) & 0xf;
+       }
+
+       FFBFifo(fmesa, 1);
+       fmesa->regs->fbc = fmesa->fbc;
+       fmesa->ffbScreen->rp_active = 1;
+       if (!fmesa->hw_locked)
+               UNLOCK_HARDWARE(fmesa);
+}
+
+void ffbDDInitStencilFuncs(GLcontext *ctx)
+{
+       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;
+       }
+}
diff --git a/src/mesa/drivers/dri/ffb/ffb_stencil.h b/src/mesa/drivers/dri/ffb/ffb_stencil.h
new file mode 100644 (file)
index 0000000..af161e7
--- /dev/null
@@ -0,0 +1,8 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_stencil.h,v 1.1 2000/06/20 05:08:39 dawes Exp $ */
+
+#ifndef _FFB_STENCIL_H
+#define _FFB_STENCIL_H
+
+extern void ffbDDInitStencilFuncs(GLcontext *ctx);
+
+#endif /* !(_FFB_STENCIL_H) */
diff --git a/src/mesa/drivers/dri/ffb/ffb_tex.c b/src/mesa/drivers/dri/ffb/ffb_tex.c
new file mode 100644 (file)
index 0000000..ba1103e
--- /dev/null
@@ -0,0 +1,51 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_tex.c,v 1.1 2002/02/22 21:32:59 dawes Exp $
+ *
+ * GLX Hardware Device Driver for Sun Creator/Creator3D
+ * Copyright (C) 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 <davem@redhat.com>
+ */
+
+#include <GL/gl.h>
+#include "texformat.h"
+#include "texstore.h"
+#include "swrast/swrast.h"
+
+#include "ffb_tex.h"
+
+/* No texture unit, all software. */
+void ffbDDInitTexFuncs(GLcontext *ctx)
+{
+       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.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.TestProxyTexImage = _mesa_test_proxy_teximage;
+}
diff --git a/src/mesa/drivers/dri/ffb/ffb_tex.h b/src/mesa/drivers/dri/ffb/ffb_tex.h
new file mode 100644 (file)
index 0000000..dba0e08
--- /dev/null
@@ -0,0 +1,34 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_tex.h,v 1.1 2002/02/22 21:32:59 dawes Exp $
+ *
+ * GLX Hardware Device Driver for Sun Creator/Creator3D.
+ * Copyright (C) 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 <davem@redhat.com>
+ */
+
+#ifndef _FFB_TEX_H
+#define _FFB_TEX_H
+
+extern void ffbDDInitTexFuncs(GLcontext *ctx);
+
+#endif /* !(_FFB_DD_H) */
+
diff --git a/src/mesa/drivers/dri/ffb/ffb_tris.c b/src/mesa/drivers/dri/ffb/ffb_tris.c
new file mode 100644 (file)
index 0000000..63113f0
--- /dev/null
@@ -0,0 +1,946 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_tris.c,v 1.3 2002/10/30 12:51:28 alanh 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 <davem@redhat.com>
+ */
+
+#include "glheader.h"
+#include "mtypes.h"
+#include "macros.h"
+#include "mmath.h"
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "swrast/s_context.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+#include "ffb_context.h"
+#include "ffb_tris.h"
+#include "ffb_lines.h"
+#include "ffb_lock.h"
+#include "ffb_points.h"
+#include "ffb_state.h"
+#include "ffb_vb.h"
+
+#undef TRI_DEBUG
+#undef FFB_RENDER_TRACE
+#undef STATE_TRACE
+
+#ifdef TRI_DEBUG
+static void ffb_print_vertex(const ffb_vertex *v)
+{
+       fprintf(stderr, "Vertex @(%p): "
+               "X[%f] Y[%f] Z[%f]\n",
+               v, v->x, v->y, v->z);
+       fprintf(stderr, "Vertex @(%p): "
+               "A[%f] R[%f] G[%f] B[%f]\n",
+               v,
+               v->color[0].alpha,
+               v->color[0].red,
+               v->color[0].green,
+               v->color[0].blue);
+}
+#define FFB_DUMP_VERTEX(V)     ffb_print_vertex(V)
+#else
+#define FFB_DUMP_VERTEX(V)     do { } while(0)
+#endif
+
+#define FFB_ALPHA_BIT          0x01
+#define FFB_FLAT_BIT           0x02
+#define FFB_TRI_CULL_BIT       0x04
+#define MAX_FFB_RENDER_FUNCS   0x08
+
+/***********************************************************************
+ *         Build low-level triangle/quad rasterize functions           *
+ ***********************************************************************/
+
+#define FFB_TRI_FLAT_BIT       0x01
+#define FFB_TRI_ALPHA_BIT      0x02
+/*#define FFB_TRI_CULL_BIT     0x04*/
+
+static ffb_tri_func ffb_tri_tab[0x8];
+static ffb_quad_func ffb_quad_tab[0x8];
+
+#define IND (0)
+#define TAG(x) x
+#include "ffb_tritmp.h"
+
+#define IND (FFB_TRI_FLAT_BIT)
+#define TAG(x) x##_flat
+#include "ffb_tritmp.h"
+
+#define IND (FFB_TRI_CULL_BIT)
+#define TAG(x) x##_cull
+#include "ffb_tritmp.h"
+
+#define IND (FFB_TRI_CULL_BIT|FFB_TRI_FLAT_BIT)
+#define TAG(x) x##_cull_flat
+#include "ffb_tritmp.h"
+
+#define IND (FFB_TRI_ALPHA_BIT)
+#define TAG(x) x##_alpha
+#include "ffb_tritmp.h"
+
+#define IND (FFB_TRI_ALPHA_BIT|FFB_TRI_FLAT_BIT)
+#define TAG(x) x##_alpha_flat
+#include "ffb_tritmp.h"
+
+#define IND (FFB_TRI_ALPHA_BIT|FFB_TRI_CULL_BIT)
+#define TAG(x) x##_alpha_cull
+#include "ffb_tritmp.h"
+
+#define IND (FFB_TRI_ALPHA_BIT|FFB_TRI_CULL_BIT|FFB_TRI_FLAT_BIT)
+#define TAG(x) x##_alpha_cull_flat
+#include "ffb_tritmp.h"
+
+static void init_tri_tab(void)
+{
+       ffb_init();
+       ffb_init_flat();
+       ffb_init_cull();
+       ffb_init_cull_flat();
+       ffb_init_alpha();
+       ffb_init_alpha_flat();
+       ffb_init_alpha_cull();
+       ffb_init_alpha_cull_flat();
+}
+
+/* Build a SWvertex from a hardware vertex. */
+static void ffb_translate_vertex(GLcontext *ctx, const ffb_vertex *src,
+                                SWvertex *dst)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       GLfloat *m = ctx->Viewport._WindowMap.m;
+       const GLfloat sx = m[0];
+       const GLfloat sy = m[5];
+       const GLfloat sz = m[10];
+       const GLfloat tx = m[12];
+       const GLfloat ty = m[13];
+       const GLfloat tz = m[14];
+
+       dst->win[0] = sx * src->x + tx;
+       dst->win[1] = sy * src->y + ty;
+       dst->win[2] = sz * src->z + tz;
+       dst->win[3] = 1.0;
+      
+       dst->color[0] = FFB_UBYTE_FROM_COLOR(src->color[0].red);
+       dst->color[1] = FFB_UBYTE_FROM_COLOR(src->color[0].green);
+       dst->color[2] = FFB_UBYTE_FROM_COLOR(src->color[0].blue);
+       dst->color[3] = FFB_UBYTE_FROM_COLOR(src->color[0].alpha);
+}
+
+/***********************************************************************
+ *          Build fallback triangle/quad rasterize functions           *
+ ***********************************************************************/
+
+static void ffb_fallback_triangle(GLcontext *ctx, ffb_vertex *v0,
+                                 ffb_vertex *v1, ffb_vertex *v2)
+{
+       SWvertex v[3];
+
+       ffb_translate_vertex(ctx, v0, &v[0]);
+       ffb_translate_vertex(ctx, v1, &v[1]);
+       ffb_translate_vertex(ctx, v2, &v[2]);
+
+       _swrast_Triangle(ctx, &v[0], &v[1], &v[2]);
+}
+
+static void ffb_fallback_quad(GLcontext *ctx,
+                             ffb_vertex *v0, ffb_vertex *v1, 
+                             ffb_vertex *v2, ffb_vertex *v3)
+{
+       SWvertex v[4];
+
+       ffb_translate_vertex(ctx, v0, &v[0]);
+       ffb_translate_vertex(ctx, v1, &v[1]);
+       ffb_translate_vertex(ctx, v2, &v[2]);
+       ffb_translate_vertex(ctx, v3, &v[3]);
+
+       _swrast_Quad(ctx, &v[0], &v[1], &v[2], &v[3]);
+}
+
+void ffb_fallback_line(GLcontext *ctx, ffb_vertex *v0, ffb_vertex *v1)
+{
+       SWvertex v[2];
+
+       ffb_translate_vertex(ctx, v0, &v[0]);
+       ffb_translate_vertex(ctx, v1, &v[1]);
+
+       _swrast_Line(ctx, &v[0], &v[1]);
+}
+
+void ffb_fallback_point(GLcontext *ctx, ffb_vertex *v0)
+{
+       SWvertex v[1];
+
+       ffb_translate_vertex(ctx, v0, &v[0]);
+
+       _swrast_Point(ctx, &v[0]);
+}
+
+/***********************************************************************
+ *             Rasterization functions for culled tris/quads           *
+ ***********************************************************************/
+
+static void ffb_nodraw_triangle(GLcontext *ctx, ffb_vertex *v0,
+                               ffb_vertex *v1, ffb_vertex *v2)
+{
+       (void) (ctx && v0 && v1 && v2);
+}
+
+static void ffb_nodraw_quad(GLcontext *ctx,
+                           ffb_vertex *v0, ffb_vertex *v1, 
+                           ffb_vertex *v2, ffb_vertex *v3)
+{
+       (void) (ctx && v0 && v1 && v2 && v3);
+}
+
+static void ffb_update_cullsign(GLcontext *ctx)
+{
+       GLfloat backface_sign = 1;
+
+       switch (ctx->Polygon.CullFaceMode) {
+       case GL_BACK:
+               if (ctx->Polygon.FrontFace==GL_CCW)
+                       backface_sign = -1;
+               break;
+
+       case GL_FRONT:
+               if (ctx->Polygon.FrontFace!=GL_CCW)
+                       backface_sign = -1;
+               break;
+
+       default:
+               break;
+       };
+
+       FFB_CONTEXT(ctx)->backface_sign = backface_sign;
+}
+
+/***********************************************************************
+ *               Choose triangle/quad rasterize functions              *
+ ***********************************************************************/
+
+void ffbChooseTriangleState(GLcontext *ctx)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       GLuint flags = ctx->_TriangleCaps;
+       GLuint ind = 0;
+
+       if (flags & DD_TRI_SMOOTH) {
+               fmesa->draw_tri = ffb_fallback_triangle;
+               fmesa->draw_quad = ffb_fallback_quad;
+               return;
+       }
+
+       if (flags & DD_FLATSHADE)
+               ind |= FFB_TRI_FLAT_BIT;
+
+       if (ctx->Polygon.CullFlag) {
+               if (ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) {
+                       fmesa->draw_tri = ffb_nodraw_triangle;
+                       fmesa->draw_quad = ffb_nodraw_quad;
+                       return;
+               }
+
+               ind |= FFB_TRI_CULL_BIT;
+               ffb_update_cullsign(ctx);
+       } else
+               FFB_CONTEXT(ctx)->backface_sign = 0;
+               
+       /* If blending or the alpha test is enabled we need to
+        * provide alpha components to the chip, else we can
+        * do without it and thus feed vertex data to the chip
+        * more efficiently.
+        */
+       if (ctx->Color.BlendEnabled || ctx->Color.AlphaEnabled)
+               ind |= FFB_TRI_ALPHA_BIT;
+
+       fmesa->draw_tri = ffb_tri_tab[ind];
+       fmesa->draw_quad = ffb_quad_tab[ind];
+}
+
+static const GLenum reduced_prim[GL_POLYGON+1] = {
+   GL_POINTS,
+   GL_LINES,
+   GL_LINES,
+   GL_LINES,
+   GL_TRIANGLES,
+   GL_TRIANGLES,
+   GL_TRIANGLES,
+   GL_TRIANGLES,
+   GL_TRIANGLES,
+   GL_TRIANGLES
+};
+
+static void ffbRenderPrimitive(GLcontext *ctx, GLenum prim);
+static void ffbRasterPrimitive(GLcontext *ctx, GLenum rprim);
+
+/***********************************************************************
+ *              Build render functions from dd templates               *
+ ***********************************************************************/
+
+#define FFB_OFFSET_BIT         0x01
+#define FFB_TWOSIDE_BIT        0x02
+#define FFB_UNFILLED_BIT       0x04
+#define FFB_MAX_TRIFUNC        0x08
+
+static struct {
+       triangle_func triangle;
+       quad_func quad;
+} rast_tab[FFB_MAX_TRIFUNC];
+
+#define DO_OFFSET   (IND & FFB_OFFSET_BIT)
+#define DO_UNFILLED (IND & FFB_UNFILLED_BIT)
+#define DO_TWOSIDE  (IND & FFB_TWOSIDE_BIT)
+#define DO_FLAT      0
+#define DO_QUAD      1
+#define DO_FULL_QUAD 1
+#define DO_TRI       1
+#define DO_LINE      0
+#define DO_POINTS    0
+
+#define QUAD( a, b, c, d ) fmesa->draw_quad( ctx, a, b, c, d )
+#define TRI( a, b, c )     fmesa->draw_tri( ctx, a, b, c )
+#define LINE( a, b )       fmesa->draw_line( ctx, a, b )
+#define POINT( a )         fmesa->draw_point( ctx, a )
+
+#define HAVE_BACK_COLORS  1
+#define HAVE_RGBA         1
+#define HAVE_SPEC         0
+#define HAVE_HW_FLATSHADE 1
+#define VERTEX            ffb_vertex
+#define TAB               rast_tab
+
+#define UNFILLED_TRI      unfilled_tri
+#define UNFILLED_QUAD     unfilled_quad
+#define DEPTH_SCALE       (fmesa->depth_scale)
+#define VERT_X(_v)        (_v->x)
+#define VERT_Y(_v)        (_v->y)
+#define VERT_Z(_v)       (_v->z)
+#define AREA_IS_CCW( a )  (a < fmesa->ffb_zero)
+#define GET_VERTEX(e)     (&fmesa->verts[e])
+#define INSANE_VERTICES
+#define VERT_SET_Z(v,val) ((v)->z = (val))
+#define VERT_Z_ADD(v,val) ((v)->z += (val))
+
+#define VERT_COPY_RGBA1( _v )     _v->color[0] = _v->color[1]
+#define VERT_COPY_RGBA( v0, v1 )  v0->color[0] = v1->color[0] 
+#define VERT_SAVE_RGBA( idx )     color[idx] = v[idx]->color[0]
+#define VERT_RESTORE_RGBA( idx )  v[idx]->color[0] = color[idx]   
+
+#define LOCAL_VARS(n)                          \
+   ffbContextPtr fmesa = FFB_CONTEXT(ctx);     \
+   __DRIdrawablePrivate *dPriv = fmesa->driDrawable; \
+   ffb_color color[n];                         \
+   (void) color; (void) dPriv;
+
+/***********************************************************************
+ *                Helpers for rendering unfilled primitives            *
+ ***********************************************************************/
+
+#define RASTERIZE(x) if (fmesa->raster_primitive != reduced_prim[x]) \
+                        ffbRasterPrimitive( ctx, reduced_prim[x] )
+#define RENDER_PRIMITIVE fmesa->render_primitive
+#define TAG(x) x
+#include "tnl_dd/t_dd_unfilled.h"
+
+/***********************************************************************
+ *                      Generate GL render functions                   *
+ ***********************************************************************/
+
+#define IND (0)
+#define TAG(x) x
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FFB_OFFSET_BIT)
+#define TAG(x) x##_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FFB_TWOSIDE_BIT)
+#define TAG(x) x##_twoside
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FFB_TWOSIDE_BIT|FFB_OFFSET_BIT)
+#define TAG(x) x##_twoside_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FFB_UNFILLED_BIT)
+#define TAG(x) x##_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FFB_OFFSET_BIT|FFB_UNFILLED_BIT)
+#define TAG(x) x##_offset_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FFB_TWOSIDE_BIT|FFB_UNFILLED_BIT)
+#define TAG(x) x##_twoside_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (FFB_TWOSIDE_BIT|FFB_OFFSET_BIT|FFB_UNFILLED_BIT)
+#define TAG(x) x##_twoside_offset_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+static void init_rast_tab( void )
+{
+   init();
+   init_offset();
+   init_twoside();
+   init_twoside_offset();
+   init_unfilled();
+   init_offset_unfilled();
+   init_twoside_unfilled();
+   init_twoside_offset_unfilled();
+}
+
+/**********************************************************************/
+/*                   Render clipped primitives                        */
+/**********************************************************************/
+
+static void ffbRenderClippedPolygon(GLcontext *ctx, const GLuint *elts, GLuint n)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       TNLcontext *tnl = TNL_CONTEXT(ctx);
+       struct vertex_buffer *VB = &tnl->vb;
+       GLuint prim = fmesa->render_primitive;
+
+       /* Render the new vertices as an unclipped polygon. */
+       {
+               GLuint *tmp = VB->Elts;
+               VB->Elts = (GLuint *)elts;
+               tnl->Driver.Render.PrimTabElts[GL_POLYGON](ctx, 0, n, PRIM_BEGIN|PRIM_END);
+               VB->Elts = tmp;
+       }
+
+       /* Restore the render primitive. */
+       if (prim != GL_POLYGON)
+               tnl->Driver.Render.PrimitiveNotify(ctx, prim);
+}
+
+static void ffbRenderClippedLine(GLcontext *ctx, GLuint ii, GLuint jj)
+{
+       TNLcontext *tnl = TNL_CONTEXT(ctx);
+       tnl->Driver.Render.Line(ctx, ii, jj);
+}
+
+/**********************************************************************/
+/*               Render unclipped begin/end objects                   */
+/**********************************************************************/
+
+static void ffb_vb_noop(GLcontext *ctx, GLuint start, GLuint count, GLuint flags)
+{
+       (void)(ctx && start && count && flags);
+}
+
+#define ELT(x) x
+
+#define IND    0
+#define TAG(x) x
+#include "ffb_rendertmp.h"
+
+#define IND    (FFB_FLAT_BIT)
+#define TAG(x) x##_flat
+#include "ffb_rendertmp.h"
+
+#define IND    (FFB_ALPHA_BIT)
+#define TAG(x) x##_alpha
+#include "ffb_rendertmp.h"
+
+#define IND    (FFB_FLAT_BIT | FFB_ALPHA_BIT)
+#define TAG(x) x##_flat_alpha
+#include "ffb_rendertmp.h"
+
+#define IND    (FFB_TRI_CULL_BIT)
+#define TAG(x) x##_tricull
+#include "ffb_rendertmp.h"
+
+#define IND    (FFB_FLAT_BIT | FFB_TRI_CULL_BIT)
+#define TAG(x) x##_flat_tricull
+#include "ffb_rendertmp.h"
+
+#define IND    (FFB_ALPHA_BIT | FFB_TRI_CULL_BIT)
+#define TAG(x) x##_alpha_tricull
+#include "ffb_rendertmp.h"
+
+#define IND    (FFB_FLAT_BIT | FFB_ALPHA_BIT | FFB_TRI_CULL_BIT)
+#define TAG(x) x##_flat_alpha_tricull
+#include "ffb_rendertmp.h"
+
+#undef ELT
+#define ELT(x) elt[x]
+
+#define IND    0
+#define TAG(x) x##_elt
+#include "ffb_rendertmp.h"
+
+#define IND    (FFB_FLAT_BIT)
+#define TAG(x) x##_flat_elt
+#include "ffb_rendertmp.h"
+
+#define IND    (FFB_ALPHA_BIT)
+#define TAG(x) x##_alpha_elt
+#include "ffb_rendertmp.h"
+
+#define IND    (FFB_FLAT_BIT | FFB_ALPHA_BIT)
+#define TAG(x) x##_flat_alpha_elt
+#include "ffb_rendertmp.h"
+
+#define IND    (FFB_TRI_CULL_BIT)
+#define TAG(x) x##_tricull_elt
+#include "ffb_rendertmp.h"
+
+#define IND    (FFB_FLAT_BIT | FFB_TRI_CULL_BIT)
+#define TAG(x) x##_flat_tricull_elt
+#include "ffb_rendertmp.h"
+
+#define IND    (FFB_ALPHA_BIT | FFB_TRI_CULL_BIT)
+#define TAG(x) x##_alpha_tricull_elt
+#include "ffb_rendertmp.h"
+
+#define IND    (FFB_FLAT_BIT | FFB_ALPHA_BIT | FFB_TRI_CULL_BIT)
+#define TAG(x) x##_flat_alpha_tricull_elt
+#include "ffb_rendertmp.h"
+
+static void *render_tabs[MAX_FFB_RENDER_FUNCS];
+static void *render_tabs_elt[MAX_FFB_RENDER_FUNCS];
+
+static void init_render_tab(void)
+{
+       int i;
+
+       render_tabs[0] = render_tab;
+       render_tabs[FFB_FLAT_BIT] = render_tab_flat;
+       render_tabs[FFB_ALPHA_BIT] = render_tab_alpha;
+       render_tabs[FFB_FLAT_BIT|FFB_ALPHA_BIT] = render_tab_flat_alpha;
+       render_tabs[FFB_TRI_CULL_BIT] = render_tab_tricull;
+       render_tabs[FFB_FLAT_BIT|FFB_TRI_CULL_BIT] = render_tab_flat_tricull;
+       render_tabs[FFB_ALPHA_BIT|FFB_TRI_CULL_BIT] = render_tab_alpha_tricull;
+       render_tabs[FFB_FLAT_BIT|FFB_ALPHA_BIT|FFB_TRI_CULL_BIT] =
+               render_tab_flat_alpha_tricull;
+
+       render_tabs_elt[0] = render_tab_elt;
+       render_tabs_elt[FFB_FLAT_BIT] = render_tab_flat_elt;
+       render_tabs_elt[FFB_ALPHA_BIT] = render_tab_alpha_elt;
+       render_tabs_elt[FFB_FLAT_BIT|FFB_ALPHA_BIT] = render_tab_flat_alpha_elt;
+       render_tabs_elt[FFB_TRI_CULL_BIT] = render_tab_tricull_elt;
+       render_tabs_elt[FFB_FLAT_BIT|FFB_TRI_CULL_BIT] = render_tab_flat_tricull_elt;
+       render_tabs_elt[FFB_ALPHA_BIT|FFB_TRI_CULL_BIT] = render_tab_alpha_tricull_elt;
+       render_tabs_elt[FFB_FLAT_BIT|FFB_ALPHA_BIT|FFB_TRI_CULL_BIT] =
+               render_tab_flat_alpha_tricull_elt;
+
+       for (i = 0; i < MAX_FFB_RENDER_FUNCS; i++) {
+               render_func *rf = render_tabs[i];
+               render_func *rfe = render_tabs_elt[i];
+
+               if (i & FFB_TRI_CULL_BIT) {
+                       int from_idx = (i & ~FFB_TRI_CULL_BIT);
+                       render_func *rf_from = render_tabs[from_idx];
+                       render_func *rfe_from = render_tabs_elt[from_idx];
+                       int j;
+
+                       for (j = GL_POINTS; j < GL_TRIANGLES; j++) {
+                               rf[j] = rf_from[j];
+                               rfe[j] = rfe_from[j];
+                       }
+               }
+       }
+}
+
+/**********************************************************************/
+/*                    Choose render functions                         */
+/**********************************************************************/
+
+#ifdef FFB_RENDER_TRACE
+static void ffbPrintRenderFlags(GLuint index, GLuint render_index)
+{
+       fprintf(stderr,
+               "ffbChooseRenderState: "
+               "index(%s%s%s) "
+               "render_index(%s%s%s)\n",
+               ((index & FFB_TWOSIDE_BIT) ? "twoside " : ""),
+               ((index & FFB_OFFSET_BIT) ? "offset " : ""),
+               ((index & FFB_UNFILLED_BIT) ? "unfilled " : ""),
+               ((render_index & FFB_FLAT_BIT) ? "flat " : ""),
+               ((render_index & FFB_ALPHA_BIT) ? "alpha " : ""),
+               ((render_index & FFB_TRI_CULL_BIT) ? "tricull " : ""));
+}
+#endif
+
+void ffbChooseRenderState(GLcontext *ctx)
+{
+       GLuint flags = ctx->_TriangleCaps;
+       TNLcontext *tnl = TNL_CONTEXT(ctx);
+       GLuint index = 0;
+
+       /* Per-primitive fallbacks and the selection of fmesa->draw_* are
+        * handled elsewhere.
+        */
+       if (flags & DD_TRI_LIGHT_TWOSIDE)       
+               index |= FFB_TWOSIDE_BIT;
+
+       if (flags & DD_TRI_OFFSET)            
+               index |= FFB_OFFSET_BIT;
+
+       if (flags & DD_TRI_UNFILLED)         
+               index |= FFB_UNFILLED_BIT;
+
+       tnl->Driver.Render.Triangle = rast_tab[index].triangle;
+       tnl->Driver.Render.Quad = rast_tab[index].quad;
+
+       if (index == 0) {
+               GLuint render_index = 0;
+
+               if (flags & DD_FLATSHADE)
+                       render_index |= FFB_FLAT_BIT;
+
+               if (ctx->Color.BlendEnabled || ctx->Color.AlphaEnabled)
+                       render_index |= FFB_ALPHA_BIT;
+
+               if (ctx->Polygon.CullFlag)
+                       render_index |= FFB_TRI_CULL_BIT;
+
+#ifdef FFB_RENDER_TRACE
+               ffbPrintRenderFlags(index, render_index);
+#endif
+               tnl->Driver.Render.PrimTabVerts = render_tabs[render_index];
+               tnl->Driver.Render.PrimTabElts = render_tabs_elt[render_index];
+       } else {
+#ifdef FFB_RENDER_TRACE
+               ffbPrintRenderFlags(index, 0);
+#endif
+               tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
+               tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
+       }
+
+       tnl->Driver.Render.ClippedPolygon = ffbRenderClippedPolygon;
+       tnl->Driver.Render.ClippedLine    = ffbRenderClippedLine;
+}
+
+static void ffbRunPipeline(GLcontext *ctx)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+
+       if (fmesa->bad_fragment_attrs == 0 &&
+           fmesa->new_gl_state) {
+               if (fmesa->new_gl_state & _FFB_NEW_TRIANGLE)
+                       ffbChooseTriangleState(ctx);
+               if (fmesa->new_gl_state & _FFB_NEW_LINE)
+                       ffbChooseLineState(ctx);
+               if (fmesa->new_gl_state & _FFB_NEW_POINT)
+                       ffbChoosePointState(ctx);
+               if (fmesa->new_gl_state & _FFB_NEW_RENDER)
+                       ffbChooseRenderState(ctx);
+               if (fmesa->new_gl_state & _FFB_NEW_VERTEX)
+                       ffbChooseVertexState(ctx);
+
+               fmesa->new_gl_state = 0;
+       }
+
+       _tnl_run_pipeline(ctx);
+}
+
+static void ffbRenderStart(GLcontext *ctx)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+
+       LOCK_HARDWARE(fmesa);
+       fmesa->hw_locked = 1;
+
+       if (fmesa->state_dirty != 0)
+               ffbSyncHardware(fmesa);
+}
+
+static void ffbRenderFinish(GLcontext *ctx)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+
+       UNLOCK_HARDWARE(fmesa);
+       fmesa->hw_locked = 0;
+}
+
+/* Even when doing full software rendering we need to
+ * wrap render{start,finish} so that the hardware is kept
+ * in sync (because multipass rendering changes the write
+ * buffer etc.)
+ */
+static void ffbSWRenderStart(GLcontext *ctx)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+
+       LOCK_HARDWARE(fmesa);
+       fmesa->hw_locked = 1;
+
+       if (fmesa->state_dirty != 0)
+               ffbSyncHardware(fmesa);
+}
+
+static void ffbSWRenderFinish(GLcontext *ctx)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+
+       UNLOCK_HARDWARE(fmesa);
+       fmesa->hw_locked = 0;
+}
+
+static void ffbRasterPrimitive(GLcontext *ctx, GLenum rprim)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       GLuint drawop, fbc, ppc;
+       int do_sw = 0;
+
+       fmesa->raster_primitive = rprim;
+
+       drawop = fmesa->drawop;
+       fbc = fmesa->fbc;
+       ppc = fmesa->ppc & ~(FFB_PPC_ZS_MASK | FFB_PPC_CS_MASK);
+
+#ifdef STATE_TRACE
+       fprintf(stderr,
+               "ffbReducedPrimitiveChange: rprim(%d) ", rprim);
+#endif
+       switch(rprim) {
+       case GL_POINTS:
+#ifdef STATE_TRACE
+               fprintf(stderr, "GL_POINTS ");
+#endif
+               if (fmesa->draw_point == ffb_fallback_point) {
+                       do_sw = 1;
+                       break;
+               }
+
+               if (ctx->Point.SmoothFlag) {
+                       ppc |= (FFB_PPC_ZS_VAR | FFB_PPC_CS_CONST);
+                       drawop = FFB_DRAWOP_AADOT;
+               } else {
+                       ppc |= (FFB_PPC_ZS_CONST | FFB_PPC_CS_CONST);
+                       drawop = FFB_DRAWOP_DOT;
+               }
+               break;
+
+       case GL_LINES:
+#ifdef STATE_TRACE
+               fprintf(stderr, "GL_LINES ");
+#endif
+               if (fmesa->draw_line == ffb_fallback_line) {
+                       do_sw = 1;
+                       break;
+               }
+
+               if (ctx->_TriangleCaps & DD_FLATSHADE) {
+                       ppc |= FFB_PPC_ZS_VAR | FFB_PPC_CS_CONST;
+               } else {
+                       ppc |= FFB_PPC_ZS_VAR | FFB_PPC_CS_VAR;
+               }
+               if (ctx->Line.SmoothFlag)
+                       drawop = FFB_DRAWOP_AALINE;
+               else
+                       drawop = FFB_DRAWOP_DDLINE;
+               break;
+
+       case GL_TRIANGLES:
+#ifdef STATE_TRACE
+               fprintf(stderr, "GL_POLYGON ");
+#endif
+               if (fmesa->draw_tri == ffb_fallback_triangle) {
+                       do_sw = 1;
+                       break;
+               }
+
+               ppc &= ~FFB_PPC_APE_MASK;
+               if (ctx->Polygon.StippleFlag)
+                       ppc |= FFB_PPC_APE_ENABLE;
+               else
+                       ppc |= FFB_PPC_APE_DISABLE;
+
+               if (ctx->_TriangleCaps & DD_FLATSHADE) {
+                       ppc |= FFB_PPC_ZS_VAR | FFB_PPC_CS_CONST;
+               } else {
+                       ppc |= FFB_PPC_ZS_VAR | FFB_PPC_CS_VAR;
+               }
+               drawop = FFB_DRAWOP_TRIANGLE;
+               break;
+
+       default:
+#ifdef STATE_TRACE
+               fprintf(stderr, "unknown %d!\n", rprim);
+#endif
+               return;
+       };
+
+#ifdef STATE_TRACE
+       fprintf(stderr, "do_sw(%d) ", do_sw);
+#endif
+       if (do_sw != 0) {
+               fbc &= ~(FFB_FBC_WB_C);
+               fbc &= ~(FFB_FBC_ZE_MASK | FFB_FBC_RGBE_MASK);
+               fbc |=   FFB_FBC_ZE_OFF  | FFB_FBC_RGBE_MASK;
+               ppc &= ~(FFB_PPC_XS_MASK | FFB_PPC_ABE_MASK |
+                        FFB_PPC_DCE_MASK | FFB_PPC_APE_MASK);
+               ppc |=  (FFB_PPC_ZS_VAR | FFB_PPC_CS_VAR | FFB_PPC_XS_WID |
+                        FFB_PPC_ABE_DISABLE | FFB_PPC_DCE_DISABLE |
+                        FFB_PPC_APE_DISABLE);
+       } else {
+               fbc |= FFB_FBC_WB_C;
+               fbc &= ~(FFB_FBC_RGBE_MASK);
+               fbc |=   FFB_FBC_RGBE_MASK;
+               ppc &= ~(FFB_PPC_ABE_MASK | FFB_PPC_XS_MASK);
+               if (ctx->Color.BlendEnabled) {
+                       if ((rprim == GL_POINTS && !ctx->Point.SmoothFlag) ||
+                           (rprim != GL_POINTS && ctx->_TriangleCaps & DD_FLATSHADE))
+                               ppc |= FFB_PPC_ABE_ENABLE | FFB_PPC_XS_CONST;
+                       else
+                               ppc |= FFB_PPC_ABE_ENABLE | FFB_PPC_XS_VAR;
+               } else {
+                       ppc |= FFB_PPC_ABE_DISABLE | FFB_PPC_XS_WID;
+               }
+       }
+#ifdef STATE_TRACE
+       fprintf(stderr, "fbc(%08x) ppc(%08x)\n", fbc, ppc);
+#endif
+
+       FFBFifo(fmesa, 4);
+       if (fmesa->drawop != drawop)
+               fmesa->regs->drawop = fmesa->drawop = drawop;
+       if (fmesa->fbc != fbc)
+               fmesa->regs->fbc = fmesa->fbc = fbc;
+       if (fmesa->ppc != ppc)
+               fmesa->regs->ppc = fmesa->ppc = ppc;
+       if (do_sw != 0) {
+               fmesa->regs->cmp =
+                       (fmesa->cmp & ~(0xff<<16)) | (0x80 << 16);
+       } else
+               fmesa->regs->cmp = fmesa->cmp;
+}
+
+static void ffbRenderPrimitive(GLcontext *ctx, GLenum prim)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       GLuint rprim = reduced_prim[prim];
+
+       fmesa->render_primitive = prim;
+
+       if (rprim == GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
+               return;
+
+       if (fmesa->raster_primitive != rprim) {
+               ffbRasterPrimitive( ctx, rprim );
+       }
+}
+
+
+
+
+/**********************************************************************/
+/*           Transition to/from hardware rasterization.               */
+/**********************************************************************/
+
+static char *fallbackStrings[] = {
+       "Fog enabled",
+       "Blend function",
+       "Blend ROP",
+       "Blend equation",
+       "Stencil",
+       "Texture",
+       "LIBGL_SOFTWARE_RENDERING"
+};
+
+static char *getFallbackString(GLuint bit)
+{
+       int i = 0;
+
+       while (bit > 1) {
+               i++;
+               bit >>= 1;
+       }
+       return fallbackStrings[i];
+}
+
+void ffbFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       TNLcontext *tnl = TNL_CONTEXT(ctx);
+       GLuint oldfallback = fmesa->bad_fragment_attrs;
+
+       if (mode) {
+               fmesa->bad_fragment_attrs |= bit;
+               if (oldfallback == 0) {
+/*                     FFB_FIREVERTICES(fmesa); */
+                       _swsetup_Wakeup( ctx );
+                       if (fmesa->debugFallbacks)
+                               fprintf(stderr, "FFB begin software fallback: 0x%x %s\n",
+                                       bit, getFallbackString(bit));
+               }
+       } else {
+               fmesa->bad_fragment_attrs &= ~bit;
+               if (oldfallback == bit) {
+                       _swrast_flush( ctx );
+
+                       tnl->Driver.Render.Start = ffbRenderStart;
+                       tnl->Driver.Render.PrimitiveNotify = ffbRenderPrimitive;
+                       tnl->Driver.Render.Finish = ffbRenderFinish;
+                       fmesa->new_gl_state = ~0;
+
+                       /* Just re-choose everything:
+                        */
+                       ffbChooseVertexState(ctx);
+                       ffbChooseRenderState(ctx);
+                       ffbChooseTriangleState(ctx);
+                       ffbChooseLineState(ctx);
+                       ffbChoosePointState(ctx);
+
+                       if (fmesa->debugFallbacks)
+                               fprintf(stderr, "FFB end software fallback: 0x%x %s\n",
+                                       bit, getFallbackString(bit));
+               }
+       }
+}
+
+/**********************************************************************/
+/*                            Initialization.                         */
+/**********************************************************************/
+
+void ffbDDInitRenderFuncs( GLcontext *ctx )
+{
+       TNLcontext *tnl = TNL_CONTEXT(ctx);
+       SWcontext *swrast = SWRAST_CONTEXT(ctx);
+       static int firsttime = 1;
+
+       if (firsttime) {
+               init_rast_tab();
+               init_tri_tab();
+               init_render_tab();
+               firsttime = 0;
+       }
+
+       tnl->Driver.RunPipeline = ffbRunPipeline;
+       tnl->Driver.Render.Start = ffbRenderStart;
+       tnl->Driver.Render.Finish = ffbRenderFinish; 
+       tnl->Driver.Render.PrimitiveNotify = ffbRenderPrimitive;
+       tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
+       tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
+       tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
+
+       swrast->Driver.SpanRenderStart = ffbSWRenderStart;
+       swrast->Driver.SpanRenderFinish = ffbSWRenderFinish;
+}
diff --git a/src/mesa/drivers/dri/ffb/ffb_tris.h b/src/mesa/drivers/dri/ffb/ffb_tris.h
new file mode 100644 (file)
index 0000000..1b1a007
--- /dev/null
@@ -0,0 +1,29 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_tris.h,v 1.2 2002/02/22 21:32:59 dawes Exp $ */
+
+#ifndef _FFB_TRIS_H
+#define _FFB_TRIS_H
+
+extern void ffbDDInitRenderFuncs( GLcontext *ctx );
+
+
+#define _FFB_NEW_RENDER (_DD_NEW_TRI_LIGHT_TWOSIDE |   \
+                        _DD_NEW_TRI_OFFSET |           \
+                        _DD_NEW_TRI_UNFILLED)
+
+extern void ffbChooseRenderState(GLcontext *ctx);
+
+
+#define _FFB_NEW_TRIANGLE (_DD_NEW_TRI_SMOOTH |        \
+                          _DD_NEW_FLATSHADE |  \
+                          _NEW_POLYGON |       \
+                          _NEW_COLOR)
+
+extern void ffbChooseTriangleState(GLcontext *ctx);
+
+extern void ffbFallback( GLcontext *ctx, GLuint bit, GLboolean mode );
+#define FALLBACK( ctx, bit, mode ) ffbFallback( ctx, bit, mode )
+
+extern void ffb_fallback_line(GLcontext *, ffb_vertex *, ffb_vertex *);
+extern void ffb_fallback_point(GLcontext *, ffb_vertex *);
+
+#endif /* !(_FFB_TRIS_H) */
diff --git a/src/mesa/drivers/dri/ffb/ffb_tritmp.h b/src/mesa/drivers/dri/ffb/ffb_tritmp.h
new file mode 100644 (file)
index 0000000..612ef24
--- /dev/null
@@ -0,0 +1,239 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_tritmp.h,v 1.2 2002/02/22 21:32:59 dawes Exp $ */
+
+static void TAG(ffb_triangle)( GLcontext *ctx,         
+                              ffb_vertex *v0,
+                              ffb_vertex *v1,
+                              ffb_vertex *v2 )
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       ffb_fbcPtr ffb = fmesa->regs;
+#if (IND & FFB_TRI_FLAT_BIT)
+       GLuint const_fg;
+#endif
+       FFB_DELAYED_VIEWPORT_VARS;
+
+#ifdef TRI_DEBUG
+       fprintf(stderr, "FFB: ffb_triangle ["
+#if (IND & FFB_TRI_CULL_BIT)
+               " CULL"
+#endif
+#if (IND & FFB_TRI_FLAT_BIT)
+               " FLAT"
+#endif
+#if (IND & FFB_TRI_ALPHA_BIT)
+               " ALPHA"
+#endif
+               " ]\n");
+#endif
+
+#if (IND & FFB_TRI_CULL_BIT)
+       {       /* NOTE: These are not viewport transformed yet. */
+               GLfloat ex = v1->x - v0->x;
+               GLfloat ey = v1->y - v0->y;
+               GLfloat fx = v2->x - v0->x;
+               GLfloat fy = v2->y - v0->y;
+               GLfloat c = ex*fy-ey*fx;
+
+               /* Culled... */
+               if (c * fmesa->backface_sign > fmesa->ffb_zero)
+                       return;
+       }
+#endif
+
+#if (IND & FFB_TRI_FLAT_BIT)
+       const_fg = FFB_PACK_CONST_UBYTE_ARGB_COLOR( v2->color[0] );
+#ifdef TRI_DEBUG
+       fprintf(stderr, "FFB_tri: const_fg %08x (B[%f] G[%f] R[%f])\n",
+               const_fg,
+               FFB_2_30_FIXED_TO_FLOAT(v2->color[0].blue),
+               FFB_2_30_FIXED_TO_FLOAT(v2->color[0].green),
+               FFB_2_30_FIXED_TO_FLOAT(v2->color[0].red));
+#endif
+#endif
+
+
+#if (IND & FFB_TRI_FLAT_BIT)
+       FFBFifo(fmesa, 1);
+       ffb->fg = const_fg;
+#endif
+
+#if (IND & FFB_TRI_FLAT_BIT)
+       FFBFifo(fmesa, 9);
+#else
+#if (IND & FFB_TRI_ALPHA_BIT)
+       FFBFifo(fmesa, 21);
+#else
+       FFBFifo(fmesa, 18);
+#endif
+#endif
+
+       FFB_DUMP_VERTEX(v0);
+#if !(IND & FFB_TRI_FLAT_BIT)
+#if (IND & FFB_TRI_ALPHA_BIT)
+       ffb->alpha = FFB_GET_ALPHA(v0);
+#endif
+       ffb->red   = FFB_GET_RED(v0);
+       ffb->green = FFB_GET_GREEN(v0);
+       ffb->blue  = FFB_GET_BLUE(v0);
+#endif
+       ffb->z     = FFB_GET_Z(v0);
+       ffb->ryf   = FFB_GET_Y(v0);
+       ffb->rxf   = FFB_GET_X(v0);
+
+       FFB_DUMP_VERTEX(v1);
+#if !(IND & FFB_TRI_FLAT_BIT)
+#if (IND & FFB_TRI_ALPHA_BIT)
+       ffb->alpha = FFB_GET_ALPHA(v1);
+#endif
+       ffb->red   = FFB_GET_RED(v1);
+       ffb->green = FFB_GET_GREEN(v1);
+       ffb->blue  = FFB_GET_BLUE(v1);
+#endif
+       ffb->z     = FFB_GET_Z(v1);
+       ffb->y     = FFB_GET_Y(v1);
+       ffb->x     = FFB_GET_X(v1);
+
+       FFB_DUMP_VERTEX(v2);
+#if !(IND & FFB_TRI_FLAT_BIT)
+#if (IND & FFB_TRI_ALPHA_BIT)
+       ffb->alpha = FFB_GET_ALPHA(v2);
+#endif
+       ffb->red   = FFB_GET_RED(v2);
+       ffb->green = FFB_GET_GREEN(v2);
+       ffb->blue  = FFB_GET_BLUE(v2);
+#endif
+       ffb->z     = FFB_GET_Z(v2);
+       ffb->y     = FFB_GET_Y(v2);
+       ffb->x     = FFB_GET_X(v2);
+
+       fmesa->ffbScreen->rp_active = 1;
+}
+
+
+static void TAG(ffb_quad)(GLcontext *ctx,                            
+                         ffb_vertex *v0,
+                         ffb_vertex *v1,
+                         ffb_vertex *v2,
+                         ffb_vertex *v3 )
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       ffb_fbcPtr ffb = fmesa->regs;
+#if (IND & FFB_TRI_FLAT_BIT)
+       GLuint const_fg;
+#endif
+       FFB_DELAYED_VIEWPORT_VARS;
+
+#ifdef TRI_DEBUG
+       fprintf(stderr, "FFB: ffb_quad ["
+#if (IND & FFB_TRI_CULL_BIT)
+               " CULL"
+#endif
+#if (IND & FFB_TRI_FLAT_BIT)
+               " FLAT"
+#endif
+#if (IND & FFB_TRI_ALPHA_BIT)
+               " ALPHA"
+#endif
+               " ]\n");
+#endif /* TRI_DEBUG */
+
+#if (IND & FFB_TRI_CULL_BIT)
+       {       /* NOTE: These are not viewport transformed yet. */
+               GLfloat ex = v2->x - v0->x;
+               GLfloat ey = v2->y - v0->y;
+               GLfloat fx = v3->x - v1->x;
+               GLfloat fy = v3->y - v1->y;
+               GLfloat c = ex*fy-ey*fx;
+
+               /* Culled... */
+               if (c * fmesa->backface_sign > fmesa->ffb_zero)
+                       return;
+       }
+#endif
+
+#if (IND & FFB_TRI_FLAT_BIT)
+       const_fg = FFB_PACK_CONST_UBYTE_ARGB_COLOR( v3->color[0] );
+#ifdef TRI_DEBUG
+       fprintf(stderr, "FFB_quad: const_fg %08x (B[%f] G[%f] R[%f])\n",
+               const_fg,
+               FFB_2_30_FIXED_TO_FLOAT(v3->color[0].blue),
+               FFB_2_30_FIXED_TO_FLOAT(v3->color[0].green),
+               FFB_2_30_FIXED_TO_FLOAT(v3->color[0].red));
+#endif
+#endif
+
+
+#if (IND & FFB_TRI_FLAT_BIT)
+       FFBFifo(fmesa, 13);
+       ffb->fg = const_fg;
+#else
+#if (IND & FFB_TRI_ALPHA_BIT)
+       FFBFifo(fmesa, 28);
+#else
+       FFBFifo(fmesa, 24);
+#endif
+#endif
+
+       FFB_DUMP_VERTEX(v0);
+#if !(IND & FFB_TRI_FLAT_BIT)
+#if (IND & FFB_TRI_ALPHA_BIT)
+       ffb->alpha = FFB_GET_ALPHA(v0);
+#endif
+       ffb->red   = FFB_GET_RED(v0);
+       ffb->green = FFB_GET_GREEN(v0);
+       ffb->blue  = FFB_GET_BLUE(v0);
+#endif
+       ffb->z     = FFB_GET_Z(v0);
+       ffb->ryf   = FFB_GET_Y(v0);
+       ffb->rxf   = FFB_GET_X(v0);
+
+       FFB_DUMP_VERTEX(v1);
+#if !(IND & FFB_TRI_FLAT_BIT)
+#if (IND & FFB_TRI_ALPHA_BIT)
+       ffb->alpha = FFB_GET_ALPHA(v1);
+#endif
+       ffb->red   = FFB_GET_RED(v1);
+       ffb->green = FFB_GET_GREEN(v1);
+       ffb->blue  = FFB_GET_BLUE(v1);
+#endif
+       ffb->z     = FFB_GET_Z(v1);
+       ffb->y     = FFB_GET_Y(v1);
+       ffb->x     = FFB_GET_X(v1);
+
+       FFB_DUMP_VERTEX(v2);
+#if !(IND & FFB_TRI_FLAT_BIT)
+#if (IND & FFB_TRI_ALPHA_BIT)
+       ffb->alpha = FFB_GET_ALPHA(v2);
+#endif
+       ffb->red   = FFB_GET_RED(v2);
+       ffb->green = FFB_GET_GREEN(v2);
+       ffb->blue  = FFB_GET_BLUE(v2);
+#endif
+       ffb->z     = FFB_GET_Z(v2);
+       ffb->y     = FFB_GET_Y(v2);
+       ffb->x     = FFB_GET_X(v2);
+
+       FFB_DUMP_VERTEX(v3);
+#if !(IND & FFB_TRI_FLAT_BIT)
+#if (IND & FFB_TRI_ALPHA_BIT)
+       ffb->alpha = FFB_GET_ALPHA(v3);
+#endif
+       ffb->red   = FFB_GET_RED(v3);
+       ffb->green = FFB_GET_GREEN(v3);
+       ffb->blue  = FFB_GET_BLUE(v3);
+#endif
+       ffb->z     = FFB_GET_Z(v3);
+       ffb->dmyf  = FFB_GET_Y(v3);
+       ffb->dmxf  = FFB_GET_X(v3);
+
+       fmesa->ffbScreen->rp_active = 1;
+}
+
+static void TAG(ffb_init)(void)
+{
+       ffb_tri_tab[IND]        = TAG(ffb_triangle);
+       ffb_quad_tab[IND]       = TAG(ffb_quad);
+}
+
+#undef IND
+#undef TAG
diff --git a/src/mesa/drivers/dri/ffb/ffb_vb.c b/src/mesa/drivers/dri/ffb/ffb_vb.c
new file mode 100644 (file)
index 0000000..40820c6
--- /dev/null
@@ -0,0 +1,241 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_vb.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 <davem@redhat.com>
+ */
+
+#include "ffb_xmesa.h"
+#include "ffb_context.h"
+#include "ffb_vb.h"
+#include "mmath.h"
+#include "imports.h"
+#include "tnl/t_context.h"
+#include "swrast_setup/swrast_setup.h"
+#include "math/m_translate.h"
+
+#undef VB_DEBUG
+
+static void ffb_copy_pv_oneside(GLcontext *ctx, GLuint edst, GLuint esrc)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       ffb_vertex *dst = &fmesa->verts[edst];
+       ffb_vertex *src = &fmesa->verts[esrc];
+
+#ifdef VB_DEBUG
+       fprintf(stderr, "ffb_copy_pv_oneside: edst(%d) esrc(%d)\n", edst, esrc);
+#endif
+       dst->color[0].alpha = src->color[0].alpha;
+       dst->color[0].red   = src->color[0].red;
+       dst->color[0].green = src->color[0].green;
+       dst->color[0].blue  = src->color[0].blue;
+}
+
+static void ffb_copy_pv_twoside(GLcontext *ctx, GLuint edst, GLuint esrc)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       ffb_vertex *dst = &fmesa->verts[edst];
+       ffb_vertex *src = &fmesa->verts[esrc];
+
+#ifdef VB_DEBUG
+       fprintf(stderr, "ffb_copy_pv_twoside: edst(%d) esrc(%d)\n", edst, esrc);
+#endif
+       dst->color[0].alpha = src->color[0].alpha;
+       dst->color[0].red   = src->color[0].red;
+       dst->color[0].green = src->color[0].green;
+       dst->color[0].blue  = src->color[0].blue;
+       dst->color[1].alpha = src->color[1].alpha;
+       dst->color[1].red   = src->color[1].red;
+       dst->color[1].green = src->color[1].green;
+       dst->color[1].blue  = src->color[1].blue;
+}
+
+#define FFB_VB_RGBA_BIT                0x01
+#define FFB_VB_XYZ_BIT         0x02
+#define FFB_VB_TWOSIDE_BIT     0x04
+#define FFB_VB_MAX             0x08
+
+typedef void (*emit_func)(GLcontext *, GLuint, GLuint);
+
+static struct {
+       emit_func       emit;
+       interp_func     interp;
+} setup_tab[FFB_VB_MAX];
+
+static void do_import(struct vertex_buffer *VB,
+                     struct gl_client_array *to,
+                     struct gl_client_array *from)
+{
+       GLuint count = VB->Count;
+
+       if (!to->Ptr) {
+               to->Ptr = ALIGN_MALLOC( VB->Size * 4 * sizeof(GLfloat), 32 );
+               to->Type = GL_FLOAT;
+       }
+
+       /* No need to transform the same value 3000 times. */
+       if (!from->StrideB) {
+               to->StrideB = 0;
+               count = 1;
+       } else
+               to->StrideB = 4 * sizeof(GLfloat);
+   
+       _math_trans_4f((GLfloat (*)[4]) to->Ptr,
+                      from->Ptr, from->StrideB,
+                      from->Type, from->Size,
+                      0, count);
+}
+
+static __inline__ void ffbImportColors(ffbContextPtr fmesa, GLcontext *ctx, int index)
+{
+       struct gl_client_array *to = &fmesa->FloatColor;
+       struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+       do_import(VB, to, VB->ColorPtr[index]);
+       VB->ColorPtr[index] = to;
+}
+
+#define IND    (FFB_VB_XYZ_BIT)
+#define TAG(x) x##_w
+#include "ffb_vbtmp.h"
+
+#define IND    (FFB_VB_RGBA_BIT)
+#define TAG(x) x##_g
+#include "ffb_vbtmp.h"
+
+#define IND    (FFB_VB_XYZ_BIT | FFB_VB_RGBA_BIT)
+#define TAG(x) x##_wg
+#include "ffb_vbtmp.h"
+
+#define IND    (FFB_VB_TWOSIDE_BIT)
+#define TAG(x) x##_t
+#include "ffb_vbtmp.h"
+
+#define IND    (FFB_VB_XYZ_BIT | FFB_VB_TWOSIDE_BIT)
+#define TAG(x) x##_wt
+#include "ffb_vbtmp.h"
+
+#define IND    (FFB_VB_RGBA_BIT | FFB_VB_TWOSIDE_BIT)
+#define TAG(x) x##_gt
+#include "ffb_vbtmp.h"
+
+#define IND    (FFB_VB_XYZ_BIT | FFB_VB_RGBA_BIT | FFB_VB_TWOSIDE_BIT)
+#define TAG(x) x##_wgt
+#include "ffb_vbtmp.h"
+
+static void init_setup_tab( void )
+{
+       init_w();
+       init_g();
+       init_wg();
+       init_t();
+       init_wt();
+       init_gt();
+       init_wgt();
+}
+
+#ifdef VB_DEBUG
+static void ffbPrintSetupFlags(char *msg, GLuint flags)
+{
+   fprintf(stderr, "%s(%x): %s%s%s\n",
+          msg,
+          (int)flags,
+          (flags & FFB_VB_XYZ_BIT)     ? " xyz," : "", 
+          (flags & FFB_VB_RGBA_BIT)    ? " rgba," : "",
+          (flags & FFB_VB_TWOSIDE_BIT) ? " twoside," : "");
+}
+#endif
+
+static void ffbDDBuildVertices(GLcontext *ctx, GLuint start, GLuint count, 
+                              GLuint newinputs)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+
+       newinputs |= fmesa->setupnewinputs;
+       fmesa->setupnewinputs = 0;
+
+       if (!newinputs)
+               return;
+
+       if (newinputs & VERT_BIT_CLIP) {
+               setup_tab[fmesa->setupindex].emit(ctx, start, count);
+       } else {
+               GLuint ind = 0;
+
+               if (newinputs & VERT_BIT_COLOR0)
+                       ind |= (FFB_VB_RGBA_BIT | FFB_VB_TWOSIDE_BIT);
+
+               ind &= fmesa->setupindex;
+
+               if (ind)
+                       setup_tab[ind].emit(ctx, start, count);
+       }
+}
+
+void ffbChooseVertexState( GLcontext *ctx )
+{
+       TNLcontext *tnl = TNL_CONTEXT(ctx);
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       int ind = FFB_VB_XYZ_BIT | FFB_VB_RGBA_BIT;
+
+       if (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE)
+               ind |= FFB_VB_TWOSIDE_BIT;
+
+#ifdef VB_DEBUG
+       ffbPrintSetupFlags("ffb: full setup function", ind);
+#endif
+
+       fmesa->setupindex = ind;
+
+       tnl->Driver.Render.BuildVertices = ffbDDBuildVertices;
+       tnl->Driver.Render.Interp = setup_tab[ind].interp;
+       if (ind & FFB_VB_TWOSIDE_BIT)
+               tnl->Driver.Render.CopyPV = ffb_copy_pv_twoside;
+       else
+               tnl->Driver.Render.CopyPV = ffb_copy_pv_oneside;
+}
+
+void ffbInitVB( GLcontext *ctx )
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       GLuint size = TNL_CONTEXT(ctx)->vb.Size;
+
+       fmesa->verts = (ffb_vertex *)ALIGN_MALLOC(size * sizeof(ffb_vertex), 32);
+
+       {
+               static int firsttime = 1;
+               if (firsttime) {
+                       init_setup_tab();
+                       firsttime = 0;
+               }
+       }
+}
+
+
+void ffbFreeVB( GLcontext *ctx )
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       if (fmesa->verts) {
+               ALIGN_FREE(fmesa->verts);
+               fmesa->verts = 0;
+       }
+}
diff --git a/src/mesa/drivers/dri/ffb/ffb_vb.h b/src/mesa/drivers/dri/ffb/ffb_vb.h
new file mode 100644 (file)
index 0000000..9eb6759
--- /dev/null
@@ -0,0 +1,45 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_vb.h,v 1.2 2002/02/22 21:32:59 dawes Exp $ */
+
+#ifndef _FFB_VB_H
+#define _FFB_VB_H
+
+#include "mtypes.h"
+#include "macros.h"
+#include "tnl/t_context.h"
+#include "swrast/swrast.h"
+
+#define __FFB_2_30_FIXED_SCALE         1073741824.0f
+#define FFB_2_30_FLOAT_TO_FIXED(X)     \
+       (IROUND((X) * fmesa->ffb_2_30_fixed_scale))
+#define FFB_2_30_FIXED_TO_FLOAT(X)     \
+       (((GLfloat)(X)) * fmesa->ffb_one_over_2_30_fixed_scale)
+
+#define __FFB_16_16_FIXED_SCALE                65536.0f
+#define FFB_16_16_FLOAT_TO_FIXED(X)    \
+       (IROUND((X) * fmesa->ffb_16_16_fixed_scale))
+#define FFB_16_16_FIXED_TO_FLOAT(X)    \
+       (((GLfloat)(X)) * fmesa->ffb_one_over_16_16_fixed_scale)
+
+#define FFB_Z_FROM_FLOAT(VAL)    FFB_2_30_FLOAT_TO_FIXED(VAL)
+#define FFB_Z_TO_FLOAT(VAL)      FFB_2_30_FIXED_TO_FLOAT(VAL)
+#define FFB_XY_FROM_FLOAT(VAL)   FFB_16_16_FLOAT_TO_FIXED(VAL)
+#define FFB_XY_TO_FLOAT(VAL)     FFB_16_16_FIXED_TO_FLOAT(VAL)
+
+#define FFB_UBYTE_FROM_COLOR(VAL) ((IROUND((VAL) * fmesa->ffb_ubyte_color_scale)))
+
+#define FFB_PACK_CONST_UBYTE_ARGB_COLOR(C)             \
+        ((FFB_UBYTE_FROM_COLOR(C.alpha) << 24) |       \
+         (FFB_UBYTE_FROM_COLOR(C.blue)  << 16) |       \
+         (FFB_UBYTE_FROM_COLOR(C.green) <<  8) |       \
+         (FFB_UBYTE_FROM_COLOR(C.red)   <<  0))
+
+#define FFB_COLOR_FROM_FLOAT(VAL) FFB_2_30_FLOAT_TO_FIXED(VAL)
+
+#define _FFB_NEW_VERTEX (_DD_NEW_TRI_LIGHT_TWOSIDE)
+
+extern void ffbDDSetupInit(void);
+extern void ffbChooseVertexState(GLcontext *);
+extern void ffbInitVB( GLcontext *ctx );
+extern void ffbFreeVB( GLcontext *ctx );
+
+#endif /* !(_FFB_VB_H) */
diff --git a/src/mesa/drivers/dri/ffb/ffb_vbtmp.h b/src/mesa/drivers/dri/ffb/ffb_vbtmp.h
new file mode 100644 (file)
index 0000000..ac0c6f0
--- /dev/null
@@ -0,0 +1,177 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_vbtmp.h,v 1.1 2002/02/22 21:32:59 dawes Exp $ */
+
+static void TAG(emit)(GLcontext *ctx, GLuint start, GLuint end)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+#if (IND & (FFB_VB_RGBA_BIT))
+       GLfloat (*col0)[4];
+       GLuint col0_stride;
+#if (IND & (FFB_VB_TWOSIDE_BIT))
+       GLfloat (*col1)[4];
+       GLuint col1_stride;
+#endif
+#endif
+#if (IND & FFB_VB_XYZ_BIT)
+       GLfloat (*proj)[4] = VB->NdcPtr->data;
+       GLuint proj_stride = VB->NdcPtr->stride;
+       const GLubyte *mask = VB->ClipMask;
+#endif
+       ffb_vertex *v = &fmesa->verts[start];
+       int i;
+
+#ifdef VB_DEBUG
+       fprintf(stderr, "FFB: ffb_emit ["
+#if (IND & (FFB_VB_XYZ_BIT))
+               " XYZ"
+#endif
+#if (IND & (FFB_VB_RGBA_BIT))
+               " RGBA"
+#endif
+#if (IND & (FFB_VB_TWOSIDE_BIT))
+               " TWOSIDE"
+#endif
+               "] start(%d) end(%d) import(%d)\n",
+               start, end,
+               VB->importable_data);
+#endif
+
+#if (IND & (FFB_VB_RGBA_BIT))
+       if (VB->ColorPtr[0]->Type != GL_FLOAT)
+               ffbImportColors(fmesa, ctx, 0);
+#if (IND & (FFB_VB_TWOSIDE_BIT))
+       if (VB->ColorPtr[1]->Type != GL_FLOAT)
+               ffbImportColors(fmesa, ctx, 1);
+#endif
+       col0 = (GLfloat (*)[4]) VB->ColorPtr[0]->Ptr;
+       col0_stride = VB->ColorPtr[0]->StrideB;
+#if (IND & (FFB_VB_TWOSIDE_BIT))
+       col1 = (GLfloat (*)[4]) VB->ColorPtr[1]->Ptr;
+       col1_stride = VB->ColorPtr[1]->StrideB;
+#endif
+#endif
+
+       if (VB->importable_data) {
+               if (start) {
+#if (IND & (FFB_VB_XYZ_BIT))
+                       proj = (GLfloat (*)[4])((GLubyte *)proj + start * proj_stride);
+#endif
+#if (IND & (FFB_VB_RGBA_BIT))
+                       col0 = (GLfloat (*)[4])((GLubyte *)col0 + start * col0_stride);
+#if (IND & (FFB_VB_TWOSIDE_BIT))
+                       col1 = (GLfloat (*)[4])((GLubyte *)col1 + start * col1_stride);
+#endif
+#endif
+               }
+               for (i = start; i < end; i++, v++) {
+#if (IND & (FFB_VB_XYZ_BIT))
+                       if (mask[i] == 0) {
+                               v->x = proj[0][0];
+                               v->y = proj[0][1];
+                               v->z = proj[0][2];
+                       }
+                       proj = (GLfloat (*)[4])((GLubyte *)proj + proj_stride);
+#endif
+#if (IND & (FFB_VB_RGBA_BIT))
+                       v->color[0].alpha = CLAMP(col0[0][3], 0.0f, 1.0f);
+                       v->color[0].red   = CLAMP(col0[0][0], 0.0f, 1.0f);
+                       v->color[0].green = CLAMP(col0[0][1], 0.0f, 1.0f);
+                       v->color[0].blue  = CLAMP(col0[0][2], 0.0f, 1.0f);
+                       col0 = (GLfloat (*)[4])((GLubyte *)col0 + col0_stride);
+#if (IND & (FFB_VB_TWOSIDE_BIT))
+                       v->color[1].alpha = CLAMP(col1[0][3], 0.0f, 1.0f);
+                       v->color[1].red   = CLAMP(col1[0][0], 0.0f, 1.0f);
+                       v->color[1].green = CLAMP(col1[0][1], 0.0f, 1.0f);
+                       v->color[1].blue  = CLAMP(col1[0][2], 0.0f, 1.0f);
+                       col1 = (GLfloat (*)[4])((GLubyte *)col1 + col1_stride);
+#endif
+#endif
+               }
+       } else {
+               for (i = start; i < end; i++, v++) {
+#if (IND & (FFB_VB_XYZ_BIT))
+                       if (mask[i] == 0) {
+                               v->x = proj[i][0];
+                               v->y = proj[i][1];
+                               v->z = proj[i][2];
+                       }
+#endif
+#if (IND & (FFB_VB_RGBA_BIT))
+                       v->color[0].alpha = CLAMP(col0[i][3], 0.0f, 1.0f);
+                       v->color[0].red   = CLAMP(col0[i][0], 0.0f, 1.0f);
+                       v->color[0].green = CLAMP(col0[i][1], 0.0f, 1.0f);
+                       v->color[0].blue  = CLAMP(col0[i][2], 0.0f, 1.0f);
+#if (IND & (FFB_VB_TWOSIDE_BIT))
+                       v->color[1].alpha = CLAMP(col1[i][3], 0.0f, 1.0f);
+                       v->color[1].red   = CLAMP(col1[i][0], 0.0f, 1.0f);
+                       v->color[1].green = CLAMP(col1[i][1], 0.0f, 1.0f);
+                       v->color[1].blue  = CLAMP(col1[i][2], 0.0f, 1.0f);
+#endif
+#endif
+               }
+       }
+}
+
+static void TAG(interp)(GLcontext *ctx, GLfloat t,
+                       GLuint edst, GLuint eout, GLuint ein,
+                       GLboolean force_boundary)
+{
+#if (IND & (FFB_VB_XYZ_BIT | FFB_VB_RGBA_BIT))
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+#endif
+#if (IND & (FFB_VB_XYZ_BIT))
+       struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+       const GLfloat *dstclip = VB->ClipPtr->data[edst];
+       GLfloat oow = 1.0 / dstclip[3];
+#endif
+#if (IND & (FFB_VB_XYZ_BIT | FFB_VB_RGBA_BIT))
+       ffb_vertex *dst = &fmesa->verts[edst];
+#endif
+#if (IND & (FFB_VB_RGBA_BIT))
+       ffb_vertex *in = &fmesa->verts[eout];
+       ffb_vertex *out = &fmesa->verts[ein];
+#endif
+
+#ifdef VB_DEBUG
+       fprintf(stderr, "FFB: ffb_interp ["
+#if (IND & (FFB_VB_XYZ_BIT))
+               " XYZ"
+#endif
+#if (IND & (FFB_VB_RGBA_BIT))
+               " RGBA"
+#endif
+#if (IND & (FFB_VB_TWOSIDE_BIT))
+               " TWOSIDE"
+#endif
+               "] edst(%d) eout(%d) ein(%d)\n",
+               edst, eout, ein);
+#endif
+
+#if (IND & (FFB_VB_XYZ_BIT))
+       dst->x = dstclip[0] * oow;
+       dst->y = dstclip[1] * oow;
+       dst->z = dstclip[2] * oow;
+#endif
+
+#if (IND & (FFB_VB_RGBA_BIT))
+       INTERP_F(t, dst->color[0].alpha, out->color[0].alpha, in->color[0].alpha);
+       INTERP_F(t, dst->color[0].red,   out->color[0].red,   in->color[0].red);
+       INTERP_F(t, dst->color[0].green, out->color[0].green, in->color[0].green);
+       INTERP_F(t, dst->color[0].blue,  out->color[0].blue,  in->color[0].blue);
+#if (IND & (FFB_VB_TWOSIDE_BIT))
+       INTERP_F(t, dst->color[1].alpha, out->color[1].alpha, in->color[1].alpha);
+       INTERP_F(t, dst->color[1].red,   out->color[1].red,   in->color[1].red);
+       INTERP_F(t, dst->color[1].green, out->color[1].green, in->color[1].green);
+       INTERP_F(t, dst->color[1].blue,  out->color[1].blue,  in->color[1].blue);
+#endif
+#endif
+}
+
+static void TAG(init)(void)
+{
+       setup_tab[IND].emit = TAG(emit);
+       setup_tab[IND].interp = TAG(interp);
+}
+
+#undef IND
+#undef TAG
diff --git a/src/mesa/drivers/dri/ffb/ffb_vtxfmt.c b/src/mesa/drivers/dri/ffb/ffb_vtxfmt.c
new file mode 100644 (file)
index 0000000..5f6d5c9
--- /dev/null
@@ -0,0 +1,429 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_vtxfmt.c,v 1.1 2002/02/22 21:32:59 dawes Exp $
+ *
+ * GLX Hardware Device Driver for Sun Creator/Creator3D
+ * Copyright (C) 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 <davem@redhat.com>
+ */
+
+#include "glheader.h"
+#include "api_noop.h"
+#include "context.h"
+#include "light.h"
+#include "macros.h"
+#include "imports.h"
+#include "mmath.h"
+#include "mtypes.h"
+#include "simple_list.h"
+#include "vtxfmt.h"
+#include "ffb_xmesa.h"
+#include "ffb_context.h"
+#include "ffb_vb.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+
+#include "ffb_vtxfmt.h"
+
+#ifndef __GNUC__
+#define __inline  /**/
+#endif
+
+#define TNL_VERTEX                     ffbTnlVertex
+
+#define LINTERP( T, A, B )             ((A) + (T) * ((B) - (A)))
+
+#define INTERP_RGBA(t, out, a, b)              \
+do {                                           \
+   GLint i;                                    \
+   for ( i = 0 ; i < 4 ; i++ ) {               \
+      GLfloat fa = a[i];                       \
+      GLfloat fb = b[i];                       \
+      out[i] = LINTERP( t, fa, fb );           \
+   }                                           \
+} while (0)
+
+/* Color functions: */
+
+static __inline void ffb_recalc_base_color(GLcontext *ctx)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       struct gl_light *light;
+
+       COPY_3V(fmesa->vtx_state.light.base_color, ctx->Light._BaseColor[0]);
+       foreach (light, &ctx->Light.EnabledList) {
+               ACC_3V(fmesa->vtx_state.light.base_color,
+                      light->_MatAmbient[0]);
+       }
+
+       fmesa->vtx_state.light.base_alpha = ctx->Light._BaseAlpha[0];
+}
+
+#define GET_CURRENT \
+       GET_CURRENT_CONTEXT(ctx);       \
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx)
+
+#define CURRENT_COLOR(COMP)            fmesa->vtx_state.current.color[COMP]
+#define CURRENT_SPECULAR(COMP)         fmesa->vtx_state.current.specular[COMP]
+#define COLOR_IS_FLOAT
+#define RECALC_BASE_COLOR(ctx)         ffb_recalc_base_color(ctx)
+
+#define TAG(x) ffb_##x
+#include "tnl_dd/t_dd_imm_capi.h"
+
+/* Normal functions: */
+
+struct ffb_norm_tab {
+       void (*normal3f_multi)(GLfloat x, GLfloat y, GLfloat z);
+       void (*normal3fv_multi)(const GLfloat *v);
+       void (*normal3f_single)(GLfloat x, GLfloat y, GLfloat z);
+       void (*normal3fv_single)(const GLfloat *v);
+};
+
+static struct ffb_norm_tab norm_tab[0x4];
+
+#define HAVE_HW_LIGHTING 0
+#define GET_CURRENT_VERTEX                     \
+       GET_CURRENT_CONTEXT(ctx);               \
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx); \
+       ffbTnlVertexPtr v = fmesa->imm.v0
+
+#define CURRENT_NORMAL         fmesa->vtx_state.current.normal
+#define BASE_COLOR             fmesa->vtx_state.light.base_color
+#define BASE_ALPHA             fmesa->vtx_state.light.base_alpha
+#define VERT_COLOR( COMP )     v->color[COMP]
+#define VERT_COLOR_IS_FLOAT
+
+#define IND (0)
+#define TAG(x) ffb_##x
+#define PRESERVE_NORMAL_DEFS
+#include "tnl_dd/t_dd_imm_napi.h"
+
+#define IND (NORM_RESCALE)
+#define TAG(x) ffb_##x##_rescale
+#define PRESERVE_NORMAL_DEFS
+#include "tnl_dd/t_dd_imm_napi.h"
+
+#define IND (NORM_NORMALIZE)
+#define TAG(x) ffb_##x##_normalize
+#include "tnl_dd/t_dd_imm_napi.h"
+
+static void ffb_init_norm_funcs(void)
+{
+       ffb_init_norm();
+       ffb_init_norm_rescale();
+       ffb_init_norm_normalize();
+}
+
+static void choose_normals(void)
+{
+       GET_CURRENT_CONTEXT(ctx);
+       GLuint index;
+
+       if (ctx->Light.Enabled) {
+               if (ctx->Transform.Normalize) {
+                       index = NORM_NORMALIZE;
+               } else if (!ctx->Transform.RescaleNormals &&
+                          ctx->_ModelViewInvScale != 1.0) {
+                       index = NORM_RESCALE;
+               } else {
+                       index = 0;
+               }
+
+               if (ctx->Light.EnabledList.next == ctx->Light.EnabledList.prev) {
+                       ctx->Exec->Normal3f  = norm_tab[index].normal3f_single;
+                       ctx->Exec->Normal3fv = norm_tab[index].normal3fv_single;
+               } else {
+                       ctx->Exec->Normal3f  = norm_tab[index].normal3f_multi;
+                       ctx->Exec->Normal3fv = norm_tab[index].normal3fv_multi;
+               }
+       } else {
+               ctx->Exec->Normal3f = _mesa_noop_Normal3f;
+               ctx->Exec->Normal3fv = _mesa_noop_Normal3fv;
+       }
+}
+
+static void ffb_choose_Normal3f(GLfloat x, GLfloat y, GLfloat z)
+{
+       choose_normals();
+       glNormal3f(x, y, z);
+}
+
+static void ffb_choose_Normal3fv(const GLfloat *v)
+{
+       choose_normals();
+       glNormal3fv(v);
+}
+
+/* Vertex functions: */
+
+#define GET_CURRENT_VERTEX                     \
+       GET_CURRENT_CONTEXT(ctx);               \
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx); \
+       ffbTnlVertexPtr v = fmesa->imm.v0
+
+#define CURRENT_VERTEX         v->obj
+#define SAVE_VERTEX            fmesa->imm.save_vertex(ctx, v)
+
+#define TAG(x) ffb_##x
+#include "tnl_dd/t_dd_imm_vapi.h"
+
+struct ffb_vert_tab {
+       void (*save_vertex)(GLcontext *ctx, ffbTnlVertexPtr v);
+       void (*interpolate_vertex)(GLfloat t,
+                                  ffbTnlVertex *O,
+                                  const ffbTnlVertex *I,
+                                  const ffbTnlVertex *J);
+};
+
+static struct ffb_vert_tab vert_tab[0xf];
+
+#define VTX_NORMAL     0x0
+#define VTX_RGBA       0x1
+
+#define LOCAL_VARS \
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx)
+
+#define CURRENT_COLOR                  fmesa->vtx_state.current.color
+#define COLOR_IS_FLOAT
+#define FLUSH_VERTEX                   fmesa->imm.flush_vertex( ctx, v );
+
+#define IND    (VTX_NORMAL)
+#define TAG(x) ffb_##x##_NORMAL
+#define PRESERVE_VERTEX_DEFS
+#include "tnl_dd/t_dd_imm_vertex.h"
+
+#define IND    (VTX_RGBA)
+#define TAG(x) ffb_##x##_RGBA
+#include "tnl_dd/t_dd_imm_vertex.h"
+
+static void ffb_init_vert_funcs( void )
+{
+       ffb_init_vert_NORMAL();
+       ffb_init_vert_RGBA();
+}
+
+#define LOCAL_VARS                                                     \
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx)
+
+#define GET_INTERP_FUNC                                                        \
+       ffb_interp_func interp = fmesa->imm.interp
+
+#define FLUSH_VERTEX                   fmesa->imm.flush_vertex
+#define IMM_VERTEX( V )                        fmesa->imm.V
+#define IMM_VERTICES( n )              fmesa->imm.vertices[n]
+
+#define EMIT_VERTEX_USES_HWREGS
+
+/* XXX Implement me XXX */
+#define EMIT_VERTEX_TRI(VTX0, VTX1, VTX2)      \
+       do { } while (0)
+#define EMIT_VERTEX_LINE(VTX0, VTX1)           \
+       do { } while (0)
+#define EMIT_VERTEX_POINT(VTX0)                        \
+       do { } while (0)
+
+#define TAG(x) ffb_##x
+#include "tnl_dd/t_dd_imm_primtmp.h"
+
+/* Bzzt: Material changes are lost on fallback. */
+static void ffb_Materialfv(GLenum face, GLenum pname,
+                          const GLfloat *params)
+{
+       GET_CURRENT_CONTEXT(ctx);
+
+       _mesa_noop_Materialfv( face, pname, params );
+       ffb_recalc_base_color( ctx );
+}
+
+/* Fallback functions: */
+
+static void ffb_do_fallback(GLcontext *ctx)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       struct ffb_current_state *current = &fmesa->vtx_state.current;
+
+       /* Tell tnl to restore its exec vtxfmt, rehook its driver callbacks
+        * and revive internal state that depended on those callbacks:
+        */
+       _tnl_wakeup_exec(ctx);
+
+       /* Replay enough vertices that the current primitive is continued
+        * correctly:
+        */
+       if (fmesa->imm.prim != PRIM_OUTSIDE_BEGIN_END )
+               glBegin(fmesa->imm.prim);
+
+       if (ctx->Light.Enabled) {
+               glColor4fv(ctx->Current.Color); /* Catch ColorMaterial */
+               glNormal3fv(current->normal);
+       } else {
+               glColor4fv(current->color);
+       }
+}
+
+#define PRE_LOOPBACK( FUNC ) do {      \
+   GET_CURRENT_CONTEXT(ctx);           \
+   ffb_do_fallback( ctx );             \
+} while (0)
+
+#define TAG(x) ffb_fallback_##x
+#include "vtxfmt_tmp.h"
+
+static void ffb_Begin(GLenum prim)
+{
+       GET_CURRENT_CONTEXT(ctx);
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+
+       if (prim > GL_POLYGON) {
+               _mesa_error( ctx, GL_INVALID_ENUM, "glBegin" );
+               return;
+       }
+
+       if (fmesa->imm.prim != PRIM_OUTSIDE_BEGIN_END) {
+               _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
+               return;
+       }
+
+       ctx->Driver.NeedFlush |= (FLUSH_STORED_VERTICES |
+                                 FLUSH_UPDATE_CURRENT);
+
+       fmesa->imm.prim = prim;
+       fmesa->imm.v0 = &fmesa->imm.vertices[0];
+       fmesa->imm.save_vertex = ffb_save_vertex_RGBA;
+       fmesa->imm.flush_vertex = ffb_flush_tab[prim];
+
+       /* XXX Lock hardware, update FBC, PPC, DRAWOP, etc. XXX */
+}
+
+static void ffb_End(void)
+{
+       GET_CURRENT_CONTEXT(ctx);
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+
+       if (fmesa->imm.prim == PRIM_OUTSIDE_BEGIN_END) {
+               _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
+               return;
+       }
+
+       fmesa->imm.prim = PRIM_OUTSIDE_BEGIN_END;
+
+       ctx->Driver.NeedFlush &= ~(FLUSH_STORED_VERTICES |
+                                  FLUSH_UPDATE_CURRENT);
+
+       /* XXX Unlock hardware, etc. */
+}
+
+void ffbInitTnlModule(GLcontext *ctx)
+{
+       ffbContextPtr fmesa = FFB_CONTEXT(ctx);
+       GLvertexformat *vfmt = &(fmesa->imm.vtxfmt);
+
+       /* Work in progress... */
+       return;
+
+       ffb_init_norm_funcs();
+       ffb_init_vert_funcs();
+
+       MEMSET(vfmt, 0, sizeof(GLvertexformat));
+
+       /* Handled fully in supported states: */
+       vfmt->ArrayElement              = NULL;         /* FIXME: ... */
+       vfmt->Color3f                   = ffb_choose_Color3f;
+       vfmt->Color3fv                  = ffb_choose_Color3fv;
+       vfmt->Color3ub                  = ffb_choose_Color3ub;
+       vfmt->Color3ubv                 = ffb_choose_Color3ubv;
+       vfmt->Color4f                   = ffb_choose_Color4f;
+       vfmt->Color4fv                  = ffb_choose_Color4fv;
+       vfmt->Color4ub                  = ffb_choose_Color4ub;
+       vfmt->Color4ubv                 = ffb_choose_Color4ubv;
+       vfmt->FogCoordfvEXT             = ffb_FogCoordfvEXT;
+       vfmt->FogCoordfEXT              = ffb_FogCoordfEXT;
+       vfmt->Materialfv                = ffb_Materialfv;
+       vfmt->MultiTexCoord1fARB        = ffb_fallback_MultiTexCoord1fARB;
+       vfmt->MultiTexCoord1fvARB       = ffb_fallback_MultiTexCoord1fvARB;
+       vfmt->MultiTexCoord2fARB        = ffb_fallback_MultiTexCoord2fARB;
+       vfmt->MultiTexCoord2fvARB       = ffb_fallback_MultiTexCoord2fvARB;
+       vfmt->MultiTexCoord3fARB        = ffb_fallback_MultiTexCoord3fARB;
+       vfmt->MultiTexCoord3fvARB       = ffb_fallback_MultiTexCoord3fvARB;
+       vfmt->MultiTexCoord4fARB        = ffb_fallback_MultiTexCoord4fARB;
+       vfmt->MultiTexCoord4fvARB       = ffb_fallback_MultiTexCoord4fvARB;
+       vfmt->Normal3f                  = ffb_choose_Normal3f;
+       vfmt->Normal3fv                 = ffb_choose_Normal3fv;
+       vfmt->SecondaryColor3ubEXT      = ffb_SecondaryColor3ubEXT;
+       vfmt->SecondaryColor3ubvEXT     = ffb_SecondaryColor3ubvEXT;
+       vfmt->SecondaryColor3fEXT       = ffb_SecondaryColor3fEXT;
+       vfmt->SecondaryColor3fvEXT      = ffb_SecondaryColor3fvEXT;
+       vfmt->TexCoord1f                = ffb_fallback_TexCoord1f;
+       vfmt->TexCoord1fv               = ffb_fallback_TexCoord1fv;
+       vfmt->TexCoord2f                = ffb_fallback_TexCoord2f;
+       vfmt->TexCoord2fv               = ffb_fallback_TexCoord2fv;
+       vfmt->TexCoord3f                = ffb_fallback_TexCoord3f;
+       vfmt->TexCoord3fv               = ffb_fallback_TexCoord3fv;
+       vfmt->TexCoord4f                = ffb_fallback_TexCoord4f;
+       vfmt->TexCoord4fv               = ffb_fallback_TexCoord4fv;
+
+       vfmt->Vertex2f                  = ffb_Vertex2f;
+       vfmt->Vertex2fv                 = ffb_Vertex2fv;
+       vfmt->Vertex3f                  = ffb_Vertex3f;
+       vfmt->Vertex3fv                 = ffb_Vertex3fv;
+       vfmt->Vertex4f                  = ffb_Vertex4f;
+       vfmt->Vertex4fv                 = ffb_Vertex4fv;
+
+       vfmt->Begin                     = ffb_Begin;
+       vfmt->End                       = ffb_End;
+
+       vfmt->Rectf = _mesa_noop_Rectf;                 /* generic helper */
+
+       vfmt->DrawArrays = NULL;
+       vfmt->DrawElements = NULL;
+       vfmt->DrawRangeElements = _mesa_noop_DrawRangeElements; /* discard range */
+
+
+       /* Not active in supported states; just keep ctx->Current uptodate: */
+       vfmt->EdgeFlag = _mesa_noop_EdgeFlag;
+       vfmt->EdgeFlagv = _mesa_noop_EdgeFlagv;
+       vfmt->Indexi = _mesa_noop_Indexi;
+       vfmt->Indexiv = _mesa_noop_Indexiv;
+
+       /* Active but unsupported -- fallback if we receive these:
+        *
+        * All of these fallbacks can be fixed with additional code, except
+        * CallList, unless we build a play_immediate_noop() command which
+        * turns an immediate back into glBegin/glEnd commands...
+        */
+       vfmt->CallList = ffb_fallback_CallList;
+       vfmt->EvalCoord1f = ffb_fallback_EvalCoord1f;
+       vfmt->EvalCoord1fv = ffb_fallback_EvalCoord1fv;
+       vfmt->EvalCoord2f = ffb_fallback_EvalCoord2f;
+       vfmt->EvalCoord2fv = ffb_fallback_EvalCoord2fv;
+       vfmt->EvalMesh1 = ffb_fallback_EvalMesh1;
+       vfmt->EvalMesh2 = ffb_fallback_EvalMesh2;
+       vfmt->EvalPoint1 = ffb_fallback_EvalPoint1;
+       vfmt->EvalPoint2 = ffb_fallback_EvalPoint2;
+
+       vfmt->prefer_float_colors = GL_TRUE;
+
+       fmesa->imm.prim = PRIM_OUTSIDE_BEGIN_END;
+
+       /* THIS IS A HACK! */
+       _mesa_install_exec_vtxfmt( ctx, vfmt );
+}
diff --git a/src/mesa/drivers/dri/ffb/ffb_vtxfmt.h b/src/mesa/drivers/dri/ffb/ffb_vtxfmt.h
new file mode 100644 (file)
index 0000000..063bb49
--- /dev/null
@@ -0,0 +1,8 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_vtxfmt.h,v 1.1 2002/02/22 21:32:59 dawes Exp $ */
+
+#ifndef _FFB_VTXFMT_H
+#define _FFB_VTXFMT_H
+
+extern void ffbInitTnlModule(GLcontext *);
+
+#endif /* !(_FFB_VTXFMT_H) */
diff --git a/src/mesa/drivers/dri/ffb/ffb_xmesa.c b/src/mesa/drivers/dri/ffb/ffb_xmesa.c
new file mode 100644 (file)
index 0000000..caca9d4
--- /dev/null
@@ -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 <davem@redhat.com>
+ */
+
+#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 */
diff --git a/src/mesa/drivers/dri/ffb/ffb_xmesa.h b/src/mesa/drivers/dri/ffb/ffb_xmesa.h
new file mode 100644 (file)
index 0000000..5569bd8
--- /dev/null
@@ -0,0 +1,30 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/ffb/ffb_xmesa.h,v 1.2 2002/02/22 21:32:59 dawes Exp $ */
+
+#ifndef _FFB_XMESA_H_
+#define _FFB_XMESA_H_
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include <sys/time.h>
+#include "dri_util.h"
+#include "mtypes.h"
+#include "ffb_drishare.h"
+#include "ffb_regs.h"
+#include "ffb_dac.h"
+#include "ffb_fifo.h"
+
+typedef struct {
+       __DRIscreenPrivate              *sPriv;
+       ffb_fbcPtr                      regs;
+       ffb_dacPtr                      dac;
+       volatile char                   *sfb8r;
+       volatile char                   *sfb32;
+       volatile char                   *sfb64;
+
+       int                             fifo_cache;
+       int                             rp_active;
+} ffbScreenPrivate;
+
+#endif /* GLX_DIRECT_RENDERING */
+
+#endif /* !(_FFB_XMESA_H) */