patch to import Jon Smirl's work from Bitkeeper
authorBrian Paul <brian.paul@tungstengraphics.com>
Fri, 22 Aug 2003 20:11:43 +0000 (20:11 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Fri, 22 Aug 2003 20:11:43 +0000 (20:11 +0000)
171 files changed:
Make-config
Makefile.X11
src/glu/mini/Makefile.X11 [new file with mode: 0644]
src/glu/mini/all.h [new file with mode: 0644]
src/glu/mini/glu.c [new file with mode: 0644]
src/glu/mini/gluP.h [new file with mode: 0644]
src/glu/mini/mipmap.c [new file with mode: 0644]
src/glu/mini/nurbs.c [new file with mode: 0644]
src/glu/mini/nurbs.h [new file with mode: 0644]
src/glu/mini/nurbscrv.c [new file with mode: 0644]
src/glu/mini/polytest.c [new file with mode: 0644]
src/glu/mini/project.c [new file with mode: 0644]
src/glu/mini/quadric.c [new file with mode: 0644]
src/glu/mini/tess.c [new file with mode: 0644]
src/glu/mini/tess.h [new file with mode: 0644]
src/glu/mini/tesselat.c [new file with mode: 0644]
src/glut/mini/Makefile.X11 [new file with mode: 0644]
src/glut/mini/bitmap.c [new file with mode: 0644]
src/glut/mini/callback.c [new file with mode: 0644]
src/glut/mini/color.c [new file with mode: 0644]
src/glut/mini/globals.c [new file with mode: 0644]
src/glut/mini/init.c [new file with mode: 0644]
src/glut/mini/internal.h [new file with mode: 0644]
src/glut/mini/menu.c [new file with mode: 0644]
src/glut/mini/models.c [new file with mode: 0644]
src/glut/mini/overlay.c [new file with mode: 0644]
src/glut/mini/state.c [new file with mode: 0644]
src/glut/mini/teapot.c [new file with mode: 0644]
src/glut/mini/window.c [new file with mode: 0644]
src/glx/mini/Makefile.X11 [new file with mode: 0644]
src/glx/mini/NOTES [new file with mode: 0644]
src/glx/mini/dispatch.c [new file with mode: 0644]
src/glx/mini/dri.h [new file with mode: 0644]
src/glx/mini/dri_util.c [new file with mode: 0644]
src/glx/mini/dri_util.h [new file with mode: 0644]
src/glx/mini/driver.h [new file with mode: 0644]
src/glx/mini/drm.h [new file with mode: 0644]
src/glx/mini/drmtest.c [new file with mode: 0644]
src/glx/mini/example.miniglx.conf [new file with mode: 0644]
src/glx/mini/miniglx.c [new file with mode: 0644]
src/glx/mini/miniglxP.h [new file with mode: 0644]
src/glx/mini/miniglx_events.c [new file with mode: 0644]
src/glx/mini/sarea.h [new file with mode: 0644]
src/glx/mini/xf86drm.c [new file with mode: 0644]
src/glx/mini/xf86drm.h [new file with mode: 0644]
src/mesa/Makefile.X11
src/mesa/drivers/dri/mga/Doxyfile [new file with mode: 0644]
src/mesa/drivers/dri/mga/Makefile.X11
src/mesa/drivers/dri/mga/mga_texstate.c [new file with mode: 0644]
src/mesa/drivers/dri/mga/mga_xmesa.c
src/mesa/drivers/dri/mga/mga_xmesa.h
src/mesa/drivers/dri/mga/mgacontext.h
src/mesa/drivers/dri/mga/mgadd.c
src/mesa/drivers/dri/mga/mgadd.h
src/mesa/drivers/dri/mga/mgaioctl.c
src/mesa/drivers/dri/mga/mgaioctl.h
src/mesa/drivers/dri/mga/mgapixel.c
src/mesa/drivers/dri/mga/mgaregs.h
src/mesa/drivers/dri/mga/mgarender.c
src/mesa/drivers/dri/mga/mgaspan.c
src/mesa/drivers/dri/mga/mgastate.c
src/mesa/drivers/dri/mga/mgastate.h
src/mesa/drivers/dri/mga/mgatex.c
src/mesa/drivers/dri/mga/mgatex.h
src/mesa/drivers/dri/mga/mgatexmem.c
src/mesa/drivers/dri/mga/mgatris.c
src/mesa/drivers/dri/mga/mgatris.h
src/mesa/drivers/dri/mga/mgavb.c
src/mesa/drivers/dri/mga/server/mga_common.h
src/mesa/drivers/dri/r128/Makefile.X11 [new file with mode: 0644]
src/mesa/drivers/dri/r128/r128_context.c [new file with mode: 0644]
src/mesa/drivers/dri/r128/r128_context.h [new file with mode: 0644]
src/mesa/drivers/dri/r128/r128_dd.c [new file with mode: 0644]
src/mesa/drivers/dri/r128/r128_dd.h [new file with mode: 0644]
src/mesa/drivers/dri/r128/r128_ioctl.c [new file with mode: 0644]
src/mesa/drivers/dri/r128/r128_ioctl.h [new file with mode: 0644]
src/mesa/drivers/dri/r128/r128_lock.c [new file with mode: 0644]
src/mesa/drivers/dri/r128/r128_lock.h [new file with mode: 0644]
src/mesa/drivers/dri/r128/r128_screen.c [new file with mode: 0644]
src/mesa/drivers/dri/r128/r128_screen.h [new file with mode: 0644]
src/mesa/drivers/dri/r128/r128_span.c [new file with mode: 0644]
src/mesa/drivers/dri/r128/r128_span.h [new file with mode: 0644]
src/mesa/drivers/dri/r128/r128_state.c [new file with mode: 0644]
src/mesa/drivers/dri/r128/r128_state.h [new file with mode: 0644]
src/mesa/drivers/dri/r128/r128_tex.c [new file with mode: 0644]
src/mesa/drivers/dri/r128/r128_tex.h [new file with mode: 0644]
src/mesa/drivers/dri/r128/r128_texmem.c [new file with mode: 0644]
src/mesa/drivers/dri/r128/r128_texobj.h [new file with mode: 0644]
src/mesa/drivers/dri/r128/r128_texstate.c [new file with mode: 0644]
src/mesa/drivers/dri/r128/r128_tris.c [new file with mode: 0644]
src/mesa/drivers/dri/r128/r128_tris.h [new file with mode: 0644]
src/mesa/drivers/dri/r128/r128_vb.c [new file with mode: 0644]
src/mesa/drivers/dri/r128/r128_vb.h [new file with mode: 0644]
src/mesa/drivers/dri/r128/server/r128.h [new file with mode: 0644]
src/mesa/drivers/dri/r128/server/r128_common.h [new file with mode: 0644]
src/mesa/drivers/dri/r128/server/r128_dri.c [new file with mode: 0644]
src/mesa/drivers/dri/r128/server/r128_dri.h [new file with mode: 0644]
src/mesa/drivers/dri/r128/server/r128_macros.h [new file with mode: 0644]
src/mesa/drivers/dri/r128/server/r128_reg.h [new file with mode: 0644]
src/mesa/drivers/dri/r128/server/r128_sarea.h [new file with mode: 0644]
src/mesa/drivers/dri/r128/server/r128_version.h [new file with mode: 0644]
src/mesa/drivers/dri/r200/Makefile.X11
src/mesa/drivers/dri/r200/r200_context.c
src/mesa/drivers/dri/r200/r200_context.h
src/mesa/drivers/dri/r200/r200_ioctl.c
src/mesa/drivers/dri/r200/r200_swtcl.c
src/mesa/drivers/dri/r200/r200_tcl.c
src/mesa/drivers/dri/radeon/Makefile.X11 [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_compat.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_context.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_context.h [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_ioctl.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_ioctl.h [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_lighting.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_lock.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_lock.h [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_maos.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_maos.h [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_maos_arrays.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_maos_vbtmp.h [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_maos_verts.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_sanity.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_sanity.h [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_screen.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_screen.h [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_span.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_span.h [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_state.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_state.h [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_state_init.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_subset.h [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_subset_bitmap.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_subset_readpix.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_subset_select.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_subset_tex.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_subset_vtx.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_swtcl.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_swtcl.h [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_tcl.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_tcl.h [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_tex.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_tex.h [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_texmem.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_texstate.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_vtxfmt.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_vtxfmt.h [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_vtxfmt_c.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_vtxfmt_sse.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/radeon_vtxfmt_x86.c [new file with mode: 0644]
src/mesa/drivers/dri/radeon/server/radeon_common.h
src/mesa/drivers/dri/radeon/server/radeon_dri.c
src/mesa/drivers/dri/radeon/server/radeon_reg.h
src/mesa/drivers/dri/radeon/server/radeon_sarea.h
src/mesa/tnl_dd/imm/NOTES.imm [new file with mode: 0644]
src/mesa/tnl_dd/imm/t_dd_imm_capi.h [new file with mode: 0644]
src/mesa/tnl_dd/imm/t_dd_imm_napi.h [new file with mode: 0644]
src/mesa/tnl_dd/imm/t_dd_imm_primtmp.h [new file with mode: 0644]
src/mesa/tnl_dd/imm/t_dd_imm_tapi.h [new file with mode: 0644]
src/mesa/tnl_dd/imm/t_dd_imm_vapi.h [new file with mode: 0644]
src/mesa/tnl_dd/imm/t_dd_imm_vb.c [new file with mode: 0644]
src/mesa/tnl_dd/imm/t_dd_imm_vbtmp.h [new file with mode: 0644]
src/mesa/tnl_dd/t_dd.c [new file with mode: 0644]
src/mesa/tnl_dd/t_dd_dmatmp.h [new file with mode: 0644]
src/mesa/tnl_dd/t_dd_dmatmp2.h [new file with mode: 0644]
src/mesa/tnl_dd/t_dd_rendertmp.h [new file with mode: 0644]
src/mesa/tnl_dd/t_dd_triemit.h [new file with mode: 0644]
src/mesa/tnl_dd/t_dd_tritmp.h [new file with mode: 0644]
src/mesa/tnl_dd/t_dd_unfilled.h [new file with mode: 0644]
src/mesa/tnl_dd/t_dd_vb.c [new file with mode: 0644]
src/mesa/tnl_dd/t_dd_vbtmp.h [new file with mode: 0644]
src/mesa/tnl_dd/t_dd_vertex.h [new file with mode: 0644]

index fffe356defa306b689ae16e0c46727e1777db0d3..4b9d7fb1c9d5936693b7eb0679e43e4f2c72a9e7 100644 (file)
@@ -664,6 +664,22 @@ linux-osmesa32:
        "GL_LIB_DEPS = -lm -lpthread" \
        "APP_LIB_DEPS = -lOSMesa32 -lGL"
 
+# standalone Mesa -- embedded
+# change -g to -O3 for non-debug
+linux-solo:
+       $(MAKE) $(MFLAGS) -f Makefile.X11 targets \
+       "LIBMESA = mesa.a" \
+       "GLU_LIB = libGLU.so" \
+       "GLUT_LIB = libglut.so" \
+       "CC = gcc" \
+       "CXX = g++" \
+       "CFLAGS = -g -std=c99 -pedantic -fPIC -ffast-math -D_POSIX_SOURCE -D_POSIX_C_SOURCE=199309L -D_SVID_SOURCE -D_BSD_SOURCE" \
+       "CXXFLAGS = $(CFLAGS)" \
+       "GL_LIB_DEPS = -lm -lpthread" \
+       "GLU_LIB_DEPS = -L$(TOP)/lib -lGL -lm  -Wl,-rpath,$(TOP)/lib" \
+       "GLUT_LIB_DEPS = -L$(TOP)/lib -lGLU -lGL -lm  -Wl,-rpath,$(TOP)/lib" \
+       "APP_LIB_DEPS = -L$(TOP)/lib -lglut -lGLU -lGL -lm  -lpthread -Wl,-rpath,$(TOP)/lib" 
+
 # May want to add these CFLAGS for better performance under LynxOS and GCC:
 # -fPIC -O2 -ansi -pedantic -mieee-fp -DUSE_XSHM -funroll-loops
 # -fexpensive-optimizations -fomit-frame-pointer -ffast-math
index 95ea5271e17d0c7b2c0c711cb8a360110754f2f2..48b929bcdb71b98147e37c65a63f4c35330567a4 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: Makefile.X11,v 1.79 2003/08/22 18:06:59 brianp Exp $
+# $Id: Makefile.X11,v 1.80 2003/08/22 20:11:43 brianp Exp $
 
 # Mesa 3-D graphics library
 # Version:  5.1
@@ -73,6 +73,7 @@ default:
        @echo "  make linux-sparc-ultra    for Linux with UltraSparc optimizations"
        @echo "  make linux-osmesa16       for 16-bit/channel OSMesa"
        @echo "  make linux-osmesa32       for 32-bit/channel OSMesa"
+       @echo "  make linux-solo           for Linux standalone with dri drivers"
        @echo "  make linux-icc            for Linux with the Intel C/C++ compiler"
        @echo "  make lynxos               for LynxOS systems with GCC"
        @echo "  make mklinux              for Linux on Power Macintosh"
@@ -227,21 +228,47 @@ linux-osmesa16 linux-osmesa32:
        if [ -d src ] ; then touch src/depend ; fi
        if [ -d src ] ; then cd src ; $(MAKE) -f Makefile.OSMesa16 $@ ; fi
        
+linux-solo:
+       -mkdir lib
+       if [ -d src/mesa     ] ; then touch src/mesa/depend     ; fi
+       if [ -d src/glx/mini ] ; then touch src/glx/mini/depend  ; fi
+       if [ -d src/glu/mini ] ; then touch src/glu/mini/depend  ; fi
+       if [ -d src/glut/mini ] ; then touch src/glut/mini/depend  ; fi
+       if [ -d src/mesa      ] ; then cd src/mesa      ; $(MAKE) -f Makefile.X11 $@ ; fi
+       if [ -d src/mesa/drivers/dri/r200 ] ; then cd src/mesa/drivers/dri/r200     ; $(MAKE) -f Makefile.X11 $@ ; fi
+       if [ -d src/mesa/drivers/dri/r128 ] ; then cd src/mesa/drivers/dri/r128     ; $(MAKE) -f Makefile.X11 $@ ; fi
+       if [ -d src/mesa/drivers/dri/radeon ] ; then cd src/mesa/drivers/dri/radeon ; $(MAKE) -f Makefile.X11 $@ ; fi
+       if [ -d src/mesa/drivers/dri/mga ] ; then cd src/mesa/drivers/dri/mga       ; $(MAKE) -f Makefile.X11 $@ ; fi
+       if [ -d src/mesa/drivers/dri/fb ] ; then cd src/mesa/drivers/dri/fb         ; $(MAKE) -f Makefile.X11 $@ ; fi
+       if [ -d src/glx/mini  ] ; then cd src/glx/mini  ; $(MAKE) -f Makefile.X11 $@ ; fi
+       if [ -d src/glu/mini  ] ; then cd src/glu/mini  ; $(MAKE) -f Makefile.X11 $@ ; fi
+       if [ -d src/glut/mini ] ; then cd src/glut/mini  ; $(MAKE) -f Makefile.X11 $@ ; fi
+       if [ -d progs/demos   ] ; then cd progs/miniglx ; $(MAKE) -f Makefile.X11 $@ ; fi
+       if [ -d progs/demos   ] ; then cd progs/tests   ; $(MAKE) -f Makefile.X11 $@ ; fi
+       if [ -d progs/demos   ] ; then cd progs/demos   ; $(MAKE) -f Makefile.X11 $@ ; fi
+       if [ -d progs/xdemos  ] ; then cd progs/xdemos  ; $(MAKE) -f Makefile.X11 $@ ; fi
+       if [ -d progs/samples ] ; then cd progs/samples ; $(MAKE) -f Makefile.X11 $@ ; fi
+       if [ -d progs/redbook ] ; then cd progs/redbook ; $(MAKE) -f Makefile.X11 $@ ; fi
 
 # Remove .o files, emacs backup files, etc.
 clean:
        -rm -f src/mesa/*/*.o
        -rm -f src/mesa/drivers/*/*.o
-       -rm -f src/mesa/drivers/*/*.o
+       -rm -f src/mesa/drivers/*/*/*.o
+       -rm -f src/mesa/drivers/*/*/*/*.o
        -rm -f include/*~
        -rm -f include/GL/*~
        -rm -f src/glu/mesa/*.o src/glu/mesa/*~ src-glu/*.a
        -rm -f src/glu/sgi/*/*.o src/glu/sgi/*/*/*.o
        -rm -f src/glut/glx/*.o
+       -rm -f src/miniglx/*.o
+       -rm -f src/miniglu/*.o
+       -rm -f src/miniglut/*.o
        -rm -f progs/demos/*.o
        -rm -f progs/redbook/*.o progs/redbook/*~
        -rm -f progs/xdemos/*.o progs/xdemos/*~
        -rm -f progs/samples/*.o progs/samples/*~
+       -rm -f progs/tests/*.o progs/tests/*~
        -rm -f src/glw/*.o
 
 # Remove everything that can be remade
diff --git a/src/glu/mini/Makefile.X11 b/src/glu/mini/Makefile.X11
new file mode 100644 (file)
index 0000000..d0ef2e5
--- /dev/null
@@ -0,0 +1,65 @@
+
+
+TOP = ../../..
+
+default: linux-solo
+
+LIBDIR = $(TOP)/lib
+
+INCLUDES = -I$(TOP)/include 
+CFLAGS = -c -g $(INCLUDES) -MD 
+
+SOURCES = glu.c \
+       mipmap.c \
+       nurbs.c \
+       polytest.c \
+       project.c \
+       quadric.c \
+       tess.c \
+       tesselat.c
+
+
+OBJS =  $(SOURCES:.c=.o)
+
+LIBS=-L$(TOP)/lib -lGL -lm
+
+##### RULES #####
+
+.c.o:
+       $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
+
+.S.o:
+       $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES)  $< -o $@
+
+
+##### TARGETS #####
+
+targets: depend libGLU.so.1.1 install 
+
+libGLU.so.1.1: $(OBJS) Makefile.X11
+       gcc -shared -Wl,-soname,libGLU.so -Wl,-Bsymbolic $(OBJS) $(LIBS) -o $@ 
+
+install:
+       rm -f $(TOP)/lib/libGLU.so*
+       install -D libGLU.so.1.1 $(TOP)/lib/libGLU.so.1.1
+       ln -s libGLU.so.1.1 $(TOP)/lib/libGLU.so.1
+       ln -s libGLU.so.1 $(TOP)/lib/libGLU.so
+
+# Run 'make -f Makefile.X11 dep' to update the dependencies if you change
+# what's included by any source file.
+depend: $(SOURCES) 
+       makedepend -fdepend -Y $(INCLUDES) \
+               $(SOURCES)
+
+# Emacs tags
+tags:
+       etags `find . -name \*.[ch]` `find ../include`
+
+
+# Remove .o and backup files
+clean:
+       -rm -f *.o *~ *.o *~ *.so
+
+include $(TOP)/Make-config
+
+include depend
diff --git a/src/glu/mini/all.h b/src/glu/mini/all.h
new file mode 100644 (file)
index 0000000..d626bee
--- /dev/null
@@ -0,0 +1,55 @@
+/* $Id: all.h,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.3
+ * Copyright (C) 1995-2000  Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+/*
+ * This file includes all .h files needed for the GLU source code for
+ * the purpose of precompiled headers.
+ *
+ * If the preprocessor symbol PCH is defined at compile time then each
+ * of the .c files will #include "all.h" only, instead of a bunch of
+ * individual .h files.
+ */
+
+
+#ifndef GLU_ALL_H
+#define GLU_ALL_H
+
+
+#ifndef PC_HEADER
+This is an error.  all.h should be included only if PCH is defined.
+#endif
+
+
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "GL/gl.h"
+#include "GL/glu.h"
+#include "gluP.h"
+#include "nurbs.h"
+#include "tess.h"
+
+
+#endif /*GLU_ALL_H */
diff --git a/src/glu/mini/glu.c b/src/glu/mini/glu.c
new file mode 100644 (file)
index 0000000..5c7722c
--- /dev/null
@@ -0,0 +1,417 @@
+/* $Id: glu.c,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.5
+ * Copyright (C) 1995-2001  Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "gluP.h"
+#endif
+
+
+/*
+ * Miscellaneous utility functions
+ */
+
+
+#ifndef M_PI
+#define M_PI 3.1415926536
+#endif
+#define EPS 0.00001
+
+#ifndef GLU_INCOMPATIBLE_GL_VERSION
+#define GLU_INCOMPATIBLE_GL_VERSION     100903
+#endif
+
+
+void GLAPIENTRY
+gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez,
+         GLdouble centerx, GLdouble centery, GLdouble centerz,
+         GLdouble upx, GLdouble upy, GLdouble upz)
+{
+   GLfloat m[16];
+   GLfloat x[3], y[3], z[3];
+   GLfloat mag;
+
+   /* Make rotation matrix */
+
+   /* Z vector */
+   z[0] = eyex - centerx;
+   z[1] = eyey - centery;
+   z[2] = eyez - centerz;
+   mag = sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
+   if (mag) {                  /* mpichler, 19950515 */
+      z[0] /= mag;
+      z[1] /= mag;
+      z[2] /= mag;
+   }
+
+   /* Y vector */
+   y[0] = upx;
+   y[1] = upy;
+   y[2] = upz;
+
+   /* X vector = Y cross Z */
+   x[0] = y[1] * z[2] - y[2] * z[1];
+   x[1] = -y[0] * z[2] + y[2] * z[0];
+   x[2] = y[0] * z[1] - y[1] * z[0];
+
+   /* Recompute Y = Z cross X */
+   y[0] = z[1] * x[2] - z[2] * x[1];
+   y[1] = -z[0] * x[2] + z[2] * x[0];
+   y[2] = z[0] * x[1] - z[1] * x[0];
+
+   /* mpichler, 19950515 */
+   /* cross product gives area of parallelogram, which is < 1.0 for
+    * non-perpendicular unit-length vectors; so normalize x, y here
+    */
+
+   mag = sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
+   if (mag) {
+      x[0] /= mag;
+      x[1] /= mag;
+      x[2] /= mag;
+   }
+
+   mag = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
+   if (mag) {
+      y[0] /= mag;
+      y[1] /= mag;
+      y[2] /= mag;
+   }
+
+#define M(row,col)  m[col*4+row]
+   M(0, 0) = x[0];
+   M(0, 1) = x[1];
+   M(0, 2) = x[2];
+   M(0, 3) = 0.0;
+   M(1, 0) = y[0];
+   M(1, 1) = y[1];
+   M(1, 2) = y[2];
+   M(1, 3) = 0.0;
+   M(2, 0) = z[0];
+   M(2, 1) = z[1];
+   M(2, 2) = z[2];
+   M(2, 3) = 0.0;
+   M(3, 0) = 0.0;
+   M(3, 1) = 0.0;
+   M(3, 2) = 0.0;
+   M(3, 3) = 1.0;
+#undef M
+   glMultMatrixf(m);
+
+   /* Translate Eye to Origin */
+   glTranslatef(-eyex, -eyey, -eyez);
+
+}
+
+
+
+void GLAPIENTRY
+gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top)
+{
+   glOrtho(left, right, bottom, top, -1.0, 1.0);
+}
+
+
+
+static void
+frustum(GLfloat left, GLfloat right,
+        GLfloat bottom, GLfloat top, 
+        GLfloat nearval, GLfloat farval)
+{
+   GLfloat x, y, a, b, c, d;
+   GLfloat m[16];
+
+   x = (2.0 * nearval) / (right - left);
+   y = (2.0 * nearval) / (top - bottom);
+   a = (right + left) / (right - left);
+   b = (top + bottom) / (top - bottom);
+   c = -(farval + nearval) / ( farval - nearval);
+   d = -(2.0 * farval * nearval) / (farval - nearval);
+
+#define M(row,col)  m[col*4+row]
+   M(0,0) = x;     M(0,1) = 0.0F;  M(0,2) = a;      M(0,3) = 0.0F;
+   M(1,0) = 0.0F;  M(1,1) = y;     M(1,2) = b;      M(1,3) = 0.0F;
+   M(2,0) = 0.0F;  M(2,1) = 0.0F;  M(2,2) = c;      M(2,3) = d;
+   M(3,0) = 0.0F;  M(3,1) = 0.0F;  M(3,2) = -1.0F;  M(3,3) = 0.0F;
+#undef M
+
+   glMultMatrixf(m);
+}
+
+
+void GLAPIENTRY
+gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
+{
+   GLfloat xmin, xmax, ymin, ymax;
+
+   ymax = zNear * tan(fovy * M_PI / 360.0);
+   ymin = -ymax;
+   xmin = ymin * aspect;
+   xmax = ymax * aspect;
+
+   /* don't call glFrustum() because of error semantics (covglu) */
+   frustum(xmin, xmax, ymin, ymax, zNear, zFar);
+}
+
+
+
+void GLAPIENTRY
+gluPickMatrix(GLdouble x, GLdouble y,
+             GLdouble width, GLdouble height, GLint viewport[4])
+{
+   GLfloat m[16];
+   GLfloat sx, sy;
+   GLfloat tx, ty;
+
+   sx = viewport[2] / width;
+   sy = viewport[3] / height;
+   tx = (viewport[2] + 2.0 * (viewport[0] - x)) / width;
+   ty = (viewport[3] + 2.0 * (viewport[1] - y)) / height;
+
+#define M(row,col)  m[col*4+row]
+   M(0, 0) = sx;
+   M(0, 1) = 0.0;
+   M(0, 2) = 0.0;
+   M(0, 3) = tx;
+   M(1, 0) = 0.0;
+   M(1, 1) = sy;
+   M(1, 2) = 0.0;
+   M(1, 3) = ty;
+   M(2, 0) = 0.0;
+   M(2, 1) = 0.0;
+   M(2, 2) = 1.0;
+   M(2, 3) = 0.0;
+   M(3, 0) = 0.0;
+   M(3, 1) = 0.0;
+   M(3, 2) = 0.0;
+   M(3, 3) = 1.0;
+#undef M
+
+   glMultMatrixf(m);
+}
+
+
+
+const GLubyte *GLAPIENTRY
+gluErrorString(GLenum errorCode)
+{
+   static char *tess_error[] = {
+      "missing gluBeginPolygon",
+      "missing gluBeginContour",
+      "missing gluEndPolygon",
+      "missing gluEndContour",
+      "misoriented or self-intersecting loops",
+      "coincident vertices",
+      "colinear vertices",
+      "FIST recovery process fatal error"
+   };
+   static char *nurbs_error[] = {
+      "spline order un-supported",
+      "too few knots",
+      "valid knot range is empty",
+      "decreasing knot sequence knot",
+      "knot multiplicity greater than order of spline",
+      "endcurve() must follow bgncurve()",
+      "bgncurve() must precede endcurve()",
+      "missing or extra geometric data",
+      "can't draw pwlcurves",
+      "missing bgncurve()",
+      "missing bgnsurface()",
+      "endtrim() must precede endsurface()",
+      "bgnsurface() must precede endsurface()",
+      "curve of improper type passed as trim curve",
+      "bgnsurface() must precede bgntrim()",
+      "endtrim() must follow bgntrim()",
+      "bgntrim() must precede endtrim()",
+      "invalid or missing trim curve",
+      "bgntrim() must precede pwlcurve()",
+      "pwlcurve referenced twice",
+      "pwlcurve and nurbscurve mixed",
+      "improper usage of trim data type",
+      "nurbscurve referenced twice",
+      "nurbscurve and pwlcurve mixed",
+      "nurbssurface referenced twice",
+      "invalid property",
+      "endsurface() must follow bgnsurface()",
+      "misoriented trim curves",
+      "intersecting trim curves",
+      "UNUSED",
+      "unconnected trim curves",
+      "unknown knot error",
+      "negative vertex count encountered",
+      "negative byte-stride encountered",
+      "unknown type descriptor",
+      "null control array or knot vector",
+      "duplicate point on pwlcurve"
+   };
+
+   /* GL Errors */
+   if (errorCode == GL_NO_ERROR) {
+      return (GLubyte *) "no error";
+   }
+   else if (errorCode == GL_INVALID_VALUE) {
+      return (GLubyte *) "invalid value";
+   }
+   else if (errorCode == GL_INVALID_ENUM) {
+      return (GLubyte *) "invalid enum";
+   }
+   else if (errorCode == GL_INVALID_OPERATION) {
+      return (GLubyte *) "invalid operation";
+   }
+   else if (errorCode == GL_STACK_OVERFLOW) {
+      return (GLubyte *) "stack overflow";
+   }
+   else if (errorCode == GL_STACK_UNDERFLOW) {
+      return (GLubyte *) "stack underflow";
+   }
+   else if (errorCode == GL_OUT_OF_MEMORY) {
+      return (GLubyte *) "out of memory";
+   }
+   /* GLU Errors */
+   else if (errorCode == GLU_NO_ERROR) {
+      return (GLubyte *) "no error";
+   }
+   else if (errorCode == GLU_INVALID_ENUM) {
+      return (GLubyte *) "invalid enum";
+   }
+   else if (errorCode == GLU_INVALID_VALUE) {
+      return (GLubyte *) "invalid value";
+   }
+   else if (errorCode == GLU_OUT_OF_MEMORY) {
+      return (GLubyte *) "out of memory";
+   }
+   else if (errorCode == GLU_INCOMPATIBLE_GL_VERSION) {
+      return (GLubyte *) "incompatible GL version";
+   }
+   else if (errorCode >= GLU_TESS_ERROR1 && errorCode <= GLU_TESS_ERROR8) {
+      return (GLubyte *) tess_error[errorCode - GLU_TESS_ERROR1];
+   }
+   else if (errorCode >= GLU_NURBS_ERROR1 && errorCode <= GLU_NURBS_ERROR37) {
+      return (GLubyte *) nurbs_error[errorCode - GLU_NURBS_ERROR1];
+   }
+   else {
+      return NULL;
+   }
+}
+
+
+
+/*
+ * New in GLU 1.1
+ */
+
+const GLubyte *GLAPIENTRY
+gluGetString(GLenum name)
+{
+   static char *extensions = "GL_EXT_abgr";
+   static char *version = "1.1 Mesa 3.5";
+
+   switch (name) {
+   case GLU_EXTENSIONS:
+      return (GLubyte *) extensions;
+   case GLU_VERSION:
+      return (GLubyte *) version;
+   default:
+      return NULL;
+   }
+}
+
+
+
+#if 0                          /* gluGetProcAddressEXT not finalized yet! */
+
+#ifdef __cplusplus
+   /* for BeOS R4.5 */
+void GLAPIENTRY(*gluGetProcAddressEXT(const GLubyte * procName)) (...)
+#else
+void (GLAPIENTRY * gluGetProcAddressEXT(const GLubyte * procName)) ()
+#endif
+{
+   struct proc
+   {
+      const char *name;
+      void *address;
+   };
+   static struct proc procTable[] = {
+      {"gluGetProcAddressEXT", (void *) gluGetProcAddressEXT}, /* me! */
+
+      /* new 1.1 functions */
+      {"gluGetString", (void *) gluGetString},
+
+      /* new 1.2 functions */
+      {"gluTessBeginPolygon", (void *) gluTessBeginPolygon},
+      {"gluTessBeginContour", (void *) gluTessBeginContour},
+      {"gluTessEndContour", (void *) gluTessEndContour},
+      {"gluTessEndPolygon", (void *) gluTessEndPolygon},
+      {"gluGetTessProperty", (void *) gluGetTessProperty},
+
+      /* new 1.3 functions */
+
+      {NULL, NULL}
+   };
+   GLuint i;
+
+   for (i = 0; procTable[i].address; i++) {
+      if (strcmp((const char *) procName, procTable[i].name) == 0)
+        return (void (GLAPIENTRY *) ()) procTable[i].address;
+   }
+
+   return NULL;
+}
+
+#endif
+
+
+
+/*
+ * New in GLU 1.3
+ */
+#ifdef GLU_VERSION_1_3
+GLboolean GLAPIENTRY
+gluCheckExtension(const GLubyte *extName, const GLubyte * extString)
+{
+   assert(extName);
+   assert(extString);
+   {
+      const int len = strlen((const char *) extName);
+      const char *start = (const char *) extString;
+
+      while (1) {
+        const char *c = strstr(start, (const char *) extName);
+        if (!c)
+           return GL_FALSE;
+
+        if ((c == start || c[-1] == ' ') && (c[len] == ' ' || c[len] == 0))
+           return GL_TRUE;
+
+        start = c + len;
+      }
+   }
+}
+#endif
diff --git a/src/glu/mini/gluP.h b/src/glu/mini/gluP.h
new file mode 100644 (file)
index 0000000..85fbc33
--- /dev/null
@@ -0,0 +1,142 @@
+/* $Id: gluP.h,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.3
+ * Copyright (C) 1995-2000  Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+/*
+ * This file allows the GLU code to be compiled either with the Mesa
+ * headers or with the real OpenGL headers.
+ */
+
+
+#ifndef GLUP_H
+#define GLUP_H
+
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <string.h>
+
+
+#if defined(_WIN32) && !defined(__WIN32__)
+#      define __WIN32__
+#endif
+
+#if !defined(OPENSTEP) && (defined(__WIN32__) || defined(__CYGWIN__))
+#  pragma warning( disable : 4068 ) /* unknown pragma */
+#  pragma warning( disable : 4710 ) /* function 'foo' not inlined */
+#  pragma warning( disable : 4711 ) /* function 'foo' selected for automatic inline expansion */
+#  pragma warning( disable : 4127 ) /* conditional expression is constant */
+#  if defined(MESA_MINWARN)
+#    pragma warning( disable : 4244 ) /* '=' : conversion from 'const double ' to 'float ', possible loss of data */
+#    pragma warning( disable : 4018 ) /* '<' : signed/unsigned mismatch */
+#    pragma warning( disable : 4305 ) /* '=' : truncation from 'const double ' to 'float ' */
+#    pragma warning( disable : 4550 ) /* 'function' undefined; assuming extern returning int */
+#    pragma warning( disable : 4761 ) /* integral size mismatch in argument; conversion supplied */
+#  endif
+#  if defined(_MSC_VER) && defined(BUILD_GL32) /* tag specify we're building mesa as a DLL */
+#    define GLAPI __declspec(dllexport)
+#    define WGLAPI __declspec(dllexport)
+#  elif defined(_MSC_VER) && defined(_DLL) /* tag specifying we're building for DLL runtime support */
+#    define GLAPI __declspec(dllimport)
+#    define WGLAPI __declspec(dllimport)
+#  else /* for use with static link lib build of Win32 edition only */
+#    define GLAPI extern
+#    define WGLAPI __declspec(dllimport)
+#  endif /* _STATIC_MESA support */
+#  define GLAPIENTRY __stdcall
+#  define GLAPIENTRYP __stdcall *
+#  define GLCALLBACK __stdcall
+#  define GLCALLBACKP __stdcall *
+#  if defined(__CYGWIN__)
+#    define GLCALLBACKPCAST *
+#  else
+#    define GLCALLBACKPCAST __stdcall *
+#  endif
+#  define GLWINAPI __stdcall
+#  define GLWINAPIV __cdecl
+#else
+/* non-Windows compilation */
+#  define GLAPI extern
+#  define GLAPIENTRY
+#  define GLAPIENTRYP *
+#  define GLCALLBACK
+#  define GLCALLBACKP *
+#  define GLCALLBACKPCAST *
+#  define GLWINAPI
+#  define GLWINAPIV
+#endif /* WIN32 / CYGWIN bracket */
+
+/* compatibility guard so we don't need to change client code */
+
+#if defined(_WIN32) && !defined(_WINDEF_) && !defined(_GNU_H_WINDOWS32_BASE) && !defined(OPENSTEP)
+#      define CALLBACK GLCALLBACK
+typedef int (GLAPIENTRY *PROC)();
+typedef void *HGLRC;
+typedef void *HDC;
+typedef unsigned long COLORREF;
+#endif
+
+#if defined(_WIN32) && !defined(_WINGDI_) && !defined(_GNU_H_WINDOWS32_DEFINES) && !defined(OPENSTEP)
+#      define WGL_FONT_LINES      0
+#      define WGL_FONT_POLYGONS   1
+#ifndef _GNU_H_WINDOWS32_FUNCTIONS
+#      ifdef UNICODE
+#              define wglUseFontBitmaps  wglUseFontBitmapsW
+#              define wglUseFontOutlines  wglUseFontOutlinesW
+#      else
+#              define wglUseFontBitmaps  wglUseFontBitmapsA
+#              define wglUseFontOutlines  wglUseFontOutlinesA
+#      endif /* !UNICODE */
+#endif /* _GNU_H_WINDOWS32_FUNCTIONS */
+typedef struct tagLAYERPLANEDESCRIPTOR LAYERPLANEDESCRIPTOR, *PLAYERPLANEDESCRIPTOR, *LPLAYERPLANEDESCRIPTOR;
+typedef struct _GLYPHMETRICSFLOAT GLYPHMETRICSFLOAT, *PGLYPHMETRICSFLOAT, *LPGLYPHMETRICSFLOAT;
+typedef struct tagPIXELFORMATDESCRIPTOR PIXELFORMATDESCRIPTOR, *PPIXELFORMATDESCRIPTOR, *LPPIXELFORMATDESCRIPTOR;
+#include <gl/mesa_wgl.h>
+#endif
+
+
+
+#ifndef GLU_TESS_ERROR9
+   /* If we're using the real OpenGL header files... */
+#  define GLU_TESS_ERROR9      100159
+#endif
+
+
+#define GLU_NO_ERROR           GL_NO_ERROR
+
+
+/* for Sun: */
+#ifdef SUNOS4
+#define MEMCPY( DST, SRC, BYTES) \
+       memcpy( (char *) (DST), (char *) (SRC), (int) (BYTES) )
+#else
+#define MEMCPY( DST, SRC, BYTES) \
+       memcpy( (void *) (DST), (void *) (SRC), (size_t) (BYTES) )
+#endif
+
+
+#ifndef NULL
+#  define NULL 0
+#endif
+
+
+#endif
diff --git a/src/glu/mini/mipmap.c b/src/glu/mini/mipmap.c
new file mode 100644 (file)
index 0000000..9729772
--- /dev/null
@@ -0,0 +1,764 @@
+/* $Id: mipmap.c,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.4
+ * Copyright (C) 1995-2000  Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "gluP.h"
+#endif
+
+
+/*
+ * Compute ceiling of integer quotient of A divided by B:
+ */
+#define CEILING( A, B )  ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
+
+
+
+#ifdef EPSILON
+#undef EPSILON
+#endif
+#define EPSILON 0.001
+
+
+/* To work around optimizer bug in MSVC4.1 */
+#if defined(__WIN32__) && !defined(OPENSTEP)
+void
+dummy(GLuint j, GLuint k)
+{
+}
+#else
+#define dummy(J, K)
+#endif
+
+
+GLint GLAPIENTRY
+gluScaleImage(GLenum format,
+             GLsizei widthin, GLsizei heightin,
+             GLenum typein, const void *datain,
+             GLsizei widthout, GLsizei heightout,
+             GLenum typeout, void *dataout)
+{
+   GLint components, i, j, k;
+   GLfloat *tempin, *tempout, f;
+   GLfloat sx, sy;
+   GLint unpackrowlength, unpackalignment, unpackskiprows, unpackskippixels;
+   GLint packrowlength, packalignment, packskiprows, packskippixels;
+   GLint sizein, sizeout;
+   GLint rowstride, rowlen;
+
+
+   /* Determine number of components per pixel */
+   switch (format) {
+   case GL_COLOR_INDEX:
+   case GL_STENCIL_INDEX:
+   case GL_DEPTH_COMPONENT:
+   case GL_RED:
+   case GL_GREEN:
+   case GL_BLUE:
+   case GL_ALPHA:
+   case GL_LUMINANCE:
+      components = 1;
+      break;
+   case GL_LUMINANCE_ALPHA:
+      components = 2;
+      break;
+   case GL_RGB:
+   case GL_BGR:
+      components = 3;
+      break;
+   case GL_RGBA:
+   case GL_BGRA:
+#ifdef GL_EXT_abgr
+   case GL_ABGR_EXT:
+#endif
+      components = 4;
+      break;
+   default:
+      return GLU_INVALID_ENUM;
+   }
+
+   /* Determine bytes per input datum */
+   switch (typein) {
+   case GL_UNSIGNED_BYTE:
+      sizein = sizeof(GLubyte);
+      break;
+   case GL_BYTE:
+      sizein = sizeof(GLbyte);
+      break;
+   case GL_UNSIGNED_SHORT:
+      sizein = sizeof(GLushort);
+      break;
+   case GL_SHORT:
+      sizein = sizeof(GLshort);
+      break;
+   case GL_UNSIGNED_INT:
+      sizein = sizeof(GLuint);
+      break;
+   case GL_INT:
+      sizein = sizeof(GLint);
+      break;
+   case GL_FLOAT:
+      sizein = sizeof(GLfloat);
+      break;
+   case GL_BITMAP:
+      /* not implemented yet */
+   default:
+      return GL_INVALID_ENUM;
+   }
+
+   /* Determine bytes per output datum */
+   switch (typeout) {
+   case GL_UNSIGNED_BYTE:
+      sizeout = sizeof(GLubyte);
+      break;
+   case GL_BYTE:
+      sizeout = sizeof(GLbyte);
+      break;
+   case GL_UNSIGNED_SHORT:
+      sizeout = sizeof(GLushort);
+      break;
+   case GL_SHORT:
+      sizeout = sizeof(GLshort);
+      break;
+   case GL_UNSIGNED_INT:
+      sizeout = sizeof(GLuint);
+      break;
+   case GL_INT:
+      sizeout = sizeof(GLint);
+      break;
+   case GL_FLOAT:
+      sizeout = sizeof(GLfloat);
+      break;
+   case GL_BITMAP:
+      /* not implemented yet */
+   default:
+      return GL_INVALID_ENUM;
+   }
+
+   /* Get glPixelStore state */
+   glGetFloatv(GL_UNPACK_ROW_LENGTH, &f); unpackrowlength = (int)f;
+   glGetFloatv(GL_UNPACK_ALIGNMENT, &f); unpackalignment = (int)f;
+   glGetFloatv(GL_UNPACK_SKIP_ROWS, &f); unpackskiprows = (int)f;
+   glGetFloatv(GL_UNPACK_SKIP_PIXELS, &f); unpackskippixels = (int)f;
+   glGetFloatv(GL_PACK_ROW_LENGTH, &f); packrowlength = (int)f;
+   glGetFloatv(GL_PACK_ALIGNMENT, &f); packalignment = (int)f;
+   glGetFloatv(GL_PACK_SKIP_ROWS, &f); packskiprows = (int)f;
+   glGetFloatv(GL_PACK_SKIP_PIXELS, &f); packskippixels = (int)f;
+
+   /* Allocate storage for intermediate images */
+   tempin = (GLfloat *) malloc(widthin * heightin
+                              * components * sizeof(GLfloat));
+   if (!tempin) {
+      return GLU_OUT_OF_MEMORY;
+   }
+   tempout = (GLfloat *) malloc(widthout * heightout
+                               * components * sizeof(GLfloat));
+   if (!tempout) {
+      free(tempin);
+      return GLU_OUT_OF_MEMORY;
+   }
+
+
+   /*
+    * Unpack the pixel data and convert to floating point
+    */
+
+   if (unpackrowlength > 0) {
+      rowlen = unpackrowlength;
+   }
+   else {
+      rowlen = widthin;
+   }
+   if (sizein >= unpackalignment) {
+      rowstride = components * rowlen;
+   }
+   else {
+      rowstride = unpackalignment / sizein
+        * CEILING(components * rowlen * sizein, unpackalignment);
+   }
+
+   switch (typein) {
+   case GL_UNSIGNED_BYTE:
+      k = 0;
+      for (i = 0; i < heightin; i++) {
+        GLubyte *ubptr = (GLubyte *) datain
+           + i * rowstride
+           + unpackskiprows * rowstride + unpackskippixels * components;
+        for (j = 0; j < widthin * components; j++) {
+           dummy(j, k);
+           tempin[k++] = (GLfloat) * ubptr++;
+        }
+      }
+      break;
+   case GL_BYTE:
+      k = 0;
+      for (i = 0; i < heightin; i++) {
+        GLbyte *bptr = (GLbyte *) datain
+           + i * rowstride
+           + unpackskiprows * rowstride + unpackskippixels * components;
+        for (j = 0; j < widthin * components; j++) {
+           dummy(j, k);
+           tempin[k++] = (GLfloat) * bptr++;
+        }
+      }
+      break;
+   case GL_UNSIGNED_SHORT:
+      k = 0;
+      for (i = 0; i < heightin; i++) {
+        GLushort *usptr = (GLushort *) datain
+           + i * rowstride
+           + unpackskiprows * rowstride + unpackskippixels * components;
+        for (j = 0; j < widthin * components; j++) {
+           dummy(j, k);
+           tempin[k++] = (GLfloat) * usptr++;
+        }
+      }
+      break;
+   case GL_SHORT:
+      k = 0;
+      for (i = 0; i < heightin; i++) {
+        GLshort *sptr = (GLshort *) datain
+           + i * rowstride
+           + unpackskiprows * rowstride + unpackskippixels * components;
+        for (j = 0; j < widthin * components; j++) {
+           dummy(j, k);
+           tempin[k++] = (GLfloat) * sptr++;
+        }
+      }
+      break;
+   case GL_UNSIGNED_INT:
+      k = 0;
+      for (i = 0; i < heightin; i++) {
+        GLuint *uiptr = (GLuint *) datain
+           + i * rowstride
+           + unpackskiprows * rowstride + unpackskippixels * components;
+        for (j = 0; j < widthin * components; j++) {
+           dummy(j, k);
+           tempin[k++] = (GLfloat) * uiptr++;
+        }
+      }
+      break;
+   case GL_INT:
+      k = 0;
+      for (i = 0; i < heightin; i++) {
+        GLint *iptr = (GLint *) datain
+           + i * rowstride
+           + unpackskiprows * rowstride + unpackskippixels * components;
+        for (j = 0; j < widthin * components; j++) {
+           dummy(j, k);
+           tempin[k++] = (GLfloat) * iptr++;
+        }
+      }
+      break;
+   case GL_FLOAT:
+      k = 0;
+      for (i = 0; i < heightin; i++) {
+        GLfloat *fptr = (GLfloat *) datain
+           + i * rowstride
+           + unpackskiprows * rowstride + unpackskippixels * components;
+        for (j = 0; j < widthin * components; j++) {
+           dummy(j, k);
+           tempin[k++] = *fptr++;
+        }
+      }
+      break;
+   default:
+      return GLU_INVALID_ENUM;
+   }
+
+
+   /*
+    * Scale the image!
+    */
+
+   if (widthout > 1)
+      sx = (GLfloat) (widthin - 1) / (GLfloat) (widthout - 1);
+   else
+      sx = (GLfloat) (widthin - 1);
+   if (heightout > 1)
+      sy = (GLfloat) (heightin - 1) / (GLfloat) (heightout - 1);
+   else
+      sy = (GLfloat) (heightin - 1);
+
+/*#define POINT_SAMPLE*/
+#ifdef POINT_SAMPLE
+   for (i = 0; i < heightout; i++) {
+      GLint ii = i * sy;
+      for (j = 0; j < widthout; j++) {
+        GLint jj = j * sx;
+
+        GLfloat *src = tempin + (ii * widthin + jj) * components;
+        GLfloat *dst = tempout + (i * widthout + j) * components;
+
+        for (k = 0; k < components; k++) {
+           *dst++ = *src++;
+        }
+      }
+   }
+#else
+   if (sx < 1.0 && sy < 1.0) {
+      /* magnify both width and height:  use weighted sample of 4 pixels */
+      GLint i0, i1, j0, j1;
+      GLfloat alpha, beta;
+      GLfloat *src00, *src01, *src10, *src11;
+      GLfloat s1, s2;
+      GLfloat *dst;
+
+      for (i = 0; i < heightout; i++) {
+        i0 = i * sy;
+        i1 = i0 + 1;
+        if (i1 >= heightin)
+           i1 = heightin - 1;
+/*      i1 = (i+1) * sy - EPSILON;*/
+        alpha = i * sy - i0;
+        for (j = 0; j < widthout; j++) {
+           j0 = j * sx;
+           j1 = j0 + 1;
+           if (j1 >= widthin)
+              j1 = widthin - 1;
+/*         j1 = (j+1) * sx - EPSILON; */
+           beta = j * sx - j0;
+
+           /* compute weighted average of pixels in rect (i0,j0)-(i1,j1) */
+           src00 = tempin + (i0 * widthin + j0) * components;
+           src01 = tempin + (i0 * widthin + j1) * components;
+           src10 = tempin + (i1 * widthin + j0) * components;
+           src11 = tempin + (i1 * widthin + j1) * components;
+
+           dst = tempout + (i * widthout + j) * components;
+
+           for (k = 0; k < components; k++) {
+              s1 = *src00++ * (1.0 - beta) + *src01++ * beta;
+              s2 = *src10++ * (1.0 - beta) + *src11++ * beta;
+              *dst++ = s1 * (1.0 - alpha) + s2 * alpha;
+           }
+        }
+      }
+   }
+   else {
+      /* shrink width and/or height:  use an unweighted box filter */
+      GLint i0, i1;
+      GLint j0, j1;
+      GLint ii, jj;
+      GLfloat sum, *dst;
+
+      for (i = 0; i < heightout; i++) {
+        i0 = i * sy;
+        i1 = i0 + 1;
+        if (i1 >= heightin)
+           i1 = heightin - 1;
+/*      i1 = (i+1) * sy - EPSILON; */
+        for (j = 0; j < widthout; j++) {
+           j0 = j * sx;
+           j1 = j0 + 1;
+           if (j1 >= widthin)
+              j1 = widthin - 1;
+/*         j1 = (j+1) * sx - EPSILON; */
+
+           dst = tempout + (i * widthout + j) * components;
+
+           /* compute average of pixels in the rectangle (i0,j0)-(i1,j1) */
+           for (k = 0; k < components; k++) {
+              sum = 0.0;
+              for (ii = i0; ii <= i1; ii++) {
+                 for (jj = j0; jj <= j1; jj++) {
+                    sum += *(tempin + (ii * widthin + jj) * components + k);
+                 }
+              }
+              sum /= (j1 - j0 + 1) * (i1 - i0 + 1);
+              *dst++ = sum;
+           }
+        }
+      }
+   }
+#endif
+
+
+   /*
+    * Return output image
+    */
+
+   if (packrowlength > 0) {
+      rowlen = packrowlength;
+   }
+   else {
+      rowlen = widthout;
+   }
+   if (sizeout >= packalignment) {
+      rowstride = components * rowlen;
+   }
+   else {
+      rowstride = packalignment / sizeout
+        * CEILING(components * rowlen * sizeout, packalignment);
+   }
+
+   switch (typeout) {
+   case GL_UNSIGNED_BYTE:
+      k = 0;
+      for (i = 0; i < heightout; i++) {
+        GLubyte *ubptr = (GLubyte *) dataout
+           + i * rowstride
+           + packskiprows * rowstride + packskippixels * components;
+        for (j = 0; j < widthout * components; j++) {
+           dummy(j, k + i);
+           *ubptr++ = (GLubyte) tempout[k++];
+        }
+      }
+      break;
+   case GL_BYTE:
+      k = 0;
+      for (i = 0; i < heightout; i++) {
+        GLbyte *bptr = (GLbyte *) dataout
+           + i * rowstride
+           + packskiprows * rowstride + packskippixels * components;
+        for (j = 0; j < widthout * components; j++) {
+           dummy(j, k + i);
+           *bptr++ = (GLbyte) tempout[k++];
+        }
+      }
+      break;
+   case GL_UNSIGNED_SHORT:
+      k = 0;
+      for (i = 0; i < heightout; i++) {
+        GLushort *usptr = (GLushort *) dataout
+           + i * rowstride
+           + packskiprows * rowstride + packskippixels * components;
+        for (j = 0; j < widthout * components; j++) {
+           dummy(j, k + i);
+           *usptr++ = (GLushort) tempout[k++];
+        }
+      }
+      break;
+   case GL_SHORT:
+      k = 0;
+      for (i = 0; i < heightout; i++) {
+        GLshort *sptr = (GLshort *) dataout
+           + i * rowstride
+           + packskiprows * rowstride + packskippixels * components;
+        for (j = 0; j < widthout * components; j++) {
+           dummy(j, k + i);
+           *sptr++ = (GLshort) tempout[k++];
+        }
+      }
+      break;
+   case GL_UNSIGNED_INT:
+      k = 0;
+      for (i = 0; i < heightout; i++) {
+        GLuint *uiptr = (GLuint *) dataout
+           + i * rowstride
+           + packskiprows * rowstride + packskippixels * components;
+        for (j = 0; j < widthout * components; j++) {
+           dummy(j, k + i);
+           *uiptr++ = (GLuint) tempout[k++];
+        }
+      }
+      break;
+   case GL_INT:
+      k = 0;
+      for (i = 0; i < heightout; i++) {
+        GLint *iptr = (GLint *) dataout
+           + i * rowstride
+           + packskiprows * rowstride + packskippixels * components;
+        for (j = 0; j < widthout * components; j++) {
+           dummy(j, k + i);
+           *iptr++ = (GLint) tempout[k++];
+        }
+      }
+      break;
+   case GL_FLOAT:
+      k = 0;
+      for (i = 0; i < heightout; i++) {
+        GLfloat *fptr = (GLfloat *) dataout
+           + i * rowstride
+           + packskiprows * rowstride + packskippixels * components;
+        for (j = 0; j < widthout * components; j++) {
+           dummy(j, k + i);
+           *fptr++ = tempout[k++];
+        }
+      }
+      break;
+   default:
+      return GLU_INVALID_ENUM;
+   }
+
+
+   /* free temporary image storage */
+   free(tempin);
+   free(tempout);
+
+   return 0;
+}
+
+
+
+/*
+ * Return the largest k such that 2^k <= n.
+ */
+static GLint
+ilog2(GLint n)
+{
+   GLint k;
+
+   if (n <= 0)
+      return 0;
+   for (k = 0; n >>= 1; k++);
+   return k;
+}
+
+
+
+/*
+ * Find the value nearest to n which is also a power of two.
+ */
+static GLint
+round2(GLint n)
+{
+   GLint m;
+
+   for (m = 1; m < n; m *= 2);
+
+   /* m>=n */
+   if (m - n <= n - m / 2) {
+      return m;
+   }
+   else {
+      return m / 2;
+   }
+}
+
+
+/*
+ * Given an pixel format and data type, return the number of bytes to
+ * store one pixel.
+ */
+static GLint
+bytes_per_pixel(GLenum format, GLenum type)
+{
+   GLint n, m;
+
+   switch (format) {
+   case GL_COLOR_INDEX:
+   case GL_STENCIL_INDEX:
+   case GL_DEPTH_COMPONENT:
+   case GL_RED:
+   case GL_GREEN:
+   case GL_BLUE:
+   case GL_ALPHA:
+   case GL_LUMINANCE:
+      n = 1;
+      break;
+   case GL_LUMINANCE_ALPHA:
+      n = 2;
+      break;
+   case GL_RGB:
+   case GL_BGR:
+      n = 3;
+      break;
+   case GL_RGBA:
+   case GL_BGRA:
+#ifdef GL_EXT_abgr
+   case GL_ABGR_EXT:
+#endif
+      n = 4;
+      break;
+   default:
+      n = 0;
+   }
+
+   switch (type) {
+   case GL_UNSIGNED_BYTE:
+      m = sizeof(GLubyte);
+      break;
+   case GL_BYTE:
+      m = sizeof(GLbyte);
+      break;
+   case GL_BITMAP:
+      m = 1;
+      break;
+   case GL_UNSIGNED_SHORT:
+      m = sizeof(GLushort);
+      break;
+   case GL_SHORT:
+      m = sizeof(GLshort);
+      break;
+   case GL_UNSIGNED_INT:
+      m = sizeof(GLuint);
+      break;
+   case GL_INT:
+      m = sizeof(GLint);
+      break;
+   case GL_FLOAT:
+      m = sizeof(GLfloat);
+      break;
+   default:
+      m = 0;
+   }
+
+   return n * m;
+}
+
+
+
+/*
+ * WARNING: This function isn't finished and has never been tested!!!!
+ */
+GLint GLAPIENTRY
+gluBuild1DMipmaps(GLenum target, GLint components,
+                 GLsizei width, GLenum format, GLenum type, const void *data)
+{
+   return 0;
+}
+
+
+
+GLint GLAPIENTRY
+gluBuild2DMipmaps(GLenum target, GLint components,
+                 GLsizei width, GLsizei height, GLenum format,
+                 GLenum type, const void *data)
+{
+   GLint w, h;
+   GLint maxsize;
+   void *image, *newimage;
+   GLint neww, newh, level, bpp;
+   int error;
+   GLboolean done;
+   GLint retval = 0;
+   GLint unpackrowlength, unpackalignment, unpackskiprows, unpackskippixels;
+   GLint packrowlength, packalignment, packskiprows, packskippixels;
+   GLfloat f;
+
+   if (width < 1 || height < 1)
+      return GLU_INVALID_VALUE;
+
+   glGetFloatv(GL_MAX_TEXTURE_SIZE, &f); maxsize = (int)f;
+
+   w = round2(width);
+   if (w > maxsize) {
+      w = maxsize;
+   }
+   h = round2(height);
+   if (h > maxsize) {
+      h = maxsize;
+   }
+
+   bpp = bytes_per_pixel(format, type);
+   if (bpp == 0) {
+      /* probably a bad format or type enum */
+      return GLU_INVALID_ENUM;
+   }
+
+   /* Get current glPixelStore values */
+   glGetFloatv(GL_UNPACK_ROW_LENGTH, &f); unpackrowlength = (int)f;
+   glGetFloatv(GL_UNPACK_ALIGNMENT, &f); unpackalignment = (int)f;
+   glGetFloatv(GL_UNPACK_SKIP_ROWS, &f); unpackskiprows = (int)f;
+   glGetFloatv(GL_UNPACK_SKIP_PIXELS, &f); unpackskippixels = (int)f;
+   glGetFloatv(GL_PACK_ROW_LENGTH, &f); packrowlength = (int)f;
+   glGetFloatv(GL_PACK_ALIGNMENT, &f); packalignment = (int)f;
+   glGetFloatv(GL_PACK_SKIP_ROWS, &f); packskiprows = (int)f;
+   glGetFloatv(GL_PACK_SKIP_PIXELS, &f); packskippixels = (int)f;
+
+   /* set pixel packing */
+   glPixelStorei(GL_PACK_ROW_LENGTH, 0);
+   glPixelStorei(GL_PACK_ALIGNMENT, 1);
+   glPixelStorei(GL_PACK_SKIP_ROWS, 0);
+   glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
+
+   done = GL_FALSE;
+
+   if (w != width || h != height) {
+      /* must rescale image to get "top" mipmap texture image */
+      image = malloc((w + 4) * h * bpp);
+      if (!image) {
+        return GLU_OUT_OF_MEMORY;
+      }
+      error = gluScaleImage(format, width, height, type, data,
+                           w, h, type, image);
+      if (error) {
+        retval = error;
+        done = GL_TRUE;
+      }
+   }
+   else {
+      image = (void *) data;
+   }
+
+   level = 0;
+   while (!done) {
+      if (image != data) {
+        /* set pixel unpacking */
+        glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+        glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+        glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+      }
+
+      glTexImage2D(target, level, components, w, h, 0, format, type, image);
+
+      if (w == 1 && h == 1)
+        break;
+
+      neww = (w < 2) ? 1 : w / 2;
+      newh = (h < 2) ? 1 : h / 2;
+      newimage = malloc((neww + 4) * newh * bpp);
+      if (!newimage) {
+        return GLU_OUT_OF_MEMORY;
+      }
+
+      error = gluScaleImage(format, w, h, type, image,
+                           neww, newh, type, newimage);
+      if (error) {
+        retval = error;
+        done = GL_TRUE;
+      }
+
+      if (image != data) {
+        free(image);
+      }
+      image = newimage;
+
+      w = neww;
+      h = newh;
+      level++;
+   }
+
+   if (image != data) {
+      free(image);
+   }
+
+   /* Restore original glPixelStore state */
+   glPixelStorei(GL_UNPACK_ROW_LENGTH, unpackrowlength);
+   glPixelStorei(GL_UNPACK_ALIGNMENT, unpackalignment);
+   glPixelStorei(GL_UNPACK_SKIP_ROWS, unpackskiprows);
+   glPixelStorei(GL_UNPACK_SKIP_PIXELS, unpackskippixels);
+   glPixelStorei(GL_PACK_ROW_LENGTH, packrowlength);
+   glPixelStorei(GL_PACK_ALIGNMENT, packalignment);
+   glPixelStorei(GL_PACK_SKIP_ROWS, packskiprows);
+   glPixelStorei(GL_PACK_SKIP_PIXELS, packskippixels);
+
+   return retval;
+}
diff --git a/src/glu/mini/nurbs.c b/src/glu/mini/nurbs.c
new file mode 100644 (file)
index 0000000..93c0dd3
--- /dev/null
@@ -0,0 +1,158 @@
+/* $Id: nurbs.c,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.3
+ * Copyright (C) 1995-2000  Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+/*
+ * NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
+ * See README2 for more info.
+ */
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include "gluP.h"
+#include "nurbs.h"
+#endif
+
+
+void
+call_user_error(GLUnurbsObj * nobj, GLenum error)
+{
+   nobj->error = error;
+   if (nobj->error_callback != NULL) {
+      (*(nobj->error_callback)) (error);
+   }
+   else {
+      printf("NURBS error %d %s\n", error, (char *) gluErrorString(error));
+   }
+}
+
+
+
+GLUnurbsObj *GLAPIENTRY
+gluNewNurbsRenderer(void)
+{
+   GLUnurbsObj *n;
+   GLfloat tmp_viewport[4];
+   GLint i, j;
+
+   n = (GLUnurbsObj *) malloc(sizeof(GLUnurbsObj));
+   return n;
+}
+
+
+
+void GLAPIENTRY
+gluDeleteNurbsRenderer(GLUnurbsObj * nobj)
+{
+   if (nobj) {
+      free(nobj);
+   }
+}
+
+
+
+void GLAPIENTRY
+gluLoadSamplingMatrices(GLUnurbsObj * nobj,
+                       const GLfloat modelMatrix[16],
+                       const GLfloat projMatrix[16], const GLint viewport[4])
+{
+}
+
+
+void GLAPIENTRY
+gluNurbsProperty(GLUnurbsObj * nobj, GLenum property, GLfloat value)
+{
+}
+
+
+void GLAPIENTRY
+gluGetNurbsProperty(GLUnurbsObj * nobj, GLenum property, GLfloat * value)
+{
+}
+
+
+
+void GLAPIENTRY
+gluBeginCurve(GLUnurbsObj * nobj)
+{
+}
+
+
+void GLAPIENTRY
+gluEndCurve(GLUnurbsObj * nobj)
+{
+}
+
+
+void GLAPIENTRY
+gluNurbsCurve(GLUnurbsObj * nobj, GLint nknots, GLfloat * knot,
+             GLint stride, GLfloat * ctlarray, GLint order, GLenum type)
+{
+}
+
+
+void GLAPIENTRY
+gluBeginSurface(GLUnurbsObj * nobj)
+{
+}
+
+
+void GLAPIENTRY
+gluEndSurface(GLUnurbsObj * nobj)
+{
+}
+
+
+void GLAPIENTRY
+gluNurbsSurface(GLUnurbsObj * nobj,
+               GLint sknot_count, GLfloat * sknot,
+               GLint tknot_count, GLfloat * tknot,
+               GLint s_stride, GLint t_stride,
+               GLfloat * ctrlarray, GLint sorder, GLint torder, GLenum type)
+{
+}
+
+
+void GLAPIENTRY
+gluNurbsCallback(GLUnurbsObj * nobj, GLenum which, void (GLCALLBACK * fn) ())
+{
+}
+
+void GLAPIENTRY
+gluBeginTrim(GLUnurbsObj * nobj)
+{
+}
+
+void GLAPIENTRY
+gluPwlCurve(GLUnurbsObj * nobj, GLint count, GLfloat * array, GLint stride,
+           GLenum type)
+{
+}
+
+void GLAPIENTRY
+gluEndTrim(GLUnurbsObj * nobj)
+{
+}
diff --git a/src/glu/mini/nurbs.h b/src/glu/mini/nurbs.h
new file mode 100644 (file)
index 0000000..c9c9c09
--- /dev/null
@@ -0,0 +1,253 @@
+/* $Id: nurbs.h,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.3
+ * Copyright (C) 1995-2000  Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+/*
+ * NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
+ * See README2 for more info.
+ */
+
+
+#ifndef NURBS_H
+#define NURBS_H
+
+
+#define EPSILON 1e-06          /* epsilon for double precision compares */
+
+typedef enum
+{
+   GLU_NURBS_CURVE, GLU_NURBS_SURFACE, GLU_NURBS_TRIM, GLU_NURBS_NO_TRIM,
+   GLU_NURBS_TRIM_DONE, GLU_NURBS_NONE
+}
+GLU_nurbs_enum;
+
+typedef enum
+{
+   GLU_TRIM_NURBS, GLU_TRIM_PWL
+}
+GLU_trim_enum;
+
+typedef struct
+{
+   GLint sknot_count;
+   GLfloat *sknot;
+   GLint tknot_count;
+   GLfloat *tknot;
+   GLint s_stride;
+   GLint t_stride;
+   GLfloat *ctrlarray;
+   GLint sorder;
+   GLint torder;
+   GLint dim;
+   GLenum type;
+}
+surface_attribs;
+
+typedef struct
+{
+   surface_attribs geom;
+   surface_attribs color;
+   surface_attribs texture;
+   surface_attribs normal;
+}
+nurbs_surface;
+
+typedef struct
+{
+   GLint knot_count;
+   GLfloat *knot;
+   GLint stride;
+   GLfloat *ctrlarray;
+   GLint order;
+   GLint dim;
+   GLenum type;
+}
+curve_attribs;
+
+typedef struct
+{
+   GLint pt_count;
+   GLfloat *ctrlarray;
+   GLint stride;
+   GLint dim;
+   GLenum type;
+}
+pwl_curve_attribs;
+
+typedef struct
+{
+   curve_attribs geom;
+   curve_attribs color;
+   curve_attribs texture;
+   curve_attribs normal;
+}
+nurbs_curve;
+
+typedef struct trim_list_str
+{
+   GLU_trim_enum trim_type;
+   union
+   {
+      pwl_curve_attribs pwl_curve;
+      curve_attribs nurbs_curve;
+   }
+   curve;
+   struct trim_list_str *next;
+}
+trim_list;
+
+typedef struct seg_trim_str
+{
+   GLfloat *points;
+   GLint pt_cnt, seg_array_len;
+   struct seg_trim_str *next;
+}
+trim_segments;
+
+typedef struct nurbs_trim_str
+{
+   trim_list *trim_loop;
+   trim_segments *segments;
+   struct nurbs_trim_str *next;
+}
+nurbs_trim;
+
+typedef struct
+{
+   GLfloat model[16], proj[16], viewport[4];
+}
+culling_and_sampling_str;
+
+struct GLUnurbs
+{
+   GLboolean culling;
+   GLenum error;
+   void (GLCALLBACK * error_callback) (GLenum err);
+   GLenum display_mode;
+   GLU_nurbs_enum nurbs_type;
+   GLboolean auto_load_matrix;
+     culling_and_sampling_str sampling_matrices;
+   GLenum sampling_method;
+   GLfloat sampling_tolerance;
+   GLfloat parametric_tolerance;
+   GLint u_step, v_step;
+   nurbs_surface surface;
+   nurbs_curve curve;
+   nurbs_trim *trim;
+};
+
+typedef struct
+{
+   GLfloat *knot;
+   GLint nknots;
+   GLfloat *unified_knot;
+   GLint unified_nknots;
+   GLint order;
+   GLint t_min, t_max;
+   GLint delta_nknots;
+   GLboolean open_at_begin, open_at_end;
+   GLfloat *new_knot;
+   GLfloat *alpha;
+}
+knot_str_type;
+
+typedef struct
+{
+   GLfloat *geom_ctrl;
+   GLint geom_s_stride, geom_t_stride;
+   GLfloat **geom_offsets;
+   GLint geom_s_pt_cnt, geom_t_pt_cnt;
+   GLfloat *color_ctrl;
+   GLint color_s_stride, color_t_stride;
+   GLfloat **color_offsets;
+   GLint color_s_pt_cnt, color_t_pt_cnt;
+   GLfloat *normal_ctrl;
+   GLint normal_s_stride, normal_t_stride;
+   GLfloat **normal_offsets;
+   GLint normal_s_pt_cnt, normal_t_pt_cnt;
+   GLfloat *texture_ctrl;
+   GLint texture_s_stride, texture_t_stride;
+   GLfloat **texture_offsets;
+   GLint texture_s_pt_cnt, texture_t_pt_cnt;
+   GLint s_bezier_cnt, t_bezier_cnt;
+}
+new_ctrl_type;
+
+extern void call_user_error(GLUnurbsObj * nobj, GLenum error);
+
+extern GLenum test_knot(GLint nknots, GLfloat * knot, GLint order);
+
+extern GLenum explode_knot(knot_str_type * the_knot);
+
+extern GLenum calc_alphas(knot_str_type * the_knot);
+
+extern GLenum calc_new_ctrl_pts(GLfloat * ctrl, GLint stride,
+                               knot_str_type * the_knot, GLint dim,
+                               GLfloat ** new_ctrl, GLint * ncontrol);
+
+extern GLenum glu_do_sampling_crv(GLUnurbsObj * nobj, GLfloat * new_ctrl,
+                                 GLint n_ctrl, GLint order, GLint dim,
+                                 GLint ** factors);
+
+extern GLenum glu_do_sampling_3D(GLUnurbsObj * nobj, new_ctrl_type * new_ctrl,
+                                int **sfactors, GLint ** tfactors);
+
+extern GLenum glu_do_sampling_uv(GLUnurbsObj * nobj, new_ctrl_type * new_ctrl,
+                                int **sfactors, GLint ** tfactors);
+
+extern GLenum glu_do_sampling_param_3D(GLUnurbsObj * nobj,
+                                      new_ctrl_type * new_ctrl,
+                                      int **sfactors, GLint ** tfactors);
+
+extern GLboolean fine_culling_test_2D(GLUnurbsObj * nobj, GLfloat * ctrl,
+                                     GLint n_ctrl, GLint stride, GLint dim);
+
+extern GLboolean fine_culling_test_3D(GLUnurbsObj * nobj, GLfloat * ctrl,
+                                     GLint s_n_ctrl, GLint t_n_ctrl,
+                                     GLint s_stride, GLint t_stride,
+                                     GLint dim);
+
+extern void do_nurbs_curve(GLUnurbsObj * nobj);
+
+extern void do_nurbs_surface(GLUnurbsObj * nobj);
+
+extern GLenum patch_trimming(GLUnurbsObj * nobj, new_ctrl_type * new_ctrl,
+                            GLint * sfactors, GLint * tfactors);
+
+extern void collect_unified_knot(knot_str_type * dest, knot_str_type * src,
+                                GLfloat maximal_min_knot,
+                                GLfloat minimal_max_knot);
+
+extern GLenum select_knot_working_range(GLUnurbsObj * nobj,
+                                       knot_str_type * geom_knot,
+                                       knot_str_type * color_knot,
+                                       knot_str_type * normal_knot,
+                                       knot_str_type * texture_knot);
+
+extern void free_unified_knots(knot_str_type * geom_knot,
+                              knot_str_type * color_knot,
+                              knot_str_type * normal_knot,
+                              knot_str_type * texture_knot);
+
+
+
+#endif
diff --git a/src/glu/mini/nurbscrv.c b/src/glu/mini/nurbscrv.c
new file mode 100644 (file)
index 0000000..62d91b4
--- /dev/null
@@ -0,0 +1,133 @@
+/* $Id: nurbscrv.c,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.3
+ * Copyright (C) 1995-2000  Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+/*
+ * NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
+ * See README2 for more info.
+ */
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <math.h>
+#include <stdlib.h>
+#include "gluP.h"
+#include "nurbs.h"
+#endif
+
+
+
+/* main NURBS curve procedure */
+void
+do_nurbs_curve(GLUnurbsObj * nobj)
+{
+   GLint geom_order, color_order = 0, normal_order = 0, texture_order = 0;
+   GLenum geom_type;
+   GLint n_ctrl;
+   GLfloat *new_geom_ctrl, *new_color_ctrl, *new_normal_ctrl,
+      *new_texture_ctrl;
+   GLfloat *geom_ctrl = 0, *color_ctrl = 0, *normal_ctrl = 0, *texture_ctrl = 0;
+   GLint *factors;
+   GLint i, j;
+   GLint geom_dim, color_dim = 0, normal_dim = 0, texture_dim = 0;
+
+   /* test the user supplied data */
+   if (test_nurbs_curves(nobj) != GLU_NO_ERROR)
+      return;
+
+   if (convert_curves(nobj, &new_geom_ctrl, &n_ctrl, &new_color_ctrl,
+                     &new_normal_ctrl, &new_texture_ctrl) != GLU_NO_ERROR)
+      return;
+
+   geom_order = nobj->curve.geom.order;
+   geom_type = nobj->curve.geom.type;
+   geom_dim = nobj->curve.geom.dim;
+
+   if (glu_do_sampling_crv(nobj, new_geom_ctrl, n_ctrl, geom_order, geom_dim,
+                          &factors) != GLU_NO_ERROR) {
+      free(new_geom_ctrl);
+      if (new_color_ctrl)
+        free(new_color_ctrl);
+      if (new_normal_ctrl)
+        free(new_normal_ctrl);
+      if (new_texture_ctrl)
+        free(new_texture_ctrl);
+      return;
+   }
+   glEnable(geom_type);
+   if (new_color_ctrl) {
+      glEnable(nobj->curve.color.type);
+      color_dim = nobj->curve.color.dim;
+      color_ctrl = new_color_ctrl;
+      color_order = nobj->curve.color.order;
+   }
+   if (new_normal_ctrl) {
+      glEnable(nobj->curve.normal.type);
+      normal_dim = nobj->curve.normal.dim;
+      normal_ctrl = new_normal_ctrl;
+      normal_order = nobj->curve.normal.order;
+   }
+   if (new_texture_ctrl) {
+      glEnable(nobj->curve.texture.type);
+      texture_dim = nobj->curve.texture.dim;
+      texture_ctrl = new_texture_ctrl;
+      texture_order = nobj->curve.texture.order;
+   }
+   for (i = 0, j = 0, geom_ctrl = new_geom_ctrl;
+       i < n_ctrl; i += geom_order, j++, geom_ctrl += geom_order * geom_dim) {
+      if (fine_culling_test_2D
+         (nobj, geom_ctrl, geom_order, geom_dim, geom_dim)) {
+        color_ctrl += color_order * color_dim;
+        normal_ctrl += normal_order * normal_dim;
+        texture_ctrl += texture_order * texture_dim;
+        continue;
+      }
+      glMap1f(geom_type, 0.0, 1.0, geom_dim, geom_order, geom_ctrl);
+      if (new_color_ctrl) {
+        glMap1f(nobj->curve.color.type, 0.0, 1.0, color_dim,
+                color_order, color_ctrl);
+        color_ctrl += color_order * color_dim;
+      }
+      if (new_normal_ctrl) {
+        glMap1f(nobj->curve.normal.type, 0.0, 1.0, normal_dim,
+                normal_order, normal_ctrl);
+        normal_ctrl += normal_order * normal_dim;
+      }
+      if (new_texture_ctrl) {
+        glMap1f(nobj->curve.texture.type, 0.0, 1.0, texture_dim,
+                texture_order, texture_ctrl);
+        texture_ctrl += texture_order * texture_dim;
+      }
+      glMapGrid1f(factors[j], 0.0, 1.0);
+      glEvalMesh1(GL_LINE, 0, factors[j]);
+   }
+   free(new_geom_ctrl);
+   free(factors);
+   if (new_color_ctrl)
+      free(new_color_ctrl);
+   if (new_normal_ctrl)
+      free(new_normal_ctrl);
+   if (new_texture_ctrl)
+      free(new_texture_ctrl);
+}
diff --git a/src/glu/mini/polytest.c b/src/glu/mini/polytest.c
new file mode 100644 (file)
index 0000000..52f272a
--- /dev/null
@@ -0,0 +1,938 @@
+/* $Id: polytest.c,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.3
+ * Copyright (C) 1995-2000  Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+/*
+ * This file is part of the polygon tesselation code contributed by
+ * Bogdan Sikorski
+ */
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <math.h>
+#include <stdlib.h>
+#include "gluP.h"
+#include "tess.h"
+#endif
+
+
+
+static GLenum store_polygon_as_contour(GLUtriangulatorObj *);
+static void free_current_polygon(tess_polygon *);
+static void prepare_projection_info(GLUtriangulatorObj *);
+static GLdouble twice_the_polygon_area(tess_vertex *, tess_vertex *);
+static GLenum verify_edge_vertex_intersections(GLUtriangulatorObj *);
+void tess_find_contour_hierarchies(GLUtriangulatorObj *);
+static GLenum test_for_overlapping_contours(GLUtriangulatorObj *);
+static GLenum contours_overlap(tess_contour *, tess_polygon *);
+static GLenum is_contour_contained_in(tess_contour *, tess_contour *);
+static void add_new_exterior(GLUtriangulatorObj *, tess_contour *);
+static void add_new_interior(GLUtriangulatorObj *, tess_contour *,
+                            tess_contour *);
+static void add_interior_with_hierarchy_check(GLUtriangulatorObj *,
+                                             tess_contour *, tess_contour *);
+static void reverse_hierarchy_and_add_exterior(GLUtriangulatorObj *,
+                                              tess_contour *,
+                                              tess_contour *);
+static GLboolean point_in_polygon(tess_contour *, GLdouble, GLdouble);
+static void shift_interior_to_exterior(GLUtriangulatorObj *, tess_contour *);
+static void add_exterior_with_check(GLUtriangulatorObj *, tess_contour *,
+                                   tess_contour *);
+static GLenum cut_out_hole(GLUtriangulatorObj *, tess_contour *,
+                          tess_contour *);
+static GLenum merge_hole_with_contour(GLUtriangulatorObj *,
+                                     tess_contour *, tess_contour *,
+                                     tess_vertex *, tess_vertex *);
+
+static GLenum
+find_normal(GLUtriangulatorObj * tobj)
+{
+   tess_polygon *polygon = tobj->current_polygon;
+   tess_vertex *va, *vb, *vc;
+   GLdouble A, B, C;
+   GLdouble A0, A1, A2, B0, B1, B2;
+
+   va = polygon->vertices;
+   vb = va->next;
+   A0 = vb->location[0] - va->location[0];
+   A1 = vb->location[1] - va->location[1];
+   A2 = vb->location[2] - va->location[2];
+   for (vc = vb->next; vc != va; vc = vc->next) {
+      B0 = vc->location[0] - va->location[0];
+      B1 = vc->location[1] - va->location[1];
+      B2 = vc->location[2] - va->location[2];
+      A = A1 * B2 - A2 * B1;
+      B = A2 * B0 - A0 * B2;
+      C = A0 * B1 - A1 * B0;
+      if (fabs(A) > EPSILON || fabs(B) > EPSILON || fabs(C) > EPSILON) {
+        polygon->A = A;
+        polygon->B = B;
+        polygon->C = C;
+        polygon->D =
+           -A * va->location[0] - B * va->location[1] - C * va->location[2];
+        return GLU_NO_ERROR;
+      }
+   }
+   tess_call_user_error(tobj, GLU_TESS_ERROR7);
+   return GLU_ERROR;
+}
+
+void
+tess_test_polygon(GLUtriangulatorObj * tobj)
+{
+   tess_polygon *polygon = tobj->current_polygon;
+
+   /* any vertices defined? */
+   if (polygon->vertex_cnt < 3) {
+      free_current_polygon(polygon);
+      return;
+   }
+   /* wrap pointers */
+   polygon->last_vertex->next = polygon->vertices;
+   polygon->vertices->previous = polygon->last_vertex;
+   /* determine the normal */
+   if (find_normal(tobj) == GLU_ERROR)
+      return;
+   /* compare the normals of previously defined contours and this one */
+   /* first contour define ? */
+   if (tobj->contours == NULL) {
+      tobj->A = polygon->A;
+      tobj->B = polygon->B;
+      tobj->C = polygon->C;
+      tobj->D = polygon->D;
+      /* determine the best projection to use */
+      if (fabs(polygon->A) > fabs(polygon->B))
+        if (fabs(polygon->A) > fabs(polygon->C))
+           tobj->projection = OYZ;
+        else
+           tobj->projection = OXY;
+      else if (fabs(polygon->B) > fabs(polygon->C))
+        tobj->projection = OXZ;
+      else
+        tobj->projection = OXY;
+   }
+   else {
+      GLdouble a[3], b[3];
+      tess_vertex *vertex = polygon->vertices;
+
+      a[0] = tobj->A;
+      a[1] = tobj->B;
+      a[2] = tobj->C;
+      b[0] = polygon->A;
+      b[1] = polygon->B;
+      b[2] = polygon->C;
+
+      /* compare the normals */
+      if (fabs(a[1] * b[2] - a[2] * b[1]) > EPSILON ||
+         fabs(a[2] * b[0] - a[0] * b[2]) > EPSILON ||
+         fabs(a[0] * b[1] - a[1] * b[0]) > EPSILON) {
+        /* not coplanar */
+        tess_call_user_error(tobj, GLU_TESS_ERROR9);
+        return;
+      }
+      /* the normals are parallel - test for plane equation */
+      if (fabs(a[0] * vertex->location[0] + a[1] * vertex->location[1] +
+              a[2] * vertex->location[2] + tobj->D) > EPSILON) {
+        /* not the same plane */
+        tess_call_user_error(tobj, GLU_TESS_ERROR9);
+        return;
+      }
+   }
+   prepare_projection_info(tobj);
+   if (verify_edge_vertex_intersections(tobj) == GLU_ERROR)
+      return;
+   if (test_for_overlapping_contours(tobj) == GLU_ERROR)
+      return;
+   if (store_polygon_as_contour(tobj) == GLU_ERROR)
+      return;
+}
+
+static GLenum
+test_for_overlapping_contours(GLUtriangulatorObj * tobj)
+{
+   tess_contour *contour;
+   tess_polygon *polygon;
+
+   polygon = tobj->current_polygon;
+   for (contour = tobj->contours; contour != NULL; contour = contour->next)
+      if (contours_overlap(contour, polygon) != GLU_NO_ERROR) {
+        tess_call_user_error(tobj, GLU_TESS_ERROR5);
+        return GLU_ERROR;
+      }
+   return GLU_NO_ERROR;
+}
+
+static GLenum
+store_polygon_as_contour(GLUtriangulatorObj * tobj)
+{
+   tess_polygon *polygon = tobj->current_polygon;
+   tess_contour *contour = tobj->contours;
+
+   /* the first contour defined */
+   if (contour == NULL) {
+      if ((contour = (tess_contour *) malloc(sizeof(tess_contour))) == NULL) {
+        tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
+        free_current_polygon(polygon);
+        return GLU_ERROR;
+      }
+      tobj->contours = tobj->last_contour = contour;
+      contour->next = contour->previous = NULL;
+   }
+   else {
+      if ((contour = (tess_contour *) malloc(sizeof(tess_contour))) == NULL) {
+        tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
+        free_current_polygon(polygon);
+        return GLU_ERROR;
+      }
+      contour->previous = tobj->last_contour;
+      tobj->last_contour->next = contour;
+      tobj->last_contour = contour;
+      contour->next = NULL;
+   }
+   /* mark all vertices in new contour as not special */
+   /* and all are boundary edges */
+   {
+      tess_vertex *vertex;
+      GLuint vertex_cnt, i;
+
+      for (vertex = polygon->vertices, i = 0, vertex_cnt =
+          polygon->vertex_cnt; i < vertex_cnt; vertex = vertex->next, i++) {
+        vertex->shadow_vertex = NULL;
+        vertex->edge_flag = GL_TRUE;
+      }
+   }
+   contour->vertex_cnt = polygon->vertex_cnt;
+   contour->area = polygon->area;
+   contour->orientation = polygon->orientation;
+   contour->type = GLU_UNKNOWN;
+   contour->vertices = polygon->vertices;
+   contour->last_vertex = polygon->last_vertex;
+   polygon->vertices = polygon->last_vertex = NULL;
+   polygon->vertex_cnt = 0;
+   ++(tobj->contour_cnt);
+   return GLU_NO_ERROR;
+}
+
+static void
+free_current_polygon(tess_polygon * polygon)
+{
+   tess_vertex *vertex, *vertex_tmp;
+   GLuint i;
+
+   /* free current_polygon structures */
+   for (vertex = polygon->vertices, i = 0; i < polygon->vertex_cnt; i++) {
+      vertex_tmp = vertex->next;
+      free(vertex);
+      vertex = vertex_tmp;
+   }
+   polygon->vertices = polygon->last_vertex = NULL;
+   polygon->vertex_cnt = 0;
+}
+
+static void
+prepare_projection_info(GLUtriangulatorObj * tobj)
+{
+   tess_polygon *polygon = tobj->current_polygon;
+   tess_vertex *vertex, *last_vertex_ptr;
+   GLdouble area;
+
+   last_vertex_ptr = polygon->last_vertex;
+   switch (tobj->projection) {
+   case OXY:
+      for (vertex = polygon->vertices; vertex != last_vertex_ptr;
+          vertex = vertex->next) {
+        vertex->x = vertex->location[0];
+        vertex->y = vertex->location[1];
+      }
+      last_vertex_ptr->x = last_vertex_ptr->location[0];
+      last_vertex_ptr->y = last_vertex_ptr->location[1];
+      break;
+   case OXZ:
+      for (vertex = polygon->vertices; vertex != last_vertex_ptr;
+          vertex = vertex->next) {
+        vertex->x = vertex->location[0];
+        vertex->y = vertex->location[2];
+      }
+      last_vertex_ptr->x = last_vertex_ptr->location[0];
+      last_vertex_ptr->y = last_vertex_ptr->location[2];
+      break;
+   case OYZ:
+      for (vertex = polygon->vertices; vertex != last_vertex_ptr;
+          vertex = vertex->next) {
+        vertex->x = vertex->location[1];
+        vertex->y = vertex->location[2];
+      }
+      last_vertex_ptr->x = last_vertex_ptr->location[1];
+      last_vertex_ptr->y = last_vertex_ptr->location[2];
+      break;
+   }
+   area = twice_the_polygon_area(polygon->vertices, polygon->last_vertex);
+   if (area >= 0.0) {
+      polygon->orientation = GLU_CCW;
+      polygon->area = area;
+   }
+   else {
+      polygon->orientation = GLU_CW;
+      polygon->area = -area;
+   }
+}
+
+static GLdouble
+twice_the_polygon_area(tess_vertex * vertex, tess_vertex * last_vertex)
+{
+   tess_vertex *next;
+   GLdouble area, x, y;
+
+   area = 0.0;
+   x = vertex->x;
+   y = vertex->y;
+   vertex = vertex->next;
+   for (; vertex != last_vertex; vertex = vertex->next) {
+      next = vertex->next;
+      area +=
+        (vertex->x - x) * (next->y - y) - (vertex->y - y) * (next->x - x);
+   }
+   return area;
+}
+
+/* test if edges ab and cd intersect */
+/* if not return GLU_NO_ERROR, else if cross return GLU_TESS_ERROR8, */
+/* else if adjacent return GLU_TESS_ERROR4 */
+static GLenum
+edge_edge_intersect(tess_vertex * a,
+                   tess_vertex * b, tess_vertex * c, tess_vertex * d)
+{
+   GLdouble denom, r, s;
+   GLdouble xba, ydc, yba, xdc, yac, xac;
+
+   xba = b->x - a->x;
+   yba = b->y - a->y;
+   xdc = d->x - c->x;
+   ydc = d->y - c->y;
+   xac = a->x - c->x;
+   yac = a->y - c->y;
+   denom = xba * ydc - yba * xdc;
+   r = yac * xdc - xac * ydc;
+   /* parallel? */
+   if (fabs(denom) < EPSILON) {
+      if (fabs(r) < EPSILON) {
+        /* colinear */
+        if (fabs(xba) < EPSILON) {
+           /* compare the Y coordinate */
+           if (yba > 0.0) {
+              if (
+                  (fabs(a->y - c->y) < EPSILON
+                   && fabs(c->y - b->y) < EPSILON)
+                  || (fabs(a->y - d->y) < EPSILON
+                      && fabs(d->y - b->y) <
+                      EPSILON)) return GLU_TESS_ERROR4;
+
+           }
+           else {
+              if (
+                  (fabs(b->y - c->y) < EPSILON
+                   && fabs(c->y - a->y) < EPSILON)
+                  || (fabs(b->y - d->y) < EPSILON
+                      && fabs(d->y - a->y) <
+                      EPSILON)) return GLU_TESS_ERROR4;
+           }
+        }
+        else {
+           /* compare the X coordinate */
+           if (xba > 0.0) {
+              if (
+                  (fabs(a->x - c->x) < EPSILON
+                   && fabs(c->x - b->x) < EPSILON)
+                  || (fabs(a->x - d->x) < EPSILON
+                      && fabs(d->x - b->x) <
+                      EPSILON)) return GLU_TESS_ERROR4;
+           }
+           else {
+              if (
+                  (fabs(b->x - c->x) < EPSILON
+                   && fabs(c->x - a->x) < EPSILON)
+                  || (fabs(b->x - d->x) < EPSILON
+                      && fabs(d->x - a->x) <
+                      EPSILON)) return GLU_TESS_ERROR4;
+           }
+        }
+      }
+      return GLU_NO_ERROR;
+   }
+   r /= denom;
+   s = (yac * xba - xac * yba) / denom;
+   /* test if one vertex lies on other edge */
+   if (((fabs(r) < EPSILON || (r < 1.0 + EPSILON && r > 1.0 - EPSILON)) &&
+       s > -EPSILON && s < 1.0 + EPSILON) ||
+       ((fabs(s) < EPSILON || (s < 1.0 + EPSILON && s > 1.0 - EPSILON)) &&
+       r > -EPSILON && r < 1.0 + EPSILON)) {
+      return GLU_TESS_ERROR4;
+   }
+   /* test for crossing */
+   if (r > -EPSILON && r < 1.0 + EPSILON && s > -EPSILON && s < 1.0 + EPSILON) {
+      return GLU_TESS_ERROR8;
+   }
+   return GLU_NO_ERROR;
+}
+
+static GLenum
+verify_edge_vertex_intersections(GLUtriangulatorObj * tobj)
+{
+   tess_polygon *polygon = tobj->current_polygon;
+   tess_vertex *vertex1, *last_vertex, *vertex2;
+   GLenum test;
+
+   last_vertex = polygon->last_vertex;
+   vertex1 = last_vertex;
+   for (vertex2 = vertex1->next->next;
+       vertex2->next != last_vertex; vertex2 = vertex2->next) {
+      test = edge_edge_intersect(vertex1, vertex1->next, vertex2,
+                                vertex2->next);
+      if (test != GLU_NO_ERROR) {
+        tess_call_user_error(tobj, test);
+        return GLU_ERROR;
+      }
+   }
+   for (vertex1 = polygon->vertices;
+       vertex1->next->next != last_vertex; vertex1 = vertex1->next) {
+      for (vertex2 = vertex1->next->next;
+          vertex2 != last_vertex; vertex2 = vertex2->next) {
+        test = edge_edge_intersect(vertex1, vertex1->next, vertex2,
+                                   vertex2->next);
+        if (test != GLU_NO_ERROR) {
+           tess_call_user_error(tobj, test);
+           return GLU_ERROR;
+        }
+      }
+   }
+   return GLU_NO_ERROR;
+}
+
+static int
+#ifdef WIN32
+  __cdecl
+#endif
+area_compare(const void *a, const void *b)
+{
+   GLdouble area1, area2;
+
+   area1 = (*((tess_contour **) a))->area;
+   area2 = (*((tess_contour **) b))->area;
+   if (area1 < area2)
+      return 1;
+   if (area1 > area2)
+      return -1;
+   return 0;
+}
+
+void
+tess_find_contour_hierarchies(GLUtriangulatorObj * tobj)
+{
+   tess_contour **contours;    /* dinamic array of pointers */
+   tess_contour *tmp_contour_ptr = tobj->contours;
+   GLuint cnt, i;
+   GLenum result;
+   GLboolean hierarchy_changed;
+
+   /* any contours? */
+   if (tobj->contour_cnt < 2) {
+      tobj->contours->type = GLU_EXTERIOR;
+      return;
+   }
+   if ((contours = (tess_contour **)
+       malloc(sizeof(tess_contour *) * (tobj->contour_cnt))) == NULL) {
+      tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
+      return;
+   }
+   for (tmp_contour_ptr = tobj->contours, cnt = 0;
+       tmp_contour_ptr != NULL; tmp_contour_ptr = tmp_contour_ptr->next)
+      contours[cnt++] = tmp_contour_ptr;
+   /* now sort the contours in decreasing area size order */
+   qsort((void *) contours, (size_t) cnt, (size_t) sizeof(tess_contour *),
+        area_compare);
+   /* we leave just the first contour - remove others from list */
+   tobj->contours = contours[0];
+   tobj->contours->next = tobj->contours->previous = NULL;
+   tobj->last_contour = tobj->contours;
+   tobj->contour_cnt = 1;
+   /* first contour is the one with greatest area */
+   /* must be EXTERIOR */
+   tobj->contours->type = GLU_EXTERIOR;
+   tmp_contour_ptr = tobj->contours;
+   /* now we play! */
+   for (i = 1; i < cnt; i++) {
+      hierarchy_changed = GL_FALSE;
+      for (tmp_contour_ptr = tobj->contours;
+          tmp_contour_ptr != NULL; tmp_contour_ptr = tmp_contour_ptr->next) {
+        if (tmp_contour_ptr->type == GLU_EXTERIOR) {
+           /* check if contour completely contained in EXTERIOR */
+           result = is_contour_contained_in(tmp_contour_ptr, contours[i]);
+           switch (result) {
+           case GLU_INTERIOR:
+              /* now we have to check if contour is inside interiors */
+              /* or not */
+              /* any interiors? */
+              if (tmp_contour_ptr->next != NULL &&
+                  tmp_contour_ptr->next->type == GLU_INTERIOR) {
+                 /* for all interior, check if inside any of them */
+                 /* if not inside any of interiors, its another */
+                 /* interior */
+                 /* or it may contain some interiors, then change */
+                 /* the contained interiors to exterior ones */
+                 add_interior_with_hierarchy_check(tobj,
+                                                   tmp_contour_ptr,
+                                                   contours[i]);
+              }
+              else {
+                 /* not in interior, add as new interior contour */
+                 add_new_interior(tobj, tmp_contour_ptr, contours[i]);
+              }
+              hierarchy_changed = GL_TRUE;
+              break;
+           case GLU_EXTERIOR:
+              /* ooops, the marked as EXTERIOR (contours[i]) is */
+              /* actually an interior of tmp_contour_ptr */
+              /*  reverse the local hierarchy */
+              reverse_hierarchy_and_add_exterior(tobj, tmp_contour_ptr,
+                                                 contours[i]);
+              hierarchy_changed = GL_TRUE;
+              break;
+           case GLU_NO_ERROR:
+              break;
+           default:
+              abort();
+           }
+        }
+        if (hierarchy_changed)
+           break;              /* break from for loop */
+      }
+      if (hierarchy_changed == GL_FALSE) {
+        /* disjoint with all contours, add to contour list */
+        add_new_exterior(tobj, contours[i]);
+      }
+   }
+   free(contours);
+}
+
+/* returns GLU_INTERIOR if inner is completey enclosed within outer */
+/* returns GLU_EXTERIOR if outer is completely enclosed within inner */
+/* returns GLU_NO_ERROR if contours are disjoint */
+static GLenum
+is_contour_contained_in(tess_contour * outer, tess_contour * inner)
+{
+   GLenum relation_flag;
+
+   /* set relation_flag to relation of containment of first inner vertex */
+   /* regarding outer contour */
+   if (point_in_polygon(outer, inner->vertices->x, inner->vertices->y))
+      relation_flag = GLU_INTERIOR;
+   else
+      relation_flag = GLU_EXTERIOR;
+   if (relation_flag == GLU_INTERIOR)
+      return GLU_INTERIOR;
+   if (point_in_polygon(inner, outer->vertices->x, outer->vertices->y))
+      return GLU_EXTERIOR;
+   return GLU_NO_ERROR;
+}
+
+static GLboolean
+point_in_polygon(tess_contour * contour, GLdouble x, GLdouble y)
+{
+   tess_vertex *v1, *v2;
+   GLuint i, vertex_cnt;
+   GLdouble xp1, yp1, xp2, yp2;
+   GLboolean tst;
+
+   tst = GL_FALSE;
+   v1 = contour->vertices;
+   v2 = contour->vertices->previous;
+   for (i = 0, vertex_cnt = contour->vertex_cnt; i < vertex_cnt; i++) {
+      xp1 = v1->x;
+      yp1 = v1->y;
+      xp2 = v2->x;
+      yp2 = v2->y;
+      if ((((yp1 <= y) && (y < yp2)) || ((yp2 <= y) && (y < yp1))) &&
+         (x < (xp2 - xp1) * (y - yp1) / (yp2 - yp1) + xp1))
+        tst = (tst == GL_FALSE ? GL_TRUE : GL_FALSE);
+      v2 = v1;
+      v1 = v1->next;
+   }
+   return tst;
+}
+
+static GLenum
+contours_overlap(tess_contour * contour, tess_polygon * polygon)
+{
+   tess_vertex *vertex1, *vertex2;
+   GLuint vertex1_cnt, vertex2_cnt, i, j;
+   GLenum test;
+
+   vertex1 = contour->vertices;
+   vertex2 = polygon->vertices;
+   vertex1_cnt = contour->vertex_cnt;
+   vertex2_cnt = polygon->vertex_cnt;
+   for (i = 0; i < vertex1_cnt; vertex1 = vertex1->next, i++) {
+      for (j = 0; j < vertex2_cnt; vertex2 = vertex2->next, j++)
+        if ((test = edge_edge_intersect(vertex1, vertex1->next, vertex2,
+                                        vertex2->next)) != GLU_NO_ERROR)
+           return test;
+   }
+   return GLU_NO_ERROR;
+}
+
+static void
+add_new_exterior(GLUtriangulatorObj * tobj, tess_contour * contour)
+{
+   contour->type = GLU_EXTERIOR;
+   contour->next = NULL;
+   contour->previous = tobj->last_contour;
+   tobj->last_contour->next = contour;
+   tobj->last_contour = contour;
+}
+
+static void
+add_new_interior(GLUtriangulatorObj * tobj,
+                tess_contour * outer, tess_contour * contour)
+{
+   contour->type = GLU_INTERIOR;
+   contour->next = outer->next;
+   contour->previous = outer;
+   if (outer->next != NULL)
+      outer->next->previous = contour;
+   outer->next = contour;
+   if (tobj->last_contour == outer)
+      tobj->last_contour = contour;
+}
+
+static void
+add_interior_with_hierarchy_check(GLUtriangulatorObj * tobj,
+                                 tess_contour * outer,
+                                 tess_contour * contour)
+{
+   tess_contour *ptr;
+
+   /* for all interiors of outer check if they are interior of contour */
+   /* if so, change that interior to exterior and move it of of the */
+   /* interior sequence */
+   if (outer->next != NULL && outer->next->type == GLU_INTERIOR) {
+      GLenum test;
+
+      for (ptr = outer->next; ptr != NULL && ptr->type == GLU_INTERIOR;
+          ptr = ptr->next) {
+        test = is_contour_contained_in(ptr, contour);
+        switch (test) {
+        case GLU_INTERIOR:
+           /* contour is contained in one of the interiors */
+           /* check if possibly contained in other exteriors */
+           /* move ptr to first EXTERIOR */
+           for (; ptr != NULL && ptr->type == GLU_INTERIOR; ptr = ptr->next);
+           if (ptr == NULL)
+              /* another exterior */
+              add_new_exterior(tobj, contour);
+           else
+              add_exterior_with_check(tobj, ptr, contour);
+           return;
+        case GLU_EXTERIOR:
+           /* one of the interiors is contained in the contour */
+           /* change it to EXTERIOR, and shift it away from the */
+           /* interior sequence */
+           shift_interior_to_exterior(tobj, ptr);
+           break;
+        case GLU_NO_ERROR:
+           /* disjoint */
+           break;
+        default:
+           abort();
+        }
+      }
+   }
+   /* add contour to the interior sequence */
+   add_new_interior(tobj, outer, contour);
+}
+
+static void
+reverse_hierarchy_and_add_exterior(GLUtriangulatorObj * tobj,
+                                  tess_contour * outer,
+                                  tess_contour * contour)
+{
+   tess_contour *ptr;
+
+   /* reverse INTERIORS to EXTERIORS */
+   /* any INTERIORS? */
+   if (outer->next != NULL && outer->next->type == GLU_INTERIOR)
+      for (ptr = outer->next; ptr != NULL && ptr->type == GLU_INTERIOR;
+          ptr = ptr->next) ptr->type = GLU_EXTERIOR;
+   /* the outer now becomes inner */
+   outer->type = GLU_INTERIOR;
+   /* contour is the EXTERIOR */
+   contour->next = outer;
+   if (tobj->contours == outer) {
+      /* first contour beeing reversed */
+      contour->previous = NULL;
+      tobj->contours = contour;
+   }
+   else {
+      outer->previous->next = contour;
+      contour->previous = outer->previous;
+   }
+   outer->previous = contour;
+}
+
+static void
+shift_interior_to_exterior(GLUtriangulatorObj * tobj, tess_contour * contour)
+{
+   contour->previous->next = contour->next;
+   if (contour->next != NULL)
+      contour->next->previous = contour->previous;
+   else
+      tobj->last_contour = contour->previous;
+}
+
+static void
+add_exterior_with_check(GLUtriangulatorObj * tobj,
+                       tess_contour * outer, tess_contour * contour)
+{
+   GLenum test;
+
+   /* this contour might be interior to further exteriors - check */
+   /* if not, just add as a new exterior */
+   for (; outer != NULL && outer->type == GLU_EXTERIOR; outer = outer->next) {
+      test = is_contour_contained_in(outer, contour);
+      switch (test) {
+      case GLU_INTERIOR:
+        /* now we have to check if contour is inside interiors */
+        /* or not */
+        /* any interiors? */
+        if (outer->next != NULL && outer->next->type == GLU_INTERIOR) {
+           /* for all interior, check if inside any of them */
+           /* if not inside any of interiors, its another */
+           /* interior */
+           /* or it may contain some interiors, then change */
+           /* the contained interiors to exterior ones */
+           add_interior_with_hierarchy_check(tobj, outer, contour);
+        }
+        else {
+           /* not in interior, add as new interior contour */
+           add_new_interior(tobj, outer, contour);
+        }
+        return;
+      case GLU_NO_ERROR:
+        /* disjoint */
+        break;
+      default:
+        abort();
+      }
+   }
+   /* add contour to the exterior sequence */
+   add_new_exterior(tobj, contour);
+}
+
+void
+tess_handle_holes(GLUtriangulatorObj * tobj)
+{
+   tess_contour *contour, *hole;
+   GLenum exterior_orientation;
+
+   /* verify hole orientation */
+   for (contour = tobj->contours; contour != NULL;) {
+      exterior_orientation = contour->orientation;
+      for (contour = contour->next;
+          contour != NULL && contour->type == GLU_INTERIOR;
+          contour = contour->next) {
+        if (contour->orientation == exterior_orientation) {
+           tess_call_user_error(tobj, GLU_TESS_ERROR5);
+           return;
+        }
+      }
+   }
+   /* now cut-out holes */
+   for (contour = tobj->contours; contour != NULL;) {
+      hole = contour->next;
+      while (hole != NULL && hole->type == GLU_INTERIOR) {
+        if (cut_out_hole(tobj, contour, hole) == GLU_ERROR)
+           return;
+        hole = contour->next;
+      }
+      contour = contour->next;
+   }
+}
+
+static GLenum
+cut_out_hole(GLUtriangulatorObj * tobj,
+            tess_contour * contour, tess_contour * hole)
+{
+   tess_contour *tmp_hole;
+   tess_vertex *v1, *v2, *tmp_vertex;
+   GLuint vertex1_cnt, vertex2_cnt, tmp_vertex_cnt;
+   GLuint i, j, k;
+   GLenum test = 0;
+
+   /* find an edge connecting contour and hole not intersecting any other */
+   /* edge belonging to either the contour or any of the other holes */
+   for (v1 = contour->vertices, vertex1_cnt = contour->vertex_cnt, i = 0;
+       i < vertex1_cnt; i++, v1 = v1->next) {
+      for (v2 = hole->vertices, vertex2_cnt = hole->vertex_cnt, j = 0;
+          j < vertex2_cnt; j++, v2 = v2->next) {
+        /* does edge (v1,v2) intersect any edge of contour */
+        for (tmp_vertex = contour->vertices, tmp_vertex_cnt =
+             contour->vertex_cnt, k = 0; k < tmp_vertex_cnt;
+             tmp_vertex = tmp_vertex->next, k++) {
+           /* skip edge tests for edges directly connected */
+           if (v1 == tmp_vertex || v1 == tmp_vertex->next)
+              continue;
+           test = edge_edge_intersect(v1, v2, tmp_vertex, tmp_vertex->next);
+           if (test != GLU_NO_ERROR)
+              break;
+        }
+        if (test == GLU_NO_ERROR) {
+           /* does edge (v1,v2) intersect any edge of hole */
+           for (tmp_vertex = hole->vertices,
+                tmp_vertex_cnt = hole->vertex_cnt, k = 0;
+                k < tmp_vertex_cnt; tmp_vertex = tmp_vertex->next, k++) {
+              /* skip edge tests for edges directly connected */
+              if (v2 == tmp_vertex || v2 == tmp_vertex->next)
+                 continue;
+              test =
+                 edge_edge_intersect(v1, v2, tmp_vertex, tmp_vertex->next);
+              if (test != GLU_NO_ERROR)
+                 break;
+           }
+           if (test == GLU_NO_ERROR) {
+              /* does edge (v1,v2) intersect any other hole? */
+              for (tmp_hole = hole->next;
+                   tmp_hole != NULL && tmp_hole->type == GLU_INTERIOR;
+                   tmp_hole = tmp_hole->next) {
+                 /* does edge (v1,v2) intersect any edge of hole */
+                 for (tmp_vertex = tmp_hole->vertices,
+                      tmp_vertex_cnt = tmp_hole->vertex_cnt, k = 0;
+                      k < tmp_vertex_cnt; tmp_vertex = tmp_vertex->next, k++) {
+                    test = edge_edge_intersect(v1, v2, tmp_vertex,
+                                               tmp_vertex->next);
+                    if (test != GLU_NO_ERROR)
+                       break;
+                 }
+                 if (test != GLU_NO_ERROR)
+                    break;
+              }
+           }
+        }
+        if (test == GLU_NO_ERROR) {
+           /* edge (v1,v2) is good for eliminating the hole */
+           if (merge_hole_with_contour(tobj, contour, hole, v1, v2)
+               == GLU_NO_ERROR)
+              return GLU_NO_ERROR;
+           else
+              return GLU_ERROR;
+        }
+      }
+   }
+   /* other holes are blocking all possible connections of hole */
+   /* with contour, we shift this hole as the last hole and retry */
+   for (tmp_hole = hole;
+       tmp_hole != NULL && tmp_hole->type == GLU_INTERIOR;
+       tmp_hole = tmp_hole->next);
+   contour->next = hole->next;
+   hole->next->previous = contour;
+   if (tmp_hole == NULL) {
+      /* last EXTERIOR contour, shift hole as last contour */
+      hole->next = NULL;
+      hole->previous = tobj->last_contour;
+      tobj->last_contour->next = hole;
+      tobj->last_contour = hole;
+   }
+   else {
+      tmp_hole->previous->next = hole;
+      hole->previous = tmp_hole->previous;
+      tmp_hole->previous = hole;
+      hole->next = tmp_hole;
+   }
+   hole = contour->next;
+   /* try once again - recurse */
+   return cut_out_hole(tobj, contour, hole);
+}
+
+static GLenum
+merge_hole_with_contour(GLUtriangulatorObj * tobj,
+                       tess_contour * contour,
+                       tess_contour * hole,
+                       tess_vertex * v1, tess_vertex * v2)
+{
+   tess_vertex *v1_new, *v2_new;
+
+   /* make copies of v1 and v2, place them respectively after their originals */
+   if ((v1_new = (tess_vertex *) malloc(sizeof(tess_vertex))) == NULL) {
+      tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
+      return GLU_ERROR;
+   }
+   if ((v2_new = (tess_vertex *) malloc(sizeof(tess_vertex))) == NULL) {
+      tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
+      return GLU_ERROR;
+   }
+   v1_new->edge_flag = GL_TRUE;
+   v1_new->data = v1->data;
+   v1_new->location[0] = v1->location[0];
+   v1_new->location[1] = v1->location[1];
+   v1_new->location[2] = v1->location[2];
+   v1_new->x = v1->x;
+   v1_new->y = v1->y;
+   v1_new->shadow_vertex = v1;
+   v1->shadow_vertex = v1_new;
+   v1_new->next = v1->next;
+   v1_new->previous = v1;
+   v1->next->previous = v1_new;
+   v1->next = v1_new;
+   v2_new->edge_flag = GL_TRUE;
+   v2_new->data = v2->data;
+   v2_new->location[0] = v2->location[0];
+   v2_new->location[1] = v2->location[1];
+   v2_new->location[2] = v2->location[2];
+   v2_new->x = v2->x;
+   v2_new->y = v2->y;
+   v2_new->shadow_vertex = v2;
+   v2->shadow_vertex = v2_new;
+   v2_new->next = v2->next;
+   v2_new->previous = v2;
+   v2->next->previous = v2_new;
+   v2->next = v2_new;
+   /* link together the two lists */
+   v1->next = v2_new;
+   v2_new->previous = v1;
+   v2->next = v1_new;
+   v1_new->previous = v2;
+   /* update the vertex count of the contour */
+   contour->vertex_cnt += hole->vertex_cnt + 2;
+   /* remove the INTERIOR contour */
+   contour->next = hole->next;
+   if (hole->next != NULL)
+      hole->next->previous = contour;
+   free(hole);
+   /* update tobj structure */
+   --(tobj->contour_cnt);
+   if (contour->last_vertex == v1)
+      contour->last_vertex = v1_new;
+   /* mark two vertices with edge_flag */
+   v2->edge_flag = GL_FALSE;
+   v1->edge_flag = GL_FALSE;
+   return GLU_NO_ERROR;
+}
diff --git a/src/glu/mini/project.c b/src/glu/mini/project.c
new file mode 100644 (file)
index 0000000..a2747de
--- /dev/null
@@ -0,0 +1,402 @@
+/* $Id: project.c,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.3
+ * Copyright (C) 1995-2000  Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "gluP.h"
+#endif
+
+
+/*
+ * This code was contributed by Marc Buffat (buffat@mecaflu.ec-lyon.fr).
+ * Thanks Marc!!!
+ */
+
+
+
+/* implementation de gluProject et gluUnproject */
+/* M. Buffat 17/2/95 */
+
+
+
+/*
+ * Transform a point (column vector) by a 4x4 matrix.  I.e.  out = m * in
+ * Input:  m - the 4x4 matrix
+ *         in - the 4x1 vector
+ * Output:  out - the resulting 4x1 vector.
+ */
+static void
+transform_point(GLdouble out[4], const GLdouble m[16], const GLdouble in[4])
+{
+#define M(row,col)  m[col*4+row]
+   out[0] =
+      M(0, 0) * in[0] + M(0, 1) * in[1] + M(0, 2) * in[2] + M(0, 3) * in[3];
+   out[1] =
+      M(1, 0) * in[0] + M(1, 1) * in[1] + M(1, 2) * in[2] + M(1, 3) * in[3];
+   out[2] =
+      M(2, 0) * in[0] + M(2, 1) * in[1] + M(2, 2) * in[2] + M(2, 3) * in[3];
+   out[3] =
+      M(3, 0) * in[0] + M(3, 1) * in[1] + M(3, 2) * in[2] + M(3, 3) * in[3];
+#undef M
+}
+
+
+
+
+/*
+ * Perform a 4x4 matrix multiplication  (product = a x b).
+ * Input:  a, b - matrices to multiply
+ * Output:  product - product of a and b
+ */
+static void
+matmul(GLdouble * product, const GLdouble * a, const GLdouble * b)
+{
+   /* This matmul was contributed by Thomas Malik */
+   GLdouble temp[16];
+   GLint i;
+
+#define A(row,col)  a[(col<<2)+row]
+#define B(row,col)  b[(col<<2)+row]
+#define T(row,col)  temp[(col<<2)+row]
+
+   /* i-te Zeile */
+   for (i = 0; i < 4; i++) {
+      T(i, 0) =
+        A(i, 0) * B(0, 0) + A(i, 1) * B(1, 0) + A(i, 2) * B(2, 0) + A(i,
+                                                                      3) *
+        B(3, 0);
+      T(i, 1) =
+        A(i, 0) * B(0, 1) + A(i, 1) * B(1, 1) + A(i, 2) * B(2, 1) + A(i,
+                                                                      3) *
+        B(3, 1);
+      T(i, 2) =
+        A(i, 0) * B(0, 2) + A(i, 1) * B(1, 2) + A(i, 2) * B(2, 2) + A(i,
+                                                                      3) *
+        B(3, 2);
+      T(i, 3) =
+        A(i, 0) * B(0, 3) + A(i, 1) * B(1, 3) + A(i, 2) * B(2, 3) + A(i,
+                                                                      3) *
+        B(3, 3);
+   }
+
+#undef A
+#undef B
+#undef T
+   MEMCPY(product, temp, 16 * sizeof(GLdouble));
+}
+
+
+
+/*
+ * Compute inverse of 4x4 transformation matrix.
+ * Code contributed by Jacques Leroy jle@star.be
+ * Return GL_TRUE for success, GL_FALSE for failure (singular matrix)
+ */
+static GLboolean
+invert_matrix(const GLdouble * m, GLdouble * out)
+{
+/* NB. OpenGL Matrices are COLUMN major. */
+#define SWAP_ROWS(a, b) { GLdouble *_tmp = a; (a)=(b); (b)=_tmp; }
+#define MAT(m,r,c) (m)[(c)*4+(r)]
+
+   GLdouble wtmp[4][8];
+   GLdouble m0, m1, m2, m3, s;
+   GLdouble *r0, *r1, *r2, *r3;
+
+   r0 = wtmp[0], r1 = wtmp[1], r2 = wtmp[2], r3 = wtmp[3];
+
+   r0[0] = MAT(m, 0, 0), r0[1] = MAT(m, 0, 1),
+      r0[2] = MAT(m, 0, 2), r0[3] = MAT(m, 0, 3),
+      r0[4] = 1.0, r0[5] = r0[6] = r0[7] = 0.0,
+      r1[0] = MAT(m, 1, 0), r1[1] = MAT(m, 1, 1),
+      r1[2] = MAT(m, 1, 2), r1[3] = MAT(m, 1, 3),
+      r1[5] = 1.0, r1[4] = r1[6] = r1[7] = 0.0,
+      r2[0] = MAT(m, 2, 0), r2[1] = MAT(m, 2, 1),
+      r2[2] = MAT(m, 2, 2), r2[3] = MAT(m, 2, 3),
+      r2[6] = 1.0, r2[4] = r2[5] = r2[7] = 0.0,
+      r3[0] = MAT(m, 3, 0), r3[1] = MAT(m, 3, 1),
+      r3[2] = MAT(m, 3, 2), r3[3] = MAT(m, 3, 3),
+      r3[7] = 1.0, r3[4] = r3[5] = r3[6] = 0.0;
+
+   /* choose pivot - or die */
+   if (fabs(r3[0]) > fabs(r2[0]))
+      SWAP_ROWS(r3, r2);
+   if (fabs(r2[0]) > fabs(r1[0]))
+      SWAP_ROWS(r2, r1);
+   if (fabs(r1[0]) > fabs(r0[0]))
+      SWAP_ROWS(r1, r0);
+   if (0.0 == r0[0])
+      return GL_FALSE;
+
+   /* eliminate first variable     */
+   m1 = r1[0] / r0[0];
+   m2 = r2[0] / r0[0];
+   m3 = r3[0] / r0[0];
+   s = r0[1];
+   r1[1] -= m1 * s;
+   r2[1] -= m2 * s;
+   r3[1] -= m3 * s;
+   s = r0[2];
+   r1[2] -= m1 * s;
+   r2[2] -= m2 * s;
+   r3[2] -= m3 * s;
+   s = r0[3];
+   r1[3] -= m1 * s;
+   r2[3] -= m2 * s;
+   r3[3] -= m3 * s;
+   s = r0[4];
+   if (s != 0.0) {
+      r1[4] -= m1 * s;
+      r2[4] -= m2 * s;
+      r3[4] -= m3 * s;
+   }
+   s = r0[5];
+   if (s != 0.0) {
+      r1[5] -= m1 * s;
+      r2[5] -= m2 * s;
+      r3[5] -= m3 * s;
+   }
+   s = r0[6];
+   if (s != 0.0) {
+      r1[6] -= m1 * s;
+      r2[6] -= m2 * s;
+      r3[6] -= m3 * s;
+   }
+   s = r0[7];
+   if (s != 0.0) {
+      r1[7] -= m1 * s;
+      r2[7] -= m2 * s;
+      r3[7] -= m3 * s;
+   }
+
+   /* choose pivot - or die */
+   if (fabs(r3[1]) > fabs(r2[1]))
+      SWAP_ROWS(r3, r2);
+   if (fabs(r2[1]) > fabs(r1[1]))
+      SWAP_ROWS(r2, r1);
+   if (0.0 == r1[1])
+      return GL_FALSE;
+
+   /* eliminate second variable */
+   m2 = r2[1] / r1[1];
+   m3 = r3[1] / r1[1];
+   r2[2] -= m2 * r1[2];
+   r3[2] -= m3 * r1[2];
+   r2[3] -= m2 * r1[3];
+   r3[3] -= m3 * r1[3];
+   s = r1[4];
+   if (0.0 != s) {
+      r2[4] -= m2 * s;
+      r3[4] -= m3 * s;
+   }
+   s = r1[5];
+   if (0.0 != s) {
+      r2[5] -= m2 * s;
+      r3[5] -= m3 * s;
+   }
+   s = r1[6];
+   if (0.0 != s) {
+      r2[6] -= m2 * s;
+      r3[6] -= m3 * s;
+   }
+   s = r1[7];
+   if (0.0 != s) {
+      r2[7] -= m2 * s;
+      r3[7] -= m3 * s;
+   }
+
+   /* choose pivot - or die */
+   if (fabs(r3[2]) > fabs(r2[2]))
+      SWAP_ROWS(r3, r2);
+   if (0.0 == r2[2])
+      return GL_FALSE;
+
+   /* eliminate third variable */
+   m3 = r3[2] / r2[2];
+   r3[3] -= m3 * r2[3], r3[4] -= m3 * r2[4],
+      r3[5] -= m3 * r2[5], r3[6] -= m3 * r2[6], r3[7] -= m3 * r2[7];
+
+   /* last check */
+   if (0.0 == r3[3])
+      return GL_FALSE;
+
+   s = 1.0 / r3[3];            /* now back substitute row 3 */
+   r3[4] *= s;
+   r3[5] *= s;
+   r3[6] *= s;
+   r3[7] *= s;
+
+   m2 = r2[3];                 /* now back substitute row 2 */
+   s = 1.0 / r2[2];
+   r2[4] = s * (r2[4] - r3[4] * m2), r2[5] = s * (r2[5] - r3[5] * m2),
+      r2[6] = s * (r2[6] - r3[6] * m2), r2[7] = s * (r2[7] - r3[7] * m2);
+   m1 = r1[3];
+   r1[4] -= r3[4] * m1, r1[5] -= r3[5] * m1,
+      r1[6] -= r3[6] * m1, r1[7] -= r3[7] * m1;
+   m0 = r0[3];
+   r0[4] -= r3[4] * m0, r0[5] -= r3[5] * m0,
+      r0[6] -= r3[6] * m0, r0[7] -= r3[7] * m0;
+
+   m1 = r1[2];                 /* now back substitute row 1 */
+   s = 1.0 / r1[1];
+   r1[4] = s * (r1[4] - r2[4] * m1), r1[5] = s * (r1[5] - r2[5] * m1),
+      r1[6] = s * (r1[6] - r2[6] * m1), r1[7] = s * (r1[7] - r2[7] * m1);
+   m0 = r0[2];
+   r0[4] -= r2[4] * m0, r0[5] -= r2[5] * m0,
+      r0[6] -= r2[6] * m0, r0[7] -= r2[7] * m0;
+
+   m0 = r0[1];                 /* now back substitute row 0 */
+   s = 1.0 / r0[0];
+   r0[4] = s * (r0[4] - r1[4] * m0), r0[5] = s * (r0[5] - r1[5] * m0),
+      r0[6] = s * (r0[6] - r1[6] * m0), r0[7] = s * (r0[7] - r1[7] * m0);
+
+   MAT(out, 0, 0) = r0[4];
+   MAT(out, 0, 1) = r0[5], MAT(out, 0, 2) = r0[6];
+   MAT(out, 0, 3) = r0[7], MAT(out, 1, 0) = r1[4];
+   MAT(out, 1, 1) = r1[5], MAT(out, 1, 2) = r1[6];
+   MAT(out, 1, 3) = r1[7], MAT(out, 2, 0) = r2[4];
+   MAT(out, 2, 1) = r2[5], MAT(out, 2, 2) = r2[6];
+   MAT(out, 2, 3) = r2[7], MAT(out, 3, 0) = r3[4];
+   MAT(out, 3, 1) = r3[5], MAT(out, 3, 2) = r3[6];
+   MAT(out, 3, 3) = r3[7];
+
+   return GL_TRUE;
+
+#undef MAT
+#undef SWAP_ROWS
+}
+
+
+
+/* projection du point (objx,objy,obz) sur l'ecran (winx,winy,winz) */
+GLint GLAPIENTRY
+gluProject(GLdouble objx, GLdouble objy, GLdouble objz,
+          const GLdouble model[16], const GLdouble proj[16],
+          const GLint viewport[4],
+          GLdouble * winx, GLdouble * winy, GLdouble * winz)
+{
+   /* matrice de transformation */
+   GLdouble in[4], out[4];
+
+   /* initilise la matrice et le vecteur a transformer */
+   in[0] = objx;
+   in[1] = objy;
+   in[2] = objz;
+   in[3] = 1.0;
+   transform_point(out, model, in);
+   transform_point(in, proj, out);
+
+   /* d'ou le resultat normalise entre -1 et 1 */
+   if (in[3] == 0.0)
+      return GL_FALSE;
+
+   in[0] /= in[3];
+   in[1] /= in[3];
+   in[2] /= in[3];
+
+   /* en coordonnees ecran */
+   *winx = viewport[0] + (1 + in[0]) * viewport[2] / 2;
+   *winy = viewport[1] + (1 + in[1]) * viewport[3] / 2;
+   /* entre 0 et 1 suivant z */
+   *winz = (1 + in[2]) / 2;
+   return GL_TRUE;
+}
+
+
+
+/* transformation du point ecran (winx,winy,winz) en point objet */
+GLint GLAPIENTRY
+gluUnProject(GLdouble winx, GLdouble winy, GLdouble winz,
+            const GLdouble model[16], const GLdouble proj[16],
+            const GLint viewport[4],
+            GLdouble * objx, GLdouble * objy, GLdouble * objz)
+{
+   /* matrice de transformation */
+   GLdouble m[16], A[16];
+   GLdouble in[4], out[4];
+
+   /* transformation coordonnees normalisees entre -1 et 1 */
+   in[0] = (winx - viewport[0]) * 2 / viewport[2] - 1.0;
+   in[1] = (winy - viewport[1]) * 2 / viewport[3] - 1.0;
+   in[2] = 2 * winz - 1.0;
+   in[3] = 1.0;
+
+   /* calcul transformation inverse */
+   matmul(A, proj, model);
+   invert_matrix(A, m);
+
+   /* d'ou les coordonnees objets */
+   transform_point(out, m, in);
+   if (out[3] == 0.0)
+      return GL_FALSE;
+   *objx = out[0] / out[3];
+   *objy = out[1] / out[3];
+   *objz = out[2] / out[3];
+   return GL_TRUE;
+}
+
+
+/*
+ * New in GLU 1.3
+ * This is like gluUnProject but also takes near and far DepthRange values.
+ */
+#ifdef GLU_VERSION_1_3
+GLint GLAPIENTRY
+gluUnProject4(GLdouble winx, GLdouble winy, GLdouble winz, GLdouble clipw,
+             const GLdouble modelMatrix[16],
+             const GLdouble projMatrix[16],
+             const GLint viewport[4],
+             GLclampd nearZ, GLclampd farZ,
+             GLdouble * objx, GLdouble * objy, GLdouble * objz,
+             GLdouble * objw)
+{
+   /* matrice de transformation */
+   GLdouble m[16], A[16];
+   GLdouble in[4], out[4];
+   GLdouble z = nearZ + winz * (farZ - nearZ);
+
+   /* transformation coordonnees normalisees entre -1 et 1 */
+   in[0] = (winx - viewport[0]) * 2 / viewport[2] - 1.0;
+   in[1] = (winy - viewport[1]) * 2 / viewport[3] - 1.0;
+   in[2] = 2.0 * z - 1.0;
+   in[3] = clipw;
+
+   /* calcul transformation inverse */
+   matmul(A, projMatrix, modelMatrix);
+   invert_matrix(A, m);
+
+   /* d'ou les coordonnees objets */
+   transform_point(out, m, in);
+   if (out[3] == 0.0)
+      return GL_FALSE;
+   *objx = out[0] / out[3];
+   *objy = out[1] / out[3];
+   *objz = out[2] / out[3];
+   *objw = out[3];
+   return GL_TRUE;
+}
+#endif
diff --git a/src/glu/mini/quadric.c b/src/glu/mini/quadric.c
new file mode 100644 (file)
index 0000000..015552e
--- /dev/null
@@ -0,0 +1,774 @@
+/* $Id: quadric.c,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.3
+ * Copyright (C) 1999-2000  Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+/* TODO:
+ *   texture coordinate support
+ *   flip normals according to orientation
+ *   there's still some inside/outside orientation bugs in possibly all
+ *     but the sphere function
+ */
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "gluP.h"
+#endif
+
+
+
+#ifndef M_PI
+#  define M_PI (3.1415926)
+#endif
+
+
+/*
+ * Convert degrees to radians:
+ */
+#define DEG_TO_RAD(A)   ((A)*(M_PI/180.0))
+
+
+/*
+ * Sin and Cos for degree angles:
+ */
+#define SIND( A )   sin( (A)*(M_PI/180.0) )
+#define COSD( A)    cos( (A)*(M_PI/180.0) )
+
+
+/*
+ * Texture coordinates if texture flag is set
+ */
+#define TXTR_COORD(x,y)    if (qobj->TextureFlag) glTexCoord2f(x,y);
+
+
+
+struct GLUquadric
+{
+   GLenum DrawStyle;           /* GLU_FILL, LINE, SILHOUETTE, or POINT */
+   GLenum Orientation;         /* GLU_INSIDE or GLU_OUTSIDE */
+   GLboolean TextureFlag;      /* Generate texture coords? */
+   GLenum Normals;             /* GLU_NONE, GLU_FLAT, or GLU_SMOOTH */
+   void (GLCALLBACK * ErrorFunc) (GLenum err); /* Error handler callback function */
+};
+
+
+
+/*
+ * Process a GLU error.
+ */
+static void
+quadric_error(GLUquadricObj * qobj, GLenum error, const char *msg)
+{
+   /* Call the error call back function if any */
+   if (qobj->ErrorFunc) {
+      (*qobj->ErrorFunc) (error);
+   }
+   /* Print a message to stdout if MESA_DEBUG variable is defined */
+   if (getenv("MESA_DEBUG")) {
+      fprintf(stderr, "GLUError: %s: %s\n", (char *) gluErrorString(error),
+             msg);
+   }
+}
+
+
+
+
+GLUquadricObj *GLAPIENTRY
+gluNewQuadric(void)
+{
+   GLUquadricObj *q;
+
+   q = (GLUquadricObj *) malloc(sizeof(struct GLUquadric));
+   if (q) {
+      q->DrawStyle = GLU_FILL;
+      q->Orientation = GLU_OUTSIDE;
+      q->TextureFlag = GL_FALSE;
+      q->Normals = GLU_SMOOTH;
+      q->ErrorFunc = NULL;
+   }
+   return q;
+}
+
+
+
+void GLAPIENTRY
+gluDeleteQuadric(GLUquadricObj * state)
+{
+   if (state) {
+      free((void *) state);
+   }
+}
+
+
+
+/*
+ * Set the drawing style to be GLU_FILL, GLU_LINE, GLU_SILHOUETTE,
+ * or GLU_POINT.
+ */
+void GLAPIENTRY
+gluQuadricDrawStyle(GLUquadricObj * quadObject, GLenum drawStyle)
+{
+   if (quadObject && (drawStyle == GLU_FILL || drawStyle == GLU_LINE
+                     || drawStyle == GLU_SILHOUETTE
+                     || drawStyle == GLU_POINT)) {
+      quadObject->DrawStyle = drawStyle;
+   }
+   else {
+      quadric_error(quadObject, GLU_INVALID_ENUM, "qluQuadricDrawStyle");
+   }
+}
+
+
+
+/*
+ * Set the orientation to GLU_INSIDE or GLU_OUTSIDE.
+ */
+void GLAPIENTRY
+gluQuadricOrientation(GLUquadricObj * quadObject, GLenum orientation)
+{
+   if (quadObject
+       && (orientation == GLU_INSIDE || orientation == GLU_OUTSIDE)) {
+      quadObject->Orientation = orientation;
+   }
+   else {
+      quadric_error(quadObject, GLU_INVALID_ENUM, "qluQuadricOrientation");
+   }
+}
+
+
+
+/*
+ * Set the error handler callback function.
+ */
+void GLAPIENTRY
+gluQuadricCallback(GLUquadricObj * qobj,
+                  GLenum which, void (GLCALLBACK * fn) ())
+{
+   /*
+    * UGH, this is a mess!  I thought ANSI was a standard.
+    */
+   if (qobj && which == GLU_ERROR) {
+#ifdef __CYGWIN32__
+      qobj->ErrorFunc = (void (GLCALLBACKPCAST) (GLenum)) fn;
+#elif defined(OPENSTEP)
+      qobj->ErrorFunc = (void (*)(GLenum)) fn;
+#elif defined(_WIN32)
+      qobj->ErrorFunc = (void (GLCALLBACK *) (int)) fn;
+#elif defined(__STORM__)
+      qobj->ErrorFunc = (void (GLCALLBACK *) (GLenum)) fn;
+#elif defined(__BEOS__)
+      qobj->ErrorFunc = (void (*)(GLenum)) fn;
+#else
+      qobj->ErrorFunc = (void (GLCALLBACK *) ()) fn;
+#endif
+   }
+}
+
+
+void GLAPIENTRY
+gluQuadricNormals(GLUquadricObj * quadObject, GLenum normals)
+{
+   if (quadObject
+       && (normals == GLU_NONE || normals == GLU_FLAT
+          || normals == GLU_SMOOTH)) {
+      quadObject->Normals = normals;
+   }
+}
+
+
+void GLAPIENTRY
+gluQuadricTexture(GLUquadricObj * quadObject, GLboolean textureCoords)
+{
+   if (quadObject) {
+      quadObject->TextureFlag = textureCoords;
+   }
+}
+
+
+
+
+/*
+ * Call glNormal3f after scaling normal to unit length.
+ */
+static void
+normal3f(GLfloat x, GLfloat y, GLfloat z)
+{
+}
+
+
+
+void GLAPIENTRY
+gluCylinder(GLUquadricObj * qobj,
+           GLdouble baseRadius, GLdouble topRadius,
+           GLdouble height, GLint slices, GLint stacks)
+{
+   GLdouble da, r, dr, dz;
+   GLfloat x, y, z, nz, nsign;
+   GLint i, j;
+
+   if (qobj->Orientation == GLU_INSIDE) {
+      nsign = -1.0;
+   }
+   else {
+      nsign = 1.0;
+   }
+
+   da = 2.0 * M_PI / slices;
+   dr = (topRadius - baseRadius) / stacks;
+   dz = height / stacks;
+   nz = (baseRadius - topRadius) / height;     /* Z component of normal vectors */
+
+   if (qobj->DrawStyle == GLU_POINT) {
+      glBegin(GL_POINTS);
+      for (i = 0; i < slices; i++) {
+        x = cos(i * da);
+        y = sin(i * da);
+        normal3f(x * nsign, y * nsign, nz * nsign);
+
+        z = 0.0;
+        r = baseRadius;
+        for (j = 0; j <= stacks; j++) {
+           glVertex3f(x * r, y * r, z);
+           z += dz;
+           r += dr;
+        }
+      }
+      glEnd();
+   }
+   else if (qobj->DrawStyle == GLU_LINE || qobj->DrawStyle == GLU_SILHOUETTE) {
+      /* Draw rings */
+      if (qobj->DrawStyle == GLU_LINE) {
+        z = 0.0;
+        r = baseRadius;
+        for (j = 0; j <= stacks; j++) {
+           glBegin(GL_LINE_LOOP);
+           for (i = 0; i < slices; i++) {
+              x = cos(i * da);
+              y = sin(i * da);
+              normal3f(x * nsign, y * nsign, nz * nsign);
+              glVertex3f(x * r, y * r, z);
+           }
+           glEnd();
+           z += dz;
+           r += dr;
+        }
+      }
+      else {
+        /* draw one ring at each end */
+        if (baseRadius != 0.0) {
+           glBegin(GL_LINE_LOOP);
+           for (i = 0; i < slices; i++) {
+              x = cos(i * da);
+              y = sin(i * da);
+              normal3f(x * nsign, y * nsign, nz * nsign);
+              glVertex3f(x * baseRadius, y * baseRadius, 0.0);
+           }
+           glEnd();
+           glBegin(GL_LINE_LOOP);
+           for (i = 0; i < slices; i++) {
+              x = cos(i * da);
+              y = sin(i * da);
+              normal3f(x * nsign, y * nsign, nz * nsign);
+              glVertex3f(x * topRadius, y * topRadius, height);
+           }
+           glEnd();
+        }
+      }
+      /* draw length lines */
+      glBegin(GL_LINES);
+      for (i = 0; i < slices; i++) {
+        x = cos(i * da);
+        y = sin(i * da);
+        normal3f(x * nsign, y * nsign, nz * nsign);
+        glVertex3f(x * baseRadius, y * baseRadius, 0.0);
+        glVertex3f(x * topRadius, y * topRadius, height);
+      }
+      glEnd();
+   }
+   else if (qobj->DrawStyle == GLU_FILL) {
+      GLfloat ds = 1.0 / slices;
+      GLfloat dt = 1.0 / stacks;
+      GLfloat t = 0.0;
+      z = 0.0;
+      r = baseRadius;
+      for (j = 0; j < stacks; j++) {
+        GLfloat s = 0.0;
+        glBegin(GL_QUAD_STRIP);
+        for (i = 0; i <= slices; i++) {
+           GLfloat x, y;
+           if (i == slices) {
+              x = sin(0.0);
+              y = cos(0.0);
+           }
+           else {
+              x = sin(i * da);
+              y = cos(i * da);
+           }
+           if (nsign == 1.0) {
+              normal3f(x * nsign, y * nsign, nz * nsign);
+              TXTR_COORD(s, t);
+              glVertex3f(x * r, y * r, z);
+              normal3f(x * nsign, y * nsign, nz * nsign);
+              TXTR_COORD(s, t + dt);
+              glVertex3f(x * (r + dr), y * (r + dr), z + dz);
+           }
+           else {
+              normal3f(x * nsign, y * nsign, nz * nsign);
+              TXTR_COORD(s, t);
+              glVertex3f(x * r, y * r, z);
+              normal3f(x * nsign, y * nsign, nz * nsign);
+              TXTR_COORD(s, t + dt);
+              glVertex3f(x * (r + dr), y * (r + dr), z + dz);
+           }
+           s += ds;
+        }                      /* for slices */
+        glEnd();
+        r += dr;
+        t += dt;
+        z += dz;
+      }                                /* for stacks */
+   }
+}
+
+
+
+
+
+void GLAPIENTRY
+gluSphere(GLUquadricObj * qobj, GLdouble radius, GLint slices, GLint stacks)
+{
+   GLfloat rho, drho, theta, dtheta;
+   GLfloat x, y, z;
+   GLfloat s, t, ds, dt;
+   GLint i, j, imin, imax;
+   GLboolean normals;
+   GLfloat nsign;
+
+   if (qobj->Normals == GLU_NONE) {
+      normals = GL_FALSE;
+   }
+   else {
+      normals = GL_TRUE;
+   }
+   if (qobj->Orientation == GLU_INSIDE) {
+      nsign = -1.0;
+   }
+   else {
+      nsign = 1.0;
+   }
+
+   drho = M_PI / (GLfloat) stacks;
+   dtheta = 2.0 * M_PI / (GLfloat) slices;
+
+   /* texturing: s goes from 0.0/0.25/0.5/0.75/1.0 at +y/+x/-y/-x/+y axis */
+   /* t goes from -1.0/+1.0 at z = -radius/+radius (linear along longitudes) */
+   /* cannot use triangle fan on texturing (s coord. at top/bottom tip varies) */
+
+   if (qobj->DrawStyle == GLU_FILL) {
+      if (!qobj->TextureFlag) {
+        /* draw +Z end as a triangle fan */
+        glBegin(GL_TRIANGLE_FAN);
+/*      glNormal3f(0.0, 0.0, 1.0); */
+        glVertex3f(0.0, 0.0, nsign * radius);
+        for (j = 0; j <= slices; j++) {
+           theta = (j == slices) ? 0.0 : j * dtheta;
+           x = -sin(theta) * sin(drho);
+           y = cos(theta) * sin(drho);
+           z = nsign * cos(drho);
+           glVertex3f(x * radius, y * radius, z * radius);
+        }
+        glEnd();
+      }
+
+      ds = 1.0 / slices;
+      dt = 1.0 / stacks;
+      t = 1.0;                 /* because loop now runs from 0 */
+      if (qobj->TextureFlag) {
+        imin = 0;
+        imax = stacks;
+      }
+      else {
+        imin = 1;
+        imax = stacks - 1;
+      }
+
+      /* draw intermediate stacks as quad strips */
+      for (i = imin; i < imax; i++) {
+        rho = i * drho;
+        glBegin(GL_QUAD_STRIP);
+        s = 0.0;
+        for (j = 0; j <= slices; j++) {
+           theta = (j == slices) ? 0.0 : j * dtheta;
+           x = -sin(theta) * sin(rho);
+           y = cos(theta) * sin(rho);
+           z = nsign * cos(rho);
+           TXTR_COORD(s, t);
+           glVertex3f(x * radius, y * radius, z * radius);
+           x = -sin(theta) * sin(rho + drho);
+           y = cos(theta) * sin(rho + drho);
+           z = nsign * cos(rho + drho);
+           TXTR_COORD(s, t - dt);
+           s += ds;
+           glVertex3f(x * radius, y * radius, z * radius);
+        }
+        glEnd();
+        t -= dt;
+      }
+
+      if (!qobj->TextureFlag) {
+        /* draw -Z end as a triangle fan */
+        glBegin(GL_TRIANGLE_FAN);
+        glVertex3f(0.0, 0.0, -radius * nsign);
+        rho = M_PI - drho;
+        s = 1.0;
+        t = dt;
+        for (j = slices; j >= 0; j--) {
+           theta = (j == slices) ? 0.0 : j * dtheta;
+           x = -sin(theta) * sin(rho);
+           y = cos(theta) * sin(rho);
+           z = nsign * cos(rho);
+           s -= ds;
+           glVertex3f(x * radius, y * radius, z * radius);
+        }
+        glEnd();
+      }
+   }
+   else if (qobj->DrawStyle == GLU_LINE || qobj->DrawStyle == GLU_SILHOUETTE) {
+      /* draw stack lines */
+      for (i = 1; i < stacks; i++) {   /* stack line at i==stacks-1 was missing here */
+        rho = i * drho;
+        glBegin(GL_LINE_LOOP);
+        for (j = 0; j < slices; j++) {
+           theta = j * dtheta;
+           x = cos(theta) * sin(rho);
+           y = sin(theta) * sin(rho);
+           z = cos(rho);
+           glVertex3f(x * radius, y * radius, z * radius);
+        }
+        glEnd();
+      }
+      /* draw slice lines */
+      for (j = 0; j < slices; j++) {
+        theta = j * dtheta;
+        glBegin(GL_LINE_STRIP);
+        for (i = 0; i <= stacks; i++) {
+           rho = i * drho;
+           x = cos(theta) * sin(rho);
+           y = sin(theta) * sin(rho);
+           z = cos(rho);
+           glVertex3f(x * radius, y * radius, z * radius);
+        }
+        glEnd();
+      }
+   }
+   else if (qobj->DrawStyle == GLU_POINT) {
+      /* top and bottom-most points */
+      glBegin(GL_POINTS);
+      glVertex3f(0.0, 0.0, radius);
+      glVertex3f(0.0, 0.0, -radius);
+
+      /* loop over stacks */
+      for (i = 1; i < stacks - 1; i++) {
+        rho = i * drho;
+        for (j = 0; j < slices; j++) {
+           theta = j * dtheta;
+           x = cos(theta) * sin(rho);
+           y = sin(theta) * sin(rho);
+           z = cos(rho);
+           glVertex3f(x * radius, y * radius, z * radius);
+        }
+      }
+      glEnd();
+   }
+
+}
+
+
+
+void GLAPIENTRY
+gluDisk(GLUquadricObj * qobj,
+       GLdouble innerRadius, GLdouble outerRadius, GLint slices, GLint loops)
+{
+   GLfloat da, dr;
+#if 0
+   GLdouble a, da;
+   GLfloat r, dr;
+   GLfloat x, y;
+   GLfloat r1, r2, dtc;
+   GLint s, l;
+#endif
+
+
+   da = 2.0 * M_PI / slices;
+   dr = (outerRadius - innerRadius) / (GLfloat) loops;
+
+   switch (qobj->DrawStyle) {
+   case GLU_FILL:
+      {
+        /* texture of a gluDisk is a cut out of the texture unit square
+         * x, y in [-outerRadius, +outerRadius]; s, t in [0, 1]
+         * (linear mapping)
+         */
+        GLfloat dtc = 2.0f * outerRadius;
+        GLfloat sa, ca;
+        GLfloat r1 = innerRadius;
+        GLint l;
+        for (l = 0; l < loops; l++) {
+           GLfloat r2 = r1 + dr;
+           if (qobj->Orientation == GLU_OUTSIDE) {
+              GLint s;
+              glBegin(GL_QUAD_STRIP);
+              for (s = 0; s <= slices; s++) {
+                 GLfloat a;
+                 if (s == slices)
+                    a = 0.0;
+                 else
+                    a = s * da;
+                 sa = sin(a);
+                 ca = cos(a);
+                 TXTR_COORD(0.5 + sa * r2 / dtc, 0.5 + ca * r2 / dtc);
+                 glVertex2f(r2 * sa, r2 * ca);
+                 TXTR_COORD(0.5 + sa * r1 / dtc, 0.5 + ca * r1 / dtc);
+                 glVertex2f(r1 * sa, r1 * ca);
+              }
+              glEnd();
+           }
+           else {
+              GLint s;
+              glBegin(GL_QUAD_STRIP);
+              for (s = slices; s >= 0; s--) {
+                 GLfloat a;
+                 if (s == slices)
+                    a = 0.0;
+                 else
+                    a = s * da;
+                 sa = sin(a);
+                 ca = cos(a);
+                 TXTR_COORD(0.5 - sa * r2 / dtc, 0.5 + ca * r2 / dtc);
+                 glVertex2f(r2 * sa, r2 * ca);
+                 TXTR_COORD(0.5 - sa * r1 / dtc, 0.5 + ca * r1 / dtc);
+                 glVertex2f(r1 * sa, r1 * ca);
+              }
+              glEnd();
+           }
+           r1 = r2;
+        }
+        break;
+      }
+   case GLU_LINE:
+      {
+        GLint l, s;
+        /* draw loops */
+        for (l = 0; l <= loops; l++) {
+           GLfloat r = innerRadius + l * dr;
+           glBegin(GL_LINE_LOOP);
+           for (s = 0; s < slices; s++) {
+              GLfloat a = s * da;
+              glVertex2f(r * sin(a), r * cos(a));
+           }
+           glEnd();
+        }
+        /* draw spokes */
+        for (s = 0; s < slices; s++) {
+           GLfloat a = s * da;
+           GLfloat x = sin(a);
+           GLfloat y = cos(a);
+           glBegin(GL_LINE_STRIP);
+           for (l = 0; l <= loops; l++) {
+              GLfloat r = innerRadius + l * dr;
+              glVertex2f(r * x, r * y);
+           }
+           glEnd();
+        }
+        break;
+      }
+   case GLU_POINT:
+      {
+        GLint s;
+        glBegin(GL_POINTS);
+        for (s = 0; s < slices; s++) {
+           GLfloat a = s * da;
+           GLfloat x = sin(a);
+           GLfloat y = cos(a);
+           GLint l;
+           for (l = 0; l <= loops; l++) {
+              GLfloat r = innerRadius * l * dr;
+              glVertex2f(r * x, r * y);
+           }
+        }
+        glEnd();
+        break;
+      }
+   case GLU_SILHOUETTE:
+      {
+        if (innerRadius != 0.0) {
+           GLfloat a;
+           glBegin(GL_LINE_LOOP);
+           for (a = 0.0; a < 2.0 * M_PI; a += da) {
+              GLfloat x = innerRadius * sin(a);
+              GLfloat y = innerRadius * cos(a);
+              glVertex2f(x, y);
+           }
+           glEnd();
+        }
+        {
+           GLfloat a;
+           glBegin(GL_LINE_LOOP);
+           for (a = 0; a < 2.0 * M_PI; a += da) {
+              GLfloat x = outerRadius * sin(a);
+              GLfloat y = outerRadius * cos(a);
+              glVertex2f(x, y);
+           }
+           glEnd();
+        }
+        break;
+      }
+   default:
+      abort();
+   }
+}
+
+
+
+void GLAPIENTRY
+gluPartialDisk(GLUquadricObj * qobj, GLdouble innerRadius,
+              GLdouble outerRadius, GLint slices, GLint loops,
+              GLdouble startAngle, GLdouble sweepAngle)
+{
+   if (qobj->DrawStyle == GLU_POINT) {
+      GLint loop, slice;
+      GLdouble radius, delta_radius;
+      GLdouble angle, delta_angle;
+      delta_radius = (outerRadius - innerRadius) / (loops - 1);
+      delta_angle = DEG_TO_RAD((sweepAngle) / (slices - 1));
+      glBegin(GL_POINTS);
+      radius = innerRadius;
+      for (loop = 0; loop < loops; loop++) {
+        angle = DEG_TO_RAD(startAngle);
+        for (slice = 0; slice < slices; slice++) {
+           glVertex2f(radius * sin(angle), radius * cos(angle));
+           angle += delta_angle;
+        }
+        radius += delta_radius;
+      }
+      glEnd();
+   }
+   else if (qobj->DrawStyle == GLU_LINE) {
+      GLint loop, slice;
+      GLdouble radius, delta_radius;
+      GLdouble angle, delta_angle;
+      delta_radius = (outerRadius - innerRadius) / loops;
+      delta_angle = DEG_TO_RAD(sweepAngle / slices);
+      /* draw rings */
+      radius = innerRadius;
+      for (loop = 0; loop < loops; loop++) {
+        angle = DEG_TO_RAD(startAngle);
+        glBegin(GL_LINE_STRIP);
+        for (slice = 0; slice <= slices; slice++) {
+           glVertex2f(radius * sin(angle), radius * cos(angle));
+           angle += delta_angle;
+        }
+        glEnd();
+        radius += delta_radius;
+      }
+      /* draw spokes */
+      angle = DEG_TO_RAD(startAngle);
+      for (slice = 0; slice <= slices; slice++) {
+        radius = innerRadius;
+        glBegin(GL_LINE_STRIP);
+        for (loop = 0; loop < loops; loop++) {
+           glVertex2f(radius * sin(angle), radius * cos(angle));
+           radius += delta_radius;
+        }
+        glEnd();
+        angle += delta_angle;
+      }
+   }
+   else if (qobj->DrawStyle == GLU_SILHOUETTE) {
+      GLint slice;
+      GLdouble angle, delta_angle;
+      delta_angle = DEG_TO_RAD(sweepAngle / slices);
+      /* draw outer ring */
+      glBegin(GL_LINE_STRIP);
+      angle = DEG_TO_RAD(startAngle);
+      for (slice = 0; slice <= slices; slice++) {
+        glVertex2f(outerRadius * sin(angle), outerRadius * cos(angle));
+        angle += delta_angle;
+      }
+      glEnd();
+      /* draw inner ring */
+      if (innerRadius > 0.0) {
+        glBegin(GL_LINE_STRIP);
+        angle = DEG_TO_RAD(startAngle);
+        for (slice = 0; slice < slices; slice++) {
+           glVertex2f(innerRadius * sin(angle), innerRadius * cos(angle));
+           angle += delta_angle;
+        }
+        glEnd();
+      }
+      /* draw spokes */
+      if (sweepAngle < 360.0) {
+        GLdouble stopAngle = startAngle + sweepAngle;
+        glBegin(GL_LINES);
+        glVertex2f(innerRadius * SIND(startAngle),
+                   innerRadius * COSD(startAngle));
+        glVertex2f(outerRadius * SIND(startAngle),
+                   outerRadius * COSD(startAngle));
+        glVertex2f(innerRadius * SIND(stopAngle),
+                   innerRadius * COSD(stopAngle));
+        glVertex2f(outerRadius * SIND(stopAngle),
+                   outerRadius * COSD(stopAngle));
+        glEnd();
+      }
+   }
+   else if (qobj->DrawStyle == GLU_FILL) {
+      GLint loop, slice;
+      GLdouble radius, delta_radius;
+      GLdouble angle, delta_angle;
+      delta_radius = (outerRadius - innerRadius) / loops;
+      delta_angle = DEG_TO_RAD(sweepAngle / slices);
+      radius = innerRadius;
+      for (loop = 0; loop < loops; loop++) {
+        glBegin(GL_QUAD_STRIP);
+        angle = DEG_TO_RAD(startAngle);
+        for (slice = 0; slice <= slices; slice++) {
+           if (qobj->Orientation == GLU_OUTSIDE) {
+              glVertex2f((radius + delta_radius) * sin(angle),
+                         (radius + delta_radius) * cos(angle));
+              glVertex2f(radius * sin(angle), radius * cos(angle));
+           }
+           else {
+              glVertex2f(radius * sin(angle), radius * cos(angle));
+              glVertex2f((radius + delta_radius) * sin(angle),
+                         (radius + delta_radius) * cos(angle));
+           }
+           angle += delta_angle;
+        }
+        glEnd();
+        radius += delta_radius;
+      }
+   }
+}
diff --git a/src/glu/mini/tess.c b/src/glu/mini/tess.c
new file mode 100644 (file)
index 0000000..1a38423
--- /dev/null
@@ -0,0 +1,328 @@
+/* $Id: tess.c,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.3
+ * Copyright (C) 1995-2000  Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+/*
+ * This file is part of the polygon tesselation code contributed by
+ * Bogdan Sikorski
+ */
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <math.h>
+#include <stdlib.h>
+#include "tess.h"
+#endif
+
+
+/*
+ * This is ugly, but seems the easiest way to do things to make the
+ * code work under YellowBox for Windows
+ */
+#if defined(OPENSTEP) && defined(CALLBACK)
+#undef CALLBACK
+#define CALLBACK
+#endif
+
+
+static void delete_contours(GLUtriangulatorObj *);
+
+#ifdef __CYGWIN32__
+#define _CALLBACK
+#else
+#define _CALLBACK GLCALLBACK
+#endif
+
+
+static void
+init_callbacks(tess_callbacks * callbacks)
+{
+   callbacks->begin = (void (_CALLBACK *) (GLenum)) 0;
+   callbacks->edgeFlag = (void (_CALLBACK *) (GLboolean)) 0;
+   callbacks->vertex = (void (_CALLBACK *) (void *)) 0;
+   callbacks->end = (void (_CALLBACK *) (void)) 0;
+   callbacks->error = (void (_CALLBACK *) (GLenum)) 0;
+}
+
+void
+tess_call_user_error(GLUtriangulatorObj * tobj, GLenum gluerr)
+{
+   if (tobj->error == GLU_NO_ERROR)
+      tobj->error = gluerr;
+   if (tobj->callbacks.error != NULL)
+      (tobj->callbacks.error) (gluerr);
+}
+
+GLUtriangulatorObj *GLAPIENTRY
+gluNewTess(void)
+{
+   GLUtriangulatorObj *tobj;
+
+   if ((tobj = (GLUtriangulatorObj *)
+       malloc(sizeof(struct GLUtesselator))) == NULL)
+      return NULL;
+   tobj->contours = tobj->last_contour = NULL;
+   init_callbacks(&tobj->callbacks);
+   tobj->error = GLU_NO_ERROR;
+   tobj->current_polygon = NULL;
+   tobj->contour_cnt = 0;
+   return tobj;
+}
+
+
+void GLAPIENTRY
+gluTessCallback(GLUtriangulatorObj * tobj, GLenum which,
+               void (GLCALLBACK * fn) ())
+{
+   switch (which) {
+   case GLU_BEGIN:
+      tobj->callbacks.begin = (void (_CALLBACK *) (GLenum)) fn;
+      break;
+   case GLU_EDGE_FLAG:
+      tobj->callbacks.edgeFlag = (void (_CALLBACK *) (GLboolean)) fn;
+      break;
+   case GLU_VERTEX:
+      tobj->callbacks.vertex = (void (_CALLBACK *) (void *)) fn;
+      break;
+   case GLU_END:
+      tobj->callbacks.end = (void (_CALLBACK *) (void)) fn;
+      break;
+   case GLU_ERROR:
+      tobj->callbacks.error = (void (_CALLBACK *) (GLenum)) fn;
+      break;
+   default:
+      tobj->error = GLU_INVALID_ENUM;
+      break;
+   }
+}
+
+
+
+void GLAPIENTRY
+gluDeleteTess(GLUtriangulatorObj * tobj)
+{
+   if (tobj->error == GLU_NO_ERROR && tobj->contour_cnt)
+      /* was gluEndPolygon called? */
+      tess_call_user_error(tobj, GLU_TESS_ERROR1);
+   /* delete all internal structures */
+   delete_contours(tobj);
+   free(tobj);
+}
+
+
+void GLAPIENTRY
+gluBeginPolygon(GLUtriangulatorObj * tobj)
+{
+/*
+       if(tobj->error!=GLU_NO_ERROR)
+               return;
+*/
+   tobj->error = GLU_NO_ERROR;
+   if (tobj->current_polygon != NULL) {
+      /* gluEndPolygon was not called */
+      tess_call_user_error(tobj, GLU_TESS_ERROR1);
+      /* delete all internal structures */
+      delete_contours(tobj);
+   }
+   else {
+      if ((tobj->current_polygon =
+          (tess_polygon *) malloc(sizeof(tess_polygon))) == NULL) {
+        tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
+        return;
+      }
+      tobj->current_polygon->vertex_cnt = 0;
+      tobj->current_polygon->vertices =
+        tobj->current_polygon->last_vertex = NULL;
+   }
+}
+
+
+void GLAPIENTRY
+gluEndPolygon(GLUtriangulatorObj * tobj)
+{
+   /*tess_contour *contour_ptr; */
+
+   /* there was an error */
+   if (tobj->error != GLU_NO_ERROR)
+      goto end;
+
+   /* check if gluBeginPolygon was called */
+   if (tobj->current_polygon == NULL) {
+      tess_call_user_error(tobj, GLU_TESS_ERROR2);
+      return;
+   }
+   tess_test_polygon(tobj);
+   /* there was an error */
+   if (tobj->error != GLU_NO_ERROR)
+      goto end;
+
+   /* any real contours? */
+   if (tobj->contour_cnt == 0) {
+      /* delete all internal structures */
+      delete_contours(tobj);
+      return;
+   }
+   tess_find_contour_hierarchies(tobj);
+   /* there was an error */
+   if (tobj->error != GLU_NO_ERROR)
+      goto end;
+
+   tess_handle_holes(tobj);
+   /* there was an error */
+   if (tobj->error != GLU_NO_ERROR)
+      goto end;
+
+   /* if no callbacks, nothing to do */
+   if (tobj->callbacks.begin != NULL && tobj->callbacks.vertex != NULL &&
+       tobj->callbacks.end != NULL) {
+      if (tobj->callbacks.edgeFlag == NULL)
+        tess_tesselate(tobj);
+      else
+        tess_tesselate_with_edge_flag(tobj);
+   }
+
+ end:
+   /* delete all internal structures */
+   delete_contours(tobj);
+}
+
+
+void GLAPIENTRY
+gluNextContour(GLUtriangulatorObj * tobj, GLenum type)
+{
+   if (tobj->error != GLU_NO_ERROR)
+      return;
+   if (tobj->current_polygon == NULL) {
+      tess_call_user_error(tobj, GLU_TESS_ERROR2);
+      return;
+   }
+   /* first contour? */
+   if (tobj->current_polygon->vertex_cnt)
+      tess_test_polygon(tobj);
+}
+
+
+void GLAPIENTRY
+gluTessVertex(GLUtriangulatorObj * tobj, GLdouble v[3], void *data)
+{
+   tess_polygon *polygon = tobj->current_polygon;
+   tess_vertex *last_vertex_ptr;
+
+   if (tobj->error != GLU_NO_ERROR)
+      return;
+   if (polygon == NULL) {
+      tess_call_user_error(tobj, GLU_TESS_ERROR2);
+      return;
+   }
+   last_vertex_ptr = polygon->last_vertex;
+   if (last_vertex_ptr == NULL) {
+      if ((last_vertex_ptr = (tess_vertex *)
+          malloc(sizeof(tess_vertex))) == NULL) {
+        tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
+        return;
+      }
+      polygon->vertices = last_vertex_ptr;
+      polygon->last_vertex = last_vertex_ptr;
+      last_vertex_ptr->data = data;
+      last_vertex_ptr->location[0] = v[0];
+      last_vertex_ptr->location[1] = v[1];
+      last_vertex_ptr->location[2] = v[2];
+      last_vertex_ptr->next = NULL;
+      last_vertex_ptr->previous = NULL;
+      ++(polygon->vertex_cnt);
+   }
+   else {
+      tess_vertex *vertex_ptr;
+
+      /* same point twice? */
+      if (fabs(last_vertex_ptr->location[0] - v[0]) < EPSILON &&
+         fabs(last_vertex_ptr->location[1] - v[1]) < EPSILON &&
+         fabs(last_vertex_ptr->location[2] - v[2]) < EPSILON) {
+        tess_call_user_error(tobj, GLU_TESS_ERROR6);
+        return;
+      }
+      if ((vertex_ptr = (tess_vertex *)
+          malloc(sizeof(tess_vertex))) == NULL) {
+        tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
+        return;
+      }
+      vertex_ptr->data = data;
+      vertex_ptr->location[0] = v[0];
+      vertex_ptr->location[1] = v[1];
+      vertex_ptr->location[2] = v[2];
+      vertex_ptr->next = NULL;
+      vertex_ptr->previous = last_vertex_ptr;
+      ++(polygon->vertex_cnt);
+      last_vertex_ptr->next = vertex_ptr;
+      polygon->last_vertex = vertex_ptr;
+   }
+}
+
+
+static void
+delete_contours(GLUtriangulatorObj * tobj)
+{
+   tess_polygon *polygon = tobj->current_polygon;
+   tess_contour *contour, *contour_tmp;
+   tess_vertex *vertex, *vertex_tmp;
+
+   /* remove current_polygon list - if exists due to detected error */
+   if (polygon != NULL) {
+      if (polygon->vertices) {
+        for (vertex = polygon->vertices; vertex != polygon->last_vertex;) {
+           vertex_tmp = vertex->next;
+           free(vertex);
+           vertex = vertex_tmp;
+        }
+        free(vertex);
+      }
+      free(polygon);
+      tobj->current_polygon = NULL;
+   }
+   /* remove all contour data */
+   for (contour = tobj->contours; contour != NULL;) {
+      for (vertex = contour->vertices; vertex != contour->last_vertex;) {
+        vertex_tmp = vertex->next;
+        free(vertex);
+        vertex = vertex_tmp;
+      }
+      free(vertex);
+      contour_tmp = contour->next;
+      free(contour);
+      contour = contour_tmp;
+   }
+   tobj->contours = tobj->last_contour = NULL;
+   tobj->contour_cnt = 0;
+}
+
+
+void GLAPIENTRY
+gluTessNormal(GLUtesselator *tess, GLdouble valueX, GLdouble valueY, GLdouble valueZ)
+{
+   /* dummy function */
+   (void) tess;
+   (void) valueX;
+   (void) valueY;
+   (void) valueZ;
+}
diff --git a/src/glu/mini/tess.h b/src/glu/mini/tess.h
new file mode 100644 (file)
index 0000000..908e209
--- /dev/null
@@ -0,0 +1,108 @@
+/* $Id: tess.h,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.3
+ * Copyright (C) 1995-2000  Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+/*
+ * This file is part of the polygon tesselation code contributed by
+ * Bogdan Sikorski
+ */
+
+
+#ifndef TESS_H
+#define TESS_H
+
+
+#include "gluP.h"
+
+#define EPSILON 1e-06          /* epsilon for double precision compares */
+
+typedef enum
+{
+   OXY,
+   OYZ,
+   OXZ
+}
+projection_type;
+
+typedef struct callbacks_str
+{
+   void (GLCALLBACK * begin) (GLenum mode);
+   void (GLCALLBACK * edgeFlag) (GLboolean flag);
+   void (GLCALLBACK * vertex) (GLvoid * v);
+   void (GLCALLBACK * end) (void);
+   void (GLCALLBACK * error) (GLenum err);
+}
+tess_callbacks;
+
+typedef struct vertex_str
+{
+   void *data;
+   GLdouble location[3];
+   GLdouble x, y;
+   GLboolean edge_flag;
+   struct vertex_str *shadow_vertex;
+   struct vertex_str *next, *previous;
+}
+tess_vertex;
+
+typedef struct contour_str
+{
+   GLenum type;
+   GLuint vertex_cnt;
+   GLdouble area;
+   GLenum orientation;
+   struct vertex_str *vertices, *last_vertex;
+   struct contour_str *next, *previous;
+}
+tess_contour;
+
+typedef struct polygon_str
+{
+   GLuint vertex_cnt;
+   GLdouble A, B, C, D;
+   GLdouble area;
+   GLenum orientation;
+   struct vertex_str *vertices, *last_vertex;
+}
+tess_polygon;
+
+struct GLUtesselator
+{
+   tess_contour *contours, *last_contour;
+   GLuint contour_cnt;
+   tess_callbacks callbacks;
+   tess_polygon *current_polygon;
+   GLenum error;
+   GLdouble A, B, C, D;
+   projection_type projection;
+};
+
+
+extern void tess_call_user_error(GLUtriangulatorObj *, GLenum);
+extern void tess_test_polygon(GLUtriangulatorObj *);
+extern void tess_find_contour_hierarchies(GLUtriangulatorObj *);
+extern void tess_handle_holes(GLUtriangulatorObj *);
+extern void tess_tesselate(GLUtriangulatorObj *);
+extern void tess_tesselate_with_edge_flag(GLUtriangulatorObj *);
+
+
+#endif
diff --git a/src/glu/mini/tesselat.c b/src/glu/mini/tesselat.c
new file mode 100644 (file)
index 0000000..a1102e6
--- /dev/null
@@ -0,0 +1,407 @@
+/* $Id: tesselat.c,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.3
+ * Copyright (C) 1995-2000  Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+/*
+ * This file is part of the polygon tesselation code contributed by
+ * Bogdan Sikorski
+ */
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <stdlib.h>
+#include <math.h>
+#include "tess.h"
+#endif
+
+
+
+static GLboolean edge_flag;
+
+static void emit_triangle(GLUtriangulatorObj *, tess_vertex *,
+                         tess_vertex *, tess_vertex *);
+
+static void emit_triangle_with_edge_flag(GLUtriangulatorObj *,
+                                        tess_vertex *, GLboolean,
+                                        tess_vertex *, GLboolean,
+                                        tess_vertex *, GLboolean);
+
+static GLdouble
+twice_the_triangle_area(tess_vertex * va, tess_vertex * vb, tess_vertex * vc)
+{
+   return (vb->x - va->x) * (vc->y - va->y) - (vb->y - va->y) * (vc->x -
+                                                                va->x);
+}
+
+static GLboolean
+left(GLdouble A, GLdouble B, GLdouble C, GLdouble x, GLdouble y)
+{
+   if (A * x + B * y + C > -EPSILON)
+      return GL_TRUE;
+   else
+      return GL_FALSE;
+}
+
+static GLboolean
+right(GLdouble A, GLdouble B, GLdouble C, GLdouble x, GLdouble y)
+{
+   if (A * x + B * y + C < EPSILON)
+      return GL_TRUE;
+   else
+      return GL_FALSE;
+}
+
+static GLint
+convex_ccw(tess_vertex * va,
+          tess_vertex * vb, tess_vertex * vc, GLUtriangulatorObj * tobj)
+{
+   GLdouble d;
+
+   d = twice_the_triangle_area(va, vb, vc);
+
+   if (d > EPSILON) {
+      return 1;
+   }
+   else if (d < -EPSILON) {
+      return 0;
+   }
+   else {
+      return -1;
+   }
+}
+
+static GLint
+convex_cw(tess_vertex * va,
+         tess_vertex * vb, tess_vertex * vc, GLUtriangulatorObj * tobj)
+{
+   GLdouble d;
+
+   d = twice_the_triangle_area(va, vb, vc);
+
+   if (d < -EPSILON) {
+      return 1;
+   }
+   else if (d > EPSILON) {
+      return 0;
+   }
+   else {
+      return -1;
+   }
+}
+
+static GLboolean
+diagonal_ccw(tess_vertex * va,
+            tess_vertex * vb,
+            GLUtriangulatorObj * tobj, tess_contour * contour)
+{
+   tess_vertex *vc = va->next, *vertex, *shadow_vertex;
+   struct
+   {
+      GLdouble A, B, C;
+   }
+   ac, cb, ba;
+   GLdouble x, y;
+
+   GLint res = convex_ccw(va, vc, vb, tobj);
+   if (res == 0)
+      return GL_FALSE;
+   if (res == -1)
+      return GL_TRUE;
+
+   ba.A = vb->y - va->y;
+   ba.B = va->x - vb->x;
+   ba.C = -ba.A * va->x - ba.B * va->y;
+   ac.A = va->y - vc->y;
+   ac.B = vc->x - va->x;
+   ac.C = -ac.A * vc->x - ac.B * vc->y;
+   cb.A = vc->y - vb->y;
+   cb.B = vb->x - vc->x;
+   cb.C = -cb.A * vb->x - cb.B * vb->y;
+   for (vertex = vb->next; vertex != va; vertex = vertex->next) {
+      shadow_vertex = vertex->shadow_vertex;
+      if (shadow_vertex != NULL &&
+         (shadow_vertex == va || shadow_vertex == vb || shadow_vertex == vc))
+        continue;
+      x = vertex->x;
+      y = vertex->y;
+      if (left(ba.A, ba.B, ba.C, x, y) &&
+         left(ac.A, ac.B, ac.C, x, y) && left(cb.A, cb.B, cb.C, x, y))
+        return GL_FALSE;
+   }
+   return GL_TRUE;
+}
+
+static GLboolean
+diagonal_cw(tess_vertex * va,
+           tess_vertex * vb,
+           GLUtriangulatorObj * tobj, tess_contour * contour)
+{
+   tess_vertex *vc = va->next, *vertex, *shadow_vertex;
+   struct
+   {
+      GLdouble A, B, C;
+   }
+   ac, cb, ba;
+   GLdouble x, y;
+
+   GLint res = convex_cw(va, vc, vb, tobj);
+   if (res == 0)
+      return GL_FALSE;
+   if (res == -1)
+      return GL_TRUE;
+
+   ba.A = vb->y - va->y;
+   ba.B = va->x - vb->x;
+   ba.C = -ba.A * va->x - ba.B * va->y;
+   ac.A = va->y - vc->y;
+   ac.B = vc->x - va->x;
+   ac.C = -ac.A * vc->x - ac.B * vc->y;
+   cb.A = vc->y - vb->y;
+   cb.B = vb->x - vc->x;
+   cb.C = -cb.A * vb->x - cb.B * vb->y;
+   for (vertex = vb->next; vertex != va; vertex = vertex->next) {
+      shadow_vertex = vertex->shadow_vertex;
+      if (shadow_vertex != NULL &&
+         (shadow_vertex == va || shadow_vertex == vb || shadow_vertex == vc))
+        continue;
+      x = vertex->x;
+      y = vertex->y;
+      if (right(ba.A, ba.B, ba.C, x, y) &&
+         right(ac.A, ac.B, ac.C, x, y) && right(cb.A, cb.B, cb.C, x, y))
+        return GL_FALSE;
+   }
+   return GL_TRUE;
+}
+
+static void
+clip_ear(GLUtriangulatorObj * tobj, tess_vertex * v, tess_contour * contour)
+{
+   emit_triangle(tobj, v->previous, v, v->next);
+   /* the first in the list */
+   if (contour->vertices == v) {
+      contour->vertices = v->next;
+      contour->last_vertex->next = v->next;
+      v->next->previous = contour->last_vertex;
+   }
+   else
+      /* the last ? */
+   if (contour->last_vertex == v) {
+      contour->vertices->previous = v->previous;
+      v->previous->next = v->next;
+      contour->last_vertex = v->previous;
+   }
+   else {
+      v->next->previous = v->previous;
+      v->previous->next = v->next;
+   }
+   free(v);
+   --(contour->vertex_cnt);
+}
+
+static void
+clip_ear_with_edge_flag(GLUtriangulatorObj * tobj,
+                       tess_vertex * v, tess_contour * contour)
+{
+   emit_triangle_with_edge_flag(tobj, v->previous, v->previous->edge_flag,
+                               v, v->edge_flag, v->next, GL_FALSE);
+   v->previous->edge_flag = GL_FALSE;
+   /* the first in the list */
+   if (contour->vertices == v) {
+      contour->vertices = v->next;
+      contour->last_vertex->next = v->next;
+      v->next->previous = contour->last_vertex;
+   }
+   else
+      /* the last ? */
+   if (contour->last_vertex == v) {
+      contour->vertices->previous = v->previous;
+      v->previous->next = v->next;
+      contour->last_vertex = v->previous;
+   }
+   else {
+      v->next->previous = v->previous;
+      v->previous->next = v->next;
+   }
+   free(v);
+   --(contour->vertex_cnt);
+}
+
+static void
+triangulate_ccw(GLUtriangulatorObj * tobj, tess_contour * contour)
+{
+   tess_vertex *vertex;
+   GLuint vertex_cnt = contour->vertex_cnt;
+
+   while (vertex_cnt > 3) {
+      vertex = contour->vertices;
+      while (diagonal_ccw(vertex, vertex->next->next, tobj, contour) ==
+            GL_FALSE && tobj->error == GLU_NO_ERROR)
+        vertex = vertex->next;
+      if (tobj->error != GLU_NO_ERROR)
+        return;
+      clip_ear(tobj, vertex->next, contour);
+      --vertex_cnt;
+   }
+}
+
+static void
+triangulate_cw(GLUtriangulatorObj * tobj, tess_contour * contour)
+{
+   tess_vertex *vertex;
+   GLuint vertex_cnt = contour->vertex_cnt;
+
+   while (vertex_cnt > 3) {
+      vertex = contour->vertices;
+      while (diagonal_cw(vertex, vertex->next->next, tobj, contour) ==
+            GL_FALSE && tobj->error == GLU_NO_ERROR)
+        vertex = vertex->next;
+      if (tobj->error != GLU_NO_ERROR)
+        return;
+      clip_ear(tobj, vertex->next, contour);
+      --vertex_cnt;
+   }
+}
+
+static void
+triangulate_ccw_with_edge_flag(GLUtriangulatorObj * tobj,
+                              tess_contour * contour)
+{
+   tess_vertex *vertex;
+   GLuint vertex_cnt = contour->vertex_cnt;
+
+   while (vertex_cnt > 3) {
+      vertex = contour->vertices;
+      while (diagonal_ccw(vertex, vertex->next->next, tobj, contour) ==
+            GL_FALSE && tobj->error == GLU_NO_ERROR)
+        vertex = vertex->next;
+      if (tobj->error != GLU_NO_ERROR)
+        return;
+      clip_ear_with_edge_flag(tobj, vertex->next, contour);
+      --vertex_cnt;
+   }
+}
+
+static void
+triangulate_cw_with_edge_flag(GLUtriangulatorObj * tobj,
+                             tess_contour * contour)
+{
+   tess_vertex *vertex;
+   GLuint vertex_cnt = contour->vertex_cnt;
+
+   while (vertex_cnt > 3) {
+      vertex = contour->vertices;
+      while (diagonal_cw(vertex, vertex->next->next, tobj, contour) ==
+            GL_FALSE && tobj->error == GLU_NO_ERROR)
+        vertex = vertex->next;
+      if (tobj->error != GLU_NO_ERROR)
+        return;
+      clip_ear_with_edge_flag(tobj, vertex->next, contour);
+      --vertex_cnt;
+   }
+}
+
+void
+tess_tesselate(GLUtriangulatorObj * tobj)
+{
+   tess_contour *contour;
+
+   for (contour = tobj->contours; contour != NULL; contour = contour->next) {
+      if (contour->orientation == GLU_CCW) {
+        triangulate_ccw(tobj, contour);
+      }
+      else {
+        triangulate_cw(tobj, contour);
+      }
+      if (tobj->error != GLU_NO_ERROR)
+        return;
+
+      /* emit the last triangle */
+      emit_triangle(tobj, contour->vertices, contour->vertices->next,
+                   contour->vertices->next->next);
+   }
+}
+
+void
+tess_tesselate_with_edge_flag(GLUtriangulatorObj * tobj)
+{
+   tess_contour *contour;
+
+   edge_flag = GL_TRUE;
+   /* first callback with edgeFlag set to GL_TRUE */
+   (tobj->callbacks.edgeFlag) (GL_TRUE);
+
+   for (contour = tobj->contours; contour != NULL; contour = contour->next) {
+      if (contour->orientation == GLU_CCW)
+        triangulate_ccw_with_edge_flag(tobj, contour);
+      else
+        triangulate_cw_with_edge_flag(tobj, contour);
+      if (tobj->error != GLU_NO_ERROR)
+        return;
+      /* emit the last triangle */
+      emit_triangle_with_edge_flag(tobj, contour->vertices,
+                                  contour->vertices->edge_flag,
+                                  contour->vertices->next,
+                                  contour->vertices->next->edge_flag,
+                                  contour->vertices->next->next,
+                                  contour->vertices->next->next->edge_flag);
+   }
+}
+
+static void
+emit_triangle(GLUtriangulatorObj * tobj,
+             tess_vertex * v1, tess_vertex * v2, tess_vertex * v3)
+{
+   (tobj->callbacks.begin) (GL_TRIANGLES);
+   (tobj->callbacks.vertex) (v1->data);
+   (tobj->callbacks.vertex) (v2->data);
+   (tobj->callbacks.vertex) (v3->data);
+   (tobj->callbacks.end) ();
+}
+
+static void
+emit_triangle_with_edge_flag(GLUtriangulatorObj * tobj,
+                            tess_vertex * v1,
+                            GLboolean edge_flag1,
+                            tess_vertex * v2,
+                            GLboolean edge_flag2,
+                            tess_vertex * v3, GLboolean edge_flag3)
+{
+   (tobj->callbacks.begin) (GL_TRIANGLES);
+   if (edge_flag1 != edge_flag) {
+      edge_flag = (edge_flag == GL_TRUE ? GL_FALSE : GL_TRUE);
+      (tobj->callbacks.edgeFlag) (edge_flag);
+   }
+   (tobj->callbacks.vertex) (v1->data);
+   if (edge_flag2 != edge_flag) {
+      edge_flag = (edge_flag == GL_TRUE ? GL_FALSE : GL_TRUE);
+      (tobj->callbacks.edgeFlag) (edge_flag);
+   }
+   (tobj->callbacks.vertex) (v2->data);
+   if (edge_flag3 != edge_flag) {
+      edge_flag = (edge_flag == GL_TRUE ? GL_FALSE : GL_TRUE);
+      (tobj->callbacks.edgeFlag) (edge_flag);
+   }
+   (tobj->callbacks.vertex) (v3->data);
+   (tobj->callbacks.end) ();
+}
diff --git a/src/glut/mini/Makefile.X11 b/src/glut/mini/Makefile.X11
new file mode 100644 (file)
index 0000000..097a665
--- /dev/null
@@ -0,0 +1,78 @@
+
+TOP = ../../..
+
+default: linux-solo
+
+MARK = $(TOP)/src/glut/glx
+
+INCLUDES = -I$(TOP)/include -I$(MARK)
+
+CORE_SOURCES = \
+       bitmap.c \
+       callback.c \
+       color.c \
+       globals.c \
+       init.c \
+       menu.c \
+       models.c \
+       overlay.c \
+       state.c \
+       teapot.c \
+       window.c
+
+
+MARK_SOURCES = \
+       $(MARK)/glut_8x13.c \
+       $(MARK)/glut_9x15.c \
+       $(MARK)/glut_hel10.c \
+       $(MARK)/glut_hel12.c \
+       $(MARK)/glut_hel18.c \
+       $(MARK)/glut_tr10.c \
+       $(MARK)/glut_tr24.c
+
+SOURCES = $(CORE_SOURCES)  $(MARK_SOURCES)
+
+OBJS =  $(SOURCES:.c=.o)
+
+LIBS = -L$(TOP)/lib -lGL -lGLU -lm
+
+##### RULES #####
+
+.c.o:
+       $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
+
+.S.o:
+       $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES)  $< -o $@
+
+
+##### TARGETS #####
+
+targets: depend libglut.so.3.7 install 
+
+libglut.so.3.7: $(OBJS) Makefile.X11
+       gcc -shared -Wl,-soname,libglut.so -Wl,-Bsymbolic $(OBJS) $(LIBS) -o $@ 
+
+install:
+       rm -f $(TOP)/lib/libglut.so*
+       install -D libglut.so.3.7 $(TOP)/lib/libglut.so.3.7
+       ln -s libglut.so.3.7 $(TOP)/lib/libglut.so.3
+       ln -s libglut.so.3 $(TOP)/lib/libglut.so
+
+# Run 'make -f Makefile.X11 dep' to update the dependencies if you change
+# what's included by any source file.
+depend: $(SOURCES) 
+       makedepend -fdepend -Y $(INCLUDES) \
+               $(SOURCES)
+
+# Emacs tags
+tags:
+       etags `find . -name \*.[ch]` `find ../include`
+
+
+# Remove .o and backup files
+clean:
+       -rm -f *.o *~ *.o *~ *.so
+
+include $(TOP)/Make-config
+
+include depend
diff --git a/src/glut/mini/bitmap.c b/src/glut/mini/bitmap.c
new file mode 100644 (file)
index 0000000..55a031a
--- /dev/null
@@ -0,0 +1,56 @@
+
+/* Copyright (c) Mark J. Kilgard, 1994. */
+
+/* This program is freely distributable without licensing fees
+   and is provided without guarantee or warrantee expressed or
+   implied. This program is -not- in the public domain. */
+
+#include "glutbitmap.h"
+
+void APIENTRY 
+glutBitmapCharacter(GLUTbitmapFont font, int c)
+{
+  const BitmapCharRec *ch;
+  BitmapFontPtr fontinfo;
+  GLfloat swapbytes, lsbfirst, rowlength;
+  GLfloat skiprows, skippixels, alignment;
+
+#if defined(_WIN32)
+  fontinfo = (BitmapFontPtr) __glutFont(font);
+#else
+  fontinfo = (BitmapFontPtr) font;
+#endif
+
+  if (c < fontinfo->first ||
+    c >= fontinfo->first + fontinfo->num_chars)
+    return;
+  ch = fontinfo->ch[c - fontinfo->first];
+  if (ch) {
+    /* Save current modes. */
+/*     glGetFloatv(GL_UNPACK_SWAP_BYTES, &swapbytes); */
+/*     glGetFloatv(GL_UNPACK_LSB_FIRST, &lsbfirst); */
+/*     glGetFloatv(GL_UNPACK_ROW_LENGTH, &rowlength); */
+/*     glGetFloatv(GL_UNPACK_SKIP_ROWS, &skiprows); */
+/*     glGetFloatv(GL_UNPACK_SKIP_PIXELS, &skippixels); */
+       glGetFloatv(GL_UNPACK_ALIGNMENT, &alignment); 
+    /* Little endian machines (DEC Alpha for example) could
+       benefit from setting GL_UNPACK_LSB_FIRST to GL_TRUE
+       instead of GL_FALSE, but this would require changing the
+       generated bitmaps too. */
+/*     glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); */
+/*     glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); */
+/*     glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); */
+/*     glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); */
+/*     glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); */
+     glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 
+    glBitmap(ch->width, ch->height, ch->xorig, ch->yorig,
+      ch->advance, 0, ch->bitmap);
+    /* Restore saved modes. */
+/*     glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes); */
+/*     glPixelStorei(GL_UNPACK_LSB_FIRST, (int)lsbfirst); */
+/*     glPixelStorei(GL_UNPACK_ROW_LENGTH, (int)rowlength); */
+/*     glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows); */
+/*     glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels); */
+     glPixelStorei(GL_UNPACK_ALIGNMENT, (int)alignment); 
+  }
+}
diff --git a/src/glut/mini/callback.c b/src/glut/mini/callback.c
new file mode 100644 (file)
index 0000000..d4e3101
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.4
+ * Copyright (C) 1995-1998  Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * DOS/DJGPP glut driver v1.0 for Mesa 4.0
+ *
+ *  Copyright (C) 2002 - Borca Daniel
+ *  Email : dborca@yahoo.com
+ *  Web   : http://www.geocities.com/dborca
+ */
+
+
+#include "GL/glut.h"
+#include "internal.h"
+
+
+void APIENTRY glutDisplayFunc (void (GLUTCALLBACK *func) (void))
+{
+ display_func = func;
+}
+
+
+void APIENTRY glutReshapeFunc (void (GLUTCALLBACK *func) (int width, int height))
+{
+ reshape_func = func;
+}
+
+
+void APIENTRY glutKeyboardFunc (void (GLUTCALLBACK *func) (unsigned char key, int x, int y))
+{
+ keyboard_func = func;
+}
+
+
+void APIENTRY glutMouseFunc (void (GLUTCALLBACK *func) (int button, int state, int x, int y))
+{
+ mouse_func = func;
+}
+
+
+void APIENTRY glutMotionFunc (void (GLUTCALLBACK *func) (int x, int y))
+{
+ motion_func = func;
+}
+
+
+void APIENTRY glutPassiveMotionFunc (void (GLUTCALLBACK *func) (int x, int y))
+{
+ passive_motion_func = func;
+}
+
+
+void APIENTRY glutEntryFunc (void (GLUTCALLBACK *func) (int state))
+{
+ entry_func = func;
+}
+
+
+void APIENTRY glutVisibilityFunc (void (GLUTCALLBACK *func) (int state))
+{
+ visibility_func = func;
+}
+
+
+void APIENTRY glutIdleFunc (void (GLUTCALLBACK *func) (void))
+{
+ idle_func = func;
+}
+
+
+void APIENTRY glutTimerFunc (unsigned int millis, void (GLUTCALLBACK *func) (int value), int value)
+{
+}
+
+
+void APIENTRY glutMenuStateFunc (void (GLUTCALLBACK *func) (int state))
+{
+ menu_state_func = func;
+}
+
+
+void APIENTRY glutSpecialFunc (void (GLUTCALLBACK *func) (int key, int x, int y))
+{
+ special_func = func;
+}
+
+
+void APIENTRY glutSpaceballMotionFunc (void (GLUTCALLBACK *func) (int x, int y, int z))
+{
+}
+
+
+void APIENTRY glutSpaceballRotateFunc (void (GLUTCALLBACK *func) (int x, int y, int z))
+{
+}
+
+
+void APIENTRY glutSpaceballButtonFunc (void (GLUTCALLBACK *func) (int button, int state))
+{
+}
+
+
+void APIENTRY glutButtonBoxFunc (void (GLUTCALLBACK *func) (int button, int state))
+{
+}
+
+
+void APIENTRY glutDialsFunc (void (GLUTCALLBACK *func) (int dial, int value))
+{
+}
+
+
+void APIENTRY glutTabletMotionFunc (void (GLUTCALLBACK *func) (int x, int y))
+{
+}
+
+
+void APIENTRY glutTabletButtonFunc (void (GLUTCALLBACK *func) (int button, int state, int x, int y))
+{
+}
+
+
+void APIENTRY glutMenuStatusFunc (void (GLUTCALLBACK *func) (int status, int x, int y))
+{
+}
+
+
+void APIENTRY glutOverlayDisplayFunc (void (GLUTCALLBACK *func) (void))
+{
+}
+
+
+void APIENTRY glutWindowStatusFunc (void (GLUTCALLBACK *func) (int state))
+{
+}
diff --git a/src/glut/mini/color.c b/src/glut/mini/color.c
new file mode 100644 (file)
index 0000000..b53c5b6
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.4
+ * Copyright (C) 1995-1998  Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * DOS/DJGPP glut driver v1.0 for Mesa 4.0
+ *
+ *  Copyright (C) 2002 - Borca Daniel
+ *  Email : dborca@yahoo.com
+ *  Web   : http://www.geocities.com/dborca
+ */
+
+
+#include "GL/glut.h"
+
+
+void APIENTRY glutSetColor (int ndx, GLfloat red, GLfloat green, GLfloat blue)
+{
+}
+
+
+GLfloat APIENTRY glutGetColor (int ndx, int component)
+{
+ return 0.0;
+}
+
+
+void APIENTRY glutCopyColormap (int win)
+{
+}
diff --git a/src/glut/mini/globals.c b/src/glut/mini/globals.c
new file mode 100644 (file)
index 0000000..76db53c
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.4
+ * Copyright (C) 1995-1998  Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * DOS/DJGPP glut driver v1.0 for Mesa 4.0
+ *
+ *  Copyright (C) 2002 - Borca Daniel
+ *  Email : dborca@yahoo.com
+ *  Web   : http://www.geocities.com/dborca
+ */
+
+
+#include "GL/glut.h"
+#include "internal.h"
+
+GLenum    g_display_mode = 0;
+GLuint    g_width        = DEFAULT_WIDTH;
+GLuint    g_height       = DEFAULT_HEIGHT;
+GLint     g_mouse        = GL_FALSE;
+GLboolean g_redisplay    = GL_FALSE;
+GLint     g_xpos         = 0;
+GLint     g_ypos         = 0;
+
+void (GLUTCALLBACK *display_func) (void)                              = 0;
+void (GLUTCALLBACK *reshape_func) (int width, int height)             = 0;
+void (GLUTCALLBACK *keyboard_func) (unsigned char key, int x, int y)  = 0;
+void (GLUTCALLBACK *mouse_func) (int button, int state, int x, int y) = 0;
+void (GLUTCALLBACK *motion_func) (int x, int y)                       = 0;
+void (GLUTCALLBACK *passive_motion_func) (int x, int y)               = 0;
+void (GLUTCALLBACK *entry_func) (int state)                           = 0;
+void (GLUTCALLBACK *visibility_func) (int state)                      = 0;
+void (GLUTCALLBACK *idle_func) (void)                                 = 0;
+void (GLUTCALLBACK *menu_state_func) (int state)                      = 0;
+void (GLUTCALLBACK *special_func) (int key, int x, int y)             = 0;
+void (GLUTCALLBACK *spaceball_motion_func) (int x, int y, int z)      = 0;
+void (GLUTCALLBACK *spaceball_rotate_func) (int x, int y, int z)      = 0;
+void (GLUTCALLBACK *spaceball_button_func) (int button, int state)    = 0;
+void (GLUTCALLBACK *button_box_func) (int button, int state)          = 0;
+void (GLUTCALLBACK *dials_func) (int dial, int value)                 = 0;
+void (GLUTCALLBACK *tablet_motion_func) (int x, int y)                = 0;
+void (GLUTCALLBACK *tabled_button_func) (int button, int state, int x, int y) = 0;
+void (GLUTCALLBACK *menu_status_func) (int status, int x, int y)      = 0;
+void (GLUTCALLBACK *overlay_display_func) (void)                      = 0;
+void (GLUTCALLBACK *window_status_func) (int state)                   = 0;
diff --git a/src/glut/mini/init.c b/src/glut/mini/init.c
new file mode 100644 (file)
index 0000000..5588db9
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  4.0
+ * Copyright (C) 1995-1998  Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * DOS/DJGPP glut driver v1.0 for Mesa 4.0
+ *
+ *  Copyright (C) 2002 - Borca Daniel
+ *  Email : dborca@yahoo.com
+ *  Web   : http://www.geocities.com/dborca
+ */
+
+
+#include "GL/glut.h"
+#include "internal.h"
+
+
+void APIENTRY glutInit (int *argcp, char **argv)
+{
+ glutGet(GLUT_ELAPSED_TIME);
+}
+
+
+void APIENTRY glutInitDisplayMode (unsigned int mode)
+{
+ g_display_mode = mode;
+}
+
+
+void APIENTRY glutInitWindowPosition (int x, int y)
+{
+ g_xpos = x;
+ g_ypos = y;
+}
+
+
+void APIENTRY glutInitWindowSize (int width, int height)
+{
+ g_width  = width;
+ g_height = height;
+}
+
+
diff --git a/src/glut/mini/internal.h b/src/glut/mini/internal.h
new file mode 100644 (file)
index 0000000..ccd12e5
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  4.0
+ * Copyright (C) 1995-1998  Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * DOS/DJGPP glut driver v1.0 for Mesa 4.0
+ *
+ *  Copyright (C) 2002 - Borca Daniel
+ *  Email : dborca@yahoo.com
+ *  Web   : http://www.geocities.com/dborca
+ */
+
+#ifndef INTERNAL_H_included
+#define INTERNAL_H_included
+
+
+#include "GL/glut.h"
+/* #include "pc_hw/pc_hw.h" */
+
+
+#define MAX_WINDOWS    4
+
+#define DEFAULT_WIDTH  640
+#define DEFAULT_HEIGHT 480
+#define DEFAULT_BPP    16
+
+#define DEPTH_SIZE   16
+#define STENCIL_SIZE 8
+#define ACCUM_SIZE   16
+
+extern GLenum    g_display_mode;
+extern GLuint    g_width;
+extern GLuint    g_height;
+extern GLint     g_mouse;
+extern GLboolean g_redisplay;
+extern GLint     g_xpos;
+extern GLint     g_ypos;
+
+extern void (GLUTCALLBACK *display_func) (void);
+extern void (GLUTCALLBACK *reshape_func) (int width, int height);
+extern void (GLUTCALLBACK *keyboard_func) (unsigned char key, int x, int y);
+extern void (GLUTCALLBACK *mouse_func) (int button, int state, int x, int y);
+extern void (GLUTCALLBACK *motion_func) (int x, int y);
+extern void (GLUTCALLBACK *passive_motion_func) (int x, int y);
+extern void (GLUTCALLBACK *entry_func) (int state);
+extern void (GLUTCALLBACK *visibility_func) (int state);
+extern void (GLUTCALLBACK *idle_func) (void);
+extern void (GLUTCALLBACK *menu_state_func) (int state);
+extern void (GLUTCALLBACK *special_func) (int key, int x, int y);
+extern void (GLUTCALLBACK *spaceball_motion_func) (int x, int y, int z);
+extern void (GLUTCALLBACK *spaceball_rotate_func) (int x, int y, int z);
+extern void (GLUTCALLBACK *spaceball_button_func) (int button, int state);
+extern void (GLUTCALLBACK *button_box_func) (int button, int state);
+extern void (GLUTCALLBACK *dials_func) (int dial, int value);
+extern void (GLUTCALLBACK *tablet_motion_func) (int x, int y);
+extern void (GLUTCALLBACK *tabled_button_func) (int button, int state, int x, int y);
+extern void (GLUTCALLBACK *menu_status_func) (int status, int x, int y);
+extern void (GLUTCALLBACK *overlay_display_func) (void);
+extern void (GLUTCALLBACK *window_status_func) (int state);
+
+#endif
diff --git a/src/glut/mini/menu.c b/src/glut/mini/menu.c
new file mode 100644 (file)
index 0000000..3c57164
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.4
+ * Copyright (C) 1995-1998  Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * DOS/DJGPP glut driver v1.0 for Mesa 4.0
+ *
+ *  Copyright (C) 2002 - Borca Daniel
+ *  Email : dborca@yahoo.com
+ *  Web   : http://www.geocities.com/dborca
+ */
+
+
+#include "GL/glut.h"
+
+
+int APIENTRY glutCreateMenu (void (GLUTCALLBACK *func) (int))
+{
+ return 0;
+}
+
+void APIENTRY glutDestroyMenu (int menu)
+{
+}
+
+
+int APIENTRY glutGetMenu (void)
+{
+ return 0;
+}
+
+
+void APIENTRY glutSetMenu (int menu)
+{
+}
+
+
+void APIENTRY glutAddMenuEntry (const char *label, int value)
+{
+}
+
+
+void APIENTRY glutAddSubMenu (const char *label, int submenu)
+{
+}
+
+
+void APIENTRY glutChangeToMenuEntry (int item, const char *label, int value)
+{
+}
+
+
+void APIENTRY glutChangeToSubMenu (int item, const char *label, int submenu)
+{
+}
+
+
+void APIENTRY glutRemoveMenuItem (int item)
+{
+}
+
+
+void APIENTRY glutAttachMenu (int button)
+{
+}
+
+
+void APIENTRY glutDetachMenu (int button)
+{
+}
diff --git a/src/glut/mini/models.c b/src/glut/mini/models.c
new file mode 100644 (file)
index 0000000..57f45a2
--- /dev/null
@@ -0,0 +1,598 @@
+
+/* Copyright (c) Mark J. Kilgard, 1994, 1997. */
+
+/**
+(c) Copyright 1993, Silicon Graphics, Inc.
+
+ALL RIGHTS RESERVED
+
+Permission to use, copy, modify, and distribute this software
+for any purpose and without fee is hereby granted, provided
+that the above copyright notice appear in all copies and that
+both the copyright notice and this permission notice appear in
+supporting documentation, and that the name of Silicon
+Graphics, Inc. not be used in advertising or publicity
+pertaining to distribution of the software without specific,
+written prior permission.
+
+THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU
+"AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR
+OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
+MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  IN NO
+EVENT SHALL SILICON GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE
+ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER,
+INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE,
+SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR
+NOT SILICON GRAPHICS, INC.  HAS BEEN ADVISED OF THE POSSIBILITY
+OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+US Government Users Restricted Rights
+
+Use, duplication, or disclosure by the Government is subject to
+restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
+(c)(1)(ii) of the Rights in Technical Data and Computer
+Software clause at DFARS 252.227-7013 and/or in similar or
+successor clauses in the FAR or the DOD or NASA FAR
+Supplement.  Unpublished-- rights reserved under the copyright
+laws of the United States.  Contractor/manufacturer is Silicon
+Graphics, Inc., 2011 N.  Shoreline Blvd., Mountain View, CA
+94039-7311.
+
+OpenGL(TM) is a trademark of Silicon Graphics, Inc.
+*/
+
+#include <math.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include "GL/glut.h"
+
+/* Some <math.h> files do not define M_PI... */
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+static GLUquadricObj *quadObj;
+
+#define QUAD_OBJ_INIT() { if(!quadObj) initQuadObj(); }
+
+static void
+initQuadObj(void)
+{
+  quadObj = gluNewQuadric();
+/*  if (!quadObj)
+    __glutFatalError("out of memory."); */
+}
+
+/* CENTRY */
+void APIENTRY
+glutWireSphere(GLdouble radius, GLint slices, GLint stacks)
+{
+  QUAD_OBJ_INIT();
+  gluQuadricDrawStyle(quadObj, GLU_LINE);
+  gluQuadricNormals(quadObj, GLU_SMOOTH);
+  /* If we ever changed/used the texture or orientation state
+     of quadObj, we'd need to change it to the defaults here
+     with gluQuadricTexture and/or gluQuadricOrientation. */
+  gluSphere(quadObj, radius, slices, stacks);
+}
+
+void APIENTRY
+glutSolidSphere(GLdouble radius, GLint slices, GLint stacks)
+{
+  QUAD_OBJ_INIT();
+  gluQuadricDrawStyle(quadObj, GLU_FILL);
+  gluQuadricNormals(quadObj, GLU_SMOOTH);
+  /* If we ever changed/used the texture or orientation state
+     of quadObj, we'd need to change it to the defaults here
+     with gluQuadricTexture and/or gluQuadricOrientation. */
+  gluSphere(quadObj, radius, slices, stacks);
+}
+
+void APIENTRY
+glutWireCone(GLdouble base, GLdouble height,
+  GLint slices, GLint stacks)
+{
+  QUAD_OBJ_INIT();
+  gluQuadricDrawStyle(quadObj, GLU_LINE);
+  gluQuadricNormals(quadObj, GLU_SMOOTH);
+  /* If we ever changed/used the texture or orientation state
+     of quadObj, we'd need to change it to the defaults here
+     with gluQuadricTexture and/or gluQuadricOrientation. */
+  gluCylinder(quadObj, base, 0.0, height, slices, stacks);
+}
+
+void APIENTRY
+glutSolidCone(GLdouble base, GLdouble height,
+  GLint slices, GLint stacks)
+{
+  QUAD_OBJ_INIT();
+  gluQuadricDrawStyle(quadObj, GLU_FILL);
+  gluQuadricNormals(quadObj, GLU_SMOOTH);
+  /* If we ever changed/used the texture or orientation state
+     of quadObj, we'd need to change it to the defaults here
+     with gluQuadricTexture and/or gluQuadricOrientation. */
+  gluCylinder(quadObj, base, 0.0, height, slices, stacks);
+}
+
+/* ENDCENTRY */
+
+static void
+drawBox(GLfloat size, GLenum type)
+{
+  static GLfloat n[6][3] =
+  {
+    {-1.0, 0.0, 0.0},
+    {0.0, 1.0, 0.0},
+    {1.0, 0.0, 0.0},
+    {0.0, -1.0, 0.0},
+    {0.0, 0.0, 1.0},
+    {0.0, 0.0, -1.0}
+  };
+  static GLint faces[6][4] =
+  {
+    {0, 1, 2, 3},
+    {3, 2, 6, 7},
+    {7, 6, 5, 4},
+    {4, 5, 1, 0},
+    {5, 6, 2, 1},
+    {7, 4, 0, 3}
+  };
+  GLfloat v[8][3];
+  GLint i;
+
+  v[0][0] = v[1][0] = v[2][0] = v[3][0] = -size / 2;
+  v[4][0] = v[5][0] = v[6][0] = v[7][0] = size / 2;
+  v[0][1] = v[1][1] = v[4][1] = v[5][1] = -size / 2;
+  v[2][1] = v[3][1] = v[6][1] = v[7][1] = size / 2;
+  v[0][2] = v[3][2] = v[4][2] = v[7][2] = -size / 2;
+  v[1][2] = v[2][2] = v[5][2] = v[6][2] = size / 2;
+
+  for (i = 5; i >= 0; i--) {
+    glBegin(type);
+/*     glNormal3fv(&n[i][0]); */
+    glVertex3fv(&v[faces[i][0]][0]);
+    glVertex3fv(&v[faces[i][1]][0]);
+    glVertex3fv(&v[faces[i][2]][0]);
+    glVertex3fv(&v[faces[i][3]][0]);
+    glEnd();
+  }
+}
+
+/* CENTRY */
+void APIENTRY
+glutWireCube(GLdouble size)
+{
+  drawBox(size, GL_LINE_LOOP);
+}
+
+void APIENTRY
+glutSolidCube(GLdouble size)
+{
+  drawBox(size, GL_QUADS);
+}
+
+/* ENDCENTRY */
+
+static void
+doughnut(GLfloat r, GLfloat R, GLint nsides, GLint rings)
+{
+  int i, j;
+  GLfloat theta, phi, theta1;
+  GLfloat cosTheta, sinTheta;
+  GLfloat cosTheta1, sinTheta1;
+  GLfloat ringDelta, sideDelta;
+
+  ringDelta = 2.0 * M_PI / rings;
+  sideDelta = 2.0 * M_PI / nsides;
+
+  theta = 0.0;
+  cosTheta = 1.0;
+  sinTheta = 0.0;
+  for (i = rings - 1; i >= 0; i--) {
+    theta1 = theta + ringDelta;
+    cosTheta1 = cos(theta1);
+    sinTheta1 = sin(theta1);
+    glBegin(GL_QUAD_STRIP);
+    phi = 0.0;
+    for (j = nsides; j >= 0; j--) {
+      GLfloat cosPhi, sinPhi, dist;
+
+      phi += sideDelta;
+      cosPhi = cos(phi);
+      sinPhi = sin(phi);
+      dist = R + r * cosPhi;
+
+/*       glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi); */
+      glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
+/*       glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi); */
+      glVertex3f(cosTheta * dist, -sinTheta * dist,  r * sinPhi);
+    }
+    glEnd();
+    theta = theta1;
+    cosTheta = cosTheta1;
+    sinTheta = sinTheta1;
+  }
+}
+
+/* CENTRY */
+void APIENTRY
+glutWireTorus(GLdouble innerRadius, GLdouble outerRadius,
+  GLint nsides, GLint rings)
+{
+/*   glPushAttrib(GL_POLYGON_BIT); */
+/*   glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); */
+  doughnut(innerRadius, outerRadius, nsides, rings);
+/*   glPopAttrib(); */
+}
+
+void APIENTRY
+glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius,
+  GLint nsides, GLint rings)
+{
+  doughnut(innerRadius, outerRadius, nsides, rings);
+}
+
+/* ENDCENTRY */
+
+static GLfloat dodec[20][3];
+
+static void
+initDodecahedron(void)
+{
+  GLfloat alpha, beta;
+
+  alpha = sqrt(2.0 / (3.0 + sqrt(5.0)));
+  beta = 1.0 + sqrt(6.0 / (3.0 + sqrt(5.0)) -
+    2.0 + 2.0 * sqrt(2.0 / (3.0 + sqrt(5.0))));
+  /* *INDENT-OFF* */
+  dodec[0][0] = -alpha; dodec[0][1] = 0; dodec[0][2] = beta;
+  dodec[1][0] = alpha; dodec[1][1] = 0; dodec[1][2] = beta;
+  dodec[2][0] = -1; dodec[2][1] = -1; dodec[2][2] = -1;
+  dodec[3][0] = -1; dodec[3][1] = -1; dodec[3][2] = 1;
+  dodec[4][0] = -1; dodec[4][1] = 1; dodec[4][2] = -1;
+  dodec[5][0] = -1; dodec[5][1] = 1; dodec[5][2] = 1;
+  dodec[6][0] = 1; dodec[6][1] = -1; dodec[6][2] = -1;
+  dodec[7][0] = 1; dodec[7][1] = -1; dodec[7][2] = 1;
+  dodec[8][0] = 1; dodec[8][1] = 1; dodec[8][2] = -1;
+  dodec[9][0] = 1; dodec[9][1] = 1; dodec[9][2] = 1;
+  dodec[10][0] = beta; dodec[10][1] = alpha; dodec[10][2] = 0;
+  dodec[11][0] = beta; dodec[11][1] = -alpha; dodec[11][2] = 0;
+  dodec[12][0] = -beta; dodec[12][1] = alpha; dodec[12][2] = 0;
+  dodec[13][0] = -beta; dodec[13][1] = -alpha; dodec[13][2] = 0;
+  dodec[14][0] = -alpha; dodec[14][1] = 0; dodec[14][2] = -beta;
+  dodec[15][0] = alpha; dodec[15][1] = 0; dodec[15][2] = -beta;
+  dodec[16][0] = 0; dodec[16][1] = beta; dodec[16][2] = alpha;
+  dodec[17][0] = 0; dodec[17][1] = beta; dodec[17][2] = -alpha;
+  dodec[18][0] = 0; dodec[18][1] = -beta; dodec[18][2] = alpha;
+  dodec[19][0] = 0; dodec[19][1] = -beta; dodec[19][2] = -alpha;
+  /* *INDENT-ON* */
+
+}
+
+#define DIFF3(_a,_b,_c) { \
+    (_c)[0] = (_a)[0] - (_b)[0]; \
+    (_c)[1] = (_a)[1] - (_b)[1]; \
+    (_c)[2] = (_a)[2] - (_b)[2]; \
+}
+
+static void
+crossprod(GLfloat v1[3], GLfloat v2[3], GLfloat prod[3])
+{
+  GLfloat p[3];         /* in case prod == v1 or v2 */
+
+  p[0] = v1[1] * v2[2] - v2[1] * v1[2];
+  p[1] = v1[2] * v2[0] - v2[2] * v1[0];
+  p[2] = v1[0] * v2[1] - v2[0] * v1[1];
+  prod[0] = p[0];
+  prod[1] = p[1];
+  prod[2] = p[2];
+}
+
+static void
+normalize(GLfloat v[3])
+{
+  GLfloat d;
+
+  d = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
+  if (d == 0.0) {
+/*    __glutWarning("normalize: zero length vector"); */
+    v[0] = d = 1.0;
+  }
+  d = 1 / d;
+  v[0] *= d;
+  v[1] *= d;
+  v[2] *= d;
+}
+
+static void
+pentagon(int a, int b, int c, int d, int e, GLenum shadeType)
+{
+  GLfloat n0[3], d1[3], d2[3];
+
+  DIFF3(dodec[a], dodec[b], d1);
+  DIFF3(dodec[b], dodec[c], d2);
+  crossprod(d1, d2, n0);
+  normalize(n0);
+
+  glBegin(shadeType);
+/*   glNormal3fv(n0); */
+  glVertex3fv(&dodec[a][0]);
+  glVertex3fv(&dodec[b][0]);
+  glVertex3fv(&dodec[c][0]);
+  glVertex3fv(&dodec[d][0]);
+  glVertex3fv(&dodec[e][0]);
+  glEnd();
+}
+
+static void
+dodecahedron(GLenum type)
+{
+  static int inited = 0;
+
+  if (inited == 0) {
+    inited = 1;
+    initDodecahedron();
+  }
+  pentagon(0, 1, 9, 16, 5, type);
+  pentagon(1, 0, 3, 18, 7, type);
+  pentagon(1, 7, 11, 10, 9, type);
+  pentagon(11, 7, 18, 19, 6, type);
+  pentagon(8, 17, 16, 9, 10, type);
+  pentagon(2, 14, 15, 6, 19, type);
+  pentagon(2, 13, 12, 4, 14, type);
+  pentagon(2, 19, 18, 3, 13, type);
+  pentagon(3, 0, 5, 12, 13, type);
+  pentagon(6, 15, 8, 10, 11, type);
+  pentagon(4, 17, 8, 15, 14, type);
+  pentagon(4, 12, 5, 16, 17, type);
+}
+
+/* CENTRY */
+void APIENTRY
+glutWireDodecahedron(void)
+{
+  dodecahedron(GL_LINE_LOOP);
+}
+
+void APIENTRY
+glutSolidDodecahedron(void)
+{
+  dodecahedron(GL_TRIANGLE_FAN);
+}
+
+/* ENDCENTRY */
+
+static void
+recorditem(GLfloat * n1, GLfloat * n2, GLfloat * n3,
+  GLenum shadeType)
+{
+  GLfloat q0[3], q1[3];
+
+  DIFF3(n1, n2, q0);
+  DIFF3(n2, n3, q1);
+  crossprod(q0, q1, q1);
+  normalize(q1);
+
+  glBegin(shadeType);
+/*   glNormal3fv(q1); */
+  glVertex3fv(n1);
+  glVertex3fv(n2);
+  glVertex3fv(n3);
+  glEnd();
+}
+
+static void
+subdivide(GLfloat * v0, GLfloat * v1, GLfloat * v2,
+  GLenum shadeType)
+{
+  int depth;
+  GLfloat w0[3], w1[3], w2[3];
+  GLfloat l;
+  int i, j, k, n;
+
+  depth = 1;
+  for (i = 0; i < depth; i++) {
+    for (j = 0; i + j < depth; j++) {
+      k = depth - i - j;
+      for (n = 0; n < 3; n++) {
+        w0[n] = (i * v0[n] + j * v1[n] + k * v2[n]) / depth;
+        w1[n] = ((i + 1) * v0[n] + j * v1[n] + (k - 1) * v2[n])
+          / depth;
+        w2[n] = (i * v0[n] + (j + 1) * v1[n] + (k - 1) * v2[n])
+          / depth;
+      }
+      l = sqrt(w0[0] * w0[0] + w0[1] * w0[1] + w0[2] * w0[2]);
+      w0[0] /= l;
+      w0[1] /= l;
+      w0[2] /= l;
+      l = sqrt(w1[0] * w1[0] + w1[1] * w1[1] + w1[2] * w1[2]);
+      w1[0] /= l;
+      w1[1] /= l;
+      w1[2] /= l;
+      l = sqrt(w2[0] * w2[0] + w2[1] * w2[1] + w2[2] * w2[2]);
+      w2[0] /= l;
+      w2[1] /= l;
+      w2[2] /= l;
+      recorditem(w1, w0, w2, shadeType);
+    }
+  }
+}
+
+static void
+drawtriangle(int i, GLfloat data[][3], int ndx[][3],
+  GLenum shadeType)
+{
+  GLfloat *x0, *x1, *x2;
+
+  x0 = data[ndx[i][0]];
+  x1 = data[ndx[i][1]];
+  x2 = data[ndx[i][2]];
+  subdivide(x0, x1, x2, shadeType);
+}
+
+/* octahedron data: The octahedron produced is centered at the
+   origin and has radius 1.0 */
+static GLfloat odata[6][3] =
+{
+  {1.0, 0.0, 0.0},
+  {-1.0, 0.0, 0.0},
+  {0.0, 1.0, 0.0},
+  {0.0, -1.0, 0.0},
+  {0.0, 0.0, 1.0},
+  {0.0, 0.0, -1.0}
+};
+
+static int ondex[8][3] =
+{
+  {0, 4, 2},
+  {1, 2, 4},
+  {0, 3, 4},
+  {1, 4, 3},
+  {0, 2, 5},
+  {1, 5, 2},
+  {0, 5, 3},
+  {1, 3, 5}
+};
+
+static void
+octahedron(GLenum shadeType)
+{
+  int i;
+
+  for (i = 7; i >= 0; i--) {
+    drawtriangle(i, odata, ondex, shadeType);
+  }
+}
+
+/* CENTRY */
+void APIENTRY
+glutWireOctahedron(void)
+{
+  octahedron(GL_LINE_LOOP);
+}
+
+void APIENTRY
+glutSolidOctahedron(void)
+{
+  octahedron(GL_TRIANGLES);
+}
+
+/* ENDCENTRY */
+
+/* icosahedron data: These numbers are rigged to make an
+   icosahedron of radius 1.0 */
+
+#define X .525731112119133606
+#define Z .850650808352039932
+
+static GLfloat idata[12][3] =
+{
+  {-X, 0, Z},
+  {X, 0, Z},
+  {-X, 0, -Z},
+  {X, 0, -Z},
+  {0, Z, X},
+  {0, Z, -X},
+  {0, -Z, X},
+  {0, -Z, -X},
+  {Z, X, 0},
+  {-Z, X, 0},
+  {Z, -X, 0},
+  {-Z, -X, 0}
+};
+
+static int index[20][3] =
+{
+  {0, 4, 1},
+  {0, 9, 4},
+  {9, 5, 4},
+  {4, 5, 8},
+  {4, 8, 1},
+  {8, 10, 1},
+  {8, 3, 10},
+  {5, 3, 8},
+  {5, 2, 3},
+  {2, 7, 3},
+  {7, 10, 3},
+  {7, 6, 10},
+  {7, 11, 6},
+  {11, 0, 6},
+  {0, 1, 6},
+  {6, 1, 10},
+  {9, 0, 11},
+  {9, 11, 2},
+  {9, 2, 5},
+  {7, 2, 11},
+};
+
+static void
+icosahedron(GLenum shadeType)
+{
+  int i;
+
+  for (i = 19; i >= 0; i--) {
+    drawtriangle(i, idata, index, shadeType);
+  }
+}
+
+/* CENTRY */
+void APIENTRY
+glutWireIcosahedron(void)
+{
+  icosahedron(GL_LINE_LOOP);
+}
+
+void APIENTRY
+glutSolidIcosahedron(void)
+{
+  icosahedron(GL_TRIANGLES);
+}
+
+/* ENDCENTRY */
+
+/* tetrahedron data: */
+
+#define T       1.73205080756887729
+
+static GLfloat tdata[4][3] =
+{
+  {T, T, T},
+  {T, -T, -T},
+  {-T, T, -T},
+  {-T, -T, T}
+};
+
+static int tndex[4][3] =
+{
+  {0, 1, 3},
+  {2, 1, 0},
+  {3, 2, 0},
+  {1, 2, 3}
+};
+
+static void
+tetrahedron(GLenum shadeType)
+{
+  int i;
+
+  for (i = 3; i >= 0; i--)
+    drawtriangle(i, tdata, tndex, shadeType);
+}
+
+/* CENTRY */
+void APIENTRY
+glutWireTetrahedron(void)
+{
+  tetrahedron(GL_LINE_LOOP);
+}
+
+void APIENTRY
+glutSolidTetrahedron(void)
+{
+  tetrahedron(GL_TRIANGLES);
+}
+
+/* ENDCENTRY */
diff --git a/src/glut/mini/overlay.c b/src/glut/mini/overlay.c
new file mode 100644 (file)
index 0000000..fc8a8e5
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.4
+ * Copyright (C) 1995-1998  Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * DOS/DJGPP glut driver v1.0 for Mesa 4.0
+ *
+ *  Copyright (C) 2002 - Borca Daniel
+ *  Email : dborca@yahoo.com
+ *  Web   : http://www.geocities.com/dborca
+ */
+
+
+#include "GL/glut.h"
+
+
+void APIENTRY glutEstablishOverlay (void)
+{
+}
+
+
+void APIENTRY glutRemoveOverlay (void)
+{
+}
+
+
+void APIENTRY glutUseLayer (GLenum layer)
+{
+}
+
+
+void APIENTRY glutPostOverlayRedisplay (void)
+{
+}
+
+
+void APIENTRY glutShowOverlay (void)
+{
+}
+
+
+void APIENTRY glutHideOverlay (void)
+{
+}
diff --git a/src/glut/mini/state.c b/src/glut/mini/state.c
new file mode 100644 (file)
index 0000000..81aefc5
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.4
+ * Copyright (C) 1995-1998  Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * DOS/DJGPP glut driver v1.0 for Mesa 4.0
+ *
+ *  Copyright (C) 2002 - Borca Daniel
+ *  Email : dborca@yahoo.com
+ *  Web   : http://www.geocities.com/dborca
+ */
+
+
+#include "GL/glut.h"
+#include <sys/time.h>
+
+
+#define TIMEDELTA(dest, src1, src2) {                          \
+   if(((dest).tv_usec = (src1).tv_usec - (src2).tv_usec) < 0) {        \
+      (dest).tv_usec += 1000000;                               \
+      (dest).tv_sec = (src1).tv_sec - (src2).tv_sec - 1;       \
+   } else {                                                    \
+      (dest).tv_sec = (src1).tv_sec - (src2).tv_sec;           \
+   }                                                           \
+}
+
+int APIENTRY glutGet (GLenum type)
+{
+   
+   switch (type) {
+   case GLUT_WINDOW_RGBA:
+      return 1;
+   case GLUT_ELAPSED_TIME: {
+      static int inited = 0;
+      static struct timeval elapsed, beginning, now;
+      if (!inited) {
+        gettimeofday(&beginning, 0);
+        inited = 1;
+      }
+      gettimeofday(&now, 0);
+      TIMEDELTA(elapsed, now, beginning);
+      /* Return elapsed milliseconds. */
+      return (int) ((elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000));
+   }
+   default:
+      return 0;
+   }
+}
+
+
+int APIENTRY glutDeviceGet (GLenum type)
+{
+ return 0;
+}
diff --git a/src/glut/mini/teapot.c b/src/glut/mini/teapot.c
new file mode 100644 (file)
index 0000000..ec2a207
--- /dev/null
@@ -0,0 +1,214 @@
+
+/* Copyright (c) Mark J. Kilgard, 1994. */
+
+/**
+(c) Copyright 1993, Silicon Graphics, Inc.
+
+ALL RIGHTS RESERVED
+
+Permission to use, copy, modify, and distribute this software
+for any purpose and without fee is hereby granted, provided
+that the above copyright notice appear in all copies and that
+both the copyright notice and this permission notice appear in
+supporting documentation, and that the name of Silicon
+Graphics, Inc. not be used in advertising or publicity
+pertaining to distribution of the software without specific,
+written prior permission.
+
+THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU
+"AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR
+OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
+MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  IN NO
+EVENT SHALL SILICON GRAPHICS, INC.  BE LIABLE TO YOU OR ANYONE
+ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER,
+INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE,
+SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR
+NOT SILICON GRAPHICS, INC.  HAS BEEN ADVISED OF THE POSSIBILITY
+OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR
+PERFORMANCE OF THIS SOFTWARE.
+
+US Government Users Restricted Rights
+
+Use, duplication, or disclosure by the Government is subject to
+restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
+(c)(1)(ii) of the Rights in Technical Data and Computer
+Software clause at DFARS 252.227-7013 and/or in similar or
+successor clauses in the FAR or the DOD or NASA FAR
+Supplement.  Unpublished-- rights reserved under the copyright
+laws of the United States.  Contractor/manufacturer is Silicon
+Graphics, Inc., 2011 N.  Shoreline Blvd., Mountain View, CA
+94039-7311.
+
+OpenGL(TM) is a trademark of Silicon Graphics, Inc.
+*/
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include "GL/glut.h"
+
+/* Rim, body, lid, and bottom data must be reflected in x and
+   y; handle and spout data across the y axis only.  */
+
+static int patchdata[][16] =
+{
+    /* rim */
+  {102, 103, 104, 105, 4, 5, 6, 7, 8, 9, 10, 11,
+    12, 13, 14, 15},
+    /* body */
+  {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
+    24, 25, 26, 27},
+  {24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36,
+    37, 38, 39, 40},
+    /* lid */
+  {96, 96, 96, 96, 97, 98, 99, 100, 101, 101, 101,
+    101, 0, 1, 2, 3,},
+  {0, 1, 2, 3, 106, 107, 108, 109, 110, 111, 112,
+    113, 114, 115, 116, 117},
+    /* bottom */
+  {118, 118, 118, 118, 124, 122, 119, 121, 123, 126,
+    125, 120, 40, 39, 38, 37},
+    /* handle */
+  {41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
+    53, 54, 55, 56},
+  {53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
+    28, 65, 66, 67},
+    /* spout */
+  {68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
+    80, 81, 82, 83},
+  {80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+    92, 93, 94, 95}
+};
+/* *INDENT-OFF* */
+
+static float cpdata[][3] =
+{
+    {0.2, 0, 2.7}, {0.2, -0.112, 2.7}, {0.112, -0.2, 2.7}, {0,
+    -0.2, 2.7}, {1.3375, 0, 2.53125}, {1.3375, -0.749, 2.53125},
+    {0.749, -1.3375, 2.53125}, {0, -1.3375, 2.53125}, {1.4375,
+    0, 2.53125}, {1.4375, -0.805, 2.53125}, {0.805, -1.4375,
+    2.53125}, {0, -1.4375, 2.53125}, {1.5, 0, 2.4}, {1.5, -0.84,
+    2.4}, {0.84, -1.5, 2.4}, {0, -1.5, 2.4}, {1.75, 0, 1.875},
+    {1.75, -0.98, 1.875}, {0.98, -1.75, 1.875}, {0, -1.75,
+    1.875}, {2, 0, 1.35}, {2, -1.12, 1.35}, {1.12, -2, 1.35},
+    {0, -2, 1.35}, {2, 0, 0.9}, {2, -1.12, 0.9}, {1.12, -2,
+    0.9}, {0, -2, 0.9}, {-2, 0, 0.9}, {2, 0, 0.45}, {2, -1.12,
+    0.45}, {1.12, -2, 0.45}, {0, -2, 0.45}, {1.5, 0, 0.225},
+    {1.5, -0.84, 0.225}, {0.84, -1.5, 0.225}, {0, -1.5, 0.225},
+    {1.5, 0, 0.15}, {1.5, -0.84, 0.15}, {0.84, -1.5, 0.15}, {0,
+    -1.5, 0.15}, {-1.6, 0, 2.025}, {-1.6, -0.3, 2.025}, {-1.5,
+    -0.3, 2.25}, {-1.5, 0, 2.25}, {-2.3, 0, 2.025}, {-2.3, -0.3,
+    2.025}, {-2.5, -0.3, 2.25}, {-2.5, 0, 2.25}, {-2.7, 0,
+    2.025}, {-2.7, -0.3, 2.025}, {-3, -0.3, 2.25}, {-3, 0,
+    2.25}, {-2.7, 0, 1.8}, {-2.7, -0.3, 1.8}, {-3, -0.3, 1.8},
+    {-3, 0, 1.8}, {-2.7, 0, 1.575}, {-2.7, -0.3, 1.575}, {-3,
+    -0.3, 1.35}, {-3, 0, 1.35}, {-2.5, 0, 1.125}, {-2.5, -0.3,
+    1.125}, {-2.65, -0.3, 0.9375}, {-2.65, 0, 0.9375}, {-2,
+    -0.3, 0.9}, {-1.9, -0.3, 0.6}, {-1.9, 0, 0.6}, {1.7, 0,
+    1.425}, {1.7, -0.66, 1.425}, {1.7, -0.66, 0.6}, {1.7, 0,
+    0.6}, {2.6, 0, 1.425}, {2.6, -0.66, 1.425}, {3.1, -0.66,
+    0.825}, {3.1, 0, 0.825}, {2.3, 0, 2.1}, {2.3, -0.25, 2.1},
+    {2.4, -0.25, 2.025}, {2.4, 0, 2.025}, {2.7, 0, 2.4}, {2.7,
+    -0.25, 2.4}, {3.3, -0.25, 2.4}, {3.3, 0, 2.4}, {2.8, 0,
+    2.475}, {2.8, -0.25, 2.475}, {3.525, -0.25, 2.49375},
+    {3.525, 0, 2.49375}, {2.9, 0, 2.475}, {2.9, -0.15, 2.475},
+    {3.45, -0.15, 2.5125}, {3.45, 0, 2.5125}, {2.8, 0, 2.4},
+    {2.8, -0.15, 2.4}, {3.2, -0.15, 2.4}, {3.2, 0, 2.4}, {0, 0,
+    3.15}, {0.8, 0, 3.15}, {0.8, -0.45, 3.15}, {0.45, -0.8,
+    3.15}, {0, -0.8, 3.15}, {0, 0, 2.85}, {1.4, 0, 2.4}, {1.4,
+    -0.784, 2.4}, {0.784, -1.4, 2.4}, {0, -1.4, 2.4}, {0.4, 0,
+    2.55}, {0.4, -0.224, 2.55}, {0.224, -0.4, 2.55}, {0, -0.4,
+    2.55}, {1.3, 0, 2.55}, {1.3, -0.728, 2.55}, {0.728, -1.3,
+    2.55}, {0, -1.3, 2.55}, {1.3, 0, 2.4}, {1.3, -0.728, 2.4},
+    {0.728, -1.3, 2.4}, {0, -1.3, 2.4}, {0, 0, 0}, {1.425,
+    -0.798, 0}, {1.5, 0, 0.075}, {1.425, 0, 0}, {0.798, -1.425,
+    0}, {0, -1.5, 0.075}, {0, -1.425, 0}, {1.5, -0.84, 0.075},
+    {0.84, -1.5, 0.075}
+};
+
+static float tex[2][2][2] =
+{
+  { {0, 0},
+    {1, 0}},
+  { {0, 1},
+    {1, 1}}
+};
+
+/* *INDENT-ON* */
+
+static void
+teapot(GLint grid, GLdouble scale, GLenum type)
+{
+  float p[4][4][3], q[4][4][3], r[4][4][3], s[4][4][3];
+  long i, j, k, l;
+
+#if 0
+  glPushAttrib(GL_ENABLE_BIT | GL_EVAL_BIT);
+  glEnable(GL_AUTO_NORMAL);
+  glEnable(GL_NORMALIZE);
+  glEnable(GL_MAP2_VERTEX_3);
+  glEnable(GL_MAP2_TEXTURE_COORD_2);
+  glPushMatrix();
+  glRotatef(270.0, 1.0, 0.0, 0.0);
+  glScalef(0.5 * scale, 0.5 * scale, 0.5 * scale);
+  glTranslatef(0.0, 0.0, -1.5);
+  for (i = 0; i < 10; i++) {
+    for (j = 0; j < 4; j++) {
+      for (k = 0; k < 4; k++) {
+        for (l = 0; l < 3; l++) {
+          p[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
+          q[j][k][l] = cpdata[patchdata[i][j * 4 + (3 - k)]][l];
+          if (l == 1)
+            q[j][k][l] *= -1.0;
+          if (i < 6) {
+            r[j][k][l] =
+              cpdata[patchdata[i][j * 4 + (3 - k)]][l];
+            if (l == 0)
+              r[j][k][l] *= -1.0;
+            s[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
+            if (l == 0)
+              s[j][k][l] *= -1.0;
+            if (l == 1)
+              s[j][k][l] *= -1.0;
+          }
+        }
+      }
+    }
+    glMap2f(GL_MAP2_TEXTURE_COORD_2, 0, 1, 2, 2, 0, 1, 4, 2,
+      &tex[0][0][0]);
+    glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4,
+      &p[0][0][0]);
+    glMapGrid2f(grid, 0.0, 1.0, grid, 0.0, 1.0);
+    glEvalMesh2(type, 0, grid, 0, grid);
+    glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4,
+      &q[0][0][0]);
+    glEvalMesh2(type, 0, grid, 0, grid);
+    if (i < 6) {
+      glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4,
+        &r[0][0][0]);
+      glEvalMesh2(type, 0, grid, 0, grid);
+      glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4,
+        &s[0][0][0]);
+      glEvalMesh2(type, 0, grid, 0, grid);
+    }
+  }
+  glPopMatrix();
+  glPopAttrib();
+#endif
+}
+
+/* CENTRY */
+void APIENTRY 
+glutSolidTeapot(GLdouble scale)
+{
+  teapot(7, scale, GL_FILL);
+}
+
+void APIENTRY 
+glutWireTeapot(GLdouble scale)
+{
+  teapot(10, scale, GL_LINE);
+}
+
+/* ENDCENTRY */
diff --git a/src/glut/mini/window.c b/src/glut/mini/window.c
new file mode 100644 (file)
index 0000000..7326676
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  4.1
+ * Copyright (C) 1995-1998  Brian Paul
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * DOS/DJGPP glut driver v1.2 for Mesa 4.1
+ *
+ *  Copyright (C) 2002 - Borca Daniel
+ *  Email : dborca@yahoo.com
+ *  Web   : http://www.geocities.com/dborca
+ */
+
+
+#include <stdio.h>
+#include <GL/gl.h>
+#include "GL/glut.h"
+#include "internal.h"
+
+#define USE_MINI_GLX 1
+#if USE_MINI_GLX
+#include "GL/miniglx.h"
+#else
+#include <GL/glx.h>
+#endif
+
+
+
+static GLXContext context = 0;
+static Window win;
+static XVisualInfo *visinfo = 0;
+static Display *dpy = 0;
+
+
+int APIENTRY glutCreateWindow (const char *title)
+{
+   XSetWindowAttributes attr;
+   unsigned long mask;
+   GLXContext ctx;
+   int scrnum = 0;
+   Window root = RootWindow( dpy, scrnum );
+
+   if (win)
+      return 0;
+
+   if (!dpy) {
+      dpy = XOpenDisplay(NULL);
+      if (!dpy) {
+        printf("Error: XOpenDisplay failed\n");
+        exit(1);
+      }
+   }
+
+   if (!visinfo) {
+      int attrib[] = {GLX_RGBA,
+                     GLX_RED_SIZE, 1,
+                     GLX_GREEN_SIZE, 1,
+                     GLX_BLUE_SIZE, 1,
+                     GLX_DEPTH_SIZE, 1,
+                     GLX_DOUBLEBUFFER, 
+                     None };
+
+    
+      visinfo = glXChooseVisual( dpy, scrnum, attrib );
+      if (!visinfo) {
+        printf("Error: couldn't get an RGB, Double-buffered visual\n");
+        exit(1);
+      }
+   }
+
+   /* window attributes */
+   attr.background_pixel = 0;
+   attr.border_pixel = 0;
+   attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
+   attr.event_mask = StructureNotifyMask | ExposureMask;
+   mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+   win = XCreateWindow( dpy, root, 0, 0, g_width, g_height,
+                       0, visinfo->depth, InputOutput,
+                       visinfo->visual, mask, &attr );
+   if (!win) {
+      printf("Error: XCreateWindow failed\n");
+      exit(1);
+   }
+
+   ctx = glXCreateContext( dpy, visinfo, NULL, True );
+   if (!ctx) {
+      printf("Error: glXCreateContext failed\n");
+      exit(1);
+   }
+
+   if (!glXMakeCurrent( dpy, win, ctx )) {
+      printf("Error: glXMakeCurrent failed\n");
+      exit(1);
+   }
+
+   if (!(g_display_mode & GLUT_DOUBLE))
+      glDrawBuffer( GL_FRONT );
+      
+
+   XMapWindow( dpy, win );
+
+#if !USE_MINI_GLX
+   {
+      XEvent e;
+      while (1) {
+        XNextEvent( dpy, &e );
+        if (e.type == MapNotify && e.xmap.window == win) {
+           break;
+        }
+      }
+   }
+#endif
+
+   return 1;
+}
+
+
+int APIENTRY glutCreateSubWindow (int win, int x, int y, int width, int height)
+{
+   return GL_FALSE;
+}
+
+
+void APIENTRY glutDestroyWindow (int idx)
+{
+   if (dpy && win)
+      XDestroyWindow( dpy, win );
+
+   if (dpy) 
+      XCloseDisplay( dpy );
+
+   win = 0;
+   dpy = 0;
+}
+
+
+void APIENTRY glutPostRedisplay (void)
+{
+ g_redisplay = GL_TRUE;
+}
+
+
+void APIENTRY glutSwapBuffers (void)
+{
+/*  if (g_mouse) pc_scare_mouse(); */
+   if (dpy && win) glXSwapBuffers( dpy, win );
+/*  if (g_mouse) pc_unscare_mouse(); */
+}
+
+
+int APIENTRY glutGetWindow (void)
+{
+   return 0;
+}
+
+
+void APIENTRY glutSetWindow (int win)
+{
+}
+
+
+void APIENTRY glutSetWindowTitle (const char *title)
+{
+}
+
+
+void APIENTRY glutSetIconTitle (const char *title)
+{
+}
+
+
+void APIENTRY glutPositionWindow (int x, int y)
+{
+}
+
+
+void APIENTRY glutReshapeWindow (int width, int height)
+{
+}
+
+
+void APIENTRY glutPopWindow (void)
+{
+}
+
+
+void APIENTRY glutPushWindow (void)
+{
+}
+
+
+void APIENTRY glutIconifyWindow (void)
+{
+}
+
+
+void APIENTRY glutShowWindow (void)
+{
+}
+
+
+void APIENTRY glutHideWindow (void)
+{
+}
+
+void APIENTRY glutMainLoop (void)
+{
+   GLboolean idle;
+   GLboolean have_event;
+   XEvent evt;
+   int visible = 0;
+
+   glutPostRedisplay();
+   if (reshape_func) reshape_func(g_width, g_height);
+
+   while (GL_TRUE) {
+      idle = GL_TRUE;
+
+
+      if (visible && idle_func) 
+        have_event = XCheckMaskEvent( dpy, ~0, &evt );
+      else 
+        have_event = XNextEvent( dpy, &evt );
+
+      if (have_event) {
+        idle = GL_FALSE;
+        switch(evt.type) {
+        case MapNotify:
+           if (visibility_func) {
+              visibility_func(GLUT_VISIBLE);
+           }
+           visible = 1;
+           break;
+        case UnmapNotify:
+           if (visibility_func) {
+              visibility_func(GLUT_NOT_VISIBLE);
+           }
+           visible = 0;
+           break;
+        case Expose:
+           g_redisplay = 1;
+           break;
+        }
+      }
+
+      if (visible && g_redisplay && display_func) {
+        idle        = GL_FALSE;
+        g_redisplay = GL_FALSE;
+
+        display_func();
+      }
+
+      if (visible && idle && idle_func) {
+        idle_func();
+      }
+   }
+}
diff --git a/src/glx/mini/Makefile.X11 b/src/glx/mini/Makefile.X11
new file mode 100644 (file)
index 0000000..2e818f0
--- /dev/null
@@ -0,0 +1,79 @@
+# Build a subset DRI-based libGL.so library.
+# Indirect rendering not supported, etc.
+
+TOP = ../../..
+
+default: linux-solo
+
+C_SOURCES = dispatch.c \
+         dri_util.c \
+         ../../mesa/glapi/glapi.c \
+         ../../mesa/glapi/glthread.c \
+         miniglx.c \
+         miniglx_events.c \
+         xf86drm.c 
+
+OBJECTS = $(C_SOURCES:.c=.o)
+
+INCLUDES = -I. $(INCLUDE_DIRS)
+LIBS = -ldl 
+
+### 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 $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
+
+.S.o:
+       $(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES)  $< -o $@
+
+
+##### TARGETS #####
+
+targets: depend libGL.so.1.2
+
+libGL.so.1.2:  $(OBJECTS) Makefile.X11
+       rm -f $@ && gcc -shared -Wl,-soname,libGL.so -Wl,-Bsymbolic $(OBJECTS) $(LIBS) -o $@ 
+       rm -f $(TOP)/lib/libGL.so* 
+       rm -f $(TOP)/lib/miniglx.conf
+       install -D libGL.so.1.2 $(TOP)/lib/libGL.so.1.2
+       ln -s libGL.so.1.2 $(TOP)/lib/libGL.so.1
+       ln -s libGL.so.1 $(TOP)/lib/libGL.so
+       install example.miniglx.conf $(TOP)/lib/miniglx.conf
+
+drmtest: xf86drm.o drmtest.o
+       rm -f drmtest && $(CC) -o drmtest xf86drm.o drmtest.o
+
+# 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 $(INCLUDES) \
+               $(C_SOURCES) $(ASM_SOURCES)
+
+
+# Emacs tags
+tags:
+       etags `find . -name \*.[ch]` `find ../include`
+
+
+# Remove .o and backup files
+clean:
+       -rm -f drmtest $(TOP)/lib/libGL.so*
+       -rm -f */*.o */*~ */*.o */*~
+
+
+include $(TOP)/Make-config
+
+include depend
diff --git a/src/glx/mini/NOTES b/src/glx/mini/NOTES
new file mode 100644 (file)
index 0000000..1774107
--- /dev/null
@@ -0,0 +1,115 @@
+
+
+Getting MiniGLX up and running
+------------------------------
+
+It's necessary to do a bit of work to set up an environment to run miniglx. 
+
+For the radeon driver, it's necessary to get the right set of kernel
+modules installed before attempting to run any programs:
+
+    rmmod radeon agpgart;
+    insmod agpgart;
+    insmod $(MESA)/src/kernel/radeonfb/radeonfb.o;
+    insmod $(MESA)/src/kernel/radeon/radeon.o;
+
+For all drivers, its necessary to reach the compiled libraries, and
+tell MiniGLX where to find it's configuration file:
+
+    export LD_LIBRARY_PATH=$(MESA)/lib;
+    export MINIGLX_CONF=$(MESA)/lib/miniglx.conf
+
+------------------------------------------------------------
+
+MiniGLX Example Programs
+------------------------
+
+The following programs will work with miniglx:
+       
+       $(MESA)/tests/miniglx
+       $(MESA)/xdemos/glxgears  
+
+Thanks to the miniglut stub library, most of the mesa glut demos will
+work.  In particular, the following have been tested.  (Note there is
+no keyboard or mouse interaction with these demos).
+
+       $(MESA)/demos/gears
+       $(MESA)/demos/geartrain
+       $(MESA)/demos/morph3d
+       $(MESA)/demos/isosurf
+       $(MESA)/demos/texobj
+       $(MESA)/demos/texcyl
+       $(MESA)/demos/gloss
+       $(MESA)/demos/fire
+       $(MESA)/demos/tunnel
+       $(MESA)/demos/teapot
+       $(MESA)/samples/prim
+       $(MESA)/samples/olympic
+       $(MESA)/samples/star
+       $(MESA)/samples/wave
+       ...etc
+
+In fact most of the glut demos seem to work within the constraints of
+having no keyboard/mouse interactivity.  Furthermore, the use of the
+glut wrapper means that these programs don't require recompilation to
+run under MiniGLX -- the same binary works with both regular GLX and
+MiniGLX.
+
+
+------------------------------------------------------------
+
+Porting GLX apps to MiniGLX
+---------------------------
+
+A quick list of issues encountered in porting existing GLX apps to
+MiniGLX.  Listed in no particular order.
+
+1) No input events
+
+MiniGLX doesn't provide an input layer, so any X11 input event
+handling in the existing app will have to be redone for whatever
+input devices exist on the target.
+
+2) No configuration, expose events
+
+Many GLX and Xlib programs wait on an event to ensure the window has
+become visible after being mapped.  MiniGLX provides no equivalent
+facility.
+
+3) Different headers
+
+X11/Xlib.h, GL/GLX.h, etc must not be used if the program is being
+compiled against MiniGLX.
+
+The equivalent header is GL/MiniGLX.h.
+
+4) Different library
+
+It may be necessary to link directly against the minGLX libGL.so.
+
+5) Reduced number of Xlib and GLX entrypoints.
+
+By definition (MiniGLX is a subset of GLX), many Xlib and GLX
+entrypoints, structures and macros are not present in MiniGLX.  It
+will be necessary to find and eliminate all references to
+non-supported entrypoints.
+
+
+---------------------------------------------------------------
+
+Bugs in radeonfb.o -- the radeon framebuffer driver.
+----------------------------------------------------
+
+Several bugs have been found in the radeonfb.o framebuffer driver.
+Most of these are resolved in the version included in the MiniGLX
+sources, but some remain:
+
+1) Occasionally, after entering graphics mode, colors appear 'shifted'
+or 'translated', particularly in higher resolution modes.  This is
+definitely a bug in radeonfb.o as this can be provoked even when using
+the software dri driver (fb_dri.so).  Importance: High.  Workaround:
+Use 800x600 as it seems to be less frequent at this resolution,
+otherwise, restart the application.
+
+
+
diff --git a/src/glx/mini/dispatch.c b/src/glx/mini/dispatch.c
new file mode 100644 (file)
index 0000000..264cd4c
--- /dev/null
@@ -0,0 +1,64 @@
+/**
+ * \file miniglx/dispatch.c
+ *
+ * \brief C-based dispatch of the OpenGL entry points (glAccum(), glBegin(),
+ * etc).
+ * 
+ * \author Brian Paul <brian@precisioninsight.com>
+ * 
+ * \note This code IS NOT USED if we're compiling on an x86 system and using
+ * the glapi_x86.S assembly code.
+ */
+
+/* 
+ * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <GL/gl.h>
+#include "glapi.h"
+#include "glapitable.h"
+
+
+#if !(defined(USE_X86_ASM) || defined(USE_SPARC_ASM))
+
+#define KEYWORD1
+
+#define KEYWORD2
+
+#define NAME(func) gl##func
+
+#define DISPATCH(func, args, msg)                                      \
+   const struct _glapi_table *dispatch;                                        \
+   dispatch = _glapi_Dispatch ? _glapi_Dispatch : _glapi_get_dispatch();\
+   (dispatch->func) args
+
+#define RETURN_DISPATCH(func, args, msg)                               \
+   const struct _glapi_table *dispatch;                                        \
+   dispatch = _glapi_Dispatch ? _glapi_Dispatch : _glapi_get_dispatch();\
+   return (dispatch->func) args
+
+
+#include "glapitemp.h"
+
+#endif /* USE_X86_ASM */
diff --git a/src/glx/mini/dri.h b/src/glx/mini/dri.h
new file mode 100644 (file)
index 0000000..71f9a1a
--- /dev/null
@@ -0,0 +1,124 @@
+/**
+ * \file miniglxP.h
+ * \brief Define replacements for some X data types and define the DRI-related
+ * data structures.
+ *
+ * \note Cut down version of glxclient.h.
+ *
+ */
+
+#ifndef _dri_h_
+#define _dri_h_
+
+#include "driver.h"
+
+typedef struct __DRIscreenRec   __DRIscreen;   /**< \copydoc __DRIscreenRec */
+typedef struct __DRIcontextRec  __DRIcontext;  /**< \copydoc __DRIcontextRec */
+typedef struct __DRIdrawableRec __DRIdrawable; /**< \copydoc __DRIdrawableRec */
+
+/**
+ * \brief Screen dependent methods.
+ *
+ * This structure is initialized during the MiniGLXDisplayRec::createScreen
+ * call.
+ */
+struct __DRIscreenRec {
+    /**
+     * \brief Method to destroy the private DRI screen data.
+     */
+    void (*destroyScreen)(__DRIscreen *screen);
+
+    /**
+     * \brief Method to create the private DRI context data and initialize the
+     * context dependent methods.
+     */
+    void *(*createContext)(__DRIscreen *screen, const __GLcontextModes *glVisual,
+                          void *sharedPrivate);
+    /**
+     * \brief Method to create the private DRI drawable data and initialize the
+     * drawable dependent methods.
+     */
+    void *(*createDrawable)(__DRIscreen *screen,
+                           int width, int height, int index,
+                           const __GLcontextModes *glVisual);
+
+    /*
+     * XXX in the future, implement this:
+    void *(*createPBuffer)(Display *dpy, int scrn, GLXPbuffer pbuffer,
+                          GLXFBConfig config, __DRIdrawable *pdraw);
+     */
+
+    /**
+     * \brief Opaque pointer to private per screen direct rendering data.  
+     *
+     * \c NULL if direct rendering is not supported on this screen.  Never
+     * dereferenced in libGL.
+     */
+};
+
+/**
+ * \brief Context dependent methods. 
+ * 
+ * This structure is initialized during the __DRIscreenRec::createContext call.
+ */
+struct __DRIcontextRec {
+    /**
+     * \brief Method to destroy the private DRI context data.
+     */
+    void (*destroyContext)(__DRIcontext *context);
+
+    /**
+     * \brief Method to bind a DRI drawable to a DRI graphics context.
+     * 
+     * \todo XXX in the future, also pass a 'read' GLXDrawable for
+     * glXMakeCurrentReadSGI() and GLX 1.3's glXMakeContextCurrent().
+     */
+    GLboolean (*bindContext)(__DRIscreen *screen, __DRIdrawable *drawable, __DRIcontext *context);
+
+    /**
+     * \brief Method to unbind a DRI drawable to a DRI graphics context.
+     */
+    GLboolean (*unbindContext)(__DRIdrawable *drawable, __DRIcontext *context);
+    /**
+     * \brief Opaque pointer to private per context direct rendering data.
+     * 
+     * NULL if direct rendering is not supported on the display or
+     * screen used to create this context.  Never dereferenced in libGL.
+     */
+};
+
+/**
+ * \brief Drawable dependent methods.
+ *
+ * This structure is initialized during the __DRIscreenRec::createDrawable call.
+ *
+ * __DRIscreenRec::createDrawable is not called by libGL at this time.  It's
+ * currently used via the dri_util.c utility code instead.
+ */
+struct __DRIdrawableRec {
+    /**
+     * \brief Method to destroy the private DRI drawable data.
+     */
+    void (*destroyDrawable)(__DRIdrawable *drawable);
+
+
+    /**
+     * \brief Method to swap the front and back buffers.
+     */
+    void (*swapBuffers)(__DRIdrawable *drawable);
+
+    /**
+     * \brief Opaque pointer to private per drawable direct rendering data.
+     * 
+     * \c NULL if direct rendering is not supported on the display or
+     * screen used to create this drawable.  Never dereferenced in libGL.
+     */
+};
+
+typedef void *(driCreateScreenFunc)(struct DRIDriverRec *driver,
+                  struct DRIDriverContextRec *driverContext);
+
+/** This must be implemented in each driver */
+extern driCreateScreenFunc __driCreateScreen;
+
+#endif /* _dri_h_ */
diff --git a/src/glx/mini/dri_util.c b/src/glx/mini/dri_util.c
new file mode 100644 (file)
index 0000000..6d79d20
--- /dev/null
@@ -0,0 +1,715 @@
+/**
+ * \file dri_util.c
+ * \brief DRI utility functions.
+ *
+ * This module acts as glue between GLX and the actual hardware driver.  A DRI
+ * driver doesn't really \e have to use any of this - it's optional.  But, some
+ * useful stuff is done here that otherwise would have to be duplicated in most
+ * drivers.
+ * 
+ * Basically, these utility functions take care of some of the dirty details of
+ * screen initialization, context creation, context binding, DRM setup, etc.
+ *
+ * These functions are compiled into each DRI driver so libGL.so knows nothing
+ * about them.
+ *
+ */
+
+#include <assert.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <linux/fb.h>
+#include <linux/vt.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/shm.h>
+
+#include "sarea.h"
+#include "dri_util.h"
+
+/**
+ * \brief Print message to \c stderr if the \c LIBGL_DEBUG environment variable
+ * is set.
+ * 
+ * Is called from the drivers.
+ * 
+ * \param f \e printf like format.
+ * 
+ * \internal
+ * This function is a wrapper around vfprintf().
+ */
+void
+__driUtilMessage(const char *f, ...)
+{
+    va_list args;
+
+    if (getenv("LIBGL_DEBUG")) {
+        fprintf(stderr, "libGL error: \n");
+        va_start(args, f);
+        vfprintf(stderr, f, args);
+        va_end(args);
+        fprintf(stderr, "\n");
+    }
+}
+
+
+/*****************************************************************/
+/** \name Visual utility functions                               */
+/*****************************************************************/
+/*@{*/
+
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Context (un)binding functions                          */
+/*****************************************************************/
+/*@{*/
+
+
+/**
+ * \brief Unbind context.
+ * 
+ * \param drawable __DRIdrawable
+ * \param context __DRIcontext
+ * \param will_rebind not used.
+ *
+ * \return GL_TRUE on success, or GL_FALSE on failure.
+ * 
+ * \internal
+ * This function calls __DriverAPIRec::UnbindContext, and then decrements
+ * __DRIdrawablePrivateRec::refcount which must be non-zero for a successful
+ * return.
+ * 
+ * While casting the opaque private pointers associated with the parameters into their
+ * respective real types it also assures they are not null. 
+ */
+static GLboolean driUnbindContext(__DRIdrawable *drawable, 
+                                 __DRIcontext *context)
+{
+    __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)drawable;
+    __DRIcontextPrivate  *pcp =  (__DRIcontextPrivate  *)context;
+    __DRIscreenPrivate *psp;
+
+    if (pdp == NULL || pcp == NULL) 
+       return GL_FALSE;
+
+    if (!(psp = (__DRIscreenPrivate *)pdp->driScreenPriv)) 
+       return GL_FALSE;
+
+    /* Let driver unbind drawable from context */
+    (*psp->DriverAPI.UnbindContext)(pcp);
+
+    if (pdp->refcount == 0) 
+       return GL_FALSE;
+
+    --pdp->refcount;
+
+    return GL_TRUE;
+}
+
+
+/**
+ * \brief Unbind context.
+ * 
+ * \param pDRIScreen __DRIscreen
+ * \param drawable __DRIdrawable
+ * \param context __DRIcontext
+ *
+ * \internal
+ * This function and increments __DRIdrawablePrivateRec::refcount and calls
+ * __DriverAPIRec::MakeCurrent to binds the drawable.
+ * 
+ * While casting the opaque private pointers into their
+ * respective real types it also assures they are not null. 
+ */
+static GLboolean driBindContext(__DRIscreen *screen, __DRIdrawable *drawable, 
+                               __DRIcontext *context)
+{
+    __DRIscreenPrivate *psp = (__DRIscreenPrivate *)screen;
+    __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)drawable;
+    __DRIcontextPrivate *pcp = (__DRIcontextPrivate *)context;
+    
+    if (psp == NULL)
+       return GL_FALSE;
+    
+    if (pdp == NULL || pcp == NULL) {
+       (*psp->DriverAPI.MakeCurrent)(0, 0, 0);
+       return GL_TRUE;
+    }
+
+    /* Bind the drawable to the context */
+    pcp->driDrawablePriv = pdp;
+    pdp->driContextPriv = pcp;
+    pdp->refcount++;
+
+    /* Call device-specific MakeCurrent */
+    (*psp->DriverAPI.MakeCurrent)(pcp, pdp, pdp);
+
+    return GL_TRUE;
+}
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Drawable handling functions                            */
+/*****************************************************************/
+/*@{*/
+
+
+/**
+ * \brief Update private drawable information.
+ *
+ * \param pdp pointer to the private drawable information to update.
+ * 
+ * \internal
+ * This function is a no-op. Should never be called but is referenced as an
+ * external symbol from client drivers.
+ */
+void __driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp)
+{
+   __DRIscreenPrivate *psp = pdp->driScreenPriv;
+
+   pdp->numClipRects = psp->pSAREA->drawableTable[pdp->index].flags ? 1 : 0;
+   pdp->lastStamp = *(pdp->pStamp);
+}
+
+
+/**
+ * \brief Swap buffers.
+ *
+ * \param pDRIscreen __DRIscreen
+ * \param drawablePrivate opaque pointer to the per-drawable private info.
+ * 
+ * \internal
+ * This function calls __DRIdrawablePrivate::swapBuffers.
+ * 
+ * Is called directly from glXSwapBuffers().
+ */
+static void driSwapBuffers(__DRIdrawable *drawable)
+{
+    __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)drawable;
+    if (pdp)
+       pdp->swapBuffers(pdp);
+}
+
+
+/**
+ * \brief Destroy per-drawable private information.
+ *
+ * \param pDRIscreen __DRIscreen
+ * \param drawablePrivate opaque pointer to the per-drawable private info.
+ *
+ * \internal
+ * This function calls __DriverAPIRec::DestroyBuffer on \p drawablePrivate,
+ * frees the clip rects if any, and finally frees \p drawablePrivate itself.
+ */
+static void driDestroyDrawable(__DRIdrawable *drawable)
+{
+    __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)drawable;
+    __DRIscreenPrivate *psp;
+
+    if (pdp) {
+       psp = pdp->driScreenPriv;
+        (*psp->DriverAPI.DestroyBuffer)(pdp);
+       if (pdp->pClipRects)
+           free(pdp->pClipRects);
+       free(pdp);
+    }
+}
+
+
+/**
+ * \brief Create the per-drawable private driver information.
+ * 
+ * \param dpy the display handle.
+ * \param scrn the screen number.
+ * \param draw the GLX drawable info.
+ * \param vid visual ID.
+ * \param pdraw will receive the drawable dependent methods.
+ * 
+ *
+ * \returns a opaque pointer to the per-drawable private info on success, or NULL
+ * on failure.
+ * 
+ * \internal
+ * This function allocates and fills a __DRIdrawablePrivateRec structure,
+ * initializing the invariant window dimensions and clip rects.  It obtains the
+ * visual config, converts it into a __GLcontextModesRec and passes it to
+ * __DriverAPIRec::CreateBuffer to create a buffer.
+ */
+static void *driCreateDrawable(__DRIscreen *screen,
+                               int width, int height, int index,
+                               const __GLcontextModes *glVisual)
+{
+    __DRIscreenPrivate *psp = (__DRIscreenPrivate *)screen;
+    __DRIdrawablePrivate *pdp;
+
+    if (!psp)
+       return NULL;
+
+    if (!(pdp = (__DRIdrawablePrivate *)malloc(sizeof(__DRIdrawablePrivate))))
+       return NULL;
+
+    pdp->index = index;
+    pdp->refcount = 0;
+    pdp->lastStamp = -1;
+    pdp->numBackClipRects = 0;
+    pdp->pBackClipRects = NULL;
+
+    /* Initialize with the invariant window dimensions and clip rects here.
+     */
+    pdp->x = 0;
+    pdp->y = 0;
+    pdp->w = width;
+    pdp->h = height;
+    pdp->numClipRects = 0;
+    pdp->pClipRects = (XF86DRIClipRectPtr) malloc(sizeof(XF86DRIClipRectRec));
+    (pdp->pClipRects)[0].x1 = 0;
+    (pdp->pClipRects)[0].y1 = 0;
+    (pdp->pClipRects)[0].x2 = width;
+    (pdp->pClipRects)[0].y2 = height;
+
+    pdp->driScreenPriv = psp;
+    pdp->driContextPriv = 0;
+    
+    pdp->frontBuffer = psp->pFB;
+    pdp->currentBuffer = pdp->frontBuffer;
+    pdp->currentPitch = psp->fbStride;
+    pdp->backBuffer = psp->pFB + psp->fbStride * psp->fbHeight;
+
+    if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, glVisual, GL_FALSE)) {
+       free(pdp);
+       return NULL;
+    }
+
+    pdp->entry.destroyDrawable = driDestroyDrawable;
+    pdp->entry.swapBuffers = driSwapBuffers;  /* called by glXSwapBuffers() */
+    pdp->swapBuffers = psp->DriverAPI.SwapBuffers;
+
+    pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);
+    return (void *) pdp;
+}
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Context handling functions                             */
+/*****************************************************************/
+/*@{*/
+
+
+/**
+ * \brief Destroy the per-context private information.
+ * 
+ * \param contextPrivate opaque pointer to the per-drawable private info.
+ *
+ * \internal
+ * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
+ * drmDestroyContext(), and finally frees \p contextPrivate.
+ */
+static void driDestroyContext(__DRIcontext *context)
+{
+    __DRIcontextPrivate *pcp = (__DRIcontextPrivate *)context;
+    __DRIscreenPrivate *psp = NULL;
+
+    if (pcp) {
+       (*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp);
+        psp = pcp->driDrawablePriv->driScreenPriv;
+       if (psp->fd) {
+          printf(">>> drmDestroyContext(0x%x)\n", (int) pcp->hHWContext);
+          drmDestroyContext(psp->fd, pcp->hHWContext);
+       }
+       free(pcp);
+    }
+}
+
+/**
+ * \brief Create the per-drawable private driver information.
+ * 
+ * \param dpy the display handle.
+ * \param vis the visual information.
+ * \param sharedPrivate the shared context dependent methods or NULL if non-existent.
+ * \param pctx will receive the context dependent methods.
+ *
+ * \returns a opaque pointer to the per-context private information on success, or NULL
+ * on failure.
+ * 
+ * \internal
+ * This function allocates and fills a __DRIcontextPrivateRec structure.  It
+ * gets the visual, converts it into a __GLcontextModesRec and passes it
+ * to __DriverAPIRec::CreateContext to create the context.
+ */
+static void *driCreateContext(__DRIscreen *screen, 
+                              const __GLcontextModes *glVisual,
+                              void *sharedPrivate)
+{
+   __DRIscreenPrivate *psp = (__DRIscreenPrivate *)screen;
+   __DRIcontextPrivate *pcp;
+   __DRIcontextPrivate *pshare = (__DRIcontextPrivate *) sharedPrivate;
+   void *shareCtx;
+
+   if (!psp) 
+      return NULL;
+
+   if (!(pcp = (__DRIcontextPrivate *)malloc(sizeof(__DRIcontextPrivate))))
+      return NULL;
+
+   pcp->driScreenPriv = psp;
+   pcp->driDrawablePriv = NULL;
+
+   if (psp->fd) {
+      if (drmCreateContext(psp->fd, &pcp->hHWContext)) {
+        fprintf(stderr, ">>> drmCreateContext failed\n");
+        free(pcp);
+        return NULL;
+      }
+   }
+
+   shareCtx = pshare ? pshare->driverPrivate : NULL;
+   
+   if (!(*psp->DriverAPI.CreateContext)(glVisual, pcp, shareCtx)) {
+      if (psp->fd) 
+        (void) drmDestroyContext(psp->fd, pcp->hHWContext);
+      free(pcp);
+      return NULL;
+   }
+
+   pcp->entry.destroyContext = driDestroyContext;
+   pcp->entry.bindContext    = driBindContext;
+   pcp->entry.unbindContext  = driUnbindContext;
+
+   return pcp;
+}
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Screen handling functions                              */
+/*****************************************************************/
+/*@{*/
+
+
+/**
+ * \brief Destroy the per-screen private information.
+ * 
+ * \param pDRIscreen __DRIscreen 
+ *
+ * \internal
+ * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
+ * drmClose(), and finally frees \p screenPrivate.
+ */
+static void driDestroyScreen(__DRIscreen *screen)
+{
+    __DRIscreenPrivate *psp = (__DRIscreenPrivate *)screen;
+    if (psp) {
+       if (psp->DriverAPI.DestroyScreen)
+           (*psp->DriverAPI.DestroyScreen)(psp);
+       
+       if (psp->fd) 
+           (void)drmClose(psp->fd);
+       
+       free(psp->pDevPriv);
+       free(psp);
+    }
+}
+
+
+/**
+ * \brief Create the per-screen private information.
+ * 
+ * \param dpy the display handle.
+ * \param scrn the screen number.
+ * \param psc will receive the screen dependent methods.
+ * \param numConfigs number of visuals.
+ * \param config visuals.
+ * \param driverAPI driver callbacks structure.
+ *
+ * \return a pointer to the per-screen private information.
+ * 
+ * \internal
+ * This function allocates and fills a __DRIscreenPrivateRec structure. It
+ * opens the DRM device verifying that the exported version matches the
+ * expected.  It copies the driver callback functions and calls
+ * __DriverAPIRec::InitDriver.
+ *
+ * If a client maps the framebuffer and SAREA regions.
+ */
+__DRIscreenPrivate *    
+__driUtilCreateScreen(struct DRIDriverRec *driver,
+                     struct DRIDriverContextRec *driverContext,
+                     const struct __DriverAPIRec *driverAPI)
+{
+    __DRIscreenPrivate *psp;
+    
+    if(!(psp = (__DRIscreenPrivate *)malloc(sizeof(__DRIscreenPrivate))))
+       return NULL;
+    
+    psp->fd = drmOpen(NULL, driverContext->pciBusID);
+    if (psp->fd < 0) {
+       fprintf(stderr, "libGL error: failed to open DRM: %s\n", 
+               strerror(-psp->fd));
+       free(psp);
+       return NULL;
+    }
+    
+    {
+       drmVersionPtr version = drmGetVersion(psp->fd);
+       if (version) {
+           psp->drmMajor = version->version_major;
+           psp->drmMinor = version->version_minor;
+           psp->drmPatch = version->version_patchlevel;
+           drmFreeVersion(version);
+       }
+       else {
+           fprintf(stderr, "libGL error: failed to get drm version: %s\n", 
+                   strerror(-psp->fd));
+           free(psp);
+           return NULL;
+       }
+    }
+    
+    /*
+    * Fake various version numbers.
+    */
+    psp->ddxMajor = 4;
+    psp->ddxMinor = 0;
+    psp->ddxPatch = 1;
+    psp->driMajor = 4;
+    psp->driMinor = 1;
+    psp->driPatch = 0;
+    
+    /* install driver's callback functions */
+    psp->DriverAPI = *driverAPI;
+    
+    /*
+    * Get device-specific info.  pDevPriv will point to a struct
+    * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h)
+    * that has information about the screen size, depth, pitch,
+    * ancilliary buffers, DRM mmap handles, etc.
+    */
+    psp->fbOrigin = driverContext->shared.fbOrigin;  
+    psp->fbSize = driverContext->shared.fbSize; 
+    psp->fbStride = driverContext->shared.fbStride;
+    psp->devPrivSize = driverContext->driverClientMsgSize;
+    psp->pDevPriv = driverContext->driverClientMsg;
+    psp->fbWidth = driverContext->shared.virtualWidth;
+    psp->fbHeight = driverContext->shared.virtualHeight;
+    psp->fbBPP = driverContext->bpp;
+    
+    if ((driverContext->FBAddress != NULL) && (driverContext->pSAREA != NULL)) {
+       /* Already mapped in server */
+       psp->pFB = driverContext->FBAddress;
+       psp->pSAREA = driverContext->pSAREA;
+    } else {
+       /*
+       * Map the framebuffer region.  
+       */
+       if (drmMap(psp->fd, driverContext->shared.hFrameBuffer, psp->fbSize, 
+                  (drmAddressPtr)&psp->pFB)) {
+           fprintf(stderr, "libGL error: drmMap of framebuffer failed\n");
+           (void)drmClose(psp->fd);
+           free(psp);
+           return NULL;
+       }
+       
+       /*
+       * Map the SAREA region.  Further mmap regions may be setup in
+       * each DRI driver's "createScreen" function.
+       */
+       if (drmMap(psp->fd, driverContext->shared.hSAREA,
+                  driverContext->shared.SAREASize, 
+                  (drmAddressPtr)&psp->pSAREA)) {
+           fprintf(stderr, "libGL error: drmMap of sarea failed\n");
+           (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
+           (void)drmClose(psp->fd);
+           free(psp);
+           return NULL;
+       }
+       
+#ifdef _EMBEDDED
+       mprotect(psp->pSAREA, driverContext->shared.SAREASize, PROT_READ);
+#endif
+    }
+    
+    
+    /* Initialize the screen specific GLX driver */
+    if (psp->DriverAPI.InitDriver) {
+       if (!(*psp->DriverAPI.InitDriver)(psp)) {
+           fprintf(stderr, "libGL error: InitDriver failed\n");
+           free(psp->pDevPriv);
+           (void)drmClose(psp->fd);
+           free(psp);
+           return NULL;
+       }
+    }
+    
+    psp->entry.destroyScreen  = driDestroyScreen;
+    psp->entry.createContext  = driCreateContext;
+    psp->entry.createDrawable = driCreateDrawable;
+    
+    return psp;
+}
+
+
+
+/**
+ * \brief Create the per-screen private information.
+ *
+ * Version for drivers without a DRM module.
+ * 
+ * \param dpy the display handle.
+ * \param scrn the screen number.
+ * \param numConfigs number of visuals.
+ * \param config visuals.
+ * \param driverAPI driver callbacks structure.
+ * 
+ * \internal
+ * Same as __driUtilCreateScreen() but without opening the DRM device.
+ */
+__DRIscreenPrivate *     
+__driUtilCreateScreenNoDRM(struct DRIDriverRec *driver,
+                          struct DRIDriverContextRec *driverContext,
+                          const struct __DriverAPIRec *driverAPI)
+{
+    __DRIscreenPrivate *psp;
+    
+    psp = (__DRIscreenPrivate *)calloc(1, sizeof(__DRIscreenPrivate));
+    if (!psp) 
+       return NULL;
+    
+    psp->ddxMajor = 4;
+    psp->ddxMinor = 0;
+    psp->ddxPatch = 1;
+    psp->driMajor = 4;
+    psp->driMinor = 1;
+    psp->driPatch = 0;
+    psp->fd = 0;
+    
+    psp->fbOrigin = driverContext->shared.fbOrigin; 
+    psp->fbSize = driverContext->shared.fbSize; 
+    psp->fbStride = driverContext->shared.fbStride;
+    psp->devPrivSize = driverContext->driverClientMsgSize;
+    psp->pDevPriv = driverContext->driverClientMsg;
+    psp->fbWidth = driverContext->shared.virtualWidth;
+    psp->fbHeight = driverContext->shared.virtualHeight;
+    psp->fbBPP = driverContext->bpp;
+    
+    psp->pFB = driverContext->FBAddress;
+    
+    /* install driver's callback functions */
+    psp->DriverAPI = *driverAPI;
+    
+    if ((driverContext->FBAddress != NULL) && (driverContext->pSAREA != NULL)) {
+       /* Already mapped in server */
+       psp->pFB = driverContext->FBAddress;
+       psp->pSAREA = driverContext->pSAREA;
+    } else {
+       psp->fd = open("/dev/mem", O_RDWR, 0);
+       /*
+       * Map the framebuffer region.  
+       */
+       if (drmMap(psp->fd, driverContext->shared.hFrameBuffer, psp->fbSize, 
+                  (drmAddressPtr)&psp->pFB)) {
+           fprintf(stderr, "libGL error: drmMap of framebuffer failed\n");
+           (void)drmClose(psp->fd);
+           free(psp);
+           return NULL;
+       }
+       driverContext->FBAddress = psp->pFB;
+       
+       /*
+       * Map the SAREA region.  Non-DRM drivers use a shmem SAREA
+       */
+       int id;
+       id = shmget(driverContext->shared.hSAREA, driverContext->shared.SAREASize, 0);
+       driverContext->pSAREA = shmat(id, NULL, 0);
+       if (!driverContext->pSAREA) {
+           fprintf(stderr, "libGL error: shmget of sarea failed\n");
+           (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
+           (void)drmClose(psp->fd);
+           free(psp);
+           return NULL;
+       }
+       
+       close(psp->fd);
+       psp->fd = 0;
+    }
+    
+    /* Initialize the screen specific GLX driver */
+    if (psp->DriverAPI.InitDriver) {
+       if (!(*psp->DriverAPI.InitDriver)(psp)) {
+           fprintf(stderr, "libGL error: InitDriver failed\n");
+           free(psp->pDevPriv);
+           free(psp);
+           return NULL;
+       }
+    }
+    
+    psp->entry.destroyScreen  = driDestroyScreen;
+    psp->entry.createContext  = driCreateContext;
+    psp->entry.createDrawable = driCreateDrawable;
+    
+    return psp;
+}
+
+/**
+ * Calculate amount of swap interval used between GLX buffer swaps.
+ * 
+ * The usage value, on the range [0,max], is the fraction of total swap
+ * interval time used between GLX buffer swaps is calculated.
+ *
+ *            \f$p = t_d / (i * t_r)\f$
+ * 
+ * Where \f$t_d\$f is the time since the last GLX buffer swap, \f$i\f$ is the
+ * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
+ * required for a single vertical refresh period (as returned by \c
+ * glXGetMscRateOML).
+ * 
+ * See the documentation for the GLX_MESA_swap_frame_usage extension for more
+ * details.
+ *
+ * \param   dPriv  Pointer to the private drawable structure.
+ * \return  If less than a single swap interval time period was required
+ *          between GLX buffer swaps, a number greater than 0 and less than
+ *          1.0 is returned.  If exactly one swap interval time period is
+ *          required, 1.0 is returned, and if more than one is required then
+ *          a number greater than 1.0 will be returned.
+ *
+ * \sa glXSwapIntervalSGI(), glXGetMscRateOML().
+ */
+float
+driCalculateSwapUsage( __DRIdrawablePrivate *dPriv, int64_t last_swap_ust,
+                      int64_t current_ust )
+{
+   return 0.0f;
+}
+
+/**
+ * Compare the current GLX API version with a driver supplied required version.
+ * 
+ * The minimum required version is compared with the API version exported by
+ * the \c __glXGetInternalVersion function (in libGL.so).
+ * 
+ * \param   required_version Minimum required internal GLX API version.
+ * \return  A tri-value return, as from strcmp is returned.  A value less
+ *          than, equal to, or greater than zero will be returned if the
+ *          internal GLX API version is less than, equal to, or greater
+ *          than \c required_version.
+ *
+ * \sa __glXGetInternalVersion().
+ */
+int driCompareGLXAPIVersion( GLuint required_version )
+{
+   return 0;
+}
+
+/*@}*/
diff --git a/src/glx/mini/dri_util.h b/src/glx/mini/dri_util.h
new file mode 100644 (file)
index 0000000..b653b3c
--- /dev/null
@@ -0,0 +1,523 @@
+/**
+ * \file dri_util.h
+ * \brief DRI utility functions definitions.
+ *
+ * This module acts as glue between GLX and the actual hardware driver.  A DRI
+ * driver doesn't really \e have to use any of this - it's optional.  But, some
+ * useful stuff is done here that otherwise would have to be duplicated in most
+ * drivers.
+ * 
+ * Basically, these utility functions take care of some of the dirty details of
+ * screen initialization, context creation, context binding, DRM setup, etc.
+ *
+ * These functions are compiled into each DRI driver so libGL.so knows nothing
+ * about them.
+ *
+ * Look for more comments in the dri_util.c file.
+ * 
+ * \author Kevin E. Martin <kevin@precisioninsight.com>
+ * \author Brian Paul <brian@precisioninsight.com>
+ */
+
+/*
+ * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef _DRI_UTIL_H_
+#define _DRI_UTIL_H_
+
+#include <inttypes.h>
+#include "dri.h"               /* public entry points */
+#include "sarea.h"             /* for XF86DRISAREAPtr */
+
+#define _SOLO
+
+typedef unsigned long CARD32;
+typedef int (* PFNGLXGETUSTPROC) ( uint64_t * ust );
+
+typedef struct __DRIdisplayPrivateRec  __DRIdisplayPrivate;  /**< \brief Alias for __DRIdisplayPrivateRec */
+typedef struct __DRIscreenPrivateRec   __DRIscreenPrivate;   /**< \brief Alias for __DRIscreenPrivateRec */
+typedef struct __DRIcontextPrivateRec  __DRIcontextPrivate;  /**< \brief Alias for __DRIcontextPrivateRec */
+typedef struct __DRIdrawablePrivateRec __DRIdrawablePrivate; /**< \brief Alias for __DRIdrawablePrivateRec */
+typedef struct __DRIswapInfoRec        __DRIswapInfo;       /**< \brief Alias for __DRIswapInfoPrivateRec */
+
+
+/**
+ * Used by DRI_VALIDATE_DRAWABLE_INFO
+ */
+#define DRI_VALIDATE_DRAWABLE_INFO_ONCE(pDrawPriv)              \
+    do {                                                        \
+       if (*(pDrawPriv->pStamp) != pDrawPriv->lastStamp) {     \
+           __driUtilUpdateDrawableInfo(pDrawPriv);             \
+       }                                                       \
+    } while (0)
+
+
+/**
+ * \brief Utility macro to validate the drawable information.
+ *
+ * See __DRIdrawablePrivateRec::pStamp and __DRIdrawablePrivateRec::lastStamp.
+ */
+#define DRI_VALIDATE_DRAWABLE_INFO(psp, pdp)                            \
+do {                                                                    \
+    DRI_VALIDATE_DRAWABLE_INFO_ONCE(pdp);                           \
+} while (0)
+
+
+/**
+ * Driver callback functions.
+ *
+ * Each DRI driver must have one of these structures with all the pointers set
+ * to appropriate functions within the driver.
+ * 
+ * When glXCreateContext() is called, for example, it'll call a helper function
+ * dri_util.c which in turn will jump through the \a CreateContext pointer in
+ * this structure.
+ */
+struct __DriverAPIRec {
+    /** 
+     * Driver initialization callback
+     */
+    GLboolean (*InitDriver)(__DRIscreenPrivate *driScrnPriv);
+    
+    /**
+     * Screen destruction callback
+     */
+    void (*DestroyScreen)(__DRIscreenPrivate *driScrnPriv);
+
+    /**
+     * Context creation callback
+     */                    
+    GLboolean (*CreateContext)(const __GLcontextModes *glVis,
+                               __DRIcontextPrivate *driContextPriv,
+                               void *sharedContextPrivate);
+
+    /**
+     * Context destruction callback
+     */
+    void (*DestroyContext)(__DRIcontextPrivate *driContextPriv);
+
+    /**
+     * Buffer (drawable) creation callback
+     */
+    GLboolean (*CreateBuffer)(__DRIscreenPrivate *driScrnPriv,
+                              __DRIdrawablePrivate *driDrawPriv,
+                              const __GLcontextModes *glVis,
+                              GLboolean pixmapBuffer);
+    
+    /**
+     * Buffer (drawable) destruction callback
+     */
+    void (*DestroyBuffer)(__DRIdrawablePrivate *driDrawPriv);
+
+    /**
+     * Buffer swapping callback 
+     */
+    void (*SwapBuffers)(__DRIdrawablePrivate *driDrawPriv);
+
+    /**
+     * Context activation callback
+     */
+    GLboolean (*MakeCurrent)(__DRIcontextPrivate *driContextPriv,
+                             __DRIdrawablePrivate *driDrawPriv,
+                             __DRIdrawablePrivate *driReadPriv);
+
+    /**
+     * Context unbinding callback
+     */
+    GLboolean (*UnbindContext)(__DRIcontextPrivate *driContextPriv);
+  
+    /**
+     * Full screen mode opening callback.
+     * 
+     * \deprecated Full screen functionality is no longer used by DRI.
+     *             Drivers should simply install a function returning 
+     *             \c GL_TRUE for backwards compatability.
+     */
+    GLboolean (*OpenFullScreen)(__DRIcontextPrivate *driContextPriv);
+
+    /**
+     * Full screen mode closing callback.
+     * 
+     * \deprecated Full screen functionality is no longer used by DRI.
+     *             Drivers should simply install a function returning 
+     *             \c GL_TRUE for backwards compatability.
+     */
+    GLboolean (*CloseFullScreen)(__DRIcontextPrivate *driContextPriv);
+
+    /* Retrieves statistics about buffer swap operations.  Required if
+     * GLX_OML_sync_control or GLX_MESA_swap_frame_usage is supported.
+     */
+    int (*GetSwapInfo)( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo );
+
+
+    /* Required if GLX_SGI_video_sync or GLX_OML_sync_control is
+     * supported.
+     */
+    int (*GetMSC)( __DRIscreenPrivate * priv, int64_t * count );
+
+    /**
+     * These are required if GLX_OML_sync_control is supported.
+     */
+    /*@{*/
+    int (*WaitForMSC)( __DRIdrawablePrivate *priv, int64_t target_msc, 
+                      int64_t divisor, int64_t remainder,
+                      int64_t * msc );
+    int (*WaitForSBC)( __DRIdrawablePrivate *priv, int64_t target_sbc,
+                      int64_t * msc, int64_t * sbc );
+
+    int64_t (*SwapBuffersMSC)( __DRIdrawablePrivate *priv, int64_t target_msc,
+                              int64_t divisor, int64_t remainder );
+    /*@}*/
+};
+
+
+struct __DRIswapInfoRec {
+    /** 
+     * Number of swapBuffers operations that have been *completed*. 
+     */
+    uint64_t  swap_count;
+
+    /*
+     * Unadjusted system time of the last buffer swap.  This is the time
+     * when the swap completed, not the time when swapBuffers was called.
+     */
+    int64_t   swap_ust;
+
+    /*
+     * Number of swap operations that occurred after the swap deadline.  That
+     * is if a swap happens more than swap_interval frames after the previous
+     * swap, it has missed its deadline.  If swap_interval is 0, then the
+     * swap deadline is 1 frame after the previous swap.
+     */
+    uint64_t  swap_missed_count;
+
+    /*
+     * Amount of time used by the last swap that missed its deadline.  This
+     * is calculated as (__glXGetUST() - swap_ust) / (swap_interval * 
+     * time_for_single_vrefresh)).  If the actual value of swap_interval is
+     * 0, then 1 is used instead.  If swap_missed_count is non-zero, this
+     * should be greater-than 1.0.
+     */
+    float     swap_missed_usage;
+};
+
+
+/**
+ * \brief Per-drawable private DRI driver information.
+ *
+ */
+struct __DRIdrawablePrivateRec {
+    
+    /**
+     * \brief Public entry points
+     */
+    __DRIdrawable entry;
+    
+    /**
+     * \brief Kernel drawable handle
+     *
+     * \note Not currently used.
+     */
+    drmDrawable hHWDrawable;
+
+    /**
+     * \brief Driver's private drawable information.  
+     *
+     * This structure is opaque.
+     */
+    void *driverPrivate;
+
+    /**
+     * \brief Reference count for number of context's currently bound to this
+     * drawable.  
+     *
+     * Once it reaches zero, the drawable can be destroyed.
+     *
+     * \note This behavior will change with GLX 1.3.
+     */
+    int refcount;
+
+    /**
+     * \brief Index of this drawable information in the SAREA.
+     */
+    unsigned int index;
+
+    /**
+     * \brief Pointer to the "drawable has changed ID" stamp in the SAREA.
+     */
+    unsigned int *pStamp;
+
+    /**
+     * \brief Last value of the stamp.
+     *
+     * If this differs from the value stored at
+     * __DRIdrawablePrivateRec::pStamp, then the drawable information has been
+     * modified by the X server, and the drawable information (below) should be
+     * retrieved from the X server.
+     */
+    unsigned int lastStamp;
+
+    /**
+     * \name Drawable 
+     * Drawable information used in software fallbacks.
+     */
+    /*@{*/
+    int x;
+    int y;
+    int w;
+    int h;
+    int numClipRects;
+    XF86DRIClipRectPtr pClipRects;
+    /*@}*/
+
+    /**
+     * \name Back and depthbuffer
+     * Information about the back and depthbuffer where different from above.
+     */
+    /*@{*/
+    int backX;
+    int backY;
+    int backClipRectType;
+    int numBackClipRects;
+    XF86DRIClipRectPtr pBackClipRects;
+    /*@}*/
+
+    /**
+     * \brief Pointer to context to which this drawable is currently bound.
+     */
+    __DRIcontextPrivate *driContextPriv;
+
+    /**
+     * \brief Pointer to screen on which this drawable was created.
+     */
+    __DRIscreenPrivate *driScreenPriv;
+
+    int cpp;
+    void *frontBuffer;
+    void *backBuffer;
+    void *currentBuffer;
+    int currentPitch;
+                                                                                                       
+    int depthCpp;
+    void *depthBuffer;
+    int depthPitch;
+                                                                                                       
+    /**
+     * \brief Called via glXSwapBuffers().
+     */
+    void (*swapBuffers)( __DRIdrawablePrivate *dPriv );
+};
+
+/**
+ * \brief Per-context private driver information.
+ */
+struct __DRIcontextPrivateRec {
+    /**
+     * \brief Public entry points
+     */
+    __DRIcontext entry;
+
+    /**
+     * \brief Kernel context handle used to access the device lock.
+     */
+    drmContext hHWContext;
+
+    /**
+     * \brief Device driver's private context data.  This structure is opaque.
+     */
+    void *driverPrivate;
+
+    /**
+     * \brief Pointer to drawable currently bound to this context.
+     */
+    __DRIdrawablePrivate *driDrawablePriv;
+
+    /**
+     * \brief Pointer to screen on which this context was created.
+     */
+    __DRIscreenPrivate *driScreenPriv;
+};
+
+/**
+ * \brief Per-screen private driver information.
+ */
+struct __DRIscreenPrivateRec {
+    
+    /**
+     * \brief Public entry points
+     */
+    __DRIscreen entry;
+    
+    /**
+     * \brief Callback functions into the hardware-specific DRI driver code.
+     */
+    struct __DriverAPIRec DriverAPI;
+
+    /**
+     * \name DDX version
+     * DDX / 2D driver version information.
+     */
+    /*@{*/
+    int ddxMajor;
+    int ddxMinor;
+    int ddxPatch;
+    /*@}*/
+
+    /**
+     * \name DRI version
+     * DRI X extension version information.
+     */
+    /*@{*/
+    int driMajor;
+    int driMinor;
+    int driPatch;
+    /*@}*/
+
+    /**
+     * \name DRM version
+     * DRM (kernel module) version information.
+     */
+    /*@{*/
+    int drmMajor;
+    int drmMinor;
+    int drmPatch;
+    /*@}*/
+
+    /**
+     * \brief ID used when the client sets the drawable lock.
+     *
+     * The X server uses this value to detect if the client has died while
+     * holding the drawable lock.
+     */
+    int drawLockID;
+
+    /**
+     * \brief File descriptor returned when the kernel device driver is opened.
+     * 
+     * Used to:
+     *   - authenticate client to kernel
+     *   - map the frame buffer, SAREA, etc.
+     *   - close the kernel device driver
+     */
+    int fd;
+
+    /**
+     * \brief SAREA pointer 
+     *
+     * Used to access:
+     *   - the device lock
+     *   - the device-independent per-drawable and per-context(?) information
+     */
+    XF86DRISAREAPtr pSAREA;
+
+    /**
+     * \name Direct frame buffer access information 
+     * Used for software fallbacks.
+     */
+    /*@{*/
+    unsigned char *pFB;
+    int fbSize;
+    int fbOrigin;
+    int fbStride;
+    int fbWidth;
+    int fbHeight;
+    int fbBPP;
+    /*@}*/
+
+    /**
+     * \name Device-dependent private information (stored in the SAREA).
+     *
+     * This data is accessed by the client driver only.
+     */
+    /*@{*/
+    void *pDevPriv;
+    int devPrivSize;
+    /*@}*/
+
+    /**
+     * \brief Dummy context to which drawables are bound when not bound to any
+     * other context. 
+     *
+     * A dummy hHWContext is created for this context, and is used by the GL
+     * core when a hardware lock is required but the drawable is not currently
+     * bound (e.g., potentially during a SwapBuffers request).  The dummy
+     * context is created when the first "real" context is created on this
+     * screen.
+     */
+    __DRIcontextPrivate dummyContextPriv;
+
+    /**
+     * \brief Hash table to hold the drawable information for this screen.
+     */
+    void *drawHash;
+
+    /**
+     * \brief Device-dependent private information (not stored in the SAREA).
+     * 
+     * This pointer is never touched by the DRI layer.
+     */
+    void *private;
+
+    /**
+     * \brief Full screen mode.
+     *
+     * If we're in full screen mode (via DRIOpenFullScreen()), this points to
+     * the drawable that was bound.  Otherwise, this is NULL.
+     */
+    __DRIdrawablePrivate *fullscreen;
+};
+
+extern void
+__driUtilMessage(const char *f, ...);
+
+
+extern void
+__driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp);
+
+
+extern __DRIscreenPrivate *
+__driUtilCreateScreen(struct DRIDriverRec *driver,
+                      struct DRIDriverContextRec *driverContext,
+                      const struct __DriverAPIRec *driverAPI);
+
+__DRIscreenPrivate *
+__driUtilCreateScreenNoDRM(struct DRIDriverRec *driver,
+                           struct DRIDriverContextRec *driverContext,
+                           const struct __DriverAPIRec *driverAPI);
+
+extern float
+driCalculateSwapUsage( __DRIdrawablePrivate *dPriv,
+                      int64_t last_swap_ust, int64_t current_ust );
+
+/* Test the version of the internal GLX API.  Returns a value like strcmp. */
+extern int
+driCompareGLXAPIVersion( GLuint required_version );
+
+/** This is optionally implemented in each driver */
+extern void
+__driRegisterExtensions( void );
+
+#endif /* _DRI_UTIL_H_ */
diff --git a/src/glx/mini/driver.h b/src/glx/mini/driver.h
new file mode 100644 (file)
index 0000000..a3ec960
--- /dev/null
@@ -0,0 +1,177 @@
+/**
+ * \file driver.h
+ * \brief DRI utility functions definitions.
+ *
+ * This module acts as glue between GLX and the actual hardware driver.  A DRI
+ * driver doesn't really \e have to use any of this - it's optional.  But, some
+ * useful stuff is done here that otherwise would have to be duplicated in most
+ * drivers.
+ * 
+ * Basically, these utility functions take care of some of the dirty details of
+ * screen initialization, context creation, context binding, DRM setup, etc.
+ *
+ * These functions are compiled into each DRI driver so libGL.so knows nothing
+ * about them.
+ *
+ * Look for more comments in the dri_util.c file.
+ * 
+ * \author Kevin E. Martin <kevin@precisioninsight.com>
+ * \author Brian Paul <brian@precisioninsight.com>
+ */
+
+/*
+ * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _driver_H_
+#define _driver_H_
+
+#define CAPI  /* XXX this should be globally defined somewhere */
+
+#include "GL/gl.h"
+#include "GL/internal/glcore.h"
+
+/**
+ * \brief Clip rectangle definition.
+ */
+typedef struct _XF86DRIClipRect {
+    unsigned short     x1; /**< \brief Upper: inclusive */
+    unsigned short     y1; /**< \brief Left: inclusive */
+    unsigned short     x2; /**< \brief Lower: exclusive */
+    unsigned short     y2; /**< \brief Right: exclusive */
+} XF86DRIClipRectRec, *XF86DRIClipRectPtr;
+
+/**
+ * \brief DRIDriverContext type.
+ */
+typedef struct DRIDriverContextRec {
+   const char *pciBusID;
+   int pciBus;
+   int pciDevice;
+   int pciFunc;
+   int chipset;
+   int bpp; 
+   int cpp;  
+   
+   unsigned long FBStart;   /**< \brief physical address of the framebuffer */
+   unsigned long MMIOStart; /**< \brief physical address of the MMIO region */
+   
+   int FBSize;              /**< \brief size of the mmap'd framebuffer in bytes */
+   int MMIOSize;            /**< \brief size of the mmap'd MMIO region in bytes */
+
+   void *FBAddress;         /**< \brief start of the mmap'd framebuffer */
+   void *MMIOAddress;       /**< \brief start of the mmap'd MMIO region */
+   
+   /**
+    * \brief Client configuration details
+    *
+    * These are computed on the server and sent to clients as part of
+    * the initial handshaking.
+    */
+   struct {
+      unsigned long hSAREA;
+      int SAREASize;
+      unsigned long hFrameBuffer;
+      int fbOrigin;
+      int fbSize;
+      int fbStride;
+      int virtualWidth;
+      int virtualHeight;
+   } shared;
+   
+   /**
+    * \name From DRIInfoRec
+    */
+   /*@{*/
+   int drmFD;  /**< \brief DRM device file descriptor */
+   struct _XF86DRISAREA *pSAREA;
+   unsigned int serverContext; /**< \brief DRM context only active on server */
+   /*@}*/
+   
+   
+   /**
+    * \name Driver private
+    *
+    * Populated by __driInitFBDev()
+    */
+   /*@{*/
+   void *driverPrivate;
+   void *driverClientMsg;
+   int driverClientMsgSize;
+   /*@}*/
+} DRIDriverContext;
+
+/**
+ * \brief Interface to the DRI driver.
+ *
+ * This structure is retrieved from the loadable driver by the \e
+ * __driDriver symbol to access the Mini GLX specific hardware
+ * initialization and take down routines.
+ */
+typedef struct DRIDriverRec { 
+   /**
+    * \brief Get the list of supported gl context modes.
+    */
+   int (*initContextModes)( const DRIDriverContext *context,
+                            int *numModes, const __GLcontextModes **modes );
+   /**
+    * \brief Validate the framebuffer device mode
+    */
+   int (*validateMode)( const DRIDriverContext *context );
+
+   /**
+    * \brief Examine mode returned by fbdev (may differ from the one
+    * requested), restore any hw regs clobbered by fbdev.
+    */
+   int (*postValidateMode)( const DRIDriverContext *context );
+
+   /**
+    * \brief Initialize the framebuffer device.
+    */
+   int (*initFBDev)( DRIDriverContext *context );
+
+   /**
+    * \brief Halt the framebuffer device.
+    */
+   void (*haltFBDev)( DRIDriverContext *context );
+
+
+   /**
+    * \brief Idle and shutdown hardware in preparation for a VT switch.
+    */
+   int (*shutdownHardware)(  const DRIDriverContext *context );
+
+   /**
+    * \brief Restore hardware state after regaining the VT.
+    */
+   int (*restoreHardware)(  const DRIDriverContext *context );
+
+   /**
+    * \brief Notify hardware driver of gain/loose focus.  May be zero
+    * as this is of limited utility for most drivers.  
+    */
+   void (*notifyFocus)( int have_focus );
+} DRIDriver;
+
+#endif /* _driver_H_ */
diff --git a/src/glx/mini/drm.h b/src/glx/mini/drm.h
new file mode 100644 (file)
index 0000000..4180d1e
--- /dev/null
@@ -0,0 +1,657 @@
+/**
+ * \file drm.h 
+ * \brief Header for the Direct Rendering Manager
+ * 
+ * This file defines the DRM device ioctls and the strucutre of respective user
+ * arguments.
+ *
+ * \sa xf86drm.h and xf86drm.c for an user-friendlier interface.
+ * 
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ * \par Acknowledgements:
+ * Dec 1999, Richard Henderson <rth@twiddle.net>, move to generic \c cmpxchg.
+ */
+
+/*
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef _DRM_H_
+#define _DRM_H_
+
+#if defined(__linux__)
+#include <linux/config.h>
+#include <asm/ioctl.h>         /* For _IO* macros */
+#define DRM_IOCTL_NR(n)                _IOC_NR(n)
+#define DRM_IOC_VOID           _IOC_NONE
+#define DRM_IOC_READ           _IOC_READ
+#define DRM_IOC_WRITE          _IOC_WRITE
+#define DRM_IOC_READWRITE      _IOC_READ|_IOC_WRITE
+#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
+#elif defined(__FreeBSD__) || defined(__NetBSD__)
+#if defined(__FreeBSD__) && defined(XFree86Server)
+/* Prevent name collision when including sys/ioccom.h */
+#undef ioctl
+#include <sys/ioccom.h>
+#define ioctl(a,b,c)           xf86ioctl(a,b,c)
+#else
+#include <sys/ioccom.h>
+#endif /* __FreeBSD__ && xf86ioctl */
+#define DRM_IOCTL_NR(n)                ((n) & 0xff)
+#define DRM_IOC_VOID           IOC_VOID
+#define DRM_IOC_READ           IOC_OUT
+#define DRM_IOC_WRITE          IOC_IN
+#define DRM_IOC_READWRITE      IOC_INOUT
+#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
+#endif
+
+#define XFREE86_VERSION(major,minor,patch,snap) \
+               ((major << 16) | (minor << 8) | patch)
+
+#ifndef CONFIG_XFREE86_VERSION
+#define CONFIG_XFREE86_VERSION XFREE86_VERSION(4,1,0,0)
+#endif
+
+#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
+#define DRM_PROC_DEVICES "/proc/devices"
+#define DRM_PROC_MISC   "/proc/misc"
+#define DRM_PROC_DRM    "/proc/drm"
+#define DRM_DEV_DRM     "/dev/drm"
+#define DRM_DEV_MODE    (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
+#define DRM_DEV_UID     0
+#define DRM_DEV_GID     0
+#endif
+
+#if CONFIG_XFREE86_VERSION >= XFREE86_VERSION(4,1,0,0)
+#define DRM_MAJOR       226
+#define DRM_MAX_MINOR   15
+#endif
+#define DRM_NAME       "drm"     /**< Name in kernel, /dev, and /proc */
+#define DRM_MIN_ORDER  5         /**< At least 2^5 bytes = 32 bytes */
+#define DRM_MAX_ORDER  22        /**< Up to 2^22 bytes = 4MB */
+#define DRM_RAM_PERCENT 10       /**< How much system ram can we lock? */
+
+#define _DRM_LOCK_HELD 0x80000000 /**< Hardware lock is held */
+#define _DRM_LOCK_CONT 0x40000000 /**< Hardware lock is contended */
+#define _DRM_LOCK_IS_HELD(lock)           ((lock) & _DRM_LOCK_HELD)
+#define _DRM_LOCK_IS_CONT(lock)           ((lock) & _DRM_LOCK_CONT)
+#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
+
+
+typedef unsigned long drm_handle_t;
+typedef unsigned int  drm_context_t;
+typedef unsigned int  drm_drawable_t;
+typedef unsigned int  drm_magic_t;
+
+
+/**
+ * Cliprect.
+ * 
+ * \warning: If you change this structure, make sure you change
+ * XF86DRIClipRectRec in the server as well
+ *
+ * \note KW: Actually it's illegal to change either for
+ * backwards-compatibility reasons.
+ */
+typedef struct drm_clip_rect {
+       unsigned short  x1;
+       unsigned short  y1;
+       unsigned short  x2;
+       unsigned short  y2;
+} drm_clip_rect_t;
+
+
+/**
+ * Texture region,
+ */
+typedef struct drm_tex_region {
+       unsigned char   next;
+       unsigned char   prev;
+       unsigned char   in_use;
+       unsigned char   padding;
+       unsigned int    age;
+} drm_tex_region_t;
+
+
+/**
+ * \brief DRM_IOCTL_VERSION ioctl argument type.
+ * 
+ * \sa drmGetVersion().
+ */
+typedef struct drm_version {
+       int    version_major;     /**< Major version */
+       int    version_minor;     /**< Minor version */
+       int    version_patchlevel;/**< Patch level */
+       size_t name_len;          /**< Length of name buffer */
+       char   *name;             /**< Name of driver */
+       size_t date_len;          /**< Length of date buffer */
+       char   *date;             /**< User-space buffer to hold date */
+       size_t desc_len;          /**< Length of desc buffer */
+       char   *desc;             /**< User-space buffer to hold desc */
+} drm_version_t;
+
+
+/**
+ * \brief DRM_IOCTL_GET_UNIQUE ioctl argument type.
+ *
+ * \sa drmGetBusid() and drmSetBusId().
+ */
+typedef struct drm_unique {
+       size_t unique_len;        /**< Length of unique */
+       char   *unique;           /**< Unique name for driver instantiation */
+} drm_unique_t;
+
+
+typedef struct drm_list {
+       int              count;   /**< Length of user-space structures */
+       drm_version_t    *version;
+} drm_list_t;
+
+
+typedef struct drm_block {
+       int              unused;
+} drm_block_t;
+
+
+/**
+ * \brief DRM_IOCTL_CONTROL ioctl argument type.
+ *
+ * \sa drmCtlInstHandler() and drmCtlUninstHandler().
+ */
+typedef struct drm_control {
+       enum {
+               DRM_ADD_COMMAND,
+               DRM_RM_COMMAND,
+               DRM_INST_HANDLER,
+               DRM_UNINST_HANDLER
+       }                func;
+       int              irq;
+} drm_control_t;
+
+
+/**
+ * \brief Type of memory to map.
+ */
+typedef enum drm_map_type {
+       _DRM_FRAME_BUFFER   = 0,  /**< WC (no caching), no core dump */
+       _DRM_REGISTERS      = 1,  /**< no caching, no core dump */
+       _DRM_SHM            = 2,  /**< shared, cached */
+       _DRM_AGP            = 3,  /**< AGP/GART */
+       _DRM_SCATTER_GATHER = 4   /**< Scatter/gather memory for PCI DMA */
+} drm_map_type_t;
+
+
+/**
+ * \brief Memory mapping flags.
+ */
+typedef enum drm_map_flags {
+       _DRM_RESTRICTED      = 0x01, /**< Cannot be mapped to user-virtual */
+       _DRM_READ_ONLY       = 0x02,
+       _DRM_LOCKED          = 0x04, /**< shared, cached, locked */
+       _DRM_KERNEL          = 0x08, /**< kernel requires access */
+       _DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */
+       _DRM_CONTAINS_LOCK   = 0x20, /**< SHM page that contains lock */
+       _DRM_REMOVABLE       = 0x40  /**< Removable mapping */
+} drm_map_flags_t;
+
+
+typedef struct drm_ctx_priv_map {
+       unsigned int    ctx_id;  /**< Context requesting private mapping */
+       void            *handle; /**< Handle of map */
+} drm_ctx_priv_map_t;
+
+
+/**
+ * \brief DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls
+ * argument type.
+ *
+ * \sa drmAddMap().
+ */
+typedef struct drm_map {
+       unsigned long   offset;  /**< Requested physical address (0 for SAREA)*/
+       unsigned long   size;    /**< Requested physical size (bytes) */
+       drm_map_type_t  type;    /**< Type of memory to map */
+       drm_map_flags_t flags;   /**< Flags */
+       void            *handle; /**< User-space: "Handle" to pass to mmap() */
+                                /**< Kernel-space: kernel-virtual address */
+       int             mtrr;    /**< MTRR slot used */
+                                /*   Private data */
+} drm_map_t;
+
+
+/**
+ * \brief DRM_IOCTL_GET_CLIENT ioctl argument type.
+ */
+typedef struct drm_client {
+       int             idx;    /**< Which client desired? */
+       int             auth;   /**< Is client authenticated? */
+       unsigned long   pid;    /**< Process ID */
+       unsigned long   uid;    /**< User ID */
+       unsigned long   magic;  /**< Magic */
+       unsigned long   iocs;   /**< Ioctl count */
+} drm_client_t;
+
+
+typedef enum {
+       _DRM_STAT_LOCK,
+       _DRM_STAT_OPENS,
+       _DRM_STAT_CLOSES,
+       _DRM_STAT_IOCTLS,
+       _DRM_STAT_LOCKS,
+       _DRM_STAT_UNLOCKS,
+       _DRM_STAT_VALUE,        /**< Generic value */
+       _DRM_STAT_BYTE,         /**< Generic byte counter (1024bytes/K) */
+       _DRM_STAT_COUNT,        /**< Generic non-byte counter (1000/k) */
+
+       _DRM_STAT_IRQ,          /**< IRQ */
+       _DRM_STAT_PRIMARY,      /**< Primary DMA bytes */
+       _DRM_STAT_SECONDARY,    /**< Secondary DMA bytes */
+       _DRM_STAT_DMA,          /**< DMA */
+       _DRM_STAT_SPECIAL,      /**< Special DMA (e.g., priority or polled) */
+       _DRM_STAT_MISSED        /**< Missed DMA opportunity */
+
+                               /* Add to the *END* of the list */
+} drm_stat_type_t;
+
+
+/**
+ * \brief DRM_IOCTL_GET_STATS ioctl argument type.
+ */
+typedef struct drm_stats {
+       unsigned long count;
+       struct {
+               unsigned long   value;
+               drm_stat_type_t type;
+       } data[15];
+} drm_stats_t;
+
+
+/**
+ * \brief Hardware locking flags.
+ */
+typedef enum drm_lock_flags {
+       _DRM_LOCK_READY      = 0x01, /**< Wait until hardware is ready for DMA */
+       _DRM_LOCK_QUIESCENT  = 0x02, /**< Wait until hardware quiescent */
+       _DRM_LOCK_FLUSH      = 0x04, /**< Flush this context's DMA queue first */
+       _DRM_LOCK_FLUSH_ALL  = 0x08, /**< Flush all DMA queues first */
+                               /* These *HALT* flags aren't supported yet
+                                  -- they will be used to support the
+                                  full-screen DGA-like mode. */
+       _DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */
+       _DRM_HALT_CUR_QUEUES = 0x20  /**< Halt all current queues */
+} drm_lock_flags_t;
+
+
+/**
+ * \brief DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type.
+ * 
+ * \sa drmGetLock() and drmUnlock().
+ */
+typedef struct drm_lock {
+       int              context;
+       drm_lock_flags_t flags;
+} drm_lock_t;
+
+
+/**
+ * \brief DMA flags
+ *
+ * \warning 
+ * These values \e must match xf86drm.h.
+ *
+ * \sa drm_dma.
+ */
+typedef enum drm_dma_flags {         
+                                     /* Flags for DMA buffer dispatch */
+       _DRM_DMA_BLOCK        = 0x01, /**<
+                                      * Block until buffer dispatched.
+                                      * 
+                                      * \note The buffer may not yet have
+                                      * been processed by the hardware --
+                                      * getting a hardware lock with the
+                                      * hardware quiescent will ensure
+                                      * that the buffer has been
+                                      * processed.
+                                      */
+       _DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */
+       _DRM_DMA_PRIORITY     = 0x04, /**< High priority dispatch */
+
+                                     /* Flags for DMA buffer request */
+       _DRM_DMA_WAIT         = 0x10, /**< Wait for free buffers */
+       _DRM_DMA_SMALLER_OK   = 0x20, /**< Smaller-than-requested buffers OK */
+       _DRM_DMA_LARGER_OK    = 0x40  /**< Larger-than-requested buffers OK */
+} drm_dma_flags_t;
+
+
+/**
+ * \brief DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type.
+ *
+ * \sa drmAddBufs().
+ */
+typedef struct drm_buf_desc {
+       int           count;     /**< Number of buffers of this size */
+       int           size;      /**< Size in bytes */
+       int           low_mark;  /**< Low water mark */
+       int           high_mark; /**< High water mark */
+       enum {
+               _DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */
+               _DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */
+               _DRM_SG_BUFFER  = 0x04  /**< Scatter/gather memory buffer */
+       }             flags;
+       unsigned long agp_start; /**< 
+                                 * Start address of where the AGP buffers are
+                                 * in the AGP aperture
+                                 */
+} drm_buf_desc_t;
+
+
+/**
+ * \brief DRM_IOCTL_INFO_BUFS ioctl argument type.
+ */
+typedef struct drm_buf_info {
+       int            count;   /**< Entries in list */
+       drm_buf_desc_t *list;
+} drm_buf_info_t;
+
+
+/**
+ * \brief DRM_IOCTL_FREE_BUFS ioctl argument type.
+ */
+typedef struct drm_buf_free {
+       int            count;
+       int            *list;
+} drm_buf_free_t;
+
+
+/**
+ * \brief Buffer information
+ *
+ * \sa drm_buf_map.
+ */
+typedef struct drm_buf_pub {
+       int               idx;         /**< Index into the master buffer list */
+       int               total;       /**< Buffer size */
+       int               used;        /**< Amount of buffer in use (for DMA) */
+       void              *address;    /**< Address of buffer */
+} drm_buf_pub_t;
+
+
+/**
+ * \brief DRM_IOCTL_MAP_BUFS ioctl argument type.
+ */
+typedef struct drm_buf_map {
+       int           count;    /**< Length of the buffer list */
+       void          *virtual; /**< Mmap'd area in user-virtual */
+       drm_buf_pub_t *list;    /**< Buffer information */
+} drm_buf_map_t;
+
+
+/**
+ * \brief DRM_IOCTL_DMA ioctl argument type.
+ *
+ * Indices here refer to the offset into the buffer list in drm_buf_get.
+ *
+ * \sa drmDMA().
+ */
+typedef struct drm_dma {
+       int             context;          /**< Context handle */
+       int             send_count;       /**< Number of buffers to send */
+       int             *send_indices;    /**< List of handles to buffers */
+       int             *send_sizes;      /**< Lengths of data to send */
+       drm_dma_flags_t flags;            /**< Flags */
+       int             request_count;    /**< Number of buffers requested */
+       int             request_size;     /**< Desired size for buffers */
+       int             *request_indices; /**< Buffer information */
+       int             *request_sizes;
+       int             granted_count;    /**< Number of buffers granted */
+} drm_dma_t;
+
+
+typedef enum {
+       _DRM_CONTEXT_PRESERVED = 0x01,
+       _DRM_CONTEXT_2DONLY    = 0x02
+} drm_ctx_flags_t;
+
+
+/**
+ * \brief DRM_IOCTL_ADD_CTX ioctl argument type.
+ *
+ * \sa drmCreateContext() and drmDestroyContext().
+ */
+typedef struct drm_ctx {
+       drm_context_t   handle;
+       drm_ctx_flags_t flags;
+} drm_ctx_t;
+
+
+/**
+ * \brief DRM_IOCTL_RES_CTX ioctl argument type.
+ */
+typedef struct drm_ctx_res {
+       int             count;
+       drm_ctx_t       *contexts;
+} drm_ctx_res_t;
+
+
+/**
+ * \brief DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type.
+ */
+typedef struct drm_draw {
+       drm_drawable_t  handle;
+} drm_draw_t;
+
+
+/**
+ * \brief DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type.
+ */
+typedef struct drm_auth {
+       drm_magic_t     magic;
+} drm_auth_t;
+
+
+/**
+ * \brief DRM_IOCTL_IRQ_BUSID ioctl argument type.
+ *
+ * \sa drmGetInterruptFromBusID().
+ */
+typedef struct drm_irq_busid {
+       int irq;        /**< IRQ number */
+       int busnum;     /**< bus number */
+       int devnum;     /**< device number */
+       int funcnum;    /**< function number */
+} drm_irq_busid_t;
+
+
+typedef enum {
+    _DRM_VBLANK_ABSOLUTE = 0x0,                /**< Wait for specific vblank sequence number */
+    _DRM_VBLANK_RELATIVE = 0x1,                /**< Wait for given number of vblanks */
+    _DRM_VBLANK_SIGNAL   = 0x8000      /**< Send signal instead of blocking */
+} drm_vblank_seq_type_t;
+
+
+#define _DRM_VBLANK_FLAGS_MASK _DRM_VBLANK_SIGNAL
+
+
+struct drm_wait_vblank_request {
+       drm_vblank_seq_type_t type;
+       unsigned int sequence;
+       unsigned long signal;
+};
+
+
+struct drm_wait_vblank_reply {
+       drm_vblank_seq_type_t type;
+       unsigned int sequence;
+       long tval_sec;
+       long tval_usec;
+};
+
+
+/**
+ * \brief DRM_IOCTL_WAIT_VBLANK ioctl argument type.
+ *
+ * \sa drmWaitVBlank().
+ */
+typedef union drm_wait_vblank {
+       struct drm_wait_vblank_request request;
+       struct drm_wait_vblank_reply reply;
+} drm_wait_vblank_t;
+
+
+/**
+ * \brief DRM_IOCTL_AGP_ENABLE ioctl argument type.
+ *
+ * \sa drmAgpEnable().
+ */
+typedef struct drm_agp_mode {
+       unsigned long mode;     /**< AGP mode */
+} drm_agp_mode_t;
+
+
+/**
+ * \brief DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type.
+ *
+ * \sa drmAgpAlloc() and drmAgpFree().
+ */
+typedef struct drm_agp_buffer {
+       unsigned long size;     /**< In bytes -- will round to page boundary */
+       unsigned long handle;   /**< Used for binding / unbinding */
+       unsigned long type;     /**< Type of memory to allocate */
+        unsigned long physical; /**< Physical used by i810 */
+} drm_agp_buffer_t;
+
+
+/**
+ * \brief DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type.
+ *
+ * \sa drmAgpBind() and drmAgpUnbind().
+ */
+typedef struct drm_agp_binding {
+       unsigned long handle;   /**< From drm_agp_buffer */
+       unsigned long offset;   /**< In bytes -- will round to page boundary */
+} drm_agp_binding_t;
+
+
+/**
+ * \brief DRM_IOCTL_AGP_INFO ioctl argument type.
+ *
+ * \sa drmAgpVersionMajor(), drmAgpVersionMinor(), drmAgpGetMode(),
+ * drmAgpBase(), drmAgpSize(), drmAgpMemoryUsed(), drmAgpMemoryAvail(),
+ * drmAgpVendorId() and drmAgpDeviceId().
+ */
+typedef struct drm_agp_info {
+       int            agp_version_major;
+       int            agp_version_minor;
+       unsigned long  mode;
+       unsigned long  aperture_base;  /* physical address */
+       unsigned long  aperture_size;  /* bytes */
+       unsigned long  memory_allowed; /* bytes */
+       unsigned long  memory_used;
+
+                               /* PCI information */
+       unsigned short id_vendor;
+       unsigned short id_device;
+} drm_agp_info_t;
+
+
+/**
+ * \brief DRM_IOCTL_SG_ALLOC ioctl argument type.
+ */
+typedef struct drm_scatter_gather {
+       unsigned long size;     /**< In bytes -- will round to page boundary */
+       unsigned long handle;   /**< Used for mapping / unmapping */
+} drm_scatter_gather_t;
+
+
+#define DRM_IOCTL_BASE                 'd'
+#define DRM_IO(nr)                     _IO(DRM_IOCTL_BASE,nr)
+#define DRM_IOR(nr,type)               _IOR(DRM_IOCTL_BASE,nr,type)
+#define DRM_IOW(nr,type)               _IOW(DRM_IOCTL_BASE,nr,type)
+#define DRM_IOWR(nr,type)              _IOWR(DRM_IOCTL_BASE,nr,type)
+
+#define DRM_IOCTL_VERSION              DRM_IOWR(0x00, drm_version_t)
+#define DRM_IOCTL_GET_UNIQUE           DRM_IOWR(0x01, drm_unique_t)
+#define DRM_IOCTL_GET_MAGIC            DRM_IOR( 0x02, drm_auth_t)
+#define DRM_IOCTL_IRQ_BUSID            DRM_IOWR(0x03, drm_irq_busid_t)
+#define DRM_IOCTL_GET_MAP               DRM_IOWR(0x04, drm_map_t)
+#define DRM_IOCTL_GET_CLIENT            DRM_IOWR(0x05, drm_client_t)
+#define DRM_IOCTL_GET_STATS             DRM_IOR( 0x06, drm_stats_t)
+
+#define DRM_IOCTL_SET_UNIQUE           DRM_IOW( 0x10, drm_unique_t)
+#define DRM_IOCTL_AUTH_MAGIC           DRM_IOW( 0x11, drm_auth_t)
+#define DRM_IOCTL_BLOCK                        DRM_IOWR(0x12, drm_block_t)
+#define DRM_IOCTL_UNBLOCK              DRM_IOWR(0x13, drm_block_t)
+#define DRM_IOCTL_CONTROL              DRM_IOW( 0x14, drm_control_t)
+#define DRM_IOCTL_ADD_MAP              DRM_IOWR(0x15, drm_map_t)
+#define DRM_IOCTL_ADD_BUFS             DRM_IOWR(0x16, drm_buf_desc_t)
+#define DRM_IOCTL_MARK_BUFS            DRM_IOW( 0x17, drm_buf_desc_t)
+#define DRM_IOCTL_INFO_BUFS            DRM_IOWR(0x18, drm_buf_info_t)
+#define DRM_IOCTL_MAP_BUFS             DRM_IOWR(0x19, drm_buf_map_t)
+#define DRM_IOCTL_FREE_BUFS            DRM_IOW( 0x1a, drm_buf_free_t)
+
+#define DRM_IOCTL_RM_MAP               DRM_IOW( 0x1b, drm_map_t)
+
+#define DRM_IOCTL_SET_SAREA_CTX                DRM_IOW( 0x1c, drm_ctx_priv_map_t)
+#define DRM_IOCTL_GET_SAREA_CTX        DRM_IOWR(0x1d, drm_ctx_priv_map_t)
+
+#define DRM_IOCTL_ADD_CTX              DRM_IOWR(0x20, drm_ctx_t)
+#define DRM_IOCTL_RM_CTX               DRM_IOWR(0x21, drm_ctx_t)
+#define DRM_IOCTL_MOD_CTX              DRM_IOW( 0x22, drm_ctx_t)
+#define DRM_IOCTL_GET_CTX              DRM_IOWR(0x23, drm_ctx_t)
+#define DRM_IOCTL_SWITCH_CTX           DRM_IOW( 0x24, drm_ctx_t)
+#define DRM_IOCTL_NEW_CTX              DRM_IOW( 0x25, drm_ctx_t)
+#define DRM_IOCTL_RES_CTX              DRM_IOWR(0x26, drm_ctx_res_t)
+#define DRM_IOCTL_ADD_DRAW             DRM_IOWR(0x27, drm_draw_t)
+#define DRM_IOCTL_RM_DRAW              DRM_IOWR(0x28, drm_draw_t)
+#define DRM_IOCTL_DMA                  DRM_IOWR(0x29, drm_dma_t)
+#define DRM_IOCTL_LOCK                 DRM_IOW( 0x2a, drm_lock_t)
+#define DRM_IOCTL_UNLOCK               DRM_IOW( 0x2b, drm_lock_t)
+#define DRM_IOCTL_FINISH               DRM_IOW( 0x2c, drm_lock_t)
+
+#define DRM_IOCTL_AGP_ACQUIRE          DRM_IO(  0x30)
+#define DRM_IOCTL_AGP_RELEASE          DRM_IO(  0x31)
+#define DRM_IOCTL_AGP_ENABLE           DRM_IOW( 0x32, drm_agp_mode_t)
+#define DRM_IOCTL_AGP_INFO             DRM_IOR( 0x33, drm_agp_info_t)
+#define DRM_IOCTL_AGP_ALLOC            DRM_IOWR(0x34, drm_agp_buffer_t)
+#define DRM_IOCTL_AGP_FREE             DRM_IOW( 0x35, drm_agp_buffer_t)
+#define DRM_IOCTL_AGP_BIND             DRM_IOW( 0x36, drm_agp_binding_t)
+#define DRM_IOCTL_AGP_UNBIND           DRM_IOW( 0x37, drm_agp_binding_t)
+
+#define DRM_IOCTL_SG_ALLOC             DRM_IOW( 0x38, drm_scatter_gather_t)
+#define DRM_IOCTL_SG_FREE              DRM_IOW( 0x39, drm_scatter_gather_t)
+
+#define DRM_IOCTL_WAIT_VBLANK          DRM_IOWR(0x3a, drm_wait_vblank_t)
+
+/**
+ * Device specific ioctls should only be in their respective headers
+ * The device specific ioctl range is from 0x40 to 0x79.
+ *
+ * \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and
+ * drmCommandReadWrite().
+ */
+#define DRM_COMMAND_BASE                0x40
+
+#endif
diff --git a/src/glx/mini/drmtest.c b/src/glx/mini/drmtest.c
new file mode 100644 (file)
index 0000000..f9cad39
--- /dev/null
@@ -0,0 +1,140 @@
+#include <assert.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include "xf86drm.h"
+
+char *pciBusID = "PCI:1:0:0";
+#define DRM_PAGE_SIZE 4096
+void *pSAREA;
+
+
+static int client( void )
+{
+   int fd, ret, err;
+   drmContext clientContext;
+
+   fprintf(stderr, "Opening client drm\n");
+
+   fd = drmOpen(NULL,pciBusID);
+   if (fd < 0) {
+      fprintf(stderr, "failed to open DRM: %s\n", strerror(-fd));
+      return 1;
+   }
+
+
+   fprintf(stderr, "Create server context\n");
+   if ((err = drmCreateContext(fd, &clientContext)) != 0) {
+      fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err);
+      return 0;
+   }
+
+
+   fprintf(stderr, "DRM_LOCK( %d %p %d )\n", fd, pSAREA, clientContext);
+   DRM_LOCK(fd, pSAREA, clientContext, 0);
+   fprintf(stderr, "locked\n");
+   DRM_UNLOCK(fd, pSAREA, clientContext);
+   fprintf(stderr, "DRM_UNLOCK finished\n");
+
+
+   fprintf(stderr, "Closing client drm: %d\n", fd);
+   ret = drmClose(fd);
+   fprintf(stderr, "done %d\n", ret);
+
+   return ret;
+}
+
+int main( int argc, char *argv[] )
+{
+   char *drmModuleName = "radeon";
+   int drmFD;
+   int err;
+   int SAREASize;
+   drmHandle hSAREA;
+   drmContext serverContext;
+
+   /* Note that drmOpen will try to load the kernel module, if needed. */
+   drmFD = drmOpen(drmModuleName, NULL );
+   if (drmFD < 0) {
+      /* failed to open DRM */
+      fprintf(stderr, "[drm] drmOpen failed\n");
+      return 0;
+   }
+
+
+   if ((err = drmSetBusid(drmFD, pciBusID)) < 0) {
+      drmClose(drmFD);
+      fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n",
+             drmFD, pciBusID, strerror(-err));
+      return 0;
+   }
+
+   
+   SAREASize = DRM_PAGE_SIZE;
+   
+   if (drmAddMap( drmFD,
+                 0,
+                 SAREASize,
+                 DRM_SHM,
+                 DRM_CONTAINS_LOCK,
+                 &hSAREA) < 0)
+   {
+      drmClose(drmFD);
+      fprintf(stderr, "[drm] drmAddMap failed\n");
+      return 0;
+   }
+
+   fprintf(stderr, "[drm] added %d byte SAREA at 0x%08lx\n",
+          SAREASize, hSAREA);
+
+   if (drmMap( drmFD,
+              hSAREA,
+              SAREASize,
+              (drmAddressPtr)(&pSAREA)) < 0)
+   {
+      drmClose(drmFD);
+      fprintf(stderr, "[drm] drmMap failed\n");
+      return 0;
+   }
+
+   memset(pSAREA, 0, SAREASize);
+   fprintf(stderr, "[drm] mapped SAREA 0x%08lx to %p, size %d\n",
+          hSAREA, pSAREA, SAREASize);
+
+   fprintf(stderr, "Create server context\n");
+   if ((err = drmCreateContext(drmFD, &serverContext)) != 0) {
+      fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err);
+      return 0;
+   }
+
+
+   fprintf(stderr, "DRM_LOCK( %d %p %d )\n", drmFD, pSAREA, serverContext);
+   DRM_LOCK(drmFD, pSAREA, serverContext, 0);
+   fprintf(stderr, "locked\n");
+   DRM_UNLOCK(drmFD, pSAREA, serverContext);
+   fprintf(stderr, "DRM_UNLOCK finished\n");
+
+
+   client();
+
+
+   fprintf(stderr, "DRM_LOCK( %d %p %d )\n", drmFD, pSAREA, serverContext);
+   DRM_LOCK(drmFD, pSAREA, serverContext, 0);
+   fprintf(stderr, "locked\n");
+   DRM_UNLOCK(drmFD, pSAREA, serverContext);
+   fprintf(stderr, "DRM_UNLOCK finished\n");
+
+
+   drmUnmap(pSAREA, SAREASize);
+   fprintf(stderr, "[drm] unmapped SAREA 0x%08lx from %p, size %d\n",
+          hSAREA, pSAREA, SAREASize);
+   pSAREA = 0;
+
+   fprintf(stderr, "%s: Closing DRM fd\n", __FUNCTION__);
+   (void)drmClose(drmFD);
+
+   return 0;
+}
+
+
+
diff --git a/src/glx/mini/example.miniglx.conf b/src/glx/mini/example.miniglx.conf
new file mode 100644 (file)
index 0000000..06adbff
--- /dev/null
@@ -0,0 +1,26 @@
+# Example miniglx configuration file (/etc/miniglx.conf)
+#
+
+# Framebuffer device to open: Might need to change this on dual-head
+# systems.
+fbdevDevice=/dev/fb0
+
+# Which driver?  
+#    radeon_dri.so -- HW accelerated radeon driver
+#    fb_dri.so -- Software rasterizer
+clientDriverName=radeon_dri.so
+
+# The pci bus id of the video card.  Find this with scanpci, lspci or
+# look in /proc/pci.  
+pciBusID=PCI:1:0:0 
+
+# Virtual screen dimensions.  Can reduce this to save videocard memory
+# at the expense of maximum window size available.
+virtualWidth=1280
+virtualHeight=1024 
+
+# Screen depth.  Only 16 & 32bpp supported.
+bpp=32
+
+# Rotated monitor? -- NOTE: only works with subsetted radeon driver!
+rotateMode=0
diff --git a/src/glx/mini/miniglx.c b/src/glx/mini/miniglx.c
new file mode 100644 (file)
index 0000000..25c7b96
--- /dev/null
@@ -0,0 +1,1975 @@
+/**
+ * \file miniglx.c
+ * \brief Mini GLX interface functions.
+ * \author Brian Paul
+ *
+ * The Mini GLX interface is a subset of the GLX interface, plus a
+ * minimal set of Xlib functions.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  5.0
+ *
+ * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* $Id: miniglx.c,v 1.1 2003/08/22 20:11:43 brianp Exp $ */
+
+/**
+ * \mainpage Mini GLX
+ *
+ * \section miniglxIntro Introduction
+ *
+ * The Mini GLX interface facilitates OpenGL rendering on embedded devices. The
+ * interface is a subset of the GLX interface, plus a minimal set of Xlib-like
+ * functions.
+ *
+ * Programs written to the Mini GLX specification should run unchanged
+ * on systems with the X Window System and the GLX extension (after
+ * recompilation). The intention is to allow flexibility for
+ * prototyping and testing.
+ *
+ * The files in the src/miniglx/ directory are compiled to build the
+ * libGL.so library.  This is the library which applications link with.
+ * libGL.so in turn, loads the hardware-specific device driver.
+ *
+ *
+ * \section miniglxDoxygen About Doxygen
+ *
+ * For a list of all files, select <b>File List</b>.  Choose a file from
+ * the list for a list of all functions in the file.
+ *
+ * For a list of all functions, types, constants, etc.
+ * select <b>File Members</b>.
+ *
+ *
+ * \section miniglxReferences References
+ *
+ * - <A HREF="file:../../docs/MiniGLX.html">Mini GLX Specification</A>,
+ *   Tungsten Graphics, Inc.
+ * - OpenGL Graphics with the X Window System, Silicon Graphics, Inc.,
+ *   ftp://ftp.sgi.com/opengl/doc/opengl1.2/glx1.3.ps
+ * - Xlib - C Language X Interface, X Consortium Standard, X Version 11,
+ *   Release 6.4, ftp://ftp.x.org/pub/R6.4/xc/doc/hardcopy/X11/xlib.PS.gz
+ * - XFree86 Man pages, The XFree86 Project, Inc.,
+ *   http://www.xfree86.org/current/manindex3.html
+ *   
+ */
+
+/**
+ * \page datatypes Notes on the XVisualInfo, Visual, and __GLXvisualConfig data types
+ * 
+ * -# X (unfortunately) has two (or three) data types which
+ *    describe visuals.  Ideally, there would just be one.
+ * -# We need the #__GLXvisualConfig type to augment #XVisualInfo and #Visual
+ *    because we need to describe the GLX-specific attributes of visuals.
+ * -# In this interface there is a one-to-one-to-one correspondence between
+ *    the three types and they're all interconnected.
+ * -# The #XVisualInfo type has a pointer to a #Visual.  The #Visual structure
+ *    (aka MiniGLXVisualRec) has a pointer to the #__GLXvisualConfig.  The
+ *    #Visual structure also has a pointer pointing back to the #XVisualInfo.
+ * -# The #XVisualInfo structure is the only one who's contents are public.
+ * -# The glXChooseVisual() and XGetVisualInfo() are the only functions that
+ *    return #XVisualInfo structures.  They can be freed with XFree(), though
+ *    there is a small memory leak.
+ */
+
+
+#include <assert.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <linux/kd.h>
+#include <linux/vt.h>
+
+#include "miniglxP.h"
+#include "dri.h"
+
+#include "glapi.h"
+#include "xf86drm.h"
+
+
+/**
+ * \brief Current GLX context.
+ *
+ * \sa glXGetCurrentContext().
+ */
+static GLXContext CurrentContext = NULL;
+
+
+
+static Display *SignalDisplay = 0;
+
+static void SwitchVT(int sig)
+{
+   fprintf(stderr, "SwitchVT %d dpy %p\n", sig, SignalDisplay);
+
+   if (SignalDisplay) {
+      SignalDisplay->vtSignalFlag = 1;
+      switch( sig )
+      {
+      case SIGUSR1:                                /* vt has been released */
+        SignalDisplay->haveVT = 0;
+        break;
+      case SIGUSR2:                                /* vt has been acquired */
+        SignalDisplay->haveVT = 1;
+        break;
+      }
+   }
+}
+
+/**********************************************************************/
+/** \name Framebuffer device functions                                */
+/**********************************************************************/
+/*@{*/
+
+/**
+ * \brief Do the first part of setting up the framebuffer device.
+ *
+ * \param dpy the display handle.
+ * \param use_vt use a VT for display or not
+ *
+ * \return GL_TRUE on success, or GL_FALSE on failure.
+ * 
+ * \sa This is called during XOpenDisplay().
+ *
+ * \internal
+ * Gets the VT number, opens the respective console TTY device. Saves its state
+ * to restore when exiting and goes into graphics mode.
+ *
+ * Opens the framebuffer device and make a copy of the original variable screen
+ * information and gets the fixed screen information.  Maps the framebuffer and
+ * MMIO region into the process address space.
+ */
+static GLboolean
+OpenFBDev( Display *dpy, int use_vt )
+{
+   char ttystr[1000];
+   int fd, vtnumber, ttyfd;
+
+   assert(dpy);
+
+   if (geteuid()) {
+      fprintf(stderr, "error: you need to be root\n");
+      return GL_FALSE;
+   }
+   
+   if (use_vt) {
+       
+       /* open /dev/tty0 and get the VT number */
+       if ((fd = open("/dev/tty0", O_WRONLY, 0)) < 0) {
+          fprintf(stderr, "error opening /dev/tty0\n");
+          return GL_FALSE;
+       }
+       if (ioctl(fd, VT_OPENQRY, &vtnumber) < 0 || vtnumber < 0) {
+          fprintf(stderr, "error: couldn't get a free vt\n");
+          return GL_FALSE;
+       }
+       
+       fprintf(stderr, "*** got vt nr: %d\n", vtnumber);
+       close(fd);
+       
+       /* open the console tty */
+       sprintf(ttystr, "/dev/tty%d", vtnumber);  /* /dev/tty1-64 */
+       dpy->ConsoleFD = open(ttystr, O_RDWR | O_NDELAY, 0);
+       if (dpy->ConsoleFD < 0) {
+          fprintf(stderr, "error couldn't open console fd\n");
+          return GL_FALSE;
+       }
+       
+       /* save current vt number */
+       {
+          struct vt_stat vts;
+          if (ioctl(dpy->ConsoleFD, VT_GETSTATE, &vts) == 0)
+              dpy->OriginalVT = vts.v_active;
+       }
+       
+       /* disconnect from controlling tty */
+       ttyfd = open("/dev/tty", O_RDWR);
+       if (ttyfd >= 0) {
+          ioctl(ttyfd, TIOCNOTTY, 0);
+          close(ttyfd);
+       }
+       
+       /* some magic to restore the vt when we exit */
+       {
+          struct vt_mode vt;
+          struct sigaction sig_tty;
+          
+          /* Set-up tty signal handler to catch the signal we request below */
+          SignalDisplay = dpy;
+          memset( &sig_tty, 0, sizeof( sig_tty ) );
+          sig_tty.sa_handler = SwitchVT;
+          sigemptyset( &sig_tty.sa_mask );
+          if( sigaction( SIGUSR1, &sig_tty, &dpy->OrigSigUsr1 ) ||
+              sigaction( SIGUSR2, &sig_tty, &dpy->OrigSigUsr2 ) )
+          {
+              fprintf(stderr, "error: can't set up signal handler (%s)",
+                      strerror(errno) );
+              return GL_FALSE;
+          }
+          
+          
+          
+          vt.mode = VT_PROCESS;
+          vt.waitv = 0;
+          vt.relsig = SIGUSR1;
+          vt.acqsig = SIGUSR2;
+          if (ioctl(dpy->ConsoleFD, VT_SETMODE, &vt) < 0) {
+              fprintf(stderr, "error: ioctl(VT_SETMODE) failed: %s\n",
+                      strerror(errno));
+              return GL_FALSE;
+          }
+          
+          
+          if (ioctl(dpy->ConsoleFD, VT_ACTIVATE, vtnumber) != 0)
+              printf("ioctl VT_ACTIVATE: %s\n", strerror(errno));
+          if (ioctl(dpy->ConsoleFD, VT_WAITACTIVE, vtnumber) != 0)
+              printf("ioctl VT_WAITACTIVE: %s\n", strerror(errno));
+          
+          if (ioctl(dpy->ConsoleFD, VT_GETMODE, &vt) < 0) {
+              fprintf(stderr, "error: ioctl VT_GETMODE: %s\n", strerror(errno));
+              return GL_FALSE;
+          }
+          
+          
+          
+       }
+       
+       /* go into graphics mode */
+       if (ioctl(dpy->ConsoleFD, KDSETMODE, KD_GRAPHICS) < 0) {
+          fprintf(stderr, "error: ioctl(KDSETMODE, KD_GRAPHICS) failed: %s\n",
+                  strerror(errno));
+          return GL_FALSE;
+       }
+   }
+
+   /* open the framebuffer device */
+   dpy->FrameBufferFD = open(dpy->fbdevDevice, O_RDWR);
+   if (dpy->FrameBufferFD < 0) {
+      fprintf(stderr, "Error opening /dev/fb0: %s\n", strerror(errno));
+      return GL_FALSE;
+   }
+
+  /* get the original variable screen info */
+   if (ioctl(dpy->FrameBufferFD, FBIOGET_VSCREENINFO, &dpy->OrigVarInfo)) {
+      fprintf(stderr, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
+              strerror(errno));
+      return GL_FALSE;
+   }
+
+   /* make copy */
+   dpy->VarInfo = dpy->OrigVarInfo;  /* structure copy */
+
+   /* Turn off hw accels (otherwise mmap of mmio region will be
+    * refused)
+    */
+   dpy->VarInfo.accel_flags = 0; 
+   if (ioctl(dpy->FrameBufferFD, FBIOPUT_VSCREENINFO, &dpy->VarInfo)) {
+      fprintf(stderr, "error: ioctl(FBIOPUT_VSCREENINFO) failed: %s\n",
+             strerror(errno));
+      return GL_FALSE;
+   }
+
+
+
+   /* Get the fixed screen info */
+   if (ioctl(dpy->FrameBufferFD, FBIOGET_FSCREENINFO, &dpy->FixedInfo)) {
+      fprintf(stderr, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
+              strerror(errno));
+      return GL_FALSE;
+   }
+
+
+
+   /* mmap the framebuffer into our address space */
+   dpy->driverContext.FBStart = dpy->FixedInfo.smem_start;
+   dpy->driverContext.FBSize = dpy->FixedInfo.smem_len;
+   dpy->driverContext.shared.fbSize = dpy->FixedInfo.smem_len;
+   dpy->driverContext.FBAddress = (caddr_t) mmap(0, /* start */
+                                     dpy->driverContext.shared.fbSize, /* bytes */
+                                     PROT_READ | PROT_WRITE, /* prot */
+                                     MAP_SHARED, /* flags */
+                                     dpy->FrameBufferFD, /* fd */
+                                     0 /* offset */);
+   if (dpy->driverContext.FBAddress == (caddr_t) - 1) {
+      fprintf(stderr, "error: unable to mmap framebuffer: %s\n",
+              strerror(errno));
+      return GL_FALSE;
+   }
+           
+   /* mmap the MMIO region into our address space */
+   dpy->driverContext.MMIOStart = dpy->FixedInfo.mmio_start;
+   dpy->driverContext.MMIOSize = dpy->FixedInfo.mmio_len;
+   dpy->driverContext.MMIOAddress = (caddr_t) mmap(0, /* start */
+                                     dpy->driverContext.MMIOSize, /* bytes */
+                                     PROT_READ | PROT_WRITE, /* prot */
+                                     MAP_SHARED, /* flags */
+                                     dpy->FrameBufferFD, /* fd */
+                                     dpy->FixedInfo.smem_len /* offset */);
+   if (dpy->driverContext.MMIOAddress == (caddr_t) - 1) {
+      fprintf(stderr, "error: unable to mmap mmio region: %s\n",
+              strerror(errno));
+      return GL_FALSE;
+   }
+
+   fprintf(stderr, "got MMIOAddress %p offset %d\n",
+           dpy->driverContext.MMIOAddress,
+          dpy->FixedInfo.smem_len);
+
+   return GL_TRUE;
+}
+
+
+
+
+/**
+ * \brief Setup up the desired framebuffer device mode.  
+ *
+ * \param dpy the display handle.
+ * 
+ * \return GL_TRUE on success, or GL_FALSE on failure.
+ * 
+ * \sa This is called during __miniglx_StartServer().
+ *
+ * \internal
+ *
+ * Bumps the size of the window the the next supported mode. Sets the
+ * variable screen information according to the desired mode and asks
+ * the driver to validate the mode. Certifies that a DirectColor or
+ * TrueColor visual is used from the updated fixed screen information.
+ * In the case of DirectColor visuals, sets up an 'identity' colormap to
+ * mimic a TrueColor visual.
+ *
+ * Calls the driver hooks 'ValidateMode' and 'PostValidateMode' to
+ * allow the driver to make modifications to the chosen mode according
+ * to hardware constraints, or to save and restore videocard registers
+ * that may be clobbered by the fbdev driver.
+ *
+ * \todo Timings are hard-coded in the source for a set of supported modes.
+ */
+static GLboolean
+SetupFBDev( Display *dpy )
+{
+   int width, height;
+
+   assert(dpy);
+
+   width = dpy->driverContext.shared.virtualWidth;
+   height = dpy->driverContext.shared.virtualHeight;
+   
+   /* Bump size up to next supported mode.
+    */
+   if (width <= 800 && height <= 600) {
+      width = 800; height = 600; 
+   }  
+   else if (width <= 1024 && height <= 768) { 
+      width = 1024; height = 768; 
+   } 
+   else if (width <= 768 && height <= 1024) {
+      width = 768; height = 1024; 
+   }  
+   else if (width <= 1280 && height <= 1024) { 
+      width = 1280; height = 1024; 
+   } 
+
+
+   dpy->driverContext.shared.virtualHeight = height;
+   dpy->driverContext.shared.virtualWidth = width;
+   dpy->driverContext.shared.fbStride = width * (dpy->driverContext.bpp / 8);
+   
+   /* set the depth, resolution, etc */
+   dpy->VarInfo = dpy->OrigVarInfo;
+   dpy->VarInfo.bits_per_pixel = dpy->driverContext.bpp;
+   dpy->VarInfo.xres_virtual = dpy->driverContext.shared.virtualWidth;
+   dpy->VarInfo.yres_virtual = dpy->driverContext.shared.virtualHeight;
+   dpy->VarInfo.xres = width;
+   dpy->VarInfo.yres = height;
+   dpy->VarInfo.xoffset = 0;
+   dpy->VarInfo.yoffset = 0;
+   dpy->VarInfo.nonstd = 0;
+   dpy->VarInfo.vmode &= ~FB_VMODE_YWRAP; /* turn off scrolling */
+
+   if (dpy->VarInfo.bits_per_pixel == 32) {
+      dpy->VarInfo.red.offset = 16;
+      dpy->VarInfo.green.offset = 8;
+      dpy->VarInfo.blue.offset = 0;
+      dpy->VarInfo.transp.offset = 24;
+      dpy->VarInfo.red.length = 8;
+      dpy->VarInfo.green.length = 8;
+      dpy->VarInfo.blue.length = 8;
+      dpy->VarInfo.transp.length = 8;
+   }
+   else if (dpy->VarInfo.bits_per_pixel == 16) {
+      dpy->VarInfo.red.offset = 11;
+      dpy->VarInfo.green.offset = 5;
+      dpy->VarInfo.blue.offset = 0;
+      dpy->VarInfo.red.length = 5;
+      dpy->VarInfo.green.length = 6;
+      dpy->VarInfo.blue.length = 5;
+      dpy->VarInfo.transp.offset = 0;
+      dpy->VarInfo.transp.length = 0;
+   }
+   else {
+      fprintf(stderr, "Only 32bpp and 16bpp modes supported at the moment\n");
+      return 0;
+   }
+
+   if (!dpy->driver->validateMode( &dpy->driverContext )) {
+      fprintf(stderr, "Driver validateMode() failed\n");
+      return 0;
+   }
+
+   if (dpy->VarInfo.xres == 1280 && 
+       dpy->VarInfo.yres == 1024) {
+      /* timing values taken from /etc/fb.modes (1280x1024 @ 75Hz) */
+      dpy->VarInfo.pixclock = 7408;
+      dpy->VarInfo.left_margin = 248;
+      dpy->VarInfo.right_margin = 16;
+      dpy->VarInfo.upper_margin = 38;
+      dpy->VarInfo.lower_margin = 1;
+      dpy->VarInfo.hsync_len = 144;
+      dpy->VarInfo.vsync_len = 3;
+   }
+   else if (dpy->VarInfo.xres == 1024 && 
+           dpy->VarInfo.yres == 768) {
+      /* timing values taken from /etc/fb.modes (1024x768 @ 75Hz) */
+      dpy->VarInfo.pixclock = 12699;
+      dpy->VarInfo.left_margin = 176;
+      dpy->VarInfo.right_margin = 16;
+      dpy->VarInfo.upper_margin = 28;
+      dpy->VarInfo.lower_margin = 1;
+      dpy->VarInfo.hsync_len = 96;
+      dpy->VarInfo.vsync_len = 3;
+   }
+   else if (dpy->VarInfo.xres == 800 &&
+           dpy->VarInfo.yres == 600) {
+      /* timing values taken from /etc/fb.modes (800x600 @ 75Hz) */
+      dpy->VarInfo.pixclock = 20203;
+      dpy->VarInfo.left_margin = 160;
+      dpy->VarInfo.right_margin = 16;
+      dpy->VarInfo.upper_margin = 21;
+      dpy->VarInfo.lower_margin = 1;
+      dpy->VarInfo.hsync_len = 80;
+      dpy->VarInfo.vsync_len = 3;
+   }
+   else if (dpy->VarInfo.xres == 768 &&
+           dpy->VarInfo.yres == 1024) {
+      /* timing values for 768x1024 @ 75Hz */
+      dpy->VarInfo.pixclock = 11993;
+      dpy->VarInfo.left_margin = 136;
+      dpy->VarInfo.right_margin = 32;
+      dpy->VarInfo.upper_margin = 41;
+      dpy->VarInfo.lower_margin = 1;
+      dpy->VarInfo.hsync_len = 80;
+      dpy->VarInfo.vsync_len = 3;
+   }
+   else {
+      /* XXX need timings for other screen sizes */
+      fprintf(stderr, "XXXX screen size %d x %d not supported at this time!\n",
+             dpy->VarInfo.xres, dpy->VarInfo.yres);
+      return GL_FALSE;
+   }
+
+   fprintf(stderr, "[miniglx] Setting mode: visible %dx%d virtual %dx%dx%d\n",
+          dpy->VarInfo.xres, dpy->VarInfo.yres,
+          dpy->VarInfo.xres_virtual, dpy->VarInfo.yres_virtual,
+          dpy->VarInfo.bits_per_pixel);
+
+   /* set variable screen info */
+   if (ioctl(dpy->FrameBufferFD, FBIOPUT_VSCREENINFO, &dpy->VarInfo)) {
+      fprintf(stderr, "error: ioctl(FBIOPUT_VSCREENINFO) failed: %s\n",
+             strerror(errno));
+      return GL_FALSE;
+   }
+
+   /* get the variable screen info, in case it has been modified */
+   if (ioctl(dpy->FrameBufferFD, FBIOGET_VSCREENINFO, &dpy->VarInfo)) {
+      fprintf(stderr, "error: ioctl(FBIOGET_VSCREENINFO) failed: %s\n",
+              strerror(errno));
+      return GL_FALSE;
+   }
+
+
+   fprintf(stderr, "[miniglx] Readback mode: visible %dx%d virtual %dx%dx%d\n",
+          dpy->VarInfo.xres, dpy->VarInfo.yres,
+          dpy->VarInfo.xres_virtual, dpy->VarInfo.yres_virtual,
+          dpy->VarInfo.bits_per_pixel);
+
+   /* Get the fixed screen info */
+   if (ioctl(dpy->FrameBufferFD, FBIOGET_FSCREENINFO, &dpy->FixedInfo)) {
+      fprintf(stderr, "error: ioctl(FBIOGET_FSCREENINFO) failed: %s\n",
+              strerror(errno));
+      return GL_FALSE;
+   }
+
+   if (dpy->FixedInfo.visual != FB_VISUAL_TRUECOLOR &&
+       dpy->FixedInfo.visual != FB_VISUAL_DIRECTCOLOR) {
+      fprintf(stderr, "non-TRUECOLOR visuals not supported.\n");
+      return GL_FALSE;
+   }
+
+   if (dpy->FixedInfo.visual == FB_VISUAL_DIRECTCOLOR) {
+      struct fb_cmap cmap;
+      unsigned short red[256], green[256], blue[256];
+      int rcols = 1 << dpy->VarInfo.red.length;
+      int gcols = 1 << dpy->VarInfo.green.length;
+      int bcols = 1 << dpy->VarInfo.blue.length;
+      int i;
+
+      cmap.start = 0;      
+      cmap.len = gcols;
+      cmap.red   = red;
+      cmap.green = green;
+      cmap.blue  = blue;
+      cmap.transp = NULL;
+
+      for (i = 0; i < rcols ; i++) 
+         red[i] = (65536/(rcols-1)) * i;
+
+      for (i = 0; i < gcols ; i++) 
+         green[i] = (65536/(gcols-1)) * i;
+
+      for (i = 0; i < bcols ; i++) 
+         blue[i] = (65536/(bcols-1)) * i;
+      
+      if (ioctl(dpy->FrameBufferFD, FBIOPUTCMAP, (void *) &cmap) < 0) {
+         fprintf(stderr, "ioctl(FBIOPUTCMAP) failed [%d]\n", i);
+        exit(1);
+      }
+   }
+
+   /* May need to restore regs fbdev has clobbered:
+    */
+   if (!dpy->driver->postValidateMode( &dpy->driverContext )) {
+      fprintf(stderr, "Driver postValidateMode() failed\n");
+      return 0;
+   }
+
+   return GL_TRUE;
+}
+
+
+/**
+ * \brief Restore the framebuffer device to state it was in before we started
+ *
+ * Undoes the work done by SetupFBDev().
+ * 
+ * \param dpy the display handle.
+ *
+ * \return GL_TRUE on success, or GL_FALSE on failure.
+ * 
+ * \sa Called from XDestroyWindow().
+ *
+ * \internal
+ * Restores the original variable screen info.
+ */
+static GLboolean
+RestoreFBDev( Display *dpy )
+{
+   /* restore original variable screen info */
+   if (ioctl(dpy->FrameBufferFD, FBIOPUT_VSCREENINFO, &dpy->OrigVarInfo)) {
+      fprintf(stderr, "ioctl(FBIOPUT_VSCREENINFO failed): %s\n",
+              strerror(errno));
+      return GL_FALSE;
+   }
+   dpy->VarInfo = dpy->OrigVarInfo;
+
+   return GL_TRUE;
+}
+
+
+/**
+ * \brief Close the framebuffer device.  
+ *
+ * \param dpy the display handle.
+ * 
+ * \sa Called from XCloseDisplay().
+ *
+ * \internal
+ * Unmaps the framebuffer and MMIO region.  Restores the text mode and the
+ * original virtual terminal. Closes the console and framebuffer devices.
+ */
+static void
+CloseFBDev( Display *dpy )
+{
+   struct vt_mode VT;
+
+   munmap(dpy->driverContext.FBAddress, dpy->driverContext.FBSize);
+   munmap(dpy->driverContext.MMIOAddress, dpy->driverContext.MMIOSize);
+
+   if (dpy->ConsoleFD) {
+       /* restore text mode */
+       ioctl(dpy->ConsoleFD, KDSETMODE, KD_TEXT);
+       
+       /* set vt */
+       if (ioctl(dpy->ConsoleFD, VT_GETMODE, &VT) != -1) {
+          VT.mode = VT_AUTO;
+          ioctl(dpy->ConsoleFD, VT_SETMODE, &VT);
+       }
+       
+       /* restore original vt */
+       if (dpy->OriginalVT >= 0) {
+          ioctl(dpy->ConsoleFD, VT_ACTIVATE, dpy->OriginalVT);
+          dpy->OriginalVT = -1;
+       }
+       
+       close(dpy->ConsoleFD);
+   }
+   close(dpy->FrameBufferFD);
+}
+
+/*@}*/
+
+
+/**********************************************************************/
+/** \name Misc functions needed for DRI drivers                       */
+/**********************************************************************/
+/*@{*/
+
+/**
+ * \brief Find the DRI screen dependent methods associated with the display.
+ *
+ * \param dpy a display handle, as returned by XOpenDisplay().
+ * \param scrn the screen number. Not referenced.
+ * 
+ * \returns a pointer to a __DRIscreenRec structure.
+ * 
+ * \internal
+ * Returns the MiniGLXDisplayRec::driScreen attribute.
+ */
+__DRIscreen *
+__glXFindDRIScreen(Display *dpy, int scrn)
+{
+   (void) scrn;
+   return dpy->driScreen;
+}
+
+/**
+ * \brief Validate a drawable.
+ *
+ * \param dpy a display handle, as returned by XOpenDisplay().
+ * \param draw drawable to validate.
+ * 
+ * \internal
+ * Since Mini GLX only supports one window, compares the specified drawable with
+ * the MiniGLXDisplayRec::TheWindow attribute.
+ */
+Bool
+__glXWindowExists(Display *dpy, GLXDrawable draw)
+{
+   if (dpy->TheWindow == draw)
+      return True;
+   else
+      return False;
+}
+
+/**
+ * \brief Get current thread ID.
+ *
+ * \return thread ID.
+ *
+ * \internal
+ * Always returns 0. 
+ */
+/*unsigned long
+_glthread_GetID(void)
+{
+   return 0;
+}*/
+
+/*@}*/
+
+
+/**
+ * \brief Scan Linux /prog/bus/pci/devices file to determine hardware
+ * chipset based on supplied bus ID.
+ * 
+ * \return probed chipset (non-zero) on success, zero otherwise.
+ * 
+ * \internal 
+ */
+static int get_chipset_from_busid( Display *dpy )
+{
+   char buf[0x200];
+   FILE *file;
+   const char *fname = "/proc/bus/pci/devices";
+   int retval = 0;
+
+   if (!(file = fopen(fname,"r"))) {
+      fprintf(stderr, "couldn't open %s: %s\n", fname, strerror(errno));
+      return 0;
+   }
+
+   while (fgets(buf, sizeof(buf)-1, file)) {
+      unsigned int nr, bus, dev, fn, vendor, device, encode;
+      nr = sscanf(buf, "%04x\t%04x%04x", &encode, 
+                 &vendor, &device);
+      
+      bus = encode >> 16;
+      dev = (encode & 0xFF) >> 3;
+      fn = encode & 0x7;
+
+      if (nr != 3)
+        break;
+
+      if (bus == dpy->driverContext.pciBus &&
+          dev == dpy->driverContext.pciDevice &&
+          fn  == dpy->driverContext.pciFunc) {
+        retval = device;
+        break;
+      }
+   }
+
+   fclose(file);
+
+   if (retval)
+      fprintf(stderr, "[miniglx] probed chipset 0x%x\n", retval);
+   else
+      fprintf(stderr, "[miniglx] failed to probe chipset\n");
+
+   return retval;
+}
+
+
+/**
+ * \brief Read settings from a configuration file.
+ * 
+ * The configuration file is usually "/etc/miniglx.conf", but can be overridden
+ * with the MINIGLX_CONF environment variable. 
+ *
+ * The format consists in \code option = value \endcode lines. The option names 
+ * corresponds to the fields in MiniGLXDisplayRec.
+ * 
+ * \param dpy the display handle as.
+ *
+ * \return non-zero on success, zero otherwise.
+ * 
+ * \internal 
+ * Sets some defaults. Opens and parses the the Mini GLX configuration file and
+ * fills in the MiniGLXDisplayRec field that corresponds for each option.
+ */
+static int __read_config_file( Display *dpy )
+{
+   FILE *file;
+   const char *fname;
+
+   /* Fallback/defaults
+    */
+   dpy->fbdevDevice = "/dev/fb0";
+   dpy->clientDriverName = "fb_dri.so";
+   dpy->driverContext.pciBus = 0;
+   dpy->driverContext.pciDevice = 0;
+   dpy->driverContext.pciFunc = 0;
+   dpy->driverContext.chipset = 0;   
+   dpy->driverContext.pciBusID = 0;
+   dpy->driverContext.shared.virtualWidth = 1280;
+   dpy->driverContext.shared.virtualHeight = 1024;
+   dpy->driverContext.bpp = 32;
+   dpy->driverContext.cpp = 4;
+   dpy->rotateMode = 0;
+
+   fname = getenv("MINIGLX_CONF");
+   if (!fname) fname = "/etc/miniglx.conf";
+
+   file = fopen(fname, "r");
+   if (!file) {
+      fprintf(stderr, "couldn't open config file %s: %s\n", fname, strerror(errno));
+      return 0;
+   }
+
+
+   while (!feof(file)) {
+      char buf[81], *opt = buf, *val, *tmp1, *tmp2;
+      fgets(buf, sizeof(buf), file); 
+
+      /* Parse 'opt = val' -- must be easier ways to do this.
+       */
+      while (isspace(*opt)) opt++;
+      val = opt;
+      if (*val == '#') continue; /* comment */
+      while (!isspace(*val) && *val != '=' && *val) val++;
+      tmp1 = val;
+      while (isspace(*val)) val++;
+      if (*val != '=') continue;
+      *tmp1 = 0; 
+      val++;
+      while (isspace(*val)) val++;
+      tmp2 = val;
+      while (!isspace(*tmp2) && *tmp2 != '\n' && *tmp2) tmp2++;
+      *tmp2 = 0;
+
+
+      if (strcmp(opt, "fbdevDevice") == 0) 
+        dpy->fbdevDevice = strdup(val);
+      else if (strcmp(opt, "clientDriverName") == 0)
+        dpy->clientDriverName = strdup(val);
+      else if (strcmp(opt, "rotateMode") == 0)
+        dpy->rotateMode = atoi(val) ? 1 : 0;
+      else if (strcmp(opt, "pciBusID") == 0) {
+        if (sscanf(val, "PCI:%d:%d:%d",
+                   &dpy->driverContext.pciBus,
+                    &dpy->driverContext.pciDevice,
+                    &dpy->driverContext.pciFunc) != 3) {
+           fprintf(stderr, "malformed bus id: %s\n", val);
+           continue;
+        }
+        dpy->driverContext.pciBusID = strdup(val);
+      }
+      else if (strcmp(opt, "chipset") == 0) {
+        if (sscanf(val, "0x%x", &dpy->driverContext.chipset) != 1)
+           fprintf(stderr, "malformed chipset: %s\n", opt);
+      }
+      else if (strcmp(opt, "virtualWidth") == 0) {
+        if (sscanf(val, "%d", &dpy->driverContext.shared.virtualWidth) != 1)
+           fprintf(stderr, "malformed virtualWidth: %s\n", opt);
+      }
+      else if (strcmp(opt, "virtualHeight") == 0) {
+        if (sscanf(val, "%d", &dpy->driverContext.shared.virtualHeight) != 1)
+           fprintf(stderr, "malformed virutalHeight: %s\n", opt);
+      }
+      else if (strcmp(opt, "bpp") == 0) {
+        if (sscanf(val, "%d", &dpy->driverContext.bpp) != 1)
+           fprintf(stderr, "malformed bpp: %s\n", opt);
+        dpy->driverContext.cpp = dpy->driverContext.bpp / 8;
+      }
+   }
+
+   fclose(file);
+
+   if (dpy->driverContext.chipset == 0 && dpy->driverContext.pciBusID != 0) 
+      dpy->driverContext.chipset = get_chipset_from_busid( dpy );
+
+   return 1;
+}
+
+static int InitDriver( Display *dpy )
+{
+   /*
+    * Begin DRI setup.
+    * We're kind of combining the per-display and per-screen information
+    * which was kept separate in XFree86/DRI's libGL.
+    */
+   dpy->dlHandle = dlopen(dpy->clientDriverName, RTLD_NOW | RTLD_GLOBAL);
+   if (!dpy->dlHandle) {
+      fprintf(stderr, "Unable to open %s: %s\n", dpy->clientDriverName,
+             dlerror());
+      return GL_FALSE;
+   }
+
+   /* Pull in Mini GLX specific hooks:
+    */
+   dpy->driver = (struct DRIDriverRec *) dlsym(dpy->dlHandle,
+                                               "__driDriver");
+   if (!dpy->driver) {
+      fprintf(stderr, "Couldn't find __driDriver in %s\n",
+              dpy->clientDriverName);
+      dlclose(dpy->dlHandle);
+      return GL_FALSE;
+   }
+
+   /* Pull in standard DRI client-side driver hooks:
+    */
+   dpy->createScreen = (driCreateScreenFunc*) dlsym(dpy->dlHandle,
+                                                "__driCreateScreen");
+   if (!dpy->createScreen) {
+      fprintf(stderr, "Couldn't find __driCreateScreen in %s\n",
+              dpy->clientDriverName);
+      dlclose(dpy->dlHandle);
+      return GL_FALSE;
+   }
+
+   return GL_TRUE;
+}
+
+
+/**********************************************************************/
+/** \name Public API functions (Xlib and GLX)                         */
+/**********************************************************************/
+/*@{*/
+
+
+/**
+ * \brief Initialize the graphics system.
+ * 
+ * \param display_name currently ignored. It is recommended to pass it as NULL.
+ * \return a pointer to a #Display if the function is able to initialize
+ * the graphics system, NULL otherwise.
+ * 
+ * Allocates a MiniGLXDisplayRec structure and fills in with information from a
+ * configuration file. 
+ *
+ * Calls OpenFBDev() to open the framebuffer device and calls
+ * DRIDriverRec::initFBDev to do the client-side initialization on it.
+ *
+ * Loads the DRI driver and pulls in Mini GLX specific hooks into a
+ * DRIDriverRec structure, and the standard DRI \e __driCreateScreen hook.
+ * Asks the driver for a list of supported visuals.  Performs the per-screen
+ * client-side initialization.  Also setups the callbacks in the screen private
+ * information.
+ *
+ * Does the framebuffer device setup. Calls __miniglx_open_connections() to
+ * serve clients.
+ */
+Display *
+__miniglx_StartServer( const char *display_name )
+{
+   Display *dpy;
+   int use_vt = 0;
+
+   dpy = (Display *)calloc(1, sizeof(Display));
+   if (!dpy)
+      return NULL;
+
+   dpy->IsClient = False;
+
+   if (!__read_config_file( dpy )) {
+      fprintf(stderr, "Couldn't get configuration details\n");
+      free(dpy);
+      return NULL;
+   }
+
+   /* Open the fbdev device
+    */
+   if (!OpenFBDev(dpy, use_vt)) {
+      fprintf(stderr, "OpenFBDev failed\n");
+      free(dpy);
+      return NULL;
+   }
+
+   if (!InitDriver(dpy)) {
+      fprintf(stderr, "InitDriver failed\n");
+      free(dpy);
+      return NULL;
+   }
+
+   /* Ask the driver for a list of supported configs:
+   */
+   dpy->driver->initContextModes( &dpy->driverContext, &dpy->numModes, &dpy->modes );
+
+   /* Perform the initialization normally done in the X server 
+    */
+   if (!dpy->driver->initFBDev( &dpy->driverContext )) {
+      fprintf(stderr, "%s: __driInitFBDev failed\n", __FUNCTION__);
+      dlclose(dpy->dlHandle);
+      return GL_FALSE;
+   }
+
+   /* do fbdev setup
+    */
+   if (!SetupFBDev(dpy)) {
+      fprintf(stderr, "SetupFBDev failed\n");
+      free(dpy);
+      return NULL;
+   }
+
+   /* unlock here if not using VT -- JDS */
+   if (!use_vt) {
+       if (dpy->driver->restoreHardware)
+          dpy->driver->restoreHardware( &dpy->driverContext ); 
+       DRM_UNLOCK( dpy->driverContext.drmFD,
+                  dpy->driverContext.pSAREA,
+                  dpy->driverContext.serverContext );
+       dpy->hwActive = 1;
+   }
+
+   /* Ready for clients:
+    */
+   if (!__miniglx_open_connections(dpy)) {
+      free(dpy);
+      return NULL;
+   }
+      
+   return dpy;
+}
+
+
+/**
+ * \brief Initialize the graphics system.
+ * 
+ * \param display_name currently ignored. It is recommended to pass it as NULL.
+ * \return a pointer to a #Display if the function is able to initialize
+ * the graphics system, NULL otherwise.
+ * 
+ * Allocates a MiniGLXDisplayRec structure and fills in with information from a
+ * configuration file. 
+ *
+ * Calls __miniglx_open_connections() to connect to the server.
+ * 
+ * Loads the DRI driver and pulls in Mini GLX specific hooks into a
+ * DRIDriverRec structure, and the standard DRI \e __driCreateScreen hook.
+ * Asks the driver for a list of supported visuals.  Performs the per-screen
+ * client-side initialization.  Also setups the callbacks in the screen private
+ * information.
+ *
+ * \todo
+ *   - read config file
+ *      - what about virtualWidth, etc?
+ *   - determine dpy->driverClientMsgSize,
+ *   - allocate dpy->driverClientMsg
+ */
+Display *
+XOpenDisplay( const char *display_name )
+{
+   Display *dpy;
+
+   dpy = (Display *)calloc(1, sizeof(Display));
+   if (!dpy)
+      return NULL;
+
+   dpy->IsClient = True;
+
+   /* read config file 
+    */
+   if (!__read_config_file( dpy )) {
+      fprintf(stderr, "Couldn't get configuration details\n");
+      free(dpy);
+      return NULL;
+   }
+
+   /* Connect to the server and receive driverClientMsg
+    */
+   if (!__miniglx_open_connections(dpy)) {
+      free(dpy);
+      return NULL;
+   }
+
+   /* dlopen the driver .so file
+    */
+   if (!InitDriver(dpy)) {
+      fprintf(stderr, "InitDriver failed\n");
+      free(dpy);
+      return NULL;
+   }
+
+   /* Ask the driver for a list of supported configs:
+   */
+   dpy->driver->initContextModes( &dpy->driverContext, &dpy->numModes, &dpy->modes );
+   
+   /* Perform the client-side initialization.  
+    *
+    * Clearly there is a limit of one on the number of windows in
+    * existence at any time.
+    *
+    * Need to shut down DRM and free DRI data in XDestroyWindow(), too.
+    */
+   dpy->driScreen = (*dpy->createScreen)(dpy->driver,
+                                        &dpy->driverContext);
+   if (!dpy->driScreen) {
+      fprintf(stderr, "%s: __driCreateScreen failed\n", __FUNCTION__);
+      dlclose(dpy->dlHandle);
+      free(dpy);
+      return NULL;
+   }
+   
+   /* Anything more to do?
+    */
+   return dpy;
+}
+
+
+/**
+ * \brief Release display resources.
+ * 
+ * When the application is about to exit, the resources associated with the
+ * graphics system can be released by calling this function.
+ * 
+ * \param dpy display handle. It becomes invalid at this point.
+ * 
+ * Destroys the window if any, and destroys the per-screen
+ * driver private information.
+ * Calls __miniglx_close_connections().
+ * 
+ * If a server, puts the the framebuffer back into the initial state.
+ *
+ * Finally frees the display structure.
+ */
+void
+XCloseDisplay( Display *dpy )
+{
+   glXMakeCurrent( dpy, NULL, NULL);
+
+   if (dpy->NumWindows) 
+      XDestroyWindow( dpy, dpy->TheWindow );
+
+   /* As this is done in XOpenDisplay, need to undo it here:
+    */
+   (*dpy->driScreen->destroyScreen)(dpy->driScreen);
+
+   __miniglx_close_connections( dpy );
+
+   if (!dpy->IsClient) {
+      /* put framebuffer back to initial state 
+       */
+      (*dpy->driver->haltFBDev)( &dpy->driverContext );
+      RestoreFBDev(dpy);
+      CloseFBDev(dpy);
+   }
+
+   dlclose(dpy->dlHandle);
+   free(dpy);
+}
+
+
+/**
+ * \brief Window creation.
+ *
+ * \param display a display handle, as returned by XOpenDisplay().
+ * \param parent the parent window for the new window. For Mini GLX this should
+ * be 
+ * \code RootWindow(display, 0) \endcode
+ * \param x the window abscissa. For Mini GLX, it should be zero.
+ * \param y the window ordinate. For Mini GLX, it should be zero.
+ * \param width the window width. For Mini GLX, this specifies the desired
+ * screen width such as 1024 or 1280. 
+ * \param height the window height. For Mini GLX, this specifies the desired
+ * screen height such as 768 or 1024.
+ * \param border_width the border width. For Mini GLX, it should be zero.
+ * \param depth the window pixel depth. For Mini GLX, this should be the depth
+ * found in the #XVisualInfo object returned by glXChooseVisual() 
+ * \param class the window class. For Mini GLX this value should be
+ * #InputOutput.
+ * \param visual the visual type. It should be the visual field of the
+ * #XVisualInfo object returned by glXChooseVisual().
+ * \param valuemask which fields of the XSetWindowAttributes() are to be used.
+ * For Mini GLX this is typically the bitmask 
+ * \code CWBackPixel | CWBorderPixel | CWColormap \endcode
+ * \param attributes initial window attributes. The
+ * XSetWindowAttributes::background_pixel, XSetWindowAttributes::border_pixel
+ * and XSetWindowAttributes::colormap fields should be set.
+ *
+ * \return a window handle if it succeeds or zero if it fails.
+ * 
+ * \note For Mini GLX, windows are full-screen; they cover the entire frame
+ * buffer.  Also, Mini GLX imposes a limit of one window. A second window
+ * cannot be created until the first one is destroyed.
+ *
+ * This function creates and initializes a ::MiniGLXWindowRec structure after
+ * ensuring that there is no other window created.  Performs the per-drawable
+ * client-side initialization calling the __DRIscreenRec::createDrawable
+ * method.
+ * 
+ */
+Window
+XCreateWindow( Display *dpy, Window parent, int x, int y,
+               unsigned int width, unsigned int height,
+               unsigned int border_width, int depth, unsigned int class,
+               Visual *visual, unsigned long valuemask,
+               XSetWindowAttributes *attributes )
+{
+   Window win;
+
+   /* ignored */
+   (void) x;
+   (void) y;
+   (void) border_width;
+   (void) depth;
+   (void) class;
+   (void) valuemask;
+   (void) attributes;
+
+   if (!dpy->IsClient) {
+      fprintf(stderr, "Server process may not create windows (currently)\n");
+      return NULL;
+   }
+
+   if (dpy->NumWindows > 0)
+      return NULL;  /* only allow one window */
+
+   assert(dpy->TheWindow == NULL);
+
+   win = malloc(sizeof(struct MiniGLXWindowRec));
+   if (!win)
+      return NULL;
+
+   /* In rotated mode, translate incoming x,y,width,height into
+    * 'normal' coordinates.
+    */
+   if (dpy->rotateMode) {
+      int tmp;
+      tmp = width; width = height; height = tmp;
+      tmp = x; x = y; y = tmp;
+   }
+
+   /* init other per-window fields */
+   win->x = 0;
+   win->y = 0;
+   win->w = width;
+   win->h = height;
+   win->visual = visual;  /* ptr assignment */
+
+   win->bytesPerPixel = dpy->driverContext.cpp;
+   win->rowStride = dpy->driverContext.shared.virtualWidth * win->bytesPerPixel;
+   win->size = win->rowStride * height; 
+   win->frontStart = dpy->driverContext.FBAddress;
+   win->frontBottom = (GLubyte *) win->frontStart + (height-1) * win->rowStride;
+
+   /* This is incorrect: the hardware driver could put the backbuffer
+    * just about anywhere.  These fields, including the above are
+    * hardware dependent & don't really belong here.
+    */
+   if (visual->mode->doubleBufferMode) {
+      win->backStart = (GLubyte *) win->frontStart +
+        win->rowStride * dpy->driverContext.shared.virtualHeight;
+      win->backBottom = (GLubyte *) win->backStart
+        + (height - 1) * win->rowStride;
+      win->curBottom = win->backBottom;
+   }
+   else {
+      /* single buffered */
+      win->backStart = NULL;
+      win->backBottom = NULL;
+      win->curBottom = win->frontBottom;
+   }
+
+   win->driDrawable = dpy->driScreen->createDrawable(dpy->driScreen, 
+                                                    width, height, 
+                                                    dpy->clientID, visual->mode);
+
+   if (!win->driDrawable) {
+      fprintf(stderr, "%s: dri.createDrawable failed\n", __FUNCTION__);
+      free(win);
+      return NULL;
+   }
+
+   dpy->NumWindows++;
+   dpy->TheWindow = win;
+
+   return win; 
+}
+
+
+/**
+ * \brief Destroy window.
+ *
+ * \param display display handle.
+ * \param w window handle.
+ *
+ * This function calls XUnmapWindow() and frees window \p w.
+ * 
+ * In case of destroying the current buffer first unbinds the GLX context
+ * by calling glXMakeCurrent() with no drawable.
+ */
+void
+XDestroyWindow( Display *display, Window win )
+{
+   if (display && display->IsClient && win) {
+      /* check if destroying the current buffer */
+      Window curDraw = glXGetCurrentDrawable();
+      if (win == curDraw) {
+         glXMakeCurrent( display, NULL, NULL);
+      }
+
+      XUnmapWindow( display, win );
+
+      /* Destroy the drawable. */
+      (*win->driDrawable->destroyDrawable)(win->driDrawable);
+      free(win);
+      
+      /* unlink window from display */
+      display->NumWindows--;
+      assert(display->NumWindows == 0);
+      display->TheWindow = NULL;
+   }
+}
+
+
+
+
+/**
+ * \brief Create color map structure.
+ *
+ * \param dpy the display handle as returned by XOpenDisplay().
+ * \param w the window on whose screen you want to create a color map. This
+ * parameter is ignored by Mini GLX but should be the value returned by the
+ * \code RootWindow(display, 0) \endcode macro.
+ * \param visual a visual type supported on the screen. This parameter is
+ * ignored by Mini GLX but should be the XVisualInfo::visual returned by
+ * glXChooseVisual().
+ * \param alloc the color map entries to be allocated. This parameter is ignored
+ * by Mini GLX but should be set to #AllocNone.
+ *
+ * \return the color map.
+ * 
+ * This function is only provided to ease porting.  Practically a no-op -
+ * returns a pointer to a dynamically allocated chunk of memory (one byte).
+ */
+Colormap
+XCreateColormap( Display *dpy, Window w, Visual *visual, int alloc )
+{
+   (void) dpy;
+   (void) w;
+   (void) visual;
+   (void) alloc;
+   return (Colormap) malloc(1);
+}
+
+
+/**
+ * \brief Destroy color map structure.
+ *
+ * \param display The display handle as returned by XOpenDisplay().
+ * \param colormap the color map to destroy.
+ *
+ * This function is only provided to ease porting.  Practically a no-op. 
+ *
+ * Frees the memory pointed by \p colormap.
+ */
+void
+XFreeColormap( Display *display, Colormap colormap )
+{
+   (void) display;
+   (void) colormap;
+   free(colormap);
+}
+
+
+/**
+ * \brief Free client data.
+ *
+ * \param data the data that is to be freed.
+ *
+ * Frees the memory pointed by \p data.
+ */
+void
+XFree( void *data )
+{
+   free(data);
+}
+
+
+/**
+ * \brief Query available visuals.
+ *
+ * \param dpy the display handle, as returned by XOpenDisplay().
+ * \param vinfo_mask a bitmask indicating which fields of the \p vinfo_template
+ * are to be matched.  The value must be \c VisualScreenMask.
+ * \param vinfo_template a template whose fields indicate which visual
+ * attributes must be matched by the results.  The XVisualInfo::screen field of
+ * this structure must be zero.
+ * \param nitens_return will hold the number of visuals returned.
+ *
+ * \return the address of an array of all available visuals.
+ * 
+ * An example of using XGetVisualInfo() to get all available visuals follows:
+ * 
+ * \code
+ * XVisualInfo vinfo_template, *results;
+ * int nitens_return;
+ * Display *dpy = XOpenDisplay(NULL);
+ * vinfo_template.screen = 0;
+ * results = XGetVisualInfo(dpy, VisualScreenMask, &vinfo_template, &nitens_return);
+ * \endcode
+ * 
+ * Returns the list of all ::XVisualInfo available, one per
+ * ::__GLcontextMode stored in MiniGLXDisplayRec::modes.
+ */
+XVisualInfo *
+XGetVisualInfo( Display *dpy, long vinfo_mask, XVisualInfo *vinfo_template, int *nitens_return )
+{
+   XVisualInfo *results;
+   Visual *visResults;
+   int i, n;
+
+   ASSERT(vinfo_mask == VisualScreenMask);
+   ASSERT(vinfo_template.screen == 0);
+
+   n = dpy->numModes;
+   results = (XVisualInfo *)calloc(1, n * sizeof(XVisualInfo));
+   if (!results) {
+      *nitens_return = 0;
+      return NULL;
+   }
+
+   visResults = (Visual *)calloc(1, n * sizeof(Visual));
+   if (!results) {
+      free(results);
+      *nitens_return = 0;
+      return NULL;
+   }
+
+   for (i = 0; i < n; i++) {
+      visResults[i].mode = dpy->modes + i;
+      visResults[i].visInfo = results + i;
+      visResults[i].dpy = dpy;
+
+      if (dpy->driverContext.bpp == 32)
+        visResults[i].pixelFormat = PF_B8G8R8A8; /* XXX: FIX ME */
+      else
+        visResults[i].pixelFormat = PF_B5G6R5; /* XXX: FIX ME */
+
+      results[i].visual = visResults + i;
+      results[i].visualid = i;
+      results[i].class = TrueColor;
+      results[i].depth = dpy->modes[i].redBits +
+                         dpy->modes[i].redBits +
+                         dpy->modes[i].redBits +
+                         dpy->modes[i].redBits;
+      results[i].bits_per_rgb = dpy->driverContext.bpp;
+   }
+   *nitens_return = n;
+   return results;
+}
+
+
+/**
+ * \brief Return a visual that matches specified attributes.
+ *
+ * \param dpy the display handle, as returned by XOpenDisplay().
+ * \param screen the screen number. It is currently ignored by Mini GLX and
+ * should be zero.
+ * \param attribList a list of GLX attributes which describe the desired pixel
+ * format. It is terminated by the token \c None. 
+ *
+ * The attributes are as follows:
+ * \arg GLX_USE_GL:
+ * This attribute should always be present in order to maintain compatibility
+ * with GLX.
+ * \arg GLX_RGBA:
+ * If present, only RGBA pixel formats will be considered. Otherwise, only
+ * color index formats are considered.
+ * \arg GLX_DOUBLEBUFFER:
+ * if present, only double-buffered pixel formats will be chosen.
+ * \arg GLX_RED_SIZE \e n:
+ * Must be followed by a non-negative integer indicating the minimum number of
+ * bits per red pixel component that is acceptable.
+ * \arg GLX_GREEN_SIZE \e n:
+ * Must be followed by a non-negative integer indicating the minimum number of
+ * bits per green pixel component that is acceptable.
+ * \arg GLX_BLUE_SIZE \e n:
+ * Must be followed by a non-negative integer indicating the minimum number of
+ * bits per blue pixel component that is acceptable.
+ * \arg GLX_ALPHA_SIZE \e n:
+ * Must be followed by a non-negative integer indicating the minimum number of
+ * bits per alpha pixel component that is acceptable.
+ * \arg GLX_STENCIL_SIZE \e n:
+ * Must be followed by a non-negative integer indicating the minimum number of
+ * bits per stencil value that is acceptable.
+ * \arg GLX_DEPTH_SIZE \e n:
+ * Must be followed by a non-negative integer indicating the minimum number of
+ * bits per depth component that is acceptable.
+ * \arg None:
+ * This token is used to terminate the attribute list.
+ *
+ * \return a pointer to an #XVisualInfo object which most closely matches the
+ * requirements of the attribute list. If there is no visual which matches the
+ * request, \c NULL will be returned.
+ *
+ * \note Visuals with accumulation buffers are not available.
+ *
+ * This function searches the list of available visual configurations in
+ * MiniGLXDisplayRec::configs for a configuration which best matches the GLX
+ * attribute list parameter.  A new ::XVisualInfo object is created which
+ * describes the visual configuration.  The match criteria is described in the
+ * specification.
+ */
+XVisualInfo*
+glXChooseVisual( Display *dpy, int screen, int *attribList )
+{
+   Visual *vis;
+   XVisualInfo *visInfo;
+   const int *attrib;
+   GLboolean rgbFlag = GL_FALSE, dbFlag = GL_FALSE, stereoFlag = GL_FALSE;
+   GLint redBits = 0, greenBits = 0, blueBits = 0, alphaBits = 0;
+   GLint indexBits = 0, depthBits = 0, stencilBits = 0;
+   GLint numSamples = 0;
+   int i;
+
+   /*
+    * XXX in the future, <screen> might be interpreted as a VT
+    */
+   ASSERT(dpy);
+   ASSERT(screen == 0);
+
+   vis = (Visual *)calloc(1, sizeof(Visual));
+   if (!vis)
+      return NULL;
+
+   visInfo = (XVisualInfo *)malloc(sizeof(XVisualInfo));
+   if (!visInfo) {
+      free(vis);
+      return NULL;
+   }
+
+   visInfo->visual = vis;
+   vis->visInfo = visInfo;
+   vis->dpy = dpy;
+
+   /* parse the attribute list */
+   for (attrib = attribList; attrib && *attrib != None; attrib++) {
+      switch (attrib[0]) {
+      case GLX_DOUBLEBUFFER:
+         dbFlag = GL_TRUE;
+         break;
+      case GLX_RGBA:
+         rgbFlag = GL_TRUE;
+         break;
+      case GLX_RED_SIZE:
+         redBits = attrib[1];
+         attrib++;
+         break;
+      case GLX_GREEN_SIZE:
+         redBits = attrib[1];
+         attrib++;
+         break;
+      case GLX_BLUE_SIZE:
+         redBits = attrib[1];
+         attrib++;
+         break;
+      case GLX_ALPHA_SIZE:
+         redBits = attrib[1];
+         attrib++;
+         break;
+      case GLX_STENCIL_SIZE:
+         stencilBits = attrib[1];
+         attrib++;
+         break;
+      case GLX_DEPTH_SIZE:
+         depthBits = attrib[1];
+         attrib++;
+         break;
+#if 0
+      case GLX_ACCUM_RED_SIZE:
+         accumRedBits = attrib[1];
+         attrib++;
+         break;
+      case GLX_ACCUM_GREEN_SIZE:
+         accumGreenBits = attrib[1];
+         attrib++;
+         break;
+      case GLX_ACCUM_BLUE_SIZE:
+         accumBlueBits = attrib[1];
+         attrib++;
+         break;
+      case GLX_ACCUM_ALPHA_SIZE:
+         accumAlphaBits = attrib[1];
+         attrib++;
+         break;
+      case GLX_LEVEL:
+         /* ignored for now */
+         break;
+#endif
+      default:
+         /* unexpected token */
+         fprintf(stderr, "unexpected token in glXChooseVisual attrib list\n");
+         free(vis);
+         free(visInfo);
+         return NULL;
+      }
+   }
+
+   /* search screen configs for suitable visual */
+   (void) numSamples;
+   (void) indexBits;
+   (void) redBits;
+   (void) greenBits;
+   (void) blueBits;
+   (void) alphaBits;
+   (void) stereoFlag;
+   for (i = 0; i < dpy->numModes; i++) {
+      const __GLcontextModes *mode = dpy->modes + i;
+      if (mode->rgbMode == rgbFlag &&
+          mode->redBits >= redBits &&
+          mode->greenBits >= greenBits &&
+          mode->blueBits >= blueBits &&
+          mode->alphaBits >= alphaBits &&
+          mode->depthBits >= depthBits &&
+          mode->stencilBits >= stencilBits) {
+         /* found it */
+         visInfo->visualid = i;
+         vis->mode = mode;
+         break;
+      }          
+   }
+   if (!vis->mode)
+       return NULL;
+
+   /* compute depth and bpp */
+   if (rgbFlag) {
+      /* XXX maybe support depth 16 someday */
+      visInfo->class = TrueColor;
+      visInfo->depth = dpy->driverContext.bpp;
+      visInfo->bits_per_rgb = dpy->driverContext.bpp;
+      if (dpy->driverContext.bpp == 32)
+        vis->pixelFormat = PF_B8G8R8A8;
+      else
+        vis->pixelFormat = PF_B5G6R5;
+   }
+   else {
+      /* color index mode */
+      visInfo->class = PseudoColor;
+      visInfo->depth = 8;
+      visInfo->bits_per_rgb = 8;  /* bits/pixel */
+      vis->pixelFormat = PF_CI8;
+   }
+
+   return visInfo;
+}
+
+
+/**
+ * \brief Return information about GLX visuals.
+ *
+ * \param dpy the display handle, as returned by XOpenDisplay().
+ * \param vis the visual to be queried, as returned by glXChooseVisual().
+ * \param attrib the visual attribute to be returned.
+ * \param value pointer to an integer in which the result of the query will be
+ * stored.
+ * 
+ * \return zero if no error occurs, \c GLX_INVALID_ATTRIBUTE if the attribute
+ * parameter is invalid, or \c GLX_BAD_VISUAL if the \p vis parameter is
+ * invalid.
+ *
+ * Returns the appropriate attribute of ::__GLXvisualConfig pointed by
+ * MiniGLXVisualRec::glxConfig of XVisualInfo::visual.
+ *
+ * \sa data types.
+ */
+int
+glXGetConfig( Display *dpy, XVisualInfo *vis, int attrib, int *value )
+{
+   const __GLcontextModes *mode = vis->visual->mode;
+   if (!mode) {
+      *value = 0;
+      return GLX_BAD_VISUAL;
+   }
+
+   switch (attrib) {
+   case GLX_USE_GL:
+      *value = True;
+      return 0;
+   case GLX_RGBA:
+      *value = mode->rgbMode;
+      return 0;
+   case GLX_DOUBLEBUFFER:
+      *value = mode->doubleBufferMode;
+      return 0;
+   case GLX_RED_SIZE:
+      *value = mode->redBits;
+      return 0;
+   case GLX_GREEN_SIZE:
+      *value = mode->greenBits;
+      return 0;
+   case GLX_BLUE_SIZE:
+      *value = mode->blueBits;
+      return 0;
+   case GLX_ALPHA_SIZE:
+      *value = mode->alphaBits;
+      return 0;
+   case GLX_DEPTH_SIZE:
+      *value = mode->depthBits;
+      return 0;
+   case GLX_STENCIL_SIZE:
+      *value = mode->stencilBits;
+      return 0;
+   default:
+      *value = 0;
+      return GLX_BAD_ATTRIBUTE;
+   }
+   return 0;
+}
+
+
+/**
+ * \brief Create a new GLX rendering context.
+ *
+ * \param dpy the display handle, as returned by XOpenDisplay().
+ * \param vis the visual that defines the frame buffer resources available to
+ * the rendering context, as returned by glXChooseVisual().
+ * \param shareList If non-zero, texture objects and display lists are shared
+ * with the named rendering context. If zero, texture objects and display lists
+ * will (initially) be private to this context. They may be shared when a
+ * subsequent context is created.
+ * \param direct whether direct or indirect rendering is desired. For Mini GLX
+ * this value is ignored but it should be set to \c True.
+ *
+ * \return a ::GLXContext handle if it succeeds or zero if it fails due to
+ * invalid parameter or insufficient resources.
+ *
+ * This function creates and initializes a ::MiniGLXContextRec structure and
+ * calls the __DRIscreenRec::createContext method to initialize the client
+ * private data.
+ */ 
+GLXContext
+glXCreateContext( Display *dpy, XVisualInfo *vis,
+                        GLXContext shareList, Bool direct )
+{
+   GLXContext ctx;
+   void *sharePriv;
+
+   ASSERT(vis);
+
+   ctx = (struct MiniGLXContextRec *)calloc(1, sizeof(struct MiniGLXContextRec));
+   if (!ctx)
+      return NULL;
+
+   ctx->vid = vis->visualid;
+   if (shareList)
+      sharePriv = shareList->driContext;
+   else
+      sharePriv = NULL;
+   
+   ctx->driContext = (*dpy->driScreen->createContext)(dpy->driScreen, 
+                                                     vis->visual->mode,
+                                                     sharePriv);
+   if (!ctx->driContext) {
+      free(ctx);
+      return NULL;
+   }
+
+   return ctx;
+}
+
+
+/**
+ * \brief Destroy a GLX context.
+ *
+ * \param dpy the display handle, as returned by XOpenDisplay().
+ * \param ctx the GLX context to be destroyed.
+ * 
+ * This function frees the \p ctx parameter after unbinding the current context
+ * by calling the __DRIcontextRec::bindContext method with zeros and calling
+ * the __DRIcontextRec::destroyContext method.
+ */
+void
+glXDestroyContext( Display *dpy, GLXContext ctx )
+{
+   GLXContext glxctx = glXGetCurrentContext();
+
+   if (ctx) {
+      if (glxctx == ctx) {
+         /* destroying current context */
+         (*ctx->driContext->bindContext)(dpy->driScreen, 0, 0);
+        CurrentContext = 0;
+      }
+      (*ctx->driContext->destroyContext)(ctx->driContext);
+      free(ctx);
+   }
+}
+
+
+/**
+ * \brief Bind a GLX context to a window or a pixmap.
+ *
+ * \param dpy the display handle, as returned by XOpenDisplay().
+ * \param drawable the window or drawable to bind to the rendering context.
+ * This should be the value returned by XCreateWindow().
+ * \param ctx the GLX context to be destroyed.
+ *
+ * \return \c True if it succeeds, \c False otherwise to indicate an invalid
+ * display, window or context parameter.
+ *
+ * The current rendering context may be unbound by calling glXMakeCurrent()
+ * with the window and context parameters set to zero.
+ * 
+ * An application may create any number of rendering contexts and bind them as
+ * needed. Note that binding a rendering context is generally not a
+ * light-weight operation.  Most simple OpenGL applications create only one
+ * rendering context.
+ *
+ * This function first unbinds any old context via
+ * __DRIcontextRec::unbindContext and binds the new one via
+ * __DRIcontextRec::bindContext.
+ *
+ * If \p drawable is zero it unbinds the GLX context by calling
+ * __DRIcontextRec::bindContext with zeros.
+ */
+Bool
+glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx)
+{
+   if (dpy && drawable && ctx) {
+      GLXContext oldContext = glXGetCurrentContext();
+      GLXDrawable oldDrawable = glXGetCurrentDrawable();
+      /* unbind old */
+      if (oldContext) {
+         (*oldContext->driContext->unbindContext)(oldDrawable->driDrawable, oldContext->driContext);
+      }
+      /* bind new */
+      CurrentContext = ctx;
+      (*ctx->driContext->bindContext)(dpy->driScreen, drawable->driDrawable, ctx->driContext);
+      ctx->drawBuffer = drawable;
+      ctx->curBuffer = drawable;
+   }
+   else if (ctx && dpy) {
+      /* unbind */
+      (*ctx->driContext->bindContext)(dpy->driScreen, 0, 0);
+   }
+   else if (dpy) {
+      CurrentContext = 0;      /* kw:  this seems to be intended??? */
+   }
+
+   return True;
+}
+
+
+/**
+ * \brief Exchange front and back buffers.
+ * 
+ * \param dpy the display handle, as returned by XOpenDisplay().
+ * \param drawable the drawable whose buffers are to be swapped.
+ * 
+ * Any pending rendering commands will be completed before the buffer swap
+ * takes place.
+ * 
+ * Calling glXSwapBuffers() on a window which is single-buffered has no effect.
+ *
+ * This function just calls the __DRIdrawableRec::swapBuffers method to do the
+ * work.
+ */
+void
+glXSwapBuffers( Display *dpy, GLXDrawable drawable )
+{
+   if (!dpy || !drawable)
+      return;
+
+   (*drawable->driDrawable->swapBuffers)(drawable->driDrawable);
+}
+
+
+/**
+ * \brief Return the current context
+ *
+ * \return the current context, as specified by glXMakeCurrent(), or zero if no
+ * context is currently bound.
+ *
+ * \sa glXCreateContext(), glXMakeCurrent()
+ *
+ * Returns the value of the ::CurrentContext global variable.
+ */
+GLXContext
+glXGetCurrentContext( void )
+{
+   return CurrentContext;
+}
+
+
+/**
+ * \brief Return the current drawable.
+ *
+ * \return the current drawable, as specified by glXMakeCurrent(), or zero if
+ * no drawable is currently bound.
+ *
+ * This function gets the current context via glXGetCurrentContext() and
+ * returns the MiniGLXContextRec::drawBuffer attribute.
+ */
+GLXDrawable
+glXGetCurrentDrawable( void )
+{
+   GLXContext glxctx = glXGetCurrentContext();
+   if (glxctx)
+      return glxctx->drawBuffer;
+   else
+      return NULL;
+}
+
+
+/**
+ * \brief Query function address.
+ *
+ * The glXGetProcAddress() function will return the address of any available
+ * OpenGL or Mini GLX function.
+ * 
+ * \param procName name of the function to be returned.
+ *
+ * \return If \p procName is a valid function name, a pointer to that function
+ * will be returned.  Otherwise, \c NULL will be returned.
+ *
+ * The purpose of glXGetProcAddress() is to facilitate using future extensions
+ * to OpenGL or Mini GLX. If a future version of the library adds new extension
+ * functions they'll be accessible via glXGetProcAddress(). The alternative is
+ * to hard-code calls to the new functions in the application but doing so will
+ * prevent linking the application with older versions of the library.
+ * 
+ * Returns the function address by looking up its name in a static (name,
+ * address) pair list.
+ */
+const void *
+glXGetProcAddress( const GLubyte *procName )
+{
+   struct name_address {
+      const char *name;
+      const void *func;
+   };
+   static const struct name_address functions[] = {
+      { "glXChooseVisual", (void *) glXChooseVisual },
+      { "glXCreateContext", (void *) glXCreateContext },
+      { "glXDestroyContext", (void *) glXDestroyContext },
+      { "glXMakeCurrent", (void *) glXMakeCurrent },
+      { "glXSwapBuffers", (void *) glXSwapBuffers },
+      { "glXGetCurrentContext", (void *) glXGetCurrentContext },
+      { "glXGetCurrentDrawable", (void *) glXGetCurrentDrawable },
+      { "glXGetProcAddress", (void *) glXGetProcAddress },
+      { "XOpenDisplay", (void *) XOpenDisplay },
+      { "XCloseDisplay", (void *) XCloseDisplay },
+      { "XCreateWindow", (void *) XCreateWindow },
+      { "XDestroyWindow", (void *) XDestroyWindow },
+      { "XMapWindow", (void *) XMapWindow },
+      { "XCreateColormap", (void *) XCreateColormap },
+      { "XFreeColormap", (void *) XFreeColormap },
+      { "XFree", (void *) XFree },
+      { "XGetVisualinfo", (void *) XGetVisualInfo },
+      { NULL, NULL }
+   };
+   const struct name_address *entry;
+   for (entry = functions; entry->name; entry++) {
+      if (strcmp(entry->name, (const char *) procName) == 0) {
+         return entry->func;
+      }
+   }
+   return _glapi_get_proc_address((const char *) procName);
+}
+
+
+/**
+ * \brief Query the Mini GLX version.
+ *
+ * \param dpy the display handle. It is currently ignored, but should be the
+ * value returned by XOpenDisplay().
+ * \param major receives the major version number of Mini GLX.
+ * \param minor receives the minor version number of Mini GLX.
+ *
+ * \return \c True if the function succeeds, \c False if the function fails due
+ * to invalid parameters.
+ *
+ * \sa #MINI_GLX_VERSION_1_0.
+ * 
+ * Returns the hard-coded Mini GLX version.
+ */
+Bool
+glXQueryVersion( Display *dpy, int *major, int *minor )
+{
+   (void) dpy;
+   *major = 1;
+   *minor = 0;
+   return True;
+}
+
+
+/*@}*/
diff --git a/src/glx/mini/miniglxP.h b/src/glx/mini/miniglxP.h
new file mode 100644 (file)
index 0000000..a32429a
--- /dev/null
@@ -0,0 +1,194 @@
+/**
+ * \file miniglxP.h
+ * \brief Define replacements for some X data types and define the DRI-related
+ * data structures.
+ *
+ * \note Cut down version of glxclient.h.
+ *
+ */
+
+#ifndef _mini_GLX_client_h_
+#define _mini_GLX_client_h_
+
+#include <signal.h>
+#include <linux/fb.h>
+
+#include <GL/miniglx.h>
+#include "glheader.h"
+#include "mtypes.h"
+
+#include "driver.h"
+#include "dri.h"
+
+/**
+ * \brief Supported pixel formats.
+ */
+enum PixelFormat {
+   PF_B8G8R8,    /**< \brief 24-bit BGR */
+   PF_B8G8R8A8,  /**< \brief 32-bit BGRA */
+   PF_B5G6R5,    /**< \brief 16-bit BGR */
+   PF_B5G5R5,    /**< \brief 15-bit BGR */
+   PF_CI8        /**< \brief 8-bit color index */
+};
+
+/**
+ * \brief X Visual type.
+ *
+ * \sa ::Visual, \ref datatypes.
+ */
+struct MiniGLXVisualRec {
+   /** \brief GLX visual information */
+   const __GLcontextModes *mode;
+
+   /** \brief pointer back to corresponding ::XVisualInfo */
+   XVisualInfo *visInfo;               
+
+   /** \brief display handle */
+   Display *dpy;
+
+   /** \brief pixel format */
+   enum PixelFormat pixelFormat;       
+};
+
+
+
+/**
+ * \brief X Window type.
+ *
+ * \sa ::Window, \ref datatypes.
+ */
+struct MiniGLXWindowRec {
+   Visual *visual;
+                                   /** \brief position (always 0,0) */
+   int x, y;
+                                   /** \brief size */
+   unsigned int w, h;
+   void *frontStart;               /**< \brief start of front color buffer */
+   void *backStart;                /**< \brief start of back color buffer */
+   size_t size;                    /**< \brief color buffer size, in bytes */
+   GLuint bytesPerPixel;
+   GLuint rowStride;               /**< \brief in bytes */
+   GLubyte *frontBottom;           /**< \brief pointer to last row */
+   GLubyte *backBottom;            /**< \brief pointer to last row */
+   GLubyte *curBottom;             /**<  = frontBottom or backBottom */
+   __DRIdrawable *driDrawable;
+   GLuint ismapped;
+};
+
+
+/**
+ * \brief GLXContext type.
+ *
+ * \sa ::GLXContext, \ref datatypes.
+ */
+struct MiniGLXContextRec {
+   Window drawBuffer;       /**< \brief drawing buffer */
+   Window curBuffer;        /**< \brief current buffer */
+   VisualID vid;            /**< \brief visual ID */
+   __DRIcontext *driContext; /**< \brief context dependent methods */
+};
+
+#define MINIGLX_BUF_SIZE 512
+#define MINIGLX_MAX_SERVER_FDS 10
+#define MINIGLX_MAX_CLIENT_FDS 1
+#define MINIGLX_EVENT_QUEUE_SZ 16
+#define MINIGLX_EVENT_QUEUE_MASK (MINIGLX_EVENT_QUEUE_SZ-1)
+
+/**
+ * A connection to/from the server
+ *
+ * All information is to/from the server is buffered and then dispatched by 
+ * __miniglx_Select() to avoid blocking the server.
+ */
+struct MiniGLXConnection {
+   int fd;                             /**< \brief file descriptor */
+   char readbuf[MINIGLX_BUF_SIZE];     /**< \brief read buffer */
+   char writebuf[MINIGLX_BUF_SIZE];    /**< \brief write buffer */
+   int readbuf_count;                  /**< \brief count of bytes waiting to be read */
+   int writebuf_count;                 /**< \brief count of bytes waiting to be written */
+};
+
+
+/**
+ * \brief X Display type
+ *
+ * \sa ::Display, \ref datatypes.
+ */
+struct MiniGLXDisplayRec {
+   /** \brief fixed framebuffer screen info */
+   struct fb_fix_screeninfo FixedInfo; 
+   /** \brief original and current variable framebuffer screen info */
+   struct fb_var_screeninfo OrigVarInfo, VarInfo;
+   struct sigaction OrigSigUsr1;
+   struct sigaction OrigSigUsr2;
+   int OriginalVT;
+   int ConsoleFD;        /**< \brief console TTY device file descriptor */
+   int FrameBufferFD;    /**< \brief framebuffer device file descriptor */
+   int NumWindows;       /**< \brief number of open windows */
+   Window TheWindow;     /**< \brief open window - only allow one window for now */
+   int rotateMode;
+
+
+   volatile int vtSignalFlag;
+   volatile int haveVT;        /**< \brief whether the VT is hold */
+   int hwActive;       /**< \brief whether the hardware is active -- mimics
+                         the variations of MiniGLXDisplayRec::haveVT */
+
+
+   int IsClient;       /**< \brief whether it's a client or the server */
+   int clientID;
+   int nrFds;          /**< \brief number of connections (usually just one for the clients) */
+   struct MiniGLXConnection *fd;       /**< \brief connections */
+
+   struct {
+      int nr, head, tail;
+      XEvent queue[MINIGLX_EVENT_QUEUE_SZ];
+   } eventqueue;
+   
+   /**
+    * \name Visuals 
+    *
+    * Visuals (configs) in this screen.
+    */
+   /*@{*/
+   int numModes;               /**< \brief Number of modes. */
+   const __GLcontextModes *modes;      /**< \brief Modes list pointer. */
+   /*@}*/
+    
+   /**
+   * \name From __GLXdisplayPrivate
+   */
+   /*@{*/
+   driCreateScreenFunc *createScreen; /**< \brief \e __driCreateScreen hook */
+   __DRIscreen *driScreen;         /**< \brief Screen dependent methods */
+   void *dlHandle;                /**<
+                                  * \brief handle to the client dynamic
+                                  * library 
+                                  */
+   /*@}*/
+
+   /**
+    * \brief Mini GLX specific driver hooks
+    */
+   struct DRIDriverRec *driver;
+   struct DRIDriverContextRec driverContext;
+
+   /**
+    * \name Configuration details
+    *
+    * They are read from a configuration file by __read_config_file().
+    */
+   /*@{*/
+   const char *fbdevDevice;
+   const char *clientDriverName;
+   /*@}*/
+};
+
+extern __DRIscreen *__glXFindDRIScreen(Display *dpy, int scrn);
+
+extern Bool __glXWindowExists(Display *dpy, GLXDrawable draw);
+
+extern int __miniglx_open_connections( Display *dpy );
+extern void __miniglx_close_connections( Display *dpy );
+
+#endif /* !_mini_GLX_client_h_ */
diff --git a/src/glx/mini/miniglx_events.c b/src/glx/mini/miniglx_events.c
new file mode 100644 (file)
index 0000000..d367dba
--- /dev/null
@@ -0,0 +1,962 @@
+/**
+ * \file miniglx_events.c
+ * \brief Mini GLX client/server communication functions.
+ * \author Keith Whitwell
+ *
+ * The Mini GLX interface is a subset of the GLX interface, plus a
+ * minimal set of Xlib functions.  This file adds interfaces to
+ * arbitrate a single cliprect between multiple direct rendering
+ * clients.
+ *
+ * A fairly complete client/server non-blocking communication
+ * mechanism.  Probably overkill given that none of our messages
+ * currently exceed 1 byte in length and take place over the
+ * relatively benign channel provided by a Unix domain socket.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  5.0
+ *
+ * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* $Id: miniglx_events.c,v 1.1 2003/08/22 20:11:43 brianp Exp $ */
+
+
+#include <assert.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+
+#include <linux/kd.h>
+#include <linux/vt.h>
+
+#include "miniglxP.h"
+
+#include "xf86drm.h"
+#include "sarea.h"
+
+#define MINIGLX_FIFO_NAME "/tmp/miniglx.fifo"
+
+/** Character messages. */
+enum msgs {
+   _CanIHaveFocus,
+   _IDontWantFocus,
+   _YouveGotFocus,
+   _YouveLostFocus,
+   _RepaintPlease,
+};
+
+/**
+ * \brief Allocate an XEvent structure on the event queue.
+ *
+ * \param dpy the display handle.
+ *
+ * \return Pointer to the queued event structure or NULL on failure.
+ * 
+ * \internal 
+ * If there is space on the XEvent queue, return a pointer
+ * to the next free event and increment the eventqueue tail value.
+ * Otherwise return null.
+ */
+static XEvent *queue_event( Display *dpy )
+{
+   int incr = (dpy->eventqueue.tail + 1) & MINIGLX_EVENT_QUEUE_MASK;
+   if (incr == dpy->eventqueue.head) {
+      return 0;
+   }
+   else {
+      XEvent *ev = &dpy->eventqueue.queue[dpy->eventqueue.tail];
+      dpy->eventqueue.tail = incr;
+      return ev;
+   }
+}
+
+/**
+ * \brief Dequeue an XEvent and copy it into provided storage.
+ *
+ * \param dpy the display handle.
+ * \param event_return pointer to copy the queued event to.
+ *
+ * \return True or False depending on success.
+ * 
+ * \internal 
+ * If there is a queued XEvent on the queue, copy it to the provided
+ * pointer and increment the eventqueue head value.  Otherwise return
+ * null.
+ */
+static int dequeue_event( Display *dpy, XEvent *event_return )
+{
+   if (dpy->eventqueue.tail == dpy->eventqueue.head) {
+      return False;
+   }
+   else {
+      *event_return = dpy->eventqueue.queue[dpy->eventqueue.head];      
+      dpy->eventqueue.head += 1;
+      dpy->eventqueue.head &= MINIGLX_EVENT_QUEUE_MASK;
+      return True;
+   }
+}
+
+/**
+ * \brief Shutdown a socket connection.
+ *
+ * \param dpy the display handle.
+ * \param i the index in dpy->fd of the socket connection.
+ *
+ * \internal 
+ * Shutdown and close the file descriptor.  If this is the special
+ * connection in fd[0], issue an error message and exit - there's been
+ * some sort of failure somewhere.  Otherwise, let the application
+ * know about whats happened by issuing a DestroyNotify event.
+ */
+static void shut_fd( Display *dpy, int i )
+{
+   if (dpy->fd[i].fd < 0) 
+      return;
+
+   shutdown (dpy->fd[i].fd, SHUT_RDWR);
+   close (dpy->fd[i].fd);
+   dpy->fd[i].fd = -1;
+   dpy->fd[i].readbuf_count = 0;
+   dpy->fd[i].writebuf_count = 0;
+
+   if (i == 0) {
+      fprintf(stderr, "server connection lost\n");
+      exit(1);
+   }
+   else {
+      /* Pass this to the application as a DestroyNotify event.
+       */
+      XEvent *er = queue_event(dpy);
+      if (!er) return;
+      er->xdestroywindow.type = DestroyNotify;
+      er->xdestroywindow.serial = 0;
+      er->xdestroywindow.send_event = 0;
+      er->xdestroywindow.display = dpy;
+      er->xdestroywindow.window = (Window)i;   
+   }
+}
+
+/**
+ * \brief Send a message to a socket connection.
+ *
+ * \param dpy the display handle.
+ * \param i the index in dpy->fd of the socket connection.
+ * \param msg the message to send.
+ * \param sz the size of the message
+ *
+ * \internal 
+ * Copy the message to the write buffer for the nominated connection.
+ * This will be actually sent to that file descriptor from
+ * __miniglx_Select().
+ */
+static int send_msg( Display *dpy, int i,
+                    const void *msg, size_t sz )
+{
+   int cnt = dpy->fd[i].writebuf_count;
+   if (MINIGLX_BUF_SIZE - cnt < sz) {
+      fprintf(stderr, "client %d: writebuf overflow\n", i);
+      return False;
+   }
+   
+   memcpy( dpy->fd[i].writebuf + cnt, msg, sz ); cnt += sz;
+   dpy->fd[i].writebuf_count = cnt;
+   return True;
+}
+
+/**
+ * \brief Send a message to a socket connection.
+ *
+ * \param dpy the display handle.
+ * \param i the index in dpy->fd of the socket connection.
+ * \param msg the message to send.
+ *
+ * \internal 
+ * Use send_msg() to send a one-byte message to a socket.
+ */
+static int send_char_msg( Display *dpy, int i, char msg )
+{
+   return send_msg( dpy, i, &msg, sizeof(char));
+}
+
+
+/**
+ * \brief Block and receive a message from a socket connection.
+ *
+ * \param dpy the display handle.
+ * \param connection the index in dpy->fd of the socket connection.
+ * \param msg storage for the received message.
+ * \param msg_size the number of bytes to read.
+ *
+ * \internal 
+ * Block and read from the connection's file descriptor
+ * until msg_size bytes have been received.  
+ *
+ * Only called from welcome_message_part().
+ */
+static int blocking_read( Display *dpy, int connection, 
+                         char *msg, size_t msg_size )
+{
+   int i, r;
+
+   for (i = 0 ; i < msg_size ; i += r) {
+      r = read(dpy->fd[connection].fd, msg + i, msg_size - i);
+      if (r < 1) {
+        fprintf(stderr, "blocking_read: %d %s\n", r, strerror(errno));
+        shut_fd(dpy,connection);
+        return False;
+      }
+   }
+
+   return True;
+}
+
+/**
+ * \brief Send/receive a part of the welcome message.
+ *
+ * \param dpy the display handle.
+ * \param i the index in dpy->fd of the socket connection.
+ * \param msg storage for the sent/received message.
+ * \param sz the number of bytes to write/read.
+ *
+ * \return True on success, or False on failure.
+ *
+ * This function is called by welcome_message_part(), to either send or receive
+ * (via blocking_read()) part of the welcome message, according to whether
+ * Display::IsClient is set.
+ *
+ * Each part of the welcome message on the wire consists of a count and then the
+ * actual message data with that number of bytes.
+ */
+static int welcome_message_part( Display *dpy, int i, void **msg, int sz )
+{
+   if (dpy->IsClient) {
+      int sz;
+      if (!blocking_read( dpy, i, (char *)&sz, sizeof(sz))) return False;
+      if (!*msg) *msg = malloc(sz);
+      if (!*msg) return False;
+      if (!blocking_read( dpy, i, *msg, sz )) return False;
+   }
+   else {
+      if (!send_msg( dpy, i, &sz, sizeof(sz))) return False;
+      if (!send_msg( dpy, i, *msg, sz )) return False;
+   }
+
+   return True;
+}
+
+/**
+ * \brief Send/receive the welcome message.
+ *
+ * \param dpy the display handle.
+ * \param i the index in dpy->fd of the socket connection.
+ *
+ * \return True on success, or False on failure.
+ *
+ * Using welcome_message_part(), sends/receives the client ID, the client
+ * configuration details in DRIDriverContext::shared, and the driver private
+ * message in DRIDriverContext::driverClientMsg.
+ */
+static int welcome_message( Display *dpy, int i )
+{
+   void *tmp = &dpy->driverContext.shared;
+   int *clientid = dpy->IsClient ? &dpy->clientID : &i;
+   
+   if (!welcome_message_part( dpy, i, (void **)&clientid, sizeof(*clientid)))
+      return False;
+
+   if (!welcome_message_part( dpy, i, &tmp, sizeof(dpy->driverContext.shared)))
+      return False;
+      
+   if (!welcome_message_part( dpy, i,
+                              (void **)&dpy->driverContext.driverClientMsg, 
+                             dpy->driverContext.driverClientMsgSize ))
+      return False;
+
+   return True;
+}
+
+
+/**
+ * \brief Handle a new client connection.
+ *
+ * \param dpy the display handle.
+ *
+ * \return True on success or False on failure.
+ * 
+ * Accepts the connection, sets it in non-blocking operation, and finds a free
+ * slot in Display::fd for it.
+ */
+static int handle_new_client( Display *dpy )
+{
+   struct sockaddr_un client_address;
+   unsigned int l = sizeof(client_address);
+   int r, i;
+
+   r = accept(dpy->fd[0].fd, (struct sockaddr *) &client_address, &l);
+   if (r < 0) {
+      perror ("accept()");
+      shut_fd(dpy,0);
+      return False;
+   } 
+
+   if (fcntl(r, F_SETFL, O_NONBLOCK) != 0) {
+      perror("fcntl");
+      close(r);
+      return False;
+   }
+
+
+   /* Some rough & ready adaption of the XEvent semantics.
+    */ 
+   for (i = 1 ; i < dpy->nrFds ; i++) {
+      if (dpy->fd[i].fd < 0) {
+        XEvent *er = queue_event(dpy);
+        if (!er) {
+           close(r);
+           return False;
+        }
+
+        dpy->fd[i].fd = r;
+        er->xcreatewindow.type = CreateNotify;
+        er->xcreatewindow.serial = 0;
+        er->xcreatewindow.send_event = 0;
+        er->xcreatewindow.display = dpy;
+        er->xcreatewindow.window = (Window)i;  /* fd slot == window, now? */
+
+        /* Send the driver client message - this is expected as the
+         * first message on a new connection.  The recpient already
+         * knows the size of the message.
+         */
+        welcome_message( dpy, i );
+        return True;
+      }            
+   }
+
+
+   fprintf(stderr, "[miniglx] %s: Max nr clients exceeded\n", __FUNCTION__);
+   close(r);
+   return False;
+}
+
+/**
+ * This routine "puffs out" the very basic communications between
+ * client and server to full-sized X Events that can be handled by the
+ * application.
+ *
+ * \param dpy the display handle.
+ * \param i the index in dpy->fd of the socket connection.
+ *
+ * \return True on success or False on failure.
+ *
+ * \internal
+ * Interprets the message (see msg) into a XEvent and advances the file FIFO
+ * buffer.
+ */
+static int
+handle_fifo_read( Display *dpy, int i )
+{
+   while (dpy->fd[i].readbuf_count) {
+      char id = dpy->fd[i].readbuf[0];
+      XEvent *er;
+      int count = 1;
+
+      if (dpy->IsClient) {
+        switch (id) {
+           /* The server has called XMapWindow on a client window */
+        case _YouveGotFocus:
+           er = queue_event(dpy);
+           if (!er) return False;
+           er->xmap.type = MapNotify;
+           er->xmap.serial = 0;
+           er->xmap.send_event = False;
+           er->xmap.display = dpy;
+           er->xmap.event = dpy->TheWindow;
+           er->xmap.window = dpy->TheWindow;
+           er->xmap.override_redirect = False;
+           if (dpy->driver->notifyFocus)
+              dpy->driver->notifyFocus( 1 ); 
+           break;
+
+           /* The server has called XMapWindow on a client window */
+        case _RepaintPlease:
+           er = queue_event(dpy);
+           if (!er) return False;
+           er->xexpose.type = Expose;
+           er->xexpose.serial = 0;
+           er->xexpose.send_event = False;
+           er->xexpose.display = dpy;
+           er->xexpose.window = dpy->TheWindow;
+           if (dpy->rotateMode) {
+              er->xexpose.x = dpy->TheWindow->y;
+              er->xexpose.y = dpy->TheWindow->x;
+              er->xexpose.width = dpy->TheWindow->h;
+              er->xexpose.height = dpy->TheWindow->w;
+           }
+           else {
+              er->xexpose.x = dpy->TheWindow->x;
+              er->xexpose.y = dpy->TheWindow->y;
+              er->xexpose.width = dpy->TheWindow->w;
+              er->xexpose.height = dpy->TheWindow->h;
+           }
+           er->xexpose.count = 0;
+           break;
+
+           /* The server has called 'XUnmapWindow' on a client
+            * window.
+            */
+        case _YouveLostFocus:
+           er = queue_event(dpy);
+           if (!er) return False;
+           er->xunmap.type = UnmapNotify;
+           er->xunmap.serial = 0;
+           er->xunmap.send_event = False;
+           er->xunmap.display = dpy;
+           er->xunmap.event = dpy->TheWindow;
+           er->xunmap.window = dpy->TheWindow;
+           er->xunmap.from_configure = False;
+           if (dpy->driver->notifyFocus)
+              dpy->driver->notifyFocus( 0 ); 
+           break;
+        
+        default:
+           fprintf(stderr, "Client received unhandled message type %d\n", id);
+           shut_fd(dpy, i);            /* Actually shuts down the client */
+           return False;
+        }
+      }
+      else {
+        switch (id) {
+           /* Lets the server know that the client is ready to render
+            * (having called 'XMapWindow' locally).
+            */
+        case _CanIHaveFocus:    
+           er = queue_event(dpy);
+           if (!er) return False;
+           er->xmaprequest.type = MapRequest;
+           er->xmaprequest.serial = 0;
+           er->xmaprequest.send_event = False;
+           er->xmaprequest.display = dpy;
+           er->xmaprequest.parent = 0;
+           er->xmaprequest.window = (Window)i;
+           break;
+
+           /* Both _YouveLostFocus and _IDontWantFocus generate unmap
+            * events.  The idea is that _YouveLostFocus lets the client
+            * know that it has had focus revoked by the server, whereas
+            * _IDontWantFocus lets the server know that the client has
+            * unmapped its own window.
+            */
+        case _IDontWantFocus:
+           er = queue_event(dpy);
+           if (!er) return False;
+           er->xunmap.type = UnmapNotify;
+           er->xunmap.serial = 0;
+           er->xunmap.send_event = False;
+           er->xunmap.display = dpy;
+           er->xunmap.event = (Window)i;
+           er->xunmap.window = (Window)i;
+           er->xunmap.from_configure = False;
+           break;
+
+        default:
+           fprintf(stderr, "Server received unhandled message type %d\n", id);
+           shut_fd(dpy, i);            /* Generates DestroyNotify event */
+           return False;
+        }
+      }
+
+      dpy->fd[i].readbuf_count -= count;
+
+      if (dpy->fd[i].readbuf_count) {
+        memmove(dpy->fd[i].readbuf,
+                dpy->fd[i].readbuf + count,
+                dpy->fd[i].readbuf_count);
+      }
+   }
+
+   return True;
+}
+
+/**
+ * Handle a VT signal
+ *
+ * \param dpy display handle.
+ *
+ * The VT switches is detected by comparing Display::haveVT and
+ * Display::hwActive. When loosing the VT the hardware lock is acquired, the
+ * hardware is shutdown via a call to DRIDriverRec::shutdownHardware(), and the
+ * VT released. When acquiring the VT back the hardware state is restored via a
+ * call to DRIDriverRec::restoreHardware() and the hardware lock released.
+ */
+static void __driHandleVtSignals( Display *dpy )
+{
+   dpy->vtSignalFlag = 0;
+
+   fprintf(stderr, "%s: haveVT %d hwActive %d\n", __FUNCTION__,
+          dpy->haveVT, dpy->hwActive);
+
+   if (!dpy->haveVT && dpy->hwActive) {
+      /* Need to get lock and shutdown hardware */
+      DRM_LIGHT_LOCK( dpy->driverContext.drmFD,
+                      dpy->driverContext.pSAREA,
+                      dpy->driverContext.serverContext ); 
+      dpy->driver->shutdownHardware( &dpy->driverContext ); 
+
+      /* Can now give up control of the VT */
+      ioctl( dpy->ConsoleFD, VT_RELDISP, 1 ); 
+      dpy->hwActive = 0;
+   }
+   else if (dpy->haveVT && !dpy->hwActive) {
+      /* Get VT (wait??) */
+      ioctl( dpy->ConsoleFD, VT_RELDISP, VT_ACTIVATE );
+
+      /* restore HW state, release lock */
+      dpy->driver->restoreHardware( &dpy->driverContext ); 
+      DRM_UNLOCK( dpy->driverContext.drmFD,
+                  dpy->driverContext.pSAREA,
+                  dpy->driverContext.serverContext ); 
+      dpy->hwActive = 1;
+   }
+}
+
+
+#undef max
+#define max(x,y) ((x) > (y) ? (x) : (y))
+
+/**
+ * Logic for the select() call.
+ *
+ * \param dpy display handle.
+ * \param n highest fd in any set plus one.
+ * \param rfds fd set to be watched for reading, or NULL to create one.
+ * \param wfds fd set to be watched for writing, or NULL to create one.
+ * \param xfds fd set to be watched for exceptions or error, or NULL to create one.
+ * \param tv timeout value, or NULL for no timeout.
+ * 
+ * \return number of file descriptors contained in the sets, or a negative number on failure.
+ * 
+ * \note
+ * This all looks pretty complex, but is necessary especially on the
+ * server side to prevent a poorly-behaved client from causing the
+ * server to block in a read or write and hence not service the other
+ * clients.
+ *
+ * \sa
+ * See select_tut in the Linux manual pages for more discussion.
+ *
+ * \internal
+ * Creates and initializes the file descriptor sets by inspecting Display::fd
+ * if these aren't passed in the function call. Calls select() and fulfill the
+ * demands by trying to fill MiniGLXConnection::readbuf and draining
+ * MiniGLXConnection::writebuf. 
+ * The server fd[0] is handled specially for new connections, by calling
+ * handle_new_client().
+ * 
+ */
+int 
+__miniglx_Select( Display *dpy, int n, fd_set *rfds, fd_set *wfds, fd_set *xfds,
+                 struct timeval *tv )
+{
+   int i;
+   int retval;
+   fd_set my_rfds, my_wfds;
+   struct timeval my_tv;
+
+   if (!rfds) {
+      rfds = &my_rfds;
+      FD_ZERO(rfds);
+   }
+
+   if (!wfds) {
+      wfds = &my_wfds;
+      FD_ZERO(wfds);
+   }
+
+   /* Don't block if there are events queued.  Review this if the
+    * flush in XMapWindow is changed to blocking.  (Test case:
+    * miniglxtest).
+    */
+   if (dpy->eventqueue.head != dpy->eventqueue.tail) {
+      my_tv.tv_sec = my_tv.tv_usec = 0;
+      tv = &my_tv;
+   }
+
+   for (i = 0 ; i < dpy->nrFds; i++) {
+      if (dpy->fd[i].fd < 0)
+        continue;
+      
+      if (dpy->fd[i].writebuf_count)
+        FD_SET(dpy->fd[i].fd, wfds);
+        
+      if (dpy->fd[i].readbuf_count < MINIGLX_BUF_SIZE) 
+        FD_SET(dpy->fd[i].fd, rfds);
+      
+      n = max(n, dpy->fd[i].fd + 1);
+   }
+
+   if (dpy->vtSignalFlag) 
+      __driHandleVtSignals( dpy ); 
+
+   retval = select( n, rfds, wfds, xfds, tv );
+
+   if (dpy->vtSignalFlag) {
+      int tmp = errno;
+      __driHandleVtSignals( dpy ); 
+      errno = tmp;
+   }
+
+   if (retval < 0) {
+      FD_ZERO(rfds);
+      FD_ZERO(wfds);
+      return retval;
+   }
+
+   /* Handle server fd[0] specially on the server - accept new client
+    * connections.
+    */
+   if (!dpy->IsClient) {
+      if (FD_ISSET(dpy->fd[0].fd, rfds)) {
+        FD_CLR(dpy->fd[0].fd, rfds);
+        handle_new_client( dpy );
+      }
+   }
+
+   /* Otherwise, try and fill readbuffer and drain writebuffer:
+    */
+   for (i = 0 ; i < dpy->nrFds ; i++) {
+      if (dpy->fd[i].fd < 0) 
+        continue;
+
+      /* If there aren't any event slots left, don't examine
+       * any more file events.  This will prevent lost events.
+       */
+      if (dpy->eventqueue.head == 
+         ((dpy->eventqueue.tail + 1) & MINIGLX_EVENT_QUEUE_MASK)) {
+        fprintf(stderr, "leaving event loop as event queue is full\n");
+        return retval;
+      }
+
+      if (FD_ISSET(dpy->fd[i].fd, wfds)) {
+        int r = write(dpy->fd[i].fd,
+                      dpy->fd[i].writebuf,
+                      dpy->fd[i].writebuf_count);
+        
+        if (r < 1) 
+           shut_fd(dpy,i);
+        else {
+           dpy->fd[i].writebuf_count -= r;
+           if (dpy->fd[i].writebuf_count) {
+              memmove(dpy->fd[i].writebuf,
+                      dpy->fd[i].writebuf + r,
+                      dpy->fd[i].writebuf_count);
+           }
+        }
+      }
+
+      if (FD_ISSET(dpy->fd[i].fd, rfds)) {
+        int r = read(dpy->fd[i].fd, 
+                     dpy->fd[i].readbuf + dpy->fd[i].readbuf_count,
+                     MINIGLX_BUF_SIZE - dpy->fd[i].readbuf_count);
+        
+        if (r < 1) 
+           shut_fd(dpy,i);
+        else {
+           dpy->fd[i].readbuf_count += r;
+        
+           handle_fifo_read( dpy, i );
+        }
+      }
+   }
+
+   return retval;
+}
+
+/**
+ * \brief Handle socket events.
+ *
+ * \param dpy the display handle.
+ * \param nonblock whether to return immediately or wait for an event.
+ *
+ * \return True on success, False on failure. Aborts on critical error.
+ *
+ * \internal
+ * This function is the select() main loop.
+ */
+static int handle_fd_events( Display *dpy, int nonblock )
+{
+   while (1) {
+      struct timeval tv = {0, 0};
+      int r = __miniglx_Select( dpy, 0, 0, 0, 0, nonblock ? &tv : 0 );
+      if (r >= 0) 
+        return True;
+      if (errno == EINTR || errno == EAGAIN)
+        continue;
+      perror ("select()");
+      exit (1);
+   }
+}
+
+/**
+ * Initializes the connections.
+ *
+ * \param dpy the display handle.
+ *
+ * \return True on success or False on failure.
+ *
+ * Allocates and initializes the Display::fd array and create a Unix socket on
+ * the first entry. For a server binds the socket to a filename and listen for
+ * connections. For a client connects to the server and waits for a welcome
+ * message. Sets the socket in nonblocking mode.
+ */
+int __miniglx_open_connections( Display *dpy )
+{
+   struct sockaddr_un sa;
+   int i;
+
+   dpy->nrFds = dpy->IsClient ? 1 : MINIGLX_MAX_SERVER_FDS;
+   dpy->fd = calloc(1, dpy->nrFds * sizeof(struct MiniGLXConnection));
+   if (!dpy->fd)
+      return False;
+
+   for (i = 0 ; i < dpy->nrFds ; i++)
+      dpy->fd[i].fd = -1;
+
+   if (!dpy->IsClient) {
+      if (unlink(MINIGLX_FIFO_NAME) != 0 && errno != ENOENT) { 
+        perror("unlink " MINIGLX_FIFO_NAME);
+        return False; 
+      } 
+      
+   } 
+
+   /* Create a Unix socket -- Note this is *not* a network connection!
+    */
+   dpy->fd[0].fd = socket(PF_UNIX, SOCK_STREAM, 0);
+   if (dpy->fd[0].fd < 0) {
+      perror("socket " MINIGLX_FIFO_NAME);
+      return False;
+   }
+
+   memset(&sa, 0, sizeof(sa));
+   sa.sun_family = AF_UNIX;
+   strcpy(sa.sun_path, MINIGLX_FIFO_NAME);
+
+   if (dpy->IsClient) {
+      /* Connect to server
+       */
+      if (connect(dpy->fd[0].fd, (struct sockaddr *)&sa, sizeof(sa)) != 0) {
+        perror("connect");
+        shut_fd(dpy,0);
+        return False;
+      }
+
+      /* Wait for configuration messages from the server.
+       */
+      welcome_message( dpy, 0 );
+   }
+   else {
+      mode_t tmp = umask( 0000 );              /* open to everybody ? */
+
+      /* Bind socket to our filename
+       */
+      if (bind(dpy->fd[0].fd, (struct sockaddr *)&sa, sizeof(sa)) != 0) {
+        perror("bind");
+        shut_fd(dpy,0);
+        return False;
+      }
+      
+      umask( tmp );
+
+      /* Listen for connections
+       */
+      if (listen(dpy->fd[0].fd, 5) != 0) {
+        perror("listen");
+        shut_fd(dpy,0);
+        return False;
+      }
+   }
+
+   if (fcntl(dpy->fd[0].fd, F_SETFL, O_NONBLOCK) != 0) {
+      perror("fcntl");
+      shut_fd(dpy,0);
+      return False;
+   }
+
+
+   return True;
+}
+
+
+/**
+ * Frees the connections initialized by __miniglx_open_connections().
+ *
+ * \param dpy the display handle.
+ */
+void __miniglx_close_connections( Display *dpy )
+{
+   int i;
+
+   for (i = 0 ; i < dpy->nrFds ; i++) {
+      if (dpy->fd[i].fd >= 0) {
+        shutdown (dpy->fd[i].fd, SHUT_RDWR);
+        close (dpy->fd[i].fd);
+      }
+   }
+
+   dpy->nrFds = 0;
+   free(dpy->fd);
+}
+
+
+/**
+ * Set a drawable flag.
+ *
+ * \param dpy the display handle.
+ * \param w drawable (window).
+ * \param flag flag.
+ *
+ * Sets the specified drawable flag in the SAREA and increment its stamp while
+ * holding the light hardware lock.
+ */
+static void set_drawable_flag( Display *dpy, int w, int flag )
+{
+   if (dpy->driverContext.pSAREA) {
+      if (dpy->hwActive) 
+        DRM_LIGHT_LOCK( dpy->driverContext.drmFD,
+                        dpy->driverContext.pSAREA,
+                        dpy->driverContext.serverContext ); 
+
+      dpy->driverContext.pSAREA->drawableTable[w].stamp++;
+      dpy->driverContext.pSAREA->drawableTable[w].flags = flag;
+
+      if (dpy->hwActive) 
+        DRM_UNLOCK( dpy->driverContext.drmFD,
+                    dpy->driverContext.pSAREA,
+                    dpy->driverContext.serverContext ); 
+   }
+}
+
+
+
+/**
+ * \brief Map Window.
+ *
+ * \param dpy the display handle as returned by XOpenDisplay().
+ * \param w the window handle.
+ * 
+ * If called by a client, sends a request for focus to the server.  If
+ * called by the server, will generate a MapNotify and Expose event at
+ * the client.
+ * 
+ */
+void
+XMapWindow( Display *dpy, Window w )
+{
+   if (dpy->IsClient) 
+      send_char_msg( dpy, 0, _CanIHaveFocus );
+   else {
+      set_drawable_flag( dpy, (int)w, 1 );
+      send_char_msg( dpy, (int)w, _YouveGotFocus );
+      send_char_msg( dpy, (int)w, _RepaintPlease );
+      dpy->TheWindow = w;
+   }
+   handle_fd_events( dpy, 0 ); /* flush write queue */
+}
+
+/**
+ * \brief Unmap Window.
+ *
+ * \param dpy the display handle as returned by XOpenDisplay().
+ * \param w the window handle.
+ * 
+ * Called from the client:  Lets the server know that the window won't
+ * be updated anymore.
+ *
+ * Called from the server:  Tells the specified client that it no longer
+ * holds the focus.
+ */
+void
+XUnmapWindow( Display *dpy, Window w )
+{
+   if (dpy->IsClient) {
+      send_char_msg( dpy, 0, _IDontWantFocus );
+   } 
+   else {
+      dpy->TheWindow = 0;
+      set_drawable_flag( dpy, (int)w, 0 );
+      send_char_msg( dpy, (int)w, _YouveLostFocus );
+   }
+   handle_fd_events( dpy, 0 ); /* flush write queue */
+}
+
+
+/**
+ * \brief Block and wait for next X event.
+ *
+ * \param dpy the display handle as returned by XOpenDisplay().
+ * \param event_return a pointer to an XEvent structure for the returned data.
+ *
+ * Wait until there is a new XEvent pending.
+ */
+int XNextEvent(Display *dpy, XEvent *event_return)
+{
+   for (;;) {
+      if ( dpy->eventqueue.head != dpy->eventqueue.tail )
+        return dequeue_event( dpy, event_return ); 
+      
+      handle_fd_events( dpy, 0 );
+   }
+}
+
+/**
+ * \brief Non-blocking check for next X event.
+ *
+ * \param dpy the display handle as returned by XOpenDisplay().
+ * \param event_mask ignored.
+ * \param event_return a pointer to an XEvent structure for the returned data.
+ *
+ * Check if there is a new XEvent pending.  Note that event_mask is
+ * ignored and any pending event will be returned.
+ */
+Bool XCheckMaskEvent(Display *dpy, long event_mask, XEvent *event_return)
+{
+   if ( dpy->eventqueue.head != dpy->eventqueue.tail )
+      return dequeue_event( dpy, event_return ); 
+
+   handle_fd_events( dpy, 1 );
+   return dequeue_event( dpy, event_return ); 
+}
diff --git a/src/glx/mini/sarea.h b/src/glx/mini/sarea.h
new file mode 100644 (file)
index 0000000..47545e1
--- /dev/null
@@ -0,0 +1,96 @@
+/**
+ * \file sarea.h 
+ * \brief SAREA definitions.
+ * 
+ * The SAREA is a memory region is shared by the DRM device, the X server and
+ * the clients.
+ *
+ * This file defines its layout in user space.
+ * 
+ * \author Kevin E. Martin <kevin@precisioninsight.com>
+ * \author Jens Owen <jens@tungstengraphics.com>
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ */
+
+/*
+ * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc.
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _SAREA_H_
+#define _SAREA_H_
+
+#include "xf86drm.h"
+
+/* SAREA area needs to be at least a page */
+#if defined(__alpha__)
+#define SAREA_MAX                      0x2000
+#elif defined(__ia64__)
+#define SAREA_MAX                      0x10000         /* 64kB */
+#else
+/* Intel 830M driver needs at least 8k SAREA */
+#define SAREA_MAX                      0x2000
+#endif
+
+#define SAREA_MAX_DRAWABLES            256
+
+#define SAREA_DRAWABLE_CLAIMED_ENTRY   0x80000000
+
+/**
+ * \brief SAREA per drawable information.
+ *
+ * \sa _XF86DRISAREA.
+ */
+typedef struct _XF86DRISAREADrawable {
+    unsigned int       stamp;
+    unsigned int       flags;
+} XF86DRISAREADrawableRec, *XF86DRISAREADrawablePtr;
+
+/**
+ * \brief SAREA frame information.
+ *
+ * \sa  _XF86DRISAREA.
+ */
+typedef struct _XF86DRISAREAFrame {
+    unsigned int        x;
+    unsigned int        y;
+    unsigned int        width;
+    unsigned int        height;
+    unsigned int        fullscreen;
+} XF86DRISAREAFrameRec, *XF86DRISAREAFramePtr;
+
+/**
+ * \brief SAREA definition.
+ */
+typedef struct _XF86DRISAREA {
+    /** first thing is always the DRM locking structure */
+    drmLock                    lock;
+    /** \todo Use readers/writer lock for drawable_lock */
+    drmLock                    drawable_lock;
+    XF86DRISAREADrawableRec    drawableTable[SAREA_MAX_DRAWABLES];
+    XF86DRISAREAFrameRec        frame;
+    drmContext                 dummy_context;
+} XF86DRISAREARec, *XF86DRISAREAPtr;
+
+#endif
diff --git a/src/glx/mini/xf86drm.c b/src/glx/mini/xf86drm.c
new file mode 100644 (file)
index 0000000..bbb02e4
--- /dev/null
@@ -0,0 +1,1587 @@
+/**
+ * \file xf86drm.c 
+ * \brief User-level interface to DRM device
+ *
+ * This file is an user-friendly interface to the DRM ioctls defined in drm.h.
+ * 
+ * This covers only the device-independent ioctls -- it is up to the driver to
+ * wrap the device-dependent ioctls.
+ * 
+ * \author Rickard E. (Rik) Faith <faith@valinux.com>
+ * \author Kevin E. Martin <martin@valinux.com>
+ */
+
+/*
+ * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+# include <stdio.h>
+# include <stdlib.h>
+# include <unistd.h>
+# include <string.h>
+# include <ctype.h>
+# include <fcntl.h>
+# include <errno.h>
+# include <signal.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <sys/ioctl.h>
+# include <sys/mman.h>
+# include <sys/time.h>
+# include <stdarg.h>
+# include "drm.h"
+
+/* Not all systems have MAP_FAILED defined */
+#ifndef MAP_FAILED
+#define MAP_FAILED ((void *)-1)
+#endif
+
+#include "xf86drm.h"
+
+#ifndef DRM_MAJOR
+#define DRM_MAJOR 226          /* Linux */
+#endif
+
+#ifndef __linux__
+#undef  DRM_MAJOR
+#define DRM_MAJOR 145          /* Should set in drm.h for *BSD */
+#endif
+
+#ifndef DRM_MAX_MINOR
+#define DRM_MAX_MINOR 16
+#endif
+
+#ifdef __linux__
+#include <sys/sysmacros.h>     /* for makedev() */
+#endif
+
+#ifndef makedev
+                               /* This definition needs to be changed on
+                                   some systems if dev_t is a structure.
+                                   If there is a header file we can get it
+                                   from, there would be best. */
+#define makedev(x,y)    ((dev_t)(((x) << 8) | (y)))
+#endif
+
+
+/**
+ * \brief Output a message to stderr.
+ *
+ * \param format printf() like format string.
+ *
+ * \internal
+ * This function is a wrapper around vfprintf().
+ */
+static void
+drmMsg(const char *format, ...)
+{
+    va_list    ap;
+
+    const char *env;
+    if ((env = getenv("LIBGL_DEBUG")) && strstr(env, "verbose")) 
+    {
+       va_start(ap, format);
+       vfprintf(stderr, format, ap);
+       va_end(ap);
+    }
+}
+
+
+
+/**
+ * \brief Open the DRM device, creating it if necessary.
+ *
+ * \param dev major and minor numbers of the device.
+ * \param minor minor number of the device.
+ * 
+ * \return a file descriptor on success, or a negative value on error.
+ *
+ * \internal
+ * Assembles the device name from \p minor and opens it, creating the device
+ * special file node with the major and minor numbers specified by \p dev and
+ * parent directory if necessary and was called by root.
+ */
+static int drmOpenDevice(long dev, int minor)
+{
+    struct stat          st;
+    char            buf[64];
+    int             fd;
+    mode_t          devmode = DRM_DEV_MODE;
+    int             isroot  = !geteuid();
+#if defined(XFree86Server)
+    uid_t           user    = DRM_DEV_UID;
+    gid_t           group   = DRM_DEV_GID;
+#endif
+
+    drmMsg("drmOpenDevice: minor is %d\n", minor);
+
+#if defined(XFree86Server)
+    devmode  = xf86ConfigDRI.mode ? xf86ConfigDRI.mode : DRM_DEV_MODE;
+    devmode &= ~(S_IXUSR|S_IXGRP|S_IXOTH);
+    group = (xf86ConfigDRI.group >= 0) ? xf86ConfigDRI.group : DRM_DEV_GID;
+#endif
+
+    if (stat(DRM_DIR_NAME, &st)) {
+       if (!isroot) return DRM_ERR_NOT_ROOT;
+       mkdir(DRM_DIR_NAME, DRM_DEV_DIRMODE);
+       chown(DRM_DIR_NAME, 0, 0); /* root:root */
+       chmod(DRM_DIR_NAME, DRM_DEV_DIRMODE);
+    }
+
+    sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
+    drmMsg("drmOpenDevice: node name is %s\n", buf);
+    if (stat(buf, &st)) {
+       if (!isroot) return DRM_ERR_NOT_ROOT;
+       remove(buf);
+       mknod(buf, S_IFCHR | devmode, dev);
+    }
+#if defined(XFree86Server)
+    chown(buf, user, group);
+    chmod(buf, devmode);
+#endif
+
+    fd = open(buf, O_RDWR, 0);
+    drmMsg("drmOpenDevice: open result is %d, (%s)\n",
+               fd, fd < 0 ? strerror(errno) : "OK");
+    if (fd >= 0) return fd;
+
+    if (st.st_rdev != dev) {
+       if (!isroot) return DRM_ERR_NOT_ROOT;
+       remove(buf);
+       mknod(buf, S_IFCHR | devmode, dev);
+    }
+    fd = open(buf, O_RDWR, 0);
+    drmMsg("drmOpenDevice: open result is %d, (%s)\n",
+               fd, fd < 0 ? strerror(errno) : "OK");
+    if (fd >= 0) return fd;
+
+    drmMsg("drmOpenDevice: Open failed\n");
+    remove(buf);
+    return -errno;
+}
+
+
+/**
+ * \brief Open the DRM device
+ *
+ * \param minor device minor number.
+ * \param create allow to create the device if set.
+ *
+ * \return a file descriptor on success, or a negative value on error.
+ * 
+ * \internal
+ * Calls drmOpenDevice() if \p create is set, otherwise assembles the device
+ * name from \p minor and opens it.
+ */
+static int drmOpenMinor(int minor, int create)
+{
+    int  fd;
+    char buf[64];
+    
+    if (create) return drmOpenDevice(makedev(DRM_MAJOR, minor), minor);
+    
+    sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
+    if ((fd = open(buf, O_RDWR, 0)) >= 0) return fd;
+    drmMsg("drmOpenMinor: open result is %d, (%s)\n",
+               fd, fd < 0 ? strerror(errno) : "OK");
+    return -errno;
+}
+
+
+/**
+ * \brief Determine whether the DRM kernel driver has been loaded.
+ * 
+ * \return 1 if the DRM driver is loaded, 0 otherwise.
+ *
+ * \internal 
+ * Determine the presence of the kernel driver by attempting to open the 0
+ * minor and get version information.  For backward compatibility with older
+ * Linux implementations, /proc/dri is also checked.
+ */
+int drmAvailable(void)
+{
+    drmVersionPtr version;
+    int           retval = 0;
+    int           fd;
+
+    if ((fd = drmOpenMinor(0, 1)) < 0) {
+                               /* Try proc for backward Linux compatibility */
+       if (!access("/proc/dri/0", R_OK)) return 1;
+       return 0;
+    }
+    
+    if ((version = drmGetVersion(fd))) {
+       retval = 1;
+       drmFreeVersion(version);
+    }
+    close(fd);
+    drmMsg("close %d\n", fd);
+
+    return retval;
+}
+
+
+/**
+ * \brief Open the device by bus ID.
+ *
+ * \param busid bus ID.
+ *
+ * \return a file descriptor on success, or a negative value on error.
+ *
+ * \internal
+ * This function attempts to open every possible minor (up to DRM_MAX_MINOR),
+ * comparing the device bus ID with the one supplied.
+ *
+ * \sa drmOpenMinor() and drmGetBusid().
+ */
+static int drmOpenByBusid(const char *busid)
+{
+    int        i;
+    int        fd;
+    const char *buf;
+    
+    drmMsg("drmOpenByBusid: busid is %s\n", busid);
+    for (i = 0; i < DRM_MAX_MINOR; i++) {
+       fd = drmOpenMinor(i, 1);
+       drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd);
+       if (fd >= 0) {
+           buf = drmGetBusid(fd);
+           drmMsg("drmOpenByBusid: drmGetBusid reports %s\n", buf);
+           if (buf && !strcmp(buf, busid)) {
+               drmFreeBusid(buf);
+               return fd;
+           }
+           if (buf) drmFreeBusid(buf);
+           close(fd);
+           drmMsg("close %d\n", fd);
+       }
+    }
+    return -1;
+}
+
+
+/**
+ * \brief Open the device by name.
+ *
+ * \param name driver name.
+ * 
+ * \return a file descriptor on success, or a negative value on error.
+ * 
+ * \internal
+ * This function opens the first minor number that matches the driver name and
+ * isn't already in use.  If it's in use it then it will already have a bus ID
+ * assigned.
+ * 
+ * \sa drmOpenMinor(), drmGetVersion() and drmGetBusid().
+ */
+static int drmOpenByName(const char *name)
+{
+    int           i;
+    int           fd;
+    drmVersionPtr version;
+    char *        id;
+    
+    if (!drmAvailable()) {
+#if !defined(XFree86Server)
+       return -1;
+#else
+        /* try to load the kernel module now */
+        if (!xf86LoadKernelModule(name)) {
+            ErrorF("[drm] failed to load kernel module \"%s\"\n",
+                  name);
+            return -1;
+        }
+#endif
+    }
+
+    for (i = 0; i < DRM_MAX_MINOR; i++) {
+       if ((fd = drmOpenMinor(i, 1)) >= 0) {
+           if ((version = drmGetVersion(fd))) {
+               if (!strcmp(version->name, name)) {
+                   drmFreeVersion(version);
+
+/*                     return fd; */
+
+                   id = drmGetBusid(fd);
+                   drmMsg("drmGetBusid returned '%s'\n", id ? id : "NULL");
+                   if (!id || !*id) {
+                       if (id) {
+                           drmFreeBusid(id);
+                       }
+                       return fd;
+                   } else {
+                       drmFreeBusid(id);
+                   }
+               } else {
+                   drmFreeVersion(version);
+               }
+           }
+           close(fd);
+           drmMsg("close %d\n", fd);
+       }
+    }
+
+    return -1;
+}
+
+
+/**
+ * \brief Open the DRM device.
+ *
+ * Looks up the specified name and bus ID, and opens the device found.  The
+ * entry in /dev/dri is created if necessary and if called by root.
+ *
+ * \param name driver name. Not referenced if bus ID is supplied.
+ * \param busid bus ID. Zero if not known.
+ * 
+ * \return a file descriptor on success, or a negative value on error.
+ * 
+ * \internal
+ * It calls drmOpenByBusid() if \p busid is specified or drmOpenByName()
+ * otherwise.
+ */
+int drmOpen(const char *name, const char *busid)
+{
+
+    if (busid) return drmOpenByBusid(busid);
+    return drmOpenByName(name);
+}
+
+
+/**
+ * \brief Free the version information returned by drmGetVersion().
+ *
+ * \param v pointer to the version information.
+ *
+ * \internal
+ * It frees the memory pointed by \p %v as well as all the non-null strings
+ * pointers in it.
+ */
+void drmFreeVersion(drmVersionPtr v)
+{
+    if (!v) return;
+    if (v->name) free(v->name);
+    if (v->date) free(v->date);
+    if (v->desc) free(v->desc);
+    free(v);
+}
+
+
+/**
+ * \brief Free the non-public version information returned by the kernel.
+ *
+ * \param v pointer to the version information.
+ *
+ * \internal
+ * Used by drmGetVersion() to free the memory pointed by \p %v as well as all
+ * the non-null strings pointers in it.
+ */
+static void drmFreeKernelVersion(drm_version_t *v)
+{
+    if (!v) return;
+    if (v->name) free(v->name);
+    if (v->date) free(v->date);
+    if (v->desc) free(v->desc);
+    free(v);
+}
+
+
+/**
+ * \brief Copy version information.
+ * 
+ * \param d destination pointer.
+ * \param s source pointer.
+ * 
+ * \internal
+ * Used by drmGetVersion() to translate the information returned by the ioctl
+ * interface in a private structure into the public structure counterpart.
+ */
+static void drmCopyVersion(drmVersionPtr d, const drm_version_t *s)
+{
+    d->version_major      = s->version_major;
+    d->version_minor      = s->version_minor;
+    d->version_patchlevel = s->version_patchlevel;
+    d->name_len           = s->name_len;
+    d->name               = strdup(s->name);
+    d->date_len           = s->date_len;
+    d->date               = strdup(s->date);
+    d->desc_len           = s->desc_len;
+    d->desc               = strdup(s->desc);
+}
+
+
+/**
+ * \brief Query the driver version information.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return pointer to a drmVersion structure which should be freed with
+ * drmFreeVersion().
+ * 
+ * \note Similar information is available via /proc/dri.
+ * 
+ * \internal
+ * It gets the version information via successive DRM_IOCTL_VERSION ioctls,
+ * first with zeros to get the string lengths, and then the actually strings.
+ * It also null-terminates them since they might not be already.
+ */
+drmVersionPtr drmGetVersion(int fd)
+{
+    drmVersionPtr retval;
+    drm_version_t *version = malloc(sizeof(*version));
+
+                               /* First, get the lengths */
+    version->name_len    = 0;
+    version->name        = NULL;
+    version->date_len    = 0;
+    version->date        = NULL;
+    version->desc_len    = 0;
+    version->desc        = NULL;
+
+    if (ioctl(fd, DRM_IOCTL_VERSION, version)) {
+       drmFreeKernelVersion(version);
+       return NULL;
+    }
+
+                               /* Now, allocate space and get the data */
+    if (version->name_len)
+       version->name    = malloc(version->name_len + 1);
+    if (version->date_len)
+       version->date    = malloc(version->date_len + 1);
+    if (version->desc_len)
+       version->desc    = malloc(version->desc_len + 1);
+
+    if (ioctl(fd, DRM_IOCTL_VERSION, version)) {
+       drmFreeKernelVersion(version);
+       return NULL;
+    }
+
+                               /* The results might not be null-terminated
+                                   strings, so terminate them. */
+
+    if (version->name_len) version->name[version->name_len] = '\0';
+    if (version->date_len) version->date[version->date_len] = '\0';
+    if (version->desc_len) version->desc[version->desc_len] = '\0';
+
+                               /* Now, copy it all back into the
+                                   client-visible data structure... */
+    retval = malloc(sizeof(*retval));
+    drmCopyVersion(retval, version);
+    drmFreeKernelVersion(version);
+    return retval;
+}
+
+
+/**
+ * \brief Get version information for the DRM user space library.
+ * 
+ * This version number is driver independent.
+ * 
+ * \param fd file descriptor.
+ *
+ * \return version information.
+ * 
+ * \internal
+ * This function allocates and fills a drm_version structure with a hard coded
+ * version number.
+ */
+drmVersionPtr drmGetLibVersion(int fd)
+{
+    drm_version_t *version = malloc(sizeof(*version));
+
+    /* Version history:
+     *   revision 1.0.x = original DRM interface with no drmGetLibVersion
+     *                    entry point and many drm<Device> extensions
+     *   revision 1.1.x = added drmCommand entry points for device extensions
+     *                    added drmGetLibVersion to identify libdrm.a version
+     */
+    version->version_major      = 1;
+    version->version_minor      = 1;
+    version->version_patchlevel = 0;
+
+    return (drmVersionPtr)version;
+}
+
+
+/**
+ * \brief Free the bus ID information.
+ *
+ * \param busid bus ID information string as given by drmGetBusid().
+ *
+ * \internal
+ * This function is just frees the memory pointed by \p busid.
+ */
+void drmFreeBusid(const char *busid)
+{
+    free((void *)busid);
+}
+
+
+/**
+ * \brief Get the bus ID of the device.
+ *
+ * \param fd file descriptor.
+ *
+ * \return bus ID string.
+ *
+ * \internal
+ * This function gets the bus ID via successive DRM_IOCTL_GET_UNIQUE ioctls to
+ * get the string length and data, passing the arguments in a drm_unique
+ * structure.
+ */
+char *drmGetBusid(int fd)
+{
+    drm_unique_t u;
+
+    u.unique_len = 0;
+    u.unique     = NULL;
+
+    if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) return NULL;
+    u.unique = malloc(u.unique_len + 1);
+    if (ioctl(fd, DRM_IOCTL_GET_UNIQUE, &u)) return NULL;
+    u.unique[u.unique_len] = '\0';
+    return u.unique;
+}
+
+
+/**
+ * \brief Set the bus ID of the device.
+ *
+ * \param fd file descriptor.
+ * \param busid bus ID string.
+ *
+ * \return zero on success, negative on failure.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_SET_UNIQUE ioctl, passing
+ * the arguments in a drm_unique structure.
+ */
+int drmSetBusid(int fd, const char *busid)
+{
+    drm_unique_t u;
+
+    u.unique     = (char *)busid;
+    u.unique_len = strlen(busid);
+
+    if (ioctl(fd, DRM_IOCTL_SET_UNIQUE, &u)) {
+       return -errno;
+    }
+    return 0;
+}
+
+
+/**
+ * \brief Specifies a range of memory that is available for mapping by a
+ * non-root process.
+ *
+ * \param fd file descriptor.
+ * \param offset usually the physical address. The actual meaning depends of
+ * the \p type parameter. See below.
+ * \param size of the memory in bytes.
+ * \param type type of the memory to be mapped.
+ * \param flags combination of several flags to modify the function actions.
+ * \param handle will be set to a value that may be used as the offset
+ * parameter for mmap().
+ * 
+ * \return zero on success or a negative value on error.
+ *
+ * \par Mapping the frame buffer
+ * For the frame buffer
+ * - \p offset will be the physical address of the start of the frame buffer,
+ * - \p size will be the size of the frame buffer in bytes, and
+ * - \p type will be DRM_FRAME_BUFFER.
+ *
+ * \par
+ * The area mapped will be uncached. If MTRR support is available in the
+ * kernel, the frame buffer area will be set to write combining. 
+ *
+ * \par Mapping the MMIO register area
+ * For the MMIO register area,
+ * - \p offset will be the physical address of the start of the register area,
+ * - \p size will be the size of the register area bytes, and
+ * - \p type will be DRM_REGISTERS.
+ * \par
+ * The area mapped will be uncached. 
+ * 
+ * \par Mapping the SAREA
+ * For the SAREA,
+ * - \p offset will be ignored and should be set to zero,
+ * - \p size will be the desired size of the SAREA in bytes,
+ * - \p type will be DRM_SHM.
+ * 
+ * \par
+ * A shared memory area of the requested size will be created and locked in
+ * kernel memory. This area may be mapped into client-space by using the handle
+ * returned. 
+ * 
+ * \note May only be called by root.
+ *
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_ADD_MAP ioctl, passing
+ * the arguments in a drm_map structure.
+ */
+int drmAddMap(int fd,
+             drmHandle offset,
+             drmSize size,
+             drmMapType type,
+             drmMapFlags flags,
+             drmHandlePtr handle)
+{
+    drm_map_t map;
+
+    map.offset  = offset;
+    map.size    = size;
+    map.handle  = 0;
+    map.type    = type;
+    map.flags   = flags;
+    if (ioctl(fd, DRM_IOCTL_ADD_MAP, &map)) return -errno;
+    if (handle) *handle = (drmHandle)map.handle;
+    return 0;
+}
+
+
+/**
+ * \brief Make buffers available for DMA transfers.
+ * 
+ * \param fd file descriptor.
+ * \param count number of buffers.
+ * \param size size of each buffer.
+ * \param flags buffer allocation flags.
+ * \param agp_offset offset in the AGP aperture 
+ *
+ * \return number of buffers allocated, negative on error.
+ *
+ * \internal
+ * This function is a wrapper around DRM_IOCTL_ADD_BUFS ioctl.
+ *
+ * \sa drm_buf_desc.
+ */
+int drmAddBufs(int fd, int count, int size, drmBufDescFlags flags,
+              int agp_offset)
+{
+    drm_buf_desc_t request;
+
+    request.count     = count;
+    request.size      = size;
+    request.low_mark  = 0;
+    request.high_mark = 0;
+    request.flags     = flags;
+    request.agp_start = agp_offset;
+
+    if (ioctl(fd, DRM_IOCTL_ADD_BUFS, &request)) return -errno;
+    return request.count;
+}
+
+
+/**
+ * \brief Free buffers.
+ *
+ * \param fd file descriptor.
+ * \param count number of buffers to free.
+ * \param list list of buffers to be freed.
+ *
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \note This function is primarily used for debugging.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_FREE_BUFS ioctl, passing
+ * the arguments in a drm_buf_free structure.
+ */
+int drmFreeBufs(int fd, int count, int *list)
+{
+    drm_buf_free_t request;
+
+    request.count = count;
+    request.list  = list;
+    if (ioctl(fd, DRM_IOCTL_FREE_BUFS, &request)) return -errno;
+    return 0;
+}
+
+
+/**
+ * \brief Close the device.
+ *
+ * \param fd file descriptor.
+ *
+ * \internal
+ * This function closes the file descriptor.
+ */
+int drmClose(int fd)
+{
+    drmMsg("close %d\n", fd);
+    return close(fd);
+}
+
+
+/**
+ * \brief Map a region of memory.
+ *
+ * \param fd file descriptor.
+ * \param handle handle returned by drmAddMap().
+ * \param size size in bytes. Must match the size used by drmAddMap().
+ * \param address will contain the user-space virtual address where the mapping
+ * begins.
+ *
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper for mmap().
+ */
+int drmMap(int fd,
+          drmHandle handle,
+          drmSize size,
+          drmAddressPtr address)
+{
+    static unsigned long pagesize_mask = 0;
+
+    if (fd < 0) return -EINVAL;
+
+    if (!pagesize_mask)
+       pagesize_mask = getpagesize() - 1;
+
+    size = (size + pagesize_mask) & ~pagesize_mask;
+
+    *address = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, handle);
+    if (*address == MAP_FAILED) return -errno;
+    return 0;
+}
+
+
+/**
+ * \brief Unmap mappings obtained with drmMap().
+ *
+ * \param address address as given by drmMap().
+ * \param size size in bytes. Must match the size used by drmMap().
+ * 
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * This function is a wrapper for unmap().
+ */
+int drmUnmap(drmAddress address, drmSize size)
+{
+    return munmap(address, size);
+}
+
+
+/**
+ * \brief Map all DMA buffers into client-virtual space.
+ *
+ * \param fd file descriptor.
+ *
+ * \return a pointer to a ::drmBufMap structure.
+ *
+ * \note The client may not use these buffers until obtaining buffer indices
+ * with drmDMA().
+ * 
+ * \internal
+ * This function calls the DRM_IOCTL_MAP_BUFS ioctl and copies the returned
+ * information about the buffers in a drm_buf_map structure into the
+ * client-visible data structures.
+ */ 
+drmBufMapPtr drmMapBufs(int fd)
+{
+    drm_buf_map_t bufs;
+    drmBufMapPtr  retval;
+    int           i;
+
+    bufs.count = 0;
+    bufs.list  = NULL;
+    if (ioctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) return NULL;
+
+    if (bufs.count) {
+       if (!(bufs.list = malloc(bufs.count * sizeof(*bufs.list))))
+           return NULL;
+
+       if (ioctl(fd, DRM_IOCTL_MAP_BUFS, &bufs)) {
+           free(bufs.list);
+           return NULL;
+       }
+                               /* Now, copy it all back into the
+                                   client-visible data structures... */
+       retval = malloc(sizeof(*retval));
+       retval->count = bufs.count;
+       retval->list  = malloc(bufs.count * sizeof(*retval->list));
+       for (i = 0; i < bufs.count; i++) {
+           retval->list[i].idx     = bufs.list[i].idx;
+           retval->list[i].total   = bufs.list[i].total;
+           retval->list[i].used    = 0;
+           retval->list[i].address = bufs.list[i].address;
+       }
+       return retval;
+    }
+    return NULL;
+}
+
+
+/**
+ * \brief Unmap buffers allocated with drmMapBufs().
+ *
+ * \return zero on success, or negative value on failure.
+ *
+ * \internal
+ * Calls munmap() for every buffer stored in \p bufs.
+ */
+int drmUnmapBufs(drmBufMapPtr bufs)
+{
+    int i;
+
+    for (i = 0; i < bufs->count; i++) {
+       munmap(bufs->list[i].address, bufs->list[i].total);
+    }
+    return 0;
+}
+
+
+#define DRM_DMA_RETRY          16
+
+/**
+ * \brief Reserve DMA buffers.
+ *
+ * \param fd file descriptor.
+ * \param request 
+ * 
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * Assemble the arguments into a drm_dma structure and keeps issuing the
+ * DRM_IOCTL_DMA ioctl until success or until maximum number of retries.
+ */
+int drmDMA(int fd, drmDMAReqPtr request)
+{
+    drm_dma_t dma;
+    int ret, i = 0;
+
+                               /* Copy to hidden structure */
+    dma.context         = request->context;
+    dma.send_count      = request->send_count;
+    dma.send_indices    = request->send_list;
+    dma.send_sizes      = request->send_sizes;
+    dma.flags           = request->flags;
+    dma.request_count   = request->request_count;
+    dma.request_size    = request->request_size;
+    dma.request_indices = request->request_list;
+    dma.request_sizes   = request->request_sizes;
+
+    do {
+       ret = ioctl( fd, DRM_IOCTL_DMA, &dma );
+    } while ( ret && errno == EAGAIN && i++ < DRM_DMA_RETRY );
+
+    if ( ret == 0 ) {
+       request->granted_count = dma.granted_count;
+       return 0;
+    } else {
+       return -errno;
+    }
+}
+
+
+/**
+ * \brief Obtain heavyweight hardware lock.
+ *
+ * \param fd file descriptor.
+ * \param context context.
+ * \param flags flags that determine the sate of the hardware when the function
+ * returns.
+ * 
+ * \return always zero.
+ * 
+ * \internal
+ * This function translates the arguments into a drm_lock structure and issue
+ * the DRM_IOCTL_LOCK ioctl until the lock is successfully acquired.
+ */
+int drmGetLock(int fd, drmContext context, drmLockFlags flags)
+{
+    drm_lock_t lock;
+
+    lock.context = context;
+    lock.flags   = 0;
+    if (flags & DRM_LOCK_READY)      lock.flags |= _DRM_LOCK_READY;
+    if (flags & DRM_LOCK_QUIESCENT)  lock.flags |= _DRM_LOCK_QUIESCENT;
+    if (flags & DRM_LOCK_FLUSH)      lock.flags |= _DRM_LOCK_FLUSH;
+    if (flags & DRM_LOCK_FLUSH_ALL)  lock.flags |= _DRM_LOCK_FLUSH_ALL;
+    if (flags & DRM_HALT_ALL_QUEUES) lock.flags |= _DRM_HALT_ALL_QUEUES;
+    if (flags & DRM_HALT_CUR_QUEUES) lock.flags |= _DRM_HALT_CUR_QUEUES;
+
+    while (ioctl(fd, DRM_IOCTL_LOCK, &lock))
+       ;
+    return 0;
+}
+
+static void (*drm_unlock_callback)( void ) = 0;
+
+/**
+ * \brief Release the hardware lock.
+ *
+ * \param fd file descriptor.
+ * \param context context.
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_UNLOCK ioctl, passing the
+ * argument in a drm_lock structure.
+ */
+int drmUnlock(int fd, drmContext context)
+{
+    drm_lock_t lock;
+    int ret;
+
+    lock.context = context;
+    lock.flags   = 0;
+    ret = ioctl(fd, DRM_IOCTL_UNLOCK, &lock);
+
+    /* Need this to synchronize vt releasing.  Could also teach fbdev
+     * about the drm lock...
+     */
+    if (drm_unlock_callback) {
+       drm_unlock_callback();
+    }
+
+    return ret;
+}
+
+
+/**
+ * \brief Create context.
+ *
+ * Used by the X server during GLXContext initialization. This causes
+ * per-context kernel-level resources to be allocated.
+ *
+ * \param fd file descriptor.
+ * \param handle is set on success. To be used by the client when requesting DMA
+ * dispatch with drmDMA().
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \note May only be called by root.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_ADD_CTX ioctl, passing the
+ * argument in a drm_ctx structure.
+ */
+int drmCreateContext(int fd, drmContextPtr handle)
+{
+    drm_ctx_t ctx;
+
+    ctx.flags = 0;     /* Modified with functions below */
+    if (ioctl(fd, DRM_IOCTL_ADD_CTX, &ctx)) return -errno;
+    *handle = ctx.handle;
+    return 0;
+}
+
+
+/**
+ * \brief Destroy context.
+ *
+ * Free any kernel-level resources allocated with drmCreateContext() associated
+ * with the context.
+ * 
+ * \param fd file descriptor.
+ * \param handle handle given by drmCreateContext().
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \note May only be called by root.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_RM_CTX ioctl, passing the
+ * argument in a drm_ctx structure.
+ */
+int drmDestroyContext(int fd, drmContext handle)
+{
+    drm_ctx_t ctx;
+    ctx.handle = handle;
+    if (ioctl(fd, DRM_IOCTL_RM_CTX, &ctx)) return -errno;
+    return 0;
+}
+
+
+/**
+ * \brief Acquire the AGP device.
+ *
+ * Must be called before any of the other AGP related calls.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_ACQUIRE ioctl.
+ */
+int drmAgpAcquire(int fd)
+{
+    if (ioctl(fd, DRM_IOCTL_AGP_ACQUIRE, NULL)) return -errno;
+    return 0;
+}
+
+
+/**
+ * \brief Release the AGP device.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_RELEASE ioctl.
+ */
+int drmAgpRelease(int fd)
+{
+    if (ioctl(fd, DRM_IOCTL_AGP_RELEASE, NULL)) return -errno;
+    return 0;
+}
+
+
+/**
+ * \brief Set the AGP mode.
+ *
+ * \param fd file descriptor.
+ * \param mode AGP mode.
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_ENABLE ioctl, passing the
+ * argument in a drm_agp_mode structure.
+ */
+int drmAgpEnable(int fd, unsigned long mode)
+{
+    drm_agp_mode_t m;
+
+    m.mode = mode;
+    if (ioctl(fd, DRM_IOCTL_AGP_ENABLE, &m)) return -errno;
+    return 0;
+}
+
+
+/**
+ * \brief Allocate a chunk of AGP memory.
+ *
+ * \param fd file descriptor.
+ * \param size requested memory size in bytes. Will be rounded to page boundary.
+ * \param type type of memory to allocate.
+ * \param address if not zero, will be set to the physical address of the
+ * allocated memory.
+ * \param handle on success will be set to a handle of the allocated memory.
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_ALLOC ioctl, passing the
+ * arguments in a drm_agp_buffer structure.
+ */
+int drmAgpAlloc(int fd, unsigned long size, unsigned long type,
+               unsigned long *address, unsigned long *handle)
+{
+    drm_agp_buffer_t b;
+    *handle = 0;
+    b.size   = size;
+    b.handle = 0;
+    b.type   = type;
+    if (ioctl(fd, DRM_IOCTL_AGP_ALLOC, &b)) return -errno;
+    if (address != 0UL) *address = b.physical;
+    *handle = b.handle;
+    return 0;
+}
+
+
+/**
+ * \brief Free a chunk of AGP memory.
+ *
+ * \param fd file descriptor.
+ * \param handle handle to the allocated memory, as given by drmAgpAllocate().
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_FREE ioctl, passing the
+ * argument in a drm_agp_buffer structure.
+ */
+int drmAgpFree(int fd, unsigned long handle)
+{
+    drm_agp_buffer_t b;
+
+    b.size   = 0;
+    b.handle = handle;
+    if (ioctl(fd, DRM_IOCTL_AGP_FREE, &b)) return -errno;
+    return 0;
+}
+
+
+/**
+ * \brief Bind a chunk of AGP memory.
+ *
+ * \param fd file descriptor.
+ * \param handle handle to the allocated memory, as given by drmAgpAllocate().
+ * \param offset offset in bytes. It will round to page boundary.
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_BIND ioctl, passing the
+ * argument in a drm_agp_binding structure.
+ */
+int drmAgpBind(int fd, unsigned long handle, unsigned long offset)
+{
+    drm_agp_binding_t b;
+
+    b.handle = handle;
+    b.offset = offset;
+    if (ioctl(fd, DRM_IOCTL_AGP_BIND, &b)) return -errno;
+    return 0;
+}
+
+
+/**
+ * \brief Unbind a chunk of AGP memory.
+ *
+ * \param fd file descriptor.
+ * \param handle handle to the allocated memory, as given by drmAgpAllocate().
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_UNBIND ioctl, passing
+ * the argument in a drm_agp_binding structure.
+ */
+int drmAgpUnbind(int fd, unsigned long handle)
+{
+    drm_agp_binding_t b;
+
+    b.handle = handle;
+    b.offset = 0;
+    if (ioctl(fd, DRM_IOCTL_AGP_UNBIND, &b)) return -errno;
+    return 0;
+}
+
+
+/**
+ * \brief Get AGP driver major version number.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return major version number on success, or a negative value on failure..
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+int drmAgpVersionMajor(int fd)
+{
+    drm_agp_info_t i;
+
+    if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return -errno;
+    return i.agp_version_major;
+}
+
+
+/**
+ * \brief Get AGP driver minor version number.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return minor version number on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+int drmAgpVersionMinor(int fd)
+{
+    drm_agp_info_t i;
+
+    if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return -errno;
+    return i.agp_version_minor;
+}
+
+
+/**
+ * \brief Get AGP mode.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return mode on success, or zero on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned long drmAgpGetMode(int fd)
+{
+    drm_agp_info_t i;
+
+    if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+    return i.mode;
+}
+
+
+/**
+ * \brief Get AGP aperture base.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return aperture base on success, zero on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned long drmAgpBase(int fd)
+{
+    drm_agp_info_t i;
+
+    if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+    return i.aperture_base;
+}
+
+
+/**
+ * \brief Get AGP aperture size.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return aperture size on success, zero on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned long drmAgpSize(int fd)
+{
+    drm_agp_info_t i;
+
+    if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+    return i.aperture_size;
+}
+
+
+/**
+ * \brief Get used AGP memory.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return memory used on success, or zero on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned long drmAgpMemoryUsed(int fd)
+{
+    drm_agp_info_t i;
+
+    if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+    return i.memory_used;
+}
+
+
+/**
+ * \brief Get available AGP memory.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return memory available on success, or zero on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned long drmAgpMemoryAvail(int fd)
+{
+    drm_agp_info_t i;
+
+    if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+    return i.memory_allowed;
+}
+
+
+/**
+ * \brief Get hardware vendor ID.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return vendor ID on success, or zero on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned int drmAgpVendorId(int fd)
+{
+    drm_agp_info_t i;
+
+    if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+    return i.id_vendor;
+}
+
+
+/**
+ * \brief Get hardware device ID.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return zero on success, or zero on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_AGP_INFO ioctl, getting the
+ * necessary information in a drm_agp_info structure.
+ */
+unsigned int drmAgpDeviceId(int fd)
+{
+    drm_agp_info_t i;
+
+    if (ioctl(fd, DRM_IOCTL_AGP_INFO, &i)) return 0;
+    return i.id_device;
+}
+
+int drmScatterGatherAlloc(int fd, unsigned long size, unsigned long *handle)
+{
+    drm_scatter_gather_t sg;
+
+    *handle = 0;
+    sg.size   = size;
+    sg.handle = 0;
+    if (ioctl(fd, DRM_IOCTL_SG_ALLOC, &sg)) return -errno;
+    *handle = sg.handle;
+    return 0;
+}
+
+int drmScatterGatherFree(int fd, unsigned long handle)
+{
+    drm_scatter_gather_t sg;
+
+    sg.size   = 0;
+    sg.handle = handle;
+    if (ioctl(fd, DRM_IOCTL_SG_FREE, &sg)) return -errno;
+    return 0;
+}
+
+/**
+ * \brief Wait for VBLANK.
+ *
+ * \param fd file descriptor.
+ * \param vbl pointer to a drmVBlank structure.
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_WAIT_VBLANK ioctl.
+ */
+int drmWaitVBlank(int fd, drmVBlankPtr vbl)
+{
+    int ret;
+
+    do {
+       ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl);
+    } while (ret && errno == EINTR);
+
+    return ret;
+}
+
+
+/**
+ * \brief Install IRQ handler.
+ *
+ * \param fd file descriptor.
+ * \param irq IRQ number.
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
+ * argument in a drm_control structure.
+ */
+int drmCtlInstHandler(int fd, int irq)
+{
+    drm_control_t ctl;
+
+    ctl.func  = DRM_INST_HANDLER;
+    ctl.irq   = irq;
+    if (ioctl(fd, DRM_IOCTL_CONTROL, &ctl)) return -errno;
+    return 0;
+}
+
+
+/**
+ * \brief Uninstall IRQ handler.
+ *
+ * \param fd file descriptor.
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_CONTROL ioctl, passing the
+ * argument in a drm_control structure.
+ */
+int drmCtlUninstHandler(int fd)
+{
+    drm_control_t ctl;
+
+    ctl.func  = DRM_UNINST_HANDLER;
+    ctl.irq   = 0;
+    if (ioctl(fd, DRM_IOCTL_CONTROL, &ctl)) return -errno;
+    return 0;
+}
+
+
+/**
+ * \brief Get IRQ from bus ID.
+ *
+ * \param fd file descriptor.
+ * \param busnum bus number.
+ * \param devnum device number.
+ * \param funcnum function number.
+ * 
+ * \return IRQ number on success, or a negative value on failure.
+ * 
+ * \internal
+ * This function is a wrapper around the DRM_IOCTL_IRQ_BUSID ioctl, passing the
+ * arguments in a drm_irq_busid structure.
+ */
+int drmGetInterruptFromBusID(int fd, int busnum, int devnum, int funcnum)
+{
+    drm_irq_busid_t p;
+
+    p.busnum  = busnum;
+    p.devnum  = devnum;
+    p.funcnum = funcnum;
+    if (ioctl(fd, DRM_IOCTL_IRQ_BUSID, &p)) return -errno;
+    return p.irq;
+}
+
+
+/**
+ * \brief Send a device-specific command.
+ *
+ * \param fd file descriptor.
+ * \param drmCommandIndex command index 
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * It issues a ioctl given by 
+ * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
+ */
+int drmCommandNone(int fd, unsigned long drmCommandIndex)
+{
+    void *data = NULL; /* dummy */
+    unsigned long request;
+
+    request = DRM_IO( DRM_COMMAND_BASE + drmCommandIndex);
+
+    if (ioctl(fd, request, data)) {
+       return -errno;
+    }
+    return 0;
+}
+
+
+/**
+ * \brief Send a device-specific read command.
+ *
+ * \param fd file descriptor.
+ * \param drmCommandIndex command index 
+ * \param data destination pointer of the data to be read.
+ * \param size size of the data to be read.
+ * 
+ * \return zero on success, or a negative value on failure.
+ *
+ * \internal
+ * It issues a read ioctl given by 
+ * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
+ */
+int drmCommandRead(int fd, unsigned long drmCommandIndex,
+                   void *data, unsigned long size )
+{
+    unsigned long request;
+
+    request = DRM_IOC( DRM_IOC_READ, DRM_IOCTL_BASE, 
+       DRM_COMMAND_BASE + drmCommandIndex, size);
+
+    if (ioctl(fd, request, data)) {
+       return -errno;
+    }
+    return 0;
+}
+
+
+/**
+ * \brief Send a device-specific write command.
+ *
+ * \param fd file descriptor.
+ * \param drmCommandIndex command index 
+ * \param data source pointer of the data to be written.
+ * \param size size of the data to be written.
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * It issues a write ioctl given by 
+ * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
+ */
+int drmCommandWrite(int fd, unsigned long drmCommandIndex,
+                   void *data, unsigned long size )
+{
+    unsigned long request;
+
+    request = DRM_IOC( DRM_IOC_WRITE, DRM_IOCTL_BASE, 
+       DRM_COMMAND_BASE + drmCommandIndex, size);
+
+    if (ioctl(fd, request, data)) {
+       return -errno;
+    }
+    return 0;
+}
+
+
+/**
+ * \brief Send a device-specific read-write command.
+ *
+ * \param fd file descriptor.
+ * \param drmCommandIndex command index 
+ * \param data source pointer of the data to be read and written.
+ * \param size size of the data to be read and written.
+ * 
+ * \return zero on success, or a negative value on failure.
+ * 
+ * \internal
+ * It issues a read-write ioctl given by 
+ * \code DRM_COMMAND_BASE + drmCommandIndex \endcode.
+ */
+int drmCommandWriteRead(int fd, unsigned long drmCommandIndex,
+                   void *data, unsigned long size )
+{
+    unsigned long request;
+
+    request = DRM_IOC( DRM_IOC_READ|DRM_IOC_WRITE, DRM_IOCTL_BASE, 
+       DRM_COMMAND_BASE + drmCommandIndex, size);
+
+    if (ioctl(fd, request, data)) {
+       return -errno;
+    }
+    return 0;
+}
+
diff --git a/src/glx/mini/xf86drm.h b/src/glx/mini/xf86drm.h
new file mode 100644 (file)
index 0000000..cee5ca5
--- /dev/null
@@ -0,0 +1,609 @@
+/* xf86drm.h -- OS-independent header for DRM user-level library interface
+ * Created: Tue Jan  5 08:17:23 1999 by faith@precisioninsight.com
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author: Rickard E. (Rik) Faith <faith@valinux.com>
+ *
+ * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/xf86drm.h,v 1.22 2003/06/12 14:12:35 eich Exp $
+ *
+ */
+
+#ifndef _XF86DRM_H_
+#define _XF86DRM_H_
+
+                               /* Defaults, if nothing set in xf86config */
+#define DRM_DEV_UID     0
+#define DRM_DEV_GID     0
+/* Default /dev/dri directory permissions 0755 */
+#define DRM_DEV_DIRMODE                \
+       (S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
+#define DRM_DEV_MODE    (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
+
+#define DRM_DIR_NAME  "/dev/dri"
+#define DRM_DEV_NAME  "%s/card%d"
+#define DRM_PROC_NAME "/proc/dri/" /* For backware Linux compatibility */
+
+#define DRM_ERR_NO_DEVICE  (-1001)
+#define DRM_ERR_NO_ACCESS  (-1002)
+#define DRM_ERR_NOT_ROOT   (-1003)
+#define DRM_ERR_INVALID    (-1004)
+#define DRM_ERR_NO_FD      (-1005)
+           
+#define DRM_AGP_NO_HANDLE 0
+
+typedef unsigned long drmHandle,   *drmHandlePtr;   /* To mapped regions    */
+typedef unsigned int  drmSize,     *drmSizePtr;            /* For mapped regions   */
+typedef void          *drmAddress, **drmAddressPtr; /* For mapped regions   */
+typedef unsigned int  drmContext,  *drmContextPtr;  /* GLXContext handle    */
+typedef unsigned int  drmDrawable, *drmDrawablePtr; /* Unused               */
+typedef unsigned int  drmMagic,    *drmMagicPtr;    /* Magic for auth       */
+
+typedef struct _drmVersion {
+    int     version_major;        /* Major version                          */
+    int     version_minor;        /* Minor version                          */
+    int     version_patchlevel;   /* Patch level                            */
+    int     name_len;            /* Length of name buffer                  */
+    char    *name;               /* Name of driver                         */
+    int     date_len;             /* Length of date buffer                  */
+    char    *date;                /* User-space buffer to hold date         */
+    int     desc_len;            /* Length of desc buffer                  */
+    char    *desc;                /* User-space buffer to hold desc         */
+} drmVersion, *drmVersionPtr;
+
+typedef struct _drmStats {
+    unsigned long count;            /* Number of data                      */
+    struct {
+       unsigned long value;         /* Value from kernel                   */
+       const char    *long_format;  /* Suggested format for long_name      */
+       const char    *long_name;    /* Long name for value                 */
+       const char    *rate_format;  /* Suggested format for rate_name      */
+       const char    *rate_name;    /* Short name for value per second     */
+       int           isvalue;       /* True if value (vs. counter)         */
+       const char    *mult_names;   /* Multiplier names (e.g., "KGM")      */
+       int           mult;          /* Multiplier value (e.g., 1024)       */
+       int           verbose;       /* Suggest only in verbose output      */
+    } data[15];
+} drmStatsT;
+
+
+                               /* All of these enums *MUST* match with the
+                                   kernel implementation -- so do *NOT*
+                                   change them!  (The drmlib implementation
+                                   will just copy the flags instead of
+                                   translating them.) */
+typedef enum {
+    DRM_FRAME_BUFFER    = 0,      /* WC, no caching, no core dump           */
+    DRM_REGISTERS       = 1,      /* no caching, no core dump               */
+    DRM_SHM             = 2,      /* shared, cached                         */
+    DRM_AGP             = 3,     /* AGP/GART                               */
+    DRM_SCATTER_GATHER  = 4      /* PCI scatter/gather                     */
+} drmMapType;
+
+typedef enum {
+    DRM_RESTRICTED      = 0x0001, /* Cannot be mapped to client-virtual     */
+    DRM_READ_ONLY       = 0x0002, /* Read-only in client-virtual            */
+    DRM_LOCKED          = 0x0004, /* Physical pages locked                  */
+    DRM_KERNEL          = 0x0008, /* Kernel requires access                 */
+    DRM_WRITE_COMBINING = 0x0010, /* Use write-combining, if available      */
+    DRM_CONTAINS_LOCK   = 0x0020, /* SHM page that contains lock            */
+    DRM_REMOVABLE      = 0x0040  /* Removable mapping                      */
+} drmMapFlags;
+
+typedef enum {                  /* These values *MUST* match drm.h         */
+                                /* Flags for DMA buffer dispatch           */
+    DRM_DMA_BLOCK        = 0x01, /* Block until buffer dispatched.  Note,
+                                    the buffer may not yet have been
+                                    processed by the hardware -- getting a
+                                    hardware lock with the hardware
+                                    quiescent will ensure that the buffer
+                                    has been processed.                    */
+    DRM_DMA_WHILE_LOCKED = 0x02, /* Dispatch while lock held                */
+    DRM_DMA_PRIORITY     = 0x04, /* High priority dispatch                  */
+
+                                /* Flags for DMA buffer request            */
+    DRM_DMA_WAIT         = 0x10, /* Wait for free buffers                   */
+    DRM_DMA_SMALLER_OK   = 0x20, /* Smaller-than-requested buffers ok       */
+    DRM_DMA_LARGER_OK    = 0x40  /* Larger-than-requested buffers ok        */
+} drmDMAFlags;
+
+typedef enum {
+    DRM_PAGE_ALIGN       = 0x01,
+    DRM_AGP_BUFFER       = 0x02,
+    DRM_SG_BUFFER        = 0x04
+} drmBufDescFlags;
+
+typedef enum {
+    DRM_LOCK_READY      = 0x01, /* Wait until hardware is ready for DMA */
+    DRM_LOCK_QUIESCENT  = 0x02, /* Wait until hardware quiescent        */
+    DRM_LOCK_FLUSH      = 0x04, /* Flush this context's DMA queue first */
+    DRM_LOCK_FLUSH_ALL  = 0x08, /* Flush all DMA queues first           */
+                               /* These *HALT* flags aren't supported yet
+                                   -- they will be used to support the
+                                   full-screen DGA-like mode. */
+    DRM_HALT_ALL_QUEUES = 0x10, /* Halt all current and future queues   */
+    DRM_HALT_CUR_QUEUES = 0x20  /* Halt all current queues              */
+} drmLockFlags;
+
+typedef enum {
+    DRM_CONTEXT_PRESERVED = 0x01, /* This context is preserved and
+                                    never swapped. */
+    DRM_CONTEXT_2DONLY    = 0x02  /* This context is for 2D rendering only. */
+} drmContextFlags, *drmContextFlagsPtr;
+
+typedef struct _drmBufDesc {
+    int              count;      /* Number of buffers of this size         */
+    int              size;       /* Size in bytes                          */
+    int              low_mark;   /* Low water mark                         */
+    int              high_mark;          /* High water mark                        */
+} drmBufDesc, *drmBufDescPtr;
+
+typedef struct _drmBufInfo {
+    int              count;      /* Number of buffers described in list    */
+    drmBufDescPtr    list;       /* List of buffer descriptions            */
+} drmBufInfo, *drmBufInfoPtr;
+
+typedef struct _drmBuf {
+    int              idx;        /* Index into master buflist              */
+    int              total;      /* Buffer size                            */
+    int              used;       /* Amount of buffer in use (for DMA)      */
+    drmAddress       address;    /* Address                                */
+} drmBuf, *drmBufPtr;
+
+typedef struct _drmBufMap {
+    int              count;      /* Number of buffers mapped               */
+    drmBufPtr        list;       /* Buffers                                */
+} drmBufMap, *drmBufMapPtr;
+
+typedef struct _drmLock {
+    volatile unsigned int lock;
+    char                      padding[60];
+    /* This is big enough for most current (and future?) architectures:
+       DEC Alpha:              32 bytes
+       Intel Merced:           ?
+       Intel P5/PPro/PII/PIII: 32 bytes
+       Intel StrongARM:        32 bytes
+       Intel i386/i486:        16 bytes
+       MIPS:                   32 bytes (?)
+       Motorola 68k:           16 bytes
+       Motorola PowerPC:       32 bytes
+       Sun SPARC:              32 bytes
+    */
+} drmLock, *drmLockPtr;
+
+typedef struct _drmDMAReq {
+                                 /* Indices here refer to the offset into
+                                    list in drmBufInfo                     */
+    drmContext    context;       /* Context handle                         */
+    int           send_count;     /* Number of buffers to send              */
+    int           *send_list;     /* List of handles to buffers             */
+    int           *send_sizes;    /* Lengths of data to send, in bytes      */
+    drmDMAFlags   flags;          /* Flags                                  */
+    int           request_count;  /* Number of buffers requested            */
+    int           request_size;          /* Desired size of buffers requested      */
+    int           *request_list;  /* Buffer information                     */
+    int           *request_sizes; /* Minimum acceptable sizes               */
+    int           granted_count;  /* Number of buffers granted at this size */
+} drmDMAReq, *drmDMAReqPtr;
+
+typedef struct _drmRegion {
+    drmHandle     handle;
+    unsigned int  offset;
+    drmSize       size;
+    drmAddress    map;
+} drmRegion, *drmRegionPtr;
+
+typedef struct _drmTextureRegion {
+    unsigned char next;
+    unsigned char prev;
+    unsigned char in_use;
+    unsigned char padding;     /* Explicitly pad this out                 */
+    unsigned int  age;
+} drmTextureRegion, *drmTextureRegionPtr;
+
+
+typedef struct _drmClipRect {
+    unsigned short     x1; /* Upper left: inclusive */
+    unsigned short     y1;
+    unsigned short     x2; /* Lower right: exclusive */
+    unsigned short     y2;
+} drmClipRect, *drmClipRectPtr;
+
+
+typedef enum {
+    DRM_VBLANK_ABSOLUTE = 0x0,         /* Wait for specific vblank sequence number */
+    DRM_VBLANK_RELATIVE = 0x1,         /* Wait for given number of vblanks */
+    DRM_VBLANK_SIGNAL   = 0x40000000   /* Send signal instead of blocking */
+} drmVBlankSeqType;
+
+typedef struct _drmVBlankReq {
+       drmVBlankSeqType type;
+       unsigned int sequence;
+       unsigned long signal;
+} drmVBlankReq, *drmVBlankReqPtr;
+
+typedef struct _drmVBlankReply {
+       drmVBlankSeqType type;
+       unsigned int sequence;
+       long tval_sec;
+       long tval_usec;
+} drmVBlankReply, *drmVBlankReplyPtr;
+
+typedef union _drmVBlank {
+       drmVBlankReq request;
+       drmVBlankReply reply;
+} drmVBlank, *drmVBlankPtr;
+
+
+
+#define __drm_dummy_lock(lock) (*(__volatile__ unsigned int *)lock)
+
+#define DRM_LOCK_HELD  0x80000000 /* Hardware lock is held                 */
+#define DRM_LOCK_CONT  0x40000000 /* Hardware lock is contended            */
+
+#if defined(__GNUC__) && (__GNUC__ >= 2)
+# if defined(__i386) || defined(__AMD64__)
+                               /* Reflect changes here to drmP.h */
+#define DRM_CAS(lock,old,new,__ret)                                    \
+       do {                                                           \
+                int __dummy;   /* Can't mark eax as clobbered */      \
+               __asm__ __volatile__(                                  \
+                       "lock ; cmpxchg %4,%1\n\t"                     \
+                        "setnz %0"                                     \
+                       : "=d" (__ret),                                \
+                         "=m" (__drm_dummy_lock(lock)),               \
+                          "=a" (__dummy)                               \
+                       : "2" (old),                                   \
+                         "r" (new));                                  \
+       } while (0)
+
+#elif defined(__alpha__)
+
+#define        DRM_CAS(lock, old, new, ret)            \
+       do {                                    \
+               int old32;                      \
+               int cur32;                      \
+               __asm__ __volatile__(           \
+               "       mb\n"                   \
+               "       zap   %4, 0xF0, %0\n"   \
+               "       ldl_l %1, %2\n"         \
+               "       zap   %1, 0xF0, %1\n"   \
+                "       cmpeq %0, %1, %1\n"    \
+                "       beq   %1, 1f\n"                \
+               "       bis   %5, %5, %1\n"     \
+                "       stl_c %1, %2\n"                \
+                "1:     xor   %1, 1, %1\n"     \
+                "       stl   %1, %3"          \
+                : "+r" (old32),                 \
+                 "+&r" (cur32),                \
+                   "=m" (__drm_dummy_lock(lock)),\
+                   "=m" (ret)                  \
+               : "r" (old),                    \
+                 "r" (new));                   \
+       } while(0)
+
+#elif defined(__sparc__)
+
+#define DRM_CAS(lock,old,new,__ret)                            \
+do {   register unsigned int __old __asm("o0");                \
+       register unsigned int __new __asm("o1");                \
+       register volatile unsigned int *__lock __asm("o2");     \
+       __old = old;                                            \
+       __new = new;                                            \
+       __lock = (volatile unsigned int *)lock;                 \
+       __asm__ __volatile__(                                   \
+               /*"cas [%2], %3, %0"*/                          \
+               ".word 0xd3e29008\n\t"                          \
+               /*"membar #StoreStore | #StoreLoad"*/           \
+               ".word 0x8143e00a"                              \
+               : "=&r" (__new)                                 \
+               : "0" (__new),                                  \
+                 "r" (__lock),                                 \
+                 "r" (__old)                                   \
+               : "memory");                                    \
+       __ret = (__new != __old);                               \
+} while(0)
+
+#elif defined(__ia64__)
+
+#if 0
+/* this currently generates bad code (missing stop bits)... */
+#include <ia64intrin.h>
+
+#define DRM_CAS(lock,old,new,__ret)                                          \
+       do {                                                                  \
+               __ret = (__sync_val_compare_and_swap(&__drm_dummy_lock(lock), \
+                                                    (old), (new))            \
+                        != (old));                                           \
+       } while (0)
+
+#else
+#define DRM_CAS(lock,old,new,__ret)                                      \
+       do {                                                              \
+               unsigned int __result, __old = (old);                     \
+               __asm__ __volatile__(                                     \
+                       "mf\n"                                            \
+                       "mov ar.ccv=%2\n"                                 \
+                       ";;\n"                                            \
+                       "cmpxchg4.acq %0=%1,%3,ar.ccv"                    \
+                       : "=r" (__result), "=m" (__drm_dummy_lock(lock))  \
+                       : "r" (__old), "r" (new)                          \
+                       : "memory");                                      \
+               __ret = (__result) != (__old);                            \
+       } while (0)
+
+#endif
+
+#elif defined(__powerpc__)
+
+#define DRM_CAS(lock,old,new,__ret)                    \
+       do {                                            \
+               __asm__ __volatile__(                   \
+                       "sync;"                         \
+                       "0:    lwarx %0,0,%1;"          \
+                       "      xor. %0,%3,%0;"          \
+                       "      bne 1f;"                 \
+                       "      stwcx. %2,0,%1;"         \
+                       "      bne- 0b;"                \
+                       "1:    "                        \
+                       "sync;"                         \
+               : "=&r"(__ret)                          \
+               : "r"(lock), "r"(new), "r"(old)         \
+               : "cr0", "memory");                     \
+       } while (0)
+
+#endif /* architecture */
+#endif /* __GNUC__ >= 2 */
+
+#ifndef DRM_CAS
+#define DRM_CAS(lock,old,new,ret) do { ret=1; } while (0) /* FAST LOCK FAILS */
+#endif
+
+#if defined(__alpha__) || defined(__powerpc__)
+#define DRM_CAS_RESULT(_result)                int _result
+#else
+#define DRM_CAS_RESULT(_result)                char _result
+#endif
+
+#define DRM_LIGHT_LOCK(fd,lock,context)                                \
+       do {                                                           \
+                DRM_CAS_RESULT(__ret);                                 \
+               DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret);     \
+                if (__ret) drmGetLock(fd,context,0);                   \
+        } while(0)
+
+                               /* This one counts fast locks -- for
+                                   benchmarking only. */
+#define DRM_LIGHT_LOCK_COUNT(fd,lock,context,count)                    \
+       do {                                                           \
+                DRM_CAS_RESULT(__ret);                                 \
+               DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret);     \
+                if (__ret) drmGetLock(fd,context,0);                   \
+                else       ++count;                                    \
+        } while(0)
+
+#define DRM_LOCK(fd,lock,context,flags)                                \
+       do {                                                           \
+               if (flags) drmGetLock(fd,context,flags);               \
+               else       DRM_LIGHT_LOCK(fd,lock,context);            \
+       } while(0)
+
+#define DRM_UNLOCK(fd,lock,context)                                    \
+       do {                                                           \
+                DRM_CAS_RESULT(__ret);                                 \
+               DRM_CAS(lock,DRM_LOCK_HELD|context,context,__ret);     \
+                if (__ret) drmUnlock(fd,context);                      \
+        } while(0)
+
+                               /* Simple spin locks */
+#define DRM_SPINLOCK(spin,val)                                         \
+       do {                                                           \
+            DRM_CAS_RESULT(__ret);                                     \
+           do {                                                       \
+               DRM_CAS(spin,0,val,__ret);                             \
+               if (__ret) while ((spin)->lock);                       \
+           } while (__ret);                                           \
+       } while(0)
+
+#define DRM_SPINLOCK_TAKE(spin,val)                                    \
+       do {                                                           \
+            DRM_CAS_RESULT(__ret);                                     \
+            int  cur;                                                  \
+           do {                                                       \
+                cur = (*spin).lock;                                    \
+               DRM_CAS(spin,cur,val,__ret);                           \
+           } while (__ret);                                           \
+       } while(0)
+
+#define DRM_SPINLOCK_COUNT(spin,val,count,__ret)                       \
+       do {                                                           \
+            int  __i;                                                  \
+            __ret = 1;                                                 \
+            for (__i = 0; __ret && __i < count; __i++) {               \
+               DRM_CAS(spin,0,val,__ret);                             \
+               if (__ret) for (;__i < count && (spin)->lock; __i++);  \
+           }                                                          \
+       } while(0)
+
+#define DRM_SPINUNLOCK(spin,val)                                       \
+       do {                                                           \
+            DRM_CAS_RESULT(__ret);                                     \
+            if ((*spin).lock == val) { /* else server stole lock */    \
+               do {                                                   \
+                   DRM_CAS(spin,val,0,__ret);                         \
+               } while (__ret);                                       \
+            }                                                          \
+       } while(0)
+
+/* General user-level programmer's API: unprivileged */
+extern int           drmAvailable(void);
+extern int           drmOpen(const char *name, const char *busid);
+extern int           drmClose(int fd);
+extern drmVersionPtr drmGetVersion(int fd);
+extern drmVersionPtr drmGetLibVersion(int fd);
+extern void          drmFreeVersion(drmVersionPtr);
+extern int           drmGetMagic(int fd, drmMagicPtr magic);
+extern char          *drmGetBusid(int fd);
+extern int           drmGetInterruptFromBusID(int fd, int busnum, int devnum,
+                                             int funcnum);
+extern int           drmGetMap(int fd, int idx, drmHandle *offset,
+                              drmSize *size, drmMapType *type,
+                              drmMapFlags *flags, drmHandle *handle,
+                              int *mtrr);
+extern int           drmGetClient(int fd, int idx, int *auth, int *pid,
+                                 int *uid, unsigned long *magic,
+                                 unsigned long *iocs);
+extern int           drmGetStats(int fd, drmStatsT *stats);
+extern int           drmCommandNone(int fd, unsigned long drmCommandIndex);
+extern int           drmCommandRead(int fd, unsigned long drmCommandIndex,
+                                    void *data, unsigned long size);
+extern int           drmCommandWrite(int fd, unsigned long drmCommandIndex,
+                                     void *data, unsigned long size);
+extern int           drmCommandWriteRead(int fd, unsigned long drmCommandIndex,
+                                         void *data, unsigned long size);
+
+/* General user-level programmer's API: X server (root) only  */
+extern void          drmFreeBusid(const char *busid);
+extern int           drmSetBusid(int fd, const char *busid);
+extern int           drmAuthMagic(int fd, drmMagic magic);
+extern int           drmAddMap(int fd,
+                              drmHandle offset,
+                              drmSize size,
+                              drmMapType type,
+                              drmMapFlags flags,
+                              drmHandlePtr handle);
+extern int          drmRmMap(int fd, drmHandle handle);
+extern int          drmAddContextPrivateMapping(int fd, drmContext ctx_id,
+                                                drmHandle handle);
+
+extern int           drmAddBufs(int fd, int count, int size,
+                               drmBufDescFlags flags,
+                               int agp_offset);
+extern int           drmMarkBufs(int fd, double low, double high);
+extern int           drmCreateContext(int fd, drmContextPtr handle);
+extern int           drmSetContextFlags(int fd, drmContext context,
+                                       drmContextFlags flags);
+extern int           drmGetContextFlags(int fd, drmContext context,
+                                       drmContextFlagsPtr flags);
+extern int           drmAddContextTag(int fd, drmContext context, void *tag);
+extern int           drmDelContextTag(int fd, drmContext context);
+extern void          *drmGetContextTag(int fd, drmContext context);
+extern drmContextPtr drmGetReservedContextList(int fd, int *count);
+extern void          drmFreeReservedContextList(drmContextPtr);
+extern int           drmSwitchToContext(int fd, drmContext context);
+extern int           drmDestroyContext(int fd, drmContext handle);
+extern int           drmCreateDrawable(int fd, drmDrawablePtr handle);
+extern int           drmDestroyDrawable(int fd, drmDrawable handle);
+extern int           drmCtlInstHandler(int fd, int irq);
+extern int           drmCtlUninstHandler(int fd);
+extern int           drmInstallSIGIOHandler(int fd,
+                                           void (*f)(int fd,
+                                                     void *oldctx,
+                                                     void *newctx));
+extern int           drmRemoveSIGIOHandler(int fd);
+
+/* General user-level programmer's API: authenticated client and/or X */
+extern int           drmMap(int fd,
+                           drmHandle handle,
+                           drmSize size,
+                           drmAddressPtr address);
+extern int           drmUnmap(drmAddress address, drmSize size);
+extern drmBufInfoPtr drmGetBufInfo(int fd);
+extern drmBufMapPtr  drmMapBufs(int fd);
+extern int           drmUnmapBufs(drmBufMapPtr bufs);
+extern int           drmDMA(int fd, drmDMAReqPtr request);
+extern int           drmFreeBufs(int fd, int count, int *list);
+extern int           drmGetLock(int fd,
+                               drmContext context,
+                               drmLockFlags flags);
+extern int           drmUnlock(int fd, drmContext context);
+extern int           drmFinish(int fd, int context, drmLockFlags flags);
+extern int          drmGetContextPrivateMapping(int fd, drmContext ctx_id, 
+                                                drmHandlePtr handle);
+
+/* AGP/GART support: X server (root) only */
+extern int           drmAgpAcquire(int fd);
+extern int           drmAgpRelease(int fd);
+extern int           drmAgpEnable(int fd, unsigned long mode);
+extern int           drmAgpAlloc(int fd, unsigned long size,
+                                unsigned long type, unsigned long *address,
+                                unsigned long *handle);
+extern int           drmAgpFree(int fd, unsigned long handle);
+extern int          drmAgpBind(int fd, unsigned long handle,
+                               unsigned long offset);
+extern int           drmAgpUnbind(int fd, unsigned long handle);
+
+/* AGP/GART info: authenticated client and/or X */
+extern int           drmAgpVersionMajor(int fd);
+extern int           drmAgpVersionMinor(int fd);
+extern unsigned long drmAgpGetMode(int fd);
+extern unsigned long drmAgpBase(int fd); /* Physical location */
+extern unsigned long drmAgpSize(int fd); /* Bytes */
+extern unsigned long drmAgpMemoryUsed(int fd);
+extern unsigned long drmAgpMemoryAvail(int fd);
+extern unsigned int  drmAgpVendorId(int fd);
+extern unsigned int  drmAgpDeviceId(int fd);
+
+/* PCI scatter/gather support: X server (root) only */
+extern int           drmScatterGatherAlloc(int fd, unsigned long size,
+                                          unsigned long *handle);
+extern int           drmScatterGatherFree(int fd, unsigned long handle);
+
+extern int           drmWaitVBlank(int fd, drmVBlankPtr vbl);
+
+/* Support routines */
+extern int           drmError(int err, const char *label);
+extern void          *drmMalloc(int size);
+extern void          drmFree(void *pt);
+
+/* Hash table routines */
+extern void *drmHashCreate(void);
+extern int  drmHashDestroy(void *t);
+extern int  drmHashLookup(void *t, unsigned long key, void **value);
+extern int  drmHashInsert(void *t, unsigned long key, void *value);
+extern int  drmHashDelete(void *t, unsigned long key);
+extern int  drmHashFirst(void *t, unsigned long *key, void **value);
+extern int  drmHashNext(void *t, unsigned long *key, void **value);
+
+/* PRNG routines */
+extern void          *drmRandomCreate(unsigned long seed);
+extern int           drmRandomDestroy(void *state);
+extern unsigned long drmRandom(void *state);
+extern double        drmRandomDouble(void *state);
+
+/* Skip list routines */
+
+extern void *drmSLCreate(void);
+extern int  drmSLDestroy(void *l);
+extern int  drmSLLookup(void *l, unsigned long key, void **value);
+extern int  drmSLInsert(void *l, unsigned long key, void *value);
+extern int  drmSLDelete(void *l, unsigned long key);
+extern int  drmSLNext(void *l, unsigned long *key, void **value);
+extern int  drmSLFirst(void *l, unsigned long *key, void **value);
+extern void drmSLDump(void *l);
+extern int  drmSLLookupNeighbors(void *l, unsigned long key,
+                                unsigned long *prev_key, void **prev_value,
+                                unsigned long *next_key, void **next_value);
+
+#endif
index c672cce47a5f1e0cfeb72449be9bd66163b8b961..d014936d3661bb9d3748c8fd6c71e9fcec7c7121 100644 (file)
@@ -296,7 +296,7 @@ default:
        @echo "Specify a target configuration"
 
 
-targets: $(LIBDIR)/$(GL_LIB) $(LIBDIR)/$(OSMESA_LIB)
+targets: $(LIBDIR)/$(GL_LIB) $(LIBDIR)/$(OSMESA_LIB) $(LIBMESA)
 
 
 # Make the GL library
@@ -321,7 +321,9 @@ libmesa: $(LIBDIR)/$(MESA_LIB)
 
 $(LIBDIR)/$(MESA_LIB): $(CORE_OBJECTS)
 
-
+mesa.a:        $(CORE_OBJECTS)
+       rm -f $@ && ar rcv $@ $(CORE_OBJECTS) && ranlib $@
+  
 # Run 'make -f Makefile.X11 dep' to update the dependencies if you change
 # what's included by any source file.
 dep: $(CORE_SOURCES) $(DRIVER_SOURCES) $(OSMESA_DRIVER_SOURCES) $(ASM_SOURCES)
@@ -336,9 +338,9 @@ tags:
 
 # Remove .o and backup files
 clean:
+       -rm *.a
        -rm -f */*.o */*~ */*.o */*~
        -rm -f drivers/*/*.o
-       -rm -f drivers/dri/*/*.o
 
 
 include $(TOP)/Make-config
diff --git a/src/mesa/drivers/dri/mga/Doxyfile b/src/mesa/drivers/dri/mga/Doxyfile
new file mode 100644 (file)
index 0000000..0d0c134
--- /dev/null
@@ -0,0 +1,234 @@
+# Doxyfile 1.3.3-Gideon
+
+#---------------------------------------------------------------------------
+# General configuration options
+#---------------------------------------------------------------------------
+PROJECT_NAME           = mga
+PROJECT_NUMBER         = $VERSION$
+OUTPUT_DIRECTORY       = 
+OUTPUT_LANGUAGE        = English
+USE_WINDOWS_ENCODING   = NO
+EXTRACT_ALL            = NO
+EXTRACT_PRIVATE        = NO
+EXTRACT_STATIC         = NO
+EXTRACT_LOCAL_CLASSES  = YES
+HIDE_UNDOC_MEMBERS     = NO
+HIDE_UNDOC_CLASSES     = NO
+HIDE_FRIEND_COMPOUNDS  = NO
+HIDE_IN_BODY_DOCS      = NO
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ALWAYS_DETAILED_SEC    = NO
+INLINE_INHERITED_MEMB  = NO
+FULL_PATH_NAMES        = NO
+STRIP_FROM_PATH        = 
+INTERNAL_DOCS          = NO
+CASE_SENSE_NAMES       = YES
+SHORT_NAMES            = NO
+HIDE_SCOPE_NAMES       = NO
+SHOW_INCLUDE_FILES     = YES
+JAVADOC_AUTOBRIEF      = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP         = NO
+INHERIT_DOCS           = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = YES
+DISTRIBUTE_GROUP_DOC   = NO
+TAB_SIZE               = 8
+GENERATE_TODOLIST      = YES
+GENERATE_TESTLIST      = YES
+GENERATE_BUGLIST       = YES
+GENERATE_DEPRECATEDLIST= YES
+ALIASES                = 
+ENABLED_SECTIONS       = 
+MAX_INITIALIZER_LINES  = 30
+OPTIMIZE_OUTPUT_FOR_C  = NO
+OPTIMIZE_OUTPUT_JAVA   = NO
+SHOW_USED_FILES        = YES
+SUBGROUPING            = YES
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = NO
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_IF_DOC_ERROR      = YES
+WARN_FORMAT            = "$file:$line: $text"
+WARN_LOGFILE           = 
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT                  = /home/newtree/temp/src/mesa/drivers/dri/mga
+FILE_PATTERNS          = *.c \
+                         *.cc \
+                         *.cxx \
+                         *.cpp \
+                         *.c++ \
+                         *.java \
+                         *.ii \
+                         *.ixx \
+                         *.ipp \
+                         *.i++ \
+                         *.inl \
+                         *.h \
+                         *.hh \
+                         *.hxx \
+                         *.hpp \
+                         *.h++ \
+                         *.idl \
+                         *.odl \
+                         *.cs \
+                         *.C \
+                         *.H \
+                         *.tlh \
+                         *.diff \
+                         *.patch \
+                         *.moc \
+                         *.xpm \
+                         *.dox
+RECURSIVE              = yes
+EXCLUDE                = 
+EXCLUDE_SYMLINKS       = NO
+EXCLUDE_PATTERNS       = 
+EXAMPLE_PATH           = 
+EXAMPLE_PATTERNS       = *
+EXAMPLE_RECURSIVE      = NO
+IMAGE_PATH             = 
+INPUT_FILTER           = 
+FILTER_SOURCE_FILES    = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER         = NO
+INLINE_SOURCES         = NO
+STRIP_CODE_COMMENTS    = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION    = YES
+VERBATIM_HEADERS       = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = NO
+COLS_IN_ALPHA_INDEX    = 5
+IGNORE_PREFIX          = 
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML          = YES
+HTML_OUTPUT            = html
+HTML_FILE_EXTENSION    = .html
+HTML_HEADER            = 
+HTML_FOOTER            = 
+HTML_STYLESHEET        = 
+HTML_ALIGN_MEMBERS     = YES
+GENERATE_HTMLHELP      = NO
+CHM_FILE               = 
+HHC_LOCATION           = 
+GENERATE_CHI           = NO
+BINARY_TOC             = NO
+TOC_EXPAND             = NO
+DISABLE_INDEX          = NO
+ENUM_VALUES_PER_LINE   = 4
+GENERATE_TREEVIEW      = NO
+TREEVIEW_WIDTH         = 250
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX         = YES
+LATEX_OUTPUT           = latex
+LATEX_CMD_NAME         = latex
+MAKEINDEX_CMD_NAME     = makeindex
+COMPACT_LATEX          = NO
+PAPER_TYPE             = a4wide
+EXTRA_PACKAGES         = 
+LATEX_HEADER           = 
+PDF_HYPERLINKS         = NO
+USE_PDFLATEX           = NO
+LATEX_BATCHMODE        = NO
+LATEX_HIDE_INDICES     = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF           = NO
+RTF_OUTPUT             = rtf
+COMPACT_RTF            = NO
+RTF_HYPERLINKS         = NO
+RTF_STYLESHEET_FILE    = 
+RTF_EXTENSIONS_FILE    = 
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = NO
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3
+MAN_LINKS              = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML           = yes
+XML_OUTPUT             = xml
+XML_SCHEMA             = 
+XML_DTD                = 
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF   = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD       = NO
+PERLMOD_LATEX          = NO
+PERLMOD_PRETTY         = YES
+PERLMOD_MAKEVAR_PREFIX = 
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = NO
+EXPAND_ONLY_PREDEF     = NO
+SEARCH_INCLUDES        = YES
+INCLUDE_PATH           = 
+INCLUDE_FILE_PATTERNS  = 
+PREDEFINED             = 
+EXPAND_AS_DEFINED      = 
+SKIP_FUNCTION_MACROS   = YES
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references   
+#---------------------------------------------------------------------------
+TAGFILES               = 
+GENERATE_TAGFILE       = 
+ALLEXTERNALS           = NO
+EXTERNAL_GROUPS        = YES
+PERL_PATH              = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS         = YES
+HIDE_UNDOC_RELATIONS   = YES
+HAVE_DOT               = NO
+CLASS_GRAPH            = YES
+COLLABORATION_GRAPH    = YES
+UML_LOOK               = NO
+TEMPLATE_RELATIONS     = NO
+INCLUDE_GRAPH          = YES
+INCLUDED_BY_GRAPH      = YES
+CALL_GRAPH             = NO
+GRAPHICAL_HIERARCHY    = YES
+DOT_IMAGE_FORMAT       = png
+DOT_PATH               = 
+DOTFILE_DIRS           = 
+MAX_DOT_GRAPH_WIDTH    = 1024
+MAX_DOT_GRAPH_HEIGHT   = 1024
+MAX_DOT_GRAPH_DEPTH    = 1000
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine   
+#---------------------------------------------------------------------------
+SEARCHENGINE           = NO
+CGI_NAME               = search.cgi
+CGI_URL                = 
+DOC_URL                = 
+DOC_ABSPATH            = 
+BIN_ABSPATH            = /usr/local/bin/
+EXT_DOC_PATHS          = 
index c69d6e5989e0ab140b1eb2ffa4c02ccc4887da9b..0dce6e7b1a787ee81862729977408b1b4d2f95e9 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: Makefile.X11,v 1.1 2003/08/06 18:01:13 keithw Exp $
+# $Id: Makefile.X11,v 1.2 2003/08/22 20:11:44 brianp Exp $
 
 # Mesa 3-D graphics library
 # Version:  5.0
@@ -6,8 +6,10 @@
 
 TOP = ../../../../..
 
+default: linux-solo
+
 SHARED_INCLUDES = $(INCLUDE_DIRS) -I. -I../common -Iserver
-MINIGLX_INCLUDES = -I$(TOP)/src/miniglx 
+MINIGLX_INCLUDES = -I$(TOP)/src/glx/mini
 
 DEFINES += \
        -D_HAVE_SWRAST=1 \
@@ -16,24 +18,27 @@ DEFINES += \
        -D_HAVE_CODEGEN=1 \
        -D_HAVE_LIGHTING=1 \
        -D_HAVE_TEXGEN=1 \
-       -D_HAVE_USERCLIP=1
+       -D_HAVE_USERCLIP=1 \
+       -DGLX_DIRECT_RENDERING
 
 MINIGLX_SOURCES = server/mga_dri.c 
 
-DRIVER_SOURCES = mgabuffers.c \
-                mgadd.c \
+DRIVER_SOURCES = mgadd.c \
                 mgaioctl.c \
                 mgarender.c \
                 mgastate.c \
                 mgatris.c \
-                ../common/mm.c 
+                ../common/mm.c \
+                ../common/utils.c \
+                ../common/texmem.c \
+                ../common/vblank.c
 
 FULL_DRIVER_SOURCES =  \
                 mgapixel.c \
                 mgaspan.c \
                 mgatex.c \
-                mgatexcnv.c \
                 mgatexmem.c \
+                mga_texstate.c \
                 mgavb.c \
                 mga_xmesa.c
 
@@ -54,7 +59,7 @@ WINOBJ=$(MESABUILDDIR)/dri/dri.a
 WINLIB=
 else
 WINOBJ=
-WINLIB=-L$(MESA)/src/miniglx
+WINLIB=-L$(MESA)/src/glx/mini
 endif
 
 ASM_SOURCES = 
@@ -87,7 +92,7 @@ INCLUDE_DIRS = \
 
 ##### TARGETS #####
 
-targets: mga_dri.so
+targets: depend mga_dri.so
 
 mga_dri.so:  $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile.X11
        rm -f $@ && gcc -o $@ -shared $(OBJECTS) $(MESA_MODULES) $(WINOBJ) $(WINLIB) -lc -lm
@@ -96,7 +101,7 @@ mga_dri.so:  $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile.X11
 
 # Run 'make -f Makefile.X11 dep' to update the dependencies if you change
 # what's included by any source file.
-dep: $(C_SOURCES) $(ASM_SOURCES)
+depend: $(C_SOURCES) $(ASM_SOURCES)
        makedepend -fdepend -Y $(SHARED_INCLUDES) \
                $(C_SOURCES) $(ASM_SOURCES)
 
@@ -108,7 +113,7 @@ tags:
 
 # Remove .o and backup files
 clean:
-       -rm -f *.o *~ *.o *~ *.so
+       -rm -f *.o *~ *.o *~ *.so server/*.o
 
 
 include $(TOP)/Make-config
diff --git a/src/mesa/drivers/dri/mga/mga_texstate.c b/src/mesa/drivers/dri/mga/mga_texstate.c
new file mode 100644 (file)
index 0000000..fc1406c
--- /dev/null
@@ -0,0 +1,747 @@
+/*
+ * Copyright 2000-2001 VA Linux Systems, Inc.
+ * (c) Copyright IBM Corporation 2002
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Ian Romanick <idr@us.ibm.com>
+ *    Keith Whitwell <keithw@tungstengraphics.com>
+ */
+/* $XFree86:$ */
+
+#include "mm.h"
+#include "mgacontext.h"
+#include "mgatex.h"
+#include "mgaregs.h"
+#include "mgatris.h"
+#include "mgaioctl.h"
+
+#include "context.h"
+#include "enums.h"
+#include "macros.h"
+#include "imports.h"
+
+#include "simple_list.h"
+#include "texformat.h"
+
+#define MGA_USE_TABLE_FOR_FORMAT
+#ifdef MGA_USE_TABLE_FOR_FORMAT
+#define TMC_nr_tformat (MESA_FORMAT_YCBCR_REV + 1)
+static const unsigned TMC_tformat[ TMC_nr_tformat ] =
+{
+    [MESA_FORMAT_ARGB8888] = TMC_tformat_tw32 | TMC_takey_1 | TMC_tamask_0,
+    [MESA_FORMAT_RGB565]   = TMC_tformat_tw16 | TMC_takey_1 | TMC_tamask_0,
+    [MESA_FORMAT_ARGB4444] = TMC_tformat_tw12 | TMC_takey_1 | TMC_tamask_0,
+    [MESA_FORMAT_ARGB1555] = TMC_tformat_tw15 | TMC_takey_1 | TMC_tamask_0,
+    [MESA_FORMAT_CI8]      = TMC_tformat_tw8  | TMC_takey_1 | TMC_tamask_0,
+    [MESA_FORMAT_YCBCR]     = TMC_tformat_tw422uyvy | TMC_takey_1 | TMC_tamask_0,
+    [MESA_FORMAT_YCBCR_REV] = TMC_tformat_tw422 | TMC_takey_1 | TMC_tamask_0,
+};
+#endif
+
+static void
+mgaSetTexImages( mgaContextPtr mmesa,
+                const struct gl_texture_object * tObj )
+{
+    mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
+    struct gl_texture_image *baseImage = tObj->Image[ tObj->BaseLevel ];
+    GLint totalSize;
+    GLint width, height;
+    GLint i;
+    GLint firstLevel, lastLevel, numLevels;
+    GLint log2Width, log2Height;
+    GLuint txformat = 0;
+    GLint ofs;
+
+    /* Set the hardware texture format
+     */
+#ifndef MGA_USE_TABLE_FOR_FORMAT
+    switch (baseImage->TexFormat->MesaFormat) {
+
+       case MESA_FORMAT_ARGB8888: txformat = TMC_tformat_tw32; break;
+       case MESA_FORMAT_RGB565:   txformat = TMC_tformat_tw16; break;
+       case MESA_FORMAT_ARGB4444: txformat = TMC_tformat_tw12; break;
+       case MESA_FORMAT_ARGB1555: txformat = TMC_tformat_tw15; break;
+       case MESA_FORMAT_CI8:      txformat = TMC_tformat_tw8;  break;
+        case MESA_FORMAT_YCBCR:    txformat  = TMC_tformat_tw422uyvy; break;
+        case MESA_FORMAT_YCBCR_REV: txformat = TMC_tformat_tw422; break;
+
+       default:
+       _mesa_problem(NULL, "unexpected texture format in %s", __FUNCTION__);
+       return;
+    }
+#else
+    if ( (baseImage->TexFormat->MesaFormat >= TMC_nr_tformat)
+        || (TMC_tformat[ baseImage->TexFormat->MesaFormat ] == 0) )
+    {
+       _mesa_problem(NULL, "unexpected texture format in %s", __FUNCTION__);
+       return;
+    }
+
+    txformat = TMC_tformat[ baseImage->TexFormat->MesaFormat ];
+
+#endif /* MGA_USE_TABLE_FOR_FORMAT */
+
+   if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
+      /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
+       */
+
+      firstLevel = lastLevel = tObj->BaseLevel;
+   } else {
+      /* Compute which mipmap levels we really want to send to the hardware.
+       * This depends on the base image size, GL_TEXTURE_MIN_LOD,
+       * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
+       * Yes, this looks overly complicated, but it's all needed.
+       */
+
+      firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
+      firstLevel = MAX2(firstLevel, tObj->BaseLevel);
+      lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
+      lastLevel = MAX2(lastLevel, tObj->BaseLevel);
+      lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
+      lastLevel = MIN2(lastLevel, tObj->MaxLevel);
+      lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
+   }
+
+   log2Width = tObj->Image[firstLevel]->WidthLog2;
+   log2Height = tObj->Image[firstLevel]->HeightLog2;
+   width = tObj->Image[firstLevel]->Width;
+   height = tObj->Image[firstLevel]->Height;
+
+   numLevels = MIN2( lastLevel - firstLevel + 1,
+                     MGA_IS_G200(mmesa) ? G200_TEX_MAXLEVELS : G400_TEX_MAXLEVELS);
+
+
+   totalSize = 0;
+   for ( i = 0 ; i < numLevels ; i++ ) {
+      const struct gl_texture_image * const texImage = tObj->Image[i+firstLevel];
+
+      if ( (texImage == NULL)
+          || ((i != 0)
+              && ((texImage->Width < 8) || (texImage->Height < 8))) ) {
+        break;
+      }
+
+      t->offsets[i] = totalSize;
+      t->base.dirty_images[0] |= (1<<i);
+
+      totalSize += ((MAX2( texImage->Width, 8 ) *
+                     MAX2( texImage->Height, 8 ) *
+                     baseImage->TexFormat->TexelBytes) + 31) & ~31;
+   }
+
+   numLevels = i;
+   lastLevel = firstLevel + numLevels - 1;
+
+   /* save these values */
+   t->base.firstLevel = firstLevel;
+   t->base.lastLevel = lastLevel;
+
+   t->base.totalSize = totalSize;
+
+   /* setup hardware register values */
+   t->setup.texctl &= (TMC_tformat_MASK & TMC_tpitch_MASK 
+                      & TMC_tpitchext_MASK);
+   t->setup.texctl |= txformat;
+
+
+   /* Set the texture width.  In order to support non-power of 2 textures and
+    * textures larger than 1024 texels wide, "linear" pitch must be used.  For
+    * the linear pitch, if the width is 2048, a value of zero is used.
+    */
+
+   t->setup.texctl |= TMC_tpitchlin_enable;
+   t->setup.texctl |= (width & (2048 - 1)) << TMC_tpitchext_SHIFT;
+
+
+   /* G400 specifies the number of mip levels in a strange way.  Since there
+    * are up to 12 levels, it requires 4 bits.  Three of the bits are at the
+    * high end of TEXFILTER.  The other bit is in the middle.  Weird.
+    */
+
+   t->setup.texfilter &= TF_mapnb_MASK & TF_mapnbhigh_MASK & TF_reserved_MASK;
+   t->setup.texfilter |= (((numLevels-1) & 0x07) << (TF_mapnb_SHIFT));
+   t->setup.texfilter |= (((numLevels-1) & 0x08) << (TF_mapnbhigh_SHIFT - 3));
+
+   /* warp texture registers */
+   ofs = MGA_IS_G200(mmesa) ? 28 : 11;
+
+   t->setup.texwidth = (MGA_FIELD(TW_twmask, width - 1) |
+                       MGA_FIELD(TW_rfw, (10 - log2Width - 8) & 63 ) |
+                       MGA_FIELD(TW_tw, (log2Width + ofs ) | 0x40 ));
+
+   t->setup.texheight = (MGA_FIELD(TH_thmask, height - 1) |
+                        MGA_FIELD(TH_rfh, (10 - log2Height - 8) & 63 ) |
+                        MGA_FIELD(TH_th, (log2Height + ofs ) | 0x40 ));
+
+   mgaUploadTexImages( mmesa, t );
+}
+
+
+/* ================================================================
+ * Texture unit state management
+ */
+
+static void mgaUpdateTextureEnvG200( GLcontext *ctx, GLuint unit )
+{
+   struct gl_texture_object *tObj = ctx->Texture.Unit[0]._Current;
+   mgaTextureObjectPtr t;
+
+   if (!tObj || !tObj->DriverData)
+      return;
+
+   t = (mgaTextureObjectPtr)tObj->DriverData;
+
+   t->setup.texctl2 &= ~TMC_decalblend_enable;
+
+   switch (ctx->Texture.Unit[0].EnvMode) {
+   case GL_REPLACE:
+      t->setup.texctl &= ~TMC_tmodulate_enable;
+      break;
+   case GL_MODULATE:
+      t->setup.texctl |= TMC_tmodulate_enable;
+      break;
+   case GL_DECAL:
+      t->setup.texctl &= ~TMC_tmodulate_enable;
+      t->setup.texctl2 |= TMC_decalblend_enable;
+      break;
+   case GL_BLEND:
+      FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
+      break;
+   default:
+      break;
+   }
+}
+
+
+#define MGA_DISABLE            0
+#define MGA_REPLACE            1
+#define MGA_MODULATE           2
+#define MGA_DECAL              3
+#define MGA_BLEND              4
+#define MGA_ADD                        5
+#define MGA_MAX_COMBFUNC       6
+
+static const GLuint g400_color_combine[][MGA_MAX_COMBFUNC] =
+{
+   /* Unit 0:
+    */
+   {
+      /* Disable combiner stage
+       */
+      (0),
+
+      /* GL_REPLACE
+       */
+      (TD0_color_sel_arg1 |
+       TD0_alpha_arg2_diffuse |
+       TD0_alpha_sel_arg2 ),
+      
+      /* GL_MODULATE
+       */
+      (TD0_color_arg2_diffuse |
+       TD0_color_sel_mul |
+       TD0_alpha_arg2_diffuse |
+       TD0_alpha_sel_mul),
+      
+      /* GL_DECAL
+       */
+      (TD0_color_sel_arg1 |
+       TD0_alpha_arg2_diffuse |
+       TD0_alpha_sel_arg2),
+      
+      /* GL_BLEND
+       */
+      (0),
+      
+      /* GL_ADD
+       */
+      (TD0_color_arg2_diffuse |
+       TD0_color_add_add |
+       TD0_color_sel_add |
+       TD0_alpha_arg2_diffuse |
+       TD0_alpha_sel_mul),
+   },
+   
+   /* Unit 1:
+    */
+   {
+      /* Disable combiner stage
+       */
+      (0),
+       
+      /* GL_REPLACE
+       */
+      (TD0_color_sel_arg1 |
+       TD0_alpha_arg2_diffuse |
+       TD0_alpha_sel_arg2 ),
+      
+      /* GL_MODULATE
+       */
+      (TD0_color_arg2_prevstage |
+       TD0_color_alpha_prevstage |
+       TD0_color_sel_mul |
+       TD0_alpha_arg2_prevstage |
+       TD0_alpha_sel_mul),
+
+      /* GL_DECAL
+       */
+      (TD0_color_sel_arg1 |
+       TD0_alpha_arg2_prevstage |
+       TD0_alpha_sel_arg2 ),
+      
+      /* GL_BLEND
+       */
+      (0),
+      
+      /* GL_ADD
+       */
+      (TD0_color_arg2_prevstage |
+       TD0_color_alpha_prevstage |
+       TD0_color_add_add |
+       TD0_color_sel_add |
+       TD0_alpha_arg2_prevstage |
+       TD0_alpha_sel_mul),
+   },
+};
+
+static const GLuint g400_alpha_combine[][MGA_MAX_COMBFUNC] =
+{
+   /* Unit 0:
+    */
+   {
+      /* Disable combiner stage
+       */
+      (0),
+
+      /* GL_REPLACE
+       */
+      (TD0_color_sel_arg2 |
+       TD0_color_arg2_diffuse |
+       TD0_alpha_sel_arg1 ),
+      
+      /* GL_MODULATE
+       * FIXME: Is this correct?
+       */
+      (TD0_color_arg2_diffuse |
+       TD0_color_sel_mul |
+       TD0_alpha_arg2_diffuse |
+       TD0_alpha_sel_mul),
+
+      /* GL_DECAL
+       */
+      (TD0_color_arg2_diffuse |
+       TD0_color_sel_arg2 |
+       TD0_alpha_arg2_diffuse |
+       TD0_alpha_sel_arg2),
+
+      /* GL_BLEND
+       */
+      (TD0_color_arg2_diffuse |
+       TD0_color_sel_mul |
+       TD0_alpha_arg2_diffuse |
+       TD0_alpha_sel_mul),
+
+      /* GL_ADD
+       */
+      (TD0_color_arg2_diffuse |
+       TD0_color_sel_mul |
+       TD0_alpha_arg2_diffuse |
+       TD0_alpha_sel_mul),
+   },
+
+   /* Unit 1:
+    */
+   {
+      /* Disable combiner stage
+       */
+      (0),
+
+      /* GL_REPLACE
+       */
+      (TD0_color_sel_arg2 |
+       TD0_color_arg2_diffuse |
+       TD0_alpha_sel_arg1 ),
+      
+      /* GL_MODULATE
+       * FIXME: Is this correct?
+       */
+      (TD0_color_arg2_prevstage |
+       TD0_color_alpha_prevstage |
+       TD0_color_sel_mul |
+       TD0_alpha_arg2_prevstage |
+       TD0_alpha_sel_mul),
+
+      /* GL_DECAL
+       */
+      (TD0_color_arg2_prevstage |
+       TD0_color_sel_arg2 |
+       TD0_alpha_arg2_prevstage |
+       TD0_alpha_sel_arg2),
+
+      /* GL_BLEND
+       */
+      (TD0_color_arg2_diffuse |
+       TD0_color_sel_mul |
+       TD0_alpha_arg2_diffuse |
+       TD0_alpha_sel_mul),
+
+      /* GL_ADD
+       */
+      (TD0_color_arg2_prevstage |
+       TD0_color_sel_mul |
+       TD0_alpha_arg2_prevstage |
+       TD0_alpha_sel_mul),
+   },
+};
+
+static void mgaUpdateTextureEnvG400( GLcontext *ctx, GLuint unit )
+{
+   mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+   const int source = mmesa->tmu_source[unit];
+   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
+   const struct gl_texture_object *tObj = texUnit->_Current;
+   GLuint *reg = ((GLuint *)&mmesa->setup.tdualstage0 + unit);
+   GLenum format;
+
+   if ( tObj != ctx->Texture.Unit[source].Current2D || !tObj ) 
+      return;
+
+   format = tObj->Image[tObj->BaseLevel]->Format;
+
+   switch (ctx->Texture.Unit[source].EnvMode) {
+   case GL_REPLACE:
+      if (format == GL_RGB || format == GL_LUMINANCE) {
+        *reg = g400_color_combine[unit][MGA_REPLACE];
+      }
+      else if (format == GL_ALPHA) {
+         *reg = g400_alpha_combine[unit][MGA_REPLACE];
+      }
+      else {
+         *reg = (TD0_color_sel_arg1 |
+                 TD0_alpha_sel_arg1 );
+      }
+      break;
+
+   case GL_MODULATE:
+      *reg = g400_color_combine[unit][MGA_MODULATE];
+      break;
+   case GL_DECAL:
+      if (format == GL_RGB) {
+        *reg = g400_color_combine[unit][MGA_DECAL];
+      }
+      else if ( format == GL_RGBA ) {
+#if 0
+         if (unit == 0) {
+            /* this doesn't work */
+            *reg = (TD0_color_arg2_diffuse |
+                    TD0_color_alpha_currtex |
+                    TD0_color_alpha2inv_enable |
+                    TD0_color_arg2mul_alpha2 |
+                    TD0_color_arg1mul_alpha1 |
+                    TD0_color_blend_enable |
+                    TD0_color_arg1add_mulout |
+                    TD0_color_arg2add_mulout |
+                    TD0_color_add_add |
+                    TD0_color_sel_mul |
+                    TD0_alpha_arg2_diffuse |
+                    TD0_alpha_sel_arg2 );
+         }
+         else {
+            *reg = (TD0_color_arg2_prevstage |
+                    TD0_color_alpha_currtex |
+                    TD0_color_alpha2inv_enable |
+                    TD0_color_arg2mul_alpha2 |
+                    TD0_color_arg1mul_alpha1 |
+                    TD0_color_add_add |
+                    TD0_color_sel_add |
+                    TD0_alpha_arg2_prevstage |
+                    TD0_alpha_sel_arg2 );
+         }
+#else
+         /* s/w fallback, pretty sure we can't do in h/w */
+        FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
+        if ( MGA_DEBUG & DEBUG_VERBOSE_FALLBACK )
+           fprintf( stderr, "FALLBACK: GL_DECAL RGBA texture, unit=%d\n",
+                    unit );
+#endif
+      }
+      else {
+       *reg = g400_alpha_combine[unit][MGA_DECAL];
+      }
+      break;
+
+   case GL_ADD:
+     if (format == GL_INTENSITY) {
+       if (unit == 0) {
+          *reg = ( TD0_color_arg2_diffuse |
+                  TD0_color_add_add |
+                  TD0_color_sel_add |
+                  TD0_alpha_arg2_diffuse |
+                  TD0_alpha_add_enable |
+                  TD0_alpha_sel_add);
+       }
+       else {
+          *reg = ( TD0_color_arg2_prevstage |
+                  TD0_color_add_add |
+                  TD0_color_sel_add |
+                  TD0_alpha_arg2_prevstage |
+                  TD0_alpha_add_enable |
+                  TD0_alpha_sel_add);
+       }
+     }      
+     else if (format == GL_ALPHA) {
+       *reg = g400_alpha_combine[unit][MGA_ADD];
+     }
+     else {
+       *reg = g400_color_combine[unit][MGA_ADD];
+     }
+     break;
+
+   case GL_BLEND:
+      if (format == GL_ALPHA) {
+        *reg = g400_alpha_combine[unit][MGA_BLEND];
+      }
+      else {
+        FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
+        if ( MGA_DEBUG & DEBUG_VERBOSE_FALLBACK )
+           fprintf( stderr, "FALLBACK: GL_BLEND envcolor=0x%08x\n",
+                    mmesa->envcolor );
+
+         /* Do singletexture GL_BLEND with 'all ones' env-color
+          * by using both texture units.  Multitexture gl_blend
+          * is a fallback.
+          */
+         if (unit == 0) {
+            /* Part 1: R1 = Rf ( 1 - Rt )
+             *         A1 = Af At
+             */
+            *reg = ( TD0_color_arg2_diffuse |
+                     TD0_color_arg1_inv_enable |
+                     TD0_color_sel_mul |
+                     TD0_alpha_arg2_diffuse |
+                     TD0_alpha_sel_arg1);
+         } else {
+            /* Part 2: R2 = R1 + Rt
+             *         A2 = A1
+             */
+            *reg = ( TD0_color_arg2_prevstage |
+                     TD0_color_add_add |
+                     TD0_color_sel_add |
+                     TD0_alpha_arg2_prevstage |
+                     TD0_alpha_sel_arg2);
+         }
+      }
+      break;
+   default:
+      break;
+   }
+}
+
+
+static void disable_tex( GLcontext *ctx, int unit )
+{
+   mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+
+   /* Texture unit disabled */
+
+   if ( mmesa->CurrentTexObj[unit] != NULL ) {
+      /* The old texture is no longer bound to this texture unit.
+       * Mark it as such.
+       */
+
+      mmesa->CurrentTexObj[unit]->base.bound &= ~(1UL << unit);
+      mmesa->CurrentTexObj[unit] = NULL;
+   }
+
+   if ( unit != 0 ) {
+      mmesa->setup.tdualstage1 = mmesa->setup.tdualstage0;
+   }
+
+   if ( ctx->Texture._EnabledUnits == 0 ) {
+      mmesa->setup.dwgctl &= DC_opcod_MASK;
+      mmesa->setup.dwgctl |= DC_opcod_trap;
+      mmesa->hw.alpha_sel = AC_alphasel_diffused;
+   }
+
+   mmesa->dirty |= MGA_UPLOAD_CONTEXT | (MGA_UPLOAD_TEX0 << unit);
+}
+
+static GLboolean enable_tex_2d( GLcontext *ctx, int unit )
+{
+   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+   const int source = mmesa->tmu_source[unit];
+   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
+   const struct gl_texture_object *tObj = texUnit->_Current;
+   mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
+
+   /* Upload teximages (not pipelined)
+    */
+   if (t->base.dirty_images[0]) {
+      FLUSH_BATCH( mmesa );
+      mgaSetTexImages( mmesa, tObj );
+      if ( t->base.memBlock == NULL ) {
+        return GL_FALSE;
+      }
+   }
+
+   return GL_TRUE;
+}
+
+static GLboolean update_tex_common( GLcontext *ctx, int unit )
+{
+   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+   const int source = mmesa->tmu_source[unit];
+   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
+   struct gl_texture_object    *tObj = texUnit->_Current;
+   mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
+
+   /* Fallback if there's a texture border */
+   if ( tObj->Image[tObj->BaseLevel]->Border > 0 ) {
+      return GL_FALSE;
+   }
+
+
+   /* Update state if this is a different texture object to last
+    * time.
+    */
+   if ( mmesa->CurrentTexObj[unit] != t ) {
+      if ( mmesa->CurrentTexObj[unit] != NULL ) {
+        /* The old texture is no longer bound to this texture unit.
+         * Mark it as such.
+         */
+
+        mmesa->CurrentTexObj[unit]->base.bound &= ~(1UL << unit);
+      }
+
+      mmesa->CurrentTexObj[unit] = t;
+      t->base.bound |= (1UL << unit);
+
+      driUpdateTextureLRU( (driTextureObject *) t ); /* done too often */
+   }
+
+   /* register setup */
+   if ( unit == 1 ) {
+      mmesa->setup.tdualstage1 = mmesa->setup.tdualstage0;
+   }
+
+   t->setup.texctl2 &= TMC_dualtex_MASK;
+   if (ctx->Texture._EnabledUnits == 0x03) {
+      t->setup.texctl2 |= TMC_dualtex_enable;
+   }
+
+   /* FIXME: The Radeon has some cached state so that it can avoid calling
+    * FIXME: UpdateTextureEnv in some cases.  Is that possible here?
+    */
+   if (MGA_IS_G400(mmesa)) {
+      /* G400: Regardless of texture env mode, we use the alpha from the
+       * texture unit (AC_alphasel_fromtex) since it will have already
+       * been modulated by the incoming fragment color, if needed.
+       * We don't want (AC_alphasel_modulate) since that'll effectively
+       * do the modulation twice.
+       */
+      mmesa->hw.alpha_sel = AC_alphasel_fromtex;
+
+      mgaUpdateTextureEnvG400( ctx, unit );
+   } else {
+      mmesa->hw.alpha_sel = 0;
+      switch (ctx->Texture.Unit[0].EnvMode) {
+      case GL_DECAL:
+        mmesa->hw.alpha_sel |= AC_alphasel_diffused;
+      case GL_REPLACE:
+        mmesa->hw.alpha_sel |= AC_alphasel_fromtex;
+        break;
+      case GL_BLEND:
+      case GL_MODULATE:
+        mmesa->hw.alpha_sel |= AC_alphasel_modulated;
+        break;
+      default:
+        break;
+      }
+
+      mgaUpdateTextureEnvG200( ctx, unit );
+   }
+
+   mmesa->setup.dwgctl &= DC_opcod_MASK;
+   mmesa->setup.dwgctl |= DC_opcod_texture_trap;
+   mmesa->dirty |= MGA_UPLOAD_CONTEXT | (MGA_UPLOAD_TEX0 << unit);
+
+   FALLBACK( ctx, MGA_FALLBACK_BORDER_MODE, t->border_fallback );
+   return !t->border_fallback;
+}
+
+
+static GLboolean updateTextureUnit( GLcontext *ctx, int unit )
+{
+   mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+   const int source = mmesa->tmu_source[unit];
+   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
+
+
+   if ( texUnit->_ReallyEnabled == TEXTURE_2D_BIT) {
+      return(enable_tex_2d( ctx, unit ) &&
+            update_tex_common( ctx, unit ));
+   }
+   else if ( texUnit->_ReallyEnabled ) {
+      return GL_FALSE;
+   }
+   else {
+      disable_tex( ctx, unit );
+      return GL_TRUE;
+   }
+}
+
+/* The G400 is now programmed quite differently wrt texture environment.
+ */
+void mgaUpdateTextureState( GLcontext *ctx )
+{
+   mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+   GLboolean ok;
+   unsigned  i;
+
+
+   /* This works around a quirk with the MGA hardware.  If only OpenGL 
+    * TEXTURE1 is enabled, then the hardware TEXTURE0 must be used.  The
+    * hardware TEXTURE1 can ONLY be used when hardware TEXTURE0 is also used.
+    */
+
+   mmesa->tmu_source[0] = 0;
+   mmesa->tmu_source[1] = 1;
+
+   if ((ctx->Texture._EnabledUnits & 0x03) == 0x02) {
+      /* only texture 1 enabled */
+      mmesa->tmu_source[0] = 1;
+      mmesa->tmu_source[1] = 0;
+   }
+
+   for ( i = 0, ok = GL_TRUE 
+        ; (i < ctx->Const.MaxTextureUnits) && ok
+        ; i++ ) {
+      ok = updateTextureUnit( ctx, i );
+   }
+
+   FALLBACK( ctx, MGA_FALLBACK_TEXTURE, !ok );
+   
+   /* FIXME: I believe that ChooseVertexState should be called here instead of
+    * FIXME: in mgaDDValidateState.
+    */
+}
index de1bcc2a0f7174f30a4205ee32216f77eef83fce..16dc349cace720ce78259faf5a8ee3531e06573c 100644 (file)
@@ -1,4 +1,4 @@
-/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mga_xmesa.c,v 1.19 2003/03/26 20:43:49 tsi Exp $ */
+/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mga_xmesa.c,v 1.18 2002/12/16 16:18:52 dawes Exp $ */
 /*
  * Copyright 2000-2001 VA Linux Systems, Inc.
  * All Rights Reserved.
  *    Keith Whitwell <keith@tungstengraphics.com>
  */
 
-#include <stdio.h>
+#ifdef GLX_DIRECT_RENDERING
 
 #include "mga_common.h"
 #include "mga_xmesa.h"
 #include "context.h"
 #include "matrix.h"
-/*#include "mmath.h"*/
 #include "simple_list.h"
-/*#include "mem.h"*/
+#include "imports.h"
 
 #include "swrast/swrast.h"
 #include "swrast_setup/swrast_setup.h"
 #include "mgaioctl.h"
 #include "mgatris.h"
 #include "mgavb.h"
-#include "mgabuffers.h"
 #include "mgapixel.h"
-
 #include "mga_xmesa.h"
-
 #include "mga_dri.h"
 
 
+#include "utils.h"
+#include "vblank.h"
+#include "dri_util.h"
+#ifndef _SOLO
+#include "glxextensions.h"
+#endif
+
 #ifndef MGA_DEBUG
-int MGA_DEBUG = (0
-/*              | DEBUG_ALWAYS_SYNC */
-/*              | DEBUG_VERBOSE_MSG */
-/*              | DEBUG_VERBOSE_LRU */
-/*              | DEBUG_VERBOSE_DRI */
-/*              | DEBUG_VERBOSE_IOCTL */
-/*              | DEBUG_VERBOSE_2D */
-/*              | DEBUG_VERBOSE_FALLBACK */
-   );
+int MGA_DEBUG = 0;
 #endif
 
+static int getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo );
 
 static GLboolean
 mgaInitDriver(__DRIscreenPrivate *sPriv)
@@ -77,16 +73,8 @@ mgaInitDriver(__DRIscreenPrivate *sPriv)
    mgaScreenPrivate *mgaScreen;
    MGADRIPtr         serverInfo = (MGADRIPtr)sPriv->pDevPriv;
 
-   if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
-      fprintf(stderr, "mgaInitDriver\n");
-
-   /* Check that the DRM driver version is compatible */
-   if (sPriv->drmMajor != 3 ||
-       sPriv->drmMinor < 0) {
-      __driUtilMessage("MGA DRI driver expected DRM driver version 3.0.x but got version %d.%d.%d", sPriv->drmMajor, sPriv->drmMinor, sPriv->drmPatch);
+   if ( ! driCheckDriDdxDrmVersions( sPriv, "MGA", 4, 0, 1, 0, 3, 0 ) )
       return GL_FALSE;
-   }
-
 
    /* Allocate the private area */
    mgaScreen = (mgaScreenPrivate *)MALLOC(sizeof(mgaScreenPrivate));
@@ -103,21 +91,37 @@ mgaInitDriver(__DRIscreenPrivate *sPriv)
       drmMGAGetParam gp;
 
       gp.param = MGA_PARAM_IRQ_NR;
-      gp.value = (int *) &mgaScreen->irq;
+      gp.value = &mgaScreen->irq;
 
       ret = drmCommandWriteRead( sPriv->fd, DRM_MGA_GETPARAM,
                                    &gp, sizeof(gp));
       if (ret) {
            fprintf(stderr, "drmMgaGetParam (MGA_PARAM_IRQ_NR): %d\n", ret);
-           FREE(mgaScreen);
+           free(mgaScreen);
            sPriv->private = NULL;
            return GL_FALSE;
       }
    }
    
+   mgaScreen->linecomp_sane = (sPriv->ddxMajor > 1) || (sPriv->ddxMinor > 1)
+       || ((sPriv->ddxMinor == 1) && (sPriv->ddxPatch > 0));
+#ifndef _SOLO   
+   if ( ! mgaScreen->linecomp_sane ) {
+      PFNGLXDISABLEEXTENSIONPROC glx_disable_extension;
+
+      glx_disable_extension = (PFNGLXDISABLEEXTENSIONPROC)
+         glXGetProcAddress( "__glXDisableExtension" );
+
+      if ( glx_disable_extension != NULL ) {
+        (*glx_disable_extension)( "GLX_SGI_swap_control" );
+        (*glx_disable_extension)( "GLX_SGI_video_sync" );
+        (*glx_disable_extension)( "GLX_MESA_swap_control" );
+      }
+   }
+#endif
    if (serverInfo->chipset != MGA_CARD_TYPE_G200 &&
        serverInfo->chipset != MGA_CARD_TYPE_G400) {
-      FREE(mgaScreen);
+      free(mgaScreen);
       sPriv->private = NULL;
       __driUtilMessage("Unrecognized chipset");
       return GL_FALSE;
@@ -164,7 +168,7 @@ mgaInitDriver(__DRIscreenPrivate *sPriv)
              mgaScreen->agp.size,
              (drmAddress *)&mgaScreen->agp.map) != 0)
    {
-      Xfree(mgaScreen);
+      free(mgaScreen);
       sPriv->private = NULL;
       __driUtilMessage("Couldn't map agp region");
       return GL_FALSE;
@@ -210,7 +214,7 @@ mgaInitDriver(__DRIscreenPrivate *sPriv)
    mgaScreen->bufs = drmMapBufs(sPriv->fd);
    if (!mgaScreen->bufs) {
       /*drmUnmap(mgaScreen->agp_tex.map, mgaScreen->agp_tex.size);*/
-      FREE(mgaScreen);
+      free(mgaScreen);
       sPriv->private = NULL;
       __driUtilMessage("Couldn't map dma buffers");
       return GL_FALSE;
@@ -254,12 +258,63 @@ static const struct gl_pipeline_stage *mga_pipeline[] = {
 };
 
 
+static const char * const g400_extensions[] =
+{
+   "GL_ARB_multitexture",
+   "GL_ARB_texture_env_add",
+   "GL_EXT_texture_env_add",
+   "GL_EXT_texture_edge_clamp",
+   "GL_SGIS_texture_edge_clamp",
+#if defined (MESA_packed_depth_stencil)
+   "GL_MESA_packed_depth_stencil",
+#endif
+   NULL
+};
+
+static const char * const card_extensions[] =
+{
+   "GL_ARB_multisample",
+   "GL_ARB_texture_compression",
+   "GL_EXT_fog_coord",
+   /* paletted_textures currently doesn't work, but we could fix them later */
+#if 0
+   "GL_EXT_shared_texture_palette",
+   "GL_EXT_paletted_texture",
+#endif
+   "GL_EXT_secondary_color",
+   "GL_EXT_stencil_wrap",
+   "GL_MESA_ycbcr_texture",
+   "GL_SGIS_generate_mipmap",
+   "GL_SGIS_texture_lod",
+   NULL
+};
+
+static const struct dri_debug_control debug_control[] =
+{
+    { "fall",  DEBUG_VERBOSE_FALLBACK },
+    { "tex",   DEBUG_VERBOSE_TEXTURE },
+    { "ioctl", DEBUG_VERBOSE_IOCTL },
+    { "verb",  DEBUG_VERBOSE_MSG },
+    { "dri",   DEBUG_VERBOSE_DRI },
+    { NULL,    0 }
+};
+
+
+static int
+get_ust_nop( uint64_t * ust )
+{
+   *ust = 1;
+   return 0;
+}
+
+
 static GLboolean
 mgaCreateContext( const __GLcontextModes *mesaVis,
                   __DRIcontextPrivate *driContextPriv,
                   void *sharedContextPrivate )
 {
    int i;
+   unsigned   maxlevels;
    GLcontext *ctx, *shareCtx;
    mgaContextPtr mmesa;
    __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
@@ -281,7 +336,7 @@ mgaCreateContext( const __GLcontextModes *mesaVis,
       shareCtx = ((mgaContextPtr) sharedContextPrivate)->glCtx;
    else 
       shareCtx = NULL;
-   mmesa->glCtx = _mesa_create_context(mesaVis, shareCtx, mmesa, GL_TRUE);
+   mmesa->glCtx = _mesa_create_context(mesaVis, shareCtx, (void *) mmesa, GL_TRUE);
    if (!mmesa->glCtx) {
       FREE(mmesa);
       return GL_FALSE;
@@ -298,13 +353,20 @@ mgaCreateContext( const __GLcontextModes *mesaVis,
    mmesa->sarea = (void *)saPriv;
    mmesa->glBuffer = NULL;
 
-   make_empty_list(&mmesa->SwappedOut);
-
-   mmesa->lastTexHeap = mgaScreen->texVirtual[MGA_AGP_HEAP] ? 2 : 1;
-
-   for (i = 0 ; i < mmesa->lastTexHeap ; i++) {
-      mmesa->texHeap[i] = mmInit( 0, mgaScreen->textureSize[i]);
-      make_empty_list(&mmesa->TexObjList[i]);
+   (void) memset( mmesa->texture_heaps, 0, sizeof( mmesa->texture_heaps ) );
+   make_empty_list( & mmesa->swapped );
+
+   mmesa->nr_heaps = mgaScreen->texVirtual[MGA_AGP_HEAP] ? 2 : 1;
+   for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
+      mmesa->texture_heaps[i] = driCreateTextureHeap( i, mmesa,
+           mgaScreen->textureSize[i],
+           6,
+           MGA_NR_TEX_REGIONS,
+           mmesa->sarea->texList[i],
+           & mmesa->sarea->texAge[i],
+           & mmesa->swapped,
+           sizeof( mgaTextureObject_t ),
+           (destroy_texture_object_t *) mgaDestroyTexObj );
    }
 
    /* Set the maximum texture size small enough that we can guarentee
@@ -312,22 +374,26 @@ mgaCreateContext( const __GLcontextModes *mesaVis,
     * on the card at once.
     */
    ctx = mmesa->glCtx;
-   { 
-      int nr = 2;
-
-      if (mgaScreen->chipset == MGA_CARD_TYPE_G200)
-        nr = 1;
-
-      if (mgaScreen->textureSize[0] < nr*1024*1024) {
-        ctx->Const.MaxTextureLevels = 9;
-      } else if (mgaScreen->textureSize[0] < nr*4*1024*1024) {
-        ctx->Const.MaxTextureLevels = 10;
-      } else {
-        ctx->Const.MaxTextureLevels = 11;
-      }
+   if ( mgaScreen->chipset == MGA_CARD_TYPE_G200 ) {
+      ctx->Const.MaxTextureUnits = 1;
+      maxlevels = G200_TEX_MAXLEVELS;
 
-      ctx->Const.MaxTextureUnits = nr;
    }
+   else {
+      ctx->Const.MaxTextureUnits = 2;
+      maxlevels = G400_TEX_MAXLEVELS;
+   }
+
+   driCalculateMaxTextureLevels( mmesa->texture_heaps,
+                                mmesa->nr_heaps,
+                                & ctx->Const,
+                                4,
+                                11, /* max 2D texture size is 1024x1024 */
+                                0,  /* 3D textures unsupported. */
+                                0,  /* cube textures unsupported. */
+                                0,  /* texture rectangles unsupported. */
+                                maxlevels,
+                                GL_FALSE );
 
    ctx->Const.MinLineWidth = 1.0;
    ctx->Const.MinLineWidthAA = 1.0;
@@ -335,6 +401,7 @@ mgaCreateContext( const __GLcontextModes *mesaVis,
    ctx->Const.MaxLineWidthAA = 10.0;
    ctx->Const.LineWidthGranularity = 1.0;
 
+   mmesa->default32BitTextures = (mesaVis->rgbBits >= 24);
    mmesa->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24;
 
    switch (mesaVis->depthBits) {
@@ -361,7 +428,6 @@ mgaCreateContext( const __GLcontextModes *mesaVis,
 
    mmesa->haveHwStipple = GL_FALSE;
    mmesa->RenderIndex = -1;            /* impossible value */
-   mmesa->new_state = ~0;
    mmesa->dirty = ~0;
    mmesa->vertex_format = 0;   
    mmesa->CurrentTexObj[0] = 0;
@@ -395,7 +461,11 @@ mgaCreateContext( const __GLcontextModes *mesaVis,
    ctx->DriverCtx = (void *) mmesa;
    mmesa->glCtx = ctx;
 
-   mgaDDExtensionsInit( ctx );
+   driInitExtensions( ctx, card_extensions, GL_FALSE );
+
+   if (MGA_IS_G400(MGA_CONTEXT(ctx))) {
+      driInitExtensions( ctx, g400_extensions, GL_FALSE );
+   }
 
    mgaDDInitStateFuncs( ctx );
    mgaDDInitTextureFuncs( ctx );
@@ -410,6 +480,24 @@ mgaCreateContext( const __GLcontextModes *mesaVis,
 
    driContextPriv->driverPrivate = (void *) mmesa;
 
+#if DO_DEBUG
+   MGA_DEBUG = driParseDebugString( getenv( "MGA_DEBUG" ),
+                                   debug_control );
+#endif
+
+   mmesa->vblank_flags = ((mmesa->mgaScreen->irq == 0) 
+                         || !mmesa->mgaScreen->linecomp_sane)
+       ? VBLANK_FLAG_NO_IRQ : driGetDefaultVBlankFlags();
+#ifndef _SOLO
+   mmesa->get_ust = (PFNGLXGETUSTPROC) glXGetProcAddress( "__glXGetUST" );
+   if ( mmesa->get_ust == NULL ) 
+#endif
+   {
+      mmesa->get_ust = get_ust_nop;
+   }
+
+   (*mmesa->get_ust)( & mmesa->swap_ust );
+
    return GL_TRUE;
 }
 
@@ -419,10 +507,15 @@ mgaDestroyContext(__DRIcontextPrivate *driContextPriv)
    mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
 
    if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
-      fprintf(stderr, "mgaDestroyContext\n");
+      fprintf( stderr, "[%s:%d] mgaDestroyContext start\n",
+              __FILE__, __LINE__ );
 
    assert(mmesa); /* should never be null */
    if (mmesa) {
+      GLboolean   release_texture_heaps;
+
+
+      release_texture_heaps = (mmesa->glCtx->Shared->RefCount == 1);
       _swsetup_DestroyContext( mmesa->glCtx );
       _tnl_DestroyContext( mmesa->glCtx );
       _ac_DestroyContext( mmesa->glCtx );
@@ -433,9 +526,27 @@ mgaDestroyContext(__DRIcontextPrivate *driContextPriv)
       /* free the Mesa context */
       mmesa->glCtx->DriverCtx = NULL;
       _mesa_destroy_context(mmesa->glCtx);
-      /* free the mga context */
+       
+      if ( release_texture_heaps ) {
+         /* This share group is about to go away, free our private
+          * texture object data.
+          */
+         int i;
+
+        assert( is_empty_list( & mmesa->swapped ) );
+
+         for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
+           driDestroyTextureHeap( mmesa->texture_heaps[ i ] );
+           mmesa->texture_heaps[ i ] = NULL;
+         }
+      }
+
       FREE(mmesa);
    }
+
+   if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
+      fprintf( stderr, "[%s:%d] mgaDestroyContext done\n",
+              __FILE__, __LINE__ );
 }
 
 
@@ -482,13 +593,7 @@ mgaUnbindContext(__DRIcontextPrivate *driContextPriv)
 }
 
 static GLboolean
-mgaOpenFullScreen(__DRIcontextPrivate *driContextPriv)
-{
-    return GL_TRUE;
-}
-
-static GLboolean
-mgaCloseFullScreen(__DRIcontextPrivate *driContextPriv)
+mgaOpenCloseFullScreen(__DRIcontextPrivate *driContextPriv)
 {
     return GL_TRUE;
 }
@@ -505,8 +610,6 @@ mgaMakeCurrent(__DRIcontextPrivate *driContextPriv,
                __DRIdrawablePrivate *driDrawPriv,
                __DRIdrawablePrivate *driReadPriv)
 {
-   fprintf(stderr, "%s\n", __FUNCTION__);
-
    if (driContextPriv) {
       mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
 
@@ -532,6 +635,7 @@ mgaMakeCurrent(__DRIcontextPrivate *driContextPriv,
    return GL_TRUE;
 }
 
+
 void mgaGetLock( mgaContextPtr mmesa, GLuint flags )
 {
    __DRIdrawablePrivate *dPriv = mmesa->driDrawable;
@@ -539,29 +643,10 @@ void mgaGetLock( mgaContextPtr mmesa, GLuint flags )
    int me = mmesa->hHWContext;
    int i;
 
-   fprintf(stderr, "%s\n", __FUNCTION__);
-
    drmGetLock(mmesa->driFd, mmesa->hHWContext, flags);
-   
-   fprintf(stderr, 
-          "mmesa->lastStamp %d dpriv->lastStamp %d *(dpriv->pStamp) %d\n",
-          mmesa->lastStamp, 
-          dPriv->lastStamp,
-          *(dPriv->pStamp));
-   
-   /* The window might have moved, so we might need to get new clip
-    * rects.
-    *
-    * NOTE: This releases and regrabs the hw lock to allow the X server
-    * to respond to the DRI protocol request for new drawable info.
-    * Since the hardware state depends on having the latest drawable
-    * clip rects, all state checking must be done _after_ this call.
-    */
-   DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv );
 
-   if ( mmesa->lastStamp == 0 ||
-       mmesa->lastStamp != dPriv->lastStamp ) {
-      mmesa->lastStamp = dPriv->lastStamp;
+   if (*(dPriv->pStamp) != mmesa->lastStamp) {
+      mmesa->lastStamp = *(dPriv->pStamp);
       mmesa->SetupNewInputs |= VERT_BIT_CLIP;
       mmesa->dirty_cliprects = (MGA_FRONT|MGA_BACK);
       mgaUpdateRects( mmesa, (MGA_FRONT|MGA_BACK) );
@@ -569,7 +654,7 @@ void mgaGetLock( mgaContextPtr mmesa, GLuint flags )
 
    mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS;
 
-   mmesa->sarea->dirty |= MGA_UPLOAD_CONTEXT;
+    mmesa->sarea->dirty |= MGA_UPLOAD_CONTEXT;
 
    if (sarea->ctxOwner != me) {
       mmesa->dirty |= (MGA_UPLOAD_CONTEXT | MGA_UPLOAD_TEX0 |
@@ -577,36 +662,48 @@ void mgaGetLock( mgaContextPtr mmesa, GLuint flags )
       sarea->ctxOwner=me;
    }
 
-   for (i = 0 ; i < mmesa->lastTexHeap ; i++)
-      if (sarea->texAge[i] != mmesa->texAge[i])
-        mgaAgeTextures( mmesa, i );
+   for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
+      DRI_AGE_TEXTURES( mmesa->texture_heaps[ i ] );
+   }
 
    sarea->last_quiescent = -1; /* just kill it for now */
 }
 
 
-
 static const struct __DriverAPIRec mgaAPI = {
-   mgaInitDriver,
-   mgaDestroyScreen,
-   mgaCreateContext,
-   mgaDestroyContext,
-   mgaCreateBuffer,
-   mgaDestroyBuffer,
-   mgaSwapBuffers,
-   mgaMakeCurrent,
-   mgaUnbindContext,
-   mgaOpenFullScreen,
-   mgaCloseFullScreen
+   .InitDriver      = mgaInitDriver,
+   .DestroyScreen   = mgaDestroyScreen,
+   .CreateContext   = mgaCreateContext,
+   .DestroyContext  = mgaDestroyContext,
+   .CreateBuffer    = mgaCreateBuffer,
+   .DestroyBuffer   = mgaDestroyBuffer,
+   .SwapBuffers     = mgaSwapBuffers,
+   .MakeCurrent     = mgaMakeCurrent,
+   .UnbindContext   = mgaUnbindContext,
+   .OpenFullScreen  = mgaOpenCloseFullScreen,
+   .CloseFullScreen = mgaOpenCloseFullScreen,
+   .GetSwapInfo     = getSwapInfo,
+   .GetMSC          = driGetMSC32,
+   .WaitForMSC      = driWaitForMSC32,
+   .WaitForSBC      = NULL,
+   .SwapBuffersMSC  = NULL
 };
 
 
-
 /*
  * This is the bootstrap function for the driver.
  * The __driCreateScreen name is the symbol that libGL.so fetches.
  * Return:  pointer to a __DRIscreenPrivate.
  */
+#ifndef _SOLO
+void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
+                        int numConfigs, __GLXvisualConfig *config)
+{
+   __DRIscreenPrivate *psp;
+   psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &mgaAPI);
+   return (void *) psp;
+}
+#else
 void *__driCreateScreen(struct DRIDriverRec *driver,
                         struct DRIDriverContextRec *driverContext)
 {
@@ -614,3 +711,56 @@ void *__driCreateScreen(struct DRIDriverRec *driver,
    psp = __driUtilCreateScreen(driver, driverContext, &mgaAPI);
    return (void *) psp;
 }
+#endif
+
+
+#ifndef _SOLO
+/* This function is called by libGL.so as soon as libGL.so is loaded.
+ * This is where we'd register new extension functions with the dispatcher.
+ */
+void
+__driRegisterExtensions( void )
+{
+   PFNGLXENABLEEXTENSIONPROC glx_enable_extension;
+
+
+   if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
+      glx_enable_extension = (PFNGLXENABLEEXTENSIONPROC)
+         glXGetProcAddress( "__glXEnableExtension" );
+
+      if ( glx_enable_extension != NULL ) {
+        (*glx_enable_extension)( "GLX_SGI_swap_control", GL_FALSE );
+        (*glx_enable_extension)( "GLX_SGI_video_sync", GL_FALSE );
+        (*glx_enable_extension)( "GLX_MESA_swap_control", GL_FALSE );
+        (*glx_enable_extension)( "GLX_MESA_swap_frame_usage", GL_FALSE );
+      }
+   }
+}
+#endif
+
+/**
+ * Get information about previous buffer swaps.
+ */
+static int
+getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo )
+{
+   mgaContextPtr  mmesa;
+
+   if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL)
+       || (dPriv->driContextPriv->driverPrivate == NULL)
+       || (sInfo == NULL) ) {
+      return -1;
+   }
+
+   mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate;
+   sInfo->swap_count = mmesa->swap_count;
+   sInfo->swap_ust = mmesa->swap_ust;
+   sInfo->swap_missed_count = mmesa->swap_missed_count;
+
+   sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
+       ? driCalculateSwapUsage( dPriv, 0, mmesa->swap_missed_ust )
+       : 0.0;
+
+   return 0;
+}
+#endif
index eda996f5a444cba4584af0abdb1478bdfce8f1b3..de349da08951db913dcf6d3522f6f947ccf9b4e8 100644 (file)
@@ -29,8 +29,9 @@
 #ifndef _MGA_INIT_H_
 #define _MGA_INIT_H_
 
+#ifdef GLX_DIRECT_RENDERING
+
 #include <sys/time.h>
-#include <linux/types.h>
 #include "dri_util.h"
 #include "mtypes.h"
 #include "mgaregs.h"
@@ -46,6 +47,9 @@ typedef struct mga_screen_private_s {
    int cpp;                    /* for front and back buffers */
    GLint agpMode;
    unsigned int irq;           /* IRQ number (0 means none) */
+   GLboolean  linecomp_sane;    /* GL_TRUE if line comp. programmed correctly
+                                * by the DDX driver.
+                                */
 
    unsigned int mAccess;
 
@@ -136,8 +140,9 @@ do {                                                \
 #define MGA_BASE( reg )                ((unsigned long)(mmesa->mgaScreen->mmio.map))
 #define MGA_ADDR( reg )                (MGA_BASE(reg) + reg)
 
-#define MGA_DEREF( reg )       *(volatile __u32 *)MGA_ADDR( reg )
+#define MGA_DEREF( reg )       *(volatile CARD32 *)MGA_ADDR( reg )
 #define MGA_READ( reg )                MGA_DEREF( reg )
 #define MGA_WRITE( reg, val )  do { MGA_DEREF( reg ) = val; } while (0)
 
 #endif
+#endif
index 3065ea9fd1fcca840a5447b649e8d00541c6c6c8..7188f6d9552130aab6cf662190dbfd74c0c91938 100644 (file)
 #ifndef MGALIB_INC
 #define MGALIB_INC
 
-/*#include <X11/Xlibint.h>*/
+#include <inttypes.h>
 #include "dri_util.h"
 #include "mtypes.h"
+#include "colormac.h"
 #include "xf86drm.h"
 #include "mm.h"
-/*#include "mem.h"*/
 #include "mga_sarea.h"
-
+#include "texmem.h"
+#include "macros.h"
 
 #define MGA_SET_FIELD(reg,mask,val)  reg = ((reg) & (mask)) | ((val) & ~(mask))
 #define MGA_FIELD(field,val) (((val) << (field ## _SHIFT)) & ~(field ## _MASK))
 #define MGA_FALLBACK_RENDERMODE     0x10
 #define MGA_FALLBACK_STENCIL        0x20
 #define MGA_FALLBACK_DEPTH          0x40
+#define MGA_FALLBACK_BORDER_MODE    0x80
 
 
-/* For mgaCtx->new_state.
- */
-#define MGA_NEW_DEPTH   0x1
-#define MGA_NEW_ALPHA   0x2
-#define MGA_NEW_CLIP    0x8
-#define MGA_NEW_TEXTURE 0x20
-#define MGA_NEW_CULL    0x40
-#define MGA_NEW_WARP    0x80
-#define MGA_NEW_STENCIL 0x100
-#define MGA_NEW_CONTEXT 0x200
-
 /* Use the templated vertex formats:
  */
 #define TAG(x) mga##x
@@ -96,43 +87,103 @@ typedef void (*mga_point_func)( mgaContextPtr, mgaVertex * );
 struct mga_texture_object_s;
 struct mga_screen_private_s;
 
-#define MGA_TEX_MAXLEVELS 5
+#define G200_TEX_MAXLEVELS 5
+#define G400_TEX_MAXLEVELS 11
 
 typedef struct mga_texture_object_s
 {
-   struct mga_texture_object_s *next;
-   struct mga_texture_object_s *prev;
-   struct gl_texture_object *tObj;
-   struct mga_context_t *ctx;
-   PMemBlock   MemBlock;
-   GLuint              offsets[MGA_TEX_MAXLEVELS];
-   int             lastLevel;
-   GLuint         dirty_images;
-   GLuint              totalSize;
-   int         texelBytes;
-   GLuint      age;
-   int             bound;
-   int             heap;       /* agp or card */
+   driTextureObject   base;
+
+   /* The G200 only has the ability to use 5 mipmap levels (including the
+    * base level).  The G400 does not have this restriction, but it still
+    * only has 5 offset pointers in the hardware.  The trick on the G400 is
+    * upto the first 4 offset pointers point to mipmap levels.  The last
+    * offset pointer tells how large the preceeding mipmap is.  This value is
+    * then used to determine where the remaining mipmaps are.
+    * 
+    * For example, if the first offsets[0] through offsets[2] are used as
+    * pointers, then offset[3] will be the size of the mipmap pointed to by
+    * offsets[2].  So mipmap level 3 will be at (offsets[2]+offsets[3]).  For
+    * each successive mipmap level, offsets[3] is divided by 4 and added to
+    * the previous address.  So mipmap level 4 will be at 
+    * (offsets[2]+offsets[3]+(offsets[3] / 4)).
+    * 
+    * The last pointer is selected by setting TO_texorgoffsetsel in its
+    * pointer.  In the previous example, offset[2] would have
+    * TO_texorgoffsetsel or'ed in before writing it to the hardware.
+    * 
+    * In the current driver all of the mipmaps are packed together linearly
+    * with mipmap level 0.  Therefore offsets[0] points to the base of the
+    * texture (and has TO_texorgoffsetsel or'ed in), and offsets[1] is the
+    * size of the base texture.
+    *
+    * There is a possible optimization available here.  At times the driver
+    * may not be able to allocate a single block of memory for the complete
+    * texture without ejecting some other textures from memory.  It may be
+    * possible to put some of the lower mipmap levels (i.e., the larger
+    * mipmaps) in memory separate from the higher levels.
+    *
+    * The implementation should be fairly obvious, but getting "right" would
+    * likely be non-trivial.  A first allocation for the entire texture would
+    * be attempted with a flag that says "don't eject other textures."  If
+    * that failed, an additional allocation would be attmpted for just the
+    * base map.  The process would repeat with the block of lower maps.  The
+    * tricky parts would be in detecting when some of the levels had been
+    * ejected from texture memory by other textures and preventing the
+    * 4th allocation (for all the smallest mipmap levels) from kicking out
+    * any of the first three.
+    * 
+    * This array holds G400_TEX_MAXLEVELS pointers to remove an if-statement
+    * in a loop in mgaSetTexImages.  Values past G200_TEX_MAXLEVELS are not
+    * used.
+    */
+   GLuint             offsets[G400_TEX_MAXLEVELS];
+
+   int                texelBytes;
+   GLuint             age;
 
    mga_texture_regs_t setup;
+
+   /* If one texture dimension wraps with GL_CLAMP and the other with
+    * GL_CLAMP_TO_EDGE, we have to fallback to software.  We would also have
+    * to fallback for GL_CLAMP_TO_BORDER.
+    */
+   GLboolean          border_fallback;
 } mgaTextureObject_t;
 
+struct mga_hw_state {
+   GLuint   specen;
+   GLuint   cull;
+   GLuint   cull_dualtex;
+   GLuint   stencil;
+   GLuint   stencilctl;
+   GLuint   stencil_enable;
+   GLuint   zmode;
+   GLuint   rop;
+   GLuint   alpha_func;
+   GLuint   alpha_func_enable;
+   GLuint   blend_func;
+   GLuint   blend_func_enable;
+   GLuint   alpha_sel;
+};
+
 struct mga_context_t {
 
    GLcontext *glCtx;
-   unsigned int lastStamp;     /* fullscreen breaks dpriv->laststamp,
-                                * need to shadow it here. */
+   unsigned int lastStamp;             /* fullscreen breaks dpriv->laststamp,
+                                        * need to shadow it here. */
+
+   /* Hardware state management
+    */
+   struct mga_hw_state hw;
 
    /* Bookkeeping for texturing
     */
-   int lastTexHeap;
-   struct mga_texture_object_s TexObjList[MGA_NR_TEX_HEAPS];
-   struct mga_texture_object_s SwappedOut;
+   unsigned           nr_heaps;
+   driTexHeap       * texture_heaps[ MGA_NR_TEX_HEAPS ];
+   driTextureObject   swapped;
+
    struct mga_texture_object_s *CurrentTexObj[2];
-   memHeap_t *texHeap[MGA_NR_TEX_HEAPS];
-   int c_texupload;
-   int c_texusage;
-   int tex_thrash;
 
 
    /* Map GL texture units onto hardware.
@@ -166,7 +217,7 @@ struct mga_context_t {
    GLenum raster_primitive;
    GLenum render_primitive;
 
-   char *verts;
+   GLubyte *verts;
    GLint vertex_stride_shift;
    GLuint vertex_format;               
    GLuint vertex_size;
@@ -180,8 +231,7 @@ struct mga_context_t {
 
    /* Manage driver and hardware state
     */
-   GLuint        new_gl_state; 
-   GLuint        new_state; 
+   GLuint        NewGLState; 
    GLuint        dirty;
 
    mga_context_regs_t setup;
@@ -205,13 +255,21 @@ struct mga_context_t {
    /* VBI
     */
    GLuint vbl_seq;
+   GLuint vblank_flags;
+
+   uint64_t swap_ust;
+   uint64_t swap_missed_ust;
+
+   GLuint swap_count;
+   GLuint swap_missed_count;
+
+   PFNGLXGETUSTPROC get_ust;
 
    /* Drawable, cliprect and scissor information
     */
    int dirty_cliprects;                /* which sets of cliprects are uptodate? */
    int draw_buffer;            /* which buffer are we rendering to */
    unsigned int drawOffset;            /* draw buffer address in  space */
-   int read_buffer;
    int readOffset;
    int drawX, drawY;           /* origin of drawable in draw buffer */
    int lastX, lastY;           /* detect DSTORG bug */
@@ -245,51 +303,38 @@ struct mga_context_t {
 
 #define MGA_CONTEXT(ctx) ((mgaContextPtr)(ctx->DriverCtx))
 
-#define MGAPACKCOLOR555(r,g,b,a) \
-  ((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \
-    ((a) ? 0x8000 : 0))
 
-#define MGAPACKCOLOR565(r,g,b) \
-  ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3))
 
-#define MGAPACKCOLOR88(l, a) \
-  (((l) << 8) | (a))
-
-#define MGAPACKCOLOR888(r,g,b) \
-  (((r) << 16) | ((g) << 8) | (b))
-
-#define MGAPACKCOLOR8888(r,g,b,a) \
-  (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
-
-#define MGAPACKCOLOR4444(r,g,b,a) \
-  ((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4))
 
+/* ================================================================
+ * Debugging:
+ */
+#define DO_DEBUG               1
 
-#define MGA_DEBUG 0
-#ifndef MGA_DEBUG
+#if DO_DEBUG
 extern int MGA_DEBUG;
+#else
+#define MGA_DEBUG              0
 #endif
 
-#define DEBUG_ALWAYS_SYNC      0x1
-#define DEBUG_VERBOSE_MSG      0x2
-#define DEBUG_VERBOSE_LRU      0x4
-#define DEBUG_VERBOSE_DRI      0x8
-#define DEBUG_VERBOSE_IOCTL    0x10
-#define DEBUG_VERBOSE_2D       0x20
-#define DEBUG_VERBOSE_FALLBACK 0x40
+#define DEBUG_VERBOSE_MSG      0x01
+#define DEBUG_VERBOSE_DRI      0x02
+#define DEBUG_VERBOSE_IOCTL    0x04
+#define DEBUG_VERBOSE_TEXTURE   0x08
+#define DEBUG_VERBOSE_FALLBACK 0x10
 
 static __inline__ GLuint mgaPackColor(GLuint cpp,
                                      GLubyte r, GLubyte g,
                                      GLubyte b, GLubyte a)
 {
-  switch (cpp) {
-  case 2:
-    return MGAPACKCOLOR565(r,g,b);
-  case 4:
-    return MGAPACKCOLOR8888(r,g,b,a);
-  default:
-    return 0;
-  }
+   switch (cpp) {
+   case 2:
+      return PACK_COLOR_565( r, g, b );
+   case 4:
+      return PACK_COLOR_8888( a, r, g, b );
+   default:
+      return 0;
+   }
 }
 
 
index 6ce50e6726e262fc1a27295b0d1997a486b0b48a..d2f11d8d457de8c74dd2622b0c3f96a89220d2f6 100644 (file)
 
 #include "mtypes.h"
 
-
-#include <stdio.h>
-#include <stdlib.h>
-
 #include "mm.h"
 #include "mgacontext.h"
 #include "mgadd.h"
 #include "mgatris.h"
 #include "mgavb.h"
 #include "mga_xmesa.h"
-#include "extensions.h"
-#if defined(USE_X86_ASM)
-#include "X86/common_x86_asm.h"
-#endif
+#include "utils.h"
 
-#define MGA_DATE       "20020221"
+#define DRIVER_DATE    "20030328"
 
 
 /***************************************
@@ -59,52 +52,19 @@ static const GLubyte *mgaDDGetString( GLcontext *ctx, GLenum name )
 {
    mgaContextPtr mmesa = MGA_CONTEXT( ctx );
    static char buffer[128];
+   unsigned   offset;
 
    switch ( name ) {
    case GL_VENDOR:
       return (GLubyte *) "VA Linux Systems Inc.";
 
    case GL_RENDERER:
-      sprintf( buffer, "Mesa DRI %s " MGA_DATE,
-              MGA_IS_G400(mmesa) ? "G400" :
-              MGA_IS_G200(mmesa) ? "G200" : "MGA" );
-
-      /* Append any AGP-specific information.
-       */
-      switch ( mmesa->mgaScreen->agpMode ) {
-      case 1:
-        strncat( buffer, " AGP 1x", 7 );
-        break;
-      case 2:
-        strncat( buffer, " AGP 2x", 7 );
-        break;
-      case 4:
-        strncat( buffer, " AGP 4x", 7 );
-        break;
-      }
-
-      /* Append any CPU-specific information.
-       */
-#ifdef USE_X86_ASM
-      if ( _mesa_x86_cpu_features ) {
-        strncat( buffer, " x86", 4 );
-      }
-#endif
-#ifdef USE_MMX_ASM
-      if ( cpu_has_mmx ) {
-        strncat( buffer, "/MMX", 4 );
-      }
-#endif
-#ifdef USE_3DNOW_ASM
-      if ( cpu_has_3dnow ) {
-        strncat( buffer, "/3DNow!", 7 );
-      }
-#endif
-#ifdef USE_SSE_ASM
-      if ( cpu_has_xmm ) {
-        strncat( buffer, "/SSE", 4 );
-      }
-#endif
+      offset = driGetRendererString( buffer, 
+                                    MGA_IS_G400(mmesa) ? "G400" :
+                                    MGA_IS_G200(mmesa) ? "G200" : "MGA",
+                                    DRIVER_DATE,
+                                    mmesa->mgaScreen->agpMode );
+
       return (GLubyte *)buffer;
 
    default:
@@ -129,40 +89,6 @@ static void mgaBufferSize(GLframebuffer *buffer, GLuint *width, GLuint *height)
    UNLOCK_HARDWARE( mmesa );
 }
 
-void mgaDDExtensionsInit( GLcontext *ctx )
-{
-   /* paletted_textures currently doesn't work, but we could fix them later */
-   /*
-   _mesa_enable_extension( ctx, "GL_EXT_shared_texture_palette" );
-   _mesa_enable_extension( ctx, "GL_EXT_paletted_texture" );
-   */
-
-   _mesa_enable_extension( ctx, "GL_ARB_texture_compression" );
-   _mesa_enable_extension( ctx, "GL_ARB_multisample" );
-
-   _mesa_enable_extension( ctx, "GL_SGIS_generate_mipmap" );
-
-   /* Turn on multitexture and texenv_add for the G400.
-    */
-   if (MGA_IS_G400(MGA_CONTEXT(ctx))) {
-      _mesa_enable_extension( ctx, "GL_ARB_multitexture" );
-      _mesa_enable_extension( ctx, "GL_ARB_texture_env_add" );
-
-      _mesa_enable_extension( ctx, "GL_EXT_texture_env_add" );
-
-#if defined (MESA_packed_depth_stencil)
-      _mesa_enable_extension( ctx, "GL_MESA_packed_depth_stencil" );
-#endif
-
-#if defined (MESA_experimetal_agp_allocator)
-      if (!getenv("MGA_DISABLE_AGP_ALLOCATOR"))  
-        _mesa_enable_extension( ctx, "GL_MESA_experimental_agp_allocator" );
-#endif
-   }
-}
-
-
-
 void mgaDDInitDriverFuncs( GLcontext *ctx )
 {
    ctx->Driver.GetBufferSize = mgaBufferSize;
index 6072e6cfc9f6dbc6558b3df1be813cb866cb1f79..919fd742d6136734c001d199defb2307c8da2622 100644 (file)
@@ -32,6 +32,5 @@
 #include "context.h"
 
 void mgaDDInitDriverFuncs( GLcontext *ctx );
-void mgaDDExtensionsInit( GLcontext *ctx );
 
 #endif
index f88c8780607cdf3006c483a8bbbd66a7384b270f..6b50af202a81742659b0460f4e1cdf5cab16608c 100644 (file)
@@ -27,7 +27,7 @@
  */
 /* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgaioctl.c,v 1.16 2002/12/16 16:18:52 dawes Exp $ */
 
-#include <stdio.h>
+#include <sched.h>
 #include <errno.h>
 
 #include "mtypes.h"
 #include "mgavb.h"
 #include "mgaioctl.h"
 #include "mgatris.h"
-#include "mgabuffers.h"
+#include "mga_common.h"
 
+#include "vblank.h"
 
-#include "xf86drm.h"
-#include "mga_common.h"
 
 static void mga_iload_dma_ioctl(mgaContextPtr mmesa,
                                unsigned long dest,
@@ -61,6 +60,13 @@ static void mga_iload_dma_ioctl(mgaContextPtr mmesa,
       fprintf(stderr, "DRM_IOCTL_MGA_ILOAD idx %d dst %x length %d\n",
              buf->idx, (int) dest, length);
 
+   if ( (length & MGA_ILOAD_MASK) != 0 ) {
+      UNLOCK_HARDWARE( mmesa );
+      fprintf( stderr, "%s: Invalid ILOAD datasize (%d), must be "
+              "multiple of %u.\n", __FUNCTION__, length, MGA_ILOAD_ALIGN );
+      exit( 1 );
+   }
+
    iload.idx = buf->idx;
    iload.dstorg = dest;
    iload.length = length;
@@ -278,65 +284,11 @@ mgaDDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
 }
 
 
-int nrswaps;
-
-
-void mgaWaitForVBlank( mgaContextPtr mmesa )
-{
-#if 0
-    drmVBlank vbl;
-    int ret;
-
-    if ( !mmesa->mgaScreen->irq )
-       return;
-
-    if ( getenv("LIBGL_SYNC_REFRESH") ) {
-       /* Wait for until the next vertical blank */
-       vbl.request.type = DRM_VBLANK_RELATIVE;
-       vbl.request.sequence = 1;
-    } else if ( getenv("LIBGL_THROTTLE_REFRESH") ) {
-       /* Wait for at least one vertical blank since the last call */
-       vbl.request.type = DRM_VBLANK_ABSOLUTE;
-       vbl.request.sequence = mmesa->vbl_seq + 1;
-    } else {
-       return;
-    }
-
-    if ((ret = drmWaitVBlank( mmesa->driFd, &vbl ))) {
-       fprintf(stderr, "%s: drmWaitVBlank returned %d, IRQs don't seem to be"
-               " working correctly.\nTry running with LIBGL_THROTTLE_REFRESH"
-               " and LIBL_SYNC_REFRESH unset.\n", __FUNCTION__, ret);
-       exit(1);
-    }
-
-    mmesa->vbl_seq = vbl.reply.sequence;
-#endif
-}
-
-
-/*
- * Copy the back buffer to the front buffer.
- */
-void mgaSwapBuffers(__DRIdrawablePrivate *dPriv)
+static void mgaWaitForFrameCompletion( mgaContextPtr mmesa )
 {
-   mgaContextPtr mmesa;
-   XF86DRIClipRectPtr pbox;
-   GLint nbox;
-   GLint ret, wait = 0;
-   GLint i;
+   unsigned wait = 0;
    GLuint last_frame, last_wrap;
 
-   assert(dPriv);
-   assert(dPriv->driContextPriv);
-   assert(dPriv->driContextPriv->driverPrivate);
-
-   mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate;
-
-   FLUSH_BATCH( mmesa );
-
-   mgaWaitForVBlank( mmesa );
-
-   LOCK_HARDWARE( mmesa );
 
    last_frame = mmesa->sarea->last_frame.head;
    last_wrap = mmesa->sarea->last_frame.wrap;
@@ -360,12 +312,46 @@ void mgaSwapBuffers(__DRIdrawablePrivate *dPriv)
       }
       UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH );
 
-      for ( i = 0 ; i < 1024 ; i++ ) {
-        /* Don't just hammer the register... */
-      }
+      UNLOCK_HARDWARE( mmesa );
+      DO_USLEEP( 1 );
+      LOCK_HARDWARE( mmesa );
    }
    if ( wait )
       fprintf( stderr, "\n" );
+}
+
+
+/*
+ * Copy the back buffer to the front buffer.
+ */
+void mgaSwapBuffers( __DRIdrawablePrivate *dPriv )
+{
+   mgaContextPtr mmesa;
+   XF86DRIClipRectPtr pbox;
+   GLint nbox;
+   GLint ret;
+   GLint i;
+   GLboolean   missed_target;
+
+
+   assert(dPriv);
+   assert(dPriv->driContextPriv);
+   assert(dPriv->driContextPriv->driverPrivate);
+
+   mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate;
+
+   FLUSH_BATCH( mmesa );
+
+   LOCK_HARDWARE( mmesa );
+   mgaWaitForFrameCompletion( mmesa );
+   UNLOCK_HARDWARE( mmesa );
+   driWaitForVBlank( dPriv, & mmesa->vbl_seq, mmesa->vblank_flags,
+                    & missed_target );
+   if ( missed_target ) {
+      mmesa->swap_missed_count++;
+      (void) (*mmesa->get_ust)( & mmesa->swap_missed_ust );
+   }
+   LOCK_HARDWARE( mmesa );
 
    /* Use the frontbuffer cliprects
     */
@@ -399,6 +385,8 @@ void mgaSwapBuffers(__DRIdrawablePrivate *dPriv)
    UNLOCK_HARDWARE( mmesa );
 
    mmesa->dirty |= MGA_UPLOAD_CLIPRECTS;
+   mmesa->swap_count++;
+   (void) (*mmesa->get_ust)( & mmesa->swap_ust );
 }
 
 
@@ -442,18 +430,17 @@ void mgaWaitAge( mgaContextPtr mmesa, int age  )
 }
 
 
-static int intersect_rect( XF86DRIClipRectPtr out,
-                          XF86DRIClipRectPtr a,
-                          XF86DRIClipRectPtr b )
+static GLboolean intersect_rect( XF86DRIClipRectPtr out,
+                                const XF86DRIClipRectPtr a,
+                                const XF86DRIClipRectPtr b )
 {
    *out = *a;
    if (b->x1 > out->x1) out->x1 = b->x1;
    if (b->y1 > out->y1) out->y1 = b->y1;
    if (b->x2 < out->x2) out->x2 = b->x2;
    if (b->y2 < out->y2) out->y2 = b->y2;
-   if (out->x1 > out->x2) return 0;
-   if (out->y1 > out->y2) return 0;
-   return 1;
+
+   return ((out->x1 < out->x2) && (out->y1 < out->y2));
 }
 
 
@@ -559,7 +546,7 @@ void mgaFlushVerticesLocked( mgaContextPtr mmesa )
          vertex.idx = buffer->idx;
          vertex.used = buffer->used;
          vertex.discard = discard;
-         drmCommandWrite( mmesa->driFd, DRM_MGA_VERTEX, 
+         drmCommandWrite( mmesa->driFd, DRM_MGA_VERTEX,
                           &vertex, sizeof(drmMGAVertex) );
 
         age_mmesa(mmesa, mmesa->sarea->last_enqueue);
index b7cf44d6ff949d8ac7fba43b93e79a2380847319..2d959d8246d847f10dba1f0c8f0bd934d3c3b5f1 100644 (file)
@@ -34,6 +34,7 @@
 #include "mga_xmesa.h"
 
 void mgaSwapBuffers( __DRIdrawablePrivate *dPriv );
+void mgaWaitForVBlank( mgaContextPtr mmesa );
 
 GLuint *mgaAllocVertexDwords( mgaContextPtr mmesa, int dwords );
 
@@ -41,7 +42,6 @@ GLuint *mgaAllocVertexDwords( mgaContextPtr mmesa, int dwords );
 void mgaGetILoadBufferLocked( mgaContextPtr mmesa );
 drmBufPtr mgaGetBufferLocked( mgaContextPtr mmesa );
 
-void mgaWaitForVBlank( mgaContextPtr mmesa );
 
 void mgaFireILoadLocked( mgaContextPtr mmesa,
                         GLuint offset, GLuint length );
@@ -104,8 +104,9 @@ do {                                                                        \
    if ( ret < 0 ) {                                                    \
       drmCommandNone( mmesa->driFd, DRM_MGA_RESET );                   \
       UNLOCK_HARDWARE( mmesa );                                                \
-      fprintf( stderr, "%s: flush ret=%d\n", __FUNCTION__, ret );      \
-      /*fprintf( stderr, "drmMGAFlushDMA: return = %d\n", ret );*/     \
+      fprintf( stderr, "%s: flush return = %s (%d), flags = 0x%08x\n", \
+              __FUNCTION__, strerror( -ret ), -ret,                    \
+              (unsigned)(flags) );                                     \
       exit( 1 );                                                       \
    }                                                                   \
 } while (0)
index 0bc4b3fac5fb12cc16e6f6035e4a574026d9f3f4..07e0c3a75636a12e6a6254b9038fef5716731c46 100644 (file)
 #include "mgacontext.h"
 #include "mgaioctl.h"
 #include "mgapixel.h"
-#include "mgabuffers.h"
+#include "mgastate.h"
 
-#include "xf86drm.h"
 #include "mga_common.h"
 
 #include "swrast/swrast.h"
+#include "imports.h"
 
 #define IS_AGP_MEM( mmesa, p )                                           \
    ((unsigned long)mmesa->mgaScreen->buffers.map <= ((unsigned long)p) && \
@@ -134,7 +134,7 @@ check_color_per_fragment_ops( const GLcontext *ctx )
                    !ctx->Color.ColorMask[2] ||
                    !ctx->Color.ColorMask[3] ||
                    ctx->Color.ColorLogicOpEnabled ||
-                   ctx->Texture.Unit[0]._ReallyEnabled ||
+                   ctx->Texture._EnabledUnits ||
                    ctx->Depth.OcclusionTest
            ) &&
           ctx->Current.RasterPosValid &&
@@ -596,7 +596,7 @@ mgaTryDrawPixels( GLcontext *ctx,
            }
         }
 #else
-        memcpy( address, pixels, rows*bufferpitch );
+        MEMCPY( address, pixels, rows*bufferpitch );
 #endif
 
         do_draw_pix( ctx, x, y, width, rows,
@@ -639,42 +639,8 @@ mgaDDDrawPixels( GLcontext *ctx,
  * the same block of agp space which isn't used for anything else at
  * present.
  */
-#if defined(MESA_hacked_agp_allocator)
-static void mgaDDFreeAgpMemory( GLcontext *ctx, void *ptr )
-{
-   (void) ptr;
-}
-
-static void *mgaDDAllocateAgpMemory( GLcontext *ctx, GLsizei size )
-{
-   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
-
-   if (size < mmesa->mgaScreen->textureSize[MGA_AGP_HEAP])
-      return mmesa->mgaScreen->texVirtual[MGA_AGP_HEAP];
-   else
-      return 0;
-}
-
-static GLint mgaDDGetAgpOffset( GLcontext *ctx, const void *ptr )
-{
-   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
-
-   if (!IS_AGP_MEM(mmesa, ptr))
-      return -1;
-
-   return AGP_OFFSET(mmesa, ptr);
-}
-#endif
-
-
 void mgaDDInitPixelFuncs( GLcontext *ctx )
 {
-#if defined (MESA_experimetal_agp_allocator)
-   ctx->Driver.AllocateAgpMemory = mgaDDAllocateAgpMemory;
-   ctx->Driver.GetAgpOffset = mgaDDGetAgpOffset;
-   ctx->Driver.FreeAgpMemory = mgaDDFreeAgpMemory;
-#endif
-
    /* Pixel path fallbacks.
     */
    ctx->Driver.Accum = _swrast_Accum;
index f07dc2de0be4129f5aba4dec5e3bee726f2434c2..e1291ca01bdb89b3865bd64773bad21366090883 100644 (file)
 #    define TMC_tformat_tw8a           0x7             /* val 7, shift 0 */
 #    define TMC_tformat_tw8al          0x8             /* val 8, shift 0 */
 #    define TMC_tformat_tw422          0xa             /* val 10, shift 0 */
+#    define TMC_tformat_tw422uyvy      0xb             /* val 11, shift 0 */
 #    define TMC_tpitchlin_MASK                 0xfffffeff      /* bit 8 */
 #    define TMC_tpitchlin_disable      0x0             
 #    define TMC_tpitchlin_enable       0x100           
 #    define TF_magfilter_nrst          0x0             /* val 0, shift 4 */
 #    define TF_magfilter_bilin                 0x20            /* val 2, shift 4 */
 #    define TF_magfilter_cnst          0x30            /* val 3, shift 4 */
+#    define TF_uvoffset_SHIFT          17
+#    define TF_uvoffset_OGL            (0U << TF_uvoffset_SHIFT)
+#    define TF_uvoffset_D3D            (1U << TF_uvoffset_SHIFT)
+#    define TF_uvoffset_MASK           (~(1U << TF_uvoffset_SHIFT))
+#    define TF_reserved_MASK           (~0x1ff00)      /* bits 8-16 */
+#    define TF_mapnbhigh_SHIFT                 18
+#    define TF_mapnbhigh_MASK          (~(1U << TF_mapnbhigh_SHIFT))
 #    define TF_avgstride_MASK          0xfff7ffff      /* bit 19 */
 #    define TF_avgstride_disable       0x0             
 #    define TF_avgstride_enable        0x80000         
 
 /**************** (END) AUTOMATICLY GENERATED REGISTER FILE ******************/
 
+/* Copied from mga_drv.h kernel file.
+ */
+
+#define MGA_ILOAD_ALIGN                64
+#define MGA_ILOAD_MASK         (MGA_ILOAD_ALIGN - 1)
+
 #endif         /* _MGAREGS_H_ */
 
index 53614c223fcca11598ad2c338b76b19df9f9daaa..516a99099fdece1c1aa8585c31648cc04472a3cc 100644 (file)
@@ -42,9 +42,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "glheader.h"
 #include "context.h"
 #include "macros.h"
-/*//#include "mem.h"*/
+#include "imports.h"
 #include "mtypes.h"
-/*#include "mmath.h" */
 
 #include "tnl/t_context.h"
 
@@ -165,7 +164,7 @@ static GLboolean mga_run_render( GLcontext *ctx,
 
 static void mga_check_render( GLcontext *ctx, struct gl_pipeline_stage *stage )
 {
-   GLuint inputs = VERT_BIT_POS | VERT_BIT_CLIP | VERT_BIT_COLOR0;
+   GLuint inputs = VERT_BIT_CLIP | VERT_BIT_COLOR0;
 
    if (ctx->RenderMode == GL_RENDER) {
       if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) 
index 8dc971cfc5705761b978a3f96be16ac0504c289f..684239865f71bb998384e7169b99ee33729e70cd 100644 (file)
 
 #undef INIT_MONO_PIXEL
 #define INIT_MONO_PIXEL(p, color) \
-  p = MGAPACKCOLOR565( color[0], color[1], color[2] )
+  p = PACK_COLOR_565( color[0], color[1], color[2] )
 
 
 #define WRITE_RGBA( _x, _y, r, g, b, a )                               \
@@ -148,7 +148,7 @@ do {                                                                \
 
 #undef INIT_MONO_PIXEL
 #define INIT_MONO_PIXEL(p, color) \
-  p = MGAPACKCOLOR8888( color[0], color[1], color[2], color[3] )
+  p = PACK_COLOR_8888( color[3], color[0], color[1], color[2] )
 
 
 #define WRITE_RGBA(_x, _y, r, g, b, a)                 \
@@ -233,11 +233,38 @@ do {                                                              \
 
 
 
+/*
+ * This function is called to specify which buffer to read and write
+ * for software rasterization (swrast) fallbacks.  This doesn't necessarily
+ * correspond to glDrawBuffer() or glReadBuffer() calls.
+ */
+static void mgaDDSetBuffer(GLcontext *ctx, GLframebuffer *buffer,
+                           GLuint bufferBit)
+{
+   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+
+   if (bufferBit == FRONT_LEFT_BIT) 
+   {
+      mmesa->drawOffset = mmesa->mgaScreen->frontOffset;
+      mmesa->readOffset = mmesa->mgaScreen->frontOffset;
+   } 
+   else if (bufferBit == BACK_LEFT_BIT)
+   {
+      mmesa->drawOffset = mmesa->mgaScreen->backOffset;
+      mmesa->readOffset = mmesa->mgaScreen->backOffset;
+   }
+   else {
+      assert(0);
+   }
+}
+
 void mgaDDInitSpanFuncs( GLcontext *ctx )
 {
    mgaContextPtr mmesa = MGA_CONTEXT(ctx);
    struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
 
+   swdd->SetBuffer = mgaDDSetBuffer;
+
    switch (mmesa->mgaScreen->cpp) {
    case 2:
       swdd->WriteRGBASpan = mgaWriteRGBASpan_565;
index 02b98fdb7661476011b7a5616acbe306020db084..0d304966d7e43bcb8796ba159315936fe94ae81b 100644 (file)
@@ -26,9 +26,9 @@
  */
 /* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgastate.c,v 1.13 2002/10/30 12:51:36 alanh Exp $ */
 
-#include <stdio.h>
 
 #include "mtypes.h"
+#include "colormac.h"
 #include "dd.h"
 
 #include "mm.h"
 #include "mgatris.h"
 #include "mgaioctl.h"
 #include "mgaregs.h"
-#include "mgabuffers.h"
 
 #include "swrast/swrast.h"
 #include "array_cache/acache.h"
 #include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
 #include "swrast_setup/swrast_setup.h"
 
 
+static void updateSpecularLighting( GLcontext *ctx );
+
 
 /* Some outstanding problems with accelerating logic ops...
  */
 #if defined(ACCEL_ROP)
-static GLuint mgarop_NoBLK[16] = {
+static const GLuint mgarop_NoBLK[16] = {
    DC_atype_rpl  | 0x00000000, DC_atype_rstr | 0x00080000,
    DC_atype_rstr | 0x00040000, DC_atype_rpl  | 0x000c0000,
    DC_atype_rstr | 0x00020000, DC_atype_rstr | 0x000a0000,
@@ -65,221 +68,57 @@ static GLuint mgarop_NoBLK[16] = {
 #endif
 
 
-static void mgaUpdateStencil(const GLcontext *ctx)
-{
-   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
-   GLuint stencil = 0, stencilctl = 0;
-
-   if (ctx->Stencil.Enabled)
-   {
-      stencil = ctx->Stencil.Ref[0] |
-        ( ctx->Stencil.ValueMask[0] << 8 ) |
-        ( ctx->Stencil.WriteMask[0] << 16 );
-
-      switch (ctx->Stencil.Function[0])
-      {
-      case GL_NEVER:
-        MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_snever);
-        break;
-      case GL_LESS:
-        MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_slt);
-        break;
-      case GL_LEQUAL:
-        MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_slte);
-        break;
-      case GL_GREATER:
-        MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_sgt);
-        break;
-      case GL_GEQUAL:
-        MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_sgte);
-        break;
-      case GL_NOTEQUAL:
-        MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_sne);
-        break;
-      case GL_EQUAL:
-        MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_se);
-        break;
-      case GL_ALWAYS:
-        MGA_SET_FIELD(stencilctl, SC_smode_MASK, SC_smode_salways);
-      default:
-        break;
-      }
-
-      switch (ctx->Stencil.FailFunc[0])
-      {
-      case GL_KEEP:
-        MGA_SET_FIELD(stencilctl, SC_sfailop_MASK, SC_sfailop_keep);
-        break;
-      case GL_ZERO:
-        MGA_SET_FIELD(stencilctl, SC_sfailop_MASK, SC_sfailop_zero);
-        break;
-      case GL_REPLACE:
-        MGA_SET_FIELD(stencilctl, SC_sfailop_MASK, SC_sfailop_replace);
-        break;
-      case GL_INCR:
-        MGA_SET_FIELD(stencilctl, SC_sfailop_MASK, SC_sfailop_incrsat);
-        break;
-      case GL_DECR:
-        MGA_SET_FIELD(stencilctl, SC_sfailop_MASK, SC_sfailop_decrsat);
-        break;
-      case GL_INVERT:
-        MGA_SET_FIELD(stencilctl, SC_sfailop_MASK, SC_sfailop_invert);
-        break;
-      default:
-        break;
-      }
-
-      switch (ctx->Stencil.ZFailFunc[0])
-      {
-      case GL_KEEP:
-        MGA_SET_FIELD(stencilctl, SC_szfailop_MASK, SC_szfailop_keep);
-        break;
-      case GL_ZERO:
-        MGA_SET_FIELD(stencilctl, SC_szfailop_MASK, SC_szfailop_zero);
-        break;
-      case GL_REPLACE:
-        MGA_SET_FIELD(stencilctl, SC_szfailop_MASK, SC_szfailop_replace);
-        break;
-      case GL_INCR:
-        MGA_SET_FIELD(stencilctl, SC_szfailop_MASK, SC_szfailop_incrsat);
-        break;
-      case GL_DECR:
-        MGA_SET_FIELD(stencilctl, SC_szfailop_MASK, SC_szfailop_decrsat);
-        break;
-      case GL_INVERT:
-        MGA_SET_FIELD(stencilctl, SC_szfailop_MASK, SC_szfailop_invert);
-        break;
-      default:
-        break;
-      }
-
-      switch (ctx->Stencil.ZPassFunc[0])
-      {
-      case GL_KEEP:
-        MGA_SET_FIELD(stencilctl, SC_szpassop_MASK, SC_szpassop_keep);
-        break;
-      case GL_ZERO:
-        MGA_SET_FIELD(stencilctl, SC_szpassop_MASK, SC_szpassop_zero);
-        break;
-      case GL_REPLACE:
-        MGA_SET_FIELD(stencilctl, SC_szpassop_MASK, SC_szpassop_replace);
-        break;
-      case GL_INCR:
-        MGA_SET_FIELD(stencilctl, SC_szpassop_MASK, SC_szpassop_incrsat);
-        break;
-      case GL_DECR:
-        MGA_SET_FIELD(stencilctl, SC_szpassop_MASK, SC_szpassop_decrsat);
-        break;
-      case GL_INVERT:
-        MGA_SET_FIELD(stencilctl, SC_szpassop_MASK, SC_szpassop_invert);
-        break;
-      default:
-        break;
-      }
-   }
-
-   mmesa->setup.stencil = stencil;
-   mmesa->setup.stencilctl = stencilctl;
-   mmesa->dirty |= MGA_UPLOAD_CONTEXT;
-}
-
-static void mgaDDStencilFunc(GLcontext *ctx, GLenum func, GLint ref,
-                            GLuint mask)
-{
-   FLUSH_BATCH( MGA_CONTEXT(ctx) );
-   MGA_CONTEXT(ctx)->new_state |= MGA_NEW_STENCIL;
-}
-
-static void mgaDDStencilMask(GLcontext *ctx, GLuint mask)
-{
-   FLUSH_BATCH( MGA_CONTEXT(ctx) );
-   MGA_CONTEXT(ctx)->new_state |= MGA_NEW_STENCIL;
-}
-
-static void mgaDDStencilOp(GLcontext *ctx, GLenum fail, GLenum zfail,
-                          GLenum zpass)
-{
-   FLUSH_BATCH( MGA_CONTEXT(ctx) );
-   MGA_CONTEXT(ctx)->new_state |= MGA_NEW_STENCIL;
-}
+/* =============================================================
+ * Alpha blending
+ */
 
-static void mgaDDClearDepth(GLcontext *ctx, GLclampd d)
+static void mgaDDAlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
 {
    mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+   GLubyte refByte;
+   GLuint  a;
 
-   /* KW: should the ~ be there? */
-   switch (mmesa->setup.maccess & ~MA_zwidth_MASK) {
-   case MA_zwidth_16: mmesa->ClearDepth = d * 0x0000ffff; break;
-   case MA_zwidth_24: mmesa->ClearDepth = d * 0xffffff00; break;
-   case MA_zwidth_32: mmesa->ClearDepth = d * 0xffffffff; break;
-   default: return;
-   }
-}
+   CLAMPED_FLOAT_TO_UBYTE(refByte, ref);
 
-static void mgaUpdateZMode(const GLcontext *ctx)
-{
-   mgaContextPtr mmesa = MGA_CONTEXT( ctx );
-   int zmode = 0;
-
-   if (ctx->Depth.Test) {
-      switch(ctx->Depth.Func)  {
-      case GL_NEVER:
-         /* can't do this in h/w, we'll use a s/w fallback */
-        zmode = DC_zmode_nozcmp;
-         break;
-      case GL_ALWAYS:
-        zmode = DC_zmode_nozcmp; break;
-      case GL_LESS:
-        zmode = DC_zmode_zlt; break;
-      case GL_LEQUAL:
-        zmode = DC_zmode_zlte; break;
-      case GL_EQUAL:
-        zmode = DC_zmode_ze; break;
-      case GL_GREATER:
-        zmode = DC_zmode_zgt; break;
-      case GL_GEQUAL:
-        zmode = DC_zmode_zgte; break;
-      case GL_NOTEQUAL:
-        zmode = DC_zmode_zne; break;
-      default:
-        break;
-      }
-
-      if (ctx->Depth.Mask)
-         zmode |= DC_atype_zi;
-      else
-         zmode |= DC_atype_i;
-   }
-   else {
-      zmode |= DC_zmode_nozcmp;
-      zmode |= DC_atype_i;  /* don't write to zbuffer */
+   switch ( func ) {
+   case GL_NEVER:
+      a = AC_atmode_alt;
+      refByte = 0;
+      break;
+   case GL_LESS:
+      a = AC_atmode_alt;
+      break;
+   case GL_GEQUAL:
+      a = AC_atmode_agte;
+      break;
+   case GL_LEQUAL:
+      a = AC_atmode_alte;
+      break;
+   case GL_GREATER:
+      a = AC_atmode_agt;
+      break;
+   case GL_NOTEQUAL:
+      a = AC_atmode_ane;
+      break;
+   case GL_EQUAL:
+      a = AC_atmode_ae;
+      break;
+   case GL_ALWAYS:
+      a = AC_atmode_noacmp;
+      break;
+   default:
+      a = 0;
+      break;
    }
 
-#if defined(ACCEL_ROP)
-   mmesa->setup.dwgctl &= DC_bop_MASK;
-   if (ctx->Color.ColorLogicOpEnabled)
-      zmode |= mgarop_NoBLK[(ctx->Color.LogicOp)&0xf];
-   else
-      zmode |= mgarop_NoBLK[GL_COPY & 0xf];
-#endif
-
-   mmesa->setup.dwgctl &= DC_zmode_MASK & DC_atype_MASK;
-   mmesa->setup.dwgctl |= zmode;
+   FLUSH_BATCH( mmesa );
+   mmesa->hw.alpha_func = a | MGA_FIELD( AC_atref, refByte );
    mmesa->dirty |= MGA_UPLOAD_CONTEXT;
 }
 
-
-static void mgaDDAlphaFunc(GLcontext *ctx, GLenum func, GLfloat ref)
-{
-   FLUSH_BATCH( MGA_CONTEXT(ctx) );
-   MGA_CONTEXT(ctx)->new_state |= MGA_NEW_ALPHA;
-}
-
-
 static void mgaDDBlendEquation(GLcontext *ctx, GLenum mode)
 {
    FLUSH_BATCH( MGA_CONTEXT(ctx) );
-   MGA_CONTEXT(ctx)->new_state |= MGA_NEW_ALPHA;
 
    /* BlendEquation sets ColorLogicOpEnabled in an unexpected 
     * manner.  
@@ -291,247 +130,169 @@ static void mgaDDBlendEquation(GLcontext *ctx, GLenum mode)
 
 static void mgaDDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor)
 {
-   FLUSH_BATCH( MGA_CONTEXT(ctx) );
-   MGA_CONTEXT(ctx)->new_state |= MGA_NEW_ALPHA;
+   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+   mgaScreenPrivate *mgaScreen = mmesa->mgaScreen;
+   GLuint   src;
+   GLuint   dst;
+
+   switch (ctx->Color.BlendSrcRGB) {
+   case GL_ZERO:
+      src = AC_src_zero; break;
+   case GL_SRC_ALPHA:
+      src = AC_src_src_alpha; break;
+   case GL_ONE:
+   default:            /* never happens */
+      src = AC_src_one; break;
+   case GL_DST_COLOR:
+      src = AC_src_dst_color; break;
+   case GL_ONE_MINUS_DST_COLOR:
+      src = AC_src_om_dst_color; break;
+   case GL_ONE_MINUS_SRC_ALPHA:
+      src = AC_src_om_src_alpha; break;
+   case GL_DST_ALPHA:
+      src = (mgaScreen->cpp == 4) 
+         ? AC_src_dst_alpha : AC_src_one;
+      break;
+   case GL_ONE_MINUS_DST_ALPHA:
+      src = (mgaScreen->cpp == 4)
+         ? AC_src_om_dst_alpha : AC_src_zero;
+      break;
+   case GL_SRC_ALPHA_SATURATE:
+      src = (ctx->Visual.alphaBits > 0)
+         ? AC_src_src_alpha_sat : AC_src_zero;
+      break;
+   }
+
+   switch (ctx->Color.BlendDstRGB) {
+   case GL_SRC_ALPHA:
+      dst = AC_dst_src_alpha; break;
+   case GL_ONE_MINUS_SRC_ALPHA:
+      dst = AC_dst_om_src_alpha; break;
+   default:            /* never happens */
+   case GL_ZERO:
+      dst = AC_dst_zero; break;
+   case GL_ONE:
+      dst = AC_dst_one; break;
+   case GL_SRC_COLOR:
+      dst = AC_dst_src_color; break;
+   case GL_ONE_MINUS_SRC_COLOR:
+      dst = AC_dst_om_src_color; break;
+   case GL_DST_ALPHA:
+      dst = (mgaScreen->cpp == 4)
+         ? AC_dst_dst_alpha : AC_dst_one;
+      break;
+   case GL_ONE_MINUS_DST_ALPHA:
+      dst = (mgaScreen->cpp == 4)
+         ? AC_dst_om_dst_alpha : AC_dst_zero;
+      break;
+   }
+
+   FLUSH_BATCH( mmesa );
+   mmesa->hw.blend_func = (src | dst);
+   mmesa->dirty |= MGA_UPLOAD_CONTEXT;
 }
 
 static void mgaDDBlendFuncSeparate( GLcontext *ctx, GLenum sfactorRGB,
                                    GLenum dfactorRGB, GLenum sfactorA,
                                    GLenum dfactorA )
 {
-   FLUSH_BATCH( MGA_CONTEXT(ctx) );
-   MGA_CONTEXT(ctx)->new_state |= MGA_NEW_ALPHA;
+   mgaDDBlendFunc( ctx, sfactorRGB, dfactorRGB );
 }
 
 
+/* =============================================================
+ * Depth testing
+ */
 
-static void mgaDDLightModelfv(GLcontext *ctx, GLenum pname,
-                             const GLfloat *param)
+static void mgaDDDepthFunc(GLcontext *ctx, GLenum func)
 {
-   if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) {
-      FLUSH_BATCH( MGA_CONTEXT(ctx) );
-      MGA_CONTEXT(ctx)->new_state |= MGA_NEW_TEXTURE;
+   mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+   int zmode;
+
+   switch (func) {
+   case GL_NEVER:
+      /* can't do this in h/w, we'll use a s/w fallback */
+      FALLBACK (ctx, MGA_FALLBACK_DEPTH, ctx->Depth.Test);
+
+      /* FALLTHROUGH */
+   case GL_ALWAYS:
+      zmode = DC_zmode_nozcmp; break;
+   case GL_LESS:
+      zmode = DC_zmode_zlt; break;
+   case GL_LEQUAL:
+      zmode = DC_zmode_zlte; break;
+   case GL_EQUAL:
+      zmode = DC_zmode_ze; break;
+   case GL_GREATER:
+      zmode = DC_zmode_zgt; break;
+   case GL_GEQUAL:
+      zmode = DC_zmode_zgte; break;
+   case GL_NOTEQUAL:
+      zmode = DC_zmode_zne; break;
+   default:
+      zmode = 0; break;
    }
-}
-
-
-static void mgaDDShadeModel(GLcontext *ctx, GLenum mode)
-{
-   FLUSH_BATCH( MGA_CONTEXT(ctx) );
-   MGA_CONTEXT(ctx)->new_state |= MGA_NEW_TEXTURE;
-}
 
-
-static void mgaDDDepthFunc(GLcontext *ctx, GLenum func)
-{
-   FLUSH_BATCH( MGA_CONTEXT(ctx) );
-   MGA_CONTEXT(ctx)->new_state |= MGA_NEW_DEPTH;
+   FLUSH_BATCH( mmesa );
+   mmesa->hw.zmode &= DC_zmode_MASK;
+   mmesa->hw.zmode |= zmode;
+   mmesa->dirty |= MGA_UPLOAD_CONTEXT;
 }
 
 static void mgaDDDepthMask(GLcontext *ctx, GLboolean flag)
 {
-   FLUSH_BATCH( MGA_CONTEXT(ctx) );
-   MGA_CONTEXT(ctx)->new_state |= MGA_NEW_DEPTH;
-}
+   mgaContextPtr mmesa = MGA_CONTEXT( ctx );
 
-#if defined(ACCEL_ROP)
-static void mgaDDLogicOp( GLcontext *ctx, GLenum opcode )
-{
-   FLUSH_BATCH( MGA_CONTEXT(ctx) );
-   MGA_CONTEXT(ctx)->new_state |= MGA_NEW_DEPTH;
-}
-#else
-static void mgaDDLogicOp( GLcontext *ctx, GLenum opcode )
-{
-   FLUSH_BATCH( MGA_CONTEXT(ctx) );
-   FALLBACK( ctx, MGA_FALLBACK_LOGICOP, 
-            (ctx->Color.ColorLogicOpEnabled && opcode != GL_COPY) );
-}
-#endif
 
+   FLUSH_BATCH( mmesa );
+   mmesa->hw.zmode &= DC_atype_MASK;
+   mmesa->hw.zmode |= (flag) ? DC_atype_zi : DC_atype_i;
+   mmesa->dirty |= MGA_UPLOAD_CONTEXT;
+}
 
 
-static void mgaDDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
+static void mgaDDClearDepth(GLcontext *ctx, GLclampd d)
 {
    mgaContextPtr mmesa = MGA_CONTEXT(ctx);
 
-   if (pname == GL_FOG_COLOR) {
-      GLuint color = MGAPACKCOLOR888((GLubyte)(ctx->Fog.Color[0]*255.0F), 
-                                    (GLubyte)(ctx->Fog.Color[1]*255.0F), 
-                                    (GLubyte)(ctx->Fog.Color[2]*255.0F));
-
-      MGA_STATECHANGE(mmesa, MGA_UPLOAD_CONTEXT);   
-      mmesa->setup.fogcolor = color;
+   /* Select the Z depth.  The ~ is used because the _MASK values in the
+    * MGA driver are used to mask OFF the selected bits.  In this case,
+    * we want to mask off everything except the MA_zwidth bits.
+    */
+   switch (mmesa->setup.maccess & ~MA_zwidth_MASK) {
+   case MA_zwidth_16: mmesa->ClearDepth = d * 0x0000ffff; break;
+   case MA_zwidth_24: mmesa->ClearDepth = d * 0xffffff00; break;
+   case MA_zwidth_32: mmesa->ClearDepth = d * 0xffffffff; break;
+   default: return;
    }
 }
 
 
-
-
 /* =============================================================
- * Alpha blending
+ * Fog
  */
 
 
-static void mgaUpdateAlphaMode(GLcontext *ctx)
+static void mgaDDFogfv(GLcontext *ctx, GLenum pname, const GLfloat *param)
 {
-   mgaContextPtr mmesa = MGA_CONTEXT( ctx );
-   mgaScreenPrivate *mgaScreen = mmesa->mgaScreen;
-   int a = 0;
-
-   /* determine source of alpha for blending and testing */
-   if ( !ctx->Texture.Unit[0]._ReallyEnabled ) {
-      a |= AC_alphasel_diffused;
-   }
-   else {
-      /* G400: Regardless of texture env mode, we use the alpha from the
-       * texture unit (AC_alphasel_fromtex) since it will have already
-       * been modulated by the incoming fragment color, if needed.
-       * We don't want (AC_alphasel_modulate) since that'll effectively
-       * do the modulation twice.
-       */
-      if (MGA_IS_G400(mmesa)) {
-         a |= AC_alphasel_fromtex;
-      }
-      else {
-         /* G200 */
-         switch (ctx->Texture.Unit[0].EnvMode) {
-         case GL_DECAL:
-            a |= AC_alphasel_diffused;
-         case GL_REPLACE:
-            a |= AC_alphasel_fromtex;
-            break;
-         case GL_BLEND:
-         case GL_MODULATE:
-            a |= AC_alphasel_modulated;
-            break;
-         default:
-            break;
-         }
-      }
-   }
-
-
-   /* alpha test control.
-    */
-   if (ctx->Color.AlphaEnabled) {
-      GLubyte ref = ctx->Color.AlphaRef;
-      switch (ctx->Color.AlphaFunc) {
-      case GL_NEVER:
-        a |= AC_atmode_alt;
-        ref = 0;
-        break;
-      case GL_LESS:
-        a |= AC_atmode_alt;
-        break;
-      case GL_GEQUAL:
-        a |= AC_atmode_agte;
-        break;
-      case GL_LEQUAL:
-        a |= AC_atmode_alte;
-        break;
-      case GL_GREATER:
-        a |= AC_atmode_agt;
-        break;
-      case GL_NOTEQUAL:
-        a |= AC_atmode_ane;
-        break;
-      case GL_EQUAL:
-        a |= AC_atmode_ae;
-        break;
-      case GL_ALWAYS:
-        a |= AC_atmode_noacmp;
-        break;
-      default:
-        break;
-      }
-      a |= MGA_FIELD(AC_atref,ref);
-   }
+   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
 
-   /* blending control */
-   if (ctx->Color.BlendEnabled) {
-      switch (ctx->Color.BlendSrcRGB) {
-      case GL_ZERO:
-        a |= AC_src_zero; break;
-      case GL_SRC_ALPHA:
-        a |= AC_src_src_alpha; break;
-      case GL_ONE:
-        a |= AC_src_one; break;
-      case GL_DST_COLOR:
-        a |= AC_src_dst_color; break;
-      case GL_ONE_MINUS_DST_COLOR:
-        a |= AC_src_om_dst_color; break;
-      case GL_ONE_MINUS_SRC_ALPHA:
-        a |= AC_src_om_src_alpha; break;
-      case GL_DST_ALPHA:
-        if (mgaScreen->cpp == 4)
-           a |= AC_src_dst_alpha;
-        else
-           a |= AC_src_one;
-        break;
-      case GL_ONE_MINUS_DST_ALPHA:
-        if (mgaScreen->cpp == 4)
-           a |= AC_src_om_dst_alpha;
-        else
-           a |= AC_src_zero;
-        break;
-      case GL_SRC_ALPHA_SATURATE:
-         if (ctx->Visual.alphaBits > 0)
-            a |= AC_src_src_alpha_sat;
-         else
-            a |= AC_src_zero;
-        break;
-      default:         /* never happens */
-        break;
-      }
+   if (pname == GL_FOG_COLOR) {
+      GLuint color = PACK_COLOR_888((GLubyte)(ctx->Fog.Color[0]*255.0F), 
+                                   (GLubyte)(ctx->Fog.Color[1]*255.0F), 
+                                   (GLubyte)(ctx->Fog.Color[2]*255.0F));
 
-      switch (ctx->Color.BlendDstRGB) {
-      case GL_SRC_ALPHA:
-        a |= AC_dst_src_alpha; break;
-      case GL_ONE_MINUS_SRC_ALPHA:
-        a |= AC_dst_om_src_alpha; break;
-      case GL_ZERO:
-        a |= AC_dst_zero; break;
-      case GL_ONE:
-        a |= AC_dst_one; break;
-      case GL_SRC_COLOR:
-        a |= AC_dst_src_color; break;
-      case GL_ONE_MINUS_SRC_COLOR:
-        a |= AC_dst_om_src_color; break;
-      case GL_DST_ALPHA:
-        if (mgaScreen->cpp == 4)
-           a |= AC_dst_dst_alpha;
-        else
-           a |= AC_dst_one;
-        break;
-      case GL_ONE_MINUS_DST_ALPHA:
-        if (mgaScreen->cpp == 4)
-           a |= AC_dst_om_dst_alpha;
-        else
-           a |= AC_dst_zero;
-        break;
-      default:         /* never happens */
-        break;
-      }
-   } else {
-      a |= AC_src_one|AC_dst_zero;
+      MGA_STATECHANGE(mmesa, MGA_UPLOAD_CONTEXT);   
+      mmesa->setup.fogcolor = color;
    }
-
-   mmesa->setup.alphactrl = (AC_amode_alpha_channel |
-                            AC_astipple_disable |
-                            AC_aten_disable |
-                            AC_atmode_noacmp |
-                            a);
-
-   mmesa->dirty |= MGA_UPLOAD_CONTEXT;
 }
 
 
-
 /* =============================================================
- * Hardware clipping
+ * Scissoring
  */
 
+
 void mgaUpdateClipping(const GLcontext *ctx)
 {
    mgaContextPtr mmesa = MGA_CONTEXT(ctx);
@@ -554,13 +315,6 @@ void mgaUpdateClipping(const GLcontext *ctx)
       mmesa->scissor_rect.x2 = x2;
       mmesa->scissor_rect.y2 = y2;
 
-      if (MGA_DEBUG&DEBUG_VERBOSE_2D)
-        fprintf(stderr, "SET SCISSOR %d,%d-%d,%d\n",
-                mmesa->scissor_rect.x1,
-                mmesa->scissor_rect.y1,
-                mmesa->scissor_rect.x2,
-                mmesa->scissor_rect.y2);
-
       mmesa->dirty |= MGA_UPLOAD_CLIPRECTS;
    }
 }
@@ -569,19 +323,10 @@ void mgaUpdateClipping(const GLcontext *ctx)
 static void mgaDDScissor( GLcontext *ctx, GLint x, GLint y,
                          GLsizei w, GLsizei h )
 {
-   FLUSH_BATCH( MGA_CONTEXT(ctx) );
-   MGA_CONTEXT(ctx)->new_state |= MGA_NEW_CLIP;
-}
-
-
-static void mgaDDClearColor(GLcontext *ctx, 
-                           const GLfloat color[4] )
-{
-   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
-
-   mmesa->ClearColor = mgaPackColor( mmesa->mgaScreen->cpp,
-                                    color[0], color[1], 
-                                    color[2], color[3]);
+   if ( ctx->Scissor.Enabled ) {
+      FLUSH_BATCH( MGA_CONTEXT(ctx) ); /* don't pipeline cliprect changes */
+      mgaUpdateClipping( ctx );
+   }
 }
 
 
@@ -589,46 +334,42 @@ static void mgaDDClearColor(GLcontext *ctx,
  * Culling
  */
 
+
 #define _CULL_DISABLE 0
 #define _CULL_NEGATIVE ((1<<11)|(1<<5)|(1<<16))
 #define _CULL_POSITIVE (1<<11)
 
-
-void mgaUpdateCull( GLcontext *ctx )
+static void mgaDDCullFaceFrontFace(GLcontext *ctx, GLenum unused)
 {
    mgaContextPtr mmesa = MGA_CONTEXT(ctx);
-   GLuint mode = _CULL_DISABLE;
 
+
+   FLUSH_BATCH( mmesa );
    if (ctx->Polygon.CullFlag && 
-       mmesa->raster_primitive == GL_TRIANGLES &&       
        ctx->Polygon.CullFaceMode != GL_FRONT_AND_BACK) 
    {
-      mode = _CULL_NEGATIVE;
+      mmesa->hw.cull = _CULL_NEGATIVE;
+
       if (ctx->Polygon.CullFaceMode == GL_FRONT)
-        mode ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE);
+        mmesa->hw.cull ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE);
+
       if (ctx->Polygon.FrontFace != GL_CCW)
-        mode ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE);
-      if ((ctx->Texture.Unit[0]._ReallyEnabled & TEXTURE_2D_BIT) &&
-          (ctx->Texture.Unit[1]._ReallyEnabled & TEXTURE_2D_BIT))
-        mode ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE); /* warp bug? */
+        mmesa->hw.cull ^= (_CULL_POSITIVE ^ _CULL_NEGATIVE);
+
+      mmesa->hw.cull_dualtex = mmesa->hw.cull ^
+         (_CULL_POSITIVE ^ _CULL_NEGATIVE); /* warp bug? */
+   }
+   else {
+      mmesa->hw.cull = _CULL_DISABLE;
+      mmesa->hw.cull_dualtex = _CULL_DISABLE;
    }
 
-   mmesa->setup.wflag = mode;
    mmesa->dirty |= MGA_UPLOAD_CONTEXT;
 }
 
 
-static void mgaDDCullFaceFrontFace(GLcontext *ctx, GLenum mode)
-{
-   FLUSH_BATCH( MGA_CONTEXT(ctx) );
-   MGA_CONTEXT(ctx)->new_state |= MGA_NEW_CULL;
-}
-
-
-
-
 /* =============================================================
- * Color masks
+ * Masks
  */
 
 static void mgaDDColorMask(GLcontext *ctx, 
@@ -654,15 +395,11 @@ static void mgaDDColorMask(GLcontext *ctx,
    }
 }
 
+
 /* =============================================================
- * Polygon stipple
- *
- * The mga supports a subset of possible 4x4 stipples natively, GL
- * wants 32x32.  Fortunately stipple is usually a repeating pattern.
- *
- * Note: the fully opaque pattern (0xffff) has been disabled in order
- * to work around a conformance issue.
+ * Polygon state
  */
+
 static int mgaStipples[16] = {
    0xffff1,  /* See above note */
    0xa5a5,
@@ -682,6 +419,17 @@ static int mgaStipples[16] = {
    0x0000
 };
 
+/**
+ * The MGA supports a subset of possible 4x4 stipples natively, GL
+ * wants 32x32.  Fortunately stipple is usually a repeating pattern.
+ *
+ * \param ctx GL rendering context to be affected
+ * \param mask Pointer to the 32x32 stipple mask
+ *
+ * \note the fully opaque pattern (0xffff) has been disabled in order
+ * to work around a conformance issue.
+ */
+
 static void mgaDDPolygonStipple( GLcontext *ctx, const GLubyte *mask )
 {
    mgaContextPtr mmesa = MGA_CONTEXT(ctx);
@@ -730,93 +478,216 @@ static void mgaDDPolygonStipple( GLcontext *ctx, const GLubyte *mask )
    }
 }
 
+
 /* =============================================================
+ * Rendering attributes
+ *
+ * We really don't want to recalculate all this every time we bind a
+ * texture.  These things shouldn't change all that often, so it makes
+ * sense to break them out of the core texture state update routines.
  */
 
-static void mgaDDPrintDirty( const char *msg, GLuint state )
+static void updateSpecularLighting( GLcontext *ctx )
 {
-   fprintf(stderr, "%s (0x%x): %s%s%s%s%s%s%s\n",
-          msg,
-          (unsigned int) state,
-          (state & MGA_WAIT_AGE) ? "wait-age, " : "",
-          (state & MGA_UPLOAD_TEX0IMAGE)  ? "upload-tex0-img, " : "",
-          (state & MGA_UPLOAD_TEX1IMAGE)  ? "upload-tex1-img, " : "",
-          (state & MGA_UPLOAD_CONTEXT)        ? "upload-ctx, " : "",
-          (state & MGA_UPLOAD_TEX0)       ? "upload-tex0, " : "",
-          (state & MGA_UPLOAD_TEX1)       ? "upload-tex1, " : "",
-          (state & MGA_UPLOAD_PIPE)       ? "upload-pipe, " : ""
-      );
+   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+   unsigned int specen;
+
+   specen = (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR &&
+            ctx->Light.Enabled) ? TMC_specen_enable : 0;
+
+   if ( specen != mmesa->hw.specen ) {
+      mmesa->hw.specen = specen;
+      mmesa->dirty |= MGA_UPLOAD_TEX0 | MGA_UPLOAD_TEX1;
+      
+      mgaChooseVertexState( ctx );
+   }
 }
 
-/* Push the state into the sarea and/or texture memory.
+
+/* =============================================================
+ * Materials
  */
-void mgaEmitHwStateLocked( mgaContextPtr mmesa )
+
+
+static void mgaDDLightModelfv(GLcontext *ctx, GLenum pname,
+                             const GLfloat *param)
 {
-   MGASAREAPrivPtr sarea = mmesa->sarea;
+   if (pname == GL_LIGHT_MODEL_COLOR_CONTROL) {
+      FLUSH_BATCH( MGA_CONTEXT(ctx) );
+      updateSpecularLighting( ctx );
+   }
+}
 
-   if (MGA_DEBUG & DEBUG_VERBOSE_MSG)
-      mgaDDPrintDirty( "mgaEmitHwStateLocked", mmesa->dirty );
 
-   if ((mmesa->dirty & MGA_UPLOAD_TEX0IMAGE) && mmesa->CurrentTexObj[0])
-      mgaUploadTexImages(mmesa, mmesa->CurrentTexObj[0]);
+static void mgaDDShadeModel(GLcontext *ctx, GLenum mode)
+{
+   /* FIXME: This used to FLUSH_BATCH and set MGA_NEW_TEXTURE in new_state,
+    * FIXME: so I'm not sure what to do here now.
+    */
+}
 
-   if ((mmesa->dirty & MGA_UPLOAD_TEX1IMAGE) && mmesa->CurrentTexObj[1])
-      mgaUploadTexImages(mmesa, mmesa->CurrentTexObj[1]);
 
-   if (mmesa->dirty & MGA_UPLOAD_CONTEXT) {
-      memcpy( &sarea->ContextState, &mmesa->setup, sizeof(mmesa->setup));
+/* =============================================================
+ * Stencil
+ */
+
+
+static void mgaDDStencilFunc(GLcontext *ctx, GLenum func, GLint ref,
+                            GLuint mask)
+{
+   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+   GLuint  stencil;
+   GLuint  stencilctl;
+
+   stencil = (ref << S_sref_SHIFT) | (mask << S_smsk_SHIFT);
+   switch (func)
+   {
+   case GL_NEVER:
+      stencilctl = SC_smode_snever;
+      break;
+   case GL_LESS:
+      stencilctl = SC_smode_slt;
+      break;
+   case GL_LEQUAL:
+      stencilctl = SC_smode_slte;
+      break;
+   case GL_GREATER:
+      stencilctl = SC_smode_sgt;
+      break;
+   case GL_GEQUAL:
+      stencilctl = SC_smode_sgte;
+      break;
+   case GL_NOTEQUAL:
+      stencilctl = SC_smode_sne;
+      break;
+   case GL_EQUAL:
+      stencilctl = SC_smode_se;
+      break;
+   case GL_ALWAYS:
+   default:
+      stencilctl = SC_smode_salways;
+      break;
    }
 
-   if ((mmesa->dirty & MGA_UPLOAD_TEX0) && mmesa->CurrentTexObj[0]) {
-      memcpy(&sarea->TexState[0],
-            &mmesa->CurrentTexObj[0]->setup,
-            sizeof(sarea->TexState[0]));
-   }
+   FLUSH_BATCH( mmesa );
+   mmesa->hw.stencil &= (S_sref_MASK & S_smsk_MASK);
+   mmesa->hw.stencil |= stencil;
+   mmesa->hw.stencilctl &= SC_smode_MASK;
+   mmesa->hw.stencilctl |= stencilctl;
+   mmesa->dirty |= MGA_UPLOAD_CONTEXT;
+}
 
-   if ((mmesa->dirty & MGA_UPLOAD_TEX1) && mmesa->CurrentTexObj[1]) {
-      memcpy(&sarea->TexState[1],
-            &mmesa->CurrentTexObj[1]->setup,
-            sizeof(sarea->TexState[1]));
-   }
+static void mgaDDStencilMask(GLcontext *ctx, GLuint mask)
+{
+   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
 
-   if (sarea->TexState[0].texctl2 !=
-       sarea->TexState[1].texctl2) {
-      memcpy(&sarea->TexState[1],
-            &sarea->TexState[0],
-            sizeof(sarea->TexState[0]));
-      mmesa->dirty |= MGA_UPLOAD_TEX1|MGA_UPLOAD_TEX0;
-   }
+   FLUSH_BATCH( mmesa );
+   mmesa->hw.stencil &= S_swtmsk_MASK;
+   mmesa->hw.stencil |= (mask << S_swtmsk_SHIFT);
+   mmesa->dirty |= MGA_UPLOAD_CONTEXT;
+}
 
-   if (mmesa->dirty & MGA_UPLOAD_PIPE) {
-/*        mmesa->sarea->wacceptseq = mmesa->hw_primitive; */
-      mmesa->sarea->WarpPipe = mmesa->vertex_format;
-      mmesa->sarea->vertsize = mmesa->vertex_size;
-   }
+static void mgaDDStencilOp(GLcontext *ctx, GLenum fail, GLenum zfail,
+                          GLenum zpass)
+{
+   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+   GLuint  stencilctl;
 
-   mmesa->sarea->dirty |= mmesa->dirty;
+   stencilctl = 0;
+   switch (ctx->Stencil.FailFunc[0])
+   {
+   case GL_KEEP:
+      stencilctl |= SC_sfailop_keep;
+      break;
+   case GL_ZERO:
+      stencilctl |= SC_sfailop_zero;
+      break;
+   case GL_REPLACE:
+      stencilctl |= SC_sfailop_replace;
+      break;
+   case GL_INCR:
+      stencilctl |= SC_sfailop_incrsat;
+      break;
+   case GL_DECR:
+      stencilctl |= SC_sfailop_decrsat;
+      break;
+   case GL_INCR_WRAP:
+      stencilctl |= SC_sfailop_incr;
+      break;
+   case GL_DECR_WRAP:
+      stencilctl |= SC_sfailop_decr;
+      break;
+   case GL_INVERT:
+      stencilctl |= SC_sfailop_invert;
+      break;
+   default:
+      break;
+   }
 
-   mmesa->dirty &= (MGA_UPLOAD_CLIPRECTS|MGA_WAIT_AGE);
+   switch (ctx->Stencil.ZFailFunc[0])
+   {
+   case GL_KEEP:
+      stencilctl |= SC_szfailop_keep;
+      break;
+   case GL_ZERO:
+      stencilctl |= SC_szfailop_zero;
+      break;
+   case GL_REPLACE:
+      stencilctl |= SC_szfailop_replace;
+      break;
+   case GL_INCR:
+      stencilctl |= SC_szfailop_incrsat;
+      break;
+   case GL_DECR:
+      stencilctl |= SC_szfailop_decrsat;
+      break;
+   case GL_INCR_WRAP:
+      stencilctl |= SC_szfailop_incr;
+      break;
+   case GL_DECR_WRAP:
+      stencilctl |= SC_szfailop_decr;
+      break;
+   case GL_INVERT:
+      stencilctl |= SC_szfailop_invert;
+      break;
+   default:
+      break;
+   }
 
-   /* This is a bit of a hack but seems to be the best place to ensure
-    * that separate specular is disabled when not needed.
-    */
-   if (mmesa->glCtx->Texture.Unit[0]._ReallyEnabled == 0 ||
-       !mmesa->glCtx->Light.Enabled ||
-       mmesa->glCtx->Light.Model.ColorControl == GL_SINGLE_COLOR) {
-      sarea->TexState[0].texctl2 &= ~TMC_specen_enable;
-      sarea->TexState[1].texctl2 &= ~TMC_specen_enable;
+   switch (ctx->Stencil.ZPassFunc[0])
+   {
+   case GL_KEEP:
+      stencilctl |= SC_szpassop_keep;
+      break;
+   case GL_ZERO:
+      stencilctl |= SC_szpassop_zero;
+      break;
+   case GL_REPLACE:
+      stencilctl |= SC_szpassop_replace;
+      break;
+   case GL_INCR:
+      stencilctl |= SC_szpassop_incrsat;
+      break;
+   case GL_DECR:
+      stencilctl |= SC_szpassop_decrsat;
+      break;
+   case GL_INVERT:
+      stencilctl |= SC_szpassop_invert;
+      break;
+   default:
+      break;
    }
-}
 
-/* Fallback to swrast for select and feedback.
- */
-static void mgaRenderMode( GLcontext *ctx, GLenum mode )
-{
-   FALLBACK( ctx, MGA_FALLBACK_RENDERMODE, (mode != GL_RENDER) );
+   FLUSH_BATCH( mmesa );
+   mmesa->hw.stencilctl &= (SC_sfailop_MASK & SC_szfailop_MASK 
+                           & SC_szpassop_MASK);
+   mmesa->hw.stencilctl |= stencilctl;
+   mmesa->dirty |= MGA_UPLOAD_CONTEXT;
 }
 
 
 /* =============================================================
+ * Window position and viewport transformation
  */
 
 void mgaCalcViewport( GLcontext *ctx )
@@ -850,9 +721,168 @@ static void mgaDepthRange( GLcontext *ctx,
    mgaCalcViewport( ctx );
 }
 
+
+/* =============================================================
+ * Miscellaneous
+ */
+
+static void mgaDDClearColor(GLcontext *ctx, 
+                           const GLfloat color[4] )
+{
+   mgaContextPtr mmesa = MGA_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]);
+   CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
+
+   mmesa->ClearColor = mgaPackColor( mmesa->mgaScreen->cpp,
+                                    c[0], c[1], c[2], c[3]);
+}
+
+
+/* Fallback to swrast for select and feedback.
+ */
+static void mgaRenderMode( GLcontext *ctx, GLenum mode )
+{
+   FALLBACK( ctx, MGA_FALLBACK_RENDERMODE, (mode != GL_RENDER) );
+}
+
+
+static void mgaDDLogicOp( GLcontext *ctx, GLenum opcode )
+{
+   mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+
+   FLUSH_BATCH( mmesa );
+#if defined(ACCEL_ROP)
+   mmesa->hw.rop = mgarop_NoBLK[ opcode & 0x0f ];
+   mmesa->dirty |= MGA_UPLOAD_CONTEXT;
+#else
+   FALLBACK( ctx, MGA_FALLBACK_LOGICOP,
+            (ctx->Color.ColorLogicOpEnabled && opcode != GL_COPY) );
+#endif
+}
+
+
+static void mgaXMesaSetFrontClipRects( mgaContextPtr mmesa )
+{
+   __DRIdrawablePrivate *driDrawable = mmesa->driDrawable;
+
+   if (driDrawable->numClipRects == 0) {
+       static XF86DRIClipRectRec zeroareacliprect = {0,0,0,0};
+       mmesa->numClipRects = 1;
+       mmesa->pClipRects = &zeroareacliprect;
+   } else {
+       mmesa->numClipRects = driDrawable->numClipRects;
+       mmesa->pClipRects = driDrawable->pClipRects;
+   }
+   mmesa->drawX = driDrawable->x;
+   mmesa->drawY = driDrawable->y;
+
+   mmesa->setup.dstorg = mmesa->drawOffset;
+   mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS;
+}
+
+
+static void mgaXMesaSetBackClipRects( mgaContextPtr mmesa )
+{
+   __DRIdrawablePrivate *driDrawable = mmesa->driDrawable;
+
+   if (driDrawable->numBackClipRects == 0)
+   {
+      if (driDrawable->numClipRects == 0) {
+         static XF86DRIClipRectRec zeroareacliprect = {0,0,0,0};
+         mmesa->numClipRects = 1;
+         mmesa->pClipRects = &zeroareacliprect;
+      } else {
+         mmesa->numClipRects = driDrawable->numClipRects;
+         mmesa->pClipRects = driDrawable->pClipRects;
+      }
+      mmesa->drawX = driDrawable->x;
+      mmesa->drawY = driDrawable->y;
+   } else {
+      mmesa->numClipRects = driDrawable->numBackClipRects;
+      mmesa->pClipRects = driDrawable->pBackClipRects;
+      mmesa->drawX = driDrawable->backX;
+      mmesa->drawY = driDrawable->backY;
+   }
+
+   mmesa->setup.dstorg = mmesa->drawOffset;
+   mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS;
+}
+
+
+void mgaUpdateRects( mgaContextPtr mmesa, GLuint buffers )
+{
+   __DRIdrawablePrivate *driDrawable = mmesa->driDrawable;
+   MGASAREAPrivPtr sarea = mmesa->sarea;
+
+
+   DRI_VALIDATE_DRAWABLE_INFO(mmesa->driScreen, driDrawable); 
+   mmesa->dirty_cliprects = 0; 
+
+   if (mmesa->draw_buffer == MGA_FRONT)
+      mgaXMesaSetFrontClipRects( mmesa );
+   else
+      mgaXMesaSetBackClipRects( mmesa );
+
+   sarea->req_draw_buffer = mmesa->draw_buffer;
+
+   mgaUpdateClipping( mmesa->glCtx );
+   mgaCalcViewport( mmesa->glCtx );
+
+   mmesa->dirty |= MGA_UPLOAD_CLIPRECTS;
+}
+
+
+static void mgaDDDrawBuffer(GLcontext *ctx, GLenum mode )
+{
+   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+
+   FLUSH_BATCH( mmesa );
+
+   /*
+    * _DrawDestMask is easier to cope with than <mode>.
+    */
+   switch ( ctx->Color._DrawDestMask ) {
+   case FRONT_LEFT_BIT:
+      mmesa->setup.dstorg = mmesa->mgaScreen->frontOffset;
+      mmesa->dirty |= MGA_UPLOAD_CONTEXT;
+      mmesa->draw_buffer = MGA_FRONT;
+      mgaXMesaSetFrontClipRects( mmesa );
+      FALLBACK( ctx, MGA_FALLBACK_DRAW_BUFFER, GL_FALSE );
+      break;
+   case BACK_LEFT_BIT:
+      mmesa->setup.dstorg = mmesa->mgaScreen->backOffset;
+      mmesa->draw_buffer = MGA_BACK;
+      mmesa->dirty |= MGA_UPLOAD_CONTEXT;
+      mgaXMesaSetBackClipRects( mmesa );
+      FALLBACK( ctx, MGA_FALLBACK_DRAW_BUFFER, GL_FALSE );
+      break;
+   default:
+      /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
+      FALLBACK( ctx, MGA_FALLBACK_DRAW_BUFFER, GL_TRUE );
+      return;
+   }
+
+   /* We want to update the s/w rast state too so that r200SetBuffer()
+    * gets called.
+    */
+   _swrast_DrawBuffer(ctx, mode);
+}
+
+
+static void mgaDDReadBuffer(GLcontext *ctx, GLenum mode )
+{
+   /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
+}
+
+
 /* =============================================================
+ * State enable/disable
  */
 
+
 static void mgaDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
 {
    mgaContextPtr mmesa = MGA_CONTEXT( ctx );
@@ -860,11 +890,11 @@ static void mgaDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
    switch(cap) {
    case GL_ALPHA_TEST:
       FLUSH_BATCH( mmesa );
-      mmesa->new_state |= MGA_NEW_ALPHA;
+      mmesa->hw.alpha_func_enable = (state) ? ~0 : 0;
       break;
    case GL_BLEND:
       FLUSH_BATCH( mmesa );
-      mmesa->new_state |= MGA_NEW_ALPHA;
+      mmesa->hw.blend_func_enable = (state) ? ~0 : 0;
 
       /* For some reason enable(GL_BLEND) affects ColorLogicOpEnabled.
        */
@@ -874,31 +904,31 @@ static void mgaDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
       break;
    case GL_DEPTH_TEST:
       FLUSH_BATCH( mmesa );
-      mmesa->new_state |= MGA_NEW_DEPTH;
       FALLBACK (ctx, MGA_FALLBACK_DEPTH,
                ctx->Depth.Func == GL_NEVER && ctx->Depth.Test);
       break;
+
    case GL_SCISSOR_TEST:
       FLUSH_BATCH( mmesa );
       mmesa->scissor = state;
-      mmesa->new_state |= MGA_NEW_CLIP;
+      mgaUpdateClipping( ctx );
       break;
+
    case GL_FOG:
       MGA_STATECHANGE( mmesa, MGA_UPLOAD_CONTEXT );
       if (ctx->Fog.Enabled) 
         mmesa->setup.maccess |= MA_fogen_enable;
       else
         mmesa->setup.maccess &= ~MA_fogen_enable;
+      
+      mgaChooseVertexState( ctx );
       break;
    case GL_CULL_FACE:
-      FLUSH_BATCH( mmesa );
-      mmesa->new_state |= MGA_NEW_CULL;
+      mgaDDCullFaceFrontFace( ctx, 0 );
       break;
    case GL_TEXTURE_1D:
    case GL_TEXTURE_2D:
    case GL_TEXTURE_3D:
-      FLUSH_BATCH( mmesa );
-      mmesa->new_state |= (MGA_NEW_TEXTURE|MGA_NEW_ALPHA);
       break;
    case GL_POLYGON_STIPPLE:
       if (mmesa->haveHwStipple && mmesa->raster_primitive == GL_TRIANGLES) {
@@ -914,16 +944,16 @@ static void mgaDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
 #if !defined(ACCEL_ROP)
       FALLBACK( ctx, MGA_FALLBACK_LOGICOP, 
                (state && ctx->Color.LogicOp != GL_COPY));
-#else
-      mmesa->new_state |= MGA_NEW_DEPTH;
 #endif
       break;
    case GL_STENCIL_TEST:
       FLUSH_BATCH( mmesa );
-      if (mmesa->hw_stencil)
-        mmesa->new_state |= MGA_NEW_STENCIL;
-      else
+      if (mmesa->hw_stencil) {
+        mmesa->hw.stencil_enable = ( state ) ? ~0 : 0;
+      }
+      else {
         FALLBACK( ctx, MGA_FALLBACK_STENCIL, state );
+      }
    default:
       break;
    }
@@ -933,56 +963,150 @@ static void mgaDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
 /* =============================================================
  */
 
-
-
-/* =============================================================
- */
-
-static void mgaDDPrintState( const char *msg, GLuint state )
+static void mgaDDPrintDirty( const char *msg, GLuint state )
 {
-   fprintf(stderr, "%s (0x%x): %s%s%s%s%s%s\n",
+   fprintf(stderr, "%s (0x%03x): %s%s%s%s%s%s%s\n",
           msg,
-          state,
-          (state & MGA_NEW_DEPTH)   ? "depth, " : "",
-          (state & MGA_NEW_ALPHA)   ? "alpha, " : "",
-          (state & MGA_NEW_CLIP)    ? "clip, " : "",
-          (state & MGA_NEW_CULL)    ? "cull, " : "",
-          (state & MGA_NEW_TEXTURE) ? "texture, " : "",
-          (state & MGA_NEW_CONTEXT) ? "context, " : "");
+          (unsigned int) state,
+          (state & MGA_WAIT_AGE)          ? "wait-age " : "",
+          (state & MGA_UPLOAD_TEX0IMAGE)  ? "upload-tex0-img " : "",
+          (state & MGA_UPLOAD_TEX1IMAGE)  ? "upload-tex1-img " : "",
+          (state & MGA_UPLOAD_CONTEXT)    ? "upload-ctx " : "",
+          (state & MGA_UPLOAD_TEX0)       ? "upload-tex0 " : "",
+          (state & MGA_UPLOAD_TEX1)       ? "upload-tex1 " : "",
+          (state & MGA_UPLOAD_PIPE)       ? "upload-pipe " : ""
+      );
 }
 
-void mgaDDUpdateHwState( GLcontext *ctx )
+/* Push the state into the sarea and/or texture memory.
+ */
+void mgaEmitHwStateLocked( mgaContextPtr mmesa )
 {
-   mgaContextPtr mmesa = MGA_CONTEXT( ctx );
-   int new_state = mmesa->new_state;
+   MGASAREAPrivPtr sarea = mmesa->sarea;
+   GLcontext * ctx = mmesa->glCtx;
 
-   if (new_state)
-   {
-      FLUSH_BATCH( mmesa );
+   if (MGA_DEBUG & DEBUG_VERBOSE_MSG)
+      mgaDDPrintDirty( __FUNCTION__, mmesa->dirty );
+
+   if (mmesa->dirty & MGA_UPLOAD_CONTEXT) {
+      mmesa->setup.wflag = _CULL_DISABLE;
+      if (mmesa->raster_primitive == GL_TRIANGLES) {
+        if ((ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT &&
+             ctx->Texture.Unit[1]._ReallyEnabled == TEXTURE_2D_BIT)) {
+           mmesa->setup.wflag = mmesa->hw.cull_dualtex;
+        }
+        else {
+           mmesa->setup.wflag = mmesa->hw.cull;
+        }
+      }
+
+      mmesa->setup.stencil = mmesa->hw.stencil 
+         & mmesa->hw.stencil_enable;
+      mmesa->setup.stencilctl = mmesa->hw.stencilctl
+         & mmesa->hw.stencil_enable;
 
-      mmesa->new_state = 0;
+      /* If depth testing is not enabled, then use the no Z-compare / no
+       * Z-write mode.  Otherwise, use whatever is set in hw.zmode.
+       */
+      mmesa->setup.dwgctl &= (DC_zmode_MASK & DC_atype_MASK);
+      mmesa->setup.dwgctl |= (ctx->Depth.Test)
+         ? mmesa->hw.zmode : (DC_zmode_nozcmp | DC_atype_i);
+
+#if defined(ACCEL_ROP)
+      mmesa->setup.dwgctl &= DC_bop_MASK;
+      mmesa->setup.dwgctl |= (ctx->Color.ColorLogicOpEnabled)
+         ? mmesa->hw.rop : mgarop_NoBLK[ GL_COPY & 0x0f ];
+#endif
+
+      mmesa->setup.alphactrl &= AC_src_MASK & AC_dst_MASK & AC_atmode_MASK
+         & AC_atref_MASK & AC_alphasel_MASK;
+      mmesa->setup.alphactrl |= 
+         ((mmesa->hw.alpha_func & mmesa->hw.alpha_func_enable)
+          | ((mmesa->hw.blend_func & mmesa->hw.blend_func_enable)
+             | ((AC_src_one | AC_dst_zero) & ~mmesa->hw.blend_func_enable))
+          | mmesa->hw.alpha_sel
+          | (AC_amode_alpha_channel
+             | AC_astipple_disable 
+             | AC_aten_disable 
+             | AC_atmode_noacmp));
+
+      memcpy( &sarea->ContextState, &mmesa->setup, sizeof(mmesa->setup));
+   }
+
+   if ((mmesa->dirty & MGA_UPLOAD_TEX0) && mmesa->CurrentTexObj[0]) {
+      mmesa->CurrentTexObj[0]->setup.texctl2 &= ~TMC_specen_enable;
+      mmesa->CurrentTexObj[0]->setup.texctl2 |= mmesa->hw.specen;
+
+      memcpy(&sarea->TexState[0],
+            &mmesa->CurrentTexObj[0]->setup,
+            sizeof(sarea->TexState[0]));
+   }
+
+   if ((mmesa->dirty & MGA_UPLOAD_TEX1) && mmesa->CurrentTexObj[1]) {
+      mmesa->CurrentTexObj[1]->setup.texctl2 &= ~TMC_specen_enable;
+      mmesa->CurrentTexObj[1]->setup.texctl2 |= mmesa->hw.specen;
+
+      memcpy(&sarea->TexState[1],
+            &mmesa->CurrentTexObj[1]->setup,
+            sizeof(sarea->TexState[1]));
+   }
+
+   if ( (sarea->TexState[0].texctl2 & TMC_borderen_MASK) !=
+       (sarea->TexState[1].texctl2 & TMC_borderen_MASK) ) {
+      const int borderen = sarea->TexState[1].texctl2 & ~TMC_borderen_MASK;
+
+      memcpy( &sarea->TexState[1], &sarea->TexState[0],
+             sizeof(sarea->TexState[0]) );
+      sarea->TexState[1].texctl2 |= borderen;
+      mmesa->dirty |= MGA_UPLOAD_TEX1|MGA_UPLOAD_TEX0;
+   }
+
+   if (mmesa->dirty & MGA_UPLOAD_PIPE) {
+/*        mmesa->sarea->wacceptseq = mmesa->hw_primitive; */
+      mmesa->sarea->WarpPipe = mmesa->vertex_format;
+      mmesa->sarea->vertsize = mmesa->vertex_size;
+   }
+
+   mmesa->sarea->dirty |= mmesa->dirty;
+   mmesa->dirty &= MGA_UPLOAD_CLIPRECTS;
+
+   /* This is a bit of a hack but seems to be the best place to ensure
+    * that separate specular is disabled when not needed.
+    */
+   if (ctx->Texture._EnabledUnits == 0 ||
+       !ctx->Light.Enabled ||
+       ctx->Light.Model.ColorControl == GL_SINGLE_COLOR) {
+      sarea->TexState[0].texctl2 &= ~TMC_specen_enable;
+      sarea->TexState[1].texctl2 &= ~TMC_specen_enable;
+   }
+}
+
+
+/* =============================================================
+ */
 
-      if (MESA_VERBOSE&VERBOSE_DRIVER)
-        mgaDDPrintState("UpdateHwState", new_state);
 
-      if (new_state & MGA_NEW_DEPTH)
-        mgaUpdateZMode(ctx);
+static void mgaDDValidateState( GLcontext *ctx )
+{
+   mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+   int new_state = mmesa->NewGLState;
 
-      if (new_state & MGA_NEW_ALPHA)
-        mgaUpdateAlphaMode(ctx);
 
-      if (new_state & MGA_NEW_CLIP)
-        mgaUpdateClipping(ctx);
+   FLUSH_BATCH( mmesa );
 
-      if (new_state & MGA_NEW_STENCIL)
-        mgaUpdateStencil(ctx);
+   if (mmesa->NewGLState & _MGA_NEW_RASTERSETUP) {
+      mgaChooseVertexState( ctx );
+   }
 
-      if (new_state & (MGA_NEW_WARP|MGA_NEW_CULL))
-        mgaUpdateCull(ctx);
+   if (mmesa->NewGLState & _MGA_NEW_RENDERSTATE) {
+      mgaChooseRenderState( ctx );
+   }
 
-      if (new_state & (MGA_NEW_WARP|MGA_NEW_TEXTURE))
-        mgaUpdateTextureState(ctx);
+   if (new_state & _NEW_TEXTURE) {
+      mgaUpdateTextureState(ctx);
    }
+
+   mmesa->NewGLState = 0;
 }
 
 
@@ -992,25 +1116,40 @@ static void mgaDDInvalidateState( GLcontext *ctx, GLuint new_state )
    _swsetup_InvalidateState( ctx, new_state );
    _ac_InvalidateState( ctx, new_state );
    _tnl_InvalidateState( ctx, new_state );
-   MGA_CONTEXT(ctx)->new_gl_state |= new_state;
+   MGA_CONTEXT(ctx)->NewGLState |= new_state;
 }
 
 
+static void mgaRunPipeline( GLcontext *ctx )
+{
+   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+
+   if (mmesa->NewGLState) {
+      mgaDDValidateState( ctx );
+   }
+
+   if (mmesa->dirty) {
+       mgaEmitHwStateLocked( mmesa );
+   }
+
+   _tnl_run_pipeline( ctx );
+}
+
 
 void mgaInitState( mgaContextPtr mmesa )
 {
    mgaScreenPrivate *mgaScreen = mmesa->mgaScreen;
    GLcontext *ctx = mmesa->glCtx;
 
-   if (ctx->Color._DrawDestMask == BACK_LEFT_BIT) {
+   if (ctx->Visual.doubleBufferMode) {
+      /* use back buffer by default */
       mmesa->draw_buffer = MGA_BACK;
-      mmesa->read_buffer = MGA_BACK;
       mmesa->drawOffset = mmesa->mgaScreen->backOffset;
       mmesa->readOffset = mmesa->mgaScreen->backOffset;
       mmesa->setup.dstorg = mgaScreen->backOffset;
    } else {
+      /* use front buffer by default */
       mmesa->draw_buffer = MGA_FRONT;
-      mmesa->read_buffer = MGA_FRONT;
       mmesa->drawOffset = mmesa->mgaScreen->frontOffset;
       mmesa->readOffset = mmesa->mgaScreen->frontOffset;
       mmesa->setup.dstorg = mgaScreen->frontOffset;
@@ -1043,14 +1182,21 @@ void mgaInitState( mgaContextPtr mmesa )
       mmesa->setup.maccess |= MA_zwidth_24;
       break;
    case 32:
-      mmesa->setup.maccess |= MA_pwidth_32;
+      mmesa->setup.maccess |= MA_zwidth_32;
       break;
    }
 
+   mmesa->hw.zmode = DC_zmode_zlt | DC_atype_zi;
+   mmesa->hw.stencil = (0x0ff << S_smsk_SHIFT) | (0x0ff << S_swtmsk_SHIFT);
+   mmesa->hw.stencilctl = SC_smode_salways | SC_sfailop_keep 
+       | SC_szfailop_keep | SC_szpassop_keep;
+   mmesa->hw.stencil_enable = 0;
+   mmesa->hw.cull = _CULL_NEGATIVE;
+   mmesa->hw.cull_dualtex = _CULL_POSITIVE;
+   mmesa->hw.specen = 0;
+
    mmesa->setup.dwgctl = (DC_opcod_trap |
-                         DC_atype_i |
                          DC_linear_xy |
-                         DC_zmode_nozcmp |
                          DC_solid_disable |
                          DC_arzero_disable |
                          DC_sgnzero_disable |
@@ -1072,16 +1218,15 @@ void mgaInitState( mgaContextPtr mmesa )
                              AC_atmode_noacmp |
                              AC_alphasel_fromtex );
 
-   mmesa->setup.fogcolor =
-      MGAPACKCOLOR888((GLubyte)(ctx->Fog.Color[0]*255.0F),
-                     (GLubyte)(ctx->Fog.Color[1]*255.0F),
-                     (GLubyte)(ctx->Fog.Color[2]*255.0F));
+   mmesa->setup.fogcolor = PACK_COLOR_888((GLubyte)(ctx->Fog.Color[0]*255.0F),
+                                         (GLubyte)(ctx->Fog.Color[1]*255.0F),
+                                         (GLubyte)(ctx->Fog.Color[2]*255.0F));
 
    mmesa->setup.wflag = 0;
    mmesa->setup.tdualstage0 = 0;
    mmesa->setup.tdualstage1 = 0;
    mmesa->setup.fcol = 0;
-   mmesa->new_state = ~0;
+   mmesa->dirty |= MGA_UPLOAD_CONTEXT;
 }
 
 
@@ -1103,8 +1248,8 @@ void mgaDDInitStateFuncs( GLcontext *ctx )
    ctx->Driver.FrontFace = mgaDDCullFaceFrontFace;
    ctx->Driver.ColorMask = mgaDDColorMask;
 
-   ctx->Driver.DrawBuffer = mgaDDSetDrawBuffer;
-   ctx->Driver.ReadBuffer = mgaDDSetReadBuffer;
+   ctx->Driver.DrawBuffer = mgaDDDrawBuffer;
+   ctx->Driver.ReadBuffer = mgaDDReadBuffer;
    ctx->Driver.ClearColor = mgaDDClearColor;
    ctx->Driver.ClearDepth = mgaDDClearDepth;
    ctx->Driver.LogicOpcode = mgaDDLogicOp;
@@ -1128,4 +1273,6 @@ void mgaDDInitStateFuncs( GLcontext *ctx )
    ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
    ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
    ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
+
+   TNL_CONTEXT(ctx)->Driver.RunPipeline = mgaRunPipeline;
 }
index a9f1039d760e02a79e8dec8b5edbe2911f37fa9a..afbe0aaf904459de21ea8a94eea0c28cd4855be9 100644 (file)
 #ifndef _MGA_STATE_H
 #define _MGA_STATE_H
 
-
 extern void mgaInitState( mgaContextPtr mmesa );
 extern void mgaDDInitStateFuncs(GLcontext *ctx);
-extern void mgaDDUpdateHwState( GLcontext *ctx );
 extern void mgaUpdateClipping(const GLcontext *ctx);
 extern void mgaUpdateCull( GLcontext *ctx );
 extern void mgaCalcViewport( GLcontext *ctx );
-
-
+extern void mgaUpdateRects( mgaContextPtr mmesa, GLuint buffers );
 
 #endif
index b4ee787e0b8af9dad8eb7a56ae29e6a5255b46dc..82eccc81498f447b94056692c4397388a8f553fb 100644 (file)
  */
 /* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgatex.c,v 1.14 2002/10/30 12:51:36 alanh Exp $ */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <GL/gl.h>
-
+#include "glheader.h"
 #include "mm.h"
 #include "mgacontext.h"
 #include "mgatex.h"
 #include "mgatris.h"
 #include "mgaioctl.h"
 
+#include "colormac.h"
+#include "context.h"
 #include "enums.h"
 #include "simple_list.h"
-/*#include "mem.h"*/
+#include "imports.h"
 #include "macros.h"
 #include "texformat.h"
 #include "texstore.h"
 
 #include "swrast/swrast.h"
 
-#define TEX_0 1
-#define TEX_1 2
-
-/*
- * mgaDestroyTexObj
- * Free all memory associated with a texture and NULL any pointers
- * to it.
+/**
+ * Set the texture wrap modes.
+ * Currently \c GL_REPEAT, \c GL_CLAMP and \c GL_CLAMP_TO_EDGE are supported.
+ * 
+ * \param t Texture object whose wrap modes are to be set
+ * \param swrap Wrap mode for the \a s texture coordinate
+ * \param twrap Wrap mode for the \a t texture coordinate
  */
-void
-mgaDestroyTexObj( mgaContextPtr mmesa, mgaTextureObjectPtr t )
+
+static void 
+mgaSetTexWrapping( mgaTextureObjectPtr t, GLenum swrap, GLenum twrap )
 {
-   if ( !t ) return;
+   GLboolean  is_clamp = GL_FALSE;
+   GLboolean  is_clamp_to_edge = GL_FALSE;
 
-   /* free the texture memory */
-   if (t->MemBlock) {
-      mmFreeMem( t->MemBlock );
-      t->MemBlock = 0;
+   t->setup.texctl &= (TMC_clampu_MASK & TMC_clampv_MASK);
+   t->setup.texctl2 &= (TMC_borderen_MASK);
 
-      if (mmesa && t->age > mmesa->dirtyAge)
-        mmesa->dirtyAge = t->age;
+   switch( swrap ) {
+   case GL_REPEAT:
+      break;
+   case GL_CLAMP:
+      t->setup.texctl |= TMC_clampu_enable;
+      is_clamp = GL_TRUE;
+      break;
+   case GL_CLAMP_TO_EDGE:
+      t->setup.texctl |= TMC_clampu_enable;
+      is_clamp_to_edge = GL_TRUE;
+      break;
+   default:
+      _mesa_problem(NULL, "bad S wrap mode in %s", __FUNCTION__);
    }
 
-   /* free mesa's link */
-   if (t->tObj)
-      t->tObj->DriverData = NULL;
-
-   /* see if it was the driver's current object */
-   if (mmesa) {
-      if (t->bound & TEX_0) mmesa->CurrentTexObj[0] = 0;
-      if (t->bound & TEX_1) mmesa->CurrentTexObj[1] = 0;
+   switch( twrap ) {
+   case GL_REPEAT:
+      break;
+   case GL_CLAMP:
+      t->setup.texctl |= TMC_clampv_enable;
+      is_clamp = GL_TRUE;
+      break;
+   case GL_CLAMP_TO_EDGE:
+      t->setup.texctl |= TMC_clampv_enable;
+      is_clamp_to_edge = GL_TRUE;
+      break;
+   default:
+      _mesa_problem(NULL, "bad T wrap mode in %s", __FUNCTION__);
    }
-       
-   remove_from_list(t);
-   free( t );
-}
 
+   if ( is_clamp ) {
+      t->setup.texctl2 |= TMC_borderen_enable;
+   }
 
-/*
- * mgaSetTexWrappings
- */
-static void mgaSetTexWrapping( mgaTextureObjectPtr t,
-                              GLenum sWrap,
-                              GLenum tWrap )
-{
-   GLuint val = 0;
-
-   if (sWrap != GL_REPEAT)
-      val |= TMC_clampu_enable;
-
-   if (tWrap != GL_REPEAT)
-      val |= TMC_clampv_enable;
-
-   t->setup.texctl &= ~(TMC_clampu_enable|TMC_clampv_enable);
-   t->setup.texctl |= val;
+   t->border_fallback = (is_clamp && is_clamp_to_edge);
 }
 
 
-/*
- * mgaSetTexFilter
+/**
+ * Set the texture magnification and minification modes.
+ * 
+ * \param t Texture whose filter modes are to be set
+ * \param minf Texture minification mode
+ * \param magf Texture magnification mode
  */
-static void mgaSetTexFilter(mgaTextureObjectPtr t, GLenum minf, GLenum magf)
+
+static void
+mgaSetTexFilter( mgaTextureObjectPtr t, GLenum minf, GLenum magf )
 {
    GLuint val = 0;
 
@@ -136,123 +140,79 @@ static void mgaSetTexFilter(mgaTextureObjectPtr t, GLenum minf, GLenum magf)
    }
 
 
-   t->setup.texfilter &= (TF_minfilter_MASK |
-                         TF_magfilter_MASK |
+   /* Mask off the bits for the fields we are setting.  Remember, the MGA mask
+    * defines have 0s for the bits in the named fields.  This is the opposite
+    * of most of the other drivers.
+    */
+
+   t->setup.texfilter &= (TF_minfilter_MASK &
+                         TF_magfilter_MASK &
                          TF_fthres_MASK);
    t->setup.texfilter |= val;
 }
 
-/*
- * mgaSetTexBorderColor
- */
 static void mgaSetTexBorderColor(mgaTextureObjectPtr t, GLubyte color[4])
 {
-   t->setup.texbordercol = MGAPACKCOLOR8888(color[0],color[1],
-                                           color[2],color[3]);
+   t->setup.texbordercol = PACK_COLOR_8888(color[3], color[0], 
+                                          color[1], color[2] );
 }
 
 
-static GLint mgaChooseTexFormat( mgaContextPtr mmesa,
-                                struct gl_texture_image *texImage,
-                                GLenum format, GLenum type )
+static const struct gl_texture_format *
+mgaChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
+                       GLenum format, GLenum type )
 {
+   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
    const GLboolean do32bpt = mmesa->default32BitTextures;
-   const struct gl_texture_format *texFormat;
-   GLint ret;
-
-   if ( 0 )
-      fprintf( stderr, "internal=%s format=%s type=%s\n",
-              texImage->IntFormat == 3 ? "GL_RGB (3)" :
-              texImage->IntFormat == 4 ? "GL_RGBA (4)" :
-              _mesa_lookup_enum_by_nr( texImage->IntFormat ),
-              _mesa_lookup_enum_by_nr( format ),
-              _mesa_lookup_enum_by_nr( type ) );
-
-#define SET_FORMAT( r, gl )                                            \
-   do {                                                                        \
-      ret = (r);                                                       \
-      texFormat = &(gl);                                               \
-   } while (0)
-
-#define SET_FORMAT_32BPT( r32, gl32, r16, gl16 )                       \
-   do {                                                                        \
-      if ( do32bpt ) {                                                 \
-        ret = (r32);                                                   \
-        texFormat = &(gl32);                                           \
-      } else {                                                         \
-        ret = (r16);                                                   \
-        texFormat = &(gl16);                                           \
-      }                                                                        \
-   } while (0)
-
-   switch ( texImage->IntFormat ) {
-      /* GH: Bias towards GL_RGB, GL_RGBA texture formats.  This has
-       * got to be better than sticking them way down the end of this
-       * huge list.
-       */
+
+   switch ( internalFormat ) {
    case 4:
    case GL_RGBA:
    case GL_COMPRESSED_RGBA:
       if ( format == GL_BGRA ) {
         if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
-           SET_FORMAT( TMC_tformat_tw32, _mesa_texformat_argb8888 );
-           break;
-        } else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
-           SET_FORMAT( TMC_tformat_tw12, _mesa_texformat_argb4444 );
-           break;
-        } else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
-           SET_FORMAT( TMC_tformat_tw15, _mesa_texformat_argb1555 );
-           break;
+           return &_mesa_texformat_argb8888;
+        }
+         else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
+            return &_mesa_texformat_argb4444;
+        }
+         else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
+           return &_mesa_texformat_argb1555;
         }
       }
-      SET_FORMAT_32BPT( TMC_tformat_tw32, _mesa_texformat_argb8888,
-                       TMC_tformat_tw12, _mesa_texformat_argb4444 );
-      break;
+      return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
 
    case 3:
    case GL_RGB:
    case GL_COMPRESSED_RGB:
       if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
-        SET_FORMAT( TMC_tformat_tw16, _mesa_texformat_rgb565 );
-        break;
+        return &_mesa_texformat_rgb565;
       }
-      SET_FORMAT_32BPT( TMC_tformat_tw32, _mesa_texformat_argb8888,
-                       TMC_tformat_tw16, _mesa_texformat_rgb565 );
-      break;
+      return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
 
-      /* GH: Okay, keep checking as normal.  Still test for GL_RGB,
-       * GL_RGBA formats first.
-       */
    case GL_RGBA8:
    case GL_RGB10_A2:
    case GL_RGBA12:
    case GL_RGBA16:
-      SET_FORMAT_32BPT( TMC_tformat_tw32, _mesa_texformat_argb8888,
-                       TMC_tformat_tw12, _mesa_texformat_argb4444 );
-      break;
+      return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444;
 
    case GL_RGBA4:
    case GL_RGBA2:
-      SET_FORMAT( TMC_tformat_tw12, _mesa_texformat_argb4444 );
-      break;
+      return &_mesa_texformat_argb4444;
 
    case GL_RGB5_A1:
-      SET_FORMAT( TMC_tformat_tw15, _mesa_texformat_argb1555 );
-      break;
+      return &_mesa_texformat_argb1555;
 
    case GL_RGB8:
    case GL_RGB10:
    case GL_RGB12:
    case GL_RGB16:
-      SET_FORMAT_32BPT( TMC_tformat_tw32, _mesa_texformat_argb8888,
-                       TMC_tformat_tw16, _mesa_texformat_rgb565 );
-      break;
+      return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565;
 
    case GL_RGB5:
    case GL_RGB4:
    case GL_R3_G3_B2:
-      SET_FORMAT( TMC_tformat_tw16, _mesa_texformat_rgb565 );
-      break;
+      return &_mesa_texformat_rgb565;
 
    case GL_ALPHA:
    case GL_ALPHA4:
@@ -261,8 +221,7 @@ static GLint mgaChooseTexFormat( mgaContextPtr mmesa,
    case GL_ALPHA16:
    case GL_COMPRESSED_ALPHA:
       /* FIXME: This will report incorrect component sizes... */
-      SET_FORMAT( TMC_tformat_tw12, _mesa_texformat_argb4444 );
-      break;
+      return &_mesa_texformat_argb4444;
 
    case 1:
    case GL_LUMINANCE:
@@ -272,8 +231,7 @@ static GLint mgaChooseTexFormat( mgaContextPtr mmesa,
    case GL_LUMINANCE16:
    case GL_COMPRESSED_LUMINANCE:
       /* FIXME: This will report incorrect component sizes... */
-      SET_FORMAT( TMC_tformat_tw16, _mesa_texformat_rgb565 );
-      break;
+      return &_mesa_texformat_rgb565;
 
    case 2:
    case GL_LUMINANCE_ALPHA:
@@ -285,8 +243,7 @@ static GLint mgaChooseTexFormat( mgaContextPtr mmesa,
    case GL_LUMINANCE16_ALPHA16:
    case GL_COMPRESSED_LUMINANCE_ALPHA:
       /* FIXME: This will report incorrect component sizes... */
-      SET_FORMAT( TMC_tformat_tw12, _mesa_texformat_argb4444 );
-      break;
+      return &_mesa_texformat_argb4444;
 
    case GL_INTENSITY:
    case GL_INTENSITY4:
@@ -295,8 +252,15 @@ static GLint mgaChooseTexFormat( mgaContextPtr mmesa,
    case GL_INTENSITY16:
    case GL_COMPRESSED_INTENSITY:
       /* FIXME: This will report incorrect component sizes... */
-      SET_FORMAT( TMC_tformat_tw12, _mesa_texformat_argb4444 );
-      break;
+      return &_mesa_texformat_argb4444;
+
+   case GL_YCBCR_MESA:
+      if (MGA_IS_G400(mmesa) &&
+          (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
+           type == GL_UNSIGNED_BYTE))
+         return &_mesa_texformat_ycbcr;
+      else
+         return &_mesa_texformat_ycbcr_rev;
 
    case GL_COLOR_INDEX:
    case GL_COLOR_INDEX1_EXT:
@@ -305,502 +269,78 @@ static GLint mgaChooseTexFormat( mgaContextPtr mmesa,
    case GL_COLOR_INDEX8_EXT:
    case GL_COLOR_INDEX12_EXT:
    case GL_COLOR_INDEX16_EXT:
-      SET_FORMAT( TMC_tformat_tw8, _mesa_texformat_ci8 );
-      break;
+      return &_mesa_texformat_ci8;
 
    default:
-      fprintf( stderr, "bad texture format in mgaChooseTexFormat() %d",
-              texImage->IntFormat );
-      return -1;
+      _mesa_problem( ctx, "unexpected texture format in %s", __FUNCTION__ );
+      return NULL;
    }
 
-   texImage->TexFormat = texFormat;
-
-   return ret;
+   return NULL; /* never get here */
 }
 
 
-/*
- * mgaCreateTexObj
+
+
+/**
  * Allocate space for and load the mesa images into the texture memory block.
  * This will happen before drawing with a new texture, or drawing with a
  * texture after it was swapped out or teximaged again.
  */
-static void mgaCreateTexObj(mgaContextPtr mmesa,
-                           struct gl_texture_object *tObj)
-{
-   const GLint baseLevel = tObj->BaseLevel;
-   struct gl_texture_image *image = tObj->Image[baseLevel];
-   mgaTextureObjectPtr t;
-   int i, ofs;
-   int LastLevel;
-   int s, s2;
-   int tformat;
-
-   if (!image) return;
-
-   tObj->DriverData = t = calloc( 1, sizeof( *t ) );
-   if (!t) {
-      fprintf(stderr, "mgaCreateTexObj: Failed to malloc mgaTextureObject\n" );
-      return;
-   }
-
-   /* FIXME: Use the real DD interface...
-    */
-   tformat = mgaChooseTexFormat( mmesa, image, image->Format,
-                                GL_UNSIGNED_BYTE );
-   t->texelBytes = image->TexFormat->TexelBytes;
-
-   /* We are going to upload all levels that are present, even if
-    * later levels wouldn't be used by the current filtering mode.  This
-    * allows the filtering mode to change without forcing another upload
-    * of the images.
-    */
-   LastLevel = MGA_TEX_MAXLEVELS-1;
-
-   ofs = 0;
-   for ( i = 0 ; i <= LastLevel ; i++ ) {
-      if ( !tObj->Image[i] ) {
-        LastLevel = i - 1;
-        break;
-      }
-
-      t->offsets[i] = ofs;
-      t->dirty_images |= (1<<i);
-
-      ofs += ((MAX2( tObj->Image[i]->Width, 8 ) *
-              MAX2( tObj->Image[i]->Height, 8 ) *
-              t->texelBytes) + 31) & ~31;
-   }
-   t->totalSize = ofs;
-   t->lastLevel = LastLevel;
-   t->tObj = tObj;
-   t->ctx = mmesa;
-   t->age = 0;
-   t->bound = 0;
-   t->MemBlock = 0;
-
-   insert_at_tail(&(mmesa->SwappedOut), t);
-
-
-   /* setup hardware register values */
-   t->setup.texctl = TMC_takey_1 | TMC_tamask_0 | tformat;
-
-   if (image->WidthLog2 >= 3)
-      t->setup.texctl |= ((image->WidthLog2 - 3) << TMC_tpitch_SHIFT);
-   else
-      t->setup.texctl |= (TMC_tpitchlin_enable |
-                         (image->Width << TMC_tpitchext_SHIFT));
-
-
-   t->setup.texctl2 = TMC_ckstransdis_enable;
-
-   if ( mmesa->glCtx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR )
-      t->setup.texctl2 |= TMC_specen_enable;
-
-
-   t->setup.texfilter = (TF_minfilter_nrst |
-                        TF_magfilter_nrst |
-                        TF_filteralpha_enable |
-                        (0x10 << TF_fthres_SHIFT) |
-                        (LastLevel << TF_mapnb_SHIFT));
-
-   /* warp texture registers */
-   ofs = MGA_IS_G200(mmesa) ? 28 : 11;
-   s = image->Width;
-   s2 = image->WidthLog2;
-   t->setup.texwidth = (MGA_FIELD(TW_twmask, s - 1) |
-                       MGA_FIELD(TW_rfw, (10 - s2 - 8) & 63 ) |
-                       MGA_FIELD(TW_tw, (s2 + ofs ) | 0x40 ));
-
 
-   s = image->Height;
-   s2 = image->HeightLog2;
-   t->setup.texheight = (MGA_FIELD(TH_thmask, s - 1) |
-                        MGA_FIELD(TH_rfh, (10 - s2 - 8) & 63 ) |
-                        MGA_FIELD(TH_th, (s2 + ofs ) | 0x40 ));
-
-
-   /* set all the register values for filtering, border, etc */
-   mgaSetTexWrapping( t, tObj->WrapS, tObj->WrapT );
-   mgaSetTexFilter( t, tObj->MinFilter, tObj->MagFilter );
-   mgaSetTexBorderColor( t, tObj->_BorderChan );
-}
-
-
-
-
-static void mgaUpdateTextureEnvG200( GLcontext *ctx )
+static mgaTextureObjectPtr
+mgaAllocTexObj( struct gl_texture_object *tObj )
 {
-   struct gl_texture_object *tObj = ctx->Texture.Unit[0]._Current;
    mgaTextureObjectPtr t;
 
-   if (!tObj || !tObj->DriverData)
-      return;
-
-   t = (mgaTextureObjectPtr)tObj->DriverData;
-
-   t->setup.texctl2 &= ~TMC_decalblend_enable;
-
-   switch (ctx->Texture.Unit[0].EnvMode) {
-   case GL_REPLACE:
-      t->setup.texctl &= ~TMC_tmodulate_enable;
-      break;
-   case GL_MODULATE:
-      t->setup.texctl |= TMC_tmodulate_enable;
-      break;
-   case GL_DECAL:
-      t->setup.texctl &= ~TMC_tmodulate_enable;
-      t->setup.texctl2 |= TMC_decalblend_enable;
-      break;
-   case GL_BLEND:
-      FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
-      break;
-   default:
-      break;
-   }
-}
-
-static void mgaUpdateTextureEnvG400( GLcontext *ctx, int unit )
-{
-   mgaContextPtr mmesa = MGA_CONTEXT( ctx );
-   GLuint *reg = ((GLuint *)&mmesa->setup.tdualstage0 + unit);
-   GLuint source = mmesa->tmu_source[unit];
-   struct gl_texture_object *tObj = ctx->Texture.Unit[source]._Current;
-   GLenum format;
-
-   if ( tObj != ctx->Texture.Unit[source].Current2D || !tObj ) 
-      return;
-
-   format = tObj->Image[tObj->BaseLevel]->Format;
-
-   switch (ctx->Texture.Unit[source].EnvMode) {
-   case GL_REPLACE:
-      if (format == GL_RGB || format == GL_LUMINANCE) {
-        *reg = (TD0_color_sel_arg1 |
-                 TD0_alpha_arg2_diffuse |
-                TD0_alpha_sel_arg2 );
-      }
-      else if (format == GL_ALPHA) {
-         *reg = (TD0_color_sel_arg2 |
-                 TD0_color_arg2_diffuse |
-                 TD0_alpha_sel_arg1 );
-      }
-      else {
-         *reg = (TD0_color_sel_arg1 |
-                 TD0_alpha_sel_arg1 );
-      }
-      break;
-
-   case GL_MODULATE:
-      if (unit == 0) {
-        *reg = ( TD0_color_arg2_diffuse |
-                 TD0_color_sel_mul |
-                 TD0_alpha_arg2_diffuse |
-                 TD0_alpha_sel_mul);
-      }
-      else {
-        *reg = ( TD0_color_arg2_prevstage |
-                 TD0_color_alpha_prevstage |
-                 TD0_color_sel_mul |
-                 TD0_alpha_arg2_prevstage |
-                 TD0_alpha_sel_mul);
-      }
-      break;
-   case GL_DECAL:
-      if (format == GL_RGB) {
-         if (unit == 0) {
-            *reg = (TD0_color_sel_arg1 |
-                    TD0_alpha_arg2_diffuse |
-                    TD0_alpha_sel_arg2 );
-         }
-         else {
-            *reg = (TD0_color_sel_arg1 |
-                    TD0_alpha_arg2_prevstage |
-                    TD0_alpha_sel_arg2 );
-         }
-      }
-      else if ( format == GL_RGBA ) {
-#if 0
-         if (unit == 0) {
-            /* this doesn't work */
-            *reg = (TD0_color_arg2_diffuse |
-                    TD0_color_alpha_currtex |
-                    TD0_color_alpha2inv_enable |
-                    TD0_color_arg2mul_alpha2 |
-                    TD0_color_arg1mul_alpha1 |
-                    TD0_color_blend_enable |
-                    TD0_color_arg1add_mulout |
-                    TD0_color_arg2add_mulout |
-                    TD0_color_add_add |
-                    TD0_color_sel_mul |
-                    TD0_alpha_arg2_diffuse |
-                    TD0_alpha_sel_arg2 );
-         }
-         else {
-            *reg = (TD0_color_arg2_prevstage |
-                    TD0_color_alpha_currtex |
-                    TD0_color_alpha2inv_enable |
-                    TD0_color_arg2mul_alpha2 |
-                    TD0_color_arg1mul_alpha1 |
-                    TD0_color_add_add |
-                    TD0_color_sel_add |
-                    TD0_alpha_arg2_prevstage |
-                    TD0_alpha_sel_arg2 );
-         }
-#else
-         /* s/w fallback, pretty sure we can't do in h/w */
-        FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
-        if ( MGA_DEBUG & DEBUG_VERBOSE_FALLBACK )
-           fprintf( stderr, "FALLBACK: GL_DECAL RGBA texture, unit=%d\n",
-                    unit );
-#endif
-      }
-      else {
-        if (unit == 0) {
-           *reg = ( TD0_color_arg2_diffuse |
-                    TD0_color_sel_arg2 |
-                    TD0_alpha_arg2_diffuse |
-                    TD0_alpha_sel_arg2);
-        }
-        else {
-           *reg = ( TD0_color_arg2_prevstage |
-                    TD0_color_sel_arg2 |
-                    TD0_alpha_arg2_prevstage |
-                    TD0_alpha_sel_arg2);
-        }
-      }
-      break;
-
-   case GL_ADD:
-      if (unit == 0) {
-         if (format == GL_INTENSITY)
-            *reg = ( TD0_color_arg2_diffuse |
-                     TD0_color_add_add |
-                     TD0_color_sel_add |
-                     TD0_alpha_arg2_diffuse |
-                     TD0_alpha_add_enable |
-                     TD0_alpha_sel_add);
-         else if (format == GL_ALPHA)
-            *reg = ( TD0_color_arg2_diffuse |
-                     TD0_color_sel_mul |
-                     TD0_alpha_arg2_diffuse |
-                     TD0_alpha_sel_mul);
-         else
-            *reg = ( TD0_color_arg2_diffuse |
-                     TD0_color_add_add |
-                     TD0_color_sel_add |
-                     TD0_alpha_arg2_diffuse |
-                     TD0_alpha_sel_mul);
-      }
-      else {
-         if (format == GL_INTENSITY) {
-            *reg = ( TD0_color_arg2_prevstage |
-                     TD0_color_add_add |
-                     TD0_color_sel_add |
-                     TD0_alpha_arg2_prevstage |
-                     TD0_alpha_add_enable |
-                     TD0_alpha_sel_add);
-         }
-         else if (format == GL_ALPHA) {
-            *reg = ( TD0_color_arg2_prevstage |
-                     TD0_color_sel_mul |
-                     TD0_alpha_arg2_prevstage |
-                     TD0_alpha_sel_mul);
-         }
-         else {
-            *reg = ( TD0_color_arg2_prevstage |
-                     TD0_color_alpha_prevstage |
-                     TD0_color_add_add |
-                     TD0_color_sel_add |
-                     TD0_alpha_arg2_prevstage |
-                     TD0_alpha_sel_mul);
-         }
-      }
-      break;
-
-   case GL_BLEND:
-      if (format == GL_ALPHA) {
-        *reg = ( TD0_color_arg2_diffuse |
-                 TD0_color_sel_mul |
-                 TD0_alpha_arg2_diffuse |
-                 TD0_alpha_sel_mul);
-      }
-      else {
-        FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
-        if ( MGA_DEBUG & DEBUG_VERBOSE_FALLBACK )
-           fprintf( stderr, "FALLBACK: GL_BLEND envcolor=0x%08x\n",
-                    mmesa->envcolor );
-
-         /* Do singletexture GL_BLEND with 'all ones' env-color
-          * by using both texture units.  Multitexture gl_blend
-          * is a fallback.
-          */
-         if (unit == 0) {
-            /* Part 1: R1 = Rf ( 1 - Rt )
-             *         A1 = Af At
-             */
-            *reg = ( TD0_color_arg2_diffuse |
-                     TD0_color_arg1_inv_enable |
-                     TD0_color_sel_mul |
-                     TD0_alpha_arg2_diffuse |
-                     TD0_alpha_sel_arg1);
-         } else {
-            /* Part 2: R2 = R1 + Rt
-             *         A2 = A1
-             */
-            *reg = ( TD0_color_arg2_prevstage |
-                     TD0_color_add_add |
-                     TD0_color_sel_add |
-                     TD0_alpha_arg2_prevstage |
-                     TD0_alpha_sel_arg2);
-         }
-      }
-      break;
-   default:
-      break;
-   }
-}
-
-
-
-static void mgaUpdateTextureObject( GLcontext *ctx, int hw_unit )
-{
-   mgaTextureObjectPtr t;
-   struct gl_texture_object    *tObj;
-   GLuint enabled;
-   mgaContextPtr mmesa = MGA_CONTEXT( ctx );
-   GLuint gl_unit = mmesa->tmu_source[hw_unit];
-
-
-   enabled = ctx->Texture.Unit[gl_unit]._ReallyEnabled;
-   tObj = ctx->Texture.Unit[gl_unit]._Current;
-
-   if (enabled != TEXTURE_2D_BIT) {
-      if (enabled)
-        FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
-      return;
-   }
-
-   if (tObj->Image[tObj->BaseLevel]->Border > 0) {
-      FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
-      if ( MGA_DEBUG & DEBUG_VERBOSE_FALLBACK )
-        fprintf( stderr, "FALLBACK: texture border\n" );
-      return;
-   }
-
-   if ( !tObj->DriverData ) {
-      mgaCreateTexObj( mmesa, tObj );
-      if ( !tObj->DriverData ) {
-        FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
-        return;                
-      }
-   }
-
-   t = (mgaTextureObjectPtr)tObj->DriverData;
-
-   if (t->dirty_images)
-      mmesa->dirty |= (MGA_UPLOAD_TEX0IMAGE << hw_unit);
-
-   mmesa->CurrentTexObj[hw_unit] = t;
-   t->bound |= hw_unit+1;
-
-/*     if (t->MemBlock) */
-/*        mgaUpdateTexLRU( mmesa, t ); */
-
-   t->setup.texctl2 &= ~TMC_dualtex_enable;
-   if ((ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT) &&
-       (ctx->Texture.Unit[1]._ReallyEnabled == TEXTURE_2D_BIT)) 
-      t->setup.texctl2 |= TMC_dualtex_enable;
-
-   t->setup.texctl2 &= ~TMC_specen_enable;
-   if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
-      t->setup.texctl2 |= TMC_specen_enable;
-}
-
-
 
+   t = CALLOC( sizeof( *t ) );
+   tObj->DriverData = t;
+   if ( t != NULL ) {
+      /* Initialize non-image-dependent parts of the state:
+       */
+      t->base.tObj = tObj;
 
+      t->setup.texctl = TMC_takey_1 | TMC_tamask_0;
+      t->setup.texctl2 = TMC_ckstransdis_enable;
+      t->setup.texfilter = (TF_minfilter_nrst 
+                           | TF_magfilter_nrst
+                           | TF_filteralpha_enable
+                           | TF_uvoffset_OGL);
 
+      t->border_fallback = GL_FALSE;
 
-/* The G400 is now programmed quite differently wrt texture environment.
- */
-void mgaUpdateTextureState( GLcontext *ctx )
-{
-   mgaContextPtr mmesa = MGA_CONTEXT( ctx );
-   FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_FALSE );
+      make_empty_list( & t->base );
 
-   if (mmesa->CurrentTexObj[0]) {
-      mmesa->CurrentTexObj[0]->bound = 0;
-      mmesa->CurrentTexObj[0] = 0;
-   }
-
-   if (mmesa->CurrentTexObj[1]) {
-      mmesa->CurrentTexObj[1]->bound = 0;
-      mmesa->CurrentTexObj[1] = 0;
-   }
-
-   if (ctx->Texture.Unit[1]._ReallyEnabled == TEXTURE_2D_BIT) {
-      mmesa->tmu_source[0] = 1;
-   } else {
-      mmesa->tmu_source[0] = 0;
-   }
-
-   if (MGA_IS_G400(mmesa)) {
-      mgaUpdateTextureObject( ctx, 0 );
-      mgaUpdateTextureEnvG400( ctx, 0 );
-
-      mmesa->setup.tdualstage1 = mmesa->setup.tdualstage0;
-      
-      if ((ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT) &&
-          (ctx->Texture.Unit[1]._ReallyEnabled == TEXTURE_2D_BIT)) {
-        mgaUpdateTextureObject( ctx, 1 );      
-        mgaUpdateTextureEnvG400( ctx, 1 );
-        mmesa->dirty |= MGA_UPLOAD_TEX1;
-      }
-   } else {
-      mgaUpdateTextureObject( ctx, 0 );
-      mgaUpdateTextureEnvG200( ctx );
+      mgaSetTexWrapping( t, tObj->WrapS, tObj->WrapT );
+      mgaSetTexFilter( t, tObj->MinFilter, tObj->MagFilter );
+      mgaSetTexBorderColor( t, tObj->_BorderChan );
    }
 
-   mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_TEX0;
-
-   mmesa->setup.dwgctl &= DC_opcod_MASK;
-   mmesa->setup.dwgctl |= (ctx->Texture.Unit[0]._ReallyEnabled
-                          ? DC_opcod_texture_trap
-                          : DC_opcod_trap);
+   return( t );
 }
 
 
-
-
 static void mgaDDTexEnv( GLcontext *ctx, GLenum target,
                         GLenum pname, const GLfloat *param )
 {
+   GLuint unit = ctx->Texture.CurrentUnit;
+   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
    mgaContextPtr mmesa = MGA_CONTEXT(ctx);
 
 
-   if (pname == GL_TEXTURE_ENV_MODE) {
-      /* force the texture state to be updated */
-      FLUSH_BATCH( MGA_CONTEXT(ctx) );
-      MGA_CONTEXT(ctx)->new_state |= (MGA_NEW_TEXTURE |
-                                     MGA_NEW_ALPHA);
-   }
-   else if (pname == GL_TEXTURE_ENV_COLOR)
-   {
-      struct gl_texture_unit *texUnit =
-        &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
-      GLfloat *fc = texUnit->EnvColor;
+   switch( pname ) {
+   case GL_TEXTURE_ENV_COLOR: {
       GLubyte c[4];
-      GLuint col;
+      GLuint envColor;
 
-      COPY_4V(c, fc);
-      col = mgaPackColor( mmesa->mgaScreen->cpp, c[0], c[1], c[2], c[3] );
-      mmesa->envcolor = (c[3]<<24) | (c[0]<<16) | (c[1]<<8) | (c[2]);
+      UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor );
+      envColor = mgaPackColor( mmesa->mgaScreen->cpp, c[0], c[1], c[2], c[3] );
+      mmesa->envcolor = PACK_COLOR_8888( c[3], c[0], c[1], c[2] );
 
-      if (mmesa->setup.fcol != col) {
+      if (mmesa->setup.fcol != envColor) {
         FLUSH_BATCH(mmesa);
-        mmesa->setup.fcol = col;
+        mmesa->setup.fcol = envColor;
         mmesa->dirty |= MGA_UPLOAD_CONTEXT;
 
         mmesa->blend_flags &= ~MGA_BLEND_ENV_COLOR;
@@ -814,6 +354,8 @@ static void mgaDDTexEnv( GLcontext *ctx, GLenum target,
         if (mmesa->envcolor != 0x0 && mmesa->envcolor != 0xffffffff)
            mmesa->blend_flags |= MGA_BLEND_ENV_COLOR;
       }
+      break;
+   }
    }
 }
 
@@ -826,14 +368,26 @@ static void mgaTexImage2D( GLcontext *ctx, GLenum target, GLint level,
                            struct gl_texture_object *texObj,
                            struct gl_texture_image *texImage )
 {
-   mgaTextureObjectPtr t = (mgaTextureObjectPtr) texObj->DriverData;
-   if (t) {
-      mgaDestroyTexObj( MGA_CONTEXT(ctx), t );
-      texObj->DriverData = 0;
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
+
+
+   if ( t != NULL ) {
+      driSwapOutTextureObject( t );
+   } 
+   else {
+      t = (driTextureObject *) mgaAllocTexObj( texObj );
+      if ( t == NULL ) {
+        _mesa_error( ctx, GL_OUT_OF_MEMORY, "glTexImage2D" );
+        return;
+      }
    }
+
    _mesa_store_teximage2d( ctx, target, level, internalFormat,
                           width, height, border, format, type,
                           pixels, packing, texObj, texImage );
+   level -= t->firstLevel;
+   if (level >= 0)
+      t->dirty_images[0] |= (1UL << level);
 }
 
 static void mgaTexSubImage2D( GLcontext *ctx, 
@@ -847,44 +401,59 @@ static void mgaTexSubImage2D( GLcontext *ctx,
                               struct gl_texture_object *texObj,
                               struct gl_texture_image *texImage )
 {
-   mgaTextureObjectPtr t = (mgaTextureObjectPtr) texObj->DriverData;
-   if (t) {
-      mgaDestroyTexObj( MGA_CONTEXT(ctx), t );
-      texObj->DriverData = 0;
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
+
+
+   assert( t != NULL ); /* this _should_ be true */
+   if ( t != NULL ) {
+      driSwapOutTextureObject( t );
+   } 
+   else {
+      t = (driTextureObject *) mgaAllocTexObj( texObj );
+      if ( t == NULL ) {
+        _mesa_error( ctx, GL_OUT_OF_MEMORY, "glTexImage2D" );
+        return;
+      }
    }
+
    _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width, 
                             height, format, type, pixels, packing, texObj,
                             texImage);
-
+   level -= t->firstLevel;
+   if (level >= 0)
+      t->dirty_images[0] |= (1UL << level);
 }
 
 
-
-
-/*
- * mgaTexParameter
- * This just changes variables and flags for a state update, which
- * will happen at the next mgaUpdateTextureState
+/**
+ * Changes variables and flags for a state update, which will happen at the
+ * next UpdateTextureState
  */
+
 static void
 mgaDDTexParameter( GLcontext *ctx, GLenum target,
                   struct gl_texture_object *tObj,
                   GLenum pname, const GLfloat *params )
 {
-   mgaContextPtr mmesa = MGA_CONTEXT( ctx );
+   mgaContextPtr       mmesa = MGA_CONTEXT( ctx );
    mgaTextureObjectPtr t;
 
    t = (mgaTextureObjectPtr) tObj->DriverData;
 
-   /* if we don't have a hardware texture, it will be automatically
-      created with current state before it is used, so we don't have
-      to do anything now */
-   if ( !t || !t->bound || target != GL_TEXTURE_2D ) {
+   /* If we don't have a hardware texture, it will be automatically
+    * created with current state before it is used, so we don't have
+    * to do anything now 
+    */
+
+   if ( (t == NULL)
+        || (target != GL_TEXTURE_2D) ) {
       return;
    }
 
    switch (pname) {
    case GL_TEXTURE_MIN_FILTER:
+      driSwapOutTextureObject( (driTextureObject *) t );
+      /* FALLTHROUGH */
    case GL_TEXTURE_MAG_FILTER:
       FLUSH_BATCH(mmesa);
       mgaSetTexFilter( t, tObj->MinFilter, tObj->MagFilter );
@@ -898,14 +467,24 @@ mgaDDTexParameter( GLcontext *ctx, GLenum target,
 
    case GL_TEXTURE_BORDER_COLOR:
       FLUSH_BATCH(mmesa);
-      mgaSetTexBorderColor(t,tObj->_BorderChan);
+      mgaSetTexBorderColor(t, tObj->_BorderChan);
+      break;
+
+   case GL_TEXTURE_BASE_LEVEL:
+   case GL_TEXTURE_MAX_LEVEL:
+   case GL_TEXTURE_MIN_LOD:
+   case GL_TEXTURE_MAX_LOD:
+      /* This isn't the most efficient solution but there doesn't appear to
+       * be a nice alternative.  Since there's no LOD clamping,
+       * we just have to rely on loading the right subset of mipmap levels
+       * to simulate a clamped LOD.
+       */
+      driSwapOutTextureObject( (driTextureObject *) t );
       break;
 
    default:
       return;
    }
-
-   mmesa->new_state |= MGA_NEW_TEXTURE;
 }
 
 
@@ -913,19 +492,11 @@ static void
 mgaDDBindTexture( GLcontext *ctx, GLenum target,
                  struct gl_texture_object *tObj )
 {
-   mgaContextPtr mmesa = MGA_CONTEXT( ctx );
-   int unit = ctx->Texture.CurrentUnit;
-
-   FLUSH_BATCH(mmesa);
-
-   if (mmesa->CurrentTexObj[unit]) {
-      mmesa->CurrentTexObj[unit]->bound &= ~(unit+1);
-      mmesa->CurrentTexObj[unit] = 0;
+   if ( target == GL_TEXTURE_2D ) {
+      if ( tObj->DriverData == NULL ) {
+        mgaAllocTexObj( tObj );
+      }
    }
-
-   /* force the texture state to be updated
-    */
-   MGA_CONTEXT(ctx)->new_state |= MGA_NEW_TEXTURE;
 }
 
 
@@ -933,53 +504,48 @@ static void
 mgaDDDeleteTexture( GLcontext *ctx, struct gl_texture_object *tObj )
 {
    mgaContextPtr mmesa = MGA_CONTEXT( ctx );
-   mgaTextureObjectPtr t = (mgaTextureObjectPtr)tObj->DriverData;
+   driTextureObject * t = (driTextureObject *) tObj->DriverData;
 
    if ( t ) {
-      if (mmesa) {
-         if (t->bound) {
-            FLUSH_BATCH(mmesa);
-            if (t->bound & TEX_0) mmesa->CurrentTexObj[0] = 0;
-            if (t->bound & TEX_1) mmesa->CurrentTexObj[1] = 0;
-         }
-         mmesa->new_state |= MGA_NEW_TEXTURE;
+      if ( mmesa ) {
+        FLUSH_BATCH( mmesa );
       }
 
-      mgaDestroyTexObj( mmesa, t );
+      driDestroyTextureObject( t );
    }
 }
 
 
-static GLboolean
-mgaDDIsTextureResident( GLcontext *ctx, struct gl_texture_object *t )
-{
-   mgaTextureObjectPtr mt = (mgaTextureObjectPtr)t->DriverData;
-   return mt && mt->MemBlock;
-}
-
-
 void
 mgaDDInitTextureFuncs( GLcontext *ctx )
 {
-   ctx->Driver.TexEnv = mgaDDTexEnv;
-
-   ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format;
-   ctx->Driver.TexImage1D = _mesa_store_teximage1d;
-   ctx->Driver.TexImage2D = mgaTexImage2D;
-   ctx->Driver.TexImage3D = _mesa_store_teximage3d;
-   ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
-   ctx->Driver.TexSubImage2D = mgaTexSubImage2D;
-   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;
-
-   ctx->Driver.BindTexture = mgaDDBindTexture;
-   ctx->Driver.DeleteTexture = mgaDDDeleteTexture;
-   ctx->Driver.TexParameter = mgaDDTexParameter;
-   ctx->Driver.UpdateTexturePalette = 0;
-   ctx->Driver.IsTextureResident = mgaDDIsTextureResident;
+   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+
+
+   ctx->Driver.ChooseTextureFormat     = mgaChooseTextureFormat;
+   ctx->Driver.TexImage1D              = _mesa_store_teximage1d;
+   ctx->Driver.TexImage2D              = mgaTexImage2D;
+   ctx->Driver.TexImage3D              = _mesa_store_teximage3d;
+   ctx->Driver.TexSubImage1D           = _mesa_store_texsubimage1d;
+   ctx->Driver.TexSubImage2D           = mgaTexSubImage2D;
+   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;
+
+   ctx->Driver.BindTexture             = mgaDDBindTexture;
+   ctx->Driver.CreateTexture           = NULL; /* FIXME: Is this used??? */
+   ctx->Driver.DeleteTexture           = mgaDDDeleteTexture;
+   ctx->Driver.IsTextureResident       = driIsTextureResident;
+   ctx->Driver.PrioritizeTexture       = NULL;
+   ctx->Driver.ActiveTexture           = NULL;
+   ctx->Driver.UpdateTexturePalette    = NULL;
+
+   ctx->Driver.TexEnv                  = mgaDDTexEnv;
+   ctx->Driver.TexParameter            = mgaDDTexParameter;
+
+   driInitTextureObjects( ctx, & mmesa->swapped, DRI_TEXMGR_DO_TEXTURE_2D );
 }
index c9f87d997e2a6e073ee3830e7632a18061768c1c..282577e9f80ad14e03a183462aac670a552a3c06 100644 (file)
@@ -40,23 +40,10 @@ typedef struct mga_texture_object_s *mgaTextureObjectPtr;
  */
 void mgaUpdateTextureState( GLcontext *ctx );
 
-void mgaConvertTexture( GLuint *dest, int texelBytes,
-                       struct gl_texture_image *image,
-                       int x, int y, int width, int height );
-
-
-void mgaUploadSubImageLocked( mgaContextPtr mmesa,
-                             mgaTextureObjectPtr t,
-                             int level,
-                             int x, int y, int width, int height );
-
 int mgaUploadTexImages( mgaContextPtr mmesa, mgaTextureObjectPtr t );
 
 void mgaDestroyTexObj( mgaContextPtr mmesa, mgaTextureObjectPtr t );
 
-void mgaAgeTextures( mgaContextPtr mmesa, int heap );
-
 void mgaDDInitTextureFuncs( GLcontext *ctx );
 
-
 #endif
index 7dbdbc582faf9cf3e9fd934a6fc821e9a17972dc..4e7fd6b24b35ae6a436cf7b1c522a858b9865154 100644 (file)
  */
 /* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgatexmem.c,v 1.7 2002/10/30 12:51:36 alanh Exp $ */
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <GL/gl.h>
+#include "glheader.h"
 
 #include "mm.h"
 #include "mgacontext.h"
 #include "mgatex.h"
 #include "mgaregs.h"
 #include "mgaioctl.h"
+#include "mga_xmesa.h"
 
-/*#include "mem.h" */
+#include "imports.h"
 #include "simple_list.h"
 
-static void
-mgaSwapOutTexObj(mgaContextPtr mmesa, mgaTextureObjectPtr t)
-{
-   if (t->MemBlock) {
-      mmFreeMem(t->MemBlock);
-      t->MemBlock = 0;
-
-      if (t->age > mmesa->dirtyAge)
-        mmesa->dirtyAge = t->age;
-   }
-
-   t->dirty_images = ~0;
-   move_to_tail(&(mmesa->SwappedOut), t);
-}
-
-static void
-mgaPrintLocalLRU( mgaContextPtr mmesa, int heap )
-{
-   mgaTextureObjectPtr t;
-   int sz = 1 << (mmesa->mgaScreen->logTextureGranularity[heap]);
-
-   fprintf(stderr, "\nLocal LRU, heap %d:\n", heap);
-
-   foreach( t, &(mmesa->TexObjList[heap]) ) {
-      if (!t->tObj)
-        fprintf(stderr, "Placeholder %d at %x sz %x\n",
-                t->MemBlock->ofs / sz,
-                t->MemBlock->ofs,
-                t->MemBlock->size);
-      else
-        fprintf(stderr, "Texture (bound %d) at %x sz %x\n",
-                t->bound,
-                t->MemBlock->ofs,
-                t->MemBlock->size);
-   }
-
-   fprintf(stderr, "\n\n");
-}
-
-static void
-mgaPrintGlobalLRU( mgaContextPtr mmesa, int heap )
+/**
+ * Destroy any device-dependent state associated with the texture.  This may
+ * include NULLing out hardware state that points to the texture.
+ */
+void
+mgaDestroyTexObj( mgaContextPtr mmesa, mgaTextureObjectPtr t )
 {
-   int i, j;
-   drmTextureRegion *list = mmesa->sarea->texList[heap];
+    unsigned   i;
 
-   fprintf(stderr, "\nGlobal LRU, heap %d list %p:\n", heap, list);
 
-   for (i = 0, j = MGA_NR_TEX_REGIONS ; i < MGA_NR_TEX_REGIONS ; i++) {
-      fprintf(stderr, "list[%d] age %d next %d prev %d\n",
-             j, list[j].age, list[j].next, list[j].prev);
-      j = list[j].next;
-      if (j == MGA_NR_TEX_REGIONS) break;
-   }
+    /* See if it was the driver's current object.
+     */
 
-   if (j != MGA_NR_TEX_REGIONS) {
-      fprintf(stderr, "Loop detected in global LRU\n\n\n");
-      for (i = 0 ; i < MGA_NR_TEX_REGIONS ; i++) {
-        fprintf(stderr, "list[%d] age %d next %d prev %d\n",
-                i, list[i].age, list[i].next, list[i].prev);
-      }
-   }
+    if ( mmesa != NULL )
+    { 
+       if ( t->age > mmesa->dirtyAge )
+           mmesa->dirtyAge = t->age;
 
-   fprintf(stderr, "\n\n");
+       for ( i = 0 ; i < mmesa->glCtx->Const.MaxTextureUnits ; i++ )
+       {
+           if ( t == mmesa->CurrentTexObj[ i ] ) {
+               mmesa->CurrentTexObj[ i ] = NULL;
+           }
+       }
+    }
 }
 
 
-static void mgaResetGlobalLRU( mgaContextPtr mmesa, GLuint heap )
+/**
+ * Upload a texture image from system memory to either on-card or AGP
+ * memory.  Uploads to on-card memory are performed using an ILOAD operation.
+ * This is used for both initial loading of the entire image, and texSubImage
+ * updates.
+ *
+ * Performed with the hardware lock held.
+ * 
+ * Even though this function is named "upload subimage," the entire image
+ * is uploaded.
+ * 
+ * \param mmesa  Driver context.
+ * \param t      Texture to be uploaded.
+ * \param hwlevel  Mipmap level of the texture to be uploaded.
+ * 
+ * \bug As mentioned above, this fuction actually copies the entier mipmap
+ *      level.  There should be a version of this function that performs
+ *      sub-rectangle uploads.  This will perform quite a bit better if only
+ *      a small portion of a larger texture has been updated.  Care would
+ *      need to be take with such an implementation once glCopyTexImage has
+ *      been hardware accelerated.
+ */
+static void mgaUploadSubImage( mgaContextPtr mmesa,
+                              mgaTextureObjectPtr t, GLint hwlevel )
 {
-   drmTextureRegion *list = mmesa->sarea->texList[heap];
-   int sz = 1 << mmesa->mgaScreen->logTextureGranularity[heap];
-   int i;
-
-   mmesa->texAge[heap] = ++mmesa->sarea->texAge[heap];
+   struct gl_texture_image * texImage;
+   unsigned     offset;
+   unsigned     texelBytes;
+   unsigned     length;
+   const int level = hwlevel + t->base.firstLevel;
 
-   if (0) fprintf(stderr, "mgaResetGlobalLRU %d\n", (int)heap);
 
-   /* (Re)initialize the global circular LRU list.  The last element
-    * in the array (MGA_NR_TEX_REGIONS) is the sentinal.  Keeping it
-    * at the end of the array allows it to be addressed rationally
-    * when looking up objects at a particular location in texture
-    * memory.
-    */
-   for (i = 0 ; (i+1) * sz <= mmesa->mgaScreen->textureSize[heap] ; i++) {
-      list[i].prev = i-1;
-      list[i].next = i+1;
-      list[i].age = mmesa->sarea->texAge[heap];
+   if ( (hwlevel < 0) 
+       || (hwlevel >= (MGA_IS_G200(mmesa) 
+                     ? G200_TEX_MAXLEVELS : G400_TEX_MAXLEVELS)) ) {
+      fprintf( stderr, "[%s:%d] level = %d\n", __FILE__, __LINE__, level );
+      return;
    }
 
-   i--;
-   list[0].prev = MGA_NR_TEX_REGIONS;
-   list[i].prev = i-1;
-   list[i].next = MGA_NR_TEX_REGIONS;
-   list[MGA_NR_TEX_REGIONS].prev = i;
-   list[MGA_NR_TEX_REGIONS].next = 0;
-
-}
-
-
-static void mgaUpdateTexLRU( mgaContextPtr mmesa, mgaTextureObjectPtr t )
-{
-   int i;
-   int heap = t->heap;
-   int logsz = mmesa->mgaScreen->logTextureGranularity[heap];
-   int start = t->MemBlock->ofs >> logsz;
-   int end = (t->MemBlock->ofs + t->MemBlock->size - 1) >> logsz;
-   drmTextureRegion *list = mmesa->sarea->texList[heap];
-
-   mmesa->texAge[heap] = ++mmesa->sarea->texAge[heap];
-
-   if (!t->MemBlock) {
-      fprintf(stderr, "no memblock\n\n");
+   texImage = t->base.tObj->Image[level];
+   if ( texImage == NULL ) {
+      fprintf( stderr, "[%s:%d] Image[%d] = NULL\n", __FILE__, __LINE__,
+              level );
       return;
    }
 
-   /* Update our local LRU
-    */
-   move_to_head( &(mmesa->TexObjList[heap]), t );
-
-
-   if (0)
-      fprintf(stderr, "mgaUpdateTexLRU heap %d list %p\n", heap, list);
-
 
-   /* Update the global LRU
-    */
-   for (i = start ; i <= end ; i++) {
-
-      list[i].in_use = 1;
-      list[i].age = mmesa->texAge[heap];
-
-      /* remove_from_list(i)
-       */
-      list[(unsigned)list[i].next].prev = list[i].prev;
-      list[(unsigned)list[i].prev].next = list[i].next;
-
-      /* insert_at_head(list, i)
-       */
-      list[i].prev = MGA_NR_TEX_REGIONS;
-      list[i].next = list[MGA_NR_TEX_REGIONS].next;
-      list[(unsigned)list[MGA_NR_TEX_REGIONS].next].prev = i;
-      list[MGA_NR_TEX_REGIONS].next = i;
-   }
-
-   if (0) {
-      mgaPrintGlobalLRU(mmesa, t->heap);
-      mgaPrintLocalLRU(mmesa, t->heap);
+   if (texImage->Data == NULL) {
+      fprintf(stderr, "null texture image data tObj %p level %d\n",
+             t->base.tObj, level);
+      return;
    }
-}
-
-/* Called for every shared texture region which has increased in age
- * since we last held the lock.
- *
- * Figures out which of our textures have been ejected by other clients,
- * and pushes a placeholder texture onto the LRU list to represent
- * the other client's textures.
- */
-static void mgaTexturesGone( mgaContextPtr mmesa,
-                            GLuint heap,
-                            GLuint offset,
-                            GLuint size,
-                            GLuint in_use )
-{
-   mgaTextureObjectPtr t, tmp;
-
-
 
-   foreach_s ( t, tmp, &(mmesa->TexObjList[heap]) ) {
 
-      if (t->MemBlock->ofs >= offset + size ||
-         t->MemBlock->ofs + t->MemBlock->size <= offset)
-        continue;
-
-
-
-
-      /* It overlaps - kick it off.  Need to hold onto the currently bound
-       * objects, however.
-       */
-      if (t->bound)
-        mgaSwapOutTexObj( mmesa, t );
-      else
-        mgaDestroyTexObj( mmesa, t );
+   /* find the proper destination offset for this level */
+   if ( MGA_IS_G200(mmesa) ) {
+      offset = (t->base.memBlock->ofs + t->offsets[hwlevel]);
    }
+   else {
+      unsigned  i;
 
-
-   if (in_use) {
-      t = (mgaTextureObjectPtr) calloc(1, sizeof(*t));
-      if (!t) return;
-
-      t->heap = heap;
-      t->MemBlock = mmAllocMem( mmesa->texHeap[heap], size, 0, offset);
-      if (!t->MemBlock) {
-        fprintf(stderr, "Couldn't alloc placeholder sz %x ofs %x\n",
-                (int)size, (int)offset);
-        mmDumpMemInfo( mmesa->texHeap[heap]);
-        return;
+      offset = t->base.memBlock->ofs;
+      for ( i = 0 ; i < hwlevel ; i++ ) {
+        offset += (t->offsets[1] >> (i * 2));
       }
-      insert_at_head( &(mmesa->TexObjList[heap]), t );
-   }
-}
-
-
-void mgaAgeTextures( mgaContextPtr mmesa, int heap )
-{
-   MGASAREAPrivPtr sarea = mmesa->sarea;
-   int sz = 1 << (mmesa->mgaScreen->logTextureGranularity[heap]);
-   int idx, nr = 0;
 
-   /* Have to go right round from the back to ensure stuff ends up
-    * LRU in our local list...  Fix with a cursor pointer.
-    */
-   for (idx = sarea->texList[heap][MGA_NR_TEX_REGIONS].prev ;
-       idx != MGA_NR_TEX_REGIONS && nr < MGA_NR_TEX_REGIONS ;
-       idx = sarea->texList[heap][idx].prev, nr++)
-   {
-      /* If switching texturing schemes, then the SAREA might not
-       * have been properly cleared, so we need to reset the
-       * global texture LRU.
+      /* Each mipmap must be DWORD aligned.
        */
-      if ( idx * sz > mmesa->mgaScreen->textureSize[heap] ) {
-         nr = MGA_NR_TEX_REGIONS;
-         break;
-      }
-
-      if (sarea->texList[heap][idx].age > mmesa->texAge[heap]) {
-        mgaTexturesGone(mmesa, heap, idx * sz, sz,
-                        sarea->texList[heap][idx].in_use);
-      }
-   }
-
-   if (nr == MGA_NR_TEX_REGIONS) {
-      mgaTexturesGone(mmesa, heap, 0,
-                     mmesa->mgaScreen->textureSize[heap], 0);
-      mgaResetGlobalLRU( mmesa, heap );
+      offset &= ~0x03;
    }
 
 
-   if (0) {
-      mgaPrintGlobalLRU( mmesa, heap );
-      mgaPrintLocalLRU( mmesa, heap );
-   }
-
-   mmesa->texAge[heap] = sarea->texAge[heap];
-   mmesa->dirty |= MGA_UPLOAD_TEX0IMAGE | MGA_UPLOAD_TEX1IMAGE;
-}
-
-/*
- * mgaUploadSubImageLocked
- *
- * Perform an iload based update of a resident buffer.  This is used for
- * both initial loading of the entire image, and texSubImage updates.
- *
- * Performed with the hardware lock held.
- */
-void mgaUploadSubImageLocked( mgaContextPtr mmesa,
-                             mgaTextureObjectPtr t,
-                             int level,
-                             int x, int y, int width, int height )
-{
-   int         x2;
-   int         dwords;
-   int         offset;
-   struct gl_texture_image *image;
-   int         texelBytes, texelsPerDword, texelMaccess, length;
-
-   if ( level < 0 || level >= MGA_TEX_MAXLEVELS )
-      return;
+   /* Copy the texture from system memory to a memory space that can be
+    * directly used by the hardware for texturing.
+    */
 
-   image = t->tObj->Image[level];
-   if ( !image ) return;
+   texelBytes = texImage->TexFormat->TexelBytes;
+   length = texImage->Width * texImage->Height * texelBytes;
+   if ( t->base.heap->heapId == MGA_CARD_HEAP ) {
+      unsigned  tex_offset = 0;
+      unsigned  to_copy;
 
 
-   if (image->Data == 0) {
-      fprintf(stderr, "null texture image data tObj %p level %d\n",
-             t->tObj, level);
-      return;
-   }
+      /* We may not be able to upload the entire texture in one batch due to
+       * register limits or dma buffer limits.  Split the copy up into maximum
+       * sized chunks.
+       */
 
+      offset += mmesa->mgaScreen->textureOffset[ t->base.heap->heapId ];
+      while ( length != 0 ) {
+        mgaGetILoadBufferLocked( mmesa );
 
-   /* find the proper destination offset for this level */
-   offset = (t->MemBlock->ofs +
-            t->offsets[level]);
-
-
-   texelBytes = t->texelBytes;
-   switch( texelBytes ) {
-   case 1:
-      texelsPerDword = 4;
-      texelMaccess = 0;
-      break;
-   case 2:
-      texelsPerDword = 2;
-      texelMaccess = 1;
-      break;
-   case 4:
-      texelsPerDword = 1;
-      texelMaccess = 2;
-      break;
-   default:
-      return;
-   }
+        /* The kernel ILOAD ioctl requires that the lenght be an even multiple
+         * of MGA_ILOAD_ALIGN.
+         */
+        length = ((length) + MGA_ILOAD_MASK) & ~MGA_ILOAD_MASK;
 
+        to_copy = MIN2( length, MGA_BUFFER_SIZE );
+        (void) memcpy( mmesa->iload_buffer->address,
+                       (GLubyte *) texImage->Data + tex_offset, to_copy );
 
-   /* We can't do a subimage update if pitch is < 32 texels due
-    * to hardware XY addressing limits, so we will need to
-    * linearly upload all modified rows.
-    */
-   if ( image->Width < 32 ) {
-      x = 0;
-      width = image->Width * height;
-      height = 1;
-
-      /* Assume that 1x1 textures aren't going to cause a
-       * bus error if we read up to four texels from that
-       * location:
-       */
-/*        if ( width < texelsPerDword ) { */
-/*      width = texelsPerDword; */
-/*        } */
-   } else {
-      /* pad the size out to dwords.  The image is a pointer
-        to the entire image, so we can safely reference
-        outside the x,y,width,height bounds if we need to */
-      x2 = x + width;
-      x2 = (x2 + (texelsPerDword-1)) & ~(texelsPerDword-1);
-      x = (x + (texelsPerDword-1)) & ~(texelsPerDword-1);
-      width = x2 - x;
-   }
+        if ( MGA_DEBUG & DEBUG_VERBOSE_TEXTURE )
+            fprintf(stderr, "[%s:%d] address/size = 0x%08lx/%d\n",
+                    __FILE__, __LINE__,
+                    (long) (offset + tex_offset),
+                    to_copy );
 
-   /* we may not be able to upload the entire texture in one
-      batch due to register limits or dma buffer limits.
-      Recursively split it up. */
-   while ( 1 ) {
-      dwords = height * width / texelsPerDword;
-      if ( dwords * 4 <= MGA_BUFFER_SIZE ) {
-        break;
+        mgaFireILoadLocked( mmesa, offset + tex_offset, to_copy );
+        tex_offset += to_copy;
+        length -= to_copy;
       }
-
-      mgaUploadSubImageLocked( mmesa, t, level, x, y,
-                              width, height >> 1 );
-      y += ( height >> 1 );
-      height -= ( height >> 1 );
-   }
-
-   length = dwords * 4;
-
-   /* Fill in the secondary buffer with properly converted texels
-    * from the mesa buffer. */
-   /* FIXME: the sync for direct copy reduces speed.. */
-   if(t->heap == MGA_CARD_HEAP  ) {
-      mgaGetILoadBufferLocked( mmesa );
-      mgaConvertTexture( (GLuint *)mmesa->iload_buffer->address,
-                        texelBytes, image, x, y, width, height );
-      if(length < 64) length = 64;
-
-      if (0)
-        fprintf(stderr, "TexelBytes : %d, offset: %d, length : %d\n",
-                texelBytes,
-                mmesa->mgaScreen->textureOffset[t->heap] +
-                offset +
-                y * width * 4/texelsPerDword,
-                length);
-
-      mgaFireILoadLocked( mmesa,
-                         mmesa->mgaScreen->textureOffset[t->heap] +
-                         offset +
-                         y * width * 4/texelsPerDword,
-                         length);
    } else {
+      /* FIXME: the sync for direct copy reduces speed.. */
       /* This works, is slower for uploads to card space and needs
        * additional synchronization with the dma stream.
        */
        
       UPDATE_LOCK(mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT);
-      mgaConvertTexture( (GLuint *)
-                        (mmesa->mgaScreen->texVirtual[t->heap] +
-                         offset +
-                         y * width * 4/texelsPerDword),
-                        texelBytes, image, x, y, width, height );
-   }
-}
-
-
-static void mgaUploadTexLevel( mgaContextPtr mmesa,
-                              mgaTextureObjectPtr t,
-                              int l )
-{
-   mgaUploadSubImageLocked( mmesa,
-                           t,
-                           l,
-                           0, 0,
-                           t->tObj->Image[l]->Width,
-                           t->tObj->Image[l]->Height);
-}
-
-
-
-
-#if 0
-static void mgaMigrateTexture( mgaContextPtr mmesa, mgaTextureObjectPtr t )
-{
-       /* NOT DONE */
-}
-#endif
-
-
-static int mgaChooseTexHeap( mgaContextPtr mmesa, mgaTextureObjectPtr t )
-{
-   int freeagp, freecard;
-   int fitincard, fitinagp;
-   int totalcard, totalagp;
-   TMemBlock *b;
-
-   totalcard = totalagp = fitincard = fitinagp = freeagp = freecard = 0;
-
-   b = mmesa->texHeap[0];
-   while(b)
-   {
-     totalcard += b->size;
-     if(b->free) if(t->totalSize <= b->size)fitincard = 1;
-     b = b->next;
-   }
-
-   b = mmesa->texHeap[1];
-   while(b)
-   {
-     totalagp += b->size;
-     if(b->free)  if(t->totalSize <= b->size)fitinagp = 1;
-     b = b->next;
-   }
 
-   if(fitincard)return 0;
-   if(fitinagp)return 1;
+      memcpy( mmesa->mgaScreen->texVirtual[t->base.heap->heapId] + offset,
+             texImage->Data, length );
 
-   if(totalcard && totalagp)
-   {
-     int ages;
-     int ratio = (totalcard > totalagp) ? totalcard / totalagp : totalagp / totalcard;
-     ages = mmesa->sarea->texAge[0] + mmesa->sarea->texAge[1];
-     if( (ages % ratio) == 0)return totalcard > totalagp ? 1 : 0;
-     else return totalcard > totalagp ? 0 : 1;
+      if ( MGA_DEBUG & DEBUG_VERBOSE_TEXTURE )
+        fprintf(stderr, "[%s:%d] address/size = 0x%08lx/%d\n",
+                __FILE__, __LINE__,
+                (long) (mmesa->mgaScreen->texVirtual[t->base.heap->heapId] 
+                        + offset),
+                length);
    }
-
-   if(totalagp) return 1;
-   return 0;
 }
 
 
+/**
+ * Upload the texture images associated with texture \a t.  This might
+ * require the allocation of texture memory.
+ * 
+ * \param mmesa Context pointer
+ * \param t Texture to be uploaded
+ */
+
 int mgaUploadTexImages( mgaContextPtr mmesa, mgaTextureObjectPtr t )
 {
-   int heap;
    int i;
    int ofs;
 
-   heap = t->heap = mgaChooseTexHeap( mmesa, t );
 
-   /* Do we need to eject LRU texture objects?
-    */
-   if (!t->MemBlock) {
-      while (1)
-      {
-        mgaTextureObjectPtr tmp = mmesa->TexObjList[heap].prev;
-
-        t->MemBlock = mmAllocMem( mmesa->texHeap[heap],
-                                  t->totalSize,
-                                  6, 0 );
-        if (t->MemBlock)
-           break;
-
-        if (mmesa->TexObjList[heap].prev->bound) {
-           fprintf(stderr, "Hit bound texture in upload\n");
-           return -1;
-        }
+   if ( (t == NULL) || (t->base.totalSize == 0) )
+      return 0;
 
-        if (mmesa->TexObjList[heap].prev ==
-            &(mmesa->TexObjList[heap]))
-        {
-           fprintf(stderr, "Failed to upload texture, sz %d\n", t->totalSize);
-           mmDumpMemInfo( mmesa->texHeap[heap] );
-           return -1;
-        }
+   LOCK_HARDWARE( mmesa );
 
-        mgaDestroyTexObj( mmesa, tmp );
+   if (t->base.memBlock == NULL ) {
+      int heap;
+
+      heap = driAllocateTexture( mmesa->texture_heaps, mmesa->nr_heaps,
+                                (driTextureObject *) t );
+      if ( heap == -1 ) {
+        UNLOCK_HARDWARE( mmesa );
+        return -1;
       }
 
-      ofs = t->MemBlock->ofs
-        + mmesa->mgaScreen->textureOffset[heap]
-        ;
+      ofs = mmesa->mgaScreen->textureOffset[ heap ]
+          + t->base.memBlock->ofs;
 
-      t->setup.texorg  = ofs;
-      t->setup.texorg1 = ofs + t->offsets[1];
-      t->setup.texorg2 = ofs + t->offsets[2];
-      t->setup.texorg3 = ofs + t->offsets[3];
-      t->setup.texorg4 = ofs + t->offsets[4];
+      if ( MGA_IS_G200(mmesa) ) {
+        t->setup.texorg  = ofs;
+        t->setup.texorg1 = ofs + t->offsets[1];
+        t->setup.texorg2 = ofs + t->offsets[2];
+        t->setup.texorg3 = ofs + t->offsets[3];
+        t->setup.texorg4 = ofs + t->offsets[4];
+      }
+      else {
+        t->setup.texorg  = ofs | TO_texorgoffsetsel;
+        t->setup.texorg1 = t->offsets[1];
+        t->setup.texorg2 = 0;
+        t->setup.texorg3 = 0;
+        t->setup.texorg4 = 0;
+      }
 
       mmesa->dirty |= MGA_UPLOAD_CONTEXT;
    }
 
    /* Let the world know we've used this memory recently.
     */
-   mgaUpdateTexLRU( mmesa, t );
-
+   driUpdateTextureLRU( (driTextureObject *) t );
 
-   if (MGA_DEBUG&DEBUG_VERBOSE_LRU)
-      fprintf(stderr, "dispatch age: %d age freed memory: %d\n",
+   if (MGA_DEBUG&DEBUG_VERBOSE_TEXTURE)
+      fprintf(stderr, "[%s:%d] dispatch age: %d age freed memory: %d\n",
+             __FILE__, __LINE__,
              GET_DISPATCH_AGE(mmesa), mmesa->dirtyAge);
 
    if (mmesa->dirtyAge >= GET_DISPATCH_AGE(mmesa))
       mgaWaitAgeLocked( mmesa, mmesa->dirtyAge );
 
-   if (t->dirty_images) {
-      if (MGA_DEBUG&DEBUG_VERBOSE_LRU)
-        fprintf(stderr, "*");
+   if (t->base.dirty_images[0]) {
+      const int numLevels = t->base.lastLevel - t->base.firstLevel + 1;
 
-      for (i = 0 ; i <= t->lastLevel ; i++)
-        if (t->dirty_images & (1<<i))
-           mgaUploadTexLevel( mmesa, t, i );
+      if (MGA_DEBUG&DEBUG_VERBOSE_TEXTURE)
+        fprintf(stderr, "[%s:%d] dirty_images[0] = 0x%04x\n",
+                __FILE__, __LINE__, t->base.dirty_images[0] );
+
+      for (i = 0 ; i < numLevels ; i++) {
+        if ( (t->base.dirty_images[0] & (1U << i)) != 0 ) {
+           mgaUploadSubImage( mmesa, t, i );
+        }
+      }
+      t->base.dirty_images[0] = 0;
    }
 
 
-   t->dirty_images = 0;
+   UNLOCK_HARDWARE( mmesa );
+
    return 0;
 }
index e47cfc171fd5619f7851f3fdce9bdadf43fb3df5..054c7f0635d2c24cee340f04faebc010b0479e9b 100644 (file)
@@ -26,9 +26,6 @@
  */
 /* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgatris.c,v 1.10 2002/10/30 12:51:36 alanh Exp $ */
 
-#include <stdio.h>
-#include <math.h>
-
 #include "mtypes.h"
 #include "macros.h"
 #include "colormac.h"
@@ -676,15 +673,6 @@ static void mgaFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
 /**********************************************************************/
 
 
-
-#define _MGA_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE |           \
-                              _DD_NEW_TRI_UNFILLED |           \
-                              _DD_NEW_TRI_LIGHT_TWOSIDE |      \
-                              _DD_NEW_TRI_OFFSET |             \
-                              _DD_NEW_TRI_STIPPLE |            \
-                              _NEW_POLYGONSTIPPLE)
-
-
 #define POINT_FALLBACK (DD_POINT_SMOOTH)
 #define LINE_FALLBACK (DD_LINE_SMOOTH | DD_LINE_STIPPLE)
 #define TRI_FALLBACK (DD_TRI_SMOOTH | DD_TRI_UNFILLED)
@@ -693,7 +681,7 @@ static void mgaFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
 #define ANY_RASTER_FLAGS (DD_FLATSHADE|DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET| \
                           DD_TRI_UNFILLED)
 
-static void mgaChooseRenderState(GLcontext *ctx)
+void mgaChooseRenderState(GLcontext *ctx)
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    mgaContextPtr mmesa = MGA_CONTEXT(ctx);
@@ -759,36 +747,6 @@ static void mgaChooseRenderState(GLcontext *ctx)
 /**********************************************************************/
 
 
-static void mgaRunPipeline( GLcontext *ctx )
-{
-   mgaContextPtr mmesa = MGA_CONTEXT(ctx);
-
-   if (mmesa->new_state) {
-      mgaDDUpdateHwState( ctx );
-   }
-
-   if (!mmesa->Fallback && mmesa->new_gl_state) {
-      if (mmesa->new_gl_state & _MGA_NEW_RASTERSETUP)
-        mgaChooseVertexState( ctx );
-      
-      if (mmesa->new_gl_state & _MGA_NEW_RENDERSTATE)
-        mgaChooseRenderState( ctx );
-      
-      mmesa->new_gl_state = 0;
-
-      /* Circularity: mgaDDUpdateHwState can affect mmesa->Fallback,
-       * but mgaChooseVertexState can affect mmesa->new_state.  Hence
-       * the second check.  (Fix this...)
-       */
-      if (mmesa->new_state) {
-        mgaDDUpdateHwState( ctx );
-      }
-   }
-
-   _tnl_run_pipeline( ctx );
-}
-
-
 static GLenum reduced_prim[GL_POLYGON+1] = {
    GL_POINTS,
    GL_LINES,
@@ -812,10 +770,14 @@ void mgaRasterPrimitive( GLcontext *ctx, GLenum prim, GLuint hwprim )
    mgaContextPtr mmesa = MGA_CONTEXT( ctx );
 
    FLUSH_BATCH( mmesa );
+
+   /* Update culling */
+   if (mmesa->raster_primitive != prim)
+      mmesa->dirty |= MGA_UPLOAD_CONTEXT;
+
    mmesa->raster_primitive = prim;
 /*     mmesa->hw_primitive = hwprim; */
    mmesa->hw_primitive = MGA_WA_TRIANGLES; /* disable mgarender.c for now */
-   mgaUpdateCull(ctx);   
 
    if (ctx->Polygon.StippleFlag && mmesa->haveHwStipple)
    {
@@ -864,6 +826,28 @@ static void mgaRenderFinish( GLcontext *ctx )
 /*               Manage total rasterization fallbacks                 */
 /**********************************************************************/
 
+static const char * const fallbackStrings[] = {
+   "Texture mode",
+   "glDrawBuffer(GL_FRONT_AND_BACK)",
+   "read buffer",
+   "LogicOp != GL_COPY",
+   "glRenderMode(selection or feedback)",
+   "No hardware stencil",
+   "glDepthFunc( GL_NEVER )",
+   "Mixing GL_CLAMP_TO_EDGE and GL_CLAMP"
+};
+
+static const char *getFallbackString(GLuint bit)
+{
+   int i = 0;
+   while (bit > 1) {
+      i++;
+      bit >>= 1;
+   }
+   return fallbackStrings[i];
+}
+
+
 void mgaFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
@@ -876,6 +860,10 @@ void mgaFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
         FLUSH_BATCH(mmesa);
         _swsetup_Wakeup( ctx );
         mmesa->RenderIndex = ~0;
+         if (MGA_DEBUG & DEBUG_VERBOSE_FALLBACK) {
+            fprintf(stderr, "MGA begin rasterization fallback: 0x%x %s\n",
+                    bit, getFallbackString(bit));
+         }
       }
    }
    else {
@@ -886,8 +874,12 @@ void mgaFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
         tnl->Driver.Render.PrimitiveNotify = mgaRenderPrimitive;
         tnl->Driver.Render.Finish = mgaRenderFinish;
         tnl->Driver.Render.BuildVertices = mgaBuildVertices;
-        mmesa->new_gl_state |= (_MGA_NEW_RENDERSTATE |
-                                _MGA_NEW_RASTERSETUP);
+        mmesa->NewGLState |= (_MGA_NEW_RENDERSTATE |
+                              _MGA_NEW_RASTERSETUP);
+         if (MGA_DEBUG & DEBUG_VERBOSE_FALLBACK) {
+            fprintf(stderr, "MGA end rasterization fallback: 0x%x %s\n",
+                    bit, getFallbackString(bit));
+         }
       }
    }
 }
@@ -905,7 +897,6 @@ void mgaDDInitTriFuncs( GLcontext *ctx )
 
    mmesa->RenderIndex = ~0;
        
-   tnl->Driver.RunPipeline               = mgaRunPipeline;
    tnl->Driver.Render.Start              = mgaCheckTexSizes;
    tnl->Driver.Render.Finish             = mgaRenderFinish; 
    tnl->Driver.Render.PrimitiveNotify    = mgaRenderPrimitive;
index 88eda91e13b9c63f15feb9771fc80849cc75ac60..a8c0b8936b7392d9f3f63942580d0fae082868a4 100644 (file)
 #include "mtypes.h"
 
 extern void mgaDDInitTriFuncs( GLcontext *ctx );
-
+extern void mgaChooseRenderState( GLcontext *ctx );
 extern void mgaRasterPrimitive( GLcontext *ctx, GLenum prim, GLuint hwprim );
 
 extern void mgaFallback( GLcontext *ctx, GLuint bit, GLboolean mode );
 #define FALLBACK( ctx, bit, mode ) mgaFallback( ctx, bit, mode )
 
-
+#define _MGA_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE |           \
+                              _DD_NEW_TRI_UNFILLED |           \
+                              _DD_NEW_TRI_LIGHT_TWOSIDE |      \
+                              _DD_NEW_TRI_OFFSET |             \
+                              _DD_NEW_TRI_STIPPLE |            \
+                              _NEW_POLYGONSTIPPLE)
 
 #endif
index d354fa43d2e741fead0b558aa966e27792e3416a..34906865e8deca7d1f60b15cd1ee0036eebe1880 100644 (file)
@@ -24,7 +24,7 @@
  * Authors:
  *    Keith Whitwell <keith@tungstengraphics.com>
  */
-/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgavb.c,v 1.15 2003/03/26 20:43:49 tsi Exp $ */
+/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgavb.c,v 1.14 2002/10/30 12:51:36 alanh Exp $ */
 
 #include "mgacontext.h"
 #include "mgavb.h"
 
 #include "glheader.h"
 #include "mtypes.h"
-/*#include "mem.h" */
+#include "imports.h"
 #include "macros.h"
 #include "colormac.h"
-/*#include "mmath.h"*/
 
 #include "tnl/t_context.h"
 #include "swrast_setup/swrast_setup.h"
 #include "swrast/swrast.h"
 
-#include <stdio.h>
-#include <stdlib.h>
-
 
 #define MGA_TEX1_BIT       0x1
 #define MGA_TEX0_BIT       0x2 
@@ -93,7 +89,7 @@ static struct {
 #define GET_VIEWPORT_MAT() mmesa->hw_viewport
 #define GET_TEXSOURCE(n)  mmesa->tmu_source[n]
 #define GET_VERTEX_FORMAT() mmesa->vertex_format
-#define GET_VERTEX_STORE() ((GLubyte *)mmesa->verts)
+#define GET_VERTEX_STORE() mmesa->verts
 #define GET_VERTEX_STRIDE_SHIFT() mmesa->vertex_stride_shift
 #define GET_UBYTE_COLOR_STORE() &mmesa->UbyteColor
 #define GET_UBYTE_SPEC_COLOR_STORE() &mmesa->UbyteSecondaryColor
@@ -407,15 +403,18 @@ void mgaChooseVertexState( GLcontext *ctx )
    if (ctx->Fog.Enabled) 
       ind |= MGA_FOG_BIT;
    
-   if (ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
-      if (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
+   if (ctx->Texture._EnabledUnits & 0x2) {
+      /* unit 1 enabled */
+      if (ctx->Texture._EnabledUnits & 0x1) {
+         /* unit 0 enabled */
         ind |= MGA_TEX1_BIT|MGA_TEX0_BIT;
       }
       else {
         ind |= MGA_TEX0_BIT;
       }
    }
-   else if (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
+   else if (ctx->Texture._EnabledUnits & 0x1) {
+      /* unit 0 enabled */
       ind |= MGA_TEX0_BIT;
    }
    
@@ -431,7 +430,6 @@ void mgaChooseVertexState( GLcontext *ctx )
 
    if (setup_tab[ind].vertex_format != mmesa->vertex_format) {
       FLUSH_BATCH(mmesa);      
-      mmesa->new_state |= MGA_NEW_WARP;
       mmesa->dirty |= MGA_UPLOAD_PIPE;
       mmesa->vertex_format = setup_tab[ind].vertex_format;
       mmesa->vertex_size = setup_tab[ind].vertex_size;
@@ -458,7 +456,7 @@ void mgaInitVB( GLcontext *ctx )
    mgaContextPtr mmesa = MGA_CONTEXT(ctx);
    GLuint size = TNL_CONTEXT(ctx)->vb.Size;
 
-   mmesa->verts = (char *)ALIGN_MALLOC(size * sizeof(mgaVertex), 32);
+   mmesa->verts = ALIGN_MALLOC(size * sizeof(mgaVertex), 32);
 
    {
       static int firsttime = 1;
@@ -468,7 +466,6 @@ void mgaInitVB( GLcontext *ctx )
       }
    }
 
-   mmesa->new_state |= MGA_NEW_WARP;
    mmesa->dirty |= MGA_UPLOAD_PIPE;
    mmesa->vertex_format = setup_tab[0].vertex_format;
    mmesa->vertex_size = setup_tab[0].vertex_size;
index 90f6b37f4e64ea198b0442efe95f0876e213d3cf..dcc260a1a59696fc9faf227857fcb630d88266ca 100644 (file)
@@ -146,7 +146,7 @@ typedef struct {
 
 typedef struct {
        int param;
-       int *value;
+       void *value;
 } drmMGAGetParam;
 
 #endif
diff --git a/src/mesa/drivers/dri/r128/Makefile.X11 b/src/mesa/drivers/dri/r128/Makefile.X11
new file mode 100644 (file)
index 0000000..8ae146a
--- /dev/null
@@ -0,0 +1,116 @@
+# $Id: Makefile.X11,v 1.1 2003/08/22 20:11:44 brianp Exp $
+
+# 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 
+
+MINIGLX_SOURCES = server/r128_dri.c 
+
+DRIVER_SOURCES = \
+               r128_context.c \
+               r128_lock.c \
+               r128_state.c \
+               r128_texstate.c \
+               r128_dd.c \
+               r128_screen.c \
+               r128_tex.c \
+               r128_tris.c \
+               r128_ioctl.c \
+               r128_span.c \
+               r128_texmem.c \
+               r128_vb.c \
+                ../common/mm.c \
+                ../common/utils.c \
+                ../common/texmem.c \
+                ../common/vblank.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) 
+
+### 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 r128_dri.so
+
+r128_dri.so:  $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile.X11
+       rm -f $@ && gcc -o $@ -shared $(OBJECTS) $(MESA_MODULES) $(WINOBJ) $(WINLIB) -lc $(GL_LIB_DEPS)
+       rm -f $(TOP)/lib/r128_dri.so && \
+       install r128_dri.so $(TOP)/lib/r128_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
+
+
+include $(TOP)/Make-config
+
+include depend
diff --git a/src/mesa/drivers/dri/r128/r128_context.c b/src/mesa/drivers/dri/r128/r128_context.c
new file mode 100644 (file)
index 0000000..f7f6d71
--- /dev/null
@@ -0,0 +1,335 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_context.c,v 1.8 2002/10/30 12:51:38 alanh Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+                                               Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#include "glheader.h"
+#include "context.h"
+#include "simple_list.h"
+#include "imports.h"
+#include "matrix.h"
+#include "extensions.h"
+
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "array_cache/acache.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_pipeline.h"
+
+#include "r128_context.h"
+#include "r128_ioctl.h"
+#include "r128_dd.h"
+#include "r128_state.h"
+#include "r128_span.h"
+#include "r128_tex.h"
+#include "r128_tris.h"
+#include "r128_vb.h"
+
+#include "vblank.h"
+#include "utils.h"
+#include "texmem.h"
+
+#ifndef R128_DEBUG
+int R128_DEBUG = 0;
+#endif
+
+static const char * const card_extensions[] =
+{
+   "GL_ARB_multitexture",
+   "GL_ARB_texture_env_add",
+   "GL_ARB_texture_mirrored_repeat",
+   "GL_EXT_texture_edge_clamp",
+   "GL_EXT_texture_env_add",
+   "GL_IBM_texture_mirrored_repeat",
+   "GL_SGIS_generate_mipmap",
+   "GL_SGIS_texture_edge_clamp",
+   NULL
+};
+
+static const struct dri_debug_control debug_control[] =
+{
+    { "ioctl", DEBUG_VERBOSE_IOCTL },
+    { "verb",  DEBUG_VERBOSE_MSG },
+    { "dri",   DEBUG_VERBOSE_DRI },
+    { "2d",    DEBUG_VERBOSE_2D },
+    { "sync",  DEBUG_ALWAYS_SYNC },
+    { "api",   DEBUG_VERBOSE_API },
+    { NULL,    0 }
+};
+
+/* Create the device specific context.
+ */
+GLboolean r128CreateContext( const __GLcontextModes *glVisual,
+                            __DRIcontextPrivate *driContextPriv,
+                             void *sharedContextPrivate )
+{
+   GLcontext *ctx, *shareCtx;
+   __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
+   r128ContextPtr rmesa;
+   r128ScreenPtr r128scrn;
+   int i;
+
+   /* Allocate the r128 context */
+   rmesa = (r128ContextPtr) CALLOC( sizeof(*rmesa) );
+   if ( !rmesa )
+      return GL_FALSE;
+
+   /* Allocate the Mesa context */
+   if (sharedContextPrivate)
+      shareCtx = ((r128ContextPtr) sharedContextPrivate)->glCtx;
+   else 
+      shareCtx = NULL;
+   rmesa->glCtx = _mesa_create_context(glVisual, shareCtx, (void *) rmesa, GL_TRUE);
+   if (!rmesa->glCtx) {
+      FREE(rmesa);
+      return GL_FALSE;
+   }
+   driContextPriv->driverPrivate = rmesa;
+   ctx = rmesa->glCtx;
+
+   rmesa->driContext = driContextPriv;
+   rmesa->driScreen = sPriv;
+   rmesa->driDrawable = NULL;
+   rmesa->hHWContext = driContextPriv->hHWContext;
+   rmesa->driHwLock = &sPriv->pSAREA->lock;
+   rmesa->driFd = sPriv->fd;
+
+   r128scrn = rmesa->r128Screen = (r128ScreenPtr)(sPriv->private);
+
+   rmesa->sarea = (R128SAREAPrivPtr)((char *)sPriv->pSAREA +
+                                    r128scrn->sarea_priv_offset);
+
+   rmesa->CurrentTexObj[0] = NULL;
+   rmesa->CurrentTexObj[1] = NULL;
+
+   (void) memset( rmesa->texture_heaps, 0, sizeof( rmesa->texture_heaps ) );
+   make_empty_list( & rmesa->swapped );
+
+   rmesa->nr_heaps = r128scrn->numTexHeaps;
+   for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
+      rmesa->texture_heaps[i] = driCreateTextureHeap( i, rmesa,
+           r128scrn->texSize[i],
+           12,
+           R128_NR_TEX_REGIONS,
+           rmesa->sarea->texList[i],
+           & rmesa->sarea->texAge[i],
+           & rmesa->swapped,
+           sizeof( r128TexObj ),
+           (destroy_texture_object_t *) r128DestroyTexObj );
+
+      driSetTextureSwapCounterLocation( rmesa->texture_heaps[i],
+                                       & rmesa->c_textureSwaps );
+   }
+
+
+   rmesa->RenderIndex = -1;            /* Impossible value */
+   rmesa->vert_buf = NULL;
+   rmesa->num_verts = 0;
+
+   /* Set the maximum texture size small enough that we can guarentee that
+    * all texture units can bind a maximal texture and have them both in
+    * texturable memory at once.
+    */
+
+   ctx->Const.MaxTextureUnits = 2;
+
+   driCalculateMaxTextureLevels( rmesa->texture_heaps,
+                                rmesa->nr_heaps,
+                                & ctx->Const,
+                                4,
+                                10, /* max 2D texture size is 1024x1024 */
+                                0,  /* 3D textures unsupported. */
+                                0,  /* cube textures unsupported. */
+                                0,  /* texture rectangles unsupported. */
+                                11,
+                                GL_FALSE );
+
+   /* No wide points.
+    */
+   ctx->Const.MinPointSize = 1.0;
+   ctx->Const.MinPointSizeAA = 1.0;
+   ctx->Const.MaxPointSize = 1.0;
+   ctx->Const.MaxPointSizeAA = 1.0;
+
+   /* No wide lines.
+    */
+   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;
+
+#if ENABLE_PERF_BOXES
+   rmesa->boxes = (getenv( "LIBGL_PERFORMANCE_BOXES" ) != NULL);
+#endif
+
+   /* Initialize the software rasterizer and helper modules.
+    */
+   _swrast_CreateContext( ctx );
+   _ac_CreateContext( ctx );
+   _tnl_CreateContext( ctx );
+   _swsetup_CreateContext( ctx );
+
+   /* Install the customized pipeline:
+    */
+/*     _tnl_destroy_pipeline( ctx ); */
+/*     _tnl_install_pipeline( ctx, r128_pipeline ); */
+
+   /* Configure swrast to match hardware characteristics:
+    */
+   _swrast_allow_pixel_fog( ctx, GL_FALSE );
+   _swrast_allow_vertex_fog( ctx, GL_TRUE );
+
+   driInitExtensions( ctx, card_extensions, GL_TRUE );
+   if (sPriv->drmMinor >= 4)
+      _mesa_enable_extension( ctx, "GL_MESA_ycbcr_texture" );
+
+   r128InitVB( ctx );
+   r128InitTriFuncs( ctx );
+   r128DDInitDriverFuncs( ctx );
+   r128DDInitIoctlFuncs( ctx );
+   r128DDInitStateFuncs( ctx );
+   r128DDInitSpanFuncs( ctx );
+   r128DDInitTextureFuncs( ctx );
+   r128DDInitState( rmesa );
+
+   rmesa->do_irqs = (rmesa->r128Screen->irq && !getenv("R128_NO_IRQS"));
+
+   rmesa->vblank_flags = (rmesa->do_irqs)
+       ? driGetDefaultVBlankFlags() : VBLANK_FLAG_NO_IRQ;
+
+   driContextPriv->driverPrivate = (void *)rmesa;
+
+#if DO_DEBUG
+   R128_DEBUG = driParseDebugString( getenv( "R128_DEBUG" ),
+                                    debug_control );
+#endif
+
+   return GL_TRUE;
+}
+
+/* Destroy the device specific context.
+ */
+void r128DestroyContext( __DRIcontextPrivate *driContextPriv  )
+{
+   r128ContextPtr rmesa = (r128ContextPtr) driContextPriv->driverPrivate;
+
+   assert(rmesa);  /* should never be null */
+   if ( rmesa ) {
+      GLboolean   release_texture_heaps;
+
+
+      release_texture_heaps = (rmesa->glCtx->Shared->RefCount == 1);
+
+      _swsetup_DestroyContext( rmesa->glCtx );
+      _tnl_DestroyContext( rmesa->glCtx );
+      _ac_DestroyContext( rmesa->glCtx );
+      _swrast_DestroyContext( rmesa->glCtx );
+
+      r128FreeVB( rmesa->glCtx );
+
+      /* free the Mesa context */
+      rmesa->glCtx->DriverCtx = NULL;
+      _mesa_destroy_context(rmesa->glCtx);
+
+      if ( release_texture_heaps ) {
+         /* This share group is about to go away, free our private
+          * texture object data.
+          */
+         int i;
+
+        assert( is_empty_list( & rmesa->swapped ) );
+
+         for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
+           driDestroyTextureHeap( rmesa->texture_heaps[ i ] );
+           rmesa->texture_heaps[ i ] = NULL;
+         }
+      }
+
+      FREE( rmesa );
+   }
+
+#if 0
+   /* Use this to force shared object profiling. */
+   glx_fini_prof();
+#endif
+}
+
+
+/* Force the context `c' to be the current context and associate with it
+ * buffer `b'.
+ */
+GLboolean
+r128MakeCurrent( __DRIcontextPrivate *driContextPriv,
+                 __DRIdrawablePrivate *driDrawPriv,
+                 __DRIdrawablePrivate *driReadPriv )
+{
+   if ( driContextPriv ) {
+      GET_CURRENT_CONTEXT(ctx);
+      r128ContextPtr oldR128Ctx = ctx ? R128_CONTEXT(ctx) : NULL;
+      r128ContextPtr newR128Ctx = (r128ContextPtr) driContextPriv->driverPrivate;
+
+      if ( newR128Ctx != oldR128Ctx ) {
+        newR128Ctx->new_state |= R128_NEW_CONTEXT;
+        newR128Ctx->dirty = R128_UPLOAD_ALL;
+      }
+
+      newR128Ctx->driDrawable = driDrawPriv;
+
+      _mesa_make_current2( newR128Ctx->glCtx,
+                           (GLframebuffer *) driDrawPriv->driverPrivate,
+                           (GLframebuffer *) driReadPriv->driverPrivate );
+
+
+      newR128Ctx->new_state |= R128_NEW_WINDOW | R128_NEW_CLIP;
+
+      if ( !newR128Ctx->glCtx->Viewport.Width ) {
+        _mesa_set_viewport(newR128Ctx->glCtx, 0, 0,
+                            driDrawPriv->w, driDrawPriv->h);
+      }
+   } else {
+      _mesa_make_current( 0, 0 );
+   }
+
+   return GL_TRUE;
+}
+
+
+/* Force the context `c' to be unbound from its buffer.
+ */
+GLboolean
+r128UnbindContext( __DRIcontextPrivate *driContextPriv )
+{
+   return GL_TRUE;
+}
diff --git a/src/mesa/drivers/dri/r128/r128_context.h b/src/mesa/drivers/dri/r128/r128_context.h
new file mode 100644 (file)
index 0000000..9c93012
--- /dev/null
@@ -0,0 +1,270 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_context.h,v 1.12 2002/12/16 16:18:52 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+                                               Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#ifndef __R128_CONTEXT_H__
+#define __R128_CONTEXT_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include "dri_util.h"
+
+#include "xf86drm.h"
+#include "r128_common.h"
+
+#include "mtypes.h"
+
+#include "r128_reg.h"
+
+#include "texmem.h"
+
+struct r128_context;
+typedef struct r128_context r128ContextRec;
+typedef struct r128_context *r128ContextPtr;
+
+#include "r128_lock.h"
+#include "r128_texobj.h"
+#include "r128_screen.h"
+
+/* Flags for what context state needs to be updated:
+ */
+#define R128_NEW_ALPHA         0x0001
+#define R128_NEW_DEPTH         0x0002
+#define R128_NEW_FOG           0x0004
+#define R128_NEW_CLIP          0x0008
+#define R128_NEW_CULL          0x0010
+#define R128_NEW_MASKS         0x0020
+#define R128_NEW_RENDER_NOT    0x0040
+#define R128_NEW_WINDOW                0x0080
+#define R128_NEW_CONTEXT       0x0100
+#define R128_NEW_ALL           0x01ff
+
+/* Flags for software fallback cases:
+ */
+#define R128_FALLBACK_TEXTURE          0x0001
+#define R128_FALLBACK_DRAW_BUFFER      0x0002
+#define R128_FALLBACK_READ_BUFFER      0x0004
+#define R128_FALLBACK_STENCIL          0x0008
+#define R128_FALLBACK_RENDER_MODE      0x0010
+#define R128_FALLBACK_MULTIDRAW                0x0020
+#define R128_FALLBACK_LOGICOP          0x0040
+#define R128_FALLBACK_SEP_SPECULAR     0x0080
+#define R128_FALLBACK_BLEND_EQ         0x0100
+#define R128_FALLBACK_BLEND_FUNC       0x0200
+
+
+/* Use the templated vertex format:
+ */
+#define TAG(x) r128##x
+#include "tnl_dd/t_dd_vertex.h"
+#undef TAG
+
+/* Reasons why the GL_BLEND fallback mightn't work:
+ */
+#define R128_BLEND_ENV_COLOR   0x1
+#define R128_BLEND_MULTITEX    0x2
+
+/* Subpixel offsets for window coordinates (triangles):
+ */
+#define SUBPIXEL_X  (0.0F)
+#define SUBPIXEL_Y  (0.125F)
+
+
+typedef void (*r128_tri_func)( r128ContextPtr, 
+                                r128Vertex *,
+                                r128Vertex *,
+                                r128Vertex * );
+
+typedef void (*r128_line_func)( r128ContextPtr, 
+                                 r128Vertex *,
+                                 r128Vertex * );
+
+typedef void (*r128_point_func)( r128ContextPtr,
+                                  r128Vertex * );
+
+
+struct r128_context {
+   GLcontext *glCtx;                   /* Mesa context */
+
+   /* Driver and hardware state management
+    */
+   GLuint new_state;
+   GLuint dirty;                       /* Hardware state to be updated */
+   r128_context_regs_t setup;
+
+   /* Temporaries for translating away float colors:
+    */
+   struct gl_client_array UbyteColor;
+   struct gl_client_array UbyteSecondaryColor;
+
+   GLuint NewGLState;
+   GLuint Fallback;
+   GLuint SetupIndex;
+   GLuint SetupNewInputs;
+   GLuint RenderIndex;
+   GLfloat hw_viewport[16];
+   GLfloat depth_scale;
+   GLuint vertex_size;
+   GLuint vertex_stride_shift;
+   GLuint vertex_format;
+   GLuint num_verts;
+   GLubyte *verts;             
+
+   CARD32 ClearColor;                  /* Color used to clear color buffer */
+   CARD32 ClearDepth;                  /* Value used to clear depth buffer */
+   CARD32 ClearStencil;                        /* Value used to clear stencil */
+
+   /* Map GL texture units onto hardware
+    */
+   GLint multitex;
+   GLint tmu_source[2];
+   GLuint tex_combine[2];
+   GLuint blend_flags;
+   GLuint env_color;
+
+   /* Texture object bookkeeping
+    */
+   unsigned              nr_heaps;
+   driTexHeap          * texture_heaps[ R128_NR_TEX_HEAPS ];
+   driTextureObject      swapped;
+
+   r128TexObjPtr CurrentTexObj[2];
+   /* Fallback rasterization functions 
+    */
+   r128_point_func draw_point;
+   r128_line_func draw_line;
+   r128_tri_func draw_tri;
+
+   /* Vertex buffers
+    */
+   drmBufPtr vert_buf;
+
+   GLuint hw_primitive;
+   GLenum render_primitive;
+
+   /* Page flipping
+    */
+   GLuint doPageFlip;
+
+   /* Busy waiting
+    */
+   GLuint do_irqs;
+
+   /* Drawable, cliprect and scissor information
+    */
+   GLint drawOffset, drawPitch;
+   GLint readOffset, readPitch;
+
+   GLuint numClipRects;                        /* Cliprects for the draw buffer */
+   XF86DRIClipRectPtr pClipRects;
+
+   GLuint scissor;
+   XF86DRIClipRectRec ScissorRect;     /* Current software scissor */
+
+   /* Mirrors of some DRI state
+    */
+   __DRIcontextPrivate *driContext;    /* DRI context */
+   __DRIscreenPrivate  *driScreen;     /* DRI screen */
+   __DRIdrawablePrivate        *driDrawable;   /* DRI drawable bound to this ctx */
+
+   unsigned int lastStamp;             /* mirror driDrawable->lastStamp */
+
+   drmContext hHWContext;
+   drmLock *driHwLock;
+   int driFd;
+
+   r128ScreenPtr r128Screen;           /* Screen private DRI data */
+   R128SAREAPrivPtr sarea;             /* Private SAREA data */
+
+   /* Performance counters
+    */
+   GLuint boxes;                       /* Draw performance boxes */
+   GLuint hardwareWentIdle;
+   GLuint c_clears;
+   GLuint c_drawWaits;
+   GLuint c_textureSwaps;
+   GLuint c_textureBytes;
+   GLuint c_vertexBuffers;
+
+   /* VBI
+    */
+   GLuint vbl_seq;
+   GLuint vblank_flags;
+};
+
+#define R128_CONTEXT(ctx)              ((r128ContextPtr)(ctx->DriverCtx))
+
+#define R128_IS_PLAIN( rmesa ) \
+               (rmesa->r128Screen->chipset == R128_CARD_TYPE_R128)
+#define R128_IS_PRO( rmesa ) \
+               (rmesa->r128Screen->chipset == R128_CARD_TYPE_R128_PRO)
+#define R128_IS_MOBILITY( rmesa ) \
+               (rmesa->r128Screen->chipset == R128_CARD_TYPE_R128_MOBILITY)
+
+
+extern GLboolean r128CreateContext( const __GLcontextModes *glVisual,
+                                   __DRIcontextPrivate *driContextPriv,
+                                    void *sharedContextPrivate );
+
+extern void r128DestroyContext( __DRIcontextPrivate * );
+
+extern GLboolean r128MakeCurrent( __DRIcontextPrivate *driContextPriv,
+                                  __DRIdrawablePrivate *driDrawPriv,
+                                  __DRIdrawablePrivate *driReadPriv );
+
+extern GLboolean r128UnbindContext( __DRIcontextPrivate *driContextPriv );
+
+/* ================================================================
+ * Debugging:
+ */
+#define DO_DEBUG               0
+#define ENABLE_PERF_BOXES      0
+
+#if DO_DEBUG
+extern int R128_DEBUG;
+#else
+#define R128_DEBUG             0
+#endif
+
+#define DEBUG_ALWAYS_SYNC      0x01
+#define DEBUG_VERBOSE_API      0x02
+#define DEBUG_VERBOSE_MSG      0x04
+#define DEBUG_VERBOSE_LRU      0x08
+#define DEBUG_VERBOSE_DRI      0x10
+#define DEBUG_VERBOSE_IOCTL    0x20
+#define DEBUG_VERBOSE_2D       0x40
+
+#endif
+#endif /* __R128_CONTEXT_H__ */
diff --git a/src/mesa/drivers/dri/r128/r128_dd.c b/src/mesa/drivers/dri/r128/r128_dd.c
new file mode 100644 (file)
index 0000000..b64c26b
--- /dev/null
@@ -0,0 +1,148 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_dd.c,v 1.15 2002/10/30 12:51:38 alanh Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+                                               Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Gareth Hughes <gareth@valinux.com>
+ *   Kevin E. Martin <martin@valinux.com>
+ *
+ */
+
+#include "r128_context.h"
+#include "r128_ioctl.h"
+#include "r128_state.h"
+#include "r128_vb.h"
+#include "r128_dd.h"
+
+#include "context.h"
+
+#include "utils.h"
+
+#define DRIVER_DATE    "20030328"
+
+
+/* Return the width and height of the current color buffer.
+ */
+static void r128DDGetBufferSize( GLframebuffer *buffer,
+                                GLuint *width, GLuint *height )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   LOCK_HARDWARE( rmesa );
+   *width  = rmesa->driDrawable->w;
+   *height = rmesa->driDrawable->h;
+   UNLOCK_HARDWARE( rmesa );
+}
+
+/* Return various strings for glGetString().
+ */
+static const GLubyte *r128DDGetString( GLcontext *ctx, GLenum name )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   static char buffer[128];
+   unsigned   offset;
+   const char * card_name = "Rage 128";
+   GLuint agp_mode = rmesa->r128Screen->IsPCI ? 0 :
+      rmesa->r128Screen->AGPMode;
+
+   switch ( name ) {
+   case GL_VENDOR:
+      return (GLubyte *)"VA Linux Systems, Inc.";
+
+   case GL_RENDERER:
+      /* Select the spefic chipset.
+       */
+      if ( R128_IS_PRO( rmesa ) ) {
+        card_name = "Rage 128 Pro";
+      }
+      else if ( R128_IS_MOBILITY( rmesa ) ) {
+        card_name = "Rage 128 Mobility";
+      }
+
+      offset = driGetRendererString( buffer, card_name, DRIVER_DATE,
+                                    agp_mode );
+
+      return (GLubyte *)buffer;
+
+   default:
+      return NULL;
+   }
+}
+
+/* Send all commands to the hardware.  If vertex buffers or indirect
+ * buffers are in use, then we need to make sure they are sent to the
+ * hardware.  All commands that are normally sent to the ring are
+ * already considered `flushed'.
+ */
+static void r128DDFlush( GLcontext *ctx )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   FLUSH_BATCH( rmesa );
+
+#if ENABLE_PERF_BOXES
+   if ( rmesa->boxes ) {
+      LOCK_HARDWARE( rmesa );
+      r128PerformanceBoxesLocked( rmesa );
+      UNLOCK_HARDWARE( rmesa );
+   }
+
+   /* Log the performance counters if necessary */
+   r128PerformanceCounters( rmesa );
+#endif
+}
+
+/* Make sure all commands have been sent to the hardware and have
+ * completed processing.
+ */
+static void r128DDFinish( GLcontext *ctx )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+#if ENABLE_PERF_BOXES
+   /* Bump the performance counter */
+   rmesa->c_drawWaits++;
+#endif
+
+   r128DDFlush( ctx );
+   r128WaitForIdle( rmesa );
+}
+
+
+/* Initialize the driver's misc functions.
+ */
+void r128DDInitDriverFuncs( GLcontext *ctx )
+{
+   ctx->Driver.GetBufferSize   = r128DDGetBufferSize;
+   ctx->Driver.ResizeBuffers    = _swrast_alloc_buffers;
+   ctx->Driver.GetString       = r128DDGetString;
+   ctx->Driver.Finish          = r128DDFinish;
+   ctx->Driver.Flush           = r128DDFlush;
+   ctx->Driver.Error           = NULL;
+}
diff --git a/src/mesa/drivers/dri/r128/r128_dd.h b/src/mesa/drivers/dri/r128/r128_dd.h
new file mode 100644 (file)
index 0000000..b8fc7ad
--- /dev/null
@@ -0,0 +1,44 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_dd.h,v 1.3 2001/01/08 01:07:20 martin Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+                                               Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Gareth Hughes <gareth@valinux.com>
+ *   Kevin E. Martin <martin@valinux.com>
+ *
+ */
+
+#ifndef __R128_DD_H__
+#define __R128_DD_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+extern void r128DDInitDriverFuncs( GLcontext *ctx );
+
+#endif
+#endif
diff --git a/src/mesa/drivers/dri/r128/r128_ioctl.c b/src/mesa/drivers/dri/r128/r128_ioctl.c
new file mode 100644 (file)
index 0000000..c584347
--- /dev/null
@@ -0,0 +1,812 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_ioctl.c,v 1.10 2002/12/16 16:18:53 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+                                               Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Gareth Hughes <gareth@valinux.com>
+ *
+ */
+#include <errno.h>
+
+#include "r128_context.h"
+#include "r128_state.h"
+#include "r128_ioctl.h"
+#include "r128_macros.h"
+
+#include "imports.h"
+#include "macros.h"
+
+#include "swrast/swrast.h"
+
+#include "vblank.h"
+
+#define R128_TIMEOUT        2048
+#define R128_IDLE_RETRY       32
+
+
+/* =============================================================
+ * Hardware vertex buffer handling
+ */
+
+/* Get a new VB from the pool of vertex buffers in AGP space.
+ */
+drmBufPtr r128GetBufferLocked( r128ContextPtr rmesa )
+{
+   int fd = rmesa->r128Screen->driScreen->fd;
+   int index = 0;
+   int size = 0;
+   drmDMAReq dma;
+   drmBufPtr buf = NULL;
+   int to = 0;
+   int ret;
+
+   dma.context = rmesa->hHWContext;
+   dma.send_count = 0;
+   dma.send_list = NULL;
+   dma.send_sizes = NULL;
+   dma.flags = 0;
+   dma.request_count = 1;
+   dma.request_size = R128_BUFFER_SIZE;
+   dma.request_list = &index;
+   dma.request_sizes = &size;
+   dma.granted_count = 0;
+
+   while ( !buf && ( to++ < R128_TIMEOUT ) ) {
+      ret = drmDMA( fd, &dma );
+
+      if ( ret == 0 ) {
+        buf = &rmesa->r128Screen->buffers->list[index];
+        buf->used = 0;
+#if ENABLE_PERF_BOXES
+        /* Bump the performance counter */
+        rmesa->c_vertexBuffers++;
+#endif
+        return buf;
+      }
+   }
+
+   if ( !buf ) {
+      drmCommandNone( fd, DRM_R128_CCE_RESET);
+      UNLOCK_HARDWARE( rmesa );
+      fprintf( stderr, "Error: Could not get new VB... exiting\n" );
+      exit( -1 );
+   }
+
+   return buf;
+}
+
+void r128FlushVerticesLocked( r128ContextPtr rmesa )
+{
+   XF86DRIClipRectPtr pbox = rmesa->pClipRects;
+   int nbox = rmesa->numClipRects;
+   drmBufPtr buffer = rmesa->vert_buf;
+   int count = rmesa->num_verts;
+   int prim = rmesa->hw_primitive;
+   int fd = rmesa->driScreen->fd;
+   drmR128Vertex vertex;
+   int i;
+
+   rmesa->num_verts = 0;
+   rmesa->vert_buf = NULL;
+
+   if ( !buffer )
+      return;
+
+   if ( rmesa->dirty & ~R128_UPLOAD_CLIPRECTS )
+      r128EmitHwStateLocked( rmesa );
+
+   if ( !nbox )
+      count = 0;
+
+   if ( nbox >= R128_NR_SAREA_CLIPRECTS )
+      rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
+
+   if ( !count || !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
+   {
+      if ( nbox < 3 ) {
+        rmesa->sarea->nbox = 0;
+      } else {
+        rmesa->sarea->nbox = nbox;
+      }
+
+      vertex.prim = prim;
+      vertex.idx = buffer->idx;
+      vertex.count = count;
+      vertex.discard = 1;
+      drmCommandWrite( fd, DRM_R128_VERTEX, &vertex, sizeof(drmR128Vertex) );
+   }
+   else
+   {
+      for ( i = 0 ; i < nbox ; ) {
+        int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
+        XF86DRIClipRectPtr b = rmesa->sarea->boxes;
+        int discard = 0;
+
+        rmesa->sarea->nbox = nr - i;
+        for ( ; i < nr ; i++ ) {
+           *b++ = pbox[i];
+        }
+
+        /* Finished with the buffer?
+         */
+        if ( nr == nbox ) {
+           discard = 1;
+        }
+
+        rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
+
+         vertex.prim = prim;
+         vertex.idx = buffer->idx;
+         vertex.count = count;
+         vertex.discard = discard;
+         drmCommandWrite( fd, DRM_R128_VERTEX, &vertex, sizeof(drmR128Vertex) );
+      }
+   }
+
+   rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
+}
+
+
+
+
+
+/* ================================================================
+ * Texture uploads
+ */
+
+void r128FireBlitLocked( r128ContextPtr rmesa, drmBufPtr buffer,
+                        GLint offset, GLint pitch, GLint format,
+                        GLint x, GLint y, GLint width, GLint height )
+{
+   drmR128Blit blit;
+   GLint ret;
+
+   blit.idx = buffer->idx;
+   blit.offset = offset;
+   blit.pitch = pitch;
+   blit.format = format;
+   blit.x = x;
+   blit.y = y;
+   blit.width = width;
+   blit.height = height;
+
+   ret = drmCommandWrite( rmesa->driFd, DRM_R128_BLIT, 
+                          &blit, sizeof(drmR128Blit) );
+
+   if ( ret ) {
+      UNLOCK_HARDWARE( rmesa );
+      fprintf( stderr, "DRM_R128_BLIT: return = %d\n", ret );
+      exit( 1 );
+   }
+}
+
+
+/* ================================================================
+ * SwapBuffers with client-side throttling
+ */
+
+static void delay( void ) {
+/* Prevent an optimizing compiler from removing a spin loop */
+}
+
+#define R128_MAX_OUTSTANDING   2
+
+/* Throttle the frame rate -- only allow one pending swap buffers
+ * request at a time.
+ * GH: We probably don't want a timeout here, as we can wait as
+ * long as we want for a frame to complete.  If it never does, then
+ * the card has locked.
+ */
+static int r128WaitForFrameCompletion( r128ContextPtr rmesa )
+{
+   unsigned char *R128MMIO = rmesa->r128Screen->mmio.map;
+   CARD32 frame;
+   int i;
+   int wait = 0;
+
+   while ( 1 ) {
+      frame = INREG( R128_LAST_FRAME_REG );
+      if ( rmesa->sarea->last_frame - frame <= R128_MAX_OUTSTANDING ) {
+        break;
+      }
+
+      /* Spin in place a bit so we aren't hammering the register */
+      wait++;
+      for ( i = 0 ; i < 1024 ; i++ ) {
+        delay();
+      }
+   }
+
+   return wait;
+}
+
+/* Copy the back color buffer to the front color buffer.
+ */
+void r128CopyBuffer( const __DRIdrawablePrivate *dPriv )
+{
+   r128ContextPtr rmesa;
+   GLint nbox, i, ret;
+   GLboolean missed_target;
+
+   assert(dPriv);
+   assert(dPriv->driContextPriv);
+   assert(dPriv->driContextPriv->driverPrivate);
+
+   rmesa = (r128ContextPtr) dPriv->driContextPriv->driverPrivate;
+
+   if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
+      fprintf( stderr, "\n********************************\n" );
+      fprintf( stderr, "\n%s( %p )\n\n",
+              __FUNCTION__, rmesa->glCtx );
+      fflush( stderr );
+   }
+
+   FLUSH_BATCH( rmesa );
+
+   LOCK_HARDWARE( rmesa );
+
+   /* Throttle the frame rate -- only allow one pending swap buffers
+    * request at a time.
+    */
+   if ( !r128WaitForFrameCompletion( rmesa ) ) {
+      rmesa->hardwareWentIdle = 1;
+   } else {
+      rmesa->hardwareWentIdle = 0;
+   }
+
+   UNLOCK_HARDWARE( rmesa );
+   driWaitForVBlank( dPriv, &rmesa->vbl_seq, rmesa->vblank_flags, &missed_target );
+   LOCK_HARDWARE( rmesa );
+
+   nbox = dPriv->numClipRects; /* must be in locked region */
+
+   for ( i = 0 ; i < nbox ; ) {
+      GLint nr = MIN2( i + R128_NR_SAREA_CLIPRECTS , nbox );
+      XF86DRIClipRectPtr box = dPriv->pClipRects;
+      XF86DRIClipRectPtr b = rmesa->sarea->boxes;
+      GLint n = 0;
+
+      for ( ; i < nr ; i++ ) {
+        *b++ = *(XF86DRIClipRectRec *)&box[i];
+        n++;
+      }
+      rmesa->sarea->nbox = n;
+
+      ret = drmCommandNone( rmesa->driFd, DRM_R128_SWAP );
+
+      if ( ret ) {
+        UNLOCK_HARDWARE( rmesa );
+        fprintf( stderr, "DRM_R128_SWAP: return = %d\n", ret );
+        exit( 1 );
+      }
+   }
+
+   if ( R128_DEBUG & DEBUG_ALWAYS_SYNC ) {
+      i = 0;
+      do {
+         ret = drmCommandNone(rmesa->driFd, DRM_R128_CCE_IDLE);
+      } while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY );
+   }
+
+   UNLOCK_HARDWARE( rmesa );
+
+   rmesa->new_state |= R128_NEW_CONTEXT;
+   rmesa->dirty |= (R128_UPLOAD_CONTEXT |
+                   R128_UPLOAD_MASKS |
+                   R128_UPLOAD_CLIPRECTS);
+
+#if ENABLE_PERF_BOXES
+   /* Log the performance counters if necessary */
+   r128PerformanceCounters( rmesa );
+#endif
+}
+
+void r128PageFlip( const __DRIdrawablePrivate *dPriv )
+{
+   r128ContextPtr rmesa;
+   GLint ret;
+   GLboolean missed_target;
+
+   assert(dPriv);
+   assert(dPriv->driContextPriv);
+   assert(dPriv->driContextPriv->driverPrivate);
+
+   rmesa = (r128ContextPtr) dPriv->driContextPriv->driverPrivate;
+
+   if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
+      fprintf( stderr, "\n%s( %p ): page=%d\n\n",
+              __FUNCTION__, rmesa->glCtx, rmesa->sarea->pfCurrentPage );
+   }
+
+   FLUSH_BATCH( rmesa );
+
+   LOCK_HARDWARE( rmesa );
+
+   /* Throttle the frame rate -- only allow one pending swap buffers
+    * request at a time.
+    */
+   if ( !r128WaitForFrameCompletion( rmesa ) ) {
+      rmesa->hardwareWentIdle = 1;
+   } else {
+      rmesa->hardwareWentIdle = 0;
+   }
+
+   UNLOCK_HARDWARE( rmesa );
+   driWaitForVBlank( dPriv, &rmesa->vbl_seq, rmesa->vblank_flags, &missed_target );
+   LOCK_HARDWARE( rmesa );
+
+   /* The kernel will have been initialized to perform page flipping
+    * on a swapbuffers ioctl.
+    */
+   ret = drmCommandNone( rmesa->driFd, DRM_R128_FLIP );
+
+   UNLOCK_HARDWARE( rmesa );
+
+   if ( ret ) {
+      fprintf( stderr, "DRM_R128_FLIP: return = %d\n", ret );
+      exit( 1 );
+   }
+
+   if ( rmesa->sarea->pfCurrentPage == 1 ) {
+        rmesa->drawOffset = rmesa->r128Screen->frontOffset;
+        rmesa->drawPitch  = rmesa->r128Screen->frontPitch;
+   } else {
+        rmesa->drawOffset = rmesa->r128Screen->backOffset;
+        rmesa->drawPitch  = rmesa->r128Screen->backPitch;
+   }
+
+   rmesa->setup.dst_pitch_offset_c = (((rmesa->drawPitch/8) << 21) |
+                                     (rmesa->drawOffset >> 5));
+   rmesa->new_state |= R128_NEW_WINDOW;
+
+   /* FIXME: Do we need this anymore? */
+   rmesa->new_state |= R128_NEW_CONTEXT;
+   rmesa->dirty |= (R128_UPLOAD_CONTEXT |
+                   R128_UPLOAD_MASKS |
+                   R128_UPLOAD_CLIPRECTS);
+
+#if ENABLE_PERF_BOXES
+   /* Log the performance counters if necessary */
+   r128PerformanceCounters( rmesa );
+#endif
+}
+
+
+/* ================================================================
+ * Buffer clear
+ */
+
+static void r128DDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
+                        GLint cx, GLint cy, GLint cw, GLint ch )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   __DRIdrawablePrivate *dPriv = rmesa->driDrawable;
+   drmR128Clear clear;
+   GLuint flags = 0;
+   GLint i;
+   GLint ret;
+
+   if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
+      fprintf( stderr, "%s:\n", __FUNCTION__ );
+   }
+
+   FLUSH_BATCH( rmesa );
+
+   /* The only state change we care about here is the RGBA colormask
+    * We'll just update that state, if needed.  If we do more then
+    * there's some strange side-effects that the conformance tests find.
+    */
+   if ( rmesa->new_state & R128_NEW_MASKS) {
+      const GLuint save_state = rmesa->new_state;
+      rmesa->new_state = R128_NEW_MASKS;
+      r128DDUpdateHWState( ctx );
+      rmesa->new_state = save_state & ~R128_NEW_MASKS;
+   }
+
+   if ( mask & DD_FRONT_LEFT_BIT ) {
+      flags |= DRM_R128_FRONT_BUFFER;
+      mask &= ~DD_FRONT_LEFT_BIT;
+   }
+
+   if ( mask & DD_BACK_LEFT_BIT ) {
+      flags |= DRM_R128_BACK_BUFFER;
+      mask &= ~DD_BACK_LEFT_BIT;
+   }
+
+   if ( ( mask & DD_DEPTH_BIT ) && ctx->Depth.Mask ) {
+      flags |= DRM_R128_DEPTH_BUFFER;
+      mask &= ~DD_DEPTH_BIT;
+   }
+#if 0
+   /* FIXME: Add stencil support */
+   if ( mask & DD_STENCIL_BIT ) {
+      flags |= DRM_R128_DEPTH_BUFFER;
+      mask &= ~DD_STENCIL_BIT;
+   }
+#endif
+
+   if ( flags ) {
+
+      /* Flip top to bottom */
+      cx += dPriv->x;
+      cy  = dPriv->y + dPriv->h - cy - ch;
+
+      LOCK_HARDWARE( rmesa );
+
+      /* FIXME: Do we actually need this?
+       */
+      if ( rmesa->dirty & ~R128_UPLOAD_CLIPRECTS ) {
+        r128EmitHwStateLocked( rmesa );
+      }
+
+      for ( i = 0 ; i < rmesa->numClipRects ; ) {
+        GLint nr = MIN2( i + R128_NR_SAREA_CLIPRECTS , rmesa->numClipRects );
+        XF86DRIClipRectPtr box = rmesa->pClipRects;
+        XF86DRIClipRectPtr b = rmesa->sarea->boxes;
+        GLint n = 0;
+
+        if ( !all ) {
+           for ( ; i < nr ; i++ ) {
+              GLint x = box[i].x1;
+              GLint y = box[i].y1;
+              GLint w = box[i].x2 - x;
+              GLint h = box[i].y2 - y;
+
+              if ( x < cx ) w -= cx - x, x = cx;
+              if ( y < cy ) h -= cy - y, y = cy;
+              if ( x + w > cx + cw ) w = cx + cw - x;
+              if ( y + h > cy + ch ) h = cy + ch - y;
+              if ( w <= 0 ) continue;
+              if ( h <= 0 ) continue;
+
+              b->x1 = x;
+              b->y1 = y;
+              b->x2 = x + w;
+              b->y2 = y + h;
+              b++;
+              n++;
+           }
+        } else {
+           for ( ; i < nr ; i++ ) {
+              *b++ = *(XF86DRIClipRectPtr)&box[i];
+              n++;
+           }
+        }
+
+        rmesa->sarea->nbox = n;
+
+        if ( R128_DEBUG & DEBUG_VERBOSE_IOCTL ) {
+           fprintf( stderr,
+                    "DRM_R128_CLEAR: flag 0x%x color %x depth %x nbox %d\n",
+                    flags,
+                    (GLuint)rmesa->ClearColor,
+                    (GLuint)rmesa->ClearDepth,
+                    rmesa->sarea->nbox );
+        }
+
+         clear.flags = flags;
+         clear.clear_color = rmesa->ClearColor;
+         clear.clear_depth = rmesa->ClearDepth;
+         clear.color_mask = rmesa->setup.plane_3d_mask_c;
+         clear.depth_mask = ~0;
+
+         ret = drmCommandWrite( rmesa->driFd, DRM_R128_CLEAR,
+                                &clear, sizeof(drmR128Clear) );
+
+        if ( ret ) {
+           UNLOCK_HARDWARE( rmesa );
+           fprintf( stderr, "DRM_R128_CLEAR: return = %d\n", ret );
+           exit( 1 );
+        }
+      }
+
+      UNLOCK_HARDWARE( rmesa );
+
+      rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
+   }
+
+   if ( mask )
+      _swrast_Clear( ctx, mask, all, cx, cy, cw, ch );
+}
+
+
+/* ================================================================
+ * Depth spans, pixels
+ */
+
+void r128WriteDepthSpanLocked( r128ContextPtr rmesa,
+                              GLuint n, GLint x, GLint y,
+                              const GLdepth depth[],
+                              const GLubyte mask[] )
+{
+   XF86DRIClipRectPtr pbox = rmesa->pClipRects;
+   drmR128Depth d;
+   int nbox = rmesa->numClipRects;
+   int fd = rmesa->driScreen->fd;
+   int i;
+
+   if ( !nbox || !n ) {
+      return;
+   }
+   if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
+      rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
+   }
+
+   if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
+   {
+      if ( nbox < 3 ) {
+        rmesa->sarea->nbox = 0;
+      } else {
+        rmesa->sarea->nbox = nbox;
+      }
+
+      d.func = DRM_R128_WRITE_SPAN;
+      d.n = n;
+      d.x = (int*)&x;
+      d.y = (int*)&y;
+      d.buffer = (unsigned int *)depth;
+      d.mask = (unsigned char *)mask;
+
+      drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
+
+   }
+   else
+   {
+      for (i = 0 ; i < nbox ; ) {
+        int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
+        XF86DRIClipRectPtr b = rmesa->sarea->boxes;
+
+        rmesa->sarea->nbox = nr - i;
+        for ( ; i < nr ; i++) {
+           *b++ = pbox[i];
+        }
+
+        rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
+
+         d.func = DRM_R128_WRITE_SPAN;
+         d.n = n;
+         d.x = (int*)&x;
+         d.y = (int*)&y;
+         d.buffer = (unsigned int *)depth;
+         d.mask = (unsigned char *)mask;
+
+         drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
+      }
+   }
+
+   rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
+}
+
+void r128WriteDepthPixelsLocked( r128ContextPtr rmesa, GLuint n,
+                                const GLint x[], const GLint y[],
+                                const GLdepth depth[],
+                                const GLubyte mask[] )
+{
+   XF86DRIClipRectPtr pbox = rmesa->pClipRects;
+   drmR128Depth d;
+   int nbox = rmesa->numClipRects;
+   int fd = rmesa->driScreen->fd;
+   int i;
+
+   if ( !nbox || !n ) {
+      return;
+   }
+   if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
+      rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
+   }
+
+   if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
+   {
+      if ( nbox < 3 ) {
+        rmesa->sarea->nbox = 0;
+      } else {
+        rmesa->sarea->nbox = nbox;
+      }
+
+      d.func = DRM_R128_WRITE_PIXELS;
+      d.n = n;
+      d.x = (int*)&x;
+      d.y = (int*)&y;
+      d.buffer = (unsigned int *)depth;
+      d.mask = (unsigned char *)mask;
+
+      drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
+   }
+   else
+   {
+      for (i = 0 ; i < nbox ; ) {
+        int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
+        XF86DRIClipRectPtr b = rmesa->sarea->boxes;
+
+        rmesa->sarea->nbox = nr - i;
+        for ( ; i < nr ; i++) {
+           *b++ = pbox[i];
+        }
+
+        rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
+
+         d.func = DRM_R128_WRITE_PIXELS;
+         d.n = n;
+         d.x = (int*)&x;
+         d.y = (int*)&y;
+         d.buffer = (unsigned int *)depth;
+         d.mask = (unsigned char *)mask;
+
+         drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
+      }
+   }
+
+   rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
+}
+
+void r128ReadDepthSpanLocked( r128ContextPtr rmesa,
+                             GLuint n, GLint x, GLint y )
+{
+   XF86DRIClipRectPtr pbox = rmesa->pClipRects;
+   drmR128Depth d;
+   int nbox = rmesa->numClipRects;
+   int fd = rmesa->driScreen->fd;
+   int i;
+
+   if ( !nbox || !n ) {
+      return;
+   }
+   if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
+      rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
+   }
+
+   if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
+   {
+      if ( nbox < 3 ) {
+        rmesa->sarea->nbox = 0;
+      } else {
+        rmesa->sarea->nbox = nbox;
+      }
+
+      d.func = DRM_R128_READ_SPAN;
+      d.n = n;
+      d.x = (int*)&x;
+      d.y = (int*)&y;
+      d.buffer = NULL;
+      d.mask = NULL;
+
+      drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
+   }
+   else
+   {
+      for (i = 0 ; i < nbox ; ) {
+        int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
+        XF86DRIClipRectPtr b = rmesa->sarea->boxes;
+
+        rmesa->sarea->nbox = nr - i;
+        for ( ; i < nr ; i++) {
+           *b++ = pbox[i];
+        }
+
+        rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
+
+         d.func = DRM_R128_READ_SPAN;
+         d.n = n;
+         d.x = (int*)&x;
+         d.y = (int*)&y;
+         d.buffer = NULL;
+         d.mask = NULL;
+
+         drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
+      }
+   }
+
+   rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
+}
+
+void r128ReadDepthPixelsLocked( r128ContextPtr rmesa, GLuint n,
+                               const GLint x[], const GLint y[] )
+{
+   XF86DRIClipRectPtr pbox = rmesa->pClipRects;
+   drmR128Depth d;
+   int nbox = rmesa->numClipRects;
+   int fd = rmesa->driScreen->fd;
+   int i;
+
+   if ( !nbox || !n ) {
+      return;
+   }
+   if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
+      rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
+   }
+
+   if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
+   {
+      if ( nbox < 3 ) {
+        rmesa->sarea->nbox = 0;
+      } else {
+        rmesa->sarea->nbox = nbox;
+      }
+
+      d.func = DRM_R128_READ_PIXELS;
+      d.n = n;
+      d.x = (int*)&x;
+      d.y = (int*)&y;
+      d.buffer = NULL;
+      d.mask = NULL;
+
+      drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
+   }
+   else
+   {
+      for (i = 0 ; i < nbox ; ) {
+        int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
+        XF86DRIClipRectPtr b = rmesa->sarea->boxes;
+
+        rmesa->sarea->nbox = nr - i;
+        for ( ; i < nr ; i++) {
+           *b++ = pbox[i];
+        }
+
+        rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
+
+         d.func = DRM_R128_READ_PIXELS;
+         d.n = n;
+         d.x = (int*)&x;
+         d.y = (int*)&y;
+         d.buffer = NULL;
+         d.mask = NULL;
+
+         drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
+      }
+   }
+
+   rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
+}
+
+
+void r128WaitForIdleLocked( r128ContextPtr rmesa )
+{
+    int fd = rmesa->r128Screen->driScreen->fd;
+    int to = 0;
+    int ret, i;
+
+    do {
+        i = 0;
+        do {
+            ret = drmCommandNone( fd, DRM_R128_CCE_IDLE);
+        } while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY );
+    } while ( ( ret == -EBUSY ) && ( to++ < R128_TIMEOUT ) );
+
+    if ( ret < 0 ) {
+        drmCommandNone( fd, DRM_R128_CCE_RESET);
+       UNLOCK_HARDWARE( rmesa );
+       fprintf( stderr, "Error: Rage 128 timed out... exiting\n" );
+       exit( -1 );
+    }
+}
+
+void r128DDInitIoctlFuncs( GLcontext *ctx )
+{
+    ctx->Driver.Clear = r128DDClear;
+}
diff --git a/src/mesa/drivers/dri/r128/r128_ioctl.h b/src/mesa/drivers/dri/r128/r128_ioctl.h
new file mode 100644 (file)
index 0000000..b0f6b36
--- /dev/null
@@ -0,0 +1,146 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_ioctl.h,v 1.6 2002/12/16 16:18:53 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+                                               Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#ifndef __R128_IOCTL_H__
+#define __R128_IOCTL_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include "r128_dri.h"
+#include "r128_reg.h"
+#include "r128_lock.h"
+
+#include "xf86drm.h"
+#include "r128_common.h"
+
+#define R128_BUFFER_MAX_DWORDS (R128_BUFFER_SIZE / sizeof(CARD32))
+
+
+extern drmBufPtr r128GetBufferLocked( r128ContextPtr rmesa );
+extern void r128FlushVerticesLocked( r128ContextPtr rmesa );
+
+static __inline void *r128AllocDmaLow( r128ContextPtr rmesa, int bytes )
+{
+   CARD32 *head;
+
+   if ( !rmesa->vert_buf ) {
+      LOCK_HARDWARE( rmesa );
+      rmesa->vert_buf = r128GetBufferLocked( rmesa );
+      UNLOCK_HARDWARE( rmesa );
+   } else if ( rmesa->vert_buf->used + bytes > rmesa->vert_buf->total ) {
+      LOCK_HARDWARE( rmesa );
+      r128FlushVerticesLocked( rmesa );
+      rmesa->vert_buf = r128GetBufferLocked( rmesa );
+      UNLOCK_HARDWARE( rmesa );
+   }
+
+   head = (CARD32 *)((char *)rmesa->vert_buf->address + rmesa->vert_buf->used);
+   rmesa->vert_buf->used += bytes;
+   return head;
+}
+
+extern void r128FireBlitLocked( r128ContextPtr rmesa, drmBufPtr buffer,
+                               GLint offset, GLint pitch, GLint format,
+                               GLint x, GLint y, GLint width, GLint height );
+
+extern void r128WriteDepthSpanLocked( r128ContextPtr rmesa,
+                                     GLuint n, GLint x, GLint y,
+                                     const GLdepth depth[],
+                                     const GLubyte mask[] );
+extern void r128WriteDepthPixelsLocked( r128ContextPtr rmesa, GLuint n,
+                                       const GLint x[], const GLint y[],
+                                       const GLdepth depth[],
+                                       const GLubyte mask[] );
+extern void r128ReadDepthSpanLocked( r128ContextPtr rmesa,
+                                    GLuint n, GLint x, GLint y );
+extern void r128ReadDepthPixelsLocked( r128ContextPtr rmesa, GLuint n,
+                                      const GLint x[], const GLint y[] );
+
+extern void r128CopyBuffer( const __DRIdrawablePrivate *dPriv );
+extern void r128PageFlip( const __DRIdrawablePrivate *dPriv );
+void r128WaitForVBlank( r128ContextPtr rmesa );
+
+extern void r128WaitForIdleLocked( r128ContextPtr rmesa );
+
+
+extern void r128DDInitIoctlFuncs( GLcontext *ctx );
+
+
+/* ================================================================
+ * Helper macros:
+ */
+
+#define FLUSH_BATCH( rmesa )                                           \
+do {                                                                   \
+   if ( R128_DEBUG & DEBUG_VERBOSE_IOCTL )                             \
+      fprintf( stderr, "FLUSH_BATCH in %s\n", __FUNCTION__ );          \
+   if ( rmesa->vert_buf ) {                                            \
+      r128FlushVertices( rmesa );                                      \
+   }                                                                   \
+} while (0)
+
+/* 64-bit align the next element address, and then make room for the
+ * next indexed prim packet header.
+ */
+#define ALIGN_NEXT_ELT( rmesa )                                                \
+do {                                                                   \
+   rmesa->next_elt = (GLushort *)                                      \
+      (((GLuint)rmesa->next_elt + 7) & ~0x7);                          \
+   rmesa->next_elt = (GLushort *)                                      \
+      ((GLubyte *)rmesa->next_elt + R128_INDEX_PRIM_OFFSET);           \
+} while (0)
+
+#define r128FlushVertices( rmesa )                                     \
+do {                                                                   \
+   LOCK_HARDWARE( rmesa );                                             \
+   r128FlushVerticesLocked( rmesa );                                   \
+   UNLOCK_HARDWARE( rmesa );                                           \
+} while (0)
+
+#define r128FlushElts( rmesa )                                         \
+do {                                                                   \
+   LOCK_HARDWARE( rmesa );                                             \
+   r128FlushEltsLocked( rmesa );                                       \
+   UNLOCK_HARDWARE( rmesa );                                           \
+} while (0)
+
+#define r128WaitForIdle( rmesa )                                       \
+   do {                                                                        \
+      LOCK_HARDWARE( rmesa );                                          \
+      r128WaitForIdleLocked( rmesa );                                  \
+      UNLOCK_HARDWARE( rmesa );                                                \
+   } while (0)
+
+#endif
+#endif /* __R128_IOCTL_H__ */
diff --git a/src/mesa/drivers/dri/r128/r128_lock.c b/src/mesa/drivers/dri/r128/r128_lock.c
new file mode 100644 (file)
index 0000000..12eb012
--- /dev/null
@@ -0,0 +1,123 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_lock.c,v 1.5 2002/10/30 12:51:38 alanh Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+                                               Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#include "r128_context.h"
+#include "r128_lock.h"
+#include "r128_tex.h"
+#include "r128_state.h"
+
+#if DEBUG_LOCKING
+char *prevLockFile = NULL;
+int prevLockLine = 0;
+#endif
+
+
+/* Turn on/off page flipping according to the flags in the sarea:
+ */
+static void
+r128UpdatePageFlipping( r128ContextPtr rmesa )
+{
+   int use_back;
+
+   rmesa->doPageFlip = rmesa->sarea->pfAllowPageFlip;
+
+   use_back = (rmesa->glCtx->Color._DrawDestMask == BACK_LEFT_BIT);
+   use_back ^= (rmesa->sarea->pfCurrentPage == 1);
+
+   if ( R128_DEBUG & DEBUG_VERBOSE_API )
+      fprintf(stderr, "%s allow %d current %d\n", __FUNCTION__, 
+             rmesa->doPageFlip,
+             rmesa->sarea->pfCurrentPage );
+
+   if ( use_back ) {
+        rmesa->drawOffset = rmesa->r128Screen->backOffset;
+        rmesa->drawPitch  = rmesa->r128Screen->backPitch;
+   } else {
+        rmesa->drawOffset = rmesa->r128Screen->frontOffset;
+        rmesa->drawPitch  = rmesa->r128Screen->frontPitch;
+   }
+
+   rmesa->setup.dst_pitch_offset_c = (((rmesa->drawPitch/8) << 21) |
+                                      (rmesa->drawOffset >> 5));
+   rmesa->new_state |= R128_NEW_WINDOW;
+}
+
+/* Update the hardware state.  This is called if another context has
+ * grabbed the hardware lock, which includes the X server.  This
+ * function also updates the driver's window state after the X server
+ * moves, resizes or restacks a window -- the change will be reflected
+ * in the drawable position and clip rects.  Since the X server grabs
+ * the hardware lock when it changes the window state, this routine will
+ * automatically be called after such a change.
+ */
+void r128GetLock( r128ContextPtr rmesa, GLuint flags )
+{
+   __DRIdrawablePrivate *dPriv = rmesa->driDrawable;
+   __DRIscreenPrivate *sPriv = rmesa->driScreen;
+   R128SAREAPrivPtr sarea = rmesa->sarea;
+   int i;
+
+   drmGetLock( rmesa->driFd, rmesa->hHWContext, flags );
+
+   /* The window might have moved, so we might need to get new clip
+    * rects.
+    *
+    * NOTE: This releases and regrabs the hw lock to allow the X server
+    * to respond to the DRI protocol request for new drawable info.
+    * Since the hardware state depends on having the latest drawable
+    * clip rects, all state checking must be done _after_ this call.
+    */
+   DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv );
+
+   if ( rmesa->lastStamp != dPriv->lastStamp ) {
+      r128UpdatePageFlipping( rmesa );
+      rmesa->lastStamp = dPriv->lastStamp;
+      rmesa->new_state |= R128_NEW_CLIP;
+      rmesa->SetupNewInputs = ~0;
+   }
+
+   rmesa->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_CLIPRECTS;
+
+   rmesa->numClipRects = dPriv->numClipRects;
+   rmesa->pClipRects = dPriv->pClipRects;
+
+   if ( sarea->ctxOwner != rmesa->hHWContext ) {
+      sarea->ctxOwner = rmesa->hHWContext;
+      rmesa->dirty = R128_UPLOAD_ALL;
+   }
+
+   for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
+      DRI_AGE_TEXTURES( rmesa->texture_heaps[i] );
+   }
+}
diff --git a/src/mesa/drivers/dri/r128/r128_lock.h b/src/mesa/drivers/dri/r128/r128_lock.h
new file mode 100644 (file)
index 0000000..e734ba2
--- /dev/null
@@ -0,0 +1,111 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_lock.h,v 1.4 2001/01/08 01:07:21 martin Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+                                               Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#ifndef __R128_LOCK_H__
+#define __R128_LOCK_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+extern void r128GetLock( r128ContextPtr rmesa, GLuint flags );
+
+/* Turn DEBUG_LOCKING on to find locking conflicts.
+ */
+#define DEBUG_LOCKING  0
+
+#if DEBUG_LOCKING
+extern char *prevLockFile;
+extern int prevLockLine;
+
+#define DEBUG_LOCK()                                                   \
+   do {                                                                        \
+      prevLockFile = (__FILE__);                                       \
+      prevLockLine = (__LINE__);                                       \
+   } while (0)
+
+#define DEBUG_RESET()                                                  \
+   do {                                                                        \
+      prevLockFile = 0;                                                        \
+      prevLockLine = 0;                                                        \
+   } while (0)
+
+#define DEBUG_CHECK_LOCK()                                             \
+   do {                                                                        \
+      if ( prevLockFile ) {                                            \
+        fprintf( stderr,                                               \
+                 "LOCK SET!\n\tPrevious %s:%d\n\tCurrent: %s:%d\n",    \
+                 prevLockFile, prevLockLine, __FILE__, __LINE__ );     \
+        exit( 1 );                                                     \
+      }                                                                        \
+   } while (0)
+
+#else
+
+#define DEBUG_LOCK()
+#define DEBUG_RESET()
+#define DEBUG_CHECK_LOCK()
+
+#endif
+
+/*
+ * !!! We may want to separate locks from locks with validation.  This
+ * could be used to improve performance for those things commands that
+ * do not do any drawing !!!
+ */
+
+/* Lock the hardware and validate our state.
+ */
+#define LOCK_HARDWARE( rmesa )                                         \
+   do {                                                                        \
+      char __ret = 0;                                                  \
+      DEBUG_CHECK_LOCK();                                              \
+      DRM_CAS( rmesa->driHwLock, rmesa->hHWContext,                    \
+              (DRM_LOCK_HELD | rmesa->hHWContext), __ret );            \
+      if ( __ret )                                                     \
+        r128GetLock( rmesa, 0 );                                       \
+      DEBUG_LOCK();                                                    \
+   } while (0)
+
+/* Unlock the hardware.
+ */
+#define UNLOCK_HARDWARE( rmesa )                                       \
+   do {                                                                        \
+      DRM_UNLOCK( rmesa->driFd,                                                \
+                 rmesa->driHwLock,                                     \
+                 rmesa->hHWContext );                                  \
+      DEBUG_RESET();                                                   \
+   } while (0)
+
+#endif
+#endif /* __R128_LOCK_H__ */
diff --git a/src/mesa/drivers/dri/r128/r128_screen.c b/src/mesa/drivers/dri/r128/r128_screen.c
new file mode 100644 (file)
index 0000000..8a8fc25
--- /dev/null
@@ -0,0 +1,357 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_screen.c,v 1.8 2002/12/16 16:18:53 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+                                               Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Gareth Hughes <gareth@valinux.com>
+ *   Kevin E. Martin <martin@valinux.com>
+ *
+ */
+
+#include "r128_dri.h"
+
+#include "r128_context.h"
+#include "r128_ioctl.h"
+#include "r128_tris.h"
+#include "r128_vb.h"
+
+#include "context.h"
+#include "imports.h"
+
+#include "utils.h"
+#include "vblank.h"
+
+#ifndef _SOLO
+#include "glxextensions.h"
+#endif
+
+#if 1
+/* Including xf86PciInfo.h introduces a bunch of errors...
+ */
+#define PCI_CHIP_RAGE128LE     0x4C45
+#define PCI_CHIP_RAGE128LF     0x4C46
+#define PCI_CHIP_RAGE128PD     0x5044
+#define PCI_CHIP_RAGE128PF     0x5046
+#define PCI_CHIP_RAGE128PR     0x5052
+#define PCI_CHIP_RAGE128RE     0x5245
+#define PCI_CHIP_RAGE128RF     0x5246
+#define PCI_CHIP_RAGE128RK     0x524B
+#define PCI_CHIP_RAGE128RL     0x524C
+#endif
+
+
+/* Create the device specific screen private data struct.
+ */
+static r128ScreenPtr
+r128CreateScreen( __DRIscreenPrivate *sPriv )
+{
+   r128ScreenPtr r128Screen;
+   R128DRIPtr r128DRIPriv = (R128DRIPtr)sPriv->pDevPriv;
+
+   if ( ! driCheckDriDdxDrmVersions( sPriv, "Rage128", 4, 0, 4, 0, 2, 2 ) )
+      return NULL;
+
+   /* Allocate the private area */
+   r128Screen = (r128ScreenPtr) CALLOC( sizeof(*r128Screen) );
+   if ( !r128Screen ) return NULL;
+
+   /* This is first since which regions we map depends on whether or
+    * not we are using a PCI card.
+    */
+   r128Screen->IsPCI = r128DRIPriv->IsPCI;
+   r128Screen->sarea_priv_offset = r128DRIPriv->sarea_priv_offset;
+   
+   if (sPriv->drmMinor >= 3) {
+      drmR128GetParam gp;
+      int ret;
+
+      gp.param = R128_PARAM_IRQ_NR;
+      gp.value = &r128Screen->irq;
+
+      ret = drmCommandWriteRead( sPriv->fd, DRM_R128_GETPARAM,
+                                   &gp, sizeof(gp));
+      if (ret) {
+         fprintf(stderr, "drmR128GetParam (R128_PARAM_IRQ_NR): %d\n", ret);
+         FREE( r128Screen );
+         return NULL;
+      }
+   }
+
+   r128Screen->mmio.handle = r128DRIPriv->registerHandle;
+   r128Screen->mmio.size   = r128DRIPriv->registerSize;
+   if ( drmMap( sPriv->fd,
+               r128Screen->mmio.handle,
+               r128Screen->mmio.size,
+               (drmAddressPtr)&r128Screen->mmio.map ) ) {
+      FREE( r128Screen );
+      return NULL;
+   }
+
+   r128Screen->buffers = drmMapBufs( sPriv->fd );
+   if ( !r128Screen->buffers ) {
+      drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
+      FREE( r128Screen );
+      return NULL;
+   }
+
+   if ( !r128Screen->IsPCI ) {
+      r128Screen->agpTextures.handle = r128DRIPriv->agpTexHandle;
+      r128Screen->agpTextures.size   = r128DRIPriv->agpTexMapSize;
+      if ( drmMap( sPriv->fd,
+                  r128Screen->agpTextures.handle,
+                  r128Screen->agpTextures.size,
+                  (drmAddressPtr)&r128Screen->agpTextures.map ) ) {
+        drmUnmapBufs( r128Screen->buffers );
+        drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
+        FREE( r128Screen );
+        return NULL;
+      }
+   }
+
+   switch ( r128DRIPriv->deviceID ) {
+   case PCI_CHIP_RAGE128RE:
+   case PCI_CHIP_RAGE128RF:
+   case PCI_CHIP_RAGE128RK:
+   case PCI_CHIP_RAGE128RL:
+      r128Screen->chipset = R128_CARD_TYPE_R128;
+      break;
+   case PCI_CHIP_RAGE128PD:
+   case PCI_CHIP_RAGE128PF:
+      r128Screen->chipset = R128_CARD_TYPE_R128_PRO;
+      break;
+   case PCI_CHIP_RAGE128LE:
+   case PCI_CHIP_RAGE128LF:
+      r128Screen->chipset = R128_CARD_TYPE_R128_MOBILITY;
+      break;
+   default:
+      r128Screen->chipset = R128_CARD_TYPE_R128;
+      break;
+   }
+
+   r128Screen->cpp = r128DRIPriv->bpp / 8;
+   r128Screen->AGPMode = r128DRIPriv->AGPMode;
+
+   r128Screen->frontOffset     = r128DRIPriv->frontOffset;
+   r128Screen->frontPitch      = r128DRIPriv->frontPitch;
+   r128Screen->backOffset      = r128DRIPriv->backOffset;
+   r128Screen->backPitch       = r128DRIPriv->backPitch;
+   r128Screen->depthOffset     = r128DRIPriv->depthOffset;
+   r128Screen->depthPitch      = r128DRIPriv->depthPitch;
+   r128Screen->spanOffset      = r128DRIPriv->spanOffset;
+
+   r128Screen->texOffset[R128_CARD_HEAP] = r128DRIPriv->textureOffset;
+   r128Screen->texSize[R128_CARD_HEAP] = r128DRIPriv->textureSize;
+   r128Screen->logTexGranularity[R128_CARD_HEAP] = r128DRIPriv->log2TexGran;
+
+   if ( r128Screen->IsPCI ) {
+      r128Screen->numTexHeaps = R128_NR_TEX_HEAPS - 1;
+      r128Screen->texOffset[R128_AGP_HEAP] = 0;
+      r128Screen->texSize[R128_AGP_HEAP] = 0;
+      r128Screen->logTexGranularity[R128_AGP_HEAP] = 0;
+   } else {
+      r128Screen->numTexHeaps = R128_NR_TEX_HEAPS;
+      r128Screen->texOffset[R128_AGP_HEAP] =
+        r128DRIPriv->agpTexOffset + R128_AGP_TEX_OFFSET;
+      r128Screen->texSize[R128_AGP_HEAP] = r128DRIPriv->agpTexMapSize;
+      r128Screen->logTexGranularity[R128_AGP_HEAP] =
+        r128DRIPriv->log2AGPTexGran;
+   }
+
+   r128Screen->driScreen = sPriv;
+
+   return r128Screen;
+}
+
+/* Destroy the device specific screen private data struct.
+ */
+static void
+r128DestroyScreen( __DRIscreenPrivate *sPriv )
+{
+   r128ScreenPtr r128Screen = (r128ScreenPtr)sPriv->private;
+
+   if ( !r128Screen )
+      return;
+
+   if ( !r128Screen->IsPCI ) {
+      drmUnmap( (drmAddress)r128Screen->agpTextures.map,
+               r128Screen->agpTextures.size );
+   }
+   drmUnmapBufs( r128Screen->buffers );
+   drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
+
+   FREE( r128Screen );
+   sPriv->private = NULL;
+}
+
+
+/* Initialize the fullscreen mode.
+ */
+static GLboolean
+r128OpenCloseFullScreen( __DRIcontextPrivate *driContextPriv )
+{
+   return GL_TRUE;
+}
+
+
+/* Create and initialize the Mesa and driver specific pixmap buffer
+ * data.
+ */
+static GLboolean
+r128CreateBuffer( __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
+r128DestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
+{
+   _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
+}
+
+
+/* Copy the back color buffer to the front color buffer */
+static void
+r128SwapBuffers(__DRIdrawablePrivate *dPriv)
+{
+   if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+      r128ContextPtr rmesa;
+      GLcontext *ctx;
+      rmesa = (r128ContextPtr) dPriv->driContextPriv->driverPrivate;
+      ctx = rmesa->glCtx;
+      if (ctx->Visual.doubleBufferMode) {
+         _mesa_notifySwapBuffers( ctx );  /* flush pending rendering comands */
+         if ( rmesa->doPageFlip ) {
+            r128PageFlip( dPriv );
+         }
+         else {
+            r128CopyBuffer( dPriv );
+         }
+      }
+   }
+   else {
+      /* XXX this shouldn't be an error but we can't handle it for now */
+      _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
+   }
+}
+
+
+/* Initialize the driver specific screen private data.
+ */
+static GLboolean
+r128InitDriver( __DRIscreenPrivate *sPriv )
+{
+   sPriv->private = (void *) r128CreateScreen( sPriv );
+
+   if ( !sPriv->private ) {
+      r128DestroyScreen( sPriv );
+      return GL_FALSE;
+   }
+
+   return GL_TRUE;
+}
+
+
+#ifndef _SOLO
+/* This function is called by libGL.so as soon as libGL.so is loaded.
+ * This is where we register new extension functions with the dispatcher.
+ */
+void __driRegisterExtensions( void )
+{
+   PFNGLXENABLEEXTENSIONPROC glx_enable_extension;
+
+   if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
+      glx_enable_extension = (PFNGLXENABLEEXTENSIONPROC)
+         glXGetProcAddress( "__glXEnableExtension" );
+
+      if ( glx_enable_extension != NULL ) {
+        glx_enable_extension( "GLX_SGI_swap_control", GL_FALSE );
+        glx_enable_extension( "GLX_SGI_video_sync", GL_FALSE );
+        glx_enable_extension( "GLX_MESA_swap_control", GL_FALSE );
+      }
+   }
+}
+#endif
+
+static struct __DriverAPIRec r128API = {
+   .InitDriver      = r128InitDriver,
+   .DestroyScreen   = r128DestroyScreen,
+   .CreateContext   = r128CreateContext,
+   .DestroyContext  = r128DestroyContext,
+   .CreateBuffer    = r128CreateBuffer,
+   .DestroyBuffer   = r128DestroyBuffer,
+   .SwapBuffers     = r128SwapBuffers,
+   .MakeCurrent     = r128MakeCurrent,
+   .UnbindContext   = r128UnbindContext,
+   .OpenFullScreen  = r128OpenCloseFullScreen,
+   .CloseFullScreen = r128OpenCloseFullScreen,
+   .GetSwapInfo     = NULL,
+   .GetMSC          = driGetMSC32,
+   .WaitForMSC      = driWaitForMSC32,
+   .WaitForSBC      = NULL,
+   .SwapBuffersMSC  = NULL
+
+};
+
+
+/*
+ * This is the bootstrap function for the driver.
+ * The __driCreateScreen name is the symbol that libGL.so fetches.
+ * Return:  pointer to a __DRIscreenPrivate.
+ */
+#ifndef _SOLO
+void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
+                        int numConfigs, __GLXvisualConfig *config)
+{
+   __DRIscreenPrivate *psp;
+   psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &r128API);
+   return (void *) psp;
+}
+#else
+void *__driCreateScreen(struct DRIDriverRec *driver,
+                        struct DRIDriverContextRec *driverContext)
+{
+   __DRIscreenPrivate *psp;
+   psp = __driUtilCreateScreen(driver, driverContext, &r128API);
+   return (void *) psp;
+}
+#endif
diff --git a/src/mesa/drivers/dri/r128/r128_screen.h b/src/mesa/drivers/dri/r128/r128_screen.h
new file mode 100644 (file)
index 0000000..4b1a572
--- /dev/null
@@ -0,0 +1,84 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_screen.h,v 1.7 2002/12/16 16:18:53 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+                                               Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Gareth Hughes <gareth@valinux.com>
+ *   Kevin E. Martin <martin@valinux.com>
+ *
+ */
+
+#ifndef __R128_SCREEN_H__
+#define __R128_SCREEN_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include "r128_sarea.h"
+
+typedef struct {
+   drmHandle handle;                   /* Handle to the DRM region */
+   drmSize size;                       /* Size of the DRM region */
+   unsigned char *map;                 /* Mapping of the DRM region */
+} r128RegionRec, *r128RegionPtr;
+
+typedef struct {
+
+   GLint chipset;
+   GLint cpp;
+   GLint IsPCI;                                /* Current card is a PCI card */
+   GLint AGPMode;
+   unsigned int irq;                   /* IRQ number (0 means none) */
+
+   GLuint frontOffset;
+   GLuint frontPitch;
+   GLuint backOffset;
+   GLuint backPitch;
+
+   GLuint depthOffset;
+   GLuint depthPitch;
+   GLuint spanOffset;
+
+    /* Shared texture data */
+   GLint numTexHeaps;
+   GLint texOffset[R128_NR_TEX_HEAPS];
+   GLint texSize[R128_NR_TEX_HEAPS];
+   GLint logTexGranularity[R128_NR_TEX_HEAPS];
+
+   r128RegionRec mmio;
+   r128RegionRec agpTextures;
+
+   drmBufMapPtr buffers;
+
+   __DRIscreenPrivate *driScreen;
+   unsigned int sarea_priv_offset;
+
+} r128ScreenRec, *r128ScreenPtr;
+
+
+#endif
+#endif /* __R128_SCREEN_H__ */
diff --git a/src/mesa/drivers/dri/r128/r128_span.c b/src/mesa/drivers/dri/r128/r128_span.c
new file mode 100644 (file)
index 0000000..c6f3195
--- /dev/null
@@ -0,0 +1,475 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_span.c,v 1.8 2002/10/30 12:51:39 alanh Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+                                               Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Gareth Hughes <gareth@valinux.com>
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ *   Kevin E. Martin <martin@valinux.com>
+ *
+ */
+
+#include "r128_context.h"
+#include "r128_ioctl.h"
+#include "r128_state.h"
+#include "r128_span.h"
+#include "r128_tex.h"
+
+#include "swrast/swrast.h"
+
+#define DBG 0
+
+#define HAVE_HW_DEPTH_SPANS    1
+#define HAVE_HW_DEPTH_PIXELS   1
+
+#define LOCAL_VARS                                                     \
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);                           \
+   r128ScreenPtr r128scrn = rmesa->r128Screen;                         \
+   __DRIscreenPrivate *sPriv = rmesa->driScreen;                       \
+   __DRIdrawablePrivate *dPriv = rmesa->driDrawable;                   \
+   GLuint pitch = r128scrn->frontPitch * r128scrn->cpp;                        \
+   GLuint height = dPriv->h;                                           \
+   char *buf = (char *)(sPriv->pFB +                                   \
+                       rmesa->drawOffset +                             \
+                       (dPriv->x * r128scrn->cpp) +                    \
+                       (dPriv->y * pitch));                            \
+   char *read_buf = (char *)(sPriv->pFB +                              \
+                            rmesa->readOffset +                        \
+                            (dPriv->x * r128scrn->cpp) +               \
+                            (dPriv->y * pitch));                       \
+   GLuint p;                                                           \
+   (void) read_buf; (void) buf; (void) p
+
+#define LOCAL_DEPTH_VARS                                               \
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);                           \
+   r128ScreenPtr r128scrn = rmesa->r128Screen;                         \
+   __DRIscreenPrivate *sPriv = rmesa->driScreen;                       \
+   __DRIdrawablePrivate *dPriv = rmesa->driDrawable;                   \
+   GLuint height = dPriv->h;                                           \
+   (void) r128scrn; (void) sPriv; (void) height
+
+#define LOCAL_STENCIL_VARS     LOCAL_DEPTH_VARS
+
+
+#define CLIPPIXEL( _x, _y )                                            \
+   ((_x >= minx) && (_x < maxx) && (_y >= miny) && (_y < maxy))
+
+
+#define CLIPSPAN( _x, _y, _n, _x1, _n1, _i )                           \
+   if ( _y < miny || _y >= maxy ) {                                    \
+      _n1 = 0, _x1 = x;                                                        \
+   } else {                                                            \
+      _n1 = _n;                                                                \
+      _x1 = _x;                                                                \
+      if ( _x1 < minx ) _i += (minx-_x1), n1 -= (minx-_x1), _x1 = minx; \
+      if ( _x1 + _n1 >= maxx ) n1 -= (_x1 + n1 - maxx);                        \
+   }
+
+#define Y_FLIP( _y )           (height - _y - 1)
+
+
+#define HW_LOCK()                                                      \
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);                           \
+   FLUSH_BATCH( rmesa );                                               \
+   LOCK_HARDWARE( rmesa );                                             \
+   r128WaitForIdleLocked( rmesa );
+
+#define HW_CLIPLOOP()                                                  \
+   do {                                                                        \
+      __DRIdrawablePrivate *dPriv = rmesa->driDrawable;                        \
+      int _nc = dPriv->numClipRects;                                   \
+                                                                       \
+      while ( _nc-- ) {                                                        \
+        int minx = dPriv->pClipRects[_nc].x1 - dPriv->x;               \
+        int miny = dPriv->pClipRects[_nc].y1 - dPriv->y;               \
+        int maxx = dPriv->pClipRects[_nc].x2 - dPriv->x;               \
+        int maxy = dPriv->pClipRects[_nc].y2 - dPriv->y;
+
+#define HW_ENDCLIPLOOP()                                               \
+      }                                                                        \
+   } while (0)
+
+#define HW_UNLOCK()                                                    \
+   UNLOCK_HARDWARE( rmesa )
+
+
+
+/* ================================================================
+ * Color buffer
+ */
+
+/* 16 bit, RGB565 color spanline and pixel functions
+ */
+#undef INIT_MONO_PIXEL
+#define INIT_MONO_PIXEL(p, color) \
+  p = R128PACKCOLOR565( color[0], color[1], color[2] )
+
+#define WRITE_RGBA( _x, _y, r, g, b, a )                               \
+   *(GLushort *)(buf + _x*2 + _y*pitch) = ((((int)r & 0xf8) << 8) |    \
+                                          (((int)g & 0xfc) << 3) |     \
+                                          (((int)b & 0xf8) >> 3))
+
+#define WRITE_PIXEL( _x, _y, p )                                       \
+   *(GLushort *)(buf + _x*2 + _y*pitch) = p
+
+#define READ_RGBA( rgba, _x, _y )                                      \
+   do {                                                                        \
+      GLushort p = *(GLushort *)(read_buf + _x*2 + _y*pitch);          \
+      rgba[0] = (p >> 8) & 0xf8;                                       \
+      rgba[1] = (p >> 3) & 0xfc;                                       \
+      rgba[2] = (p << 3) & 0xf8;                                       \
+      rgba[3] = 0xff;                                                  \
+      if ( rgba[0] & 0x08 ) rgba[0] |= 0x07;                           \
+      if ( rgba[1] & 0x04 ) rgba[1] |= 0x03;                           \
+      if ( rgba[2] & 0x08 ) rgba[2] |= 0x07;                           \
+   } while (0)
+
+#define TAG(x) r128##x##_RGB565
+#include "spantmp.h"
+
+#define READ_DEPTH(d, _x, _y)                                                 \
+    d = *(GLushort *)(buf + _x*2 + _y*pitch)
+
+/* 32 bit, ARGB8888 color spanline and pixel functions
+ */
+#undef INIT_MONO_PIXEL
+#define INIT_MONO_PIXEL(p, color) \
+  p = R128PACKCOLOR8888( color[0], color[1], color[2], color[3] )
+
+#define WRITE_RGBA( _x, _y, r, g, b, a )                               \
+   *(GLuint *)(buf + _x*4 + _y*pitch) = ((b <<  0) |                   \
+                                        (g <<  8) |                    \
+                                        (r << 16) |                    \
+                                        (a << 24) )
+
+#define WRITE_PIXEL( _x, _y, p )                                       \
+   *(GLuint *)(buf + _x*4 + _y*pitch) = p
+
+#define READ_RGBA( rgba, _x, _y )                                      \
+do {                                                                   \
+   GLuint p = *(GLuint *)(read_buf + _x*4 + _y*pitch);                 \
+   rgba[0] = (p >> 16) & 0xff;                                         \
+   rgba[1] = (p >>  8) & 0xff;                                         \
+   rgba[2] = (p >>  0) & 0xff;                                         \
+   rgba[3] = 0xff;/*(p >> 24) & 0xff;*/                                                \
+} while (0)
+
+#define TAG(x) r128##x##_ARGB8888
+#include "spantmp.h"
+
+
+/* 24 bit, RGB888 color spanline and pixel functions */
+#undef INIT_MONO_PIXEL
+#define INIT_MONO_PIXEL(p, color) \
+  p = R128PACKCOLOR888( color[0], color[1], color[2] )
+
+#define WRITE_RGBA(_x, _y, r, g, b, a)                                        \
+    *(GLuint *)(buf + _x*3 + _y*pitch) = ((r << 16) |                         \
+                                         (g << 8)  |                         \
+                                         (b << 0))
+
+#define WRITE_PIXEL(_x, _y, p)                                                \
+    *(GLuint *)(buf + _x*3 + _y*pitch) = p
+
+#define READ_RGBA(rgba, _x, _y)                                               \
+    do {                                                                      \
+       GLuint p = *(GLuint *)(read_buf + _x*3 + _y*pitch);                   \
+       rgba[0] = (p >> 16) & 0xff;                                           \
+       rgba[1] = (p >> 8)  & 0xff;                                           \
+       rgba[2] = (p >> 0)  & 0xff;                                           \
+       rgba[3] = 0xff;                                                       \
+    } while (0)
+
+/* ================================================================
+ * Depth buffer
+ */
+
+/* 16-bit depth buffer functions
+ */
+#define WRITE_DEPTH_SPAN()                                             \
+   r128WriteDepthSpanLocked( rmesa, n,                                 \
+                            x + dPriv->x,                              \
+                            y + dPriv->y,                              \
+                            depth, mask );
+
+#define WRITE_DEPTH_PIXELS()                                           \
+do {                                                                   \
+   GLint ox[MAX_WIDTH];                                                        \
+   GLint oy[MAX_WIDTH];                                                        \
+   for ( i = 0 ; i < n ; i++ ) {                                       \
+      ox[i] = x[i] + dPriv->x;                                         \
+   }                                                                   \
+   for ( i = 0 ; i < n ; i++ ) {                                       \
+      oy[i] = Y_FLIP( y[i] ) + dPriv->y;                               \
+   }                                                                   \
+   r128WriteDepthPixelsLocked( rmesa, n, ox, oy, depth, mask );                \
+} while (0)
+
+#define READ_DEPTH_SPAN()                                              \
+do {                                                                   \
+   GLushort *buf = (GLushort *)((GLubyte *)sPriv->pFB +                        \
+                               r128scrn->spanOffset);                  \
+   GLint i;                                                            \
+                                                                       \
+   r128ReadDepthSpanLocked( rmesa, n,                                  \
+                           x + dPriv->x,                               \
+                           y + dPriv->y );                             \
+   r128WaitForIdleLocked( rmesa );                                     \
+                                                                       \
+   for ( i = 0 ; i < n ; i++ ) {                                       \
+      depth[i] = buf[i];                                               \
+   }                                                                   \
+} while (0)
+
+#define READ_DEPTH_PIXELS()                                            \
+do {                                                                   \
+   GLushort *buf = (GLushort *)((GLubyte *)sPriv->pFB +                        \
+                               r128scrn->spanOffset);                  \
+   GLint i, remaining = n;                                             \
+                                                                       \
+   while ( remaining > 0 ) {                                           \
+      GLint ox[MAX_WIDTH];                                             \
+      GLint oy[MAX_WIDTH];                                             \
+      GLint count;                                                     \
+                                                                       \
+      if ( remaining <= 128 ) {                                                \
+        count = remaining;                                             \
+      } else {                                                         \
+        count = 128;                                                   \
+      }                                                                        \
+      for ( i = 0 ; i < count ; i++ ) {                                        \
+        ox[i] = x[i] + dPriv->x;                                       \
+      }                                                                        \
+      for ( i = 0 ; i < count ; i++ ) {                                        \
+        oy[i] = Y_FLIP( y[i] ) + dPriv->y;                             \
+      }                                                                        \
+                                                                       \
+      r128ReadDepthPixelsLocked( rmesa, count, ox, oy );               \
+      r128WaitForIdleLocked( rmesa );                                  \
+                                                                       \
+      for ( i = 0 ; i < count ; i++ ) {                                        \
+        depth[i] = buf[i];                                             \
+      }                                                                        \
+      depth += count;                                                  \
+      x += count;                                                      \
+      y += count;                                                      \
+      remaining -= count;                                              \
+   }                                                                   \
+} while (0)
+
+#define TAG(x) r128##x##_16
+#include "depthtmp.h"
+
+
+/* 24-bit depth, 8-bit stencil buffer functions
+ */
+#define WRITE_DEPTH_SPAN()                                             \
+   r128WriteDepthSpanLocked( rmesa, n,                                 \
+                            x + dPriv->x,                              \
+                            y + dPriv->y,                              \
+                            depth, mask );
+
+#define WRITE_DEPTH_PIXELS()                                           \
+do {                                                                   \
+   GLint ox[MAX_WIDTH];                                                        \
+   GLint oy[MAX_WIDTH];                                                        \
+   for ( i = 0 ; i < n ; i++ ) {                                       \
+      ox[i] = x[i] + dPriv->x;                                         \
+   }                                                                   \
+   for ( i = 0 ; i < n ; i++ ) {                                       \
+      oy[i] = Y_FLIP( y[i] ) + dPriv->y;                               \
+   }                                                                   \
+   r128WriteDepthPixelsLocked( rmesa, n, ox, oy, depth, mask );                \
+} while (0)
+
+#define READ_DEPTH_SPAN()                                              \
+do {                                                                   \
+   GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB +                    \
+                           r128scrn->spanOffset);                      \
+   GLint i;                                                            \
+                                                                       \
+   r128ReadDepthSpanLocked( rmesa, n,                                  \
+                           x + dPriv->x,                               \
+                           y + dPriv->y );                             \
+   r128WaitForIdleLocked( rmesa );                                     \
+                                                                       \
+   for ( i = 0 ; i < n ; i++ ) {                                       \
+      depth[i] = buf[i] & 0x00ffffff;                                  \
+   }                                                                   \
+} while (0)
+
+#define READ_DEPTH_PIXELS()                                            \
+do {                                                                   \
+   GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB +                    \
+                           r128scrn->spanOffset);                      \
+   GLint i, remaining = n;                                             \
+                                                                       \
+   while ( remaining > 0 ) {                                           \
+      GLint ox[MAX_WIDTH];                                             \
+      GLint oy[MAX_WIDTH];                                             \
+      GLint count;                                                     \
+                                                                       \
+      if ( remaining <= 128 ) {                                                \
+        count = remaining;                                             \
+      } else {                                                         \
+        count = 128;                                                   \
+      }                                                                        \
+      for ( i = 0 ; i < count ; i++ ) {                                        \
+        ox[i] = x[i] + dPriv->x;                                       \
+      }                                                                        \
+      for ( i = 0 ; i < count ; i++ ) {                                        \
+        oy[i] = Y_FLIP( y[i] ) + dPriv->y;                             \
+      }                                                                        \
+                                                                       \
+      r128ReadDepthPixelsLocked( rmesa, count, ox, oy );               \
+      r128WaitForIdleLocked( rmesa );                                  \
+                                                                       \
+      for ( i = 0 ; i < count ; i++ ) {                                        \
+        depth[i] = buf[i] & 0x00ffffff;                                \
+      }                                                                        \
+      depth += count;                                                  \
+      x += count;                                                      \
+      y += count;                                                      \
+      remaining -= count;                                              \
+   }                                                                   \
+} while (0)
+
+#define TAG(x) r128##x##_24_8
+#include "depthtmp.h"
+
+
+
+/* ================================================================
+ * Stencil buffer
+ */
+
+/* FIXME: Add support for hardware stencil buffers.
+ */
+
+
+/* 32 bit depthbuffer functions */
+#define WRITE_DEPTH(_x, _y, d)                                                \
+    *(GLuint *)(buf + _x*4 + _y*pitch) = d
+
+
+
+/*
+ * This function is called to specify which buffer to read and write
+ * for software rasterization (swrast) fallbacks.  This doesn't necessarily
+ * correspond to glDrawBuffer() or glReadBuffer() calls.
+ */
+static void r128DDSetBuffer( GLcontext *ctx,
+                             GLframebuffer *colorBuffer,
+                             GLuint bufferBit )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   switch ( bufferBit ) {
+   case FRONT_LEFT_BIT:
+      if ( rmesa->sarea->pfCurrentPage == 1 ) {
+         rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->backOffset;
+         rmesa->drawPitch  = rmesa->readPitch  = rmesa->r128Screen->backPitch;
+      } else {
+         rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->frontOffset;
+         rmesa->drawPitch  = rmesa->readPitch  = rmesa->r128Screen->frontPitch;
+      }
+      break;
+   case BACK_LEFT_BIT:
+      if ( rmesa->sarea->pfCurrentPage == 1 ) {
+         rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->frontOffset;
+         rmesa->drawPitch  = rmesa->readPitch  = rmesa->r128Screen->frontPitch;
+      } else {
+         rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->backOffset;
+         rmesa->drawPitch  = rmesa->readPitch  = rmesa->r128Screen->backPitch;
+      }
+      break;
+   default:
+      break;
+   }
+}
+
+
+void r128DDInitSpanFuncs( GLcontext *ctx )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
+
+   swdd->SetBuffer = r128DDSetBuffer;
+
+   switch ( rmesa->r128Screen->cpp ) {
+   case 2:
+      swdd->WriteRGBASpan      = r128WriteRGBASpan_RGB565;
+      swdd->WriteRGBSpan       = r128WriteRGBSpan_RGB565;
+      swdd->WriteMonoRGBASpan  = r128WriteMonoRGBASpan_RGB565;
+      swdd->WriteRGBAPixels    = r128WriteRGBAPixels_RGB565;
+      swdd->WriteMonoRGBAPixels        = r128WriteMonoRGBAPixels_RGB565;
+      swdd->ReadRGBASpan       = r128ReadRGBASpan_RGB565;
+      swdd->ReadRGBAPixels     = r128ReadRGBAPixels_RGB565;
+      break;
+
+   case 4:
+      swdd->WriteRGBASpan      = r128WriteRGBASpan_ARGB8888;
+      swdd->WriteRGBSpan       = r128WriteRGBSpan_ARGB8888;
+      swdd->WriteMonoRGBASpan  = r128WriteMonoRGBASpan_ARGB8888;
+      swdd->WriteRGBAPixels    = r128WriteRGBAPixels_ARGB8888;
+      swdd->WriteMonoRGBAPixels        = r128WriteMonoRGBAPixels_ARGB8888;
+      swdd->ReadRGBASpan       = r128ReadRGBASpan_ARGB8888;
+      swdd->ReadRGBAPixels     = r128ReadRGBAPixels_ARGB8888;
+      break;
+
+   default:
+      break;
+   }
+
+   switch ( rmesa->glCtx->Visual.depthBits ) {
+   case 16:
+      swdd->ReadDepthSpan      = r128ReadDepthSpan_16;
+      swdd->WriteDepthSpan     = r128WriteDepthSpan_16;
+      swdd->ReadDepthPixels    = r128ReadDepthPixels_16;
+      swdd->WriteDepthPixels   = r128WriteDepthPixels_16;
+      break;
+
+   case 24:
+      swdd->ReadDepthSpan      = r128ReadDepthSpan_24_8;
+      swdd->WriteDepthSpan     = r128WriteDepthSpan_24_8;
+      swdd->ReadDepthPixels    = r128ReadDepthPixels_24_8;
+      swdd->WriteDepthPixels   = r128WriteDepthPixels_24_8;
+      break;
+
+   default:
+      break;
+   }
+
+   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/r128/r128_span.h b/src/mesa/drivers/dri/r128/r128_span.h
new file mode 100644 (file)
index 0000000..44356c5
--- /dev/null
@@ -0,0 +1,44 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_span.h,v 1.3 2001/01/08 01:07:21 martin Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+                                               Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Gareth Hughes <gareth@valinux.com>
+ *   Kevin E. Martin <martin@valinux.com>
+ *
+ */
+
+#ifndef __R128_SPAN_H__
+#define __R128_SPAN_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+extern void r128DDInitSpanFuncs( GLcontext *ctx );
+
+#endif
+#endif
diff --git a/src/mesa/drivers/dri/r128/r128_state.c b/src/mesa/drivers/dri/r128/r128_state.c
new file mode 100644 (file)
index 0000000..85b3b68
--- /dev/null
@@ -0,0 +1,1239 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_state.c,v 1.11 2002/10/30 12:51:39 alanh Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+                                               Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Gareth Hughes <gareth@valinux.com>
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#include "r128_context.h"
+#include "r128_state.h"
+#include "r128_ioctl.h"
+#include "r128_tris.h"
+#include "r128_vb.h"
+#include "r128_tex.h"
+
+#include "context.h"
+#include "enums.h"
+#include "colormac.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"
+
+
+/* =============================================================
+ * Alpha blending
+ */
+
+static void r128UpdateAlphaMode( GLcontext *ctx )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   GLuint a = rmesa->setup.misc_3d_state_cntl_reg;
+   GLuint t = rmesa->setup.tex_cntl_c;
+
+   if ( ctx->Color.AlphaEnabled ) {
+      GLubyte ref;
+
+      CLAMPED_FLOAT_TO_UBYTE(ref, ctx->Color.AlphaRef);
+
+      a &= ~(R128_ALPHA_TEST_MASK | R128_REF_ALPHA_MASK);
+
+      switch ( ctx->Color.AlphaFunc ) {
+      case GL_NEVER:
+        a |= R128_ALPHA_TEST_NEVER;
+        break;
+      case GL_LESS:
+        a |= R128_ALPHA_TEST_LESS;
+         break;
+      case GL_LEQUAL:
+        a |= R128_ALPHA_TEST_LESSEQUAL;
+        break;
+      case GL_EQUAL:
+        a |= R128_ALPHA_TEST_EQUAL;
+        break;
+      case GL_GEQUAL:
+        a |= R128_ALPHA_TEST_GREATEREQUAL;
+        break;
+      case GL_GREATER:
+        a |= R128_ALPHA_TEST_GREATER;
+        break;
+      case GL_NOTEQUAL:
+        a |= R128_ALPHA_TEST_NEQUAL;
+        break;
+      case GL_ALWAYS:
+        a |= R128_ALPHA_TEST_ALWAYS;
+        break;
+      }
+
+      a |= ref & R128_REF_ALPHA_MASK;
+      t |= R128_ALPHA_TEST_ENABLE;
+   } else {
+      t &= ~R128_ALPHA_TEST_ENABLE;
+   }
+
+   FALLBACK( rmesa, R128_FALLBACK_BLEND_FUNC, GL_FALSE );
+
+   if ( ctx->Color.BlendEnabled ) {
+      a &= ~(R128_ALPHA_BLEND_SRC_MASK | R128_ALPHA_BLEND_DST_MASK);
+
+      switch ( ctx->Color.BlendSrcRGB ) {
+      case GL_ZERO:
+        a |= R128_ALPHA_BLEND_SRC_ZERO;
+        break;
+      case GL_ONE:
+        a |= R128_ALPHA_BLEND_SRC_ONE;
+        break;
+      case GL_DST_COLOR:
+        a |= R128_ALPHA_BLEND_SRC_DESTCOLOR;
+        break;
+      case GL_ONE_MINUS_DST_COLOR:
+        a |= R128_ALPHA_BLEND_SRC_INVDESTCOLOR;
+        break;
+      case GL_SRC_ALPHA:
+        a |= R128_ALPHA_BLEND_SRC_SRCALPHA;
+        break;
+      case GL_ONE_MINUS_SRC_ALPHA:
+        a |= R128_ALPHA_BLEND_SRC_INVSRCALPHA;
+        break;
+      case GL_DST_ALPHA:
+        a |= R128_ALPHA_BLEND_SRC_DESTALPHA;
+        break;
+      case GL_ONE_MINUS_DST_ALPHA:
+        a |= R128_ALPHA_BLEND_SRC_INVDESTALPHA;
+        break;
+      case GL_SRC_ALPHA_SATURATE:
+        a |= R128_ALPHA_BLEND_SRC_SRCALPHASAT;
+        break;
+      default:
+         FALLBACK( rmesa, R128_FALLBACK_BLEND_FUNC, GL_TRUE );
+      }
+
+      switch ( ctx->Color.BlendDstRGB ) {
+      case GL_ZERO:
+        a |= R128_ALPHA_BLEND_DST_ZERO;
+        break;
+      case GL_ONE:
+        a |= R128_ALPHA_BLEND_DST_ONE;
+        break;
+      case GL_SRC_COLOR:
+        a |= R128_ALPHA_BLEND_DST_SRCCOLOR;
+        break;
+      case GL_ONE_MINUS_SRC_COLOR:
+        a |= R128_ALPHA_BLEND_DST_INVSRCCOLOR;
+        break;
+      case GL_SRC_ALPHA:
+        a |= R128_ALPHA_BLEND_DST_SRCALPHA;
+        break;
+      case GL_ONE_MINUS_SRC_ALPHA:
+        a |= R128_ALPHA_BLEND_DST_INVSRCALPHA;
+        break;
+      case GL_DST_ALPHA:
+        a |= R128_ALPHA_BLEND_DST_DESTALPHA;
+        break;
+      case GL_ONE_MINUS_DST_ALPHA:
+        a |= R128_ALPHA_BLEND_DST_INVDESTALPHA;
+        break;
+      default:
+         FALLBACK( rmesa, R128_FALLBACK_BLEND_FUNC, GL_TRUE );
+      }
+
+      t |=  R128_ALPHA_ENABLE;
+   } else {
+      t &= ~R128_ALPHA_ENABLE;
+   }
+
+   if ( rmesa->setup.misc_3d_state_cntl_reg != a ) {
+      rmesa->setup.misc_3d_state_cntl_reg = a;
+      rmesa->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
+   }
+   if ( rmesa->setup.tex_cntl_c != t ) {
+      rmesa->setup.tex_cntl_c = t;
+      rmesa->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
+   }
+}
+
+static void r128DDAlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   FLUSH_BATCH( rmesa );
+   rmesa->new_state |= R128_NEW_ALPHA;
+}
+
+static void r128DDBlendEquation( GLcontext *ctx, GLenum mode )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   FLUSH_BATCH( rmesa );
+
+   /* BlendEquation sets ColorLogicOpEnabled in an unexpected
+    * manner.
+    */
+   FALLBACK( R128_CONTEXT(ctx), R128_FALLBACK_LOGICOP,
+            (ctx->Color.ColorLogicOpEnabled &&
+             ctx->Color.LogicOp != GL_COPY));
+
+   /* Can only do blend addition, not min, max, subtract, etc. */
+   FALLBACK( R128_CONTEXT(ctx), R128_FALLBACK_BLEND_EQ,
+            mode != GL_FUNC_ADD_EXT);
+
+   rmesa->new_state |= R128_NEW_ALPHA;
+}
+
+static void r128DDBlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   FLUSH_BATCH( rmesa );
+   rmesa->new_state |= R128_NEW_ALPHA;
+}
+
+static void r128DDBlendFuncSeparate( GLcontext *ctx,
+                                    GLenum sfactorRGB, GLenum dfactorRGB,
+                                    GLenum sfactorA, GLenum dfactorA )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   FLUSH_BATCH( rmesa );
+   rmesa->new_state |= R128_NEW_ALPHA;
+}
+
+
+/* =============================================================
+ * Depth testing
+ */
+
+static void r128UpdateZMode( GLcontext *ctx )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   GLuint z = rmesa->setup.z_sten_cntl_c;
+   GLuint t = rmesa->setup.tex_cntl_c;
+
+   if ( ctx->Depth.Test ) {
+      z &= ~R128_Z_TEST_MASK;
+
+      switch ( ctx->Depth.Func ) {
+      case GL_NEVER:
+        z |= R128_Z_TEST_NEVER;
+        break;
+      case GL_ALWAYS:
+        z |= R128_Z_TEST_ALWAYS;
+        break;
+      case GL_LESS:
+        z |= R128_Z_TEST_LESS;
+        break;
+      case GL_LEQUAL:
+        z |= R128_Z_TEST_LESSEQUAL;
+        break;
+      case GL_EQUAL:
+        z |= R128_Z_TEST_EQUAL;
+        break;
+      case GL_GEQUAL:
+        z |= R128_Z_TEST_GREATEREQUAL;
+        break;
+      case GL_GREATER:
+        z |= R128_Z_TEST_GREATER;
+        break;
+      case GL_NOTEQUAL:
+        z |= R128_Z_TEST_NEQUAL;
+        break;
+      }
+
+      t |=  R128_Z_ENABLE;
+   } else {
+      t &= ~R128_Z_ENABLE;
+   }
+
+   if ( ctx->Depth.Mask ) {
+      t |=  R128_Z_WRITE_ENABLE;
+   } else {
+      t &= ~R128_Z_WRITE_ENABLE;
+   }
+
+   if ( rmesa->setup.z_sten_cntl_c != z ) {
+      rmesa->setup.z_sten_cntl_c = z;
+      rmesa->dirty |= R128_UPLOAD_CONTEXT;
+   }
+   if ( rmesa->setup.tex_cntl_c != t ) {
+      rmesa->setup.tex_cntl_c = t;
+      rmesa->dirty |= R128_UPLOAD_CONTEXT;
+   }
+}
+
+static void r128DDDepthFunc( GLcontext *ctx, GLenum func )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   FLUSH_BATCH( rmesa );
+   rmesa->new_state |= R128_NEW_DEPTH;
+}
+
+static void r128DDDepthMask( GLcontext *ctx, GLboolean flag )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   FLUSH_BATCH( rmesa );
+   rmesa->new_state |= R128_NEW_DEPTH;
+}
+
+static void r128DDClearDepth( GLcontext *ctx, GLclampd d )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   switch ( rmesa->setup.z_sten_cntl_c &  R128_Z_PIX_WIDTH_MASK ) {
+   case R128_Z_PIX_WIDTH_16:
+      rmesa->ClearDepth = d * 0x0000ffff;
+      break;
+   case R128_Z_PIX_WIDTH_24:
+      rmesa->ClearDepth = d * 0x00ffffff;
+      break;
+   case R128_Z_PIX_WIDTH_32:
+      rmesa->ClearDepth = d * 0xffffffff;
+      break;
+   }
+}
+
+
+/* =============================================================
+ * Fog
+ */
+
+static void r128UpdateFogAttrib( GLcontext *ctx )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   GLuint t = rmesa->setup.tex_cntl_c;
+   GLubyte c[4];
+   GLuint col;
+
+   if ( ctx->Fog.Enabled ) {
+      t |=  R128_FOG_ENABLE;
+   } else {
+      t &= ~R128_FOG_ENABLE;
+   }
+
+   c[0] = FLOAT_TO_UBYTE( ctx->Fog.Color[0] );
+   c[1] = FLOAT_TO_UBYTE( ctx->Fog.Color[1] );
+   c[2] = FLOAT_TO_UBYTE( ctx->Fog.Color[2] );
+
+   col = r128PackColor( 4, c[0], c[1], c[2], 0 );
+
+   if ( rmesa->setup.fog_color_c != col ) {
+      rmesa->setup.fog_color_c = col;
+      rmesa->dirty |= R128_UPLOAD_CONTEXT;
+   }
+   if ( rmesa->setup.tex_cntl_c != t ) {
+      rmesa->setup.tex_cntl_c = t;
+      rmesa->dirty |= R128_UPLOAD_CONTEXT;
+   }
+}
+
+static void r128DDFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   FLUSH_BATCH( rmesa );
+   rmesa->new_state |= R128_NEW_FOG;
+}
+
+
+/* =============================================================
+ * Clipping
+ */
+
+static void r128UpdateClipping( GLcontext *ctx )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   if ( rmesa->driDrawable ) {
+      __DRIdrawablePrivate *drawable = rmesa->driDrawable;
+      int x1 = 0;
+      int y1 = 0;
+      int x2 = drawable->w - 1;
+      int y2 = drawable->h - 1;
+
+      if ( ctx->Scissor.Enabled ) {
+        if ( ctx->Scissor.X > x1 ) {
+           x1 = ctx->Scissor.X;
+        }
+        if ( drawable->h - ctx->Scissor.Y - ctx->Scissor.Height > y1 ) {
+           y1 = drawable->h - ctx->Scissor.Y - ctx->Scissor.Height;
+        }
+        if ( ctx->Scissor.X + ctx->Scissor.Width - 1 < x2 ) {
+           x2 = ctx->Scissor.X + ctx->Scissor.Width - 1;
+        }
+        if ( drawable->h - ctx->Scissor.Y - 1 < y2 ) {
+           y2 = drawable->h - ctx->Scissor.Y - 1;
+        }
+      }
+
+      x1 += drawable->x;
+      y1 += drawable->y;
+      x2 += drawable->x;
+      y2 += drawable->y;
+
+      rmesa->setup.sc_top_left_c     = ((y1 << 16) | x1);
+      rmesa->setup.sc_bottom_right_c = ((y2 << 16) | x2);
+
+      rmesa->dirty |= R128_UPLOAD_CONTEXT;
+   }
+}
+
+static void r128DDScissor( GLcontext *ctx,
+                          GLint x, GLint y, GLsizei w, GLsizei h )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   FLUSH_BATCH( rmesa );
+   rmesa->new_state |= R128_NEW_CLIP;
+}
+
+
+/* =============================================================
+ * Culling
+ */
+
+static void r128UpdateCull( GLcontext *ctx )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   GLuint f = rmesa->setup.pm4_vc_fpu_setup;
+
+   f &= ~R128_FRONT_DIR_MASK;
+
+   switch ( ctx->Polygon.FrontFace ) {
+   case GL_CW:
+      f |= R128_FRONT_DIR_CW;
+      break;
+   case GL_CCW:
+      f |= R128_FRONT_DIR_CCW;
+      break;
+   }
+
+   f |= R128_BACKFACE_SOLID | R128_FRONTFACE_SOLID;
+
+   if ( ctx->Polygon.CullFlag ) {
+      switch ( ctx->Polygon.CullFaceMode ) {
+      case GL_FRONT:
+        f &= ~R128_FRONTFACE_SOLID;
+        break;
+      case GL_BACK:
+        f &= ~R128_BACKFACE_SOLID;
+        break;
+      case GL_FRONT_AND_BACK:
+        f &= ~(R128_BACKFACE_SOLID |
+               R128_FRONTFACE_SOLID);
+        break;
+      }
+   }
+
+   if ( 1 || rmesa->setup.pm4_vc_fpu_setup != f ) {
+      rmesa->setup.pm4_vc_fpu_setup = f;
+      rmesa->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_SETUP;
+   }
+}
+
+static void r128DDCullFace( GLcontext *ctx, GLenum mode )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   FLUSH_BATCH( rmesa );
+   rmesa->new_state |= R128_NEW_CULL;
+}
+
+static void r128DDFrontFace( GLcontext *ctx, GLenum mode )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   FLUSH_BATCH( rmesa );
+   rmesa->new_state |= R128_NEW_CULL;
+}
+
+
+/* =============================================================
+ * Masks
+ */
+
+static void r128UpdateMasks( GLcontext *ctx )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   GLuint mask = r128PackColor( rmesa->r128Screen->cpp,
+                               ctx->Color.ColorMask[RCOMP],
+                               ctx->Color.ColorMask[GCOMP],
+                               ctx->Color.ColorMask[BCOMP],
+                               ctx->Color.ColorMask[ACOMP] );
+
+   if ( rmesa->setup.plane_3d_mask_c != mask ) {
+      rmesa->setup.plane_3d_mask_c = mask;
+      rmesa->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
+   }
+}
+
+static void r128DDColorMask( GLcontext *ctx,
+                            GLboolean r, GLboolean g,
+                            GLboolean b, GLboolean a )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   FLUSH_BATCH( rmesa );
+   rmesa->new_state |= R128_NEW_MASKS;
+}
+
+
+/* =============================================================
+ * Rendering attributes
+ *
+ * We really don't want to recalculate all this every time we bind a
+ * texture.  These things shouldn't change all that often, so it makes
+ * sense to break them out of the core texture state update routines.
+ */
+
+static void updateSpecularLighting( GLcontext *ctx )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   GLuint t = rmesa->setup.tex_cntl_c;
+
+   if ( ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR &&
+        ctx->Light.Enabled) {
+      /* XXX separate specular color just doesn't seem to work as it should.
+       * For now, we fall back to s/w rendering whenever separate specular
+       * is enabled.
+       */
+#if 0
+      if (ctx->Light.ShadeModel == GL_FLAT) {
+         /* R128 can't do flat-shaded separate specular */
+         t &= ~R128_SPEC_LIGHT_ENABLE;
+         FALLBACK( rmesa, R128_FALLBACK_SEP_SPECULAR, GL_TRUE );
+         /*printf("%s fallback  sep spec\n", __FUNCTION__);*/
+      }
+      else {
+         t |= R128_SPEC_LIGHT_ENABLE;
+         FALLBACK( rmesa, R128_FALLBACK_SEP_SPECULAR, GL_FALSE );
+         /*printf("%s enable sep spec\n", __FUNCTION__);*/
+      }
+#else
+      t &= ~R128_SPEC_LIGHT_ENABLE;
+      FALLBACK( rmesa, R128_FALLBACK_SEP_SPECULAR, GL_TRUE );
+      /*printf("%s fallback  sep spec\n", __FUNCTION__);*/
+#endif
+   }
+   else {
+      t &= ~R128_SPEC_LIGHT_ENABLE;
+      FALLBACK( rmesa, R128_FALLBACK_SEP_SPECULAR, GL_FALSE );
+      /*printf("%s disable sep spec\n", __FUNCTION__);*/
+   }
+
+   if ( rmesa->setup.tex_cntl_c != t ) {
+      rmesa->setup.tex_cntl_c = t;
+      rmesa->dirty |= R128_UPLOAD_CONTEXT;
+      rmesa->dirty |= R128_UPLOAD_SETUP;
+      rmesa->new_state |= R128_NEW_CONTEXT;
+   }
+}
+
+
+static void r128DDLightModelfv( GLcontext *ctx, GLenum pname,
+                               const GLfloat *param )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   if ( pname == GL_LIGHT_MODEL_COLOR_CONTROL ) {
+      FLUSH_BATCH( rmesa );
+      updateSpecularLighting(ctx);
+   }
+}
+
+static void r128DDShadeModel( GLcontext *ctx, GLenum mode )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   GLuint s = rmesa->setup.pm4_vc_fpu_setup;
+
+   s &= ~R128_FPU_COLOR_MASK;
+
+   switch ( mode ) {
+   case GL_FLAT:
+      s |= R128_FPU_COLOR_FLAT;
+      break;
+   case GL_SMOOTH:
+      s |= R128_FPU_COLOR_GOURAUD;
+      break;
+   default:
+      return;
+   }
+
+   updateSpecularLighting(ctx);
+
+   if ( rmesa->setup.pm4_vc_fpu_setup != s ) {
+      FLUSH_BATCH( rmesa );
+      rmesa->setup.pm4_vc_fpu_setup = s;
+
+      rmesa->new_state |= R128_NEW_CONTEXT;
+      rmesa->dirty |= R128_UPLOAD_SETUP;
+   }
+}
+
+
+/* =============================================================
+ * Window position
+ */
+
+void r128UpdateWindow( GLcontext *ctx )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   int x = rmesa->driDrawable->x;
+   int y = rmesa->driDrawable->y;
+
+   rmesa->setup.window_xy_offset = ((y << R128_WINDOW_Y_SHIFT) |
+                                   (x << R128_WINDOW_X_SHIFT));
+
+   rmesa->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_WINDOW;
+}
+
+/* =============================================================
+ * Viewport
+ */
+
+
+static void r128CalcViewport( GLcontext *ctx )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   const GLfloat *v = ctx->Viewport._WindowMap.m;
+   GLfloat *m = rmesa->hw_viewport;
+
+   /* See also r128_translate_vertex.
+    */
+   m[MAT_SX] =   v[MAT_SX];
+   m[MAT_TX] =   v[MAT_TX] + SUBPIXEL_X;
+   m[MAT_SY] = - v[MAT_SY];
+   m[MAT_TY] = - v[MAT_TY] + rmesa->driDrawable->h + SUBPIXEL_Y;
+   m[MAT_SZ] =   v[MAT_SZ] * rmesa->depth_scale;
+   m[MAT_TZ] =   v[MAT_TZ] * rmesa->depth_scale;
+}
+
+static void r128Viewport( GLcontext *ctx,
+                         GLint x, GLint y,
+                         GLsizei width, GLsizei height )
+{
+   r128CalcViewport( ctx );
+}
+
+static void r128DepthRange( GLcontext *ctx,
+                           GLclampd nearval, GLclampd farval )
+{
+   r128CalcViewport( ctx );
+}
+
+
+/* =============================================================
+ * Miscellaneous
+ */
+
+static void r128DDClearColor( GLcontext *ctx,
+                             const GLfloat color[4] )
+{
+   r128ContextPtr rmesa = R128_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]);
+   CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
+
+   rmesa->ClearColor = r128PackColor( rmesa->r128Screen->cpp,
+                                     c[0], c[1], c[2], c[3] );
+}
+
+static void r128DDLogicOpCode( GLcontext *ctx, GLenum opcode )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   if ( ctx->Color.ColorLogicOpEnabled ) {
+      FLUSH_BATCH( rmesa );
+
+      FALLBACK( rmesa, R128_FALLBACK_LOGICOP, opcode != GL_COPY );
+   }
+}
+
+static void r128DDDrawBuffer( GLcontext *ctx, GLenum mode )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   FLUSH_BATCH( rmesa );
+
+   /*
+    * _DrawDestMask is easier to cope with than <mode>.
+    */
+   switch ( ctx->Color._DrawDestMask ) {
+   case FRONT_LEFT_BIT:
+      FALLBACK( rmesa, R128_FALLBACK_DRAW_BUFFER, GL_FALSE );
+      break;
+   case BACK_LEFT_BIT:
+      FALLBACK( rmesa, R128_FALLBACK_DRAW_BUFFER, GL_FALSE );
+      break;
+   default:
+      /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
+      FALLBACK( rmesa, R128_FALLBACK_DRAW_BUFFER, GL_TRUE );
+      break;
+   }
+
+   /* We want to update the s/w rast state too so that r200SetBuffer()
+    * gets called.
+    */
+   _swrast_DrawBuffer(ctx, mode);
+
+   rmesa->setup.dst_pitch_offset_c = (((rmesa->drawPitch/8) << 21) |
+                                      (rmesa->drawOffset >> 5));
+   rmesa->new_state |= R128_NEW_WINDOW;
+}
+
+static void r128DDReadBuffer( GLcontext *ctx, GLenum mode )
+{
+   /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
+}
+
+
+/* =============================================================
+ * Polygon stipple
+ */
+
+static void r128DDPolygonStipple( GLcontext *ctx, const GLubyte *mask )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   GLuint stipple[32], i;
+   drmR128Stipple stippleRec;
+
+   for (i = 0; i < 32; i++) {
+      stipple[31 - i] = ((mask[i*4+0] << 24) |
+                         (mask[i*4+1] << 16) |
+                         (mask[i*4+2] << 8)  |
+                         (mask[i*4+3]));
+   }
+
+   FLUSH_BATCH( rmesa );
+   LOCK_HARDWARE( rmesa );
+
+   stippleRec.mask = stipple;
+   drmCommandWrite( rmesa->driFd, DRM_R128_STIPPLE, 
+                    &stippleRec, sizeof(drmR128Stipple) );
+
+   UNLOCK_HARDWARE( rmesa );
+
+   rmesa->new_state |= R128_NEW_CONTEXT;
+   rmesa->dirty |= R128_UPLOAD_CONTEXT;
+}
+
+
+/* =============================================================
+ * Render mode
+ */
+
+static void r128DDRenderMode( GLcontext *ctx, GLenum mode )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   FALLBACK( rmesa, R128_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
+}
+
+
+
+/* =============================================================
+ * State enable/disable
+ */
+
+static void r128DDEnable( GLcontext *ctx, GLenum cap, GLboolean state )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
+      fprintf( stderr, "%s( %s = %s )\n",
+              __FUNCTION__, _mesa_lookup_enum_by_nr( cap ),
+              state ? "GL_TRUE" : "GL_FALSE" );
+   }
+
+   switch ( cap ) {
+   case GL_ALPHA_TEST:
+      FLUSH_BATCH( rmesa );
+      rmesa->new_state |= R128_NEW_ALPHA;
+      break;
+
+   case GL_BLEND:
+      FLUSH_BATCH( rmesa );
+      rmesa->new_state |= R128_NEW_ALPHA;
+
+      /* For some reason enable(GL_BLEND) affects ColorLogicOpEnabled.
+       */
+      FALLBACK( rmesa, R128_FALLBACK_LOGICOP,
+               (ctx->Color.ColorLogicOpEnabled &&
+                ctx->Color.LogicOp != GL_COPY));
+      break;
+
+   case GL_CULL_FACE:
+      FLUSH_BATCH( rmesa );
+      rmesa->new_state |= R128_NEW_CULL;
+      break;
+
+   case GL_DEPTH_TEST:
+      FLUSH_BATCH( rmesa );
+      rmesa->new_state |= R128_NEW_DEPTH;
+      break;
+
+   case GL_DITHER:
+      do {
+        GLuint t = rmesa->setup.tex_cntl_c;
+        FLUSH_BATCH( rmesa );
+
+        if ( ctx->Color.DitherFlag ) {
+           t |=  R128_DITHER_ENABLE;
+        } else {
+           t &= ~R128_DITHER_ENABLE;
+        }
+
+        if ( rmesa->setup.tex_cntl_c != t ) {
+           rmesa->setup.tex_cntl_c = t;
+           rmesa->dirty |= R128_UPLOAD_CONTEXT;
+        }
+      } while (0);
+      break;
+
+   case GL_FOG:
+      FLUSH_BATCH( rmesa );
+      rmesa->new_state |= R128_NEW_FOG;
+      break;
+
+   case GL_COLOR_LOGIC_OP:
+      FLUSH_BATCH( rmesa );
+      FALLBACK( rmesa, R128_FALLBACK_LOGICOP,
+               state && ctx->Color.LogicOp != GL_COPY );
+      break;
+
+   case GL_LIGHTING:
+      updateSpecularLighting(ctx);
+      break;
+
+   case GL_SCISSOR_TEST:
+      FLUSH_BATCH( rmesa );
+      rmesa->scissor = state;
+      rmesa->new_state |= R128_NEW_CLIP;
+      break;
+
+   case GL_STENCIL_TEST:
+      FLUSH_BATCH( rmesa );
+      FALLBACK( rmesa, R128_FALLBACK_STENCIL, state );
+      break;
+
+   case GL_TEXTURE_1D:
+   case GL_TEXTURE_2D:
+   case GL_TEXTURE_3D:
+      FLUSH_BATCH( rmesa );
+      break;
+
+   case GL_POLYGON_STIPPLE:
+      if ( rmesa->render_primitive == GL_TRIANGLES ) {
+        FLUSH_BATCH( rmesa );
+        rmesa->setup.dp_gui_master_cntl_c &= ~R128_GMC_BRUSH_NONE;
+        if ( state ) {
+           rmesa->setup.dp_gui_master_cntl_c |=
+              R128_GMC_BRUSH_32x32_MONO_FG_LA;
+        } else {
+           rmesa->setup.dp_gui_master_cntl_c |=
+              R128_GMC_BRUSH_SOLID_COLOR;
+        }
+        rmesa->new_state |= R128_NEW_CONTEXT;
+        rmesa->dirty |= R128_UPLOAD_CONTEXT;
+      }
+      break;
+
+   default:
+      return;
+   }
+}
+
+
+/* =============================================================
+ * State initialization, management
+ */
+
+static void r128DDPrintDirty( const char *msg, GLuint state )
+{
+   fprintf( stderr,
+           "%s: (0x%x) %s%s%s%s%s%s%s%s%s\n",
+           msg,
+           state,
+           (state & R128_UPLOAD_CORE)          ? "core, " : "",
+           (state & R128_UPLOAD_CONTEXT)       ? "context, " : "",
+           (state & R128_UPLOAD_SETUP)         ? "setup, " : "",
+           (state & R128_UPLOAD_TEX0)          ? "tex0, " : "",
+           (state & R128_UPLOAD_TEX1)          ? "tex1, " : "",
+           (state & R128_UPLOAD_MASKS)         ? "masks, " : "",
+           (state & R128_UPLOAD_WINDOW)        ? "window, " : "",
+           (state & R128_UPLOAD_CLIPRECTS)     ? "cliprects, " : "",
+           (state & R128_REQUIRE_QUIESCENCE)   ? "quiescence, " : "" );
+}
+
+/*
+ * Load the current context's state into the hardware.
+ *
+ * NOTE: Be VERY careful about ensuring the context state is marked for
+ * upload, the only place it shouldn't be uploaded is when the setup
+ * state has changed in ReducedPrimitiveChange as this comes right after
+ * a state update.
+ *
+ * Blits of any type should always upload the context and masks after
+ * they are done.
+ */
+void r128EmitHwStateLocked( r128ContextPtr rmesa )
+{
+   R128SAREAPrivPtr sarea = rmesa->sarea;
+   r128_context_regs_t *regs = &(rmesa->setup);
+   const r128TexObjPtr t0 = rmesa->CurrentTexObj[0];
+   const r128TexObjPtr t1 = rmesa->CurrentTexObj[1];
+
+   if ( R128_DEBUG & DEBUG_VERBOSE_MSG ) {
+      r128DDPrintDirty( "r128EmitHwStateLocked", rmesa->dirty );
+   }
+
+   if ( rmesa->dirty & (R128_UPLOAD_CONTEXT |
+                       R128_UPLOAD_SETUP |
+                       R128_UPLOAD_MASKS |
+                       R128_UPLOAD_WINDOW |
+                       R128_UPLOAD_CORE) ) {
+      memcpy( &sarea->ContextState, regs, sizeof(sarea->ContextState) );
+   }
+
+   if ( (rmesa->dirty & R128_UPLOAD_TEX0) && t0 ) {
+      r128_texture_regs_t *tex = &sarea->TexState[0];
+
+      tex->tex_cntl            = t0->setup.tex_cntl;
+      tex->tex_combine_cntl    = rmesa->tex_combine[0];
+      tex->tex_size_pitch      = t0->setup.tex_size_pitch;
+      memcpy( &tex->tex_offset[0], &t0->setup.tex_offset[0],
+             sizeof(tex->tex_offset ) );
+      tex->tex_border_color    = t0->setup.tex_border_color;
+   }
+
+   if ( (rmesa->dirty & R128_UPLOAD_TEX1) && t1 ) {
+      r128_texture_regs_t *tex = &sarea->TexState[1];
+
+      tex->tex_cntl            = t1->setup.tex_cntl;
+      tex->tex_combine_cntl    = rmesa->tex_combine[1];
+      tex->tex_size_pitch      = t1->setup.tex_size_pitch;
+      memcpy( &tex->tex_offset[0], &t1->setup.tex_offset[0],
+             sizeof(tex->tex_offset ) );
+      tex->tex_border_color    = t1->setup.tex_border_color;
+   }
+
+   sarea->vertsize = rmesa->vertex_size;
+   sarea->vc_format = rmesa->vertex_format;
+
+   /* Turn off the texture cache flushing */
+   rmesa->setup.tex_cntl_c &= ~R128_TEX_CACHE_FLUSH;
+
+   sarea->dirty |= rmesa->dirty;
+   rmesa->dirty &= R128_UPLOAD_CLIPRECTS;
+}
+
+static void r128DDPrintState( const char *msg, GLuint flags )
+{
+   fprintf( stderr,
+           "%s: (0x%x) %s%s%s%s%s%s%s%s\n",
+           msg,
+           flags,
+           (flags & R128_NEW_CONTEXT)  ? "context, " : "",
+           (flags & R128_NEW_ALPHA)    ? "alpha, " : "",
+           (flags & R128_NEW_DEPTH)    ? "depth, " : "",
+           (flags & R128_NEW_FOG)      ? "fog, " : "",
+           (flags & R128_NEW_CLIP)     ? "clip, " : "",
+           (flags & R128_NEW_CULL)     ? "cull, " : "",
+           (flags & R128_NEW_MASKS)    ? "masks, " : "",
+           (flags & R128_NEW_WINDOW)   ? "window, " : "" );
+}
+
+void r128DDUpdateHWState( GLcontext *ctx )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   int new_state = rmesa->new_state;
+
+   if ( new_state || rmesa->NewGLState & _NEW_TEXTURE )
+   {
+      FLUSH_BATCH( rmesa );
+
+      rmesa->new_state = 0;
+
+      if ( R128_DEBUG & DEBUG_VERBOSE_MSG )
+        r128DDPrintState( "r128UpdateHwState", new_state );
+
+      /* Update the various parts of the context's state.
+       */
+      if ( new_state & R128_NEW_ALPHA )
+        r128UpdateAlphaMode( ctx );
+
+      if ( new_state & R128_NEW_DEPTH )
+        r128UpdateZMode( ctx );
+
+      if ( new_state & R128_NEW_FOG )
+        r128UpdateFogAttrib( ctx );
+
+      if ( new_state & R128_NEW_CLIP )
+        r128UpdateClipping( ctx );
+
+      if ( new_state & R128_NEW_CULL )
+        r128UpdateCull( ctx );
+
+      if ( new_state & R128_NEW_MASKS )
+        r128UpdateMasks( ctx );
+
+      if ( new_state & R128_NEW_WINDOW )
+        r128UpdateWindow( ctx );
+
+      if ( rmesa->NewGLState & _NEW_TEXTURE ) {
+        r128UpdateTextureState( ctx );
+      }
+   }
+}
+
+
+static void r128DDInvalidateState( GLcontext *ctx, GLuint new_state )
+{
+   _swrast_InvalidateState( ctx, new_state );
+   _swsetup_InvalidateState( ctx, new_state );
+   _ac_InvalidateState( ctx, new_state );
+   _tnl_InvalidateState( ctx, new_state );
+   R128_CONTEXT(ctx)->NewGLState |= new_state;
+}
+
+
+
+/* Initialize the context's hardware state.
+ */
+void r128DDInitState( r128ContextPtr rmesa )
+{
+   int dst_bpp, depth_bpp;
+
+   switch ( rmesa->r128Screen->cpp ) {
+   case 2:
+      dst_bpp = R128_GMC_DST_16BPP;
+      break;
+   case 4:
+      dst_bpp = R128_GMC_DST_32BPP;
+      break;
+   default:
+      fprintf( stderr, "Error: Unsupported pixel depth... exiting\n" );
+      exit( -1 );
+   }
+
+   rmesa->ClearColor = 0x00000000;
+
+   switch ( rmesa->glCtx->Visual.depthBits ) {
+   case 16:
+      rmesa->ClearDepth = 0x0000ffff;
+      depth_bpp = R128_Z_PIX_WIDTH_16;
+      rmesa->depth_scale = 1.0 / (GLfloat)0xffff;
+      break;
+   case 24:
+      rmesa->ClearDepth = 0x00ffffff;
+      depth_bpp = R128_Z_PIX_WIDTH_24;
+      rmesa->depth_scale = 1.0 / (GLfloat)0xffffff;
+      break;
+   default:
+      fprintf( stderr, "Error: Unsupported depth %d... exiting\n",
+              rmesa->glCtx->Visual.depthBits );
+      exit( -1 );
+   }
+
+   rmesa->Fallback = 0;
+
+   if ( rmesa->glCtx->Visual.doubleBufferMode && rmesa->sarea->pfCurrentPage == 0 ) {
+      rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->backOffset;
+      rmesa->drawPitch  = rmesa->readPitch  = rmesa->r128Screen->backPitch;
+   } else {
+      rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->frontOffset;
+      rmesa->drawPitch  = rmesa->readPitch  = rmesa->r128Screen->frontPitch;
+   }
+
+   /* Harware state:
+    */
+   rmesa->setup.dst_pitch_offset_c = (((rmesa->drawPitch/8) << 21) |
+                                     (rmesa->drawOffset >> 5));
+
+   rmesa->setup.dp_gui_master_cntl_c = (R128_GMC_DST_PITCH_OFFSET_CNTL |
+                                       R128_GMC_DST_CLIPPING |
+                                       R128_GMC_BRUSH_SOLID_COLOR |
+                                       dst_bpp |
+                                       R128_GMC_SRC_DATATYPE_COLOR |
+                                       R128_GMC_BYTE_MSB_TO_LSB |
+                                       R128_GMC_CONVERSION_TEMP_6500 |
+                                       R128_ROP3_S |
+                                       R128_DP_SRC_SOURCE_MEMORY |
+                                       R128_GMC_3D_FCN_EN |
+                                       R128_GMC_CLR_CMP_CNTL_DIS |
+                                       R128_GMC_AUX_CLIP_DIS |
+                                       R128_GMC_WR_MSK_DIS);
+
+   rmesa->setup.sc_top_left_c     = 0x00000000;
+   rmesa->setup.sc_bottom_right_c = 0x1fff1fff;
+
+   rmesa->setup.z_offset_c = rmesa->r128Screen->depthOffset;
+   rmesa->setup.z_pitch_c = ((rmesa->r128Screen->depthPitch >> 3) |
+                            R128_Z_TILE);
+
+   rmesa->setup.z_sten_cntl_c = (depth_bpp |
+                                R128_Z_TEST_LESS |
+                                R128_STENCIL_TEST_ALWAYS |
+                                R128_STENCIL_S_FAIL_KEEP |
+                                R128_STENCIL_ZPASS_KEEP |
+                                R128_STENCIL_ZFAIL_KEEP);
+
+   rmesa->setup.tex_cntl_c = (R128_Z_WRITE_ENABLE |
+                             R128_SHADE_ENABLE |
+                             R128_DITHER_ENABLE |
+                             R128_ALPHA_IN_TEX_COMPLETE_A |
+                             R128_LIGHT_DIS |
+                             R128_ALPHA_LIGHT_DIS |
+                             R128_TEX_CACHE_FLUSH |
+                             (0x3f << R128_LOD_BIAS_SHIFT));
+
+   rmesa->setup.misc_3d_state_cntl_reg = (R128_MISC_SCALE_3D_TEXMAP_SHADE |
+                                         R128_MISC_SCALE_PIX_REPLICATE |
+                                         R128_ALPHA_COMB_ADD_CLAMP |
+                                         R128_FOG_VERTEX |
+                                         R128_ALPHA_BLEND_SRC_ONE |
+                                         R128_ALPHA_BLEND_DST_ZERO |
+                                         R128_ALPHA_TEST_ALWAYS);
+
+   rmesa->setup.texture_clr_cmp_clr_c = 0x00000000;
+   rmesa->setup.texture_clr_cmp_msk_c = 0xffffffff;
+
+   rmesa->setup.fog_color_c = 0x00000000;
+
+   rmesa->setup.pm4_vc_fpu_setup = (R128_FRONT_DIR_CCW |
+                                   R128_BACKFACE_SOLID |
+                                   R128_FRONTFACE_SOLID |
+                                   R128_FPU_COLOR_GOURAUD |
+                                   R128_FPU_SUB_PIX_4BITS |
+                                   R128_FPU_MODE_3D |
+                                   R128_TRAP_BITS_DISABLE |
+                                   R128_XFACTOR_2 |
+                                   R128_YFACTOR_2 |
+                                   R128_FLAT_SHADE_VERTEX_OGL |
+                                   R128_FPU_ROUND_TRUNCATE |
+                                   R128_WM_SEL_8DW);
+
+   rmesa->setup.setup_cntl = (R128_COLOR_GOURAUD |
+                             R128_PRIM_TYPE_TRI |
+                             R128_TEXTURE_ST_MULT_W |
+                             R128_STARTING_VERTEX_1 |
+                             R128_ENDING_VERTEX_3 |
+                             R128_SU_POLY_LINE_NOT_LAST |
+                             R128_SUB_PIX_4BITS);
+
+   rmesa->setup.tex_size_pitch_c = 0x00000000;
+   rmesa->setup.constant_color_c = 0x00ffffff;
+
+   rmesa->setup.dp_write_mask   = 0xffffffff;
+   rmesa->setup.sten_ref_mask_c = 0xffff0000;
+   rmesa->setup.plane_3d_mask_c = 0xffffffff;
+
+   rmesa->setup.window_xy_offset = 0x00000000;
+
+   rmesa->setup.scale_3d_cntl = (R128_SCALE_DITHER_TABLE |
+                                R128_TEX_CACHE_SIZE_FULL |
+                                R128_DITHER_INIT_RESET |
+                                R128_SCALE_3D_TEXMAP_SHADE |
+                                R128_SCALE_PIX_REPLICATE |
+                                R128_ALPHA_COMB_ADD_CLAMP |
+                                R128_FOG_VERTEX |
+                                R128_ALPHA_BLEND_SRC_ONE |
+                                R128_ALPHA_BLEND_DST_ZERO |
+                                R128_ALPHA_TEST_ALWAYS |
+                                R128_COMPOSITE_SHADOW_CMP_EQUAL |
+                                R128_TEX_MAP_ALPHA_IN_TEXTURE |
+                                R128_TEX_CACHE_LINE_SIZE_4QW);
+
+   rmesa->new_state = R128_NEW_ALL;
+}
+
+/* Initialize the driver's state functions.
+ */
+void r128DDInitStateFuncs( GLcontext *ctx )
+{
+   ctx->Driver.UpdateState             = r128DDInvalidateState;
+
+   ctx->Driver.ClearIndex              = NULL;
+   ctx->Driver.ClearColor              = r128DDClearColor;
+   ctx->Driver.DrawBuffer              = r128DDDrawBuffer;
+   ctx->Driver.ReadBuffer              = r128DDReadBuffer;
+
+   ctx->Driver.IndexMask               = NULL;
+   ctx->Driver.ColorMask               = r128DDColorMask;
+   ctx->Driver.AlphaFunc               = r128DDAlphaFunc;
+   ctx->Driver.BlendEquation           = r128DDBlendEquation;
+   ctx->Driver.BlendFunc               = r128DDBlendFunc;
+   ctx->Driver.BlendFuncSeparate       = r128DDBlendFuncSeparate;
+   ctx->Driver.ClearDepth              = r128DDClearDepth;
+   ctx->Driver.CullFace                        = r128DDCullFace;
+   ctx->Driver.FrontFace               = r128DDFrontFace;
+   ctx->Driver.DepthFunc               = r128DDDepthFunc;
+   ctx->Driver.DepthMask               = r128DDDepthMask;
+   ctx->Driver.Enable                  = r128DDEnable;
+   ctx->Driver.Fogfv                   = r128DDFogfv;
+   ctx->Driver.Hint                    = NULL;
+   ctx->Driver.Lightfv                 = NULL;
+   ctx->Driver.LightModelfv            = r128DDLightModelfv;
+   ctx->Driver.LogicOpcode             = r128DDLogicOpCode;
+   ctx->Driver.PolygonMode             = NULL;
+   ctx->Driver.PolygonStipple          = r128DDPolygonStipple;
+   ctx->Driver.RenderMode              = r128DDRenderMode;
+   ctx->Driver.Scissor                 = r128DDScissor;
+   ctx->Driver.ShadeModel              = r128DDShadeModel;
+   ctx->Driver.ClearStencil            = NULL;
+   ctx->Driver.StencilFunc             = NULL;
+   ctx->Driver.StencilMask             = NULL;
+   ctx->Driver.StencilOp               = NULL;
+
+   ctx->Driver.DepthRange               = r128DepthRange;
+   ctx->Driver.Viewport                 = r128Viewport;
+
+   /* Pixel path fallbacks.
+    */
+   ctx->Driver.Accum = _swrast_Accum;
+   ctx->Driver.Bitmap = _swrast_Bitmap;
+   ctx->Driver.CopyPixels = _swrast_CopyPixels;
+   ctx->Driver.DrawPixels = _swrast_DrawPixels;
+   ctx->Driver.ReadPixels = _swrast_ReadPixels;
+
+   /* 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;
+}
diff --git a/src/mesa/drivers/dri/r128/r128_state.h b/src/mesa/drivers/dri/r128/r128_state.h
new file mode 100644 (file)
index 0000000..c51ac23
--- /dev/null
@@ -0,0 +1,54 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_state.h,v 1.3 2001/01/08 01:07:21 martin Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+                                               Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Gareth Hughes <gareth@valinux.com>
+ *   Kevin E. Martin <martin@valinux.com>
+ *
+ */
+
+#ifndef __R128_STATE_H__
+#define __R128_STATE_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include "r128_context.h"
+
+extern void r128DDInitState( r128ContextPtr rmesa );
+extern void r128DDInitStateFuncs( GLcontext *ctx );
+
+extern void r128DDUpdateState( GLcontext *ctx );
+extern void r128DDUpdateHWState( GLcontext *ctx );
+
+extern void r128UpdateWindow( GLcontext *ctx );
+
+extern void r128EmitHwStateLocked( r128ContextPtr rmesa );
+
+#endif
+#endif
diff --git a/src/mesa/drivers/dri/r128/r128_tex.c b/src/mesa/drivers/dri/r128/r128_tex.c
new file mode 100644 (file)
index 0000000..2793a79
--- /dev/null
@@ -0,0 +1,598 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tex.c,v 1.14 2002/11/05 17:46:08 tsi Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+                                               Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Gareth Hughes <gareth@valinux.com>
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Brian Paul <brianp@valinux.com>
+ */
+
+#include "r128_context.h"
+#include "r128_state.h"
+#include "r128_ioctl.h"
+#include "r128_vb.h"
+#include "r128_tris.h"
+#include "r128_tex.h"
+#include "r128_texobj.h"
+
+#include "context.h"
+#include "macros.h"
+#include "simple_list.h"
+#include "enums.h"
+#include "texstore.h"
+#include "texformat.h"
+#include "teximage.h"
+#include "imports.h"
+#include "colormac.h"
+
+#define TEX_0  1
+#define TEX_1  2
+
+
+static void r128SetTexWrap( r128TexObjPtr t, GLenum swrap, GLenum twrap )
+{
+   t->setup.tex_cntl &= ~(R128_TEX_CLAMP_S_MASK | R128_TEX_CLAMP_T_MASK);
+
+   switch ( swrap ) {
+   case GL_CLAMP:
+      t->setup.tex_cntl |= R128_TEX_CLAMP_S_BORDER_COLOR;
+      break;
+   case GL_CLAMP_TO_EDGE:
+      t->setup.tex_cntl |= R128_TEX_CLAMP_S_CLAMP;
+      break;
+   case GL_REPEAT:
+      t->setup.tex_cntl |= R128_TEX_CLAMP_S_WRAP;
+      break;
+   case GL_CLAMP_TO_BORDER:
+      t->setup.tex_cntl |= R128_TEX_CLAMP_S_BORDER_COLOR;
+      break;
+   case GL_MIRRORED_REPEAT:
+      t->setup.tex_cntl |= R128_TEX_CLAMP_S_MIRROR;
+      break;
+   }
+
+   switch ( twrap ) {
+   case GL_CLAMP:
+      t->setup.tex_cntl |= R128_TEX_CLAMP_T_BORDER_COLOR;
+      break;
+   case GL_CLAMP_TO_EDGE:
+      t->setup.tex_cntl |= R128_TEX_CLAMP_T_CLAMP;
+      break;
+   case GL_REPEAT:
+      t->setup.tex_cntl |= R128_TEX_CLAMP_T_WRAP;
+      break;
+   case GL_CLAMP_TO_BORDER:
+      t->setup.tex_cntl |= R128_TEX_CLAMP_T_BORDER_COLOR;
+      break;
+   case GL_MIRRORED_REPEAT:
+      t->setup.tex_cntl |= R128_TEX_CLAMP_T_MIRROR;
+      break;
+   }
+}
+
+static void r128SetTexFilter( r128TexObjPtr t, GLenum minf, GLenum magf )
+{
+   t->setup.tex_cntl &= ~(R128_MIN_BLEND_MASK | R128_MAG_BLEND_MASK);
+
+   switch ( minf ) {
+   case GL_NEAREST:
+      t->setup.tex_cntl |= R128_MIN_BLEND_NEAREST;
+      break;
+   case GL_LINEAR:
+      t->setup.tex_cntl |= R128_MIN_BLEND_LINEAR;
+      break;
+   case GL_NEAREST_MIPMAP_NEAREST:
+      t->setup.tex_cntl |= R128_MIN_BLEND_MIPNEAREST;
+      break;
+   case GL_LINEAR_MIPMAP_NEAREST:
+      t->setup.tex_cntl |= R128_MIN_BLEND_MIPLINEAR;
+      break;
+   case GL_NEAREST_MIPMAP_LINEAR:
+      t->setup.tex_cntl |= R128_MIN_BLEND_LINEARMIPNEAREST;
+      break;
+   case GL_LINEAR_MIPMAP_LINEAR:
+      t->setup.tex_cntl |= R128_MIN_BLEND_LINEARMIPLINEAR;
+      break;
+   }
+
+   switch ( magf ) {
+   case GL_NEAREST:
+      t->setup.tex_cntl |= R128_MAG_BLEND_NEAREST;
+      break;
+   case GL_LINEAR:
+      t->setup.tex_cntl |= R128_MAG_BLEND_LINEAR;
+      break;
+   }
+}
+
+static void r128SetTexBorderColor( r128TexObjPtr t, GLubyte c[4] )
+{
+   t->setup.tex_border_color = r128PackColor( 4, c[0], c[1], c[2], c[3] );
+}
+
+
+static r128TexObjPtr r128AllocTexObj( struct gl_texture_object *texObj )
+{
+   r128TexObjPtr t;
+
+   if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
+      fprintf( stderr, "%s( %p )\n", __FUNCTION__, texObj );
+   }
+
+   t = (r128TexObjPtr) CALLOC_STRUCT( r128_tex_obj );
+   texObj->DriverData = t;
+   if ( t != NULL ) {
+
+      /* Initialize non-image-dependent parts of the state:
+       */
+      t->base.tObj = texObj;
+
+      /* FIXME Something here to set initial values for other parts of
+       * FIXME t->setup?
+       */
+  
+      make_empty_list( (driTextureObject *) t );
+
+      r128SetTexWrap( t, texObj->WrapS, texObj->WrapT );
+      r128SetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
+      r128SetTexBorderColor( t, texObj->_BorderChan );
+   }
+
+   return t;
+}
+
+
+/* Called by the _mesa_store_teximage[123]d() functions. */
+static const struct gl_texture_format *
+r128ChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
+                         GLenum format, GLenum type )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   (void) format;
+   (void) type;
+
+   switch ( internalFormat ) {
+   case GL_ALPHA:
+   case GL_ALPHA4:
+   case GL_ALPHA8:
+   case GL_ALPHA12:
+   case GL_ALPHA16:
+   case GL_COMPRESSED_ALPHA:
+   case 2:
+   case GL_LUMINANCE_ALPHA:
+   case GL_LUMINANCE4_ALPHA4:
+   case GL_LUMINANCE6_ALPHA2:
+   case GL_LUMINANCE8_ALPHA8:
+   case GL_LUMINANCE12_ALPHA4:
+   case GL_LUMINANCE12_ALPHA12:
+   case GL_LUMINANCE16_ALPHA16:
+   case GL_COMPRESSED_LUMINANCE_ALPHA:
+   case 4:
+   case GL_RGBA:
+   case GL_COMPRESSED_RGBA:
+   case GL_RGBA2:
+   case GL_RGB5_A1:
+   case GL_RGBA8:
+   case GL_RGB10_A2:
+   case GL_RGBA12:
+   case GL_RGBA16:
+      if (rmesa->r128Screen->cpp == 4)
+         return &_mesa_texformat_argb8888;
+      else
+         return &_mesa_texformat_argb4444;
+   case GL_RGBA4:
+         return &_mesa_texformat_argb4444;
+
+   case 3:
+   case GL_RGB:
+   case GL_COMPRESSED_RGB:
+   case GL_R3_G3_B2:
+   case GL_RGB4:
+   case GL_RGB5:
+   case GL_RGB8:
+   case GL_RGB10:
+   case GL_RGB12:
+   case GL_RGB16:
+      if (rmesa->r128Screen->cpp == 4)
+         return &_mesa_texformat_argb8888;
+      else
+         return &_mesa_texformat_rgb565;
+
+   case 1:
+   case GL_LUMINANCE:
+   case GL_LUMINANCE4:
+   case GL_LUMINANCE8:
+   case GL_LUMINANCE12:
+   case GL_LUMINANCE16:
+   case GL_COMPRESSED_LUMINANCE:
+      if (rmesa->r128Screen->cpp == 4)
+         return &_mesa_texformat_argb8888; /* inefficient but accurate */
+      else
+         return &_mesa_texformat_rgb565;
+
+   case GL_INTENSITY4:
+      return &_mesa_texformat_argb4444;
+   case GL_INTENSITY:
+   case GL_INTENSITY8:
+   case GL_INTENSITY12:
+   case GL_INTENSITY16:
+   case GL_COMPRESSED_INTENSITY:
+      if (rmesa->r128Screen->cpp == 4)
+         return &_mesa_texformat_argb8888; /* inefficient but accurate */
+      else
+         return &_mesa_texformat_argb4444;
+
+   case GL_COLOR_INDEX:
+   case GL_COLOR_INDEX1_EXT:
+   case GL_COLOR_INDEX2_EXT:
+   case GL_COLOR_INDEX4_EXT:
+   case GL_COLOR_INDEX8_EXT:
+   case GL_COLOR_INDEX12_EXT:
+   case GL_COLOR_INDEX16_EXT:
+      return &_mesa_texformat_ci8;
+
+   case GL_YCBCR_MESA:
+      if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
+          type == GL_UNSIGNED_BYTE)
+         return &_mesa_texformat_ycbcr;
+      else
+         return &_mesa_texformat_ycbcr_rev;
+
+   default:
+      _mesa_problem( ctx, "unexpected format in %s", __FUNCTION__ );
+      return NULL;
+   }
+}
+
+
+static void r128TexImage1D( GLcontext *ctx, GLenum target, GLint level,
+                           GLint internalFormat,
+                           GLint width, GLint border,
+                           GLenum format, GLenum type, const GLvoid *pixels,
+                           const struct gl_pixelstore_attrib *packing,
+                           struct gl_texture_object *texObj,
+                           struct gl_texture_image *texImage )
+{
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
+
+   if ( t ) {
+      driSwapOutTextureObject( t );
+   }
+   else {
+      t = (driTextureObject *) r128AllocTexObj(texObj);
+      if (!t) {
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
+         return;
+      }
+   }
+
+   /* Note, this will call r128ChooseTextureFormat */
+   _mesa_store_teximage1d( ctx, target, level, internalFormat,
+                          width, border, format, type,
+                          pixels, packing, texObj, texImage );
+
+   t->dirty_images[0] |= (1 << level);
+}
+
+
+static void r128TexSubImage1D( GLcontext *ctx,
+                              GLenum target,
+                              GLint level,
+                              GLint xoffset,
+                              GLsizei width,
+                              GLenum format, GLenum type,
+                              const GLvoid *pixels,
+                              const struct gl_pixelstore_attrib *packing,
+                              struct gl_texture_object *texObj,
+                              struct gl_texture_image *texImage )
+{
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
+
+   assert( t ); /* this _should_ be true */
+   if ( t ) {
+      driSwapOutTextureObject( t );
+   }
+   else {
+      t = (driTextureObject *) r128AllocTexObj(texObj);
+      if (!t) {
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
+         return;
+      }
+   }
+
+   _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
+                            format, type, pixels, packing, texObj,
+                            texImage);
+
+   t->dirty_images[0] |= (1 << level);
+}
+
+
+static void r128TexImage2D( GLcontext *ctx, GLenum target, GLint level,
+                           GLint internalFormat,
+                           GLint width, GLint height, GLint border,
+                           GLenum format, GLenum type, const GLvoid *pixels,
+                           const struct gl_pixelstore_attrib *packing,
+                           struct gl_texture_object *texObj,
+                           struct gl_texture_image *texImage )
+{
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
+
+   if ( t ) {
+      driSwapOutTextureObject( (driTextureObject *) t );
+   }
+   else {
+      t = (driTextureObject *) r128AllocTexObj(texObj);
+      if (!t) {
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+         return;
+      }
+   }
+
+   /* Note, this will call r128ChooseTextureFormat */
+   _mesa_store_teximage2d(ctx, target, level, internalFormat,
+                          width, height, border, format, type, pixels,
+                          &ctx->Unpack, texObj, texImage);
+
+   t->dirty_images[0] |= (1 << level);
+}
+
+
+static void r128TexSubImage2D( GLcontext *ctx,
+                              GLenum target,
+                              GLint level,
+                              GLint xoffset, GLint yoffset,
+                              GLsizei width, GLsizei height,
+                              GLenum format, GLenum type,
+                              const GLvoid *pixels,
+                              const struct gl_pixelstore_attrib *packing,
+                              struct gl_texture_object *texObj,
+                              struct gl_texture_image *texImage )
+{
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
+
+   assert( t ); /* this _should_ be true */
+   if ( t ) {
+      driSwapOutTextureObject( t );
+   }
+   else {
+      t = (driTextureObject *) r128AllocTexObj(texObj);
+      if (!t) {
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+         return;
+      }
+   }
+
+   _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
+                            height, format, type, pixels, packing, texObj,
+                            texImage);
+   t->dirty_images[0] |= (1 << level);
+}
+
+
+static void r128DDTexEnv( GLcontext *ctx, GLenum target,
+                         GLenum pname, const GLfloat *param )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   struct gl_texture_unit *texUnit;
+   GLubyte c[4];
+
+   if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
+      fprintf( stderr, "%s( %s )\n",
+              __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
+   }
+
+   switch ( pname ) {
+   case GL_TEXTURE_ENV_MODE:
+      FLUSH_BATCH( rmesa );
+      rmesa->new_state |= R128_NEW_ALPHA;
+      break;
+
+   case GL_TEXTURE_ENV_COLOR:
+      texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+      CLAMPED_FLOAT_TO_UBYTE( c[0], texUnit->EnvColor[0] );
+      CLAMPED_FLOAT_TO_UBYTE( c[1], texUnit->EnvColor[1] );
+      CLAMPED_FLOAT_TO_UBYTE( c[2], texUnit->EnvColor[2] );
+      CLAMPED_FLOAT_TO_UBYTE( c[3], texUnit->EnvColor[3] );
+      rmesa->env_color = r128PackColor( 4, c[0], c[1], c[2], c[3] );
+      if ( rmesa->setup.constant_color_c != rmesa->env_color ) {
+        FLUSH_BATCH( rmesa );
+        rmesa->setup.constant_color_c = rmesa->env_color;
+
+        /* More complex multitexture/multipass fallbacks for GL_BLEND
+         * can be done later, but this allows a single pass GL_BLEND
+         * in some cases (ie. Performer town demo).  This is only
+         * applicable to the regular Rage 128, as the Pro and M3 can
+         * handle true single-pass GL_BLEND texturing.
+         */
+        rmesa->blend_flags &= ~R128_BLEND_ENV_COLOR;
+        if ( R128_IS_PLAIN( rmesa ) &&
+             rmesa->env_color != 0x00000000 &&
+             rmesa->env_color != 0xff000000 &&
+             rmesa->env_color != 0x00ffffff &&
+             rmesa->env_color != 0xffffffff ) {
+           rmesa->blend_flags |= R128_BLEND_ENV_COLOR;
+        }
+      }
+      break;
+
+   case GL_TEXTURE_LOD_BIAS_EXT:
+      do {
+        CARD32 t = rmesa->setup.tex_cntl_c;
+        GLint bias;
+        CARD32 b;
+
+        /* GTH: This isn't exactly correct, but gives good results up to a
+         * certain point.  It is better than completely ignoring the LOD
+         * bias.  Unfortunately there isn't much range in the bias, the
+         * spec mentions strides that vary between 0.5 and 2.0 but these
+         * numbers don't seem to relate the the GL LOD bias value at all.
+         */
+        if ( param[0] >= 1.0 ) {
+           bias = -128;
+        } else if ( param[0] >= 0.5 ) {
+           bias = -64;
+        } else if ( param[0] >= 0.25 ) {
+           bias = 0;
+        } else if ( param[0] >= 0.0 ) {
+           bias = 63;
+        } else {
+           bias = 127;
+        }
+
+        b = (CARD32)bias & 0xff;
+        t &= ~R128_LOD_BIAS_MASK;
+        t |= (b << R128_LOD_BIAS_SHIFT);
+
+        if ( rmesa->setup.tex_cntl_c != t ) {
+           FLUSH_BATCH( rmesa );
+           rmesa->setup.tex_cntl_c = t;
+           rmesa->dirty |= R128_UPLOAD_CONTEXT;
+        }
+      } while (0);
+      break;
+
+   default:
+      return;
+   }
+}
+
+
+static void r128DDTexParameter( GLcontext *ctx, GLenum target,
+                               struct gl_texture_object *tObj,
+                               GLenum pname, const GLfloat *params )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   r128TexObjPtr t = (r128TexObjPtr)tObj->DriverData;
+
+   if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
+      fprintf( stderr, "%s( %s )\n",
+              __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
+   }
+
+   if ( ( target != GL_TEXTURE_2D ) && ( target != GL_TEXTURE_1D ) )
+      return;
+
+   switch ( pname ) {
+   case GL_TEXTURE_MIN_FILTER:
+   case GL_TEXTURE_MAG_FILTER:
+      if ( t->base.bound ) FLUSH_BATCH( rmesa );
+      r128SetTexFilter( t, tObj->MinFilter, tObj->MagFilter );
+      break;
+
+   case GL_TEXTURE_WRAP_S:
+   case GL_TEXTURE_WRAP_T:
+      if ( t->base.bound ) FLUSH_BATCH( rmesa );
+      r128SetTexWrap( t, tObj->WrapS, tObj->WrapT );
+      break;
+
+   case GL_TEXTURE_BORDER_COLOR:
+      if ( t->base.bound ) FLUSH_BATCH( rmesa );
+      r128SetTexBorderColor( t, tObj->_BorderChan );
+      break;
+
+   case GL_TEXTURE_BASE_LEVEL:
+   case GL_TEXTURE_MAX_LEVEL:
+   case GL_TEXTURE_MIN_LOD:
+   case GL_TEXTURE_MAX_LOD:
+      /* This isn't the most efficient solution but there doesn't appear to
+       * be a nice alternative for R128.  Since there's no LOD clamping,
+       * we just have to rely on loading the right subset of mipmap levels
+       * to simulate a clamped LOD.
+       */
+      if ( t->base.bound ) FLUSH_BATCH( rmesa );
+      driSwapOutTextureObject( (driTextureObject *) t );
+      break;
+
+   default:
+      return;
+   }
+}
+
+static void r128DDBindTexture( GLcontext *ctx, GLenum target,
+                              struct gl_texture_object *tObj )
+{
+   if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
+      fprintf( stderr, "%s( %p ) unit=%d\n", __FUNCTION__, tObj,
+              ctx->Texture.CurrentUnit );
+   }
+
+   if ( target == GL_TEXTURE_2D || target == GL_TEXTURE_1D ) {
+      if ( tObj->DriverData == NULL ) {
+        r128AllocTexObj( tObj );
+      }
+   }
+}
+
+static void r128DDDeleteTexture( GLcontext *ctx,
+                                struct gl_texture_object *tObj )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   driTextureObject * t = (driTextureObject *) tObj->DriverData;
+
+   if ( t ) {
+      if ( t->bound && rmesa ) {
+        FLUSH_BATCH( rmesa );
+      }
+
+      driDestroyTextureObject( t );
+   }
+}
+
+void r128DDInitTextureFuncs( GLcontext *ctx )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+
+   ctx->Driver.TexEnv                  = r128DDTexEnv;
+   ctx->Driver.ChooseTextureFormat     = r128ChooseTextureFormat;
+   ctx->Driver.TexImage1D              = r128TexImage1D;
+   ctx->Driver.TexSubImage1D           = r128TexSubImage1D;
+   ctx->Driver.TexImage2D              = r128TexImage2D;
+   ctx->Driver.TexSubImage2D           = r128TexSubImage2D;
+   ctx->Driver.TexImage3D               = _mesa_store_teximage3d;
+   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;
+   ctx->Driver.TexParameter            = r128DDTexParameter;
+   ctx->Driver.BindTexture             = r128DDBindTexture;
+   ctx->Driver.DeleteTexture           = r128DDDeleteTexture;
+   ctx->Driver.UpdateTexturePalette    = NULL;
+   ctx->Driver.ActiveTexture           = NULL;
+   ctx->Driver.IsTextureResident       = driIsTextureResident;
+   ctx->Driver.PrioritizeTexture       = NULL;
+
+   driInitTextureObjects( ctx, & rmesa->swapped,
+                         DRI_TEXMGR_DO_TEXTURE_1D
+                         | DRI_TEXMGR_DO_TEXTURE_2D );
+}
diff --git a/src/mesa/drivers/dri/r128/r128_tex.h b/src/mesa/drivers/dri/r128/r128_tex.h
new file mode 100644 (file)
index 0000000..2e3d954
--- /dev/null
@@ -0,0 +1,88 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tex.h,v 1.7 2002/02/22 21:44:58 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+                                               Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Gareth Hughes <gareth@valinux.com>
+ *   Kevin E. Martin <martin@valinux.com>
+ *
+ */
+
+#ifndef __R128_TEX_H__
+#define __R128_TEX_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+extern void r128UpdateTextureState( GLcontext *ctx );
+
+extern void r128UploadTexImages( r128ContextPtr rmesa, r128TexObjPtr t );
+
+extern void r128DestroyTexObj( r128ContextPtr rmesa, r128TexObjPtr t );
+
+extern void r128DDInitTextureFuncs( GLcontext *ctx );
+
+
+/* ================================================================
+ * Color conversion macros:
+ */
+
+#define R128PACKCOLOR332( r, g, b )                                    \
+   (((r) & 0xe0) | (((g) & 0xe0) >> 3) | (((b) & 0xc0) >> 6))
+
+#define R128PACKCOLOR1555( r, g, b, a )                                        \
+   ((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) |  \
+    ((a) ? 0x8000 : 0))
+
+#define R128PACKCOLOR565( r, g, b )                                    \
+   ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3))
+
+#define R128PACKCOLOR888( r, g, b )                                    \
+   (((r) << 16) | ((g) << 8) | (b))
+
+#define R128PACKCOLOR8888( r, g, b, a )                                        \
+   (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
+
+#define R128PACKCOLOR4444( r, g, b, a )                                        \
+   ((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4))
+
+static __inline__ CARD32 r128PackColor( GLuint cpp,
+                                       GLubyte r, GLubyte g,
+                                       GLubyte b, GLubyte a )
+{
+    switch ( cpp ) {
+    case 2:
+       return R128PACKCOLOR565( r, g, b );
+    case 4:
+       return R128PACKCOLOR8888( r, g, b, a );
+    default:
+       return 0;
+    }
+}
+
+#endif
+#endif /* __R128_TEX_H__ */
diff --git a/src/mesa/drivers/dri/r128/r128_texmem.c b/src/mesa/drivers/dri/r128/r128_texmem.c
new file mode 100644 (file)
index 0000000..f6a5dfb
--- /dev/null
@@ -0,0 +1,302 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tex.c,v 1.7 2001/01/08 01:07:21 martin Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+                                               Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Gareth Hughes <gareth@valinux.com>
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Brian Paul <brianp@valinux.com>
+ */
+
+#include "r128_context.h"
+#include "r128_state.h"
+#include "r128_ioctl.h"
+#include "r128_vb.h"
+#include "r128_tris.h"
+#include "r128_tex.h"
+
+#include "context.h"
+#include "macros.h"
+#include "simple_list.h"
+#include "texformat.h"
+#include "imports.h"
+
+#define TEX_0  1
+#define TEX_1  2
+
+
+/* Destroy hardware state associated with texture `t'.
+ */
+void r128DestroyTexObj( r128ContextPtr rmesa, r128TexObjPtr t )
+{
+    unsigned   i;
+
+
+    /* See if it was the driver's current object.
+     */
+
+    if ( rmesa != NULL )
+    { 
+       for ( i = 0 ; i < rmesa->glCtx->Const.MaxTextureUnits ; i++ )
+       {
+           if ( t == rmesa->CurrentTexObj[ i ] ) {
+               assert( t->base.bound & (1 << i) );
+               rmesa->CurrentTexObj[ i ] = NULL;
+           }
+       }
+    }
+}
+
+
+/**
+ * Upload the texture image associated with texture \a t at the specified
+ * level at the address relative to \a start.
+ */
+static void uploadSubImage( r128ContextPtr rmesa, r128TexObjPtr t,
+                           GLint level,
+                           GLint x, GLint y, GLint width, GLint height )
+{
+   struct gl_texture_image *image;
+   int texelsPerDword = 0;
+   int imageWidth, imageHeight;
+   int remaining, rows;
+   int format, dwords;
+   CARD32 pitch, offset;
+   int i;
+
+   /* Ensure we have a valid texture to upload */
+   if ( ( level < 0 ) || ( level > R128_MAX_TEXTURE_LEVELS ) )
+      return;
+
+   image = t->base.tObj->Image[level];
+   if ( !image )
+      return;
+
+   switch ( image->TexFormat->TexelBytes ) {
+   case 1: texelsPerDword = 4; break;
+   case 2: texelsPerDword = 2; break;
+   case 4: texelsPerDword = 1; break;
+   }
+
+#if 1
+   /* FIXME: The subimage index calcs are wrong... */
+   x = 0;
+   y = 0;
+   width = image->Width;
+   height = image->Height;
+#endif
+
+   imageWidth  = image->Width;
+   imageHeight = image->Height;
+
+   format = t->textureFormat >> 16;
+
+   /* The texel upload routines have a minimum width, so force the size
+    * if needed.
+    */
+   if ( imageWidth < texelsPerDword ) {
+      int factor;
+
+      factor = texelsPerDword / imageWidth;
+      imageWidth = texelsPerDword;
+      imageHeight /= factor;
+      if ( imageHeight == 0 ) {
+        /* In this case, the texel converter will actually walk a
+         * texel or two off the end of the image, but normal malloc
+         * alignment should prevent it from ever causing a fault.
+         */
+        imageHeight = 1;
+      }
+   }
+
+   /* We can't upload to a pitch less than 8 texels so we will need to
+    * linearly upload all modified rows for textures smaller than this.
+    * This makes the x/y/width/height different for the blitter and the
+    * texture walker.
+    */
+   if ( imageWidth >= 8 ) {
+      /* The texture walker and the blitter look identical */
+      pitch = imageWidth >> 3;
+   } else {
+      int factor;
+      int y2;
+      int start, end;
+
+      start = (y * imageWidth) & ~7;
+      end = (y + height) * imageWidth;
+
+      if ( end - start < 8 ) {
+        /* Handle the case where the total number of texels
+         * uploaded is < 8.
+         */
+        x = 0;
+        y = start / 8;
+        width = end - start;
+        height = 1;
+      } else {
+        /* Upload some number of full 8 texel blit rows */
+        factor = 8 / imageWidth;
+
+        y2 = y + height - 1;
+        y /= factor;
+        y2 /= factor;
+
+        x = 0;
+        width = 8;
+        height = y2 - y + 1;
+      }
+
+      /* Fixed pitch of 8 */
+      pitch = 1;
+   }
+
+   dwords = width * height / texelsPerDword;
+   offset = t->bufAddr + t->image[level - t->base.firstLevel].offset;
+
+#if ENABLE_PERF_BOXES
+   /* Bump the performace counter */
+   rmesa->c_textureBytes += (dwords << 2);
+#endif
+
+   if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
+      fprintf( stderr, "r128UploadSubImage: %d,%d of %d,%d at %d,%d\n",
+              width, height, image->Width, image->Height, x, y );
+      fprintf( stderr, "          blit ofs: 0x%07x pitch: 0x%x dwords: %d "
+              "level: %d format: %x\n",
+              (GLuint)offset, (GLuint)pitch, dwords, level, format );
+   }
+
+   /* Subdivide the texture if required */
+   if ( dwords <= R128_BUFFER_MAX_DWORDS / 2 ) {
+      rows = height;
+   } else {
+      rows = (R128_BUFFER_MAX_DWORDS * texelsPerDword) / (2 * width);
+   }
+
+   for ( i = 0, remaining = height ;
+        remaining > 0 ;
+        remaining -= rows, y += rows, i++ )
+   {
+      CARD32 *dst;
+      drmBufPtr buffer;
+
+      assert(image->Data);
+
+      height = MIN2(remaining, rows);
+
+      /* Grab the indirect buffer for the texture blit */
+      LOCK_HARDWARE( rmesa );
+      buffer = r128GetBufferLocked( rmesa );
+
+      dst = (CARD32 *)((char *)buffer->address + R128_HOSTDATA_BLIT_OFFSET);
+
+      /* Copy the next chunck of the texture image into the blit buffer */
+      {
+         const GLubyte *src = (const GLubyte *) image->Data +
+            (y * image->Width + x) * image->TexFormat->TexelBytes;
+         const GLuint bytes = width * height * image->TexFormat->TexelBytes;
+         memcpy(dst, src, bytes);
+      }
+
+      r128FireBlitLocked( rmesa, buffer,
+                         offset, pitch, format,
+                         x, y, width, height );
+      UNLOCK_HARDWARE( rmesa );
+   }
+
+   rmesa->new_state |= R128_NEW_CONTEXT;
+   rmesa->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
+}
+
+
+/* Upload the texture images associated with texture `t'.  This might
+ * require removing our own and/or other client's texture objects to
+ * make room for these images.
+ */
+void r128UploadTexImages( r128ContextPtr rmesa, r128TexObjPtr t )
+{
+   const GLint numLevels = t->base.lastLevel - t->base.firstLevel + 1;
+   GLint i;
+
+   if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
+      fprintf( stderr, "%s( %p, %p )\n",
+              __FUNCTION__, rmesa->glCtx, t );
+   }
+
+   assert(t);
+
+   LOCK_HARDWARE( rmesa );
+
+   if ( !t->base.memBlock ) {
+      int heap;
+
+
+      heap = driAllocateTexture( rmesa->texture_heaps, rmesa->nr_heaps,
+                                (driTextureObject *) t );
+      if ( heap == -1 ) {
+        UNLOCK_HARDWARE( rmesa );
+        return;
+      }
+
+      /* Set the base offset of the texture image */
+      t->bufAddr = rmesa->r128Screen->texOffset[heap] 
+          + t->base.memBlock->ofs;
+
+      /* Set texture offsets for each mipmap level */
+      if ( t->setup.tex_cntl & R128_MIP_MAP_DISABLE ) {
+        for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
+           t->setup.tex_offset[i] = t->bufAddr;
+        }
+      } else {
+         for ( i = 0; i < numLevels; i++ ) {
+            const int j = numLevels - i - 1;
+            t->setup.tex_offset[j] = t->bufAddr + t->image[i].offset;
+         }
+      }
+   }
+
+   /* Let the world know we've used this memory recently.
+    */
+   driUpdateTextureLRU( (driTextureObject *) t );
+   UNLOCK_HARDWARE( rmesa );
+
+   /* Upload any images that are new */
+   if ( t->base.dirty_images[0] ) {
+      for ( i = 0 ; i < numLevels; i++ ) {
+         const GLint j = t->base.firstLevel + i;  /* the texObj's level */
+        if ( t->base.dirty_images[0] & (1 << j) ) {
+           uploadSubImage( rmesa, t, j, 0, 0,
+                           t->image[i].width, t->image[i].height );
+        }
+      }
+
+      rmesa->setup.tex_cntl_c |= R128_TEX_CACHE_FLUSH;
+      rmesa->dirty |= R128_UPLOAD_CONTEXT;
+      t->base.dirty_images[0] = 0;
+   }
+}
diff --git a/src/mesa/drivers/dri/r128/r128_texobj.h b/src/mesa/drivers/dri/r128/r128_texobj.h
new file mode 100644 (file)
index 0000000..e2ff1ac
--- /dev/null
@@ -0,0 +1,69 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_texobj.h,v 1.5 2002/02/22 21:44:58 dawes Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+                                               Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#ifndef _R128_TEXOBJ_H_
+#define _R128_TEXOBJ_H_
+
+#include "r128_sarea.h"
+#include "mm.h"
+
+/* Individual texture image information.
+ */
+typedef struct {
+    GLuint offset;                     /* Relative to local texture space */
+    GLuint width;
+    GLuint height;
+} r128TexImage;
+
+typedef struct r128_tex_obj r128TexObj, *r128TexObjPtr;
+
+/* Texture object in locally shared texture space.
+ */
+struct r128_tex_obj {
+   driTextureObject   base;
+
+   CARD32 bufAddr;                     /* Offset to start of locally
+                                          shared texture block */
+
+   GLuint age;
+   r128TexImage image[R128_MAX_TEXTURE_LEVELS]; /* Image data for all
+                                                  mipmap levels */
+
+   CARD32 textureFormat;               /* Actual hardware format */
+
+   r128_texture_regs_t setup;          /* Setup regs for texture */
+};
+
+#endif /* _R128_TEXOBJ_H_ */
diff --git a/src/mesa/drivers/dri/r128/r128_texstate.c b/src/mesa/drivers/dri/r128/r128_texstate.c
new file mode 100644 (file)
index 0000000..3f4347b
--- /dev/null
@@ -0,0 +1,652 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tex.c,v 1.7 2001/01/08 01:07:21 martin Exp $ */
+/**************************************************************************
+
+Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
+                                               Cedar Park, Texas.
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Gareth Hughes <gareth@valinux.com>
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Brian Paul <brianp@valinux.com>
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "context.h"
+#include "macros.h"
+#include "texformat.h"
+
+#include "r128_context.h"
+#include "r128_state.h"
+#include "r128_ioctl.h"
+#include "r128_vb.h"
+#include "r128_tris.h"
+#include "r128_tex.h"
+
+
+static void r128SetTexImages( r128ContextPtr rmesa,
+                              const struct gl_texture_object *tObj )
+{
+   r128TexObjPtr t = (r128TexObjPtr) tObj->DriverData;
+   struct gl_texture_image *baseImage = tObj->Image[tObj->BaseLevel];
+   int log2Pitch, log2Height, log2Size, log2MinSize;
+   int totalSize;
+   int i;
+   GLint firstLevel, lastLevel;
+
+   assert(t);
+   assert(baseImage);
+
+   if ( R128_DEBUG & DEBUG_VERBOSE_API )
+      fprintf( stderr, "%s( %p )\n", __FUNCTION__, tObj );
+
+   switch (baseImage->TexFormat->MesaFormat) {
+   case MESA_FORMAT_ARGB8888:
+      t->textureFormat = R128_DATATYPE_ARGB8888;
+      break;
+   case MESA_FORMAT_ARGB4444:
+      t->textureFormat = R128_DATATYPE_ARGB4444;
+      break;
+   case MESA_FORMAT_RGB565:
+      t->textureFormat = R128_DATATYPE_RGB565;
+      break;
+   case MESA_FORMAT_RGB332:
+      t->textureFormat = R128_DATATYPE_RGB8;
+      break;
+   case MESA_FORMAT_CI8:
+      t->textureFormat = R128_DATATYPE_CI8;
+      break;
+   case MESA_FORMAT_YCBCR:
+      t->textureFormat = R128_DATATYPE_YVYU422;
+      break;
+   case MESA_FORMAT_YCBCR_REV:
+      t->textureFormat = R128_DATATYPE_VYUY422;
+      break;
+   default:
+      _mesa_problem(rmesa->glCtx, "Bad texture format in %s", __FUNCTION__);
+   };
+
+   /* Compute which mipmap levels we really want to send to the hardware.
+    * This depends on the base image size, GL_TEXTURE_MIN_LOD,
+    * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
+    * Yes, this looks overly complicated, but it's all needed.
+    */
+   firstLevel = tObj->BaseLevel + (GLint) (tObj->MinLod + 0.5);
+   firstLevel = MAX2(firstLevel, tObj->BaseLevel);
+   lastLevel = tObj->BaseLevel + (GLint) (tObj->MaxLod + 0.5);
+   lastLevel = MAX2(lastLevel, tObj->BaseLevel);
+   lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
+   lastLevel = MIN2(lastLevel, tObj->MaxLevel);
+   lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
+
+   log2Pitch = tObj->Image[firstLevel]->WidthLog2;
+   log2Height = tObj->Image[firstLevel]->HeightLog2;
+   log2Size = MAX2(log2Pitch, log2Height);
+   log2MinSize = log2Size;
+
+   t->base.dirty_images[0] = 0;
+   totalSize = 0;
+   for ( i = firstLevel; i <= lastLevel; i++ ) {
+      const struct gl_texture_image *texImage;
+
+      texImage = tObj->Image[i];
+      if ( !texImage || !texImage->Data ) {
+         lastLevel = i - 1;
+        break;
+      }
+
+      log2MinSize = texImage->MaxLog2;
+
+      t->image[i - firstLevel].offset = totalSize;
+      t->image[i - firstLevel].width  = tObj->Image[i]->Width;
+      t->image[i - firstLevel].height = tObj->Image[i]->Height;
+
+      t->base.dirty_images[0] |= (1 << i);
+
+      totalSize += (tObj->Image[i]->Height *
+                   tObj->Image[i]->Width *
+                   tObj->Image[i]->TexFormat->TexelBytes);
+
+      /* Offsets must be 32-byte aligned for host data blits and tiling */
+      totalSize = (totalSize + 31) & ~31;
+   }
+
+   t->base.totalSize = totalSize;
+   t->base.firstLevel = firstLevel;
+   t->base.lastLevel = lastLevel;
+
+   /* Set the texture format */
+   t->setup.tex_cntl &= ~(0xf << 16);
+   t->setup.tex_cntl |= t->textureFormat;
+
+   t->setup.tex_combine_cntl = 0x00000000;  /* XXX is this right? */
+
+   t->setup.tex_size_pitch = ((log2Pitch   << R128_TEX_PITCH_SHIFT) |
+                             (log2Size    << R128_TEX_SIZE_SHIFT) |
+                             (log2Height  << R128_TEX_HEIGHT_SHIFT) |
+                             (log2MinSize << R128_TEX_MIN_SIZE_SHIFT));
+
+   for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
+      t->setup.tex_offset[i]  = 0x00000000;
+   }
+
+   if (firstLevel == lastLevel)
+      t->setup.tex_cntl |= R128_MIP_MAP_DISABLE;
+   else
+      t->setup.tex_cntl &= ~R128_MIP_MAP_DISABLE;
+
+   /* FYI: r128UploadTexImages( rmesa, t ); used to be called here */
+}
+
+
+/* ================================================================
+ * Texture combine functions
+ */
+
+#define COLOR_COMB_DISABLE             (R128_COMB_DIS |                \
+                                        R128_COLOR_FACTOR_TEX)
+#define COLOR_COMB_COPY_INPUT          (R128_COMB_COPY_INP |           \
+                                        R128_COLOR_FACTOR_TEX)
+#define COLOR_COMB_MODULATE            (R128_COMB_MODULATE |           \
+                                        R128_COLOR_FACTOR_TEX)
+#define COLOR_COMB_MODULATE_NTEX       (R128_COMB_MODULATE |           \
+                                        R128_COLOR_FACTOR_NTEX)
+#define COLOR_COMB_ADD                 (R128_COMB_ADD |                \
+                                        R128_COLOR_FACTOR_TEX)
+#define COLOR_COMB_BLEND_TEX           (R128_COMB_BLEND_TEXTURE |      \
+                                        R128_COLOR_FACTOR_TEX)
+/* Rage 128 Pro/M3 only! */
+#define COLOR_COMB_BLEND_COLOR         (R128_COMB_MODULATE2X |         \
+                                        R128_COMB_FCN_MSB |            \
+                                        R128_COLOR_FACTOR_CONST_COLOR)
+
+#define ALPHA_COMB_DISABLE             (R128_COMB_ALPHA_DIS |          \
+                                        R128_ALPHA_FACTOR_TEX_ALPHA)
+#define ALPHA_COMB_COPY_INPUT          (R128_COMB_ALPHA_COPY_INP |     \
+                                        R128_ALPHA_FACTOR_TEX_ALPHA)
+#define ALPHA_COMB_MODULATE            (R128_COMB_ALPHA_MODULATE |     \
+                                        R128_ALPHA_FACTOR_TEX_ALPHA)
+#define ALPHA_COMB_MODULATE_NTEX       (R128_COMB_ALPHA_MODULATE |     \
+                                        R128_ALPHA_FACTOR_NTEX_ALPHA)
+#define ALPHA_COMB_ADD                 (R128_COMB_ALPHA_ADD |          \
+                                        R128_ALPHA_FACTOR_TEX_ALPHA)
+
+#define INPUT_INTERP                   (R128_INPUT_FACTOR_INT_COLOR |  \
+                                        R128_INP_FACTOR_A_INT_ALPHA)
+#define INPUT_PREVIOUS                 (R128_INPUT_FACTOR_PREV_COLOR | \
+                                        R128_INP_FACTOR_A_PREV_ALPHA)
+
+static GLboolean r128UpdateTextureEnv( GLcontext *ctx, int unit )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   GLint source = rmesa->tmu_source[unit];
+   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
+   const struct gl_texture_object *tObj = texUnit->_Current;
+   const GLenum format = tObj->Image[tObj->BaseLevel]->Format;
+   GLuint combine;
+
+   if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
+      fprintf( stderr, "%s( %p, %d )\n",
+              __FUNCTION__, ctx, unit );
+   }
+
+   if ( unit == 0 ) {
+      combine = INPUT_INTERP;
+   } else {
+      combine = INPUT_PREVIOUS;
+   }
+
+   /* Set the texture environment state */
+   switch ( texUnit->EnvMode ) {
+   case GL_REPLACE:
+      switch ( format ) {
+      case GL_RGBA:
+      case GL_LUMINANCE_ALPHA:
+      case GL_INTENSITY:
+        combine |= (COLOR_COMB_DISABLE |               /* C = Ct            */
+                    ALPHA_COMB_DISABLE);               /* A = At            */
+        break;
+      case GL_RGB:
+      case GL_LUMINANCE:
+        combine |= (COLOR_COMB_DISABLE |               /* C = Ct            */
+                    ALPHA_COMB_COPY_INPUT);            /* A = Af            */
+        break;
+      case GL_ALPHA:
+        combine |= (COLOR_COMB_COPY_INPUT |            /* C = Cf            */
+                    ALPHA_COMB_DISABLE);               /* A = At            */
+        break;
+      case GL_COLOR_INDEX:
+      default:
+        return GL_FALSE;
+      }
+      break;
+
+   case GL_MODULATE:
+      switch ( format ) {
+      case GL_RGBA:
+      case GL_LUMINANCE_ALPHA:
+      case GL_INTENSITY:
+        combine |= (COLOR_COMB_MODULATE |              /* C = CfCt          */
+                    ALPHA_COMB_MODULATE);              /* A = AfAt          */
+        break;
+      case GL_RGB:
+      case GL_LUMINANCE:
+        combine |= (COLOR_COMB_MODULATE |              /* C = CfCt          */
+                    ALPHA_COMB_COPY_INPUT);            /* A = Af            */
+        break;
+      case GL_ALPHA:
+        combine |= (COLOR_COMB_COPY_INPUT |            /* C = Cf            */
+                    ALPHA_COMB_MODULATE);              /* A = AfAt          */
+        break;
+      case GL_COLOR_INDEX:
+      default:
+        return GL_FALSE;
+      }
+      break;
+
+   case GL_DECAL:
+      switch ( format ) {
+      case GL_RGBA:
+        combine |= (COLOR_COMB_BLEND_TEX |             /* C = Cf(1-At)+CtAt */
+                    ALPHA_COMB_COPY_INPUT);            /* A = Af            */
+        break;
+      case GL_RGB:
+        combine |= (COLOR_COMB_DISABLE |               /* C = Ct            */
+                    ALPHA_COMB_COPY_INPUT);            /* A = Af            */
+        break;
+      case GL_ALPHA:
+      case GL_LUMINANCE:
+      case GL_LUMINANCE_ALPHA:
+      case GL_INTENSITY:
+        /* Undefined behaviour - just copy the incoming fragment */
+        combine |= (COLOR_COMB_COPY_INPUT |            /* C = undefined     */
+                    ALPHA_COMB_COPY_INPUT);            /* A = undefined     */
+        break;
+      case GL_COLOR_INDEX:
+      default:
+        return GL_FALSE;
+      }
+      break;
+
+   case GL_BLEND:
+      /* Rage 128 Pro and M3 can handle GL_BLEND texturing.
+       */
+      if ( !R128_IS_PLAIN( rmesa ) ) {
+         /* XXX this hasn't been fully tested, I don't have a Pro card. -BP */
+        switch ( format ) {
+        case GL_RGBA:
+        case GL_LUMINANCE_ALPHA:
+           combine |= (COLOR_COMB_BLEND_COLOR |        /* C = Cf(1-Ct)+CcCt */
+                       ALPHA_COMB_MODULATE);           /* A = AfAt          */
+           break;
+
+        case GL_RGB:
+        case GL_LUMINANCE:
+           combine |= (COLOR_COMB_BLEND_COLOR |        /* C = Cf(1-Ct)+CcCt */
+                       ALPHA_COMB_COPY_INPUT);         /* A = Af            */
+           break;
+
+        case GL_ALPHA:
+           combine |= (COLOR_COMB_COPY_INPUT |         /* C = Cf            */
+                       ALPHA_COMB_MODULATE);           /* A = AfAt          */
+           break;
+
+        case GL_INTENSITY:
+           /* GH: We could be smarter about this... */
+           switch ( rmesa->env_color & 0xff000000 ) {
+           case 0x00000000:
+              combine |= (COLOR_COMB_BLEND_COLOR |     /* C = Cf(1-It)+CcIt */
+                          ALPHA_COMB_MODULATE_NTEX);   /* A = Af(1-It)      */
+           default:
+              combine |= (COLOR_COMB_MODULATE |        /* C = fallback      */
+                          ALPHA_COMB_MODULATE);        /* A = fallback      */
+              return GL_FALSE;
+           }
+           break;
+
+        case GL_COLOR_INDEX:
+        default:
+           return GL_FALSE;
+        }
+        break;
+      }
+
+      /* Rage 128 has to fake some cases of GL_BLEND, otherwise fallback
+       * to software rendering.
+       */
+      if ( rmesa->blend_flags ) {
+        return GL_FALSE;
+      }
+      switch ( format ) {
+      case GL_RGBA:
+      case GL_LUMINANCE_ALPHA:
+        switch ( rmesa->env_color & 0x00ffffff ) {
+        case 0x00000000:
+           combine |= (COLOR_COMB_MODULATE_NTEX |      /* C = Cf(1-Ct)      */
+                       ALPHA_COMB_MODULATE);           /* A = AfAt          */
+           break;
+#if 0
+         /* This isn't right - BP */
+        case 0x00ffffff:
+           if ( unit == 0 ) {
+              combine |= (COLOR_COMB_MODULATE_NTEX |   /* C = Cf(1-Ct)      */
+                          ALPHA_COMB_MODULATE);        /* A = AfAt          */
+           } else {
+              combine |= (COLOR_COMB_ADD |             /* C = Cf+Ct         */
+                          ALPHA_COMB_COPY_INPUT);      /* A = Af            */
+           }
+           break;
+#endif
+        default:
+           combine |= (COLOR_COMB_MODULATE |           /* C = fallback      */
+                       ALPHA_COMB_MODULATE);           /* A = fallback      */
+           return GL_FALSE;
+        }
+        break;
+      case GL_RGB:
+      case GL_LUMINANCE:
+        switch ( rmesa->env_color & 0x00ffffff ) {
+        case 0x00000000:
+           combine |= (COLOR_COMB_MODULATE_NTEX |      /* C = Cf(1-Ct)      */
+                       ALPHA_COMB_COPY_INPUT);         /* A = Af            */
+           break;
+#if 0
+         /* This isn't right - BP */
+        case 0x00ffffff:
+           if ( unit == 0 ) {
+              combine |= (COLOR_COMB_MODULATE_NTEX |   /* C = Cf(1-Ct)      */
+                          ALPHA_COMB_COPY_INPUT);      /* A = Af            */
+           } else {
+              combine |= (COLOR_COMB_ADD |             /* C = Cf+Ct         */
+                          ALPHA_COMB_COPY_INPUT);      /* A = Af            */
+           }
+           break;
+#endif
+        default:
+           combine |= (COLOR_COMB_MODULATE |           /* C = fallback      */
+                       ALPHA_COMB_COPY_INPUT);         /* A = fallback      */
+           return GL_FALSE;
+        }
+        break;
+      case GL_ALPHA:
+        if ( unit == 0 ) {
+           combine |= (COLOR_COMB_COPY_INPUT |         /* C = Cf            */
+                       ALPHA_COMB_MODULATE);           /* A = AfAt          */
+        } else {
+           combine |= (COLOR_COMB_COPY_INPUT |         /* C = Cf            */
+                       ALPHA_COMB_COPY_INPUT);         /* A = Af            */
+        }
+        break;
+      case GL_INTENSITY:
+        switch ( rmesa->env_color & 0x00ffffff ) {
+        case 0x00000000:
+           combine |= COLOR_COMB_MODULATE_NTEX;        /* C = Cf(1-It)      */
+           break;
+#if 0
+         /* This isn't right - BP */
+        case 0x00ffffff:
+           if ( unit == 0 ) {
+              combine |= COLOR_COMB_MODULATE_NTEX;     /* C = Cf(1-It)      */
+           } else {
+              combine |= COLOR_COMB_ADD;               /* C = Cf+It         */
+           }
+           break;
+#endif
+        default:
+           combine |= (COLOR_COMB_MODULATE |           /* C = fallback      */
+                       ALPHA_COMB_MODULATE);           /* A = fallback      */
+           return GL_FALSE;
+        }
+        switch ( rmesa->env_color & 0xff000000 ) {
+        case 0x00000000:
+           combine |= ALPHA_COMB_MODULATE_NTEX;        /* A = Af(1-It)      */
+           break;
+#if 0
+         /* This isn't right - BP */
+        case 0xff000000:
+           if ( unit == 0 ) {
+              combine |= ALPHA_COMB_MODULATE_NTEX;     /* A = Af(1-It)      */
+           } else {
+              combine |= ALPHA_COMB_ADD;               /* A = Af+It         */
+           }
+           break;
+#endif
+        default:
+           combine |= (COLOR_COMB_MODULATE |           /* C = fallback      */
+                       ALPHA_COMB_MODULATE);           /* A = fallback      */
+           return GL_FALSE;
+        }
+        break;
+      case GL_COLOR_INDEX:
+      default:
+        return GL_FALSE;
+      }
+      break;
+
+   case GL_ADD:
+      switch ( format ) {
+      case GL_RGBA:
+      case GL_LUMINANCE_ALPHA:
+        combine |= (COLOR_COMB_ADD |                   /* C = Cf+Ct         */
+                    ALPHA_COMB_MODULATE);              /* A = AfAt          */
+        break;
+      case GL_RGB:
+      case GL_LUMINANCE:
+        combine |= (COLOR_COMB_ADD |                   /* C = Cf+Ct         */
+                    ALPHA_COMB_COPY_INPUT);            /* A = Af            */
+        break;
+      case GL_ALPHA:
+        combine |= (COLOR_COMB_COPY_INPUT |            /* C = Cf            */
+                    ALPHA_COMB_MODULATE);              /* A = AfAt          */
+        break;
+      case GL_INTENSITY:
+        combine |= (COLOR_COMB_ADD |                   /* C = Cf+Ct         */
+                    ALPHA_COMB_ADD);                   /* A = Af+At         */
+        break;
+      case GL_COLOR_INDEX:
+      default:
+        return GL_FALSE;
+      }
+      break;
+
+   default:
+      return GL_FALSE;
+   }
+
+   if ( rmesa->tex_combine[unit] != combine ) {
+     rmesa->tex_combine[unit] = combine;
+     rmesa->dirty |= R128_UPLOAD_TEX0 << unit;
+   }
+   return GL_TRUE;
+}
+
+static void disable_tex( GLcontext *ctx, int unit )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   FLUSH_BATCH( rmesa );
+
+   if ( rmesa->CurrentTexObj[unit] ) {
+      rmesa->CurrentTexObj[unit]->base.bound &= ~(1 << unit);
+      rmesa->CurrentTexObj[unit] = NULL;
+   }
+
+   rmesa->setup.tex_cntl_c &= ~(R128_TEXMAP_ENABLE << unit);
+   rmesa->setup.tex_size_pitch_c &= ~(R128_TEX_SIZE_PITCH_MASK << 
+                                     (R128_SEC_TEX_SIZE_PITCH_SHIFT * unit));
+   rmesa->dirty |= R128_UPLOAD_CONTEXT;
+
+   /* If either texture unit is disabled, then multitexturing is not
+    * happening.
+    */
+
+   rmesa->blend_flags &= ~R128_BLEND_MULTITEX;
+}
+
+static GLboolean enable_tex_2d( GLcontext *ctx, int unit )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   const int source = rmesa->tmu_source[unit];
+   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
+   const struct gl_texture_object *tObj = texUnit->_Current;
+   r128TexObjPtr t = (r128TexObjPtr) tObj->DriverData;
+
+   /* Need to load the 2d images associated with this unit.
+    */
+   if ( t->base.dirty_images[0] ) {
+      /* FIXME: For Radeon, RADEON_FIREVERTICES is called here.  Should
+       * FIXME: something similar be done for R128?
+       */
+      /*  FLUSH_BATCH( rmesa ); */
+
+      r128SetTexImages( rmesa, tObj );
+      r128UploadTexImages( rmesa, t );
+      if ( !t->base.memBlock ) 
+         return GL_FALSE;
+   }
+
+   return GL_TRUE;
+}
+
+static GLboolean update_tex_common( GLcontext *ctx, int unit )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   const int source = rmesa->tmu_source[unit];
+   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
+   const struct gl_texture_object *tObj = texUnit->_Current;
+   r128TexObjPtr t = (r128TexObjPtr) tObj->DriverData;
+
+
+   /* Fallback if there's a texture border */
+   if ( tObj->Image[tObj->BaseLevel]->Border > 0 ) {
+      return GL_FALSE;
+   }
+
+
+   /* Update state if this is a different texture object to last
+    * time.
+    */
+   if ( rmesa->CurrentTexObj[unit] != t ) {
+      if ( rmesa->CurrentTexObj[unit] != NULL ) {
+        /* The old texture is no longer bound to this texture unit.
+         * Mark it as such.
+         */
+
+        rmesa->CurrentTexObj[unit]->base.bound &= 
+            ~(1UL << unit);
+      }
+
+      rmesa->CurrentTexObj[unit] = t;
+      t->base.bound |= (1UL << unit);
+      rmesa->dirty |= R128_UPLOAD_TEX0 << unit;
+
+      driUpdateTextureLRU( (driTextureObject *) t ); /* XXX: should be locked! */
+   }
+
+   /* FIXME: We need to update the texture unit if any texture parameters have
+    * changed, but this texture was already bound.  This could be changed to
+    * work like the Radeon driver where the texture object has it's own
+    * dirty state flags
+    */
+   rmesa->dirty |= R128_UPLOAD_TEX0 << unit;
+
+   /* register setup */
+   rmesa->setup.tex_size_pitch_c &= ~(R128_TEX_SIZE_PITCH_MASK << 
+                                     (R128_SEC_TEX_SIZE_PITCH_SHIFT * unit));
+
+   if ( unit == 0 ) {
+      rmesa->setup.tex_cntl_c       |= R128_TEXMAP_ENABLE;
+      rmesa->setup.tex_size_pitch_c |= t->setup.tex_size_pitch << 0;
+      rmesa->setup.scale_3d_cntl    &= ~R128_TEX_CACHE_SPLIT;
+      t->setup.tex_cntl             &= ~R128_SEC_SELECT_SEC_ST;
+   }
+   else {
+      rmesa->setup.tex_cntl_c       |= R128_SEC_TEXMAP_ENABLE;
+      rmesa->setup.tex_size_pitch_c |= t->setup.tex_size_pitch << 16;
+      rmesa->setup.scale_3d_cntl    |= R128_TEX_CACHE_SPLIT;
+      t->setup.tex_cntl             |=  R128_SEC_SELECT_SEC_ST;
+
+      /* If the second TMU is enabled, then multitexturing is happening.
+       */
+      if ( R128_IS_PLAIN( rmesa ) )
+         rmesa->blend_flags            |= R128_BLEND_MULTITEX;
+   }
+
+   rmesa->dirty |= R128_UPLOAD_CONTEXT;
+
+
+   /* FIXME: The Radeon has some cached state so that it can avoid calling
+    * FIXME: UpdateTextureEnv in some cases.  Is that possible here?
+    */
+   return r128UpdateTextureEnv( ctx, unit );
+}
+
+static GLboolean updateTextureUnit( GLcontext *ctx, int unit )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   const int source = rmesa->tmu_source[unit];
+   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
+
+
+   if (texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) {
+      return (enable_tex_2d( ctx, unit ) &&
+             update_tex_common( ctx, unit ));
+   }
+   else if ( texUnit->_ReallyEnabled ) {
+      return GL_FALSE;
+   }
+   else {
+      disable_tex( ctx, unit );
+      return GL_TRUE;
+   }
+}
+
+
+void r128UpdateTextureState( GLcontext *ctx )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   GLboolean ok;
+
+
+   /* This works around a quirk with the R128 hardware.  If only OpenGL 
+    * TEXTURE1 is enabled, then the hardware TEXTURE0 must be used.  The
+    * hardware TEXTURE1 can ONLY be used when hardware TEXTURE0 is also used.
+    */
+
+   rmesa->tmu_source[0] = 0;
+   rmesa->tmu_source[1] = 1;
+
+   if ((ctx->Texture._EnabledUnits & 0x03) == 0x02) {
+      /* only texture 1 enabled */
+      rmesa->tmu_source[0] = 1;
+      rmesa->tmu_source[1] = 0;
+   }
+
+   ok = (updateTextureUnit( ctx, 0 ) &&
+        updateTextureUnit( ctx, 1 ));
+
+   FALLBACK( rmesa, R128_FALLBACK_TEXTURE, !ok );
+}
diff --git a/src/mesa/drivers/dri/r128/r128_tris.c b/src/mesa/drivers/dri/r128/r128_tris.c
new file mode 100644 (file)
index 0000000..4e28602
--- /dev/null
@@ -0,0 +1,721 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tris.c,v 1.8 2002/10/30 12:51:43 alanh Exp $ */ /* -*- c-basic-offset: 3 -*- */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#include "glheader.h"
+#include "mtypes.h"
+#include "colormac.h"
+#include "macros.h"
+
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+#include "r128_tris.h"
+#include "r128_state.h"
+#include "r128_tex.h"
+#include "r128_vb.h"
+#include "r128_ioctl.h"
+
+static const GLuint hw_prim[GL_POLYGON+1] = {
+   R128_CCE_VC_CNTL_PRIM_TYPE_POINT,
+   R128_CCE_VC_CNTL_PRIM_TYPE_LINE,
+   R128_CCE_VC_CNTL_PRIM_TYPE_LINE,
+   R128_CCE_VC_CNTL_PRIM_TYPE_LINE,
+   R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
+   R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
+   R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
+   R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
+   R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
+   R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
+};
+
+static void r128RasterPrimitive( GLcontext *ctx, GLuint hwprim );
+static void r128RenderPrimitive( GLcontext *ctx, GLenum prim );
+
+
+/***********************************************************************
+ *                    Emit primitives as inline vertices               *
+ ***********************************************************************/
+
+#if defined(USE_X86_ASM)
+#define COPY_DWORDS( j, vb, vertsize, v )                              \
+do {                                                                   \
+       int __tmp;                                                      \
+       __asm__ __volatile__( "rep ; movsl"                             \
+                             : "=%c" (j), "=D" (vb), "=S" (__tmp)      \
+                             : "0" (vertsize),                         \
+                               "D" ((long)vb),                         \
+                               "S" ((long)v) );                        \
+} while (0)
+#else
+#define COPY_DWORDS( j, vb, vertsize, v )                              \
+do {                                                                   \
+   for ( j = 0 ; j < vertsize ; j++ )                                  \
+      vb[j] = CPU_TO_LE32(((GLuint *)v)[j]);                           \
+   vb += vertsize;                                                     \
+} while (0)
+#endif
+
+static __inline void r128_draw_quad( r128ContextPtr rmesa,
+                                    r128VertexPtr v0,
+                                    r128VertexPtr v1,
+                                    r128VertexPtr v2,
+                                    r128VertexPtr v3 )
+{
+   GLuint vertsize = rmesa->vertex_size;
+   GLuint *vb = (GLuint *)r128AllocDmaLow( rmesa, 6 * vertsize * 4 );
+   GLuint j;
+
+   rmesa->num_verts += 6;
+   COPY_DWORDS( j, vb, vertsize, v0 );
+   COPY_DWORDS( j, vb, vertsize, v1 );
+   COPY_DWORDS( j, vb, vertsize, v3 );
+   COPY_DWORDS( j, vb, vertsize, v1 );
+   COPY_DWORDS( j, vb, vertsize, v2 );
+   COPY_DWORDS( j, vb, vertsize, v3 );
+}
+
+
+static __inline void r128_draw_triangle( r128ContextPtr rmesa,
+                                        r128VertexPtr v0,
+                                        r128VertexPtr v1,
+                                        r128VertexPtr v2 )
+{
+   GLuint vertsize = rmesa->vertex_size;
+   GLuint *vb = (GLuint *)r128AllocDmaLow( rmesa, 3 * vertsize * 4 );
+   GLuint j;
+
+   rmesa->num_verts += 3;
+   COPY_DWORDS( j, vb, vertsize, v0 );
+   COPY_DWORDS( j, vb, vertsize, v1 );
+   COPY_DWORDS( j, vb, vertsize, v2 );
+}
+
+static __inline void r128_draw_line( r128ContextPtr rmesa,
+                                    r128VertexPtr v0,
+                                    r128VertexPtr v1 )
+{
+   GLuint vertsize = rmesa->vertex_size;
+   GLuint *vb = (GLuint *)r128AllocDmaLow( rmesa, 2 * vertsize * 4 );
+   GLuint j;
+
+   rmesa->num_verts += 2;
+   COPY_DWORDS( j, vb, vertsize, v0 );
+   COPY_DWORDS( j, vb, vertsize, v1 );
+}
+
+static __inline void r128_draw_point( r128ContextPtr rmesa,
+                                     r128VertexPtr v0 )
+{
+   int vertsize = rmesa->vertex_size;
+   GLuint *vb = (GLuint *)r128AllocDmaLow( rmesa, vertsize * 4 );
+   int j;
+
+   rmesa->num_verts += 1;
+   COPY_DWORDS( j, vb, vertsize, v0 );
+}
+
+/***********************************************************************
+ *          Macros for t_dd_tritmp.h to draw basic primitives          *
+ ***********************************************************************/
+
+#define TRI( a, b, c )                         \
+do {                                           \
+   if (DO_FALLBACK)                            \
+      rmesa->draw_tri( rmesa, a, b, c );       \
+   else                                                \
+      r128_draw_triangle( rmesa, a, b, c );    \
+} while (0)
+
+#define QUAD( a, b, c, d )                     \
+do {                                           \
+   if (DO_FALLBACK) {                          \
+      rmesa->draw_tri( rmesa, a, b, d );       \
+      rmesa->draw_tri( rmesa, b, c, d );       \
+   } else                                      \
+      r128_draw_quad( rmesa, a, b, c, d );     \
+} while (0)
+
+#define LINE( v0, v1 )                         \
+do {                                           \
+   if (DO_FALLBACK)                            \
+      rmesa->draw_line( rmesa, v0, v1 );       \
+   else                                        \
+      r128_draw_line( rmesa, v0, v1 ); \
+} while (0)
+
+#define POINT( v0 )                            \
+do {                                           \
+   if (DO_FALLBACK)                            \
+      rmesa->draw_point( rmesa, v0 );          \
+   else                                        \
+      r128_draw_point( rmesa, v0 );            \
+} while (0)
+
+
+/***********************************************************************
+ *              Build render functions from dd templates               *
+ ***********************************************************************/
+
+#define R128_OFFSET_BIT        0x01
+#define R128_TWOSIDE_BIT       0x02
+#define R128_UNFILLED_BIT      0x04
+#define R128_FALLBACK_BIT      0x08
+#define R128_MAX_TRIFUNC       0x10
+
+
+static struct {
+   points_func         points;
+   line_func           line;
+   triangle_func       triangle;
+   quad_func           quad;
+} rast_tab[R128_MAX_TRIFUNC];
+
+
+#define DO_FALLBACK (IND & R128_FALLBACK_BIT)
+#define DO_OFFSET   (IND & R128_OFFSET_BIT)
+#define DO_UNFILLED (IND & R128_UNFILLED_BIT)
+#define DO_TWOSIDE  (IND & R128_TWOSIDE_BIT)
+#define DO_FLAT      0
+#define DO_TRI       1
+#define DO_QUAD      1
+#define DO_LINE      1
+#define DO_POINTS    1
+#define DO_FULL_QUAD 1
+
+#define HAVE_RGBA   1
+#define HAVE_SPEC   1
+#define HAVE_BACK_COLORS  0
+#define HAVE_HW_FLATSHADE 1
+#define VERTEX r128Vertex
+#define TAB rast_tab
+
+#define DEPTH_SCALE 1.0
+#define UNFILLED_TRI unfilled_tri
+#define UNFILLED_QUAD unfilled_quad
+#define VERT_X(_v) _v->v.x
+#define VERT_Y(_v) _v->v.y
+#define VERT_Z(_v) _v->v.z
+#define AREA_IS_CCW( a ) (a > 0)
+#define GET_VERTEX(e) (rmesa->verts + (e<<rmesa->vertex_stride_shift))
+
+#define VERT_SET_RGBA( v, c )  do {                            \
+                                       r128_color_t *vc = (r128_color_t *)&(v)->ui[coloroffset];       \
+                                       vc->blue  = (c)[2];     \
+                                       vc->green = (c)[1];     \
+                                       vc->red   = (c)[0];     \
+                                       vc->alpha = (c)[3];     \
+                               } while (0)
+#define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
+#define VERT_SAVE_RGBA( idx )    color[idx] = v[idx]->ui[coloroffset]
+#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
+
+#define VERT_SET_SPEC( v0, c )   if (havespec) {                       \
+                                       (v0)->v.specular.red   = (c)[0];\
+                                       (v0)->v.specular.green = (c)[1];\
+                                       (v0)->v.specular.blue  = (c)[2]; }
+#define VERT_COPY_SPEC( v0, v1 ) if (havespec) {                                       \
+                                       (v0)->v.specular.red   = v1->v.specular.red;    \
+                                       (v0)->v.specular.green = v1->v.specular.green;  \
+                                       (v0)->v.specular.blue  = v1->v.specular.blue; }
+
+#define VERT_SAVE_SPEC( idx )    if (havespec) spec[idx] = v[idx]->ui[5]
+#define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = spec[idx]
+
+#define LOCAL_VARS(n)                                          \
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);                   \
+   GLuint color[n], spec[n];                                   \
+   GLuint coloroffset = (rmesa->vertex_size == 4 ? 3 : 4);     \
+   GLboolean havespec = (rmesa->vertex_size == 4 ? 0 : 1);     \
+   (void) color; (void) spec; (void) coloroffset; (void) havespec;
+
+/***********************************************************************
+ *                Helpers for rendering unfilled primitives            *
+ ***********************************************************************/
+
+#define RASTERIZE(x) if (rmesa->hw_primitive != hw_prim[x]) \
+                        r128RasterPrimitive( ctx, hw_prim[x] )
+#define RENDER_PRIMITIVE rmesa->render_primitive
+#define IND R128_FALLBACK_BIT
+#define TAG(x) x
+#include "tnl_dd/t_dd_unfilled.h"
+#undef IND
+
+
+/***********************************************************************
+ *                      Generate GL render functions                   *
+ ***********************************************************************/
+
+
+#define IND (0)
+#define TAG(x) x
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_OFFSET_BIT)
+#define TAG(x) x##_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_TWOSIDE_BIT)
+#define TAG(x) x##_twoside
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT)
+#define TAG(x) x##_twoside_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_UNFILLED_BIT)
+#define TAG(x) x##_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_OFFSET_BIT|R128_UNFILLED_BIT)
+#define TAG(x) x##_offset_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_TWOSIDE_BIT|R128_UNFILLED_BIT)
+#define TAG(x) x##_twoside_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT|R128_UNFILLED_BIT)
+#define TAG(x) x##_twoside_offset_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_FALLBACK_BIT)
+#define TAG(x) x##_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_OFFSET_BIT|R128_FALLBACK_BIT)
+#define TAG(x) x##_offset_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_TWOSIDE_BIT|R128_FALLBACK_BIT)
+#define TAG(x) x##_twoside_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT|R128_FALLBACK_BIT)
+#define TAG(x) x##_twoside_offset_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_UNFILLED_BIT|R128_FALLBACK_BIT)
+#define TAG(x) x##_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_OFFSET_BIT|R128_UNFILLED_BIT|R128_FALLBACK_BIT)
+#define TAG(x) x##_offset_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_TWOSIDE_BIT|R128_UNFILLED_BIT|R128_FALLBACK_BIT)
+#define TAG(x) x##_twoside_unfilled_fallback
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT|R128_UNFILLED_BIT| \
+            R128_FALLBACK_BIT)
+#define TAG(x) x##_twoside_offset_unfilled_fallback
+#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();
+   init_fallback();
+   init_offset_fallback();
+   init_twoside_fallback();
+   init_twoside_offset_fallback();
+   init_unfilled_fallback();
+   init_offset_unfilled_fallback();
+   init_twoside_unfilled_fallback();
+   init_twoside_offset_unfilled_fallback();
+}
+
+
+
+/***********************************************************************
+ *                    Rasterization fallback helpers                   *
+ ***********************************************************************/
+
+
+/* This code is hit only when a mix of accelerated and unaccelerated
+ * primitives are being drawn, and only for the unaccelerated
+ * primitives.
+ */
+static void
+r128_fallback_tri( r128ContextPtr rmesa,
+                    r128Vertex *v0,
+                    r128Vertex *v1,
+                    r128Vertex *v2 )
+{
+   GLcontext *ctx = rmesa->glCtx;
+   SWvertex v[3];
+   r128_translate_vertex( ctx, v0, &v[0] );
+   r128_translate_vertex( ctx, v1, &v[1] );
+   r128_translate_vertex( ctx, v2, &v[2] );
+   _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
+}
+
+
+static void
+r128_fallback_line( r128ContextPtr rmesa,
+                   r128Vertex *v0,
+                   r128Vertex *v1 )
+{
+   GLcontext *ctx = rmesa->glCtx;
+   SWvertex v[2];
+   r128_translate_vertex( ctx, v0, &v[0] );
+   r128_translate_vertex( ctx, v1, &v[1] );
+   _swrast_Line( ctx, &v[0], &v[1] );
+}
+
+
+static void
+r128_fallback_point( r128ContextPtr rmesa,
+                    r128Vertex *v0 )
+{
+   GLcontext *ctx = rmesa->glCtx;
+   SWvertex v[1];
+   r128_translate_vertex( ctx, v0, &v[0] );
+   _swrast_Point( ctx, &v[0] );
+}
+
+
+
+/**********************************************************************/
+/*               Render unclipped begin/end objects                   */
+/**********************************************************************/
+
+#define VERT(x) (r128Vertex *)(r128verts + (x << shift))
+#define RENDER_POINTS( start, count )          \
+   for ( ; start < count ; start++)            \
+      r128_draw_point( rmesa, VERT(start) )
+#define RENDER_LINE( v0, v1 ) \
+   r128_draw_line( rmesa, VERT(v0), VERT(v1) )
+#define RENDER_TRI( v0, v1, v2 )  \
+   r128_draw_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) )
+#define RENDER_QUAD( v0, v1, v2, v3 ) \
+   r128_draw_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
+#define INIT(x) do {                                   \
+   if (0) fprintf(stderr, "%s\n", __FUNCTION__);       \
+   r128RenderPrimitive( ctx, x );                      \
+} while (0)
+#undef LOCAL_VARS
+#define LOCAL_VARS                                             \
+    r128ContextPtr rmesa = R128_CONTEXT(ctx);          \
+    const GLuint shift = rmesa->vertex_stride_shift;           \
+    const char *r128verts = (char *)rmesa->verts;              \
+    const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;      \
+    (void) elt;
+#define RESET_STIPPLE
+#define RESET_OCCLUSION
+#define PRESERVE_VB_DEFS
+#define ELT(x) (x)
+#define TAG(x) r128_##x##_verts
+#include "tnl/t_vb_rendertmp.h"
+#undef ELT
+#undef TAG
+#define TAG(x) r128_##x##_elts
+#define ELT(x) elt[x]
+#include "tnl/t_vb_rendertmp.h"
+
+
+/**********************************************************************/
+/*                    Render clipped primitives                       */
+/**********************************************************************/
+
+static void r128RenderClippedPoly( GLcontext *ctx, const GLuint *elts,
+                                    GLuint n )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+   /* 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;
+   }
+}
+
+static void r128RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   tnl->Driver.Render.Line( ctx, ii, jj );
+}
+
+static void r128FastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
+                                        GLuint n )
+{
+   r128ContextPtr rmesa = R128_CONTEXT( ctx );
+   GLuint vertsize = rmesa->vertex_size;
+   GLuint *vb = r128AllocDmaLow( rmesa, (n-2) * 3 * 4 * vertsize );
+   GLubyte *r128verts = (GLubyte *)rmesa->verts;
+   const GLuint shift = rmesa->vertex_stride_shift;
+   const GLuint *start = (const GLuint *)VERT(elts[0]);
+   int i,j;
+
+   rmesa->num_verts += (n-2) * 3;
+
+   for (i = 2 ; i < n ; i++) {
+      COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i-1]) );
+      COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i]) );
+      COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) start );
+   }
+}
+
+
+
+
+/**********************************************************************/
+/*                    Choose render functions                         */
+/**********************************************************************/
+
+#define _R128_NEW_RENDER_STATE (_DD_NEW_LINE_STIPPLE | \
+                                 _DD_NEW_LINE_SMOOTH |         \
+                                 _DD_NEW_POINT_SMOOTH |        \
+                                 _DD_NEW_TRI_SMOOTH |          \
+                                 _DD_NEW_TRI_UNFILLED |        \
+                                 _DD_NEW_TRI_LIGHT_TWOSIDE |   \
+                                 _DD_NEW_TRI_OFFSET)           \
+
+
+#define POINT_FALLBACK (DD_POINT_SMOOTH)
+#define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
+#define TRI_FALLBACK (DD_TRI_SMOOTH)
+#define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
+#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
+
+
+static void r128ChooseRenderState(GLcontext *ctx)
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   GLuint flags = ctx->_TriangleCaps;
+   GLuint index = 0;
+
+   if (flags & (ANY_RASTER_FLAGS|ANY_FALLBACK_FLAGS)) {
+      rmesa->draw_point = r128_draw_point;
+      rmesa->draw_line = r128_draw_line;
+      rmesa->draw_tri = r128_draw_triangle;
+
+      if (flags & ANY_RASTER_FLAGS) {
+        if (flags & DD_TRI_LIGHT_TWOSIDE) index |= R128_TWOSIDE_BIT;
+        if (flags & DD_TRI_OFFSET)        index |= R128_OFFSET_BIT;
+        if (flags & DD_TRI_UNFILLED)      index |= R128_UNFILLED_BIT;
+      }
+
+      /* Hook in fallbacks for specific primitives.
+       */
+      if (flags & (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)) {
+        if (flags & POINT_FALLBACK) rmesa->draw_point = r128_fallback_point;
+        if (flags & LINE_FALLBACK)  rmesa->draw_line = r128_fallback_line;
+        if (flags & TRI_FALLBACK)   rmesa->draw_tri = r128_fallback_tri;
+        index |= R128_FALLBACK_BIT;
+      }
+   }
+
+   if (index != rmesa->RenderIndex) {
+      TNLcontext *tnl = TNL_CONTEXT(ctx);
+      tnl->Driver.Render.Points = rast_tab[index].points;
+      tnl->Driver.Render.Line = rast_tab[index].line;
+      tnl->Driver.Render.Triangle = rast_tab[index].triangle;
+      tnl->Driver.Render.Quad = rast_tab[index].quad;
+
+      if (index == 0) {
+        tnl->Driver.Render.PrimTabVerts = r128_render_tab_verts;
+        tnl->Driver.Render.PrimTabElts = r128_render_tab_elts;
+        tnl->Driver.Render.ClippedLine = rast_tab[index].line;
+        tnl->Driver.Render.ClippedPolygon = r128FastRenderClippedPoly;
+      } else {
+        tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
+        tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
+        tnl->Driver.Render.ClippedLine = r128RenderClippedLine;
+        tnl->Driver.Render.ClippedPolygon = r128RenderClippedPoly;
+      }
+
+      rmesa->RenderIndex = index;
+   }
+}
+
+/**********************************************************************/
+/*                 Validate state at pipeline start                   */
+/**********************************************************************/
+
+static void r128RunPipeline( GLcontext *ctx )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   if (rmesa->new_state || rmesa->NewGLState & _NEW_TEXTURE)
+      r128DDUpdateHWState( ctx );
+
+   if (!rmesa->Fallback && rmesa->NewGLState) {
+      if (rmesa->NewGLState & _R128_NEW_VERTEX_STATE)
+        r128ChooseVertexState( ctx );
+
+      if (rmesa->NewGLState & _R128_NEW_RENDER_STATE)
+        r128ChooseRenderState( ctx );
+
+      rmesa->NewGLState = 0;
+   }
+
+   _tnl_run_pipeline( ctx );
+}
+
+/**********************************************************************/
+/*                 High level hooks for t_vb_render.c                 */
+/**********************************************************************/
+
+/* This is called when Mesa switches between rendering triangle
+ * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
+ * and lines, points and bitmaps.
+ *
+ * As the r128 uses triangles to render lines and points, it is
+ * necessary to turn off hardware culling when rendering these
+ * primitives.
+ */
+
+static void r128RasterPrimitive( GLcontext *ctx, GLuint hwprim )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+
+   rmesa->setup.dp_gui_master_cntl_c &= ~R128_GMC_BRUSH_NONE;
+
+   if ( ctx->Polygon.StippleFlag && hwprim == GL_TRIANGLES ) {
+      rmesa->setup.dp_gui_master_cntl_c |= R128_GMC_BRUSH_32x32_MONO_FG_LA;
+   }
+   else {
+      rmesa->setup.dp_gui_master_cntl_c |= R128_GMC_BRUSH_SOLID_COLOR;
+   }
+
+   rmesa->new_state |= R128_NEW_CONTEXT;
+   rmesa->dirty |= R128_UPLOAD_CONTEXT;
+
+   if (rmesa->hw_primitive != hwprim) {
+      FLUSH_BATCH( rmesa );
+      rmesa->hw_primitive = hwprim;
+   }
+}
+
+static void r128RenderPrimitive( GLcontext *ctx, GLenum prim )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   GLuint hw = hw_prim[prim];
+   rmesa->render_primitive = prim;
+   if (prim >= GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
+      return;
+   r128RasterPrimitive( ctx, hw );
+}
+
+
+static void r128RenderStart( GLcontext *ctx )
+{
+   /* Check for projective texturing.  Make sure all texcoord
+    * pointers point to something.  (fix in mesa?)
+    */
+   r128CheckTexSizes( ctx );
+}
+
+static void r128RenderFinish( GLcontext *ctx )
+{
+   if (R128_CONTEXT(ctx)->RenderIndex & R128_FALLBACK_BIT)
+      _swrast_flush( ctx );
+}
+
+
+/**********************************************************************/
+/*           Transition to/from hardware rasterization.               */
+/**********************************************************************/
+
+void r128Fallback( GLcontext *ctx, GLuint bit, GLboolean mode )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   GLuint oldfallback = rmesa->Fallback;
+
+   if (mode) {
+      rmesa->Fallback |= bit;
+      if (oldfallback == 0) {
+        FLUSH_BATCH( rmesa );
+        _swsetup_Wakeup( ctx );
+        rmesa->RenderIndex = ~0;
+      }
+   }
+   else {
+      rmesa->Fallback &= ~bit;
+      if (oldfallback == bit) {
+        _swrast_flush( ctx );
+        tnl->Driver.Render.Start = r128RenderStart;
+        tnl->Driver.Render.PrimitiveNotify = r128RenderPrimitive;
+        tnl->Driver.Render.Finish = r128RenderFinish;
+        tnl->Driver.Render.BuildVertices = r128BuildVertices;
+        rmesa->NewGLState |= (_R128_NEW_RENDER_STATE|
+                              _R128_NEW_VERTEX_STATE);
+      }
+   }
+}
+
+
+/**********************************************************************/
+/*                            Initialization.                         */
+/**********************************************************************/
+
+void r128InitTriFuncs( GLcontext *ctx )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   static int firsttime = 1;
+
+   if (firsttime) {
+      init_rast_tab();
+      firsttime = 0;
+   }
+
+   tnl->Driver.RunPipeline = r128RunPipeline;
+   tnl->Driver.Render.Start = r128RenderStart;
+   tnl->Driver.Render.Finish = r128RenderFinish;
+   tnl->Driver.Render.PrimitiveNotify = r128RenderPrimitive;
+   tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
+   tnl->Driver.Render.BuildVertices = r128BuildVertices;
+   rmesa->NewGLState |= (_R128_NEW_RENDER_STATE|
+                        _R128_NEW_VERTEX_STATE);
+
+/*     r128Fallback( ctx, 0x100000, 1 ); */
+}
diff --git a/src/mesa/drivers/dri/r128/r128_tris.h b/src/mesa/drivers/dri/r128/r128_tris.h
new file mode 100644 (file)
index 0000000..755d332
--- /dev/null
@@ -0,0 +1,48 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tris.h,v 1.8 2002/10/30 12:51:43 alanh Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#ifndef __R128_TRIS_H__
+#define __R128_TRIS_H__
+
+#include "mtypes.h"
+
+extern void r128InitTriFuncs( GLcontext *ctx );
+
+
+extern void r128Fallback( GLcontext *ctx, GLuint bit, GLboolean mode );
+#define FALLBACK( rmesa, bit, mode ) r128Fallback( rmesa->glCtx, bit, mode )
+
+
+#endif /* __R128_TRIS_H__ */
diff --git a/src/mesa/drivers/dri/r128/r128_vb.c b/src/mesa/drivers/dri/r128/r128_vb.c
new file mode 100644 (file)
index 0000000..7738901
--- /dev/null
@@ -0,0 +1,522 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_vb.c,v 1.15 2002/10/30 12:51:43 alanh Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#include "glheader.h"
+#include "mtypes.h"
+#include "imports.h"
+#include "macros.h"
+#include "colormac.h"
+
+#include "swrast_setup/swrast_setup.h"
+#include "tnl/t_context.h"
+
+#include "r128_context.h"
+#include "r128_vb.h"
+#include "r128_ioctl.h"
+#include "r128_tris.h"
+#include "r128_state.h"
+
+
+#define R128_TEX1_BIT       0x1
+#define R128_TEX0_BIT       0x2
+#define R128_RGBA_BIT       0x4
+#define R128_SPEC_BIT       0x8
+#define R128_FOG_BIT       0x10
+#define R128_XYZW_BIT       0x20
+#define R128_PTEX_BIT       0x40
+#define R128_MAX_SETUP      0x80
+
+static struct {
+   void                (*emit)( GLcontext *, GLuint, GLuint, void *, GLuint );
+   interp_func         interp;
+   copy_pv_func                copy_pv;
+   GLboolean           (*check_tex_sizes)( GLcontext *ctx );
+   GLuint               vertex_size;
+   GLuint               vertex_stride_shift;
+   GLuint               vertex_format;
+} setup_tab[R128_MAX_SETUP];
+
+#define TINY_VERTEX_FORMAT             (R128_CCE_VC_FRMT_DIFFUSE_ARGB)
+
+#define NOTEX_VERTEX_FORMAT            (R128_CCE_VC_FRMT_RHW |         \
+                                        R128_CCE_VC_FRMT_DIFFUSE_ARGB |\
+                                        R128_CCE_VC_FRMT_SPEC_FRGB)
+
+#define TEX0_VERTEX_FORMAT             (R128_CCE_VC_FRMT_RHW |         \
+                                        R128_CCE_VC_FRMT_DIFFUSE_ARGB |\
+                                        R128_CCE_VC_FRMT_SPEC_FRGB |   \
+                                        R128_CCE_VC_FRMT_S_T)
+
+#define TEX1_VERTEX_FORMAT             (R128_CCE_VC_FRMT_RHW |         \
+                                        R128_CCE_VC_FRMT_DIFFUSE_ARGB |\
+                                        R128_CCE_VC_FRMT_SPEC_FRGB |   \
+                                        R128_CCE_VC_FRMT_S_T |         \
+                                        R128_CCE_VC_FRMT_S2_T2)
+
+
+#define PROJ_TEX1_VERTEX_FORMAT 0
+#define TEX2_VERTEX_FORMAT      0
+#define TEX3_VERTEX_FORMAT      0
+#define PROJ_TEX3_VERTEX_FORMAT 0
+
+#define DO_XYZW (IND & R128_XYZW_BIT)
+#define DO_RGBA (IND & R128_RGBA_BIT)
+#define DO_SPEC (IND & R128_SPEC_BIT)
+#define DO_FOG  (IND & R128_FOG_BIT)
+#define DO_TEX0 (IND & R128_TEX0_BIT)
+#define DO_TEX1 (IND & R128_TEX1_BIT)
+#define DO_TEX2 0
+#define DO_TEX3 0
+#define DO_PTEX (IND & R128_PTEX_BIT)
+
+#define VERTEX r128Vertex
+#define VERTEX_COLOR r128_color_t
+#define LOCALVARS r128ContextPtr rmesa = R128_CONTEXT(ctx);
+#define GET_VIEWPORT_MAT() rmesa->hw_viewport
+#define GET_TEXSOURCE(n)  rmesa->tmu_source[n]
+#define GET_VERTEX_FORMAT() rmesa->vertex_format
+#define GET_VERTEX_STORE() rmesa->verts
+#define GET_VERTEX_STRIDE_SHIFT() rmesa->vertex_stride_shift
+#define INVALIDATE_STORED_VERTICES()
+#define GET_UBYTE_COLOR_STORE() &rmesa->UbyteColor
+#define GET_UBYTE_SPEC_COLOR_STORE() &rmesa->UbyteSecondaryColor
+
+#define HAVE_HW_VIEWPORT    0
+#define HAVE_HW_DIVIDE      0
+#define HAVE_RGBA_COLOR     0
+#define HAVE_TINY_VERTICES  1
+#define HAVE_NOTEX_VERTICES 1
+#define HAVE_TEX0_VERTICES  1
+#define HAVE_TEX1_VERTICES  1
+#define HAVE_TEX2_VERTICES  0
+#define HAVE_TEX3_VERTICES  0
+#define HAVE_PTEX_VERTICES  0  /* r128 rhw2 not supported by template */
+
+#define UNVIEWPORT_VARS  GLfloat h = R128_CONTEXT(ctx)->driDrawable->h
+#define UNVIEWPORT_X(x)  x - SUBPIXEL_X
+#define UNVIEWPORT_Y(y)  - y + h + SUBPIXEL_Y
+#define UNVIEWPORT_Z(z)  z / rmesa->depth_scale
+
+#define PTEX_FALLBACK() FALLBACK(R128_CONTEXT(ctx), R128_FALLBACK_TEXTURE, 1)
+
+#define IMPORT_FLOAT_COLORS r128_import_float_colors
+#define IMPORT_FLOAT_SPEC_COLORS r128_import_float_spec_colors
+
+#define INTERP_VERTEX setup_tab[rmesa->SetupIndex].interp
+#define COPY_PV_VERTEX setup_tab[rmesa->SetupIndex].copy_pv
+
+/***********************************************************************
+ *         Generate  pv-copying and translation functions              *
+ ***********************************************************************/
+
+#define TAG(x) r128_##x
+#include "tnl_dd/t_dd_vb.c"
+
+/***********************************************************************
+ *             Generate vertex emit and interp functions               *
+ ***********************************************************************/
+
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT)
+#define TAG(x) x##_wg
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_SPEC_BIT)
+#define TAG(x) x##_wgs
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_TEX0_BIT)
+#define TAG(x) x##_wgt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_TEX0_BIT|R128_TEX1_BIT)
+#define TAG(x) x##_wgt0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_TEX0_BIT|R128_PTEX_BIT)
+#define TAG(x) x##_wgpt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT)
+#define TAG(x) x##_wgst0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT|\
+             R128_TEX1_BIT)
+#define TAG(x) x##_wgst0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT|\
+             R128_PTEX_BIT)
+#define TAG(x) x##_wgspt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT)
+#define TAG(x) x##_wgf
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT)
+#define TAG(x) x##_wgfs
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT)
+#define TAG(x) x##_wgft0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT|\
+             R128_TEX1_BIT)
+#define TAG(x) x##_wgft0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT|\
+             R128_PTEX_BIT)
+#define TAG(x) x##_wgfpt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|\
+             R128_TEX0_BIT)
+#define TAG(x) x##_wgfst0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|\
+             R128_TEX0_BIT|R128_TEX1_BIT)
+#define TAG(x) x##_wgfst0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|\
+             R128_TEX0_BIT|R128_PTEX_BIT)
+#define TAG(x) x##_wgfspt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_TEX0_BIT)
+#define TAG(x) x##_t0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_TEX0_BIT|R128_TEX1_BIT)
+#define TAG(x) x##_t0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_FOG_BIT)
+#define TAG(x) x##_f
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_FOG_BIT|R128_TEX0_BIT)
+#define TAG(x) x##_ft0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_FOG_BIT|R128_TEX0_BIT|R128_TEX1_BIT)
+#define TAG(x) x##_ft0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_RGBA_BIT)
+#define TAG(x) x##_g
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_RGBA_BIT|R128_SPEC_BIT)
+#define TAG(x) x##_gs
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_RGBA_BIT|R128_TEX0_BIT)
+#define TAG(x) x##_gt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_RGBA_BIT|R128_TEX0_BIT|R128_TEX1_BIT)
+#define TAG(x) x##_gt0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT)
+#define TAG(x) x##_gst0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT|R128_TEX1_BIT)
+#define TAG(x) x##_gst0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_RGBA_BIT|R128_FOG_BIT)
+#define TAG(x) x##_gf
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT)
+#define TAG(x) x##_gfs
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT)
+#define TAG(x) x##_gft0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT|R128_TEX1_BIT)
+#define TAG(x) x##_gft0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|R128_TEX0_BIT)
+#define TAG(x) x##_gfst0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|R128_TEX0_BIT|\
+             R128_TEX1_BIT)
+#define TAG(x) x##_gfst0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+
+static void init_setup_tab( void )
+{
+   init_wg();
+   init_wgs();
+   init_wgt0();
+   init_wgt0t1();
+   init_wgpt0();
+   init_wgst0();
+   init_wgst0t1();
+   init_wgspt0();
+   init_wgf();
+   init_wgfs();
+   init_wgft0();
+   init_wgft0t1();
+   init_wgfpt0();
+   init_wgfst0();
+   init_wgfst0t1();
+   init_wgfspt0();
+   init_t0();
+   init_t0t1();
+   init_f();
+   init_ft0();
+   init_ft0t1();
+   init_g();
+   init_gs();
+   init_gt0();
+   init_gt0t1();
+   init_gst0();
+   init_gst0t1();
+   init_gf();
+   init_gfs();
+   init_gft0();
+   init_gft0t1();
+   init_gfst0();
+   init_gfst0t1();
+}
+
+
+
+void r128PrintSetupFlags(char *msg, GLuint flags )
+{
+   fprintf(stderr, "%s(%x): %s%s%s%s%s%s\n",
+          msg,
+          (int)flags,
+          (flags & R128_XYZW_BIT)     ? " xyzw," : "",
+          (flags & R128_RGBA_BIT)     ? " rgba," : "",
+          (flags & R128_SPEC_BIT)     ? " spec," : "",
+          (flags & R128_FOG_BIT)      ? " fog," : "",
+          (flags & R128_TEX0_BIT)     ? " tex-0," : "",
+          (flags & R128_TEX1_BIT)     ? " tex-1," : "");
+}
+
+
+
+void r128CheckTexSizes( GLcontext *ctx )
+{
+   r128ContextPtr rmesa = R128_CONTEXT( ctx );
+
+   if (!setup_tab[rmesa->SetupIndex].check_tex_sizes(ctx)) {
+      TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+      /* Invalidate stored verts
+       */
+      rmesa->SetupNewInputs = ~0;
+      rmesa->SetupIndex |= R128_PTEX_BIT;
+
+      if (!rmesa->Fallback &&
+         !(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
+        tnl->Driver.Render.Interp = setup_tab[rmesa->SetupIndex].interp;
+        tnl->Driver.Render.CopyPV = setup_tab[rmesa->SetupIndex].copy_pv;
+      }
+   }
+}
+
+void r128BuildVertices( GLcontext *ctx,
+                       GLuint start,
+                       GLuint count,
+                       GLuint newinputs )
+{
+   r128ContextPtr rmesa = R128_CONTEXT( ctx );
+   GLubyte *v = ((GLubyte *)rmesa->verts + (start<<rmesa->vertex_stride_shift));
+   GLuint stride = 1<<rmesa->vertex_stride_shift;
+
+   newinputs |= rmesa->SetupNewInputs;
+   rmesa->SetupNewInputs = 0;
+
+   if (!newinputs)
+      return;
+
+   if (newinputs & VERT_BIT_CLIP) {
+      setup_tab[rmesa->SetupIndex].emit( ctx, start, count, v, stride );
+   } else {
+      GLuint ind = 0;
+
+      if (newinputs & VERT_BIT_COLOR0)
+        ind |= R128_RGBA_BIT;
+
+      if (newinputs & VERT_BIT_COLOR1)
+        ind |= R128_SPEC_BIT;
+
+      if (newinputs & VERT_BIT_TEX0)
+        ind |= R128_TEX0_BIT;
+
+      if (newinputs & VERT_BIT_TEX1)
+        ind |= R128_TEX1_BIT;
+
+      if (newinputs & VERT_BIT_FOG)
+        ind |= R128_FOG_BIT;
+
+      if (rmesa->SetupIndex & R128_PTEX_BIT)
+        ind = ~0;
+
+      ind &= rmesa->SetupIndex;
+
+      if (ind) {
+        setup_tab[ind].emit( ctx, start, count, v, stride );
+      }
+   }
+}
+
+void r128ChooseVertexState( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   r128ContextPtr rmesa = R128_CONTEXT( ctx );
+   GLuint ind = R128_XYZW_BIT|R128_RGBA_BIT;
+
+   if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
+      ind |= R128_SPEC_BIT;
+
+   if (ctx->Fog.Enabled)
+      ind |= R128_FOG_BIT;
+
+   if (ctx->Texture._EnabledUnits) {
+      ind |= R128_TEX0_BIT;
+      if (ctx->Texture.Unit[0]._ReallyEnabled &&
+         ctx->Texture.Unit[1]._ReallyEnabled)
+        ind |= R128_TEX1_BIT;
+   }
+
+   rmesa->SetupIndex = ind;
+
+   if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) {
+      tnl->Driver.Render.Interp = r128_interp_extras;
+      tnl->Driver.Render.CopyPV = r128_copy_pv_extras;
+   } else {
+      tnl->Driver.Render.Interp = setup_tab[ind].interp;
+      tnl->Driver.Render.CopyPV = setup_tab[ind].copy_pv;
+   }
+
+   if (setup_tab[ind].vertex_format != rmesa->vertex_format) {
+      FLUSH_BATCH(rmesa);
+      rmesa->vertex_format = setup_tab[ind].vertex_format;
+      rmesa->vertex_size = setup_tab[ind].vertex_size;
+      rmesa->vertex_stride_shift = setup_tab[ind].vertex_stride_shift;
+   }
+}
+
+
+
+void r128_emit_contiguous_verts( GLcontext *ctx,
+                                GLuint start,
+                                GLuint count )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   GLuint vertex_size = rmesa->vertex_size * 4;
+   GLuint *dest = r128AllocDmaLow( rmesa, (count-start) * vertex_size);
+   setup_tab[rmesa->SetupIndex].emit( ctx, start, count, dest, vertex_size );
+}
+
+
+#if 0
+void r128_emit_indexed_verts( GLcontext *ctx, GLuint start, GLuint count )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   GLuint vertex_size = rmesa->vertex_size * 4;
+   GLuint bufsz = (count-start) * vertex_size;
+   CARD32 *dest;
+
+   rmesa->vertex_low = (rmesa->vertex_low + 63) & ~63; /* alignment */
+   rmesa->vertex_last_prim = rmesa->vertex_low;
+
+   dest = r128AllocDmaLow( rmesa, bufsz, __FUNCTION__);
+   setup_tab[rmesa->SetupIndex].emit( ctx, start, count, dest, vertex_size );
+
+   rmesa->retained_buffer = rmesa->vertex_buffer;
+   rmesa->vb_offset = (rmesa->vertex_buffer->idx * R128_BUFFER_SIZE +
+                      rmesa->vertex_low - bufsz);
+
+   rmesa->vertex_low = (rmesa->vertex_low + 0x7) & ~0x7;  /* alignment */
+   rmesa->vertex_last_prim = rmesa->vertex_low;
+}
+#endif
+
+
+void r128InitVB( GLcontext *ctx )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   GLuint size = TNL_CONTEXT(ctx)->vb.Size;
+
+   rmesa->verts = ALIGN_MALLOC(size * 4 * 16, 32);
+
+   {
+      static int firsttime = 1;
+      if (firsttime) {
+        init_setup_tab();
+        firsttime = 0;
+      }
+   }
+}
+
+
+void r128FreeVB( GLcontext *ctx )
+{
+   r128ContextPtr rmesa = R128_CONTEXT(ctx);
+   if (rmesa->verts) {
+      ALIGN_FREE(rmesa->verts);
+      rmesa->verts = 0;
+   }
+
+
+   if (rmesa->UbyteSecondaryColor.Ptr) {
+      ALIGN_FREE(rmesa->UbyteSecondaryColor.Ptr);
+      rmesa->UbyteSecondaryColor.Ptr = 0;
+   }
+
+   if (rmesa->UbyteColor.Ptr) {
+      ALIGN_FREE(rmesa->UbyteColor.Ptr);
+      rmesa->UbyteColor.Ptr = 0;
+   }
+}
diff --git a/src/mesa/drivers/dri/r128/r128_vb.h b/src/mesa/drivers/dri/r128/r128_vb.h
new file mode 100644 (file)
index 0000000..31afa74
--- /dev/null
@@ -0,0 +1,74 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_vb.h,v 1.8 2002/10/30 12:51:46 alanh Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#ifndef R128VB_INC
+#define R128VB_INC
+
+#include "mtypes.h"
+#include "swrast/swrast.h"
+#include "r128_context.h"
+
+#define _R128_NEW_VERTEX_STATE (_DD_NEW_SEPARATE_SPECULAR |            \
+                               _DD_NEW_TRI_LIGHT_TWOSIDE |             \
+                               _DD_NEW_TRI_UNFILLED |                  \
+                               _NEW_TEXTURE |                          \
+                               _NEW_FOG)
+
+extern void r128CheckTexSizes( GLcontext *ctx );
+extern void r128ChooseVertexState( GLcontext *ctx );
+
+extern void r128BuildVertices( GLcontext *ctx, GLuint start, GLuint count,
+                                GLuint newinputs );
+
+extern void r128PrintSetupFlags(char *msg, GLuint flags );
+
+extern void r128InitVB( GLcontext *ctx );
+extern void r128FreeVB( GLcontext *ctx );
+
+extern void r128_emit_contiguous_verts( GLcontext *ctx,
+                                         GLuint start,
+                                         GLuint count );
+
+extern void r128_emit_indexed_verts( GLcontext *ctx,
+                                      GLuint start,
+                                      GLuint count );
+
+extern void r128_translate_vertex( GLcontext *ctx,
+                                    const r128Vertex *src,
+                                    SWvertex *dst );
+
+extern void r128_print_vertex( GLcontext *ctx, const r128Vertex *v );
+
+#endif
diff --git a/src/mesa/drivers/dri/r128/server/r128.h b/src/mesa/drivers/dri/r128/server/r128.h
new file mode 100644 (file)
index 0000000..fba01d6
--- /dev/null
@@ -0,0 +1,566 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128.h,v 1.24 2002/12/16 16:19:10 dawes Exp $ */
+/*
+ * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
+ *                      Precision Insight, Inc., Cedar Park, Texas, and
+ *                      VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
+ * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ *   Rickard E. Faith <faith@valinux.com>
+ *   Kevin E. Martin <martin@valinux.com>
+ *
+ */
+
+#ifndef _R128_H_
+#define _R128_H_
+
+#include "dri_util.h"
+#ifndef _SOLO
+#include "xf86str.h"
+
+                               /* PCI support */
+#include "xf86Pci.h"
+
+                               /* XAA and Cursor Support */
+#include "xaa.h"
+#include "xf86Cursor.h"
+
+                               /* DDC support */
+#include "xf86DDC.h"
+
+                               /* Xv support */
+#include "xf86xv.h"
+
+                               /* DRI support */
+#ifdef XF86DRI
+#define _XF86DRI_SERVER_
+#include "r128_dripriv.h"
+#include "dri.h"
+#include "GL/glxint.h"
+#endif
+#endif
+#ifdef _SOLO
+#define XF86DRI
+#endif
+
+#define R128_DEBUG          0   /* Turn off debugging output               */
+#define R128_IDLE_RETRY    32   /* Fall out of idle loops after this count */
+#define R128_TIMEOUT  2000000   /* Fall out of wait loops after this count */
+#define R128_MMIOSIZE  0x4000
+
+#define R128_VBIOS_SIZE 0x00010000
+
+#if R128_DEBUG
+#define R128TRACE(x)                                          \
+    do {                                                      \
+       ErrorF("(**) %s(%d): ", R128_NAME, pScrn->scrnIndex); \
+       ErrorF x;                                             \
+    } while (0);
+#else
+#define R128TRACE(x)
+#endif
+
+
+/* Other macros */
+#define R128_ARRAY_SIZE(x)  (sizeof(x)/sizeof(x[0]))
+#define R128_ALIGN(x,bytes) (((x) + ((bytes) - 1)) & ~((bytes) - 1))
+#define R128PTR(pScrn) ((R128InfoPtr)(pScrn)->driverPrivate)
+    
+/**
+ * \brief Chip families.
+ */
+typedef enum {
+    CHIP_FAMILY_UNKNOWN,
+    CHIP_FAMILY_R128_PCI,
+    CHIP_FAMILY_R128_AGP,
+} R128ChipFamily;
+
+typedef struct {        /* All values in XCLKS    */
+    int  ML;            /* Memory Read Latency    */
+    int  MB;            /* Memory Burst Length    */
+    int  Trcd;          /* RAS to CAS delay       */
+    int  Trp;           /* RAS percentage         */
+    int  Twr;           /* Write Recovery         */
+    int  CL;            /* CAS Latency            */
+    int  Tr2w;          /* Read to Write Delay    */
+    int  Rloop;         /* Loop Latency           */
+    int  Rloop_fudge;   /* Add to ML to get Rloop */
+    char *name;
+} R128RAMRec, *R128RAMPtr;
+
+typedef struct {
+                               /* Common registers */
+    CARD32     ovr_clr;
+    CARD32     ovr_wid_left_right;
+    CARD32     ovr_wid_top_bottom;
+    CARD32     ov0_scale_cntl;
+    CARD32     mpp_tb_config;
+    CARD32     mpp_gp_config;
+    CARD32     subpic_cntl;
+    CARD32     viph_control;
+    CARD32     i2c_cntl_1;
+    CARD32     gen_int_cntl;
+    CARD32     cap0_trig_cntl;
+    CARD32     cap1_trig_cntl;
+    CARD32     bus_cntl;
+    CARD32     config_cntl;
+
+                               /* Other registers to save for VT switches */
+    CARD32     dp_datatype;
+    CARD32     gen_reset_cntl;
+    CARD32     clock_cntl_index;
+    CARD32     amcgpio_en_reg;
+    CARD32     amcgpio_mask;
+
+                               /* CRTC registers */
+    CARD32     crtc_gen_cntl;
+    CARD32     crtc_ext_cntl;
+    CARD32     dac_cntl;
+    CARD32     crtc_h_total_disp;
+    CARD32     crtc_h_sync_strt_wid;
+    CARD32     crtc_v_total_disp;
+    CARD32     crtc_v_sync_strt_wid;
+    CARD32     crtc_offset;
+    CARD32     crtc_offset_cntl;
+    CARD32     crtc_pitch;
+
+                               /* CRTC2 registers */
+    CARD32     crtc2_gen_cntl;
+
+                               /* Flat panel registers */
+    CARD32     fp_crtc_h_total_disp;
+    CARD32     fp_crtc_v_total_disp;
+    CARD32     fp_gen_cntl;
+    CARD32     fp_h_sync_strt_wid;
+    CARD32     fp_horz_stretch;
+    CARD32     fp_panel_cntl;
+    CARD32     fp_v_sync_strt_wid;
+    CARD32     fp_vert_stretch;
+    CARD32     lvds_gen_cntl;
+    CARD32     tmds_crc;
+    CARD32     tmds_transmitter_cntl;
+
+                               /* Computed values for PLL */
+    CARD32     dot_clock_freq;
+    CARD32     pll_output_freq;
+    int        feedback_div;
+    int        post_div;
+
+                               /* PLL registers */
+    CARD32     ppll_ref_div;
+    CARD32     ppll_div_3;
+    CARD32     htotal_cntl;
+
+                               /* DDA register */
+    CARD32     dda_config;
+    CARD32     dda_on_off;
+
+                               /* Pallet */
+    GLboolean  palette_valid;
+    CARD32     palette[256];
+} R128SaveRec, *R128SavePtr;
+
+#ifndef _SOLO
+typedef struct {
+    CARD16        reference_freq;
+    CARD16        reference_div;
+    CARD32        min_pll_freq;
+    CARD32        max_pll_freq;
+    CARD16        xclk;
+} R128PLLRec, *R128PLLPtr;
+
+typedef struct {
+    int                bitsPerPixel;
+    int                depth;
+    int                displayWidth;
+    int                pixel_code;
+    int                pixel_bytes;
+    DisplayModePtr     mode;
+} R128FBLayout;
+#endif
+
+typedef struct {
+#ifndef _SOLO    
+    EntityInfoPtr     pEnt;
+    pciVideoPtr       PciInfo;
+    PCITAG            PciTag;
+#endif    
+    int               Chipset;
+    GLboolean              Primary;
+
+    GLboolean              FBDev;
+
+    unsigned long     LinearAddr;   /* Frame buffer physical address         */
+    unsigned long     BIOSAddr;     /* BIOS physical address                 */
+
+    unsigned char     *MMIO;        /* Map of MMIO region                    */
+    unsigned char     *FB;          /* Map of frame buffer                   */
+
+    CARD32            MemCntl;
+    CARD32            BusCntl;
+    unsigned long     FbMapSize;    /* Size of frame buffer, in bytes        */
+    int               Flags;        /* Saved copy of mode flags              */
+
+#ifndef _SOLO    
+    CARD8             BIOSDisplay;  /* Device the BIOS is set to display to  */
+
+    GLboolean         HasPanelRegs; /* Current chip can connect to a FP      */
+    CARD8             *VBIOS;       /* Video BIOS for mode validation on FPs */
+    int               FPBIOSstart;  /* Start of the flat panel info          */
+#endif
+                               /* Computed values for FPs */
+    int               PanelXRes;
+    int               PanelYRes;
+    int               HOverPlus;
+    int               HSyncWidth;
+    int               HBlank;
+    int               VOverPlus;
+    int               VSyncWidth;
+    int               VBlank;
+    int               PanelPwrDly;
+#ifndef _SOLO
+    R128PLLRec        pll;
+    R128RAMPtr        ram;
+
+    R128SaveRec       SavedReg;     /* Original (text) mode                  */
+    R128SaveRec       ModeReg;      /* Current mode                          */
+    GLboolean              (*CloseScreen)(int, ScreenPtr);
+    void              (*BlockHandler)(int, pointer, pointer, pointer);
+
+    GLboolean              PaletteSavedOnVT; /* Palette saved on last VT switch   */
+
+    XAAInfoRecPtr     accel;
+    GLboolean              accelOn;
+    xf86CursorInfoPtr cursor;
+#endif    
+    unsigned long     cursor_start;
+    unsigned long     cursor_end;
+
+    /*
+     * XAAForceTransBlit is used to change the behavior of the XAA
+     * SetupForScreenToScreenCopy function, to make it DGA-friendly.
+     */
+    GLboolean              XAAForceTransBlit;
+
+    int               fifo_slots;   /* Free slots in the FIFO (64 max)       */
+    int               pix24bpp;     /* Depth of pixmap for 24bpp framebuffer */
+    GLboolean              dac6bits;     /* Use 6 bit DAC?                        */
+
+                               /* Computed values for Rage 128 */
+    int               pitch;
+    int               datatype;
+    CARD32            dp_gui_master_cntl;
+
+                               /* Saved values for ScreenToScreenCopy */
+    int               xdir;
+    int               ydir;
+
+                               /* ScanlineScreenToScreenColorExpand support */
+    unsigned char     *scratch_buffer[1];
+    unsigned char     *scratch_save;
+    int               scanline_x;
+    int               scanline_y;
+    int               scanline_w;
+    int               scanline_h;
+#ifdef XF86DRI
+    int               scanline_hpass;
+    int               scanline_x1clip;
+    int               scanline_x2clip;
+    int               scanline_rop;
+    int               scanline_fg;
+    int               scanline_bg;
+#endif /* XF86DRI */
+    int               scanline_words;
+    int               scanline_direct;
+    int               scanline_bpp; /* Only used for ImageWrite */
+
+#ifndef _SOLO    
+    DGAModePtr        DGAModes;
+    int               numDGAModes;
+    GLboolean         DGAactive;
+    int               DGAViewportStatus;
+    DGAFunctionRec    DGAFuncs;
+
+    R128FBLayout      CurrentLayout;
+#endif    
+#ifdef XF86DRI
+    drmContext        drmCtx;
+#ifndef _SOLO    
+    DRIInfoPtr        pDRIInfo;
+    int               numVisualConfigs;
+    __GLXvisualConfig *pVisualConfigs;
+    R128ConfigPrivPtr pVisualConfigsPriv;
+#endif    
+
+    drmSize           registerSize;
+    drmHandle         registerHandle;
+
+    GLboolean         IsPCI;            /* Current card is a PCI card */
+    drmSize           pciSize;
+    drmHandle         pciMemHandle;
+    unsigned char     *PCI;             /* Map */
+
+    GLboolean         allowPageFlip;    /* Enable 3d page flipping */
+    GLboolean         have3DWindows;    /* Are there any 3d clients? */
+    int               drmMinor;
+
+    drmSize           agpSize;
+    drmHandle         agpMemHandle;     /* Handle from drmAgpAlloc */
+    unsigned long     agpOffset;
+    unsigned char     *AGP;             /* Map */
+    int               agpMode;
+
+    GLboolean         CCEInUse;         /* CCE is currently active */
+    int               CCEMode;          /* CCE mode that server/clients use */
+    int               CCEFifoSize;      /* Size of the CCE command FIFO */
+    GLboolean         CCESecure;        /* CCE security enabled */
+    int               CCEusecTimeout;   /* CCE timeout in usecs */
+
+                               /* CCE ring buffer data */
+    unsigned long     ringStart;        /* Offset into AGP space */
+    drmHandle         ringHandle;       /* Handle from drmAddMap */
+    drmSize           ringMapSize;      /* Size of map */
+    int               ringSize;         /* Size of ring (in MB) */
+    unsigned char     *ring;            /* Map */
+    int               ringSizeLog2QW;
+
+    unsigned long     ringReadOffset;   /* Offset into AGP space */
+    drmHandle         ringReadPtrHandle; /* Handle from drmAddMap */
+    drmSize           ringReadMapSize;  /* Size of map */
+    unsigned char     *ringReadPtr;     /* Map */
+
+                               /* CCE vertex/indirect buffer data */
+    unsigned long     bufStart;        /* Offset into AGP space */
+    drmHandle         bufHandle;       /* Handle from drmAddMap */
+    drmSize           bufMapSize;      /* Size of map */
+    int               bufSize;         /* Size of buffers (in MB) */
+    unsigned char     *buf;            /* Map */
+    int               bufNumBufs;      /* Number of buffers */
+    drmBufMapPtr      buffers;         /* Buffer map */
+
+                               /* CCE AGP Texture data */
+    unsigned long     agpTexStart;      /* Offset into AGP space */
+    drmHandle         agpTexHandle;     /* Handle from drmAddMap */
+    drmSize           agpTexMapSize;    /* Size of map */
+    int               agpTexSize;       /* Size of AGP tex space (in MB) */
+    unsigned char     *agpTex;          /* Map */
+    int               log2AGPTexGran;
+
+                               /* CCE 2D accleration */
+    drmBufPtr         indirectBuffer;
+    int               indirectStart;
+
+                               /* DRI screen private data */
+    int               fbX;
+    int               fbY;
+    int               backX;
+    int               backY;
+    int               depthX;
+    int               depthY;
+
+    int               frontOffset;
+    int               frontPitch;
+    int               backOffset;
+    int               backPitch;
+    int               depthOffset;
+    int               depthPitch;
+    int               spanOffset;
+    int               textureOffset;
+    int               textureSize;
+    int               log2TexGran;
+
+                               /* Saved scissor values */
+    CARD32            sc_left;
+    CARD32            sc_right;
+    CARD32            sc_top;
+    CARD32            sc_bottom;
+
+    CARD32            re_top_left;
+    CARD32            re_width_height;
+
+    CARD32            aux_sc_cntl;
+
+    int               irq;
+    CARD32            gen_int_cntl;
+
+    GLboolean              DMAForXv;
+#endif
+
+#ifndef _SOLO    
+    XF86VideoAdaptorPtr adaptor;
+    void              (*VideoTimerCallback)(ScrnInfoPtr, Time);
+    int               videoKey;
+    GLboolean              showCache;
+    OptionInfoPtr     Options;
+
+    GLboolean              isDFP;
+    GLboolean              isPro2;
+    I2CBusPtr         pI2CBus;
+    CARD32            DDCReg;
+#endif
+} R128InfoRec, *R128InfoPtr;
+
+#define R128WaitForFifo(pScrn, entries)                                      \
+do {                                                                         \
+    if (info->fifo_slots < entries) R128WaitForFifoFunction(pScrn, entries); \
+    info->fifo_slots -= entries;                                             \
+} while (0)
+
+extern void        r128WaitForFifoFunction(const DRIDriverContext *ctx, int entries);
+extern void        r128WaitForIdle(const DRIDriverContext *ctx);
+
+extern void        r128WaitForVerticalSync(const DRIDriverContext *ctx);
+
+extern GLboolean        r128AccelInit(const DRIDriverContext *ctx);
+extern void        r128EngineInit(const DRIDriverContext *ctx);
+extern GLboolean        r128CursorInit(const DRIDriverContext *ctx);
+extern GLboolean        r128DGAInit(const DRIDriverContext *ctx);
+
+extern void        r128InitVideo(const DRIDriverContext *ctx);
+
+extern GLboolean        r128DRIScreenInit(const DRIDriverContext *ctx);
+extern void        r128DRICloseScreen(const DRIDriverContext *ctx);
+extern GLboolean        r128DRIFinishScreenInit(const DRIDriverContext *ctx);
+
+#define R128CCE_START(ctx, info)                                       \
+do {                                                                   \
+    int _ret = drmCommandNone(ctx->drmFD, DRM_R128_CCE_START);         \
+    if (_ret) {                                                                \
+          fprintf(stderr,                              \
+                  "%s: CCE start %d\n", __FUNCTION__, _ret);           \
+    }                                                                  \
+} while (0)
+
+#define R128CCE_STOP(ctx, info)                                        \
+do {                                                                   \
+    int _ret = R128CCEStop(ctx);                                       \
+    if (_ret) {                                                                \
+          fprintf(stderr,                              \
+                  "%s: CCE stop %d\n", __FUNCTION__, _ret);            \
+    }                                                                  \
+} while (0)
+
+#define R128CCE_RESET(ctx, info)                                       \
+do {                                                                   \
+    if (info->directRenderingEnabled                                   \
+       && R128CCE_USE_RING_BUFFER(info->CCEMode)) {                    \
+       int _ret = drmCommandNone(info->drmFD, DRM_R128_CCE_RESET);     \
+       if (_ret) {                                                     \
+              fprintf(stderr,                  \
+                      "%s: CCE reset %d\n", __FUNCTION__, _ret);       \
+       }                                                               \
+    }                                                                  \
+} while (0)
+
+    
+#define CCE_PACKET0( reg, n )                                          \
+       (R128_CCE_PACKET0 | ((n) << 16) | ((reg) >> 2))
+#define CCE_PACKET1( reg0, reg1 )                                      \
+       (R128_CCE_PACKET1 | (((reg1) >> 2) << 11) | ((reg0) >> 2))
+#define CCE_PACKET2()                                                  \
+       (R128_CCE_PACKET2)
+#define CCE_PACKET3( pkt, n )                                          \
+       (R128_CCE_PACKET3 | (pkt) | ((n) << 16))
+
+
+#define R128_VERBOSE   0
+
+#define RING_LOCALS    CARD32 *__head; int __count;
+
+#define R128CCE_REFRESH(pScrn, info)                                   \
+do {                                                                   \
+   if ( R128_VERBOSE ) {                                               \
+         fprintf(stderr, "REFRESH( %d ) in %s\n",      \
+                 !info->CCEInUse , __FUNCTION__ );                     \
+   }                                                                   \
+   if ( !info->CCEInUse ) {                                            \
+      R128CCEWaitForIdle(pScrn);                                               \
+      BEGIN_RING( 6 );                                                 \
+      OUT_RING_REG( R128_RE_TOP_LEFT,     info->re_top_left );         \
+      OUT_RING_REG( R128_RE_WIDTH_HEIGHT, info->re_width_height );     \
+      OUT_RING_REG( R128_AUX_SC_CNTL,     info->aux_sc_cntl );         \
+      ADVANCE_RING();                                                  \
+      info->CCEInUse = TRUE;                                           \
+   }                                                                   \
+} while (0)
+
+#define BEGIN_RING( n ) do {                                           \
+   if ( R128_VERBOSE ) {                                               \
+         fprintf(stderr,                               \
+                 "BEGIN_RING( %d ) in %s\n", n, __FUNCTION__ );        \
+   }                                                                   \
+   if ( !info->indirectBuffer ) {                                      \
+      info->indirectBuffer = R128CCEGetBuffer( pScrn );                        \
+      info->indirectStart = 0;                                         \
+   } else if ( (info->indirectBuffer->used + 4*(n)) >                  \
+                info->indirectBuffer->total ) {                                \
+      R128CCEFlushIndirect( pScrn, 1 );                                        \
+   }                                                                   \
+   __head = (pointer)((char *)info->indirectBuffer->address +          \
+                      info->indirectBuffer->used);                     \
+   __count = 0;                                                                \
+} while (0)
+
+#define ADVANCE_RING() do {                                            \
+   if ( R128_VERBOSE ) {                                               \
+         fprintf(stderr,                               \
+                 "ADVANCE_RING() used: %d+%d=%d/%d\n",                 \
+                 info->indirectBuffer->used - info->indirectStart,     \
+                 __count * sizeof(CARD32),                             \
+                 info->indirectBuffer->used - info->indirectStart +    \
+                 __count * sizeof(CARD32),                             \
+                 info->indirectBuffer->total - info->indirectStart );  \
+   }                                                                   \
+   info->indirectBuffer->used += __count * (int)sizeof(CARD32);                \
+} while (0)
+
+#define OUT_RING( x ) do {                                             \
+   if ( R128_VERBOSE ) {                                               \
+         fprintf(stderr,                               \
+                 "   OUT_RING( 0x%08x )\n", (unsigned int)(x) );       \
+   }                                                                   \
+   MMIO_OUT32(&__head[__count++], 0, (x));                             \
+} while (0)
+
+#define OUT_RING_REG( reg, val )                                       \
+do {                                                                   \
+   OUT_RING( CCE_PACKET0( reg, 0 ) );                                  \
+   OUT_RING( val );                                                    \
+} while (0)
+
+#define FLUSH_RING()                                                   \
+do {                                                                   \
+   if ( R128_VERBOSE )                                                 \
+         fprintf(stderr,                               \
+                 "FLUSH_RING in %s\n", __FUNCTION__ );                 \
+   if ( info->indirectBuffer ) {                                       \
+      R128CCEFlushIndirect( pScrn, 0 );                                        \
+   }                                                                   \
+} while (0)
+
+    
+#endif
diff --git a/src/mesa/drivers/dri/r128/server/r128_common.h b/src/mesa/drivers/dri/r128/server/r128_common.h
new file mode 100644 (file)
index 0000000..fa81360
--- /dev/null
@@ -0,0 +1,169 @@
+/* r128_common.h -- common header definitions for R128 2D/3D/DRM suite
+ * Created: Sun Apr  9 18:16:28 2000 by kevin@precisioninsight.com
+ *
+ * Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
+ * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author:
+ *   Gareth Hughes <gareth@valinux.com>
+ *   Kevin E. Martin <martin@valinux.com>
+ *
+ * Converted to common header format:
+ *   Jens Owen <jens@tungstengraphics.com>
+ *
+ * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/xf86drmR128.h,v 3.11 2001/04/16 15:02:13 tsi Exp $
+ *
+ */
+
+#ifndef _R128_COMMON_H_
+#define _R128_COMMON_H_
+
+/*
+ * WARNING: If you change any of these defines, make sure to change
+ * the kernel include file as well (r128_drm.h)
+ */
+
+/* Driver specific DRM command indices
+ * NOTE: these are not OS specific, but they are driver specific
+ */
+#define DRM_R128_INIT           0x00
+#define DRM_R128_CCE_START      0x01
+#define DRM_R128_CCE_STOP       0x02
+#define DRM_R128_CCE_RESET      0x03
+#define DRM_R128_CCE_IDLE       0x04
+#define DRM_R128_UNDEFINED1     0x05
+#define DRM_R128_RESET          0x06
+#define DRM_R128_SWAP           0x07
+#define DRM_R128_CLEAR          0x08
+#define DRM_R128_VERTEX         0x09
+#define DRM_R128_INDICES        0x0a
+#define DRM_R128_BLIT           0x0b
+#define DRM_R128_DEPTH          0x0c
+#define DRM_R128_STIPPLE        0x0d
+#define DRM_R128_UNDEFINED2     0x0e
+#define DRM_R128_INDIRECT       0x0f
+#define DRM_R128_FULLSCREEN     0x10
+#define DRM_R128_CLEAR2         0x11
+#define DRM_R128_GETPARAM       0x12
+#define DRM_R128_FLIP           0x13
+
+#define DRM_R128_FRONT_BUFFER  0x1
+#define DRM_R128_BACK_BUFFER   0x2
+#define DRM_R128_DEPTH_BUFFER  0x4
+
+typedef struct {
+   enum {
+      DRM_R128_INIT_CCE    = 0x01,
+      DRM_R128_CLEANUP_CCE = 0x02
+   } func;
+   unsigned long sarea_priv_offset;
+   int is_pci;
+   int cce_mode;
+   int cce_secure;             /* FIXME: Deprecated, we should remove this */
+   int ring_size;
+   int usec_timeout;
+
+   unsigned int fb_bpp;
+   unsigned int front_offset, front_pitch;
+   unsigned int back_offset, back_pitch;
+   unsigned int depth_bpp;
+   unsigned int depth_offset, depth_pitch;
+   unsigned int span_offset;
+
+   unsigned long fb_offset;
+   unsigned long mmio_offset;
+   unsigned long ring_offset;
+   unsigned long ring_rptr_offset;
+   unsigned long buffers_offset;
+   unsigned long agp_textures_offset;
+} drmR128Init;
+
+typedef struct {
+   int flush;
+   int idle;
+} drmR128CCEStop;
+
+typedef struct {
+   int idx;
+   int start;
+   int end;
+   int discard;
+} drmR128Indirect;
+
+typedef struct {
+   int idx;
+   int pitch;
+   int offset;
+   int format;
+   unsigned short x, y;
+   unsigned short width, height;
+} drmR128Blit;
+
+typedef struct {
+   enum {
+      DRM_R128_WRITE_SPAN         = 0x01,
+      DRM_R128_WRITE_PIXELS       = 0x02,
+      DRM_R128_READ_SPAN          = 0x03,
+      DRM_R128_READ_PIXELS        = 0x04
+   } func;
+   int n;
+   int *x;
+   int *y;
+   unsigned int *buffer;
+   unsigned char *mask;
+} drmR128Depth;
+
+typedef struct {
+   int prim;
+   int idx;                        /* Index of vertex buffer */
+   int count;                      /* Number of vertices in buffer */
+   int discard;                    /* Client finished with buffer? */
+} drmR128Vertex;
+
+typedef struct {
+   unsigned int *mask;
+} drmR128Stipple;
+
+typedef struct {
+   unsigned int flags;
+   unsigned int clear_color;
+   unsigned int clear_depth;
+   unsigned int color_mask;
+   unsigned int depth_mask;
+} drmR128Clear;
+
+typedef struct {
+   enum {
+      DRM_R128_INIT_FULLSCREEN    = 0x01,
+      DRM_R128_CLEANUP_FULLSCREEN = 0x02
+   } func;
+} drmR128Fullscreen;
+
+typedef struct drm_r128_getparam {
+       int param;
+       void *value;
+} drmR128GetParam;
+
+#define R128_PARAM_IRQ_NR            1
+
+#endif
diff --git a/src/mesa/drivers/dri/r128/server/r128_dri.c b/src/mesa/drivers/dri/r128/server/r128_dri.c
new file mode 100644 (file)
index 0000000..aa8f49f
--- /dev/null
@@ -0,0 +1,1165 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_dri.c,v 1.28 2003/02/07 20:41:14 martin Exp $ */
+/*
+ * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
+ *                      Precision Insight, Inc., Cedar Park, Texas, and
+ *                      VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
+ * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Rickard E. Faith <faith@valinux.com>
+ *   Daryll Strauss <daryll@valinux.com>
+ *   Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#include "sarea.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <linux/pci_ids.h>
+
+#include "driver.h"
+#include "drm.h"
+
+#include "sarea.h"
+#include "r128.h"
+#include "r128_dri.h"
+#include "r128_macros.h"
+#include "r128_reg.h"
+#include "r128_sarea.h"
+#include "r128_version.h"
+
+
+/* ?? HACK - for now, put this here... */
+/* ?? Alpha - this may need to be a variable to handle UP1x00 vs TITAN */
+#if defined(__alpha__)
+# define DRM_PAGE_SIZE 8192
+#elif defined(__ia64__)
+# define DRM_PAGE_SIZE getpagesize()
+#else
+# define DRM_PAGE_SIZE 4096
+#endif
+
+/**
+ * \brief Establish the set of modes available for the display.
+ *
+ * \param ctx display handle.
+ * \param numModes will receive the number of supported modes.
+ * \param modes will point to the list of supported modes.
+ *
+ * \return one on success, or zero on failure.
+ * 
+ * Allocates a single visual and fills it with information according to the
+ * display bit depth. Supports only 16 and 32 bpp bit depths, aborting
+ * otherwise.
+ */
+const __GLcontextModes __glModes[] = {
+    
+    /* 32 bit, RGBA Depth=24 Stencil=8 */
+    {.rgbMode = GL_TRUE, .colorIndexMode = GL_FALSE, .doubleBufferMode = GL_TRUE, .stereoMode = GL_FALSE,
+     .haveAccumBuffer = GL_FALSE, .haveDepthBuffer = GL_TRUE, .haveStencilBuffer = GL_TRUE,
+     .redBits = 8, .greenBits = 8, .blueBits = 8, .alphaBits = 8,
+     .redMask = 0xff0000, .greenMask = 0xff00, .blueMask = 0xff, .alphaMask = 0xff000000,
+     .rgbBits = 32, .indexBits = 0,
+     .accumRedBits = 0, .accumGreenBits = 0, .accumBlueBits = 0, .accumAlphaBits = 0,
+     .depthBits = 24, .stencilBits = 8,
+     .numAuxBuffers= 0, .level = 0, .pixmapMode = GL_FALSE, },
+
+    /* 16 bit, RGB Depth=16 */
+    {.rgbMode = GL_TRUE, .colorIndexMode = GL_FALSE, .doubleBufferMode = GL_TRUE, .stereoMode = GL_FALSE,
+     .haveAccumBuffer = GL_FALSE, .haveDepthBuffer = GL_TRUE, .haveStencilBuffer = GL_FALSE,
+     .redBits = 5, .greenBits = 6, .blueBits = 5, .alphaBits = 0,
+     .redMask = 0xf800, .greenMask = 0x07e0, .blueMask = 0x001f, .alphaMask = 0x0,
+     .rgbBits = 16, .indexBits = 0,
+     .accumRedBits = 0, .accumGreenBits = 0, .accumBlueBits = 0, .accumAlphaBits = 0,
+     .depthBits = 16, .stencilBits = 0,
+     .numAuxBuffers= 0, .level = 0, .pixmapMode = GL_FALSE, },
+};
+static int R128InitContextModes( const DRIDriverContext *ctx,
+                                  int *numModes, const __GLcontextModes **modes)
+{
+   *numModes = sizeof(__glModes)/sizeof(__GLcontextModes *);
+   *modes = &__glModes[0];
+   return 1;
+}
+
+/* Compute log base 2 of val. */
+static int R128MinBits(int val)
+{
+    int bits;
+
+    if (!val) return 1;
+    for (bits = 0; val; val >>= 1, ++bits);
+    return bits;
+}
+
+/* Initialize the AGP state.  Request memory for use in AGP space, and
+   initialize the Rage 128 registers to point to that memory. */
+static GLboolean R128DRIAgpInit(const DRIDriverContext *ctx)
+{
+    unsigned char *R128MMIO = ctx->MMIOAddress;
+    R128InfoPtr info = ctx->driverPrivate;
+    unsigned long mode;
+    unsigned int  vendor, device;
+    int           ret;
+    unsigned long cntl, chunk;
+    int           s, l;
+    int           flags;
+    unsigned long agpBase;
+
+    if (drmAgpAcquire(ctx->drmFD) < 0) {
+       fprintf(stderr, "[agp] AGP not available\n");
+       return GL_FALSE;
+    }
+
+                               /* Modify the mode if the default mode is
+                                  not appropriate for this particular
+                                  combination of graphics card and AGP
+                                  chipset. */
+
+    mode   = drmAgpGetMode(ctx->drmFD);        /* Default mode */
+    vendor = drmAgpVendorId(ctx->drmFD);
+    device = drmAgpDeviceId(ctx->drmFD);
+
+    mode &= ~R128_AGP_MODE_MASK;
+    switch (info->agpMode) {
+    case 4:          mode |= R128_AGP_4X_MODE;
+    case 2:          mode |= R128_AGP_2X_MODE;
+    case 1: default: mode |= R128_AGP_1X_MODE;
+    }
+
+    fprintf(stderr,
+              "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
+              mode, vendor, device,
+              0x1002,
+              info->Chipset);
+
+    if (drmAgpEnable(ctx->drmFD, mode) < 0) {
+       fprintf(stderr, "[agp] AGP not enabled\n");
+       drmAgpRelease(ctx->drmFD);
+       return GL_FALSE;
+    }
+
+    info->agpOffset = 0;
+
+    if ((ret = drmAgpAlloc(ctx->drmFD, info->agpSize*1024*1024, 0, NULL,
+                          &info->agpMemHandle)) < 0) {
+       fprintf(stderr, "[agp] Out of memory (%d)\n", ret);
+       drmAgpRelease(ctx->drmFD);
+       return GL_FALSE;
+    }
+    fprintf(stderr,
+              "[agp] %d kB allocated with handle 0x%08x\n",
+              info->agpSize*1024, info->agpMemHandle);
+
+    if (drmAgpBind(ctx->drmFD, info->agpMemHandle, info->agpOffset) < 0) {
+       fprintf(stderr, "[agp] Could not bind\n");
+       drmAgpFree(ctx->drmFD, info->agpMemHandle);
+       drmAgpRelease(ctx->drmFD);
+       return GL_FALSE;
+    }
+
+                               /* Initialize the CCE ring buffer data */
+    info->ringStart       = info->agpOffset;
+    info->ringMapSize     = info->ringSize*1024*1024 + DRM_PAGE_SIZE;
+    info->ringSizeLog2QW  = R128MinBits(info->ringSize*1024*1024/8) - 1;
+
+    info->ringReadOffset  = info->ringStart + info->ringMapSize;
+    info->ringReadMapSize = DRM_PAGE_SIZE;
+
+                               /* Reserve space for vertex/indirect buffers */
+    info->bufStart        = info->ringReadOffset + info->ringReadMapSize;
+    info->bufMapSize      = info->bufSize*1024*1024;
+
+                               /* Reserve the rest for AGP textures */
+    info->agpTexStart     = info->bufStart + info->bufMapSize;
+    s = (info->agpSize*1024*1024 - info->agpTexStart);
+    l = R128MinBits((s-1) / R128_NR_TEX_REGIONS);
+    if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY;
+    info->agpTexMapSize   = (s >> l) << l;
+    info->log2AGPTexGran  = l;
+
+    if (info->CCESecure) flags = DRM_READ_ONLY;
+    else                  flags = 0;
+
+    if (drmAddMap(ctx->drmFD, info->ringStart, info->ringMapSize,
+                 DRM_AGP, flags, &info->ringHandle) < 0) {
+       fprintf(stderr,
+                  "[agp] Could not add ring mapping\n");
+       return GL_FALSE;
+    }
+    fprintf(stderr,
+              "[agp] ring handle = 0x%08lx\n", info->ringHandle);
+
+    if (drmMap(ctx->drmFD, info->ringHandle, info->ringMapSize,
+              (drmAddressPtr)&info->ring) < 0) {
+       fprintf(stderr, "[agp] Could not map ring\n");
+       return GL_FALSE;
+    }
+    fprintf(stderr,
+              "[agp] Ring mapped at 0x%08lx\n",
+              (unsigned long)info->ring);
+
+    if (drmAddMap(ctx->drmFD, info->ringReadOffset, info->ringReadMapSize,
+                 DRM_AGP, flags, &info->ringReadPtrHandle) < 0) {
+       fprintf(stderr,
+                  "[agp] Could not add ring read ptr mapping\n");
+       return GL_FALSE;
+    }
+    fprintf(stderr,
+              "[agp] ring read ptr handle = 0x%08lx\n",
+              info->ringReadPtrHandle);
+
+    if (drmMap(ctx->drmFD, info->ringReadPtrHandle, info->ringReadMapSize,
+              (drmAddressPtr)&info->ringReadPtr) < 0) {
+       fprintf(stderr,
+                  "[agp] Could not map ring read ptr\n");
+       return GL_FALSE;
+    }
+    fprintf(stderr,
+              "[agp] Ring read ptr mapped at 0x%08lx\n",
+              (unsigned long)info->ringReadPtr);
+
+    if (drmAddMap(ctx->drmFD, info->bufStart, info->bufMapSize,
+                 DRM_AGP, 0, &info->bufHandle) < 0) {
+       fprintf(stderr,
+                  "[agp] Could not add vertex/indirect buffers mapping\n");
+       return GL_FALSE;
+    }
+    fprintf(stderr,
+              "[agp] vertex/indirect buffers handle = 0x%08lx\n",
+              info->bufHandle);
+
+    if (drmMap(ctx->drmFD, info->bufHandle, info->bufMapSize,
+              (drmAddressPtr)&info->buf) < 0) {
+       fprintf(stderr,
+                  "[agp] Could not map vertex/indirect buffers\n");
+       return GL_FALSE;
+    }
+    fprintf(stderr,
+              "[agp] Vertex/indirect buffers mapped at 0x%08lx\n",
+              (unsigned long)info->buf);
+
+    if (drmAddMap(ctx->drmFD, info->agpTexStart, info->agpTexMapSize,
+                 DRM_AGP, 0, &info->agpTexHandle) < 0) {
+       fprintf(stderr,
+                  "[agp] Could not add AGP texture map mapping\n");
+       return GL_FALSE;
+    }
+    fprintf(stderr,
+              "[agp] AGP texture map handle = 0x%08lx\n",
+              info->agpTexHandle);
+
+    if (drmMap(ctx->drmFD, info->agpTexHandle, info->agpTexMapSize,
+              (drmAddressPtr)&info->agpTex) < 0) {
+       fprintf(stderr,
+                  "[agp] Could not map AGP texture map\n");
+       return GL_FALSE;
+    }
+    fprintf(stderr,
+              "[agp] AGP Texture map mapped at 0x%08lx\n",
+              (unsigned long)info->agpTex);
+
+                               /* Initialize Rage 128's AGP registers */
+    cntl  = INREG(R128_AGP_CNTL);
+    cntl &= ~R128_AGP_APER_SIZE_MASK;
+    switch (info->agpSize) {
+    case 256: cntl |= R128_AGP_APER_SIZE_256MB; break;
+    case 128: cntl |= R128_AGP_APER_SIZE_128MB; break;
+    case  64: cntl |= R128_AGP_APER_SIZE_64MB;  break;
+    case  32: cntl |= R128_AGP_APER_SIZE_32MB;  break;
+    case  16: cntl |= R128_AGP_APER_SIZE_16MB;  break;
+    case   8: cntl |= R128_AGP_APER_SIZE_8MB;   break;
+    case   4: cntl |= R128_AGP_APER_SIZE_4MB;   break;
+    default:
+       fprintf(stderr,
+                  "[agp] Illegal aperture size %d kB\n",
+                  info->agpSize*1024);
+       return GL_FALSE;
+    }
+    agpBase = drmAgpBase(ctx->drmFD);
+    OUTREG(R128_AGP_BASE, agpBase); 
+    OUTREG(R128_AGP_CNTL, cntl);
+
+                               /* Disable Rage 128's PCIGART registers */
+    chunk = INREG(R128_BM_CHUNK_0_VAL);
+    chunk &= ~(R128_BM_PTR_FORCE_TO_PCI |
+              R128_BM_PM4_RD_FORCE_TO_PCI |
+              R128_BM_GLOBAL_FORCE_TO_PCI);
+    OUTREG(R128_BM_CHUNK_0_VAL, chunk);
+
+    OUTREG(R128_PCI_GART_PAGE, 1); /* Ensure AGP GART is used (for now) */
+
+    return GL_TRUE;
+}
+
+static GLboolean R128DRIPciInit(const DRIDriverContext *ctx)
+{
+    R128InfoPtr info = ctx->driverPrivate;
+    unsigned char *R128MMIO = ctx->MMIOAddress;
+    CARD32 chunk;
+    int ret;
+    int flags;
+
+    info->agpOffset = 0;
+
+    ret = drmScatterGatherAlloc(ctx->drmFD, info->agpSize*1024*1024,
+                               &info->pciMemHandle);
+    if (ret < 0) {
+       fprintf(stderr, "[pci] Out of memory (%d)\n", ret);
+       return GL_FALSE;
+    }
+    fprintf(stderr,
+              "[pci] %d kB allocated with handle 0x%08x\n",
+              info->agpSize*1024, info->pciMemHandle);
+
+                               /* Initialize the CCE ring buffer data */
+    info->ringStart       = info->agpOffset;
+    info->ringMapSize     = info->ringSize*1024*1024 + DRM_PAGE_SIZE;
+    info->ringSizeLog2QW  = R128MinBits(info->ringSize*1024*1024/8) - 1;
+
+    info->ringReadOffset  = info->ringStart + info->ringMapSize;
+    info->ringReadMapSize = DRM_PAGE_SIZE;
+
+                               /* Reserve space for vertex/indirect buffers */
+    info->bufStart        = info->ringReadOffset + info->ringReadMapSize;
+    info->bufMapSize      = info->bufSize*1024*1024;
+
+    flags = DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL;
+
+    if (drmAddMap(ctx->drmFD, info->ringStart, info->ringMapSize,
+                 DRM_SCATTER_GATHER, flags, &info->ringHandle) < 0) {
+       fprintf(stderr,
+                  "[pci] Could not add ring mapping\n");
+       return GL_FALSE;
+    }
+    fprintf(stderr,
+              "[pci] ring handle = 0x%08lx\n", info->ringHandle);
+
+    if (drmMap(ctx->drmFD, info->ringHandle, info->ringMapSize,
+              (drmAddressPtr)&info->ring) < 0) {
+       fprintf(stderr, "[pci] Could not map ring\n");
+       return GL_FALSE;
+    }
+    fprintf(stderr,
+              "[pci] Ring mapped at 0x%08lx\n",
+              (unsigned long)info->ring);
+    fprintf(stderr,
+              "[pci] Ring contents 0x%08lx\n",
+              *(unsigned long *)info->ring);
+
+    if (drmAddMap(ctx->drmFD, info->ringReadOffset, info->ringReadMapSize,
+                 DRM_SCATTER_GATHER, flags, &info->ringReadPtrHandle) < 0) {
+       fprintf(stderr,
+                  "[pci] Could not add ring read ptr mapping\n");
+       return GL_FALSE;
+    }
+    fprintf(stderr,
+              "[pci] ring read ptr handle = 0x%08lx\n",
+              info->ringReadPtrHandle);
+
+    if (drmMap(ctx->drmFD, info->ringReadPtrHandle, info->ringReadMapSize,
+              (drmAddressPtr)&info->ringReadPtr) < 0) {
+       fprintf(stderr,
+                  "[pci] Could not map ring read ptr\n");
+       return GL_FALSE;
+    }
+    fprintf(stderr,
+              "[pci] Ring read ptr mapped at 0x%08lx\n",
+              (unsigned long)info->ringReadPtr);
+    fprintf(stderr,
+              "[pci] Ring read ptr contents 0x%08lx\n",
+              *(unsigned long *)info->ringReadPtr);
+
+    if (drmAddMap(ctx->drmFD, info->bufStart, info->bufMapSize,
+                 DRM_SCATTER_GATHER, 0, &info->bufHandle) < 0) {
+       fprintf(stderr,
+                  "[pci] Could not add vertex/indirect buffers mapping\n");
+       return GL_FALSE;
+    }
+    fprintf(stderr,
+              "[pci] vertex/indirect buffers handle = 0x%08lx\n",
+              info->bufHandle);
+
+    if (drmMap(ctx->drmFD, info->bufHandle, info->bufMapSize,
+              (drmAddressPtr)&info->buf) < 0) {
+       fprintf(stderr,
+                  "[pci] Could not map vertex/indirect buffers\n");
+       return GL_FALSE;
+    }
+    fprintf(stderr,
+              "[pci] Vertex/indirect buffers mapped at 0x%08lx\n",
+              (unsigned long)info->buf);
+    fprintf(stderr,
+              "[pci] Vertex/indirect buffers contents 0x%08lx\n",
+              *(unsigned long *)info->buf);
+
+    if (!info->IsPCI) {
+       /* This is really an AGP card, force PCI GART mode */
+        chunk = INREG(R128_BM_CHUNK_0_VAL);
+        chunk |= (R128_BM_PTR_FORCE_TO_PCI |
+                 R128_BM_PM4_RD_FORCE_TO_PCI |
+                 R128_BM_GLOBAL_FORCE_TO_PCI);
+        OUTREG(R128_BM_CHUNK_0_VAL, chunk);
+        OUTREG(R128_PCI_GART_PAGE, 0); /* Ensure PCI GART is used */
+    }
+
+    return GL_TRUE;
+}
+
+/* Add a map for the MMIO registers that will be accessed by any
+   DRI-based clients. */
+static GLboolean R128DRIMapInit(const DRIDriverContext *ctx)
+{
+    R128InfoPtr info = ctx->driverPrivate;
+    int flags;
+
+    if (info->CCESecure) flags = DRM_READ_ONLY;
+    else                 flags = 0;
+
+                               /* Map registers */
+    if (drmAddMap(ctx->drmFD, ctx->MMIOStart, ctx->MMIOSize,
+                 DRM_REGISTERS, flags, &info->registerHandle) < 0) {
+       return GL_FALSE;
+    }
+    fprintf(stderr,
+              "[drm] register handle = 0x%08lx\n", info->registerHandle);
+
+    return GL_TRUE;
+}
+
+/* Initialize the kernel data structures. */
+static int R128DRIKernelInit(const DRIDriverContext *ctx)
+{
+    R128InfoPtr info = ctx->driverPrivate;
+    drmR128Init drmInfo;
+
+    memset( &drmInfo, 0, sizeof(drmR128Init) );
+
+    drmInfo.func                = DRM_R128_INIT_CCE;
+    drmInfo.sarea_priv_offset   = sizeof(XF86DRISAREARec);
+    drmInfo.is_pci              = info->IsPCI;
+    drmInfo.cce_mode            = info->CCEMode;
+    drmInfo.cce_secure          = info->CCESecure;
+    drmInfo.ring_size           = info->ringSize*1024*1024;
+    drmInfo.usec_timeout        = info->CCEusecTimeout;
+
+    drmInfo.fb_bpp              = ctx->bpp;
+    drmInfo.depth_bpp           = ctx->bpp;
+
+    drmInfo.front_offset        = info->frontOffset;
+    drmInfo.front_pitch         = info->frontPitch;
+
+    drmInfo.back_offset         = info->backOffset;
+    drmInfo.back_pitch          = info->backPitch;
+
+    drmInfo.depth_offset        = info->depthOffset;
+    drmInfo.depth_pitch         = info->depthPitch;
+    drmInfo.span_offset         = info->spanOffset;
+
+    drmInfo.fb_offset           = info->LinearAddr;
+    drmInfo.mmio_offset         = info->registerHandle;
+    drmInfo.ring_offset         = info->ringHandle;
+    drmInfo.ring_rptr_offset    = info->ringReadPtrHandle;
+    drmInfo.buffers_offset      = info->bufHandle;
+    drmInfo.agp_textures_offset = info->agpTexHandle;
+
+    if (drmCommandWrite(ctx->drmFD, DRM_R128_INIT,
+                        &drmInfo, sizeof(drmR128Init)) < 0)
+        return GL_FALSE;
+
+    return GL_TRUE;
+}
+
+/* Add a map for the vertex buffers that will be accessed by any
+   DRI-based clients. */
+static GLboolean R128DRIBufInit(const DRIDriverContext *ctx)
+{
+    R128InfoPtr info = ctx->driverPrivate;
+                               /* Initialize vertex buffers */
+    if (info->IsPCI) {
+       info->bufNumBufs = drmAddBufs(ctx->drmFD,
+                                     info->bufMapSize / R128_BUFFER_SIZE,
+                                     R128_BUFFER_SIZE,
+                                     DRM_SG_BUFFER,
+                                     info->bufStart);
+    } else {
+       info->bufNumBufs = drmAddBufs(ctx->drmFD,
+                                     info->bufMapSize / R128_BUFFER_SIZE,
+                                     R128_BUFFER_SIZE,
+                                     DRM_AGP_BUFFER,
+                                     info->bufStart);
+    }
+    if (info->bufNumBufs <= 0) {
+       fprintf(stderr,
+                  "[drm] Could not create vertex/indirect buffers list\n");
+       return GL_FALSE;
+    }
+    fprintf(stderr,
+              "[drm] Added %d %d byte vertex/indirect buffers\n",
+              info->bufNumBufs, R128_BUFFER_SIZE);
+
+    if (!(info->buffers = drmMapBufs(ctx->drmFD))) {
+       fprintf(stderr,
+                  "[drm] Failed to map vertex/indirect buffers list\n");
+       return GL_FALSE;
+    }
+    fprintf(stderr,
+              "[drm] Mapped %d vertex/indirect buffers\n",
+              info->buffers->count);
+
+    return GL_TRUE;
+}
+
+static void R128DRIIrqInit(const DRIDriverContext *ctx)
+{
+   R128InfoPtr info = ctx->driverPrivate;
+   unsigned char *R128MMIO = ctx->MMIOAddress;
+   
+   if (!info->irq) {
+       info->irq = drmGetInterruptFromBusID(
+          ctx->drmFD,
+          ctx->pciBus,
+          ctx->pciDevice,
+          ctx->pciFunc);
+
+      if((drmCtlInstHandler(ctx->drmFD, info->irq)) != 0) {
+        fprintf(stderr,
+                   "[drm] failure adding irq handler, "
+                   "there is a device already using that irq\n"
+                   "[drm] falling back to irq-free operation\n");
+        info->irq = 0;
+      } else {
+          info->gen_int_cntl = INREG( R128_GEN_INT_CNTL );
+      }
+   }
+
+   if (info->irq)
+      fprintf(stderr,
+                "[drm] dma control initialized, using IRQ %d\n",
+                info->irq);
+}
+
+static int R128CCEStop(const DRIDriverContext *ctx)
+{
+    R128InfoPtr info = ctx->driverPrivate;
+    drmR128CCEStop stop;
+    int            ret, i;
+
+    stop.flush = 1;
+    stop.idle  = 1;
+
+    ret = drmCommandWrite( ctx->drmFD, DRM_R128_CCE_STOP,
+                           &stop, sizeof(drmR128CCEStop) );
+
+    if ( ret == 0 ) {
+        return 0;
+    } else if ( errno != EBUSY ) {
+        return -errno;
+    }
+
+    stop.flush = 0;
+
+    i = 0;
+    do {
+        ret = drmCommandWrite( ctx->drmFD, DRM_R128_CCE_STOP,
+                               &stop, sizeof(drmR128CCEStop) );
+    } while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY );
+
+    if ( ret == 0 ) {
+        return 0;
+    } else if ( errno != EBUSY ) {
+        return -errno;
+    }
+
+    stop.idle = 0;
+
+    if ( drmCommandWrite( ctx->drmFD, DRM_R128_CCE_STOP,
+                          &stop, sizeof(drmR128CCEStop) )) {
+        return -errno;
+    } else {
+        return 0;
+    }
+}
+
+/* Initialize the CCE state, and start the CCE (if used by the X server) */
+static void R128DRICCEInit(const DRIDriverContext *ctx)
+{
+   R128InfoPtr info = ctx->driverPrivate;
+
+                               /* Turn on bus mastering */
+    info->BusCntl &= ~R128_BUS_MASTER_DIS;
+
+                               /* CCEMode is initialized in r128_driver.c */
+    switch (info->CCEMode) {
+    case R128_PM4_NONPM4:                 info->CCEFifoSize = 0;   break;
+    case R128_PM4_192PIO:                 info->CCEFifoSize = 192; break;
+    case R128_PM4_192BM:                  info->CCEFifoSize = 192; break;
+    case R128_PM4_128PIO_64INDBM:         info->CCEFifoSize = 128; break;
+    case R128_PM4_128BM_64INDBM:          info->CCEFifoSize = 128; break;
+    case R128_PM4_64PIO_128INDBM:         info->CCEFifoSize = 64;  break;
+    case R128_PM4_64BM_128INDBM:          info->CCEFifoSize = 64;  break;
+    case R128_PM4_64PIO_64VCBM_64INDBM:   info->CCEFifoSize = 64;  break;
+    case R128_PM4_64BM_64VCBM_64INDBM:    info->CCEFifoSize = 64;  break;
+    case R128_PM4_64PIO_64VCPIO_64INDPIO: info->CCEFifoSize = 64;  break;
+    }
+
+    /* Make sure the CCE is on for the X server */
+    R128CCE_START(ctx, info);
+}
+
+
+static int R128MemoryInit(const DRIDriverContext *ctx)
+{
+   R128InfoPtr info = ctx->driverPrivate;
+   int        width_bytes = ctx->shared.virtualWidth * ctx->cpp;
+   int        cpp         = ctx->cpp;
+   int        bufferSize  = ((ctx->shared.virtualHeight * width_bytes
+                             + R128_BUFFER_ALIGN)
+                            & ~R128_BUFFER_ALIGN);
+   int        depthSize   = ((((ctx->shared.virtualHeight+15) & ~15) * width_bytes
+                             + R128_BUFFER_ALIGN)
+                            & ~R128_BUFFER_ALIGN);
+   int        l;
+
+   info->frontOffset = 0;
+   info->frontPitch = ctx->shared.virtualWidth;
+
+   fprintf(stderr, 
+          "Using %d MB AGP aperture\n", info->agpSize);
+   fprintf(stderr, 
+          "Using %d MB for the ring buffer\n", info->ringSize);
+   fprintf(stderr, 
+          "Using %d MB for vertex/indirect buffers\n", info->bufSize);
+   fprintf(stderr, 
+          "Using %d MB for AGP textures\n", info->agpTexSize);
+
+   /* Front, back and depth buffers - everything else texture??
+    */
+   info->textureSize = ctx->shared.fbSize - 2 * bufferSize - depthSize;
+
+   if (info->textureSize < 0) 
+      return 0;
+
+   l = R128MinBits((info->textureSize-1) / R128_NR_TEX_REGIONS);
+   if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY;
+
+   /* Round the texture size up to the nearest whole number of
+    * texture regions.  Again, be greedy about this, don't
+    * round down.
+    */
+   info->log2TexGran = l;
+   info->textureSize = (info->textureSize >> l) << l;
+
+   /* Set a minimum usable local texture heap size.  This will fit
+    * two 256x256x32bpp textures.
+    */
+   if (info->textureSize < 512 * 1024) {
+      info->textureOffset = 0;
+      info->textureSize = 0;
+   }
+
+   /* Reserve space for textures */
+   info->textureOffset = ((ctx->shared.fbSize - info->textureSize +
+                          R128_BUFFER_ALIGN) &
+                         ~R128_BUFFER_ALIGN);
+
+   /* Reserve space for the shared depth
+    * buffer.
+    */
+   info->depthOffset = ((info->textureOffset - depthSize +
+                        R128_BUFFER_ALIGN) &
+                       ~R128_BUFFER_ALIGN);
+   info->depthPitch = ctx->shared.virtualWidth;
+
+   info->backOffset = ((info->depthOffset - bufferSize +
+                       R128_BUFFER_ALIGN) &
+                      ~R128_BUFFER_ALIGN);
+   info->backPitch = ctx->shared.virtualWidth;
+
+
+   fprintf(stderr, 
+          "Will use back buffer at offset 0x%x\n",
+          info->backOffset);
+   fprintf(stderr, 
+          "Will use depth buffer at offset 0x%x\n",
+          info->depthOffset);
+   fprintf(stderr, 
+          "Will use %d kb for textures at offset 0x%x\n",
+          info->textureSize/1024, info->textureOffset);
+
+   return 1;
+} 
+
+
+/* Initialize the screen-specific data structures for the DRI and the
+   Rage 128.  This is the main entry point to the device-specific
+   initialization code.  It calls device-independent DRI functions to
+   create the DRI data structures and initialize the DRI state. */
+static GLboolean R128DRIScreenInit(DRIDriverContext *ctx)
+{
+    R128InfoPtr info = ctx->driverPrivate;
+    R128DRIPtr    pR128DRI;
+    int           err, major, minor, patch;
+    drmVersionPtr version;
+
+    switch (ctx->bpp) {
+    case 8:
+       /* These modes are not supported (yet). */
+    case 15:
+    case 24:
+       fprintf(stderr,
+                  "[dri] R128DRIScreenInit failed (depth %d not supported).  "
+                  "[dri] Disabling DRI.\n", ctx->bpp);
+       return GL_FALSE;
+
+       /* Only 16 and 32 color depths are supports currently. */
+    case 16:
+    case 32:
+       break;
+    }
+
+    info->registerSize = ctx->MMIOSize;
+    ctx->shared.SAREASize = DRM_PAGE_SIZE;
+
+    /* Note that drmOpen will try to load the kernel module, if needed. */
+    ctx->drmFD = drmOpen("r128", NULL );
+    if (ctx->drmFD < 0) {
+       fprintf(stderr, "[drm] drmOpen failed\n");
+       return 0;
+    }
+    
+    /* Check the r128 DRM version */
+    version = drmGetVersion(ctx->drmFD);
+    if (version) {
+       if (version->version_major != 2 ||
+           version->version_minor < 2) {
+           /* incompatible drm version */
+           fprintf(stderr,
+               "[dri] R128DRIScreenInit failed because of a version mismatch.\n"
+               "[dri] r128.o kernel module version is %d.%d.%d but version 2.2 or greater is needed.\n"
+               "[dri] Disabling the DRI.\n",
+               version->version_major,
+               version->version_minor,
+               version->version_patchlevel);
+           drmFreeVersion(version);
+           return GL_FALSE;
+       }
+       info->drmMinor = version->version_minor;
+       drmFreeVersion(version);
+    }
+    
+    if ((err = drmSetBusid(ctx->drmFD, ctx->pciBusID)) < 0) {
+       fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n",
+               ctx->drmFD, ctx->pciBusID, strerror(-err));
+       return 0;
+    }
+    
+   if (drmAddMap( ctx->drmFD,
+                 0,
+                 ctx->shared.SAREASize,
+                 DRM_SHM,
+                 DRM_CONTAINS_LOCK,
+                 &ctx->shared.hSAREA) < 0)
+   {
+      fprintf(stderr, "[drm] drmAddMap failed\n");
+      return 0;
+   }
+   fprintf(stderr, "[drm] added %d byte SAREA at 0x%08lx\n",
+          ctx->shared.SAREASize, ctx->shared.hSAREA);
+
+   if (drmMap( ctx->drmFD,
+              ctx->shared.hSAREA,
+              ctx->shared.SAREASize,
+              (drmAddressPtr)(&ctx->pSAREA)) < 0)
+   {
+      fprintf(stderr, "[drm] drmMap failed\n");
+      return 0;
+   }
+   memset(ctx->pSAREA, 0, ctx->shared.SAREASize);
+   fprintf(stderr, "[drm] mapped SAREA 0x%08lx to %p, size %d\n",
+          ctx->shared.hSAREA, ctx->pSAREA, ctx->shared.SAREASize);
+   
+   /* Need to AddMap the framebuffer and mmio regions here:
+    */
+   if (drmAddMap( ctx->drmFD,
+                 (drmHandle)ctx->FBStart,
+                 ctx->FBSize,
+                 DRM_FRAME_BUFFER,
+                 0,
+                 &ctx->shared.hFrameBuffer) < 0)
+   {
+      fprintf(stderr, "[drm] drmAddMap framebuffer failed\n");
+      return 0;
+   }
+
+   fprintf(stderr, "[drm] framebuffer handle = 0x%08lx\n",
+          ctx->shared.hFrameBuffer);
+
+   if (!R128MemoryInit(ctx))
+       return GL_FALSE;
+   
+                               /* Initialize AGP */
+    if (!info->IsPCI && !R128DRIAgpInit(ctx)) {
+       info->IsPCI = GL_TRUE;
+       fprintf(stderr,
+                  "[agp] AGP failed to initialize -- falling back to PCI mode.\n");
+       fprintf(stderr,
+                  "[agp] Make sure you have the agpgart kernel module loaded.\n");
+    }
+
+                               /* Initialize PCIGART */
+    if (info->IsPCI && !R128DRIPciInit(ctx)) {
+       return GL_FALSE;
+    }
+
+                               /* DRIScreenInit doesn't add all the
+                                  common mappings.  Add additional
+                                  mappings here. */
+    if (!R128DRIMapInit(ctx)) {
+       return GL_FALSE;
+    }
+
+   /* Create a 'server' context so we can grab the lock for
+    * initialization ioctls.
+    */
+   if ((err = drmCreateContext(ctx->drmFD, &ctx->serverContext)) != 0) {
+      fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err);
+      return 0;
+   }
+
+   DRM_LOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext, 0); 
+
+    /* Initialize the kernel data structures */
+    if (!R128DRIKernelInit(ctx)) {
+       return GL_FALSE;
+    }
+
+    /* Initialize the vertex buffers list */
+    if (!R128DRIBufInit(ctx)) {
+       return GL_FALSE;
+    }
+
+    /* Initialize IRQ */
+    R128DRIIrqInit(ctx);
+
+    /* Initialize and start the CCE if required */
+    R128DRICCEInit(ctx);
+
+   /* Quick hack to clear the front & back buffers.  Could also use
+    * the clear ioctl to do this, but would need to setup hw state
+    * first.
+    */
+   memset((char *)ctx->FBAddress + info->frontOffset,
+         0,
+         info->frontPitch * ctx->cpp * ctx->shared.virtualHeight );
+
+   memset((char *)ctx->FBAddress + info->backOffset,
+         0,
+         info->backPitch * ctx->cpp * ctx->shared.virtualHeight );
+    
+    R128SAREAPrivPtr pSAREAPriv;
+    pSAREAPriv = (R128SAREAPrivPtr)(((char*)ctx->pSAREA) + 
+                                       sizeof(XF86DRISAREARec));
+    memset(pSAREAPriv, 0, sizeof(*pSAREAPriv));
+
+   /* This is the struct passed to radeon_dri.so for its initialization */
+   ctx->driverClientMsg = malloc(sizeof(R128DRIRec));
+   ctx->driverClientMsgSize = sizeof(R128DRIRec);
+   
+    pR128DRI                    = (R128DRIPtr)ctx->driverClientMsg;
+    pR128DRI->deviceID          = info->Chipset;
+    pR128DRI->width             = ctx->shared.virtualWidth;
+    pR128DRI->height            = ctx->shared.virtualHeight;
+    pR128DRI->depth             = ctx->bpp;
+    pR128DRI->bpp               = ctx->bpp;
+
+    pR128DRI->IsPCI             = info->IsPCI;
+    pR128DRI->AGPMode           = info->agpMode;
+
+    pR128DRI->frontOffset       = info->frontOffset;
+    pR128DRI->frontPitch        = info->frontPitch;
+    pR128DRI->backOffset        = info->backOffset;
+    pR128DRI->backPitch         = info->backPitch;
+    pR128DRI->depthOffset       = info->depthOffset;
+    pR128DRI->depthPitch        = info->depthPitch;
+    pR128DRI->spanOffset        = info->spanOffset;
+    pR128DRI->textureOffset     = info->textureOffset;
+    pR128DRI->textureSize       = info->textureSize;
+    pR128DRI->log2TexGran       = info->log2TexGran;
+
+    pR128DRI->registerHandle    = info->registerHandle;
+    pR128DRI->registerSize      = info->registerSize;
+
+    pR128DRI->agpTexHandle      = info->agpTexHandle;
+    pR128DRI->agpTexMapSize     = info->agpTexMapSize;
+    pR128DRI->log2AGPTexGran    = info->log2AGPTexGran;
+    pR128DRI->agpTexOffset      = info->agpTexStart;
+    pR128DRI->sarea_priv_offset = sizeof(XF86DRISAREARec);
+
+    return GL_TRUE;
+}
+
+/* The screen is being closed, so clean up any state and free any
+   resources used by the DRI. */
+void R128DRICloseScreen(const DRIDriverContext *ctx)
+{
+    R128InfoPtr info = ctx->driverPrivate;
+    drmR128Init drmInfo;
+
+    /* Stop the CCE if it is still in use */
+    R128CCE_STOP(ctx, info);
+
+    if (info->irq) {
+       drmCtlUninstHandler(ctx->drmFD);
+       info->irq = 0;
+    }
+
+    /* De-allocate vertex buffers */
+    if (info->buffers) {
+       drmUnmapBufs(info->buffers);
+       info->buffers = NULL;
+    }
+
+    /* De-allocate all kernel resources */
+    memset(&drmInfo, 0, sizeof(drmR128Init));
+    drmInfo.func = DRM_R128_CLEANUP_CCE;
+    drmCommandWrite(ctx->drmFD, DRM_R128_INIT,
+                    &drmInfo, sizeof(drmR128Init));
+
+    /* De-allocate all AGP resources */
+    if (info->agpTex) {
+       drmUnmap(info->agpTex, info->agpTexMapSize);
+       info->agpTex = NULL;
+    }
+    if (info->buf) {
+       drmUnmap(info->buf, info->bufMapSize);
+       info->buf = NULL;
+    }
+    if (info->ringReadPtr) {
+       drmUnmap(info->ringReadPtr, info->ringReadMapSize);
+       info->ringReadPtr = NULL;
+    }
+    if (info->ring) {
+       drmUnmap(info->ring, info->ringMapSize);
+       info->ring = NULL;
+    }
+    if (info->agpMemHandle != DRM_AGP_NO_HANDLE) {
+       drmAgpUnbind(ctx->drmFD, info->agpMemHandle);
+       drmAgpFree(ctx->drmFD, info->agpMemHandle);
+       info->agpMemHandle = 0;
+       drmAgpRelease(ctx->drmFD);
+    }
+    if (info->pciMemHandle) {
+       drmScatterGatherFree(ctx->drmFD, info->pciMemHandle);
+       info->pciMemHandle = 0;
+    }
+}
+
+static GLboolean R128PreInitDRI(const DRIDriverContext *ctx)
+{
+    R128InfoPtr info = ctx->driverPrivate;
+
+    /*info->CCEMode = R128_DEFAULT_CCE_PIO_MODE;*/
+    info->CCEMode = R128_DEFAULT_CCE_BM_MODE;
+    info->CCESecure = GL_TRUE;
+
+    info->agpMode        = R128_DEFAULT_AGP_MODE;
+    info->agpSize        = R128_DEFAULT_AGP_SIZE;
+    info->ringSize       = R128_DEFAULT_RING_SIZE;
+    info->bufSize        = R128_DEFAULT_BUFFER_SIZE;
+    info->agpTexSize     = R128_DEFAULT_AGP_TEX_SIZE;
+
+    info->CCEusecTimeout = R128_DEFAULT_CCE_TIMEOUT;
+
+    return GL_TRUE;
+}
+
+/**
+ * \brief Initialize the framebuffer device mode
+ *
+ * \param ctx display handle.
+ *
+ * \return one on success, or zero on failure.
+ *
+ * Fills in \p info with some default values and some information from \p ctx
+ * and then calls R128ScreenInit() for the screen initialization.
+ * 
+ * Before exiting clears the framebuffer memory accessing it directly.
+ */
+static int R128InitFBDev( DRIDriverContext *ctx )
+{
+   R128InfoPtr info = calloc(1, sizeof(*info));
+
+   {
+      int  dummy = ctx->shared.virtualWidth;
+
+      switch (ctx->bpp / 8) {
+      case 1: dummy = (ctx->shared.virtualWidth + 127) & ~127; break;
+      case 2: dummy = (ctx->shared.virtualWidth +  31) &  ~31; break;
+      case 3:
+      case 4: dummy = (ctx->shared.virtualWidth +  15) &  ~15; break;
+      }
+
+      ctx->shared.virtualWidth = dummy;
+   }
+
+   ctx->driverPrivate = (void *)info;
+   
+   info->Chipset = ctx->chipset;
+
+   switch (info->Chipset) {
+   case PCI_DEVICE_ID_ATI_RAGE128_LE:
+   case PCI_DEVICE_ID_ATI_RAGE128_RE:
+   case PCI_DEVICE_ID_ATI_RAGE128_RK:
+   case PCI_DEVICE_ID_ATI_RAGE128_PD:
+   case PCI_DEVICE_ID_ATI_RAGE128_PP:
+   case PCI_DEVICE_ID_ATI_RAGE128_PR:
+       /* This is a PCI card */
+       info->IsPCI = GL_TRUE;
+       break;
+   default:
+       /* This is an AGP card */
+       info->IsPCI = GL_FALSE;
+       break;
+   }
+
+   info->frontPitch = ctx->shared.virtualWidth;
+   info->LinearAddr = ctx->FBStart & 0xfc000000;
+   
+   if (!R128PreInitDRI(ctx))
+       return 0;
+
+   if (!R128DRIScreenInit(ctx))
+      return 0;
+
+   return 1;
+}
+
+
+/**
+ * \brief The screen is being closed, so clean up any state and free any
+ * resources used by the DRI.
+ *
+ * \param ctx display handle.
+ *
+ * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver
+ * private data.
+ */
+static void R128HaltFBDev( DRIDriverContext *ctx )
+{
+    drmUnmap( ctx->pSAREA, ctx->shared.SAREASize );
+    drmClose(ctx->drmFD);
+
+    if (ctx->driverPrivate) {
+       free(ctx->driverPrivate);
+       ctx->driverPrivate = 0;
+    }
+}
+
+
+/**
+ * \brief Validate the fbdev mode.
+ * 
+ * \param ctx display handle.
+ *
+ * \return one on success, or zero on failure.
+ *
+ * Saves some registers and returns 1.
+ *
+ * \sa R128PostValidateMode().
+ */
+static int R128ValidateMode( const DRIDriverContext *ctx )
+{
+   return 1;
+}
+
+
+/**
+ * \brief Examine mode returned by fbdev.
+ * 
+ * \param ctx display handle.
+ *
+ * \return one on success, or zero on failure.
+ *
+ * Restores registers that fbdev has clobbered and returns 1.
+ *
+ * \sa R128ValidateMode().
+ */
+static int R128PostValidateMode( const DRIDriverContext *ctx )
+{
+   return 1;
+}
+
+
+/**
+ * \brief Shutdown the drawing engine.
+ *
+ * \param ctx display handle
+ *
+ * Turns off the command processor engine & restores the graphics card
+ * to a state that fbdev understands.
+ */
+static int R128EngineShutdown( const DRIDriverContext *ctx )
+{
+    return 1;
+}
+
+/**
+ * \brief Restore the drawing engine.
+ *
+ * \param ctx display handle
+ *
+ * Resets the graphics card and sets initial values for several registers of
+ * the card's drawing engine.
+ *
+ * Turns on the R128 command processor engine (i.e., the ringbuffer).
+ */
+static int R128EngineRestore( const DRIDriverContext *ctx )
+{
+   return 1;
+}
+
+
+/**
+ * \brief Exported driver interface for Mini GLX.
+ *
+ * \sa DRIDriverRec.
+ */
+const struct DRIDriverRec __driDriver = {
+   R128InitContextModes,
+   R128ValidateMode,
+   R128PostValidateMode,
+   R128InitFBDev,
+   R128HaltFBDev,
+   R128EngineShutdown,
+   R128EngineRestore,  
+   0,
+};
diff --git a/src/mesa/drivers/dri/r128/server/r128_dri.h b/src/mesa/drivers/dri/r128/server/r128_dri.h
new file mode 100644 (file)
index 0000000..80f94de
--- /dev/null
@@ -0,0 +1,103 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_dri.h,v 1.7 2002/10/30 12:52:12 alanh Exp $ */
+/*
+ * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
+ *                      Precision Insight, Inc., Cedar Park, Texas, and
+ *                      VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
+ * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Rickard E. Faith <faith@valinux.com>
+ *   Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#ifndef _R128_DRI_
+#define _R128_DRI_
+
+#include "xf86drm.h"
+#include "r128_common.h"
+
+/* DRI Driver defaults */
+#define R128_DEFAULT_CCE_PIO_MODE R128_PM4_64PIO_64VCBM_64INDBM
+#define R128_DEFAULT_CCE_BM_MODE  R128_PM4_64BM_64VCBM_64INDBM
+#define R128_DEFAULT_AGP_MODE     1
+#define R128_DEFAULT_AGP_SIZE     8 /* MB (must be a power of 2 and > 4MB) */
+#define R128_DEFAULT_RING_SIZE    1 /* MB (must be page aligned) */
+#define R128_DEFAULT_BUFFER_SIZE  2 /* MB (must be page aligned) */
+#define R128_DEFAULT_AGP_TEX_SIZE 1 /* MB (must be page aligned) */
+
+#define R128_DEFAULT_CCE_TIMEOUT  10000  /* usecs */
+
+#define R128_AGP_MAX_MODE         4
+#define R128_BUFFER_ALIGN         0x00000fff
+
+#define R128_CARD_TYPE_R128          1
+#define R128_CARD_TYPE_R128_PRO      2
+#define R128_CARD_TYPE_R128_MOBILITY 3
+
+#define R128CCE_USE_RING_BUFFER(m)                                        \
+(((m) == R128_PM4_192BM) ||                                               \
+ ((m) == R128_PM4_128BM_64INDBM) ||                                       \
+ ((m) == R128_PM4_64BM_128INDBM) ||                                       \
+ ((m) == R128_PM4_64BM_64VCBM_64INDBM))
+
+typedef struct {
+    /* DRI screen private data */
+    int           deviceID;     /* PCI device ID */
+    int           width;        /* Width in pixels of display */
+    int           height;       /* Height in scanlines of display */
+    int           depth;        /* Depth of display (8, 15, 16, 24) */
+    int           bpp;          /* Bit depth of display (8, 16, 24, 32) */
+
+    int           IsPCI;        /* Current card is a PCI card */
+    int           AGPMode;
+
+    int           frontOffset;  /* Start of front buffer */
+    int           frontPitch;
+    int           backOffset;   /* Start of shared back buffer */
+    int           backPitch;
+    int           depthOffset;  /* Start of shared depth buffer */
+    int           depthPitch;
+    int           spanOffset;   /* Start of scratch spanline */
+    int           textureOffset;/* Start of texture data in frame buffer */
+    int           textureSize;
+    int           log2TexGran;
+
+    /* MMIO register data */
+    drmHandle     registerHandle;
+    drmSize       registerSize;
+
+    /* CCE AGP Texture data */
+    drmHandle     agpTexHandle;
+    drmSize       agpTexMapSize;
+    int           log2AGPTexGran;
+    int           agpTexOffset;
+    unsigned int  sarea_priv_offset;
+} R128DRIRec, *R128DRIPtr;
+
+#endif
diff --git a/src/mesa/drivers/dri/r128/server/r128_macros.h b/src/mesa/drivers/dri/r128/server/r128_macros.h
new file mode 100644 (file)
index 0000000..93b7feb
--- /dev/null
@@ -0,0 +1,135 @@
+/**
+ * \file server/R128_macros.h
+ * \brief Macros for R128 MMIO operation.
+ *
+ * \authors Kevin E. Martin <martin@xfree86.org>
+ * \authors Rickard E. Faith <faith@valinux.com>
+ * \authors Alan Hourihane <alanh@fairlite.demon.co.uk>
+ */
+
+/*
+ * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
+ *                VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
+ * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/R128_reg.h,v 1.20 2002/10/12 01:38:07 martin Exp $ */
+
+#ifndef _R128_MACROS_H_
+#define _R128_MACROS_H_
+
+
+
+#  define MMIO_IN8(base, offset) \
+       *(volatile unsigned char *)(((unsigned char*)(base)) + (offset))
+#  define MMIO_IN16(base, offset) \
+       *(volatile unsigned short *)(void *)(((unsigned char*)(base)) + (offset))
+#  define MMIO_IN32(base, offset) \
+       *(volatile unsigned int *)(void *)(((unsigned char*)(base)) + (offset))
+#  define MMIO_OUT8(base, offset, val) \
+       *(volatile unsigned char *)(((unsigned char*)(base)) + (offset)) = (val)
+#  define MMIO_OUT16(base, offset, val) \
+       *(volatile unsigned short *)(void *)(((unsigned char*)(base)) + (offset)) = (val)
+#  define MMIO_OUT32(base, offset, val) \
+       *(volatile unsigned int *)(void *)(((unsigned char*)(base)) + (offset)) = (val)
+
+
+                               /* Memory mapped register access macros */
+#define INREG8(addr)        MMIO_IN8(R128MMIO, addr)
+#define INREG16(addr)       MMIO_IN16(R128MMIO, addr)
+#define INREG(addr)         MMIO_IN32(R128MMIO, addr)
+#define OUTREG8(addr, val)  MMIO_OUT8(R128MMIO, addr, val)
+#define OUTREG16(addr, val) MMIO_OUT16(R128MMIO, addr, val)
+#define OUTREG(addr, val)   MMIO_OUT32(R128MMIO, addr, val)
+
+#define ADDRREG(addr)       ((volatile GLuint *)(pointer)(R128MMIO + (addr)))
+
+
+#define OUTREGP(addr, val, mask)                                       \
+do {                                                                   \
+    GLuint tmp = INREG(addr);                                          \
+    tmp &= (mask);                                                     \
+    tmp |= (val);                                                      \
+    OUTREG(addr, tmp);                                                 \
+} while (0)
+
+#define INPLL(dpy, addr) r128INPLL(dpy, addr)
+
+#define OUTPLL(addr, val)                                              \
+do {                                                                   \
+    OUTREG8(R128_CLOCK_CNTL_INDEX, (((addr) & 0x3f) |                  \
+                                     R128_PLL_WR_EN));         \
+    OUTREG(R128_CLOCK_CNTL_DATA, val);                         \
+} while (0)
+
+#define OUTPLLP(dpy, addr, val, mask)                                  \
+do {                                                                   \
+    GLuint tmp = INPLL(dpy, addr);                                     \
+    tmp &= (mask);                                                     \
+    tmp |= (val);                                                      \
+    OUTPLL(addr, tmp);                                                 \
+} while (0)
+
+#define OUTPAL_START(idx)                                              \
+do {                                                                   \
+    OUTREG8(R128_PALETTE_INDEX, (idx));                                \
+} while (0)
+
+#define OUTPAL_NEXT(r, g, b)                                           \
+do {                                                                   \
+    OUTREG(R128_PALETTE_DATA, ((r) << 16) | ((g) << 8) | (b)); \
+} while (0)
+
+#define OUTPAL_NEXT_CARD32(v)                                          \
+do {                                                                   \
+    OUTREG(R128_PALETTE_DATA, (v & 0x00ffffff));                       \
+} while (0)
+
+#define OUTPAL(idx, r, g, b)                                           \
+do {                                                                   \
+    OUTPAL_START((idx));                                               \
+    OUTPAL_NEXT((r), (g), (b));                                                \
+} while (0)
+
+#define INPAL_START(idx)                                               \
+do {                                                                   \
+    OUTREG(R128_PALETTE_INDEX, (idx) << 16);                           \
+} while (0)
+
+#define INPAL_NEXT() INREG(R128_PALETTE_DATA)
+
+#define PAL_SELECT(idx)                                                        \
+do {                                                                   \
+    if (!idx) {                                                                \
+       OUTREG(R128_DAC_CNTL2, INREG(R128_DAC_CNTL2) &          \
+              (GLuint)~R128_DAC2_PALETTE_ACC_CTL);                     \
+    } else {                                                           \
+       OUTREG(R128_DAC_CNTL2, INREG(R128_DAC_CNTL2) |          \
+              R128_DAC2_PALETTE_ACC_CTL);                              \
+    }                                                                  \
+} while (0)
+
+
+#endif
diff --git a/src/mesa/drivers/dri/r128/server/r128_reg.h b/src/mesa/drivers/dri/r128/server/r128_reg.h
new file mode 100644 (file)
index 0000000..7ec4004
--- /dev/null
@@ -0,0 +1,1431 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_reg.h,v 1.15 2002/12/16 16:19:11 dawes Exp $ */
+/*
+ * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
+ *                      Precision Insight, Inc., Cedar Park, Texas, and
+ *                      VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
+ * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ *   Rickard E. Faith <faith@valinux.com>
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Gareth Hughes <gareth@valinux.com>
+ *
+ * References:
+ *
+ *   RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
+ *   Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
+ *   1999.
+ *
+ *   RAGE 128 Software Development Manual (Technical Reference Manual P/N
+ *   SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
+ *
+ */
+
+#ifndef _R128_REG_H_
+#define _R128_REG_H_
+
+#define R128_ADAPTER_ID                   0x0f2c /* PCI */
+#define R128_AGP_APER_OFFSET              0x0178
+#define R128_AGP_BASE                     0x0170
+#define R128_AGP_CNTL                     0x0174
+#       define R128_AGP_APER_SIZE_256MB   (0x00 << 0)
+#       define R128_AGP_APER_SIZE_128MB   (0x20 << 0)
+#       define R128_AGP_APER_SIZE_64MB    (0x30 << 0)
+#       define R128_AGP_APER_SIZE_32MB    (0x38 << 0)
+#       define R128_AGP_APER_SIZE_16MB    (0x3c << 0)
+#       define R128_AGP_APER_SIZE_8MB     (0x3e << 0)
+#       define R128_AGP_APER_SIZE_4MB     (0x3f << 0)
+#       define R128_AGP_APER_SIZE_MASK    (0x3f << 0)
+#define R128_AGP_CNTL_B                   0x0b44
+#define R128_AGP_COMMAND                  0x0f58 /* PCI */
+#define R128_AGP_PLL_CNTL                 0x0010 /* PLL */
+#define R128_AGP_STATUS                   0x0f54 /* PCI */
+#       define R128_AGP_1X_MODE           0x01
+#       define R128_AGP_2X_MODE           0x02
+#       define R128_AGP_4X_MODE           0x04
+#       define R128_AGP_MODE_MASK         0x07
+#define R128_AMCGPIO_A_REG                0x01a0
+#define R128_AMCGPIO_EN_REG               0x01a8
+#define R128_AMCGPIO_MASK                 0x0194
+#define R128_AMCGPIO_Y_REG                0x01a4
+#define R128_ATTRDR                       0x03c1 /* VGA */
+#define R128_ATTRDW                       0x03c0 /* VGA */
+#define R128_ATTRX                        0x03c0 /* VGA */
+#define R128_AUX_SC_CNTL                  0x1660
+#       define R128_AUX1_SC_EN            (1 << 0)
+#       define R128_AUX1_SC_MODE_OR       (0 << 1)
+#       define R128_AUX1_SC_MODE_NAND     (1 << 1)
+#       define R128_AUX2_SC_EN            (1 << 2)
+#       define R128_AUX2_SC_MODE_OR       (0 << 3)
+#       define R128_AUX2_SC_MODE_NAND     (1 << 3)
+#       define R128_AUX3_SC_EN            (1 << 4)
+#       define R128_AUX3_SC_MODE_OR       (0 << 5)
+#       define R128_AUX3_SC_MODE_NAND     (1 << 5)
+#define R128_AUX1_SC_BOTTOM               0x1670
+#define R128_AUX1_SC_LEFT                 0x1664
+#define R128_AUX1_SC_RIGHT                0x1668
+#define R128_AUX1_SC_TOP                  0x166c
+#define R128_AUX2_SC_BOTTOM               0x1680
+#define R128_AUX2_SC_LEFT                 0x1674
+#define R128_AUX2_SC_RIGHT                0x1678
+#define R128_AUX2_SC_TOP                  0x167c
+#define R128_AUX3_SC_BOTTOM               0x1690
+#define R128_AUX3_SC_LEFT                 0x1684
+#define R128_AUX3_SC_RIGHT                0x1688
+#define R128_AUX3_SC_TOP                  0x168c
+#define R128_AUX_WINDOW_HORZ_CNTL         0x02d8
+#define R128_AUX_WINDOW_VERT_CNTL         0x02dc
+
+#define R128_BASE_CODE                    0x0f0b
+#define R128_BIOS_0_SCRATCH               0x0010
+#define R128_BIOS_1_SCRATCH               0x0014
+#define R128_BIOS_2_SCRATCH               0x0018
+#define R128_BIOS_3_SCRATCH               0x001c
+#define R128_BIOS_4_SCRATCH               0x0020
+#define R128_BIOS_5_SCRATCH               0x0024
+#       define R128_BIOS_DISPLAY_FP       (1 << 0)
+#       define R128_BIOS_DISPLAY_CRT      (2 << 0)
+#       define R128_BIOS_DISPLAY_FP_CRT   (3 << 0)
+#define R128_BIOS_6_SCRATCH               0x0028
+#define R128_BIOS_7_SCRATCH               0x002c
+#define R128_BIOS_ROM                     0x0f30 /* PCI */
+#define R128_BIST                         0x0f0f /* PCI */
+#define R128_BM_CHUNK_0_VAL               0x0a18
+#       define R128_BM_PTR_FORCE_TO_PCI    (1 << 21)
+#       define R128_BM_PM4_RD_FORCE_TO_PCI (1 << 22)
+#       define R128_BM_GLOBAL_FORCE_TO_PCI (1 << 23)
+#define R128_BRUSH_DATA0                  0x1480
+#define R128_BRUSH_DATA1                  0x1484
+#define R128_BRUSH_DATA10                 0x14a8
+#define R128_BRUSH_DATA11                 0x14ac
+#define R128_BRUSH_DATA12                 0x14b0
+#define R128_BRUSH_DATA13                 0x14b4
+#define R128_BRUSH_DATA14                 0x14b8
+#define R128_BRUSH_DATA15                 0x14bc
+#define R128_BRUSH_DATA16                 0x14c0
+#define R128_BRUSH_DATA17                 0x14c4
+#define R128_BRUSH_DATA18                 0x14c8
+#define R128_BRUSH_DATA19                 0x14cc
+#define R128_BRUSH_DATA2                  0x1488
+#define R128_BRUSH_DATA20                 0x14d0
+#define R128_BRUSH_DATA21                 0x14d4
+#define R128_BRUSH_DATA22                 0x14d8
+#define R128_BRUSH_DATA23                 0x14dc
+#define R128_BRUSH_DATA24                 0x14e0
+#define R128_BRUSH_DATA25                 0x14e4
+#define R128_BRUSH_DATA26                 0x14e8
+#define R128_BRUSH_DATA27                 0x14ec
+#define R128_BRUSH_DATA28                 0x14f0
+#define R128_BRUSH_DATA29                 0x14f4
+#define R128_BRUSH_DATA3                  0x148c
+#define R128_BRUSH_DATA30                 0x14f8
+#define R128_BRUSH_DATA31                 0x14fc
+#define R128_BRUSH_DATA32                 0x1500
+#define R128_BRUSH_DATA33                 0x1504
+#define R128_BRUSH_DATA34                 0x1508
+#define R128_BRUSH_DATA35                 0x150c
+#define R128_BRUSH_DATA36                 0x1510
+#define R128_BRUSH_DATA37                 0x1514
+#define R128_BRUSH_DATA38                 0x1518
+#define R128_BRUSH_DATA39                 0x151c
+#define R128_BRUSH_DATA4                  0x1490
+#define R128_BRUSH_DATA40                 0x1520
+#define R128_BRUSH_DATA41                 0x1524
+#define R128_BRUSH_DATA42                 0x1528
+#define R128_BRUSH_DATA43                 0x152c
+#define R128_BRUSH_DATA44                 0x1530
+#define R128_BRUSH_DATA45                 0x1534
+#define R128_BRUSH_DATA46                 0x1538
+#define R128_BRUSH_DATA47                 0x153c
+#define R128_BRUSH_DATA48                 0x1540
+#define R128_BRUSH_DATA49                 0x1544
+#define R128_BRUSH_DATA5                  0x1494
+#define R128_BRUSH_DATA50                 0x1548
+#define R128_BRUSH_DATA51                 0x154c
+#define R128_BRUSH_DATA52                 0x1550
+#define R128_BRUSH_DATA53                 0x1554
+#define R128_BRUSH_DATA54                 0x1558
+#define R128_BRUSH_DATA55                 0x155c
+#define R128_BRUSH_DATA56                 0x1560
+#define R128_BRUSH_DATA57                 0x1564
+#define R128_BRUSH_DATA58                 0x1568
+#define R128_BRUSH_DATA59                 0x156c
+#define R128_BRUSH_DATA6                  0x1498
+#define R128_BRUSH_DATA60                 0x1570
+#define R128_BRUSH_DATA61                 0x1574
+#define R128_BRUSH_DATA62                 0x1578
+#define R128_BRUSH_DATA63                 0x157c
+#define R128_BRUSH_DATA7                  0x149c
+#define R128_BRUSH_DATA8                  0x14a0
+#define R128_BRUSH_DATA9                  0x14a4
+#define R128_BRUSH_SCALE                  0x1470
+#define R128_BRUSH_Y_X                    0x1474
+#define R128_BUS_CNTL                     0x0030
+#       define R128_BUS_MASTER_DIS         (1 << 6)
+#       define R128_BUS_RD_DISCARD_EN      (1 << 24)
+#       define R128_BUS_RD_ABORT_EN        (1 << 25)
+#       define R128_BUS_MSTR_DISCONNECT_EN (1 << 28)
+#       define R128_BUS_WRT_BURST          (1 << 29)
+#       define R128_BUS_READ_BURST         (1 << 30)
+#define R128_BUS_CNTL1                    0x0034
+#       define R128_BUS_WAIT_ON_LOCK_EN    (1 << 4)
+
+#define R128_CACHE_CNTL                   0x1724
+#define R128_CACHE_LINE                   0x0f0c /* PCI */
+#define R128_CAP0_TRIG_CNTL               0x0950 /* ? */
+#define R128_CAP1_TRIG_CNTL               0x09c0 /* ? */
+#define R128_CAPABILITIES_ID              0x0f50 /* PCI */
+#define R128_CAPABILITIES_PTR             0x0f34 /* PCI */
+#define R128_CLK_PIN_CNTL                 0x0001 /* PLL */
+#define R128_CLOCK_CNTL_DATA              0x000c
+#define R128_CLOCK_CNTL_INDEX             0x0008
+#       define R128_PLL_WR_EN             (1 << 7)
+#       define R128_PLL_DIV_SEL           (3 << 8)
+#define R128_CLR_CMP_CLR_3D               0x1a24
+#define R128_CLR_CMP_CLR_DST              0x15c8
+#define R128_CLR_CMP_CLR_SRC              0x15c4
+#define R128_CLR_CMP_CNTL                 0x15c0
+#       define R128_SRC_CMP_EQ_COLOR      (4 <<  0)
+#       define R128_SRC_CMP_NEQ_COLOR     (5 <<  0)
+#       define R128_CLR_CMP_SRC_SOURCE    (1 << 24)
+#define R128_CLR_CMP_MASK                 0x15cc
+#       define R128_CLR_CMP_MSK           0xffffffff
+#define R128_CLR_CMP_MASK_3D              0x1A28
+#define R128_COMMAND                      0x0f04 /* PCI */
+#define R128_COMPOSITE_SHADOW_ID          0x1a0c
+#define R128_CONFIG_APER_0_BASE           0x0100
+#define R128_CONFIG_APER_1_BASE           0x0104
+#define R128_CONFIG_APER_SIZE             0x0108
+#define R128_CONFIG_BONDS                 0x00e8
+#define R128_CONFIG_CNTL                  0x00e0
+#       define APER_0_BIG_ENDIAN_16BPP_SWAP (1 << 0)
+#       define APER_0_BIG_ENDIAN_32BPP_SWAP (2 << 0)
+#define R128_CONFIG_MEMSIZE               0x00f8
+#define R128_CONFIG_MEMSIZE_EMBEDDED      0x0114
+#define R128_CONFIG_REG_1_BASE            0x010c
+#define R128_CONFIG_REG_APER_SIZE         0x0110
+#define R128_CONFIG_XSTRAP                0x00e4
+#define R128_CONSTANT_COLOR_C             0x1d34
+#       define R128_CONSTANT_COLOR_MASK   0x00ffffff
+#       define R128_CONSTANT_COLOR_ONE    0x00ffffff
+#       define R128_CONSTANT_COLOR_ZERO   0x00000000
+#define R128_CRC_CMDFIFO_ADDR             0x0740
+#define R128_CRC_CMDFIFO_DOUT             0x0744
+#define R128_CRTC_CRNT_FRAME              0x0214
+#define R128_CRTC_DEBUG                   0x021c
+#define R128_CRTC_EXT_CNTL                0x0054
+#       define R128_CRTC_VGA_XOVERSCAN    (1 <<  0)
+#       define R128_VGA_ATI_LINEAR        (1 <<  3)
+#       define R128_XCRT_CNT_EN           (1 <<  6)
+#       define R128_CRTC_HSYNC_DIS        (1 <<  8)
+#       define R128_CRTC_VSYNC_DIS        (1 <<  9)
+#       define R128_CRTC_DISPLAY_DIS      (1 << 10)
+#       define R128_CRTC_CRT_ON           (1 << 15)
+#       define R128_FP_OUT_EN             (1 << 22)
+#       define R128_FP_ACTIVE             (1 << 23)
+#define R128_CRTC_EXT_CNTL_DPMS_BYTE      0x0055
+#       define R128_CRTC_HSYNC_DIS_BYTE   (1 <<  0)
+#       define R128_CRTC_VSYNC_DIS_BYTE   (1 <<  1)
+#       define R128_CRTC_DISPLAY_DIS_BYTE (1 <<  2)
+#define R128_CRTC_GEN_CNTL                0x0050
+#       define R128_CRTC_DBL_SCAN_EN      (1 <<  0)
+#       define R128_CRTC_INTERLACE_EN     (1 <<  1)
+#       define R128_CRTC_CSYNC_EN         (1 <<  4)
+#       define R128_CRTC_CUR_EN           (1 << 16)
+#       define R128_CRTC_CUR_MODE_MASK    (7 << 17)
+#       define R128_CRTC_ICON_EN          (1 << 20)
+#       define R128_CRTC_EXT_DISP_EN      (1 << 24)
+#       define R128_CRTC_EN               (1 << 25)
+#       define R128_CRTC_DISP_REQ_EN_B    (1 << 26)
+#define R128_CRTC_GUI_TRIG_VLINE          0x0218
+#define R128_CRTC_H_SYNC_STRT_WID         0x0204
+#       define R128_CRTC_H_SYNC_STRT_PIX        (0x07  <<  0)
+#       define R128_CRTC_H_SYNC_STRT_CHAR       (0x1ff <<  3)
+#       define R128_CRTC_H_SYNC_STRT_CHAR_SHIFT 3
+#       define R128_CRTC_H_SYNC_WID             (0x3f  << 16)
+#       define R128_CRTC_H_SYNC_WID_SHIFT       16
+#       define R128_CRTC_H_SYNC_POL             (1     << 23)
+#define R128_CRTC_H_TOTAL_DISP            0x0200
+#       define R128_CRTC_H_TOTAL          (0x01ff << 0)
+#       define R128_CRTC_H_TOTAL_SHIFT    0
+#       define R128_CRTC_H_DISP           (0x00ff << 16)
+#       define R128_CRTC_H_DISP_SHIFT     16
+#define R128_CRTC_OFFSET                  0x0224
+#define R128_CRTC_OFFSET_CNTL             0x0228
+#define R128_CRTC_PITCH                   0x022c
+#define R128_CRTC_STATUS                  0x005c
+#       define R128_CRTC_VBLANK_SAVE      (1 <<  1)
+#define R128_CRTC_V_SYNC_STRT_WID         0x020c
+#       define R128_CRTC_V_SYNC_STRT       (0x7ff <<  0)
+#       define R128_CRTC_V_SYNC_STRT_SHIFT 0
+#       define R128_CRTC_V_SYNC_WID        (0x1f  << 16)
+#       define R128_CRTC_V_SYNC_WID_SHIFT  16
+#       define R128_CRTC_V_SYNC_POL        (1     << 23)
+#define R128_CRTC_V_TOTAL_DISP            0x0208
+#       define R128_CRTC_V_TOTAL          (0x07ff << 0)
+#       define R128_CRTC_V_TOTAL_SHIFT    0
+#       define R128_CRTC_V_DISP           (0x07ff << 16)
+#       define R128_CRTC_V_DISP_SHIFT     16
+#define R128_CRTC_VLINE_CRNT_VLINE        0x0210
+#       define R128_CRTC_CRNT_VLINE_MASK  (0x7ff << 16)
+#define R128_CRTC2_CRNT_FRAME             0x0314
+#define R128_CRTC2_DEBUG                  0x031c
+#define R128_CRTC2_GEN_CNTL               0x03f8
+#define R128_CRTC2_GUI_TRIG_VLINE         0x0318
+#define R128_CRTC2_H_SYNC_STRT_WID        0x0304
+#define R128_CRTC2_H_TOTAL_DISP           0x0300
+#define R128_CRTC2_OFFSET                 0x0324
+#define R128_CRTC2_OFFSET_CNTL            0x0328
+#define R128_CRTC2_PITCH                  0x032c
+#define R128_CRTC2_STATUS                 0x03fc
+#define R128_CRTC2_V_SYNC_STRT_WID        0x030c
+#define R128_CRTC2_V_TOTAL_DISP           0x0308
+#define R128_CRTC2_VLINE_CRNT_VLINE       0x0310
+#define R128_CRTC8_DATA                   0x03d5 /* VGA, 0x3b5 */
+#define R128_CRTC8_IDX                    0x03d4 /* VGA, 0x3b4 */
+#define R128_CUR_CLR0                     0x026c
+#define R128_CUR_CLR1                     0x0270
+#define R128_CUR_HORZ_VERT_OFF            0x0268
+#define R128_CUR_HORZ_VERT_POSN           0x0264
+#define R128_CUR_OFFSET                   0x0260
+#       define R128_CUR_LOCK              (1 << 31)
+
+#define R128_DAC_CNTL                     0x0058
+#       define R128_DAC_RANGE_CNTL        (3 <<  0)
+#       define R128_DAC_BLANKING          (1 <<  2)
+#       define R128_DAC_CRT_SEL_CRTC2     (1 <<  4)
+#       define R128_DAC_PALETTE_ACC_CTL   (1 <<  5)
+#       define R128_DAC_8BIT_EN           (1 <<  8)
+#       define R128_DAC_VGA_ADR_EN        (1 << 13)
+#       define R128_DAC_MASK_ALL          (0xff << 24)
+#define R128_DAC_CRC_SIG                  0x02cc
+#define R128_DAC_DATA                     0x03c9 /* VGA */
+#define R128_DAC_MASK                     0x03c6 /* VGA */
+#define R128_DAC_R_INDEX                  0x03c7 /* VGA */
+#define R128_DAC_W_INDEX                  0x03c8 /* VGA */
+#define R128_DDA_CONFIG                   0x02e0
+#define R128_DDA_ON_OFF                   0x02e4
+#define R128_DEFAULT_OFFSET               0x16e0
+#define R128_DEFAULT_PITCH                0x16e4
+#define R128_DEFAULT_SC_BOTTOM_RIGHT      0x16e8
+#       define R128_DEFAULT_SC_RIGHT_MAX  (0x1fff <<  0)
+#       define R128_DEFAULT_SC_BOTTOM_MAX (0x1fff << 16)
+#define R128_DESTINATION_3D_CLR_CMP_VAL   0x1820
+#define R128_DESTINATION_3D_CLR_CMP_MSK   0x1824
+#define R128_DEVICE_ID                    0x0f02 /* PCI */
+#define R128_DP_BRUSH_BKGD_CLR            0x1478
+#define R128_DP_BRUSH_FRGD_CLR            0x147c
+#define R128_DP_CNTL                      0x16c0
+#       define R128_DST_X_LEFT_TO_RIGHT   (1 <<  0)
+#       define R128_DST_Y_TOP_TO_BOTTOM   (1 <<  1)
+#define R128_DP_CNTL_XDIR_YDIR_YMAJOR     0x16d0
+#       define R128_DST_Y_MAJOR             (1 <<  2)
+#       define R128_DST_Y_DIR_TOP_TO_BOTTOM (1 << 15)
+#       define R128_DST_X_DIR_LEFT_TO_RIGHT (1 << 31)
+#define R128_DP_DATATYPE                  0x16c4
+#       define R128_HOST_BIG_ENDIAN_EN    (1 << 29)
+#define R128_DP_GUI_MASTER_CNTL           0x146c
+#       define R128_GMC_SRC_PITCH_OFFSET_CNTL (1    <<  0)
+#       define R128_GMC_DST_PITCH_OFFSET_CNTL (1    <<  1)
+#       define R128_GMC_SRC_CLIPPING          (1    <<  2)
+#       define R128_GMC_DST_CLIPPING          (1    <<  3)
+#       define R128_GMC_BRUSH_DATATYPE_MASK   (0x0f <<  4)
+#       define R128_GMC_BRUSH_8X8_MONO_FG_BG  (0    <<  4)
+#       define R128_GMC_BRUSH_8X8_MONO_FG_LA  (1    <<  4)
+#       define R128_GMC_BRUSH_1X8_MONO_FG_BG  (4    <<  4)
+#       define R128_GMC_BRUSH_1X8_MONO_FG_LA  (5    <<  4)
+#       define R128_GMC_BRUSH_32x1_MONO_FG_BG (6    <<  4)
+#       define R128_GMC_BRUSH_32x1_MONO_FG_LA (7    <<  4)
+#       define R128_GMC_BRUSH_32x32_MONO_FG_BG (8    <<  4)
+#       define R128_GMC_BRUSH_32x32_MONO_FG_LA (9    <<  4)
+#       define R128_GMC_BRUSH_8x8_COLOR       (10   <<  4)
+#       define R128_GMC_BRUSH_1X8_COLOR       (12   <<  4)
+#       define R128_GMC_BRUSH_SOLID_COLOR     (13   <<  4)
+#       define R128_GMC_BRUSH_NONE            (15   <<  4)
+#       define R128_GMC_DST_8BPP_CI           (2    <<  8)
+#       define R128_GMC_DST_15BPP             (3    <<  8)
+#       define R128_GMC_DST_16BPP             (4    <<  8)
+#       define R128_GMC_DST_24BPP             (5    <<  8)
+#       define R128_GMC_DST_32BPP             (6    <<  8)
+#       define R128_GMC_DST_8BPP_RGB          (7    <<  8)
+#       define R128_GMC_DST_Y8                (8    <<  8)
+#       define R128_GMC_DST_RGB8              (9    <<  8)
+#       define R128_GMC_DST_VYUY              (11   <<  8)
+#       define R128_GMC_DST_YVYU              (12   <<  8)
+#       define R128_GMC_DST_AYUV444           (14   <<  8)
+#       define R128_GMC_DST_ARGB4444          (15   <<  8)
+#       define R128_GMC_DST_DATATYPE_MASK     (0x0f <<  8)
+#       define R128_GMC_DST_DATATYPE_SHIFT    8
+#       define R128_GMC_SRC_DATATYPE_MASK       (3    << 12)
+#       define R128_GMC_SRC_DATATYPE_MONO_FG_BG (0    << 12)
+#       define R128_GMC_SRC_DATATYPE_MONO_FG_LA (1    << 12)
+#       define R128_GMC_SRC_DATATYPE_COLOR      (3    << 12)
+#       define R128_GMC_BYTE_PIX_ORDER        (1    << 14)
+#       define R128_GMC_BYTE_MSB_TO_LSB       (0    << 14)
+#       define R128_GMC_BYTE_LSB_TO_MSB       (1    << 14)
+#       define R128_GMC_CONVERSION_TEMP       (1    << 15)
+#       define R128_GMC_CONVERSION_TEMP_6500  (0    << 15)
+#       define R128_GMC_CONVERSION_TEMP_9300  (1    << 15)
+#       define R128_GMC_ROP3_MASK             (0xff << 16)
+#       define R128_DP_SRC_SOURCE_MASK        (7    << 24)
+#       define R128_DP_SRC_SOURCE_MEMORY      (2    << 24)
+#       define R128_DP_SRC_SOURCE_HOST_DATA   (3    << 24)
+#       define R128_GMC_3D_FCN_EN             (1    << 27)
+#       define R128_GMC_CLR_CMP_CNTL_DIS      (1    << 28)
+#       define R128_GMC_AUX_CLIP_DIS          (1    << 29)
+#       define R128_GMC_WR_MSK_DIS            (1    << 30)
+#       define R128_GMC_LD_BRUSH_Y_X          (1    << 31)
+#       define R128_ROP3_ZERO             0x00000000
+#       define R128_ROP3_DSa              0x00880000
+#       define R128_ROP3_SDna             0x00440000
+#       define R128_ROP3_S                0x00cc0000
+#       define R128_ROP3_DSna             0x00220000
+#       define R128_ROP3_D                0x00aa0000
+#       define R128_ROP3_DSx              0x00660000
+#       define R128_ROP3_DSo              0x00ee0000
+#       define R128_ROP3_DSon             0x00110000
+#       define R128_ROP3_DSxn             0x00990000
+#       define R128_ROP3_Dn               0x00550000
+#       define R128_ROP3_SDno             0x00dd0000
+#       define R128_ROP3_Sn               0x00330000
+#       define R128_ROP3_DSno             0x00bb0000
+#       define R128_ROP3_DSan             0x00770000
+#       define R128_ROP3_ONE              0x00ff0000
+#       define R128_ROP3_DPa              0x00a00000
+#       define R128_ROP3_PDna             0x00500000
+#       define R128_ROP3_P                0x00f00000
+#       define R128_ROP3_DPna             0x000a0000
+#       define R128_ROP3_D                0x00aa0000
+#       define R128_ROP3_DPx              0x005a0000
+#       define R128_ROP3_DPo              0x00fa0000
+#       define R128_ROP3_DPon             0x00050000
+#       define R128_ROP3_PDxn             0x00a50000
+#       define R128_ROP3_PDno             0x00f50000
+#       define R128_ROP3_Pn               0x000f0000
+#       define R128_ROP3_DPno             0x00af0000
+#       define R128_ROP3_DPan             0x005f0000
+
+
+#define R128_DP_GUI_MASTER_CNTL_C         0x1c84
+#define R128_DP_MIX                       0x16c8
+#define R128_DP_SRC_BKGD_CLR              0x15dc
+#define R128_DP_SRC_FRGD_CLR              0x15d8
+#define R128_DP_WRITE_MASK                0x16cc
+#define R128_DST_BRES_DEC                 0x1630
+#define R128_DST_BRES_ERR                 0x1628
+#define R128_DST_BRES_INC                 0x162c
+#define R128_DST_BRES_LNTH                0x1634
+#define R128_DST_BRES_LNTH_SUB            0x1638
+#define R128_DST_HEIGHT                   0x1410
+#define R128_DST_HEIGHT_WIDTH             0x143c
+#define R128_DST_HEIGHT_WIDTH_8           0x158c
+#define R128_DST_HEIGHT_WIDTH_BW          0x15b4
+#define R128_DST_HEIGHT_Y                 0x15a0
+#define R128_DST_OFFSET                   0x1404
+#define R128_DST_PITCH                    0x1408
+#define R128_DST_PITCH_OFFSET             0x142c
+#define R128_DST_PITCH_OFFSET_C           0x1c80
+#       define R128_PITCH_SHIFT               21
+#       define R128_DST_TILE                 (1 << 31)
+#define R128_DST_WIDTH                    0x140c
+#define R128_DST_WIDTH_HEIGHT             0x1598
+#define R128_DST_WIDTH_X                  0x1588
+#define R128_DST_WIDTH_X_INCY             0x159c
+#define R128_DST_X                        0x141c
+#define R128_DST_X_SUB                    0x15a4
+#define R128_DST_X_Y                      0x1594
+#define R128_DST_Y                        0x1420
+#define R128_DST_Y_SUB                    0x15a8
+#define R128_DST_Y_X                      0x1438
+
+#define R128_EXT_MEM_CNTL                 0x0144
+
+#define R128_FCP_CNTL                     0x0012 /* PLL */
+#define R128_FLUSH_1                      0x1704
+#define R128_FLUSH_2                      0x1708
+#define R128_FLUSH_3                      0x170c
+#define R128_FLUSH_4                      0x1710
+#define R128_FLUSH_5                      0x1714
+#define R128_FLUSH_6                      0x1718
+#define R128_FLUSH_7                      0x171c
+#define R128_FOG_3D_TABLE_START           0x1810
+#define R128_FOG_3D_TABLE_END             0x1814
+#define R128_FOG_3D_TABLE_DENSITY         0x181c
+#define R128_FOG_TABLE_INDEX              0x1a14
+#define R128_FOG_TABLE_DATA               0x1a18
+#define R128_FP_CRTC_H_TOTAL_DISP         0x0250
+#define R128_FP_CRTC_V_TOTAL_DISP         0x0254
+#define R128_FP_GEN_CNTL                  0x0284
+#       define R128_FP_FPON                  (1 << 0)
+#       define R128_FP_BLANK_DIS             (1 << 1)
+#       define R128_FP_TDMS_EN               (1 <<  2)
+#       define R128_FP_DETECT_SENSE          (1 <<  8)
+#       define R128_FP_SEL_CRTC2             (1 << 13)
+#       define R128_FP_CRTC_DONT_SHADOW_VPAR (1 << 16)
+#       define R128_FP_CRTC_DONT_SHADOW_HEND (1 << 17)
+#       define R128_FP_CRTC_USE_SHADOW_VEND  (1 << 18)
+#       define R128_FP_CRTC_USE_SHADOW_ROWCUR (1 << 19)
+#       define R128_FP_CRTC_HORZ_DIV2_EN     (1 << 20)
+#       define R128_FP_CRTC_HOR_CRT_DIV2_DIS (1 << 21)
+#       define R128_FP_CRT_SYNC_SEL          (1 << 23)
+#       define R128_FP_USE_SHADOW_EN         (1 << 24)
+#define R128_FP_H_SYNC_STRT_WID           0x02c4
+#define R128_FP_HORZ_STRETCH              0x028c
+#       define R128_HORZ_STRETCH_RATIO_MASK  0xffff
+#       define R128_HORZ_STRETCH_RATIO_SHIFT 0
+#       define R128_HORZ_STRETCH_RATIO_MAX   4096
+#       define R128_HORZ_PANEL_SIZE          (0xff   << 16)
+#       define R128_HORZ_PANEL_SHIFT         16
+#       define R128_AUTO_HORZ_RATIO          (0      << 24)
+#       define R128_HORZ_STRETCH_PIXREP      (0      << 25)
+#       define R128_HORZ_STRETCH_BLEND       (1      << 25)
+#       define R128_HORZ_STRETCH_ENABLE      (1      << 26)
+#       define R128_HORZ_FP_LOOP_STRETCH     (0x7    << 27)
+#       define R128_HORZ_STRETCH_RESERVED    (1      << 30)
+#       define R128_HORZ_AUTO_RATIO_FIX_EN   (1      << 31)
+
+#define R128_FP_PANEL_CNTL                0x0288
+#       define R128_FP_DIGON              (1 << 0)
+#       define R128_FP_BLON               (1 << 1)
+#define R128_FP_V_SYNC_STRT_WID           0x02c8
+#define R128_FP_VERT_STRETCH              0x0290
+#       define R128_VERT_PANEL_SIZE          (0x7ff <<  0)
+#       define R128_VERT_PANEL_SHIFT         0
+#       define R128_VERT_STRETCH_RATIO_MASK  0x3ff
+#       define R128_VERT_STRETCH_RATIO_SHIFT 11
+#       define R128_VERT_STRETCH_RATIO_MAX   1024
+#       define R128_VERT_STRETCH_ENABLE      (1     << 24)
+#       define R128_VERT_STRETCH_LINEREP     (0     << 25)
+#       define R128_VERT_STRETCH_BLEND       (1     << 25)
+#       define R128_VERT_AUTO_RATIO_EN       (1     << 26)
+#       define R128_VERT_STRETCH_RESERVED    0xf8e00000
+
+#define R128_GEN_INT_CNTL                 0x0040
+#define R128_GEN_INT_STATUS               0x0044
+#       define R128_VSYNC_INT_AK          (1 <<  2)
+#       define R128_VSYNC_INT             (1 <<  2)
+#define R128_GEN_RESET_CNTL               0x00f0
+#       define R128_SOFT_RESET_GUI          (1 <<  0)
+#       define R128_SOFT_RESET_VCLK         (1 <<  8)
+#       define R128_SOFT_RESET_PCLK         (1 <<  9)
+#       define R128_SOFT_RESET_DISPENG_XCLK (1 << 11)
+#       define R128_SOFT_RESET_MEMCTLR_XCLK (1 << 12)
+#define R128_GENENB                       0x03c3 /* VGA */
+#define R128_GENFC_RD                     0x03ca /* VGA */
+#define R128_GENFC_WT                     0x03da /* VGA, 0x03ba */
+#define R128_GENMO_RD                     0x03cc /* VGA */
+#define R128_GENMO_WT                     0x03c2 /* VGA */
+#define R128_GENS0                        0x03c2 /* VGA */
+#define R128_GENS1                        0x03da /* VGA, 0x03ba */
+#define R128_GPIO_MONID                   0x0068
+#       define R128_GPIO_MONID_A_0        (1 <<  0)
+#       define R128_GPIO_MONID_A_1        (1 <<  1)
+#       define R128_GPIO_MONID_A_2        (1 <<  2)
+#       define R128_GPIO_MONID_A_3        (1 <<  3)
+#       define R128_GPIO_MONID_Y_0        (1 <<  8)
+#       define R128_GPIO_MONID_Y_1        (1 <<  9)
+#       define R128_GPIO_MONID_Y_2        (1 << 10)
+#       define R128_GPIO_MONID_Y_3        (1 << 11)
+#       define R128_GPIO_MONID_EN_0       (1 << 16)
+#       define R128_GPIO_MONID_EN_1       (1 << 17)
+#       define R128_GPIO_MONID_EN_2       (1 << 18)
+#       define R128_GPIO_MONID_EN_3       (1 << 19)
+#       define R128_GPIO_MONID_MASK_0     (1 << 24)
+#       define R128_GPIO_MONID_MASK_1     (1 << 25)
+#       define R128_GPIO_MONID_MASK_2     (1 << 26)
+#       define R128_GPIO_MONID_MASK_3     (1 << 27)
+#define R128_GPIO_MONIDB                  0x006c
+#define R128_GRPH8_DATA                   0x03cf /* VGA */
+#define R128_GRPH8_IDX                    0x03ce /* VGA */
+#define R128_GUI_DEBUG0                   0x16a0
+#define R128_GUI_DEBUG1                   0x16a4
+#define R128_GUI_DEBUG2                   0x16a8
+#define R128_GUI_DEBUG3                   0x16ac
+#define R128_GUI_DEBUG4                   0x16b0
+#define R128_GUI_DEBUG5                   0x16b4
+#define R128_GUI_DEBUG6                   0x16b8
+#define R128_GUI_PROBE                    0x16bc
+#define R128_GUI_SCRATCH_REG0             0x15e0
+#define R128_GUI_SCRATCH_REG1             0x15e4
+#define R128_GUI_SCRATCH_REG2             0x15e8
+#define R128_GUI_SCRATCH_REG3             0x15ec
+#define R128_GUI_SCRATCH_REG4             0x15f0
+#define R128_GUI_SCRATCH_REG5             0x15f4
+#define R128_GUI_STAT                     0x1740
+#       define R128_GUI_FIFOCNT_MASK      0x0fff
+#       define R128_GUI_ACTIVE            (1 << 31)
+
+#define R128_HEADER                       0x0f0e /* PCI */
+#define R128_HOST_DATA0                   0x17c0
+#define R128_HOST_DATA1                   0x17c4
+#define R128_HOST_DATA2                   0x17c8
+#define R128_HOST_DATA3                   0x17cc
+#define R128_HOST_DATA4                   0x17d0
+#define R128_HOST_DATA5                   0x17d4
+#define R128_HOST_DATA6                   0x17d8
+#define R128_HOST_DATA7                   0x17dc
+#define R128_HOST_DATA_LAST               0x17e0
+#define R128_HOST_PATH_CNTL               0x0130
+#define R128_HTOTAL_CNTL                  0x0009 /* PLL */
+#define R128_HW_DEBUG                     0x0128
+#define R128_HW_DEBUG2                    0x011c
+
+#define R128_I2C_CNTL_1                   0x0094 /* ? */
+#define R128_INTERRUPT_LINE               0x0f3c /* PCI */
+#define R128_INTERRUPT_PIN                0x0f3d /* PCI */
+#define R128_IO_BASE                      0x0f14 /* PCI */
+
+#define R128_LATENCY                      0x0f0d /* PCI */
+#define R128_LEAD_BRES_DEC                0x1608
+#define R128_LEAD_BRES_ERR                0x1600
+#define R128_LEAD_BRES_INC                0x1604
+#define R128_LEAD_BRES_LNTH               0x161c
+#define R128_LEAD_BRES_LNTH_SUB           0x1624
+#define R128_LVDS_GEN_CNTL                0x02d0
+#       define R128_LVDS_ON               (1   <<  0)
+#       define R128_LVDS_DISPLAY_DIS      (1   <<  1)
+#       define R128_LVDS_EN               (1   <<  7)
+#       define R128_LVDS_DIGON            (1   << 18)
+#       define R128_LVDS_BLON             (1   << 19)
+#       define R128_LVDS_SEL_CRTC2        (1   << 23)
+#       define R128_HSYNC_DELAY_SHIFT     28
+#       define R128_HSYNC_DELAY_MASK      (0xf << 28)
+
+#define R128_MAX_LATENCY                  0x0f3f /* PCI */
+#define R128_MCLK_CNTL                    0x000f /* PLL */
+#       define R128_FORCE_GCP             (1 << 16)
+#       define R128_FORCE_PIPE3D_CP       (1 << 17)
+#       define R128_FORCE_RCP             (1 << 18)
+#define R128_MDGPIO_A_REG                 0x01ac
+#define R128_MDGPIO_EN_REG                0x01b0
+#define R128_MDGPIO_MASK                  0x0198
+#define R128_MDGPIO_Y_REG                 0x01b4
+#define R128_MEM_ADDR_CONFIG              0x0148
+#define R128_MEM_BASE                     0x0f10 /* PCI */
+#define R128_MEM_CNTL                     0x0140
+#define R128_MEM_INIT_LAT_TIMER           0x0154
+#define R128_MEM_INTF_CNTL                0x014c
+#define R128_MEM_SDRAM_MODE_REG           0x0158
+#define R128_MEM_STR_CNTL                 0x0150
+#define R128_MEM_VGA_RP_SEL               0x003c
+#define R128_MEM_VGA_WP_SEL               0x0038
+#define R128_MIN_GRANT                    0x0f3e /* PCI */
+#define R128_MM_DATA                      0x0004
+#define R128_MM_INDEX                     0x0000
+#define R128_MPLL_CNTL                    0x000e /* PLL */
+#define R128_MPP_TB_CONFIG                0x01c0 /* ? */
+#define R128_MPP_GP_CONFIG                0x01c8 /* ? */
+
+#define R128_N_VIF_COUNT                  0x0248
+
+#define R128_OVR_CLR                      0x0230
+#define R128_OVR_WID_LEFT_RIGHT           0x0234
+#define R128_OVR_WID_TOP_BOTTOM           0x0238
+
+/* first overlay unit (there is only one) */
+
+#define R128_OV0_Y_X_START                0x0400
+#define R128_OV0_Y_X_END                  0x0404
+#define R128_OV0_EXCLUSIVE_HORZ           0x0408
+#       define  R128_EXCL_HORZ_START_MASK        0x000000ff
+#       define  R128_EXCL_HORZ_END_MASK          0x0000ff00
+#       define  R128_EXCL_HORZ_BACK_PORCH_MASK   0x00ff0000
+#       define  R128_EXCL_HORZ_EXCLUSIVE_EN      0x80000000
+#define R128_OV0_EXCLUSIVE_VERT           0x040C
+#       define  R128_EXCL_VERT_START_MASK        0x000003ff
+#       define  R128_EXCL_VERT_END_MASK          0x03ff0000
+#define R128_OV0_REG_LOAD_CNTL            0x0410
+#       define  R128_REG_LD_CTL_LOCK                 0x00000001L
+#       define  R128_REG_LD_CTL_VBLANK_DURING_LOCK   0x00000002L
+#       define  R128_REG_LD_CTL_STALL_GUI_UNTIL_FLIP 0x00000004L
+#       define  R128_REG_LD_CTL_LOCK_READBACK        0x00000008L
+#define R128_OV0_SCALE_CNTL               0x0420
+#       define  R128_SCALER_PIX_EXPAND           0x00000001L
+#       define  R128_SCALER_Y2R_TEMP             0x00000002L
+#       define  R128_SCALER_HORZ_PICK_NEAREST    0x00000003L
+#       define  R128_SCALER_VERT_PICK_NEAREST    0x00000004L
+#       define  R128_SCALER_SIGNED_UV            0x00000010L
+#       define  R128_SCALER_GAMMA_SEL_MASK       0x00000060L
+#       define  R128_SCALER_GAMMA_SEL_BRIGHT     0x00000000L
+#       define  R128_SCALER_GAMMA_SEL_G22        0x00000020L
+#       define  R128_SCALER_GAMMA_SEL_G18        0x00000040L
+#       define  R128_SCALER_GAMMA_SEL_G14        0x00000060L
+#       define  R128_SCALER_COMCORE_SHIFT_UP_ONE 0x00000080L
+#       define  R128_SCALER_SURFAC_FORMAT        0x00000f00L
+#       define  R128_SCALER_SOURCE_15BPP         0x00000300L
+#       define  R128_SCALER_SOURCE_16BPP         0x00000400L
+#       define  R128_SCALER_SOURCE_32BPP         0x00000600L
+#       define  R128_SCALER_SOURCE_YUV9          0x00000900L
+#       define  R128_SCALER_SOURCE_YUV12         0x00000A00L
+#       define  R128_SCALER_SOURCE_VYUY422       0x00000B00L
+#       define  R128_SCALER_SOURCE_YVYU422       0x00000C00L
+#       define  R128_SCALER_SMART_SWITCH         0x00008000L
+#       define  R128_SCALER_BURST_PER_PLANE      0x00ff0000L
+#       define  R128_SCALER_DOUBLE_BUFFER        0x01000000L
+#       define  R128_SCALER_DIS_LIMIT            0x08000000L
+#       define  R128_SCALER_PRG_LOAD_START       0x10000000L
+#       define  R128_SCALER_INT_EMU              0x20000000L
+#       define  R128_SCALER_ENABLE               0x40000000L
+#       define  R128_SCALER_SOFT_RESET           0x80000000L
+#define R128_OV0_V_INC                    0x0424
+#define R128_OV0_P1_V_ACCUM_INIT          0x0428
+#       define  R128_OV0_P1_MAX_LN_IN_PER_LN_OUT        0x00000003L
+#       define  R128_OV0_P1_V_ACCUM_INIT_MASK           0x01ff8000L
+#define R128_OV0_P23_V_ACCUM_INIT         0x042C
+#define R128_OV0_P1_BLANK_LINES_AT_TOP    0x0430
+#       define  R128_P1_BLNK_LN_AT_TOP_M1_MASK   0x00000fffL
+#       define  R128_P1_ACTIVE_LINES_M1          0x0fff0000L
+#define R128_OV0_P23_BLANK_LINES_AT_TOP   0x0434
+#       define  R128_P23_BLNK_LN_AT_TOP_M1_MASK  0x000007ffL
+#       define  R128_P23_ACTIVE_LINES_M1         0x07ff0000L
+#define R128_OV0_VID_BUF0_BASE_ADRS       0x0440
+#       define  R128_VIF_BUF0_PITCH_SEL          0x00000001L
+#       define  R128_VIF_BUF0_TILE_ADRS          0x00000002L
+#       define  R128_VIF_BUF0_BASE_ADRS_MASK     0x03fffff0L
+#       define  R128_VIF_BUF0_1ST_LINE_LSBS_MASK 0x48000000L
+#define R128_OV0_VID_BUF1_BASE_ADRS       0x0444
+#       define  R128_VIF_BUF1_PITCH_SEL          0x00000001L
+#       define  R128_VIF_BUF1_TILE_ADRS          0x00000002L
+#       define  R128_VIF_BUF1_BASE_ADRS_MASK     0x03fffff0L
+#       define  R128_VIF_BUF1_1ST_LINE_LSBS_MASK 0x48000000L
+#define R128_OV0_VID_BUF2_BASE_ADRS       0x0448
+#       define  R128_VIF_BUF2_PITCH_SEL          0x00000001L
+#       define  R128_VIF_BUF2_TILE_ADRS          0x00000002L
+#       define  R128_VIF_BUF2_BASE_ADRS_MASK     0x03fffff0L
+#       define  R128_VIF_BUF2_1ST_LINE_LSBS_MASK 0x48000000L
+#define R128_OV0_VID_BUF3_BASE_ADRS       0x044C
+#define R128_OV0_VID_BUF4_BASE_ADRS       0x0450
+#define R128_OV0_VID_BUF5_BASE_ADRS       0x0454
+#define R128_OV0_VID_BUF_PITCH0_VALUE     0x0460
+#define R128_OV0_VID_BUF_PITCH1_VALUE     0x0464
+#define R128_OV0_AUTO_FLIP_CNTL           0x0470
+#define R128_OV0_DEINTERLACE_PATTERN      0x0474
+#define R128_OV0_H_INC                    0x0480
+#define R128_OV0_STEP_BY                  0x0484
+#define R128_OV0_P1_H_ACCUM_INIT          0x0488
+#define R128_OV0_P23_H_ACCUM_INIT         0x048C
+#define R128_OV0_P1_X_START_END           0x0494
+#define R128_OV0_P2_X_START_END           0x0498
+#define R128_OV0_P3_X_START_END           0x049C
+#define R128_OV0_FILTER_CNTL              0x04A0
+#define R128_OV0_FOUR_TAP_COEF_0          0x04B0
+#define R128_OV0_FOUR_TAP_COEF_1          0x04B4
+#define R128_OV0_FOUR_TAP_COEF_2          0x04B8
+#define R128_OV0_FOUR_TAP_COEF_3          0x04BC
+#define R128_OV0_FOUR_TAP_COEF_4          0x04C0
+#define R128_OV0_COLOUR_CNTL              0x04E0
+#define R128_OV0_VIDEO_KEY_CLR            0x04E4
+#define R128_OV0_VIDEO_KEY_MSK            0x04E8
+#define R128_OV0_GRAPHICS_KEY_CLR         0x04EC
+#define R128_OV0_GRAPHICS_KEY_MSK         0x04F0
+#define R128_OV0_KEY_CNTL                 0x04F4
+#       define  R128_VIDEO_KEY_FN_MASK           0x00000007L
+#       define  R128_VIDEO_KEY_FN_FALSE          0x00000000L
+#       define  R128_VIDEO_KEY_FN_TRUE           0x00000001L
+#       define  R128_VIDEO_KEY_FN_EQ             0x00000004L
+#       define  R128_VIDEO_KEY_FN_NE             0x00000005L
+#       define  R128_GRAPHIC_KEY_FN_MASK         0x00000070L
+#       define  R128_GRAPHIC_KEY_FN_FALSE        0x00000000L
+#       define  R128_GRAPHIC_KEY_FN_TRUE         0x00000010L
+#       define  R128_GRAPHIC_KEY_FN_EQ           0x00000040L
+#       define  R128_GRAPHIC_KEY_FN_NE           0x00000050L
+#       define  R128_CMP_MIX_MASK                0x00000100L
+#       define  R128_CMP_MIX_OR                  0x00000000L
+#       define  R128_CMP_MIX_AND                 0x00000100L
+#define R128_OV0_TEST                     0x04F8
+
+
+#define R128_PALETTE_DATA                 0x00b4
+#define R128_PALETTE_INDEX                0x00b0
+#define R128_PC_DEBUG_MODE                0x1760
+#define R128_PC_GUI_CTLSTAT               0x1748
+#define R128_PC_GUI_MODE                  0x1744
+#       define R128_PC_IGNORE_UNIFY       (1 << 5)
+#define R128_PC_MISC_CNTL                 0x0188
+#define R128_PC_NGUI_CTLSTAT              0x0184
+#       define R128_PC_FLUSH_GUI          (3 << 0)
+#       define R128_PC_RI_GUI             (1 << 2)
+#       define R128_PC_FLUSH_ALL          0x00ff
+#       define R128_PC_BUSY               (1 << 31)
+#define R128_PC_NGUI_MODE                 0x0180
+#define R128_PCI_GART_PAGE                0x017c
+#define R128_PLANE_3D_MASK_C              0x1d44
+#define R128_PLL_TEST_CNTL                0x0013 /* PLL */
+#define R128_PMI_CAP_ID                   0x0f5c /* PCI */
+#define R128_PMI_DATA                     0x0f63 /* PCI */
+#define R128_PMI_NXT_CAP_PTR              0x0f5d /* PCI */
+#define R128_PMI_PMC_REG                  0x0f5e /* PCI */
+#define R128_PMI_PMCSR_REG                0x0f60 /* PCI */
+#define R128_PMI_REGISTER                 0x0f5c /* PCI */
+#define R128_PPLL_CNTL                    0x0002 /* PLL */
+#       define R128_PPLL_RESET                (1 <<  0)
+#       define R128_PPLL_SLEEP                (1 <<  1)
+#       define R128_PPLL_ATOMIC_UPDATE_EN     (1 << 16)
+#       define R128_PPLL_VGA_ATOMIC_UPDATE_EN (1 << 17)
+#define R128_PPLL_DIV_0                   0x0004 /* PLL */
+#define R128_PPLL_DIV_1                   0x0005 /* PLL */
+#define R128_PPLL_DIV_2                   0x0006 /* PLL */
+#define R128_PPLL_DIV_3                   0x0007 /* PLL */
+#       define R128_PPLL_FB3_DIV_MASK     0x07ff
+#       define R128_PPLL_POST3_DIV_MASK   0x00070000
+#define R128_PPLL_REF_DIV                 0x0003 /* PLL */
+#       define R128_PPLL_REF_DIV_MASK     0x03ff
+#       define R128_PPLL_ATOMIC_UPDATE_R  (1 << 15) /* same as _W */
+#       define R128_PPLL_ATOMIC_UPDATE_W  (1 << 15) /* same as _R */
+#define R128_PWR_MNGMT_CNTL_STATUS        0x0f60 /* PCI */
+#define R128_REG_BASE                     0x0f18 /* PCI */
+#define R128_REGPROG_INF                  0x0f09 /* PCI */
+#define R128_REVISION_ID                  0x0f08 /* PCI */
+
+#define R128_SC_BOTTOM                    0x164c
+#define R128_SC_BOTTOM_RIGHT              0x16f0
+#define R128_SC_BOTTOM_RIGHT_C            0x1c8c
+#define R128_SC_LEFT                      0x1640
+#define R128_SC_RIGHT                     0x1644
+#define R128_SC_TOP                       0x1648
+#define R128_SC_TOP_LEFT                  0x16ec
+#define R128_SC_TOP_LEFT_C                0x1c88
+#define R128_SEQ8_DATA                    0x03c5 /* VGA */
+#define R128_SEQ8_IDX                     0x03c4 /* VGA */
+#define R128_SNAPSHOT_F_COUNT             0x0244
+#define R128_SNAPSHOT_VH_COUNTS           0x0240
+#define R128_SNAPSHOT_VIF_COUNT           0x024c
+#define R128_SRC_OFFSET                   0x15ac
+#define R128_SRC_PITCH                    0x15b0
+#define R128_SRC_PITCH_OFFSET             0x1428
+#define R128_SRC_SC_BOTTOM                0x165c
+#define R128_SRC_SC_BOTTOM_RIGHT          0x16f4
+#define R128_SRC_SC_RIGHT                 0x1654
+#define R128_SRC_X                        0x1414
+#define R128_SRC_X_Y                      0x1590
+#define R128_SRC_Y                        0x1418
+#define R128_SRC_Y_X                      0x1434
+#define R128_STATUS                       0x0f06 /* PCI */
+#define R128_SUBPIC_CNTL                  0x0540 /* ? */
+#define R128_SUB_CLASS                    0x0f0a /* PCI */
+#define R128_SURFACE_DELAY                0x0b00
+#define R128_SURFACE0_INFO                0x0b0c
+#define R128_SURFACE0_LOWER_BOUND         0x0b04
+#define R128_SURFACE0_UPPER_BOUND         0x0b08
+#define R128_SURFACE1_INFO                0x0b1c
+#define R128_SURFACE1_LOWER_BOUND         0x0b14
+#define R128_SURFACE1_UPPER_BOUND         0x0b18
+#define R128_SURFACE2_INFO                0x0b2c
+#define R128_SURFACE2_LOWER_BOUND         0x0b24
+#define R128_SURFACE2_UPPER_BOUND         0x0b28
+#define R128_SURFACE3_INFO                0x0b3c
+#define R128_SURFACE3_LOWER_BOUND         0x0b34
+#define R128_SURFACE3_UPPER_BOUND         0x0b38
+#define R128_SW_SEMAPHORE                 0x013c
+
+#define R128_TEST_DEBUG_CNTL              0x0120
+#define R128_TEST_DEBUG_MUX               0x0124
+#define R128_TEST_DEBUG_OUT               0x012c
+#define R128_TMDS_CRC                     0x02a0
+#define R128_TMDS_TRANSMITTER_CNTL        0x02a4
+#       define R128_TMDS_PLLEN            (1 << 0)
+#       define R128_TMDS_PLLRST           (1 << 1)
+#define R128_TRAIL_BRES_DEC               0x1614
+#define R128_TRAIL_BRES_ERR               0x160c
+#define R128_TRAIL_BRES_INC               0x1610
+#define R128_TRAIL_X                      0x1618
+#define R128_TRAIL_X_SUB                  0x1620
+
+#define R128_VCLK_ECP_CNTL                0x0008 /* PLL */
+#define R128_VENDOR_ID                    0x0f00 /* PCI */
+#define R128_VGA_DDA_CONFIG               0x02e8
+#define R128_VGA_DDA_ON_OFF               0x02ec
+#define R128_VID_BUFFER_CONTROL           0x0900
+#define R128_VIDEOMUX_CNTL                0x0190
+#define R128_VIPH_CONTROL                 0x01D0 /* ? */
+
+#define R128_WAIT_UNTIL                   0x1720
+
+#define R128_X_MPLL_REF_FB_DIV            0x000a /* PLL */
+#define R128_XCLK_CNTL                    0x000d /* PLL */
+#define R128_XDLL_CNTL                    0x000c /* PLL */
+#define R128_XPLL_CNTL                    0x000b /* PLL */
+
+                               /* Registers for CCE and Microcode Engine */
+#define R128_PM4_MICROCODE_ADDR           0x07d4
+#define R128_PM4_MICROCODE_RADDR          0x07d8
+#define R128_PM4_MICROCODE_DATAH          0x07dc
+#define R128_PM4_MICROCODE_DATAL          0x07e0
+
+#define R128_PM4_BUFFER_OFFSET            0x0700
+#define R128_PM4_BUFFER_CNTL              0x0704
+#       define R128_PM4_NONPM4                 (0  << 28)
+#       define R128_PM4_192PIO                 (1  << 28)
+#       define R128_PM4_192BM                  (2  << 28)
+#       define R128_PM4_128PIO_64INDBM         (3  << 28)
+#       define R128_PM4_128BM_64INDBM          (4  << 28)
+#       define R128_PM4_64PIO_128INDBM         (5  << 28)
+#       define R128_PM4_64BM_128INDBM          (6  << 28)
+#       define R128_PM4_64PIO_64VCBM_64INDBM   (7  << 28)
+#       define R128_PM4_64BM_64VCBM_64INDBM    (8  << 28)
+#       define R128_PM4_64PIO_64VCPIO_64INDPIO (15 << 28)
+#define R128_PM4_BUFFER_WM_CNTL           0x0708
+#       define R128_WMA_SHIFT                  0
+#       define R128_WMB_SHIFT                  8
+#       define R128_WMC_SHIFT                 16
+#       define R128_WB_WM_SHIFT               24
+#define R128_PM4_BUFFER_DL_RPTR_ADDR      0x070c
+#define R128_PM4_BUFFER_DL_RPTR           0x0710
+#define R128_PM4_BUFFER_DL_WPTR           0x0714
+#       define R128_PM4_BUFFER_DL_DONE    (1 << 31)
+#define R128_PM4_BUFFER_DL_WPTR_DELAY     0x0718
+#       define R128_PRE_WRITE_TIMER_SHIFT      0
+#       define R128_PRE_WRITE_LIMIT_SHIFT     23
+#define R128_PM4_VC_FPU_SETUP             0x071c
+#       define R128_FRONT_DIR_CW          (0 <<  0)
+#       define R128_FRONT_DIR_CCW         (1 <<  0)
+#       define R128_FRONT_DIR_MASK        (1 <<  0)
+#       define R128_BACKFACE_CULL         (0 <<  1)
+#       define R128_BACKFACE_POINTS       (1 <<  1)
+#       define R128_BACKFACE_LINES        (2 <<  1)
+#       define R128_BACKFACE_SOLID        (3 <<  1)
+#       define R128_BACKFACE_MASK         (3 <<  1)
+#       define R128_FRONTFACE_CULL        (0 <<  3)
+#       define R128_FRONTFACE_POINTS      (1 <<  3)
+#       define R128_FRONTFACE_LINES       (2 <<  3)
+#       define R128_FRONTFACE_SOLID       (3 <<  3)
+#       define R128_FRONTFACE_MASK        (3 <<  3)
+#       define R128_FPU_COLOR_SOLID       (0 <<  5)
+#       define R128_FPU_COLOR_FLAT        (1 <<  5)
+#       define R128_FPU_COLOR_GOURAUD     (2 <<  5)
+#       define R128_FPU_COLOR_GOURAUD2    (3 <<  5)
+#       define R128_FPU_COLOR_MASK        (3 <<  5)
+#       define R128_FPU_SUB_PIX_2BITS     (0 <<  7)
+#       define R128_FPU_SUB_PIX_4BITS     (1 <<  7)
+#       define R128_FPU_MODE_2D           (0 <<  8)
+#       define R128_FPU_MODE_3D           (1 <<  8)
+#       define R128_TRAP_BITS_DISABLE     (1 <<  9)
+#       define R128_EDGE_ANTIALIAS        (1 << 10)
+#       define R128_SUPERSAMPLE           (1 << 11)
+#       define R128_XFACTOR_2             (0 << 12)
+#       define R128_XFACTOR_4             (1 << 12)
+#       define R128_YFACTOR_2             (0 << 13)
+#       define R128_YFACTOR_4             (1 << 13)
+#       define R128_FLAT_SHADE_VERTEX_D3D (0 << 14)
+#       define R128_FLAT_SHADE_VERTEX_OGL (1 << 14)
+#       define R128_FPU_ROUND_TRUNCATE    (0 << 15)
+#       define R128_FPU_ROUND_NEAREST     (1 << 15)
+#       define R128_WM_SEL_8DW            (0 << 16)
+#       define R128_WM_SEL_16DW           (1 << 16)
+#       define R128_WM_SEL_32DW           (2 << 16)
+#define R128_PM4_VC_DEBUG_CONFIG          0x07a4
+#define R128_PM4_VC_STAT                  0x07a8
+#define R128_PM4_VC_TIMESTAMP0            0x07b0
+#define R128_PM4_VC_TIMESTAMP1            0x07b4
+#define R128_PM4_STAT                     0x07b8
+#       define R128_PM4_FIFOCNT_MASK      0x0fff
+#       define R128_PM4_BUSY              (1 << 16)
+#       define R128_PM4_GUI_ACTIVE        (1 << 31)
+#define R128_PM4_BUFFER_ADDR              0x07f0
+#define R128_PM4_MICRO_CNTL               0x07fc
+#       define R128_PM4_MICRO_FREERUN     (1 << 30)
+#define R128_PM4_FIFO_DATA_EVEN           0x1000
+#define R128_PM4_FIFO_DATA_ODD            0x1004
+
+#define R128_SCALE_3D_CNTL                0x1a00
+#       define R128_SCALE_DITHER_ERR_DIFF         (0  <<  1)
+#       define R128_SCALE_DITHER_TABLE            (1  <<  1)
+#       define R128_TEX_CACHE_SIZE_FULL           (0  <<  2)
+#       define R128_TEX_CACHE_SIZE_HALF           (1  <<  2)
+#       define R128_DITHER_INIT_CURR              (0  <<  3)
+#       define R128_DITHER_INIT_RESET             (1  <<  3)
+#       define R128_ROUND_24BIT                   (1  <<  4)
+#       define R128_TEX_CACHE_DISABLE             (1  <<  5)
+#       define R128_SCALE_3D_NOOP                 (0  <<  6)
+#       define R128_SCALE_3D_SCALE                (1  <<  6)
+#       define R128_SCALE_3D_TEXMAP_SHADE         (2  <<  6)
+#       define R128_SCALE_PIX_BLEND               (0  <<  8)
+#       define R128_SCALE_PIX_REPLICATE           (1  <<  8)
+#       define R128_TEX_CACHE_SPLIT               (1  <<  9)
+#       define R128_APPLE_YUV_MODE                (1  << 10)
+#       define R128_TEX_CACHE_PALLETE_MODE        (1  << 11)
+#       define R128_ALPHA_COMB_ADD_CLAMP          (0  << 12)
+#       define R128_ALPHA_COMB_ADD_NCLAMP         (1  << 12)
+#       define R128_ALPHA_COMB_SUB_DST_SRC_CLAMP  (2  << 12)
+#       define R128_ALPHA_COMB_SUB_DST_SRC_NCLAMP (3  << 12)
+#       define R128_FOG_TABLE                     (1  << 14)
+#       define R128_SIGNED_DST_CLAMP              (1  << 15)
+#       define R128_ALPHA_BLEND_SRC_ZERO          (0  << 16)
+#       define R128_ALPHA_BLEND_SRC_ONE           (1  << 16)
+#       define R128_ALPHA_BLEND_SRC_SRCCOLOR      (2  << 16)
+#       define R128_ALPHA_BLEND_SRC_INVSRCCOLOR   (3  << 16)
+#       define R128_ALPHA_BLEND_SRC_SRCALPHA      (4  << 16)
+#       define R128_ALPHA_BLEND_SRC_INVSRCALPHA   (5  << 16)
+#       define R128_ALPHA_BLEND_SRC_DSTALPHA      (6  << 16)
+#       define R128_ALPHA_BLEND_SRC_INVDSTALPHA   (7  << 16)
+#       define R128_ALPHA_BLEND_SRC_DSTCOLOR      (8  << 16)
+#       define R128_ALPHA_BLEND_SRC_INVDSTCOLOR   (9  << 16)
+#       define R128_ALPHA_BLEND_SRC_SAT           (10 << 16)
+#       define R128_ALPHA_BLEND_SRC_BLEND         (11 << 16)
+#       define R128_ALPHA_BLEND_SRC_INVBLEND      (12 << 16)
+#       define R128_ALPHA_BLEND_DST_ZERO          (0  << 20)
+#       define R128_ALPHA_BLEND_DST_ONE           (1  << 20)
+#       define R128_ALPHA_BLEND_DST_SRCCOLOR      (2  << 20)
+#       define R128_ALPHA_BLEND_DST_INVSRCCOLOR   (3  << 20)
+#       define R128_ALPHA_BLEND_DST_SRCALPHA      (4  << 20)
+#       define R128_ALPHA_BLEND_DST_INVSRCALPHA   (5  << 20)
+#       define R128_ALPHA_BLEND_DST_DSTALPHA      (6  << 20)
+#       define R128_ALPHA_BLEND_DST_INVDSTALPHA   (7  << 20)
+#       define R128_ALPHA_BLEND_DST_DSTCOLOR      (8  << 20)
+#       define R128_ALPHA_BLEND_DST_INVDSTCOLOR   (9  << 20)
+#       define R128_ALPHA_TEST_NEVER              (0  << 24)
+#       define R128_ALPHA_TEST_LESS               (1  << 24)
+#       define R128_ALPHA_TEST_LESSEQUAL          (2  << 24)
+#       define R128_ALPHA_TEST_EQUAL              (3  << 24)
+#       define R128_ALPHA_TEST_GREATEREQUAL       (4  << 24)
+#       define R128_ALPHA_TEST_GREATER            (5  << 24)
+#       define R128_ALPHA_TEST_NEQUAL             (6  << 24)
+#       define R128_ALPHA_TEST_ALWAYS             (7  << 24)
+#       define R128_COMPOSITE_SHADOW_CMP_EQUAL    (0  << 28)
+#       define R128_COMPOSITE_SHADOW_CMP_NEQUAL   (1  << 28)
+#       define R128_COMPOSITE_SHADOW              (1  << 29)
+#       define R128_TEX_MAP_ALPHA_IN_TEXTURE      (1  << 30)
+#       define R128_TEX_CACHE_LINE_SIZE_8QW       (0  << 31)
+#       define R128_TEX_CACHE_LINE_SIZE_4QW       (1  << 31)
+#define R128_SCALE_3D_DATATYPE            0x1a20
+
+#define R128_SETUP_CNTL                   0x1bc4
+#       define R128_DONT_START_TRIANGLE   (1 <<  0)
+#       define R128_Z_BIAS                (0 <<  1)
+#       define R128_DONT_START_ANY_ON     (1 <<  2)
+#       define R128_COLOR_SOLID_COLOR     (0 <<  3)
+#       define R128_COLOR_FLAT_VERT_1     (1 <<  3)
+#       define R128_COLOR_FLAT_VERT_2     (2 <<  3)
+#       define R128_COLOR_FLAT_VERT_3     (3 <<  3)
+#       define R128_COLOR_GOURAUD         (4 <<  3)
+#       define R128_PRIM_TYPE_TRI         (0 <<  7)
+#       define R128_PRIM_TYPE_LINE        (1 <<  7)
+#       define R128_PRIM_TYPE_POINT       (2 <<  7)
+#       define R128_PRIM_TYPE_POLY_EDGE   (3 <<  7)
+#       define R128_TEXTURE_ST_MULT_W     (0 <<  9)
+#       define R128_TEXTURE_ST_DIRECT     (1 <<  9)
+#       define R128_STARTING_VERTEX_1     (1 << 14)
+#       define R128_STARTING_VERTEX_2     (2 << 14)
+#       define R128_STARTING_VERTEX_3     (3 << 14)
+#       define R128_ENDING_VERTEX_1       (1 << 16)
+#       define R128_ENDING_VERTEX_2       (2 << 16)
+#       define R128_ENDING_VERTEX_3       (3 << 16)
+#       define R128_SU_POLY_LINE_LAST     (0 << 18)
+#       define R128_SU_POLY_LINE_NOT_LAST (1 << 18)
+#       define R128_SUB_PIX_2BITS         (0 << 19)
+#       define R128_SUB_PIX_4BITS         (1 << 19)
+#       define R128_SET_UP_CONTINUE       (1 << 31)
+
+#define R128_WINDOW_XY_OFFSET             0x1bcc
+#       define R128_WINDOW_Y_SHIFT        4
+#       define R128_WINDOW_X_SHIFT        20
+
+#define R128_Z_OFFSET_C                   0x1c90
+#define R128_Z_PITCH_C                    0x1c94
+#       define R128_Z_TILE                    (1 << 16)
+#define R128_Z_STEN_CNTL_C                0x1c98
+#       define R128_Z_PIX_WIDTH_16            (0 <<  1)
+#       define R128_Z_PIX_WIDTH_24            (1 <<  1)
+#       define R128_Z_PIX_WIDTH_32            (2 <<  1)
+#       define R128_Z_PIX_WIDTH_MASK          (3 <<  1)
+#       define R128_Z_TEST_NEVER              (0 <<  4)
+#       define R128_Z_TEST_LESS               (1 <<  4)
+#       define R128_Z_TEST_LESSEQUAL          (2 <<  4)
+#       define R128_Z_TEST_EQUAL              (3 <<  4)
+#       define R128_Z_TEST_GREATEREQUAL       (4 <<  4)
+#       define R128_Z_TEST_GREATER            (5 <<  4)
+#       define R128_Z_TEST_NEQUAL             (6 <<  4)
+#       define R128_Z_TEST_ALWAYS             (7 <<  4)
+#       define R128_Z_TEST_MASK               (7 <<  4)
+#       define R128_STENCIL_TEST_NEVER        (0 << 12)
+#       define R128_STENCIL_TEST_LESS         (1 << 12)
+#       define R128_STENCIL_TEST_LESSEQUAL    (2 << 12)
+#       define R128_STENCIL_TEST_EQUAL        (3 << 12)
+#       define R128_STENCIL_TEST_GREATEREQUAL (4 << 12)
+#       define R128_STENCIL_TEST_GREATER      (5 << 12)
+#       define R128_STENCIL_TEST_NEQUAL       (6 << 12)
+#       define R128_STENCIL_TEST_ALWAYS       (7 << 12)
+#       define R128_STENCIL_S_FAIL_KEEP       (0 << 16)
+#       define R128_STENCIL_S_FAIL_ZERO       (1 << 16)
+#       define R128_STENCIL_S_FAIL_REPLACE    (2 << 16)
+#       define R128_STENCIL_S_FAIL_INC        (3 << 16)
+#       define R128_STENCIL_S_FAIL_DEC        (4 << 16)
+#       define R128_STENCIL_S_FAIL_INV        (5 << 16)
+#       define R128_STENCIL_ZPASS_KEEP        (0 << 20)
+#       define R128_STENCIL_ZPASS_ZERO        (1 << 20)
+#       define R128_STENCIL_ZPASS_REPLACE     (2 << 20)
+#       define R128_STENCIL_ZPASS_INC         (3 << 20)
+#       define R128_STENCIL_ZPASS_DEC         (4 << 20)
+#       define R128_STENCIL_ZPASS_INV         (5 << 20)
+#       define R128_STENCIL_ZFAIL_KEEP        (0 << 24)
+#       define R128_STENCIL_ZFAIL_ZERO        (1 << 24)
+#       define R128_STENCIL_ZFAIL_REPLACE     (2 << 24)
+#       define R128_STENCIL_ZFAIL_INC         (3 << 24)
+#       define R128_STENCIL_ZFAIL_DEC         (4 << 24)
+#       define R128_STENCIL_ZFAIL_INV         (5 << 24)
+#define R128_TEX_CNTL_C                   0x1c9c
+#       define R128_Z_ENABLE                   (1 <<  0)
+#       define R128_Z_WRITE_ENABLE             (1 <<  1)
+#       define R128_STENCIL_ENABLE             (1 <<  3)
+#       define R128_SHADE_ENABLE               (0 <<  4)
+#       define R128_TEXMAP_ENABLE              (1 <<  4)
+#       define R128_SEC_TEXMAP_ENABLE          (1 <<  5)
+#       define R128_FOG_ENABLE                 (1 <<  7)
+#       define R128_DITHER_ENABLE              (1 <<  8)
+#       define R128_ALPHA_ENABLE               (1 <<  9)
+#       define R128_ALPHA_TEST_ENABLE          (1 << 10)
+#       define R128_SPEC_LIGHT_ENABLE          (1 << 11)
+#       define R128_TEX_CHROMA_KEY_ENABLE      (1 << 12)
+#       define R128_ALPHA_IN_TEX_COMPLETE_A    (0 << 13)
+#       define R128_ALPHA_IN_TEX_LSB_A         (1 << 13)
+#       define R128_LIGHT_DIS                  (0 << 14)
+#       define R128_LIGHT_COPY                 (1 << 14)
+#       define R128_LIGHT_MODULATE             (2 << 14)
+#       define R128_LIGHT_ADD                  (3 << 14)
+#       define R128_LIGHT_BLEND_CONSTANT       (4 << 14)
+#       define R128_LIGHT_BLEND_TEXTURE        (5 << 14)
+#       define R128_LIGHT_BLEND_VERTEX         (6 << 14)
+#       define R128_LIGHT_BLEND_CONST_COLOR    (7 << 14)
+#       define R128_ALPHA_LIGHT_DIS            (0 << 18)
+#       define R128_ALPHA_LIGHT_COPY           (1 << 18)
+#       define R128_ALPHA_LIGHT_MODULATE       (2 << 18)
+#       define R128_ALPHA_LIGHT_ADD            (3 << 18)
+#       define R128_ANTI_ALIAS                 (1 << 21)
+#       define R128_TEX_CACHE_FLUSH            (1 << 23)
+#       define R128_LOD_BIAS_SHIFT             24
+#       define R128_LOD_BIAS_MASK              (0xff << 24)
+#define R128_MISC_3D_STATE_CNTL_REG       0x1ca0
+#       define R128_REF_ALPHA_MASK                  0xff
+#       define R128_MISC_SCALE_3D_NOOP              (0  <<  8)
+#       define R128_MISC_SCALE_3D_SCALE             (1  <<  8)
+#       define R128_MISC_SCALE_3D_TEXMAP_SHADE      (2  <<  8)
+#       define R128_MISC_SCALE_PIX_BLEND            (0  << 10)
+#       define R128_MISC_SCALE_PIX_REPLICATE        (1  << 10)
+#       define R128_ALPHA_COMB_ADD_CLAMP            (0  << 12)
+#       define R128_ALPHA_COMB_ADD_NO_CLAMP         (1  << 12)
+#       define R128_ALPHA_COMB_SUB_SRC_DST_CLAMP    (2  << 12)
+#       define R128_ALPHA_COMB_SUB_SRC_DST_NO_CLAMP (3  << 12)
+#       define R128_FOG_VERTEX                      (0  << 14)
+#       define R128_FOG_TABLE                       (1  << 14)
+#       define R128_ALPHA_BLEND_SRC_ZERO            (0  << 16)
+#       define R128_ALPHA_BLEND_SRC_ONE             (1  << 16)
+#       define R128_ALPHA_BLEND_SRC_SRCCOLOR        (2  << 16)
+#       define R128_ALPHA_BLEND_SRC_INVSRCCOLOR     (3  << 16)
+#       define R128_ALPHA_BLEND_SRC_SRCALPHA        (4  << 16)
+#       define R128_ALPHA_BLEND_SRC_INVSRCALPHA     (5  << 16)
+#       define R128_ALPHA_BLEND_SRC_DESTALPHA       (6  << 16)
+#       define R128_ALPHA_BLEND_SRC_INVDESTALPHA    (7  << 16)
+#       define R128_ALPHA_BLEND_SRC_DESTCOLOR       (8  << 16)
+#       define R128_ALPHA_BLEND_SRC_INVDESTCOLOR    (9  << 16)
+#       define R128_ALPHA_BLEND_SRC_SRCALPHASAT     (10 << 16)
+#       define R128_ALPHA_BLEND_SRC_BOTHSRCALPHA    (11 << 16)
+#       define R128_ALPHA_BLEND_SRC_BOTHINVSRCALPHA (12 << 16)
+#       define R128_ALPHA_BLEND_SRC_MASK            (15 << 16)
+#       define R128_ALPHA_BLEND_DST_ZERO            (0  << 20)
+#       define R128_ALPHA_BLEND_DST_ONE             (1  << 20)
+#       define R128_ALPHA_BLEND_DST_SRCCOLOR        (2  << 20)
+#       define R128_ALPHA_BLEND_DST_INVSRCCOLOR     (3  << 20)
+#       define R128_ALPHA_BLEND_DST_SRCALPHA        (4  << 20)
+#       define R128_ALPHA_BLEND_DST_INVSRCALPHA     (5  << 20)
+#       define R128_ALPHA_BLEND_DST_DESTALPHA       (6  << 20)
+#       define R128_ALPHA_BLEND_DST_INVDESTALPHA    (7  << 20)
+#       define R128_ALPHA_BLEND_DST_DESTCOLOR       (8  << 20)
+#       define R128_ALPHA_BLEND_DST_INVDESTCOLOR    (9  << 20)
+#       define R128_ALPHA_BLEND_DST_SRCALPHASAT     (10 << 20)
+#       define R128_ALPHA_BLEND_DST_MASK            (15 << 20)
+#       define R128_ALPHA_TEST_NEVER                (0  << 24)
+#       define R128_ALPHA_TEST_LESS                 (1  << 24)
+#       define R128_ALPHA_TEST_LESSEQUAL            (2  << 24)
+#       define R128_ALPHA_TEST_EQUAL                (3  << 24)
+#       define R128_ALPHA_TEST_GREATEREQUAL         (4  << 24)
+#       define R128_ALPHA_TEST_GREATER              (5  << 24)
+#       define R128_ALPHA_TEST_NEQUAL               (6  << 24)
+#       define R128_ALPHA_TEST_ALWAYS               (7  << 24)
+#       define R128_ALPHA_TEST_MASK                 (7  << 24)
+#define R128_TEXTURE_CLR_CMP_CLR_C        0x1ca4
+#define R128_TEXTURE_CLR_CMP_MSK_C        0x1ca8
+#define R128_FOG_COLOR_C                  0x1cac
+#       define R128_FOG_BLUE_SHIFT             0
+#       define R128_FOG_GREEN_SHIFT            8
+#       define R128_FOG_RED_SHIFT             16
+#define R128_PRIM_TEX_CNTL_C              0x1cb0
+#       define R128_MIN_BLEND_NEAREST          (0  <<  1)
+#       define R128_MIN_BLEND_LINEAR           (1  <<  1)
+#       define R128_MIN_BLEND_MIPNEAREST       (2  <<  1)
+#       define R128_MIN_BLEND_MIPLINEAR        (3  <<  1)
+#       define R128_MIN_BLEND_LINEARMIPNEAREST (4  <<  1)
+#       define R128_MIN_BLEND_LINEARMIPLINEAR  (5  <<  1)
+#       define R128_MIN_BLEND_MASK             (7  <<  1)
+#       define R128_MAG_BLEND_NEAREST          (0  <<  4)
+#       define R128_MAG_BLEND_LINEAR           (1  <<  4)
+#       define R128_MAG_BLEND_MASK             (7  <<  4)
+#       define R128_MIP_MAP_DISABLE            (1  <<  7)
+#       define R128_TEX_CLAMP_S_WRAP           (0  <<  8)
+#       define R128_TEX_CLAMP_S_MIRROR         (1  <<  8)
+#       define R128_TEX_CLAMP_S_CLAMP          (2  <<  8)
+#       define R128_TEX_CLAMP_S_BORDER_COLOR   (3  <<  8)
+#       define R128_TEX_CLAMP_S_MASK           (3  <<  8)
+#       define R128_TEX_WRAP_S                 (1  << 10)
+#       define R128_TEX_CLAMP_T_WRAP           (0  << 11)
+#       define R128_TEX_CLAMP_T_MIRROR         (1  << 11)
+#       define R128_TEX_CLAMP_T_CLAMP          (2  << 11)
+#       define R128_TEX_CLAMP_T_BORDER_COLOR   (3  << 11)
+#       define R128_TEX_CLAMP_T_MASK           (3  << 11)
+#       define R128_TEX_WRAP_T                 (1  << 13)
+#       define R128_TEX_PERSPECTIVE_DISABLE    (1  << 14)
+#       define R128_DATATYPE_VQ                (0  << 16)
+#       define R128_DATATYPE_CI4               (1  << 16)
+#       define R128_DATATYPE_CI8               (2  << 16)
+#       define R128_DATATYPE_ARGB1555          (3  << 16)
+#       define R128_DATATYPE_RGB565            (4  << 16)
+#       define R128_DATATYPE_RGB888            (5  << 16)
+#       define R128_DATATYPE_ARGB8888          (6  << 16)
+#       define R128_DATATYPE_RGB332            (7  << 16)
+#       define R128_DATATYPE_Y8                (8  << 16)
+#       define R128_DATATYPE_RGB8              (9  << 16)
+#       define R128_DATATYPE_CI16              (10 << 16)
+#       define R128_DATATYPE_YVYU422           (11 << 16)
+#       define R128_DATATYPE_VYUY422           (12 << 16)
+#       define R128_DATATYPE_AYUV444           (14 << 16)
+#       define R128_DATATYPE_ARGB4444          (15 << 16)
+#       define R128_PALLETE_EITHER             (0  << 20)
+#       define R128_PALLETE_1                  (1  << 20)
+#       define R128_PALLETE_2                  (2  << 20)
+#       define R128_PSEUDOCOLOR_DT_RGB565      (0  << 24)
+#       define R128_PSEUDOCOLOR_DT_ARGB1555    (1  << 24)
+#       define R128_PSEUDOCOLOR_DT_ARGB4444    (2  << 24)
+#define R128_PRIM_TEXTURE_COMBINE_CNTL_C  0x1cb4
+#       define R128_COMB_DIS                   (0  <<  0)
+#       define R128_COMB_COPY                  (1  <<  0)
+#       define R128_COMB_COPY_INP              (2  <<  0)
+#       define R128_COMB_MODULATE              (3  <<  0)
+#       define R128_COMB_MODULATE2X            (4  <<  0)
+#       define R128_COMB_MODULATE4X            (5  <<  0)
+#       define R128_COMB_ADD                   (6  <<  0)
+#       define R128_COMB_ADD_SIGNED            (7  <<  0)
+#       define R128_COMB_BLEND_VERTEX          (8  <<  0)
+#       define R128_COMB_BLEND_TEXTURE         (9  <<  0)
+#       define R128_COMB_BLEND_CONST           (10 <<  0)
+#       define R128_COMB_BLEND_PREMULT         (11 <<  0)
+#       define R128_COMB_BLEND_PREV            (12 <<  0)
+#       define R128_COMB_BLEND_PREMULT_INV     (13 <<  0)
+#       define R128_COMB_ADD_SIGNED2X          (14 <<  0)
+#       define R128_COMB_BLEND_CONST_COLOR     (15 <<  0)
+#       define R128_COMB_MASK                  (15 <<  0)
+#       define R128_COLOR_FACTOR_CONST_COLOR   (0  <<  4)
+#       define R128_COLOR_FACTOR_NCONST_COLOR  (1  <<  4)
+#       define R128_COLOR_FACTOR_TEX           (4  <<  4)
+#       define R128_COLOR_FACTOR_NTEX          (5  <<  4)
+#       define R128_COLOR_FACTOR_ALPHA         (6  <<  4)
+#       define R128_COLOR_FACTOR_NALPHA        (7  <<  4)
+#       define R128_COLOR_FACTOR_PREV_COLOR    (8  <<  4)
+#       define R128_COLOR_FACTOR_MASK          (15 <<  4)
+#       define R128_COMB_FCN_MSB               (1  <<  8)
+#       define R128_INPUT_FACTOR_CONST_COLOR   (2  << 10)
+#       define R128_INPUT_FACTOR_CONST_ALPHA   (3  << 10)
+#       define R128_INPUT_FACTOR_INT_COLOR     (4  << 10)
+#       define R128_INPUT_FACTOR_INT_ALPHA     (5  << 10)
+#       define R128_INPUT_FACTOR_MASK          (15 << 10)
+#       define R128_COMB_ALPHA_DIS             (0  << 14)
+#       define R128_COMB_ALPHA_COPY            (1  << 14)
+#       define R128_COMB_ALPHA_COPY_INP        (2  << 14)
+#       define R128_COMB_ALPHA_MODULATE        (3  << 14)
+#       define R128_COMB_ALPHA_MODULATE2X      (4  << 14)
+#       define R128_COMB_ALPHA_MODULATE4X      (5  << 14)
+#       define R128_COMB_ALPHA_ADD             (6  << 14)
+#       define R128_COMB_ALPHA_ADD_SIGNED      (7  << 14)
+#       define R128_COMB_ALPHA_ADD_SIGNED2X    (14 << 14)
+#       define R128_COMB_ALPHA_MASK            (15 << 14)
+#       define R128_ALPHA_FACTOR_TEX_ALPHA     (6  << 18)
+#       define R128_ALPHA_FACTOR_NTEX_ALPHA    (7  << 18)
+#       define R128_ALPHA_FACTOR_MASK          (15 << 18)
+#       define R128_INP_FACTOR_A_CONST_ALPHA   (1  << 25)
+#       define R128_INP_FACTOR_A_INT_ALPHA     (2  << 25)
+#       define R128_INP_FACTOR_A_MASK          (7  << 25)
+#define R128_TEX_SIZE_PITCH_C             0x1cb8
+#       define R128_TEX_PITCH_SHIFT           0
+#       define R128_TEX_SIZE_SHIFT            4
+#       define R128_TEX_HEIGHT_SHIFT          8
+#       define R128_TEX_MIN_SIZE_SHIFT       12
+#       define R128_SEC_TEX_PITCH_SHIFT      16
+#       define R128_SEC_TEX_SIZE_SHIFT       20
+#       define R128_SEC_TEX_HEIGHT_SHIFT     24
+#       define R128_SEC_TEX_MIN_SIZE_SHIFT   28
+#       define R128_TEX_PITCH_MASK           (0x0f <<  0)
+#       define R128_TEX_SIZE_MASK            (0x0f <<  4)
+#       define R128_TEX_HEIGHT_MASK          (0x0f <<  8)
+#       define R128_TEX_MIN_SIZE_MASK        (0x0f << 12)
+#       define R128_SEC_TEX_PITCH_MASK       (0x0f << 16)
+#       define R128_SEC_TEX_SIZE_MASK        (0x0f << 20)
+#       define R128_SEC_TEX_HEIGHT_MASK      (0x0f << 24)
+#       define R128_SEC_TEX_MIN_SIZE_MASK    (0x0f << 28)
+#       define R128_TEX_SIZE_PITCH_SHIFT      0
+#       define R128_SEC_TEX_SIZE_PITCH_SHIFT 16
+#       define R128_TEX_SIZE_PITCH_MASK      (0xffff <<  0)
+#       define R128_SEC_TEX_SIZE_PITCH_MASK  (0xffff << 16)
+#define R128_PRIM_TEX_0_OFFSET_C          0x1cbc
+#define R128_PRIM_TEX_1_OFFSET_C          0x1cc0
+#define R128_PRIM_TEX_2_OFFSET_C          0x1cc4
+#define R128_PRIM_TEX_3_OFFSET_C          0x1cc8
+#define R128_PRIM_TEX_4_OFFSET_C          0x1ccc
+#define R128_PRIM_TEX_5_OFFSET_C          0x1cd0
+#define R128_PRIM_TEX_6_OFFSET_C          0x1cd4
+#define R128_PRIM_TEX_7_OFFSET_C          0x1cd8
+#define R128_PRIM_TEX_8_OFFSET_C          0x1cdc
+#define R128_PRIM_TEX_9_OFFSET_C          0x1ce0
+#define R128_PRIM_TEX_10_OFFSET_C         0x1ce4
+#       define R128_TEX_NO_TILE           (0 << 30)
+#       define R128_TEX_TILED_BY_HOST     (1 << 30)
+#       define R128_TEX_TILED_BY_STORAGE  (2 << 30)
+#       define R128_TEX_TILED_BY_STORAGE2 (3 << 30)
+
+#define R128_SEC_TEX_CNTL_C               0x1d00
+#       define R128_SEC_SELECT_PRIM_ST    (0  <<  0)
+#       define R128_SEC_SELECT_SEC_ST     (1  <<  0)
+#define R128_SEC_TEX_COMBINE_CNTL_C       0x1d04
+#       define R128_INPUT_FACTOR_PREV_COLOR (8  << 10)
+#       define R128_INPUT_FACTOR_PREV_ALPHA (9  << 10)
+#       define R128_INP_FACTOR_A_PREV_ALPHA (4  << 25)
+#define R128_SEC_TEX_0_OFFSET_C           0x1d08
+#define R128_SEC_TEX_1_OFFSET_C           0x1d0c
+#define R128_SEC_TEX_2_OFFSET_C           0x1d10
+#define R128_SEC_TEX_3_OFFSET_C           0x1d14
+#define R128_SEC_TEX_4_OFFSET_C           0x1d18
+#define R128_SEC_TEX_5_OFFSET_C           0x1d1c
+#define R128_SEC_TEX_6_OFFSET_C           0x1d20
+#define R128_SEC_TEX_7_OFFSET_C           0x1d24
+#define R128_SEC_TEX_8_OFFSET_C           0x1d28
+#define R128_SEC_TEX_9_OFFSET_C           0x1d2c
+#define R128_SEC_TEX_10_OFFSET_C          0x1d30
+#define R128_CONSTANT_COLOR_C             0x1d34
+#       define R128_CONSTANT_BLUE_SHIFT        0
+#       define R128_CONSTANT_GREEN_SHIFT       8
+#       define R128_CONSTANT_RED_SHIFT        16
+#       define R128_CONSTANT_ALPHA_SHIFT      24
+#define R128_PRIM_TEXTURE_BORDER_COLOR_C  0x1d38
+#       define R128_PRIM_TEX_BORDER_BLUE_SHIFT   0
+#       define R128_PRIM_TEX_BORDER_GREEN_SHIFT  8
+#       define R128_PRIM_TEX_BORDER_RED_SHIFT   16
+#       define R128_PRIM_TEX_BORDER_ALPHA_SHIFT 24
+#define R128_SEC_TEXTURE_BORDER_COLOR_C   0x1d3c
+#       define R128_SEC_TEX_BORDER_BLUE_SHIFT   0
+#       define R128_SEC_TEX_BORDER_GREEN_SHIFT  8
+#       define R128_SEC_TEX_BORDER_RED_SHIFT   16
+#       define R128_SEC_TEX_BORDER_ALPHA_SHIFT 24
+#define R128_STEN_REF_MASK_C              0x1d40
+#       define R128_STEN_REFERENCE_SHIFT       0
+#       define R128_STEN_MASK_SHIFT           16
+#       define R128_STEN_WRITE_MASK_SHIFT     24
+#define R128_PLANE_3D_MASK_C              0x1d44
+#define R128_TEX_CACHE_STAT_COUNT         0x1974
+
+
+                               /* Constants */
+#define R128_AGP_TEX_OFFSET               0x02000000
+
+#define R128_LAST_FRAME_REG               R128_GUI_SCRATCH_REG0
+
+                               /* CCE packet types */
+#define R128_CCE_PACKET0                         0x00000000
+#define R128_CCE_PACKET0_ONE_REG_WR              0x00008000
+#define R128_CCE_PACKET1                         0x40000000
+#define R128_CCE_PACKET2                         0x80000000
+#define R128_CCE_PACKET3                         0xC0000000
+#define R128_CCE_PACKET3_NOP                     0xC0001000
+#define R128_CCE_PACKET3_PAINT                   0xC0001100
+#define R128_CCE_PACKET3_BITBLT                  0xC0001200
+#define R128_CCE_PACKET3_SMALLTEXT               0xC0001300
+#define R128_CCE_PACKET3_HOSTDATA_BLT            0xC0001400
+#define R128_CCE_PACKET3_POLYLINE                0xC0001500
+#define R128_CCE_PACKET3_SCALING                 0xC0001600
+#define R128_CCE_PACKET3_TRANS_SCALING           0xC0001700
+#define R128_CCE_PACKET3_POLYSCANLINES           0xC0001800
+#define R128_CCE_PACKET3_NEXT_CHAR               0xC0001900
+#define R128_CCE_PACKET3_PAINT_MULTI             0xC0001A00
+#define R128_CCE_PACKET3_BITBLT_MULTI            0xC0001B00
+#define R128_CCE_PACKET3_PLY_NEXTSCAN            0xC0001D00
+#define R128_CCE_PACKET3_SET_SCISSORS            0xC0001E00
+#define R128_CCE_PACKET3_SET_MODE24BPP           0xC0001F00
+#define R128_CCE_PACKET3_CNTL_PAINT              0xC0009100
+#define R128_CCE_PACKET3_CNTL_BITBLT             0xC0009200
+#define R128_CCE_PACKET3_CNTL_SMALLTEXT          0xC0009300
+#define R128_CCE_PACKET3_CNTL_HOSTDATA_BLT       0xC0009400
+#define R128_CCE_PACKET3_CNTL_POLYLINE           0xC0009500
+#define R128_CCE_PACKET3_CNTL_SCALING            0xC0009600
+#define R128_CCE_PACKET3_CNTL_TRANS_SCALING      0xC0009700
+#define R128_CCE_PACKET3_CNTL_POLYSCANLINES      0xC0009800
+#define R128_CCE_PACKET3_CNTL_NEXT_CHAR          0xC0009900
+#define R128_CCE_PACKET3_CNTL_PAINT_MULTI        0xC0009A00
+#define R128_CCE_PACKET3_CNTL_BITBLT_MULTI       0xC0009B00
+#define R128_CCE_PACKET3_CNTL_TRANS_BITBLT       0xC0009C00
+#define R128_CCE_PACKET3_3D_SAVE_CONTEXT         0xC0002000
+#define R128_CCE_PACKET3_3D_PLAY_CONTEXT         0xC0002100
+#define R128_CCE_PACKET3_3D_RNDR_GEN_INDX_PRIM   0xC0002300
+#define R128_CCE_PACKET3_3D_RNDR_GEN_PRIM        0xC0002500
+#define R128_CCE_PACKET3_LOAD_PALETTE            0xC0002C00
+#define R128_CCE_PACKET3_PURGE                   0xC0002D00
+#define R128_CCE_PACKET3_NEXT_VERTEX_BUNDLE      0xC0002E00
+#       define R128_CCE_PACKET_MASK              0xC0000000
+#       define R128_CCE_PACKET_COUNT_MASK        0x3fff0000
+#       define R128_CCE_PACKET_MAX_DWORDS        (1 << 12)
+#       define R128_CCE_PACKET0_REG_MASK         0x000007ff
+#       define R128_CCE_PACKET1_REG0_MASK        0x000007ff
+#       define R128_CCE_PACKET1_REG1_MASK        0x003ff800
+
+#define R128_CCE_VC_FRMT_RHW                     0x00000001
+#define R128_CCE_VC_FRMT_DIFFUSE_BGR             0x00000002
+#define R128_CCE_VC_FRMT_DIFFUSE_A               0x00000004
+#define R128_CCE_VC_FRMT_DIFFUSE_ARGB            0x00000008
+#define R128_CCE_VC_FRMT_SPEC_BGR                0x00000010
+#define R128_CCE_VC_FRMT_SPEC_F                  0x00000020
+#define R128_CCE_VC_FRMT_SPEC_FRGB               0x00000040
+#define R128_CCE_VC_FRMT_S_T                     0x00000080
+#define R128_CCE_VC_FRMT_S2_T2                   0x00000100
+#define R128_CCE_VC_FRMT_RHW2                    0x00000200
+
+#define R128_CCE_VC_CNTL_PRIM_TYPE_NONE          0x00000000
+#define R128_CCE_VC_CNTL_PRIM_TYPE_POINT         0x00000001
+#define R128_CCE_VC_CNTL_PRIM_TYPE_LINE          0x00000002
+#define R128_CCE_VC_CNTL_PRIM_TYPE_POLY_LINE     0x00000003
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST      0x00000004
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_FAN       0x00000005
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_STRIP     0x00000006
+#define R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2     0x00000007
+#define R128_CCE_VC_CNTL_PRIM_WALK_IND           0x00000010
+#define R128_CCE_VC_CNTL_PRIM_WALK_LIST          0x00000020
+#define R128_CCE_VC_CNTL_PRIM_WALK_RING          0x00000030
+#define R128_CCE_VC_CNTL_NUM_SHIFT               16
+
+/* hmm copyed blindly (no specs) from radeon.h ... */
+#define R128_RE_TOP_LEFT                  0x26c0
+#       define R128_RE_LEFT_SHIFT         0
+#       define R128_RE_TOP_SHIFT          16
+#define R128_RE_WIDTH_HEIGHT              0x1c44
+#       define R128_RE_WIDTH_SHIFT        0
+#       define R128_RE_HEIGHT_SHIFT       16
+
+#endif
diff --git a/src/mesa/drivers/dri/r128/server/r128_sarea.h b/src/mesa/drivers/dri/r128/server/r128_sarea.h
new file mode 100644 (file)
index 0000000..8a9f3a4
--- /dev/null
@@ -0,0 +1,195 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_sarea.h,v 1.7 2002/02/16 21:26:35 herrb Exp $ */
+/*
+ * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
+ *                      Precision Insight, Inc., Cedar Park, Texas, and
+ *                      VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT.  IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
+ * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#ifndef _R128_SAREA_H_
+#define _R128_SAREA_H_
+
+/* WARNING: If you change any of these defines, make sure to change the
+ * defines in the kernel file (r128_drm.h)
+ */
+#ifndef __R128_SAREA_DEFINES__
+#define __R128_SAREA_DEFINES__
+
+/* What needs to be changed for the current vertex buffer?
+ */
+#define R128_UPLOAD_CONTEXT            0x001
+#define R128_UPLOAD_SETUP              0x002
+#define R128_UPLOAD_TEX0               0x004
+#define R128_UPLOAD_TEX1               0x008
+#define R128_UPLOAD_TEX0IMAGES         0x010
+#define R128_UPLOAD_TEX1IMAGES         0x020
+#define R128_UPLOAD_CORE               0x040
+#define R128_UPLOAD_MASKS              0x080
+#define R128_UPLOAD_WINDOW             0x100
+#define R128_UPLOAD_CLIPRECTS          0x200   /* handled client-side */
+#define R128_REQUIRE_QUIESCENCE                0x400
+#define R128_UPLOAD_ALL                        0x7ff
+
+#define R128_FRONT                     0x1
+#define R128_BACK                      0x2
+#define R128_DEPTH                     0x4
+
+/* Primitive types
+ */
+#define R128_POINTS                    0x1
+#define R128_LINES                     0x2
+#define R128_LINE_STRIP                        0x3
+#define R128_TRIANGLES                 0x4
+#define R128_TRIANGLE_FAN              0x5
+#define R128_TRIANGLE_STRIP            0x6
+
+/* Vertex/indirect buffer size
+ */
+#define R128_BUFFER_SIZE               16384
+
+/* Byte offsets for indirect buffer data
+ */
+#define R128_INDEX_PRIM_OFFSET         20
+#define R128_HOSTDATA_BLIT_OFFSET      32
+
+/* Keep these small for testing
+ */
+#define R128_NR_SAREA_CLIPRECTS                12
+
+/* There are 2 heaps (local/AGP).  Each region within a heap is a
+ * minimum of 64k, and there are at most 64 of them per heap.
+ */
+#define R128_CARD_HEAP                 0
+#define R128_AGP_HEAP                  1
+#define R128_NR_TEX_HEAPS              2
+#define R128_NR_TEX_REGIONS            64
+#define R128_LOG_TEX_GRANULARITY       16
+
+#define R128_NR_CONTEXT_REGS           12
+
+#define R128_MAX_TEXTURE_LEVELS                11
+#define R128_MAX_TEXTURE_UNITS         2
+
+#endif /* __R128_SAREA_DEFINES__ */
+
+typedef struct {
+    /* Context state - can be written in one large chunk */
+    unsigned int dst_pitch_offset_c;
+    unsigned int dp_gui_master_cntl_c;
+    unsigned int sc_top_left_c;
+    unsigned int sc_bottom_right_c;
+    unsigned int z_offset_c;
+    unsigned int z_pitch_c;
+    unsigned int z_sten_cntl_c;
+    unsigned int tex_cntl_c;
+    unsigned int misc_3d_state_cntl_reg;
+    unsigned int texture_clr_cmp_clr_c;
+    unsigned int texture_clr_cmp_msk_c;
+    unsigned int fog_color_c;
+
+    /* Texture state */
+    unsigned int tex_size_pitch_c;
+    unsigned int constant_color_c;
+
+    /* Setup state */
+    unsigned int pm4_vc_fpu_setup;
+    unsigned int setup_cntl;
+
+    /* Mask state */
+    unsigned int dp_write_mask;
+    unsigned int sten_ref_mask_c;
+    unsigned int plane_3d_mask_c;
+
+    /* Window state */
+    unsigned int window_xy_offset;
+
+    /* Core state */
+    unsigned int scale_3d_cntl;
+} r128_context_regs_t;
+
+/* Setup registers for each texture unit
+ */
+typedef struct {
+    unsigned int tex_cntl;
+    unsigned int tex_combine_cntl;
+    unsigned int tex_size_pitch;
+    unsigned int tex_offset[R128_MAX_TEXTURE_LEVELS];
+    unsigned int tex_border_color;
+} r128_texture_regs_t;
+
+typedef struct {
+    /* The channel for communication of state information to the kernel
+     * on firing a vertex buffer.
+     */
+    r128_context_regs_t        ContextState;
+    r128_texture_regs_t        TexState[R128_MAX_TEXTURE_UNITS];
+    unsigned int dirty;
+    unsigned int vertsize;
+    unsigned int vc_format;
+
+#if defined(XF86DRI) | defined(_SOLO)
+    /* The current cliprects, or a subset thereof.
+     */
+    XF86DRIClipRectRec boxes[R128_NR_SAREA_CLIPRECTS];
+    unsigned int nbox;
+#endif
+
+    /* Counters for throttling of rendering clients.
+     */
+    unsigned int last_frame;
+    unsigned int last_dispatch;
+
+    /* Maintain an LRU of contiguous regions of texture space.  If you
+     * think you own a region of texture memory, and it has an age
+     * different to the one you set, then you are mistaken and it has
+     * been stolen by another client.  If global texAge hasn't changed,
+     * there is no need to walk the list.
+     *
+     * These regions can be used as a proxy for the fine-grained texture
+     * information of other clients - by maintaining them in the same
+     * lru which is used to age their own textures, clients have an
+     * approximate lru for the whole of global texture space, and can
+     * make informed decisions as to which areas to kick out.  There is
+     * no need to choose whether to kick out your own texture or someone
+     * else's - simply eject them all in LRU order.
+     */
+                               /* Last elt is sentinal */
+    drmTextureRegion texList[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1];
+                               /* last time texture was uploaded */
+    unsigned int texAge[R128_NR_TEX_HEAPS];
+
+    int ctxOwner;              /* last context to upload state */
+    int pfAllowPageFlip;       /* set by the 2d driver, read by the client */
+    int pfCurrentPage;         /* set by kernel, read by others */
+} R128SAREAPriv, *R128SAREAPrivPtr;
+
+#endif
diff --git a/src/mesa/drivers/dri/r128/server/r128_version.h b/src/mesa/drivers/dri/r128/server/r128_version.h
new file mode 100644 (file)
index 0000000..589d8d4
--- /dev/null
@@ -0,0 +1,60 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_version.h,v 1.6 2003/01/01 19:16:35 tsi Exp $ */
+/*
+ * Copyright 2000 through 2003 by Marc Aurele La France (TSI @ UQV), tsi@xfree86.org
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of Marc Aurele La France not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  Marc Aurele La France makes no representations
+ * about the suitability of this software for any purpose.  It is provided
+ * "as-is" without express or implied warranty.
+ *
+ * MARC AURELE LA FRANCE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO
+ * EVENT SHALL MARC AURELE LA FRANCE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _R128_VERSION_H_
+#define _R128_VERSION_H_ 1
+
+#undef  R128_NAME
+#undef  R128_DRIVER_NAME
+#undef  R128_VERSION_MAJOR
+#undef  R128_VERSION_MINOR
+#undef  R128_VERSION_PATCH
+#undef  R128_VERSION_CURRENT
+#undef  R128_VERSION_EVALUATE
+#undef  R128_VERSION_STRINGIFY
+#undef  R128_VERSION_NAME
+
+#define R128_NAME          "R128"
+#define R128_DRIVER_NAME   "r128"
+
+#define R128_VERSION_MAJOR 4
+#define R128_VERSION_MINOR 0
+#define R128_VERSION_PATCH 1
+
+#ifndef R128_VERSION_EXTRA
+#define R128_VERSION_EXTRA ""
+#endif
+
+#define R128_VERSION_CURRENT \
+    ((R128_VERSION_MAJOR << 20) | \
+     (R128_VERSION_MINOR << 10) | \
+     (R128_VERSION_PATCH))
+
+#define R128_VERSION_EVALUATE(__x) #__x
+#define R128_VERSION_STRINGIFY(_x) R128_VERSION_EVALUATE(_x)
+#define R128_VERSION_NAME                                         \
+    R128_VERSION_STRINGIFY(R128_VERSION_MAJOR) "."                \
+    R128_VERSION_STRINGIFY(R128_VERSION_MINOR) "."                \
+    R128_VERSION_STRINGIFY(R128_VERSION_MINOR) R128_VERSION_EXTRA
+
+#endif /* _R128_VERSION_H_ */
index b182ba559aa2059684fbeead4f4012251bf5a66d..f1887b591441d3b5da18cdda5578b2df69bfc5a5 100644 (file)
@@ -1,4 +1,4 @@
-# $Id: Makefile.X11,v 1.1 2003/08/06 17:59:57 keithw Exp $
+# $Id: Makefile.X11,v 1.2 2003/08/22 20:11:45 brianp Exp $
 
 # Mesa 3-D graphics library
 # Version:  5.0
@@ -6,8 +6,10 @@
 
 TOP = ../../../../..
 
+default: linux-solo
+
 SHARED_INCLUDES = $(INCLUDE_DIRS) -I. -I../common -Iserver
-MINIGLX_INCLUDES = -I$(TOP)/src/miniglx 
+MINIGLX_INCLUDES = -I$(TOP)/src/glx/mini
 
 DEFINES += \
        -D_HAVE_SWRAST=1 \
@@ -62,7 +64,7 @@ WINOBJ=$(MESABUILDDIR)/dri/dri.a
 WINLIB=
 else
 WINOBJ=
-WINLIB=-L$(MESA)/src/miniglx
+WINLIB=-L$(MESA)/src/glx/mini
 endif
 
 ASM_SOURCES = 
@@ -107,7 +109,7 @@ INCLUDE_DIRS = \
 
 ##### TARGETS #####
 
-targets: r200_dri.so
+targets: depend r200_dri.so
 
 r200_dri.so:  $(SYMLINKS) $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile.X11
        rm -f $@ && gcc -o $@ -shared $(OBJECTS) $(MESA_MODULES) $(WINOBJ) $(WINLIB) -lc $(GL_LIB_DEPS)
@@ -116,8 +118,8 @@ r200_dri.so:  $(SYMLINKS) $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile.X11
 
 # Run 'make -f Makefile.X11 dep' to update the dependencies if you change
 # what's included by any source file.
-dep: $(C_SOURCES) $(ASM_SOURCES)
-       makedepend -fdepend -Y $(SHARED_INCLUDES) \
+depend: $(C_SOURCES) $(ASM_SOURCES)
+       makedepend -fdepend -Y $(SHARED_INCLUDES) $(MINIGLX_INCLUDES) \
                $(C_SOURCES) $(ASM_SOURCES)
 
 
@@ -128,7 +130,7 @@ tags:
 
 # Remove .o and backup files
 clean:
-       -rm -f *.o *~ *.o *~ *.so
+       -rm -f *.o */*.o *~ *.o *~ *.so server/*.o
 
 
 include $(TOP)/Make-config
index c5f23effabbee59f1b6e34bad29c3fcd31b0382a..ec95f05e6ef1ec25feff8afc4a6606dc222b51fd 100644 (file)
@@ -492,8 +492,9 @@ void r200DestroyContext( __DRIcontextPrivate *driContextPriv )
           * texture object data.
           */
          int i;
-
-        assert( is_empty_list( & rmesa->swapped ) );
+        
+        /* this assert is wrong. The default textures are always on swap list
+        assert( is_empty_list( & rmesa->swapped ) ); */
 
          for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
            driDestroyTextureHeap( rmesa->texture_heaps[ i ] );
index 3802deead98a3c229b87706b7c7411e6661f5ae3..9e00d7a35852812acd54ba45db51a971dde0a436 100644 (file)
@@ -615,7 +615,7 @@ struct r200_swtcl_info {
    GLuint vertex_size;
    GLuint vertex_stride_shift;
    GLuint vertex_format;
-   char *verts;
+   GLubyte *verts;
 
    /* Fallback rasterization functions
     */
index ea672162387bd2f04f2279fc80992984bf922ce1..480121a094d751e8fec19c0f2db0953f037e01ad 100644 (file)
@@ -320,7 +320,7 @@ static CARD32 r200GetLastFrame(r200ContextPtr rmesa)
    CARD32 frame;
 
    gp.param = RADEON_PARAM_LAST_FRAME;
-   gp.value = (int *)&frame;
+   gp.value = &frame;
    ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_GETPARAM,
                              &gp, sizeof(gp) );
    if ( ret ) {
@@ -404,7 +404,7 @@ void r200CopyBuffer( const __DRIdrawablePrivate *dPriv )
    r200ContextPtr rmesa;
    GLint nbox, i, ret;
    GLboolean   missed_target;
-   int64_t     ust;
+   uint64_t     ust;
 
    assert(dPriv);
    assert(dPriv->driContextPriv);
@@ -616,7 +616,7 @@ static void r200Clear( GLcontext *ctx, GLbitfield mask, GLboolean all,
       int clear;
 
       gp.param = RADEON_PARAM_LAST_CLEAR;
-      gp.value = (int *)&clear;
+      gp.value = &clear;
       ret = drmCommandWriteRead( rmesa->dri.fd,
                      DRM_RADEON_GETPARAM, &gp, sizeof(gp) );
 
index 6a436509a01c394a42a3aa6362c5f71550d90f9d..dd4025235b6559a122e5db5c67aee97927789a58 100644 (file)
@@ -446,7 +446,7 @@ static __inline void *r200AllocDmaLowVerts( r200ContextPtr rmesa,
 
 
    {
-      GLubyte *head = rmesa->dma.current.address + rmesa->dma.current.ptr;
+      char *head = rmesa->dma.current.address + rmesa->dma.current.ptr;
       rmesa->dma.current.ptr += bytes;
       rmesa->swtcl.numverts += nverts;
       return head;
@@ -1260,7 +1260,7 @@ void r200InitSwtcl( GLcontext *ctx )
    tnl->Driver.Render.ResetLineStipple = r200ResetLineStipple;
    tnl->Driver.Render.BuildVertices = r200BuildVertices;
 
-   rmesa->swtcl.verts = (char *)ALIGN_MALLOC( size * 16 * 4, 32 );
+   rmesa->swtcl.verts = (GLubyte *)ALIGN_MALLOC( size * 16 * 4, 32 );
    rmesa->swtcl.RenderIndex = ~0;
    rmesa->swtcl.render_primitive = GL_TRIANGLES;
    rmesa->swtcl.hw_primitive = 0;
index 994221d80cfe703ccf4296382a29dd44683f2e75..9869ad61963ec63ff3d710f6ba770bc4fe83fdd6 100644 (file)
@@ -102,33 +102,23 @@ static GLboolean discrete_prim[0x10] = {
 };
    
 
-#define LOCAL_VARS r200ContextPtr rmesa = R200_CONTEXT(ctx);rmesa = rmesa
-#define ELTS_VARS  GLushort *dest
+#define LOCAL_VARS r200ContextPtr rmesa = R200_CONTEXT(ctx)
+#define ELT_TYPE  GLushort
 
 #define ELT_INIT(prim, hw_prim) \
    r200TclPrimitive( ctx, prim, hw_prim | R200_VF_PRIM_WALK_IND )
 
-#define GET_ELTS() rmesa->tcl.Elts
+#define GET_MESA_ELTS() rmesa->tcl.Elts
 
 
-#define NEW_PRIMITIVE()  R200_NEWPRIM( rmesa )
-#define NEW_BUFFER()  r200RefillCurrentDmaRegion( rmesa )
-
 /* Don't really know how many elts will fit in what's left of cmdbuf,
  * as there is state to emit, etc:
  */
 
-#if 0
-#define GET_CURRENT_VB_MAX_ELTS() \
-   ((R200_CMD_BUF_SZ - (rmesa->store.cmd_used + 16)) / 2) 
-#define GET_SUBSEQUENT_VB_MAX_ELTS() ((R200_CMD_BUF_SZ - 16) / 2) 
-#else
 /* Testing on isosurf shows a maximum around here.  Don't know if it's
  * the card or driver or kernel module that is causing the behaviour.
  */
-#define GET_CURRENT_VB_MAX_ELTS() 300
-#define GET_SUBSEQUENT_VB_MAX_ELTS() 300
-#endif
+#define GET_MAX_HW_ELTS() 300
 
 #define RESET_STIPPLE() do {                   \
    R200_STATECHANGE( rmesa, lin );             \
@@ -147,32 +137,22 @@ static GLboolean discrete_prim[0x10] = {
 } while (0)
 
 
-/* How do you extend an existing primitive?
- */
-#define ALLOC_ELTS(nr)                                                 \
-do {                                                                   \
-   if (rmesa->dma.flush == r200FlushElts &&                            \
-       rmesa->store.cmd_used + nr*2 < R200_CMD_BUF_SZ) {               \
-                                                                       \
-      dest = (GLushort *)(rmesa->store.cmd_buf +                       \
-                         rmesa->store.cmd_used);                       \
-      rmesa->store.cmd_used += nr*2;                                   \
-   }                                                                   \
-   else {                                                              \
-      if (rmesa->dma.flush)                                            \
-        rmesa->dma.flush( rmesa );                                     \
-                                                                       \
-      r200EmitAOS( rmesa,                                              \
-                    rmesa->tcl.aos_components,                         \
-                    rmesa->tcl.nr_aos_components,                      \
-                    0 );                                               \
-                                                                       \
-      dest = r200AllocEltsOpenEnded( rmesa,                            \
-                                      rmesa->tcl.hw_primitive,         \
-                                      nr );                            \
-   }                                                                   \
-} while (0) 
+#define ALLOC_ELTS(nr) r200AllocElts( rmesa, nr )
 
+static GLushort *r200AllocElts( r200ContextPtr rmesa, GLuint nr ) 
+{
+   if (rmesa->dma.flush)
+      rmesa->dma.flush( rmesa );
+
+   r200EmitAOS( rmesa,
+               rmesa->tcl.aos_components,
+               rmesa->tcl.nr_aos_components, 0 );
+
+   return r200AllocEltsOpenEnded( rmesa, rmesa->tcl.hw_primitive, nr );
+}
+
+
+#define CLOSE_ELTS()  R200_NEWPRIM( rmesa )
 
 
 /* TODO: Try to extend existing primitive if both are identical,
@@ -217,17 +197,15 @@ static void EMIT_PRIM( GLcontext *ctx,
 
 #ifdef MESA_BIG_ENDIAN
 /* We could do without (most of) this ugliness if dest was always 32 bit word aligned... */
-#define EMIT_ELT(offset, x) do {                                \
+#define EMIT_ELT(dest, offset, x) do {                                \
         int off = offset + ( ( (GLuint)dest & 0x2 ) >> 1 );     \
         GLushort *des = (GLushort *)( (GLuint)dest & ~0x2 );    \
         (des)[ off + 1 - 2 * ( off & 1 ) ] = (GLushort)(x); } while (0)
 #else
-#define EMIT_ELT(offset, x) (dest)[offset] = (GLushort) (x)
+#define EMIT_ELT(dest, offset, x) (dest)[offset] = (GLushort) (x)
 #endif
-#define EMIT_TWO_ELTS(offset, x, y)  *(GLuint *)(dest+offset) = ((y)<<16)|(x);
-#define INCR_ELTS( nr ) dest += nr
-#define RELEASE_ELT_VERTS() \
-   r200ReleaseArrays( ctx, ~0 )
+
+#define EMIT_TWO_ELTS(dest, offset, x, y)  *(GLuint *)((dest)+offset) = ((y)<<16)|(x);
 
 
 
diff --git a/src/mesa/drivers/dri/radeon/Makefile.X11 b/src/mesa/drivers/dri/radeon/Makefile.X11
new file mode 100644 (file)
index 0000000..b73abe8
--- /dev/null
@@ -0,0 +1,154 @@
+# $Id: Makefile.X11,v 1.1 2003/08/22 20:11:45 brianp Exp $
+
+# 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
+
+ifeq ($(EMBEDDED),true)
+TARGET = radeon_es_dri.so
+DEFINES += \
+              -D_EMBEDDED \
+       -D_HAVE_SWRAST=0 \
+       -D_HAVE_SWTNL=0 \
+       -D_HAVE_SANITY=0 \
+       -D_HAVE_CODEGEN=0 \
+       -D_HAVE_LIGHTING=0 \
+       -D_HAVE_TEXGEN=0 \
+       -D_HAVE_USERCLIP=0 \
+       -DGLX_DIRECT_RENDERING
+else
+TARGET = radeon_dri.so
+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
+endif
+
+MESA_MODULES = $(TOP)/src/mesa/mesa.a
+
+MINIGLX_SOURCES = server/radeon_dri.c 
+
+DRIVER_SOURCES = radeon_context.c \
+                radeon_ioctl.c \
+                radeon_lock.c \
+                radeon_screen.c \
+                radeon_state.c \
+                radeon_state_init.c \
+                ../common/mm.c \
+                ../common/utils.c \
+                ../common/texmem.c \
+                ../common/vblank.c
+
+SUBSET_DRIVER_SOURCES = \
+               radeon_subset_bitmap.c \
+               radeon_subset_readpix.c \
+               radeon_subset_select.c \
+               radeon_subset_tex.c \
+               radeon_subset_vtx.c 
+
+FULL_DRIVER_SOURCES =  \
+                radeon_tex.c \
+                radeon_texmem.c \
+                radeon_texstate.c \
+                radeon_tcl.c \
+                radeon_swtcl.c \
+                radeon_span.c \
+                radeon_maos.c \
+                radeon_sanity.c \
+                radeon_compat.c \
+                radeon_vtxfmt.c \
+                radeon_vtxfmt_c.c \
+                radeon_vtxfmt_sse.c \
+                radeon_vtxfmt_x86.c 
+
+
+INCLUDES = $(MINIGLX_INCLUDES) \
+          $(SHARED_INCLUDES)
+
+
+ifeq ($(EMBEDDED),true)
+C_SOURCES = $(DRIVER_SOURCES) \
+           $(SUBSET_DRIVER_SOURCES) \
+           $(MINIGLX_SOURCES) 
+else
+C_SOURCES = $(DRIVER_SOURCES) \
+           $(FULL_DRIVER_SOURCES) \
+           $(MINIGLX_SOURCES) 
+endif
+
+
+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) 
+
+### 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 $(TARGET)
+
+$(TARGET):  $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile.X11
+       rm -f $@ && gcc -o $@ -shared $(OBJECTS) $(MESA_MODULES) $(WINOBJ) $(WINLIB) -lc -lm
+       rm -f $(TOP)/lib/$(TARGET) && \
+       install $(TARGET) $(TOP)/lib/$(TARGET)
+
+# 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 *~ *.so server/*.o
+
+
+include $(TOP)/Make-config
+
+include depend
diff --git a/src/mesa/drivers/dri/radeon/radeon_compat.c b/src/mesa/drivers/dri/radeon/radeon_compat.c
new file mode 100644 (file)
index 0000000..0c32641
--- /dev/null
@@ -0,0 +1,304 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 2002 ATI Technologies Inc., Ontario, Canada, and
+               Tungsten Graphics Inc., Austin, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#include "glheader.h"
+#include "imports.h"
+
+#include "radeon_context.h"
+#include "radeon_state.h"
+#include "radeon_ioctl.h"
+
+
+static struct { 
+       int start; 
+       int len; 
+       const char *name;
+} packet[RADEON_MAX_STATE_PACKETS] = {
+       { RADEON_PP_MISC,7,"RADEON_PP_MISC" },
+       { RADEON_PP_CNTL,3,"RADEON_PP_CNTL" },
+       { RADEON_RB3D_COLORPITCH,1,"RADEON_RB3D_COLORPITCH" },
+       { RADEON_RE_LINE_PATTERN,2,"RADEON_RE_LINE_PATTERN" },
+       { RADEON_SE_LINE_WIDTH,1,"RADEON_SE_LINE_WIDTH" },
+       { RADEON_PP_LUM_MATRIX,1,"RADEON_PP_LUM_MATRIX" },
+       { RADEON_PP_ROT_MATRIX_0,2,"RADEON_PP_ROT_MATRIX_0" },
+       { RADEON_RB3D_STENCILREFMASK,3,"RADEON_RB3D_STENCILREFMASK" },
+       { RADEON_SE_VPORT_XSCALE,6,"RADEON_SE_VPORT_XSCALE" },
+       { RADEON_SE_CNTL,2,"RADEON_SE_CNTL" },
+       { RADEON_SE_CNTL_STATUS,1,"RADEON_SE_CNTL_STATUS" },
+       { RADEON_RE_MISC,1,"RADEON_RE_MISC" },
+       { RADEON_PP_TXFILTER_0,6,"RADEON_PP_TXFILTER_0" },
+       { RADEON_PP_BORDER_COLOR_0,1,"RADEON_PP_BORDER_COLOR_0" },
+       { RADEON_PP_TXFILTER_1,6,"RADEON_PP_TXFILTER_1" },
+       { RADEON_PP_BORDER_COLOR_1,1,"RADEON_PP_BORDER_COLOR_1" },
+       { RADEON_PP_TXFILTER_2,6,"RADEON_PP_TXFILTER_2" },
+       { RADEON_PP_BORDER_COLOR_2,1,"RADEON_PP_BORDER_COLOR_2" },
+       { RADEON_SE_ZBIAS_FACTOR,2,"RADEON_SE_ZBIAS_FACTOR" },
+       { RADEON_SE_TCL_OUTPUT_VTX_FMT,11,"RADEON_SE_TCL_OUTPUT_VTX_FMT" },
+       { RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED,17,"RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED" },
+};
+
+
+static void radeonCompatEmitPacket( radeonContextPtr rmesa, 
+                                   struct radeon_state_atom *state )
+{
+   RADEONSAREAPrivPtr sarea = rmesa->sarea;
+   radeon_context_regs_t *ctx = &sarea->ContextState;
+   radeon_texture_regs_t *tex0 = &sarea->TexState[0];
+   radeon_texture_regs_t *tex1 = &sarea->TexState[1];
+   int i;
+   int *buf = state->cmd;
+
+   for ( i = 0 ; i < state->cmd_size ; ) {
+      drmRadeonCmdHeader *header = (drmRadeonCmdHeader *)&buf[i++];
+
+      if (RADEON_DEBUG & DEBUG_STATE)
+        fprintf(stderr, "%s %d: %s\n", __FUNCTION__, header->packet.packet_id,
+                packet[(int)header->packet.packet_id].name);
+
+      switch (header->packet.packet_id) {
+      case RADEON_EMIT_PP_MISC:
+        ctx->pp_misc = buf[i++]; 
+        ctx->pp_fog_color = buf[i++];
+        ctx->re_solid_color = buf[i++];
+        ctx->rb3d_blendcntl = buf[i++];
+        ctx->rb3d_depthoffset = buf[i++];
+        ctx->rb3d_depthpitch = buf[i++];
+        ctx->rb3d_zstencilcntl = buf[i++];
+        sarea->dirty |= RADEON_UPLOAD_CONTEXT;
+        break;
+      case RADEON_EMIT_PP_CNTL:
+        ctx->pp_cntl = buf[i++];
+        ctx->rb3d_cntl = buf[i++];
+        ctx->rb3d_coloroffset = buf[i++];
+        sarea->dirty |= RADEON_UPLOAD_CONTEXT;
+        break;
+      case RADEON_EMIT_RB3D_COLORPITCH:
+        ctx->rb3d_colorpitch = buf[i++];
+        sarea->dirty |= RADEON_UPLOAD_CONTEXT;
+        break;
+      case RADEON_EMIT_RE_LINE_PATTERN:
+        ctx->re_line_pattern = buf[i++];
+        ctx->re_line_state = buf[i++];
+        sarea->dirty |= RADEON_UPLOAD_LINE;
+        break;
+      case RADEON_EMIT_SE_LINE_WIDTH:
+        ctx->se_line_width = buf[i++];
+        sarea->dirty |= RADEON_UPLOAD_LINE;
+        break;
+      case RADEON_EMIT_PP_LUM_MATRIX:
+        ctx->pp_lum_matrix = buf[i++];
+        sarea->dirty |= RADEON_UPLOAD_BUMPMAP;
+        break;
+      case RADEON_EMIT_PP_ROT_MATRIX_0:
+        ctx->pp_rot_matrix_0 = buf[i++];
+        ctx->pp_rot_matrix_1 = buf[i++];
+        sarea->dirty |= RADEON_UPLOAD_BUMPMAP;
+        break;
+      case RADEON_EMIT_RB3D_STENCILREFMASK:
+        ctx->rb3d_stencilrefmask = buf[i++];
+        ctx->rb3d_ropcntl = buf[i++];
+        ctx->rb3d_planemask = buf[i++];
+        sarea->dirty |= RADEON_UPLOAD_MASKS;
+        break;
+      case RADEON_EMIT_SE_VPORT_XSCALE:
+        ctx->se_vport_xscale = buf[i++];
+        ctx->se_vport_xoffset = buf[i++];
+        ctx->se_vport_yscale = buf[i++];
+        ctx->se_vport_yoffset = buf[i++];
+        ctx->se_vport_zscale = buf[i++];
+        ctx->se_vport_zoffset = buf[i++];
+        sarea->dirty |= RADEON_UPLOAD_VIEWPORT;
+        break;
+      case RADEON_EMIT_SE_CNTL:
+        ctx->se_cntl = buf[i++];
+        ctx->se_coord_fmt = buf[i++];
+        sarea->dirty |= RADEON_UPLOAD_CONTEXT | RADEON_UPLOAD_VERTFMT;
+        break;
+      case RADEON_EMIT_SE_CNTL_STATUS:
+        ctx->se_cntl_status = buf[i++];
+        sarea->dirty |= RADEON_UPLOAD_SETUP;
+        break;
+      case RADEON_EMIT_RE_MISC:
+        ctx->re_misc = buf[i++];
+        sarea->dirty |= RADEON_UPLOAD_MISC;
+        break;
+      case RADEON_EMIT_PP_TXFILTER_0:
+        tex0->pp_txfilter = buf[i++];
+        tex0->pp_txformat = buf[i++];
+        tex0->pp_txoffset = buf[i++];
+        tex0->pp_txcblend = buf[i++];
+        tex0->pp_txablend = buf[i++];
+        tex0->pp_tfactor = buf[i++];
+        sarea->dirty |= RADEON_UPLOAD_TEX0;
+        break;
+      case RADEON_EMIT_PP_BORDER_COLOR_0:
+        tex0->pp_border_color = buf[i++];
+        sarea->dirty |= RADEON_UPLOAD_TEX0;
+        break;
+      case RADEON_EMIT_PP_TXFILTER_1:
+        tex1->pp_txfilter = buf[i++];
+        tex1->pp_txformat = buf[i++];
+        tex1->pp_txoffset = buf[i++];
+        tex1->pp_txcblend = buf[i++];
+        tex1->pp_txablend = buf[i++];
+        tex1->pp_tfactor = buf[i++];
+        sarea->dirty |= RADEON_UPLOAD_TEX1;
+        break;
+      case RADEON_EMIT_PP_BORDER_COLOR_1:
+        tex1->pp_border_color = buf[i++];
+        sarea->dirty |= RADEON_UPLOAD_TEX1;
+        break;
+
+      case RADEON_EMIT_SE_ZBIAS_FACTOR:
+        i++;
+        i++;
+        break;
+
+      case RADEON_EMIT_PP_TXFILTER_2:
+      case RADEON_EMIT_PP_BORDER_COLOR_2:
+      case RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT:
+      case RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED:
+      default:
+        /* These states aren't understood by radeon drm 1.1 */
+        fprintf(stderr, "Tried to emit unsupported state\n");
+        return;
+      }
+   }
+}
+
+
+
+static void radeonCompatEmitStateLocked( radeonContextPtr rmesa )
+{
+   struct radeon_state_atom *state, *tmp;
+
+   if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS))
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   if (rmesa->lost_context) {
+      if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS|DEBUG_IOCTL))
+        fprintf(stderr, "%s - lost context\n", __FUNCTION__); 
+
+      foreach_s( state, tmp, &(rmesa->hw.clean) ) 
+        move_to_tail(&(rmesa->hw.dirty), state );
+
+      rmesa->lost_context = 0;
+   }
+
+   foreach_s( state, tmp, &(rmesa->hw.dirty) ) {
+      if (!state->is_tcl)
+        radeonCompatEmitPacket( rmesa, state );
+      move_to_head( &(rmesa->hw.clean), state );
+   }
+}
+
+
+
+static void radeonCompatEmitPrimitiveLocked( radeonContextPtr rmesa,
+                                            GLuint hw_primitive,
+                                            GLuint nverts,
+                                            XF86DRIClipRectPtr pbox,
+                                            GLuint nbox )
+{
+   int i;
+
+   for ( i = 0 ; i < nbox ; ) {
+      int nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, nbox );
+      XF86DRIClipRectPtr b = rmesa->sarea->boxes;
+      drmRadeonVertex vtx;
+      
+      rmesa->sarea->dirty |= RADEON_UPLOAD_CLIPRECTS;
+      rmesa->sarea->nbox = nr - i;
+
+      for ( ; i < nr ; i++) 
+        *b++ = pbox[i];
+      
+      if (RADEON_DEBUG & DEBUG_IOCTL)
+        fprintf(stderr, 
+                "RadeonFlushVertexBuffer: prim %x buf %d verts %d "
+                "disc %d nbox %d\n",
+                hw_primitive, 
+                rmesa->dma.current.buf->buf->idx, 
+                nverts, 
+                nr == nbox,
+                rmesa->sarea->nbox );
+
+      vtx.prim = hw_primitive;
+      vtx.idx = rmesa->dma.current.buf->buf->idx;
+      vtx.count = nverts;
+      vtx.discard = (nr == nbox);      
+
+      drmCommandWrite( rmesa->dri.fd, 
+                      DRM_RADEON_VERTEX,
+                      &vtx, sizeof(vtx));
+   }
+}
+
+
+
+/* No 'start' for 1.1 vertices ioctl: only one vertex prim/buffer!  
+ */
+void radeonCompatEmitPrimitive( radeonContextPtr rmesa,
+                               GLuint vertex_format,
+                               GLuint hw_primitive,
+                               GLuint nrverts )
+{
+   if (RADEON_DEBUG & DEBUG_IOCTL)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   LOCK_HARDWARE( rmesa );
+
+   radeonCompatEmitStateLocked( rmesa );
+   rmesa->sarea->vc_format = vertex_format;
+   
+   if (rmesa->state.scissor.enabled) {
+      radeonCompatEmitPrimitiveLocked( rmesa, 
+                                      hw_primitive,
+                                      nrverts,
+                                      rmesa->state.scissor.pClipRects,
+                                      rmesa->state.scissor.numClipRects );
+   }
+   else {
+      radeonCompatEmitPrimitiveLocked( rmesa, 
+                                      hw_primitive,
+                                      nrverts,
+                                      rmesa->pClipRects,
+                                      rmesa->numClipRects );
+   }
+
+
+   UNLOCK_HARDWARE( rmesa );
+}
+
diff --git a/src/mesa/drivers/dri/radeon/radeon_context.c b/src/mesa/drivers/dri/radeon/radeon_context.c
new file mode 100644 (file)
index 0000000..835cecb
--- /dev/null
@@ -0,0 +1,598 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_context.c,v 1.7 2003/02/08 21:26:45 dawes Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Gareth Hughes <gareth@valinux.com>
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "glheader.h"
+#include "api_arrayelt.h"
+#include "context.h"
+#include "simple_list.h"
+#include "imports.h"
+#include "matrix.h"
+#include "extensions.h"
+
+#include "swrast/swrast.h"
+#include "swrast_setup/swrast_setup.h"
+#include "array_cache/acache.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_pipeline.h"
+
+#include "radeon_context.h"
+#include "radeon_ioctl.h"
+#include "radeon_state.h"
+#include "radeon_span.h"
+#include "radeon_tex.h"
+#include "radeon_swtcl.h"
+#include "radeon_tcl.h"
+#include "radeon_vtxfmt.h"
+#include "radeon_maos.h"
+
+#define DRIVER_DATE    "20030328"
+
+#include "vblank.h"
+#include "utils.h"
+#ifndef RADEON_DEBUG
+int RADEON_DEBUG = (0);
+#endif
+
+
+
+/* Return the width and height of the given buffer.
+ */
+static void radeonGetBufferSize( GLframebuffer *buffer,
+                                GLuint *width, GLuint *height )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   LOCK_HARDWARE( rmesa );
+   *width  = rmesa->dri.drawable->w;
+   *height = rmesa->dri.drawable->h;
+   UNLOCK_HARDWARE( rmesa );
+}
+
+/* Return various strings for glGetString().
+ */
+static const GLubyte *radeonGetString( GLcontext *ctx, GLenum name )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   static char buffer[128];
+   unsigned   offset;
+   GLuint agp_mode = rmesa->radeonScreen->IsPCI ? 0 :
+      rmesa->radeonScreen->AGPMode;
+
+   switch ( name ) {
+   case GL_VENDOR:
+      return (GLubyte *)"Tungsten Graphics, Inc.";
+
+   case GL_RENDERER:
+      offset = driGetRendererString( buffer, "Radeon", DRIVER_DATE,
+                                    agp_mode );
+
+      sprintf( & buffer[ offset ], "%s %sTCL",
+              ( rmesa->dri.drmMinor < 3 ) ? " DRM-COMPAT" : "",
+              !(rmesa->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE)
+              ? "" : "NO-" );
+
+      return (GLubyte *)buffer;
+
+   default:
+      return NULL;
+   }
+}
+
+
+/* Extension strings exported by the R100 driver.
+ */
+static const char * const card_extensions[] =
+{
+    "GL_ARB_multisample",
+    "GL_ARB_multitexture",
+    "GL_ARB_texture_border_clamp",
+    "GL_ARB_texture_compression",
+    "GL_ARB_texture_env_add",
+    "GL_ARB_texture_env_combine",
+    "GL_ARB_texture_env_dot3",
+    "GL_ARB_texture_mirrored_repeat",
+    "GL_EXT_blend_logic_op",
+    "GL_EXT_blend_subtract",
+    "GL_EXT_secondary_color",
+    "GL_EXT_texture_edge_clamp",
+    "GL_EXT_texture_env_add",
+    "GL_EXT_texture_env_combine",
+    "GL_EXT_texture_env_dot3",
+    "GL_EXT_texture_filter_anisotropic",
+    "GL_EXT_texture_lod_bias",
+    "GL_ATI_texture_env_combine3",
+    "GL_ATI_texture_mirror_once",
+    "GL_IBM_texture_mirrored_repeat",
+    "GL_MESA_ycbcr_texture",
+    "GL_NV_blend_square",
+    "GL_SGIS_generate_mipmap",
+    "GL_SGIS_texture_border_clamp",
+    "GL_SGIS_texture_edge_clamp",
+    NULL
+};
+
+extern const struct gl_pipeline_stage _radeon_texrect_stage;
+extern const struct gl_pipeline_stage _radeon_render_stage;
+extern const struct gl_pipeline_stage _radeon_tcl_stage;
+
+static const struct gl_pipeline_stage *radeon_pipeline[] = {
+
+   /* Try and go straight to t&l
+    */
+   &_radeon_tcl_stage,  
+
+   /* Catch any t&l fallbacks
+    */
+   &_tnl_vertex_transform_stage,
+   &_tnl_normal_transform_stage,
+   &_tnl_lighting_stage,
+   &_tnl_fog_coordinate_stage,
+   &_tnl_texgen_stage,
+   &_tnl_texture_transform_stage,
+
+   /* Scale texture rectangle to 0..1.
+    */
+   &_radeon_texrect_stage,
+
+   &_radeon_render_stage,
+   &_tnl_render_stage,         /* FALLBACK:  */
+   0,
+};
+
+
+
+/* Initialize the driver's misc functions.
+ */
+static void radeonInitDriverFuncs( GLcontext *ctx )
+{
+    ctx->Driver.GetBufferSize          = radeonGetBufferSize;
+    ctx->Driver.ResizeBuffers           = _swrast_alloc_buffers;
+    ctx->Driver.GetString              = radeonGetString;
+
+    ctx->Driver.Error                  = NULL;
+    ctx->Driver.DrawPixels             = NULL;
+    ctx->Driver.Bitmap                 = NULL;
+}
+
+static const struct dri_debug_control debug_control[] =
+{
+    { "fall",  DEBUG_FALLBACKS },
+    { "tex",   DEBUG_TEXTURE },
+    { "ioctl", DEBUG_IOCTL },
+    { "prim",  DEBUG_PRIMS },
+    { "vert",  DEBUG_VERTS },
+    { "state", DEBUG_STATE },
+    { "code",  DEBUG_CODEGEN },
+    { "vfmt",  DEBUG_VFMT },
+    { "vtxf",  DEBUG_VFMT },
+    { "verb",  DEBUG_VERBOSE },
+    { "dri",   DEBUG_DRI },
+    { "dma",   DEBUG_DMA },
+    { "san",   DEBUG_SANITY },
+    { NULL,    0 }
+};
+
+
+static int
+get_ust_nop( uint64_t * ust )
+{
+   *ust = 1;
+   return 0;
+}
+
+
+/* Create the device specific context.
+ */
+GLboolean
+radeonCreateContext( const __GLcontextModes *glVisual,
+                     __DRIcontextPrivate *driContextPriv,
+                     void *sharedContextPrivate)
+{
+   __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
+   radeonScreenPtr screen = (radeonScreenPtr)(sPriv->private);
+   radeonContextPtr rmesa;
+   GLcontext *ctx, *shareCtx;
+   int i;
+
+   assert(glVisual);
+   assert(driContextPriv);
+   assert(screen);
+
+   /* Allocate the Radeon context */
+   rmesa = (radeonContextPtr) CALLOC( sizeof(*rmesa) );
+   if ( !rmesa )
+      return GL_FALSE;
+
+   /* Allocate the Mesa context */
+   if (sharedContextPrivate)
+      shareCtx = ((radeonContextPtr) sharedContextPrivate)->glCtx;
+   else
+      shareCtx = NULL;
+   rmesa->glCtx = _mesa_create_context(glVisual, shareCtx, (void *) rmesa, GL_TRUE);
+   if (!rmesa->glCtx) {
+      FREE(rmesa);
+      return GL_FALSE;
+   }
+   driContextPriv->driverPrivate = rmesa;
+
+   /* Init radeon context data */
+   rmesa->dri.context = driContextPriv;
+   rmesa->dri.screen = sPriv;
+   rmesa->dri.drawable = NULL; /* Set by XMesaMakeCurrent */
+   rmesa->dri.hwContext = driContextPriv->hHWContext;
+   rmesa->dri.hwLock = &sPriv->pSAREA->lock;
+   rmesa->dri.fd = sPriv->fd;
+
+   /* If we don't have 1.3, fallback to the 1.1 interfaces.
+    */
+   if (getenv("RADEON_COMPAT") || sPriv->drmMinor < 3 ) 
+      rmesa->dri.drmMinor = 1;
+   else
+      rmesa->dri.drmMinor = sPriv->drmMinor;
+
+   rmesa->radeonScreen = screen;
+   rmesa->sarea = (RADEONSAREAPrivPtr)((GLubyte *)sPriv->pSAREA +
+                                      screen->sarea_priv_offset);
+
+
+   rmesa->dma.buf0_address = rmesa->radeonScreen->buffers->list[0].address;
+
+   (void) memset( rmesa->texture_heaps, 0, sizeof( rmesa->texture_heaps ) );
+   make_empty_list( & rmesa->swapped );
+
+   rmesa->nr_heaps = screen->numTexHeaps;
+   for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
+      rmesa->texture_heaps[i] = driCreateTextureHeap( i, rmesa,
+           screen->texSize[i],
+           12,
+           RADEON_NR_TEX_REGIONS,
+           rmesa->sarea->texList[i],
+           & rmesa->sarea->texAge[i],
+           & rmesa->swapped,
+           sizeof( radeonTexObj ),
+           (destroy_texture_object_t *) radeonDestroyTexObj );
+
+      driSetTextureSwapCounterLocation( rmesa->texture_heaps[i],
+                                       & rmesa->c_textureSwaps );
+   }
+
+   rmesa->swtcl.RenderIndex = ~0;
+   rmesa->lost_context = 1;
+
+   /* Set the maximum texture size small enough that we can guarentee that
+    * all texture units can bind a maximal texture and have them both in
+    * texturable memory at once.
+    */
+
+   ctx = rmesa->glCtx;
+   ctx->Const.MaxTextureUnits = 2;
+
+   driCalculateMaxTextureLevels( rmesa->texture_heaps,
+                                rmesa->nr_heaps,
+                                & ctx->Const,
+                                4,
+                                11, /* max 2D texture size is 2048x2048 */
+                                0,  /* 3D textures unsupported. */
+                                0,  /* cube textures unsupported. */
+                                11, /* max rect texture size is 2048x2048. */
+                                12,
+                                GL_FALSE );
+
+   ctx->Const.MaxTextureMaxAnisotropy = 16.0;
+
+   /* No wide points.
+    */
+   ctx->Const.MinPointSize = 1.0;
+   ctx->Const.MinPointSizeAA = 1.0;
+   ctx->Const.MaxPointSize = 1.0;
+   ctx->Const.MaxPointSizeAA = 1.0;
+
+   ctx->Const.MinLineWidth = 1.0;
+   ctx->Const.MinLineWidthAA = 1.0;
+   ctx->Const.MaxLineWidth = 10.0;
+   ctx->Const.MaxLineWidthAA = 10.0;
+   ctx->Const.LineWidthGranularity = 0.0625;
+
+   /* Set maxlocksize (and hence vb size) small enough to avoid
+    * fallbacks in radeon_tcl.c.  ie. guarentee that all vertices can
+    * fit in a single dma buffer for indexed rendering of quad strips,
+    * etc.
+    */
+   ctx->Const.MaxArrayLockSize = 
+      MIN2( ctx->Const.MaxArrayLockSize, 
+           RADEON_BUFFER_SIZE / RADEON_MAX_TCL_VERTSIZE ); 
+
+   rmesa->boxes = (getenv("LIBGL_PERFORMANCE_BOXES") != NULL);
+
+   /* Initialize the software rasterizer and helper modules.
+    */
+   _swrast_CreateContext( ctx );
+   _ac_CreateContext( ctx );
+   _tnl_CreateContext( ctx );
+   _swsetup_CreateContext( ctx );
+   _ae_create_context( ctx );
+
+   /* Install the customized pipeline:
+    */
+   _tnl_destroy_pipeline( ctx );
+   _tnl_install_pipeline( ctx, radeon_pipeline );
+   ctx->Driver.FlushVertices = radeonFlushVertices;
+
+   /* Try and keep materials and vertices separate:
+    */
+   _tnl_isolate_materials( ctx, GL_TRUE );
+
+
+/*     _mesa_allow_light_in_model( ctx, GL_FALSE ); */
+
+   /* Try and keep materials and vertices separate:
+    */
+   _tnl_isolate_materials( ctx, GL_TRUE );
+
+
+   /* Configure swrast to match hardware characteristics:
+    */
+   _swrast_allow_pixel_fog( ctx, GL_FALSE );
+   _swrast_allow_vertex_fog( ctx, GL_TRUE );
+
+
+   _math_matrix_ctr( &rmesa->TexGenMatrix[0] );
+   _math_matrix_ctr( &rmesa->TexGenMatrix[1] );
+   _math_matrix_ctr( &rmesa->tmpmat );
+   _math_matrix_set_identity( &rmesa->TexGenMatrix[0] );
+   _math_matrix_set_identity( &rmesa->TexGenMatrix[1] );
+   _math_matrix_set_identity( &rmesa->tmpmat );
+
+   driInitExtensions( ctx, card_extensions, GL_TRUE );
+
+   if (rmesa->dri.drmMinor >= 9)
+      _mesa_enable_extension( ctx, "GL_NV_texture_rectangle");
+
+   radeonInitDriverFuncs( ctx );
+   radeonInitIoctlFuncs( ctx );
+   radeonInitStateFuncs( ctx );
+   radeonInitSpanFuncs( ctx );
+   radeonInitTextureFuncs( ctx );
+   radeonInitState( rmesa );
+   radeonInitSwtcl( ctx );
+
+   rmesa->iw.irq_seq = -1;
+   rmesa->irqsEmitted = 0;
+   rmesa->do_irqs = (rmesa->radeonScreen->irq && !getenv("RADEON_NO_IRQS"));
+
+   rmesa->do_usleeps = !getenv("RADEON_NO_USLEEPS");
+
+   rmesa->vblank_flags = (rmesa->do_irqs)
+       ? driGetDefaultVBlankFlags() : VBLANK_FLAG_NO_IRQ;
+
+#ifndef _SOLO
+   rmesa->get_ust = (PFNGLXGETUSTPROC) glXGetProcAddress( "__glXGetUST" );
+   if ( rmesa->get_ust == NULL ) 
+#endif
+   {
+      rmesa->get_ust = get_ust_nop;
+   }
+
+   (*rmesa->get_ust)( & rmesa->swap_ust );
+
+
+#if DO_DEBUG
+   RADEON_DEBUG = driParseDebugString( getenv( "RADEON_DEBUG" ),
+                                      debug_control );
+#endif
+
+   if (getenv("RADEON_NO_RAST")) {
+      fprintf(stderr, "disabling 3D acceleration\n");
+      FALLBACK(rmesa, RADEON_FALLBACK_DISABLE, 1); 
+   }
+   else if (getenv("RADEON_TCL_FORCE_ENABLE")) {
+      fprintf(stderr, "Enabling TCL support...  this will probably crash\n");
+      fprintf(stderr, "         your card if it isn't capable of TCL!\n");
+      rmesa->radeonScreen->chipset |= RADEON_CHIPSET_TCL;
+   } else if (getenv("RADEON_TCL_FORCE_DISABLE") ||
+           rmesa->dri.drmMinor < 3 ||
+           !(rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL)) {
+      rmesa->radeonScreen->chipset &= ~RADEON_CHIPSET_TCL;
+      fprintf(stderr, "disabling TCL support\n");
+      TCL_FALLBACK(rmesa->glCtx, RADEON_TCL_FALLBACK_TCL_DISABLE, 1); 
+   }
+
+   if (rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL) {
+      if (!getenv("RADEON_NO_VTXFMT"))
+        radeonVtxfmtInit( ctx );
+
+      _tnl_need_dlist_norm_lengths( ctx, GL_FALSE );
+   }
+   return GL_TRUE;
+}
+
+
+/* Destroy the device specific context.
+ */
+/* Destroy the Mesa and driver specific context data.
+ */
+void radeonDestroyContext( __DRIcontextPrivate *driContextPriv )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = (radeonContextPtr) driContextPriv->driverPrivate;
+   radeonContextPtr current = ctx ? RADEON_CONTEXT(ctx) : NULL;
+
+   /* check if we're deleting the currently bound context */
+   if (rmesa == current) {
+      RADEON_FIREVERTICES( rmesa );
+      _mesa_make_current2(NULL, NULL, NULL);
+   }
+
+   /* Free radeon context resources */
+   assert(rmesa); /* should never be null */
+   if ( rmesa ) {
+      GLboolean   release_texture_heaps;
+
+
+      release_texture_heaps = (rmesa->glCtx->Shared->RefCount == 1);
+      _swsetup_DestroyContext( rmesa->glCtx );
+      _tnl_DestroyContext( rmesa->glCtx );
+      _ac_DestroyContext( rmesa->glCtx );
+      _swrast_DestroyContext( rmesa->glCtx );
+
+      radeonDestroySwtcl( rmesa->glCtx );
+      radeonReleaseArrays( rmesa->glCtx, ~0 );
+      if (rmesa->dma.current.buf) {
+        radeonReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ );
+        radeonFlushCmdBuf( rmesa, __FUNCTION__ );
+      }
+
+      if (!rmesa->TclFallback & RADEON_TCL_FALLBACK_TCL_DISABLE)
+        if (!getenv("RADEON_NO_VTXFMT"))
+           radeonVtxfmtDestroy( rmesa->glCtx );
+
+      /* free the Mesa context */
+      rmesa->glCtx->DriverCtx = NULL;
+      _mesa_destroy_context( rmesa->glCtx );
+
+      if (rmesa->state.scissor.pClipRects) {
+        FREE(rmesa->state.scissor.pClipRects);
+        rmesa->state.scissor.pClipRects = 0;
+      }
+
+      if ( release_texture_heaps ) {
+         /* This share group is about to go away, free our private
+          * texture object data.
+          */
+         int i;
+
+        /* this assert is not correct, default textures are always on swap list
+        assert( is_empty_list( & rmesa->swapped ) ); */
+
+         for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
+           driDestroyTextureHeap( rmesa->texture_heaps[ i ] );
+           rmesa->texture_heaps[ i ] = NULL;
+         }
+      }
+
+      FREE( rmesa );
+   }
+}
+
+
+
+
+void
+radeonSwapBuffers( __DRIdrawablePrivate *dPriv )
+{
+
+   if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
+      radeonContextPtr rmesa;
+      GLcontext *ctx;
+      rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
+      ctx = rmesa->glCtx;
+      if (ctx->Visual.doubleBufferMode) {
+         _mesa_notifySwapBuffers( ctx );  /* flush pending rendering comands */
+
+         if ( rmesa->doPageFlip ) {
+            radeonPageFlip( dPriv );
+         }
+         else {
+            radeonCopyBuffer( dPriv );
+         }
+      }
+   }
+   else {
+      /* XXX this shouldn't be an error but we can't handle it for now */
+      _mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
+   }
+}
+
+
+/* Force the context `c' to be the current context and associate with it
+ * buffer `b'.
+ */
+GLboolean
+radeonMakeCurrent( __DRIcontextPrivate *driContextPriv,
+                   __DRIdrawablePrivate *driDrawPriv,
+                   __DRIdrawablePrivate *driReadPriv )
+{
+   if ( driContextPriv ) {
+      radeonContextPtr newCtx = 
+        (radeonContextPtr) driContextPriv->driverPrivate;
+
+      if (RADEON_DEBUG & DEBUG_DRI)
+        fprintf(stderr, "%s ctx %p\n", __FUNCTION__, newCtx->glCtx);
+
+      if ( newCtx->dri.drawable != driDrawPriv ) {
+        newCtx->dri.drawable = driDrawPriv;
+        radeonUpdateWindow( newCtx->glCtx );
+        radeonUpdateViewportOffset( newCtx->glCtx );
+      }
+
+      _mesa_make_current2( newCtx->glCtx,
+                          (GLframebuffer *) driDrawPriv->driverPrivate,
+                          (GLframebuffer *) driReadPriv->driverPrivate );
+
+      if ( !newCtx->glCtx->Viewport.Width ) {
+        _mesa_set_viewport( newCtx->glCtx, 0, 0,
+                            driDrawPriv->w, driDrawPriv->h );
+      }
+
+      if (newCtx->vb.enabled)
+        radeonVtxfmtMakeCurrent( newCtx->glCtx );
+
+   } else {
+      if (RADEON_DEBUG & DEBUG_DRI)
+        fprintf(stderr, "%s ctx is null\n", __FUNCTION__);
+      _mesa_make_current( 0, 0 );
+   }
+
+   if (RADEON_DEBUG & DEBUG_DRI)
+      fprintf(stderr, "End %s\n", __FUNCTION__);
+   return GL_TRUE;
+}
+
+/* Force the context `c' to be unbound from its buffer.
+ */
+GLboolean
+radeonUnbindContext( __DRIcontextPrivate *driContextPriv )
+{
+   radeonContextPtr rmesa = (radeonContextPtr) driContextPriv->driverPrivate;
+
+   if (RADEON_DEBUG & DEBUG_DRI)
+      fprintf(stderr, "%s ctx %p\n", __FUNCTION__, rmesa->glCtx);
+
+   return GL_TRUE;
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_context.h b/src/mesa/drivers/dri/radeon/radeon_context.h
new file mode 100644 (file)
index 0000000..5f1f965
--- /dev/null
@@ -0,0 +1,839 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_context.h,v 1.6 2002/12/16 16:18:58 dawes Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Gareth Hughes <gareth@valinux.com>
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef __RADEON_CONTEXT_H__
+#define __RADEON_CONTEXT_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include <inttypes.h>
+#include "dri_util.h"
+#include "radeon_common.h"
+#include "texmem.h"
+
+#include "macros.h"
+#include "mtypes.h"
+#include "colormac.h"
+
+struct radeon_context;
+typedef struct radeon_context radeonContextRec;
+typedef struct radeon_context *radeonContextPtr;
+
+#include "radeon_lock.h"
+#include "radeon_screen.h"
+#include "mm.h"
+
+/* Flags for software fallback cases */
+/* See correponding strings in radeon_swtcl.c */
+#define RADEON_FALLBACK_TEXTURE                0x0001
+#define RADEON_FALLBACK_DRAW_BUFFER    0x0002
+#define RADEON_FALLBACK_STENCIL                0x0004
+#define RADEON_FALLBACK_RENDER_MODE    0x0008
+#define RADEON_FALLBACK_BLEND_EQ       0x0010
+#define RADEON_FALLBACK_BLEND_FUNC     0x0020
+#define RADEON_FALLBACK_DISABLE        0x0040
+#define RADEON_FALLBACK_BORDER_MODE    0x0080
+
+/* The blit width for texture uploads
+ */
+#define BLIT_WIDTH_BYTES 1024
+
+/* Use the templated vertex format:
+ */
+#define COLOR_IS_RGBA
+#define TAG(x) radeon##x
+#include "tnl_dd/t_dd_vertex.h"
+#undef TAG
+
+typedef void (*radeon_tri_func)( radeonContextPtr,
+                                radeonVertex *,
+                                radeonVertex *,
+                                radeonVertex * );
+
+typedef void (*radeon_line_func)( radeonContextPtr,
+                                 radeonVertex *,
+                                 radeonVertex * );
+
+typedef void (*radeon_point_func)( radeonContextPtr,
+                                  radeonVertex * );
+
+
+struct radeon_colorbuffer_state {
+   GLuint clear;
+   GLint drawOffset, drawPitch;
+};
+
+
+struct radeon_depthbuffer_state {
+   GLuint clear;
+   GLfloat scale;
+};
+
+struct radeon_pixel_state {
+   GLint readOffset, readPitch;
+};
+
+struct radeon_scissor_state {
+   XF86DRIClipRectRec rect;
+   GLboolean enabled;
+
+   GLuint numClipRects;                        /* Cliprects active */
+   GLuint numAllocedClipRects;         /* Cliprects available */
+   XF86DRIClipRectPtr pClipRects;
+};
+
+struct radeon_stencilbuffer_state {
+   GLboolean hwBuffer;
+   GLuint clear;                       /* rb3d_stencilrefmask value */
+};
+
+struct radeon_stipple_state {
+   GLuint mask[32];
+};
+
+
+
+#define TEX_0   0x1
+#define TEX_1   0x2
+#define TEX_ALL 0x3
+
+typedef struct radeon_tex_obj radeonTexObj, *radeonTexObjPtr;
+
+/* Texture object in locally shared texture space.
+ */
+struct radeon_tex_obj {
+   driTextureObject   base;
+
+   GLuint bufAddr;                     /* Offset to start of locally
+                                          shared texture block */
+
+   GLuint dirty_state;                 /* Flags (1 per texunit) for
+                                          whether or not this texobj
+                                          has dirty hardware state
+                                          (pp_*) that needs to be
+                                          brought into the
+                                          texunit. */
+
+   drmRadeonTexImage image[6][RADEON_MAX_TEXTURE_LEVELS];
+                                       /* Six, for the cube faces */
+
+   GLuint pp_txfilter;                 /* hardware register values */
+   GLuint pp_txformat;
+   GLuint pp_txoffset;                 /* Image location in texmem.
+                                          All cube faces follow. */
+   GLuint pp_txsize;                   /* npot only */
+   GLuint pp_txpitch;                  /* npot only */
+   GLuint pp_border_color;
+   GLuint pp_cubic_faces;              /* cube face 1,2,3,4 log2 sizes */
+
+   GLboolean  border_fallback;
+};
+
+
+struct radeon_texture_env_state {
+   radeonTexObjPtr texobj;
+   GLenum format;
+   GLenum envMode;
+};
+
+struct radeon_texture_state {
+   struct radeon_texture_env_state unit[RADEON_MAX_TEXTURE_UNITS];
+};
+
+
+struct radeon_state_atom {
+   struct radeon_state_atom *next, *prev;
+   const char *name;                    /* for debug */
+   int cmd_size;                        /* size in bytes */
+   GLuint is_tcl;
+   int *cmd;                            /* one or more cmd's */
+   int *lastcmd;                        /* one or more cmd's */
+   GLboolean (*check)( GLcontext * );    /* is this state active? */
+};
+   
+
+
+/* Trying to keep these relatively short as the variables are becoming
+ * extravagently long.  Drop the driver name prefix off the front of
+ * everything - I think we know which driver we're in by now, and keep the
+ * prefix to 3 letters unless absolutely impossible.  
+ */
+
+#define CTX_CMD_0             0
+#define CTX_PP_MISC           1
+#define CTX_PP_FOG_COLOR      2
+#define CTX_RE_SOLID_COLOR    3
+#define CTX_RB3D_BLENDCNTL    4
+#define CTX_RB3D_DEPTHOFFSET  5
+#define CTX_RB3D_DEPTHPITCH   6
+#define CTX_RB3D_ZSTENCILCNTL 7
+#define CTX_CMD_1             8
+#define CTX_PP_CNTL           9
+#define CTX_RB3D_CNTL         10
+#define CTX_RB3D_COLOROFFSET  11
+#define CTX_CMD_2             12
+#define CTX_RB3D_COLORPITCH   13
+#define CTX_STATE_SIZE        14
+
+#define SET_CMD_0               0
+#define SET_SE_CNTL             1
+#define SET_SE_COORDFMT         2
+#define SET_CMD_1               3
+#define SET_SE_CNTL_STATUS      4
+#define SET_STATE_SIZE          5
+
+#define LIN_CMD_0               0
+#define LIN_RE_LINE_PATTERN     1
+#define LIN_RE_LINE_STATE       2
+#define LIN_CMD_1               3
+#define LIN_SE_LINE_WIDTH       4
+#define LIN_STATE_SIZE          5
+
+#define MSK_CMD_0               0
+#define MSK_RB3D_STENCILREFMASK 1
+#define MSK_RB3D_ROPCNTL        2
+#define MSK_RB3D_PLANEMASK      3
+#define MSK_STATE_SIZE          4
+
+#define VPT_CMD_0           0
+#define VPT_SE_VPORT_XSCALE          1
+#define VPT_SE_VPORT_XOFFSET         2
+#define VPT_SE_VPORT_YSCALE          3
+#define VPT_SE_VPORT_YOFFSET         4
+#define VPT_SE_VPORT_ZSCALE          5
+#define VPT_SE_VPORT_ZOFFSET         6
+#define VPT_STATE_SIZE      7
+
+#define MSC_CMD_0               0
+#define MSC_RE_MISC             1
+#define MSC_STATE_SIZE          2
+
+#define TEX_CMD_0                   0
+#define TEX_PP_TXFILTER             1
+#define TEX_PP_TXFORMAT             2
+#define TEX_PP_TXOFFSET             3
+#define TEX_PP_TXCBLEND             4
+#define TEX_PP_TXABLEND             5
+#define TEX_PP_TFACTOR              6
+#define TEX_CMD_1                   7
+#define TEX_PP_BORDER_COLOR         8
+#define TEX_STATE_SIZE              9
+
+#define TXR_CMD_0                   0 /* rectangle textures */
+#define TXR_PP_TEX_SIZE             1 /* 0x1d04, 0x1d0c for NPOT! */
+#define TXR_PP_TEX_PITCH            2 /* 0x1d08, 0x1d10 for NPOT! */
+#define TXR_STATE_SIZE              3
+
+#define ZBS_CMD_0              0
+#define ZBS_SE_ZBIAS_FACTOR             1
+#define ZBS_SE_ZBIAS_CONSTANT           2
+#define ZBS_STATE_SIZE         3
+
+#define TCL_CMD_0                        0
+#define TCL_OUTPUT_VTXFMT         1
+#define TCL_OUTPUT_VTXSEL         2
+#define TCL_MATRIX_SELECT_0       3
+#define TCL_MATRIX_SELECT_1       4
+#define TCL_UCP_VERT_BLEND_CTL    5
+#define TCL_TEXTURE_PROC_CTL      6
+#define TCL_LIGHT_MODEL_CTL       7
+#define TCL_PER_LIGHT_CTL_0       8
+#define TCL_PER_LIGHT_CTL_1       9
+#define TCL_PER_LIGHT_CTL_2       10
+#define TCL_PER_LIGHT_CTL_3       11
+#define TCL_STATE_SIZE                   12
+
+#define MTL_CMD_0            0 
+#define MTL_EMMISSIVE_RED    1 
+#define MTL_EMMISSIVE_GREEN  2 
+#define MTL_EMMISSIVE_BLUE   3 
+#define MTL_EMMISSIVE_ALPHA  4 
+#define MTL_AMBIENT_RED      5
+#define MTL_AMBIENT_GREEN    6
+#define MTL_AMBIENT_BLUE     7
+#define MTL_AMBIENT_ALPHA    8
+#define MTL_DIFFUSE_RED      9
+#define MTL_DIFFUSE_GREEN    10
+#define MTL_DIFFUSE_BLUE     11
+#define MTL_DIFFUSE_ALPHA    12
+#define MTL_SPECULAR_RED     13
+#define MTL_SPECULAR_GREEN   14
+#define MTL_SPECULAR_BLUE    15
+#define MTL_SPECULAR_ALPHA   16
+#define MTL_SHININESS        17
+#define MTL_STATE_SIZE       18
+
+#define VTX_CMD_0              0
+#define VTX_SE_COORD_FMT       1
+#define VTX_STATE_SIZE         2
+
+#define MAT_CMD_0              0
+#define MAT_ELT_0              1
+#define MAT_STATE_SIZE         17
+
+#define GRD_CMD_0                  0
+#define GRD_VERT_GUARD_CLIP_ADJ    1
+#define GRD_VERT_GUARD_DISCARD_ADJ 2
+#define GRD_HORZ_GUARD_CLIP_ADJ    3
+#define GRD_HORZ_GUARD_DISCARD_ADJ 4
+#define GRD_STATE_SIZE             5
+
+/* position changes frequently when lighting in modelpos - separate
+ * out to new state item?  
+ */
+#define LIT_CMD_0                  0
+#define LIT_AMBIENT_RED            1
+#define LIT_AMBIENT_GREEN          2
+#define LIT_AMBIENT_BLUE           3
+#define LIT_AMBIENT_ALPHA          4
+#define LIT_DIFFUSE_RED            5
+#define LIT_DIFFUSE_GREEN          6
+#define LIT_DIFFUSE_BLUE           7
+#define LIT_DIFFUSE_ALPHA          8
+#define LIT_SPECULAR_RED           9
+#define LIT_SPECULAR_GREEN         10
+#define LIT_SPECULAR_BLUE          11
+#define LIT_SPECULAR_ALPHA         12
+#define LIT_POSITION_X             13
+#define LIT_POSITION_Y             14
+#define LIT_POSITION_Z             15
+#define LIT_POSITION_W             16
+#define LIT_DIRECTION_X            17
+#define LIT_DIRECTION_Y            18
+#define LIT_DIRECTION_Z            19
+#define LIT_DIRECTION_W            20
+#define LIT_ATTEN_CONST            21
+#define LIT_ATTEN_LINEAR           22
+#define LIT_ATTEN_QUADRATIC        23
+#define LIT_ATTEN_XXX              24
+#define LIT_CMD_1                  25
+#define LIT_SPOT_DCD               26
+#define LIT_SPOT_EXPONENT          27
+#define LIT_SPOT_CUTOFF            28
+#define LIT_SPECULAR_THRESH        29
+#define LIT_RANGE_CUTOFF           30 /* ? */
+#define LIT_RANGE_ATTEN            31 /* ? */
+#define LIT_STATE_SIZE             32
+
+/* Fog
+ */
+#define FOG_CMD_0      0
+#define FOG_R          1
+#define FOG_C          2
+#define FOG_D          3
+#define FOG_PAD        4
+#define FOG_STATE_SIZE 5
+
+/* UCP
+ */
+#define UCP_CMD_0      0
+#define UCP_X          1
+#define UCP_Y          2
+#define UCP_Z          3
+#define UCP_W          4
+#define UCP_STATE_SIZE 5
+
+/* GLT - Global ambient
+ */
+#define GLT_CMD_0      0
+#define GLT_RED        1
+#define GLT_GREEN      2
+#define GLT_BLUE       3
+#define GLT_ALPHA      4
+#define GLT_STATE_SIZE 5
+
+/* EYE
+ */
+#define EYE_CMD_0          0
+#define EYE_X              1
+#define EYE_Y              2
+#define EYE_Z              3
+#define EYE_RESCALE_FACTOR 4
+#define EYE_STATE_SIZE     5
+
+#define SHN_CMD_0          0
+#define SHN_SHININESS      1
+#define SHN_STATE_SIZE     2
+
+
+
+
+
+struct radeon_hw_state {
+   /* All state should be on one of these lists:
+    */
+   struct radeon_state_atom dirty; /* dirty list head placeholder */
+   struct radeon_state_atom clean; /* clean list head placeholder */
+
+   /* Hardware state, stored as cmdbuf commands:  
+    *   -- Need to doublebuffer for
+    *           - reviving state after loss of context
+    *           - eliding noop statechange loops? (except line stipple count)
+    */
+   struct radeon_state_atom ctx;
+   struct radeon_state_atom set;
+   struct radeon_state_atom lin;
+   struct radeon_state_atom msk;
+   struct radeon_state_atom vpt;
+   struct radeon_state_atom tcl;
+   struct radeon_state_atom msc;
+   struct radeon_state_atom tex[2];
+   struct radeon_state_atom zbs;
+   struct radeon_state_atom mtl; 
+   struct radeon_state_atom mat[5]; 
+   struct radeon_state_atom lit[8]; /* includes vec, scl commands */
+   struct radeon_state_atom ucp[6];
+   struct radeon_state_atom eye; /* eye pos */
+   struct radeon_state_atom grd; /* guard band clipping */
+   struct radeon_state_atom fog; 
+   struct radeon_state_atom glt; 
+   struct radeon_state_atom txr[2]; /* for NPOT */
+};
+
+struct radeon_state {
+   /* Derived state for internal purposes:
+    */
+   struct radeon_colorbuffer_state color;
+   struct radeon_depthbuffer_state depth;
+   struct radeon_pixel_state pixel;
+   struct radeon_scissor_state scissor;
+   struct radeon_stencilbuffer_state stencil;
+   struct radeon_stipple_state stipple;
+   struct radeon_texture_state texture;
+};
+
+
+/* Need refcounting on dma buffers:
+ */
+struct radeon_dma_buffer {
+   int refcount;               /* the number of retained regions in buf */
+   drmBufPtr buf;
+};
+
+#define GET_START(rvb) (rmesa->radeonScreen->agp_buffer_offset +                       \
+                       (rvb)->address - rmesa->dma.buf0_address +      \
+                       (rvb)->start)
+
+/* A retained region, eg vertices for indexed vertices.
+ */
+struct radeon_dma_region {
+   struct radeon_dma_buffer *buf;
+   char *address;              /* == buf->address */
+   int start, end, ptr;                /* offsets from start of buf */
+   int aos_start;
+   int aos_stride;
+   int aos_size;
+};
+
+
+struct radeon_dma {
+   /* Active dma region.  Allocations for vertices and retained
+    * regions come from here.  Also used for emitting random vertices,
+    * these may be flushed by calling flush_current();
+    */
+   struct radeon_dma_region current;
+   
+   void (*flush)( radeonContextPtr );
+
+   char *buf0_address;         /* start of buf[0], for index calcs */
+   GLuint nr_released_bufs;    /* flush after so many buffers released */
+};
+
+struct radeon_dri_mirror {
+   __DRIcontextPrivate *context;       /* DRI context */
+   __DRIscreenPrivate  *screen;        /* DRI screen */
+   __DRIdrawablePrivate        *drawable;      /* DRI drawable bound to this ctx */
+
+   drmContext hwContext;
+   drmLock *hwLock;
+   int fd;
+   int drmMinor;
+};
+
+
+#define RADEON_CMD_BUF_SZ  (8*1024) 
+
+struct radeon_store {
+   GLuint statenr;
+   GLuint primnr;
+   char cmd_buf[RADEON_CMD_BUF_SZ];
+   int cmd_used;   
+   int elts_start;
+};
+
+
+/* radeon_tcl.c
+ */
+struct radeon_tcl_info {
+   GLuint vertex_format;
+   GLint last_offset;
+   GLuint hw_primitive;
+
+   struct radeon_dma_region *aos_components[8];
+   GLuint nr_aos_components;
+
+   GLuint *Elts;
+
+   struct radeon_dma_region indexed_verts;
+   struct radeon_dma_region obj;
+   struct radeon_dma_region rgba;
+   struct radeon_dma_region spec;
+   struct radeon_dma_region fog;
+   struct radeon_dma_region tex[RADEON_MAX_TEXTURE_UNITS];
+   struct radeon_dma_region norm;
+};
+
+
+/* radeon_swtcl.c
+ */
+struct radeon_swtcl_info {
+   GLuint SetupIndex;
+   GLuint SetupNewInputs;
+   GLuint RenderIndex;
+   GLuint vertex_size;
+   GLuint vertex_stride_shift;
+   GLuint vertex_format;
+   GLubyte *verts;
+
+   /* Fallback rasterization functions
+    */
+   radeon_point_func draw_point;
+   radeon_line_func draw_line;
+   radeon_tri_func draw_tri;
+
+   GLuint hw_primitive;
+   GLenum render_primitive;
+   GLuint numverts;
+
+   struct radeon_dma_region indexed_verts;
+};
+
+
+struct radeon_ioctl {
+   GLuint vertex_offset;
+   GLuint vertex_size;
+};
+
+
+
+#define RADEON_MAX_PRIMS 64
+
+
+/* Want to keep a cache of these around.  Each is parameterized by
+ * only a single value which has only a small range.  Only expect a
+ * few, so just rescan the list each time?
+ */
+struct dynfn {
+   struct dynfn *next, *prev;
+   int key;
+   char *code;
+};
+
+struct dfn_lists {
+   struct dynfn Vertex2f;
+   struct dynfn Vertex2fv;
+   struct dynfn Vertex3f;
+   struct dynfn Vertex3fv;
+   struct dynfn Color4ub;
+   struct dynfn Color4ubv;
+   struct dynfn Color3ub;
+   struct dynfn Color3ubv;
+   struct dynfn Color4f;
+   struct dynfn Color4fv;
+   struct dynfn Color3f;
+   struct dynfn Color3fv;
+   struct dynfn SecondaryColor3ubEXT;
+   struct dynfn SecondaryColor3ubvEXT;
+   struct dynfn SecondaryColor3fEXT;
+   struct dynfn SecondaryColor3fvEXT;
+   struct dynfn Normal3f;
+   struct dynfn Normal3fv;
+   struct dynfn TexCoord2f;
+   struct dynfn TexCoord2fv;
+   struct dynfn TexCoord1f;
+   struct dynfn TexCoord1fv;
+   struct dynfn MultiTexCoord2fARB;
+   struct dynfn MultiTexCoord2fvARB;
+   struct dynfn MultiTexCoord1fARB;
+   struct dynfn MultiTexCoord1fvARB;
+};
+
+struct dfn_generators {
+   struct dynfn *(*Vertex2f)( GLcontext *, int );
+   struct dynfn *(*Vertex2fv)( GLcontext *, int );
+   struct dynfn *(*Vertex3f)( GLcontext *, int );
+   struct dynfn *(*Vertex3fv)( GLcontext *, int );
+   struct dynfn *(*Color4ub)( GLcontext *, int );
+   struct dynfn *(*Color4ubv)( GLcontext *, int );
+   struct dynfn *(*Color3ub)( GLcontext *, int );
+   struct dynfn *(*Color3ubv)( GLcontext *, int );
+   struct dynfn *(*Color4f)( GLcontext *, int );
+   struct dynfn *(*Color4fv)( GLcontext *, int );
+   struct dynfn *(*Color3f)( GLcontext *, int );
+   struct dynfn *(*Color3fv)( GLcontext *, int );
+   struct dynfn *(*SecondaryColor3ubEXT)( GLcontext *, int );
+   struct dynfn *(*SecondaryColor3ubvEXT)( GLcontext *, int );
+   struct dynfn *(*SecondaryColor3fEXT)( GLcontext *, int );
+   struct dynfn *(*SecondaryColor3fvEXT)( GLcontext *, int );
+   struct dynfn *(*Normal3f)( GLcontext *, int );
+   struct dynfn *(*Normal3fv)( GLcontext *, int );
+   struct dynfn *(*TexCoord2f)( GLcontext *, int );
+   struct dynfn *(*TexCoord2fv)( GLcontext *, int );
+   struct dynfn *(*TexCoord1f)( GLcontext *, int );
+   struct dynfn *(*TexCoord1fv)( GLcontext *, int );
+   struct dynfn *(*MultiTexCoord2fARB)( GLcontext *, int );
+   struct dynfn *(*MultiTexCoord2fvARB)( GLcontext *, int );
+   struct dynfn *(*MultiTexCoord1fARB)( GLcontext *, int );
+   struct dynfn *(*MultiTexCoord1fvARB)( GLcontext *, int );
+};
+
+
+
+struct radeon_prim {
+   GLuint start;
+   GLuint end;
+   GLuint prim;
+};
+
+struct radeon_vbinfo {
+   GLint counter, initial_counter;
+   GLint *dmaptr;
+   void (*notify)( void );
+   GLint vertex_size;
+
+   /* A maximum total of 15 elements per vertex:  3 floats for position, 3
+    * floats for normal, 4 floats for color, 4 bytes for secondary color,
+    * 2 floats for each texture unit (4 floats total).
+    * 
+    * As soon as the 3rd TMU is supported or cube maps (or 3D textures) are
+    * supported, this value will grow.
+    * 
+    * The position data is never actually stored here, so 3 elements could be
+    * trimmed out of the buffer.
+    */
+   union { float f; int i; radeon_color_t color; } vertex[15];
+
+   GLfloat *normalptr;
+   GLfloat *floatcolorptr;
+   radeon_color_t *colorptr;
+   GLfloat *floatspecptr;
+   radeon_color_t *specptr;
+   GLfloat *texcoordptr[2];
+
+   GLenum *prim;               /* &ctx->Driver.CurrentExecPrimitive */
+   GLuint primflags;
+   GLboolean enabled;          /* *_NO_VTXFMT / *_NO_TCL env vars */
+   GLboolean installed;
+   GLboolean fell_back;
+   GLboolean recheck;
+   GLint nrverts;
+   GLuint vertex_format;
+
+   GLuint installed_vertex_format;
+   GLuint installed_color_3f_sz;
+
+   struct radeon_prim primlist[RADEON_MAX_PRIMS];
+   int nrprims;
+
+   struct dfn_lists dfn_cache;
+   struct dfn_generators codegen;
+   GLvertexformat vtxfmt;
+};
+
+
+
+
+struct radeon_context {
+   GLcontext *glCtx;                   /* Mesa context */
+
+   /* Driver and hardware state management
+    */
+   struct radeon_hw_state hw;
+   struct radeon_state state;
+
+   /* Texture object bookkeeping
+    */
+   unsigned              nr_heaps;
+   driTexHeap          * texture_heaps[ RADEON_NR_TEX_HEAPS ];
+   driTextureObject      swapped;
+
+
+   /* Rasterization and vertex state:
+    */
+   GLuint TclFallback;
+   GLuint Fallback;
+   GLuint NewGLState;
+
+   
+   /* Temporaries for translating away float colors:
+    */
+   struct gl_client_array UbyteColor;
+   struct gl_client_array UbyteSecondaryColor;
+
+   /* Vertex buffers
+    */
+   struct radeon_ioctl ioctl;
+   struct radeon_dma dma;
+   struct radeon_store store;
+
+   /* Page flipping
+    */
+   GLuint doPageFlip;
+
+   /* Busy waiting
+    */
+   GLuint do_usleeps;
+   GLuint do_irqs;
+   GLuint irqsEmitted;
+   drmRadeonIrqWait iw;
+
+   /* Drawable, cliprect and scissor information
+    */
+   GLuint numClipRects;                        /* Cliprects for the draw buffer */
+   XF86DRIClipRectPtr pClipRects;
+   unsigned int lastStamp;
+   GLboolean lost_context;
+   radeonScreenPtr radeonScreen;       /* Screen private DRI data */
+   RADEONSAREAPrivPtr sarea;           /* Private SAREA data */
+
+   /* TCL stuff
+    */
+   GLmatrix TexGenMatrix[RADEON_MAX_TEXTURE_UNITS];
+   GLboolean recheck_texgen[RADEON_MAX_TEXTURE_UNITS];
+   GLboolean TexGenNeedNormals[RADEON_MAX_TEXTURE_UNITS];
+   GLuint TexMatEnabled;
+   GLuint TexGenEnabled;
+   GLmatrix tmpmat;
+   GLuint last_ReallyEnabled;
+
+   /* VBI
+    */
+   GLuint vbl_seq;
+   GLuint vblank_flags;
+
+   uint64_t swap_ust;
+   uint64_t swap_missed_ust;
+
+   GLuint swap_count;
+   GLuint swap_missed_count;
+
+   PFNGLXGETUSTPROC get_ust;
+
+   /* radeon_tcl.c
+    */
+   struct radeon_tcl_info tcl;
+
+   /* radeon_swtcl.c
+    */
+   struct radeon_swtcl_info swtcl;
+
+   /* radeon_vtxfmt.c
+    */
+   struct radeon_vbinfo vb;
+
+   /* Mirrors of some DRI state
+    */
+   struct radeon_dri_mirror dri;
+
+   /* Performance counters
+    */
+   GLuint boxes;                       /* Draw performance boxes */
+   GLuint hardwareWentIdle;
+   GLuint c_clears;
+   GLuint c_drawWaits;
+   GLuint c_textureSwaps;
+   GLuint c_textureBytes;
+   GLuint c_vertexBuffers;
+};
+
+#define RADEON_CONTEXT(ctx)            ((radeonContextPtr)(ctx->DriverCtx))
+
+
+static __inline GLuint radeonPackColor( GLuint cpp,
+                                       GLubyte r, GLubyte g,
+                                       GLubyte b, GLubyte a )
+{
+   switch ( cpp ) {
+   case 2:
+      return PACK_COLOR_565( r, g, b );
+   case 4:
+      return PACK_COLOR_8888( a, r, g, b );
+   default:
+      return 0;
+   }
+}
+
+#define RADEON_OLD_PACKETS 1
+
+
+extern void radeonDestroyContext( __DRIcontextPrivate *driContextPriv );
+extern GLboolean radeonCreateContext(const __GLcontextModes *glVisual,
+                                    __DRIcontextPrivate *driContextPriv,
+                                    void *sharedContextPrivate);
+extern void radeonSwapBuffers( __DRIdrawablePrivate *dPriv );
+extern GLboolean radeonMakeCurrent( __DRIcontextPrivate *driContextPriv,
+                                   __DRIdrawablePrivate *driDrawPriv,
+                                   __DRIdrawablePrivate *driReadPriv );
+extern GLboolean radeonUnbindContext( __DRIcontextPrivate *driContextPriv );
+
+/* ================================================================
+ * Debugging:
+ */
+#define DO_DEBUG               1
+
+#if DO_DEBUG
+extern int RADEON_DEBUG;
+#else
+#define RADEON_DEBUG           0
+#endif
+
+#define DEBUG_TEXTURE  0x001
+#define DEBUG_STATE    0x002
+#define DEBUG_IOCTL    0x004
+#define DEBUG_PRIMS    0x008
+#define DEBUG_VERTS    0x010
+#define DEBUG_FALLBACKS        0x020
+#define DEBUG_VFMT     0x040
+#define DEBUG_CODEGEN  0x080
+#define DEBUG_VERBOSE  0x100
+#define DEBUG_DRI       0x200
+#define DEBUG_DMA       0x400
+#define DEBUG_SANITY    0x800
+
+#endif
+#endif /* __RADEON_CONTEXT_H__ */
diff --git a/src/mesa/drivers/dri/radeon/radeon_ioctl.c b/src/mesa/drivers/dri/radeon/radeon_ioctl.c
new file mode 100644 (file)
index 0000000..a388720
--- /dev/null
@@ -0,0 +1,1191 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.c,v 1.11 2003/01/29 22:04:59 dawes Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Gareth Hughes <gareth@valinux.com>
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ */
+#include <sched.h>
+#include <errno.h>
+
+#include "glheader.h"
+#include "imports.h"
+#include "simple_list.h"
+#include "swrast/swrast.h"
+
+#include "radeon_context.h"
+#include "radeon_state.h"
+#include "radeon_ioctl.h"
+#include "radeon_tcl.h"
+#include "radeon_sanity.h"
+
+#include "radeon_macros.h"  /* for INREG() */
+
+#include "vblank.h"
+
+#define RADEON_TIMEOUT             512
+#define RADEON_IDLE_RETRY           16
+
+
+static void radeonWaitForIdle( radeonContextPtr rmesa );
+
+/* =============================================================
+ * Kernel command buffer handling
+ */
+
+static void print_state_atom( struct radeon_state_atom *state )
+{
+   int i;
+
+   fprintf(stderr, "emit %s/%d\n", state->name, state->cmd_size);
+
+   if (RADEON_DEBUG & DEBUG_VERBOSE) 
+      for (i = 0 ; i < state->cmd_size ; i++) 
+        fprintf(stderr, "\t%s[%d]: %x\n", state->name, i, state->cmd[i]);
+
+}
+
+static void radeon_emit_state_list( radeonContextPtr rmesa, 
+                                   struct radeon_state_atom *list )
+{
+   struct radeon_state_atom *state, *tmp;
+   char *dest;
+
+   /* From Felix Kuhling: similar to some other lockups, glaxium will
+    * lock with what we believe to be a normal command stream, but
+    * sprinkling some magic waits arounds allows it to run
+    * uninterrupted.  This has a slight effect on q3 framerates, but
+    * it might now be possible to remove the zbs hack, below.
+    *
+    * Felix reports that this can be narrowed down to just
+    * tcl,tex0,tex1 state, but that's pretty much every statechange,
+    * so let's just put the wait in always (unless Felix wants to
+    * narrow it down further...)
+    */
+   if (1) {
+      drmRadeonCmdHeader *cmd;
+      cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, sizeof(*cmd), 
+                                                    __FUNCTION__ );
+      cmd->wait.cmd_type = RADEON_CMD_WAIT;
+      cmd->wait.flags = RADEON_WAIT_3D;
+   }
+
+   foreach_s( state, tmp, list ) {
+      if (state->check( rmesa->glCtx )) {
+        dest = radeonAllocCmdBuf( rmesa, state->cmd_size * 4, __FUNCTION__);
+        memcpy( dest, state->cmd, state->cmd_size * 4);
+        move_to_head( &(rmesa->hw.clean), state );
+        if (RADEON_DEBUG & DEBUG_STATE) 
+           print_state_atom( state );
+      }
+      else if (RADEON_DEBUG & DEBUG_STATE)
+        fprintf(stderr, "skip state %s\n", state->name);
+   }
+}
+
+
+void radeonEmitState( radeonContextPtr rmesa )
+{
+   struct radeon_state_atom *state, *tmp;
+
+   if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS))
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   /* Somewhat overkill:
+    */
+   if (rmesa->lost_context) {
+      if (RADEON_DEBUG & (DEBUG_STATE|DEBUG_PRIMS|DEBUG_IOCTL))
+        fprintf(stderr, "%s - lost context\n", __FUNCTION__); 
+
+      foreach_s( state, tmp, &(rmesa->hw.clean) ) 
+        move_to_tail(&(rmesa->hw.dirty), state );
+
+      rmesa->lost_context = 0;
+   }
+   else if (1) {
+      /* This is a darstardly kludge to work around a lockup that I
+       * haven't otherwise figured out.
+       */
+      move_to_tail(&(rmesa->hw.dirty), &(rmesa->hw.zbs) );
+   }
+
+   if (!(rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL)) {
+     foreach_s( state, tmp, &(rmesa->hw.dirty) ) {
+       if (state->is_tcl) {
+        move_to_head( &(rmesa->hw.clean), state );
+       }
+     }
+   }
+
+   radeon_emit_state_list( rmesa, &rmesa->hw.dirty );
+}
+
+
+
+/* Fire a section of the retained (indexed_verts) buffer as a regular
+ * primtive.  
+ */
+extern void radeonEmitVbufPrim( radeonContextPtr rmesa,
+                               GLuint vertex_format,
+                               GLuint primitive,
+                               GLuint vertex_nr )
+{
+   drmRadeonCmdHeader *cmd;
+
+
+   assert(rmesa->dri.drmMinor >= 3); 
+   assert(!(primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND));
+   
+   radeonEmitState( rmesa );
+
+   if (RADEON_DEBUG & DEBUG_IOCTL)
+      fprintf(stderr, "%s cmd_used/4: %d\n", __FUNCTION__,
+             rmesa->store.cmd_used/4);
+   
+#if RADEON_OLD_PACKETS
+   cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, 6 * sizeof(*cmd),
+                                                 __FUNCTION__ );
+   cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
+   cmd[1].i = RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM | (3 << 16);
+   cmd[2].i = rmesa->ioctl.vertex_offset;
+   cmd[3].i = vertex_nr;
+   cmd[4].i = vertex_format;
+   cmd[5].i = (primitive | 
+              RADEON_CP_VC_CNTL_PRIM_WALK_LIST |
+              RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
+              RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
+              (vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT));
+
+   if (RADEON_DEBUG & DEBUG_PRIMS)
+      fprintf(stderr, "%s: header 0x%x offt 0x%x vfmt 0x%x vfcntl %x \n",
+             __FUNCTION__,
+             cmd[1].i, cmd[2].i, cmd[4].i, cmd[5].i);
+#else
+   cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, 4 * sizeof(*cmd),
+                                                 __FUNCTION__ );
+   cmd[0].i = 0;
+   cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
+   cmd[1].i = RADEON_CP_PACKET3_3D_DRAW_VBUF | (1 << 16);
+   cmd[2].i = vertex_format;
+   cmd[3].i = (primitive | 
+              RADEON_CP_VC_CNTL_PRIM_WALK_LIST |
+              RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
+              RADEON_CP_VC_CNTL_MAOS_ENABLE |
+              RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE |
+              (vertex_nr << RADEON_CP_VC_CNTL_NUM_SHIFT));
+
+
+   if (RADEON_DEBUG & DEBUG_PRIMS)
+      fprintf(stderr, "%s: header 0x%x vfmt 0x%x vfcntl %x \n",
+             __FUNCTION__,
+             cmd[1].i, cmd[2].i, cmd[3].i);
+#endif
+}
+
+
+void radeonFlushElts( radeonContextPtr rmesa )
+{
+   int *cmd = (int *)(rmesa->store.cmd_buf + rmesa->store.elts_start);
+   int dwords;
+#if RADEON_OLD_PACKETS
+   int nr = (rmesa->store.cmd_used - (rmesa->store.elts_start + 24)) / 2;
+#else
+   int nr = (rmesa->store.cmd_used - (rmesa->store.elts_start + 16)) / 2;
+#endif
+
+   if (RADEON_DEBUG & DEBUG_IOCTL)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   assert( rmesa->dma.flush == radeonFlushElts );
+   rmesa->dma.flush = 0;
+
+   /* Cope with odd number of elts:
+    */
+   rmesa->store.cmd_used = (rmesa->store.cmd_used + 2) & ~2;
+   dwords = (rmesa->store.cmd_used - rmesa->store.elts_start) / 4;
+
+#if RADEON_OLD_PACKETS
+   cmd[1] |= (dwords - 3) << 16;
+   cmd[5] |= nr << RADEON_CP_VC_CNTL_NUM_SHIFT;
+#else
+   cmd[1] |= (dwords - 3) << 16;
+   cmd[3] |= nr << RADEON_CP_VC_CNTL_NUM_SHIFT;
+#endif
+}
+
+
+GLushort *radeonAllocEltsOpenEnded( radeonContextPtr rmesa,
+                                   GLuint vertex_format,
+                                   GLuint primitive,
+                                   GLuint min_nr )
+{
+   drmRadeonCmdHeader *cmd;
+   GLushort *retval;
+
+   if (RADEON_DEBUG & DEBUG_IOCTL)
+      fprintf(stderr, "%s %d\n", __FUNCTION__, min_nr);
+
+   assert(rmesa->dri.drmMinor >= 3); 
+   assert((primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND));
+   
+   radeonEmitState( rmesa );
+   
+#if RADEON_OLD_PACKETS
+   cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, 
+                                                 24 + min_nr*2,
+                                                 __FUNCTION__ );
+   cmd[0].i = 0;
+   cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
+   cmd[1].i = RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM;
+   cmd[2].i = rmesa->ioctl.vertex_offset;
+   cmd[3].i = 0xffff;
+   cmd[4].i = vertex_format;
+   cmd[5].i = (primitive | 
+              RADEON_CP_VC_CNTL_PRIM_WALK_IND |
+              RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
+              RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE);
+
+   retval = (GLushort *)(cmd+6);
+#else   
+   cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, 
+                                                 16 + min_nr*2,
+                                                 __FUNCTION__ );
+   cmd[0].i = 0;
+   cmd[0].header.cmd_type = RADEON_CMD_PACKET3_CLIP;
+   cmd[1].i = RADEON_CP_PACKET3_3D_DRAW_INDX;
+   cmd[2].i = vertex_format;
+   cmd[3].i = (primitive | 
+              RADEON_CP_VC_CNTL_PRIM_WALK_IND |
+              RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA |
+              RADEON_CP_VC_CNTL_MAOS_ENABLE |
+              RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE);
+
+   retval = (GLushort *)(cmd+4);
+#endif
+
+   if (RADEON_DEBUG & DEBUG_PRIMS)
+      fprintf(stderr, "%s: header 0x%x vfmt 0x%x prim %x \n",
+             __FUNCTION__,
+             cmd[1].i, vertex_format, primitive);
+
+   assert(!rmesa->dma.flush);
+   rmesa->glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
+   rmesa->dma.flush = radeonFlushElts;
+
+   rmesa->store.elts_start = ((char *)cmd) - rmesa->store.cmd_buf;
+
+   return retval;
+}
+
+
+
+void radeonEmitVertexAOS( radeonContextPtr rmesa,
+                         GLuint vertex_size,
+                         GLuint offset )
+{
+#if RADEON_OLD_PACKETS
+   rmesa->ioctl.vertex_size = vertex_size;
+   rmesa->ioctl.vertex_offset = offset;
+#else
+   drmRadeonCmdHeader *cmd;
+   assert(rmesa->dri.drmMinor >= 3); 
+
+   if (RADEON_DEBUG & (DEBUG_PRIMS|DEBUG_IOCTL))
+      fprintf(stderr, "%s:  vertex_size 0x%x offset 0x%x \n",
+             __FUNCTION__, vertex_size, offset);
+
+   cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, 5 * sizeof(int),
+                                                 __FUNCTION__ );
+
+   cmd[0].i = 0;
+   cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
+   cmd[1].i = RADEON_CP_PACKET3_3D_LOAD_VBPNTR | (2 << 16);
+   cmd[2].i = 1;
+   cmd[3].i = vertex_size | (vertex_size << 8);
+   cmd[4].i = offset;
+#endif
+}
+                      
+
+void radeonEmitAOS( radeonContextPtr rmesa,
+                   struct radeon_dma_region **component,
+                   GLuint nr,
+                   GLuint offset )
+{
+#if RADEON_OLD_PACKETS
+   assert( nr == 1 );
+   assert( component[0]->aos_size == component[0]->aos_stride );
+   rmesa->ioctl.vertex_size = component[0]->aos_size;
+   rmesa->ioctl.vertex_offset = 
+      (component[0]->aos_start + offset * component[0]->aos_stride * 4);
+#else
+   drmRadeonCmdHeader *cmd;
+   int sz = 3 + (nr/2 * 3) + (nr & 1) * 2;
+   int i;
+   int *tmp;
+
+   if (RADEON_DEBUG & DEBUG_IOCTL)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   assert(rmesa->dri.drmMinor >= 3); 
+
+   cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, sz * sizeof(int),
+                                                 __FUNCTION__ );
+   cmd[0].i = 0;
+   cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
+   cmd[1].i = RADEON_CP_PACKET3_3D_LOAD_VBPNTR | ((sz-3) << 16);
+   cmd[2].i = nr;
+   tmp = &cmd[0].i;
+   cmd += 3;
+
+   for (i = 0 ; i < nr ; i++) {
+      if (i & 1) {
+        cmd[0].i |= ((component[i]->aos_stride << 24) | 
+                     (component[i]->aos_size << 16));
+        cmd[2].i = (component[i]->aos_start + 
+                    offset * component[i]->aos_stride * 4);
+        cmd += 3;
+      }
+      else {
+        cmd[0].i = ((component[i]->aos_stride << 8) | 
+                    (component[i]->aos_size << 0));
+        cmd[1].i = (component[i]->aos_start + 
+                    offset * component[i]->aos_stride * 4);
+      }
+   }
+
+   if (RADEON_DEBUG & DEBUG_VERTS) {
+      fprintf(stderr, "%s:\n", __FUNCTION__);
+      for (i = 0 ; i < sz ; i++)
+        fprintf(stderr, "   %d: %x\n", i, tmp[i]);
+   }
+#endif
+}
+
+/* using already shifted color_fmt! */
+void radeonEmitBlit( radeonContextPtr rmesa, /* FIXME: which drmMinor is required? */
+                  GLuint color_fmt,
+                  GLuint src_pitch,
+                  GLuint src_offset,
+                  GLuint dst_pitch,
+                  GLuint dst_offset,
+                  GLint srcx, GLint srcy,
+                  GLint dstx, GLint dsty,
+                  GLuint w, GLuint h )
+{
+   drmRadeonCmdHeader *cmd;
+
+   if (RADEON_DEBUG & DEBUG_IOCTL)
+      fprintf(stderr, "%s src %x/%x %d,%d dst: %x/%x %d,%d sz: %dx%d\n",
+             __FUNCTION__, 
+             src_pitch, src_offset, srcx, srcy,
+             dst_pitch, dst_offset, dstx, dsty,
+             w, h);
+
+   assert( (src_pitch & 63) == 0 );
+   assert( (dst_pitch & 63) == 0 );
+   assert( (src_offset & 1023) == 0 ); 
+   assert( (dst_offset & 1023) == 0 ); 
+   assert( w < (1<<16) );
+   assert( h < (1<<16) );
+
+   cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, 8 * sizeof(int),
+                                                 __FUNCTION__ );
+
+
+   cmd[0].i = 0;
+   cmd[0].header.cmd_type = RADEON_CMD_PACKET3;
+   cmd[1].i = RADEON_CP_PACKET3_CNTL_BITBLT_MULTI | (5 << 16);
+   cmd[2].i = (RADEON_GMC_SRC_PITCH_OFFSET_CNTL |
+              RADEON_GMC_DST_PITCH_OFFSET_CNTL |
+              RADEON_GMC_BRUSH_NONE |
+              color_fmt |
+              RADEON_GMC_SRC_DATATYPE_COLOR |
+              RADEON_ROP3_S |
+              RADEON_DP_SRC_SOURCE_MEMORY |
+              RADEON_GMC_CLR_CMP_CNTL_DIS |
+              RADEON_GMC_WR_MSK_DIS );
+
+   cmd[3].i = ((src_pitch/64)<<22) | (src_offset >> 10);
+   cmd[4].i = ((dst_pitch/64)<<22) | (dst_offset >> 10);
+   cmd[5].i = (srcx << 16) | srcy;
+   cmd[6].i = (dstx << 16) | dsty; /* dst */
+   cmd[7].i = (w << 16) | h;
+}
+
+
+void radeonEmitWait( radeonContextPtr rmesa, GLuint flags )
+{
+   if (rmesa->dri.drmMinor >= 6) {
+      drmRadeonCmdHeader *cmd;
+
+      assert( !(flags & ~(RADEON_WAIT_2D|RADEON_WAIT_3D)) );
+      
+      cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, 1 * sizeof(int),
+                                                  __FUNCTION__ );
+      cmd[0].i = 0;
+      cmd[0].wait.cmd_type = RADEON_CMD_WAIT;
+      cmd[0].wait.flags = flags;
+   }
+}
+
+
+static int radeonFlushCmdBufLocked( radeonContextPtr rmesa, 
+                                   const char * caller )
+{
+   int ret, i;
+   drmRadeonCmdBuffer cmd;
+
+   if (RADEON_DEBUG & DEBUG_IOCTL) {
+      fprintf(stderr, "%s from %s\n", __FUNCTION__, caller); 
+
+      if (RADEON_DEBUG & DEBUG_VERBOSE) 
+        for (i = 0 ; i < rmesa->store.cmd_used ; i += 4 )
+           fprintf(stderr, "%d: %x\n", i/4, 
+                   *(int *)(&rmesa->store.cmd_buf[i]));
+   }
+
+   if (RADEON_DEBUG & DEBUG_DMA)
+      fprintf(stderr, "%s: Releasing %d buffers\n", __FUNCTION__,
+             rmesa->dma.nr_released_bufs);
+
+
+   if (RADEON_DEBUG & DEBUG_SANITY) {
+      if (rmesa->state.scissor.enabled) 
+        ret = radeonSanityCmdBuffer( rmesa, 
+                                     rmesa->state.scissor.numClipRects,
+                                     rmesa->state.scissor.pClipRects);
+      else
+        ret = radeonSanityCmdBuffer( rmesa, 
+                                     rmesa->numClipRects,
+                                     rmesa->pClipRects);
+      if (ret) {
+        fprintf(stderr, "drmSanityCommandWrite: %d\n", ret);    
+        goto out;
+      }
+   }
+
+
+   cmd.bufsz = rmesa->store.cmd_used;
+   cmd.buf = rmesa->store.cmd_buf;
+
+   if (rmesa->state.scissor.enabled) {
+      cmd.nbox = rmesa->state.scissor.numClipRects;
+      cmd.boxes = (drmClipRect *)rmesa->state.scissor.pClipRects;
+   } else {
+      cmd.nbox = rmesa->numClipRects;
+      cmd.boxes = (drmClipRect *)rmesa->pClipRects;
+   }
+
+   ret = drmCommandWrite( rmesa->dri.fd,
+                         DRM_RADEON_CMDBUF,
+                         &cmd, sizeof(cmd) );
+
+   if (ret)
+      fprintf(stderr, "drmCommandWrite: %d\n", ret);
+
+ out:
+   rmesa->store.primnr = 0;
+   rmesa->store.statenr = 0;
+   rmesa->store.cmd_used = 0;
+   rmesa->dma.nr_released_bufs = 0;
+   rmesa->lost_context = 1;    
+   return ret;
+}
+
+
+/* Note: does not emit any commands to avoid recursion on
+ * radeonAllocCmdBuf.
+ */
+void radeonFlushCmdBuf( radeonContextPtr rmesa, const char *caller )
+{
+   int ret;
+
+             
+   assert (rmesa->dri.drmMinor >= 3);
+
+   LOCK_HARDWARE( rmesa );
+
+   ret = radeonFlushCmdBufLocked( rmesa, caller );
+
+   UNLOCK_HARDWARE( rmesa );
+
+   if (ret) {
+      fprintf(stderr, "drmRadeonCmdBuffer: %d (exiting)\n", ret);
+      exit(ret);
+   }
+}
+
+/* =============================================================
+ * Hardware vertex buffer handling
+ */
+
+
+void radeonRefillCurrentDmaRegion( radeonContextPtr rmesa )
+{
+   struct radeon_dma_buffer *dmabuf;
+   int fd = rmesa->dri.fd;
+   int index = 0;
+   int size = 0;
+   drmDMAReq dma;
+   int ret;
+
+   if (RADEON_DEBUG & (DEBUG_IOCTL|DEBUG_DMA))
+      fprintf(stderr, "%s\n", __FUNCTION__);  
+
+   if (rmesa->dma.flush) {
+      rmesa->dma.flush( rmesa );
+   }
+
+   if (rmesa->dma.current.buf)
+      radeonReleaseDmaRegion( rmesa, &rmesa->dma.current, __FUNCTION__ );
+
+   if (rmesa->dma.nr_released_bufs > 4)
+      radeonFlushCmdBuf( rmesa, __FUNCTION__ );
+
+   dma.context = rmesa->dri.hwContext;
+   dma.send_count = 0;
+   dma.send_list = NULL;
+   dma.send_sizes = NULL;
+   dma.flags = 0;
+   dma.request_count = 1;
+   dma.request_size = RADEON_BUFFER_SIZE;
+   dma.request_list = &index;
+   dma.request_sizes = &size;
+   dma.granted_count = 0;
+
+   LOCK_HARDWARE(rmesa);       /* no need to validate */
+
+   ret = drmDMA( fd, &dma );
+      
+   if (ret != 0) {
+      /* Free some up this way?
+       */
+      if (rmesa->dma.nr_released_bufs) {
+        radeonFlushCmdBufLocked( rmesa, __FUNCTION__ );
+      }
+      
+      if (RADEON_DEBUG & DEBUG_DMA)
+        fprintf(stderr, "Waiting for buffers\n");
+
+      radeonWaitForIdleLocked( rmesa );
+      ret = drmDMA( fd, &dma );
+
+      if ( ret != 0 ) {
+        UNLOCK_HARDWARE( rmesa );
+        fprintf( stderr, "Error: Could not get dma buffer... exiting\n" );
+        exit( -1 );
+      }
+   }
+
+   UNLOCK_HARDWARE(rmesa);
+
+   if (RADEON_DEBUG & DEBUG_DMA)
+      fprintf(stderr, "Allocated buffer %d\n", index);
+
+   dmabuf = CALLOC_STRUCT( radeon_dma_buffer );
+   dmabuf->buf = &rmesa->radeonScreen->buffers->list[index];
+   dmabuf->refcount = 1;
+
+   rmesa->dma.current.buf = dmabuf;
+   rmesa->dma.current.address = dmabuf->buf->address;
+   rmesa->dma.current.end = dmabuf->buf->total;
+   rmesa->dma.current.start = 0;
+   rmesa->dma.current.ptr = 0;
+
+   rmesa->c_vertexBuffers++;
+}
+
+void radeonReleaseDmaRegion( radeonContextPtr rmesa,
+                            struct radeon_dma_region *region,
+                            const char *caller )
+{
+   if (RADEON_DEBUG & DEBUG_IOCTL)
+      fprintf(stderr, "%s from %s\n", __FUNCTION__, caller); 
+   
+   if (!region->buf)
+      return;
+
+   if (rmesa->dma.flush)
+      rmesa->dma.flush( rmesa );
+
+   if (--region->buf->refcount == 0) {
+      drmRadeonCmdHeader *cmd;
+
+      if (RADEON_DEBUG & (DEBUG_IOCTL|DEBUG_DMA))
+        fprintf(stderr, "%s -- DISCARD BUF %d\n", __FUNCTION__,
+                region->buf->buf->idx);  
+      
+      cmd = (drmRadeonCmdHeader *)radeonAllocCmdBuf( rmesa, sizeof(*cmd), 
+                                                    __FUNCTION__ );
+      cmd->dma.cmd_type = RADEON_CMD_DMA_DISCARD;
+      cmd->dma.buf_idx = region->buf->buf->idx;
+      FREE(region->buf);
+      rmesa->dma.nr_released_bufs++;
+   }
+
+   region->buf = 0;
+   region->start = 0;
+}
+
+/* Allocates a region from rmesa->dma.current.  If there isn't enough
+ * space in current, grab a new buffer (and discard what was left of current)
+ */
+void radeonAllocDmaRegion( radeonContextPtr rmesa, 
+                          struct radeon_dma_region *region,
+                          int bytes,
+                          int alignment )
+{
+   if (RADEON_DEBUG & DEBUG_IOCTL)
+      fprintf(stderr, "%s %d\n", __FUNCTION__, bytes);
+
+   if (rmesa->dma.flush)
+      rmesa->dma.flush( rmesa );
+
+   if (region->buf)
+      radeonReleaseDmaRegion( rmesa, region, __FUNCTION__ );
+
+   alignment--;
+   rmesa->dma.current.start = rmesa->dma.current.ptr = 
+      (rmesa->dma.current.ptr + alignment) & ~alignment;
+
+   if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end ) 
+      radeonRefillCurrentDmaRegion( rmesa );
+
+   region->start = rmesa->dma.current.start;
+   region->ptr = rmesa->dma.current.start;
+   region->end = rmesa->dma.current.start + bytes;
+   region->address = rmesa->dma.current.address;
+   region->buf = rmesa->dma.current.buf;
+   region->buf->refcount++;
+
+   rmesa->dma.current.ptr += bytes; /* bug - if alignment > 7 */
+   rmesa->dma.current.start = 
+      rmesa->dma.current.ptr = (rmesa->dma.current.ptr + 0x7) & ~0x7;  
+
+   if ( rmesa->dri.drmMinor < 3 ) 
+      radeonRefillCurrentDmaRegion( rmesa );
+}
+
+void radeonAllocDmaRegionVerts( radeonContextPtr rmesa, 
+                               struct radeon_dma_region *region,
+                               int numverts,
+                               int vertsize,
+                               int alignment )
+{
+   radeonAllocDmaRegion( rmesa, region, vertsize * numverts, alignment );
+}
+
+/* ================================================================
+ * SwapBuffers with client-side throttling
+ */
+
+static CARD32 radeonGetLastFrame (radeonContextPtr rmesa) 
+{
+   unsigned char *RADEONMMIO = rmesa->radeonScreen->mmio.map;
+   int ret;
+   CARD32 frame;
+
+   if (rmesa->dri.screen->drmMinor >= 4) {
+      drmRadeonGetParam gp;
+
+      gp.param = RADEON_PARAM_LAST_FRAME;
+      gp.value = &frame;
+      ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_GETPARAM,
+                                &gp, sizeof(gp) );
+   } 
+   else
+      ret = -EINVAL;
+
+#ifndef __alpha__
+   if ( ret == -EINVAL ) {
+      frame = INREG( RADEON_LAST_FRAME_REG );
+      ret = 0;
+   } 
+#endif
+   if ( ret ) {
+      fprintf( stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, ret );
+      exit(1);
+   }
+
+   return frame;
+}
+
+static void radeonEmitIrqLocked( radeonContextPtr rmesa )
+{
+   drmRadeonIrqEmit ie;
+   int ret;
+
+   ie.irq_seq = &rmesa->iw.irq_seq;
+   ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_IRQ_EMIT, 
+                             &ie, sizeof(ie) );
+   if ( ret ) {
+      fprintf( stderr, "%s: drmRadeonIrqEmit: %d\n", __FUNCTION__, ret );
+      exit(1);
+   }
+}
+
+
+static void radeonWaitIrq( radeonContextPtr rmesa )
+{
+   int ret;
+
+   do {
+      ret = drmCommandWrite( rmesa->dri.fd, DRM_RADEON_IRQ_WAIT,
+                            &rmesa->iw, sizeof(rmesa->iw) );
+   } while (ret && (errno == EINTR || errno == EAGAIN));
+
+   if ( ret ) {
+      fprintf( stderr, "%s: drmRadeonIrqWait: %d\n", __FUNCTION__, ret );
+      exit(1);
+   }
+}
+
+
+static void radeonWaitForFrameCompletion( radeonContextPtr rmesa )
+{
+   RADEONSAREAPrivPtr sarea = rmesa->sarea;
+
+   if (rmesa->do_irqs) {
+      if (radeonGetLastFrame(rmesa) < sarea->last_frame) {
+        if (!rmesa->irqsEmitted) {
+           while (radeonGetLastFrame (rmesa) < sarea->last_frame)
+              ;
+        }
+        else {
+           UNLOCK_HARDWARE( rmesa ); 
+           radeonWaitIrq( rmesa );     
+           LOCK_HARDWARE( rmesa ); 
+        }
+        rmesa->irqsEmitted = 10;
+      }
+
+      if (rmesa->irqsEmitted) {
+        radeonEmitIrqLocked( rmesa );
+        rmesa->irqsEmitted--;
+      }
+   } 
+   else {
+      while (radeonGetLastFrame (rmesa) < sarea->last_frame) {
+        UNLOCK_HARDWARE( rmesa ); 
+        if (rmesa->do_usleeps) 
+           DO_USLEEP( 1 );
+        LOCK_HARDWARE( rmesa ); 
+      }
+   }
+}
+
+/* Copy the back color buffer to the front color buffer.
+ */
+void radeonCopyBuffer( const __DRIdrawablePrivate *dPriv )
+{
+   radeonContextPtr rmesa;
+   GLint nbox, i, ret;
+   GLboolean   missed_target;
+   uint64_t     ust;
+
+   assert(dPriv);
+   assert(dPriv->driContextPriv);
+   assert(dPriv->driContextPriv->driverPrivate);
+
+   rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
+
+   if ( RADEON_DEBUG & DEBUG_IOCTL ) {
+      fprintf( stderr, "\n%s( %p )\n\n", __FUNCTION__, rmesa->glCtx );
+   }
+
+   RADEON_FIREVERTICES( rmesa );
+   LOCK_HARDWARE( rmesa );
+
+   /* Throttle the frame rate -- only allow one pending swap buffers
+    * request at a time.
+    */
+   radeonWaitForFrameCompletion( rmesa );
+   UNLOCK_HARDWARE( rmesa );
+   driWaitForVBlank( dPriv, & rmesa->vbl_seq, rmesa->vblank_flags, & missed_target );
+   LOCK_HARDWARE( rmesa );
+
+   nbox = dPriv->numClipRects; /* must be in locked region */
+
+   for ( i = 0 ; i < nbox ; ) {
+      GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS , nbox );
+      XF86DRIClipRectPtr box = dPriv->pClipRects;
+      XF86DRIClipRectPtr b = rmesa->sarea->boxes;
+      GLint n = 0;
+
+      for ( ; i < nr ; i++ ) {
+        *b++ = box[i];
+        n++;
+      }
+      rmesa->sarea->nbox = n;
+
+      ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_SWAP );
+
+      if ( ret ) {
+        fprintf( stderr, "DRM_RADEON_SWAP_BUFFERS: return = %d\n", ret );
+        UNLOCK_HARDWARE( rmesa );
+        exit( 1 );
+      }
+   }
+
+   UNLOCK_HARDWARE( rmesa );
+   rmesa->swap_count++;
+   (*rmesa->get_ust)( & ust );
+   if ( missed_target ) {
+      rmesa->swap_missed_count++;
+      rmesa->swap_missed_ust = ust - rmesa->swap_ust;
+   }
+
+   rmesa->swap_ust = ust;
+}
+
+void radeonPageFlip( const __DRIdrawablePrivate *dPriv )
+{
+   radeonContextPtr rmesa;
+   GLint ret;
+   GLboolean   missed_target;
+
+   assert(dPriv);
+   assert(dPriv->driContextPriv);
+   assert(dPriv->driContextPriv->driverPrivate);
+
+   rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
+
+   if ( RADEON_DEBUG & DEBUG_IOCTL ) {
+      fprintf(stderr, "%s: pfCurrentPage: %d\n", __FUNCTION__,
+             rmesa->sarea->pfCurrentPage);
+   }
+
+   RADEON_FIREVERTICES( rmesa );
+   LOCK_HARDWARE( rmesa );
+
+   /* Need to do this for the perf box placement:
+    */
+   if (dPriv->numClipRects)
+   {
+      XF86DRIClipRectPtr box = dPriv->pClipRects;
+      XF86DRIClipRectPtr b = rmesa->sarea->boxes;
+      b[0] = box[0];
+      rmesa->sarea->nbox = 1;
+   }
+
+   /* Throttle the frame rate -- only allow a few pending swap buffers
+    * request at a time.
+    */
+   radeonWaitForFrameCompletion( rmesa );
+   UNLOCK_HARDWARE( rmesa );
+   driWaitForVBlank( dPriv, & rmesa->vbl_seq, rmesa->vblank_flags, & missed_target );
+   if ( missed_target ) {
+      rmesa->swap_missed_count++;
+      (void) (*rmesa->get_ust)( & rmesa->swap_missed_ust );
+   }
+   LOCK_HARDWARE( rmesa );
+
+   ret = drmCommandNone( rmesa->dri.fd, DRM_RADEON_FLIP );
+
+   UNLOCK_HARDWARE( rmesa );
+
+   if ( ret ) {
+      fprintf( stderr, "DRM_RADEON_FLIP: return = %d\n", ret );
+      exit( 1 );
+   }
+
+   rmesa->swap_count++;
+   (void) (*rmesa->get_ust)( & rmesa->swap_ust );
+
+   if ( rmesa->sarea->pfCurrentPage == 1 ) {
+        rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset;
+        rmesa->state.color.drawPitch  = rmesa->radeonScreen->frontPitch;
+   } else {
+        rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset;
+        rmesa->state.color.drawPitch  = rmesa->radeonScreen->backPitch;
+   }
+
+   RADEON_STATECHANGE( rmesa, ctx );
+   rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = rmesa->state.color.drawOffset;
+   rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH]  = rmesa->state.color.drawPitch;
+}
+
+
+/* ================================================================
+ * Buffer clear
+ */
+#define RADEON_MAX_CLEARS      256
+
+static void radeonClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
+                        GLint cx, GLint cy, GLint cw, GLint ch )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
+   RADEONSAREAPrivPtr sarea = rmesa->sarea;
+   unsigned char *RADEONMMIO = rmesa->radeonScreen->mmio.map;
+   CARD32 clear;
+   GLuint flags = 0;
+   GLuint color_mask = 0;
+   GLint ret, i;
+
+   if ( RADEON_DEBUG & DEBUG_IOCTL ) {
+      fprintf( stderr, "%s:  all=%d cx=%d cy=%d cw=%d ch=%d\n",
+              __FUNCTION__, all, cx, cy, cw, ch );
+   }
+
+   radeonEmitState( rmesa );
+
+   /* Need to cope with lostcontext here as kernel relies on
+    * some residual state:
+    */
+   RADEON_FIREVERTICES( rmesa ); 
+
+   if ( mask & DD_FRONT_LEFT_BIT ) {
+      flags |= RADEON_FRONT;
+      color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
+      mask &= ~DD_FRONT_LEFT_BIT;
+   }
+
+   if ( mask & DD_BACK_LEFT_BIT ) {
+      flags |= RADEON_BACK;
+      color_mask = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
+      mask &= ~DD_BACK_LEFT_BIT;
+   }
+
+   if ( mask & DD_DEPTH_BIT ) {
+      if ( ctx->Depth.Mask ) flags |= RADEON_DEPTH; /* FIXME: ??? */
+      mask &= ~DD_DEPTH_BIT;
+   }
+
+   if ( (mask & DD_STENCIL_BIT) && rmesa->state.stencil.hwBuffer ) {
+      flags |= RADEON_STENCIL;
+      mask &= ~DD_STENCIL_BIT;
+   }
+
+   if ( mask ) {
+      if (RADEON_DEBUG & DEBUG_FALLBACKS)
+        fprintf(stderr, "%s: swrast clear, mask: %x\n", __FUNCTION__, mask);
+      _swrast_Clear( ctx, mask, all, cx, cy, cw, ch );
+   }
+
+   if ( !flags ) 
+      return;
+
+
+   /* Flip top to bottom */
+   cx += dPriv->x;
+   cy  = dPriv->y + dPriv->h - cy - ch;
+
+   LOCK_HARDWARE( rmesa );
+
+   /* Throttle the number of clear ioctls we do.
+    */
+   while ( 1 ) {
+      int ret;
+
+      if (rmesa->dri.screen->drmMinor >= 4) {
+       drmRadeonGetParam gp;
+
+       gp.param = RADEON_PARAM_LAST_CLEAR;
+       gp.value = &clear;
+       ret = drmCommandWriteRead( rmesa->dri.fd,
+                                  DRM_RADEON_GETPARAM, &gp, sizeof(gp) );
+      } else
+       ret = -EINVAL;
+
+#ifndef __alpha__
+      if ( ret == -EINVAL ) {
+        clear = INREG( RADEON_LAST_CLEAR_REG );
+        ret = 0;
+      }
+#endif
+      if ( ret ) {
+        fprintf( stderr, "%s: drmRadeonGetParam: %d\n", __FUNCTION__, ret );
+        exit(1);
+      }
+      if ( RADEON_DEBUG & DEBUG_IOCTL ) {
+        fprintf( stderr, "%s( %d )\n", __FUNCTION__, (int)clear );
+        if ( ret ) fprintf( stderr, " ( RADEON_LAST_CLEAR register read directly )\n" );
+      }
+
+      if ( sarea->last_clear - clear <= RADEON_MAX_CLEARS ) {
+        break;
+      }
+
+      if ( rmesa->do_usleeps ) {
+        UNLOCK_HARDWARE( rmesa );
+        DO_USLEEP( 1 );
+        LOCK_HARDWARE( rmesa );
+      }
+   }
+
+   for ( i = 0 ; i < dPriv->numClipRects ; ) {
+      GLint nr = MIN2( i + RADEON_NR_SAREA_CLIPRECTS, dPriv->numClipRects );
+      XF86DRIClipRectPtr box = dPriv->pClipRects;
+      XF86DRIClipRectPtr b = rmesa->sarea->boxes;
+      drmRadeonClearType clear;
+      drmRadeonClearRect depth_boxes[RADEON_NR_SAREA_CLIPRECTS];
+      GLint n = 0;
+
+      if ( !all ) {
+        for ( ; i < nr ; i++ ) {
+           GLint x = box[i].x1;
+           GLint y = box[i].y1;
+           GLint w = box[i].x2 - x;
+           GLint h = box[i].y2 - y;
+
+           if ( x < cx ) w -= cx - x, x = cx;
+           if ( y < cy ) h -= cy - y, y = cy;
+           if ( x + w > cx + cw ) w = cx + cw - x;
+           if ( y + h > cy + ch ) h = cy + ch - y;
+           if ( w <= 0 ) continue;
+           if ( h <= 0 ) continue;
+
+           b->x1 = x;
+           b->y1 = y;
+           b->x2 = x + w;
+           b->y2 = y + h;
+           b++;
+           n++;
+        }
+      } else {
+        for ( ; i < nr ; i++ ) {
+           *b++ = box[i];
+           n++;
+        }
+      }
+
+      rmesa->sarea->nbox = n;
+
+      clear.flags       = flags;
+      clear.clear_color = rmesa->state.color.clear;
+      clear.clear_depth = rmesa->state.depth.clear;
+      clear.color_mask  = rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK];
+      clear.depth_mask  = rmesa->state.stencil.clear;
+      clear.depth_boxes = depth_boxes;
+
+      n--;
+      b = rmesa->sarea->boxes;
+      for ( ; n >= 0 ; n-- ) {
+        depth_boxes[n].f[RADEON_CLEAR_X1] = (float)b[n].x1;
+        depth_boxes[n].f[RADEON_CLEAR_Y1] = (float)b[n].y1;
+        depth_boxes[n].f[RADEON_CLEAR_X2] = (float)b[n].x2;
+        depth_boxes[n].f[RADEON_CLEAR_Y2] = (float)b[n].y2;
+        depth_boxes[n].f[RADEON_CLEAR_DEPTH] = 
+           (float)rmesa->state.depth.clear;
+      }
+
+      ret = drmCommandWrite( rmesa->dri.fd, DRM_RADEON_CLEAR,
+                            &clear, sizeof(drmRadeonClearType));
+
+      if ( ret ) {
+        UNLOCK_HARDWARE( rmesa );
+        fprintf( stderr, "DRM_RADEON_CLEAR: return = %d\n", ret );
+        exit( 1 );
+      }
+   }
+
+   UNLOCK_HARDWARE( rmesa );
+}
+
+
+void radeonWaitForIdleLocked( radeonContextPtr rmesa )
+{
+    int fd = rmesa->dri.fd;
+    int to = 0;
+    int ret, i = 0;
+
+    rmesa->c_drawWaits++;
+
+    do {
+        do {
+            ret = drmCommandNone( fd, DRM_RADEON_CP_IDLE);
+        } while ( ret && errno == EBUSY && i++ < RADEON_IDLE_RETRY );
+    } while ( ( ret == -EBUSY ) && ( to++ < RADEON_TIMEOUT ) );
+
+    if ( ret < 0 ) {
+       UNLOCK_HARDWARE( rmesa );
+       fprintf( stderr, "Error: Radeon timed out... exiting\n" );
+       exit( -1 );
+    }
+}
+
+
+static void radeonWaitForIdle( radeonContextPtr rmesa )
+{
+   LOCK_HARDWARE(rmesa);
+   radeonWaitForIdleLocked( rmesa );
+   UNLOCK_HARDWARE(rmesa);
+}
+
+
+void radeonFlush( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+
+   if (RADEON_DEBUG & DEBUG_IOCTL)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   if (rmesa->dma.flush)
+      rmesa->dma.flush( rmesa );
+
+   if (rmesa->dri.drmMinor >= 3) {
+      if (!is_empty_list(&rmesa->hw.dirty)) 
+        radeonEmitState( rmesa );
+   
+      if (rmesa->store.cmd_used)
+        radeonFlushCmdBuf( rmesa, __FUNCTION__ );
+   }
+}
+
+/* Make sure all commands have been sent to the hardware and have
+ * completed processing.
+ */
+void radeonFinish( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   radeonFlush( ctx );
+
+   if (rmesa->do_irqs) {
+      LOCK_HARDWARE( rmesa );
+      radeonEmitIrqLocked( rmesa );
+      UNLOCK_HARDWARE( rmesa );
+      radeonWaitIrq( rmesa );
+   }
+   else
+      radeonWaitForIdle( rmesa );
+}
+
+
+void radeonInitIoctlFuncs( GLcontext *ctx )
+{
+    ctx->Driver.Clear = radeonClear;
+    ctx->Driver.Finish = radeonFinish;
+    ctx->Driver.Flush = radeonFlush;
+}
+
diff --git a/src/mesa/drivers/dri/radeon/radeon_ioctl.h b/src/mesa/drivers/dri/radeon/radeon_ioctl.h
new file mode 100644 (file)
index 0000000..3f6e175
--- /dev/null
@@ -0,0 +1,188 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_ioctl.h,v 1.6 2002/12/16 16:18:58 dawes Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifndef __RADEON_IOCTL_H__
+#define __RADEON_IOCTL_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include "simple_list.h"
+#include "radeon_lock.h"
+
+
+extern void radeonEmitState( radeonContextPtr rmesa );
+extern void radeonEmitVertexAOS( radeonContextPtr rmesa,
+                                GLuint vertex_size,
+                                GLuint offset );
+
+extern void radeonEmitVbufPrim( radeonContextPtr rmesa,
+                               GLuint vertex_format,
+                               GLuint primitive,
+                               GLuint vertex_nr );
+
+extern void radeonFlushElts( radeonContextPtr rmesa );
+
+extern GLushort *radeonAllocEltsOpenEnded( radeonContextPtr rmesa,
+                                          GLuint vertex_format,
+                                          GLuint primitive,
+                                          GLuint min_nr );
+
+extern void radeonEmitAOS( radeonContextPtr rmesa,
+                          struct radeon_dma_region **regions,
+                          GLuint n,
+                          GLuint offset );
+
+extern void radeonEmitBlit( radeonContextPtr rmesa,
+                           GLuint color_fmt,
+                           GLuint src_pitch,
+                           GLuint src_offset,
+                           GLuint dst_pitch,
+                           GLuint dst_offset,
+                           GLint srcx, GLint srcy,
+                           GLint dstx, GLint dsty,
+                           GLuint w, GLuint h );
+
+extern void radeonEmitWait( radeonContextPtr rmesa, GLuint flags );
+
+extern void radeonFlushCmdBuf( radeonContextPtr rmesa, const char * );
+extern void radeonRefillCurrentDmaRegion( radeonContextPtr rmesa );
+
+extern void radeonAllocDmaRegion( radeonContextPtr rmesa,
+                                 struct radeon_dma_region *region,
+                                 int bytes, 
+                                 int alignment );
+
+extern void radeonAllocDmaRegionVerts( radeonContextPtr rmesa,
+                                      struct radeon_dma_region *region,
+                                      int numverts,
+                                      int vertsize, 
+                                      int alignment );
+
+extern void radeonReleaseDmaRegion( radeonContextPtr rmesa,
+                                   struct radeon_dma_region *region,
+                                   const char *caller );
+
+extern void radeonCopyBuffer( const __DRIdrawablePrivate *drawable );
+extern void radeonPageFlip( const __DRIdrawablePrivate *drawable );
+extern void radeonFlush( GLcontext *ctx );
+extern void radeonFinish( GLcontext *ctx );
+extern void radeonWaitForIdleLocked( radeonContextPtr rmesa );
+extern void radeonWaitForVBlank( radeonContextPtr rmesa );
+extern void radeonInitIoctlFuncs( GLcontext *ctx );
+extern void radeonGetAllParams( radeonContextPtr rmesa );
+
+/* radeon_compat.c:
+ */
+extern void radeonCompatEmitPrimitive( radeonContextPtr rmesa,
+                                      GLuint vertex_format,
+                                      GLuint hw_primitive,
+                                      GLuint nrverts );
+
+
+/* ================================================================
+ * Helper macros:
+ */
+
+/* Close off the last primitive, if it exists.
+ */
+#define RADEON_NEWPRIM( rmesa )                        \
+do {                                           \
+   if ( rmesa->dma.flush )                     \
+      rmesa->dma.flush( rmesa );       \
+} while (0)
+
+/* Can accomodate several state changes and primitive changes without
+ * actually firing the buffer.
+ */
+#define RADEON_STATECHANGE( rmesa, ATOM )                      \
+do {                                                           \
+   RADEON_NEWPRIM( rmesa );                                    \
+   move_to_head( &(rmesa->hw.dirty), &(rmesa->hw.ATOM));       \
+} while (0)
+
+#define RADEON_DB_STATE( ATOM )                                \
+   memcpy( rmesa->hw.ATOM.lastcmd, rmesa->hw.ATOM.cmd, \
+          rmesa->hw.ATOM.cmd_size * 4)
+
+static __inline int RADEON_DB_STATECHANGE( 
+   radeonContextPtr rmesa,
+   struct radeon_state_atom *atom )
+{
+   if (memcmp(atom->cmd, atom->lastcmd, atom->cmd_size*4)) {
+      int *tmp;
+      RADEON_NEWPRIM( rmesa );
+      move_to_head( &(rmesa->hw.dirty), atom );
+      tmp = atom->cmd; 
+      atom->cmd = atom->lastcmd;
+      atom->lastcmd = tmp;
+      return 1;
+   }
+   else
+      return 0;
+}
+
+
+/* Fire the buffered vertices no matter what.
+ */
+#define RADEON_FIREVERTICES( rmesa )                   \
+do {                                                   \
+   if ( rmesa->store.cmd_used || rmesa->dma.flush ) {  \
+      radeonFlush( rmesa->glCtx );                     \
+   }                                                   \
+} while (0)
+
+/* Alloc space in the command buffer
+ */
+static __inline char *radeonAllocCmdBuf( radeonContextPtr rmesa,
+                                        int bytes, const char *where )
+{
+   if (rmesa->store.cmd_used + bytes > RADEON_CMD_BUF_SZ)
+      radeonFlushCmdBuf( rmesa, __FUNCTION__ );
+   
+   assert(rmesa->dri.drmMinor >= 3);
+
+   {
+      char *head = rmesa->store.cmd_buf + rmesa->store.cmd_used;
+      rmesa->store.cmd_used += bytes;
+      return head;
+   }
+}
+
+
+
+
+#endif
+#endif /* __RADEON_IOCTL_H__ */
diff --git a/src/mesa/drivers/dri/radeon/radeon_lighting.c b/src/mesa/drivers/dri/radeon/radeon_lighting.c
new file mode 100644 (file)
index 0000000..b00c9cb
--- /dev/null
@@ -0,0 +1,682 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_state.c,v 1.5 2002/09/16 18:05:20 eich Exp $ */
+/*
+ * Copyright 2000, 2001 VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "api_arrayelt.h"
+/* #include "mmath.h" */
+#include "enums.h"
+#include "colormac.h"
+
+
+#include "radeon_context.h"
+#include "radeon_ioctl.h"
+#include "radeon_state.h"
+#include "radeon_tcl.h"
+#include "radeon_tex.h"
+#include "radeon_vtxfmt.h"
+
+
+
+/* =============================================================
+ * Materials
+ */
+
+
+/* Update on colormaterial, material emmissive/ambient, 
+ * lightmodel.globalambient
+ */
+void update_global_ambient( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   float *fcmd = (float *)RADEON_DB_STATE( glt );
+
+   /* Need to do more if both emmissive & ambient are PREMULT:
+    */
+   if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &
+       ((3 << RADEON_EMISSIVE_SOURCE_SHIFT) |
+       (3 << RADEON_AMBIENT_SOURCE_SHIFT))) == 0) 
+   {
+      COPY_3V( &fcmd[GLT_RED], 
+              ctx->Light.Material[0].Emission);
+      ACC_SCALE_3V( &fcmd[GLT_RED],
+                  ctx->Light.Model.Ambient,
+                  ctx->Light.Material[0].Ambient);
+   } 
+   else
+   {
+      COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient );
+   }
+   
+   RADEON_DB_STATECHANGE(rmesa, &rmesa->hw.glt);
+}
+
+/* Update on change to 
+ *    - light[p].colors
+ *    - light[p].enabled
+ *    - material,
+ *    - colormaterial enabled
+ *    - colormaterial bitmask
+ */
+void update_light_colors( GLcontext *ctx, GLuint p )
+{
+   struct gl_light *l = &ctx->Light.Light[p];
+
+/*     fprintf(stderr, "%s\n", __FUNCTION__); */
+
+   if (l->Enabled) {
+      radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+      float *fcmd = (float *)RADEON_DB_STATE( lit[p] );
+      GLuint bitmask = ctx->Light.ColorMaterialBitmask;
+      struct gl_material *mat = &ctx->Light.Material[0];
+
+      COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient );    
+      COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse );
+      COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular );
+      
+      if (!ctx->Light.ColorMaterialEnabled)
+        bitmask = 0;
+
+      if ((bitmask & FRONT_AMBIENT_BIT) == 0) 
+        SELF_SCALE_3V( &fcmd[LIT_AMBIENT_RED], mat->Ambient );
+
+      if ((bitmask & FRONT_DIFFUSE_BIT) == 0) 
+        SELF_SCALE_3V( &fcmd[LIT_DIFFUSE_RED], mat->Diffuse );
+      
+      if ((bitmask & FRONT_SPECULAR_BIT) == 0) 
+        SELF_SCALE_3V( &fcmd[LIT_SPECULAR_RED], mat->Specular );
+
+      RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
+   }
+}
+
+/* Also fallback for asym colormaterial mode in twoside lighting...
+ */
+void check_twoside_fallback( GLcontext *ctx )
+{
+   GLboolean fallback = GL_FALSE;
+
+   if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) {
+      if (memcmp( &ctx->Light.Material[0],
+                 &ctx->Light.Material[1],
+                 sizeof(struct gl_material)) != 0)
+        fallback = GL_TRUE;  
+      else if (ctx->Light.ColorMaterialEnabled &&
+              (ctx->Light.ColorMaterialBitmask & BACK_MATERIAL_BITS) != 
+              ((ctx->Light.ColorMaterialBitmask & FRONT_MATERIAL_BITS)<<1))
+        fallback = GL_TRUE;
+   }
+
+   TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_LIGHT_TWOSIDE, fallback );
+}
+
+void radeonColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
+{
+   if (ctx->Light.ColorMaterialEnabled) {
+      radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+      GLuint light_model_ctl = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL];
+      GLuint mask = ctx->Light.ColorMaterialBitmask;
+
+      /* Default to PREMULT:
+       */
+      light_model_ctl &= ~((3 << RADEON_EMISSIVE_SOURCE_SHIFT) |
+                          (3 << RADEON_AMBIENT_SOURCE_SHIFT) |
+                          (3 << RADEON_DIFFUSE_SOURCE_SHIFT) |
+                          (3 << RADEON_SPECULAR_SOURCE_SHIFT)); 
+   
+      if (mask & FRONT_EMISSION_BIT) {
+        light_model_ctl |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
+                            RADEON_EMISSIVE_SOURCE_SHIFT);
+      }
+
+      if (mask & FRONT_AMBIENT_BIT) {
+        light_model_ctl |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
+                            RADEON_AMBIENT_SOURCE_SHIFT);
+      }
+        
+      if (mask & FRONT_DIFFUSE_BIT) {
+        light_model_ctl |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
+                            RADEON_DIFFUSE_SOURCE_SHIFT);
+      }
+   
+      if (mask & FRONT_SPECULAR_BIT) {
+        light_model_ctl |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
+                            RADEON_SPECULAR_SOURCE_SHIFT);
+      }
+   
+      if (light_model_ctl != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]) {
+        GLuint p;
+
+        RADEON_STATECHANGE( rmesa, tcl );
+        rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = light_model_ctl;      
+
+        for (p = 0 ; p < MAX_LIGHTS; p++) 
+           update_light_colors( ctx, p );
+        update_global_ambient( ctx );
+      }
+   }
+   
+   check_twoside_fallback( ctx );
+}
+
+void radeonUpdateMaterial( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( mtl );
+   GLuint p;
+   GLuint mask = ~0;
+   
+   if (ctx->Light.ColorMaterialEnabled)
+      mask &= ~ctx->Light.ColorMaterialBitmask;
+
+   if (RADEON_DEBUG & DEBUG_STATE)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+      
+   if (mask & FRONT_EMISSION_BIT) {
+      fcmd[MTL_EMMISSIVE_RED]   = ctx->Light.Material[0].Emission[0];
+      fcmd[MTL_EMMISSIVE_GREEN] = ctx->Light.Material[0].Emission[1];
+      fcmd[MTL_EMMISSIVE_BLUE]  = ctx->Light.Material[0].Emission[2];
+      fcmd[MTL_EMMISSIVE_ALPHA] = ctx->Light.Material[0].Emission[3];
+   }
+   if (mask & FRONT_AMBIENT_BIT) {
+      fcmd[MTL_AMBIENT_RED]     = ctx->Light.Material[0].Ambient[0];
+      fcmd[MTL_AMBIENT_GREEN]   = ctx->Light.Material[0].Ambient[1];
+      fcmd[MTL_AMBIENT_BLUE]    = ctx->Light.Material[0].Ambient[2];
+      fcmd[MTL_AMBIENT_ALPHA]   = ctx->Light.Material[0].Ambient[3];
+   }
+   if (mask & FRONT_DIFFUSE_BIT) {
+      fcmd[MTL_DIFFUSE_RED]     = ctx->Light.Material[0].Diffuse[0];
+      fcmd[MTL_DIFFUSE_GREEN]   = ctx->Light.Material[0].Diffuse[1];
+      fcmd[MTL_DIFFUSE_BLUE]    = ctx->Light.Material[0].Diffuse[2];
+      fcmd[MTL_DIFFUSE_ALPHA]   = ctx->Light.Material[0].Diffuse[3];
+   }
+   if (mask & FRONT_SPECULAR_BIT) {
+      fcmd[MTL_SPECULAR_RED]    = ctx->Light.Material[0].Specular[0];
+      fcmd[MTL_SPECULAR_GREEN]  = ctx->Light.Material[0].Specular[1];
+      fcmd[MTL_SPECULAR_BLUE]   = ctx->Light.Material[0].Specular[2];
+      fcmd[MTL_SPECULAR_ALPHA]  = ctx->Light.Material[0].Specular[3];
+   }
+   if (mask & FRONT_SHININESS_BIT) {
+      fcmd[MTL_SHININESS]       = ctx->Light.Material[0].Shininess;
+   }
+
+   if (RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mtl )) {
+      for (p = 0 ; p < MAX_LIGHTS; p++) 
+        update_light_colors( ctx, p );
+
+      check_twoside_fallback( ctx );
+      update_global_ambient( ctx );
+   }
+   else if (RADEON_DEBUG & (DEBUG_PRIMS|DEBUG_STATE))
+      fprintf(stderr, "%s: Elided noop material call\n", __FUNCTION__);
+}
+
+/* _NEW_LIGHT
+ * _NEW_MODELVIEW
+ * _MESA_NEW_NEED_EYE_COORDS
+ *
+ * Uses derived state from mesa:
+ *       _VP_inf_norm
+ *       _h_inf_norm
+ *       _Position
+ *       _NormDirection
+ *       _ModelViewInvScale
+ *       _NeedEyeCoords
+ *       _EyeZDir
+ *
+ * which are calculated in light.c and are correct for the current
+ * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
+ * and _MESA_NEW_NEED_EYE_COORDS.  
+ */
+void radeonUpdateLighting( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   /* Have to check these, or have an automatic shortcircuit mechanism
+    * to remove noop statechanges. (Or just do a better job on the
+    * front end).
+    */
+   {
+      GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL];
+
+      if (ctx->_NeedEyeCoords)
+        tmp &= ~RADEON_LIGHT_IN_MODELSPACE;
+      else
+        tmp |= RADEON_LIGHT_IN_MODELSPACE;
+      
+
+      /* Leave this test disabled: (unexplained q3 lockup) (even with
+         new packets)
+      */
+      if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]) 
+      {
+        RADEON_STATECHANGE( rmesa, tcl );
+        rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = tmp;
+      }
+   }
+
+   {
+      GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( eye );
+      fcmd[EYE_X] = ctx->_EyeZDir[0];
+      fcmd[EYE_Y] = ctx->_EyeZDir[1];
+      fcmd[EYE_Z] = - ctx->_EyeZDir[2];
+      fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale;
+      RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.eye );
+   }
+
+
+/*     RADEON_STATECHANGE( rmesa, glt ); */
+
+   if (ctx->Light.Enabled) {
+      GLint p;
+      for (p = 0 ; p < MAX_LIGHTS; p++) {
+        if (ctx->Light.Light[p].Enabled) {
+           struct gl_light *l = &ctx->Light.Light[p];
+           GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( lit[p] );
+           
+           if (l->EyePosition[3] == 0.0) {
+              COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm ); 
+              COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm ); 
+              fcmd[LIT_POSITION_W] = 0;
+              fcmd[LIT_DIRECTION_W] = 0;
+           } else {
+              COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
+              fcmd[LIT_DIRECTION_X] = -l->_NormDirection[0];
+              fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1];
+              fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[2];
+              fcmd[LIT_DIRECTION_W] = 0;
+           }
+
+           RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
+        }
+      }
+   }
+}
+
+
+void radeonLightfv( GLcontext *ctx, GLenum light,
+                   GLenum pname, const GLfloat *params )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLint p = light - GL_LIGHT0;
+   struct gl_light *l = &ctx->Light.Light[p];
+   GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
+   
+
+   switch (pname) {
+   case GL_AMBIENT:            
+   case GL_DIFFUSE:
+   case GL_SPECULAR:
+      update_light_colors( ctx, p );
+      break;
+
+   case GL_SPOT_DIRECTION: 
+      /* picked up in update_light */  
+      break;
+
+   case GL_POSITION: {
+      /* positions picked up in update_light, but can do flag here */  
+      GLuint flag = (p&1)? RADEON_LIGHT_1_IS_LOCAL : RADEON_LIGHT_0_IS_LOCAL;
+      GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
+
+      RADEON_STATECHANGE(rmesa, tcl);
+      if (l->EyePosition[3] != 0.0F)
+        rmesa->hw.tcl.cmd[idx] |= flag;
+      else
+        rmesa->hw.tcl.cmd[idx] &= ~flag;
+      break;
+   }
+
+   case GL_SPOT_EXPONENT:
+      RADEON_STATECHANGE(rmesa, lit[p]);
+      fcmd[LIT_SPOT_EXPONENT] = params[0];
+      break;
+
+   case GL_SPOT_CUTOFF: {
+      GLuint flag = (p&1) ? RADEON_LIGHT_1_IS_SPOT : RADEON_LIGHT_0_IS_SPOT;
+      GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
+
+      RADEON_STATECHANGE(rmesa, lit[p]);
+      fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff;
+
+      RADEON_STATECHANGE(rmesa, tcl);
+      if (l->SpotCutoff != 180.0F)
+        rmesa->hw.tcl.cmd[idx] |= flag;
+      else
+        rmesa->hw.tcl.cmd[idx] &= ~flag;
+      break;
+   }
+
+   case GL_CONSTANT_ATTENUATION:
+      RADEON_STATECHANGE(rmesa, lit[p]);
+      fcmd[LIT_ATTEN_CONST] = params[0];
+      break;
+   case GL_LINEAR_ATTENUATION:
+      RADEON_STATECHANGE(rmesa, lit[p]);
+      fcmd[LIT_ATTEN_LINEAR] = params[0];
+      break;
+   case GL_QUADRATIC_ATTENUATION:
+      RADEON_STATECHANGE(rmesa, lit[p]);
+      fcmd[LIT_ATTEN_QUADRATIC] = params[0];
+      break;
+   default:
+      return;
+   }
+
+}
+
+                 
+
+
+void radeonLightModelfv( GLcontext *ctx, GLenum pname,
+                        const GLfloat *param )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   switch (pname) {
+      case GL_LIGHT_MODEL_AMBIENT: 
+        update_global_ambient( ctx );
+        break;
+
+      case GL_LIGHT_MODEL_LOCAL_VIEWER:
+        RADEON_STATECHANGE( rmesa, tcl );
+        if (ctx->Light.Model.LocalViewer)
+           rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LOCAL_VIEWER;
+        else
+           rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LOCAL_VIEWER;
+         break;
+
+      case GL_LIGHT_MODEL_TWO_SIDE:
+        RADEON_STATECHANGE( rmesa, tcl );
+        if (ctx->Light.Model.TwoSide)
+           rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_LIGHT_TWOSIDE;
+        else
+           rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_LIGHT_TWOSIDE;
+
+        check_twoside_fallback( ctx );
+
+#if _HAVE_SWTNL
+        if (rmesa->TclFallback) {
+           radeonChooseRenderState( ctx );
+           radeonChooseVertexState( ctx );
+        }
+#endif
+         break;
+
+      case GL_LIGHT_MODEL_COLOR_CONTROL:
+        radeonUpdateSpecular(ctx);
+
+        RADEON_STATECHANGE( rmesa, tcl );
+        if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) 
+           rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= 
+              ~RADEON_DIFFUSE_SPECULAR_COMBINE;
+        else
+           rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= 
+              RADEON_DIFFUSE_SPECULAR_COMBINE;
+         break;
+
+      default:
+         break;
+   }
+}
+
+
+/* =============================================================
+ * Fog
+ */
+
+
+static void radeonFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   union { int i; float f; } c, d;
+   GLchan col[4];
+
+   c.i = rmesa->hw.fog.cmd[FOG_C];
+   d.i = rmesa->hw.fog.cmd[FOG_D];
+
+   switch (pname) {
+   case GL_FOG_MODE:
+      if (!ctx->Fog.Enabled)
+        return;
+      RADEON_STATECHANGE(rmesa, tcl);
+      rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK;
+      switch (ctx->Fog.Mode) {
+      case GL_LINEAR:
+        rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_LINEAR;
+        if (ctx->Fog.Start == ctx->Fog.End) {
+           c.f = 1.0F;
+           d.f = 1.0F;
+        }
+        else {
+           c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
+           d.f = 1.0/(ctx->Fog.End-ctx->Fog.Start);
+        }
+        break;
+      case GL_EXP:
+        rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP;
+        c.f = 0.0;
+        d.f = ctx->Fog.Density;
+        break;
+      case GL_EXP2:
+        rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP2;
+        c.f = 0.0;
+        d.f = -(ctx->Fog.Density * ctx->Fog.Density);
+        break;
+      default:
+        return;
+      }
+      break;
+   case GL_FOG_DENSITY:
+      switch (ctx->Fog.Mode) {
+      case GL_EXP:
+        c.f = 0.0;
+        d.f = ctx->Fog.Density;
+        break;
+      case GL_EXP2:
+        c.f = 0.0;
+        d.f = -(ctx->Fog.Density * ctx->Fog.Density);
+        break;
+      default:
+        break;
+      }
+      break;
+   case GL_FOG_START:
+   case GL_FOG_END:
+      if (ctx->Fog.Mode == GL_LINEAR) {
+        if (ctx->Fog.Start == ctx->Fog.End) {
+           c.f = 1.0F;
+           d.f = 1.0F;
+        } else {
+           c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
+           d.f = 1.0/(ctx->Fog.End-ctx->Fog.Start);
+        }
+      }
+      break;
+   case GL_FOG_COLOR: 
+      RADEON_STATECHANGE( rmesa, ctx );
+      UNCLAMPED_FLOAT_TO_RGB_CHAN( col, ctx->Fog.Color );
+      rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] =
+        radeonPackColor( 4, col[0], col[1], col[2], 0 );
+      break;
+   case GL_FOG_COORDINATE_SOURCE_EXT: 
+      /* What to do?
+       */
+      break;
+   default:
+      return;
+   }
+
+   if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) {
+      RADEON_STATECHANGE( rmesa, fog );
+      rmesa->hw.fog.cmd[FOG_C] = c.i;
+      rmesa->hw.fog.cmd[FOG_D] = d.i;
+   }
+}
+
+/* Examine lighting and texture state to determine if separate specular
+ * should be enabled.
+ */
+void radeonUpdateSpecular( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLuint p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
+
+   if ( ctx->_TriangleCaps & DD_SEPARATE_SPECULAR ) {
+      p |=  RADEON_SPECULAR_ENABLE;
+   } else {
+      p &= ~RADEON_SPECULAR_ENABLE;
+   }
+
+   if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) {
+      RADEON_STATECHANGE( rmesa, ctx );
+      rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p;
+   }
+
+   /* Bizzare: have to leave lighting enabled to get fog.
+    */
+   RADEON_STATECHANGE( rmesa, tcl );
+   if ((ctx->Light.Enabled &&
+       ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) {
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE;
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
+      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
+   }
+   else if (ctx->Fog.Enabled) {
+      if (ctx->Light.Enabled) {
+        rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
+        rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE;
+        rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
+        rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
+        rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
+      } else {
+        rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
+        rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_DIFFUSE;
+        rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
+        rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
+        rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
+      }
+   }
+   else if (ctx->Light.Enabled) {
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_SPECULAR;
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE;
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~RADEON_TCL_VTX_PK_SPEC;
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
+      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
+   } else if (ctx->Fog.ColorSumEnabled ) {
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_SPECULAR;
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_DIFFUSE;
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
+      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LIGHTING_ENABLE;
+   } else {
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_SPECULAR;
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_DIFFUSE;
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~RADEON_TCL_VTX_PK_SPEC;
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
+      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LIGHTING_ENABLE;
+   }
+
+#if _HAVE_SWTNL
+   /* Update vertex/render formats
+    */
+   if (rmesa->TclFallback) { 
+      radeonChooseRenderState( ctx );
+      radeonChooseVertexState( ctx );
+   }
+#endif
+}
+
+
+
+static void radeonLightingSpaceChange( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLboolean tmp;
+   RADEON_STATECHANGE( rmesa, tcl );
+
+   if (RADEON_DEBUG & DEBUG_STATE)
+      fprintf(stderr, "%s %d\n", __FUNCTION__, ctx->_NeedEyeCoords);
+
+   if (ctx->_NeedEyeCoords)
+      tmp = ctx->Transform.RescaleNormals;
+   else
+      tmp = !ctx->Transform.RescaleNormals;
+
+   if ( tmp ) {
+      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |=  RADEON_RESCALE_NORMALS;
+   } else {
+      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS;
+   }
+}
+
+void radeonInitLightStateFuncs( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   int i;
+
+   ctx->Driver.LightModelfv            = radeonLightModelfv; 
+   ctx->Driver.Lightfv                 = radeonLightfv; 
+   ctx->Driver.Fogfv                   = radeonFogfv;
+   ctx->Driver.LightingSpaceChange      = radeonLightingSpaceChange;
+
+   for (i = 0 ; i < 8; i++) {
+      struct gl_light *l = &ctx->Light.Light[i];
+      GLenum p = GL_LIGHT0 + i;
+      *(float *)&(rmesa->hw.lit[i].cmd[LIT_RANGE_CUTOFF]) = FLT_MAX;
+
+      ctx->Driver.Lightfv( ctx, p, GL_AMBIENT, l->Ambient );
+      ctx->Driver.Lightfv( ctx, p, GL_DIFFUSE, l->Diffuse );
+      ctx->Driver.Lightfv( ctx, p, GL_SPECULAR, l->Specular );
+      ctx->Driver.Lightfv( ctx, p, GL_POSITION, 0 );
+      ctx->Driver.Lightfv( ctx, p, GL_SPOT_DIRECTION, 0 );
+      ctx->Driver.Lightfv( ctx, p, GL_SPOT_EXPONENT, &l->SpotExponent );
+      ctx->Driver.Lightfv( ctx, p, GL_SPOT_CUTOFF, &l->SpotCutoff );
+      ctx->Driver.Lightfv( ctx, p, GL_CONSTANT_ATTENUATION,
+                          &l->ConstantAttenuation );
+      ctx->Driver.Lightfv( ctx, p, GL_LINEAR_ATTENUATION, 
+                          &l->LinearAttenuation );
+      ctx->Driver.Lightfv( ctx, p, GL_QUADRATIC_ATTENUATION, 
+                    &l->QuadraticAttenuation );
+   }
+
+   ctx->Driver.LightModelfv( ctx, GL_LIGHT_MODEL_AMBIENT, 
+                            ctx->Light.Model.Ambient );
+
+   ctx->Driver.Fogfv( ctx, GL_FOG_MODE, 0 );
+   ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density );
+   ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start );
+   ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End );
+   ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color );
+   ctx->Driver.Fogfv( ctx, GL_FOG_COORDINATE_SOURCE_EXT, 0 );
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_lock.c b/src/mesa/drivers/dri/radeon/radeon_lock.c
new file mode 100644 (file)
index 0000000..96a4f9d
--- /dev/null
@@ -0,0 +1,128 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_lock.c,v 1.5 2002/10/30 12:51:55 alanh Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Gareth Hughes <gareth@valinux.com>
+ */
+
+#include "glheader.h"
+#include "radeon_context.h"
+#include "radeon_lock.h"
+#include "radeon_tex.h"
+#include "radeon_state.h"
+#include "radeon_ioctl.h"
+
+#if DEBUG_LOCKING
+char *prevLockFile = NULL;
+int prevLockLine = 0;
+#endif
+
+/* Turn on/off page flipping according to the flags in the sarea:
+ */
+static void
+radeonUpdatePageFlipping( radeonContextPtr rmesa )
+{
+   int use_back;
+
+   if (rmesa->dri.drmMinor < 3)
+      return;
+
+   rmesa->doPageFlip = rmesa->sarea->pfAllowPageFlip;
+
+   use_back = (rmesa->glCtx->Color._DrawDestMask == BACK_LEFT_BIT);
+   use_back ^= (rmesa->sarea->pfCurrentPage == 1);
+
+   if ( RADEON_DEBUG & DEBUG_VERBOSE )
+      fprintf(stderr, "%s allow %d current %d\n", __FUNCTION__, 
+             rmesa->doPageFlip,
+             rmesa->sarea->pfCurrentPage );
+
+   if ( use_back ) {
+        rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset;
+        rmesa->state.color.drawPitch  = rmesa->radeonScreen->backPitch;
+   } else {
+        rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset;
+        rmesa->state.color.drawPitch  = rmesa->radeonScreen->frontPitch;
+   }
+
+   RADEON_STATECHANGE( rmesa, ctx );
+   rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = rmesa->state.color.drawOffset;
+   rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH]  = rmesa->state.color.drawPitch;
+}
+
+
+
+/* Update the hardware state.  This is called if another context has
+ * grabbed the hardware lock, which includes the X server.  This
+ * function also updates the driver's window state after the X server
+ * moves, resizes or restacks a window -- the change will be reflected
+ * in the drawable position and clip rects.  Since the X server grabs
+ * the hardware lock when it changes the window state, this routine will
+ * automatically be called after such a change.
+ */
+void radeonGetLock( radeonContextPtr rmesa, GLuint flags )
+{
+   __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
+   __DRIscreenPrivate *sPriv = rmesa->dri.screen;
+   RADEONSAREAPrivPtr sarea = rmesa->sarea;
+
+   drmGetLock( rmesa->dri.fd, rmesa->dri.hwContext, flags );
+
+   /* The window might have moved, so we might need to get new clip
+    * rects.
+    *
+    * NOTE: This releases and regrabs the hw lock to allow the X server
+    * to respond to the DRI protocol request for new drawable info.
+    * Since the hardware state depends on having the latest drawable
+    * clip rects, all state checking must be done _after_ this call.
+    */
+   DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv );
+
+   if ( rmesa->lastStamp != dPriv->lastStamp ) {
+      radeonUpdatePageFlipping( rmesa );
+      if (rmesa->glCtx->Color._DrawDestMask == BACK_LEFT_BIT)
+         radeonSetCliprects( rmesa, GL_BACK_LEFT );
+      else
+         radeonSetCliprects( rmesa, GL_FRONT_LEFT );
+      radeonUpdateViewportOffset( rmesa->glCtx );
+      rmesa->lastStamp = dPriv->lastStamp;
+   }
+
+   if ( sarea->ctxOwner != rmesa->dri.hwContext ) {
+      int i;
+      sarea->ctxOwner = rmesa->dri.hwContext;
+
+      for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
+        DRI_AGE_TEXTURES( rmesa->texture_heaps[ i ] );
+      }
+   }
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_lock.h b/src/mesa/drivers/dri/radeon/radeon_lock.h
new file mode 100644 (file)
index 0000000..783db7e
--- /dev/null
@@ -0,0 +1,113 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_lock.h,v 1.3 2002/10/30 12:51:55 alanh Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifndef __RADEON_LOCK_H__
+#define __RADEON_LOCK_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+extern void radeonGetLock( radeonContextPtr rmesa, GLuint flags );
+
+/* Turn DEBUG_LOCKING on to find locking conflicts.
+ */
+#define DEBUG_LOCKING  0
+
+#if DEBUG_LOCKING
+extern char *prevLockFile;
+extern int prevLockLine;
+
+#define DEBUG_LOCK()                                                   \
+   do {                                                                        \
+      prevLockFile = (__FILE__);                                       \
+      prevLockLine = (__LINE__);                                       \
+   } while (0)
+
+#define DEBUG_RESET()                                                  \
+   do {                                                                        \
+      prevLockFile = 0;                                                        \
+      prevLockLine = 0;                                                        \
+   } while (0)
+
+#define DEBUG_CHECK_LOCK()                                             \
+   do {                                                                        \
+      if ( prevLockFile ) {                                            \
+        fprintf( stderr,                                               \
+                 "LOCK SET!\n\tPrevious %s:%d\n\tCurrent: %s:%d\n",    \
+                 prevLockFile, prevLockLine, __FILE__, __LINE__ );     \
+        exit( 1 );                                                     \
+      }                                                                        \
+   } while (0)
+
+#else
+
+#define DEBUG_LOCK()
+#define DEBUG_RESET()
+#define DEBUG_CHECK_LOCK()
+
+#endif
+
+/*
+ * !!! We may want to separate locks from locks with validation.  This
+ * could be used to improve performance for those things commands that
+ * do not do any drawing !!!
+ */
+
+
+/* Lock the hardware and validate our state.
+ */
+#define LOCK_HARDWARE( rmesa )                                 \
+   do {                                                                \
+      char __ret = 0;                                          \
+      DEBUG_CHECK_LOCK();                                      \
+      DRM_CAS( rmesa->dri.hwLock, rmesa->dri.hwContext,                \
+              (DRM_LOCK_HELD | rmesa->dri.hwContext), __ret ); \
+      if ( __ret )                                             \
+        radeonGetLock( rmesa, 0 );                             \
+      DEBUG_LOCK();                                            \
+   } while (0)
+
+/* Unlock the hardware.
+ */
+#define UNLOCK_HARDWARE( rmesa )                                       \
+   do {                                                                        \
+      DRM_UNLOCK( rmesa->dri.fd,                                       \
+                 rmesa->dri.hwLock,                                    \
+                 rmesa->dri.hwContext );                               \
+      DEBUG_RESET();                                                   \
+   } while (0)
+
+#endif
+#endif /* __RADEON_LOCK_H__ */
diff --git a/src/mesa/drivers/dri/radeon/radeon_maos.c b/src/mesa/drivers/dri/radeon/radeon_maos.c
new file mode 100644 (file)
index 0000000..c62edd7
--- /dev/null
@@ -0,0 +1,12 @@
+
+
+/* If using new packets, can choose either verts or arrays.
+ * Otherwise, must use verts.
+ */
+#include "radeon_context.h"
+#define RADEON_MAOS_VERTS 1
+#if (RADEON_MAOS_VERTS) || (RADEON_OLD_PACKETS)
+#include "radeon_maos_verts.c"
+#else
+#include "radeon_maos_arrays.c"
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_maos.h b/src/mesa/drivers/dri/radeon/radeon_maos.h
new file mode 100644 (file)
index 0000000..7e2bd64
--- /dev/null
@@ -0,0 +1,47 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     Tungsten Grahpics Inc., Austin, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef __RADEON_MAOS_H__
+#define __RADEON_MAOS_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include "radeon_context.h"
+
+extern void radeonEmitArrays( GLcontext *ctx, GLuint inputs );
+extern void radeonReleaseArrays( GLcontext *ctx, GLuint newinputs );
+
+#endif
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_maos_arrays.c b/src/mesa/drivers/dri/radeon/radeon_maos_arrays.c
new file mode 100644 (file)
index 0000000..cec05a8
--- /dev/null
@@ -0,0 +1,591 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "mtypes.h"
+#include "mmath.h"
+#include "macros.h"
+
+#include "swrast_setup/swrast_setup.h"
+#include "math/m_translate.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_imm_debug.h"
+
+#include "radeon_context.h"
+#include "radeon_ioctl.h"
+#include "radeon_state.h"
+#include "radeon_swtcl.h"
+#include "radeon_maos.h"
+
+/* Usage:
+ *   - from radeon_tcl_render
+ *   - call radeonEmitArrays to ensure uptodate arrays in dma
+ *   - emit primitives (new type?) which reference the data
+ *       -- need to use elts for lineloop, quads, quadstrip/flat
+ *       -- other primitives are all well-formed (need tristrip-1,fake-poly)
+ *
+ */
+static void emit_ubyte_rgba3( GLcontext *ctx,
+                      struct radeon_dma_region *rvb,
+                      char *data,
+                      int stride,
+                      int count )
+{
+   int i;
+   radeon_color_t *out = (radeon_color_t *)(rvb->start + rvb->address);
+
+   if (RADEON_DEBUG & DEBUG_VERTS)
+      fprintf(stderr, "%s count %d stride %d out %p\n",
+             __FUNCTION__, count, stride, out);
+
+   for (i = 0; i < count; i++) {
+      out->red   = *data;
+      out->green = *(data+1);
+      out->blue  = *(data+2);
+      out->alpha = 0xFF;
+      out++;
+      data += stride;
+   }
+}
+
+
+#if defined(USE_X86_ASM)
+#define COPY_DWORDS( dst, src, nr )                                    \
+do {                                                                   \
+       int __tmp;                                                      \
+       __asm__ __volatile__( "rep ; movsl"                             \
+                             : "=%c" (__tmp), "=D" (dst), "=S" (__tmp) \
+                             : "0" (nr),                               \
+                               "D" ((long)dst),                        \
+                               "S" ((long)src) );                      \
+} while (0)
+#else
+#define COPY_DWORDS( dst, src, nr )            \
+do {                                           \
+   int j;                                      \
+   for ( j = 0 ; j < nr ; j++ )                        \
+      dst[j] = ((int *)src)[j];                        \
+   dst += nr;                                  \
+} while (0)
+#endif
+
+
+
+static void emit_ubyte_rgba4( GLcontext *ctx,
+                             struct radeon_dma_region *rvb,
+                             char *data,
+                             int stride,
+                             int count )
+{
+   int i;
+   int *out = (int *)(rvb->address + rvb->start);
+
+   if (RADEON_DEBUG & DEBUG_VERTS)
+      fprintf(stderr, "%s count %d stride %d\n",
+             __FUNCTION__, count, stride);
+
+   if (stride == 4)
+       COPY_DWORDS( out, data, count );
+   else
+      for (i = 0; i < count; i++) {
+        *out++ = LE32_TO_CPU(*(int *)data);
+        data += stride;
+      }
+}
+
+
+static void emit_ubyte_rgba( GLcontext *ctx,
+                            struct radeon_dma_region *rvb,
+                            char *data,
+                            int size,
+                            int stride,
+                            int count )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   if (RADEON_DEBUG & DEBUG_VERTS)
+      fprintf(stderr, "%s %d/%d\n", __FUNCTION__, count, size);
+
+   assert (!rvb->buf);
+
+   if (stride == 0) {
+      radeonAllocDmaRegion( rmesa, rvb, 4, 4 );
+      count = 1;
+      rvb->aos_start = GET_START(rvb);
+      rvb->aos_stride = 0;
+      rvb->aos_size = 1;
+   }
+   else {
+      radeonAllocDmaRegion( rmesa, rvb, 4 * count, 4 );        /* alignment? */
+      rvb->aos_start = GET_START(rvb);
+      rvb->aos_stride = 1;
+      rvb->aos_size = 1;
+   }
+
+   /* Emit the data
+    */
+   switch (size) {
+   case 3:
+      emit_ubyte_rgba3( ctx, rvb, data, stride, count );
+      break;
+   case 4:
+      emit_ubyte_rgba4( ctx, rvb, data, stride, count );
+      break;
+   default:
+      assert(0);
+      exit(1);
+      break;
+   }
+}
+
+
+
+
+static void emit_vec8( GLcontext *ctx,
+                      struct radeon_dma_region *rvb,
+                      char *data,
+                      int stride,
+                      int count )
+{
+   int i;
+   int *out = (int *)(rvb->address + rvb->start);
+
+   if (RADEON_DEBUG & DEBUG_VERTS)
+      fprintf(stderr, "%s count %d stride %d\n",
+             __FUNCTION__, count, stride);
+
+   if (stride == 8)
+      COPY_DWORDS( out, data, count*2 );
+   else
+      for (i = 0; i < count; i++) {
+        out[0] = *(int *)data;
+        out[1] = *(int *)(data+4);
+        out += 2;
+        data += stride;
+      }
+}
+
+static void emit_vec12( GLcontext *ctx,
+                      struct radeon_dma_region *rvb,
+                      char *data,
+                      int stride,
+                      int count )
+{
+   int i;
+   int *out = (int *)(rvb->address + rvb->start);
+
+   if (RADEON_DEBUG & DEBUG_VERTS)
+      fprintf(stderr, "%s count %d stride %d out %p data %p\n",
+             __FUNCTION__, count, stride, out, data);
+
+   if (stride == 12)
+      COPY_DWORDS( out, data, count*3 );
+   else
+      for (i = 0; i < count; i++) {
+        out[0] = *(int *)data;
+        out[1] = *(int *)(data+4);
+        out[2] = *(int *)(data+8);
+        out += 3;
+        data += stride;
+      }
+}
+
+static void emit_vec16( GLcontext *ctx,
+                       struct radeon_dma_region *rvb,
+                       char *data,
+                       int stride,
+                       int count )
+{
+   int i;
+   int *out = (int *)(rvb->address + rvb->start);
+
+   if (RADEON_DEBUG & DEBUG_VERTS)
+      fprintf(stderr, "%s count %d stride %d\n",
+             __FUNCTION__, count, stride);
+
+   if (stride == 16)
+      COPY_DWORDS( out, data, count*4 );
+   else
+      for (i = 0; i < count; i++) {
+        out[0] = *(int *)data;
+        out[1] = *(int *)(data+4);
+        out[2] = *(int *)(data+8);
+        out[3] = *(int *)(data+12);
+        out += 4;
+        data += stride;
+      }
+}
+
+
+static void emit_vector( GLcontext *ctx,
+                        struct radeon_dma_region *rvb,
+                        char *data,
+                        int size,
+                        int stride,
+                        int count )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   if (RADEON_DEBUG & DEBUG_VERTS)
+      fprintf(stderr, "%s count %d size %d stride %d\n",
+             __FUNCTION__, count, size, stride);
+
+   assert (!rvb->buf);
+
+   if (stride == 0) {
+      radeonAllocDmaRegion( rmesa, rvb, size * 4, 4 );
+      count = 1;
+      rvb->aos_start = GET_START(rvb);
+      rvb->aos_stride = 0;
+      rvb->aos_size = size;
+   }
+   else {
+      radeonAllocDmaRegion( rmesa, rvb, size * count * 4, 4 ); /* alignment? */
+      rvb->aos_start = GET_START(rvb);
+      rvb->aos_stride = size;
+      rvb->aos_size = size;
+   }
+
+   /* Emit the data
+    */
+   switch (size) {
+   case 2:
+      emit_vec8( ctx, rvb, data, stride, count );
+      break;
+   case 3:
+      emit_vec12( ctx, rvb, data, stride, count );
+      break;
+   case 4:
+      emit_vec16( ctx, rvb, data, stride, count );
+      break;
+   default:
+      assert(0);
+      exit(1);
+      break;
+   }
+
+}
+
+
+
+static void emit_s0_vec( GLcontext *ctx,
+                        struct radeon_dma_region *rvb,
+                        char *data,
+                        int stride,
+                        int count )
+{
+   int i;
+   int *out = (int *)(rvb->address + rvb->start);
+
+   if (RADEON_DEBUG & DEBUG_VERTS)
+      fprintf(stderr, "%s count %d stride %d\n",
+             __FUNCTION__, count, stride);
+
+   for (i = 0; i < count; i++) {
+      out[0] = *(int *)data;
+      out[1] = 0;
+      out += 2;
+      data += stride;
+   }
+}
+
+static void emit_stq_vec( GLcontext *ctx,
+                        struct radeon_dma_region *rvb,
+                        char *data,
+                        int stride,
+                        int count )
+{
+   int i;
+   int *out = (int *)(rvb->address + rvb->start);
+
+   if (RADEON_DEBUG & DEBUG_VERTS)
+      fprintf(stderr, "%s count %d stride %d\n",
+             __FUNCTION__, count, stride);
+
+   for (i = 0; i < count; i++) {
+      out[0] = *(int *)data;
+      out[1] = *(int *)(data+4);
+      out[2] = *(int *)(data+12);
+      out += 3;
+      data += stride;
+   }
+}
+
+
+
+
+static void emit_tex_vector( GLcontext *ctx,
+                            struct radeon_dma_region *rvb,
+                            char *data,
+                            int size,
+                            int stride,
+                            int count )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   int emitsize;
+
+   if (RADEON_DEBUG & DEBUG_VERTS)
+      fprintf(stderr, "%s %d/%d\n", __FUNCTION__, count, size);
+
+   assert (!rvb->buf);
+
+   switch (size) {
+   case 4: emitsize = 3; break;
+   default: emitsize = 2; break;
+   }
+
+
+   if (stride == 0) {
+      radeonAllocDmaRegion( rmesa, rvb, 4 * emitsize, 4 );
+      count = 1;
+      rvb->aos_start = GET_START(rvb);
+      rvb->aos_stride = 0;
+      rvb->aos_size = emitsize;
+   }
+   else {
+      radeonAllocDmaRegion( rmesa, rvb, 4 * emitsize * count, 4 );
+      rvb->aos_start = GET_START(rvb);
+      rvb->aos_stride = emitsize;
+      rvb->aos_size = emitsize;
+   }
+
+
+   /* Emit the data
+    */
+   switch (size) {
+   case 1:
+      emit_s0_vec( ctx, rvb, data, stride, count ); 
+      break;
+   case 2:
+      emit_vec8( ctx, rvb, data, stride, count );
+      break;
+   case 3:
+      emit_vec8( ctx, rvb, data, stride, count );
+      break;
+   case 4:
+      emit_stq_vec( ctx, rvb, data, stride, count );
+      break;
+   default:
+      assert(0);
+      exit(1);
+      break;
+   }
+}
+
+
+
+
+/* Emit any changed arrays to new agp memory, re-emit a packet to
+ * update the arrays.  
+ */
+void radeonEmitArrays( GLcontext *ctx, GLuint inputs )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+   struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb;
+   struct radeon_dma_region **component = rmesa->tcl.aos_components;
+   GLuint nr = 0;
+   GLuint vfmt = 0;
+   GLuint count = VB->Count;
+   GLuint vtx;
+   
+   if (RADEON_DEBUG & DEBUG_VERTS) 
+      _tnl_print_vert_flags( __FUNCTION__, inputs );
+
+   if (1) {
+      if (!rmesa->tcl.obj.buf) 
+        emit_vector( ctx, 
+                     &rmesa->tcl.obj, 
+                     (char *)VB->ObjPtr->data,
+                     VB->ObjPtr->size,
+                     VB->ObjPtr->stride,
+                     count);
+
+      switch( VB->ObjPtr->size ) {
+      case 4: vfmt |= RADEON_CP_VC_FRMT_W0;
+      case 3: vfmt |= RADEON_CP_VC_FRMT_Z;
+      case 2: vfmt |= RADEON_CP_VC_FRMT_XY;
+      default:
+      }
+      component[nr++] = &rmesa->tcl.obj;
+   }
+   
+
+   if (inputs & VERT_BIT_NORMAL) {
+      if (!rmesa->tcl.norm.buf)
+        emit_vector( ctx, 
+                     &(rmesa->tcl.norm), 
+                     (char *)VB->NormalPtr->data,
+                     3,
+                     VB->NormalPtr->stride,
+                     count);
+
+      vfmt |= RADEON_CP_VC_FRMT_N0;
+      component[nr++] = &rmesa->tcl.norm;
+   }
+
+   if (inputs & VERT_BIT_COLOR0) {
+      if (VB->ColorPtr[0]->Type == GL_UNSIGNED_BYTE) {
+        if (!rmesa->tcl.rgba.buf)
+           emit_ubyte_rgba( ctx, 
+                            &rmesa->tcl.rgba, 
+                            (char *)VB->ColorPtr[0]->Ptr,
+                            VB->ColorPtr[0]->Size,
+                            VB->ColorPtr[0]->StrideB,
+                            count);
+
+        vfmt |= RADEON_CP_VC_FRMT_PKCOLOR; 
+      }
+      else {
+        int emitsize;
+
+        if (VB->ColorPtr[0]->Size == 4 &&
+            (VB->ColorPtr[0]->StrideB != 0 ||
+             ((GLfloat *)VB->ColorPtr[0]->Ptr)[3] != 1.0)) { 
+           vfmt |= RADEON_CP_VC_FRMT_FPCOLOR | RADEON_CP_VC_FRMT_FPALPHA;
+           emitsize = 4;
+        }
+        else { 
+           vfmt |= RADEON_CP_VC_FRMT_FPCOLOR;
+           emitsize = 3;
+        }
+
+        if (!rmesa->tcl.rgba.buf)
+           emit_vector( ctx, 
+                        &(rmesa->tcl.rgba), 
+                        (char *)VB->ColorPtr[0]->Ptr,
+                        emitsize,
+                        VB->ColorPtr[0]->StrideB,
+                        count);
+      }
+
+      component[nr++] = &rmesa->tcl.rgba;
+   }
+
+
+   if (inputs & VERT_BIT_COLOR1) {
+      if (!rmesa->tcl.spec.buf) {
+        if (VB->SecondaryColorPtr[0]->Type != GL_UNSIGNED_BYTE)
+           radeon_import_float_spec_colors( ctx );
+
+        emit_ubyte_rgba( ctx, 
+                         &rmesa->tcl.spec, 
+                         (char *)VB->SecondaryColorPtr[0]->Ptr,
+                         3,
+                         VB->SecondaryColorPtr[0]->StrideB,
+                         count);
+      }
+
+      vfmt |= RADEON_CP_VC_FRMT_PKSPEC; 
+      component[nr++] = &rmesa->tcl.spec;
+   }
+
+   vtx = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &
+         ~(RADEON_TCL_VTX_Q0|RADEON_TCL_VTX_Q1));
+      
+   if (inputs & VERT_BIT_TEX0) {
+      if (!rmesa->tcl.tex[0].buf)
+        emit_tex_vector( ctx, 
+                         &(rmesa->tcl.tex[0]), 
+                         (char *)VB->TexCoordPtr[0]->data,
+                         VB->TexCoordPtr[0]->size,
+                         VB->TexCoordPtr[0]->stride,
+                         count );
+
+      switch( VB->TexCoordPtr[0]->size ) {
+      case 4:
+        vtx |= RADEON_TCL_VTX_Q0; 
+        vfmt |= RADEON_CP_VC_FRMT_Q0;
+      default: 
+        vfmt |= RADEON_CP_VC_FRMT_ST0;
+      }
+      component[nr++] = &rmesa->tcl.tex[0];
+   }
+
+   if (inputs & VERT_BIT_TEX1) {
+      if (!rmesa->tcl.tex[1].buf)
+        emit_tex_vector( ctx, 
+                         &(rmesa->tcl.tex[1]), 
+                         (char *)VB->TexCoordPtr[1]->data,
+                         VB->TexCoordPtr[1]->size,
+                         VB->TexCoordPtr[1]->stride,
+                         count );
+        
+      switch( VB->TexCoordPtr[1]->size ) {
+      case 4: 
+        vtx |= RADEON_TCL_VTX_Q1;
+        vfmt |= RADEON_CP_VC_FRMT_Q1;
+      default: 
+        vfmt |= RADEON_CP_VC_FRMT_ST1;
+      }
+      component[nr++] = &rmesa->tcl.tex[1];
+   }
+
+   if (vtx != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT]) {
+      RADEON_STATECHANGE( rmesa, tcl );
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] = vtx;
+   }
+
+   rmesa->tcl.nr_aos_components = nr;
+   rmesa->tcl.vertex_format = vfmt;
+}
+
+
+void radeonReleaseArrays( GLcontext *ctx, GLuint newinputs )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+
+   if (RADEON_DEBUG & DEBUG_VERTS) 
+      _tnl_print_vert_flags( __FUNCTION__, newinputs );
+
+   if (newinputs & VERT_BIT_POS) 
+     radeonReleaseDmaRegion( rmesa, &rmesa->tcl.obj, __FUNCTION__ );
+
+   if (newinputs & VERT_BIT_NORMAL) 
+      radeonReleaseDmaRegion( rmesa, &rmesa->tcl.norm, __FUNCTION__ );
+
+   if (newinputs & VERT_BIT_COLOR0) 
+      radeonReleaseDmaRegion( rmesa, &rmesa->tcl.rgba, __FUNCTION__ );
+
+   if (newinputs & VERT_BIT_COLOR1) 
+      radeonReleaseDmaRegion( rmesa, &rmesa->tcl.spec, __FUNCTION__ );
+
+   if (newinputs & VERT_BIT_TEX0)
+      radeonReleaseDmaRegion( rmesa, &rmesa->tcl.tex[0], __FUNCTION__ );
+
+   if (newinputs & VERT_BIT_TEX1)
+      radeonReleaseDmaRegion( rmesa, &rmesa->tcl.tex[1], __FUNCTION__ );
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_maos_vbtmp.h b/src/mesa/drivers/dri/radeon/radeon_maos_vbtmp.h
new file mode 100644 (file)
index 0000000..b379bad
--- /dev/null
@@ -0,0 +1,368 @@
+/*
+ * Mesa 3-D graphics library
+ * Version:  4.1
+ *
+ * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef LOCALVARS
+#define LOCALVARS
+#endif
+
+#undef TCL_DEBUG
+#ifndef TCL_DEBUG
+#define TCL_DEBUG 0
+#endif
+
+static void TAG(emit)( GLcontext *ctx,
+                      GLuint start, GLuint end,
+                      void *dest )
+{
+   LOCALVARS
+   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+   GLuint (*tc0)[4], (*tc1)[4], (*tc2)[4];
+   GLfloat (*fog)[4];
+   GLuint (*norm)[4];
+   GLubyte (*col)[4], (*spec)[4];
+   GLuint tc0_stride, tc1_stride, col_stride, spec_stride, fog_stride;
+   GLuint tc2_stride, norm_stride;
+   GLuint (*coord)[4];
+   GLuint coord_stride; /* object coordinates */
+   GLubyte dummy[4];
+   int i;
+
+   union emit_union *v = (union emit_union *)dest;
+
+   if (RADEON_DEBUG & DEBUG_VERTS)
+      fprintf(stderr, "%s\n", __FUNCTION__); 
+
+   /* The vertex code expects Obj to be clean to element 3.  To fix
+    * this, add more vertex code (for obj-2, obj-3) or preferably move
+    * to maos.  
+    */
+   if (VB->ObjPtr->size < 3) {
+      if (VB->ObjPtr->flags & VEC_NOT_WRITEABLE) {
+        VB->import_data( ctx, VERT_BIT_POS, VEC_NOT_WRITEABLE );
+      }
+      _mesa_vector4f_clean_elem( VB->ObjPtr, VB->Count, 2 );
+   }
+
+   if (DO_W && VB->ObjPtr->size < 4) {
+      if (VB->ObjPtr->flags & VEC_NOT_WRITEABLE) {
+        VB->import_data( ctx, VERT_BIT_POS, VEC_NOT_WRITEABLE );
+      }
+      _mesa_vector4f_clean_elem( VB->ObjPtr, VB->Count, 3 );
+   }
+
+   coord = (GLuint (*)[4])VB->ObjPtr->data;
+   coord_stride = VB->ObjPtr->stride;
+
+   if (DO_TEX2) {
+      const GLuint t2 = GET_TEXSOURCE(2);
+      tc2 = (GLuint (*)[4])VB->TexCoordPtr[t2]->data;
+      tc2_stride = VB->TexCoordPtr[t2]->stride;
+      if (DO_PTEX && VB->TexCoordPtr[t2]->size < 4) {
+        if (VB->TexCoordPtr[t2]->flags & VEC_NOT_WRITEABLE) {
+           VB->import_data( ctx, VERT_BIT_TEX2, VEC_NOT_WRITEABLE );
+        }
+        _mesa_vector4f_clean_elem( VB->TexCoordPtr[t2], VB->Count, 3 );
+      }
+   }
+
+   if (DO_TEX1) {
+      if (VB->TexCoordPtr[1]) {
+        const GLuint t1 = GET_TEXSOURCE(1);
+        tc1 = (GLuint (*)[4])VB->TexCoordPtr[t1]->data;
+        tc1_stride = VB->TexCoordPtr[t1]->stride;
+        if (DO_PTEX && VB->TexCoordPtr[t1]->size < 4) {
+           if (VB->TexCoordPtr[t1]->flags & VEC_NOT_WRITEABLE) {
+              VB->import_data( ctx, VERT_BIT_TEX1, VEC_NOT_WRITEABLE );
+           }
+           _mesa_vector4f_clean_elem( VB->TexCoordPtr[t1], VB->Count, 3 );
+        }
+      } else {
+        tc1 = (GLuint (*)[4])&ctx->Current.Attrib[VERT_ATTRIB_TEX1]; /* could be anything, really */
+        tc1_stride = 0;
+      }
+   }
+
+   if (DO_TEX0) {
+      if (VB->TexCoordPtr[0]) {
+        const GLuint t0 = GET_TEXSOURCE(0);
+        tc0_stride = VB->TexCoordPtr[t0]->stride;
+        tc0 = (GLuint (*)[4])VB->TexCoordPtr[t0]->data;
+        if (DO_PTEX && VB->TexCoordPtr[t0]->size < 4) {
+           if (VB->TexCoordPtr[t0]->flags & VEC_NOT_WRITEABLE) {
+              VB->import_data( ctx, VERT_BIT_TEX0, VEC_NOT_WRITEABLE );
+           }
+           _mesa_vector4f_clean_elem( VB->TexCoordPtr[t0], VB->Count, 3 );
+        }
+      } else {
+        tc0 = (GLuint (*)[4])&ctx->Current.Attrib[VERT_ATTRIB_TEX0]; /* could be anything, really */
+        tc0_stride = 0;
+      }
+        
+   }
+
+   if (DO_NORM) {
+      if (VB->NormalPtr) {
+        norm_stride = VB->NormalPtr->stride;
+        norm = (GLuint (*)[4])VB->NormalPtr->data;
+      } else {
+        norm_stride = 0;
+        norm = (GLuint (*)[4])&ctx->Current.Attrib[VERT_ATTRIB_NORMAL];
+      }
+   }
+
+   if (DO_RGBA) {
+      if (VB->ColorPtr[0]) {
+        /* This is incorrect when colormaterial is enabled:
+         */
+        if (VB->ColorPtr[0]->Type != GL_UNSIGNED_BYTE) {
+           if (0) fprintf(stderr, "IMPORTING FLOAT COLORS\n");
+           IMPORT_FLOAT_COLORS( ctx );
+        }
+        col = (GLubyte (*)[4])VB->ColorPtr[0]->Ptr;
+        col_stride = VB->ColorPtr[0]->StrideB;
+      } else {
+        col = &dummy; /* any old memory is fine */
+        col_stride = 0;
+      }
+   }
+
+   if (DO_SPEC) {
+      if (VB->SecondaryColorPtr[0]) {
+        if (VB->SecondaryColorPtr[0]->Type != GL_UNSIGNED_BYTE)
+           IMPORT_FLOAT_SPEC_COLORS( ctx );
+        spec = (GLubyte (*)[4])VB->SecondaryColorPtr[0]->Ptr;
+        spec_stride = VB->SecondaryColorPtr[0]->StrideB;
+      } else {
+        spec = &dummy;
+        spec_stride = 0;
+      }
+   }
+
+   if (DO_FOG) {
+      if (VB->FogCoordPtr) {
+        fog = VB->FogCoordPtr->data;
+        fog_stride = VB->FogCoordPtr->stride;
+      } else {
+        fog = (GLfloat (*)[4])&dummy; fog[0][0] = 0.0F;
+        fog_stride = 0;
+      }
+   }
+   
+   
+   if (VB->importable_data) {
+      if (start) {
+        coord =  (GLuint (*)[4])((GLubyte *)coord + start * coord_stride);
+        if (DO_TEX0)
+           tc0 =  (GLuint (*)[4])((GLubyte *)tc0 + start * tc0_stride);
+        if (DO_TEX1) 
+           tc1 =  (GLuint (*)[4])((GLubyte *)tc1 + start * tc1_stride);
+        if (DO_TEX2) 
+           tc2 =  (GLuint (*)[4])((GLubyte *)tc2 + start * tc2_stride);
+        if (DO_NORM) 
+           norm =  (GLuint (*)[4])((GLubyte *)norm + start * norm_stride);
+        if (DO_RGBA) 
+           STRIDE_4UB(col, start * col_stride);
+        if (DO_SPEC)
+           STRIDE_4UB(spec, start * spec_stride);
+        if (DO_FOG)
+           fog =  (GLfloat (*)[4])((GLubyte *)fog + start * fog_stride);
+      }
+
+      for (i=start; i < end; i++) {
+        v[0].ui = coord[0][0];
+        v[1].ui = coord[0][1];
+        v[2].ui = coord[0][2];
+        if (TCL_DEBUG) fprintf(stderr, "%d: %.2f %.2f %.2f ", i, v[0].f, v[1].f, v[2].f);
+        if (DO_W) {
+           v[3].ui = coord[0][3];
+           if (TCL_DEBUG) fprintf(stderr, "%.2f ", v[3].f);
+           v += 4;
+        } 
+        else
+           v += 3;
+        coord =  (GLuint (*)[4])((GLubyte *)coord +  coord_stride);
+
+        if (DO_NORM) {
+           v[0].ui = norm[0][0];
+           v[1].ui = norm[0][1];
+           v[2].ui = norm[0][2];
+           if (TCL_DEBUG) fprintf(stderr, "norm: %.2f %.2f %.2f ", v[0].f, v[1].f, v[2].f);
+           v += 3;
+           norm =  (GLuint (*)[4])((GLubyte *)norm +  norm_stride);
+        }
+        if (DO_RGBA) {
+           v[0].ui = LE32_TO_CPU(*(GLuint *)&col[0]);
+           STRIDE_4UB(col, col_stride);
+           if (TCL_DEBUG) fprintf(stderr, "%x ", v[0].ui);
+           v++;
+        }
+        if (DO_SPEC || DO_FOG) {
+           if (DO_SPEC) {
+              v[0].specular.red   = spec[0][0];
+              v[0].specular.green = spec[0][1];
+              v[0].specular.blue  = spec[0][2];
+              STRIDE_4UB(spec, spec_stride);
+           }
+           if (DO_FOG) {
+              v[0].specular.alpha = fog[0][0] * 255.0;
+               fog = (GLfloat (*)[4])((GLubyte *)fog + fog_stride);
+           }
+           if (TCL_DEBUG) fprintf(stderr, "%x ", v[0].ui);
+           v++;
+        }
+        if (DO_TEX0) {
+           v[0].ui = tc0[0][0];
+           v[1].ui = tc0[0][1];
+           if (TCL_DEBUG) fprintf(stderr, "t0: %.2f %.2f ", v[0].f, v[1].f);
+           if (DO_PTEX) {
+              v[2].ui = tc0[0][3];
+              if (TCL_DEBUG) fprintf(stderr, "%.2f ", v[2].f);
+              v += 3;
+           } 
+           else
+              v += 2;
+           tc0 =  (GLuint (*)[4])((GLubyte *)tc0 +  tc0_stride);
+        }
+        if (DO_TEX1) {
+           v[0].ui = tc1[0][0];
+           v[1].ui = tc1[0][1];
+           if (TCL_DEBUG) fprintf(stderr, "t1: %.2f %.2f ", v[0].f, v[1].f);
+           if (DO_PTEX) {
+              v[2].ui = tc1[0][3];
+              if (TCL_DEBUG) fprintf(stderr, "%.2f ", v[2].f);
+              v += 3;
+           } 
+           else
+              v += 2;
+           tc1 =  (GLuint (*)[4])((GLubyte *)tc1 +  tc1_stride);
+        } 
+        if (DO_TEX2) {
+           v[0].ui = tc2[0][0];
+           v[1].ui = tc2[0][1];
+           if (DO_PTEX) {
+              v[2].ui = tc2[0][3];
+              v += 3;
+           } 
+           else
+              v += 2;
+           tc2 =  (GLuint (*)[4])((GLubyte *)tc2 +  tc2_stride);
+        } 
+        if (TCL_DEBUG) fprintf(stderr, "\n");
+      }
+   } else {
+      for (i=start; i < end; i++) {
+        v[0].ui = coord[i][0];
+        v[1].ui = coord[i][1];
+        v[2].ui = coord[i][2];
+        if (DO_W) {
+           v[3].ui = coord[i][3];
+           v += 4;
+        } 
+        else
+           v += 3;
+
+        if (DO_NORM) {
+           v[0].ui = norm[i][0];
+           v[1].ui = norm[i][1];
+           v[2].ui = norm[i][2];
+           v += 3;
+        }
+        if (DO_RGBA) {
+           v[0].ui = LE32_TO_CPU(*(GLuint *)&col[i]);
+           v++;
+        }
+        if (DO_SPEC || DO_FOG) {
+           if (DO_SPEC) {
+              v[0].specular.red   = spec[i][0];
+              v[0].specular.green = spec[i][1];
+              v[0].specular.blue  = spec[i][2];
+           }
+           if (DO_FOG) {
+               GLfloat *f = (GLfloat *) ((GLubyte *)fog + fog_stride);
+               v[0].specular.alpha = *f * 255.0;
+           }
+           v++;
+        }
+        if (DO_TEX0) {
+           v[0].ui = tc0[i][0];
+           v[1].ui = tc0[i][1];
+           if (DO_PTEX) {
+              v[2].ui = tc0[i][3];
+              v += 3;
+           } 
+           else
+              v += 2;
+        }
+        if (DO_TEX1) {
+           v[0].ui = tc1[i][0];
+           v[1].ui = tc1[i][1];
+           if (DO_PTEX) {
+              v[2].ui = tc1[i][3];
+              v += 3;
+           } 
+           else
+              v += 2;
+        } 
+        if (DO_TEX2) {
+           v[0].ui = tc2[i][0];
+           v[1].ui = tc2[i][1];
+           if (DO_PTEX) {
+              v[2].ui = tc2[i][3];
+              v += 3;
+           } 
+           else
+              v += 2;
+        } 
+      }
+   }
+}
+
+
+
+static void TAG(init)( void )
+{
+   int sz = 3;
+   if (DO_W) sz++;
+   if (DO_NORM) sz += 3;
+   if (DO_RGBA) sz++;
+   if (DO_SPEC || DO_FOG) sz++;
+   if (DO_TEX0) sz += 2;
+   if (DO_TEX0 && DO_PTEX) sz++;
+   if (DO_TEX1) sz += 2;
+   if (DO_TEX1 && DO_PTEX) sz++;
+   if (DO_TEX2) sz += 2;
+   if (DO_TEX2 && DO_PTEX) sz++;
+
+   setup_tab[IDX].emit = TAG(emit);
+   setup_tab[IDX].vertex_format = IND;
+   setup_tab[IDX].vertex_size = sz;
+}
+
+
+#undef IND
+#undef TAG
+#undef IDX
diff --git a/src/mesa/drivers/dri/radeon/radeon_maos_verts.c b/src/mesa/drivers/dri/radeon/radeon_maos_verts.c
new file mode 100644 (file)
index 0000000..39b1f57
--- /dev/null
@@ -0,0 +1,335 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     Tungsten Graphics Inc., Austin, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "mtypes.h"
+
+#include "array_cache/acache.h"
+#include "tnl/tnl.h"
+#include "tnl/t_pipeline.h"
+#include "tnl/t_imm_debug.h"
+
+#include "radeon_context.h"
+#include "radeon_state.h"
+#include "radeon_ioctl.h"
+#include "radeon_tex.h"
+#include "radeon_tcl.h"
+#include "radeon_swtcl.h"
+#include "radeon_maos.h"
+
+
+#define RADEON_TCL_MAX_SETUP 13
+
+union emit_union { float f; GLuint ui; radeon_color_t specular; };
+
+static struct {
+   void   (*emit)( GLcontext *, GLuint, GLuint, void * );
+   GLuint vertex_size;
+   GLuint vertex_format;
+} setup_tab[RADEON_TCL_MAX_SETUP];
+
+#define DO_W    (IND & RADEON_CP_VC_FRMT_W0)
+#define DO_RGBA (IND & RADEON_CP_VC_FRMT_PKCOLOR)
+#define DO_SPEC (IND & RADEON_CP_VC_FRMT_PKSPEC)
+#define DO_FOG  (IND & RADEON_CP_VC_FRMT_PKSPEC)
+#define DO_TEX0 (IND & RADEON_CP_VC_FRMT_ST0)
+#define DO_TEX1 (IND & RADEON_CP_VC_FRMT_ST1)
+#define DO_PTEX (IND & RADEON_CP_VC_FRMT_Q0)
+#define DO_NORM (IND & RADEON_CP_VC_FRMT_N0)
+
+#define DO_TEX2 0
+#define DO_TEX3 0
+
+#define GET_TEXSOURCE(n)  n
+#define GET_UBYTE_COLOR_STORE() &RADEON_CONTEXT(ctx)->UbyteColor
+#define GET_UBYTE_SPEC_COLOR_STORE() &RADEON_CONTEXT(ctx)->UbyteSecondaryColor
+
+#define IMPORT_FLOAT_COLORS radeon_import_float_colors
+#define IMPORT_FLOAT_SPEC_COLORS radeon_import_float_spec_colors
+
+/***********************************************************************
+ *             Generate vertex emit functions               *
+ ***********************************************************************/
+
+
+/* Defined in order of increasing vertex size:
+ */
+#define IDX 0
+#define IND (RADEON_CP_VC_FRMT_XY|             \
+            RADEON_CP_VC_FRMT_Z|               \
+            RADEON_CP_VC_FRMT_PKCOLOR)
+#define TAG(x) x##_rgba
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 1
+#define IND (RADEON_CP_VC_FRMT_XY|             \
+            RADEON_CP_VC_FRMT_Z|               \
+            RADEON_CP_VC_FRMT_N0)
+#define TAG(x) x##_n
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 2
+#define IND (RADEON_CP_VC_FRMT_XY|             \
+            RADEON_CP_VC_FRMT_Z|               \
+            RADEON_CP_VC_FRMT_PKCOLOR|         \
+            RADEON_CP_VC_FRMT_ST0)
+#define TAG(x) x##_rgba_st
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 3
+#define IND (RADEON_CP_VC_FRMT_XY|             \
+            RADEON_CP_VC_FRMT_Z|               \
+            RADEON_CP_VC_FRMT_PKCOLOR|         \
+            RADEON_CP_VC_FRMT_N0)
+#define TAG(x) x##_rgba_n
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 4
+#define IND (RADEON_CP_VC_FRMT_XY|             \
+            RADEON_CP_VC_FRMT_Z|               \
+            RADEON_CP_VC_FRMT_ST0|             \
+            RADEON_CP_VC_FRMT_N0)
+#define TAG(x) x##_st_n
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 5
+#define IND (RADEON_CP_VC_FRMT_XY|             \
+            RADEON_CP_VC_FRMT_Z|               \
+            RADEON_CP_VC_FRMT_PKCOLOR|         \
+            RADEON_CP_VC_FRMT_ST0|             \
+            RADEON_CP_VC_FRMT_ST1)
+#define TAG(x) x##_rgba_st_st
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 6
+#define IND (RADEON_CP_VC_FRMT_XY|             \
+            RADEON_CP_VC_FRMT_Z|               \
+            RADEON_CP_VC_FRMT_PKCOLOR|         \
+            RADEON_CP_VC_FRMT_ST0|             \
+            RADEON_CP_VC_FRMT_N0)
+#define TAG(x) x##_rgba_st_n
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 7
+#define IND (RADEON_CP_VC_FRMT_XY|             \
+            RADEON_CP_VC_FRMT_Z|               \
+            RADEON_CP_VC_FRMT_PKCOLOR|         \
+            RADEON_CP_VC_FRMT_PKSPEC|          \
+            RADEON_CP_VC_FRMT_ST0|             \
+            RADEON_CP_VC_FRMT_ST1)
+#define TAG(x) x##_rgba_spec_st_st
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 8
+#define IND (RADEON_CP_VC_FRMT_XY|             \
+            RADEON_CP_VC_FRMT_Z|               \
+            RADEON_CP_VC_FRMT_ST0|             \
+            RADEON_CP_VC_FRMT_ST1|             \
+            RADEON_CP_VC_FRMT_N0)
+#define TAG(x) x##_st_st_n
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 9
+#define IND (RADEON_CP_VC_FRMT_XY|             \
+            RADEON_CP_VC_FRMT_Z|               \
+            RADEON_CP_VC_FRMT_PKCOLOR|         \
+            RADEON_CP_VC_FRMT_PKSPEC|          \
+            RADEON_CP_VC_FRMT_ST0|             \
+            RADEON_CP_VC_FRMT_ST1|             \
+            RADEON_CP_VC_FRMT_N0)
+#define TAG(x) x##_rgpa_spec_st_st_n
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 10
+#define IND (RADEON_CP_VC_FRMT_XY|             \
+            RADEON_CP_VC_FRMT_Z|               \
+            RADEON_CP_VC_FRMT_PKCOLOR|         \
+            RADEON_CP_VC_FRMT_ST0|             \
+            RADEON_CP_VC_FRMT_Q0)
+#define TAG(x) x##_rgba_stq
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 11
+#define IND (RADEON_CP_VC_FRMT_XY|             \
+            RADEON_CP_VC_FRMT_Z|               \
+            RADEON_CP_VC_FRMT_PKCOLOR|         \
+            RADEON_CP_VC_FRMT_ST1|             \
+            RADEON_CP_VC_FRMT_Q1|              \
+            RADEON_CP_VC_FRMT_ST0|             \
+            RADEON_CP_VC_FRMT_Q0)
+#define TAG(x) x##_rgba_stq_stq
+#include "radeon_maos_vbtmp.h"
+
+#define IDX 12
+#define IND (RADEON_CP_VC_FRMT_XY|             \
+            RADEON_CP_VC_FRMT_Z|               \
+            RADEON_CP_VC_FRMT_W0|              \
+            RADEON_CP_VC_FRMT_PKCOLOR|         \
+            RADEON_CP_VC_FRMT_PKSPEC|          \
+            RADEON_CP_VC_FRMT_ST0|             \
+            RADEON_CP_VC_FRMT_Q0|              \
+            RADEON_CP_VC_FRMT_ST1|             \
+            RADEON_CP_VC_FRMT_Q1|              \
+            RADEON_CP_VC_FRMT_N0)
+#define TAG(x) x##_w_rgpa_spec_stq_stq_n
+#include "radeon_maos_vbtmp.h"
+
+
+
+
+
+/***********************************************************************
+ *                         Initialization 
+ ***********************************************************************/
+
+
+static void init_tcl_verts( void )
+{
+   init_rgba();
+   init_n();
+   init_rgba_n();
+   init_rgba_st();
+   init_st_n();
+   init_rgba_st_st();
+   init_rgba_st_n();
+   init_rgba_spec_st_st();
+   init_st_st_n();
+   init_rgpa_spec_st_st_n();
+   init_rgba_stq();
+   init_rgba_stq_stq();
+   init_w_rgpa_spec_stq_stq_n();
+}
+
+
+void radeonEmitArrays( GLcontext *ctx, GLuint inputs )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+   GLuint req = 0;
+   GLuint vtx = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &
+                ~(RADEON_TCL_VTX_Q0|RADEON_TCL_VTX_Q1));
+   int i;
+   static int firsttime = 1;
+
+   if (firsttime) {
+      init_tcl_verts();
+      firsttime = 0;
+   }
+                    
+   if (1) {
+      req |= RADEON_CP_VC_FRMT_Z;
+      if (VB->ObjPtr->size == 4) {
+        req |= RADEON_CP_VC_FRMT_W0;
+      }
+   }
+
+   if (inputs & VERT_BIT_NORMAL) {
+      req |= RADEON_CP_VC_FRMT_N0;
+   }
+   
+   if (inputs & VERT_BIT_COLOR0) {
+      req |= RADEON_CP_VC_FRMT_PKCOLOR;
+   }
+
+   if (inputs & VERT_BIT_COLOR1) {
+      req |= RADEON_CP_VC_FRMT_PKSPEC;
+   }
+
+   if (inputs & VERT_BIT_TEX0) {
+      req |= RADEON_CP_VC_FRMT_ST0;
+
+      if (VB->TexCoordPtr[0]->size == 4) {
+        req |= RADEON_CP_VC_FRMT_Q0;
+        vtx |= RADEON_TCL_VTX_Q0;
+      }
+   }
+
+   if (inputs & VERT_BIT_TEX1) {
+      req |= RADEON_CP_VC_FRMT_ST1;
+
+      if (VB->TexCoordPtr[1]->size == 4) {
+        req |= RADEON_CP_VC_FRMT_Q1;
+        vtx |= RADEON_TCL_VTX_Q1;
+      }
+   }
+
+   if (vtx != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT]) {
+      RADEON_STATECHANGE( rmesa, tcl );
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] = vtx;
+   }
+
+   for (i = 0 ; i < RADEON_TCL_MAX_SETUP ; i++) 
+      if ((setup_tab[i].vertex_format & req) == req) 
+        break;
+
+   if (rmesa->tcl.vertex_format == setup_tab[i].vertex_format &&
+       rmesa->tcl.indexed_verts.buf)
+      return;
+
+   if (rmesa->tcl.indexed_verts.buf)
+      radeonReleaseArrays( ctx, ~0 );
+
+   radeonAllocDmaRegionVerts( rmesa, 
+                             &rmesa->tcl.indexed_verts, 
+                             VB->Count,
+                             setup_tab[i].vertex_size * 4, 
+                             4);
+
+   setup_tab[i].emit( ctx, 0, VB->Count, 
+                     rmesa->tcl.indexed_verts.address + 
+                     rmesa->tcl.indexed_verts.start );
+
+   rmesa->tcl.vertex_format = setup_tab[i].vertex_format;
+   rmesa->tcl.indexed_verts.aos_start = GET_START( &rmesa->tcl.indexed_verts );
+   rmesa->tcl.indexed_verts.aos_size = setup_tab[i].vertex_size;
+   rmesa->tcl.indexed_verts.aos_stride = setup_tab[i].vertex_size;
+
+   rmesa->tcl.aos_components[0] = &rmesa->tcl.indexed_verts;
+   rmesa->tcl.nr_aos_components = 1;
+}
+
+
+
+void radeonReleaseArrays( GLcontext *ctx, GLuint newinputs )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+
+   if (RADEON_DEBUG & DEBUG_VERTS) 
+      _tnl_print_vert_flags( __FUNCTION__, newinputs );
+
+   if (newinputs) 
+     radeonReleaseDmaRegion( rmesa, &rmesa->tcl.indexed_verts, __FUNCTION__ );
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_sanity.c b/src/mesa/drivers/dri/radeon/radeon_sanity.c
new file mode 100644 (file)
index 0000000..e3b37bf
--- /dev/null
@@ -0,0 +1,1043 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 2002 ATI Technologies Inc., Ontario, Canada, and
+                     Tungsten Graphics Inc, Cedar Park, TX.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+#include <errno.h>
+
+#include "glheader.h"
+
+#include "radeon_context.h"
+#include "radeon_ioctl.h"
+#include "radeon_sanity.h"
+
+/* Set this '1' to get more verbiage.
+ */
+#define MORE_VERBOSE 1
+
+#if MORE_VERBOSE
+#define VERBOSE (RADEON_DEBUG & DEBUG_VERBOSE)
+#define NORMAL  (1)
+#else
+#define VERBOSE 0
+#define NORMAL  (RADEON_DEBUG & DEBUG_VERBOSE)
+#endif
+
+
+/* New (1.3) state mechanism.  3 commands (packet, scalar, vector) in
+ * 1.3 cmdbuffers allow all previous state to be updated as well as
+ * the tcl scalar and vector areas.  
+ */
+static struct { 
+   int start; 
+   int len; 
+   const char *name;
+} packet[RADEON_MAX_STATE_PACKETS] = {
+   { RADEON_PP_MISC,7,"RADEON_PP_MISC" },
+   { RADEON_PP_CNTL,3,"RADEON_PP_CNTL" },
+   { RADEON_RB3D_COLORPITCH,1,"RADEON_RB3D_COLORPITCH" },
+   { RADEON_RE_LINE_PATTERN,2,"RADEON_RE_LINE_PATTERN" },
+   { RADEON_SE_LINE_WIDTH,1,"RADEON_SE_LINE_WIDTH" },
+   { RADEON_PP_LUM_MATRIX,1,"RADEON_PP_LUM_MATRIX" },
+   { RADEON_PP_ROT_MATRIX_0,2,"RADEON_PP_ROT_MATRIX_0" },
+   { RADEON_RB3D_STENCILREFMASK,3,"RADEON_RB3D_STENCILREFMASK" },
+   { RADEON_SE_VPORT_XSCALE,6,"RADEON_SE_VPORT_XSCALE" },
+   { RADEON_SE_CNTL,2,"RADEON_SE_CNTL" },
+   { RADEON_SE_CNTL_STATUS,1,"RADEON_SE_CNTL_STATUS" },
+   { RADEON_RE_MISC,1,"RADEON_RE_MISC" },
+   { RADEON_PP_TXFILTER_0,6,"RADEON_PP_TXFILTER_0" },
+   { RADEON_PP_BORDER_COLOR_0,1,"RADEON_PP_BORDER_COLOR_0" },
+   { RADEON_PP_TXFILTER_1,6,"RADEON_PP_TXFILTER_1" },
+   { RADEON_PP_BORDER_COLOR_1,1,"RADEON_PP_BORDER_COLOR_1" },
+   { RADEON_PP_TXFILTER_2,6,"RADEON_PP_TXFILTER_2" },
+   { RADEON_PP_BORDER_COLOR_2,1,"RADEON_PP_BORDER_COLOR_2" },
+   { RADEON_SE_ZBIAS_FACTOR,2,"RADEON_SE_ZBIAS_FACTOR" },
+   { RADEON_SE_TCL_OUTPUT_VTX_FMT,11,"RADEON_SE_TCL_OUTPUT_VTX_FMT" },
+   { RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED,17,"RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED" },
+       { 0, 4, "R200_PP_TXCBLEND_0" },
+       { 0, 4, "R200_PP_TXCBLEND_1" },
+       { 0, 4, "R200_PP_TXCBLEND_2" },
+       { 0, 4, "R200_PP_TXCBLEND_3" },
+       { 0, 4, "R200_PP_TXCBLEND_4" },
+       { 0, 4, "R200_PP_TXCBLEND_5" },
+       { 0, 4, "R200_PP_TXCBLEND_6" },
+       { 0, 4, "R200_PP_TXCBLEND_7" },
+       { 0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0" },
+       { 0, 6, "R200_PP_TFACTOR_0" },
+       { 0, 4, "R200_SE_VTX_FMT_0" },
+       { 0, 1, "R200_SE_VAP_CNTL" },
+       { 0, 5, "R200_SE_TCL_MATRIX_SEL_0" },
+       { 0, 5, "R200_SE_TCL_TEX_PROC_CTL_2" },
+       { 0, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL" },
+       { 0, 6, "R200_PP_TXFILTER_0" },
+       { 0, 6, "R200_PP_TXFILTER_1" },
+       { 0, 6, "R200_PP_TXFILTER_2" },
+       { 0, 6, "R200_PP_TXFILTER_3" },
+       { 0, 6, "R200_PP_TXFILTER_4" },
+       { 0, 6, "R200_PP_TXFILTER_5" },
+       { 0, 1, "R200_PP_TXOFFSET_0" },
+       { 0, 1, "R200_PP_TXOFFSET_1" },
+       { 0, 1, "R200_PP_TXOFFSET_2" },
+       { 0, 1, "R200_PP_TXOFFSET_3" },
+       { 0, 1, "R200_PP_TXOFFSET_4" },
+       { 0, 1, "R200_PP_TXOFFSET_5" },
+       { 0, 1, "R200_SE_VTE_CNTL" },
+       { 0, 1, "R200_SE_TCL_OUTPUT_VTX_COMP_SEL" },
+       { 0, 1, "R200_PP_TAM_DEBUG3" },
+       { 0, 1, "R200_PP_CNTL_X" }, 
+       { 0, 1, "R200_RB3D_DEPTHXY_OFFSET" }, 
+       { 0, 1, "R200_RE_AUX_SCISSOR_CNTL" }, 
+       { 0, 2, "R200_RE_SCISSOR_TL_0" }, 
+       { 0, 2, "R200_RE_SCISSOR_TL_1" }, 
+       { 0, 2, "R200_RE_SCISSOR_TL_2" }, 
+       { 0, 1, "R200_SE_VAP_CNTL_STATUS" }, 
+       { 0, 1, "R200_SE_VTX_STATE_CNTL" }, 
+       { 0, 1, "R200_RE_POINTSIZE" }, 
+       { 0, 4, "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0" },
+       { 0, 1, "R200_PP_CUBIC_FACES_0" }, /* 61 */
+       { 0, 5, "R200_PP_CUBIC_OFFSET_F1_0" }, /* 62 */
+       { 0, 1, "R200_PP_CUBIC_FACES_1" },
+       { 0, 5, "R200_PP_CUBIC_OFFSET_F1_1" },
+       { 0, 1, "R200_PP_CUBIC_FACES_2" },
+       { 0, 5, "R200_PP_CUBIC_OFFSET_F1_2" },
+       { 0, 1, "R200_PP_CUBIC_FACES_3" },
+       { 0, 5, "R200_PP_CUBIC_OFFSET_F1_3" },
+       { 0, 1, "R200_PP_CUBIC_FACES_4" },
+       { 0, 5, "R200_PP_CUBIC_OFFSET_F1_4" },
+       { 0, 1, "R200_PP_CUBIC_FACES_5" },
+       { 0, 5, "R200_PP_CUBIC_OFFSET_F1_5" },
+   { RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0" },
+   { RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1" },
+   { RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_1" },
+};
+
+struct reg_names {
+   int idx;
+   const char *name;
+};
+
+static struct reg_names reg_names[] = {
+   { RADEON_PP_MISC, "RADEON_PP_MISC" },
+   { RADEON_PP_FOG_COLOR, "RADEON_PP_FOG_COLOR" },
+   { RADEON_RE_SOLID_COLOR, "RADEON_RE_SOLID_COLOR" },
+   { RADEON_RB3D_BLENDCNTL, "RADEON_RB3D_BLENDCNTL" },
+   { RADEON_RB3D_DEPTHOFFSET, "RADEON_RB3D_DEPTHOFFSET" },
+   { RADEON_RB3D_DEPTHPITCH, "RADEON_RB3D_DEPTHPITCH" },
+   { RADEON_RB3D_ZSTENCILCNTL, "RADEON_RB3D_ZSTENCILCNTL" },
+   { RADEON_PP_CNTL, "RADEON_PP_CNTL" },
+   { RADEON_RB3D_CNTL, "RADEON_RB3D_CNTL" },
+   { RADEON_RB3D_COLOROFFSET, "RADEON_RB3D_COLOROFFSET" },
+   { RADEON_RB3D_COLORPITCH, "RADEON_RB3D_COLORPITCH" },
+   { RADEON_SE_CNTL, "RADEON_SE_CNTL" },
+   { RADEON_SE_COORD_FMT, "RADEON_SE_COORDFMT" },
+   { RADEON_SE_CNTL_STATUS, "RADEON_SE_CNTL_STATUS" },
+   { RADEON_RE_LINE_PATTERN, "RADEON_RE_LINE_PATTERN" },
+   { RADEON_RE_LINE_STATE, "RADEON_RE_LINE_STATE" },
+   { RADEON_SE_LINE_WIDTH, "RADEON_SE_LINE_WIDTH" },
+   { RADEON_RB3D_STENCILREFMASK, "RADEON_RB3D_STENCILREFMASK" },
+   { RADEON_RB3D_ROPCNTL, "RADEON_RB3D_ROPCNTL" },
+   { RADEON_RB3D_PLANEMASK, "RADEON_RB3D_PLANEMASK" },
+   { RADEON_SE_VPORT_XSCALE, "RADEON_SE_VPORT_XSCALE" },
+   { RADEON_SE_VPORT_XOFFSET, "RADEON_SE_VPORT_XOFFSET" },
+   { RADEON_SE_VPORT_YSCALE, "RADEON_SE_VPORT_YSCALE" },
+   { RADEON_SE_VPORT_YOFFSET, "RADEON_SE_VPORT_YOFFSET" },
+   { RADEON_SE_VPORT_ZSCALE, "RADEON_SE_VPORT_ZSCALE" },
+   { RADEON_SE_VPORT_ZOFFSET, "RADEON_SE_VPORT_ZOFFSET" },
+   { RADEON_RE_MISC, "RADEON_RE_MISC" },
+   { RADEON_PP_TXFILTER_0, "RADEON_PP_TXFILTER_0" },
+   { RADEON_PP_TXFILTER_1, "RADEON_PP_TXFILTER_1" },
+   { RADEON_PP_TXFILTER_2, "RADEON_PP_TXFILTER_2" },
+   { RADEON_PP_TXFORMAT_0, "RADEON_PP_TXFORMAT_0" },
+   { RADEON_PP_TXFORMAT_1, "RADEON_PP_TXFORMAT_1" },
+   { RADEON_PP_TXFORMAT_2, "RADEON_PP_TXFORMAT_3" },
+   { RADEON_PP_TXOFFSET_0, "RADEON_PP_TXOFFSET_0" },
+   { RADEON_PP_TXOFFSET_1, "RADEON_PP_TXOFFSET_1" },
+   { RADEON_PP_TXOFFSET_2, "RADEON_PP_TXOFFSET_3" },
+   { RADEON_PP_TXCBLEND_0, "RADEON_PP_TXCBLEND_0" },
+   { RADEON_PP_TXCBLEND_1, "RADEON_PP_TXCBLEND_1" },
+   { RADEON_PP_TXCBLEND_2, "RADEON_PP_TXCBLEND_3" },
+   { RADEON_PP_TXABLEND_0, "RADEON_PP_TXABLEND_0" },
+   { RADEON_PP_TXABLEND_1, "RADEON_PP_TXABLEND_1" },
+   { RADEON_PP_TXABLEND_2, "RADEON_PP_TXABLEND_3" },
+   { RADEON_PP_TFACTOR_0, "RADEON_PP_TFACTOR_0" },
+   { RADEON_PP_TFACTOR_1, "RADEON_PP_TFACTOR_1" },
+   { RADEON_PP_TFACTOR_2, "RADEON_PP_TFACTOR_3" },
+   { RADEON_PP_BORDER_COLOR_0, "RADEON_PP_BORDER_COLOR_0" },
+   { RADEON_PP_BORDER_COLOR_1, "RADEON_PP_BORDER_COLOR_1" },
+   { RADEON_PP_BORDER_COLOR_2, "RADEON_PP_BORDER_COLOR_3" },
+   { RADEON_SE_ZBIAS_FACTOR, "RADEON_SE_ZBIAS_FACTOR" },
+   { RADEON_SE_ZBIAS_CONSTANT, "RADEON_SE_ZBIAS_CONSTANT" },
+   { RADEON_SE_TCL_OUTPUT_VTX_FMT, "RADEON_SE_TCL_OUTPUT_VTXFMT" },
+   { RADEON_SE_TCL_OUTPUT_VTX_SEL, "RADEON_SE_TCL_OUTPUT_VTXSEL" },
+   { RADEON_SE_TCL_MATRIX_SELECT_0, "RADEON_SE_TCL_MATRIX_SELECT_0" },
+   { RADEON_SE_TCL_MATRIX_SELECT_1, "RADEON_SE_TCL_MATRIX_SELECT_1" },
+   { RADEON_SE_TCL_UCP_VERT_BLEND_CTL, "RADEON_SE_TCL_UCP_VERT_BLEND_CTL" },
+   { RADEON_SE_TCL_TEXTURE_PROC_CTL, "RADEON_SE_TCL_TEXTURE_PROC_CTL" },
+   { RADEON_SE_TCL_LIGHT_MODEL_CTL, "RADEON_SE_TCL_LIGHT_MODEL_CTL" },
+   { RADEON_SE_TCL_PER_LIGHT_CTL_0, "RADEON_SE_TCL_PER_LIGHT_CTL_0" },
+   { RADEON_SE_TCL_PER_LIGHT_CTL_1, "RADEON_SE_TCL_PER_LIGHT_CTL_1" },
+   { RADEON_SE_TCL_PER_LIGHT_CTL_2, "RADEON_SE_TCL_PER_LIGHT_CTL_2" },
+   { RADEON_SE_TCL_PER_LIGHT_CTL_3, "RADEON_SE_TCL_PER_LIGHT_CTL_3" },
+   { RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, "RADEON_SE_TCL_EMMISSIVE_RED" },
+   { RADEON_SE_TCL_MATERIAL_EMMISSIVE_GREEN, "RADEON_SE_TCL_EMMISSIVE_GREEN" },
+   { RADEON_SE_TCL_MATERIAL_EMMISSIVE_BLUE, "RADEON_SE_TCL_EMMISSIVE_BLUE" },
+   { RADEON_SE_TCL_MATERIAL_EMMISSIVE_ALPHA, "RADEON_SE_TCL_EMMISSIVE_ALPHA" },
+   { RADEON_SE_TCL_MATERIAL_AMBIENT_RED, "RADEON_SE_TCL_AMBIENT_RED" },
+   { RADEON_SE_TCL_MATERIAL_AMBIENT_GREEN, "RADEON_SE_TCL_AMBIENT_GREEN" },
+   { RADEON_SE_TCL_MATERIAL_AMBIENT_BLUE, "RADEON_SE_TCL_AMBIENT_BLUE" },
+   { RADEON_SE_TCL_MATERIAL_AMBIENT_ALPHA, "RADEON_SE_TCL_AMBIENT_ALPHA" },
+   { RADEON_SE_TCL_MATERIAL_DIFFUSE_RED, "RADEON_SE_TCL_DIFFUSE_RED" },
+   { RADEON_SE_TCL_MATERIAL_DIFFUSE_GREEN, "RADEON_SE_TCL_DIFFUSE_GREEN" },
+   { RADEON_SE_TCL_MATERIAL_DIFFUSE_BLUE, "RADEON_SE_TCL_DIFFUSE_BLUE" },
+   { RADEON_SE_TCL_MATERIAL_DIFFUSE_ALPHA, "RADEON_SE_TCL_DIFFUSE_ALPHA" },
+   { RADEON_SE_TCL_MATERIAL_SPECULAR_RED, "RADEON_SE_TCL_SPECULAR_RED" },
+   { RADEON_SE_TCL_MATERIAL_SPECULAR_GREEN, "RADEON_SE_TCL_SPECULAR_GREEN" },
+   { RADEON_SE_TCL_MATERIAL_SPECULAR_BLUE, "RADEON_SE_TCL_SPECULAR_BLUE" },
+   { RADEON_SE_TCL_MATERIAL_SPECULAR_ALPHA, "RADEON_SE_TCL_SPECULAR_ALPHA" },
+   { RADEON_SE_TCL_SHININESS, "RADEON_SE_TCL_SHININESS" },
+   { RADEON_SE_COORD_FMT, "RADEON_SE_COORD_FMT" },
+   { RADEON_PP_TEX_SIZE_0, "RADEON_PP_TEX_SIZE_0" },
+   { RADEON_PP_TEX_SIZE_1, "RADEON_PP_TEX_SIZE_1" },
+   { RADEON_PP_TEX_SIZE_2, "RADEON_PP_TEX_SIZE_2" },
+   { RADEON_PP_TEX_SIZE_0+4, "RADEON_PP_TEX_PITCH_0" },
+   { RADEON_PP_TEX_SIZE_1+4, "RADEON_PP_TEX_PITCH_1" },
+   { RADEON_PP_TEX_SIZE_2+4, "RADEON_PP_TEX_PITCH_2" },
+};
+
+static struct reg_names scalar_names[] = {
+   { RADEON_SS_LIGHT_DCD_ADDR, "LIGHT_DCD" },
+   { RADEON_SS_LIGHT_SPOT_EXPONENT_ADDR, "LIGHT_SPOT_EXPONENT" },
+   { RADEON_SS_LIGHT_SPOT_CUTOFF_ADDR, "LIGHT_SPOT_CUTOFF" },
+   { RADEON_SS_LIGHT_SPECULAR_THRESH_ADDR, "LIGHT_SPECULAR_THRESH" },
+   { RADEON_SS_LIGHT_RANGE_CUTOFF_ADDR, "LIGHT_RANGE_CUTOFF" },
+   { RADEON_SS_VERT_GUARD_CLIP_ADJ_ADDR, "VERT_GUARD_CLIP" },
+   { RADEON_SS_VERT_GUARD_DISCARD_ADJ_ADDR, "VERT_GUARD_DISCARD" },
+   { RADEON_SS_HORZ_GUARD_CLIP_ADJ_ADDR, "HORZ_GUARD_CLIP" },
+   { RADEON_SS_HORZ_GUARD_DISCARD_ADJ_ADDR, "HORZ_GUARD_DISCARD" },
+   { RADEON_SS_SHININESS, "SHININESS" },
+   { 1000, "" },
+};
+
+/* Puff these out to make them look like normal (dword) registers.
+ */
+static struct reg_names vector_names[] = {
+   { RADEON_VS_MATRIX_0_ADDR * 4, "MATRIX_0" },
+   { RADEON_VS_MATRIX_1_ADDR * 4, "MATRIX_1" },
+   { RADEON_VS_MATRIX_2_ADDR * 4, "MATRIX_2" },
+   { RADEON_VS_MATRIX_3_ADDR * 4, "MATRIX_3" },
+   { RADEON_VS_MATRIX_4_ADDR * 4, "MATRIX_4" },
+   { RADEON_VS_MATRIX_5_ADDR * 4, "MATRIX_5" },
+   { RADEON_VS_MATRIX_6_ADDR * 4, "MATRIX_6" },
+   { RADEON_VS_MATRIX_7_ADDR * 4, "MATRIX_7" },
+   { RADEON_VS_MATRIX_8_ADDR * 4, "MATRIX_8" },
+   { RADEON_VS_MATRIX_9_ADDR * 4, "MATRIX_9" },
+   { RADEON_VS_MATRIX_10_ADDR * 4, "MATRIX_10" },
+   { RADEON_VS_MATRIX_11_ADDR * 4, "MATRIX_11" },
+   { RADEON_VS_MATRIX_12_ADDR * 4, "MATRIX_12" },
+   { RADEON_VS_MATRIX_13_ADDR * 4, "MATRIX_13" },
+   { RADEON_VS_MATRIX_14_ADDR * 4, "MATRIX_14" },
+   { RADEON_VS_MATRIX_15_ADDR * 4, "MATRIX_15" },
+   { RADEON_VS_LIGHT_AMBIENT_ADDR * 4, "LIGHT_AMBIENT" },
+   { RADEON_VS_LIGHT_DIFFUSE_ADDR * 4, "LIGHT_DIFFUSE" },
+   { RADEON_VS_LIGHT_SPECULAR_ADDR * 4, "LIGHT_SPECULAR" },
+   { RADEON_VS_LIGHT_DIRPOS_ADDR * 4, "LIGHT_DIRPOS" },
+   { RADEON_VS_LIGHT_HWVSPOT_ADDR * 4, "LIGHT_HWVSPOT" },
+   { RADEON_VS_LIGHT_ATTENUATION_ADDR * 4, "LIGHT_ATTENUATION" },
+   { RADEON_VS_MATRIX_EYE2CLIP_ADDR * 4, "MATRIX_EYE2CLIP" },
+   { RADEON_VS_UCP_ADDR * 4, "UCP" },
+   { RADEON_VS_GLOBAL_AMBIENT_ADDR * 4, "GLOBAL_AMBIENT" },
+   { RADEON_VS_FOG_PARAM_ADDR * 4, "FOG_PARAM" },
+   { RADEON_VS_EYE_VECTOR_ADDR * 4, "EYE_VECTOR" },
+   { 1000, "" },
+};
+
+union fi { float f; int i; };
+
+#define ISVEC   1
+#define ISFLOAT 2
+#define TOUCHED 4
+
+struct reg {
+   int idx; 
+   struct reg_names *closest;
+   int flags;
+   union fi current;
+   union fi *values;
+   int nvalues;
+   int nalloc;
+   float vmin, vmax;
+};
+
+
+static struct reg regs[Elements(reg_names)+1];
+static struct reg scalars[512+1];
+static struct reg vectors[512*4+1];
+
+static int total, total_changed, bufs;
+
+static void init_regs( void )
+{
+   struct reg_names *tmp;
+   int i;
+
+   for (i = 0 ; i < Elements(regs) ; i++) {
+      regs[i].idx = reg_names[i].idx;
+      regs[i].closest = &reg_names[i];
+      regs[i].flags = 0;
+   }
+
+   for (i = 0, tmp = scalar_names ; i < Elements(scalars) ; i++) {
+      if (tmp[1].idx == i) tmp++;
+      scalars[i].idx = i;
+      scalars[i].closest = tmp;
+      scalars[i].flags = ISFLOAT;
+   }
+
+   for (i = 0, tmp = vector_names ; i < Elements(vectors) ; i++) {
+      if (tmp[1].idx*4 == i) tmp++;
+      vectors[i].idx = i;
+      vectors[i].closest = tmp;
+      vectors[i].flags = ISFLOAT|ISVEC;
+   }
+
+   regs[Elements(regs)-1].idx = -1;
+   scalars[Elements(scalars)-1].idx = -1;
+   vectors[Elements(vectors)-1].idx = -1;
+}
+
+static int find_or_add_value( struct reg *reg, int val )
+{
+   int j;
+
+   for ( j = 0 ; j < reg->nvalues ; j++)
+      if ( val == reg->values[j].i )
+        return 1;
+
+   if (j == reg->nalloc) {
+      reg->nalloc += 5;
+      reg->nalloc *= 2;
+      reg->values = (union fi *) realloc( reg->values, 
+                                         reg->nalloc * sizeof(union fi) );
+   }
+
+   reg->values[reg->nvalues++].i = val;
+   return 0;
+}
+
+static struct reg *lookup_reg( struct reg *tab, int reg )
+{
+   int i;
+
+   for (i = 0 ; tab[i].idx != -1 ; i++) {
+      if (tab[i].idx == reg)
+        return &tab[i];
+   }
+
+   fprintf(stderr, "*** unknown reg 0x%x\n", reg);
+   return 0;
+}
+
+
+static const char *get_reg_name( struct reg *reg )
+{
+   static char tmp[80];
+
+   if (reg->idx == reg->closest->idx) 
+      return reg->closest->name;
+
+   
+   if (reg->flags & ISVEC) {
+      if (reg->idx/4 != reg->closest->idx)
+        sprintf(tmp, "%s+%d[%d]", 
+                reg->closest->name, 
+                (reg->idx/4) - reg->closest->idx,
+                reg->idx%4);
+      else
+        sprintf(tmp, "%s[%d]", reg->closest->name, reg->idx%4);
+   }
+   else {
+      if (reg->idx != reg->closest->idx)
+        sprintf(tmp, "%s+%d", reg->closest->name, reg->idx - reg->closest->idx);
+      else
+        sprintf(tmp, "%s", reg->closest->name);
+   }
+
+   return tmp;
+}
+
+static int print_int_reg_assignment( struct reg *reg, int data )
+{
+   int changed = (reg->current.i != data);
+   int ever_seen = find_or_add_value( reg, data );
+   
+   if (VERBOSE || (NORMAL && (changed || !ever_seen)))
+       fprintf(stderr, "   %s <-- 0x%x", get_reg_name(reg), data);
+       
+   if (NORMAL) {
+      if (!ever_seen) 
+        fprintf(stderr, " *** BRAND NEW VALUE");
+      else if (changed) 
+        fprintf(stderr, " *** CHANGED"); 
+   }
+   
+   reg->current.i = data;
+
+   if (VERBOSE || (NORMAL && (changed || !ever_seen)))
+      fprintf(stderr, "\n");
+
+   return changed;
+}
+
+
+static int print_float_reg_assignment( struct reg *reg, float data )
+{
+   int changed = (reg->current.f != data);
+   int newmin = (data < reg->vmin);
+   int newmax = (data > reg->vmax);
+
+   if (VERBOSE || (NORMAL && (newmin || newmax || changed)))
+      fprintf(stderr, "   %s <-- %.3f", get_reg_name(reg), data);
+
+   if (NORMAL) {
+      if (newmin) {
+        fprintf(stderr, " *** NEW MIN (prev %.3f)", reg->vmin);
+        reg->vmin = data;
+      }
+      else if (newmax) {
+        fprintf(stderr, " *** NEW MAX (prev %.3f)", reg->vmax);
+        reg->vmax = data;
+      }
+      else if (changed) {
+        fprintf(stderr, " *** CHANGED");
+      }
+   }
+
+   reg->current.f = data;
+
+   if (VERBOSE || (NORMAL && (newmin || newmax || changed)))
+      fprintf(stderr, "\n");
+
+   return changed;
+}
+
+static int print_reg_assignment( struct reg *reg, int data )
+{
+   reg->flags |= TOUCHED;
+   if (reg->flags & ISFLOAT)
+      return print_float_reg_assignment( reg, *(float *)&data );
+   else
+      return print_int_reg_assignment( reg, data );
+}
+
+static void print_reg( struct reg *reg )
+{
+   if (reg->flags & TOUCHED) {
+      if (reg->flags & ISFLOAT) {
+        fprintf(stderr, "   %s == %f\n", get_reg_name(reg), reg->current.f);
+      } else {
+        fprintf(stderr, "   %s == 0x%x\n", get_reg_name(reg), reg->current.i);
+      }
+   }
+}
+
+
+static void dump_state( void )
+{
+   int i;
+
+   for (i = 0 ; i < Elements(regs) ; i++) 
+      print_reg( &regs[i] );
+
+   for (i = 0 ; i < Elements(scalars) ; i++) 
+      print_reg( &scalars[i] );
+
+   for (i = 0 ; i < Elements(vectors) ; i++) 
+      print_reg( &vectors[i] );
+}
+
+
+
+static int radeon_emit_packets( 
+   drmRadeonCmdHeader header,
+   drmRadeonCmdBuffer *cmdbuf )
+{
+   int id = (int)header.packet.packet_id;
+   int sz = packet[id].len;
+   int *data = (int *)cmdbuf->buf;
+   int i;
+   
+   if (sz * sizeof(int) > cmdbuf->bufsz) {
+      fprintf(stderr, "Packet overflows cmdbuf\n");      
+      return -EINVAL;
+   }
+
+   if (!packet[id].name) {
+      fprintf(stderr, "*** Unknown packet 0 nr %d\n", id );
+      return -EINVAL;
+   }
+
+   
+   if (VERBOSE) 
+      fprintf(stderr, "Packet 0 reg %s nr %d\n", packet[id].name, sz );
+
+   for ( i = 0 ; i < sz ; i++) {
+      struct reg *reg = lookup_reg( regs, packet[id].start + i*4 );
+      if (print_reg_assignment( reg, data[i] ))
+        total_changed++;
+      total++;
+   }
+
+   cmdbuf->buf += sz * sizeof(int);
+   cmdbuf->bufsz -= sz * sizeof(int);
+   return 0;
+}
+
+
+static int radeon_emit_scalars( 
+   drmRadeonCmdHeader header,
+   drmRadeonCmdBuffer *cmdbuf )
+{
+   int sz = header.scalars.count;
+   int *data = (int *)cmdbuf->buf;
+   int start = header.scalars.offset;
+   int stride = header.scalars.stride;
+   int i;
+
+   if (VERBOSE)
+      fprintf(stderr, "emit scalars, start %d stride %d nr %d (end %d)\n",
+             start, stride, sz, start + stride * sz);
+
+
+   for (i = 0 ; i < sz ; i++, start += stride) {
+      struct reg *reg = lookup_reg( scalars, start );
+      if (print_reg_assignment( reg, data[i] ))
+        total_changed++;
+      total++;
+   }
+        
+   cmdbuf->buf += sz * sizeof(int);
+   cmdbuf->bufsz -= sz * sizeof(int);
+   return 0;
+}
+
+
+static int radeon_emit_scalars2( 
+   drmRadeonCmdHeader header,
+   drmRadeonCmdBuffer *cmdbuf )
+{
+   int sz = header.scalars.count;
+   int *data = (int *)cmdbuf->buf;
+   int start = header.scalars.offset + 0x100;
+   int stride = header.scalars.stride;
+   int i;
+
+   if (VERBOSE)
+      fprintf(stderr, "emit scalars2, start %d stride %d nr %d (end %d)\n",
+             start, stride, sz, start + stride * sz);
+
+   if (start + stride * sz > 257) {
+      fprintf(stderr, "emit scalars OVERFLOW %d/%d/%d\n", start, stride, sz);
+      return -1;
+   }
+
+   for (i = 0 ; i < sz ; i++, start += stride) {
+      struct reg *reg = lookup_reg( scalars, start );
+      if (print_reg_assignment( reg, data[i] ))
+        total_changed++;
+      total++;
+   }
+        
+   cmdbuf->buf += sz * sizeof(int);
+   cmdbuf->bufsz -= sz * sizeof(int);
+   return 0;
+}
+
+/* Check: inf/nan/extreme-size?
+ * Check: table start, end, nr, etc.
+ */
+static int radeon_emit_vectors( 
+   drmRadeonCmdHeader header,
+   drmRadeonCmdBuffer *cmdbuf )
+{
+   int sz = header.vectors.count;
+   int *data = (int *)cmdbuf->buf;
+   int start = header.vectors.offset;
+   int stride = header.vectors.stride;
+   int i,j;
+
+   if (VERBOSE)
+      fprintf(stderr, "emit vectors, start %d stride %d nr %d (end %d) (0x%x)\n",
+             start, stride, sz, start + stride * sz, header.i);
+
+/*    if (start + stride * (sz/4) > 128) { */
+/*       fprintf(stderr, "emit vectors OVERFLOW %d/%d/%d\n", start, stride, sz); */
+/*       return -1; */
+/*    } */
+
+   for (i = 0 ; i < sz ;  start += stride) {
+      int changed = 0;
+      for (j = 0 ; j < 4 ; i++,j++) {
+        struct reg *reg = lookup_reg( vectors, start*4+j );
+        if (print_reg_assignment( reg, data[i] ))
+           changed = 1;
+      }
+      if (changed)
+        total_changed += 4;
+      total += 4;
+   }
+        
+
+   cmdbuf->buf += sz * sizeof(int);
+   cmdbuf->bufsz -= sz * sizeof(int);
+   return 0;
+}
+
+
+static int print_vertex_format( int vfmt )
+{
+   if (NORMAL) {
+      fprintf(stderr, "   %s(%x): %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+             "vertex format",
+             vfmt,
+             "xy,",
+             (vfmt & RADEON_CP_VC_FRMT_Z) ? "z," : "",
+             (vfmt & RADEON_CP_VC_FRMT_W0) ? "w0," : "",
+             (vfmt & RADEON_CP_VC_FRMT_FPCOLOR) ? "fpcolor," : "",
+             (vfmt & RADEON_CP_VC_FRMT_FPALPHA) ? "fpalpha," : "",
+             (vfmt & RADEON_CP_VC_FRMT_PKCOLOR) ? "pkcolor," : "",
+             (vfmt & RADEON_CP_VC_FRMT_FPSPEC) ? "fpspec," : "",
+             (vfmt & RADEON_CP_VC_FRMT_FPFOG) ? "fpfog," : "",
+             (vfmt & RADEON_CP_VC_FRMT_PKSPEC) ? "pkspec," : "",
+             (vfmt & RADEON_CP_VC_FRMT_ST0) ? "st0," : "",
+             (vfmt & RADEON_CP_VC_FRMT_ST1) ? "st1," : "",
+             (vfmt & RADEON_CP_VC_FRMT_Q1) ? "q1," : "",
+             (vfmt & RADEON_CP_VC_FRMT_ST2) ? "st2," : "",
+             (vfmt & RADEON_CP_VC_FRMT_Q2) ? "q2," : "",
+             (vfmt & RADEON_CP_VC_FRMT_ST3) ? "st3," : "",
+             (vfmt & RADEON_CP_VC_FRMT_Q3) ? "q3," : "",
+             (vfmt & RADEON_CP_VC_FRMT_Q0) ? "q0," : "",
+             (vfmt & RADEON_CP_VC_FRMT_N0) ? "n0," : "",
+             (vfmt & RADEON_CP_VC_FRMT_XY1) ? "xy1," : "",
+             (vfmt & RADEON_CP_VC_FRMT_Z1) ? "z1," : "",
+             (vfmt & RADEON_CP_VC_FRMT_W1) ? "w1," : "",
+             (vfmt & RADEON_CP_VC_FRMT_N1) ? "n1," : "");
+
+   
+/*       if (!find_or_add_value( &others[V_VTXFMT], vfmt )) */
+/*      fprintf(stderr, " *** NEW VALUE"); */
+
+      fprintf(stderr, "\n");
+   }
+
+   return 0;
+}
+
+static char *primname[0xf] = {
+   "NONE",
+   "POINTS",
+   "LINES",
+   "LINE_STRIP",
+   "TRIANGLES",
+   "TRIANGLE_FAN",
+   "TRIANGLE_STRIP",
+   "TRI_TYPE_2",
+   "RECT_LIST",
+   "3VRT_POINTS",
+   "3VRT_LINES",
+};
+
+static int print_prim_and_flags( int prim )
+{
+   int numverts;
+   
+   if (NORMAL)
+      fprintf(stderr, "   %s(%x): %s%s%s%s%s%s%s\n",
+             "prim flags",
+             prim,
+             ((prim & 0x30) == RADEON_CP_VC_CNTL_PRIM_WALK_IND) ? "IND," : "",
+             ((prim & 0x30) == RADEON_CP_VC_CNTL_PRIM_WALK_LIST) ? "LIST," : "",
+             ((prim & 0x30) == RADEON_CP_VC_CNTL_PRIM_WALK_RING) ? "RING," : "",
+             (prim & RADEON_CP_VC_CNTL_COLOR_ORDER_RGBA) ? "RGBA," : "BGRA, ",
+             (prim & RADEON_CP_VC_CNTL_MAOS_ENABLE) ? "MAOS," : "",
+             (prim & RADEON_CP_VC_CNTL_VTX_FMT_RADEON_MODE) ? "RADEON," : "",
+             (prim & RADEON_CP_VC_CNTL_TCL_ENABLE) ? "TCL," : "");
+
+   if ((prim & 0xf) > RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST) {
+      fprintf(stderr, "   *** Bad primitive: %x\n", prim & 0xf);
+      return -1;
+   }
+
+   numverts = prim>>16;
+   
+   if (NORMAL)
+      fprintf(stderr, "   prim: %s numverts %d\n", primname[prim&0xf], numverts);
+
+   switch (prim & 0xf) {
+   case RADEON_CP_VC_CNTL_PRIM_TYPE_NONE:
+   case RADEON_CP_VC_CNTL_PRIM_TYPE_POINT:
+      if (numverts < 1) {
+        fprintf(stderr, "Bad nr verts for line %d\n", numverts);
+        return -1;
+      }
+      break;
+   case RADEON_CP_VC_CNTL_PRIM_TYPE_LINE:
+      if ((numverts & 1) || numverts == 0) {
+        fprintf(stderr, "Bad nr verts for line %d\n", numverts);
+        return -1;
+      }
+      break;
+   case RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP:
+      if (numverts < 2) {
+        fprintf(stderr, "Bad nr verts for line_strip %d\n", numverts);
+        return -1;
+      }
+      break;
+   case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST:
+   case RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_POINT_LIST:
+   case RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST:
+   case RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST:
+      if (numverts % 3 || numverts == 0) {
+        fprintf(stderr, "Bad nr verts for tri %d\n", numverts);
+        return -1;
+      }
+      break;
+   case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN:
+   case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP:
+      if (numverts < 3) {
+        fprintf(stderr, "Bad nr verts for strip/fan %d\n", numverts);
+        return -1;
+      }
+      break;
+   default:
+      fprintf(stderr, "Bad primitive\n");
+      return -1;
+   }   
+   return 0;
+}
+
+/* build in knowledge about each packet type
+ */
+static int radeon_emit_packet3( drmRadeonCmdBuffer *cmdbuf )
+{
+   int cmdsz;
+   int *cmd = (int *)cmdbuf->buf;
+   int *tmp;
+   int i, stride, size, start;
+
+   cmdsz = 2 + ((cmd[0] & RADEON_CP_PACKET_COUNT_MASK) >> 16);
+
+   if ((cmd[0] & RADEON_CP_PACKET_MASK) != RADEON_CP_PACKET3 ||
+       cmdsz * 4 > cmdbuf->bufsz ||
+       cmdsz > RADEON_CP_PACKET_MAX_DWORDS) {
+      fprintf(stderr, "Bad packet\n");
+      return -EINVAL;
+   }
+
+   switch( cmd[0] & ~RADEON_CP_PACKET_COUNT_MASK ) {
+   case RADEON_CP_PACKET3_NOP:
+      if (NORMAL)
+        fprintf(stderr, "PACKET3_NOP, %d dwords\n", cmdsz);
+      break;
+   case RADEON_CP_PACKET3_NEXT_CHAR:
+      if (NORMAL)
+        fprintf(stderr, "PACKET3_NEXT_CHAR, %d dwords\n", cmdsz);
+      break;
+   case RADEON_CP_PACKET3_PLY_NEXTSCAN:
+      if (NORMAL)
+        fprintf(stderr, "PACKET3_PLY_NEXTSCAN, %d dwords\n", cmdsz);
+      break;
+   case RADEON_CP_PACKET3_SET_SCISSORS:
+      if (NORMAL)
+        fprintf(stderr, "PACKET3_SET_SCISSORS, %d dwords\n", cmdsz);
+      break;
+   case RADEON_CP_PACKET3_3D_RNDR_GEN_INDX_PRIM:
+      if (NORMAL)
+        fprintf(stderr, "PACKET3_3D_RNDR_GEN_INDX_PRIM, %d dwords\n",
+             cmdsz);
+      break;
+   case RADEON_CP_PACKET3_LOAD_MICROCODE:
+      if (NORMAL)
+        fprintf(stderr, "PACKET3_LOAD_MICROCODE, %d dwords\n", cmdsz);
+      break;
+   case RADEON_CP_PACKET3_WAIT_FOR_IDLE:
+      if (NORMAL)
+        fprintf(stderr, "PACKET3_WAIT_FOR_IDLE, %d dwords\n", cmdsz);
+      break;
+
+   case RADEON_CP_PACKET3_3D_DRAW_VBUF:
+      if (NORMAL)
+        fprintf(stderr, "PACKET3_3D_DRAW_VBUF, %d dwords\n", cmdsz);
+      print_vertex_format(cmd[1]);
+      print_prim_and_flags(cmd[2]);
+      break;
+
+   case RADEON_CP_PACKET3_3D_DRAW_IMMD:
+      if (NORMAL)
+        fprintf(stderr, "PACKET3_3D_DRAW_IMMD, %d dwords\n", cmdsz);
+      break;
+   case RADEON_CP_PACKET3_3D_DRAW_INDX: {
+      int neltdwords;
+      if (NORMAL)
+        fprintf(stderr, "PACKET3_3D_DRAW_INDX, %d dwords\n", cmdsz);
+      print_vertex_format(cmd[1]);
+      print_prim_and_flags(cmd[2]);
+      neltdwords = cmd[2]>>16;
+      neltdwords += neltdwords & 1;
+      neltdwords /= 2;
+      if (neltdwords + 3 != cmdsz)
+        fprintf(stderr, "Mismatch in DRAW_INDX, %d vs cmdsz %d\n",
+                neltdwords, cmdsz);
+      break;
+   }
+   case RADEON_CP_PACKET3_LOAD_PALETTE:
+      if (NORMAL)
+        fprintf(stderr, "PACKET3_LOAD_PALETTE, %d dwords\n", cmdsz);
+      break;
+   case RADEON_CP_PACKET3_3D_LOAD_VBPNTR:
+      if (NORMAL) {
+        fprintf(stderr, "PACKET3_3D_LOAD_VBPNTR, %d dwords\n", cmdsz);
+        fprintf(stderr, "   nr arrays: %d\n", cmd[1]);
+      }
+
+      if (cmd[1]/2 + cmd[1]%2 != cmdsz - 3) {
+        fprintf(stderr, "  ****** MISMATCH %d/%d *******\n",
+                cmd[1]/2 + cmd[1]%2 + 3, cmdsz);
+        return -EINVAL;
+      }
+
+      if (NORMAL) {
+        tmp = cmd+2;
+        for (i = 0 ; i < cmd[1] ; i++) {
+           if (i & 1) {
+              stride = (tmp[0]>>24) & 0xff;
+              size = (tmp[0]>>16) & 0xff;
+              start = tmp[2];
+              tmp += 3;
+           }
+           else {
+              stride = (tmp[0]>>8) & 0xff;
+              size = (tmp[0]) & 0xff;
+              start = tmp[1];
+           }
+           fprintf(stderr, "   array %d: start 0x%x vsize %d vstride %d\n",
+                   i, start, size, stride );
+        }
+      }
+      break;
+   case RADEON_CP_PACKET3_CNTL_PAINT:
+      if (NORMAL)
+        fprintf(stderr, "PACKET3_CNTL_PAINT, %d dwords\n", cmdsz);
+      break;
+   case RADEON_CP_PACKET3_CNTL_BITBLT:
+      if (NORMAL)
+        fprintf(stderr, "PACKET3_CNTL_BITBLT, %d dwords\n", cmdsz);
+      break;
+   case RADEON_CP_PACKET3_CNTL_SMALLTEXT:
+      if (NORMAL)
+        fprintf(stderr, "PACKET3_CNTL_SMALLTEXT, %d dwords\n", cmdsz);
+      break;
+   case RADEON_CP_PACKET3_CNTL_HOSTDATA_BLT:
+      if (NORMAL)
+        fprintf(stderr, "PACKET3_CNTL_HOSTDATA_BLT, %d dwords\n", 
+             cmdsz);
+      break;
+   case RADEON_CP_PACKET3_CNTL_POLYLINE:
+      if (NORMAL)
+        fprintf(stderr, "PACKET3_CNTL_POLYLINE, %d dwords\n", cmdsz);
+      break;
+   case RADEON_CP_PACKET3_CNTL_POLYSCANLINES:
+      if (NORMAL)
+        fprintf(stderr, "PACKET3_CNTL_POLYSCANLINES, %d dwords\n", 
+             cmdsz);
+      break;
+   case RADEON_CP_PACKET3_CNTL_PAINT_MULTI:
+      if (NORMAL)
+        fprintf(stderr, "PACKET3_CNTL_PAINT_MULTI, %d dwords\n", 
+             cmdsz);
+      break;
+   case RADEON_CP_PACKET3_CNTL_BITBLT_MULTI:
+      if (NORMAL)
+        fprintf(stderr, "PACKET3_CNTL_BITBLT_MULTI, %d dwords\n", 
+             cmdsz);
+      break;
+   case RADEON_CP_PACKET3_CNTL_TRANS_BITBLT:
+      if (NORMAL)
+        fprintf(stderr, "PACKET3_CNTL_TRANS_BITBLT, %d dwords\n", 
+             cmdsz);
+      break;
+   default:
+      fprintf(stderr, "UNKNOWN PACKET, %d dwords\n", cmdsz);
+      break;
+   }
+      
+   cmdbuf->buf += cmdsz * 4;
+   cmdbuf->bufsz -= cmdsz * 4;
+   return 0;
+}
+
+
+/* Check cliprects for bounds, then pass on to above:
+ */
+static int radeon_emit_packet3_cliprect( drmRadeonCmdBuffer *cmdbuf )
+{   
+   XF86DRIClipRectRec *boxes = (XF86DRIClipRectRec *)cmdbuf->boxes;
+   int i = 0;
+
+   if (VERBOSE && total_changed) {
+      dump_state();
+      total_changed = 0;
+   }
+   else fprintf(stderr, "total_changed zero\n");
+
+   if (NORMAL) {
+      do {
+        if ( i < cmdbuf->nbox ) {
+           fprintf(stderr, "Emit box %d/%d %d,%d %d,%d\n",
+                   i, cmdbuf->nbox,
+                   boxes[i].x1, boxes[i].y1, boxes[i].x2, boxes[i].y2);
+        }
+      } while ( ++i < cmdbuf->nbox );
+   }
+
+   if (cmdbuf->nbox == 1)
+      cmdbuf->nbox = 0;
+
+   return radeon_emit_packet3( cmdbuf );
+}
+
+
+int radeonSanityCmdBuffer( radeonContextPtr rmesa,
+                          int nbox,
+                          XF86DRIClipRectRec *boxes )
+{
+   int idx;
+   drmRadeonCmdBuffer cmdbuf;
+   drmRadeonCmdHeader header;
+   static int inited = 0;
+
+   if (!inited) {
+      init_regs();
+      inited = 1;
+   }
+
+   cmdbuf.buf = rmesa->store.cmd_buf;
+   cmdbuf.bufsz = rmesa->store.cmd_used;
+   cmdbuf.boxes = (drmClipRect *)boxes;
+   cmdbuf.nbox = nbox;
+
+   while ( cmdbuf.bufsz >= sizeof(header) ) {
+               
+      header.i = *(int *)cmdbuf.buf;
+      cmdbuf.buf += sizeof(header);
+      cmdbuf.bufsz -= sizeof(header);
+
+      switch (header.header.cmd_type) {
+      case RADEON_CMD_PACKET: 
+        if (radeon_emit_packets( header, &cmdbuf )) {
+           fprintf(stderr,"radeon_emit_packets failed\n");
+           return -EINVAL;
+        }
+        break;
+
+      case RADEON_CMD_SCALARS:
+        if (radeon_emit_scalars( header, &cmdbuf )) {
+           fprintf(stderr,"radeon_emit_scalars failed\n");
+           return -EINVAL;
+        }
+        break;
+
+      case RADEON_CMD_SCALARS2:
+        if (radeon_emit_scalars2( header, &cmdbuf )) {
+           fprintf(stderr,"radeon_emit_scalars failed\n");
+           return -EINVAL;
+        }
+        break;
+
+      case RADEON_CMD_VECTORS:
+        if (radeon_emit_vectors( header, &cmdbuf )) {
+           fprintf(stderr,"radeon_emit_vectors failed\n");
+           return -EINVAL;
+        }
+        break;
+
+      case RADEON_CMD_DMA_DISCARD:
+        idx = header.dma.buf_idx;
+        if (NORMAL)
+           fprintf(stderr, "RADEON_CMD_DMA_DISCARD buf %d\n", idx);
+        bufs++;
+        break;
+
+      case RADEON_CMD_PACKET3:
+        if (radeon_emit_packet3( &cmdbuf )) {
+           fprintf(stderr,"radeon_emit_packet3 failed\n");
+           return -EINVAL;
+        }
+        break;
+
+      case RADEON_CMD_PACKET3_CLIP:
+        if (radeon_emit_packet3_cliprect( &cmdbuf )) {
+           fprintf(stderr,"radeon_emit_packet3_clip failed\n");
+           return -EINVAL;
+        }
+        break;
+
+      case RADEON_CMD_WAIT:
+        break;
+
+      default:
+        fprintf(stderr,"bad cmd_type %d at %p\n", 
+                  header.header.cmd_type,
+                  cmdbuf.buf - sizeof(header));
+        return -EINVAL;
+      }
+   }
+
+   if (0)
+   {
+      static int n = 0;
+      n++;
+      if (n == 10) {
+        fprintf(stderr, "Bufs %d Total emitted %d real changes %d (%.2f%%)\n",
+                bufs,
+                total, total_changed, 
+                ((float)total_changed/(float)total*100.0));
+        fprintf(stderr, "Total emitted per buf: %.2f\n",
+                (float)total/(float)bufs);
+        fprintf(stderr, "Real changes per buf: %.2f\n",
+                (float)total_changed/(float)bufs);
+
+        bufs = n = total = total_changed = 0;
+      }
+   }
+
+   return 0;
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_sanity.h b/src/mesa/drivers/dri/radeon/radeon_sanity.h
new file mode 100644 (file)
index 0000000..58e8335
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef RADEON_SANITY_H
+#define RADEON_SANITY_H
+
+extern int radeonSanityCmdBuffer( radeonContextPtr rmesa,
+                                 int nbox,
+                                 XF86DRIClipRectRec *boxes );
+
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.c b/src/mesa/drivers/dri/radeon/radeon_screen.c
new file mode 100644 (file)
index 0000000..ec8ed42
--- /dev/null
@@ -0,0 +1,421 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_screen.c,v 1.6 2002/12/16 16:18:58 dawes Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#include "glheader.h"
+#include "imports.h"
+
+#include "radeon_context.h"
+#include "radeon_screen.h"
+#include "radeon_macros.h"
+
+#include "utils.h"
+#include "context.h"
+#include "vblank.h"
+
+#ifndef _SOLO
+#include "glxextensions.h"
+#endif 
+
+#if 1
+/* Including xf86PciInfo.h introduces a bunch of errors...
+ */
+#define PCI_CHIP_RADEON_QD     0x5144
+#define PCI_CHIP_RADEON_QE     0x5145
+#define PCI_CHIP_RADEON_QF     0x5146
+#define PCI_CHIP_RADEON_QG     0x5147
+
+#define PCI_CHIP_RADEON_QY     0x5159
+#define PCI_CHIP_RADEON_QZ     0x515A
+
+#define PCI_CHIP_RADEON_LW     0x4C57 /* mobility 7 - has tcl */
+
+#define PCI_CHIP_RADEON_LY     0x4C59
+#define PCI_CHIP_RADEON_LZ     0x4C5A
+
+#define PCI_CHIP_RV200_QW      0x5157 /* Radeon 7500 - not an R200 at all */
+#endif
+
+static int getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo );
+
+/* Create the device specific screen private data struct.
+ */
+radeonScreenPtr radeonCreateScreen( __DRIscreenPrivate *sPriv )
+{
+   radeonScreenPtr screen;
+   RADEONDRIPtr dri_priv = (RADEONDRIPtr)sPriv->pDevPriv;
+
+   if ( ! driCheckDriDdxDrmVersions( sPriv, "Radeon", 4, 0, 4, 0, 1, 3 ) )
+      return NULL;
+
+   /* Allocate the private area */
+   screen = (radeonScreenPtr) CALLOC( sizeof(*screen) );
+   if ( !screen ) {
+      __driUtilMessage("%s: Could not allocate memory for screen structure",
+                      __FUNCTION__);
+      return NULL;
+   }
+
+   if ( sPriv->drmMinor < 3 ||
+        getenv("RADEON_COMPAT")) {
+          fprintf( stderr, "Radeon DRI driver:\n\t"
+                   "Compatibility mode for DRM driver version %d.%d.%d\n\t"
+                   "TCL will be disabled, expect reduced performance\n\t"
+                   "(prefer DRM radeon.o 1.3.x or newer)\n\t", 
+                   sPriv->drmMajor, sPriv->drmMinor, sPriv->drmPatch ); 
+   }
+
+
+   /* This is first since which regions we map depends on whether or
+    * not we are using a PCI card.
+    */
+   screen->IsPCI = dri_priv->IsPCI;
+
+   if (sPriv->drmMinor >= 3) {
+      int ret;
+      drmRadeonGetParam gp;
+
+      gp.param = RADEON_PARAM_AGP_BUFFER_OFFSET;
+      gp.value = &screen->agp_buffer_offset;
+
+      ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM,
+                                &gp, sizeof(gp));
+      if (ret) {
+        fprintf(stderr, "drmRadeonGetParam (RADEON_PARAM_AGP_BUFFER_OFFSET): %d\n", ret);
+        return NULL;
+      }
+
+      if (sPriv->drmMinor >= 6) {
+        gp.param = RADEON_PARAM_IRQ_NR;
+        gp.value = &screen->irq;
+
+        ret = drmCommandWriteRead( sPriv->fd, DRM_RADEON_GETPARAM,
+                                   &gp, sizeof(gp));
+        if (ret) {
+           FREE( screen );
+           fprintf(stderr, "drmRadeonGetParam (RADEON_PARAM_IRQ_NR): %d\n", ret);
+           return NULL;
+        }
+      }
+   }
+
+   screen->mmio.handle = dri_priv->registerHandle;
+   screen->mmio.size   = dri_priv->registerSize;
+   if ( drmMap( sPriv->fd,
+               screen->mmio.handle,
+               screen->mmio.size,
+               &screen->mmio.map ) ) {
+      FREE( screen );
+      __driUtilMessage("%s: drmMap failed\n", __FUNCTION__ );
+      return NULL;
+   }
+
+   screen->status.handle = dri_priv->statusHandle;
+   screen->status.size   = dri_priv->statusSize;
+   if ( drmMap( sPriv->fd,
+               screen->status.handle,
+               screen->status.size,
+               &screen->status.map ) ) {
+      drmUnmap( screen->mmio.map, screen->mmio.size );
+      FREE( screen );
+      __driUtilMessage("%s: drmMap (2) failed\n", __FUNCTION__ );
+      return NULL;
+   }
+   screen->scratch = (__volatile__ CARD32 *)
+      ((GLubyte *)screen->status.map + RADEON_SCRATCH_REG_OFFSET);
+
+   screen->buffers = drmMapBufs( sPriv->fd );
+   if ( !screen->buffers ) {
+      drmUnmap( screen->status.map, screen->status.size );
+      drmUnmap( screen->mmio.map, screen->mmio.size );
+      FREE( screen );
+      __driUtilMessage("%s: drmMapBufs failed\n", __FUNCTION__ );
+      return NULL;
+   }
+
+   if ( !screen->IsPCI ) {
+      screen->agpTextures.handle = dri_priv->agpTexHandle;
+      screen->agpTextures.size   = dri_priv->agpTexMapSize;
+      if ( drmMap( sPriv->fd,
+                  screen->agpTextures.handle,
+                  screen->agpTextures.size,
+                  (drmAddressPtr)&screen->agpTextures.map ) ) {
+        drmUnmapBufs( screen->buffers );
+        drmUnmap( screen->status.map, screen->status.size );
+        drmUnmap( screen->mmio.map, screen->mmio.size );
+        FREE( screen );
+         __driUtilMessage("%s: IsPCI failed\n", __FUNCTION__);
+        return NULL;
+      }
+   }
+
+   screen->chipset = 0;
+   switch ( dri_priv->deviceID ) {
+   default:
+      fprintf(stderr, "unknown chip id, assuming full radeon support\n");
+   case PCI_CHIP_RADEON_QD:
+   case PCI_CHIP_RADEON_QE:
+   case PCI_CHIP_RADEON_QF:
+   case PCI_CHIP_RADEON_QG:
+   case PCI_CHIP_RV200_QW:
+   case PCI_CHIP_RADEON_LW:
+      screen->chipset |= RADEON_CHIPSET_TCL;
+   case PCI_CHIP_RADEON_QY:
+   case PCI_CHIP_RADEON_QZ:
+   case PCI_CHIP_RADEON_LY:
+   case PCI_CHIP_RADEON_LZ:
+      break;
+   }
+
+   screen->cpp = dri_priv->bpp / 8;
+   screen->AGPMode = dri_priv->AGPMode;
+
+   screen->frontOffset = dri_priv->frontOffset;
+   screen->frontPitch  = dri_priv->frontPitch;
+   screen->backOffset  = dri_priv->backOffset;
+   screen->backPitch   = dri_priv->backPitch;
+   screen->depthOffset = dri_priv->depthOffset;
+   screen->depthPitch  = dri_priv->depthPitch;
+
+   screen->texOffset[RADEON_CARD_HEAP] = dri_priv->textureOffset;
+   screen->texSize[RADEON_CARD_HEAP] = dri_priv->textureSize;
+   screen->logTexGranularity[RADEON_CARD_HEAP] =
+      dri_priv->log2TexGran;
+
+   if ( screen->IsPCI 
+       || getenv( "RADEON_AGPTEXTURING_FORCE_DISABLE" ) ) {
+      screen->numTexHeaps = RADEON_NR_TEX_HEAPS - 1;
+      screen->texOffset[RADEON_AGP_HEAP] = 0;
+      screen->texSize[RADEON_AGP_HEAP] = 0;
+      screen->logTexGranularity[RADEON_AGP_HEAP] = 0;
+   } else {
+      screen->numTexHeaps = RADEON_NR_TEX_HEAPS;
+      screen->texOffset[RADEON_AGP_HEAP] =
+        dri_priv->agpTexOffset + RADEON_AGP_TEX_OFFSET;
+      screen->texSize[RADEON_AGP_HEAP] = dri_priv->agpTexMapSize;
+      screen->logTexGranularity[RADEON_AGP_HEAP] =
+        dri_priv->log2AGPTexGran;
+   }
+
+   screen->driScreen = sPriv;
+   screen->sarea_priv_offset = dri_priv->sarea_priv_offset;
+   return screen;
+}
+
+/* Destroy the device specific screen private data struct.
+ */
+void radeonDestroyScreen( __DRIscreenPrivate *sPriv )
+{
+   radeonScreenPtr screen = (radeonScreenPtr)sPriv->private;
+
+   if (!screen)
+      return;
+
+   if ( !screen->IsPCI ) {
+      drmUnmap( screen->agpTextures.map,
+               screen->agpTextures.size );
+   }
+   drmUnmapBufs( screen->buffers );
+   drmUnmap( screen->status.map, screen->status.size );
+   drmUnmap( screen->mmio.map, screen->mmio.size );
+
+   FREE( screen );
+   sPriv->private = NULL;
+}
+
+
+/* Initialize the driver specific screen private data.
+ */
+static GLboolean
+radeonInitDriver( __DRIscreenPrivate *sPriv )
+{
+   sPriv->private = (void *) radeonCreateScreen( sPriv );
+   if ( !sPriv->private ) {
+      radeonDestroyScreen( sPriv );
+      return GL_FALSE;
+   }
+
+   return GL_TRUE;
+}
+
+
+
+/* Create and initialize the Mesa and driver specific pixmap buffer
+ * data.
+ */
+static GLboolean
+radeonCreateBuffer( __DRIscreenPrivate *driScrnPriv,
+                    __DRIdrawablePrivate *driDrawPriv,
+                    const __GLcontextModes *mesaVis,
+                    GLboolean isPixmap )
+{
+   if (isPixmap) {
+      return GL_FALSE; /* not implemented */
+   }
+   else {
+      const GLboolean swDepth = GL_FALSE;
+      const GLboolean swAlpha = GL_FALSE;
+      const GLboolean swAccum = mesaVis->accumRedBits > 0;
+      const GLboolean swStencil = mesaVis->stencilBits > 0 &&
+         mesaVis->depthBits != 24;
+      driDrawPriv->driverPrivate = (void *)
+         _mesa_create_framebuffer( mesaVis,
+                                   swDepth,
+                                   swStencil,
+                                   swAccum,
+                                   swAlpha );
+      return (driDrawPriv->driverPrivate != NULL);
+   }
+}
+
+
+static void
+radeonDestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
+{
+   _mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
+}
+
+
+
+
+/* Fullscreen mode isn't used for much -- could be a way to shrink
+ * front/back buffers & get more texture memory if the client has
+ * changed the video resolution.
+ * 
+ * Pageflipping is now done automatically whenever there is a single
+ * 3d client.
+ */
+static GLboolean
+radeonOpenCloseFullScreen( __DRIcontextPrivate *driContextPriv )
+{
+   return GL_TRUE;
+}
+
+static struct __DriverAPIRec radeonAPI = {
+   .InitDriver      = radeonInitDriver,
+   .DestroyScreen   = radeonDestroyScreen,
+   .CreateContext   = radeonCreateContext,
+   .DestroyContext  = radeonDestroyContext,
+   .CreateBuffer    = radeonCreateBuffer,
+   .DestroyBuffer   = radeonDestroyBuffer,
+   .SwapBuffers     = radeonSwapBuffers,
+   .MakeCurrent     = radeonMakeCurrent,
+   .UnbindContext   = radeonUnbindContext,
+   .OpenFullScreen  = radeonOpenCloseFullScreen,
+   .CloseFullScreen = radeonOpenCloseFullScreen,
+   .GetSwapInfo     = getSwapInfo,
+   .GetMSC          = driGetMSC32,
+   .WaitForMSC      = driWaitForMSC32,
+   .WaitForSBC      = NULL,
+   .SwapBuffersMSC  = NULL
+};
+
+
+
+/*
+ * This is the bootstrap function for the driver.
+ * The __driCreateScreen name is the symbol that libGL.so fetches.
+ * Return:  pointer to a __DRIscreenPrivate.
+ */
+#ifndef _SOLO
+void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
+                        int numConfigs, __GLXvisualConfig *config)
+{
+   __DRIscreenPrivate *psp;
+   psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &radeonAPI);
+   return (void *) psp;
+}
+#else
+void *__driCreateScreen(struct DRIDriverRec *driver,
+                        struct DRIDriverContextRec *driverContext)
+{
+   __DRIscreenPrivate *psp;
+   psp = __driUtilCreateScreen(driver, driverContext, &radeonAPI);
+   return (void *) psp;
+}
+#endif
+
+
+#ifndef _SOLO
+/* This function is called by libGL.so as soon as libGL.so is loaded.
+ * This is where we'd register new extension functions with the dispatcher.
+ */
+void
+__driRegisterExtensions( void )
+{
+   PFNGLXENABLEEXTENSIONPROC glx_enable_extension;
+
+
+   if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
+      glx_enable_extension = (PFNGLXENABLEEXTENSIONPROC)
+         glXGetProcAddress( "__glXEnableExtension" );
+
+      if ( glx_enable_extension != NULL ) {
+        glx_enable_extension( "GLX_SGI_swap_control", GL_FALSE );
+        glx_enable_extension( "GLX_SGI_video_sync", GL_FALSE );
+        glx_enable_extension( "GLX_MESA_swap_control", GL_FALSE );
+        glx_enable_extension( "GLX_MESA_swap_frame_usage", GL_FALSE );
+      }
+   }
+}
+#endif
+
+
+/**
+ * Get information about previous buffer swaps.
+ */
+static int
+getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo )
+{
+   radeonContextPtr  rmesa;
+
+   if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL)
+       || (dPriv->driContextPriv->driverPrivate == NULL)
+       || (sInfo == NULL) ) {
+      return -1;
+   }
+
+   rmesa = (radeonContextPtr) dPriv->driContextPriv->driverPrivate;
+   sInfo->swap_count = rmesa->swap_count;
+   sInfo->swap_ust = rmesa->swap_ust;
+   sInfo->swap_missed_count = rmesa->swap_missed_count;
+
+   sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
+       ? driCalculateSwapUsage( dPriv, 0, rmesa->swap_missed_ust )
+       : 0.0;
+
+   return 0;
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_screen.h b/src/mesa/drivers/dri/radeon/radeon_screen.h
new file mode 100644 (file)
index 0000000..2c69d86
--- /dev/null
@@ -0,0 +1,101 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_screen.h,v 1.5 2002/12/16 16:18:58 dawes Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifndef __RADEON_SCREEN_H__
+#define __RADEON_SCREEN_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+/*
+ * IMPORTS: these headers contain all the DRI, X and kernel-related
+ * definitions that we need.
+ */
+#include "dri_util.h"
+#include "radeon_common.h"
+#include "radeon_dri.h"
+#include "radeon_reg.h"
+#include "radeon_sarea.h"
+
+
+typedef struct {
+   drmHandle handle;                   /* Handle to the DRM region */
+   drmSize size;                       /* Size of the DRM region */
+   drmAddress map;                     /* Mapping of the DRM region */
+} radeonRegionRec, *radeonRegionPtr;
+
+/* chipset features */
+#define RADEON_CHIPSET_TCL     (1 << 0)
+
+typedef struct {
+
+   int chipset;
+   int cpp;
+   int IsPCI;                          /* Current card is a PCI card */
+   int AGPMode;
+   unsigned int irq;                   /* IRQ number (0 means none) */
+
+   unsigned int frontOffset;
+   unsigned int frontPitch;
+   unsigned int backOffset;
+   unsigned int backPitch;
+
+   unsigned int depthOffset;
+   unsigned int depthPitch;
+
+    /* Shared texture data */
+   int numTexHeaps;
+   int texOffset[RADEON_NR_TEX_HEAPS];
+   int texSize[RADEON_NR_TEX_HEAPS];
+   int logTexGranularity[RADEON_NR_TEX_HEAPS];
+
+   radeonRegionRec mmio;
+   radeonRegionRec status;
+   radeonRegionRec agpTextures;
+
+   drmBufMapPtr buffers;
+
+   __volatile__ CARD32 *scratch;
+
+   __DRIscreenPrivate *driScreen;
+   unsigned int sarea_priv_offset;
+   unsigned int agp_buffer_offset;     /* offset in card memory space */
+} radeonScreenRec, *radeonScreenPtr;
+
+extern radeonScreenPtr radeonCreateScreen( __DRIscreenPrivate *sPriv );
+extern void radeonDestroyScreen( __DRIscreenPrivate *sPriv );
+
+#endif
+#endif /* __RADEON_SCREEN_H__ */
diff --git a/src/mesa/drivers/dri/radeon/radeon_span.c b/src/mesa/drivers/dri/radeon/radeon_span.c
new file mode 100644 (file)
index 0000000..029d7cd
--- /dev/null
@@ -0,0 +1,415 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_span.c,v 1.6 2002/10/30 12:51:56 alanh Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Gareth Hughes <gareth@valinux.com>
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#include "glheader.h"
+#include "swrast/swrast.h"
+
+#include "radeon_context.h"
+#include "radeon_ioctl.h"
+#include "radeon_state.h"
+#include "radeon_span.h"
+#include "radeon_tex.h"
+
+#define DBG 0
+
+#define LOCAL_VARS                                                     \
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);                       \
+   radeonScreenPtr radeonScreen = rmesa->radeonScreen;                 \
+   __DRIscreenPrivate *sPriv = rmesa->dri.screen;                      \
+   __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;                  \
+   GLuint pitch = radeonScreen->frontPitch * radeonScreen->cpp;                \
+   GLuint height = dPriv->h;                                           \
+   char *buf = (char *)(sPriv->pFB +                                   \
+                       rmesa->state.color.drawOffset +                 \
+                       (dPriv->x * radeonScreen->cpp) +                \
+                       (dPriv->y * pitch));                            \
+   char *read_buf = (char *)(sPriv->pFB +                              \
+                            rmesa->state.pixel.readOffset +            \
+                            (dPriv->x * radeonScreen->cpp) +           \
+                            (dPriv->y * pitch));                       \
+   GLuint p;                                                           \
+   (void) read_buf; (void) buf; (void) p
+
+#define LOCAL_DEPTH_VARS                                               \
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);                       \
+   radeonScreenPtr radeonScreen = rmesa->radeonScreen;                 \
+   __DRIscreenPrivate *sPriv = rmesa->dri.screen;                      \
+   __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;                  \
+   GLuint height = dPriv->h;                                           \
+   GLuint xo = dPriv->x;                                               \
+   GLuint yo = dPriv->y;                                               \
+   char *buf = (char *)(sPriv->pFB + radeonScreen->depthOffset);       \
+   (void) buf
+
+#define LOCAL_STENCIL_VARS     LOCAL_DEPTH_VARS
+
+
+#define CLIPPIXEL( _x, _y )                                            \
+   ((_x >= minx) && (_x < maxx) && (_y >= miny) && (_y < maxy))
+
+
+#define CLIPSPAN( _x, _y, _n, _x1, _n1, _i )                           \
+   if ( _y < miny || _y >= maxy ) {                                    \
+      _n1 = 0, _x1 = x;                                                        \
+   } else {                                                            \
+      _n1 = _n;                                                                \
+      _x1 = _x;                                                                \
+      if ( _x1 < minx ) _i += (minx-_x1), n1 -= (minx-_x1), _x1 = minx; \
+      if ( _x1 + _n1 >= maxx ) n1 -= (_x1 + n1 - maxx);                        \
+   }
+
+#define Y_FLIP( _y )           (height - _y - 1)
+
+
+#define HW_LOCK() 
+
+#define HW_CLIPLOOP()                                                  \
+   do {                                                                        \
+      __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;               \
+      int _nc = dPriv->numClipRects;                                   \
+                                                                       \
+      while ( _nc-- ) {                                                        \
+        int minx = dPriv->pClipRects[_nc].x1 - dPriv->x;               \
+        int miny = dPriv->pClipRects[_nc].y1 - dPriv->y;               \
+        int maxx = dPriv->pClipRects[_nc].x2 - dPriv->x;               \
+        int maxy = dPriv->pClipRects[_nc].y2 - dPriv->y;
+
+#define HW_ENDCLIPLOOP()                                               \
+      }                                                                        \
+   } while (0)
+
+#define HW_UNLOCK()                                                    
+
+
+
+/* ================================================================
+ * Color buffer
+ */
+
+/* 16 bit, RGB565 color spanline and pixel functions
+ */
+#define INIT_MONO_PIXEL(p, color) \
+  p = PACK_COLOR_565( color[0], color[1], color[2] )
+
+#define WRITE_RGBA( _x, _y, r, g, b, a )                               \
+   *(GLushort *)(buf + _x*2 + _y*pitch) = ((((int)r & 0xf8) << 8) |    \
+                                          (((int)g & 0xfc) << 3) |     \
+                                          (((int)b & 0xf8) >> 3))
+
+#define WRITE_PIXEL( _x, _y, p )                                       \
+   *(GLushort *)(buf + _x*2 + _y*pitch) = p
+
+#define READ_RGBA( rgba, _x, _y )                                      \
+   do {                                                                        \
+      GLushort p = *(GLushort *)(read_buf + _x*2 + _y*pitch);          \
+      rgba[0] = ((p >> 8) & 0xf8) * 255 / 0xf8;                                \
+      rgba[1] = ((p >> 3) & 0xfc) * 255 / 0xfc;                                \
+      rgba[2] = ((p << 3) & 0xf8) * 255 / 0xf8;                                \
+      rgba[3] = 0xff;                                                  \
+   } while (0)
+
+#define TAG(x) radeon##x##_RGB565
+#include "spantmp.h"
+
+/* 32 bit, ARGB8888 color spanline and pixel functions
+ */
+#undef INIT_MONO_PIXEL
+#define INIT_MONO_PIXEL(p, color) \
+  p = PACK_COLOR_8888( color[3], color[0], color[1], color[2] )
+
+#define WRITE_RGBA( _x, _y, r, g, b, a )                       \
+do {                                                           \
+   *(GLuint *)(buf + _x*4 + _y*pitch) = ((b <<  0) |           \
+                                        (g <<  8) |            \
+                                        (r << 16) |            \
+                                        (a << 24) );           \
+} while (0)
+
+#define WRITE_PIXEL( _x, _y, p )                       \
+do {                                                   \
+   *(GLuint *)(buf + _x*4 + _y*pitch) = p;             \
+} while (0)
+
+#define READ_RGBA( rgba, _x, _y )                              \
+do {                                                           \
+   volatile GLuint *ptr = (volatile GLuint *)(read_buf + _x*4 + _y*pitch); \
+   GLuint p = *ptr;                                    \
+   rgba[0] = (p >> 16) & 0xff;                                 \
+   rgba[1] = (p >>  8) & 0xff;                                 \
+   rgba[2] = (p >>  0) & 0xff;                                 \
+   rgba[3] = (p >> 24) & 0xff;                                 \
+} while (0)
+
+#define TAG(x) radeon##x##_ARGB8888
+#include "spantmp.h"
+
+
+
+/* ================================================================
+ * Depth buffer
+ */
+
+/* The Radeon family has depth tiling on all the time, so we have to convert
+ * the x,y coordinates into the memory bus address (mba) in the same
+ * manner as the engine.  In each case, the linear block address (ba)
+ * is calculated, and then wired with x and y to produce the final
+ * memory address.
+ */
+
+static GLuint radeon_mba_z32( radeonContextPtr rmesa,
+                                      GLint x, GLint y )
+{
+   GLuint pitch = rmesa->radeonScreen->frontPitch;
+   GLuint ba, address = 0;                     /* a[0..1] = 0           */
+
+   ba = (y / 16) * (pitch / 16) + (x / 16);
+
+   address |= (x & 0x7) << 2;                  /* a[2..4] = x[0..2]     */
+   address |= (y & 0x3) << 5;                  /* a[5..6] = y[0..1]     */
+   address |=
+      (((x & 0x10) >> 2) ^ (y & 0x4)) << 5;    /* a[7]    = x[4] ^ y[2] */
+   address |= (ba & 0x3) << 8;                 /* a[8..9] = ba[0..1]    */
+
+   address |= (y & 0x8) << 7;                  /* a[10]   = y[3]        */
+   address |=
+      (((x & 0x8) << 1) ^ (y & 0x10)) << 7;    /* a[11]   = x[3] ^ y[4] */
+   address |= (ba & ~0x3) << 10;               /* a[12..] = ba[2..]     */
+
+   return address;
+}
+
+static __inline GLuint radeon_mba_z16( radeonContextPtr rmesa, GLint x, GLint y )
+{
+   GLuint pitch = rmesa->radeonScreen->frontPitch;
+   GLuint ba, address = 0;                     /* a[0]    = 0           */
+
+   ba = (y / 16) * (pitch / 32) + (x / 32);
+
+   address |= (x & 0x7) << 1;                  /* a[1..3] = x[0..2]     */
+   address |= (y & 0x7) << 4;                  /* a[4..6] = y[0..2]     */
+   address |= (x & 0x8) << 4;                  /* a[7]    = x[3]        */
+   address |= (ba & 0x3) << 8;                 /* a[8..9] = ba[0..1]    */
+   address |= (y & 0x8) << 7;                  /* a[10]   = y[3]        */
+   address |= ((x & 0x10) ^ (y & 0x10)) << 7;  /* a[11]   = x[4] ^ y[4] */
+   address |= (ba & ~0x3) << 10;               /* a[12..] = ba[2..]     */
+
+   return address;
+}
+
+
+/* 16-bit depth buffer functions
+ */
+#define WRITE_DEPTH( _x, _y, d )                                       \
+   *(GLushort *)(buf + radeon_mba_z16( rmesa, _x + xo, _y + yo )) = d;
+
+#define READ_DEPTH( d, _x, _y )                                                \
+   d = *(GLushort *)(buf + radeon_mba_z16( rmesa, _x + xo, _y + yo ));
+
+#define TAG(x) radeon##x##_16
+#include "depthtmp.h"
+
+/* 24 bit depth, 8 bit stencil depthbuffer functions
+ */
+#define WRITE_DEPTH( _x, _y, d )                                       \
+do {                                                                   \
+   GLuint offset = radeon_mba_z32( rmesa, _x + xo, _y + yo );          \
+   GLuint tmp = *(GLuint *)(buf + offset);                             \
+   tmp &= 0xff000000;                                                  \
+   tmp |= ((d) & 0x00ffffff);                                          \
+   *(GLuint *)(buf + offset) = tmp;                                    \
+} while (0)
+
+#define READ_DEPTH( d, _x, _y )                                                \
+   d = *(GLuint *)(buf + radeon_mba_z32( rmesa, _x + xo,               \
+                                        _y + yo )) & 0x00ffffff;
+
+#define TAG(x) radeon##x##_24_8
+#include "depthtmp.h"
+
+
+/* ================================================================
+ * Stencil buffer
+ */
+
+/* 24 bit depth, 8 bit stencil depthbuffer functions
+ */
+#define WRITE_STENCIL( _x, _y, d )                                     \
+do {                                                                   \
+   GLuint offset = radeon_mba_z32( rmesa, _x + xo, _y + yo );          \
+   GLuint tmp = *(GLuint *)(buf + offset);                             \
+   tmp &= 0x00ffffff;                                                  \
+   tmp |= (((d) & 0xff) << 24);                                                \
+   *(GLuint *)(buf + offset) = tmp;                                    \
+} while (0)
+
+#define READ_STENCIL( d, _x, _y )                                      \
+do {                                                                   \
+   GLuint offset = radeon_mba_z32( rmesa, _x + xo, _y + yo );          \
+   GLuint tmp = *(GLuint *)(buf + offset);                             \
+   tmp &= 0xff000000;                                                  \
+   d = tmp >> 24;                                                      \
+} while (0)
+
+#define TAG(x) radeon##x##_24_8
+#include "stenciltmp.h"
+
+
+/*
+ * This function is called to specify which buffer to read and write
+ * for software rasterization (swrast) fallbacks.  This doesn't necessarily
+ * correspond to glDrawBuffer() or glReadBuffer() calls.
+ */
+static void radeonSetBuffer( GLcontext *ctx,
+                             GLframebuffer *colorBuffer,
+                             GLuint bufferBit )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   switch ( bufferBit ) {
+   case FRONT_LEFT_BIT:
+      if ( rmesa->sarea->pfCurrentPage == 1 ) {
+        rmesa->state.pixel.readOffset = rmesa->radeonScreen->backOffset;
+        rmesa->state.pixel.readPitch  = rmesa->radeonScreen->backPitch;
+        rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset;
+        rmesa->state.color.drawPitch  = rmesa->radeonScreen->backPitch;
+      } else {
+       rmesa->state.pixel.readOffset = rmesa->radeonScreen->frontOffset;
+       rmesa->state.pixel.readPitch  = rmesa->radeonScreen->frontPitch;
+       rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset;
+       rmesa->state.color.drawPitch  = rmesa->radeonScreen->frontPitch;
+      }
+      break;
+   case BACK_LEFT_BIT:
+      if ( rmesa->sarea->pfCurrentPage == 1 ) {
+       rmesa->state.pixel.readOffset = rmesa->radeonScreen->frontOffset;
+       rmesa->state.pixel.readPitch  = rmesa->radeonScreen->frontPitch;
+       rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset;
+       rmesa->state.color.drawPitch  = rmesa->radeonScreen->frontPitch;
+      } else {
+        rmesa->state.pixel.readOffset = rmesa->radeonScreen->backOffset;
+        rmesa->state.pixel.readPitch  = rmesa->radeonScreen->backPitch;
+        rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset;
+        rmesa->state.color.drawPitch  = rmesa->radeonScreen->backPitch;
+      }
+      break;
+   default:
+      assert(0);
+      break;
+   }
+}
+
+/* Move locking out to get reasonable span performance (10x better
+ * than doing this in HW_LOCK above).  WaitForIdle() is the main
+ * culprit.
+ */
+
+static void radeonSpanRenderStart( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+
+   RADEON_FIREVERTICES( rmesa );
+   LOCK_HARDWARE( rmesa );
+   radeonWaitForIdleLocked( rmesa );
+}
+
+static void radeonSpanRenderFinish( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+   _swrast_flush( ctx );
+   UNLOCK_HARDWARE( rmesa );
+}
+
+void radeonInitSpanFuncs( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
+
+   swdd->SetBuffer = radeonSetBuffer;
+
+   switch ( rmesa->radeonScreen->cpp ) {
+   case 2:
+      swdd->WriteRGBASpan      = radeonWriteRGBASpan_RGB565;
+      swdd->WriteRGBSpan       = radeonWriteRGBSpan_RGB565;
+      swdd->WriteMonoRGBASpan  = radeonWriteMonoRGBASpan_RGB565;
+      swdd->WriteRGBAPixels    = radeonWriteRGBAPixels_RGB565;
+      swdd->WriteMonoRGBAPixels        = radeonWriteMonoRGBAPixels_RGB565;
+      swdd->ReadRGBASpan       = radeonReadRGBASpan_RGB565;
+      swdd->ReadRGBAPixels      = radeonReadRGBAPixels_RGB565;
+      break;
+
+   case 4:
+      swdd->WriteRGBASpan      = radeonWriteRGBASpan_ARGB8888;
+      swdd->WriteRGBSpan       = radeonWriteRGBSpan_ARGB8888;
+      swdd->WriteMonoRGBASpan   = radeonWriteMonoRGBASpan_ARGB8888;
+      swdd->WriteRGBAPixels     = radeonWriteRGBAPixels_ARGB8888;
+      swdd->WriteMonoRGBAPixels = radeonWriteMonoRGBAPixels_ARGB8888;
+      swdd->ReadRGBASpan       = radeonReadRGBASpan_ARGB8888;
+      swdd->ReadRGBAPixels      = radeonReadRGBAPixels_ARGB8888;
+      break;
+
+   default:
+      break;
+   }
+
+   switch ( rmesa->glCtx->Visual.depthBits ) {
+   case 16:
+      swdd->ReadDepthSpan      = radeonReadDepthSpan_16;
+      swdd->WriteDepthSpan     = radeonWriteDepthSpan_16;
+      swdd->ReadDepthPixels    = radeonReadDepthPixels_16;
+      swdd->WriteDepthPixels   = radeonWriteDepthPixels_16;
+      break;
+
+   case 24:
+      swdd->ReadDepthSpan      = radeonReadDepthSpan_24_8;
+      swdd->WriteDepthSpan     = radeonWriteDepthSpan_24_8;
+      swdd->ReadDepthPixels    = radeonReadDepthPixels_24_8;
+      swdd->WriteDepthPixels   = radeonWriteDepthPixels_24_8;
+
+      swdd->ReadStencilSpan    = radeonReadStencilSpan_24_8;
+      swdd->WriteStencilSpan   = radeonWriteStencilSpan_24_8;
+      swdd->ReadStencilPixels  = radeonReadStencilPixels_24_8;
+      swdd->WriteStencilPixels = radeonWriteStencilPixels_24_8;
+      break;
+
+   default:
+      break;
+   }
+
+   swdd->SpanRenderStart          = radeonSpanRenderStart;
+   swdd->SpanRenderFinish         = radeonSpanRenderFinish; 
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_span.h b/src/mesa/drivers/dri/radeon/radeon_span.h
new file mode 100644 (file)
index 0000000..011e8ef
--- /dev/null
@@ -0,0 +1,45 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_span.h,v 1.2 2002/02/22 21:45:01 dawes Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Gareth Hughes <gareth@valinux.com>
+ */
+
+#ifndef __RADEON_SPAN_H__
+#define __RADEON_SPAN_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+extern void radeonInitSpanFuncs( GLcontext *ctx );
+
+#endif
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_state.c b/src/mesa/drivers/dri/radeon/radeon_state.c
new file mode 100644 (file)
index 0000000..7b1bbe7
--- /dev/null
@@ -0,0 +1,2211 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_state.c,v 1.8 2002/12/16 16:18:58 dawes Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Gareth Hughes <gareth@valinux.com>
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "api_arrayelt.h"
+#include "enums.h"
+#include "colormac.h"
+#include "state.h"
+
+#include "swrast/swrast.h"
+#include "array_cache/acache.h"
+#include "tnl/tnl.h"
+#include "tnl/t_pipeline.h"
+#include "main/light.h"
+#include "swrast_setup/swrast_setup.h"
+
+#include "radeon_context.h"
+#include "radeon_ioctl.h"
+#include "radeon_state.h"
+#include "radeon_tcl.h"
+#include "radeon_tex.h"
+#include "radeon_swtcl.h"
+#include "radeon_vtxfmt.h"
+
+/* =============================================================
+ * Alpha blending
+ */
+
+static void radeonAlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   int pp_misc = rmesa->hw.ctx.cmd[CTX_PP_MISC];
+   GLubyte refByte;
+
+   CLAMPED_FLOAT_TO_UBYTE(refByte, ref);
+
+   RADEON_STATECHANGE( rmesa, ctx );
+
+   pp_misc &= ~(RADEON_ALPHA_TEST_OP_MASK | RADEON_REF_ALPHA_MASK);
+   pp_misc |= (refByte & RADEON_REF_ALPHA_MASK);
+
+   switch ( func ) {
+   case GL_NEVER:
+      pp_misc |= RADEON_ALPHA_TEST_FAIL;
+      break;
+   case GL_LESS:
+      pp_misc |= RADEON_ALPHA_TEST_LESS;
+      break;
+   case GL_EQUAL:
+      pp_misc |= RADEON_ALPHA_TEST_EQUAL;
+      break;
+   case GL_LEQUAL:
+      pp_misc |= RADEON_ALPHA_TEST_LEQUAL;
+      break;
+   case GL_GREATER:
+      pp_misc |= RADEON_ALPHA_TEST_GREATER;
+      break;
+   case GL_NOTEQUAL:
+      pp_misc |= RADEON_ALPHA_TEST_NEQUAL;
+      break;
+   case GL_GEQUAL:
+      pp_misc |= RADEON_ALPHA_TEST_GEQUAL;
+      break;
+   case GL_ALWAYS:
+      pp_misc |= RADEON_ALPHA_TEST_PASS;
+      break;
+   }
+
+   rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc;
+}
+
+static void radeonBlendEquation( GLcontext *ctx, GLenum mode )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & ~RADEON_COMB_FCN_MASK;
+   GLboolean fallback = GL_FALSE;
+
+   switch ( mode ) {
+   case GL_FUNC_ADD:
+   case GL_LOGIC_OP:
+      b |= RADEON_COMB_FCN_ADD_CLAMP;
+      break;
+
+   case GL_FUNC_SUBTRACT:
+      b |= RADEON_COMB_FCN_SUB_CLAMP;
+      break;
+
+   default:
+      if (ctx->Color.BlendEnabled)
+        fallback = GL_TRUE;
+      else
+        b |= RADEON_COMB_FCN_ADD_CLAMP;
+      break;
+   }
+
+   FALLBACK( rmesa, RADEON_FALLBACK_BLEND_EQ, fallback );
+   if ( !fallback ) {
+      RADEON_STATECHANGE( rmesa, ctx );
+      rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b;
+      if ( ctx->Color.ColorLogicOpEnabled ) {
+        rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  RADEON_ROP_ENABLE;
+      } else {
+        rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
+      }
+   }
+}
+
+static void radeonBlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & 
+      ~(RADEON_SRC_BLEND_MASK | RADEON_DST_BLEND_MASK);
+   GLboolean fallback = GL_FALSE;
+
+   switch ( ctx->Color.BlendSrcRGB ) {
+   case GL_ZERO:
+      b |= RADEON_SRC_BLEND_GL_ZERO;
+      break;
+   case GL_ONE:
+      b |= RADEON_SRC_BLEND_GL_ONE;
+      break;
+   case GL_DST_COLOR:
+      b |= RADEON_SRC_BLEND_GL_DST_COLOR;
+      break;
+   case GL_ONE_MINUS_DST_COLOR:
+      b |= RADEON_SRC_BLEND_GL_ONE_MINUS_DST_COLOR;
+      break;
+   case GL_SRC_COLOR:
+      b |= RADEON_SRC_BLEND_GL_SRC_COLOR;
+      break;
+   case GL_ONE_MINUS_SRC_COLOR:
+      b |= RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR;
+      break;
+   case GL_SRC_ALPHA:
+      b |= RADEON_SRC_BLEND_GL_SRC_ALPHA;
+      break;
+   case GL_ONE_MINUS_SRC_ALPHA:
+      b |= RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA;
+      break;
+   case GL_DST_ALPHA:
+      b |= RADEON_SRC_BLEND_GL_DST_ALPHA;
+      break;
+   case GL_ONE_MINUS_DST_ALPHA:
+      b |= RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA;
+      break;
+   case GL_SRC_ALPHA_SATURATE:
+      b |= RADEON_SRC_BLEND_GL_SRC_ALPHA_SATURATE;
+      break;
+   case GL_CONSTANT_COLOR:
+   case GL_ONE_MINUS_CONSTANT_COLOR:
+   case GL_CONSTANT_ALPHA:
+   case GL_ONE_MINUS_CONSTANT_ALPHA:
+      if (ctx->Color.BlendEnabled)
+        fallback = GL_TRUE;
+      else
+        b |= RADEON_SRC_BLEND_GL_ONE;
+      break;
+   default:
+      break;
+   }
+
+   switch ( ctx->Color.BlendDstRGB ) {
+   case GL_ZERO:
+      b |= RADEON_DST_BLEND_GL_ZERO;
+      break;
+   case GL_ONE:
+      b |= RADEON_DST_BLEND_GL_ONE;
+      break;
+   case GL_SRC_COLOR:
+      b |= RADEON_DST_BLEND_GL_SRC_COLOR;
+      break;
+   case GL_ONE_MINUS_SRC_COLOR:
+      b |= RADEON_DST_BLEND_GL_ONE_MINUS_SRC_COLOR;
+      break;
+   case GL_SRC_ALPHA:
+      b |= RADEON_DST_BLEND_GL_SRC_ALPHA;
+      break;
+   case GL_ONE_MINUS_SRC_ALPHA:
+      b |= RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA;
+      break;
+   case GL_DST_COLOR:
+      b |= RADEON_DST_BLEND_GL_DST_COLOR;
+      break;
+   case GL_ONE_MINUS_DST_COLOR:
+      b |= RADEON_DST_BLEND_GL_ONE_MINUS_DST_COLOR;
+      break;
+   case GL_DST_ALPHA:
+      b |= RADEON_DST_BLEND_GL_DST_ALPHA;
+      break;
+   case GL_ONE_MINUS_DST_ALPHA:
+      b |= RADEON_DST_BLEND_GL_ONE_MINUS_DST_ALPHA;
+      break;
+   case GL_CONSTANT_COLOR:
+   case GL_ONE_MINUS_CONSTANT_COLOR:
+   case GL_CONSTANT_ALPHA:
+   case GL_ONE_MINUS_CONSTANT_ALPHA:
+      if (ctx->Color.BlendEnabled)
+        fallback = GL_TRUE;
+      else
+        b |= RADEON_DST_BLEND_GL_ZERO;
+      break;
+   default:
+      break;
+   }
+
+   FALLBACK( rmesa, RADEON_FALLBACK_BLEND_FUNC, fallback );
+   if ( !fallback ) {
+      RADEON_STATECHANGE( rmesa, ctx );
+      rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b;
+   }
+}
+
+static void radeonBlendFuncSeparate( GLcontext *ctx,
+                                    GLenum sfactorRGB, GLenum dfactorRGB,
+                                    GLenum sfactorA, GLenum dfactorA )
+{
+   radeonBlendFunc( ctx, sfactorRGB, dfactorRGB );
+}
+
+
+/* =============================================================
+ * Depth testing
+ */
+
+static void radeonDepthFunc( GLcontext *ctx, GLenum func )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   RADEON_STATECHANGE( rmesa, ctx );
+   rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_Z_TEST_MASK;
+
+   switch ( ctx->Depth.Func ) {
+   case GL_NEVER:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_NEVER;
+      break;
+   case GL_LESS:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_LESS;
+      break;
+   case GL_EQUAL:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_EQUAL;
+      break;
+   case GL_LEQUAL:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_LEQUAL;
+      break;
+   case GL_GREATER:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_GREATER;
+      break;
+   case GL_NOTEQUAL:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_NEQUAL;
+      break;
+   case GL_GEQUAL:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_GEQUAL;
+      break;
+   case GL_ALWAYS:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_ALWAYS;
+      break;
+   }
+}
+
+
+static void radeonDepthMask( GLcontext *ctx, GLboolean flag )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   RADEON_STATECHANGE( rmesa, ctx );
+
+   if ( ctx->Depth.Mask ) {
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |=  RADEON_Z_WRITE_ENABLE;
+   } else {
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_Z_WRITE_ENABLE;
+   }
+}
+
+static void radeonClearDepth( GLcontext *ctx, GLclampd d )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLuint format = (rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &
+                   RADEON_DEPTH_FORMAT_MASK);
+
+   switch ( format ) {
+   case RADEON_DEPTH_FORMAT_16BIT_INT_Z:
+      rmesa->state.depth.clear = d * 0x0000ffff;
+      break;
+   case RADEON_DEPTH_FORMAT_24BIT_INT_Z:
+      rmesa->state.depth.clear = d * 0x00ffffff;
+      break;
+   }
+}
+
+
+/* =============================================================
+ * Fog
+ */
+
+
+static void radeonFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   union { int i; float f; } c, d;
+   GLchan col[4];
+
+   c.i = rmesa->hw.fog.cmd[FOG_C];
+   d.i = rmesa->hw.fog.cmd[FOG_D];
+
+   switch (pname) {
+   case GL_FOG_MODE:
+      if (!ctx->Fog.Enabled)
+        return;
+      RADEON_STATECHANGE(rmesa, tcl);
+      rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK;
+      switch (ctx->Fog.Mode) {
+      case GL_LINEAR:
+        rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_LINEAR;
+        if (ctx->Fog.Start == ctx->Fog.End) {
+           c.f = 1.0F;
+           d.f = 1.0F;
+        }
+        else {
+           c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
+           d.f = 1.0/(ctx->Fog.End-ctx->Fog.Start);
+        }
+        break;
+      case GL_EXP:
+        rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP;
+        c.f = 0.0;
+        d.f = ctx->Fog.Density;
+        break;
+      case GL_EXP2:
+        rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP2;
+        c.f = 0.0;
+        d.f = -(ctx->Fog.Density * ctx->Fog.Density);
+        break;
+      default:
+        return;
+      }
+      break;
+   case GL_FOG_DENSITY:
+      switch (ctx->Fog.Mode) {
+      case GL_EXP:
+        c.f = 0.0;
+        d.f = ctx->Fog.Density;
+        break;
+      case GL_EXP2:
+        c.f = 0.0;
+        d.f = -(ctx->Fog.Density * ctx->Fog.Density);
+        break;
+      default:
+        break;
+      }
+      break;
+   case GL_FOG_START:
+   case GL_FOG_END:
+      if (ctx->Fog.Mode == GL_LINEAR) {
+        if (ctx->Fog.Start == ctx->Fog.End) {
+           c.f = 1.0F;
+           d.f = 1.0F;
+        } else {
+           c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
+           d.f = 1.0/(ctx->Fog.End-ctx->Fog.Start);
+        }
+      }
+      break;
+   case GL_FOG_COLOR: 
+      RADEON_STATECHANGE( rmesa, ctx );
+      UNCLAMPED_FLOAT_TO_RGB_CHAN( col, ctx->Fog.Color );
+      rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] =
+        radeonPackColor( 4, col[0], col[1], col[2], 0 );
+      break;
+   case GL_FOG_COORDINATE_SOURCE_EXT: 
+      /* What to do?
+       */
+      break;
+   default:
+      return;
+   }
+
+   if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) {
+      RADEON_STATECHANGE( rmesa, fog );
+      rmesa->hw.fog.cmd[FOG_C] = c.i;
+      rmesa->hw.fog.cmd[FOG_D] = d.i;
+   }
+}
+
+
+/* =============================================================
+ * Scissoring
+ */
+
+
+static GLboolean intersect_rect( XF86DRIClipRectPtr out,
+                                XF86DRIClipRectPtr a,
+                                XF86DRIClipRectPtr b )
+{
+   *out = *a;
+   if ( b->x1 > out->x1 ) out->x1 = b->x1;
+   if ( b->y1 > out->y1 ) out->y1 = b->y1;
+   if ( b->x2 < out->x2 ) out->x2 = b->x2;
+   if ( b->y2 < out->y2 ) out->y2 = b->y2;
+   if ( out->x1 >= out->x2 ) return GL_FALSE;
+   if ( out->y1 >= out->y2 ) return GL_FALSE;
+   return GL_TRUE;
+}
+
+
+void radeonRecalcScissorRects( radeonContextPtr rmesa )
+{
+   XF86DRIClipRectPtr out;
+   int i;
+
+   /* Grow cliprect store?
+    */
+   if (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
+      while (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
+        rmesa->state.scissor.numAllocedClipRects += 1; /* zero case */
+        rmesa->state.scissor.numAllocedClipRects *= 2;
+      }
+
+      if (rmesa->state.scissor.pClipRects)
+        FREE(rmesa->state.scissor.pClipRects);
+
+      rmesa->state.scissor.pClipRects = 
+        MALLOC( rmesa->state.scissor.numAllocedClipRects * 
+                sizeof(XF86DRIClipRectRec) );
+
+      if ( rmesa->state.scissor.pClipRects == NULL ) {
+        rmesa->state.scissor.numAllocedClipRects = 0;
+        return;
+      }
+   }
+   
+   out = rmesa->state.scissor.pClipRects;
+   rmesa->state.scissor.numClipRects = 0;
+
+   for ( i = 0 ; i < rmesa->numClipRects ;  i++ ) {
+      if ( intersect_rect( out, 
+                          &rmesa->pClipRects[i], 
+                          &rmesa->state.scissor.rect ) ) {
+        rmesa->state.scissor.numClipRects++;
+        out++;
+      }
+   }
+}
+
+
+static void radeonUpdateScissor( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   if ( rmesa->dri.drawable ) {
+      __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
+
+      int x = ctx->Scissor.X;
+      int y = dPriv->h - ctx->Scissor.Y - ctx->Scissor.Height;
+      int w = ctx->Scissor.X + ctx->Scissor.Width - 1;
+      int h = dPriv->h - ctx->Scissor.Y - 1;
+
+      rmesa->state.scissor.rect.x1 = x + dPriv->x;
+      rmesa->state.scissor.rect.y1 = y + dPriv->y;
+      rmesa->state.scissor.rect.x2 = w + dPriv->x + 1;
+      rmesa->state.scissor.rect.y2 = h + dPriv->y + 1;
+
+      radeonRecalcScissorRects( rmesa );
+   }
+}
+
+
+static void radeonScissor( GLcontext *ctx,
+                          GLint x, GLint y, GLsizei w, GLsizei h )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   if ( ctx->Scissor.Enabled ) {
+      RADEON_FIREVERTICES( rmesa );    /* don't pipeline cliprect changes */
+      radeonUpdateScissor( ctx );
+   }
+
+}
+
+
+/* =============================================================
+ * Culling
+ */
+
+static void radeonCullFace( GLcontext *ctx, GLenum unused )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
+   GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL];
+
+   s |= RADEON_FFACE_SOLID | RADEON_BFACE_SOLID;
+   t &= ~(RADEON_CULL_FRONT | RADEON_CULL_BACK);
+
+   if ( ctx->Polygon.CullFlag ) {
+      switch ( ctx->Polygon.CullFaceMode ) {
+      case GL_FRONT:
+        s &= ~RADEON_FFACE_SOLID;
+        t |= RADEON_CULL_FRONT;
+        break;
+      case GL_BACK:
+        s &= ~RADEON_BFACE_SOLID;
+        t |= RADEON_CULL_BACK;
+        break;
+      case GL_FRONT_AND_BACK:
+        s &= ~(RADEON_FFACE_SOLID | RADEON_BFACE_SOLID);
+        t |= (RADEON_CULL_FRONT | RADEON_CULL_BACK);
+        break;
+      }
+   }
+
+   if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
+      RADEON_STATECHANGE(rmesa, set );
+      rmesa->hw.set.cmd[SET_SE_CNTL] = s;
+   }
+
+   if ( rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] != t ) {
+      RADEON_STATECHANGE(rmesa, tcl );
+      rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = t;
+   }
+}
+
+static void radeonFrontFace( GLcontext *ctx, GLenum mode )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   RADEON_STATECHANGE( rmesa, set );
+   rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_FFACE_CULL_DIR_MASK;
+
+   RADEON_STATECHANGE( rmesa, tcl );
+   rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_CULL_FRONT_IS_CCW;
+
+   switch ( mode ) {
+   case GL_CW:
+      rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_FFACE_CULL_CW;
+      break;
+   case GL_CCW:
+      rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_FFACE_CULL_CCW;
+      rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_CULL_FRONT_IS_CCW;
+      break;
+   }
+}
+
+
+/* =============================================================
+ * Line state
+ */
+static void radeonLineWidth( GLcontext *ctx, GLfloat widthf )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   RADEON_STATECHANGE( rmesa, lin );
+   RADEON_STATECHANGE( rmesa, set );
+
+   /* Line width is stored in U6.4 format.
+    */
+   rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] = (GLuint)(widthf * 16.0);
+   if ( widthf > 1.0 ) {
+      rmesa->hw.set.cmd[SET_SE_CNTL] |=  RADEON_WIDELINE_ENABLE;
+   } else {
+      rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_WIDELINE_ENABLE;
+   }
+}
+
+static void radeonLineStipple( GLcontext *ctx, GLint factor, GLushort pattern )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   RADEON_STATECHANGE( rmesa, lin );
+   rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] = 
+      ((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern));
+}
+
+
+/* =============================================================
+ * Masks
+ */
+static void radeonColorMask( GLcontext *ctx,
+                            GLboolean r, GLboolean g,
+                            GLboolean b, GLboolean a )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLuint mask = radeonPackColor( rmesa->radeonScreen->cpp,
+                                 ctx->Color.ColorMask[RCOMP],
+                                 ctx->Color.ColorMask[GCOMP],
+                                 ctx->Color.ColorMask[BCOMP],
+                                 ctx->Color.ColorMask[ACOMP] );
+
+   if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) {
+      RADEON_STATECHANGE( rmesa, msk );
+      rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask;
+   }
+}
+
+
+/* =============================================================
+ * Polygon state
+ */
+
+static void radeonPolygonOffset( GLcontext *ctx,
+                                GLfloat factor, GLfloat units )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat constant = units * rmesa->state.depth.scale;
+
+   RADEON_STATECHANGE( rmesa, zbs );
+   rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR]   = *(GLuint *)&factor;
+   rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = *(GLuint *)&constant;
+}
+
+static void radeonPolygonStipple( GLcontext *ctx, const GLubyte *mask )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLuint i;
+   drmRadeonStipple stipple;
+
+   /* Must flip pattern upside down.
+    */
+   for ( i = 0 ; i < 32 ; i++ ) {
+      rmesa->state.stipple.mask[31 - i] = ((GLuint *) mask)[i];
+   }
+
+   /* TODO: push this into cmd mechanism
+    */
+   RADEON_FIREVERTICES( rmesa );
+   LOCK_HARDWARE( rmesa );
+
+   /* FIXME: Use window x,y offsets into stipple RAM.
+    */
+   stipple.mask = rmesa->state.stipple.mask;
+   drmCommandWrite( rmesa->dri.fd, DRM_RADEON_STIPPLE, 
+                    &stipple, sizeof(drmRadeonStipple) );
+   UNLOCK_HARDWARE( rmesa );
+}
+
+static void radeonPolygonMode( GLcontext *ctx, GLenum face, GLenum mode )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLboolean flag = (ctx->_TriangleCaps & DD_TRI_UNFILLED) != 0;
+
+   /* Can't generally do unfilled via tcl, but some good special
+    * cases work. 
+    */
+   TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_UNFILLED, flag);
+   if (rmesa->TclFallback) {
+      radeonChooseRenderState( ctx );
+      radeonChooseVertexState( ctx );
+   }
+}
+
+
+/* =============================================================
+ * Rendering attributes
+ *
+ * We really don't want to recalculate all this every time we bind a
+ * texture.  These things shouldn't change all that often, so it makes
+ * sense to break them out of the core texture state update routines.
+ */
+
+/* Examine lighting and texture state to determine if separate specular
+ * should be enabled.
+ */
+static void radeonUpdateSpecular( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   CARD32 p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
+
+   RADEON_STATECHANGE( rmesa, tcl );
+
+   rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_SPECULAR;
+   rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_DIFFUSE;
+   rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~RADEON_TCL_VTX_PK_SPEC;
+   rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~RADEON_TCL_VTX_PK_DIFFUSE;
+   rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LIGHTING_ENABLE;
+
+   p &= ~RADEON_SPECULAR_ENABLE;
+
+   rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_DIFFUSE_SPECULAR_COMBINE;
+
+
+   if (ctx->Light.Enabled &&
+       ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) {
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE;
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
+      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
+      p |=  RADEON_SPECULAR_ENABLE;
+      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= 
+        ~RADEON_DIFFUSE_SPECULAR_COMBINE;
+   }
+   else if (ctx->Light.Enabled) {
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE;
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
+      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
+   } else if (ctx->Fog.ColorSumEnabled ) {
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
+      p |= RADEON_SPECULAR_ENABLE;
+   } else {
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
+   }
+
+   if (ctx->Fog.Enabled) {
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
+
+      /* Bizzare: have to leave lighting enabled to get fog.
+       */
+      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
+   }
+
+   if ( ctx->_TriangleCaps & DD_SEPARATE_SPECULAR ) {
+      assert( (p & RADEON_SPECULAR_ENABLE) != 0 );
+   } else {
+      assert( (p & RADEON_SPECULAR_ENABLE) == 0 );
+   }
+
+   if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) {
+      RADEON_STATECHANGE( rmesa, ctx );
+      rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p;
+   }
+
+   /* Update vertex/render formats
+    */
+   if (rmesa->TclFallback) { 
+      radeonChooseRenderState( ctx );
+      radeonChooseVertexState( ctx );
+   }
+}
+
+
+/* =============================================================
+ * Materials
+ */
+
+
+/* Update on colormaterial, material emmissive/ambient, 
+ * lightmodel.globalambient
+ */
+static void update_global_ambient( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   float *fcmd = (float *)RADEON_DB_STATE( glt );
+
+   /* Need to do more if both emmissive & ambient are PREMULT:
+    */
+   if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &
+       ((3 << RADEON_EMISSIVE_SOURCE_SHIFT) |
+       (3 << RADEON_AMBIENT_SOURCE_SHIFT))) == 0) 
+   {
+      COPY_3V( &fcmd[GLT_RED], 
+              ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]);
+      ACC_SCALE_3V( &fcmd[GLT_RED],
+                  ctx->Light.Model.Ambient,
+                  ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]);
+   } 
+   else
+   {
+      COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient );
+   }
+   
+   RADEON_DB_STATECHANGE(rmesa, &rmesa->hw.glt);
+}
+
+/* Update on change to 
+ *    - light[p].colors
+ *    - light[p].enabled
+ *    - material,
+ *    - colormaterial enabled
+ *    - colormaterial bitmask
+ */
+static void update_light_colors( GLcontext *ctx, GLuint p )
+{
+   struct gl_light *l = &ctx->Light.Light[p];
+
+/*     fprintf(stderr, "%s\n", __FUNCTION__); */
+
+   if (l->Enabled) {
+      radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+      float *fcmd = (float *)RADEON_DB_STATE( lit[p] );
+      GLuint bitmask = ctx->Light.ColorMaterialBitmask;
+      GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
+
+      COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient );    
+      COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse );
+      COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular );
+      
+      if (!ctx->Light.ColorMaterialEnabled)
+        bitmask = 0;
+
+      if ((bitmask & MAT_BIT_FRONT_AMBIENT) == 0) 
+        SELF_SCALE_3V( &fcmd[LIT_AMBIENT_RED], mat[MAT_ATTRIB_FRONT_AMBIENT] );
+
+      if ((bitmask & MAT_BIT_FRONT_DIFFUSE) == 0) 
+        SELF_SCALE_3V( &fcmd[LIT_DIFFUSE_RED], mat[MAT_ATTRIB_FRONT_DIFFUSE] );
+      
+      if ((bitmask & MAT_BIT_FRONT_SPECULAR) == 0) 
+        SELF_SCALE_3V( &fcmd[LIT_SPECULAR_RED], mat[MAT_ATTRIB_FRONT_SPECULAR] );
+
+      RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
+   }
+}
+
+/* Also fallback for asym colormaterial mode in twoside lighting...
+ */
+static void check_twoside_fallback( GLcontext *ctx )
+{
+   GLboolean fallback = GL_FALSE;
+   GLint i;
+
+   if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) {
+      if (ctx->Light.ColorMaterialEnabled &&
+         (ctx->Light.ColorMaterialBitmask & BACK_MATERIAL_BITS) != 
+         ((ctx->Light.ColorMaterialBitmask & FRONT_MATERIAL_BITS)<<1))
+        fallback = GL_TRUE;
+      else {
+        for (i = MAT_ATTRIB_FRONT_AMBIENT; i < MAT_ATTRIB_FRONT_INDEXES; i+=2)
+           if (memcmp( ctx->Light.Material.Attrib[i],
+                       ctx->Light.Material.Attrib[i+1],
+                       sizeof(GLfloat)*4) != 0) {
+              fallback = GL_TRUE;  
+              break;
+           }
+      }
+   }
+
+   TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_LIGHT_TWOSIDE, fallback );
+}
+
+
+static void radeonColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
+{
+   if (ctx->Light.ColorMaterialEnabled) {
+      radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+      GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL];
+      GLuint mask = ctx->Light.ColorMaterialBitmask;
+
+      /* Default to PREMULT:
+       */
+      light_model_ctl1 &= ~((0xf << RADEON_EMISSIVE_SOURCE_SHIFT) |
+                          (0xf << RADEON_AMBIENT_SOURCE_SHIFT) |
+                          (0xf << RADEON_DIFFUSE_SOURCE_SHIFT) |
+                          (0xf << RADEON_SPECULAR_SOURCE_SHIFT)); 
+   
+      if (mask & MAT_BIT_FRONT_EMISSION) {
+        light_model_ctl1 |= (3 <<
+                            RADEON_EMISSIVE_SOURCE_SHIFT);
+      }
+
+      if (mask & MAT_BIT_FRONT_AMBIENT) {
+        light_model_ctl1 |= (3 <<
+                            RADEON_AMBIENT_SOURCE_SHIFT);
+      }
+        
+      if (mask & MAT_BIT_FRONT_DIFFUSE) {
+        light_model_ctl1 |= (3 <<
+                            RADEON_DIFFUSE_SOURCE_SHIFT);
+      }
+   
+      if (mask & MAT_BIT_FRONT_SPECULAR) {
+        light_model_ctl1 |= (3 <<
+                            RADEON_SPECULAR_SOURCE_SHIFT);
+      }
+   
+      if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]) {
+        GLuint p;
+
+        RADEON_STATECHANGE( rmesa, tcl );
+        rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = light_model_ctl1;      
+
+        for (p = 0 ; p < MAX_LIGHTS; p++) 
+           update_light_colors( ctx, p );
+        update_global_ambient( ctx );
+      }
+   }
+   
+   check_twoside_fallback( ctx );
+}
+
+void radeonUpdateMaterial( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
+   GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( mtl );
+   GLuint p;
+   GLuint mask = ~0;
+   
+   if (ctx->Light.ColorMaterialEnabled)
+      mask &= ~ctx->Light.ColorMaterialBitmask;
+
+   if (RADEON_DEBUG & DEBUG_STATE)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+      
+   if (mask & MAT_BIT_FRONT_EMISSION) {
+      fcmd[MTL_EMMISSIVE_RED]   = mat[MAT_ATTRIB_FRONT_EMISSION][0];
+      fcmd[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_FRONT_EMISSION][1];
+      fcmd[MTL_EMMISSIVE_BLUE]  = mat[MAT_ATTRIB_FRONT_EMISSION][2];
+      fcmd[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_FRONT_EMISSION][3];
+   }
+   if (mask & MAT_BIT_FRONT_AMBIENT) {
+      fcmd[MTL_AMBIENT_RED]     = mat[MAT_ATTRIB_FRONT_AMBIENT][0];
+      fcmd[MTL_AMBIENT_GREEN]   = mat[MAT_ATTRIB_FRONT_AMBIENT][1];
+      fcmd[MTL_AMBIENT_BLUE]    = mat[MAT_ATTRIB_FRONT_AMBIENT][2];
+      fcmd[MTL_AMBIENT_ALPHA]   = mat[MAT_ATTRIB_FRONT_AMBIENT][3];
+   }
+   if (mask & MAT_BIT_FRONT_DIFFUSE) {
+      fcmd[MTL_DIFFUSE_RED]     = mat[MAT_ATTRIB_FRONT_DIFFUSE][0];
+      fcmd[MTL_DIFFUSE_GREEN]   = mat[MAT_ATTRIB_FRONT_DIFFUSE][1];
+      fcmd[MTL_DIFFUSE_BLUE]    = mat[MAT_ATTRIB_FRONT_DIFFUSE][2];
+      fcmd[MTL_DIFFUSE_ALPHA]   = mat[MAT_ATTRIB_FRONT_DIFFUSE][3];
+   }
+   if (mask & MAT_BIT_FRONT_SPECULAR) {
+      fcmd[MTL_SPECULAR_RED]    = mat[MAT_ATTRIB_FRONT_SPECULAR][0];
+      fcmd[MTL_SPECULAR_GREEN]  = mat[MAT_ATTRIB_FRONT_SPECULAR][1];
+      fcmd[MTL_SPECULAR_BLUE]   = mat[MAT_ATTRIB_FRONT_SPECULAR][2];
+      fcmd[MTL_SPECULAR_ALPHA]  = mat[MAT_ATTRIB_FRONT_SPECULAR][3];
+   }
+   if (mask & MAT_BIT_FRONT_SHININESS) {
+      fcmd[MTL_SHININESS]       = mat[MAT_ATTRIB_FRONT_SHININESS][0];
+   }
+
+   if (RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mtl )) {
+      for (p = 0 ; p < MAX_LIGHTS; p++) 
+        update_light_colors( ctx, p );
+
+      check_twoside_fallback( ctx );
+      update_global_ambient( ctx );
+   }
+   else if (RADEON_DEBUG & (DEBUG_PRIMS|DEBUG_STATE))
+      fprintf(stderr, "%s: Elided noop material call\n", __FUNCTION__);
+}
+
+/* _NEW_LIGHT
+ * _NEW_MODELVIEW
+ * _MESA_NEW_NEED_EYE_COORDS
+ *
+ * Uses derived state from mesa:
+ *       _VP_inf_norm
+ *       _h_inf_norm
+ *       _Position
+ *       _NormDirection
+ *       _ModelViewInvScale
+ *       _NeedEyeCoords
+ *       _EyeZDir
+ *
+ * which are calculated in light.c and are correct for the current
+ * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
+ * and _MESA_NEW_NEED_EYE_COORDS.  
+ */
+static void update_light( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   /* Have to check these, or have an automatic shortcircuit mechanism
+    * to remove noop statechanges. (Or just do a better job on the
+    * front end).
+    */
+   {
+      GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL];
+
+      if (ctx->_NeedEyeCoords)
+        tmp &= ~RADEON_LIGHT_IN_MODELSPACE;
+      else
+        tmp |= RADEON_LIGHT_IN_MODELSPACE;
+      
+
+      /* Leave this test disabled: (unexplained q3 lockup) (even with
+         new packets)
+      */
+      if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]) 
+      {
+        RADEON_STATECHANGE( rmesa, tcl );
+        rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = tmp;
+      }
+   }
+
+   {
+      GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( eye );
+      fcmd[EYE_X] = ctx->_EyeZDir[0];
+      fcmd[EYE_Y] = ctx->_EyeZDir[1];
+      fcmd[EYE_Z] = - ctx->_EyeZDir[2];
+      fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale;
+      RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.eye );
+   }
+
+
+
+   if (ctx->Light.Enabled) {
+      GLint p;
+      for (p = 0 ; p < MAX_LIGHTS; p++) {
+        if (ctx->Light.Light[p].Enabled) {
+           struct gl_light *l = &ctx->Light.Light[p];
+           GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( lit[p] );
+           
+           if (l->EyePosition[3] == 0.0) {
+              COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm ); 
+              COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm ); 
+              fcmd[LIT_POSITION_W] = 0;
+              fcmd[LIT_DIRECTION_W] = 0;
+           } else {
+              COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
+              fcmd[LIT_DIRECTION_X] = -l->_NormDirection[0];
+              fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1];
+              fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[2];
+              fcmd[LIT_DIRECTION_W] = 0;
+           }
+
+           RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
+        }
+      }
+   }
+}
+
+static void radeonLightfv( GLcontext *ctx, GLenum light,
+                          GLenum pname, const GLfloat *params )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLint p = light - GL_LIGHT0;
+   struct gl_light *l = &ctx->Light.Light[p];
+   GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
+   
+
+   switch (pname) {
+   case GL_AMBIENT:            
+   case GL_DIFFUSE:
+   case GL_SPECULAR:
+      update_light_colors( ctx, p );
+      break;
+
+   case GL_SPOT_DIRECTION: 
+      /* picked up in update_light */  
+      break;
+
+   case GL_POSITION: {
+      /* positions picked up in update_light, but can do flag here */  
+      GLuint flag;
+      GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
+
+      /* FIXME: Set RANGE_ATTEN only when needed */
+      if (p&1) 
+        flag = RADEON_LIGHT_1_IS_LOCAL;
+      else
+        flag = RADEON_LIGHT_0_IS_LOCAL;
+
+      RADEON_STATECHANGE(rmesa, tcl);
+      if (l->EyePosition[3] != 0.0F)
+        rmesa->hw.tcl.cmd[idx] |= flag;
+      else
+        rmesa->hw.tcl.cmd[idx] &= ~flag;
+      break;
+   }
+
+   case GL_SPOT_EXPONENT:
+      RADEON_STATECHANGE(rmesa, lit[p]);
+      fcmd[LIT_SPOT_EXPONENT] = params[0];
+      break;
+
+   case GL_SPOT_CUTOFF: {
+      GLuint flag = (p&1) ? RADEON_LIGHT_1_IS_SPOT : RADEON_LIGHT_0_IS_SPOT;
+      GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
+
+      RADEON_STATECHANGE(rmesa, lit[p]);
+      fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff;
+
+      RADEON_STATECHANGE(rmesa, tcl);
+      if (l->SpotCutoff != 180.0F)
+        rmesa->hw.tcl.cmd[idx] |= flag;
+      else
+        rmesa->hw.tcl.cmd[idx] &= ~flag;
+
+      break;
+   }
+
+   case GL_CONSTANT_ATTENUATION:
+      RADEON_STATECHANGE(rmesa, lit[p]);
+      fcmd[LIT_ATTEN_CONST] = params[0];
+      break;
+   case GL_LINEAR_ATTENUATION:
+      RADEON_STATECHANGE(rmesa, lit[p]);
+      fcmd[LIT_ATTEN_LINEAR] = params[0];
+      break;
+   case GL_QUADRATIC_ATTENUATION:
+      RADEON_STATECHANGE(rmesa, lit[p]);
+      fcmd[LIT_ATTEN_QUADRATIC] = params[0];
+      break;
+   default:
+      return;
+   }
+
+   /* Set RANGE_ATTEN only when needed */
+   switch (pname) {
+   case GL_POSITION:
+   case GL_LINEAR_ATTENUATION:
+   case GL_QUADRATIC_ATTENUATION:
+   {
+      GLuint flag;
+      GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
+
+      if (p&1) 
+        flag = RADEON_LIGHT_1_ENABLE_RANGE_ATTEN;
+      else
+        flag = RADEON_LIGHT_0_ENABLE_RANGE_ATTEN;
+
+      RADEON_STATECHANGE(rmesa, tcl);
+      if (l->EyePosition[3] != 0.0F &&
+         (l->LinearAttenuation != 0.0F || l->QuadraticAttenuation != 0.0F))
+        rmesa->hw.tcl.cmd[idx] |= flag;
+      else
+        rmesa->hw.tcl.cmd[idx] &= ~flag;
+      break;
+   }
+   default:
+      break;
+   }
+}
+
+                 
+
+
+static void radeonLightModelfv( GLcontext *ctx, GLenum pname,
+                               const GLfloat *param )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   switch (pname) {
+      case GL_LIGHT_MODEL_AMBIENT: 
+        update_global_ambient( ctx );
+        break;
+
+      case GL_LIGHT_MODEL_LOCAL_VIEWER:
+        RADEON_STATECHANGE( rmesa, tcl );
+        if (ctx->Light.Model.LocalViewer)
+           rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LOCAL_VIEWER;
+        else
+           rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LOCAL_VIEWER;
+         break;
+
+      case GL_LIGHT_MODEL_TWO_SIDE:
+        RADEON_STATECHANGE( rmesa, tcl );
+        if (ctx->Light.Model.TwoSide)
+           rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_LIGHT_TWOSIDE;
+        else
+           rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_LIGHT_TWOSIDE;
+
+        check_twoside_fallback( ctx );
+
+        if (rmesa->TclFallback) {
+           radeonChooseRenderState( ctx );
+           radeonChooseVertexState( ctx );
+        }
+         break;
+
+      case GL_LIGHT_MODEL_COLOR_CONTROL:
+        radeonUpdateSpecular(ctx);
+         break;
+
+      default:
+         break;
+   }
+}
+
+static void radeonShadeModel( GLcontext *ctx, GLenum mode )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
+
+   s &= ~(RADEON_DIFFUSE_SHADE_MASK |
+         RADEON_ALPHA_SHADE_MASK |
+         RADEON_SPECULAR_SHADE_MASK |
+         RADEON_FOG_SHADE_MASK);
+
+   switch ( mode ) {
+   case GL_FLAT:
+      s |= (RADEON_DIFFUSE_SHADE_FLAT |
+           RADEON_ALPHA_SHADE_FLAT |
+           RADEON_SPECULAR_SHADE_FLAT |
+           RADEON_FOG_SHADE_FLAT);
+      break;
+   case GL_SMOOTH:
+      s |= (RADEON_DIFFUSE_SHADE_GOURAUD |
+           RADEON_ALPHA_SHADE_GOURAUD |
+           RADEON_SPECULAR_SHADE_GOURAUD |
+           RADEON_FOG_SHADE_GOURAUD);
+      break;
+   default:
+      return;
+   }
+
+   if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
+      RADEON_STATECHANGE( rmesa, set );
+      rmesa->hw.set.cmd[SET_SE_CNTL] = s;
+   }
+}
+
+
+/* =============================================================
+ * User clip planes
+ */
+
+static void radeonClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq )
+{
+   GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
+
+   RADEON_STATECHANGE( rmesa, ucp[p] );
+   rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
+   rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
+   rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
+   rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
+}
+
+static void radeonUpdateClipPlanes( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLuint p;
+
+   for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
+      if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
+        GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
+
+        RADEON_STATECHANGE( rmesa, ucp[p] );
+        rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
+        rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
+        rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
+        rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
+      }
+   }
+}
+
+
+/* =============================================================
+ * Stencil
+ */
+
+static void radeonStencilFunc( GLcontext *ctx, GLenum func,
+                              GLint ref, GLuint mask )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLuint refmask = ((ctx->Stencil.Ref[0] << RADEON_STENCIL_REF_SHIFT) |
+                    (ctx->Stencil.ValueMask[0] << RADEON_STENCIL_MASK_SHIFT));
+
+   RADEON_STATECHANGE( rmesa, ctx );
+   RADEON_STATECHANGE( rmesa, msk );
+
+   rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_STENCIL_TEST_MASK;
+   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(RADEON_STENCIL_REF_MASK|
+                                                  RADEON_STENCIL_VALUE_MASK);
+
+   switch ( ctx->Stencil.Function[0] ) {
+   case GL_NEVER:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_NEVER;
+      break;
+   case GL_LESS:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_LESS;
+      break;
+   case GL_EQUAL:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_EQUAL;
+      break;
+   case GL_LEQUAL:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_LEQUAL;
+      break;
+   case GL_GREATER:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_GREATER;
+      break;
+   case GL_NOTEQUAL:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_NEQUAL;
+      break;
+   case GL_GEQUAL:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_GEQUAL;
+      break;
+   case GL_ALWAYS:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_ALWAYS;
+      break;
+   }
+
+   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
+}
+
+static void radeonStencilMask( GLcontext *ctx, GLuint mask )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   RADEON_STATECHANGE( rmesa, msk );
+   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~RADEON_STENCIL_WRITE_MASK;
+   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |=
+      (ctx->Stencil.WriteMask[0] << RADEON_STENCIL_WRITEMASK_SHIFT);
+}
+
+static void radeonStencilOp( GLcontext *ctx, GLenum fail,
+                            GLenum zfail, GLenum zpass )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   RADEON_STATECHANGE( rmesa, ctx );
+   rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(RADEON_STENCIL_FAIL_MASK |
+                                              RADEON_STENCIL_ZFAIL_MASK |
+                                              RADEON_STENCIL_ZPASS_MASK);
+
+   switch ( ctx->Stencil.FailFunc[0] ) {
+   case GL_KEEP:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_KEEP;
+      break;
+   case GL_ZERO:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_ZERO;
+      break;
+   case GL_REPLACE:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_REPLACE;
+      break;
+   case GL_INCR:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_INC;
+      break;
+   case GL_DECR:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_DEC;
+      break;
+   case GL_INVERT:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_INVERT;
+      break;
+   }
+
+   switch ( ctx->Stencil.ZFailFunc[0] ) {
+   case GL_KEEP:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_KEEP;
+      break;
+   case GL_ZERO:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_ZERO;
+      break;
+   case GL_REPLACE:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_REPLACE;
+      break;
+   case GL_INCR:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_INC;
+      break;
+   case GL_DECR:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_DEC;
+      break;
+   case GL_INVERT:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_INVERT;
+      break;
+   }
+
+   switch ( ctx->Stencil.ZPassFunc[0] ) {
+   case GL_KEEP:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_KEEP;
+      break;
+   case GL_ZERO:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_ZERO;
+      break;
+   case GL_REPLACE:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_REPLACE;
+      break;
+   case GL_INCR:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_INC;
+      break;
+   case GL_DECR:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_DEC;
+      break;
+   case GL_INVERT:
+      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_INVERT;
+      break;
+   }
+}
+
+static void radeonClearStencil( GLcontext *ctx, GLint s )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   rmesa->state.stencil.clear = 
+      ((GLuint) ctx->Stencil.Clear |
+       (0xff << RADEON_STENCIL_MASK_SHIFT) |
+       (ctx->Stencil.WriteMask[0] << RADEON_STENCIL_WRITEMASK_SHIFT));
+}
+
+
+/* =============================================================
+ * Window position and viewport transformation
+ */
+
+/*
+ * To correctly position primitives:
+ */
+#define SUBPIXEL_X 0.125
+#define SUBPIXEL_Y 0.125
+
+void radeonUpdateWindow( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
+   GLfloat xoffset = (GLfloat)dPriv->x;
+   GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
+   const GLfloat *v = ctx->Viewport._WindowMap.m;
+
+   GLfloat sx = v[MAT_SX];
+   GLfloat tx = v[MAT_TX] + xoffset + SUBPIXEL_X;
+   GLfloat sy = - v[MAT_SY];
+   GLfloat ty = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y;
+   GLfloat sz = v[MAT_SZ] * rmesa->state.depth.scale;
+   GLfloat tz = v[MAT_TZ] * rmesa->state.depth.scale;
+   RADEON_FIREVERTICES( rmesa );
+   RADEON_STATECHANGE( rmesa, vpt );
+
+   rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE]  = *(GLuint *)&sx;
+   rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx;
+   rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE]  = *(GLuint *)&sy;
+   rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty;
+   rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE]  = *(GLuint *)&sz;
+   rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = *(GLuint *)&tz;
+}
+
+
+
+static void radeonViewport( GLcontext *ctx, GLint x, GLint y,
+                           GLsizei width, GLsizei height )
+{
+   /* Don't pipeline viewport changes, conflict with window offset
+    * setting below.  Could apply deltas to rescue pipelined viewport
+    * values, or keep the originals hanging around.
+    */
+   RADEON_FIREVERTICES( RADEON_CONTEXT(ctx) );
+   radeonUpdateWindow( ctx );
+}
+
+static void radeonDepthRange( GLcontext *ctx, GLclampd nearval,
+                             GLclampd farval )
+{
+   radeonUpdateWindow( ctx );
+}
+
+void radeonUpdateViewportOffset( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
+   GLfloat xoffset = (GLfloat)dPriv->x;
+   GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
+   const GLfloat *v = ctx->Viewport._WindowMap.m;
+
+   GLfloat tx = v[MAT_TX] + xoffset;
+   GLfloat ty = (- v[MAT_TY]) + yoffset;
+
+   if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != *(GLuint *)&tx ||
+       rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != *(GLuint *)&ty )
+   {
+      /* Note: this should also modify whatever data the context reset
+       * code uses...
+       */
+      rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx;
+      rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty;
+      
+      /* update polygon stipple x/y screen offset */
+      {
+         GLuint stx, sty;
+         GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC];
+
+         m &= ~(RADEON_STIPPLE_X_OFFSET_MASK |
+                RADEON_STIPPLE_Y_OFFSET_MASK);
+
+         /* add magic offsets, then invert */
+         stx = 31 - ((rmesa->dri.drawable->x - 1) & RADEON_STIPPLE_COORD_MASK);
+         sty = 31 - ((rmesa->dri.drawable->y + rmesa->dri.drawable->h - 1)
+                     & RADEON_STIPPLE_COORD_MASK);
+
+         m |= ((stx << RADEON_STIPPLE_X_OFFSET_SHIFT) |
+               (sty << RADEON_STIPPLE_Y_OFFSET_SHIFT));
+
+         if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) {
+            RADEON_STATECHANGE( rmesa, msc );
+           rmesa->hw.msc.cmd[MSC_RE_MISC] = m;
+         }
+      }
+   }
+
+   radeonUpdateScissor( ctx );
+}
+
+
+
+/* =============================================================
+ * Miscellaneous
+ */
+
+static void radeonClearColor( GLcontext *ctx, const GLfloat color[4] )
+{
+   radeonContextPtr rmesa = RADEON_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]);
+   CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
+   rmesa->state.color.clear = radeonPackColor( rmesa->radeonScreen->cpp,
+                                              c[0], c[1], c[2], c[3] );
+}
+
+
+static void radeonRenderMode( GLcontext *ctx, GLenum mode )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   FALLBACK( rmesa, RADEON_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
+}
+
+
+static GLuint radeon_rop_tab[] = {
+   RADEON_ROP_CLEAR,
+   RADEON_ROP_AND,
+   RADEON_ROP_AND_REVERSE,
+   RADEON_ROP_COPY,
+   RADEON_ROP_AND_INVERTED,
+   RADEON_ROP_NOOP,
+   RADEON_ROP_XOR,
+   RADEON_ROP_OR,
+   RADEON_ROP_NOR,
+   RADEON_ROP_EQUIV,
+   RADEON_ROP_INVERT,
+   RADEON_ROP_OR_REVERSE,
+   RADEON_ROP_COPY_INVERTED,
+   RADEON_ROP_OR_INVERTED,
+   RADEON_ROP_NAND,
+   RADEON_ROP_SET,
+};
+
+static void radeonLogicOpCode( GLcontext *ctx, GLenum opcode )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLuint rop = (GLuint)opcode - GL_CLEAR;
+
+   ASSERT( rop < 16 );
+
+   RADEON_STATECHANGE( rmesa, msk );
+   rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = radeon_rop_tab[rop];
+}
+
+
+void radeonSetCliprects( radeonContextPtr rmesa, GLenum mode )
+{
+   __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
+
+   switch ( mode ) {
+   case GL_FRONT_LEFT:
+      rmesa->numClipRects = dPriv->numClipRects;
+      rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects;
+      break;
+   case GL_BACK_LEFT:
+      /* Can't ignore 2d windows if we are page flipping.
+       */
+      if ( dPriv->numBackClipRects == 0 || rmesa->doPageFlip ) {
+        rmesa->numClipRects = dPriv->numClipRects;
+        rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pClipRects;
+      }
+      else {
+        rmesa->numClipRects = dPriv->numBackClipRects;
+        rmesa->pClipRects = (XF86DRIClipRectPtr)dPriv->pBackClipRects;
+      }
+      break;
+   default:
+      fprintf(stderr, "bad mode in radeonSetCliprects\n");
+      return;
+   }
+
+   if (rmesa->state.scissor.enabled)
+      radeonRecalcScissorRects( rmesa );
+}
+
+
+static void radeonDrawBuffer( GLcontext *ctx, GLenum mode )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   if (RADEON_DEBUG & DEBUG_DRI)
+      fprintf(stderr, "%s %s\n", __FUNCTION__,
+             _mesa_lookup_enum_by_nr( mode ));
+
+   RADEON_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */
+
+   /*
+    * _DrawDestMask is easier to cope with than <mode>.
+    */
+   switch ( ctx->Color._DrawDestMask ) {
+   case FRONT_LEFT_BIT:
+      FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE );
+      radeonSetCliprects( rmesa, GL_FRONT_LEFT );
+      break;
+   case BACK_LEFT_BIT:
+      FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE );
+      radeonSetCliprects( rmesa, GL_BACK_LEFT );
+      break;
+   default:
+      /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
+      FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE );
+      return;
+   }
+
+   /* We want to update the s/w rast state too so that r200SetBuffer()
+    * gets called.
+    */
+   _swrast_DrawBuffer(ctx, mode);
+
+   RADEON_STATECHANGE( rmesa, ctx );
+   rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = (rmesa->state.color.drawOffset &
+                                           RADEON_COLOROFFSET_MASK);
+   rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = rmesa->state.color.drawPitch;
+}
+
+static void radeonReadBuffer( GLcontext *ctx, GLenum mode )
+{
+   /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
+}
+
+
+/* =============================================================
+ * State enable/disable
+ */
+
+static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLuint p, flag;
+
+   if ( RADEON_DEBUG & DEBUG_STATE )
+      fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__,
+              _mesa_lookup_enum_by_nr( cap ),
+              state ? "GL_TRUE" : "GL_FALSE" );
+
+   switch ( cap ) {
+      /* Fast track this one...
+       */
+   case GL_TEXTURE_1D:
+   case GL_TEXTURE_2D:
+   case GL_TEXTURE_3D:
+      break;
+
+   case GL_ALPHA_TEST:
+      RADEON_STATECHANGE( rmesa, ctx );
+      if (state) {
+        rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ALPHA_TEST_ENABLE;
+      } else {
+        rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ALPHA_TEST_ENABLE;
+      }
+      break;
+
+   case GL_BLEND:
+      RADEON_STATECHANGE( rmesa, ctx );
+      if (state) {
+        rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  RADEON_ALPHA_BLEND_ENABLE;
+      } else {
+        rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ALPHA_BLEND_ENABLE;
+      }
+      if ( ctx->Color.ColorLogicOpEnabled ) {
+        rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  RADEON_ROP_ENABLE;
+      } else {
+        rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
+      }
+
+      /* Catch a possible fallback:
+       */
+      if (state) {
+        ctx->Driver.BlendEquation( ctx, ctx->Color.BlendEquation );
+        ctx->Driver.BlendFunc( ctx, ctx->Color.BlendSrcRGB,
+                               ctx->Color.BlendDstRGB );
+      }
+      else {
+        FALLBACK( rmesa, RADEON_FALLBACK_BLEND_FUNC, GL_FALSE );
+        FALLBACK( rmesa, RADEON_FALLBACK_BLEND_EQ, GL_FALSE );
+      }
+      break;
+
+   case GL_CLIP_PLANE0:
+   case GL_CLIP_PLANE1:
+   case GL_CLIP_PLANE2:
+   case GL_CLIP_PLANE3:
+   case GL_CLIP_PLANE4:
+   case GL_CLIP_PLANE5: 
+      p = cap-GL_CLIP_PLANE0;
+      RADEON_STATECHANGE( rmesa, tcl );
+      if (state) {
+        rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (RADEON_UCP_ENABLE_0<<p);
+        radeonClipPlane( ctx, cap, NULL );
+      }
+      else {
+        rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(RADEON_UCP_ENABLE_0<<p);
+      }
+      break;
+
+   case GL_COLOR_MATERIAL:
+      radeonColorMaterial( ctx, 0, 0 );
+      if (!state) 
+        radeonUpdateMaterial( ctx );
+      break;
+
+   case GL_CULL_FACE:
+      radeonCullFace( ctx, 0 );
+      break;
+
+   case GL_DEPTH_TEST:
+      RADEON_STATECHANGE(rmesa, ctx );
+      if ( state ) {
+        rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  RADEON_Z_ENABLE;
+      } else {
+        rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_Z_ENABLE;
+      }
+      break;
+
+   case GL_DITHER:
+      RADEON_STATECHANGE(rmesa, ctx );
+      if ( state ) {
+        rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  RADEON_DITHER_ENABLE;
+      } else {
+        rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_DITHER_ENABLE;
+      }
+      break;
+
+   case GL_FOG:
+      RADEON_STATECHANGE(rmesa, ctx );
+      if ( state ) {
+        rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_FOG_ENABLE;
+        radeonFogfv( ctx, GL_FOG_MODE, 0 );
+      } else {
+        rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_FOG_ENABLE;
+        RADEON_STATECHANGE(rmesa, tcl);
+        rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK;
+      }
+      radeonUpdateSpecular( ctx ); /* for PK_SPEC */
+      if (rmesa->TclFallback) 
+        radeonChooseVertexState( ctx );
+      _mesa_allow_light_in_model( ctx, !state );
+      break;
+
+   case GL_LIGHT0:
+   case GL_LIGHT1:
+   case GL_LIGHT2:
+   case GL_LIGHT3:
+   case GL_LIGHT4:
+   case GL_LIGHT5:
+   case GL_LIGHT6:
+   case GL_LIGHT7:
+      RADEON_STATECHANGE(rmesa, tcl);
+      p = cap - GL_LIGHT0;
+      if (p&1) 
+        flag = (RADEON_LIGHT_1_ENABLE |
+                RADEON_LIGHT_1_ENABLE_AMBIENT | 
+                RADEON_LIGHT_1_ENABLE_SPECULAR);
+      else
+        flag = (RADEON_LIGHT_0_ENABLE |
+                RADEON_LIGHT_0_ENABLE_AMBIENT | 
+                RADEON_LIGHT_0_ENABLE_SPECULAR);
+
+      if (state)
+        rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
+      else
+        rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
+
+      /* 
+       */
+      update_light_colors( ctx, p );
+      break;
+
+   case GL_LIGHTING:
+      RADEON_STATECHANGE(rmesa, tcl);
+      radeonUpdateSpecular(ctx);
+      check_twoside_fallback( ctx );
+      break;
+
+   case GL_LINE_SMOOTH:
+      RADEON_STATECHANGE( rmesa, ctx );
+      if ( state ) {
+        rmesa->hw.ctx.cmd[CTX_PP_CNTL] |=  RADEON_ANTI_ALIAS_LINE;
+      } else {
+        rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ANTI_ALIAS_LINE;
+      }
+      break;
+
+   case GL_LINE_STIPPLE:
+      RADEON_STATECHANGE( rmesa, ctx );
+      if ( state ) {
+        rmesa->hw.ctx.cmd[CTX_PP_CNTL] |=  RADEON_PATTERN_ENABLE;
+      } else {
+        rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_PATTERN_ENABLE;
+      }
+      break;
+
+   case GL_COLOR_LOGIC_OP:
+      RADEON_STATECHANGE( rmesa, ctx );
+      if ( state ) {
+        rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  RADEON_ROP_ENABLE;
+      } else {
+        rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
+      }
+      break;
+      
+   case GL_NORMALIZE:
+      RADEON_STATECHANGE( rmesa, tcl );
+      if ( state ) {
+        rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |=  RADEON_NORMALIZE_NORMALS;
+      } else {
+        rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_NORMALIZE_NORMALS;
+      }
+      break;
+
+   case GL_POLYGON_OFFSET_POINT:
+      if (rmesa->dri.drmMinor == 1) {
+        radeonChooseRenderState( ctx );
+      } 
+      else {
+        RADEON_STATECHANGE( rmesa, set );
+        if ( state ) {
+           rmesa->hw.set.cmd[SET_SE_CNTL] |=  RADEON_ZBIAS_ENABLE_POINT;
+        } else {
+           rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_POINT;
+        }
+      }
+      break;
+
+   case GL_POLYGON_OFFSET_LINE:
+      if (rmesa->dri.drmMinor == 1) {
+        radeonChooseRenderState( ctx );
+      } 
+      else {
+        RADEON_STATECHANGE( rmesa, set );
+        if ( state ) {
+           rmesa->hw.set.cmd[SET_SE_CNTL] |=  RADEON_ZBIAS_ENABLE_LINE;
+        } else {
+           rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_LINE;
+        }
+      }
+      break;
+
+   case GL_POLYGON_OFFSET_FILL:
+      if (rmesa->dri.drmMinor == 1) {
+        radeonChooseRenderState( ctx );
+      } 
+      else {
+        RADEON_STATECHANGE( rmesa, set );
+        if ( state ) {
+           rmesa->hw.set.cmd[SET_SE_CNTL] |=  RADEON_ZBIAS_ENABLE_TRI;
+        } else {
+           rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_TRI;
+        }
+      }
+      break;
+
+   case GL_POLYGON_SMOOTH:
+      RADEON_STATECHANGE( rmesa, ctx );
+      if ( state ) {
+        rmesa->hw.ctx.cmd[CTX_PP_CNTL] |=  RADEON_ANTI_ALIAS_POLY;
+      } else {
+        rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ANTI_ALIAS_POLY;
+      }
+      break;
+
+   case GL_POLYGON_STIPPLE:
+      RADEON_STATECHANGE(rmesa, ctx );
+      if ( state ) {
+        rmesa->hw.ctx.cmd[CTX_PP_CNTL] |=  RADEON_STIPPLE_ENABLE;
+      } else {
+        rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_STIPPLE_ENABLE;
+      }
+      break;
+
+   case GL_RESCALE_NORMAL_EXT: {
+      GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
+      RADEON_STATECHANGE( rmesa, tcl );
+      if ( tmp ) {
+        rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |=  RADEON_RESCALE_NORMALS;
+      } else {
+        rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS;
+      }
+      break;
+   }
+
+   case GL_SCISSOR_TEST:
+      RADEON_FIREVERTICES( rmesa );
+      rmesa->state.scissor.enabled = state;
+      radeonUpdateScissor( ctx );
+      break;
+
+   case GL_STENCIL_TEST:
+      if ( rmesa->state.stencil.hwBuffer ) {
+        RADEON_STATECHANGE( rmesa, ctx );
+        if ( state ) {
+           rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  RADEON_STENCIL_ENABLE;
+        } else {
+           rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_STENCIL_ENABLE;
+        }
+      } else {
+        FALLBACK( rmesa, RADEON_FALLBACK_STENCIL, state );
+      }
+      break;
+
+   case GL_TEXTURE_GEN_Q:
+   case GL_TEXTURE_GEN_R:
+   case GL_TEXTURE_GEN_S:
+   case GL_TEXTURE_GEN_T:
+      /* Picked up in radeonUpdateTextureState.
+       */
+      rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE; 
+      break;
+
+   case GL_COLOR_SUM_EXT:
+      radeonUpdateSpecular ( ctx );
+      break;
+
+   default:
+      return;
+   }
+}
+
+
+static void radeonLightingSpaceChange( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLboolean tmp;
+   RADEON_STATECHANGE( rmesa, tcl );
+
+   if (RADEON_DEBUG & DEBUG_STATE)
+      fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
+             rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]);
+
+   if (ctx->_NeedEyeCoords)
+      tmp = ctx->Transform.RescaleNormals;
+   else
+      tmp = !ctx->Transform.RescaleNormals;
+
+   if ( tmp ) {
+      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |=  RADEON_RESCALE_NORMALS;
+   } else {
+      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS;
+   }
+
+   if (RADEON_DEBUG & DEBUG_STATE) 
+      fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
+             rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]);
+}
+
+/* =============================================================
+ * Deferred state management - matrices, textures, other?
+ */
+
+
+
+
+static void upload_matrix( radeonContextPtr rmesa, GLfloat *src, int idx )
+{
+   float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0;
+   int i;
+
+
+   for (i = 0 ; i < 4 ; i++) {
+      *dest++ = src[i];
+      *dest++ = src[i+4];
+      *dest++ = src[i+8];
+      *dest++ = src[i+12];
+   }
+
+   RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
+}
+
+static void upload_matrix_t( radeonContextPtr rmesa, GLfloat *src, int idx )
+{
+   float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0;
+   memcpy(dest, src, 16*sizeof(float));
+   RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
+}
+
+
+static void update_texturematrix( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+   GLuint tpc = rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL];
+   GLuint vs = rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL];
+   int unit;
+
+   rmesa->TexMatEnabled = 0;
+
+   for (unit = 0 ; unit < 2; unit++) {
+      if (!ctx->Texture.Unit[unit]._ReallyEnabled) {
+      }
+      else if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
+        GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4;
+        
+        rmesa->TexMatEnabled |= (RADEON_TEXGEN_TEXMAT_0_ENABLE|
+                                 RADEON_TEXMAT_0_ENABLE) << unit;
+
+        if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) {
+           /* Need to preconcatenate any active texgen 
+            * obj/eyeplane matrices:
+            */
+           _math_matrix_mul_matrix( &rmesa->tmpmat, 
+                                    &rmesa->TexGenMatrix[unit],
+                                    ctx->TextureMatrixStack[unit].Top );
+           upload_matrix( rmesa, rmesa->tmpmat.m, TEXMAT_0+unit );
+        } 
+        else {
+           rmesa->TexMatEnabled |= 
+              (RADEON_TEXGEN_INPUT_TEXCOORD_0+unit) << inputshift;
+           upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m, 
+                          TEXMAT_0+unit );
+        }
+      }
+      else if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) {
+        upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m, 
+                       TEXMAT_0+unit );
+      }
+   }
+
+
+   tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled);
+
+   vs &= ~((0xf << RADEON_TCL_TEX_0_OUTPUT_SHIFT) |
+          (0xf << RADEON_TCL_TEX_1_OUTPUT_SHIFT));
+
+   if (tpc & RADEON_TEXGEN_TEXMAT_0_ENABLE)
+      vs |= RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT;
+   else
+      vs |= RADEON_TCL_TEX_INPUT_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT;
+
+   if (tpc & RADEON_TEXGEN_TEXMAT_1_ENABLE)
+      vs |= RADEON_TCL_TEX_COMPUTED_TEX_1 << RADEON_TCL_TEX_1_OUTPUT_SHIFT;
+   else
+      vs |= RADEON_TCL_TEX_INPUT_TEX_1 << RADEON_TCL_TEX_1_OUTPUT_SHIFT;
+
+   if (tpc != rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] ||
+       vs != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL]) {
+      
+      RADEON_STATECHANGE(rmesa, tcl);
+      rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] = tpc;
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] = vs;
+   }
+}
+
+
+
+void radeonValidateState( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLuint new_state = rmesa->NewGLState;
+
+   if (new_state & _NEW_TEXTURE) {
+      radeonUpdateTextureState( ctx );
+      new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */
+   }
+
+   /* Need an event driven matrix update?
+    */
+   if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION)) 
+      upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, MODEL_PROJ );
+
+   /* Need these for lighting (shouldn't upload otherwise)
+    */
+   if (new_state & (_NEW_MODELVIEW)) {
+      upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, MODEL );
+      upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, MODEL_IT );
+   }
+
+   /* Does this need to be triggered on eg. modelview for
+    * texgen-derived objplane/eyeplane matrices?
+    */
+   if (new_state & _NEW_TEXTURE_MATRIX) {
+      update_texturematrix( ctx );
+   }      
+
+   if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
+      update_light( ctx );
+   }
+
+   /* emit all active clip planes if projection matrix changes.
+    */
+   if (new_state & (_NEW_PROJECTION)) {
+      if (ctx->Transform.ClipPlanesEnabled) 
+        radeonUpdateClipPlanes( ctx );
+   }
+
+
+   rmesa->NewGLState = 0;
+}
+
+
+static void radeonInvalidateState( GLcontext *ctx, GLuint new_state )
+{
+   _swrast_InvalidateState( ctx, new_state );
+   _swsetup_InvalidateState( ctx, new_state );
+   _ac_InvalidateState( ctx, new_state );
+   _tnl_InvalidateState( ctx, new_state );
+   _ae_invalidate_state( ctx, new_state );
+   RADEON_CONTEXT(ctx)->NewGLState |= new_state;
+   radeonVtxfmtInvalidate( ctx );
+}
+
+static void radeonWrapRunPipeline( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+   if (0)
+      fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState);
+
+   /* Validate state:
+    */
+   if (rmesa->NewGLState)
+      radeonValidateState( ctx );
+
+   if (tnl->vb.Material) {
+      TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_TRUE );
+   }
+
+   /* Run the pipeline.
+    */ 
+   _tnl_run_pipeline( ctx );
+
+   if (tnl->vb.Material) {
+      TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_FALSE );
+      radeonUpdateMaterial( ctx ); /* not needed any more? */
+   }
+}
+
+
+/* Initialize the driver's state functions.
+ */
+void radeonInitStateFuncs( GLcontext *ctx )
+{
+   ctx->Driver.UpdateState             = radeonInvalidateState;
+   ctx->Driver.LightingSpaceChange      = radeonLightingSpaceChange;
+
+   ctx->Driver.DrawBuffer              = radeonDrawBuffer;
+   ctx->Driver.ReadBuffer              = radeonReadBuffer;
+
+   ctx->Driver.AlphaFunc               = radeonAlphaFunc;
+   ctx->Driver.BlendEquation           = radeonBlendEquation;
+   ctx->Driver.BlendFunc               = radeonBlendFunc;
+   ctx->Driver.BlendFuncSeparate       = radeonBlendFuncSeparate;
+   ctx->Driver.ClearColor              = radeonClearColor;
+   ctx->Driver.ClearDepth              = radeonClearDepth;
+   ctx->Driver.ClearIndex              = NULL;
+   ctx->Driver.ClearStencil            = radeonClearStencil;
+   ctx->Driver.ClipPlane               = radeonClipPlane;
+   ctx->Driver.ColorMask               = radeonColorMask;
+   ctx->Driver.CullFace                        = radeonCullFace;
+   ctx->Driver.DepthFunc               = radeonDepthFunc;
+   ctx->Driver.DepthMask               = radeonDepthMask;
+   ctx->Driver.DepthRange              = radeonDepthRange;
+   ctx->Driver.Enable                  = radeonEnable;
+   ctx->Driver.Fogfv                   = radeonFogfv;
+   ctx->Driver.FrontFace               = radeonFrontFace;
+   ctx->Driver.Hint                    = NULL;
+   ctx->Driver.IndexMask               = NULL;
+   ctx->Driver.LightModelfv            = radeonLightModelfv;
+   ctx->Driver.Lightfv                 = radeonLightfv;
+   ctx->Driver.LineStipple              = radeonLineStipple;
+   ctx->Driver.LineWidth                = radeonLineWidth;
+   ctx->Driver.LogicOpcode             = radeonLogicOpCode;
+   ctx->Driver.PolygonMode             = radeonPolygonMode;
+
+   if (RADEON_CONTEXT(ctx)->dri.drmMinor > 1)
+      ctx->Driver.PolygonOffset                = radeonPolygonOffset;
+
+   ctx->Driver.PolygonStipple          = radeonPolygonStipple;
+   ctx->Driver.RenderMode              = radeonRenderMode;
+   ctx->Driver.Scissor                 = radeonScissor;
+   ctx->Driver.ShadeModel              = radeonShadeModel;
+   ctx->Driver.StencilFunc             = radeonStencilFunc;
+   ctx->Driver.StencilMask             = radeonStencilMask;
+   ctx->Driver.StencilOp               = radeonStencilOp;
+   ctx->Driver.Viewport                        = radeonViewport;
+
+   /* Pixel path fallbacks
+    */
+   ctx->Driver.Accum                    = _swrast_Accum;
+   ctx->Driver.Bitmap                   = _swrast_Bitmap;
+   ctx->Driver.CopyPixels               = _swrast_CopyPixels;
+   ctx->Driver.DrawPixels               = _swrast_DrawPixels;
+   ctx->Driver.ReadPixels               = _swrast_ReadPixels;
+
+   /* 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;
+
+   TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = radeonUpdateMaterial;
+   TNL_CONTEXT(ctx)->Driver.RunPipeline = radeonWrapRunPipeline;
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_state.h b/src/mesa/drivers/dri/radeon/radeon_state.h
new file mode 100644 (file)
index 0000000..a181d42
--- /dev/null
@@ -0,0 +1,77 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_state.h,v 1.5 2002/11/05 17:46:09 tsi Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#ifndef __RADEON_STATE_H__
+#define __RADEON_STATE_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include "radeon_context.h"
+
+extern void radeonInitState( radeonContextPtr rmesa );
+extern void radeonInitStateFuncs( GLcontext *ctx );
+
+extern void radeonUpdateMaterial( GLcontext *ctx );
+
+extern void radeonSetCliprects( radeonContextPtr rmesa, GLenum mode );
+extern void radeonRecalcScissorRects( radeonContextPtr rmesa );
+extern void radeonUpdateViewportOffset( GLcontext *ctx );
+extern void radeonUpdateWindow( GLcontext *ctx );
+
+extern void radeonValidateState( GLcontext *ctx );
+
+extern void radeonPrintDirty( radeonContextPtr rmesa,
+                             const char *msg );
+
+
+extern void radeonFallback( GLcontext *ctx, GLuint bit, GLboolean mode );
+#define FALLBACK( rmesa, bit, mode ) do {                              \
+   if ( 0 ) fprintf( stderr, "FALLBACK in %s: #%d=%d\n",               \
+                    __FUNCTION__, bit, mode );                         \
+   radeonFallback( rmesa->glCtx, bit, mode );                          \
+} while (0)
+
+
+#define MODEL_PROJ 0
+#define MODEL      1
+#define MODEL_IT   2
+#define TEXMAT_0   3
+#define TEXMAT_1   4
+#define TEXMAT_2   5
+
+#endif
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_state_init.c b/src/mesa/drivers/dri/radeon/radeon_state_init.c
new file mode 100644 (file)
index 0000000..971ea69
--- /dev/null
@@ -0,0 +1,531 @@
+/* $XFree86$ */
+/*
+ * Copyright 2000, 2001 VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "api_arrayelt.h"
+
+#include "swrast/swrast.h"
+#include "array_cache/acache.h"
+#include "tnl/tnl.h"
+#include "tnl/t_pipeline.h"
+#include "swrast_setup/swrast_setup.h"
+
+#include "radeon_context.h"
+#include "radeon_ioctl.h"
+#include "radeon_state.h"
+#include "radeon_tcl.h"
+#include "radeon_tex.h"
+#include "radeon_swtcl.h"
+#include "radeon_vtxfmt.h"
+
+/* =============================================================
+ * State initialization
+ */
+
+void radeonPrintDirty( radeonContextPtr rmesa, const char *msg )
+{
+   struct radeon_state_atom *l;
+
+   fprintf(stderr, msg);
+   fprintf(stderr, ": ");
+
+   foreach(l, &(rmesa->hw.dirty)) {
+      fprintf(stderr, "%s, ", l->name);
+   }
+
+   fprintf(stderr, "\n");
+}
+
+static int cmdpkt( int id ) 
+{
+   drmRadeonCmdHeader h;
+   h.i = 0;
+   h.packet.cmd_type = RADEON_CMD_PACKET;
+   h.packet.packet_id = id;
+   return h.i;
+}
+
+static int cmdvec( int offset, int stride, int count ) 
+{
+   drmRadeonCmdHeader h;
+   h.i = 0;
+   h.vectors.cmd_type = RADEON_CMD_VECTORS;
+   h.vectors.offset = offset;
+   h.vectors.stride = stride;
+   h.vectors.count = count;
+   return h.i;
+}
+
+static int cmdscl( int offset, int stride, int count ) 
+{
+   drmRadeonCmdHeader h;
+   h.i = 0;
+   h.scalars.cmd_type = RADEON_CMD_SCALARS;
+   h.scalars.offset = offset;
+   h.scalars.stride = stride;
+   h.scalars.count = count;
+   return h.i;
+}
+
+#define CHECK( NM, FLAG )                      \
+static GLboolean check_##NM( GLcontext *ctx )  \
+{                                              \
+   return FLAG;                                        \
+}
+
+#define TCL_CHECK( NM, FLAG )                          \
+static GLboolean check_##NM( GLcontext *ctx )          \
+{                                                      \
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);       \
+   return !rmesa->TclFallback && (FLAG);               \
+}
+
+
+CHECK( always, GL_TRUE )
+CHECK( tex0, ctx->Texture.Unit[0]._ReallyEnabled )
+CHECK( tex1, ctx->Texture.Unit[1]._ReallyEnabled )
+CHECK( fog, ctx->Fog.Enabled )
+TCL_CHECK( tcl, GL_TRUE )
+TCL_CHECK( tcl_tex0, ctx->Texture.Unit[0]._ReallyEnabled )
+TCL_CHECK( tcl_tex1, ctx->Texture.Unit[1]._ReallyEnabled )
+TCL_CHECK( tcl_lighting, ctx->Light.Enabled )
+TCL_CHECK( tcl_eyespace_or_lighting, ctx->_NeedEyeCoords || ctx->Light.Enabled )
+TCL_CHECK( tcl_lit0, ctx->Light.Enabled && ctx->Light.Light[0].Enabled )
+TCL_CHECK( tcl_lit1, ctx->Light.Enabled && ctx->Light.Light[1].Enabled )
+TCL_CHECK( tcl_lit2, ctx->Light.Enabled && ctx->Light.Light[2].Enabled )
+TCL_CHECK( tcl_lit3, ctx->Light.Enabled && ctx->Light.Light[3].Enabled )
+TCL_CHECK( tcl_lit4, ctx->Light.Enabled && ctx->Light.Light[4].Enabled )
+TCL_CHECK( tcl_lit5, ctx->Light.Enabled && ctx->Light.Light[5].Enabled )
+TCL_CHECK( tcl_lit6, ctx->Light.Enabled && ctx->Light.Light[6].Enabled )
+TCL_CHECK( tcl_lit7, ctx->Light.Enabled && ctx->Light.Light[7].Enabled )
+TCL_CHECK( tcl_ucp0, (ctx->Transform.ClipPlanesEnabled & 0x1) )
+TCL_CHECK( tcl_ucp1, (ctx->Transform.ClipPlanesEnabled & 0x2) )
+TCL_CHECK( tcl_ucp2, (ctx->Transform.ClipPlanesEnabled & 0x4) )
+TCL_CHECK( tcl_ucp3, (ctx->Transform.ClipPlanesEnabled & 0x8) )
+TCL_CHECK( tcl_ucp4, (ctx->Transform.ClipPlanesEnabled & 0x10) )
+TCL_CHECK( tcl_ucp5, (ctx->Transform.ClipPlanesEnabled & 0x20) )
+TCL_CHECK( tcl_eyespace_or_fog, ctx->_NeedEyeCoords || ctx->Fog.Enabled ) 
+
+CHECK( txr0, (ctx->Texture.Unit[0]._ReallyEnabled & TEXTURE_RECT_BIT))
+CHECK( txr1, (ctx->Texture.Unit[1]._ReallyEnabled & TEXTURE_RECT_BIT))
+
+
+
+/* Initialize the context's hardware state.
+ */
+void radeonInitState( radeonContextPtr rmesa )
+{
+   GLcontext *ctx = rmesa->glCtx;
+   GLuint color_fmt, depth_fmt, i;
+
+   switch ( rmesa->radeonScreen->cpp ) {
+   case 2:
+      color_fmt = RADEON_COLOR_FORMAT_RGB565;
+      break;
+   case 4:
+      color_fmt = RADEON_COLOR_FORMAT_ARGB8888;
+      break;
+   default:
+      fprintf( stderr, "Error: Unsupported pixel depth... exiting\n" );
+      exit( -1 );
+   }
+
+   rmesa->state.color.clear = 0x00000000;
+
+   switch ( ctx->Visual.depthBits ) {
+   case 16:
+      rmesa->state.depth.clear = 0x0000ffff;
+      rmesa->state.depth.scale = 1.0 / (GLfloat)0xffff;
+      depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;
+      rmesa->state.stencil.clear = 0x00000000;
+      break;
+   case 24:
+      rmesa->state.depth.clear = 0x00ffffff;
+      rmesa->state.depth.scale = 1.0 / (GLfloat)0xffffff;
+      depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;
+      rmesa->state.stencil.clear = 0xff000000;
+      break;
+   default:
+      fprintf( stderr, "Error: Unsupported depth %d... exiting\n",
+              ctx->Visual.depthBits );
+      exit( -1 );
+   }
+
+   /* Only have hw stencil when depth buffer is 24 bits deep */
+   rmesa->state.stencil.hwBuffer = ( ctx->Visual.stencilBits > 0 &&
+                                    ctx->Visual.depthBits == 24 );
+
+   rmesa->Fallback = 0;
+
+   if ( ctx->Visual.doubleBufferMode && rmesa->sarea->pfCurrentPage == 0 ) {
+      rmesa->state.color.drawOffset = rmesa->radeonScreen->backOffset;
+      rmesa->state.color.drawPitch  = rmesa->radeonScreen->backPitch;
+   } else {
+      rmesa->state.color.drawOffset = rmesa->radeonScreen->frontOffset;
+      rmesa->state.color.drawPitch  = rmesa->radeonScreen->frontPitch;
+   }
+   rmesa->state.pixel.readOffset = rmesa->state.color.drawOffset;
+   rmesa->state.pixel.readPitch  = rmesa->state.color.drawPitch;
+
+   /* Initialize lists:
+    */
+   make_empty_list(&(rmesa->hw.dirty));
+   make_empty_list(&(rmesa->hw.clean));
+
+
+#define ALLOC_STATE( ATOM, CHK, SZ, NM, FLAG )                         \
+   do {                                                                \
+      rmesa->hw.ATOM.cmd_size = SZ;                            \
+      rmesa->hw.ATOM.cmd = (int *)CALLOC(SZ * sizeof(int));    \
+      rmesa->hw.ATOM.lastcmd = (int *)CALLOC(SZ * sizeof(int));        \
+      rmesa->hw.ATOM.name = NM;                                        \
+      rmesa->hw.ATOM.is_tcl = FLAG;                                    \
+      rmesa->hw.ATOM.check = check_##CHK;                              \
+      insert_at_head(&(rmesa->hw.dirty), &(rmesa->hw.ATOM));   \
+   } while (0)
+      
+      
+   /* Allocate state buffers:
+    */
+   ALLOC_STATE( ctx, always, CTX_STATE_SIZE, "CTX/context", 0 );
+   ALLOC_STATE( lin, always, LIN_STATE_SIZE, "LIN/line", 0 );
+   ALLOC_STATE( msk, always, MSK_STATE_SIZE, "MSK/mask", 0 );
+   ALLOC_STATE( vpt, always, VPT_STATE_SIZE, "VPT/viewport", 0 );
+   ALLOC_STATE( set, always, SET_STATE_SIZE, "SET/setup", 0 );
+   ALLOC_STATE( msc, always, MSC_STATE_SIZE, "MSC/misc", 0 );
+   ALLOC_STATE( zbs, always, ZBS_STATE_SIZE, "ZBS/zbias", 0 );
+   ALLOC_STATE( tcl, always, TCL_STATE_SIZE, "TCL/tcl", 1 );
+   ALLOC_STATE( mtl, tcl_lighting, MTL_STATE_SIZE, "MTL/material", 1 );
+   ALLOC_STATE( grd, always, GRD_STATE_SIZE, "GRD/guard-band", 1 );
+   ALLOC_STATE( fog, fog, FOG_STATE_SIZE, "FOG/fog", 1 );
+   ALLOC_STATE( glt, tcl_lighting, GLT_STATE_SIZE, "GLT/light-global", 1 );
+   ALLOC_STATE( eye, tcl_lighting, EYE_STATE_SIZE, "EYE/eye-vector", 1 );
+   ALLOC_STATE( tex[0], tex0, TEX_STATE_SIZE, "TEX/tex-0", 0 );
+   ALLOC_STATE( tex[1], tex1, TEX_STATE_SIZE, "TEX/tex-1", 0 );
+   ALLOC_STATE( mat[0], tcl, MAT_STATE_SIZE, "MAT/modelproject", 1 );
+   ALLOC_STATE( mat[1], tcl_eyespace_or_fog, MAT_STATE_SIZE, "MAT/modelview", 1 );
+   ALLOC_STATE( mat[2], tcl_eyespace_or_lighting, MAT_STATE_SIZE, "MAT/it-modelview", 1 );
+   ALLOC_STATE( mat[3], tcl_tex0, MAT_STATE_SIZE, "MAT/texmat0", 1 );
+   ALLOC_STATE( mat[4], tcl_tex1, MAT_STATE_SIZE, "MAT/texmat1", 1 );
+   ALLOC_STATE( ucp[0], tcl_ucp0, UCP_STATE_SIZE, "UCP/userclip-0", 1 );
+   ALLOC_STATE( ucp[1], tcl_ucp1, UCP_STATE_SIZE, "UCP/userclip-1", 1 );
+   ALLOC_STATE( ucp[2], tcl_ucp2, UCP_STATE_SIZE, "UCP/userclip-2", 1 );
+   ALLOC_STATE( ucp[3], tcl_ucp3, UCP_STATE_SIZE, "UCP/userclip-3", 1 );
+   ALLOC_STATE( ucp[4], tcl_ucp4, UCP_STATE_SIZE, "UCP/userclip-4", 1 );
+   ALLOC_STATE( ucp[5], tcl_ucp5, UCP_STATE_SIZE, "UCP/userclip-5", 1 );
+   ALLOC_STATE( lit[0], tcl_lit0, LIT_STATE_SIZE, "LIT/light-0", 1 );
+   ALLOC_STATE( lit[1], tcl_lit1, LIT_STATE_SIZE, "LIT/light-1", 1 );
+   ALLOC_STATE( lit[2], tcl_lit2, LIT_STATE_SIZE, "LIT/light-2", 1 );
+   ALLOC_STATE( lit[3], tcl_lit3, LIT_STATE_SIZE, "LIT/light-3", 1 );
+   ALLOC_STATE( lit[4], tcl_lit4, LIT_STATE_SIZE, "LIT/light-4", 1 );
+   ALLOC_STATE( lit[5], tcl_lit5, LIT_STATE_SIZE, "LIT/light-5", 1 );
+   ALLOC_STATE( lit[6], tcl_lit6, LIT_STATE_SIZE, "LIT/light-6", 1 );
+   ALLOC_STATE( lit[7], tcl_lit7, LIT_STATE_SIZE, "LIT/light-7", 1 );
+   ALLOC_STATE( txr[0], txr0, TXR_STATE_SIZE, "TXR/txr-0", 0 );
+   ALLOC_STATE( txr[1], txr1, TXR_STATE_SIZE, "TXR/txr-1", 0 );
+
+
+   /* Fill in the packet headers:
+    */
+   rmesa->hw.ctx.cmd[CTX_CMD_0] = cmdpkt(RADEON_EMIT_PP_MISC);
+   rmesa->hw.ctx.cmd[CTX_CMD_1] = cmdpkt(RADEON_EMIT_PP_CNTL);
+   rmesa->hw.ctx.cmd[CTX_CMD_2] = cmdpkt(RADEON_EMIT_RB3D_COLORPITCH);
+   rmesa->hw.lin.cmd[LIN_CMD_0] = cmdpkt(RADEON_EMIT_RE_LINE_PATTERN);
+   rmesa->hw.lin.cmd[LIN_CMD_1] = cmdpkt(RADEON_EMIT_SE_LINE_WIDTH);
+   rmesa->hw.msk.cmd[MSK_CMD_0] = cmdpkt(RADEON_EMIT_RB3D_STENCILREFMASK);
+   rmesa->hw.vpt.cmd[VPT_CMD_0] = cmdpkt(RADEON_EMIT_SE_VPORT_XSCALE);
+   rmesa->hw.set.cmd[SET_CMD_0] = cmdpkt(RADEON_EMIT_SE_CNTL);
+   rmesa->hw.set.cmd[SET_CMD_1] = cmdpkt(RADEON_EMIT_SE_CNTL_STATUS);
+   rmesa->hw.msc.cmd[MSC_CMD_0] = cmdpkt(RADEON_EMIT_RE_MISC);
+   rmesa->hw.tex[0].cmd[TEX_CMD_0] = cmdpkt(RADEON_EMIT_PP_TXFILTER_0);
+   rmesa->hw.tex[0].cmd[TEX_CMD_1] = cmdpkt(RADEON_EMIT_PP_BORDER_COLOR_0);
+   rmesa->hw.tex[1].cmd[TEX_CMD_0] = cmdpkt(RADEON_EMIT_PP_TXFILTER_1);
+   rmesa->hw.tex[1].cmd[TEX_CMD_1] = cmdpkt(RADEON_EMIT_PP_BORDER_COLOR_1);
+   rmesa->hw.zbs.cmd[ZBS_CMD_0] = cmdpkt(RADEON_EMIT_SE_ZBIAS_FACTOR);
+   rmesa->hw.tcl.cmd[TCL_CMD_0] = cmdpkt(RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT);
+   rmesa->hw.mtl.cmd[MTL_CMD_0] = 
+      cmdpkt(RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED);
+   rmesa->hw.txr[0].cmd[TXR_CMD_0] = cmdpkt(RADEON_EMIT_PP_TEX_SIZE_0);
+   rmesa->hw.txr[1].cmd[TXR_CMD_0] = cmdpkt(RADEON_EMIT_PP_TEX_SIZE_1);
+   rmesa->hw.grd.cmd[GRD_CMD_0] = 
+      cmdscl( RADEON_SS_VERT_GUARD_CLIP_ADJ_ADDR, 1, 4 );
+   rmesa->hw.fog.cmd[FOG_CMD_0] = 
+      cmdvec( RADEON_VS_FOG_PARAM_ADDR, 1, 4 );
+   rmesa->hw.glt.cmd[GLT_CMD_0] = 
+      cmdvec( RADEON_VS_GLOBAL_AMBIENT_ADDR, 1, 4 );
+   rmesa->hw.eye.cmd[EYE_CMD_0] = 
+      cmdvec( RADEON_VS_EYE_VECTOR_ADDR, 1, 4 );
+
+   for (i = 0 ; i < 5; i++) {
+      rmesa->hw.mat[i].cmd[MAT_CMD_0] = 
+        cmdvec( RADEON_VS_MATRIX_0_ADDR + i*4, 1, 16);
+   }
+
+   for (i = 0 ; i < 8; i++) {
+      rmesa->hw.lit[i].cmd[LIT_CMD_0] = 
+        cmdvec( RADEON_VS_LIGHT_AMBIENT_ADDR + i, 8, 24 );
+      rmesa->hw.lit[i].cmd[LIT_CMD_1] = 
+        cmdscl( RADEON_SS_LIGHT_DCD_ADDR + i, 8, 6 );
+   }
+
+   for (i = 0 ; i < 6; i++) {
+      rmesa->hw.ucp[i].cmd[UCP_CMD_0] = 
+        cmdvec( RADEON_VS_UCP_ADDR + i, 1, 4 );
+   }
+
+   rmesa->last_ReallyEnabled = -1;
+
+   /* Initial Harware state:
+    */
+   rmesa->hw.ctx.cmd[CTX_PP_MISC] = (RADEON_ALPHA_TEST_PASS |
+                                    RADEON_CHROMA_FUNC_FAIL |
+                                    RADEON_CHROMA_KEY_NEAREST |
+                                    RADEON_SHADOW_FUNC_EQUAL |
+                                    RADEON_SHADOW_PASS_1 |
+                                    RADEON_RIGHT_HAND_CUBE_OGL);
+
+   rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = (RADEON_FOG_VERTEX |
+                                         RADEON_FOG_USE_DEPTH);
+
+   rmesa->hw.ctx.cmd[CTX_RE_SOLID_COLOR] = 0x00000000;
+
+   rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = (RADEON_COMB_FCN_ADD_CLAMP |
+                                           RADEON_SRC_BLEND_GL_ONE |
+                                           RADEON_DST_BLEND_GL_ZERO );
+
+   rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHOFFSET] =
+      rmesa->radeonScreen->depthOffset;
+
+   rmesa->hw.ctx.cmd[CTX_RB3D_DEPTHPITCH] = 
+      ((rmesa->radeonScreen->depthPitch &
+       RADEON_DEPTHPITCH_MASK) |
+       RADEON_DEPTH_ENDIAN_NO_SWAP);
+
+   rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] = (depth_fmt |
+                                              RADEON_Z_TEST_LESS |
+                                              RADEON_STENCIL_TEST_ALWAYS |
+                                              RADEON_STENCIL_FAIL_KEEP |
+                                              RADEON_STENCIL_ZPASS_KEEP |
+                                              RADEON_STENCIL_ZFAIL_KEEP |
+                                              RADEON_Z_WRITE_ENABLE);
+
+   rmesa->hw.ctx.cmd[CTX_PP_CNTL] = (RADEON_SCISSOR_ENABLE |
+                                    RADEON_ANTI_ALIAS_NONE);
+
+   rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = (RADEON_PLANE_MASK_ENABLE |
+                                      color_fmt |
+                                      (1<<15));
+
+   rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  RADEON_DITHER_ENABLE;
+
+   rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] = (rmesa->state.color.drawOffset &
+                                             RADEON_COLOROFFSET_MASK);
+
+   rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = ((rmesa->state.color.drawPitch &
+                                             RADEON_COLORPITCH_MASK) |
+                                            RADEON_COLOR_ENDIAN_NO_SWAP);
+
+   rmesa->hw.set.cmd[SET_SE_CNTL] = (RADEON_FFACE_CULL_CCW |
+                                    RADEON_BFACE_SOLID |
+                                    RADEON_FFACE_SOLID |
+/*                          RADEON_BADVTX_CULL_DISABLE | */
+                                    RADEON_FLAT_SHADE_VTX_LAST |
+                                    RADEON_DIFFUSE_SHADE_GOURAUD |
+                                    RADEON_ALPHA_SHADE_GOURAUD |
+                                    RADEON_SPECULAR_SHADE_GOURAUD |
+                                    RADEON_FOG_SHADE_GOURAUD |
+                                    RADEON_VPORT_XY_XFORM_ENABLE |
+                                    RADEON_VPORT_Z_XFORM_ENABLE |
+                                    RADEON_VTX_PIX_CENTER_OGL |
+                                    RADEON_ROUND_MODE_TRUNC |
+                                    RADEON_ROUND_PREC_8TH_PIX);
+
+   rmesa->hw.set.cmd[SET_SE_CNTL_STATUS] =
+#ifdef MESA_BIG_ENDIAN
+                                           RADEON_VC_32BIT_SWAP;
+#else
+                                           RADEON_VC_NO_SWAP;
+#endif
+
+   if (!(rmesa->radeonScreen->chipset & RADEON_CHIPSET_TCL)) {
+     rmesa->hw.set.cmd[SET_SE_CNTL_STATUS] |= RADEON_TCL_BYPASS;
+   }
+
+   rmesa->hw.set.cmd[SET_SE_COORDFMT] = (
+      RADEON_VTX_W0_IS_NOT_1_OVER_W0 |
+      RADEON_TEX1_W_ROUTING_USE_Q1);
+
+
+   rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] = ((1 << 16) | 0xffff);
+
+   rmesa->hw.lin.cmd[LIN_RE_LINE_STATE] = 
+      ((0 << RADEON_LINE_CURRENT_PTR_SHIFT) |
+       (1 << RADEON_LINE_CURRENT_COUNT_SHIFT));
+
+   rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] = (1 << 4);
+
+   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] = 
+      ((0x00 << RADEON_STENCIL_REF_SHIFT) |
+       (0xff << RADEON_STENCIL_MASK_SHIFT) |
+       (0xff << RADEON_STENCIL_WRITEMASK_SHIFT));
+
+   rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = RADEON_ROP_COPY;
+   rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = 0xffffffff;
+
+   rmesa->hw.msc.cmd[MSC_RE_MISC] = 
+      ((0 << RADEON_STIPPLE_X_OFFSET_SHIFT) |
+       (0 << RADEON_STIPPLE_Y_OFFSET_SHIFT) |
+       RADEON_STIPPLE_BIG_BIT_ORDER);
+
+   rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE]  = 0x00000000;
+   rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = 0x00000000;
+   rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE]  = 0x00000000;
+   rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = 0x00000000;
+   rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE]  = 0x00000000;
+   rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = 0x00000000;
+
+   for ( i = 0 ; i < ctx->Const.MaxTextureUnits ; i++ ) {
+      rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] = RADEON_BORDER_MODE_OGL;
+      rmesa->hw.tex[i].cmd[TEX_PP_TXFORMAT] = 
+         (RADEON_TXFORMAT_ENDIAN_NO_SWAP |
+          RADEON_TXFORMAT_PERSPECTIVE_ENABLE |
+          (i << 24) | /* This is one of RADEON_TXFORMAT_ST_ROUTE_STQ[012] */
+          (2 << RADEON_TXFORMAT_WIDTH_SHIFT) |
+          (2 << RADEON_TXFORMAT_HEIGHT_SHIFT));
+
+      /* FIXME: What is this magic value? */
+      rmesa->hw.tex[i].cmd[TEX_PP_TXOFFSET] = 0x2000 << (2 * i);
+
+      rmesa->hw.tex[i].cmd[TEX_PP_BORDER_COLOR] = 0;
+      rmesa->hw.tex[i].cmd[TEX_PP_TXCBLEND] =  
+         (RADEON_COLOR_ARG_A_ZERO |
+          RADEON_COLOR_ARG_B_ZERO |
+          RADEON_COLOR_ARG_C_CURRENT_COLOR |
+          RADEON_BLEND_CTL_ADD |
+          RADEON_SCALE_1X |
+          RADEON_CLAMP_TX);
+      rmesa->hw.tex[i].cmd[TEX_PP_TXABLEND] = 
+         (RADEON_ALPHA_ARG_A_ZERO |
+          RADEON_ALPHA_ARG_B_ZERO |
+          RADEON_ALPHA_ARG_C_CURRENT_ALPHA |
+          RADEON_BLEND_CTL_ADD |
+          RADEON_SCALE_1X |
+          RADEON_CLAMP_TX);
+      rmesa->hw.tex[i].cmd[TEX_PP_TFACTOR] = 0;
+   }
+
+   /* Can only add ST1 at the time of doing some multitex but can keep
+    * it after that.  Errors if DIFFUSE is missing.
+    */
+   rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] = 
+      (RADEON_TCL_VTX_Z0 |
+       RADEON_TCL_VTX_W0 |
+       RADEON_TCL_VTX_PK_DIFFUSE
+        );     /* need to keep this uptodate */
+                                                  
+   rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] =
+      ( RADEON_TCL_COMPUTE_XYZW        |
+       (RADEON_TCL_TEX_INPUT_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT) |
+       (RADEON_TCL_TEX_INPUT_TEX_1 << RADEON_TCL_TEX_1_OUTPUT_SHIFT) |
+       (RADEON_TCL_TEX_INPUT_TEX_2 << RADEON_TCL_TEX_2_OUTPUT_SHIFT));
+
+
+   /* XXX */
+   rmesa->hw.tcl.cmd[TCL_MATRIX_SELECT_0] = 
+      ((MODEL << RADEON_MODELVIEW_0_SHIFT) |
+       (MODEL_IT << RADEON_IT_MODELVIEW_0_SHIFT));
+
+   rmesa->hw.tcl.cmd[TCL_MATRIX_SELECT_1] = 
+      ((MODEL_PROJ << RADEON_MODELPROJECT_0_SHIFT) |
+       (TEXMAT_0 << RADEON_TEXMAT_0_SHIFT) |
+       (TEXMAT_1 << RADEON_TEXMAT_1_SHIFT));
+
+   rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = 
+      (RADEON_UCP_IN_CLIP_SPACE |
+       RADEON_CULL_FRONT_IS_CCW);
+
+   rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] = 0; 
+
+   rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = 
+      (RADEON_SPECULAR_LIGHTS |
+       RADEON_DIFFUSE_SPECULAR_COMBINE |
+       RADEON_LOCAL_LIGHT_VEC_GL |
+       (RADEON_LM_SOURCE_STATE_PREMULT << RADEON_EMISSIVE_SOURCE_SHIFT) |
+       (RADEON_LM_SOURCE_STATE_PREMULT << RADEON_AMBIENT_SOURCE_SHIFT) |
+       (RADEON_LM_SOURCE_STATE_PREMULT << RADEON_DIFFUSE_SOURCE_SHIFT) |
+       (RADEON_LM_SOURCE_STATE_PREMULT << RADEON_SPECULAR_SOURCE_SHIFT)); 
+
+   for (i = 0 ; i < 8; i++) {
+      struct gl_light *l = &ctx->Light.Light[i];
+      GLenum p = GL_LIGHT0 + i;
+      *(float *)&(rmesa->hw.lit[i].cmd[LIT_RANGE_CUTOFF]) = FLT_MAX;
+
+      ctx->Driver.Lightfv( ctx, p, GL_AMBIENT, l->Ambient );
+      ctx->Driver.Lightfv( ctx, p, GL_DIFFUSE, l->Diffuse );
+      ctx->Driver.Lightfv( ctx, p, GL_SPECULAR, l->Specular );
+      ctx->Driver.Lightfv( ctx, p, GL_POSITION, 0 );
+      ctx->Driver.Lightfv( ctx, p, GL_SPOT_DIRECTION, 0 );
+      ctx->Driver.Lightfv( ctx, p, GL_SPOT_EXPONENT, &l->SpotExponent );
+      ctx->Driver.Lightfv( ctx, p, GL_SPOT_CUTOFF, &l->SpotCutoff );
+      ctx->Driver.Lightfv( ctx, p, GL_CONSTANT_ATTENUATION,
+                          &l->ConstantAttenuation );
+      ctx->Driver.Lightfv( ctx, p, GL_LINEAR_ATTENUATION, 
+                          &l->LinearAttenuation );
+      ctx->Driver.Lightfv( ctx, p, GL_QUADRATIC_ATTENUATION, 
+                    &l->QuadraticAttenuation );
+   }
+
+   ctx->Driver.LightModelfv( ctx, GL_LIGHT_MODEL_AMBIENT, 
+                            ctx->Light.Model.Ambient );
+
+   TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
+
+   for (i = 0 ; i < 6; i++) {
+      ctx->Driver.ClipPlane( ctx, GL_CLIP_PLANE0 + i, NULL );
+   }
+
+   ctx->Driver.Fogfv( ctx, GL_FOG_MODE, 0 );
+   ctx->Driver.Fogfv( ctx, GL_FOG_DENSITY, &ctx->Fog.Density );
+   ctx->Driver.Fogfv( ctx, GL_FOG_START, &ctx->Fog.Start );
+   ctx->Driver.Fogfv( ctx, GL_FOG_END, &ctx->Fog.End );
+   ctx->Driver.Fogfv( ctx, GL_FOG_COLOR, ctx->Fog.Color );
+   ctx->Driver.Fogfv( ctx, GL_FOG_COORDINATE_SOURCE_EXT, 0 );
+   
+   rmesa->hw.grd.cmd[GRD_VERT_GUARD_CLIP_ADJ] = IEEE_ONE;
+   rmesa->hw.grd.cmd[GRD_VERT_GUARD_DISCARD_ADJ] = IEEE_ONE;
+   rmesa->hw.grd.cmd[GRD_HORZ_GUARD_CLIP_ADJ] = IEEE_ONE;
+   rmesa->hw.grd.cmd[GRD_HORZ_GUARD_DISCARD_ADJ] = IEEE_ONE;
+
+   rmesa->hw.eye.cmd[EYE_X] = 0;
+   rmesa->hw.eye.cmd[EYE_Y] = 0;
+   rmesa->hw.eye.cmd[EYE_Z] = IEEE_ONE;
+   rmesa->hw.eye.cmd[EYE_RESCALE_FACTOR] = IEEE_ONE;
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_subset.h b/src/mesa/drivers/dri/radeon/radeon_subset.h
new file mode 100644 (file)
index 0000000..1b6e7bd
--- /dev/null
@@ -0,0 +1,75 @@
+/**
+ * \file radeon_subset.h
+ * \brief Radeon subset driver declarations.
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+/*
+ * Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+ *                      Tungsten Grahpics Inc., Austin, Texas.
+ * 
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * ATI, TUNGSTEN GRAHPICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* $XFree86$ */
+
+#ifndef __RADEON_SUBSET_H__
+#define __RADEON_SUBSET_H__
+
+extern void radeonPointsBitmap( GLsizei width, GLsizei height,
+                               GLfloat xorig, GLfloat yorig,
+                               GLfloat xmove, GLfloat ymove,
+                               const GLubyte *bitmap );
+
+extern void radeonReadPixels( GLint x, GLint y,
+                             GLsizei width, GLsizei height,
+                             GLenum format, GLenum type,
+                             GLvoid *pixels );
+
+extern void radeon_select_Install( GLcontext *ctx );
+
+extern void radeonInitSelect( GLcontext *ctx );
+
+extern void radeonVtxfmtDestroy( GLcontext *ctx );
+
+extern void radeonVtxfmtMakeCurrent( GLcontext *ctx );
+
+extern void radeonVtxfmtUnbindContext( GLcontext *ctx );
+
+extern void radeonVtxfmtInit( GLcontext *ctx );
+
+extern void radeonTclFallback( GLcontext *ctx, GLuint bit, GLboolean mode );
+
+extern void radeonVtxfmtInvalidate( GLcontext *ctx );
+
+extern void radeonSubsetVtxEnableTCL( radeonContextPtr rmesa, GLboolean flag );
+
+extern void radeonUpdateTextureState( GLcontext *ctx );
+
+extern void radeonInitTextureFuncs( GLcontext *ctx );
+
+extern void radeonAgeTextures( radeonContextPtr rmesa, int heap );
+
+extern void radeonDestroyTexObj( radeonContextPtr rmesa, radeonTexObjPtr t );
+
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_subset_bitmap.c b/src/mesa/drivers/dri/radeon/radeon_subset_bitmap.c
new file mode 100644 (file)
index 0000000..cb4a514
--- /dev/null
@@ -0,0 +1,197 @@
+/**
+ * \file radeon_subset_bitmap.c
+ * \brief Bitmap drawing.
+ * 
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+/*
+ * Copyright 2003       ATI Technologies Inc., Ontario, Canada, and
+ *                      Tungsten Graphics Inc., Cedar Park, Texas.
+ * 
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ */
+
+/* $XFree86$ */
+
+#include "glheader.h"
+#include "mtypes.h"
+#include "colormac.h"
+#include "context.h"
+#include "enums.h"
+#include "imports.h"
+#include "image.h"
+/*#include "mmath.h"*/
+#include "macros.h"
+#include "state.h"
+
+#include "radeon_context.h"
+#include "radeon_ioctl.h"
+#include "radeon_state.h"
+#include "radeon_subset.h"
+
+/**
+ * \brief Cope with depth operations by drawing individual pixels as points
+ *
+ * \param xorig x coordinate of the bitmap corner.
+ * \param yorig y coordinate of the bitmap corner.
+ * \param xmove increment to the final x coordinate.
+ * \param ymove increment to the final y coordinate.
+ * \param width bitmap width.
+ * \param height bitmap height.
+ * \param bitmap bitmap pointer.
+ * 
+ * Clips the bitmap coordinates and adjusts for windows coordinates. Draws the
+ * bitmap with glPoints(), turning off TCL and hardware viewport transformation
+ * to emit raw pixel coordinates. Finally fires any outstanding vertices and
+ * restores TCL, viewport, texture and color states.
+ */
+void
+radeonPointsBitmap(  GLsizei width, GLsizei height,
+                    GLfloat xorig, GLfloat yorig, 
+                    GLfloat xmove, GLfloat ymove,
+                    const GLubyte *bitmap )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLsizei bmwidth = width, bmheight = height;   
+   GLint px, py;
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat saved_color[4], saved_tex0[2];
+   GLint row, col;
+   GLuint orig_se_cntl;
+   GLuint w, h;
+   const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
+
+   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+   if (width < 0 || height < 0) {
+      _mesa_error( ctx, GL_INVALID_VALUE, "glBitmap(width or height < 0)" );
+      return;
+   }
+
+   if (!ctx->Current.RasterPosValid)
+      return;
+
+   if (ctx->NewState) 
+      _mesa_update_state(ctx);
+
+
+   if (ctx->_RotateMode) {
+      width = bmheight; height = bmwidth;
+
+      px = IFLOOR(ctx->Current.RasterPos[0] + yorig);
+      py = IFLOOR(ctx->Current.RasterPos[1] + xorig);
+
+      ctx->Current.RasterPos[0] += ymove;
+      ctx->Current.RasterPos[1] += xmove;
+   }
+   else {
+      px = IFLOOR(ctx->Current.RasterPos[0] - xorig);
+      py = IFLOOR(ctx->Current.RasterPos[1] - yorig);
+
+      ctx->Current.RasterPos[0] += xmove;
+      ctx->Current.RasterPos[1] += ymove;
+   }
+
+
+
+   /* Turn off tcl and the hw viewport transformation so that we can
+    * emit raw pixel coordinates:
+    */
+   radeonSubsetVtxEnableTCL( rmesa, GL_FALSE );
+   RADEON_STATECHANGE( rmesa, set );
+   orig_se_cntl = rmesa->hw.set.cmd[SET_SE_CNTL];
+   rmesa->hw.set.cmd[SET_SE_CNTL] &= ~(RADEON_VPORT_XY_XFORM_ENABLE |
+                                      RADEON_VPORT_Z_XFORM_ENABLE);
+
+
+   /* Adjust for window coordinates, flip y values:
+    */
+   h = rmesa->dri.drawable->h + rmesa->dri.drawable->y - 1;
+   w = rmesa->dri.drawable->w;
+   px += rmesa->dri.drawable->x;
+
+   /* Save current color, texcoord to restore later:
+    */
+   COPY_4V( saved_color, ctx->Current.Attrib[VERT_ATTRIB_COLOR0] );
+   COPY_2V( saved_tex0, ctx->Current.Attrib[VERT_ATTRIB_TEX0] );
+
+   /* Just use the GL entrypoints to talk to radeon_subset_vtx.c:
+    */
+   glBegin( GL_POINTS );
+   glColor4fv( ctx->Current.RasterColor );
+   glTexCoord2fv( ctx->Current.RasterTexCoords[0] );
+
+
+   if (ctx->_RotateMode) {
+      for (col=0; col<width; col++) {
+        const GLubyte *src = (const GLubyte *) 
+           _mesa_image_address( unpack, bitmap, height, width, 
+                                GL_COLOR_INDEX, GL_BITMAP, 0, col, 0 );
+           
+        /* Msb first */
+        GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
+        for (row=0; row<height; row++) {
+           if (*src & mask) {
+              glVertex2f( px-col, h - (py + row) );
+           }
+           src += mask & 1;
+           mask = ((mask << 7) & 0xff) | (mask >> 1);
+        }
+        /* get ready for next row */
+        if (mask != 128)
+           src++;
+      }
+   }
+   else {
+      for (row=0; row<height; row++) {
+        const GLubyte *src = (const GLubyte *) 
+           _mesa_image_address( unpack, bitmap, width, height, 
+                                GL_COLOR_INDEX, GL_BITMAP, 0, row, 0 );
+           
+        /* Msb first */
+        GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
+        for (col=0; col<width; col++) {
+           if (*src & mask) {
+              glVertex2f( px+col, h - (py + row) );
+           }
+           src += mask & 1;
+           mask = ((mask << 7) & 0xff) | (mask >> 1);
+        }
+        /* get ready for next row */
+        if (mask != 128)
+           src++;
+      }
+   }
+
+   glEnd();
+   glColor4fv( saved_color );
+   glTexCoord2fv( saved_tex0 );
+
+   /* Fire outstanding vertices, restore state
+    */
+   RADEON_STATECHANGE( rmesa, set );
+   rmesa->hw.set.cmd[SET_SE_CNTL] = orig_se_cntl;
+   radeonSubsetVtxEnableTCL( rmesa, GL_TRUE );
+}
+
diff --git a/src/mesa/drivers/dri/radeon/radeon_subset_readpix.c b/src/mesa/drivers/dri/radeon/radeon_subset_readpix.c
new file mode 100644 (file)
index 0000000..f72d3b8
--- /dev/null
@@ -0,0 +1,246 @@
+/**
+ * \file radeon_subset_readpix.c
+ * \brief Pixel reading.
+ * 
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ * \author Brian Paul <brian@tungstengraphics.com>
+ */
+
+/*
+ * Copyright 2003       ATI Technologies Inc., Ontario, Canada, and
+ *                      Tungsten Graphics Inc., Cedar Park, Texas.
+ * 
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* $XFree86$ */
+
+#include "glheader.h"
+#include "mtypes.h"
+#include "colormac.h"
+#include "context.h"
+#include "enums.h"
+#include "imports.h"
+/*#include "mmath.h" */
+#include "macros.h"
+#include "state.h"
+
+#include "radeon_context.h"
+#include "radeon_ioctl.h"
+#include "radeon_state.h"
+#include "radeon_subset.h"
+
+/**
+ * \brief Read pixel in RGBA format on a Radeon 16bpp frame buffer.
+ *
+ * \param rgba destination pointer.
+ * \param ptr pointer to the pixel in the frame buffer.
+ */
+#define READ_RGBA_16( rgba, ptr )              \
+do {                                           \
+    GLushort p = *(GLushort *)ptr;             \
+    rgba[0] = ((p >> 8) & 0xf8) * 255 / 0xf8;  \
+    rgba[1] = ((p >> 3) & 0xfc) * 255 / 0xfc;  \
+    rgba[2] = ((p << 3) & 0xf8) * 255 / 0xf8;  \
+    rgba[3] = 0xff;                            \
+} while (0)
+
+/**
+ * \brief Read pixel in RGBA format on a Radeon 32bpp frame buffer.
+ *
+ * \param rgba destination pointer.
+ * \param ptr pointer to the pixel in the frame buffer.
+ */
+#define READ_RGBA_32( rgba, ptr )              \
+do {                                           \
+   GLuint p = *(GLuint *)ptr;                  \
+   rgba[0] = (p >> 16) & 0xff;                 \
+   rgba[1] = (p >>  8) & 0xff;                 \
+   rgba[2] = (p >>  0) & 0xff;                 \
+   rgba[3] = (p >> 24) & 0xff;                 \
+} while (0)
+
+/**
+ * \brief Read a span in RGBA format.
+ * 
+ * \param ctx GL context.
+ * \param n number of pixels in the span.
+ * \param x x position of the span start.
+ * \param y y position of the span.
+ * \param rgba destination buffer.
+ *
+ * Calculates the pointer to the span start in the frame buffer and uses either
+ * #READ_RGBA_16 or #READ_RGBA_32 macros to copy the values.
+ */
+static void ReadRGBASpan( const GLcontext *ctx,
+                              GLuint n, GLint x, GLint y,
+                              GLubyte rgba[][4])
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   radeonScreenPtr radeonScreen = rmesa->radeonScreen;
+   __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
+   GLuint cpp = radeonScreen->cpp;
+   GLuint pitch = radeonScreen->frontPitch * cpp;
+   GLint i;
+
+   if (ctx->_RotateMode) {
+      char *ptr = (char *)(rmesa->dri.screen->pFB +
+                          rmesa->state.pixel.readOffset +
+                          ((dPriv->x + (dPriv->w - y - 1)) * cpp) +
+                          ((dPriv->y + (dPriv->h - x - 1)) * pitch));
+
+      if (cpp == 4)
+        for (i = 0; i < n; i++, ptr -= pitch)
+           READ_RGBA_32( rgba[i], ptr );
+      else
+        for (i = 0; i < n; i++, ptr -= pitch)
+           READ_RGBA_16( rgba[i], ptr );
+   }
+   else {
+      char *ptr = (char *)(rmesa->dri.screen->pFB +
+                          rmesa->state.pixel.readOffset +
+                          ((dPriv->x + x) * cpp) +
+                          ((dPriv->y + (dPriv->h - y - 1)) * pitch));
+
+      if (cpp == 4)
+        for (i = 0; i < n; i++, ptr += cpp)
+           READ_RGBA_32( rgba[i], ptr );
+      else
+        for (i = 0; i < n; i++, ptr += cpp)
+           READ_RGBA_16( rgba[i], ptr );
+   }
+}
+
+
+/**
+ * \brief Optimized glReadPixels().
+ *
+ * To be used with particular pixel formats GL_UNSIGNED_BYTE and GL_RGBA, when pixel
+ * scaling, biasing and mapping are disabled.
+ *
+ * \param x x start position of the reading rectangle.
+ * \param y y start position of the reading rectangle.
+ * \param width width of the reading rectangle.
+ * \param height height of the reading rectangle.
+ * \param format pixel format. Must be GL_RGBA.
+ * \param type pixel type. Must be GL_UNSIGNED_BYTE.
+ * \param pixels pixel data.
+ * 
+ * After asserting the above conditions, compensates for clipping and calls
+ * ReadRGBASpan() to read each row.
+ */
+void radeonReadPixels( GLint x, GLint y,
+                      GLsizei width, GLsizei height,
+                      GLenum format, GLenum type,
+                      GLvoid *pixels )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLint srcX = x;
+   GLint srcY = y;
+   GLint readWidth = width;           /* actual width read */
+   GLint readHeight = height;         /* actual height read */
+   const struct gl_pixelstore_attrib *packing = &ctx->Pack;
+   GLint skipRows = packing->SkipRows;
+   GLint skipPixels = packing->SkipPixels;
+   GLint rowLength;
+   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
+
+   {
+      GLint tmp, tmps;
+      tmp = x; x = y; y = tmp;
+      tmps = width; width = height; height = tmps;
+   }
+
+   if (width < 0 || height < 0) {
+      _mesa_error( ctx, GL_INVALID_VALUE,
+                   "glReadPixels(width=%d height=%d)", width, height );
+      return;
+   }
+
+   if (!pixels) {
+      _mesa_error( ctx, GL_INVALID_VALUE, "glReadPixels(pixels)" );
+      return;
+   }
+
+   if (ctx->NewState)
+      _mesa_update_state(ctx);
+
+
+   /* can't do scale, bias, mapping, etc */
+   assert(!ctx->_ImageTransferState);
+
+   /* can't do fancy pixel packing */
+   assert (packing->Alignment == 1 &&
+          !packing->SwapBytes &&
+          !packing->LsbFirst);
+
+
+   if (packing->RowLength > 0)
+      rowLength = packing->RowLength;
+   else
+      rowLength = width;
+
+   /* horizontal clipping */
+   if (srcX < 0) {
+      skipPixels -= srcX;
+      readWidth += srcX;
+      srcX = 0;
+   }
+   if (srcX + readWidth > (GLint) ctx->ReadBuffer->Width)
+      readWidth -= (srcX + readWidth - (GLint) ctx->ReadBuffer->Width);
+   if (readWidth <= 0)
+      return;
+
+   /* vertical clipping */
+   if (srcY < 0) {
+      skipRows -= srcY;
+      readHeight += srcY;
+      srcY = 0;
+   }
+   if (srcY + readHeight > (GLint) ctx->ReadBuffer->Height)
+      readHeight -= (srcY + readHeight - (GLint) ctx->ReadBuffer->Height);
+   if (readHeight <= 0)
+      return;
+
+   /*
+    * Ready to read!
+    * The window region at (destX, destY) of size (readWidth, readHeight)
+    * will be read back.
+    * We'll write pixel data to buffer pointed to by "pixels" but we'll
+    * skip "skipRows" rows and skip "skipPixels" pixels/row.
+    */
+   if (format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
+      GLchan *dest = (GLchan *) pixels 
+        + (skipRows * rowLength + skipPixels) * 4;
+      GLint row;
+
+      for (row=0; row<readHeight; row++) {
+        ReadRGBASpan(ctx, readWidth, srcX, srcY, (GLchan (*)[4]) dest);
+        dest += rowLength * 4;
+        srcY++;
+      }
+   }
+   else {
+      /* can't do this format/type combination */
+      assert(0);
+   }
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_subset_select.c b/src/mesa/drivers/dri/radeon/radeon_subset_select.c
new file mode 100644 (file)
index 0000000..bd5003f
--- /dev/null
@@ -0,0 +1,998 @@
+/**
+ * \file radeon_subset_select.c
+ * \brief Selection.
+ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  4.1
+ *
+ * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* $Id: radeon_subset_select.c,v 1.2 2003/08/22 20:11:45 brianp Exp $ */
+
+
+#include "glheader.h"
+#include "imports.h"
+#include "context.h"
+/*#include "mmath.h"*/
+#include "mtypes.h"
+#include "enums.h"
+#include "glapi.h"
+#include "feedback.h"
+
+#include "radeon_context.h"
+#include "radeon_subset.h"
+
+/**
+ * \brief Vertex.
+ */
+typedef struct {
+   struct { GLfloat x, y, z, w; } pos;      /**< \brief position */
+   struct { GLfloat x, y, z, w; } eyePos;   /**< \brief position, eye coordinates */
+   struct { GLfloat x, y, z, w; } clipPos;  /**< \brief clipped coordinates */
+   struct { GLfloat x, y, z, w; } winPos;   /**< \brief position, windows coordinates */
+   struct { GLfloat s, t; } texCoord;       /**< \brief texture coordinates */
+   struct { GLfloat r, g, b, a; } color;    /**< \brief color */
+} vertex;
+
+
+/**
+ * \brief Vertex buffer.
+ */
+static struct select_vb_t {
+   GLuint    vCount;           /**< \brief vertex count */
+   vertex  vBuffer[4];         /**< \brief vertex buffer */
+   GLboolean lineReset;
+   GLboolean partialLineLoop;  /**< \brief whether we are in a middle of a line loop */
+} vb;
+
+
+
+
+/**********************************************************************/
+/** \name        Vertex Transformation and Clipping                   */
+/**********************************************************************/
+/*@{*/
+
+/**
+ * \brief Transform a point (column vector) by a matrix:  Q = M * P.
+ *
+ * \param Q destination point.
+ * \param P source point.
+ * \param M transformation matrix.
+ */
+#define TRANSFORM_POINT( Q, M, P )                             \
+   Q.x = M[0] * P.x + M[4] * P.y + M[8] *  P.z + M[12] * P.w;  \
+   Q.y = M[1] * P.x + M[5] * P.y + M[9] *  P.z + M[13] * P.w;  \
+   Q.z = M[2] * P.x + M[6] * P.y + M[10] * P.z + M[14] * P.w;  \
+   Q.w = M[3] * P.x + M[7] * P.y + M[11] * P.z + M[15] * P.w;
+
+/**
+ * \brief Clip coord to window coord mapping.
+ *
+ * \param Q destination point.
+ * \param P source point.
+ * \param VP view port.
+ */
+#define MAP_POINT( Q, P, VP )                                      \
+   Q.x = (GLfloat) (((P.x / P.w) + 1.0) * VP.Width / 2.0 + VP.X);  \
+   Q.y = (GLfloat) (((P.y / P.w) + 1.0) * VP.Height / 2.0 + VP.Y);  \
+   Q.z = (GLfloat) (((P.z / P.w) + 1.0) * (VP.Far - VP.Near) / 2.0 + VP.Near);\
+   Q.w = (GLfloat) P.w;
+
+
+/**
+ * \brief Linear interpolation:  (1 - T) * A + T * B.
+ *
+ * \param T interpolation factor.
+ * \param A first value.
+ * \param B second value.
+ * \result interpolated value.
+ */
+#define INTERPOLATE(T, A, B)   ((A) + ((B) - (A)) * (T))
+
+
+
+/**
+ * \brief Interpolate vertex position, color, texcoords, etc.
+ *
+ * \param t interpolation factor.
+ * \param v0 first vertex.
+ * \param v1 second vertex.
+ * \param vOut output vertex.
+ * 
+ * Uses the #INTERPOLATE macro for all the interpolation of all elements.
+ */
+static void
+interpolate_vertex(GLfloat t, const vertex *v0, const vertex *v1, 
+                  vertex *vOut)
+{
+   vOut->eyePos.x = INTERPOLATE(t, v0->eyePos.x, v1->eyePos.x);
+   vOut->eyePos.y = INTERPOLATE(t, v0->eyePos.y, v1->eyePos.y);
+   vOut->eyePos.z = INTERPOLATE(t, v0->eyePos.z, v1->eyePos.z);
+   vOut->eyePos.w = INTERPOLATE(t, v0->eyePos.w, v1->eyePos.w);
+
+   vOut->clipPos.x = INTERPOLATE(t, v0->clipPos.x, v1->clipPos.x);
+   vOut->clipPos.y = INTERPOLATE(t, v0->clipPos.y, v1->clipPos.y);
+   vOut->clipPos.z = INTERPOLATE(t, v0->clipPos.z, v1->clipPos.z);
+   vOut->clipPos.w = INTERPOLATE(t, v0->clipPos.w, v1->clipPos.w);
+
+   vOut->color.r = INTERPOLATE(t, v0->color.r, v1->color.r);
+   vOut->color.g = INTERPOLATE(t, v0->color.g, v1->color.g);
+   vOut->color.b = INTERPOLATE(t, v0->color.b, v1->color.b);
+   vOut->color.a = INTERPOLATE(t, v0->color.a, v1->color.a);
+
+   vOut->texCoord.s = INTERPOLATE(t, v0->texCoord.s, v1->texCoord.s);
+   vOut->texCoord.t = INTERPOLATE(t, v0->texCoord.t, v1->texCoord.t);
+}
+
+
+
+
+/*
+ * Clip bit codes 
+ */
+#define CLIP_LEFT    1
+#define CLIP_RIGHT   2
+#define CLIP_BOTTOM  4
+#define CLIP_TOP     8
+#define CLIP_NEAR   16
+#define CLIP_FAR    32
+
+
+/**
+ * \brief Apply view volume clip testing to a point.
+ *
+ * \param v point to test.
+ * \return zero if visible, or the clip code mask, i.e., binary OR of a
+ * combination of the #CLIP_LEFT, #CLIP_RIGHT, #CLIP_BOTTOM, #CLIP_TOP, #CLIP_NEAR,
+ * #CLIP_FAR clip bit codes.
+ */
+static GLuint
+clip_point(const vertex *v)
+{
+   GLuint mask = 0;
+   if (v->clipPos.x > v->clipPos.w) mask |= CLIP_RIGHT;
+   if (v->clipPos.x < -v->clipPos.w) mask |= CLIP_LEFT;
+   if (v->clipPos.y > v->clipPos.w) mask |= CLIP_TOP;
+   if (v->clipPos.y < -v->clipPos.w) mask |= CLIP_BOTTOM;
+   if (v->clipPos.z > v->clipPos.w) mask |= CLIP_FAR;
+   if (v->clipPos.z < -v->clipPos.w) mask |= CLIP_NEAR;
+   return mask;
+}
+
+
+/**
+ * \def GENERAL_CLIP
+ * \brief Clipping utility macro.
+ * 
+ * We use 6 instances of this code in each of the clip_line() and
+ * clip_polygon() to clip against the 6 planes.  For each plane, we define the
+ * #OUTSIDE and #COMPUTE_INTERSECTION macros appropriately.
+ */
+
+
+/**
+ * \brief Apply clipping to a line segment.
+ *
+ * \param v0in input start vertex
+ * \param v1in input end vertesx
+ * \param v0new output start vertex
+ * \param v1new output end vertex
+ *
+ * \return GL_TRUE if the line segment is visible, or GL_FALSE if it is totally
+ * clipped.
+ *
+ * \sa #GENERAL_CLIP.
+ */
+static GLboolean
+clip_line(const vertex *v0in, const vertex *v1in,
+         vertex *v0new, vertex *v1new)
+{
+   vertex v0, v1, vNew;
+   GLfloat dx, dy, dz, dw, t;
+   GLuint code0, code1;
+
+   code0 = clip_point(v0in);
+   code1 = clip_point(v1in);
+   if (code0 & code1)
+      return GL_FALSE;  /* totally clipped */
+   
+   *v0new = *v0in;
+   *v1new = *v1in;
+   if (code0 == 0 && code1 == 0)
+      return GL_TRUE;   /* no clipping needed */
+   
+   v0 = *v0in;
+   v1 = *v1in;
+
+
+#define GENERAL_CLIP                                                    \
+   if (OUTSIDE(v0)) {                                                   \
+      if (OUTSIDE(v1)) {                                                \
+         /* both verts are outside ==> return 0 */                      \
+         return 0;                                                      \
+      }                                                                 \
+      else {                                                            \
+         /* v0 is outside, v1 is inside ==> clip */                     \
+         COMPUTE_INTERSECTION( v1, v0, vNew )                           \
+         interpolate_vertex(t, &v1, &v0, &vNew);                        \
+         v0 = vNew;                                                     \
+      }                                                                 \
+   }                                                                    \
+   else {                                                               \
+      if (OUTSIDE(v1)) {                                                \
+         /* v0 is inside, v1 is outside ==> clip */                     \
+         COMPUTE_INTERSECTION( v0, v1, vNew )                           \
+         interpolate_vertex(t, &v0, &v1, &vNew);                        \
+         v1 = vNew;                                                     \
+      }                                                                 \
+      /* else both verts are inside ==> do nothing */                   \
+   }
+
+   /* Clip against +X side */
+#define OUTSIDE(V)      (V.clipPos.x > V.clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW )                         \
+        dx = OUT.clipPos.x - IN.clipPos.x;                           \
+        dw = OUT.clipPos.w - IN.clipPos.w;                           \
+        t = (IN.clipPos.x - IN.clipPos.w) / (dw-dx);
+   GENERAL_CLIP
+#undef OUTSIDE
+#undef COMPUTE_INTERSECTION
+
+   /* Clip against -X side */
+#define OUTSIDE(V)      (V.clipPos.x < -(V.clipPos.w))
+#define COMPUTE_INTERSECTION( IN, OUT, NEW )                         \
+        dx = OUT.clipPos.x - IN.clipPos.x;                           \
+        dw = OUT.clipPos.w - IN.clipPos.w;                           \
+        t = -(IN.clipPos.x + IN.clipPos.w) / (dw+dx);
+   GENERAL_CLIP
+#undef OUTSIDE
+#undef COMPUTE_INTERSECTION
+
+   /* Clip against +Y side */
+#define OUTSIDE(V)      (V.clipPos.y > V.clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW )                         \
+        dy = OUT.clipPos.y - IN.clipPos.y;                           \
+        dw = OUT.clipPos.w - IN.clipPos.w;                           \
+        t = (IN.clipPos.y - IN.clipPos.w) / (dw-dy);
+   GENERAL_CLIP
+#undef OUTSIDE
+#undef COMPUTE_INTERSECTION
+
+   /* Clip against -Y side */
+#define OUTSIDE(V)      (V.clipPos.y < -(V.clipPos.w))
+#define COMPUTE_INTERSECTION( IN, OUT, NEW )                         \
+        dy = OUT.clipPos.y - IN.clipPos.y;                           \
+        dw = OUT.clipPos.w - IN.clipPos.w;                           \
+        t = -(IN.clipPos.y + IN.clipPos.w) / (dw+dy);
+   GENERAL_CLIP
+#undef OUTSIDE
+#undef COMPUTE_INTERSECTION
+
+   /* Clip against +Z side */
+#define OUTSIDE(V)      (V.clipPos.z > V.clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW )                         \
+        dz = OUT.clipPos.z - IN.clipPos.z;                           \
+        dw = OUT.clipPos.w - IN.clipPos.w;                           \
+        t = (IN.clipPos.z - IN.clipPos.w) / (dw-dz);
+   GENERAL_CLIP
+#undef OUTSIDE
+#undef COMPUTE_INTERSECTION
+
+   /* Clip against -Z side */
+#define OUTSIDE(V)      (V.clipPos.z < -(V.clipPos.w))
+#define COMPUTE_INTERSECTION( IN, OUT, NEW )                         \
+        dz = OUT.clipPos.z - IN.clipPos.z;                           \
+        dw = OUT.clipPos.w - IN.clipPos.w;                           \
+        t = -(IN.clipPos.z + IN.clipPos.w) / (dw+dz);
+   GENERAL_CLIP
+#undef OUTSIDE
+#undef COMPUTE_INTERSECTION
+
+#undef GENERAL_CLIP
+
+   *v0new = v0;
+   *v1new = v1;
+   return GL_TRUE;
+}
+
+
+
+/**
+ * \brief Apply clipping to a polygon.
+ *
+ * \param vIn array of input vertices.
+ * \param inCount number of input vertices
+ * \param vOut array of output vertices.
+ *
+ * \return number of vertices in \p vOut.
+ *
+ * \sa #GENERAL_CLIP.
+ */
+static GLuint
+clip_polygon(const vertex *vIn, unsigned int inCount, vertex *vOut)
+{
+   vertex inlist[20], outlist[20];
+   GLfloat dx, dy, dz, dw, t;
+   GLuint incount, outcount, previ, curri, result;
+   const vertex *currVert, *prevVert;
+   vertex *newVert;
+
+
+#define GENERAL_CLIP(INCOUNT, INLIST, OUTCOUNT, OUTLIST)                \
+   if (INCOUNT < 3)                                                     \
+      return GL_FALSE;                                                  \
+   previ = INCOUNT - 1;         /* let previous = last vertex */        \
+   prevVert = INLIST + previ;                                           \
+   OUTCOUNT = 0;                                                        \
+   for (curri = 0; curri < INCOUNT; curri++) {                          \
+      currVert = INLIST + curri;                                        \
+      if (INSIDE(currVert)) {                                           \
+         if (INSIDE(prevVert)) {                                        \
+            /* both verts are inside ==> copy current to outlist */     \
+            OUTLIST[OUTCOUNT] = *currVert;                              \
+            OUTCOUNT++;                                                 \
+         }                                                              \
+         else {                                                         \
+            newVert = OUTLIST + OUTCOUNT;                               \
+            /* current is inside and previous is outside ==> clip */    \
+            COMPUTE_INTERSECTION( currVert, prevVert, newVert )         \
+            OUTCOUNT++;                                                 \
+            /* Output current */                                        \
+            OUTLIST[OUTCOUNT] = *currVert;                              \
+            OUTCOUNT++;                                                 \
+         }                                                              \
+      }                                                                 \
+      else {                                                            \
+         if (INSIDE(prevVert)) {                                        \
+            newVert = OUTLIST + OUTCOUNT;                               \
+            /* current is outside and previous is inside ==> clip */    \
+            COMPUTE_INTERSECTION( prevVert, currVert, newVert );        \
+            OUTLIST[OUTCOUNT] = *newVert;                               \
+            OUTCOUNT++;                                                 \
+         }                                                              \
+         /* else both verts are outside ==> do nothing */               \
+      }                                                                 \
+      /* let previous = current */                                      \
+      previ = curri;                                                    \
+      prevVert = currVert;                                              \
+   }
+
+/*
+ * Clip against +X
+ */
+#define INSIDE(V)       (V->clipPos.x <= V->clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW )              \
+        dx = OUT->clipPos.x - IN->clipPos.x;              \
+        dw = OUT->clipPos.w - IN->clipPos.w;              \
+        t = (IN->clipPos.x - IN->clipPos.w) / (dw - dx);  \
+        interpolate_vertex(t, IN, OUT, NEW );
+
+   GENERAL_CLIP(inCount, vIn, outcount, outlist)
+
+#undef INSIDE
+#undef COMPUTE_INTERSECTION
+
+/*
+ * Clip against -X
+ */
+#define INSIDE(V)       (V->clipPos.x >= -V->clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW )               \
+        dx = OUT->clipPos.x - IN->clipPos.x;               \
+        dw = OUT->clipPos.w - IN->clipPos.w;               \
+        t = -(IN->clipPos.x + IN->clipPos.w) / (dw + dx);  \
+        interpolate_vertex(t, IN, OUT, NEW );
+
+   GENERAL_CLIP(outcount, outlist, incount, inlist)
+
+#undef INSIDE
+#undef COMPUTE_INTERSECTION
+
+/*
+ * Clip against +Y
+ */
+#define INSIDE(V)       (V->clipPos.y <= V->clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW )              \
+        dy = OUT->clipPos.y - IN->clipPos.y;              \
+        dw = OUT->clipPos.w - IN->clipPos.w;              \
+        t = (IN->clipPos.y - IN->clipPos.w) / (dw - dy);  \
+        interpolate_vertex(t, IN, OUT, NEW );
+
+   GENERAL_CLIP(incount, inlist, outcount, outlist)
+
+#undef INSIDE
+#undef COMPUTE_INTERSECTION
+
+/*
+ * Clip against -Y
+ */
+#define INSIDE(V)       (V->clipPos.y >= -V->clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW )               \
+        dy = OUT->clipPos.y - IN->clipPos.y;               \
+        dw = OUT->clipPos.w - IN->clipPos.w;               \
+        t = -(IN->clipPos.y + IN->clipPos.w) / (dw + dy);  \
+        interpolate_vertex(t, IN, OUT, NEW );
+
+   GENERAL_CLIP(outcount, outlist, incount, inlist)
+
+#undef INSIDE
+#undef COMPUTE_INTERSECTION
+
+/*
+ * Clip against +Z
+ */
+#define INSIDE(V)       (V->clipPos.z <= V->clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW )              \
+        dz = OUT->clipPos.z - IN->clipPos.z;              \
+        dw = OUT->clipPos.w - IN->clipPos.w;              \
+        t = (IN->clipPos.z - IN->clipPos.w) / (dw - dz);  \
+        interpolate_vertex(t, IN, OUT, NEW );
+
+   GENERAL_CLIP(incount, inlist, outcount, outlist)
+
+#undef INSIDE
+#undef COMPUTE_INTERSECTION
+
+/*
+ * Clip against -Z
+ */
+#define INSIDE(V)       (V->clipPos.z >= -V->clipPos.w)
+#define COMPUTE_INTERSECTION( IN, OUT, NEW )               \
+        dz = OUT->clipPos.z - IN->clipPos.z;               \
+        dw = OUT->clipPos.w - IN->clipPos.w;               \
+        t = -(IN->clipPos.z + IN->clipPos.w) / (dw + dz);  \
+        interpolate_vertex(t, IN, OUT, NEW );
+
+   GENERAL_CLIP(outcount, outlist, result, vOut)
+
+#undef INSIDE
+#undef COMPUTE_INTERSECTION
+
+#undef GENERAL_CLIP
+
+       return result;
+}
+
+/*@}*/
+
+
+
+/**********************************************************************/
+/** \name                    Selection                                */
+/**********************************************************************/
+/*@{*/
+
+/**
+ * \brief Select point.
+ * 
+ * \param v vertex.
+ *
+ * If the clipped point is visible then maps the vertex into window coordinates
+ * and calls _mesa_update_hitflag().
+ */
+static void
+select_point(const vertex *v)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   if (clip_point(v) == 0)
+   {
+      vertex c = *v;
+      MAP_POINT(c.winPos, c.clipPos, ctx->Viewport);
+      _mesa_update_hitflag(ctx, c.winPos.z);
+   }
+}
+
+/**
+ * \brief Select line.
+ * 
+ * \param v0 first vertex.
+ * \param v1 second vertex.
+ *
+ * If the clipped line is visible then maps the vertices into window coordinates
+ * and calls _mesa_update_hitflag().
+ */
+static void
+select_line(const vertex *v0, const vertex *v1)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   vertex c0, c1;
+   if (clip_line(v0, v1, &c0, &c1))
+   {
+      MAP_POINT(c0.winPos, c0.clipPos, ctx->Viewport);
+      MAP_POINT(c1.winPos, c1.clipPos, ctx->Viewport);
+      _mesa_update_hitflag(ctx, c0.winPos.z);
+      _mesa_update_hitflag(ctx, c1.winPos.z);
+   }
+}
+
+/**
+ * \brief Select line.
+ * 
+ * \param v0 first vertex.
+ * \param v1 second vertex.
+ * \param v2 third vertex.
+ *
+ * If the clipped polygon is visible then maps the vertices into window
+ * coordinates and calls _mesa_update_hitflag().
+ */
+static void
+select_triangle(const vertex *v0,
+               const vertex *v1,
+               const vertex *v2)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   vertex vlist[3], vclipped[8];
+   GLuint i, n;
+
+   vlist[0] = *v0;
+   vlist[1] = *v1;
+   vlist[2] = *v2;
+   n = clip_polygon(vlist, 3, vclipped);
+   for (i = 0; i < n; i++) {
+      MAP_POINT(vclipped[i].winPos, vclipped[i].clipPos, ctx->Viewport);
+      _mesa_update_hitflag(ctx, vclipped[i].winPos.z);
+   }
+}
+
+/**
+ * \brief Set current vertex coordinates.
+ *
+ * \param x x vertex coordinate.
+ * \param y y vertex coordinate.
+ * \param z z vertex coordinate.
+ * \param w homogeneous coordinate.
+ * 
+ * Stores the vertex and current attributes in ::vb, transforms it into eye space and then clip space.
+ * 
+ * If a sufficient number of vertices is stored calls one of select_point(),
+ * select_line() or select_triangle(), according to the current primitive.
+ */
+static void
+radeon_select_Vertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_polygon_attrib *p = &(ctx->Polygon);
+   vertex *v = vb.vBuffer + vb.vCount;
+
+   /* store the vertex */
+   v->pos.x = x;
+   v->pos.y = y;
+   v->pos.z = z;
+   v->pos.w = w;
+   v->color.r = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0];  
+   v->color.g = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1];  
+   v->color.b = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2];  
+   v->color.a = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3];  
+   v->texCoord.s = ctx->Current.Attrib[VERT_ATTRIB_TEX0][0]; 
+   v->texCoord.t = ctx->Current.Attrib[VERT_ATTRIB_TEX0][1]; 
+
+   /* transform to eye space, then clip space */
+   TRANSFORM_POINT(v->eyePos, ctx->ModelviewMatrixStack.Top->m, v->pos);
+   TRANSFORM_POINT(v->clipPos, ctx->ProjectionMatrixStack.Top->m, v->eyePos);
+
+   switch (ctx->Driver.CurrentExecPrimitive) {
+   case GL_POINTS:
+      assert(vb.vCount == 0);
+      select_point(v);
+      break;
+   case GL_LINES:
+      if (vb.vCount == 0)
+      {
+        vb.vCount = 1;
+      }
+      else
+      {
+        assert(vb.vCount == 1);
+        select_line(vb.vBuffer + 0, vb.vBuffer + 1);
+        vb.vCount = 0;
+      }
+      break;
+   case GL_LINE_STRIP:
+      if (vb.vCount == 0)
+      {
+        vb.vCount = 1;
+      }
+      else
+      {
+        assert(vb.vCount == 1);
+        select_line(vb.vBuffer + 0, vb.vBuffer + 1);
+        vb.vBuffer[0] = vb.vBuffer[1];
+        /* leave vb.vCount at 1 */
+      }
+      break;
+   case GL_LINE_LOOP:
+      if (vb.vCount == 0)
+      {
+        vb.vCount = 1;
+        vb.partialLineLoop = GL_FALSE;
+      }
+      else if (vb.vCount == 1)
+      {
+        select_line(vb.vBuffer + 0, vb.vBuffer + 1);
+        vb.partialLineLoop = GL_TRUE;
+        vb.vCount = 2;
+      }
+      else
+      {
+        assert(vb.vCount == 2);
+        vb.partialLineLoop = GL_FALSE;
+        select_line(vb.vBuffer + 1, vb.vBuffer + 2);
+        vb.vBuffer[1] = vb.vBuffer[2];
+        /* leave vb.vCount at 2 */
+      }
+      break;
+   case GL_TRIANGLES:
+      if (vb.vCount == 0 || vb.vCount == 1)
+      {
+        vb.vCount++;
+      }
+      else
+      {
+        assert(vb.vCount == 2);
+        select_triangle(vb.vBuffer + 0, vb.vBuffer + 1, vb.vBuffer + 2);
+        vb.vCount = 0;
+      }
+      break;
+   case GL_TRIANGLE_STRIP:
+      if (vb.vCount == 0 || vb.vCount == 1)
+      {
+        vb.vCount++;
+      }
+      else if (vb.vCount == 2)
+      {
+        select_triangle(vb.vBuffer + 0, vb.vBuffer + 1, vb.vBuffer + 2);
+        vb.vCount = 3;
+      }
+      else
+      {
+        assert(vb.vCount == 3);
+        select_triangle(vb.vBuffer + 1, vb.vBuffer + 3, vb.vBuffer + 2);
+        vb.vBuffer[0] = vb.vBuffer[2];
+        vb.vBuffer[1] = vb.vBuffer[3];
+        vb.vCount = 2;
+      }
+      break;           
+   case GL_TRIANGLE_FAN:
+      if (vb.vCount == 0 || vb.vCount == 1)
+      {
+        vb.vCount++;
+      }
+      else
+      {
+        assert(vb.vCount == 2);
+        select_triangle(vb.vBuffer + 0, vb.vBuffer + 1, vb.vBuffer + 2);
+        vb.vBuffer[1] = vb.vBuffer[2];
+        /* leave vb.vCount = 2 */
+      }
+      break;
+   case GL_QUADS:
+      if (vb.vCount < 3)
+      {
+        vb.vCount++;
+      }
+      else
+      {
+        assert(vb.vCount == 3);
+        select_triangle(vb.vBuffer + 0, vb.vBuffer + 1, vb.vBuffer + 2);
+        select_triangle(vb.vBuffer + 0, vb.vBuffer + 2, vb.vBuffer + 3);
+        vb.vCount = 0;
+      }
+      break;           
+   case GL_QUAD_STRIP:
+      if (vb.vCount < 3)
+      {
+        vb.vCount++;
+      }
+      else
+      {
+        assert(vb.vCount == 3);
+        select_triangle(vb.vBuffer + 0, vb.vBuffer + 1, vb.vBuffer + 2);
+        select_triangle(vb.vBuffer + 1, vb.vBuffer + 3, vb.vBuffer + 2);
+        vb.vBuffer[0] = vb.vBuffer[2];
+        vb.vBuffer[1] = vb.vBuffer[3];
+        vb.vCount = 2;
+      }
+      break;           
+   case GL_POLYGON:
+      switch (p->FrontMode) {
+      case GL_POINT:
+        assert(vb.vCount == 0);
+        select_point(v);
+        break;
+      case GL_LINE:
+        if (vb.vCount == 0)
+        {
+           vb.vCount = 1;
+           vb.partialLineLoop = GL_FALSE;
+        }
+        else if (vb.vCount == 1)
+        {
+           select_line(vb.vBuffer + 0, vb.vBuffer + 1);
+           vb.partialLineLoop = GL_TRUE;
+           vb.vCount = 2;
+        }
+        else
+        {
+           assert(vb.vCount == 2);
+           vb.partialLineLoop = GL_FALSE;
+           select_line(vb.vBuffer + 1, vb.vBuffer + 2);
+           vb.vBuffer[1] = vb.vBuffer[2];
+           /* leave vb.vCount at 2 */
+        }
+        break;
+      case GL_FILL:
+        /* draw as a tri-fan */
+        if (vb.vCount == 0 || vb.vCount == 1)
+        {
+           vb.vCount++;
+        }
+        else
+        {
+           assert(vb.vCount == 2);
+           select_triangle(vb.vBuffer + 0, vb.vBuffer + 1, vb.vBuffer + 2);
+           vb.vBuffer[1] = vb.vBuffer[2];
+           /* leave vb.vCount = 2 */
+        }
+        break;
+      default:
+        ; /* impossible */
+      }
+      break;
+   default:
+      ; /* outside begin/end -- no action required */
+   }
+}
+
+/**
+ * \brief Calls radeon_select_Vertex4f().
+ */
+static void radeon_select_Vertex2f(GLfloat x, GLfloat y)
+{
+   radeon_select_Vertex4f(x, y, 0.0, 1.0);
+}
+
+/**
+ * \brief Calls radeon_select_Vertex4f().
+ */
+static void radeon_select_Vertex2fv(const GLfloat * v)
+{
+   radeon_select_Vertex4f(v[0], v[1], 0.0, 1.0);
+}
+
+/**
+ * \brief Calls radeon_select_Vertex4f().
+ */
+static void radeon_select_Vertex3f(GLfloat x, GLfloat y, GLfloat z)
+{
+   radeon_select_Vertex4f(x, y, z, 1.0);
+}
+
+/**
+ * \brief Calls radeon_select_Vertex4f().
+ */
+static void radeon_select_Vertex3fv(const GLfloat * v)
+{
+   radeon_select_Vertex4f(v[0], v[1], v[2], 1.0);
+}
+
+
+/**
+ * \brief Set current vertex color.
+ *
+ * \param r red color component.
+ * \param g gree color component.
+ * \param b blue color component.
+ * \param a alpha color component.
+ *
+ * Updates the GL context's current vertex color.
+ */
+static void radeon_select_Color4f( GLfloat r, GLfloat g,
+                                  GLfloat b, GLfloat a )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
+   dest[0] = r;
+   dest[1] = g;
+   dest[2] = b;
+   dest[3] = a;
+}
+
+/**
+ * \brief Calls radeon_select_Color4f().
+ */
+static void radeon_select_Color4fv( const GLfloat *v )
+{
+   radeon_select_Color4f( v[0], v[1], v[2], v[3] );
+}
+
+/**
+ * \brief Calls radeon_select_Color4f().
+ */
+static void radeon_select_Color3f( GLfloat r, GLfloat g, GLfloat b )
+{
+   radeon_select_Color4f( r, g, b, 1.0 );
+}
+
+/**
+ * \brief Calls radeon_select_Color4f().
+ */
+static void radeon_select_Color3fv( const GLfloat *v )
+{
+   radeon_select_Color4f( v[0], v[1], v[2], 1.0 );
+}
+
+/**
+ * \brief Set current vertex texture coordinates.
+ *
+ * \param s texture coordinate.
+ * \param t texture coordinate.
+ *
+ * Updates the GL context's current vertex texture coordinates.
+ */
+static __inline__ void radeon_select_TexCoord2f( GLfloat s, GLfloat t )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLfloat *dest = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
+   dest[0] = s;
+   dest[1] = t;
+}
+
+/**
+ * \brief Calls radeon_select_TexCoord2f().
+ */
+static void radeon_select_TexCoord2fv( const GLfloat *v )
+{
+   radeon_select_TexCoord2f( v[0], v[1] );
+}
+
+
+/**
+ * \brief Process glBegin().
+ *
+ * \param mode primitive.
+ */ 
+static void radeon_select_Begin(GLenum mode)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (mode > GL_POLYGON) {
+      _mesa_error( ctx, GL_INVALID_ENUM, "glBegin" );
+      return;
+   }
+
+   if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
+      _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
+      return;
+   }
+
+   ctx->Driver.CurrentExecPrimitive = mode;
+
+   vb.vCount = 0;
+   vb.lineReset = GL_TRUE;
+   vb.partialLineLoop = GL_FALSE;
+}
+
+/**
+ * \brief Process glEnd().
+ */
+static void radeon_select_End(void)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if ( (ctx->Driver.CurrentExecPrimitive == GL_LINE_LOOP ||
+        (ctx->Driver.CurrentExecPrimitive == GL_POLYGON && 
+         ctx->Polygon.FrontMode == GL_LINE))
+       && vb.vCount == 2 )
+   {
+      /* draw the last line segment */
+      if (vb.partialLineLoop)
+        select_line(vb.vBuffer + 1, vb.vBuffer + 0);
+      else
+        select_line(vb.vBuffer + 2, vb.vBuffer + 0);
+   }
+
+   ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
+}
+
+
+/**
+ * \brief Flush vertices.
+ * 
+ * \param ctx GL context.
+ * \param flags not used.
+ *
+ * Nothing much to do here, besides marking the vertices as flushed, as we
+ * don't buffer anything.
+ */
+static void radeonSelectFlushVertices( GLcontext *ctx, GLuint flags )
+{
+   ctx->Driver.NeedFlush = 0;
+}
+
+/**
+ * \brief Install the select callbacks.
+ *
+ * \param ctx GL context.
+ *
+ * Installs the glBegin()/glEnd() associated select callbacks into the glapi
+ * table.
+ */
+void radeon_select_Install( GLcontext *ctx )
+{
+   struct _glapi_table *exec = ctx->Exec;
+
+   exec->Color3f = radeon_select_Color3f;
+   exec->Color3fv = radeon_select_Color3fv;
+   exec->Color4f = radeon_select_Color4f;
+   exec->Color4fv = radeon_select_Color4fv;
+   exec->TexCoord2f = radeon_select_TexCoord2f;
+   exec->TexCoord2fv = radeon_select_TexCoord2fv;
+   exec->Vertex2f = radeon_select_Vertex2f;
+   exec->Vertex2fv = radeon_select_Vertex2fv;
+   exec->Vertex3f = radeon_select_Vertex3f;
+   exec->Vertex3fv = radeon_select_Vertex3fv;
+   exec->Begin = radeon_select_Begin;
+   exec->End = radeon_select_End;
+
+   ctx->Driver.FlushVertices = radeonSelectFlushVertices;
+}
+/*@}*/
+
+
+
+/**
+ * \brief Set rasterization mode.
+ *
+ * \param ctx GL context.
+ * \param mode rasterization mode. Supports GL_RENDER or
+ *
+ * If mode is GL_RENDER, calls either radeonVtxfmtInit() or
+ * radeon_noop_Install depending on whether the application has focus
+ * (i.e., a fullscreen-cliprect) or not.  If mode is GL_SELECT, calls
+ * radeon_select_Install().
+ */
+static void radeonRenderMode( GLcontext *ctx, GLenum mode )
+{
+   switch (mode) {
+   case GL_RENDER:
+      radeonVtxfmtInit( ctx );
+      break;
+   case GL_SELECT:
+      radeon_select_Install( ctx );
+      break;
+   default:
+      break;
+   }
+}
+
+/**
+ * \brief Setup the GL context driver callbacks.
+ *
+ * \param ctx GL context.
+ *
+ * \sa Called by radeonCreateContext().
+ */
+void radeonInitSelect( GLcontext *ctx )
+{
+   ctx->Driver.RenderMode = radeonRenderMode;
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_subset_tex.c b/src/mesa/drivers/dri/radeon/radeon_subset_tex.c
new file mode 100644 (file)
index 0000000..e401779
--- /dev/null
@@ -0,0 +1,1018 @@
+/**
+ * \file radeon_subset_tex.c
+ * \brief Texturing.
+ *
+ * \author Gareth Hughes <gareth@valinux.com>
+ * \author Brian Paul <brianp@valinux.com>
+ */
+
+/*
+ * Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+ *                      VA Linux Systems Inc., Fremont, California.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_tex.c,v 1.6 2002/09/16 18:05:20 eich Exp $ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "colormac.h"
+#include "context.h"
+#include "enums.h"
+#include "image.h"
+#include "simple_list.h"
+#include "texformat.h"
+#include "texstore.h"
+
+#include "radeon_context.h"
+#include "radeon_state.h"
+#include "radeon_ioctl.h"
+#include "radeon_subset.h"
+
+#include <errno.h>
+#include <stdio.h>
+
+
+/**
+ * \brief Destroy hardware state associated with a texture.
+ *
+ * \param rmesa Radeon context.
+ * \param t Radeon texture object to be destroyed.
+ *
+ * Frees the memory associated with the texture and if the texture is bound to
+ * a texture unit cleans the associated hardware state.
+ */
+void radeonDestroyTexObj( radeonContextPtr rmesa, radeonTexObjPtr t )
+{
+   if ( t->memBlock ) {
+      mmFreeMem( t->memBlock );
+      t->memBlock = NULL;
+   }
+
+   if ( t->tObj )
+      t->tObj->DriverData = NULL;
+
+   if ( rmesa ) {
+      if ( t == rmesa->state.texture.unit[0].texobj ) {
+         rmesa->state.texture.unit[0].texobj = NULL;
+        remove_from_list( &rmesa->hw.tex[0] );
+        make_empty_list( &rmesa->hw.tex[0] );
+      }
+   }
+
+   remove_from_list( t );
+   FREE( t );
+}
+
+
+/**
+ * \brief Keep track of swapped out texture objects.
+ * 
+ * \param rmesa Radeon context.
+ * \param t Radeon texture object.
+ *
+ * Frees the memory associated with the texture, marks all mipmap images in
+ * the texture as dirty and add it to the radeon_texture::swapped list.
+ */
+static void radeonSwapOutTexObj( radeonContextPtr rmesa, radeonTexObjPtr t )
+{
+   if ( t->memBlock ) {
+      mmFreeMem( t->memBlock );
+      t->memBlock = NULL;
+   }
+
+   t->dirty_images = ~0;
+   move_to_tail( &rmesa->texture.swapped, t );
+}
+
+
+/**
+ * Texture space has been invalidated.
+ *
+ * \param rmesa Radeon context.
+ * \param heap texture heap number.
+ * 
+ * Swaps out every texture in the specified heap.
+ */
+void radeonAgeTextures( radeonContextPtr rmesa, int heap )
+{
+   radeonTexObjPtr t, tmp;
+
+   foreach_s ( t, tmp, &rmesa->texture.objects[heap] ) 
+      radeonSwapOutTexObj( rmesa, t );
+}
+
+
+/***************************************************************/
+/** \name Texture image conversions
+ */
+/*@{*/
+
+/**
+ * \brief Upload texture image.
+ *
+ * \param rmesa Radeon context.
+ * \param t Radeon texture object.
+ * \param level level of the image to take the sub-image.
+ * \param x sub-image abscissa.
+ * \param y sub-image ordinate.
+ * \param width sub-image width.
+ * \param height sub-image height.
+ *
+ * Fills in a drmRadeonTexture and drmRadeonTexImage structures and uploads the
+ * texture via the DRM_RADEON_TEXTURE ioctl, aborting in case of failure.
+ */
+static void radeonUploadSubImage( radeonContextPtr rmesa,
+                                 radeonTexObjPtr t, GLint level,
+                                 GLint x, GLint y, GLint width, GLint height )
+{
+   struct gl_texture_image *texImage;
+   GLint ret;
+   drmRadeonTexture tex;
+   drmRadeonTexImage tmp;
+
+   level += t->firstLevel;
+   texImage = t->tObj->Image[level];
+
+   if ( !texImage || !texImage->Data ) 
+      return;
+
+   t->image[level].data = texImage->Data;
+
+   tex.offset = t->bufAddr;
+   tex.pitch = (t->image[0].width * texImage->TexFormat->TexelBytes) / 64;
+   tex.format = t->pp_txformat & RADEON_TXFORMAT_FORMAT_MASK;
+   tex.width = texImage->Width;
+   tex.height = texImage->Height;
+   tex.image = &tmp;
+
+   memcpy( &tmp, &t->image[level], sizeof(drmRadeonTexImage) );
+
+   do {
+      ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_TEXTURE,
+                                 &tex, sizeof(drmRadeonTexture) );
+   } while ( ret && errno == EAGAIN );
+
+   if ( ret ) {
+      UNLOCK_HARDWARE( rmesa );
+      fprintf( stderr, "DRM_RADEON_TEXTURE: return = %d\n", ret );
+      exit( 1 );
+   }
+}
+
+/**
+ * \brief Upload texture images.
+ *
+ * This might require removing our own and/or other client's texture objects to
+ * make room for these images.
+ *
+ * \param rmesa Radeon context.
+ * \param tObj texture object to upload.
+ *
+ * Sets the matching hardware texture format. Calculates which mipmap levels to
+ * send, depending of the base image size, GL_TEXTURE_MIN_LOD,
+ * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL and the
+ * Radeon offset rules. Kicks out textures until the requested texture fits,
+ * sets the texture hardware state and, while holding the hardware lock,
+ * uploads any images that are new.
+ */
+static void radeonSetTexImages( radeonContextPtr rmesa,
+                               struct gl_texture_object *tObj )
+{
+   radeonTexObjPtr t = (radeonTexObjPtr)tObj->DriverData;
+   const struct gl_texture_image *baseImage = tObj->Image[tObj->BaseLevel];
+   GLint totalSize;
+   GLint texelsPerDword = 0, blitWidth = 0, blitPitch = 0;
+   GLint x, y, width, height;
+   GLint i;
+   GLint firstLevel, lastLevel, numLevels;
+   GLint log2Width, log2Height;
+   GLuint txformat = 0;
+
+   /* This code cannot be reached once we have lost focus
+    */
+   assert(rmesa->radeonScreen->buffers);
+
+   /* Set the hardware texture format
+    */
+   switch (baseImage->TexFormat->MesaFormat) {
+   case MESA_FORMAT_I8:
+      txformat = RADEON_TXFORMAT_I8;
+      texelsPerDword = 4;
+      blitPitch = 64;
+      break;
+   case MESA_FORMAT_RGBA8888:
+      txformat = RADEON_TXFORMAT_RGBA8888 | RADEON_TXFORMAT_ALPHA_IN_MAP;
+      texelsPerDword = 1;
+      blitPitch = 16;
+      break;
+   case MESA_FORMAT_RGB565:
+      txformat = RADEON_TXFORMAT_RGB565;
+      texelsPerDword = 2;
+      blitPitch = 32;
+      break;
+   default:
+      _mesa_problem(NULL, "unexpected texture format in radeonTexImage2D");
+      return;
+   }
+
+   t->pp_txformat &= ~(RADEON_TXFORMAT_FORMAT_MASK |
+                      RADEON_TXFORMAT_ALPHA_IN_MAP);
+   t->pp_txformat |= txformat;
+
+
+   /* Select the larger of the two widths for our global texture image
+    * coordinate space.  As the Radeon has very strict offset rules, we
+    * can't upload mipmaps directly and have to reference their location
+    * from the aligned start of the whole image.
+    */
+   blitWidth = MAX2( baseImage->Width, blitPitch );
+
+   /* Calculate mipmap offsets and dimensions.
+    */
+   totalSize = 0;
+   x = 0;
+   y = 0;
+
+   /* Compute which mipmap levels we really want to send to the hardware.
+    * This depends on the base image size, GL_TEXTURE_MIN_LOD,
+    * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
+    * Yes, this looks overly complicated, but it's all needed.
+    */
+   firstLevel = tObj->BaseLevel + (GLint) (tObj->MinLod + 0.5);
+   firstLevel = MAX2(firstLevel, tObj->BaseLevel);
+   lastLevel = tObj->BaseLevel + (GLint) (tObj->MaxLod + 0.5);
+   lastLevel = MAX2(lastLevel, tObj->BaseLevel);
+   lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
+   lastLevel = MIN2(lastLevel, tObj->MaxLevel);
+   lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
+
+   /* save these values */
+   t->firstLevel = firstLevel;
+   t->lastLevel = lastLevel;
+
+   numLevels = lastLevel - firstLevel + 1;
+
+   log2Width = tObj->Image[firstLevel]->WidthLog2;
+   log2Height = tObj->Image[firstLevel]->HeightLog2;
+
+   for ( i = 0 ; i < numLevels ; i++ ) {
+      const struct gl_texture_image *texImage = tObj->Image[i + firstLevel];
+      if ( !texImage )
+        break;
+
+      width = texImage->Width;
+      height = texImage->Height;
+
+      /* Texture images have a minimum pitch of 32 bytes (half of the
+       * 64-byte minimum pitch for blits).  For images that have a
+       * width smaller than this, we must pad each texture image
+       * scanline out to this amount.
+       */
+      if ( width < blitPitch / 2 ) {
+        width = blitPitch / 2;
+      }
+
+      totalSize += width * height * baseImage->TexFormat->TexelBytes;
+      ASSERT( (totalSize & 31) == 0 );
+
+      while ( width < blitWidth && height > 1 ) {
+        width *= 2;
+        height /= 2;
+      }
+
+      ASSERT(i < RADEON_MAX_TEXTURE_LEVELS);
+      t->image[i].x = x;
+      t->image[i].y = y;
+      t->image[i].width  = width;
+      t->image[i].height = height;
+
+      /* While blits must have a pitch of at least 64 bytes, mipmaps
+       * must be aligned on a 32-byte boundary (just like each texture
+       * image scanline).
+       */
+      if ( width >= blitWidth ) {
+        y += height;
+      } else {
+        x += width;
+        if ( x >= blitWidth ) {
+           x = 0;
+           y++;
+        }
+      }
+   }
+
+   /* Align the total size of texture memory block.
+    */
+   t->totalSize = (totalSize + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
+
+   /* Hardware state:
+    */
+   t->pp_txfilter &= ~RADEON_MAX_MIP_LEVEL_MASK;
+   t->pp_txfilter |= (numLevels - 1) << RADEON_MAX_MIP_LEVEL_SHIFT;
+
+   t->pp_txformat &= ~(RADEON_TXFORMAT_WIDTH_MASK |
+                      RADEON_TXFORMAT_HEIGHT_MASK);
+   t->pp_txformat |= ((log2Width << RADEON_TXFORMAT_WIDTH_SHIFT) |
+                     (log2Height << RADEON_TXFORMAT_HEIGHT_SHIFT));
+   t->dirty_state = TEX_ALL;
+
+   /* Update the local texture LRU.
+    */
+   move_to_head( &rmesa->texture.objects[0], t );
+
+   LOCK_HARDWARE( rmesa );
+
+   /* Kick out textures until the requested texture fits */
+   while ( !t->memBlock ) {
+      t->memBlock = mmAllocMem( rmesa->texture.heap[0], t->totalSize, 12, 0);
+        
+      if (!t->memBlock)
+        radeonSwapOutTexObj( rmesa, rmesa->texture.objects[0].prev );
+        
+   }
+
+   /* Set the base offset of the texture image */
+   t->bufAddr = rmesa->radeonScreen->texOffset[0] + t->memBlock->ofs;
+   t->pp_txoffset = t->bufAddr;
+
+   /* Upload any images that are new 
+    */
+   for ( i = 0 ; i < numLevels ; i++ ) {
+      if ( t->dirty_images & (1 << i) ) {
+        radeonUploadSubImage( rmesa, t, i, 0, 0,
+                              t->image[i].width, t->image[i].height );
+      }
+   }
+
+   rmesa->texture.age[0] = ++rmesa->sarea->texAge[0]; 
+   UNLOCK_HARDWARE( rmesa );
+   t->dirty_images = 0;
+}
+
+/*@}*/
+
+
+/******************************************************************/
+/** \name Texture combine functions
+ */
+/*@{*/
+
+enum {
+   RADEON_DISABLE      = 0, /**< \brief disabled */
+   RADEON_REPLACE      = 1, /**< \brief replace function */
+   RADEON_MODULATE     = 2, /**< \brief modulate function */
+   RADEON_DECAL                = 3, /**< \brief decal function */
+   RADEON_BLEND                = 4, /**< \brief blend function */
+   RADEON_MAX_COMBFUNC = 5  /**< \brief max number of combine functions */
+} ;
+
+
+/**
+ * \brief Color combine function hardware state table.
+ */
+static GLuint radeon_color_combine[][RADEON_MAX_COMBFUNC] =
+{
+   /* Unit 0:
+    */
+   {
+      /* Disable combiner stage
+       */
+      (RADEON_COLOR_ARG_A_ZERO |
+       RADEON_COLOR_ARG_B_ZERO |
+       RADEON_COLOR_ARG_C_CURRENT_COLOR |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_REPLACE = 0x00802800
+       */
+      (RADEON_COLOR_ARG_A_ZERO |
+       RADEON_COLOR_ARG_B_ZERO |
+       RADEON_COLOR_ARG_C_T0_COLOR |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_MODULATE = 0x00800142
+       */
+      (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+       RADEON_COLOR_ARG_B_T0_COLOR |
+       RADEON_COLOR_ARG_C_ZERO |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_DECAL = 0x008c2d42
+       */
+      (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+       RADEON_COLOR_ARG_B_T0_COLOR |
+       RADEON_COLOR_ARG_C_T0_ALPHA |
+       RADEON_BLEND_CTL_BLEND |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_BLEND = 0x008c2902
+       */
+      (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+       RADEON_COLOR_ARG_B_TFACTOR_COLOR |
+       RADEON_COLOR_ARG_C_T0_COLOR |
+       RADEON_BLEND_CTL_BLEND |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+   },
+
+};
+
+/**
+ * \brief Alpha combine function hardware state table.
+ */
+static GLuint radeon_alpha_combine[][RADEON_MAX_COMBFUNC] =
+{
+   /* Unit 0:
+    */
+   {
+      /* Disable combiner stage
+       */
+      (RADEON_ALPHA_ARG_A_ZERO |
+       RADEON_ALPHA_ARG_B_ZERO |
+       RADEON_ALPHA_ARG_C_CURRENT_ALPHA |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_REPLACE = 0x00800500
+       */
+      (RADEON_ALPHA_ARG_A_ZERO |
+       RADEON_ALPHA_ARG_B_ZERO |
+       RADEON_ALPHA_ARG_C_T0_ALPHA |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_MODULATE = 0x00800051
+       */
+      (RADEON_ALPHA_ARG_A_CURRENT_ALPHA |
+       RADEON_ALPHA_ARG_B_T0_ALPHA |
+       RADEON_ALPHA_ARG_C_ZERO |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_DECAL = 0x00800100
+       */
+      (RADEON_ALPHA_ARG_A_ZERO |
+       RADEON_ALPHA_ARG_B_ZERO |
+       RADEON_ALPHA_ARG_C_CURRENT_ALPHA |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_BLEND = 0x00800051
+       */
+      (RADEON_ALPHA_ARG_A_CURRENT_ALPHA |
+       RADEON_ALPHA_ARG_B_TFACTOR_ALPHA |
+       RADEON_ALPHA_ARG_C_T0_ALPHA |
+       RADEON_BLEND_CTL_BLEND |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+   },
+
+};
+
+/*@}*/
+
+
+/******************************************************************/
+/** \name Texture unit state management
+ */
+/*@{*/
+
+/**
+ * \brief Update the texture environment.
+ *
+ * \param ctx GL context
+ * \param unit texture unit to update.
+ *
+ * Sets the state of the RADEON_TEX_PP_TXCBLEND and RADEON_TEX_PP_TXABLEND
+ * registers using the ::radeon_color_combine and ::radeon_alpha_combine tables,
+ * and informs of the state change.
+ */
+static void radeonUpdateTextureEnv( GLcontext *ctx, int unit )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   const struct gl_texture_object *tObj = texUnit->_Current;
+   const GLenum format = tObj->Image[tObj->BaseLevel]->Format;
+   GLuint color_combine = radeon_color_combine[unit][RADEON_DISABLE];
+   GLuint alpha_combine = radeon_alpha_combine[unit][RADEON_DISABLE];
+
+
+   /* Set the texture environment state.  Isn't this nice and clean?
+    * The Radeon will automagically set the texture alpha to 0xff when
+    * the texture format does not include an alpha component.  This
+    * reduces the amount of special-casing we have to do, alpha-only
+    * textures being a notable exception.
+    */
+   switch ( texUnit->EnvMode ) {
+   case GL_REPLACE:
+      switch ( format ) {
+      case GL_RGBA:
+      case GL_INTENSITY:
+        color_combine = radeon_color_combine[unit][RADEON_REPLACE];
+        alpha_combine = radeon_alpha_combine[unit][RADEON_REPLACE];
+        break;
+      case GL_RGB:
+        color_combine = radeon_color_combine[unit][RADEON_REPLACE];
+        alpha_combine = radeon_alpha_combine[unit][RADEON_DISABLE];
+         break;
+      default:
+        break;
+      }
+      break;
+
+   case GL_MODULATE:
+      switch ( format ) {
+      case GL_RGBA:
+      case GL_INTENSITY:
+        color_combine = radeon_color_combine[unit][RADEON_MODULATE];
+        alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE];
+        break;
+      case GL_RGB:
+        color_combine = radeon_color_combine[unit][RADEON_MODULATE];
+        alpha_combine = radeon_alpha_combine[unit][RADEON_DISABLE];
+        break;
+      default:
+        break;
+      }
+      break;
+
+   case GL_DECAL:
+      switch ( format ) {
+      case GL_RGBA:
+      case GL_RGB:
+        color_combine = radeon_color_combine[unit][RADEON_DECAL];
+        alpha_combine = radeon_alpha_combine[unit][RADEON_DISABLE];
+        break;
+      case GL_INTENSITY:
+        color_combine = radeon_color_combine[unit][RADEON_DISABLE];
+        alpha_combine = radeon_alpha_combine[unit][RADEON_DISABLE];
+        break;
+      default:
+        break;
+      }
+      break;
+
+   case GL_BLEND:
+      switch ( format ) {
+      case GL_RGBA:
+      case GL_RGB:
+        color_combine = radeon_color_combine[unit][RADEON_BLEND];
+        alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE];
+        break;
+      case GL_INTENSITY:
+        color_combine = radeon_color_combine[unit][RADEON_BLEND];
+        alpha_combine = radeon_alpha_combine[unit][RADEON_BLEND];
+        break;
+      default:
+        break;
+      }
+      break;
+
+   default:
+      break;
+   }
+
+   if ( rmesa->hw.tex[unit].cmd[TEX_PP_TXCBLEND] != color_combine ||
+       rmesa->hw.tex[unit].cmd[TEX_PP_TXABLEND] != alpha_combine ) {
+      RADEON_STATECHANGE( rmesa, tex[unit] );
+      rmesa->hw.tex[unit].cmd[TEX_PP_TXCBLEND] = color_combine;
+      rmesa->hw.tex[unit].cmd[TEX_PP_TXABLEND] = alpha_combine;
+   }
+}
+
+
+#define TEXOBJ_TXFILTER_MASK (RADEON_MAX_MIP_LEVEL_MASK |      \
+                             RADEON_MIN_FILTER_MASK |          \
+                             RADEON_MAG_FILTER_MASK |          \
+                             RADEON_MAX_ANISO_MASK |           \
+                             RADEON_CLAMP_S_MASK |             \
+                             RADEON_CLAMP_T_MASK)
+
+#define TEXOBJ_TXFORMAT_MASK (RADEON_TXFORMAT_WIDTH_MASK |     \
+                             RADEON_TXFORMAT_HEIGHT_MASK |     \
+                             RADEON_TXFORMAT_FORMAT_MASK |     \
+                             RADEON_TXFORMAT_ALPHA_IN_MAP)
+
+
+
+void radeonUpdateTextureState( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[0];
+
+   if ( texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT) ) {
+      struct gl_texture_object *tObj = texUnit->_Current;
+      radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData;
+
+      /* Upload teximages (not pipelined)
+       */
+      if ( t->dirty_images ) {
+        RADEON_FIREVERTICES( rmesa );
+        radeonSetTexImages( rmesa, tObj );
+      }
+
+      /* Update state if this is a different texture object to last
+       * time.
+       */
+      if ( rmesa->state.texture.unit[0].texobj != t ) {
+        rmesa->state.texture.unit[0].texobj = t;
+        t->dirty_state |= 1<<0;
+        move_to_head( &rmesa->texture.objects[0], t );
+      }
+
+      if (t->dirty_state) {
+        GLuint *cmd = RADEON_DB_STATE( tex[0] );
+
+        cmd[TEX_PP_TXFILTER] &= ~TEXOBJ_TXFILTER_MASK;
+        cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
+        cmd[TEX_PP_TXFILTER] |= t->pp_txfilter & TEXOBJ_TXFILTER_MASK;
+        cmd[TEX_PP_TXFORMAT] |= t->pp_txformat & TEXOBJ_TXFORMAT_MASK;
+        cmd[TEX_PP_TXOFFSET] = t->pp_txoffset;
+        cmd[TEX_PP_BORDER_COLOR] = t->pp_border_color;
+        
+        RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.tex[0] );
+        t->dirty_state = 0;
+      }
+
+      /* Newly enabled?
+       */
+      if (!(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & RADEON_TEX_0_ENABLE)) {
+        RADEON_STATECHANGE( rmesa, ctx );
+        rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (RADEON_TEX_0_ENABLE | 
+                                           RADEON_TEX_BLEND_0_ENABLE);
+
+        RADEON_STATECHANGE( rmesa, tcl );
+        rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_ST0;
+      }
+
+      radeonUpdateTextureEnv( ctx, 0 );
+   }
+   else if (rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (RADEON_TEX_0_ENABLE<<0)) {
+      /* Texture unit disabled */
+      rmesa->state.texture.unit[0].texobj = 0;
+      RADEON_STATECHANGE( rmesa, ctx );
+      rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= 
+        ~((RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE) << 0);
+
+      RADEON_STATECHANGE( rmesa, tcl );
+      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~(RADEON_TCL_VTX_ST0 |
+                                               RADEON_TCL_VTX_Q0);
+   }
+}
+
+
+
+/**
+ * \brief Choose texture format.
+ *
+ * \param ctx GL context.
+ * \param internalFormat texture internal format.
+ * \param format pixel format. Not used.
+ * \param type pixel data type. Not used.
+ *
+ * \return pointer to chosen texture format.
+ *
+ * Returns a pointer to one of the Mesa texture formats which is supported by
+ * Radeon and matches the internal format.
+ */
+static const struct gl_texture_format *
+radeonChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
+                           GLenum format, GLenum type )
+{
+   switch ( internalFormat ) {
+   case GL_RGBA:
+   case GL_RGBA8:
+      return &_mesa_texformat_rgba8888;
+
+   case GL_RGB:
+   case GL_RGB5:
+      return &_mesa_texformat_rgb565;
+
+   case GL_INTENSITY:
+   case GL_INTENSITY8:
+      return &_mesa_texformat_i8;
+
+   default:
+      _mesa_problem(ctx, "unexpected texture format in radeonChoosTexFormat");
+      return NULL;
+   }
+}
+
+/**
+ * \brief Allocate a Radeon texture object.
+ *
+ * \param texObj texture object.
+ *
+ * \return pointer to the device specific texture object on success, or NULL on failure.
+ *
+ * Allocates and initializes a radeon_tex_obj structure to connect it to the
+ * driver private data pointer in \p texObj.
+ */
+static radeonTexObjPtr radeonAllocTexObj( struct gl_texture_object *texObj )
+{
+   radeonTexObjPtr t;
+
+   t = CALLOC_STRUCT( radeon_tex_obj );
+   if (!t)
+      return NULL;
+
+   t->tObj = texObj;
+   texObj->DriverData = t;
+   make_empty_list( t );
+   t->dirty_images = ~0;
+   return t;
+}
+
+
+/**
+ * \brief Load a texture image.
+ *
+ * \param ctx GL context.
+ * \param texObj texture object
+ * \param target target texture.
+ * \param level level of detail number.
+ * \param internalFormat internal format.
+ * \param width texture image width.
+ * \param height texture image height.
+ * \param border border width.
+ * \param format pixel format.
+ * \param type pixel data type.
+ * \param pixels image data.
+ * \param packing passed to _mesa_store_teximage2d() unchanged.
+ * \param texImage passed to _mesa_store_teximage2d() unchanged.
+ * 
+ * If there is a device specific texture object associated with the given
+ * texture object then swaps that texture out. Calls _mesa_store_teximage2d()
+ * with all other parameters unchanged.
+ */
+static void radeonTexImage2D( GLcontext *ctx, GLenum target, GLint level,
+                              GLint internalFormat,
+                              GLint width, GLint height, GLint border,
+                              GLenum format, GLenum type, const GLvoid *pixels,
+                              const struct gl_pixelstore_attrib *packing,
+                              struct gl_texture_object *texObj,
+                              struct gl_texture_image *texImage )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   radeonTexObjPtr t = (radeonTexObjPtr)texObj->DriverData;
+
+   if ( t ) 
+      radeonSwapOutTexObj( rmesa, t );
+
+   /* Note, this will call radeonChooseTextureFormat */
+   _mesa_store_teximage2d(ctx, target, level, internalFormat,
+                          width, height, border, format, type, pixels,
+                          &ctx->Unpack, texObj, texImage);
+}
+
+/**
+ * \brief Set texture environment parameters.
+ *
+ * \param ctx GL context.
+ * \param target texture environment.
+ * \param pname texture parameter. Accepted value is GL_TEXTURE_ENV_COLOR.
+ * \param param parameter value.
+ *
+ * Updates the current unit's RADEON_TEX_PP_TFACTOR register and informs of the
+ * state change.
+ */
+static void radeonTexEnv( GLcontext *ctx, GLenum target,
+                         GLenum pname, const GLfloat *param )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLuint unit = ctx->Texture.CurrentUnit;
+   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+
+   switch ( pname ) {
+   case GL_TEXTURE_ENV_COLOR: {
+      GLubyte c[4];
+      GLuint envColor;
+      UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor );
+      envColor = radeonPackColor( 4, c[0], c[1], c[2], c[3] );
+      if ( rmesa->hw.tex[unit].cmd[TEX_PP_TFACTOR] != envColor ) {
+        RADEON_STATECHANGE( rmesa, tex[unit] );
+        rmesa->hw.tex[unit].cmd[TEX_PP_TFACTOR] = envColor;
+      }
+      break;
+   }
+
+   default:
+      return;
+   }
+}
+
+/**
+ * \brief Set texture parameter.
+ *
+ * \param ctx GL context.
+ * \param target target texture.
+ * \param texObj texture object.
+ * \param pname texture parameter.
+ * \param params parameter value.
+ * 
+ * Allocates the device specific texture object data if it doesn't exist
+ * already.
+ * 
+ * Updates the texture object radeon_tex_obj::pp_txfilter register and marks
+ * the texture state (radeon_tex_obj::dirty_state) as dirty.
+ */
+static void radeonTexParameter( GLcontext *ctx, GLenum target,
+                               struct gl_texture_object *texObj,
+                               GLenum pname, const GLfloat *params )
+{
+   radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData;
+   
+   if (!t)
+      t = radeonAllocTexObj( texObj );
+
+   switch ( pname ) {
+   case GL_TEXTURE_MIN_FILTER:
+      t->pp_txfilter &= ~RADEON_MIN_FILTER_MASK;
+      switch ( texObj->MinFilter ) {
+      case GL_NEAREST:
+        t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST;
+        break;
+      case GL_LINEAR:
+        t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR;
+        break;
+      case GL_NEAREST_MIPMAP_NEAREST:
+        t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST_MIP_NEAREST;
+        break;
+      case GL_NEAREST_MIPMAP_LINEAR:
+        t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR_MIP_NEAREST;
+        break;
+      case GL_LINEAR_MIPMAP_NEAREST:
+        t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST_MIP_LINEAR;
+        break;
+      case GL_LINEAR_MIPMAP_LINEAR:
+        t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR_MIP_LINEAR;
+        break;
+      }
+      break;
+
+   case GL_TEXTURE_MAG_FILTER:
+      t->pp_txfilter &= ~RADEON_MAG_FILTER_MASK;
+      switch ( texObj->MagFilter ) {
+      case GL_NEAREST:
+        t->pp_txfilter |= RADEON_MAG_FILTER_NEAREST;
+        break;
+      case GL_LINEAR:
+        t->pp_txfilter |= RADEON_MAG_FILTER_LINEAR;
+        break;
+      }
+      break;
+
+   case GL_TEXTURE_WRAP_S:
+      t->pp_txfilter &= ~RADEON_CLAMP_S_MASK;
+      switch ( texObj->WrapS ) {
+      case GL_REPEAT:
+        t->pp_txfilter |= RADEON_CLAMP_S_WRAP;
+        break;
+      case GL_CLAMP_TO_EDGE:
+        t->pp_txfilter |= RADEON_CLAMP_S_CLAMP_LAST;
+        break;
+      }
+      break;
+
+   case GL_TEXTURE_WRAP_T:
+      t->pp_txfilter &= ~RADEON_CLAMP_T_MASK;
+      switch ( texObj->WrapT ) {
+      case GL_REPEAT:
+        t->pp_txfilter |= RADEON_CLAMP_T_WRAP;
+        break;
+      case GL_CLAMP_TO_EDGE:
+        t->pp_txfilter |= RADEON_CLAMP_T_CLAMP_LAST;
+        break;
+      }
+      break;
+
+   default:
+      return;
+   }
+
+   /* Mark this texobj as dirty (one bit per tex unit)
+    */
+   t->dirty_state = TEX_ALL;
+}
+
+/**
+ * \brief Bind texture.
+ *
+ * \param ctx GL context.
+ * \param target not used.
+ * \param texObj texture object.
+ * 
+ * Allocates the device specific texture data if it doesn't exist already.
+ */
+static void radeonBindTexture( GLcontext *ctx, GLenum target,
+                              struct gl_texture_object *texObj )
+{
+   if ( !texObj->DriverData ) 
+      radeonAllocTexObj( texObj );
+}
+
+/**
+ * \brief Delete texture.
+ *
+ * \param ctx GL context.
+ * \param texObj texture object.
+ *
+ * Fires any outstanding vertices and destroy the device specific texture
+ * object.
+ */ 
+static void radeonDeleteTexture( GLcontext *ctx,
+                                struct gl_texture_object *texObj )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData;
+
+   if ( t ) {
+      if ( rmesa ) 
+         RADEON_FIREVERTICES( rmesa );
+      radeonDestroyTexObj( rmesa, t );
+   }
+}
+
+/**
+ * \brief Initialize context texture object data.
+ * 
+ * \param ctx GL context.
+ *
+ * Called by radeonInitTextureFuncs() to setup the context initial texture
+ * objects.
+ */
+static void radeonInitTextureObjects( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   struct gl_texture_object *texObj;
+   GLuint tmp = ctx->Texture.CurrentUnit;
+
+   ctx->Texture.CurrentUnit = 0;
+
+   texObj = ctx->Texture.Unit[0].Current2D;
+   radeonBindTexture( ctx, GL_TEXTURE_2D, texObj );
+   move_to_tail( &rmesa->texture.swapped,
+                (radeonTexObjPtr)texObj->DriverData );
+
+
+   ctx->Texture.CurrentUnit = tmp;
+}
+
+/**
+ * \brief Setup the GL context driver callbacks.
+ *
+ * \param ctx GL context.
+ *
+ * \sa Called by radeonCreateContext().
+ */
+void radeonInitTextureFuncs( GLcontext *ctx )
+{
+   ctx->Driver.ChooseTextureFormat     = radeonChooseTextureFormat;
+   ctx->Driver.TexImage2D              = radeonTexImage2D;
+
+   ctx->Driver.BindTexture             = radeonBindTexture;
+   ctx->Driver.CreateTexture           = NULL; /* FIXME: Is this used??? */
+   ctx->Driver.DeleteTexture           = radeonDeleteTexture;
+   ctx->Driver.PrioritizeTexture       = NULL;
+   ctx->Driver.ActiveTexture           = NULL;
+   ctx->Driver.UpdateTexturePalette    = NULL;
+
+   ctx->Driver.TexEnv                  = radeonTexEnv;
+   ctx->Driver.TexParameter            = radeonTexParameter;
+
+   radeonInitTextureObjects( ctx );
+}
+
+/*@}*/
diff --git a/src/mesa/drivers/dri/radeon/radeon_subset_vtx.c b/src/mesa/drivers/dri/radeon/radeon_subset_vtx.c
new file mode 100644 (file)
index 0000000..aa6ec73
--- /dev/null
@@ -0,0 +1,989 @@
+/**
+ * \file radeon_subset_vtx.c
+ * \brief Vertex buffering.
+ *
+ * \author Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+/*
+ * Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+ *                      Tungsten Graphics Inc., Cedar Park, Texas.
+ * 
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * ATI, TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ */
+
+/* $XFree86$ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "api_noop.h"
+#include "context.h"
+/*#include "mmath.h" */
+#include "mtypes.h"
+#include "enums.h"
+#include "glapi.h"
+#include "colormac.h"
+#include "state.h"
+
+#include "radeon_context.h"
+#include "radeon_state.h"
+#include "radeon_ioctl.h"
+#include "radeon_subset.h"
+
+/**
+ * \brief Union for vertex data.
+ */
+union vertex_dword { 
+       float f; /**< \brief floating point value */
+       int i;   /**< \brief integer point value */
+};
+
+
+/**
+ * \brief Maximum number of dwords per vertex.
+ *
+ * Defined as 10 to hold: \code xyzw rgba st \endcode
+ */
+#define MAX_VERTEX_DWORDS 10
+
+
+/**
+ * \brief Global vertex buffer data.
+ */
+static struct vb_t {
+   /**
+    * \brief Notification mechanism.  
+    *
+    * These are treated as a stack to allow us to do things like build quads in
+    * temporary storage and then emit them as triangles.
+    */
+   struct {
+      GLint vertspace;         /**< \brief free vertices count */
+      GLint initial_vertspace; /**< \brief total vertices count */
+      GLint *dmaptr;           /**< \brief */
+      void (*notify)( void );  /**< \brief notification callback */
+   } stack[2];
+
+   /**
+    * \brief Storage for current vertex.
+    */
+   union vertex_dword vertex[MAX_VERTEX_DWORDS];
+
+   /**
+    * \brief Temporary storage for quads, etc.
+    */
+   union vertex_dword vertex_store[MAX_VERTEX_DWORDS * 4];
+
+   /**
+    * \name Color/texture
+    *
+    * Pointers to either vertex or ctx->Current.Attrib, depending on whether
+    * color/texture participates in the current vertex.
+    */
+   /*@{*/
+   GLfloat *floatcolorptr; /**< \brief color */
+   GLfloat *texcoordptr;   /**< \brief texture */
+   /*@}*/
+
+   /**
+    * \brief Pointer to the GL context.
+    */
+   GLcontext *context;
+
+   /**
+    * \brief Active primitive.
+    *
+    * \note May differ from ctx->Driver.CurrentExecPrimitive.
+    */
+   /*@{*/
+   GLenum prim;          /**< \brief primitive */
+   GLuint vertex_format; /**< \brief vertex format */
+   GLint vertex_size;    /**< \brief vertex size */
+   GLboolean recheck;    /**< \brief set if it's needed to validate this information */
+   /*@}*/
+} vb;
+
+
+static void radeonFlushVertices( GLcontext *, GLuint );
+
+
+/**
+ * \brief Primitive information table.
+ */
+static struct prims_t { 
+   int start,  /**< \brief vertex count for the starting primitive */
+       incr,   /**< \brief vertex increment for a further primitive */
+       hwprim; /**< \brief hardware primitive */
+} prims[10] = {
+   { 1, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_POINT },
+   { 2, 2, RADEON_CP_VC_CNTL_PRIM_TYPE_LINE }, 
+   { 2, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP },
+   { 2, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP },
+   { 3, 3, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST },
+   { 3, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP },
+   { 3, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN }, 
+   { 4, 4, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST },
+   { 4, 2, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP }, 
+   { 3, 1, RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN }, 
+};
+
+
+/**
+ * \brief Finish the primitive in the vertex buffer.
+ *
+ * \param rmesa Radeon context.
+ *
+ * Truncates any redundant vertices off the end of the buffer, emit the
+ * remaining vertices and advances the current DMA region.
+ */
+static void finish_prim( radeonContextPtr rmesa )
+{
+   GLuint prim_end = vb.stack[0].initial_vertspace - vb.stack[0].vertspace;
+   
+   /* Too few vertices? (eg: 2 vertices for a triangles prim?)
+    */
+   if (prim_end < prims[vb.prim].start) 
+      return;
+
+   /* Drop redundant vertices off end of primitive.  (eg: 5 vertices
+    * for triangles prim?)
+    */
+   prim_end -= (prim_end - prims[vb.prim].start) % prims[vb.prim].incr;
+
+   radeonEmitVertexAOS( rmesa, vb.vertex_size, GET_START(&rmesa->dma.current) );
+
+   radeonEmitVbufPrim( rmesa, vb.vertex_format,
+                      prims[vb.prim].hwprim | rmesa->tcl.tcl_flag, 
+                      prim_end );
+
+   rmesa->dma.current.ptr = 
+      rmesa->dma.current.start += prim_end * vb.vertex_size * 4; 
+}
+
+
+/**
+ * \brief Copy a vertex from the current DMA region
+ *
+ * \param rmesa Radeon context.
+ * \param n vertex index relative to the current DMA region.
+ * \param dst destination pointer.
+ *
+ * Used internally by copy_dma_verts().
+ */
+static void copy_vertex( radeonContextPtr rmesa, GLuint n, GLfloat *dst )
+{
+   GLuint i;
+   GLfloat *src = (GLfloat *)(rmesa->dma.current.address + 
+                             rmesa->dma.current.ptr + 
+                             n * vb.vertex_size * 4);
+
+   for (i = 0 ; i < vb.vertex_size; i++) 
+      dst[i] = src[i];
+}
+
+
+/**
+ * \brief Copy last vertices from the current DMA buffer to resume in a new buffer.
+ *
+ * \param rmesa Radeon context.
+ * \param tmp destination buffer.
+ *
+ * Takes from the current DMA buffer the last vertices necessary to resume in a
+ * new buffer, according to the current primitive.  Uses internally
+ * copy_vertex() for the vertex copying.
+ * 
+ */
+static GLuint copy_dma_verts( radeonContextPtr rmesa, 
+                             GLfloat (*tmp)[MAX_VERTEX_DWORDS] )
+{
+   GLuint ovf, i;
+   GLuint nr = vb.stack[0].initial_vertspace - vb.stack[0].vertspace;
+
+   switch( vb.prim )
+   {
+   case GL_POINTS:
+      return 0;
+   case GL_LINES:
+      ovf = nr&1;
+      for (i = 0 ; i < ovf ; i++)
+        copy_vertex( rmesa, nr-ovf+i, tmp[i] );
+      return i;
+   case GL_LINE_STRIP:
+      if (nr == 0) 
+        return 0;
+      copy_vertex( rmesa, nr-1, tmp[0] );
+      return 1;
+   case GL_LINE_LOOP:
+   case GL_TRIANGLE_FAN:
+   case GL_POLYGON:
+      if (nr == 0) 
+        return 0;
+      else if (nr == 1) {
+        copy_vertex( rmesa, 0, tmp[0] );
+        return 1;
+      } else {
+        copy_vertex( rmesa, 0, tmp[0] );
+        copy_vertex( rmesa, nr-1, tmp[1] );
+        return 2;
+      }
+   case GL_TRIANGLES:
+      ovf = nr % 3;
+      for (i = 0 ; i < ovf ; i++)
+        copy_vertex( rmesa, nr-ovf+i, tmp[i] );
+      return i;
+   case GL_QUADS:
+      ovf = nr % 4;
+      for (i = 0 ; i < ovf ; i++)
+        copy_vertex( rmesa, nr-ovf+i, tmp[i] );
+      return i;
+   case GL_TRIANGLE_STRIP:
+   case GL_QUAD_STRIP:
+      ovf = MIN2(nr, 2);
+      for (i = 0 ; i < ovf ; i++)
+        copy_vertex( rmesa, nr-ovf+i, tmp[i] );
+      return i;
+   default:
+      return 0;
+   }
+}
+
+static void notify_wrap_buffer( void );
+
+/**
+ * \brief Resets the vertex buffer notification mechanism.
+ *
+ * Fills in vb_t::stack with the values from the current DMA region in
+ * radeon_dma::current and sets the notification callback to
+ * notify_wrap_buffer().
+ */
+static void reset_notify( void )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT( vb.context );
+
+   vb.stack[0].dmaptr = (int *)(rmesa->dma.current.address +
+                               rmesa->dma.current.ptr);
+   vb.stack[0].vertspace = ((rmesa->dma.current.end - rmesa->dma.current.ptr) / 
+                           (vb.vertex_size * 4));
+   vb.stack[0].vertspace &= ~1;        /* even numbers only -- avoid tristrip parity */
+   vb.stack[0].initial_vertspace = vb.stack[0].vertspace;
+   vb.stack[0].notify = notify_wrap_buffer;
+}      
+
+/**
+ * \brief Full buffer notification callback.
+ *
+ * Makes a copy of the necessary vertices of the current buffer via
+ * copy_dma_verts(), gets and resets new buffer via radeon and re-emits the
+ * saved vertices.
+ */
+static void notify_wrap_buffer( void )
+{
+   GLcontext *ctx = vb.context;
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat tmp[3][MAX_VERTEX_DWORDS];
+   GLuint i, nrverts = 0;
+
+   /* Copy vertices out of dma:
+    */
+   nrverts = copy_dma_verts( rmesa, tmp );
+   finish_prim( rmesa );
+
+   /* Get new buffer
+    */
+   radeonRefillCurrentDmaRegion( rmesa );
+
+   /* Reset vertspace[0], dmaptr
+    */
+   reset_notify();
+
+   /* Reemit saved vertices
+    */
+   for (i = 0 ; i < nrverts; i++) {
+      memcpy( vb.stack[0].dmaptr, tmp[i], vb.vertex_size * 4 );
+      vb.stack[0].dmaptr += vb.vertex_size;
+      vb.stack[0].vertspace--;
+   }
+}
+
+
+static void notify_noop( void )
+{
+   vb.stack[0].dmaptr = (int *)vb.vertex;
+   vb.stack[0].notify = notify_noop;
+   vb.stack[0].vertspace = 1;
+}
+
+/**
+ * \brief Pop the notification mechanism stack.
+ *
+ * Simply copy the second stack array element into the first.
+ *
+ * \sa vb_t::stack and push_notify().
+ */
+static void pop_notify( void )
+{
+   vb.stack[0] = vb.stack[1];
+}
+
+/**
+ * \brief Push the notification mechanism stack.
+ *
+ * \param notify new notify callback for the stack head.
+ * \param space space available for vertices in \p store.
+ * \param store buffer where to store the vertices.
+ * 
+ * Copy the second stack array element into the first and makes the stack head
+ * use the given resources.
+ * 
+ * \sa vb_t::stack and pop_notify().
+ */
+static void push_notify( void (*notify)( void ), int space, 
+                        union vertex_dword *store )
+{
+   vb.stack[1] = vb.stack[0];
+   vb.stack[0].notify = notify;
+   vb.stack[0].initial_vertspace = space;
+   vb.stack[0].vertspace = space;
+   vb.stack[0].dmaptr = (int *)store;
+}
+
+
+/**
+ * \brief Emit a stored vertex (in vb_t::vertex_store) to DMA.
+ *
+ * \param v vertex index.
+ *
+ * Adds the vertex into the current vertex buffer and calls the notification
+ * callback vb_t::notify().
+ */
+static void emit_vertex( int v )
+{
+   int i, *tmp = (int *)vb.vertex_store + v * vb.vertex_size;
+   
+   for (i = 0 ; i < vb.vertex_size ; i++) 
+      *vb.stack[0].dmaptr++ = *tmp++;
+
+   if (--vb.stack[0].vertspace == 0)
+      vb.stack[0].notify();
+}
+
+
+/**
+ * \brief Emit a quad (in vb_t::vertex_store) to DMA as two triangles.
+ *
+ * \param v0 first vertex index.
+ * \param v1 second vertex index.
+ * \param v2 third vertex index.
+ * \param v3 fourth vertex index.
+ *
+ * Calls emit_vertex() to emit the triangles' vertices.
+ */
+static void emit_quad( int v0, int v1, int v2, int v3 )
+{
+   emit_vertex( v0 ); emit_vertex( v1 ); emit_vertex( v3 );
+   emit_vertex( v1 ); emit_vertex( v2 ); emit_vertex( v3 );
+}
+
+/**
+ * \brief Every fourth vertex in a quad primitive, this is called to emit it.
+ *
+ * Pops the notification stack, calls emit_quad() and pushes the notification
+ * stack again, with itself and the vb_t::vertex_store to process another four
+ * vertices.
+ */
+static void notify_quad( void )
+{
+   pop_notify();
+   emit_quad( 0, 1, 2, 3 ); 
+   push_notify( notify_quad, 4, vb.vertex_store );
+}
+
+static void notify_qstrip1( void );
+
+/**
+ * \brief After the 4th vertex, emit either a quad or a flipped quad each two
+ * vertices.
+ *
+ * Pops the notification stack, calls emit_quad() with the flipped vertices and
+ * pushes the notification stack again, with notify_qstrip1() and the
+ * vb_t::vertex_store to process another two vertices.
+ *
+ * \sa notify_qstrip1().
+ */
+static void notify_qstrip0( void )
+{
+   pop_notify();
+   emit_quad( 0, 1, 3, 2 );
+   push_notify( notify_qstrip1, 2, vb.vertex_store );
+}
+
+/**
+ * \brief After the 4th vertex, emit either a quad or a flipped quad each two
+ * vertices.
+ *
+ * Pops the notification stack, calls emit_quad() with the straight vertices
+ * and pushes the notification stack again, with notify_qstrip0() and the
+ * vb_t::vertex_store to process another two vertices.
+ *
+ * \sa notify_qstrip0().
+ */
+static void notify_qstrip1( void )
+{
+   pop_notify();
+   emit_quad( 2, 3, 1, 0 ); 
+   push_notify( notify_qstrip0, 2, vb.vertex_store + 2*vb.vertex_size );
+}
+
+/**
+ * \brief Emit the saved vertex (but hang on to it for later).
+ *
+ * Continue processing this primitive as a linestrip.
+ *
+ * Pops the notification stack and calls emit_quad with the first vertex.
+ */
+static void notify_lineloop0( void )
+{
+   pop_notify();
+   emit_vertex(0);
+}
+
+/**
+ * \brief Invalidate the current vertex format.
+ *
+ * \param ctx GL context.
+ *
+ * Sets the vb_t::recheck flag.
+ */
+void radeonVtxfmtInvalidate( GLcontext *ctx )
+{
+   vb.recheck = GL_TRUE;
+}
+
+
+/**
+ * \brief Validate the vertex format from the context.
+ *
+ * \param ctx GL context.
+ *
+ * Signals a new primitive and determines the appropriate vertex format and
+ * size. Points vb_t::floatcolorptr and vb_t::texcoordptr to the current vertex
+ * and sets them to the current color and texture attributes.
+ *
+ * Clears the vb_t::recheck flag on exit.
+ */
+static void radeonVtxfmtValidate( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+   GLuint ind = (RADEON_CP_VC_FRMT_Z |
+                RADEON_CP_VC_FRMT_FPCOLOR | 
+                RADEON_CP_VC_FRMT_FPALPHA);
+
+   if (ctx->Driver.NeedFlush)
+      ctx->Driver.FlushVertices( ctx, ctx->Driver.NeedFlush );
+
+   if (ctx->Texture.Unit[0]._ReallyEnabled) 
+      ind |= RADEON_CP_VC_FRMT_ST0;
+
+   RADEON_NEWPRIM(rmesa);
+   vb.vertex_format = ind;
+   vb.vertex_size = 3;
+
+   /* Would prefer to use ubyte floats in the vertex:
+    */
+   vb.floatcolorptr = &vb.vertex[vb.vertex_size].f;
+   vb.vertex_size += 4;
+   vb.floatcolorptr[0] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0];
+   vb.floatcolorptr[1] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1];
+   vb.floatcolorptr[2] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2];
+   vb.floatcolorptr[3] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3];
+   
+   if (ind & RADEON_CP_VC_FRMT_ST0) {
+      vb.texcoordptr = &vb.vertex[vb.vertex_size].f;
+      vb.vertex_size += 2;
+      vb.texcoordptr[0] = ctx->Current.Attrib[VERT_ATTRIB_TEX0][0];
+      vb.texcoordptr[1] = ctx->Current.Attrib[VERT_ATTRIB_TEX0][1];   
+   } 
+   else
+      vb.texcoordptr = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
+
+   vb.recheck = GL_FALSE;
+   ctx->Driver.NeedFlush = FLUSH_UPDATE_CURRENT;
+}
+
+
+#define RESET_STIPPLE() do {                   \
+   RADEON_STATECHANGE( rmesa, lin );           \
+   radeonEmitState( rmesa );                   \
+} while (0)
+
+#define AUTO_STIPPLE( mode )  do {             \
+   RADEON_STATECHANGE( rmesa, lin );           \
+   if (mode)                                   \
+      rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] |=        \
+        RADEON_LINE_PATTERN_AUTO_RESET;        \
+   else                                                \
+      rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] &=        \
+        ~RADEON_LINE_PATTERN_AUTO_RESET;       \
+   radeonEmitState( rmesa );                   \
+} while (0)
+
+
+/**
+ * \brief Process glBegin().
+ *
+ * \param mode primitive.
+ */
+static void radeon_Begin( GLenum mode )
+{
+   GLcontext *ctx = vb.context;
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLuint se_cntl;
+   
+   if (mode > GL_POLYGON) {
+      _mesa_error( ctx, GL_INVALID_ENUM, "glBegin" );
+      return;
+   }
+
+   if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
+      _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
+      return;
+   }
+   
+   if (ctx->NewState) 
+      _mesa_update_state( ctx );
+
+   if (rmesa->NewGLState)
+      radeonValidateState( ctx );
+
+   if (vb.recheck) 
+      radeonVtxfmtValidate( ctx );
+
+   /* Do we need to grab a new DMA region for the vertices?
+    */
+   if (rmesa->dma.current.ptr + 12*vb.vertex_size*4 > rmesa->dma.current.end) {
+      RADEON_NEWPRIM( rmesa );
+      radeonRefillCurrentDmaRegion( rmesa );
+   }
+
+   reset_notify();
+   vb.prim = ctx->Driver.CurrentExecPrimitive = mode;
+   se_cntl = rmesa->hw.set.cmd[SET_SE_CNTL] | RADEON_FLAT_SHADE_VTX_LAST;
+
+   if (ctx->Line.StippleFlag && 
+       (mode == GL_LINES || 
+       mode == GL_LINE_LOOP ||
+       mode == GL_LINE_STRIP))
+      RESET_STIPPLE();
+
+   switch( mode ) {
+   case GL_LINES:
+      if (ctx->Line.StippleFlag) 
+        AUTO_STIPPLE( GL_TRUE );
+      break;
+   case GL_LINE_LOOP:
+      vb.prim = GL_LINE_STRIP;
+      push_notify( notify_lineloop0, 1, vb.vertex_store );
+      break;
+   case GL_QUADS:
+      vb.prim = GL_TRIANGLES;
+      push_notify( notify_quad, 4, vb.vertex_store );
+      break;
+   case GL_QUAD_STRIP:
+      if (ctx->_TriangleCaps & DD_FLATSHADE) {
+        vb.prim = GL_TRIANGLES;
+        push_notify( notify_qstrip0, 4, vb.vertex_store );
+      }
+      break;
+   case GL_POLYGON:
+      if (ctx->_TriangleCaps & DD_FLATSHADE)
+        se_cntl &= ~RADEON_FLAT_SHADE_VTX_LAST;
+      break;
+   default:
+      break;
+   }
+
+   if (se_cntl != rmesa->hw.set.cmd[SET_SE_CNTL]) {
+      RADEON_STATECHANGE( rmesa, set );
+      rmesa->hw.set.cmd[SET_SE_CNTL] = se_cntl;
+   }
+}
+
+
+/**
+ * \brief Process glEnd().
+ *
+ */
+static void radeon_End( void )
+{
+   GLcontext *ctx = vb.context;
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
+      _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
+      return;
+   }
+
+   /* Need to finish a line loop?
+    */
+   if (ctx->Driver.CurrentExecPrimitive == GL_LINE_LOOP) 
+      emit_vertex( 0 );
+
+   /* Need to pop off quads/quadstrip/etc notification?
+    */
+   if (vb.stack[0].notify != notify_wrap_buffer)
+      pop_notify();
+
+   finish_prim( rmesa );
+
+   if (ctx->Driver.CurrentExecPrimitive == GL_LINES && ctx->Line.StippleFlag) 
+      AUTO_STIPPLE( GL_FALSE );
+         
+   ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
+   notify_noop();
+}
+
+
+
+/**
+ * \brief Flush vertices.
+ *
+ * \param ctx GL context.
+ * \param flags flags.
+ *
+ * If FLUSH_UPDATE_CURRENT is et in \p flags then the current vertex attributes
+ * in the GL context is updated from vb_t::floatcolorptr and vb_t::texcoordptr.
+ */
+static void radeonFlushVertices( GLcontext *ctx, GLuint flags )
+{
+   if (flags & FLUSH_UPDATE_CURRENT) {
+      ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0] = vb.floatcolorptr[0];
+      ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1] = vb.floatcolorptr[1];
+      ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2] = vb.floatcolorptr[2];
+      ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] = vb.floatcolorptr[3];
+
+      if (vb.vertex_format & RADEON_CP_VC_FRMT_ST0) {
+        ctx->Current.Attrib[VERT_ATTRIB_TEX0][0] = vb.texcoordptr[0];
+        ctx->Current.Attrib[VERT_ATTRIB_TEX0][1] = vb.texcoordptr[1];
+        ctx->Current.Attrib[VERT_ATTRIB_TEX0][2] = 0.0F;
+        ctx->Current.Attrib[VERT_ATTRIB_TEX0][3] = 1.0F;
+      }
+   }
+
+   ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES;
+}
+
+
+/**
+ * \brief Set current vertex coordinates.
+ *
+ * \param x x vertex coordinate.
+ * \param y y vertex coordinate.
+ * \param z z vertex coordinate.
+ * 
+ * Set the current vertex coordinates. If run out of space in this buffer call
+ * the notification callback.
+ */
+static __inline__ void radeon_Vertex3f( GLfloat x, GLfloat y, GLfloat z )
+{
+   int i;
+
+   *vb.stack[0].dmaptr++ = *(int *)&x;
+   *vb.stack[0].dmaptr++ = *(int *)&y;
+   *vb.stack[0].dmaptr++ = *(int *)&z;
+
+   for (i = 3; i < vb.vertex_size; i++) 
+      *vb.stack[0].dmaptr++ = vb.vertex[i].i;
+
+   if (--vb.stack[0].vertspace == 0)
+      vb.stack[0].notify();
+}
+
+/**
+ * \brief Set current vertex color.
+ *
+ * \param r red color component.
+ * \param g gree color component.
+ * \param b blue color component.
+ * \param a alpha color component.
+ *
+ * Sets the current vertex color via vb_t::floatcolorptr.
+ */
+static __inline__  void radeon_Color4f( GLfloat r, GLfloat g,
+                                       GLfloat b, GLfloat a )
+{
+   GLfloat *dest = vb.floatcolorptr;
+   dest[0] = r;
+   dest[1] = g;
+   dest[2] = b;
+   dest[3] = a;
+}
+
+/**
+ * \brief Set current vertex texture coordinates.
+ *
+ * \param s texture coordinate.
+ * \param t texture coordinate.
+ *
+ * Sets the current vertex color via vb_t::texcoordptr.
+ */
+static __inline__ void radeon_TexCoord2f( GLfloat s, GLfloat t )
+{
+   GLfloat *dest = vb.texcoordptr;
+   dest[0] = s;
+   dest[1] = t;
+}
+
+/**
+ * Calls radeon_Vertex3f(), which is expanded inline by the compiler to be
+ * efficient.
+ */
+static void radeon_Vertex3fv( const GLfloat *v )
+{
+   radeon_Vertex3f( v[0], v[1], v[2] );
+}
+
+/**
+ * Calls radeon_Vertex3f(), which is expanded inline by the compiler to be
+ * efficient.
+ */
+static void radeon_Vertex2f( GLfloat x, GLfloat y )
+{
+   radeon_Vertex3f( x, y, 0 );
+}
+
+/**
+ * Calls radeon_Vertex3f(), which is expanded inline by the compiler to be
+ * efficient.
+ */
+static void radeon_Vertex2fv( const GLfloat *v )
+{
+   radeon_Vertex3f( v[0], v[1], 0 );
+}
+
+/**
+ * Calls radeon_Vertex3f(), which is expanded inline by the compiler to be
+ * efficient.
+ */
+static void radeon_Color4fv( const GLfloat *v )
+{
+   radeon_Color4f( v[0], v[1], v[2], v[3] );
+}
+
+/**
+ * Calls radeon_Color4f(), which is expanded inline by the compiler to be
+ * efficient.
+ */
+static void radeon_Color3f( GLfloat r, GLfloat g, GLfloat b )
+{
+   radeon_Color4f( r, g, b, 1.0 );
+}
+
+/**
+ * Calls radeon_Color4f(), which is expanded inline by the compiler to be
+ * efficient.
+ */
+static void radeon_Color3fv( const GLfloat *v )
+{
+   radeon_Color4f( v[0], v[1], v[2], 1.0 );
+}
+
+/**
+ * Calls radeon_TexCoord2f(), which is expanded inline by the compiler to be
+ * efficient.
+ */
+static void radeon_TexCoord2fv( const GLfloat *v )
+{
+   radeon_TexCoord2f( v[0], v[1] );
+}
+
+
+/**
+ * No-op.
+ */
+void radeonVtxfmtUnbindContext( GLcontext *ctx )
+{
+}
+
+/**
+ * No-op.
+ */
+void radeonVtxfmtMakeCurrent( GLcontext *ctx )
+{
+}
+
+/**
+ * No-op.
+ */
+void radeonVtxfmtDestroy( GLcontext *ctx )
+{
+}
+
+/**
+ * \brief Software rendering fallback.
+ *
+ * \param ctx GL context.
+ * \param bit fallback bitmask.
+ * \param mode enable or disable.
+ * 
+ * Does nothing except display a warning message if \p mode is set.
+ */
+void radeonFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
+{
+   if (mode)
+      fprintf(stderr, "Warning: hit nonexistant fallback path!\n");
+}
+
+/**
+ * \brief Software TCL fallback.
+ *
+ * \param ctx GL context.
+ * \param bit fallback bitmask.
+ * \param mode enable or disable.
+ * 
+ * Does nothing except display a warning message if \p mode is set.
+ */
+void radeonTclFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
+{
+   if (mode)
+      fprintf(stderr, "Warning: hit nonexistant fallback path!\n");
+}
+
+/**
+ * \brief Called by radeonPointsBitmap() to disable TCL.
+ *
+ * \param rmesa Radeon context.
+ * \param flag whether to enable or disable TCL.
+ * 
+ * Updates radeon_tcl_info::tcl_flag.
+ */
+void radeonSubsetVtxEnableTCL( radeonContextPtr rmesa, GLboolean flag )
+{
+   rmesa->tcl.tcl_flag = flag ? RADEON_CP_VC_CNTL_TCL_ENABLE : 0;
+}
+
+
+
+/**********************************************************************/
+/** \name        Noop mode for operation without focus                */
+/**********************************************************************/
+/*@{*/
+
+
+/**
+ * \brief Process glBegin().
+ *
+ * \param mode primitive.
+ */ 
+static void radeon_noop_Begin(GLenum mode)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if (mode > GL_POLYGON) {
+      _mesa_error( ctx, GL_INVALID_ENUM, "glBegin" );
+      return;
+   }
+
+   if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
+      _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
+      return;
+   }
+
+   ctx->Driver.CurrentExecPrimitive = mode;
+}
+
+/**
+ * \brief Process glEnd().
+ */
+static void radeon_noop_End(void)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
+}
+
+
+/**
+ * \brief Install the noop callbacks.
+ *
+ * \param ctx GL context.
+ *
+ * Installs the noop callbacks into the glapi table.  These functions
+ * will not attempt to emit any DMA vertices, but will keep internal
+ * GL state updated.  Borrows heavily from the select code.
+ */
+static void radeon_noop_Install( GLcontext *ctx )
+{
+   ctx->Exec->Begin = radeon_noop_Begin;
+   ctx->Exec->End = radeon_noop_End;
+
+   vb.texcoordptr = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
+   vb.floatcolorptr = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
+
+   notify_noop();
+}
+
+
+/**
+ * \brief Setup the GL context callbacks.
+ * 
+ * \param ctx GL context.
+ * 
+ * Setups the GL context callbacks and links _glapi_table entries related to
+ * the glBegin()/glEnd() pairs to the functions in this module.
+ * 
+ * Called by radeonCreateContext() and radeonRenderMode().
+ */
+void radeonVtxfmtInit( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   struct _glapi_table *exec = ctx->Exec;
+
+   exec->Color3f = radeon_Color3f;
+   exec->Color3fv = radeon_Color3fv;
+   exec->Color4f = radeon_Color4f;
+   exec->Color4fv = radeon_Color4fv;
+   exec->TexCoord2f = radeon_TexCoord2f;
+   exec->TexCoord2fv = radeon_TexCoord2fv;
+   exec->Vertex2f = radeon_Vertex2f;
+   exec->Vertex2fv = radeon_Vertex2fv;
+   exec->Vertex3f = radeon_Vertex3f;
+   exec->Vertex3fv = radeon_Vertex3fv;
+   exec->Begin = radeon_Begin;
+   exec->End = radeon_End;
+
+   vb.context = ctx;
+   
+   ctx->Driver.FlushVertices = radeonFlushVertices;
+   ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
+
+   if (rmesa->radeonScreen->buffers) {
+      radeonVtxfmtValidate( ctx );
+      notify_noop();
+   }
+   else 
+      radeon_noop_Install( ctx );
+}
+
+
+/*@}*/
+
+
diff --git a/src/mesa/drivers/dri/radeon/radeon_swtcl.c b/src/mesa/drivers/dri/radeon/radeon_swtcl.c
new file mode 100644 (file)
index 0000000..926b152
--- /dev/null
@@ -0,0 +1,1332 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "glheader.h"
+#include "mtypes.h"
+#include "colormac.h"
+#include "enums.h"
+#include "imports.h"
+#include "macros.h"
+
+#include "swrast_setup/swrast_setup.h"
+#include "math/m_translate.h"
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_imm_exec.h"
+#include "tnl/t_pipeline.h"
+
+#include "radeon_context.h"
+#include "radeon_ioctl.h"
+#include "radeon_state.h"
+#include "radeon_swtcl.h"
+#include "radeon_tcl.h"
+
+/***********************************************************************
+ *              Build render functions from dd templates               *
+ ***********************************************************************/
+
+
+#define RADEON_XYZW_BIT                0x01
+#define RADEON_RGBA_BIT                0x02
+#define RADEON_SPEC_BIT                0x04
+#define RADEON_TEX0_BIT                0x08
+#define RADEON_TEX1_BIT                0x10
+#define RADEON_PTEX_BIT                0x20
+#define RADEON_MAX_SETUP       0x40
+
+static void flush_last_swtcl_prim( radeonContextPtr rmesa  );
+static void flush_last_swtcl_prim_compat( radeonContextPtr rmesa );
+
+static struct {
+   void                (*emit)( GLcontext *, GLuint, GLuint, void *, GLuint );
+   interp_func         interp;
+   copy_pv_func                copy_pv;
+   GLboolean           (*check_tex_sizes)( GLcontext *ctx );
+   GLuint               vertex_size;
+   GLuint               vertex_stride_shift;
+   GLuint               vertex_format;
+} setup_tab[RADEON_MAX_SETUP];
+
+
+#define TINY_VERTEX_FORMAT             (RADEON_CP_VC_FRMT_XY |         \
+                                        RADEON_CP_VC_FRMT_Z |          \
+                                        RADEON_CP_VC_FRMT_PKCOLOR)
+
+#define NOTEX_VERTEX_FORMAT            (RADEON_CP_VC_FRMT_XY |         \
+                                        RADEON_CP_VC_FRMT_Z |          \
+                                        RADEON_CP_VC_FRMT_W0 |         \
+                                        RADEON_CP_VC_FRMT_PKCOLOR |    \
+                                        RADEON_CP_VC_FRMT_PKSPEC)
+
+#define TEX0_VERTEX_FORMAT             (RADEON_CP_VC_FRMT_XY |         \
+                                        RADEON_CP_VC_FRMT_Z |          \
+                                        RADEON_CP_VC_FRMT_W0 |         \
+                                        RADEON_CP_VC_FRMT_PKCOLOR |    \
+                                        RADEON_CP_VC_FRMT_PKSPEC |     \
+                                        RADEON_CP_VC_FRMT_ST0)
+
+#define TEX1_VERTEX_FORMAT             (RADEON_CP_VC_FRMT_XY |         \
+                                        RADEON_CP_VC_FRMT_Z |          \
+                                        RADEON_CP_VC_FRMT_W0 |         \
+                                        RADEON_CP_VC_FRMT_PKCOLOR |    \
+                                        RADEON_CP_VC_FRMT_PKSPEC |     \
+                                        RADEON_CP_VC_FRMT_ST0 |        \
+                                        RADEON_CP_VC_FRMT_ST1)
+
+#define PROJ_TEX1_VERTEX_FORMAT                (RADEON_CP_VC_FRMT_XY |         \
+                                        RADEON_CP_VC_FRMT_Z |          \
+                                        RADEON_CP_VC_FRMT_W0 |         \
+                                        RADEON_CP_VC_FRMT_PKCOLOR |    \
+                                        RADEON_CP_VC_FRMT_PKSPEC |     \
+                                        RADEON_CP_VC_FRMT_ST0 |        \
+                                        RADEON_CP_VC_FRMT_Q0 |         \
+                                        RADEON_CP_VC_FRMT_ST1 |        \
+                                        RADEON_CP_VC_FRMT_Q1)
+
+#define TEX2_VERTEX_FORMAT 0
+#define TEX3_VERTEX_FORMAT 0
+#define PROJ_TEX3_VERTEX_FORMAT 0
+
+#define DO_XYZW (IND & RADEON_XYZW_BIT)
+#define DO_RGBA (IND & RADEON_RGBA_BIT)
+#define DO_SPEC (IND & RADEON_SPEC_BIT)
+#define DO_FOG  (IND & RADEON_SPEC_BIT)
+#define DO_TEX0 (IND & RADEON_TEX0_BIT)
+#define DO_TEX1 (IND & RADEON_TEX1_BIT)
+#define DO_TEX2 0
+#define DO_TEX3 0
+#define DO_PTEX (IND & RADEON_PTEX_BIT)
+
+#define VERTEX radeonVertex
+#define VERTEX_COLOR radeon_color_t
+#define GET_VIEWPORT_MAT() 0
+#define GET_TEXSOURCE(n)  n
+#define GET_VERTEX_FORMAT() RADEON_CONTEXT(ctx)->swtcl.vertex_format
+#define GET_VERTEX_STORE() RADEON_CONTEXT(ctx)->swtcl.verts
+#define GET_VERTEX_STRIDE_SHIFT() RADEON_CONTEXT(ctx)->swtcl.vertex_stride_shift
+#define GET_UBYTE_COLOR_STORE() &RADEON_CONTEXT(ctx)->UbyteColor
+#define GET_UBYTE_SPEC_COLOR_STORE() &RADEON_CONTEXT(ctx)->UbyteSecondaryColor
+
+#define HAVE_HW_VIEWPORT    1
+/* Tiny vertices don't seem to work atm - haven't looked into why.
+ */
+#define HAVE_HW_DIVIDE      (IND & ~(RADEON_XYZW_BIT|RADEON_RGBA_BIT))
+#define HAVE_TINY_VERTICES  1
+#define HAVE_RGBA_COLOR     1
+#define HAVE_NOTEX_VERTICES 1
+#define HAVE_TEX0_VERTICES  1
+#define HAVE_TEX1_VERTICES  1
+#define HAVE_TEX2_VERTICES  0
+#define HAVE_TEX3_VERTICES  0
+#define HAVE_PTEX_VERTICES  1
+
+#define CHECK_HW_DIVIDE    (!(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE| \
+                                                    DD_TRI_UNFILLED)))
+
+#define IMPORT_QUALIFIER
+#define IMPORT_FLOAT_COLORS radeon_import_float_colors
+#define IMPORT_FLOAT_SPEC_COLORS radeon_import_float_spec_colors
+
+#define INTERP_VERTEX setup_tab[RADEON_CONTEXT(ctx)->swtcl.SetupIndex].interp
+#define COPY_PV_VERTEX setup_tab[RADEON_CONTEXT(ctx)->swtcl.SetupIndex].copy_pv
+
+
+/***********************************************************************
+ *         Generate  pv-copying and translation functions              *
+ ***********************************************************************/
+
+#define TAG(x) radeon_##x
+#define IND ~0
+#include "tnl_dd/t_dd_vb.c"
+#undef IND
+
+
+/***********************************************************************
+ *             Generate vertex emit and interp functions               *
+ ***********************************************************************/
+
+#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT)
+#define TAG(x) x##_wg
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_TEX0_BIT)
+#define TAG(x) x##_wgt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_TEX0_BIT|RADEON_PTEX_BIT)
+#define TAG(x) x##_wgpt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_TEX0_BIT|RADEON_TEX1_BIT)
+#define TAG(x) x##_wgt0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_TEX0_BIT|RADEON_TEX1_BIT|\
+             RADEON_PTEX_BIT)
+#define TAG(x) x##_wgpt0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT)
+#define TAG(x) x##_wgfs
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT|\
+            RADEON_TEX0_BIT)
+#define TAG(x) x##_wgfst0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT|\
+            RADEON_TEX0_BIT|RADEON_PTEX_BIT)
+#define TAG(x) x##_wgfspt0
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT|\
+            RADEON_TEX0_BIT|RADEON_TEX1_BIT)
+#define TAG(x) x##_wgfst0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+#define IND (RADEON_XYZW_BIT|RADEON_RGBA_BIT|RADEON_SPEC_BIT|\
+            RADEON_TEX0_BIT|RADEON_TEX1_BIT|RADEON_PTEX_BIT)
+#define TAG(x) x##_wgfspt0t1
+#include "tnl_dd/t_dd_vbtmp.h"
+
+
+/***********************************************************************
+ *                         Initialization 
+ ***********************************************************************/
+
+static void init_setup_tab( void )
+{
+   init_wg();
+   init_wgt0();
+   init_wgpt0();
+   init_wgt0t1();
+   init_wgpt0t1();
+   init_wgfs();
+   init_wgfst0();
+   init_wgfspt0();
+   init_wgfst0t1();
+   init_wgfspt0t1();
+}
+
+
+
+void radeonPrintSetupFlags(char *msg, GLuint flags )
+{
+   fprintf(stderr, "%s(%x): %s%s%s%s%s%s\n",
+          msg,
+          (int)flags,
+          (flags & RADEON_XYZW_BIT)      ? " xyzw," : "",
+          (flags & RADEON_RGBA_BIT)     ? " rgba," : "",
+          (flags & RADEON_SPEC_BIT)     ? " spec/fog," : "",
+          (flags & RADEON_TEX0_BIT)     ? " tex-0," : "",
+          (flags & RADEON_TEX1_BIT)     ? " tex-1," : "",
+          (flags & RADEON_PTEX_BIT)     ? " proj-tex," : "");
+}
+
+
+static void radeonRenderStart( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+
+   if (!setup_tab[rmesa->swtcl.SetupIndex].check_tex_sizes(ctx)) {
+      GLuint ind = rmesa->swtcl.SetupIndex |= (RADEON_PTEX_BIT|RADEON_RGBA_BIT);
+
+      /* Projective textures are handled nicely; just have to change
+       * up to the new vertex format.
+       */
+      if (setup_tab[ind].vertex_format != rmesa->swtcl.vertex_format) {
+        RADEON_NEWPRIM(rmesa);
+        rmesa->swtcl.vertex_format = setup_tab[ind].vertex_format;
+        rmesa->swtcl.vertex_size = setup_tab[ind].vertex_size;
+        rmesa->swtcl.vertex_stride_shift = setup_tab[ind].vertex_stride_shift;
+      }
+
+      if (!(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
+        tnl->Driver.Render.Interp = setup_tab[rmesa->swtcl.SetupIndex].interp;
+        tnl->Driver.Render.CopyPV = setup_tab[rmesa->swtcl.SetupIndex].copy_pv;
+      }
+   }
+   
+   if (rmesa->dma.flush != 0 && 
+       rmesa->dma.flush != flush_last_swtcl_prim_compat &&
+       rmesa->dma.flush != flush_last_swtcl_prim)
+      rmesa->dma.flush( rmesa );
+}
+
+
+void radeonBuildVertices( GLcontext *ctx, GLuint start, GLuint count,
+                          GLuint newinputs )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+   GLubyte *v = ((GLubyte *)rmesa->swtcl.verts + 
+                (start << rmesa->swtcl.vertex_stride_shift));
+   GLuint stride = 1 << rmesa->swtcl.vertex_stride_shift;
+
+   newinputs |= rmesa->swtcl.SetupNewInputs;
+   rmesa->swtcl.SetupNewInputs = 0;
+
+   if (!newinputs)
+      return;
+
+   setup_tab[rmesa->swtcl.SetupIndex].emit( ctx, start, count, v, stride );
+}
+
+void radeonChooseVertexState( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   GLuint ind = (RADEON_XYZW_BIT | RADEON_RGBA_BIT);
+
+   if (!rmesa->TclFallback || rmesa->Fallback)
+      return;
+
+   if (ctx->Fog.Enabled || (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR))
+      ind |= RADEON_SPEC_BIT;
+
+   if (ctx->Texture._EnabledUnits & 0x2)
+      /* unit 1 enabled */
+      ind |= RADEON_TEX0_BIT|RADEON_TEX1_BIT;
+   else if (ctx->Texture._EnabledUnits & 0x1)
+      /* unit 0 enabled */
+      ind |= RADEON_TEX0_BIT;
+
+   rmesa->swtcl.SetupIndex = ind;
+
+   if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) {
+      tnl->Driver.Render.Interp = radeon_interp_extras;
+      tnl->Driver.Render.CopyPV = radeon_copy_pv_extras;
+   }
+   else {
+      tnl->Driver.Render.Interp = setup_tab[ind].interp;
+      tnl->Driver.Render.CopyPV = setup_tab[ind].copy_pv;
+   }
+
+   if (setup_tab[ind].vertex_format != rmesa->swtcl.vertex_format) {
+      RADEON_NEWPRIM(rmesa);
+      rmesa->swtcl.vertex_format = setup_tab[ind].vertex_format;
+      rmesa->swtcl.vertex_size = setup_tab[ind].vertex_size;
+      rmesa->swtcl.vertex_stride_shift = setup_tab[ind].vertex_stride_shift;
+   }
+
+   {
+      GLuint se_coord_fmt, needproj;
+
+      /* HW perspective divide is a win, but tiny vertex formats are a
+       * bigger one.
+       */
+      if (setup_tab[ind].vertex_format == TINY_VERTEX_FORMAT ||
+         (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
+        needproj = GL_TRUE;
+        se_coord_fmt = (RADEON_VTX_XY_PRE_MULT_1_OVER_W0 |
+                        RADEON_VTX_Z_PRE_MULT_1_OVER_W0 |
+                        RADEON_TEX1_W_ROUTING_USE_Q1);
+      }
+      else {
+        needproj = GL_FALSE;
+        se_coord_fmt = (RADEON_VTX_W0_IS_NOT_1_OVER_W0 |
+                        RADEON_TEX1_W_ROUTING_USE_Q1);
+      }
+
+      if ( se_coord_fmt != rmesa->hw.set.cmd[SET_SE_COORDFMT] ) {
+        RADEON_STATECHANGE( rmesa, set );
+        rmesa->hw.set.cmd[SET_SE_COORDFMT] = se_coord_fmt;
+      }
+      _tnl_need_projected_coords( ctx, needproj );
+   }
+}
+
+
+/* Flush vertices in the current dma region.
+ */
+static void flush_last_swtcl_prim( radeonContextPtr rmesa  )
+{
+   if (RADEON_DEBUG & DEBUG_IOCTL)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   rmesa->dma.flush = 0;
+
+   if (rmesa->dma.current.buf) {
+      struct radeon_dma_region *current = &rmesa->dma.current;
+      GLuint current_offset = (rmesa->radeonScreen->agp_buffer_offset +
+                              current->buf->buf->idx * RADEON_BUFFER_SIZE + 
+                              current->start);
+
+      assert (!(rmesa->swtcl.hw_primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND));
+
+      assert (current->start + 
+             rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
+             current->ptr);
+
+      if (rmesa->dma.current.start != rmesa->dma.current.ptr) {
+        radeonEmitVertexAOS( rmesa,
+                             rmesa->swtcl.vertex_size,
+                             current_offset);
+
+        radeonEmitVbufPrim( rmesa,
+                            rmesa->swtcl.vertex_format,
+                            rmesa->swtcl.hw_primitive,
+                            rmesa->swtcl.numverts);
+      }
+
+      rmesa->swtcl.numverts = 0;
+      current->start = current->ptr;
+   }
+}
+
+
+static void flush_last_swtcl_prim_compat( radeonContextPtr rmesa )
+{
+   struct radeon_dma_region *current = &rmesa->dma.current;
+
+   if (RADEON_DEBUG & DEBUG_IOCTL)
+      fprintf(stderr, "%s buf %p start %d ptr %d\n", 
+             __FUNCTION__,
+             current->buf,
+             current->start,
+             current->ptr);
+
+   assert (!(rmesa->swtcl.hw_primitive & RADEON_CP_VC_CNTL_PRIM_WALK_IND));
+   assert (current->start + 
+          rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
+          current->ptr);
+   assert (current->start == 0);
+
+   rmesa->dma.flush = 0;
+
+   if (current->ptr && current->buf) {
+      assert (current->buf->refcount == 1);
+
+      radeonCompatEmitPrimitive( rmesa,
+                                rmesa->swtcl.vertex_format,
+                                rmesa->swtcl.hw_primitive,
+                                rmesa->swtcl.numverts);
+      
+      /* The buffer has been released:
+       */
+      FREE(current->buf);
+      current->buf = 0;
+      current->start = 0;
+      current->ptr = current->end;
+
+   }
+
+   rmesa->swtcl.numverts = 0;
+}
+
+
+/* Alloc space in the current dma region.
+ */
+static __inline void *radeonAllocDmaLowVerts( radeonContextPtr rmesa,
+                                             int nverts, int vsize )
+{
+   GLuint bytes = vsize * nverts;
+
+   if ( rmesa->dma.current.ptr + bytes > rmesa->dma.current.end ) 
+      radeonRefillCurrentDmaRegion( rmesa );
+
+   if (!rmesa->dma.flush) {
+      rmesa->glCtx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
+      if (rmesa->dri.drmMinor == 1)
+        rmesa->dma.flush = flush_last_swtcl_prim_compat;
+      else
+        rmesa->dma.flush = flush_last_swtcl_prim;
+   }
+
+   assert( vsize == rmesa->swtcl.vertex_size * 4 );
+   assert( rmesa->dma.flush == flush_last_swtcl_prim ||
+          rmesa->dma.flush == flush_last_swtcl_prim_compat);
+   assert (rmesa->dma.current.start + 
+          rmesa->swtcl.numverts * rmesa->swtcl.vertex_size * 4 ==
+          rmesa->dma.current.ptr);
+
+
+   {
+      char *head = rmesa->dma.current.address + rmesa->dma.current.ptr;
+      rmesa->dma.current.ptr += bytes;
+      rmesa->swtcl.numverts += nverts;
+      return head;
+   }
+
+}
+
+
+
+
+void radeon_emit_contiguous_verts( GLcontext *ctx, GLuint start, GLuint count )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLuint vertex_size = rmesa->swtcl.vertex_size * 4;
+   CARD32 *dest = radeonAllocDmaLowVerts( rmesa, count-start, vertex_size );
+   setup_tab[rmesa->swtcl.SetupIndex].emit( ctx, start, count, dest, 
+                                           vertex_size );
+}
+
+
+
+void radeon_emit_indexed_verts( GLcontext *ctx, GLuint start, GLuint count )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   radeonAllocDmaRegionVerts( rmesa, 
+                             &rmesa->swtcl.indexed_verts, 
+                             count - start,
+                             rmesa->swtcl.vertex_size * 4, 
+                             64);
+
+   setup_tab[rmesa->swtcl.SetupIndex].emit( 
+      ctx, start, count, 
+      rmesa->swtcl.indexed_verts.address + rmesa->swtcl.indexed_verts.start, 
+      rmesa->swtcl.vertex_size * 4 );
+}
+
+
+/*
+ * Render unclipped vertex buffers by emitting vertices directly to
+ * dma buffers.  Use strip/fan hardware primitives where possible.
+ * Try to simulate missing primitives with indexed vertices.
+ */
+#define HAVE_POINTS      1
+#define HAVE_LINES       1
+#define HAVE_LINE_STRIPS 1
+#define HAVE_TRIANGLES   1
+#define HAVE_TRI_STRIPS  1
+#define HAVE_TRI_STRIP_1 0
+#define HAVE_TRI_FANS    1
+#define HAVE_QUADS       0
+#define HAVE_QUAD_STRIPS 0
+#define HAVE_POLYGONS    0
+#define HAVE_ELTS        1
+
+static const GLuint hw_prim[GL_POLYGON+1] = {
+   RADEON_CP_VC_CNTL_PRIM_TYPE_POINT,
+   RADEON_CP_VC_CNTL_PRIM_TYPE_LINE,
+   0,
+   RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP,
+   RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST,
+   RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP,
+   RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN,
+   0,
+   0,
+   0
+};
+
+static __inline void radeonDmaPrimitive( radeonContextPtr rmesa, GLenum prim )
+{
+   RADEON_NEWPRIM( rmesa );
+   rmesa->swtcl.hw_primitive = hw_prim[prim];
+   assert(rmesa->dma.current.ptr == rmesa->dma.current.start);
+}
+
+static __inline void radeonEltPrimitive( radeonContextPtr rmesa, GLenum prim )
+{
+   RADEON_NEWPRIM( rmesa );
+   rmesa->swtcl.hw_primitive = hw_prim[prim] | RADEON_CP_VC_CNTL_PRIM_WALK_IND;
+}
+
+
+static void VERT_FALLBACK( GLcontext *ctx,
+                          GLuint start,
+                          GLuint count,
+                          GLuint flags )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   tnl->Driver.Render.PrimitiveNotify( ctx, flags & PRIM_MODE_MASK );
+   tnl->Driver.Render.BuildVertices( ctx, start, count, ~0 );
+   tnl->Driver.Render.PrimTabVerts[flags&PRIM_MODE_MASK]( ctx, start, count, flags );
+   RADEON_CONTEXT(ctx)->swtcl.SetupNewInputs = VERT_BIT_CLIP;
+}
+
+static void ELT_FALLBACK( GLcontext *ctx,
+                         GLuint start,
+                         GLuint count,
+                         GLuint flags )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   tnl->Driver.Render.PrimitiveNotify( ctx, flags & PRIM_MODE_MASK );
+   tnl->Driver.Render.BuildVertices( ctx, start, count, ~0 );
+   tnl->Driver.Render.PrimTabElts[flags&PRIM_MODE_MASK]( ctx, start, count, flags );
+   RADEON_CONTEXT(ctx)->swtcl.SetupNewInputs = VERT_BIT_CLIP;
+}
+
+
+#define LOCAL_VARS radeonContextPtr rmesa = RADEON_CONTEXT(ctx)
+#define ELTS_VARS  GLushort *dest
+#define INIT( prim ) radeonDmaPrimitive( rmesa, prim )
+#define ELT_INIT(prim) radeonEltPrimitive( rmesa, prim )
+#define NEW_PRIMITIVE()  RADEON_NEWPRIM( rmesa )
+#define NEW_BUFFER()  radeonRefillCurrentDmaRegion( rmesa )
+#define GET_CURRENT_VB_MAX_VERTS() \
+  (((int)rmesa->dma.current.end - (int)rmesa->dma.current.ptr) / (rmesa->swtcl.vertex_size*4))
+#define GET_SUBSEQUENT_VB_MAX_VERTS() \
+  ((RADEON_BUFFER_SIZE) / (rmesa->swtcl.vertex_size*4))
+
+#if RADEON_OLD_PACKETS
+# define GET_CURRENT_VB_MAX_ELTS() \
+  ((RADEON_CMD_BUF_SZ - (rmesa->store.cmd_used + 24)) / 2)
+#else
+# define GET_CURRENT_VB_MAX_ELTS() \
+  ((RADEON_CMD_BUF_SZ - (rmesa->store.cmd_used + 16)) / 2)
+#endif
+#define GET_SUBSEQUENT_VB_MAX_ELTS() \
+  ((RADEON_CMD_BUF_SZ - 1024) / 2)
+
+
+
+/* How do you extend an existing primitive?
+ */
+#define ALLOC_ELTS(nr)                                                 \
+do {                                                                   \
+   if (rmesa->dma.flush == radeonFlushElts &&                          \
+       rmesa->store.cmd_used + nr*2 < RADEON_CMD_BUF_SZ) {             \
+                                                                       \
+      dest = (GLushort *)(rmesa->store.cmd_buf +                       \
+                         rmesa->store.cmd_used);                       \
+      rmesa->store.cmd_used += nr*2;                                   \
+   }                                                                   \
+   else {                                                              \
+      if (rmesa->dma.flush) {                                          \
+        rmesa->dma.flush( rmesa );                                     \
+      }                                                                        \
+                                                                       \
+      radeonEmitVertexAOS( rmesa,                                      \
+                          rmesa->swtcl.vertex_size,                    \
+                          (rmesa->radeonScreen->agp_buffer_offset +            \
+                           rmesa->swtcl.indexed_verts.buf->buf->idx *  \
+                           RADEON_BUFFER_SIZE +                        \
+                           rmesa->swtcl.indexed_verts.start));         \
+                                                                       \
+      dest = radeonAllocEltsOpenEnded( rmesa,                          \
+                                      rmesa->swtcl.vertex_format,      \
+                                      rmesa->swtcl.hw_primitive,       \
+                                      nr );                            \
+   }                                                                   \
+} while (0)
+
+#define ALLOC_ELTS_NEW_PRIMITIVE(nr) ALLOC_ELTS( nr )
+
+#ifdef MESA_BIG_ENDIAN
+/* We could do without (most of) this ugliness if dest was always 32 bit word aligned... */
+#define EMIT_ELT(offset, x) do {                               \
+       int off = offset + ( ( (GLuint)dest & 0x2 ) >> 1 );     \
+       GLushort *des = (GLushort *)( (GLuint)dest & ~0x2 );    \
+       (des)[ off + 1 - 2 * ( off & 1 ) ] = (GLushort)(x); } while (0)
+#else
+#define EMIT_ELT(offset, x) (dest)[offset] = (GLushort) (x)
+#endif
+#define EMIT_TWO_ELTS(offset, x, y)  *(GLuint *)(dest+offset) = ((y)<<16)|(x);
+#define INCR_ELTS( nr ) dest += nr
+#define RELEASE_ELT_VERTS() \
+  radeonReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, __FUNCTION__ )
+#define EMIT_VERTS( ctx, j, nr ) \
+  radeon_emit_contiguous_verts(ctx, j, (j)+(nr))
+#define EMIT_INDEXED_VERTS( ctx, start, count ) \
+  radeon_emit_indexed_verts( ctx, start, count )
+
+
+#define TAG(x) radeon_dma_##x
+#include "tnl_dd/t_dd_dmatmp.h"
+
+
+/**********************************************************************/
+/*                          Render pipeline stage                     */
+/**********************************************************************/
+
+
+static GLboolean radeon_run_render( GLcontext *ctx,
+                                   struct gl_pipeline_stage *stage )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct vertex_buffer *VB = &tnl->vb;
+   GLuint i, length, flags = 0;
+   render_func *tab = TAG(render_tab_verts);
+
+   if (rmesa->swtcl.indexed_verts.buf && (!VB->Elts || stage->changed_inputs)) 
+      RELEASE_ELT_VERTS();
+       
+   if (VB->ClipOrMask ||            /* No clipping */
+       rmesa->swtcl.RenderIndex != 0 ||    /* No per-vertex manipulations */
+       ctx->Line.StippleFlag)        /* GH: THIS IS A HACK!!! */
+      return GL_TRUE;          
+
+   if (rmesa->dri.drmMinor < 3) {
+      /* drm 1.1 doesn't support vertex primitives starting in the
+       * middle of a buffer.  It doesn't support sane indexed vertices
+       * either.  drm 1.2 fixes both of these problems, but we don't have a
+       * compatibility layer to that version yet.  
+       */
+      return GL_TRUE;
+   }
+
+   tnl->Driver.Render.Start( ctx );
+
+   if (VB->Elts) {
+      tab = TAG(render_tab_elts);
+      if (!rmesa->swtcl.indexed_verts.buf)
+        if (!TAG(emit_elt_verts)(ctx, 0, VB->Count))
+           return GL_TRUE;     /* too many vertices */
+   }
+
+   for (i = 0 ; !(flags & PRIM_LAST) ; i += length)
+   {
+      flags = VB->Primitive[i];
+      length = VB->PrimitiveLength[i];
+
+      if (RADEON_DEBUG & DEBUG_PRIMS)
+        fprintf(stderr, "radeon_render.c: prim %s %d..%d\n", 
+                _mesa_lookup_enum_by_nr(flags & PRIM_MODE_MASK), 
+                i, i+length);
+
+      if (length)
+        tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags );
+   }
+
+   tnl->Driver.Render.Finish( ctx );
+
+   return GL_FALSE;            /* finished the pipe */
+}
+
+
+
+static void radeon_check_render( GLcontext *ctx,
+                                struct gl_pipeline_stage *stage )
+{
+   GLuint inputs = VERT_BIT_POS | VERT_BIT_CLIP | VERT_BIT_COLOR0;
+
+   if (ctx->RenderMode == GL_RENDER) {
+      if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
+        inputs |= VERT_BIT_COLOR1;
+
+      if (ctx->Texture.Unit[0]._ReallyEnabled)
+        inputs |= VERT_BIT_TEX0;
+
+      if (ctx->Texture.Unit[1]._ReallyEnabled)
+        inputs |= VERT_BIT_TEX1;
+
+      if (ctx->Fog.Enabled)
+        inputs |= VERT_BIT_FOG;
+   }
+
+   stage->inputs = inputs;
+}
+
+
+static void dtr( struct gl_pipeline_stage *stage )
+{
+   (void)stage;
+}
+
+
+const struct gl_pipeline_stage _radeon_render_stage =
+{
+   "radeon render",
+   (_DD_NEW_SEPARATE_SPECULAR |
+    _NEW_TEXTURE|
+    _NEW_FOG|
+    _NEW_RENDERMODE),          /* re-check (new inputs) */
+   0,                          /* re-run (always runs) */
+   GL_TRUE,                    /* active */
+   0, 0,                       /* inputs (set in check_render), outputs */
+   0, 0,                       /* changed_inputs, private */
+   dtr,                                /* destructor */
+   radeon_check_render,                /* check - initially set to alloc data */
+   radeon_run_render           /* run */
+};
+
+
+/**************************************************************************/
+
+/* Radeon texture rectangle expects coords in 0..1 range, not 0..dimension
+ * as in the extension spec.  Need to translate here.
+ *
+ * Note that swrast expects 0..dimension, so if a fallback is active,
+ * don't do anything.  (Maybe need to configure swrast to match hw)
+ */
+struct texrect_stage_data {
+   GLvector4f texcoord[MAX_TEXTURE_UNITS];
+};
+
+#define TEXRECT_STAGE_DATA(stage) ((struct texrect_stage_data *)stage->privatePtr)
+
+
+static GLboolean run_texrect_stage( GLcontext *ctx,
+                                   struct gl_pipeline_stage *stage )
+{
+   struct texrect_stage_data *store = TEXRECT_STAGE_DATA(stage);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct vertex_buffer *VB = &tnl->vb;
+   GLuint i;
+
+   if (rmesa->Fallback)
+      return GL_TRUE;
+
+   for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
+      if (!(ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_RECT_BIT))
+        continue;
+   
+      if (stage->changed_inputs & VERT_BIT_TEX(i)) {
+        struct gl_texture_object *texObj = ctx->Texture.Unit[i].CurrentRect;
+        struct gl_texture_image *texImage = texObj->Image[texObj->BaseLevel];
+        const GLfloat iw = 1.0/texImage->Width;
+        const GLfloat ih = 1.0/texImage->Height;
+        GLfloat *in = (GLfloat *)VB->TexCoordPtr[i]->data;
+        GLint instride = VB->TexCoordPtr[i]->stride;
+        GLfloat (*out)[4] = store->texcoord[i].data;
+        GLint j;
+        
+        for (j = 0 ; j < VB->Count ; j++) {
+           out[j][0] = in[0] * iw;
+           out[j][1] = in[1] * ih;
+           in = (GLfloat *)((GLubyte *)in + instride);
+        }
+      }
+
+      VB->TexCoordPtr[i] = &store->texcoord[i];
+   }
+
+   return GL_TRUE;
+}
+
+
+/* Called the first time stage->run() is invoked.
+ */
+static GLboolean alloc_texrect_data( GLcontext *ctx,
+                                    struct gl_pipeline_stage *stage )
+{
+   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+   struct texrect_stage_data *store;
+   GLuint i;
+
+   stage->privatePtr = CALLOC(sizeof(*store));
+   store = TEXRECT_STAGE_DATA(stage);
+   if (!store)
+      return GL_FALSE;
+
+   for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
+      _mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 );
+
+   /* Now run the stage.
+    */
+   stage->run = run_texrect_stage;
+   return stage->run( ctx, stage );
+}
+
+
+static void check_texrect( GLcontext *ctx,
+                          struct gl_pipeline_stage *stage )
+{
+   GLuint flags = 0;
+
+   if (ctx->Texture.Unit[0]._ReallyEnabled & TEXTURE_RECT_BIT)
+      flags |= VERT_BIT_TEX0;
+
+   if (ctx->Texture.Unit[1]._ReallyEnabled & TEXTURE_RECT_BIT)
+      flags |= VERT_BIT_TEX1;
+
+   stage->inputs = flags;
+   stage->outputs = flags;
+   stage->active = (flags != 0);
+}
+
+
+static void free_texrect_data( struct gl_pipeline_stage *stage )
+{
+   struct texrect_stage_data *store = TEXRECT_STAGE_DATA(stage);
+   GLuint i;
+
+   if (store) {
+      for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
+        if (store->texcoord[i].data)
+           _mesa_vector4f_free( &store->texcoord[i] );
+      FREE( store );
+      stage->privatePtr = 0;
+   }
+}
+
+
+const struct gl_pipeline_stage _radeon_texrect_stage =
+{
+   "radeon texrect stage",                     /* name */
+   _NEW_TEXTURE,       /* check_state */
+   _NEW_TEXTURE,       /* run_state */
+   GL_TRUE,                            /* active? */
+   0,                                  /* inputs */
+   0,                                  /* outputs */
+   0,                                  /* changed_inputs */
+   NULL,                               /* private data */
+   free_texrect_data,                  /* destructor */
+   check_texrect,                      /* check */
+   alloc_texrect_data,                 /* run -- initially set to init */
+};
+
+
+/**************************************************************************/
+
+
+static const GLuint reduced_hw_prim[GL_POLYGON+1] = {
+   RADEON_CP_VC_CNTL_PRIM_TYPE_POINT,
+   RADEON_CP_VC_CNTL_PRIM_TYPE_LINE,
+   RADEON_CP_VC_CNTL_PRIM_TYPE_LINE,
+   RADEON_CP_VC_CNTL_PRIM_TYPE_LINE,
+   RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST,
+   RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST,
+   RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST,
+   RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST,
+   RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST,
+   RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST
+};
+
+static void radeonRasterPrimitive( GLcontext *ctx, GLuint hwprim );
+static void radeonRenderPrimitive( GLcontext *ctx, GLenum prim );
+static void radeonResetLineStipple( GLcontext *ctx );
+
+
+/***********************************************************************
+ *                    Emit primitives as inline vertices               *
+ ***********************************************************************/
+
+#undef LOCAL_VARS
+#define CTX_ARG radeonContextPtr rmesa
+#define CTX_ARG2 rmesa
+#define GET_VERTEX_DWORDS() rmesa->swtcl.vertex_size
+#define ALLOC_VERTS( n, size ) radeonAllocDmaLowVerts( rmesa, n, size * 4 )
+#undef LOCAL_VARS
+#define LOCAL_VARS                                             \
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);               \
+   const GLuint shift = rmesa->swtcl.vertex_stride_shift;      \
+   const char *radeonverts = (char *)rmesa->swtcl.verts;
+#define VERT(x) (radeonVertex *)(radeonverts + (x << shift))
+#define VERTEX radeonVertex 
+#undef TAG
+#define TAG(x) radeon_##x
+#include "tnl_dd/t_dd_triemit.h"
+
+
+/***********************************************************************
+ *          Macros for t_dd_tritmp.h to draw basic primitives          *
+ ***********************************************************************/
+
+#define QUAD( a, b, c, d ) radeon_quad( rmesa, a, b, c, d )
+#define TRI( a, b, c )     radeon_triangle( rmesa, a, b, c )
+#define LINE( a, b )       radeon_line( rmesa, a, b )
+#define POINT( a )         radeon_point( rmesa, a )
+
+/***********************************************************************
+ *              Build render functions from dd templates               *
+ ***********************************************************************/
+
+#define RADEON_TWOSIDE_BIT     0x01
+#define RADEON_UNFILLED_BIT    0x02
+#define RADEON_OFFSET_BIT      0x04 /* drmMinor == 1 */
+#define RADEON_MAX_TRIFUNC     0x08
+
+
+static struct {
+   points_func         points;
+   line_func           line;
+   triangle_func       triangle;
+   quad_func           quad;
+} rast_tab[RADEON_MAX_TRIFUNC];
+
+
+#define DO_FALLBACK  0
+#define DO_OFFSET   (IND & RADEON_OFFSET_BIT)
+#define DO_UNFILLED (IND & RADEON_UNFILLED_BIT)
+#define DO_TWOSIDE  (IND & RADEON_TWOSIDE_BIT)
+#define DO_FLAT      0
+#define DO_TRI       1
+#define DO_QUAD      1
+#define DO_LINE      1
+#define DO_POINTS    1
+#define DO_FULL_QUAD 1
+
+#define HAVE_RGBA   1
+#define HAVE_SPEC   1
+#define HAVE_INDEX  0
+#define HAVE_BACK_COLORS  0
+#define HAVE_HW_FLATSHADE 1
+#define TAB rast_tab
+
+#define DEPTH_SCALE 1.0
+#define UNFILLED_TRI unfilled_tri
+#define UNFILLED_QUAD unfilled_quad
+#define VERT_X(_v) _v->v.x
+#define VERT_Y(_v) _v->v.y
+#define VERT_Z(_v) _v->v.z
+#define AREA_IS_CCW( a ) (a < 0)
+#define GET_VERTEX(e) (rmesa->swtcl.verts + (e<<rmesa->swtcl.vertex_stride_shift))
+
+#define VERT_SET_RGBA( v, c )    v->ui[coloroffset] = LE32_TO_CPU(*(GLuint *)c)
+#define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
+#define VERT_SAVE_RGBA( idx )    color[idx] = CPU_TO_LE32(v[idx]->ui[coloroffset])
+#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = LE32_TO_CPU(color[idx])
+
+#define VERT_SET_SPEC( v0, c )   if (havespec) {                       \
+                                       v0->v.specular.red   = (c)[0];  \
+                                       v0->v.specular.green = (c)[1];  \
+                                       v0->v.specular.blue  = (c)[2]; }
+#define VERT_COPY_SPEC( v0, v1 ) if (havespec) {                                       \
+                                       v0->v.specular.red   = v1->v.specular.red;      \
+                                       v0->v.specular.green = v1->v.specular.green;    \
+                                       v0->v.specular.blue  = v1->v.specular.blue; }
+#define VERT_SAVE_SPEC( idx )    if (havespec) spec[idx] = CPU_TO_LE32(v[idx]->ui[5])
+#define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = LE32_TO_CPU(spec[idx])
+
+#undef LOCAL_VARS
+#undef TAG
+#undef INIT
+
+#define LOCAL_VARS(n)                                                  \
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);                       \
+   GLuint color[n], spec[n];                                           \
+   GLuint coloroffset = (rmesa->swtcl.vertex_size == 4 ? 3 : 4);       \
+   GLboolean havespec = (rmesa->swtcl.vertex_size > 4);                        \
+   (void) color; (void) spec; (void) coloroffset; (void) havespec;
+
+/***********************************************************************
+ *                Helpers for rendering unfilled primitives            *
+ ***********************************************************************/
+
+#define RASTERIZE(x) radeonRasterPrimitive( ctx, reduced_hw_prim[x] )
+#define RENDER_PRIMITIVE rmesa->swtcl.render_primitive
+#undef TAG
+#define TAG(x) x
+#include "tnl_dd/t_dd_unfilled.h"
+#undef IND
+
+
+/***********************************************************************
+ *                      Generate GL render functions                   *
+ ***********************************************************************/
+
+
+#define IND (0)
+#define TAG(x) x
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (RADEON_TWOSIDE_BIT)
+#define TAG(x) x##_twoside
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (RADEON_UNFILLED_BIT)
+#define TAG(x) x##_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (RADEON_TWOSIDE_BIT|RADEON_UNFILLED_BIT)
+#define TAG(x) x##_twoside_unfilled
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (RADEON_OFFSET_BIT)
+#define TAG(x) x##_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (RADEON_TWOSIDE_BIT|RADEON_OFFSET_BIT)
+#define TAG(x) x##_twoside_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (RADEON_UNFILLED_BIT|RADEON_OFFSET_BIT)
+#define TAG(x) x##_unfilled_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+#define IND (RADEON_TWOSIDE_BIT|RADEON_UNFILLED_BIT|RADEON_OFFSET_BIT)
+#define TAG(x) x##_twoside_unfilled_offset
+#include "tnl_dd/t_dd_tritmp.h"
+
+
+static void init_rast_tab( void )
+{
+   init();
+   init_twoside();
+   init_unfilled();
+   init_twoside_unfilled();
+   init_offset();
+   init_twoside_offset();
+   init_unfilled_offset();
+   init_twoside_unfilled_offset();
+}
+
+/**********************************************************************/
+/*               Render unclipped begin/end objects                   */
+/**********************************************************************/
+
+#define VERT(x) (radeonVertex *)(radeonverts + (x << shift))
+#define RENDER_POINTS( start, count )          \
+   for ( ; start < count ; start++)            \
+      radeon_point( rmesa, VERT(start) )
+#define RENDER_LINE( v0, v1 ) \
+   radeon_line( rmesa, VERT(v0), VERT(v1) )
+#define RENDER_TRI( v0, v1, v2 )  \
+   radeon_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) )
+#define RENDER_QUAD( v0, v1, v2, v3 ) \
+   radeon_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
+#undef INIT
+#define INIT(x) do {                                   \
+   radeonRenderPrimitive( ctx, x );                    \
+} while (0)
+#undef LOCAL_VARS
+#define LOCAL_VARS                                             \
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);               \
+   const GLuint shift = rmesa->swtcl.vertex_stride_shift;              \
+   const char *radeonverts = (char *)rmesa->swtcl.verts;               \
+   const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;       \
+   const GLboolean stipple = ctx->Line.StippleFlag;            \
+   (void) elt; (void) stipple;
+#define RESET_STIPPLE  if ( stipple ) radeonResetLineStipple( ctx );
+#define RESET_OCCLUSION
+#define PRESERVE_VB_DEFS
+#define ELT(x) (x)
+#define TAG(x) radeon_##x##_verts
+#include "tnl/t_vb_rendertmp.h"
+#undef ELT
+#undef TAG
+#define TAG(x) radeon_##x##_elts
+#define ELT(x) elt[x]
+#include "tnl/t_vb_rendertmp.h"
+
+
+
+/**********************************************************************/
+/*                    Choose render functions                         */
+/**********************************************************************/
+
+void radeonChooseRenderState( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLuint index = 0;
+   GLuint flags = ctx->_TriangleCaps;
+
+   if (!rmesa->TclFallback || rmesa->Fallback) 
+      return;
+
+   if (flags & DD_TRI_LIGHT_TWOSIDE) index |= RADEON_TWOSIDE_BIT;
+   if (flags & DD_TRI_UNFILLED)      index |= RADEON_UNFILLED_BIT;
+   if ((flags & DD_TRI_OFFSET) &&
+       rmesa->dri.drmMinor == 1)  index |= RADEON_OFFSET_BIT;
+
+   if (index != rmesa->swtcl.RenderIndex) {
+      tnl->Driver.Render.Points = rast_tab[index].points;
+      tnl->Driver.Render.Line = rast_tab[index].line;
+      tnl->Driver.Render.ClippedLine = rast_tab[index].line;
+      tnl->Driver.Render.Triangle = rast_tab[index].triangle;
+      tnl->Driver.Render.Quad = rast_tab[index].quad;
+
+      if (index == 0) {
+        tnl->Driver.Render.PrimTabVerts = radeon_render_tab_verts;
+        tnl->Driver.Render.PrimTabElts = radeon_render_tab_elts;
+        tnl->Driver.Render.ClippedPolygon = radeon_fast_clipped_poly;
+      } else {
+        tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
+        tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
+        tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
+      }
+
+      rmesa->swtcl.RenderIndex = index;
+   }
+}
+
+
+/**********************************************************************/
+/*                 High level hooks for t_vb_render.c                 */
+/**********************************************************************/
+
+
+static void radeonRasterPrimitive( GLcontext *ctx, GLuint hwprim )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   if (rmesa->swtcl.hw_primitive != hwprim) {
+      RADEON_NEWPRIM( rmesa );
+      rmesa->swtcl.hw_primitive = hwprim;
+   }
+}
+
+static void radeonRenderPrimitive( GLcontext *ctx, GLenum prim )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   rmesa->swtcl.render_primitive = prim;
+   if (prim < GL_TRIANGLES || !(ctx->_TriangleCaps & DD_TRI_UNFILLED)) 
+      radeonRasterPrimitive( ctx, reduced_hw_prim[prim] );
+}
+
+static void radeonRenderFinish( GLcontext *ctx )
+{
+}
+
+static void radeonResetLineStipple( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   RADEON_STATECHANGE( rmesa, lin );
+}
+
+
+/**********************************************************************/
+/*           Transition to/from hardware rasterization.               */
+/**********************************************************************/
+
+static const char * const fallbackStrings[] = {
+   "Texture mode",
+   "glDrawBuffer(GL_FRONT_AND_BACK)",
+   "glEnable(GL_STENCIL) without hw stencil buffer",
+   "glRenderMode(selection or feedback)",
+   "glBlendEquation",
+   "glBlendFunc",
+   "RADEON_NO_RAST",
+   "Mixing GL_CLAMP_TO_BORDER and GL_CLAMP (or GL_MIRROR_CLAMP_ATI)"
+};
+
+
+static const char *getFallbackString(GLuint bit)
+{
+   int i = 0;
+   while (bit > 1) {
+      i++;
+      bit >>= 1;
+   }
+   return fallbackStrings[i];
+}
+
+
+void radeonFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   GLuint oldfallback = rmesa->Fallback;
+
+   if (mode) {
+      rmesa->Fallback |= bit;
+      if (oldfallback == 0) {
+        RADEON_FIREVERTICES( rmesa );
+        TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_RASTER, GL_TRUE );
+        _swsetup_Wakeup( ctx );
+        _tnl_need_projected_coords( ctx, GL_TRUE );
+        rmesa->swtcl.RenderIndex = ~0;
+         if (RADEON_DEBUG & DEBUG_FALLBACKS) {
+            fprintf(stderr, "Radeon begin rasterization fallback: 0x%x %s\n",
+                    bit, getFallbackString(bit));
+         }
+      }
+   }
+   else {
+      rmesa->Fallback &= ~bit;
+      if (oldfallback == bit) {
+        _swrast_flush( ctx );
+        tnl->Driver.Render.Start = radeonRenderStart;
+        tnl->Driver.Render.PrimitiveNotify = radeonRenderPrimitive;
+        tnl->Driver.Render.Finish = radeonRenderFinish;
+        tnl->Driver.Render.BuildVertices = radeonBuildVertices;
+        tnl->Driver.Render.ResetLineStipple = radeonResetLineStipple;
+        TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_RASTER, GL_FALSE );
+        if (rmesa->TclFallback) {
+           /* These are already done if rmesa->TclFallback goes to
+            * zero above. But not if it doesn't (RADEON_NO_TCL for
+            * example?)
+            */
+           radeonChooseVertexState( ctx );
+           radeonChooseRenderState( ctx );
+        }
+         if (RADEON_DEBUG & DEBUG_FALLBACKS) {
+            fprintf(stderr, "Radeon end rasterization fallback: 0x%x %s\n",
+                    bit, getFallbackString(bit));
+         }
+      }
+   }
+}
+
+
+void radeonFlushVertices( GLcontext *ctx, GLuint flags )
+{
+   _tnl_flush_vertices( ctx, flags );
+
+   if (flags & FLUSH_STORED_VERTICES)
+      RADEON_NEWPRIM( RADEON_CONTEXT( ctx ) );
+}
+
+/**********************************************************************/
+/*                            Initialization.                         */
+/**********************************************************************/
+
+void radeonInitSwtcl( GLcontext *ctx )
+{
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLuint size = TNL_CONTEXT(ctx)->vb.Size;
+   static int firsttime = 1;
+
+   if (firsttime) {
+      init_rast_tab();
+      init_setup_tab();
+      firsttime = 0;
+   }
+
+   tnl->Driver.Render.Start = radeonRenderStart;
+   tnl->Driver.Render.Finish = radeonRenderFinish;
+   tnl->Driver.Render.PrimitiveNotify = radeonRenderPrimitive;
+   tnl->Driver.Render.ResetLineStipple = radeonResetLineStipple;
+   tnl->Driver.Render.BuildVertices = radeonBuildVertices;
+
+   rmesa->swtcl.verts = ALIGN_MALLOC( size * 16 * 4, 32 );
+   rmesa->swtcl.RenderIndex = ~0;
+   rmesa->swtcl.render_primitive = GL_TRIANGLES;
+   rmesa->swtcl.hw_primitive = 0;
+}
+
+
+void radeonDestroySwtcl( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   if (rmesa->swtcl.indexed_verts.buf) 
+      radeonReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, 
+                             __FUNCTION__ );
+
+   if (rmesa->swtcl.verts) {
+      ALIGN_FREE(rmesa->swtcl.verts);
+      rmesa->swtcl.verts = 0;
+   }
+
+   if (rmesa->UbyteSecondaryColor.Ptr) {
+      ALIGN_FREE(rmesa->UbyteSecondaryColor.Ptr);
+      rmesa->UbyteSecondaryColor.Ptr = 0;
+   }
+
+   if (rmesa->UbyteColor.Ptr) {
+      ALIGN_FREE(rmesa->UbyteColor.Ptr);
+      rmesa->UbyteColor.Ptr = 0;
+   }
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_swtcl.h b/src/mesa/drivers/dri/radeon/radeon_swtcl.h
new file mode 100644 (file)
index 0000000..c45e711
--- /dev/null
@@ -0,0 +1,77 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+on the rights to use, copy, modify, merge, publish, distribute, sub
+license, and/or sell copies of the Software, and to permit persons to whom
+the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#ifndef __RADEON_TRIS_H__
+#define __RADEON_TRIS_H__
+
+#include "mtypes.h"
+#include "swrast/swrast.h"
+#include "radeon_context.h"
+
+extern void radeonInitSwtcl( GLcontext *ctx );
+extern void radeonDestroySwtcl( GLcontext *ctx );
+
+extern void radeonFlushVertices( GLcontext *ctx, GLuint flags );
+extern void radeonChooseRenderState( GLcontext *ctx );
+extern void radeonChooseVertexState( GLcontext *ctx );
+
+extern void radeonCheckTexSizes( GLcontext *ctx );
+
+extern void radeonBuildVertices( GLcontext *ctx, GLuint start, GLuint count,
+                                GLuint newinputs );
+
+extern void radeonPrintSetupFlags(char *msg, GLuint flags );
+
+
+extern void radeon_emit_contiguous_verts( GLcontext *ctx,
+                                         GLuint start,
+                                         GLuint count );
+
+extern void radeon_emit_indexed_verts( GLcontext *ctx,
+                                      GLuint start,
+                                      GLuint count );
+
+extern void radeon_translate_vertex( GLcontext *ctx, 
+                                    const radeonVertex *src, 
+                                    SWvertex *dst );
+
+extern void radeon_print_vertex( GLcontext *ctx, const radeonVertex *v );
+
+extern void radeon_import_float_colors( GLcontext *ctx );
+extern void radeon_import_float_spec_colors( GLcontext *ctx );
+
+
+
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_tcl.c b/src/mesa/drivers/dri/radeon/radeon_tcl.c
new file mode 100644 (file)
index 0000000..651194a
--- /dev/null
@@ -0,0 +1,527 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     Tungsten Graphics Inc., Austin, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "light.h"
+#include "mtypes.h"
+#include "enums.h"
+
+#include "array_cache/acache.h"
+#include "tnl/tnl.h"
+#include "tnl/t_pipeline.h"
+
+#include "radeon_context.h"
+#include "radeon_state.h"
+#include "radeon_ioctl.h"
+#include "radeon_tex.h"
+#include "radeon_tcl.h"
+#include "radeon_swtcl.h"
+#include "radeon_maos.h"
+
+
+
+/*
+ * Render unclipped vertex buffers by emitting vertices directly to
+ * dma buffers.  Use strip/fan hardware primitives where possible.
+ * Try to simulate missing primitives with indexed vertices.
+ */
+#define HAVE_POINTS      1
+#define HAVE_LINES       1
+#define HAVE_LINE_LOOP   0
+#define HAVE_LINE_STRIPS 1
+#define HAVE_TRIANGLES   1
+#define HAVE_TRI_STRIPS  1
+#define HAVE_TRI_STRIP_1 0
+#define HAVE_TRI_FANS    1
+#define HAVE_QUADS       0
+#define HAVE_QUAD_STRIPS 0
+#define HAVE_POLYGONS    1
+#define HAVE_ELTS        1
+
+
+#define HW_POINTS           RADEON_CP_VC_CNTL_PRIM_TYPE_POINT
+#define HW_LINES            RADEON_CP_VC_CNTL_PRIM_TYPE_LINE
+#define HW_LINE_LOOP        0
+#define HW_LINE_STRIP       RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP
+#define HW_TRIANGLES        RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST
+#define HW_TRIANGLE_STRIP_0 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP
+#define HW_TRIANGLE_STRIP_1 0
+#define HW_TRIANGLE_FAN     RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN
+#define HW_QUADS            0
+#define HW_QUAD_STRIP       0
+#define HW_POLYGON          RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN
+
+
+static GLboolean discrete_prim[0x10] = {
+   0,                          /* 0 none */
+   1,                          /* 1 points */
+   1,                          /* 2 lines */
+   0,                          /* 3 line_strip */
+   1,                          /* 4 tri_list */
+   0,                          /* 5 tri_fan */
+   0,                          /* 6 tri_type2 */
+   1,                          /* 7 rect list (unused) */
+   1,                          /* 8 3vert point */
+   1,                          /* 9 3vert line */
+   0,
+   0,
+   0,
+   0,
+   0,
+   0,
+};
+   
+
+#define LOCAL_VARS radeonContextPtr rmesa = RADEON_CONTEXT(ctx)
+#define ELT_TYPE  GLushort
+
+#define ELT_INIT(prim, hw_prim) \
+   radeonTclPrimitive( ctx, prim, hw_prim | RADEON_CP_VC_CNTL_PRIM_WALK_IND )
+
+#define GET_MESA_ELTS() rmesa->tcl.Elts
+
+
+/* Don't really know how many elts will fit in what's left of cmdbuf,
+ * as there is state to emit, etc:
+ */
+
+/* Testing on isosurf shows a maximum around here.  Don't know if it's
+ * the card or driver or kernel module that is causing the behaviour.
+ */
+#define GET_MAX_HW_ELTS() 300
+
+
+#define RESET_STIPPLE() do {                   \
+   RADEON_STATECHANGE( rmesa, lin );           \
+   radeonEmitState( rmesa );                   \
+} while (0)
+
+#define AUTO_STIPPLE( mode )  do {             \
+   RADEON_STATECHANGE( rmesa, lin );           \
+   if (mode)                                   \
+      rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] |=        \
+        RADEON_LINE_PATTERN_AUTO_RESET;        \
+   else                                                \
+      rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] &=        \
+        ~RADEON_LINE_PATTERN_AUTO_RESET;       \
+   radeonEmitState( rmesa );                   \
+} while (0)
+
+
+
+#define ALLOC_ELTS(nr) radeonAllocElts( rmesa, nr )
+
+static GLushort *radeonAllocElts( radeonContextPtr rmesa, GLuint nr ) 
+{
+   if (rmesa->dma.flush)
+      rmesa->dma.flush( rmesa );
+
+   radeonEmitAOS( rmesa,
+               rmesa->tcl.aos_components,
+               rmesa->tcl.nr_aos_components, 0 );
+
+   return radeonAllocEltsOpenEnded( rmesa,
+                                   rmesa->tcl.vertex_format, 
+                                   rmesa->tcl.hw_primitive, nr );
+}
+
+#define CLOSE_ELTS()  RADEON_NEWPRIM( rmesa )
+
+
+
+/* TODO: Try to extend existing primitive if both are identical,
+ * discrete and there are no intervening state changes.  (Somewhat
+ * duplicates changes to DrawArrays code)
+ */
+static void EMIT_PRIM( GLcontext *ctx, 
+                      GLenum prim, 
+                      GLuint hwprim, 
+                      GLuint start, 
+                      GLuint count)    
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+   radeonTclPrimitive( ctx, prim, hwprim );
+   
+   radeonEmitAOS( rmesa,
+                 rmesa->tcl.aos_components,
+                 rmesa->tcl.nr_aos_components,
+                 start );
+   
+   /* Why couldn't this packet have taken an offset param?
+    */
+   radeonEmitVbufPrim( rmesa,
+                      rmesa->tcl.vertex_format,
+                      rmesa->tcl.hw_primitive,
+                      count - start );
+}
+
+
+
+/* Try & join small primitives
+ */
+#if 0
+#define PREFER_DISCRETE_ELT_PRIM( NR, PRIM ) 0
+#else
+#define PREFER_DISCRETE_ELT_PRIM( NR, PRIM )                   \
+  ((NR) < 20 ||                                                        \
+   ((NR) < 40 &&                                               \
+    rmesa->tcl.hw_primitive == (PRIM|                          \
+                           RADEON_CP_VC_CNTL_PRIM_WALK_IND|    \
+                           RADEON_CP_VC_CNTL_TCL_ENABLE)))
+#endif
+
+#ifdef MESA_BIG_ENDIAN
+/* We could do without (most of) this ugliness if dest was always 32 bit word aligned... */
+#define EMIT_ELT(dest, offset, x) do {                         \
+       int off = offset + ( ( (GLuint)dest & 0x2 ) >> 1 );     \
+       GLushort *des = (GLushort *)( (GLuint)dest & ~0x2 );    \
+       (des)[ off + 1 - 2 * ( off & 1 ) ] = (GLushort)(x); } while (0)
+#else
+#define EMIT_ELT(dest, offset, x) (dest)[offset] = (GLushort) (x)
+#endif
+
+#define EMIT_TWO_ELTS(dest, offset, x, y)  *(GLuint *)(dest+offset) = ((y)<<16)|(x);
+
+
+
+#define TAG(x) tcl_##x
+#include "tnl_dd/t_dd_dmatmp2.h"
+
+/**********************************************************************/
+/*                          External entrypoints                     */
+/**********************************************************************/
+
+void radeonEmitPrimitive( GLcontext *ctx, 
+                         GLuint first,
+                         GLuint last,
+                         GLuint flags )
+{
+   tcl_render_tab_verts[flags&PRIM_MODE_MASK]( ctx, first, last, flags );
+}
+
+void radeonEmitEltPrimitive( GLcontext *ctx, 
+                            GLuint first,
+                            GLuint last,
+                            GLuint flags )
+{
+   tcl_render_tab_elts[flags&PRIM_MODE_MASK]( ctx, first, last, flags );
+}
+
+void radeonTclPrimitive( GLcontext *ctx, 
+                        GLenum prim,
+                        int hw_prim )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLuint se_cntl;
+   GLuint newprim = hw_prim | RADEON_CP_VC_CNTL_TCL_ENABLE;
+
+   if (newprim != rmesa->tcl.hw_primitive ||
+       !discrete_prim[hw_prim&0xf]) {
+      RADEON_NEWPRIM( rmesa );
+      rmesa->tcl.hw_primitive = newprim;
+   }
+
+   se_cntl = rmesa->hw.set.cmd[SET_SE_CNTL];
+   se_cntl &= ~RADEON_FLAT_SHADE_VTX_LAST;
+
+   if (prim == GL_POLYGON && (ctx->_TriangleCaps & DD_FLATSHADE)) 
+      se_cntl |= RADEON_FLAT_SHADE_VTX_0;
+   else
+      se_cntl |= RADEON_FLAT_SHADE_VTX_LAST;
+
+   if (se_cntl != rmesa->hw.set.cmd[SET_SE_CNTL]) {
+      RADEON_STATECHANGE( rmesa, set );
+      rmesa->hw.set.cmd[SET_SE_CNTL] = se_cntl;
+   }
+}
+
+
+/**********************************************************************/
+/*                          Render pipeline stage                     */
+/**********************************************************************/
+
+
+/* TCL render.
+ */
+static GLboolean radeon_run_tcl_render( GLcontext *ctx,
+                                       struct gl_pipeline_stage *stage )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   struct vertex_buffer *VB = &tnl->vb;
+   GLuint i,flags = 0,length;
+
+   /* TODO: separate this from the swtnl pipeline 
+    */
+   if (rmesa->TclFallback)
+      return GL_TRUE;  /* fallback to software t&l */
+
+   if (VB->Count == 0)
+      return GL_FALSE;
+
+   radeonReleaseArrays( ctx, stage->changed_inputs );
+   radeonEmitArrays( ctx, stage->inputs );
+
+   rmesa->tcl.Elts = VB->Elts;
+
+   for (i = VB->FirstPrimitive ; !(flags & PRIM_LAST) ; i += length)
+   {
+      flags = VB->Primitive[i];
+      length = VB->PrimitiveLength[i];
+
+      if (RADEON_DEBUG & DEBUG_PRIMS)
+        fprintf(stderr, "%s: prim %s %d..%d\n", 
+                __FUNCTION__,
+                _mesa_lookup_enum_by_nr(flags & PRIM_MODE_MASK), 
+                i, i+length);
+
+      if (!length)
+        continue;
+
+      if (rmesa->tcl.Elts)
+        radeonEmitEltPrimitive( ctx, i, i+length, flags );
+      else
+        radeonEmitPrimitive( ctx, i, i+length, flags );
+   }
+
+   return GL_FALSE;            /* finished the pipe */
+}
+
+
+
+static void radeon_check_tcl_render( GLcontext *ctx,
+                                    struct gl_pipeline_stage *stage )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLuint inputs = VERT_BIT_POS;
+
+   if (ctx->RenderMode == GL_RENDER) {
+      /* Make all this event-driven:
+       */
+      if (ctx->Light.Enabled) {
+        inputs |= VERT_BIT_NORMAL;
+
+        if (1 || ctx->Light.ColorMaterialEnabled) {
+           inputs |= VERT_BIT_COLOR0;
+        }
+      }
+      else {
+        inputs |= VERT_BIT_COLOR0;
+        
+        if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
+           inputs |= VERT_BIT_COLOR1;
+        }
+      }
+
+      if (ctx->Texture.Unit[0]._ReallyEnabled) {
+        if (ctx->Texture.Unit[0].TexGenEnabled) {
+           if (rmesa->TexGenNeedNormals[0]) {
+              inputs |= VERT_BIT_NORMAL;
+           }
+        } else {
+           inputs |= VERT_BIT_TEX0;
+        }
+      }
+
+      if (ctx->Texture.Unit[1]._ReallyEnabled) {
+        if (ctx->Texture.Unit[1].TexGenEnabled) {
+           if (rmesa->TexGenNeedNormals[1]) {
+              inputs |= VERT_BIT_NORMAL;
+           }
+        } else {
+           inputs |= VERT_BIT_TEX1;
+        }
+      }
+
+      stage->inputs = inputs;
+      stage->active = 1;
+   }
+   else
+      stage->active = 0;
+}
+
+static void radeon_init_tcl_render( GLcontext *ctx,
+                                   struct gl_pipeline_stage *stage )
+{
+   stage->check = radeon_check_tcl_render;
+   stage->check( ctx, stage );
+}
+
+static void dtr( struct gl_pipeline_stage *stage )
+{
+   (void)stage;
+}
+
+
+/* Initial state for tcl stage.  
+ */
+const struct gl_pipeline_stage _radeon_tcl_stage =
+{
+   "radeon render",
+   (_DD_NEW_SEPARATE_SPECULAR |
+    _NEW_LIGHT|
+    _NEW_TEXTURE|
+    _NEW_FOG|
+    _NEW_RENDERMODE),          /* re-check (new inputs) */
+   0,                          /* re-run (always runs) */
+   GL_TRUE,                    /* active */
+   0, 0,                       /* inputs (set in check_render), outputs */
+   0, 0,                       /* changed_inputs, private */
+   dtr,                                /* destructor */
+   radeon_init_tcl_render,     /* check - initially set to alloc data */
+   radeon_run_tcl_render       /* run */
+};
+
+
+
+/**********************************************************************/
+/*                 Validate state at pipeline start                   */
+/**********************************************************************/
+
+
+/*-----------------------------------------------------------------------
+ * Manage TCL fallbacks
+ */
+
+
+static void transition_to_swtnl( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   GLuint se_cntl;
+
+   RADEON_NEWPRIM( rmesa );
+   rmesa->swtcl.vertex_format = 0;
+
+   radeonChooseVertexState( ctx );
+   radeonChooseRenderState( ctx );
+
+   _mesa_validate_all_lighting_tables( ctx ); 
+
+   tnl->Driver.NotifyMaterialChange = 
+      _mesa_validate_all_lighting_tables;
+
+   radeonReleaseArrays( ctx, ~0 );
+
+   se_cntl = rmesa->hw.set.cmd[SET_SE_CNTL];
+   se_cntl |= RADEON_FLAT_SHADE_VTX_LAST;
+        
+   if (se_cntl != rmesa->hw.set.cmd[SET_SE_CNTL]) {
+      RADEON_STATECHANGE( rmesa, set );
+      rmesa->hw.set.cmd[SET_SE_CNTL] = se_cntl;
+   }
+}
+
+
+static void transition_to_hwtnl( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   TNLcontext *tnl = TNL_CONTEXT(ctx);
+   GLuint se_coord_fmt = (RADEON_VTX_W0_IS_NOT_1_OVER_W0 |
+                         RADEON_TEX1_W_ROUTING_USE_Q1);
+
+   if ( se_coord_fmt != rmesa->hw.set.cmd[SET_SE_COORDFMT] ) {
+      RADEON_STATECHANGE( rmesa, set );
+      rmesa->hw.set.cmd[SET_SE_COORDFMT] = se_coord_fmt;
+      _tnl_need_projected_coords( ctx, GL_FALSE );
+   }
+
+   radeonUpdateMaterial( ctx );
+
+   tnl->Driver.NotifyMaterialChange = radeonUpdateMaterial;
+
+   if ( rmesa->dma.flush )                     
+      rmesa->dma.flush( rmesa );       
+
+   rmesa->dma.flush = 0;
+   rmesa->swtcl.vertex_format = 0;
+   
+   if (rmesa->swtcl.indexed_verts.buf) 
+      radeonReleaseDmaRegion( rmesa, &rmesa->swtcl.indexed_verts, 
+                             __FUNCTION__ );
+
+   if (RADEON_DEBUG & DEBUG_FALLBACKS) 
+      fprintf(stderr, "Radeon end tcl fallback\n");
+}
+
+static char *fallbackStrings[] = {
+   "Rasterization fallback",
+   "Unfilled triangles",
+   "Twosided lighting, differing materials",
+   "Materials in VB (maybe between begin/end)",
+   "Texgen unit 0",
+   "Texgen unit 1",
+   "Texgen unit 2",
+   "User disable"
+};
+
+
+static char *getFallbackString(GLuint bit)
+{
+   int i = 0;
+   while (bit > 1) {
+      i++;
+      bit >>= 1;
+   }
+   return fallbackStrings[i];
+}
+
+
+
+void radeonTclFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLuint oldfallback = rmesa->TclFallback;
+
+   if (mode) {
+      rmesa->TclFallback |= bit;
+      if (oldfallback == 0) {
+        if (RADEON_DEBUG & DEBUG_FALLBACKS) 
+           fprintf(stderr, "Radeon begin tcl fallback %s\n",
+                   getFallbackString( bit ));
+        transition_to_swtnl( ctx );
+      }
+   }
+   else {
+      rmesa->TclFallback &= ~bit;
+      if (oldfallback == bit) {
+        if (RADEON_DEBUG & DEBUG_FALLBACKS) 
+           fprintf(stderr, "Radeon end tcl fallback %s\n",
+                   getFallbackString( bit ));
+        transition_to_hwtnl( ctx );
+      }
+   }
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_tcl.h b/src/mesa/drivers/dri/radeon/radeon_tcl.h
new file mode 100644 (file)
index 0000000..1e97d32
--- /dev/null
@@ -0,0 +1,70 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     Tungsten Grahpics Inc., Austin, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ *
+ */
+
+#ifndef __RADEON_TCL_H__
+#define __RADEON_TCL_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include "radeon_context.h"
+
+extern void radeonTclPrimitive( GLcontext *ctx, GLenum prim, int hw_prim );
+extern void radeonEmitEltPrimitive( GLcontext *ctx, GLuint first, GLuint last,
+                                   GLuint flags );
+extern void radeonEmitPrimitive( GLcontext *ctx, GLuint first, GLuint last,
+                                GLuint flags );
+
+extern void radeonTclFallback( GLcontext *ctx, GLuint bit, GLboolean mode );
+                                             
+#define RADEON_TCL_FALLBACK_RASTER            0x1 /* rasterization */
+#define RADEON_TCL_FALLBACK_UNFILLED          0x2 /* unfilled tris */
+#define RADEON_TCL_FALLBACK_LIGHT_TWOSIDE     0x4 /* twoside tris */
+#define RADEON_TCL_FALLBACK_MATERIAL          0x8 /* material in vb */
+#define RADEON_TCL_FALLBACK_TEXGEN_0          0x10 /* texgen, unit 0 */
+#define RADEON_TCL_FALLBACK_TEXGEN_1          0x20 /* texgen, unit 1 */
+#define RADEON_TCL_FALLBACK_TEXGEN_2          0x40 /* texgen, unit 2 */
+#define RADEON_TCL_FALLBACK_TCL_DISABLE       0x80 /* user disable */
+#define RADEON_TCL_FALLBACK_TEXRECT_0         0x100 /* texture rectangle */
+#define RADEON_TCL_FALLBACK_TEXRECT_1         0x200 /* texture rectangle */
+#define RADEON_TCL_FALLBACK_TEXRECT_2         0x400 /* texture rectangle */
+
+#define RADEON_MAX_TCL_VERTSIZE (15*4)
+
+#define TCL_FALLBACK( ctx, bit, mode ) radeonTclFallback( ctx, bit, mode )
+
+
+#endif
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_tex.c b/src/mesa/drivers/dri/radeon/radeon_tex.c
new file mode 100644 (file)
index 0000000..e068202
--- /dev/null
@@ -0,0 +1,733 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_tex.c,v 1.6 2002/09/16 18:05:20 eich Exp $ */
+/*
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+/*
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ *    Brian Paul <brianp@valinux.com>
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "colormac.h"
+#include "context.h"
+#include "enums.h"
+#include "image.h"
+#include "simple_list.h"
+#include "texformat.h"
+#include "texstore.h"
+#include "teximage.h"
+
+
+#include "radeon_context.h"
+#include "radeon_state.h"
+#include "radeon_ioctl.h"
+#include "radeon_swtcl.h"
+#include "radeon_tex.h"
+
+
+
+/**
+ * Set the texture wrap modes.
+ * 
+ * \param t Texture object whose wrap modes are to be set
+ * \param swrap Wrap mode for the \a s texture coordinate
+ * \param twrap Wrap mode for the \a t texture coordinate
+ */
+
+static void radeonSetTexWrap( radeonTexObjPtr t, GLenum swrap, GLenum twrap )
+{
+   GLboolean  is_clamp = GL_FALSE;
+   GLboolean  is_clamp_to_border = GL_FALSE;
+
+   t->pp_txfilter &= ~(RADEON_CLAMP_S_MASK | RADEON_CLAMP_T_MASK | RADEON_BORDER_MODE_D3D);
+
+   switch ( swrap ) {
+   case GL_REPEAT:
+      t->pp_txfilter |= RADEON_CLAMP_S_WRAP;
+      break;
+   case GL_CLAMP:
+      t->pp_txfilter |= RADEON_CLAMP_S_CLAMP_GL;
+      is_clamp = GL_TRUE;
+      break;
+   case GL_CLAMP_TO_EDGE:
+      t->pp_txfilter |= RADEON_CLAMP_S_CLAMP_LAST;
+      break;
+   case GL_CLAMP_TO_BORDER:
+      t->pp_txfilter |= RADEON_CLAMP_S_CLAMP_GL;
+      is_clamp_to_border = GL_TRUE;
+      break;
+   case GL_MIRRORED_REPEAT:
+      t->pp_txfilter |= RADEON_CLAMP_S_MIRROR;
+      break;
+   case GL_MIRROR_CLAMP_ATI:
+      t->pp_txfilter |= RADEON_CLAMP_S_MIRROR_CLAMP_GL;
+      is_clamp = GL_TRUE;
+      break;
+   case GL_MIRROR_CLAMP_TO_EDGE_ATI:
+      t->pp_txfilter |= RADEON_CLAMP_S_MIRROR_CLAMP_LAST;
+      break;
+   default:
+      _mesa_problem(NULL, "bad S wrap mode in %s", __FUNCTION__);
+   }
+
+   switch ( twrap ) {
+   case GL_REPEAT:
+      t->pp_txfilter |= RADEON_CLAMP_T_WRAP;
+      break;
+   case GL_CLAMP:
+      t->pp_txfilter |= RADEON_CLAMP_T_CLAMP_GL;
+      is_clamp = GL_TRUE;
+      break;
+   case GL_CLAMP_TO_EDGE:
+      t->pp_txfilter |= RADEON_CLAMP_T_CLAMP_LAST;
+      break;
+   case GL_CLAMP_TO_BORDER:
+      t->pp_txfilter |= RADEON_CLAMP_T_CLAMP_GL;
+      is_clamp_to_border = GL_TRUE;
+      break;
+   case GL_MIRRORED_REPEAT:
+      t->pp_txfilter |= RADEON_CLAMP_T_MIRROR;
+      break;
+   case GL_MIRROR_CLAMP_ATI:
+      t->pp_txfilter |= RADEON_CLAMP_T_MIRROR_CLAMP_GL;
+      is_clamp = GL_TRUE;
+      break;
+   case GL_MIRROR_CLAMP_TO_EDGE_ATI:
+      t->pp_txfilter |= RADEON_CLAMP_T_MIRROR_CLAMP_LAST;
+      break;
+   default:
+      _mesa_problem(NULL, "bad T wrap mode in %s", __FUNCTION__);
+   }
+
+   if ( is_clamp_to_border ) {
+      t->pp_txfilter |= RADEON_BORDER_MODE_D3D;
+   }
+
+   t->border_fallback = (is_clamp && is_clamp_to_border);
+}
+
+static void radeonSetTexMaxAnisotropy( radeonTexObjPtr t, GLfloat max )
+{
+   t->pp_txfilter &= ~RADEON_MAX_ANISO_MASK;
+
+   if ( max == 1.0 ) {
+      t->pp_txfilter |= RADEON_MAX_ANISO_1_TO_1;
+   } else if ( max <= 2.0 ) {
+      t->pp_txfilter |= RADEON_MAX_ANISO_2_TO_1;
+   } else if ( max <= 4.0 ) {
+      t->pp_txfilter |= RADEON_MAX_ANISO_4_TO_1;
+   } else if ( max <= 8.0 ) {
+      t->pp_txfilter |= RADEON_MAX_ANISO_8_TO_1;
+   } else {
+      t->pp_txfilter |= RADEON_MAX_ANISO_16_TO_1;
+   }
+}
+
+/**
+ * Set the texture magnification and minification modes.
+ * 
+ * \param t Texture whose filter modes are to be set
+ * \param minf Texture minification mode
+ * \param magf Texture magnification mode
+ */
+
+static void radeonSetTexFilter( radeonTexObjPtr t, GLenum minf, GLenum magf )
+{
+   GLuint anisotropy = (t->pp_txfilter & RADEON_MAX_ANISO_MASK);
+
+   t->pp_txfilter &= ~(RADEON_MIN_FILTER_MASK | RADEON_MAG_FILTER_MASK);
+
+   if ( anisotropy == RADEON_MAX_ANISO_1_TO_1 ) {
+      switch ( minf ) {
+      case GL_NEAREST:
+        t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST;
+        break;
+      case GL_LINEAR:
+        t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR;
+        break;
+      case GL_NEAREST_MIPMAP_NEAREST:
+        t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST_MIP_NEAREST;
+        break;
+      case GL_NEAREST_MIPMAP_LINEAR:
+        t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR_MIP_NEAREST;
+        break;
+      case GL_LINEAR_MIPMAP_NEAREST:
+        t->pp_txfilter |= RADEON_MIN_FILTER_NEAREST_MIP_LINEAR;
+        break;
+      case GL_LINEAR_MIPMAP_LINEAR:
+        t->pp_txfilter |= RADEON_MIN_FILTER_LINEAR_MIP_LINEAR;
+        break;
+      }
+   } else {
+      switch ( minf ) {
+      case GL_NEAREST:
+        t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_NEAREST;
+        break;
+      case GL_LINEAR:
+        t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_LINEAR;
+        break;
+      case GL_NEAREST_MIPMAP_NEAREST:
+      case GL_LINEAR_MIPMAP_NEAREST:
+        t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST;
+        break;
+      case GL_NEAREST_MIPMAP_LINEAR:
+      case GL_LINEAR_MIPMAP_LINEAR:
+        t->pp_txfilter |= RADEON_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR;
+        break;
+      }
+   }
+
+   switch ( magf ) {
+   case GL_NEAREST:
+      t->pp_txfilter |= RADEON_MAG_FILTER_NEAREST;
+      break;
+   case GL_LINEAR:
+      t->pp_txfilter |= RADEON_MAG_FILTER_LINEAR;
+      break;
+   }
+}
+
+static void radeonSetTexBorderColor( radeonTexObjPtr t, GLubyte c[4] )
+{
+   t->pp_border_color = radeonPackColor( 4, c[0], c[1], c[2], c[3] );
+}
+
+
+/**
+ * Allocate space for and load the mesa images into the texture memory block.
+ * This will happen before drawing with a new texture, or drawing with a
+ * texture after it was swapped out or teximaged again.
+ */
+
+static radeonTexObjPtr radeonAllocTexObj( struct gl_texture_object *texObj )
+{
+   radeonTexObjPtr t;
+
+   t = CALLOC_STRUCT( radeon_tex_obj );
+   texObj->DriverData = t;
+   if ( t != NULL ) {
+      if ( RADEON_DEBUG & DEBUG_TEXTURE ) {
+        fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, texObj, t );
+      }
+
+      /* Initialize non-image-dependent parts of the state:
+       */
+      t->base.tObj = texObj;
+      t->border_fallback = GL_FALSE;
+
+      t->pp_txfilter = RADEON_BORDER_MODE_OGL;
+      t->pp_txformat = (RADEON_TXFORMAT_ENDIAN_NO_SWAP |
+                       RADEON_TXFORMAT_PERSPECTIVE_ENABLE);
+
+      make_empty_list( & t->base );
+
+      radeonSetTexWrap( t, texObj->WrapS, texObj->WrapT );
+      radeonSetTexMaxAnisotropy( t, texObj->MaxAnisotropy );
+      radeonSetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
+      radeonSetTexBorderColor( t, texObj->_BorderChan );
+   }
+
+   return t;
+}
+
+
+static const struct gl_texture_format *
+radeonChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
+                           GLenum format, GLenum type )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   const GLboolean do32bpt = ( rmesa->radeonScreen->cpp == 4 );
+
+   switch ( internalFormat ) {
+   case 4:
+   case GL_RGBA:
+   case GL_COMPRESSED_RGBA:
+      if ( format == GL_BGRA ) {
+        if ( type == GL_UNSIGNED_INT_8_8_8_8_REV ) {
+           return &_mesa_texformat_argb8888;
+        }
+         else if ( type == GL_UNSIGNED_SHORT_4_4_4_4_REV ) {
+            return &_mesa_texformat_argb4444;
+        }
+         else if ( type == GL_UNSIGNED_SHORT_1_5_5_5_REV ) {
+           return &_mesa_texformat_argb1555;
+        }
+      }
+      return do32bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_argb4444;
+
+   case 3:
+   case GL_RGB:
+   case GL_COMPRESSED_RGB:
+      if ( format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5 ) {
+        return &_mesa_texformat_rgb565;
+      }
+      return do32bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_rgb565;
+
+   case GL_RGBA8:
+   case GL_RGB10_A2:
+   case GL_RGBA12:
+   case GL_RGBA16:
+      return do32bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_argb4444;
+
+   case GL_RGBA4:
+   case GL_RGBA2:
+      return &_mesa_texformat_argb4444;
+
+   case GL_RGB5_A1:
+      return &_mesa_texformat_argb1555;
+
+   case GL_RGB8:
+   case GL_RGB10:
+   case GL_RGB12:
+   case GL_RGB16:
+      return do32bpt ? &_mesa_texformat_rgba8888 : &_mesa_texformat_rgb565;
+
+   case GL_RGB5:
+   case GL_RGB4:
+   case GL_R3_G3_B2:
+      return &_mesa_texformat_rgb565;
+
+   case GL_ALPHA:
+   case GL_ALPHA4:
+   case GL_ALPHA8:
+   case GL_ALPHA12:
+   case GL_ALPHA16:
+   case GL_COMPRESSED_ALPHA:
+      return &_mesa_texformat_al88;
+
+   case 1:
+   case GL_LUMINANCE:
+   case GL_LUMINANCE4:
+   case GL_LUMINANCE8:
+   case GL_LUMINANCE12:
+   case GL_LUMINANCE16:
+   case GL_COMPRESSED_LUMINANCE:
+      return &_mesa_texformat_al88;
+
+   case 2:
+   case GL_LUMINANCE_ALPHA:
+   case GL_LUMINANCE4_ALPHA4:
+   case GL_LUMINANCE6_ALPHA2:
+   case GL_LUMINANCE8_ALPHA8:
+   case GL_LUMINANCE12_ALPHA4:
+   case GL_LUMINANCE12_ALPHA12:
+   case GL_LUMINANCE16_ALPHA16:
+   case GL_COMPRESSED_LUMINANCE_ALPHA:
+      return &_mesa_texformat_al88;
+
+   case GL_INTENSITY:
+   case GL_INTENSITY4:
+   case GL_INTENSITY8:
+   case GL_INTENSITY12:
+   case GL_INTENSITY16:
+   case GL_COMPRESSED_INTENSITY:
+      return &_mesa_texformat_i8;
+
+   case GL_YCBCR_MESA:
+      if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
+          type == GL_UNSIGNED_BYTE)
+         return &_mesa_texformat_ycbcr;
+      else
+         return &_mesa_texformat_ycbcr_rev;
+
+   default:
+      _mesa_problem(ctx, "unexpected texture format in %s", __FUNCTION__);
+      return NULL;
+   }
+
+   return NULL; /* never get here */
+}
+
+
+static void radeonTexImage1D( GLcontext *ctx, GLenum target, GLint level,
+                              GLint internalFormat,
+                              GLint width, GLint border,
+                              GLenum format, GLenum type, const GLvoid *pixels,
+                              const struct gl_pixelstore_attrib *packing,
+                              struct gl_texture_object *texObj,
+                              struct gl_texture_image *texImage )
+{
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
+
+   if ( t ) {
+      driSwapOutTextureObject( t );
+   }
+   else {
+      t = (driTextureObject *) radeonAllocTexObj( texObj );
+      if (!t) {
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
+         return;
+      }
+   }
+
+   /* Note, this will call ChooseTextureFormat */
+   _mesa_store_teximage1d(ctx, target, level, internalFormat,
+                          width, border, format, type, pixels,
+                          &ctx->Unpack, texObj, texImage);
+
+   t->dirty_images[0] |= (1 << level);
+}
+
+
+static void radeonTexSubImage1D( GLcontext *ctx, GLenum target, GLint level,
+                                 GLint xoffset,
+                                 GLsizei width,
+                                 GLenum format, GLenum type,
+                                 const GLvoid *pixels,
+                                 const struct gl_pixelstore_attrib *packing,
+                                 struct gl_texture_object *texObj,
+                                 struct gl_texture_image *texImage )
+{
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
+
+   assert( t ); /* this _should_ be true */
+   if ( t ) {
+      driSwapOutTextureObject( t );
+   }
+   else {
+      t = (driTextureObject *) radeonAllocTexObj( texObj );
+      if (!t) {
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
+         return;
+      }
+   }
+
+   _mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
+                            format, type, pixels, packing, texObj,
+                            texImage);
+
+   t->dirty_images[0] |= (1 << level);
+}
+
+
+static void radeonTexImage2D( GLcontext *ctx, GLenum target, GLint level,
+                              GLint internalFormat,
+                              GLint width, GLint height, GLint border,
+                              GLenum format, GLenum type, const GLvoid *pixels,
+                              const struct gl_pixelstore_attrib *packing,
+                              struct gl_texture_object *texObj,
+                              struct gl_texture_image *texImage )
+{
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
+   GLuint face;
+
+   /* which cube face or ordinary 2D image */
+   switch (target) {
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+      face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+      ASSERT(face < 6);
+      break;
+   default:
+      face = 0;
+   }
+
+   if ( t != NULL ) {
+      driSwapOutTextureObject( t );
+   }
+   else {
+      t = (driTextureObject *) radeonAllocTexObj( texObj );
+      if (!t) {
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
+         return;
+      }
+   }
+
+   /* Note, this will call ChooseTextureFormat */
+   _mesa_store_teximage2d(ctx, target, level, internalFormat,
+                          width, height, border, format, type, pixels,
+                          &ctx->Unpack, texObj, texImage);
+
+   t->dirty_images[face] |= (1 << level);
+}
+
+
+static void radeonTexSubImage2D( GLcontext *ctx, GLenum target, GLint level,
+                                 GLint xoffset, GLint yoffset,
+                                 GLsizei width, GLsizei height,
+                                 GLenum format, GLenum type,
+                                 const GLvoid *pixels,
+                                 const struct gl_pixelstore_attrib *packing,
+                                 struct gl_texture_object *texObj,
+                                 struct gl_texture_image *texImage )
+{
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
+   GLuint face;
+
+
+   /* which cube face or ordinary 2D image */
+   switch (target) {
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
+   case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
+   case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
+      face = (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+      ASSERT(face < 6);
+      break;
+   default:
+      face = 0;
+   }
+
+   assert( t ); /* this _should_ be true */
+   if ( t ) {
+      driSwapOutTextureObject( t );
+   }
+   else {
+      t = (driTextureObject *) radeonAllocTexObj( texObj );
+      if (!t) {
+         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
+         return;
+      }
+   }
+
+   _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
+                            height, format, type, pixels, packing, texObj,
+                            texImage);
+
+   t->dirty_images[face] |= (1 << level);
+}
+
+
+
+#define SCALED_FLOAT_TO_BYTE( x, scale ) \
+               (((GLuint)((255.0F / scale) * (x))) / 2)
+
+static void radeonTexEnv( GLcontext *ctx, GLenum target,
+                         GLenum pname, const GLfloat *param )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLuint unit = ctx->Texture.CurrentUnit;
+   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+
+   if ( RADEON_DEBUG & DEBUG_STATE ) {
+      fprintf( stderr, "%s( %s )\n",
+              __FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
+   }
+
+   switch ( pname ) {
+   case GL_TEXTURE_ENV_COLOR: {
+      GLubyte c[4];
+      GLuint envColor;
+      UNCLAMPED_FLOAT_TO_RGBA_CHAN( c, texUnit->EnvColor );
+      envColor = radeonPackColor( 4, c[0], c[1], c[2], c[3] );
+      if ( rmesa->hw.tex[unit].cmd[TEX_PP_TFACTOR] != envColor ) {
+        RADEON_STATECHANGE( rmesa, tex[unit] );
+        rmesa->hw.tex[unit].cmd[TEX_PP_TFACTOR] = envColor;
+      }
+      break;
+   }
+
+   case GL_TEXTURE_LOD_BIAS_EXT: {
+      GLfloat bias;
+      GLuint b;
+
+      /* The Radeon's LOD bias is a signed 2's complement value with a
+       * range of -1.0 <= bias < 4.0.  We break this into two linear
+       * functions, one mapping [-1.0,0.0] to [-128,0] and one mapping
+       * [0.0,4.0] to [0,127].
+       */
+      bias = CLAMP( *param, -1.0, 4.0 );
+      if ( bias == 0 ) {
+        b = 0;
+      } else if ( bias > 0 ) {
+        b = ((GLuint)SCALED_FLOAT_TO_BYTE( bias, 4.0 )) << RADEON_LOD_BIAS_SHIFT;
+      } else {
+        b = ((GLuint)SCALED_FLOAT_TO_BYTE( bias, 1.0 )) << RADEON_LOD_BIAS_SHIFT;
+      }
+      if ( (rmesa->hw.tex[unit].cmd[TEX_PP_TXFILTER] & RADEON_LOD_BIAS_MASK) != b ) {
+        RADEON_STATECHANGE( rmesa, tex[unit] );
+        rmesa->hw.tex[unit].cmd[TEX_PP_TXFILTER] &= ~RADEON_LOD_BIAS_MASK;
+        rmesa->hw.tex[unit].cmd[TEX_PP_TXFILTER] |= (b & RADEON_LOD_BIAS_MASK);
+      }
+      break;
+   }
+
+   default:
+      return;
+   }
+}
+
+
+/**
+ * Changes variables and flags for a state update, which will happen at the
+ * next UpdateTextureState
+ */
+
+static void radeonTexParameter( GLcontext *ctx, GLenum target,
+                               struct gl_texture_object *texObj,
+                               GLenum pname, const GLfloat *params )
+{
+   radeonTexObjPtr t = (radeonTexObjPtr) texObj->DriverData;
+
+   if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
+      fprintf( stderr, "%s( %s )\n", __FUNCTION__,
+              _mesa_lookup_enum_by_nr( pname ) );
+   }
+
+   if ( ( target != GL_TEXTURE_2D ) &&
+       ( target != GL_TEXTURE_1D ) )
+      return;
+
+   switch ( pname ) {
+   case GL_TEXTURE_MIN_FILTER:
+   case GL_TEXTURE_MAG_FILTER:
+   case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+      radeonSetTexMaxAnisotropy( t, texObj->MaxAnisotropy );
+      radeonSetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
+      break;
+
+   case GL_TEXTURE_WRAP_S:
+   case GL_TEXTURE_WRAP_T:
+      radeonSetTexWrap( t, texObj->WrapS, texObj->WrapT );
+      break;
+
+   case GL_TEXTURE_BORDER_COLOR:
+      radeonSetTexBorderColor( t, texObj->_BorderChan );
+      break;
+
+   case GL_TEXTURE_BASE_LEVEL:
+   case GL_TEXTURE_MAX_LEVEL:
+   case GL_TEXTURE_MIN_LOD:
+   case GL_TEXTURE_MAX_LOD:
+      /* This isn't the most efficient solution but there doesn't appear to
+       * be a nice alternative.  Since there's no LOD clamping,
+       * we just have to rely on loading the right subset of mipmap levels
+       * to simulate a clamped LOD.
+       */
+      driSwapOutTextureObject( (driTextureObject *) t );
+      break;
+
+   default:
+      return;
+   }
+
+   /* Mark this texobj as dirty (one bit per tex unit)
+    */
+   t->dirty_state = TEX_ALL;
+}
+
+
+
+static void radeonBindTexture( GLcontext *ctx, GLenum target,
+                              struct gl_texture_object *texObj )
+{
+   if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
+      fprintf( stderr, "%s( %p ) unit=%d\n", __FUNCTION__, texObj,
+              ctx->Texture.CurrentUnit );
+   }
+
+   if ( target == GL_TEXTURE_2D || target == GL_TEXTURE_1D ) {
+      if ( texObj->DriverData == NULL ) {
+        radeonAllocTexObj( texObj );
+      }
+   }
+}
+
+static void radeonDeleteTexture( GLcontext *ctx,
+                                struct gl_texture_object *texObj )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   driTextureObject * t = (driTextureObject *) texObj->DriverData;
+
+   if ( RADEON_DEBUG & (DEBUG_STATE|DEBUG_TEXTURE) ) {
+      fprintf( stderr, "%s( %p (target = %s) )\n", __FUNCTION__, texObj,
+              _mesa_lookup_enum_by_nr( texObj->Target ) );
+   }
+
+   if ( t != NULL ) {
+      if ( rmesa ) {
+         RADEON_FIREVERTICES( rmesa );
+      }
+
+      driDestroyTextureObject( t );
+   }
+}
+
+/* Need:  
+ *  - Same GEN_MODE for all active bits
+ *  - Same EyePlane/ObjPlane for all active bits when using Eye/Obj
+ *  - STRQ presumably all supported (matrix means incoming R values
+ *    can end up in STQ, this has implications for vertex support,
+ *    presumably ok if maos is used, though?)
+ *  
+ * Basically impossible to do this on the fly - just collect some
+ * basic info & do the checks from ValidateState().
+ */
+static void radeonTexGen( GLcontext *ctx,
+                         GLenum coord,
+                         GLenum pname,
+                         const GLfloat *params )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLuint unit = ctx->Texture.CurrentUnit;
+   rmesa->recheck_texgen[unit] = GL_TRUE;
+}
+
+
+void radeonInitTextureFuncs( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+
+   ctx->Driver.ChooseTextureFormat     = radeonChooseTextureFormat;
+   ctx->Driver.TexImage1D              = radeonTexImage1D;
+   ctx->Driver.TexImage2D              = radeonTexImage2D;
+   ctx->Driver.TexImage3D              = _mesa_store_teximage3d;
+   ctx->Driver.TexSubImage1D           = radeonTexSubImage1D;
+   ctx->Driver.TexSubImage2D           = radeonTexSubImage2D;
+   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;
+
+   ctx->Driver.BindTexture             = radeonBindTexture;
+   ctx->Driver.CreateTexture           = NULL; /* FIXME: Is this used??? */
+   ctx->Driver.DeleteTexture           = radeonDeleteTexture;
+   ctx->Driver.IsTextureResident       = driIsTextureResident;
+   ctx->Driver.PrioritizeTexture       = NULL;
+   ctx->Driver.ActiveTexture           = NULL;
+   ctx->Driver.UpdateTexturePalette    = NULL;
+
+   ctx->Driver.TexEnv                  = radeonTexEnv;
+   ctx->Driver.TexParameter            = radeonTexParameter;
+   ctx->Driver.TexGen                   = radeonTexGen;
+
+   driInitTextureObjects( ctx, & rmesa->swapped,
+                         DRI_TEXMGR_DO_TEXTURE_1D
+                         | DRI_TEXMGR_DO_TEXTURE_2D );
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_tex.h b/src/mesa/drivers/dri/radeon/radeon_tex.h
new file mode 100644 (file)
index 0000000..ce079ba
--- /dev/null
@@ -0,0 +1,53 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_tex.h,v 1.3 2002/02/22 21:45:01 dawes Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Gareth Hughes <gareth@valinux.com>
+ *
+ */
+
+#ifndef __RADEON_TEX_H__
+#define __RADEON_TEX_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+extern void radeonUpdateTextureState( GLcontext *ctx );
+
+extern int radeonUploadTexImages( radeonContextPtr rmesa, radeonTexObjPtr t,
+                                 GLuint face );
+
+extern void radeonDestroyTexObj( radeonContextPtr rmesa, radeonTexObjPtr t );
+
+extern void radeonInitTextureFuncs( GLcontext *ctx );
+
+#endif
+#endif /* __RADEON_TEX_H__ */
diff --git a/src/mesa/drivers/dri/radeon/radeon_texmem.c b/src/mesa/drivers/dri/radeon/radeon_texmem.c
new file mode 100644 (file)
index 0000000..3adc2a9
--- /dev/null
@@ -0,0 +1,378 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_texmem.c,v 1.7 2002/12/16 16:18:59 dawes Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation on the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR THEIR
+SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Gareth Hughes <gareth@valinux.com>
+ *
+ */
+#include <errno.h>
+
+#include "glheader.h"
+#include "imports.h"
+#include "context.h"
+#include "macros.h"
+#include "simple_list.h"
+
+#include "radeon_context.h"
+#include "radeon_ioctl.h"
+#include "radeon_tex.h"
+
+
+/**
+ * Destroy any device-dependent state associated with the texture.  This may
+ * include NULLing out hardware state that points to the texture.
+ */
+void
+radeonDestroyTexObj( radeonContextPtr rmesa, radeonTexObjPtr t )
+{
+   if ( RADEON_DEBUG & DEBUG_TEXTURE ) {
+      fprintf( stderr, "%s( %p, %p )\n", __FUNCTION__, t, t->base.tObj );
+   }
+
+   if ( rmesa != NULL ) {
+      unsigned   i;
+
+
+      for ( i = 0 ; i < rmesa->glCtx->Const.MaxTextureUnits ; i++ ) {
+        if ( t == rmesa->state.texture.unit[i].texobj ) {
+           rmesa->state.texture.unit[i].texobj = NULL;
+           remove_from_list( &rmesa->hw.tex[i] );
+           make_empty_list( &rmesa->hw.tex[i] );
+        }
+      }
+   }
+}
+
+
+/* ------------------------------------------------------------
+ * Texture image conversions
+ */
+
+
+static void radeonUploadRectSubImage( radeonContextPtr rmesa,
+                                     radeonTexObjPtr t, 
+                                     struct gl_texture_image *texImage,
+                                     GLint x, GLint y, 
+                                     GLint width, GLint height )
+{
+   const struct gl_texture_format *texFormat = texImage->TexFormat;
+   int blit_format, dstPitch, done;
+
+   switch ( texFormat->TexelBytes ) {
+   case 1:
+      blit_format = RADEON_GMC_DST_8BPP_CI;
+      break;
+   case 2:
+      blit_format = RADEON_GMC_DST_16BPP;
+      break;
+   case 4:
+      blit_format = RADEON_GMC_DST_32BPP;
+      break;
+   default:
+      fprintf( stderr, "radeonUploadRectSubImage: unknown blit_format (texelbytes=%d)\n", 
+              texFormat->TexelBytes);
+      return;
+   }
+
+   t->image[0][0].data = texImage->Data;
+
+   /* Currently don't need to cope with small pitches.
+    */
+   width = texImage->Width;
+   height = texImage->Height;
+   dstPitch = t->pp_txpitch + 32;
+
+   {   /* FIXME: prefer AGP-texturing if possible */
+      /* Data not in agp memory, or bad pitch.
+       */
+      for (done = 0; done < height ; ) {
+        struct radeon_dma_region region;
+        int lines = MIN2( height - done, RADEON_BUFFER_SIZE / dstPitch );
+        int src_pitch;
+        char *tex;
+
+         src_pitch = texImage->RowStride * texFormat->TexelBytes;
+
+        tex = (char *)texImage->Data + done * src_pitch;
+
+        memset(&region, 0, sizeof(region));
+        radeonAllocDmaRegion( rmesa, &region, lines * dstPitch, 1024 );
+
+        /* Copy texdata to dma:
+         */
+        if (0)
+           fprintf(stderr, "%s: src_pitch %d dst_pitch %d\n",
+                   __FUNCTION__, src_pitch, dstPitch);
+
+        if (src_pitch == dstPitch) {
+           memcpy( region.address, tex, lines * src_pitch );
+        } 
+        else {
+           char *buf = region.address;
+           int i;
+           for (i = 0 ; i < lines ; i++) {
+              memcpy( buf, tex, src_pitch );
+              buf += dstPitch;
+              tex += src_pitch;
+           }
+        }
+
+        radeonEmitWait( rmesa, RADEON_WAIT_3D );
+
+        
+
+        /* Blit to framebuffer
+         */
+        radeonEmitBlit( rmesa, 
+                      blit_format, 
+                      dstPitch, GET_START( &region ),    
+                      dstPitch, t->bufAddr, 
+                      0, 0, 
+                      0, done, 
+                      width, lines );
+        
+        radeonEmitWait( rmesa, RADEON_WAIT_2D );
+
+        radeonReleaseDmaRegion( rmesa, &region, __FUNCTION__ );
+        done += lines;
+      }
+   }
+}
+
+
+/**
+ * Upload the texture image associated with texture \a t at the specified
+ * level at the address relative to \a start.
+ */
+static void uploadSubImage( radeonContextPtr rmesa, radeonTexObjPtr t, 
+                           GLint hwlevel,
+                           GLint x, GLint y, GLint width, GLint height,
+                           GLuint face )
+{
+   struct gl_texture_image *texImage = NULL;
+   GLuint offset;
+   GLint imageWidth, imageHeight;
+   GLint ret;
+   drmRadeonTexture tex;
+   drmRadeonTexImage tmp;
+   const int level = hwlevel + t->base.firstLevel;
+
+   if ( RADEON_DEBUG & DEBUG_TEXTURE ) {
+      fprintf( stderr, "%s( %p, %p ) level/width/height/face = %d/%d/%d/%u\n", 
+              __FUNCTION__, t, t->base.tObj, level, width, height, face );
+   }
+
+   ASSERT(face < 6);
+
+   /* Ensure we have a valid texture to upload */
+   if ( ( hwlevel < 0 ) || ( hwlevel >= RADEON_MAX_TEXTURE_LEVELS ) ) {
+      _mesa_problem(NULL, "bad texture level in %s", __FUNCTION__);
+      return;
+   }
+
+   switch (face) {
+   case 0:
+      texImage = t->base.tObj->Image[level];
+      break;
+   case 1:
+      texImage = t->base.tObj->NegX[level];
+      break;
+   case 2:
+      texImage = t->base.tObj->PosY[level];
+      break;
+   case 3:
+      texImage = t->base.tObj->NegY[level];
+      break;
+   case 4:
+      texImage = t->base.tObj->PosZ[level];
+      break;
+   case 5:
+      texImage = t->base.tObj->NegZ[level];
+      break;
+   }
+
+   if ( !texImage ) {
+      if ( RADEON_DEBUG & DEBUG_TEXTURE )
+        fprintf( stderr, "%s: texImage %d is NULL!\n", __FUNCTION__, level );
+      return;
+   }
+   if ( !texImage->Data ) {
+      if ( RADEON_DEBUG & DEBUG_TEXTURE )
+        fprintf( stderr, "%s: image data is NULL!\n", __FUNCTION__ );
+      return;
+   }
+
+
+   if (t->base.tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
+      assert(level == 0);
+      assert(hwlevel == 0);
+      if ( RADEON_DEBUG & DEBUG_TEXTURE )
+        fprintf( stderr, "%s: image data is rectangular\n", __FUNCTION__);
+      radeonUploadRectSubImage( rmesa, t, texImage, x, y, width, height );
+      return;
+   }
+
+   imageWidth = texImage->Width;
+   imageHeight = texImage->Height;
+
+   offset = t->bufAddr;
+
+   if ( RADEON_DEBUG & (DEBUG_TEXTURE|DEBUG_IOCTL) ) {
+      GLint imageX = 0;
+      GLint imageY = 0;
+      GLint blitX = t->image[face][hwlevel].x;
+      GLint blitY = t->image[face][hwlevel].y;
+      GLint blitWidth = t->image[face][hwlevel].width;
+      GLint blitHeight = t->image[face][hwlevel].height;
+      fprintf( stderr, "   upload image: %d,%d at %d,%d\n",
+              imageWidth, imageHeight, imageX, imageY );
+      fprintf( stderr, "   upload  blit: %d,%d at %d,%d\n",
+              blitWidth, blitHeight, blitX, blitY );
+      fprintf( stderr, "       blit ofs: 0x%07x level: %d/%d\n",
+              (GLuint)offset, hwlevel, level );
+   }
+
+   t->image[face][hwlevel].data = texImage->Data;
+
+   /* Init the DRM_RADEON_TEXTURE command / drmRadeonTexture struct.
+    * NOTE: we're always use a 1KB-wide blit and I8 texture format.
+    * We used to use 1, 2 and 4-byte texels and used to use the texture
+    * width to dictate the blit width - but that won't work for compressed
+    * textures. (Brian)
+    */
+   tex.offset = offset;
+   tex.pitch = BLIT_WIDTH_BYTES / 64;
+   tex.format = RADEON_TXFORMAT_I8; /* any 1-byte texel format */
+   if (texImage->TexFormat->TexelBytes) {
+      tex.width = imageWidth * texImage->TexFormat->TexelBytes; /* in bytes */
+      tex.height = imageHeight;
+   }
+   else {
+      tex.width = imageWidth; /* compressed */
+      tex.height = imageHeight;
+      if (tex.height < 4)
+         tex.height = 4;
+   }
+   tex.image = &tmp;
+
+   /* copy (x,y,width,height,data) */
+   memcpy( &tmp, &t->image[face][hwlevel], sizeof(drmRadeonTexImage) );
+
+   LOCK_HARDWARE( rmesa );
+   do {
+      ret = drmCommandWriteRead( rmesa->dri.fd, DRM_RADEON_TEXTURE,
+                                 &tex, sizeof(drmRadeonTexture) );
+   } while ( ret && errno == EAGAIN );
+
+   UNLOCK_HARDWARE( rmesa );
+
+   if ( ret ) {
+      fprintf( stderr, "DRM_RADEON_TEXTURE: return = %d\n", ret );
+      fprintf( stderr, "   offset=0x%08x\n",
+              offset );
+      fprintf( stderr, "   image width=%d height=%d\n",
+              imageWidth, imageHeight );
+      fprintf( stderr, "    blit width=%d height=%d data=%p\n",
+              t->image[face][hwlevel].width, t->image[face][hwlevel].height,
+              t->image[face][hwlevel].data );
+      exit( 1 );
+   }
+}
+
+
+/**
+ * Upload the texture images associated with texture \a t.  This might
+ * require the allocation of texture memory.
+ * 
+ * \param rmesa Context pointer
+ * \param t Texture to be uploaded
+ * \param face Cube map face to be uploaded.  Zero for non-cube maps.
+ */
+
+int radeonUploadTexImages( radeonContextPtr rmesa, radeonTexObjPtr t, GLuint face )
+{
+   const int numLevels = t->base.lastLevel - t->base.firstLevel + 1;
+
+   if ( RADEON_DEBUG & (DEBUG_TEXTURE|DEBUG_IOCTL) ) {
+      fprintf( stderr, "%s( %p, %p ) sz=%d lvls=%d-%d\n", __FUNCTION__,
+              rmesa->glCtx, t->base.tObj, t->base.totalSize,
+              t->base.firstLevel, t->base.lastLevel );
+   }
+
+   if ( !t || t->base.totalSize == 0 )
+      return 0;
+
+   LOCK_HARDWARE( rmesa );
+
+   if ( t->base.memBlock == NULL ) {
+      int heap;
+
+      heap = driAllocateTexture( rmesa->texture_heaps, rmesa->nr_heaps,
+                                (driTextureObject *) t );
+      if ( heap == -1 ) {
+        UNLOCK_HARDWARE( rmesa );
+        return -1;
+      }
+
+      /* Set the base offset of the texture image */
+      t->bufAddr = rmesa->radeonScreen->texOffset[heap] 
+          + t->base.memBlock->ofs;
+      t->pp_txoffset = t->bufAddr;
+
+
+      /* Mark this texobj as dirty on all units:
+       */
+      t->dirty_state = TEX_ALL;
+   }
+
+
+   /* Let the world know we've used this memory recently.
+    */
+   driUpdateTextureLRU( (driTextureObject *) t );
+   UNLOCK_HARDWARE( rmesa );
+
+
+   /* Upload any images that are new */
+   if (t->base.dirty_images[face]) {
+      int i;
+      for ( i = 0 ; i < numLevels ; i++ ) {
+         if ( (t->base.dirty_images[face] & (1 << (i+t->base.firstLevel))) != 0 ) {
+            uploadSubImage( rmesa, t, i, 0, 0, t->image[face][i].width,
+                           t->image[face][i].height, face );
+         }
+      }
+      t->base.dirty_images[face] = 0;
+   }
+
+   return 0;
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_texstate.c b/src/mesa/drivers/dri/radeon/radeon_texstate.c
new file mode 100644 (file)
index 0000000..6dccd31
--- /dev/null
@@ -0,0 +1,1628 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_texstate.c,v 1.6 2002/12/16 16:18:59 dawes Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     VA Linux Systems Inc., Fremont, California.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Gareth Hughes <gareth@valinux.com>
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "colormac.h"
+#include "context.h"
+#include "macros.h"
+#include "texformat.h"
+#include "enums.h"
+
+#include "radeon_context.h"
+#include "radeon_state.h"
+#include "radeon_ioctl.h"
+#include "radeon_swtcl.h"
+#include "radeon_tex.h"
+#include "radeon_tcl.h"
+
+
+#define RADEON_TXFORMAT_AL88      RADEON_TXFORMAT_AI88
+#define RADEON_TXFORMAT_YCBCR     RADEON_TXFORMAT_YVYU422
+#define RADEON_TXFORMAT_YCBCR_REV RADEON_TXFORMAT_VYUY422
+
+#define _COLOR(f) \
+    [ MESA_FORMAT_ ## f ] = { RADEON_TXFORMAT_ ## f, 0 }
+#define _ALPHA(f) \
+    [ MESA_FORMAT_ ## f ] = { RADEON_TXFORMAT_ ## f | RADEON_TXFORMAT_ALPHA_IN_MAP, 0 }
+#define _YUV(f) \
+   [ MESA_FORMAT_ ## f ] = { RADEON_TXFORMAT_ ## f, RADEON_YUV_TO_RGB }
+#define _INVALID(f) \
+    [ MESA_FORMAT_ ## f ] = { 0xffffffff, 0 }
+#define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_YCBCR_REV) \
+                            && (tx_table[f].format != 0xffffffff) )
+
+static const struct {
+   GLuint format, filter;
+}
+tx_table[] =
+{
+   _ALPHA(RGBA8888),
+   _ALPHA(ARGB8888),
+   _INVALID(RGB888),
+   _COLOR(RGB565),
+   _ALPHA(ARGB4444),
+   _ALPHA(ARGB1555),
+   _ALPHA(AL88),
+   _INVALID(A8),
+   _INVALID(L8),
+   _COLOR(I8),
+   _INVALID(CI8),
+   _YUV(YCBCR),
+   _YUV(YCBCR_REV),
+};
+
+#undef _COLOR
+#undef _ALPHA
+#undef _INVALID
+
+/**
+ * This function computes the number of bytes of storage needed for
+ * the given texture object (all mipmap levels, all cube faces).
+ * The \c image[face][level].x/y/width/height parameters for upload/blitting
+ * are computed here.  \c pp_txfilter, \c pp_txformat, etc. will be set here
+ * too.
+ * 
+ * \param rmesa Context pointer
+ * \param tObj GL texture object whose images are to be posted to
+ *                 hardware state.
+ */
+static void radeonSetTexImages( radeonContextPtr rmesa,
+                               struct gl_texture_object *tObj )
+{
+   radeonTexObjPtr t = (radeonTexObjPtr)tObj->DriverData;
+   const struct gl_texture_image *baseImage = tObj->Image[tObj->BaseLevel];
+   GLint curOffset;
+   GLint i;
+   GLint firstLevel=0, lastLevel=0, numLevels;
+   GLint log2Width, log2Height, log2Depth;
+
+   /* Set the hardware texture format
+    */
+
+   t->pp_txformat &= ~(RADEON_TXFORMAT_FORMAT_MASK |
+                      RADEON_TXFORMAT_ALPHA_IN_MAP);
+   t->pp_txfilter &= ~RADEON_YUV_TO_RGB;
+
+   if ( VALID_FORMAT( baseImage->TexFormat->MesaFormat ) ) {
+      t->pp_txformat |= tx_table[ baseImage->TexFormat->MesaFormat ].format;
+      t->pp_txfilter |= tx_table[ baseImage->TexFormat->MesaFormat ].filter;
+   }
+   else {
+      _mesa_problem(NULL, "unexpected texture format in %s", __FUNCTION__);
+      return;
+   }
+
+
+
+   /* Compute which mipmap levels we really want to send to the hardware.
+    * This depends on the base image size, GL_TEXTURE_MIN_LOD,
+    * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
+    * Yes, this looks overly complicated, but it's all needed.
+    */
+   switch (tObj->Target) {
+   case GL_TEXTURE_1D:
+   case GL_TEXTURE_2D:
+      firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
+      firstLevel = MAX2(firstLevel, tObj->BaseLevel);
+      lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
+      lastLevel = MAX2(lastLevel, tObj->BaseLevel);
+      lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
+      lastLevel = MIN2(lastLevel, tObj->MaxLevel);
+      lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
+      log2Width = tObj->Image[firstLevel]->WidthLog2;
+      log2Height = tObj->Image[firstLevel]->HeightLog2;
+      log2Depth = 0;
+      break;
+   case GL_TEXTURE_RECTANGLE_NV:
+      firstLevel = lastLevel = 0;
+      log2Width = log2Height = 1; /* ? */
+      log2Depth = 0;
+      break;
+   default:
+      return;
+   }
+
+   /* save these values */
+   t->base.firstLevel = firstLevel;
+   t->base.lastLevel = lastLevel;
+
+   numLevels = lastLevel - firstLevel + 1;
+
+   assert(numLevels <= RADEON_MAX_TEXTURE_LEVELS);
+
+   /* Calculate mipmap offsets and dimensions for blitting (uploading)
+    * The idea is that we lay out the mipmap levels within a block of
+    * memory organized as a rectangle of width BLIT_WIDTH_BYTES.
+    */
+   curOffset = 0;
+
+   for (i = 0; i < numLevels; i++) {
+      const struct gl_texture_image *texImage;
+      GLuint size;
+
+      texImage = tObj->Image[i + firstLevel];
+      if ( !texImage )
+        break;
+
+      /* find image size in bytes */
+      if (texImage->IsCompressed) {
+         size = texImage->CompressedSize;
+      }
+      else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
+        size = ((texImage->Width * texImage->TexFormat->TexelBytes + 63)
+                & ~63) * texImage->Height;
+      }
+      else {
+         int w = texImage->Width * texImage->TexFormat->TexelBytes;
+         if (w < 32)
+            w = 32;
+         size = w * texImage->Height * texImage->Depth;
+      }
+      assert(size > 0);
+
+      if (curOffset & 0x1f) {
+         /* align to 32-byte offset */
+         curOffset = (curOffset + 0x1f) & ~0x1f;
+      }
+
+      t->image[0][i].x = curOffset % BLIT_WIDTH_BYTES;
+      t->image[0][i].y = curOffset / BLIT_WIDTH_BYTES;
+      t->image[0][i].width  = MIN2(size, BLIT_WIDTH_BYTES);
+      t->image[0][i].height = size / t->image[0][i].width;
+
+#if 0
+      /* for debugging only and only  applicable to non-rectangle targets */
+      assert(size % t->image[0][i].width == 0);
+      assert(t->image[0][i].x == 0
+             || (size < BLIT_WIDTH_BYTES && t->image[0][i].height == 1));
+#endif
+
+      if (0)
+         fprintf(stderr,
+                 "level %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
+                 i, texImage->Width, texImage->Height,
+                 t->image[0][i].x, t->image[0][i].y,
+                 t->image[0][i].width, t->image[0][i].height, size, curOffset);
+
+      curOffset += size;
+
+   }
+
+   /* Align the total size of texture memory block.
+    */
+   t->base.totalSize = (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
+
+   /* Hardware state:
+    */
+   t->pp_txfilter &= ~RADEON_MAX_MIP_LEVEL_MASK;
+   t->pp_txfilter |= (numLevels - 1) << RADEON_MAX_MIP_LEVEL_SHIFT;
+
+   t->pp_txformat &= ~(RADEON_TXFORMAT_WIDTH_MASK |
+                      RADEON_TXFORMAT_HEIGHT_MASK |
+                       RADEON_TXFORMAT_CUBIC_MAP_ENABLE);
+   t->pp_txformat |= ((log2Width << RADEON_TXFORMAT_WIDTH_SHIFT) |
+                     (log2Height << RADEON_TXFORMAT_HEIGHT_SHIFT));
+
+   t->pp_txsize = (((tObj->Image[firstLevel]->Width - 1) << 0) |
+                   ((tObj->Image[firstLevel]->Height - 1) << 16));
+
+   /* Only need to round to nearest 32 for textures, but the blitter
+    * requires 64-byte aligned pitches, and we may/may not need the
+    * blitter.   NPOT only!
+    */
+   if (baseImage->IsCompressed)
+      t->pp_txpitch = (tObj->Image[firstLevel]->Width + 63) & ~(63);
+   else
+      t->pp_txpitch = ((tObj->Image[firstLevel]->Width * baseImage->TexFormat->TexelBytes) + 63) & ~(63);
+   t->pp_txpitch -= 32;
+
+   t->dirty_state = TEX_ALL;
+
+   /* FYI: radeonUploadTexImages( rmesa, t ); used to be called here */
+}
+
+
+
+/* ================================================================
+ * Texture combine functions
+ */
+
+#define RADEON_DISABLE         0
+#define RADEON_REPLACE         1
+#define RADEON_MODULATE                2
+#define RADEON_DECAL           3
+#define RADEON_BLEND           4
+#define RADEON_ADD             5
+#define RADEON_MAX_COMBFUNC    6
+
+static GLuint radeon_color_combine[][RADEON_MAX_COMBFUNC] =
+{
+   /* Unit 0:
+    */
+   {
+      /* Disable combiner stage
+       */
+      (RADEON_COLOR_ARG_A_ZERO |
+       RADEON_COLOR_ARG_B_ZERO |
+       RADEON_COLOR_ARG_C_CURRENT_COLOR |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_REPLACE = 0x00802800
+       */
+      (RADEON_COLOR_ARG_A_ZERO |
+       RADEON_COLOR_ARG_B_ZERO |
+       RADEON_COLOR_ARG_C_T0_COLOR |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_MODULATE = 0x00800142
+       */
+      (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+       RADEON_COLOR_ARG_B_T0_COLOR |
+       RADEON_COLOR_ARG_C_ZERO |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_DECAL = 0x008c2d42
+       */
+      (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+       RADEON_COLOR_ARG_B_T0_COLOR |
+       RADEON_COLOR_ARG_C_T0_ALPHA |
+       RADEON_BLEND_CTL_BLEND |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_BLEND = 0x008c2902
+       */
+      (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+       RADEON_COLOR_ARG_B_TFACTOR_COLOR |
+       RADEON_COLOR_ARG_C_T0_COLOR |
+       RADEON_BLEND_CTL_BLEND |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_ADD = 0x00812802
+       */
+      (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+       RADEON_COLOR_ARG_B_ZERO |
+       RADEON_COLOR_ARG_C_T0_COLOR |
+       RADEON_COMP_ARG_B |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+   },
+
+   /* Unit 1:
+    */
+   {
+      /* Disable combiner stage
+       */
+      (RADEON_COLOR_ARG_A_ZERO |
+       RADEON_COLOR_ARG_B_ZERO |
+       RADEON_COLOR_ARG_C_CURRENT_COLOR |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_REPLACE = 0x00803000
+       */
+      (RADEON_COLOR_ARG_A_ZERO |
+       RADEON_COLOR_ARG_B_ZERO |
+       RADEON_COLOR_ARG_C_T1_COLOR |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_MODULATE = 0x00800182
+       */
+      (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+       RADEON_COLOR_ARG_B_T1_COLOR |
+       RADEON_COLOR_ARG_C_ZERO |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_DECAL = 0x008c3582
+       */
+      (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+       RADEON_COLOR_ARG_B_T1_COLOR |
+       RADEON_COLOR_ARG_C_T1_ALPHA |
+       RADEON_BLEND_CTL_BLEND |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_BLEND = 0x008c3102
+       */
+      (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+       RADEON_COLOR_ARG_B_TFACTOR_COLOR |
+       RADEON_COLOR_ARG_C_T1_COLOR |
+       RADEON_BLEND_CTL_BLEND |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_ADD = 0x00813002
+       */
+      (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+       RADEON_COLOR_ARG_B_ZERO |
+       RADEON_COLOR_ARG_C_T1_COLOR |
+       RADEON_COMP_ARG_B |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+   },
+
+   /* Unit 2:
+    */
+   {
+      /* Disable combiner stage
+       */
+      (RADEON_COLOR_ARG_A_ZERO |
+       RADEON_COLOR_ARG_B_ZERO |
+       RADEON_COLOR_ARG_C_CURRENT_COLOR |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_REPLACE = 0x00803800
+       */
+      (RADEON_COLOR_ARG_A_ZERO |
+       RADEON_COLOR_ARG_B_ZERO |
+       RADEON_COLOR_ARG_C_T2_COLOR |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_MODULATE = 0x008001c2
+       */
+      (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+       RADEON_COLOR_ARG_B_T2_COLOR |
+       RADEON_COLOR_ARG_C_ZERO |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_DECAL = 0x008c3dc2
+       */
+      (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+       RADEON_COLOR_ARG_B_T2_COLOR |
+       RADEON_COLOR_ARG_C_T2_ALPHA |
+       RADEON_BLEND_CTL_BLEND |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_BLEND = 0x008c3902
+       */
+      (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+       RADEON_COLOR_ARG_B_TFACTOR_COLOR |
+       RADEON_COLOR_ARG_C_T2_COLOR |
+       RADEON_BLEND_CTL_BLEND |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_ADD = 0x00813802
+       */
+      (RADEON_COLOR_ARG_A_CURRENT_COLOR |
+       RADEON_COLOR_ARG_B_ZERO |
+       RADEON_COLOR_ARG_C_T2_COLOR |
+       RADEON_COMP_ARG_B |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+   }
+};
+
+static GLuint radeon_alpha_combine[][RADEON_MAX_COMBFUNC] =
+{
+   /* Unit 0:
+    */
+   {
+      /* Disable combiner stage
+       */
+      (RADEON_ALPHA_ARG_A_ZERO |
+       RADEON_ALPHA_ARG_B_ZERO |
+       RADEON_ALPHA_ARG_C_CURRENT_ALPHA |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_REPLACE = 0x00800500
+       */
+      (RADEON_ALPHA_ARG_A_ZERO |
+       RADEON_ALPHA_ARG_B_ZERO |
+       RADEON_ALPHA_ARG_C_T0_ALPHA |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_MODULATE = 0x00800051
+       */
+      (RADEON_ALPHA_ARG_A_CURRENT_ALPHA |
+       RADEON_ALPHA_ARG_B_T0_ALPHA |
+       RADEON_ALPHA_ARG_C_ZERO |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_DECAL = 0x00800100
+       */
+      (RADEON_ALPHA_ARG_A_ZERO |
+       RADEON_ALPHA_ARG_B_ZERO |
+       RADEON_ALPHA_ARG_C_CURRENT_ALPHA |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_BLEND = 0x00800051
+       */
+      (RADEON_ALPHA_ARG_A_CURRENT_ALPHA |
+       RADEON_ALPHA_ARG_B_TFACTOR_ALPHA |
+       RADEON_ALPHA_ARG_C_T0_ALPHA |
+       RADEON_BLEND_CTL_BLEND |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_ADD = 0x00800051
+       */
+      (RADEON_ALPHA_ARG_A_CURRENT_ALPHA |
+       RADEON_ALPHA_ARG_B_ZERO |
+       RADEON_ALPHA_ARG_C_T0_ALPHA |
+       RADEON_COMP_ARG_B |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+   },
+
+   /* Unit 1:
+    */
+   {
+      /* Disable combiner stage
+       */
+      (RADEON_ALPHA_ARG_A_ZERO |
+       RADEON_ALPHA_ARG_B_ZERO |
+       RADEON_ALPHA_ARG_C_CURRENT_ALPHA |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_REPLACE = 0x00800600
+       */
+      (RADEON_ALPHA_ARG_A_ZERO |
+       RADEON_ALPHA_ARG_B_ZERO |
+       RADEON_ALPHA_ARG_C_T1_ALPHA |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_MODULATE = 0x00800061
+       */
+      (RADEON_ALPHA_ARG_A_CURRENT_ALPHA |
+       RADEON_ALPHA_ARG_B_T1_ALPHA |
+       RADEON_ALPHA_ARG_C_ZERO |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_DECAL = 0x00800100
+       */
+      (RADEON_ALPHA_ARG_A_ZERO |
+       RADEON_ALPHA_ARG_B_ZERO |
+       RADEON_ALPHA_ARG_C_CURRENT_ALPHA |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_BLEND = 0x00800061
+       */
+      (RADEON_ALPHA_ARG_A_CURRENT_ALPHA |
+       RADEON_ALPHA_ARG_B_TFACTOR_ALPHA |
+       RADEON_ALPHA_ARG_C_T1_ALPHA |
+       RADEON_BLEND_CTL_BLEND |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_ADD = 0x00800061
+       */
+      (RADEON_ALPHA_ARG_A_CURRENT_ALPHA |
+       RADEON_ALPHA_ARG_B_ZERO |
+       RADEON_ALPHA_ARG_C_T1_ALPHA |
+       RADEON_COMP_ARG_B |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+   },
+
+   /* Unit 2:
+    */
+   {
+      /* Disable combiner stage
+       */
+      (RADEON_ALPHA_ARG_A_ZERO |
+       RADEON_ALPHA_ARG_B_ZERO |
+       RADEON_ALPHA_ARG_C_CURRENT_ALPHA |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_REPLACE = 0x00800700
+       */
+      (RADEON_ALPHA_ARG_A_ZERO |
+       RADEON_ALPHA_ARG_B_ZERO |
+       RADEON_ALPHA_ARG_C_T2_ALPHA |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_MODULATE = 0x00800071
+       */
+      (RADEON_ALPHA_ARG_A_CURRENT_ALPHA |
+       RADEON_ALPHA_ARG_B_T2_ALPHA |
+       RADEON_ALPHA_ARG_C_ZERO |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_DECAL = 0x00800100
+       */
+      (RADEON_ALPHA_ARG_A_ZERO |
+       RADEON_ALPHA_ARG_B_ZERO |
+       RADEON_ALPHA_ARG_C_CURRENT_ALPHA |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_BLEND = 0x00800071
+       */
+      (RADEON_ALPHA_ARG_A_CURRENT_ALPHA |
+       RADEON_ALPHA_ARG_B_TFACTOR_ALPHA |
+       RADEON_ALPHA_ARG_C_T2_ALPHA |
+       RADEON_BLEND_CTL_BLEND |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+
+      /* GL_ADD = 0x00800021
+       */
+      (RADEON_ALPHA_ARG_A_CURRENT_ALPHA |
+       RADEON_ALPHA_ARG_B_ZERO |
+       RADEON_ALPHA_ARG_C_T2_ALPHA |
+       RADEON_COMP_ARG_B |
+       RADEON_BLEND_CTL_ADD |
+       RADEON_SCALE_1X |
+       RADEON_CLAMP_TX),
+   }
+};
+
+
+/* GL_ARB_texture_env_combine support
+ */
+
+/* The color tables have combine functions for GL_SRC_COLOR,
+ * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
+ */
+static GLuint radeon_texture_color[][RADEON_MAX_TEXTURE_UNITS] =
+{
+   {
+      RADEON_COLOR_ARG_A_T0_COLOR,
+      RADEON_COLOR_ARG_A_T1_COLOR,
+      RADEON_COLOR_ARG_A_T2_COLOR
+   },
+   {
+      RADEON_COLOR_ARG_A_T0_COLOR | RADEON_COMP_ARG_A,
+      RADEON_COLOR_ARG_A_T1_COLOR | RADEON_COMP_ARG_A,
+      RADEON_COLOR_ARG_A_T2_COLOR | RADEON_COMP_ARG_A
+   },
+   {
+      RADEON_COLOR_ARG_A_T0_ALPHA,
+      RADEON_COLOR_ARG_A_T1_ALPHA,
+      RADEON_COLOR_ARG_A_T2_ALPHA
+   },
+   {
+      RADEON_COLOR_ARG_A_T0_ALPHA | RADEON_COMP_ARG_A,
+      RADEON_COLOR_ARG_A_T1_ALPHA | RADEON_COMP_ARG_A,
+      RADEON_COLOR_ARG_A_T2_ALPHA | RADEON_COMP_ARG_A
+   },
+};
+
+static GLuint radeon_tfactor_color[] =
+{
+   RADEON_COLOR_ARG_A_TFACTOR_COLOR,
+   RADEON_COLOR_ARG_A_TFACTOR_COLOR | RADEON_COMP_ARG_A,
+   RADEON_COLOR_ARG_A_TFACTOR_ALPHA,
+   RADEON_COLOR_ARG_A_TFACTOR_ALPHA | RADEON_COMP_ARG_A
+};
+
+static GLuint radeon_primary_color[] =
+{
+   RADEON_COLOR_ARG_A_DIFFUSE_COLOR,
+   RADEON_COLOR_ARG_A_DIFFUSE_COLOR | RADEON_COMP_ARG_A,
+   RADEON_COLOR_ARG_A_DIFFUSE_ALPHA,
+   RADEON_COLOR_ARG_A_DIFFUSE_ALPHA | RADEON_COMP_ARG_A
+};
+
+static GLuint radeon_previous_color[] =
+{
+   RADEON_COLOR_ARG_A_CURRENT_COLOR,
+   RADEON_COLOR_ARG_A_CURRENT_COLOR | RADEON_COMP_ARG_A,
+   RADEON_COLOR_ARG_A_CURRENT_ALPHA,
+   RADEON_COLOR_ARG_A_CURRENT_ALPHA | RADEON_COMP_ARG_A
+};
+
+/* GL_ZERO table - indices 0-3
+ * GL_ONE  table - indices 1-4
+ */
+static GLuint radeon_zero_color[] =
+{
+   RADEON_COLOR_ARG_A_ZERO,
+   RADEON_COLOR_ARG_A_ZERO | RADEON_COMP_ARG_A,
+   RADEON_COLOR_ARG_A_ZERO,
+   RADEON_COLOR_ARG_A_ZERO | RADEON_COMP_ARG_A,
+   RADEON_COLOR_ARG_A_ZERO
+};
+
+
+/* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
+ */
+static GLuint radeon_texture_alpha[][RADEON_MAX_TEXTURE_UNITS] =
+{
+   {
+      RADEON_ALPHA_ARG_A_T0_ALPHA,
+      RADEON_ALPHA_ARG_A_T1_ALPHA,
+      RADEON_ALPHA_ARG_A_T2_ALPHA
+   },
+   {
+      RADEON_ALPHA_ARG_A_T0_ALPHA | RADEON_COMP_ARG_A,
+      RADEON_ALPHA_ARG_A_T1_ALPHA | RADEON_COMP_ARG_A,
+      RADEON_ALPHA_ARG_A_T2_ALPHA | RADEON_COMP_ARG_A
+   },
+};
+
+static GLuint radeon_tfactor_alpha[] =
+{
+   RADEON_ALPHA_ARG_A_TFACTOR_ALPHA,
+   RADEON_ALPHA_ARG_A_TFACTOR_ALPHA | RADEON_COMP_ARG_A
+};
+
+static GLuint radeon_primary_alpha[] =
+{
+   RADEON_ALPHA_ARG_A_DIFFUSE_ALPHA,
+   RADEON_ALPHA_ARG_A_DIFFUSE_ALPHA | RADEON_COMP_ARG_A
+};
+
+static GLuint radeon_previous_alpha[] =
+{
+   RADEON_ALPHA_ARG_A_CURRENT_ALPHA,
+   RADEON_ALPHA_ARG_A_CURRENT_ALPHA | RADEON_COMP_ARG_A
+};
+
+/* GL_ZERO table - indices 0-1
+ * GL_ONE  table - indices 1-2
+ */
+static GLuint radeon_zero_alpha[] =
+{
+   RADEON_ALPHA_ARG_A_ZERO,
+   RADEON_ALPHA_ARG_A_ZERO | RADEON_COMP_ARG_A,
+   RADEON_ALPHA_ARG_A_ZERO
+};
+
+
+/* Extract the arg from slot A, shift it into the correct argument slot
+ * and set the corresponding complement bit.
+ */
+#define RADEON_COLOR_ARG( n, arg )                     \
+do {                                                   \
+   color_combine |=                                    \
+      ((color_arg[n] & RADEON_COLOR_ARG_MASK)          \
+       << RADEON_COLOR_ARG_##arg##_SHIFT);             \
+   color_combine |=                                    \
+      ((color_arg[n] >> RADEON_COMP_ARG_SHIFT)         \
+       << RADEON_COMP_ARG_##arg##_SHIFT);              \
+} while (0)
+
+#define RADEON_ALPHA_ARG( n, arg )                     \
+do {                                                   \
+   alpha_combine |=                                    \
+      ((alpha_arg[n] & RADEON_ALPHA_ARG_MASK)          \
+       << RADEON_ALPHA_ARG_##arg##_SHIFT);             \
+   alpha_combine |=                                    \
+      ((alpha_arg[n] >> RADEON_COMP_ARG_SHIFT)         \
+       << RADEON_COMP_ARG_##arg##_SHIFT);              \
+} while (0)
+
+
+/* ================================================================
+ * Texture unit state management
+ */
+
+static GLboolean radeonUpdateTextureEnv( GLcontext *ctx, int unit )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   GLuint color_combine, alpha_combine;
+
+   /* texUnit->_Current can be NULL if and only if the texture unit is
+    * not actually enabled.
+    */
+   assert( (texUnit->_ReallyEnabled == 0)
+          || (texUnit->_Current != NULL) );
+
+   if ( RADEON_DEBUG & DEBUG_TEXTURE ) {
+      fprintf( stderr, "%s( %p, %d )\n", __FUNCTION__, ctx, unit );
+   }
+
+   /* Set the texture environment state.  Isn't this nice and clean?
+    * The chip will automagically set the texture alpha to 0xff when
+    * the texture format does not include an alpha component.  This
+    * reduces the amount of special-casing we have to do, alpha-only
+    * textures being a notable exception.
+    */
+   if ( !texUnit->_ReallyEnabled ) {
+      /* Don't cache these results.
+       */
+      rmesa->state.texture.unit[unit].format = 0;
+      rmesa->state.texture.unit[unit].envMode = 0;
+      color_combine = radeon_color_combine[unit][RADEON_DISABLE];
+      alpha_combine = radeon_alpha_combine[unit][RADEON_DISABLE];
+   }
+   else {
+      const struct gl_texture_object *tObj = texUnit->_Current;
+      const GLenum format = tObj->Image[tObj->BaseLevel]->Format;
+      GLuint color_arg[3], alpha_arg[3];
+      GLuint i, numColorArgs = 0, numAlphaArgs = 0;
+      GLuint RGBshift = texUnit->CombineScaleShiftRGB;
+      GLuint Ashift = texUnit->CombineScaleShiftA;
+
+      switch ( texUnit->EnvMode ) {
+      case GL_REPLACE:
+         switch ( format ) {
+        case GL_RGBA:
+         case GL_LUMINANCE_ALPHA:
+         case GL_INTENSITY:
+           color_combine = radeon_color_combine[unit][RADEON_REPLACE];
+           alpha_combine = radeon_alpha_combine[unit][RADEON_REPLACE];
+           break;
+        case GL_ALPHA:
+           color_combine = radeon_color_combine[unit][RADEON_DISABLE];
+           alpha_combine = radeon_alpha_combine[unit][RADEON_REPLACE];
+           break;
+        case GL_LUMINANCE:
+        case GL_RGB:
+        case GL_YCBCR_MESA:
+           color_combine = radeon_color_combine[unit][RADEON_REPLACE];
+           alpha_combine = radeon_alpha_combine[unit][RADEON_DISABLE];
+           break;
+        case GL_COLOR_INDEX:
+        default:
+           return GL_FALSE;
+        }
+        break;
+
+      case GL_MODULATE:
+        switch ( format ) {
+        case GL_RGBA:
+        case GL_LUMINANCE_ALPHA:
+        case GL_INTENSITY:
+           color_combine = radeon_color_combine[unit][RADEON_MODULATE];
+           alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE];
+           break;
+        case GL_ALPHA:
+           color_combine = radeon_color_combine[unit][RADEON_DISABLE];
+           alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE];
+           break;
+        case GL_RGB:
+        case GL_LUMINANCE:
+        case GL_YCBCR_MESA:
+           color_combine = radeon_color_combine[unit][RADEON_MODULATE];
+           alpha_combine = radeon_alpha_combine[unit][RADEON_DISABLE];
+           break;
+        case GL_COLOR_INDEX:
+        default:
+           return GL_FALSE;
+        }
+        break;
+
+      case GL_DECAL:
+        switch ( format ) {
+        case GL_RGBA:
+        case GL_RGB:
+        case GL_YCBCR_MESA:
+           color_combine = radeon_color_combine[unit][RADEON_DECAL];
+           alpha_combine = radeon_alpha_combine[unit][RADEON_DISABLE];
+           break;
+        case GL_ALPHA:
+        case GL_LUMINANCE:
+        case GL_LUMINANCE_ALPHA:
+        case GL_INTENSITY:
+           color_combine = radeon_color_combine[unit][RADEON_DISABLE];
+           alpha_combine = radeon_alpha_combine[unit][RADEON_DISABLE];
+           break;
+        case GL_COLOR_INDEX:
+        default:
+           return GL_FALSE;
+        }
+        break;
+
+      case GL_BLEND:
+        switch ( format ) {
+        case GL_RGBA:
+        case GL_RGB:
+        case GL_LUMINANCE:
+        case GL_LUMINANCE_ALPHA:
+        case GL_YCBCR_MESA:
+           color_combine = radeon_color_combine[unit][RADEON_BLEND];
+           alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE];
+           break;
+        case GL_ALPHA:
+           color_combine = radeon_color_combine[unit][RADEON_DISABLE];
+           alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE];
+           break;
+        case GL_INTENSITY:
+           color_combine = radeon_color_combine[unit][RADEON_BLEND];
+           alpha_combine = radeon_alpha_combine[unit][RADEON_BLEND];
+           break;
+        case GL_COLOR_INDEX:
+        default:
+           return GL_FALSE;
+        }
+        break;
+
+      case GL_ADD:
+        switch ( format ) {
+        case GL_RGBA:
+        case GL_RGB:
+        case GL_LUMINANCE:
+        case GL_LUMINANCE_ALPHA:
+        case GL_YCBCR_MESA:
+           color_combine = radeon_color_combine[unit][RADEON_ADD];
+           alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE];
+           break;
+        case GL_ALPHA:
+           color_combine = radeon_color_combine[unit][RADEON_DISABLE];
+           alpha_combine = radeon_alpha_combine[unit][RADEON_MODULATE];
+           break;
+        case GL_INTENSITY:
+           color_combine = radeon_color_combine[unit][RADEON_ADD];
+           alpha_combine = radeon_alpha_combine[unit][RADEON_ADD];
+           break;
+        case GL_COLOR_INDEX:
+        default:
+           return GL_FALSE;
+        }
+        break;
+
+      case GL_COMBINE:
+        /* Don't cache these results.
+         */
+        rmesa->state.texture.unit[unit].format = 0;
+        rmesa->state.texture.unit[unit].envMode = 0;
+
+        /* Step 0:
+         * Calculate how many arguments we need to process.
+         */
+        switch ( texUnit->CombineModeRGB ) {
+        case GL_REPLACE:
+           numColorArgs = 1;
+           break;
+        case GL_MODULATE:
+        case GL_ADD:
+        case GL_ADD_SIGNED:
+        case GL_SUBTRACT:
+        case GL_DOT3_RGB:
+        case GL_DOT3_RGBA:
+        case GL_DOT3_RGB_EXT:
+        case GL_DOT3_RGBA_EXT:
+           numColorArgs = 2;
+           break;
+        case GL_INTERPOLATE:
+        case GL_MODULATE_ADD_ATI:
+        case GL_MODULATE_SIGNED_ADD_ATI:
+        case GL_MODULATE_SUBTRACT_ATI:
+           numColorArgs = 3;
+           break;
+        default:
+           return GL_FALSE;
+        }
+
+        switch ( texUnit->CombineModeA ) {
+        case GL_REPLACE:
+           numAlphaArgs = 1;
+           break;
+        case GL_MODULATE:
+        case GL_ADD:
+        case GL_ADD_SIGNED:
+        case GL_SUBTRACT:
+           numAlphaArgs = 2;
+           break;
+        case GL_INTERPOLATE:
+        case GL_MODULATE_ADD_ATI:
+        case GL_MODULATE_SIGNED_ADD_ATI:
+        case GL_MODULATE_SUBTRACT_ATI:
+           numAlphaArgs = 3;
+           break;
+        default:
+           return GL_FALSE;
+        }
+
+        /* Step 1:
+         * Extract the color and alpha combine function arguments.
+         */
+        for ( i = 0 ; i < numColorArgs ; i++ ) {
+           const GLuint op = texUnit->CombineOperandRGB[i] - GL_SRC_COLOR;
+           assert(op >= 0);
+           assert(op <= 3);
+           switch ( texUnit->CombineSourceRGB[i] ) {
+           case GL_TEXTURE:
+              color_arg[i] = radeon_texture_color[op][unit];
+              break;
+           case GL_CONSTANT:
+              color_arg[i] = radeon_tfactor_color[op];
+              break;
+           case GL_PRIMARY_COLOR:
+              color_arg[i] = radeon_primary_color[op];
+              break;
+           case GL_PREVIOUS:
+              color_arg[i] = radeon_previous_color[op];
+              break;
+           case GL_ZERO:
+              color_arg[i] = radeon_zero_color[op];
+              break;
+           case GL_ONE:
+              color_arg[i] = radeon_zero_color[op+1];
+              break;
+           default:
+              return GL_FALSE;
+           }
+        }
+
+        for ( i = 0 ; i < numAlphaArgs ; i++ ) {
+           const GLuint op = texUnit->CombineOperandA[i] - GL_SRC_ALPHA;
+           assert(op >= 0);
+           assert(op <= 1);
+           switch ( texUnit->CombineSourceA[i] ) {
+           case GL_TEXTURE:
+              alpha_arg[i] = radeon_texture_alpha[op][unit];
+              break;
+           case GL_CONSTANT:
+              alpha_arg[i] = radeon_tfactor_alpha[op];
+              break;
+           case GL_PRIMARY_COLOR:
+              alpha_arg[i] = radeon_primary_alpha[op];
+              break;
+           case GL_PREVIOUS:
+              alpha_arg[i] = radeon_previous_alpha[op];
+              break;
+           case GL_ZERO:
+              alpha_arg[i] = radeon_zero_alpha[op];
+              break;
+           case GL_ONE:
+              alpha_arg[i] = radeon_zero_alpha[op+1];
+              break;
+           default:
+              return GL_FALSE;
+           }
+        }
+
+        /* Step 2:
+         * Build up the color and alpha combine functions.
+         */
+        switch ( texUnit->CombineModeRGB ) {
+        case GL_REPLACE:
+           color_combine = (RADEON_COLOR_ARG_A_ZERO |
+                            RADEON_COLOR_ARG_B_ZERO |
+                            RADEON_BLEND_CTL_ADD |
+                            RADEON_CLAMP_TX);
+           RADEON_COLOR_ARG( 0, C );
+           break;
+        case GL_MODULATE:
+           color_combine = (RADEON_COLOR_ARG_C_ZERO |
+                            RADEON_BLEND_CTL_ADD |
+                            RADEON_CLAMP_TX);
+           RADEON_COLOR_ARG( 0, A );
+           RADEON_COLOR_ARG( 1, B );
+           break;
+        case GL_ADD:
+           color_combine = (RADEON_COLOR_ARG_B_ZERO |
+                            RADEON_COMP_ARG_B |
+                            RADEON_BLEND_CTL_ADD |
+                            RADEON_CLAMP_TX);
+           RADEON_COLOR_ARG( 0, A );
+           RADEON_COLOR_ARG( 1, C );
+           break;
+        case GL_ADD_SIGNED:
+           color_combine = (RADEON_COLOR_ARG_B_ZERO |
+                            RADEON_COMP_ARG_B |
+                            RADEON_BLEND_CTL_ADDSIGNED |
+                            RADEON_CLAMP_TX);
+           RADEON_COLOR_ARG( 0, A );
+           RADEON_COLOR_ARG( 1, C );
+           break;
+        case GL_SUBTRACT:
+           color_combine = (RADEON_COLOR_ARG_B_ZERO |
+                            RADEON_COMP_ARG_B |
+                            RADEON_BLEND_CTL_SUBTRACT |
+                            RADEON_CLAMP_TX);
+           RADEON_COLOR_ARG( 0, A );
+           RADEON_COLOR_ARG( 1, C );
+           break;
+        case GL_INTERPOLATE:
+           color_combine = (RADEON_BLEND_CTL_BLEND |
+                            RADEON_CLAMP_TX);
+           RADEON_COLOR_ARG( 0, B );
+           RADEON_COLOR_ARG( 1, A );
+           RADEON_COLOR_ARG( 2, C );
+           break;
+
+        case GL_DOT3_RGB_EXT:
+        case GL_DOT3_RGBA_EXT:
+           /* The EXT version of the DOT3 extension does not support the
+            * scale factor, but the ARB version (and the version in OpenGL
+            * 1.3) does.
+            */
+           RGBshift = 0;
+           Ashift = 0;
+           /* FALLTHROUGH */
+
+        case GL_DOT3_RGB:
+        case GL_DOT3_RGBA:
+           /* The R100 / RV200 only support a 1X multiplier in hardware
+            * w/the ARB version.
+            */
+           if ( RGBshift != (RADEON_SCALE_1X >> RADEON_SCALE_SHIFT) ) {
+              return GL_FALSE;
+           }
+
+           RGBshift += 2;
+           Ashift = RGBshift;
+
+           color_combine = (RADEON_COLOR_ARG_C_ZERO |
+                            RADEON_BLEND_CTL_DOT3 |
+                            RADEON_CLAMP_TX);
+           RADEON_COLOR_ARG( 0, A );
+           RADEON_COLOR_ARG( 1, B );
+           break;
+
+        case GL_MODULATE_ADD_ATI:
+           color_combine = (RADEON_BLEND_CTL_ADD |
+                            RADEON_CLAMP_TX);
+           RADEON_COLOR_ARG( 0, A );
+           RADEON_COLOR_ARG( 1, C );
+           RADEON_COLOR_ARG( 2, B );
+           break;
+        case GL_MODULATE_SIGNED_ADD_ATI:
+           color_combine = (RADEON_BLEND_CTL_ADDSIGNED |
+                            RADEON_CLAMP_TX);
+           RADEON_COLOR_ARG( 0, A );
+           RADEON_COLOR_ARG( 1, C );
+           RADEON_COLOR_ARG( 2, B );
+           break;
+        case GL_MODULATE_SUBTRACT_ATI:
+           color_combine = (RADEON_BLEND_CTL_SUBTRACT |
+                            RADEON_CLAMP_TX);
+           RADEON_COLOR_ARG( 0, A );
+           RADEON_COLOR_ARG( 1, C );
+           RADEON_COLOR_ARG( 2, B );
+           break;
+        default:
+           return GL_FALSE;
+        }
+
+        switch ( texUnit->CombineModeA ) {
+        case GL_REPLACE:
+           alpha_combine = (RADEON_ALPHA_ARG_A_ZERO |
+                            RADEON_ALPHA_ARG_B_ZERO |
+                            RADEON_BLEND_CTL_ADD |
+                            RADEON_CLAMP_TX);
+           RADEON_ALPHA_ARG( 0, C );
+           break;
+        case GL_MODULATE:
+           alpha_combine = (RADEON_ALPHA_ARG_C_ZERO |
+                            RADEON_BLEND_CTL_ADD |
+                            RADEON_CLAMP_TX);
+           RADEON_ALPHA_ARG( 0, A );
+           RADEON_ALPHA_ARG( 1, B );
+           break;
+        case GL_ADD:
+           alpha_combine = (RADEON_ALPHA_ARG_B_ZERO |
+                            RADEON_COMP_ARG_B |
+                            RADEON_BLEND_CTL_ADD |
+                            RADEON_CLAMP_TX);
+           RADEON_ALPHA_ARG( 0, A );
+           RADEON_ALPHA_ARG( 1, C );
+           break;
+        case GL_ADD_SIGNED:
+           alpha_combine = (RADEON_ALPHA_ARG_B_ZERO |
+                            RADEON_COMP_ARG_B |
+                            RADEON_BLEND_CTL_ADDSIGNED |
+                            RADEON_CLAMP_TX);
+           RADEON_ALPHA_ARG( 0, A );
+           RADEON_ALPHA_ARG( 1, C );
+           break;
+        case GL_SUBTRACT:
+           alpha_combine = (RADEON_COLOR_ARG_B_ZERO |
+                            RADEON_COMP_ARG_B |
+                            RADEON_BLEND_CTL_SUBTRACT |
+                            RADEON_CLAMP_TX);
+           RADEON_ALPHA_ARG( 0, A );
+           RADEON_ALPHA_ARG( 1, C );
+           break;
+        case GL_INTERPOLATE:
+           alpha_combine = (RADEON_BLEND_CTL_BLEND |
+                            RADEON_CLAMP_TX);
+           RADEON_ALPHA_ARG( 0, B );
+           RADEON_ALPHA_ARG( 1, A );
+           RADEON_ALPHA_ARG( 2, C );
+           break;
+
+        case GL_MODULATE_ADD_ATI:
+           alpha_combine = (RADEON_BLEND_CTL_ADD |
+                            RADEON_CLAMP_TX);
+           RADEON_ALPHA_ARG( 0, A );
+           RADEON_ALPHA_ARG( 1, C );
+           RADEON_ALPHA_ARG( 2, B );
+           break;
+        case GL_MODULATE_SIGNED_ADD_ATI:
+           alpha_combine = (RADEON_BLEND_CTL_ADDSIGNED |
+                            RADEON_CLAMP_TX);
+           RADEON_ALPHA_ARG( 0, A );
+           RADEON_ALPHA_ARG( 1, C );
+           RADEON_ALPHA_ARG( 2, B );
+           break;
+        case GL_MODULATE_SUBTRACT_ATI:
+           alpha_combine = (RADEON_BLEND_CTL_SUBTRACT |
+                            RADEON_CLAMP_TX);
+           RADEON_ALPHA_ARG( 0, A );
+           RADEON_ALPHA_ARG( 1, C );
+           RADEON_ALPHA_ARG( 2, B );
+           break;
+        default:
+           return GL_FALSE;
+        }
+
+        if ( (texUnit->CombineModeRGB == GL_DOT3_RGB_EXT)
+             || (texUnit->CombineModeRGB == GL_DOT3_RGB) ) {
+           alpha_combine |= RADEON_DOT_ALPHA_DONT_REPLICATE;
+        }
+
+        /* Step 3:
+         * Apply the scale factor.
+         */
+        color_combine |= (RGBshift << RADEON_SCALE_SHIFT);
+        alpha_combine |= (Ashift   << RADEON_SCALE_SHIFT);
+
+        /* All done!
+         */
+        break;
+
+      default:
+        return GL_FALSE;
+      }
+   }
+
+   if ( rmesa->hw.tex[unit].cmd[TEX_PP_TXCBLEND] != color_combine ||
+       rmesa->hw.tex[unit].cmd[TEX_PP_TXABLEND] != alpha_combine ) {
+      RADEON_STATECHANGE( rmesa, tex[unit] );
+      rmesa->hw.tex[unit].cmd[TEX_PP_TXCBLEND] = color_combine;
+      rmesa->hw.tex[unit].cmd[TEX_PP_TXABLEND] = alpha_combine;
+   }
+
+   return GL_TRUE;
+}
+
+#define TEXOBJ_TXFILTER_MASK (RADEON_MAX_MIP_LEVEL_MASK |      \
+                             RADEON_MIN_FILTER_MASK |          \
+                             RADEON_MAG_FILTER_MASK |          \
+                             RADEON_MAX_ANISO_MASK |           \
+                             RADEON_YUV_TO_RGB |               \
+                             RADEON_YUV_TEMPERATURE_MASK |     \
+                             RADEON_CLAMP_S_MASK |             \
+                             RADEON_CLAMP_T_MASK |             \
+                             RADEON_BORDER_MODE_D3D )
+
+#define TEXOBJ_TXFORMAT_MASK (RADEON_TXFORMAT_WIDTH_MASK |     \
+                             RADEON_TXFORMAT_HEIGHT_MASK |     \
+                             RADEON_TXFORMAT_FORMAT_MASK |     \
+                              RADEON_TXFORMAT_F5_WIDTH_MASK |  \
+                              RADEON_TXFORMAT_F5_HEIGHT_MASK | \
+                             RADEON_TXFORMAT_ALPHA_IN_MAP |    \
+                             RADEON_TXFORMAT_CUBIC_MAP_ENABLE |        \
+                              RADEON_TXFORMAT_NON_POWER2)
+
+
+static void import_tex_obj_state( radeonContextPtr rmesa,
+                                 int unit,
+                                 radeonTexObjPtr texobj )
+{
+   GLuint *cmd = RADEON_DB_STATE( tex[unit] );
+
+   cmd[TEX_PP_TXFILTER] &= ~TEXOBJ_TXFILTER_MASK;
+   cmd[TEX_PP_TXFILTER] |= texobj->pp_txfilter & TEXOBJ_TXFILTER_MASK;
+   cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
+   cmd[TEX_PP_TXFORMAT] |= texobj->pp_txformat & TEXOBJ_TXFORMAT_MASK;
+   cmd[TEX_PP_TXOFFSET] = texobj->pp_txoffset;
+   cmd[TEX_PP_BORDER_COLOR] = texobj->pp_border_color;
+   RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.tex[unit] );
+
+   if (texobj->base.tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
+      GLuint *txr_cmd = RADEON_DB_STATE( txr[unit] );
+      txr_cmd[TXR_PP_TEX_SIZE] = texobj->pp_txsize; /* NPOT only! */
+      txr_cmd[TXR_PP_TEX_PITCH] = texobj->pp_txpitch; /* NPOT only! */
+      RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.txr[unit] );
+   }
+
+   texobj->dirty_state &= ~(1<<unit);
+}
+
+
+
+
+static void set_texgen_matrix( radeonContextPtr rmesa, 
+                              GLuint unit,
+                              const GLfloat *s_plane,
+                              const GLfloat *t_plane )
+{
+   static const GLfloat scale_identity[4] = { 1,1,1,1 };
+
+   if (!TEST_EQ_4V( s_plane, scale_identity) ||
+       !TEST_EQ_4V( t_plane, scale_identity)) {
+      rmesa->TexGenEnabled |= RADEON_TEXMAT_0_ENABLE<<unit;
+      rmesa->TexGenMatrix[unit].m[0]  = s_plane[0];
+      rmesa->TexGenMatrix[unit].m[4]  = s_plane[1];
+      rmesa->TexGenMatrix[unit].m[8]  = s_plane[2];
+      rmesa->TexGenMatrix[unit].m[12] = s_plane[3];
+
+      rmesa->TexGenMatrix[unit].m[1]  = t_plane[0];
+      rmesa->TexGenMatrix[unit].m[5]  = t_plane[1];
+      rmesa->TexGenMatrix[unit].m[9]  = t_plane[2];
+      rmesa->TexGenMatrix[unit].m[13] = t_plane[3];
+      rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
+   }
+}
+
+/* Ignoring the Q texcoord for now.
+ *
+ * Returns GL_FALSE if fallback required.  
+ */
+static GLboolean radeon_validate_texgen( GLcontext *ctx, GLuint unit )
+{  
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4;
+   GLuint tmp = rmesa->TexGenEnabled;
+
+   rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_TEXMAT_0_ENABLE<<unit);
+   rmesa->TexGenEnabled &= ~(RADEON_TEXMAT_0_ENABLE<<unit);
+   rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_INPUT_MASK<<inputshift);
+   rmesa->TexGenNeedNormals[unit] = 0;
+
+   if ((texUnit->TexGenEnabled & (S_BIT|T_BIT)) == 0) {
+      /* Disabled, no fallback:
+       */
+      rmesa->TexGenEnabled |= 
+        (RADEON_TEXGEN_INPUT_TEXCOORD_0+unit) << inputshift;
+      return GL_TRUE;
+   }
+   else if (texUnit->TexGenEnabled & Q_BIT) {
+      /* Very easy to do this, in fact would remove a fallback case
+       * elsewhere, but I haven't done it yet...  Fallback: 
+       */
+      fprintf(stderr, "fallback Q_BIT\n");
+      return GL_FALSE;
+   }
+   else if ((texUnit->TexGenEnabled & (S_BIT|T_BIT)) != (S_BIT|T_BIT) ||
+           texUnit->GenModeS != texUnit->GenModeT) {
+      /* Mixed modes, fallback:
+       */
+      /* fprintf(stderr, "fallback mixed texgen\n"); */
+      return GL_FALSE;
+   }
+   else
+      rmesa->TexGenEnabled |= RADEON_TEXGEN_TEXMAT_0_ENABLE << unit;
+
+   switch (texUnit->GenModeS) {
+   case GL_OBJECT_LINEAR:
+      rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_OBJ << inputshift;
+      set_texgen_matrix( rmesa, unit, 
+                        texUnit->ObjectPlaneS,
+                        texUnit->ObjectPlaneT);
+      break;
+
+   case GL_EYE_LINEAR:
+      rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE << inputshift;
+      set_texgen_matrix( rmesa, unit, 
+                        texUnit->EyePlaneS,
+                        texUnit->EyePlaneT);
+      break;
+
+   case GL_REFLECTION_MAP_NV:
+      rmesa->TexGenNeedNormals[unit] = GL_TRUE;
+      rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE_REFLECT<<inputshift;
+      break;
+
+   case GL_NORMAL_MAP_NV:
+      rmesa->TexGenNeedNormals[unit] = GL_TRUE;
+      rmesa->TexGenEnabled |= RADEON_TEXGEN_INPUT_EYE_NORMAL<<inputshift;
+      break;
+
+   case GL_SPHERE_MAP:
+   default:
+      /* Unsupported mode, fallback:
+       */
+      /*  fprintf(stderr, "fallback unsupported texgen\n"); */
+      return GL_FALSE;
+   }
+
+   if (tmp != rmesa->TexGenEnabled) {
+      rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
+   }
+
+   return GL_TRUE;
+}
+
+
+static void disable_tex( GLcontext *ctx, int unit )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   if (rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (RADEON_TEX_0_ENABLE<<unit)) {
+      /* Texture unit disabled */
+      if ( rmesa->state.texture.unit[unit].texobj != NULL ) {
+        /* The old texture is no longer bound to this texture unit.
+         * Mark it as such.
+         */
+
+        rmesa->state.texture.unit[unit].texobj->base.bound &= ~(1UL << unit);
+        rmesa->state.texture.unit[unit].texobj = NULL;
+      }
+
+      RADEON_STATECHANGE( rmesa, ctx );
+      rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= 
+         ~((RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE) << unit);
+
+      RADEON_STATECHANGE( rmesa, tcl );
+      switch (unit) {
+      case 0:
+        rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~(RADEON_TCL_VTX_ST0 |
+                                                  RADEON_TCL_VTX_Q0);
+           break;
+      case 1:
+        rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~(RADEON_TCL_VTX_ST1 |
+                                                  RADEON_TCL_VTX_Q1);
+        break;
+      default:
+        break;
+      }
+
+
+      if (rmesa->TclFallback & (RADEON_TCL_FALLBACK_TEXGEN_0<<unit)) {
+        TCL_FALLBACK( ctx, (RADEON_TCL_FALLBACK_TEXGEN_0<<unit), GL_FALSE);
+        rmesa->recheck_texgen[unit] = GL_TRUE;
+      }
+
+
+
+      {
+        GLuint inputshift = RADEON_TEXGEN_0_INPUT_SHIFT + unit*4;
+        GLuint tmp = rmesa->TexGenEnabled;
+
+        rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_TEXMAT_0_ENABLE<<unit);
+        rmesa->TexGenEnabled &= ~(RADEON_TEXMAT_0_ENABLE<<unit);
+        rmesa->TexGenEnabled &= ~(RADEON_TEXGEN_INPUT_MASK<<inputshift);
+        rmesa->TexGenNeedNormals[unit] = 0;
+        rmesa->TexGenEnabled |= 
+            (RADEON_TEXGEN_INPUT_TEXCOORD_0+unit) << inputshift;
+
+        if (tmp != rmesa->TexGenEnabled) {
+           rmesa->recheck_texgen[unit] = GL_TRUE;
+           rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
+        }
+      }
+   }
+}
+
+static GLboolean enable_tex_2d( GLcontext *ctx, int unit )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   struct gl_texture_object *tObj = texUnit->_Current;
+   radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData;
+
+   /* Need to load the 2d images associated with this unit.
+    */
+   if (t->pp_txformat & RADEON_TXFORMAT_NON_POWER2) {
+      t->pp_txformat &= ~RADEON_TXFORMAT_NON_POWER2;
+      t->base.dirty_images[0] = ~0;
+   }
+
+   ASSERT(tObj->Target == GL_TEXTURE_2D || tObj->Target == GL_TEXTURE_1D);
+
+   if ( t->base.dirty_images[0] ) {
+      RADEON_FIREVERTICES( rmesa );
+      radeonSetTexImages( rmesa, tObj );
+      radeonUploadTexImages( rmesa, (radeonTexObjPtr) tObj->DriverData, 0 );
+      if ( !t->base.memBlock ) 
+       return GL_FALSE;
+   }
+
+   return GL_TRUE;
+}
+
+static GLboolean enable_tex_rect( GLcontext *ctx, int unit )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   struct gl_texture_object *tObj = texUnit->_Current;
+   radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData;
+
+   if (!(t->pp_txformat & RADEON_TXFORMAT_NON_POWER2)) {
+      t->pp_txformat |= RADEON_TXFORMAT_NON_POWER2;
+      t->base.dirty_images[0] = ~0;
+   }
+
+   ASSERT(tObj->Target == GL_TEXTURE_RECTANGLE_NV);
+
+   if ( t->base.dirty_images[0] ) {
+      RADEON_FIREVERTICES( rmesa );
+      radeonSetTexImages( rmesa, tObj );
+      radeonUploadTexImages( rmesa, (radeonTexObjPtr) tObj->DriverData, 0 );
+      if ( !t->base.memBlock /* && !rmesa->prefer_agp_client_texturing  FIXME */ ) {
+        fprintf(stderr, "%s: upload failed\n", __FUNCTION__);
+        return GL_FALSE;
+      }
+   }
+
+   return GL_TRUE;
+}
+
+
+static GLboolean update_tex_common( GLcontext *ctx, int unit )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+   struct gl_texture_object *tObj = texUnit->_Current;
+   radeonTexObjPtr t = (radeonTexObjPtr) tObj->DriverData;
+   GLenum format;
+
+   /* Fallback if there's a texture border */
+   if ( tObj->Image[tObj->BaseLevel]->Border > 0 ) {
+      fprintf(stderr, "%s: border\n", __FUNCTION__);
+      return GL_FALSE;
+   }
+
+   /* Update state if this is a different texture object to last
+    * time.
+    */
+   if ( rmesa->state.texture.unit[unit].texobj != t ) {
+      if ( rmesa->state.texture.unit[unit].texobj != NULL ) {
+        /* The old texture is no longer bound to this texture unit.
+         * Mark it as such.
+         */
+
+        rmesa->state.texture.unit[unit].texobj->base.bound &= 
+            ~(1UL << unit);
+      }
+
+      rmesa->state.texture.unit[unit].texobj = t;
+      t->base.bound |= (1UL << unit);
+      t->dirty_state |= 1<<unit;
+      driUpdateTextureLRU( (driTextureObject *) t ); /* XXX: should be locked! */
+   }
+
+
+   /* Newly enabled?
+    */
+   if ( !(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (RADEON_TEX_0_ENABLE<<unit))) {
+      RADEON_STATECHANGE( rmesa, ctx );
+      rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= 
+         (RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE) << unit;
+
+      RADEON_STATECHANGE( rmesa, tcl );
+
+      if (unit == 0)
+         rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_ST0;
+      else 
+         rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_ST1;
+
+      rmesa->recheck_texgen[unit] = GL_TRUE;
+   }
+
+   if (t->dirty_state & (1<<unit)) {
+      import_tex_obj_state( rmesa, unit, t );
+   }
+
+   if (rmesa->recheck_texgen[unit]) {
+      GLboolean fallback = !radeon_validate_texgen( ctx, unit );
+      TCL_FALLBACK( ctx, (RADEON_TCL_FALLBACK_TEXGEN_0<<unit), fallback);
+      rmesa->recheck_texgen[unit] = 0;
+      rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
+   }
+
+   format = tObj->Image[tObj->BaseLevel]->Format;
+   if ( rmesa->state.texture.unit[unit].format != format ||
+       rmesa->state.texture.unit[unit].envMode != texUnit->EnvMode ) {
+      rmesa->state.texture.unit[unit].format = format;
+      rmesa->state.texture.unit[unit].envMode = texUnit->EnvMode;
+      if ( ! radeonUpdateTextureEnv( ctx, unit ) ) {
+        return GL_FALSE;
+      }
+   }
+
+   FALLBACK( rmesa, RADEON_FALLBACK_BORDER_MODE, t->border_fallback );
+   return !t->border_fallback;
+}
+
+
+
+static GLboolean radeonUpdateTextureUnit( GLcontext *ctx, int unit )
+{
+   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+
+   TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_TEXRECT_0 << unit, 0 );
+
+   if ( texUnit->_ReallyEnabled & (TEXTURE_RECT_BIT) ) {
+      TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_TEXRECT_0 << unit, 1 );
+
+      return (enable_tex_rect( ctx, unit ) &&
+             update_tex_common( ctx, unit ));
+   }
+   else if ( texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT) ) {
+      return (enable_tex_2d( ctx, unit ) &&
+             update_tex_common( ctx, unit ));
+   }
+   else if ( texUnit->_ReallyEnabled ) {
+      return GL_FALSE;
+   }
+   else {
+      disable_tex( ctx, unit );
+      return GL_TRUE;
+   }
+}
+
+void radeonUpdateTextureState( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLboolean ok;
+
+   ok = (radeonUpdateTextureUnit( ctx, 0 ) &&
+        radeonUpdateTextureUnit( ctx, 1 ));
+
+   FALLBACK( rmesa, RADEON_FALLBACK_TEXTURE, !ok );
+
+   if (rmesa->TclFallback)
+      radeonChooseVertexState( ctx );
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_vtxfmt.c b/src/mesa/drivers/dri/radeon/radeon_vtxfmt.c
new file mode 100644 (file)
index 0000000..b613e9e
--- /dev/null
@@ -0,0 +1,1089 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.c,v 1.5 2002/12/16 16:18:59 dawes Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ */
+#include "glheader.h"
+#include "imports.h"
+#include "api_noop.h"
+#include "api_arrayelt.h"
+#include "context.h"
+#include "mtypes.h"
+#include "enums.h"
+#include "glapi.h"
+#include "colormac.h"
+#include "light.h"
+#include "state.h"
+#include "vtxfmt.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_array_api.h"
+
+#include "radeon_context.h"
+#include "radeon_state.h"
+#include "radeon_ioctl.h"
+#include "radeon_tex.h"
+#include "radeon_tcl.h"
+#include "radeon_swtcl.h"
+#include "radeon_vtxfmt.h"
+
+static void radeonVtxfmtFlushVertices( GLcontext *, GLuint );
+
+static void count_func( const char *name,  struct dynfn *l )
+{
+   int i = 0;
+   struct dynfn *f;
+   foreach (f, l) i++;
+   if (i) fprintf(stderr, "%s: %d\n", name, i );
+}
+
+static void count_funcs( radeonContextPtr rmesa )
+{
+   count_func( "Vertex2f", &rmesa->vb.dfn_cache.Vertex2f );
+   count_func( "Vertex2fv", &rmesa->vb.dfn_cache.Vertex2fv );
+   count_func( "Vertex3f", &rmesa->vb.dfn_cache.Vertex3f );
+   count_func( "Vertex3fv", &rmesa->vb.dfn_cache.Vertex3fv );
+   count_func( "Color4ub", &rmesa->vb.dfn_cache.Color4ub );
+   count_func( "Color4ubv", &rmesa->vb.dfn_cache.Color4ubv );
+   count_func( "Color3ub", &rmesa->vb.dfn_cache.Color3ub );
+   count_func( "Color3ubv", &rmesa->vb.dfn_cache.Color3ubv );
+   count_func( "Color4f", &rmesa->vb.dfn_cache.Color4f );
+   count_func( "Color4fv", &rmesa->vb.dfn_cache.Color4fv );
+   count_func( "Color3f", &rmesa->vb.dfn_cache.Color3f );
+   count_func( "Color3fv", &rmesa->vb.dfn_cache.Color3fv );
+   count_func( "SecondaryColor3f", &rmesa->vb.dfn_cache.SecondaryColor3fEXT );
+   count_func( "SecondaryColor3fv", &rmesa->vb.dfn_cache.SecondaryColor3fvEXT );
+   count_func( "SecondaryColor3ub", &rmesa->vb.dfn_cache.SecondaryColor3ubEXT );
+   count_func( "SecondaryColor3ubv", &rmesa->vb.dfn_cache.SecondaryColor3ubvEXT );
+   count_func( "Normal3f", &rmesa->vb.dfn_cache.Normal3f );
+   count_func( "Normal3fv", &rmesa->vb.dfn_cache.Normal3fv );
+   count_func( "TexCoord2f", &rmesa->vb.dfn_cache.TexCoord2f );
+   count_func( "TexCoord2fv", &rmesa->vb.dfn_cache.TexCoord2fv );
+   count_func( "TexCoord1f", &rmesa->vb.dfn_cache.TexCoord1f );
+   count_func( "TexCoord1fv", &rmesa->vb.dfn_cache.TexCoord1fv );
+   count_func( "MultiTexCoord2fARB", &rmesa->vb.dfn_cache.MultiTexCoord2fARB );
+   count_func( "MultiTexCoord2fvARB", &rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
+   count_func( "MultiTexCoord1fARB", &rmesa->vb.dfn_cache.MultiTexCoord1fARB );
+   count_func( "MultiTexCoord1fvARB", &rmesa->vb.dfn_cache.MultiTexCoord1fvARB );
+}
+
+
+void radeon_copy_to_current( GLcontext *ctx ) 
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   assert(ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT);
+
+   if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_N0) {
+      ctx->Current.Attrib[VERT_ATTRIB_NORMAL][0] = rmesa->vb.normalptr[0];
+      ctx->Current.Attrib[VERT_ATTRIB_NORMAL][1] = rmesa->vb.normalptr[1];
+      ctx->Current.Attrib[VERT_ATTRIB_NORMAL][2] = rmesa->vb.normalptr[2];
+   }
+
+   if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_PKCOLOR) {
+      ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0] = UBYTE_TO_FLOAT( rmesa->vb.colorptr->red );
+      ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1] = UBYTE_TO_FLOAT( rmesa->vb.colorptr->green );
+      ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2] = UBYTE_TO_FLOAT( rmesa->vb.colorptr->blue );
+      ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] = UBYTE_TO_FLOAT( rmesa->vb.colorptr->alpha );
+   } 
+   
+   if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_FPCOLOR) {
+      ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0] = rmesa->vb.floatcolorptr[0];
+      ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1] = rmesa->vb.floatcolorptr[1];
+      ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2] = rmesa->vb.floatcolorptr[2];
+   }
+
+   if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_FPALPHA)
+      ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] = rmesa->vb.floatcolorptr[3];
+      
+   if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_PKSPEC) {
+      ctx->Current.Attrib[VERT_ATTRIB_COLOR1][0] = UBYTE_TO_FLOAT( rmesa->vb.specptr->red );
+      ctx->Current.Attrib[VERT_ATTRIB_COLOR1][1] = UBYTE_TO_FLOAT( rmesa->vb.specptr->green );
+      ctx->Current.Attrib[VERT_ATTRIB_COLOR1][2] = UBYTE_TO_FLOAT( rmesa->vb.specptr->blue );
+   } 
+
+   if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_ST0) {
+      ctx->Current.Attrib[VERT_ATTRIB_TEX0][0] = rmesa->vb.texcoordptr[0][0];
+      ctx->Current.Attrib[VERT_ATTRIB_TEX0][1] = rmesa->vb.texcoordptr[0][1];
+      ctx->Current.Attrib[VERT_ATTRIB_TEX0][2] = 0.0F;
+      ctx->Current.Attrib[VERT_ATTRIB_TEX0][3] = 1.0F;
+   }
+
+   if (rmesa->vb.vertex_format & RADEON_CP_VC_FRMT_ST1) {
+      ctx->Current.Attrib[VERT_ATTRIB_TEX1][0] = rmesa->vb.texcoordptr[1][0];
+      ctx->Current.Attrib[VERT_ATTRIB_TEX1][1] = rmesa->vb.texcoordptr[1][1];
+      ctx->Current.Attrib[VERT_ATTRIB_TEX1][2] = 0.0F;
+      ctx->Current.Attrib[VERT_ATTRIB_TEX1][3] = 1.0F;
+   }
+
+   ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
+}
+
+static GLboolean discreet_gl_prim[GL_POLYGON+1] = {
+   1,                          /* 0 points */
+   1,                          /* 1 lines */
+   0,                          /* 2 line_strip */
+   0,                          /* 3 line_loop */
+   1,                          /* 4 tris */
+   0,                          /* 5 tri_fan */
+   0,                          /* 6 tri_strip */
+   1,                          /* 7 quads */
+   0,                          /* 8 quadstrip */
+   0,                          /* 9 poly */
+};
+
+static void flush_prims( radeonContextPtr rmesa )
+{
+   int i,j;
+   struct radeon_dma_region tmp = rmesa->dma.current;
+   
+   tmp.buf->refcount++;
+   tmp.aos_size = rmesa->vb.vertex_size;
+   tmp.aos_stride = rmesa->vb.vertex_size;
+   tmp.aos_start = GET_START(&tmp);
+
+   rmesa->dma.current.ptr = rmesa->dma.current.start += 
+      (rmesa->vb.initial_counter - rmesa->vb.counter) * rmesa->vb.vertex_size * 4; 
+
+   rmesa->tcl.vertex_format = rmesa->vb.vertex_format;
+   rmesa->tcl.aos_components[0] = &tmp;
+   rmesa->tcl.nr_aos_components = 1;
+   rmesa->dma.flush = 0;
+
+   /* Optimize the primitive list:
+    */
+   if (rmesa->vb.nrprims > 1) {
+      for (j = 0, i = 1 ; i < rmesa->vb.nrprims; i++) {
+        int pj = rmesa->vb.primlist[j].prim & 0xf;
+        int pi = rmesa->vb.primlist[i].prim & 0xf;
+      
+        if (pj == pi && discreet_gl_prim[pj] &&
+            rmesa->vb.primlist[i].start == rmesa->vb.primlist[j].end) {
+           rmesa->vb.primlist[j].end = rmesa->vb.primlist[i].end;
+        }
+        else {
+           j++;
+           if (j != i) rmesa->vb.primlist[j] = rmesa->vb.primlist[i];
+        }
+      }
+      rmesa->vb.nrprims = j+1;
+   }
+
+   for (i = 0 ; i < rmesa->vb.nrprims; i++) {
+      if (RADEON_DEBUG & DEBUG_PRIMS)
+        fprintf(stderr, "vtxfmt prim %d: %s %d..%d\n", i,
+                _mesa_lookup_enum_by_nr( rmesa->vb.primlist[i].prim & 
+                                         PRIM_MODE_MASK ),
+                rmesa->vb.primlist[i].start,
+                rmesa->vb.primlist[i].end);
+
+      radeonEmitPrimitive( rmesa->glCtx,
+                          rmesa->vb.primlist[i].start,
+                          rmesa->vb.primlist[i].end,
+                          rmesa->vb.primlist[i].prim );
+   }
+
+   rmesa->vb.nrprims = 0;
+   radeonReleaseDmaRegion( rmesa, &tmp, __FUNCTION__ );
+}
+
+
+static void start_prim( radeonContextPtr rmesa, GLuint mode )
+{
+   if (RADEON_DEBUG & DEBUG_VFMT)
+      fprintf(stderr, "%s %d\n", __FUNCTION__, rmesa->vb.initial_counter - rmesa->vb.counter);
+
+   rmesa->vb.primlist[rmesa->vb.nrprims].start = rmesa->vb.initial_counter - rmesa->vb.counter;
+   rmesa->vb.primlist[rmesa->vb.nrprims].prim = mode;
+}
+
+static void note_last_prim( radeonContextPtr rmesa, GLuint flags )
+{
+   if (RADEON_DEBUG & DEBUG_VFMT)
+      fprintf(stderr, "%s %d\n", __FUNCTION__, rmesa->vb.initial_counter - rmesa->vb.counter);
+
+   if (rmesa->vb.prim[0] != GL_POLYGON+1) {
+      rmesa->vb.primlist[rmesa->vb.nrprims].prim |= flags;
+      rmesa->vb.primlist[rmesa->vb.nrprims].end = rmesa->vb.initial_counter - rmesa->vb.counter;
+
+      if (++(rmesa->vb.nrprims) == RADEON_MAX_PRIMS)
+        flush_prims( rmesa );
+   }
+}
+
+
+static void copy_vertex( radeonContextPtr rmesa, GLuint n, GLfloat *dst )
+{
+   GLuint i;
+   GLfloat *src = (GLfloat *)(rmesa->dma.current.address + 
+                             rmesa->dma.current.ptr + 
+                             (rmesa->vb.primlist[rmesa->vb.nrprims].start + n) * 
+                             rmesa->vb.vertex_size * 4);
+
+   if (RADEON_DEBUG & DEBUG_VFMT) 
+      fprintf(stderr, "copy_vertex %d\n", rmesa->vb.primlist[rmesa->vb.nrprims].start + n);
+
+   for (i = 0 ; i < rmesa->vb.vertex_size; i++) {
+      dst[i] = src[i];
+   }
+}
+
+/* NOTE: This actually reads the copied vertices back from uncached
+ * memory.  Could also use the counter/notify mechanism to populate
+ * tmp on the fly as vertices are generated.  
+ */
+static GLuint copy_dma_verts( radeonContextPtr rmesa, GLfloat (*tmp)[15] )
+{
+   GLuint ovf, i;
+   GLuint nr = (rmesa->vb.initial_counter - rmesa->vb.counter) - rmesa->vb.primlist[rmesa->vb.nrprims].start;
+
+   if (RADEON_DEBUG & DEBUG_VFMT)
+      fprintf(stderr, "%s %d verts\n", __FUNCTION__, nr);
+
+   switch( rmesa->vb.prim[0] )
+   {
+   case GL_POINTS:
+      return 0;
+   case GL_LINES:
+      ovf = nr&1;
+      for (i = 0 ; i < ovf ; i++)
+        copy_vertex( rmesa, nr-ovf+i, tmp[i] );
+      return i;
+   case GL_TRIANGLES:
+      ovf = nr%3;
+      for (i = 0 ; i < ovf ; i++)
+        copy_vertex( rmesa, nr-ovf+i, tmp[i] );
+      return i;
+   case GL_QUADS:
+      ovf = nr&3;
+      for (i = 0 ; i < ovf ; i++)
+        copy_vertex( rmesa, nr-ovf+i, tmp[i] );
+      return i;
+   case GL_LINE_STRIP:
+      if (nr == 0) 
+        return 0;
+      copy_vertex( rmesa, nr-1, tmp[0] );
+      return 1;
+   case GL_LINE_LOOP:
+   case GL_TRIANGLE_FAN:
+   case GL_POLYGON:
+      if (nr == 0) 
+        return 0;
+      else if (nr == 1) {
+        copy_vertex( rmesa, 0, tmp[0] );
+        return 1;
+      } else {
+        copy_vertex( rmesa, 0, tmp[0] );
+        copy_vertex( rmesa, nr-1, tmp[1] );
+        return 2;
+      }
+   case GL_TRIANGLE_STRIP:
+      ovf = MIN2(nr, 2);
+      for (i = 0 ; i < ovf ; i++)
+        copy_vertex( rmesa, nr-ovf+i, tmp[i] );
+      return i;
+   case GL_QUAD_STRIP:
+      switch (nr) {
+      case 0: ovf = 0; break;
+      case 1: ovf = 1; break;
+      default: ovf = 2 + (nr&1); break;
+      }
+      for (i = 0 ; i < ovf ; i++)
+        copy_vertex( rmesa, nr-ovf+i, tmp[i] );
+      return i;
+   default:
+      assert(0);
+      return 0;
+   }
+}
+
+static void VFMT_FALLBACK_OUTSIDE_BEGIN_END( const char *caller )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   if (RADEON_DEBUG & (DEBUG_VFMT|DEBUG_FALLBACKS))
+      fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
+
+   if (ctx->Driver.NeedFlush) 
+      radeonVtxfmtFlushVertices( ctx, ctx->Driver.NeedFlush );
+
+   if (ctx->NewState)
+      _mesa_update_state( ctx ); /* clear state so fell_back sticks */
+
+   _tnl_wakeup_exec( ctx );
+   ctx->Driver.FlushVertices = radeonFlushVertices;
+
+   assert( rmesa->dma.flush == 0 );
+   rmesa->vb.fell_back = GL_TRUE;
+   rmesa->vb.installed = GL_FALSE;
+}
+
+
+static void VFMT_FALLBACK( const char *caller )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat tmp[3][15];
+   GLuint i, prim;
+   GLuint ind = rmesa->vb.vertex_format;
+   GLuint nrverts;
+   GLfloat alpha = 1.0;
+
+   if (RADEON_DEBUG & (DEBUG_FALLBACKS|DEBUG_VFMT))
+      fprintf(stderr, "%s from %s\n", __FUNCTION__, caller);
+
+   if (rmesa->vb.prim[0] == GL_POLYGON+1) {
+      VFMT_FALLBACK_OUTSIDE_BEGIN_END( __FUNCTION__ );
+      return;
+   }
+
+   /* Copy vertices out of dma:
+    */
+   nrverts = copy_dma_verts( rmesa, tmp );
+
+   /* Finish the prim at this point:
+    */
+   note_last_prim( rmesa, 0 );
+   flush_prims( rmesa );
+
+   /* Update ctx->Driver.CurrentExecPrimitive and swap in swtnl. 
+    */
+   prim = rmesa->vb.prim[0];
+   ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
+   _tnl_wakeup_exec( ctx );
+   ctx->Driver.FlushVertices = radeonFlushVertices;
+
+   assert(rmesa->dma.flush == 0);
+   rmesa->vb.fell_back = GL_TRUE;
+   rmesa->vb.installed = GL_FALSE;
+   glBegin( prim );
+   
+   if (rmesa->vb.installed_color_3f_sz == 4)
+      alpha = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3];
+
+   /* Replay saved vertices
+    */
+   for (i = 0 ; i < nrverts; i++) {
+      GLuint offset = 3;
+      if (ind & RADEON_CP_VC_FRMT_N0) {
+        glNormal3fv( &tmp[i][offset] ); 
+        offset += 3;
+      }
+
+      if (ind & RADEON_CP_VC_FRMT_PKCOLOR) {
+        radeon_color_t *col = (radeon_color_t *)&tmp[i][offset];
+        glColor4ub( col->red, col->green, col->blue, col->alpha );
+        offset++;
+      }
+      else if (ind & RADEON_CP_VC_FRMT_FPALPHA) {
+        glColor4fv( &tmp[i][offset] ); 
+        offset+=4;
+      } 
+      else if (ind & RADEON_CP_VC_FRMT_FPCOLOR) {
+        glColor3fv( &tmp[i][offset] ); 
+        offset+=3;
+      }
+
+      if (ind & RADEON_CP_VC_FRMT_PKSPEC) {
+        radeon_color_t *spec = (radeon_color_t *)&tmp[i][offset];
+        _glapi_Dispatch->SecondaryColor3ubEXT( spec->red, spec->green, spec->blue );
+        offset++;
+      }
+
+      if (ind & RADEON_CP_VC_FRMT_ST0) {
+        glTexCoord2fv( &tmp[i][offset] ); 
+        offset += 2;
+      }
+
+      if (ind & RADEON_CP_VC_FRMT_ST1) {
+        glMultiTexCoord2fvARB( GL_TEXTURE1_ARB, &tmp[i][offset] );
+        offset += 2;
+      }
+      glVertex3fv( &tmp[i][0] );
+   }
+
+   /* Replay current vertex
+    */
+   if (ind & RADEON_CP_VC_FRMT_N0) 
+      glNormal3fv( rmesa->vb.normalptr );
+
+   if (ind & RADEON_CP_VC_FRMT_PKCOLOR)
+      glColor4ub( rmesa->vb.colorptr->red, rmesa->vb.colorptr->green, rmesa->vb.colorptr->blue, rmesa->vb.colorptr->alpha );
+   else if (ind & RADEON_CP_VC_FRMT_FPALPHA)
+      glColor4fv( rmesa->vb.floatcolorptr );
+   else if (ind & RADEON_CP_VC_FRMT_FPCOLOR) {
+      if (rmesa->vb.installed_color_3f_sz == 4 && alpha != 1.0)
+        glColor4f( rmesa->vb.floatcolorptr[0],
+                   rmesa->vb.floatcolorptr[1],
+                   rmesa->vb.floatcolorptr[2],
+                   alpha );
+      else
+        glColor3fv( rmesa->vb.floatcolorptr );
+   }
+
+   if (ind & RADEON_CP_VC_FRMT_PKSPEC) 
+      _glapi_Dispatch->SecondaryColor3ubEXT( rmesa->vb.specptr->red, rmesa->vb.specptr->green, rmesa->vb.specptr->blue ); 
+
+   if (ind & RADEON_CP_VC_FRMT_ST0) 
+      glTexCoord2fv( rmesa->vb.texcoordptr[0] );
+
+   if (ind & RADEON_CP_VC_FRMT_ST1) 
+      glMultiTexCoord2fvARB( GL_TEXTURE1_ARB, rmesa->vb.texcoordptr[1] );
+}
+
+
+
+static void wrap_buffer( void )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat tmp[3][15];
+   GLuint i, nrverts;
+
+   if (RADEON_DEBUG & (DEBUG_VFMT|DEBUG_PRIMS))
+      fprintf(stderr, "%s %d\n", __FUNCTION__, rmesa->vb.initial_counter - rmesa->vb.counter);
+
+   /* Don't deal with parity.
+    */
+   if ((((rmesa->vb.initial_counter - rmesa->vb.counter) -  
+        rmesa->vb.primlist[rmesa->vb.nrprims].start) & 1)) {
+      rmesa->vb.counter++;
+      rmesa->vb.initial_counter++;
+      return;
+   }
+
+   /* Copy vertices out of dma:
+    */
+   if (rmesa->vb.prim[0] == GL_POLYGON+1) 
+      nrverts = 0;
+   else {
+      nrverts = copy_dma_verts( rmesa, tmp );
+
+      if (RADEON_DEBUG & DEBUG_VFMT)
+        fprintf(stderr, "%d vertices to copy\n", nrverts);
+   
+      /* Finish the prim at this point:
+       */
+      note_last_prim( rmesa, 0 );
+   }
+
+   /* Fire any buffered primitives
+    */
+   flush_prims( rmesa );
+
+   /* Get new buffer
+    */
+   radeonRefillCurrentDmaRegion( rmesa );
+
+   /* Reset counter, dmaptr
+    */
+   rmesa->vb.dmaptr = (int *)(rmesa->dma.current.ptr + rmesa->dma.current.address);
+   rmesa->vb.counter = (rmesa->dma.current.end - rmesa->dma.current.ptr) / 
+      (rmesa->vb.vertex_size * 4);
+   rmesa->vb.counter--;
+   rmesa->vb.initial_counter = rmesa->vb.counter;
+   rmesa->vb.notify = wrap_buffer;
+
+   rmesa->dma.flush = flush_prims;
+
+   /* Restart wrapped primitive:
+    */
+   if (rmesa->vb.prim[0] != GL_POLYGON+1)
+      start_prim( rmesa, rmesa->vb.prim[0] );
+
+   /* Reemit saved vertices
+    */
+   for (i = 0 ; i < nrverts; i++) {
+      if (RADEON_DEBUG & DEBUG_VERTS) {
+        int j;
+        fprintf(stderr, "re-emit vertex %d to %p\n", i, rmesa->vb.dmaptr);
+        if (RADEON_DEBUG & DEBUG_VERBOSE)
+           for (j = 0 ; j < rmesa->vb.vertex_size; j++) 
+              fprintf(stderr, "\t%08x/%f\n", *(int*)&tmp[i][j], tmp[i][j]);
+      }
+
+      memcpy( rmesa->vb.dmaptr, tmp[i], rmesa->vb.vertex_size * 4 );
+      rmesa->vb.dmaptr += rmesa->vb.vertex_size;
+      rmesa->vb.counter--;
+   }
+}
+
+
+
+static GLboolean check_vtx_fmt( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLuint ind = RADEON_CP_VC_FRMT_Z;
+
+   if (rmesa->TclFallback || rmesa->vb.fell_back || ctx->CompileFlag)
+      return GL_FALSE;
+
+   if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) 
+      ctx->Driver.FlushVertices( ctx, FLUSH_UPDATE_CURRENT );
+   
+   /* Make all this event-driven:
+    */
+   if (ctx->Light.Enabled) {
+      ind |= RADEON_CP_VC_FRMT_N0;
+
+      /* TODO: make this data driven: If we receive only ubytes, send
+       * color as ubytes.  Also check if converting (with free
+       * checking for overflow) is cheaper than sending floats
+       * directly.
+       */
+      if (ctx->Light.ColorMaterialEnabled) {
+        ind |= (RADEON_CP_VC_FRMT_FPCOLOR |
+                RADEON_CP_VC_FRMT_FPALPHA);
+      }
+      else
+        ind |= RADEON_CP_VC_FRMT_PKCOLOR; /* for alpha? */
+   }
+   else {
+      /* TODO: make this data driven?
+       */
+      ind |= RADEON_CP_VC_FRMT_PKCOLOR;
+        
+      if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
+        ind |= RADEON_CP_VC_FRMT_PKSPEC;
+      }
+   }
+
+   if (ctx->Texture.Unit[0]._ReallyEnabled) {
+      if (ctx->Texture.Unit[0].TexGenEnabled) {
+        if (rmesa->TexGenNeedNormals[0]) {
+           ind |= RADEON_CP_VC_FRMT_N0;
+        }
+      } else {
+        if (ctx->Current.Attrib[VERT_ATTRIB_TEX0][2] != 0.0F ||
+            ctx->Current.Attrib[VERT_ATTRIB_TEX0][3] != 1.0) {
+           if (RADEON_DEBUG & (DEBUG_VFMT|DEBUG_FALLBACKS))
+              fprintf(stderr, "%s: rq0\n", __FUNCTION__);
+           return GL_FALSE;
+        }
+        ind |= RADEON_CP_VC_FRMT_ST0;
+      }
+   }
+
+   if (ctx->Texture.Unit[1]._ReallyEnabled) {
+      if (ctx->Texture.Unit[1].TexGenEnabled) {
+        if (rmesa->TexGenNeedNormals[1]) {
+           ind |= RADEON_CP_VC_FRMT_N0;
+        }
+      } else {
+        if (ctx->Current.Attrib[VERT_ATTRIB_TEX1][2] != 0.0F ||
+            ctx->Current.Attrib[VERT_ATTRIB_TEX1][3] != 1.0) {
+           if (RADEON_DEBUG & (DEBUG_VFMT|DEBUG_FALLBACKS))
+              fprintf(stderr, "%s: rq1\n", __FUNCTION__);
+           return GL_FALSE;
+        }
+        ind |= RADEON_CP_VC_FRMT_ST1;
+      }
+   }
+
+   if (RADEON_DEBUG & (DEBUG_VFMT|DEBUG_STATE))
+      fprintf(stderr, "%s: format: 0x%x\n", __FUNCTION__, ind );
+
+   RADEON_NEWPRIM(rmesa);
+   rmesa->vb.vertex_format = ind;
+   rmesa->vb.vertex_size = 3;
+   rmesa->vb.prim = &ctx->Driver.CurrentExecPrimitive;
+
+   rmesa->vb.normalptr = ctx->Current.Attrib[VERT_ATTRIB_NORMAL];
+   rmesa->vb.colorptr = NULL;
+   rmesa->vb.floatcolorptr = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
+   rmesa->vb.specptr = NULL;
+   rmesa->vb.floatspecptr = ctx->Current.Attrib[VERT_ATTRIB_COLOR1];
+   rmesa->vb.texcoordptr[0] = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
+   rmesa->vb.texcoordptr[1] = ctx->Current.Attrib[VERT_ATTRIB_TEX1];
+
+   /* Run through and initialize the vertex components in the order
+    * the hardware understands:
+    */
+   if (ind & RADEON_CP_VC_FRMT_N0) {
+      rmesa->vb.normalptr = &rmesa->vb.vertex[rmesa->vb.vertex_size].f;
+      rmesa->vb.vertex_size += 3;
+      rmesa->vb.normalptr[0] = ctx->Current.Attrib[VERT_ATTRIB_NORMAL][0];
+      rmesa->vb.normalptr[1] = ctx->Current.Attrib[VERT_ATTRIB_NORMAL][1];
+      rmesa->vb.normalptr[2] = ctx->Current.Attrib[VERT_ATTRIB_NORMAL][2];
+   }
+
+   if (ind & RADEON_CP_VC_FRMT_PKCOLOR) {
+      rmesa->vb.colorptr = &rmesa->vb.vertex[rmesa->vb.vertex_size].color;
+      rmesa->vb.vertex_size += 1;
+      UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.colorptr->red,   ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0] );
+      UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.colorptr->green, ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1] );
+      UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.colorptr->blue,  ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2] );
+      UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.colorptr->alpha, ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] );
+   }
+
+   if (ind & RADEON_CP_VC_FRMT_FPCOLOR) {
+      assert(!(ind & RADEON_CP_VC_FRMT_PKCOLOR));
+      rmesa->vb.floatcolorptr = &rmesa->vb.vertex[rmesa->vb.vertex_size].f;
+      rmesa->vb.vertex_size += 3;
+      rmesa->vb.floatcolorptr[0] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][0];
+      rmesa->vb.floatcolorptr[1] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][1];
+      rmesa->vb.floatcolorptr[2] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][2];
+
+      if (ind & RADEON_CP_VC_FRMT_FPALPHA) {
+        rmesa->vb.vertex_size += 1;
+        rmesa->vb.floatcolorptr[3] = ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3];
+      }
+   }
+   
+   if (ind & RADEON_CP_VC_FRMT_PKSPEC) {
+      rmesa->vb.specptr = &rmesa->vb.vertex[rmesa->vb.vertex_size].color;
+      rmesa->vb.vertex_size += 1;
+      UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.specptr->red,   ctx->Current.Attrib[VERT_ATTRIB_COLOR1][0] );
+      UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.specptr->green, ctx->Current.Attrib[VERT_ATTRIB_COLOR1][1] );
+      UNCLAMPED_FLOAT_TO_CHAN( rmesa->vb.specptr->blue,  ctx->Current.Attrib[VERT_ATTRIB_COLOR1][2] );
+   }
+
+   if (ind & RADEON_CP_VC_FRMT_ST0) {
+      rmesa->vb.texcoordptr[0] = &rmesa->vb.vertex[rmesa->vb.vertex_size].f;
+      rmesa->vb.vertex_size += 2;
+      rmesa->vb.texcoordptr[0][0] = ctx->Current.Attrib[VERT_ATTRIB_TEX0][0];
+      rmesa->vb.texcoordptr[0][1] = ctx->Current.Attrib[VERT_ATTRIB_TEX0][1];   
+   } 
+
+   if (ind & RADEON_CP_VC_FRMT_ST1) {
+      rmesa->vb.texcoordptr[1] = &rmesa->vb.vertex[rmesa->vb.vertex_size].f;
+      rmesa->vb.vertex_size += 2;
+      rmesa->vb.texcoordptr[1][0] = ctx->Current.Attrib[VERT_ATTRIB_TEX1][0];
+      rmesa->vb.texcoordptr[1][1] = ctx->Current.Attrib[VERT_ATTRIB_TEX1][1];
+   } 
+
+   if (rmesa->vb.installed_vertex_format != rmesa->vb.vertex_format) {
+      if (RADEON_DEBUG & DEBUG_VFMT)
+        fprintf(stderr, "reinstall on vertex_format change\n");
+      _mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt );
+      rmesa->vb.installed_vertex_format = rmesa->vb.vertex_format;
+   }
+
+   if (RADEON_DEBUG & DEBUG_VFMT)
+      fprintf(stderr, "%s -- success\n", __FUNCTION__);
+   
+   return GL_TRUE;
+}
+
+void radeonVtxfmtInvalidate( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+
+   rmesa->vb.recheck = GL_TRUE;
+   rmesa->vb.fell_back = GL_FALSE;
+}
+
+
+static void radeonNewList( GLcontext *ctx, GLuint list, GLenum mode )
+{
+   VFMT_FALLBACK_OUTSIDE_BEGIN_END( __FUNCTION__ );
+}
+
+
+static void radeonVtxfmtValidate( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+
+   if (RADEON_DEBUG & DEBUG_VFMT)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   if (ctx->Driver.NeedFlush)
+      ctx->Driver.FlushVertices( ctx, ctx->Driver.NeedFlush );
+
+   rmesa->vb.recheck = GL_FALSE;
+
+   if (check_vtx_fmt( ctx )) {
+      if (!rmesa->vb.installed) {
+        if (RADEON_DEBUG & DEBUG_VFMT)
+           fprintf(stderr, "reinstall (new install)\n");
+
+        _mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt );
+        ctx->Driver.FlushVertices = radeonVtxfmtFlushVertices;
+        ctx->Driver.NewList = radeonNewList;
+        rmesa->vb.installed = GL_TRUE;
+      }
+      else if (RADEON_DEBUG & DEBUG_VFMT)
+        fprintf(stderr, "%s: already installed", __FUNCTION__);
+   } 
+   else {
+      if (RADEON_DEBUG & DEBUG_VFMT)
+        fprintf(stderr, "%s: failed\n", __FUNCTION__);
+
+      if (rmesa->vb.installed) {
+        if (rmesa->dma.flush)
+           rmesa->dma.flush( rmesa );
+        _tnl_wakeup_exec( ctx );
+        ctx->Driver.FlushVertices = radeonFlushVertices;
+        rmesa->vb.installed = GL_FALSE;
+      }
+   }      
+}
+
+
+
+/* Materials:
+ */
+static void radeon_Materialfv( GLenum face, GLenum pname, 
+                              const GLfloat *params )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+
+   if (RADEON_DEBUG & DEBUG_VFMT)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   if (rmesa->vb.prim[0] != GL_POLYGON+1) {
+      VFMT_FALLBACK( __FUNCTION__ );
+      glMaterialfv( face, pname, params );
+      return;
+   }
+   _mesa_noop_Materialfv( face, pname, params );
+   radeonUpdateMaterial( ctx );
+}
+
+
+/* Begin/End
+ */
+static void radeon_Begin( GLenum mode )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   if (RADEON_DEBUG & DEBUG_VFMT)
+      fprintf(stderr, "%s( %s )\n", __FUNCTION__,
+             _mesa_lookup_enum_by_nr( mode ));
+
+   if (mode > GL_POLYGON) {
+      _mesa_error( ctx, GL_INVALID_ENUM, "glBegin" );
+      return;
+   }
+
+   if (rmesa->vb.prim[0] != GL_POLYGON+1) {
+      _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
+      return;
+   }
+   
+   if (ctx->NewState) 
+      _mesa_update_state( ctx );
+
+   if (rmesa->NewGLState)
+      radeonValidateState( ctx );
+
+   if (rmesa->vb.recheck) 
+      radeonVtxfmtValidate( ctx );
+
+   if (!rmesa->vb.installed) {
+      glBegin( mode );
+      return;
+   }
+
+
+   if (rmesa->dma.flush && rmesa->vb.counter < 12) {
+      if (RADEON_DEBUG & DEBUG_VFMT)
+        fprintf(stderr, "%s: flush almost-empty buffers\n", __FUNCTION__);
+      flush_prims( rmesa );
+   }
+
+   /* Need to arrange to save vertices here?  Or always copy from dma (yuk)?
+    */
+   if (!rmesa->dma.flush) {
+      if (rmesa->dma.current.ptr + 12*rmesa->vb.vertex_size*4 > 
+         rmesa->dma.current.end) {
+        RADEON_NEWPRIM( rmesa );
+        radeonRefillCurrentDmaRegion( rmesa );
+      }
+
+      rmesa->vb.dmaptr = (int *)(rmesa->dma.current.address + rmesa->dma.current.ptr);
+      rmesa->vb.counter = (rmesa->dma.current.end - rmesa->dma.current.ptr) / 
+        (rmesa->vb.vertex_size * 4);
+      rmesa->vb.counter--;
+      rmesa->vb.initial_counter = rmesa->vb.counter;
+      rmesa->vb.notify = wrap_buffer;
+      rmesa->dma.flush = flush_prims;
+      ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
+   }
+   
+   
+   rmesa->vb.prim[0] = mode;
+   start_prim( rmesa, mode | PRIM_BEGIN );
+}
+
+
+
+static void radeon_End( void )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   if (RADEON_DEBUG & DEBUG_VFMT)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   if (rmesa->vb.prim[0] == GL_POLYGON+1) {
+      _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
+      return;
+   }
+         
+   note_last_prim( rmesa, PRIM_END );
+   rmesa->vb.prim[0] = GL_POLYGON+1;
+}
+
+
+/* Fallback on difficult entrypoints:
+ */
+#define PRE_LOOPBACK( FUNC )                   \
+do {                                           \
+   if (RADEON_DEBUG & DEBUG_VFMT)              \
+      fprintf(stderr, "%s\n", __FUNCTION__);   \
+   VFMT_FALLBACK( __FUNCTION__ );              \
+} while (0)
+#define TAG(x) radeon_fallback_##x
+#include "vtxfmt_tmp.h"
+
+
+
+static GLboolean radeonNotifyBegin( GLcontext *ctx, GLenum p )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+   
+   if (RADEON_DEBUG & DEBUG_VFMT)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   assert(!rmesa->vb.installed);
+
+   if (ctx->NewState) 
+      _mesa_update_state( ctx );
+
+   if (rmesa->NewGLState)
+      radeonValidateState( ctx );
+
+   if (ctx->Driver.NeedFlush)
+      ctx->Driver.FlushVertices( ctx, ctx->Driver.NeedFlush );
+
+   if (rmesa->vb.recheck) 
+      radeonVtxfmtValidate( ctx );
+
+   if (!rmesa->vb.installed) {
+      if (RADEON_DEBUG & DEBUG_VFMT)
+        fprintf(stderr, "%s -- failed\n", __FUNCTION__);
+      return GL_FALSE;
+   }
+
+   radeon_Begin( p );
+   return GL_TRUE;
+}
+
+static void radeonVtxfmtFlushVertices( GLcontext *ctx, GLuint flags )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+
+   if (RADEON_DEBUG & DEBUG_VFMT)
+      fprintf(stderr, "%s\n", __FUNCTION__);
+
+   assert(rmesa->vb.installed);
+
+   if (flags & FLUSH_UPDATE_CURRENT) {
+      radeon_copy_to_current( ctx );
+      if (RADEON_DEBUG & DEBUG_VFMT)
+        fprintf(stderr, "reinstall on update_current\n");
+      _mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt );
+      ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
+   }
+
+   if (flags & FLUSH_STORED_VERTICES) {
+      radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+      assert (rmesa->dma.flush == 0 ||
+             rmesa->dma.flush == flush_prims);
+      if (rmesa->dma.flush == flush_prims)
+        flush_prims( RADEON_CONTEXT( ctx ) );
+      ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES;
+   }
+}
+
+
+
+/* At this point, don't expect very many versions of each function to
+ * be generated, so not concerned about freeing them?
+ */
+
+
+void radeonVtxfmtInit( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+   GLvertexformat *vfmt = &(rmesa->vb.vtxfmt);
+
+   MEMSET( vfmt, 0, sizeof(GLvertexformat) );
+
+   /* Hook in chooser functions for codegen, etc:
+    */
+   radeonVtxfmtInitChoosers( vfmt );
+
+   /* Handled fully in supported states, but no codegen:
+    */
+   vfmt->Materialfv = radeon_Materialfv;
+   vfmt->ArrayElement = _ae_loopback_array_elt;                /* generic helper */
+   vfmt->Rectf = _mesa_noop_Rectf;                     /* generic helper */
+   vfmt->Begin = radeon_Begin;
+   vfmt->End = radeon_End;
+
+   /* Fallback for performance reasons:  (Fix with cva/elt path here and
+    * dmatmp2.h style primitive-merging)
+    *
+    * These should call NotifyBegin(), as should _tnl_EvalMesh, to allow
+    * a driver-hook.
+    */
+   vfmt->DrawArrays = radeon_fallback_DrawArrays;
+   vfmt->DrawElements = radeon_fallback_DrawElements;
+   vfmt->DrawRangeElements = radeon_fallback_DrawRangeElements; 
+
+
+   /* Not active in supported states; just keep ctx->Current uptodate:
+    */
+   vfmt->FogCoordfvEXT = _mesa_noop_FogCoordfvEXT;
+   vfmt->FogCoordfEXT = _mesa_noop_FogCoordfEXT;
+   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:
+    */
+   vfmt->CallList = radeon_fallback_CallList;
+   vfmt->EvalCoord1f = radeon_fallback_EvalCoord1f;
+   vfmt->EvalCoord1fv = radeon_fallback_EvalCoord1fv;
+   vfmt->EvalCoord2f = radeon_fallback_EvalCoord2f;
+   vfmt->EvalCoord2fv = radeon_fallback_EvalCoord2fv;
+   vfmt->EvalMesh1 = radeon_fallback_EvalMesh1;
+   vfmt->EvalMesh2 = radeon_fallback_EvalMesh2;
+   vfmt->EvalPoint1 = radeon_fallback_EvalPoint1;
+   vfmt->EvalPoint2 = radeon_fallback_EvalPoint2;
+   vfmt->TexCoord3f = radeon_fallback_TexCoord3f;
+   vfmt->TexCoord3fv = radeon_fallback_TexCoord3fv;
+   vfmt->TexCoord4f = radeon_fallback_TexCoord4f;
+   vfmt->TexCoord4fv = radeon_fallback_TexCoord4fv;
+   vfmt->MultiTexCoord3fARB = radeon_fallback_MultiTexCoord3fARB;
+   vfmt->MultiTexCoord3fvARB = radeon_fallback_MultiTexCoord3fvARB;
+   vfmt->MultiTexCoord4fARB = radeon_fallback_MultiTexCoord4fARB;
+   vfmt->MultiTexCoord4fvARB = radeon_fallback_MultiTexCoord4fvARB;
+   vfmt->Vertex4f = radeon_fallback_Vertex4f;
+   vfmt->Vertex4fv = radeon_fallback_Vertex4fv;
+
+   (void)radeon_fallback_vtxfmt;
+
+   TNL_CONTEXT(ctx)->Driver.NotifyBegin = radeonNotifyBegin;
+
+   rmesa->vb.enabled = 1;
+   rmesa->vb.prim = &ctx->Driver.CurrentExecPrimitive;
+   rmesa->vb.primflags = 0;
+
+   make_empty_list( &rmesa->vb.dfn_cache.Vertex2f );
+   make_empty_list( &rmesa->vb.dfn_cache.Vertex2fv );
+   make_empty_list( &rmesa->vb.dfn_cache.Vertex3f );
+   make_empty_list( &rmesa->vb.dfn_cache.Vertex3fv );
+   make_empty_list( &rmesa->vb.dfn_cache.Color4ub );
+   make_empty_list( &rmesa->vb.dfn_cache.Color4ubv );
+   make_empty_list( &rmesa->vb.dfn_cache.Color3ub );
+   make_empty_list( &rmesa->vb.dfn_cache.Color3ubv );
+   make_empty_list( &rmesa->vb.dfn_cache.Color4f );
+   make_empty_list( &rmesa->vb.dfn_cache.Color4fv );
+   make_empty_list( &rmesa->vb.dfn_cache.Color3f );
+   make_empty_list( &rmesa->vb.dfn_cache.Color3fv );
+   make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3fEXT );
+   make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3fvEXT );
+   make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3ubEXT );
+   make_empty_list( &rmesa->vb.dfn_cache.SecondaryColor3ubvEXT );
+   make_empty_list( &rmesa->vb.dfn_cache.Normal3f );
+   make_empty_list( &rmesa->vb.dfn_cache.Normal3fv );
+   make_empty_list( &rmesa->vb.dfn_cache.TexCoord2f );
+   make_empty_list( &rmesa->vb.dfn_cache.TexCoord2fv );
+   make_empty_list( &rmesa->vb.dfn_cache.TexCoord1f );
+   make_empty_list( &rmesa->vb.dfn_cache.TexCoord1fv );
+   make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord2fARB );
+   make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
+   make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord1fARB );
+   make_empty_list( &rmesa->vb.dfn_cache.MultiTexCoord1fvARB );
+
+   radeonInitCodegen( &rmesa->vb.codegen );
+}
+
+static void free_funcs( struct dynfn *l )
+{
+   struct dynfn *f, *tmp;
+   foreach_s (f, tmp, l) {
+      remove_from_list( f );
+      ALIGN_FREE( f->code );
+      FREE( f );
+   }
+}
+
+
+
+void radeonVtxfmtMakeCurrent( GLcontext *ctx )
+{
+}
+
+
+void radeonVtxfmtDestroy( GLcontext *ctx )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
+
+   count_funcs( rmesa );
+   free_funcs( &rmesa->vb.dfn_cache.Vertex2f );
+   free_funcs( &rmesa->vb.dfn_cache.Vertex2fv );
+   free_funcs( &rmesa->vb.dfn_cache.Vertex3f );
+   free_funcs( &rmesa->vb.dfn_cache.Vertex3fv );
+   free_funcs( &rmesa->vb.dfn_cache.Color4ub );
+   free_funcs( &rmesa->vb.dfn_cache.Color4ubv );
+   free_funcs( &rmesa->vb.dfn_cache.Color3ub );
+   free_funcs( &rmesa->vb.dfn_cache.Color3ubv );
+   free_funcs( &rmesa->vb.dfn_cache.Color4f );
+   free_funcs( &rmesa->vb.dfn_cache.Color4fv );
+   free_funcs( &rmesa->vb.dfn_cache.Color3f );
+   free_funcs( &rmesa->vb.dfn_cache.Color3fv );
+   free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3ubEXT );
+   free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3ubvEXT );
+   free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3fEXT );
+   free_funcs( &rmesa->vb.dfn_cache.SecondaryColor3fvEXT );
+   free_funcs( &rmesa->vb.dfn_cache.Normal3f );
+   free_funcs( &rmesa->vb.dfn_cache.Normal3fv );
+   free_funcs( &rmesa->vb.dfn_cache.TexCoord2f );
+   free_funcs( &rmesa->vb.dfn_cache.TexCoord2fv );
+   free_funcs( &rmesa->vb.dfn_cache.TexCoord1f );
+   free_funcs( &rmesa->vb.dfn_cache.TexCoord1fv );
+   free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord2fARB );
+   free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
+   free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord1fARB );
+   free_funcs( &rmesa->vb.dfn_cache.MultiTexCoord1fvARB );
+}
+
diff --git a/src/mesa/drivers/dri/radeon/radeon_vtxfmt.h b/src/mesa/drivers/dri/radeon/radeon_vtxfmt.h
new file mode 100644 (file)
index 0000000..9792fcb
--- /dev/null
@@ -0,0 +1,124 @@
+/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_vtxfmt.h,v 1.3 2002/12/21 17:02:16 dawes Exp $ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef __RADEON_VTXFMT_H__
+#define __RADEON_VTXFMT_H__
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include "radeon_context.h"
+
+
+extern void radeonVtxfmtUpdate( GLcontext *ctx );
+extern void radeonVtxfmtInit( GLcontext *ctx );
+extern void radeonVtxfmtInvalidate( GLcontext *ctx );
+extern void radeonVtxfmtDestroy( GLcontext *ctx );
+extern void radeonVtxfmtInitChoosers( GLvertexformat *vfmt );
+
+extern void radeonVtxfmtMakeCurrent( GLcontext *ctx );
+extern void radeonVtxfmtUnbindContext( GLcontext *ctx );
+
+extern void radeon_copy_to_current( GLcontext *ctx );
+
+#define DFN( FUNC, CACHE)                              \
+do {                                                   \
+   char *start = (char *)&FUNC;                                \
+   char *end = (char *)&FUNC##_end;                    \
+   insert_at_head( &CACHE, dfn );                      \
+   dfn->key = key;                                     \
+   dfn->code = ALIGN_MALLOC( end - start, 16 );                \
+   memcpy (dfn->code, start, end - start);             \
+}                                                      \
+while ( 0 )
+
+#define FIXUP( CODE, OFFSET, CHECKVAL, NEWVAL )        \
+do {                                           \
+   int *icode = (int *)(CODE+OFFSET);          \
+   assert (*icode == CHECKVAL);                        \
+   *icode = (int)NEWVAL;                       \
+} while (0)
+
+
+/* Useful for figuring out the offsets:
+ */
+#define FIXUP2( CODE, OFFSET, CHECKVAL, NEWVAL )               \
+do {                                                           \
+   while (*(int *)(CODE+OFFSET) != CHECKVAL) OFFSET++;         \
+   fprintf(stderr, "%s/%d CVAL %x OFFSET %d VAL %x\n", __FUNCTION__,   \
+          __LINE__, CHECKVAL, OFFSET, (int)(NEWVAL));                  \
+   *(int *)(CODE+OFFSET) = (int)(NEWVAL);                              \
+   OFFSET += 4;                                                        \
+} while (0)
+
+/* 
+ */
+void radeonInitCodegen( struct dfn_generators *gen );
+void radeonInitX86Codegen( struct dfn_generators *gen );
+void radeonInitSSECodegen( struct dfn_generators *gen );
+
+
+
+/* Defined in radeon_vtxfmt_x86.c
+ */
+struct dynfn *radeon_makeX86Vertex2f( GLcontext *, int );
+struct dynfn *radeon_makeX86Vertex2fv( GLcontext *, int );
+struct dynfn *radeon_makeX86Vertex3f( GLcontext *, int );
+struct dynfn *radeon_makeX86Vertex3fv( GLcontext *, int );
+struct dynfn *radeon_makeX86Color4ub( GLcontext *, int );
+struct dynfn *radeon_makeX86Color4ubv( GLcontext *, int );
+struct dynfn *radeon_makeX86Color3ub( GLcontext *, int );
+struct dynfn *radeon_makeX86Color3ubv( GLcontext *, int );
+struct dynfn *radeon_makeX86Color4f( GLcontext *, int );
+struct dynfn *radeon_makeX86Color4fv( GLcontext *, int );
+struct dynfn *radeon_makeX86Color3f( GLcontext *, int );
+struct dynfn *radeon_makeX86Color3fv( GLcontext *, int );
+struct dynfn *radeon_makeX86SecondaryColor3ubEXT( GLcontext *, int );
+struct dynfn *radeon_makeX86SecondaryColor3ubvEXT( GLcontext *, int );
+struct dynfn *radeon_makeX86SecondaryColor3fEXT( GLcontext *, int );
+struct dynfn *radeon_makeX86SecondaryColor3fvEXT( GLcontext *, int );
+struct dynfn *radeon_makeX86Normal3f( GLcontext *, int );
+struct dynfn *radeon_makeX86Normal3fv( GLcontext *, int );
+struct dynfn *radeon_makeX86TexCoord2f( GLcontext *, int );
+struct dynfn *radeon_makeX86TexCoord2fv( GLcontext *, int );
+struct dynfn *radeon_makeX86TexCoord1f( GLcontext *, int );
+struct dynfn *radeon_makeX86TexCoord1fv( GLcontext *, int );
+struct dynfn *radeon_makeX86MultiTexCoord2fARB( GLcontext *, int );
+struct dynfn *radeon_makeX86MultiTexCoord2fvARB( GLcontext *, int );
+struct dynfn *radeon_makeX86MultiTexCoord1fARB( GLcontext *, int );
+struct dynfn *radeon_makeX86MultiTexCoord1fvARB( GLcontext *, int );
+
+
+#endif
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_vtxfmt_c.c b/src/mesa/drivers/dri/radeon/radeon_vtxfmt_c.c
new file mode 100644 (file)
index 0000000..188e34a
--- /dev/null
@@ -0,0 +1,905 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 2002 ATI Technologies Inc., Ontario, Canada, and
+                     Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ */
+#include "glheader.h"
+#include "mtypes.h"
+#include "colormac.h"
+#include "simple_list.h"
+#include "api_noop.h"
+#include "vtxfmt.h"
+
+#include "radeon_vtxfmt.h"
+
+/* Fallback versions of all the entrypoints for situations where
+ * codegen isn't available.  This is still a lot faster than the
+ * vb/pipeline implementation in Mesa.
+ */
+static void radeon_Vertex3f( GLfloat x, GLfloat y, GLfloat z )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   int i;
+
+   *rmesa->vb.dmaptr++ = *(int *)&x;
+   *rmesa->vb.dmaptr++ = *(int *)&y;
+   *rmesa->vb.dmaptr++ = *(int *)&z;
+
+   for (i = 3; i < rmesa->vb.vertex_size; i++)
+      *rmesa->vb.dmaptr++ = rmesa->vb.vertex[i].i;
+   
+   if (--rmesa->vb.counter == 0)
+      rmesa->vb.notify();
+}
+
+
+static void radeon_Vertex3fv( const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   int i;
+
+   *rmesa->vb.dmaptr++ = *(int *)&v[0];
+   *rmesa->vb.dmaptr++ = *(int *)&v[1];
+   *rmesa->vb.dmaptr++ = *(int *)&v[2];
+
+   for (i = 3; i < rmesa->vb.vertex_size; i++)
+      *rmesa->vb.dmaptr++ = rmesa->vb.vertex[i].i;
+   
+   if (--rmesa->vb.counter == 0)
+      rmesa->vb.notify();
+}
+
+
+static void radeon_Vertex2f( GLfloat x, GLfloat y )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   int i;
+
+   *rmesa->vb.dmaptr++ = *(int *)&x;
+   *rmesa->vb.dmaptr++ = *(int *)&y;
+   *rmesa->vb.dmaptr++ = 0;
+
+   for (i = 3; i < rmesa->vb.vertex_size; i++)
+      *rmesa->vb.dmaptr++ = *(int *)&rmesa->vb.vertex[i];
+   
+   if (--rmesa->vb.counter == 0)
+      rmesa->vb.notify();
+}
+
+
+static void radeon_Vertex2fv( const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   int i;
+
+   *rmesa->vb.dmaptr++ = *(int *)&v[0];
+   *rmesa->vb.dmaptr++ = *(int *)&v[1];
+   *rmesa->vb.dmaptr++ = 0;
+
+   for (i = 3; i < rmesa->vb.vertex_size; i++)
+      *rmesa->vb.dmaptr++ = rmesa->vb.vertex[i].i;
+   
+   if (--rmesa->vb.counter == 0)
+      rmesa->vb.notify();
+}
+
+
+
+/* Color for ubyte (packed) color formats:
+ */
+static void radeon_Color3ub_ub( GLubyte r, GLubyte g, GLubyte b )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   radeon_color_t *dest = rmesa->vb.colorptr;
+   dest->red   = r;
+   dest->green = g;
+   dest->blue  = b;
+   dest->alpha = 0xff;
+}
+
+static void radeon_Color3ubv_ub( const GLubyte *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   radeon_color_t *dest = rmesa->vb.colorptr;
+   dest->red   = v[0];
+   dest->green = v[1];
+   dest->blue  = v[2];
+   dest->alpha = 0xff;
+}
+
+static void radeon_Color4ub_ub( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   radeon_color_t *dest = rmesa->vb.colorptr;
+   dest->red   = r;
+   dest->green = g;
+   dest->blue  = b;
+   dest->alpha = a;
+}
+
+static void radeon_Color4ubv_ub( const GLubyte *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   *(GLuint *)rmesa->vb.colorptr = LE32_TO_CPU(*(GLuint *)v);
+}
+
+
+static void radeon_Color3f_ub( GLfloat r, GLfloat g, GLfloat b )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   radeon_color_t *dest = rmesa->vb.colorptr;
+   UNCLAMPED_FLOAT_TO_UBYTE( dest->red,   r );
+   UNCLAMPED_FLOAT_TO_UBYTE( dest->green, g );
+   UNCLAMPED_FLOAT_TO_UBYTE( dest->blue,  b );
+   dest->alpha = 255;
+}
+
+static void radeon_Color3fv_ub( const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   radeon_color_t *dest = rmesa->vb.colorptr;
+   UNCLAMPED_FLOAT_TO_UBYTE( dest->red,   v[0] );
+   UNCLAMPED_FLOAT_TO_UBYTE( dest->green, v[1] );
+   UNCLAMPED_FLOAT_TO_UBYTE( dest->blue,  v[2] );
+   dest->alpha = 255;
+}
+
+static void radeon_Color4f_ub( GLfloat r, GLfloat g, GLfloat b, GLfloat a )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   radeon_color_t *dest = rmesa->vb.colorptr;
+   UNCLAMPED_FLOAT_TO_UBYTE( dest->red,   r );
+   UNCLAMPED_FLOAT_TO_UBYTE( dest->green, g );
+   UNCLAMPED_FLOAT_TO_UBYTE( dest->blue,  b );
+   UNCLAMPED_FLOAT_TO_UBYTE( dest->alpha, a );
+}
+
+static void radeon_Color4fv_ub( const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   radeon_color_t *dest = rmesa->vb.colorptr;
+   UNCLAMPED_FLOAT_TO_UBYTE( dest->red,          v[0] );
+   UNCLAMPED_FLOAT_TO_UBYTE( dest->green, v[1] );
+   UNCLAMPED_FLOAT_TO_UBYTE( dest->blue,  v[2] );
+   UNCLAMPED_FLOAT_TO_UBYTE( dest->alpha, v[3] );
+}
+
+
+/* Color for float color+alpha formats:
+ */
+static void radeon_Color3ub_4f( GLubyte r, GLubyte g, GLubyte b )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.floatcolorptr;
+   dest[0] = UBYTE_TO_FLOAT(r);
+   dest[1] = UBYTE_TO_FLOAT(g);
+   dest[2] = UBYTE_TO_FLOAT(b);
+   dest[3] = 1.0;
+}
+
+static void radeon_Color3ubv_4f( const GLubyte *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.floatcolorptr;
+   dest[0] = UBYTE_TO_FLOAT(v[0]);
+   dest[1] = UBYTE_TO_FLOAT(v[1]);
+   dest[2] = UBYTE_TO_FLOAT(v[2]);
+   dest[3] = 1.0;
+}
+
+static void radeon_Color4ub_4f( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.floatcolorptr;
+   dest[0] = UBYTE_TO_FLOAT(r);
+   dest[1] = UBYTE_TO_FLOAT(g);
+   dest[2] = UBYTE_TO_FLOAT(b);
+   dest[3] = UBYTE_TO_FLOAT(a);
+}
+
+static void radeon_Color4ubv_4f( const GLubyte *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.floatcolorptr;
+   dest[0] = UBYTE_TO_FLOAT(v[0]);
+   dest[1] = UBYTE_TO_FLOAT(v[1]);
+   dest[2] = UBYTE_TO_FLOAT(v[2]);
+   dest[3] = UBYTE_TO_FLOAT(v[3]);
+}
+
+
+static void radeon_Color3f_4f( GLfloat r, GLfloat g, GLfloat b )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.floatcolorptr;
+   dest[0] = r;
+   dest[1] = g;
+   dest[2] = b;
+   dest[3] = 1.0;              
+}
+
+static void radeon_Color3fv_4f( const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.floatcolorptr;
+   dest[0] = v[0];
+   dest[1] = v[1];
+   dest[2] = v[2];
+   dest[3] = 1.0;
+}
+
+static void radeon_Color4f_4f( GLfloat r, GLfloat g, GLfloat b, GLfloat a )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.floatcolorptr;
+   dest[0] = r;
+   dest[1] = g;
+   dest[2] = b;
+   dest[3] = a;
+}
+
+static void radeon_Color4fv_4f( const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.floatcolorptr;
+   dest[0] = v[0];
+   dest[1] = v[1];
+   dest[2] = v[2];
+   dest[3] = v[3];
+}
+
+
+/* Color for float color formats:
+ */
+static void radeon_Color3ub_3f( GLubyte r, GLubyte g, GLubyte b )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.floatcolorptr;
+   dest[0] = UBYTE_TO_FLOAT(r);
+   dest[1] = UBYTE_TO_FLOAT(g);
+   dest[2] = UBYTE_TO_FLOAT(b);
+}
+
+static void radeon_Color3ubv_3f( const GLubyte *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.floatcolorptr;
+   dest[0] = UBYTE_TO_FLOAT(v[0]);
+   dest[1] = UBYTE_TO_FLOAT(v[1]);
+   dest[2] = UBYTE_TO_FLOAT(v[2]);
+}
+
+static void radeon_Color4ub_3f( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.floatcolorptr;
+   dest[0] = UBYTE_TO_FLOAT(r);
+   dest[1] = UBYTE_TO_FLOAT(g);
+   dest[2] = UBYTE_TO_FLOAT(b);
+   ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] = UBYTE_TO_FLOAT(a);
+}
+
+static void radeon_Color4ubv_3f( const GLubyte *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.floatcolorptr;
+   dest[0] = UBYTE_TO_FLOAT(v[0]);
+   dest[1] = UBYTE_TO_FLOAT(v[1]);
+   dest[2] = UBYTE_TO_FLOAT(v[2]);
+   ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] = UBYTE_TO_FLOAT(v[3]);
+}
+
+
+static void radeon_Color3f_3f( GLfloat r, GLfloat g, GLfloat b )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.floatcolorptr;
+   dest[0] = r;
+   dest[1] = g;
+   dest[2] = b;
+}
+
+static void radeon_Color3fv_3f( const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.floatcolorptr;
+   dest[0] = v[0];
+   dest[1] = v[1];
+   dest[2] = v[2];
+}
+
+static void radeon_Color4f_3f( GLfloat r, GLfloat g, GLfloat b, GLfloat a )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.floatcolorptr;
+   dest[0] = r;
+   dest[1] = g;
+   dest[2] = b;
+   ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] = a;
+}
+
+static void radeon_Color4fv_3f( const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.floatcolorptr;
+   dest[0] = v[0];
+   dest[1] = v[1];
+   dest[2] = v[2];
+   ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] = v[3]; 
+}
+
+
+/* Secondary Color:
+ */
+static void radeon_SecondaryColor3ubEXT_ub( GLubyte r, GLubyte g, GLubyte b )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   radeon_color_t *dest = rmesa->vb.specptr;
+   dest->red   = r;
+   dest->green = g;
+   dest->blue  = b;
+   dest->alpha = 0xff;
+}
+
+static void radeon_SecondaryColor3ubvEXT_ub( const GLubyte *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   radeon_color_t *dest = rmesa->vb.specptr;
+   dest->red   = v[0];
+   dest->green = v[1];
+   dest->blue  = v[2];
+   dest->alpha = 0xff;
+}
+
+static void radeon_SecondaryColor3fEXT_ub( GLfloat r, GLfloat g, GLfloat b )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   radeon_color_t *dest = rmesa->vb.specptr;
+   UNCLAMPED_FLOAT_TO_UBYTE( dest->red,          r );
+   UNCLAMPED_FLOAT_TO_UBYTE( dest->green, g );
+   UNCLAMPED_FLOAT_TO_UBYTE( dest->blue,  b );
+   dest->alpha = 255;
+}
+
+static void radeon_SecondaryColor3fvEXT_ub( const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   radeon_color_t *dest = rmesa->vb.specptr;
+   UNCLAMPED_FLOAT_TO_UBYTE( dest->red,          v[0] );
+   UNCLAMPED_FLOAT_TO_UBYTE( dest->green, v[1] );
+   UNCLAMPED_FLOAT_TO_UBYTE( dest->blue,  v[2] );
+   dest->alpha = 255;
+}
+
+static void radeon_SecondaryColor3ubEXT_3f( GLubyte r, GLubyte g, GLubyte b )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.floatspecptr;
+   dest[0] = UBYTE_TO_FLOAT(r);
+   dest[1] = UBYTE_TO_FLOAT(g);
+   dest[2] = UBYTE_TO_FLOAT(b);
+   dest[3] = 1.0;
+}
+
+static void radeon_SecondaryColor3ubvEXT_3f( const GLubyte *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.floatspecptr;
+   dest[0] = UBYTE_TO_FLOAT(v[0]);
+   dest[1] = UBYTE_TO_FLOAT(v[1]);
+   dest[2] = UBYTE_TO_FLOAT(v[2]);
+   dest[3] = 1.0;
+}
+
+static void radeon_SecondaryColor3fEXT_3f( GLfloat r, GLfloat g, GLfloat b )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.floatspecptr;
+   dest[0] = r;
+   dest[1] = g;
+   dest[2] = b;
+   dest[3] = 1.0;
+}
+
+static void radeon_SecondaryColor3fvEXT_3f( const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.floatspecptr;
+   dest[0] = v[0];
+   dest[1] = v[1];
+   dest[2] = v[2];
+   dest[3] = 1.0;
+}
+
+
+/* Normal
+ */
+static void radeon_Normal3f( GLfloat n0, GLfloat n1, GLfloat n2 )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.normalptr;
+   dest[0] = n0;
+   dest[1] = n1;
+   dest[2] = n2;
+}
+
+static void radeon_Normal3fv( const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.normalptr;
+   dest[0] = v[0];
+   dest[1] = v[1];
+   dest[2] = v[2];
+}
+
+
+/* TexCoord
+ */
+static void radeon_TexCoord1f( GLfloat s )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.texcoordptr[0];
+   dest[0] = s;
+   dest[1] = 0;
+}
+
+static void radeon_TexCoord1fv( const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.texcoordptr[0];
+   dest[0] = v[0];
+   dest[1] = 0;
+}
+
+static void radeon_TexCoord2f( GLfloat s, GLfloat t )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.texcoordptr[0];
+   dest[0] = s;
+   dest[1] = t;
+}
+
+static void radeon_TexCoord2fv( const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.texcoordptr[0];
+   dest[0] = v[0];
+   dest[1] = v[1];
+}
+
+
+/* MultiTexcoord
+ * 
+ * Technically speaking, these functions should subtract GL_TEXTURE0 from
+ * \c target before masking and using it.  The value of GL_TEXTURE0 is 0x84C0,
+ * which has the low-order 5 bits 0.  For all possible valid values of 
+ * \c target.  Subtracting GL_TEXTURE0 has the net effect of masking \c target
+ * with 0x1F.  Masking with 0x1F and then masking with 0x01 is redundant, so
+ * the subtraction has been omitted.
+ */
+
+static void radeon_MultiTexCoord1fARB( GLenum target, GLfloat s  )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.texcoordptr[target & 1];
+   dest[0] = s;
+   dest[1] = 0;
+}
+
+static void radeon_MultiTexCoord1fvARB( GLenum target, const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.texcoordptr[target & 1];
+   dest[0] = v[0];
+   dest[1] = 0;
+}
+
+static void radeon_MultiTexCoord2fARB( GLenum target, GLfloat s, GLfloat t )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.texcoordptr[target & 1];
+   dest[0] = s;
+   dest[1] = t;
+}
+
+static void radeon_MultiTexCoord2fvARB( GLenum target, const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   GLfloat *dest = rmesa->vb.texcoordptr[target & 1];
+   dest[0] = v[0];
+   dest[1] = v[1];
+}
+
+static struct dynfn *lookup( struct dynfn *l, int key )
+{
+   struct dynfn *f;
+
+   foreach( f, l ) {
+      if (f->key == key) 
+        return f;
+   }
+
+   return 0;
+}
+
+/* Can't use the loopback template for this:
+ */
+
+#define CHOOSE(FN, FNTYPE, MASK, ACTIVE, ARGS1, ARGS2 )                        \
+static void choose_##FN ARGS1                                          \
+{                                                                      \
+   GET_CURRENT_CONTEXT(ctx);                                           \
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);                       \
+   int key = rmesa->vb.vertex_format & (MASK|ACTIVE);                  \
+   struct dynfn *dfn;                                                  \
+                                                                       \
+   dfn = lookup( &rmesa->vb.dfn_cache.FN, key );                       \
+   if (dfn == 0)                                                       \
+      dfn = rmesa->vb.codegen.FN( ctx, key );                          \
+   else if (RADEON_DEBUG & DEBUG_CODEGEN)                              \
+      fprintf(stderr, "%s -- cached codegen\n", __FUNCTION__ );                \
+                                                                       \
+   if (dfn)                                                            \
+      ctx->Exec->FN = (FNTYPE)(dfn->code);                             \
+   else {                                                              \
+      if (RADEON_DEBUG & DEBUG_CODEGEN)                                        \
+        fprintf(stderr, "%s -- generic version\n", __FUNCTION__ );     \
+      ctx->Exec->FN = radeon_##FN;                                     \
+   }                                                                   \
+                                                                       \
+   ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;                      \
+   ctx->Exec->FN ARGS2;                                                        \
+}
+
+
+
+/* For the _3f case, only allow one color function to be hooked in at
+ * a time.  Eventually, use a similar mechanism to allow selecting the
+ * color component of the vertex format based on client behaviour.  
+ *
+ * Note:  Perform these actions even if there is a codegen or cached 
+ * codegen version of the chosen function.
+ */
+#define CHOOSE_COLOR(FN, FNTYPE, NR, MASK, ACTIVE, ARGS1, ARGS2 )      \
+static void choose_##FN ARGS1                                          \
+{                                                                      \
+   GET_CURRENT_CONTEXT(ctx); \
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);                       \
+   int key = rmesa->vb.vertex_format & (MASK|ACTIVE);                  \
+   struct dynfn *dfn;                                                  \
+                                                                       \
+   if (rmesa->vb.vertex_format & ACTIVE_PKCOLOR) {                     \
+      ctx->Exec->FN = radeon_##FN##_ub;                                        \
+   }                                                                   \
+   else if ((rmesa->vb.vertex_format &                                 \
+            (ACTIVE_FPCOLOR|ACTIVE_FPALPHA)) == ACTIVE_FPCOLOR) {      \
+                                                                       \
+      if (rmesa->vb.installed_color_3f_sz != NR) {                     \
+         rmesa->vb.installed_color_3f_sz = NR;                         \
+         if (NR == 3) ctx->Current.Attrib[VERT_ATTRIB_COLOR0][3] = 1.0;        \
+         if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) {           \
+            radeon_copy_to_current( ctx );                             \
+            _mesa_install_exec_vtxfmt( ctx, &rmesa->vb.vtxfmt );       \
+            ctx->Exec->FN ARGS2;                                       \
+            return;                                                    \
+         }                                                             \
+      }                                                                        \
+                                                                       \
+      ctx->Exec->FN = radeon_##FN##_3f;                                        \
+   }                                                                   \
+   else {                                                              \
+      ctx->Exec->FN = radeon_##FN##_4f;                                        \
+   }                                                                   \
+                                                                       \
+                                                                       \
+   dfn = lookup( &rmesa->vb.dfn_cache.FN, key );                       \
+   if (!dfn) dfn = rmesa->vb.codegen.FN( ctx, key );                   \
+                                                                       \
+   if (dfn) {                                                          \
+      if (RADEON_DEBUG & DEBUG_CODEGEN)                                        \
+         fprintf(stderr, "%s -- codegen version\n", __FUNCTION__ );    \
+      ctx->Exec->FN = (FNTYPE)dfn->code;                               \
+   }                                                                   \
+   else if (RADEON_DEBUG & DEBUG_CODEGEN)                              \
+         fprintf(stderr, "%s -- 'c' version\n", __FUNCTION__ );                \
+                                                                       \
+   ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;                      \
+   ctx->Exec->FN ARGS2;                                                        \
+}
+
+
+
+/* Right now there are both _ub and _3f versions of the secondary color
+ * functions.  Currently, we only set-up the hardware to use the _ub versions.
+ * The _3f versions are needed for the cases where secondary color isn't used
+ * in the vertex format, but it still needs to be stored in the context
+ * state vector.
+ */
+#define CHOOSE_SECONDARY_COLOR(FN, FNTYPE, MASK, ACTIVE, ARGS1, ARGS2 )        \
+static void choose_##FN ARGS1                                          \
+{                                                                      \
+   GET_CURRENT_CONTEXT(ctx);                                           \
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);                       \
+   int key = rmesa->vb.vertex_format & (MASK|ACTIVE);                  \
+   struct dynfn *dfn = lookup( &rmesa->vb.dfn_cache.FN, key );         \
+                                                                       \
+   if (dfn == 0)                                                       \
+      dfn = rmesa->vb.codegen.FN( ctx, key );                          \
+   else  if (RADEON_DEBUG & DEBUG_CODEGEN)                             \
+      fprintf(stderr, "%s -- cached version\n", __FUNCTION__ );                \
+                                                                       \
+   if (dfn)                                                            \
+      ctx->Exec->FN = (FNTYPE)(dfn->code);                             \
+   else {                                                              \
+      if (RADEON_DEBUG & DEBUG_CODEGEN)                                        \
+         fprintf(stderr, "%s -- generic version\n", __FUNCTION__ );    \
+      ctx->Exec->FN = ((rmesa->vb.vertex_format & ACTIVE_PKSPEC) != 0) \
+         ? radeon_##FN##_ub : radeon_##FN##_3f;                        \
+   }                                                                   \
+                                                                       \
+   ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;                      \
+   ctx->Exec->FN ARGS2;                                                        \
+}
+
+
+
+
+
+/* Shorthands
+ */
+#define ACTIVE_XYZW (RADEON_CP_VC_FRMT_W0|RADEON_CP_VC_FRMT_Z)
+#define ACTIVE_NORM RADEON_CP_VC_FRMT_N0
+
+#define ACTIVE_PKCOLOR RADEON_CP_VC_FRMT_PKCOLOR
+#define ACTIVE_FPCOLOR RADEON_CP_VC_FRMT_FPCOLOR
+#define ACTIVE_FPALPHA RADEON_CP_VC_FRMT_FPALPHA
+#define ACTIVE_COLOR (ACTIVE_FPCOLOR|ACTIVE_PKCOLOR)
+
+#define ACTIVE_PKSPEC RADEON_CP_VC_FRMT_PKSPEC
+#define ACTIVE_FPSPEC RADEON_CP_VC_FRMT_FPSPEC
+#define ACTIVE_SPEC   (ACTIVE_FPSPEC|ACTIVE_PKSPEC)
+
+#define ACTIVE_ST0 RADEON_CP_VC_FRMT_ST0
+#define ACTIVE_ST1 RADEON_CP_VC_FRMT_ST1
+#define ACTIVE_ST_ALL (RADEON_CP_VC_FRMT_ST1|RADEON_CP_VC_FRMT_ST0)
+
+/* Each codegen function should be able to be fully specified by a
+ * subsetted version of rmesa->vb.vertex_format.
+ */
+#define MASK_NORM    (ACTIVE_XYZW)
+#define MASK_COLOR   (MASK_NORM|ACTIVE_NORM)
+#define MASK_SPEC    (MASK_COLOR|ACTIVE_COLOR)
+#define MASK_ST0     (MASK_SPEC|ACTIVE_SPEC)
+#define MASK_ST1     (MASK_ST0|ACTIVE_ST0)
+#define MASK_ST_ALL  (MASK_ST1|ACTIVE_ST1)
+#define MASK_VERTEX  (MASK_ST_ALL|ACTIVE_FPALPHA) 
+
+
+typedef void (*p4f)( GLfloat, GLfloat, GLfloat, GLfloat );
+typedef void (*p3f)( GLfloat, GLfloat, GLfloat );
+typedef void (*p2f)( GLfloat, GLfloat );
+typedef void (*p1f)( GLfloat );
+typedef void (*pe2f)( GLenum, GLfloat, GLfloat );
+typedef void (*pe1f)( GLenum, GLfloat );
+typedef void (*p4ub)( GLubyte, GLubyte, GLubyte, GLubyte );
+typedef void (*p3ub)( GLubyte, GLubyte, GLubyte );
+typedef void (*pfv)( const GLfloat * );
+typedef void (*pefv)( GLenum, const GLfloat * );
+typedef void (*pubv)( const GLubyte * );
+
+
+CHOOSE(Normal3f, p3f, MASK_NORM, ACTIVE_NORM, 
+       (GLfloat a,GLfloat b,GLfloat c), (a,b,c))
+CHOOSE(Normal3fv, pfv, MASK_NORM, ACTIVE_NORM, 
+       (const GLfloat *v), (v))
+
+CHOOSE_COLOR(Color4ub, p4ub, 4, MASK_COLOR, ACTIVE_COLOR,
+       (GLubyte a,GLubyte b, GLubyte c, GLubyte d), (a,b,c,d))
+CHOOSE_COLOR(Color4ubv, pubv, 4, MASK_COLOR, ACTIVE_COLOR, 
+       (const GLubyte *v), (v))
+CHOOSE_COLOR(Color3ub, p3ub, 3, MASK_COLOR, ACTIVE_COLOR, 
+       (GLubyte a,GLubyte b, GLubyte c), (a,b,c))
+CHOOSE_COLOR(Color3ubv, pubv, 3, MASK_COLOR, ACTIVE_COLOR, 
+       (const GLubyte *v), (v))
+
+CHOOSE_COLOR(Color4f, p4f, 4, MASK_COLOR, ACTIVE_COLOR, 
+       (GLfloat a,GLfloat b, GLfloat c, GLfloat d), (a,b,c,d))
+CHOOSE_COLOR(Color4fv, pfv, 4, MASK_COLOR, ACTIVE_COLOR, 
+       (const GLfloat *v), (v))
+CHOOSE_COLOR(Color3f, p3f, 3, MASK_COLOR, ACTIVE_COLOR,
+       (GLfloat a,GLfloat b, GLfloat c), (a,b,c))
+CHOOSE_COLOR(Color3fv, pfv, 3, MASK_COLOR, ACTIVE_COLOR,
+       (const GLfloat *v), (v))
+
+
+CHOOSE_SECONDARY_COLOR(SecondaryColor3ubEXT, p3ub, MASK_SPEC, ACTIVE_SPEC,
+       (GLubyte a,GLubyte b, GLubyte c), (a,b,c))
+CHOOSE_SECONDARY_COLOR(SecondaryColor3ubvEXT, pubv, MASK_SPEC, ACTIVE_SPEC,
+       (const GLubyte *v), (v))
+CHOOSE_SECONDARY_COLOR(SecondaryColor3fEXT, p3f, MASK_SPEC, ACTIVE_SPEC,
+       (GLfloat a,GLfloat b, GLfloat c), (a,b,c))
+CHOOSE_SECONDARY_COLOR(SecondaryColor3fvEXT, pfv, MASK_SPEC, ACTIVE_SPEC,
+       (const GLfloat *v), (v))
+
+CHOOSE(TexCoord2f, p2f, MASK_ST0, ACTIVE_ST0, 
+       (GLfloat a,GLfloat b), (a,b))
+CHOOSE(TexCoord2fv, pfv, MASK_ST0, ACTIVE_ST0, 
+       (const GLfloat *v), (v))
+CHOOSE(TexCoord1f, p1f, MASK_ST0, ACTIVE_ST0, 
+       (GLfloat a), (a))
+CHOOSE(TexCoord1fv, pfv, MASK_ST0, ACTIVE_ST0, 
+       (const GLfloat *v), (v))
+
+CHOOSE(MultiTexCoord2fARB, pe2f, MASK_ST_ALL, ACTIVE_ST_ALL,
+        (GLenum u,GLfloat a,GLfloat b), (u,a,b))
+CHOOSE(MultiTexCoord2fvARB, pefv, MASK_ST_ALL, ACTIVE_ST_ALL,
+       (GLenum u,const GLfloat *v), (u,v))
+CHOOSE(MultiTexCoord1fARB, pe1f, MASK_ST_ALL, ACTIVE_ST_ALL,
+        (GLenum u,GLfloat a), (u,a))
+CHOOSE(MultiTexCoord1fvARB, pefv, MASK_ST_ALL, ACTIVE_ST_ALL,
+       (GLenum u,const GLfloat *v), (u,v))
+
+CHOOSE(Vertex3f, p3f, MASK_VERTEX, MASK_VERTEX, 
+       (GLfloat a,GLfloat b,GLfloat c), (a,b,c))
+CHOOSE(Vertex3fv, pfv, MASK_VERTEX, MASK_VERTEX, 
+       (const GLfloat *v), (v))
+CHOOSE(Vertex2f, p2f, MASK_VERTEX, MASK_VERTEX, 
+       (GLfloat a,GLfloat b), (a,b))
+CHOOSE(Vertex2fv, pfv, MASK_VERTEX, MASK_VERTEX, 
+       (const GLfloat *v), (v))
+
+
+
+
+
+void radeonVtxfmtInitChoosers( GLvertexformat *vfmt )
+{
+   vfmt->Color3f = choose_Color3f;
+   vfmt->Color3fv = choose_Color3fv;
+   vfmt->Color3ub = choose_Color3ub;
+   vfmt->Color3ubv = choose_Color3ubv;
+   vfmt->Color4f = choose_Color4f;
+   vfmt->Color4fv = choose_Color4fv;
+   vfmt->Color4ub = choose_Color4ub;
+   vfmt->Color4ubv = choose_Color4ubv;
+   vfmt->SecondaryColor3fEXT = choose_SecondaryColor3fEXT;
+   vfmt->SecondaryColor3fvEXT = choose_SecondaryColor3fvEXT;
+   vfmt->SecondaryColor3ubEXT = choose_SecondaryColor3ubEXT;
+   vfmt->SecondaryColor3ubvEXT = choose_SecondaryColor3ubvEXT;
+   vfmt->MultiTexCoord1fARB = choose_MultiTexCoord1fARB;
+   vfmt->MultiTexCoord1fvARB = choose_MultiTexCoord1fvARB;
+   vfmt->MultiTexCoord2fARB = choose_MultiTexCoord2fARB;
+   vfmt->MultiTexCoord2fvARB = choose_MultiTexCoord2fvARB;
+   vfmt->Normal3f = choose_Normal3f;
+   vfmt->Normal3fv = choose_Normal3fv;
+   vfmt->TexCoord1f = choose_TexCoord1f;
+   vfmt->TexCoord1fv = choose_TexCoord1fv;
+   vfmt->TexCoord2f = choose_TexCoord2f;
+   vfmt->TexCoord2fv = choose_TexCoord2fv;
+   vfmt->Vertex2f = choose_Vertex2f;
+   vfmt->Vertex2fv = choose_Vertex2fv;
+   vfmt->Vertex3f = choose_Vertex3f;
+   vfmt->Vertex3fv = choose_Vertex3fv;
+}
+
+
+static struct dynfn *codegen_noop( GLcontext *ctx, int key )
+{
+   (void) ctx; (void) key;
+   return 0;
+}
+
+void radeonInitCodegen( struct dfn_generators *gen )
+{
+   gen->Vertex3f = codegen_noop;
+   gen->Vertex3fv = codegen_noop;
+   gen->Color4ub = codegen_noop;
+   gen->Color4ubv = codegen_noop;
+   gen->Normal3f = codegen_noop;
+   gen->Normal3fv = codegen_noop;
+   gen->TexCoord2f = codegen_noop;
+   gen->TexCoord2fv = codegen_noop;
+   gen->MultiTexCoord2fARB = codegen_noop;
+   gen->MultiTexCoord2fvARB = codegen_noop;
+   gen->Vertex2f = codegen_noop;
+   gen->Vertex2fv = codegen_noop;
+   gen->Color3ub = codegen_noop;
+   gen->Color3ubv = codegen_noop;
+   gen->Color4f = codegen_noop;
+   gen->Color4fv = codegen_noop;
+   gen->Color3f = codegen_noop;
+   gen->Color3fv = codegen_noop;
+   gen->SecondaryColor3fEXT = codegen_noop;
+   gen->SecondaryColor3fvEXT = codegen_noop;
+   gen->SecondaryColor3ubEXT = codegen_noop;
+   gen->SecondaryColor3ubvEXT = codegen_noop;
+   gen->TexCoord1f = codegen_noop;
+   gen->TexCoord1fv = codegen_noop;
+   gen->MultiTexCoord1fARB = codegen_noop;
+   gen->MultiTexCoord1fvARB = codegen_noop;
+
+   if (!getenv("RADEON_NO_CODEGEN")) {
+#if defined(USE_X86_ASM)
+      radeonInitX86Codegen( gen );
+#endif
+
+#if defined(USE_SSE_ASM)
+      radeonInitSSECodegen( gen );
+#endif
+   }
+}
diff --git a/src/mesa/drivers/dri/radeon/radeon_vtxfmt_sse.c b/src/mesa/drivers/dri/radeon/radeon_vtxfmt_sse.c
new file mode 100644 (file)
index 0000000..0f2c82b
--- /dev/null
@@ -0,0 +1,232 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "simple_list.h" 
+#include "radeon_vtxfmt.h"
+
+#if defined(USE_SSE_ASM)
+#include "X86/common_x86_asm.h"
+
+#define EXTERN( FUNC )         \
+extern const char *FUNC;       \
+extern const char *FUNC##_end
+
+EXTERN( _sse_Attribute2fv );
+EXTERN( _sse_Attribute2f );
+EXTERN( _sse_Attribute3fv );
+EXTERN( _sse_Attribute3f );
+EXTERN( _sse_MultiTexCoord2fv );
+EXTERN( _sse_MultiTexCoord2f );
+EXTERN( _sse_MultiTexCoord2fv_2 );
+EXTERN( _sse_MultiTexCoord2f_2 );
+
+/* Build specialized versions of the immediate calls on the fly for
+ * the current state.
+ */
+
+static struct dynfn *radeon_makeSSEAttribute2fv( struct dynfn * cache, int key,
+                                              const char * name, void * dest)
+{
+   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+
+   if (RADEON_DEBUG & DEBUG_CODEGEN)
+      fprintf(stderr, "%s 0x%08x\n", name, key );
+
+   DFN ( _sse_Attribute2fv, (*cache) );
+   FIXUP(dfn->code, 10, 0x0, (int)dest);
+   return dfn;
+}
+
+static struct dynfn *radeon_makeSSEAttribute2f( struct dynfn * cache, int key,
+                                             const char * name, void * dest )
+{
+   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+
+   if (RADEON_DEBUG & DEBUG_CODEGEN)
+      fprintf(stderr, "%s 0x%08x\n", name, key );
+
+   DFN ( _sse_Attribute2f, (*cache) );
+   FIXUP(dfn->code, 8, 0x0, (int)dest); 
+   return dfn;
+}
+
+static struct dynfn *radeon_makeSSEAttribute3fv( struct dynfn * cache, int key,
+                                              const char * name, void * dest)
+{
+   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+
+   if (RADEON_DEBUG & DEBUG_CODEGEN)
+      fprintf(stderr, "%s 0x%08x\n", name, key );
+
+   DFN ( _sse_Attribute3fv, (*cache) );
+   FIXUP(dfn->code, 13, 0x0, (int)dest);
+   FIXUP(dfn->code, 18, 0x8, 8+(int)dest);
+   return dfn;
+}
+
+static struct dynfn *radeon_makeSSEAttribute3f( struct dynfn * cache, int key,
+                                             const char * name, void * dest )
+{
+   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+
+   if (RADEON_DEBUG & DEBUG_CODEGEN)
+      fprintf(stderr, "%s 0x%08x\n", name, key );
+
+   DFN ( _sse_Attribute3f, (*cache) );
+   FIXUP(dfn->code, 12, 0x0, (int)dest); 
+   FIXUP(dfn->code, 17, 0x8, 8+(int)dest); 
+   return dfn;
+}
+
+static struct dynfn * radeon_makeSSENormal3fv( GLcontext *ctx, int key )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   return radeon_makeSSEAttribute3fv( & rmesa->vb.dfn_cache.Normal3fv, key,
+                                     __FUNCTION__, rmesa->vb.normalptr );
+}
+
+static struct dynfn *radeon_makeSSENormal3f( GLcontext *ctx, int key )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   return radeon_makeSSEAttribute3f( & rmesa->vb.dfn_cache.Normal3f, key,
+                                    __FUNCTION__, rmesa->vb.normalptr );
+}
+
+static struct dynfn *radeon_makeSSEColor3fv( GLcontext *ctx, int key )
+{
+   if (key & (RADEON_CP_VC_FRMT_PKCOLOR|RADEON_CP_VC_FRMT_FPALPHA))
+      return 0;
+   else
+   {
+      radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+      return radeon_makeSSEAttribute3fv( & rmesa->vb.dfn_cache.Color3fv, key,
+                                        __FUNCTION__, rmesa->vb.floatcolorptr );
+   }
+}
+
+static struct dynfn *radeon_makeSSEColor3f( GLcontext *ctx, int key )
+{
+   if (key & (RADEON_CP_VC_FRMT_PKCOLOR|RADEON_CP_VC_FRMT_FPALPHA))
+      return 0;
+   else
+   {
+      radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+      return radeon_makeSSEAttribute3f( & rmesa->vb.dfn_cache.Color3f, key,
+                                       __FUNCTION__, rmesa->vb.floatcolorptr );
+   }
+}
+
+static struct dynfn *radeon_makeSSETexCoord2fv( GLcontext *ctx, int key )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   return radeon_makeSSEAttribute2fv( & rmesa->vb.dfn_cache.TexCoord2fv, key,
+                                      __FUNCTION__, rmesa->vb.texcoordptr[0] );
+}
+
+static struct dynfn *radeon_makeSSETexCoord2f( GLcontext *ctx, int key )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   return radeon_makeSSEAttribute2f( & rmesa->vb.dfn_cache.TexCoord2f, key,
+                                    __FUNCTION__, rmesa->vb.texcoordptr[0] );
+}
+
+static struct dynfn *radeon_makeSSEMultiTexCoord2fv( GLcontext *ctx, int key )
+{
+   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   if (RADEON_DEBUG & DEBUG_CODEGEN)
+      fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
+
+   if ((key & (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) ==
+      (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) {
+      DFN ( _sse_MultiTexCoord2fv, rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
+      FIXUP(dfn->code, 18, 0xdeadbeef, (int)rmesa->vb.texcoordptr[0]); 
+   } else {
+      DFN ( _sse_MultiTexCoord2fv_2, rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
+      FIXUP(dfn->code, 14, 0x0, (int)rmesa->vb.texcoordptr);
+   }
+   return dfn;
+}
+
+static struct dynfn *radeon_makeSSEMultiTexCoord2f( GLcontext *ctx, int key )
+{
+   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   if (RADEON_DEBUG & DEBUG_CODEGEN)
+      fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
+
+   if ((key & (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) ==
+      (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) {
+      DFN ( _sse_MultiTexCoord2f, rmesa->vb.dfn_cache.MultiTexCoord2fARB );
+      FIXUP(dfn->code, 16, 0xdeadbeef, (int)rmesa->vb.texcoordptr[0]); 
+   } else {
+      DFN ( _sse_MultiTexCoord2f_2, rmesa->vb.dfn_cache.MultiTexCoord2fARB );
+      FIXUP(dfn->code, 15, 0x0, (int)rmesa->vb.texcoordptr);
+   }
+   return dfn;
+}
+
+void radeonInitSSECodegen( struct dfn_generators *gen )
+{
+   if ( cpu_has_xmm ) {
+      gen->Normal3fv = (void *) radeon_makeSSENormal3fv;
+      gen->Normal3f = (void *) radeon_makeSSENormal3f;
+      gen->Color3fv = (void *) radeon_makeSSEColor3fv;
+      gen->Color3f = (void *) radeon_makeSSEColor3f;
+      gen->TexCoord2fv = (void *) radeon_makeSSETexCoord2fv;
+      gen->TexCoord2f = (void *) radeon_makeSSETexCoord2f;
+      gen->MultiTexCoord2fvARB = (void *) radeon_makeSSEMultiTexCoord2fv;
+      gen->MultiTexCoord2fARB = (void *) radeon_makeSSEMultiTexCoord2f;
+   }
+}
+
+#else 
+
+void radeonInitSSECodegen( struct dfn_generators *gen )
+{
+   (void) gen;
+}
+
+#endif
diff --git a/src/mesa/drivers/dri/radeon/radeon_vtxfmt_x86.c b/src/mesa/drivers/dri/radeon/radeon_vtxfmt_x86.c
new file mode 100644 (file)
index 0000000..92941ca
--- /dev/null
@@ -0,0 +1,437 @@
+/* $XFree86$ */
+/**************************************************************************
+
+Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
+                     Tungsten Graphics Inc., Cedar Park, Texas.
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial
+portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+/*
+ * Authors:
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "glheader.h"
+#include "imports.h"
+#include "simple_list.h" 
+#include "radeon_vtxfmt.h"
+
+#if defined(USE_X86_ASM)
+
+#define EXTERN( FUNC )         \
+extern const char *FUNC;       \
+extern const char *FUNC##_end
+
+EXTERN ( _x86_Attribute2fv );
+EXTERN ( _x86_Attribute2f );
+EXTERN ( _x86_Attribute3fv );
+EXTERN ( _x86_Attribute3f );
+EXTERN ( _x86_Vertex3fv_6 );
+EXTERN ( _x86_Vertex3fv_8 );
+EXTERN ( _x86_Vertex3fv );
+EXTERN ( _x86_Vertex3f_4 );
+EXTERN ( _x86_Vertex3f_6 );
+EXTERN ( _x86_Vertex3f );
+EXTERN ( _x86_Color4ubv_ub );
+EXTERN ( _x86_Color4ubv_4f );
+EXTERN ( _x86_Color4ub_ub );
+EXTERN ( _x86_MultiTexCoord2fv );
+EXTERN ( _x86_MultiTexCoord2fv_2 );
+EXTERN ( _x86_MultiTexCoord2f );
+EXTERN ( _x86_MultiTexCoord2f_2 );
+
+
+/* Build specialized versions of the immediate calls on the fly for
+ * the current state.  Generic x86 versions.
+ */
+
+struct dynfn *radeon_makeX86Vertex3f( GLcontext *ctx, int key )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+
+   if (RADEON_DEBUG & DEBUG_CODEGEN)
+      fprintf(stderr, "%s 0x%08x %d\n", __FUNCTION__, key, rmesa->vb.vertex_size );
+
+   switch (rmesa->vb.vertex_size) {
+   case 4: {
+
+      DFN ( _x86_Vertex3f_4, rmesa->vb.dfn_cache.Vertex3f );
+      FIXUP(dfn->code, 2, 0x0, (int)&rmesa->vb.dmaptr);
+      FIXUP(dfn->code, 25, 0x0, (int)&rmesa->vb.vertex[3]);
+      FIXUP(dfn->code, 36, 0x0, (int)&rmesa->vb.counter);
+      FIXUP(dfn->code, 46, 0x0, (int)&rmesa->vb.dmaptr);
+      FIXUP(dfn->code, 51, 0x0, (int)&rmesa->vb.counter);
+      FIXUP(dfn->code, 60, 0x0, (int)&rmesa->vb.notify);
+      break;
+   }
+   case 6: {
+
+      DFN ( _x86_Vertex3f_6, rmesa->vb.dfn_cache.Vertex3f );
+      FIXUP(dfn->code, 3, 0x0, (int)&rmesa->vb.dmaptr);
+      FIXUP(dfn->code, 28, 0x0, (int)&rmesa->vb.vertex[3]);
+      FIXUP(dfn->code, 34, 0x0, (int)&rmesa->vb.vertex[4]);
+      FIXUP(dfn->code, 40, 0x0, (int)&rmesa->vb.vertex[5]);
+      FIXUP(dfn->code, 57, 0x0, (int)&rmesa->vb.counter);
+      FIXUP(dfn->code, 63, 0x0, (int)&rmesa->vb.dmaptr);
+      FIXUP(dfn->code, 70, 0x0, (int)&rmesa->vb.counter);
+      FIXUP(dfn->code, 79, 0x0, (int)&rmesa->vb.notify);
+      break;
+   }
+   default: {
+
+      DFN ( _x86_Vertex3f, rmesa->vb.dfn_cache.Vertex3f );
+      FIXUP(dfn->code, 3, 0x0, (int)&rmesa->vb.vertex[3]);
+      FIXUP(dfn->code, 9, 0x0, (int)&rmesa->vb.dmaptr);
+      FIXUP(dfn->code, 37, 0x0, rmesa->vb.vertex_size-3);
+      FIXUP(dfn->code, 44, 0x0, (int)&rmesa->vb.counter);
+      FIXUP(dfn->code, 50, 0x0, (int)&rmesa->vb.dmaptr);
+      FIXUP(dfn->code, 56, 0x0, (int)&rmesa->vb.counter);
+      FIXUP(dfn->code, 67, 0x0, (int)&rmesa->vb.notify);
+   break;
+   }
+   }
+
+   return dfn;
+}
+
+
+
+struct dynfn *radeon_makeX86Vertex3fv( GLcontext *ctx, int key )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+
+   if (RADEON_DEBUG & DEBUG_CODEGEN)
+      fprintf(stderr, "%s 0x%08x %d\n", __FUNCTION__, key, rmesa->vb.vertex_size );
+
+   switch (rmesa->vb.vertex_size) {
+   case 6: {
+
+      DFN ( _x86_Vertex3fv_6, rmesa->vb.dfn_cache.Vertex3fv );
+      FIXUP(dfn->code, 1, 0x00000000, (int)&rmesa->vb.dmaptr);
+      FIXUP(dfn->code, 27, 0x0000001c, (int)&rmesa->vb.vertex[3]);
+      FIXUP(dfn->code, 33, 0x00000020, (int)&rmesa->vb.vertex[4]);
+      FIXUP(dfn->code, 45, 0x00000024, (int)&rmesa->vb.vertex[5]);
+      FIXUP(dfn->code, 56, 0x00000000, (int)&rmesa->vb.dmaptr);
+      FIXUP(dfn->code, 61, 0x00000004, (int)&rmesa->vb.counter);
+      FIXUP(dfn->code, 67, 0x00000004, (int)&rmesa->vb.counter);
+      FIXUP(dfn->code, 76, 0x00000008, (int)&rmesa->vb.notify);
+      break;
+   }
+   
+
+   case 8: {
+
+      DFN ( _x86_Vertex3fv_8, rmesa->vb.dfn_cache.Vertex3fv );
+      FIXUP(dfn->code, 1, 0x00000000, (int)&rmesa->vb.dmaptr);
+      FIXUP(dfn->code, 27, 0x0000001c, (int)&rmesa->vb.vertex[3]);
+      FIXUP(dfn->code, 33, 0x00000020, (int)&rmesa->vb.vertex[4]);
+      FIXUP(dfn->code, 45, 0x0000001c, (int)&rmesa->vb.vertex[5]);
+      FIXUP(dfn->code, 51, 0x00000020, (int)&rmesa->vb.vertex[6]);
+      FIXUP(dfn->code, 63, 0x00000024, (int)&rmesa->vb.vertex[7]);
+      FIXUP(dfn->code, 74, 0x00000000, (int)&rmesa->vb.dmaptr);
+      FIXUP(dfn->code, 79, 0x00000004, (int)&rmesa->vb.counter);
+      FIXUP(dfn->code, 85, 0x00000004, (int)&rmesa->vb.counter);
+      FIXUP(dfn->code, 94, 0x00000008, (int)&rmesa->vb.notify);
+      break;
+   }
+   
+
+
+   default: {
+
+      DFN ( _x86_Vertex3fv, rmesa->vb.dfn_cache.Vertex3fv );
+      FIXUP(dfn->code, 8, 0x01010101, (int)&rmesa->vb.dmaptr);
+      FIXUP(dfn->code, 32, 0x00000006, rmesa->vb.vertex_size-3);
+      FIXUP(dfn->code, 37, 0x00000058, (int)&rmesa->vb.vertex[3]);
+      FIXUP(dfn->code, 45, 0x01010101, (int)&rmesa->vb.dmaptr);
+      FIXUP(dfn->code, 50, 0x02020202, (int)&rmesa->vb.counter);
+      FIXUP(dfn->code, 58, 0x02020202, (int)&rmesa->vb.counter);
+      FIXUP(dfn->code, 67, 0x0, (int)&rmesa->vb.notify);
+   break;
+   }
+   }
+
+   return dfn;
+}
+
+static struct dynfn *
+radeon_makeX86Attribute2fv( struct dynfn * cache, int key,
+                           const char * name, void * dest )
+{
+   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+
+   if (RADEON_DEBUG & DEBUG_CODEGEN)
+      fprintf(stderr, "%s 0x%08x\n", name, key );
+
+   DFN ( _x86_Attribute2fv, (*cache) );
+   FIXUP(dfn->code, 11, 0x0, (int)dest); 
+   FIXUP(dfn->code, 16, 0x4, 4+(int)dest); 
+
+   return dfn;
+}
+
+static struct dynfn *
+radeon_makeX86Attribute2f( struct dynfn * cache, int key,
+                          const char * name, void * dest )
+{
+   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+
+   if (RADEON_DEBUG & DEBUG_CODEGEN)
+      fprintf(stderr, "%s 0x%08x\n", name, key );
+
+   DFN ( _x86_Attribute2f, (*cache) );
+   FIXUP(dfn->code, 1, 0x0, (int)dest); 
+
+   return dfn;
+}
+
+
+static struct dynfn *
+radeon_makeX86Attribute3fv( struct dynfn * cache, int key,
+                           const char * name, void * dest )
+{
+   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+
+   if (RADEON_DEBUG & DEBUG_CODEGEN)
+      fprintf(stderr, "%s 0x%08x\n", name, key );
+
+   DFN ( _x86_Attribute3fv, (*cache) );
+   FIXUP(dfn->code, 14, 0x0, (int)dest); 
+   FIXUP(dfn->code, 20, 0x4, 4+(int)dest); 
+   FIXUP(dfn->code, 25, 0x8, 8+(int)dest);
+
+   return dfn;
+}
+
+static struct dynfn *
+radeon_makeX86Attribute3f( struct dynfn * cache, int key,
+                        const char * name, void * dest )
+{
+   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+
+   if (RADEON_DEBUG & DEBUG_CODEGEN)
+      fprintf(stderr, "%s 0x%08x\n", name, key );
+
+   DFN ( _x86_Attribute3f, (*cache) );
+   FIXUP(dfn->code, 14, 0x0, (int)dest); 
+   FIXUP(dfn->code, 20, 0x4, 4+(int)dest); 
+   FIXUP(dfn->code, 25, 0x8, 8+(int)dest);
+
+   return dfn;
+}
+
+struct dynfn *radeon_makeX86Normal3fv( GLcontext *ctx, int key )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   return radeon_makeX86Attribute3fv( & rmesa->vb.dfn_cache.Normal3fv, key,
+                                     __FUNCTION__, rmesa->vb.normalptr );
+}
+
+struct dynfn *radeon_makeX86Normal3f( GLcontext *ctx, int key )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   return radeon_makeX86Attribute3f( & rmesa->vb.dfn_cache.Normal3f, key,
+                                    __FUNCTION__, rmesa->vb.normalptr );
+}
+
+struct dynfn *radeon_makeX86Color4ubv( GLcontext *ctx, int key )
+{
+   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+
+   if (RADEON_DEBUG & DEBUG_CODEGEN)
+      fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
+
+   if (key & RADEON_CP_VC_FRMT_PKCOLOR) {
+      DFN ( _x86_Color4ubv_ub, rmesa->vb.dfn_cache.Color4ubv);
+      FIXUP(dfn->code, 5, 0x12345678, (int)rmesa->vb.colorptr); 
+      return dfn;
+   } 
+   else {
+
+      DFN ( _x86_Color4ubv_4f, rmesa->vb.dfn_cache.Color4ubv);
+      FIXUP(dfn->code, 2, 0x00000000, (int)_mesa_ubyte_to_float_color_tab); 
+      FIXUP(dfn->code, 27, 0xdeadbeaf, (int)rmesa->vb.floatcolorptr); 
+      FIXUP(dfn->code, 33, 0xdeadbeaf, (int)rmesa->vb.floatcolorptr+4); 
+      FIXUP(dfn->code, 55, 0xdeadbeaf, (int)rmesa->vb.floatcolorptr+8); 
+      FIXUP(dfn->code, 61, 0xdeadbeaf, (int)rmesa->vb.floatcolorptr+12); 
+      return dfn;
+   }
+}
+
+struct dynfn *radeon_makeX86Color4ub( GLcontext *ctx, int key )
+{
+   if (RADEON_DEBUG & DEBUG_CODEGEN)
+      fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
+
+   if (key & RADEON_CP_VC_FRMT_PKCOLOR) {
+      struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+      radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+      DFN ( _x86_Color4ub_ub, rmesa->vb.dfn_cache.Color4ub );
+      FIXUP(dfn->code, 18, 0x0, (int)rmesa->vb.colorptr); 
+      FIXUP(dfn->code, 24, 0x0, (int)rmesa->vb.colorptr+1); 
+      FIXUP(dfn->code, 30, 0x0, (int)rmesa->vb.colorptr+2); 
+      FIXUP(dfn->code, 36, 0x0, (int)rmesa->vb.colorptr+3); 
+      return dfn;
+   }
+   else
+      return 0;
+}
+
+
+struct dynfn *radeon_makeX86Color3fv( GLcontext *ctx, int key )
+{
+   if (key & (RADEON_CP_VC_FRMT_PKCOLOR|RADEON_CP_VC_FRMT_FPALPHA))
+      return 0;
+   else
+   {
+      radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+      return radeon_makeX86Attribute3fv( & rmesa->vb.dfn_cache.Color3fv, key,
+                                        __FUNCTION__, rmesa->vb.floatcolorptr );
+   }
+}
+
+struct dynfn *radeon_makeX86Color3f( GLcontext *ctx, int key )
+{
+   if (key & (RADEON_CP_VC_FRMT_PKCOLOR|RADEON_CP_VC_FRMT_FPALPHA))
+      return 0;
+   else
+   {
+      radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+      return radeon_makeX86Attribute3f( & rmesa->vb.dfn_cache.Color3f, key,
+                                       __FUNCTION__, rmesa->vb.floatcolorptr );
+   }
+}
+
+
+
+struct dynfn *radeon_makeX86TexCoord2fv( GLcontext *ctx, int key )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   return radeon_makeX86Attribute2fv( & rmesa->vb.dfn_cache.TexCoord2fv, key,
+                                     __FUNCTION__, rmesa->vb.texcoordptr[0] );
+}
+
+struct dynfn *radeon_makeX86TexCoord2f( GLcontext *ctx, int key )
+{
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   return radeon_makeX86Attribute2f( & rmesa->vb.dfn_cache.TexCoord2f, key,
+                                    __FUNCTION__, rmesa->vb.texcoordptr[0] );
+}
+
+struct dynfn *radeon_makeX86MultiTexCoord2fvARB( GLcontext *ctx, int key )
+{
+   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   if (RADEON_DEBUG & DEBUG_CODEGEN)
+      fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
+
+   if ((key & (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) ==
+      (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) {
+      DFN ( _x86_MultiTexCoord2fv, rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
+      FIXUP(dfn->code, 21, 0xdeadbeef, (int)rmesa->vb.texcoordptr[0]);
+      FIXUP(dfn->code, 27, 0xdeadbeef, (int)rmesa->vb.texcoordptr[0]+4);
+   } else {
+      DFN ( _x86_MultiTexCoord2fv_2, rmesa->vb.dfn_cache.MultiTexCoord2fvARB );
+      FIXUP(dfn->code, 14, 0x0, (int)rmesa->vb.texcoordptr);
+   }
+   return dfn;
+}
+
+struct dynfn *radeon_makeX86MultiTexCoord2fARB( GLcontext *ctx, 
+                                               int key )
+{
+   struct dynfn *dfn = MALLOC_STRUCT( dynfn );
+   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+
+   if (RADEON_DEBUG & DEBUG_CODEGEN)
+      fprintf(stderr, "%s 0x%08x\n", __FUNCTION__, key );
+
+   if ((key & (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) ==
+       (RADEON_CP_VC_FRMT_ST0|RADEON_CP_VC_FRMT_ST1)) {
+      DFN ( _x86_MultiTexCoord2f, rmesa->vb.dfn_cache.MultiTexCoord2fARB );
+      FIXUP(dfn->code, 20, 0xdeadbeef, (int)rmesa->vb.texcoordptr[0]);
+      FIXUP(dfn->code, 26, 0xdeadbeef, (int)rmesa->vb.texcoordptr[0]+4); 
+   }
+   else {
+      /* Note: this might get generated multiple times, even though the
+       * actual emitted code is the same.
+       */
+      DFN ( _x86_MultiTexCoord2f_2, rmesa->vb.dfn_cache.MultiTexCoord2fARB );
+      FIXUP(dfn->code, 18, 0x0, (int)rmesa->vb.texcoordptr); 
+   }      
+   return dfn;
+}
+
+
+void radeonInitX86Codegen( struct dfn_generators *gen )
+{
+   gen->Vertex3f = radeon_makeX86Vertex3f;
+   gen->Vertex3fv = radeon_makeX86Vertex3fv;
+   gen->Color4ub = radeon_makeX86Color4ub; /* PKCOLOR only */
+   gen->Color4ubv = radeon_makeX86Color4ubv; /* PKCOLOR only */
+   gen->Normal3f = radeon_makeX86Normal3f;
+   gen->Normal3fv = radeon_makeX86Normal3fv;
+   gen->TexCoord2f = radeon_makeX86TexCoord2f;
+   gen->TexCoord2fv = radeon_makeX86TexCoord2fv;
+   gen->MultiTexCoord2fARB = radeon_makeX86MultiTexCoord2fARB;
+   gen->MultiTexCoord2fvARB = radeon_makeX86MultiTexCoord2fvARB;
+   gen->Color3f = radeon_makeX86Color3f;
+   gen->Color3fv = radeon_makeX86Color3fv;
+
+   /* Not done:
+    */
+/*     gen->Vertex2f = radeon_makeX86Vertex2f; */
+/*     gen->Vertex2fv = radeon_makeX86Vertex2fv; */
+/*     gen->Color3ub = radeon_makeX86Color3ub; */
+/*     gen->Color3ubv = radeon_makeX86Color3ubv; */
+/*     gen->Color4f = radeon_makeX86Color4f; */
+/*     gen->Color4fv = radeon_makeX86Color4fv; */
+/*     gen->TexCoord1f = radeon_makeX86TexCoord1f; */
+/*     gen->TexCoord1fv = radeon_makeX86TexCoord1fv; */
+/*     gen->MultiTexCoord1fARB = radeon_makeX86MultiTexCoord1fARB; */
+/*     gen->MultiTexCoord1fvARB = radeon_makeX86MultiTexCoord1fvARB; */
+}
+
+
+#else 
+
+void radeonInitX86Codegen( struct dfn_generators *gen )
+{
+   (void) gen;
+}
+
+#endif
index c26ccd3cc2d12bdc6267ed6889a526d1c57fdaee..0792b5c2e0e8ce815d63daba6591e9ae9f02c191 100644 (file)
@@ -1,19 +1,5 @@
-/**
- * \file server/radeon_common.h 
- * \brief Common header definitions for Radeon 2D/3D/DRM driver suite.
+/* radeon_common.h -- common header definitions for Radeon 2D/3D/DRM suite
  *
- * \note Some of these structures are meant for backward compatibility and
- * aren't used by the subset driver.
- *
- * \author Gareth Hughes <gareth@valinux.com>
- * \author Kevin E. Martin <martin@valinux.com>
- * \author Keith Whitwell <keith@tungstengraphics.com>
- * 
- * \author Converted to common header format by
- * Jens Owen <jens@tungstengraphics.com>
- */
-
-/*
  * Copyright 2000 VA Linux Systems, Inc., Fremont, California.
  * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas.
  * All Rights Reserved.
  * 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.
+ *
+ * Author:
+ *   Gareth Hughes <gareth@valinux.com>
+ *   Kevin E. Martin <martin@valinux.com>
+ *   Keith Whitwell <keith@tungstengraphics.com>
+ *
+ * Converted to common header format:
+ *   Jens Owen <jens@tungstengraphics.com>
+ *
+ * $XFree86: xc/programs/Xserver/hw/xfree86/os-support/xf86drmRadeon.h,v 1.6 2001/04/16 15:02:13 tsi Exp $
+ *
  */
 
-/* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/xf86drmRadeon.h,v 1.6 2001/04/16 15:02:13 tsi Exp $ */
-
 #ifndef _RADEON_COMMON_H_
 #define _RADEON_COMMON_H_
 
 #define RADEON_CLEAR_DEPTH     4
 
 
-/**
- * \brief DRM_RADEON_CP_INIT ioctl argument type.
- */
 typedef struct {
    enum {
-      DRM_RADEON_INIT_CP    = 0x01,   /**< \brief initialize CP */
-      DRM_RADEON_CLEANUP_CP = 0x02,   /**< \brief clean up CP */
-      DRM_RADEON_INIT_R200_CP = 0x03  /**< \brief initialize R200 CP */
-   } func;                            /**< \brief request */
-   unsigned long sarea_priv_offset;   /**< \brief SAREA private offset */
-   int is_pci;                        /**< \brief is current card a PCI card? */
-   int cp_mode;                       /**< \brief CP mode */
-   int agp_size;                      /**< \brief AGP space size */
-   int ring_size;                     /**< \brief CP ring buffer size */
-   int usec_timeout;                  /**< \brief timeout for DRM operations in usecs */
-
-   unsigned int fb_bpp;               
-   unsigned int front_offset;         /**< \brief front color buffer offset */
-   unsigned int front_pitch;          /**< \brief front color buffer pitch */
-   unsigned int back_offset;          /**< \brief back color buffer offset */
-   unsigned int back_pitch;           /**< \brief back color buffer pitch*/
-   unsigned int depth_bpp;            /**< \brief depth buffer bits-per-pixel */
-   unsigned int depth_offset;         /**< \brief depth buffer offset */
-   unsigned int depth_pitch;          /**< \brief depth buffer pitch */
-
-   unsigned long fb_offset;           /**< \brief framebuffer offset */
-   unsigned long mmio_offset;         /**< \brief MMIO register offset */
-   unsigned long ring_offset;         /**< \brief CP ring buffer offset */
-   unsigned long ring_rptr_offset;    /**< \brief CP ring buffer read pointer offset */
-   unsigned long buffers_offset;      /**< \brief vertex buffers offset */
-   unsigned long agp_textures_offset; /**< \brief AGP textures offset */
+      DRM_RADEON_INIT_CP    = 0x01,
+      DRM_RADEON_CLEANUP_CP = 0x02,
+      DRM_RADEON_INIT_R200_CP = 0x03
+   } func;
+   unsigned long sarea_priv_offset;
+   int is_pci;
+   int cp_mode;
+   int agp_size;
+   int ring_size;
+   int usec_timeout;
+
+   unsigned int fb_bpp;
+   unsigned int front_offset, front_pitch;
+   unsigned int back_offset, back_pitch;
+   unsigned int depth_bpp;
+   unsigned int depth_offset, depth_pitch;
+
+   unsigned long fb_offset;
+   unsigned long mmio_offset;
+   unsigned long ring_offset;
+   unsigned long ring_rptr_offset;
+   unsigned long buffers_offset;
+   unsigned long agp_textures_offset;
 } drmRadeonInit;
 
-/**
- * \brief DRM_RADEON_CP_STOP ioctl argument type.
- */
 typedef struct {
    int flush;
    int idle;
@@ -143,17 +129,13 @@ typedef union drmRadeonClearR {
         unsigned int ui[5];
 } drmRadeonClearRect;
 
-/**
- * \brief DRM_RADEON_CLEAR ioctl argument type.
- */
 typedef struct drmRadeonClearT {
-        unsigned int flags;              /**< \brief bitmask of the planes to clear */
-        unsigned int clear_color;        /**< \brief color buffer clear value */
-        unsigned int clear_depth;        /**< \brief depth buffer clear value */
-        unsigned int color_mask;         /**< \brief color buffer clear mask */
-        unsigned int depth_mask;         /**< \brief stencil buffer clear value
-                                          *  \todo Misnamed field. */
-        drmRadeonClearRect *depth_boxes; /**< \brief depth buffer cliprects */
+        unsigned int flags;
+        unsigned int clear_color;
+        unsigned int clear_depth;
+        unsigned int color_mask;
+        unsigned int depth_mask;   /* misnamed field:  should be stencil */
+        drmRadeonClearRect *depth_boxes;
 } drmRadeonClearType;
 
 typedef struct drmRadeonFullscreenT {
@@ -163,16 +145,10 @@ typedef struct drmRadeonFullscreenT {
         } func;
 } drmRadeonFullscreenType;
 
-/**
- * \brief DRM_RADEON_STIPPLE ioctl argument type.
- */
 typedef struct {
         unsigned int *mask;
 } drmRadeonStipple;
 
-/**
- * \brief Texture image for drmRadeonTexture.
- */
 typedef struct {
         unsigned int x;
         unsigned int y;
@@ -181,22 +157,18 @@ typedef struct {
         const void *data;
 } drmRadeonTexImage;
 
-/**
- * \brief DRM_RADEON_TEXTURE ioctl argument type.
- */
 typedef struct {
-        int offset;               /**< \brief texture offset */
-        int pitch;                /**< \brief texture pitch */
-        int format;               /**< \brief pixel format */
-        int width;                /**< \brief texture width */
-        int height;               /**< \brief texture height */
-       drmRadeonTexImage *image; /**< \brief image */
+        int offset;
+        int pitch;
+        int format;
+        int width;                      /* Texture image coordinates */
+        int height;
+        drmRadeonTexImage *image;
 } drmRadeonTexture;
 
 
 #define RADEON_MAX_TEXTURE_UNITS 3
 
-
 /* Layout matches drm_radeon_state_t in linux drm_radeon.h.  
  */
 typedef struct {
@@ -266,16 +238,13 @@ typedef struct {
        unsigned int dirty;
 } drmRadeonState;
 
-/**
- * \brief DRM 1.1 vertex ioctl.
- *
- * Used in compatibility modes.
+/* 1.1 vertex ioctl.  Used in compatibility modes.
  */
 typedef struct {
-       int prim;                       /**< \brief Primitive number */
-       int idx;                        /**< \brief Index of vertex buffer */
-       int count;                      /**< \brief Number of vertices in buffer */
-       int discard;                    /**< \brief Client finished with buffer? */
+       int prim;
+       int idx;                        /* Index of vertex buffer */
+       int count;                      /* Number of vertices in buffer */
+       int discard;                    /* Client finished with buffer? */
 } drmRadeonVertex;
 
 typedef struct {
@@ -283,13 +252,13 @@ typedef struct {
        unsigned int finish;
        unsigned int prim:8;
        unsigned int stateidx:8;
-       unsigned int numverts:16;       /**< overloaded as offset/64 for elt prims */
+       unsigned int numverts:16; /* overloaded as offset/64 for elt prims */
         unsigned int vc_format;
 } drmRadeonPrim;
 
 typedef struct {
-        int idx;                        /**< \brief Index of vertex buffer */
-        int discard;                    /**< \brief Client finished with buffer? */
+        int idx;                        /* Index of vertex buffer */
+        int discard;                    /* Client finished with buffer? */
         int nr_states;
         drmRadeonState *state;
         int nr_prims;
@@ -299,156 +268,127 @@ typedef struct {
 #define RADEON_MAX_STATES 16
 #define RADEON_MAX_PRIMS  64
 
-
-/**
- * \brief Command buffer.  
- *
- * \todo Replace with true DMA stream?
+/* Command buffer.  Replace with true dma stream?
  */
 typedef struct {
-       int bufsz;          /**< \brief buffer size */
-       char *buf;          /**< \brief buffer */
-       int nbox;           /**< \brief number of cliprects */
-        drmClipRect *boxes; /**< \brief cliprects */
+       int bufsz;
+       char *buf;
+       int nbox;
+        drmClipRect *boxes;
 } drmRadeonCmdBuffer;
 
-
-/**
- * \brief Per-packet identifiers for use with the ::RADEON_CMD_PACKET command
- * in the DRM_RADEON_CMDBUF ioctl.  
- *
- * \note Comments relate new packets to old state bits and the packet size.
+/* New style per-packet identifiers for use in cmd_buffer ioctl with
+ * the RADEON_EMIT_PACKET command.  Comments relate new packets to old
+ * state bits and the packet size:
  */
-enum drmRadeonCmdPkt {
-   RADEON_EMIT_PP_MISC                       = 0, /* context/7 */
-   RADEON_EMIT_PP_CNTL                       = 1, /* context/3 */
-   RADEON_EMIT_RB3D_COLORPITCH               = 2, /* context/1 */
-   RADEON_EMIT_RE_LINE_PATTERN               = 3, /* line/2 */
-   RADEON_EMIT_SE_LINE_WIDTH                 = 4, /* line/1 */
-   RADEON_EMIT_PP_LUM_MATRIX                 = 5, /* bumpmap/1 */
-   RADEON_EMIT_PP_ROT_MATRIX_0               = 6, /* bumpmap/2 */
-   RADEON_EMIT_RB3D_STENCILREFMASK           = 7, /* masks/3 */
-   RADEON_EMIT_SE_VPORT_XSCALE               = 8, /* viewport/6 */
-   RADEON_EMIT_SE_CNTL                       = 9, /* setup/2 */
-   RADEON_EMIT_SE_CNTL_STATUS                = 10, /* setup/1 */
-   RADEON_EMIT_RE_MISC                       = 11, /* misc/1 */
-   RADEON_EMIT_PP_TXFILTER_0                 = 12, /* tex0/6 */
-   RADEON_EMIT_PP_BORDER_COLOR_0             = 13, /* tex0/1 */
-   RADEON_EMIT_PP_TXFILTER_1                 = 14, /* tex1/6 */
-   RADEON_EMIT_PP_BORDER_COLOR_1             = 15, /* tex1/1 */
-   RADEON_EMIT_PP_TXFILTER_2                 = 16, /* tex2/6 */
-   RADEON_EMIT_PP_BORDER_COLOR_2             = 17, /* tex2/1 */
-   RADEON_EMIT_SE_ZBIAS_FACTOR               = 18, /* zbias/2 */
-   RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT         = 19, /* tcl/11 */
-   RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED = 20, /* material/17 */
-   R200_EMIT_PP_TXCBLEND_0                   = 21, /* tex0/4 */
-   R200_EMIT_PP_TXCBLEND_1                   = 22, /* tex1/4 */
-   R200_EMIT_PP_TXCBLEND_2                   = 23, /* tex2/4 */
-   R200_EMIT_PP_TXCBLEND_3                   = 24, /* tex3/4 */
-   R200_EMIT_PP_TXCBLEND_4                   = 25, /* tex4/4 */
-   R200_EMIT_PP_TXCBLEND_5                   = 26, /* tex5/4 */
-   R200_EMIT_PP_TXCBLEND_6                   = 27, /* /4 */
-   R200_EMIT_PP_TXCBLEND_7                   = 28, /* /4 */
-   R200_EMIT_TCL_LIGHT_MODEL_CTL_0           = 29, /* tcl/6 */
-   R200_EMIT_TFACTOR_0                       = 30, /* tf/6 */
-   R200_EMIT_VTX_FMT_0                       = 31, /* vtx/4 */
-   R200_EMIT_VAP_CTL                         = 32, /* vap/1 */
-   R200_EMIT_MATRIX_SELECT_0                 = 33, /* msl/5 */
-   R200_EMIT_TEX_PROC_CTL_2                  = 34, /* tcg/5 */
-   R200_EMIT_TCL_UCP_VERT_BLEND_CTL          = 35, /* tcl/1 */
-   R200_EMIT_PP_TXFILTER_0                   = 36, /* tex0/6 */
-   R200_EMIT_PP_TXFILTER_1                   = 37, /* tex1/6 */
-   R200_EMIT_PP_TXFILTER_2                   = 38, /* tex2/6 */
-   R200_EMIT_PP_TXFILTER_3                   = 39, /* tex3/6 */
-   R200_EMIT_PP_TXFILTER_4                   = 40, /* tex4/6 */
-   R200_EMIT_PP_TXFILTER_5                   = 41, /* tex5/6 */
-   R200_EMIT_PP_TXOFFSET_0                   = 42, /* tex0/1 */
-   R200_EMIT_PP_TXOFFSET_1                   = 43, /* tex1/1 */
-   R200_EMIT_PP_TXOFFSET_2                   = 44, /* tex2/1 */
-   R200_EMIT_PP_TXOFFSET_3                   = 45, /* tex3/1 */
-   R200_EMIT_PP_TXOFFSET_4                   = 46, /* tex4/1 */
-   R200_EMIT_PP_TXOFFSET_5                   = 47, /* tex5/1 */
-   R200_EMIT_VTE_CNTL                        = 48, /* vte/1 */
-   R200_EMIT_OUTPUT_VTX_COMP_SEL             = 49, /* vtx/1 */
-   R200_EMIT_PP_TAM_DEBUG3                   = 50, /* tam/1 */
-   R200_EMIT_PP_CNTL_X                       = 51, /* cst/1 */
-   R200_EMIT_RB3D_DEPTHXY_OFFSET             = 52, /* cst/1 */
-   R200_EMIT_RE_AUX_SCISSOR_CNTL             = 53, /* cst/1 */
-   R200_EMIT_RE_SCISSOR_TL_0                 = 54, /* cst/2 */
-   R200_EMIT_RE_SCISSOR_TL_1                 = 55, /* cst/2 */
-   R200_EMIT_RE_SCISSOR_TL_2                 = 56, /* cst/2 */
-   R200_EMIT_SE_VAP_CNTL_STATUS              = 57, /* cst/1 */
-   R200_EMIT_SE_VTX_STATE_CNTL               = 58, /* cst/1 */
-   R200_EMIT_RE_POINTSIZE                    = 59, /* cst/1 */
-   R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0     = 60, /* cst/4 */
-   R200_EMIT_PP_CUBIC_FACES_0                = 61,
-   R200_EMIT_PP_CUBIC_OFFSETS_0              = 62,
-   R200_EMIT_PP_CUBIC_FACES_1                = 63,
-   R200_EMIT_PP_CUBIC_OFFSETS_1              = 64,
-   R200_EMIT_PP_CUBIC_FACES_2                = 65,
-   R200_EMIT_PP_CUBIC_OFFSETS_2              = 66,
-   R200_EMIT_PP_CUBIC_FACES_3                = 67,
-   R200_EMIT_PP_CUBIC_OFFSETS_3              = 68,
-   R200_EMIT_PP_CUBIC_FACES_4                = 69,
-   R200_EMIT_PP_CUBIC_OFFSETS_4              = 70,
-   R200_EMIT_PP_CUBIC_FACES_5                = 71,
-   R200_EMIT_PP_CUBIC_OFFSETS_5              = 72,
-   RADEON_MAX_STATE_PACKETS                  = 73
-} ;
-
-
-/**
- * \brief Command types understood by the DRM_RADEON_CMDBUF ioctl.  
- * 
- * More can be added but obviously these can't be removed or changed.
- *
- * \sa drmRadeonCmdHeader.
- */
-enum drmRadeonCmdType {
-   RADEON_CMD_PACKET       = 1, /**< \brief emit one of the ::drmRadeonCmdPkt register packets */
-   RADEON_CMD_SCALARS      = 2, /**< \brief emit scalar data */
-   RADEON_CMD_VECTORS      = 3, /**< \brief emit vector data */
-   RADEON_CMD_DMA_DISCARD  = 4, /**< \brief discard current DMA buffer */
-   RADEON_CMD_PACKET3      = 5, /**< \brief emit hardware packet */
-   RADEON_CMD_PACKET3_CLIP = 6, /**< \brief emit hardware packet wrapped in cliprects */
-   RADEON_CMD_SCALARS2     = 7, /**< \brief R200 stopgap */
-   RADEON_CMD_WAIT         = 8  /**< \brief synchronization */
-} ;
-
-/**
- * \brief Command packet headers understood by the DRM_RADEON_CMDBUF ioctl.
- *
- * \sa drmRadeonCmdType.
+#define RADEON_EMIT_PP_MISC                         0 /* context/7 */
+#define RADEON_EMIT_PP_CNTL                         1 /* context/3 */
+#define RADEON_EMIT_RB3D_COLORPITCH                 2 /* context/1 */
+#define RADEON_EMIT_RE_LINE_PATTERN                 3 /* line/2 */
+#define RADEON_EMIT_SE_LINE_WIDTH                   4 /* line/1 */
+#define RADEON_EMIT_PP_LUM_MATRIX                   5 /* bumpmap/1 */
+#define RADEON_EMIT_PP_ROT_MATRIX_0                 6 /* bumpmap/2 */
+#define RADEON_EMIT_RB3D_STENCILREFMASK             7 /* masks/3 */
+#define RADEON_EMIT_SE_VPORT_XSCALE                 8 /* viewport/6 */
+#define RADEON_EMIT_SE_CNTL                         9 /* setup/2 */
+#define RADEON_EMIT_SE_CNTL_STATUS                  10 /* setup/1 */
+#define RADEON_EMIT_RE_MISC                         11 /* misc/1 */
+#define RADEON_EMIT_PP_TXFILTER_0                   12 /* tex0/6 */
+#define RADEON_EMIT_PP_BORDER_COLOR_0               13 /* tex0/1 */
+#define RADEON_EMIT_PP_TXFILTER_1                   14 /* tex1/6 */
+#define RADEON_EMIT_PP_BORDER_COLOR_1               15 /* tex1/1 */
+#define RADEON_EMIT_PP_TXFILTER_2                   16 /* tex2/6 */
+#define RADEON_EMIT_PP_BORDER_COLOR_2               17 /* tex2/1 */
+#define RADEON_EMIT_SE_ZBIAS_FACTOR                 18 /* zbias/2 */
+#define RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT           19 /* tcl/11 */
+#define RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED   20 /* material/17 */
+#define R200_EMIT_PP_TXCBLEND_0                     21 /* tex0/4 */
+#define R200_EMIT_PP_TXCBLEND_1                     22 /* tex1/4 */
+#define R200_EMIT_PP_TXCBLEND_2                     23 /* tex2/4 */
+#define R200_EMIT_PP_TXCBLEND_3                     24 /* tex3/4 */
+#define R200_EMIT_PP_TXCBLEND_4                     25 /* tex4/4 */
+#define R200_EMIT_PP_TXCBLEND_5                     26 /* tex5/4 */
+#define R200_EMIT_PP_TXCBLEND_6                     27 /* /4 */
+#define R200_EMIT_PP_TXCBLEND_7                     28 /* /4 */
+#define R200_EMIT_TCL_LIGHT_MODEL_CTL_0             29 /* tcl/6 */
+#define R200_EMIT_TFACTOR_0                         30 /* tf/6 */
+#define R200_EMIT_VTX_FMT_0                         31 /* vtx/4 */
+#define R200_EMIT_VAP_CTL                           32 /* vap/1 */
+#define R200_EMIT_MATRIX_SELECT_0                   33 /* msl/5 */
+#define R200_EMIT_TEX_PROC_CTL_2                    34 /* tcg/5 */
+#define R200_EMIT_TCL_UCP_VERT_BLEND_CTL            35 /* tcl/1 */
+#define R200_EMIT_PP_TXFILTER_0                     36 /* tex0/6 */
+#define R200_EMIT_PP_TXFILTER_1                     37 /* tex1/6 */
+#define R200_EMIT_PP_TXFILTER_2                     38 /* tex2/6 */
+#define R200_EMIT_PP_TXFILTER_3                     39 /* tex3/6 */
+#define R200_EMIT_PP_TXFILTER_4                     40 /* tex4/6 */
+#define R200_EMIT_PP_TXFILTER_5                     41 /* tex5/6 */
+#define R200_EMIT_PP_TXOFFSET_0                     42 /* tex0/1 */
+#define R200_EMIT_PP_TXOFFSET_1                     43 /* tex1/1 */
+#define R200_EMIT_PP_TXOFFSET_2                     44 /* tex2/1 */
+#define R200_EMIT_PP_TXOFFSET_3                     45 /* tex3/1 */
+#define R200_EMIT_PP_TXOFFSET_4                     46 /* tex4/1 */
+#define R200_EMIT_PP_TXOFFSET_5                     47 /* tex5/1 */
+#define R200_EMIT_VTE_CNTL                          48 /* vte/1 */
+#define R200_EMIT_OUTPUT_VTX_COMP_SEL               49 /* vtx/1 */
+#define R200_EMIT_PP_TAM_DEBUG3                     50 /* tam/1 */
+#define R200_EMIT_PP_CNTL_X                         51 /* cst/1 */
+#define R200_EMIT_RB3D_DEPTHXY_OFFSET               52 /* cst/1 */
+#define R200_EMIT_RE_AUX_SCISSOR_CNTL               53 /* cst/1 */
+#define R200_EMIT_RE_SCISSOR_TL_0                   54 /* cst/2 */
+#define R200_EMIT_RE_SCISSOR_TL_1                   55 /* cst/2 */
+#define R200_EMIT_RE_SCISSOR_TL_2                   56 /* cst/2 */
+#define R200_EMIT_SE_VAP_CNTL_STATUS                57 /* cst/1 */
+#define R200_EMIT_SE_VTX_STATE_CNTL                 58 /* cst/1 */
+#define R200_EMIT_RE_POINTSIZE                      59 /* cst/1 */
+#define R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0       60 /* cst/4 */
+#define R200_EMIT_PP_CUBIC_FACES_0                  61
+#define R200_EMIT_PP_CUBIC_OFFSETS_0                62
+#define R200_EMIT_PP_CUBIC_FACES_1                  63
+#define R200_EMIT_PP_CUBIC_OFFSETS_1                64
+#define R200_EMIT_PP_CUBIC_FACES_2                  65
+#define R200_EMIT_PP_CUBIC_OFFSETS_2                66
+#define R200_EMIT_PP_CUBIC_FACES_3                  67
+#define R200_EMIT_PP_CUBIC_OFFSETS_3                68
+#define R200_EMIT_PP_CUBIC_FACES_4                  69
+#define R200_EMIT_PP_CUBIC_OFFSETS_4                70
+#define R200_EMIT_PP_CUBIC_FACES_5                  71
+#define R200_EMIT_PP_CUBIC_OFFSETS_5                72
+#define RADEON_EMIT_PP_TEX_SIZE_0                   73
+#define RADEON_EMIT_PP_TEX_SIZE_1                   74
+#define RADEON_EMIT_PP_TEX_SIZE_2                   75
+#define RADEON_MAX_STATE_PACKETS                    76
+
+
+/* Commands understood by cmd_buffer ioctl.  More can be added but
+ * obviously these can't be removed or changed:
  */
+#define RADEON_CMD_PACKET      1 /* emit one of the register packets above */
+#define RADEON_CMD_SCALARS     2 /* emit scalar data */
+#define RADEON_CMD_VECTORS     3 /* emit vector data */
+#define RADEON_CMD_DMA_DISCARD 4 /* discard current dma buf */
+#define RADEON_CMD_PACKET3     5 /* emit hw packet */
+#define RADEON_CMD_PACKET3_CLIP 6 /* emit hw packet wrapped in cliprects */
+#define RADEON_CMD_SCALARS2     7 /* R200 stopgap */
+#define RADEON_CMD_WAIT         8 /* synchronization */
+
 typedef union {
-       /** \brief integer equivalent */
        int i;
-
        struct { 
           unsigned char cmd_type, pad0, pad1, pad2;
        } header;
-
-       /** \brief emit a register packet */
        struct { 
           unsigned char cmd_type, packet_id, pad0, pad1;
        } packet;
-       
-       /** \brief scalar data */
        struct { 
           unsigned char cmd_type, offset, stride, count; 
        } scalars;
-       
-       /** \brief vector data */
        struct { 
           unsigned char cmd_type, offset, stride, count; 
        } vectors;
-       
-       /** \brief discard current DMA buffer */
        struct { 
           unsigned char cmd_type, buf_idx, pad0, pad1; 
        } dma;
-       
-       /** \brief synchronization */
        struct { 
           unsigned char cmd_type, flags, pad0, pad1; 
        } wait;
@@ -458,12 +398,10 @@ typedef union {
 #define RADEON_WAIT_2D  0x1
 #define RADEON_WAIT_3D  0x2
 
-/**
- * \brief DRM_RADEON_GETPARAM ioctl argument type.
- */
+
 typedef struct drm_radeon_getparam {
-       int param;  /**< \brief parameter number */
-       int *value; /**< \brief parameter value */
+       int param;
+       void *value;
 } drmRadeonGetParam;
 
 #define RADEON_PARAM_AGP_BUFFER_OFFSET 1
@@ -472,10 +410,6 @@ typedef struct drm_radeon_getparam {
 #define RADEON_PARAM_LAST_CLEAR        4
 #define RADEON_PARAM_IRQ_NR            5
 #define RADEON_PARAM_AGP_BASE          6
-#define RADEON_PARAM_REGISTER_HANDLE   7 
-#define RADEON_PARAM_STATUS_HANDLE     8
-#define RADEON_PARAM_SAREA_HANDLE      9
-#define RADEON_PARAM_AGP_TEX_HANDLE    10
 
 
 #define RADEON_MEM_REGION_AGP 1
@@ -493,29 +427,18 @@ typedef struct drm_radeon_mem_free {
        int region_offset;
 } drmRadeonMemFree;
 
-/**
- * \brief DRM_RADEON_INIT_HEAP argument type.
- */
 typedef struct drm_radeon_mem_init_heap {
-       int region; /**< \brief region type */
-       int size;   /**< \brief region size */
-       int start;  /**< \brief region start offset */
+       int region;
+       int size;
+       int start;      
 } drmRadeonMemInitHeap;
 
-/**
- * \brief DRM_RADEON_IRQ_EMIT ioctl argument type.
- *
- * New in DRM 1.6: userspace can request and wait on IRQ's.
+/* 1.6: Userspace can request & wait on irq's:
  */
 typedef struct drm_radeon_irq_emit {
        int *irq_seq;
 } drmRadeonIrqEmit;
 
-/**
- * \brief DRM_RADEON_IRQ_WAIT ioctl argument type.
- *
- * New in DRM 1.6: userspace can request and wait on IRQ's.
- */
 typedef struct drm_radeon_irq_wait {
        int irq_seq;
 } drmRadeonIrqWait;
index f14bd13a952fc55da45bea4d78bd64825fa2a2b6..4271aa7da23b8cb114cd3c5df445b078a50223c4 100644 (file)
@@ -12,6 +12,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
+#include <unistd.h>
 
 #include "driver.h"
 #include "drm.h"
@@ -23,9 +24,6 @@
 #include "radeon_sarea.h"
 #include "sarea.h"
 
-#include <unistd.h>
-
-
 
 /* HACK - for now, put this here... */
 /* Alpha - this may need to be a variable to handle UP1x00 vs TITAN */
@@ -735,7 +733,7 @@ static int RADEONMemoryInit( const DRIDriverContext *ctx, RADEONInfoPtr info )
  * Setups a RADEONDRIRec structure to be passed to radeon_dri.so for its
  * initialization.
  */
-static int RADEONScreenInit( DRIDriverContext *ctx, RADEONInfoPtr info )
+static int RADEONScreenInit( const DRIDriverContext *ctx, RADEONInfoPtr info )
 {
    RADEONDRIPtr   pRADEONDRI;
    int err;
index 2cd9dbe094faec1ad065255a18b4aad2488abfdb..5570a43945858e1002f931fce35f4b372670724c 100644 (file)
@@ -1,24 +1,4 @@
-/**
- * \file server/radeon_reg.h
- * \brief Registers and register definitions for the Radeon.
- * 
- * \authors Kevin E. Martin <martin@xfree86.org>
- * \authors Rickard E. Faith <faith@valinux.com>
- * \authors Alan Hourihane <alanh@fairlite.demon.co.uk>
- *
- * \par References
- *
- * - RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
- *   Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
- *   1999.
- * - RAGE 128 Software Development Manual (Technical Reference Manual P/N
- *   SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
- *
- * \note !!!! FIXME !!!! THIS FILE HAS BEEN CONVERTED FROM r128_reg.h
- * AND CONTAINS REGISTERS AND REGISTER DEFINITIONS THAT ARE NOT CORRECT
- * ON THE RADEON.  A FULL AUDIT OF THIS CODE IS NEEDED!
- */
-
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h,v 1.25 2003/02/07 18:08:59 martin Exp $ */
 /*
  * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
  *                VA Linux Systems Inc., Fremont, California.
  * DEALINGS IN THE SOFTWARE.
  */
 
-/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h,v 1.20 2002/10/12 01:38:07 martin Exp $ */
+/*
+ * Authors:
+ *   Kevin E. Martin <martin@xfree86.org>
+ *   Rickard E. Faith <faith@valinux.com>
+ *   Alan Hourihane <alanh@fairlite.demon.co.uk>
+ *
+ * References:
+ *
+ * !!!! FIXME !!!!
+ *   RAGE 128 VR/ RAGE 128 GL Register Reference Manual (Technical
+ *   Reference Manual P/N RRG-G04100-C Rev. 0.04), ATI Technologies: April
+ *   1999.
+ *
+ * !!!! FIXME !!!!
+ *   RAGE 128 Software Development Manual (Technical Reference Manual P/N
+ *   SDK-G04000 Rev. 0.01), ATI Technologies: June 1999.
+ *
+ */
+
+/* !!!! FIXME !!!!  NOTE: THIS FILE HAS BEEN CONVERTED FROM r128_reg.h
+ * AND CONTAINS REGISTERS AND REGISTER DEFINITIONS THAT ARE NOT CORRECT
+ * ON THE RADEON.  A FULL AUDIT OF THIS CODE IS NEEDED!  */
 
 #ifndef _RADEON_REG_H_
 #define _RADEON_REG_H_
 #define RADEON_CONFIG_APER_SIZE             0x0108
 #define RADEON_CONFIG_BONDS                 0x00e8
 #define RADEON_CONFIG_CNTL                  0x00e0
+#       define RADEON_CFG_ATI_REV_A11       (0   << 16)
+#       define RADEON_CFG_ATI_REV_A12       (1   << 16)
+#       define RADEON_CFG_ATI_REV_A13       (2   << 16)
+#       define RADEON_CFG_ATI_REV_ID_MASK   (0xf << 16)
 #define RADEON_CONFIG_MEMSIZE               0x00f8
 #define RADEON_CONFIG_MEMSIZE_EMBEDDED      0x0114
 #define RADEON_CONFIG_REG_1_BASE            0x010c
 #define RADEON_CRTC2_PITCH                  0x032c
 #define RADEON_CRTC_STATUS                  0x005c
 #       define RADEON_CRTC_VBLANK_SAVE      (1 <<  1)
+#       define RADEON_CRTC_VBLANK_SAVE_CLEAR  (1 <<  1)
+#define RADEON_CRTC2_STATUS                  0x03fc
+#       define RADEON_CRTC2_VBLANK_SAVE      (1 <<  1)
+#       define RADEON_CRTC2_VBLANK_SAVE_CLEAR  (1 <<  1)
 #define RADEON_CRTC_V_SYNC_STRT_WID         0x020c
 #       define RADEON_CRTC_V_SYNC_STRT        (0x7ff <<  0)
 #       define RADEON_CRTC_V_SYNC_STRT_SHIFT  0
 #define RADEON_DST_LINE_START               0x1600
 #define RADEON_DST_LINE_END                 0x1604
 #define RADEON_DST_LINE_PATCOUNT            0x1608
+#       define RADEON_BRES_CNTL_SHIFT       8
 #define RADEON_DST_OFFSET                   0x1404
 #define RADEON_DST_PITCH                    0x1408
 #define RADEON_DST_PITCH_OFFSET             0x142c
 #define RADEON_FP_GEN_CNTL                  0x0284
 #       define RADEON_FP_FPON                  (1 <<  0)
 #       define RADEON_FP_TMDS_EN               (1 <<  2)
+#       define RADEON_FP_PANEL_FORMAT          (1 <<  3)
 #       define RADEON_FP_EN_TMDS               (1 <<  7)
 #       define RADEON_FP_DETECT_SENSE          (1 <<  8)
 #       define RADEON_FP_SEL_CRTC2             (1 << 13)
 #define RADEON_GEN_INT_STATUS               0x0044
 #       define RADEON_VSYNC_INT_AK          (1 <<  2)
 #       define RADEON_VSYNC_INT             (1 <<  2)
+#       define RADEON_VSYNC2_INT_AK         (1 <<  6)
+#       define RADEON_VSYNC2_INT            (1 <<  6)
 #define RADEON_GENENB                       0x03c3 /* VGA */
 #define RADEON_GENFC_RD                     0x03ca /* VGA */
 #define RADEON_GENFC_WT                     0x03da /* VGA, 0x03ba */
 #define RADEON_MM_DATA                      0x0004
 #define RADEON_MM_INDEX                     0x0000
 #define RADEON_MPLL_CNTL                    0x000e /* PLL */
+#define RADEON_MPP_TB_CONFIG                0x01c0 /* ? */
+#define RADEON_MPP_GP_CONFIG                0x01c8 /* ? */
+
 
 #define RADEON_N_VIF_COUNT                  0x0248
 
 #       define RADEON_P2PLL_REF_DIV_MASK    0x03ff
 #       define RADEON_P2PLL_ATOMIC_UPDATE_R (1 << 15) /* same as _W */
 #       define RADEON_P2PLL_ATOMIC_UPDATE_W (1 << 15) /* same as _R */
+#       define R300_PPLL_REF_DIV_ACC_MASK   (0x3ff < 18)
+#       define R300_PPLL_REF_DIV_ACC_SHIFT  18
 #define RADEON_PALETTE_DATA                 0x00b4
 #define RADEON_PALETTE_30_DATA              0x00b8
 #define RADEON_PALETTE_INDEX                0x00b0
 #       define RADEON_LOD_BIAS_SHIFT                       8
 #       define RADEON_MAX_MIP_LEVEL_MASK                   (0x0f << 16)
 #       define RADEON_MAX_MIP_LEVEL_SHIFT                  16
+#       define RADEON_YUV_TO_RGB                           (1  << 20)
+#       define RADEON_YUV_TEMPERATURE_COOL                 (0  << 21)
+#       define RADEON_YUV_TEMPERATURE_HOT                  (1  << 21)
+#       define RADEON_YUV_TEMPERATURE_MASK                 (1  << 21)
 #       define RADEON_WRAPEN_S                             (1  << 22)
 #       define RADEON_CLAMP_S_WRAP                         (0  << 23)
 #       define RADEON_CLAMP_S_MIRROR                       (1  << 23)
 #       define RADEON_CLAMP_S_MIRROR_CLAMP_LAST            (3  << 23)
 #       define RADEON_CLAMP_S_CLAMP_BORDER                 (4  << 23)
 #       define RADEON_CLAMP_S_MIRROR_CLAMP_BORDER          (5  << 23)
+#       define RADEON_CLAMP_S_CLAMP_GL                     (6  << 23)
+#       define RADEON_CLAMP_S_MIRROR_CLAMP_GL              (7  << 23)
 #       define RADEON_CLAMP_S_MASK                         (7  << 23)
 #       define RADEON_WRAPEN_T                             (1  << 26)
 #       define RADEON_CLAMP_T_WRAP                         (0  << 27)
 #       define RADEON_CLAMP_T_MIRROR_CLAMP_LAST            (3  << 27)
 #       define RADEON_CLAMP_T_CLAMP_BORDER                 (4  << 27)
 #       define RADEON_CLAMP_T_MIRROR_CLAMP_BORDER          (5  << 27)
+#       define RADEON_CLAMP_T_CLAMP_GL                     (6  << 27)
+#       define RADEON_CLAMP_T_MIRROR_CLAMP_GL              (7  << 27)
 #       define RADEON_CLAMP_T_MASK                         (7  << 27)
 #       define RADEON_BORDER_MODE_OGL                      (0  << 31)
 #       define RADEON_BORDER_MODE_D3D                      (1  << 31)
 #       define RADEON_TXFORMAT_ARGB8888           (6  <<  0)
 #       define RADEON_TXFORMAT_RGBA8888           (7  <<  0)
 #       define RADEON_TXFORMAT_Y8                 (8  <<  0)
+#       define RADEON_TXFORMAT_VYUY422            (10 <<  0)
+#       define RADEON_TXFORMAT_YVYU422            (11 <<  0)
+#       define RADEON_TXFORMAT_DXT1               (12 <<  0)
+#       define RADEON_TXFORMAT_DXT23              (14 <<  0)
+#       define RADEON_TXFORMAT_DXT45              (15 <<  0)
 #       define RADEON_TXFORMAT_FORMAT_MASK        (31 <<  0)
 #       define RADEON_TXFORMAT_FORMAT_SHIFT       0
 #       define RADEON_TXFORMAT_APPLE_YUV_MODE     (1  <<  5)
 #       define RADEON_TXFORMAT_WIDTH_SHIFT        8
 #       define RADEON_TXFORMAT_HEIGHT_MASK        (15 << 12)
 #       define RADEON_TXFORMAT_HEIGHT_SHIFT       12
+#       define RADEON_TXFORMAT_F5_WIDTH_MASK      (15 << 16)
+#       define RADEON_TXFORMAT_F5_WIDTH_SHIFT     16
+#       define RADEON_TXFORMAT_F5_HEIGHT_MASK     (15 << 20)
+#       define RADEON_TXFORMAT_F5_HEIGHT_SHIFT    20
 #       define RADEON_TXFORMAT_ST_ROUTE_STQ0      (0  << 24)
 #       define RADEON_TXFORMAT_ST_ROUTE_MASK      (3  << 24)
 #       define RADEON_TXFORMAT_ST_ROUTE_STQ1      (1  << 24)
 #       define RADEON_TXFORMAT_CHROMA_KEY_ENABLE  (1  << 29)
 #       define RADEON_TXFORMAT_CUBIC_MAP_ENABLE   (1  << 30)
 #       define RADEON_TXFORMAT_PERSPECTIVE_ENABLE (1  << 31)
+#define RADEON_PP_CUBIC_FACES_0             0x1d24
+#define RADEON_PP_CUBIC_FACES_1             0x1d28
+#define RADEON_PP_CUBIC_FACES_2             0x1d2c
+#       define RADEON_FACE_WIDTH_1_SHIFT          0
+#       define RADEON_FACE_HEIGHT_1_SHIFT         4
+#       define RADEON_FACE_WIDTH_1_MASK           (0xf << 0)
+#       define RADEON_FACE_HEIGHT_1_MASK          (0xf << 4)
+#       define RADEON_FACE_WIDTH_2_SHIFT          8
+#       define RADEON_FACE_HEIGHT_2_SHIFT         12
+#       define RADEON_FACE_WIDTH_2_MASK           (0xf << 8)
+#       define RADEON_FACE_HEIGHT_2_MASK          (0xf << 12)
+#       define RADEON_FACE_WIDTH_3_SHIFT          16
+#       define RADEON_FACE_HEIGHT_3_SHIFT         20
+#       define RADEON_FACE_WIDTH_3_MASK           (0xf << 16)
+#       define RADEON_FACE_HEIGHT_3_MASK          (0xf << 20)
+#       define RADEON_FACE_WIDTH_4_SHIFT          24
+#       define RADEON_FACE_HEIGHT_4_SHIFT         28
+#       define RADEON_FACE_WIDTH_4_MASK           (0xf << 24)
+#       define RADEON_FACE_HEIGHT_4_MASK          (0xf << 28)
+
 #define RADEON_PP_TXOFFSET_0                0x1c5c
 #define RADEON_PP_TXOFFSET_1                0x1c74
 #define RADEON_PP_TXOFFSET_2                0x1c8c
 #       define RADEON_TXO_MICRO_TILE_OPT     (2 << 3)
 #       define RADEON_TXO_OFFSET_MASK        0xffffffe0
 #       define RADEON_TXO_OFFSET_SHIFT       5
+
+#define RADEON_PP_CUBIC_OFFSET_T0_0         0x1dd0  /* bits [31:5] */
+#define RADEON_PP_CUBIC_OFFSET_T0_1         0x1dd4
+#define RADEON_PP_CUBIC_OFFSET_T0_2         0x1dd8
+#define RADEON_PP_CUBIC_OFFSET_T0_3         0x1ddc
+#define RADEON_PP_CUBIC_OFFSET_T0_4         0x1de0
+#define RADEON_PP_CUBIC_OFFSET_T1_0         0x1e00
+#define RADEON_PP_CUBIC_OFFSET_T1_1         0x1e04
+#define RADEON_PP_CUBIC_OFFSET_T1_2         0x1e08
+#define RADEON_PP_CUBIC_OFFSET_T1_3         0x1e0c
+#define RADEON_PP_CUBIC_OFFSET_T1_4         0x1e10
+#define RADEON_PP_CUBIC_OFFSET_T2_0         0x1e14
+#define RADEON_PP_CUBIC_OFFSET_T2_1         0x1e18
+#define RADEON_PP_CUBIC_OFFSET_T2_2         0x1e1c
+#define RADEON_PP_CUBIC_OFFSET_T2_3         0x1e20
+#define RADEON_PP_CUBIC_OFFSET_T2_4         0x1e24
+
+#define RADEON_PP_TEX_SIZE_0                0x1d04  /* NPOT */
+#define RADEON_PP_TEX_SIZE_1                0x1d0c
+#define RADEON_PP_TEX_SIZE_2                0x1d14
+#       define RADEON_TEX_USIZE_MASK        (0x7ff << 0)
+#       define RADEON_TEX_USIZE_SHIFT       0
+#       define RADEON_TEX_VSIZE_MASK        (0x7ff << 16)
+#       define RADEON_TEX_VSIZE_SHIFT       16
+#       define RADEON_SIGNED_RGB_MASK       (1 << 30)
+#       define RADEON_SIGNED_RGB_SHIFT      30
+#       define RADEON_SIGNED_ALPHA_MASK     (1 << 31)
+#       define RADEON_SIGNED_ALPHA_SHIFT    31
+#define RADEON_PP_TEX_PITCH_0               0x1d08  /* NPOT */
+#define RADEON_PP_TEX_PITCH_1               0x1d10  /* NPOT */
+#define RADEON_PP_TEX_PITCH_2               0x1d18  /* NPOT */
+/* note: bits 13-5: 32 byte aligned stride of texture map */
+
 #define RADEON_PP_TXCBLEND_0                0x1c60
 #define RADEON_PP_TXCBLEND_1                0x1c78
 #define RADEON_PP_TXCBLEND_2                0x1c90
index f682bb6b6a648eed2c67aa4d60307e0faabbc91c..81e4325d7a1abe9a8938bcf232a9baea8b3cdd61 100644 (file)
@@ -296,9 +296,9 @@ typedef struct {
     /** \brief Texture regions. 
      * Last element is sentinal
      */
-    radeon_tex_region_t texList[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1];
+    drmTextureRegion texList[RADEON_NR_TEX_HEAPS][RADEON_NR_TEX_REGIONS+1];
     /** \brief last time texture was uploaded */
-    int texAge[RADEON_NR_TEX_HEAPS];
+    unsigned int texAge[RADEON_NR_TEX_HEAPS];
     /*@}*/
 
     int ctxOwner;              /**< \brief last context to upload state */
diff --git a/src/mesa/tnl_dd/imm/NOTES.imm b/src/mesa/tnl_dd/imm/NOTES.imm
new file mode 100644 (file)
index 0000000..9b2bd65
--- /dev/null
@@ -0,0 +1,112 @@
+
+NOTE:
+
+These files are incomplete.  They do not yet form a working
+implementation of hte concepts discused below.
+
+
+OVERVIEW
+
+The t_dd_imm_* files form a set of templates to produce driver -
+specific software tnl modules for a small subset of transformation and
+lighting states.
+
+The approach is quite different to the large vertex buffers of the
+src/tnl module, and is based around a cache of four recent vertices
+and a 'current' vertex which is updated directly from the Color,
+Normal, Texcoord, SecondaryColor and Fog entrypoints.
+
+The current vertex is actually a composite of the ctx->Current values
+and a partial hardware vertex maintained where the hardware values
+differ from those in ctx->Current.  For example, clamped color values
+are kept in the hardware vertex, while texcoords remain in
+ctx->Current.
+
+A crude diagram:
+
+                       +--------------+        +-------------------+
+               | ctx->Current |        | Current-HW-vertex |
+               +--------------+        +-------------------+
+                      \                          /
+                       \                        /
+                        \                      /
+                         \                    /
+                          ---------   --------
+                                  |   |      
+                                  v   v     
+       +--------+   +--------+  +--------+  +--------+ 
+       | vert-0 |   | vert-1 |  | vert-2 |  | vert-3 |                  
+       +--------+   +--------+  +--------+  +--------+                  
+                                    |
+                                    |
+                                    v
+                                    
+                                   DMA
+
+
+Here values from ctx->Current and current-HW-vertex are merged to
+build vert-2, which is then dumped to hardware (DMA).  A state machine
+determines which vertex is built in turn, and how the vertices are
+used to present primitives to hardware.  These actions all occur
+during a call to Vertex{234}f{v}.
+
+Each vert-n includes clip coordinates and a clipmask in addition to
+the hardware (window) coordinates.  This information allows clipping
+to take place directly on these vertices, if need be.
+
+t_dd_imm_capi.h
+       
+       Color{34}{fub}{v}() implementations.  These update both
+       ctx->Current (unclamped float colors) and current-HW-vertex
+       with hardware-specific color values (typically unsigned
+       bytes).
+
+       When lighting is enabled, the functions from src/api_noop.c
+       should be used, which just update ctx->Current.  (The
+       current-hw-vertex colors are produced from lighting, which is
+       keyed to Normal3f).
+
+t_dd_imm_vb.c
+
+       Support functions for clipping and fallback.  See
+       t_dd_imm_primtmp.h.
+
+t_dd_imm_napi.c
+t_dd_imm_napi.h
+
+       Versions of Normal3f{v} to perform lighting with one or more
+       infinite lights.  Updates ctx->Current.Normal and the current
+       HW colors.
+
+       When lighting is disabled, use the functions from api_noop.c
+       instead.
+
+
+t_dd_imm_primtmp.h
+
+       State machine to control emission of vertices and primitives
+       to hardware.  Called indirectly from Vertex{234}f{v}.  Capable
+       of supporting hardware strip and fan primitives, and of
+       decomposing to discreet primitives for clipping or fallback,
+       or where the native primitive is unavailable.
+
+t_dd_imm_tapi.h
+
+       Implementations of TexCoord{v} and MultiTexCoord4f{v}ARB to
+       fire a callback when transitioning to projective texture.
+       Most drivers will need to change vertex format at this point,
+       some may need to enable a software rasterization fallback.
+
+t_dd_imm_vapi.h
+
+       Implementations of Vertex{234}f{v}.  These perform
+       transformation and cliptesting on their arguments, then jump
+       into the state machine implemented in primtmp.h.
+
+t_dd_imm_vertex.h
+
+       Support functions for building and clip-interpolating hardware
+       vertices.  Called from primtmp.h.
+
+
+Keith Whitwell, June 2001.
\ No newline at end of file
diff --git a/src/mesa/tnl_dd/imm/t_dd_imm_capi.h b/src/mesa/tnl_dd/imm/t_dd_imm_capi.h
new file mode 100644 (file)
index 0000000..77f3a4a
--- /dev/null
@@ -0,0 +1,419 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.5
+ *
+ * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+/* Template for immediate mode color functions.
+ *
+ * FIXME: Floating-point color versions of these...
+ */
+
+
+static void TAG(Color3f)( GLfloat r, GLfloat g, GLfloat b )
+{
+   GET_CURRENT;
+#ifdef COLOR_IS_FLOAT
+   CURRENT_COLOR( RCOMP ) = CLAMP(r, 0.0f, 1.0f);
+   CURRENT_COLOR( GCOMP ) = CLAMP(g, 0.0f, 1.0f);
+   CURRENT_COLOR( BCOMP ) = CLAMP(b, 0.0f, 1.0f);
+   CURRENT_COLOR( ACOMP ) = 1.0f;
+#else
+   UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( RCOMP ), r );
+   UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( GCOMP ), g );
+   UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( BCOMP ), b );
+   CURRENT_COLOR( ACOMP ) = 255;
+#endif
+}
+
+static void TAG(Color3fv)( const GLfloat *v )
+{
+   GET_CURRENT;
+#ifdef COLOR_IS_FLOAT
+   CURRENT_COLOR( RCOMP ) = CLAMP(v[0], 0.0f, 1.0f);
+   CURRENT_COLOR( GCOMP ) = CLAMP(v[1], 0.0f, 1.0f);
+   CURRENT_COLOR( BCOMP ) = CLAMP(v[2], 0.0f, 1.0f);
+   CURRENT_COLOR( ACOMP ) = 1.0f;
+#else
+   UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( RCOMP ), v[0] );
+   UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( GCOMP ), v[1] );
+   UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( BCOMP ), v[2] );
+   CURRENT_COLOR( ACOMP ) = 255;
+#endif
+}
+
+static void TAG(Color3ub)( GLubyte r, GLubyte g, GLubyte b )
+{
+   GET_CURRENT;
+#ifdef COLOR_IS_FLOAT
+   CURRENT_COLOR( RCOMP ) = UBYTE_TO_FLOAT( r );
+   CURRENT_COLOR( GCOMP ) = UBYTE_TO_FLOAT( g );
+   CURRENT_COLOR( BCOMP ) = UBYTE_TO_FLOAT( b );
+   CURRENT_COLOR( ACOMP ) = 1.0f;
+#else
+   CURRENT_COLOR( RCOMP ) = r;
+   CURRENT_COLOR( GCOMP ) = g;
+   CURRENT_COLOR( BCOMP ) = b;
+   CURRENT_COLOR( ACOMP ) = 255;
+#endif
+}
+
+static void TAG(Color3ubv)( const GLubyte *v )
+{
+   GET_CURRENT;
+#ifdef COLOR_IS_FLOAT
+   CURRENT_COLOR( RCOMP ) = UBYTE_TO_FLOAT( v[0] );
+   CURRENT_COLOR( GCOMP ) = UBYTE_TO_FLOAT( v[1] );
+   CURRENT_COLOR( BCOMP ) = UBYTE_TO_FLOAT( v[2] );
+   CURRENT_COLOR( ACOMP ) = 1.0f;
+#else
+   CURRENT_COLOR( RCOMP ) = v[0];
+   CURRENT_COLOR( GCOMP ) = v[1];
+   CURRENT_COLOR( BCOMP ) = v[2];
+   CURRENT_COLOR( ACOMP ) = 255;
+#endif
+}
+
+static void TAG(Color4f)( GLfloat r, GLfloat g, GLfloat b, GLfloat a )
+{
+   GET_CURRENT;
+#ifdef COLOR_IS_FLOAT
+   CURRENT_COLOR( RCOMP ) = CLAMP(r, 0.0f, 1.0f);
+   CURRENT_COLOR( GCOMP ) = CLAMP(g, 0.0f, 1.0f);
+   CURRENT_COLOR( BCOMP ) = CLAMP(b, 0.0f, 1.0f);
+   CURRENT_COLOR( ACOMP ) = CLAMP(a, 0.0f, 1.0f);
+#else
+   UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( RCOMP ), r );
+   UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( GCOMP ), g );
+   UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( BCOMP ), b );
+   UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( ACOMP ), a );
+#endif
+}
+
+static void TAG(Color4fv)( const GLfloat *v )
+{
+   GET_CURRENT;
+#ifdef COLOR_IS_FLOAT
+   CURRENT_COLOR( RCOMP ) = CLAMP(v[0], 0.0f, 1.0f);
+   CURRENT_COLOR( GCOMP ) = CLAMP(v[1], 0.0f, 1.0f);
+   CURRENT_COLOR( BCOMP ) = CLAMP(v[2], 0.0f, 1.0f);
+   CURRENT_COLOR( ACOMP ) = CLAMP(v[3], 0.0f, 1.0f);
+#else
+   UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( RCOMP ), v[0] );
+   UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( GCOMP ), v[1] );
+   UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( BCOMP ), v[2] );
+   UNCLAMPED_FLOAT_TO_UBYTE( CURRENT_COLOR( ACOMP ), v[3] );
+#endif
+}
+
+static void TAG(Color4ub)( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+   GET_CURRENT;
+#ifdef COLOR_IS_FLOAT
+   CURRENT_COLOR( RCOMP ) = UBYTE_TO_FLOAT( r );
+   CURRENT_COLOR( GCOMP ) = UBYTE_TO_FLOAT( g );
+   CURRENT_COLOR( BCOMP ) = UBYTE_TO_FLOAT( b );
+   CURRENT_COLOR( ACOMP ) = UBYTE_TO_FLOAT( a );
+#else
+   CURRENT_COLOR( RCOMP ) = r;
+   CURRENT_COLOR( GCOMP ) = g;
+   CURRENT_COLOR( BCOMP ) = b;
+   CURRENT_COLOR( ACOMP ) = a;
+#endif
+}
+
+static void TAG(Color4ubv)( const GLubyte *v )
+{
+   GET_CURRENT;
+#ifdef COLOR_IS_FLOAT
+   CURRENT_COLOR( RCOMP ) = UBYTE_TO_FLOAT( v[0] );
+   CURRENT_COLOR( GCOMP ) = UBYTE_TO_FLOAT( v[1] );
+   CURRENT_COLOR( BCOMP ) = UBYTE_TO_FLOAT( v[2] );
+   CURRENT_COLOR( ACOMP ) = UBYTE_TO_FLOAT( v[3] );
+#else
+   CURRENT_COLOR( RCOMP ) = v[0];
+   CURRENT_COLOR( GCOMP ) = v[1];
+   CURRENT_COLOR( BCOMP ) = v[2];
+   CURRENT_COLOR( ACOMP ) = v[3];
+#endif
+}
+
+
+static void TAG(ColorMaterial3f)( GLfloat r, GLfloat g, GLfloat b )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLfloat *color = ctx->Current.Color;
+
+   color[0] = r;
+   color[1] = g;
+   color[2] = b;
+   color[3] = 1.0;
+
+   _mesa_update_color_material( ctx, color );
+   RECALC_BASE_COLOR( ctx );
+}
+
+static void TAG(ColorMaterial3fv)( const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLfloat *color = ctx->Current.Color;
+
+   color[0] = v[0];
+   color[1] = v[1];
+   color[2] = v[2];
+   color[3] = 1.0;
+
+   _mesa_update_color_material( ctx, color );
+   RECALC_BASE_COLOR( ctx );
+}
+
+static void TAG(ColorMaterial3ub)( GLubyte r, GLubyte g, GLubyte b )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLfloat *color = ctx->Current.Color;
+
+   color[0] = UBYTE_TO_FLOAT( r );
+   color[1] = UBYTE_TO_FLOAT( g );
+   color[2] = UBYTE_TO_FLOAT( b );
+   color[3] = 1.0;
+
+   _mesa_update_color_material( ctx, color );
+   RECALC_BASE_COLOR( ctx );
+}
+
+static void TAG(ColorMaterial3ubv)( const GLubyte *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLfloat *color = ctx->Current.Color;
+
+   color[0] = UBYTE_TO_FLOAT( v[0] );
+   color[1] = UBYTE_TO_FLOAT( v[1] );
+   color[2] = UBYTE_TO_FLOAT( v[2] );
+   color[3] = 1.0;
+
+   _mesa_update_color_material( ctx, color );
+   RECALC_BASE_COLOR( ctx );
+}
+
+static void TAG(ColorMaterial4f)( GLfloat r, GLfloat g, GLfloat b, GLfloat a )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLfloat *color = ctx->Current.Color;
+
+   color[0] = r;
+   color[1] = g;
+   color[2] = b;
+   color[3] = a;
+
+   _mesa_update_color_material( ctx, color );
+   RECALC_BASE_COLOR( ctx );
+}
+
+static void TAG(ColorMaterial4fv)( const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLfloat *color = ctx->Current.Color;
+
+   color[0] = v[0];
+   color[1] = v[1];
+   color[2] = v[2];
+   color[3] = v[3];
+
+   _mesa_update_color_material( ctx, color );
+   RECALC_BASE_COLOR( ctx );
+}
+
+static void TAG(ColorMaterial4ub)( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLfloat *color = ctx->Current.Color;
+
+   color[0] = UBYTE_TO_FLOAT( r );
+   color[1] = UBYTE_TO_FLOAT( g );
+   color[2] = UBYTE_TO_FLOAT( b );
+   color[3] = UBYTE_TO_FLOAT( a );
+
+   _mesa_update_color_material( ctx, color );
+   RECALC_BASE_COLOR( ctx );
+}
+
+static void TAG(ColorMaterial4ubv)( const GLubyte *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLfloat *color = ctx->Current.Color;
+
+   color[0] = UBYTE_TO_FLOAT( v[0] );
+   color[1] = UBYTE_TO_FLOAT( v[1] );
+   color[2] = UBYTE_TO_FLOAT( v[2] );
+   color[3] = UBYTE_TO_FLOAT( v[3] );
+
+   _mesa_update_color_material( ctx, color );
+   RECALC_BASE_COLOR( ctx );
+}
+
+
+
+
+
+/* =============================================================
+ * Color chooser functions:
+ */
+
+static void TAG(choose_Color3f)( GLfloat r, GLfloat g, GLfloat b )
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if ( ctx->Light.Enabled ) {
+      if ( ctx->Light.ColorMaterialEnabled ) {
+        ctx->Exec->Color3f = TAG(ColorMaterial3f);
+      } else {
+        ctx->Exec->Color3f = _mesa_noop_Color3f;
+      }
+   } else {
+      ctx->Exec->Color3f = TAG(Color3f);
+   }
+   glColor3f( r, g, b );
+}
+
+static void TAG(choose_Color3fv)( const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if ( ctx->Light.Enabled ) {
+      if ( ctx->Light.ColorMaterialEnabled ) {
+        ctx->Exec->Color3fv = TAG(ColorMaterial3fv);
+      } else {
+        ctx->Exec->Color3fv = _mesa_noop_Color3fv;
+      }
+   } else {
+      ctx->Exec->Color3fv = TAG(Color3fv);
+   }
+   glColor3fv( v );
+}
+
+static void TAG(choose_Color3ub)( GLubyte r, GLubyte g, GLubyte b )
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if ( ctx->Light.Enabled ) {
+      if ( ctx->Light.ColorMaterialEnabled ) {
+        ctx->Exec->Color3ub = TAG(ColorMaterial3ub);
+      } else {
+        ctx->Exec->Color3ub = _mesa_noop_Color3ub;
+      }
+   } else {
+      ctx->Exec->Color3ub = TAG(Color3ub);
+   }
+   glColor3ub( r, g, b );
+}
+
+static void TAG(choose_Color3ubv)( const GLubyte *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if ( ctx->Light.Enabled ) {
+      if ( ctx->Light.ColorMaterialEnabled ) {
+        ctx->Exec->Color3ubv = TAG(ColorMaterial3ubv);
+      } else {
+        ctx->Exec->Color3ubv = _mesa_noop_Color3ubv;
+      }
+   } else {
+      ctx->Exec->Color3ubv = TAG(Color3ubv);
+   }
+   glColor3ubv( v );
+}
+
+static void TAG(choose_Color4f)( GLfloat r, GLfloat g, GLfloat b, GLfloat a )
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if ( ctx->Light.Enabled ) {
+      if ( ctx->Light.ColorMaterialEnabled ) {
+        ctx->Exec->Color4f = TAG(ColorMaterial4f);
+      } else {
+        ctx->Exec->Color4f = _mesa_noop_Color4f;
+      }
+   } else {
+      ctx->Exec->Color4f = TAG(Color4f);
+   }
+   glColor4f( r, g, b, a );
+}
+
+static void TAG(choose_Color4fv)( const GLfloat *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if ( ctx->Light.Enabled ) {
+      if ( ctx->Light.ColorMaterialEnabled ) {
+        ctx->Exec->Color4fv = TAG(ColorMaterial4fv);
+      } else {
+        ctx->Exec->Color4fv = _mesa_noop_Color4fv;
+      }
+   } else {
+      ctx->Exec->Color4fv = TAG(Color4fv);
+   }
+   glColor4fv( v );
+}
+
+static void TAG(choose_Color4ub)( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if ( ctx->Light.Enabled ) {
+      if ( ctx->Light.ColorMaterialEnabled ) {
+        ctx->Exec->Color4ub = TAG(ColorMaterial4ub);
+      } else {
+        ctx->Exec->Color4ub = _mesa_noop_Color4ub;
+      }
+   } else {
+      ctx->Exec->Color4ub = TAG(Color4ub);
+   }
+   glColor4ub( r, g, b, a );
+}
+
+static void TAG(choose_Color4ubv)( const GLubyte *v )
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   if ( ctx->Light.Enabled ) {
+      if ( ctx->Light.ColorMaterialEnabled ) {
+        ctx->Exec->Color4ubv = TAG(ColorMaterial4ubv);
+      } else {
+        ctx->Exec->Color4ubv = _mesa_noop_Color4ubv;
+      }
+   } else {
+      ctx->Exec->Color4ubv = TAG(Color4ubv);
+   }
+   glColor4ubv( v );
+}
+
+
+
+#undef GET_CURRENT
+#undef CURRENT_COLOR
+#undef CURRENT_SPECULAR
+#undef COLOR_IS_FLOAT
+#undef RECALC_BASE_COLOR
+#undef TAG
diff --git a/src/mesa/tnl_dd/imm/t_dd_imm_napi.h b/src/mesa/tnl_dd/imm/t_dd_imm_napi.h
new file mode 100644 (file)
index 0000000..9844f61
--- /dev/null
@@ -0,0 +1,226 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.5
+ *
+ * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ *    Keith Whitwell <keith_whitwell@yahoo.com>
+ */
+
+/* Template for immediate mode normal functions.  Optimize for infinite
+ * lights when doing software lighting.
+ */
+
+static void TAG(Normal3f_single)( GLfloat x, GLfloat y, GLfloat z )
+{
+   GET_CURRENT_VERTEX;
+   const struct gl_light *light = ctx->Light.EnabledList.prev;
+   GLfloat n_dot_h, n_dot_VP, spec, sum[3];
+   GLfloat *normal = ctx->Current.Normal;
+   GLfloat scale = 1.0;
+
+   ASSIGN_3V( normal, x, y, z );
+   COPY_3V( sum, BASE_COLOR );
+
+   if ( IND & NORM_RESCALE ) {
+      scale = ctx->_ModelViewInvScale;
+   } else if ( IND & NORM_NORMALIZE ) {
+      scale = LEN_3FV( normal );
+      if ( scale != 0.0 ) scale = 1.0 / scale;
+   }
+
+   n_dot_VP = DOT3( normal, light->_VP_inf_norm ) * scale;
+   if ( n_dot_VP > 0.0F ) {
+      ACC_SCALE_SCALAR_3V( sum, n_dot_VP, light->_MatDiffuse[0] );
+      n_dot_h = DOT3( normal, light->_h_inf_norm ) * scale;
+      if ( n_dot_h > 0.0F ) {
+        GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec );
+        ACC_SCALE_SCALAR_3V( sum, spec, light->_MatSpecular[0] );
+      }
+   }
+
+#ifdef LIT_COLOR_IS_FLOAT
+   LIT_COLOR ( RCOMP ) = CLAMP(sum[0], 0.0f, 0.1f);
+   LIT_COLOR ( GCOMP ) = CLAMP(sum[1], 0.0f, 0.1f);
+   LIT_COLOR ( BCOMP ) = CLAMP(sum[2], 0.0f, 0.1f);
+#else
+   UNCLAMPED_FLOAT_TO_UBYTE( LIT_COLOR( RCOMP ), sum[0] );
+   UNCLAMPED_FLOAT_TO_UBYTE( LIT_COLOR( GCOMP ), sum[1] );
+   UNCLAMPED_FLOAT_TO_UBYTE( LIT_COLOR( BCOMP ), sum[2] );
+#endif
+   LIT_COLOR( ACOMP ) = LIT_ALPHA;
+}
+
+static void TAG(Normal3fv_single)( const GLfloat *normal )
+{
+   GET_CURRENT_VERTEX;
+   const struct gl_light *light = ctx->Light.EnabledList.prev;
+   GLfloat n_dot_h, n_dot_VP, spec, sum[3];
+   GLfloat scale = 1.0;
+
+   COPY_3V( ctx->Current.Normal, normal );
+   COPY_3V( sum, BASE_COLOR );
+
+   if ( IND & NORM_RESCALE ) {
+      scale = ctx->_ModelViewInvScale;
+   } else if ( IND & NORM_NORMALIZE ) {
+      scale = LEN_3FV( normal );
+      if ( scale != 0.0 ) scale = 1.0 / scale;
+   }
+
+   n_dot_VP = DOT3( normal, light->_VP_inf_norm ) * scale;
+   if ( n_dot_VP > 0.0F ) {
+      ACC_SCALE_SCALAR_3V( sum, n_dot_VP, light->_MatDiffuse[0] );
+      n_dot_h = DOT3( normal, light->_h_inf_norm ) * scale;
+      if ( n_dot_h > 0.0F ) {
+        GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec );
+        ACC_SCALE_SCALAR_3V( sum, spec, light->_MatSpecular[0] );
+      }
+   }
+
+#ifdef LIT_COLOR_IS_FLOAT
+   LIT_COLOR ( RCOMP ) = CLAMP(sum[0], 0.0f, 0.1f);
+   LIT_COLOR ( GCOMP ) = CLAMP(sum[1], 0.0f, 0.1f);
+   LIT_COLOR ( BCOMP ) = CLAMP(sum[2], 0.0f, 0.1f);
+#else
+   UNCLAMPED_FLOAT_TO_UBYTE( LIT_COLOR( RCOMP ), sum[0] );
+   UNCLAMPED_FLOAT_TO_UBYTE( LIT_COLOR( GCOMP ), sum[1] );
+   UNCLAMPED_FLOAT_TO_UBYTE( LIT_COLOR( BCOMP ), sum[2] );
+#endif
+   LIT_COLOR( ACOMP ) = LIT_ALPHA;
+}
+
+
+static void TAG(Normal3f_multi)( GLfloat x, GLfloat y, GLfloat z )
+{
+   GET_CURRENT_VERTEX;
+   struct gl_light *light;
+   GLfloat n_dot_h, n_dot_VP, spec, sum[3], tmp[3];
+   GLfloat *normal;
+
+   ASSIGN_3V( ctx->Current.Normal, x, y, z );
+   COPY_3V( sum, BASE_COLOR );
+
+   if ( IND & NORM_RESCALE ) {
+      normal = tmp;
+      ASSIGN_3V( normal, x, y, z );
+      SELF_SCALE_SCALAR_3V( normal, ctx->_ModelViewInvScale );
+   } else if ( IND & NORM_NORMALIZE ) {
+      normal = tmp;
+      ASSIGN_3V( normal, x, y, z );
+      NORMALIZE_3FV( normal );
+   } else {
+      normal = ctx->Current.Normal;
+   }
+
+   foreach ( light, &ctx->Light.EnabledList ) {
+      n_dot_VP = DOT3( normal, light->_VP_inf_norm );
+      if ( n_dot_VP > 0.0F ) {
+        ACC_SCALE_SCALAR_3V( sum, n_dot_VP, light->_MatDiffuse[0] );
+        n_dot_h = DOT3( normal, light->_h_inf_norm );
+        if ( n_dot_h > 0.0F ) {
+           GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec );
+           ACC_SCALE_SCALAR_3V( sum, spec, light->_MatSpecular[0] );
+        }
+      }
+   }
+
+#ifdef LIT_COLOR_IS_FLOAT
+   LIT_COLOR ( RCOMP ) = CLAMP(sum[0], 0.0f, 0.1f);
+   LIT_COLOR ( GCOMP ) = CLAMP(sum[1], 0.0f, 0.1f);
+   LIT_COLOR ( BCOMP ) = CLAMP(sum[2], 0.0f, 0.1f);
+#else
+   UNCLAMPED_FLOAT_TO_UBYTE( LIT_COLOR( RCOMP ), sum[0] );
+   UNCLAMPED_FLOAT_TO_UBYTE( LIT_COLOR( GCOMP ), sum[1] );
+   UNCLAMPED_FLOAT_TO_UBYTE( LIT_COLOR( BCOMP ), sum[2] );
+#endif
+   LIT_COLOR( ACOMP ) = LIT_ALPHA;
+}
+
+static void TAG(Normal3fv_multi)( const GLfloat *n )
+{
+   GET_CURRENT_VERTEX;
+   struct gl_light *light;
+   GLfloat n_dot_h, n_dot_VP, spec, sum[3], tmp[3];
+   GLfloat *normal;
+
+   COPY_3V( ctx->Current.Normal, n );
+   COPY_3V( sum, BASE_COLOR );
+
+   if ( IND & NORM_RESCALE ) {
+      normal = tmp;
+      COPY_3V( normal, n );
+      SELF_SCALE_SCALAR_3V( normal, ctx->_ModelViewInvScale );
+   } else if ( IND & NORM_NORMALIZE ) {
+      normal = tmp;
+      COPY_3V( normal, n );
+      NORMALIZE_3FV( normal );
+   } else {
+      normal = ctx->Current.Normal;
+   }
+
+   foreach ( light, &ctx->Light.EnabledList ) {
+      n_dot_VP = DOT3( normal, light->_VP_inf_norm );
+      if ( n_dot_VP > 0.0F ) {
+        ACC_SCALE_SCALAR_3V( sum, n_dot_VP, light->_MatDiffuse[0] );
+        n_dot_h = DOT3( normal, light->_h_inf_norm );
+        if ( n_dot_h > 0.0F ) {
+           GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec );
+           ACC_SCALE_SCALAR_3V( sum, spec, light->_MatSpecular[0] );
+        }
+      }
+   }
+
+#ifdef LIT_COLOR_IS_FLOAT
+   LIT_COLOR ( RCOMP ) = CLAMP(sum[0], 0.0f, 0.1f);
+   LIT_COLOR ( GCOMP ) = CLAMP(sum[1], 0.0f, 0.1f);
+   LIT_COLOR ( BCOMP ) = CLAMP(sum[2], 0.0f, 0.1f);
+#else
+   UNCLAMPED_FLOAT_TO_UBYTE( LIT_COLOR( RCOMP ), sum[0] );
+   UNCLAMPED_FLOAT_TO_UBYTE( LIT_COLOR( GCOMP ), sum[1] );
+   UNCLAMPED_FLOAT_TO_UBYTE( LIT_COLOR( BCOMP ), sum[2] );
+#endif
+   LIT_COLOR( ACOMP ) = LIT_ALPHA;
+}
+
+
+
+static void TAG(init_norm)( void )
+{
+   norm_tab[IND].normal3f_single = TAG(Normal3f_single);
+   norm_tab[IND].normal3fv_single = TAG(Normal3fv_single);
+   norm_tab[IND].normal3f_multi = TAG(Normal3f_multi);
+   norm_tab[IND].normal3fv_multi = TAG(Normal3fv_multi);
+}
+
+
+
+#ifndef PRESERVE_NORMAL_DEFS
+#undef GET_CURRENT
+#undef GET_CURRENT_VERTEX
+#undef LIT_COLOR
+#undef LIT_COLOR_IS_FLOAT
+#endif
+#undef PRESERVE_NORMAL_DEFS
+#undef IND
+#undef TAG
diff --git a/src/mesa/tnl_dd/imm/t_dd_imm_primtmp.h b/src/mesa/tnl_dd/imm/t_dd_imm_primtmp.h
new file mode 100644 (file)
index 0000000..97dca3f
--- /dev/null
@@ -0,0 +1,570 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.5
+ *
+ * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keithw@valinux.com>
+ *    Gareth Hughes <gareth@valinux.com>
+ */
+
+/* Template for immediate mode vertices. 
+ *
+ * Probably instantiate once for each vertex format used:
+ *   - TINY_VERTICES
+ *   - TEX0_VERTICES
+ *   - TEX1_VERTICES
+ *   - PTEX_VERTICES
+ *
+ * Have to handle TEX->PTEX transition somehow.
+ */
+
+#define DBG 0
+
+
+
+/* =============================================================
+ * GL_POINTS
+ */
+
+static void TAG(flush_point_0)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   if ( !v0->mask ) {
+      LOCAL_VARS;
+      DRAW_POINT( v0 );
+   }
+}
+
+
+/* =============================================================
+ * GL_LINES
+ */
+
+static void TAG(flush_line_1)( GLcontext *ctx, TNL_VERTEX *v0 );
+
+static void TAG(flush_line_0)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+   FLUSH_VERTEX = TAG(flush_line_1);
+   ACTIVE_VERTEX = IMM_VERTICES( 1 );
+}
+
+static void TAG(flush_line_1)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+   TNL_VERTEX *v1 = v0 - 1;
+   ACTIVE_VERTEX = IMM_VERTICES( 0 );
+   FLUSH_VERTEX = TAG(flush_line_0);
+   if (FALLBACK_OR_CLIPPING) 
+      CLIP_OR_DRAW_LINE( ctx, v1, v0 ); 
+   else
+      DRAW_LINE( ctx, v1, v0 ); 
+}
+
+
+/* =============================================================
+ * GL_LINE_LOOP
+ */
+
+static void TAG(flush_line_loop_2)( GLcontext *ctx, TNL_VERTEX *v0 );
+static void TAG(flush_line_loop_1)( GLcontext *ctx, TNL_VERTEX *v0 );
+
+static void TAG(flush_line_loop_0)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+
+   ACTIVE_VERTEX = v0 + 1;
+   FLUSH_VERTEX = TAG(flush_line_loop_1);
+}
+
+#define DRAW_LINELOOP_LINE( a, b )                     \
+   if (!HAVE_LINE_STRIP || FALLBACK_OR_CLIPPING) {     \
+      CLIP_OR_DRAW_LINE( ctx, a, b );                  \
+   } else if (EXTEND_PRIM( 1 )) {                      \
+      EMIT_VERTEX( b );                                        \
+   } else {                                            \
+      BEGIN_PRIM( GL_LINE_STRIP, 2 );                  \
+      EMIT_VERTEX( a );                                        \
+      EMIT_VERTEX( b );                                \
+   }
+
+static void TAG(flush_line_loop_1)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+   TNL_VERTEX *v1 = v0 - 1;
+   ACTIVE_VERTEX = v1;
+   FLUSH_VERTEX = TAG(flush_line_loop_2);
+   DRAW_LINELOOP_LINE( v1, v0 );
+}
+
+static void TAG(flush_line_loop_2)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+   TNL_VERTEX *v1 = v0 + 1;
+   ACTIVE_VERTEX = v1;
+   FLUSH_VERTEX = TAG(flush_line_loop_1);
+   DRAW_LINELOOP_LINE( v1, v0 );
+}
+
+static void TAG(end_line_loop)( GLcontext *ctx )
+{
+   LOCAL_VARS;
+
+   if ( FLUSH_VERTEX != TAG(flush_line_loop_0) ) {
+      TNL_VERTEX *v1 = ACTIVE_VERTEX;
+      TNL_VERTEX *v0 = IMM_VERTICES( 0 );
+      DRAW_LINELOOP_LINE( v1, v0 );
+   }
+}
+
+
+
+/* =============================================================
+ * GL_LINE_STRIP
+ */
+
+static void TAG(flush_line_strip_2)( GLcontext *ctx, TNL_VERTEX *v0 );
+static void TAG(flush_line_strip_1)( GLcontext *ctx, TNL_VERTEX *v0 );
+
+static void TAG(flush_line_strip_0)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+
+   ACTIVE_VERTEX = v0 + 1;
+   FLUSH_VERTEX = TAG(flush_line_strip_0b);
+}
+
+
+static void TAG(flush_line_strip_1)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+   TNL_VERTEX *v1 = v0 - 1;
+
+   ACTIVE_VERTEX = v1;
+   FLUSH_VERTEX = TAG(flush_line_strip_2);
+
+   if (!HAVE_LINE_STRIP || FALLBACK_OR_CLIPPING)
+      CLIP_OR_DRAW_LINE( ctx, v1, v0 );
+   else if (EXTEND_PRIM( 1 )) {
+      EMIT_VERTEX( v0 );
+   } else {
+      BEGIN_PRIM( GL_LINE_STRIP, 2 ); 
+      EMIT_VERTEX( v1 );
+      EMIT_VERTEX( v0 );      
+   }      
+}
+
+static void TAG(flush_line_strip_2)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+   TNL_VERTEX *v1 = v0 + 1;
+
+   ACTIVE_VERTEX = v1;
+   FLUSH_VERTEX = TAG(flush_line_strip_1);
+
+   if (!HAVE_LINE_STRIP || FALLBACK_OR_CLIPPING)
+      CLIP_OR_DRAW_LINE( ctx, v1, v0 );
+   else if (EXTEND_PRIM( 1 )) {
+      EMIT_VERTEX( v0 );
+   } else {
+      BEGIN_PRIM( GL_LINE_STRIP, 2 ); 
+      EMIT_VERTEX( v1 );
+      EMIT_VERTEX( v0 );      
+   }      
+}
+
+
+
+/* =============================================================
+ * GL_TRIANGLES
+ */
+
+static void TAG(flush_triangle_2)( GLcontext *ctx, TNL_VERTEX *v0 );
+static void TAG(flush_triangle_1)( GLcontext *ctx, TNL_VERTEX *v0 );
+
+static void TAG(flush_triangle_0)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+
+   if ( DBG ) fprintf( stderr, __FUNCTION__ "\n" );
+
+   ACTIVE_VERTEX = v0 + 1;
+   FLUSH_VERTEX = TAG(flush_triangle_1);
+   BEGIN_PRIM( GL_TRIANGLES, 0 );
+}
+
+static void TAG(flush_triangle_1)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+
+   if ( DBG ) fprintf( stderr, __FUNCTION__ "\n" );
+
+   ACTIVE_VERTEX = v0 + 1;
+   FLUSH_VERTEX = TAG(flush_triangle_2);
+}
+
+static void TAG(flush_triangle_2)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+   TNL_VERTEX *v2 = v0 - 2;
+   TNL_VERTEX *v1 = v0 - 1;
+
+   if ( DBG ) fprintf( stderr, __FUNCTION__ "\n" );
+
+   ACTIVE_VERTEX = v2;
+   FLUSH_VERTEX = TAG(flush_triangle_0);
+
+   /* nothing gained by trying to emit as hw primitives -- that
+    * happens normally in this case.  
+    */
+   if (FALLBACK_OR_CLIPPING)
+      CLIP_OR_DRAW_TRI( ctx, v2, v1, v0 );
+   else
+      DRAW_TRI( ctx, v2, v1, v0 );
+}
+
+
+
+
+/* =============================================================
+ * GL_TRIANGLE_STRIP
+ */
+
+static void TAG(flush_tri_strip_3)( GLcontext *ctx, TNL_VERTEX *v0 );
+static void TAG(flush_tri_strip_2)( GLcontext *ctx, TNL_VERTEX *v0 );
+static void TAG(flush_tri_strip_1)( GLcontext *ctx, TNL_VERTEX *v0 );
+
+static void TAG(flush_tri_strip_0)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+   ACTIVE_VERTEX = IMM_VERTICES( 1 );
+   FLUSH_VERTEX = TAG(flush_tri_strip_1);
+}
+
+static void TAG(flush_tri_strip_1)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+   ACTIVE_VERTEX = IMM_VERTICES( 2 );
+   FLUSH_VERTEX = TAG(flush_tri_strip_2);
+}
+
+#define DO_TRISTRIP_TRI( vert0, vert1 )                                \
+   if (!HAVE_TRI_STRIP || FALLBACK_OR_CLIPPING) {      \
+      TNL_VERTEX *v2 = IMM_VERTICES( vert0 );                  \
+      TNL_VERTEX *v1 = IMM_VERTICES( vert1 );                  \
+      TAG(draw_tri)( ctx, v2, v1, v0 );                                \
+   } else if (EXTEND_PRIM( 1 )) {                              \
+      EMIT_VERTEX( v0 );                                       \
+   } else {                                                    \
+      TNL_VERTEX *v2 = IMM_VERTICES( vert0 );                  \
+      TNL_VERTEX *v1 = IMM_VERTICES( vert1 );                  \
+      BEGIN_PRIM( GL_TRIANGLE_STRIP, 3 );                      \
+      EMIT_VERTEX( v2 );                                       \
+      EMIT_VERTEX( v1 );                                       \
+      EMIT_VERTEX( v0 );                                       \
+   }      
+
+static void TAG(flush_tri_strip_2)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+   FLUSH_VERTEX = TAG(flush_tri_strip_3);
+   ACTIVE_VERTEX = IMM_VERTICES( 3 );
+   DO_TRISTRIP_TRI( 0, 1 );
+}
+
+static void TAG(flush_tri_strip_3)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+   FLUSH_VERTEX = TAG(flush_tri_strip_4);
+   ACTIVE_VERTEX = IMM_VERTICES( 0 );
+   DO_TRISTRIP_TRI( 1, 2 );
+}
+
+static void TAG(flush_tri_strip_4)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+   FLUSH_VERTEX = TAG(flush_tri_strip_5);
+   ACTIVE_VERTEX = IMM_VERTICES( 1 );
+   DO_TRISTRIP_TRI( 2, 3 );
+}
+
+static void TAG(flush_tri_strip_5)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+   FLUSH_VERTEX = TAG(flush_tri_strip_2);
+   ACTIVE_VERTEX = IMM_VERTICES( 2 );
+   DO_TRISTRIP_TRI( 0, 3 );
+}
+
+
+
+/* =============================================================
+ * GL_TRIANGLE_FAN
+ */
+
+static void TAG(flush_tri_fan_2)( GLcontext *ctx, TNL_VERTEX *v0 );
+static void TAG(flush_tri_fan_1)( GLcontext *ctx, TNL_VERTEX *v0 );
+
+static void TAG(flush_tri_fan_0)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+
+   ACTIVE_VERTEX = v0 + 1;
+   FLUSH_VERTEX = TAG(flush_tri_fan_1);
+}
+
+static void TAG(flush_tri_fan_1)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+
+   ACTIVE_VERTEX = v0 + 1;
+   FLUSH_VERTEX = TAG(flush_tri_fan_2);
+}
+
+#define DO_TRIFAN_TRI( vert0, vert1 )                          \
+   if (!HAVE_TRI_FAN || FALLBACK_OR_CLIPPING) {        \
+      TNL_VERTEX *v2 = IMM_VERTICES( vert0 );                  \
+      TNL_VERTEX *v1 = IMM_VERTICES( vert1 );                  \
+      TAG(draw_tri)( ctx, v2, v1, v0 );                                \
+   } else if (EXTEND_PRIM( 1 )) {                              \
+      EMIT_VERTEX( v0 );                                       \
+   } else {                                                    \
+      TNL_VERTEX *v2 = IMM_VERTICES( vert0 );                  \
+      TNL_VERTEX *v1 = IMM_VERTICES( vert1 );                  \
+      BEGIN_PRIM( GL_TRIANGLE_FAN, 3 );                        \
+      EMIT_VERTEX( v2 );                                       \
+      EMIT_VERTEX( v1 );                                       \
+      EMIT_VERTEX( v0 );                                       \
+   }      
+
+static void TAG(flush_tri_fan_2)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+   ACTIVE_VERTEX = IMM_VERTICES( 1 );
+   FLUSH_VERTEX = TAG(flush_tri_fan_3 );
+   DO_TRIFAN_TRI( 0, 1 );
+}
+
+static void TAG(flush_tri_fan_3)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+   ACTIVE_VERTEX = IMM_VERTICES( 2 );
+   FLUSH_VERTEX = TAG(flush_tri_fan_2 );
+   DO_TRIFAN_TRI( 0, 2 );
+}
+
+
+
+/* =============================================================
+ * GL_QUADS
+ */
+
+static void TAG(flush_quad_3)( GLcontext *ctx, TNL_VERTEX *v0 );
+static void TAG(flush_quad_2)( GLcontext *ctx, TNL_VERTEX *v0 );
+static void TAG(flush_quad_1)( GLcontext *ctx, TNL_VERTEX *v0 );
+
+static void TAG(flush_quad_0)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+   IMM_VERTEX( v0 ) = v0 + 1;
+   FLUSH_VERTEX = TAG(flush_quad_1);
+}
+
+static void TAG(flush_quad_1)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+   IMM_VERTEX( v0 ) = v0 + 1;
+   FLUSH_VERTEX = TAG(flush_quad_2);
+}
+
+static void TAG(flush_quad_2)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+   IMM_VERTEX( v0 ) = v0 + 1;
+   FLUSH_VERTEX = TAG(flush_quad_3);
+}
+
+static void TAG(flush_quad_3)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+   TNL_VERTEX *v3 = v0 - 3;
+   TNL_VERTEX *v2 = v0 - 2;
+   TNL_VERTEX *v1 = v0 - 1;
+
+   IMM_VERTEX( v0 ) = v3;
+   FLUSH_VERTEX = TAG(flush_quad_0);
+
+   if (!HAVE_HW_QUADS || FALLBACK_OR_CLIPPING) {
+      CLIP_OR_DRAW_TRI( ctx, v3, v2, v0 );
+      CLIP_OR_DRAW_TRI( ctx, v2, v1, v0 );
+   } else {
+      EXTEND_PRIM_NF( GL_QUADS, 4 );
+      EMIT_VERTEX( v3 );
+      EMIT_VERTEX( v2 );
+      EMIT_VERTEX( v1 );      
+      EMIT_VERTEX( v0 );      
+   }
+}
+
+
+
+/* =============================================================
+ * GL_QUAD_STRIP
+ */
+
+static void TAG(flush_quad_strip_3)( GLcontext *ctx, TNL_VERTEX *v0 );
+static void TAG(flush_quad_strip_2)( GLcontext *ctx, TNL_VERTEX *v0 );
+static void TAG(flush_quad_strip_1)( GLcontext *ctx, TNL_VERTEX *v0 );
+
+static void TAG(flush_quad_strip_0)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+
+   IMM_VERTEX( v3 ) = v0;
+   IMM_VERTEX( v0 ) = v0 + 1;
+   FLUSH_VERTEX = TAG(flush_quad_strip_1);
+}
+
+static void TAG(flush_quad_strip_1)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+
+   IMM_VERTEX( v2 ) = v0;
+   IMM_VERTEX( v0 ) = v0 + 1;
+   FLUSH_VERTEX = TAG(flush_quad_strip_2);
+}
+
+static void TAG(flush_quad_strip_2)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+
+   IMM_VERTEX( v1 ) = v0;
+   IMM_VERTEX( v0 ) = v0 + 1;
+   FLUSH_VERTEX = TAG(flush_quad_strip_3);
+}
+
+static void TAG(flush_quad_strip_3)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+   TNL_VERTEX *v3 = IMM_VERTEX( v3 );
+   TNL_VERTEX *v2 = IMM_VERTEX( v2 );
+   TNL_VERTEX *v1 = IMM_VERTEX( v1 );
+
+   IMM_VERTEX( v0 ) = v3;
+   IMM_VERTEX( v2 ) = v0;
+   IMM_VERTEX( v3 ) = v1;
+   FLUSH_VERTEX = TAG(flush_quad_strip_2);
+
+   if (FALLBACK_OR_CLIPPING) {
+      CLIP_OR_DRAW_TRI( ctx, v3, v2, v0 );
+      CLIP_OR_DRAW_TRI( ctx, v2, v1, v0 );
+   } else {
+      DRAW_TRI( ctx, v3, v2, v0 );
+      DRAW_TRI( ctx, v2, v1, v0 );
+   }
+}
+
+
+
+/* =============================================================
+ * GL_POLYGON
+ */
+
+static void TAG(flush_poly_2)( GLcontext *ctx, TNL_VERTEX *v0 );
+static void TAG(flush_poly_1)( GLcontext *ctx, TNL_VERTEX *v0 );
+
+static void TAG(flush_poly_0)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+   ACTIVE_VERTEX = IMM_VERTICES( 1 );
+   FLUSH_VERTEX = TAG(flush_poly_1);
+}
+
+static void TAG(flush_poly_1)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+   ACTIVE_VERTEX = IMM_VERTICES( 2 );
+   FLUSH_VERTEX = TAG(flush_poly_2);
+}
+
+#define DO_POLY_TRI( vert0, vert1 )                            \
+   if (!HAVE_POLYGONS || FALLBACK_OR_CLIPPING) {       \
+      TNL_VERTEX *v2 = IMM_VERTICES( vert0 );                  \
+      TNL_VERTEX *v1 = IMM_VERTICES( vert1 );                  \
+      TAG(draw_tri)( ctx, v1, v0, v2 );                                \
+   } else if (EXTEND_PRIM( 1 )) {                              \
+      EMIT_VERTEX( v0 );                                       \
+   } else {                                                    \
+      TNL_VERTEX *v2 = IMM_VERTICES( vert0 );                  \
+      TNL_VERTEX *v1 = IMM_VERTICES( vert1 );                  \
+      BEGIN_PRIM( GL_POLYGON, 3 );                             \
+      EMIT_VERTEX( v2 );                                       \
+      EMIT_VERTEX( v1 );                                       \
+      EMIT_VERTEX( v0 );                                       \
+   }      
+
+static void TAG(flush_poly_2)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+   ACTIVE_VERTEX = IMM_VERTICES( 1 );
+   FLUSH_VERTEX = TAG(flush_poly_3);
+   DO_POLY_TRI( 0, 1 );
+}
+
+static void TAG(flush_poly_3)( GLcontext *ctx, TNL_VERTEX *v0 )
+{
+   LOCAL_VARS;
+   ACTIVE_VERTEX = IMM_VERTICES( 2 );
+   FLUSH_VERTEX = TAG(flush_poly_2);
+   DO_POLY_TRI( 0, 2 );
+}
+
+
+void (*TAG(flush_tab)[GL_POLYGON+1])( GLcontext *, TNL_VERTEX * ) =
+{
+   TAG(flush_point),
+   TAG(flush_line_0),
+   TAG(flush_line_loop_0),
+   TAG(flush_line_strip_0),
+   TAG(flush_triangle_0),
+   TAG(flush_tri_strip_0),
+   TAG(flush_tri_fan_0),
+   TAG(flush_quad_0),
+   TAG(flush_quad_strip_0),
+   TAG(flush_poly_0),
+};
+
+
+#ifndef PRESERVE_PRIM_DEFS
+#undef LOCAL_VARS
+#undef GET_INTERP_FUNC
+#undef IMM_VERTEX
+#undef IMM_VERTICES
+#undef FLUSH_VERTEX
+#endif
+#undef PRESERVE_PRIM_DEFS
+#undef EXTEND_PRIM
+#undef EMIT_VERTEX
+#undef EMIT_VERTEX_TRI
+#undef EMIT_VERTEX_LINE
+#undef EMIT_VERTEX_POINT
+#undef TAG
diff --git a/src/mesa/tnl_dd/imm/t_dd_imm_tapi.h b/src/mesa/tnl_dd/imm/t_dd_imm_tapi.h
new file mode 100644 (file)
index 0000000..b82a9ab
--- /dev/null
@@ -0,0 +1,75 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.5
+ *
+ * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ *    Keith Whitwell <keith_whitwell@yahoo.com>
+ */
+
+/* Template for immediate mode texture coordinate functions.
+ */
+
+#ifndef DO_PROJ_TEX
+#error "Need to define DO_PROJ_TEX"
+#endif
+
+
+/* =============================================================
+ * Notify on calls to texture4f, to allow switch to projected texture
+ * vertex format:
+ */
+
+static void TAG(TexCoord4f)( GLfloat s, GLfloat t, GLfloat r, GLfloat q )
+{
+   GET_CURRENT;
+   DO_PROJ_TEX;
+   TEXCOORD4( s, t, r, q );
+}
+
+static void TAG(TexCoord4fv)( const GLfloat *v )
+{
+   GET_CURRENT;
+   DO_PROJ_TEX;
+   TEXCOORD4( v[0], v[1], v[2], v[3] );
+}
+
+static void TAG(MultiTexCoord4fARB)( GLenum target, GLfloat s,
+                                    GLfloat t, GLfloat r, GLfloat q )
+{
+   GET_CURRENT;
+   DO_PROJ_TEX;
+   MULTI_TEXCOORD4( unit, s, t, r, q );
+}
+
+static void TAG(MultiTexCoord4fvARB)( GLenum target, const GLfloat *v )
+{
+   GET_CURRENT;
+   DO_PROJ_TEX;
+   MULTI_TEXCOORD4( unit, v[0], v[1], v[2], v[3] );
+}
+
+
+
+#undef DO_PROJ_TEX
+#undef TAG
diff --git a/src/mesa/tnl_dd/imm/t_dd_imm_vapi.h b/src/mesa/tnl_dd/imm/t_dd_imm_vapi.h
new file mode 100644 (file)
index 0000000..95e93b1
--- /dev/null
@@ -0,0 +1,159 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.5
+ *
+ * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Gareth Hughes <gareth@valinux.com>
+ *    Keith Whitwell <keithw@valinux.com>
+ */
+
+/* Template for immediate mode vertex functions.
+ */
+
+#define DBG 0
+
+#define VERTEX( ox, oy, oz, ow )
+do {
+   GET_CURRENT_VERTEX;
+   GLfloat w;
+   GLuint mask;
+   const GLfloat * const m = ctx->_ModelProjectMatrix.m;
+
+   if (DO_FULL_MATRIX) {
+      VERTEX_CLIP(0) = m[0] * ox + m[4] * oy + m[8]  * oz + m[12] * ow;
+      VERTEX_CLIP(1) = m[1] * ox + m[5] * oy + m[9]  * oz + m[13] * ow;
+      VERTEX_CLIP(2) = m[2] * ox + m[6] * oy + m[10] * oz + m[14] * ow;
+      VERTEX_CLIP(3) = m[3] * ox + m[7] * oy + m[11] * oz + m[15] * ow;
+      w = VERTEX_CLIP(3);
+   }
+   else if (DO_NOROT_MATRIX) {
+      VERTEX_CLIP(0) = m[0] * ox                          + m[12] * ow;
+      VERTEX_CLIP(1) =             m[5] * oy              + m[13] * ow;
+      VERTEX_CLIP(2) =                         m[10] * oz + m[14] * ow;
+      VERTEX_CLIP(3) =                                              ow;
+      w = ow;
+   } 
+   else {
+      ASSERT (DO_IDENTITY_MATRIX);
+      VERTEX_CLIP(0) = ox;
+      VERTEX_CLIP(1) = oy;
+      VERTEX_CLIP(2) = oz;
+      VERTEX_CLIP(3) = ow;
+      w = ow;
+   }
+
+   mask = 0;
+   if (DO_CLIP_TEST) {
+      if ( VERTEX_CLIP(0) >  w ) mask |= CLIP_RIGHT_BIT;
+      if ( VERTEX_CLIP(0) < -w ) mask |= CLIP_LEFT_BIT;
+      if ( VERTEX_CLIP(1) >  w ) mask |= CLIP_TOP_BIT;
+      if ( VERTEX_CLIP(1) < -w ) mask |= CLIP_BOTTOM_BIT;
+      if ( VERTEX_CLIP(2) >  w ) mask |= CLIP_FAR_BIT;
+      if ( VERTEX_CLIP(2) < -w ) mask |= CLIP_NEAR_BIT;
+      VERTEX_MASK(v) = mask;
+   }
+
+   if (!mask) {
+      if (HAVE_VERTEX_WIN) {
+        if (!HAVE_HW_VIEWPORT) {
+           const GLfloat *s = GET_VIEWPORT_MATRIX();
+           if (HAVE_W && HAVE_HW_DIVIDE) {
+              VERTEX_WIN( 0 ) = s[0]  * VERTEX_CLIP( 0 ) + s[12];
+              VERTEX_WIN( 1 ) = s[5]  * VERTEX_CLIP( 1 ) + s[13];
+              VERTEX_WIN( 2 ) = s[10] * VERTEX_CLIP( 2 ) + s[14];
+              VERTEX_WIN( 3 ) = w;
+           }
+           else {
+              const GLfloat oow = 1.0/w; /* possibly opt away */
+              VERTEX_WIN( 0 ) = s[0]  * VERTEX_CLIP( 0 ) * oow + s[12];
+              VERTEX_WIN( 1 ) = s[5]  * VERTEX_CLIP( 1 ) * oow + s[13];
+              VERTEX_WIN( 2 ) = s[10] * VERTEX_CLIP( 2 ) * oow + s[14];
+              if (HAVE_W)
+                 VERTEX_WIN( 3 ) = oow;
+           }
+        }
+        else if (HAVE_W && HAVE_HW_DIVIDE) {
+           if (!VERTEX_WIN_IS_VERTEX_CLIP) {
+              VERTEX_WIN( 0 ) = VERTEX_CLIP( 0 );
+              VERTEX_WIN( 1 ) = VERTEX_CLIP( 1 );
+              VERTEX_WIN( 2 ) = VERTEX_CLIP( 2 );
+              VERTEX_WIN( 3 ) = w;
+           }
+        }
+        else {
+           const GLfloat oow = 1.0/w; /* possibly opt away */
+           VERTEX_WIN( 0 ) = VERTEX_CLIP( 0 ) * oow;
+           VERTEX_WIN( 1 ) = VERTEX_CLIP( 1 ) * oow;
+           VERTEX_WIN( 2 ) = VERTEX_CLIP( 2 ) * oow;
+           if (HAVE_W)
+              VERTEX_WIN( 3 ) = oow;
+        }
+      }
+   } else if (!FALLBACK_OR_CLIPPING) {
+      SET_CLIPPING();          /* transition to clipping */
+   }
+
+   COPY_VERTEX_FROM_CURRENT;
+   BUILD_PRIM_FROM_VERTEX;
+}
+
+/* Let the compiler optimize away the constant operations:
+ */
+static void VTAG(Vertex2f)( GLfloat ox, GLfloat oy )
+{
+   /* Cliptest on clip[2] could also be eliminated...
+    */
+   VERTEX( ox, oy, 0, 1 );
+}
+
+static void VTAG(Vertex2fv)( const GLfloat *obj )
+{
+   /* Cliptest on clip[2] could also be eliminated...
+    */
+   VERTEX( obj[0], obj[1], 0, 1 );
+}
+
+static void VTAG(Vertex3f)( GLfloat ox, GLfloat oy, GLfloat oz )
+{
+   VERTEX( ox, oy, oz, 1 );
+}
+
+static void VTAG(Vertex3fv)( const GLfloat *obj )
+{
+   VERTEX( obj[0], obj[1], obj[2], 1 );
+}
+
+static void VTAG(Vertex4f)( GLfloat ox, GLfloat oy, GLfloat oz, GLfloat ow )
+{
+   VERTEX( ox, oy, oz, ow );
+}
+
+static void VTAG(Vertex4fv)( const GLfloat *obj )
+{
+   VERTEX( obj[0], obj[1], obj[2], obj[3] );
+}
+
+
+#undef DO_FULL_MATRIX
+#undef VTAG
+#undef VERTEX
diff --git a/src/mesa/tnl_dd/imm/t_dd_imm_vb.c b/src/mesa/tnl_dd/imm/t_dd_imm_vb.c
new file mode 100644 (file)
index 0000000..0c4462f
--- /dev/null
@@ -0,0 +1,204 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.5
+ *
+ * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keith_whitwell@yahoo.com>
+ */
+
+/* Template to build clipping routines to support t_dd_imm_primtmp.h.
+ *
+ * The TAG(draw_line) and TAG(draw_triangle) routines are called in
+ * clipping and fallback scenarios, and when the native hardware
+ * primitive (eg polygons) is unavailable.
+ */
+
+
+#define CLIP_DOTPROD(K, A, B, C, D)            \
+   (CLIP_X(K)*A + CLIP_Y(K)*B +        \
+    CLIP_Z(K)*C + CLIP_W(K)*D)
+
+#define POLY_CLIP( PLANE, A, B, C, D )                                 \
+do {                                                                   \
+   if (mask & PLANE) {                                                 \
+      TNL_VERTEX **indata = inlist[in];                                        \
+      TNL_VERTEX **outdata = inlist[in ^= 1];                          \
+      TNL_VERTEX *J = indata[0];                                       \
+      GLfloat dpJ = CLIP_DOTPROD(J, A, B, C, D );                      \
+      GLuint outcount = 0;                                             \
+      GLuint i;                                                                \
+                                                                       \
+      indata[n] = indata[0]; /* prevent rotation of vertices */                \
+      for (i = 1; i <= n; i++) {                                       \
+        TNL_VERTEX *I = indata[i];                                     \
+        GLfloat dpI = CLIP_DOTPROD(idx, A, B, C, D );                  \
+                                                                       \
+        if (!NEGATIVE(dpPrev)) {                                       \
+           outdata[outcount++] = J;                                    \
+        }                                                              \
+                                                                       \
+        if (DIFFERENT_SIGNS(dpI, dpJ)) {                               \
+            TNL_VERTEX *O = verts++;                                   \
+            outdata[outcount++] = O;                                   \
+           if (NEGATIVE(dpI)) {                                        \
+              /* Going out of bounds.  Avoid division by zero as we    \
+               * know dp != dpPrev from DIFFERENT_SIGNS, above.        \
+               */                                                      \
+              GLfloat t = dpI / (dpI - dpJ);                           \
+              INTERP( ctx, t, O, I, J );                               \
+           } else {                                                    \
+              /* Coming back in.                                       \
+               */                                                      \
+              GLfloat t = dpJ / (dpJ - dpI);                           \
+              INTERP( ctx, t, O, J, I );                               \
+           }                                                           \
+        }                                                              \
+                                                                       \
+        J = I;                                                         \
+        dpJ = dpI;                                                     \
+      }                                                                        \
+                                                                       \
+      if (outcount < 3)                                                        \
+        return;                                                        \
+                                                                       \
+      nr = outcount;                                                   \
+   }                                                                   \
+} while (0)
+
+
+#define LINE_CLIP(PLANE, A, B, C, D )                  \
+do {                                                   \
+   if (mask & PLANE) {                                 \
+      GLfloat dpI = CLIP_DOTPROD( I, A, B, C, D );     \
+      GLfloat dpJ = CLIP_DOTPROD( J, A, B, C, D );     \
+                                                       \
+      if (DIFFERENT_SIGNS(dpI, dpJ)) {                 \
+         TNL_VERTEX *O = verts++;                      \
+        if (NEGATIVE(dpJ)) {                           \
+           GLfloat t = dpI / (dpI - dpJ);              \
+           INTERP( ctx, t, O, I, J );  \
+            J = O;                                     \
+        } else {                                       \
+           GLfloat t = dpJ / (dpJ - dpI);              \
+           INTERP( ctx, t, O, J, I );  \
+            I = O;                                     \
+        }                                              \
+      }                                                        \
+      else if (NEGATIVE(dpI))                          \
+        return;                                        \
+  }                                                    \
+} while (0)
+
+
+
+/* Clip a line against the viewport and user clip planes.
+ */
+static void TAG(clip_draw_line)( GLcontext *ctx,
+                                TNL_VERTEX *I,
+                                TNL_VERTEX *J,
+                                GLuint mask )
+{
+   LOCAL_VARS;
+   GET_INTERP_FUNC;
+   TNL_VERTEX tmp[MAX_CLIPPED_VERTICES];
+   TNL_VERTEX *verts = tmp;
+   TNL_VERTEX *pv = J;
+
+   LINE_CLIP( CLIP_RIGHT_BIT,  -1,  0,  0, 1 );
+   LINE_CLIP( CLIP_LEFT_BIT,    1,  0,  0, 1 );
+   LINE_CLIP( CLIP_TOP_BIT,     0, -1,  0, 1 );
+   LINE_CLIP( CLIP_BOTTOM_BIT,  0,  1,  0, 1 );
+   LINE_CLIP( CLIP_FAR_BIT,     0,  0, -1, 1 );
+   LINE_CLIP( CLIP_NEAR_BIT,    0,  0,  1, 1 );
+
+   if ((ctx->_TriangleCaps & DD_FLATSHADE) && J != pv)
+      COPY_PV( ctx, J, pv );
+
+   DRAW_LINE( I, J );
+}
+
+
+/* Clip a triangle against the viewport and user clip planes.
+ */
+static void TAG(clip_draw_triangle)( GLcontext *ctx,
+                                    TNL_VERTEX *v0,
+                                    TNL_VERTEX *v1,
+                                    TNL_VERTEX *v2,
+                                    GLuint mask )
+{
+   LOCAL_VARS;
+   GET_INTERP_FUNC;
+   TNL_VERTEX tmp[MAX_CLIPPED_VERTICES];
+   TNL_VERTEX *verts = tmp;
+   TNL_VERTEX *(inlist[2][MAX_CLIPPED_VERTICES]);
+   TNL_VERTEX **out;
+   GLuint in = 0;
+   GLuint n = 3;
+   GLuint i;
+
+   ASSIGN_3V(inlist, v2, v0, v1 ); /* pv rotated to slot zero */
+
+   POLY_CLIP( CLIP_RIGHT_BIT,  -1,  0,  0, 1 );
+   POLY_CLIP( CLIP_LEFT_BIT,    1,  0,  0, 1 );
+   POLY_CLIP( CLIP_TOP_BIT,     0, -1,  0, 1 );
+   POLY_CLIP( CLIP_BOTTOM_BIT,  0,  1,  0, 1 );
+   POLY_CLIP( CLIP_FAR_BIT,     0,  0, -1, 1 );
+   POLY_CLIP( CLIP_NEAR_BIT,    0,  0,  1, 1 );
+
+   if ((ctx->_TriangleCaps & DD_FLATSHADE) && v2 != inlist[0]) 
+      COPY_PV( ctx, inlist[0], v2 );
+
+   out = inlist[in];
+   DRAW_POLYGON( out, n );
+}
+
+
+static __inline void TAG(draw_triangle)( GLcontext *ctx,
+                                        TNL_VERTEX *v0,
+                                        TNL_VERTEX *v1,
+                                        TNL_VERTEX *v2 )
+{
+   LOCAL_VARS;
+   GLubyte ormask = (v0->mask | v1->mask | v2->mask);
+
+   if ( !ormask ) {
+      DRAW_TRI( v0, v1, v2 );
+   } else if ( !(v0->mask & v1->mask & v2->mask) ) {
+      TAG(clip_draw_triangle)( ctx, v0, v1, v2, ormask );
+   }
+}
+
+static __inline void TAG(draw_line)( GLcontext *ctx,
+                                    TNL_VERTEX *v0,
+                                    TNL_VERTEX *v1 )
+{
+   LOCAL_VARS;
+   GLubyte ormask = (v0->mask | v1->mask);
+
+   if ( !ormask ) {
+      DRAW_LINE( v0, v1 );
+   } else if ( !(v0->mask & v1->mask) ) {
+      TAG(clip_draw_line)( ctx, v0, v1, ormask );
+   }
+}
+
diff --git a/src/mesa/tnl_dd/imm/t_dd_imm_vbtmp.h b/src/mesa/tnl_dd/imm/t_dd_imm_vbtmp.h
new file mode 100644 (file)
index 0000000..2f76553
--- /dev/null
@@ -0,0 +1,268 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.5
+ *
+ * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keith_whitwell@yahoo.com>
+ */
+
+/* Template to build support for t_dd_imm_* tnl module using vertices
+ * as defined in t_dd_vertex.h.
+ *
+ * See t_dd_vbtmp.h for definitions of arguments to this file.
+ * Unfortunately it seems necessary to duplicate a lot of that code.
+ */
+
+#ifndef LOCALVARS
+#define LOCALVARS
+#endif
+
+
+
+/* COPY_VERTEX_FROM_CURRENT in t_dd_imm_vapi.c
+ */
+static void TAG(emit_vfmt)( GLcontext *ctx, VERTEX *v )
+{
+   LOCALVARS
+      ;
+
+   /* This template assumes (like t_dd_vbtmp.h) that color is ubyte.
+    */
+   if (DO_TEX0 || DO_TEX1 || !HAVE_TINY_VERTICES)
+   {
+      const GLubyte *col = GET_HARDWARE_COLOR();
+      if (HAVE_RGBA_COLOR) {
+        v->v.ui[4] = *(GLuint *)&col;
+      } else {
+        v->v.color.blue  = col[2];
+        v->v.color.green = col[1];
+        v->v.color.red   = col[0];
+        v->v.color.alpha = col[3];
+      }
+   }
+   else {
+      if (HAVE_RGBA_COLOR) {
+        v->v.ui[3] = *(GLuint *)col;
+      }
+      else {
+        v->tv.color.blue  = col[2];
+        v->tv.color.green = col[1];
+        v->tv.color.red   = col[0];
+        v->tv.color.alpha = col[3];
+      }
+   }
+
+   if (DO_TEX0) {
+      GLfloat *tc = ctx->Current.Texture[0];
+      v->v.u0 = tc[0];
+      v->v.v0 = tc[1];
+      if (DO_PTEX) {
+        if (HAVE_PTEX_VERTICES) {
+           v->pv.q0 = tc[3];
+        } 
+        else {
+           float rhw = 1.0 / tc[3];
+           v->v.w *= tc[3];
+           v->v.u0 *= rhw;
+           v->v.v0 *= rhw;
+        } 
+      } 
+   }
+   if (DO_TEX1) {
+      GLfloat *tc = ctx->Current.Texture[1];
+      if (DO_PTEX) {
+        v->pv.u1 = tc[0];
+        v->pv.v1 = tc[1];
+        v->pv.q1 = tc[3];
+      } 
+      else {
+        v->v.u1 = tc[0];
+        v->v.v1 = tc[1];
+      }
+   } 
+   else if (DO_PTEX) {
+      *(GLuint *)&v->pv.q1 = 0;        /* avoid culling on radeon */
+   }
+   if (DO_TEX2) {
+      GLfloat *tc = ctx->Current.Texture[2];
+      if (DO_PTEX) {
+        v->pv.u2 = tc[0];
+        v->pv.v2 = tc[1];
+        v->pv.q2 = tc[3];
+      } 
+      else {
+        v->v.u2 = tc[0];
+        v->v.v2 = tc[1];
+      }
+   } 
+   if (DO_TEX3) {
+      GLfloat *tc = ctx->Current.Texture[3];
+      if (DO_PTEX) {
+        v->pv.u3 = tc[0];
+        v->pv.v3 = tc[1];
+        v->pv.q3 = tc[3];
+      } 
+      else {
+        v->v.u3 = tc[0];
+        v->v.v3 = tc[1];
+      }
+   } 
+}
+
+
+
+
+static void TAG(interp)( GLcontext *ctx,
+                        GLfloat t,
+                        TNL_VERTEX *dst,
+                        TNL_VERTEX *in,
+                        TNL_VERTEX *out )
+{
+   LOCALVARS
+   const GLfloat *s = GET_VIEWPORT_MAT();
+   GLfloat w;
+
+   (void)s;
+
+   if (HAVE_HW_DIVIDE) {
+      VIEWPORT_X( dst->v.v.x, dst->clip[0] );
+      VIEWPORT_Y( dst->v.v.y, dst->clip[1] );
+      VIEWPORT_Z( dst->v.v.z, dst->clip[2] );
+      w = dstclip[3];
+   }
+   else {
+      w = 1.0 / dst->clip[3];
+      VIEWPORT_X( dst->v.v.x, dst->clip[0] * w );
+      VIEWPORT_Y( dst->v.v.y, dst->clip[1] * w );
+      VIEWPORT_Z( dst->v.v.z, dst->clip[2] * w );
+   }
+
+   if (HAVE_HW_DIVIDE || DO_TEX0) {
+
+      dst->v.v.w = w;
+
+      INTERP_UB( t, dst->v.ub4[4][0], out->v.ub4[4][0], in->v.ub4[4][0] );
+      INTERP_UB( t, dst->v.ub4[4][1], out->v.ub4[4][1], in->v.ub4[4][1] );
+      INTERP_UB( t, dst->v.ub4[4][2], out->v.ub4[4][2], in->v.ub4[4][2] );
+      INTERP_UB( t, dst->v.ub4[4][3], out->v.ub4[4][3], in->v.ub4[4][3] );
+
+      if (DO_TEX0) {
+        if (DO_PTEX) {
+           if (HAVE_PTEX_VERTICES) {
+              INTERP_F( t, dst->v.pv.u0, out->v.pv.u0, in->v.pv.u0 );
+              INTERP_F( t, dst->v.pv.v0, out->v.pv.v0, in->v.pv.v0 );
+              INTERP_F( t, dst->v.pv.q0, out->v.pv.q0, in->v.pv.q0 );
+           } else {
+              GLfloat wout = out->clip[3]; /* projected clip */
+              GLfloat win = in->clip[3]; /* projected clip */
+              GLfloat qout = out->v.pv.w / wout;
+              GLfloat qin = in->v.pv.w / win;
+              GLfloat qdst, rqdst;
+
+              ASSERT( !HAVE_HW_DIVIDE ); /* assert win, wout projected clip */
+
+              INTERP_F( t, dst->v.v.u0, out->v.v.u0 * qout, in->v.v.u0 * qin );
+              INTERP_F( t, dst->v.v.v0, out->v.v.v0 * qout, in->v.v.v0 * qin );
+              INTERP_F( t, qdst, qout, qin );
+
+              rqdst = 1.0 / qdst;
+              dst->v.v.u0 *= rqdst;
+              dst->v.v.v0 *= rqdst;
+              dst->v.v.w *= rqdst;
+           }
+        }
+        else {
+           INTERP_F( t, dst->v.v.u0, out->v.v.u0, in->v.v.u0 );
+           INTERP_F( t, dst->v.v.v0, out->v.v.v0, in->v.v.v0 );
+        }
+      }
+      if (DO_TEX1) {
+        if (DO_PTEX) {
+           INTERP_F( t, dst->v.pv.u1, out->v.pv.u1, in->v.pv.u1 );
+           INTERP_F( t, dst->v.pv.v1, out->v.pv.v1, in->v.pv.v1 );
+           INTERP_F( t, dst->v.pv.q1, out->v.pv.q1, in->v.pv.q1 );
+        } else {
+           INTERP_F( t, dst->v.v.u1, out->v.v.u1, in->v.v.u1 );
+           INTERP_F( t, dst->v.v.v1, out->v.v.v1, in->v.v.v1 );
+        }
+      }
+      else if (DO_PTEX) {
+        dst->v.pv.q0 = 0.0;    /* must be a valid float on radeon */
+      }
+      if (DO_TEX2) {
+        if (DO_PTEX) {
+           INTERP_F( t, dst->v.pv.u2, out->v.pv.u2, in->v.pv.u2 );
+           INTERP_F( t, dst->v.pv.v2, out->v.pv.v2, in->v.pv.v2 );
+           INTERP_F( t, dst->v.pv.q2, out->v.pv.q2, in->v.pv.q2 );
+        } else {
+           INTERP_F( t, dst->v.v.u2, out->v.v.u2, in->v.v.u2 );
+           INTERP_F( t, dst->v.v.v2, out->v.v.v2, in->v.v.v2 );
+        }
+      }
+      if (DO_TEX3) {
+        if (DO_PTEX) {
+           INTERP_F( t, dst->v.pv.u3, out->v.pv.u3, in->v.pv.u3 );
+           INTERP_F( t, dst->v.pv.v3, out->v.pv.v3, in->v.pv.v3 );
+           INTERP_F( t, dst->v.pv.q3, out->v.pv.q3, in->v.pv.q3 );
+        } else {
+           INTERP_F( t, dst->v.v.u3, out->v.v.u3, in->v.v.u3 );
+           INTERP_F( t, dst->v.v.v3, out->v.v.v3, in->v.v.v3 );
+        }
+      }
+   } else {
+      /* 4-dword vertex.  Color is in v[3] and there is no oow coordinate.
+       */
+      INTERP_UB( t, dst->v.ub4[3][0], out->v.ub4[3][0], in->v.ub4[3][0] );
+      INTERP_UB( t, dst->v.ub4[3][1], out->v.ub4[3][1], in->v.ub4[3][1] );
+      INTERP_UB( t, dst->v.ub4[3][2], out->v.ub4[3][2], in->v.ub4[3][2] );
+      INTERP_UB( t, dst->v.ub4[3][3], out->v.ub4[3][3], in->v.ub4[3][3] );
+   }
+}
+
+
+static __inline void TAG(copy_pv)( GLcontext *ctx,
+                                  TNL_VERTEX *dst, 
+                                  TNL_VERTEX *src )
+{
+   if (DO_TEX0 || DO_TEX1 || !HAVE_TINY_VERTICES) {
+      dst->v.v.ui[4] = src->v.v.ui[4];
+   }
+   else {
+      dst->v.v.ui[3] = src->v.v.ui[3];
+   }
+}
+
+
+
+static void TAG(init)( void )
+{
+   setup_tab[IND].emit = TAG(emit_vfmt);
+   setup_tab[IND].interp = TAG(interp_vfmt);
+}
+
+
+#undef IND
+#undef TAG
+
+
+
diff --git a/src/mesa/tnl_dd/t_dd.c b/src/mesa/tnl_dd/t_dd.c
new file mode 100644 (file)
index 0000000..731da5c
--- /dev/null
@@ -0,0 +1,58 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.5
+ *
+ * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+static void copy_pv_rgba4_spec5( GLcontext *ctx, GLuint edst, GLuint esrc )
+{
+   i810ContextPtr imesa = I810_CONTEXT( ctx );
+   GLubyte *i810verts = (GLubyte *)imesa->verts;
+   GLuint shift = imesa->vertex_stride_shift;
+   i810Vertex *dst = (i810Vertex *)(i810verts + (edst << shift));
+   i810Vertex *src = (i810Vertex *)(i810verts + (esrc << shift));
+   dst->ui[4] = src->ui[4];
+   dst->ui[5] = src->ui[5];
+}
+
+static void copy_pv_rgba4( GLcontext *ctx, GLuint edst, GLuint esrc )
+{
+   i810ContextPtr imesa = I810_CONTEXT( ctx );
+   GLubyte *i810verts = (GLubyte *)imesa->verts;
+   GLuint shift = imesa->vertex_stride_shift;
+   i810Vertex *dst = (i810Vertex *)(i810verts + (edst << shift));
+   i810Vertex *src = (i810Vertex *)(i810verts + (esrc << shift));
+   dst->ui[4] = src->ui[4];
+}
+
+static void copy_pv_rgba3( GLcontext *ctx, GLuint edst, GLuint esrc )
+{
+   i810ContextPtr imesa = I810_CONTEXT( ctx );
+   GLubyte *i810verts = (GLubyte *)imesa->verts;
+   GLuint shift = imesa->vertex_stride_shift;
+   i810Vertex *dst = (i810Vertex *)(i810verts + (edst << shift));
+   i810Vertex *src = (i810Vertex *)(i810verts + (esrc << shift));
+   dst->ui[3] = src->ui[3];
+}
diff --git a/src/mesa/tnl_dd/t_dd_dmatmp.h b/src/mesa/tnl_dd/t_dd_dmatmp.h
new file mode 100644 (file)
index 0000000..d9f7093
--- /dev/null
@@ -0,0 +1,1105 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.5
+ *
+ * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+/* Template for render stages which build and emit vertices directly
+ * to fixed-size dma buffers.  Useful for rendering strips and other
+ * native primitives where clipping and per-vertex tweaks such as
+ * those in t_dd_tritmp.h are not required.
+ *
+ * Produces code for both inline triangles and indexed triangles.
+ * Where various primitive types are unaccelerated by hardware, the
+ * code attempts to fallback to other primitive types (quadstrips to
+ * tristrips, lineloops to linestrips), or to indexed vertices.
+ * Ultimately, a FALLBACK() macro is invoked if there is no way to
+ * render the primitive natively.
+ */
+
+#if !defined(HAVE_TRIANGLES)
+#error "must have at least triangles to use render template"
+#endif
+
+#if !HAVE_ELTS
+#define ELTS_VARS
+#define ALLOC_ELTS( nr )
+#define EMIT_ELT( offset, elt )
+#define EMIT_TWO_ELTS( offset, elt0, elt1 )
+#define INCR_ELTS( nr )
+#define ELT_INIT(prim)
+#define GET_CURRENT_VB_MAX_ELTS() 0
+#define GET_SUBSEQUENT_VB_MAX_ELTS() 0
+#define ALLOC_ELTS_NEW_PRIMITIVE(nr)
+#define RELEASE_ELT_VERTS()
+#define EMIT_INDEXED_VERTS( ctx, start, count )
+#endif
+
+#ifndef EMIT_TWO_ELTS
+#define EMIT_TWO_ELTS( offset, elt0, elt1 )    \
+do {                                           \
+   EMIT_ELT( offset, elt0 );                   \
+   EMIT_ELT( offset+1, elt1 );                         \
+} while (0)
+#endif
+
+#ifndef FINISH
+#define FINISH
+#endif
+
+/**********************************************************************/
+/*                  Render whole begin/end objects                    */
+/**********************************************************************/
+
+
+
+static GLboolean TAG(emit_elt_verts)( GLcontext *ctx,
+                                     GLuint start, GLuint count )
+{
+   if (HAVE_ELTS) {
+      LOCAL_VARS;
+      GLuint nr = count - start;
+
+      if ( nr >= GET_SUBSEQUENT_VB_MAX_VERTS() ) /* assumes same packing for
+                                                 * indexed and regualar verts
+                                                 */
+        return GL_FALSE;
+
+      NEW_PRIMITIVE(); /* finish last prim */
+      EMIT_INDEXED_VERTS( ctx, start, count );
+      return GL_TRUE;
+   } else {
+      return GL_FALSE;
+   }
+}
+
+#if (HAVE_ELTS)
+static void TAG(emit_elts)( GLcontext *ctx, GLuint *elts, GLuint nr )
+{
+   GLint i;
+   LOCAL_VARS;
+   ELTS_VARS;
+
+   ALLOC_ELTS( nr );
+
+   for ( i = 0 ; i < nr ; i+=2, elts += 2 ) {
+      EMIT_TWO_ELTS( 0, elts[0], elts[1] );
+      INCR_ELTS( 2 );
+   }
+}
+#endif
+
+
+/***********************************************************************
+ *                    Render non-indexed primitives.
+ ***********************************************************************/
+
+
+
+static void TAG(render_points_verts)( GLcontext *ctx,
+                                     GLuint start,
+                                     GLuint count,
+                                     GLuint flags )
+{
+   if (HAVE_POINTS) {
+      LOCAL_VARS;
+      int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS();
+      int currentsz = GET_CURRENT_VB_MAX_VERTS();
+      GLuint j, nr;
+
+      INIT( GL_POINTS );
+
+      if (currentsz < 8)
+        currentsz = dmasz;
+
+      for (j = start; j < count; j += nr ) {
+        nr = MIN2( currentsz, count - j );
+        EMIT_VERTS( ctx, j, nr );
+        currentsz = dmasz;
+      }
+
+      FINISH;
+
+   } else {
+      VERT_FALLBACK( ctx, start, count, flags );
+   }
+}
+
+static void TAG(render_lines_verts)( GLcontext *ctx,
+                                    GLuint start,
+                                    GLuint count,
+                                    GLuint flags )
+{
+   if (HAVE_LINES) {
+      LOCAL_VARS;
+      int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS();
+      int currentsz = GET_CURRENT_VB_MAX_VERTS();
+      GLuint j, nr;
+
+      INIT( GL_LINES );
+
+      /* Emit whole number of lines in total and in each buffer:
+       */
+      count -= (count-start) & 1;
+      currentsz -= currentsz & 1;
+      dmasz -= dmasz & 1;
+
+      if (currentsz < 8)
+        currentsz = dmasz;
+
+      for (j = start; j < count; j += nr ) {
+        nr = MIN2( currentsz, count - j );
+        EMIT_VERTS( ctx, j, nr );
+        currentsz = dmasz;
+      }
+
+      FINISH;
+
+   } else {
+      VERT_FALLBACK( ctx, start, count, flags );
+   }
+}
+
+
+static void TAG(render_line_strip_verts)( GLcontext *ctx,
+                                         GLuint start,
+                                         GLuint count,
+                                         GLuint flags )
+{
+   if (HAVE_LINE_STRIPS) {
+      LOCAL_VARS;
+      int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS();
+      int currentsz = GET_CURRENT_VB_MAX_VERTS();
+      GLuint j, nr;
+
+      NEW_PRIMITIVE(); /* always a new primitive */
+      INIT( GL_LINE_STRIP );
+
+      if (currentsz < 8)
+        currentsz = dmasz;
+
+      for (j = start; j + 1 < count; j += nr - 1 ) {
+        nr = MIN2( currentsz, count - j );
+        EMIT_VERTS( ctx, j, nr );
+        currentsz = dmasz;
+      }
+      FINISH;
+
+   } else {
+      VERT_FALLBACK( ctx, start, count, flags );
+   }
+}
+
+
+static void TAG(render_line_loop_verts)( GLcontext *ctx,
+                                        GLuint start,
+                                        GLuint count,
+                                        GLuint flags )
+{
+   if (HAVE_LINE_STRIPS) {
+      LOCAL_VARS;
+      int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS();
+      int currentsz = GET_CURRENT_VB_MAX_VERTS();
+      GLuint j, nr;
+
+      NEW_PRIMITIVE();
+      INIT( GL_LINE_STRIP );
+
+      if (flags & PRIM_BEGIN)
+        j = start;
+      else
+        j = start + 1;
+
+      /* Ensure last vertex won't wrap buffers:
+       */
+      currentsz--;
+      dmasz--;
+
+      if (currentsz < 8) {
+        NEW_BUFFER();
+        currentsz = dmasz;
+      }
+
+      if (j + 1 < count) {
+        for ( ; j + 1 < count; j += nr - 1 ) {
+           nr = MIN2( currentsz, count - j );
+           EMIT_VERTS( ctx, j, nr );
+           currentsz = dmasz;
+        }
+
+        if (start < count - 1 && (flags & PRIM_END))
+           EMIT_VERTS( ctx, start, 1 );
+      }
+      else if (start + 1 < count && (flags & PRIM_END)) {
+        EMIT_VERTS( ctx, start+1, 1 );
+        EMIT_VERTS( ctx, start, 1 );
+      }
+
+      FINISH;
+
+   } else {
+      VERT_FALLBACK( ctx, start, count, flags );
+   }
+}
+
+
+static void TAG(render_triangles_verts)( GLcontext *ctx,
+                                        GLuint start,
+                                        GLuint count,
+                                        GLuint flags )
+{
+   LOCAL_VARS;
+   int dmasz = (GET_SUBSEQUENT_VB_MAX_VERTS()/3) * 3;
+   int currentsz = (GET_CURRENT_VB_MAX_VERTS()/3) * 3;
+   GLuint j, nr;
+
+   INIT(GL_TRIANGLES);
+
+   /* Emit whole number of tris in total.  dmasz is already a multiple
+    * of 3.
+    */
+   count -= (count-start)%3;
+
+   if (currentsz < 8)
+      currentsz = dmasz;
+
+   for (j = start; j < count; j += nr) {
+      nr = MIN2( currentsz, count - j );
+      EMIT_VERTS( ctx, j, nr );
+      currentsz = dmasz;
+   }
+   FINISH;
+}
+
+
+
+static void TAG(render_tri_strip_verts)( GLcontext *ctx,
+                                        GLuint start,
+                                        GLuint count,
+                                        GLuint flags )
+{
+   if (HAVE_TRI_STRIPS) {
+      LOCAL_VARS;
+      GLuint j, nr;
+      int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS();
+      int currentsz;
+
+      INIT(GL_TRIANGLE_STRIP);
+      NEW_PRIMITIVE();
+
+      currentsz = GET_CURRENT_VB_MAX_VERTS();
+
+      if (currentsz < 8) {
+        NEW_BUFFER();
+        currentsz = dmasz;
+      }
+
+      if ((flags & PRIM_PARITY) && count - start > 2) {
+        if (HAVE_TRI_STRIP_1 && 0) {
+        } else {
+           EMIT_VERTS( ctx, start, 1 );
+           currentsz--;
+        }
+      }
+
+      /* From here on emit even numbers of tris when wrapping over buffers:
+       */
+      dmasz -= (dmasz & 1);
+      currentsz -= (currentsz & 1);
+
+      for (j = start ; j + 2 < count; j += nr - 2 ) {
+        nr = MIN2( currentsz, count - j );
+        EMIT_VERTS( ctx, j, nr );
+        currentsz = dmasz;
+      }
+
+      FINISH;
+
+   } else {
+      VERT_FALLBACK( ctx, start, count, flags );
+   }
+}
+
+static void TAG(render_tri_fan_verts)( GLcontext *ctx,
+                                      GLuint start,
+                                      GLuint count,
+                                      GLuint flags )
+{
+   if (HAVE_TRI_FANS) {
+      LOCAL_VARS;
+      GLuint j, nr;
+      int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS();
+      int currentsz = GET_CURRENT_VB_MAX_VERTS();
+
+      NEW_PRIMITIVE();
+      INIT(GL_TRIANGLE_FAN);
+
+      if (currentsz < 8) {
+        NEW_BUFFER();
+        currentsz = dmasz;
+      }
+
+      for (j = start + 1 ; j + 1 < count; j += nr - 1 ) {
+        nr = MIN2( currentsz, count - j + 1 );
+        EMIT_VERTS( ctx, start, 1 );
+        EMIT_VERTS( ctx, j, nr - 1 );
+        currentsz = dmasz;
+      }
+
+      FINISH;
+
+   }
+   else {
+      /* Could write code to emit these as indexed vertices (for the
+       * g400, for instance).
+       */
+      VERT_FALLBACK( ctx, start, count, flags );
+   }
+}
+
+
+static void TAG(render_poly_verts)( GLcontext *ctx,
+                                   GLuint start,
+                                   GLuint count,
+                                   GLuint flags )
+{
+   if (HAVE_POLYGONS) {
+      LOCAL_VARS;
+      GLuint j, nr;
+      int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS();
+      int currentsz = GET_CURRENT_VB_MAX_VERTS();
+
+      NEW_PRIMITIVE();
+      INIT(GL_POLYGON);
+
+      if (currentsz < 8) {
+        NEW_BUFFER();
+        currentsz = dmasz;
+      }
+
+      for (j = start + 1 ; j + 1 < count ; j += nr - 1 ) {
+        nr = MIN2( currentsz, count - j + 1 );
+        EMIT_VERTS( ctx, start, 1 );
+        EMIT_VERTS( ctx, j, nr - 1 );
+        currentsz = dmasz;
+      }
+
+      FINISH;
+
+   }
+   else if (HAVE_TRI_FANS && !(ctx->_TriangleCaps & DD_FLATSHADE)) {
+      TAG(render_tri_fan_verts)( ctx, start, count, flags );
+   } else {
+      VERT_FALLBACK( ctx, start, count, flags );
+   }
+}
+
+static void TAG(render_quad_strip_verts)( GLcontext *ctx,
+                                         GLuint start,
+                                         GLuint count,
+                                         GLuint flags )
+{
+   GLuint j, nr;
+
+   if (HAVE_QUAD_STRIPS) {
+      LOCAL_VARS;
+      GLuint j, nr;
+      int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS();
+      int currentsz;
+
+      INIT(GL_QUAD_STRIP);
+      NEW_PRIMITIVE();
+
+      currentsz = GET_CURRENT_VB_MAX_VERTS();
+
+      if (currentsz < 8) {
+        NEW_BUFFER();
+        currentsz = dmasz;
+      }
+
+      dmasz -= (dmasz & 2);
+      currentsz -= (currentsz & 2);
+
+      for (j = start ; j + 3 < count; j += nr - 2 ) {
+        nr = MIN2( currentsz, count - j );
+        EMIT_VERTS( ctx, j, nr );
+        currentsz = dmasz;
+      }
+
+      FINISH;
+
+   } else if (HAVE_TRI_STRIPS && (ctx->_TriangleCaps & DD_FLATSHADE)) {
+      if (TAG(emit_elt_verts)( ctx, start, count )) {
+        LOCAL_VARS;
+        int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
+        int currentsz;
+        GLuint j, nr;
+
+        /* Simulate flat-shaded quadstrips using indexed vertices:
+         */
+        NEW_PRIMITIVE();
+        ELT_INIT( GL_TRIANGLES );
+
+        currentsz = GET_CURRENT_VB_MAX_ELTS();
+
+        /* Emit whole number of quads in total, and in each buffer.
+         */
+        dmasz -= dmasz & 1;
+        count -= (count-start) & 1;
+        currentsz -= currentsz & 1;
+
+        if (currentsz < 12)
+           currentsz = dmasz;
+
+        currentsz = currentsz/6*2;
+        dmasz = dmasz/6*2;
+
+        for (j = start; j + 3 < count; j += nr - 2 ) {
+           nr = MIN2( currentsz, count - j );
+           if (nr >= 4) {
+              GLint quads = (nr/2)-1;
+              GLint i;
+              ELTS_VARS;
+
+              NEW_PRIMITIVE();
+              ALLOC_ELTS_NEW_PRIMITIVE( quads*6 );
+
+              for ( i = j-start ; i < j-start+quads*2 ; i+=2 ) {
+                 EMIT_TWO_ELTS( 0, (i+0), (i+1) );
+                 EMIT_TWO_ELTS( 2, (i+2), (i+1) );
+                 EMIT_TWO_ELTS( 4, (i+3), (i+2) );
+                 INCR_ELTS( 6 );
+              }
+
+              NEW_PRIMITIVE();
+           }
+           currentsz = dmasz;
+        }
+
+        RELEASE_ELT_VERTS();
+      }
+      else {
+        /* Vertices won't fit in a single buffer or elts not available,
+         * VERT_FALLBACK.
+         */
+        VERT_FALLBACK( ctx, start, count, flags );
+      }
+   }
+   else if (HAVE_TRI_STRIPS) {
+      LOCAL_VARS;
+      int dmasz = GET_SUBSEQUENT_VB_MAX_VERTS();
+      int currentsz = GET_CURRENT_VB_MAX_VERTS();
+
+      /* Emit smooth-shaded quadstrips as tristrips:
+       */
+      NEW_PRIMITIVE();
+      INIT( GL_TRIANGLE_STRIP );
+
+      /* Emit whole number of quads in total, and in each buffer.
+       */
+      dmasz -= dmasz & 1;
+      currentsz -= currentsz & 1;
+      count -= (count-start) & 1;
+
+      if (currentsz < 8) {
+        NEW_BUFFER();
+        currentsz = dmasz;
+      }
+
+      for (j = start; j + 3 < count; j += nr - 2 ) {
+        nr = MIN2( currentsz, count - j );
+        EMIT_VERTS( ctx, j, nr );
+        currentsz = dmasz;
+      }
+
+      FINISH;
+
+   } else {
+      VERT_FALLBACK( ctx, start, count, flags );
+   }
+}
+
+
+static void TAG(render_quads_verts)( GLcontext *ctx,
+                                    GLuint start,
+                                    GLuint count,
+                                    GLuint flags )
+{
+   if (HAVE_QUADS) {
+      LOCAL_VARS;
+      int dmasz = (GET_SUBSEQUENT_VB_MAX_VERTS()/4) * 4;
+      int currentsz = (GET_CURRENT_VB_MAX_VERTS()/4) * 4;
+      GLuint j, nr;
+
+      INIT(GL_QUADS);
+
+      /* Emit whole number of quads in total.  dmasz is already a multiple
+       * of 4.
+       */
+      count -= (count-start)%4;
+
+      if (currentsz < 8)
+         currentsz = dmasz;
+
+      for (j = start; j < count; j += nr) {
+         nr = MIN2( currentsz, count - j );
+         EMIT_VERTS( ctx, j, nr );
+         currentsz = dmasz;
+      }
+      FINISH;
+   } else if (TAG(emit_elt_verts)( ctx, start, count )) {
+      /* Hardware doesn't have a quad primitive type -- try to
+       * simulate it using indexed vertices and the triangle
+       * primitive:
+       */
+      LOCAL_VARS;
+      int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
+      int currentsz;
+      GLuint j, nr;
+
+      NEW_PRIMITIVE();
+      ELT_INIT( GL_TRIANGLES );
+      currentsz = GET_CURRENT_VB_MAX_ELTS();
+
+      /* Emit whole number of quads in total, and in each buffer.
+       */
+      dmasz -= dmasz & 3;
+      count -= (count-start) & 3;
+      currentsz -= currentsz & 3;
+
+      /* Adjust for rendering as triangles:
+       */
+      currentsz = currentsz/6*4;
+      dmasz = dmasz/6*4;
+
+      if (currentsz < 8)
+        currentsz = dmasz;
+
+      for (j = start; j < count; j += nr ) {
+        nr = MIN2( currentsz, count - j );
+        if (nr >= 4) {
+           GLint quads = nr/4;
+           GLint i;
+           ELTS_VARS;
+
+           NEW_PRIMITIVE();
+           ALLOC_ELTS_NEW_PRIMITIVE( quads*6 );
+
+           for ( i = j-start ; i < j-start+quads*4 ; i+=4 ) {
+              EMIT_TWO_ELTS( 0, (i+0), (i+1) );
+              EMIT_TWO_ELTS( 2, (i+3), (i+1) );
+              EMIT_TWO_ELTS( 4, (i+2), (i+3) );
+              INCR_ELTS( 6 );
+           }
+
+           NEW_PRIMITIVE();
+        }
+        currentsz = dmasz;
+      }
+
+      RELEASE_ELT_VERTS();
+   }
+   else {
+      /* Vertices won't fit in a single buffer, fallback.
+       */
+      VERT_FALLBACK( ctx, start, count, flags );
+   }
+}
+
+static void TAG(render_noop)( GLcontext *ctx,
+                             GLuint start,
+                             GLuint count,
+                             GLuint flags )
+{
+}
+
+
+
+
+static render_func TAG(render_tab_verts)[GL_POLYGON+2] =
+{
+   TAG(render_points_verts),
+   TAG(render_lines_verts),
+   TAG(render_line_loop_verts),
+   TAG(render_line_strip_verts),
+   TAG(render_triangles_verts),
+   TAG(render_tri_strip_verts),
+   TAG(render_tri_fan_verts),
+   TAG(render_quads_verts),
+   TAG(render_quad_strip_verts),
+   TAG(render_poly_verts),
+   TAG(render_noop),
+};
+
+
+/****************************************************************************
+ *                 Render elts using hardware indexed verts                 *
+ ****************************************************************************/
+
+#if (HAVE_ELTS)
+static void TAG(render_points_elts)( GLcontext *ctx,
+                                    GLuint start,
+                                    GLuint count,
+                                    GLuint flags )
+{
+   if (HAVE_POINTS) {
+      LOCAL_VARS;
+      int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
+      int currentsz;
+      GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
+      GLuint j, nr;
+
+      ELT_INIT( GL_POINTS );
+
+      currentsz = GET_CURRENT_VB_MAX_ELTS();
+      if (currentsz < 8)
+        currentsz = dmasz;
+
+      for (j = start; j < count; j += nr ) {
+        nr = MIN2( currentsz, count - j );
+        TAG(emit_elts)( ctx, elts+j, nr );
+        NEW_PRIMITIVE();
+        currentsz = dmasz;
+      }
+   } else {
+      ELT_FALLBACK( ctx, start, count, flags );
+   }
+}
+
+
+
+static void TAG(render_lines_elts)( GLcontext *ctx,
+                                   GLuint start,
+                                   GLuint count,
+                                   GLuint flags )
+{
+   if (HAVE_LINES) {
+      LOCAL_VARS;
+      int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
+      int currentsz;
+      GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
+      GLuint j, nr;
+
+      ELT_INIT( GL_LINES );
+
+      /* Emit whole number of lines in total and in each buffer:
+       */
+      count -= (count-start) & 1;
+      currentsz -= currentsz & 1;
+      dmasz -= dmasz & 1;
+
+      currentsz = GET_CURRENT_VB_MAX_ELTS();
+      if (currentsz < 8)
+        currentsz = dmasz;
+
+      for (j = start; j < count; j += nr ) {
+        nr = MIN2( currentsz, count - j );
+        TAG(emit_elts)( ctx, elts+j, nr );
+        NEW_PRIMITIVE();
+        currentsz = dmasz;
+      }
+   } else {
+      ELT_FALLBACK( ctx, start, count, flags );
+   }
+}
+
+
+static void TAG(render_line_strip_elts)( GLcontext *ctx,
+                                        GLuint start,
+                                        GLuint count,
+                                        GLuint flags )
+{
+   if (HAVE_LINE_STRIPS) {
+      LOCAL_VARS;
+      int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
+      int currentsz;
+      GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
+      GLuint j, nr;
+
+      NEW_PRIMITIVE(); /* always a new primitive */
+      ELT_INIT( GL_LINE_STRIP );
+
+      currentsz = GET_CURRENT_VB_MAX_ELTS();
+      if (currentsz < 8)
+        currentsz = dmasz;
+
+      for (j = start; j + 1 < count; j += nr - 1 ) {
+        nr = MIN2( currentsz, count - j );
+        TAG(emit_elts)( ctx, elts+j, nr );
+        NEW_PRIMITIVE();
+        currentsz = dmasz;
+      }
+   } else {
+      /* TODO: Try to emit as indexed lines.
+       */
+      ELT_FALLBACK( ctx, start, count, flags );
+   }
+}
+
+
+static void TAG(render_line_loop_elts)( GLcontext *ctx,
+                                       GLuint start,
+                                       GLuint count,
+                                       GLuint flags )
+{
+   if (HAVE_LINE_STRIPS) {
+      LOCAL_VARS;
+      int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
+      int currentsz;
+      GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
+      GLuint j, nr;
+
+      NEW_PRIMITIVE();
+      ELT_INIT( GL_LINE_STRIP );
+
+      if (flags & PRIM_BEGIN)
+        j = start;
+      else
+        j = start + 1;
+
+      currentsz = GET_CURRENT_VB_MAX_ELTS();
+      if (currentsz < 8) {
+        NEW_BUFFER();
+        currentsz = dmasz;
+      }
+
+      /* Ensure last vertex doesn't wrap:
+       */
+      currentsz--;
+      dmasz--;
+
+      for ( ; j + 1 < count; j += nr - 1 ) {
+        nr = MIN2( currentsz, count - j );
+/*      NEW_PRIMITIVE(); */
+        TAG(emit_elts)( ctx, elts+j, nr );
+        currentsz = dmasz;
+      }
+
+      if (flags & PRIM_END)
+        TAG(emit_elts)( ctx, elts+start, 1 );
+
+      NEW_PRIMITIVE();
+   } else {
+      /* TODO: Try to emit as indexed lines */
+      ELT_FALLBACK( ctx, start, count, flags );
+   }
+}
+
+
+/* For verts, we still eliminate the copy from main memory to dma
+ * buffers.  For elts, this is probably no better (worse?) than the
+ * standard path.
+ */
+static void TAG(render_triangles_elts)( GLcontext *ctx,
+                                       GLuint start,
+                                       GLuint count,
+                                       GLuint flags )
+{
+   LOCAL_VARS;
+   GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
+   int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS()/3*3;
+   int currentsz;
+   GLuint j, nr;
+
+   NEW_PRIMITIVE();
+   ELT_INIT( GL_TRIANGLES );
+
+   currentsz = GET_CURRENT_VB_MAX_ELTS();
+
+   /* Emit whole number of tris in total.  dmasz is already a multiple
+    * of 3.
+    */
+   count -= (count-start)%3;
+   currentsz -= currentsz%3;
+   if (currentsz < 8)
+      currentsz = dmasz;
+
+   for (j = start; j < count; j += nr) {
+      nr = MIN2( currentsz, count - j );
+      TAG(emit_elts)( ctx, elts+j, nr );
+      NEW_PRIMITIVE();
+      currentsz = dmasz;
+   }
+}
+
+
+
+static void TAG(render_tri_strip_elts)( GLcontext *ctx,
+                                       GLuint start,
+                                       GLuint count,
+                                       GLuint flags )
+{
+   if (HAVE_TRI_STRIPS) {
+      LOCAL_VARS;
+      GLuint j, nr;
+      GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
+      int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
+      int currentsz;
+
+      NEW_PRIMITIVE();
+      ELT_INIT( GL_TRIANGLE_STRIP );
+
+      currentsz = GET_CURRENT_VB_MAX_ELTS();
+      if (currentsz < 8) {
+        NEW_BUFFER();
+        currentsz = dmasz;
+      }
+
+      if ((flags & PRIM_PARITY) && count - start > 2) {
+        TAG(emit_elts)( ctx, elts+start, 1 );
+      }
+
+      /* Keep the same winding over multiple buffers:
+       */
+      dmasz -= (dmasz & 1);
+      currentsz -= (currentsz & 1);
+
+      for (j = start ; j + 2 < count; j += nr - 2 ) {
+        nr = MIN2( currentsz, count - j );
+        TAG(emit_elts)( ctx, elts+j, nr );
+        NEW_PRIMITIVE();
+        currentsz = dmasz;
+      }
+   } else {
+      /* TODO: try to emit as indexed triangles */
+      ELT_FALLBACK( ctx, start, count, flags );
+   }
+}
+
+static void TAG(render_tri_fan_elts)( GLcontext *ctx,
+                                     GLuint start,
+                                     GLuint count,
+                                     GLuint flags )
+{
+   if (HAVE_TRI_FANS) {
+      LOCAL_VARS;
+      GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
+      GLuint j, nr;
+      int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
+      int currentsz;
+
+      NEW_PRIMITIVE();
+      ELT_INIT( GL_TRIANGLE_FAN );
+
+      currentsz = GET_CURRENT_VB_MAX_ELTS();
+      if (currentsz < 8) {
+        NEW_BUFFER();
+        currentsz = dmasz;
+      }
+
+      for (j = start + 1 ; j + 1 < count; j += nr - 1 ) {
+        nr = MIN2( currentsz, count - j + 1 );
+        TAG(emit_elts)( ctx, elts+start, 1 );
+        TAG(emit_elts)( ctx, elts+j, nr - 1 );
+        NEW_PRIMITIVE();
+        currentsz = dmasz;
+      }
+   } else {
+      /* TODO: try to emit as indexed triangles */
+      ELT_FALLBACK( ctx, start, count, flags );
+   }
+}
+
+
+static void TAG(render_poly_elts)( GLcontext *ctx,
+                                  GLuint start,
+                                  GLuint count,
+                                  GLuint flags )
+{
+   if (HAVE_POLYGONS && 0) {
+   } else if (HAVE_TRI_FANS && !(ctx->_TriangleCaps & DD_FLATSHADE)) {
+      LOCAL_VARS;
+      GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
+      GLuint j, nr;
+      int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
+      int currentsz;
+
+      NEW_PRIMITIVE();
+      ELT_INIT( GL_TRIANGLE_FAN );
+
+      currentsz = GET_CURRENT_VB_MAX_ELTS();
+      if (currentsz < 8) {
+        NEW_BUFFER();
+        currentsz = dmasz;
+      }
+
+      for (j = start + 1 ; j + 1 < count ; j += nr - 1 ) {
+        nr = MIN2( currentsz, count - j + 1 );
+        TAG(emit_elts)( ctx, elts+start, 1 );
+        TAG(emit_elts)( ctx, elts+j, nr - 1 );
+        NEW_PRIMITIVE();
+        currentsz = dmasz;
+      }
+   } else {
+      ELT_FALLBACK( ctx, start, count, flags );
+   }
+}
+
+static void TAG(render_quad_strip_elts)( GLcontext *ctx,
+                                        GLuint start,
+                                        GLuint count,
+                                        GLuint flags )
+{
+   if (HAVE_QUAD_STRIPS && 0) {
+   }
+   else if (HAVE_TRI_STRIPS) {
+      LOCAL_VARS;
+      GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
+      int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
+      int currentsz;
+      GLuint j, nr;
+
+      NEW_PRIMITIVE();
+      currentsz = GET_CURRENT_VB_MAX_ELTS();
+
+      /* Emit whole number of quads in total, and in each buffer.
+       */
+      dmasz -= dmasz & 1;
+      count -= (count-start) & 1;
+      currentsz -= currentsz & 1;
+
+      if (currentsz < 12)
+        currentsz = dmasz;
+
+      if (ctx->_TriangleCaps & DD_FLATSHADE) {
+        ELT_INIT( GL_TRIANGLES );
+
+        currentsz = currentsz/6*2;
+        dmasz = dmasz/6*2;
+
+        for (j = start; j + 3 < count; j += nr - 2 ) {
+           nr = MIN2( currentsz, count - j );
+
+           if (nr >= 4)
+           {
+              GLint i;
+              GLint quads = (nr/2)-1;
+              ELTS_VARS;
+
+
+              NEW_PRIMITIVE();
+              ALLOC_ELTS_NEW_PRIMITIVE( quads*6 );
+
+              for ( i = j-start ; i < j-start+quads ; i++, elts += 2 ) {
+                 EMIT_TWO_ELTS( 0, elts[0], elts[1] );
+                 EMIT_TWO_ELTS( 2, elts[2], elts[1] );
+                 EMIT_TWO_ELTS( 4, elts[3], elts[2] );
+                 INCR_ELTS( 6 );
+              }
+
+              NEW_PRIMITIVE();
+           }
+
+           currentsz = dmasz;
+        }
+      }
+      else {
+        ELT_INIT( GL_TRIANGLE_STRIP );
+
+        for (j = start; j + 3 < count; j += nr - 2 ) {
+           nr = MIN2( currentsz, count - j );
+           TAG(emit_elts)( ctx, elts+j, nr );
+           NEW_PRIMITIVE();
+           currentsz = dmasz;
+        }
+      }
+   }
+}
+
+
+static void TAG(render_quads_elts)( GLcontext *ctx,
+                                   GLuint start,
+                                   GLuint count,
+                                   GLuint flags )
+{
+   if (HAVE_QUADS && 0) {
+   } else {
+      LOCAL_VARS;
+      GLuint *elts = TNL_CONTEXT(ctx)->vb.Elts;
+      int dmasz = GET_SUBSEQUENT_VB_MAX_ELTS();
+      int currentsz;
+      GLuint j, nr;
+
+      ELT_INIT( GL_TRIANGLES );
+      currentsz = GET_CURRENT_VB_MAX_ELTS();
+
+      /* Emit whole number of quads in total, and in each buffer.
+       */
+      dmasz -= dmasz & 3;
+      count -= (count-start) & 3;
+      currentsz -= currentsz & 3;
+
+      /* Adjust for rendering as triangles:
+       */
+      currentsz = currentsz/6*4;
+      dmasz = dmasz/6*4;
+
+      if (currentsz < 8)
+        currentsz = dmasz;
+
+      for (j = start; j + 3 < count; j += nr - 2 ) {
+        nr = MIN2( currentsz, count - j );
+
+        if (nr >= 4)
+        {
+           GLint quads = nr/4;
+           GLint i;
+           ELTS_VARS;
+           NEW_PRIMITIVE();
+           ALLOC_ELTS_NEW_PRIMITIVE( quads * 6 );
+
+           for ( i = j-start ; i < j-start+quads ; i++, elts += 4 ) {
+              EMIT_TWO_ELTS( 0, elts[0], elts[1] );
+              EMIT_TWO_ELTS( 2, elts[3], elts[1] );
+              EMIT_TWO_ELTS( 4, elts[2], elts[3] );
+              INCR_ELTS( 6 );
+           }
+        }
+
+        NEW_PRIMITIVE();
+        currentsz = dmasz;
+      }
+   }
+}
+
+
+
+static render_func TAG(render_tab_elts)[GL_POLYGON+2] =
+{
+   TAG(render_points_elts),
+   TAG(render_lines_elts),
+   TAG(render_line_loop_elts),
+   TAG(render_line_strip_elts),
+   TAG(render_triangles_elts),
+   TAG(render_tri_strip_elts),
+   TAG(render_tri_fan_elts),
+   TAG(render_quads_elts),
+   TAG(render_quad_strip_elts),
+   TAG(render_poly_elts),
+   TAG(render_noop),
+};
+#endif
diff --git a/src/mesa/tnl_dd/t_dd_dmatmp2.h b/src/mesa/tnl_dd/t_dd_dmatmp2.h
new file mode 100644 (file)
index 0000000..3f58d24
--- /dev/null
@@ -0,0 +1,949 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  4.0.3
+ *
+ * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+/* Template for render stages which build and emit vertices directly
+ * to fixed-size dma buffers.  Useful for rendering strips and other
+ * native primitives where clipping and per-vertex tweaks such as
+ * those in t_dd_tritmp.h are not required.
+ *
+ */
+
+#if !HAVE_TRIANGLES || !HAVE_POINTS || !HAVE_LINES
+#error "must have points, lines & triangles to use render template"
+#endif
+
+#if !HAVE_TRI_STRIPS || !HAVE_TRI_FANS
+#error "must have tri strip and fans to use render template"
+#endif
+
+#if !HAVE_LINE_STRIPS
+#error "must have line strips to use render template"
+#endif
+
+#if !HAVE_POLYGONS
+#error "must have polygons to use render template"
+#endif
+
+#if !HAVE_ELTS
+#error "must have elts to use render template"
+#endif
+
+
+#ifndef EMIT_TWO_ELTS
+#define EMIT_TWO_ELTS( dest, offset, elt0, elt1 )      \
+do {                                           \
+   (dest)[offset] = (elt0);                    \
+   (dest)[offset+1] = (elt1);                  \
+} while (0)
+#endif
+
+
+/**********************************************************************/
+/*                  Render whole begin/end objects                    */
+/**********************************************************************/
+
+
+static ELT_TYPE *TAG(emit_elts)( GLcontext *ctx, 
+                           ELT_TYPE *dest,
+                           GLuint *elts, GLuint nr )
+{
+   GLint i;
+   LOCAL_VARS;
+
+   for ( i = 0 ; i+1 < nr ; i+=2, elts += 2 ) {
+      EMIT_TWO_ELTS( dest, 0, elts[0], elts[1] );
+      dest += 2;
+   }
+   if (i < nr) {
+      EMIT_ELT( dest, 0, elts[0] );
+      dest += 1;
+   }
+   
+   return dest;
+}
+
+static ELT_TYPE *TAG(emit_consecutive_elts)( GLcontext *ctx, 
+                                       ELT_TYPE *dest,
+                                       GLuint start, GLuint nr )
+{
+   GLint i;
+   LOCAL_VARS;
+
+   for ( i = 0 ; i+1 < nr ; i+=2, start += 2 ) {
+      EMIT_TWO_ELTS( dest, 0, start, start+1 );
+      dest += 2;
+   }
+   if (i < nr) {
+      EMIT_ELT( dest, 0, start );
+      dest += 1;
+   }
+
+   return dest;
+}
+
+/***********************************************************************
+ *                    Render non-indexed primitives.
+ ***********************************************************************/
+
+
+
+static void TAG(render_points_verts)( GLcontext *ctx,
+                                     GLuint start,
+                                     GLuint count,
+                                     GLuint flags )
+{
+   if (start < count) {
+      LOCAL_VARS;
+      if (0) fprintf(stderr, "%s\n", __FUNCTION__);
+      EMIT_PRIM( ctx, GL_POINTS, HW_POINTS, start, count );
+   }
+}
+
+static void TAG(render_lines_verts)( GLcontext *ctx,
+                                    GLuint start,
+                                    GLuint count,
+                                    GLuint flags )
+{
+   LOCAL_VARS;
+   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
+   count -= (count-start) & 1;
+
+   if (start+1 >= count)
+      return;
+
+   if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag) {
+      RESET_STIPPLE();
+      AUTO_STIPPLE( GL_TRUE );
+   }
+      
+   EMIT_PRIM( ctx, GL_LINES, HW_LINES, start, count );
+
+   if ((flags & PRIM_END) && ctx->Line.StippleFlag)
+      AUTO_STIPPLE( GL_FALSE );
+}
+
+
+static void TAG(render_line_strip_verts)( GLcontext *ctx,
+                                         GLuint start,
+                                         GLuint count,
+                                         GLuint flags )
+{
+   LOCAL_VARS;
+   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
+
+   if (start+1 >= count)
+      return;
+
+   if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag)
+      RESET_STIPPLE();
+
+
+   if (PREFER_DISCRETE_ELT_PRIM( count-start, HW_LINES ))
+   {   
+      int dmasz = GET_MAX_HW_ELTS();
+      GLuint j, nr;
+
+      ELT_INIT( GL_LINES, HW_LINES );
+
+      /* Emit whole number of lines in each full buffer.
+       */
+      dmasz = dmasz/2;
+
+
+      for (j = start; j + 1 < count; j += nr - 1 ) {
+        ELT_TYPE *dest;
+        GLint i;
+
+        nr = MIN2( dmasz, count - j );
+        dest = ALLOC_ELTS( (nr-1)*2 );
+           
+        for ( i = j ; i+1 < j+nr ; i+=1 ) {
+           EMIT_TWO_ELTS( dest, 0, (i+0), (i+1) );
+           dest += 2;
+        }
+
+        CLOSE_ELTS();
+      }
+   }
+   else
+      EMIT_PRIM( ctx, GL_LINE_STRIP, HW_LINE_STRIP, start, count );
+}
+
+
+static void TAG(render_line_loop_verts)( GLcontext *ctx,
+                                        GLuint start,
+                                        GLuint count,
+                                        GLuint flags )
+{
+   LOCAL_VARS;
+   GLuint j, nr;
+   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
+
+   if (flags & PRIM_BEGIN) {
+      j = start;
+      if (ctx->Line.StippleFlag)
+        RESET_STIPPLE( );
+   }
+   else
+      j = start + 1;
+
+   if (flags & PRIM_END) {
+
+      if (start+1 >= count)
+        return;
+
+      if (PREFER_DISCRETE_ELT_PRIM( count-start, HW_LINES )) {
+        int dmasz = GET_MAX_HW_ELTS();
+
+        ELT_INIT( GL_LINES, HW_LINES );
+
+        /* Emit whole number of lines in each full buffer.
+         */
+        dmasz = dmasz/2;
+
+        /* Ensure last vertex doesn't wrap:
+         */
+        dmasz--;
+
+        for (; j + 1 < count;  ) {
+           GLint i;
+           ELT_TYPE *dest;
+
+           nr = MIN2( dmasz, count - j );
+           dest = ALLOC_ELTS( nr*2 );  /* allocs room for 1 more line */
+
+           for ( i = 0 ; i < nr - 1 ; i+=1 ) {
+              EMIT_TWO_ELTS( dest, 0, (j+i), (j+i+1) );
+              dest += 2;
+           }
+
+           j += nr - 1;
+
+           /* Emit 1 more line into space alloced above */
+           if (j + 1 >= count) {
+              EMIT_TWO_ELTS( dest, 0, (j), (start) ); 
+              dest += 2; 
+           }
+           CLOSE_ELTS();
+        }
+      }
+      else
+      {
+        int dmasz = GET_MAX_HW_ELTS() - 1;
+
+        ELT_INIT( GL_LINE_STRIP, HW_LINE_STRIP );
+
+        for ( ; j + 1 < count;  ) {
+           nr = MIN2( dmasz, count - j );
+           if (j + nr < count) {
+              ELT_TYPE *dest = ALLOC_ELTS( nr );
+              dest = TAG(emit_consecutive_elts)( ctx, dest, j, nr );
+              j += nr - 1;
+              CLOSE_ELTS();
+           }
+           else if (nr) {
+              ELT_TYPE *dest = ALLOC_ELTS( nr + 1 );
+              dest = TAG(emit_consecutive_elts)( ctx, dest, j, nr );
+              dest = TAG(emit_consecutive_elts)( ctx, dest, start, 1 );
+              j += nr;
+              CLOSE_ELTS();
+           }
+        }   
+      }
+   } else {
+      TAG(render_line_strip_verts)( ctx, j, count, flags );
+   }
+}
+
+
+static void TAG(render_triangles_verts)( GLcontext *ctx,
+                                        GLuint start,
+                                        GLuint count,
+                                        GLuint flags )
+{
+   LOCAL_VARS;
+   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
+
+   count -= (count-start)%3;
+
+   if (start+2 >= count) {
+      return;
+   }
+
+   /* need a PREFER_DISCRETE_ELT_PRIM here too..
+    */
+   EMIT_PRIM( ctx, GL_TRIANGLES, HW_TRIANGLES, start, count );
+}
+
+
+
+static void TAG(render_tri_strip_verts)( GLcontext *ctx,
+                                        GLuint start,
+                                        GLuint count,
+                                        GLuint flags )
+{
+   LOCAL_VARS;
+   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
+
+   if (start + 2 >= count)
+      return;
+
+   if (PREFER_DISCRETE_ELT_PRIM( count-start, HW_TRIANGLES ))
+   {   
+      int dmasz = GET_MAX_HW_ELTS();
+      int parity = 0;
+      GLuint j, nr;
+
+      ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
+
+      if (flags & PRIM_PARITY)
+        parity = 1;
+
+      /* Emit even number of tris in each full buffer.
+       */
+      dmasz = dmasz/3;
+      dmasz -= dmasz & 1;
+
+      for (j = start; j + 2 < count; j += nr - 2 ) {
+        ELT_TYPE *dest;
+        GLint i;
+
+        nr = MIN2( dmasz, count - j );
+        dest = ALLOC_ELTS( (nr-2)*3 );
+           
+        for ( i = j ; i+2 < j+nr ; i++, parity^=1 ) {
+           EMIT_ELT( dest, 0, (i+0+parity) );
+           EMIT_ELT( dest, 1, (i+1-parity) );
+           EMIT_ELT( dest, 2, (i+2) );
+           dest += 3;
+        }
+
+        CLOSE_ELTS();
+      }
+   }
+   else if ((flags & PRIM_PARITY) == 0)  
+      EMIT_PRIM( ctx, GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0, start, count );
+   else if (HAVE_TRI_STRIP_1)
+      EMIT_PRIM( ctx, GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_1, start, count );
+   else {
+      /* Emit the first triangle with elts, then the rest as a regular strip.
+       * TODO:  Make this unlikely in t_imm_api.c
+       */
+      ELT_TYPE *dest;
+
+      ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
+      dest = ALLOC_ELTS( 3 );
+      EMIT_ELT( dest, 0, (start+1) );
+      EMIT_ELT( dest, 1, (start+0) );
+      EMIT_ELT( dest, 2, (start+2) );
+      dest += 3;
+      CLOSE_ELTS();
+
+      start++;
+      if (start + 2 >= count)
+        return;
+
+      EMIT_PRIM( ctx, GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0, start, 
+                count );
+   }
+}
+
+static void TAG(render_tri_fan_verts)( GLcontext *ctx,
+                                      GLuint start,
+                                      GLuint count,
+                                      GLuint flags )
+{
+   LOCAL_VARS;
+   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
+
+   if (start+2 >= count) 
+      return;
+
+   if (PREFER_DISCRETE_ELT_PRIM( count-start, HW_TRIANGLES ))
+   {   
+      int dmasz = GET_MAX_HW_ELTS();
+      GLuint j, nr;
+
+      ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
+
+      dmasz = dmasz/3;
+
+      for (j = start + 1; j + 1 < count; j += nr - 1 ) {
+        ELT_TYPE *dest;
+        GLint i;
+
+        nr = MIN2( dmasz, count - j );
+        dest = ALLOC_ELTS( (nr-1)*3 );
+           
+        for ( i = j ; i+1 < j+nr ; i++ ) {
+           EMIT_ELT( dest, 0, (start) );
+           EMIT_ELT( dest, 1, (i) );
+           EMIT_ELT( dest, 2, (i+1) );
+           dest += 3;
+        }
+        
+        CLOSE_ELTS();
+      }
+   }
+   else {
+      EMIT_PRIM( ctx, GL_TRIANGLE_FAN, HW_TRIANGLE_FAN, start, count );
+   }
+}
+
+
+static void TAG(render_poly_verts)( GLcontext *ctx,
+                                   GLuint start,
+                                   GLuint count,
+                                   GLuint flags )
+{
+   LOCAL_VARS;
+   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
+
+   if (start+2 >= count) 
+      return;
+
+   EMIT_PRIM( ctx, GL_POLYGON, HW_POLYGON, start, count );
+}
+
+static void TAG(render_quad_strip_verts)( GLcontext *ctx,
+                                         GLuint start,
+                                         GLuint count,
+                                         GLuint flags )
+{
+   LOCAL_VARS;
+   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
+
+   count -= (count-start) & 1;
+
+   if (start+3 >= count) 
+      return;
+
+   if (HAVE_QUAD_STRIPS) {
+      EMIT_PRIM( ctx, GL_QUAD_STRIP, HW_QUAD_STRIP, start, count );
+   } 
+   else if (ctx->_TriangleCaps & DD_FLATSHADE) {
+      LOCAL_VARS;
+      int dmasz = GET_MAX_HW_ELTS();
+      GLuint j, nr;
+
+      ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
+
+      /* Emit whole number of quads in total, and in each buffer.
+       */
+      dmasz = (dmasz/6)*2;
+
+      for (j = start; j + 3 < count; j += nr - 2 ) {
+        ELT_TYPE *dest;
+        GLint quads, i;
+
+        nr = MIN2( dmasz, count - j );
+        quads = (nr/2)-1;
+        dest = ALLOC_ELTS( quads*6 );
+           
+        for ( i = j ; i < j+quads*2 ; i+=2 ) {
+           EMIT_TWO_ELTS( dest, 0, (i+0), (i+1) );
+           EMIT_TWO_ELTS( dest, 2, (i+2), (i+1) );
+           EMIT_TWO_ELTS( dest, 4, (i+3), (i+2) );
+           dest += 6;
+        }
+
+        CLOSE_ELTS();
+      }
+   }
+   else {
+      EMIT_PRIM( ctx, GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0, start, count );
+   }
+}
+
+
+static void TAG(render_quads_verts)( GLcontext *ctx,
+                                    GLuint start,
+                                    GLuint count,
+                                    GLuint flags )
+{
+   LOCAL_VARS;
+   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
+   count -= (count-start)%4;
+
+   if (start+3 >= count) 
+      return;
+
+   if (HAVE_QUADS) {
+      EMIT_PRIM( ctx, HW_QUADS, GL_QUADS, start, count );
+   } 
+   else {
+      /* Hardware doesn't have a quad primitive type -- simulate it
+       * using indexed vertices and the triangle primitive: 
+       */
+      LOCAL_VARS;
+      int dmasz = GET_MAX_HW_ELTS();
+      GLuint j, nr;
+
+      ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
+
+      /* Adjust for rendering as triangles:
+       */
+      dmasz = (dmasz/6)*4;
+
+      for (j = start; j < count; j += nr ) {
+        ELT_TYPE *dest;
+        GLint quads, i;
+
+        nr = MIN2( dmasz, count - j );
+        quads = nr/4;
+        dest = ALLOC_ELTS( quads*6 );
+
+        for ( i = j ; i < j+quads*4 ; i+=4 ) {
+           EMIT_TWO_ELTS( dest, 0, (i+0), (i+1) );
+           EMIT_TWO_ELTS( dest, 2, (i+3), (i+1) );
+           EMIT_TWO_ELTS( dest, 4, (i+2), (i+3) );
+           dest += 6;
+        }
+
+        CLOSE_ELTS();
+      }
+   }
+}
+
+static void TAG(render_noop)( GLcontext *ctx,
+                             GLuint start,
+                             GLuint count,
+                             GLuint flags )
+{
+}
+
+
+
+
+static render_func TAG(render_tab_verts)[GL_POLYGON+2] =
+{
+   TAG(render_points_verts),
+   TAG(render_lines_verts),
+   TAG(render_line_loop_verts),
+   TAG(render_line_strip_verts),
+   TAG(render_triangles_verts),
+   TAG(render_tri_strip_verts),
+   TAG(render_tri_fan_verts),
+   TAG(render_quads_verts),
+   TAG(render_quad_strip_verts),
+   TAG(render_poly_verts),
+   TAG(render_noop),
+};
+
+
+/****************************************************************************
+ *                 Render elts using hardware indexed verts                 *
+ ****************************************************************************/
+
+static void TAG(render_points_elts)( GLcontext *ctx,
+                                    GLuint start,
+                                    GLuint count,
+                                    GLuint flags )
+{
+   LOCAL_VARS;
+   int dmasz = GET_MAX_HW_ELTS();
+   GLuint *elts = GET_MESA_ELTS();
+   GLuint j, nr;
+   ELT_TYPE *dest;
+
+   ELT_INIT( GL_POINTS, HW_POINTS );
+
+   for (j = start; j < count; j += nr ) {
+      nr = MIN2( dmasz, count - j );
+      dest = ALLOC_ELTS( nr );
+      dest = TAG(emit_elts)( ctx, dest, elts+j, nr );
+      CLOSE_ELTS();
+   }
+}
+
+
+
+static void TAG(render_lines_elts)( GLcontext *ctx,
+                                   GLuint start,
+                                   GLuint count,
+                                   GLuint flags )
+{
+   LOCAL_VARS;
+   int dmasz = GET_MAX_HW_ELTS();
+   GLuint *elts = GET_MESA_ELTS();
+   GLuint j, nr;
+   ELT_TYPE *dest;
+
+   if (start+1 >= count)
+      return;
+
+   if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag) {
+      RESET_STIPPLE();
+      AUTO_STIPPLE( GL_TRUE );
+   }
+
+   ELT_INIT( GL_LINES, HW_LINES );
+
+   /* Emit whole number of lines in total and in each buffer:
+    */
+   count -= (count-start) & 1;
+   dmasz -= dmasz & 1;
+
+   for (j = start; j < count; j += nr ) {
+      nr = MIN2( dmasz, count - j );
+      dest = ALLOC_ELTS( nr );
+      dest = TAG(emit_elts)( ctx, dest, elts+j, nr );
+      CLOSE_ELTS();
+   }
+
+   if ((flags & PRIM_END) && ctx->Line.StippleFlag)
+      AUTO_STIPPLE( GL_FALSE );
+}
+
+
+static void TAG(render_line_strip_elts)( GLcontext *ctx,
+                                        GLuint start,
+                                        GLuint count,
+                                        GLuint flags )
+{
+   LOCAL_VARS;
+   int dmasz = GET_MAX_HW_ELTS();
+   GLuint *elts = GET_MESA_ELTS();
+   GLuint j, nr;
+   ELT_TYPE *dest;
+
+   if (start+1 >= count)
+      return;
+
+   ELT_INIT( GL_LINE_STRIP, HW_LINE_STRIP );
+
+   if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag)
+      RESET_STIPPLE();
+
+   for (j = start; j + 1 < count; j += nr - 1 ) {
+      nr = MIN2( dmasz, count - j );
+      dest = ALLOC_ELTS( nr );
+      dest = TAG(emit_elts)( ctx, dest, elts+j, nr );
+      CLOSE_ELTS();
+   }
+}
+
+
+static void TAG(render_line_loop_elts)( GLcontext *ctx,
+                                       GLuint start,
+                                       GLuint count,
+                                       GLuint flags )
+{
+   LOCAL_VARS;
+   int dmasz = GET_MAX_HW_ELTS();
+   GLuint *elts = GET_MESA_ELTS();
+   GLuint j, nr;
+   ELT_TYPE *dest;
+
+   if (0) fprintf(stderr, "%s\n", __FUNCTION__);
+
+   if (flags & PRIM_BEGIN)
+      j = start;
+   else
+      j = start + 1;
+
+   
+   if (flags & PRIM_END) {
+      if (start+1 >= count)
+        return;
+   } 
+   else {
+      if (j+1 >= count)
+        return;
+   }
+
+   ELT_INIT( GL_LINE_STRIP, HW_LINE_STRIP );
+
+   if ((flags & PRIM_BEGIN) && ctx->Line.StippleFlag)
+      RESET_STIPPLE();
+
+   
+   /* Ensure last vertex doesn't wrap:
+    */
+   dmasz--;
+
+   for ( ; j + 1 < count; ) {
+      nr = MIN2( dmasz, count - j );
+      dest = ALLOC_ELTS( nr+1 );       /* Reserve possible space for last elt */
+      dest = TAG(emit_elts)( ctx, dest, elts+j, nr );
+      j += nr - 1;
+      if (j + 1 >= count && (flags & PRIM_END)) {
+        dest = TAG(emit_elts)( ctx, dest, elts+start, 1 );
+      }
+      CLOSE_ELTS();
+   }
+}
+
+
+static void TAG(render_triangles_elts)( GLcontext *ctx,
+                                       GLuint start,
+                                       GLuint count,
+                                       GLuint flags )
+{
+   LOCAL_VARS;
+   GLuint *elts = GET_MESA_ELTS();
+   int dmasz = GET_MAX_HW_ELTS()/3*3;
+   GLuint j, nr;
+   ELT_TYPE *dest;
+
+   if (start+2 >= count)
+      return;
+
+   ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
+
+
+   /* Emit whole number of tris in total.  dmasz is already a multiple
+    * of 3.
+    */
+   count -= (count-start)%3;
+
+   for (j = start; j < count; j += nr) {
+      nr = MIN2( dmasz, count - j );
+      dest = ALLOC_ELTS( nr );
+      dest = TAG(emit_elts)( ctx, dest, elts+j, nr );
+      CLOSE_ELTS();
+   }
+}
+
+
+
+static void TAG(render_tri_strip_elts)( GLcontext *ctx,
+                                       GLuint start,
+                                       GLuint count,
+                                       GLuint flags )
+{
+   LOCAL_VARS;
+   GLuint j, nr;
+   GLuint *elts = GET_MESA_ELTS();
+   int dmasz = GET_MAX_HW_ELTS();
+   ELT_TYPE *dest;
+
+   if (start+2 >= count)
+      return;
+
+   ELT_INIT( GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0 );
+
+   /* Keep the same winding over multiple buffers:
+    */
+   dmasz -= (dmasz & 1);
+
+   for (j = start ; j + 2 < count; j += nr - 2 ) {
+      nr = MIN2( dmasz, count - j );
+
+      if (flags & PRIM_PARITY) {
+        dest = ALLOC_ELTS( nr );       
+        dest = TAG(emit_elts)( ctx, dest, elts+j, 1 );
+        dest = TAG(emit_elts)( ctx, dest, elts+j, nr-1 );
+        nr--; flags &= ~PRIM_PARITY;
+        CLOSE_ELTS();
+      }
+      else {
+        dest = ALLOC_ELTS( nr );
+        dest = TAG(emit_elts)( ctx, dest, elts+j, nr );
+        CLOSE_ELTS();
+      }
+   }
+}
+
+static void TAG(render_tri_fan_elts)( GLcontext *ctx,
+                                     GLuint start,
+                                     GLuint count,
+                                     GLuint flags )
+{
+   LOCAL_VARS;
+   GLuint *elts = GET_MESA_ELTS();
+   GLuint j, nr;
+   int dmasz = GET_MAX_HW_ELTS();
+   ELT_TYPE *dest;
+
+   if (start+2 >= count)
+      return;
+
+   ELT_INIT( GL_TRIANGLE_FAN, HW_TRIANGLE_FAN );
+
+   for (j = start + 1 ; j + 1 < count; j += nr - 1 ) {
+      nr = MIN2( dmasz, count - j + 1 );
+      dest = ALLOC_ELTS( nr );
+      dest = TAG(emit_elts)( ctx, dest, elts+start, 1 );
+      dest = TAG(emit_elts)( ctx, dest, elts+j, nr - 1 );
+      CLOSE_ELTS();
+   }
+}
+
+
+static void TAG(render_poly_elts)( GLcontext *ctx,
+                                  GLuint start,
+                                  GLuint count,
+                                  GLuint flags )
+{
+   LOCAL_VARS;
+   GLuint *elts = GET_MESA_ELTS();
+   GLuint j, nr;
+   int dmasz = GET_MAX_HW_ELTS();
+   ELT_TYPE *dest;
+
+   if (start+2 >= count)
+      return;
+
+   ELT_INIT( GL_POLYGON, HW_POLYGON );
+
+   for (j = start + 1 ; j + 1 < count ; j += nr - 1 ) {
+      nr = MIN2( dmasz, count - j + 1 );
+      dest = ALLOC_ELTS( nr );
+      dest = TAG(emit_elts)( ctx, dest, elts+start, 1 );
+      dest = TAG(emit_elts)( ctx, dest, elts+j, nr - 1 );
+      CLOSE_ELTS();
+   }
+}
+
+static void TAG(render_quad_strip_elts)( GLcontext *ctx,
+                                        GLuint start,
+                                        GLuint count,
+                                        GLuint flags )
+{
+   if (start+3 >= count)
+      return;
+
+   if (HAVE_QUAD_STRIPS && 0) {
+   }
+   else {
+      LOCAL_VARS;
+      GLuint *elts = GET_MESA_ELTS();
+      int dmasz = GET_MAX_HW_ELTS();
+      GLuint j, nr;
+      ELT_TYPE *dest;
+
+      /* Emit whole number of quads in total, and in each buffer.
+       */
+      dmasz -= dmasz & 1;
+      count -= (count-start) & 1;
+
+      if (ctx->_TriangleCaps & DD_FLATSHADE) {
+        ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
+
+        dmasz = dmasz/6*2;
+
+        for (j = start; j + 3 < count; j += nr - 2 ) {
+           nr = MIN2( dmasz, count - j );
+
+           if (nr >= 4)
+           {
+              GLint quads = (nr/2)-1;
+              ELT_TYPE *dest = ALLOC_ELTS( quads*6 );
+              GLint i;
+
+              for ( i = j-start ; i < j-start+quads ; i++, elts += 2 ) {
+                 EMIT_TWO_ELTS( dest, 0, elts[0], elts[1] );
+                 EMIT_TWO_ELTS( dest, 2, elts[2], elts[1] );
+                 EMIT_TWO_ELTS( dest, 4, elts[3], elts[2] );
+                 dest += 6;
+              }
+
+              CLOSE_ELTS();
+           }
+        }
+      }
+      else {
+        ELT_INIT( GL_TRIANGLE_STRIP, HW_TRIANGLE_STRIP_0 );
+
+        for (j = start; j + 3 < count; j += nr - 2 ) {
+           nr = MIN2( dmasz, count - j );
+           dest = ALLOC_ELTS( nr );
+           dest = TAG(emit_elts)( ctx, dest, elts+j, nr );
+           CLOSE_ELTS();
+        }
+      }
+   }
+}
+
+
+static void TAG(render_quads_elts)( GLcontext *ctx,
+                                   GLuint start,
+                                   GLuint count,
+                                   GLuint flags )
+{
+   if (start+3 >= count)
+      return;
+
+   if (HAVE_QUADS && 0) {
+   } else {
+      LOCAL_VARS;
+      GLuint *elts = GET_MESA_ELTS();
+      int dmasz = GET_MAX_HW_ELTS();
+      GLuint j, nr;
+
+      ELT_INIT( GL_TRIANGLES, HW_TRIANGLES );
+
+      /* Emit whole number of quads in total, and in each buffer.
+       */
+      dmasz -= dmasz & 3;
+      count -= (count-start) & 3;
+
+      /* Adjust for rendering as triangles:
+       */
+      dmasz = dmasz/6*4;
+
+      for (j = start; j + 3 < count; j += nr ) {
+        nr = MIN2( dmasz, count - j );
+
+        {
+           GLint quads = nr/4;
+           ELT_TYPE *dest = ALLOC_ELTS( quads * 6 );
+           GLint i;
+
+           for ( i = j-start ; i < j-start+quads ; i++, elts += 4 ) {
+              EMIT_TWO_ELTS( dest, 0, elts[0], elts[1] );
+              EMIT_TWO_ELTS( dest, 2, elts[3], elts[1] );
+              EMIT_TWO_ELTS( dest, 4, elts[2], elts[3] );
+              dest += 6;
+           }
+
+           CLOSE_ELTS();
+        }
+      }
+   }
+}
+
+
+
+static render_func TAG(render_tab_elts)[GL_POLYGON+2] =
+{
+   TAG(render_points_elts),
+   TAG(render_lines_elts),
+   TAG(render_line_loop_elts),
+   TAG(render_line_strip_elts),
+   TAG(render_triangles_elts),
+   TAG(render_tri_strip_elts),
+   TAG(render_tri_fan_elts),
+   TAG(render_quads_elts),
+   TAG(render_quad_strip_elts),
+   TAG(render_poly_elts),
+   TAG(render_noop),
+};
diff --git a/src/mesa/tnl_dd/t_dd_rendertmp.h b/src/mesa/tnl_dd/t_dd_rendertmp.h
new file mode 100644 (file)
index 0000000..fc00e76
--- /dev/null
@@ -0,0 +1,437 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.5
+ *
+ * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#ifndef POSTFIX
+#define POSTFIX
+#endif
+
+#ifndef INIT
+#define INIT(x)
+#endif
+
+#ifndef NEED_EDGEFLAG_SETUP
+#define NEED_EDGEFLAG_SETUP 0
+#define EDGEFLAG_GET(a) 0
+#define EDGEFLAG_SET(a,b) (void)b
+#endif
+
+#ifndef RESET_STIPPLE
+#define RESET_STIPPLE
+#endif
+
+#ifndef RESET_OCCLUSION
+#define RESET_OCCLUSION
+#endif
+
+#ifndef TEST_PRIM_END
+#define TEST_PRIM_END(flags) (flags & PRIM_END)
+#define TEST_PRIM_BEGIN(flags) (flags & PRIM_BEGIN)
+#define TEST_PRIM_PARITY(flags) (flags & PRIM_PARITY)
+#endif
+
+#ifndef ELT
+#define ELT(x) x
+#endif
+
+#ifndef RENDER_TAB_QUALIFIER
+#define RENDER_TAB_QUALIFIER static
+#endif
+
+static void TAG(render_points)( GLcontext *ctx,
+                               GLuint start,
+                               GLuint count,
+                               GLuint flags )
+{
+   LOCAL_VARS;
+   (void) flags;
+
+   RESET_OCCLUSION;
+   INIT(GL_POINTS);
+   RENDER_POINTS( start, count );
+   POSTFIX;
+}
+
+static void TAG(render_lines)( GLcontext *ctx,
+                              GLuint start,
+                              GLuint count,
+                              GLuint flags )
+{
+   GLuint j;
+   LOCAL_VARS;
+   (void) flags;
+
+   RESET_OCCLUSION;
+   INIT(GL_LINES);
+   for (j=start+1; j<count; j+=2 ) {
+      RENDER_LINE( ELT(j-1), ELT(j) );
+      RESET_STIPPLE;
+   }
+   POSTFIX;
+}
+
+
+static void TAG(render_line_strip)( GLcontext *ctx,
+                                   GLuint start,
+                                   GLuint count,
+                                   GLuint flags )
+{
+   GLuint j;
+   LOCAL_VARS;
+   (void) flags;
+
+   RESET_OCCLUSION;
+   INIT(GL_LINE_STRIP);
+
+   for (j=start+1; j<count; j++ )
+      RENDER_LINE( ELT(j-1), ELT(j) );
+
+   if (TEST_PRIM_END(flags))
+      RESET_STIPPLE;
+
+   POSTFIX;
+}
+
+
+static void TAG(render_line_loop)( GLcontext *ctx,
+                                  GLuint start,
+                                  GLuint count,
+                                  GLuint flags )
+{
+   GLuint i;
+   LOCAL_VARS;
+
+   (void) flags;
+
+   RESET_OCCLUSION;
+   INIT(GL_LINE_LOOP);
+
+   if (start+1 < count) {
+      if (TEST_PRIM_BEGIN(flags)) {
+        RENDER_LINE( ELT(start), ELT(start+1) );
+      }
+
+      for ( i = start+2 ; i < count ; i++) {
+        RENDER_LINE( ELT(i-1), ELT(i) );
+      }
+
+      if ( TEST_PRIM_END(flags)) {
+        RENDER_LINE( ELT(count-1), ELT(start) );
+        RESET_STIPPLE;
+      }
+   }
+
+   POSTFIX;
+}
+
+
+static void TAG(render_triangles)( GLcontext *ctx,
+                                  GLuint start,
+                                  GLuint count,
+                                  GLuint flags )
+{
+   GLuint j;
+   LOCAL_VARS;
+   (void) flags;
+
+   INIT(GL_TRIANGLES);
+   if (NEED_EDGEFLAG_SETUP) {
+      for (j=start+2; j<count; j+=3) {
+        /* Leave the edgeflags as supplied by the user.
+         */
+        RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) );
+        RESET_STIPPLE;
+      }
+   } else {
+      for (j=start+2; j<count; j+=3) {
+        RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) );
+      }
+   }
+   POSTFIX;
+}
+
+
+
+static void TAG(render_tri_strip)( GLcontext *ctx,
+                                  GLuint start,
+                                  GLuint count,
+                                  GLuint flags )
+{
+   GLuint j;
+   GLuint parity = 0;
+   LOCAL_VARS;
+
+   if (TEST_PRIM_PARITY(flags))
+      parity = 1;
+
+   INIT(GL_TRIANGLE_STRIP);
+   if (NEED_EDGEFLAG_SETUP) {
+      for (j=start+2;j<count;j++,parity^=1) {
+        GLuint ej2 = ELT(j-2+parity);
+        GLuint ej1 = ELT(j-1-parity);
+        GLuint ej = ELT(j);
+        GLboolean ef2 = EDGEFLAG_GET( ej2 );
+        GLboolean ef1 = EDGEFLAG_GET( ej1 );
+        GLboolean ef = EDGEFLAG_GET( ej );
+        EDGEFLAG_SET( ej2, GL_TRUE );
+        EDGEFLAG_SET( ej1, GL_TRUE );
+        EDGEFLAG_SET( ej, GL_TRUE );
+        RENDER_TRI( ej2, ej1, ej );
+        EDGEFLAG_SET( ej2, ef2 );
+        EDGEFLAG_SET( ej1, ef1 );
+        EDGEFLAG_SET( ej, ef );
+        RESET_STIPPLE;
+      }
+   } else {
+      for (j=start+2; j<count ; j++, parity^=1) {
+        RENDER_TRI( ELT(j-2+parity), ELT(j-1-parity), ELT(j) );
+      }
+   }
+   POSTFIX;
+}
+
+
+static void TAG(render_tri_fan)( GLcontext *ctx,
+                                GLuint start,
+                                GLuint count,
+                                GLuint flags )
+{
+   GLuint j;
+   LOCAL_VARS;
+   (void) flags;
+
+   INIT(GL_TRIANGLE_FAN);
+   if (NEED_EDGEFLAG_SETUP) {
+      for (j=start+2;j<count;j++) {
+        /* For trifans, all edges are boundary.
+         */
+        GLuint ejs = ELT(start);
+        GLuint ej1 = ELT(j-1);
+        GLuint ej = ELT(j);
+        GLboolean efs = EDGEFLAG_GET( ejs );
+        GLboolean ef1 = EDGEFLAG_GET( ej1 );
+        GLboolean ef = EDGEFLAG_GET( ej );
+        EDGEFLAG_SET( ejs, GL_TRUE );
+        EDGEFLAG_SET( ej1, GL_TRUE );
+        EDGEFLAG_SET( ej, GL_TRUE );
+        RENDER_TRI( ejs, ej1, ej);
+        EDGEFLAG_SET( ejs, efs );
+        EDGEFLAG_SET( ej1, ef1 );
+        EDGEFLAG_SET( ej, ef );
+        RESET_STIPPLE;
+      }
+   } else {
+      for (j=start+2;j<count;j++) {
+        RENDER_TRI( ELT(start), ELT(j-1), ELT(j) );
+      }
+   }
+
+   POSTFIX;
+}
+
+
+static void TAG(render_poly)( GLcontext *ctx,
+                             GLuint start,
+                             GLuint count,
+                             GLuint flags )
+{
+   GLuint j = start+2;
+   LOCAL_VARS;
+   (void) flags;
+
+   INIT(GL_POLYGON);
+   if (NEED_EDGEFLAG_SETUP) {
+      GLboolean efstart = EDGEFLAG_GET( ELT(start) );
+      GLboolean efcount = EDGEFLAG_GET( ELT(count-1) );
+
+      /* If the primitive does not begin here, the first edge
+       * is non-boundary.
+       */
+      if (!TEST_PRIM_BEGIN(flags))
+        EDGEFLAG_SET( ELT(start), GL_FALSE );
+
+      /* If the primitive does not end here, the final edge is
+       * non-boundary.
+       */
+      if (!TEST_PRIM_END(flags))
+        EDGEFLAG_SET( ELT(count-1), GL_FALSE );
+
+      /* Draw the first triangles (possibly zero)
+       */
+      if (j<count-1) {
+        GLboolean ef = EDGEFLAG_GET( ELT(j) );
+        EDGEFLAG_SET( ELT(j), GL_FALSE );
+        RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
+        EDGEFLAG_SET( ELT(j), ef );
+        j++;
+
+        /* Don't render the first edge again:
+         */
+        EDGEFLAG_SET( ELT(start), GL_FALSE );
+
+        for (;j<count-1;j++) {
+           GLboolean efj = EDGEFLAG_GET( ELT(j) );
+           EDGEFLAG_SET( ELT(j), GL_FALSE );
+           RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
+           EDGEFLAG_SET( ELT(j), efj );
+        }
+      }
+
+      /* Draw the last or only triangle
+       */
+      if (j < count)
+        RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
+
+      /* Restore the first and last edgeflags:
+       */
+      EDGEFLAG_SET( ELT(count-1), efcount );
+      EDGEFLAG_SET( ELT(start), efstart );
+
+      if (TEST_PRIM_END(flags)) {
+        RESET_STIPPLE;
+      }
+   }
+   else {
+      for (j=start+2;j<count;j++) {
+        RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
+      }
+   }
+   POSTFIX;
+}
+
+static void TAG(render_quads)( GLcontext *ctx,
+                              GLuint start,
+                              GLuint count,
+                              GLuint flags )
+{
+   GLuint j;
+   LOCAL_VARS;
+   (void) flags;
+
+   INIT(GL_QUADS);
+   if (NEED_EDGEFLAG_SETUP) {
+      for (j=start+3; j<count; j+=4) {
+        /* Use user-specified edgeflags for quads.
+         */
+        RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) );
+        RESET_STIPPLE;
+      }
+   } else {
+      for (j=start+3; j<count; j+=4) {
+        RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) );
+      }
+   }
+   POSTFIX;
+}
+
+static void TAG(render_quad_strip)( GLcontext *ctx,
+                                   GLuint start,
+                                   GLuint count,
+                                   GLuint flags )
+{
+   GLuint j;
+   LOCAL_VARS;
+   (void) flags;
+
+   INIT(GL_QUAD_STRIP);
+   if (NEED_EDGEFLAG_SETUP) {
+      for (j=start+3;j<count;j+=2) {
+        /* All edges are boundary.  Set edgeflags to 1, draw the
+         * quad, and restore them to the original values.
+         */
+        GLboolean ef3 = EDGEFLAG_GET( ELT(j-3) );
+        GLboolean ef2 = EDGEFLAG_GET( ELT(j-2) );
+        GLboolean ef1 = EDGEFLAG_GET( ELT(j-1) );
+        GLboolean ef = EDGEFLAG_GET( ELT(j) );
+        EDGEFLAG_SET( ELT(j-3), GL_TRUE );
+        EDGEFLAG_SET( ELT(j-2), GL_TRUE );
+        EDGEFLAG_SET( ELT(j-1), GL_TRUE );
+        EDGEFLAG_SET( ELT(j), GL_TRUE );
+        RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) );
+        EDGEFLAG_SET( ELT(j-3), ef3 );
+        EDGEFLAG_SET( ELT(j-2), ef2 );
+        EDGEFLAG_SET( ELT(j-1), ef1 );
+        EDGEFLAG_SET( ELT(j), ef );
+        RESET_STIPPLE;
+      }
+   } else {
+      for (j=start+3;j<count;j+=2) {
+        RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) );
+      }
+   }
+   POSTFIX;
+}
+
+static void TAG(render_noop)( GLcontext *ctx,
+                             GLuint start,
+                             GLuint count,
+                             GLuint flags )
+{
+   (void)(ctx && start && count && flags);
+}
+
+RENDER_TAB_QUALIFIER void (*TAG(render_tab)[GL_POLYGON+2])(GLcontext *,
+                                                          GLuint,
+                                                          GLuint,
+                                                          GLuint) =
+{
+   TAG(render_points),
+   TAG(render_lines),
+   TAG(render_line_loop),
+   TAG(render_line_strip),
+   TAG(render_triangles),
+   TAG(render_tri_strip),
+   TAG(render_tri_fan),
+   TAG(render_quads),
+   TAG(render_quad_strip),
+   TAG(render_poly),
+   TAG(render_noop),
+};
+
+
+
+#ifndef PRESERVE_VB_DEFS
+#undef RENDER_TRI
+#undef RENDER_QUAD
+#undef RENDER_LINE
+#undef RENDER_POINTS
+#undef LOCAL_VARS
+#undef INIT
+#undef POSTFIX
+#undef RESET_STIPPLE
+#undef DBG
+#undef ELT
+#undef RENDER_TAB_QUALIFIER
+#endif
+
+#ifndef PRESERVE_TAG
+#undef TAG
+#endif
+
+#undef PRESERVE_VB_DEFS
+#undef PRESERVE_TAG
diff --git a/src/mesa/tnl_dd/t_dd_triemit.h b/src/mesa/tnl_dd/t_dd_triemit.h
new file mode 100644 (file)
index 0000000..2f5bcee
--- /dev/null
@@ -0,0 +1,157 @@
+#ifndef DO_DEBUG_VERTS
+#define DO_DEBUG_VERTS 0
+#endif 
+
+#ifndef PRINT_VERTEX
+#define PRINT_VERTEX(x) 
+#endif
+
+#if defined(USE_X86_ASM)
+#define COPY_DWORDS( j, vb, vertsize, v )                              \
+do {                                                                   \
+       int __tmp;                                                      \
+       __asm__ __volatile__( "rep ; movsl"                             \
+                             : "=%c" (j), "=D" (vb), "=S" (__tmp)      \
+                             : "0" (vertsize),                         \
+                               "D" ((long)vb),                         \
+                               "S" ((long)v) );                        \
+} while (0)
+#else
+#define COPY_DWORDS( j, vb, vertsize, v )                              \
+do {                                                                   \
+   for ( j = 0 ; j < vertsize ; j++ )                                  \
+      vb[j] = ((GLuint *)v)[j];                                                \
+   vb += vertsize;                                                     \
+} while (0)
+#endif
+
+
+
+#if HAVE_QUADS
+static __inline void TAG(quad)( CTX_ARG,
+                               VERTEX *v0,
+                               VERTEX *v1,
+                               VERTEX *v2,
+                               VERTEX *v3 )
+{
+   GLuint vertsize = GET_VERTEX_DWORDS();
+   GLuint *vb = (GLuint *)ALLOC_VERTS( 4, vertsize);
+   GLuint j;
+
+   if (DO_DEBUG_VERTS) {
+      fprintf(stderr, "%s\n", __FUNCTION__);
+      PRINT_VERTEX(v0);
+      PRINT_VERTEX(v1);
+      PRINT_VERTEX(v2);
+      PRINT_VERTEX(v3);
+   }
+      
+   COPY_DWORDS( j, vb, vertsize, v0 );
+   COPY_DWORDS( j, vb, vertsize, v1 );
+   COPY_DWORDS( j, vb, vertsize, v2 );
+   COPY_DWORDS( j, vb, vertsize, v3 );
+}
+#else
+static __inline void TAG(quad)( CTX_ARG,
+                               VERTEX *v0,
+                               VERTEX *v1,
+                               VERTEX *v2,
+                               VERTEX *v3 )
+{
+   GLuint vertsize = GET_VERTEX_DWORDS();
+   GLuint *vb = (GLuint *)ALLOC_VERTS(  6, vertsize);
+   GLuint j;
+
+   if (DO_DEBUG_VERTS) {
+      fprintf(stderr, "%s\n", __FUNCTION__);
+      PRINT_VERTEX(v0);
+      PRINT_VERTEX(v1);
+      PRINT_VERTEX(v2);
+      PRINT_VERTEX(v3);
+   }
+   COPY_DWORDS( j, vb, vertsize, v0 );
+   COPY_DWORDS( j, vb, vertsize, v1 );
+   COPY_DWORDS( j, vb, vertsize, v3 );
+   COPY_DWORDS( j, vb, vertsize, v1 );
+   COPY_DWORDS( j, vb, vertsize, v2 );
+   COPY_DWORDS( j, vb, vertsize, v3 );
+}
+#endif
+
+
+static __inline void TAG(triangle)( CTX_ARG,
+                                   VERTEX *v0,
+                                   VERTEX *v1,
+                                   VERTEX *v2 )
+{
+   GLuint vertsize = GET_VERTEX_DWORDS();
+   GLuint *vb = (GLuint *)ALLOC_VERTS( 3, vertsize);
+   GLuint j;
+
+   if (DO_DEBUG_VERTS) {
+      fprintf(stderr, "%s\n", __FUNCTION__);
+      PRINT_VERTEX(v0);
+      PRINT_VERTEX(v1);
+      PRINT_VERTEX(v2);
+   }
+
+   COPY_DWORDS( j, vb, vertsize, v0 );
+   COPY_DWORDS( j, vb, vertsize, v1 );
+   COPY_DWORDS( j, vb, vertsize, v2 );
+}
+
+
+#if HAVE_LINES
+static __inline void TAG(line)( CTX_ARG,
+                               VERTEX *v0,
+                               VERTEX *v1 )
+{
+   GLuint vertsize = GET_VERTEX_DWORDS();
+   GLuint *vb = (GLuint *)ALLOC_VERTS( 2, vertsize);
+   GLuint j;
+
+   COPY_DWORDS( j, vb, vertsize, v0 );
+   COPY_DWORDS( j, vb, vertsize, v1 );
+}
+#endif
+
+#if HAVE_POINTS
+static __inline void TAG(point)( CTX_ARG,
+                                VERTEX *v0 )
+{
+   GLuint vertsize = GET_VERTEX_DWORDS();
+   GLuint *vb = (GLuint *)ALLOC_VERTS( 1, vertsize);
+   int j;
+
+   COPY_DWORDS( j, vb, vertsize, v0 );
+}
+#endif
+
+
+static void TAG(fast_clipped_poly)( GLcontext *ctx, const GLuint *elts,
+                                   GLuint n )
+{
+   LOCAL_VARS
+   GLuint vertsize = GET_VERTEX_DWORDS();
+   GLuint *vb = (GLuint *)ALLOC_VERTS( (n-2) * 3, vertsize );
+   const GLuint *start = (const GLuint *)VERT(elts[0]);
+   int i,j;
+
+   if (DO_DEBUG_VERTS) {
+      fprintf(stderr, "%s\n", __FUNCTION__);
+      PRINT_VERTEX(VERT(elts[0]));
+      PRINT_VERTEX(VERT(elts[1]));
+   }
+
+   for (i = 2 ; i < n ; i++) {
+      if (DO_DEBUG_VERTS) {
+        PRINT_VERTEX(VERT(elts[i]));
+      }
+
+      COPY_DWORDS( j, vb, vertsize, VERT(elts[i-1]) );
+      COPY_DWORDS( j, vb, vertsize, VERT(elts[i]) );
+      COPY_DWORDS( j, vb, vertsize, start );
+   }
+}
+
diff --git a/src/mesa/tnl_dd/t_dd_tritmp.h b/src/mesa/tnl_dd/t_dd_tritmp.h
new file mode 100644 (file)
index 0000000..cc47798
--- /dev/null
@@ -0,0 +1,739 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.5
+ *
+ * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+/* Template for building functions to plug into the driver interface
+ * of t_vb_render.c:
+ *     ctx->Driver.QuadFunc
+ *     ctx->Driver.TriangleFunc
+ *     ctx->Driver.LineFunc
+ *     ctx->Driver.PointsFunc
+ *
+ * DO_TWOSIDE:   Plug back-color values from the VB into backfacing triangles,
+ *               and restore vertices afterwards.
+ * DO_OFFSET:    Calculate offset for triangles and adjust vertices.  Restore
+ *               vertices after rendering.
+ * DO_FLAT:      For hardware without native flatshading, copy provoking colors
+ *               into the other vertices.  Restore after rendering.
+ * DO_UNFILLED:  Decompose triangles to lines and points where appropriate.
+ *
+ * HAVE_RGBA: Vertices have rgba values (otherwise index values).
+ * HAVE_SPEC: Vertices have secondary rgba values.
+ *
+ * VERT_X(v): Alias for vertex x value.
+ * VERT_Y(v): Alias for vertex y value.
+ * VERT_Z(v): Alias for vertex z value.
+ * DEPTH_SCALE: Scale for offset.
+ *
+ * VERTEX: Hardware vertex type.
+ * GET_VERTEX(n): Retreive vertex with index n.
+ * AREA_IS_CCW(a): Return true if triangle with signed area a is ccw.
+ *
+ * VERT_SET_RGBA: Assign vertex rgba from VB color.
+ * VERT_COPY_RGBA: Copy vertex rgba another vertex.
+ * VERT_SAVE_RGBA: Save vertex rgba to a local variable.
+ * VERT_RESTORE_RGBA: Restore vertex rgba from a local variable.
+ *   --> Similar for IND and SPEC.
+ *
+ * LOCAL_VARS(n): (At least) define local vars for save/restore rgba.
+ *
+ */
+
+#if HAVE_RGBA
+#define VERT_SET_IND( v, c ) (void) c
+#define VERT_COPY_IND( v0, v1 )
+#define VERT_SAVE_IND( idx )
+#define VERT_RESTORE_IND( idx )
+#if HAVE_BACK_COLORS
+#define VERT_SET_RGBA( v, c )
+#endif
+#else
+#define VERT_SET_RGBA( v, c ) (void) c
+#define VERT_COPY_RGBA( v0, v1 )
+#define VERT_SAVE_RGBA( idx )
+#define VERT_RESTORE_RGBA( idx )
+#if HAVE_BACK_COLORS
+#define VERT_SET_IND( v, c )
+#endif
+#endif
+
+#if !HAVE_SPEC
+#define VERT_SET_SPEC( v, c ) (void) c
+#define VERT_COPY_SPEC( v0, v1 )
+#define VERT_SAVE_SPEC( idx )
+#define VERT_RESTORE_SPEC( idx )
+#if HAVE_BACK_COLORS
+#define VERT_COPY_SPEC1( v )
+#endif
+#else
+#if HAVE_BACK_COLORS
+#define VERT_SET_SPEC( v, c )
+#endif
+#endif
+
+#if !HAVE_BACK_COLORS
+#define VERT_COPY_SPEC1( v )
+#define VERT_COPY_IND1( v )
+#define VERT_COPY_RGBA1( v )
+#endif
+
+#ifndef INSANE_VERTICES
+#define VERT_SET_Z(v,val) VERT_Z(v) = val
+#define VERT_Z_ADD(v,val) VERT_Z(v) += val
+#endif
+
+#if DO_TRI
+static void TAG(triangle)( GLcontext *ctx, GLuint e0, GLuint e1, GLuint e2 )
+{
+   struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb;
+   VERTEX *v[3];
+   GLfloat offset;
+   GLfloat z[3];
+   GLenum mode = GL_FILL;
+   GLuint facing;
+   LOCAL_VARS(3);
+
+/*     fprintf(stderr, "%s\n", __FUNCTION__); */
+
+   v[0] = (VERTEX *)GET_VERTEX(e0);
+   v[1] = (VERTEX *)GET_VERTEX(e1);
+   v[2] = (VERTEX *)GET_VERTEX(e2);
+
+   if (DO_TWOSIDE || DO_OFFSET || DO_UNFILLED)
+   {
+      GLfloat ex = VERT_X(v[0]) - VERT_X(v[2]);
+      GLfloat ey = VERT_Y(v[0]) - VERT_Y(v[2]);
+      GLfloat fx = VERT_X(v[1]) - VERT_X(v[2]);
+      GLfloat fy = VERT_Y(v[1]) - VERT_Y(v[2]);
+      GLfloat cc = ex*fy - ey*fx;
+
+      if (DO_TWOSIDE || DO_UNFILLED)
+      {
+        facing = AREA_IS_CCW( cc ) ^ ctx->Polygon._FrontBit;
+
+        if (DO_UNFILLED) {
+           if (facing) {
+              mode = ctx->Polygon.BackMode;
+              if (ctx->Polygon.CullFlag &&
+                  ctx->Polygon.CullFaceMode != GL_FRONT) {
+                 return;
+              }
+           } else {
+              mode = ctx->Polygon.FrontMode;
+              if (ctx->Polygon.CullFlag &&
+                  ctx->Polygon.CullFaceMode != GL_BACK) {
+                 return;
+              }
+           }
+        }
+
+        if (DO_TWOSIDE && facing == 1)
+        {
+           if (HAVE_RGBA) {
+              if (HAVE_BACK_COLORS) {
+                 if (!DO_FLAT) {
+                    VERT_SAVE_RGBA( 0 );
+                    VERT_SAVE_RGBA( 1 );
+                    VERT_COPY_RGBA1( v[0] );
+                    VERT_COPY_RGBA1( v[1] );
+                 }
+                 VERT_SAVE_RGBA( 2 );
+                 VERT_COPY_RGBA1( v[2] );
+                 if (HAVE_SPEC) {
+                    if (!DO_FLAT) {
+                       VERT_SAVE_SPEC( 0 );
+                       VERT_SAVE_SPEC( 1 );
+                       VERT_COPY_SPEC1( v[0] );
+                       VERT_COPY_SPEC1( v[1] );
+                    }
+                    VERT_SAVE_SPEC( 2 );
+                    VERT_COPY_SPEC1( v[2] );
+                 }
+              }
+              else {
+                 GLchan (*vbcolor)[4] = VB->ColorPtr[1]->Ptr;
+                 ASSERT(VB->ColorPtr[1]->Type == CHAN_TYPE);
+                 ASSERT(VB->ColorPtr[1]->StrideB == 4*sizeof(GLchan));
+                 (void) vbcolor;
+
+                 if (!DO_FLAT) {
+                    VERT_SAVE_RGBA( 0 );
+                    VERT_SAVE_RGBA( 1 );
+                    VERT_SET_RGBA( v[0], vbcolor[e0] );
+                    VERT_SET_RGBA( v[1], vbcolor[e1] );
+                 }
+                 VERT_SAVE_RGBA( 2 );
+                 VERT_SET_RGBA( v[2], vbcolor[e2] );
+
+                 if (HAVE_SPEC && VB->SecondaryColorPtr[1]) {
+                    GLchan (*vbspec)[4] = VB->SecondaryColorPtr[1]->Ptr;
+
+                    if (!DO_FLAT) {
+                       VERT_SAVE_SPEC( 0 );
+                       VERT_SAVE_SPEC( 1 );
+                       VERT_SET_SPEC( v[0], vbspec[e0] );
+                       VERT_SET_SPEC( v[1], vbspec[e1] );
+                    }
+                    VERT_SAVE_SPEC( 2 );
+                    VERT_SET_SPEC( v[2], vbspec[e2] );
+                 }
+              }
+           }
+           else {
+              GLuint *vbindex = VB->IndexPtr[1]->data;
+              if (!DO_FLAT) {
+                 VERT_SET_IND( v[0], vbindex[e0] );
+                 VERT_SET_IND( v[1], vbindex[e1] );
+              }
+              VERT_SET_IND( v[2], vbindex[e2] );
+           }
+        }
+      }
+
+
+      if (DO_OFFSET)
+      {
+        offset = ctx->Polygon.OffsetUnits * DEPTH_SCALE;
+        z[0] = VERT_Z(v[0]);
+        z[1] = VERT_Z(v[1]);
+        z[2] = VERT_Z(v[2]);
+        if (cc * cc > 1e-16) {
+           GLfloat ic  = 1.0 / cc;
+           GLfloat ez  = z[0] - z[2];
+           GLfloat fz  = z[1] - z[2];
+           GLfloat a   = ey*fz - ez*fy;
+           GLfloat b   = ez*fx - ex*fz;
+           GLfloat ac  = a * ic;
+           GLfloat bc  = b * ic;
+           if ( ac < 0.0f ) ac = -ac;
+           if ( bc < 0.0f ) bc = -bc;
+           offset += MAX2( ac, bc ) * ctx->Polygon.OffsetFactor;
+        }
+        offset *= ctx->MRD;
+      }
+   }
+
+   if (DO_FLAT) {
+      if (HAVE_RGBA) {
+        VERT_SAVE_RGBA( 0 );
+        VERT_SAVE_RGBA( 1 );
+        VERT_COPY_RGBA( v[0], v[2] );
+        VERT_COPY_RGBA( v[1], v[2] );
+        if (HAVE_SPEC && VB->SecondaryColorPtr[0]) {
+           VERT_SAVE_SPEC( 0 );
+           VERT_SAVE_SPEC( 1 );
+           VERT_COPY_SPEC( v[0], v[2] );
+           VERT_COPY_SPEC( v[1], v[2] );
+        }
+      }
+      else {
+        VERT_SAVE_IND( 0 );
+        VERT_SAVE_IND( 1 );
+        VERT_COPY_IND( v[0], v[2] );
+        VERT_COPY_IND( v[1], v[2] );
+      }
+   }
+
+   if (mode == GL_POINT) {
+      if (DO_OFFSET && ctx->Polygon.OffsetPoint) {
+        VERT_Z_ADD(v[0], offset);
+        VERT_Z_ADD(v[1], offset);
+        VERT_Z_ADD(v[2], offset);
+      }
+      UNFILLED_TRI( ctx, GL_POINT, e0, e1, e2 );
+   } else if (mode == GL_LINE) {
+      if (DO_OFFSET && ctx->Polygon.OffsetLine) {
+        VERT_Z_ADD(v[0], offset);
+        VERT_Z_ADD(v[1], offset);
+        VERT_Z_ADD(v[2], offset);
+      }
+      UNFILLED_TRI( ctx, GL_LINE, e0, e1, e2 );
+   } else {
+      if (DO_OFFSET && ctx->Polygon.OffsetFill) {
+        VERT_Z_ADD(v[0], offset);
+        VERT_Z_ADD(v[1], offset);
+        VERT_Z_ADD(v[2], offset);
+      }
+      if (DO_UNFILLED)
+        RASTERIZE( GL_TRIANGLES );
+      TRI( v[0], v[1], v[2] );
+   }
+
+   if (DO_OFFSET)
+   {
+      VERT_SET_Z(v[0], z[0]);
+      VERT_SET_Z(v[1], z[1]);
+      VERT_SET_Z(v[2], z[2]);
+   }
+
+   if (DO_TWOSIDE && facing == 1)
+   {
+      if (HAVE_RGBA) {
+        if (!DO_FLAT) {
+           VERT_RESTORE_RGBA( 0 );
+           VERT_RESTORE_RGBA( 1 );
+        }
+        VERT_RESTORE_RGBA( 2 );
+        if (HAVE_SPEC) {
+           if (!DO_FLAT) {
+              VERT_RESTORE_SPEC( 0 );
+              VERT_RESTORE_SPEC( 1 );
+           }
+           VERT_RESTORE_SPEC( 2 );
+        }
+      }
+      else {
+        GLuint *vbindex = VB->IndexPtr[0]->data;
+        if (!DO_FLAT) {
+           VERT_SET_IND( v[0], vbindex[e0] );
+           VERT_SET_IND( v[1], vbindex[e1] );
+        }
+        VERT_SET_IND( v[2], vbindex[e2] );
+      }
+   }
+
+
+   if (DO_FLAT) {
+      if (HAVE_RGBA) {
+        VERT_RESTORE_RGBA( 0 );
+        VERT_RESTORE_RGBA( 1 );
+        if (HAVE_SPEC && VB->SecondaryColorPtr[0]) {
+           VERT_RESTORE_SPEC( 0 );
+           VERT_RESTORE_SPEC( 1 );
+        }
+      }
+      else {
+        VERT_RESTORE_IND( 0 );
+        VERT_RESTORE_IND( 1 );
+      }
+   }
+}
+#endif
+
+#if DO_QUAD
+#if DO_FULL_QUAD
+static void TAG(quad)( GLcontext *ctx,
+                      GLuint e0, GLuint e1, GLuint e2, GLuint e3 )
+{
+   struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb;
+   VERTEX *v[4];
+   GLfloat offset;
+   GLfloat z[4];
+   GLenum mode = GL_FILL;
+   GLuint facing;
+   LOCAL_VARS(4);
+
+   v[0] = (VERTEX *)GET_VERTEX(e0);
+   v[1] = (VERTEX *)GET_VERTEX(e1);
+   v[2] = (VERTEX *)GET_VERTEX(e2);
+   v[3] = (VERTEX *)GET_VERTEX(e3);
+
+   if (DO_TWOSIDE || DO_OFFSET || DO_UNFILLED)
+   {
+      GLfloat ex = VERT_X(v[2]) - VERT_X(v[0]);
+      GLfloat ey = VERT_Y(v[2]) - VERT_Y(v[0]);
+      GLfloat fx = VERT_X(v[3]) - VERT_X(v[1]);
+      GLfloat fy = VERT_Y(v[3]) - VERT_Y(v[1]);
+      GLfloat cc = ex*fy - ey*fx;
+
+      if (DO_TWOSIDE || DO_UNFILLED)
+      {
+        facing = AREA_IS_CCW( cc ) ^ ctx->Polygon._FrontBit;
+
+        if (DO_UNFILLED) {
+           if (facing) {
+              mode = ctx->Polygon.BackMode;
+              if (ctx->Polygon.CullFlag &&
+                  ctx->Polygon.CullFaceMode != GL_FRONT) {
+                 return;
+              }
+           } else {
+              mode = ctx->Polygon.FrontMode;
+              if (ctx->Polygon.CullFlag &&
+                  ctx->Polygon.CullFaceMode != GL_BACK) {
+                 return;
+              }
+           }
+        }
+
+        if (DO_TWOSIDE && facing == 1)
+        {
+           if (HAVE_RGBA) {
+              GLchan (*vbcolor)[4] = VB->ColorPtr[1]->Ptr;
+              (void)vbcolor;
+
+              if (HAVE_BACK_COLORS) {
+                  if (!DO_FLAT) {
+                     VERT_SAVE_RGBA( 0 );
+                     VERT_SAVE_RGBA( 1 );
+                     VERT_SAVE_RGBA( 2 );
+                    VERT_COPY_RGBA1( v[0] );
+                    VERT_COPY_RGBA1( v[1] );
+                    VERT_COPY_RGBA1( v[2] );
+                 }
+                 VERT_SAVE_RGBA( 3 );
+                 VERT_COPY_RGBA1( v[3] );
+                 if (HAVE_SPEC) {
+                     if (!DO_FLAT) {
+                        VERT_SAVE_SPEC( 0 );
+                        VERT_SAVE_SPEC( 1 );
+                        VERT_SAVE_SPEC( 2 );
+                       VERT_COPY_SPEC1( v[0] );
+                       VERT_COPY_SPEC1( v[1] );
+                       VERT_COPY_SPEC1( v[2] );
+                    }
+                    VERT_SAVE_SPEC( 3 );
+                    VERT_COPY_SPEC1( v[3] );
+                 }
+              }
+              else {
+                 if (!DO_FLAT) {
+                    VERT_SAVE_RGBA( 0 );
+                    VERT_SAVE_RGBA( 1 );
+                    VERT_SAVE_RGBA( 2 );
+                    VERT_SET_RGBA( v[0], vbcolor[e0] );
+                    VERT_SET_RGBA( v[1], vbcolor[e1] );
+                    VERT_SET_RGBA( v[2], vbcolor[e2] );
+                 }
+                 VERT_SAVE_RGBA( 3 );
+                 VERT_SET_RGBA( v[3], vbcolor[e3] );
+
+                 if (HAVE_SPEC && VB->SecondaryColorPtr[1]) {
+                    GLchan (*vbspec)[4] = VB->SecondaryColorPtr[1]->Ptr;
+                    ASSERT(VB->SecondaryColorPtr[1]->StrideB==4*sizeof(GLchan));
+
+                    if (!DO_FLAT) {
+                       VERT_SAVE_SPEC( 0 );
+                       VERT_SAVE_SPEC( 1 );
+                       VERT_SAVE_SPEC( 2 );
+                       VERT_SET_SPEC( v[0], vbspec[e0] );
+                       VERT_SET_SPEC( v[1], vbspec[e1] );
+                       VERT_SET_SPEC( v[2], vbspec[e2] );
+                    }
+                    VERT_SAVE_SPEC( 3 );
+                    VERT_SET_SPEC( v[3], vbspec[e3] );
+                 }
+              }
+           }
+           else {
+              GLuint *vbindex = VB->IndexPtr[1]->data;
+              if (!DO_FLAT) {
+                 VERT_SET_IND( v[0], vbindex[e0] );
+                 VERT_SET_IND( v[1], vbindex[e1] );
+                 VERT_SET_IND( v[2], vbindex[e2] );
+              }
+              VERT_SET_IND( v[3], vbindex[e3] );
+           }
+        }
+      }
+
+
+      if (DO_OFFSET)
+      {
+        offset = ctx->Polygon.OffsetUnits * DEPTH_SCALE;
+        z[0] = VERT_Z(v[0]);
+        z[1] = VERT_Z(v[1]);
+        z[2] = VERT_Z(v[2]);
+        z[3] = VERT_Z(v[3]);
+        if (cc * cc > 1e-16) {
+           GLfloat ez = z[2] - z[0];
+           GLfloat fz = z[3] - z[1];
+           GLfloat a   = ey*fz - ez*fy;
+           GLfloat b   = ez*fx - ex*fz;
+           GLfloat ic  = 1.0 / cc;
+           GLfloat ac  = a * ic;
+           GLfloat bc  = b * ic;
+           if ( ac < 0.0f ) ac = -ac;
+           if ( bc < 0.0f ) bc = -bc;
+           offset += MAX2( ac, bc ) * ctx->Polygon.OffsetFactor;
+        }
+        offset *= ctx->MRD;
+      }
+   }
+
+   if (DO_FLAT) {
+      if (HAVE_RGBA) {
+        VERT_SAVE_RGBA( 0 );
+        VERT_SAVE_RGBA( 1 );
+        VERT_SAVE_RGBA( 2 );
+        VERT_COPY_RGBA( v[0], v[3] );
+        VERT_COPY_RGBA( v[1], v[3] );
+        VERT_COPY_RGBA( v[2], v[3] );
+        if (HAVE_SPEC && VB->SecondaryColorPtr[0]) {
+           VERT_SAVE_SPEC( 0 );
+           VERT_SAVE_SPEC( 1 );
+           VERT_SAVE_SPEC( 2 );
+           VERT_COPY_SPEC( v[0], v[3] );
+           VERT_COPY_SPEC( v[1], v[3] );
+           VERT_COPY_SPEC( v[2], v[3] );
+        }
+      }
+      else {
+        VERT_SAVE_IND( 0 );
+        VERT_SAVE_IND( 1 );
+        VERT_SAVE_IND( 2 );
+        VERT_COPY_IND( v[0], v[3] );
+        VERT_COPY_IND( v[1], v[3] );
+        VERT_COPY_IND( v[2], v[3] );
+      }
+   }
+
+   if (mode == GL_POINT) {
+      if (( DO_OFFSET) && ctx->Polygon.OffsetPoint) {
+        VERT_Z_ADD(v[0], offset);
+        VERT_Z_ADD(v[1], offset);
+        VERT_Z_ADD(v[2], offset);
+        VERT_Z_ADD(v[3], offset);
+      }
+      UNFILLED_QUAD( ctx, GL_POINT, e0, e1, e2, e3 );
+   } else if (mode == GL_LINE) {
+      if (DO_OFFSET && ctx->Polygon.OffsetLine) {
+        VERT_Z_ADD(v[0], offset);
+        VERT_Z_ADD(v[1], offset);
+        VERT_Z_ADD(v[2], offset);
+        VERT_Z_ADD(v[3], offset);
+      }
+      UNFILLED_QUAD( ctx, GL_LINE, e0, e1, e2, e3 );
+   } else {
+      if (DO_OFFSET && ctx->Polygon.OffsetFill) {
+        VERT_Z_ADD(v[0], offset);
+        VERT_Z_ADD(v[1], offset);
+        VERT_Z_ADD(v[2], offset);
+        VERT_Z_ADD(v[3], offset);
+      }
+      RASTERIZE( GL_TRIANGLES );
+      QUAD( (v[0]), (v[1]), (v[2]), (v[3]) );
+   }
+
+   if (DO_OFFSET)
+   {
+      VERT_SET_Z(v[0], z[0]);
+      VERT_SET_Z(v[1], z[1]);
+      VERT_SET_Z(v[2], z[2]);
+      VERT_SET_Z(v[3], z[3]);
+   }
+
+   if (DO_TWOSIDE && facing == 1)
+   {
+      if (HAVE_RGBA) {
+        if (!DO_FLAT) {
+           VERT_RESTORE_RGBA( 0 );
+           VERT_RESTORE_RGBA( 1 );
+           VERT_RESTORE_RGBA( 2 );
+        }
+        VERT_RESTORE_RGBA( 3 );
+        if (HAVE_SPEC) {
+           if (!DO_FLAT) {
+              VERT_RESTORE_SPEC( 0 );
+              VERT_RESTORE_SPEC( 1 );
+              VERT_RESTORE_SPEC( 2 );
+           }
+           VERT_RESTORE_SPEC( 3 );
+        }
+      }
+      else {
+        GLuint *vbindex = VB->IndexPtr[0]->data;
+        if (!DO_FLAT) {
+           VERT_SET_IND( v[0], vbindex[e0] );
+           VERT_SET_IND( v[1], vbindex[e1] );
+           VERT_SET_IND( v[2], vbindex[e2] );
+        }
+        VERT_SET_IND( v[3], vbindex[e3] );
+      }
+   }
+
+
+   if (DO_FLAT) {
+      if (HAVE_RGBA) {
+        VERT_RESTORE_RGBA( 0 );
+        VERT_RESTORE_RGBA( 1 );
+        VERT_RESTORE_RGBA( 2 );
+        if (HAVE_SPEC && VB->SecondaryColorPtr[0]) {
+           VERT_RESTORE_SPEC( 0 );
+           VERT_RESTORE_SPEC( 1 );
+           VERT_RESTORE_SPEC( 2 );
+        }
+      }
+      else {
+        VERT_RESTORE_IND( 0 );
+        VERT_RESTORE_IND( 1 );
+        VERT_RESTORE_IND( 2 );
+      }
+   }
+}
+#else
+static void TAG(quad)( GLcontext *ctx, GLuint e0,
+                      GLuint e1, GLuint e2, GLuint e3 )
+{
+   if (DO_UNFILLED) {
+      struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+      GLubyte ef1 = VB->EdgeFlag[e1];
+      GLubyte ef3 = VB->EdgeFlag[e3];
+      VB->EdgeFlag[e1] = 0;
+      TAG(triangle)( ctx, e0, e1, e3 );
+      VB->EdgeFlag[e1] = ef1;
+      VB->EdgeFlag[e3] = 0;
+      TAG(triangle)( ctx, e1, e2, e3 );
+      VB->EdgeFlag[e3] = ef3;
+   } else {
+      TAG(triangle)( ctx, e0, e1, e3 );
+      TAG(triangle)( ctx, e1, e2, e3 );
+   }
+}
+#endif
+#endif
+
+#if DO_LINE
+static void TAG(line)( GLcontext *ctx, GLuint e0, GLuint e1 )
+{
+   TNLvertexbuffer *VB = &TNL_CONTEXT(ctx)->vb;
+   VERTEX *v[2];
+   LOCAL_VARS(2);
+
+   v[0] = (VERTEX *)GET_VERTEX(e0);
+   v[1] = (VERTEX *)GET_VERTEX(e1);
+
+   if (DO_FLAT) {
+      if (HAVE_RGBA) {
+        VERT_SAVE_RGBA( 0 );
+        VERT_COPY_RGBA( v[0], v[1] );
+        if (HAVE_SPEC && VB->SecondaryColorPtr[0]) {
+           VERT_SAVE_SPEC( 0 );
+           VERT_COPY_SPEC( v[0], v[1] );
+        }
+      }
+      else {
+        VERT_SAVE_IND( 0 );
+        VERT_COPY_IND( v[0], v[1] );
+      }
+   }
+
+   LINE( v[0], v[1] );
+
+   if (DO_FLAT) {
+      if (HAVE_RGBA) {
+        VERT_RESTORE_RGBA( 0 );
+
+        if (HAVE_SPEC && VB->SecondaryColorPtr[0]) {
+           VERT_RESTORE_SPEC( 0 );
+        }
+      }
+      else {
+        VERT_RESTORE_IND( 0 );
+      }
+   }
+}
+#endif
+
+#if DO_POINTS
+static void TAG(points)( GLcontext *ctx, GLuint first, GLuint last )
+{
+   struct vertex_buffer *VB = &TNL_CONTEXT( ctx )->vb;
+   int i;
+   LOCAL_VARS(1);
+
+   if (VB->Elts == 0) {
+      for ( i = first ; i < last ; i++ ) {
+        if ( VB->ClipMask[i] == 0 ) {
+           VERTEX *v = (VERTEX *)GET_VERTEX(i);
+           POINT( v );
+        }
+      }
+   } else {
+      for ( i = first ; i < last ; i++ ) {
+        GLuint e = VB->Elts[i];
+        if ( VB->ClipMask[e] == 0 ) {
+           VERTEX *v = (VERTEX *)GET_VERTEX(e);
+           POINT( v );
+        }
+      }
+   }
+}
+#endif
+
+static void TAG(init)( void )
+{
+#if DO_QUAD
+   TAB[IND].quad = TAG(quad);
+#endif
+#if DO_TRI
+   TAB[IND].triangle = TAG(triangle);
+#endif
+#if DO_LINE
+   TAB[IND].line = TAG(line);
+#endif
+#if DO_POINTS
+   TAB[IND].points = TAG(points);
+#endif
+}
+
+#undef IND
+#undef TAG
+
+#if HAVE_RGBA
+#undef VERT_SET_IND
+#undef VERT_COPY_IND
+#undef VERT_SAVE_IND
+#undef VERT_RESTORE_IND
+#if HAVE_BACK_COLORS
+#undef VERT_SET_RGBA
+#endif
+#else
+#undef VERT_SET_RGBA
+#undef VERT_COPY_RGBA
+#undef VERT_SAVE_RGBA
+#undef VERT_RESTORE_RGBA
+#if HAVE_BACK_COLORS
+#undef VERT_SET_IND
+#endif
+#endif
+
+#if !HAVE_SPEC
+#undef VERT_SET_SPEC
+#undef VERT_COPY_SPEC
+#undef VERT_SAVE_SPEC
+#undef VERT_RESTORE_SPEC
+#if HAVE_BACK_COLORS
+#undef VERT_COPY_SPEC1
+#endif
+#else
+#if HAVE_BACK_COLORS
+#undef VERT_SET_SPEC
+#endif
+#endif
+
+#if !HAVE_BACK_COLORS
+#undef VERT_COPY_SPEC1
+#undef VERT_COPY_IND1
+#undef VERT_COPY_RGBA1
+#endif
+
+#ifndef INSANE_VERTICES
+#undef VERT_SET_Z
+#undef VERT_Z_ADD
+#endif
diff --git a/src/mesa/tnl_dd/t_dd_unfilled.h b/src/mesa/tnl_dd/t_dd_unfilled.h
new file mode 100644 (file)
index 0000000..46415ea
--- /dev/null
@@ -0,0 +1,212 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.5
+ *
+ * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#if HAVE_RGBA
+#define VERT_SET_IND( v, c )
+#define VERT_COPY_IND( v0, v1 )
+#define VERT_SAVE_IND( idx )
+#define VERT_RESTORE_IND( idx )
+#endif
+
+#if !HAVE_SPEC
+#define VERT_SET_SPEC( v, c )
+#define VERT_COPY_SPEC( v0, v1 )
+#define VERT_SAVE_SPEC( idx )
+#define VERT_RESTORE_SPEC( idx )
+#endif
+
+static void TAG(unfilled_tri)( GLcontext *ctx,
+                              GLenum mode,
+                              GLuint e0, GLuint e1, GLuint e2 )
+{
+   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+   GLubyte *ef = VB->EdgeFlag;
+   VERTEX *v[3];
+   LOCAL_VARS(3);
+
+   v[0] = (VERTEX *)GET_VERTEX(e0);
+   v[1] = (VERTEX *)GET_VERTEX(e1);
+   v[2] = (VERTEX *)GET_VERTEX(e2);
+
+   if ((ctx->_TriangleCaps & DD_FLATSHADE) && HAVE_HW_FLATSHADE) {
+      if (HAVE_RGBA) {
+        VERT_SAVE_RGBA(0);
+        VERT_SAVE_RGBA(1);
+        VERT_COPY_RGBA(v[0], v[2]);
+        VERT_COPY_RGBA(v[1], v[2]);
+
+        if (HAVE_SPEC) {
+           VERT_SAVE_SPEC(0);
+           VERT_SAVE_SPEC(1);
+           VERT_COPY_SPEC(v[0], v[2]);
+           VERT_COPY_SPEC(v[1], v[2]);
+        }
+      } else {
+        VERT_SAVE_IND(0);
+        VERT_SAVE_IND(1);
+        VERT_COPY_IND(v[0], v[2]);
+        VERT_COPY_IND(v[1], v[2]);
+      }
+   }
+
+/*     fprintf(stderr, "%s %s %d %d %d\n", __FUNCTION__, */
+/*        _mesa_lookup_enum_by_nr( mode ), */
+/*        ef[e0], ef[e1], ef[e2]); */
+
+   if (mode == GL_POINT) {
+      RASTERIZE(GL_POINTS);
+      if (ef[e0]) POINT( v[0] );
+      if (ef[e1]) POINT( v[1] );
+      if (ef[e2]) POINT( v[2] );
+   }
+   else {
+      RASTERIZE(GL_LINES);
+      if (RENDER_PRIMITIVE == GL_POLYGON) {
+        if (ef[e2]) LINE( v[2], v[0] );
+        if (ef[e0]) LINE( v[0], v[1] );
+        if (ef[e1]) LINE( v[1], v[2] );
+      }
+      else {
+        if (ef[e0]) LINE( v[0], v[1] );
+        if (ef[e1]) LINE( v[1], v[2] );
+        if (ef[e2]) LINE( v[2], v[0] );
+      }
+   }
+
+   if ((ctx->_TriangleCaps & DD_FLATSHADE) && HAVE_HW_FLATSHADE) {
+      if (HAVE_RGBA) {
+        VERT_RESTORE_RGBA(0);
+        VERT_RESTORE_RGBA(1);
+
+        if (HAVE_SPEC) {
+           VERT_RESTORE_SPEC(0);
+           VERT_RESTORE_SPEC(1);
+        }
+      } else {
+        VERT_RESTORE_IND(0);
+        VERT_RESTORE_IND(1);
+      }
+   }
+}
+
+
+static void TAG(unfilled_quad)( GLcontext *ctx,
+                               GLenum mode,
+                               GLuint e0, GLuint e1,
+                               GLuint e2, GLuint e3 )
+{
+   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+   GLubyte *ef = VB->EdgeFlag;
+   VERTEX *v[4];
+   LOCAL_VARS(4);
+
+   v[0] = (VERTEX *)GET_VERTEX(e0);
+   v[1] = (VERTEX *)GET_VERTEX(e1);
+   v[2] = (VERTEX *)GET_VERTEX(e2);
+   v[3] = (VERTEX *)GET_VERTEX(e3);
+
+   /* Hardware flatshading breaks down here.  If the hardware doesn't
+    * support flatshading, this will already have been done:
+    */
+   if ((ctx->_TriangleCaps & DD_FLATSHADE) && HAVE_HW_FLATSHADE) {
+      if (HAVE_RGBA) {
+        VERT_SAVE_RGBA(0);
+        VERT_SAVE_RGBA(1);
+        VERT_SAVE_RGBA(2);
+        VERT_COPY_RGBA(v[0], v[3]);
+        VERT_COPY_RGBA(v[1], v[3]);
+        VERT_COPY_RGBA(v[2], v[3]);
+
+        if (HAVE_SPEC) {
+           VERT_SAVE_SPEC(0);
+           VERT_SAVE_SPEC(1);
+           VERT_SAVE_SPEC(2);
+           VERT_COPY_SPEC(v[0], v[3]);
+           VERT_COPY_SPEC(v[1], v[3]);
+           VERT_COPY_SPEC(v[2], v[3]);
+        }
+      } else {
+        VERT_SAVE_IND(0);
+        VERT_SAVE_IND(1);
+        VERT_SAVE_IND(2);
+        VERT_COPY_IND(v[0], v[3]);
+        VERT_COPY_IND(v[1], v[3]);
+        VERT_COPY_IND(v[2], v[3]);
+      }
+   }
+
+   if (mode == GL_POINT) {
+      RASTERIZE(GL_POINTS);
+      if (ef[e0]) POINT( v[0] );
+      if (ef[e1]) POINT( v[1] );
+      if (ef[e2]) POINT( v[2] );
+      if (ef[e3]) POINT( v[3] );
+   }
+   else {
+      RASTERIZE(GL_LINES);
+      if (ef[e0]) LINE( v[0], v[1] );
+      if (ef[e1]) LINE( v[1], v[2] );
+      if (ef[e2]) LINE( v[2], v[3] );
+      if (ef[e3]) LINE( v[3], v[0] );
+   }
+
+   if ((ctx->_TriangleCaps & DD_FLATSHADE) && HAVE_HW_FLATSHADE) {
+      if (HAVE_RGBA) {
+        VERT_RESTORE_RGBA(0);
+        VERT_RESTORE_RGBA(1);
+        VERT_RESTORE_RGBA(2);
+
+        if (HAVE_SPEC) {
+           VERT_RESTORE_SPEC(0);
+           VERT_RESTORE_SPEC(1);
+           VERT_RESTORE_SPEC(2);
+        }
+      } else {
+        VERT_RESTORE_IND(0);
+        VERT_RESTORE_IND(1);
+        VERT_RESTORE_IND(2);
+      }
+   }
+}
+
+
+#if HAVE_RGBA
+#undef VERT_SET_IND
+#undef VERT_COPY_IND
+#undef VERT_SAVE_IND
+#undef VERT_RESTORE_IND
+#endif
+
+#if !HAVE_SPEC
+#undef VERT_SET_SPEC
+#undef VERT_COPY_SPEC
+#undef VERT_SAVE_SPEC
+#undef VERT_RESTORE_SPEC
+#endif
+
+#undef TAG
diff --git a/src/mesa/tnl_dd/t_dd_vb.c b/src/mesa/tnl_dd/t_dd_vb.c
new file mode 100644 (file)
index 0000000..4a742bc
--- /dev/null
@@ -0,0 +1,392 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  3.5
+ *
+ * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ */
+#include "math/m_translate.h"
+
+#if (HAVE_HW_VIEWPORT)
+#define UNVIEWPORT_VARS
+#define UNVIEWPORT_X(x) x
+#define UNVIEWPORT_Y(x) x
+#define UNVIEWPORT_Z(x) x
+#endif
+
+#ifndef LOCALVARS
+#define LOCALVARS
+#endif
+
+#ifndef CHECK_HW_DIVIDE
+#define CHECK_HW_DIVIDE 1
+#endif
+
+/* These don't need to be duplicated, but there's currently nowhere
+ * really convenient to put them.  Need to build some actual .o files in
+ * this directory?
+ */
+static void copy_pv_rgba4_spec5( GLcontext *ctx, GLuint edst, GLuint esrc )
+{
+   LOCALVARS   
+   GLubyte *verts = GET_VERTEX_STORE();
+   GLuint shift = GET_VERTEX_STRIDE_SHIFT();
+   GLuint *dst = (GLuint *)(verts + (edst << shift));
+   GLuint *src = (GLuint *)(verts + (esrc << shift));
+   dst[4] = src[4];
+   dst[5] = src[5];
+}
+
+static void copy_pv_rgba4( GLcontext *ctx, GLuint edst, GLuint esrc )
+{
+   LOCALVARS
+   GLubyte *verts = GET_VERTEX_STORE();
+   GLuint shift = GET_VERTEX_STRIDE_SHIFT();
+   GLuint *dst = (GLuint *)(verts + (edst << shift));
+   GLuint *src = (GLuint *)(verts + (esrc << shift));
+   dst[4] = src[4];
+}
+
+static void copy_pv_rgba3( GLcontext *ctx, GLuint edst, GLuint esrc )
+{
+   LOCALVARS
+   GLubyte *verts = GET_VERTEX_STORE();
+   GLuint shift = GET_VERTEX_STRIDE_SHIFT();
+   GLuint *dst = (GLuint *)(verts + (edst << shift));
+   GLuint *src = (GLuint *)(verts + (esrc << shift));
+   dst[3] = src[3];
+}
+
+
+void TAG(translate_vertex)(GLcontext *ctx,
+                          const VERTEX *src,
+                          SWvertex *dst)
+{
+   LOCALVARS
+   GLuint format = GET_VERTEX_FORMAT();
+   GLfloat *s = ctx->Viewport._WindowMap.m;
+   UNVIEWPORT_VARS;
+
+   if (format == TINY_VERTEX_FORMAT) {
+      if (HAVE_HW_VIEWPORT) {
+        dst->win[0] = s[0]  * src->v.x + s[12];
+        dst->win[1] = s[5]  * src->v.y + s[13];
+        dst->win[2] = s[10] * src->v.z + s[14];
+        dst->win[3] = 1.0;
+      } else {
+        dst->win[0] = UNVIEWPORT_X( src->v.x );
+        dst->win[1] = UNVIEWPORT_Y( src->v.y );
+        dst->win[2] = UNVIEWPORT_Z( src->v.z );
+        dst->win[3] = 1.0;
+      }
+
+      dst->color[0] = src->tv.color.red;
+      dst->color[1] = src->tv.color.green;
+      dst->color[2] = src->tv.color.blue;
+      dst->color[3] = src->tv.color.alpha;
+   }
+   else {
+      if (HAVE_HW_VIEWPORT) {
+        if (HAVE_HW_DIVIDE && CHECK_HW_DIVIDE) {
+           GLfloat oow = 1.0 / src->v.w;
+           dst->win[0] = s[0]  * src->v.x * oow + s[12];
+           dst->win[1] = s[5]  * src->v.y * oow + s[13];
+           dst->win[2] = s[10] * src->v.z * oow + s[14];
+           dst->win[3] = oow;
+        } else {
+           dst->win[0] = s[0]  * src->v.x + s[12];
+           dst->win[1] = s[5]  * src->v.y + s[13];
+           dst->win[2] = s[10] * src->v.z + s[14];
+           dst->win[3] = src->v.w;
+        }
+      } else {
+        dst->win[0] = UNVIEWPORT_X( src->v.x );
+        dst->win[1] = UNVIEWPORT_Y( src->v.y );
+        dst->win[2] = UNVIEWPORT_Z( src->v.z );
+        dst->win[3] = src->v.w;
+      }
+
+      dst->color[0] = src->v.color.red;
+      dst->color[1] = src->v.color.green;
+      dst->color[2] = src->v.color.blue;
+      dst->color[3] = src->v.color.alpha;
+
+      dst->specular[0] = src->v.specular.red;
+      dst->specular[1] = src->v.specular.green;
+      dst->specular[2] = src->v.specular.blue;
+
+      dst->fog = src->v.specular.alpha/255.0;
+
+      if (HAVE_PTEX_VERTICES &&
+         ((HAVE_TEX2_VERTICES && format == PROJ_TEX3_VERTEX_FORMAT) ||
+          (format == PROJ_TEX1_VERTEX_FORMAT))) {
+
+        dst->texcoord[0][0] = src->pv.u0;
+        dst->texcoord[0][1] = src->pv.v0;
+        dst->texcoord[0][3] = src->pv.q0;
+
+        dst->texcoord[1][0] = src->pv.u1;
+        dst->texcoord[1][1] = src->pv.v1;
+        dst->texcoord[1][3] = src->pv.q1;
+
+        if (HAVE_TEX2_VERTICES) {
+           dst->texcoord[2][0] = src->pv.u2;
+           dst->texcoord[2][1] = src->pv.v2;
+           dst->texcoord[2][3] = src->pv.q2;
+        }
+
+        if (HAVE_TEX3_VERTICES) {
+           dst->texcoord[3][0] = src->pv.u3;
+           dst->texcoord[3][1] = src->pv.v3;
+           dst->texcoord[3][3] = src->pv.q3;
+        }
+      }
+      else {
+        dst->texcoord[0][0] = src->v.u0;
+        dst->texcoord[0][1] = src->v.v0;
+        dst->texcoord[0][3] = 1.0;
+
+        dst->texcoord[1][0] = src->v.u1;
+        dst->texcoord[1][1] = src->v.v1;
+        dst->texcoord[1][3] = 1.0;
+
+        if (HAVE_TEX2_VERTICES) {
+           dst->texcoord[2][0] = src->v.u2;
+           dst->texcoord[2][1] = src->v.v2;
+           dst->texcoord[2][3] = 1.0;
+        }
+
+        if (HAVE_TEX3_VERTICES) {
+           dst->texcoord[3][0] = src->v.u3;
+           dst->texcoord[3][1] = src->v.v3;
+           dst->texcoord[3][3] = 1.0;
+        }
+      }
+   }
+
+   dst->pointSize = ctx->Point._Size;
+}
+
+
+
+void TAG(print_vertex)( GLcontext *ctx, const VERTEX *v )
+{
+   LOCALVARS
+   GLuint format = GET_VERTEX_FORMAT();
+
+   fprintf(stderr, "(%x) ", format);
+
+   switch (format) {
+#if HAVE_TINY_VERTICES
+   case TINY_VERTEX_FORMAT:
+      fprintf(stderr, "xyz %.4f,%.4f,%.4f rgba %x:%x:%x:%x\n",
+             v->v.x, v->v.y, v->v.z,
+             v->tv.color.red,
+             v->tv.color.green,
+             v->tv.color.blue,
+             v->tv.color.alpha);
+      break;
+#endif
+#if HAVE_NOTEX_VERTICES
+   case NOTEX_VERTEX_FORMAT:
+      fprintf(stderr, "xyzw %.4f,%.4f,%.4f,%.4f rgba %x:%x:%x:%x spec %x:%x:%x:%x\n",
+             v->v.x, v->v.y, v->v.z, v->v.w,
+             v->v.color.red,
+             v->v.color.green,
+             v->v.color.blue,
+             v->v.color.alpha,
+             v->v.specular.red,
+             v->v.specular.green,
+             v->v.specular.blue,
+             v->v.specular.alpha);
+      break;
+#endif
+#if HAVE_TEX0_VERTICES
+   case TEX0_VERTEX_FORMAT:
+      fprintf(stderr, "xyzw %.4f,%.4f,%.4f,%.4f rgba %x:%x:%x:%x st %.4f,%.4f\n",
+             v->v.x, v->v.y, v->v.z, v->v.w,
+             v->v.color.red,
+             v->v.color.green,
+             v->v.color.blue,
+             v->v.color.alpha,
+             v->v.u0,
+             v->v.v0);
+      break;
+#endif
+#if HAVE_TEX1_VERTICES
+   case TEX1_VERTEX_FORMAT:
+      fprintf(stderr, "xyzw %.4f,%.4f,%.4f,%.4f rgba %x:%x:%x:%x st %.4f,%.4f st %.4f,%.4f\n",
+             v->v.x, v->v.y, v->v.z, v->v.w,
+             v->v.color.red,
+             v->v.color.green,
+             v->v.color.blue,
+             v->v.color.alpha,
+             v->v.u0,
+             v->v.v0,
+             v->v.u1,
+             v->v.u2);
+      break;
+#endif
+#if HAVE_PTEX_VERTICES
+   case PROJ_TEX1_VERTEX_FORMAT:
+      fprintf(stderr, "xyzw %.4f,%.4f,%.4f,%.4f rgba %x:%x:%x:%x stq %.4f,%.4f,%.4f stq %.4f,%.4f,%.4f\n",
+             v->v.x, v->v.y, v->v.z, v->v.w,
+             v->v.color.red,
+             v->v.color.green,
+             v->v.color.blue,
+             v->v.color.alpha,
+             v->pv.u0,
+             v->pv.v0,
+             v->pv.q0,
+             v->pv.u1,
+             v->pv.v1,
+             v->pv.q1);
+      break;
+#endif      
+   default:
+      fprintf(stderr, "???\n");
+      break;
+   }
+
+   fprintf(stderr, "\n");
+}
+
+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(GLubyte), 32 );
+      to->Type = GL_UNSIGNED_BYTE;
+   }
+
+   /* No need to transform the same value 3000 times.
+    */
+   if (!from->StrideB) {
+      to->StrideB = 0;
+      count = 1;
+   }
+   else
+      to->StrideB = 4 * sizeof(GLubyte);
+   
+   _math_trans_4ub( (GLubyte (*)[4]) to->Ptr,
+                   from->Ptr,
+                   from->StrideB,
+                   from->Type,
+                   from->Size,
+                   0,
+                   count);
+}
+
+#ifndef IMPORT_QUALIFIER
+#define IMPORT_QUALIFIER static
+#endif
+
+IMPORT_QUALIFIER void TAG(import_float_colors)( GLcontext *ctx )
+{
+   LOCALVARS
+   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+   struct gl_client_array *to = GET_UBYTE_COLOR_STORE();
+   do_import( VB, to, VB->ColorPtr[0] );
+   VB->ColorPtr[0] = to;
+}
+
+IMPORT_QUALIFIER void TAG(import_float_spec_colors)( GLcontext *ctx )
+{
+   LOCALVARS
+   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+   struct gl_client_array *to = GET_UBYTE_SPEC_COLOR_STORE();
+   do_import( VB, to, VB->SecondaryColorPtr[0] );
+   VB->SecondaryColorPtr[0] = to;
+}
+
+/* Interpolate the elements of the VB not included in typical hardware
+ * vertices.  
+ *
+ * NOTE: All these arrays are guarenteed by tnl to be writeable and
+ * have good stride.
+ */
+#ifndef INTERP_QUALIFIER 
+#define INTERP_QUALIFIER static
+#endif
+
+#define GET_COLOR(ptr, idx) (((GLchan (*)[4])((ptr)->Ptr))[idx])
+
+
+INTERP_QUALIFIER void TAG(interp_extras)( GLcontext *ctx,
+                                         GLfloat t,
+                                         GLuint dst, GLuint out, GLuint in,
+                                         GLboolean force_boundary )
+{
+   LOCALVARS
+   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+   if (VB->ColorPtr[1]) {
+      INTERP_4CHAN( t,
+                   GET_COLOR(VB->ColorPtr[1], dst),
+                   GET_COLOR(VB->ColorPtr[1], out),
+                   GET_COLOR(VB->ColorPtr[1], in) );
+
+      if (VB->SecondaryColorPtr[1]) {
+        INTERP_3CHAN( t,
+                      GET_COLOR(VB->SecondaryColorPtr[1], dst),
+                      GET_COLOR(VB->SecondaryColorPtr[1], out),
+                      GET_COLOR(VB->SecondaryColorPtr[1], in) );
+      }
+   }
+
+   if (VB->EdgeFlag) {
+      VB->EdgeFlag[dst] = VB->EdgeFlag[out] || force_boundary;
+   }
+
+   INTERP_VERTEX(ctx, t, dst, out, in, force_boundary);
+}
+
+INTERP_QUALIFIER void TAG(copy_pv_extras)( GLcontext *ctx, 
+                                          GLuint dst, GLuint src )
+{
+   LOCALVARS
+      struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+   if (VB->ColorPtr[1]) {
+      COPY_CHAN4( GET_COLOR(VB->ColorPtr[1], dst), 
+                 GET_COLOR(VB->ColorPtr[1], src) );
+
+      if (VB->SecondaryColorPtr[1]) {
+        COPY_CHAN4( GET_COLOR(VB->SecondaryColorPtr[1], dst), 
+                    GET_COLOR(VB->SecondaryColorPtr[1], src) );
+      }
+   }
+
+   COPY_PV_VERTEX(ctx, dst, src);
+}
+
+
+#undef INTERP_QUALIFIER
+#undef IMPORT_QUALIFIER
+#undef GET_COLOR
+
+#undef IND
+#undef TAG
diff --git a/src/mesa/tnl_dd/t_dd_vbtmp.h b/src/mesa/tnl_dd/t_dd_vbtmp.h
new file mode 100644 (file)
index 0000000..5aad0b5
--- /dev/null
@@ -0,0 +1,834 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  5.0.1
+ *
+ * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+/* Unlike the other templates here, this assumes quite a bit about the
+ * underlying hardware.  Specifically it assumes a d3d-like vertex
+ * format, with a layout more or less constrained to look like the
+ * following:
+ *
+ * union {
+ *    struct {
+ *        float x, y, z, w;
+ *        struct { char r, g, b, a; } color;
+ *        struct { char r, g, b, fog; } spec;
+ *        float u0, v0;
+ *        float u1, v1;
+ *        float u2, v2;
+ *        float u3, v3;
+ *    } v;
+ *    struct {
+ *        float x, y, z, w;
+ *        struct { char r, g, b, a; } color;
+ *        struct { char r, g, b, fog; } spec;
+ *        float u0, v0, q0;
+ *        float u1, v1, q1;
+ *        float u2, v2, q2;
+ *        float u3, v3, q3;
+ *    } pv;
+ *    struct {
+ *        float x, y, z;
+ *        struct { char r, g, b, a; } color;
+ *    } tv;
+ *    float f[16];
+ *    unsigned int ui[16];
+ *    unsigned char ub4[4][16];
+ * }
+ *
+ * VERTEX:   hw vertex type as above
+ * VERTEX_COLOR: hw color struct type in VERTEX
+ *
+ * DO_XYZW:  Emit xyz and maybe w coordinates.
+ * DO_RGBA:  Emit color.
+ * DO_SPEC:  Emit specular color.
+ * DO_FOG:   Emit fog coordinate in specular alpha.
+ * DO_TEX0:  Emit tex0 u,v coordinates.
+ * DO_TEX1:  Emit tex1 u,v coordinates.
+ * DO_TEX2:  Emit tex2 u,v coordinates.
+ * DO_TEX3:  Emit tex3 u,v coordinates.
+ * DO_PTEX:  Emit tex0,1,2,3 q coordinates where possible.
+ *
+ * HAVE_RGBA_COLOR: Hardware takes color in rgba order (else bgra).
+ *
+ * HAVE_HW_VIEWPORT:  Hardware performs viewport transform.
+ * HAVE_HW_DIVIDE:  Hardware performs perspective divide.
+ *
+ * HAVE_TINY_VERTICES:  Hardware understands v.tv format.
+ * HAVE_PTEX_VERTICES:  Hardware understands v.pv format.
+ * HAVE_NOTEX_VERTICES:  Hardware understands v.v format with texcount 0.
+ *
+ * Additionally, this template assumes it is emitting *transformed*
+ * vertices; the modifications to emit untransformed vertices (ie. to
+ * t&l hardware) are probably too great to cooexist with the code
+ * already in this file.
+ *
+ * NOTE: The PTEX vertex format always includes TEX0 and TEX1, even if
+ * only TEX0 is enabled, in order to maintain a vertex size which is
+ * an exact number of quadwords.
+ */
+
+#if (HAVE_HW_VIEWPORT)
+#define VIEWPORT_X(dst,x) dst = x
+#define VIEWPORT_Y(dst,y) dst = y
+#define VIEWPORT_Z(dst,z) dst = z
+#else
+#define VIEWPORT_X(dst,x) dst = s[0]  * x + s[12]
+#define VIEWPORT_Y(dst,y) dst = s[5]  * y + s[13]
+#define VIEWPORT_Z(dst,z) dst = s[10] * z + s[14]
+#endif
+
+#if (HAVE_HW_DIVIDE && !HAVE_PTEX_VERTICES)
+#error "can't cope with this combination" 
+#endif 
+
+#ifndef LOCALVARS
+#define LOCALVARS
+#endif
+
+#ifndef CHECK_HW_DIVIDE
+#define CHECK_HW_DIVIDE 1
+#endif
+
+#if (HAVE_HW_DIVIDE || DO_SPEC || DO_TEX0 || DO_FOG || !HAVE_TINY_VERTICES)
+
+static void TAG(emit)( GLcontext *ctx,
+                      GLuint start, GLuint end,
+                      void *dest,
+                      GLuint stride )
+{
+   LOCALVARS
+   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+   GLfloat (*tc0)[4], (*tc1)[4], (*fog)[4];
+   GLfloat (*tc2)[4], (*tc3)[4];
+   GLubyte (*col)[4], (*spec)[4];
+   GLuint tc0_stride, tc1_stride, col_stride, spec_stride, fog_stride;
+   GLuint tc2_stride, tc3_stride;
+   GLuint tc0_size, tc1_size;
+   GLuint tc2_size, tc3_size;
+   GLfloat (*coord)[4];
+   GLuint coord_stride;
+   VERTEX *v = (VERTEX *)dest;
+   const GLfloat *s = GET_VIEWPORT_MAT();
+   const GLubyte *mask = VB->ClipMask;
+   int i;
+
+/*     fprintf(stderr, "%s(big) importable %d %d..%d\n",  */
+/*        __FUNCTION__, VB->importable_data, start, end); */
+
+   if (HAVE_HW_VIEWPORT && HAVE_HW_DIVIDE && CHECK_HW_DIVIDE) {
+      (void) s;
+      coord = VB->ClipPtr->data;
+      coord_stride = VB->ClipPtr->stride;
+   }
+   else {
+      coord = VB->NdcPtr->data;
+      coord_stride = VB->NdcPtr->stride;
+   }
+
+   if (DO_TEX3) {
+      const GLuint t3 = GET_TEXSOURCE(3);
+      tc3 = VB->TexCoordPtr[t3]->data;
+      tc3_stride = VB->TexCoordPtr[t3]->stride;
+      if (DO_PTEX)
+        tc3_size = VB->TexCoordPtr[t3]->size;
+   }
+
+   if (DO_TEX2) {
+      const GLuint t2 = GET_TEXSOURCE(2);
+      tc2 = VB->TexCoordPtr[t2]->data;
+      tc2_stride = VB->TexCoordPtr[t2]->stride;
+      if (DO_PTEX)
+        tc2_size = VB->TexCoordPtr[t2]->size;
+   }
+
+   if (DO_TEX1) {
+      const GLuint t1 = GET_TEXSOURCE(1);
+      tc1 = VB->TexCoordPtr[t1]->data;
+      tc1_stride = VB->TexCoordPtr[t1]->stride;
+      if (DO_PTEX)
+        tc1_size = VB->TexCoordPtr[t1]->size;
+   }
+
+   if (DO_TEX0) {
+      const GLuint t0 = GET_TEXSOURCE(0);
+      tc0_stride = VB->TexCoordPtr[t0]->stride;
+      tc0 = VB->TexCoordPtr[t0]->data;
+      if (DO_PTEX) 
+        tc0_size = VB->TexCoordPtr[t0]->size;
+   }
+
+   if (DO_RGBA) {
+      if (VB->ColorPtr[0]->Type != GL_UNSIGNED_BYTE)
+        IMPORT_FLOAT_COLORS( ctx );
+      col = (GLubyte (*)[4])VB->ColorPtr[0]->Ptr;
+      col_stride = VB->ColorPtr[0]->StrideB;
+   }
+
+   if (DO_SPEC) {
+      if (VB->SecondaryColorPtr[0]) {
+        if (VB->SecondaryColorPtr[0]->Type != GL_UNSIGNED_BYTE)
+           IMPORT_FLOAT_SPEC_COLORS( ctx );
+        spec = (GLubyte (*)[4])VB->SecondaryColorPtr[0]->Ptr;
+        spec_stride = VB->SecondaryColorPtr[0]->StrideB;
+      } else {
+        GLubyte tmp[4];
+        spec = &tmp;
+        spec_stride = 0;
+      }
+   }
+
+   if (DO_FOG) {
+      if (VB->FogCoordPtr) {
+        fog = VB->FogCoordPtr->data;
+        fog_stride = VB->FogCoordPtr->stride;
+      }
+      else {
+        static GLfloat tmp[4] = {0, 0, 0, 0};
+        fog = &tmp;
+        fog_stride = 0;
+      }
+   }
+
+   if (VB->importable_data || (DO_SPEC && !spec_stride) || (DO_FOG && !fog_stride)) {
+      /* May have nonstandard strides:
+       */
+      if (start) {
+        coord =  (GLfloat (*)[4])((GLubyte *)coord + start * coord_stride);
+        if (DO_TEX0)
+           tc0 =  (GLfloat (*)[4])((GLubyte *)tc0 + start * tc0_stride);
+        if (DO_TEX1) 
+           tc1 =  (GLfloat (*)[4])((GLubyte *)tc1 + start * tc1_stride);
+        if (DO_TEX2) 
+           tc2 =  (GLfloat (*)[4])((GLubyte *)tc2 + start * tc2_stride);
+        if (DO_TEX3) 
+           tc3 =  (GLfloat (*)[4])((GLubyte *)tc3 + start * tc3_stride);
+        if (DO_RGBA) 
+           STRIDE_4UB(col, start * col_stride);
+        if (DO_SPEC)
+           STRIDE_4UB(spec, start * spec_stride);
+        if (DO_FOG)
+           /*STRIDE_F(fog, start * fog_stride);*/
+           fog =  (GLfloat (*)[4])((GLubyte *)fog + start * fog_stride);
+      }
+
+      for (i=start; i < end; i++, v = (VERTEX *)((GLubyte *)v + stride)) {
+        if (DO_XYZW) {
+           if (HAVE_HW_VIEWPORT || mask[i] == 0) {
+              VIEWPORT_X(v->v.x, coord[0][0]);
+              VIEWPORT_Y(v->v.y, coord[0][1]);
+              VIEWPORT_Z(v->v.z, coord[0][2]);
+              v->v.w = coord[0][3];
+           }
+/*         fprintf(stderr, "vert %d: %.2f %.2f %.2f %.2f\n",  */
+/*                 i, v->v.x, v->v.y, v->v.z, v->v.w); */
+           coord =  (GLfloat (*)[4])((GLubyte *)coord +  coord_stride);
+        }
+        if (DO_RGBA) {
+           if (HAVE_RGBA_COLOR) {
+              *(GLuint *)&v->v.color = LE32_TO_CPU(*(GLuint *)&col[0]);
+              STRIDE_4UB(col, col_stride);
+           } else {
+              v->v.color.blue  = col[0][2];
+              v->v.color.green = col[0][1];
+              v->v.color.red   = col[0][0];
+              v->v.color.alpha = col[0][3];
+              STRIDE_4UB(col, col_stride);
+           }
+        }
+        if (DO_SPEC) {
+           v->v.specular.red = spec[0][0];
+           v->v.specular.green = spec[0][1];
+           v->v.specular.blue = spec[0][2];
+           STRIDE_4UB(spec, spec_stride);
+        }
+        if (DO_FOG) {
+           v->v.specular.alpha = fog[0][0] * 255.0;
+           /*STRIDE_F(fog, fog_stride);*/
+           fog =  (GLfloat (*)[4])((GLubyte *)fog + fog_stride);
+        }
+        if (DO_TEX0) {
+           v->v.u0 = tc0[0][0];
+           v->v.v0 = tc0[0][1];
+           if (DO_PTEX) {
+              if (HAVE_PTEX_VERTICES) {
+                 if (tc0_size == 4) 
+                    v->pv.q0 = tc0[0][3];
+                 else
+                    v->pv.q0 = 1.0;
+              } 
+              else if (tc0_size == 4) {
+                 float rhw = 1.0 / tc0[0][3];
+                 v->v.w *= tc0[0][3];
+                 v->v.u0 *= rhw;
+                 v->v.v0 *= rhw;
+              } 
+           } 
+           tc0 =  (GLfloat (*)[4])((GLubyte *)tc0 +  tc0_stride);
+        }
+        if (DO_TEX1) {
+           if (DO_PTEX) {
+              v->pv.u1 = tc1[0][0];
+              v->pv.v1 = tc1[0][1];
+              if (tc1_size == 4) 
+                 v->pv.q1 = tc1[0][3];
+              else
+                 v->pv.q1 = 1.0;
+           } 
+           else {
+              v->v.u1 = tc1[0][0];
+              v->v.v1 = tc1[0][1];
+           }
+           tc1 =  (GLfloat (*)[4])((GLubyte *)tc1 +  tc1_stride);
+        } 
+        else if (DO_PTEX) {
+           *(GLuint *)&v->pv.q1 = 0;   /* avoid culling on radeon */
+        }
+        if (DO_TEX2) {
+           if (DO_PTEX) {
+              v->pv.u2 = tc2[0][0];
+              v->pv.v2 = tc2[0][1];
+              if (tc2_size == 4) 
+                 v->pv.q2 = tc2[0][3];
+              else
+                 v->pv.q2 = 1.0;
+           } 
+           else {
+              v->v.u2 = tc2[0][0];
+              v->v.v2 = tc2[0][1];
+           }
+           tc2 =  (GLfloat (*)[4])((GLubyte *)tc2 +  tc2_stride);
+        } 
+        if (DO_TEX3) {
+           if (DO_PTEX) {
+              v->pv.u3 = tc3[0][0];
+              v->pv.v3 = tc3[0][1];
+              if (tc3_size == 4) 
+                 v->pv.q3 = tc3[0][3];
+              else
+                 v->pv.q3 = 1.0;
+           } 
+           else {
+              v->v.u3 = tc3[0][0];
+              v->v.v3 = tc3[0][1];
+           }
+           tc3 =  (GLfloat (*)[4])((GLubyte *)tc3 +  tc3_stride);
+        } 
+      }
+   }
+   else {
+      for (i=start; i < end; i++, v = (VERTEX *)((GLubyte *)v + stride)) {
+        if (DO_XYZW) {
+           if (HAVE_HW_VIEWPORT || mask[i] == 0) {
+              VIEWPORT_X(v->v.x, coord[i][0]);
+              VIEWPORT_Y(v->v.y, coord[i][1]);
+              VIEWPORT_Z(v->v.z, coord[i][2]);
+              v->v.w = coord[i][3];
+           }
+        }
+        if (DO_RGBA) {
+           if (HAVE_RGBA_COLOR) {
+              *(GLuint *)&v->v.color = LE32_TO_CPU(*(GLuint *)&col[i]);
+           }
+           else {
+              v->v.color.blue  = col[i][2];
+              v->v.color.green = col[i][1];
+              v->v.color.red   = col[i][0];
+              v->v.color.alpha = col[i][3];
+           }
+        }
+        if (DO_SPEC) {
+           v->v.specular.red   = spec[i][0];
+           v->v.specular.green = spec[i][1];
+           v->v.specular.blue  = spec[i][2];
+        }
+        if (DO_FOG) {
+           v->v.specular.alpha = fog[i][0] * 255.0;
+        }
+        if (DO_TEX0) {
+           v->v.u0 = tc0[i][0];
+           v->v.v0 = tc0[i][1];
+           if (DO_PTEX) {
+              if (HAVE_PTEX_VERTICES) {
+                 if (tc0_size == 4) 
+                    v->pv.q0 = tc0[i][3];
+                 else
+                    v->pv.q0 = 1.0;
+
+                 v->pv.q1 = 0; /* radeon */
+              } 
+              else if (tc0_size == 4) {
+                 float rhw = 1.0 / tc0[i][3];
+                 v->v.w *= tc0[i][3];
+                 v->v.u0 *= rhw;
+                 v->v.v0 *= rhw;
+              } 
+           } 
+        }
+        if (DO_TEX1) {
+           if (DO_PTEX) {
+              v->pv.u1 = tc1[i][0];
+              v->pv.v1 = tc1[i][1];
+              if (tc1_size == 4) 
+                 v->pv.q1 = tc1[i][3];
+              else
+                 v->pv.q1 = 1.0;
+           } 
+           else {
+              v->v.u1 = tc1[i][0];
+              v->v.v1 = tc1[i][1];
+           }
+        }
+      }
+   }
+}
+#else
+#if DO_XYZW
+
+#if HAVE_HW_DIVIDE
+#error "cannot use tiny vertices with hw perspective divide"
+#endif
+
+static void TAG(emit)( GLcontext *ctx, GLuint start, GLuint end,
+                      void *dest, GLuint stride )
+{
+   LOCALVARS
+   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+   GLubyte (*col)[4];
+   GLuint col_stride;
+   GLfloat (*coord)[4] = VB->NdcPtr->data;
+   GLuint coord_stride = VB->NdcPtr->stride;
+   GLfloat *v = (GLfloat *)dest;
+   const GLubyte *mask = VB->ClipMask;
+   const GLfloat *s = GET_VIEWPORT_MAT();
+   int i;
+
+   (void) s;
+
+   ASSERT(stride == 4);
+
+   if (VB->ColorPtr[0]->Type != GL_UNSIGNED_BYTE)
+      IMPORT_FLOAT_COLORS( ctx );
+
+   col = (GLubyte (*)[4])VB->ColorPtr[0]->Ptr;
+   col_stride = VB->ColorPtr[0]->StrideB;
+   ASSERT(VB->ColorPtr[0]->Type == GL_UNSIGNED_BYTE);
+
+/*     fprintf(stderr, "%s(small) importable %x\n",  */
+/*        __FUNCTION__, VB->importable_data); */
+
+   /* Pack what's left into a 4-dword vertex.  Color is in a different
+    * place, and there is no 'w' coordinate.
+    */
+   if (VB->importable_data) {
+      if (start) {
+        coord =  (GLfloat (*)[4])((GLubyte *)coord + start * coord_stride);
+        STRIDE_4UB(col, start * col_stride);
+      }
+
+      for (i=start; i < end; i++, v+=4) {
+        if (HAVE_HW_VIEWPORT || mask[i] == 0) {
+           VIEWPORT_X(v[0], coord[0][0]);
+           VIEWPORT_Y(v[1], coord[0][1]);
+           VIEWPORT_Z(v[2], coord[0][2]);
+        }
+        coord =  (GLfloat (*)[4])((GLubyte *)coord +  coord_stride);
+        if (DO_RGBA) {
+           if (HAVE_RGBA_COLOR) {
+              *(GLuint *)&v[3] = LE32_TO_CPU(*(GLuint *)col);
+           }
+           else {
+              VERTEX_COLOR *c = (VERTEX_COLOR *)&v[3];
+              c->blue  = col[0][2];
+              c->green = col[0][1];
+              c->red   = col[0][0];
+              c->alpha = col[0][3];
+           }
+           STRIDE_4UB( col, col_stride );
+        }
+/*      fprintf(stderr, "vert %d: %.2f %.2f %.2f %x\n",  */
+/*              i, v[0], v[1], v[2], *(int *)&v[3]); */
+      }
+   }
+   else {
+      for (i=start; i < end; i++, v+=4) {
+        if (HAVE_HW_VIEWPORT || mask[i] == 0) {
+           VIEWPORT_X(v[0], coord[i][0]);
+           VIEWPORT_Y(v[1], coord[i][1]);
+           VIEWPORT_Z(v[2], coord[i][2]);
+        }
+        if (DO_RGBA) {
+           if (HAVE_RGBA_COLOR) {
+              *(GLuint *)&v[3] = LE32_TO_CPU(*(GLuint *)&col[i]);
+           }
+           else {
+              VERTEX_COLOR *c = (VERTEX_COLOR *)&v[3];
+              c->blue  = col[i][2];
+              c->green = col[i][1];
+              c->red   = col[i][0];
+              c->alpha = col[i][3];
+           }
+        }
+/*      fprintf(stderr, "vert %d: %.2f %.2f %.2f %x\n",  */
+/*              i, v[0], v[1], v[2], *(int *)&v[3]); */
+
+      }
+   }
+}
+#else
+static void TAG(emit)( GLcontext *ctx, GLuint start, GLuint end,
+                      void *dest, GLuint stride )
+{
+   LOCALVARS
+   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+   GLubyte (*col)[4];
+   GLuint col_stride;
+   GLfloat *v = (GLfloat *)dest;
+   int i;
+
+   if (VB->ColorPtr[0]->Type != GL_UNSIGNED_BYTE)
+      IMPORT_FLOAT_COLORS( ctx );
+
+   col = VB->ColorPtr[0]->Ptr;
+   col_stride = VB->ColorPtr[0]->StrideB;
+
+   if (start)
+      STRIDE_4UB(col, col_stride * start);
+
+   /* Need to figure out where color is:
+    */
+   if (GET_VERTEX_FORMAT() == TINY_VERTEX_FORMAT)
+      v += 3;
+   else
+      v += 4;
+
+   for (i=start; i < end; i++, STRIDE_F(v, stride)) {
+      if (HAVE_RGBA_COLOR) {
+        *(GLuint *)v = LE32_TO_CPU(*(GLuint *)col[0]);
+      }
+      else {
+        VERTEX_COLOR *c = (VERTEX_COLOR *)v;
+        c->blue  = col[0][2];
+        c->green = col[0][1];
+        c->red   = col[0][0];
+        c->alpha = col[0][3];
+      }
+      STRIDE_4UB( col, col_stride );
+   }
+}
+#endif /* emit */
+#endif /* emit */
+
+#if (DO_XYZW) && (DO_RGBA)
+
+
+#if (HAVE_PTEX_VERTICES)
+static GLboolean TAG(check_tex_sizes)( GLcontext *ctx )
+{
+   LOCALVARS
+   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+   /* Force 'missing' texcoords to something valid.
+    */
+   if (DO_TEX3 && VB->TexCoordPtr[2] == 0)
+      VB->TexCoordPtr[2] = VB->TexCoordPtr[3];
+
+   if (DO_TEX2 && VB->TexCoordPtr[1] == 0)
+      VB->TexCoordPtr[1] = VB->TexCoordPtr[2];
+
+   if (DO_TEX1 && VB->TexCoordPtr[0] == 0)
+      VB->TexCoordPtr[0] = VB->TexCoordPtr[1];
+
+   if (DO_PTEX)
+      return GL_TRUE;
+   
+   if ((DO_TEX3 && VB->TexCoordPtr[GET_TEXSOURCE(3)]->size == 4) ||
+       (DO_TEX2 && VB->TexCoordPtr[GET_TEXSOURCE(2)]->size == 4) ||
+       (DO_TEX1 && VB->TexCoordPtr[GET_TEXSOURCE(1)]->size == 4) ||
+       (DO_TEX0 && VB->TexCoordPtr[GET_TEXSOURCE(0)]->size == 4))
+      return GL_FALSE;
+
+   return GL_TRUE;
+}
+#else
+static GLboolean TAG(check_tex_sizes)( GLcontext *ctx )
+{
+   LOCALVARS
+   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+   /* Force 'missing' texcoords to something valid.
+    */
+   if (DO_TEX3 && VB->TexCoordPtr[2] == 0)
+      VB->TexCoordPtr[2] = VB->TexCoordPtr[3];
+
+   if (DO_TEX2 && VB->TexCoordPtr[1] == 0)
+      VB->TexCoordPtr[1] = VB->TexCoordPtr[2];
+
+   if (DO_TEX1 && VB->TexCoordPtr[0] == 0)
+      VB->TexCoordPtr[0] = VB->TexCoordPtr[1];
+
+   if (DO_PTEX)
+      return GL_TRUE;
+
+   /* No hardware support for projective texture.  Can fake it for
+    * TEX0 only.
+    */
+   if ((DO_TEX3 && VB->TexCoordPtr[GET_TEXSOURCE(3)]->size == 4) ||
+       (DO_TEX2 && VB->TexCoordPtr[GET_TEXSOURCE(2)]->size == 4) ||
+       (DO_TEX1 && VB->TexCoordPtr[GET_TEXSOURCE(1)]->size == 4)) {
+      PTEX_FALLBACK();
+      return GL_FALSE;
+   }
+
+   if (DO_TEX0 && VB->TexCoordPtr[GET_TEXSOURCE(0)]->size == 4) {
+      if (DO_TEX1 || DO_TEX2 || DO_TEX3) {
+        PTEX_FALLBACK();
+      }
+      return GL_FALSE;
+   }
+
+   return GL_TRUE;
+}
+#endif /* ptex */
+
+
+static void TAG(interp)( GLcontext *ctx,
+                        GLfloat t,
+                        GLuint edst, GLuint eout, GLuint ein,
+                        GLboolean force_boundary )
+{
+   LOCALVARS
+   struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+   GLubyte *ddverts = GET_VERTEX_STORE();
+   GLuint shift = GET_VERTEX_STRIDE_SHIFT();
+   const GLfloat *dstclip = VB->ClipPtr->data[edst];
+   GLfloat w;
+   const GLfloat *s = GET_VIEWPORT_MAT();
+
+   VERTEX *dst = (VERTEX *)(ddverts + (edst << shift));
+   VERTEX *in  = (VERTEX *)(ddverts + (ein << shift));
+   VERTEX *out = (VERTEX *)(ddverts + (eout << shift));
+
+   (void)s;
+
+   if (HAVE_HW_DIVIDE && CHECK_HW_DIVIDE) {
+      VIEWPORT_X( dst->v.x, dstclip[0] );
+      VIEWPORT_Y( dst->v.y, dstclip[1] );
+      VIEWPORT_Z( dst->v.z, dstclip[2] );
+      w = dstclip[3];
+   }
+   else {
+      w = 1.0 / dstclip[3];
+      VIEWPORT_X( dst->v.x, dstclip[0] * w );
+      VIEWPORT_Y( dst->v.y, dstclip[1] * w );
+      VIEWPORT_Z( dst->v.z, dstclip[2] * w );
+   }
+
+   if ((HAVE_HW_DIVIDE && CHECK_HW_DIVIDE) || 
+       DO_FOG || DO_SPEC || DO_TEX0 || DO_TEX1 ||
+       DO_TEX2 || DO_TEX3 || !HAVE_TINY_VERTICES) {
+
+      dst->v.w = w;
+
+      INTERP_UB( t, dst->ub4[4][0], out->ub4[4][0], in->ub4[4][0] );
+      INTERP_UB( t, dst->ub4[4][1], out->ub4[4][1], in->ub4[4][1] );
+      INTERP_UB( t, dst->ub4[4][2], out->ub4[4][2], in->ub4[4][2] );
+      INTERP_UB( t, dst->ub4[4][3], out->ub4[4][3], in->ub4[4][3] );
+
+      if (DO_SPEC) {
+        INTERP_UB( t, dst->v.specular.red,   out->v.specular.red,   in->v.specular.red );
+        INTERP_UB( t, dst->v.specular.green, out->v.specular.green, in->v.specular.green );
+        INTERP_UB( t, dst->v.specular.blue,  out->v.specular.blue,  in->v.specular.blue );
+      }
+      if (DO_FOG) {
+        INTERP_UB( t, dst->v.specular.alpha, out->v.specular.alpha, in->v.specular.alpha );
+      }
+      if (DO_TEX0) {
+        if (DO_PTEX) {
+           if (HAVE_PTEX_VERTICES) {
+              INTERP_F( t, dst->pv.u0, out->pv.u0, in->pv.u0 );
+              INTERP_F( t, dst->pv.v0, out->pv.v0, in->pv.v0 );
+              INTERP_F( t, dst->pv.q0, out->pv.q0, in->pv.q0 );
+           } else {
+              GLfloat wout = VB->NdcPtr->data[eout][3];
+              GLfloat win = VB->NdcPtr->data[ein][3];
+              GLfloat qout = out->pv.w / wout;
+              GLfloat qin = in->pv.w / win;
+              GLfloat qdst, rqdst;
+
+              ASSERT( !HAVE_HW_DIVIDE );
+
+              INTERP_F( t, dst->v.u0, out->v.u0 * qout, in->v.u0 * qin );
+              INTERP_F( t, dst->v.v0, out->v.v0 * qout, in->v.v0 * qin );
+              INTERP_F( t, qdst, qout, qin );
+
+              rqdst = 1.0 / qdst;
+              dst->v.u0 *= rqdst;
+              dst->v.v0 *= rqdst;
+              dst->v.w *= rqdst;
+           }
+        }
+        else {
+           INTERP_F( t, dst->v.u0, out->v.u0, in->v.u0 );
+           INTERP_F( t, dst->v.v0, out->v.v0, in->v.v0 );
+        }
+      }
+      if (DO_TEX1) {
+        if (DO_PTEX) {
+           INTERP_F( t, dst->pv.u1, out->pv.u1, in->pv.u1 );
+           INTERP_F( t, dst->pv.v1, out->pv.v1, in->pv.v1 );
+           INTERP_F( t, dst->pv.q1, out->pv.q1, in->pv.q1 );
+        } else {
+           INTERP_F( t, dst->v.u1, out->v.u1, in->v.u1 );
+           INTERP_F( t, dst->v.v1, out->v.v1, in->v.v1 );
+        }
+      }
+      else if (DO_PTEX) {
+        dst->pv.q1 = 0.0;      /* must be a valid float on radeon */
+      }
+      if (DO_TEX2) {
+        if (DO_PTEX) {
+           INTERP_F( t, dst->pv.u2, out->pv.u2, in->pv.u2 );
+           INTERP_F( t, dst->pv.v2, out->pv.v2, in->pv.v2 );
+           INTERP_F( t, dst->pv.q2, out->pv.q2, in->pv.q2 );
+        } else {
+           INTERP_F( t, dst->v.u2, out->v.u2, in->v.u2 );
+           INTERP_F( t, dst->v.v2, out->v.v2, in->v.v2 );
+        }
+      }
+      if (DO_TEX3) {
+        if (DO_PTEX) {
+           INTERP_F( t, dst->pv.u3, out->pv.u3, in->pv.u3 );
+           INTERP_F( t, dst->pv.v3, out->pv.v3, in->pv.v3 );
+           INTERP_F( t, dst->pv.q3, out->pv.q3, in->pv.q3 );
+        } else {
+           INTERP_F( t, dst->v.u3, out->v.u3, in->v.u3 );
+           INTERP_F( t, dst->v.v3, out->v.v3, in->v.v3 );
+        }
+      }
+   } else {
+      /* 4-dword vertex.  Color is in v[3] and there is no oow coordinate.
+       */
+      INTERP_UB( t, dst->ub4[3][0], out->ub4[3][0], in->ub4[3][0] );
+      INTERP_UB( t, dst->ub4[3][1], out->ub4[3][1], in->ub4[3][1] );
+      INTERP_UB( t, dst->ub4[3][2], out->ub4[3][2], in->ub4[3][2] );
+      INTERP_UB( t, dst->ub4[3][3], out->ub4[3][3], in->ub4[3][3] );
+   }
+}
+
+#endif /* rgba && xyzw */
+
+
+static void TAG(init)( void )
+{
+   setup_tab[IND].emit = TAG(emit);
+
+#if (DO_XYZW && DO_RGBA)
+   setup_tab[IND].check_tex_sizes = TAG(check_tex_sizes);
+   setup_tab[IND].interp = TAG(interp);
+#endif
+
+   if (DO_SPEC)
+      setup_tab[IND].copy_pv = copy_pv_rgba4_spec5;
+   else if (HAVE_HW_DIVIDE || DO_SPEC || DO_FOG || DO_TEX0 || DO_TEX1 ||
+           DO_TEX2 || DO_TEX3 || !HAVE_TINY_VERTICES)
+      setup_tab[IND].copy_pv = copy_pv_rgba4;
+   else
+      setup_tab[IND].copy_pv = copy_pv_rgba3;
+
+   if (DO_TEX3) {
+      if (DO_PTEX) {
+        ASSERT(HAVE_PTEX_VERTICES);
+        setup_tab[IND].vertex_format = PROJ_TEX3_VERTEX_FORMAT;
+        setup_tab[IND].vertex_size = 18;
+        setup_tab[IND].vertex_stride_shift = 7;
+      }
+      else {
+        setup_tab[IND].vertex_format = TEX3_VERTEX_FORMAT;
+        setup_tab[IND].vertex_size = 14;
+        setup_tab[IND].vertex_stride_shift = 6;
+      }
+   }
+   else if (DO_TEX2) {
+      if (DO_PTEX) {
+        ASSERT(HAVE_PTEX_VERTICES);
+        setup_tab[IND].vertex_format = PROJ_TEX3_VERTEX_FORMAT;
+        setup_tab[IND].vertex_size = 18;
+        setup_tab[IND].vertex_stride_shift = 7;
+      }
+      else {
+        setup_tab[IND].vertex_format = TEX2_VERTEX_FORMAT;
+        setup_tab[IND].vertex_size = 12;
+        setup_tab[IND].vertex_stride_shift = 6;
+      }
+   }
+   else if (DO_TEX1) {
+      if (DO_PTEX) {
+        ASSERT(HAVE_PTEX_VERTICES);
+        setup_tab[IND].vertex_format = PROJ_TEX1_VERTEX_FORMAT;
+        setup_tab[IND].vertex_size = 12;
+        setup_tab[IND].vertex_stride_shift = 6;
+      }
+      else {
+        setup_tab[IND].vertex_format = TEX1_VERTEX_FORMAT;
+        setup_tab[IND].vertex_size = 10;
+        setup_tab[IND].vertex_stride_shift = 6;
+      }
+   }
+   else if (DO_TEX0) {
+      if (DO_PTEX && HAVE_PTEX_VERTICES) {
+        setup_tab[IND].vertex_format = PROJ_TEX1_VERTEX_FORMAT;
+        setup_tab[IND].vertex_size = 12;
+        setup_tab[IND].vertex_stride_shift = 6;
+      } else {
+        setup_tab[IND].vertex_format = TEX0_VERTEX_FORMAT;
+        setup_tab[IND].vertex_size = 8;
+        setup_tab[IND].vertex_stride_shift = 5;
+      }
+   }
+   else if (!HAVE_HW_DIVIDE && !DO_SPEC && !DO_FOG && HAVE_TINY_VERTICES) {
+      setup_tab[IND].vertex_format = TINY_VERTEX_FORMAT;
+      setup_tab[IND].vertex_size = 4;
+      setup_tab[IND].vertex_stride_shift = 4;
+   } else if (HAVE_NOTEX_VERTICES) {
+      setup_tab[IND].vertex_format = NOTEX_VERTEX_FORMAT;
+      setup_tab[IND].vertex_size = 6;
+      setup_tab[IND].vertex_stride_shift = 5;
+   } else {
+      setup_tab[IND].vertex_format = TEX0_VERTEX_FORMAT;
+      setup_tab[IND].vertex_size = 8;
+      setup_tab[IND].vertex_stride_shift = 5;
+   }
+
+   assert(setup_tab[IND].vertex_size * 4 <=
+          1 << setup_tab[IND].vertex_stride_shift);
+}
+
+
+#undef IND
+#undef TAG
diff --git a/src/mesa/tnl_dd/t_dd_vertex.h b/src/mesa/tnl_dd/t_dd_vertex.h
new file mode 100644 (file)
index 0000000..d45dd09
--- /dev/null
@@ -0,0 +1,78 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version:  4.0.3
+ *
+ * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+typedef struct {
+   GLfloat x, y, z, w;
+} TAG(_coord_t);
+
+#ifdef COLOR_IS_RGBA
+typedef struct {
+#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
+   GLubyte alpha, blue, green, red;
+#else
+   GLubyte red, green, blue, alpha;
+#endif
+} TAG(_color_t);
+#else
+typedef struct {
+#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
+   GLubyte alpha, red, green, blue;
+#else
+   GLubyte blue, green, red, alpha;
+#endif
+} TAG(_color_t);
+#endif
+
+typedef union {
+   struct {
+      GLfloat x, y, z, w;
+      TAG(_color_t) color;
+      TAG(_color_t) specular;
+      GLfloat u0, v0;
+      GLfloat u1, v1;
+      GLfloat u2, v2;
+      GLfloat u3, v3;
+   } v;
+   struct {
+      GLfloat x, y, z, w;
+      TAG(_color_t) color;
+      TAG(_color_t) specular;
+      GLfloat u0, v0, q0;
+      GLfloat u1, v1, q1;
+      GLfloat u2, v2, q2;
+      GLfloat u3, v3, q3;
+   } pv;
+   struct {
+      GLfloat x, y, z;
+      TAG(_color_t) color;
+   } tv;
+   GLfloat f[24];
+   GLuint  ui[24];
+   GLubyte ub4[24][4];
+} TAG(Vertex), *TAG(VertexPtr);
+