summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjtg <jtg>1999-08-19 00:55:39 +0000
committerjtg <jtg>1999-08-19 00:55:39 +0000
commitafb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1c (patch)
tree59d65b4da12fb5379224cf5f6b808fde91523c7f /src
parentf2544d4920ce168bec9cd94d774b7ea5103a3d74 (diff)
Initial revision
Diffstat (limited to 'src')
-rw-r--r--src/glu/mesa/Makefile.BeOS73
-rw-r--r--src/glu/mesa/Makefile.BeOS-R485
-rw-r--r--src/glu/mesa/Makefile.X1157
-rw-r--r--src/glu/mesa/MesaGLU.def54
-rw-r--r--src/glu/mesa/README1195
-rw-r--r--src/glu/mesa/README243
-rw-r--r--src/glu/mesa/all.h69
-rw-r--r--src/glu/mesa/descrip.mms62
-rw-r--r--src/glu/mesa/glu.c335
-rw-r--r--src/glu/mesa/gluP.h83
-rw-r--r--src/glu/mesa/mipmap.c790
-rw-r--r--src/glu/mesa/mms_depend13
-rw-r--r--src/glu/mesa/nurbs.c715
-rw-r--r--src/glu/mesa/nurbs.h252
-rw-r--r--src/glu/mesa/nurbscrv.c500
-rw-r--r--src/glu/mesa/nurbssrf.c1422
-rw-r--r--src/glu/mesa/nurbsutl.c1403
-rw-r--r--src/glu/mesa/polytest.c1049
-rw-r--r--src/glu/mesa/project.c318
-rw-r--r--src/glu/mesa/quadric.c858
-rw-r--r--src/glu/mesa/tess.c369
-rw-r--r--src/glu/mesa/tess.h121
-rw-r--r--src/glu/mesa/tesselat.c456
-rw-r--r--src/glw/GLwDrawA.c686
-rw-r--r--src/glw/GLwDrawA.h195
-rw-r--r--src/glw/GLwDrawAP.h130
-rw-r--r--src/glw/GLwMDrawA.c41
-rw-r--r--src/glw/GLwMDrawA.h41
-rw-r--r--src/glw/GLwMDrawAP.h41
-rw-r--r--src/glw/Makefile59
-rw-r--r--src/glw/README56
-rw-r--r--src/glw/boilerplate.c451
-rw-r--r--src/glw/depend6
-rw-r--r--src/mesa/Makefile.X11243
-rw-r--r--src/mesa/drivers/allegro/amesa.c395
-rw-r--r--src/mesa/drivers/allegro/direct.h189
-rw-r--r--src/mesa/drivers/allegro/generic.h233
-rw-r--r--src/mesa/drivers/beos/GLView.cpp1233
-rw-r--r--src/mesa/drivers/d3d/D3DCAPS.CPP251
-rw-r--r--src/mesa/drivers/d3d/D3DHAL.H69
-rw-r--r--src/mesa/drivers/d3d/D3DInit.cpp891
-rw-r--r--src/mesa/drivers/d3d/D3DMESA.H85
-rw-r--r--src/mesa/drivers/d3d/D3DRaster.cpp214
-rw-r--r--src/mesa/drivers/d3d/D3DShared.h154
-rw-r--r--src/mesa/drivers/d3d/D3DTEXT.CPP577
-rw-r--r--src/mesa/drivers/d3d/D3DTextureMgr.cpp948
-rw-r--r--src/mesa/drivers/d3d/D3DTextureMgr.h63
-rw-r--r--src/mesa/drivers/d3d/D3DUTILS.CPP639
-rw-r--r--src/mesa/drivers/d3d/D3Dvbrender.c2150
-rw-r--r--src/mesa/drivers/d3d/DDrawPROCS.c400
-rw-r--r--src/mesa/drivers/d3d/DEBUG.C144
-rw-r--r--src/mesa/drivers/d3d/DEBUG.H91
-rw-r--r--src/mesa/drivers/d3d/DbgEnv.bat25
-rw-r--r--src/mesa/drivers/d3d/MAKEFILE102
-rw-r--r--src/mesa/drivers/d3d/NULLProcs.h49
-rw-r--r--src/mesa/drivers/d3d/NullProcs.c130
-rw-r--r--src/mesa/drivers/d3d/OPENGL32.DEF443
-rw-r--r--src/mesa/drivers/d3d/WGL.C1262
-rw-r--r--src/mesa/drivers/d3d/d3dText.h53
-rw-r--r--src/mesa/drivers/dos/DEPEND.DOS119
-rw-r--r--src/mesa/drivers/dos/dosmesa.c1513
-rw-r--r--src/mesa/drivers/ggi/ggimesa.conf.in13
-rw-r--r--src/mesa/drivers/glide/fxapi.c1411
-rw-r--r--src/mesa/drivers/glide/fxdd.c632
-rw-r--r--src/mesa/drivers/glide/fxddspan.c817
-rw-r--r--src/mesa/drivers/glide/fxddtex.c1299
-rw-r--r--src/mesa/drivers/glide/fxdrv.h576
-rw-r--r--src/mesa/drivers/glide/fxglidew.c247
-rw-r--r--src/mesa/drivers/glide/fxglidew.h358
-rw-r--r--src/mesa/drivers/glide/fxopengl.def467
-rw-r--r--src/mesa/drivers/glide/fxsetup.c1552
-rw-r--r--src/mesa/drivers/glide/fxtexman.c579
-rw-r--r--src/mesa/drivers/glide/fxwgl.c806
-rw-r--r--src/mesa/drivers/osmesa/osmesa.c1594
-rw-r--r--src/mesa/drivers/svga/svgamesa.c540
-rw-r--r--src/mesa/drivers/windows/colors.h499
-rw-r--r--src/mesa/drivers/windows/mesa_extend.c211
-rw-r--r--src/mesa/drivers/windows/mesa_extend.h43
-rw-r--r--src/mesa/drivers/windows/stereo.h47
-rw-r--r--src/mesa/drivers/windows/wgl.c518
-rw-r--r--src/mesa/drivers/windows/wing32.def12
-rw-r--r--src/mesa/drivers/windows/wmesa.c3021
-rw-r--r--src/mesa/drivers/windows/wmesaBackup.c2879
-rw-r--r--src/mesa/drivers/windows/wmesaOld.c2737
-rw-r--r--src/mesa/drivers/windows/wmesa_stereo.c1872
-rw-r--r--src/mesa/drivers/windows/wmesadef.h154
-rw-r--r--src/mesa/drivers/x11/fakeglx.c1516
-rw-r--r--src/mesa/drivers/x11/glxapi.c405
-rw-r--r--src/mesa/drivers/x11/realglx.c239
-rw-r--r--src/mesa/drivers/x11/realglx.h111
-rw-r--r--src/mesa/drivers/x11/xfonts.c398
-rw-r--r--src/mesa/drivers/x11/xmesaP.h499
-rw-r--r--src/mesa/main/Imakefile127
-rw-r--r--src/mesa/main/KNOWN_BUGS20
-rw-r--r--src/mesa/main/Makefile.DJ95
-rw-r--r--src/mesa/main/Makefile.X11243
-rw-r--r--src/mesa/main/accum.c495
-rw-r--r--src/mesa/main/accum.h51
-rw-r--r--src/mesa/main/attrib.c863
-rw-r--r--src/mesa/main/attrib.h47
-rw-r--r--src/mesa/main/blend.c812
-rw-r--r--src/mesa/main/blend.h68
-rw-r--r--src/mesa/main/clip.c460
-rw-r--r--src/mesa/main/clip.h105
-rw-r--r--src/mesa/main/colortab.c312
-rw-r--r--src/mesa/main/colortab.h55
-rw-r--r--src/mesa/main/config.h222
-rw-r--r--src/mesa/main/context.c2388
-rw-r--r--src/mesa/main/context.h167
-rw-r--r--src/mesa/main/dd.h635
-rw-r--r--src/mesa/main/depth.c879
-rw-r--r--src/mesa/main/depth.h98
-rw-r--r--src/mesa/main/descrip.mms156
-rw-r--r--src/mesa/main/dlist.c3501
-rw-r--r--src/mesa/main/dlist.h79
-rw-r--r--src/mesa/main/drawpix.c946
-rw-r--r--src/mesa/main/drawpix.h54
-rw-r--r--src/mesa/main/enable.c699
-rw-r--r--src/mesa/main/enable.h51
-rw-r--r--src/mesa/main/enums.c893
-rw-r--r--src/mesa/main/enums.h34
-rw-r--r--src/mesa/main/eval.c2725
-rw-r--r--src/mesa/main/eval.h95
-rw-r--r--src/mesa/main/extensions.c196
-rw-r--r--src/mesa/main/extensions.h56
-rw-r--r--src/mesa/main/feedback.c395
-rw-r--r--src/mesa/main/feedback.h74
-rw-r--r--src/mesa/main/fog.c327
-rw-r--r--src/mesa/main/fog.h51
-rw-r--r--src/mesa/main/get.c3692
-rw-r--r--src/mesa/main/get.h48
-rw-r--r--src/mesa/main/hash.c295
-rw-r--r--src/mesa/main/hash.h59
-rw-r--r--src/mesa/main/image.c2417
-rw-r--r--src/mesa/main/image.h109
-rw-r--r--src/mesa/main/light.c1183
-rw-r--r--src/mesa/main/light.h103
-rw-r--r--src/mesa/main/lines.c1146
-rw-r--r--src/mesa/main/lines.h45
-rw-r--r--src/mesa/main/macros.h546
-rw-r--r--src/mesa/main/matrix.c1438
-rw-r--r--src/mesa/main/matrix.h115
-rw-r--r--src/mesa/main/mesa.conf74
-rw-r--r--src/mesa/main/pixel.c774
-rw-r--r--src/mesa/main/pixel.h111
-rw-r--r--src/mesa/main/points.c1344
-rw-r--r--src/mesa/main/points.h45
-rw-r--r--src/mesa/main/polygon.c177
-rw-r--r--src/mesa/main/polygon.h53
-rw-r--r--src/mesa/main/rastpos.c227
-rw-r--r--src/mesa/main/rastpos.h48
-rw-r--r--src/mesa/main/simple_list.h99
-rw-r--r--src/mesa/main/stencil.c1107
-rw-r--r--src/mesa/main/stencil.h88
-rw-r--r--src/mesa/main/teximage.c2344
-rw-r--r--src/mesa/main/teximage.h186
-rw-r--r--src/mesa/main/texobj.c571
-rw-r--r--src/mesa/main/texobj.h85
-rw-r--r--src/mesa/main/texstate.c1146
-rw-r--r--src/mesa/main/texstate.h112
-rw-r--r--src/mesa/main/varray.c1259
-rw-r--r--src/mesa/main/varray.h113
-rw-r--r--src/mesa/x86/3dnow.c168
-rw-r--r--src/mesa/x86/3dnow.h95
-rw-r--r--src/mesa/x86/assyntax.h1629
-rw-r--r--src/mesa/x86/common_x86.c77
-rw-r--r--src/mesa/x86/mmx.h77
-rw-r--r--src/mesa/x86/mmx_blend.S363
-rw-r--r--src/mesa/x86/x86.c107
-rw-r--r--src/mesa/x86/x86.h37
170 files changed, 91931 insertions, 0 deletions
diff --git a/src/glu/mesa/Makefile.BeOS b/src/glu/mesa/Makefile.BeOS
new file mode 100644
index 0000000000..d1e489c199
--- /dev/null
+++ b/src/glu/mesa/Makefile.BeOS
@@ -0,0 +1,73 @@
+# Makefile for GLU for BeOS contributed by
+# Tinic Uro <5uro@informatik.uni-hamburg.de>
+
+# Mesa 3-D graphics library
+# Version: 2.6
+# Copyright (C) 1995-1997 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.
+
+
+
+##### MACROS #####
+
+VPATH = RCS
+
+INCDIR = ../include
+LIBDIR = ../lib
+
+SOURCES = glu.c mipmap.c nurbs.c nurbscrv.c nurbssrf.c nurbsutl.c \
+ project.c quadric.c tess.c tesselat.c polytest.c
+
+OBJECTS = $(SOURCES:.c=.o)
+
+
+
+##### RULES #####
+
+.c.o:
+ $(CC) -c -i . -i- -i $(INCDIR) $(CFLAGS) $<
+
+
+
+##### TARGETS #####
+
+default:
+ @echo "Specify a target configuration"
+
+clean:
+ -rm *.o *~
+
+targets: $(LIBDIR)/$(GLU_LIB)
+
+# Make the library:
+$(LIBDIR)/$(GLU_LIB): $(OBJECTS)
+ $(MAKELIB) $(GLU_LIB) 2 6 $(OBJECTS)
+# $(RANLIB) $(GLU_LIB)
+ mv $(GLU_LIB)* $(LIBDIR)
+
+include ../Make-config
+
+include depend
+
+
+
+#
+# Run 'make depend' to update the dependencies if you change what's included
+# by any source file.
+#
+depend: $(SOURCES)
+ makedepend -fdepend -Y -I../include $(SOURCES)
+
diff --git a/src/glu/mesa/Makefile.BeOS-R4 b/src/glu/mesa/Makefile.BeOS-R4
new file mode 100644
index 0000000000..d664534491
--- /dev/null
+++ b/src/glu/mesa/Makefile.BeOS-R4
@@ -0,0 +1,85 @@
+# Makefile for GLU for BeOS R4
+
+# Mesa 3-D graphics library
+# Version: 3.1
+# Copyright (C) 1995-1999 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.
+
+
+# $Id: Makefile.BeOS-R4,v 1.1 1999/08/19 00:55:42 jtg Exp $
+
+# $Log: Makefile.BeOS-R4,v $
+# Revision 1.1 1999/08/19 00:55:42 jtg
+# Initial revision
+#
+# Revision 1.2 1999/02/02 04:44:40 brianp
+# fixed some problems
+#
+# Revision 1.1 1999/01/19 04:10:02 brianp
+# Initial revision
+#
+
+
+
+##### MACROS #####
+
+VPATH = RCS
+
+INCDIR = ../include
+LIBDIR = ../lib
+
+SOURCES = glu.c mipmap.c nurbs.c nurbscrv.c nurbssrf.c nurbsutl.c \
+ project.c quadric.c tess.c tesselat.c polytest.c
+
+OBJECTS = $(SOURCES:.c=.o)
+
+
+
+##### TARGETS #####
+
+default:
+ @echo "Specify a target configuration"
+
+clean:
+ -rm *.o *~
+
+targets: $(LIBDIR)/$(GLU_LIB)
+
+# Make the library:
+$(LIBDIR)/$(GLU_LIB): $(OBJECTS)
+ $(MAKELIB) $(GLU_LIB) $(MAJOR) $(MINOR) -L$(LIBDIR) -lMesaGL $(OBJECTS)
+ mv $(GLU_LIB)* $(LIBDIR)
+
+include ../Make-config
+
+include depend
+
+
+
+##### RULES #####
+
+.c.o:
+ $(CC) -c -I. -I../ -I$(INCDIR) $(CFLAGS) $<
+
+
+
+#
+# Run 'make depend' to update the dependencies if you change what's included
+# by any source file.
+#
+depend: $(SOURCES)
+ makedepend -fdepend -Y -I../include $(SOURCES)
+
diff --git a/src/glu/mesa/Makefile.X11 b/src/glu/mesa/Makefile.X11
new file mode 100644
index 0000000000..c155aea9a5
--- /dev/null
+++ b/src/glu/mesa/Makefile.X11
@@ -0,0 +1,57 @@
+# $Id: Makefile.X11,v 1.1 1999/08/19 00:55:42 jtg Exp $
+
+# Mesa 3-D graphics library
+# Version: 3.1
+# Copyright (C) 1995-1999 Brian Paul
+
+# Makefile for GLU library
+
+
+##### MACROS #####
+
+VPATH = RCS
+
+INCDIR = ../include
+LIBDIR = ../lib
+
+SOURCES = glu.c mipmap.c nurbs.c nurbscrv.c nurbssrf.c nurbsutl.c \
+ project.c quadric.c tess.c tesselat.c polytest.c
+
+OBJECTS = $(SOURCES:.c=.o)
+
+
+
+##### RULES #####
+
+.c.o:
+ $(CC) -c -I$(INCDIR) $(CFLAGS) $<
+
+
+
+##### TARGETS #####
+
+default:
+ @echo "Specify a target configuration"
+
+clean:
+ -rm *.o *~
+
+targets: $(LIBDIR)/$(GLU_LIB)
+
+# Make the library:
+$(LIBDIR)/$(GLU_LIB): $(OBJECTS)
+ $(MAKELIB) $(GLU_LIB) $(MAJOR) $(MINOR) $(OBJECTS)
+ mv $(GLU_LIB)* $(LIBDIR)
+
+include ../Make-config
+
+include depend
+
+
+
+#
+# Run 'make depend' to update the dependencies if you change what's included
+# by any source file.
+#
+dep: $(SOURCES)
+ makedepend -fdepend -Y -I../include $(SOURCES)
diff --git a/src/glu/mesa/MesaGLU.def b/src/glu/mesa/MesaGLU.def
new file mode 100644
index 0000000000..8b1c4449ff
--- /dev/null
+++ b/src/glu/mesa/MesaGLU.def
@@ -0,0 +1,54 @@
+LIBRARY MESAGLU
+DESCRIPTION 'GLU for Windows Mesa'
+EXETYPE WINDOWS
+CODE MOVEABLE DISCARDABLE
+DATA MOVEABLE SINGLE
+HEAPSIZE 256000
+
+STACKSIZE 4096
+
+EXPORTS
+ gluLookAt
+ gluOrtho2D
+ gluPerspective
+ gluPickMatrix
+ gluProject
+ gluUnProject
+ gluErrorString
+ gluScaleImage
+ gluBuild1DMipmaps
+ gluBuild2DMipmaps
+ gluNewQuadric
+ gluDeleteQuadric
+ gluQuadricDrawStyle
+ gluQuadricOrientation
+ gluQuadricNormals
+ gluQuadricTexture
+ gluQuadricCallback
+ gluCylinder
+ gluSphere
+ gluDisk
+ gluPartialDisk
+ gluNewNurbsRenderer
+ gluDeleteNurbsRenderer
+ gluLoadSamplingMatrices
+ gluNurbsProperty
+ gluGetNurbsProperty
+ gluBeginCurve
+ gluEndCurve
+ gluNurbsCurve
+ gluBeginSurface
+ gluEndSurface
+ gluNurbsSurface
+ gluBeginTrim
+ gluEndTrim
+ gluPwlCurve
+ gluNurbsCallback
+ gluNewTess
+ gluTessCallback
+ gluDeleteTess
+ gluBeginPolygon
+ gluEndPolygon
+ gluNextContour
+ gluTessVertex
+ gluGetString
diff --git a/src/glu/mesa/README1 b/src/glu/mesa/README1
new file mode 100644
index 0000000000..75968572ff
--- /dev/null
+++ b/src/glu/mesa/README1
@@ -0,0 +1,195 @@
+
+Notes on the GLU polygon tesselation facility implemented by Bogdan Sikorski...
+
+
+
+The tesselation module is provided under the same terms as the Mesa
+package.
+
+This is the first release of polygon tesselation code for Mesa.
+It was written during my very little free time, so lets name it:
+"its not perfect". If someone hates pointers, don't look at the code.
+I preffer dynamic allocation versus static. But _all_ ideas, suggestions,
+bug reports and fixes are welcome (if You want, also flames). I am aware
+that many things could have been written using better techniques, but time
+that I could devote to this library was very limited. It is not well commented,
+excuse me. Also I am thinking of continuing working on this code to improve,
+fix and polish it. And make it as compliant as possible to the OpenGL, so
+software ports from OpenGL to Mesa will work correctly. If You know of any
+differences in behaviour, expected input/output between Mesa tesselation library
+and OpenGL, please send me a note. I explain later on why I am not
+confident with this code.
+
+I tried to be fully compliant with the OpenGL routines. By "tried" I mean that
+up to my knowledge it behaves as OpenGL tesselation routines. Just recently
+I began to experiment with OpenGL (actually only Mesa), and also have
+no access to any machine providing official implementation of OpenGL,
+nor access to books (particulary Addison-Wesley publications). Thus my
+knowledge on how the original tesselation code works, what kind of data
+it expects etc. is based _only_ on the publicly available documentation
+provided by SGI. Namely:
+
+* "The OpenGL Graphics System Utility Library" by K.P.Smith
+ (Silicon Graphics, 1992)
+* "The OpenGL Graphics Interface" by M.Segal and K.Akeley
+ (Silicon Graphics, 19??)
+* "OpenGL and X, Part 1: Introduction" by M.J.Kilgard
+ (Silicon Graphics, 1994)
+* "OpenGL and X, Part 2: Using OpenGL with Xlib" by M.J.Kilgard
+ (Silicon Graphics, 1994)
+* "OpenGL Graphics with the X Window System" by P.Karlton
+ (Silicon Graphics, 1993)
+* Online Docs - Appendix C of OpenGL Programming Guide, Polygon Tesselation
+ (partial text cut and sent by e-mail)
+
+
+The tesselation routines use slightly different prototypes than the ones
+specified in the mentioned above publications. The _only_ differences are
+the enumeration types which are not GLenum, but are GLUenum. So the
+implemented routines have following prototypes:
+
+GLUtringulatorObj *gluNewTess(void);
+
+void gluTessCallback(GLUtriangulatorObj *,GLUenum,void (*)());
+ ^^^^^^^
+void gluBeginPolygon(GLUtriangulatorObj *);
+
+void gluTessVertex(GLUtriangulatorObj *,GLdouble [3],void *);
+
+void gluNextContour(GLUtriangulatorObj *,GLUenum);
+ ^^^^^^^
+void gluEndPolygon(GLUtriangulatorObj *);
+
+const GLubyte *gluErrorString(GLUenum);
+ ^^^^^^^
+ prototypes for callback functions:
+
+void <begin>(GLUenum);
+ ^^^^^^^
+void <edgeFlag>(GLboolean);
+void <vertex>(void *);
+void <end>(void);
+void <error>(GLUenum);
+ ^^^^^^^
+
+The begin callback will be called only with GLU_TRIANGLES. No support
+for traingle fans or strips yet.
+
+In case of errors an internal error variable is set to the appropiate
+error enum values (GLU_TESS_ERROR?). Initially it is set to GLU_NO_ERROR.
+The OpenGL library provides 8 error conditions, the tesselation code
+of Mesa provides 9. They are:
+
+GLU_TESS_ERROR1: missing gluEndPolygon /* same as OpenGL */
+GLU_TESS_ERROR2: missing gluBeginPolygon /* same as OpenGL */
+GLU_TESS_ERROR3: misoriented contour /* not used in Mesa
+ in OpenGL is bad orientation or intersecting edges */
+GLU_TESS_ERROR4: vertex/edge intersection /* same as OpenGL */
+GLU_TESS_ERROR5: misoriented or self-intersecting loops /* same as OpenGL */
+GLU_TESS_ERROR6: coincident vertices /* same as OpenGL */
+GLU_TESS_ERROR7: colinear vertices /* OpenGL's illegal data */
+GLU_TESS_ERROR8: intersecting edges /* same as OpenGL */
+GLU_TESS_ERROR9: not coplanar contours /* new for Mesa */
+
+The Mesa tesselation code ignores all data and calls after detecting an error
+codition. This means that a _new_ tesselation object must be used for further
+triangulations. Maybe this is too restrictive, and will be lifted in
+future versions.
+
+The tesselation code completely ignores the type parameter passed in
+gluNextContour. It also doesn't check if the passed parameter is a legal
+enum value - ignores silently (maybe at least this should be checked).
+The reason I chose this behaviour is based on what I read in the
+beforementioned documents. I cite:
+
+"....
+void gluNextContour(GLUtriangulatorObj *tessobj, GLenum type);
+
+Marks the beginning of the next contour when multiple contours make up the
+boundary of the polygon to be tessellated. type can be GLU_EXTERIOR,
+GLU_INTERIOR, GLU_CCW, GLU_CW, or GLU_UNKNOWN. These serve only as
+to the tessellation. If you get them right, the tessellation might
+go faster. If you get them wrong, they're ignored, and the tesselation still
+works.
+....."
+
+I hope You agree with me that my decision was correct. Mesa tesselation
+_always_ checks by itself the interrelations between contours. Just as if
+all contours were specified with the type GLU_UNKNOWN.
+
+One of OpenGL's policy is not to check all error conditions - rely sometimes
+that the user "got things right". This is justified, since exhausting
+error checking is timeconsuming, and would significantly slow down
+a correct application. The Mesa tesselation code assumes only _one_ condition
+when triangulating - all vertices in a contour are planar. This is _not_
+checked for correctness. Trying to tesselate such objects will lead to
+unpredictable output.
+
+And now we arrive to the moment where I would like to list the required
+(but checked for) conditions for triangulation, as well as summarize the
+library:
+
+* all contours in a single tesselation cycle _must_ be coplanar - if not
+ an error is raised (and if provided a call to the error callback
+ is made)
+* the contours can be passed in _any_ order, exteriors and holes can be
+ intermixed within a tesselation cycle and the correct hierarchy
+ will be determined by the library; thus specifying first holes then
+ exteriors, then holes within holes form a valid input.
+* a hole within a hole is consider to be a yet another exterior contour
+* multiple exterior contours (polygons) can be tesselated in one cycle;
+ _but_ this significantly degrades performance since many tests will be
+ performed for every contour pair; if You want triangulation to be fast
+ tesselate a single polygon (with possible holes) one at a time.
+* orientation of exterior contours is arbitray, but if it has holes,
+ all interior holes of this particular exterior contour _must_ have an
+ opposite orientation.
+* the output triangles have the same orientation as the exterior contour
+ that forms them
+* each triangle is "enclosed" within the begin and end callbacks;
+ this is not efficent, but was made on purpose; so if triangulation
+ results in 2 triangles the following callbacks will be made in such
+ order:
+ <begin>(GLU_TRAINGLES)
+ <vertex>(...) /* 3 vertices of first triangle */
+ <vertex>(...)
+ <vertex>(...)
+ <end>()
+ <begin>(GLU_TRAINGLES)
+ <vertex>(...) /* 3 vertices of second triangle */
+ <vertex>(...)
+ <vertex>(...)
+ <end>()
+ Of course only when begin, vertex, and end callback were provided,
+ otherwise no output is done (actually tesselation does not take place).
+* You will notice that some output traingles are very "thin"; there
+ exist possible several ways to traingulate a polygon, but "smart" code
+ avoiding such cases would require time to write, and will impact on
+ execution speed.
+* like OpenGL, no new vertices are introduced during triangulation
+* if the edgeflag callback is provided it will be called whenever
+ the just-about-to be output vertex begins a different type of edge
+ than the previous vertices; always before the first output a call
+ is made with GL_TRUE, to allow synchronization.
+* all intermediate computations are done using GLdouble type, and comparisons
+ are biased with a precision value (EPSILON defined in tess.h)
+* the point_in_poly function is my adaptation of code from the
+ comp.graphics.alg newsgroup FAQ (originally written by Mr. Wm. Randolph
+ Franklin, modified by Scott Anguish).
+* the edge_edge_intersect test is also an adopted code from comp.graphics.alg
+ newsgroup FAQ
+* the general idea for traingulation used in this library is described in
+ the book "Computational Geometry in C" by Joseph O'Rourke.
+
+
+Excuse my English, its not my mother tongue. I should be available for some
+time uner the following e-mail address. But For how long I am not certain.
+Once I am settled in my new place, I'll post on the Mesa mailing list
+my new address.
+
+(PS: today is my last day of work here, I'm changing my job).
+
+Bogdan. ( bogdan@dia.unisa.it )
+
+Apr 28, 1995.
+
diff --git a/src/glu/mesa/README2 b/src/glu/mesa/README2
new file mode 100644
index 0000000000..3c9959179b
--- /dev/null
+++ b/src/glu/mesa/README2
@@ -0,0 +1,43 @@
+The current NURBS implementation has no trimming facilities yet.
+
+The code is not well commented.
+
+1) Normal calculus fails for special cases of NURBS (independent
+ of the NURBS modules)
+ Those cases arise when for u or v, some control points
+ for a fixed value of that parameter form the same point.
+ Imagine a Bezier patch degenerated into a "triangle".
+
+ v ^ 0,1,2 order=3
+ | *
+ |
+ | 3* 4* 5*
+ |
+ | 6* 7* 8*
+ |
+ |
+ +------------------------> u
+
+ The calculus of du derivative at triple point (0,1 and 2) will fail.
+ As a result, the normal vector will be 0.
+ The eval2.c code has to be changed to handle the above situation.
+
+2) Adjacent NURBS surfaces ("sharing" the same control points along
+ the "joining" edge) will be sampled with the same factor.
+ This prevents the formation of "cracks".
+ When the control polygon of the "shared" edge is not the same,
+ cracks might appear.
+
+The sampling tolerance is sometimes not respected!
+A NURBS object is broken into Bezier curves/surfaces. If one of such
+Bezier objects has a local high curvature with other portions of it
+relatively flat then the high curvature part will be sampled more dense that
+its flatter regions.
+The flat regions might be tesselated into quads having sides of length
+greater than the current sampling tolernace setting.
+I believe such behaviour is acceptable, though not along the concept of
+sampling tolerance.
+
+February 20, 1996.
+
+Bogdan.
diff --git a/src/glu/mesa/all.h b/src/glu/mesa/all.h
new file mode 100644
index 0000000000..3712ca884a
--- /dev/null
+++ b/src/glu/mesa/all.h
@@ -0,0 +1,69 @@
+/* $Id: all.h,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 2.3
+ * Copyright (C) 1995-1997 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.
+ */
+
+
+/*
+ * $Log: all.h,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 1.2 1997/11/20 00:28:20 brianp
+ * changed PCH to PC_HEADER
+ *
+ * Revision 1.1 1997/05/28 02:29:14 brianp
+ * Initial revision
+ *
+ */
+
+
+/*
+ * 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/mesa/descrip.mms b/src/glu/mesa/descrip.mms
new file mode 100644
index 0000000000..b660f6914d
--- /dev/null
+++ b/src/glu/mesa/descrip.mms
@@ -0,0 +1,62 @@
+# Makefile for GLU for VMS
+# contributed by Jouk Jansen joukj@crys.chem.uva.nl
+
+.first
+ define gl [-.include.gl]
+
+.include [-]mms-config.
+
+##### MACROS #####
+
+VPATH = RCS
+
+INCDIR = $disk2:[-.include]
+LIBDIR = [-.lib]
+CFLAGS = /include=$(INCDIR)/define=(FBIND=1)
+
+SOURCES = glu.c mipmap.c nurbs.c nurbscrv.c nurbssrf.c nurbsutl.c \
+ project.c quadric.c tess.c tesselat.c polytest.c
+
+OBJECTS =glu.obj,mipmap.obj,nurbs.obj,nurbscrv.obj,nurbssrf.obj,nurbsutl.obj,\
+ project.obj,quadric.obj,tess.obj,tesselat.obj,polytest.obj
+
+
+
+##### RULES #####
+
+VERSION=MesaGlu V3.1
+
+##### TARGETS #####
+
+# Make the library:
+$(LIBDIR)$(GLU_LIB) : $(OBJECTS)
+.ifdef SHARE
+ @ WRITE_ SYS$OUTPUT " generating mesagl1.opt"
+ @ OPEN_/WRITE FILE mesagl1.opt
+ @ WRITE_ FILE "!"
+ @ WRITE_ FILE "! mesagl1.opt generated by DESCRIP.$(MMS_EXT)"
+ @ WRITE_ FILE "!"
+ @ WRITE_ FILE "IDENTIFICATION=""$(VERSION)"""
+ @ WRITE_ FILE "GSMATCH=LEQUAL,3,1
+ @ WRITE_ FILE "$(OBJECTS)"
+ @ WRITE_ FILE "[-.lib]libmesagl.exe/SHARE"
+ @ WRITE_ FILE "SYS$SHARE:DECW$XEXTLIBSHR/SHARE"
+ @ WRITE_ FILE "SYS$SHARE:DECW$XLIBSHR/SHARE"
+ @ CLOSE_ FILE
+ @ WRITE_ SYS$OUTPUT " generating mesagl.map ..."
+ @ LINK_/NODEB/NOSHARE/NOEXE/MAP=mesagl.map/FULL mesagl1.opt/OPT
+ @ WRITE_ SYS$OUTPUT " analyzing mesagl.map ..."
+ @ @[-.vms]ANALYZE_MAP.COM mesagl.map mesagl.opt
+ @ WRITE_ SYS$OUTPUT " linking $(GLU_LIB) ..."
+ @ LINK_/noinform/NODEB/SHARE=$(GLU_LIB)/MAP=mesagl.map/FULL mesagl1.opt/opt,mesagl.opt/opt
+.else
+ @ $(MAKELIB) $(GLU_LIB) $(OBJECTS)
+.endif
+ @ rename $(GLU_LIB)* $(LIBDIR)
+
+clean :
+ delete *.obj;*
+ purge
+
+include mms_depend.
+
diff --git a/src/glu/mesa/glu.c b/src/glu/mesa/glu.c
new file mode 100644
index 0000000000..2cceb8b743
--- /dev/null
+++ b/src/glu/mesa/glu.c
@@ -0,0 +1,335 @@
+/* $Id: glu.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ * Copyright (C) 1995-1999 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.
+ */
+
+
+/*
+ * $Log: glu.c,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 1.13 1999/03/31 19:07:28 brianp
+ * added GL_EXT_abgr to extensions
+ *
+ * Revision 1.12 1999/02/06 06:12:41 brianp
+ * updated version string to 3.1
+ *
+ * Revision 1.11 1999/01/03 03:23:15 brianp
+ * now using GLAPIENTRY and GLCALLBACK keywords (Ted Jump)
+ *
+ * Revision 1.10 1998/04/22 00:35:50 brianp
+ * changed version to 3.0
+ *
+ * Revision 1.9 1997/12/09 03:03:32 brianp
+ * changed version to 2.6
+ *
+ * Revision 1.8 1997/10/04 01:30:20 brianp
+ * changed version to 2.5
+ *
+ * Revision 1.7 1997/08/13 01:25:21 brianp
+ * changed version string to 2.4
+ *
+ * Revision 1.6 1997/07/24 01:28:44 brianp
+ * changed precompiled header symbol from PCH to PC_HEADER
+ *
+ * Revision 1.5 1997/07/13 22:59:11 brianp
+ * added const to viewport parameter of gluPickMatrix()
+ *
+ * Revision 1.4 1997/05/28 02:29:38 brianp
+ * added support for precompiled headers (PCH), inserted APIENTRY keyword
+ *
+ * Revision 1.3 1997/04/12 16:19:02 brianp
+ * changed version to 2.3
+ *
+ * Revision 1.2 1997/03/11 00:58:34 brianp
+ * changed version to 2.2
+ *
+ * Revision 1.1 1996/09/27 01:19:39 brianp
+ * Initial revision
+ *
+ */
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "gluP.h"
+#endif
+
+
+/*
+ * Miscellaneous utility functions
+ */
+
+
+#ifndef M_PI
+#define M_PI 3.1415926536
+#endif
+#define EPS 0.00001
+
+
+
+
+void GLAPIENTRY gluLookAt( GLdouble eyex, GLdouble eyey, GLdouble eyez,
+ GLdouble centerx, GLdouble centery, GLdouble centerz,
+ GLdouble upx, GLdouble upy, GLdouble upz )
+{
+ GLdouble m[16];
+ GLdouble x[3], y[3], z[3];
+ GLdouble 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
+ glMultMatrixd( m );
+
+ /* Translate Eye to Origin */
+ glTranslated( -eyex, -eyey, -eyez );
+
+}
+
+
+
+void GLAPIENTRY gluOrtho2D( GLdouble left, GLdouble right,
+ GLdouble bottom, GLdouble top )
+{
+ glOrtho( left, right, bottom, top, -1.0, 1.0 );
+}
+
+
+
+void GLAPIENTRY gluPerspective( GLdouble fovy, GLdouble aspect,
+ GLdouble zNear, GLdouble zFar )
+{
+ GLdouble xmin, xmax, ymin, ymax;
+
+ ymax = zNear * tan( fovy * M_PI / 360.0 );
+ ymin = -ymax;
+
+ xmin = ymin * aspect;
+ xmax = ymax * aspect;
+
+ glFrustum( xmin, xmax, ymin, ymax, zNear, zFar );
+}
+
+
+
+void GLAPIENTRY gluPickMatrix( GLdouble x, GLdouble y,
+ GLdouble width, GLdouble height,
+ const 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 gluEndPolygon",
+ "missing gluBeginPolygon",
+ "misoriented contour",
+ "vertex/edge intersection",
+ "misoriented or self-intersecting loops",
+ "coincident vertices",
+ "colinear vertices",
+ "intersecting edges",
+ "not coplanar contours"
+ };
+ 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 encounteed",
+ "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_ERROR9) {
+ 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.1";
+
+ switch (name) {
+ case GLU_EXTENSIONS:
+ return (GLubyte *) extensions;
+ case GLU_VERSION:
+ return (GLubyte *) version;
+ default:
+ return NULL;
+ }
+}
+
diff --git a/src/glu/mesa/gluP.h b/src/glu/mesa/gluP.h
new file mode 100644
index 0000000000..1d036eeb5e
--- /dev/null
+++ b/src/glu/mesa/gluP.h
@@ -0,0 +1,83 @@
+/* $Id: gluP.h,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ * Copyright (C) 1995-1999 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.
+ */
+
+
+/*
+ * $Log: gluP.h,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 1.4 1999/01/03 03:23:15 brianp
+ * now using GLAPIENTRY and GLCALLBACK keywords (Ted Jump)
+ *
+ * Revision 1.3 1997/08/01 22:25:27 brianp
+ * check for Cygnus Win32 (Stephen Rehel)
+ *
+ * Revision 1.2 1997/05/27 02:59:46 brianp
+ * added defines for APIENTRY and CALLBACK if not compiling on Win32
+ *
+ * Revision 1.1 1996/09/27 01:19:39 brianp
+ * Initial revision
+ *
+ */
+
+
+
+/*
+ * 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"
+
+
+#ifndef MESA
+ /* 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/mesa/mipmap.c b/src/glu/mesa/mipmap.c
new file mode 100644
index 0000000000..24af0ba33c
--- /dev/null
+++ b/src/glu/mesa/mipmap.c
@@ -0,0 +1,790 @@
+/* $Id: mipmap.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ * Copyright (C) 1995-1999 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.
+ */
+
+
+/*
+ * $Log: mipmap.c,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 1.13 1999/03/05 17:49:06 brianp
+ * added support for GL_EXT_abgr (devernay@istar.fr)
+ *
+ * Revision 1.12 1999/01/03 03:23:15 brianp
+ * now using GLAPIENTRY and GLCALLBACK keywords (Ted Jump)
+ *
+ * Revision 1.11 1998/09/18 02:44:03 brianp
+ * further changes to gluScaleImage() per Randy Frank
+ *
+ * Revision 1.10 1998/09/17 03:20:26 brianp
+ * fixed another bug in gluScaleImage() per Sven Panne
+ *
+ * Revision 1.9 1998/07/31 03:06:20 brianp
+ * tweaked the gluScaleImage() function per Randy Frank
+ *
+ * Revision 1.8 1998/07/08 01:02:53 brianp
+ * if gluBuildxDMipmaps() width or height <= 0 return GLU_INVALID_VALUE
+ *
+ * Revision 1.7 1998/07/01 00:18:02 brianp
+ * if gluBuildxDMipmaps() width or height <= 0 just return 0
+ *
+ * Revision 1.6 1998/06/01 01:06:41 brianp
+ * small update for Next/OpenStep from Alexander Mai
+ *
+ * Revision 1.5 1997/07/24 01:28:44 brianp
+ * changed precompiled header symbol from PCH to PC_HEADER
+ *
+ * Revision 1.4 1997/06/23 00:22:56 brianp
+ * added dummy() call to work around an MSVC 4.1 bug
+ *
+ * Revision 1.3 1997/05/28 02:29:38 brianp
+ * added support for precompiled headers (PCH), inserted APIENTRY keyword
+ *
+ * Revision 1.2 1997/05/24 13:32:25 brianp
+ * undef EPSILON in case it's already defined
+ *
+ * Revision 1.1 1996/09/27 01:19:39 brianp
+ * Initial revision
+ *
+ */
+
+
+#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,
+ GLint widthin, GLint heightin,
+ GLenum typein, const void *datain,
+ GLint widthout, GLint heightout,
+ GLenum typeout, void *dataout )
+{
+ GLint components, i, j, k;
+ GLfloat *tempin, *tempout;
+ 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:
+ components = 3;
+ break;
+ case GL_RGBA:
+#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 */
+ glGetIntegerv( GL_UNPACK_ROW_LENGTH, &unpackrowlength );
+ glGetIntegerv( GL_UNPACK_ALIGNMENT, &unpackalignment );
+ glGetIntegerv( GL_UNPACK_SKIP_ROWS, &unpackskiprows );
+ glGetIntegerv( GL_UNPACK_SKIP_PIXELS, &unpackskippixels );
+ glGetIntegerv( GL_PACK_ROW_LENGTH, &packrowlength );
+ glGetIntegerv( GL_PACK_ALIGNMENT, &packalignment );
+ glGetIntegerv( GL_PACK_SKIP_ROWS, &packskiprows );
+ glGetIntegerv( GL_PACK_SKIP_PIXELS, &packskippixels );
+
+ /* 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 datatype, 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:
+ n = 3;
+ break;
+ case GL_RGBA:
+#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,
+ GLint width, GLenum format,
+ GLenum type, const void *data )
+{
+ GLubyte *texture;
+ GLint levels, max_levels;
+ GLint new_width, max_width;
+ GLint i, j, k, l;
+
+ if (width < 1)
+ return GLU_INVALID_VALUE;
+
+ glGetIntegerv( GL_MAX_TEXTURE_SIZE, &max_width );
+ max_levels = ilog2( max_width ) + 1;
+
+ /* Compute how many mipmap images to make */
+ levels = ilog2( width ) + 1;
+ if (levels>max_levels) {
+ levels = max_levels;
+ }
+
+ new_width = 1 << (levels-1);
+
+ texture = (GLubyte *) malloc( new_width * components );
+ if (!texture) {
+ return GLU_OUT_OF_MEMORY;
+ }
+
+ if (width != new_width) {
+ /* initial rescaling */
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ {
+ GLubyte *ub_data = (GLubyte *) data;
+ for (i=0;i<new_width;i++) {
+ j = i * width / new_width;
+ for (k=0;k<components;k++) {
+ texture[i*components+k] = ub_data[j*components+k];
+ }
+ }
+ }
+ break;
+ default:
+ /* Not implemented */
+ return GLU_ERROR;
+ }
+ }
+
+ /* generate and load mipmap images */
+ for (l=0;l<levels;l++) {
+ glTexImage1D( GL_TEXTURE_1D, l, components, new_width, 0,
+ format, GL_UNSIGNED_BYTE, texture );
+
+ /* Scale image down to 1/2 size */
+ new_width = new_width / 2;
+ for (i=0;i<new_width;i++) {
+ for (k=0;k<components;k++) {
+ GLint sample1, sample2;
+ sample1 = (GLint) texture[i*2*components+k];
+ sample2 = (GLint) texture[(i*2+1)*components+k];
+ texture[i*components+k] = (GLubyte) ((sample1 + sample2) / 2);
+ }
+ }
+ }
+
+ free( texture );
+
+ /* make sure remaining mipmap levels are removed */
+ for (l=levels;l<max_levels;l++) {
+ glTexImage1D( GL_TEXTURE_1D, l, components, 0, 0,
+ format, GL_UNSIGNED_BYTE, NULL );
+ }
+
+ return 0;
+}
+
+
+
+GLint GLAPIENTRY gluBuild2DMipmaps( GLenum target, GLint components,
+ GLint width, GLint height, GLenum format,
+ GLenum type, const void *data )
+{
+ GLint w, h, maxsize;
+ void *image, *newimage;
+ GLint neww, newh, level, bpp;
+ int error;
+
+ if (width < 1 || height < 1)
+ return GLU_INVALID_VALUE;
+
+ glGetIntegerv( GL_MAX_TEXTURE_SIZE, &maxsize );
+
+ 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;
+ }
+
+ 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) {
+ return error;
+ }
+ }
+ else {
+ image = (void *) data;
+ }
+
+ level = 0;
+ while (1) {
+ 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) {
+ return error;
+ }
+
+ if (image!=data) {
+ free( image );
+ }
+ image = newimage;
+
+ w = neww;
+ h = newh;
+ level++;
+ }
+
+ if (image!=data) {
+ free( image );
+ }
+
+ return 0;
+}
+
diff --git a/src/glu/mesa/mms_depend b/src/glu/mesa/mms_depend
new file mode 100644
index 0000000000..372e3fff1e
--- /dev/null
+++ b/src/glu/mesa/mms_depend
@@ -0,0 +1,13 @@
+# DO NOT DELETE THIS LINE -- make depend depends on it.
+
+glu.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h
+mipmap.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h
+nurbs.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h nurbs.h
+nurbscrv.obj : nurbs.h gluP.h [-.include.gl]gl.h [-.include.gl]glu.h
+nurbssrf.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h nurbs.h
+nurbsutl.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h nurbs.h
+project.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h
+quadric.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h
+tess.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h tess.h
+tesselat.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h tess.h
+polytest.obj : gluP.h [-.include.gl]gl.h [-.include.gl]glu.h tess.h
diff --git a/src/glu/mesa/nurbs.c b/src/glu/mesa/nurbs.c
new file mode 100644
index 0000000000..65bc6f8acb
--- /dev/null
+++ b/src/glu/mesa/nurbs.c
@@ -0,0 +1,715 @@
+/* $Id: nurbs.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ * Copyright (C) 1995-1999 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.
+ */
+
+
+/*
+ * $Log: nurbs.c,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 1.14 1999/01/03 03:23:15 brianp
+ * now using GLAPIENTRY and GLCALLBACK keywords (Ted Jump)
+ *
+ * Revision 1.13 1998/06/01 01:07:49 brianp
+ * small update for Next/OpenStep from Alexander Mai
+ *
+ * Revision 1.12 1998/03/15 18:14:30 brianp
+ * fixed a compiler cast warning
+ *
+ * Revision 1.11 1998/02/07 14:29:11 brianp
+ * fixed casting problem in gluNurbsCallback, again
+ *
+ * Revision 1.10 1998/02/04 00:21:20 brianp
+ * fixed cygnus compilation problem (Stephane Rehel)
+ *
+ * Revision 1.9 1998/01/16 03:35:26 brianp
+ * fixed Windows compilation warnings (Theodore Jump)
+ *
+ * Revision 1.8 1997/09/17 01:51:48 brianp
+ * changed glu*Callback() functions to match prototype in glu.h
+ *
+ * Revision 1.7 1997/07/24 01:28:44 brianp
+ * changed precompiled header symbol from PCH to PC_HEADER
+ *
+ * Revision 1.6 1997/07/24 01:26:31 brianp
+ * added CALLBACK keyword to gluNurbsCallback()
+ *
+ * Revision 1.5 1997/05/28 02:29:38 brianp
+ * added support for precompiled headers (PCH), inserted APIENTRY keyword
+ *
+ * Revision 1.4 1997/05/27 03:17:22 brianp
+ * minor clean-up
+ *
+ * Revision 1.3 1997/05/27 03:00:16 brianp
+ * incorporated Bogdan's new NURBS code
+ *
+ * Revision 1.2 1996/09/27 23:11:23 brianp
+ * ifdef'd out unimplemented trimmed nurbs code
+ *
+ * Revision 1.1 1996/09/27 01:19:39 brianp
+ * Initial revision
+ *
+ */
+
+
+/*
+ * 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) );
+ if (n) {
+ /* init */
+ n->culling=GL_FALSE;
+ n->nurbs_type=GLU_NURBS_NONE;
+ n->error=GLU_NO_ERROR;
+ n->error_callback=NULL;
+ n->auto_load_matrix=GL_TRUE;
+ n->sampling_tolerance=50.0;
+ n->parametric_tolerance=0.5;
+ n->u_step = n->v_step = 100;
+ n->sampling_method = GLU_PATH_LENGTH;
+ n->display_mode=GLU_FILL;
+ /* in case the user doesn't supply the sampling matrices */
+ /* set projection and modelview to identity */
+ for(i=0;i<4;i++)
+ for(j=0;j<4;j++)
+ if(i==j)
+ {
+ n->sampling_matrices.model[i*4+j]=1.0;
+ n->sampling_matrices.proj[i*4+j]=1.0;
+ }
+ else
+ {
+ n->sampling_matrices.model[i*4+j]=0.0;
+ n->sampling_matrices.proj[i*4+j]=0.0;
+ }
+ /* and set the viewport sampling matrix to current ciewport */
+ glGetFloatv(GL_VIEWPORT,tmp_viewport);
+ for(i=0;i<4;i++)
+ n->sampling_matrices.viewport[i]=tmp_viewport[i];
+ n->trim=NULL;
+ }
+ 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] )
+{
+ GLint i;
+
+ for(i=0;i<16;i++)
+ {
+ nobj->sampling_matrices.model[i]=modelMatrix[i];
+ nobj->sampling_matrices.proj[i]=projMatrix[i];
+ }
+ for(i=0;i<4;i++)
+ nobj->sampling_matrices.viewport[i]=viewport[i];
+}
+
+
+void GLAPIENTRY gluNurbsProperty( GLUnurbsObj *nobj, GLenum property, GLfloat value )
+{
+ GLenum val;
+
+ switch (property) {
+ case GLU_SAMPLING_TOLERANCE:
+ if(value <= 0.0)
+ {
+ call_user_error(nobj,GLU_INVALID_VALUE);
+ return;
+ }
+ nobj->sampling_tolerance=value;
+ break;
+ case GLU_PARAMETRIC_TOLERANCE:
+ if(value <= 0.0)
+ {
+ call_user_error(nobj,GLU_INVALID_VALUE);
+ return;
+ }
+ nobj->parametric_tolerance=value;
+ break;
+ case GLU_U_STEP:
+ if(value <= 0.0)
+ {
+ call_user_error(nobj,GLU_INVALID_VALUE);
+ return;
+ }
+ nobj->u_step=(GLint)value;
+ break;
+ case GLU_V_STEP:
+ if(value <= 0.0)
+ {
+ call_user_error(nobj,GLU_INVALID_VALUE);
+ return;
+ }
+ nobj->v_step=(GLint)value;
+ break;
+ case GLU_SAMPLING_METHOD:
+ val = (GLenum)value;
+ if(val!=GLU_PATH_LENGTH && val!=GLU_PARAMETRIC_ERROR && val!=GLU_DOMAIN_DISTANCE)
+ {
+ call_user_error(nobj,GLU_INVALID_ENUM);
+ return;
+ }
+ nobj->sampling_method=val;
+ break;
+ case GLU_DISPLAY_MODE:
+ val=(GLenum)value;
+ if(val!=GLU_FILL && val!=GLU_OUTLINE_POLYGON && val!=GLU_OUTLINE_PATCH)
+ {
+ call_user_error(nobj,GLU_INVALID_ENUM);
+ return;
+ }
+ if(nobj->nurbs_type==GLU_NURBS_CURVE)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR26);
+ return;
+ }
+ nobj->display_mode=val;
+if(val==GLU_OUTLINE_PATCH)
+ fprintf(stderr,"NURBS, for the moment, can display only in POLYGON mode\n");
+ break;
+ case GLU_CULLING:
+ val=(GLenum)value;
+ if(val!=GL_TRUE && val!=GL_FALSE)
+ {
+ call_user_error(nobj,GLU_INVALID_ENUM);
+ return;
+ }
+ nobj->culling = (GLboolean) value;
+ break;
+ case GLU_AUTO_LOAD_MATRIX:
+ val=(GLenum)value;
+ if(val!=GL_TRUE && val!=GL_FALSE)
+ {
+ call_user_error(nobj,GLU_INVALID_ENUM);
+ return;
+ }
+ nobj->auto_load_matrix = (GLboolean) value;
+ break;
+ default:
+ call_user_error(nobj,GLU_NURBS_ERROR26);
+ }
+}
+
+
+void GLAPIENTRY gluGetNurbsProperty( GLUnurbsObj *nobj, GLenum property, GLfloat *value )
+{
+ switch (property) {
+ case GLU_SAMPLING_TOLERANCE:
+ *value = nobj->sampling_tolerance;
+ break;
+ case GLU_DISPLAY_MODE:
+ *value = (GLfloat) (GLint) nobj->display_mode;
+ break;
+ case GLU_CULLING:
+ *value = nobj->culling ? 1.0 : 0.0;
+ break;
+ case GLU_AUTO_LOAD_MATRIX:
+ *value = nobj->auto_load_matrix ? 1.0 : 0.0;
+ break;
+ default:
+ call_user_error(nobj,GLU_INVALID_ENUM);
+ }
+}
+
+
+
+void GLAPIENTRY gluBeginCurve( GLUnurbsObj *nobj )
+{
+ if(nobj->nurbs_type==GLU_NURBS_CURVE)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR6);
+ return;
+ }
+ nobj->nurbs_type=GLU_NURBS_CURVE;
+ nobj->curve.geom.type=GLU_INVALID_ENUM;
+ nobj->curve.color.type=GLU_INVALID_ENUM;
+ nobj->curve.texture.type=GLU_INVALID_ENUM;
+ nobj->curve.normal.type=GLU_INVALID_ENUM;
+}
+
+
+void GLAPIENTRY gluEndCurve( GLUnurbsObj * nobj )
+{
+ if(nobj->nurbs_type==GLU_NURBS_NONE)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR7);
+ return;
+ }
+ if(nobj->curve.geom.type==GLU_INVALID_ENUM)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR8);
+ nobj->nurbs_type=GLU_NURBS_NONE;
+ return;
+ }
+ glPushAttrib( (GLbitfield) (GL_EVAL_BIT | GL_ENABLE_BIT) );
+ glDisable(GL_MAP1_VERTEX_3);
+ glDisable(GL_MAP1_VERTEX_4);
+ glDisable(GL_MAP1_INDEX);
+ glDisable(GL_MAP1_COLOR_4);
+ glDisable(GL_MAP1_NORMAL);
+ glDisable(GL_MAP1_TEXTURE_COORD_1);
+ glDisable(GL_MAP1_TEXTURE_COORD_2);
+ glDisable(GL_MAP1_TEXTURE_COORD_3);
+ glDisable(GL_MAP1_TEXTURE_COORD_4);
+ glDisable(GL_MAP2_VERTEX_3);
+ glDisable(GL_MAP2_VERTEX_4);
+ glDisable(GL_MAP2_INDEX);
+ glDisable(GL_MAP2_COLOR_4);
+ glDisable(GL_MAP2_NORMAL);
+ glDisable(GL_MAP2_TEXTURE_COORD_1);
+ glDisable(GL_MAP2_TEXTURE_COORD_2);
+ glDisable(GL_MAP2_TEXTURE_COORD_3);
+ glDisable(GL_MAP2_TEXTURE_COORD_4);
+ do_nurbs_curve(nobj);
+ glPopAttrib();
+ nobj->nurbs_type=GLU_NURBS_NONE;
+}
+
+
+void GLAPIENTRY gluNurbsCurve( GLUnurbsObj *nobj, GLint nknots, GLfloat *knot,
+ GLint stride, GLfloat *ctlarray, GLint order, GLenum type )
+{
+ if(nobj->nurbs_type==GLU_NURBS_TRIM)
+ {
+#if 0
+/* TODO: NOT IMPLEMENTED YET */
+ nurbs_trim *ptr1;
+ trim_list *ptr2;
+
+ if(type!=GLU_MAP1_TRIM_2 && type!=GLU_MAP1_TRIM_3)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR14);
+ return;
+ }
+ for(ptr1=nobj->trim;ptr1->next;ptr1=ptr1->next);
+ if(ptr1->trim_loop)
+ {
+ for(ptr2=ptr1->trim_loop;ptr2->next;ptr2=ptr2->next);
+ if((ptr2->next=(trim_list *)malloc(sizeof(trim_list)))==NULL)
+ {
+ call_user_error(nobj,GLU_OUT_OF_MEMORY);
+ return;
+ }
+ ptr2=ptr2->next;
+ }
+ else
+ {
+ if((ptr2=(trim_list *)malloc(sizeof(trim_list)))==NULL)
+ {
+ call_user_error(nobj,GLU_OUT_OF_MEMORY);
+ return;
+ }
+ ptr1->trim_loop=ptr2;
+ }
+ ptr2->trim_type=GLU_TRIM_NURBS;
+ ptr2->curve.nurbs_curve.knot_count=nknots;
+ ptr2->curve.nurbs_curve.knot=knot;
+ ptr2->curve.nurbs_curve.stride=stride;
+ ptr2->curve.nurbs_curve.ctrlarray=ctlarray;
+ ptr2->curve.nurbs_curve.order=order;
+ ptr2->curve.nurbs_curve.dim= (type==GLU_MAP1_TRIM_2 ? 2 : 3 );
+ ptr2->curve.nurbs_curve.type=type;
+ ptr2->next=NULL;
+#endif
+ }
+ else
+ {
+ if(type==GLU_MAP1_TRIM_2 || type==GLU_MAP1_TRIM_3)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR22);
+ return;
+ }
+ if(nobj->nurbs_type!=GLU_NURBS_CURVE)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR10);
+ return;
+ }
+ switch(type)
+ {
+ case GL_MAP1_VERTEX_3:
+ case GL_MAP1_VERTEX_4:
+ if(nobj->curve.geom.type!=GLU_INVALID_ENUM)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR8);
+ return;
+ }
+ nobj->curve.geom.type=type;
+ nobj->curve.geom.knot_count=nknots;
+ nobj->curve.geom.knot=knot;
+ nobj->curve.geom.stride=stride;
+ nobj->curve.geom.ctrlarray=ctlarray;
+ nobj->curve.geom.order=order;
+ break;
+ case GL_MAP1_INDEX:
+ case GL_MAP1_COLOR_4:
+ nobj->curve.color.type=type;
+ nobj->curve.color.knot_count=nknots;
+ nobj->curve.color.knot=knot;
+ nobj->curve.color.stride=stride;
+ nobj->curve.color.ctrlarray=ctlarray;
+ nobj->curve.color.order=order;
+ break;
+ case GL_MAP1_NORMAL:
+ nobj->curve.normal.type=type;
+ nobj->curve.normal.knot_count=nknots;
+ nobj->curve.normal.knot=knot;
+ nobj->curve.normal.stride=stride;
+ nobj->curve.normal.ctrlarray=ctlarray;
+ nobj->curve.normal.order=order;
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ case GL_MAP1_TEXTURE_COORD_2:
+ case GL_MAP1_TEXTURE_COORD_3:
+ case GL_MAP1_TEXTURE_COORD_4:
+ nobj->curve.texture.type=type;
+ nobj->curve.texture.knot_count=nknots;
+ nobj->curve.texture.knot=knot;
+ nobj->curve.texture.stride=stride;
+ nobj->curve.texture.ctrlarray=ctlarray;
+ nobj->curve.texture.order=order;
+ break;
+ default:
+ call_user_error(nobj,GLU_INVALID_ENUM);
+ }
+ }
+}
+
+
+void GLAPIENTRY gluBeginSurface( GLUnurbsObj *nobj )
+{
+ switch(nobj->nurbs_type)
+ {
+ case GLU_NURBS_NONE:
+ nobj->nurbs_type=GLU_NURBS_SURFACE;
+ nobj->surface.geom.type=GLU_INVALID_ENUM;
+ nobj->surface.color.type=GLU_INVALID_ENUM;
+ nobj->surface.texture.type=GLU_INVALID_ENUM;
+ nobj->surface.normal.type=GLU_INVALID_ENUM;
+ break;
+ case GLU_NURBS_TRIM:
+ call_user_error(nobj,GLU_NURBS_ERROR16);
+ break;
+ case GLU_NURBS_SURFACE:
+ case GLU_NURBS_NO_TRIM:
+ case GLU_NURBS_TRIM_DONE:
+ call_user_error(nobj,GLU_NURBS_ERROR27);
+ break;
+ case GLU_NURBS_CURVE:
+ call_user_error(nobj,GLU_NURBS_ERROR6);
+ break;
+ }
+}
+
+
+void GLAPIENTRY gluEndSurface( GLUnurbsObj * nobj )
+{
+ switch(nobj->nurbs_type)
+ {
+ case GLU_NURBS_NONE:
+ call_user_error(nobj,GLU_NURBS_ERROR13);
+ break;
+ case GLU_NURBS_TRIM:
+ call_user_error(nobj,GLU_NURBS_ERROR12);
+ break;
+ case GLU_NURBS_TRIM_DONE:
+/* if(nobj->trim->trim_loop==NULL)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR18);
+ return;
+ }*/
+ /* no break - fallthrough */
+ case GLU_NURBS_NO_TRIM:
+ glPushAttrib( (GLbitfield)
+ (GL_EVAL_BIT | GL_ENABLE_BIT | GL_POLYGON_BIT) );
+ glDisable(GL_MAP2_VERTEX_3);
+ glDisable(GL_MAP2_VERTEX_4);
+ glDisable(GL_MAP2_INDEX);
+ glDisable(GL_MAP2_COLOR_4);
+ glDisable(GL_MAP2_NORMAL);
+ glDisable(GL_MAP2_TEXTURE_COORD_1);
+ glDisable(GL_MAP2_TEXTURE_COORD_2);
+ glDisable(GL_MAP2_TEXTURE_COORD_3);
+ glDisable(GL_MAP2_TEXTURE_COORD_4);
+/* glDisable(GL_MAP1_VERTEX_3);
+ glDisable(GL_MAP1_VERTEX_4);
+ glDisable(GL_MAP1_INDEX);
+ glDisable(GL_MAP1_COLOR_4);
+ glDisable(GL_MAP1_NORMAL);
+ glDisable(GL_MAP1_TEXTURE_COORD_1);
+ glDisable(GL_MAP1_TEXTURE_COORD_2);
+ glDisable(GL_MAP1_TEXTURE_COORD_3);
+ glDisable(GL_MAP1_TEXTURE_COORD_4);*/
+ do_nurbs_surface(nobj);
+ glPopAttrib();
+ break;
+ default:
+ call_user_error(nobj,GLU_NURBS_ERROR8);
+ }
+ nobj->nurbs_type=GLU_NURBS_NONE;
+}
+
+
+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 )
+{
+ if(nobj->nurbs_type==GLU_NURBS_NO_TRIM || nobj->nurbs_type==GLU_NURBS_TRIM ||
+ nobj->nurbs_type==GLU_NURBS_TRIM_DONE)
+ {
+ if(type==GL_MAP2_VERTEX_3 || type==GL_MAP2_VERTEX_4)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR8);
+ return;
+ }
+ }
+ else
+ if(nobj->nurbs_type!=GLU_NURBS_SURFACE)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR11);
+ return;
+ }
+ switch(type)
+ {
+ case GL_MAP2_VERTEX_3:
+ case GL_MAP2_VERTEX_4:
+ nobj->surface.geom.sknot_count=sknot_count;
+ nobj->surface.geom.sknot=sknot;
+ nobj->surface.geom.tknot_count=tknot_count;
+ nobj->surface.geom.tknot=tknot;
+ nobj->surface.geom.s_stride=s_stride;
+ nobj->surface.geom.t_stride=t_stride;
+ nobj->surface.geom.ctrlarray=ctrlarray;
+ nobj->surface.geom.sorder=sorder;
+ nobj->surface.geom.torder=torder;
+ nobj->surface.geom.type=type;
+ nobj->nurbs_type=GLU_NURBS_NO_TRIM;
+ break;
+ case GL_MAP2_INDEX:
+ case GL_MAP2_COLOR_4:
+ nobj->surface.color.sknot_count=sknot_count;
+ nobj->surface.color.sknot=sknot;
+ nobj->surface.color.tknot_count=tknot_count;
+ nobj->surface.color.tknot=tknot;
+ nobj->surface.color.s_stride=s_stride;
+ nobj->surface.color.t_stride=t_stride;
+ nobj->surface.color.ctrlarray=ctrlarray;
+ nobj->surface.color.sorder=sorder;
+ nobj->surface.color.torder=torder;
+ nobj->surface.color.type=type;
+ break;
+ case GL_MAP2_NORMAL:
+ nobj->surface.normal.sknot_count=sknot_count;
+ nobj->surface.normal.sknot=sknot;
+ nobj->surface.normal.tknot_count=tknot_count;
+ nobj->surface.normal.tknot=tknot;
+ nobj->surface.normal.s_stride=s_stride;
+ nobj->surface.normal.t_stride=t_stride;
+ nobj->surface.normal.ctrlarray=ctrlarray;
+ nobj->surface.normal.sorder=sorder;
+ nobj->surface.normal.torder=torder;
+ nobj->surface.normal.type=type;
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ case GL_MAP2_TEXTURE_COORD_2:
+ case GL_MAP2_TEXTURE_COORD_3:
+ case GL_MAP2_TEXTURE_COORD_4:
+ nobj->surface.texture.sknot_count=sknot_count;
+ nobj->surface.texture.sknot=sknot;
+ nobj->surface.texture.tknot_count=tknot_count;
+ nobj->surface.texture.tknot=tknot;
+ nobj->surface.texture.s_stride=s_stride;
+ nobj->surface.texture.t_stride=t_stride;
+ nobj->surface.texture.ctrlarray=ctrlarray;
+ nobj->surface.texture.sorder=sorder;
+ nobj->surface.texture.torder=torder;
+ nobj->surface.texture.type=type;
+ break;
+ default:
+ call_user_error(nobj,GLU_INVALID_ENUM);
+ }
+}
+
+
+void GLAPIENTRY
+gluNurbsCallback( GLUnurbsObj *nobj, GLenum which, void (GLCALLBACK *fn)())
+{
+#if defined(__CYGWIN32__) || defined(OPENSTEP)
+ nobj->error_callback = (void(*)(GLenum))fn;
+#else
+ nobj->error_callback = (void(GLCALLBACK*)(GLenum))fn;
+#endif
+
+ if(which!=GLU_ERROR)
+ call_user_error(nobj,GLU_INVALID_ENUM);
+}
+
+void GLAPIENTRY
+gluBeginTrim( GLUnurbsObj *nobj )
+{
+#if 0
+ nurbs_trim *ptr;
+#endif
+
+ if(nobj->nurbs_type!=GLU_NURBS_TRIM_DONE)
+ if(nobj->nurbs_type!=GLU_NURBS_NO_TRIM)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR15);
+ return;
+ }
+ nobj->nurbs_type=GLU_NURBS_TRIM;
+fprintf(stderr,"NURBS - trimming not supported yet\n");
+#if 0
+ if((ptr=(nurbs_trim *)malloc(sizeof(nurbs_trim)))==NULL)
+ {
+ call_user_error(nobj,GLU_OUT_OF_MEMORY);
+ return;
+ }
+ if(nobj->trim)
+ {
+ nurbs_trim *tmp_ptr;
+
+ for(tmp_ptr=nobj->trim;tmp_ptr->next;tmp_ptr=tmp_ptr->next);
+ tmp_ptr->next=ptr;
+ }
+ else
+ nobj->trim=ptr;
+ ptr->trim_loop=NULL;
+ ptr->segments=NULL;
+ ptr->next=NULL;
+#endif
+}
+
+void GLAPIENTRY
+gluPwlCurve( GLUnurbsObj *nobj, GLint count, GLfloat *array, GLint stride,
+ GLenum type)
+{
+#if 0
+ nurbs_trim *ptr1;
+ trim_list *ptr2;
+#endif
+ if(nobj->nurbs_type==GLU_NURBS_CURVE)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR9);
+ return;
+ }
+ if(nobj->nurbs_type==GLU_NURBS_NONE)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR19);
+ return;
+ }
+ if(type!=GLU_MAP1_TRIM_2 && type!=GLU_MAP1_TRIM_3)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR14);
+ return;
+ }
+#if 0
+ for(ptr1=nobj->trim;ptr1->next;ptr1=ptr1->next);
+ if(ptr1->trim_loop)
+ {
+ for(ptr2=ptr1->trim_loop;ptr2->next;ptr2=ptr2->next);
+ if((ptr2->next=(trim_list *)malloc(sizeof(trim_list)))==NULL)
+ {
+ call_user_error(nobj,GLU_OUT_OF_MEMORY);
+ return;
+ }
+ ptr2=ptr2->next;
+ }
+ else
+ {
+ if((ptr2=(trim_list *)malloc(sizeof(trim_list)))==NULL)
+ {
+ call_user_error(nobj,GLU_OUT_OF_MEMORY);
+ return;
+ }
+ ptr1->trim_loop=ptr2;
+ }
+ ptr2->trim_type=GLU_TRIM_PWL;
+ ptr2->curve.pwl_curve.pt_count=count;
+ ptr2->curve.pwl_curve.ctrlarray=array;
+ ptr2->curve.pwl_curve.stride=stride;
+ ptr2->curve.pwl_curve.dim= (type==GLU_MAP1_TRIM_2 ? 2 : 3 );
+ ptr2->curve.pwl_curve.type=type;
+ ptr2->next=NULL;
+#endif
+}
+
+void GLAPIENTRY
+gluEndTrim( GLUnurbsObj *nobj )
+{
+ if(nobj->nurbs_type!=GLU_NURBS_TRIM)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR17);
+ return;
+ }
+ nobj->nurbs_type=GLU_NURBS_TRIM_DONE;
+}
+
diff --git a/src/glu/mesa/nurbs.h b/src/glu/mesa/nurbs.h
new file mode 100644
index 0000000000..fc2b4f7d55
--- /dev/null
+++ b/src/glu/mesa/nurbs.h
@@ -0,0 +1,252 @@
+/* $Id: nurbs.h,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ * Copyright (C) 1995-1999 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.
+ */
+
+
+/*
+ * $Log: nurbs.h,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 1.5 1999/02/27 13:55:31 brianp
+ * fixed BeOS-related GLU typedef problems
+ *
+ * Revision 1.4 1999/01/03 03:23:15 brianp
+ * now using GLAPIENTRY and GLCALLBACK keywords (Ted Jump)
+ *
+ * Revision 1.3 1997/05/27 03:18:23 brianp
+ * minor clean-up
+ *
+ * Revision 1.2 1997/05/27 03:00:16 brianp
+ * incorporated Bogdan's new NURBS code
+ *
+ * Revision 1.1 1996/09/27 01:19:39 brianp
+ * Initial revision
+ *
+ */
+
+
+/*
+ * 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/mesa/nurbscrv.c b/src/glu/mesa/nurbscrv.c
new file mode 100644
index 0000000000..022818b73c
--- /dev/null
+++ b/src/glu/mesa/nurbscrv.c
@@ -0,0 +1,500 @@
+/* $Id: nurbscrv.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 2.4
+ * Copyright (C) 1995-1997 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.
+ */
+
+
+/*
+ * $Log: nurbscrv.c,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 1.6 1997/07/24 01:28:44 brianp
+ * changed precompiled header symbol from PCH to PC_HEADER
+ *
+ * Revision 1.5 1997/05/28 02:29:38 brianp
+ * added support for precompiled headers (PCH), inserted APIENTRY keyword
+ *
+ * Revision 1.4 1997/05/27 03:21:22 brianp
+ * minor clean-up
+ *
+ * Revision 1.3 1997/05/27 03:00:16 brianp
+ * incorporated Bogdan's new NURBS code
+ *
+ * Revision 1.2 1996/09/27 23:12:22 brianp
+ * added return 0 to get_surface_dim() to silence warning
+ *
+ * Revision 1.1 1996/09/27 01:19:39 brianp
+ * Initial revision
+ *
+ */
+
+
+/*
+ * 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
+
+
+static int
+get_curve_dim(GLenum type)
+{
+ switch(type)
+ {
+ case GL_MAP1_VERTEX_3: return 3;
+ case GL_MAP1_VERTEX_4: return 4;
+ case GL_MAP1_INDEX: return 1;
+ case GL_MAP1_COLOR_4: return 4;
+ case GL_MAP1_NORMAL: return 3;
+ case GL_MAP1_TEXTURE_COORD_1: return 1;
+ case GL_MAP1_TEXTURE_COORD_2: return 2;
+ case GL_MAP1_TEXTURE_COORD_3: return 3;
+ case GL_MAP1_TEXTURE_COORD_4: return 4;
+ default: abort(); /* TODO: is this OK? */
+ }
+ return 0; /*never get here*/
+}
+
+static GLenum
+test_nurbs_curve(GLUnurbsObj *nobj, curve_attribs *attribs)
+{
+ GLenum err;
+ GLint tmp_int;
+
+ if(attribs->order < 0)
+ {
+ call_user_error(nobj,GLU_INVALID_VALUE);
+ return GLU_ERROR;
+ }
+ glGetIntegerv(GL_MAX_EVAL_ORDER,&tmp_int);
+ if(attribs->order > tmp_int || attribs->order < 2)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR1);
+ return GLU_ERROR;
+ }
+ if(attribs->knot_count < attribs->order +2)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR2);
+ return GLU_ERROR;
+ }
+ if(attribs->stride < 0)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR34);
+ return GLU_ERROR;
+ }
+ if(attribs->knot==NULL || attribs->ctrlarray==NULL)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR36);
+ return GLU_ERROR;
+ }
+ if((err=test_knot(attribs->knot_count,attribs->knot,attribs->order))
+ !=GLU_NO_ERROR)
+ {
+ call_user_error(nobj,err);
+ return GLU_ERROR;
+ }
+ return GLU_NO_ERROR;
+}
+
+static GLenum
+test_nurbs_curves(GLUnurbsObj *nobj)
+{
+ /* test the geometric data */
+ if(test_nurbs_curve(nobj,&(nobj->curve.geom))!=GLU_NO_ERROR)
+ return GLU_ERROR;
+ /* now test the attributive data */
+ /* color */
+ if(nobj->curve.color.type!=GLU_INVALID_ENUM)
+ if(test_nurbs_curve(nobj,&(nobj->curve.color))!=GLU_NO_ERROR)
+ return GLU_ERROR;
+ /* normal */
+ if(nobj->curve.normal.type!=GLU_INVALID_ENUM)
+ if(test_nurbs_curve(nobj,&(nobj->curve.normal))!=GLU_NO_ERROR)
+ return GLU_ERROR;
+ /* texture */
+ if(nobj->curve.texture.type!=GLU_INVALID_ENUM)
+ if(test_nurbs_curve(nobj,&(nobj->curve.texture))!=GLU_NO_ERROR)
+ return GLU_ERROR;
+ return GLU_NO_ERROR;
+}
+
+/* prepare the knot information structures */
+static GLenum
+fill_knot_structures(GLUnurbsObj *nobj,knot_str_type *geom_knot,
+ knot_str_type *color_knot, knot_str_type *normal_knot,
+ knot_str_type *texture_knot)
+{
+ GLint order;
+ GLfloat *knot;
+ GLint nknots;
+ GLint t_min,t_max;
+
+ geom_knot->unified_knot=NULL;
+ knot=geom_knot->knot=nobj->curve.geom.knot;
+ nknots=geom_knot->nknots=nobj->curve.geom.knot_count;
+ order=geom_knot->order=nobj->curve.geom.order;
+ geom_knot->delta_nknots=0;
+ t_min=geom_knot->t_min=order-1;
+ t_max=geom_knot->t_max=nknots-order;
+ if(fabs(knot[t_min]-knot[t_max])<EPSILON)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR3);
+ return GLU_ERROR;
+ }
+ if(fabs(knot[0]-knot[t_min])<EPSILON)
+ {
+ /* knot open at beggining */
+ geom_knot->open_at_begin=GL_TRUE;
+ }
+ else
+ geom_knot->open_at_begin=GL_FALSE;
+ if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
+ {
+ /* knot open at end */
+ geom_knot->open_at_end=GL_TRUE;
+ }
+ else
+ geom_knot->open_at_end=GL_FALSE;
+ if(nobj->curve.color.type!=GLU_INVALID_ENUM)
+ {
+ color_knot->unified_knot=(GLfloat *)1;
+ knot=color_knot->knot=nobj->curve.color.knot;
+ nknots=color_knot->nknots=nobj->curve.color.knot_count;
+ order=color_knot->order=nobj->curve.color.order;
+ color_knot->delta_nknots=0;
+ t_min=color_knot->t_min=order-1;
+ t_max=color_knot->t_max=nknots-order;
+ if(fabs(knot[t_min]-knot[t_max])<EPSILON)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR3);
+ return GLU_ERROR;
+ }
+ if(fabs(knot[0]-knot[t_min])<EPSILON)
+ {
+ /* knot open at beggining */
+ color_knot->open_at_begin=GL_TRUE;
+ }
+ else
+ color_knot->open_at_begin=GL_FALSE;
+ if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
+ {
+ /* knot open at end */
+ color_knot->open_at_end=GL_TRUE;
+ }
+ else
+ color_knot->open_at_end=GL_FALSE;
+ }
+ else
+ color_knot->unified_knot=NULL;
+ if(nobj->curve.normal.type!=GLU_INVALID_ENUM)
+ {
+ normal_knot->unified_knot=(GLfloat *)1;
+ knot=normal_knot->knot=nobj->curve.normal.knot;
+ nknots=normal_knot->nknots=nobj->curve.normal.knot_count;
+ order=normal_knot->order=nobj->curve.normal.order;
+ normal_knot->delta_nknots=0;
+ t_min=normal_knot->t_min=order-1;
+ t_max=normal_knot->t_max=nknots-order;
+ if(fabs(knot[t_min]-knot[t_max])<EPSILON)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR3);
+ return GLU_ERROR;
+ }
+ if(fabs(knot[0]-knot[t_min])<EPSILON)
+ {
+ /* knot open at beggining */
+ normal_knot->open_at_begin=GL_TRUE;
+ }
+ else
+ normal_knot->open_at_begin=GL_FALSE;
+ if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
+ {
+ /* knot open at end */
+ normal_knot->open_at_end=GL_TRUE;
+ }
+ else
+ normal_knot->open_at_end=GL_FALSE;
+ }
+ else
+ normal_knot->unified_knot=NULL;
+ if(nobj->curve.texture.type!=GLU_INVALID_ENUM)
+ {
+ texture_knot->unified_knot=(GLfloat *)1;
+ knot=texture_knot->knot=nobj->curve.texture.knot;
+ nknots=texture_knot->nknots=nobj->curve.texture.knot_count;
+ order=texture_knot->order=nobj->curve.texture.order;
+ texture_knot->delta_nknots=0;
+ t_min=texture_knot->t_min=order-1;
+ t_max=texture_knot->t_max=nknots-order;
+ if(fabs(knot[t_min]-knot[t_max])<EPSILON)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR3);
+ return GLU_ERROR;
+ }
+ if(fabs(knot[0]-knot[t_min])<EPSILON)
+ {
+ /* knot open at beggining */
+ texture_knot->open_at_begin=GL_TRUE;
+ }
+ else
+ texture_knot->open_at_begin=GL_FALSE;
+ if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
+ {
+ /* knot open at end */
+ texture_knot->open_at_end=GL_TRUE;
+ }
+ else
+ texture_knot->open_at_end=GL_FALSE;
+ }
+ else
+ texture_knot->unified_knot=NULL;
+ return GLU_NO_ERROR;
+}
+
+/* covert the NURBS curve into a series of adjacent Bezier curves */
+static GLenum
+convert_curve(knot_str_type *the_knot, curve_attribs *attrib,
+ GLfloat **new_ctrl,GLint *ncontrol)
+{
+ GLenum err;
+
+ if((err=explode_knot(the_knot))!=GLU_NO_ERROR)
+ {
+ if(the_knot->unified_knot)
+ {
+ free(the_knot->unified_knot);
+ the_knot->unified_knot=NULL;
+ }
+ return err;
+ }
+ if(the_knot->unified_knot)
+ {
+ free(the_knot->unified_knot);
+ the_knot->unified_knot=NULL;
+ }
+ if((err=calc_alphas(the_knot))!=GLU_NO_ERROR)
+ {
+ free(the_knot->new_knot);
+ return err;
+ }
+ free(the_knot->new_knot);
+ if((err=calc_new_ctrl_pts(attrib->ctrlarray,attrib->stride,the_knot,
+ attrib->dim,new_ctrl,ncontrol))
+ !=GLU_NO_ERROR)
+ {
+ free(the_knot->alpha);
+ return err;
+ }
+ free(the_knot->alpha);
+ return GLU_NO_ERROR;
+}
+
+/* covert curves - geometry and possible attribute ones into equivalent */
+/* sequence of adjacent Bezier curves */
+static GLenum
+convert_curves(GLUnurbsObj *nobj, GLfloat **new_geom_ctrl,
+ GLint *ncontrol, GLfloat **new_color_ctrl, GLfloat **new_normal_ctrl,
+ GLfloat **new_texture_ctrl)
+{
+ knot_str_type geom_knot,color_knot,normal_knot,texture_knot;
+ GLint junk;
+ GLenum err;
+
+ *new_color_ctrl=*new_normal_ctrl=*new_texture_ctrl=NULL;
+
+ if(fill_knot_structures(nobj,&geom_knot,&color_knot,&normal_knot,
+ &texture_knot)!=GLU_NO_ERROR)
+ return GLU_ERROR;
+
+ /* unify knots - all knots should have the same number of working */
+ /* ranges */
+ if((err=select_knot_working_range(nobj,&geom_knot,&color_knot,&normal_knot,
+ &texture_knot))!=GLU_NO_ERROR)
+ {
+ return err;
+ }
+ /* convert the geometry curve */
+ nobj->curve.geom.dim=get_curve_dim(nobj->curve.geom.type);
+ if((err=convert_curve(&geom_knot,&(nobj->curve.geom),new_geom_ctrl,
+ ncontrol))!=GLU_NO_ERROR)
+ {
+ free_unified_knots(&geom_knot,&color_knot,&normal_knot,&texture_knot);
+ call_user_error(nobj,err);
+ return err;
+ }
+ /* if additional attributive curves are given convert them as well */
+ if(color_knot.unified_knot)
+ {
+ nobj->curve.color.dim=get_curve_dim(nobj->curve.color.type);
+ if((err=convert_curve(&color_knot,&(nobj->curve.color),
+ new_color_ctrl,&junk))!=GLU_NO_ERROR)
+ {
+ free_unified_knots(&geom_knot,&color_knot,&normal_knot,&texture_knot);
+ free(*new_geom_ctrl);
+ call_user_error(nobj,err);
+ return err;
+ }
+ }
+ if(normal_knot.unified_knot)
+ {
+ nobj->curve.normal.dim=get_curve_dim(nobj->curve.normal.type);
+ if((err=convert_curve(&normal_knot,&(nobj->curve.normal),
+ new_normal_ctrl,&junk))!=GLU_NO_ERROR)
+ {
+ free_unified_knots(&geom_knot,&color_knot,&normal_knot,&texture_knot);
+ free(*new_geom_ctrl);
+ if(*new_color_ctrl)
+ free(*new_color_ctrl);
+ call_user_error(nobj,err);
+ return err;
+ }
+ }
+ if(texture_knot.unified_knot)
+ {
+ nobj->curve.texture.dim=get_curve_dim(nobj->curve.texture.type);
+ if((err=convert_curve(&texture_knot,&(nobj->curve.texture),
+ new_texture_ctrl,&junk))!=GLU_NO_ERROR)
+ {
+ free_unified_knots(&geom_knot,&color_knot,&normal_knot,&texture_knot);
+ free(*new_geom_ctrl);
+ if(*new_color_ctrl)
+ free(*new_color_ctrl);
+ if(*new_normal_ctrl)
+ free(*new_normal_ctrl);
+ call_user_error(nobj,err);
+ return err;
+ }
+ }
+ return GLU_NO_ERROR;
+}
+
+/* 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,*color_ctrl,*normal_ctrl,*texture_ctrl;
+ 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/mesa/nurbssrf.c b/src/glu/mesa/nurbssrf.c
new file mode 100644
index 0000000000..57eb956986
--- /dev/null
+++ b/src/glu/mesa/nurbssrf.c
@@ -0,0 +1,1422 @@
+/* $Id: nurbssrf.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 2.4
+ * Copyright (C) 1995-1997 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.
+ */
+
+
+/*
+ * $Log: nurbssrf.c,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 1.7 1997/07/24 01:28:44 brianp
+ * changed precompiled header symbol from PCH to PC_HEADER
+ *
+ * Revision 1.6 1997/06/23 00:22:07 brianp
+ * include <string.h>
+ *
+ * Revision 1.5 1997/05/28 02:29:38 brianp
+ * added support for precompiled headers (PCH), inserted APIENTRY keyword
+ *
+ * Revision 1.4 1997/05/27 03:20:35 brianp
+ * minor clean-up
+ *
+ * Revision 1.3 1997/05/27 03:00:16 brianp
+ * incorporated Bogdan's new NURBS code
+ *
+ * Revision 1.2 1996/09/27 23:13:02 brianp
+ * added return 0 to get_surface_dim() to silence warning
+ *
+ * Revision 1.1 1996/09/27 01:19:39 brianp
+ * Initial revision
+ *
+ */
+
+
+/*
+ * 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 <string.h>
+#include "gluP.h"
+#include "nurbs.h"
+#endif
+
+
+static int
+get_surface_dim(GLenum type)
+{
+ switch(type)
+ {
+ case GL_MAP2_VERTEX_3: return 3;
+ case GL_MAP2_VERTEX_4: return 4;
+ case GL_MAP2_INDEX: return 1;
+ case GL_MAP2_COLOR_4: return 4;
+ case GL_MAP2_NORMAL: return 3;
+ case GL_MAP2_TEXTURE_COORD_1: return 1;
+ case GL_MAP2_TEXTURE_COORD_2: return 2;
+ case GL_MAP2_TEXTURE_COORD_3: return 3;
+ case GL_MAP2_TEXTURE_COORD_4: return 4;
+ default: abort(); /* TODO: is this OK? */
+ }
+ return 0; /*never get here*/
+}
+
+static GLenum
+test_nurbs_surface(GLUnurbsObj *nobj, surface_attribs *attrib)
+{
+ GLenum err;
+ GLint tmp_int;
+
+ if(attrib->sorder < 0 || attrib->torder < 0)
+ {
+ call_user_error(nobj,GLU_INVALID_VALUE);
+ return GLU_ERROR;
+ }
+ glGetIntegerv(GL_MAX_EVAL_ORDER,&tmp_int);
+ if(attrib->sorder > tmp_int || attrib->sorder < 2)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR1);
+ return GLU_ERROR;
+ }
+ if(attrib->torder > tmp_int || attrib->torder < 2)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR1);
+ return GLU_ERROR;
+ }
+ if(attrib->sknot_count < attrib->sorder +2)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR2);
+ return GLU_ERROR;
+ }
+ if(attrib->tknot_count < attrib->torder +2)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR2);
+ return GLU_ERROR;
+ }
+ if(attrib->s_stride < 0 || attrib->t_stride < 0)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR34);
+ return GLU_ERROR;
+ }
+ if(attrib->sknot==NULL || attrib->tknot==NULL || attrib->ctrlarray==NULL)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR36);
+ return GLU_ERROR;
+ }
+ if((err=test_knot(attrib->tknot_count,attrib->tknot,attrib->torder))
+ !=GLU_NO_ERROR)
+ {
+ call_user_error(nobj,err);
+ return GLU_ERROR;
+ }
+ if((err=test_knot(attrib->sknot_count,attrib->sknot,attrib->sorder))
+ !=GLU_NO_ERROR)
+ {
+ call_user_error(nobj,err);
+ return GLU_ERROR;
+ }
+ return GLU_NO_ERROR;
+}
+
+static GLenum
+test_nurbs_surfaces(GLUnurbsObj *nobj)
+{
+ /* test the geometric data */
+ if(test_nurbs_surface(nobj,&(nobj->surface.geom))!=GLU_NO_ERROR)
+ return GLU_ERROR;
+ /* now test the attributive data */
+ /* color */
+ if(nobj->surface.color.type!=GLU_INVALID_ENUM)
+ if(test_nurbs_surface(nobj,&(nobj->surface.color))!=GLU_NO_ERROR)
+ return GLU_ERROR;
+ /* normal */
+ if(nobj->surface.normal.type!=GLU_INVALID_ENUM)
+ if(test_nurbs_surface(nobj,&(nobj->surface.normal))!=GLU_NO_ERROR)
+ return GLU_ERROR;
+ /* texture */
+ if(nobj->surface.texture.type!=GLU_INVALID_ENUM)
+ if(test_nurbs_surface(nobj,&(nobj->surface.texture))!=GLU_NO_ERROR)
+ return GLU_ERROR;
+ return GLU_NO_ERROR;
+}
+
+static GLenum
+convert_surf(knot_str_type *s_knot, knot_str_type *t_knot,
+ surface_attribs *attrib, GLfloat **new_ctrl,
+ GLint *s_n_ctrl, GLint *t_n_ctrl)
+{
+ GLfloat **tmp_ctrl;
+ GLfloat *ctrl_offset;
+ GLint tmp_n_control;
+ GLint i,j,t_cnt,s_cnt;
+ GLint tmp_stride;
+ GLint dim;
+ GLenum err;
+
+ /* valid range is empty? */
+ if((s_knot->unified_knot !=NULL && s_knot->unified_nknots==0) ||
+ (t_knot->unified_knot !=NULL && t_knot->unified_nknots==0))
+ {
+ if(s_knot->unified_knot)
+ {
+ free(s_knot->unified_knot);
+ s_knot->unified_knot=NULL;
+ }
+ if(t_knot->unified_knot)
+ {
+ free(t_knot->unified_knot);
+ t_knot->unified_knot=NULL;
+ }
+ *s_n_ctrl=0;
+ *t_n_ctrl=0;
+ return GLU_NO_ERROR;
+ }
+ t_cnt=attrib->tknot_count-attrib->torder;
+ s_cnt=attrib->sknot_count-attrib->sorder;
+ if((tmp_ctrl=(GLfloat **)malloc(sizeof(GLfloat *)*t_cnt))==NULL)
+ return GLU_OUT_OF_MEMORY;
+ if((err=explode_knot(s_knot))!=GLU_NO_ERROR)
+ {
+ free(tmp_ctrl);
+ if(s_knot->unified_knot)
+ {
+ free(s_knot->unified_knot);
+ s_knot->unified_knot=NULL;
+ }
+ return err;
+ }
+ if(s_knot->unified_knot)
+ {
+ free(s_knot->unified_knot);
+ s_knot->unified_knot=NULL;
+ }
+ if((err=calc_alphas(s_knot))!=GLU_NO_ERROR)
+ {
+ free(tmp_ctrl);
+ free(s_knot->new_knot);
+ return err;
+ }
+ free(s_knot->new_knot);
+ ctrl_offset=attrib->ctrlarray;
+ dim=attrib->dim;
+ for(i=0;i<t_cnt;i++)
+ {
+ if((err=calc_new_ctrl_pts(ctrl_offset,attrib->s_stride,s_knot,
+ dim,&(tmp_ctrl[i]),&tmp_n_control))!=GLU_NO_ERROR)
+ {
+ for(--i;i<=0;i--)
+ free(tmp_ctrl[i]);
+ free(tmp_ctrl);
+ free(s_knot->alpha);
+ return err;
+ }
+ ctrl_offset+=attrib->t_stride;
+ }
+ free(s_knot->alpha);
+ tmp_stride=dim*tmp_n_control;
+ if((*new_ctrl=(GLfloat *)malloc(sizeof(GLfloat)*tmp_stride*t_cnt))
+ ==NULL)
+ {
+ for(i=0;i<t_cnt;i++)
+ free(tmp_ctrl[i]);
+ free(tmp_ctrl);
+ return GLU_OUT_OF_MEMORY;
+ }
+ for(i=0;i<tmp_n_control;i++)
+ for(j=0;j<t_cnt;j++)
+ MEMCPY(*new_ctrl+j*dim+i*dim*t_cnt,tmp_ctrl[j]+dim*i,
+ sizeof(GLfloat)*dim);
+ for(i=0;i<t_cnt;i++)
+ free(tmp_ctrl[i]);
+ free(tmp_ctrl);
+ *s_n_ctrl=tmp_n_control;
+
+ if((tmp_ctrl=(GLfloat **)malloc(sizeof(GLfloat *)*(*s_n_ctrl)))==NULL)
+ {
+ return GLU_OUT_OF_MEMORY;
+ }
+ if((err=explode_knot(t_knot))!=GLU_NO_ERROR)
+ {
+ free(tmp_ctrl);
+ if(t_knot->unified_knot)
+ {
+ free(t_knot->unified_knot);
+ t_knot->unified_knot=NULL;
+ }
+ return err;
+ }
+ if(t_knot->unified_knot)
+ {
+ free(t_knot->unified_knot);
+ t_knot->unified_knot=NULL;
+ }
+ if((err=calc_alphas(t_knot))!=GLU_NO_ERROR)
+ {
+ free(tmp_ctrl);
+ free(t_knot->new_knot);
+ return err;
+ }
+ free(t_knot->new_knot);
+ ctrl_offset=*new_ctrl;
+ for(i=0;i<(*s_n_ctrl);i++)
+ {
+ if((err=calc_new_ctrl_pts(ctrl_offset,dim,t_knot,
+ dim,&(tmp_ctrl[i]),&tmp_n_control))!=GLU_NO_ERROR)
+ {
+ for(--i;i<=0;i--)
+ free(tmp_ctrl[i]);
+ free(tmp_ctrl);
+ free(t_knot->alpha);
+ return err;
+ }
+ ctrl_offset+=dim*t_cnt;
+ }
+ free(t_knot->alpha);
+ free(*new_ctrl);
+ tmp_stride=dim*tmp_n_control;
+ if((*new_ctrl=(GLfloat *)malloc(sizeof(GLfloat)*tmp_stride*(*s_n_ctrl)))
+ ==NULL)
+ {
+ for(i=0;i<(*s_n_ctrl);i++)
+ free(tmp_ctrl[i]);
+ free(tmp_ctrl);
+ return GLU_OUT_OF_MEMORY;
+ }
+ for(i=0;i<(*s_n_ctrl);i++)
+ {
+ MEMCPY(*new_ctrl+i*tmp_stride,tmp_ctrl[i],sizeof(GLfloat)*tmp_stride);
+ free(tmp_ctrl[i]);
+ }
+ free(tmp_ctrl);
+ *t_n_ctrl=tmp_n_control;
+ return GLU_NO_ERROR;
+}
+
+/* prepare the knot information structures */
+static GLenum
+fill_knot_structures(GLUnurbsObj *nobj,
+ knot_str_type *geom_s_knot, knot_str_type *geom_t_knot,
+ knot_str_type *color_s_knot, knot_str_type *color_t_knot,
+ knot_str_type *normal_s_knot, knot_str_type *normal_t_knot,
+ knot_str_type *texture_s_knot, knot_str_type *texture_t_knot)
+{
+ GLint order;
+ GLfloat *knot;
+ GLint nknots;
+ GLint t_min,t_max;
+
+ geom_s_knot->unified_knot=NULL;
+ knot=geom_s_knot->knot=nobj->surface.geom.sknot;
+ nknots=geom_s_knot->nknots=nobj->surface.geom.sknot_count;
+ order=geom_s_knot->order=nobj->surface.geom.sorder;
+ geom_s_knot->delta_nknots=0;
+ t_min=geom_s_knot->t_min=order-1;
+ t_max=geom_s_knot->t_max=nknots-order;
+ if(fabs(knot[t_min]-knot[t_max])<EPSILON)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR3);
+ return GLU_ERROR;
+ }
+ if(fabs(knot[0]-knot[t_min])<EPSILON)
+ {
+ /* knot open at beggining */
+ geom_s_knot->open_at_begin=GL_TRUE;
+ }
+ else
+ geom_s_knot->open_at_begin=GL_FALSE;
+ if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
+ {
+ /* knot open at end */
+ geom_s_knot->open_at_end=GL_TRUE;
+ }
+ else
+ geom_s_knot->open_at_end=GL_FALSE;
+ geom_t_knot->unified_knot=NULL;
+ knot=geom_t_knot->knot=nobj->surface.geom.tknot;
+ nknots=geom_t_knot->nknots=nobj->surface.geom.tknot_count;
+ order=geom_t_knot->order=nobj->surface.geom.torder;
+ geom_t_knot->delta_nknots=0;
+ t_min=geom_t_knot->t_min=order-1;
+ t_max=geom_t_knot->t_max=nknots-order;
+ if(fabs(knot[t_min]-knot[t_max])<EPSILON)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR3);
+ return GLU_ERROR;
+ }
+ if(fabs(knot[0]-knot[t_min])<EPSILON)
+ {
+ /* knot open at beggining */
+ geom_t_knot->open_at_begin=GL_TRUE;
+ }
+ else
+ geom_t_knot->open_at_begin=GL_FALSE;
+ if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
+ {
+ /* knot open at end */
+ geom_t_knot->open_at_end=GL_TRUE;
+ }
+ else
+ geom_t_knot->open_at_end=GL_FALSE;
+
+ if(nobj->surface.color.type!=GLU_INVALID_ENUM)
+ {
+ color_s_knot->unified_knot=(GLfloat *)1;
+ knot=color_s_knot->knot=nobj->surface.color.sknot;
+ nknots=color_s_knot->nknots=nobj->surface.color.sknot_count;
+ order=color_s_knot->order=nobj->surface.color.sorder;
+ color_s_knot->delta_nknots=0;
+ t_min=color_s_knot->t_min=order-1;
+ t_max=color_s_knot->t_max=nknots-order;
+ if(fabs(knot[t_min]-knot[t_max])<EPSILON)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR3);
+ return GLU_ERROR;
+ }
+ if(fabs(knot[0]-knot[t_min])<EPSILON)
+ {
+ /* knot open at beggining */
+ color_s_knot->open_at_begin=GL_TRUE;
+ }
+ else
+ color_s_knot->open_at_begin=GL_FALSE;
+ if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
+ {
+ /* knot open at end */
+ color_s_knot->open_at_end=GL_TRUE;
+ }
+ else
+ color_s_knot->open_at_end=GL_FALSE;
+ color_t_knot->unified_knot=(GLfloat *)1;
+ knot=color_t_knot->knot=nobj->surface.color.tknot;
+ nknots=color_t_knot->nknots=nobj->surface.color.tknot_count;
+ order=color_t_knot->order=nobj->surface.color.torder;
+ color_t_knot->delta_nknots=0;
+ t_min=color_t_knot->t_min=order-1;
+ t_max=color_t_knot->t_max=nknots-order;
+ if(fabs(knot[t_min]-knot[t_max])<EPSILON)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR3);
+ return GLU_ERROR;
+ }
+ if(fabs(knot[0]-knot[t_min])<EPSILON)
+ {
+ /* knot open at beggining */
+ color_t_knot->open_at_begin=GL_TRUE;
+ }
+ else
+ color_t_knot->open_at_begin=GL_FALSE;
+ if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
+ {
+ /* knot open at end */
+ color_t_knot->open_at_end=GL_TRUE;
+ }
+ else
+ color_t_knot->open_at_end=GL_FALSE;
+ }
+ else
+ {
+ color_s_knot->unified_knot=NULL;
+ color_t_knot->unified_knot=NULL;
+ }
+
+ if(nobj->surface.normal.type!=GLU_INVALID_ENUM)
+ {
+ normal_s_knot->unified_knot=(GLfloat *)1;
+ knot=normal_s_knot->knot=nobj->surface.normal.sknot;
+ nknots=normal_s_knot->nknots=nobj->surface.normal.sknot_count;
+ order=normal_s_knot->order=nobj->surface.normal.sorder;
+ normal_s_knot->delta_nknots=0;
+ t_min=normal_s_knot->t_min=order-1;
+ t_max=normal_s_knot->t_max=nknots-order;
+ if(fabs(knot[t_min]-knot[t_max])<EPSILON)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR3);
+ return GLU_ERROR;
+ }
+ if(fabs(knot[0]-knot[t_min])<EPSILON)
+ {
+ /* knot open at beggining */
+ normal_s_knot->open_at_begin=GL_TRUE;
+ }
+ else
+ normal_s_knot->open_at_begin=GL_FALSE;
+ if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
+ {
+ /* knot open at end */
+ normal_s_knot->open_at_end=GL_TRUE;
+ }
+ else
+ normal_s_knot->open_at_end=GL_FALSE;
+ normal_t_knot->unified_knot=(GLfloat *)1;
+ knot=normal_t_knot->knot=nobj->surface.normal.tknot;
+ nknots=normal_t_knot->nknots=nobj->surface.normal.tknot_count;
+ order=normal_t_knot->order=nobj->surface.normal.torder;
+ normal_t_knot->delta_nknots=0;
+ t_min=normal_t_knot->t_min=order-1;
+ t_max=normal_t_knot->t_max=nknots-order;
+ if(fabs(knot[t_min]-knot[t_max])<EPSILON)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR3);
+ return GLU_ERROR;
+ }
+ if(fabs(knot[0]-knot[t_min])<EPSILON)
+ {
+ /* knot open at beggining */
+ normal_t_knot->open_at_begin=GL_TRUE;
+ }
+ else
+ normal_t_knot->open_at_begin=GL_FALSE;
+ if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
+ {
+ /* knot open at end */
+ normal_t_knot->open_at_end=GL_TRUE;
+ }
+ else
+ normal_t_knot->open_at_end=GL_FALSE;
+ }
+ else
+ {
+ normal_s_knot->unified_knot=NULL;
+ normal_t_knot->unified_knot=NULL;
+ }
+
+ if(nobj->surface.texture.type!=GLU_INVALID_ENUM)
+ {
+ texture_s_knot->unified_knot=(GLfloat *)1;
+ knot=texture_s_knot->knot=nobj->surface.texture.sknot;
+ nknots=texture_s_knot->nknots=nobj->surface.texture.sknot_count;
+ order=texture_s_knot->order=nobj->surface.texture.sorder;
+ texture_s_knot->delta_nknots=0;
+ t_min=texture_s_knot->t_min=order-1;
+ t_max=texture_s_knot->t_max=nknots-order;
+ if(fabs(knot[t_min]-knot[t_max])<EPSILON)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR3);
+ return GLU_ERROR;
+ }
+ if(fabs(knot[0]-knot[t_min])<EPSILON)
+ {
+ /* knot open at beggining */
+ texture_s_knot->open_at_begin=GL_TRUE;
+ }
+ else
+ texture_s_knot->open_at_begin=GL_FALSE;
+ if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
+ {
+ /* knot open at end */
+ texture_s_knot->open_at_end=GL_TRUE;
+ }
+ else
+ texture_s_knot->open_at_end=GL_FALSE;
+ texture_t_knot->unified_knot=(GLfloat *)1;
+ knot=texture_t_knot->knot=nobj->surface.texture.tknot;
+ nknots=texture_t_knot->nknots=nobj->surface.texture.tknot_count;
+ order=texture_t_knot->order=nobj->surface.texture.torder;
+ texture_t_knot->delta_nknots=0;
+ t_min=texture_t_knot->t_min=order-1;
+ t_max=texture_t_knot->t_max=nknots-order;
+ if(fabs(knot[t_min]-knot[t_max])<EPSILON)
+ {
+ call_user_error(nobj,GLU_NURBS_ERROR3);
+ return GLU_ERROR;
+ }
+ if(fabs(knot[0]-knot[t_min])<EPSILON)
+ {
+ /* knot open at beggining */
+ texture_t_knot->open_at_begin=GL_TRUE;
+ }
+ else
+ texture_t_knot->open_at_begin=GL_FALSE;
+ if(fabs(knot[t_max]-knot[nknots-1])<EPSILON)
+ {
+ /* knot open at end */
+ texture_t_knot->open_at_end=GL_TRUE;
+ }
+ else
+ texture_t_knot->open_at_end=GL_FALSE;
+ }
+ else
+ {
+ texture_s_knot->unified_knot=NULL;
+ texture_t_knot->unified_knot=NULL;
+ }
+ return GLU_NO_ERROR;
+}
+
+void
+free_new_ctrl(new_ctrl_type *p)
+{
+ if(p->geom_ctrl)
+ free(p->geom_ctrl);
+ if(p->geom_offsets)
+ free(p->geom_offsets);
+ if(p->color_ctrl)
+ {
+ free(p->color_ctrl);
+ if(p->color_offsets)
+ free(p->color_offsets);
+ }
+ if(p->normal_ctrl)
+ {
+ free(p->normal_ctrl);
+ if(p->normal_offsets)
+ free(p->normal_offsets);
+ }
+ if(p->texture_ctrl)
+ {
+ free(p->texture_ctrl);
+ if(p->texture_offsets)
+ free(p->texture_offsets);
+ }
+}
+
+/* convert surfaces - geometry and possible attribute ones into equivalent */
+/* sequence of adjacent Bezier patches */
+static GLenum
+convert_surfs(GLUnurbsObj *nobj, new_ctrl_type *new_ctrl)
+{
+ knot_str_type geom_s_knot,color_s_knot,normal_s_knot,texture_s_knot;
+ knot_str_type geom_t_knot,color_t_knot,normal_t_knot,texture_t_knot;
+ GLenum err;
+
+ if((err=fill_knot_structures(nobj,&geom_s_knot,&geom_t_knot,
+ &color_s_knot,&color_t_knot,&normal_s_knot,&normal_t_knot,
+ &texture_s_knot,&texture_t_knot)) !=GLU_NO_ERROR)
+ {
+ return err;
+ }
+ /* unify knots - all knots should have the same working range */
+ if((err=select_knot_working_range(nobj,&geom_s_knot,&color_s_knot,
+ &normal_s_knot,&texture_s_knot)) !=GLU_NO_ERROR)
+ {
+ call_user_error(nobj,err);
+ return err;
+ }
+ if((err=select_knot_working_range(nobj,&geom_t_knot,&color_t_knot,
+ &normal_t_knot,&texture_t_knot)) !=GLU_NO_ERROR)
+ {
+ free_unified_knots(&geom_s_knot,&color_s_knot,&normal_s_knot,
+ &texture_s_knot);
+ call_user_error(nobj,err);
+ return err;
+ }
+
+ /* convert the geometry surface */
+ nobj->surface.geom.dim=get_surface_dim(nobj->surface.geom.type);
+ if((err=convert_surf(&geom_s_knot,&geom_t_knot,&(nobj->surface.geom),
+ &(new_ctrl->geom_ctrl),&(new_ctrl->geom_s_pt_cnt),
+ &(new_ctrl->geom_t_pt_cnt)))!=GLU_NO_ERROR)
+ {
+ free_unified_knots(&geom_s_knot,&color_s_knot,&normal_s_knot,
+ &texture_s_knot);
+ free_unified_knots(&geom_t_knot,&color_t_knot,&normal_t_knot,
+ &texture_t_knot);
+ call_user_error(nobj,err);
+ return err;
+ }
+ /* if additional attributive surfaces are given convert them as well */
+ if(color_s_knot.unified_knot)
+ {
+ nobj->surface.color.dim=get_surface_dim(nobj->surface.color.type);
+ if((err=convert_surf(&color_s_knot,&color_t_knot,&(nobj->surface.color),
+ &(new_ctrl->color_ctrl),&(new_ctrl->color_s_pt_cnt),
+ &(new_ctrl->color_t_pt_cnt)))!=GLU_NO_ERROR)
+ {
+ free_unified_knots(&color_s_knot,&color_s_knot,&normal_s_knot,
+ &texture_s_knot);
+ free_unified_knots(&color_t_knot,&color_t_knot,&normal_t_knot,
+ &texture_t_knot);
+ free_new_ctrl(new_ctrl);
+ call_user_error(nobj,err);
+ return err;
+ }
+ }
+ if(normal_s_knot.unified_knot)
+ {
+ nobj->surface.normal.dim=get_surface_dim(nobj->surface.normal.type);
+ if((err=convert_surf(&normal_s_knot,&normal_t_knot,
+ &(nobj->surface.normal),
+ &(new_ctrl->normal_ctrl),&(new_ctrl->normal_s_pt_cnt),
+ &(new_ctrl->normal_t_pt_cnt)))!=GLU_NO_ERROR)
+ {
+ free_unified_knots(&normal_s_knot,&normal_s_knot,&normal_s_knot,
+ &texture_s_knot);
+ free_unified_knots(&normal_t_knot,&normal_t_knot,&normal_t_knot,
+ &texture_t_knot);
+ free_new_ctrl(new_ctrl);
+ call_user_error(nobj,err);
+ return err;
+ }
+ }
+ if(texture_s_knot.unified_knot)
+ {
+ nobj->surface.texture.dim=get_surface_dim(nobj->surface.texture.type);
+ if((err=convert_surf(&texture_s_knot,&texture_t_knot,
+ &(nobj->surface.texture),
+ &(new_ctrl->texture_ctrl),&(new_ctrl->texture_s_pt_cnt),
+ &(new_ctrl->texture_t_pt_cnt)))!=GLU_NO_ERROR)
+ {
+ free_unified_knots(&texture_s_knot,&texture_s_knot,&texture_s_knot,
+ &texture_s_knot);
+ free_unified_knots(&texture_t_knot,&texture_t_knot,&texture_t_knot,
+ &texture_t_knot);
+ free_new_ctrl(new_ctrl);
+ call_user_error(nobj,err);
+ return err;
+ }
+ }
+ return GLU_NO_ERROR;
+}
+
+/* tesselate the "boundary" Bezier edge strips */
+void
+tesselate_strip_t_line(GLint top_start,GLint top_end,GLint top_z,
+ GLint bottom_start,GLint bottom_end,GLint bottom_z,GLint bottom_domain)
+{
+ GLint top_cnt,bottom_cnt,tri_cnt,k;
+ GLint direction;
+
+ top_cnt=top_end-top_start;
+ direction= (top_cnt>=0 ? 1: -1);
+ bottom_cnt=bottom_end-bottom_start;
+ glBegin(GL_LINES);
+ while(top_cnt)
+ {
+ if(bottom_cnt)
+ tri_cnt=top_cnt/bottom_cnt;
+ else
+ tri_cnt=abs(top_cnt);
+ for(k=0;k<=tri_cnt;k++ , top_start+=direction)
+ {
+ glEvalCoord2f((GLfloat)bottom_z/bottom_domain,
+ (GLfloat)bottom_start/bottom_domain);
+ glEvalPoint2(top_z,top_start);
+ }
+ if(bottom_cnt)
+ {
+ glEvalCoord2f((GLfloat)bottom_z/bottom_domain,
+ (GLfloat)bottom_start/bottom_domain);
+ bottom_start+=direction;
+ top_start-=direction;
+ glEvalCoord2f((GLfloat)bottom_z/bottom_domain,
+ (GLfloat)bottom_start/bottom_domain);
+ glEvalCoord2f((GLfloat)bottom_z/bottom_domain,
+ (GLfloat)bottom_start/bottom_domain);
+ glEvalPoint2(top_z,top_start);
+ }
+ top_cnt-=direction*tri_cnt;
+ bottom_cnt-=direction;
+ }
+ glEnd();
+}
+
+void
+tesselate_strip_t_fill(GLint top_start,GLint top_end,GLint top_z,
+ GLint bottom_start,GLint bottom_end,GLint bottom_z,GLint bottom_domain)
+{
+ GLint top_cnt,bottom_cnt,tri_cnt,k;
+ GLint direction;
+
+ top_cnt=top_end-top_start;
+ direction= (top_cnt>=0 ? 1: -1);
+ bottom_cnt=bottom_end-bottom_start;
+ while(top_cnt)
+ {
+ if(bottom_cnt)
+ tri_cnt=top_cnt/bottom_cnt;
+ else
+ tri_cnt=abs(top_cnt);
+ glBegin(GL_TRIANGLE_FAN);
+ glEvalCoord2f((GLfloat)bottom_z/bottom_domain,
+ (GLfloat)bottom_start/bottom_domain);
+ for(k=0;k<=tri_cnt;k++ , top_start+=direction)
+ glEvalPoint2(top_z,top_start);
+ if(bottom_cnt)
+ {
+ bottom_start+=direction;
+ top_start-=direction;
+ glEvalCoord2f((GLfloat)bottom_z/bottom_domain,
+ (GLfloat)bottom_start/bottom_domain);
+ }
+ glEnd();
+ top_cnt-=direction*tri_cnt;
+ bottom_cnt-=direction;
+ }
+}
+
+void
+tesselate_strip_t(GLenum display_mode, GLint top_start, GLint top_end,
+ GLint top_z, GLint bottom_start, GLint bottom_end, GLint bottom_z,
+ GLint bottom_domain)
+{
+ if(display_mode==GL_FILL)
+ tesselate_strip_t_fill(top_start,top_end,top_z,bottom_start,
+ bottom_end,bottom_z,bottom_domain);
+ else
+ tesselate_strip_t_line(top_start,top_end,top_z,bottom_start,
+ bottom_end,bottom_z,bottom_domain);
+}
+
+
+void
+tesselate_strip_s_fill(GLint top_start, GLint top_end, GLint top_z,
+ GLint bottom_start, GLint bottom_end, GLint bottom_z, GLfloat bottom_domain)
+{
+ GLint top_cnt,bottom_cnt,tri_cnt,k;
+ GLint direction;
+
+ top_cnt=top_end-top_start;
+ direction= (top_cnt>=0 ? 1: -1);
+ bottom_cnt=bottom_end-bottom_start;
+ while(top_cnt)
+ {
+ if(bottom_cnt)
+ tri_cnt=top_cnt/bottom_cnt;
+ else
+ tri_cnt=abs(top_cnt);
+ glBegin(GL_TRIANGLE_FAN);
+ glEvalCoord2f((GLfloat)bottom_start/bottom_domain,
+ (GLfloat)bottom_z/bottom_domain);
+ for(k=0;k<=tri_cnt;k++ , top_start+=direction)
+ glEvalPoint2(top_start,top_z);
+ if(bottom_cnt)
+ {
+ bottom_start+=direction;
+ top_start-=direction;
+ glEvalCoord2f((GLfloat)bottom_start/bottom_domain,
+ (GLfloat)bottom_z/bottom_domain);
+ }
+ glEnd();
+ top_cnt-=direction*tri_cnt;
+ bottom_cnt-=direction;
+ }
+}
+
+void
+tesselate_strip_s_line(GLint top_start, GLint top_end, GLint top_z,
+ GLint bottom_start, GLint bottom_end, GLint bottom_z, GLfloat bottom_domain)
+{
+ GLint top_cnt,bottom_cnt,tri_cnt,k;
+ GLint direction;
+
+ top_cnt=top_end-top_start;
+ direction= (top_cnt>=0 ? 1: -1);
+ bottom_cnt=bottom_end-bottom_start;
+ glBegin(GL_LINES);
+ while(top_cnt)
+ {
+ if(bottom_cnt)
+ tri_cnt=top_cnt/bottom_cnt;
+ else
+ tri_cnt=abs(top_cnt);
+ for(k=0;k<=tri_cnt;k++ , top_start+=direction)
+ {
+ glEvalCoord2f((GLfloat)bottom_start/bottom_domain,
+ (GLfloat)bottom_z/bottom_domain);
+ glEvalPoint2(top_start,top_z);
+ }
+ if(bottom_cnt)
+ {
+ glEvalCoord2f((GLfloat)bottom_start/bottom_domain,
+ (GLfloat)bottom_z/bottom_domain);
+ bottom_start+=direction;
+ top_start-=direction;
+ glEvalCoord2f((GLfloat)bottom_start/bottom_domain,
+ (GLfloat)bottom_z/bottom_domain);
+ glEvalPoint2(top_start,top_z);
+ glEvalCoord2f((GLfloat)bottom_start/bottom_domain,
+ (GLfloat)bottom_z/bottom_domain);
+ }
+ top_cnt-=direction*tri_cnt;
+ bottom_cnt-=direction;
+ }
+ glEnd();
+}
+
+void
+tesselate_strip_s(GLenum display_mode, GLint top_start, GLint top_end,
+ GLint top_z, GLint bottom_start, GLint bottom_end, GLint bottom_z,
+ GLfloat bottom_domain)
+{
+ if(display_mode==GL_FILL)
+ tesselate_strip_s_fill(top_start,top_end,top_z,bottom_start,
+ bottom_end,bottom_z,bottom_domain);
+ else
+ tesselate_strip_s_line(top_start,top_end,top_z,bottom_start,
+ bottom_end,bottom_z,bottom_domain);
+}
+
+void
+tesselate_bottom_left_corner(GLenum display_mode, GLfloat s_1, GLfloat t_1)
+{
+ if(display_mode==GL_FILL)
+ {
+ glBegin(GL_TRIANGLE_FAN);
+ glEvalPoint2(1,1);
+ glEvalCoord2f(s_1,0.0);
+ glEvalCoord2f(0.0,0.0);
+ glEvalCoord2f(0.0,t_1);
+ }
+ else
+ {
+ glBegin(GL_LINES);
+ glEvalCoord2f(0.0,0.0);
+ glEvalCoord2f(0.0,t_1);
+ glEvalCoord2f(0.0,0.0);
+ glEvalPoint2(1,1);
+ glEvalCoord2f(0.0,0.0);
+ glEvalCoord2f(s_1,0.0);
+ }
+ glEnd();
+}
+
+void
+tesselate_bottom_right_corner(GLenum display_mode, GLint v_top,GLint v_bottom,
+ GLfloat s_1, GLfloat t_1)
+{
+ if(display_mode==GL_FILL)
+ {
+ glBegin(GL_TRIANGLE_FAN);
+ glEvalPoint2(1,v_top);
+ glEvalCoord2f(0.0,v_bottom*t_1);
+ glEvalCoord2f(0.0,(v_bottom+1)*t_1);
+ glEvalCoord2f(s_1,(v_bottom+1)*t_1);
+ }
+ else
+ {
+ glBegin(GL_LINES);
+ glEvalCoord2f(0.0,(v_bottom+1)*t_1);
+ glEvalPoint2(1,v_top);
+ glEvalCoord2f(0.0,(v_bottom+1)*t_1);
+ glEvalCoord2f(0.0,v_bottom*t_1);
+ glEvalCoord2f(0.0,(v_bottom+1)*t_1);
+ glEvalCoord2f(s_1,(v_bottom+1)*t_1);
+ }
+ glEnd();
+}
+
+void
+tesselate_top_left_corner(GLenum display_mode, GLint u_right, GLint u_left,
+ GLfloat s_1, GLfloat t_1)
+{
+ if(display_mode==GL_FILL)
+ {
+ glBegin(GL_TRIANGLE_FAN);
+ glEvalPoint2(u_right,1);
+ glEvalCoord2f((u_left+1)*s_1,t_1);
+ glEvalCoord2f((u_left+1)*s_1,0.0);
+ glEvalCoord2f(u_left*s_1,0.0);
+ }
+ else
+ {
+ glBegin(GL_LINES);
+ glEvalCoord2f((u_left+1)*s_1,0.0);
+ glEvalPoint2(u_right,1);
+ glEvalCoord2f((u_left+1)*s_1,0.0);
+ glEvalCoord2f(u_left*s_1,0.0);
+ glEvalCoord2f((u_left+1)*s_1,0.0);
+ glEvalCoord2f((u_left+1)*s_1,t_1);
+ }
+ glEnd();
+}
+
+void
+tesselate_top_right_corner(GLenum display_mode, GLint u_left, GLint v_bottom,
+ GLint u_right, GLint v_top, GLfloat s_1, GLfloat t_1)
+{
+ if(display_mode==GL_FILL)
+ {
+ glBegin(GL_TRIANGLE_FAN);
+ glEvalPoint2(u_left,v_bottom);
+ glEvalCoord2f((u_right-1)*s_1,v_top*t_1);
+ glEvalCoord2f(u_right*s_1,v_top*t_1);
+ glEvalCoord2f(u_right*s_1,(v_top-1)*t_1);
+ }
+ else
+ {
+ glBegin(GL_LINES);
+ glEvalCoord2f(u_right*s_1,v_top*t_1);
+ glEvalPoint2(u_left,v_bottom);
+ glEvalCoord2f(u_right*s_1,v_top*t_1);
+ glEvalCoord2f(u_right*s_1,(v_top-1)*t_1);
+ glEvalCoord2f(u_right*s_1,v_top*t_1);
+ glEvalCoord2f((u_right-1)*s_1,v_top*t_1);
+ }
+ glEnd();
+}
+
+/* do mesh mapping of Bezier */
+static void
+nurbs_map_bezier(GLenum display_mode,GLint *sfactors,GLint *tfactors,
+ GLint s_bezier_cnt, GLint t_bezier_cnt, GLint s, GLint t)
+{
+ GLint top,bottom,right,left;
+
+
+ if(s==0)
+ {
+ top=*(tfactors+t*3);
+ bottom=*(tfactors+t*3+1);
+ }
+ else
+ if(s==s_bezier_cnt-1)
+ {
+ top=*(tfactors+t*3+2);
+ bottom=*(tfactors+t*3);
+ }
+ else
+ {
+ top=bottom=*(tfactors+t*3);
+ }
+ if(t==0)
+ {
+ left=*(sfactors+s*3+1);
+ right=*(sfactors+s*3);
+ }
+ else
+ if(t==t_bezier_cnt-1)
+ {
+ left=*(sfactors+s*3);
+ right=*(sfactors+s*3+2);
+ }
+ else
+ {
+ left=right=*(sfactors+s*3);
+ }
+
+ if(top>bottom)
+ {
+ if(left<right)
+ {
+ glMapGrid2f(right, 0.0, 1.0, top, 0.0, 1.0);
+ glEvalMesh2(display_mode,1,right, 1, top);
+ tesselate_strip_s(display_mode,1,right,1,1,left,0,(GLfloat)left);
+ tesselate_bottom_left_corner(display_mode,(GLfloat)(1.0/left),
+ (GLfloat)(1.0/bottom));
+/* tesselate_strip_t(display_mode,1,top,1,1,bottom,0,(GLfloat)bottom);*/
+ tesselate_strip_t(display_mode,top,1,1,bottom,1,0,(GLfloat)bottom);
+ }
+ else
+ if(left==right)
+ {
+ glMapGrid2f(right, 0.0, 1.0, top, 0.0, 1.0);
+ glEvalMesh2(display_mode,1,right, 0, top);
+/* tesselate_strip_t(display_mode,0,top,1,0,bottom,0,(GLfloat)bottom);*/
+ tesselate_strip_t(display_mode,top,0,1,bottom,0,0,(GLfloat)bottom);
+ }
+ else
+ {
+ glMapGrid2f(left, 0.0, 1.0, top, 0.0, 1.0);
+ glEvalMesh2(display_mode,1,left, 0, top-1);
+/* tesselate_strip_t(display_mode,0,top-1,1,0,bottom-1,0,
+ (GLfloat)bottom);*/
+ tesselate_strip_t(display_mode,top-1,0,1,bottom-1,0,0,
+ (GLfloat)bottom);
+ tesselate_bottom_right_corner(display_mode,top-1,bottom-1,
+ (GLfloat)(1.0/right),(GLfloat)(1.0/bottom));
+/* tesselate_strip_s(display_mode,1,left,top-1,1,right,right,
+ (GLfloat)right);*/
+ tesselate_strip_s(display_mode,left,1,top-1,right,1,right,
+ (GLfloat)right);
+ }
+ }
+ else
+ if(top==bottom)
+ {
+ if(left<right)
+ {
+ glMapGrid2f(right, 0.0, 1.0, top, 0.0, 1.0);
+ glEvalMesh2(display_mode,0,right, 1, top);
+ tesselate_strip_s(display_mode,0,right,1,0,left,0,(GLfloat)left);
+ }
+ else
+ if(left==right)
+ {
+ glMapGrid2f(right, 0.0, 1.0, top, 0.0, 1.0);
+ glEvalMesh2(display_mode,0,right, 0, top);
+ }
+ else
+ {
+ glMapGrid2f(left, 0.0, 1.0, top, 0.0, 1.0);
+ glEvalMesh2(display_mode,0,left, 0, top-1);
+/* tesselate_strip_s(display_mode,0,left,top-1,0,right,right,
+ (GLfloat)right);*/
+ tesselate_strip_s(display_mode,left,0,top-1,right,0,right,
+ (GLfloat)right);
+ }
+ }
+ else
+ {
+ if(left<right)
+ {
+ glMapGrid2f(right, 0.0, 1.0, bottom, 0.0, 1.0);
+ glEvalMesh2(display_mode,0,right-1, 1, bottom);
+ tesselate_strip_s(display_mode,0,right-1,1,0,left-1,0,
+ (GLfloat)left);
+ tesselate_top_left_corner(display_mode,right-1,left-1,
+ (GLfloat)(1.0/left),(GLfloat)(1.0/top));
+ tesselate_strip_t(display_mode,1,bottom,right-1,1,top,top,
+ (GLfloat)top);
+ }
+ else
+ if(left==right)
+ {
+ glMapGrid2f(right, 0.0, 1.0, bottom, 0.0, 1.0);
+ glEvalMesh2(display_mode,0,right-1, 0, bottom);
+ tesselate_strip_t(display_mode,0,bottom,right-1,0,top,top,
+ (GLfloat)top);
+ }
+ else
+ {
+ glMapGrid2f(left, 0.0, 1.0, bottom, 0.0, 1.0);
+ glEvalMesh2(display_mode,0,left-1, 0, bottom-1);
+ tesselate_strip_t(display_mode,0,bottom-1,left-1,0,top-1,top,
+ (GLfloat)top);
+ tesselate_top_right_corner(display_mode,left-1,bottom-1,right,top,
+ (GLfloat)(1.0/right),(GLfloat)(1.0/top));
+/* tesselate_strip_s(display_mode,0,left-1,bottom-1,0,right-1,right,
+ (GLfloat)right);*/
+ tesselate_strip_s(display_mode,left-1,0,bottom-1,right-1,0,right,
+ (GLfloat)right);
+ }
+ }
+}
+
+/* draw NURBS surface in OUTLINE POLYGON mode */
+static void
+draw_polygon_mode( GLenum display_mode, GLUnurbsObj *nobj,
+ new_ctrl_type *new_ctrl, GLint *sfactors, GLint *tfactors )
+{
+ GLsizei offset;
+ GLint t_bezier_cnt,s_bezier_cnt;
+ GLboolean do_color,do_normal,do_texture;
+ GLint i,j;
+
+ t_bezier_cnt=new_ctrl->t_bezier_cnt;
+ s_bezier_cnt=new_ctrl->s_bezier_cnt;
+ glEnable(nobj->surface.geom.type);
+ if(new_ctrl->color_ctrl)
+ {
+ glEnable(nobj->surface.color.type);
+ do_color=GL_TRUE;
+ }
+ else
+ do_color=GL_FALSE;
+ if(new_ctrl->normal_ctrl)
+ {
+ glEnable(nobj->surface.normal.type);
+ do_normal=GL_TRUE;
+ }
+ else
+ do_normal=GL_FALSE;
+ if(new_ctrl->texture_ctrl)
+ {
+ glEnable(nobj->surface.texture.type);
+ do_texture=GL_TRUE;
+ }
+ else
+ do_texture=GL_FALSE;
+ for(j=0; j<s_bezier_cnt; j++)
+ {
+ for(i=0; i<t_bezier_cnt; i++)
+ {
+ offset=j*t_bezier_cnt + i;
+ if(fine_culling_test_3D(nobj,*(new_ctrl->geom_offsets + offset),
+ nobj->surface.geom.sorder,nobj->surface.geom.torder,
+ new_ctrl->geom_s_stride,new_ctrl->geom_t_stride,
+ nobj->surface.geom.dim))
+ continue;
+ glMap2f(nobj->surface.geom.type,0.0,1.0,new_ctrl->geom_s_stride,
+ nobj->surface.geom.sorder,0.0,1.0,new_ctrl->geom_t_stride,
+ nobj->surface.geom.torder,*(new_ctrl->geom_offsets + offset));
+ if(do_color)
+ {
+ glMap2f(nobj->surface.color.type,0.0,1.0,
+ new_ctrl->color_s_stride,nobj->surface.color.sorder,
+ 0.0,1.0,new_ctrl->color_t_stride,nobj->surface.color.torder,
+ *(new_ctrl->color_offsets + offset));
+ }
+ if(do_normal)
+ {
+ glMap2f(nobj->surface.normal.type,0.0,1.0,
+ new_ctrl->normal_s_stride,nobj->surface.normal.sorder,
+ 0.0,1.0,new_ctrl->normal_t_stride,
+ nobj->surface.normal.torder,
+ *(new_ctrl->normal_offsets+offset));
+ }
+ if(do_texture)
+ {
+ glMap2f(nobj->surface.texture.type,0.0,1.0,
+ new_ctrl->texture_s_stride,nobj->surface.texture.sorder,
+ 0.0,1.0,new_ctrl->texture_t_stride,
+ nobj->surface.texture.torder,
+ *(new_ctrl->texture_offsets+offset));
+ }
+/* glMapGrid2f(sfactors[j*3+0],0.0,1.0,tfactors[i*3+0],0.0,1.0);
+ glEvalMesh2(display_mode,0,sfactors[j*3+0],0,tfactors[i*3+0]);*/
+ nurbs_map_bezier(display_mode,sfactors,tfactors,s_bezier_cnt,
+ t_bezier_cnt,j,i);
+ }
+ }
+}
+
+
+
+/* draw NURBS surface in OUTLINE POLYGON mode */
+#if 0
+static void
+draw_patch_mode( GLenum display_mode, GLUnurbsObj *nobj,
+ new_ctrl_type *new_ctrl, GLint *sfactors, GLint *tfactors )
+{
+ GLsizei offset;
+ GLint t_bezier_cnt,s_bezier_cnt;
+ GLboolean do_color,do_normal,do_texture;
+ GLint i,j;
+
+ t_bezier_cnt=new_ctrl->t_bezier_cnt;
+ s_bezier_cnt=new_ctrl->s_bezier_cnt;
+ glEnable(nobj->surface.geom.type);
+ if(new_ctrl->color_ctrl)
+ {
+ glEnable(nobj->surface.color.type);
+ do_color=GL_TRUE;
+ }
+ else
+ do_color=GL_FALSE;
+ if(new_ctrl->normal_ctrl)
+ {
+ glEnable(nobj->surface.normal.type);
+ do_normal=GL_TRUE;
+ }
+ else
+ do_normal=GL_FALSE;
+ if(new_ctrl->texture_ctrl)
+ {
+ glEnable(nobj->surface.texture.type);
+ do_texture=GL_TRUE;
+ }
+ else
+ do_texture=GL_FALSE;
+ for(j=0; j<s_bezier_cnt; j++)
+ {
+ for(i=0; i<t_bezier_cnt; i++)
+ {
+ offset=j*t_bezier_cnt + i;
+ if(fine_culling_test_3D(nobj,*(new_ctrl->geom_offsets + offset),
+ nobj->surface.geom.sorder,nobj->surface.geom.torder,
+ new_ctrl->geom_s_stride,new_ctrl->geom_t_stride,
+ nobj->surface.geom.dim))
+ continue;
+ glMap2f(nobj->surface.geom.type,0.0,1.0,new_ctrl->geom_s_stride,
+ nobj->surface.geom.sorder,0.0,1.0,new_ctrl->geom_t_stride,
+ nobj->surface.geom.torder,*(new_ctrl->geom_offsets + offset));
+ if(do_color)
+ {
+ glMap2f(nobj->surface.color.type,0.0,1.0,
+ new_ctrl->color_s_stride,nobj->surface.color.sorder,
+ 0.0,1.0,new_ctrl->color_t_stride,nobj->surface.color.torder,
+ *(new_ctrl->color_offsets + offset));
+ }
+ if(do_normal)
+ {
+ glMap2f(nobj->surface.normal.type,0.0,1.0,
+ new_ctrl->normal_s_stride,nobj->surface.normal.sorder,
+ 0.0,1.0,new_ctrl->normal_t_stride,
+ nobj->surface.normal.torder,
+ *(new_ctrl->normal_offsets+offset));
+ }
+ if(do_texture)
+ {
+ glMap2f(nobj->surface.texture.type,0.0,1.0,
+ new_ctrl->texture_s_stride,nobj->surface.texture.sorder,
+ 0.0,1.0,new_ctrl->texture_t_stride,
+ nobj->surface.texture.torder,
+ *(new_ctrl->texture_offsets+offset));
+ }
+ nurbs_map_bezier(display_mode,sfactors,tfactors,s_bezier_cnt,
+ t_bezier_cnt,i,j);
+/* glMapGrid2f(sfactors[j],0.0,1.0,tfactors[i],0.0,1.0);
+ glEvalMesh2(display_mode,0,sfactors[j],0,tfactors[i]);*/
+ }
+ }
+}
+#endif
+
+
+
+void
+init_new_ctrl(new_ctrl_type *p)
+{
+ p->geom_ctrl=p->color_ctrl=p->normal_ctrl=p->texture_ctrl=NULL;
+ p->geom_offsets=p->color_offsets=p->normal_offsets=p->texture_offsets=NULL;
+ p->s_bezier_cnt=p->t_bezier_cnt=0;
+}
+
+GLenum
+augment_new_ctrl(GLUnurbsObj *nobj, new_ctrl_type *p)
+{
+ GLsizei offset_size;
+ GLint i,j;
+
+ p->s_bezier_cnt=(p->geom_s_pt_cnt)/(nobj->surface.geom.sorder);
+ p->t_bezier_cnt=(p->geom_t_pt_cnt)/(nobj->surface.geom.torder);
+ offset_size=(p->s_bezier_cnt)*(p->t_bezier_cnt);
+ p->geom_t_stride=nobj->surface.geom.dim;
+ p->geom_s_stride=(p->geom_t_pt_cnt)*(nobj->surface.geom.dim);
+ p->color_t_stride=nobj->surface.color.dim;
+ p->color_s_stride=(p->color_t_pt_cnt)*(nobj->surface.color.dim);
+ p->normal_t_stride=nobj->surface.normal.dim;
+ p->normal_s_stride=(p->normal_t_pt_cnt)*(nobj->surface.normal.dim);
+ p->texture_t_stride=nobj->surface.texture.dim;
+ p->texture_s_stride=(p->texture_t_pt_cnt)*(nobj->surface.texture.dim);
+ if((p->geom_offsets=(GLfloat **)malloc(sizeof(GLfloat *)*offset_size))==NULL)
+ {
+ call_user_error(nobj,GLU_OUT_OF_MEMORY);
+ return GLU_ERROR;
+ }
+ if(p->color_ctrl)
+ if((p->color_offsets=(GLfloat **)malloc(sizeof(GLfloat *)*offset_size))==NULL)
+ {
+ free_new_ctrl(p);
+ call_user_error(nobj,GLU_OUT_OF_MEMORY);
+ return GLU_ERROR;
+ }
+ if(p->normal_ctrl)
+ if((p->normal_offsets=(GLfloat **)malloc(sizeof(GLfloat *)*offset_size))==NULL)
+ {
+ free_new_ctrl(p);
+ call_user_error(nobj,GLU_OUT_OF_MEMORY);
+ return GLU_ERROR;
+ }
+ if(p->texture_ctrl)
+ if((p->texture_offsets=(GLfloat **)malloc(sizeof(GLfloat *)*offset_size))==NULL)
+ {
+ free_new_ctrl(p);
+ call_user_error(nobj,GLU_OUT_OF_MEMORY);
+ return GLU_ERROR;
+ }
+ for(i=0;i<p->s_bezier_cnt;i++)
+ for(j=0;j<p->t_bezier_cnt;j++)
+ *(p->geom_offsets + i*(p->t_bezier_cnt) + j) =
+ p->geom_ctrl + i*(nobj->surface.geom.sorder)*
+ (nobj->surface.geom.dim)*(p->geom_t_pt_cnt) +
+ j*(nobj->surface.geom.dim)*(nobj->surface.geom.torder);
+ if(p->color_ctrl)
+ for(i=0;i<p->s_bezier_cnt;i++)
+ for(j=0;j<p->t_bezier_cnt;j++)
+ *(p->color_offsets + i*(p->t_bezier_cnt) + j) =
+ p->color_ctrl + i*(nobj->surface.color.sorder)*
+ (nobj->surface.color.dim)*(p->color_t_pt_cnt) +
+ j*(nobj->surface.color.dim)*(nobj->surface.color.torder);
+ if(p->normal_ctrl)
+ for(i=0;i<p->s_bezier_cnt;i++)
+ for(j=0;j<p->t_bezier_cnt;j++)
+ *(p->normal_offsets + i*(p->t_bezier_cnt) + j) =
+ p->normal_ctrl + i*(nobj->surface.normal.sorder)*
+ (nobj->surface.normal.dim)*(p->normal_t_pt_cnt) +
+ j*(nobj->surface.normal.dim)*(nobj->surface.normal.torder);
+ if(p->texture_ctrl)
+ for(i=0;i<p->s_bezier_cnt;i++)
+ for(j=0;j<p->t_bezier_cnt;j++)
+ *(p->texture_offsets + i*(p->t_bezier_cnt) + j) =
+ p->texture_ctrl + i*(nobj->surface.texture.sorder)*
+ (nobj->surface.texture.dim)*(p->texture_t_pt_cnt) +
+ j*(nobj->surface.texture.dim)*(nobj->surface.texture.torder);
+ return GLU_NO_ERROR;
+}
+
+/* main NURBS surface procedure */
+void
+do_nurbs_surface( GLUnurbsObj *nobj )
+{
+ GLint *sfactors,*tfactors;
+ new_ctrl_type new_ctrl;
+
+ /* test user supplied data */
+ if(test_nurbs_surfaces(nobj)!=GLU_NO_ERROR)
+ return;
+
+ init_new_ctrl(&new_ctrl);
+
+ if(convert_surfs(nobj,&new_ctrl)!=GLU_NO_ERROR)
+ return;
+ if(augment_new_ctrl(nobj,&new_ctrl)!=GLU_NO_ERROR)
+ return;
+ switch(nobj->sampling_method)
+ {
+ case GLU_PATH_LENGTH:
+ if(glu_do_sampling_3D(nobj,&new_ctrl,&sfactors,&tfactors)!=
+ GLU_NO_ERROR)
+ {
+ free_new_ctrl(&new_ctrl);
+ return;
+ }
+ break;
+ case GLU_DOMAIN_DISTANCE:
+ if(glu_do_sampling_uv(nobj,&new_ctrl,&sfactors,&tfactors)!=
+ GLU_NO_ERROR)
+ {
+ free_new_ctrl(&new_ctrl);
+ return;
+ }
+ break;
+ case GLU_PARAMETRIC_ERROR:
+ if(glu_do_sampling_param_3D(nobj,&new_ctrl,&sfactors,&tfactors)!=
+ GLU_NO_ERROR)
+ {
+ free_new_ctrl(&new_ctrl);
+ return;
+ }
+ break;
+ default:
+ abort();
+ }
+ glFrontFace(GL_CW);
+ switch(nobj->display_mode)
+ {
+ case GLU_FILL:
+/* if(polygon_trimming(nobj,&new_ctrl,sfactors,tfactors)==GLU_NO_ERROR)*/
+ draw_polygon_mode(GL_FILL,nobj,&new_ctrl,sfactors,tfactors);
+ break;
+ case GLU_OUTLINE_POLYGON:
+ /* TODO - missing trimming handeling */
+/* just for now - no OUTLINE_PATCH mode
+ draw_patch_mode(GL_LINE,nobj,&new_ctrl,sfactors,tfactors);
+ break; */
+ case GLU_OUTLINE_PATCH:
+/* if(polygon_trimming(nobj,&new_ctrl,sfactors,tfactors)==GLU_NO_ERROR)*/
+ draw_polygon_mode(GL_LINE,nobj,&new_ctrl,sfactors,tfactors);
+ break;
+ default:
+ abort(); /* TODO: is this OK? */
+ }
+ free(sfactors);
+ free(tfactors);
+ free_new_ctrl(&new_ctrl);
+}
+
diff --git a/src/glu/mesa/nurbsutl.c b/src/glu/mesa/nurbsutl.c
new file mode 100644
index 0000000000..f0f166cb64
--- /dev/null
+++ b/src/glu/mesa/nurbsutl.c
@@ -0,0 +1,1403 @@
+/* $Id: nurbsutl.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 2.4
+ * Copyright (C) 1995-1997 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.
+ */
+
+
+/*
+ * $Log: nurbsutl.c,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 1.8 1999/06/08 00:44:51 brianp
+ * OpenStep updates (pete@ohm.york.ac.uk)
+ *
+ * Revision 1.7 1998/07/26 02:07:59 brianp
+ * updated for Windows compilation per Ted Jump
+ *
+ * Revision 1.6 1997/10/29 02:02:20 brianp
+ * various MS Windows compiler changes (David Bucciarelli, v20 3dfx driver)
+ *
+ * Revision 1.5 1997/07/24 01:28:44 brianp
+ * changed precompiled header symbol from PCH to PC_HEADER
+ *
+ * Revision 1.4 1997/05/28 02:29:38 brianp
+ * added support for precompiled headers (PCH), inserted APIENTRY keyword
+ *
+ * Revision 1.3 1997/05/27 03:19:54 brianp
+ * minor clean-up
+ *
+ * Revision 1.2 1997/05/27 03:00:16 brianp
+ * incorporated Bogdan's new NURBS code
+ *
+ * Revision 1.1 1996/09/27 01:19:39 brianp
+ * Initial revision
+ *
+ */
+
+
+/*
+ * 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
+
+
+GLenum
+test_knot(GLint nknots, GLfloat *knot, GLint order)
+{
+ GLsizei i;
+ GLint knot_mult;
+ GLfloat tmp_knot;
+
+ tmp_knot=knot[0];
+ knot_mult=1;
+ for(i=1;i<nknots;i++)
+ {
+ if(knot[i] < tmp_knot)
+ return GLU_NURBS_ERROR4;
+ if(fabs(tmp_knot-knot[i]) > EPSILON)
+ {
+ if(knot_mult>order)
+ return GLU_NURBS_ERROR5;
+ knot_mult=1;
+ tmp_knot=knot[i];
+ }
+ else
+ ++knot_mult;
+ }
+ return GLU_NO_ERROR;
+}
+
+static int
+/* qsort function */
+#if defined(WIN32) && !defined(OPENSTEP)
+__cdecl
+#endif
+knot_sort(const void *a, const void *b)
+{
+ GLfloat x,y;
+
+ x=*((GLfloat *)a);
+ y=*((GLfloat *)b);
+ if(fabs(x-y) < EPSILON)
+ return 0;
+ if(x > y)
+ return 1;
+ return -1;
+}
+
+/* insert into dest knot all values within the valid range from src knot */
+/* that do not appear in dest */
+void
+collect_unified_knot(knot_str_type *dest, knot_str_type *src,
+ GLfloat maximal_min_knot, GLfloat minimal_max_knot)
+{
+ GLfloat *src_knot,*dest_knot;
+ GLint src_t_min,src_t_max,dest_t_min,dest_t_max;
+ GLint src_nknots,dest_nknots;
+ GLint i,j,k,new_cnt;
+ GLboolean not_found_flag;
+
+ src_knot=src->unified_knot;
+ dest_knot=dest->unified_knot;
+ src_t_min=src->t_min;
+ src_t_max=src->t_max;
+ dest_t_min=dest->t_min;
+ dest_t_max=dest->t_max;
+ src_nknots=src->unified_nknots;
+ dest_nknots=dest->unified_nknots;
+
+ k=new_cnt=dest_nknots;
+ for(i=src_t_min;i<=src_t_max;i++)
+ if(src_knot[i] - maximal_min_knot > -EPSILON &&
+ src_knot[i] - minimal_max_knot < EPSILON)
+ {
+ not_found_flag=GL_TRUE;
+ for(j=dest_t_min;j<=dest_t_max;j++)
+ if(fabs(dest_knot[j]-src_knot[i]) < EPSILON)
+ {
+ not_found_flag=GL_FALSE;
+ break;
+ }
+ if(not_found_flag)
+ {
+ /* knot from src is not in dest - add this knot to dest */
+ dest_knot[k++]=src_knot[i];
+ ++new_cnt;
+ ++(dest->t_max); /* the valid range widens */
+ ++(dest->delta_nknots); /* increment the extra knot value counter */
+ }
+ }
+ dest->unified_nknots=new_cnt;
+ qsort((void *)dest_knot,(size_t)new_cnt,(size_t)sizeof(GLfloat),
+ &knot_sort);
+}
+
+/* basing on the new common knot range for all attributes set */
+/* t_min and t_max values for each knot - they will be used later on */
+/* by explode_knot() and calc_new_ctrl_pts */
+static void
+set_new_t_min_t_max(knot_str_type *geom_knot, knot_str_type *color_knot,
+ knot_str_type *normal_knot, knot_str_type *texture_knot,
+ GLfloat maximal_min_knot, GLfloat minimal_max_knot)
+{
+ GLuint t_min,t_max,cnt;
+
+ if(minimal_max_knot-maximal_min_knot < EPSILON)
+ {
+ /* knot common range empty */
+ geom_knot->t_min=geom_knot->t_max=0;
+ color_knot->t_min=color_knot->t_max=0;
+ normal_knot->t_min=normal_knot->t_max=0;
+ texture_knot->t_min=texture_knot->t_max=0;
+ }
+ else
+ {
+ if(geom_knot->unified_knot!=NULL)
+ {
+ cnt=geom_knot->unified_nknots;
+ for(t_min=0;t_min<cnt;t_min++)
+ if(fabs((geom_knot->unified_knot)[t_min] - maximal_min_knot) <
+ EPSILON)
+ break;
+ for(t_max=cnt-1;t_max;t_max--)
+ if(fabs((geom_knot->unified_knot)[t_max] - minimal_max_knot) <
+ EPSILON)
+ break;
+ }
+ else
+ if(geom_knot->nknots)
+ {
+ cnt=geom_knot->nknots;
+ for(t_min=0;t_min<cnt;t_min++)
+ if(fabs((geom_knot->knot)[t_min] - maximal_min_knot) < EPSILON)
+ break;
+ for(t_max=cnt-1;t_max;t_max--)
+ if(fabs((geom_knot->knot)[t_max] - minimal_max_knot) < EPSILON)
+ break;
+ }
+ geom_knot->t_min=t_min;
+ geom_knot->t_max=t_max;
+ if(color_knot->unified_knot!=NULL)
+ {
+ cnt=color_knot->unified_nknots;
+ for(t_min=0;t_min<cnt;t_min++)
+ if(fabs((color_knot->unified_knot)[t_min] - maximal_min_knot) <
+ EPSILON)
+ break;
+ for(t_max=cnt-1;t_max;t_max--)
+ if(fabs((color_knot->unified_knot)[t_max] - minimal_max_knot) <
+ EPSILON)
+ break;
+ color_knot->t_min=t_min;
+ color_knot->t_max=t_max;
+ }
+ if(normal_knot->unified_knot!=NULL)
+ {
+ cnt=normal_knot->unified_nknots;
+ for(t_min=0;t_min<cnt;t_min++)
+ if(fabs((normal_knot->unified_knot)[t_min] - maximal_min_knot) <
+ EPSILON)
+ break;
+ for(t_max=cnt-1;t_max;t_max--)
+ if(fabs((normal_knot->unified_knot)[t_max] - minimal_max_knot) <
+ EPSILON)
+ break;
+ normal_knot->t_min=t_min;
+ normal_knot->t_max=t_max;
+ }
+ if(texture_knot->unified_knot!=NULL)
+ {
+ cnt=texture_knot->unified_nknots;
+ for(t_min=0;t_min<cnt;t_min++)
+ if(fabs((texture_knot->unified_knot)[t_min] - maximal_min_knot)
+ < EPSILON)
+ break;
+ for(t_max=cnt-1;t_max;t_max--)
+ if(fabs((texture_knot->unified_knot)[t_max] - minimal_max_knot)
+ < EPSILON)
+ break;
+ texture_knot->t_min=t_min;
+ texture_knot->t_max=t_max;
+ }
+ }
+}
+
+/* modify all knot valid ranges in such a way that all have the same */
+/* range, common to all knots */
+/* do this by knot insertion */
+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)
+{
+ GLint max_nknots;
+ GLfloat maximal_min_knot,minimal_max_knot;
+ GLint i;
+
+ /* find the maximum modified knot length */
+ max_nknots=geom_knot->nknots;
+ if(color_knot->unified_knot)
+ max_nknots+=color_knot->nknots;
+ if(normal_knot->unified_knot)
+ max_nknots+=normal_knot->nknots;
+ if(texture_knot->unified_knot)
+ max_nknots+=texture_knot->nknots;
+ maximal_min_knot=(geom_knot->knot)[geom_knot->t_min];
+ minimal_max_knot=(geom_knot->knot)[geom_knot->t_max];
+ /* any attirb data ? */
+ if(max_nknots!=geom_knot->nknots)
+ {
+ /* allocate space for the unified knots */
+ if((geom_knot->unified_knot=
+ (GLfloat *)malloc(sizeof(GLfloat)*max_nknots))==NULL)
+ {
+ call_user_error(nobj,GLU_OUT_OF_MEMORY);
+ return GLU_ERROR;
+ }
+ /* copy the original knot to the unified one */
+ geom_knot->unified_nknots=geom_knot->nknots;
+ for(i=0;i<geom_knot->nknots;i++)
+ (geom_knot->unified_knot)[i]=(geom_knot->knot)[i];
+ if(color_knot->unified_knot)
+ {
+ if((color_knot->knot)[color_knot->t_min] - maximal_min_knot >
+ EPSILON)
+ maximal_min_knot=(color_knot->knot)[color_knot->t_min];
+ if(minimal_max_knot - (color_knot->knot)[color_knot->t_max] >
+ EPSILON)
+ minimal_max_knot=(color_knot->knot)[color_knot->t_max];
+ if((color_knot->unified_knot=
+ (GLfloat *)malloc(sizeof(GLfloat)*max_nknots))==NULL)
+ {
+ free(geom_knot->unified_knot);
+ call_user_error(nobj,GLU_OUT_OF_MEMORY);
+ return GLU_ERROR;
+ }
+ /* copy the original knot to the unified one */
+ color_knot->unified_nknots=color_knot->nknots;
+ for(i=0;i<color_knot->nknots;i++)
+ (color_knot->unified_knot)[i]=(color_knot->knot)[i];
+ }
+ if(normal_knot->unified_knot)
+ {
+ if((normal_knot->knot)[normal_knot->t_min] - maximal_min_knot >
+ EPSILON)
+ maximal_min_knot=(normal_knot->knot)[normal_knot->t_min];
+ if(minimal_max_knot - (normal_knot->knot)[normal_knot->t_max] >
+ EPSILON)
+ minimal_max_knot=(normal_knot->knot)[normal_knot->t_max];
+ if((normal_knot->unified_knot=
+ (GLfloat *)malloc(sizeof(GLfloat)*max_nknots))==NULL)
+ {
+ free(geom_knot->unified_knot);
+ free(color_knot->unified_knot);
+ call_user_error(nobj,GLU_OUT_OF_MEMORY);
+ return GLU_ERROR;
+ }
+ /* copy the original knot to the unified one */
+ normal_knot->unified_nknots=normal_knot->nknots;
+ for(i=0;i<normal_knot->nknots;i++)
+ (normal_knot->unified_knot)[i]=(normal_knot->knot)[i];
+ }
+ if(texture_knot->unified_knot)
+ {
+ if((texture_knot->knot)[texture_knot->t_min] - maximal_min_knot >
+ EPSILON)
+ maximal_min_knot=(texture_knot->knot)[texture_knot->t_min];
+ if(minimal_max_knot - (texture_knot->knot)[texture_knot->t_max] >
+ EPSILON)
+ minimal_max_knot=(texture_knot->knot)[texture_knot->t_max];
+ if((texture_knot->unified_knot=
+ (GLfloat *)malloc(sizeof(GLfloat)*max_nknots))==NULL)
+ {
+ free(geom_knot->unified_knot);
+ free(color_knot->unified_knot);
+ free(normal_knot->unified_knot);
+ call_user_error(nobj,GLU_OUT_OF_MEMORY);
+ return GLU_ERROR;
+ }
+ /* copy the original knot to the unified one */
+ texture_knot->unified_nknots=texture_knot->nknots;
+ for(i=0;i<texture_knot->nknots;i++)
+ (texture_knot->unified_knot)[i]=(texture_knot->knot)[i];
+ }
+ /* work on the geometry knot with all additional knot values */
+ /* appearing in attirbutive knots */
+ if(minimal_max_knot-maximal_min_knot < EPSILON)
+ {
+ /* empty working range */
+ geom_knot->unified_nknots=0;
+ color_knot->unified_nknots=0;
+ normal_knot->unified_nknots=0;
+ texture_knot->unified_nknots=0;
+ }
+ else
+ {
+ if(color_knot->unified_knot)
+ collect_unified_knot(geom_knot,color_knot,maximal_min_knot,
+ minimal_max_knot);
+ if(normal_knot->unified_knot)
+ collect_unified_knot(geom_knot,normal_knot,maximal_min_knot,
+ minimal_max_knot);
+ if(texture_knot->unified_knot)
+ collect_unified_knot(geom_knot,texture_knot,maximal_min_knot,
+ minimal_max_knot);
+ /* since we have now built the "unified" geometry knot */
+ /* add same knot values to all attributive knots */
+ if(color_knot->unified_knot)
+ collect_unified_knot(color_knot,geom_knot,maximal_min_knot,
+ minimal_max_knot);
+ if(normal_knot->unified_knot)
+ collect_unified_knot(normal_knot,geom_knot,maximal_min_knot,
+ minimal_max_knot);
+ if(texture_knot->unified_knot)
+ collect_unified_knot(texture_knot,geom_knot,maximal_min_knot,
+ minimal_max_knot);
+ }
+ }
+ set_new_t_min_t_max(geom_knot,color_knot,normal_knot,texture_knot,
+ maximal_min_knot,minimal_max_knot);
+ return GLU_NO_ERROR;
+}
+
+void
+free_unified_knots(knot_str_type *geom_knot, knot_str_type *color_knot,
+ knot_str_type *normal_knot, knot_str_type *texture_knot)
+{
+ if(geom_knot->unified_knot)
+ free(geom_knot->unified_knot);
+ if(color_knot->unified_knot)
+ free(color_knot->unified_knot);
+ if(normal_knot->unified_knot)
+ free(normal_knot->unified_knot);
+ if(texture_knot->unified_knot)
+ free(texture_knot->unified_knot);
+}
+
+GLenum
+explode_knot(knot_str_type *the_knot)
+{
+ GLfloat *knot,*new_knot;
+ GLint nknots,n_new_knots=0;
+ GLint t_min,t_max;
+ GLint ord;
+ GLsizei i,j,k;
+ GLfloat tmp_float;
+
+ if(the_knot->unified_knot)
+ {
+ knot=the_knot->unified_knot;
+ nknots=the_knot->unified_nknots;
+ }
+ else
+ {
+ knot=the_knot->knot;
+ nknots=the_knot->nknots;
+ }
+ ord=the_knot->order;
+ t_min=the_knot->t_min;
+ t_max=the_knot->t_max;
+
+ for(i=t_min;i<=t_max;)
+ {
+ tmp_float=knot[i];
+ for(j=0;j<ord && (i+j)<=t_max;j++)
+ if(fabs(tmp_float-knot[i+j])>EPSILON)
+ break;
+ n_new_knots+=ord-j;
+ i+=j;
+ }
+ /* alloc space for new_knot */
+ if((new_knot=(GLfloat *)malloc(sizeof(GLfloat)*(nknots+n_new_knots)))==NULL)
+ {
+ return GLU_OUT_OF_MEMORY;
+ }
+ /* fill in new knot */
+ for(j=0;j<t_min;j++)
+ new_knot[j]=knot[j];
+ for(i=j;i<=t_max;i++)
+ {
+ tmp_float=knot[i];
+ for(k=0;k<ord;k++)
+ {
+ new_knot[j++]=knot[i];
+ if(tmp_float==knot[i+1])
+ i++;
+ }
+ }
+ for(i=t_max+1;i<(int)nknots;i++)
+ new_knot[j++]=knot[i];
+ /* fill in the knot structure */
+ the_knot->new_knot=new_knot;
+ the_knot->delta_nknots+=n_new_knots;
+ the_knot->t_max+=n_new_knots;
+ return GLU_NO_ERROR;
+}
+
+GLenum
+calc_alphas(knot_str_type *the_knot)
+{
+ GLfloat tmp_float;
+ int i,j,k,m,n;
+ int order;
+ GLfloat *alpha,*alpha_new,*tmp_alpha;
+ GLfloat denom;
+ GLfloat *knot,*new_knot;
+
+
+ knot=the_knot->knot;
+ order=the_knot->order;
+ new_knot=the_knot->new_knot;
+ n=the_knot->nknots-the_knot->order;
+ m=n+the_knot->delta_nknots;
+ if((alpha=(GLfloat *)malloc(sizeof(GLfloat)*n*m))==NULL)
+ {
+ return GLU_OUT_OF_MEMORY;
+ }
+ if((alpha_new=(GLfloat *)malloc(sizeof(GLfloat)*n*m))==NULL)
+ {
+ free(alpha);
+ return GLU_OUT_OF_MEMORY;
+ }
+ for(j=0;j<m;j++)
+ {
+ for(i=0;i<n;i++)
+ {
+ if((knot[i] <= new_knot[j]) && (new_knot[j] < knot[i+1]))
+ tmp_float=1.0;
+ else
+ tmp_float=0.0;
+ alpha[i+j*n]=tmp_float;
+ }
+ }
+ for(k=1;k<order;k++)
+ {
+ for(j=0;j<m;j++)
+ for(i=0;i<n;i++)
+ {
+ denom=knot[i+k]-knot[i];
+ if(fabs(denom)<EPSILON)
+ tmp_float=0.0;
+ else
+ tmp_float=(new_knot[j+k]-knot[i])/denom*
+ alpha[i+j*n];
+ denom=knot[i+k+1]-knot[i+1];
+ if(fabs(denom)>EPSILON)
+ tmp_float+=(knot[i+k+1]-new_knot[j+k])/denom*
+ alpha[(i+1)+j*n];
+ alpha_new[i+j*n]=tmp_float;
+ }
+ tmp_alpha=alpha_new;
+ alpha_new=alpha;
+ alpha=tmp_alpha;
+ }
+ the_knot->alpha=alpha;
+ free(alpha_new);
+ return GLU_NO_ERROR;
+}
+
+GLenum
+calc_new_ctrl_pts(GLfloat *ctrl,GLint stride,knot_str_type *the_knot,
+ GLint dim,GLfloat **new_ctrl,GLint *ncontrol)
+{
+ GLsizei i,j,k,l,m,n;
+ GLsizei index1,index2;
+ GLfloat *alpha;
+ GLfloat *new_knot;
+
+ new_knot=the_knot->new_knot;
+ n=the_knot->nknots-the_knot->order;
+ alpha=the_knot->alpha;
+
+ m=the_knot->t_max+1-the_knot->t_min-the_knot->order;
+ k=the_knot->t_min;
+ /* allocate space for new control points */
+ if((*new_ctrl=(GLfloat *)malloc(sizeof(GLfloat)*dim*m))==NULL)
+ {
+ return GLU_OUT_OF_MEMORY;
+ }
+ for(j=0;j<m;j++)
+ {
+ for(l=0;l<dim;l++)
+ (*new_ctrl)[j*dim+l]=0.0;
+ for(i=0;i<n;i++)
+ {
+ index1=i+(j+k)*n;
+ index2=i*stride;
+ for(l=0;l<dim;l++)
+ (*new_ctrl)[j*dim+l]+=alpha[index1]*ctrl[index2+l];
+ }
+ }
+ *ncontrol=(GLint)m;
+ return GLU_NO_ERROR;
+}
+
+static GLint
+calc_factor(GLfloat *pts,GLint order,GLint indx,GLint stride,GLfloat tolerance,
+ GLint dim)
+{
+ GLdouble model[16],proj[16];
+ GLint viewport[4];
+ GLdouble x,y,z,w,winx1,winy1,winz,winx2,winy2;
+ GLint i;
+ GLdouble len,dx,dy;
+
+ glGetDoublev(GL_MODELVIEW_MATRIX,model);
+ glGetDoublev(GL_PROJECTION_MATRIX,proj);
+ glGetIntegerv(GL_VIEWPORT,viewport);
+ if(dim==4)
+ {
+ w=(GLdouble)pts[indx+3];
+ x=(GLdouble)pts[indx]/w;
+ y=(GLdouble)pts[indx+1]/w;
+ z=(GLdouble)pts[indx+2]/w;
+ gluProject(x,y,z,model,proj,viewport,&winx1,&winy1,&winz);
+ len=0.0;
+ for(i=1;i<order;i++)
+ {
+ w=(GLdouble)pts[indx+i*stride+3];
+ x=(GLdouble)pts[indx+i*stride]/w;
+ y=(GLdouble)pts[indx+i*stride+1]/w;
+ z=(GLdouble)pts[indx+i*stride+2]/w;
+ if(gluProject(x,y,z,model,proj,viewport,&winx2,&winy2,&winz))
+ {
+ dx=winx2-winx1;
+ dy=winy2-winy1;
+ len+=sqrt(dx*dx+dy*dy);
+ }
+ winx1=winx2; winy1=winy2;
+ }
+ }
+ else
+ {
+ x=(GLdouble)pts[indx];
+ y=(GLdouble)pts[indx+1];
+ if(dim==2)
+ z=0.0;
+ else
+ z=(GLdouble)pts[indx+2];
+ gluProject(x,y,z,model,proj,viewport,&winx1,&winy1,&winz);
+ len=0.0;
+ for(i=1;i<order;i++)
+ {
+ x=(GLdouble)pts[indx+i*stride];
+ y=(GLdouble)pts[indx+i*stride+1];
+ if(dim==2)
+ z=0.0;
+ else
+ z=(GLdouble)pts[indx+i*stride+2];
+ if(gluProject(x,y,z,model,proj,viewport,&winx2,&winy2,&winz))
+ {
+ dx=winx2-winx1;
+ dy=winy2-winy1;
+ len+=sqrt(dx*dx+dy*dy);
+ }
+ winx1=winx2; winy1=winy2;
+ }
+ }
+ len /= tolerance;
+ return ((GLint)len+1);
+}
+
+/* we can't use the Mesa evaluators - no way to get the point coords */
+/* so we use our own Bezier point calculus routines */
+/* because I'm lazy, I reuse the ones from eval.c */
+
+static void
+bezier_curve(GLfloat *cp, GLfloat *out, GLfloat t,
+ GLuint dim, GLuint order, GLint offset)
+{
+ GLfloat s, powert;
+ GLuint i, k, bincoeff;
+
+ if(order >= 2)
+ {
+ bincoeff = order-1;
+ s = 1.0-t;
+
+ for(k=0; k<dim; k++)
+ out[k] = s*cp[k] + bincoeff*t*cp[offset+k];
+
+ for(i=2, cp+=2*offset, powert=t*t; i<order; i++, powert*=t, cp +=offset)
+ {
+ bincoeff *= order-i;
+ bincoeff /= i;
+
+ for(k=0; k<dim; k++)
+ out[k] = s*out[k] + bincoeff*powert*cp[k];
+ }
+ }
+ else /* order=1 -> constant curve */
+ {
+ for(k=0; k<dim; k++)
+ out[k] = cp[k];
+ }
+}
+
+static GLint
+calc_parametric_factor(GLfloat *pts,GLint order,GLint indx,GLint stride,
+ GLfloat tolerance,GLint dim)
+{
+ GLdouble model[16],proj[16];
+ GLint viewport[4];
+ GLdouble x,y,z,w,x1,y1,z1,x2,y2,z2,x3,y3,z3;
+ GLint i;
+ GLint P;
+ GLfloat bez_pt[4];
+ GLdouble len=0.0,tmp,z_med;
+
+ P = 2*(order+2);
+ glGetDoublev(GL_MODELVIEW_MATRIX,model);
+ glGetDoublev(GL_PROJECTION_MATRIX,proj);
+ glGetIntegerv(GL_VIEWPORT,viewport);
+ z_med = (viewport[2] + viewport[3]) * 0.5;
+ switch(dim)
+ {
+ case 4:
+ for(i=1;i<P;i++)
+ {
+ bezier_curve(pts+indx, bez_pt, (GLfloat)i/(GLfloat)P, 4,
+ order,stride);
+ w = (GLdouble)bez_pt[3];
+ x = (GLdouble)bez_pt[0] / w;
+ y = (GLdouble)bez_pt[1] / w;
+ z = (GLdouble)bez_pt[2] / w;
+ gluProject(x,y,z,model,proj,viewport,&x3,&y3,&z3);
+ z3 *= z_med;
+ bezier_curve(pts+indx, bez_pt, (GLfloat)(i-1)/(GLfloat)P, 4,
+ order,stride);
+ w = (GLdouble)bez_pt[3];
+ x = (GLdouble)bez_pt[0] / w;
+ y = (GLdouble)bez_pt[1] / w;
+ z = (GLdouble)bez_pt[2] / w;
+ gluProject(x,y,z,model,proj,viewport,&x1,&y1,&z1);
+ z1 *= z_med;
+ bezier_curve(pts+indx, bez_pt, (GLfloat)(i+1)/(GLfloat)P, 4,
+ order,stride);
+ w = (GLdouble)bez_pt[3];
+ x = (GLdouble)bez_pt[0] / w;
+ y = (GLdouble)bez_pt[1] / w;
+ z = (GLdouble)bez_pt[2] / w;
+ gluProject(x,y,z,model,proj,viewport,&x2,&y2,&z2);
+ z2 *= z_med;
+ /* calc distance between point (x3,y3,z3) and line segment */
+ /* <x1,y1,z1><x2,y2,z2> */
+ x = x2-x1;
+ y = y2-y1;
+ z = z2-z1;
+ tmp = sqrt(x*x+y*y+z*z);
+ x /= tmp;
+ y /= tmp;
+ z /= tmp;
+ tmp = x3*x+y3*y+z3*z-x1*x-y1*y-z1*z;
+ x = x1+x*tmp-x3;
+ y = y1+y*tmp-y3;
+ z = z1+z*tmp-z3;
+ tmp = sqrt(x*x+y*y+z*z);
+ if(tmp > len)
+ len = tmp;
+ }
+ break;
+ case 3:
+ for(i=1;i<P;i++)
+ {
+ bezier_curve(pts+indx, bez_pt, (GLfloat)i/(GLfloat)P, 3,
+ order,stride);
+ x = (GLdouble)bez_pt[0];
+ y = (GLdouble)bez_pt[1];
+ z = (GLdouble)bez_pt[2];
+ gluProject(x,y,z,model,proj,viewport,&x3,&y3,&z3);
+ z3 *= z_med;
+ bezier_curve(pts+indx, bez_pt, (GLfloat)(i-1)/(GLfloat)P, 3,
+ order,stride);
+ x = (GLdouble)bez_pt[0];
+ y = (GLdouble)bez_pt[1];
+ z = (GLdouble)bez_pt[2];
+ gluProject(x,y,z,model,proj,viewport,&x1,&y1,&z1);
+ z1 *= z_med;
+ bezier_curve(pts+indx, bez_pt, (GLfloat)(i+1)/(GLfloat)P, 3,
+ order,stride);
+ x = (GLdouble)bez_pt[0];
+ y = (GLdouble)bez_pt[1];
+ z = (GLdouble)bez_pt[2];
+ gluProject(x,y,z,model,proj,viewport,&x2,&y2,&z2);
+ z2 *= z_med;
+ /* calc distance between point (x3,y3,z3) and line segment */
+ /* <x1,y1,z1><x2,y2,z2> */
+ x = x2-x1;
+ y = y2-y1;
+ z = z2-z1;
+ tmp = sqrt(x*x+y*y+z*z);
+ x /= tmp;
+ y /= tmp;
+ z /= tmp;
+ tmp = x3*x+y3*y+z3*z-x1*x-y1*y-z1*z;
+ x = x1+x*tmp-x3;
+ y = y1+y*tmp-y3;
+ z = z1+z*tmp-z3;
+ tmp = sqrt(x*x+y*y+z*z);
+ if(tmp > len)
+ len = tmp;
+ }
+ break;
+ case 2:
+ for(i=1;i<P;i++)
+ {
+ bezier_curve(pts+indx, bez_pt, (GLfloat)i/(GLfloat)P, 2,
+ order,stride);
+ x = (GLdouble)bez_pt[0];
+ y = (GLdouble)bez_pt[1];
+ z = 0.0;
+ gluProject(x,y,z,model,proj,viewport,&x3,&y3,&z3);
+ z3 *= z_med;
+ bezier_curve(pts+indx, bez_pt, (GLfloat)(i-1)/(GLfloat)P, 2,
+ order,stride);
+ x = (GLdouble)bez_pt[0];
+ y = (GLdouble)bez_pt[1];
+ z = 0.0;
+ gluProject(x,y,z,model,proj,viewport,&x1,&y1,&z1);
+ z1 *= z_med;
+ bezier_curve(pts+indx, bez_pt, (GLfloat)(i+1)/(GLfloat)P, 2,
+ order,stride);
+ x = (GLdouble)bez_pt[0];
+ y = (GLdouble)bez_pt[1];
+ z = 0.0;
+ gluProject(x,y,z,model,proj,viewport,&x2,&y2,&z2);
+ z2 *= z_med;
+ /* calc distance between point (x3,y3,z3) and line segment */
+ /* <x1,y1,z1><x2,y2,z2> */
+ x = x2-x1;
+ y = y2-y1;
+ z = z2-z1;
+ tmp = sqrt(x*x+y*y+z*z);
+ x /= tmp;
+ y /= tmp;
+ z /= tmp;
+ tmp = x3*x+y3*y+z3*z-x1*x-y1*y-z1*z;
+ x = x1+x*tmp-x3;
+ y = y1+y*tmp-y3;
+ z = z1+z*tmp-z3;
+ tmp = sqrt(x*x+y*y+z*z);
+ if(tmp > len)
+ len = tmp;
+ }
+ break;
+
+ }
+ if(len < tolerance)
+ return (order);
+ else
+ return (GLint)(sqrt(len/tolerance)*(order+2)+1);
+}
+
+static GLenum
+calc_sampling_3D(new_ctrl_type *new_ctrl, GLfloat tolerance, GLint dim,
+ GLint uorder, GLint vorder, GLint **ufactors, GLint **vfactors)
+{
+ GLfloat *ctrl;
+ GLint tmp_factor1,tmp_factor2;
+ GLint ufactor_cnt,vfactor_cnt;
+ GLint offset1,offset2,offset3;
+ GLint i,j;
+
+ ufactor_cnt=new_ctrl->s_bezier_cnt;
+ vfactor_cnt=new_ctrl->t_bezier_cnt;
+ if((*ufactors=(GLint *)malloc(sizeof(GLint)*ufactor_cnt*3))
+ ==NULL)
+ {
+ return GLU_OUT_OF_MEMORY;
+ }
+ if((*vfactors=(GLint *)malloc(sizeof(GLint)*vfactor_cnt*3))
+ ==NULL)
+ {
+ free(*ufactors);
+ return GLU_OUT_OF_MEMORY;
+ }
+ ctrl=new_ctrl->geom_ctrl;
+ offset1=new_ctrl->geom_t_stride*vorder;
+ offset2=new_ctrl->geom_s_stride*uorder;
+ for(j=0;j<vfactor_cnt;j++)
+ {
+ *(*vfactors+j*3+1)=tmp_factor1=calc_factor(ctrl,vorder,
+ j*offset1,dim,tolerance,dim);
+ /* loop ufactor_cnt-1 times */
+ for(i=1;i<ufactor_cnt;i++)
+ {
+ tmp_factor2=calc_factor(ctrl,vorder,
+ j*offset1+i*offset2,dim,tolerance,dim);
+ if(tmp_factor2>tmp_factor1)
+ tmp_factor1=tmp_factor2;
+ }
+ /* last time for the opposite edge */
+ *(*vfactors+j*3+2)=tmp_factor2=calc_factor(ctrl,vorder,
+ j*offset1+i*offset2-new_ctrl->geom_s_stride,
+ dim,tolerance,dim);
+ if(tmp_factor2>tmp_factor1)
+ *(*vfactors+j*3)=tmp_factor2;
+ else
+ *(*vfactors+j*3)=tmp_factor1;
+ }
+ offset3=new_ctrl->geom_s_stride;
+ offset2=new_ctrl->geom_s_stride*uorder;
+ for(j=0;j<ufactor_cnt;j++)
+ {
+ *(*ufactors+j*3+1)=tmp_factor1=calc_factor(ctrl,uorder,
+ j*offset2,offset3,tolerance,dim);
+ /* loop vfactor_cnt-1 times */
+ for(i=1;i<vfactor_cnt;i++)
+ {
+ tmp_factor2=calc_factor(ctrl,uorder,
+ j*offset2+i*offset1,offset3,tolerance,dim);
+ if(tmp_factor2>tmp_factor1)
+ tmp_factor1=tmp_factor2;
+ }
+ /* last time for the opposite edge */
+ *(*ufactors+j*3+2)=tmp_factor2=calc_factor(ctrl,uorder,
+ j*offset2+i*offset1-new_ctrl->geom_t_stride,
+ offset3,tolerance,dim);
+ if(tmp_factor2>tmp_factor1)
+ *(*ufactors+j*3)=tmp_factor2;
+ else
+ *(*ufactors+j*3)=tmp_factor1;
+ }
+ return GL_NO_ERROR;
+}
+
+static GLenum
+calc_sampling_param_3D(new_ctrl_type *new_ctrl, GLfloat tolerance, GLint dim,
+ GLint uorder, GLint vorder, GLint **ufactors, GLint **vfactors)
+{
+ GLfloat *ctrl;
+ GLint tmp_factor1,tmp_factor2;
+ GLint ufactor_cnt,vfactor_cnt;
+ GLint offset1,offset2,offset3;
+ GLint i,j;
+
+ ufactor_cnt=new_ctrl->s_bezier_cnt;
+ vfactor_cnt=new_ctrl->t_bezier_cnt;
+ if((*ufactors=(GLint *)malloc(sizeof(GLint)*ufactor_cnt*3))
+ ==NULL)
+ {
+ return GLU_OUT_OF_MEMORY;
+ }
+ if((*vfactors=(GLint *)malloc(sizeof(GLint)*vfactor_cnt*3))
+ ==NULL)
+ {
+ free(*ufactors);
+ return GLU_OUT_OF_MEMORY;
+ }
+ ctrl=new_ctrl->geom_ctrl;
+ offset1=new_ctrl->geom_t_stride*vorder;
+ offset2=new_ctrl->geom_s_stride*uorder;
+ for(j=0;j<vfactor_cnt;j++)
+ {
+ *(*vfactors+j*3+1)=tmp_factor1=calc_parametric_factor(ctrl,vorder,
+ j*offset1,dim,tolerance,dim);
+ /* loop ufactor_cnt-1 times */
+ for(i=1;i<ufactor_cnt;i++)
+ {
+ tmp_factor2=calc_parametric_factor(ctrl,vorder,
+ j*offset1+i*offset2,dim,tolerance,dim);
+ if(tmp_factor2>tmp_factor1)
+ tmp_factor1=tmp_factor2;
+ }
+ /* last time for the opposite edge */
+ *(*vfactors+j*3+2)=tmp_factor2=calc_parametric_factor(ctrl,vorder,
+ j*offset1+i*offset2-new_ctrl->geom_s_stride,
+ dim,tolerance,dim);
+ if(tmp_factor2>tmp_factor1)
+ *(*vfactors+j*3)=tmp_factor2;
+ else
+ *(*vfactors+j*3)=tmp_factor1;
+ }
+ offset3=new_ctrl->geom_s_stride;
+ offset2=new_ctrl->geom_s_stride*uorder;
+ for(j=0;j<ufactor_cnt;j++)
+ {
+ *(*ufactors+j*3+1)=tmp_factor1=calc_parametric_factor(ctrl,uorder,
+ j*offset2,offset3,tolerance,dim);
+ /* loop vfactor_cnt-1 times */
+ for(i=1;i<vfactor_cnt;i++)
+ {
+ tmp_factor2=calc_parametric_factor(ctrl,uorder,
+ j*offset2+i*offset1,offset3,tolerance,dim);
+ if(tmp_factor2>tmp_factor1)
+ tmp_factor1=tmp_factor2;
+ }
+ /* last time for the opposite edge */
+ *(*ufactors+j*3+2)=tmp_factor2=calc_parametric_factor(ctrl,uorder,
+ j*offset2+i*offset1-new_ctrl->geom_t_stride,
+ offset3,tolerance,dim);
+ if(tmp_factor2>tmp_factor1)
+ *(*ufactors+j*3)=tmp_factor2;
+ else
+ *(*ufactors+j*3)=tmp_factor1;
+ }
+ return GL_NO_ERROR;
+}
+
+static GLenum
+calc_sampling_2D(GLfloat *ctrl, GLint cnt, GLint order,
+ GLfloat tolerance, GLint dim, GLint **factors)
+{
+ GLint factor_cnt;
+ GLint tmp_factor;
+ GLint offset;
+ GLint i;
+
+ factor_cnt=cnt/order;
+ if((*factors=(GLint *)malloc(sizeof(GLint)*factor_cnt))==NULL)
+ {
+ return GLU_OUT_OF_MEMORY;
+ }
+ offset=order*dim;
+ for(i=0;i<factor_cnt;i++)
+ {
+ tmp_factor=calc_factor(ctrl,order,i*offset,dim,tolerance,dim);
+ if(tmp_factor == 0)
+ (*factors)[i]=1;
+ else
+ (*factors)[i]=tmp_factor;
+ }
+ return GL_NO_ERROR;
+}
+
+static void
+set_sampling_and_culling( GLUnurbsObj *nobj )
+{
+ if(nobj->auto_load_matrix==GL_FALSE)
+ {
+ GLint i;
+ GLfloat m[4];
+
+ glPushAttrib( (GLbitfield) (GL_VIEWPORT_BIT | GL_TRANSFORM_BIT));
+ for(i=0;i<4;i++)
+ m[i]=nobj->sampling_matrices.viewport[i];
+ glViewport(m[0],m[1],m[2],m[3]);
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadMatrixf(nobj->sampling_matrices.proj);
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glLoadMatrixf(nobj->sampling_matrices.model);
+ }
+}
+
+static void
+revert_sampling_and_culling( GLUnurbsObj *nobj )
+{
+ if(nobj->auto_load_matrix==GL_FALSE)
+ {
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ glMatrixMode(GL_PROJECTION);
+ glPopMatrix();
+ glPopAttrib();
+ }
+}
+
+GLenum
+glu_do_sampling_3D( GLUnurbsObj *nobj, new_ctrl_type *new_ctrl,
+ GLint **sfactors, GLint **tfactors)
+{
+ GLint dim;
+ GLenum err;
+
+ *sfactors=NULL;
+ *tfactors=NULL;
+ dim=nobj->surface.geom.dim;
+ set_sampling_and_culling(nobj);
+ if((err=calc_sampling_3D(new_ctrl,nobj->sampling_tolerance,dim,
+ nobj->surface.geom.sorder,nobj->surface.geom.torder,
+ sfactors,tfactors))==GLU_ERROR)
+ {
+ revert_sampling_and_culling(nobj);
+ call_user_error(nobj,err);
+ return GLU_ERROR;
+ }
+ revert_sampling_and_culling(nobj);
+ return GLU_NO_ERROR;
+}
+
+GLenum
+glu_do_sampling_uv( GLUnurbsObj *nobj, new_ctrl_type *new_ctrl,
+ GLint **sfactors, GLint **tfactors)
+{
+ GLint s_cnt, t_cnt, i;
+ GLint u_steps, v_steps;
+
+ s_cnt = new_ctrl->s_bezier_cnt;
+ t_cnt = new_ctrl->t_bezier_cnt;
+ *sfactors=NULL;
+ *tfactors=NULL;
+ if((*sfactors=(GLint *)malloc(sizeof(GLint)*s_cnt*3))
+ ==NULL)
+ {
+ return GLU_OUT_OF_MEMORY;
+ }
+ if((*tfactors=(GLint *)malloc(sizeof(GLint)*t_cnt*3))
+ ==NULL)
+ {
+ free(*sfactors);
+ return GLU_OUT_OF_MEMORY;
+ }
+ u_steps = nobj->u_step;
+ v_steps = nobj->v_step;
+ for(i=0; i<s_cnt; i++)
+ {
+ *(*sfactors+i*3) = u_steps;
+ *(*sfactors+i*3+1) = u_steps;
+ *(*sfactors+i*3+2) = u_steps;
+ }
+ for(i=0; i<t_cnt; i++)
+ {
+ *(*tfactors+i*3) = v_steps;
+ *(*tfactors+i*3+1) = v_steps;
+ *(*tfactors+i*3+2) = v_steps;
+ }
+ return GLU_NO_ERROR;
+}
+
+GLenum
+glu_do_sampling_param_3D( GLUnurbsObj *nobj, new_ctrl_type *new_ctrl,
+ GLint **sfactors, GLint **tfactors)
+{
+ GLint dim;
+ GLenum err;
+
+ *sfactors=NULL;
+ *tfactors=NULL;
+ dim=nobj->surface.geom.dim;
+ set_sampling_and_culling(nobj);
+ if((err=calc_sampling_param_3D(new_ctrl,nobj->parametric_tolerance,dim,
+ nobj->surface.geom.sorder,nobj->surface.geom.torder,
+ sfactors,tfactors))==GLU_ERROR)
+ {
+ revert_sampling_and_culling(nobj);
+ call_user_error(nobj,err);
+ return GLU_ERROR;
+ }
+ revert_sampling_and_culling(nobj);
+ return GLU_NO_ERROR;
+}
+
+GLenum
+glu_do_sampling_2D( GLUnurbsObj *nobj, GLfloat *ctrl, GLint cnt, GLint order,
+ GLint dim, GLint **factors)
+{
+ GLenum err;
+
+ set_sampling_and_culling(nobj);
+ err=calc_sampling_2D(ctrl,cnt,order,nobj->sampling_tolerance,dim,
+ factors);
+ revert_sampling_and_culling(nobj);
+ return err;
+}
+
+
+GLenum
+glu_do_sampling_u( GLUnurbsObj *nobj, GLfloat *ctrl, GLint cnt, GLint order,
+ GLint dim, GLint **factors)
+{
+ GLint i;
+ GLint u_steps;
+
+ cnt /= order;
+ if((*factors=(GLint *)malloc(sizeof(GLint)*cnt))
+ ==NULL)
+ {
+ return GLU_OUT_OF_MEMORY;
+ }
+ u_steps = nobj->u_step;
+ for(i=0; i<cnt; i++)
+ (*factors)[i] = u_steps;
+ return GLU_NO_ERROR;
+}
+
+GLenum
+glu_do_sampling_param_2D( GLUnurbsObj *nobj, GLfloat *ctrl, GLint cnt,
+ GLint order, GLint dim, GLint **factors)
+{
+ GLint i;
+ GLint u_steps;
+ GLfloat tolerance;
+
+ set_sampling_and_culling(nobj);
+ tolerance = nobj->parametric_tolerance;
+ cnt /= order;
+ if((*factors=(GLint *)malloc(sizeof(GLint)*cnt))
+ ==NULL)
+ {
+ revert_sampling_and_culling(nobj);
+ return GLU_OUT_OF_MEMORY;
+ }
+ u_steps = nobj->u_step;
+ for(i=0; i<cnt; i++)
+ {
+ (*factors)[i] = calc_parametric_factor(ctrl,order,0,
+ dim,tolerance,dim);
+
+ }
+ revert_sampling_and_culling(nobj);
+ return GLU_NO_ERROR;
+}
+
+GLenum
+glu_do_sampling_crv( GLUnurbsObj *nobj, GLfloat *ctrl, GLint cnt, GLint order,
+ GLint dim, GLint **factors)
+{
+ GLenum err;
+
+ *factors=NULL;
+ switch(nobj->sampling_method)
+ {
+ case GLU_PATH_LENGTH:
+ if((err=glu_do_sampling_2D(nobj,ctrl,cnt,order,dim,factors))!=
+ GLU_NO_ERROR)
+ {
+ call_user_error(nobj,err);
+ return GLU_ERROR;
+ }
+ break;
+ case GLU_DOMAIN_DISTANCE:
+ if((err=glu_do_sampling_u(nobj,ctrl,cnt,order,dim,factors))!=
+ GLU_NO_ERROR)
+ {
+ call_user_error(nobj,err);
+ return GLU_ERROR;
+ }
+ break;
+ case GLU_PARAMETRIC_ERROR:
+ if((err=glu_do_sampling_param_2D(nobj,ctrl,cnt,order,dim,factors))!=
+ GLU_NO_ERROR)
+ {
+ call_user_error(nobj,err);
+ return GLU_ERROR;
+ }
+ break;
+ default:
+ abort();
+ }
+
+ return GLU_NO_ERROR;
+}
+
+/* TODO - i don't like this culling - this one just tests if at least one */
+/* ctrl point lies within the viewport . Also the point_in_viewport() */
+/* should be included in the fnctions for efficiency reasons */
+
+static GLboolean
+point_in_viewport(GLfloat *pt, GLint dim)
+{
+ GLdouble model[16],proj[16];
+ GLint viewport[4];
+ GLdouble x,y,z,w,winx,winy,winz;
+
+ glGetDoublev(GL_MODELVIEW_MATRIX,model);
+ glGetDoublev(GL_PROJECTION_MATRIX,proj);
+ glGetIntegerv(GL_VIEWPORT,viewport);
+ if(dim==3)
+ {
+ x=(GLdouble)pt[0];
+ y=(GLdouble)pt[1];
+ z=(GLdouble)pt[2];
+ gluProject(x,y,z,model,proj,viewport,&winx,&winy,&winz);
+ }
+ else
+ {
+ w=(GLdouble)pt[3];
+ x=(GLdouble)pt[0]/w;
+ y=(GLdouble)pt[1]/w;
+ z=(GLdouble)pt[2]/w;
+ gluProject(x,y,z,model,proj,viewport,&winx,&winy,&winz);
+ }
+ if((GLint)winx >= viewport[0] && (GLint)winx < viewport[2] &&
+ (GLint)winy >= viewport[1] && (GLint)winy < viewport[3])
+ return GL_TRUE;
+ return GL_FALSE;
+}
+
+GLboolean
+fine_culling_test_3D(GLUnurbsObj *nobj,GLfloat *pts,GLint s_cnt,GLint t_cnt,
+ GLint s_stride,GLint t_stride, GLint dim)
+{
+ GLint i,j;
+
+ if(nobj->culling==GL_FALSE)
+ return GL_FALSE;
+ set_sampling_and_culling(nobj);
+
+ if(dim==3)
+ {
+ for(i=0;i<s_cnt;i++)
+ for(j=0;j<t_cnt;j++)
+ if(point_in_viewport(pts+i*s_stride+j*t_stride,dim))
+ {
+ revert_sampling_and_culling(nobj);
+ return GL_FALSE;
+ }
+ }
+ else
+ {
+ for(i=0;i<s_cnt;i++)
+ for(j=0;j<t_cnt;j++)
+ if(point_in_viewport(pts+i*s_stride+j*t_stride,dim))
+ {
+ revert_sampling_and_culling(nobj);
+ return GL_FALSE;
+ }
+ }
+ revert_sampling_and_culling(nobj);
+ return GL_TRUE;
+}
+
+/*GLboolean
+fine_culling_test_3D(GLUnurbsObj *nobj,GLfloat *pts,GLint s_cnt,GLint t_cnt,
+ GLint s_stride,GLint t_stride, GLint dim)
+{
+ GLint visible_cnt;
+ GLfloat feedback_buffer[5];
+ GLsizei buffer_size;
+ GLint i,j;
+
+ if(nobj->culling==GL_FALSE)
+ return GL_FALSE;
+ buffer_size=5;
+ set_sampling_and_culling(nobj);
+
+ glFeedbackBuffer(buffer_size,GL_2D,feedback_buffer);
+ glRenderMode(GL_FEEDBACK);
+ if(dim==3)
+ {
+ for(i=0;i<s_cnt;i++)
+ {
+ glBegin(GL_LINE_LOOP);
+ for(j=0;j<t_cnt;j++)
+ glVertex3fv(pts+i*s_stride+j*t_stride);
+ glEnd();
+ }
+ for(j=0;j<t_cnt;j++)
+ {
+ glBegin(GL_LINE_LOOP);
+ for(i=0;i<s_cnt;i++)
+ glVertex3fv(pts+i*s_stride+j*t_stride);
+ glEnd();
+ }
+ }
+ else
+ {
+ for(i=0;i<s_cnt;i++)
+ {
+ glBegin(GL_LINE_LOOP);
+ for(j=0;j<t_cnt;j++)
+ glVertex4fv(pts+i*s_stride+j*t_stride);
+ glEnd();
+ }
+ for(j=0;j<t_cnt;j++)
+ {
+ glBegin(GL_LINE_LOOP);
+ for(i=0;i<s_cnt;i++)
+ glVertex4fv(pts+i*s_stride+j*t_stride);
+ glEnd();
+ }
+ }
+ visible_cnt=glRenderMode(GL_RENDER);
+
+ revert_sampling_and_culling(nobj);
+ return (GLboolean)(visible_cnt==0);
+}*/
+
+GLboolean
+fine_culling_test_2D(GLUnurbsObj *nobj,GLfloat *pts,GLint cnt,
+ GLint stride, GLint dim)
+{
+ GLint i;
+
+ if(nobj->culling==GL_FALSE)
+ return GL_FALSE;
+ set_sampling_and_culling(nobj);
+
+ if(dim==3)
+ {
+ for(i=0;i<cnt;i++)
+ if(point_in_viewport(pts+i*stride,dim))
+ {
+ revert_sampling_and_culling(nobj);
+ return GL_FALSE;
+ }
+ }
+ else
+ {
+ for(i=0;i<cnt;i++)
+ if(point_in_viewport(pts+i*stride,dim))
+ {
+ revert_sampling_and_culling(nobj);
+ return GL_FALSE;
+ }
+ }
+ revert_sampling_and_culling(nobj);
+ return GL_TRUE;
+}
+
+/*GLboolean
+fine_culling_test_2D(GLUnurbsObj *nobj,GLfloat *pts,GLint cnt,
+ GLint stride, GLint dim)
+{
+ GLint visible_cnt;
+ GLfloat feedback_buffer[5];
+ GLsizei buffer_size;
+ GLint i;
+
+ if(nobj->culling==GL_FALSE)
+ return GL_FALSE;
+ buffer_size=5;
+ set_sampling_and_culling(nobj);
+
+ glFeedbackBuffer(buffer_size,GL_2D,feedback_buffer);
+ glRenderMode(GL_FEEDBACK);
+ glBegin(GL_LINE_LOOP);
+ if(dim==3)
+ {
+ for(i=0;i<cnt;i++)
+ glVertex3fv(pts+i*stride);
+ }
+ else
+ {
+ for(i=0;i<cnt;i++)
+ glVertex4fv(pts+i*stride);
+ }
+ glEnd();
+ visible_cnt=glRenderMode(GL_RENDER);
+
+ revert_sampling_and_culling(nobj);
+ return (GLboolean)(visible_cnt==0);
+}*/
+
diff --git a/src/glu/mesa/polytest.c b/src/glu/mesa/polytest.c
new file mode 100644
index 0000000000..9b42c63477
--- /dev/null
+++ b/src/glu/mesa/polytest.c
@@ -0,0 +1,1049 @@
+/* $Id: polytest.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 2.4
+ * Copyright (C) 1995-1997 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.
+ */
+
+
+/*
+ * $Log: polytest.c,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 1.7 1999/06/08 00:44:51 brianp
+ * OpenStep updates (pete@ohm.york.ac.uk)
+ *
+ * Revision 1.6 1998/07/26 02:08:52 brianp
+ * updated for Windows compilation per Ted Jump
+ *
+ * Revision 1.5 1997/10/29 02:02:20 brianp
+ * various MS Windows compiler changes (David Bucciarelli, v20 3dfx driver)
+ *
+ * Revision 1.4 1997/07/24 01:28:44 brianp
+ * changed precompiled header symbol from PCH to PC_HEADER
+ *
+ * Revision 1.3 1997/05/28 02:29:38 brianp
+ * added support for precompiled headers (PCH), inserted APIENTRY keyword
+ *
+ * Revision 1.2 1997/05/08 01:53:21 brianp
+ * fixed memory leak in free_current_polygon() reported by Randy Frank
+ *
+ * Revision 1.1 1996/09/27 01:19:39 brianp
+ * Initial revision
+ *
+ */
+
+
+/*
+ * 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
+#if defined(WIN32) && !defined(OPENSTEP)
+__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;
+
+ /* 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/mesa/project.c b/src/glu/mesa/project.c
new file mode 100644
index 0000000000..32142c959e
--- /dev/null
+++ b/src/glu/mesa/project.c
@@ -0,0 +1,318 @@
+/* $Id: project.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ * Copyright (C) 1995-1999 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.
+ */
+
+
+/*
+ * $Log: project.c,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 1.7 1999/01/03 03:23:15 brianp
+ * now using GLAPIENTRY and GLCALLBACK keywords (Ted Jump)
+ *
+ * Revision 1.6 1998/07/08 01:43:43 brianp
+ * new version of invert_matrix() (also in src/matrix.c)
+ *
+ * Revision 1.5 1997/07/24 01:28:44 brianp
+ * changed precompiled header symbol from PCH to PC_HEADER
+ *
+ * Revision 1.4 1997/05/28 02:29:38 brianp
+ * added support for precompiled headers (PCH), inserted APIENTRY keyword
+ *
+ * Revision 1.3 1997/04/11 23:22:42 brianp
+ * added divide by zero checks to gluProject() and gluUnproject()
+ *
+ * Revision 1.2 1997/01/29 19:05:29 brianp
+ * faster invert_matrix() function from Stephane Rehel
+ *
+ * Revision 1.1 1996/09/27 01:19:39 brianp
+ * Initial revision
+ *
+ */
+
+
+#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) );
+}
+
+
+static GLdouble Identity[16] = {
+ 1.0, 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 0.0, 0.0, 0.0, 1.0
+};
+
+
+
+/*
+ * 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;
+}
+
diff --git a/src/glu/mesa/quadric.c b/src/glu/mesa/quadric.c
new file mode 100644
index 0000000000..4698e795b1
--- /dev/null
+++ b/src/glu/mesa/quadric.c
@@ -0,0 +1,858 @@
+/* $Id: quadric.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ * Copyright (C) 1995-1999 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.
+ */
+
+
+/*
+ * $Log: quadric.c,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 1.19 1999/02/27 13:55:31 brianp
+ * fixed BeOS-related GLU typedef problems
+ *
+ * Revision 1.18 1999/01/03 03:23:15 brianp
+ * now using GLAPIENTRY and GLCALLBACK keywords (Ted Jump)
+ *
+ * Revision 1.17 1999/01/03 03:19:15 brianp
+ * rewrote some of gluCylinder
+ *
+ * Revision 1.16 1998/06/01 01:08:36 brianp
+ * small update for Next/OpenStep from Alexander Mai
+ *
+ * Revision 1.15 1998/03/15 18:28:54 brianp
+ * reimplemented gluDisk() point and line mode
+ *
+ * Revision 1.14 1998/03/15 18:14:17 brianp
+ * fixed a compiler cast warning
+ *
+ * Revision 1.13 1998/02/07 14:28:34 brianp
+ * another change to gluQuadricCallback(), this time for StormC compiler
+ *
+ * Revision 1.12 1998/02/05 00:43:19 brianp
+ * Yes, still another change to gluQuadricCallback()!
+ *
+ * Revision 1.11 1998/02/04 00:27:43 brianp
+ * yet another change to gluQuadricCallback()!
+ *
+ * Revision 1.10 1998/02/04 00:23:23 brianp
+ * fixed CALLBACK problem in gluQuadricCallback() (Stephane Rehel)
+ *
+ * Revision 1.9 1998/02/04 00:20:09 brianp
+ * added missing (int) in ErrorFunc cast
+ *
+ * Revision 1.8 1998/01/16 03:37:51 brianp
+ * fixed another assignment warning in gluQuadricCallback()
+ *
+ * Revision 1.7 1998/01/16 03:35:26 brianp
+ * fixed Windows compilation warnings (Theodore Jump)
+ *
+ * Revision 1.6 1997/10/29 02:02:20 brianp
+ * various MS Windows compiler changes (David Bucciarelli, v20 3dfx driver)
+ *
+ * Revision 1.5 1997/09/17 01:51:48 brianp
+ * changed glu*Callback() functions to match prototype in glu.h
+ *
+ * Revision 1.4 1997/07/24 01:28:44 brianp
+ * changed precompiled header symbol from PCH to PC_HEADER
+ *
+ * Revision 1.3 1997/05/28 02:29:38 brianp
+ * added support for precompiled headers (PCH), inserted APIENTRY keyword
+ *
+ * Revision 1.2 1997/03/12 02:15:38 brianp
+ * fixed problem in gluPartialDisk() reported by Kenneth H. Carpenter
+ *
+ * Revision 1.1 1996/09/27 01:19:39 brianp
+ * Initial revision
+ *
+ */
+
+
+/* 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(*)(int))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 )
+{
+ GLdouble mag;
+
+ mag = sqrt( x*x + y*y + z*z );
+ if (mag>0.00001F) {
+ x /= mag;
+ y /= mag;
+ z /= mag;
+ }
+ glNormal3f( x, y, 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);
+ y = cos(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 );
+ TXTR_COORD(0.5,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);
+ if (normals) glNormal3f( x*nsign, y*nsign, z*nsign );
+ 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);
+ if (normals) glNormal3f( x*nsign, y*nsign, z*nsign );
+ 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);
+ if (normals) glNormal3f( x*nsign, y*nsign, z*nsign );
+ 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 );
+ glNormal3f( 0.0, 0.0, -1.0 );
+ TXTR_COORD(0.5,0.0);
+ 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);
+ if (normals) glNormal3f( x*nsign, y*nsign, z*nsign );
+ TXTR_COORD(s,t);
+ 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);
+ if (normals) glNormal3f( x*nsign, y*nsign, z*nsign );
+ 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);
+ if (normals) glNormal3f( x*nsign, y*nsign, z*nsign );
+ glVertex3f( x*radius, y*radius, z*radius );
+ }
+ glEnd();
+ }
+ }
+ else if (qobj->DrawStyle==GLU_POINT) {
+ /* top and bottom-most points */
+ glBegin( GL_POINTS );
+ if (normals) glNormal3f( 0.0, 0.0, nsign );
+ glVertex3d( 0.0, 0.0, radius );
+ if (normals) glNormal3f( 0.0, 0.0, -nsign );
+ glVertex3d( 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);
+ if (normals) glNormal3f( x*nsign, y*nsign, z*nsign );
+ 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
+
+ /* Normal vectors */
+ if (qobj->Normals!=GLU_NONE) {
+ if (qobj->Orientation==GLU_OUTSIDE) {
+ glNormal3f( 0.0, 0.0, +1.0 );
+ }
+ else {
+ glNormal3f( 0.0, 0.0, -1.0 );
+ }
+ }
+
+ 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->Normals!=GLU_NONE) {
+ if (qobj->Orientation==GLU_OUTSIDE) {
+ glNormal3f( 0.0, 0.0, +1.0 );
+ }
+ else {
+ glNormal3f( 0.0, 0.0, -1.0 );
+ }
+ }
+
+ 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++) {
+ glVertex2d( 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++) {
+ glVertex2d( 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++) {
+ glVertex2d( 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++) {
+ glVertex2d( 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++) {
+ glVertex2d( innerRadius * sin(angle), innerRadius * cos(angle) );
+ angle += delta_angle;
+ }
+ glEnd();
+ }
+ /* draw spokes */
+ if (sweepAngle<360.0) {
+ GLdouble stopAngle = startAngle + sweepAngle;
+ glBegin( GL_LINES );
+ glVertex2d( innerRadius*SIND(startAngle), innerRadius*COSD(startAngle) );
+ glVertex2d( outerRadius*SIND(startAngle), outerRadius*COSD(startAngle) );
+ glVertex2d( innerRadius*SIND(stopAngle), innerRadius*COSD(stopAngle) );
+ glVertex2d( 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) {
+ glVertex2d( (radius+delta_radius)*sin(angle),
+ (radius+delta_radius)*cos(angle) );
+ glVertex2d( radius * sin(angle), radius * cos(angle) );
+ }
+ else {
+ glVertex2d( radius * sin(angle), radius * cos(angle) );
+ glVertex2d( (radius+delta_radius)*sin(angle),
+ (radius+delta_radius)*cos(angle) );
+ }
+ angle += delta_angle;
+ }
+ glEnd();
+ radius += delta_radius;
+ }
+ }
+}
+
+
+
diff --git a/src/glu/mesa/tess.c b/src/glu/mesa/tess.c
new file mode 100644
index 0000000000..c773fbaae4
--- /dev/null
+++ b/src/glu/mesa/tess.c
@@ -0,0 +1,369 @@
+/* $Id: tess.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ * Copyright (C) 1995-1999 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.
+ */
+
+
+/*
+ * $Log: tess.c,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 1.11 1999/02/27 13:55:31 brianp
+ * fixed BeOS-related GLU typedef problems
+ *
+ * Revision 1.10 1999/01/03 03:23:15 brianp
+ * now using GLAPIENTRY and GLCALLBACK keywords (Ted Jump)
+ *
+ * Revision 1.9 1998/06/01 01:10:29 brianp
+ * small update for Next/OpenStep from Alexander Mai
+ *
+ * Revision 1.8 1998/02/04 00:27:58 brianp
+ * cygnus changes from Stephane Rehel
+ *
+ * Revision 1.7 1998/01/16 03:35:26 brianp
+ * fixed Windows compilation warnings (Theodore Jump)
+ *
+ * Revision 1.6 1997/09/17 01:51:48 brianp
+ * changed glu*Callback() functions to match prototype in glu.h
+ *
+ * Revision 1.5 1997/07/24 01:28:44 brianp
+ * changed precompiled header symbol from PCH to PC_HEADER
+ *
+ * Revision 1.4 1997/05/28 02:29:38 brianp
+ * added support for precompiled headers (PCH), inserted APIENTRY keyword
+ *
+ * Revision 1.3 1996/11/12 01:23:02 brianp
+ * added test to prevent free(vertex) when vertex==NULL in delete_contours()
+ *
+ * Revision 1.2 1996/10/22 22:57:19 brianp
+ * better error handling in gluBegin/EndPolygon() from Erich Eder
+ *
+ * Revision 1.1 1996/09/27 01:19:39 brianp
+ * Initial revision
+ *
+ */
+
+
+/*
+ * 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(GLCALLBACK)
+#undef GLCALLBACK
+#define GLCALLBACK
+#endif
+
+
+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 *);
+static void delete_contours(GLUtriangulatorObj *);
+
+#ifdef __CYGWIN32__
+#define _CALLBACK
+#else
+#define _CALLBACK GLCALLBACK
+#endif
+
+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;
+ tobj = (GLUtriangulatorObj *) malloc(sizeof(struct GLUtesselator));
+ if (!tobj)
+ 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;
+}
+
+
+
diff --git a/src/glu/mesa/tess.h b/src/glu/mesa/tess.h
new file mode 100644
index 0000000000..53d673ccbe
--- /dev/null
+++ b/src/glu/mesa/tess.h
@@ -0,0 +1,121 @@
+/* $Id: tess.h,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.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.
+ */
+
+
+/*
+ * $Log: tess.h,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 1.5 1999/02/27 13:55:31 brianp
+ * fixed BeOS-related GLU typedef problems
+ *
+ * Revision 1.4 1999/01/03 03:23:15 brianp
+ * now using GLAPIENTRY and GLCALLBACK keywords (Ted Jump)
+ *
+ * Revision 1.3 1997/10/29 02:02:20 brianp
+ * various MS Windows compiler changes (David Bucciarelli, v20 3dfx driver)
+ *
+ * Revision 1.2 1997/05/24 13:30:58 brianp
+ * added TESS_H multi-inclusion prevention test
+ *
+ * Revision 1.1 1996/09/27 01:19:39 brianp
+ * Initial revision
+ *
+ */
+
+
+/*
+ * 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);
+
+
+#endif
diff --git a/src/glu/mesa/tesselat.c b/src/glu/mesa/tesselat.c
new file mode 100644
index 0000000000..1e424c17ca
--- /dev/null
+++ b/src/glu/mesa/tesselat.c
@@ -0,0 +1,456 @@
+/* $Id: tesselat.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 2.4
+ * Copyright (C) 1995-1997 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.
+ */
+
+
+/*
+ * $Log: tesselat.c,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 1.5 1997/07/24 01:28:44 brianp
+ * changed precompiled header symbol from PCH to PC_HEADER
+ *
+ * Revision 1.4 1997/05/28 02:29:38 brianp
+ * added support for precompiled headers (PCH), inserted APIENTRY keyword
+ *
+ * Revision 1.3 1997/02/17 17:24:58 brianp
+ * more tesselation changes (Randy Frank)
+ *
+ * Revision 1.2 1997/02/13 18:31:57 brianp
+ * fixed some numerical precision problems (Randy Frank)
+ *
+ * Revision 1.1 1996/09/27 01:19:39 brianp
+ * Initial revision
+ *
+ */
+
+
+/*
+ * 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/glw/GLwDrawA.c b/src/glw/GLwDrawA.c
new file mode 100644
index 0000000000..670ddb18ed
--- /dev/null
+++ b/src/glw/GLwDrawA.c
@@ -0,0 +1,686 @@
+/*
+ * (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.
+ */
+
+/*
+ *
+ * This file has been slightly modified from the original for use with Mesa
+ *
+ * Jeroen van der Zijp
+ *
+ * jvz@cyberia.cfdrc.com
+ *
+ */
+#include <X11/IntrinsicP.h>
+#include <X11/StringDefs.h>
+#include <GL/glx.h>
+#include <GL/gl.h>
+#ifdef __GLX_MOTIF
+#include <Xm/PrimitiveP.h>
+#include "GLwMDrawAP.h"
+#else
+#include "GLwDrawAP.h"
+#endif
+#include <assert.h>
+#include <stdio.h>
+
+#ifdef __GLX_MOTIF
+#define GLwDrawingAreaWidget GLwMDrawingAreaWidget
+#define GLwDrawingAreaClassRec GLwMDrawingAreaClassRec
+#define glwDrawingAreaClassRec glwMDrawingAreaClassRec
+#define glwDrawingAreaWidgetClass glwMDrawingAreaWidgetClass
+#define GLwDrawingAreaRec GLwMDrawingAreaRec
+#endif
+
+#define ATTRIBLIST_SIZE 30
+
+#define offset(field) XtOffset(GLwDrawingAreaWidget,glwDrawingArea.field)
+
+
+/* forward definitions */
+static void createColormap(GLwDrawingAreaWidget w,int offset,XrmValue *value);
+static void Initialize(GLwDrawingAreaWidget req,GLwDrawingAreaWidget neww,ArgList args,Cardinal *num_args);
+static void Realize(Widget w,Mask *valueMask,XSetWindowAttributes *attributes);
+static void Redraw(GLwDrawingAreaWidget w,XEvent *event,Region region);
+static void Resize(GLwDrawingAreaWidget glw);
+static void Destroy(GLwDrawingAreaWidget glw);
+static void glwInput(GLwDrawingAreaWidget glw,XEvent *event,String *params,Cardinal *numParams);
+
+
+
+static char defaultTranslations[] =
+#ifdef __GLX_MOTIF
+ "<Key>osfHelp:PrimitiveHelp() \n"
+#endif
+ "<KeyDown>: glwInput() \n\
+ <KeyUp>: glwInput() \n\
+ <BtnDown>: glwInput() \n\
+ <BtnUp>: glwInput() \n\
+ <BtnMotion>: glwInput() ";
+
+
+static XtActionsRec actions[] = {
+ {"glwInput",(XtActionProc)glwInput}, /* key or mouse input */
+ };
+
+
+/*
+ * There is a bit of unusual handling of the resources here.
+ * Because Xt insists on allocating the colormap resource when it is
+ * processing the core resources (even if we redeclare the colormap
+ * resource here, we need to do a little trick. When Xt first allocates
+ * the colormap, we allow it to allocate the default one, since we have
+ * not yet determined the appropriate visual (which is determined from
+ * resources parsed after the colormap). We also let it allocate colors
+ * in that default colormap.
+ *
+ * In the initialize proc we calculate the actual visual. Then, we
+ * reobtain the colormap resource using XtGetApplicationResources in
+ * the initialize proc. If requested, we also reallocate colors in
+ * that colormap using the same method.
+ */
+
+static XtResource resources[] = {
+ /* The GLX attributes. Add any new attributes here */
+
+ {GLwNbufferSize, GLwCBufferSize, XtRInt, sizeof (int),
+ offset(bufferSize), XtRImmediate, (XtPointer) 0},
+
+ {GLwNlevel, GLwCLevel, XtRInt, sizeof (int),
+ offset(level), XtRImmediate, (XtPointer) 0},
+
+ {GLwNrgba, GLwCRgba, XtRBoolean, sizeof (Boolean),
+ offset(rgba), XtRImmediate, (XtPointer) FALSE},
+
+ {GLwNdoublebuffer, GLwCDoublebuffer, XtRBoolean, sizeof (Boolean),
+ offset(doublebuffer), XtRImmediate, (XtPointer) FALSE},
+
+ {GLwNstereo, GLwCStereo, XtRBoolean, sizeof (Boolean),
+ offset(stereo), XtRImmediate, (XtPointer) FALSE},
+
+ {GLwNauxBuffers, GLwCAuxBuffers, XtRInt, sizeof (int),
+ offset(auxBuffers), XtRImmediate, (XtPointer) 0},
+
+ {GLwNredSize, GLwCColorSize, XtRInt, sizeof (int),
+ offset(redSize), XtRImmediate, (XtPointer) 1},
+
+ {GLwNgreenSize, GLwCColorSize, XtRInt, sizeof (int),
+ offset(greenSize), XtRImmediate, (XtPointer) 1},
+
+ {GLwNblueSize, GLwCColorSize, XtRInt, sizeof (int),
+ offset(blueSize), XtRImmediate, (XtPointer) 1},
+
+ {GLwNalphaSize, GLwCAlphaSize, XtRInt, sizeof (int),
+ offset(alphaSize), XtRImmediate, (XtPointer) 0},
+
+ {GLwNdepthSize, GLwCDepthSize, XtRInt, sizeof (int),
+ offset(depthSize), XtRImmediate, (XtPointer) 0},
+
+ {GLwNstencilSize, GLwCStencilSize, XtRInt, sizeof (int),
+ offset(stencilSize), XtRImmediate, (XtPointer) 0},
+
+ {GLwNaccumRedSize, GLwCAccumColorSize, XtRInt, sizeof (int),
+ offset(accumRedSize), XtRImmediate, (XtPointer) 0},
+
+ {GLwNaccumGreenSize, GLwCAccumColorSize, XtRInt, sizeof (int),
+ offset(accumGreenSize), XtRImmediate, (XtPointer) 0},
+
+ {GLwNaccumBlueSize, GLwCAccumColorSize, XtRInt, sizeof (int),
+ offset(accumBlueSize), XtRImmediate, (XtPointer) 0},
+
+ {GLwNaccumAlphaSize, GLwCAccumAlphaSize, XtRInt, sizeof (int),
+ offset(accumAlphaSize), XtRImmediate, (XtPointer) 0},
+
+ /* the attribute list */
+ {GLwNattribList, GLwCAttribList, XtRPointer, sizeof(int *),
+ offset(attribList), XtRImmediate, (XtPointer) NULL},
+
+ /* the visual info */
+ {GLwNvisualInfo, GLwCVisualInfo, GLwRVisualInfo, sizeof (XVisualInfo *),
+ offset(visualInfo), XtRImmediate, (XtPointer) NULL},
+
+ /* miscellaneous resources */
+ {GLwNinstallColormap, GLwCInstallColormap, XtRBoolean, sizeof (Boolean),
+ offset(installColormap), XtRImmediate, (XtPointer) TRUE},
+
+ {GLwNallocateBackground, GLwCAllocateColors, XtRBoolean, sizeof (Boolean),
+ offset(allocateBackground), XtRImmediate, (XtPointer) FALSE},
+
+ {GLwNallocateOtherColors, GLwCAllocateColors, XtRBoolean, sizeof (Boolean),
+ offset(allocateOtherColors), XtRImmediate, (XtPointer) FALSE},
+
+ {GLwNinstallBackground, GLwCInstallBackground, XtRBoolean, sizeof (Boolean),
+ offset(installBackground), XtRImmediate, (XtPointer) TRUE},
+
+ {GLwNginitCallback, GLwCCallback, XtRCallback, sizeof (XtCallbackList),
+ offset(ginitCallback), XtRImmediate, (XtPointer) NULL},
+
+ {GLwNinputCallback, GLwCCallback, XtRCallback, sizeof (XtCallbackList),
+ offset(inputCallback), XtRImmediate, (XtPointer) NULL},
+
+ {GLwNresizeCallback, GLwCCallback, XtRCallback, sizeof (XtCallbackList),
+ offset(resizeCallback), XtRImmediate, (XtPointer) NULL},
+
+ {GLwNexposeCallback, GLwCCallback, XtRCallback, sizeof (XtCallbackList),
+ offset(exposeCallback), XtRImmediate, (XtPointer) NULL},
+
+ /* Changes to Motif primitive resources */
+#ifdef __GLX_MOTIF
+ {XmNtraversalOn, XmCTraversalOn, XmRBoolean, sizeof (Boolean),
+ XtOffset (GLwDrawingAreaWidget, primitive.traversal_on), XmRImmediate,
+ (XtPointer)FALSE},
+
+ /* highlighting is normally disabled, as when Motif tries to disable
+ * highlighting, it tries to reset the color back to the parent's
+ * background (usually Motif blue). Unfortunately, that is in a
+ * different colormap, and doesn't work too well.
+ */
+ {XmNhighlightOnEnter, XmCHighlightOnEnter, XmRBoolean, sizeof (Boolean),
+ XtOffset (GLwDrawingAreaWidget, primitive.highlight_on_enter),
+ XmRImmediate, (XtPointer) FALSE},
+
+ {XmNhighlightThickness, XmCHighlightThickness, XmRHorizontalDimension,
+ sizeof (Dimension),
+ XtOffset (GLwDrawingAreaWidget, primitive.highlight_thickness),
+ XmRImmediate, (XtPointer) 0},
+#endif
+ };
+
+
+/*
+** The following resources are reobtained using XtGetApplicationResources
+** in the initialize proc.
+*/
+
+/* The colormap */
+static XtResource initializeResources[] = {
+ /* reobtain the colormap with the new visual */
+ {XtNcolormap, XtCColormap, XtRColormap, sizeof(Colormap),
+ XtOffset(GLwDrawingAreaWidget, core.colormap),
+ XtRCallProc,(XtPointer) createColormap},
+ };
+
+
+/* reallocate any colors we need in the new colormap */
+
+/* The background is obtained only if the allocateBackground resource is TRUE*/
+static XtResource backgroundResources[] = {
+#ifdef __GLX_MOTIF
+ {XmNbackground, XmCBackground,XmRPixel,
+ sizeof(Pixel),XtOffset(GLwDrawingAreaWidget,core.background_pixel),
+ XmRString,(XtPointer)"lightgrey"},
+ /*XmRCallProc,(XtPointer)_XmBackgroundColorDefault},*/
+
+ {XmNbackgroundPixmap,XmCPixmap,XmRXmBackgroundPixmap,
+ sizeof(Pixmap),XtOffset(GLwDrawingAreaWidget,core.background_pixmap),
+ XmRImmediate,(XtPointer)XmUNSPECIFIED_PIXMAP},
+
+#else
+ {XtNbackground,XtCBackground,XtRPixel,sizeof(Pixel),
+ XtOffset(GLwDrawingAreaWidget,core.background_pixel),
+ XtRString,(XtPointer)"lightgrey"},
+ /*XtRString,(XtPointer)"XtDefaultBackground"},*/
+
+ {XtNbackgroundPixmap, XtCPixmap, XtRPixmap, sizeof(Pixmap),
+ XtOffset(GLwDrawingAreaWidget,core.background_pixmap),
+ XtRImmediate,(XtPointer)XtUnspecifiedPixmap},
+#endif
+ };
+
+
+
+/* The other colors such as the foreground are allocated only if
+ * allocateOtherColors are set. These resources only exist in Motif.
+ */
+#ifdef __GLX_MOTIF
+static XtResource otherColorResources[] = {
+ {XmNforeground,XmCForeground,XmRPixel,
+ sizeof(Pixel),XtOffset(GLwDrawingAreaWidget,primitive.foreground),
+ XmRString,(XtPointer)"lighgrey"},
+ /*XmRCallProc, (XtPointer) _XmForegroundColorDefault},*/
+
+ {XmNhighlightColor,XmCHighlightColor,XmRPixel,sizeof(Pixel),
+ XtOffset(GLwDrawingAreaWidget,primitive.highlight_color),
+ XmRString,(XtPointer)"lightgrey"},
+ /*XmRCallProc,(XtPointer)_XmHighlightColorDefault},*/
+
+ {XmNhighlightPixmap,XmCHighlightPixmap,XmRPrimHighlightPixmap,
+ sizeof(Pixmap),
+ XtOffset(GLwDrawingAreaWidget,primitive.highlight_pixmap),
+ XmRImmediate,(XtPointer)XmUNSPECIFIED_PIXMAP},
+ /*XmRCallProc,(XtPointer)_XmPrimitiveHighlightPixmapDefault},*/
+ };
+#endif
+
+
+#undef offset
+
+
+GLwDrawingAreaClassRec glwDrawingAreaClassRec = {
+ { /* core fields */
+#ifdef __GLX_MOTIF
+ /* superclass */ (WidgetClass) &xmPrimitiveClassRec,
+ /* class_name */ "GLwMDrawingArea",
+#else /* not __GLX_MOTIF */
+ /* superclass */ (WidgetClass) &widgetClassRec,
+ /* class_name */ "GLwDrawingArea",
+#endif /* __GLX_MOTIF */
+ /* widget_size */ sizeof(GLwDrawingAreaRec),
+ /* class_initialize */ NULL,
+ /* class_part_initialize */ NULL,
+ /* class_inited */ FALSE,
+ /* initialize */ (XtInitProc) Initialize,
+ /* initialize_hook */ NULL,
+ /* realize */ Realize,
+ /* actions */ actions,
+ /* num_actions */ XtNumber(actions),
+ /* resources */ resources,
+ /* num_resources */ XtNumber(resources),
+ /* xrm_class */ NULLQUARK,
+ /* compress_motion */ TRUE,
+ /* compress_exposure */ TRUE,
+ /* compress_enterleave */ TRUE,
+ /* visible_interest */ TRUE,
+ /* destroy */ (XtWidgetProc) Destroy,
+ /* resize */ (XtWidgetProc) Resize,
+ /* expose */ (XtExposeProc) Redraw,
+ /* set_values */ NULL,
+ /* set_values_hook */ NULL,
+ /* set_values_almost */ XtInheritSetValuesAlmost,
+ /* get_values_hook */ NULL,
+ /* accept_focus */ NULL,
+ /* version */ XtVersion,
+ /* callback_private */ NULL,
+ /* tm_table */ defaultTranslations,
+ /* query_geometry */ XtInheritQueryGeometry,
+ /* display_accelerator */ XtInheritDisplayAccelerator,
+ /* extension */ NULL
+ },
+#ifdef __GLX_MOTIF /* primitive resources */
+ {
+ /* border_highlight */ XmInheritBorderHighlight,
+ /* border_unhighlight */ XmInheritBorderUnhighlight,
+ /* translations */ XtInheritTranslations,
+ /* arm_and_activate */ NULL,
+ /* get_resources */ NULL,
+ /* num get_resources */ 0,
+ /* extension */ NULL,
+ }
+#endif
+ };
+
+WidgetClass glwDrawingAreaWidgetClass=(WidgetClass)&glwDrawingAreaClassRec;
+
+
+
+static void error(Widget w,char* string){
+ char buf[100];
+#ifdef __GLX_MOTIF
+ sprintf(buf,"GLwMDrawingArea: %s\n",string);
+#else
+ sprintf(buf,"GLwDrawingArea: %s\n",string);
+#endif
+ XtAppError(XtWidgetToApplicationContext(w),buf);
+ }
+
+
+static void warning(Widget w,char* string){
+ char buf[100];
+#ifdef __GLX_MOTIF
+ sprintf (buf, "GLwMDraw: %s\n", string);
+#else
+ sprintf (buf, "GLwDraw: %s\n", string);
+#endif
+ XtAppWarning(XtWidgetToApplicationContext(w), buf);
+ }
+
+
+
+/* Initialize the attribList based on the attributes */
+static void createAttribList(GLwDrawingAreaWidget w){
+ int *ptr;
+ w->glwDrawingArea.attribList = (int*)XtMalloc(ATTRIBLIST_SIZE*sizeof(int));
+ if(!w->glwDrawingArea.attribList){
+ error((Widget)w,"Unable to allocate attribute list");
+ }
+ ptr = w->glwDrawingArea.attribList;
+ *ptr++ = GLX_BUFFER_SIZE;
+ *ptr++ = w->glwDrawingArea.bufferSize;
+ *ptr++ = GLX_LEVEL;
+ *ptr++ = w->glwDrawingArea.level;
+ if(w->glwDrawingArea.rgba) *ptr++ = GLX_RGBA;
+ if(w->glwDrawingArea.doublebuffer) *ptr++ = GLX_DOUBLEBUFFER;
+ if(w->glwDrawingArea.stereo) *ptr++ = GLX_STEREO;
+ *ptr++ = GLX_AUX_BUFFERS;
+ *ptr++ = w->glwDrawingArea.auxBuffers;
+ *ptr++ = GLX_RED_SIZE;
+ *ptr++ = w->glwDrawingArea.redSize;
+ *ptr++ = GLX_GREEN_SIZE;
+ *ptr++ = w->glwDrawingArea.greenSize;
+ *ptr++ = GLX_BLUE_SIZE;
+ *ptr++ = w->glwDrawingArea.blueSize;
+ *ptr++ = GLX_ALPHA_SIZE;
+ *ptr++ = w->glwDrawingArea.alphaSize;
+ *ptr++ = GLX_DEPTH_SIZE;
+ *ptr++ = w->glwDrawingArea.depthSize;
+ *ptr++ = GLX_STENCIL_SIZE;
+ *ptr++ = w->glwDrawingArea.stencilSize;
+ *ptr++ = GLX_ACCUM_RED_SIZE;
+ *ptr++ = w->glwDrawingArea.accumRedSize;
+ *ptr++ = GLX_ACCUM_GREEN_SIZE;
+ *ptr++ = w->glwDrawingArea.accumGreenSize;
+ *ptr++ = GLX_ACCUM_BLUE_SIZE;
+ *ptr++ = w->glwDrawingArea.accumBlueSize;
+ *ptr++ = GLX_ACCUM_ALPHA_SIZE;
+ *ptr++ = w->glwDrawingArea.accumAlphaSize;
+ *ptr++ = None;
+ assert((ptr-w->glwDrawingArea.attribList)<ATTRIBLIST_SIZE);
+ }
+
+
+
+/* Initialize the visualInfo based on the attribute list */
+static void createVisualInfo(GLwDrawingAreaWidget w){
+ static XVisualInfo *visualInfo;
+ assert(w->glwDrawingArea.attribList);
+ w->glwDrawingArea.visualInfo=glXChooseVisual(XtDisplay(w),XScreenNumberOfScreen(XtScreen(w)),w->glwDrawingArea.attribList);
+ if(!w->glwDrawingArea.visualInfo) error((Widget)w,"requested visual not supported");
+ }
+
+
+
+/* Initialize the colormap based on the visual info.
+ * This routine maintains a cache of visual-infos to colormaps. If two
+ * widgets share the same visual info, they share the same colormap.
+ * This function is called by the callProc of the colormap resource entry.
+ */
+static void createColormap(GLwDrawingAreaWidget w,int offset,XrmValue *value){
+ static struct cmapCache { Visual *visual; Colormap cmap; } *cmapCache;
+ static int cacheEntries=0;
+ static int cacheMalloced=0;
+ register int i;
+
+ assert(w->glwDrawingArea.visualInfo);
+
+ /* see if we can find it in the cache */
+ for(i=0; i<cacheEntries; i++){
+ if(cmapCache[i].visual==w->glwDrawingArea.visualInfo->visual){
+ value->addr=(XtPointer)(&cmapCache[i].cmap);
+ return;
+ }
+ }
+
+ /* not in the cache, create a new entry */
+ if(cacheEntries >= cacheMalloced){
+ /* need to malloc a new one. Since we are likely to have only a
+ * few colormaps, we allocate one the first time, and double
+ * each subsequent time.
+ */
+ if(cacheMalloced==0){
+ cacheMalloced=1;
+ cmapCache=(struct cmapCache*)XtMalloc(sizeof(struct cmapCache));
+ }
+ else{
+ cacheMalloced<<=1;
+ cmapCache=(struct cmapCache*)XtRealloc((char*)cmapCache,sizeof(struct cmapCache)*cacheMalloced);
+ }
+ }
+
+ cmapCache[cacheEntries].cmap=XCreateColormap(XtDisplay(w),
+ RootWindow(XtDisplay(w),
+ w->glwDrawingArea.visualInfo->screen),
+ w->glwDrawingArea.visualInfo->visual,
+ AllocNone);
+ cmapCache[cacheEntries].visual=w->glwDrawingArea.visualInfo->visual;
+ value->addr=(XtPointer)(&cmapCache[cacheEntries++].cmap);
+ }
+
+
+
+static void Initialize(GLwDrawingAreaWidget req,GLwDrawingAreaWidget neww,ArgList args,Cardinal *num_args){
+
+ /* fix size */
+ if(req->core.width==0) neww->core.width=100;
+ if(req->core.height==0) neww->core.width=100;
+
+ /* create the attribute list if needed */
+ neww->glwDrawingArea.myList=FALSE;
+ if(neww->glwDrawingArea.attribList==NULL){
+ neww->glwDrawingArea.myList=TRUE;
+ createAttribList(neww);
+ }
+
+ /* Gotta have it */
+ assert(neww->glwDrawingArea.attribList);
+
+ /* determine the visual info if needed */
+ neww->glwDrawingArea.myVisual=FALSE;
+ if(neww->glwDrawingArea.visualInfo==NULL){
+ neww->glwDrawingArea.myVisual=TRUE;
+ createVisualInfo(neww);
+ }
+
+ /* Gotta have that too */
+ assert(neww->glwDrawingArea.visualInfo);
+
+ neww->core.depth=neww->glwDrawingArea.visualInfo->depth;
+
+ /* Reobtain the colormap and colors in it using XtGetApplicationResources*/
+ XtGetApplicationResources((Widget)neww,neww,initializeResources,XtNumber(initializeResources),args,*num_args);
+
+ /* obtain the color resources if appropriate */
+ if(req->glwDrawingArea.allocateBackground){
+ XtGetApplicationResources((Widget)neww,neww,backgroundResources,XtNumber(backgroundResources),args,*num_args);
+ }
+
+#ifdef __GLX_MOTIF
+ if(req->glwDrawingArea.allocateOtherColors){
+ XtGetApplicationResources((Widget)neww,neww,otherColorResources,XtNumber(otherColorResources),args,*num_args);
+ }
+#endif
+ }
+
+
+
+static void Realize(Widget w,Mask *valueMask,XSetWindowAttributes *attributes){
+ register GLwDrawingAreaWidget glw=(GLwDrawingAreaWidget)w;
+ GLwDrawingAreaCallbackStruct cb;
+ Widget parentShell;
+ Status status;
+ Window windows[2],*windowsReturn,*windowList;
+ int countReturn,i;
+
+ /* if we haven't requested that the background be both installed and
+ * allocated, don't install it.
+ */
+ if(!(glw->glwDrawingArea.installBackground && glw->glwDrawingArea.allocateBackground)){
+ *valueMask&=~CWBackPixel;
+ }
+
+ XtCreateWindow(w,(unsigned int)InputOutput,glw->glwDrawingArea.visualInfo->visual,*valueMask,attributes);
+
+ /* if appropriate, call XSetWMColormapWindows to install the colormap */
+ if(glw->glwDrawingArea.installColormap){
+
+ /* Get parent shell */
+ for(parentShell=XtParent(w); parentShell&&!XtIsShell(parentShell); parentShell=XtParent(parentShell));
+
+ if(parentShell && XtWindow(parentShell)){
+
+ /* check to see if there is already a property */
+ status=XGetWMColormapWindows(XtDisplay(parentShell),XtWindow(parentShell),&windowsReturn,&countReturn);
+
+ /* if no property, just create one */
+ if(!status){
+ windows[0]=XtWindow(w);
+ windows[1]=XtWindow(parentShell);
+ XSetWMColormapWindows(XtDisplay(parentShell),XtWindow(parentShell),windows,2);
+ }
+
+ /* there was a property, add myself to the beginning */
+ else{
+ windowList=(Window *)XtMalloc((sizeof(Window))*(countReturn+1));
+ windowList[0]=XtWindow(w);
+ for(i=0; i<countReturn; i++) windowList[i+1]=windowsReturn[i];
+ XSetWMColormapWindows(XtDisplay(parentShell),XtWindow(parentShell),windowList,countReturn+1);
+ XtFree((char*)windowList);
+ XtFree((char*)windowsReturn);
+ }
+ }
+ else{
+ warning(w,"Could not set colormap property on parent shell");
+ }
+ }
+
+ /* Invoke callbacks */
+ cb.reason=GLwCR_GINIT;
+ cb.event=NULL;
+ cb.width=glw->core.width;
+ cb.height=glw->core.height;
+ XtCallCallbackList((Widget)glw,glw->glwDrawingArea.ginitCallback,&cb);
+ }
+
+
+
+static void Redraw(GLwDrawingAreaWidget w,XEvent *event,Region region){
+ GLwDrawingAreaCallbackStruct cb;
+ XtCallbackList cblist;
+ if(!XtIsRealized((Widget)w)) return;
+ cb.reason=GLwCR_EXPOSE;
+ cb.event=event;
+ cb.width=w->core.width;
+ cb.height=w->core.height;
+ XtCallCallbackList((Widget)w,w->glwDrawingArea.exposeCallback,&cb);
+ }
+
+
+
+static void Resize(GLwDrawingAreaWidget glw){
+ GLwDrawingAreaCallbackStruct cb;
+ if(!XtIsRealized((Widget)glw)) return;
+ cb.reason=GLwCR_RESIZE;
+ cb.event=NULL;
+ cb.width=glw->core.width;
+ cb.height=glw->core.height;
+ XtCallCallbackList((Widget)glw,glw->glwDrawingArea.resizeCallback,&cb);
+ }
+
+
+
+static void Destroy(GLwDrawingAreaWidget glw){
+ Window *windowsReturn;
+ Widget parentShell;
+ Status status;
+ int countReturn;
+ register int i;
+
+ if(glw->glwDrawingArea.myList && glw->glwDrawingArea.attribList){
+ XtFree((XtPointer)glw->glwDrawingArea.attribList);
+ }
+
+ if(glw->glwDrawingArea.myVisual && glw->glwDrawingArea.visualInfo){
+ XtFree((XtPointer)glw->glwDrawingArea.visualInfo);
+ }
+
+ /* if my colormap was installed, remove it */
+ if(glw->glwDrawingArea.installColormap){
+
+ /* Get parent shell */
+ for(parentShell=XtParent(glw); parentShell&&!XtIsShell(parentShell); parentShell=XtParent(parentShell));
+
+ if(parentShell && XtWindow(parentShell)){
+
+ /* make sure there is a property */
+ status=XGetWMColormapWindows(XtDisplay(parentShell),XtWindow(parentShell),&windowsReturn,&countReturn);
+
+ /* if no property, just return. If there was a property, continue */
+ if(status){
+
+ /* search for a match */
+ for(i=0; i<countReturn; i++){
+ if(windowsReturn[i]==XtWindow(glw)){
+
+ /* we found a match, now copy the rest down */
+ for(i++; i<countReturn; i++){ windowsReturn[i-1]=windowsReturn[i]; }
+
+ XSetWMColormapWindows(XtDisplay(parentShell),XtWindow(parentShell),windowsReturn,countReturn-1);
+ break;
+ }
+ }
+ XtFree((char *)windowsReturn);
+ }
+ }
+ }
+ }
+
+
+
+/* Action routine for keyboard and mouse events */
+static void glwInput(GLwDrawingAreaWidget glw,XEvent *event,String *params,Cardinal *numParams){
+ GLwDrawingAreaCallbackStruct cb;
+ cb.reason=GLwCR_INPUT;
+ cb.event=event;
+ cb.width=glw->core.width;
+ cb.height=glw->core.height;
+ XtCallCallbackList((Widget)glw,glw->glwDrawingArea.inputCallback,&cb);
+ }
+
+
+#ifdef __GLX_MOTIF
+
+/* Create routine */
+Widget GLwCreateMDrawingArea(Widget parent, char *name,ArgList arglist,Cardinal argcount){
+ return XtCreateWidget(name,glwMDrawingAreaWidgetClass, parent, arglist,argcount);
+ }
+
+#endif
+
+
+#ifndef __GLX_MOTIF
+
+/* Make context current */
+void GLwDrawingAreaMakeCurrent(Widget w,GLXContext ctx){
+ glXMakeCurrent(XtDisplay(w),XtWindow(w),ctx);
+ }
+
+
+/* Swap buffers convenience function */
+void GLwDrawingAreaSwapBuffers(Widget w){
+ glXSwapBuffers(XtDisplay(w),XtWindow(w));
+ }
+
+#endif
diff --git a/src/glw/GLwDrawA.h b/src/glw/GLwDrawA.h
new file mode 100644
index 0000000000..a62852c260
--- /dev/null
+++ b/src/glw/GLwDrawA.h
@@ -0,0 +1,195 @@
+/*
+ * (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.
+ */
+#ifndef _GLwDrawA_h
+#define _GLwDrawA_h
+
+#include <GL/glx.h>
+#include <GL/gl.h>
+
+/****************************************************************
+ *
+ * GLwDrawingArea widgets
+ *
+ ****************************************************************/
+
+/* Resources:
+
+ Name Class RepType Default Value
+ ---- ----- ------- -------------
+ attribList AttribList int * NULL
+ visualInfo VisualInfo VisualInfo NULL
+ installColormap InstallColormap Boolean TRUE
+ allocateBackground AllocateColors Boolean FALSE
+ allocateOtherColors AllocateColors Boolean FALSE
+ installBackground InstallBackground Boolean TRUE
+ exposeCallback Callback Pointer NULL
+ ginitCallback Callback Pointer NULL
+ inputCallback Callback Pointer NULL
+ resizeCallback Callback Pointer NULL
+
+*** The following resources all correspond to the GLX configuration
+*** attributes and are used to create the attribList if it is NULL
+ bufferSize BufferSize int 0
+ level Level int 0
+ rgba Rgba Boolean FALSE
+ doublebuffer Doublebuffer Boolean FALSE
+ stereo Stereo Boolean FALSE
+ auxBuffers AuxBuffers int 0
+ redSize ColorSize int 1
+ greenSize ColorSize int 1
+ blueSize ColorSize int 1
+ alphaSize AlphaSize int 0
+ depthSize DepthSize int 0
+ stencilSize StencilSize int 0
+ accumRedSize AccumColorSize int 0
+ accumGreenSize AccumColorSize int 0
+ accumBlueSize AccumColorSize int 0
+ accumAlphaSize AccumAlphaSize int 0
+*/
+
+#define GLwNattribList "attribList"
+#define GLwCAttribList "AttribList"
+#define GLwNvisualInfo "visualInfo"
+#define GLwCVisualInfo "VisualInfo"
+#define GLwRVisualInfo "VisualInfo"
+
+#define GLwNinstallColormap "installColormap"
+#define GLwCInstallColormap "InstallColormap"
+#define GLwNallocateBackground "allocateBackground"
+#define GLwNallocateOtherColors "allocateOtherColors"
+#define GLwCAllocateColors "AllocateColors"
+#define GLwNinstallBackground "installBackground"
+#define GLwCInstallBackground "InstallBackground"
+
+#define GLwCCallback "Callback"
+#define GLwNexposeCallback "exposeCallback"
+#define GLwNginitCallback "ginitCallback"
+#define GLwNresizeCallback "resizeCallback"
+#define GLwNinputCallback "inputCallback"
+
+#define GLwNbufferSize "bufferSize"
+#define GLwCBufferSize "BufferSize"
+#define GLwNlevel "level"
+#define GLwCLevel "Level"
+#define GLwNrgba "rgba"
+#define GLwCRgba "Rgba"
+#define GLwNdoublebuffer "doublebuffer"
+#define GLwCDoublebuffer "Doublebuffer"
+#define GLwNstereo "stereo"
+#define GLwCStereo "Stereo"
+#define GLwNauxBuffers "auxBuffers"
+#define GLwCAuxBuffers "AuxBuffers"
+#define GLwNredSize "redSize"
+#define GLwNgreenSize "greenSize"
+#define GLwNblueSize "blueSize"
+#define GLwCColorSize "ColorSize"
+#define GLwNalphaSize "alphaSize"
+#define GLwCAlphaSize "AlphaSize"
+#define GLwNdepthSize "depthSize"
+#define GLwCDepthSize "DepthSize"
+#define GLwNstencilSize "stencilSize"
+#define GLwCStencilSize "StencilSize"
+#define GLwNaccumRedSize "accumRedSize"
+#define GLwNaccumGreenSize "accumGreenSize"
+#define GLwNaccumBlueSize "accumBlueSize"
+#define GLwCAccumColorSize "AccumColorSize"
+#define GLwNaccumAlphaSize "accumAlphaSize"
+#define GLwCAccumAlphaSize "AccumAlphaSize"
+
+#ifdef __GLX_MOTIF
+
+typedef struct _GLwMDrawingAreaClassRec *GLwMDrawingAreaWidgetClass;
+typedef struct _GLwMDrawingAreaRec *GLwMDrawingAreaWidget;
+
+extern WidgetClass glwMDrawingAreaWidgetClass;
+
+
+#else
+
+typedef struct _GLwDrawingAreaClassRec *GLwDrawingAreaWidgetClass;
+typedef struct _GLwDrawingAreaRec *GLwDrawingAreaWidget;
+
+extern WidgetClass glwDrawingAreaWidgetClass;
+
+
+#endif
+
+
+/* Callback reasons */
+#ifdef __GLX_MOTIF
+#define GLwCR_EXPOSE XmCR_EXPOSE
+#define GLwCR_RESIZE XmCR_RESIZE
+#define GLwCR_INPUT XmCR_INPUT
+#else
+/* The same values as Motif, but don't use Motif constants */
+#define GLwCR_EXPOSE 38
+#define GLwCR_RESIZE 39
+#define GLwCR_INPUT 40
+#endif
+
+#define GLwCR_GINIT 32135 /* Arbitrary number that should neverr clash */
+
+typedef struct
+ {
+ int reason;
+ XEvent *event;
+ Dimension width,height;
+ }
+ GLwDrawingAreaCallbackStruct;
+
+#if defined(__cplusplus) || defined(c_plusplus)
+extern "C" {
+#endif
+
+/* front ends to glXMakeCurrent and glXSwapBuffers */
+extern void GLwDrawingAreaMakeCurrent(Widget w,GLXContext ctx);
+extern void GLwDrawingAreaSwapBuffers(Widget w);
+
+#ifdef __GLX_MOTIF
+#ifdef _NO_PROTO
+extern Widget GLwCreateMDrawingArea();
+#else
+extern Widget GLwCreateMDrawingArea(Widget parent,char *name,ArgList arglist,Cardinal argcount);
+#endif
+#endif
+
+#if defined(__cplusplus) || defined(c_plusplus)
+}
+#endif
+
+#endif
diff --git a/src/glw/GLwDrawAP.h b/src/glw/GLwDrawAP.h
new file mode 100644
index 0000000000..f121701954
--- /dev/null
+++ b/src/glw/GLwDrawAP.h
@@ -0,0 +1,130 @@
+/*
+ * (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.
+ */
+#ifndef _GLwDrawAP_h
+#define _GLwDrawAP_h
+
+
+/* MOTIF */
+#ifdef __GLX_MOTIF
+#include "GLwMDrawA.h"
+#else
+#include "GLwDrawA.h"
+#endif
+
+typedef struct _GLwDrawingAreaClassPart {
+ caddr_t extension;
+ } GLwDrawingAreaClassPart;
+
+
+#ifdef __GLX_MOTIF
+typedef struct _GLwMDrawingAreaClassRec {
+ CoreClassPart core_class;
+ XmPrimitiveClassPart primitive_class;
+ GLwDrawingAreaClassPart glwDrawingArea_class;
+ } GLwMDrawingAreaClassRec;
+
+
+extern GLwMDrawingAreaClassRec glwMDrawingAreaClassRec;
+
+
+/* XT */
+#else
+
+typedef struct _GLwDrawingAreaClassRec {
+ CoreClassPart core_class;
+ GLwDrawingAreaClassPart glwDrawingArea_class;
+ } GLwDrawingAreaClassRec;
+
+extern GLwDrawingAreaClassRec glwDrawingAreaClassRec;
+
+
+#endif
+
+
+
+typedef struct {
+ /* resources */
+ int * attribList;
+ XVisualInfo * visualInfo;
+ Boolean myList; /* TRUE if we malloced the attribList*/
+ Boolean myVisual; /* TRUE if we created the visualInfo*/
+ Boolean installColormap;
+ Boolean allocateBackground;
+ Boolean allocateOtherColors;
+ Boolean installBackground;
+ XtCallbackList ginitCallback;
+ XtCallbackList resizeCallback;
+ XtCallbackList exposeCallback;
+ XtCallbackList inputCallback;
+ /* specific attributes; add as we get new attributes */
+ int bufferSize;
+ int level;
+ Boolean rgba;
+ Boolean doublebuffer;
+ Boolean stereo;
+ int auxBuffers;
+ int redSize;
+ int greenSize;
+ int blueSize;
+ int alphaSize;
+ int depthSize;
+ int stencilSize;
+ int accumRedSize;
+ int accumGreenSize;
+ int accumBlueSize;
+ int accumAlphaSize;
+ } GLwDrawingAreaPart;
+
+#ifdef __GLX_MOTIF
+
+typedef struct _GLwMDrawingAreaRec {
+ CorePart core;
+ XmPrimitivePart primitive;
+ GLwDrawingAreaPart glwDrawingArea;
+ } GLwMDrawingAreaRec;
+
+#else
+
+typedef struct _GLwDrawingAreaRec {
+ CorePart core;
+ GLwDrawingAreaPart glwDrawingArea;
+ } GLwDrawingAreaRec;
+
+#endif
+
+#endif
diff --git a/src/glw/GLwMDrawA.c b/src/glw/GLwMDrawA.c
new file mode 100644
index 0000000000..bdefe92a6d
--- /dev/null
+++ b/src/glw/GLwMDrawA.c
@@ -0,0 +1,41 @@
+/*
+ * (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.
+ */
+#ifndef __GLX_MOTIF
+#define __GLX_MOTIF 1
+#endif
+#include "GLwDrawA.c"
diff --git a/src/glw/GLwMDrawA.h b/src/glw/GLwMDrawA.h
new file mode 100644
index 0000000000..2e24589041
--- /dev/null
+++ b/src/glw/GLwMDrawA.h
@@ -0,0 +1,41 @@
+/*
+ * (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.
+ */
+#ifndef __GLX_MOTIF
+#define __GLX_MOTIF 1
+#endif
+#include "GLwDrawA.h"
diff --git a/src/glw/GLwMDrawAP.h b/src/glw/GLwMDrawAP.h
new file mode 100644
index 0000000000..a0a689bb99
--- /dev/null
+++ b/src/glw/GLwMDrawAP.h
@@ -0,0 +1,41 @@
+/*
+ * (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.
+ */
+#ifndef __GLX_MOTIF
+#define __GLX_MOTIF 1
+#endif
+#include "GLwDrawAP.h"
diff --git a/src/glw/Makefile b/src/glw/Makefile
new file mode 100644
index 0000000000..af55a1bf38
--- /dev/null
+++ b/src/glw/Makefile
@@ -0,0 +1,59 @@
+# Makefile for OpenGL widgets
+
+# NOTE: widget code is from SGI. See any of the .c or .h files for the
+# complete copyright. Mesa's GNU copyright DOES NOT apply to this widget
+# code.
+
+
+##### MACROS #####
+
+VPATH = RCS
+
+INCDIRS = -I../include -I/usr/include/Motif1.2 -I/usr/X11R6/include
+LIBDIR = ../lib
+
+SOURCES = GLwDrawA.c GLwMDrawA.c
+
+
+OBJECTS = $(SOURCES:.c=.o)
+
+
+
+##### RULES #####
+
+.c.o:
+ $(CC) -c $(INCDIRS) $(CFLAGS) $<
+
+
+
+##### TARGETS #####
+
+default:
+ @echo "Specify a target configuration"
+
+clean:
+ -rm *.o *~
+
+# The name of the library file comes from Make-config
+#XXX GLW_LIB = libGLw.a
+
+targets: $(LIBDIR)/$(GLW_LIB)
+
+
+# Make the library
+$(LIBDIR)/$(GLW_LIB): $(OBJECTS)
+ $(MAKELIB) $(GLW_LIB) $(MAJOR) $(MINOR) $(OBJECTS)
+ mv $(GLW_LIB)* $(LIBDIR)
+
+include ../Make-config
+
+include depend
+
+
+
+#
+# Run 'make depend' to update the dependencies if you change what's included
+# by any source file.
+#
+dep: $(SOURCES)
+ makedepend -fdepend -Y -I../include $(SOURCES)
diff --git a/src/glw/README b/src/glw/README
new file mode 100644
index 0000000000..545f8b2a4c
--- /dev/null
+++ b/src/glw/README
@@ -0,0 +1,56 @@
+
+
+ widgets README file
+
+
+This directory contains the source code for SGI's OpenGL Xt/Motif widgets,
+slightly modified by Jeroen van der Zijp to work better with Mesa.
+
+To compile the widget code (producing lib/libGLw.a) cd to the widgets/
+directory and type 'make <config>' where <config> is the system configuration
+you used to compile Mesa. This hasn't been tested on many systems so
+let us know if you have trouble.
+
+If you want to make a Linux ELF shared lib instead of the non-shared .a
+file see the notes in the Makefile.
+
+
+These files are NOT covered by Mesa's GNU copyright. The real copyright
+is as follows.
+
+
+ * (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.
diff --git a/src/glw/boilerplate.c b/src/glw/boilerplate.c
new file mode 100644
index 0000000000..c53a3fa735
--- /dev/null
+++ b/src/glw/boilerplate.c
@@ -0,0 +1,451 @@
+/*
+
+ BOILERPLATE
+
+ To get started with mixed model programming with Motif and OpenGL, this
+ boilerplate `application' might help get you started.
+
+ This program honors two environment variables:
+
+ SETVISUAL <id> Makes the application use the indicated visual,
+ instead of the one chosen by glxChooseVisual.
+
+ SAMEVISUAL Make the application use the same visual for the
+ GUI as for the 3D GL Widget.
+
+ The basic idea is to minimize colormap `flash' on systems with only one
+ hardware colormap, especially when focus shifts between several
+ of the application's windows, e.g. the about box.
+
+ If you have suggestions for improvements, please mail to:
+
+
+ Jeroen van der Zijp <jvz@cyberia.cfdrc.com>
+
+
+ Feel free to turn this into a useful program!!
+
+*/
+
+
+/*
+
+ This code is hereby placed under GNU GENERAL PUBLIC LICENSE.
+ Copyright (C) 1996 Jeroen van der Zijp <jvz@cyberia.cfdrc.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+/* Include the kitchen sink */
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/cursorfont.h>
+#include <X11/keysym.h>
+#include <Xm/Xm.h>
+#include <Xm/MainW.h>
+#include <Xm/RowColumn.h>
+#include <Xm/PushB.h>
+#include <Xm/CascadeB.h>
+#include <Xm/BulletinB.h>
+#include <Xm/DialogS.h>
+#include <Xm/Frame.h>
+#include <Xm/MessageB.h>
+#include <Xm/Form.h>
+#include <Xm/Separator.h>
+#include <Xm/MwmUtil.h>
+
+/* Now some good stuff */
+#include <GLwMDrawA.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <GL/glx.h>
+
+
+/* Stuff */
+Display *display;
+Visual *gui_visual;
+Colormap gui_colormap;
+Colormap gl_colormap;
+XVisualInfo *gl_visualinfo;
+XtAppContext app_context;
+Widget toplevel;
+Widget mainwindow;
+Widget menubar;
+Widget mainform;
+Widget mainframe;
+Widget glwidget;
+Widget button;
+Widget separator;
+GLXContext glx_context;
+
+#ifndef __cplusplus
+#define c_class class
+#endif
+
+/* Requested attributes; fix as you see fit */
+static int glxConfig[]={
+ GLX_RGBA,
+ GLX_DOUBLEBUFFER,
+ GLX_DEPTH_SIZE, 16,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ None
+ };
+
+
+/* Forwards */
+static void exposeCB(Widget w,XtPointer client_data,GLwDrawingAreaCallbackStruct *cbs);
+static void initCB(Widget w,XtPointer client_data,GLwDrawingAreaCallbackStruct *cbs);
+static void resizeCB(Widget w,XtPointer client_data,GLwDrawingAreaCallbackStruct *cbs);
+static void inputCB(Widget w,XtPointer client_data,GLwDrawingAreaCallbackStruct *cbs);
+static void byeCB(Widget w,XtPointer client_data,XtPointer call_data);
+static void aboutCB(Widget w,XtPointer client_data,XtPointer call_data);
+static char* showvisualclass(int cls);
+
+
+
+/* Sample application */
+int main(int argc, char *argv[]){
+ char *thevisual;
+ XVisualInfo vi;
+ int nvisinfos,visid,n;
+ Arg args[30];
+ Widget pane,cascade,but;
+
+ /*
+ ** Initialize toolkit
+ ** We do *not* use XtAppInitialize as we want to figure visual and
+ ** colormap BEFORE we create the top level shell!!!
+ */
+ XtToolkitInitialize();
+
+ /* Make application context */
+ app_context=XtCreateApplicationContext();
+
+ /* Try open display */
+ display=XtOpenDisplay(app_context,NULL,"boilerPlate","BoilerPlate",NULL,0,&argc,argv);
+
+ /* Report failure */
+ if(!display){
+ fprintf(stderr,"Unable to open the specified display.\n");
+ fprintf(stderr,"Set your `DISPLAY' environment variable properly or\n");
+ fprintf(stderr,"use the `xhost' command to authorize access to the display.\n");
+ exit(1);
+ }
+
+ /* Check for extension; for Mesa, this is always cool */
+ if(!glXQueryExtension(display,NULL,NULL)){
+ fprintf(stderr,"The specified display does not support the OpenGL extension\n");
+ exit(1);
+ }
+
+ /* Init with default visual and colormap */
+ gui_visual=DefaultVisual(display,0);
+ gui_colormap=DefaultColormap(display,0);
+ gl_colormap=DefaultColormap(display,0);
+
+ /* User insists on a specific visual */
+ if((thevisual=getenv("SETVISUAL"))!=NULL){
+ if(sscanf(thevisual,"%x",&visid)==1){
+ vi.visualid=visid;
+ gl_visualinfo=XGetVisualInfo(display,VisualIDMask,&vi,&nvisinfos);
+ }
+ else{
+ fprintf(stderr,"Please set the `SETVISUAL' variable in hexadecimal\n");
+ fprintf(stderr,"Use one of the Visual ID's reported by `xdpyinfo'\n");
+ exit(1);
+ }
+ }
+
+ /* Find visual the regular way */
+ else{
+ gl_visualinfo=glXChooseVisual(display,DefaultScreen(display),glxConfig);
+ }
+
+ /* Make sure we have a visual */
+ if(!gl_visualinfo){
+ fprintf(stderr,"Unable to obtain visual for graphics\n");
+ exit(1);
+ }
+
+ /* Show what visual is being used */
+ fprintf(stderr,"Using the following visual:\n");
+ fprintf(stderr," visualid: %lx\n",gl_visualinfo->visualid);
+ fprintf(stderr," depth: %d\n",gl_visualinfo->depth);
+ fprintf(stderr," screen: %d\n",gl_visualinfo->screen);
+ fprintf(stderr," bits/rgb: %d\n",gl_visualinfo->bits_per_rgb);
+ fprintf(stderr," class: %s\n",showvisualclass(gl_visualinfo->c_class));
+
+ /*
+ ** If not using default visual, we need a colormap for this visual.
+ ** Yes, the GL widget can allocate one itself, but we want to make
+ ** sure the GUI and the 3D have the same one (if hardware does not
+ ** allow more than one simultaneously).
+ ** This prevents nasty flashing when the window with the 3D widget
+ ** looses the focus.
+ */
+ if(gl_visualinfo->visual!=DefaultVisual(display,0)){
+ fprintf(stderr,"Making another colormap\n");
+ gl_colormap=XCreateColormap(display,
+ RootWindow(display,0),
+ gl_visualinfo->visual,
+ AllocNone);
+ if(!gl_colormap){
+ fprintf(stderr,"Unable to create private colormap\n");
+ exit(1);
+ }
+ }
+
+ /*
+ ** Use common visual for GUI and GL?
+ ** Maybe you can invoke some hardware interrogation function and
+ ** see if more than one hardware map is supported. For the purpose
+ ** of this demo, we'll use an environment variable instead.
+ */
+ if(getenv("SAMEVISUAL")!=NULL){
+ gui_visual=gl_visualinfo->visual;
+ gui_colormap=gl_colormap;
+ }
+
+ fprintf(stderr,"GUI uses visual: %lx\n",XVisualIDFromVisual(gui_visual));
+
+ /* Create application shell, finally */
+ n=0;
+ XtSetArg(args[n],XmNvisual,gui_visual); n++; /* Plug in that visual */
+ XtSetArg(args[n],XmNcolormap,gui_colormap); n++; /* And that colormap */
+ toplevel=XtAppCreateShell("boilerPlate","BoilerPlate",
+ applicationShellWidgetClass,display,args,n);
+
+
+ /* Main window */
+ n=0;
+ mainwindow=XmCreateMainWindow(toplevel,"window",args,n);
+ XtManageChild(mainwindow);
+
+ /* Make a menu */
+ n=0;
+ XtSetArg(args[n],XmNmarginWidth,0); n++;
+ XtSetArg(args[n],XmNmarginHeight,0); n++;
+ menubar=XmCreateMenuBar(mainwindow,"menubar",args,2);
+ XtManageChild(menubar);
+
+ n=0;
+ pane=XmCreatePulldownMenu(menubar,"pane",args,n);
+ n=0;
+ but=XmCreatePushButton(pane,"Open",args,n);
+ XtManageChild(but);
+ but=XmCreatePushButton(pane,"Save",args,n);
+ XtManageChild(but);
+ but=XmCreatePushButton(pane,"Save As",args,n);
+ XtManageChild(but);
+ but=XmCreatePushButton(pane,"Quit",args,n);
+ XtAddCallback(but,XmNactivateCallback,byeCB,(XtPointer)NULL);
+ XtManageChild(but);
+ XtSetArg(args[0],XmNsubMenuId,pane);
+ cascade=XmCreateCascadeButton(menubar,"File",args,1);
+ XtManageChild(cascade);
+
+ n=0;
+ pane=XmCreatePulldownMenu(menubar,"pane",args,n);
+ n=0;
+ but=XmCreatePushButton(pane,"About",args,n);
+ XtAddCallback(but,XmNactivateCallback,aboutCB,(XtPointer)NULL);
+ XtManageChild(but);
+ XtSetArg(args[0],XmNsubMenuId,pane);
+ cascade=XmCreateCascadeButton(menubar,"Help",args,1);
+ XtManageChild(cascade);
+ XtVaSetValues(menubar,XmNmenuHelpWidget,cascade,NULL);
+
+ /* Main window form */
+ n=0;
+ XtSetArg(args[n],XmNmarginWidth,5); n++;
+ XtSetArg(args[n],XmNmarginHeight,5); n++;
+ mainform=XmCreateForm(mainwindow,"mainForm",args,n);
+ XtManageChild(mainform);
+
+ /* Some nice button */
+ n=0;
+ XtSetArg(args[n],XmNbottomAttachment,XmATTACH_FORM); n++;
+ XtSetArg(args[n],XmNrightAttachment,XmATTACH_FORM); n++;
+ button=XmCreatePushButton(mainform,"Bye",args,n);
+ XtAddCallback(button,XmNactivateCallback,byeCB,(XtPointer)NULL);
+ XtManageChild(button);
+
+ n=0;
+ XtSetArg(args[n],XmNleftAttachment,XmATTACH_FORM); n++;
+ XtSetArg(args[n],XmNrightAttachment,XmATTACH_FORM); n++;
+ XtSetArg(args[n],XmNbottomAttachment,XmATTACH_WIDGET); n++;
+ XtSetArg(args[n],XmNbottomWidget,button); n++;
+ XtSetArg(args[n],XmNshadowType,XmSHADOW_ETCHED_IN); n++;
+ separator=XmCreateSeparator(mainform,"separator",args,n);
+ XtManageChild(separator);
+
+ /* Main window frame */
+ n = 0;
+ XtSetArg(args[n],XmNleftAttachment,XmATTACH_FORM); n++;
+ XtSetArg(args[n],XmNrightAttachment,XmATTACH_FORM); n++;
+ XtSetArg(args[n],XmNtopAttachment,XmATTACH_FORM); n++;
+ XtSetArg(args[n],XmNbottomAttachment,XmATTACH_WIDGET); n++;
+ XtSetArg(args[n],XmNbottomWidget,separator); n++;
+ XtSetArg(args[n],XmNshadowType,XmSHADOW_IN); n++;
+ mainframe = XmCreateFrame(mainform,"mainFrame",args,n);
+ XtManageChild(mainframe);
+
+ /* GL drawing area */
+ n = 0;
+ XtSetArg(args[n],XmNcolormap,gl_colormap); n++;
+ XtSetArg(args[n],GLwNvisualInfo,gl_visualinfo); n++;
+ XtSetArg(args[n],GLwNinstallColormap,True); n++;
+ XtSetArg(args[n],XmNtraversalOn,True); n++;
+ XtSetArg(args[n],XmNwidth,400); n++;
+ XtSetArg(args[n],XmNheight,300); n++;
+ glwidget = GLwCreateMDrawingArea(mainframe,"glWidget",args,n);
+ XtAddCallback(glwidget,GLwNexposeCallback,(XtCallbackProc)exposeCB,(XtPointer)NULL);
+ XtAddCallback(glwidget,GLwNresizeCallback,(XtCallbackProc)resizeCB,(XtPointer)NULL);
+ XtAddCallback(glwidget,GLwNginitCallback,(XtCallbackProc)initCB,(XtPointer)NULL);
+ XtAddCallback(glwidget,GLwNinputCallback,(XtCallbackProc)inputCB,(XtPointer)NULL);
+ XtManageChild(glwidget);
+
+ /* Set into main window */
+ XmMainWindowSetAreas(mainwindow,menubar,NULL,NULL,NULL,mainform);
+ XtRealizeWidget(toplevel);
+
+ /* Loop until were done */
+ XtAppMainLoop(app_context);
+ return 0;
+ }
+
+
+/* Show visual class */
+static char* showvisualclass(int cls){
+ if(cls==TrueColor) return "TrueColor";
+ if(cls==DirectColor) return "DirectColor";
+ if(cls==PseudoColor) return "PseudoColor";
+ if(cls==StaticColor) return "StaticColor";
+ if(cls==GrayScale) return "GrayScale";
+ if(cls==StaticGray) return "StaticGray";
+ return "Unknown";
+ }
+
+
+static void exposeCB(Widget w,XtPointer client_data,GLwDrawingAreaCallbackStruct *cbs){
+ GLwDrawingAreaMakeCurrent(glwidget,glx_context);
+
+ glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
+ glMatrixMode(GL_PROJECTION);
+
+ glLoadIdentity();
+ glOrtho(-1.0,1.0,-1.0,1.0,0.0,1.0);
+
+ glMatrixMode(GL_MODELVIEW);
+
+ glLoadIdentity();
+
+ glColor3f(1.0,0.0,0.0);
+ glBegin(GL_LINE_STRIP);
+ glVertex3f(-1.0,-1.0,0.0);
+ glVertex3f( 1.0, 1.0,0.0);
+ glEnd();
+ glXSwapBuffers(display,XtWindow(glwidget));
+ }
+
+
+/* Initialize widget */
+static void initCB(Widget w,XtPointer client_data,GLwDrawingAreaCallbackStruct *cbs){
+
+ /* First, create context. We prefer direct rendering */
+ glx_context=glXCreateContext(display,gl_visualinfo,0,TRUE);
+ if(!glx_context){
+ fprintf(stderr,"Unable to create gl context\n");
+ exit(1);
+ }
+
+ /* Make it current */
+ GLwDrawingAreaMakeCurrent(glwidget,glx_context);
+
+ /* Set a viewport */
+ glViewport(0,0,cbs->width,cbs->height);
+
+ /* You might want to do a lot more here ... */
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LEQUAL);
+ glClearColor(1.0,1.0,1.0,1.0);
+ glClearDepth(1.0);
+
+
+ }
+
+
+/* Widget changed size, so adjust txform */
+static void resizeCB(Widget w,XtPointer client_data,GLwDrawingAreaCallbackStruct *cbs){
+ GLwDrawingAreaMakeCurrent(glwidget,glx_context);
+ glViewport(0,0,cbs->width,cbs->height);
+
+ /* blablabla */
+ }
+
+
+/* Boilerplate event handling */
+static void inputCB(Widget w,XtPointer client_data,GLwDrawingAreaCallbackStruct *cbs){
+ switch(cbs->event->type){
+ case ButtonPress:
+ switch(cbs->event->xbutton.button){
+ case Button1: fprintf(stderr,"Pressed 1\n"); break;
+ case Button2: fprintf(stderr,"Pressed 2\n"); break;
+ case Button3: fprintf(stderr,"Pressed 3\n"); break;
+ }
+ break;
+ case ButtonRelease:
+ switch(cbs->event->xbutton.button){
+ case Button1: fprintf(stderr,"Released 1\n"); break;
+ case Button2: fprintf(stderr,"Released 2\n"); break;
+ case Button3: fprintf(stderr,"Released 3\n"); break;
+ }
+ break;
+ case MotionNotify:
+ fprintf(stderr,"Moved mouse to (%d %d)\n",
+ cbs->event->xbutton.x,
+ cbs->event->xbutton.y);
+ break;
+ }
+ }
+
+
+/* Hasta la vista, baby */
+static void byeCB(Widget w,XtPointer client_data,XtPointer call_data){
+ exit(0);
+ }
+
+
+/* Pop informative panel */
+static void aboutCB(Widget w,XtPointer client_data,XtPointer call_data){
+ Arg args[10];
+ XmString str;
+ Widget box;
+ str=XmStringCreateLtoR("Boilerplate Mixed Model Programming Example\n\n (C) 1996 Jeroen van der Zijp \n\n jvz@cyberia.cfdrc.com",XmSTRING_DEFAULT_CHARSET);
+ XtSetArg(args[0],XmNnoResize,True);
+ XtSetArg(args[1],XmNautoUnmanage,True);
+ XtSetArg(args[2],XmNmessageString,str);
+ XtSetArg(args[3],XmNdefaultPosition,False);
+ box=XmCreateInformationDialog(toplevel,"About Boilerplate",args,4);
+ XtManageChild(box);
+ XtUnmanageChild(XmMessageBoxGetChild(box,XmDIALOG_HELP_BUTTON));
+ XtUnmanageChild(XmMessageBoxGetChild(box,XmDIALOG_CANCEL_BUTTON));
+ XmStringFree(str);
+ }
diff --git a/src/glw/depend b/src/glw/depend
new file mode 100644
index 0000000000..e0c23de53d
--- /dev/null
+++ b/src/glw/depend
@@ -0,0 +1,6 @@
+# DO NOT DELETE
+
+GLwDrawA.o: ../include/GL/glx.h ../include/GL/gl.h ../include/GL/xmesa.h
+GLwDrawA.o: GLwDrawAP.h GLwDrawA.h
+GLwMDrawA.o: GLwDrawA.c ../include/GL/glx.h ../include/GL/gl.h
+GLwMDrawA.o: ../include/GL/xmesa.h GLwDrawAP.h GLwDrawA.h GLwMDrawAP.h
diff --git a/src/mesa/Makefile.X11 b/src/mesa/Makefile.X11
new file mode 100644
index 0000000000..e6419b555a
--- /dev/null
+++ b/src/mesa/Makefile.X11
@@ -0,0 +1,243 @@
+# $Id: Makefile.X11,v 1.1 1999/08/19 00:55:41 jtg Exp $
+
+# Mesa 3-D graphics library
+# Version: 3.1
+# Copyright (C) 1995-1999 Brian Paul
+
+# Makefile for core library
+
+
+##### MACROS #####
+
+VPATH = RCS
+
+INCDIR = ../include
+LIBDIR = ../lib
+
+CORE_SOURCES = \
+ accum.c \
+ alpha.c \
+ alphabuf.c \
+ api1.c \
+ api2.c \
+ apiext.c \
+ attrib.c \
+ bbox.c \
+ bitmap.c \
+ blend.c \
+ clip.c \
+ colortab.c \
+ config.c \
+ context.c \
+ copypix.c \
+ cva.c \
+ debug_xform.c \
+ depth.c \
+ dlist.c \
+ drawpix.c \
+ enable.c \
+ enums.c \
+ eval.c \
+ extensions.c \
+ feedback.c \
+ fog.c \
+ get.c \
+ hash.c \
+ image.c \
+ light.c \
+ lines.c \
+ logic.c \
+ masking.c \
+ matrix.c \
+ misc.c \
+ mmath.c \
+ mthreads.c \
+ pb.c \
+ pixel.c \
+ pipeline.c \
+ points.c \
+ pointers.c \
+ polygon.c \
+ quads.c \
+ rastpos.c \
+ readpix.c \
+ rect.c \
+ scissor.c \
+ shade.c \
+ span.c \
+ stages.c \
+ stencil.c \
+ teximage.c \
+ texobj.c \
+ texstate.c \
+ texture.c \
+ translate.c \
+ triangle.c \
+ varray.c \
+ vb.c \
+ vbcull.c \
+ vbfill.c \
+ vbindirect.c \
+ vbrender.c \
+ vbxform.c \
+ vector.c \
+ winpos.c \
+ xform.c \
+ zoom.c \
+ X86/x86.c \
+ X86/common_x86.c \
+ X86/3dnow.c
+
+DRIVER_SOURCES = \
+ X/glxapi.c \
+ X/fakeglx.c \
+ X/realglx.c \
+ X/xfonts.c \
+ X/xmesa1.c \
+ X/xmesa2.c \
+ X/xmesa3.c \
+ X/xmesa4.c \
+ OSmesa/osmesa.c \
+ SVGA/svgamesa.c \
+ FX/fxapi.c \
+ FX/fxclip.c \
+ FX/fxcva.c \
+ FX/fxdd.c \
+ FX/fxddspan.c \
+ FX/fxddtex.c \
+ FX/fxfastpath.c \
+ FX/fxpipeline.c \
+ FX/fxrender.c \
+ FX/fxsanity.c \
+ FX/fxsetup.c \
+ FX/fxtexman.c \
+ FX/fxtrifuncs.c \
+ FX/fxvsetup.c \
+ FX/fxglidew.c
+# GGI/ggimesa.c
+
+ASM_SOURCES =
+
+ADDITIONAL_OBJ =
+
+OBJECTS = $(ASM_SOURCES:.S=.o) \
+ $(CORE_SOURCES:.c=.o) \
+ $(DRIVER_SOURCES:.c=.o) \
+ $(ADDITIONAL_OBJ)
+
+
+#who put these here!?!
+#GL_LIB = libMesaGL.so
+#GLU_LIB = libMesaGLU.so
+#GLUT_LIB = libglut.so
+#CC = gcc
+#INCLUDES=-I. -I../include -I/usr/X11R6/include -I/usr/include/glide -I/usr/local/glide/include
+
+
+##### RULES #####
+
+.c.o:
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+
+.S.o:
+ $(CC) -c $(CFLAGS) $< -o $@
+
+
+# UGH! These rules shouldn't be needed but IRIX's make (and others?) needs them
+X/glxapi.o: X/glxapi.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+X/fakeglx.o: X/fakeglx.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+X/realglx.o: X/realglx.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+X/xfonts.o: X/xfonts.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+X/xmesa1.o: X/xmesa1.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+X/xmesa2.o: X/xmesa2.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+X/xmesa3.o: X/xmesa3.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+X/xmesa4.o: X/xmesa4.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+SVGA/svgamesa.o: SVGA/svgamesa.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+OSmesa/osmesa.o: OSmesa/osmesa.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxapi.o: FX/fxapi.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxclip.o: FX/fxclip.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxcva.o: FX/fxcva.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxdd.o: FX/fxdd.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxddspan.o: FX/fxddspan.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxddtex.o: FX/fxddtex.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxfastpath.o: FX/fxfastpath.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxpipeline.o: FX/fxpipeline.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxrender.o: FX/fxrender.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxsanity.o: FX/fxsanity.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxsetup.o: FX/fxsetup.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxtrifuncs.o: FX/fxtrifuncs.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxtexman.o: FX/fxtexman.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxvsetup.o: FX/fxvsetup.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxglidew.o: FX/fxglidew.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/X86/fx_3dnow_fastpath.o: FX/X86/fx_3dnow_fastpath.S FX/X86/fx_regoff.h
+FX/X86/fx_regoff.h: FX/X86/fx_gen_regoff
+ $< > $@
+FX/X86/fx_gen_regoff : FX/X86/fx_gen_regoff.c
+ $(CC) -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+GGI/ggimesa.o: GGI/ggimesa.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+X86/x86.o: X86/x86.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+X86/common_x86.o: X86/common_x86.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+X86/3dnow.o: X86/3dnow.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+
+
+##### TARGETS #####
+
+#default:
+# @echo "Specify a target configuration"
+
+clean:
+ -rm *.o *~ */*.o */*~
+
+targets: $(LIBDIR)/$(GL_LIB)
+
+# Make the library
+$(LIBDIR)/$(GL_LIB): $(OBJECTS)
+ $(MAKELIB) $(GL_LIB) $(MAJOR) $(MINOR) $(OBJECTS)
+ rm -f $(LIBDIR)/$(GL_LIB)*
+ mv $(GL_LIB)* $(LIBDIR)
+
+
+include ../Make-config
+
+include depend
+
+
+
+#
+# Run 'make dep' to update the dependencies if you change what's included
+# by any source file.
+#
+dep: $(CORE_SOURCES) $(DRIVER_SOURCES)
+ makedepend -fdepend -Y -I../include -DGGI -DSVGA -DFX $(CORE_SOURCES) $(DRIVER_SOURCES)
+
+tags:
+ etags `find . -name \*.[ch]` `find ../include`
diff --git a/src/mesa/drivers/allegro/amesa.c b/src/mesa/drivers/allegro/amesa.c
new file mode 100644
index 0000000000..6e0f21d804
--- /dev/null
+++ b/src/mesa/drivers/allegro/amesa.c
@@ -0,0 +1,395 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <allegro.h>
+#include "context.h"
+#include "matrix.h"
+#include "types.h"
+#include "GL/amesa.h"
+
+
+struct amesa_visual
+ {
+ GLvisual *GLVisual; /* inherit from GLvisual */
+ GLboolean DBFlag; /* double buffered? */
+ GLuint Depth; /* bits per pixel ( >= 15 ) */
+ };
+
+
+struct amesa_buffer
+ {
+ GLframebuffer *GLBuffer; /* inherit from GLframebuffer */
+ GLuint Width, Height;
+ BITMAP *Screen;
+ BITMAP *Background;
+ BITMAP *Active;
+ };
+
+
+struct amesa_context
+ {
+ GLcontext *GLContext; /* inherit from GLcontext */
+ AMesaVisual Visual;
+ AMesaBuffer Buffer;
+ GLuint ClearColor;
+ GLuint CurrentColor;
+ };
+
+
+static void setup_dd_pointers(GLcontext *ctx);
+
+
+/**********************************************************************/
+/***** drawing functions *****/
+/**********************************************************************/
+
+#define FLIP(context, y) (context->Buffer->Height - (y) - 1)
+
+#include "allegro/generic.h"
+#include "allegro/direct.h"
+
+
+/**********************************************************************/
+/***** 15-bit accelerated drawing funcs *****/
+/**********************************************************************/
+
+IMPLEMENT_WRITE_RGBA_SPAN(15, unsigned short)
+IMPLEMENT_WRITE_RGB_SPAN(15, unsigned short)
+IMPLEMENT_WRITE_MONO_RGBA_SPAN(15, unsigned short)
+IMPLEMENT_READ_RGBA_SPAN(15, unsigned short)
+IMPLEMENT_WRITE_RGBA_PIXELS(15, unsigned short)
+IMPLEMENT_WRITE_MONO_RGBA_PIXELS(15, unsigned short)
+IMPLEMENT_READ_RGBA_PIXELS(15, unsigned short)
+
+
+/**********************************************************************/
+/***** 16-bit accelerated drawing funcs *****/
+/**********************************************************************/
+
+IMPLEMENT_WRITE_RGBA_SPAN(16, unsigned short)
+IMPLEMENT_WRITE_RGB_SPAN(16, unsigned short)
+IMPLEMENT_WRITE_MONO_RGBA_SPAN(16, unsigned short)
+IMPLEMENT_READ_RGBA_SPAN(16, unsigned short)
+IMPLEMENT_WRITE_RGBA_PIXELS(16, unsigned short)
+IMPLEMENT_WRITE_MONO_RGBA_PIXELS(16, unsigned short)
+IMPLEMENT_READ_RGBA_PIXELS(16, unsigned short)
+
+
+/**********************************************************************/
+/***** 32-bit accelerated drawing funcs *****/
+/**********************************************************************/
+
+IMPLEMENT_WRITE_RGBA_SPAN(32, unsigned long)
+IMPLEMENT_WRITE_RGB_SPAN(32, unsigned long)
+IMPLEMENT_WRITE_MONO_RGBA_SPAN(32, unsigned long)
+IMPLEMENT_READ_RGBA_SPAN(32, unsigned long)
+IMPLEMENT_WRITE_RGBA_PIXELS(32, unsigned long)
+IMPLEMENT_WRITE_MONO_RGBA_PIXELS(32, unsigned long)
+IMPLEMENT_READ_RGBA_PIXELS(32, unsigned long)
+
+
+/**********************************************************************/
+/***** Miscellaneous device driver funcs *****/
+/**********************************************************************/
+
+static GLboolean set_buffer(GLcontext *ctx, GLenum mode)
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+ GLboolean ok = GL_TRUE;
+
+ if (mode == GL_FRONT_LEFT)
+ context->Buffer->Active = context->Buffer->Screen;
+
+ else if (mode == GL_BACK_LEFT)
+ {
+ if (context->Buffer->Background)
+ context->Buffer->Active = context->Buffer->Background;
+ else
+ ok = GL_FALSE;
+ }
+
+ else
+ ok = GL_FALSE;
+
+ return ok;
+ }
+
+
+static void get_buffer_size(GLcontext *ctx, GLuint *width, GLuint *height)
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+
+ *width = context->Buffer->Width;
+ *height = context->Buffer->Height;
+ }
+
+
+/**********************************************************************/
+/**********************************************************************/
+
+static void setup_dd_pointers(GLcontext *ctx)
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+
+ /* Initialize all the pointers in the driver struct. Do this whenever */
+ /* a new context is made current or we change buffers via set_buffer! */
+
+ ctx->Driver.UpdateState = setup_dd_pointers;
+ ctx->Driver.SetBuffer = set_buffer;
+ ctx->Driver.GetBufferSize = get_buffer_size;
+
+ ctx->Driver.Color = set_color_generic;
+ ctx->Driver.ClearColor = clear_color_generic;
+ ctx->Driver.Clear = clear_generic;
+ ctx->Driver.WriteRGBASpan = write_rgba_span_generic;
+ ctx->Driver.WriteRGBSpan = write_rgb_span_generic;
+ ctx->Driver.WriteMonoRGBASpan = write_mono_rgba_span_generic;
+ ctx->Driver.WriteRGBAPixels = write_rgba_pixels_generic;
+ ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels_generic;
+ ctx->Driver.ReadRGBASpan = read_rgba_span_generic;
+ ctx->Driver.ReadRGBAPixels = read_rgba_pixels_generic;
+
+ if (context->Buffer->Active != screen)
+ {
+ switch (context->Visual->Depth)
+ {
+ case 15:
+ ctx->Driver.WriteRGBASpan = write_rgba_span_15;
+ ctx->Driver.WriteRGBSpan = write_rgb_span_15;
+ ctx->Driver.WriteMonoRGBASpan = write_mono_rgba_span_15;
+ ctx->Driver.WriteRGBAPixels = write_rgba_pixels_15;
+ ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels_15;
+ ctx->Driver.ReadRGBASpan = read_rgba_span_15;
+ ctx->Driver.ReadRGBAPixels = read_rgba_pixels_15;
+ break;
+
+ case 16:
+ ctx->Driver.WriteRGBASpan = write_rgba_span_16;
+ ctx->Driver.WriteRGBSpan = write_rgb_span_16;
+ ctx->Driver.WriteMonoRGBASpan = write_mono_rgba_span_16;
+ ctx->Driver.WriteRGBAPixels = write_rgba_pixels_16;
+ ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels_16;
+ ctx->Driver.ReadRGBASpan = read_rgba_span_16;
+ ctx->Driver.ReadRGBAPixels = read_rgba_pixels_16;
+ break;
+
+ case 32:
+ ctx->Driver.WriteRGBASpan = write_rgba_span_32;
+ ctx->Driver.WriteRGBSpan = write_rgb_span_32;
+ ctx->Driver.WriteMonoRGBASpan = write_mono_rgba_span_32;
+ ctx->Driver.WriteRGBAPixels = write_rgba_pixels_32;
+ ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels_32;
+ ctx->Driver.ReadRGBASpan = read_rgba_span_32;
+ ctx->Driver.ReadRGBAPixels = read_rgba_pixels_32;
+ break;
+ }
+ }
+ }
+
+
+/**********************************************************************/
+/***** AMesa Public API Functions *****/
+/**********************************************************************/
+
+
+AMesaVisual AMesaCreateVisual(GLboolean dbFlag, GLint depth,
+ GLint depthSize, GLint stencilSize, GLint accumSize)
+ {
+ AMesaVisual visual;
+ GLbyte redBits, greenBits, blueBits;
+
+ visual = (AMesaVisual)calloc(1, sizeof(struct amesa_visual));
+ if (!visual)
+ return NULL;
+
+ switch (depth)
+ {
+ case 15:
+ redBits = 5;
+ greenBits = 5;
+ blueBits = 5;
+ break;
+
+ case 16:
+ redBits = 5;
+ greenBits = 6;
+ blueBits = 5;
+ break;
+
+ case 24: case 32:
+ redBits = 8;
+ greenBits = 8;
+ blueBits = 8;
+ break;
+
+ default:
+ free(visual);
+ return NULL;
+ }
+
+ visual->DBFlag = dbFlag;
+ visual->Depth = depth;
+ visual->GLVisual = gl_create_visual(GL_TRUE, /* rgb mode */
+ GL_TRUE, /* software alpha */
+ dbFlag, /* db_flag */
+ GL_FALSE, /* stereo */
+ depthSize, /* depth bits */
+ stencilSize,/* stencil bits */
+ accumSize, /* accum bits */
+ 0, /* index bits */
+ redBits, greenBits, blueBits, 0);
+ if (!visual->GLVisual)
+ {
+ free(visual);
+ return NULL;
+ }
+
+ return visual;
+ }
+
+
+void AMesaDestroyVisual(AMesaVisual visual)
+ {
+ gl_destroy_visual(visual->GLVisual);
+ free(visual);
+ }
+
+
+AMesaBuffer AMesaCreateBuffer(AMesaVisual visual,
+ GLint width, GLint height)
+ {
+ AMesaBuffer buffer;
+
+ buffer = (AMesaBuffer)calloc(1, sizeof(struct amesa_buffer));
+ if (!buffer)
+ return NULL;
+
+ buffer->Screen = NULL;
+ buffer->Background = NULL;
+ buffer->Active = NULL;
+ buffer->Width = width;
+ buffer->Height = height;
+
+ if (visual->DBFlag)
+ {
+ buffer->Background = create_bitmap_ex(visual->Depth, width, height);
+ if (!buffer->Background)
+ {
+ free(buffer);
+ return NULL;
+ }
+ }
+
+ buffer->GLBuffer = gl_create_framebuffer(visual->GLVisual);
+ if (!buffer->GLBuffer)
+ {
+ if (buffer->Background) destroy_bitmap(buffer->Background);
+ free(buffer);
+ return NULL;
+ }
+
+ return buffer;
+ }
+
+
+void AMesaDestroyBuffer(AMesaBuffer buffer)
+ {
+ if (buffer->Screen) destroy_bitmap(buffer->Screen);
+ if (buffer->Background) destroy_bitmap(buffer->Background);
+ gl_destroy_framebuffer(buffer->GLBuffer);
+ free(buffer);
+ }
+
+
+AMesaContext AMesaCreateContext(AMesaVisual visual,
+ AMesaContext share)
+ {
+ AMesaContext context;
+ GLboolean direct = GL_FALSE;
+
+ context = (AMesaContext)calloc(1, sizeof(struct amesa_context));
+ if (!context)
+ return NULL;
+
+ context->Visual = visual;
+ context->Buffer = NULL;
+ context->ClearColor = 0;
+ context->CurrentColor = 0;
+ context->GLContext = gl_create_context(visual->GLVisual,
+ share ? share->GLContext : NULL,
+ (void*)context,
+ direct);
+ if (!context->GLContext)
+ {
+ free(context);
+ return NULL;
+ }
+
+ return context;
+ }
+
+
+void AMesaDestroyContext(AMesaContext context)
+ {
+ gl_destroy_context(context->GLContext);
+ free(context);
+ }
+
+
+GLboolean AMesaMakeCurrent(AMesaContext context, AMesaBuffer buffer)
+ {
+ if (context && buffer)
+ {
+ set_color_depth(context->Visual->Depth);
+ if (set_gfx_mode(GFX_AUTODETECT, buffer->Width, buffer->Height, 0, 0) != 0)
+ return GL_FALSE;
+
+ context->Buffer = buffer;
+ buffer->Screen = screen;
+ buffer->Active = buffer->Background ? buffer->Background : screen;
+
+ setup_dd_pointers(context->GLContext);
+ gl_make_current(context->GLContext, buffer->GLBuffer);
+ gl_Viewport(context->GLContext, 0, 0, buffer->Width, buffer->Height);
+ }
+ else
+ {
+ destroy_bitmap(context->Buffer->Screen);
+ context->Buffer->Screen = NULL;
+ context->Buffer->Active = NULL;
+ context->Buffer = NULL;
+ gl_make_current(NULL, NULL);
+ }
+
+ return GL_TRUE;
+ }
+
+
+void AMesaSwapBuffers(AMesaBuffer buffer)
+ {
+ if (buffer->Background)
+ {
+ blit(buffer->Background, buffer->Screen,
+ 0, 0, 0, 0,
+ buffer->Width, buffer->Height);
+ }
+ }
diff --git a/src/mesa/drivers/allegro/direct.h b/src/mesa/drivers/allegro/direct.h
new file mode 100644
index 0000000000..3998fc19d7
--- /dev/null
+++ b/src/mesa/drivers/allegro/direct.h
@@ -0,0 +1,189 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.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.
+ */
+
+
+#define DESTINATION(BMP, X, Y, TYPE) \
+ ({ \
+ BITMAP *_bmp = BMP; \
+ \
+ (TYPE*)(_bmp->line[_bmp->h - (Y) - 1]) + (X); \
+ })
+
+
+#define IMPLEMENT_WRITE_RGBA_SPAN(DEPTH, TYPE) \
+static void write_rgba_span_##DEPTH (const GLcontext *ctx, \
+ GLuint n, GLint x, GLint y, \
+ const GLubyte rgba[][4], \
+ const GLubyte mask[]) \
+ { \
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx); \
+ TYPE *d = DESTINATION(context->Buffer->Active, x, y, TYPE); \
+ \
+ if (mask) \
+ { \
+ while (n--) \
+ { \
+ if (mask[0]) d[0] = makecol##DEPTH(rgba[0][RCOMP], rgba[0][GCOMP], rgba[0][BCOMP]); \
+ d++; rgba++; mask++; \
+ } \
+ } \
+ else \
+ { \
+ while (n--) \
+ { \
+ d[0] = makecol##DEPTH(rgba[0][RCOMP], rgba[0][GCOMP], rgba[0][BCOMP]); \
+ d++; rgba++; \
+ } \
+ } \
+ }
+
+
+#define IMPLEMENT_WRITE_RGB_SPAN(DEPTH, TYPE) \
+static void write_rgb_span_##DEPTH (const GLcontext *ctx, \
+ GLuint n, GLint x, GLint y, \
+ const GLubyte rgb[][3], \
+ const GLubyte mask[]) \
+ { \
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx); \
+ TYPE *d = DESTINATION(context->Buffer->Active, x, y, TYPE); \
+ \
+ if (mask) \
+ { \
+ while (n--) \
+ { \
+ if (mask[0]) d[0] = makecol##DEPTH(rgb[0][RCOMP], rgb[0][GCOMP], rgb[0][BCOMP]); \
+ d++; rgb++; mask++; \
+ } \
+ } \
+ else \
+ { \
+ while (n--) \
+ { \
+ d[0] = makecol##DEPTH(rgb[0][RCOMP], rgb[0][GCOMP], rgb[0][BCOMP]); \
+ d++; rgb++; \
+ } \
+ } \
+ }
+
+
+#define IMPLEMENT_WRITE_MONO_RGBA_SPAN(DEPTH, TYPE) \
+static void write_mono_rgba_span_##DEPTH (const GLcontext *ctx, \
+ GLuint n, GLint x, GLint y, \
+ const GLubyte mask[]) \
+ { \
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx); \
+ TYPE color = context->CurrentColor; \
+ TYPE *d = DESTINATION(context->Buffer->Active, x, y, TYPE); \
+ \
+ while (n--) \
+ { \
+ if (mask[0]) d[0] = color; \
+ d++; mask++; \
+ } \
+ }
+
+
+#define IMPLEMENT_READ_RGBA_SPAN(DEPTH, TYPE) \
+static void read_rgba_span_##DEPTH (const GLcontext *ctx, \
+ GLuint n, GLint x, GLint y, \
+ GLubyte rgba[][4]) \
+ { \
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx); \
+ BITMAP *bmp = context->Buffer->Active; \
+ TYPE *d = DESTINATION(bmp, x, y, TYPE); \
+ \
+ while (n--) \
+ { \
+ rgba[0][RCOMP] = getr##DEPTH(d[0]); \
+ rgba[0][GCOMP] = getg##DEPTH(d[0]); \
+ rgba[0][BCOMP] = getb##DEPTH(d[0]); \
+ rgba[0][ACOMP] = 255; \
+ \
+ d++; rgba++; \
+ } \
+ }
+
+
+#define IMPLEMENT_WRITE_RGBA_PIXELS(DEPTH, TYPE) \
+static void write_rgba_pixels_##DEPTH (const GLcontext *ctx, \
+ GLuint n, \
+ const GLint x[], \
+ const GLint y[], \
+ const GLubyte rgba[][4], \
+ const GLubyte mask[]) \
+ { \
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx); \
+ BITMAP *bmp = context->Buffer->Active; \
+ \
+ while (n--) \
+ { \
+ if (mask[0]) *DESTINATION(bmp, x[0], y[0], TYPE) = makecol##DEPTH(rgba[0][RCOMP], rgba[0][GCOMP], rgba[0][BCOMP]); \
+ rgba++; x++; y++; mask++; \
+ } \
+ }
+
+
+
+#define IMPLEMENT_WRITE_MONO_RGBA_PIXELS(DEPTH, TYPE) \
+static void write_mono_rgba_pixels_##DEPTH (const GLcontext *ctx, \
+ GLuint n, \
+ const GLint x[], \
+ const GLint y[], \
+ const GLubyte mask[]) \
+ { \
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx); \
+ TYPE color = context->CurrentColor; \
+ BITMAP *bmp = context->Buffer->Active; \
+ \
+ while (n--) \
+ { \
+ if (mask[0]) *DESTINATION(bmp, x[0], y[0], TYPE) = color; \
+ x++; y++; mask++; \
+ } \
+ }
+
+
+#define IMPLEMENT_READ_RGBA_PIXELS(DEPTH, TYPE) \
+static void read_rgba_pixels_##DEPTH (const GLcontext *ctx, \
+ GLuint n, \
+ const GLint x[], \
+ const GLint y[], \
+ GLubyte rgba[][4], \
+ const GLubyte mask[]) \
+ { \
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx); \
+ BITMAP *bmp = context->Buffer->Active; \
+ \
+ while (n--) \
+ { \
+ if (mask[0]) \
+ { \
+ int color = *DESTINATION(bmp, x[0], y[0], TYPE); \
+ \
+ rgba[0][RCOMP] = getr##DEPTH(color); \
+ rgba[0][GCOMP] = getg##DEPTH(color); \
+ rgba[0][BCOMP] = getb##DEPTH(color); \
+ rgba[0][ACOMP] = 255; \
+ } \
+ \
+ x++; y++; rgba++; mask++; \
+ } \
+ }
+
diff --git a/src/mesa/drivers/allegro/generic.h b/src/mesa/drivers/allegro/generic.h
new file mode 100644
index 0000000000..898a055d62
--- /dev/null
+++ b/src/mesa/drivers/allegro/generic.h
@@ -0,0 +1,233 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.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.
+ */
+
+static void clear_color_generic(GLcontext *ctx,
+ GLubyte red, GLubyte green,
+ GLubyte blue, GLubyte alpha)
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+
+ context->ClearColor = makecol(red, green, blue);
+ }
+
+
+static void set_color_generic(GLcontext *ctx,
+ GLubyte red, GLubyte green,
+ GLubyte blue, GLubyte alpha)
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+
+ context->CurrentColor = makecol(red, green, blue);
+ }
+
+
+static GLbitfield clear_generic(GLcontext *ctx,
+ GLbitfield mask, GLboolean all,
+ GLint x, GLint y,
+ GLint width, GLint height)
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+
+ if (mask & GL_COLOR_BUFFER_BIT)
+ {
+ if (all)
+ clear_to_color(context->Buffer->Active, context->ClearColor);
+ else
+ rect(context->Buffer->Active,
+ x, y, x+width-1, y+height-1,
+ context->ClearColor);
+ }
+
+ return mask & (~GL_COLOR_BUFFER_BIT);
+ }
+
+
+static void write_rgba_span_generic(const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4],
+ const GLubyte mask[])
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+ BITMAP *bmp = context->Buffer->Active;
+
+ y = FLIP(context, y);
+
+ if (mask)
+ {
+ while (n--)
+ {
+ if (mask[0]) putpixel(bmp, x, y, makecol(rgba[0][RCOMP], rgba[0][GCOMP], rgba[0][BCOMP]));
+ x++; mask++; rgba++;
+ }
+ }
+ else
+ {
+ while (n--)
+ {
+ putpixel(bmp, x, y, makecol(rgba[0][RCOMP], rgba[0][GCOMP], rgba[0][BCOMP]));
+ x++; rgba++;
+ }
+ }
+ }
+
+
+static void write_rgb_span_generic(const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgb[][3],
+ const GLubyte mask[])
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+ BITMAP *bmp = context->Buffer->Active;
+
+ y = FLIP(context, y);
+
+ if (mask)
+ {
+ while(n--)
+ {
+ if (mask[0]) putpixel(bmp, x, y, makecol(rgb[0][RCOMP], rgb[0][GCOMP], rgb[0][BCOMP]));
+ x++; mask++; rgb++;
+ }
+ }
+ else
+ {
+ while (n--)
+ {
+ putpixel(bmp, x, y, makecol(rgb[0][RCOMP], rgb[0][GCOMP], rgb[0][BCOMP]));
+ x++; rgb++;
+ }
+ }
+ }
+
+
+static void write_mono_rgba_span_generic(const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte mask[])
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+ BITMAP *bmp = context->Buffer->Active;
+ int color = context->CurrentColor;
+
+ y = FLIP(context, y);
+
+ if (mask)
+ {
+ while(n--)
+ {
+ if (mask[0]) putpixel(bmp, x, y, color);
+ x++; mask++;
+ }
+ }
+ else
+ {
+ while(n--)
+ {
+ putpixel(bmp, x, y, color);
+ x++;
+ }
+ }
+ }
+
+
+static void read_rgba_span_generic(const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4])
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+ BITMAP *bmp = context->Buffer->Active;
+
+ y = FLIP(context, y);
+
+ while (n--)
+ {
+ int color = getpixel(bmp, x, y);
+
+ rgba[0][RCOMP] = getr(color);
+ rgba[0][GCOMP] = getg(color);
+ rgba[0][BCOMP] = getb(color);
+ rgba[0][ACOMP] = 255;
+
+ x++; rgba++;
+ }
+ }
+
+
+static void write_rgba_pixels_generic(const GLcontext *ctx,
+ GLuint n,
+ const GLint x[],
+ const GLint y[],
+ const GLubyte rgba[][4],
+ const GLubyte mask[])
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+ BITMAP *bmp = context->Buffer->Active;
+
+ while (n--)
+ {
+ if (mask[0]) putpixel(bmp, x[0], FLIP(context, y[0]), makecol(rgba[0][RCOMP], rgba[0][GCOMP], rgba[0][BCOMP]));
+ x++; y++; mask++;
+ }
+ }
+
+
+static void write_mono_rgba_pixels_generic(const GLcontext *ctx,
+ GLuint n,
+ const GLint x[],
+ const GLint y[],
+ const GLubyte mask[])
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+ BITMAP *bmp = context->Buffer->Active;
+ int color = context->CurrentColor;
+
+ while (n--)
+ {
+ if (mask[0]) putpixel(bmp, x[0], FLIP(context, y[0]), color);
+ x++; y++; mask++;
+ }
+ }
+
+
+static void read_rgba_pixels_generic(const GLcontext *ctx,
+ GLuint n,
+ const GLint x[],
+ const GLint y[],
+ GLubyte rgba[][4],
+ const GLubyte mask[])
+ {
+ AMesaContext context = (AMesaContext)(ctx->DriverCtx);
+ BITMAP *bmp = context->Buffer->Active;
+
+ while (n--)
+ {
+ if (mask[0])
+ {
+ int color = getpixel(bmp, x[0], FLIP(context, y[0]));
+
+ rgba[0][RCOMP] = getr(color);
+ rgba[0][GCOMP] = getg(color);
+ rgba[0][BCOMP] = getb(color);
+ rgba[0][ACOMP] = 255;
+ }
+
+ x++; y++; mask++; rgba++;
+ }
+ }
+
diff --git a/src/mesa/drivers/beos/GLView.cpp b/src/mesa/drivers/beos/GLView.cpp
new file mode 100644
index 0000000000..4332f97b20
--- /dev/null
+++ b/src/mesa/drivers/beos/GLView.cpp
@@ -0,0 +1,1233 @@
+/* $Id: GLView.cpp,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+/*
+ * $Log: GLView.cpp,v $
+ * Revision 1.1 1999/08/19 00:55:41 jtg
+ * Initial revision
+ *
+ * Revision 1.7 1999/03/28 21:08:17 brianp
+ * updated SetBuffer driver function
+ *
+ * Revision 1.6 1999/02/14 03:44:37 brianp
+ * new copyright
+ *
+ * Revision 1.5 1999/02/11 03:50:57 brianp
+ * added CopySubBufferMESA()
+ *
+ * Revision 1.4 1999/02/06 17:44:59 brianp
+ * code clean-up and bug fixes
+ *
+ * Revision 1.3 1999/02/04 04:13:15 brianp
+ * implemented double buffering
+ *
+ * Revision 1.2 1999/02/03 04:23:28 brianp
+ * basic device driver functions now work (yeah!)
+ *
+ * Revision 1.1 1999/02/02 04:40:46 brianp
+ * Initial revision
+ */
+
+
+
+#include <assert.h>
+#include <stdio.h>
+#include <GLView.h>
+#include "../src/context.h"
+
+
+// BeOS component ordering for B_RGBA32 bitmap format
+#define BE_RCOMP 2
+#define BE_GCOMP 1
+#define BE_BCOMP 0
+#define BE_ACOMP 3
+
+
+//
+// This object hangs off of the BGLView object. We have to use
+// Be's BGLView class as-is to maintain binary compatibility (we
+// can't add new members to it). Instead we just put all our data
+// in this class and use BGLVIew::m_gc to point to it.
+//
+class AuxInfo
+{
+public:
+ AuxInfo();
+ ~AuxInfo();
+ void Init(BGLView *bglView, GLcontext *c, GLvisual *v, GLframebuffer *b);
+
+ void MakeCurrent();
+ void SwapBuffers() const;
+ void CopySubBuffer(GLint x, GLint y, GLuint width, GLuint height) const;
+
+private:
+ AuxInfo(const AuxInfo &rhs); // copy constructor illegal
+ AuxInfo &operator=(const AuxInfo &rhs); // assignment oper. illegal
+
+ GLcontext *mContext;
+ GLvisual *mVisual;
+ GLframebuffer *mBuffer;
+
+ BGLView *mBGLView;
+ BBitmap *mBitmap;
+
+ GLubyte mColor[4]; // current color
+ GLuint mIndex; // current color index
+ GLubyte mClearColor[4]; // buffer clear color
+ GLuint mClearIndex; // buffer clear color index
+ GLint mBottom; // used for flipping Y coords
+ GLint mWidth, mHeight; // size of buffer
+
+ // Mesa device driver functions
+ static void UpdateState(GLcontext *ctx);
+ static void ClearIndex(GLcontext *ctx, GLuint index);
+ static void ClearColor(GLcontext *ctx, GLubyte r, GLubyte g,
+ GLubyte b, GLubyte a);
+ static GLbitfield ClearFront(GLcontext *ctx, GLbitfield mask,
+ GLboolean all, GLint x, GLint y,
+ GLint width, GLint height);
+ static GLbitfield ClearBack(GLcontext *ctx, GLbitfield mask,
+ GLboolean all, GLint x, GLint y,
+ GLint width, GLint height);
+ static void Index(GLcontext *ctx, GLuint index);
+ static void Color(GLcontext *ctx, GLubyte r, GLubyte g,
+ GLubyte b, GLubyte a);
+ static GLboolean SetBuffer(GLcontext *ctx, GLenum mode);
+ static void GetBufferSize(GLcontext *ctgx, GLuint *width,
+ GLuint *height);
+ static const GLubyte *GetString(GLcontext *ctx, GLenum name);
+
+ // Front-buffer functions
+ static void WriteRGBASpanFront(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ CONST GLubyte rgba[][4],
+ const GLubyte mask[]);
+ static void WriteRGBSpanFront(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ CONST GLubyte rgba[][3],
+ const GLubyte mask[]);
+ static void WriteMonoRGBASpanFront(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y, const GLubyte mask[]);
+ static void WriteRGBAPixelsFront(const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ CONST GLubyte rgba[][4],
+ const GLubyte mask[]);
+ static void WriteMonoRGBAPixelsFront(const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ const GLubyte mask[]);
+ static void WriteCI32SpanFront(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ const GLuint index[], const GLubyte mask[]);
+ static void WriteCI8SpanFront(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ const GLubyte index[], const GLubyte mask[]);
+ static void WriteMonoCISpanFront(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y, const GLubyte mask[]);
+ static void WriteCI32PixelsFront(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLuint index[], const GLubyte mask[]);
+ static void WriteMonoCIPixelsFront(const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ const GLubyte mask[]);
+ static void ReadCI32SpanFront(const GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLuint index[]);
+ static void ReadRGBASpanFront(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ GLubyte rgba[][4]);
+ static void ReadCI32PixelsFront(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint indx[], const GLubyte mask[]);
+ static void ReadRGBAPixelsFront(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[]);
+
+ // Back buffer functions
+ static void WriteRGBASpanBack(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ CONST GLubyte rgba[][4],
+ const GLubyte mask[]);
+ static void WriteRGBSpanBack(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ CONST GLubyte rgba[][3],
+ const GLubyte mask[]);
+ static void WriteMonoRGBASpanBack(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y, const GLubyte mask[]);
+ static void WriteRGBAPixelsBack(const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ CONST GLubyte rgba[][4],
+ const GLubyte mask[]);
+ static void WriteMonoRGBAPixelsBack(const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ const GLubyte mask[]);
+ static void WriteCI32SpanBack(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ const GLuint index[], const GLubyte mask[]);
+ static void WriteCI8SpanBack(const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLubyte index[], const GLubyte mask[]);
+ static void WriteMonoCISpanBack(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ const GLubyte mask[]);
+ static void WriteCI32PixelsBack(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLuint index[], const GLubyte mask[]);
+ static void WriteMonoCIPixelsBack(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte mask[]);
+ static void ReadCI32SpanBack(const GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLuint index[]);
+ static void ReadRGBASpanBack(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ GLubyte rgba[][4]);
+ static void ReadCI32PixelsBack(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint indx[], const GLubyte mask[]);
+ static void ReadRGBAPixelsBack(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[]);
+
+};
+
+
+
+AuxInfo::AuxInfo()
+{
+ mContext = NULL;
+ mVisual = NULL;
+ mBuffer = NULL;
+ mBGLView = NULL;
+ mBitmap = NULL;
+ mClearColor[BE_RCOMP] = 0;
+ mClearColor[BE_GCOMP] = 0;
+ mClearColor[BE_BCOMP] = 0;
+ mClearColor[BE_ACOMP] = 0;
+ mClearIndex = 0;
+ mColor[BE_RCOMP] = 255;
+ mColor[BE_GCOMP] = 255;
+ mColor[BE_BCOMP] = 255;
+ mColor[BE_ACOMP] = 255;
+ mIndex = 1;
+}
+
+
+AuxInfo::~AuxInfo()
+{
+
+ gl_destroy_visual(mVisual);
+ gl_destroy_framebuffer(mBuffer);
+ gl_destroy_context(mContext);
+}
+
+
+void AuxInfo::Init(BGLView *bglView, GLcontext *c, GLvisual *v, GLframebuffer *b)
+{
+ mBGLView = bglView;
+ mContext = c;
+ mVisual = v;
+ mBuffer = b;
+}
+
+
+void AuxInfo::MakeCurrent()
+{
+ UpdateState(mContext);
+ gl_make_current(mContext, mBuffer);
+}
+
+
+void AuxInfo::SwapBuffers() const
+{
+ if (mBitmap) {
+ mBGLView->DrawBitmap(mBitmap, BPoint(0, 0));
+ }
+}
+
+
+void AuxInfo::CopySubBuffer(GLint x, GLint y, GLuint width, GLuint height) const
+{
+ if (mBitmap) {
+ // Source bitmap and view's bitmap are same size.
+ // Source and dest rectangle are the same.
+ // Note (x,y) = (0,0) is the lower-left corner, have to flip Y
+ BRect srcAndDest;
+ srcAndDest.left = x;
+ srcAndDest.right = x + width - 1;
+ srcAndDest.bottom = mBottom - y;
+ srcAndDest.top = srcAndDest.bottom - height + 1;
+ mBGLView->DrawBitmap(mBitmap, srcAndDest, srcAndDest);
+ }
+}
+
+
+void AuxInfo::UpdateState( GLcontext *ctx )
+{
+ AuxInfo *aux = (AuxInfo *) ctx->DriverCtx;
+
+ assert(aux->mContext == ctx );
+
+ ctx->Driver.UpdateState = AuxInfo::UpdateState;
+ ctx->Driver.SetBuffer = AuxInfo::SetBuffer;
+ ctx->Driver.Color = AuxInfo::Color;
+ ctx->Driver.Index = AuxInfo::Index;
+ ctx->Driver.ClearIndex = AuxInfo::ClearIndex;
+ ctx->Driver.ClearColor = AuxInfo::ClearColor;
+ ctx->Driver.GetBufferSize = AuxInfo::GetBufferSize;
+ ctx->Driver.GetString = AuxInfo::GetString;
+
+ if (ctx->Color.DrawBuffer == GL_FRONT) {
+ /* read/write front buffer */
+ ctx->Driver.Clear = AuxInfo::ClearFront;
+ ctx->Driver.WriteRGBASpan = AuxInfo::WriteRGBASpanFront;
+ ctx->Driver.WriteRGBSpan = AuxInfo::WriteRGBSpanFront;
+ ctx->Driver.WriteRGBAPixels = AuxInfo::WriteRGBAPixelsFront;
+ ctx->Driver.WriteMonoRGBASpan = AuxInfo::WriteMonoRGBASpanFront;
+ ctx->Driver.WriteMonoRGBAPixels = AuxInfo::WriteMonoRGBAPixelsFront;
+ ctx->Driver.WriteCI32Span = AuxInfo::WriteCI32SpanFront;
+ ctx->Driver.WriteCI8Span = AuxInfo::WriteCI8SpanFront;
+ ctx->Driver.WriteMonoCISpan = AuxInfo::WriteMonoCISpanFront;
+ ctx->Driver.WriteCI32Pixels = AuxInfo::WriteCI32PixelsFront;
+ ctx->Driver.WriteMonoCIPixels = AuxInfo::WriteMonoCIPixelsFront;
+ ctx->Driver.ReadRGBASpan = AuxInfo::ReadRGBASpanFront;
+ ctx->Driver.ReadRGBAPixels = AuxInfo::ReadRGBAPixelsFront;
+ ctx->Driver.ReadCI32Span = AuxInfo::ReadCI32SpanFront;
+ ctx->Driver.ReadCI32Pixels = AuxInfo::ReadCI32PixelsFront;
+ }
+ else {
+ /* read/write back buffer */
+ ctx->Driver.Clear = AuxInfo::ClearBack;
+ ctx->Driver.WriteRGBASpan = AuxInfo::WriteRGBASpanBack;
+ ctx->Driver.WriteRGBSpan = AuxInfo::WriteRGBSpanBack;
+ ctx->Driver.WriteRGBAPixels = AuxInfo::WriteRGBAPixelsBack;
+ ctx->Driver.WriteMonoRGBASpan = AuxInfo::WriteMonoRGBASpanBack;
+ ctx->Driver.WriteMonoRGBAPixels = AuxInfo::WriteMonoRGBAPixelsBack;
+ ctx->Driver.WriteCI32Span = AuxInfo::WriteCI32SpanBack;
+ ctx->Driver.WriteCI8Span = AuxInfo::WriteCI8SpanBack;
+ ctx->Driver.WriteMonoCISpan = AuxInfo::WriteMonoCISpanBack;
+ ctx->Driver.WriteCI32Pixels = AuxInfo::WriteCI32PixelsBack;
+ ctx->Driver.WriteMonoCIPixels = AuxInfo::WriteMonoCIPixelsBack;
+ ctx->Driver.ReadRGBASpan = AuxInfo::ReadRGBASpanBack;
+ ctx->Driver.ReadRGBAPixels = AuxInfo::ReadRGBAPixelsBack;
+ ctx->Driver.ReadCI32Span = AuxInfo::ReadCI32SpanBack;
+ ctx->Driver.ReadCI32Pixels = AuxInfo::ReadCI32PixelsBack;
+ }
+}
+
+
+void AuxInfo::ClearIndex(GLcontext *ctx, GLuint index)
+{
+ AuxInfo *aux = (AuxInfo *) ctx->DriverCtx;
+ aux->mClearIndex = index;
+}
+
+
+void AuxInfo::ClearColor(GLcontext *ctx, GLubyte r, GLubyte g,
+ GLubyte b, GLubyte a)
+{
+ AuxInfo *aux = (AuxInfo *) ctx->DriverCtx;
+ aux->mClearColor[BE_RCOMP] = r;
+ aux->mClearColor[BE_GCOMP] = g;
+ aux->mClearColor[BE_BCOMP] = b;
+ aux->mClearColor[BE_ACOMP] = a;
+ assert(aux->mBGLView);
+}
+
+
+GLbitfield AuxInfo::ClearFront(GLcontext *ctx, GLbitfield mask,
+ GLboolean all, GLint x, GLint y,
+ GLint width, GLint height)
+{
+ AuxInfo *aux = (AuxInfo *) ctx->DriverCtx;
+ BGLView *bglview = aux->mBGLView;
+ assert(bglview);
+
+ bglview->SetHighColor(aux->mClearColor[BE_RCOMP],
+ aux->mClearColor[BE_GCOMP],
+ aux->mClearColor[BE_BCOMP],
+ aux->mClearColor[BE_ACOMP]);
+ bglview->SetLowColor(aux->mClearColor[BE_RCOMP],
+ aux->mClearColor[BE_GCOMP],
+ aux->mClearColor[BE_BCOMP],
+ aux->mClearColor[BE_ACOMP]);
+ if (all) {
+ BRect b = bglview->Bounds();
+ bglview->FillRect(b);
+ }
+ else {
+ // XXX untested
+ BRect b;
+ b.left = x;
+ b.right = x + width;
+ b.bottom = aux->mHeight - y - 1;
+ b.top = b.bottom - height;
+ bglview->FillRect(b);
+ }
+
+ // restore drawing color
+ bglview->SetHighColor(aux->mColor[BE_RCOMP],
+ aux->mColor[BE_GCOMP],
+ aux->mColor[BE_BCOMP],
+ aux->mColor[BE_ACOMP]);
+ bglview->SetLowColor(aux->mColor[BE_RCOMP],
+ aux->mColor[BE_GCOMP],
+ aux->mColor[BE_BCOMP],
+ aux->mColor[BE_ACOMP]);
+
+ return mask & (~GL_COLOR_BUFFER_BIT);
+}
+
+
+GLbitfield AuxInfo::ClearBack(GLcontext *ctx, GLbitfield mask,
+ GLboolean all, GLint x, GLint y,
+ GLint width, GLint height)
+{
+ AuxInfo *aux = (AuxInfo *) ctx->DriverCtx;
+ BGLView *bglview = aux->mBGLView;
+ assert(bglview);
+ BBitmap *bitmap = aux->mBitmap;
+ assert(bitmap);
+ GLuint *start = (GLuint *) bitmap->Bits();
+ const GLuint *clearPixelPtr = (const GLuint *) aux->mClearColor;
+ const GLuint clearPixel = *clearPixelPtr;
+
+ if (all) {
+ const int numPixels = aux->mWidth * aux->mHeight;
+ if (clearPixel == 0) {
+ memset(start, 0, numPixels * 4);
+ }
+ else {
+ for (int i = 0; i < numPixels; i++) {
+ start[i] = clearPixel;
+ }
+ }
+ }
+ else {
+ // XXX untested
+ start += y * aux->mWidth + x;
+ for (int i = 0; i < height; i++) {
+ for (int j = 0; j < width; j++) {
+ start[j] = clearPixel;
+ }
+ start += aux->mWidth;
+ }
+ }
+
+ return mask & (~GL_COLOR_BUFFER_BIT);
+}
+
+
+void AuxInfo::Index(GLcontext *ctx, GLuint index)
+{
+ AuxInfo *aux = (AuxInfo *) ctx->DriverCtx;
+ BGLView *bglview = aux->mBGLView;
+ assert(bglview);
+ aux->mIndex = index;
+}
+
+
+void AuxInfo::Color(GLcontext *ctx, GLubyte r, GLubyte g,
+ GLubyte b, GLubyte a)
+{
+ AuxInfo *aux = (AuxInfo *) ctx->DriverCtx;
+ BGLView *bglview = aux->mBGLView;
+ assert(bglview);
+ aux->mColor[BE_RCOMP] = r;
+ aux->mColor[BE_GCOMP] = g;
+ aux->mColor[BE_BCOMP] = b;
+ aux->mColor[BE_ACOMP] = a;
+ bglview->SetHighColor(r, g, b, a);
+ bglview->SetLowColor(r, g, b, a);
+}
+
+GLboolean AuxInfo::SetBuffer(GLcontext *ctx, GLenum buffer)
+{
+ if (buffer == GL_FRONT_LEFT)
+ return GL_TRUE;
+ else if (buffer == GL_BACK_LEFT)
+ return GL_TRUE;
+ else
+ return GL_FALSE;
+}
+
+void AuxInfo::GetBufferSize(GLcontext *ctx, GLuint *width,
+ GLuint *height)
+{
+ AuxInfo *aux = (AuxInfo *) ctx->DriverCtx;
+ BGLView *bglview = aux->mBGLView;
+ assert(bglview);
+ BRect b = bglview->Bounds();
+ *width = (GLuint) (b.right - b.left + 1);
+ *height = (GLuint) (b.bottom - b.top + 1);
+ aux->mBottom = (GLint) b.bottom;
+
+ if (ctx->Visual->DBflag) {
+ if (*width != aux->mWidth || *height != aux->mHeight) {
+ // allocate new size of back buffer bitmap
+ if (aux->mBitmap)
+ delete aux->mBitmap;
+ BRect rect(0.0, 0.0, *width - 1, *height - 1);
+ aux->mBitmap = new BBitmap(rect, B_RGBA32);
+ }
+ }
+ else
+ {
+ aux->mBitmap = NULL;
+ }
+
+ aux->mWidth = *width;
+ aux->mHeight = *height;
+}
+
+
+const GLubyte *AuxInfo::GetString(GLcontext *ctx, GLenum name)
+{
+ switch (name) {
+ case GL_RENDERER:
+ return (const GLubyte *) "Mesa BeOS";
+ default:
+ // Let core library handle all other cases
+ return NULL;
+ }
+}
+
+
+// Plot a pixel. (0,0) is upper-left corner
+// This is only used when drawing to the front buffer.
+static void Plot(BGLView *bglview, int x, int y)
+{
+ // XXX There's got to be a better way!
+ BPoint p(x, y), q(x+1, y);
+ bglview->StrokeLine(p, q);
+}
+
+
+void AuxInfo::WriteRGBASpanFront(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ CONST GLubyte rgba[][4],
+ const GLubyte mask[])
+{
+ AuxInfo *aux = (AuxInfo *) ctx->DriverCtx;
+ BGLView *bglview = aux->mBGLView;
+ assert(bglview);
+ int flippedY = aux->mBottom - y;
+ if (mask) {
+ for (GLuint i = 0; i < n; i++) {
+ if (mask[i]) {
+ bglview->SetHighColor(rgba[i][0], rgba[i][1], rgba[i][2], rgba[i][3]);
+ Plot(bglview, x++, flippedY);
+ }
+ }
+ }
+ else {
+ for (GLuint i = 0; i < n; i++) {
+ bglview->SetHighColor(rgba[i][0], rgba[i][1], rgba[i][2], rgba[i][3]);
+ Plot(bglview, x++, flippedY);
+ }
+ }
+}
+
+void AuxInfo::WriteRGBSpanFront(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ CONST GLubyte rgba[][3],
+ const GLubyte mask[])
+{
+ AuxInfo *aux = (AuxInfo *) ctx->DriverCtx;
+ BGLView *bglview = aux->mBGLView;
+ assert(bglview);
+ int flippedY = aux->mBottom - y;
+ if (mask) {
+ for (GLuint i = 0; i < n; i++) {
+ if (mask[i]) {
+ bglview->SetHighColor(rgba[i][0], rgba[i][1], rgba[i][2]);
+ Plot(bglview, x++, flippedY);
+ }
+ }
+ }
+ else {
+ for (GLuint i = 0; i < n; i++) {
+ bglview->SetHighColor(rgba[i][0], rgba[i][1], rgba[i][2]);
+ Plot(bglview, x++, flippedY);
+ }
+ }
+}
+
+void AuxInfo::WriteMonoRGBASpanFront(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y, const GLubyte mask[])
+{
+ AuxInfo *aux = (AuxInfo *) ctx->DriverCtx;
+ BGLView *bglview = aux->mBGLView;
+ assert(bglview);
+ int flippedY = aux->mBottom - y;
+ if (mask) {
+ for (GLuint i = 0; i < n; i++) {
+ if (mask[i]) {
+ Plot(bglview, x++, flippedY);
+ }
+ }
+ }
+ else {
+ for (GLuint i = 0; i < n; i++) {
+ Plot(bglview, x++, flippedY);
+ }
+ }
+}
+
+void AuxInfo::WriteRGBAPixelsFront(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ CONST GLubyte rgba[][4],
+ const GLubyte mask[] )
+{
+ AuxInfo *aux = (AuxInfo *) ctx->DriverCtx;
+ BGLView *bglview = aux->mBGLView;
+ assert(bglview);
+ if (mask) {
+ for (GLuint i = 0; i < n; i++) {
+ if (mask[i]) {
+ bglview->SetHighColor(rgba[i][0], rgba[i][1], rgba[i][2]);
+ Plot(bglview, x[i], aux->mBottom - y[i]);
+ }
+ }
+ }
+ else {
+ for (GLuint i = 0; i < n; i++) {
+ bglview->SetHighColor(rgba[i][0], rgba[i][1], rgba[i][2]);
+ Plot(bglview, x[i], aux->mBottom - y[i]);
+ }
+ }
+}
+
+
+void AuxInfo::WriteMonoRGBAPixelsFront(const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ const GLubyte mask[])
+{
+ AuxInfo *aux = (AuxInfo *) ctx->DriverCtx;
+ BGLView *bglview = aux->mBGLView;
+ assert(bglview);
+ // plot points using current color
+ if (mask) {
+ for (GLuint i = 0; i < n; i++) {
+ if (mask[i]) {
+ Plot(bglview, x[i], aux->mBottom - y[i]);
+ }
+ }
+ }
+ else {
+ for (GLuint i = 0; i < n; i++) {
+ Plot(bglview, x[i], aux->mBottom - y[i]);
+ }
+ }
+}
+
+
+void AuxInfo::WriteCI32SpanFront( const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLuint index[], const GLubyte mask[] )
+{
+ // XXX to do
+}
+
+void AuxInfo::WriteCI8SpanFront( const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLubyte index[], const GLubyte mask[] )
+{
+ // XXX to do
+}
+
+void AuxInfo::WriteMonoCISpanFront( const GLcontext *ctx, GLuint n,
+ GLint x, GLint y, const GLubyte mask[] )
+{
+ // XXX to do
+}
+
+
+void AuxInfo::WriteCI32PixelsFront( const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ const GLuint index[], const GLubyte mask[] )
+{
+ // XXX to do
+}
+
+void AuxInfo::WriteMonoCIPixelsFront( const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ const GLubyte mask[] )
+{
+ // XXX to do
+}
+
+
+void AuxInfo::ReadCI32SpanFront( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLuint index[] )
+{
+ // XXX to do
+}
+
+
+void AuxInfo::ReadRGBASpanFront( const GLcontext *ctx, GLuint n,
+ GLint x, GLint y, GLubyte rgba[][4] )
+{
+ // XXX to do
+}
+
+
+void AuxInfo::ReadCI32PixelsFront( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint indx[], const GLubyte mask[] )
+{
+ // XXX to do
+}
+
+
+void AuxInfo::ReadRGBAPixelsFront( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[] )
+{
+ // XXX to do
+}
+
+
+
+
+void AuxInfo::WriteRGBASpanBack(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ CONST GLubyte rgba[][4],
+ const GLubyte mask[])
+{
+ AuxInfo *aux = (AuxInfo *) ctx->DriverCtx;
+ BBitmap *bitmap = aux->mBitmap;
+ assert(bitmap);
+ int row = aux->mBottom - y;
+ GLubyte *pixel = (GLubyte *) bitmap->Bits() + (row * aux->mWidth + x) * 4;
+ if (mask) {
+ for (GLuint i = 0; i < n; i++) {
+ if (mask[i]) {
+ pixel[BE_RCOMP] = rgba[i][RCOMP];
+ pixel[BE_GCOMP] = rgba[i][GCOMP];
+ pixel[BE_BCOMP] = rgba[i][BCOMP];
+ pixel[BE_ACOMP] = rgba[i][ACOMP];
+ }
+ pixel += 4;
+ }
+ }
+ else {
+ for (GLuint i = 0; i < n; i++) {
+ pixel[BE_RCOMP] = rgba[i][RCOMP];
+ pixel[BE_GCOMP] = rgba[i][GCOMP];
+ pixel[BE_BCOMP] = rgba[i][BCOMP];
+ pixel[BE_ACOMP] = rgba[i][ACOMP];
+ pixel += 4;
+ }
+ }
+}
+
+
+void AuxInfo::WriteRGBSpanBack(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ CONST GLubyte rgb[][3],
+ const GLubyte mask[])
+{
+ AuxInfo *aux = (AuxInfo *) ctx->DriverCtx;
+ BBitmap *bitmap = aux->mBitmap;
+ assert(bitmap);
+ int row = aux->mBottom - y;
+ GLubyte *pixel = (GLubyte *) bitmap->Bits() + (row * aux->mWidth + x) * 4;
+ if (mask) {
+ for (GLuint i = 0; i < n; i++) {
+ if (mask[i]) {
+ pixel[BE_RCOMP] = rgb[i][RCOMP];
+ pixel[BE_GCOMP] = rgb[i][GCOMP];
+ pixel[BE_BCOMP] = rgb[i][BCOMP];
+ pixel[BE_ACOMP] = 255;
+ }
+ pixel += 4;
+ }
+ }
+ else {
+ for (GLuint i = 0; i < n; i++) {
+ pixel[BE_RCOMP] = rgb[i][RCOMP];
+ pixel[BE_GCOMP] = rgb[i][GCOMP];
+ pixel[BE_BCOMP] = rgb[i][BCOMP];
+ pixel[BE_ACOMP] = 255;
+ pixel += 4;
+ }
+ }
+}
+
+
+void AuxInfo::WriteMonoRGBASpanBack(const GLcontext *ctx, GLuint n,
+ GLint x, GLint y, const GLubyte mask[])
+{
+ AuxInfo *aux = (AuxInfo *) ctx->DriverCtx;
+ BBitmap *bitmap = aux->mBitmap;
+ assert(bitmap);
+ int row = aux->mBottom - y;
+ GLuint *pixelPtr = (GLuint *) bitmap->Bits() + row * aux->mWidth + x;
+ const GLuint pixel = *((GLuint *) aux->mColor);
+ if (mask) {
+ for (GLuint i = 0; i < n; i++) {
+ if (mask[i])
+ *pixelPtr = pixel;
+ pixelPtr++;
+ }
+ }
+ else {
+ for (GLuint i = 0; i < n; i++) {
+ *pixelPtr++ = pixel;
+ }
+ }
+}
+
+
+void AuxInfo::WriteRGBAPixelsBack(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ CONST GLubyte rgba[][4],
+ const GLubyte mask[] )
+{
+ AuxInfo *aux = (AuxInfo *) ctx->DriverCtx;
+ BBitmap *bitmap = aux->mBitmap;
+ assert(bitmap);
+ if (mask) {
+ for (GLuint i = 0; i < n; i++) {
+ if (mask[i]) {
+ GLubyte *pixel = (GLubyte *) bitmap->Bits()
+ + (aux->mBottom - y[i]) * bitmap->BytesPerRow() + x[i] * 4;
+ pixel[BE_RCOMP] = rgba[i][RCOMP];
+ pixel[BE_GCOMP] = rgba[i][GCOMP];
+ pixel[BE_BCOMP] = rgba[i][BCOMP];
+ pixel[BE_ACOMP] = rgba[i][ACOMP];
+ }
+ }
+ }
+ else {
+ for (GLuint i = 0; i < n; i++) {
+ GLubyte *pixel = (GLubyte *) bitmap->Bits()
+ + (aux->mBottom - y[i]) * bitmap->BytesPerRow() + x[i] * 4;
+ pixel[BE_RCOMP] = rgba[i][RCOMP];
+ pixel[BE_GCOMP] = rgba[i][GCOMP];
+ pixel[BE_BCOMP] = rgba[i][BCOMP];
+ pixel[BE_ACOMP] = rgba[i][ACOMP];
+ }
+ }
+}
+
+
+void AuxInfo::WriteMonoRGBAPixelsBack(const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ const GLubyte mask[])
+{
+ AuxInfo *aux = (AuxInfo *) ctx->DriverCtx;
+ BBitmap *bitmap = aux->mBitmap;
+ assert(bitmap);
+ const GLuint pixel = *((GLuint *) aux->mColor);
+ if (mask) {
+ for (GLuint i = 0; i < n; i++) {
+ if (mask[i]) {
+ GLuint *pixelPtr = (GLuint *) bitmap->Bits()
+ + (aux->mBottom - y[i]) * aux->mWidth + x[i];
+ *pixelPtr = pixel;
+ }
+ }
+ }
+ else {
+ for (GLuint i = 0; i < n; i++) {
+ GLuint *pixelPtr = (GLuint *) bitmap->Bits()
+ + (aux->mBottom - y[i]) * aux->mWidth + x[i];
+ *pixelPtr = pixel;
+ }
+ }
+}
+
+
+void AuxInfo::WriteCI32SpanBack( const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ const GLuint index[], const GLubyte mask[] )
+{
+ // XXX to do
+}
+
+void AuxInfo::WriteCI8SpanBack( const GLcontext *ctx, GLuint n,
+ GLint x, GLint y,
+ const GLubyte index[], const GLubyte mask[] )
+{
+ // XXX to do
+}
+
+void AuxInfo::WriteMonoCISpanBack( const GLcontext *ctx, GLuint n,
+ GLint x, GLint y, const GLubyte mask[] )
+{
+ // XXX to do
+}
+
+
+void AuxInfo::WriteCI32PixelsBack( const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ const GLuint index[], const GLubyte mask[] )
+{
+ // XXX to do
+}
+
+void AuxInfo::WriteMonoCIPixelsBack( const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ const GLubyte mask[] )
+{
+ // XXX to do
+}
+
+
+void AuxInfo::ReadCI32SpanBack( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLuint index[] )
+{
+ // XXX to do
+}
+
+
+void AuxInfo::ReadRGBASpanBack( const GLcontext *ctx, GLuint n,
+ GLint x, GLint y, GLubyte rgba[][4] )
+{
+ AuxInfo *aux = (AuxInfo *) ctx->DriverCtx;
+ const BBitmap *bitmap = aux->mBitmap;
+ assert(bitmap);
+ int row = aux->mBottom - y;
+ const GLubyte *pixel = (GLubyte *) bitmap->Bits()
+ + row * bitmap->BytesPerRow() + x * 4;
+ for (GLuint i = 0; i < n; i++) {
+ rgba[i][RCOMP] = pixel[BE_RCOMP];
+ rgba[i][GCOMP] = pixel[BE_GCOMP];
+ rgba[i][BCOMP] = pixel[BE_BCOMP];
+ rgba[i][ACOMP] = pixel[BE_ACOMP];
+ pixel += 4;
+ }
+}
+
+
+void AuxInfo::ReadCI32PixelsBack( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint indx[], const GLubyte mask[] )
+{
+ // XXX to do
+}
+
+
+void AuxInfo::ReadRGBAPixelsBack( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[] )
+{
+ AuxInfo *aux = (AuxInfo *) ctx->DriverCtx;
+ const BBitmap *bitmap = aux->mBitmap;
+ assert(bitmap);
+ for (GLuint i = 0; i < n; i++) {
+ if (y[i] < aux->mHeight) {
+ const GLubyte *pixel = (const GLubyte *) bitmap->Bits()
+ + ((aux->mBottom - y[i]) * aux->mWidth + x[i]) * 4;
+ rgba[i][RCOMP] = pixel[BE_RCOMP];
+ rgba[i][GCOMP] = pixel[BE_GCOMP];
+ rgba[i][BCOMP] = pixel[BE_BCOMP];
+ rgba[i][ACOMP] = pixel[BE_ACOMP];
+ }
+ }
+}
+
+
+
+
+//------------------------------------------------------------------
+// Public interface methods
+//------------------------------------------------------------------
+
+
+//
+// Input: rect - initial rectangle
+// name - window name
+// resizingMode - example: B_FOLLOW_NONE
+// mode - usually 0 ?
+// options - Bitwise-OR of BGL_* tokens
+//
+BGLView::BGLView(BRect rect, char *name,
+ ulong resizingMode, ulong mode,
+ ulong options)
+ :BView(rect, name, resizingMode, mode)
+{
+ const GLboolean rgbFlag = (options & BGL_RGB) == BGL_RGB;
+ const GLboolean alphaFlag = (options & BGL_ALPHA) == BGL_ALPHA;
+ const GLboolean dblFlag = (options & BGL_DOUBLE) == BGL_DOUBLE;
+ const GLboolean stereoFlag = false;
+ const GLint depth = (options & BGL_DEPTH) ? 16 : 0;
+ const GLint stencil = (options & BGL_STENCIL) ? 8 : 0;
+ const GLint accum = (options & BGL_ACCUM) ? 16 : 0;
+ const GLint index = (options & BGL_INDEX) ? 32 : 0;
+ const GLint red = (options & BGL_RGB) ? 8 : 0;
+ const GLint green = (options & BGL_RGB) ? 8 : 0;
+ const GLint blue = (options & BGL_RGB) ? 8 : 0;
+ const GLint alpha = (options & BGL_RGB) ? 8 : 0;
+
+ if (!rgbFlag) {
+ fprintf(stderr, "Mesa Warning: color index mode not supported\n");
+ }
+
+ // Allocate auxiliary data object
+ AuxInfo *aux = new AuxInfo;
+
+ // examine option flags and create gl_context struct
+ GLvisual *visual = gl_create_visual( rgbFlag, alphaFlag,
+ dblFlag, stereoFlag,
+ depth, stencil, accum, index,
+ red, green, blue, alpha);
+
+ // create core framebuffer
+ GLframebuffer *buffer = gl_create_framebuffer(visual);
+
+ // create core context
+ const GLboolean direct = GL_TRUE;
+ GLcontext *ctx = gl_create_context( visual, NULL, aux, direct );
+
+ aux->Init(this, ctx, visual, buffer );
+
+ // Hook aux data into BGLView object
+ m_gc = aux;
+}
+
+
+BGLView::~BGLView()
+{
+ printf("BGLView destructor\n");
+ AuxInfo *aux = (AuxInfo *) m_gc;
+ assert(aux);
+ delete aux;
+}
+
+void BGLView::LockGL()
+{
+ AuxInfo *aux = (AuxInfo *) m_gc;
+ assert(aux);
+ aux->MakeCurrent();
+}
+
+void BGLView::UnlockGL()
+{
+ AuxInfo *aux = (AuxInfo *) m_gc;
+ assert(aux);
+ // Could call gl_make_current(NULL, NULL) but it would just
+ // hinder performance
+}
+
+void BGLView::SwapBuffers()
+{
+ AuxInfo *aux = (AuxInfo *) m_gc;
+ assert(aux);
+ aux->SwapBuffers();
+}
+
+
+void BGLView::CopySubBufferMESA(GLint x, GLint y, GLuint width, GLuint height)
+{
+ AuxInfo *aux = (AuxInfo *) m_gc;
+ assert(aux);
+ aux->CopySubBuffer(x, y, width, height);
+}
+
+
+BView *BGLView::EmbeddedView()
+{
+ // XXX to do
+
+}
+
+status_t BGLView::CopyPixelsOut(BPoint source, BBitmap *dest)
+{
+ // XXX to do
+}
+
+
+status_t BGLView::CopyPixelsIn(BBitmap *source, BPoint dest)
+{
+ // XXX to do
+}
+
+void BGLView::ErrorCallback(GLenum errorCode)
+{
+ // XXX to do
+}
+
+void BGLView::Draw(BRect updateRect)
+{
+// printf("BGLView draw\n");
+ // XXX to do
+}
+
+void BGLView::AttachedToWindow()
+{
+ BView::AttachedToWindow();
+
+ // don't paint window background white when resized
+ SetViewColor(B_TRANSPARENT_32_BIT);
+}
+
+void BGLView::AllAttached()
+{
+ BView::AllAttached();
+// printf("BGLView AllAttached\n");
+}
+
+void BGLView::DetachedFromWindow()
+{
+ BView::DetachedFromWindow();
+}
+
+void BGLView::AllDetached()
+{
+ BView::AllDetached();
+// printf("BGLView AllDetached");
+}
+
+void BGLView::FrameResized(float width, float height)
+{
+ return BView::FrameResized(width, height);
+}
+
+status_t BGLView::Perform(perform_code d, void *arg)
+{
+ return BView::Perform(d, arg);
+}
+
+
+status_t BGLView::Archive(BMessage *data, bool deep) const
+{
+ return BView::Archive(data, deep);
+}
+
+void BGLView::MessageReceived(BMessage *msg)
+{
+ BView::MessageReceived(msg);
+}
+
+void BGLView::SetResizingMode(uint32 mode)
+{
+ BView::SetResizingMode(mode);
+}
+
+void BGLView::Show()
+{
+// printf("BGLView Show\n");
+ BView::Show();
+}
+
+void BGLView::Hide()
+{
+// printf("BGLView Hide\n");
+ BView::Hide();
+}
+
+BHandler *BGLView::ResolveSpecifier(BMessage *msg, int32 index,
+ BMessage *specifier, int32 form,
+ const char *property)
+{
+ return BView::ResolveSpecifier(msg, index, specifier, form, property);
+}
+
+status_t BGLView::GetSupportedSuites(BMessage *data)
+{
+ return BView::GetSupportedSuites(data);
+}
+
+void BGLView::DirectConnected( direct_buffer_info *info )
+{
+ // XXX to do
+}
+
+void BGLView::EnableDirectMode( bool enabled )
+{
+ // XXX to do
+}
+
+
+
+//---- private methods ----------
+
+void BGLView::_ReservedGLView1() {}
+void BGLView::_ReservedGLView2() {}
+void BGLView::_ReservedGLView3() {}
+void BGLView::_ReservedGLView4() {}
+void BGLView::_ReservedGLView5() {}
+void BGLView::_ReservedGLView6() {}
+void BGLView::_ReservedGLView7() {}
+void BGLView::_ReservedGLView8() {}
+
+#if 0
+BGLView::BGLView(const BGLView &v)
+ : BView(v)
+{
+ // XXX not sure how this should work
+ printf("Warning BGLView::copy constructor not implemented\n");
+}
+#endif
+
+
+BGLView &BGLView::operator=(const BGLView &v)
+{
+ printf("Warning BGLView::operator= not implemented\n");
+}
+
+void BGLView::dither_front()
+{
+ // no-op
+}
+
+bool BGLView::confirm_dither()
+{
+ // no-op
+ return false;
+}
+
+void BGLView::draw(BRect r)
+{
+ // XXX no-op ???
+}
+
+/* Direct Window stuff */
+void BGLView::drawScanline( int x1, int x2, int y, void *data )
+{
+ // no-op
+}
+
+void BGLView::scanlineHandler(struct rasStateRec *state,
+ GLint x1, GLint x2)
+{
+ // no-op
+}
+
+void BGLView::lock_draw()
+{
+ // no-op
+}
+
+void BGLView::unlock_draw()
+{
+ // no-op
+}
+
+bool BGLView::validateView()
+{
+ // no-op
+ return true;
+}
+
diff --git a/src/mesa/drivers/d3d/D3DCAPS.CPP b/src/mesa/drivers/d3d/D3DCAPS.CPP
new file mode 100644
index 0000000000..53595f0c34
--- /dev/null
+++ b/src/mesa/drivers/d3d/D3DCAPS.CPP
@@ -0,0 +1,251 @@
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver Build 5 */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#include "D3DHAL.h"
+/*===========================================================================*/
+/* Macros. */
+/*===========================================================================*/
+#define SRCBLEND_MAP(gl,d3d,fall) if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwSrcBlendCaps & d3d ) \
+ { \
+ sprintf( buffer, "SRC Blend: %s -> %s", # gl, # d3d ); \
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), buffer )); \
+ pShared->dwSrcBlendCaps[index] = d3d; \
+ } \
+ else \
+ { \
+ sprintf( buffer, "SRC Blend: %s -> %s", # gl, # fall ); \
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), buffer )); \
+ pShared->dwSrcBlendCaps[index] = fall; \
+ }
+#define DSTBLEND_MAP(gl,d3d,fall) if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwDestBlendCaps & d3d ) \
+ { \
+ sprintf( buffer, "DST Blend: %s -> %s", # gl, # d3d ); \
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), buffer )); \
+ pShared->dwDestBlendCaps[index] = d3d; \
+ } \
+ else \
+ { \
+ sprintf( buffer, "DST Blend: %s -> %s", # gl, # fall ); \
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), buffer )); \
+ pShared->dwDestBlendCaps[index] = fall; \
+ }
+
+/*===========================================================================*/
+/* I use this function to handle the fact that the D3D texture blending and */
+/* OpenGL texture blending functions don't map one to one. Also there is the*/
+/* problem with cards not supporting all the D3D functions. So I use the CAPS*/
+/* of the card to make a table of functions that will have defaults for the */
+/* unsupported functions. */
+/* So first I fill the table with the fallback function then I check to see */
+/* if the card supports the requested function. If it does I replace the */
+/* default thats already in the array. Now order does matter as I used an */
+/* enum type in D3DShared.h so that the mapping would be a little easier. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void AlphaBlendTableHAL( PMESAD3DHAL pHAL )
+{
+ PMESAD3DSHARED pShared = &pHAL->shared;
+ int index;
+ char buffer[128];
+
+ DPF(( DBG_FUNC, "AlphaBlendTableHAL();" ));
+
+ /* Make the fallback for the Source blend. */
+ for( index = 0; index < 14; index++ )
+ {
+ switch( index )
+ {
+ case s_zero:
+ SRCBLEND_MAP( GL_ZERO, D3DBLEND_ZERO, D3DBLEND_ONE );
+ break;
+ case s_one:
+ SRCBLEND_MAP( GL_ONE, D3DBLEND_ONE, D3DBLEND_ONE );
+ break;
+ case s_dst_color:
+ SRCBLEND_MAP( GL_DST_COLOR, D3DBLEND_DESTCOLOR, D3DBLEND_ONE );
+ break;
+ case s_one_minus_dst_color:
+ SRCBLEND_MAP( GL_ONE_MINUS_DST_COLOR, D3DBLEND_INVDESTCOLOR, D3DBLEND_ONE );
+ break;
+ case s_src_alpha:
+ SRCBLEND_MAP( GL_SRC_ALPHA, D3DBLEND_SRCALPHA, D3DBLEND_ONE );
+ break;
+ case s_one_minus_src_alpha:
+ SRCBLEND_MAP( GL_ONE_MINUS_SRC_ALPHA, D3DBLEND_INVSRCALPHA, D3DBLEND_ONE );
+ break;
+ case s_dst_alpha:
+ SRCBLEND_MAP( GL_DST_ALPHA, D3DBLEND_DESTALPHA, D3DBLEND_ONE );
+ break;
+ case s_one_minus_dst_alpha:
+ SRCBLEND_MAP( GL_ONE_MINUS_DST_ALPHA, D3DBLEND_INVDESTALPHA, D3DBLEND_ONE );
+ break;
+ case s_src_alpha_saturate:
+ SRCBLEND_MAP( GL_SRC_ALPHA_SATURATE, D3DBLEND_SRCALPHASAT, D3DBLEND_ONE );
+ break;
+ case s_constant_color:
+ SRCBLEND_MAP( GL_CONSTANT_COLOR, D3DBLEND_SRCCOLOR, D3DBLEND_ONE );
+ break;
+ case s_one_minus_constant_color:
+ SRCBLEND_MAP( GL_ONE_MINUS_CONSTANT_COLOR, D3DBLEND_INVSRCCOLOR, D3DBLEND_ONE );
+ break;
+ case s_constant_alpha:
+ SRCBLEND_MAP( GL_CONSTANT_ALPHA, D3DBLEND_BOTHSRCALPHA, D3DBLEND_ONE );
+ break;
+ case s_one_minus_constant_alpha:
+ SRCBLEND_MAP( GL_ONE_MINUS_CONSTANT_ALPHA, D3DBLEND_BOTHINVSRCALPHA, D3DBLEND_ONE );
+ break;
+ }
+ }
+
+ /* Make the fallback for the Destination blend. */
+ for( index = 0; index < 14; index++ )
+ {
+ switch( index )
+ {
+ case d_zero:
+ DSTBLEND_MAP( GL_ZERO, D3DBLEND_ZERO, D3DBLEND_ONE );
+ break;
+ case d_one:
+ DSTBLEND_MAP( GL_ONE, D3DBLEND_ONE, D3DBLEND_ONE );
+ break;
+ case d_src_color:
+ DSTBLEND_MAP( GL_SRC_COLOR, D3DBLEND_SRCCOLOR, D3DBLEND_ONE );
+ break;
+ case d_one_minus_src_color:
+ DSTBLEND_MAP( GL_ONE_MINUS_SRC_COLOR, D3DBLEND_INVSRCCOLOR, D3DBLEND_ONE );
+ break;
+ case d_src_alpha:
+ DSTBLEND_MAP( GL_SRC_ALPHA, D3DBLEND_SRCALPHA, D3DBLEND_ONE );
+ break;
+ case d_one_minus_src_alpha:
+ DSTBLEND_MAP( GL_ONE_MINUS_SRC_ALPHA, D3DBLEND_INVSRCALPHA, D3DBLEND_ONE );
+ break;
+ case d_dst_alpha:
+ DSTBLEND_MAP( GL_DST_ALPHA, D3DBLEND_DESTALPHA, D3DBLEND_ONE );
+ break;
+ case d_one_minus_dst_alpha:
+ DSTBLEND_MAP( GL_ONE_MINUS_DST_ALPHA, D3DBLEND_INVDESTALPHA, D3DBLEND_ONE );
+ break;
+ case d_constant_color:
+ DSTBLEND_MAP( GL_CONSTANT_COLOR, D3DBLEND_DESTCOLOR, D3DBLEND_ONE );
+ break;
+ case d_one_minus_constant_color:
+ DSTBLEND_MAP( GL_ONE_MINUS_CONSTANT_COLOR, D3DBLEND_INVDESTCOLOR, D3DBLEND_ONE );
+ break;
+ case d_constant_alpha:
+ DSTBLEND_MAP( GL_CONSTANT_ALPHAR, D3DBLEND_BOTHSRCALPHA, D3DBLEND_ONE );
+ break;
+ case d_one_minus_constant_alpha:
+ DSTBLEND_MAP( GL_ONE_MINUS_CONSTANT_ALPHA, D3DBLEND_BOTHINVSRCALPHA, D3DBLEND_ONE );
+ break;
+ }
+ }
+
+ /* Make the fallbacks for the texture functions. */
+ for( index = 0; index < 4; index++ )
+ {
+ switch( index )
+ {
+ case d3dtblend_decal:
+ if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_DECAL )
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_DECAL -> D3DTBLEND_DECAL" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_DECAL;
+ }
+ else
+ {
+ if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_MODULATE )
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_DECAL -> D3DTBLEND_MODULATE" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_MODULATE;
+ }
+ else
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_DECAL -> D3DTBLEND_ADD" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_ADD;
+ }
+ }
+ break;
+ case d3dtblend_decalalpha:
+ if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_DECALALPHA )
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_DECALALPHA -> D3DTBLEND_DECALALPHA" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_DECALALPHA;
+ }
+ else
+ {
+ if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_DECAL )
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_DECALALPA -> D3DTBLEND_DECAL" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_DECAL;
+ }
+ else
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_DECALALPHA -> D3DTBLEND_ADD" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_ADD;
+ }
+ }
+ break;
+ case d3dtblend_modulate:
+ if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_MODULATE )
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_MODULATE -> D3DTBLEND_MODULATE" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_MODULATE;
+ }
+ else
+ {
+ if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_MODULATEALPHA )
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_MODULATE -> D3DTBLEND_MODULATEALPHA" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_MODULATEALPHA;
+ }
+ else if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_DECAL )
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_MODULATE -> D3DTBLEND_DECAL" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_DECAL;
+ }
+ else
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_MODULATE -> D3DTBLEND_ADD" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_ADD;
+ }
+ }
+ break;
+ case d3dtblend_modulatealpha:
+ if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_MODULATEALPHA )
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_MODULATEALPHA -> D3DTBLEND_MODULATEALPHA" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_MODULATEALPHA;
+ }
+ else
+ {
+ if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_MODULATE )
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_MODULATEALPHA -> D3DTBLEND_MODULATE" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_MODULATE;
+ }
+ else if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureBlendCaps & D3DTBLEND_DECAL )
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_MODULATEALPHA -> D3DTBLEND_DECALE" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_DECAL;
+ }
+ else
+ {
+ DPF(( (DBG_CNTX_INFO|DBG_TXT_INFO), "D3DTBLEND_MODULATEALPHA -> D3DTBLEND_ADD" ));
+ pShared->dwTexFunc[index] = D3DTBLEND_ADD;
+ }
+ }
+ break;
+ }
+ }
+}
+
+ \ No newline at end of file
diff --git a/src/mesa/drivers/d3d/D3DHAL.H b/src/mesa/drivers/d3d/D3DHAL.H
new file mode 100644
index 0000000000..12f4b4e728
--- /dev/null
+++ b/src/mesa/drivers/d3d/D3DHAL.H
@@ -0,0 +1,69 @@
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#ifndef _D3D_HAL_INC
+#define _D3D_HAL_INC
+
+/*===========================================================================*/
+/* Includes. */
+/*===========================================================================*/
+#include <windows.h>
+#include <ddraw.h>
+#include <d3d.h>
+#include <stdlib.h>
+#include <time.h>
+#include "D3DShared.h"
+#include "D3DTextureMgr.h"
+#include "Debug.h"
+/*===========================================================================*/
+/* Defines. */
+/*===========================================================================*/
+#define DX_RESTORE(ps) if ( (ps) && (ps)->IsLost() ) (ps)->Restore();
+/*===========================================================================*/
+/* Type defines. */
+/*===========================================================================*/
+typedef struct _d3d_hal_struct
+{
+ MESAD3DSHARED shared;
+
+ GUID guid;
+ LPDIRECTDRAW lpDD;
+ LPDIRECTDRAW4 lpDD4;
+ LPDIRECT3D3 lpD3D3;
+ LPDIRECT3DDEVICE3 lpD3DDevice;
+ D3DDEVICEDESC D3DHWDevDesc;
+ LPDIRECTDRAWSURFACE4 lpDDSPrimary,
+ lpDDSRender,
+ lpDDSZbuffer;
+ LPDIRECT3DVIEWPORT3 lpViewport;
+ LPDIRECTDRAWCLIPPER lpClipper;
+ DDPIXELFORMAT ddpf,
+ ddpfZBuffer;
+ PTM_OBJECT pTMList;
+
+} MESAD3DHAL, *PMESAD3DHAL;
+/*===========================================================================*/
+/* External function prototypes. */
+/*===========================================================================*/
+extern BOOL InitTMgrHAL( PMESAD3DHAL pHAL );
+extern void TermTMgrHAL( PMESAD3DHAL pHAL );
+extern void AlphaBlendTableHAL( PMESAD3DHAL pHAL );
+
+extern void Solve8BitChannelPixelFormat( DDPIXELFORMAT *pddpf, PPIXELINFO pPixel );
+extern char *ErrorStringD3D( HRESULT hr );
+extern void FatalShutDown( PMESAD3DHAL pHAL );
+/*===========================================================================*/
+/* Global variables. */
+/*===========================================================================*/
+extern char *errorMsg;
+
+#endif
+
+ \ No newline at end of file
diff --git a/src/mesa/drivers/d3d/D3DInit.cpp b/src/mesa/drivers/d3d/D3DInit.cpp
new file mode 100644
index 0000000000..ba7891612e
--- /dev/null
+++ b/src/mesa/drivers/d3d/D3DInit.cpp
@@ -0,0 +1,891 @@
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver Build 5 */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#include "D3DHAL.h"
+/*===========================================================================*/
+/* Local function prototypes. */
+/*===========================================================================*/
+static void DestroyAllSurfaces( PMESAD3DHAL pHAL );
+static void DestroyDevice( PMESAD3DHAL pHAL );
+static void DestroyInterfaces( PMESAD3DHAL pHAL );
+
+HRESULT WINAPI EnumSurfacesHook( LPDIRECTDRAWSURFACE4 lpDDS, LPDDSURFACEDESC2 lpDDSDesc, LPVOID pVoid );
+HRESULT CALLBACK EnumZBufferHook( DDPIXELFORMAT* pddpf, VOID *pVoid );
+HRESULT CALLBACK EnumDeviceHook( GUID FAR* lpGuid, LPSTR lpDesc, LPSTR lpName, LPD3DDEVICEDESC lpD3DHWDesc, LPD3DDEVICEDESC lpD3DHELDesc, void *pVoid );
+/*===========================================================================*/
+/* Globals. */
+/*===========================================================================*/
+//char *errorMsg;
+/*===========================================================================*/
+/* This function is responable for allocating the actual MESAD3DHAL struct. */
+/* Each Mesa context will have its own MESAD3DHAL struct so its like a mini */
+/* context to some extent. All one time allocations/operations get done here.*/
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+extern "C" PMESAD3DSHARED InitHAL( HWND hwnd )
+{
+ PMESAD3DHAL pHAL;
+ ULONG rc;
+
+ DPF(( DBG_FUNC, "InitHAL();" ));
+ DPF(( DBG_CNTX_INFO, "hwnd: %d", hwnd ));
+
+ /* Allocate the structure and zero it out. */
+ pHAL = (PMESAD3DHAL)ALLOC( sizeof(MESAD3DHAL) );
+ if ( pHAL == NULL )
+ {
+ RIP( pHAL, "InitHAL->", "Memory Allocation" );
+ return (PMESAD3DSHARED)NULL;
+ }
+ memset( pHAL, 0, sizeof(MESAD3DHAL) );
+
+ /* Get the texture manager going. */
+ rc = InitTMgrHAL( pHAL );
+ if ( rc == FALSE )
+ {
+ RIP( pHAL, "InitTMgrHAL->", "Failed" );
+ return (PMESAD3DSHARED)NULL;
+ }
+
+ /* Fill in the window parameters if we can. */
+ pHAL->shared.hwnd = hwnd;
+
+ /* Parse the user's enviroment variables to generate a debug mask. */
+ ReadDBGEnv();
+
+ return (PMESAD3DSHARED)pHAL;
+}
+/*===========================================================================*/
+/* This function will unload all the resources that the MESAD3DHAL struct */
+/* has bound to it. The actual structure itself will be freed. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" void TermHAL( PMESAD3DSHARED pShared )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+
+ DPF(( DBG_FUNC, "TermHAL();" ));
+
+ /* Check for an empty wrapper structure. */
+ if ( pHAL == NULL )
+ return;
+
+ /* Kill this texture manager. */
+ TermTMgrHAL( pHAL );
+
+ /* Kill any DDraw stuff if exists. */
+ DestroyDevice( pHAL );
+ DestroyAllSurfaces( pHAL );
+ DestroyInterfaces( pHAL );
+
+ FREE( pHAL );
+}
+/*===========================================================================*/
+/* This function is used to init and resize the rendering surface as the two*/
+/* are almost the same. First the device and all the surfaces are destoryed */
+/* if they already exist. Next we create a OffScreen rendering surface and */
+/* save some pixelformat info to do color convertions. Next we start to take */
+/* care of getting the most out of the hardware. I use bHardware to determine*/
+/* the state of the device we found in the device enumeration. The enum proc*/
+/* will try for hardware first. I next use a bForceSW to make the enum proc */
+/* choose a software device. So I will try some combinations with HW first */
+/* until I feel I have to set the bForceSW and call this function again. If */
+/* this function is called with no width or height then use the internals. */
+/* NOTE: The worst case is that all will be in SW (RGBDevice) and really */
+/* I should forget the whole thing and fall back to a DDraw span type*/
+/* rendering but what is the point. This way I always know I have a */
+/* D3DDevice and that makes things easier. I do impliment the span */
+/* rendering function for stuff that I haven't done support for such */
+/* as points and lines. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE */
+/*===========================================================================*/
+extern "C" BOOL CreateHAL( PMESAD3DSHARED pShared )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+ DDSURFACEDESC2 ddsd2;
+ D3DDEVICEDESC D3DSWDevDesc;
+ DDSCAPS2 ddscaps;
+ DWORD dwCoopFlags,
+ dwWidth,
+ dwHeight;
+ ULONG rc;
+
+ DPF(( DBG_FUNC, "CreateHAL();" ));
+
+#define InitDDSD2(f) memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) ); \
+ ddsd2.dwSize = sizeof( DDSURFACEDESC2 ); \
+ ddsd2.dwFlags = f;
+
+ if ( pHAL == NULL )
+ return FALSE;
+
+ /* Use the internal rectangle struct. */
+ dwWidth = pShared->rectW.right - pShared->rectW.left;
+ dwHeight = pShared->rectW.bottom - pShared->rectW.top;
+
+ DPF(( DBG_CNTX_INFO, "Width: %d Height: %d", dwWidth, dwHeight ));
+
+ /* The dimensions might still be the same so just leave. */
+ if ( (dwWidth == pShared->dwWidth) && (dwHeight == pShared->dwHeight) )
+ {
+ DPF(( DBG_CNTX_WARN, "Context size hasn't changed" ));
+ return TRUE;
+ }
+
+ /* If one of the dimensions are zero then leave. WM_SIZE should get us back here. */
+ if ( (dwWidth == 0) || (dwHeight == 0) )
+ return TRUE;
+
+ /* Save the renders dimensions. */
+ pShared->dwWidth = dwWidth;
+ pShared->dwHeight = dwHeight;
+
+ DPF(( DBG_CNTX_INFO, "Creating Context:\n cx:%d cy:%d", pShared->dwWidth, pShared->dwHeight ));
+
+ /*=================================*/
+ /* Create all required interfaces. */
+ /*=================================*/
+
+ /* Kill any DDraw stuff if exists. */
+ DestroyDevice( pHAL );
+ DestroyAllSurfaces( pHAL );
+ DestroyInterfaces( pHAL );
+
+ /* Create a instance of DDraw using the Primary display driver. */
+ rc = DirectDrawCreate( NULL, &pHAL->lpDD, NULL );
+ if( FAILED(rc) )
+ {
+ RIP( pHAL, "DirectDrawCreate->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Get the DDraw4 interface. */
+ rc = pHAL->lpDD->QueryInterface( IID_IDirectDraw4, (void **)&pHAL->lpDD4 );
+ if( FAILED(rc) )
+ {
+ RIP( pHAL, "QueryInterface (IID_IDirectDraw4) ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Get the Direct3D3 interface. */
+ rc = pHAL->lpDD4->QueryInterface( IID_IDirect3D3, (void **)&pHAL->lpD3D3 );
+ if( FAILED(rc) )
+ {
+ RIP( pHAL, "QueryInterface (IID_IDirect3D3) ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Set the Cooperative level. NOTE: we need to know if we are FS at this point.*/
+ dwCoopFlags = (pShared->bWindow == TRUE) ? DDSCL_NORMAL : (DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
+ rc = pHAL->lpDD4->SetCooperativeLevel( pShared->hwnd, dwCoopFlags );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "SetCooperativeLevel->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /*==================================================================*/
+ /* Get the best device we can and note whether its hardware or not. */
+ /*==================================================================*/
+ pShared->bForceSW = FALSE;
+ pHAL->lpD3D3->EnumDevices( EnumDeviceHook, (void *)pHAL );
+ pShared->bHardware = IsEqualIID( pHAL->guid, IID_IDirect3DHALDevice );
+ DPF(( DBG_CNTX_INFO, "bHardware: %s", (pShared->bHardware) ? "TRUE" : "FALSE" ));
+ DPF(( DBG_CNTX_INFO, "bWindowed: %s", (pShared->bWindow) ? "TRUE" : "FALSE" ));
+
+ /*========================================================================*/
+ /* HARDWARE was found. */
+ /*========================================================================*/
+ if ( pShared->bHardware == TRUE )
+ {
+ /*===================================*/
+ /* HARDWARE -> Z-BUFFER. */
+ /*===================================*/
+
+ /* Get a Z-Buffer pixelformat. */
+ memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
+ ddsd2.dwSize = sizeof( DDSURFACEDESC2 );
+ rc = pHAL->lpD3D3->EnumZBufferFormats( pHAL->guid, EnumZBufferHook, (VOID*)&ddsd2.ddpfPixelFormat );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "EnumZBufferFormatsl->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Setup our request structure for the Z-buffer surface. */
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_ZBUFFER | DDSCAPS_VIDEOMEMORY;
+ ddsd2.dwWidth = dwWidth;
+ ddsd2.dwHeight = dwHeight;
+ rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSZbuffer, NULL );
+ if ( !FAILED(rc) )
+ {
+ DPF(( DBG_CNTX_INFO, "HW ZBuffer" ));
+
+ /*===================================*/
+ /* HARDWARE -> Z-BUFFER -> FLIPABLE */
+ /*===================================*/
+ if ( pShared->bWindow == FALSE )
+ {
+ InitDDSD2( DDSD_CAPS | DDSD_BACKBUFFERCOUNT );
+ ddsd2.dwBackBufferCount = 1;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
+ rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSPrimary, NULL );
+ if ( FAILED(rc) )
+ {
+ /* Make sure we try the next fall back. */
+ DPF(( DBG_CNTX_WARN, "HW Flip/Complex not available" ));
+ pHAL->lpDDSPrimary = NULL;
+ }
+ else
+ {
+ /* Get the back buffer that was created. */
+ ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
+ rc = pHAL->lpDDSPrimary->GetAttachedSurface( &ddscaps, &pHAL->lpDDSRender );
+ if ( FAILED(rc) )
+ {
+ DPF(( DBG_CNTX_WARN, "GetAttachedSurface failed -> HW Flip/Complex" ));
+
+ /* Make sure we try the next fall back. */
+ pHAL->lpDDSPrimary->Release();
+ pHAL->lpDDSPrimary = NULL;
+ }
+ else
+ {
+ /* I have had problems when a complex surface comes back */
+ /* with the back buffer being created in SW. Not sure why */
+ /* or how this is possable but I'm checking for it here. */
+ memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
+ ddsd2.dwSize = sizeof( DDSURFACEDESC2 );
+ DX_RESTORE( pHAL->lpDDSRender );
+ rc = pHAL->lpDDSRender->GetSurfaceDesc( &ddsd2 );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "GetSurfaceDesc (RENDER) ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* If the surface is in VID then we are happy with are Flipable. */
+ if ( ddsd2.ddsCaps.dwCaps & DDSCAPS_LOCALVIDMEM )
+ {
+ pShared->bFlipable = TRUE;
+ DPF(( DBG_CNTX_INFO, "HW Flip/Complex!" ));
+ }
+ else
+ {
+ /* Kill this setup. */
+ pHAL->lpDDSPrimary->Release();
+ pHAL->lpDDSPrimary = NULL;
+ }
+ }
+ }
+ }
+
+ /*===================================*/
+ /* HARDWARE -> Z-BUFFER -> BLT */
+ /*===================================*/
+ if ( pHAL->lpDDSPrimary == NULL )
+ {
+ pShared->bFlipable = FALSE;
+
+ /* Create the Primary (front buffer). */
+ InitDDSD2( DDSD_CAPS );
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+ rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSPrimary, NULL );
+ if ( FAILED(rc) )
+ {
+ /* This is an error as we should be able to do this at minimum. */
+ RIP( pHAL, "CreateSurface (PRIMARY) ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Create the Render (back buffer). */
+ InitDDSD2( DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT );
+ ddsd2.dwWidth = dwWidth;
+ ddsd2.dwHeight = dwHeight;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
+ rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSRender, NULL );
+ if ( FAILED(rc) )
+ {
+ DPF(( DBG_CNTX_WARN, "Failed HW Offscreen surface" ));
+
+ /* Make sure we try the next fall back. */
+ pHAL->lpDDSPrimary->Release();
+ pHAL->lpDDSPrimary = NULL;
+ }
+ else
+ {
+ /* Might as well check here too see if this surface is in */
+ /* hardware. If nothing else just to be consistant. */
+ memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
+ ddsd2.dwSize = sizeof( DDSURFACEDESC2 );
+ DX_RESTORE( pHAL->lpDDSRender );
+ rc = pHAL->lpDDSRender->GetSurfaceDesc( &ddsd2 );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "GetSurfaceDesc (RENDER) ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* If the surface is in VID then we are happy. */
+ if ( ddsd2.ddsCaps.dwCaps & DDSCAPS_LOCALVIDMEM )
+ {
+ /* Create a clipper object so that DDraw will be able to blt windows that */
+ /* have been clipped by the screen or other windows. */
+ pHAL->lpDD4->CreateClipper( 0, &pHAL->lpClipper, NULL );
+ pHAL->lpClipper->SetHWnd( 0, pShared->hwnd );
+ pHAL->lpDDSPrimary->SetClipper( pHAL->lpClipper );
+ pHAL->lpClipper->Release();
+ DPF(( DBG_CNTX_INFO, "HW RENDER surface" ));
+ }
+ else
+ {
+ /* Kill this setup. */
+ pHAL->lpDDSRender->Release();
+ pHAL->lpDDSRender = NULL;
+ pHAL->lpDDSPrimary->Release();
+ pHAL->lpDDSPrimary = NULL;
+ }
+ }
+ }
+
+ /*===================================*/
+ /* Create D3DDEVICE -> HARDWARE. */
+ /*===================================*/
+ if ( pHAL->lpDDSZbuffer && pHAL->lpDDSPrimary && pHAL->lpDDSRender )
+ {
+ DX_RESTORE( pHAL->lpDDSRender );
+ DX_RESTORE( pHAL->lpDDSZbuffer );
+
+ rc = pHAL->lpDDSRender->AddAttachedSurface( pHAL->lpDDSZbuffer );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "AddAttachedSurface (ZBUFFER) ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ rc = pHAL->lpD3D3->CreateDevice( IID_IDirect3DHALDevice, pHAL->lpDDSRender, &pHAL->lpD3DDevice, NULL );
+ if ( rc != D3D_OK )
+ {
+ DPF(( DBG_CNTX_WARN, "Failed HW Device" ));
+ pHAL->lpD3DDevice = NULL;
+ }
+ else
+ {
+ DPF(( DBG_CNTX_INFO, "HW Device" ));
+ }
+ }
+ }
+ }
+
+ /*========================================================================*/
+ /* SOFTWARE fallback. */
+ /*========================================================================*/
+ if ( pHAL->lpD3DDevice == NULL )
+ {
+ DPF(( DBG_CNTX_INFO, "SW fallback :(" ));
+
+ /* Make sure we have no surfaces allocated. Just incase. */
+ DestroyAllSurfaces( pHAL );
+
+ /* Get a software device. */
+ pShared->bFlipable = FALSE;
+ pShared->bForceSW = TRUE;
+ pHAL->lpD3D3->EnumDevices( EnumDeviceHook, (void *)pHAL );
+ pShared->bHardware = IsEqualIID( pHAL->guid, IID_IDirect3DHALDevice );
+
+ /*===================================*/
+ /* SOFTWARE -> Z-BUFFER. */
+ /*===================================*/
+
+ /*===================================*/
+ /* SOFTWARE -> Z-BUFFER -> FLIPABLE */
+ /*===================================*/
+ if ( pShared->bWindow == FALSE )
+ {
+ InitDDSD2( DDSD_CAPS | DDSD_BACKBUFFERCOUNT );
+ ddsd2.dwBackBufferCount = 1;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
+ ddsd2.ddpfPixelFormat.dwSize = sizeof( DDPIXELFORMAT );
+ ddsd2.ddpfPixelFormat.dwFlags = (DDPF_RGB | DDPF_ALPHAPIXELS);
+ rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSPrimary, NULL );
+ if ( FAILED(rc) )
+ {
+ DPF(( DBG_CNTX_WARN, "Failed SW Flip/Complex" ));
+
+ /* Make sure we try the next fall back. */
+ pHAL->lpDDSPrimary = NULL;
+ }
+ else
+ {
+ ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
+ rc = pHAL->lpDDSPrimary->GetAttachedSurface( &ddscaps, &pHAL->lpDDSRender );
+ if ( FAILED(rc) )
+ {
+ /* Make sure we try the next fall back. */
+ DPF(( DBG_CNTX_WARN, "GetAttachedSurface failed -> SW Flip/Complex" ));
+ pHAL->lpDDSPrimary->Release();
+ pHAL->lpDDSPrimary = NULL;
+ }
+ else
+ {
+ DPF(( DBG_CNTX_INFO, "SW Flip/Complex" ));
+ pShared->bFlipable = TRUE;
+ }
+ }
+ }
+
+ /*===================================*/
+ /* SOFTWARE -> Z-BUFFER -> BLT */
+ /*===================================*/
+ if ( pHAL->lpDDSPrimary == NULL )
+ {
+ /* Create the Primary (front buffer). */
+ InitDDSD2( DDSD_CAPS );
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+ rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSPrimary, NULL );
+ if ( FAILED(rc) )
+ {
+ /* This is an error as we should be able to do this at minimum. */
+ RIP( pHAL, "CreateSurface (PRIMARY) ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Create the Render (back buffer). */
+ InitDDSD2( DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT );
+ ddsd2.dwWidth = dwWidth;
+ ddsd2.dwHeight = dwHeight;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
+ ddsd2.ddpfPixelFormat.dwSize = sizeof( DDPIXELFORMAT );
+ ddsd2.ddpfPixelFormat.dwFlags = (DDPF_RGB | DDPF_ALPHAPIXELS);
+ rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pHAL->lpDDSRender, NULL );
+ if ( FAILED(rc) )
+ {
+ /* That was our last hope. */
+ RIP( pHAL, "CreateSurface (RENDER) ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+ else
+ {
+ DPF(( DBG_CNTX_INFO, "SW RENDER surface" ));
+
+ /* Create a clipper object so that DDraw will be able to blt windows that */
+ /* have been clipped by the screen or other windows. */
+ pHAL->lpDD4->CreateClipper( 0, &pHAL->lpClipper, NULL );
+ pHAL->lpClipper->SetHWnd( 0, pShared->hwnd );
+ pHAL->lpDDSPrimary->SetClipper( pHAL->lpClipper );
+ pHAL->lpClipper->Release();
+ }
+ }
+
+ /*===================================*/
+ /* Create D3DDEVICE -> SOFTWARE. */
+ /*===================================*/
+ if ( pHAL->lpDDSPrimary && pHAL->lpDDSRender )
+ {
+ DX_RESTORE( pHAL->lpDDSRender );
+ rc = pHAL->lpD3D3->CreateDevice( IID_IDirect3DRGBDevice, pHAL->lpDDSRender, &pHAL->lpD3DDevice, NULL );
+ if ( rc != D3D_OK )
+ {
+ /* That was our last hope. */
+ RIP( pHAL, "CreateDevice (IID_IDirect3DRGBDevice) ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ DPF(( DBG_CNTX_INFO, "SW Device" ));
+ }
+ }
+
+ /*==============================================================================*/
+ /* Get a copy of the render pixelformat so that wgl.c can call GetPixelInfoD3D. */
+ /*==============================================================================*/
+ memset( &pHAL->ddpf, 0, sizeof(DDPIXELFORMAT) );
+ pHAL->ddpf.dwSize = sizeof( DDPIXELFORMAT );
+ rc = pHAL->lpDDSRender->GetPixelFormat( &pHAL->ddpf );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "GetPixelFormat ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+ DebugPixelFormat( "Using OFFSCREEN", &pHAL->ddpf );
+ DebugPixelFormat( "Using ZBUFFER", &ddsd2.ddpfPixelFormat );
+
+ /* Get a copy of what the D3DDevice supports for later use. */
+ memset( &D3DSWDevDesc, 0, sizeof(D3DDEVICEDESC) );
+ memset( &pHAL->D3DHWDevDesc, 0, sizeof(D3DDEVICEDESC) );
+ D3DSWDevDesc.dwSize = sizeof( D3DDEVICEDESC );
+ pHAL->D3DHWDevDesc.dwSize = sizeof( D3DDEVICEDESC );
+ rc = pHAL->lpD3DDevice->GetCaps( &pHAL->D3DHWDevDesc, &D3DSWDevDesc );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "GetCaps ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Get a copy of the pixel convertion stuff for direct buffer access. */
+ Solve8BitChannelPixelFormat( &pHAL->ddpf, &pShared->pixel );
+ AlphaBlendTableHAL( pHAL );
+
+ /* We must prime the Begin/End scene for SwapBuffers to work. */
+ rc = pHAL->lpD3DDevice->BeginScene();
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "BeginScene ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+#undef InitDDSD2
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* This function will make sure a viewport is created and set for the device*/
+/* in the supplied structure. If a rect is supplied then it will be used for*/
+/* the viewport otherwise the current setting in the strucute will be used. */
+/* Note that the rect is relative to the window. So left/top must be 0,0 to */
+/* use the whole window else there is scissoring going down. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+extern "C" BOOL SetViewportHAL( PMESAD3DSHARED pShared, RECT *pRect, float minZ, float maxZ )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+ D3DVIEWPORT2 vdData;
+ ULONG rc;
+ POINT pt;
+
+ DPF(( DBG_FUNC, "SetViewportHAL();" ));
+
+ /* Make sure we have enough info. */
+ if ( !pHAL || !pHAL->lpDDSPrimary || !pHAL->lpD3DDevice )
+ {
+ DPF(( DBG_CNTX_WARN, "SetViewport() -> NULL Pointer" ));
+ return FALSE;
+ }
+
+ /* TODO: this is just a temp fix to stop redundant changes. */
+ if ( pRect &&
+ (pShared->rectV.left == pRect->left) &&
+ (pShared->rectV.right == pRect->right) &&
+ (pShared->rectV.top == pRect->top) &&
+ (pShared->rectV.bottom == pRect->bottom) )
+ {
+ DPF(( DBG_CNTX_WARN, "Redundant viewport" ));
+ return TRUE;
+ }
+
+ DPF(( DBG_CNTX_INFO, "Current Viewport:" ));
+ DPF(( DBG_CNTX_INFO, "x: %d y: %d", pShared->rectV.left, pShared->rectV.top ));
+ DPF(( DBG_CNTX_INFO, "cx: %d cy: %d", (pShared->rectV.right-pShared->rectV.left), (pShared->rectV.bottom-pShared->rectV.top) ));
+ DPF(( DBG_CNTX_INFO, "New Viewport:" ));
+ DPF(( DBG_CNTX_INFO, "x: %d y: %d", pRect->left, pRect->top ));
+ DPF(( DBG_CNTX_INFO, "cx: %d cy: %d", (pRect->right-pRect->left), (pRect->bottom-pRect->top) ));
+
+ /* Update the current viewport rect if one is supplied. */
+ if ( pRect )
+ memcpy( &pShared->rectV, pRect, sizeof(RECT) );
+
+ /* Build the request structure. */
+ memset( &vdData, 0, sizeof(D3DVIEWPORT2) );
+ vdData.dwSize = sizeof(D3DVIEWPORT2);
+ vdData.dwX = pShared->rectV.left;
+ vdData.dwY = pShared->rectV.top;
+ vdData.dwWidth = (pShared->rectV.right - pShared->rectV.left);
+ vdData.dwHeight = (pShared->rectV.bottom - pShared->rectV.top);
+
+ if ( !vdData.dwWidth || !vdData.dwHeight )
+ {
+ GetClientRect( pShared->hwnd, &pShared->rectW );
+ pt.x = pt.y = 0;
+ ClientToScreen( pShared->hwnd, &pt );
+ OffsetRect( &pShared->rectW, pt.x, pt.y);
+ vdData.dwX = pShared->rectW.left;
+ vdData.dwY = pShared->rectW.top;
+ vdData.dwWidth = (pShared->rectW.right - pShared->rectW.left);
+ vdData.dwHeight = (pShared->rectW.bottom - pShared->rectW.top);
+ memcpy( &pShared->rectV, &pShared->rectW, sizeof(RECT) );
+ }
+
+ // The dvClipX, dvClipY, dvClipWidth, dvClipHeight, dvMinZ,
+ // and dvMaxZ members define the non-normalized post-perspective
+ // 3-D view volume which is visible to the viewer. In most cases,
+ // dvClipX is set to -1.0 and dvClipY is set to the inverse of
+ // the viewport's aspect ratio on the target surface, which can be
+ // calculated by dividing the dwHeight member by dwWidth. Similarly,
+ // the dvClipWidth member is typically 2.0 and dvClipHeight is set
+ // to twice the aspect ratio set in dwClipY. The dvMinZ and dvMaxZ
+ // are usually set to 0.0 and 1.0.
+ vdData.dvClipX = -1.0f;
+ vdData.dvClipWidth = 2.0f;
+ vdData.dvClipY = 1.0f;
+ vdData.dvClipHeight = 2.0f;
+ vdData.dvMaxZ = maxZ;
+ vdData.dvMinZ = minZ;
+
+ DPF(( DBG_CNTX_INFO, "zMin: %f zMax: %f", minZ, maxZ ));
+
+ /* I'm going to destroy the viewport everytime as when we size we will */
+ /* have a new D3DDevice. As this area doesn't need to be fast... */
+ if ( pHAL->lpViewport )
+ {
+ DPF(( DBG_CNTX_INFO, "DeleteViewport" ));
+
+ pHAL->lpD3DDevice->DeleteViewport( pHAL->lpViewport );
+ rc = pHAL->lpViewport->Release();
+ pHAL->lpViewport = NULL;
+ }
+
+ rc = pHAL->lpD3D3->CreateViewport( &pHAL->lpViewport, NULL );
+ if ( rc != D3D_OK )
+ {
+ DPF(( DBG_CNTX_ERROR, "CreateViewport Failed" ));
+ return FALSE;
+ }
+
+ /* Update the device with the new viewport. */
+ pHAL->lpD3DDevice->AddViewport( pHAL->lpViewport );
+ pHAL->lpViewport->SetViewport2( &vdData );
+ pHAL->lpD3DDevice->SetCurrentViewport( pHAL->lpViewport );
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* */
+/* */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+HRESULT WINAPI EnumSurfacesHook( LPDIRECTDRAWSURFACE4 lpDDS, LPDDSURFACEDESC2 lpDDSDesc, LPVOID pVoid )
+{
+ DDSURFACEDESC2 *pddsd2 = (DDSURFACEDESC2 *)pVoid;
+
+ DPF(( DBG_FUNC, "EnumSurfacesHook();" ));
+
+ if ( (lpDDSDesc->ddpfPixelFormat.dwFlags == pddsd2->ddpfPixelFormat.dwFlags) && (lpDDSDesc->ddsCaps.dwCaps == pddsd2->ddsCaps.dwCaps) )
+ {
+ /* Save the pixelformat now so that we know we have one. */
+ memcpy( pddsd2, lpDDSDesc, sizeof(DDSURFACEDESC2) );
+
+ return D3DENUMRET_CANCEL;
+ }
+
+ return D3DENUMRET_OK;
+}
+/*===========================================================================*/
+/* This is the callback proc to get a Z-Buffer. Thats it. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+HRESULT CALLBACK EnumZBufferHook( DDPIXELFORMAT* pddpf, VOID *pVoid )
+{
+ DDPIXELFORMAT *pddpfChoice = (DDPIXELFORMAT *)pVoid;
+
+ DPF(( DBG_FUNC, "EnumZBufferHook();" ));
+
+ /* If this is ANY type of depth-buffer, stop. */
+ if( pddpf->dwFlags == DDPF_ZBUFFER )
+ {
+ /* Save the pixelformat now so that we know we have one. */
+ memcpy( pddpfChoice, pddpf, sizeof(DDPIXELFORMAT) );
+
+ /* I feel if the hardware supports this low then lets use it. Could get ugly. */
+ if( pddpf->dwZBufferBitDepth >= 8 )
+ {
+ return D3DENUMRET_CANCEL;
+ }
+ }
+
+ return D3DENUMRET_OK;
+}
+/*===========================================================================*/
+/* This function handles the callback for the D3DDevice enumeration. Good */
+/* god who's idea was this? The D3D wrapper has two variable related to what*/
+/* kind of device we want and have. First we have a Bool that is set if we */
+/* have allocated a HW device. We always look for the HW device first. The */
+/* other variable is used to force SW. If we have run into a case that we */
+/* want to fallback to SW then we set this. We will fallback if we cannot */
+/* texture in video memory (among others). */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+HRESULT CALLBACK EnumDeviceHook( GUID FAR* lpGuid, LPSTR lpDesc, LPSTR lpName, LPD3DDEVICEDESC lpD3DHWDesc, LPD3DDEVICEDESC lpD3DHELDesc, void *pVoid )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pVoid;
+ LPD3DDEVICEDESC pChoice = lpD3DHWDesc;
+
+ DPF(( DBG_FUNC, "EnumDeviceHook();" ));
+
+ /* Determine if which device description is valid. */
+ if ( pChoice->dcmColorModel == 0 )
+ pChoice = lpD3DHELDesc;
+
+ /* Make sure we always have a GUID. */
+ memcpy( &pHAL->guid, lpGuid, sizeof(GUID) );
+
+ /* This controls whether we will except HW or not. */
+ if ( pHAL->shared.bForceSW == TRUE )
+ {
+ return (pChoice == lpD3DHELDesc) ? D3DENUMRET_CANCEL : D3DENUMRET_OK;
+ }
+
+ /* Always try for hardware. */
+ if ( pChoice == lpD3DHWDesc )
+ {
+ return D3DENUMRET_CANCEL;
+ }
+
+ return D3DENUMRET_OK;
+}
+/*===========================================================================*/
+/* This function will destroy any and all surfaces that this context has */
+/* allocated. If there is a clipper object then it will also be destoryed as*/
+/* it is part of the Primary Surface. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void DestroyAllSurfaces( PMESAD3DHAL pHAL )
+{
+ LONG refCount;
+
+ DPF(( DBG_FUNC, "DestroyAllSurfaces();" ));
+
+ DX_RESTORE( pHAL->lpDDSPrimary );
+ DX_RESTORE( pHAL->lpDDSRender );
+ DX_RESTORE( pHAL->lpDDSZbuffer);
+
+ if ( pHAL->lpDDSRender )
+ {
+ pHAL->lpDDSRender->Unlock( NULL );
+
+ /* If this isn't a Flipable surface then we must clean up the render. */
+ if ( pHAL->shared.bFlipable == FALSE)
+ {
+ if ( pHAL->lpDDSZbuffer )
+ {
+ DPF(( DBG_CNTX_INFO, "Remove attached surfaces from RENDER" ));
+ pHAL->lpDDSRender->DeleteAttachedSurface( 0, NULL );
+ }
+
+ DPF(( DBG_CNTX_INFO, "Release RENDER" ));
+ refCount = pHAL->lpDDSRender->Release();
+ pHAL->lpDDSRender = NULL;
+ }
+ }
+
+ if ( pHAL->lpDDSZbuffer )
+ {
+ DPF(( DBG_CNTX_INFO, "Release ZBuffer" ));
+ pHAL->lpDDSZbuffer->Unlock( NULL );
+ refCount = pHAL->lpDDSZbuffer->Release();
+ pHAL->lpDDSZbuffer = NULL;
+ }
+
+ if ( pHAL->lpClipper )
+ {
+ DPF(( DBG_CNTX_INFO, "Release Clipper" ));
+ refCount = pHAL->lpClipper->Release();
+ pHAL->lpClipper = NULL;
+ }
+
+ if ( pHAL->lpDDSPrimary )
+ {
+ pHAL->lpDDSPrimary->Unlock( NULL );
+
+ DPF(( DBG_CNTX_INFO, "Release PRIMARY" ));
+ refCount = pHAL->lpDDSPrimary->Release();
+ pHAL->lpDDSPrimary = NULL;
+ }
+}
+/*===========================================================================*/
+/* This function will destroy the current D3DDevice and any resources that */
+/* belong to it. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void DestroyDevice( PMESAD3DHAL pHAL )
+{
+ LONG refCount;
+
+ DPF(( DBG_FUNC, "DestroyDevice();" ));
+
+ /* Kill the D3D stuff if exists. */
+ if ( pHAL->lpViewport )
+ {
+ DPF(( DBG_CNTX_INFO, "Delete Viewport" ));
+ pHAL->lpD3DDevice->DeleteViewport( pHAL->lpViewport );
+
+ DPF(( DBG_CNTX_INFO, "Release Viewport" ));
+ refCount = pHAL->lpViewport->Release();
+ pHAL->lpViewport = NULL;
+ }
+
+ if ( pHAL->lpD3DDevice != NULL )
+ {
+ DPF(( DBG_CNTX_INFO, "Release D3DDevice" ));
+ refCount = pHAL->lpD3DDevice->EndScene();
+ refCount = pHAL->lpD3DDevice->Release();
+ pHAL->lpD3DDevice = NULL;
+ }
+}
+/*===========================================================================*/
+/* This function will destroy the current D3DDevice and any resources that */
+/* belong to it. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void DestroyInterfaces( PMESAD3DHAL pHAL )
+{
+ LONG refCount;
+
+ DPF(( DBG_FUNC, "DestroyInterfaces();" ));
+
+ if ( pHAL->lpD3D3 != NULL )
+ {
+ DPF(( DBG_CNTX_INFO, "Release Direct3D3" ));
+ refCount = pHAL->lpD3D3->Release();
+ pHAL->lpD3D3 = NULL;
+ }
+
+ if ( pHAL->lpDD4 != NULL )
+ {
+ DPF(( DBG_CNTX_INFO, "Release DDraw4" ));
+ refCount = pHAL->lpDD4->Release();
+ pHAL->lpDD4 = NULL;
+ }
+
+ if ( pHAL->lpDD != NULL )
+ {
+ DPF(( DBG_CNTX_INFO, "Release DDraw" ));
+ refCount = pHAL->lpDD->Release();
+ pHAL->lpDD = NULL;
+ }
+}
+/*===========================================================================*/
+/* This function will first send (not post) a message to the client window */
+/* that this context is using. The client will respond by unbinding itself */
+/* and binding the 'default' context. This allows the API to be supported */
+/* until the window can be destroyed. Finally we post the quit message to */
+/* the client in hopes to end the application. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void FatalShutDown( PMESAD3DHAL pHAL )
+{
+ /* Whip this baby in too try and support the API until we die... */
+ if ( pHAL )
+ SendMessage( pHAL->shared.hwnd, UM_FATALSHUTDOWN, 0L, 0L );
+
+ /* Close the client application down. */
+ PostQuitMessage( 0 );
+}
+
diff --git a/src/mesa/drivers/d3d/D3DMESA.H b/src/mesa/drivers/d3d/D3DMESA.H
new file mode 100644
index 0000000000..907f69ffb1
--- /dev/null
+++ b/src/mesa/drivers/d3d/D3DMESA.H
@@ -0,0 +1,85 @@
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#ifndef D3D_MESA_H
+#define D3D_MESA_H
+/*===========================================================================*/
+/* Includes. */
+/*===========================================================================*/
+#include <windows.h>
+#include <ddraw.h>
+#include <d3d.h>
+#include "matrix.h"
+#include "context.h"
+#include "types.h"
+#include "vb.h"
+#include "D3DShared.h"
+#include "Debug.h"
+#include "NULLProcs.h"
+/*===========================================================================*/
+/* Macros. */
+/*===========================================================================*/
+#define FLIP(h,y) (h-y)
+/*===========================================================================*/
+/* Magic numbers. */
+/*===========================================================================*/
+/*===========================================================================*/
+/* Type defines. */
+/*===========================================================================*/
+struct __extensions__
+{
+ PROC proc;
+ char *name;
+};
+
+typedef GLbitfield (*ClearPROC)( GLcontext *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height );
+typedef void (*WSpanRGBPROC)( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte rgb[][3], const GLubyte mask[] );
+typedef void (*WSpanRGBAPROC)( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte rgba[][4], const GLubyte mask[] );
+typedef void (*WSpanRGBAMonoPROC)( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte mask[] );
+typedef void (*WPixelsRGBAPROC)( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte rgba[][4], const GLubyte mask[] );
+typedef void (*WPixelsRGBAMonoPROC)( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte mask[] );
+typedef void (*RSpanRGBAPROC)( const GLcontext* ctx, GLuint n, GLint x, GLint y, GLubyte rgba[][4] );
+typedef void (*RPixelsRGBAPROC)( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], GLubyte rgba[][4], const GLubyte mask[] );
+
+typedef struct D3D_mesa_context
+{
+ PMESAD3DSHARED pShared;
+
+ GLcontext *gl_ctx; /* The core GL/Mesa context */
+ GLvisual *gl_visual; /* Describes the buffers */
+ GLframebuffer *gl_buffer; /* Depth, stencil, accum, etc buffers */
+
+ HDC hdc;
+ WNDPROC hOldProc;
+
+ UCHAR rClear, /* Current clear colors. */
+ gClear,
+ bClear,
+ aClear,
+ rCurrent, /* Current rendering colors. */
+ gCurrent,
+ bCurrent,
+ aCurrent;
+
+ struct D3D_mesa_context *next;
+
+} D3DMESACONTEXT, *PD3DMESACONTEXT;
+/*===========================================================================*/
+/* Extern function prototypes. */
+/*===========================================================================*/
+extern void gl_Viewport( GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height );
+/*===========================================================================*/
+/* Global variables. */
+/*===========================================================================*/
+extern D3DTLVERTEX D3DTLVertices[(VB_MAX*6)];
+
+#endif
+
+ \ No newline at end of file
diff --git a/src/mesa/drivers/d3d/D3DRaster.cpp b/src/mesa/drivers/d3d/D3DRaster.cpp
new file mode 100644
index 0000000000..b87b3abd6d
--- /dev/null
+++ b/src/mesa/drivers/d3d/D3DRaster.cpp
@@ -0,0 +1,214 @@
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#include "D3DHAL.h"
+/*===========================================================================*/
+/* This function clears the context bound to the supplied shared context. */
+/* The function takes the D3D flags D3DCLEAR_TARGET, D3DCLEAR_STENCIL and */
+/* D3DCLEAR_ZBUFFER. Set bAll to TRUE for a full clear else supply the coord*/
+/* of the rect to be cleared relative to the window. The color is always a */
+/* 32bit value (RGBA). Fill in the z-value and stencil if needed. */
+/* */
+/* TODO: this can be redone to be called by Mesa directly. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" void ClearHAL( PMESAD3DSHARED pShared, DWORD dwFlags, BOOL bAll, int x, int y, int cx, int cy, DWORD dwColor, float zv, DWORD dwStencil )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+ D3DRECT d3dRect;
+
+#ifdef D3D_DEBUG
+ HRESULT rc;
+
+ DPF(( DBG_FUNC, "CleaHAL();" ));
+
+ /* Make sure we have enough info. */
+ if ( (pHAL == NULL) || (pHAL->lpViewport == NULL) )
+ return;
+#endif
+
+ if ( bAll )
+ {
+ /* I assume my viewport is valid. */
+ d3dRect.lX1 = pShared->rectV.left;
+ d3dRect.lY1 = pShared->rectV.top;
+ d3dRect.lX2 = pShared->rectV.right;
+ d3dRect.lY2 = pShared->rectV.bottom;
+ }
+ else
+ {
+ d3dRect.lX1 = pShared->rectV.left + x;
+ d3dRect.lY1 = pShared->rectV.top + y;
+ d3dRect.lX2 = d3dRect.lX1 + cx;
+ d3dRect.lY2 = d3dRect.lY1 + cy;
+ }
+
+#ifdef D3D_DEBUG
+ rc = pHAL->lpViewport->Clear2( 1, &d3dRect, dwFlags, dwColor, zv, dwStencil );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "Clear2 ->", ErrorStringD3D(rc) );
+ }
+#else
+ pHAL->lpViewport->Clear2( 1, &d3dRect, dwFlags, dwColor, zv, dwStencil );
+#endif
+}
+/*===========================================================================*/
+/* Well this is the guts of it all. Here we rasterize the primitives that */
+/* are in their final form. OpenGL has done all the lighting, transfomations*/
+/* and clipping at this point. */
+/* */
+/* TODO: I'm not sure if I want to bother to check for errors on this call. */
+/* The overhead kills me... */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" void DrawPrimitiveHAL( PMESAD3DSHARED pShared, D3DPRIMITIVETYPE dptPrimitiveType, D3DTLVERTEX *pVertices, DWORD dwCount )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+
+#ifdef D3D_DEBUG
+ HRESULT rc;
+
+ DPF(( DBG_FUNC, "DrawPrimitveHAL();" ));
+
+ /* Make sure we have enough info. */
+ if ( (pHAL == NULL) || (pHAL->lpD3DDevice == NULL) )
+ return;
+
+ DPF(( DBG_PRIM_INFO, "DP( %d )", dwCount ));
+
+ rc = pHAL->lpD3DDevice->DrawPrimitive( dptPrimitiveType,
+ D3DFVF_TLVERTEX,
+ (LPVOID)pVertices,
+ dwCount,
+ (D3DDP_DONOTCLIP | D3DDP_DONOTLIGHT) );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "DrawPrimitive ->", ErrorStringD3D(rc) );
+ }
+#else
+ pHAL->lpD3DDevice->DrawPrimitive( dptPrimitiveType,
+ D3DFVF_TLVERTEX,
+ (LPVOID)pVertices,
+ dwCount,
+ (D3DDP_DONOTCLIP | D3DDP_DONOTLIGHT) );
+#endif
+}
+/*===========================================================================*/
+/* This call will handle the swapping of the buffers. Now I didn't bother */
+/* to support single buffered so this will be used for glFlush() as its all */
+/* the same. So first we do an EndScene as we are always considered to be in*/
+/* a BeginScene because when we leave we do a BeginScene. Now note that when*/
+/* the context is created in the first place we do a BeginScene also just to */
+/* get things going. The call will use either Flip/blt based on the type of */
+/* surface was created for rendering. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" void SwapBuffersHAL( PMESAD3DSHARED pShared )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+
+#ifdef D3D_DEBUG
+ HRESULT rc;
+
+ DPF(( DBG_FUNC, "SwapBuffersHAL();" ));
+ DPF(( DBG_ALL_PROFILE, "=================SWAP===================" ));
+
+ /* Make sure we have enough info. */
+ if ( (pHAL == NULL) || (pHAL->lpD3DDevice == NULL) )
+ return;
+
+ /* Make sure we have enough info. */
+ if ( pHAL->lpDDSPrimary != NULL )
+ {
+ rc = pHAL->lpD3DDevice->EndScene();
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "EndScene ->", ErrorStringD3D(rc) );
+ }
+
+ if ( pShared->bFlipable )
+ {
+ DPF(( DBG_CNTX_PROFILE, "Swap->FLIP" ));
+ rc = pHAL->lpDDSPrimary->Flip( NULL, DDFLIP_WAIT );
+ }
+ else
+ {
+ DPF(( DBG_CNTX_PROFILE, "Swap->Blt" ));
+ rc = pHAL->lpDDSPrimary->Blt( &pShared->rectW, pHAL->lpDDSRender, NULL, DDBLT_WAIT, NULL );
+ }
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "Blt (RENDER/PRIMARY) ->", ErrorStringD3D(rc) );
+ }
+
+ rc = pHAL->lpD3DDevice->BeginScene();
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "BeginScene ->", ErrorStringD3D(rc) );
+ }
+ }
+#else
+ pHAL->lpD3DDevice->EndScene();
+
+ if ( pShared->bFlipable )
+ pHAL->lpDDSPrimary->Flip( NULL, DDFLIP_WAIT );
+ else
+ pHAL->lpDDSPrimary->Blt( &pShared->rectW, pHAL->lpDDSRender, NULL, DDBLT_WAIT, NULL );
+
+ pHAL->lpD3DDevice->BeginScene();
+
+#endif
+}
+/*===========================================================================*/
+/* This function is a very thin wrapper for the D3D call 'SetRenderState'. */
+/* Using this function requires all the types to be defined by including the */
+/* D3D header file. */
+/* */
+/* TODO: would be much better to get ride of all these calls per VBRender. */
+/* I feel I should get this call into SetRenderStates() the RenderVB. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" void SetStateHAL( PMESAD3DSHARED pShared, DWORD dwType, DWORD dwState )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+
+#ifdef D3D_DEBUG
+ HRESULT rc;
+
+ DPF(( DBG_FUNC, "SetStateHAL();" ));
+
+ /* Make sure we have enough info. */
+ if ( (pHAL == NULL) || (pHAL->lpD3DDevice == NULL) )
+ return;
+
+ rc = pHAL->lpD3DDevice->SetRenderState( (D3DRENDERSTATETYPE)dwType, dwState );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "SetRenderState ->", ErrorStringD3D(rc) );
+ }
+
+#else
+ pHAL->lpD3DDevice->SetRenderState( (D3DRENDERSTATETYPE)dwType, dwState );
+#endif
+}
+
+
+
+
+
+
+
+
+ \ No newline at end of file
diff --git a/src/mesa/drivers/d3d/D3DShared.h b/src/mesa/drivers/d3d/D3DShared.h
new file mode 100644
index 0000000000..cc629e2111
--- /dev/null
+++ b/src/mesa/drivers/d3d/D3DShared.h
@@ -0,0 +1,154 @@
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#ifndef D3D_MESA_ALL_H
+#define D3D_MESA_ALL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================*/
+/* Includes. */
+/*===========================================================================*/
+#include <stdio.h>
+#include <string.h>
+/*===========================================================================*/
+/* Magic numbers. */
+/*===========================================================================*/
+#define TM_ACTION_LOAD 0x01
+#define TM_ACTION_BIND 0x02
+#define TM_ACTION_UPDATE 0x04
+
+#define UM_FATALSHUTDOWN (WM_USER+42)
+/*===========================================================================*/
+/* Macros defines. */
+/*===========================================================================*/
+#define ALLOC(cb) malloc( (cb) )
+#define FREE(p) { free( (p) ); (p) = NULL; }
+/*===========================================================================*/
+/* Type defines. */
+/*===========================================================================*/
+typedef struct _pixel_convert
+{
+ int cb, /* Count in bytes of one pixel. */
+ rShift, /* Shift count that postions each componet. */
+ gShift,
+ bShift,
+ aShift;
+ float rScale, /* Value that scales a color that ranges 0.0 -> 1.0 */
+ gScale, /* to this pixel format. */
+ bScale,
+ aScale;
+ DWORD dwRMask, /* Color mask per component. */
+ dwGMask,
+ dwBMask,
+ dwAMask;
+
+} PIXELINFO, *PPIXELINFO;
+
+
+typedef struct _d3d_shared_info
+{
+ HWND hwnd;
+ BOOL bWindow,
+ bFlipable,
+ bForceSW,
+ bHardware;
+ RECT rectW, /* Window size and postion in screen space. */
+ rectV; /* Viewport size and postion. */
+ DWORD dwWidth, /* Current render size for quick checks. */
+ dwHeight;
+
+ PIXELINFO pixel;
+ DWORD dwSrcBlendCaps[14], /* See D3DCAPS.CPP */
+ dwDestBlendCaps[14],
+ dwTexFunc[4];
+
+} MESAD3DSHARED, *PMESAD3DSHARED;
+
+typedef struct _render_options
+{
+ BOOL bForceSoftware, /* TODO: Add user switches. */
+ bStretchtoPrimary;
+
+} USER_CTRL, *PUSER_CRTL;
+
+enum { s_zero = 0,
+ s_one,
+ s_dst_color,
+ s_one_minus_dst_color,
+ s_src_alpha,
+ s_one_minus_src_alpha,
+ s_dst_alpha,
+ s_one_minus_dst_alpha,
+ s_src_alpha_saturate,
+ s_constant_color,
+ s_one_minus_constant_color,
+ s_constant_alpha,
+ s_one_minus_constant_alpha };
+
+enum { d_zero = 0,
+ d_one,
+ d_src_color,
+ d_one_minus_src_color,
+ d_src_alpha,
+ d_one_minus_src_alpha,
+ d_dst_alpha,
+ d_one_minus_dst_alpha,
+ d_constant_color,
+ d_one_minus_constant_color,
+ d_constant_alpha,
+ d_one_minus_constant_alpha };
+
+enum { d3dtblend_decal = 0,
+ d3dtblend_decalalpha,
+ d3dtblend_modulate,
+ d3dtblend_modulatealpha };
+
+/*===========================================================================*/
+/* Function prototypes. */
+/*===========================================================================*/
+PMESAD3DSHARED InitHAL( HWND hwnd );
+void TermHAL( PMESAD3DSHARED pShared );
+BOOL CreateHAL( PMESAD3DSHARED pShared );
+BOOL SetViewportHAL( PMESAD3DSHARED pShared, RECT *pRect, float minZ, float maxZ );
+
+void ClearHAL( PMESAD3DSHARED pShared, DWORD dwFlags, BOOL bAll, int x, int y, int cx, int cy, DWORD dwColor, float zv, DWORD dwStencil );
+void SetStateHAL( PMESAD3DSHARED pShared, DWORD dwType, DWORD dwState );
+void DrawPrimitiveHAL( PMESAD3DSHARED pShared, D3DPRIMITIVETYPE dptPrimitiveType, D3DTLVERTEX *pVertices, DWORD dwCount );
+
+void SwapBuffersHAL( PMESAD3DSHARED pShared );
+DDSURFACEDESC2 *LockHAL( PMESAD3DSHARED pShared, BOOL bBack );
+void UnlockHAL( PMESAD3DSHARED pShared, BOOL bBack );
+void UpdateScreenPosHAL( PMESAD3DSHARED pShared );
+void GetPixelInfoHAL( PMESAD3DSHARED pShared, PPIXELINFO pPixel );
+BOOL CreateTMgrHAL( PMESAD3DSHARED pShared, DWORD dwName, int level, DWORD dwRequestFlags, RECT *rectDirty, DWORD dwWidth, DWORD dwHeight, DWORD dwAction, void *pPixels );
+void DisableTMgrHAL( PMESAD3DSHARED pShared );
+
+
+int SaveDIBitmap( char *filename, BITMAPINFO *info, void *bits );
+int ARGB_SaveBitmap( char *filename, int width, int height, unsigned char *pARGB );
+int BGRA_SaveBitmap( char *filename, int width, int height, unsigned char *pBGRA );
+int BGR_SaveBitmap( char *filename, int width, int height, unsigned char *pBGR );
+/*===========================================================================*/
+/* Global variables. */
+/*===========================================================================*/
+extern float g_DepthScale, /* Mesa needs to scale Z in SW. The HAL */
+ g_MaxDepth; /* doesn't but I wanted SW still to work.*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
diff --git a/src/mesa/drivers/d3d/D3DTEXT.CPP b/src/mesa/drivers/d3d/D3DTEXT.CPP
new file mode 100644
index 0000000000..7321eeb7c4
--- /dev/null
+++ b/src/mesa/drivers/d3d/D3DTEXT.CPP
@@ -0,0 +1,577 @@
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#include "d3dText.h"
+
+/*=============================================================================
+
+ 1
+ ------
+ | |
+ 6 | | 2
+ | 7 |
+ ------
+ | |
+ 5 | | 3
+ | |
+ ------
+ 4
+
+ TL_0 TR_0
+TLL TL_1 TR_1 TRR
+
+MLL_0 ML_0 MR_0 MRR_0
+MLL_1 ML_1 MR_1 MRR_1
+
+BLL BL_0 BR_0 BRR
+ BL_1 BR_1
+
+=============================================================================*/
+
+#define TLL 0
+#define TRR 1
+#define TL_0 2
+#define TL_1 3
+#define TR_0 4
+#define TR_1 5
+
+#define MLL_0 6
+#define MLL_1 7
+#define MRR_0 8
+#define MRR_1 9
+
+#define ML_0 10
+#define ML_1 11
+#define MR_0 12
+#define MR_1 13
+
+#define BL_0 14
+#define BL_1 15
+#define BR_0 16
+#define BR_1 17
+#define BLL 18
+#define BRR 19
+
+#define BIT1 0x00000001
+#define BIT2 0x00000002
+#define BIT3 0x00000004
+#define BIT4 0x00000008
+#define BIT5 0x00000010
+#define BIT6 0x00000020
+#define BIT7 0x00000040
+
+#define TOP BIT4
+#define MIDDLE BIT7
+#define BOTTOM BIT1
+#define TLEFT BIT5
+#define BLEFT BIT6
+#define LEFT (TLEFT|BLEFT)
+#define TRIGHT BIT3
+#define BRIGHT BIT2
+#define RIGHT (TRIGHT|BRIGHT)
+#define ALL 0xFFFFFFFF
+
+/*===========================================================================*/
+/* This is the static array that will map the ASCII value of the character */
+/* being draw to the bit mask that will be scan converted to the LED display.*/
+/*===========================================================================*/
+DWORD textBitMasks[] =
+{
+ 0xFFFFFFFF, // 000
+ 0xFFFFFFFF, // 001
+ 0xFFFFFFFF, // 002
+ 0xFFFFFFFF, // 003
+ 0xFFFFFFFF, // 004
+ 0xFFFFFFFF, // 005
+ 0xFFFFFFFF, // 006
+ 0xFFFFFFFF, // 007
+ 0xFFFFFFFF, // 008
+ 0xFFFFFFFF, // 009
+ 0xFFFFFFFF, // 010
+ 0xFFFFFFFF, // 011
+ 0xFFFFFFFF, // 012
+ 0xFFFFFFFF, // 013
+ 0xFFFFFFFF, // 014
+ 0xFFFFFFFF, // 015
+ 0xFFFFFFFF, // 016
+ 0xFFFFFFFF, // 017
+ 0xFFFFFFFF, // 018
+ 0xFFFFFFFF, // 019
+ 0xFFFFFFFF, // 020
+ 0xFFFFFFFF, // 021
+ 0xFFFFFFFF, // 022
+ 0xFFFFFFFF, // 023
+ 0xFFFFFFFF, // 024
+ 0xFFFFFFFF, // 025
+ 0xFFFFFFFF, // 026
+ 0xFFFFFFFF, // 027
+ 0xFFFFFFFF, // 028
+ 0xFFFFFFFF, // 029
+ 0xFFFFFFFF, // 030
+ 0XFFFFFFFF, // 031
+ 0x00000000, // 032 'SPC'
+ 0xFFFFFFFF, // 033
+ 0xFFFFFFFF, // 034
+ 0xFFFFFFFF, // 035
+ 0xFFFFFFFF, // 036
+ 0xFFFFFFFF, // 037
+ 0xFFFFFFFF, // 038
+ 0xFFFFFFFF, // 039
+ 0xFFFFFFFF, // 040
+ 0xFFFFFFFF, // 041
+ 0xFFFFFFFF, // 042
+ 0xFFFFFFFF, // 043
+ 0xFFFFFFFF, // 044
+ 0xFFFFFFFF, // 045
+ 0xFFFFFFFF, // 046
+ 0xFFFFFFFF, // 047
+ (ALL &~ MIDDLE), // 048 '0'
+ (RIGHT), // 049 '1'
+ (ALL &~ TLEFT &~ BRIGHT), // 050 '2'
+ (ALL &~ LEFT), // 051 '3'
+ (TLEFT | MIDDLE | RIGHT), // 052 '4'
+ (ALL &~ TRIGHT &~ BLEFT), // 053 '5'
+ (ALL &~ TRIGHT), // 054 '6'
+ (TOP | RIGHT), // 055 '7'
+ (ALL), // 056 '8'
+ (ALL &~ BOTTOM &~ BLEFT), // 057 '9'
+ 0xFFFFFFFF, // 058
+ 0xFFFFFFFF, // 059
+ 0xFFFFFFFF, // 060
+ 0XFFFFFFFF, // 061
+ 0xFFFFFFFF, // 062
+ 0xFFFFFFFF, // 063
+ 0xFFFFFFFF, // 064
+ (ALL &~ BOTTOM), // 065 'A'
+ (ALL), // 066 'B'
+ (TOP | LEFT | BOTTOM), // 067 'C'
+ (ALL &~ MIDDLE), // 068 'D'
+ (ALL &~ RIGHT), // 069 'E'
+ (LEFT | TOP | MIDDLE), // 070 'F'
+ 0x00000000, // 071 'G'
+ (ALL &~ TOP &~ BOTTOM), // 072 'H'
+ (RIGHT), // 073 'I'
+ (RIGHT | BOTTOM), // 074 'J'
+ 0x00000000, // 075 'K'
+ (LEFT | BOTTOM), // 076 'L'
+ 0x00000000, // 088 'M'
+ 0x00000000, // 089 'N'
+ (ALL &~ MIDDLE), // 090 'O'
+ (ALL &~ BRIGHT &~ BOTTOM),// 091 'P'
+ 0x00000000, // 092 'Q'
+ 0x00000000, // 093 'R'
+ (ALL &~ TRIGHT &~ BLEFT), // 094 'S'
+ 0X00000000, // 095 'T'
+ (LEFT | RIGHT | BOTTOM), // 096 'U'
+ 0x00000000, // 097 'V'
+ 0x00000000, // 098 'W'
+ 0x00000000, // 099 'X'
+ 0x00000000, // 1000 'Z'
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, // 100
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, // 104
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, // 108
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, // 112
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, // 116
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, // 120
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF // 124
+};
+
+#define CT 1.0f
+#define CX 7.0f
+#define CY 13.0f
+#define CM ((CY-(CT*3.0f))/2.0f)
+
+float lCoords[][2] =
+{
+ /* Top outsides. */
+ { 0, (CY-CT) },
+ { CX, (CY-CT) },
+
+ /* Top Line. */
+ { CT, CY },
+ { CT, (CY-CT) },
+ { (CX-CT), CY },
+ { (CX-CT), (CY-CT) },
+
+ /* Middle outsides. */
+ { 0.0f, (CT+CM+CT) },
+ { 0.0f, (CT+CM) },
+ { CX, (CT+CM+CT) },
+ { CX, (CT+CM) },
+
+ /* Middle Line. */
+ { CT, (CT+CM+CT) },
+ { CT, (CT+CM) },
+ { (CX-CT), (CT+CM+CT) },
+ { (CX-CT), (CT+CM) },
+
+ /* Bottom line. */
+ { CT, CT },
+ { CT, 0.0f },
+ { (CX-CT), CT },
+ { (CX-CT), 0.0f },
+
+ /* Bottom outsides. */
+ { 0.0f, CT},
+ { CX, CT }
+};
+
+static int ConvertCharacter( char *c, int cIndex, PD3DFONTMETRICS pfntMetrics );
+
+D3DTLVERTEX TextVertices[MAX_VERTICES];
+/*===========================================================================*/
+/* When we attach I will zero out the whole D3D vertex buffer I'm using for */
+/* the text. This way I don't need to set all the redundant values. I also */
+/* set all the oow values to 1 as I will be doing direct rendering. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+extern "C" BOOL InitD3DText( void )
+{
+ int index;
+
+ /* Set the D3D Vertex Buffer up once so we don't do redundant changes. */
+ memset( &TextVertices[0], 0, sizeof(TextVertices) );
+ for( index = 0; index < MAX_VERTICES; index++ )
+ TextVertices[index].rhw = D3DVAL( 1.0 );
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* This function takes a single character and draw it using the supplied */
+/* fontmetrics structure. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" void d3dTextDrawString( char *pszString, int x, int y, PD3DFONTMETRICS pfntMetrics )
+{
+ int cIndex,
+ nIndex,
+ index;
+ float cWidth = CX,
+ cHeight = CY;
+
+ /* Find the max width/height of a character and add the spacing so */
+ /* that we can use this value to calculate the x,y of the character.*/
+ cWidth = (cWidth * pfntMetrics->fntXScale) + pfntMetrics->fntXSpacing;
+ cHeight = (cHeight * pfntMetrics->fntYScale) + pfntMetrics->fntYSpacing;
+
+ /* Walk the string. This must be NULL terminated. */
+ for( cIndex = 0, nIndex = 0; *pszString; pszString++, cIndex = nIndex, x++ )
+ {
+ /* Convert the character and get the index into the text vertex buffer. */
+ nIndex = ConvertCharacter( &pszString[0], cIndex, pfntMetrics );
+ if ( (nIndex - cIndex) > 2 )
+ {
+ /* Modify the text vertex buffer based on the fntMetrics structure. */
+ for( index = cIndex; index < nIndex; index++ )
+ {
+ /* Scale the character. */
+ TextVertices[index].sx *= pfntMetrics->fntXScale;
+ TextVertices[index].sy *= pfntMetrics->fntYScale;
+
+ /* Move the character. */
+ TextVertices[index].sx += (cWidth*x);
+ TextVertices[index].sy += (cHeight*y);
+
+ /* Set the color. */
+ TextVertices[index].color = pfntMetrics->dwColor;
+ }
+ }
+ }
+
+ if ( nIndex < 3 )
+ return;
+
+ /* Set the states that slim things down. */
+ pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_NONE );
+ pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_FILLMODE, D3DFILL_SOLID );
+ pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_ZENABLE, FALSE );
+ pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE , FALSE );
+ pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_ALPHATESTENABLE, FALSE );
+ pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, FALSE );
+
+ /* Blast them baby... */
+ pfntMetrics->lpD3DDevice->DrawPrimitive( D3DPT_TRIANGLELIST,
+ D3DFVF_TLVERTEX,
+ (LPVOID)&TextVertices[0],
+ nIndex,
+ (D3DDP_DONOTCLIP | D3DDP_DONOTLIGHT) );
+}
+/*===========================================================================*/
+/* This function takes a single character and draw it directly to the screen*/
+/* unsing the supplied fntMetrics structure. The character will be drawn at */
+/* the supplied x,y. The x,y position is relative to the top left and uses */
+/* the spacing in the fntMetrics structure. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" void d3dTextDrawCharacter( char *c, int x, int y, PD3DFONTMETRICS pfntMetrics )
+{
+ int cIndex = 0,
+ index;
+ float cWidth = CX,
+ cHeight = CY;
+
+ /* Convert the character and get the index into the text vertex buffer. */
+ cIndex = ConvertCharacter( c, 0, pfntMetrics );
+ if ( cIndex < 3 )
+ return;
+
+ /* Find the max width/height of a character and add the spacing so */
+ /* that we can use this value to calculate the x,y of the character.*/
+ cWidth = (cWidth * pfntMetrics->fntXScale) + pfntMetrics->fntXSpacing;
+ cHeight = (cHeight * pfntMetrics->fntYScale) + pfntMetrics->fntYSpacing;
+
+ /* Modify the text vertex buffer based on the fntMetrics structure. */
+ for( index = 0; index < cIndex; index++ )
+ {
+ /* Scale the character. */
+ TextVertices[index].sx *= pfntMetrics->fntXScale;
+ TextVertices[index].sy *= pfntMetrics->fntYScale;
+
+ /* Move the character. */
+ TextVertices[index].sx += (cWidth*x);
+ TextVertices[index].sy += (cHeight*y);
+
+ /* Set the color. */
+ TextVertices[index].color = pfntMetrics->dwColor;
+ }
+
+
+ /* Set the states that slim things down. */
+ pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_NONE );
+ pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_FILLMODE, D3DFILL_SOLID );
+ pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_ZENABLE, FALSE );
+ pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE , FALSE );
+ pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_ALPHATESTENABLE, FALSE );
+ pfntMetrics->lpD3DDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, FALSE );
+
+ /* Blast them baby... */
+ pfntMetrics->lpD3DDevice->DrawPrimitive( D3DPT_TRIANGLELIST,
+ D3DFVF_TLVERTEX,
+ (LPVOID)&TextVertices[0],
+ cIndex,
+ (D3DDP_DONOTCLIP | D3DDP_DONOTLIGHT) );
+}
+/*===========================================================================*/
+/* This function takes a single character and draw it using the supplied */
+/* fontmetrics structure. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static int ConvertCharacter( char *c, int cIndex, PD3DFONTMETRICS pfntMetrics )
+{
+ DWORD asciiChar = (int)(*c);
+
+ /* Handle the TOP line. */
+ if ( textBitMasks[asciiChar] & BIT1 )
+ {
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TL_0][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[TL_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TR_0][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[TR_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TR_1][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[TR_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TR_1][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[TR_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TL_1][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[TL_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TL_0][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[TL_0][1] );
+ }
+
+ /* Handle the TOP/BOTTOM RIGHT lines. */
+ // if ( textBitMasks[index] & (BIT2|BIT3) )
+ if ( 1 == 0 )
+ {
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TR_1][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[TR_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TRR][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[TRR][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BRR][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[BRR][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BRR][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[BRR][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BR_0][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[BR_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TR_1][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[TR_1][1] );
+ }
+ else
+ {
+ if ( textBitMasks[asciiChar] & BIT2 )
+ {
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TR_1][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[TR_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TRR][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[TRR][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[MRR_0][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[MRR_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[MRR_0][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[MRR_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[MR_0][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[MR_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TR_1][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[TR_1][1] );
+ }
+ if ( textBitMasks[asciiChar] & BIT3 )
+ {
+ TextVertices[cIndex].sx = D3DVAL( lCoords[MR_1][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[MR_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[MRR_1][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[MRR_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BRR][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[BRR][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BRR][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[BRR][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BR_0][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[BR_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[MR_1][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[MR_1][1] );
+ }
+ }
+
+ /* Handle the TOP/BOTTOM LEFT lines. */
+ // if ( textBitMasks[asciiChar] & (BIT5|BIT6) )
+ if ( 1 == 0 )
+ {
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TLL][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[TLL][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TL_1][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[TL_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BL_0][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[BL_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BL_0][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[BL_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BLL][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[BLL][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TLL][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[TLL][1] );
+ }
+ else
+ {
+ if ( textBitMasks[asciiChar] & BIT5 )
+ {
+ TextVertices[cIndex].sx = D3DVAL( lCoords[MLL_1][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[MLL_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[ML_1][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[ML_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BL_0][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[BL_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BL_0][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[BL_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BLL][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[BLL][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[MLL_1][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[MLL_1][1] );
+ }
+ if ( textBitMasks[asciiChar] & BIT6 )
+ {
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TLL][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[TLL][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TL_1][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[TL_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[ML_0][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[ML_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[ML_0][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[ML_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[MLL_0][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[MLL_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[TLL][0] );
+ TextVertices[cIndex++].sy = D3DVAL( lCoords[TLL][1] );
+ }
+ }
+
+ /* Handle the MIDDLE line. */
+ if ( textBitMasks[asciiChar] & BIT7 )
+ {
+ TextVertices[cIndex].sx = D3DVAL( lCoords[ML_0][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[ML_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[MR_0][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[MR_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[MR_1][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[MR_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[MR_1][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[MR_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[ML_1][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[ML_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[ML_0][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[ML_0][1] );
+ }
+
+ /* Handle the BOTTOM line. */
+ if ( textBitMasks[asciiChar] & BIT4 )
+ {
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BL_0][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[BL_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BR_0][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[BR_0][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BR_1][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[BR_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BR_1][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[BR_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BL_1][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[BL_1][1] );
+ TextVertices[cIndex].sx = D3DVAL( lCoords[BL_0][0] );
+ TextVertices[cIndex++].sy= D3DVAL( lCoords[BL_0][1] );
+ }
+
+ return cIndex;
+}
+
+#undef CM
+#undef CY
+#undef CX
+#undef CT
+
+#undef TLL
+#undef TRR
+#undef TL_0
+#undef TL_1
+#undef TR_0
+#undef TR_1
+
+#undef MLL_0
+#undef MLL_1
+#undef MRR_0
+#undef MRR_1
+
+#undef ML_0
+#undef ML_1
+#undef MR_0
+#undef MR_1
+
+#undef BL_0
+#undef BL_1
+#undef BR_0
+#undef BR_1
+#undef BLL
+#undef BRR
+
+#undef BIT1
+#undef BIT2
+#undef BIT3
+#undef BIT4
+#undef BIT5
+#undef BIT6
+#undef BIT7
+
+#undef TOP
+#undef MIDDLE
+#undef BOTTOM
+#undef TLEFT
+#undef BLEFT
+#undef LEFT
+#undef TRIGHT
+#undef BRIGHT
+#undef RIGHT
+#undef ALL
+ \ No newline at end of file
diff --git a/src/mesa/drivers/d3d/D3DTextureMgr.cpp b/src/mesa/drivers/d3d/D3DTextureMgr.cpp
new file mode 100644
index 0000000000..9375e51e32
--- /dev/null
+++ b/src/mesa/drivers/d3d/D3DTextureMgr.cpp
@@ -0,0 +1,948 @@
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#include "D3DHAL.h"
+/*===========================================================================*/
+/* Local function prototypes. */
+/*===========================================================================*/
+static void UpdateTexture( PTM_OBJECT pTMObj, BOOL bVideo, RECT *pRect, UCHAR *pixels );
+static BOOL LoadTextureInVideo( PMESAD3DHAL pHAL, PTM_OBJECT pTMObj );
+static BOOL FreeTextureMemory( PMESAD3DHAL pHAL, PTM_OBJECT pTMObject );
+static BOOL DestroyTextureObject( PMESAD3DHAL pHAL, PTM_OBJECT pTMObject );
+HRESULT CALLBACK EnumPFHook( LPDDPIXELFORMAT lpDDPixFmt, LPVOID lpContext );
+/*===========================================================================*/
+/* This function will simply set the top of stack to NULL. I only used it */
+/* just incase I want to add something later. */
+/*===========================================================================*/
+/* RETURN: TRUE. */
+/*===========================================================================*/
+BOOL InitTMgrHAL( PMESAD3DHAL pHAL )
+{
+ DPF(( DBG_FUNC, "InitTMgrHAL();" ));
+
+ /* Be clean my friend. */
+ pHAL->pTMList = NULL;
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* This function will walk the Texture Managers linked list and destroy all */
+/* surfaces (SYSTEM/VIDEO). The texture objects themselves also will be */
+/* freed. */
+/* NOTE: this is per/context. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void TermTMgrHAL( PMESAD3DHAL pHAL )
+{
+ DPF(( DBG_FUNC, "TermTMgrHAL();" ));
+
+ if ( pHAL && pHAL->pTMList )
+ {
+ /* Destroy the surface and remove the TMO from the stack. */
+ while( DestroyTextureObject(pHAL,NULL) );
+
+ /* Be clean my friend. */
+ pHAL->pTMList = NULL;
+ }
+}
+/*===========================================================================*/
+/* This function is a HACK as I don't know how I can disable a texture with-*/
+/* out booting it out. Is there know state change? */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" void DisableTMgrHAL( PMESAD3DSHARED pShared )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+
+ DPF(( DBG_FUNC, "DisableTMgrHAL();" ));
+
+ /* Check too see that we have a valid context. */
+ if ( (pHAL == NULL) && (pHAL->lpD3DDevice != NULL) )
+ {
+ DPF(( DBG_TXT_WARN, "Null HAL/Direct3D Device!" ));
+ return;
+ }
+
+ // TODO: This is a hack to shut off textures.
+ pHAL->lpD3DDevice->SetTexture( 0, NULL );
+}
+/*===========================================================================*/
+/* This function is the only entry into the TextureManager that Mesa/wgl */
+/* will see. It uses a dwAction to specify what we are doing. I did this as*/
+/* depending on the cards resources the action taken can change. */
+/* When this function is called we will always search the Texture Managers */
+/* linked list (per context remember) and try and find a structure that has */
+/* the same dwName. If we have a match we pull it out of the list and put it*/
+/* at the top of the list (TOL). If we don't find one then we create a struc*/
+/* and put it a TOL. This TOL idea makes for some caching as we will always */
+/* destroy Texture Surfaces from the bottom up... */
+/* All texture objects at this point will create a texture surface in System*/
+/* memory (SMEM). Then we will copy the Mesa texture into the surface using */
+/* the 'pixel' struc to get the translation info. So now this means that all*/
+/* textures that Mesa gives me I will have a Surface with a copy. If Mesa */
+/* changes the texture the I update the surface in (SMEM). */
+/* Now we have a texture struc and a Texture Surface in SMEM. At this point*/
+/* we create another surface on the card (VMEM). Finally we blt from the */
+/* SMEM to the VMEM and set the texture as current. Why do I need two? First*/
+/* this solves square textures. If the cards CAPS is square textures only */
+/* then I change the dimensions of the VMEM surface and the blt solves it for*/
+/* me. Second it saves me from filling D3D textures over and over if the */
+/* card needs to be creating and destroying surfaces because of low memory. */
+/* The surface in SMEM is expected to work always. When a surface has to be*/
+/* created in VMEM then we put it in a loop that tries to create the surface.*/
+/* If we create the surface ok then we brake from the loop. If we fail then */
+/* we will call 'FreeTextureMemory' that will return TRUE/FALSE as to whether*/
+/* memory was freed. If memory was freed then we can try again. If no memory*/
+/* was freed then it just can't fit. */
+/* 'FreeTextureMemory' will find the end of the list and start freeing VMEM */
+/* (never SMEM) surfaces that are not locked. */
+/* BIND - when we bind and there is a texture struct with a texture surface */
+/* in VMEM then we just make it current. If we have a struct and a surface */
+/* in SMEM but no VMEM surface then we create the surface in VMEM and blt */
+/* from the SMEM surface. If we have nothing its just like a creation... */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+extern "C" BOOL CreateTMgrHAL( PMESAD3DSHARED pShared, DWORD dwName, int level, DWORD dwRequestFlags,
+ RECT *rectDirty, DWORD dwWidth, DWORD dwHeight, DWORD dwAction, void *pPixels )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+ PTM_OBJECT pTMObj,
+ pTemp;
+ DDSURFACEDESC2 ddsd2;
+ HRESULT rc;
+
+
+ DPF(( DBG_FUNC, "CreateTMgrHAL();" ));
+
+ DPF(( DBG_TXT_INFO, "Texture:" ));
+ DPF(( DBG_TXT_INFO, "cx: %d cy: %d", dwWidth, dwHeight ));
+ DPF(( DBG_TXT_INFO, "Rect:" ));
+ if ( rectDirty )
+ {
+ DPF(( DBG_TXT_INFO, "x0: %d y0: %d", rectDirty->left, rectDirty->top ));
+ DPF(( DBG_TXT_INFO, "x1: %d y1: %d", rectDirty->right, rectDirty->bottom ));
+ }
+
+ /* Check too see that we have a valid context. */
+ if ( (pHAL == NULL) && (pHAL->lpD3DDevice != NULL) )
+ {
+ DPF(( DBG_TXT_WARN, "Null HAL/Direct3D Device!" ));
+ return FALSE;
+ }
+
+ /*=================================================*/
+ /* See if we can find this texture object by name. */
+ /*=================================================*/
+ for( pTMObj = pHAL->pTMList; pTMObj && (pTMObj->dwName != dwName); pTMObj = pTMObj->next );
+
+ /*=========================================================*/
+ /* Allocate a new object if we didn't get a matching name. */
+ /*=========================================================*/
+ if ( pTMObj == NULL )
+ {
+ pTMObj = (PTM_OBJECT)ALLOC( sizeof(TM_OBJECT) );
+ if ( pTMObj == NULL )
+ return FALSE;
+ memset( pTMObj, 0, sizeof(TM_OBJECT) );
+
+ /* Put the object at the beginning of the list. */
+ pTMObj->next = pHAL->pTMList;
+ if ( pTMObj->next )
+ {
+ pTemp = pTMObj->next;
+ pTemp->prev = pTMObj;
+ }
+ pHAL->pTMList = pTMObj;
+ }
+ else
+ {
+ /*===============================================================*/
+ /* Make some caching happen by pulling this object to the front. */
+ /*===============================================================*/
+ if ( pHAL->pTMList != pTMObj )
+ {
+ /* Pull the object out of the list. */
+ if ( pTMObj->prev )
+ {
+ pTemp = pTMObj->prev;
+ pTemp->next = pTMObj->next;
+ }
+ if ( pTMObj->next )
+ {
+ pTemp = pTMObj->next;
+ pTemp->prev = pTMObj->prev;
+ }
+
+ pTMObj->prev = NULL;
+ pTMObj->next = NULL;
+
+ /* Put the object at the front of the list. */
+ pTMObj->next = pHAL->pTMList;
+ if ( pTMObj->next )
+ {
+ pTemp = pTMObj->next;
+ pTemp->prev = pTMObj;
+ }
+ pHAL->pTMList = pTMObj;
+ }
+ }
+
+ /*========================================================*/
+ /* If we are doing BIND and the texture is in VID memory. */
+ /*========================================================*/
+ if ( (dwAction == TM_ACTION_BIND) && pTMObj->lpDDS_Video )
+ {
+ DPF(( DBG_TXT_PROFILE, "Cache HIT (%d)", dwName ));
+
+ /* Make this the current texture. */
+ rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );
+ if ( FAILED(rc) )
+ {
+ DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));
+ pHAL->lpD3DDevice->SetTexture( 0, NULL );
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /*=================================================================*/
+ /* If we are doing BIND and the texture is at least in SYS memory. */
+ /*=================================================================*/
+ if ( (dwAction == TM_ACTION_BIND) && pTMObj->lpDDS_System )
+ {
+ DPF(( DBG_TXT_PROFILE, "Cache MISS (%d)", dwName ));
+
+ /* Create the texture on the card. */
+ rc = LoadTextureInVideo( pHAL, pTMObj );
+ if ( rc == FALSE )
+ return FALSE;
+
+ /* Make this the current texture. */
+ rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );
+ if ( FAILED(rc) )
+ {
+ DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));
+ pHAL->lpD3DDevice->SetTexture( 0, NULL );
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /*=========================================================*/
+ /* If we are doing UPDATE then try in VID first for speed. */
+ /*=========================================================*/
+ if ( (dwAction == TM_ACTION_UPDATE) && pTMObj->lpDDS_Video &&
+ !(pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY) )
+ {
+ DPF(( DBG_TXT_INFO, "Fix the SubTexture update Leigh!" ));
+
+ /* Update the texture on the card. */
+ UpdateTexture( pTMObj, TRUE, rectDirty, (UCHAR *)pPixels );
+
+ /* We updated the texture in VID so kill the SYS so we know its dirty. */
+ if ( pTMObj->lpDDS_System )
+ {
+ DPF(( DBG_TXT_INFO, "Release texture (SYS)" ));
+ DX_RESTORE( pTMObj->lpDDS_System );
+ pTMObj->lpDDS_System->Release();
+ pTMObj->lpDDS_System = NULL;
+ }
+
+ /* Make this the current texture. */
+ rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );
+ if ( FAILED(rc) )
+ {
+ DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));
+ pHAL->lpD3DDevice->SetTexture( 0, NULL );
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /*===========================================================*/
+ /* If we are doing UPDATE then try in SYS still gives speed. */
+ /*===========================================================*/
+ if ( (dwAction == TM_ACTION_UPDATE) && pTMObj->lpDDS_System )
+ {
+ DPF(( DBG_TXT_INFO, "Fix the SubTexture update Leigh!" ));
+
+ /* Update the texture in SYS. */
+ UpdateTexture( pTMObj, FALSE, NULL, (UCHAR *)pPixels );
+
+ /* We updated the SYS texture only so now blt to the VID. */
+ rc = LoadTextureInVideo( pHAL, pTMObj );
+ if ( rc == FALSE )
+ return FALSE;
+
+ /* Make this the current texture. */
+ rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );
+ if ( FAILED(rc) )
+ {
+ DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));
+ pHAL->lpD3DDevice->SetTexture( 0, NULL );
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ /* At this point we have a valid Texture Manager Object with updated */
+ /* links. We now need to create or update a texture surface that is */
+ /* in system memory. Every texture has a copy in system so we can use*/
+ /* blt to solve problems with textures allocated on the card (square */
+ /* only textures, pixelformats...). */
+
+ // TODO: make support for update also. Dirty rectangle basicly...
+
+ /* Kill the interface if we have one no matter what. */
+ if ( pTMObj->lpD3DTexture2 )
+ {
+ DPF(( DBG_TXT_INFO, "Release Texture2" ));
+ pTMObj->lpD3DTexture2->Release();
+ pTMObj->lpD3DTexture2 = NULL;
+ }
+
+ /* Kill the system surface. TODO: should try to get the SubIMage going again */
+ if ( pTMObj->lpDDS_System )
+ {
+ DPF(( DBG_TXT_INFO, "Release texture (SYS)" ));
+ DX_RESTORE( pTMObj->lpDDS_System );
+ pTMObj->lpDDS_System->Release();
+ pTMObj->lpDDS_System = NULL;
+ }
+
+ /* Kill the Video surface. TODO: need some reuse system... */
+ if ( pTMObj->lpDDS_Video )
+ {
+ DPF(( DBG_TXT_INFO, "Release texture (VID)" ));
+ DX_RESTORE( pTMObj->lpDDS_Video );
+ pTMObj->lpDDS_Video->Release();
+ pTMObj->lpDDS_Video = NULL;
+ }
+
+ /*================================================================*/
+ /* Translate the the Mesa/OpenGL pixel channels to the D3D flags. */
+ /*================================================================*/
+ switch( dwRequestFlags )
+ {
+ case GL_ALPHA:
+ dwRequestFlags = DDPF_ALPHA;
+ DPF(( DBG_TXT_WARN, "GL_ALPHA not supported!)" ));
+ return FALSE;
+
+ case GL_INTENSITY:
+ case GL_LUMINANCE:
+ DPF(( DBG_TXT_WARN, "GL_INTENSITY/GL_LUMINANCE not supported!)" ));
+ dwRequestFlags = DDPF_LUMINANCE;
+ return FALSE;
+
+ case GL_LUMINANCE_ALPHA:
+ DPF(( DBG_TXT_WARN, "GL_LUMINANCE_ALPHA not supported!)" ));
+ dwRequestFlags = DDPF_LUMINANCE | DDPF_ALPHAPIXELS;
+ return FALSE;
+
+ case GL_RGB:
+ DPF(( DBG_TXT_INFO, "Texture -> GL_RGB" ));
+ dwRequestFlags = DDPF_RGB;
+ break;
+
+ case GL_RGBA:
+ DPF(( DBG_TXT_INFO, "Texture -> GL_RGBA" ));
+ dwRequestFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
+ break;
+ }
+
+ /*==============================*/
+ /* Populate the texture object. */
+ /*==============================*/
+ pTMObj->dwName = dwName;
+ pTMObj->lpD3DDevice = pHAL->lpD3DDevice;
+ pTMObj->dwFlags = dwRequestFlags;
+ if ( pHAL->D3DHWDevDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_SQUAREONLY )
+ {
+ DPF(( DBG_TXT_INFO, "Convert to Square..." ));
+ pTMObj->dwSHeight = dwHeight;
+ pTMObj->dwSWidth = dwWidth;
+
+ /* Shrink non-square textures. */
+ pTMObj->dwVHeight = (dwHeight > dwWidth) ? dwWidth : dwHeight;
+ pTMObj->dwVWidth = (dwHeight > dwWidth) ? dwWidth : dwHeight;
+ }
+ else
+ {
+ pTMObj->dwSHeight = dwHeight;
+ pTMObj->dwSWidth = dwWidth;
+ pTMObj->dwVHeight = dwHeight;
+ pTMObj->dwVWidth = dwWidth;
+ }
+
+ /*========================*/
+ /* Create SYSTEM surface. */
+ /*========================*/
+
+ /* Request a surface in system memory. */
+ memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
+ ddsd2.dwSize = sizeof( DDSURFACEDESC2 );
+ ddsd2.dwWidth = pTMObj->dwSWidth;
+ ddsd2.dwHeight = pTMObj->dwSHeight;
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_SYSTEMMEMORY;
+ ddsd2.ddsCaps.dwCaps2 = 0L;
+ memset( &ddsd2.ddpfPixelFormat, 0, sizeof(DDPIXELFORMAT) );
+ ddsd2.ddpfPixelFormat.dwSize = sizeof( DDPIXELFORMAT );
+ ddsd2.ddpfPixelFormat.dwFlags = dwRequestFlags;
+ rc = pHAL->lpD3DDevice->EnumTextureFormats( EnumPFHook, &ddsd2.ddpfPixelFormat );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "EnumerTextureFormats (SYSTEM)->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Create the surface using the enumerated pixelformat. */
+ rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pTMObj->lpDDS_System, NULL );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "CreateSurface (TEXTURE/SYSTEM)->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Solve the pixel mapping info using the surface pixelformat. */
+ Solve8BitChannelPixelFormat( &ddsd2.ddpfPixelFormat, &pTMObj->pixel );
+
+ /*===================================================================*/
+ /* Fill the texture using the PixelInfo structure to do the mapping. */
+ /*===================================================================*/
+ UpdateTexture( pTMObj, FALSE, NULL, (UCHAR *)pPixels );
+
+ /*=======================*/
+ /* Create VIDEO surface. */
+ /*=======================*/
+ rc = LoadTextureInVideo( pHAL, pTMObj );
+ if ( rc == FALSE )
+ return FALSE;
+
+ /* Make this the current texture. */
+ rc = pHAL->lpD3DDevice->SetTexture( 0, pTMObj->lpD3DTexture2 );
+ if ( FAILED(rc) )
+ {
+ DPF(( DBG_TXT_WARN, "Failed SetTexture() (%s)", ErrorStringD3D(rc) ));
+ pHAL->lpD3DDevice->SetTexture( 0, NULL );
+ return FALSE;
+ }
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* This function will handle the creation and destruction of the texture */
+/* surfaces on the card. Using the dw'V'Width/Height dimensions the call */
+/* try and create the texture on the card and keep using FreeTextureMemory */
+/* until the surace can be created. Once the surface is created we get the */
+/* interface that we will use to make it the current texture. I didn't put */
+/* the code to make the texture current in this function as BIND needs to */
+/* use the same code and this function doesn't always get called when we do a*/
+/* bind. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+static BOOL LoadTextureInVideo( PMESAD3DHAL pHAL, PTM_OBJECT pTMObj )
+{
+ DDSURFACEDESC2 ddsd2;
+ HRESULT rc;
+
+ DPF(( DBG_FUNC, "LoadTextureInVideo();" ));
+
+ /* Kill the interface if we have one no matter what. */
+ if ( pTMObj->lpD3DTexture2 )
+ {
+ DPF(( DBG_TXT_INFO, "Release Texture2" ));
+ pTMObj->lpD3DTexture2->Release();
+ pTMObj->lpD3DTexture2 = NULL;
+ }
+
+ /* Kill the Video surface. TODO: need some reuse system... */
+ if ( pTMObj->lpDDS_Video )
+ {
+ DPF(( DBG_TXT_INFO, "Release texture (VID)" ));
+ DX_RESTORE( pTMObj->lpDDS_Video );
+ pTMObj->lpDDS_Video->Release();
+ pTMObj->lpDDS_Video = NULL;
+ }
+
+ /* Request a surface in Video memory. */
+ memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
+ ddsd2.dwSize = sizeof( DDSURFACEDESC2 );
+ ddsd2.dwWidth = pTMObj->dwVWidth;
+ ddsd2.dwHeight = pTMObj->dwVHeight;
+ ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
+ ddsd2.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY;
+ ddsd2.ddsCaps.dwCaps2 = 0L;
+ memset( &ddsd2.ddpfPixelFormat, 0, sizeof(DDPIXELFORMAT) );
+ ddsd2.ddpfPixelFormat.dwSize = sizeof( DDPIXELFORMAT );
+ ddsd2.ddpfPixelFormat.dwFlags = pTMObj->dwFlags;
+ rc = pHAL->lpD3DDevice->EnumTextureFormats( EnumPFHook, &ddsd2.ddpfPixelFormat );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "EnumerTextureFormats ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Make sure we lock so we don't nuke this texture trying to free memory for it. */
+ pTMObj->bLock = TRUE;
+
+ /* Start a loop that will free all textures until we have created the texture */
+ /* surface or we can't free up more memory. */
+ do
+ {
+ /* Try to create the texture surface. */
+ rc = pHAL->lpDD4->CreateSurface( &ddsd2, &pTMObj->lpDDS_Video, NULL );
+ if ( !FAILED(rc) )
+ break;
+
+ DPF(( DBG_TXT_INFO, "Free Texture Memory" ));
+
+ /* DestroyTexture will return TRUE if a surface was freed. */
+ } while( FreeTextureMemory(pHAL,NULL) );
+
+ /* Make sure we unlock or we won't be able to nuke the TMO later. */
+ pTMObj->bLock = FALSE;
+
+ /* Did we create a valid texture surface? */
+ if ( FAILED(rc) )
+ {
+ DPF(( DBG_TXT_WARN, "Failed to load texture" ));
+ pHAL->lpD3DDevice->SetTexture( 0, NULL );
+ return FALSE;
+ }
+
+ DX_RESTORE( pTMObj->lpDDS_System );
+ DX_RESTORE( pTMObj->lpDDS_Video );
+
+ DPF(( DBG_TXT_INFO, "Texture Blt SYSTEM -> VID" ));
+
+ /* Now blt the texture in system memory to the card. */
+ rc = pTMObj->lpDDS_Video->Blt( NULL, pTMObj->lpDDS_System, NULL, DDBLT_WAIT, NULL );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "Blt (TEXTURE) ->", ErrorStringD3D(rc) );
+ return FALSE;
+ }
+
+ /* Get the Texture interface that is used to render with. */
+ pTMObj->lpDDS_Video->QueryInterface( IID_IDirect3DTexture2, (void **)&pTMObj->lpD3DTexture2 );
+ if ( pTMObj->lpD3DTexture2 == NULL )
+ {
+ DPF(( DBG_TXT_WARN, "Failed QueryTextureInterface" ));
+ pHAL->lpD3DDevice->SetTexture( 0, NULL );
+ return FALSE;
+ }
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* If this function gets a texture object struc then we will try and free */
+/* it. If we get a NULL then we will search from the bottom up and free one */
+/* VMEM surface. I can only free when the surface isn't locked and of course*/
+/* there must be a VMEM surface. We never free SMEM surfaces as that isn't */
+/* the point. */
+/* TODO: should have a pointer to the bottom of the stack really. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static BOOL FreeTextureMemory( PMESAD3DHAL pHAL, PTM_OBJECT pTMObject )
+{
+ PTM_OBJECT pCurrent;
+ BOOL bFreed = FALSE;
+
+ DPF(( DBG_FUNC, "FreeTextureMemory();" ));
+ DPF(( DBG_TXT_WARN, "FREE TEXTURE!" ));
+
+ /* Just to be safe. */
+ if ( !pHAL || !pHAL->pTMList )
+ {
+ DPF(( DBG_TXT_WARN, "FreeTextureMemory() -> NULL pHAL/pHAL->pTMList" ));
+ return FALSE;
+ }
+
+ /* Free the last texture in the list. */
+ if ( pTMObject == NULL )
+ {
+ DPF(( DBG_TXT_INFO, "Free Last texture in cache" ));
+
+ /* Find the last texture object. */
+ for( pCurrent = pHAL->pTMList; pCurrent->next; pCurrent = pCurrent->next );
+
+ /* Now backup until we find a texture on the card. */
+ while( pCurrent && (pCurrent->lpDDS_Video == NULL) && (pCurrent->bLock == FALSE) )
+ pCurrent = pCurrent->prev;
+
+ /* Didn't find anything. */
+ if ( pCurrent == NULL )
+ {
+ DPF(( DBG_TXT_INFO, "No texture memory freed" ));
+ return FALSE;
+ }
+ }
+ else
+ {
+ /* See if we can find this texture object. */
+ for( pCurrent = pHAL->pTMList; pCurrent && (pCurrent != pTMObject); pCurrent = pCurrent->next );
+
+ /* Didn't find anything. */
+ if ( pCurrent == NULL )
+ {
+ DPF(( DBG_TXT_INFO, "Requested texture to be freed NOT FOUND" ));
+ return FALSE;
+ }
+ }
+
+ /* Can't free this baby. */
+ if ( pCurrent->bLock == TRUE )
+ {
+ DPF(( DBG_TXT_WARN, "Requested texture LOCKED" ));
+ return FALSE;
+ }
+
+ /* Free the texture memory. */
+ if ( pCurrent->lpD3DTexture2 )
+ {
+ DPF(( DBG_TXT_INFO, "Release Texture2" ));
+ pCurrent->lpD3DTexture2->Release();
+ pCurrent->lpD3DTexture2 = NULL;
+ bFreed = TRUE;
+ }
+ if ( pCurrent->lpDDS_Video )
+ {
+ DPF(( DBG_TXT_INFO, "Release texture (VID):" ));
+ DPF(( DBG_TXT_INFO, "dwName: %d", pCurrent->dwName ));
+ DPF(( DBG_TXT_INFO, "cx: %d, cy: %d", pCurrent->dwVWidth, pCurrent->dwVHeight ));
+ pCurrent->lpDDS_Video->Release();
+ pCurrent->lpDDS_Video = NULL;
+ bFreed = TRUE;
+ }
+
+ return bFreed;
+}
+/*===========================================================================*/
+/* This function searches the linked list of texture objects in the supplied*/
+/* D3Dwrapper structure. If it finds a match it will free it and pull it out*/
+/* of the linked list. The function works on the bases of a matching pointer*/
+/* to the object (not matching content). */
+/* If the function gets passed a NULL then we want to free the last texture */
+/* object in the list. Used in a loop to destory all. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+static BOOL DestroyTextureObject( PMESAD3DHAL pHAL, PTM_OBJECT pTMObject )
+{
+ PTM_OBJECT pCurrent;
+
+ DPF(( DBG_FUNC, "DestoryTextureObject();" ));
+
+ /* Just to be safe. */
+ if ( !pHAL || !pHAL->pTMList )
+ {
+ DPF(( DBG_TXT_WARN, "DestroyTextureObject() -> NULL pHAL/pHAL->pTMList" ));
+ return FALSE;
+ }
+
+ /* Free the last texture in the list. */
+ if ( pTMObject == NULL )
+ {
+ /* Find the last texture object. */
+ for( pCurrent = pHAL->pTMList; pCurrent->next; pCurrent = pCurrent->next );
+ }
+ else
+ {
+ /* See if we can find this texture object. */
+ for( pCurrent = pHAL->pTMList; pCurrent && (pCurrent != pTMObject); pCurrent = pCurrent->next );
+
+ /* Didn't find anything. */
+ if ( pCurrent == NULL )
+ {
+ DPF(( DBG_TXT_WARN, "No textures to be freed" ));
+ return FALSE;
+ }
+ }
+
+ /* Can't free this baby. */
+ if ( pCurrent->bLock == TRUE )
+ {
+ DPF(( DBG_TXT_WARN, "Requested texture to be freed LOCKED" ));
+ return FALSE;
+ }
+
+ /* Free the texture memory. */
+ if ( pCurrent->lpD3DTexture2 )
+ {
+ DPF(( DBG_TXT_INFO, "Release Texture2" ));
+ pCurrent->lpD3DTexture2->Release();
+ pCurrent->lpD3DTexture2 = NULL;
+ }
+ if ( pCurrent->lpDDS_Video )
+ {
+ DPF(( DBG_TXT_INFO, "Release texture (VID):" ));
+ pCurrent->lpDDS_Video->Release();
+ pCurrent->lpDDS_Video = NULL;
+ }
+ if ( pCurrent->lpDDS_System )
+ {
+ DPF(( DBG_TXT_INFO, "Release texture (SYS):" ));
+ pCurrent->lpDDS_System->Release();
+ pCurrent->lpDDS_System = NULL;
+ }
+
+ /* Pull this texture out of the list. */
+ if ( pCurrent == pHAL->pTMList )
+ pHAL->pTMList = NULL;
+ if ( pCurrent->prev )
+ (pCurrent->prev)->next = pCurrent->next;
+ if ( pCurrent->next )
+ (pCurrent->next)->prev = pCurrent->prev;
+ FREE( pCurrent );
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* This function is the callback function that gets called when we are doing*/
+/* an enumeration of the texture formats supported by this device. The choice*/
+/* is made by checking to see if we have a match with the supplied D3D pixel-*/
+/* format. So the enumeration has to pass a desired D3D PF as the user var. */
+/*===========================================================================*/
+/* RETURN: D3DENUMRET_OK, D3DENUMRET_CANCEL. */
+/*===========================================================================*/
+static void UpdateTexture( PTM_OBJECT pTMObj, BOOL bVideo, RECT *pRect, UCHAR *pixels )
+{
+ LPDIRECTDRAWSURFACE4 lpDDS;
+ DDSURFACEDESC2 ddsd2;
+ DWORD srcPitch,
+ dwHeight,
+ dwWidth,
+ dwCol,
+ dwColor;
+ UCHAR *pSrc,
+ *pSrcRow,
+ *pDest,
+ *pDestRow;
+ int rc;
+
+ // TODO: Do I need to pass the h/w when its in the object!
+ DPF(( DBG_FUNC, "UpdateTexture();" ));
+
+ /* Get the surface pointer we are looking for. */
+ lpDDS = (bVideo) ? pTMObj->lpDDS_Video : pTMObj->lpDDS_System;
+
+ /*===================================================================*/
+ /* Fill the texture using the PixelInfo structure to do the mapping. */
+ /*===================================================================*/
+
+ /* Get the surface pointer. */
+ memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
+ ddsd2.dwSize = sizeof(DDSURFACEDESC2);
+ rc = lpDDS->Lock( NULL, &ddsd2, DDLOCK_WAIT, NULL );
+ if ( FAILED(rc) )
+ {
+ RIP( NULL, "Lock (TEXTURE/SYSTEM)->", ErrorStringD3D(rc) );
+ return;
+ }
+
+ /* For now we are only updating the system surface so use its dimensions. */
+ dwWidth = (bVideo) ? pTMObj->dwVWidth : pTMObj->dwSWidth;
+ dwHeight = (bVideo) ? pTMObj->dwVHeight : pTMObj->dwSHeight;
+
+ /* If we are updating the whole surface then the pDest/pSrc will */
+ /* always be the same. */
+ if ( pRect == NULL )
+ {
+ pDest = (UCHAR *)ddsd2.lpSurface;
+ pSrc = pixels;
+ }
+
+ /* Fill the texture surface based on the pixelformat flags. */
+ if ( pTMObj->dwFlags == (DDPF_RGB | DDPF_ALPHAPIXELS) )
+ {
+ srcPitch = dwWidth * 4;
+ if ( pRect )
+ {
+ pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);
+ pSrc = pixels + (pRect->top * dwWidth * 4) + (pRect->left * 4);
+ dwHeight = (pRect->bottom - pRect->top);
+ dwWidth = (pRect->right - pRect->left);
+ }
+
+ for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )
+ {
+ for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )
+ {
+ dwColor = ( ((DWORD)(*(pSrc ) * pTMObj->pixel.rScale)) << pTMObj->pixel.rShift );
+ dwColor |= ( ((DWORD)(*(pSrc+1) * pTMObj->pixel.gScale)) << pTMObj->pixel.gShift );
+ dwColor |= ( ((DWORD)(*(pSrc+2) * pTMObj->pixel.bScale)) << pTMObj->pixel.bShift );
+ if ( pTMObj->pixel.aScale == -1.0 )
+ dwColor |= ( (*(pSrc+3) & 0x80) ? (1 << pTMObj->pixel.aShift) : 0 );
+ else
+ dwColor |= ( ((DWORD)(*(pSrc+3) * pTMObj->pixel.aScale)) << pTMObj->pixel.aShift );
+ memcpy( pDest, &dwColor, pTMObj->pixel.cb );
+ pDest += pTMObj->pixel.cb;
+ pSrc += 4;
+ }
+ }
+ }
+ else if ( pTMObj->dwFlags == DDPF_RGB )
+ {
+ srcPitch = dwWidth * 3;
+ if ( pRect )
+ {
+ pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);
+ pSrc = pixels + (pRect->top * dwWidth * 3) + (pRect->left * 3);
+ dwHeight = (pRect->bottom - pRect->top);
+ dwWidth = (pRect->right - pRect->left);
+ }
+
+ for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )
+ {
+ for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )
+ {
+ dwColor = ( ((DWORD)(*(pSrc ) * pTMObj->pixel.rScale)) << pTMObj->pixel.rShift );
+ dwColor |= ( ((DWORD)(*(pSrc+1) * pTMObj->pixel.gScale)) << pTMObj->pixel.gShift );
+ dwColor |= ( ((DWORD)(*(pSrc+2) * pTMObj->pixel.bScale)) << pTMObj->pixel.bShift );
+ memcpy( pDest, &dwColor, pTMObj->pixel.cb );
+ pDest += pTMObj->pixel.cb;
+ pSrc += 3;
+ }
+ }
+ }
+ else if ( pTMObj->dwFlags == (DDPF_LUMINANCE | DDPF_ALPHAPIXELS) )
+ {
+ srcPitch = dwWidth * 2;
+ if ( pRect )
+ {
+ pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);
+ pSrc = pixels + (pRect->top * dwWidth * 2) + (pRect->left * 2);
+ dwHeight = (pRect->bottom - pRect->top);
+ dwWidth = (pRect->right - pRect->left);
+ }
+
+ for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )
+ {
+ for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )
+ {
+ dwColor = ( ((DWORD)(*(pSrc ) * pTMObj->pixel.rScale)) << pTMObj->pixel.rShift );
+ if ( pTMObj->pixel.aScale == -1.0 )
+ dwColor |= ( (*(pSrc+1) & 0x80) ? (1 << pTMObj->pixel.aShift) : 0 );
+ else
+ dwColor |= ( ((DWORD)(*(pSrc+1) * pTMObj->pixel.aScale)) << pTMObj->pixel.aShift );
+ memcpy( pDest, &dwColor, pTMObj->pixel.cb );
+ pDest += pTMObj->pixel.cb;
+ pSrc += 2;
+ }
+ }
+ }
+ else if ( pTMObj->dwFlags == DDPF_LUMINANCE )
+ {
+ srcPitch = dwWidth;
+ if ( pRect )
+ {
+ pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);
+ pSrc = pixels + (pRect->top * dwWidth) + (pRect->left);
+ dwHeight = (pRect->bottom - pRect->top);
+ dwWidth = (pRect->right - pRect->left);
+ }
+
+ for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )
+ {
+ for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )
+ {
+ dwColor = ( ((DWORD)(*pSrc * pTMObj->pixel.rScale)) << pTMObj->pixel.rShift );
+ memcpy( pDest, &dwColor, pTMObj->pixel.cb );
+ pDest += pTMObj->pixel.cb;
+ pSrc++;
+ }
+ }
+ }
+ else if ( pTMObj->dwFlags == DDPF_ALPHAPIXELS )
+ {
+ srcPitch = dwWidth;
+ if ( pRect )
+ {
+ pDest = ((UCHAR *)ddsd2.lpSurface) + (pRect->top * ddsd2.lPitch) + (pRect->left * pTMObj->pixel.cb);
+ pSrc = pixels + (pRect->top * dwWidth) + (pRect->left);
+ dwHeight = (pRect->bottom - pRect->top);
+ dwWidth = (pRect->right - pRect->left);
+ }
+
+ for( pDestRow = pDest, pSrcRow = pSrc; dwHeight > 0; dwHeight--, pDestRow += ddsd2.lPitch, pSrcRow += srcPitch )
+ {
+ for( dwCol = 0, pDest = pDestRow, pSrc = pSrcRow; dwCol < dwWidth; dwCol++ )
+ {
+ if ( pTMObj->pixel.aScale == -1.0 )
+ dwColor = ( (*pSrc & 0x80) ? (1 << pTMObj->pixel.aShift) : 0 );
+ else
+ dwColor = ( ((DWORD)(*pSrc * pTMObj->pixel.aScale)) << pTMObj->pixel.aShift );
+ memcpy( pDest, &dwColor, pTMObj->pixel.cb );
+ pDest += pTMObj->pixel.cb;
+ pSrc++;
+ }
+ }
+ }
+
+ /* Unlock the surface. */
+ rc = lpDDS->Unlock( NULL );
+ if ( FAILED(rc) )
+ {
+ RIP( NULL, "Unlock (TEXTURE/SYSTEM)->", ErrorStringD3D(rc) );
+ }
+}
+/*===========================================================================*/
+/* This function is the callback function that gets called when we are doing*/
+/* an enumeration of the texture formats supported by this device. The choice*/
+/* is made by checking to see if we have a match with the supplied D3D pixel-*/
+/* format. So the enumeration has to pass a desired D3D PF as the user var. */
+/*===========================================================================*/
+/* RETURN: D3DENUMRET_OK, D3DENUMRET_CANCEL. */
+/*===========================================================================*/
+HRESULT CALLBACK EnumPFHook( LPDDPIXELFORMAT lpDDPixFmt, LPVOID lpContext )
+{
+ LPDDPIXELFORMAT lpDDPixFmtRequest = (LPDDPIXELFORMAT)lpContext;
+ PIXELINFO pixel;
+
+ DPF(( DBG_FUNC, "EnumPFHook();" ));
+
+ if ( lpDDPixFmt->dwFlags == lpDDPixFmtRequest->dwFlags )
+ {
+ /* Are we looking for an alpha channel? */
+ if ( lpDDPixFmtRequest->dwFlags & DDPF_ALPHAPIXELS )
+ {
+ /* Try for something that has more then 1bits of Alpha. */
+ Solve8BitChannelPixelFormat( lpDDPixFmt, &pixel );
+ if ( pixel.aScale == -1.0 )
+ {
+ /* Save this format no matter what as its a match of sorts. */
+ memcpy( lpDDPixFmtRequest, lpDDPixFmt, sizeof(DDPIXELFORMAT) );
+ return D3DENUMRET_OK;
+ }
+ }
+
+ /* Save this format as its a good match. */
+ memcpy( lpDDPixFmtRequest, lpDDPixFmt, sizeof(DDPIXELFORMAT) );
+
+ /* We are happy at this point so lets leave. */
+ return D3DENUMRET_CANCEL;
+ }
+
+ return D3DENUMRET_OK;
+}
+
+
+ \ No newline at end of file
diff --git a/src/mesa/drivers/d3d/D3DTextureMgr.h b/src/mesa/drivers/d3d/D3DTextureMgr.h
new file mode 100644
index 0000000000..6b3ac78560
--- /dev/null
+++ b/src/mesa/drivers/d3d/D3DTextureMgr.h
@@ -0,0 +1,63 @@
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#ifndef _TEXTURE_MGR_INC
+#define _TEXTURE_MGR_INC
+
+/*===========================================================================*/
+/* Includes. */
+/*===========================================================================*/
+#include <windows.h>
+#include <ddraw.h>
+#include <d3d.h>
+#include <stdlib.h>
+#include <stdlib.h>
+#include "GL/gl.h"
+/*========================================================================*/
+/* Defines. */
+/*========================================================================*/
+/*========================================================================*/
+/* Type defines. */
+/*========================================================================*/
+typedef struct _local_texture_object
+{
+ DWORD dwName,
+ dwPriority,
+ dwFlags,
+ dwSWidth,
+ dwSHeight,
+ dwVWidth,
+ dwVHeight;
+ BOOL bLock,
+ bDirty; /* I only update VID on SubImage calls so the system */
+ /* texture can get invalid. */
+
+ LPDIRECT3DDEVICE3 lpD3DDevice; /* If the device changes we must get new handles... */
+ LPDIRECTDRAWSURFACE4 lpDDS_System,
+ lpDDS_Video;
+ LPDIRECT3DTEXTURE2 lpD3DTexture2;
+
+ PIXELINFO pixel;
+
+ struct _local_texture_object *next;
+ struct _local_texture_object *prev;
+
+} TM_OBJECT, *PTM_OBJECT;
+/*========================================================================*/
+/* Function prototypes. */
+/*========================================================================*/
+void APIENTRY InitTMD3D( void *pVoid );
+void APIENTRY TermTMD3D( void *pVoid );
+/*========================================================================*/
+/* Global variables declaration. */
+/*========================================================================*/
+
+#endif
+ \ No newline at end of file
diff --git a/src/mesa/drivers/d3d/D3DUTILS.CPP b/src/mesa/drivers/d3d/D3DUTILS.CPP
new file mode 100644
index 0000000000..381e09f2a1
--- /dev/null
+++ b/src/mesa/drivers/d3d/D3DUTILS.CPP
@@ -0,0 +1,639 @@
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#include "D3DHAL.h"
+/*===========================================================================*/
+/* Local only functions. */
+/*===========================================================================*/
+static int CountTrailingZeros( DWORD dwMask );
+/*===========================================================================*/
+/* This function is used to get the pointer to the surface and the pitch for*/
+/* the scanline rendering functions. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" DDSURFACEDESC2 *LockHAL( PMESAD3DSHARED pShared, BOOL bBack )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+ static DDSURFACEDESC2 ddsd2;
+ HRESULT rc;
+
+ DPF(( DBG_FUNC, "LockHAL();" ));
+
+ /* Set the request structure up first. */
+ memset( &ddsd2, 0, sizeof(DDSURFACEDESC2) );
+ ddsd2.dwSize = sizeof(DDSURFACEDESC2);
+
+ /* Make sure we have enough info. */
+ if ( pHAL )
+ {
+ rc = pHAL->lpDDSRender->Lock( NULL, &ddsd2, DDLOCK_WAIT, NULL );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "Lock (RENDER) ->", ErrorStringD3D(rc) );
+ }
+ }
+
+ return &ddsd2;
+}
+/*===========================================================================*/
+/* This is just a simple wrapper. I probably don't need to do any error */
+/* checking as the Lock must have worked inorder to get here... */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" void UnlockHAL( PMESAD3DSHARED pShared, BOOL bBack )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+ HRESULT rc;
+
+ DPF(( DBG_FUNC, "UnlockHAL();" ));
+
+ /* Make sure we have enough info. */
+ if ( pHAL )
+ {
+ rc = pHAL->lpDDSRender->Unlock( NULL );
+ if ( FAILED(rc) )
+ {
+ RIP( pHAL, "Unlock (RENDER) ->", ErrorStringD3D(rc) );
+ }
+ }
+}
+/*===========================================================================*/
+/* This function will track the main/Primary window that will be used as the*/
+/* target for the Blt in SwapBuffers. As a side effect the call will check */
+/* to see if the primary surface is the same size and position as the screen.*/
+/* If they are the same size we will call it fullscreen... */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+extern "C" void UpdateScreenPosHAL( PMESAD3DSHARED pShared )
+{
+ PMESAD3DHAL pHAL = (PMESAD3DHAL)pShared;
+ POINT pt;
+ DWORD dwWidth, dwHeight;
+
+ DPF(( DBG_FUNC, "UpdateScreenPosHAL();" ));
+
+ /* Make sure we have enough info. */
+ if ( pHAL != NULL )
+ {
+ /* Update the windows screen position. */
+ GetClientRect( pShared->hwnd, &pShared->rectW );
+ pt.x = pt.y = 0;
+ ClientToScreen( pShared->hwnd, &pt );
+ OffsetRect( &pShared->rectW, pt.x, pt.y);
+
+ /* Compare the primary to the screen. */
+ dwWidth = GetSystemMetrics( SM_CXSCREEN );
+ dwHeight = GetSystemMetrics( SM_CYSCREEN );
+ if ( (pShared->rectW.left > 0) || (pShared->rectW.top > 0) ||
+ (pShared->rectW.right > dwWidth) || (pShared->rectW.bottom > dwHeight) )
+ pShared->bWindow = TRUE;
+ else
+ pShared->bWindow = FALSE;
+ }
+}
+/*===========================================================================*/
+/* This function will fill in the pixel info structure defined in D3Dshared.*/
+/* Basicly it will take a DirectDraw pixelformat structure and make scaling */
+/* values that will convert from 8bit channels to whatever the supplied ddpf */
+/* uses. Also we will generate shift values that will be used to get move */
+/* each component of the pixel into place. */
+/* I have now added a special case for a 1bit alpha channel. If I find a 1b*/
+/* alpha then I will set the scale to -1.0 which should be unique. Later I */
+/* can check the alpha scale value too see if its -1.0 and thus handle it. I*/
+/* was finding that the case was not working tom my advantage so this is my */
+/* HACK for the day. As a TODO I should work on this... */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void Solve8BitChannelPixelFormat( DDPIXELFORMAT *pddpf, PPIXELINFO pPixel )
+{
+ DPF(( DBG_FUNC, "Solve8BitChannelPixelFromat();" ));
+
+ memset( pPixel, 0, sizeof(PPIXELINFO) );
+
+ /* Check too see if the color space is valid in the PF. */
+ if ( pddpf->dwFlags & DDPF_RGB )
+ {
+ /* Solve the red stuff. */
+ pPixel->dwRMask = pddpf->dwRBitMask;
+ pPixel->rShift = CountTrailingZeros( pPixel->dwRMask );
+ pPixel->rScale = (float)0.00392156 * (float)(pPixel->dwRMask >> pPixel->rShift);
+
+ /* Solve the green thingy's. */
+ pPixel->dwGMask = pddpf->dwGBitMask;
+ pPixel->gShift = CountTrailingZeros( pPixel->dwGMask );
+ pPixel->gScale = (float)0.00392156 * (float)(pPixel->dwGMask >> pPixel->gShift);
+
+ /* Solve the blues. */
+ pPixel->dwBMask = pddpf->dwBBitMask;
+ pPixel->bShift = CountTrailingZeros( pddpf->dwBBitMask );
+ pPixel->bScale = (float)0.00392156 * (float)(pddpf->dwBBitMask >> pPixel->bShift);
+ }
+
+ /* Do the alpha channel if there is one. */
+ if ( pddpf->dwFlags & DDPF_ALPHAPIXELS )
+ {
+ pPixel->dwAMask = pddpf->dwRGBAlphaBitMask;
+ pPixel->aShift = CountTrailingZeros( pPixel->dwAMask );
+
+ /* Special case a 1bit alpha. */
+ if ( (pPixel->dwAMask >> pPixel->aShift) == 1 )
+ pPixel->aScale = -1.0;
+ else
+ pPixel->aScale = (float)0.00392156 * (float)(pPixel->dwAMask >> pPixel->aShift);
+ }
+
+ /* Get the size of the pixel in bytes. Should work as dwRGBBitCount is in a union. */
+ pPixel->cb = pddpf->dwRGBBitCount / 8;
+}
+/*===========================================================================*/
+/* See RETURN :) */
+/*===========================================================================*/
+/* RETURN: number of contiguous zeros starting from the right. */
+/*===========================================================================*/
+static int CountTrailingZeros( DWORD dwMask )
+{
+ DWORD Mask;
+
+ if ( dwMask == 0 )
+ return 32;
+
+ /* Can't take credit for this one! */
+ Mask = dwMask & -(int)dwMask;
+ return ((Mask & 0xFFFF0000)!=0) << 4
+ | ((Mask & 0xFF00FF00)!=0) << 3
+ | ((Mask & 0xF0F0F0F0)!=0) << 2
+ | ((Mask & 0xCCCCCCCC)!=0) << 1
+ | ((Mask & 0xAAAAAAAA)!=0);
+}
+/*===========================================================================*/
+/* This function will convert the DDraw error code to its macro string. The*/
+/* returned pointer is static so you need not worry about memory managemnet */
+/* but the error message gets written over from call to call... */
+/*===========================================================================*/
+/* RETURN: pointer to the single static buffer that hold the error message. */
+/*===========================================================================*/
+char *ErrorStringD3D( HRESULT hr )
+{
+ static char errorString[128];
+
+ switch( hr )
+ {
+ case DDERR_ALREADYINITIALIZED:
+ strcpy( errorString, "DDERR_ALREADYINITIALIZED" );
+ break;
+
+ case DDERR_CANNOTATTACHSURFACE:
+ strcpy( errorString, "DDERR_CANNOTATTACHSURFACE" );
+ break;
+
+ case DDERR_CANNOTDETACHSURFACE:
+ strcpy( errorString, "DDERR_CANNOTDETACHSURFACE" );
+ break;
+
+ case DDERR_CURRENTLYNOTAVAIL:
+ strcpy( errorString, "DDERR_CURRENTLYNOTAVAIL" );
+ break;
+
+ case DDERR_EXCEPTION:
+ strcpy( errorString, "DDERR_EXCEPTION" );
+ break;
+
+ case DDERR_GENERIC:
+ strcpy( errorString, "DDERR_GENERIC" );
+ break;
+
+ case DDERR_HEIGHTALIGN:
+ strcpy( errorString, "DDERR_HEIGHTALIGN" );
+ break;
+
+ case DDERR_INCOMPATIBLEPRIMARY:
+ strcpy( errorString, "DDERR_INCOMPATIBLEPRIMARY" );
+ break;
+
+ case DDERR_INVALIDCAPS:
+ strcpy( errorString, "DDERR_INVALIDCAPS" );
+ break;
+
+ case DDERR_INVALIDCLIPLIST:
+ strcpy( errorString, "DDERR_INVALIDCLIPLIST" );
+ break;
+
+ case DDERR_INVALIDMODE:
+ strcpy( errorString, "DDERR_INVALIDMODE" );
+ break;
+
+ case DDERR_INVALIDOBJECT:
+ strcpy( errorString, "DDERR_INVALIDOBJECT" );
+ break;
+
+ case DDERR_INVALIDPARAMS:
+ strcpy( errorString, "DDERR_INVALIDPARAMS" );
+ break;
+
+ case DDERR_INVALIDPIXELFORMAT:
+ strcpy( errorString, "DDERR_INVALIDPIXELFORMAT" );
+ break;
+
+ case DDERR_INVALIDRECT:
+ strcpy( errorString, "DDERR_INVALIDRECT" );
+ break;
+
+ case DDERR_LOCKEDSURFACES:
+ strcpy( errorString, "DDERR_LOCKEDSURFACES" );
+ break;
+
+ case DDERR_NO3D:
+ strcpy( errorString, "DDERR_NO3D" );
+ break;
+
+ case DDERR_NOALPHAHW:
+ strcpy( errorString, "DDERR_NOALPHAHW" );
+ break;
+
+ case DDERR_NOCLIPLIST:
+ strcpy( errorString, "DDERR_NOCLIPLIST" );
+ break;
+
+ case DDERR_NOCOLORCONVHW:
+ strcpy( errorString, "DDERR_NOCOLORCONVHW" );
+ break;
+
+ case DDERR_NOCOOPERATIVELEVELSET:
+ strcpy( errorString, "DDERR_NOCOOPERATIVELEVELSET" );
+ break;
+
+ case DDERR_NOCOLORKEY:
+ strcpy( errorString, "DDERR_NOCOLORKEY" );
+ break;
+
+ case DDERR_NOCOLORKEYHW:
+ strcpy( errorString, "DDERR_NOCOLORKEYHW" );
+ break;
+
+ case DDERR_NODIRECTDRAWSUPPORT:
+ strcpy( errorString, "DDERR_NODIRECTDRAWSUPPORT" );
+ break;
+
+ case DDERR_NOEXCLUSIVEMODE:
+ strcpy( errorString, "DDERR_NOEXCLUSIVEMODE" );
+ break;
+
+ case DDERR_NOFLIPHW:
+ strcpy( errorString, "DDERR_NOFLIPHW" );
+ break;
+
+ case DDERR_NOGDI:
+ strcpy( errorString, "DDERR_NOGDI" );
+ break;
+
+ case DDERR_NOMIRRORHW:
+ strcpy( errorString, "DDERR_NOMIRRORHW" );
+ break;
+
+ case DDERR_NOTFOUND:
+ strcpy( errorString, "DDERR_NOTFOUND" );
+ break;
+
+ case DDERR_NOOVERLAYHW:
+ strcpy( errorString, "DDERR_NOOVERLAYHW" );
+ break;
+
+ case DDERR_OVERLAPPINGRECTS:
+ strcpy( errorString, "DDERR_OVERLAPPINGRECTS" );
+ break;
+
+ case DDERR_NORASTEROPHW:
+ strcpy( errorString, "DDERR_NORASTEROPHW" );
+ break;
+
+ case DDERR_NOROTATIONHW:
+ strcpy( errorString, "DDERR_NOROTATIONHW" );
+ break;
+
+ case DDERR_NOSTRETCHHW:
+ strcpy( errorString, "DDERR_NOSTRETCHHW" );
+ break;
+
+ case DDERR_NOT4BITCOLOR:
+ strcpy( errorString, "DDERR_NOT4BITCOLOR" );
+ break;
+
+ case DDERR_NOT4BITCOLORINDEX:
+ strcpy( errorString, "DDERR_NOT4BITCOLORINDEX" );
+ break;
+
+ case DDERR_NOT8BITCOLOR:
+ strcpy( errorString, "DDERR_NOT8BITCOLOR" );
+ break;
+
+ case DDERR_NOTEXTUREHW:
+ strcpy( errorString, "DDERR_NOTEXTUREHW" );
+ break;
+
+ case DDERR_NOVSYNCHW:
+ strcpy( errorString, "DDERR_NOVSYNCHW" );
+ break;
+
+ case DDERR_NOZBUFFERHW:
+ strcpy( errorString, "DDERR_NOZBUFFERHW" );
+ break;
+
+ case DDERR_NOZOVERLAYHW:
+ strcpy( errorString, "DDERR_NOZOVERLAYHW" );
+ break;
+
+ case DDERR_OUTOFCAPS:
+ strcpy( errorString, "DDERR_OUTOFCAPS" );
+ break;
+
+ case DDERR_OUTOFMEMORY:
+ strcpy( errorString, "DDERR_OUTOFMEMORY" );
+ break;
+
+ case DDERR_OUTOFVIDEOMEMORY:
+ strcpy( errorString, "DDERR_OUTOFVIDEOMEMORY" );
+ break;
+
+ case DDERR_OVERLAYCANTCLIP:
+ strcpy( errorString, "DDERR_OVERLAYCANTCLIP" );
+ break;
+
+ case DDERR_OVERLAYCOLORKEYONLYONEACTIVE:
+ strcpy( errorString, "DDERR_OVERLAYCOLORKEYONLYONEACTIVE" );
+ break;
+
+ case DDERR_PALETTEBUSY:
+ strcpy( errorString, "DDERR_PALETTEBUSY" );
+ break;
+
+ case DDERR_COLORKEYNOTSET:
+ strcpy( errorString, "DDERR_COLORKEYNOTSET" );
+ break;
+
+ case DDERR_SURFACEALREADYATTACHED:
+ strcpy( errorString, "DDERR_SURFACEALREADYATTACHED" );
+ break;
+
+ case DDERR_SURFACEALREADYDEPENDENT:
+ strcpy( errorString, "DDERR_SURFACEALREADYDEPENDENT" );
+ break;
+
+ case DDERR_SURFACEBUSY:
+ strcpy( errorString, "DDERR_SURFACEBUSY" );
+ break;
+
+ case DDERR_CANTLOCKSURFACE:
+ strcpy( errorString, "DDERR_CANTLOCKSURFACE" );
+ break;
+
+ case DDERR_SURFACEISOBSCURED:
+ strcpy( errorString, "DDERR_SURFACEISOBSCURED" );
+ break;
+
+ case DDERR_SURFACELOST:
+ strcpy( errorString, "DDERR_SURFACELOST" );
+ break;
+
+ case DDERR_SURFACENOTATTACHED:
+ strcpy( errorString, "DDERR_SURFACENOTATTACHED" );
+ break;
+
+ case DDERR_TOOBIGHEIGHT:
+ strcpy( errorString, "DDERR_TOOBIGHEIGHT" );
+ break;
+
+ case DDERR_TOOBIGSIZE:
+ strcpy( errorString, "DDERR_TOOBIGSIZE" );
+ break;
+
+ case DDERR_TOOBIGWIDTH:
+ strcpy( errorString, "DDERR_TOOBIGWIDTH" );
+ break;
+
+ case DDERR_UNSUPPORTED:
+ strcpy( errorString, "DDERR_UNSUPPORTED" );
+ break;
+
+ case DDERR_UNSUPPORTEDFORMAT:
+ strcpy( errorString, "DDERR_UNSUPPORTEDFORMAT" );
+ break;
+
+ case DDERR_UNSUPPORTEDMASK:
+ strcpy( errorString, "DDERR_UNSUPPORTEDMASK" );
+ break;
+
+ case DDERR_INVALIDSTREAM:
+ strcpy( errorString, "DDERR_INVALIDSTREAM" );
+ break;
+
+ case DDERR_VERTICALBLANKINPROGRESS:
+ strcpy( errorString, "DDERR_VERTICALBLANKINPROGRESS" );
+ break;
+
+ case DDERR_WASSTILLDRAWING:
+ strcpy( errorString, "DDERR_WASSTILLDRAWING" );
+ break;
+
+ case DDERR_XALIGN:
+ strcpy( errorString, "DDERR_XALIGN" );
+ break;
+
+ case DDERR_INVALIDDIRECTDRAWGUID:
+ strcpy( errorString, "DDERR_INVALIDDIRECTDRAWGUID" );
+ break;
+
+ case DDERR_DIRECTDRAWALREADYCREATED:
+ strcpy( errorString, "DDERR_DIRECTDRAWALREADYCREATED" );
+ break;
+
+ case DDERR_NODIRECTDRAWHW:
+ strcpy( errorString, "DDERR_NODIRECTDRAWHW" );
+ break;
+
+ case DDERR_PRIMARYSURFACEALREADYEXISTS:
+ strcpy( errorString, "DDERR_PRIMARYSURFACEALREADYEXISTS" );
+ break;
+
+ case DDERR_NOEMULATION:
+ strcpy( errorString, "DDERR_NOEMULATION" );
+ break;
+
+ case DDERR_REGIONTOOSMALL:
+ strcpy( errorString, "DDERR_REGIONTOOSMALL" );
+ break;
+
+ case DDERR_CLIPPERISUSINGHWND:
+ strcpy( errorString, "DDERR_CLIPPERISUSINGHWND" );
+ break;
+
+ case DDERR_NOCLIPPERATTACHED:
+ strcpy( errorString, "DDERR_NOCLIPPERATTACHED" );
+ break;
+
+ case DDERR_NOHWND:
+ strcpy( errorString, "DDERR_NOHWND" );
+ break;
+
+ case DDERR_HWNDSUBCLASSED:
+ strcpy( errorString, "DDERR_HWNDSUBCLASSED" );
+ break;
+
+ case DDERR_HWNDALREADYSET:
+ strcpy( errorString, "DDERR_HWNDALREADYSET" );
+ break;
+
+ case DDERR_NOPALETTEATTACHED:
+ strcpy( errorString, "DDERR_NOPALETTEATTACHED" );
+ break;
+
+ case DDERR_NOPALETTEHW:
+ strcpy( errorString, "DDERR_NOPALETTEHW" );
+ break;
+
+ case DDERR_BLTFASTCANTCLIP:
+ strcpy( errorString, "DDERR_BLTFASTCANTCLIP" );
+ break;
+
+ case DDERR_NOBLTHW:
+ strcpy( errorString, "DDERR_NOBLTHW" );
+ break;
+
+ case DDERR_NODDROPSHW:
+ strcpy( errorString, "DDERR_NODDROPSHW" );
+ break;
+
+ case DDERR_OVERLAYNOTVISIBLE:
+ strcpy( errorString, "DDERR_OVERLAYNOTVISIBLE" );
+ break;
+
+ case DDERR_NOOVERLAYDEST:
+ strcpy( errorString, "DDERR_NOOVERLAYDEST" );
+ break;
+
+ case DDERR_INVALIDPOSITION:
+ strcpy( errorString, "DDERR_INVALIDPOSITION" );
+ break;
+
+ case DDERR_NOTAOVERLAYSURFACE:
+ strcpy( errorString, "DDERR_NOTAOVERLAYSURFACE" );
+ break;
+
+ case DDERR_EXCLUSIVEMODEALREADYSET:
+ strcpy( errorString, "DDERR_EXCLUSIVEMODEALREADYSET" );
+ break;
+
+ case DDERR_NOTFLIPPABLE:
+ strcpy( errorString, "DDERR_NOTFLIPPABLE" );
+ break;
+
+ case DDERR_CANTDUPLICATE:
+ strcpy( errorString, "DDERR_CANTDUPLICATE" );
+ break;
+
+ case DDERR_NOTLOCKED:
+ strcpy( errorString, "DDERR_NOTLOCKED" );
+ break;
+
+ case DDERR_CANTCREATEDC:
+ strcpy( errorString, "DDERR_CANTCREATEDC" );
+ break;
+
+ case DDERR_NODC:
+ strcpy( errorString, "DDERR_NODC" );
+ break;
+
+ case DDERR_WRONGMODE:
+ strcpy( errorString, "DDERR_WRONGMODE" );
+ break;
+
+ case DDERR_IMPLICITLYCREATED:
+ strcpy( errorString, "DDERR_IMPLICITLYCREATED" );
+ break;
+
+ case DDERR_NOTPALETTIZED:
+ strcpy( errorString, "DDERR_NOTPALETTIZED" );
+ break;
+
+ case DDERR_UNSUPPORTEDMODE:
+ strcpy( errorString, "DDERR_UNSUPPORTEDMODE" );
+ break;
+
+ case DDERR_NOMIPMAPHW:
+ strcpy( errorString, "DDERR_NOMIPMAPHW" );
+ break;
+
+ case DDERR_INVALIDSURFACETYPE:
+ strcpy( errorString, "DDERR_INVALIDSURFACETYPE" );
+ break;
+
+ case DDERR_NOOPTIMIZEHW:
+ strcpy( errorString, "DDERR_NOOPTIMIZEHW" );
+ break;
+
+ case DDERR_NOTLOADED:
+ strcpy( errorString, "DDERR_NOTLOADED" );
+ break;
+
+ case DDERR_NOFOCUSWINDOW:
+ strcpy( errorString, "DDERR_NOFOCUSWINDOW" );
+ break;
+
+ case DDERR_DCALREADYCREATED:
+ strcpy( errorString, "DDERR_DCALREADYCREATED" );
+ break;
+
+ case DDERR_NONONLOCALVIDMEM:
+ strcpy( errorString, "DDERR_NONONLOCALVIDMEM" );
+ break;
+
+ case DDERR_CANTPAGELOCK:
+ strcpy( errorString, "DDERR_CANTPAGELOCK" );
+ break;
+
+ case DDERR_CANTPAGEUNLOCK:
+ strcpy( errorString, "DDERR_CANTPAGEUNLOCK" );
+ break;
+
+ case DDERR_NOTPAGELOCKED:
+ strcpy( errorString, "DDERR_NOTPAGELOCKED" );
+ break;
+
+ case DDERR_MOREDATA:
+ strcpy( errorString, "DDERR_MOREDATA" );
+ break;
+
+ case DDERR_EXPIRED:
+ strcpy( errorString, "DDERR_EXPIRED" );
+ break;
+
+ case DDERR_VIDEONOTACTIVE:
+ strcpy( errorString, "DDERR_VIDEONOTACTIVE" );
+ break;
+
+ case DDERR_DEVICEDOESNTOWNSURFACE:
+ strcpy( errorString, "DDERR_DEVICEDOESNTOWNSURFACE" );
+ break;
+
+ case DDERR_NOTINITIALIZED:
+ strcpy( errorString, "DDERR_NOTINITIALIZED" );
+ break;
+
+ default:
+ strcpy( errorString, "<unknown error code>" );
+ break;
+ }
+
+ return &errorString[0];
+}
+ \ No newline at end of file
diff --git a/src/mesa/drivers/d3d/D3Dvbrender.c b/src/mesa/drivers/d3d/D3Dvbrender.c
new file mode 100644
index 0000000000..57c1306d60
--- /dev/null
+++ b/src/mesa/drivers/d3d/D3Dvbrender.c
@@ -0,0 +1,2150 @@
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#include <stdio.h>
+#include "clip.h"
+#include "context.h"
+#include "light.h"
+#include "lines.h"
+#include "macros.h"
+#include "matrix.h"
+#include "pb.h"
+#include "points.h"
+#include "types.h"
+#include "vb.h"
+#include "vbrender.h"
+#include "xform.h"
+#include "D3DMesa.h"
+
+static void SetRenderStates( GLcontext *ctx );
+static void DebugRenderStates( GLcontext *ctx, BOOL bForce );
+
+static void RenderPointsVB( GLcontext *ctx, GLuint start, GLuint end );
+static void RenderTriangleVB( GLcontext *ctx, GLuint start, GLuint end );
+static void RenderTriangleFanVB( GLcontext *ctx, GLuint start, GLuint end );
+static void RenderTriangleStripVB( GLcontext *ctx, GLuint start, GLuint end );
+static void RenderQuadVB( GLcontext *ctx, GLuint start, GLuint end );
+static void RenderQuad( GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint v4, GLuint pv );
+void RenderOneTriangle( GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint pv );
+void RenderOneLine( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv );
+
+/* I went with a D3D vertex buffer that is 6 times that of the Mesa one */
+/* instead of having the D3D one flush when its full. This way Mesa will*/
+/* handle all the flushing. I need x6 as points can use 4 vertex each. */
+D3DTLVERTEX D3DTLVertices[ (VB_MAX*6) ];
+GLuint VList[VB_SIZE];
+/*===========================================================================*/
+/* Compute Z offsets for a polygon with plane defined by (A,B,C,D) */
+/* D is not needed. TODO: Currently we are calculating this but not using it.*/
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void OffsetPolygon( GLcontext *ctx, GLfloat a, GLfloat b, GLfloat c )
+{
+ GLfloat ac,
+ bc,
+ m,
+ offset;
+
+ DPF(( DBG_FUNC, "OffsetPolygon();" ));
+
+ if ( (c < 0.001F) && (c > - 0.001F) )
+ {
+ /* Prevents underflow problems. */
+ ctx->PointZoffset = 0.0F;
+ ctx->LineZoffset = 0.0F;
+ ctx->PolygonZoffset = 0.0F;
+ }
+ else
+ {
+ ac = a / c;
+ bc = b / c;
+ if ( ac < 0.0F )
+ ac = -ac;
+ if ( bc<0.0F )
+ bc = -bc;
+ m = MAX2( ac, bc ); /* m = sqrt( ac*ac + bc*bc ); */
+
+ offset = (m * ctx->Polygon.OffsetFactor + ctx->Polygon.OffsetUnits);
+ ctx->PointZoffset = ctx->Polygon.OffsetPoint ? offset : 0.0F;
+ ctx->LineZoffset = ctx->Polygon.OffsetLine ? offset : 0.0F;
+ ctx->PolygonZoffset = ctx->Polygon.OffsetFill ? offset : 0.0F;
+ }
+
+ DPF(( DBG_PRIM_INFO, "OffsetPolygon: %f", offset ));
+}
+/*===========================================================================*/
+/* Compute signed area of the n-sided polgyon specified by vertices */
+/* vb->Win[] and vertex list vlist[]. */
+/* A clockwise polygon will return a negative area. A counter-clockwise */
+/* polygon will return a positive area. I have changed this function to */
+/* actually calculate twice the area as its faster and still gives the sign. */
+/*===========================================================================*/
+/* RETURN: signed area of the polgon. */
+/*===========================================================================*/
+static GLfloat PolygonArea( const struct vertex_buffer *vb, GLuint n, const GLuint vlist[] )
+{
+ GLfloat area;
+ GLuint i;
+
+ DPF(( DBG_FUNC, "PolygonArea();" ));
+
+#define j0 vlist[i]
+#define j1 vlist[(i+1)%n]
+#define x0 vb->Win[j0][0]
+#define y0 vb->Win[j0][1]
+#define x1 vb->Win[j1][0]
+#define y1 vb->Win[j1][1]
+
+ /* area = sum of trapezoids */
+ for( i = 0, area = 0.0; i < n; i++ )
+ area += ((x0 - x1) * (y0 + y1)); /* Note: no divide by two here! */
+
+#undef x0
+#undef y0
+#undef x1
+#undef y1
+#undef j1
+#undef j0
+
+ // TODO: I don't see the point or * 0.5 as we just want the sign...
+ return area;
+}
+/*===========================================================================*/
+/* Render a polygon that needs clipping on at least one vertex. The function*/
+/* will first clip the polygon to any user clipping planes then clip to the */
+/* viewing volume. The final polygon will be draw as single triangles that */
+/* first need minor proccessing (culling, offset, etc) before we draw the */
+/* polygon as a fan. NOTE: the fan is draw as single triangles as its not */
+/* formed sequentaly in the VB but is in the vlist[]. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void RenderClippedPolygon( GLcontext *ctx, GLuint n, GLuint vlist[] )
+{
+ struct vertex_buffer *VB = ctx->VB;
+ GLfloat (*win)[3] = VB->Win,
+ *proj = ctx->ProjectionMatrix,
+ ex, ey,
+ fx, fy, c,
+ wInv;
+ GLuint index,
+ pv,
+ facing;
+
+ DPF(( DBG_FUNC, "RenderClippedPolygon();" ));
+
+ DPF(( DBG_PRIM_INFO, "RenderClippedtPolygon( %d )", n ));
+
+ /* Which vertex dictates the color when flat shading. */
+ pv = (ctx->Primitive==GL_POLYGON) ? vlist[0] : vlist[n-1];
+
+ /* Clipping may introduce new vertices. New vertices will be stored in */
+ /* the vertex buffer arrays starting with location VB->Free. After we've*/
+ /* rendered the polygon, these extra vertices can be overwritten. */
+ VB->Free = VB_MAX;
+
+ /* Clip against user clipping planes in eye coord space. */
+ if ( ctx->Transform.AnyClip )
+ {
+ n = gl_userclip_polygon( ctx, n, vlist );
+ if ( n < 3 )
+ return;
+
+ /* Transform vertices from eye to clip coordinates: clip = Proj * eye */
+ for( index = 0; index < n; index++ )
+ {
+ TRANSFORM_POINT( VB->Clip[vlist[index]], proj, VB->Eye[vlist[index]] );
+ }
+ }
+
+ /* Clip against view volume in clip coord space */
+ n = gl_viewclip_polygon( ctx, n, vlist );
+ if ( n < 3 )
+ return;
+
+ /* Transform new vertices from clip to ndc to window coords. */
+ /* ndc = clip / W window = viewport_mapping(ndc) */
+ /* Note that window Z values are scaled to the range of integer */
+ /* depth buffer values. */
+
+ /* Only need to compute window coords for new vertices */
+ for( index = VB_MAX; index < VB->Free; index++ )
+ {
+ if ( VB->Clip[index][3] != 0.0F )
+ {
+ wInv = 1.0F / VB->Clip[index][3];
+
+ win[index][0] = VB->Clip[index][0] * wInv * ctx->Viewport.Sx + ctx->Viewport.Tx;
+ win[index][1] = VB->Clip[index][1] * wInv * ctx->Viewport.Sy + ctx->Viewport.Ty;
+ win[index][2] = VB->Clip[index][2] * wInv * ctx->Viewport.Sz + ctx->Viewport.Tz;
+ }
+ else
+ {
+ /* Can't divide by zero, so... */
+ win[index][0] = win[index][1] = win[index][2] = 0.0F;
+ }
+ }
+
+ /* Draw filled polygon as a triangle fan */
+ for( index = 2; index < n; index++ )
+ {
+ /* Compute orientation of triangle */
+ ex = win[vlist[index-1]][0] - win[vlist[0]][0];
+ ey = win[vlist[index-1]][1] - win[vlist[0]][1];
+ fx = win[vlist[index]][0] - win[vlist[0]][0];
+ fy = win[vlist[index]][1] - win[vlist[0]][1];
+ c = (ex * fy) - (ey * fx);
+
+ /* polygon is perpindicular to view plane, don't draw it */
+ if ( (c == 0.0F) && !ctx->Polygon.Unfilled )
+ continue;
+
+ /* Backface culling. */
+ facing = (c < 0.0F) ^ ctx->Polygon.FrontBit;
+ if ( (facing + 1) & ctx->Polygon.CullBits )
+ continue;
+
+ if ( ctx->IndirectTriangles & DD_TRI_LIGHT_TWOSIDE )
+ {
+ if ( facing == 1 )
+ {
+ /* use back color */
+ VB->Color = VB->Bcolor;
+ VB->Specular= VB->Bspec;
+ }
+ else
+ {
+ /* use front color */
+ VB->Color = VB->Fcolor;
+ VB->Specular= VB->Fspec;
+ }
+ }
+
+ if ( ctx->IndirectTriangles & DD_TRI_OFFSET )
+ {
+ /* finish computing plane equation of polygon, compute offset */
+ GLfloat fz = win[vlist[index]][2] - win[vlist[0]][2];
+ GLfloat ez = win[vlist[index-1]][2] - win[vlist[0]][2];
+ GLfloat a = (ey * fz) - (ez * fy);
+ GLfloat b = (ez * fx) - (ex * fz);
+ OffsetPolygon( ctx, a, b, c );
+ }
+ RenderOneTriangle( ctx, vlist[0], vlist[index-1], vlist[index], pv );
+ }
+}
+/*===========================================================================*/
+/* This function gets called when either the vertex buffer is full or glEnd */
+/* has been called. If the we aren't in rendering mode (FEEDBACK) then I */
+/* pass the vertex buffer back to Mesa to deal with by returning FALSE. */
+/* If I can render the primitive types in the buffer directly then I will */
+/* return TRUE after I render the vertex buffer and reset the vertex buffer. */
+/* */
+/* TODO: I don't handle the special case of when the vertex buffer is full */
+/* and we have a primitive that bounds this buffer and the next one to */
+/* come. I'm not sure right now if Mesa handles this for me... */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+GLboolean RenderVertexBuffer( GLcontext *ctx, GLboolean allDone )
+{
+ struct vertex_buffer *VB = ctx->VB;
+ GLuint index,
+ vlist[VB_SIZE];
+
+ DPF(( DBG_FUNC, "RenderVertexBuffer();" ));
+
+ /* We only need to hook actual tri's that need rendering. */
+ if ( ctx->RenderMode != GL_RENDER )
+ {
+ // (ctx->Visual->AccumBits > 0) )
+ // (ctx->Visual->StencilBits > 0) )
+ DPF(( DBG_PRIM_INFO, "Passing VB back to Mesa" ));
+ return FALSE;
+ }
+
+ /* I'm going to set the states here so that all functions will */
+ /* be assured to have the right states. If Mesa's vertex bufefr */
+ /* function calls one of my primitive functions (TRI,POINT,LINE) */
+ /* it will need the right states. So instead of doing it in the */
+ /* primitive function I will always do it here at risk of some */
+ /* slow down to some cases... */
+ SetRenderStates( ctx );
+
+ switch( ctx->Primitive )
+ {
+ case GL_POINTS:
+ DPF(( DBG_PRIM_INFO, "GL_POINTS( %d )", VB->Count ));
+ RenderPointsVB( ctx, 0, VB->Count );
+ break;
+
+ case GL_LINES:
+ case GL_LINE_STRIP:
+ case GL_LINE_LOOP:
+ /* Not supported functions yet so pass back that we failed to */
+ /* render the vertex buffer and Mesa will have to do it. */
+ DPF(( DBG_PRIM_INFO, "GL_LINE_?( %d )", VB->Count ));
+ return FALSE;
+
+ case GL_TRIANGLES:
+ if ( VB->Count < 3 )
+ {
+ DPF(( DBG_PRIM_WARN, "GL_TRIANGLES( %d )", VB->Count ));
+ return FALSE;
+ }
+
+ DPF(( DBG_PRIM_INFO, "GL_TRIANGLES( %d )", VB->Count ));
+ RenderTriangleVB( ctx, 0, VB->Count );
+ break;
+
+ case GL_TRIANGLE_STRIP:
+ if ( VB->Count < 3 )
+ {
+ DPF(( DBG_PRIM_WARN, "GL_TRIANGLE_STRIP( %d )", VB->Count ));
+ return FALSE;
+ }
+
+ DPF(( DBG_PRIM_INFO, "GL_TRIANGLE_STRIP( %d )", VB->Count ));
+ RenderTriangleStripVB( ctx, 0, VB->Count );
+ break;
+
+ case GL_TRIANGLE_FAN:
+ if ( VB->Count < 3 )
+ {
+ DPF(( DBG_PRIM_WARN, "GL_TRIANGLE_FAN( %d )", VB->Count ));
+ return FALSE;
+ }
+
+ DPF(( DBG_PRIM_INFO, "GL_TRIANGLE_FAN( %d )", VB->Count ));
+ RenderTriangleFanVB( ctx, 0, VB->Count );
+ break;
+
+ case GL_QUADS:
+ if ( VB->Count < 4 )
+ {
+ DPF(( DBG_PRIM_WARN, "GL_QUADS( %d )", VB->Count ));
+ return FALSE;
+ }
+
+ DPF(( DBG_PRIM_INFO, "GL_QUADS( %d )", VB->Count ));
+ RenderQuadVB( ctx, 0, VB->Count );
+ break;
+
+ case GL_QUAD_STRIP:
+ if ( VB->Count < 4 )
+ {
+ DPF(( DBG_PRIM_WARN, "GL_QUAD_STRIP( %d )", VB->Count ));
+ return FALSE;
+ }
+
+ DPF(( DBG_PRIM_INFO, "GL_QUAD_STRIP( %d )", VB->Count ));
+
+ if ( VB->ClipOrMask )
+ {
+ for( index = 3; index < VB->Count; index += 2 )
+ {
+ if ( VB->ClipMask[index-3] & VB->ClipMask[index-2] & VB->ClipMask[index-1] & VB->ClipMask[index] & CLIP_ALL_BITS )
+ {
+ /* All points clipped by common plane */
+ DPF(( DBG_PRIM_WARN, "GL_QUAD_STRIP( %d )", VB->Count ));
+ continue;
+ }
+ else if ( VB->ClipMask[index-3] | VB->ClipMask[index-2] | VB->ClipMask[index-1] | VB->ClipMask[index] )
+ {
+ vlist[0] = index - 3;
+ vlist[1] = index - 2;
+ vlist[2] = index;
+ vlist[3] = index - 1;
+ RenderClippedPolygon( ctx, 4, vlist );
+ }
+ else
+ {
+ RenderQuad( ctx, (index-3), (index-2), index, (index-1), index );
+ }
+ }
+ }
+ else
+ {
+ /* No clipping needed */
+ for( index = 3; index < VB->Count; index += 2 )
+ RenderQuad( ctx, (index-3), (index-2), index, (index-1), index );
+ }
+ break;
+
+ case GL_POLYGON:
+ if ( VB->Count < 3 )
+ {
+ DPF(( DBG_PRIM_WARN, "GL_POLYGON( %d )", VB->Count ));
+ return FALSE;
+ }
+
+ DPF(( DBG_PRIM_INFO, "GL_POLYGON( %d )", VB->Count ));
+
+ /* All points clipped by common plane, draw nothing */
+ if ( !(VB->ClipAndMask & CLIP_ALL_BITS) )
+ RenderTriangleFanVB( ctx, 0, VB->Count );
+ break;
+
+ default:
+ /* should never get here */
+ gl_problem( ctx, "invalid mode in gl_render_vb" );
+ }
+
+ DPF(( DBG_PRIM_INFO, "ResetVB" ));
+
+ /* We return TRUE to indicate we rendered the VB. */
+ gl_reset_vb( ctx, allDone );
+ return TRUE;
+}
+/*===========================================================================*/
+/* This function will render the current vertex buffer as triangles. The */
+/* buffer has to be able to be rendered directly. This means that we are */
+/* filled, no offsets, no culling and one sided rendering. Also we must be */
+/* in render mode of course. */
+/* First I will fill the global D3D vertice buffer. Next I will set all the*/
+/* states for D3D based on the current OGL state. Finally I pass the D3D VB */
+/* to the wrapper that call DrawPrimitives. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void RenderTriangleVB( GLcontext *ctx, GLuint start, GLuint end )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ struct vertex_buffer *VB = ctx->VB;
+ int index,
+ cVertex,
+ height = (pContext->pShared->rectW.bottom - pContext->pShared->rectW.top);
+ DWORD dwPVColor;
+ GLfloat ex, ey,
+ fx, fy, c;
+ GLuint facing;
+
+ DPF(( DBG_FUNC, "RenderTriangleVB" ));
+
+ if ( (!(ctx->IndirectTriangles & DD_SW_SETUP)) && !VB->ClipOrMask )
+ {
+ DPF(( DBG_PRIM_INFO, "DirectTriangles( %d )", (end-start) ));
+ for( index = start, cVertex = 0; index < end; )
+ {
+ dwPVColor = (VB->Color[(index+2)][3]<<24) | (VB->Color[(index+2)][0]<<16) | (VB->Color[(index+2)][1]<<8) | VB->Color[(index+2)][2];
+
+ /*=====================================*/
+ /* Populate the the triangle vertices. */
+ /*=====================================*/
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[index][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[index][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( VB->Win[index][2] );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[index][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[index][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[index][3]) );
+ D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?
+ dwPVColor :
+ (VB->Color[index][3]<<24) | (VB->Color[index][0]<<16) | (VB->Color[index][1]<<8) | VB->Color[index][2];
+ index++;
+
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[index][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[index][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( VB->Win[index][2] );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[index][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[index][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[index][3]) );
+ D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?
+ dwPVColor :
+ (VB->Color[index][3]<<24) | (VB->Color[index][0]<<16) | (VB->Color[index][1]<<8) | VB->Color[index][2];
+ index++;
+
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[index][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[index][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( VB->Win[index][2] );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[index][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[index][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[index][3]) );
+ D3DTLVertices[cVertex++].color= dwPVColor;
+ index++;
+ }
+ }
+ else
+ {
+#define v1 index
+#define v2 (index+1)
+#define v3 (index+2)
+
+ for( index = start, cVertex = 0; index < end; index += 3 )
+ {
+ if ( VB->ClipMask[v1] & VB->ClipMask[v2] & VB->ClipMask[v3] & CLIP_ALL_BITS )
+ {
+ continue;
+ }
+ else if ( VB->ClipMask[v1] | VB->ClipMask[v2] | VB->ClipMask[v3] )
+ {
+ VList[0] = v1;
+ VList[1] = v2;
+ VList[2] = v3;
+ RenderClippedPolygon( ctx, 3, VList );
+ continue;
+ }
+
+ /* Compute orientation of triangle */
+ ex = VB->Win[v2][0] - VB->Win[v1][0];
+ ey = VB->Win[v2][1] - VB->Win[v1][1];
+ fx = VB->Win[v3][0] - VB->Win[v1][0];
+ fy = VB->Win[v3][1] - VB->Win[v1][1];
+ c = (ex * fy) - (ey * fx);
+
+ /* polygon is perpindicular to view plane, don't draw it */
+ if ( (c == 0.0F) && !ctx->Polygon.Unfilled )
+ continue;
+
+ /* Backface culling. */
+ facing = (c < 0.0F) ^ ctx->Polygon.FrontBit;
+ if ( (facing + 1) & ctx->Polygon.CullBits )
+ continue;
+
+ if ( ctx->IndirectTriangles & DD_TRI_LIGHT_TWOSIDE )
+ {
+ if ( facing == 1 )
+ {
+ /* use back color */
+ VB->Color = VB->Bcolor;
+ VB->Specular= VB->Bspec;
+ }
+ else
+ {
+ /* use front color */
+ VB->Color = VB->Fcolor;
+ VB->Specular= VB->Fspec;
+ }
+ }
+
+ if ( ctx->IndirectTriangles & DD_TRI_OFFSET )
+ {
+ /* Finish computing plane equation of polygon, compute offset */
+ GLfloat fz = VB->Win[v3][2] - VB->Win[v1][2];
+ GLfloat ez = VB->Win[v2][2] - VB->Win[v1][2];
+ GLfloat a = (ey * fz) - (ez * fy);
+ GLfloat b = (ez * fx) - (ex * fz);
+ OffsetPolygon( ctx, a, b, c );
+ }
+
+ /*=====================================*/
+ /* Populate the the triangle vertices. */
+ /*=====================================*/
+ /* Solve the prevoking vertex color as we need it for the 3rd triangle and flat shading. */
+ dwPVColor = (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2];
+
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v1][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v1][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v1][2] + ctx->PolygonZoffset) );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v1][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v1][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v1][3]) );
+ D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?
+ dwPVColor :
+ (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2];
+
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v2][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v2][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v2][2] + ctx->PolygonZoffset) );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v2][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v2][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v2][3]) );
+ D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?
+ dwPVColor :
+ (VB->Color[v2][3]<<24) | (VB->Color[v2][0]<<16) | (VB->Color[v2][1]<<8) | VB->Color[v2][2];
+
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v3][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v3][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v3][2] + ctx->PolygonZoffset) );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v3][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v3][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v3][3]) );
+ D3DTLVertices[cVertex++].color= dwPVColor;
+ }
+#undef v1
+#undef v2
+#undef v3
+ }
+
+ /* Render the converted vertex buffer. */
+ if ( cVertex > 2 )
+ DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLELIST, &D3DTLVertices[0], cVertex );
+}
+/*===========================================================================*/
+/* This function will render the current vertex buffer as a triangle fan. */
+/* The buffer has to be able to be rendered directly. This means that we are*/
+/* filled, no offsets, no culling and one sided rendering. Also we must be */
+/* in render mode of course. */
+/* First I will fill the global D3D vertice buffer. Next I will set all the*/
+/* states for D3D based on the current OGL state. Finally I pass the D3D VB */
+/* to the wrapper that call DrawPrimitives. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void RenderTriangleFanVB( GLcontext *ctx, GLuint start, GLuint end )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ struct vertex_buffer *VB = ctx->VB;
+ int index,
+ cVertex,
+ height = (pContext->pShared->rectW.bottom - pContext->pShared->rectW.top);
+ GLfloat ex, ey,
+ fx, fy, c;
+ GLuint facing;
+ DWORD dwPVColor;
+
+ DPF(( DBG_FUNC, "RenderTriangleFanVB();" ));
+
+ /* Special case that we can blast the fan without culling, offset, etc... */
+ if ( (!(ctx->IndirectTriangles & DD_SW_SETUP)) && !VB->ClipOrMask && (ctx->Light.ShadeModel != GL_FLAT) )
+ {
+ DPF(( DBG_PRIM_INFO, "DirectTriangles( %d )", (end-start) ));
+
+ /* Seed the the fan. */
+ D3DTLVertices[0].sx = D3DVAL( VB->Win[start][0] );
+ D3DTLVertices[0].sy = D3DVAL( (height - VB->Win[start][1]) );
+ D3DTLVertices[0].sz = D3DVAL( VB->Win[start][2] );
+ D3DTLVertices[0].tu = D3DVAL( VB->TexCoord[start][0] );
+ D3DTLVertices[0].tv = D3DVAL( VB->TexCoord[start][1] );
+ D3DTLVertices[0].rhw = D3DVAL( (1.0 / VB->Clip[start][3]) );
+ D3DTLVertices[0].color= (VB->Color[start][3]<<24) | (VB->Color[start][0]<<16) | (VB->Color[start][1]<<8) | VB->Color[start][2];
+
+ /* Seed the the fan. */
+ D3DTLVertices[1].sx = D3DVAL( VB->Win[(start+1)][0] );
+ D3DTLVertices[1].sy = D3DVAL( (height - VB->Win[(start+1)][1]) );
+ D3DTLVertices[1].sz = D3DVAL( VB->Win[(start+1)][2] );
+ D3DTLVertices[1].tu = D3DVAL( VB->TexCoord[(start+1)][0] );
+ D3DTLVertices[1].tv = D3DVAL( VB->TexCoord[(start+1)][1] );
+ D3DTLVertices[1].rhw = D3DVAL( (1.0 / VB->Clip[(start+1)][3]) );
+ D3DTLVertices[1].color= (VB->Color[(start+1)][3]<<24) | (VB->Color[(start+1)][0]<<16) | (VB->Color[(start+1)][1]<<8) | VB->Color[(start+1)][2];
+
+ for( index = (start+2), cVertex = 2; index < end; index++, cVertex++ )
+ {
+ /*=================================*/
+ /* Add the next vertex to the fan. */
+ /*=================================*/
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[index][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[index][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( VB->Win[index][2] );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[index][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[index][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[index][3]) );
+ D3DTLVertices[cVertex].color = (VB->Color[index][3]<<24) | (VB->Color[index][0]<<16) | (VB->Color[index][1]<<8) | VB->Color[index][2];
+ }
+
+ /* Render the converted vertex buffer. */
+ if ( cVertex )
+ DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLEFAN, &D3DTLVertices[0], cVertex );
+ }
+ else
+ {
+#define v1 start
+#define v2 (index-1)
+#define v3 index
+
+ for( index = (start+2), cVertex = 0; index < end; index++ )
+ {
+ if ( VB->ClipOrMask )
+ {
+ /* All points clipped by common plane */
+ if ( VB->ClipMask[v1] & VB->ClipMask[v2] & VB->ClipMask[v3] & CLIP_ALL_BITS )
+ {
+ continue;
+ }
+ else if ( VB->ClipMask[v1] | VB->ClipMask[v2] | VB->ClipMask[v3] )
+ {
+ VList[0] = v1;
+ VList[1] = v2;
+ VList[2] = v3;
+ RenderClippedPolygon( ctx, 3, VList );
+ continue;
+ }
+ }
+
+ /* Compute orientation of triangle */
+ ex = VB->Win[v2][0] - VB->Win[v1][0];
+ ey = VB->Win[v2][1] - VB->Win[v1][1];
+ fx = VB->Win[v3][0] - VB->Win[v1][0];
+ fy = VB->Win[v3][1] - VB->Win[v1][1];
+ c = (ex * fy) - (ey * fx);
+
+ /* polygon is perpindicular to view plane, don't draw it */
+ if ( (c == 0.0F) && !ctx->Polygon.Unfilled )
+ continue;
+
+ /* Backface culling. */
+ facing = (c < 0.0F) ^ ctx->Polygon.FrontBit;
+ if ( (facing + 1) & ctx->Polygon.CullBits )
+ continue;
+
+ if ( ctx->IndirectTriangles & DD_TRI_OFFSET )
+ {
+ /* Finish computing plane equation of polygon, compute offset */
+ GLfloat fz = VB->Win[v3][2] - VB->Win[v1][2];
+ GLfloat ez = VB->Win[v2][2] - VB->Win[v1][2];
+ GLfloat a = (ey * fz) - (ez * fy);
+ GLfloat b = (ez * fx) - (ex * fz);
+ OffsetPolygon( ctx, a, b, c );
+ }
+
+ /*=====================================*/
+ /* Populate the the triangle vertices. */
+ /*=====================================*/
+ dwPVColor = (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2];
+
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v1][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v1][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v1][2] + ctx->PolygonZoffset) );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v1][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v1][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v1][3]) );
+ D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor :
+ (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2];
+
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v2][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v2][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v2][2] + ctx->PolygonZoffset) );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v2][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v2][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v2][3]) );
+ D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor :
+ (VB->Color[v2][3]<<24) | (VB->Color[v2][0]<<16) | (VB->Color[v2][1]<<8) | VB->Color[v2][2];
+
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v3][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v3][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v3][2] + ctx->PolygonZoffset) );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v3][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v3][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v3][3]) );
+ D3DTLVertices[cVertex++].color= dwPVColor;
+ }
+
+ /* Render the converted vertex buffer. */
+ if ( cVertex )
+ DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLELIST, &D3DTLVertices[0], cVertex );
+#undef v1
+#undef v2
+#undef v3
+ }
+}
+/*===========================================================================*/
+/* This function will render the current vertex buffer as a triangle strip. */
+/* The buffer has to be able to be rendered directly. This means that we are*/
+/* filled, no offsets, no culling and one sided rendering. Also we must be */
+/* in render mode of course. */
+/* First I will fill the global D3D vertice buffer. Next I will set all the*/
+/* states for D3D based on the current OGL state. Finally I pass the D3D VB */
+/* to the wrapper that call DrawPrimitives. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void RenderTriangleStripVB( GLcontext *ctx, GLuint start, GLuint end )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ struct vertex_buffer *VB = ctx->VB;
+ int index,
+ cVertex = 0,
+ v1, v2, v3,
+ height = (pContext->pShared->rectW.bottom - pContext->pShared->rectW.top);
+ GLfloat ex, ey,
+ fx, fy, c;
+ GLuint facing;
+ DWORD dwPVColor;
+
+ DPF(( DBG_FUNC, "RenderTriangleStripVB();" ));
+
+ /* Special case that we can blast the fan without culling, offset, etc... */
+ if ( (!(ctx->IndirectTriangles & DD_SW_SETUP)) && !VB->ClipOrMask && (ctx->Light.ShadeModel != GL_FLAT) )
+ {
+ DPF(( DBG_PRIM_PROFILE, "DirectTriangles" ));
+
+ /* Seed the the strip. */
+ D3DTLVertices[0].sx = D3DVAL( VB->Win[start][0] );
+ D3DTLVertices[0].sy = D3DVAL( (height - VB->Win[start][1]) );
+ D3DTLVertices[0].sz = D3DVAL( VB->Win[start][2] );
+ D3DTLVertices[0].tu = D3DVAL( VB->TexCoord[start][0] );
+ D3DTLVertices[0].tv = D3DVAL( VB->TexCoord[start][1] );
+ D3DTLVertices[0].rhw = D3DVAL( (1.0 / VB->Clip[start][3]) );
+ D3DTLVertices[0].color= (VB->Color[start][3]<<24) | (VB->Color[start][0]<<16) | (VB->Color[start][1]<<8) | VB->Color[start][2];
+
+ /* Seed the the strip. */
+ D3DTLVertices[1].sx = D3DVAL( VB->Win[(start+1)][0] );
+ D3DTLVertices[1].sy = D3DVAL( (height - VB->Win[(start+1)][1]) );
+ D3DTLVertices[1].sz = D3DVAL( VB->Win[(start+1)][2] );
+ D3DTLVertices[1].tu = D3DVAL( VB->TexCoord[(start+1)][0] );
+ D3DTLVertices[1].tv = D3DVAL( VB->TexCoord[(start+1)][1] );
+ D3DTLVertices[1].rhw = D3DVAL( (1.0 / VB->Clip[(start+1)][3]) );
+ D3DTLVertices[1].color= (VB->Color[(start+1)][3]<<24) | (VB->Color[(start+1)][0]<<16) | (VB->Color[(start+1)][1]<<8) | VB->Color[(start+1)][2];
+
+ for( index = (start+2), cVertex = 2; index < end; index++, cVertex++ )
+ {
+ /*===================================*/
+ /* Add the next vertex to the strip. */
+ /*===================================*/
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[index][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[index][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( VB->Win[index][2] );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[index][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[index][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[index][3]) );
+ D3DTLVertices[cVertex].color = (VB->Color[index][3]<<24) | (VB->Color[index][0]<<16) | (VB->Color[index][1]<<8) | VB->Color[index][2];
+ }
+
+ /* Render the converted vertex buffer. */
+ if ( cVertex )
+ DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLESTRIP, &D3DTLVertices[0], cVertex );
+ }
+ else
+ {
+ for( index = (start+2); index < end; index++ )
+ {
+ /* We need to switch order so that winding won't be a problem. */
+ if ( index & 1 )
+ {
+ v1 = index - 1;
+ v2 = index - 2;
+ v3 = index - 0;
+ }
+ else
+ {
+ v1 = index - 2;
+ v2 = index - 1;
+ v3 = index - 0;
+ }
+
+ /* All vertices clipped by common plane */
+ if ( VB->ClipMask[v1] & VB->ClipMask[v2] & VB->ClipMask[v3] & CLIP_ALL_BITS )
+ continue;
+
+ /* Check if any vertices need clipping. */
+ if ( VB->ClipMask[v1] | VB->ClipMask[v2] | VB->ClipMask[v3] )
+ {
+ VList[0] = v1;
+ VList[1] = v2;
+ VList[2] = v3;
+ RenderClippedPolygon( ctx, 3, VList );
+ }
+ else
+ {
+ /* Compute orientation of triangle */
+ ex = VB->Win[v2][0] - VB->Win[v1][0];
+ ey = VB->Win[v2][1] - VB->Win[v1][1];
+ fx = VB->Win[v3][0] - VB->Win[v1][0];
+ fy = VB->Win[v3][1] - VB->Win[v1][1];
+ c = (ex * fy) - (ey * fx);
+
+ /* Polygon is perpindicular to view plane, don't draw it */
+ if ( (c == 0.0F) && !ctx->Polygon.Unfilled )
+ continue;
+
+ /* Backface culling. */
+ facing = (c < 0.0F) ^ ctx->Polygon.FrontBit;
+ if ( (facing + 1) & ctx->Polygon.CullBits )
+ continue;
+
+ /* Need right color if we have two sided lighting. */
+ if ( ctx->IndirectTriangles & DD_TRI_LIGHT_TWOSIDE )
+ {
+ if ( facing == 1 )
+ {
+ /* use back color */
+ VB->Color = VB->Bcolor;
+ VB->Specular= VB->Bspec;
+ }
+ else
+ {
+ /* use front color */
+ VB->Color = VB->Fcolor;
+ VB->Specular= VB->Fspec;
+ }
+ }
+
+ if ( ctx->IndirectTriangles & DD_TRI_OFFSET )
+ {
+ /* Finish computing plane equation of polygon, compute offset */
+ GLfloat fz = VB->Win[v3][2] - VB->Win[v1][2];
+ GLfloat ez = VB->Win[v2][2] - VB->Win[v1][2];
+ GLfloat a = (ey * fz) - (ez * fy);
+ GLfloat b = (ez * fx) - (ex * fz);
+ OffsetPolygon( ctx, a, b, c );
+ }
+ /*=====================================*/
+ /* Populate the the triangle vertices. */
+ /*=====================================*/
+
+ /* Solve the prevoking vertex color as we need it for the 3rd triangle and flat shading. */
+ dwPVColor = (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2];
+
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v1][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v1][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v1][2] + ctx->PolygonZoffset) );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v1][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v1][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v1][3]) );
+ D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?
+ dwPVColor :
+ (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2];
+
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v2][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v2][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v2][2] + ctx->PolygonZoffset) );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v2][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v2][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v2][3]) );
+ D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?
+ dwPVColor :
+ (VB->Color[v2][3]<<24) | (VB->Color[v2][0]<<16) | (VB->Color[v2][1]<<8) | VB->Color[v2][2];
+
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v3][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v3][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v3][2] + ctx->PolygonZoffset) );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v3][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v3][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v3][3]) );
+ D3DTLVertices[cVertex++].color= dwPVColor;
+ }
+ }
+
+ /* Render the converted vertex buffer. */
+ if ( cVertex )
+ DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLELIST, &D3DTLVertices[0], cVertex );
+ }
+}
+/*===========================================================================*/
+/* This function will render the current vertex buffer as Quads. The buffer*/
+/* has to be able to be rendered directly. This means that we are filled, no*/
+/* offsets, no culling and one sided rendering. Also we must be in render */
+/* mode of cource. */
+/* First I will fill the global D3D vertice buffer. Next I will set all the*/
+/* states for D3D based on the current OGL state. Finally I pass the D3D VB */
+/* to the wrapper that call DrawPrimitives. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void RenderQuadVB( GLcontext *ctx, GLuint start, GLuint end )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ struct vertex_buffer *VB = ctx->VB;
+ int index,
+ cVertex,
+ height = (pContext->pShared->rectW.bottom - pContext->pShared->rectW.top);
+ DWORD dwPVColor;
+ GLfloat ex, ey,
+ fx, fy, c;
+ GLuint facing; /* 0=front, 1=back */
+
+ DPF(( DBG_FUNC, "RenderQuadVB();" ));
+
+#define v1 (index)
+#define v2 (index+1)
+#define v3 (index+2)
+#define v4 (index+3)
+
+ if ( (!(ctx->IndirectTriangles & DD_SW_SETUP)) && !VB->ClipOrMask )
+ {
+ DPF(( DBG_PRIM_PROFILE, "DirectTriangles" ));
+
+ for( cVertex = 0, index = start; index < end; index += 4 )
+ {
+ if ( ctx->Light.ShadeModel == GL_FLAT )
+ dwPVColor = (VB->Color[v4][3]<<24) | (VB->Color[v4][0]<<16) | (VB->Color[v4][1]<<8) | VB->Color[v4][2];
+
+ /*=====================================*/
+ /* Populate the the triangle vertices. */
+ /*=====================================*/
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v1][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v1][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( VB->Win[v1][2] );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v1][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v1][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v1][3]) );
+ D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?
+ dwPVColor :
+ (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2];
+
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v2][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v2][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( VB->Win[v2][2] );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v2][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v2][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v2][3]) );
+ D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?
+ dwPVColor :
+ (VB->Color[v2][3]<<24) | (VB->Color[v2][0]<<16) | (VB->Color[v2][1]<<8) | VB->Color[v2][2];
+
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v3][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v3][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( VB->Win[v3][2] );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v3][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v3][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v3][3]) );
+ D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?
+ dwPVColor :
+ (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2];
+
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v1][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v1][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( VB->Win[v1][2] );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v1][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v1][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v1][3]) );
+ D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?
+ dwPVColor :
+ (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2];
+
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v3][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v3][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( VB->Win[v3][2] );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v3][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v3][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v3][3]) );
+ D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?
+ dwPVColor :
+ (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2];
+
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v4][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v4][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( VB->Win[v4][2] );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v4][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v4][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v4][3]) );
+ D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?
+ dwPVColor :
+ (VB->Color[v4][3]<<24) | (VB->Color[v4][0]<<16) | (VB->Color[v4][1]<<8) | VB->Color[v4][2];
+ }
+ }
+ else
+ {
+ for( cVertex = 0, index = start; index < end; index += 4 )
+ {
+ if ( VB->ClipMask[v1] & VB->ClipMask[v2] & VB->ClipMask[v3] & VB->ClipMask[v4] & CLIP_ALL_BITS )
+ {
+ continue;
+ }
+ else if ( VB->ClipMask[v1] | VB->ClipMask[v2] | VB->ClipMask[v3] | VB->ClipMask[v4] )
+ {
+ VList[0] = v1;
+ VList[1] = v2;
+ VList[2] = v3;
+ VList[3] = v4;
+ RenderClippedPolygon( ctx, 4, VList );
+ continue;
+ }
+
+ /* Compute orientation of triangle */
+ ex = VB->Win[v2][0] - VB->Win[v1][0];
+ ey = VB->Win[v2][1] - VB->Win[v1][1];
+ fx = VB->Win[v3][0] - VB->Win[v1][0];
+ fy = VB->Win[v3][1] - VB->Win[v1][1];
+ c = (ex * fy) - (ey * fx);
+
+ /* polygon is perpindicular to view plane, don't draw it */
+ if ( (c == 0.0F) && !ctx->Polygon.Unfilled )
+ continue;
+
+ /* Backface culling. */
+ facing = (c < 0.0F) ^ ctx->Polygon.FrontBit;
+ if ( (facing + 1) & ctx->Polygon.CullBits )
+ continue;
+
+ if ( ctx->IndirectTriangles & DD_TRI_LIGHT_TWOSIDE )
+ {
+ if ( facing == 1 )
+ {
+ /* use back color */
+ VB->Color = VB->Bcolor;
+ VB->Specular= VB->Bspec;
+ }
+ else
+ {
+ /* use front color */
+ VB->Color = VB->Fcolor;
+ VB->Specular= VB->Fspec;
+ }
+ }
+
+ if ( ctx->IndirectTriangles & DD_TRI_OFFSET )
+ {
+ /* Finish computing plane equation of polygon, compute offset */
+ GLfloat fz = VB->Win[v3][2] - VB->Win[v1][2];
+ GLfloat ez = VB->Win[v2][2] - VB->Win[v1][2];
+ GLfloat a = (ey * fz) - (ez * fy);
+ GLfloat b = (ez * fx) - (ex * fz);
+ OffsetPolygon( ctx, a, b, c );
+ }
+
+ if ( ctx->Light.ShadeModel == GL_FLAT )
+ dwPVColor = (VB->Color[v4][3]<<24) | (VB->Color[v4][0]<<16) | (VB->Color[v4][1]<<8) | VB->Color[v4][2];
+
+ /*=====================================*/
+ /* Populate the the triangle vertices. */
+ /*=====================================*/
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v1][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v1][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v1][2] + ctx->PolygonZoffset) );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v1][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v1][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v1][3]) );
+ D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?
+ dwPVColor :
+ (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2];
+
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v2][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v2][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v2][2] + ctx->PolygonZoffset) );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v2][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v2][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v2][3]) );
+ D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?
+ dwPVColor :
+ (VB->Color[v2][3]<<24) | (VB->Color[v2][0]<<16) | (VB->Color[v2][1]<<8) | VB->Color[v2][2];
+
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v3][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v3][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v3][2] + ctx->PolygonZoffset) );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v3][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v3][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v3][3]) );
+ D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?
+ dwPVColor :
+ (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2];
+
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v1][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v1][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v1][2] + ctx->PolygonZoffset) );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v1][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v1][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v1][3]) );
+ D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?
+ dwPVColor :
+ (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2];
+
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v3][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v3][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v3][2] + ctx->PolygonZoffset) );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v3][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v3][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v3][3]) );
+ D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?
+ dwPVColor :
+ (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2];
+
+ D3DTLVertices[cVertex].sx = D3DVAL( VB->Win[v4][0] );
+ D3DTLVertices[cVertex].sy = D3DVAL( (height - VB->Win[v4][1]) );
+ D3DTLVertices[cVertex].sz = D3DVAL( (VB->Win[v4][2] + ctx->PolygonZoffset) );
+ D3DTLVertices[cVertex].tu = D3DVAL( VB->TexCoord[v4][0] );
+ D3DTLVertices[cVertex].tv = D3DVAL( VB->TexCoord[v4][1] );
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[v4][3]) );
+ D3DTLVertices[cVertex++].color= (ctx->Light.ShadeModel == GL_FLAT) ?
+ dwPVColor :
+ (VB->Color[v4][3]<<24) | (VB->Color[v4][0]<<16) | (VB->Color[v4][1]<<8) | VB->Color[v4][2];
+ }
+ }
+
+#undef v4
+#undef v3
+#undef v2
+#undef v1
+
+ /* Render the converted vertex buffer. */
+ if ( cVertex )
+ DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLELIST, &D3DTLVertices[0], cVertex );
+}
+/*===========================================================================*/
+/* */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+static void RenderQuad( GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint v4, GLuint pv )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ struct vertex_buffer *VB = ctx->VB;
+ int height = (pContext->pShared->rectW.bottom - pContext->pShared->rectW.top);
+ DWORD dwPVColor;
+ GLfloat ex, ey,
+ fx, fy, c;
+ GLuint facing; /* 0=front, 1=back */
+ static D3DTLVERTEX TLVertices[6];
+
+ DPF(( DBG_FUNC, "RenderQuad" ));
+ DPF(( DBG_PRIM_INFO, "RenderQuad( 1 )" ));
+
+ /* Compute orientation of triangle */
+ ex = VB->Win[v2][0] - VB->Win[v1][0];
+ ey = VB->Win[v2][1] - VB->Win[v1][1];
+ fx = VB->Win[v3][0] - VB->Win[v1][0];
+ fy = VB->Win[v3][1] - VB->Win[v1][1];
+ c = (ex * fy) - (ey * fx);
+
+ /* polygon is perpindicular to view plane, don't draw it */
+ if ( (c == 0.0F) && !ctx->Polygon.Unfilled )
+ return;
+
+ /* Backface culling. */
+ facing = (c < 0.0F) ^ ctx->Polygon.FrontBit;
+ if ( (facing + 1) & ctx->Polygon.CullBits )
+ return;
+
+ if ( ctx->IndirectTriangles & DD_TRI_LIGHT_TWOSIDE )
+ {
+ if ( facing == 1 )
+ {
+ /* use back color */
+ VB->Color = VB->Bcolor;
+ VB->Specular= VB->Bspec;
+ }
+ else
+ {
+ /* use front color */
+ VB->Color = VB->Fcolor;
+ VB->Specular= VB->Fspec;
+ }
+ }
+
+ if ( ctx->IndirectTriangles & DD_TRI_OFFSET )
+ {
+ /* Finish computing plane equation of polygon, compute offset */
+ GLfloat fz = VB->Win[v3][2] - VB->Win[v1][2];
+ GLfloat ez = VB->Win[v2][2] - VB->Win[v1][2];
+ GLfloat a = (ey * fz) - (ez * fy);
+ GLfloat b = (ez * fx) - (ex * fz);
+ OffsetPolygon( ctx, a, b, c );
+ }
+
+ if ( ctx->Light.ShadeModel == GL_FLAT )
+ dwPVColor = (VB->Color[pv][3]<<24) | (VB->Color[pv][0]<<16) | (VB->Color[pv][1]<<8) | VB->Color[pv][2];
+
+ /*=====================================*/
+ /* Populate the the triangle vertices. */
+ /*=====================================*/
+ TLVertices[0].sx = D3DVAL( VB->Win[v1][0] );
+ TLVertices[0].sy = D3DVAL( (height - VB->Win[v1][1]) );
+ TLVertices[0].sz = D3DVAL( (VB->Win[v1][2] + ctx->PolygonZoffset) );
+ TLVertices[0].tu = D3DVAL( VB->TexCoord[v1][0] );
+ TLVertices[0].tv = D3DVAL( VB->TexCoord[v1][1] );
+ TLVertices[0].rhw = D3DVAL( (1.0 / VB->Clip[v1][3]) );
+ TLVertices[0].color = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor :
+ (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2];
+
+ TLVertices[1].sx = D3DVAL( VB->Win[v2][0] );
+ TLVertices[1].sy = D3DVAL( (height - VB->Win[v2][1]) );
+ TLVertices[1].sz = D3DVAL( (VB->Win[v2][2] + ctx->PolygonZoffset) );
+ TLVertices[1].tu = D3DVAL( VB->TexCoord[v2][0] );
+ TLVertices[1].tv = D3DVAL( VB->TexCoord[v2][1] );
+ TLVertices[1].rhw = D3DVAL( (1.0 / VB->Clip[v2][3]) );
+ TLVertices[1].color = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor :
+ (VB->Color[v2][3]<<24) | (VB->Color[v2][0]<<16) | (VB->Color[v2][1]<<8) | VB->Color[v2][2];
+
+ TLVertices[2].sx = D3DVAL( VB->Win[v3][0] );
+ TLVertices[2].sy = D3DVAL( (height - VB->Win[v3][1]) );
+ TLVertices[2].sz = D3DVAL( (VB->Win[v3][2] + ctx->PolygonZoffset) );
+ TLVertices[2].tu = D3DVAL( VB->TexCoord[v3][0] );
+ TLVertices[2].tv = D3DVAL( VB->TexCoord[v3][1] );
+ TLVertices[2].rhw = D3DVAL( (1.0 / VB->Clip[v3][3]) );
+ TLVertices[2].color = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor :
+ (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2];
+
+ TLVertices[3].sx = D3DVAL( VB->Win[v3][0] );
+ TLVertices[3].sy = D3DVAL( (height - VB->Win[v3][1]) );
+ TLVertices[3].sz = D3DVAL( (VB->Win[v3][2] + ctx->PolygonZoffset) );
+ TLVertices[3].tu = D3DVAL( VB->TexCoord[v3][0] );
+ TLVertices[3].tv = D3DVAL( VB->TexCoord[v3][1] );
+ TLVertices[3].rhw = D3DVAL( (1.0 / VB->Clip[v3][3]) );
+ TLVertices[3].color = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor :
+ (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2];
+
+ TLVertices[4].sx = D3DVAL( VB->Win[v4][0] );
+ TLVertices[4].sy = D3DVAL( (height - VB->Win[v4][1]) );
+ TLVertices[4].sz = D3DVAL( (VB->Win[v4][2] + ctx->PolygonZoffset) );
+ TLVertices[4].tu = D3DVAL( VB->TexCoord[v4][0] );
+ TLVertices[4].tv = D3DVAL( VB->TexCoord[v4][1] );
+ TLVertices[4].rhw = D3DVAL( (1.0 / VB->Clip[v4][3]) );
+ TLVertices[4].color = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor :
+ (VB->Color[v4][3]<<24) | (VB->Color[v4][0]<<16) | (VB->Color[v4][1]<<8) | VB->Color[v4][2];
+
+ TLVertices[5].sx = D3DVAL( VB->Win[v1][0] );
+ TLVertices[5].sy = D3DVAL( (height - VB->Win[v1][1]) );
+ TLVertices[5].sz = D3DVAL( (VB->Win[v1][2] + ctx->PolygonZoffset) );
+ TLVertices[5].tu = D3DVAL( VB->TexCoord[v1][0] );
+ TLVertices[5].tv = D3DVAL( VB->TexCoord[v1][1] );
+ TLVertices[5].rhw = D3DVAL( (1.0 / VB->Clip[v1][3]) );
+ TLVertices[5].color = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor :
+ (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2];
+
+ /* Draw the two triangles. */
+ DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLELIST, &TLVertices[0], 6 );
+}
+/*===========================================================================*/
+/* */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+void RenderOneTriangle( GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint pv )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ struct vertex_buffer *VB = ctx->VB;
+ int height = (pContext->pShared->rectW.bottom - pContext->pShared->rectW.top);
+ DWORD dwPVColor;
+ static D3DTLVERTEX TLVertices[3];
+
+ DPF(( DBG_FUNC, "RenderOneTriangle" ));
+ DPF(( DBG_PRIM_INFO, "RenderTriangle( 1 )" ));
+
+ /*=====================================*/
+ /* Populate the the triangle vertices. */
+ /*=====================================*/
+ if ( ctx->Light.ShadeModel == GL_FLAT )
+ dwPVColor = (VB->Color[pv][3]<<24) | (VB->Color[pv][0]<<16) | (VB->Color[pv][1]<<8) | VB->Color[pv][2];
+
+ TLVertices[0].sx = D3DVAL( VB->Win[v1][0] );
+ TLVertices[0].sy = D3DVAL( (height - VB->Win[v1][1]) );
+ TLVertices[0].sz = D3DVAL( (VB->Win[v1][2] + ctx->PolygonZoffset) );
+ TLVertices[0].tu = D3DVAL( VB->TexCoord[v1][0] );
+ TLVertices[0].tv = D3DVAL( VB->TexCoord[v1][1] );
+ TLVertices[0].rhw = D3DVAL( (1.0 / VB->Clip[v1][3]) );
+ TLVertices[0].color = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor :
+ (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2];
+ DPF(( DBG_PRIM_INFO, "V1 -> x:%f y:%f z:%f c:%x",
+ TLVertices[0].sx,
+ TLVertices[0].sy,
+ TLVertices[0].sz,
+ TLVertices[0].color ));
+
+ TLVertices[1].sx = D3DVAL( VB->Win[v2][0] );
+ TLVertices[1].sy = D3DVAL( (height - VB->Win[v2][1]) );
+ TLVertices[1].sz = D3DVAL( (VB->Win[v2][2] + ctx->PolygonZoffset) );
+ TLVertices[1].tu = D3DVAL( VB->TexCoord[v2][0] );
+ TLVertices[1].tv = D3DVAL( VB->TexCoord[v2][1] );
+ TLVertices[1].rhw = D3DVAL( (1.0 / VB->Clip[v2][3]) );
+ TLVertices[1].color = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor :
+ (VB->Color[v2][3]<<24) | (VB->Color[v2][0]<<16) | (VB->Color[v2][1]<<8) | VB->Color[v2][2];
+ DPF(( DBG_PRIM_INFO, "V2 -> x:%f y:%f z:%f c:%x",
+ TLVertices[1].sx,
+ TLVertices[1].sy,
+ TLVertices[1].sz,
+ TLVertices[1].color ));
+
+ TLVertices[2].sx = D3DVAL( VB->Win[v3][0] );
+ TLVertices[2].sy = D3DVAL( (height - VB->Win[v3][1]) );
+ TLVertices[2].sz = D3DVAL( (VB->Win[v3][2] + ctx->PolygonZoffset) );
+ TLVertices[2].tu = D3DVAL( VB->TexCoord[v3][0] );
+ TLVertices[2].tv = D3DVAL( VB->TexCoord[v3][1] );
+ TLVertices[2].rhw = D3DVAL( (1.0 / VB->Clip[v3][3]) );
+ TLVertices[2].color = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor :
+ (VB->Color[v3][3]<<24) | (VB->Color[v3][0]<<16) | (VB->Color[v3][1]<<8) | VB->Color[v3][2];
+ DPF(( DBG_PRIM_INFO, "V3 -> x:%f y:%f z:%f c:%x",
+ TLVertices[2].sx,
+ TLVertices[2].sy,
+ TLVertices[2].sz,
+ TLVertices[2].color ));
+
+ /* Draw the triangle. */
+ DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLELIST, &TLVertices[0], 3 );
+}
+/*===========================================================================*/
+/* */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+void RenderOneLine( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ struct vertex_buffer *VB = ctx->VB;
+ int height = (pContext->pShared->rectW.bottom - pContext->pShared->rectW.top);
+ DWORD dwPVColor;
+ static D3DTLVERTEX TLVertices[2];
+
+ DPF(( DBG_FUNC, "RenderOneLine" ));
+ DPF(( DBG_PRIM_INFO, "RenderLine( 1 )" ));
+
+ if ( VB->MonoColor )
+ dwPVColor = (pContext->aCurrent<<24) | (pContext->rCurrent<<16) | (pContext->gCurrent<<8) | pContext->bCurrent;
+ else
+ dwPVColor = (VB->Color[pv][3]<<24) | (VB->Color[pv][0]<<16) | (VB->Color[pv][1]<<8) | VB->Color[pv][2];
+
+ TLVertices[0].sx = D3DVAL( VB->Win[v1][0] );
+ TLVertices[0].sy = D3DVAL( (height - VB->Win[v1][1]) );
+ TLVertices[0].sz = D3DVAL( (VB->Win[v1][2] + ctx->LineZoffset) );
+ TLVertices[0].tu = D3DVAL( VB->TexCoord[v1][0] );
+ TLVertices[0].tv = D3DVAL( VB->TexCoord[v1][1] );
+ TLVertices[0].rhw = D3DVAL( (1.0 / VB->Clip[v1][3]) );
+ TLVertices[0].color = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor :
+ (VB->Color[v1][3]<<24) | (VB->Color[v1][0]<<16) | (VB->Color[v1][1]<<8) | VB->Color[v1][2];
+
+ TLVertices[1].sx = D3DVAL( VB->Win[v2][0] );
+ TLVertices[1].sy = D3DVAL( (height - VB->Win[v2][1]) );
+ TLVertices[1].sz = D3DVAL( (VB->Win[v2][2] + ctx->LineZoffset) );
+ TLVertices[1].tu = D3DVAL( VB->TexCoord[v2][0] );
+ TLVertices[1].tv = D3DVAL( VB->TexCoord[v2][1] );
+ TLVertices[1].rhw = D3DVAL( (1.0 / VB->Clip[v2][3]) );
+ TLVertices[1].color = (ctx->Light.ShadeModel == GL_FLAT) ? dwPVColor :
+ (VB->Color[v2][3]<<24) | (VB->Color[v2][0]<<16) | (VB->Color[v2][1]<<8) | VB->Color[v2][2];
+
+ /* Draw line from (x0,y0) to (x1,y1) with current pixel color/index */
+ DrawPrimitiveHAL( pContext->pShared, D3DPT_LINELIST, &TLVertices[0], 2 );
+}
+/*===========================================================================*/
+/* This function was written to convert points into triangles. I did this */
+/* as all card accelerate triangles and most drivers do this anyway. In hind*/
+/* thought this might be a bad idea as some cards do better. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void RenderPointsVB( GLcontext *ctx, GLuint start, GLuint end )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ struct vertex_buffer *VB = ctx->VB;
+ struct pixel_buffer *PB = ctx->PB;
+ GLuint index;
+ GLfloat radius, z,
+ xmin, ymin,
+ xmax, ymax;
+ GLint cVertex,
+ height = (pContext->pShared->rectW.bottom - pContext->pShared->rectW.top);
+ DWORD dwPVColor;
+
+ DPF(( DBG_FUNC, "RenderPointsVB();" ));
+
+ radius = CLAMP( ctx->Point.Size, MIN_POINT_SIZE, MAX_POINT_SIZE ) * 0.5F;
+
+ for( index = start, cVertex = 0; index <= end; index++ )
+ {
+ if ( VB->ClipMask[index] == 0 )
+ {
+ xmin = D3DVAL( VB->Win[index][0] - radius );
+ xmax = D3DVAL( VB->Win[index][0] + radius );
+ ymin = D3DVAL( height - VB->Win[index][1] - radius );
+ ymax = D3DVAL( height - VB->Win[index][1] + radius );
+ z = D3DVAL( (VB->Win[index][2] + ctx->PointZoffset) );
+
+ dwPVColor = (VB->Color[index][3]<<24) |
+ (VB->Color[index][0]<<16) |
+ (VB->Color[index][1]<<8) |
+ VB->Color[index][2];
+
+ D3DTLVertices[cVertex].sx = xmin;
+ D3DTLVertices[cVertex].sy = ymax;
+ D3DTLVertices[cVertex].sz = z;
+ D3DTLVertices[cVertex].tu = 0.0;
+ D3DTLVertices[cVertex].tv = 0.0;
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[index][3]) );
+ D3DTLVertices[cVertex++].color = dwPVColor;
+
+ D3DTLVertices[cVertex].sx = xmin;
+ D3DTLVertices[cVertex].sy = ymin;
+ D3DTLVertices[cVertex].sz = z;
+ D3DTLVertices[cVertex].tu = 0.0;
+ D3DTLVertices[cVertex].tv = 0.0;
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[index][3]) );
+ D3DTLVertices[cVertex++].color = dwPVColor;
+
+ D3DTLVertices[cVertex].sx = xmax;
+ D3DTLVertices[cVertex].sy = ymin;
+ D3DTLVertices[cVertex].sz = z;
+ D3DTLVertices[cVertex].tu = 0.0;
+ D3DTLVertices[cVertex].tv = 0.0;
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[index][3]) );
+ D3DTLVertices[cVertex++].color = dwPVColor;
+
+ D3DTLVertices[cVertex].sx = xmax;
+ D3DTLVertices[cVertex].sy = ymin;
+ D3DTLVertices[cVertex].sz = z;
+ D3DTLVertices[cVertex].tu = 0.0;
+ D3DTLVertices[cVertex].tv = 0.0;
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[index][3]) );
+ D3DTLVertices[cVertex++].color = dwPVColor;
+
+ D3DTLVertices[cVertex].sx = xmax;
+ D3DTLVertices[cVertex].sy = ymax;
+ D3DTLVertices[cVertex].sz = z;
+ D3DTLVertices[cVertex].tu = 0.0;
+ D3DTLVertices[cVertex].tv = 0.0;
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[index][3]) );
+ D3DTLVertices[cVertex++].color = dwPVColor;
+
+ D3DTLVertices[cVertex].sx = xmin;
+ D3DTLVertices[cVertex].sy = ymax;
+ D3DTLVertices[cVertex].sz = z;
+ D3DTLVertices[cVertex].tu = 0.0;
+ D3DTLVertices[cVertex].tv = 0.0;
+ D3DTLVertices[cVertex].rhw = D3DVAL( (1.0 / VB->Clip[index][3]) );
+ D3DTLVertices[cVertex++].color = dwPVColor;
+ }
+ }
+
+ /* Render the converted vertex buffer. */
+ if ( cVertex )
+ DrawPrimitiveHAL( pContext->pShared, D3DPT_TRIANGLELIST, &D3DTLVertices[0], cVertex );
+}
+/*===========================================================================*/
+/* This gets call before we render any primitives so that the current OGL */
+/* states will be mapped the D3D context. I'm still not sure how D3D works */
+/* but I'm finding that it doesn't act like a state machine as OGL is. It */
+/* looks like the state gets set back to the defaults after a DrawPrimitives */
+/* or an EndScene. Also I set states that are the default even though this */
+/* is redundant as the defaults seem screwed up. */
+/* TODO: make a batch call. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void SetRenderStates( GLcontext *ctx )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ DWORD dwFunc;
+ static BOOL bTexture = FALSE;
+ static int texName = -1;
+
+ DPF(( DBG_FUNC, "SetRenderStates();" ));
+
+ if ( g_DBGMask & DBG_STATES )
+ DebugRenderStates( ctx, FALSE );
+
+ SetStateHAL( pContext->pShared, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE );
+ SetStateHAL( pContext->pShared, D3DRENDERSTATE_DITHERENABLE, (ctx->Color.DitherFlag) ? TRUE : FALSE );
+
+ /*================================================*/
+ /* Check too see if there are new TEXTURE states. */
+ /*================================================*/
+ if ( ctx->Texture.Enabled )
+ {
+ switch( ctx->Texture.Set[ctx->Texture.CurrentSet].EnvMode )
+ {
+ case GL_MODULATE:
+ if ( ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Format == GL_RGBA )
+ dwFunc = pContext->pShared->dwTexFunc[d3dtblend_modulatealpha];
+ else
+ dwFunc = pContext->pShared->dwTexFunc[d3dtblend_modulate];
+ break;
+
+ case GL_BLEND:
+ dwFunc = pContext->pShared->dwTexFunc[d3dtblend_decalalpha];
+ break;
+
+ case GL_REPLACE:
+ dwFunc = pContext->pShared->dwTexFunc[d3dtblend_decal];
+ break;
+
+ case GL_DECAL:
+ if ( ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Format == GL_RGBA )
+ dwFunc = pContext->pShared->dwTexFunc[d3dtblend_decalalpha];
+ else
+ dwFunc = pContext->pShared->dwTexFunc[d3dtblend_decal];
+ break;
+ }
+ SetStateHAL( pContext->pShared, D3DRENDERSTATE_TEXTUREMAPBLEND, dwFunc );
+
+ switch( ctx->Texture.Set[ctx->Texture.CurrentSet].Current->MagFilter )
+ {
+ case GL_NEAREST:
+ dwFunc = D3DFILTER_NEAREST;
+ break;
+ case GL_LINEAR:
+ dwFunc = D3DFILTER_LINEAR;
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ dwFunc = D3DFILTER_MIPNEAREST;
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ dwFunc = D3DFILTER_LINEARMIPNEAREST;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ dwFunc = D3DFILTER_MIPLINEAR;
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ dwFunc = D3DFILTER_LINEARMIPLINEAR;
+ break;
+ }
+ SetStateHAL( pContext->pShared, D3DRENDERSTATE_TEXTUREMAG, dwFunc );
+
+ switch( ctx->Texture.Set[ctx->Texture.CurrentSet].Current->MinFilter )
+ {
+ case GL_NEAREST:
+ dwFunc = D3DFILTER_NEAREST;
+ break;
+ case GL_LINEAR:
+ dwFunc = D3DFILTER_LINEAR;
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ dwFunc = D3DFILTER_MIPNEAREST;
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ dwFunc = D3DFILTER_LINEARMIPNEAREST;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ dwFunc = D3DFILTER_MIPLINEAR;
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ dwFunc = D3DFILTER_LINEARMIPLINEAR;
+ break;
+ }
+ SetStateHAL( pContext->pShared, D3DRENDERSTATE_TEXTUREMIN, dwFunc );
+
+ /* Another hack to cut down on redundant texture binding. */
+ // if ( texName != ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Name )
+ // {
+ texName = ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Name;
+ CreateTMgrHAL( pContext->pShared,
+ texName,
+ 0,
+ ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Format,
+ (RECT *)NULL,
+ ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Width,
+ ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Height,
+ TM_ACTION_BIND,
+ (void *)ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Data );
+ // }
+ bTexture = TRUE;
+ }
+ else
+ {
+ /* This is nasty but should cut down on the number of redundant calls. */
+ if ( bTexture == TRUE )
+ {
+ DisableTMgrHAL( pContext->pShared );
+ bTexture = FALSE;
+ }
+ }
+
+ /*===============================================*/
+ /* Check too see if there are new RASTER states. */
+ /*===============================================*/
+
+ // TODO: no concept of front & back.
+ switch( ctx->Polygon.FrontMode )
+ {
+ case GL_POINT:
+ SetStateHAL( pContext->pShared, D3DRENDERSTATE_FILLMODE, D3DFILL_POINT );
+ break;
+ case GL_LINE:
+ SetStateHAL( pContext->pShared, D3DRENDERSTATE_FILLMODE, D3DFILL_WIREFRAME );
+ break;
+ case GL_FILL:
+ SetStateHAL( pContext->pShared, D3DRENDERSTATE_FILLMODE, D3DFILL_SOLID );
+ break;
+ }
+
+ /*************/
+ /* Z-Buffer. */
+ /*************/
+ if ( ctx->Depth.Test == GL_TRUE )
+ {
+ switch( ctx->Depth.Func )
+ {
+ case GL_NEVER:
+ dwFunc = D3DCMP_NEVER;
+ break;
+ case GL_LESS:
+ dwFunc = D3DCMP_LESS;
+ break;
+ case GL_GEQUAL:
+ dwFunc = D3DCMP_GREATEREQUAL;
+ break;
+ case GL_LEQUAL:
+ dwFunc = D3DCMP_LESSEQUAL;
+ break;
+ case GL_GREATER:
+ dwFunc = D3DCMP_GREATER;
+ break;
+ case GL_NOTEQUAL:
+ dwFunc = D3DCMP_NOTEQUAL;
+ break;
+ case GL_EQUAL:
+ dwFunc = D3DCMP_EQUAL;
+ break;
+ case GL_ALWAYS:
+ dwFunc = D3DCMP_ALWAYS;
+ break;
+ }
+ SetStateHAL( pContext->pShared, D3DRENDERSTATE_ZFUNC, dwFunc );
+ SetStateHAL( pContext->pShared, D3DRENDERSTATE_ZENABLE, TRUE );
+ }
+ else
+ {
+ SetStateHAL( pContext->pShared, D3DRENDERSTATE_ZENABLE, FALSE );
+ }
+
+ /*******************/
+ /* Z-Write Enable. */
+ /*******************/
+ SetStateHAL( pContext->pShared, D3DRENDERSTATE_ZWRITEENABLE , (ctx->Depth.Mask == GL_TRUE) ? TRUE : FALSE );
+
+ /***************/
+ /* Alpha test. */
+ /***************/
+ if ( ctx->Color.AlphaEnabled == GL_TRUE )
+ {
+ switch( ctx->Color.AlphaFunc )
+ {
+ case GL_NEVER:
+ dwFunc = D3DCMP_NEVER;
+ break;
+ case GL_LESS:
+ dwFunc = D3DCMP_LESS;
+ break;
+ case GL_GEQUAL:
+ dwFunc = D3DCMP_GREATEREQUAL;
+ break;
+ case GL_LEQUAL:
+ dwFunc = D3DCMP_LESSEQUAL;
+ break;
+ case GL_GREATER:
+ dwFunc = D3DCMP_GREATER;
+ break;
+ case GL_NOTEQUAL:
+ dwFunc = D3DCMP_NOTEQUAL;
+ break;
+ case GL_EQUAL:
+ dwFunc = D3DCMP_EQUAL;
+ break;
+ case GL_ALWAYS:
+ dwFunc = D3DCMP_ALWAYS;
+ break;
+ }
+ SetStateHAL( pContext->pShared, D3DRENDERSTATE_ALPHAFUNC , dwFunc );
+ SetStateHAL( pContext->pShared, D3DRENDERSTATE_ALPHATESTENABLE, TRUE );
+ }
+ else
+ {
+ SetStateHAL( pContext->pShared, D3DRENDERSTATE_ALPHATESTENABLE, FALSE );
+ }
+
+ /****************/
+ /* Alpha blend. */
+ /****************/
+ if ( ctx->Color.BlendEnabled == GL_TRUE )
+ {
+ switch( ctx->Color.BlendSrc )
+ {
+ case GL_ZERO:
+ dwFunc = pContext->pShared->dwSrcBlendCaps[s_zero];
+ break;
+ case GL_ONE:
+ dwFunc = pContext->pShared->dwSrcBlendCaps[s_one];
+ break;
+ case GL_DST_COLOR:
+ dwFunc = pContext->pShared->dwSrcBlendCaps[s_dst_color];
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ dwFunc = pContext->pShared->dwSrcBlendCaps[s_one_minus_dst_color];
+ break;
+ case GL_SRC_ALPHA:
+ dwFunc = pContext->pShared->dwSrcBlendCaps[s_src_alpha];
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ dwFunc = pContext->pShared->dwSrcBlendCaps[s_one_minus_src_alpha];
+ break;
+ case GL_DST_ALPHA:
+ dwFunc = pContext->pShared->dwSrcBlendCaps[s_dst_alpha];
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ dwFunc = pContext->pShared->dwSrcBlendCaps[s_one_minus_dst_alpha];
+ break;
+ case GL_SRC_ALPHA_SATURATE:
+ dwFunc = pContext->pShared->dwSrcBlendCaps[s_src_alpha_saturate];
+ break;
+ case GL_CONSTANT_COLOR:
+ dwFunc = pContext->pShared->dwSrcBlendCaps[s_constant_color];
+ break;
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ dwFunc = pContext->pShared->dwSrcBlendCaps[s_one_minus_constant_color];
+ break;
+ case GL_CONSTANT_ALPHA:
+ dwFunc = pContext->pShared->dwSrcBlendCaps[s_constant_alpha];
+ break;
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ dwFunc = pContext->pShared->dwSrcBlendCaps[s_one_minus_constant_alpha];
+ break;
+ }
+ SetStateHAL( pContext->pShared, D3DRENDERSTATE_SRCBLEND, dwFunc );
+
+ switch( ctx->Color.BlendDst )
+ {
+ case GL_ZERO:
+ dwFunc = pContext->pShared->dwDestBlendCaps[d_zero];
+ break;
+ case GL_ONE:
+ dwFunc = pContext->pShared->dwDestBlendCaps[d_one];
+ break;
+ case GL_SRC_COLOR:
+ dwFunc = pContext->pShared->dwDestBlendCaps[d_src_color];
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ dwFunc = pContext->pShared->dwDestBlendCaps[d_one_minus_src_color];
+ break;
+ case GL_SRC_ALPHA:
+ dwFunc = pContext->pShared->dwDestBlendCaps[d_src_alpha];
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ dwFunc = pContext->pShared->dwDestBlendCaps[d_one_minus_src_alpha];
+ break;
+ case GL_DST_ALPHA:
+ dwFunc = pContext->pShared->dwDestBlendCaps[d_dst_alpha];
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ dwFunc = pContext->pShared->dwDestBlendCaps[d_one_minus_dst_alpha];
+ break;
+ case GL_CONSTANT_COLOR:
+ dwFunc = pContext->pShared->dwDestBlendCaps[d_constant_color];
+ break;
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ dwFunc = pContext->pShared->dwDestBlendCaps[d_one_minus_constant_color];
+ break;
+ case GL_CONSTANT_ALPHA:
+ dwFunc = pContext->pShared->dwDestBlendCaps[d_constant_alpha];
+ break;
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ dwFunc = pContext->pShared->dwDestBlendCaps[d_one_minus_constant_alpha];
+ break;
+ }
+ SetStateHAL( pContext->pShared, D3DRENDERSTATE_DESTBLEND, dwFunc );
+ SetStateHAL( pContext->pShared, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE );
+ }
+ else
+ {
+ SetStateHAL( pContext->pShared, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE );
+ }
+}
+/*===========================================================================*/
+/* If this function is called it will track the changes to the current */
+/* states that I'm setting in Direct3D. I did this so that the DPF's would */
+/* be under control! */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void DebugRenderStates( GLcontext *ctx, BOOL bForce )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ DWORD dwFunc;
+ static int dither = -1,
+ texture = -1,
+ textName = -1,
+ textEnv = -1,
+ textMin = -1,
+ textMag = -1,
+ polyMode = -1,
+ depthTest = -1,
+ depthFunc = -1,
+ depthMask = -1,
+ alphaTest = -1,
+ alphaFunc = -1,
+ blend = -1,
+ blendSrc = -1,
+ blendDest = -1;
+
+ /* Force a displayed update of all current states. */
+ if ( bForce )
+ {
+ dither = texture = textName = textEnv = textMin = textMag = -1;
+ polyMode = depthTest = depthFunc = depthMask = -1;
+ alphaTest = alphaFunc = blend = blendSrc = blendDest = -1;
+ }
+
+ if ( dither != ctx->Color.DitherFlag )
+ {
+ dither = ctx->Color.DitherFlag;
+ DPF(( 0, "\tDither\t\t%s", (dither) ? "ENABLED" : "--------" ));
+ }
+ if ( depthTest != ctx->Depth.Test )
+ {
+ depthTest = ctx->Depth.Test;
+ DPF(( 0, "\tDepth Test\t%s", (depthTest) ? "ENABLED" : "--------" ));
+ }
+ if ( alphaTest != ctx->Color.AlphaEnabled )
+ {
+ alphaTest = ctx->Color.AlphaEnabled;
+
+ DPF(( 0, "\tAlpha Test\t%s", (alphaTest) ? "ENABLED" : "--------" ));
+ }
+ if ( blend != ctx->Color.BlendEnabled )
+ {
+ blend = ctx->Color.BlendEnabled;
+
+ DPF(( 0, "\tBlending\t%s", (blend) ? "ENABLED" : "--------" ));
+ }
+
+ /*================================================*/
+ /* Check too see if there are new TEXTURE states. */
+ /*================================================*/
+ if ( texture != ctx->Texture.Enabled )
+ {
+ texture = ctx->Texture.Enabled;
+ DPF(( 0, "\tTexture\t\t%s", (texture) ? "ENABLED" : "--------" ));
+ }
+
+ if ( ctx->Texture.Set[ctx->Texture.CurrentSet].Current )
+ {
+ if ( ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Name != textName )
+ {
+ textName = ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Name;
+ DPF(( 0, "\tTexture Name:\t%d", textName ));
+ DPF(( 0, "\tTexture Format:\t%s",
+ (ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Format == GL_RGBA) ?
+ "GL_RGBA" : "GLRGB" ));
+ }
+
+ if ( textEnv != ctx->Texture.Set[ctx->Texture.CurrentSet].EnvMode )
+ {
+ textEnv = ctx->Texture.Set[ctx->Texture.CurrentSet].EnvMode;
+
+ switch( textEnv )
+ {
+ case GL_MODULATE:
+ DPF(( 0, "\tTexture\tMode\tGL_MODULATE" ));
+ break;
+ case GL_BLEND:
+ DPF(( 0, "\tTexture\tMode\tGL_BLEND" ));
+ break;
+ case GL_REPLACE:
+ DPF(( 0, "\tTexture\tMode\tGL_REPLACE" ));
+ break;
+ case GL_DECAL:
+ DPF(( 0, "\tTexture\tMode\tGL_DECAL" ));
+ break;
+ }
+ }
+
+ if ( textMag != ctx->Texture.Set[ctx->Texture.CurrentSet].Current->MagFilter )
+ {
+ textMag = ctx->Texture.Set[ctx->Texture.CurrentSet].Current->MagFilter;
+
+ switch( textMag )
+ {
+ case GL_NEAREST:
+ DPF(( 0, "\tTexture MAG\tGL_NEAREST" ));
+ break;
+ case GL_LINEAR:
+ DPF(( 0, "\tTexture MAG\tGL_LINEAR" ));
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ DPF(( 0, "\tTexture MAG\tGL_NEAREST_MIPMAP_NEAREST" ));
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ DPF(( 0, "\tTexture MAG\tGL_LINEAR_MIPMAP_NEAREST" ));
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ DPF(( 0, "\tTexture MAG\tGL_NEAREST_MIPMAP_LINEAR" ));
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ DPF(( 0, "\tTexture MAG\tGL_LINEAR_MIPMAP_LINEAR" ));
+ break;
+ }
+ }
+
+ if ( textMin != ctx->Texture.Set[ctx->Texture.CurrentSet].Current->MinFilter )
+ {
+ textMin = ctx->Texture.Set[ctx->Texture.CurrentSet].Current->MinFilter;
+
+ switch( textMin )
+ {
+ case GL_NEAREST:
+ DPF(( 0, "\tTexture MIN\tGL_NEAREST" ));
+ break;
+ case GL_LINEAR:
+ DPF(( 0, "\tTexture MIN\tGL_LINEAR" ));
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ DPF(( 0, "\tTexture MIN\tGL_NEAREST_MIPMAP_NEAREST" ));
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ DPF(( 0, "\tTexture MIN\tGL_LINEAR_MIPMAP_NEAREST" ));
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ DPF(( 0, "\tTexture MIN\tGL_LINEAR_MIPMAP_LINEAR" ));
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ DPF(( 0, "\tTexture MIN\tGL_LINEAR_MIPMAP_LINEAR" ));
+ break;
+ }
+ }
+ }
+
+ if ( ctx->Polygon.FrontMode != polyMode )
+ {
+ polyMode = ctx->Polygon.FrontMode;
+
+ switch( polyMode )
+ {
+ case GL_POINT:
+ DPF(( 0, "\tMode\t\tGL_POINT" ));
+ break;
+ case GL_LINE:
+ DPF(( 0, "\tMode\t\tGL_LINE" ));
+ break;
+ case GL_FILL:
+ DPF(( 0, "\tMode\t\tGL_FILL" ));
+ break;
+ }
+ }
+
+ if ( depthFunc != ctx->Depth.Func )
+ {
+ depthFunc = ctx->Depth.Func;
+
+ switch( depthFunc )
+ {
+ case GL_NEVER:
+ DPF(( 0, "\tDepth Func\tGL_NEVER" ));
+ break;
+ case GL_LESS:
+ DPF(( 0, "\tDepth Func\tGL_LESS" ));
+ break;
+ case GL_GEQUAL:
+ DPF(( 0, "\tDepth Func\tGL_GEQUAL" ));
+ break;
+ case GL_LEQUAL:
+ DPF(( 0, "\tDepth Func\tGL_LEQUAL" ));
+ break;
+ case GL_GREATER:
+ DPF(( 0, "\tDepth Func\tGL_GREATER" ));
+ break;
+ case GL_NOTEQUAL:
+ DPF(( 0, "\tDepth Func\tGL_NOTEQUAL" ));
+ break;
+ case GL_EQUAL:
+ DPF(( 0, "\tDepth Func\tGL_EQUAL" ));
+ break;
+ case GL_ALWAYS:
+ DPF(( 0, "\tDepth Func\tGL_ALWAYS" ));
+ break;
+ }
+ }
+
+ if ( depthMask != ctx->Depth.Mask )
+ {
+ depthMask = ctx->Depth.Mask;
+ DPF(( 0, "\tZWrite\t\t%s", (depthMask) ? "ENABLED" : "--------" ));
+ }
+
+ if ( alphaFunc != ctx->Color.AlphaFunc )
+ {
+ alphaFunc = ctx->Color.AlphaFunc;
+
+ switch( alphaFunc )
+ {
+ case GL_NEVER:
+ DPF(( 0, "\tAlpha Func\tGL_NEVER" ));
+ break;
+ case GL_LESS:
+ DPF(( 0, "\tAlpha Func\tGL_LESS" ));
+ break;
+ case GL_GEQUAL:
+ DPF(( 0, "\tAlpha Func\tGL_GEQUAL" ));
+ break;
+ case GL_LEQUAL:
+ DPF(( 0, "\tAlpha Func\tGL_LEQUAL" ));
+ break;
+ case GL_GREATER:
+ DPF(( 0, "\tAlpha Func\tGL_GREATER" ));
+ break;
+ case GL_NOTEQUAL:
+ DPF(( 0, "\tAlpha Func\tGL_NOTEQUAL" ));
+ break;
+ case GL_EQUAL:
+ DPF(( 0, "\tAlpha Func\tGL_EQUAL" ));
+ break;
+ case GL_ALWAYS:
+ DPF(( 0, "\tAlpha Func\tGL_ALWAYS" ));
+ break;
+ }
+ }
+
+ if ( blendSrc != ctx->Color.BlendSrc )
+ {
+ blendSrc = ctx->Color.BlendSrc;
+
+ switch( blendSrc )
+ {
+ case GL_ZERO:
+ DPF(( 0, "\tSRC Blend\tGL_ZERO" ));
+ break;
+ case GL_ONE:
+ DPF(( 0, "\tSRC Blend\tGL_ONE" ));
+ break;
+ case GL_DST_COLOR:
+ DPF(( 0, "\tSRC Blend\tGL_DST_COLOR" ));
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ DPF(( 0, "\tSRC Blend\tGL_ONE_MINUS_DST_COLOR" ));
+ break;
+ case GL_SRC_ALPHA:
+ DPF(( 0, "\tSRC Blend\tGL_SRC_ALPHA" ));
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ DPF(( 0, "\tSRC Blend\tGL_MINUS_SRC_ALPHA" ));
+ break;
+ case GL_DST_ALPHA:
+ DPF(( 0, "\tSRC Blend\tGL_DST_ALPHA" ));
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ DPF(( 0, "\tSRC Blend\tGL_ONE_MINUS_DST_ALPHA" ));
+ break;
+ case GL_SRC_ALPHA_SATURATE:
+ DPF(( 0, "\tSRC Blend\tGL_SRC_ALPHA_SATURATE" ));
+ break;
+ case GL_CONSTANT_COLOR:
+ DPF(( 0, "\tSRC Blend\tGL_CONSTANT_COLOR" ));
+ break;
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ DPF(( 0, "\tSRC Blend\tGL_ONE_MINUS_CONSTANT_COLOR" ));
+ break;
+ case GL_CONSTANT_ALPHA:
+ DPF(( 0, "\tSRC Blend\tGL_CONSTANT_ALPHA" ));
+ break;
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ DPF(( 0, "\tSRC Blend\tGL_ONE_MINUS_CONSTANT_ALPHA" ));
+ break;
+ }
+ }
+
+ if ( blendDest != ctx->Color.BlendDst )
+ {
+ blendDest = ctx->Color.BlendDst;
+
+ switch( blendDest )
+ {
+ case GL_ZERO:
+ DPF(( 0, "\tDST Blend\tGL_ZERO" ));
+ break;
+ case GL_ONE:
+ DPF(( 0, "\tDST Blend\tGL_ONE" ));
+ break;
+ case GL_SRC_COLOR:
+ DPF(( 0, "\tDST Blend\tGL_SRC_COLOR" ));
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ DPF(( 0, "\tDST Blend\tGL_ONE_MINUS_SRC_COLOR" ));
+ break;
+ case GL_SRC_ALPHA:
+ DPF(( 0, "\tDST Blend\tGL_SRC_ALPHA" ));
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ DPF(( 0, "\tDST Blend\tGL_ONE_MINUS_SRC_ALPHA" ));
+ break;
+ case GL_DST_ALPHA:
+ DPF(( 0, "\tDST Blend\tGL_DST_ALPHA" ));
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ DPF(( 0, "\tDST Blend\tGL_ONE_MINUS_DST_ALPHA" ));
+ break;
+ case GL_CONSTANT_COLOR:
+ DPF(( 0, "\tDST Blend\tGL_CONSTANT_COLOR" ));
+ break;
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ DPF(( 0, "\tDST Blend\tGL_ONE_MINUS_CONSTANT_COLOR" ));
+ break;
+ case GL_CONSTANT_ALPHA:
+ DPF(( 0, "\tDST Blend\tGL_CONSTANT_ALPHA" ));
+ break;
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ DPF(( 0, "\tDST Blend\tGL_ONE_MINUS_CONSTANT_ALPHA" ));
+ break;
+ }
+ }
+}
+
diff --git a/src/mesa/drivers/d3d/DDrawPROCS.c b/src/mesa/drivers/d3d/DDrawPROCS.c
new file mode 100644
index 0000000000..33a1e47bba
--- /dev/null
+++ b/src/mesa/drivers/d3d/DDrawPROCS.c
@@ -0,0 +1,400 @@
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#include "D3DMesa.h"
+/*===========================================================================*/
+/* This call will clear the render surface using the pixel info built from */
+/* the surface at creation time. The call uses Lock/Unlock to access the */
+/* surface. The call also special cases a full clear or a dirty rectangle. */
+/* Finally the call returns the new clear mask that reflects that the color */
+/* buffer was cleared. */
+/*===========================================================================*/
+/* RETURN: the original mask with the bits cleared that represents the buffer*/
+/* or buffers we just cleared. */
+/*===========================================================================*/
+GLbitfield ClearBuffers( GLcontext *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ DDSURFACEDESC2 *pddsd2;
+ UCHAR *pBuffer,
+ *pScanLine;
+ int index,
+ index2;
+ DWORD dwColor;
+
+ if ( mask & GL_COLOR_BUFFER_BIT )
+ {
+ /* Lock the surface to get the surface pointer. */
+ pddsd2 = LockHAL( pContext->pShared, TRUE );
+
+ /* Solve the color once only. */
+ dwColor = ( ((DWORD)((float)pContext->rClear * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
+ dwColor |= ( ((DWORD)((float)pContext->gClear * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
+ dwColor |= ( ((DWORD)((float)pContext->bClear * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
+
+ if ( all )
+ {
+ for( index = 0, pScanLine = (UCHAR *)pddsd2->lpSurface; index < pContext->pShared->dwHeight; index++, pScanLine += pddsd2->lPitch )
+ for( pBuffer = pScanLine, index2 = 0; index2 < pContext->pShared->dwWidth; index2++, pBuffer += pContext->pShared->pixel.cb )
+ memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
+ }
+ else
+ {
+ pScanLine = ((UCHAR *)pddsd2->lpSurface) +
+ ( (FLIP( pContext->pShared->dwHeight, (y+height)) * pddsd2->lPitch) + (x * pContext->pShared->pixel.cb) );
+
+ for( index = 0; index < height; index++, pScanLine += pddsd2->lPitch )
+ {
+ for( index2 = 0, pBuffer = pScanLine; index2 < width; index2++, pBuffer += pContext->pShared->pixel.cb )
+ memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
+ }
+ }
+
+ UnlockHAL( pContext->pShared, TRUE );
+ }
+
+ return (mask & ~GL_COLOR_BUFFER_BIT);
+}
+/*===========================================================================*/
+/* This proc (as all others) has been written for the general case. I use */
+/* the PIXELINFO structure to pack the pixel from RGB24 to whatever the Off- */
+/* Screen render surface uses. The alpha is ignored as Mesa does it in SW. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void WSpanRGB( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte rgb[][3], const GLubyte mask[] )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ DDSURFACEDESC2 *pddsd2;
+ UCHAR *pBuffer;
+ int index;
+ DWORD dwColor;
+
+ /* Get the surface pointer and the pitch. */
+ pddsd2 = LockHAL( pContext->pShared, TRUE );
+
+ /* Find the start of the span. Invert y for Windows. */
+ pBuffer = (UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y) * pddsd2->lPitch) + (x*pContext->pShared->pixel.cb);
+
+ if ( mask )
+ {
+ for( index = 0; index < n; index++, pBuffer += pContext->pShared->pixel.cb )
+ {
+ if ( mask[index] )
+ {
+ /* Pack the color components. */
+ dwColor = ( ((DWORD)((float)rgb[index][RCOMP] * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
+ dwColor |= ( ((DWORD)((float)rgb[index][GCOMP] * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
+ dwColor |= ( ((DWORD)((float)rgb[index][BCOMP] * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
+ memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
+ }
+ }
+ }
+ else
+ {
+ for( index = 0; index < n; index++, pBuffer += pContext->pShared->pixel.cb )
+ {
+ /* Pack the color components. */
+ dwColor = ( ((DWORD)((float)rgb[index][RCOMP] * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
+ dwColor |= ( ((DWORD)((float)rgb[index][GCOMP] * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
+ dwColor |= ( ((DWORD)((float)rgb[index][BCOMP] * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
+ memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
+ }
+ }
+
+ /* Giver back. */
+ UnlockHAL( pContext->pShared, TRUE );
+}
+/*===========================================================================*/
+/* This proc (as all others) has been written for the general case. I use */
+/* the PIXELINFO structure to pack the pixel from RGB24 to whatever the Off- */
+/* Screen render surface uses. The alpha is ignored as Mesa does it in SW. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void WSpanRGBA( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte rgba[][4], const GLubyte mask[] )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ DDSURFACEDESC2 *pddsd2;
+ UCHAR *pBuffer;
+ int index;
+ DWORD dwColor;
+
+ /* Get the surface pointer and the pitch. */
+ pddsd2 = LockHAL( pContext->pShared, TRUE );
+
+ /* Find the start of the span. Invert y for Windows. */
+ pBuffer = (UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y) * pddsd2->lPitch) + (x*pContext->pShared->pixel.cb);
+
+ if ( mask )
+ {
+ for( index = 0; index < n; index++, pBuffer += pContext->pShared->pixel.cb )
+ {
+ if ( mask[index] )
+ {
+ /* Pack the color components. */
+ dwColor = ( ((DWORD)((float)rgba[index][RCOMP] * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
+ dwColor |= ( ((DWORD)((float)rgba[index][GCOMP] * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
+ dwColor |= ( ((DWORD)((float)rgba[index][BCOMP] * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
+ memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
+ }
+ }
+ }
+ else
+ {
+ for( index = 0; index < n; index++, pBuffer += pContext->pShared->pixel.cb )
+ {
+ /* Pack the color components. */
+ dwColor = ( ((DWORD)((float)rgba[index][RCOMP] * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
+ dwColor |= ( ((DWORD)((float)rgba[index][GCOMP] * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
+ dwColor |= ( ((DWORD)((float)rgba[index][BCOMP] * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
+ memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
+ }
+ }
+
+ /* Giver back. */
+ UnlockHAL( pContext->pShared, TRUE );
+}
+/*===========================================================================*/
+/* This proc (as all others) has been written for the general case. I use */
+/* the PIXELINFO structure to pack the pixel from RGB24 to whatever the Off- */
+/* Screen render surface uses. The color is solved once from the current */
+/* color components. The alpha is ignored as Mesa is doing it in SW. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void WSpanRGBAMono( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte mask[] )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ DDSURFACEDESC2 *pddsd2;
+ UCHAR *pBuffer;
+ int index;
+ DWORD dwColor;
+
+ /* Lock the surface to get the surface pointer and the pitch. */
+ pddsd2 = LockHAL( pContext->pShared, TRUE );
+
+ /* Solve the color once only. (no alpha) */
+ dwColor = ( ((DWORD)((float)pContext->rCurrent * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
+ dwColor |= ( ((DWORD)((float)pContext->gCurrent * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
+ dwColor |= ( ((DWORD)((float)pContext->bCurrent * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
+
+ /* Find the start of the span. Invert y for Windows. */
+ pBuffer = (UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y) * pddsd2->lPitch) + (x*pContext->pShared->pixel.cb);
+
+ if ( mask )
+ {
+ for( index = 0; index < n; index++, pBuffer += pContext->pShared->pixel.cb )
+ if ( mask[index] )
+ memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
+ }
+ else
+ {
+ for( index = 0; index < n; index++, pBuffer += pContext->pShared->pixel.cb )
+ memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
+ }
+
+ /* Giver back. */
+ UnlockHAL( pContext->pShared, TRUE );
+}
+/*===========================================================================*/
+/* This proc (as all others) has been written for the general case. I use */
+/* the PIXELINFO structure to pack the pixel from RGB24 to whatever the Off- */
+/* Screen render surface uses. The alpha is ignored as Mesa does it in SW. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void WPixelsRGBA( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte rgba[][4], const GLubyte mask[] )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ DDSURFACEDESC2 *pddsd2;
+ UCHAR *pBuffer;
+ int index;
+ DWORD dwColor;
+
+ /* Get the surface pointer and the pitch. */
+ pddsd2 = LockHAL( pContext->pShared, TRUE );
+
+ if ( mask )
+ {
+ for( index = 0; index < n; index++ )
+ {
+ if ( mask[index] )
+ {
+ /* Pack the color components. */
+ dwColor = ( ((DWORD)((float)rgba[index][RCOMP] * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
+ dwColor |= ( ((DWORD)((float)rgba[index][GCOMP] * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
+ dwColor |= ( ((DWORD)((float)rgba[index][BCOMP] * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
+
+ /* Find the pixel. Invert y for Windows. */
+ pBuffer = (UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y[index]) * pddsd2->lPitch) + (x[index]*pContext->pShared->pixel.cb);
+ memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
+ }
+ }
+ }
+ else
+ {
+ for( index = 0; index < n; index++ )
+ {
+ /* Pack the color components. */
+ dwColor = ( ((DWORD)((float)rgba[index][RCOMP] * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
+ dwColor |= ( ((DWORD)((float)rgba[index][GCOMP] * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
+ dwColor |= ( ((DWORD)((float)rgba[index][BCOMP] * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
+
+ /* Find the pixel. Invert y for Windows. */
+ pBuffer = (UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y[index]) * pddsd2->lPitch) + (x[index]*pContext->pShared->pixel.cb);
+ memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
+ }
+ }
+
+ /* Giver back. */
+ UnlockHAL( pContext->pShared, TRUE );
+}
+/*===========================================================================*/
+/* This proc (as all others) has been written for the general case. I use */
+/* the PIXELINFO structure to pack the pixel from RGB24 to whatever the Off- */
+/* Screen render surface uses. The color is solved once from the current */
+/* color components. The alpha is ignored as Mesa is doing it in SW. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void WPixelsRGBAMono( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte mask[] )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ DDSURFACEDESC2 *pddsd2;
+ UCHAR *pBuffer;
+ int index;
+ DWORD dwColor;
+
+ /* Get the surface pointer and the pitch. */
+ pddsd2 = LockHAL( pContext->pShared, TRUE );
+
+ /* Solve the color once only. I don't uses the alpha. */
+ dwColor = ( ((DWORD)((float)pContext->rCurrent * pContext->pShared->pixel.rScale)) << pContext->pShared->pixel.rShift );
+ dwColor |= ( ((DWORD)((float)pContext->gCurrent * pContext->pShared->pixel.gScale)) << pContext->pShared->pixel.gShift );
+ dwColor |= ( ((DWORD)((float)pContext->bCurrent * pContext->pShared->pixel.bScale)) << pContext->pShared->pixel.bShift );
+
+ if ( mask )
+ {
+ /* We store the surface pointer as a UCHAR so that pixel.cb (count in btyles) will work for all. */
+ for( index = 0; index < n; index++ )
+ {
+ if ( mask[index] )
+ {
+ /* Find the pixel. Invert y for Windows. */
+ pBuffer = (UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y[index]) * pddsd2->lPitch) + (x[index]*pContext->pShared->pixel.cb);
+ memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
+ }
+ }
+ }
+ else
+ {
+ /* We store the surface pointer as a UCHAR so that pixel.cb (count in btyles) will work for all. */
+ for( index = 0; index < n; index++ )
+ {
+ /* Find the pixel. Invert y for Windows. */
+ pBuffer = (UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y[index]) * pddsd2->lPitch) + (x[index]*pContext->pShared->pixel.cb);
+ memcpy( pBuffer, &dwColor, pContext->pShared->pixel.cb );
+ }
+ }
+
+ /* Giver back. */
+ UnlockHAL( pContext->pShared, TRUE );
+}
+/*===========================================================================*/
+/* This proc isn't written for speed rather its to handle the general case. */
+/* I grab each pixel from the surface and unpack the info using the PIXELINFO*/
+/* structure that was generated from the OffScreen surface pixelformat. The */
+/* function will not fill in the alpha value as Mesa I have Mesa allocate its*/
+/* own alpha channel when the context was created. I did this as I didn't */
+/* feel that it was worth the effort to try and get HW to work (bus bound). */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void RSpanRGBA( const GLcontext* ctx, GLuint n, GLint x, GLint y, GLubyte rgba[][4] )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ DDSURFACEDESC2 *pddsd2;
+ UCHAR *pBuffer;
+ int index;
+ DWORD *pdwColor;
+
+ /* Get the surface pointer and the pitch. */
+ pddsd2 = LockHAL( pContext->pShared, TRUE );
+
+ /* Find the start of the span. Invert y for Windows. */
+ pBuffer = (UCHAR *)pddsd2->lpSurface +
+ (FLIP(pContext->pShared->dwHeight,y) * pddsd2->lPitch) +
+ (x*pContext->pShared->pixel.cb);
+
+ /* We store the surface pointer as a UCHAR so that pixel.cb (count in btyles) will work for all. */
+ for( index = 0; index < n; index++, pBuffer += pContext->pShared->pixel.cb )
+ {
+ pdwColor = (DWORD *)pBuffer;
+ rgba[index][RCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwRMask) >> pContext->pShared->pixel.rShift) / pContext->pShared->pixel.rScale);
+ rgba[index][GCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwGMask) >> pContext->pShared->pixel.gShift) / pContext->pShared->pixel.gScale);
+ rgba[index][BCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwBMask) >> pContext->pShared->pixel.bShift) / pContext->pShared->pixel.bScale);
+ }
+
+ /* Giver back. */
+ UnlockHAL( pContext->pShared, TRUE );
+}
+/*===========================================================================*/
+/* This proc isn't written for speed rather its to handle the general case. */
+/* I grab each pixel from the surface and unpack the info using the PIXELINFO*/
+/* structure that was generated from the OffScreen surface pixelformat. The */
+/* function will not fill in the alpha value as Mesa I have Mesa allocate its*/
+/* own alpha channel when the context was created. I did this as I didn't */
+/* feel that it was worth the effort to try and get HW to work (bus bound). */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void RPixelsRGBA( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], GLubyte rgba[][4], const GLubyte mask[] )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ DDSURFACEDESC2 *pddsd2;
+ int index;
+ DWORD *pdwColor;
+
+ /* Get the surface pointer and the pitch. */
+ pddsd2 = LockHAL( pContext->pShared, TRUE );
+
+ if ( mask )
+ {
+ /* We store the surface pointer as a UCHAR so that pixel.cb (count in btyles) will work for all. */
+ for( index = 0; index < n; index++ )
+ {
+ if ( mask[index] )
+ {
+ /* Find the start of the pixel. Invert y for Windows. */
+ pdwColor = (DWORD *)((UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y[index]) * pddsd2->lPitch) + (x[index]*pContext->pShared->pixel.cb));
+ rgba[index][RCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwRMask) >> pContext->pShared->pixel.rShift) / pContext->pShared->pixel.rScale);
+ rgba[index][GCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwGMask) >> pContext->pShared->pixel.gShift) / pContext->pShared->pixel.gScale);
+ rgba[index][BCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwBMask) >> pContext->pShared->pixel.bShift) / pContext->pShared->pixel.bScale);
+ }
+ }
+ }
+ else
+ {
+ /* We store the surface pointer as a UCHAR so that pixel.cb (count in btyles) will work for all. */
+ for( index = 0; index < n; index++ )
+ {
+ /* Find the start of the pixel. Invert y for Windows. */
+ pdwColor = (DWORD *)((UCHAR *)pddsd2->lpSurface + (FLIP(pContext->pShared->dwHeight,y[index]) * pddsd2->lPitch) + (x[index]*pContext->pShared->pixel.cb));
+ rgba[index][RCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwRMask) >> pContext->pShared->pixel.rShift) / pContext->pShared->pixel.rScale);
+ rgba[index][GCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwGMask) >> pContext->pShared->pixel.gShift) / pContext->pShared->pixel.gScale);
+ rgba[index][BCOMP] = (GLubyte)((float)((*pdwColor & pContext->pShared->pixel.dwBMask) >> pContext->pShared->pixel.bShift) / pContext->pShared->pixel.bScale);
+ }
+ }
+
+ /* Giver back. */
+ UnlockHAL( pContext->pShared, TRUE );
+}
+ \ No newline at end of file
diff --git a/src/mesa/drivers/d3d/DEBUG.C b/src/mesa/drivers/d3d/DEBUG.C
new file mode 100644
index 0000000000..26c2c25be7
--- /dev/null
+++ b/src/mesa/drivers/d3d/DEBUG.C
@@ -0,0 +1,144 @@
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#include "Debug.h"
+/*===========================================================================*/
+/* Global variables. */
+/*===========================================================================*/
+DWORD g_DBGMask = DBG_ALL_ERROR;
+/*===========================================================================*/
+/* This is your basic DPF function with printf like support. The function */
+/* also works with a global debug mask variable. I have written support that*/
+/* allows for the user's enviroment variable space to be read and set the */
+/* masks. This is done when the dll starts and is only in the debug version.*/
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void _cdecl DebugPrint( int mask, char *pszFormat, ... )
+{
+ char buffer[512];
+ va_list args;
+
+ /* A mask of 0 will always pass. Easy to remeber. */
+ if ( (mask == 0) || (mask & g_DBGMask) )
+ {
+ va_start( args, pszFormat );
+
+ if ( mask & DBG_ALL_ERROR )
+ OutputDebugString( "MesaD3D: (ERROR)" );
+ else
+ OutputDebugString( "MesaD3D: " );
+
+ vsprintf( buffer, pszFormat, args );
+ strcat( buffer, "\n" );
+ OutputDebugString( buffer );
+
+ va_end( args );
+ }
+}
+/*===========================================================================*/
+/* This call reads the users enviroment variables and sets any debug mask */
+/* that they have set to TRUE. Now the value must be "TRUE". */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void ReadDBGEnv( void )
+{
+ g_DBGMask = DBG_ALL_ERROR;
+
+#define IS_VAR_SET(v) if ( getenv( # v ) && !strcmp(getenv( # v ),"TRUE") ) g_DBGMask |= v;
+
+ IS_VAR_SET( DBG_FUNC );
+ IS_VAR_SET( DBG_STATES );
+
+ IS_VAR_SET( DBG_CNTX_INFO );
+ IS_VAR_SET( DBG_CNTX_WARN );
+ IS_VAR_SET( DBG_CNTX_PROFILE );
+ IS_VAR_SET( DBG_CNTX_ERROR );
+ IS_VAR_SET( DBG_CNTX_ALL );
+
+ IS_VAR_SET( DBG_PRIM_INFO );
+ IS_VAR_SET( DBG_PRIM_WARN );
+ IS_VAR_SET( DBG_PRIM_PROFILE );
+ IS_VAR_SET( DBG_PRIM_ERROR );
+ IS_VAR_SET( DBG_PRIM_ALL );
+
+ IS_VAR_SET( DBG_TXT_INFO );
+ IS_VAR_SET( DBG_TXT_WARN );
+ IS_VAR_SET( DBG_TXT_PROFILE );
+ IS_VAR_SET( DBG_TXT_ERROR );
+ IS_VAR_SET( DBG_TXT_ALL );
+
+ IS_VAR_SET( DBG_ALL_INFO );
+ IS_VAR_SET( DBG_ALL_WARN );
+ IS_VAR_SET( DBG_ALL_PROFILE );
+ IS_VAR_SET( DBG_ALL_ERROR );
+ IS_VAR_SET( DBG_ALL );
+
+#undef IS_VAR_SET
+}
+/*===========================================================================*/
+/* This function will take a pointer to a DDSURFACEDESC2 structure & display*/
+/* the parsed information using a DPF call. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void DebugPixelFormat( char *pszSurfaceName, DDPIXELFORMAT *pddpf )
+{
+ char buffer[256];
+
+ /* Parse the flag type and write the string equivalent. */
+ if ( pddpf->dwFlags & DDPF_ALPHA )
+ strcat( buffer, "DDPF_ALPHA " );
+ if ( pddpf->dwFlags & DDPF_ALPHAPIXELS )
+ strcat( buffer, "DDPF_ALPHAPIXELS " );
+ if ( pddpf->dwFlags & DDPF_ALPHAPREMULT )
+ strcat( buffer, "DDPF_ALPHAPREMULT " );
+ if ( pddpf->dwFlags & DDPF_BUMPLUMINANCE )
+ strcat( buffer, "DDPF_BUMPLUMINANCE " );
+ if ( pddpf->dwFlags & DDPF_BUMPDUDV )
+ strcat( buffer, "DDPF_BUMPDUDV " );
+ if ( pddpf->dwFlags & DDPF_COMPRESSED )
+ strcat( buffer, "DDPF_COMPRESSED " );
+ if ( pddpf->dwFlags & DDPF_FOURCC )
+ strcat( buffer, "DDPF_FOURCC " );
+ if ( pddpf->dwFlags & DDPF_LUMINANCE )
+ strcat( buffer, "DDPF_LUMINANCE " );
+ if ( pddpf->dwFlags & DDPF_PALETTEINDEXED1 )
+ strcat( buffer, "DDPF_PALETTEINDEXED1 " );
+ if ( pddpf->dwFlags & DDPF_PALETTEINDEXED2 )
+ strcat( buffer, "DDPF_PALETTEINDEXED2 " );
+ if ( pddpf->dwFlags & DDPF_PALETTEINDEXED4 )
+ strcat( buffer, "DDPF_PALETTEINDEXED4 " );
+ if ( pddpf->dwFlags & DDPF_PALETTEINDEXED8 )
+ strcat( buffer, "DDPF_PALETTEINDEXED8 " );
+ if ( pddpf->dwFlags & DDPF_PALETTEINDEXEDTO8 )
+ strcat( buffer, "DDPF_PALETTEINDEXEDTO8 " );
+ if ( pddpf->dwFlags & DDPF_RGB )
+ strcat( buffer, "DDPF_RGB " );
+ if ( pddpf->dwFlags & DDPF_RGBTOYUV )
+ strcat( buffer, "DDPF_RGBTOYUV " );
+ if ( pddpf->dwFlags & DDPF_STENCILBUFFER )
+ strcat( buffer, "DDPF_STENCILBUFFER " );
+ if ( pddpf->dwFlags & DDPF_YUV )
+ strcat( buffer, "DDPF_YUV " );
+ if ( pddpf->dwFlags & DDPF_ZBUFFER )
+ strcat( buffer, "DDPF_ZBUFFER " );
+ if ( pddpf->dwFlags & DDPF_ZPIXELS )
+ strcat( buffer, "DDPF_ZPIXELS " );
+
+ DPF(( (DBG_TXT_INFO|DBG_CNTX_INFO),"%s", buffer ));
+}
+
+
+
+
+
+ \ No newline at end of file
diff --git a/src/mesa/drivers/d3d/DEBUG.H b/src/mesa/drivers/d3d/DEBUG.H
new file mode 100644
index 0000000000..e63d6c500c
--- /dev/null
+++ b/src/mesa/drivers/d3d/DEBUG.H
@@ -0,0 +1,91 @@
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#ifndef _DEBUG_H
+#define _DEBUG_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================*/
+/* Includes. */
+/*===========================================================================*/
+#include <stdio.h>
+#include <string.h>
+#include <ddraw.h>
+#include <d3d.h>
+#include "D3DShared.h"
+/*===========================================================================*/
+/* Magic numbers. */
+/*===========================================================================*/
+/*===========================================================================*/
+/* Macros defines. */
+/*===========================================================================*/
+#define DBG_FUNC 0x00000001
+#define DBG_STATES 0x00000002
+
+#define DBG_CNTX_INFO 0x00000010
+#define DBG_CNTX_WARN 0x00000020
+#define DBG_CNTX_PROFILE 0x00000040
+#define DBG_CNTX_ERROR 0x00000080
+#define DBG_CNTX_ALL 0x000000F0
+
+#define DBG_PRIM_INFO 0x00000100
+#define DBG_PRIM_WARN 0x00000200
+#define DBG_PRIM_PROFILE 0x00000400
+#define DBG_PRIM_ERROR 0x00000800
+#define DBG_PRIM_ALL 0x00000F00
+
+#define DBG_TXT_INFO 0x00001000
+#define DBG_TXT_WARN 0x00002000
+#define DBG_TXT_PROFILE 0x00004000
+#define DBG_TXT_ERROR 0x00008000
+#define DBG_TXT_ALL 0x0000F000
+
+#define DBG_ALL_INFO 0x11111110
+#define DBG_ALL_WARN 0x22222220
+#define DBG_ALL_PROFILE 0x44444440
+#define DBG_ALL_ERROR 0x88888880
+#define DBG_ALL 0xFFFFFFFF
+
+#ifdef D3D_DEBUG
+# define DPF(arg) DebugPrint arg
+# define RIP(pH,msg,err) OutputDebugString(msg); \
+ OutputDebugString(err); \
+ OutputDebugString("\n"); \
+ FatalShutDown(pH)
+#else
+# define DPF(arg)
+# define RIP(pH,msg,err) FatalShutDown(pH)
+#endif
+/*===========================================================================*/
+/* Type defines. */
+/*===========================================================================*/
+/*===========================================================================*/
+/* Function prototypes. */
+/*===========================================================================*/
+extern void ReadDBGEnv( void );
+extern void _cdecl DebugPrint( int mask, char *pszFormat, ... );
+extern void DebugPixelFormat( char *pszSurfaceName, DDPIXELFORMAT *pddpf );
+/*===========================================================================*/
+/* Global variables. */
+/*===========================================================================*/
+extern DWORD g_DBGMask;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
+ \ No newline at end of file
diff --git a/src/mesa/drivers/d3d/DbgEnv.bat b/src/mesa/drivers/d3d/DbgEnv.bat
new file mode 100644
index 0000000000..40858e6684
--- /dev/null
+++ b/src/mesa/drivers/d3d/DbgEnv.bat
@@ -0,0 +1,25 @@
+SET DBG_FUNC=FALSE
+
+SET DBG_CNTX_INFO=TRUE
+SET DBG_CNTX_WARN=TRUE
+SET DBG_CNTX_PROFILE=FALSE
+SET DBG_CNTX_ERROR=TRUE
+SET DBG_CNTX_ALL=TRUE
+
+SET DBG_PRIM_INFO=FALSE
+SET DBG_PRIM_WARN=FALSE
+SET DBG_PRIM_PROFILE=FALSE
+SET DBG_PRIM_ERROR=TRUE
+SET DBG_PRIM_ALL=FALSE
+
+SET DBG_TXT_INFO=FALSE
+SET DBG_TXT_WARN=TRUE
+SET DBG_TXT_PROFILE=FALSE
+SET DBG_TXT_ERROR=TRUE
+SET DBG_TXT_ALL=FALSE
+
+SET DBG_ALL_INFO=FALSE
+SET DBG_ALL_WARN=TRUE
+SET DBG_ALL_PROFILE=FALSE
+SET DBG_ALL_ERROR=TRUE
+SET DBG_ALL=FALSE
diff --git a/src/mesa/drivers/d3d/MAKEFILE b/src/mesa/drivers/d3d/MAKEFILE
new file mode 100644
index 0000000000..59734cfd32
--- /dev/null
+++ b/src/mesa/drivers/d3d/MAKEFILE
@@ -0,0 +1,102 @@
+##############################################################################
+#
+# Mesa-3.0 Makefile for DirectX 6 Driver
+#
+# By Leigh McRae
+#
+# http://www.altsoftware.com/
+#
+# Copyright (c) 1999-1998 alt.software inc. All Rights Reserved
+##############################################################################
+NAME=
+TARGET= WGL Driver (D3DHAL)
+
+D3D_DIR=$(MAKEDIR)\D3D
+TARGET_DIR=e:\WinNT\System32
+TEMP_DIR=c:\Temp
+
+SPACE=-
+LINKER=link.exe
+
+INCLUDE=$(SDKROOT)\include;$(INCLUDE)
+LIB=$(SDKROOT)\lib;$(LIB)
+##############################################################################
+CFLAGS = /c /nologo /W1 /G5 /I..\ /I..\..\Include \
+ /D "_WIN32" /D "WIN32" /D "_WINDOWS" /D "__WIN32__" /D "__MSC__" /D "MESAD3D"
+CPPFLAGS= /c /nologo /W1 /G5 /I..\ /I..\..\Include \
+ /D "_WIN32" /D "WIN32" /D "_WINDOWS" /D "__WIN32__" /D "__MSC__" /D "MESAD3D"
+
+!IF "$(DEBUG)" == "1"
+
+CFLAGS = /MTd /Od /Z7 /Yd /D "_DEBUG" /D "D3D_DEBUG" $(CFLAGS)
+CPPFLAGS = /MTd /Od /Z7 /Yd /D "_DEBUG" /D "D3D_DEBUG" $(CPPFLAGS)
+BUILD_TYPE=debug
+
+!ELSE
+
+CFLAGS = /MT /Ox /D "NDEBUG" $(CFLAGS)
+CPPFLAGS = /MT /Ox /D "NDEBUG" $(CPPFLAGS)
+BUILD_TYPE=release
+
+!ENDIF
+##############################################################################
+SRCS_WGL = wgl.c D3Dvbrender.c DDrawPROCS.c NULLProcs.c Debug.c
+SRCS_HAL = D3DInit.cpp D3DRaster.cpp D3DTextureMgr.cpp D3DUtils.cpp D3DCaps.cpp
+OBJS_WGL = $(SRCS_WGL:.c=.obj)
+OBJS_HAL = $(SRCS_HAL:.cpp=.obj)
+
+WINLIBS = kernel32.lib user32.lib gdi32.lib oldnames.lib
+DXLIBS =
+LIBS = $(WINLIBS) $(DXLIBS)
+###############################################################################
+# Primary Targets #
+###############################################################################
+
+default: header WGL HAL footer
+
+all: default
+
+WGL : $(OBJS_WGL)
+
+HAL : $(OBJS_HAL)
+
+install : forceit
+ @echo $(SPACE)
+ @echo ========================================
+ @echo Install files created.
+ @echo ========================================
+
+
+###############################################################################
+# Secondary Targets #
+###############################################################################
+
+clean:
+ @echo ========================================
+ @echo Cleaning $(TARGET)
+ @del *.obj
+ @del *.dep
+ @del *.exp
+ @del *.ncb
+ @del *.plg
+ @del *.lib
+ @echo ========================================
+
+header:
+ @echo ============================================================
+ @echo Building $(TARGET) ($(BUILD_TYPE) version)
+ @echo ============================================================
+ @echo $(SPACE)
+
+footer:
+ @echo $(SPACE)
+ @echo ============================================================
+ @echo DONE building $(TARGET) ($(BUILD_TYPE) version)
+ @echo ============================================================
+
+forceit:
+
+
+
+
+ \ No newline at end of file
diff --git a/src/mesa/drivers/d3d/NULLProcs.h b/src/mesa/drivers/d3d/NULLProcs.h
new file mode 100644
index 0000000000..f0bbd2162d
--- /dev/null
+++ b/src/mesa/drivers/d3d/NULLProcs.h
@@ -0,0 +1,49 @@
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#ifndef NULL_MESA_PROCS_INC
+#define NULL_MESA_PROCS_INC
+/*===========================================================================*/
+/* Includes. */
+/*===========================================================================*/
+#include "matrix.h"
+#include "context.h"
+#include "types.h"
+#include "vb.h"
+/*===========================================================================*/
+/* Macros. */
+/*===========================================================================*/
+/*===========================================================================*/
+/* Magic numbers. */
+/*===========================================================================*/
+/*===========================================================================*/
+/* Type defines. */
+/*===========================================================================*/
+void NULLSetColor( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a );
+void NULLClearColor( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a );
+GLboolean NULLSetBuffer( GLcontext *ctx, GLenum mode );
+void NULLGetBufferSize( GLcontext *ctx, GLuint *width, GLuint *height );
+GLbitfield NULLClearBuffers( GLcontext *ctx, GLbitfield m, GLboolean a, GLint x, GLint y, GLint w, GLint h );
+void NULLWrSpRGB( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte r[][3], const GLubyte m[] );
+void NULLWrSpRGBA( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte r[][4], const GLubyte m[] );
+void NULLWrSpRGBAMono( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte m[] );
+void NULLWrPiRGBA( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte r[][4], const GLubyte m[] );
+void NULLWrPiRGBAMono( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte m[] );
+void NULLReSpRGBA( const GLcontext* ctx, GLuint n, GLint x, GLint y, GLubyte r[][4] );
+void NULLRePiRGBA( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], GLubyte r[][4], const GLubyte m[] );
+/*===========================================================================*/
+/* Extern function prototypes. */
+/*===========================================================================*/
+/*===========================================================================*/
+/* Global variables. */
+/*===========================================================================*/
+
+#endif
+
diff --git a/src/mesa/drivers/d3d/NullProcs.c b/src/mesa/drivers/d3d/NullProcs.c
new file mode 100644
index 0000000000..e8f18545d1
--- /dev/null
+++ b/src/mesa/drivers/d3d/NullProcs.c
@@ -0,0 +1,130 @@
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 DirectX 6 Driver */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1999-1998 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#include "NULLProcs.h"
+/*===========================================================================*/
+/* */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void NULLSetColor( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+
+}
+/*===========================================================================*/
+/* */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void NULLClearColor( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+}
+/*===========================================================================*/
+/* */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+GLboolean NULLSetBuffer( GLcontext *ctx, GLenum mode )
+{
+ return TRUE;
+}
+/*===========================================================================*/
+/* */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void NULLGetBufferSize( GLcontext *ctx, GLuint *width, GLuint *height )
+{
+ *width = 1;
+ *height = 1;
+}
+/*===========================================================================*/
+/* */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+GLbitfield NULLClearBuffers( GLcontext *ctx, GLbitfield m, GLboolean a, GLint x, GLint y, GLint w, GLint h )
+{
+ return m;
+}
+/*===========================================================================*/
+/* */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void NULLWrSpRGB( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte r[][3], const GLubyte m[] )
+{
+
+}
+/*===========================================================================*/
+/* */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void NULLWrSpRGBA( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte r[][4], const GLubyte m[] )
+{
+
+}
+/*===========================================================================*/
+/* */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void NULLWrSpRGBAMono( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte m[] )
+{
+
+}
+/*===========================================================================*/
+/* */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void NULLWrPiRGBA( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte r[][4], const GLubyte m[] )
+{
+
+}
+/*===========================================================================*/
+/* */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void NULLWrPiRGBAMono( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte m[] )
+{
+
+}
+/*===========================================================================*/
+/* */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void NULLReSpRGBA( const GLcontext* ctx, GLuint n, GLint x, GLint y, GLubyte r[][4] )
+{
+
+}
+/*===========================================================================*/
+/* */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+void NULLRePiRGBA( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], GLubyte r[][4], const GLubyte m[] )
+{
+
+}
+
+
+
+
+
+
+
+
+
+
+ \ No newline at end of file
diff --git a/src/mesa/drivers/d3d/OPENGL32.DEF b/src/mesa/drivers/d3d/OPENGL32.DEF
new file mode 100644
index 0000000000..19762bbebe
--- /dev/null
+++ b/src/mesa/drivers/d3d/OPENGL32.DEF
@@ -0,0 +1,443 @@
+;===========================================================================
+;
+; Mesa-3.0 DirectX 6 Driver
+;
+; By Leigh McRae
+;
+; http://www.altsoftware.com/
+;
+; Copyright (c) 1999-1998 alt.software inc. All Rights Reserved
+;===========================================================================
+NAME OpenGL32.DLL
+DESCRIPTION "Mesa-3.0 DX6 Driver Version 0.5"
+
+EXPORTS
+ DllMain
+ glAccum
+ glAlphaFunc
+ glAreTexturesResident
+ glAreTexturesResidentEXT
+ glArrayElement
+ glArrayElementEXT
+ glBegin
+ glBindTexture
+ glBindTextureEXT
+ glBitmap
+ glBlendColorEXT
+ glBlendEquationEXT
+ glBlendFunc
+ glCallList
+ glCallLists
+ glClear
+ glClearAccum
+ glClearColor
+ glClearDepth
+ glClearIndex
+ glClearStencil
+ glClipPlane
+ glColor3b
+ glColor3bv
+ glColor3d
+ glColor3dv
+ glColor3f
+ glColor3fv
+ glColor3i
+ glColor3iv
+ glColor3s
+ glColor3sv
+ glColor3ub
+ glColor3ubv
+ glColor3ui
+ glColor3uiv
+ glColor3us
+ glColor3usv
+ glColor4b
+ glColor4bv
+ glColor4d
+ glColor4dv
+ glColor4f
+ glColor4fv
+ glColor4i
+ glColor4iv
+ glColor4s
+ glColor4sv
+ glColor4ub
+ glColor4ubv
+ glColor4ui
+ glColor4uiv
+ glColor4us
+ glColor4usv
+ glColorMask
+ glColorMaterial
+ glColorPointer
+ glColorPointerEXT
+ glColorSubTableEXT
+ glColorTableEXT
+ glCopyPixels
+ glCopyTexImage1D
+ glCopyTexImage2D
+ glCopyTexSubImage1D
+ glCopyTexSubImage2D
+ glCopyTexSubImage3DEXT
+ glCullFace
+ glDeleteLists
+ glDeleteTextures
+ glDeleteTexturesEXT
+ glDepthFunc
+ glDepthMask
+ glDepthRange
+ glDisable
+ glDisableClientState
+ glDrawArrays
+ glDrawArraysEXT
+ glDrawBuffer
+ glDrawElements
+ glDrawPixels
+ glEdgeFlag
+ glEdgeFlagPointer
+ glEdgeFlagPointerEXT
+ glEdgeFlagv
+ glEnable
+ glEnableClientState
+ glEnd
+ glEndList
+ glEvalCoord1d
+ glEvalCoord1dv
+ glEvalCoord1f
+ glEvalCoord1fv
+ glEvalCoord2d
+ glEvalCoord2dv
+ glEvalCoord2f
+ glEvalCoord2fv
+ glEvalMesh1
+ glEvalMesh2
+ glEvalPoint1
+ glEvalPoint2
+ glFeedbackBuffer
+ glFinish
+ glFlush
+ glFogf
+ glFogfv
+ glFogi
+ glFogiv
+ glFrontFace
+ glFrustum
+ glGenLists
+ glGenTextures
+ glGenTexturesEXT
+ glGetBooleanv
+ glGetClipPlane
+ glGetColorTableEXT
+ glGetColorTableParameterfvEXT
+ glGetColorTableParameterivEXT
+ glGetDoublev
+ glGetError
+ glGetFloatv
+ glGetIntegerv
+ glGetLightfv
+ glGetLightiv
+ glGetMapdv
+ glGetMapfv
+ glGetMapiv
+ glGetMaterialfv
+ glGetMaterialiv
+ glGetPixelMapfv
+ glGetPixelMapuiv
+ glGetPixelMapusv
+ glGetPointerv
+ glGetPointervEXT
+ glGetPolygonStipple
+ glGetString
+ glGetTexEnvfv
+ glGetTexEnviv
+ glGetTexGendv
+ glGetTexGenfv
+ glGetTexGeniv
+ glGetTexImage
+ glGetTexLevelParameterfv
+ glGetTexLevelParameteriv
+ glGetTexParameterfv
+ glGetTexParameteriv
+ glHint
+ glIndexd
+ glIndexdv
+ glIndexf
+ glIndexfv
+ glIndexi
+ glIndexiv
+ glIndexMask
+ glIndexPointer
+ glIndexPointerEXT
+ glIndexs
+ glIndexsv
+ glIndexub
+ glIndexubv
+ glInitNames
+ glInterleavedArrays
+ glIsEnabled
+ glIsList
+ glIsTexture
+ glIsTextureEXT
+ glLightf
+ glLightfv
+ glLighti
+ glLightiv
+ glLightModelf
+ glLightModelfv
+ glLightModeli
+ glLightModeliv
+ glLineStipple
+ glLineWidth
+ glListBase
+ glLoadIdentity
+ glLoadMatrixd
+ glLoadMatrixf
+ glLoadName
+ glLogicOp
+ glMap1d
+ glMap1f
+ glMap2d
+ glMap2f
+ glMapGrid1d
+ glMapGrid1f
+ glMapGrid2d
+ glMapGrid2f
+ glMaterialf
+ glMaterialfv
+ glMateriali
+ glMaterialiv
+ glMatrixMode
+ glMultMatrixd
+ glMultMatrixf
+ glNewList
+ glNormal3b
+ glNormal3bv
+ glNormal3d
+ glNormal3dv
+ glNormal3f
+ glNormal3fv
+ glNormal3i
+ glNormal3iv
+ glNormal3s
+ glNormal3sv
+ glNormalPointer
+ glNormalPointerEXT
+ glOrtho
+ glPassThrough
+ glPixelMapfv
+ glPixelMapuiv
+ glPixelMapusv
+ glPixelStoref
+ glPixelStorei
+ glPixelTransferf
+ glPixelTransferi
+ glPixelZoom
+ glPointParameterfEXT
+ glPointParameterfvEXT
+ glPointSize
+ glPolygonMode
+ glPolygonOffset
+ glPolygonOffsetEXT
+ glPolygonStipple
+ glPopAttrib
+ glPopClientAttrib
+ glPopMatrix
+ glPopName
+ glPrioritizeTextures
+ glPrioritizeTexturesEXT
+ glPushAttrib
+ glPushClientAttrib
+ glPushMatrix
+ glPushName
+ glRasterPos2d
+ glRasterPos2dv
+ glRasterPos2f
+ glRasterPos2fv
+ glRasterPos2i
+ glRasterPos2iv
+ glRasterPos2s
+ glRasterPos2sv
+ glRasterPos3d
+ glRasterPos3dv
+ glRasterPos3f
+ glRasterPos3fv
+ glRasterPos3i
+ glRasterPos3iv
+ glRasterPos3s
+ glRasterPos3sv
+ glRasterPos4d
+ glRasterPos4dv
+ glRasterPos4f
+ glRasterPos4fv
+ glRasterPos4i
+ glRasterPos4iv
+ glRasterPos4s
+ glRasterPos4sv
+ glReadBuffer
+ glReadPixels
+ glRectd
+ glRectdv
+ glRectf
+ glRectfv
+ glRecti
+ glRectiv
+ glRects
+ glRectsv
+ glRenderMode
+ glResizeBuffersMESA
+ glRotated
+ glRotatef
+ glScaled
+ glScalef
+ glScissor
+ glSelectBuffer
+ glShadeModel
+ glStencilFunc
+ glStencilMask
+ glStencilOp
+ glTexCoord1d
+ glTexCoord1dv
+ glTexCoord1f
+ glTexCoord1fv
+ glTexCoord1i
+ glTexCoord1iv
+ glTexCoord1s
+ glTexCoord1sv
+ glTexCoord2d
+ glTexCoord2dv
+ glTexCoord2f
+ glTexCoord2fv
+ glTexCoord2i
+ glTexCoord2iv
+ glTexCoord2s
+ glTexCoord2sv
+ glTexCoord3d
+ glTexCoord3dv
+ glTexCoord3f
+ glTexCoord3fv
+ glTexCoord3i
+ glTexCoord3iv
+ glTexCoord3s
+ glTexCoord3sv
+ glTexCoord4d
+ glTexCoord4dv
+ glTexCoord4f
+ glTexCoord4fv
+ glTexCoord4i
+ glTexCoord4iv
+ glTexCoord4s
+ glTexCoord4sv
+ glTexCoordPointer
+ glTexCoordPointerEXT
+ glTexEnvf
+ glTexEnvfv
+ glTexEnvi
+ glTexEnviv
+ glTexGend
+ glTexGendv
+ glTexGenf
+ glTexGenfv
+ glTexGeni
+ glTexGeniv
+ glTexImage1D
+ glTexImage2D
+ glTexImage3DEXT
+ glTexParameterf
+ glTexParameterfv
+ glTexParameteri
+ glTexParameteriv
+ glTexSubImage1D
+ glTexSubImage2D
+ glTexSubImage3DEXT
+ glTranslated
+ glTranslatef
+ glVertex2d
+ glVertex2dv
+ glVertex2f
+ glVertex2fv
+ glVertex2i
+ glVertex2iv
+ glVertex2s
+ glVertex2sv
+ glVertex3d
+ glVertex3dv
+ glVertex3f
+ glVertex3fv
+ glVertex3i
+ glVertex3iv
+ glVertex3s
+ glVertex3sv
+ glVertex4d
+ glVertex4dv
+ glVertex4f
+ glVertex4fv
+ glVertex4i
+ glVertex4iv
+ glVertex4s
+ glVertex4sv
+ glVertexPointer
+ glVertexPointerEXT
+ glViewport
+ glWindowPos2dMESA
+ glWindowPos2dvMESA
+ glWindowPos2fMESA
+ glWindowPos2fvMESA
+ glWindowPos2iMESA
+ glWindowPos2ivMESA
+ glWindowPos2sMESA
+ glWindowPos2svMESA
+ glWindowPos3dMESA
+ glWindowPos3dvMESA
+ glWindowPos3fMESA
+ glWindowPos3fvMESA
+ glWindowPos3iMESA
+ glWindowPos3ivMESA
+ glWindowPos3sMESA
+ glWindowPos3svMESA
+ glWindowPos4dMESA
+ glWindowPos4dvMESA
+ glWindowPos4fMESA
+ glWindowPos4fvMESA
+ glWindowPos4iMESA
+ glWindowPos4ivMESA
+ glWindowPos4sMESA
+ glWindowPos4svMESA
+; WMesaCreateContext
+; WMesaDestroyContext
+; WMesaMakeCurrent
+; WMesaPaletteChange
+; WMesaSwapBuffers
+; OSMesaCreateContext
+; OSMesaDestroyContext
+; OSMesaMakeCurrent
+; OSMesaGetCurrentContext
+; OSMesaPixelStore
+; OSMesaGetIntegerv
+; OSMesaGetDepthBuffer
+ wglCopyContext
+ wglCreateContext
+ wglCreateLayerContext
+ wglDeleteContext
+; wglDescribeLayerPlane
+ wglGetCurrentContext
+ wglGetCurrentDC
+; wglGetLayerPaletteEntries
+ wglGetProcAddress
+ wglMakeCurrent
+; wglRealizeLayerPalette
+; wglSetLayerPaletteEntries
+ wglShareLists
+ wglSwapLayerBuffers
+ wglUseFontBitmapsA
+ wglUseFontBitmapsW
+ wglUseFontOutlinesA
+ wglUseFontOutlinesW
+ wglChoosePixelFormat
+ wglDescribePixelFormat
+ wglGetPixelFormat
+ wglSetPixelFormat
+ wglSwapBuffers
+
+
+
+ \ No newline at end of file
diff --git a/src/mesa/drivers/d3d/WGL.C b/src/mesa/drivers/d3d/WGL.C
new file mode 100644
index 0000000000..2d1a6a0c4d
--- /dev/null
+++ b/src/mesa/drivers/d3d/WGL.C
@@ -0,0 +1,1262 @@
+/*===========================================================================*/
+/* */
+/* Mesa-3.0 Makefile for DirectX 6 */
+/* */
+/* By Leigh McRae */
+/* */
+/* http://www.altsoftware.com/ */
+/* */
+/* Copyright (c) 1998-1997 alt.software inc. All Rights Reserved */
+/*===========================================================================*/
+#include "D3DMesa.h"
+/*===========================================================================*/
+/* Window managment. */
+/*===========================================================================*/
+static BOOL InitOpenGL( HINSTANCE hInst );
+static BOOL TermOpenGL( HINSTANCE hInst );
+static BOOL ResizeContext( GLcontext *ctx );
+static BOOL MakeCurrent( D3DMESACONTEXT *pContext );
+static void DestroyContext( D3DMESACONTEXT *pContext );
+static BOOL UnBindWindow( D3DMESACONTEXT *pContext );
+LONG APIENTRY wglMonitorProc( HWND hwnd, UINT message, UINT wParam, LONG lParam );
+/*===========================================================================*/
+/* Mesa hooks. */
+/*===========================================================================*/
+static void SetupDDPointers( GLcontext *ctx );
+static void SetupSWDDPointers( GLcontext *ctx );
+static void SetupHWDDPointers( GLcontext *ctx );
+static void SetupNULLDDPointers( GLcontext *ctx );
+static const char *RendererString( void );
+
+/* State Management hooks. */
+static void SetColor( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a );
+static void ClearColor( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a );
+static GLboolean SetBuffer( GLcontext *ctx, GLenum buffer );
+
+/* Window Management hooks. */
+static void GetBufferSize( GLcontext *ctx, GLuint *width, GLuint *height );
+static void SetViewport( GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h );
+static void Flush( GLcontext *ctx );
+
+/* Span rendering hooks. */
+void WSpanRGB( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte rgb[][3], const GLubyte mask[] );
+void WSpanRGBA( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte rgba[][4], const GLubyte mask[] );
+void WSpanRGBAMono( const GLcontext* ctx, GLuint n, GLint x, GLint y, const GLubyte mask[] );
+void WPixelsRGBA( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte rgba[][4], const GLubyte mask[] );
+void WPixelsRGBAMono( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], const GLubyte mask[] );
+void RSpanRGBA( const GLcontext* ctx, GLuint n, GLint x, GLint y, GLubyte rgba[][4] );
+void RPixelsRGBA( const GLcontext* ctx, GLuint n, const GLint x[], const GLint y[], GLubyte rgba[][4], const GLubyte mask[] );
+GLbitfield ClearBuffers( GLcontext *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height );
+
+/* Primitve rendering hooks. */
+GLboolean RenderVertexBuffer( GLcontext *ctx, GLboolean allDone );
+void RenderOneTriangle( GLcontext *ctx, GLuint v1, GLuint v2, GLuint v3, GLuint pv );
+void RenderOneLine( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv );
+GLbitfield ClearBuffersD3D( GLcontext *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height );
+
+/* Texture Management hooks. */
+static void TextureBind( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj );
+static void TextureLoad( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj, GLint level, GLint internalFormat, const struct gl_texture_image *image );
+static void TextureSubImage( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLint internalFormat, const struct gl_texture_image *image );
+/*===========================================================================*/
+/* Global variables. */
+/*===========================================================================*/
+D3DMESACONTEXT *pD3DCurrent,
+ *pD3DDefault; /* Thin support context. */
+
+struct __extensions__ ext[] = {
+
+ { (PROC)glPolygonOffsetEXT, "glPolygonOffsetEXT" },
+ { (PROC)glBlendEquationEXT, "glBlendEquationEXT" },
+ { (PROC)glBlendColorEXT, "glBlendColorExt" },
+ { (PROC)glVertexPointerEXT, "glVertexPointerEXT" },
+ { (PROC)glNormalPointerEXT, "glNormalPointerEXT" },
+ { (PROC)glColorPointerEXT, "glColorPointerEXT" },
+ { (PROC)glIndexPointerEXT, "glIndexPointerEXT" },
+ { (PROC)glTexCoordPointerEXT, "glTexCoordPointer" },
+ { (PROC)glEdgeFlagPointerEXT, "glEdgeFlagPointerEXT" },
+ { (PROC)glGetPointervEXT, "glGetPointervEXT" },
+ { (PROC)glArrayElementEXT, "glArrayElementEXT" },
+ { (PROC)glDrawArraysEXT, "glDrawArrayEXT" },
+ { (PROC)glAreTexturesResidentEXT, "glAreTexturesResidentEXT" },
+ { (PROC)glBindTextureEXT, "glBindTextureEXT" },
+ { (PROC)glDeleteTexturesEXT, "glDeleteTexturesEXT" },
+ { (PROC)glGenTexturesEXT, "glGenTexturesEXT" },
+ { (PROC)glIsTextureEXT, "glIsTextureEXT" },
+ { (PROC)glPrioritizeTexturesEXT, "glPrioritizeTexturesEXT" },
+ { (PROC)glCopyTexSubImage3DEXT, "glCopyTexSubImage3DEXT" },
+ { (PROC)glTexImage3DEXT, "glTexImage3DEXT" },
+ { (PROC)glTexSubImage3DEXT, "glTexSubImage3DEXT" },
+};
+
+int qt_ext = sizeof(ext) / sizeof(ext[0]);
+float g_DepthScale,
+ g_MaxDepth;
+/*===========================================================================*/
+/* When a process loads this DLL we will setup the linked list for context */
+/* management and create a default context that will support the API until */
+/* the user creates and binds thier own. This THIN default context is useful*/
+/* to have around. */
+/* When the process terminates we will clean up all resources here. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+BOOL APIENTRY DllMain( HINSTANCE hInst, DWORD reason, LPVOID reserved )
+{
+ switch( reason )
+ {
+ case DLL_PROCESS_ATTACH:
+ return InitOpenGL( hInst );
+
+ case DLL_PROCESS_DETACH:
+ return TermOpenGL( hInst );
+ }
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* The first thing we do when this dll is hit is connect to the dll that has*/
+/* handles all the DirectX 6 rendering. I decided to use another dll as DX6 */
+/* is all C++ and Mesa-3.0 is C (thats a good thing). This way I can write */
+/* the DX6 in C++ and Mesa-3.0 in C without having to worry about linkage. */
+/* I feel this is easy and better then using static wrappers as it is likely */
+/* faster and it allows me to just develope the one without compiling the */
+/* other. */
+/* NOTE that at this point we don't have much other than a very thin context*/
+/* that will support the API calls only to the point of not causing the app */
+/* to crash from the API table being empty. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+static BOOL InitOpenGL( HINSTANCE hInst )
+{
+ /* Allocate and clear the default context. */
+ pD3DDefault = (PD3DMESACONTEXT)ALLOC( sizeof(D3DMESACONTEXT) );
+ if ( pD3DDefault == NULL )
+ return FALSE;
+ memset( pD3DDefault, 0, sizeof(D3DMESACONTEXT) );
+
+ /* Clear the D3D vertex buffer so that values not used will be zero. This */
+ /* save me from some redundant work. */
+ memset( &D3DTLVertices, 0, sizeof(D3DTLVertices) );
+
+ /* Update the link. We uses a circular list so that it is easy to */
+ /* add and search. This context will also be used for head and tail.*/
+ pD3DDefault->next = pD3DDefault;
+
+ /*========================================================================*/
+ /* Do all core Mesa stuff. */
+ /*========================================================================*/
+ pD3DDefault->gl_visual = gl_create_visual( TRUE,
+ GL_FALSE, /* software alpha */
+ FALSE, /* db_flag */
+ GL_FALSE, /* stereo */
+ 16, /* depth_bits */
+ 8, /* stencil_bits */
+ 8, /* accum_bits */
+ 0, /* index bits */
+ 8,8,8,8 ); /* r, g, b, a bits */
+
+ if ( pD3DDefault->gl_visual == NULL)
+ {
+ FREE( pD3DDefault );
+ return FALSE;
+ }
+
+ /* Allocate a new Mesa context */
+ pD3DDefault->gl_ctx = gl_create_context( pD3DDefault->gl_visual, NULL, pD3DDefault, GL_TRUE );
+ if ( pD3DDefault->gl_ctx == NULL )
+ {
+ gl_destroy_visual( pD3DDefault->gl_visual );
+ FREE( pD3DDefault );
+ return FALSE;
+ }
+
+ /* Allocate a new Mesa frame buffer */
+ pD3DDefault->gl_buffer = gl_create_framebuffer( pD3DDefault->gl_visual );
+ if ( pD3DDefault->gl_buffer == NULL )
+ {
+ gl_destroy_visual( pD3DDefault->gl_visual );
+ gl_destroy_context( pD3DDefault->gl_ctx );
+ FREE( pD3DDefault );
+ return FALSE;
+ }
+ SetupDDPointers( pD3DDefault->gl_ctx );
+ gl_make_current( pD3DDefault->gl_ctx, pD3DDefault->gl_buffer );
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* This function will create a new D3D context but will not create the D3D */
+/* surfaces or even an instance of D3D (see at GetBufferSize). The only stuff*/
+/* done here is the internal Mesa stuff and some Win32 handles. */
+/*===========================================================================*/
+/* RETURN: casted pointer to the context, NULL. */
+/*===========================================================================*/
+HGLRC APIENTRY wglCreateContext( HDC hdc )
+{
+ D3DMESACONTEXT *pNewContext;
+ DWORD dwCoopFlags = DDSCL_NORMAL;
+ RECT rectClient;
+ POINT pt;
+
+ /* ALLOC and clear the new context. */
+ pNewContext = (PD3DMESACONTEXT)ALLOC( sizeof(D3DMESACONTEXT) );
+ if ( pNewContext == NULL )
+ {
+ SetLastError( 0 );
+ return (HGLRC)NULL;
+ }
+ memset( pNewContext, 0, sizeof(D3DMESACONTEXT) );
+
+ /*========================================================================*/
+ /* Do all core Mesa stuff. */
+ /*========================================================================*/
+
+ /* TODO: support more then one visual. */
+ pNewContext->gl_visual = gl_create_visual( TRUE,
+ GL_TRUE, /* software alpha */
+ TRUE, /* db_flag */
+ GL_FALSE, /* stereo */
+ 16, /* depth_bits */
+ 8, /* stencil_bits */
+ 8, /* accum_bits */
+ 0, /* index bits */
+ 8,8,8,8 ); /* r, g, b, a bits */
+ if ( pNewContext->gl_visual == NULL)
+ {
+ FREE( pNewContext );
+ SetLastError( 0 );
+ return (HGLRC)NULL;
+ }
+
+ /* Allocate a new Mesa context */
+ pNewContext->gl_ctx = gl_create_context( pNewContext->gl_visual, NULL, pNewContext, GL_TRUE );
+ if ( pNewContext->gl_ctx == NULL )
+ {
+ gl_destroy_visual( pNewContext->gl_visual );
+ FREE( pNewContext );
+ SetLastError( 0 );
+ return (HGLRC)NULL;
+ }
+
+ /* Allocate a new Mesa frame buffer */
+ pNewContext->gl_buffer = gl_create_framebuffer( pNewContext->gl_visual );
+ if ( pNewContext->gl_buffer == NULL )
+ {
+ gl_destroy_visual( pNewContext->gl_visual );
+ gl_destroy_context( pNewContext->gl_ctx );
+ FREE( pNewContext );
+ SetLastError( 0 );
+ return (HGLRC)NULL;
+ }
+
+ /*========================================================================*/
+ /* Do all the driver stuff. */
+ /*========================================================================*/
+ pNewContext->hdc = hdc;
+ pNewContext->next = pD3DDefault->next;
+ pD3DDefault->next = pNewContext; /* Add to circular list. */
+
+ /* Create the HAL for the new context. */
+ pNewContext->pShared = InitHAL( WindowFromDC(hdc) );
+
+ return (HGLRC)pNewContext;
+}
+/*===========================================================================*/
+/* This is a wrapper function that is supported by MakeCurrent. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+BOOL APIENTRY wglMakeCurrent( HDC hdc, HGLRC hglrc )
+{
+ return MakeCurrent((D3DMESACONTEXT *)hglrc);
+}
+/*===========================================================================*/
+/* MakeCurrent will unbind whatever context is current (if any) & then bind */
+/* the supplied context. A context that is bound has it's window proc hooked*/
+/* with the wglMonitorProc and the context pointer is saved in pD3DCurrent. */
+/* Once the context is bound we update the Mesa-3.0 hooks (SetDDPointers) and*/
+/* the viewport (Mesa-.30 and DX6). */
+/* */
+/* TODO: this function can't fail. */
+/*===========================================================================*/
+/* RETURN: TRUE */
+/*===========================================================================*/
+static BOOL MakeCurrent( D3DMESACONTEXT *pContext )
+{
+ D3DMESACONTEXT *pNext;
+
+ /*====================================================================*/
+ /* This is a special case that is a request to have no context bound. */
+ /*====================================================================*/
+ if ( pContext == NULL )
+ {
+ /* Walk the whole list. We start and end at the Default context. */
+ for( pNext = pD3DDefault->next; pNext != pD3DDefault; pNext = pNext->next )
+ UnBindWindow( pNext );
+
+ return TRUE;
+ }
+
+ /*=================================================*/
+ /* Make for a fast redundant use of this function. */
+ /*=================================================*/
+ if ( pD3DCurrent == pContext )
+ return TRUE;
+
+ /*=============================*/
+ /* Unbind the current context. */
+ /*=============================*/
+ UnBindWindow( pD3DCurrent );
+
+ /*=====================================*/
+ /* Let Mesa-3.0 we have a new context. */
+ /*=====================================*/
+ SetupDDPointers( pContext->gl_ctx );
+ gl_make_current( pContext->gl_ctx, pContext->gl_buffer );
+
+ /* We are done so set the internal current context. */
+ if ( pContext != pD3DDefault )
+ {
+ ResizeContext( pContext->gl_ctx );
+ pContext->hOldProc = (WNDPROC)GetWindowLong( pContext->pShared->hwnd, GWL_WNDPROC );
+ SetWindowLong( pContext->pShared->hwnd, GWL_WNDPROC, (LONG)wglMonitorProc );
+ }
+ pD3DCurrent = pContext;
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* This function will only return the current window size. I have re-done */
+/* this function so that it doesn't check the current size and react to it as*/
+/* I should be able to have all the react code in the WM_SIZE message. The */
+/* old version would check the current window size and create/resize the HAL */
+/* surfaces if they have changed. I needed to delay the creation if the */
+/* surfaces because sometimes I wouldn't have a window size so this is where */
+/* I delayed it. If you are reading this then all went ok! */
+/* The default context will return a zero sized window and I'm not sure if */
+/* this is ok at this point (TODO). */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void GetBufferSize( GLcontext *ctx, GLuint *width, GLuint *height )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+
+ /* Fall through for the default because that is one of the uses for it. */
+ if ( pContext == pD3DDefault )
+ {
+ *width = 0;
+ *height = 0;
+ }
+ else
+ {
+ *width = pContext->pShared->dwWidth;
+ *height = pContext->pShared->dwHeight;
+ }
+}
+/*===========================================================================*/
+/* */
+/* */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static BOOL ResizeContext( GLcontext *ctx )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx,
+ *pCurrentTemp;
+ RECT rectClient;
+ POINT pt;
+ DWORD dwWidth,
+ dwHeight;
+ static BOOL bDDrawLock = FALSE;
+
+ /* Make sure we have some values. */
+ if ( (pContext->hdc == NULL ) ||
+ (pContext->pShared->hwnd != WindowFromDC(pContext->hdc)) ||
+ (pContext == pD3DDefault) )
+ return FALSE;
+
+ /* Having problems with DDraw sending resize messages before I was done. */
+ if( bDDrawLock == TRUE )
+ return FALSE;
+
+ // TODO: don't think I need this anymore.
+ pCurrentTemp = pD3DCurrent;
+ pD3DCurrent = pD3DDefault;
+ bDDrawLock = TRUE;
+
+ /* Get the current window dimentions. */
+ UpdateScreenPosHAL( pContext->pShared );
+ dwWidth = pContext->pShared->rectW.right - pContext->pShared->rectW.left;
+ dwHeight = pContext->pShared->rectW.bottom - pContext->pShared->rectW.top;
+
+ /* Is the size of the OffScreen Render different? */
+ if ( (dwWidth != pContext->pShared->dwWidth) || (dwHeight != pContext->pShared->dwHeight) )
+ {
+ /* Create all the D3D surfaces and device. */
+ CreateHAL( pContext->pShared );
+
+ /* I did this so that software rendering would still work as */
+ /* I don't need to scale the z values twice. */
+ g_DepthScale = (pContext->pShared->bHardware) ? 1.0 : ((float)0x00FFFFFF);
+ g_MaxDepth = (pContext->pShared->bHardware) ? 1.0 : ((float)0x00FFFFFF);
+ gl_DepthRange( pContext->gl_ctx, ctx->Viewport.Near, ctx->Viewport.Far );
+
+ /* Make sure we have a viewport. */
+ gl_Viewport( pContext->gl_ctx, 0, 0, dwWidth, dwHeight );
+
+ /* Update Mesa as we might have changed from SW <-> HW. */
+ SetupDDPointers( pContext->gl_ctx );
+ gl_make_current( pContext->gl_ctx, pContext->gl_buffer );
+
+ /* If we are in HW we need to load the current texture if there is one already. */
+ // if ( (ctx->Texture.Set[ctx->Texture.CurrentSet].Current != NULL) &&
+ // (pContext->pShared->bHardware == TRUE) )
+ // {
+ // CreateTMgrHAL( pContext->pShared,
+ // ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Name,
+ // 0,
+ // ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Format,
+ // (RECT *)NULL,
+ // ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Width,
+ // ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Height,
+ // TM_ACTION_BIND,
+ // (void *)ctx->Texture.Set[ctx->Texture.CurrentSet].Current->Image[0]->Data );
+ // }
+ }
+
+ // TODO: don't think I need this anymore.
+ pD3DCurrent = pCurrentTemp;
+ bDDrawLock = FALSE;
+
+ return TRUE;
+}
+
+/*===========================================================================*
+/* This function will Blt the render buffer to the PRIMARY surface. I repeat*/
+/* this code for the other SwapBuffer like functions and the flush (didn't */
+/* want the function calling overhead). Thsi could have been a macro... */
+/* */
+/* TODO: there are some problems with viewport/scissoring. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+BOOL APIENTRY wglSwapBuffers( HDC hdc )
+{
+ /* Fall through for the default because that is one of the uses for it. */
+ if ( pD3DCurrent == pD3DDefault )
+ return FALSE;
+
+ SwapBuffersHAL( pD3DCurrent->pShared );
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* Same as wglSwapBuffers. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+BOOL APIENTRY SwapBuffers( HDC hdc )
+{
+ /* Fall through for the default because that is one of the uses for it. */
+ if ( pD3DCurrent == pD3DDefault )
+ return FALSE;
+
+ SwapBuffersHAL( pD3DCurrent->pShared );
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* This should be ok as none of the SwapBuffers will cause a redundant Blt */
+/* as none of my Swap functions will call flush. This should also allow */
+/* sinlge buffered applications to work (not really worried though). Some */
+/* applications may flush then swap but then this is there fault IMHO. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void Flush( GLcontext *ctx )
+{
+ /* Fall through for the default because that is one of the uses for it. */
+ if ( pD3DCurrent == pD3DDefault )
+ return;
+
+ SwapBuffersHAL( pD3DCurrent->pShared );
+}
+/*===========================================================================*/
+/* For now this function will ignore the supplied PF. If I'm going to allow */
+/* the user to choice the mode and device at startup I'm going to have to do */
+/* something different. */
+/* */
+/* TODO: use the linked list of modes to build a pixel format to be returned */
+/* to the caller. */
+/*===========================================================================*/
+/* RETURN: 1. */
+/*===========================================================================*/
+int APIENTRY wglChoosePixelFormat( HDC hdc, CONST PIXELFORMATDESCRIPTOR *ppfd )
+{
+ return 1;
+}
+/*===========================================================================*/
+/* See wglChoosePixelFormat. */
+/*===========================================================================*/
+/* RETURN: 1. */
+/*===========================================================================*/
+int APIENTRY ChoosePixelFormat( HDC hdc, CONST PIXELFORMATDESCRIPTOR *ppfd )
+{
+ return wglChoosePixelFormat(hdc,ppfd);
+}
+/*===========================================================================*/
+/* This function (for now) returns a static PF everytime. This is just to */
+/* allow things to continue. */
+/*===========================================================================*/
+/* RETURN: 1. */
+/*===========================================================================*/
+int APIENTRY wglDescribePixelFormat( HDC hdc, int iPixelFormat, UINT nBytes, LPPIXELFORMATDESCRIPTOR ppfd )
+{
+ static PIXELFORMATDESCRIPTOR pfd =
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), /* size */
+ 1, /* version */
+ PFD_SUPPORT_OPENGL |
+ PFD_DRAW_TO_WINDOW |
+ PFD_DOUBLEBUFFER, /* support double-buffering */
+ PFD_TYPE_RGBA, /* color type */
+ 16, /* prefered color depth */
+ 0, 0, 0, 0, 0, 0, /* color bits (ignored) */
+ 0, /* no alpha buffer */
+ 0, /* alpha bits (ignored) */
+ 0, /* no accumulation buffer */
+ 0, 0, 0, 0, /* accum bits (ignored) */
+ 16, /* depth buffer */
+ 0, /* no stencil buffer */
+ 0, /* no auxiliary buffers */
+ PFD_MAIN_PLANE, /* main layer */
+ 0, /* reserved */
+ 0, 0, 0, /* no layer, visible, damage masks */
+ };
+
+ /* Return the address of this static PF if one was requested. */
+ if ( ppfd != NULL )
+ memcpy( ppfd, &pfd, sizeof(PIXELFORMATDESCRIPTOR) );
+
+ return 1;
+}
+/*===========================================================================*/
+/* See wglDescribePixelFormat. */
+/*===========================================================================*/
+/* RETURN: 1. */
+/*===========================================================================*/
+int APIENTRY DescribePixelFormat( HDC hdc, int iPixelFormat, UINT nBytes, LPPIXELFORMATDESCRIPTOR ppfd )
+{
+ return wglDescribePixelFormat(hdc,iPixelFormat,nBytes,ppfd);
+}
+/*===========================================================================*/
+/* This function will always return 1 for now. Just to allow for support. */
+/*===========================================================================*/
+/* RETURN: 1. */
+/*===========================================================================*/
+int APIENTRY wglGetPixelFormat( HDC hdc )
+{
+ return 1;
+}
+/*===========================================================================*/
+/* See wglGetPixelFormat. */
+/*===========================================================================*/
+/* RETURN: 1. */
+/*===========================================================================*/
+int APIENTRY GetPixelFormat( HDC hdc )
+{
+ return wglGetPixelFormat(hdc);
+}
+/*===========================================================================*/
+/* This will aways work for now. */
+/*===========================================================================*/
+/* RETURN: TRUE. */
+/*===========================================================================*/
+BOOL APIENTRY wglSetPixelFormat( HDC hdc, int iPixelFormat, CONST PIXELFORMATDESCRIPTOR *ppfd )
+{
+ return TRUE;
+}
+/*===========================================================================*/
+/* See wglSetPixelFormat. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+BOOL APIENTRY SetPixelFormat( HDC hdc, int iPixelFormat, CONST PIXELFORMATDESCRIPTOR *ppfd )
+{
+ return wglSetPixelFormat(hdc,iPixelFormat,ppfd);
+}
+/*===========================================================================*/
+/* This is a wrapper function that is supported by my own internal function.*/
+/* that takes my own D3D Mesa context structure. This so I can reuse the */
+/* function (no need for speed). */
+/*===========================================================================*/
+/* RETURN: TRUE. */
+/*===========================================================================*/
+BOOL APIENTRY wglDeleteContext( HGLRC hglrc )
+{
+ DestroyContext( (D3DMESACONTEXT *)hglrc );
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* Simple getter function that uses a cast. */
+/*===========================================================================*/
+/* RETURN: casted pointer to the context, NULL. */
+/*===========================================================================*/
+HGLRC APIENTRY wglGetCurrentContext( VOID )
+{
+ return (pD3DCurrent) ? (HGLRC)pD3DCurrent : (HGLRC)NULL;
+}
+/*===========================================================================*/
+/* No support. */
+/*===========================================================================*/
+/* RETURN: FALSE. */
+/*===========================================================================*/
+BOOL APIENTRY wglCopyContext( HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask )
+{
+ SetLastError( 0 );
+ return FALSE;
+}
+/*===========================================================================*/
+/* No support. */
+/*===========================================================================*/
+/* RETURN: NULL. */
+/*===========================================================================*/
+HGLRC APIENTRY wglCreateLayerContext( HDC hdc,int iLayerPlane )
+{
+ SetLastError( 0 );
+ return (HGLRC)NULL;
+}
+/*===========================================================================*/
+/* Simple getter function. */
+/*===========================================================================*/
+/* RETURN: FALSE. */
+/*===========================================================================*/
+HDC APIENTRY wglGetCurrentDC( VOID )
+{
+ return (pD3DCurrent) ? pD3DCurrent->hdc : (HDC)NULL;
+}
+/*===========================================================================*/
+/* Simply call that searches the supported extensions for a match & returns */
+/* the pointer to the function that lends support. */
+/*===========================================================================*/
+/* RETURN: pointer to API call, NULL. */
+/*===========================================================================*/
+PROC APIENTRY wglGetProcAddress( LPCSTR lpszProc )
+{
+ int index;
+
+ for( index = 0; index < qt_ext; index++ )
+ if( !strcmp(lpszProc,ext[index].name) )
+ return ext[index].proc;
+
+ SetLastError( 0 );
+ return NULL;
+}
+/*===========================================================================*/
+/* No support. */
+/*===========================================================================*/
+/* RETURN: FALSE. */
+/*===========================================================================*/
+BOOL APIENTRY wglShareLists( HGLRC hglrc1, HGLRC hglrc2 )
+{
+ SetLastError( 0 );
+ return FALSE;
+}
+/*===========================================================================*/
+/* No support. */
+/*===========================================================================*/
+/* RETURN: FALSE. */
+/*===========================================================================*/
+BOOL APIENTRY wglUseFontBitmaps( HDC fontDevice, DWORD firstChar, DWORD numChars, DWORD listBase )
+{
+ SetLastError( 0 );
+ return FALSE;
+}
+/*===========================================================================*/
+/* No support. */
+/*===========================================================================*/
+/* RETURN: FALSE. */
+/*===========================================================================*/
+BOOL APIENTRY wglUseFontBitmapsW( HDC hdc,DWORD first,DWORD count,DWORD listBase )
+{
+ SetLastError( 0 );
+ return FALSE;
+}
+/*===========================================================================*/
+/* No support. */
+/*===========================================================================*/
+/* RETURN: FALSE. */
+/*===========================================================================*/
+BOOL APIENTRY wglUseFontOutlinesA( HDC hdc, DWORD first, DWORD count, DWORD listBase, FLOAT deviation, FLOAT extrusion, int format, LPGLYPHMETRICSFLOAT lpgmf )
+{
+ SetLastError( 0 );
+ return FALSE;
+}
+/*===========================================================================*/
+/* No support. */
+/*===========================================================================*/
+/* RETURN: FALSE. */
+/*===========================================================================*/
+BOOL APIENTRY wglUseFontOutlinesW( HDC hdc,DWORD first,DWORD count, DWORD listBase,FLOAT deviation, FLOAT extrusion,int format, LPGLYPHMETRICSFLOAT lpgmf )
+{
+ SetLastError( 0 );
+ return FALSE ;
+}
+/*===========================================================================*/
+/* No support. */
+/*===========================================================================*/
+/* RETURN: FALSE. */
+/*===========================================================================*/
+BOOL APIENTRY wglSwapLayerBuffers( HDC hdc, UINT fuPlanes )
+{
+ SetLastError( 0 );
+ return FALSE;
+}
+/*===========================================================================*/
+/* This function will be hooked into the window that has been bound. Right */
+/* now it is used to track the window size and position. Also the we clean */
+/* up the currrent context when the window is close/destroyed. */
+/* */
+/* TODO: there might be something wrong here as some games (Heretic II) don't*/
+/* track the window quit right. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+LONG APIENTRY wglMonitorProc( HWND hwnd, UINT message, UINT wParam, LONG lParam )
+{
+ WNDPROC hOldProc;
+ GLint width,
+ height;
+
+ switch( message )
+ {
+// case WM_PAINT:
+// break;
+// case WM_ACTIVATE:
+// break;
+// case WM_SHOWWINDOW:
+// break;
+
+ case UM_FATALSHUTDOWN:
+ /* Support the API until we die... */
+ MakeCurrent( pD3DDefault );
+ break;
+
+ case WM_MOVE:
+ case WM_DISPLAYCHANGE:
+ case WM_SIZE:
+ ResizeContext( pD3DCurrent->gl_ctx );
+ break;
+
+ case WM_CLOSE:
+ case WM_DESTROY:
+ /* Support the API until we die... */
+ hOldProc = pD3DCurrent->hOldProc;
+ DestroyContext( pD3DCurrent );
+ return (hOldProc)(hwnd,message,wParam,lParam);
+ }
+
+ return (pD3DCurrent->hOldProc)(hwnd,message,wParam,lParam);
+}
+
+/**********************************************************************/
+/***** Miscellaneous device driver funcs *****/
+/**********************************************************************/
+
+/*===========================================================================*/
+/* Not reacting to this as I'm only supporting drawing to the back buffer */
+/* right now. */
+/*===========================================================================*/
+/* RETURN: TRUE. */
+/*===========================================================================*/
+static GLboolean SetBuffer( GLcontext *ctx, GLenum buffer )
+{
+ if (buffer == GL_BACK_LEFT)
+ return GL_TRUE;
+ else
+ return GL_FALSE;
+}
+/*===========================================================================*/
+/* This proc will be called by Mesa when the viewport has been set. So if */
+/* we have a context and it isn't the default then we should let D3D know of */
+/* the change. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void SetViewport( GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ RECT rect;
+
+ /* Make sure we can set a viewport. */
+ if ( pContext->pShared && (pContext != pD3DDefault) )
+ {
+ // TODO: might be needed.
+ UpdateScreenPosHAL( pContext->pShared );
+ rect.left = x;
+ rect.right = x + w;
+ rect.top = y;
+ rect.bottom = y + h;
+
+ // TODO: shared struct should make this call smaller
+ SetViewportHAL( pContext->pShared, &rect, 0.0F, 1.0F );
+ }
+}
+/*===========================================================================*/
+/* This function could be better I guess but I decided just to grab the four*/
+/* components and store then seperately. Makes it easier to use IMHO. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void ClearColor( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+
+ pContext->aClear = a;
+ pContext->bClear = b;
+ pContext->gClear = g;
+ pContext->rClear = r;
+}
+/*===========================================================================*/
+/* This function could be better I guess but I decided just to grab the four*/
+/* components and store then seperately. Makes it easier to use IMHO. */
+/* (is there an echo in here?) */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void SetColor( GLcontext *ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+
+ pContext->aCurrent = a;
+ pContext->bCurrent = b;
+ pContext->gCurrent = g;
+ pContext->rCurrent = r;
+}
+/*===========================================================================*/
+/* */
+/* */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static const char *RendererString( void )
+{
+ static char pszRender[64];
+
+ strcpy( pszRender, "altD3D " );
+
+ if ( pD3DCurrent->pShared->bHardware )
+ strcat( pszRender, "(HW)");
+ else
+ strcat( pszRender, "(SW)");
+
+ return (const char *)pszRender;
+}
+/*===========================================================================*/
+/* This function will choose which set of pointers Mesa will use based on */
+/* whether we hard using hardware or software. I have added another set of */
+/* pointers that will do nothing but stop the API from crashing. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void SetupDDPointers( GLcontext *ctx )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+
+ // TODO: write a generic NULL support for the span render.
+ if ( pContext->pShared && pContext->pShared->bHardware )
+ {
+ ctx->Driver.UpdateState = SetupHWDDPointers;
+ }
+ else if ( pContext == pD3DDefault )
+ {
+ ctx->Driver.UpdateState = SetupNULLDDPointers;
+ }
+ else
+ {
+ ctx->Driver.UpdateState = SetupSWDDPointers;
+ }
+}
+/*===========================================================================*/
+/* This function will populate all the Mesa driver hooks. This version of */
+/* hooks will do nothing but support the API when we don't have a valid */
+/* context bound. This is mostly for applications that don't behave right */
+/* and also to help exit as clean as possable when we have a FatalError. */
+/*===========================================================================*/
+/* RETURN: pointer to the specific function. */
+/*===========================================================================*/
+static void SetupNULLDDPointers( GLcontext *ctx )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+
+ /* Initialize all the pointers in the DD struct. Do this whenever */
+ /* a new context is made current or we change buffers via set_buffer! */
+ ctx->Driver.UpdateState = SetupNULLDDPointers;
+
+ /* State management hooks. */
+ ctx->Driver.Color = NULLSetColor;
+ ctx->Driver.ClearColor = NULLClearColor;
+ ctx->Driver.Clear = NULLClearBuffers;
+ ctx->Driver.SetBuffer = NULLSetBuffer;
+
+ /* Window management hooks. */
+ ctx->Driver.GetBufferSize = NULLGetBufferSize;
+
+ /* Primitive rendering hooks. */
+ ctx->Driver.TriangleFunc = NULL;
+ ctx->Driver.RenderVB = NULL;
+
+ /* Pixel/span writing functions: */
+ ctx->Driver.WriteRGBASpan = NULLWrSpRGBA;
+ ctx->Driver.WriteRGBSpan = NULLWrSpRGB;
+ ctx->Driver.WriteMonoRGBASpan = NULLWrSpRGBAMono;
+ ctx->Driver.WriteRGBAPixels = NULLWrPiRGBA;
+ ctx->Driver.WriteMonoRGBAPixels = NULLWrPiRGBAMono;
+
+ /* Pixel/span reading functions: */
+ ctx->Driver.ReadRGBASpan = NULLReSpRGBA;
+ ctx->Driver.ReadRGBAPixels = NULLRePiRGBA;
+
+ /* Misc. hooks. */
+ ctx->Driver.RendererString = RendererString;
+}
+/*===========================================================================*/
+/* This function will populate all the Mesa driver hooks. There are two of */
+/* these functions. One if we have hardware support and one is there is only*/
+/* software. These functions will be called by Mesa and by the wgl.c when we*/
+/* have resized (or created) the buffers. The thing is that if a window gets*/
+/* resized we may loose hardware support or gain it... */
+/*===========================================================================*/
+/* RETURN: pointer to the specific function. */
+/*===========================================================================*/
+static void SetupSWDDPointers( GLcontext *ctx )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+
+ /* Initialize all the pointers in the DD struct. Do this whenever */
+ /* a new context is made current or we change buffers via set_buffer! */
+ ctx->Driver.UpdateState = SetupSWDDPointers;
+
+ /* State management hooks. */
+ ctx->Driver.Color = SetColor;
+ ctx->Driver.ClearColor = ClearColor;
+ ctx->Driver.Clear = ClearBuffers;
+ ctx->Driver.SetBuffer = SetBuffer;
+
+ /* Window management hooks. */
+ ctx->Driver.GetBufferSize = GetBufferSize;
+ ctx->Driver.Viewport = SetViewport;
+
+ /* Primitive rendering hooks. */
+ ctx->Driver.TriangleFunc = NULL;
+ ctx->Driver.RenderVB = NULL;
+
+ /* Texture management hooks. */
+
+ /* Pixel/span writing functions: */
+ ctx->Driver.WriteRGBASpan = WSpanRGBA;
+ ctx->Driver.WriteRGBSpan = WSpanRGB;
+ ctx->Driver.WriteMonoRGBASpan = WSpanRGBAMono;
+ ctx->Driver.WriteRGBAPixels = WPixelsRGBA;
+ ctx->Driver.WriteMonoRGBAPixels = WPixelsRGBAMono;
+
+ /* Pixel/span reading functions: */
+ ctx->Driver.ReadRGBASpan = RSpanRGBA;
+ ctx->Driver.ReadRGBAPixels = RPixelsRGBA;
+
+ /* Misc. hooks. */
+ ctx->Driver.Flush = Flush;
+ ctx->Driver.RendererString = RendererString;
+}
+/*===========================================================================*/
+/* This function will populate all the Mesa driver hooks. There are two of */
+/* these functions. One if we have hardware support and one is there is only*/
+/* software. These functions will be called by Mesa and by the wgl.c when we*/
+/* have resized (or created) the buffers. The thing is that if a window gets*/
+/* resized we may loose hardware support or gain it... */
+/*===========================================================================*/
+/* RETURN: pointer to the specific function. */
+/*===========================================================================*/
+static void SetupHWDDPointers( GLcontext *ctx )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+
+ /* Initialize all the pointers in the DD struct. Do this whenever */
+ /* a new context is made current or we change buffers via set_buffer! */
+ ctx->Driver.UpdateState = SetupHWDDPointers;
+
+ /* State management hooks. */
+ ctx->Driver.Color = SetColor;
+ ctx->Driver.ClearColor = ClearColor;
+ ctx->Driver.Clear = ClearBuffersD3D;
+ ctx->Driver.SetBuffer = SetBuffer;
+
+ /* Window management hooks. */
+ ctx->Driver.GetBufferSize = GetBufferSize;
+ ctx->Driver.Viewport = SetViewport;
+
+ /* Primitive rendering hooks. */
+ ctx->Driver.TriangleFunc = RenderOneTriangle;
+ ctx->Driver.LineFunc = RenderOneLine;
+ ctx->Driver.RenderVB = RenderVertexBuffer;
+
+ /* Pixel/span writing functions: */
+ ctx->Driver.WriteRGBASpan = WSpanRGBA;
+ ctx->Driver.WriteRGBSpan = WSpanRGB;
+ ctx->Driver.WriteMonoRGBASpan = WSpanRGBAMono;
+ ctx->Driver.WriteRGBAPixels = WPixelsRGBA;
+ ctx->Driver.WriteMonoRGBAPixels = WPixelsRGBAMono;
+
+ /* Pixel/span reading functions: */
+ ctx->Driver.ReadRGBASpan = RSpanRGBA;
+ ctx->Driver.ReadRGBAPixels = RPixelsRGBA;
+
+ /* Texture management hooks. */
+ // ctx->Driver.BindTexture = TextureBind;
+ ctx->Driver.TexImage = TextureLoad;
+ ctx->Driver.TexSubImage = TextureSubImage;
+
+ /* Misc. hooks. */
+ ctx->Driver.Flush = Flush;
+ ctx->Driver.RendererString = RendererString;
+}
+/*===========================================================================*/
+/* This function will release all resources used by the DLL. Every context */
+/* will be clobbered by releaseing all driver desources and then freeing the */
+/* context memory. Most all the work is done in DestroyContext. */
+/*===========================================================================*/
+/* RETURN: TRUE. */
+/*===========================================================================*/
+static BOOL TermOpenGL( HINSTANCE hInst )
+{
+ D3DMESACONTEXT *pTmp,
+ *pNext;
+
+ /* Just incase we are still getting paint msg. */
+ MakeCurrent( pD3DDefault );
+
+ /* Walk the list until we get back to the default context. */
+ for( pTmp = pD3DDefault->next; pTmp != pD3DDefault; pTmp = pNext )
+ {
+ pNext = pTmp->next;
+ DestroyContext( pTmp );
+ }
+ DestroyContext( pD3DDefault );
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* This function is an internal function that will clean up all the Mesa */
+/* context bound to this D3D context. Also any D3D stuff that this context */
+/* uses will be unloaded. */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+static void DestroyContext( D3DMESACONTEXT *pContext )
+{
+ D3DMESACONTEXT *pTmp;
+
+ /* Walk the list until we find the context before this one. */
+ for( pTmp = pD3DDefault; pTmp && (pTmp->next != pContext); pTmp = pTmp->next )
+ if ( pTmp == pTmp->next )
+ break;
+
+ /* If we never found it it must already be deleted. */
+ if ( pTmp->next != pContext )
+ return;
+
+ /* Make sure we are not using this context. */
+ if ( pContext == pD3DCurrent )
+ MakeCurrent( pD3DDefault );
+
+ /* Free the Mesa stuff. */
+ if ( pContext->gl_visual )
+ {
+ gl_destroy_visual( pContext->gl_visual );
+ pContext->gl_visual = NULL;
+ }
+ if ( pContext->gl_buffer )
+ {
+ gl_destroy_framebuffer( pContext->gl_buffer );
+ pContext->gl_buffer = NULL;
+ }
+ if ( pContext->gl_ctx )
+ {
+ gl_destroy_context( pContext->gl_ctx );
+ pContext->gl_ctx = NULL;
+ }
+
+ /* Now dump the D3D. */
+ if ( pContext->pShared )
+ TermHAL( pContext->pShared );
+
+ /* Update the previous context's link. */
+ pTmp->next = pContext->next;
+
+ /* Gonzo. */
+ FREE( pContext );
+}
+/*===========================================================================*/
+/* This function will pull the supplied context away from Win32. Basicly it*/
+/* will remove the hook from the window Proc. */
+/* */
+/* TODO: might want to serialize this stuff... */
+/*===========================================================================*/
+/* RETURN: TRUE, FALSE. */
+/*===========================================================================*/
+static BOOL UnBindWindow( D3DMESACONTEXT *pContext )
+{
+ if ( pContext == NULL )
+ return FALSE;
+
+ if ( pContext == pD3DDefault )
+ return TRUE;
+
+ /* Make sure we always have a context bound. */
+ if ( pContext == pD3DCurrent )
+ pD3DCurrent = pD3DDefault;
+
+ SetWindowLong( pContext->pShared->hwnd, GWL_WNDPROC, (LONG)pContext->hOldProc );
+ pContext->hOldProc = NULL;
+
+ return TRUE;
+}
+/*===========================================================================*/
+/* There are two cases that allow for a faster clear when we know that the */
+/* whole buffer is cleared and that there is no clipping. */
+/*===========================================================================*/
+/* RETURN: the original mask with the bits cleared that represents the buffer*
+/* or buffers we just cleared. */
+/*===========================================================================*/
+GLbitfield ClearBuffersD3D( GLcontext *ctx, GLbitfield mask, GLboolean all, GLint x, GLint y, GLint width, GLint height )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ DWORD dwFlags = 0;
+
+ if ( mask & GL_COLOR_BUFFER_BIT )
+ {
+ dwFlags |= D3DCLEAR_TARGET;
+ mask &= ~GL_COLOR_BUFFER_BIT;
+ }
+ if ( mask & GL_DEPTH_BUFFER_BIT )
+ {
+ dwFlags |= D3DCLEAR_ZBUFFER;
+ mask &= ~GL_DEPTH_BUFFER_BIT;
+ }
+ if ( dwFlags == 0 )
+ return mask;
+
+ ClearHAL( pContext->pShared,
+ dwFlags,
+ all,
+ x, y,
+ width, height,
+ ((pContext->aClear<<24) | (pContext->rClear<<16) | (pContext->gClear<<8) | (pContext->bClear)),
+ ctx->Depth.Clear,
+ 0 );
+
+ return mask;
+}
+
+
+
+/*===========================================================================*/
+/* TEXTURE MANAGER: ok here is how I did textures. Mesa-3.0 will keep track*/
+/* of all the textures for us. So this means that at anytime we can go to */
+/* the Mesa context and get the current texture. With this in mind this is */
+/* what I did. I really don't care about what textures get or are loaded */
+/* until I actually have to draw a tri that is textured. At this point I */
+/* must have the texture so I demand the texture by destorying all other */
+/* texture surfaces if need be and load the current one. This allows for the*/
+/* best preformance on low memory cards as time is not wasted loading and */
+/* unload textures. */
+/*===========================================================================*/
+
+
+
+
+
+/*===========================================================================*/
+/* TextureLoad will try and create a D3D surface from the supplied texture */
+/* object if its level 0 (first). The surface will be fully filled with the */
+/* texture. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void TextureLoad( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj, GLint level, GLint internalFormat, const struct gl_texture_image *image )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+
+ /* TODO: only doing first LOD. */
+ if ( (ctx->DriverCtx == NULL) || (level != 0) )
+ return;
+
+ CreateTMgrHAL( pContext->pShared,
+ tObj->Name,
+ level,
+ tObj->Image[level]->Format,
+ (RECT *)NULL,
+ tObj->Image[level]->Width,
+ tObj->Image[level]->Height,
+ TM_ACTION_LOAD,
+ (void *)tObj->Image[level]->Data );
+}
+/*===========================================================================*/
+/* TextureBind make sure that the texture is on the card. Thats it. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void TextureBind( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+
+ /* TODO: only doing first LOD. */
+ if ( (tObj->Image[0] == NULL) || (ctx->DriverCtx == NULL) )
+ return;
+
+ CreateTMgrHAL( pContext->pShared,
+ tObj->Name,
+ 0,
+ tObj->Image[0]->Format,
+ (RECT *)NULL,
+ tObj->Image[0]->Width,
+ tObj->Image[0]->Height,
+ TM_ACTION_BIND,
+ (void *)tObj->Image[0]->Data );
+}
+/*===========================================================================*/
+/* TextureSubImage will make sure that the texture being updated is updated */
+/* if its on the card. */
+/*===========================================================================*/
+/* RETURN: */
+/*===========================================================================*/
+static void TextureSubImage( GLcontext *ctx, GLenum target, struct gl_texture_object *tObj, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLint internalFormat, const struct gl_texture_image *image )
+{
+ D3DMESACONTEXT *pContext = (D3DMESACONTEXT *)ctx->DriverCtx;
+ RECT rect;
+
+ /* TODO: only doing first LOD. */
+ if ( (ctx->DriverCtx == NULL) || (level > 0) )
+ return;
+
+ /* Create a dirty rectangle structure. */
+ rect.left = xoffset;
+ rect.right = xoffset + width;
+ rect.top = yoffset;
+ rect.bottom = yoffset + height;
+
+ CreateTMgrHAL( pContext->pShared,
+ tObj->Name,
+ 0,
+ tObj->Image[0]->Format,
+ &rect,
+ tObj->Image[0]->Width,
+ tObj->Image[0]->Height,
+ TM_ACTION_UPDATE,
+ (void *)tObj->Image[0]->Data );
+}
+
diff --git a/src/mesa/drivers/d3d/d3dText.h b/src/mesa/drivers/d3d/d3dText.h
new file mode 100644
index 0000000000..9ff0650518
--- /dev/null
+++ b/src/mesa/drivers/d3d/d3dText.h
@@ -0,0 +1,53 @@
+#ifndef D3D_TEXT_H
+#define D3D_TEXT_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*===========================================================================*/
+/* Includes. */
+/*===========================================================================*/
+#include <windows.h>
+#include <ddraw.h>
+#include <d3d.h>
+/*===========================================================================*/
+/* Magic numbers. */
+/*===========================================================================*/
+#define D3DLTEXT_BITSUSED 0xFFFFFFFF
+#define MAX_VERTICES 700 // (14*40) 14 per character, 40 characters
+/*===========================================================================*/
+/* Macros defines. */
+/*===========================================================================*/
+/*===========================================================================*/
+/* Type defines. */
+/*===========================================================================*/
+typedef struct _d3dText_metrics
+{
+ float fntYScale,
+ fntXScale;
+
+ int fntXSpacing,
+ fntYSpacing;
+
+ DWORD dwColor;
+ LPDIRECT3DDEVICE3 lpD3DDevice;
+
+} D3DFONTMETRICS, *PD3DFONTMETRICS;
+/*===========================================================================*/
+/* Function prototypes. */
+/*===========================================================================*/
+extern BOOL InitD3DText( void );
+extern void d3dTextDrawCharacter( char *c, int x, int y, PD3DFONTMETRICS pfntMetrics );
+extern void d3dTextDrawString( char *pszString, int x, int y, PD3DFONTMETRICS pfntMetrics );
+/*===========================================================================*/
+/* Global variables. */
+/*===========================================================================*/
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/src/mesa/drivers/dos/DEPEND.DOS b/src/mesa/drivers/dos/DEPEND.DOS
new file mode 100644
index 0000000000..60a0fdcc28
--- /dev/null
+++ b/src/mesa/drivers/dos/DEPEND.DOS
@@ -0,0 +1,119 @@
+# DO NOT DELETE
+
+accum.obj: accum.h types.h ..\include\GL\gl.h config.h fixed.h dd.h context.h
+accum.obj: dlist.h macros.h
+alpha.obj: alpha.h types.h ..\include\GL\gl.h config.h fixed.h dd.h context.h
+alpha.obj: dlist.h macros.h
+alphabuf.obj: alphabuf.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
+alphabuf.obj: context.h macros.h
+api1.obj: api.h bitmap.h types.h ..\include\GL\gl.h config.h fixed.h dd.h context.h
+api1.obj: eval.h image.h macros.h matrix.h teximage.h
+api2.obj: api.h bitmap.h types.h ..\include\GL\gl.h config.h fixed.h dd.h context.h
+api2.obj: eval.h image.h macros.h matrix.h teximage.h
+attrib.obj: attrib.h types.h ..\include\GL\gl.h config.h fixed.h dd.h context.h
+attrib.obj: draw.h dlist.h macros.h
+bitmap.obj: bitmap.h types.h ..\include\GL\gl.h config.h fixed.h dd.h context.h
+bitmap.obj: feedback.h image.h macros.h pb.h
+blend.obj: alphabuf.h types.h ..\include\GL\gl.h config.h fixed.h dd.h blend.h
+blend.obj: context.h dlist.h macros.h pb.h span.h
+bresenhm.obj: bresenhm.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
+clip.obj: clip.h types.h ..\include\GL\gl.h config.h fixed.h dd.h context.h
+clip.obj: dlist.h macros.h matrix.h vb.h xform.h
+context.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h depth.h
+context.obj: draw.h eval.h light.h lines.h dlist.h macros.h pb.h points.h
+context.obj: pointers.h triangle.h teximage.h texobj.h texture.h vb.h vertex.h
+copypix.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
+copypix.obj: copypix.h depth.h feedback.h dlist.h macros.h pixel.h span.h
+copypix.obj: stencil.h
+depth.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h depth.h
+depth.obj: dlist.h macros.h
+dlist.obj: accum.h types.h ..\include\GL\gl.h config.h fixed.h dd.h alpha.h
+dlist.obj: attrib.h bitmap.h blend.h clip.h context.h copypix.h depth.h draw.h
+dlist.obj: drawpix.h enable.h eval.h feedback.h fog.h image.h light.h lines.h
+dlist.obj: dlist.h logic.h macros.h masking.h matrix.h misc.h pixel.h points.h
+dlist.obj: polygon.h scissor.h stencil.h texobj.h teximage.h texture.h vb.h
+dlist.obj: vertex.h winpos.h
+draw.obj: clip.h types.h ..\include\GL\gl.h config.h fixed.h dd.h context.h
+draw.obj: draw.h feedback.h fog.h light.h lines.h dlist.h macros.h matrix.h
+draw.obj: pb.h points.h texture.h vb.h xform.h
+drawpix.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
+drawpix.obj: drawpix.h feedback.h dlist.h macros.h pixel.h span.h stencil.h
+enable.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h depth.h
+enable.obj: draw.h enable.h light.h dlist.h macros.h stencil.h
+eval.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h draw.h
+eval.obj: eval.h dlist.h macros.h
+feedback.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
+feedback.obj: feedback.h dlist.h macros.h
+fog.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h fog.h
+fog.obj: dlist.h macros.h
+get.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h get.h
+get.obj: dlist.h macros.h
+hash.obj: hash.h
+interp.obj: interp.h types.h ..\include\GL\gl.h config.h fixed.h dd.h macros.h
+image.obj: image.h types.h ..\include\GL\gl.h config.h fixed.h dd.h macros.h
+image.obj: pixel.h
+light.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h light.h
+light.obj: dlist.h macros.h matrix.h vb.h xform.h
+lines.obj: bresenhm.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
+lines.obj: context.h feedback.h interp.h lines.h dlist.h macros.h pb.h vb.h
+logic.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h dlist.h
+logic.obj: logic.h macros.h pb.h
+masking.obj: alphabuf.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
+masking.obj: context.h macros.h masking.h pb.h
+matrix.obj: accum.h types.h ..\include\GL\gl.h config.h fixed.h dd.h alphabuf.h
+matrix.obj: context.h depth.h dlist.h macros.h matrix.h stencil.h
+misc.obj: accum.h types.h ..\include\GL\gl.h config.h fixed.h dd.h alphabuf.h
+misc.obj: context.h depth.h macros.h masking.h misc.h stencil.h
+pb.obj: alpha.h types.h ..\include\GL\gl.h config.h fixed.h dd.h alphabuf.h
+pb.obj: blend.h depth.h fog.h logic.h macros.h masking.h pb.h scissor.h
+pb.obj: stencil.h texture.h
+pixel.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h dlist.h
+pixel.obj: macros.h pixel.h image.h span.h stencil.h
+points.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
+points.obj: feedback.h dlist.h macros.h pb.h span.h vb.h
+pointers.obj: accum.h types.h ..\include\GL\gl.h config.h fixed.h dd.h alpha.h
+pointers.obj: attrib.h bitmap.h blend.h clip.h context.h copypix.h depth.h
+pointers.obj: draw.h drawpix.h enable.h eval.h feedback.h fog.h get.h light.h
+pointers.obj: lines.h dlist.h logic.h macros.h masking.h matrix.h misc.h
+pointers.obj: pixel.h points.h polygon.h readpix.h scissor.h stencil.h
+pointers.obj: teximage.h texobj.h texture.h varray.h vb.h vertex.h winpos.h
+polygon.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
+polygon.obj: macros.h polygon.h
+readpix.obj: alphabuf.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
+readpix.obj: context.h depth.h feedback.h dlist.h macros.h image.h readpix.h
+readpix.obj: span.h stencil.h
+scissor.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
+scissor.obj: macros.h dlist.h scissor.h
+span.obj: alpha.h types.h ..\include\GL\gl.h config.h fixed.h dd.h alphabuf.h
+span.obj: blend.h depth.h fog.h logic.h macros.h masking.h scissor.h span.h
+span.obj: stencil.h texture.h
+stencil.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h dlist.h
+stencil.obj: macros.h pb.h stencil.h
+teximage.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
+teximage.obj: image.h macros.h pixel.h span.h teximage.h
+texobj.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h macros.h
+texobj.obj: teximage.h texobj.h
+texture.obj: context.h types.h ..\include\GL\gl.h config.h fixed.h dd.h dlist.h
+texture.obj: macros.h pb.h teximage.h texture.h
+triangle.obj: depth.h types.h ..\include\GL\gl.h config.h fixed.h dd.h
+triangle.obj: feedback.h macros.h span.h triangle.h vb.h tritemp.h
+varray.obj: draw.h types.h ..\include\GL\gl.h config.h fixed.h dd.h context.h
+varray.obj: enable.h dlist.h macros.h varray.h vb.h xform.h
+vb.obj: types.h ..\include\GL\gl.h config.h fixed.h dd.h vb.h
+vertex.obj: draw.h types.h ..\include\GL\gl.h config.h fixed.h dd.h light.h
+vertex.obj: dlist.h macros.h vb.h vertex.h
+winpos.obj: ..\include\GL\gl.h draw.h types.h config.h fixed.h dd.h dlist.h
+winpos.obj: macros.h winpos.h
+xform.obj: types.h ..\include\GL\gl.h config.h fixed.h dd.h xform.h
+glx.obj: ..\include\GL\gl.h ..\include\GL\glx.h ..\include\GL\xmesa.h context.h
+glx.obj: types.h config.h fixed.h dd.h macros.h xmesaP.h
+osmesa.obj: ..\include\GL\osmesa.h ..\include\GL\gl.h context.h types.h
+osmesa.obj: config.h fixed.h dd.h depth.h macros.h matrix.h vb.h tritemp.h
+xfonts.obj: ..\include\GL\gl.h ..\include\GL\xmesa.h macros.h xmesaP.h types.h
+xfonts.obj: config.h fixed.h dd.h context.h
+xmesa1.obj: ..\include\GL\xmesa.h ..\include\GL\gl.h xmesaP.h types.h config.h
+xmesa1.obj: fixed.h dd.h context.h macros.h matrix.h
+xmesa2.obj: ..\include\GL\xmesa.h ..\include\GL\gl.h macros.h types.h config.h
+xmesa2.obj: fixed.h dd.h xmesaP.h
+xmesa3.obj: bresenhm.h types.h ..\include\GL\gl.h config.h fixed.h dd.h depth.h
+xmesa3.obj: interp.h macros.h vb.h xmesaP.h ..\include\GL\xmesa.h tritemp.h
diff --git a/src/mesa/drivers/dos/dosmesa.c b/src/mesa/drivers/dos/dosmesa.c
new file mode 100644
index 0000000000..2f3973284a
--- /dev/null
+++ b/src/mesa/drivers/dos/dosmesa.c
@@ -0,0 +1,1513 @@
+/* $Id: dosmesa.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 2.3
+ * Copyright (C) 1995-1997 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.
+ */
+
+
+/*
+ * $Log: dosmesa.c,v $
+ * Revision 1.1 1999/08/19 00:55:41 jtg
+ * Initial revision
+ *
+ * Revision 1.2 1999/03/28 21:11:57 brianp
+ * updated SetBuffer driver function
+ *
+ * Revision 1.1 1999/02/24 03:56:31 brianp
+ * initial check-in
+ *
+ *
+ * Revision 1.5 1997/06/19 22:00:00 Brian Paul
+ * Removed all ColorShift stuff
+ *
+ * Revision 1.4 1997/06/03 19:00:00 Brian Paul
+ * Replaced VB->Unclipped[] with VB->ClipMask[]
+ *
+ * Revision 1.3 1997/05/28 07:00:00 Phil Frisbie, Jr.
+ * Now pass red/green/blue/alpha bits to gl_create_visual()
+ * Fixed DJGPP mode 13 support.
+ *
+ * Revision 1.2 1996/12/08 16:13:45 Charlie
+ * Added VESA support via Scitechs SVGA kit.
+ *
+ * Revision 1.1 1996/12/08 16:09:52 Charlie
+ * Initial revision
+ *
+ */
+
+
+/*
+ * DOS VGA/VESA/MGL/Mesa interface.
+ *
+ */
+
+/*
+ *
+ * TODO: (cw)
+ * Improve the colour matcher for rgb non vesa modes, its pretty bad and incorrect
+ * Keyboard interrupt.
+ * Comments and tidy up.
+ * Add support for VESA without SVGAKIT.
+ * DirectX Support.
+ * Better GLIDE Support.
+ * Clear up the #ifdef madness.
+ */
+
+#ifdef DOSVGA
+
+#if defined(DOSVGA) && !defined(GLIDE) && defined(DJGPP) && !defined(UNIVBE) && !defined(MGL)
+
+/* Should help cut down on the crazy #if`s */
+#define MODE13 1
+
+#else
+#undef MODE13
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <string.h>
+#include <dos.h>
+
+#ifdef DJGPP
+#include <go32.h>
+#endif
+
+#ifdef MGL
+#include <mgraph.h>
+#endif
+
+#include "GL/DOSmesa.h"
+#include "context.h"
+#include "matrix.h"
+#include "types.h"
+
+#ifdef GLIDE
+
+static void glideshutdown( void );
+#include "vb.h"
+#include "glide.h"
+
+/* the glide modes available, set one */
+
+//#define GLIDE_MODE GR_RESOLUTION_
+#define GLIDE_MODE GR_RESOLUTION_800x600
+//#define GLIDE_MODE GR_RESOLUTION_640x480
+
+static GrVertex gr_vtx,gr_vtx1,gr_vtx2;
+
+#endif
+
+#ifdef UNIVBE
+/* You get this file from Scitechs VESA development kit */
+#include "svga.h"
+
+/*
+ Set these to the VESA mode you require, the first is for 256 colour modes,
+ the other is High colour modes, they must both be the same XRes and YRes.
+ */
+
+#define VESA_256COLOUR_MODE 0x11c
+#define VESA_HICOLOUR_MODE 0x11f
+
+#endif
+
+struct DOSmesa_context {
+ GLcontext *gl_ctx; /* the core Mesa context */
+ GLvisual *gl_vis; /* describes the color buffer */
+ GLframebuffer *gl_buffer; /* the ancillary buffers */
+ GLuint index; /* current color index */
+ GLint red, green, blue; /* current rgb color */
+ GLint width, height; /* size of color buffer */
+ GLint depth; /* bits per pixel (8,16,24 or 32) */
+};
+
+static DOSMesaContext DOSMesa = NULL; /* the current context */
+
+#ifdef UNIVBE
+SV_devCtx *DC=NULL;
+int useLinear = TRUE;
+SV_modeInfo *mi=NULL;
+unsigned long modeNumber = 0;
+
+int activePage = 0;
+int visualPage = 1;
+
+#endif
+
+#if defined(MODE13)
+
+/* DOSVGA With no UniVBE support */
+
+unsigned char *video_buffer;
+
+#define VID_BUF(x,y) *(video_buffer+x+(y*320))
+
+#if defined(__WATCOMC__) && defined(__386__) && defined(__DOS__)
+
+void setupcopy(void);
+void copyscr(void);
+
+/* Watcom C specfic, screen copy and clear */
+
+#pragma aux setupcopy = \
+ ".386P"\
+ "push ebp" \
+ "mov esi,video_buffer" \
+ "mov edi,0xa0000" \
+ "mov ecx,2000" \
+ "xor ebp,ebp";
+
+#pragma aux copyscr = \
+ ".386P" \
+ "lop1: mov eax,[esi]"\
+ "mov ebx,[esi+4]"\
+ "mov edx,[esi+8]"\
+ "mov [edi],eax"\
+ "mov eax,[esi+12]"\
+ "mov dword ptr [esi],ebp"\
+ "mov dword ptr [esi+4],ebp"\
+ "mov dword ptr [esi+8],ebp"\
+ "mov dword ptr [esi+12],ebp"\
+ "mov [edi+4],ebx"\
+ "mov [edi+8],edx"\
+ "mov [edi+12],eax"\
+ "mov eax,[esi+16]"\
+ "mov ebx,[esi+4+16]"\
+ "mov edx,[esi+8+16]"\
+ "mov [edi+16],eax"\
+ "mov eax,[esi+12+16]"\
+ "mov dword ptr [esi+16],ebp"\
+ "mov dword ptr [esi+4+16],ebp"\
+ "mov dword ptr [esi+8+16],ebp"\
+ "mov dword ptr [esi+12+16],ebp"\
+ "mov [edi+4+16],ebx"\
+ "mov [edi+8+16],edx"\
+ "mov [edi+12+16],eax"\
+ "add esi,32"\
+ "add edi,32"\
+ "dec ecx"\
+ "jnz lop1"\
+ "pop ebp"\
+ modify exact [edi esi eax ebx ecx] ;
+
+#endif // WATCOM
+
+#endif // MODE13
+
+/*
+ * Convert Mesa window Y coordinate to VGA screen Y coordinate:
+ */
+#define FLIP(Y) (DOSMesa->height-(Y)-1)
+
+unsigned short vga_cindex = 32768 ;
+
+static points_func choose_points_function( void );
+static line_func choose_line_function( void );
+static triangle_func choose_polygon_function( void );
+static void fast_tri(GLcontext *ctx,GLuint v0, GLuint v1, GLuint v2, GLuint pv );
+
+static points_func choose_points_function( void )
+{
+ return NULL;
+}
+
+static line_func choose_line_function( void )
+{
+ return NULL;
+}
+
+static triangle_func choose_triangle_function( void )
+{
+ #if defined(MODE13)
+ return NULL;
+ #endif
+
+ #if defined(GLIDE)
+ return fast_tri;
+ #endif
+
+ return NULL;
+}
+
+
+#if defined(MODE13)
+
+void setgfxmode(void);
+void settextmode(void);
+
+#ifndef DJGPP
+#pragma aux setgfxmode = \
+ "mov ax,13h" \
+ "int 10h" \
+ modify [eax];
+
+#pragma aux settextmode = \
+ "mov ax,3h" \
+ "int 10h" \
+ modify [eax];
+#else
+void setgfxmode(void)
+{
+ union REGS in_regs,out_regs;
+
+ in_regs.x.ax = 0x13;
+ int386(0x10,&in_regs,&out_regs);
+}
+
+void settextmode(void)
+{
+ union REGS in_regs,out_regs;
+
+ in_regs.x.ax = 0x3;
+ int386(0x10,&in_regs,&out_regs);
+}
+
+#endif
+
+int set_video_mode(unsigned short x,unsigned short y,char mode)
+{
+ setgfxmode();
+ return 1; /* likelyhood of this failing is very small */
+}
+
+void restore_video_mode(void)
+{
+ settextmode();
+}
+
+int vga_getcolors(void)
+{
+ return vga_cindex;
+}
+
+int vga_getxdim(void)
+{
+ return 320;
+}
+
+int vga_getydim(void)
+{
+ return 200;
+}
+
+static unsigned short num_rgb_alloc = 1; /* start from 1, zero is black */
+
+/* an unlikely colour */
+static unsigned char last_r=1,last_g=255,last_b=99;
+
+extern void set_onecolor(int index,int R,int G,int B);
+
+static unsigned char rgbtable[64][64][64];
+
+void vga_setrgbcolor(int r,int g,int b)
+{
+
+/*
+ * make this into a translation table
+ */
+
+ DOSMesa->red = r;
+ DOSMesa->green = g ;
+ DOSMesa->blue = b ;
+
+ r/=4; g/=4; b/=4;
+
+ if( (r == last_r) && (g == last_g) && (b == last_b) ) return;
+
+ last_r = r ;
+ last_g = g ;
+ last_b = b ;
+
+ if(r+g+b == 0 ) {
+ DOSMesa->index = 0 ;
+ return ;
+ }
+
+ if( rgbtable[r][g][b] == 0 ) {
+ /* not allocated yet */
+ if(num_rgb_alloc<256) {
+ DOSMesa->index = num_rgb_alloc;
+ set_onecolor(num_rgb_alloc,r,g,b);
+ rgbtable[r][g][b] = num_rgb_alloc;
+ num_rgb_alloc++;
+ return;
+
+ } else {
+ /* need to search for a close colour */
+ {
+ unsigned short pass ;
+
+ for(pass=0;pass<64;pass++) {
+ if(r-pass>0) {
+ if( rgbtable[r-pass][g][b] !=0 ) {
+ rgbtable[r][g][b] = rgbtable[r-pass][g][b];
+ DOSMesa->index = rgbtable[r-pass][g][b];
+ return;
+ }
+ }
+ if(r+pass<64) {
+ if( rgbtable[r+pass][g][b] !=0 ) {
+ rgbtable[r][g][b] = rgbtable[r+pass][g][b];
+ DOSMesa->index = rgbtable[r+pass][g][b];
+ return;
+ }
+ }
+ }
+ }
+ rgbtable[r][g][b] = rand()%255;
+ }
+ }
+ DOSMesa->index = rgbtable[r][g][b];
+}
+
+#if defined(DJGPP)
+static int dos_seg;
+#endif
+
+void vga_clear(void)
+{
+
+/* Check if we`re using watcom and DOS */
+#if defined(__WATCOMC__) && defined(__386__) && defined(__DOS__)
+ setupcopy();
+ copyscr();
+#else
+
+#if defined (DJGPP)
+
+
+ asm ("
+ pusha
+ pushw %es
+
+ movw _dos_seg, %es
+
+ movl _video_buffer, %esi
+ movl $0xa0000, %edi
+
+ movl $64000, %ecx
+
+ rep ; movsb
+
+ popw %es
+ popa
+ ");
+
+#else
+
+ /* copy the RAM buffer to the Video memory */
+ memcpy((unsigned char *)0xa0000,video_buffer, vga_getxdim()*vga_getydim() );
+
+#endif //DJGPP
+
+ /* clear the RAM buffer */
+ memset(video_buffer,0, vga_getxdim()*vga_getydim() );
+
+#endif //WATCOMC
+
+}
+
+#ifndef DEBUG
+#define vga_drawpixel(x,y) { VID_BUF(x,y) = DOSMesa->index; }
+#else
+void vga_drawpixel(x,y)
+{
+ VID_BUF(x,y) = DOSMesa->index;
+}
+#endif
+
+int vga_getpixel(int x,int y)
+{
+ return 1;
+}
+
+void vga_flip(void)
+{
+
+}
+
+void vga_setcolor(int index)
+{
+ /* does something, what i`ve no idea */
+ DOSMesa->index = index;
+
+}
+
+#endif
+
+#if defined(UNIVBE)
+
+/* UniVBE VESA support */
+
+void set_video_mode(unsigned short x,unsigned short y,char mode)
+{
+ if( setup_vesa_mode(x,y,mode) == FALSE ) {
+ fprintf(stderr,"VESA: Set mode failed\n");
+ exit(1);
+ }
+}
+
+/*
+ This is problematic as we don`t know what resolution the user program
+ wants when we reach here. This is why the 256 colour and HiColour modes
+ should be the same resolution, perhaps i`ll make this an environment
+ variable
+ */
+
+
+void check_mi(void)
+{
+ if(mi!=0) return;
+
+ if(DC==NULL) {
+ DC = SV_init( TRUE );
+ }
+
+ if(modeNumber == 0 ) {
+ modeNumber = VESA_HICOLOUR_MODE;
+ }
+
+ SV_getModeInfo(modeNumber,mi);
+
+ return;
+}
+
+int setup_vesa_mode(short height,short width,short depth)
+{
+ if(DC==NULL) {
+ DC = SV_init( TRUE );
+ /* how many bits per pixel */
+ if( depth == 0)
+ modeNumber = VESA_256COLOUR_MODE;
+ else
+ modeNumber = VESA_HICOLOUR_MODE;
+ }
+
+ /* Check if correct VESA Version is available */
+ if( !DC || DC->VBEVersion < 0x0102) {
+ fprintf(stderr,"Require a VESA VBE version 1.2 or higher\n");
+ return FALSE;
+ }
+
+ /* Check for LFB Supprt */
+ if(DC->VBEVersion < 0x0200 ) {
+ useLinear = FALSE;
+ } else {
+ useLinear = TRUE ;
+ }
+
+ /* Get desired mode info */
+ if(!SV_getModeInfo( modeNumber, mi))
+ return FALSE;
+
+ /* Set VESA mode */
+ if(!SV_setMode(modeNumber | svMultiBuffer, FALSE, TRUE, mi->NumberOfPages) )
+ return FALSE;
+
+ return TRUE;
+}
+
+void restore_video_mode(void)
+{
+ SV_restoreMode();
+}
+
+void vga_clear(void)
+{
+ SV_clear(0);
+}
+
+void vga_flip(void)
+{
+ activePage = 1-activePage;
+ visualPage = 1-activePage;
+
+ SV_setActivePage(activePage);
+
+ /*
+ Change false to true if you`re getting flickering
+ even in double buffer mode, ( sets wait for Vertical retrace )
+ */
+ SV_setVisualPage(visualPage,false);
+}
+
+int vga_getcolors(void)
+{
+ check_mi();
+ switch ( mi->BitsPerPixel ) {
+ case 8:
+ return 256;
+ case 15:
+ case 16:
+ return 32768;
+ default:
+ return 64000;
+ }
+}
+
+int vga_getxdim(void)
+{
+ check_mi();
+ return mi->XResolution;
+}
+
+int vga_getydim(void)
+{
+ check_mi();
+ return mi->YResolution;
+}
+
+unsigned long current_color = 255;
+
+void vga_setrgbcolor(int r,int g,int b)
+{
+ DOSMesa->red = r;
+ DOSMesa->green = g ;
+ DOSMesa->blue = b ;
+ current_color = SV_rgbColor(r,g,b);
+}
+
+void vga_setcolor(int index)
+{
+ DOSMesa->index = index;
+ current_color = index;
+}
+
+void vga_drawpixel(x,y)
+{
+ SV_putPixel(x,y,current_color);
+}
+
+/* TODO: */
+int vga_getpixel(x,y)
+{
+/* return (int)SV_getPixel(x,y); */
+ fprintf(stderr,"vga_getpixel: Not implemented yet\n");
+ return 1;
+}
+
+/* End of UNIVBE section */
+#endif
+
+/* Scitechs MegaGraphicsLibrary http://www.scitechsoft.com/ */
+
+#if defined(MGL)
+
+/* MGL support */
+struct MI {
+ unsigned short BitsPerPixel;
+ unsigned long XResolution;
+ unsigned long YResolution;
+};
+
+struct MI*mi;
+
+static MGLDC*DC;
+static int activePage = 0;
+static int visualPage = 1;
+static int modeNumber = 0;
+
+void set_video_mode(unsigned short xres,unsigned short yres,char mode)
+{
+ int i,driver = grDETECT,dmode = grDETECT;
+ event_t evt;
+
+ /* Start the MGL with only the SVGA 16m driver active */
+ MGL_registerDriver(MGL_SVGA16NAME,SVGA16_driver);
+ if (!MGL_init(&driver,&dmode,"..\\..\\"))
+ MGL_fatalError(MGL_errorMsg(MGL_result()));
+ if ((DC = MGL_createDisplayDC(false)) == NULL)
+ MGL_fatalError(MGL_errorMsg(MGL_result()));
+ MGL_makeCurrentDC(DC);
+}
+
+/*
+ This is problematic as we don`t know what resolution the user program
+ wants when we reach here. This is why the 256 colour and HiColour modes
+ should be the same resolution, perhaps i`ll make this an environment
+ variable
+ */
+
+#define MGL_HICOLOUR_MODE 0
+
+
+void check_mi(void)
+{
+ if(mi!=0) return;
+
+ if(DC==NULL) {
+// DC = SV_init( TRUE );
+ }
+
+ if(modeNumber == 0 ) {
+ modeNumber = MGL_HICOLOUR_MODE;
+ }
+
+// SV_getModeInfo(modeNumber,mi);
+
+ return;
+}
+
+void restore_video_mode(void)
+{
+ MGL_exit();
+}
+
+void vga_clear(void)
+{
+ MGL_clearDevice();
+}
+
+void vga_flip(void)
+{
+ activePage = 1-activePage;
+ visualPage = 1-activePage;
+
+// SV_setActivePage(activePage);
+
+ /*
+ Change false to true if you`re getting flickering
+ even in double buffer mode, ( sets wait for Vertical retrace )
+ */
+// SV_setVisualPage(visualPage,false);
+}
+
+int vga_getcolors(void)
+{
+ check_mi();
+ switch ( mi->BitsPerPixel ) {
+ case 8:
+ return 256;
+ case 15:
+ case 16:
+ return 32768;
+ default:
+ return 64000;
+ }
+}
+
+int vga_getxdim(void)
+{
+ check_mi();
+ return mi->XResolution;
+}
+
+int vga_getydim(void)
+{
+ check_mi();
+ return mi->YResolution;
+}
+
+unsigned long current_color = 255;
+
+void vga_setrgbcolor(int r,int g,int b)
+{
+ DOSMesa->red = r;
+ DOSMesa->green = g ;
+ DOSMesa->blue = b ;
+ current_color = MGL_rgbColor(DC,r,g,b);
+}
+
+void vga_setcolor(int index)
+{
+ DOSMesa->index = index;
+ current_color = index;
+}
+
+void vga_drawpixel(x,y)
+{
+ MGL_pixelCoord(x,y);
+}
+
+/* TODO: */
+int vga_getpixel(x,y)
+{
+/* return (int)SV_getPixel(x,y); */
+ fprintf(stderr,"vga_getpixel: Not implemented yet\n");
+ return 1;
+}
+
+/* End of UNIVBE section */
+#endif
+
+#ifdef GLIDE
+
+/* GLIDE support */
+
+static GrHwConfiguration hwconfig;
+
+void set_video_mode(unsigned short x,unsigned short y,char mode)
+{
+ grGlideInit();
+ if( grSstQueryHardware( &hwconfig ) ) {
+ grSstSelect( 0 ) ;
+ if( !grSstOpen( GLIDE_MODE,
+ GR_REFRESH_60Hz,
+ GR_COLORFORMAT_ABGR,
+ GR_ORIGIN_UPPER_LEFT,
+ GR_SMOOTHING_ENABLE,
+ 2 ) ) {
+ fprintf(stderr,"Detected 3DFX board, but couldn`t initialize!");
+ exit(1);
+ }
+
+ grBufferClear( 0, 0, GR_WDEPTHVALUE_FARTHEST);
+
+ grDisableAllEffects();
+ atexit( glideshutdown );
+
+// guColorCombineFunction( GR_COLORCOMBINE_ITRGB );
+// grTexCombineFunction( GR_TMU0, GR_TEXTURECOMBINE_ZERO);
+ }
+}
+
+void restore_video_mode(void)
+{
+}
+
+static void glideshutdown( void )
+{
+ grGlideShutdown() ;
+}
+
+void vga_clear(void)
+{
+ grBufferSwap(0);
+ grBufferClear( 0, 0, GR_WDEPTHVALUE_FARTHEST);
+}
+
+void vga_flip(void)
+{
+}
+
+int vga_getcolors(void)
+{
+ return 32768;
+}
+
+int vga_getxdim(void)
+{
+#if GLIDE_MODE == GR_RESOLUTION_800x600
+ return 800;
+#else
+ return 640;
+#endif
+}
+
+int vga_getydim(void)
+{
+#if GLIDE_MODE == GR_RESOLUTION_800x600
+ return 600;
+#else
+ return 480;
+#endif
+}
+
+unsigned long current_color = 255;
+
+void vga_setrgbcolor(int r,int g,int b)
+{
+ DOSMesa->red = r;
+ DOSMesa->green = g ;
+ DOSMesa->blue = b ;
+}
+
+void vga_setcolor(int index)
+{
+ DOSMesa->index = index;
+}
+
+void vga_drawpixel(x,y)
+{
+
+ gr_vtx.x = x;
+ gr_vtx.y = y;
+ gr_vtx.z = 0;
+ gr_vtx.r = DOSMesa->red;
+ gr_vtx.g = DOSMesa->green;
+ gr_vtx.b = DOSMesa->blue;
+
+ grDrawPoint( &gr_vtx );
+}
+
+static void fast_tri(GLcontext *ctx,GLuint v0, GLuint v1, GLuint v2, GLuint pv )
+{
+ struct vertex_buffer *VB = ctx->VB;
+
+ gr_vtx.z = 0;
+ gr_vtx1.z = 0;
+ gr_vtx2.z = 0;
+
+ if (VB->MonoColor) {
+ gr_vtx.r = DOSMesa->red;
+ gr_vtx.g = DOSMesa->green;
+ gr_vtx.b = DOSMesa->blue;
+ gr_vtx1.r = DOSMesa->red;
+ gr_vtx1.g = DOSMesa->green;
+ gr_vtx1.b = DOSMesa->blue;
+ gr_vtx2.r = DOSMesa->red;
+ gr_vtx2.g = DOSMesa->green;
+ gr_vtx2.b = DOSMesa->blue;
+ } else {
+ if(ctx->Light.ShadeModel == GL_SMOOTH ) {
+ gr_vtx.r = FixedToInt( VB->Color[v0][0] );
+ gr_vtx.g = FixedToInt( VB->Color[v0][1] );
+ gr_vtx.b = FixedToInt( VB->Color[v0][2] );
+
+ gr_vtx1.r = FixedToInt( VB->Color[v1][0] );
+ gr_vtx1.g = FixedToInt( VB->Color[v1][1] );
+ gr_vtx1.b = FixedToInt( VB->Color[v1][2] );
+
+ gr_vtx2.r = FixedToInt( VB->Color[v2][0] );
+ gr_vtx2.g = FixedToInt( VB->Color[v2][1] );
+ gr_vtx2.b = FixedToInt( VB->Color[v2][2] );
+ } else {
+ gr_vtx.r = VB->Color[pv][0];
+ gr_vtx.g = VB->Color[pv][1];
+ gr_vtx.b = VB->Color[pv][2];
+
+ gr_vtx1.r = VB->Color[pv][0];
+ gr_vtx1.g = VB->Color[pv][1];
+ gr_vtx1.b = VB->Color[pv][2];
+
+ gr_vtx2.r = VB->Color[pv][0];
+ gr_vtx2.g = VB->Color[pv][1];
+ gr_vtx2.b = VB->Color[pv][2];
+ }
+ }
+
+ gr_vtx.x = (VB->Win[v0][0] );
+ gr_vtx.y = FLIP( (VB->Win[v0][1] ) );
+ gr_vtx1.x = (VB->Win[v1][0] );
+ gr_vtx1.y = FLIP( (VB->Win[v1][1] ) );
+ gr_vtx2.x = (VB->Win[v2][0] );
+ gr_vtx2.y = FLIP( (VB->Win[v2][1] ) );
+
+ if(gr_vtx.x <0 || gr_vtx.x > 639 )
+ return;
+ if(gr_vtx1.x <0 || gr_vtx1.x > 639 )
+ return;
+ if(gr_vtx2.x <0 || gr_vtx2.x > 639 )
+ return;
+
+ if(gr_vtx.y <0 || gr_vtx.y > 479 )
+ return;
+ if(gr_vtx1.y <0 || gr_vtx1.y > 479 )
+ return;
+ if(gr_vtx2.y <0 || gr_vtx2.y > 479 )
+ return;
+
+ grDrawTriangle( &gr_vtx,&gr_vtx1,&gr_vtx2);
+}
+
+void fast_plot(GLcontext *ctx,GLuint first,GLuint last )
+{
+ struct vertex_buffer *VB = ctx->VB;
+ register GLuint i;
+
+ if(VB->MonoColor) {
+ /* all same color */
+
+ gr_vtx.r = DOSMesa->red;
+ gr_vtx.g = DOSMesa->green;
+ gr_vtx.b = DOSMesa->blue;
+
+ for(i=first;i<last;i++) {
+ if(VB->ClipMask[i]==0) {
+ gr_vtx.x = VB->Win[i][0];
+ gr_vtx.y = FLIP(VB->Win[i][1]);
+ }
+ }
+ }
+}
+
+/* TODO: */
+int vga_getpixel(x,y)
+{
+/* return (int)SV_getPixel(x,y); */
+ fprintf(stderr,"vga_getpixel: Not implemented yet\n");
+ return 1;
+}
+
+/* End of GLIDE section */
+
+#endif // GLIDE
+/**********************************************************************/
+/***** Miscellaneous functions *****/
+/**********************************************************************/
+
+
+static void get_buffer_size( GLcontext *ctx, GLuint *width, GLuint *height )
+{
+ *width = DOSMesa->width = vga_getxdim();
+ *height = DOSMesa->height = vga_getydim();
+}
+
+
+/* Set current color index */
+static void set_index( GLcontext *ctx, GLuint index )
+{
+ DOSMesa->index = index;
+ /*vga_setcolor( index );*/
+}
+
+
+/* Set current drawing color */
+static void set_color( GLcontext *ctx,
+ GLubyte red, GLubyte green,
+ GLubyte blue, GLubyte alpha )
+{
+ DOSMesa->red = red;
+ DOSMesa->green = green;
+ DOSMesa->blue = blue;
+ vga_setrgbcolor( red, green, blue );
+}
+
+
+static void clear_index( GLcontext *ctx, GLuint index )
+{
+ /* TODO: Implements glClearIndex() */
+}
+
+
+static void clear_color( GLcontext *ctx,
+ GLubyte red, GLubyte green,
+ GLubyte blue, GLubyte alpha )
+{
+ /* TODO: Implements glClearColor() */
+}
+
+
+static void clear( GLcontext *ctx,
+ GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ vga_clear();
+}
+
+
+static GLboolean set_buffer( GLcontext *ctx,
+ GLenum mode )
+{
+ /* TODO: implement double buffering and use this function to select */
+ /* between front and back buffers. */
+ if (buffer == GL_FRONT_LEFT)
+ return GL_TRUE;
+ else if (buffer == GL_BACK_LEFT)
+ return GL_TRUE;
+ else
+ return GL_FALSE;
+}
+
+
+
+
+/**********************************************************************/
+/***** Write spans of pixels *****/
+/**********************************************************************/
+
+
+static void write_index_span( GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLuint index[],
+ const GLubyte mask[] )
+{
+ int i;
+ y = FLIP(y);
+#ifdef UNIVBE
+ SV_beginPixel();
+#endif
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+#ifdef UNIVBE
+ SV_putPixelFast(x,y,current_color);
+#else
+ vga_setcolor( index[i] );
+ vga_drawpixel( x, y );
+#endif
+ }
+ }
+
+#ifdef UNIVBE
+ SV_endPixel();
+#endif
+
+}
+
+
+
+static void write_monoindex_span( GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte mask[] )
+{
+ int i;
+ y = FLIP(y);
+ /* use current color index */
+ vga_setcolor( DOSMesa->index );
+#ifdef UNIVBE
+ SV_beginPixel();
+#endif
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+#ifdef UNIVBE
+ SV_putPixelFast(x,y,current_color);
+#else
+ vga_drawpixel( x, y );
+#endif
+ }
+ }
+#ifdef UNIVBE
+ SV_endPixel();
+#endif
+}
+
+
+
+static void write_color_span( GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte red[], const GLubyte green[],
+ const GLubyte blue[], const GLubyte alpha[],
+ const GLubyte mask[] )
+{
+ int i;
+ y=FLIP(y);
+#ifdef UNIVBE
+ SV_beginPixel();
+#endif
+ if (mask) {
+ /* draw some pixels */
+ for (i=0; i<n; i++, x++) {
+ if (mask[i]) {
+#ifdef UNIVBE
+ SV_putPixelFast(x,y,SV_rgbColor(red[i], green[i], blue[i]) );
+#else
+ vga_setrgbcolor( red[i], green[i], blue[i] );
+ vga_drawpixel( x, y );
+#endif
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0; i<n; i++, x++) {
+#ifdef UNIVBE
+ SV_putPixelFast(x,y,SV_rgbColor(red[i], green[i], blue[i]) );
+#else
+ vga_setrgbcolor( red[i], green[i], blue[i] );
+ vga_drawpixel( x, y );
+#endif
+ }
+ }
+#ifdef UNIVBE
+ SV_endPixel();
+#endif
+}
+
+
+
+static void write_monocolor_span( GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte mask[])
+{
+ int i;
+ y=FLIP(y);
+#ifdef UNIVBE
+ SV_beginPixel();
+#endif
+ /* use current rgb color */
+ vga_setrgbcolor( DOSMesa->red, DOSMesa->green, DOSMesa->blue );
+ for (i=0; i<n; i++, x++) {
+ if (mask[i]) {
+#ifdef UNIVBE
+ SV_putPixelFast(x,y,current_color);
+#else
+ vga_drawpixel( x, y );
+#endif
+ }
+ }
+#ifdef UNIVBE
+ SV_endPixel();
+#endif
+}
+
+
+
+/**********************************************************************/
+/***** Read spans of pixels *****/
+/**********************************************************************/
+
+
+static void read_index_span( GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLuint index[])
+{
+ int i;
+ y = FLIP(y);
+ for (i=0; i<n; i++,x++) {
+ index[i] = vga_getpixel( x, y );
+ }
+}
+
+
+
+static void read_color_span( GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ GLubyte red[], GLubyte green[],
+ GLubyte blue[], GLubyte alpha[] )
+{
+ int i;
+ for (i=0; i<n; i++, x++) {
+ /* TODO */
+ }
+}
+
+
+
+/**********************************************************************/
+/***** Write arrays of pixels *****/
+/**********************************************************************/
+
+
+static void write_index_pixels( GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLuint index[], const GLubyte mask[] )
+{
+ int i;
+#ifdef UNIVBE
+ SV_beginPixel();
+#endif
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+#ifdef UNIVBE
+ SV_putPixelFast(x[i], FLIP(y[i]), index[i] );
+#else
+ vga_setcolor( index[i] );
+ vga_drawpixel( x[i], FLIP(y[i]) );
+#endif
+ }
+ }
+#ifdef UNIVBE
+ SV_endPixel();
+#endif
+}
+
+
+
+static void write_monoindex_pixels( GLcontext *ctx,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLubyte mask[] )
+{
+ int i;
+ /* use current color index */
+ vga_setcolor( DOSMesa->index );
+#ifdef UNIVBE
+ SV_beginPixel();
+#endif
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+#ifdef UNIVBE
+ SV_putPixelFast(x[i], FLIP(y[i]), DOSMesa->index);
+#else
+ vga_drawpixel( x[i], FLIP(y[i]) );
+#endif
+ }
+ }
+#ifdef UNIVBE
+ SV_endPixel();
+#endif
+}
+
+
+
+static void write_color_pixels( GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte r[], const GLubyte g[],
+ const GLubyte b[], const GLubyte a[],
+ const GLubyte mask[] )
+{
+ int i;
+#ifdef UNIVBE
+ SV_beginPixel();
+#endif
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+#ifdef UNIVBE
+ SV_putPixelFast(x[i], FLIP(y[i]), SV_rgbColor(r[i], g[i], b[i]) );
+#else
+ vga_setrgbcolor( r[i], g[i], b[i] );
+ vga_drawpixel( x[i], FLIP(y[i]) );
+#endif
+ }
+ }
+#ifdef UNIVBE
+ SV_endPixel();
+#endif
+}
+
+static void write_monocolor_pixels( GLcontext *ctx,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLubyte mask[] )
+{
+ int i;
+ /* use current rgb color */
+ vga_setrgbcolor( DOSMesa->red, DOSMesa->green, DOSMesa->blue );
+#ifdef UNIVBE
+ SV_beginPixel();
+#endif
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+#ifdef UNIVBE
+ SV_putPixelFast(x[i], FLIP(y[i]), current_color );
+#else
+ vga_drawpixel( x[i], FLIP(y[i]) );
+#endif
+ }
+ }
+#ifdef UNIVBE
+ SV_endPixel();
+#endif
+}
+
+/**********************************************************************/
+/***** Read arrays of pixels *****/
+/**********************************************************************/
+
+/* Read an array of color index pixels. */
+static void read_index_pixels( GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint index[], const GLubyte mask[] )
+{
+ int i;
+ for (i=0; i<n; i++) {
+ index[i] = vga_getpixel( x[i], FLIP(y[i]) );
+ }
+}
+
+
+
+static void read_color_pixels( GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte red[], GLubyte green[],
+ GLubyte blue[], GLubyte alpha[],
+ const GLubyte mask[] )
+{
+ /* TODO */
+}
+
+static void DOSmesa_setup_DD_pointers( GLcontext *ctx )
+{
+ /* Initialize all the pointers in the DD struct. Do this whenever */
+ /* a new context is made current or we change buffers via set_buffer! */
+
+ ctx->Driver.UpdateState = DOSmesa_setup_DD_pointers;
+
+ ctx->Driver.ClearIndex = clear_index;
+ ctx->Driver.ClearColor = clear_color;
+ ctx->Driver.Clear = clear;
+
+ ctx->Driver.Index = set_index;
+ ctx->Driver.Color = set_color;
+
+ ctx->Driver.SetBuffer = set_buffer;
+ ctx->Driver.GetBufferSize = get_buffer_size;
+
+ ctx->Driver.PointsFunc = choose_points_function();
+ ctx->Driver.LineFunc = choose_line_function();
+ ctx->Driver.TriangleFunc = choose_triangle_function();
+
+
+ /* Pixel/span writing functions: */
+ /* TODO: use different funcs for 8, 16, 32-bit depths */
+ ctx->Driver.WriteColorSpan = write_color_span;
+ ctx->Driver.WriteMonocolorSpan = write_monocolor_span;
+ ctx->Driver.WriteColorPixels = write_color_pixels;
+ ctx->Driver.WriteMonocolorPixels = write_monocolor_pixels;
+ ctx->Driver.WriteIndexSpan = write_index_span;
+ ctx->Driver.WriteMonoindexSpan = write_monoindex_span;
+ ctx->Driver.WriteIndexPixels = write_index_pixels;
+ ctx->Driver.WriteMonoindexPixels = write_monoindex_pixels;
+
+ /* Pixel/span reading functions: */
+ /* TODO: use different funcs for 8, 16, 32-bit depths */
+ ctx->Driver.ReadIndexSpan = read_index_span;
+ ctx->Driver.ReadColorSpan = read_color_span;
+ ctx->Driver.ReadIndexPixels = read_index_pixels;
+ ctx->Driver.ReadColorPixels = read_color_pixels;
+}
+
+/*
+ * Create a new VGA/Mesa context and return a handle to it.
+ */
+DOSMesaContext DOSMesaCreateContext( void )
+{
+ DOSMesaContext ctx;
+ GLboolean rgb_flag;
+ GLfloat redscale, greenscale, bluescale, alphascale;
+ GLboolean db_flag = GL_FALSE;
+ GLboolean alpha_flag = GL_FALSE;
+ int colors;
+ GLint index_bits;
+ GLint redbits, greenbits, bluebits, alphabits;
+
+#if !defined(UNIVBE) && !defined(GLIDE) && !defined(MGL)
+ video_buffer = (unsigned char *) malloc( vga_getxdim() * vga_getydim() );
+
+ memset(video_buffer,0, vga_getxdim() * vga_getydim() );
+
+ memset(rgbtable,0,sizeof( rgbtable ) );
+#endif
+
+#if defined( DJGPP ) && !defined(UNIVBE) && !defined(GLIDE)
+ dos_seg = _go32_conventional_mem_selector();
+#endif
+
+ /* determine if we're in RGB or color index mode */
+ colors = vga_getcolors();
+ if (colors==32768) {
+ rgb_flag = GL_TRUE;
+ redscale = greenscale = bluescale = alphascale = 255.0;
+ redbits = greenbits = bluebits = 8;
+ alphabits = 0;
+ index_bits = 0;
+ }
+ else if (colors==256) {
+ rgb_flag = GL_FALSE;
+ redscale = greenscale = bluescale = alphascale = 0.0;
+ redbits = greenbits = bluebits = alphabits = 0;
+ index_bits = 8;
+ }
+ else {
+ restore_video_mode();
+ fprintf(stderr,"[%d] >16 bit color not implemented yet!\n",colors);
+ return NULL;
+ }
+
+ ctx = (DOSMesaContext) calloc( 1, sizeof(struct DOSmesa_context) );
+ if (!ctx) {
+ return NULL;
+ }
+
+ ctx->gl_vis = gl_create_visual( rgb_flag,
+ alpha_flag,
+ db_flag,
+ 16, /* depth_size */
+ 8, /* stencil_size */
+ 16, /* accum_size */
+ index_bits,
+ redscale,
+ greenscale,
+ bluescale,
+ alphascale,
+ redbits, greenbits,
+ bluebits, alphabits);
+
+ ctx->gl_ctx = gl_create_context( ctx->gl_vis,
+ NULL, /* share list context */
+ (void *) ctx
+ );
+
+ ctx->gl_buffer = gl_create_framebuffer( ctx->gl_vis );
+
+ ctx->index = 1;
+ ctx->red = ctx->green = ctx->blue = 255;
+
+ ctx->width = ctx->height = 0; /* temporary until first "make-current" */
+
+ return ctx;
+}
+
+/*
+ * Destroy the given VGA/Mesa context.
+ */
+void DOSMesaDestroyContext( DOSMesaContext ctx )
+{
+ if (ctx) {
+ gl_destroy_visual( ctx->gl_vis );
+ gl_destroy_context( ctx->gl_ctx );
+ gl_destroy_framebuffer( ctx->gl_buffer );
+ free( ctx );
+ if (ctx==DOSMesa) {
+ DOSMesa = NULL;
+ }
+ }
+}
+
+
+
+/*
+ * Make the specified VGA/Mesa context the current one.
+ */
+void DOSMesaMakeCurrent( DOSMesaContext ctx )
+{
+ DOSMesa = ctx;
+ gl_make_current( ctx->gl_ctx, ctx->gl_buffer );
+ DOSmesa_setup_DD_pointers( ctx->gl_ctx );
+
+ if (ctx->width==0 || ctx->height==0) {
+ /* setup initial viewport */
+ ctx->width = vga_getxdim();
+ ctx->height = vga_getydim();
+ gl_Viewport( ctx->gl_ctx, 0, 0, ctx->width, ctx->height );
+ }
+}
+
+
+
+/*
+ * Return a handle to the current VGA/Mesa context.
+ */
+DOSMesaContext DOSMesaGetCurrentContext( void )
+{
+ return DOSMesa;
+}
+
+
+/*
+ * Swap front/back buffers for current context if double buffered.
+ */
+void DOSMesaSwapBuffers( void )
+{
+#if !defined(UNIVBE)
+/* Assume double buffering is available if in UNIVBE,
+ if it isn`t its taken care of anyway */
+// if (DOSMesa->gl_vis->DBflag)
+#endif
+ {
+ vga_flip();
+ }
+}
+
+
+#else
+
+/*
+ * Need this to provide at least one external definition when DOS is
+ * not defined on the compiler command line.
+ */
+
+int gl_DOS_dummy_function(void)
+{
+ return 0;
+}
+
+#endif /*DOS*/
+
diff --git a/src/mesa/drivers/ggi/ggimesa.conf.in b/src/mesa/drivers/ggi/ggimesa.conf.in
new file mode 100644
index 0000000000..72132334fd
--- /dev/null
+++ b/src/mesa/drivers/ggi/ggimesa.conf.in
@@ -0,0 +1,13 @@
+# GGIMesa global configuration
+.root: @ggi_libdir@/ggi/mesa
+
+generic-stubs-mesa default/stubs.so
+generic-linear-8-mesa default/linear_8.so
+generic-linear-15-mesa default/linear_15.so
+generic-linear-16-mesa default/linear_16.so
+generic-linear-24-mesa default/linear_24.so
+generic-linear-32-mesa default/linear_32.so
+
+display-fbdev-mesa display/fbdev.so
+
+# .include @ggi_confdir@/ggi/mesa/targets/fbdev.conf
diff --git a/src/mesa/drivers/glide/fxapi.c b/src/mesa/drivers/glide/fxapi.c
new file mode 100644
index 0000000000..fbc586e757
--- /dev/null
+++ b/src/mesa/drivers/glide/fxapi.c
@@ -0,0 +1,1411 @@
+/* -*- mode: C; tab-width:8; -*-
+
+ fxapi.c - 3Dfx VooDoo/Mesa interface
+*/
+
+/*
+ * 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.
+ *
+ ********************************************************************
+ *
+ * Function names:
+ * fxMesa.... (The driver API)
+ * fxDD.... (Mesa device driver functions)
+ * fxTM.... (Texture manager functions)
+ * fxSetup.... (Voodoo units setup functions)
+ * fx.... (Internal driver functions)
+ *
+ * Data type names:
+ * fxMesa.... (Public driver data types)
+ * tfx.... (Private driver data types)
+ *
+ ********************************************************************
+ *
+ * V0.30 - David Bucciarelli (davibu@tin.it) Humanware s.r.l.
+ * - introduced a new MESA_GLX_FX related behavior
+ * - the Glide fog table was built in a wrong way (using
+ * gu* Glide function). Added the code for building the
+ * table following the OpenGL specs. Thanks to Steve Baker
+ * for highlighting the problem.
+ * - fixed few problems in my and Keith's fxDDClear code
+ * - merged my code with the Keith's one
+ * - used the new BlendFunc Mesa device driver function
+ * - used the new AlphaFunc Mesa device driver function
+ * - used the new Enable Mesa device driver function
+ * - fixed a bug related to fog in the Mesa core. Fog
+ * were applied two times: at vertex level and at fragment
+ * level (thanks to Steve Baker for reporting the problem)
+ * - glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE) now works
+ * (thanks to Jiri Pop for reporting the problem)
+ * - the driver works fine with OpenGL Unreal
+ * - fixed a bug in the Mesa core clipping code (related
+ * to the q texture coordinate)
+ * - introduced the support for the q texture coordinate
+ *
+ * Keith Whitwell (keithw@cableinet.co.uk)
+ * - optimized the driver and written all the new code
+ * required by the new Mesa-3.1 device driver API
+ * and by the new Mesa-3.1 core changes
+ * - written the cva support and many other stuff
+ *
+ * Brian Paul (brian_paul@avid.com) Avid Technology
+ * - fixed display list share bug for MESA_GLX_FX = window/fullscreen
+ * - fixed glClear/gl...Mask related problem
+ *
+ * Bert Schoenwaelder (bert@prinz-atm.CS.Uni-Magdeburg.De)
+ * - the driver is now able to sleep when waiting for the completation
+ * of multiple swapbuffer operations instead of wasting
+ * CPU time (NOTE: you must uncomment the lines in the
+ * fxMesaSwapBuffers function in order to enable this option)
+ *
+ * Eero Pajarre (epajarre@koti.tpo.fi)
+ * - enabled the macro FLOAT_COLOR_TO_UBYTE_COLOR under
+ * windows
+ * - written an asm x86 optimized float->integer conversions
+ * for windows
+ *
+ * Theodore Jump (tjump@cais.com)
+ * - fixed a small problem in the __wglMonitor function of the
+ * wgl emulator
+ * - written the in-window-rendering hack support for windows
+ * and Vooodoo1/2 cards
+ *
+ * V0.29 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
+ * - included in Mesa-3.0
+ * - now glGetString(GL_RENDERER) returns more information
+ * about the hardware configuration: "Mesa Glide <version>
+ * <Voodoo_Graphics|Voodoo_Rush|UNKNOWN> <num> CARD/<num> FB/
+ * <num> TM/<num> TMU/<NOSLI|SLI>"
+ * where: <num> CARD is the card used for the current context,
+ * <num> FB is the number of MB for the framebuffer,
+ * <num> TM is the number of MB for the texture memory,
+ * <num> TMU is the number of TMU. You can try to run
+ * Mesa/demos/glinfo in order to have an example of the
+ * output
+ * - fixed a problem of the WGL emulator with the
+ * OpenGL Optimizer 1.1 (thanks to Erwin Coumans for
+ * the bug report)
+ * - fixed some bug in the fxwgl.c code (thanks to
+ * Peter Pettersson for a patch and a bug report)
+ *
+ * Theodore Jump (tjump@cais.com)
+ * - written the SST_DUALHEAD support in the WGL emulator
+ *
+ * Daryll Strauss (daryll@harlot.rb.ca.us)
+ * - fixed the Voodoo Rush support for the in window rendering
+ *
+ * V0.28 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
+ * - the only supported multitexture functions are GL_MODULATE
+ * for texture set 0 and GL_MODULATE for texture set 1. In
+ * all other cases, the driver falls back to pure software
+ * rendering
+ * - written the support for the new GL_EXT_multitexture
+ * - written the DD_MAX_TEXTURE_COORD_SETS support in the
+ * fxDDGetParameteri() function
+ * - the driver falls back to pure software rendering when
+ * texture mapping function is GL_BLEND
+ *
+ * V0.27 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
+ * - inluded in the Mesa-3.0beta5
+ * - written a smal extension (GL_FXMESA_global_texture_lod_bias) in
+ * order to expose the LOD bias related Glide function
+ * - fixed a bug fxDDWriteMonoRGBAPixels()
+ * - the driver is now able to fallback to software rendering in
+ * any case not directly supported by the hardware
+ * - written the support for enabling/disabling dithering
+ * - the in-window-rendering hack now works with any X11 screen
+ * depth
+ * - fixed a problem related to color/depth/alpha buffer clears
+ * - fixed a problem when clearing buffer for a context with the
+ * alpha buffer
+ * - fixed a problem in the fxTMReloadSubMipMapLevel() function,
+ * I have forget a "break;" (thanks to Joe Waters for the bug report)
+ * - fixed a problem in the color format for the in window
+ * rendering hack
+ * - written the fxDDReadRGBAPixels function
+ * - written the fxDDDepthTestPixelsGeneric function
+ * - written the fxDDDepthTestSpanGeneric function
+ * - written the fxDDWriteMonoRGBAPixels function
+ * - written the fxDDWriteRGBAPixels function
+ * - removed the multitexture emulation code for Voodoo board
+ * with only one TMU
+ *
+ * Chris Prince <cprince@cs.washington.edu>
+ * - fixed a new bug in the wglUseFontBitmaps code
+ *
+ * Ralf Knoesel (rknoesel@Stormfront.com)
+ * - fixed a bug in the wglUseFontBitmaps code
+ *
+ * Rune Hasvold (runeh@ifi.uio.no)
+ * - fixed a problem related to the aux usage in the fxBestResolution
+ * function
+ * - fixed the order of pixel formats in the WGL emulator
+ *
+ * Fredrik Hubinette (hubbe@hubbe.net)
+ * - the driver shutdown the Glide for most common signals
+ *
+ * V0.26 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
+ * - included in the Mesa-3.0beta4
+ * - fixed a problem related to a my optimization for the Rune's
+ * pixel-span optimization
+ * - fixed a problem related to fxDDSetNearFar() and ctx->ProjectionMatrixType
+ * (thanks to Ben "Ctrl-Alt-Delete" and the Raul Alonso's ssystem)
+ * - fixed a small bug in the Rune's pixel-span optimization
+ * - fixed a problem with GL_CCW (thanks to Curt Olson for and example
+ * of the problem)
+ * - grVertex setup code is now ready for the internal thread support
+ * - fixed a no used optimization with clipped vertices in
+ * grVertex setup code
+ * - fixed a problem in the GL_LIGHT_MODEL_TWO_SIDE support (thanks
+ * to Patrick H. Madden for a complete example of the bug)
+ *
+ * Rune Hasvold (runeh@ifi.uio.no)
+ * - highly optimized the driver functions for writing pixel
+ * span (2-3 times faster !)
+ *
+ * Axel W. Volley (volley@acm.org) Krauss-Maffei Wehrtechnik
+ * - written the fxDDReadDepthSpanFloat() and fxDDReadDepthSpanInt()
+ * functions
+ *
+ * V0.25 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
+ * - fixed a problem with Voodoo boards with only one TMU
+ * - fixed a bug in the fxMesaCreateContext()
+ * - now the GL_FRONT_AND_BACK works fine also with
+ * the alpha buffer and/or antialiasing
+ * - written the support for GL_FRONT_AND_BACK drawing but
+ * it doesn't works with the alpha buffer and/or antialiasing
+ * - fixed some bug in the Mesa core for glCopyTexSubImage
+ * and glCopyTexImage functions (thanks to Mike Connell
+ * for an example of the problem)
+ * - make some small optimizations in the Mesa core in order
+ * to save same driver call and state change for not very
+ * well written applications
+ * - introduced the NEW_DRVSTATE and make other optimizations
+ * for minimizing state changes
+ * - made a lot of optimizations in order to minimize state
+ * changes
+ * - it isn't more possible to create a context with the
+ * depth buffer and the stancil buffer (it isn't yet supported)
+ * - now the partial support for the Multitexture extension
+ * works with Quake2 for windows
+ * - vertex snap is not longer used for the Voodoo2 (FX_V2
+ * must be defined)
+ * - done a lot of cleanup in the fxsetup.c file
+ * - now the partial support for the Multitexture extension
+ * works with GLQuake for windows
+ *
+ * Dieter Nuetzel (nuetzel@kogs.informatik.uni-hamburg.de) University of Hamburg
+ * - fixed a problem in the asm code for Linux of the fxvsetup.c file
+ * highlighted by the binutils-2.8.1.0.29. 'fildw' asm instruction
+ * changed in 'fild'
+ *
+ * Kevin Hester (kevinh@glassworks.net)
+ * - written the wglUseFontBitmaps() function in the WGL emulator
+ *
+ * V0.24 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
+ * - now the drive always uses per fragment fog
+ * - written a small optimization in the points drawing function
+ * - written the support for trilinear filtering with 2 TMUs
+ * - written the first partial support for the Multitexture extension.
+ * This task is quite hard because the color combine units work after
+ * the two texture combine units and not before as required by the
+ * Multitexture extension
+ * - written a workaround in fxBestResolution() in order to solve a
+ * problem with bzflag (it asks for 1x1 window !)
+ * - changed the fxBestResolution() behavior. It now returns the larger
+ * screen resolution supported by the hardware (instead of 640x480)
+ * when it is unable to find an appropriate resolution that is large
+ * enough for the requested size
+ * - the driver is now able to use also the texture memory attached to
+ * second TMU
+ * - the texture memory manager is now able to work with two TMUs and
+ * store texture maps in the memory attached to TMU0, TMU1 or to split
+ * the mimpmap levels across TMUs in order to support trilinear filtering
+ * - I have bought a Voodoo2 board !
+ * - the amount of frambuffer ram is now doubled when an SLI configuration
+ * is detected
+ * - solved a problem related to the fxDDTexParam() and fxTexInvalidate()
+ * functions (thanks to Rune Hasvold for highlighting the problem)
+ * - done some cleanup in the fxvsetup.c file, written
+ * the FXVSETUP_FUNC macro
+ * - done a lot of cleanup in data types and field names
+ *
+ * Rune Hasvold (runeh@ifi.uio.no)
+ * - written the support for a right management of the auxiliary buffer.
+ * You can now use an 800x600 screen without the depth and alpha
+ * buffer
+ * - written the support for a new pixel format (without the depth
+ * and alpha buffer) in the WGL emulator
+ * - fixed a bug in the window version of the GLUT (it was ever asking
+ * for depth buffer)
+ *
+ * V0.23 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
+ * - included in the Mesa-3.0beta2 release
+ * - written the support for the OpenGL 1.2 GL_TEXTURE_BASE_LEVEL
+ * and GL_TEXTURE_MAX_LEVEL
+ * - rewritten several functions for a more clean support of texture
+ * mapping and in order to solve some bug
+ * - the accumulation buffer works (it is bit slow beacuase it requires
+ * to read/write from/to the Voodoo frame buffer but it works)
+ * - fixed a bug in the fxDDReadRGBASpan driver function (the R and
+ * B channels were read in the wrong order). Thanks to Jason Heym
+ * for highlighting the problem
+ * - written the support for multiple contexts on multiple boards.
+ * you can now use the Mesa/Voodoo with multiple Voodoo Graphics
+ * boards (for example with multiple screens or an HMD)
+ * - the fxBestResolution() now check all available resolutions
+ * and it is able to check the amount of framebuffer memory
+ * before return a resolution
+ * - modified the GLX/X11 driver in order to support all the
+ * resolution available
+ * - changed all function names. They should be now a bit more
+ * readable
+ * - written the Glide grVertex setup code for two TMU or
+ * for Multitexture support with emulationa dn one TMU
+ * - written the support for the new Mesa driver
+ * function GetParametri
+ * - small optimization/clean up in the texbind() function
+ * - fixed a FPU precision problem for glOrtho and texture
+ * mapping (thanks to Antti Juhani Huovilainen for an example
+ * of the problem)
+ * - written some small SGI OpenGL emulation code for the wgl,
+ * the OpenGL Optimizer and Cosmo3D work fine under windows !
+ * - moved the point/line/triangle/quad support in the fxmesa7.c
+ * - fixed a bug in the clear_color_depth() (thanks to Henk Kok
+ * for an example of the problem)
+ * - written a small workaround for Linux GLQuake, it asks
+ * for the alpha buffer and the depth buffer at the some time
+ * (but it never uses the alpha buffer)
+ * - checked the antialiasing points, lines and polygons support.
+ * It works fine
+ * - written the support for standard OpenGL antialiasing using
+ * blending. Lines support works fine (tested with BZflag)
+ * while I have still to check the polygons and points support
+ * - written the support for the alpha buffer. The driver is now
+ * able to use the Voodoo auxiliary buffer as an alpha buffer
+ * instead of a depth buffer. Also all the OpenGL blending
+ * modes are now supported. But you can't request a context
+ * with an alpha buffer AND a depth buffer at the some time
+ * (this is an hardware limitation)
+ * - written the support for switching between the fullscreen
+ * rendering and the in-window-rendering hack on the fly
+ *
+ * Rune Hasvold (runeh@ifi.uio.no)
+ * - fixed a bug in the texparam() function
+ *
+ * Brian Paul (brianp@elastic.avid.com) Avid Technology
+ * - sources accomodated for the new Mesa 3.0beta1
+ *
+ * V0.22 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
+ * - included with some v0.23 bug fix in the final release
+ * of the Mesa-2.6
+ * - written the support for the MESA_WGL_FX env. var. but
+ * not tested because I have only Voodoo Graphics boards
+ * - fixed a bug in the backface culling code
+ * (thanks to David Farrell for an example of the problem)
+ * - fixed the "Quake2 elevator" bug
+ * - GL_POLYGONS with 3/4 vertices are now drawn as
+ * GL_TRIANLGES/GL_QUADS (a small optimization for GLQuake)
+ * - fixed a bug in fxmesa6.h for GL_LINE_LOOP
+ * - fixed a NearFarStack bug in the Mesa when applications
+ * directly call glLoadMatrix to load a projection matrix
+ * - done some cleanup in the fxmesa2.c file
+ * - the driver no longer translates the texture maps
+ * when the Mesa internal format and the Voodoo
+ * format are the some (usefull for 1 byte texture maps
+ * where the driver can directly use the Mesa texture
+ * map). Also the amount of used memory is halfed
+ * - fixed a bug for GL_DECAL and GL_RGBA
+ * - fixed a bug in the clear_color_depth()
+ * - tested the v0.22 with the Mesa-2.6beta2. Impressive
+ * performances improvement thanks to the new Josh's
+ * asm code (+10fps in the isosurf demo, +5fps in GLQuake
+ * TIMEREFRESH)
+ * - written a optimized version of the RenderVB Mesa driver
+ * function. The Voodoo driver is now able to upload polygons
+ * in the most common cases at a very good speed. Good
+ * performance improvement for large set of small polygons
+ * - optimized the asm code for setting up the color information
+ * in the Glide grVertex structure
+ * - fixed a bug in the fxmesa2.c asm code (the ClipMask[]
+ * wasn't working)
+ *
+ * Josh Vanderhoof (joshv@planet.net)
+ * - removed the flush() function because it isn't required
+ * - limited the maximum number of swapbuffers in the Voodoo
+ * commands FIFO (controlled by the env. var. MESA_FX_SWAP_PENDING)
+ *
+ * Holger Kleemiss (holger.kleemiss@metronet.de) STN Atlas Elektronik GmbH
+ * - applied some patch for the Voodoo Rush
+ *
+ * V0.21 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
+ * - the driver is now able to take advantage of the ClipMask[],
+ * ClipOrMask and ClipAndMask information also under Windows
+ * - introduced a new function in the Mesa driver interface
+ * ClearColorAndDepth(). Now the glClear() function is
+ * 2 times faster (!) when you have to clear the color buffer
+ * and the depth buffer at some time
+ * - written the first version of the fxRenderVB() driver
+ * function
+ * - optimized the glTexImage() path
+ * - removed the fxMesaTextureUsePalette() support
+ * - fixed a bug in the points support (thanks to David Farrell
+ * for an example of the problem)
+ * - written the optimized path for glSubTexImage(),
+ * introduced a new function in the Mesa driver interface
+ * TexSubImage(...)
+ * - fixed a bug for glColorMask and glDepthMask
+ * - the wbuffer is not more used. The Voodoo driver uses
+ * a standard 16bit zbuffer in all cases. It is more consistent
+ * and now GLQuake and GLQuake2test work also with a GL_ZTRICK 0
+ * - the driver is now able to take advantage of the ClipMask[],
+ * ClipOrMask and ClipAndMask information (under Linux);
+ * - rewritten the setup_fx_units() function, now the texture
+ * mapping support is compliant to the OpenGL specs (GL_BLEND
+ * support is still missing). The LinuxGLQuake console correctly
+ * fade in/out and transparent water of GLQuake2test works fine
+ * - written the support for the env. var. FX_GLIDE_SWAPINTERVAL
+ * - found a bug in the Mesa core. There is a roundup problem for
+ * color values out of the [0.0,1.0] range
+ *
+ * Wonko <matt@khm.de>
+ * - fixed a Voodoo Rush related problem in the fxwgl.c
+ *
+ * Daryll Strauss <daryll@harlot.rb.ca.us>
+ * - written the scissor test support
+ *
+ * V0.20 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
+ * - written the closetmmanger() function in order to free all the memory
+ * allocated by the Texture Memory Manager (it will be useful
+ * when the support for multiple contexts/boards will be ready)
+ * - now the Voodoo driver runs without printing any information,
+ * define the env. var. MESA_FX_INFO if you want to read some
+ * information about the hardware and some statistic
+ * - written a small workaround for the "GLQuake multiplayer white box bug"
+ * in the setup_fx_units() funxtions. I'm already rewriting
+ * this function because it is the source of nearly all the current
+ * Voodoo driver problems
+ * - fixed the GLQuake texture misalignment problem (the texture
+ * coordinates must be scaled between 0.0 and 256.0 and not
+ * between 0.0 and 255.0)
+ * - written the support for the GL_EXT_shared_texture_palette
+ * - some small change for supporting the automatic building of the
+ * OpenGL32.dll under the Windows platform
+ * - the redefinition of a mipmap level is now a LOT faster. This path
+ * is used by GLQuake for dynamic lighting with some call to glTexSubImage2D()
+ * - the texture memory is now managed a set of 2MB blocks so
+ * texture maps can't be allocated on a 2MB boundary. The new Pure3D
+ * needs this kind of support (and probably any other Voodoo Graphics
+ * board with more than 2MB of texture memory)
+ *
+ * Brian Paul (brianp@elastic.avid.com) Avid Technology
+ * - added write_monocolor_span(), fixed bug in write_color_span()
+ * - added test for stenciling in choosepoint/line/triangle functions
+ *
+ * Joe Waters (falc@attila.aegistech.com) Aegis
+ * - written the support for the env. var. SST_SCREENREFRESH
+ *
+ * V0.19 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
+ * - written the 3Dfx Global Palette extension for GLQuake
+ * - written the support for the GL_EXT_paletted_texture (it works only with GL_RGBA
+ * palettes and the alpha value is ignored ... this is a limitation of the
+ * the current Glide version and Voodoo hardware)
+ * - fixed the amount of memory allocated for 8bit textures
+ * - merged the under construction v0.19 driver with the Mesa 2.5
+ * - finally written the support for deleting textures
+ * - introduced a new powerful texture memory manager: the texture memory
+ * is used as a cache of the set of all defined texture maps. You can
+ * now define several MB of texture maps also with a 2MB of texture memory
+ * (the texture memory manager will do automatically all the swap out/swap in
+ * work). The new texture memory manager has also
+ * solved a lot of other bugs/no specs compliance/problems
+ * related to the texture memory usage. The texture
+ * manager code is inside the new fxmesa3.c file
+ * - broken the fxmesa.c file in two files (fxmesa1.c and fxmesa2.c)
+ * and done some code cleanup
+ * - now is possible to redefine texture mipmap levels already defined
+ * - fixed a problem with the amount of texture memory allocated for textures
+ * with not all mipmap levels defined
+ * - fixed a small problem with single buffer rendering
+ *
+ * Brian Paul (brianp@elastic.avid.com) Avid Technology
+ * - read/write_color_span() now use front/back buffer correctly
+ * - create GLvisual with 5,6,5 bits per pixel, not 8,8,8
+ * - removed a few ^M characters from fxmesa2.c file
+ *
+ * V0.18 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
+ * - the Mesa-2.4beta3 is finally using the driver quads support (the
+ * previous Mesa versions have never taken any advantage from the quads support !)
+ * - tested with the Glide 2.4 for Win
+ * - ported all asm code to Linux
+ * - ported the v0.18 to Linux (without asm code)
+ * - back to Linux !!!
+ * - optimized the SETUP macro (no more vertex snap for points and lines)
+ * - optimized the SETUP macro (added one argument)
+ * - the Mesa/Voodoo is now 20/30% for points, lines and small triangles !
+ * - performance improvement setting VBSIZE to 72
+ * - the GrVertex texture code is now written in asm
+ * - the GrVertex zbuffer code is now written in asm
+ * - the GrVertex wbuffer code is now written in asm
+ * - the GrVertex gouraud code is now written in asm
+ * - the GrVertex snap code is now written in asm
+ * - changed the 8bit compressed texture maps in 8bit palette texture maps
+ * support (it has the some advantage of compressed texture maps without the
+ * problem of a fixed NCC table for all mipmap levels)
+ * - written the support for 8bit compressed texture maps (but texture maps with
+ * more than one mipmap level aren't working fine)
+ * - finnaly everthing is working fine in MesaQuake !
+ * - fixed a bug in the computation of texture mapping coordinates (I have found
+ * the bug thanks to MesaQuake !)
+ * - written the GL_REPLACE support (mainly for MesaQuake)
+ * - written the support for textures with not all mipmap levels defined
+ * - rewritten all the Texture memory stuff
+ * - written the MesaQuake support (define MESAQUAKE)
+ * - working with a ZBuffer if glOrtho or not int the default glDepthRange,
+ * otherwise working with the WBuffer
+ * written the glDepthRange support
+ *
+ * Diego Picciani (d.picciani@novacomp.it) Nova Computer s.r.l.
+ * - written the fxCloseHardware() and the fxQuaryHardware() (mainly
+ * for the VoodooWGL emulator)
+ *
+ * Brian Paul (brianp@elastic.avid.com) Avid Technology
+ * - implemented read/write_color_span() so glRead/DrawPixels() works
+ * - now needs Glide 2.3 or later. Removed GLIDE_FULL_SCREEN and call to grSstOpen()
+ *
+ * V0.17 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
+ * - optimized the bitmap support (66% faster)
+ * - tested with the Mesa 2.3beta2
+ *
+ * Diego Picciani (d.picciani@novacomp.it) Nova Computer s.r.l.
+ * - solved a problem with the drawbitmap() and the Voodoo Rush
+ * (GR_ORIGIN_LOWER_LEFT did not work with the Stingray)
+ *
+ * Brian Paul (brianp@elastic.avid.com) Avid Technology
+ * - linux stuff
+ * - general code clean-up
+ * - added attribList parameter to fxMesaCreateContext()
+ * - single buffering works now
+ * - VB colors are now GLubytes, removed ColorShift stuff
+ *
+ * Paul Metzger
+ * - linux stuff
+ *
+ * V0.16 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
+ * - written the quadfunc support (no performance improvement)
+ * - written the support for the new Mesa 2.3beta1 driver interface (Wow ! It is faaaster)
+ * - rewritten the glBitmap support for the Glide 2.3 (~35% slower !)
+ * - written the glBitmap support for the most common case (fonts)
+ *
+ * Jack Palevich
+ * - Glide 2.3 porting
+ *
+ * Diego Picciani (d.picciani@novacomp.it) Nova Computer s.r.l.
+ * - extended the fxMesaCreateContext() and fxMesaCreateBestContext()
+ * functions in order to support also the Voodoo Rush
+ * - tested with the Hercules Stingray 128/3D (The rendering in a window works !)
+ *
+ * V0.15 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
+ * - written the GL_LUMINANCE_ALPHA support
+ * - written the GL_ALPHA support
+ * - written the GL_LUMINANCE support
+ * - now SETUP correctly set color for mono color sequences
+ * - written the 9x1,10x1,...,1x9,1x10,... texture map ratio support
+ * - written the no square texture map support
+ * - the fog table is no more rebuilt inside setup_fx_units() each time
+ *
+ * Henri Fousse (arnaud@pobox.oleane.com) Thomson Training & Simulation
+ * - written (not yet finished: no texture mapping) support for glOrtho
+ * - some change to setup functions
+ * - the fog support is now fully compatible with the standard OpenGL
+ * - rewritten several parts of the driver in order to take
+ * advantage of meshes (40% faster !!!)
+ *
+ * V0.14 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
+ * - now glAlphaFunc() works
+ * - now glDepthMask() works
+ * - solved a mipmap problem when using more than one texture
+ * - moved ti, texid and wscale inside the fxMesaContext (now we can
+ * easy support more ctx and more boards)
+ * - the management of the fxMesaContext was completly broken !
+ * - solved several problems about Alpha and texture Alpha
+ * - 4 (RGBA) texture channels supported
+ * - setting the default color to white
+ *
+ * Henri Fousse (arnaud@pobox.oleane.com) Thomson Training & Simulation
+ * - small change to fxMesaCreateContext() and fxMesaMakeCurrent()
+ * - written the fog support
+ * - setting the default clear color to black
+ * - written cleangraphics() for the onexit() function
+ * - written fxMesaCreateBestContext()
+ *
+ * V0.13 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
+ * - now glBlendFunc() works for all glBlendFunc without DST_ALPHA
+ * (because the alpha buffer is not yet implemented)
+ * - now fxMesaCreateContext() accept resolution and refresh rate
+ * - fixed a bug for texture mapping: the w (alias z) must be set
+ * also without depth buffer
+ * - fixed a bug for texture image with width!=256
+ * - written texparam()
+ * - written all point, line and triangle functions for all possible supported
+ * contexts and the driver is slight faster with points, lines and small triangles
+ * - fixed a small bug in fx/fxmesa.h (glOrtho)
+ *
+ * V0.12 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
+ * - glDepthFunc supported
+ * - introduced a trick to discover the far plane distance
+ * (see fxMesaSetFar and fx/fxmesa.h)
+ * - now the wbuffer works with homogeneous coordinate (and it
+ * doesn't work with a glOrtho projection :)
+ * - solved several problems with homogeneous coordinate and texture mapping
+ * - fixed a bug in all line functions
+ * - fixed a clear framebuffer bug
+ * - solved a display list/teximg problem (but use
+ * glBindTexture: it is several times faster)
+ *
+ * V0.11 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
+ * - introduced texture mapping support (not yet finished !)
+ * - tested with Mesa2.2b6
+ * - the driver is faster
+ * - written glFlush/glFinish
+ * - the driver print a lot of info about the Glide lib
+ *
+ * v0.1 - David Bucciarelli (tech.hmw@plus.it) Humanware s.r.l.
+ * - Initial revision
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#if defined(FX)
+#include "fxdrv.h"
+
+fxMesaContext fxMesaCurrentCtx=NULL;
+
+/*
+ * Status of 3Dfx hardware initialization
+ */
+
+static int glbGlideInitialized=0;
+static int glb3DfxPresent=0;
+static int glbTotNumCtx=0;
+
+GrHwConfiguration glbHWConfig;
+int glbCurrentBoard=0;
+
+
+#if defined(__WIN32__)
+static int cleangraphics(void)
+{
+ glbTotNumCtx=1;
+ fxMesaDestroyContext(fxMesaCurrentCtx);
+
+ return 0;
+}
+#elif defined(__linux__)
+static void cleangraphics(void)
+{
+ glbTotNumCtx=1;
+ fxMesaDestroyContext(fxMesaCurrentCtx);
+}
+
+static void cleangraphics_handler(int s)
+{
+ fprintf(stderr,"fxmesa: Received a not handled signal %d\n",s);
+
+ cleangraphics();
+/* abort(); */
+ exit(1);
+}
+#endif
+
+
+/*
+ * Select the Voodoo board to use when creating
+ * a new context.
+ */
+GLboolean GLAPIENTRY fxMesaSelectCurrentBoard(int n)
+{
+ fxQueryHardware();
+
+ if((n<0) || (n>=glbHWConfig.num_sst))
+ return GL_FALSE;
+
+ glbCurrentBoard=n;
+
+ return GL_TRUE;
+}
+
+
+fxMesaContext GLAPIENTRY fxMesaGetCurrentContext(void)
+{
+ return fxMesaCurrentCtx;
+}
+
+
+void GLAPIENTRY fxMesaSetNearFar(GLfloat n, GLfloat f)
+{
+ if(fxMesaCurrentCtx)
+ fxDDSetNearFar(fxMesaCurrentCtx->glCtx,n,f);
+}
+
+
+/*
+ * The extension GL_FXMESA_global_texture_lod_bias
+ */
+void GLAPIENTRY glGlobalTextureLODBiasFXMESA(GLfloat biasVal)
+{
+ grTexLodBiasValue(GR_TMU0,biasVal);
+
+ if(fxMesaCurrentCtx->haveTwoTMUs)
+ grTexLodBiasValue(GR_TMU1,biasVal);
+}
+
+
+/*
+ * The 3Dfx Global Palette extension for GLQuake.
+ * More a trick than a real extesion, use the shared global
+ * palette extension.
+ */
+void GLAPIENTRY gl3DfxSetPaletteEXT(GLuint *pal)
+{
+ fxMesaContext fxMesa =fxMesaCurrentCtx;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ int i;
+
+ fprintf(stderr,"fxmesa: gl3DfxSetPaletteEXT()\n");
+
+ for(i=0;i<256;i++)
+ fprintf(stderr,"%x\n",pal[i]);
+ }
+
+ if(fxMesa) {
+ fxMesa->haveGlobalPaletteTexture=1;
+
+ FX_grTexDownloadTable(GR_TMU0,GR_TEXTABLE_PALETTE,(GuTexPalette *)pal);
+ if (fxMesa->haveTwoTMUs)
+ FX_grTexDownloadTable(GR_TMU1,GR_TEXTABLE_PALETTE,(GuTexPalette *)pal);
+ }
+}
+
+
+static GrScreenResolution_t fxBestResolution(int width, int height, int aux)
+{
+ static int resolutions[][5]={
+ { 512, 384, GR_RESOLUTION_512x384, 2, 2 },
+ { 640, 400, GR_RESOLUTION_640x400, 2, 2 },
+ { 640, 480, GR_RESOLUTION_640x480, 2, 2 },
+ { 800, 600, GR_RESOLUTION_800x600, 4, 2 },
+ { 960, 720, GR_RESOLUTION_960x720, 6, 4 }
+#ifdef GR_RESOLUTION_1024x768
+ ,{ 1024, 768, GR_RESOLUTION_1024x768, 8, 4 }
+#endif
+#ifdef GR_RESOLUTION_1280x1024
+ ,{ 1024, 768, GR_RESOLUTION_1280x1024, 8, 8 }
+#endif
+#ifdef GR_RESOLUTION_1600x1200
+ ,{ 1024, 768, GR_RESOLUTION_1600x1200, 16, 8 }
+#endif
+ };
+ int NUM_RESOLUTIONS = sizeof(resolutions) / (sizeof(int)*5);
+ int i,fbmem;
+ GrScreenResolution_t lastvalidres=resolutions[1][2];
+
+ fxQueryHardware();
+
+ if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_VOODOO) {
+ fbmem=glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.fbRam;
+
+ if(glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.sliDetect)
+ fbmem*=2;
+ } else if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_SST96)
+ fbmem=glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.fbRam;
+ else
+ fbmem=2;
+
+ /* A work around for BZFlag */
+
+ if((width==1) && (height==1)) {
+ width=640;
+ height=480;
+ }
+
+ for(i=0;i<NUM_RESOLUTIONS;i++)
+ if(resolutions[i][4-aux]<=fbmem) {
+ if((width<=resolutions[i][0]) && (height<=resolutions[i][1]))
+ return resolutions[i][2];
+
+ lastvalidres=resolutions[i][2];
+ }
+
+ return lastvalidres;
+}
+
+
+fxMesaContext GLAPIENTRY fxMesaCreateBestContext(GLuint win,GLint width, GLint height,
+ const GLint attribList[])
+{
+ GrScreenRefresh_t refresh;
+ int i;
+ int res,aux;
+ refresh=GR_REFRESH_75Hz;
+
+ if(getenv("SST_SCREENREFRESH")) {
+ if(!strcmp(getenv("SST_SCREENREFRESH"),"60"))
+ refresh=GR_REFRESH_60Hz;
+ if(!strcmp(getenv("SST_SCREENREFRESH"),"70"))
+ refresh=GR_REFRESH_70Hz;
+ if(!strcmp(getenv("SST_SCREENREFRESH"),"72"))
+ refresh=GR_REFRESH_72Hz;
+ if(!strcmp(getenv("SST_SCREENREFRESH"),"75"))
+ refresh=GR_REFRESH_75Hz;
+ if(!strcmp(getenv("SST_SCREENREFRESH"),"80"))
+ refresh=GR_REFRESH_80Hz;
+ if(!strcmp(getenv("SST_SCREENREFRESH"),"85"))
+ refresh=GR_REFRESH_85Hz;
+ if(!strcmp(getenv("SST_SCREENREFRESH"),"90"))
+ refresh=GR_REFRESH_90Hz;
+ if(!strcmp(getenv("SST_SCREENREFRESH"),"100"))
+ refresh=GR_REFRESH_100Hz;
+ if(!strcmp(getenv("SST_SCREENREFRESH"),"120"))
+ refresh=GR_REFRESH_120Hz;
+ }
+
+ aux=0;
+ for(i=0;attribList[i]!=FXMESA_NONE;i++)
+ if((attribList[i]==FXMESA_ALPHA_SIZE) ||
+ (attribList[i]==FXMESA_DEPTH_SIZE)) {
+ if(attribList[++i]>0) {
+ aux=1;
+ break;
+ }
+ }
+
+ res=fxBestResolution(width,height,aux);
+
+ return fxMesaCreateContext(win,res,refresh,attribList);
+}
+
+
+#if 0
+void fxsignals()
+{
+ signal(SIGINT,SIG_IGN);
+ signal(SIGHUP,SIG_IGN);
+ signal(SIGPIPE,SIG_IGN);
+ signal(SIGFPE,SIG_IGN);
+ signal(SIGBUS,SIG_IGN);
+ signal(SIGILL,SIG_IGN);
+ signal(SIGSEGV,SIG_IGN);
+ signal(SIGTERM,SIG_IGN);
+}
+#endif
+
+/*
+ * Create a new FX/Mesa context and return a handle to it.
+ */
+fxMesaContext GLAPIENTRY fxMesaCreateContext(GLuint win,GrScreenResolution_t res,
+ GrScreenRefresh_t ref,
+ const GLint attribList[])
+{
+ fxMesaContext fxMesa;
+ int i,type;
+ int aux;
+ GLboolean doubleBuffer=GL_FALSE;
+ GLboolean alphaBuffer=GL_FALSE;
+ GLboolean verbose=GL_FALSE;
+ GLint depthSize=0;
+ GLint stencilSize=0;
+ GLint accumSize=0;
+ GLcontext *shareCtx = NULL;
+ GLcontext *ctx = 0;
+ FX_GrContext_t glideContext = 0;
+ char *errorstr;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxMesaCreateContext() Start\n");
+ }
+
+ if(getenv("MESA_FX_INFO"))
+ verbose=GL_TRUE;
+
+ aux=0;
+ i=0;
+ while(attribList[i]!=FXMESA_NONE) {
+ switch (attribList[i]) {
+ case FXMESA_DOUBLEBUFFER:
+ doubleBuffer=GL_TRUE;
+ break;
+ case FXMESA_ALPHA_SIZE:
+ i++;
+ alphaBuffer=attribList[i]>0;
+ if(alphaBuffer)
+ aux=1;
+ break;
+ case FXMESA_DEPTH_SIZE:
+ i++;
+ depthSize=attribList[i];
+ if(depthSize)
+ aux=1;
+ break;
+ case FXMESA_STENCIL_SIZE:
+ i++;
+ stencilSize=attribList[i];
+ break;
+ case FXMESA_ACCUM_SIZE:
+ i++;
+ accumSize=attribList[i];
+ break;
+ /* XXX ugly hack here for sharing display lists */
+#define FXMESA_SHARE_CONTEXT 990099 /* keep in sync with xmesa1.c! */
+ case FXMESA_SHARE_CONTEXT:
+ i++;
+ {
+ const void *vPtr = &attribList[i];
+ GLcontext **ctx = (GLcontext **) vPtr;
+ shareCtx = *ctx;
+ }
+ break;
+ default:
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxMesaCreateContext() End (defualt)\n");
+ }
+ return NULL;
+ }
+ i++;
+ }
+
+ /* A workaround for Linux GLQuake */
+ if(depthSize && alphaBuffer)
+ alphaBuffer=0;
+
+ if(verbose)
+ fprintf(stderr,"Mesa fx Voodoo Device Driver v0.30\nWritten by David Bucciarelli (davibu@tin.it.it)\n");
+
+ if((type=fxQueryHardware()) >= 0) {
+ if(type==GR_SSTTYPE_VOODOO)
+ win=0;
+
+ grSstSelect(glbCurrentBoard);
+
+#if FXMESA_USE_ARGB
+ glideContext = FX_grSstWinOpen((FxU32)win,res,ref,
+ GR_COLORFORMAT_ARGB,GR_ORIGIN_LOWER_LEFT,2,aux);
+
+#else
+ glideContext = FX_grSstWinOpen((FxU32)win,res,ref,
+ GR_COLORFORMAT_ABGR,GR_ORIGIN_LOWER_LEFT,2,aux);
+#endif
+ if (!glideContext){
+ errorstr = "grSstWinOpen";
+ goto errorhandler;
+ }
+
+ if(verbose)
+ fprintf(stderr,"Glide screen size: %dx%d\n",
+ (int)FX_grSstScreenWidth(),(int)FX_grSstScreenHeight());
+ } else {
+ fprintf(stderr,"fx Driver: ERROR no Voodoo1/2 Graphics or Voodoo Rush !\n");
+ return NULL;
+ }
+
+ fxMesa=(fxMesaContext)calloc(1,sizeof(struct tfxMesaContext));
+ if(!fxMesa) {
+ errorstr = "malloc";
+ goto errorhandler;
+ }
+
+ FX_setupGrVertexLayout();
+
+ fxMesa->glideContext = glideContext;
+ fxMesa->board=glbCurrentBoard;
+ fxMesa->width=FX_grSstScreenWidth();
+ fxMesa->height=FX_grSstScreenHeight();
+
+ fxMesa->verbose=verbose;
+
+ if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_VOODOO)
+ fxMesa->haveTwoTMUs=(glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.nTexelfx > 1);
+ else if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_SST96)
+ fxMesa->haveTwoTMUs=(glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.nTexelfx > 1);
+ else
+ fxMesa->haveTwoTMUs=GL_FALSE;
+
+ if (getenv("FX_EMULATE_SINGLE_TMU")) {
+ if (MESA_VERBOSE&VERBOSE_DRIVER)
+ fprintf(stderr, "\n\nEmulating single tmu\n\n");
+ fxMesa->haveTwoTMUs = GL_FALSE;
+ }
+
+ fxMesa->emulateTwoTMUs = fxMesa->haveTwoTMUs;
+
+ if (!getenv("FX_DONT_FAKE_MULTITEX")) {
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ if (!fxMesa->haveTwoTMUs)
+ fprintf(stderr, "\n\nEmulating multitexture\n\n");
+ }
+ fxMesa->emulateTwoTMUs = GL_TRUE;
+ }
+
+
+ fxMesa->haveDoubleBuffer=doubleBuffer;
+ fxMesa->haveAlphaBuffer=alphaBuffer;
+ fxMesa->haveGlobalPaletteTexture=GL_FALSE;
+
+ if(getenv("FX_GLIDE_SWAPINTERVAL"))
+ fxMesa->swapInterval=atoi(getenv("FX_GLIDE_SWAPINTERVAL"));
+ else
+ fxMesa->swapInterval=1;
+
+ if(getenv("MESA_FX_SWAP_PENDING"))
+ fxMesa->maxPendingSwapBuffers=atoi(getenv("MESA_FX_SWAP_PENDING"));
+ else
+ fxMesa->maxPendingSwapBuffers=2;
+
+ fxMesa->color=0xffffffff;
+ fxMesa->clearC=0;
+ fxMesa->clearA=0;
+
+ fxMesa->stats.swapBuffer=0;
+ fxMesa->stats.reqTexUpload=0;
+ fxMesa->stats.texUpload=0;
+ fxMesa->stats.memTexUpload=0;
+
+ fxMesa->tmuSrc=FX_TMU_NONE;
+ fxMesa->lastUnitsMode=FX_UM_NONE;
+ fxTMInit(fxMesa);
+
+ /* FX units setup */
+
+ fxMesa->unitsState.alphaTestEnabled=GL_FALSE;
+ fxMesa->unitsState.alphaTestFunc=GR_CMP_ALWAYS;
+ fxMesa->unitsState.alphaTestRefValue=0;
+
+ fxMesa->unitsState.blendEnabled=GL_FALSE;
+ fxMesa->unitsState.blendSrcFuncRGB=GR_BLEND_ONE;
+ fxMesa->unitsState.blendDstFuncRGB=GR_BLEND_ZERO;
+ fxMesa->unitsState.blendSrcFuncAlpha=GR_BLEND_ONE;
+ fxMesa->unitsState.blendDstFuncAlpha=GR_BLEND_ZERO;
+
+ fxMesa->unitsState.depthTestEnabled =GL_FALSE;
+ fxMesa->unitsState.depthMask =GL_TRUE;
+ fxMesa->unitsState.depthTestFunc =GR_CMP_LESS;
+
+ grColorMask(FXTRUE,alphaBuffer ? FXTRUE : FXFALSE);
+ if(doubleBuffer) {
+ fxMesa->currentFB=GR_BUFFER_BACKBUFFER;
+ grRenderBuffer(GR_BUFFER_BACKBUFFER);
+ } else {
+ fxMesa->currentFB=GR_BUFFER_FRONTBUFFER;
+ grRenderBuffer(GR_BUFFER_FRONTBUFFER);
+ }
+
+ fxMesa->state = NULL;
+ fxMesa->fogTable = NULL;
+
+ fxMesa->state = malloc(FX_grGetInteger(FX_GLIDE_STATE_SIZE));
+ fxMesa->fogTable = malloc(FX_grGetInteger(FX_FOG_TABLE_ENTRIES)*sizeof(GrFog_t));
+
+ if (!fxMesa->state || !fxMesa->fogTable) {
+ errorstr = "malloc";
+ goto errorhandler;
+ }
+
+ if(depthSize)
+ grDepthBufferMode(GR_DEPTHBUFFER_ZBUFFER);
+
+#if (!FXMESA_USE_ARGB)
+ grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); /* Not every Glide supports this */
+#endif
+
+ fxMesa->glVis=gl_create_visual(GL_TRUE, /* RGB mode */
+ alphaBuffer,
+ doubleBuffer,
+ GL_FALSE, /* stereo */
+ depthSize, /* depth_size */
+ stencilSize, /* stencil_size */
+ accumSize, /* accum_size */
+ 0, /* index bits */
+ 5,6,5,0); /* RGBA bits */
+ if (!fxMesa->glVis) {
+ errorstr = "gl_create_visual";
+ goto errorhandler;
+ }
+
+ ctx = fxMesa->glCtx=gl_create_context(fxMesa->glVis,
+ shareCtx, /* share list context */
+ (void *) fxMesa, GL_TRUE);
+ if (!ctx) {
+ errorstr = "gl_create_context";
+ goto errorhandler;
+ }
+
+ fxMesa->glBuffer=gl_create_framebuffer(fxMesa->glVis);
+ if (!fxMesa->glBuffer) {
+ errorstr = "gl_create_framebuffer";
+ goto errorhandler;
+ }
+
+ fxMesa->glCtx->Const.MaxTextureLevels=9;
+ fxMesa->glCtx->Const.MaxTextureSize=256;
+ fxMesa->glCtx->Const.MaxTextureUnits=fxMesa->emulateTwoTMUs ? 2 : 1;
+
+ fxMesa->glCtx->NewState|=NEW_DRVSTATE1;
+ fxMesa->new_state = NEW_ALL;
+
+ fxDDSetupInit();
+ fxDDCvaInit();
+ fxDDClipInit();
+ fxDDTrifuncInit();
+ fxDDFastPathInit();
+
+ fxSetupDDPointers(fxMesa->glCtx);
+ fxDDRenderInit(fxMesa->glCtx);
+ fxDDInitExtensions(fxMesa->glCtx);
+
+ fxDDSetNearFar(fxMesa->glCtx,1.0,100.0);
+
+ grGlideGetState((GrState*)fxMesa->state);
+
+ /* XXX Fix me: callback not registered when main VB is created.
+ */
+ if (fxMesa->glCtx->VB)
+ fxDDRegisterVB( fxMesa->glCtx->VB );
+
+ /* XXX Fix me too: need to have the 'struct dd' prepared prior to
+ * creating the context... The below is broken if you try to insert
+ * new stages.
+ */
+ if (ctx->NrPipelineStages)
+ ctx->NrPipelineStages = fxDDRegisterPipelineStages( ctx->PipelineStage,
+ ctx->PipelineStage,
+ ctx->NrPipelineStages);
+
+
+ glbTotNumCtx++;
+
+ /* Run the config file */
+ gl_context_initialize( fxMesa->glCtx );
+
+ /* install signal handlers */
+#if defined(__linux__)
+ if (fxMesa->glCtx->CatchSignals) {
+ signal(SIGINT,cleangraphics_handler);
+ signal(SIGHUP,cleangraphics_handler);
+ signal(SIGPIPE,cleangraphics_handler);
+ signal(SIGFPE,cleangraphics_handler);
+ signal(SIGBUS,cleangraphics_handler);
+ signal(SIGILL,cleangraphics_handler);
+ signal(SIGSEGV,cleangraphics_handler);
+ signal(SIGTERM,cleangraphics_handler);
+ }
+#endif
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxMesaCreateContext() End\n");
+ }
+
+ return fxMesa;
+
+errorhandler:
+ if (fxMesa) {
+ if (fxMesa->glideContext)
+ FX_grSstWinClose(fxMesa->glideContext);
+ fxMesa->glideContext = 0;
+
+ if (fxMesa->state)
+ free(fxMesa->state);
+ if (fxMesa && fxMesa->fogTable)
+ free(fxMesa->fogTable);
+ if (fxMesa->glBuffer)
+ gl_destroy_framebuffer(fxMesa->glBuffer);
+ if (fxMesa->glVis)
+ gl_destroy_visual(fxMesa->glVis);
+ if (fxMesa->glCtx)
+ gl_destroy_context(fxMesa->glCtx);
+ free(fxMesa);
+ }
+
+
+
+
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxMesaCreateContext() End (%s)\n",errorstr);
+ }
+ return NULL;
+}
+
+
+/*
+ * Function to set the new window size in the context (mainly for the Voodoo Rush)
+ */
+void GLAPIENTRY fxMesaUpdateScreenSize(fxMesaContext fxMesa)
+{
+ fxMesa->width=FX_grSstScreenWidth();
+ fxMesa->height=FX_grSstScreenHeight();
+}
+
+
+/*
+ * Destroy the given FX/Mesa context.
+ */
+void GLAPIENTRY fxMesaDestroyContext(fxMesaContext fxMesa)
+{
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxMesaDestroyContext()\n");
+ }
+
+ if(fxMesa) {
+ gl_destroy_visual(fxMesa->glVis);
+ gl_destroy_context(fxMesa->glCtx);
+ gl_destroy_framebuffer(fxMesa->glBuffer);
+
+ glbTotNumCtx--;
+
+ fxCloseHardware();
+ FX_grSstWinClose(fxMesa->glideContext);
+
+ if(fxMesa->verbose) {
+ fprintf(stderr,"Misc Stats:\n");
+ fprintf(stderr," # swap buffer: %u\n",fxMesa->stats.swapBuffer);
+
+ if(!fxMesa->stats.swapBuffer)
+ fxMesa->stats.swapBuffer=1;
+
+ fprintf(stderr,"Textures Stats:\n");
+ fprintf(stderr," Free texture memory on TMU0: %d:\n",fxMesa->freeTexMem[FX_TMU0]);
+ if(fxMesa->haveTwoTMUs)
+ fprintf(stderr," Free texture memory on TMU1: %d:\n",fxMesa->freeTexMem[FX_TMU1]);
+ fprintf(stderr," # request to TMM to upload a texture objects: %u\n",
+ fxMesa->stats.reqTexUpload);
+ fprintf(stderr," # request to TMM to upload a texture objects per swapbuffer: %.2f\n",
+ fxMesa->stats.reqTexUpload/(float)fxMesa->stats.swapBuffer);
+ fprintf(stderr," # texture objects uploaded: %u\n",
+ fxMesa->stats.texUpload);
+ fprintf(stderr," # texture objects uploaded per swapbuffer: %.2f\n",
+ fxMesa->stats.texUpload/(float)fxMesa->stats.swapBuffer);
+ fprintf(stderr," # MBs uploaded to texture memory: %.2f\n",
+ fxMesa->stats.memTexUpload/(float)(1<<20));
+ fprintf(stderr," # MBs uploaded to texture memory per swapbuffer: %.2f\n",
+ (fxMesa->stats.memTexUpload/(float)fxMesa->stats.swapBuffer)/(float)(1<<20));
+ }
+ if (fxMesa->state)
+ free(fxMesa->state);
+ if (fxMesa->fogTable)
+ free(fxMesa->fogTable);
+ fxTMClose(fxMesa);
+
+ free(fxMesa);
+ }
+
+ if(fxMesa==fxMesaCurrentCtx)
+ fxMesaCurrentCtx=NULL;
+}
+
+
+/*
+ * Make the specified FX/Mesa context the current one.
+ */
+void GLAPIENTRY fxMesaMakeCurrent(fxMesaContext fxMesa)
+{
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxMesaMakeCurrent(...) Start\n");
+ }
+
+ if(!fxMesa) {
+ gl_make_current(NULL,NULL);
+ fxMesaCurrentCtx=NULL;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxMesaMakeCurrent(NULL) End\n");
+ }
+
+ return;
+ }
+
+ /* if this context is already the current one, we can return early */
+ if (fxMesaCurrentCtx == fxMesa
+ && fxMesaCurrentCtx->glCtx == gl_get_current_context()) {
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxMesaMakeCurrent(fxMesaCurrentCtx==fxMesa) End\n");
+ }
+
+ return;
+ }
+
+ if(fxMesaCurrentCtx)
+ grGlideGetState((GrState*)fxMesaCurrentCtx->state);
+
+ fxMesaCurrentCtx=fxMesa;
+
+ grSstSelect(fxMesa->board);
+ grGlideSetState((GrState*)fxMesa->state);
+
+ gl_make_current(fxMesa->glCtx,fxMesa->glBuffer);
+
+ fxSetupDDPointers(fxMesa->glCtx);
+
+ /* The first time we call MakeCurrent we set the initial viewport size */
+ if(fxMesa->glCtx->Viewport.Width==0)
+ gl_Viewport(fxMesa->glCtx,0,0,fxMesa->width,fxMesa->height);
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxMesaMakeCurrent(...) End\n");
+ }
+}
+
+
+/*
+ * Swap front/back buffers for current context if double buffered.
+ */
+void GLAPIENTRY fxMesaSwapBuffers(void)
+{
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: ------------------------------- fxMesaSwapBuffers() -------------------------------\n");
+ }
+
+ if(fxMesaCurrentCtx) {
+ FLUSH_VB( fxMesaCurrentCtx->glCtx, "swap buffers" );
+
+ if(fxMesaCurrentCtx->haveDoubleBuffer) {
+
+ grBufferSwap(fxMesaCurrentCtx->swapInterval);
+
+ /*
+ * Don't allow swap buffer commands to build up!
+ */
+ while(FX_grGetInteger(FX_PENDING_BUFFERSWAPS)>fxMesaCurrentCtx->maxPendingSwapBuffers)
+ /* The driver is able to sleep when waiting for the completation
+ of multiple swapbuffer operations instead of wasting
+ CPU time (NOTE: you must uncomment the following line in the
+ in order to enable this option) */
+ /* usleep(10000); */
+ ;
+
+ fxMesaCurrentCtx->stats.swapBuffer++;
+ }
+ }
+}
+
+
+/*
+ * Query 3Dfx hardware presence/kind
+ */
+int GLAPIENTRY fxQueryHardware(void)
+{
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxQueryHardware() Start\n");
+ }
+
+ if(!glbGlideInitialized) {
+ grGlideInit();
+ if(FX_grSstQueryHardware(&glbHWConfig)) {
+ grSstSelect(glbCurrentBoard);
+ glb3DfxPresent=1;
+
+ if(getenv("MESA_FX_INFO")) {
+ char buf[80];
+
+ FX_grGlideGetVersion(buf);
+ fprintf(stderr,"Using Glide V%s\n",0);
+ fprintf(stderr,"Number of boards: %d\n",glbHWConfig.num_sst);
+
+ if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_VOODOO) {
+ fprintf(stderr,"Framebuffer RAM: %d\n",
+ glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.sliDetect ?
+ (glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.fbRam*2) :
+ glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.fbRam);
+ fprintf(stderr,"Number of TMUs: %d\n",
+ glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.nTexelfx);
+ fprintf(stderr,"SLI detected: %d\n",
+ glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.sliDetect);
+ } else if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_SST96) {
+ fprintf(stderr,"Framebuffer RAM: %d\n",
+ glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.fbRam);
+ fprintf(stderr,"Number of TMUs: %d\n",
+ glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.nTexelfx);
+ }
+
+ }
+ } else
+ glb3DfxPresent=0;
+
+ glbGlideInitialized=1;
+
+#if defined(__WIN32__)
+ onexit((_onexit_t)cleangraphics);
+#elif defined(__linux__)
+ atexit(cleangraphics);
+#endif
+ }
+
+ if(!glb3DfxPresent) {
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxQueryHardware() End (-1)\n");
+ }
+ return(-1);
+ }
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxQueryHardware() End (voodooo)\n");
+ }
+ return(glbHWConfig.SSTs[glbCurrentBoard].type);
+}
+
+
+/*
+ * Shutdown Glide library
+ */
+void GLAPIENTRY fxCloseHardware(void)
+{
+ if(glbGlideInitialized) {
+ if(getenv("MESA_FX_INFO")) {
+ GrSstPerfStats_t st;
+
+ FX_grSstPerfStats(&st);
+ fprintf(stderr,"Pixels Stats:\n");
+ fprintf(stderr," # pixels processed (minus buffer clears): %u\n",(unsigned)st.pixelsIn);
+ fprintf(stderr," # pixels not drawn due to chroma key test failure: %u\n",(unsigned)st.chromaFail);
+ fprintf(stderr," # pixels not drawn due to depth test failure: %u\n",(unsigned)st.zFuncFail);
+ fprintf(stderr," # pixels not drawn due to alpha test failure: %u\n",(unsigned)st.aFuncFail);
+ fprintf(stderr," # pixels drawn (including buffer clears and LFB writes): %u\n",(unsigned)st.pixelsOut);
+ }
+
+ if(glbTotNumCtx==0) {
+ grGlideShutdown();
+ glbGlideInitialized=0;
+ }
+ }
+}
+
+
+#else
+
+
+/*
+ * Need this to provide at least one external definition.
+ */
+
+int gl_fx_dummy_function_api(void)
+{
+ return 0;
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/fxdd.c b/src/mesa/drivers/glide/fxdd.c
new file mode 100644
index 0000000000..b2f3a7a43c
--- /dev/null
+++ b/src/mesa/drivers/glide/fxdd.c
@@ -0,0 +1,632 @@
+/* -*- mode: C; tab-width:8; -*-
+
+ fxdd.c - 3Dfx VooDoo Mesa device driver functions
+*/
+
+/*
+ * 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.
+ *
+ * See the file fxapi.c for more informations about authors
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#if defined(FX)
+
+#include "fxdrv.h"
+#include "enums.h"
+
+/**********************************************************************/
+/***** Miscellaneous functions *****/
+/**********************************************************************/
+
+/* Enalbe/Disable dithering */
+void fxDDDither(GLcontext *ctx, GLboolean enable)
+{
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDDither()\n");
+ }
+
+ if(enable)
+ grDitherMode(GR_DITHER_4x4);
+ else
+ grDitherMode(GR_DITHER_DISABLE);
+}
+
+
+/* Return buffer size information */
+void fxDDBufferSize(GLcontext *ctx, GLuint *width, GLuint *height)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDBufferSize(...) Start\n");
+ }
+
+ *width=fxMesa->width;
+ *height=fxMesa->height;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDBufferSize(...) End\n");
+ }
+}
+
+
+/* Set current drawing color */
+static void fxDDSetColor(GLcontext *ctx, GLubyte red, GLubyte green,
+ GLubyte blue, GLubyte alpha )
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLubyte col[4];
+ ASSIGN_4V( col, red, green, blue, alpha );
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDSetColor(%d,%d,%d,%d)\n",red,green,blue,alpha);
+ }
+
+ fxMesa->color=FXCOLOR4(col);
+}
+
+
+/* Implements glClearColor() */
+static void fxDDClearColor(GLcontext *ctx, GLubyte red, GLubyte green,
+ GLubyte blue, GLubyte alpha )
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLubyte col[4];
+
+
+
+ ASSIGN_4V( col, red, green, blue, 255 );
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDClearColor(%d,%d,%d,%d)\n",red,green,blue,alpha);
+ }
+
+ fxMesa->clearC=FXCOLOR4( col );
+ fxMesa->clearA=alpha;
+}
+
+/* Clear the color and/or depth buffers */
+static GLbitfield fxDDClear(GLcontext *ctx, GLbitfield mask, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLbitfield newmask;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDClear(%d,%d,%d,%d)\n",x,y,width,height);
+ }
+
+ switch(mask & (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)) {
+ case (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT):
+ /* clear color and depth buffer */
+
+ if (ctx->Color.DrawDestMask & BACK_LEFT_BIT) {
+ grRenderBuffer(GR_BUFFER_BACKBUFFER);
+ grBufferClear(fxMesa->clearC, fxMesa->clearA,
+ (FxU16)(ctx->Depth.Clear*0xffff));
+ }
+ if (ctx->Color.DrawDestMask & FRONT_LEFT_BIT) {
+ grRenderBuffer(GR_BUFFER_FRONTBUFFER);
+ grBufferClear(fxMesa->clearC, fxMesa->clearA,
+ (FxU16)(ctx->Depth.Clear*0xffff));
+ }
+
+ newmask=mask & (~(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT));
+ break;
+ case (GL_COLOR_BUFFER_BIT):
+ /* clear color buffer */
+
+ if(ctx->Color.ColorMask) {
+ grDepthMask(FXFALSE);
+
+ if (ctx->Color.DrawDestMask & BACK_LEFT_BIT) {
+ grRenderBuffer(GR_BUFFER_BACKBUFFER);
+ grBufferClear(fxMesa->clearC, fxMesa->clearA, 0);
+ }
+ if (ctx->Color.DrawDestMask & FRONT_LEFT_BIT) {
+ grRenderBuffer(GR_BUFFER_FRONTBUFFER);
+ grBufferClear(fxMesa->clearC, fxMesa->clearA, 0);
+ }
+
+ if(ctx->Depth.Mask)
+ grDepthMask(FXTRUE);
+ }
+
+ newmask=mask & (~(GL_COLOR_BUFFER_BIT));
+ break;
+ case (GL_DEPTH_BUFFER_BIT):
+ /* clear depth buffer */
+
+ if(ctx->Depth.Mask) {
+ grColorMask(FXFALSE,FXFALSE);
+ grBufferClear(fxMesa->clearC, fxMesa->clearA,
+ (FxU16)(ctx->Depth.Clear*0xffff));
+
+ grColorMask(ctx->Color.ColorMask[RCOMP] ||
+ ctx->Color.ColorMask[GCOMP] ||
+ ctx->Color.ColorMask[BCOMP],
+ ctx->Color.ColorMask[ACOMP] && fxMesa->haveAlphaBuffer);
+ }
+
+ newmask=mask & (~(GL_DEPTH_BUFFER_BIT));
+ break;
+ default:
+ newmask=mask;
+ break;
+ }
+
+ return newmask;
+}
+
+
+/* Set the buffer used in double buffering */
+static GLboolean fxDDSetBuffer(GLcontext *ctx, GLenum mode )
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDSetBuffer(%x)\n",mode);
+ }
+
+ if (mode == GL_FRONT_LEFT) {
+ fxMesa->currentFB = GR_BUFFER_FRONTBUFFER;
+ grRenderBuffer(fxMesa->currentFB);
+ return GL_TRUE;
+ }
+ else if (mode == GL_BACK_LEFT) {
+ fxMesa->currentFB = GR_BUFFER_BACKBUFFER;
+ grRenderBuffer(fxMesa->currentFB);
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
+
+static GLboolean fxDDDrawBitMap(GLcontext *ctx, GLint px, GLint py,
+ GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ FxU16 *p;
+ GrLfbInfo_t info;
+ const GLubyte *pb;
+ int x,y;
+ GLint r,g,b,a,scrwidth,scrheight,stride;
+ FxU16 color;
+
+ /* TODO: with a little work, these bitmap unpacking parameter restrictions
+ * could be removed.
+ */
+ if((unpack->Alignment!=1) ||
+ (unpack->RowLength!=0) ||
+ (unpack->SkipPixels!=0) ||
+ (unpack->SkipRows!=0) ||
+ (unpack->SwapBytes) ||
+ (unpack->LsbFirst))
+ return GL_FALSE;
+
+#define ISCLIPPED(rx) ( ((rx)<0) || ((rx)>=scrwidth) )
+#define DRAWBIT(i) { \
+ if(!ISCLIPPED(x+px)) \
+ if( (*pb) & (1<<(i)) ) \
+ (*p)=color; \
+ p++; \
+ x++; \
+ if(x>=width) { \
+ pb++; \
+ break; \
+ } \
+}
+
+ scrwidth=fxMesa->width;
+ scrheight=fxMesa->height;
+
+ if((px>=scrwidth) || (px+width<=0) || (py>=scrheight) || (py+height<=0))
+ return GL_TRUE;
+
+ pb=bitmap;
+
+ if(py<0) {
+ pb+=(height*(-py)) >> (3+1);
+ height+=py;
+ py=0;
+ }
+
+ if(py+height>=scrheight)
+ height-=(py+height)-scrheight;
+
+ info.size=sizeof(info);
+ if(!grLfbLock(GR_LFB_WRITE_ONLY,
+ fxMesa->currentFB,
+ GR_LFBWRITEMODE_565,
+ GR_ORIGIN_UPPER_LEFT,
+ FXFALSE,
+ &info)) {
+#ifndef FX_SILENT
+ fprintf(stderr,"fx Driver: error locking the linear frame buffer\n");
+#endif
+ return GL_TRUE;
+ }
+
+ r=(GLint)(ctx->Current.RasterColor[0]*255.0f);
+ g=(GLint)(ctx->Current.RasterColor[1]*255.0f);
+ b=(GLint)(ctx->Current.RasterColor[2]*255.0f);
+ a=(GLint)(ctx->Current.RasterColor[3]*255.0f);
+ color=(FxU16)
+ ( ((FxU16)0xf8 & b) <<(11-3)) |
+ ( ((FxU16)0xfc & g) <<(5-3+1)) |
+ ( ((FxU16)0xf8 & r) >> 3);
+
+ stride=info.strideInBytes>>1;
+
+ /* This code is a bit slow... */
+
+ for(y=0;y<height;y++) {
+ p=((FxU16 *)info.lfbPtr)+px+((scrheight-(y+py))*stride);
+
+ for(x=0;;) {
+ DRAWBIT(7); DRAWBIT(6); DRAWBIT(5); DRAWBIT(4);
+ DRAWBIT(3); DRAWBIT(2); DRAWBIT(1); DRAWBIT(0);
+ pb++;
+ }
+ }
+
+ grLfbUnlock(GR_LFB_WRITE_ONLY,fxMesa->currentFB);
+
+#undef ISCLIPPED
+#undef DRAWBIT
+
+ return GL_TRUE;
+}
+
+static void fxDDFinish(GLcontext *ctx)
+{
+ FX_grFlush();
+}
+
+
+static GLint fxDDGetParameteri(const GLcontext *ctx, GLint param)
+{
+ switch(param) {
+ case DD_HAVE_HARDWARE_FOG:
+ return 1;
+ default:
+ fprintf(stderr,"fx Driver: internal error in fxDDGetParameteri(): %x\n",param);
+ fxCloseHardware();
+ exit(-1);
+ }
+}
+
+
+void fxDDSetNearFar(GLcontext *ctx, GLfloat n, GLfloat f)
+{
+ FX_CONTEXT(ctx)->new_state |= FX_NEW_FOG;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+}
+
+/* KW: Put the word Mesa in the render string because quakeworld
+ * checks for this rather than doing a glGet(GL_MAX_TEXTURE_SIZE).
+ * Why?
+ */
+static const GLubyte *fxDDGetString(GLcontext *ctx, GLenum name)
+{
+ static char *extensions="GL_EXT_blend_color GL_EXT_blend_minmax GL_EXT_blend_logic_op GL_EXT_blend_subtract GL_EXT_paletted_texture GL_EXT_point_parameters GL_EXT_polygon_offset GL_EXT_vertex_array GL_EXT_texture_object GL_EXT_texture3D GL_MESA_window_pos GL_MESA_resize_buffers GL_EXT_shared_texture_palette GL_EXT_rescale_normal GL_EXT_abgr GL_SGIS_texture_edge_clamp 3DFX_set_global_palette GL_FXMESA_global_texture_lod_bias";
+
+ static char buf[MAX_NUM_SST][64];
+
+ fxQueryHardware();
+
+ switch (name) {
+ case GL_RENDERER:
+ if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_VOODOO) {
+ sprintf(buf[glbCurrentBoard],"Mesa Glide v0.30 Voodoo_Graphics %d CARD/%d FB/%d TM/%d TMU/%s",
+ glbCurrentBoard,
+
+ (glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.sliDetect ?
+ (glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.fbRam*2) :
+ glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.fbRam),
+
+ glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.tmuConfig[GR_TMU0].tmuRam+
+ ((glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.nTexelfx>1) ?
+ glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.tmuConfig[GR_TMU1].tmuRam :
+ 0),
+
+ glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.nTexelfx,
+
+ (glbHWConfig.SSTs[glbCurrentBoard].sstBoard.VoodooConfig.sliDetect ? "SLI" : "NOSLI")
+ );
+ }
+ else {
+ if(glbHWConfig.SSTs[glbCurrentBoard].type==GR_SSTTYPE_SST96)
+ sprintf(buf[glbCurrentBoard],"Glide v0.30 Voodoo_Rush %d CARD/%d FB/%d TM/%d TMU/NOSLI",
+ glbCurrentBoard,
+
+ glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.fbRam,
+
+ glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.tmuConfig.tmuRam,
+
+ glbHWConfig.SSTs[glbCurrentBoard].sstBoard.SST96Config.nTexelfx
+ );
+ else
+ strcpy(buf[glbCurrentBoard],"Glide v0.30 UNKNOWN");
+ }
+ return (GLubyte *) buf[glbCurrentBoard];
+ case GL_EXTENSIONS:
+ return (GLubyte *) extensions;
+ default:
+ return NULL;
+ }
+}
+
+
+void fxDDInitExtensions( GLcontext *ctx )
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+
+ gl_extensions_add( ctx, DEFAULT_ON, "3DFX_set_global_palette", 0 );
+ gl_extensions_add( ctx, DEFAULT_ON, "GL_FXMESA_global_texture_lod_bias", 0);
+
+ if (!fxMesa->emulateTwoTMUs)
+ gl_extensions_disable( ctx, "GL_ARB_multitexture" );
+}
+
+/************************************************************************/
+/************************************************************************/
+/************************************************************************/
+
+/* This is a no-op, since the z-buffer is in hardware */
+static void fxAllocDepthBuffer(GLcontext *ctx)
+{
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxAllocDepthBuffer()\n");
+ }
+}
+
+/************************************************************************/
+/************************************************************************/
+/************************************************************************/
+
+/* Check if the hardware supports the current context
+ *
+ * Performs similar work to fxDDChooseRenderState() - should be merged.
+ */
+static GLboolean fxIsInHardware(GLcontext *ctx)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+
+ if (!ctx->Hint.AllowDrawMem)
+ return GL_TRUE; /* you'll take it and like it */
+
+ if((ctx->RasterMask & STENCIL_BIT) ||
+ ((ctx->Color.BlendEnabled) && (ctx->Color.BlendEquation!=GL_FUNC_ADD_EXT)) ||
+ ((ctx->Color.ColorLogicOpEnabled) && (ctx->Color.LogicOp!=GL_COPY)) ||
+ (ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) ||
+ (!((ctx->Color.ColorMask[RCOMP]==ctx->Color.ColorMask[GCOMP]) &&
+ (ctx->Color.ColorMask[GCOMP]==ctx->Color.ColorMask[BCOMP]) &&
+ (ctx->Color.ColorMask[ACOMP]==ctx->Color.ColorMask[ACOMP])))
+ )
+ return GL_FALSE;
+
+ /* Unsupported texture/multitexture cases */
+
+ if(fxMesa->emulateTwoTMUs) {
+ if((ctx->Enabled & (TEXTURE0_3D | TEXTURE1_3D)) ||
+ /* Not very well written ... */
+ ((ctx->Enabled & (TEXTURE0_1D | TEXTURE1_1D)) &&
+ ((ctx->Enabled & (TEXTURE0_2D | TEXTURE1_2D))!=(TEXTURE0_2D | TEXTURE1_2D)))
+ )
+ return GL_FALSE;
+
+ if((ctx->Texture.ReallyEnabled & TEXTURE0_2D) &&
+ (ctx->Texture.Unit[0].EnvMode==GL_BLEND))
+ return GL_FALSE;
+
+ if((ctx->Texture.ReallyEnabled & TEXTURE1_2D) &&
+ (ctx->Texture.Unit[1].EnvMode==GL_BLEND))
+ return GL_FALSE;
+
+
+ if (MESA_VERBOSE & (VERBOSE_DRIVER|VERBOSE_TEXTURE))
+ fprintf(stderr, "fxMesa: fxIsInHardware, envmode is %s/%s\n",
+ gl_lookup_enum_by_nr(ctx->Texture.Unit[0].EnvMode),
+ gl_lookup_enum_by_nr(ctx->Texture.Unit[1].EnvMode));
+
+ /* KW: This was wrong (I think) and I changed it... which doesn't mean
+ * it is now correct...
+ */
+ if((ctx->Enabled & (TEXTURE0_1D | TEXTURE0_2D | TEXTURE0_3D)) &&
+ (ctx->Enabled & (TEXTURE1_1D | TEXTURE1_2D | TEXTURE1_3D)))
+ {
+ /* Can't use multipass to blend a multitextured triangle - fall
+ * back to software.
+ */
+ if (!fxMesa->haveTwoTMUs && ctx->Color.BlendEnabled)
+ return GL_FALSE;
+
+ if ((ctx->Texture.Unit[0].EnvMode!=ctx->Texture.Unit[1].EnvMode) &&
+ (ctx->Texture.Unit[0].EnvMode!=GL_MODULATE) &&
+ (ctx->Texture.Unit[0].EnvMode!=GL_REPLACE)) /* q2, seems ok... */
+ {
+ if (MESA_VERBOSE&VERBOSE_DRIVER)
+ fprintf(stderr, "fxMesa: unsupported multitex env mode\n");
+
+ return GL_FALSE;
+ }
+ }
+ } else {
+ if((ctx->Enabled & (TEXTURE1_1D | TEXTURE1_2D | TEXTURE1_3D)) ||
+ /* Not very well written ... */
+ ((ctx->Enabled & TEXTURE0_1D) &&
+ (!(ctx->Enabled & TEXTURE0_2D)))
+ )
+ return GL_FALSE;
+
+
+ if((ctx->Texture.ReallyEnabled & TEXTURE0_2D) &&
+ (ctx->Texture.Unit[0].EnvMode==GL_BLEND))
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+
+
+#define INTERESTED (~(NEW_MODELVIEW|NEW_PROJECTION|NEW_PROJECTION|NEW_TEXTURE_MATRIX|NEW_USER_CLIP|NEW_CLIENT_STATE|NEW_TEXTURE_ENABLE))
+
+static void fxDDUpdateDDPointers(GLcontext *ctx)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLuint new_state = ctx->NewState;
+
+ if (MESA_VERBOSE&(VERBOSE_DRIVER|VERBOSE_STATE))
+ fprintf(stderr,"fxmesa: fxDDUpdateDDPointers(...)\n");
+
+ if (new_state & (NEW_RASTER_OPS|NEW_TEXTURING))
+ fxMesa->is_in_hardware = fxIsInHardware(ctx);
+
+ if (fxMesa->is_in_hardware) {
+ if (fxMesa->new_state)
+ fxSetupFXUnits(ctx);
+
+ if(new_state & INTERESTED) {
+ fxDDChooseRenderState( ctx );
+ fxMesa->RenderVBTables=fxDDChooseRenderVBTables(ctx);
+ ctx->Driver.RasterSetup=fxDDChooseSetupFunction(ctx);
+ }
+
+ ctx->Driver.PointsFunc=fxMesa->PointsFunc;
+ ctx->Driver.LineFunc=fxMesa->LineFunc;
+ ctx->Driver.TriangleFunc=fxMesa->TriangleFunc;
+ ctx->Driver.QuadFunc=fxMesa->QuadFunc;
+ ctx->Driver.RenderVBClippedTab=fxMesa->RenderVBTables[0];
+ ctx->Driver.RenderVBCulledTab=fxMesa->RenderVBTables[1];
+ ctx->Driver.RenderVBRawTab=fxMesa->RenderVBTables[2];
+
+ }
+
+ ctx->Driver.AllocDepthBuffer=fxAllocDepthBuffer;
+ ctx->Driver.DepthTestSpan=fxDDDepthTestSpanGeneric;
+ ctx->Driver.DepthTestPixels=fxDDDepthTestPixelsGeneric;
+ ctx->Driver.ReadDepthSpanFloat=fxDDReadDepthSpanFloat;
+ ctx->Driver.ReadDepthSpanInt=fxDDReadDepthSpanInt;
+ ctx->Driver.RenderStart = 0;
+}
+
+
+void fxSetupDDPointers(GLcontext *ctx)
+{
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxSetupDDPointers()\n");
+ }
+
+ ctx->Driver.UpdateState=fxDDUpdateDDPointers;
+
+ ctx->Driver.GetString=fxDDGetString;
+
+ ctx->Driver.Dither=fxDDDither;
+
+ ctx->Driver.NearFar=fxDDSetNearFar;
+
+ ctx->Driver.GetParameteri=fxDDGetParameteri;
+
+ ctx->Driver.ClearIndex=NULL;
+ ctx->Driver.ClearColor=fxDDClearColor;
+ ctx->Driver.Clear=fxDDClear;
+
+ ctx->Driver.Index=NULL;
+ ctx->Driver.Color=fxDDSetColor;
+
+ ctx->Driver.SetBuffer=fxDDSetBuffer;
+ ctx->Driver.GetBufferSize=fxDDBufferSize;
+
+ ctx->Driver.Bitmap=fxDDDrawBitMap;
+ ctx->Driver.DrawPixels=NULL;
+
+ ctx->Driver.Finish=fxDDFinish;
+ ctx->Driver.Flush=NULL;
+
+ ctx->Driver.RenderStart=NULL;
+ ctx->Driver.RenderFinish=NULL;
+
+ ctx->Driver.TexEnv=fxDDTexEnv;
+ ctx->Driver.TexImage=fxDDTexImg;
+ ctx->Driver.TexSubImage=fxDDTexSubImg;
+ ctx->Driver.TexParameter=fxDDTexParam;
+ ctx->Driver.BindTexture=fxDDTexBind;
+ ctx->Driver.DeleteTexture=fxDDTexDel;
+ ctx->Driver.UpdateTexturePalette=fxDDTexPalette;
+ ctx->Driver.UseGlobalTexturePalette=fxDDTexUseGlbPalette;
+
+ ctx->Driver.RectFunc=NULL;
+
+ ctx->Driver.AlphaFunc=fxDDAlphaFunc;
+ ctx->Driver.BlendFunc=fxDDBlendFunc;
+ ctx->Driver.DepthFunc=fxDDDepthFunc;
+ ctx->Driver.DepthMask=fxDDDepthMask;
+ ctx->Driver.ColorMask=fxDDColorMask;
+ ctx->Driver.Fogfv=fxDDFogfv;
+ ctx->Driver.Scissor=fxDDScissor;
+ ctx->Driver.FrontFace=fxDDFrontFace;
+ ctx->Driver.CullFace=fxDDCullFace;
+ ctx->Driver.ShadeModel=fxDDShadeModel;
+ ctx->Driver.Enable=fxDDEnable;
+
+
+ ctx->Driver.RegisterVB=fxDDRegisterVB;
+ ctx->Driver.UnregisterVB=fxDDUnregisterVB;
+
+ ctx->Driver.RegisterPipelineStages = fxDDRegisterPipelineStages;
+
+ ctx->Driver.OptimizeImmediatePipeline = 0; /* nothing done yet */
+ ctx->Driver.OptimizePrecalcPipeline = 0;
+
+/* if (getenv("MESA_USE_FAST") || getenv("FX_USE_FAST")) */
+/* ctx->Driver.OptimizePrecalcPipeline = fxDDOptimizePrecalcPipeline; */
+
+ if (!getenv("FX_NO_FAST"))
+ ctx->Driver.BuildPrecalcPipeline = fxDDBuildPrecalcPipeline;
+
+ ctx->Driver.TriangleCaps = DD_TRI_CULL|DD_TRI_OFFSET|DD_TRI_LIGHT_TWOSIDE;
+
+ fxSetupDDSpanPointers(ctx);
+
+ FX_CONTEXT(ctx)->render_index = 1; /* force an update */
+ fxDDUpdateDDPointers(ctx);
+}
+
+
+#else
+
+
+/*
+ * Need this to provide at least one external definition.
+ */
+
+int gl_fx_dummy_function_dd(void)
+{
+ return 0;
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/fxddspan.c b/src/mesa/drivers/glide/fxddspan.c
new file mode 100644
index 0000000000..fc7c38d5c4
--- /dev/null
+++ b/src/mesa/drivers/glide/fxddspan.c
@@ -0,0 +1,817 @@
+/* -*- mode: C; tab-width:8; -*-
+
+ fxdd.c - 3Dfx VooDoo Mesa span and pixel functions
+*/
+
+/*
+ * 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.
+ *
+ * See the file fxapi.c for more informations about authors
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#if defined(FX)
+
+#include "fxdrv.h"
+
+#ifdef _MSC_VER
+#ifdef _WIN32
+#pragma warning( disable : 4090 4022 )
+/* 4101 : "different 'const' qualifier"
+ * 4022 : "pointer mistmatch for actual parameter 'n'
+ */
+#endif
+#endif
+
+
+#if !defined(FXMESA_USE_ARGB)
+
+ #define LFB_WRITE_SPAN_MESA(dst_buffer,dst_x,dst_y,src_width,src_stride,src_data) \
+ grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_width,1,GR_LFB_SRC_FMT_8888,src_stride,src_data)
+#else /* defined(FXMESA_USE_RGBA) */
+
+ #define MESACOLOR_TO_ARGB(c) ( \
+ ( ((unsigned int)(c[ACOMP]))<<24 ) | \
+ ( ((unsigned int)(c[RCOMP]))<<16 ) | \
+ ( ((unsigned int)(c[GCOMP]))<<8 ) | \
+ ( (unsigned int)(c[BCOMP])) )
+
+ /* inline */ void LFB_WRITE_SPAN_MESA(GrBuffer_t dst_buffer,
+ FxU32 dst_x, FxU32 dst_y,
+ /* GrLfbSrcFmt_t src_format, format is GR_LFB_SRC_FMT_8888 */
+ FxU32 src_width,/* FxU32 src_height, height is 1 */
+ FxI32 src_stride, void *src_data )
+ {
+ /* Covert to ARGB */
+ GLubyte (*rgba)[4] = src_data;
+ GLuint argb[MAX_WIDTH];
+ int i;
+
+ for (i = 0; i < src_width; i++)
+ {
+ argb[i] = MESACOLOR_TO_ARGB(rgba[i]);
+ }
+ FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,GR_LFB_SRC_FMT_8888,src_width,1,src_stride,(void*)argb);
+ }
+#endif
+
+/************************************************************************/
+/***** Span functions *****/
+/************************************************************************/
+
+static void fxDDWriteRGBASpan(const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4], const GLubyte mask[])
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLuint i;
+ GLint bottom=fxMesa->height-1;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDWriteRGBASpan(...)\n");
+ }
+
+ if (mask) {
+ int span=0;
+
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ ++span;
+ } else {
+ if (span > 0) {
+ LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x+i-span, bottom-y,
+ /* GR_LFB_SRC_FMT_8888,*/ span, /*1,*/ 0, (void *) rgba[i-span] );
+ span = 0;
+ }
+ }
+ }
+
+ if (span > 0)
+ LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x+n-span, bottom-y,
+ /* GR_LFB_SRC_FMT_8888, */ span, /*1,*/ 0, (void *) rgba[n-span] );
+ } else
+ LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x, bottom-y,/* GR_LFB_SRC_FMT_8888,*/
+ n,/* 1,*/ 0, (void *) rgba );
+}
+
+
+static void fxDDWriteRGBSpan(const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgb[][3], const GLubyte mask[])
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLuint i;
+ GLint bottom=fxMesa->height-1;
+ GLubyte rgba[MAX_WIDTH][4];
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDWriteRGBSpan()\n");
+ }
+
+ if (mask) {
+ int span=0;
+
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ rgba[span][RCOMP] = rgb[i][0];
+ rgba[span][GCOMP] = rgb[i][1];
+ rgba[span][BCOMP] = rgb[i][2];
+ rgba[span][ACOMP] = 255;
+ ++span;
+ } else {
+ if (span > 0) {
+ LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x+i-span, bottom-y,
+ /*GR_LFB_SRC_FMT_8888,*/ span,/* 1,*/ 0, (void *) rgba );
+ span = 0;
+ }
+ }
+ }
+
+ if (span > 0)
+ LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x+n-span, bottom-y,
+ /*GR_LFB_SRC_FMT_8888,*/ span,/* 1,*/ 0, (void *) rgba );
+ } else {
+ for (i=0;i<n;i++) {
+ rgba[i][RCOMP]=rgb[i][0];
+ rgba[i][GCOMP]=rgb[i][1];
+ rgba[i][BCOMP]=rgb[i][2];
+ rgba[i][ACOMP]=255;
+ }
+
+ LFB_WRITE_SPAN_MESA( fxMesa->currentFB, x, bottom-y,/* GR_LFB_SRC_FMT_8888,*/
+ n,/* 1,*/ 0, (void *) rgba );
+ }
+}
+
+
+static void fxDDWriteMonoRGBASpan(const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte mask[])
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLuint i;
+ GLint bottom=fxMesa->height-1;
+ GLuint data[MAX_WIDTH];
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDWriteMonoRGBASpan(...)\n");
+ }
+
+ if (mask) {
+ int span=0;
+
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ data[span] = (GLuint) fxMesa->color;
+ ++span;
+ } else {
+ if (span > 0) {
+ FX_grLfbWriteRegion( fxMesa->currentFB, x+i-span, bottom-y,
+ GR_LFB_SRC_FMT_8888, span, 1, 0,
+ (void *) data );
+ span = 0;
+ }
+ }
+ }
+
+ if (span > 0)
+ FX_grLfbWriteRegion( fxMesa->currentFB, x+n-span, bottom-y,
+ GR_LFB_SRC_FMT_8888, span, 1, 0,
+ (void *) data );
+ } else {
+ for (i=0;i<n;i++) {
+ data[i]=(GLuint) fxMesa->color;
+ }
+
+ FX_grLfbWriteRegion( fxMesa->currentFB, x, bottom-y, GR_LFB_SRC_FMT_8888,
+ n, 1, 0, (void *) data );
+ }
+}
+
+
+static void fxDDReadRGBASpan(const GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLubyte rgba[][4])
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLushort data[MAX_WIDTH];
+ GLuint i;
+ GLint bottom=fxMesa->height-1;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDReadRGBASpan(...)\n");
+ }
+
+ assert(n < MAX_WIDTH);
+
+ grLfbReadRegion( fxMesa->currentFB, x, bottom-y, n, 1, 0, data);
+ for (i=0;i<n;i++) {
+#if FXMESA_USE_ARGB
+ rgba[i][RCOMP]=(data[i] & 0xF800) >> 8;
+ rgba[i][GCOMP]=(data[i] & 0x07E0) >> 3;
+ rgba[i][BCOMP]=(data[i] & 0x001F) << 3;
+#else
+ rgba[i][RCOMP]=(data[i] & 0x001f) << 3;
+ rgba[i][GCOMP]=(data[i] & 0x07e0) >> 3;
+ rgba[i][BCOMP]=(data[i] & 0xf800) >> 8;
+#endif
+ rgba[i][ACOMP]=255;
+ }
+
+}
+
+/************************************************************************/
+/***** Pixel functions *****/
+/************************************************************************/
+
+static void fxDDWriteRGBAPixels(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ CONST GLubyte rgba[][4], const GLubyte mask[])
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLuint i;
+ GLint bottom=fxMesa->height-1;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDWriteRGBAPixels(...)\n");
+ }
+
+ for(i=0;i<n;i++)
+ if(mask[i])
+ LFB_WRITE_SPAN_MESA(fxMesa->currentFB,x[i],bottom-y[i],
+ /*GR_LFB_SRC_FMT_8888,*/1,/*1,*/0,(void *)rgba[i]);
+}
+
+static void fxDDWriteMonoRGBAPixels(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte mask[])
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLuint i;
+ GLint bottom=fxMesa->height-1;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDWriteMonoRGBAPixels(...)\n");
+ }
+
+ for(i=0;i<n;i++)
+ if(mask[i])
+ FX_grLfbWriteRegion(fxMesa->currentFB,x[i],bottom-y[i],
+ GR_LFB_SRC_FMT_8888,1,1,0,(void *) &fxMesa->color);
+}
+
+static void fxDDReadRGBAPixels(const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[])
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLuint i;
+ GLint bottom=fxMesa->height-1;
+ GLushort data;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDReadRGBAPixels(...)\n");
+ }
+
+ for(i=0;i<n;i++)
+ if(mask[i]) {
+ grLfbReadRegion(fxMesa->currentFB,x[i],bottom-y[i],1,1,0,&data);
+ #if FXMESA_USE_ARGB
+ rgba[i][RCOMP]=(data & 0xF800) >> 8;
+ rgba[i][GCOMP]=(data & 0x07E0) >> 3;
+ rgba[i][BCOMP]=(data & 0x001F) >> 8;
+ #else
+ rgba[i][RCOMP]=(data & 0x001f) << 3;
+ rgba[i][GCOMP]=(data & 0x07e0) >> 3;
+ rgba[i][BCOMP]=(data & 0xf800) >> 8;
+ #endif
+ /* the alpha value should be read from the auxiliary buffer when required */
+
+ rgba[i][ACOMP]=255;
+ }
+}
+
+/************************************************************************/
+/***** Depth functions *****/
+/************************************************************************/
+
+void fxDDReadDepthSpanFloat(GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLfloat depth[])
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLuint i;
+ GLint bottom=fxMesa->height-1;
+ GLushort data[MAX_WIDTH];
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDReadDepthSpanFloat(...)\n");
+ }
+
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x,bottom-y,n,1,0,data);
+
+ /*
+ convert the read values to float values [0.0 .. 1.0].
+ */
+ for(i=0;i<n;i++)
+ depth[i]=data[i]/65535.0f;
+}
+
+void fxDDReadDepthSpanInt(GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLdepth depth[])
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLint bottom=fxMesa->height-1;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDReadDepthSpanInt(...)\n");
+ }
+
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x,bottom-y,n,1,0,depth);
+}
+
+GLuint fxDDDepthTestSpanGeneric(GLcontext *ctx,
+ GLuint n, GLint x, GLint y, const GLdepth z[],
+ GLubyte mask[])
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLushort depthdata[MAX_WIDTH];
+ GLdepth *zptr=depthdata;
+ GLubyte *m=mask;
+ GLuint i;
+ GLuint passed=0;
+ GLint bottom=fxMesa->height-1;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDDepthTestSpanGeneric(...)\n");
+ }
+
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x,bottom-y,n,1,0,depthdata);
+
+ /* switch cases ordered from most frequent to less frequent */
+ switch (ctx->Depth.Func) {
+ case GL_LESS:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0; i<n; i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] < *zptr) {
+ /* pass */
+ *zptr = z[i];
+ passed++;
+ } else {
+ /* fail */
+ *m = 0;
+ }
+ }
+ }
+ } else {
+ /* Don't update Z buffer */
+ for (i=0; i<n; i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] < *zptr) {
+ /* pass */
+ passed++;
+ } else {
+ *m = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_LEQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] <= *zptr) {
+ *zptr = z[i];
+ passed++;
+ } else {
+ *m = 0;
+ }
+ }
+ }
+ } else {
+ /* Don't update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] <= *zptr) {
+ /* pass */
+ passed++;
+ } else {
+ *m = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_GEQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] >= *zptr) {
+ *zptr = z[i];
+ passed++;
+ } else {
+ *m = 0;
+ }
+ }
+ }
+ } else {
+ /* Don't update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] >= *zptr) {
+ /* pass */
+ passed++;
+ } else {
+ *m = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_GREATER:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] > *zptr) {
+ *zptr = z[i];
+ passed++;
+ } else {
+ *m = 0;
+ }
+ }
+ }
+ } else {
+ /* Don't update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] > *zptr) {
+ /* pass */
+ passed++;
+ } else {
+ *m = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_NOTEQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] != *zptr) {
+ *zptr = z[i];
+ passed++;
+ } else {
+ *m = 0;
+ }
+ }
+ }
+ } else {
+ /* Don't update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] != *zptr) {
+ /* pass */
+ passed++;
+ } else {
+ *m = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_EQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] == *zptr) {
+ *zptr = z[i];
+ passed++;
+ } else {
+ *m =0;
+ }
+ }
+ }
+ } else {
+ /* Don't update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] == *zptr) {
+ /* pass */
+ passed++;
+ } else {
+ *m =0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_ALWAYS:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ *zptr = z[i];
+ passed++;
+ }
+ }
+ } else {
+ /* Don't update Z buffer or mask */
+ passed = n;
+ }
+ break;
+ case GL_NEVER:
+ for (i=0;i<n;i++) {
+ mask[i] = 0;
+ }
+ break;
+ default:
+ ;
+ } /*switch*/
+
+ if(passed)
+ FX_grLfbWriteRegion(GR_BUFFER_AUXBUFFER,x,bottom-y,GR_LFB_SRC_FMT_ZA16,n,1,0,depthdata);
+
+ return passed;
+}
+
+void fxDDDepthTestPixelsGeneric(GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLdepth z[], GLubyte mask[])
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLdepth zval;
+ GLuint i;
+ GLint bottom=fxMesa->height-1;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDDepthTestPixelsGeneric(...)\n");
+ }
+
+ /* switch cases ordered from most frequent to less frequent */
+ switch (ctx->Depth.Func) {
+ case GL_LESS:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval);
+ if (z[i] < zval) {
+ /* pass */
+ FX_grLfbWriteRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],GR_LFB_SRC_FMT_ZA16,1,1,0,(void*)&z[i]);
+ } else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ } else {
+ /* Don't update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval);
+ if (z[i] < zval) {
+ /* pass */
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_LEQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval);
+ if (z[i] <= zval) {
+ /* pass */
+ FX_grLfbWriteRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],GR_LFB_SRC_FMT_ZA16,1,1,0,(void*)&z[i]);
+ } else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ } else {
+ /* Don't update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval);
+ if (z[i] <= zval) {
+ /* pass */
+ } else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_GEQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval);
+ if (z[i] >= zval) {
+ /* pass */
+ FX_grLfbWriteRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],GR_LFB_SRC_FMT_ZA16,1,1,0,(void*)&z[i]);
+ } else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ } else {
+ /* Don't update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval);
+ if (z[i] >= zval) {
+ /* pass */
+ } else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_GREATER:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval);
+ if (z[i] > zval) {
+ /* pass */
+ FX_grLfbWriteRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],GR_LFB_SRC_FMT_ZA16,1,1,0,(void*)&z[i]);
+ } else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ } else {
+ /* Don't update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval);
+ if (z[i] > zval) {
+ /* pass */
+ } else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_NOTEQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval);
+ if (z[i] != zval) {
+ /* pass */
+ FX_grLfbWriteRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],GR_LFB_SRC_FMT_ZA16,1,1,0,(void*)&z[i]);
+ } else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ } else {
+ /* Don't update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval);
+ if (z[i] != zval) {
+ /* pass */
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_EQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval);
+ if (z[i] == zval) {
+ /* pass */
+ FX_grLfbWriteRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],GR_LFB_SRC_FMT_ZA16,1,1,0,(void*)&z[i]);
+ } else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ } else {
+ /* Don't update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ grLfbReadRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],1,1,0,&zval);
+ if (z[i] == zval) {
+ /* pass */
+ } else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_ALWAYS:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ FX_grLfbWriteRegion(GR_BUFFER_AUXBUFFER,x[i],bottom-y[i],GR_LFB_SRC_FMT_ZA16,1,1,0,(void*)&z[i]);
+ }
+ }
+ } else {
+ /* Don't update Z buffer or mask */
+ }
+ break;
+ case GL_NEVER:
+ /* depth test never passes */
+ for (i=0;i<n;i++) {
+ mask[i] = 0;
+ }
+ break;
+ default:
+ ;
+ } /*switch*/
+}
+
+/************************************************************************/
+
+
+void fxSetupDDSpanPointers(GLcontext *ctx)
+{
+ ctx->Driver.WriteRGBASpan =fxDDWriteRGBASpan;
+ ctx->Driver.WriteRGBSpan =fxDDWriteRGBSpan;
+ ctx->Driver.WriteMonoRGBASpan =fxDDWriteMonoRGBASpan;
+ ctx->Driver.WriteRGBAPixels =fxDDWriteRGBAPixels;
+ ctx->Driver.WriteMonoRGBAPixels =fxDDWriteMonoRGBAPixels;
+
+ ctx->Driver.WriteCI8Span =NULL;
+ ctx->Driver.WriteCI32Span =NULL;
+ ctx->Driver.WriteMonoCISpan =NULL;
+ ctx->Driver.WriteCI32Pixels =NULL;
+ ctx->Driver.WriteMonoCIPixels =NULL;
+
+ ctx->Driver.ReadRGBASpan =fxDDReadRGBASpan;
+ ctx->Driver.ReadRGBAPixels =fxDDReadRGBAPixels;
+
+ ctx->Driver.ReadCI32Span =NULL;
+ ctx->Driver.ReadCI32Pixels =NULL;
+}
+
+
+#else
+
+
+/*
+ * Need this to provide at least one external definition.
+ */
+
+int gl_fx_dummy_function_span(void)
+{
+ return 0;
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/fxddtex.c b/src/mesa/drivers/glide/fxddtex.c
new file mode 100644
index 0000000000..05ef77570c
--- /dev/null
+++ b/src/mesa/drivers/glide/fxddtex.c
@@ -0,0 +1,1299 @@
+/* -*- mode: C; tab-width:8; -*-
+
+ fxddtex.c - 3Dfx VooDoo Texture mapping functions
+*/
+
+/*
+ * 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.
+ *
+ * See the file fxapi.c for more informations about authors
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#if defined(FX)
+
+#include "fxdrv.h"
+
+/************************************************************************/
+/*************************** Texture Mapping ****************************/
+/************************************************************************/
+
+static void fxTexInvalidate(GLcontext *ctx, struct gl_texture_object *tObj)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxTexInfo *ti;
+
+ fxTMMoveOutTM(fxMesa,tObj); /* TO DO: SLOW but easy to write */
+
+ ti=(tfxTexInfo *)tObj->DriverData;
+ ti->validated=GL_FALSE;
+ fxMesa->new_state|=FX_NEW_TEXTURING;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+}
+
+static tfxTexInfo *fxAllocTexObjData(fxMesaContext fxMesa)
+{
+ tfxTexInfo *ti;
+ int i;
+
+ if(!(ti=malloc(sizeof(tfxTexInfo)))) {
+ fprintf(stderr,"fx Driver: out of memory !\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ ti->validated=GL_FALSE;
+ ti->tmi.isInTM=GL_FALSE;
+
+ ti->tmi.whichTMU=FX_TMU_NONE;
+
+ ti->tmi.tm[FX_TMU0]=NULL;
+ ti->tmi.tm[FX_TMU1]=NULL;
+
+ ti->minFilt=GR_TEXTUREFILTER_POINT_SAMPLED;
+ ti->maxFilt=GR_TEXTUREFILTER_BILINEAR;
+
+ ti->sClamp=GR_TEXTURECLAMP_WRAP;
+ ti->tClamp=GR_TEXTURECLAMP_WRAP;
+
+ if(fxMesa->haveTwoTMUs) {
+ ti->mmMode=GR_MIPMAP_NEAREST;
+ ti->LODblend=FXTRUE;
+ } else {
+ ti->mmMode=GR_MIPMAP_NEAREST_DITHER;
+ ti->LODblend=FXFALSE;
+ }
+
+ for(i=0;i<MAX_TEXTURE_LEVELS;i++) {
+ ti->tmi.mipmapLevel[i].used=GL_FALSE;
+ ti->tmi.mipmapLevel[i].data=NULL;
+ }
+
+ return ti;
+}
+
+void fxDDTexBind(GLcontext *ctx, GLenum target, struct gl_texture_object *tObj)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxTexInfo *ti;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDTexBind(%d,%x)\n",tObj->Name,(GLuint)tObj->DriverData);
+ }
+
+ if(target!=GL_TEXTURE_2D)
+ return;
+
+ if(!tObj->DriverData)
+ tObj->DriverData=fxAllocTexObjData(fxMesa);
+
+ ti=(tfxTexInfo *)tObj->DriverData;
+
+ fxMesa->texBindNumber++;
+ ti->tmi.lastTimeUsed=fxMesa->texBindNumber;
+
+ fxMesa->new_state|=FX_NEW_TEXTURING;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+}
+
+void fxDDTexEnv(GLcontext *ctx, GLenum pname, const GLfloat *param)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ if(param)
+ fprintf(stderr,"fxmesa: texenv(%x,%x)\n",pname,(GLint)(*param));
+ else
+ fprintf(stderr,"fxmesa: texenv(%x)\n",pname);
+ }
+
+ fxMesa->new_state|=FX_NEW_TEXTURING;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+}
+
+void fxDDTexParam(GLcontext *ctx, GLenum target, struct gl_texture_object *tObj,
+ GLenum pname, const GLfloat *params)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLenum param=(GLenum)(GLint)params[0];
+ tfxTexInfo *ti;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDTexParam(%d,%x,%x,%x)\n",tObj->Name,(GLuint)tObj->DriverData,pname,param);
+ }
+
+ if(target!=GL_TEXTURE_2D)
+ return;
+
+ if(!tObj->DriverData)
+ tObj->DriverData=fxAllocTexObjData(fxMesa);
+
+ ti=(tfxTexInfo *)tObj->DriverData;
+
+ switch(pname) {
+
+ case GL_TEXTURE_MIN_FILTER:
+ switch(param) {
+ case GL_NEAREST:
+ ti->mmMode=GR_MIPMAP_DISABLE;
+ ti->minFilt=GR_TEXTUREFILTER_POINT_SAMPLED;
+ ti->LODblend=FXFALSE;
+ break;
+ case GL_LINEAR:
+ ti->mmMode=GR_MIPMAP_DISABLE;
+ ti->minFilt=GR_TEXTUREFILTER_BILINEAR;
+ ti->LODblend=FXFALSE;
+ break;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ ti->mmMode=GR_MIPMAP_NEAREST;
+ ti->minFilt=GR_TEXTUREFILTER_POINT_SAMPLED;
+ ti->LODblend=FXFALSE;
+ break;
+ case GL_LINEAR_MIPMAP_NEAREST:
+ ti->mmMode=GR_MIPMAP_NEAREST;
+ ti->minFilt=GR_TEXTUREFILTER_BILINEAR;
+ ti->LODblend=FXFALSE;
+ break;
+ case GL_NEAREST_MIPMAP_LINEAR:
+ if(fxMesa->haveTwoTMUs) {
+ ti->mmMode=GR_MIPMAP_NEAREST;
+ ti->LODblend=FXTRUE;
+ } else {
+ ti->mmMode=GR_MIPMAP_NEAREST_DITHER;
+ ti->LODblend=FXFALSE;
+ }
+ ti->minFilt=GR_TEXTUREFILTER_POINT_SAMPLED;
+ break;
+ case GL_LINEAR_MIPMAP_LINEAR:
+ if(fxMesa->haveTwoTMUs) {
+ ti->mmMode=GR_MIPMAP_NEAREST;
+ ti->LODblend=FXTRUE;
+ } else {
+ ti->mmMode=GR_MIPMAP_NEAREST_DITHER;
+ ti->LODblend=FXFALSE;
+ }
+ ti->minFilt=GR_TEXTUREFILTER_BILINEAR;
+ break;
+ default:
+ break;
+ }
+ fxTexInvalidate(ctx,tObj);
+ break;
+
+ case GL_TEXTURE_MAG_FILTER:
+ switch(param) {
+ case GL_NEAREST:
+ ti->maxFilt=GR_TEXTUREFILTER_POINT_SAMPLED;
+ break;
+ case GL_LINEAR:
+ ti->maxFilt=GR_TEXTUREFILTER_BILINEAR;
+ break;
+ default:
+ break;
+ }
+ fxTexInvalidate(ctx,tObj);
+ break;
+
+ case GL_TEXTURE_WRAP_S:
+ switch(param) {
+ case GL_CLAMP:
+ ti->sClamp=GR_TEXTURECLAMP_CLAMP;
+ break;
+ case GL_REPEAT:
+ ti->sClamp=GR_TEXTURECLAMP_WRAP;
+ break;
+ default:
+ break;
+ }
+ fxMesa->new_state|=FX_NEW_TEXTURING;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ break;
+
+ case GL_TEXTURE_WRAP_T:
+ switch(param) {
+ case GL_CLAMP:
+ ti->tClamp=GR_TEXTURECLAMP_CLAMP;
+ break;
+ case GL_REPEAT:
+ ti->tClamp=GR_TEXTURECLAMP_WRAP;
+ break;
+ default:
+ break;
+ }
+ fxMesa->new_state|=FX_NEW_TEXTURING;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ break;
+
+ case GL_TEXTURE_BORDER_COLOR:
+ /* TO DO */
+ break;
+
+ case GL_TEXTURE_MIN_LOD:
+ /* TO DO */
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ /* TO DO */
+ break;
+ case GL_TEXTURE_BASE_LEVEL:
+ fxTexInvalidate(ctx,tObj);
+ break;
+ case GL_TEXTURE_MAX_LEVEL:
+ fxTexInvalidate(ctx,tObj);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void fxDDTexDel(GLcontext *ctx, struct gl_texture_object *tObj)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDTexDel(%d,%x)\n",tObj->Name,(GLuint)ti);
+ }
+
+ if(!ti)
+ return;
+
+ fxTMFreeTexture(fxMesa,tObj);
+
+ free(ti);
+ tObj->DriverData=NULL;
+
+ ctx->NewState|=NEW_TEXTURING;
+}
+
+void fxDDTexPalette(GLcontext *ctx, struct gl_texture_object *tObj)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ int i;
+ FxU32 r,g,b,a;
+ tfxTexInfo *ti;
+
+ if(tObj) {
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDTexPalette(%d,%x)\n",tObj->Name,(GLuint)tObj->DriverData);
+ }
+
+ if(tObj->PaletteFormat!=GL_RGBA) {
+#ifndef FX_SILENT
+ fprintf(stderr,"fx Driver: unsupported palette format in texpalette()\n");
+#endif
+ return;
+ }
+
+ if(tObj->PaletteSize>256) {
+#ifndef FX_SILENT
+ fprintf(stderr,"fx Driver: unsupported palette size in texpalette()\n");
+#endif
+ return;
+ }
+
+ if(!tObj->DriverData)
+ tObj->DriverData=fxAllocTexObjData(fxMesa);
+
+ ti=(tfxTexInfo *)tObj->DriverData;
+
+ for(i=0;i<tObj->PaletteSize;i++) {
+ r=tObj->Palette[i*4];
+ g=tObj->Palette[i*4+1];
+ b=tObj->Palette[i*4+2];
+ a=tObj->Palette[i*4+3];
+ ti->palette.data[i]=(a<<24)|(r<<16)|(g<<8)|b;
+ }
+
+ fxTexInvalidate(ctx,tObj);
+ } else {
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDTexPalette(global)\n");
+ }
+ if(ctx->Texture.PaletteFormat!=GL_RGBA) {
+#ifndef FX_SILENT
+ fprintf(stderr,"fx Driver: unsupported palette format in texpalette()\n");
+#endif
+ return;
+ }
+
+ if(ctx->Texture.PaletteSize>256) {
+#ifndef FX_SILENT
+ fprintf(stderr,"fx Driver: unsupported palette size in texpalette()\n");
+#endif
+ return;
+ }
+
+ for(i=0;i<ctx->Texture.PaletteSize;i++) {
+ r=ctx->Texture.Palette[i*4];
+ g=ctx->Texture.Palette[i*4+1];
+ b=ctx->Texture.Palette[i*4+2];
+ a=ctx->Texture.Palette[i*4+3];
+ fxMesa->glbPalette.data[i]=(a<<24)|(r<<16)|(g<<8)|b;
+ }
+
+ fxMesa->new_state|=FX_NEW_TEXTURING;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ }
+}
+
+void fxDDTexUseGlbPalette(GLcontext *ctx, GLboolean state)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDTexUseGlbPalette(%d)\n",state);
+ }
+
+ if(state) {
+ fxMesa->haveGlobalPaletteTexture=1;
+
+ FX_grTexDownloadTable(GR_TMU0,GR_TEXTABLE_PALETTE,&(fxMesa->glbPalette));
+ if (fxMesa->haveTwoTMUs)
+ FX_grTexDownloadTable(GR_TMU1,GR_TEXTABLE_PALETTE,&(fxMesa->glbPalette));
+ } else {
+ fxMesa->haveGlobalPaletteTexture=0;
+
+ if((ctx->Texture.Unit[0].Current==ctx->Texture.Unit[0].CurrentD[2]) &&
+ (ctx->Texture.Unit[0].Current!=NULL)) {
+ struct gl_texture_object *tObj=ctx->Texture.Unit[0].Current;
+ tfxTexInfo *ti;
+
+ if(!tObj->DriverData)
+ tObj->DriverData=fxAllocTexObjData(fxMesa);
+
+ ti=(tfxTexInfo *)tObj->DriverData;
+
+ fxTexInvalidate(ctx,tObj);
+ }
+ }
+}
+
+static int logbase2(int n)
+{
+ GLint i = 1;
+ GLint log2 = 0;
+
+ if (n<0) {
+ return -1;
+ }
+
+ while (n > i) {
+ i *= 2;
+ log2++;
+ }
+ if (i != n) {
+ return -1;
+ }
+ else {
+ return log2;
+ }
+}
+
+/* Need different versions for different cpus.
+ */
+#define INT_TRICK(l2) (0x800000 * l2)
+
+
+int fxTexGetInfo(int w, int h, GrLOD_t *lodlevel, GrAspectRatio_t *ar,
+ float *sscale, float *tscale,
+ int *i_sscale, int *i_tscale,
+ int *wscale, int *hscale)
+{
+
+ static GrLOD_t lod[9]={GR_LOD_256,GR_LOD_128,GR_LOD_64,GR_LOD_32,
+ GR_LOD_16,GR_LOD_8,GR_LOD_4,GR_LOD_2,GR_LOD_1};
+
+ int logw,logh,ws,hs;
+ GrLOD_t l;
+ GrAspectRatio_t aspectratio;
+ float s,t;
+ int is,it;
+
+ logw=logbase2(w);
+ logh=logbase2(h);
+
+ switch(logw-logh) {
+ case 0:
+ aspectratio=GR_ASPECT_1x1;
+ l=lod[8-logw];
+ s=t=256.0f;
+ is=it=INT_TRICK(8);
+ ws=hs=1;
+ break;
+ case 1:
+ aspectratio=GR_ASPECT_2x1;
+ l=lod[8-logw];
+ s=256.0f;
+ t=128.0f;
+ is=INT_TRICK(8);it=INT_TRICK(7);
+ ws=1;
+ hs=1;
+ break;
+ case 2:
+ aspectratio=GR_ASPECT_4x1;
+ l=lod[8-logw];
+ s=256.0f;
+ t=64.0f;
+ is=INT_TRICK(8);it=INT_TRICK(6);
+ ws=1;
+ hs=1;
+ break;
+ case 3:
+ aspectratio=GR_ASPECT_8x1;
+ l=lod[8-logw];
+ s=256.0f;
+ t=32.0f;
+ is=INT_TRICK(8);it=INT_TRICK(5);
+ ws=1;
+ hs=1;
+ break;
+ case 4:
+ aspectratio=GR_ASPECT_8x1;
+ l=lod[8-logw];
+ s=256.0f;
+ t=32.0f;
+ is=INT_TRICK(8);it=INT_TRICK(5);
+ ws=1;
+ hs=2;
+ break;
+ case 5:
+ aspectratio=GR_ASPECT_8x1;
+ l=lod[8-logw];
+ s=256.0f;
+ t=32.0f;
+ is=INT_TRICK(8);it=INT_TRICK(5);
+ ws=1;
+ hs=4;
+ break;
+ case 6:
+ aspectratio=GR_ASPECT_8x1;
+ l=lod[8-logw];
+ s=256.0f;
+ t=32.0f;
+ is=INT_TRICK(8);it=INT_TRICK(5);
+ ws=1;
+ hs=8;
+ break;
+ case 7:
+ aspectratio=GR_ASPECT_8x1;
+ l=lod[8-logw];
+ s=256.0f;
+ t=32.0f;
+ is=INT_TRICK(8);it=INT_TRICK(5);
+ ws=1;
+ hs=16;
+ break;
+ case 8:
+ aspectratio=GR_ASPECT_8x1;
+ l=lod[8-logw];
+ s=256.0f;
+ t=32.0f;
+ is=INT_TRICK(8);it=INT_TRICK(5);
+ ws=1;
+ hs=32;
+ break;
+ case -1:
+ aspectratio=GR_ASPECT_1x2;
+ l=lod[8-logh];
+ s=128.0f;
+ t=256.0f;
+ is=INT_TRICK(7);it=INT_TRICK(8);
+ ws=1;
+ hs=1;
+ break;
+ case -2:
+ aspectratio=GR_ASPECT_1x4;
+ l=lod[8-logh];
+ s=64.0f;
+ t=256.0f;
+ is=INT_TRICK(6);it=INT_TRICK(8);
+ ws=1;
+ hs=1;
+ break;
+ case -3:
+ aspectratio=GR_ASPECT_1x8;
+ l=lod[8-logh];
+ s=32.0f;
+ t=256.0f;
+ is=INT_TRICK(5);it=INT_TRICK(8);
+ ws=1;
+ hs=1;
+ break;
+ case -4:
+ aspectratio=GR_ASPECT_1x8;
+ l=lod[8-logh];
+ s=32.0f;
+ t=256.0f;
+ is=INT_TRICK(5);it=INT_TRICK(8);
+ ws=2;
+ hs=1;
+ break;
+ case -5:
+ aspectratio=GR_ASPECT_1x8;
+ l=lod[8-logh];
+ s=32.0f;
+ t=256.0f;
+ is=INT_TRICK(5);it=INT_TRICK(8);
+ ws=4;
+ hs=1;
+ break;
+ case -6:
+ aspectratio=GR_ASPECT_1x8;
+ l=lod[8-logh];
+ s=32.0f;
+ t=256.0f;
+ is=INT_TRICK(5);it=INT_TRICK(8);
+ ws=8;
+ hs=1;
+ break;
+ case -7:
+ aspectratio=GR_ASPECT_1x8;
+ l=lod[8-logh];
+ s=32.0f;
+ t=256.0f;
+ is=INT_TRICK(5);it=INT_TRICK(8);
+ ws=16;
+ hs=1;
+ break;
+ case -8:
+ aspectratio=GR_ASPECT_1x8;
+ l=lod[8-logh];
+ s=32.0f;
+ t=256.0f;
+ is=INT_TRICK(5);it=INT_TRICK(8);
+ ws=32;
+ hs=1;
+ break;
+ default:
+ return 0;
+ break;
+ }
+
+ if(lodlevel)
+ (*lodlevel)=l;
+
+ if(ar)
+ (*ar)=aspectratio;
+
+ if(sscale)
+ (*sscale)=s;
+
+ if(tscale)
+ (*tscale)=t;
+
+ if(wscale)
+ (*wscale)=ws;
+
+ if(hscale)
+ (*hscale)=hs;
+
+ if (i_sscale)
+ *i_sscale = is;
+
+ if (i_tscale)
+ *i_tscale = it;
+
+
+ return 1;
+}
+
+void fxTexGetFormat(GLenum glformat, GrTextureFormat_t *tfmt, GLint *ifmt)
+{
+ switch(glformat) {
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ if(tfmt)
+ (*tfmt)=GR_TEXFMT_INTENSITY_8;
+ if(ifmt)
+ (*ifmt)=GL_LUMINANCE;
+ break;
+ 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:
+ if(tfmt)
+ (*tfmt)=GR_TEXFMT_ALPHA_INTENSITY_88;
+ if(ifmt)
+ (*ifmt)=GL_LUMINANCE_ALPHA;
+ break;
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ if(tfmt)
+ (*tfmt)=GR_TEXFMT_ALPHA_8;
+ if(ifmt)
+ (*ifmt)=GL_INTENSITY;
+ break;
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ if(tfmt)
+ (*tfmt)=GR_TEXFMT_ALPHA_8;
+ if(ifmt)
+ (*ifmt)=GL_ALPHA;
+ break;
+ case 3:
+ case GL_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(tfmt)
+ (*tfmt)=GR_TEXFMT_RGB_565;
+ if(ifmt)
+ (*ifmt)=GL_RGB;
+ break;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA2:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ if(tfmt)
+ (*tfmt)=GR_TEXFMT_ARGB_4444;
+ if(ifmt)
+ (*ifmt)=GL_RGBA;
+ break;
+ 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:
+ if(tfmt)
+ (*tfmt)=GR_TEXFMT_P_8;
+ if(ifmt)
+ (*ifmt)=GL_RGBA;
+ break;
+ default:
+ fprintf(stderr,"fx Driver: unsupported internalFormat in fxTexGetFormat()\n");
+ fxCloseHardware();
+ exit(-1);
+ break;
+ }
+}
+
+static int fxIsTexSupported(GLenum target, GLint internalFormat,
+ const struct gl_texture_image *image)
+{
+ if(target!=GL_TEXTURE_2D)
+ return GL_FALSE;
+
+ switch(internalFormat) {
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ 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_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ case 3:
+ case GL_RGB:
+ case GL_R3_G3_B2:
+ case GL_RGB4:
+ case GL_RGB5:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA2:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ 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:
+ break;
+ default:
+ return GL_FALSE;
+ }
+
+ if(image->Width>256)
+ return GL_FALSE;
+
+ if(image->Height>256)
+ return GL_FALSE;
+
+ if(!fxTexGetInfo(image->Width,image->Height,NULL,NULL,NULL,NULL,NULL,NULL,
+ NULL,NULL))
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+static void fxTexBuildImageMap(const struct gl_texture_image *image,
+ GLint internalFormat, unsigned short **dest,
+ GLboolean *istranslate)
+{
+ unsigned short *src;
+ unsigned char *data;
+ int x,y,w,h,wscale,hscale,idx;
+
+ fxTexGetInfo(image->Width,image->Height,NULL,NULL,NULL,NULL,NULL,NULL,
+ &wscale,&hscale);
+ w=image->Width*wscale;
+ h=image->Height*hscale;
+
+ data=image->Data;
+ switch(internalFormat) {
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ 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:
+ /* Optimized for GLQuake */
+
+ if(wscale==hscale==1) {
+ (*istranslate)=GL_FALSE;
+
+ (*dest)=(unsigned short *)data;
+ } else {
+ unsigned char *srcb;
+
+ (*istranslate)=GL_TRUE;
+
+ if(!(*dest)) {
+ if(!((*dest)=src=(unsigned short *)malloc(sizeof(unsigned char)*w*h))) {
+ fprintf(stderr,"fx Driver: out of memory !\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+ } else
+ src=(*dest);
+
+ srcb=(unsigned char *)src;
+
+ for(y=0;y<h;y++)
+ for(x=0;x<w;x++) {
+ idx=(x/wscale+(y/hscale)*(w/wscale));
+ srcb[x+y*w]=data[idx];
+ }
+ }
+ break;
+ 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:
+ (*istranslate)=GL_TRUE;
+
+ if(!(*dest)) {
+ if(!((*dest)=src=(unsigned short *)malloc(sizeof(unsigned short)*w*h))) {
+ fprintf(stderr,"fx Driver: out of memory !\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+ } else
+ src=(*dest);
+
+ if(wscale==hscale==1) {
+ int i=0;
+ int lenght=h*w;
+ unsigned short a,l;
+
+ while(i++<lenght) {
+ l=*data++;
+ a=*data++;
+
+ *src++=(a << 8) | l;
+ }
+ } else {
+ unsigned short a,l;
+
+ for(y=0;y<h;y++)
+ for(x=0;x<w;x++) {
+ idx=(x/wscale+(y/hscale)*(w/wscale))*2;
+ l=data[idx];
+ a=data[idx+1];
+
+ src[x+y*w]=(a << 8) | l;
+ }
+ }
+ break;
+ case 3:
+ case GL_RGB:
+ case GL_R3_G3_B2:
+ case GL_RGB4:
+ case GL_RGB5:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ (*istranslate)=GL_TRUE;
+
+ if(!(*dest)) {
+ if(!((*dest)=src=(unsigned short *)malloc(sizeof(unsigned short)*w*h))) {
+ fprintf(stderr,"fx Driver: out of memory !\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+ } else
+ src=(*dest);
+
+ if(wscale==hscale==1) {
+ int i=0;
+ int lenght=h*w;
+ unsigned short r,g,b;
+
+ while(i++<lenght) {
+ r=*data++;
+ g=*data++;
+ b=*data++;
+
+ *src++=((0xf8 & r) << (11-3)) |
+ ((0xfc & g) << (5-3+1)) |
+ ((0xf8 & b) >> 3);
+ }
+ } else {
+ unsigned short r,g,b;
+
+ for(y=0;y<h;y++)
+ for(x=0;x<w;x++) {
+ idx=(x/wscale+(y/hscale)*(w/wscale))*3;
+ r=data[idx];
+ g=data[idx+1];
+ b=data[idx+2];
+
+ src[x+y*w]=((0xf8 & r) << (11-3)) |
+ ((0xfc & g) << (5-3+1)) |
+ ((0xf8 & b) >> 3);
+ }
+ }
+ break;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA2:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ (*istranslate)=GL_TRUE;
+
+ if(!(*dest)) {
+ if(!((*dest)=src=(unsigned short *)malloc(sizeof(unsigned short)*w*h))) {
+ fprintf(stderr,"fx Driver: out of memory !\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+ } else
+ src=(*dest);
+
+ if(wscale==hscale==1) {
+ int i=0;
+ int lenght=h*w;
+ unsigned short r,g,b,a;
+
+ while(i++<lenght) {
+ r=*data++;
+ g=*data++;
+ b=*data++;
+ a=*data++;
+
+ *src++=((0xf0 & a) << 8) |
+ ((0xf0 & r) << 4) |
+ (0xf0 & g) |
+ ((0xf0 & b) >> 4);
+ }
+ } else {
+ unsigned short r,g,b,a;
+
+ for(y=0;y<h;y++)
+ for(x=0;x<w;x++) {
+ idx=(x/wscale+(y/hscale)*(w/wscale))*4;
+ r=data[idx];
+ g=data[idx+1];
+ b=data[idx+2];
+ a=data[idx+3];
+
+ src[x+y*w]=((0xf0 & a) << 8) |
+ ((0xf0 & r) << 4) |
+ (0xf0 & g) |
+ ((0xf0 & b) >> 4);
+ }
+ }
+ break;
+ default:
+ fprintf(stderr,"fx Driver: wrong internalFormat in texbuildimagemap()\n");
+ fxCloseHardware();
+ exit(-1);
+ break;
+ }
+}
+
+void fxDDTexImg(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *tObj, GLint level, GLint internalFormat,
+ const struct gl_texture_image *image)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxTexInfo *ti;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: (%d) fxDDTexImg(...,%d,%x,%d,%d...)\n",tObj->Name,
+ target,internalFormat,image->Width,image->Height);
+ }
+
+ if(target!=GL_TEXTURE_2D)
+ return;
+
+ if(!tObj->DriverData)
+ tObj->DriverData=fxAllocTexObjData(fxMesa);
+
+ ti=(tfxTexInfo *)tObj->DriverData;
+
+ if(fxIsTexSupported(target,internalFormat,image)) {
+ GrTextureFormat_t gldformat;
+ tfxMipMapLevel *mml=&ti->tmi.mipmapLevel[level];
+
+ fxTexGetFormat(internalFormat,&gldformat,NULL);
+
+ if(mml->used) {
+ if((mml->glideFormat==gldformat) &&
+ (mml->width==image->Width) &&
+ (mml->height==image->Height)) {
+ fxTexBuildImageMap(image,internalFormat,&(mml->data),
+ &(mml->translated));
+
+ if(ti->validated && ti->tmi.isInTM)
+ fxTMReloadMipMapLevel(fxMesa,tObj,level);
+ else
+ fxTexInvalidate(ctx,tObj);
+
+ return;
+ } else {
+ if(mml->translated)
+ free(mml->data);
+ mml->data=NULL;
+ }
+ }
+
+ mml->glideFormat=gldformat;
+ mml->width=image->Width;
+ mml->height=image->Height;
+ mml->used=GL_TRUE;
+
+ fxTexBuildImageMap(image,internalFormat,&(mml->data),
+ &(mml->translated));
+
+ fxTexInvalidate(ctx,tObj);
+ }
+#ifndef FX_SILENT
+ else
+ fprintf(stderr,"fx Driver: unsupported texture in fxDDTexImg()\n");
+#endif
+}
+
+static void fxTexBuildSubImageMap(const struct gl_texture_image *image,
+ GLint internalFormat,
+ GLint xoffset, GLint yoffset, GLint width, GLint height,
+ unsigned short *destimg)
+{
+ fxTexGetInfo(image->Width,image->Height,NULL,NULL,NULL,NULL,NULL,NULL,
+ NULL,NULL);
+
+ switch(internalFormat) {
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ 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:
+ {
+
+ int y;
+ unsigned char *bsrc,*bdst;
+
+ bsrc=(unsigned char *)(image->Data+(yoffset*image->Width+xoffset));
+ bdst=((unsigned char *)destimg)+(yoffset*image->Width+xoffset);
+
+ for(y=0;y<height;y++) {
+ MEMCPY(bdst,bsrc,width);
+ bsrc += image->Width;
+ bdst += image->Width;
+ }
+ }
+ break;
+ 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:
+ {
+ int x,y;
+ unsigned char *src;
+ unsigned short *dst,a,l;
+ int simgw,dimgw;
+
+ src=(unsigned char *)(image->Data+(yoffset*image->Width+xoffset)*2);
+ dst=destimg+(yoffset*image->Width+xoffset);
+
+ simgw=(image->Width-width)*2;
+ dimgw=image->Width-width;
+ for(y=0;y<height;y++) {
+ for(x=0;x<width;x++) {
+ l=*src++;
+ a=*src++;
+ *dst++=(a << 8) | l;
+ }
+
+ src += simgw;
+ dst += dimgw;
+ }
+ }
+ break;
+ case 3:
+ case GL_RGB:
+ case GL_R3_G3_B2:
+ case GL_RGB4:
+ case GL_RGB5:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ {
+ int x,y;
+ unsigned char *src;
+ unsigned short *dst,r,g,b;
+ int simgw,dimgw;
+
+ src=(unsigned char *)(image->Data+(yoffset*image->Width+xoffset)*3);
+ dst=destimg+(yoffset*image->Width+xoffset);
+
+ simgw=(image->Width-width)*3;
+ dimgw=image->Width-width;
+ for(y=0;y<height;y++) {
+ for(x=0;x<width;x++) {
+ r=*src++;
+ g=*src++;
+ b=*src++;
+ *dst++=((0xf8 & r) << (11-3)) |
+ ((0xfc & g) << (5-3+1)) |
+ ((0xf8 & b) >> 3);
+ }
+
+ src += simgw;
+ dst += dimgw;
+ }
+ }
+ break;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA2:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ {
+ int x,y;
+ unsigned char *src;
+ unsigned short *dst,r,g,b,a;
+ int simgw,dimgw;
+
+ src=(unsigned char *)(image->Data+(yoffset*image->Width+xoffset)*4);
+ dst=destimg+(yoffset*image->Width+xoffset);
+
+ simgw=(image->Width-width)*4;
+ dimgw=image->Width-width;
+ for(y=0;y<height;y++) {
+ for(x=0;x<width;x++) {
+ r=*src++;
+ g=*src++;
+ b=*src++;
+ a=*src++;
+ *dst++=((0xf0 & a) << 8) |
+ ((0xf0 & r) << 4) |
+ (0xf0 & g) |
+ ((0xf0 & b) >> 4);
+ }
+
+ src += simgw;
+ dst += dimgw;
+ }
+ }
+ break;
+ default:
+ fprintf(stderr,"fx Driver: wrong internalFormat in fxTexBuildSubImageMap()\n");
+ fxCloseHardware();
+ exit(-1);
+ break;
+ }
+}
+
+
+void fxDDTexSubImg(GLcontext *ctx, GLenum target,
+ struct gl_texture_object *tObj, GLint level,
+ GLint xoffset, GLint yoffset, GLint width, GLint height,
+ GLint internalFormat, const struct gl_texture_image *image)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxTexInfo *ti;
+ GrTextureFormat_t gldformat;
+ int wscale,hscale;
+ tfxMipMapLevel *mml;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: (%d) fxDDTexSubImg(...,%d,%x,%d,%d...)\n",tObj->Name,
+ target,internalFormat,image->Width,image->Height);
+ }
+
+ if(target!=GL_TEXTURE_2D)
+ return;
+
+ if(!tObj->DriverData)
+ return;
+
+ ti=(tfxTexInfo *)tObj->DriverData;
+ mml=&ti->tmi.mipmapLevel[level];
+
+ fxTexGetFormat(internalFormat,&gldformat,NULL);
+
+ if(mml->glideFormat!=gldformat) {
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: ti->info.format!=format in fxDDTexSubImg()\n");
+ }
+ fxDDTexImg(ctx,target,tObj,level,internalFormat,image);
+
+ return;
+ }
+
+ fxTexGetInfo(image->Width,image->Height,NULL,NULL,NULL,NULL,NULL,NULL,&wscale,&hscale);
+
+ if((wscale!=1) || (hscale!=1)) {
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: (wscale!=1) || (hscale!=1) in fxDDTexSubImg()\n");
+ }
+ fxDDTexImg(ctx,target,tObj,level,internalFormat,image);
+
+ return;
+ }
+
+ if(mml->translated)
+ fxTexBuildSubImageMap(image,internalFormat,xoffset,yoffset,
+ width,height,mml->data);
+
+ if(ti->validated && ti->tmi.isInTM)
+ fxTMReloadSubMipMapLevel(fxMesa,tObj,level,yoffset,height);
+ else
+ fxTexInvalidate(ctx,tObj);
+}
+
+
+#else
+
+
+/*
+ * Need this to provide at least one external definition.
+ */
+
+int gl_fx_dummy_function_ddtex(void)
+{
+ return 0;
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/fxdrv.h b/src/mesa/drivers/glide/fxdrv.h
new file mode 100644
index 0000000000..bb8f5b8761
--- /dev/null
+++ b/src/mesa/drivers/glide/fxdrv.h
@@ -0,0 +1,576 @@
+/* -*- mode: C; tab-width:8; -*-
+
+ fxdrv.h - 3Dfx VooDoo driver types
+*/
+
+/*
+ * 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.
+ *
+ * See the file fxapi.c for more informations about authors
+ *
+ */
+
+#ifndef FXDRV_H
+#define FXDRV_H
+
+/* If you comment out this define, a variable takes its place, letting
+ * you turn debugging on/off from the debugger.
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <assert.h>
+
+#if defined(__linux__)
+#include <signal.h>
+#endif
+
+#include "context.h"
+#include "macros.h"
+#include "matrix.h"
+#include "texture.h"
+#include "types.h"
+#include "vb.h"
+#include "xform.h"
+#include "clip.h"
+#include "vbrender.h"
+
+#include "GL/fxmesa.h"
+#include "fxglidew.h"
+/* use gl/gl.h GLAPI/GLAPIENTRY/GLCALLBACK in place of WINGDIAPI/APIENTRY/CALLBACK, */
+/* these are defined in mesa gl/gl.h - tjump@spgs.com */
+
+
+
+#if defined(MESA_DEBUG) && 0
+extern void fx_sanity_triangle( GrVertex *, GrVertex *, GrVertex * );
+#define grDrawTriangle fx_sanity_triangle
+#endif
+
+
+/* Define some shorter names for these things.
+ */
+#define XCOORD GR_VERTEX_X_OFFSET
+#define YCOORD GR_VERTEX_Y_OFFSET
+#define ZCOORD GR_VERTEX_OOZ_OFFSET
+#define OOWCOORD GR_VERTEX_OOW_OFFSET
+
+#define RCOORD GR_VERTEX_R_OFFSET
+#define GCOORD GR_VERTEX_G_OFFSET
+#define BCOORD GR_VERTEX_B_OFFSET
+#define ACOORD GR_VERTEX_A_OFFSET
+
+#define S0COORD GR_VERTEX_SOW_TMU0_OFFSET
+#define T0COORD GR_VERTEX_TOW_TMU0_OFFSET
+#define S1COORD GR_VERTEX_SOW_TMU1_OFFSET
+#define T1COORD GR_VERTEX_TOW_TMU1_OFFSET
+
+#define CLIP_XCOORD 0 /* normal place */
+#define CLIP_YCOROD 1 /* normal place */
+#define CLIP_ZCOORD 2 /* GR_VERTEX_Z_OFFSET */
+#define CLIP_WCOORD 3 /* GR_VERTEX_R_OFFSET */
+#define CLIP_GCOORD 4 /* normal place */
+#define CLIP_BCOORD 5 /* normal place */
+#define CLIP_RCOORD 6 /* GR_VERTEX_OOZ_OFFSET */
+#define CLIP_ACOORD 7 /* normal place */
+
+
+
+
+/* Should have size == 16 * sizeof(float).
+ */
+typedef struct {
+ GLfloat f[15]; /* Same layout as GrVertex */
+ GLubyte mask; /* Unsued */
+ GLubyte usermask; /* Unused */
+} fxVertex;
+
+
+
+
+#if defined(FXMESA_USE_ARGB)
+#define FXCOLOR4( c ) ( \
+ ( ((unsigned int)(c[3]))<<24 ) | \
+ ( ((unsigned int)(c[0]))<<16 ) | \
+ ( ((unsigned int)(c[1]))<<8 ) | \
+ ( (unsigned int)(c[2])) )
+
+#else
+#ifdef __i386__
+#define FXCOLOR4( c ) (* (int *)c)
+#else
+#define FXCOLOR4( c ) ( \
+ ( ((unsigned int)(c[3]))<<24 ) | \
+ ( ((unsigned int)(c[2]))<<16 ) | \
+ ( ((unsigned int)(c[1]))<<8 ) | \
+ ( (unsigned int)(c[0])) )
+#endif
+#endif
+
+#define FX_VB_COLOR(fxm, color) \
+do { \
+ if (sizeof(GLint) == 4*sizeof(GLubyte)) { \
+ if (fxm->constColor != *(GLuint*)color) { \
+ fxm->constColor = *(GLuint*)color; \
+ grConstantColorValue(FXCOLOR4(color)); \
+ } \
+ } else { \
+ grConstantColorValue(FXCOLOR4(color)); \
+ } \
+} while (0)
+
+#define GOURAUD(x) { \
+ GLubyte *col = VB->ColorPtr->data[(x)]; \
+ gWin[(x)].v.r=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[0]); \
+ gWin[(x)].v.g=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[1]); \
+ gWin[(x)].v.b=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[2]); \
+ gWin[(x)].v.a=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[3]); \
+}
+
+#define GOURAUD2(v, c) { \
+ GLubyte *col = c; \
+ v->r=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[0]); \
+ v->g=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[1]); \
+ v->b=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[2]); \
+ v->a=UBYTE_COLOR_TO_FLOAT_255_COLOR(col[3]); \
+}
+
+
+/* Mergable items first
+ */
+#define SETUP_RGBA 0x1
+#define SETUP_TMU0 0x2
+#define SETUP_TMU1 0x4
+#define SETUP_XY 0x8
+#define SETUP_Z 0x10
+#define SETUP_W 0x20
+
+#define MAX_MERGABLE 0x8
+
+
+#define FX_NUM_TMU 2
+
+#define FX_TMU0 GR_TMU0
+#define FX_TMU1 GR_TMU1
+#define FX_TMU_SPLIT 98
+#define FX_TMU_BOTH 99
+#define FX_TMU_NONE 100
+
+/* Used for fxMesa->lastUnitsMode */
+
+#define FX_UM_NONE 0x00000000
+
+#define FX_UM_E0_REPLACE 0x00000001
+#define FX_UM_E0_MODULATE 0x00000002
+#define FX_UM_E0_DECAL 0x00000004
+#define FX_UM_E0_BLEND 0x00000008
+
+#define FX_UM_E1_REPLACE 0x00000010
+#define FX_UM_E1_MODULATE 0x00000020
+#define FX_UM_E1_DECAL 0x00000040
+#define FX_UM_E1_BLEND 0x00000080
+
+#define FX_UM_E_ENVMODE 0x000000ff
+
+#define FX_UM_E0_ALPHA 0x00000100
+#define FX_UM_E0_LUMINANCE 0x00000200
+#define FX_UM_E0_LUMINANCE_ALPHA 0x00000400
+#define FX_UM_E0_INTENSITY 0x00000800
+#define FX_UM_E0_RGB 0x00001000
+#define FX_UM_E0_RGBA 0x00002000
+
+#define FX_UM_E1_ALPHA 0x00004000
+#define FX_UM_E1_LUMINANCE 0x00008000
+#define FX_UM_E1_LUMINANCE_ALPHA 0x00010000
+#define FX_UM_E1_INTENSITY 0x00020000
+#define FX_UM_E1_RGB 0x00040000
+#define FX_UM_E1_RGBA 0x00080000
+
+#define FX_UM_E_IFMT 0x000fff00
+
+#define FX_UM_COLOR_ITERATED 0x00100000
+#define FX_UM_COLOR_CONSTANT 0x00200000
+#define FX_UM_ALPHA_ITERATED 0x00400000
+#define FX_UM_ALPHA_CONSTANT 0x00800000
+
+typedef void (*tfxRenderVBFunc)(GLcontext *);
+
+typedef struct tfxTMFreeListNode {
+ struct tfxTMFreeListNode *next;
+ FxU32 startAddress, endAddress;
+} tfxTMFreeNode;
+
+typedef struct tfxTMAllocListNode {
+ struct tfxTMAllocListNode *next;
+ FxU32 startAddress, endAddress;
+ struct gl_texture_object *tObj;
+} tfxTMAllocNode;
+
+typedef struct {
+ GLsizei width, height;
+ GLint glideFormat;
+
+ unsigned short *data;
+ GLboolean translated, used;
+} tfxMipMapLevel;
+
+typedef struct {
+ GLuint lastTimeUsed;
+
+ FxU32 whichTMU;
+
+ tfxTMAllocNode *tm[FX_NUM_TMU];
+
+ tfxMipMapLevel mipmapLevel[MAX_TEXTURE_LEVELS];
+ GLboolean isInTM;
+} tfxTMInfo;
+
+typedef struct {
+ tfxTMInfo tmi;
+
+ GLint minLevel, maxLevel;
+ GLint baseLevelInternalFormat;
+
+ GrTexInfo info;
+
+ GrTextureFilterMode_t minFilt;
+ GrTextureFilterMode_t maxFilt;
+ FxBool LODblend;
+
+ GrTextureClampMode_t sClamp;
+ GrTextureClampMode_t tClamp;
+
+ GrMipMapMode_t mmMode;
+
+ GLfloat sScale, tScale;
+ GLint int_sScale, int_tScale; /* x86 floating point trick for
+ * multiplication by powers of 2.
+ * Used in fxfasttmp.h
+ */
+
+ GuTexPalette palette;
+
+ GLboolean fixedPalette;
+ GLboolean validated;
+} tfxTexInfo;
+
+typedef struct {
+ GLuint swapBuffer;
+ GLuint reqTexUpload;
+ GLuint texUpload;
+ GLuint memTexUpload;
+} tfxStats;
+
+
+typedef void (*tfxTriViewClipFunc)( struct vertex_buffer *VB,
+ GLuint v[],
+ GLubyte mask );
+
+typedef void (*tfxTriClipFunc)( struct vertex_buffer *VB,
+ GLuint v[],
+ GLuint mask );
+
+
+typedef void (*tfxLineClipFunc)( struct vertex_buffer *VB,
+ GLuint v1, GLuint v2,
+ GLubyte mask );
+
+
+extern tfxTriViewClipFunc fxTriViewClipTab[0x8];
+extern tfxTriClipFunc fxTriClipStrideTab[0x8];
+extern tfxLineClipFunc fxLineClipTab[0x8];
+
+typedef struct {
+ /* Alpha test */
+
+ GLboolean alphaTestEnabled;
+ GrCmpFnc_t alphaTestFunc;
+ GrAlpha_t alphaTestRefValue;
+
+ /* Blend function */
+
+ GLboolean blendEnabled;
+ GrAlphaBlendFnc_t blendSrcFuncRGB;
+ GrAlphaBlendFnc_t blendDstFuncRGB;
+ GrAlphaBlendFnc_t blendSrcFuncAlpha;
+ GrAlphaBlendFnc_t blendDstFuncAlpha;
+
+ /* Depth test */
+
+ GLboolean depthTestEnabled;
+ GLboolean depthMask;
+ GrCmpFnc_t depthTestFunc;
+} tfxUnitsState;
+
+
+/* Flags for render_index.
+ */
+#define FX_OFFSET 0x1
+#define FX_TWOSIDE 0x2
+#define FX_FRONT_BACK 0x4
+#define FX_FLAT 0x8
+#define FX_ANTIALIAS 0x10
+#define FX_FALLBACK 0x20
+
+
+/* Flags for fxMesa->new_state
+ */
+#define FX_NEW_TEXTURING 0x1
+#define FX_NEW_BLEND 0x2
+#define FX_NEW_ALPHA 0x4
+#define FX_NEW_DEPTH 0x8
+#define FX_NEW_FOG 0x10
+#define FX_NEW_SCISSOR 0x20
+#define FX_NEW_COLOR_MASK 0x40
+#define FX_NEW_CULL 0x80
+
+/* FX struct stored in VB->driver_data.
+ */
+struct tfxMesaVertexBuffer {
+ GLvector1ui clipped_elements;
+
+ fxVertex *verts;
+ fxVertex *last_vert;
+ void *vert_store;
+#if defined(FX_GLIDE3)
+ GrVertex **triangle_b; /* Triangle buffer */
+ GrVertex **strips_b; /* Strips buffer */
+#endif
+
+ GLuint size;
+};
+
+#define FX_DRIVER_DATA(vb) ((struct tfxMesaVertexBuffer *)((vb)->driver_data))
+#define FX_CONTEXT(ctx) ((struct tfxMesaContext *)((ctx)->DriverCtx))
+#define FX_TEXTURE_DATA(t) ((tfxTexInfo *) ((t)->Current->DriverData))
+
+struct tfxMesaContext {
+ GuTexPalette glbPalette;
+
+ GLcontext *glCtx; /* the core Mesa context */
+ GLvisual *glVis; /* describes the color buffer */
+ GLframebuffer *glBuffer; /* the ancillary buffers */
+
+ GLint board; /* the board used for this context */
+ GLint width, height; /* size of color buffer */
+
+ GrBuffer_t currentFB;
+
+ GrColor_t color;
+ GrColor_t clearC;
+ GrAlpha_t clearA;
+ GLuint constColor;
+
+ tfxUnitsState unitsState;
+ tfxUnitsState restoreUnitsState; /* saved during multipass */
+
+
+ GLuint tmu_source[FX_NUM_TMU];
+ GLuint tex_dest[MAX_TEXTURE_UNITS];
+ GLuint setupindex;
+ GLuint partial_setup_index;
+ GLuint setupdone;
+ GLuint mergeindex;
+ GLuint mergeinputs;
+ GLuint render_index;
+ GLuint last_tri_caps;
+ GLuint stw_hint_state; /* for grHints */
+ GLuint is_in_hardware;
+ GLuint new_state;
+ GLuint using_fast_path, passes, multipass;
+
+ tfxLineClipFunc clip_line;
+ tfxTriClipFunc clip_tri_stride;
+ tfxTriViewClipFunc view_clip_tri;
+
+
+ /* Texture Memory Manager Data */
+
+ GLuint texBindNumber;
+ GLint tmuSrc;
+ GLuint lastUnitsMode;
+ GLuint freeTexMem[FX_NUM_TMU];
+ tfxTMFreeNode *tmFree[FX_NUM_TMU];
+ tfxTMAllocNode *tmAlloc[FX_NUM_TMU];
+
+ GLenum fogTableMode;
+ GLfloat fogDensity;
+ GrFog_t *fogTable;
+
+ /* Acc. functions */
+
+ points_func PointsFunc;
+ line_func LineFunc;
+ triangle_func TriangleFunc;
+ quad_func QuadFunc;
+
+ render_func **RenderVBTables;
+
+ tfxStats stats;
+
+ void *state;
+
+ /* Options */
+
+ GLboolean verbose;
+ GLboolean haveTwoTMUs; /* True if we really have 2 tmu's */
+ GLboolean emulateTwoTMUs; /* True if we present 2 tmu's to mesa. */
+ GLboolean haveAlphaBuffer;
+ GLboolean haveDoubleBuffer;
+ GLboolean haveGlobalPaletteTexture;
+ GLint swapInterval;
+ GLint maxPendingSwapBuffers;
+
+ FX_GrContext_t glideContext;
+};
+
+typedef void (*tfxSetupFunc)(struct vertex_buffer *, GLuint, GLuint);
+
+extern GrHwConfiguration glbHWConfig;
+extern int glbCurrentBoard;
+
+extern void fxSetupFXUnits(GLcontext *);
+extern void fxSetupDDPointers(GLcontext *);
+extern void fxDDSetNearFar(GLcontext *, GLfloat, GLfloat);
+
+extern void fxDDSetupInit();
+extern void fxDDCvaInit();
+extern void fxDDTrifuncInit();
+extern void fxDDFastPathInit();
+
+extern void fxDDChooseRenderState( GLcontext *ctx );
+
+extern void fxRenderClippedLine( struct vertex_buffer *VB,
+ GLuint v1, GLuint v2 );
+
+extern void fxRenderClippedTriangle( struct vertex_buffer *VB,
+ GLuint n, GLuint vlist[] );
+
+
+extern tfxSetupFunc fxDDChooseSetupFunction(GLcontext *);
+
+extern points_func fxDDChoosePointsFunction(GLcontext *);
+extern line_func fxDDChooseLineFunction(GLcontext *);
+extern triangle_func fxDDChooseTriangleFunction(GLcontext *);
+extern quad_func fxDDChooseQuadFunction(GLcontext *);
+extern render_func **fxDDChooseRenderVBTables(GLcontext *);
+
+extern void fxDDRenderInit(GLcontext *);
+extern void fxDDClipInit();
+
+extern void fxUpdateDDSpanPointers(GLcontext *);
+extern void fxSetupDDSpanPointers(GLcontext *);
+
+extern void fxDDBufferSize(GLcontext *, GLuint *, GLuint *);
+
+extern void fxDDTexEnv(GLcontext *, GLenum, const GLfloat *);
+extern void fxDDTexImg(GLcontext *, GLenum, struct gl_texture_object *,
+ GLint, GLint, const struct gl_texture_image *);
+extern void fxDDTexParam(GLcontext *, GLenum, struct gl_texture_object *,
+ GLenum, const GLfloat *);
+extern void fxDDTexBind(GLcontext *, GLenum, struct gl_texture_object *);
+extern void fxDDTexDel(GLcontext *, struct gl_texture_object *);
+extern void fxDDTexPalette(GLcontext *, struct gl_texture_object *);
+extern void fxDDTexuseGlbPalette(GLcontext *, GLboolean);
+extern void fxDDTexSubImg(GLcontext *, GLenum, struct gl_texture_object *, GLint,
+ GLint, GLint, GLint, GLint, GLint, const struct gl_texture_image *);
+extern void fxDDTexUseGlbPalette(GLcontext *, GLboolean);
+
+extern void fxDDEnable(GLcontext *, GLenum, GLboolean);
+extern void fxDDAlphaFunc(GLcontext *, GLenum, GLclampf);
+extern void fxDDBlendFunc(GLcontext *, GLenum, GLenum);
+extern void fxDDDepthMask(GLcontext *, GLboolean);
+extern void fxDDDepthFunc(GLcontext *, GLenum);
+
+extern void fxDDRegisterVB( struct vertex_buffer *VB );
+extern void fxDDUnregisterVB( struct vertex_buffer *VB );
+extern void fxDDResizeVB( struct tfxMesaVertexBuffer *fvb, GLuint size );
+
+extern void fxDDCheckMergeAndRender( GLcontext *ctx,
+ struct gl_pipeline_stage *d );
+
+extern void fxDDMergeAndRender( struct vertex_buffer *VB );
+
+extern void fxDDCheckPartialRasterSetup( GLcontext *ctx,
+ struct gl_pipeline_stage *d );
+
+extern void fxDDPartialRasterSetup( struct vertex_buffer *VB );
+
+extern void fxDDDoRasterSetup( struct vertex_buffer *VB );
+
+extern GLuint fxDDRegisterPipelineStages( struct gl_pipeline_stage *out,
+ const struct gl_pipeline_stage *in,
+ GLuint nr );
+
+extern GLboolean fxDDBuildPrecalcPipeline( GLcontext *ctx );
+
+extern void fxDDOptimizePrecalcPipeline( GLcontext *ctx,
+ struct gl_pipeline *pipe );
+
+extern void fxDDRenderElementsDirect( struct vertex_buffer *VB );
+extern void fxDDRenderVBIndirectDirect( struct vertex_buffer *VB );
+
+extern void fxDDInitExtensions( GLcontext *ctx );
+
+extern void fxTMInit(fxMesaContext);
+extern void fxTMClose(fxMesaContext);
+extern void fxTMMoveInTM(fxMesaContext, struct gl_texture_object *, GLint);
+extern void fxTMMoveOutTM(fxMesaContext, struct gl_texture_object *);
+extern void fxTMFreeTexture(fxMesaContext, struct gl_texture_object *);
+extern void fxTMReloadMipMapLevel(fxMesaContext, struct gl_texture_object *, GLint);
+extern void fxTMReloadSubMipMapLevel(fxMesaContext, struct gl_texture_object *,
+ GLint, GLint, GLint);
+
+extern void fxTexGetFormat(GLenum, GrTextureFormat_t *, GLint *);
+extern int fxTexGetInfo(int, int, GrLOD_t *, GrAspectRatio_t *,
+ float *, float *, int *, int *, int *, int *);
+
+extern void fxDDScissor( GLcontext *ctx,
+ GLint x, GLint y, GLsizei w, GLsizei h );
+extern void fxDDFogfv( GLcontext *ctx, GLenum pname, const GLfloat *params );
+extern GLboolean fxDDColorMask(GLcontext *ctx,
+ GLboolean r, GLboolean g,
+ GLboolean b, GLboolean a );
+
+extern GLuint fxDDDepthTestSpanGeneric(GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLdepth z[],
+ GLubyte mask[]);
+
+extern void fxDDDepthTestPixelsGeneric(GLcontext* ctx,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLdepth z[], GLubyte mask[]);
+
+extern void fxDDReadDepthSpanFloat(GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLfloat depth[]);
+
+extern void fxDDReadDepthSpanInt(GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLdepth depth[]);
+
+
+extern void fxDDFastPath( struct vertex_buffer *VB );
+
+extern void fxDDShadeModel(GLcontext *ctx, GLenum mode);
+
+extern void fxDDCullFace(GLcontext *ctx, GLenum mode);
+extern void fxDDFrontFace(GLcontext *ctx, GLenum mode);
+
+
+
+
+#endif
diff --git a/src/mesa/drivers/glide/fxglidew.c b/src/mesa/drivers/glide/fxglidew.c
new file mode 100644
index 0000000000..3ced928f49
--- /dev/null
+++ b/src/mesa/drivers/glide/fxglidew.c
@@ -0,0 +1,247 @@
+/* $Id: fxglidew.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#if defined(FX)
+#include "glide.h"
+#include "fxglidew.h"
+#include "fxdrv.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+
+FxI32 FX_grGetInteger(FxU32 pname)
+{
+#if !defined(FX_GLIDE3)
+ switch (pname)
+ {
+ case FX_FOG_TABLE_ENTRIES:
+ return GR_FOG_TABLE_SIZE;
+ case FX_GLIDE_STATE_SIZE:
+ return sizeof(GrState);
+ case FX_LFB_PIXEL_PIPE:
+ return FXFALSE;
+ case FX_PENDING_BUFFERSWAPS:
+ return grBufferNumPending();
+ default:
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"Wrong parameter in FX_grGetInteger!\n");
+ return -1;
+ }
+ }
+#else
+ FxU32 grname;
+ FxI32 result;
+
+ switch (pname)
+ {
+ case FX_FOG_TABLE_ENTRIES:
+ case FX_GLIDE_STATE_SIZE:
+ case FX_LFB_PIXEL_PIPE:
+ case FX_PENDING_BUFFERSWAPS:
+ grname = pname;
+ break;
+ default:
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"Wrong parameter in FX_grGetInteger!\n");
+ return -1;
+ }
+ }
+
+ grGet(grname,4,&result);
+ return result;
+#endif
+}
+
+
+
+#if defined(FX_GLIDE3)
+
+void FX_grGammaCorrectionValue(float val)
+{
+ (void)val;
+/* ToDo */
+}
+
+void FX_grSstControl(int par)
+{
+ (void)par;
+ /* ToDo */
+}
+int FX_getFogTableSize(void)
+{
+ int result;
+ grGet(GR_FOG_TABLE_ENTRIES,sizeof(int),(void*)&result);
+ return result;
+}
+
+int FX_getGrStateSize(void)
+{
+ int result;
+ grGet(GR_GLIDE_STATE_SIZE,sizeof(int),(void*)&result);
+
+ return result;
+
+}
+int FX_grBufferNumPending()
+{
+ int result;
+ grGet(GR_PENDING_BUFFERSWAPS,sizeof(int),(void*)&result);
+
+ return result;
+}
+
+int FX_grSstScreenWidth()
+{
+ FxI32 result[4];
+
+ grGet(GR_VIEWPORT,sizeof(FxI32)*4,result);
+
+ return result[2];
+}
+
+int FX_grSstScreenHeight()
+{
+ FxI32 result[4];
+
+ grGet(GR_VIEWPORT,sizeof(FxI32)*4,result);
+
+ return result[3];
+}
+
+void FX_grGlideGetVersion(char *buf)
+{
+ strcpy(buf,grGetString(GR_VERSION));
+}
+
+void FX_grSstPerfStats(GrSstPerfStats_t *st)
+{
+ /* ToDo */
+ st->pixelsIn = 0;
+ st->chromaFail = 0;
+ st->zFuncFail = 0;
+ st->aFuncFail = 0;
+ st->pixelsOut = 0;
+}
+
+void FX_grAADrawLine(GrVertex *a,GrVertex *b)
+{
+ /* ToDo */
+ grDrawLine(a,b);
+}
+void FX_grAADrawPoint(GrVertex *a)
+{
+ grDrawPoint(a);
+}
+
+void FX_setupGrVertexLayout(void)
+{
+ grReset(GR_VERTEX_PARAMETER);
+
+ grCoordinateSpace(GR_WINDOW_COORDS);
+ grVertexLayout(GR_PARAM_XY, GR_VERTEX_X_OFFSET << 2, GR_PARAM_ENABLE);
+ grVertexLayout(GR_PARAM_RGB, GR_VERTEX_R_OFFSET << 2, GR_PARAM_ENABLE);
+ /* grVertexLayout(GR_PARAM_Z, GR_VERTEX_Z_OFFSET << 2, GR_PARAM_ENABLE); */
+ grVertexLayout(GR_PARAM_A, GR_VERTEX_A_OFFSET << 2, GR_PARAM_ENABLE);
+ grVertexLayout(GR_PARAM_Q, GR_VERTEX_OOW_OFFSET << 2, GR_PARAM_ENABLE);
+ grVertexLayout(GR_PARAM_Z, GR_VERTEX_OOZ_OFFSET << 2, GR_PARAM_ENABLE);
+ grVertexLayout(GR_PARAM_ST0, GR_VERTEX_SOW_TMU0_OFFSET << 2, GR_PARAM_ENABLE);
+ grVertexLayout(GR_PARAM_Q0, GR_VERTEX_OOW_TMU0_OFFSET << 2, GR_PARAM_DISABLE);
+ grVertexLayout(GR_PARAM_ST1, GR_VERTEX_SOW_TMU1_OFFSET << 2, GR_PARAM_DISABLE);
+ grVertexLayout(GR_PARAM_Q1, GR_VERTEX_OOW_TMU1_OFFSET << 2, GR_PARAM_DISABLE);
+}
+
+void FX_grHints(GrHint_t hintType, FxU32 hintMask)
+{
+ switch(hintType) {
+ case GR_HINT_STWHINT:
+ {
+ if (hintMask & GR_STWHINT_W_DIFF_TMU0)
+ grVertexLayout(GR_PARAM_Q0, GR_VERTEX_OOW_TMU0_OFFSET << 2, GR_PARAM_ENABLE);
+ else
+ grVertexLayout(GR_PARAM_Q0,GR_VERTEX_OOW_TMU0_OFFSET << 2, GR_PARAM_DISABLE);
+
+ if (hintMask & GR_STWHINT_ST_DIFF_TMU1)
+ grVertexLayout(GR_PARAM_ST1,GR_VERTEX_SOW_TMU1_OFFSET << 2, GR_PARAM_ENABLE);
+ else
+ grVertexLayout(GR_PARAM_ST1,GR_VERTEX_SOW_TMU1_OFFSET << 2, GR_PARAM_DISABLE);
+
+ if (hintMask & GR_STWHINT_W_DIFF_TMU1)
+ grVertexLayout(GR_PARAM_Q1,GR_VERTEX_OOW_TMU1_OFFSET << 2, GR_PARAM_ENABLE);
+ else
+ grVertexLayout(GR_PARAM_Q1,GR_VERTEX_OOW_TMU1_OFFSET << 2, GR_PARAM_DISABLE);
+
+ }
+ }
+}
+int FX_grSstQueryHardware(GrHwConfiguration *config)
+{
+ int i,j;
+ int numFB;
+ grGet(GR_NUM_BOARDS,4,(void*)&(config->num_sst));
+ if (config->num_sst == 0)
+ return 0;
+ for (i = 0; i< config->num_sst; i++)
+ {
+ config->SSTs[i].type = GR_SSTTYPE_VOODOO;
+ grSstSelect(i);
+ grGet(GR_MEMORY_FB,4,(void*)&(config->SSTs[i].sstBoard.VoodooConfig.fbRam));
+ config->SSTs[i].sstBoard.VoodooConfig.fbRam/= 1024*1024;
+
+ grGet(GR_NUM_TMU,4,(void*)&(config->SSTs[i].sstBoard.VoodooConfig.nTexelfx));
+
+
+ grGet(GR_NUM_FB,4,(void*)&numFB);
+ if (numFB > 1)
+ config->SSTs[i].sstBoard.VoodooConfig.sliDetect = FXTRUE;
+ else
+ config->SSTs[i].sstBoard.VoodooConfig.sliDetect = FXFALSE;
+ for (j = 0; j < config->SSTs[i].sstBoard.VoodooConfig.nTexelfx; j++)
+ {
+ grGet(GR_MEMORY_TMU,4,(void*)&(config->SSTs[i].sstBoard.VoodooConfig.tmuConfig[i].tmuRam));
+ }
+ }
+ return 1;
+}
+
+
+#endif
+#else
+
+/*
+ * Need this to provide at least one external definition.
+ */
+
+int gl_fx_dummy_function_glidew(void)
+{
+ return 0;
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/fxglidew.h b/src/mesa/drivers/glide/fxglidew.h
new file mode 100644
index 0000000000..17f395686c
--- /dev/null
+++ b/src/mesa/drivers/glide/fxglidew.h
@@ -0,0 +1,358 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+#ifndef __FX_GLIDE_WARPER__
+#define __FX_GLIDE_WARPER__
+
+#include <glide.h>
+
+/*
+ * General context:
+ */
+#if !defined(FX_GLIDE3)
+ typedef FxU32 FX_GrContext_t; /* Not used in Glide2 */
+#else
+ typedef GrContext_t FX_GrContext_t;
+#endif
+
+/*
+ * Glide3 emulation on Glide2:
+ */
+#if !defined(FX_GLIDE3)
+ /* Constanst for FX_grGetInteger( ) */
+ #define FX_FOG_TABLE_ENTRIES 0x0004 /* The number of entries in the hardware fog table. */
+ #define FX_GLIDE_STATE_SIZE 0x0006 /* Size of buffer, in bytes, needed to save Glide state. */
+ #define FX_LFB_PIXEL_PIPE 0x0009 /* 1 if LFB writes can go through the 3D pixel pipe. */
+ #define FX_PENDING_BUFFERSWAPS 0x0014 /* The number of buffer swaps pending. */
+#else
+ #define FX_FOG_TABLE_ENTRIES GR_FOG_TABLE_ENTRIES
+ #define FX_GLIDE_STATE_SIZE GR_GLIDE_STATE_SIZE
+ #define FX_LFB_PIXEL_PIPE GR_LFB_PIXEL_PIPE
+ #define FX_PENDING_BUFFERSWAPS GR_PENDING_BUFFERSWAPS
+#endif
+
+/*
+ * Genral warper functions for Glide2/Glide3:
+ */
+extern FxI32 FX_grGetInteger(FxU32 pname);
+
+/*
+ * Glide2 emulation on Glide3:
+ */
+#if defined(FX_GLIDE3)
+
+#define GR_ASPECT_1x1 GR_ASPECT_LOG2_1x1
+#define GR_ASPECT_2x1 GR_ASPECT_LOG2_2x1
+#define GR_ASPECT_4x1 GR_ASPECT_LOG2_4x1
+#define GR_ASPECT_8x1 GR_ASPECT_LOG2_8x1
+#define GR_ASPECT_1x2 GR_ASPECT_LOG2_1x2
+#define GR_ASPECT_1x4 GR_ASPECT_LOG2_1x4
+#define GR_ASPECT_1x8 GR_ASPECT_LOG2_1x8
+
+#define GR_LOD_256 GR_LOD_LOG2_256
+#define GR_LOD_128 GR_LOD_LOG2_128
+#define GR_LOD_64 GR_LOD_LOG2_64
+#define GR_LOD_32 GR_LOD_LOG2_32
+#define GR_LOD_16 GR_LOD_LOG2_16
+#define GR_LOD_8 GR_LOD_LOG2_8
+#define GR_LOD_4 GR_LOD_LOG2_4
+#define GR_LOD_2 GR_LOD_LOG2_2
+#define GR_LOD_1 GR_LOD_LOG2_1
+
+#define GR_FOG_WITH_TABLE GR_FOG_WITH_TABLE_ON_Q
+
+typedef int GrSstType;
+
+#define MAX_NUM_SST 4
+
+#define GR_SSTTYPE_VOODOO 0
+#define GR_SSTTYPE_SST96 1
+#define GR_SSTTYPE_AT3D 2
+#define GR_SSTTYPE_Voodoo2 3
+
+typedef struct GrTMUConfig_St {
+ int tmuRev; /* Rev of Texelfx chip */
+ int tmuRam; /* 1, 2, or 4 MB */
+} GrTMUConfig_t;
+
+typedef struct GrVoodooConfig_St {
+ int fbRam; /* 1, 2, or 4 MB */
+ int fbiRev; /* Rev of Pixelfx chip */
+ int nTexelfx; /* How many texelFX chips are there? */
+ FxBool sliDetect; /* Is it a scan-line interleaved board? */
+ GrTMUConfig_t tmuConfig[GLIDE_NUM_TMU]; /* Configuration of the Texelfx chips */
+} GrVoodooConfig_t;
+
+typedef struct GrSst96Config_St {
+ int fbRam; /* How much? */
+ int nTexelfx;
+ GrTMUConfig_t tmuConfig;
+} GrSst96Config_t;
+
+typedef GrVoodooConfig_t GrVoodoo2Config_t;
+
+typedef struct GrAT3DConfig_St {
+ int rev;
+} GrAT3DConfig_t;
+
+typedef struct {
+ int num_sst; /* # of HW units in the system */
+ struct {
+ GrSstType type; /* Which hardware is it? */
+ union SstBoard_u {
+ GrVoodooConfig_t VoodooConfig;
+ GrSst96Config_t SST96Config;
+ GrAT3DConfig_t AT3DConfig;
+ GrVoodoo2Config_t Voodoo2Config;
+ } sstBoard;
+ } SSTs[MAX_NUM_SST]; /* configuration for each board */
+} GrHwConfiguration;
+
+typedef FxU32 GrHint_t;
+#define GR_HINTTYPE_MIN 0
+#define GR_HINT_STWHINT 0
+
+typedef FxU32 GrSTWHint_t;
+#define GR_STWHINT_W_DIFF_FBI FXBIT(0)
+#define GR_STWHINT_W_DIFF_TMU0 FXBIT(1)
+#define GR_STWHINT_ST_DIFF_TMU0 FXBIT(2)
+#define GR_STWHINT_W_DIFF_TMU1 FXBIT(3)
+#define GR_STWHINT_ST_DIFF_TMU1 FXBIT(4)
+#define GR_STWHINT_W_DIFF_TMU2 FXBIT(5)
+#define GR_STWHINT_ST_DIFF_TMU2 FXBIT(6)
+
+#define GR_CONTROL_ACTIVATE 1
+#define GR_CONTROL_DEACTIVATE 0
+
+#define GrState void
+
+/*
+** move the vertex layout defintion to application
+*/
+typedef struct {
+ float sow; /* s texture ordinate (s over w) */
+ float tow; /* t texture ordinate (t over w) */
+ float oow; /* 1/w (used mipmapping - really 0xfff/w) */
+} GrTmuVertex;
+
+typedef struct
+{
+ float x, y; /* X and Y in screen space */
+ float ooz; /* 65535/Z (used for Z-buffering) */
+ float oow; /* 1/W (used for W-buffering, texturing) */
+ float r, g, b, a; /* R, G, B, A [0..255.0] */
+ float z; /* Z is ignored */
+ GrTmuVertex tmuvtx[GLIDE_NUM_TMU];
+} GrVertex;
+
+#define GR_VERTEX_X_OFFSET 0
+#define GR_VERTEX_Y_OFFSET 1
+#define GR_VERTEX_OOZ_OFFSET 2
+#define GR_VERTEX_OOW_OFFSET 3
+#define GR_VERTEX_R_OFFSET 4
+#define GR_VERTEX_G_OFFSET 5
+#define GR_VERTEX_B_OFFSET 6
+#define GR_VERTEX_A_OFFSET 7
+#define GR_VERTEX_Z_OFFSET 8
+#define GR_VERTEX_SOW_TMU0_OFFSET 9
+#define GR_VERTEX_TOW_TMU0_OFFSET 10
+#define GR_VERTEX_OOW_TMU0_OFFSET 11
+#define GR_VERTEX_SOW_TMU1_OFFSET 12
+#define GR_VERTEX_TOW_TMU1_OFFSET 13
+#define GR_VERTEX_OOW_TMU1_OFFSET 14
+
+#endif
+
+
+/*
+ * Glide2 functions for Glide3
+ */
+#if defined(FX_GLIDE3)
+#define FX_grTexDownloadTable(TMU,type,data) grTexDownloadTable(type,data)
+#else
+#define FX_grTexDownloadTable(TMU,type,data) grTexDownloadTable(TMU,type,data)
+#endif
+
+/*
+ * Flush
+ */
+#if defined(FX_GLIDE3)
+#define FX_grFlush grFlush
+#else
+#define FX_grFlush grSstIdle
+#endif
+/*
+ * Write region: ToDo possible exploit the PixelPipe parameter.
+ */
+#if defined(FX_GLIDE3)
+#define FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data) \
+ grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,FXFALSE,src_stride,src_data)
+#else
+#define FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data) \
+ grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data)
+#endif
+/*
+ * For Lod/LodLog2 conversion.
+ */
+#if defined(FX_GLIDE3)
+ #define FX_largeLodLog2(info) (info).largeLodLog2
+#else
+ #define FX_largeLodLog2(info) (info).largeLod
+#endif
+
+#if defined(FX_GLIDE3)
+ #define FX_aspectRatioLog2(info) (info).aspectRatioLog2
+#else
+ #define FX_aspectRatioLog2(info) (info).aspectRatio
+#endif
+
+#if defined(FX_GLIDE3)
+ #define FX_smallLodLog2(info) (info).smallLodLog2
+#else
+ #define FX_smallLodLog2(info) (info).smallLod
+#endif
+
+#if defined(FX_GLIDE3)
+ #define FX_lodToValue(val) ((int)(GR_LOD_256-val))
+#else
+ #define FX_lodToValue(val) ((int)(val))
+#endif
+
+#if defined(FX_GLIDE3)
+ #define FX_largeLodValue(info) ((int)(GR_LOD_256-(info).largeLodLog2))
+#else
+ #define FX_largeLodValue(info) ((int)(info).largeLod)
+#endif
+
+#if defined(FX_GLIDE3)
+ #define FX_smallLodValue(info) ((int)(GR_LOD_256-(info).smallLodLog2))
+#else
+ #define FX_smallLodValue(info) ((int)(info).smallLod)
+#endif
+
+#if defined(FX_GLIDE3)
+ #define FX_valueToLod(val) ((GrLOD_t)(GR_LOD_256-val))
+#else
+ #define FX_valueToLod(val) ((GrLOD_t)(val))
+#endif
+
+/*
+ * ScreenWidth/Height stuff.
+ */
+#if defined(FX_GLIDE3)
+ extern int FX_grSstScreenWidth();
+ extern int FX_grSstScreenHeight();
+#else
+ #define FX_grSstScreenWidth() grSstScreenWidth()
+ #define FX_grSstScreenHeight() grSstScreenHeight()
+#endif
+
+
+/*
+ * Version string.
+ */
+#if defined(FX_GLIDE3)
+ extern void FX_grGlideGetVersion(char *buf);
+#else
+ #define FX_grGlideGetVersion grGlideGetVersion
+#endif
+/*
+ * Performance statistics
+ */
+#if defined(FX_GLIDE3)
+ extern void FX_grSstPerfStats(GrSstPerfStats_t *st);
+#else
+ #define FX_grSstPerfStats grSstPerfStats
+#endif
+
+/*
+ * Hardware Query
+ */
+#if defined(FX_GLIDE3)
+ extern int FX_grSstQueryHardware(GrHwConfiguration *config);
+#else
+ #define FX_grSstQueryHardware grSstQueryHardware
+#endif
+
+/*
+ * GrHints
+ */
+#if defined(FX_GLIDE3)
+ extern void FX_grHints(GrHint_t hintType, FxU32 hintMask);
+#else
+ #define FX_grHints grHints
+#endif
+/*
+ * Antialiashed line+point drawing.
+ */
+#if defined(FX_GLIDE3)
+ extern void FX_grAADrawLine(GrVertex *a,GrVertex *b);
+#else
+ #define FX_grAADrawLine grAADrawLine
+#endif
+
+#if defined(FX_GLIDE3)
+ extern void FX_grAADrawPoint(GrVertex *a);
+#else
+ #define FX_grAADrawPoint grAADrawPoint
+#endif
+
+/*
+ * Needed for Glide3 only, to set up Glide2 compatible vertex layout.
+ */
+#if defined(FX_GLIDE3)
+ extern void FX_setupGrVertexLayout(void);
+#else
+ #define FX_setupGrVertexLayout() do {} while (0)
+#endif
+/*
+ * grSstControl stuff
+ */
+#if defined(FX_GLIDE3)
+ extern void FX_grSstControl(int par);
+#else
+ #define FX_grSstControl grSstControl
+#endif
+/*
+ * grGammaCorrectionValue
+ */
+#if defined(FX_GLIDE3)
+ extern void FX_grGammaCorrectionValue(float val);
+#else
+ #define FX_grGammaCorrectionValue grGammaCorrectionValue
+#endif
+
+/*
+ * WinOpen/Close.
+ */
+#if defined(FX_GLIDE3)
+ #define FX_grSstWinOpen(hWnd,screen_resolution,refresh_rate,color_format,origin_location,nColBuffers,nAuxBuffers) \
+ grSstWinOpen(-1,screen_resolution,refresh_rate,color_format,origin_location,nColBuffers,nAuxBuffers)
+ #define FX_grSstWinClose grSstWinClose
+#else
+ #define FX_grSstWinOpen grSstWinOpen
+ #define FX_grSstWinClose(win) grSstWinClose()
+#endif
+
+
+#endif /* __FX_GLIDE_WARPER__ */
diff --git a/src/mesa/drivers/glide/fxopengl.def b/src/mesa/drivers/glide/fxopengl.def
new file mode 100644
index 0000000000..af76f4c1b2
--- /dev/null
+++ b/src/mesa/drivers/glide/fxopengl.def
@@ -0,0 +1,467 @@
+EXPORTS
+ glAccum
+ glAlphaFunc
+ glAreTexturesResident
+ glArrayElement
+ glBegin
+ glBindTexture
+ glBitmap
+ glBlendFunc
+ glCallList
+ glCallLists
+ glClear
+ glClearAccum
+ glClearIndex
+ glClearColor
+ glClearDepth
+ glClearStencil
+ glClipPlane
+ glColor3b
+ glColor3d
+ glColor3f
+ glColor3i
+ glColor3s
+ glColor3ub
+ glColor3ui
+ glColor3us
+ glColor4b
+ glColor4d
+ glColor4f
+ glColor4i
+ glColor4s
+ glColor4ub
+ glColor4ui
+ glColor4us
+ glColor3bv
+ glColor3dv
+ glColor3fv
+ glColor3iv
+ glColor3sv
+ glColor3ubv
+ glColor3uiv
+ glColor3usv
+ glColor4bv
+ glColor4dv
+ glColor4fv
+ glColor4iv
+ glColor4sv
+ glColor4ubv
+ glColor4uiv
+ glColor4usv
+ glColorMask
+ glColorMaterial
+ glColorPointer
+ glColorTableEXT
+ glColorSubTableEXT
+ glCopyPixels
+ glCopyTexImage1D
+ glCopyTexImage2D
+ glCopyTexSubImage1D
+ glCopyTexSubImage2D
+ glCullFace
+ glDepthFunc
+ glDepthMask
+ glDepthRange
+ glDeleteLists
+ glDeleteTextures
+ glDisable
+ glDisableClientState
+ glDrawArrays
+ glDrawBuffer
+ glDrawElements
+ glDrawPixels
+ glEnable
+ glEnableClientState
+ glEnd
+ glEndList
+ glEvalCoord1d
+ glEvalCoord1f
+ glEvalCoord1dv
+ glEvalCoord1fv
+ glEvalCoord2d
+ glEvalCoord2f
+ glEvalCoord2dv
+ glEvalCoord2fv
+ glEvalPoint1
+ glEvalPoint2
+ glEvalMesh1
+ glEdgeFlag
+ glEdgeFlagv
+ glEdgeFlagPointer
+ glEvalMesh2
+ glFeedbackBuffer
+ glFinish
+ glFlush
+ glFogf
+ glFogi
+ glFogfv
+ glFogiv
+ glFrontFace
+ glFrustum
+ glGenLists
+ glGenTextures
+ glGetBooleanv
+ glGetClipPlane
+ glGetColorTableEXT
+ glGetColorTableParameterivEXT
+ glGetColorTableParameterfvEXT
+ glGetDoublev
+ glGetError
+ glGetFloatv
+ glGetIntegerv
+ glGetLightfv
+ glGetLightiv
+ glGetMapdv
+ glGetMapfv
+ glGetMapiv
+ glGetMaterialfv
+ glGetMaterialiv
+ glGetPixelMapfv
+ glGetPixelMapuiv
+ glGetPixelMapusv
+ glGetPointerv
+ glGetPolygonStipple
+ glGetString
+ glGetTexEnvfv
+ glGetTexEnviv
+ glGetTexGeniv
+ glGetTexGendv
+ glGetTexGenfv
+ glGetTexImage
+ glGetTexLevelParameterfv
+ glGetTexLevelParameteriv
+ glGetTexParameterfv
+ glGetTexParameteriv
+ glHint
+ glIndexd
+ glIndexf
+ glIndexi
+ glIndexs
+ glIndexub
+ glIndexdv
+ glIndexfv
+ glIndexiv
+ glIndexsv
+ glIndexubv
+ glIndexMask
+ glIndexPointer
+ glInterleavedArrays
+ glInitNames
+ glIsList
+ glIsTexture
+ glLightf
+ glLighti
+ glLightfv
+ glLightiv
+ glLightModelf
+ glLightModeli
+ glLightModelfv
+ glLightModeliv
+ glLineWidth
+ glLineStipple
+ glListBase
+ glLoadIdentity
+ glLoadMatrixd
+ glLoadMatrixf
+ glLoadName
+ glLogicOp
+ glMap1d
+ glMap1f
+ glMap2d
+ glMap2f
+ glMapGrid1d
+ glMapGrid1f
+ glMapGrid2d
+ glMapGrid2f
+ glMaterialf
+ glMateriali
+ glMaterialfv
+ glMaterialiv
+ glMatrixMode
+ glMultMatrixd
+ glMultMatrixf
+ glNewList
+ glNormal3b
+ glNormal3d
+ glNormal3f
+ glNormal3i
+ glNormal3s
+ glNormal3bv
+ glNormal3dv
+ glNormal3fv
+ glNormal3iv
+ glNormal3sv
+ glNormalPointer
+ glOrtho
+ glPassThrough
+ glPixelMapfv
+ glPixelMapuiv
+ glPixelMapusv
+ glPixelStoref
+ glPixelStorei
+ glPixelTransferf
+ glPixelTransferi
+ glPixelZoom
+ glPointSize
+ glPolygonMode
+ glPolygonOffset
+ glPolygonOffsetEXT
+ glPolygonStipple
+ glPopAttrib
+ glPopClientAttrib
+ glPopMatrix
+ glPopName
+ glPrioritizeTextures
+ glPushMatrix
+ glRasterPos2d
+ glRasterPos2f
+ glRasterPos2i
+ glRasterPos2s
+ glRasterPos3d
+ glRasterPos3f
+ glRasterPos3i
+ glRasterPos3s
+ glRasterPos4d
+ glRasterPos4f
+ glRasterPos4i
+ glRasterPos4s
+ glRasterPos2dv
+ glRasterPos2fv
+ glRasterPos2iv
+ glRasterPos2sv
+ glRasterPos3dv
+ glRasterPos3fv
+ glRasterPos3iv
+ glRasterPos3sv
+ glRasterPos4dv
+ glRasterPos4fv
+ glRasterPos4iv
+ glRasterPos4sv
+ glReadBuffer
+ glReadPixels
+ glRectd
+ glRectf
+ glRecti
+ glRects
+ glRectdv
+ glRectfv
+ glRectiv
+ glRectsv
+ glScissor
+ glIsEnabled
+ glPushAttrib
+ glPushClientAttrib
+ glPushName
+ glRenderMode
+ glRotated
+ glRotatef
+ glSelectBuffer
+ glScaled
+ glScalef
+ glShadeModel
+ glStencilFunc
+ glStencilMask
+ glStencilOp
+ glTexCoord1d
+ glTexCoord1f
+ glTexCoord1i
+ glTexCoord1s
+ glTexCoord2d
+ glTexCoord2f
+ glTexCoord2i
+ glTexCoord2s
+ glTexCoord3d
+ glTexCoord3f
+ glTexCoord3i
+ glTexCoord3s
+ glTexCoord4d
+ glTexCoord4f
+ glTexCoord4i
+ glTexCoord4s
+ glTexCoord1dv
+ glTexCoord1fv
+ glTexCoord1iv
+ glTexCoord1sv
+ glTexCoord2dv
+ glTexCoord2fv
+ glTexCoord2iv
+ glTexCoord2sv
+ glTexCoord3dv
+ glTexCoord3fv
+ glTexCoord3iv
+ glTexCoord3sv
+ glTexCoord4dv
+ glTexCoord4fv
+ glTexCoord4iv
+ glTexCoord4sv
+ glTexCoordPointer
+ glTexGend
+ glTexGenf
+ glTexGeni
+ glTexGendv
+ glTexGeniv
+ glTexGenfv
+ glTexEnvf
+ glTexEnvi
+ glTexEnvfv
+ glTexEnviv
+ glTexImage1D
+ glTexImage2D
+ glTexParameterf
+ glTexParameteri
+ glTexParameterfv
+ glTexParameteriv
+ glTexSubImage1D
+ glTexSubImage2D
+ glTranslated
+ glTranslatef
+ glVertex2d
+ glVertex2f
+ glVertex2i
+ glVertex2s
+ glVertex3d
+ glVertex3f
+ glVertex3i
+ glVertex3s
+ glVertex4d
+ glVertex4f
+ glVertex4i
+ glVertex4s
+ glVertex2dv
+ glVertex2fv
+ glVertex2iv
+ glVertex2sv
+ glVertex3dv
+ glVertex3fv
+ glVertex3iv
+ glVertex3sv
+ glVertex4dv
+ glVertex4fv
+ glVertex4iv
+ glVertex4sv
+ glVertexPointer
+ glViewport
+ glBlendEquationEXT
+ glBlendColorEXT
+ glVertexPointerEXT
+ glNormalPointerEXT
+ glColorPointerEXT
+ glIndexPointerEXT
+ glTexCoordPointerEXT
+ glEdgeFlagPointerEXT
+ glGetPointervEXT
+ glArrayElementEXT
+ glDrawArraysEXT
+ glBindTextureEXT
+ glDeleteTexturesEXT
+ glGenTexturesEXT
+ glPrioritizeTexturesEXT
+ glCopyTexSubImage3DEXT
+ glTexImage3DEXT
+ glTexSubImage3DEXT
+ glWindowPos4fMESA
+ glWindowPos2iMESA
+ glWindowPos2sMESA
+ glWindowPos2fMESA
+ glWindowPos2dMESA
+ glWindowPos2ivMESA
+ glWindowPos2svMESA
+ glWindowPos2fvMESA
+ glWindowPos2dvMESA
+ glWindowPos3iMESA
+ glWindowPos3sMESA
+ glWindowPos3fMESA
+ glWindowPos3dMESA
+ glWindowPos3ivMESA
+ glWindowPos3svMESA
+ glWindowPos3fvMESA
+ glWindowPos3dvMESA
+ glWindowPos4iMESA
+ glWindowPos4sMESA
+ glWindowPos4dMESA
+ glWindowPos4ivMESA
+ glWindowPos4svMESA
+ glWindowPos4fvMESA
+ glWindowPos4dvMESA
+ glResizeBuffersMESA
+ wglCopyContext
+ wglCreateContext
+ wglCreateLayerContext
+ wglDeleteContext
+;wglDescribeLayerPlane
+ wglGetCurrentContext
+ wglGetCurrentDC
+;wglGetLayerPaletteEntries
+ wglGetProcAddress
+ wglMakeCurrent
+;wglRealizeLayerPalette
+;wglSetLayerPaletteEntries
+ wglShareLists
+ wglSwapLayerBuffers
+ wglUseFontBitmapsA
+ wglUseFontBitmapsW
+ wglUseFontOutlinesA
+ wglUseFontOutlinesW
+ wglChoosePixelFormat
+ ChoosePixelFormat
+ wglDescribePixelFormat
+ DescribePixelFormat
+ wglGetPixelFormat
+ GetPixelFormat
+ wglSetPixelFormat
+ SetPixelFormat
+ wglSwapBuffers
+ SwapBuffers
+ gl3DfxSetPaletteEXT
+ glActiveTextureARB
+ glClientActiveTextureARB
+ glMultiTexCoord1dARB
+ glMultiTexCoord1dvARB
+ glMultiTexCoord1fARB
+ glMultiTexCoord1fvARB
+ glMultiTexCoord1iARB
+ glMultiTexCoord1ivARB
+ glMultiTexCoord1sARB
+ glMultiTexCoord1svARB
+ glMultiTexCoord2dARB
+ glMultiTexCoord2dvARB
+ glMultiTexCoord2fARB
+ glMultiTexCoord2fvARB
+ glMultiTexCoord2iARB
+ glMultiTexCoord2ivARB
+ glMultiTexCoord2sARB
+ glMultiTexCoord2svARB
+ glMultiTexCoord3dARB
+ glMultiTexCoord3dvARB
+ glMultiTexCoord3fARB
+ glMultiTexCoord3fvARB
+ glMultiTexCoord3iARB
+ glMultiTexCoord3ivARB
+ glMultiTexCoord3sARB
+ glMultiTexCoord3svARB
+ glMultiTexCoord4dARB
+ glMultiTexCoord4dvARB
+ glMultiTexCoord4fARB
+ glMultiTexCoord4fvARB
+ glMultiTexCoord4iARB
+ glMultiTexCoord4ivARB
+ glMultiTexCoord4sARB
+ glMultiTexCoord4svARB
+ fxMesaCreateContext
+ fxMesaCreateBestContext
+ fxMesaDestroyContext
+ fxMesaSelectCurrentBoard
+ fxMesaMakeCurrent
+ fxMesaGetCurrentContext
+ fxMesaSwapBuffers
+ fxMesaSetNearFar
+ fxMesaUpdateScreenSize
+ fxQueryHardware
+ fxCloseHardware
+ OSMesaCreateContext
+ OSMesaDestroyContext
+ OSMesaGetCurrentContext
+ OSMesaGetDepthBuffer
+ OSMesaGetIntegerv
+ OSMesaMakeCurrent
+ OSMesaPixelStore
diff --git a/src/mesa/drivers/glide/fxsetup.c b/src/mesa/drivers/glide/fxsetup.c
new file mode 100644
index 0000000000..9996499316
--- /dev/null
+++ b/src/mesa/drivers/glide/fxsetup.c
@@ -0,0 +1,1552 @@
+/* -*- mode: C; tab-width:8; -*-
+
+ fxsetup.c - 3Dfx VooDoo rendering mode setup functions
+*/
+
+/*
+ * 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.
+ *
+ * See the file fxapi.c for more informations about authors
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#if defined(FX)
+
+#include "fxdrv.h"
+#include "enums.h"
+
+static void fxTexValidate(GLcontext *ctx, struct gl_texture_object *tObj)
+{
+ tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData;
+ GLint minl,maxl;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxTexValidate(...) Start\n");
+ }
+
+ if(ti->validated) {
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxTexValidate(...) End (validated=GL_TRUE)\n");
+ }
+ return;
+ }
+
+ minl=ti->minLevel=tObj->BaseLevel;
+ maxl=ti->maxLevel=MIN2(tObj->MaxLevel,tObj->Image[0]->MaxLog2);
+
+ fxTexGetInfo(tObj->Image[minl]->Width,tObj->Image[minl]->Height,
+ &(FX_largeLodLog2(ti->info)),&(FX_aspectRatioLog2(ti->info)),
+ &(ti->sScale),&(ti->tScale),
+ &(ti->int_sScale),&(ti->int_tScale),
+ NULL,NULL);
+
+
+ if((tObj->MinFilter!=GL_NEAREST) && (tObj->MinFilter!=GL_LINEAR))
+ fxTexGetInfo(tObj->Image[maxl]->Width,tObj->Image[maxl]->Height,
+ &(FX_smallLodLog2(ti->info)),NULL,
+ NULL,NULL,
+ NULL,NULL,
+ NULL,NULL);
+ else
+ FX_smallLodLog2(ti->info)=FX_largeLodLog2(ti->info);
+
+ fxTexGetFormat(tObj->Image[minl]->Format,&(ti->info.format),&(ti->baseLevelInternalFormat));
+
+ ti->validated=GL_TRUE;
+
+ ti->info.data=NULL;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxTexValidate(...) End\n");
+ }
+}
+
+static void fxPrintUnitsMode( const char *msg, GLuint mode )
+{
+ fprintf(stderr,
+ "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+ msg,
+ mode,
+ (mode & FX_UM_E0_REPLACE) ? "E0_REPLACE, " : "",
+ (mode & FX_UM_E0_MODULATE) ? "E0_MODULATE, " : "",
+ (mode & FX_UM_E0_DECAL) ? "E0_DECAL, " : "",
+ (mode & FX_UM_E0_BLEND) ? "E0_BLEND, " : "",
+ (mode & FX_UM_E1_REPLACE) ? "E1_REPLACE, " : "",
+ (mode & FX_UM_E1_MODULATE) ? "E1_MODULATE, " : "",
+ (mode & FX_UM_E1_DECAL) ? "E1_DECAL, " : "",
+ (mode & FX_UM_E1_BLEND) ? "E1_BLEND, " : "",
+ (mode & FX_UM_E0_ALPHA) ? "E0_ALPHA, " : "",
+ (mode & FX_UM_E0_LUMINANCE) ? "E0_LUMINANCE, " : "",
+ (mode & FX_UM_E0_LUMINANCE_ALPHA) ? "E0_LUMINANCE_ALPHA, " : "",
+ (mode & FX_UM_E0_INTENSITY) ? "E0_INTENSITY, " : "",
+ (mode & FX_UM_E0_RGB) ? "E0_RGB, " : "",
+ (mode & FX_UM_E0_RGBA) ? "E0_RGBA, " : "",
+ (mode & FX_UM_E1_ALPHA) ? "E1_ALPHA, " : "",
+ (mode & FX_UM_E1_LUMINANCE) ? "E1_LUMINANCE, " : "",
+ (mode & FX_UM_E1_LUMINANCE_ALPHA) ? "E1_LUMINANCE_ALPHA, " : "",
+ (mode & FX_UM_E1_INTENSITY) ? "E1_INTENSITY, " : "",
+ (mode & FX_UM_E1_RGB) ? "E1_RGB, " : "",
+ (mode & FX_UM_E1_RGBA) ? "E1_RGBA, " : "",
+ (mode & FX_UM_COLOR_ITERATED) ? "COLOR_ITERATED, " : "",
+ (mode & FX_UM_COLOR_CONSTANT) ? "COLOR_CONSTANT, " : "",
+ (mode & FX_UM_ALPHA_ITERATED) ? "ALPHA_ITERATED, " : "",
+ (mode & FX_UM_ALPHA_CONSTANT) ? "ALPHA_CONSTANT, " : "");
+}
+
+GLuint fxGetTexSetConfiguration(GLcontext *ctx,
+ struct gl_texture_object *tObj0,
+ struct gl_texture_object *tObj1)
+{
+ GLuint unitsmode=0;
+ GLuint envmode=0;
+ GLuint ifmt=0;
+
+ if((ctx->Light.ShadeModel==GL_SMOOTH) ||
+ (ctx->Point.SmoothFlag) ||
+ (ctx->Line.SmoothFlag) ||
+ (ctx->Polygon.SmoothFlag))
+ unitsmode|=FX_UM_ALPHA_ITERATED;
+ else
+ unitsmode|=FX_UM_ALPHA_CONSTANT;
+
+ if(ctx->Light.ShadeModel==GL_SMOOTH)
+ unitsmode|=FX_UM_COLOR_ITERATED;
+ else
+ unitsmode|=FX_UM_COLOR_CONSTANT;
+
+ if(tObj0) {
+ tfxTexInfo *ti0=(tfxTexInfo *)tObj0->DriverData;
+
+ switch(ti0->baseLevelInternalFormat) {
+ case GL_ALPHA:
+ ifmt|=FX_UM_E0_ALPHA;
+ break;
+ case GL_LUMINANCE:
+ ifmt|=FX_UM_E0_LUMINANCE;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ ifmt|=FX_UM_E0_LUMINANCE_ALPHA;
+ break;
+ case GL_INTENSITY:
+ ifmt|=FX_UM_E0_INTENSITY;
+ break;
+ case GL_RGB:
+ ifmt|=FX_UM_E0_RGB;
+ break;
+ case GL_RGBA:
+ ifmt|=FX_UM_E0_RGBA;
+ break;
+ }
+
+ switch(ctx->Texture.Unit[0].EnvMode) {
+ case GL_DECAL:
+ envmode|=FX_UM_E0_DECAL;
+ break;
+ case GL_MODULATE:
+ envmode|=FX_UM_E0_MODULATE;
+ break;
+ case GL_REPLACE:
+ envmode|=FX_UM_E0_REPLACE;
+ break;
+ case GL_BLEND:
+ envmode|=FX_UM_E0_BLEND;
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+ }
+
+ if(tObj1) {
+ tfxTexInfo *ti1=(tfxTexInfo *)tObj1->DriverData;
+
+ switch(ti1->baseLevelInternalFormat) {
+ case GL_ALPHA:
+ ifmt|=FX_UM_E1_ALPHA;
+ break;
+ case GL_LUMINANCE:
+ ifmt|=FX_UM_E1_LUMINANCE;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ ifmt|=FX_UM_E1_LUMINANCE_ALPHA;
+ break;
+ case GL_INTENSITY:
+ ifmt|=FX_UM_E1_INTENSITY;
+ break;
+ case GL_RGB:
+ ifmt|=FX_UM_E1_RGB;
+ break;
+ case GL_RGBA:
+ ifmt|=FX_UM_E1_RGBA;
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+
+ switch(ctx->Texture.Unit[1].EnvMode) {
+ case GL_DECAL:
+ envmode|=FX_UM_E1_DECAL;
+ break;
+ case GL_MODULATE:
+ envmode|=FX_UM_E1_MODULATE;
+ break;
+ case GL_REPLACE:
+ envmode|=FX_UM_E1_REPLACE;
+ break;
+ case GL_BLEND:
+ envmode|=FX_UM_E1_BLEND;
+ break;
+ default:
+ /* do nothing */
+ break;
+ }
+ }
+
+ unitsmode|=(ifmt | envmode);
+
+ if (MESA_VERBOSE & (VERBOSE_DRIVER|VERBOSE_TEXTURE))
+ fxPrintUnitsMode("unitsmode", unitsmode);
+
+ return unitsmode;
+}
+
+/************************************************************************/
+/************************* Rendering Mode SetUp *************************/
+/************************************************************************/
+
+/************************* Single Texture Set ***************************/
+
+static void fxSetupSingleTMU(fxMesaContext fxMesa, struct gl_texture_object *tObj)
+{
+ tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData;
+
+ if(!ti->tmi.isInTM) {
+ if(ti->LODblend)
+ fxTMMoveInTM(fxMesa,tObj,FX_TMU_SPLIT);
+ else {
+ if(fxMesa->haveTwoTMUs) {
+ if(fxMesa->freeTexMem[FX_TMU0]>grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH,&(ti->info)))
+ fxTMMoveInTM(fxMesa,tObj,FX_TMU0);
+ else
+ fxTMMoveInTM(fxMesa,tObj,FX_TMU1);
+ } else
+ fxTMMoveInTM(fxMesa,tObj,FX_TMU0);
+ }
+ }
+
+ if(ti->LODblend && ti->tmi.whichTMU == FX_TMU_SPLIT) {
+ if((ti->info.format==GR_TEXFMT_P_8) && (!fxMesa->haveGlobalPaletteTexture)) {
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: uploading texture palette\n");
+ }
+ FX_grTexDownloadTable(GR_TMU0,GR_TEXTABLE_PALETTE,&(ti->palette));
+ FX_grTexDownloadTable(GR_TMU1,GR_TEXTABLE_PALETTE,&(ti->palette));
+ }
+
+ grTexClampMode(GR_TMU0,ti->sClamp,ti->tClamp);
+ grTexClampMode(GR_TMU1,ti->sClamp,ti->tClamp);
+ grTexFilterMode(GR_TMU0,ti->minFilt,ti->maxFilt);
+ grTexFilterMode(GR_TMU1,ti->minFilt,ti->maxFilt);
+ grTexMipMapMode(GR_TMU0,ti->mmMode,ti->LODblend);
+ grTexMipMapMode(GR_TMU1,ti->mmMode,ti->LODblend);
+
+ grTexSource(GR_TMU0,ti->tmi.tm[FX_TMU0]->startAddress,
+ GR_MIPMAPLEVELMASK_ODD,&(ti->info));
+ grTexSource(GR_TMU1,ti->tmi.tm[FX_TMU1]->startAddress,
+ GR_MIPMAPLEVELMASK_EVEN,&(ti->info));
+ } else {
+ if((ti->info.format==GR_TEXFMT_P_8) && (!fxMesa->haveGlobalPaletteTexture)) {
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: uploading texture palette\n");
+ }
+ FX_grTexDownloadTable(ti->tmi.whichTMU,GR_TEXTABLE_PALETTE,&(ti->palette));
+ }
+
+ /* KW: The alternative is to do the download to the other tmu. If
+ * we get to this point, I think it means we are thrashing the
+ * texture memory, so perhaps it's not a good idea.
+ */
+ if (ti->LODblend && (MESA_VERBOSE&VERBOSE_DRIVER))
+ fprintf(stderr, "fxmesa: not blending texture - only on one tmu\n");
+
+ grTexClampMode(ti->tmi.whichTMU,ti->sClamp,ti->tClamp);
+ grTexFilterMode(ti->tmi.whichTMU,ti->minFilt,ti->maxFilt);
+ grTexMipMapMode(ti->tmi.whichTMU,ti->mmMode,FXFALSE);
+
+ grTexSource(ti->tmi.whichTMU,ti->tmi.tm[ti->tmi.whichTMU]->startAddress,
+ GR_MIPMAPLEVELMASK_BOTH,&(ti->info));
+ }
+}
+
+static void fxSelectSingleTMUSrc(fxMesaContext fxMesa, GLint tmu, FxBool LODblend)
+{
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxSelectSingleTMUSrc(%d,%d)\n",tmu,LODblend);
+ }
+
+ if(LODblend) {
+ grTexCombine(GR_TMU0,
+ GR_COMBINE_FUNCTION_BLEND,
+ GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION,
+ GR_COMBINE_FUNCTION_BLEND,
+ GR_COMBINE_FACTOR_ONE_MINUS_LOD_FRACTION,
+ FXFALSE,FXFALSE);
+
+ grTexCombine(GR_TMU1,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ FXFALSE,FXFALSE);
+
+ fxMesa->tmuSrc=FX_TMU_SPLIT;
+ } else {
+ if(tmu==FX_TMU0) {
+ grTexCombine(GR_TMU0,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ FXFALSE,FXFALSE);
+
+ fxMesa->tmuSrc=FX_TMU0;
+ } else {
+ grTexCombine(GR_TMU1,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ FXFALSE,FXFALSE);
+
+ /* GR_COMBINE_FUNCTION_SCALE_OTHER doesn't work ?!? */
+
+ grTexCombine(GR_TMU0,
+ GR_COMBINE_FUNCTION_BLEND,GR_COMBINE_FACTOR_ONE,
+ GR_COMBINE_FUNCTION_BLEND,GR_COMBINE_FACTOR_ONE,
+ FXFALSE,FXFALSE);
+
+ fxMesa->tmuSrc=FX_TMU1;
+ }
+ }
+}
+
+void fxSetupTextureSingleTMU(GLcontext *ctx, GLuint textureset)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GrCombineLocal_t localc,locala;
+ GLuint unitsmode;
+ GLint ifmt;
+ tfxTexInfo *ti;
+ struct gl_texture_object *tObj=ctx->Texture.Unit[textureset].CurrentD[2];
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxSetupTextureSingleTMU(...) Start\n");
+ }
+
+ ti=(tfxTexInfo *)tObj->DriverData;
+
+ fxTexValidate(ctx,tObj);
+
+ fxSetupSingleTMU(fxMesa,tObj);
+
+ if(fxMesa->tmuSrc!=ti->tmi.whichTMU)
+ fxSelectSingleTMUSrc(fxMesa,ti->tmi.whichTMU,ti->LODblend);
+
+ if(textureset==0 || !fxMesa->haveTwoTMUs)
+ unitsmode=fxGetTexSetConfiguration(ctx,tObj,NULL);
+ else
+ unitsmode=fxGetTexSetConfiguration(ctx,NULL,tObj);
+
+ if(fxMesa->lastUnitsMode==unitsmode)
+ return;
+
+ fxMesa->lastUnitsMode=unitsmode;
+
+ fxMesa->stw_hint_state = 0;
+ FX_grHints(GR_HINT_STWHINT,0);
+
+ ifmt=ti->baseLevelInternalFormat;
+
+ if(unitsmode & FX_UM_ALPHA_ITERATED)
+ locala=GR_COMBINE_LOCAL_ITERATED;
+ else
+ locala=GR_COMBINE_LOCAL_CONSTANT;
+
+ if(unitsmode & FX_UM_COLOR_ITERATED)
+ localc=GR_COMBINE_LOCAL_ITERATED;
+ else
+ localc=GR_COMBINE_LOCAL_CONSTANT;
+
+ if (MESA_VERBOSE & (VERBOSE_DRIVER|VERBOSE_TEXTURE))
+ fprintf(stderr, "fxMesa: fxSetupTextureSingleTMU, envmode is %s\n",
+ gl_lookup_enum_by_nr(ctx->Texture.Unit[textureset].EnvMode));
+
+ switch(ctx->Texture.Unit[textureset].EnvMode) {
+ case GL_DECAL:
+ grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ locala,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+
+ grColorCombine(GR_COMBINE_FUNCTION_BLEND,
+ GR_COMBINE_FACTOR_TEXTURE_ALPHA,
+ localc,
+ GR_COMBINE_OTHER_TEXTURE,
+ FXFALSE);
+ break;
+ case GL_MODULATE:
+ grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,
+ GR_COMBINE_FACTOR_LOCAL,
+ locala,
+ GR_COMBINE_OTHER_TEXTURE,
+ FXFALSE);
+
+ if(ifmt==GL_ALPHA)
+ grColorCombine(GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ localc,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+ else
+ grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,
+ GR_COMBINE_FACTOR_LOCAL,
+ localc,
+ GR_COMBINE_OTHER_TEXTURE,
+ FXFALSE);
+ break;
+ case GL_BLEND:
+#ifndef FX_SILENT
+ fprintf(stderr,"fx Driver: GL_BLEND not yet supported\n");
+#endif
+ /* TO DO (I think that the Voodoo Graphics isn't able to support GL_BLEND) */
+ break;
+ case GL_REPLACE:
+ if((ifmt==GL_RGB) || (ifmt==GL_LUMINANCE))
+ grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ locala,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+ else
+ grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,
+ GR_COMBINE_FACTOR_ONE,
+ locala,
+ GR_COMBINE_OTHER_TEXTURE,
+ FXFALSE);
+
+ if(ifmt==GL_ALPHA)
+ grColorCombine(GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ localc,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+ else
+ grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,
+ GR_COMBINE_FACTOR_ONE,
+ localc,
+ GR_COMBINE_OTHER_TEXTURE,
+ FXFALSE);
+ break;
+ default:
+#ifndef FX_SILENT
+ fprintf(stderr,"fx Driver: %x Texture.EnvMode not yet supported\n",ctx->Texture.Unit[textureset].EnvMode);
+#endif
+ break;
+ }
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxSetupTextureSingleTMU(...) End\n");
+ }
+}
+
+/************************* Double Texture Set ***************************/
+
+void fxSetupDoubleTMU(fxMesaContext fxMesa, struct gl_texture_object *tObj0,
+ struct gl_texture_object *tObj1)
+{
+#define T0_NOT_IN_TMU 0x01
+#define T1_NOT_IN_TMU 0x02
+#define T0_IN_TMU0 0x04
+#define T1_IN_TMU0 0x08
+#define T0_IN_TMU1 0x10
+#define T1_IN_TMU1 0x20
+
+ tfxTexInfo *ti0=(tfxTexInfo *)tObj0->DriverData;
+ tfxTexInfo *ti1=(tfxTexInfo *)tObj1->DriverData;
+ GLuint tstate=0;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxSetupDoubleTMU(...)\n");
+ }
+
+ if(ti0->tmi.isInTM) {
+ if(ti0->tmi.whichTMU==FX_TMU0)
+ tstate|=T0_IN_TMU0;
+ else if(ti0->tmi.whichTMU==FX_TMU1)
+ tstate|=T0_IN_TMU1;
+ else {
+ fxTMMoveOutTM(fxMesa,tObj0);
+ tstate|=T0_NOT_IN_TMU;
+ }
+ } else
+ tstate|=T0_NOT_IN_TMU;
+
+ if(ti1->tmi.isInTM) {
+ if(ti1->tmi.whichTMU==FX_TMU0)
+ tstate|=T1_IN_TMU0;
+ else if(ti1->tmi.whichTMU==FX_TMU1)
+ tstate|=T1_IN_TMU1;
+ else {
+ fxTMMoveOutTM(fxMesa,tObj1);
+ tstate|=T1_NOT_IN_TMU;
+ }
+ } else
+ tstate|=T1_NOT_IN_TMU;
+
+ ti0->tmi.lastTimeUsed=fxMesa->texBindNumber;
+ ti1->tmi.lastTimeUsed=fxMesa->texBindNumber;
+
+ /* Move texture maps in TMUs */
+
+ switch(tstate) {
+ case (T0_IN_TMU0 | T1_IN_TMU0):
+ fxTMMoveOutTM(fxMesa,tObj1);
+
+ fxTMMoveInTM(fxMesa,tObj1,FX_TMU1);
+ break;
+
+ case (T0_IN_TMU1 | T1_IN_TMU1):
+ fxTMMoveOutTM(fxMesa,tObj0);
+
+ fxTMMoveInTM(fxMesa,tObj0,FX_TMU0);
+ break;
+
+ case (T0_NOT_IN_TMU | T1_NOT_IN_TMU):
+ fxTMMoveInTM(fxMesa,tObj0,FX_TMU0);
+ fxTMMoveInTM(fxMesa,tObj1,FX_TMU1);
+ break;
+
+ /*** T0/T1 ***/
+
+ case (T0_NOT_IN_TMU | T1_IN_TMU0):
+ fxTMMoveInTM(fxMesa,tObj0,FX_TMU1);
+ break;
+
+ case (T0_NOT_IN_TMU | T1_IN_TMU1):
+ fxTMMoveInTM(fxMesa,tObj0,FX_TMU0);
+ break;
+
+ case (T0_IN_TMU0 | T1_NOT_IN_TMU):
+ fxTMMoveInTM(fxMesa,tObj1,FX_TMU1);
+ break;
+
+ case (T0_IN_TMU1 | T1_NOT_IN_TMU):
+ fxTMMoveInTM(fxMesa,tObj1,FX_TMU0);
+ break;
+
+ /*** Best Case ***/
+
+ case (T0_IN_TMU1 | T1_IN_TMU0):
+ case (T0_IN_TMU0 | T1_IN_TMU1):
+ break;
+
+ default:
+ fprintf(stderr,"fx Driver: internal error in fxSetupDoubleTMU()\n");
+ fxCloseHardware();
+ exit(-1);
+ break;
+ }
+
+ if(!fxMesa->haveGlobalPaletteTexture) {
+ if(ti0->info.format==GR_TEXFMT_P_8) {
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: uploading texture palette TMU0\n");
+ }
+ FX_grTexDownloadTable(ti0->tmi.whichTMU,GR_TEXTABLE_PALETTE,&(ti0->palette));
+ }
+
+ if(ti1->info.format==GR_TEXFMT_P_8) {
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: uploading texture palette TMU1\n");
+ }
+ FX_grTexDownloadTable(ti1->tmi.whichTMU,GR_TEXTABLE_PALETTE,&(ti1->palette));
+ }
+ }
+
+ grTexClampMode(ti0->tmi.whichTMU,ti0->sClamp,ti0->tClamp);
+ grTexFilterMode(ti0->tmi.whichTMU,ti0->minFilt,ti0->maxFilt);
+ grTexMipMapMode(ti0->tmi.whichTMU,ti0->mmMode,FXFALSE);
+ grTexSource(ti0->tmi.whichTMU,ti0->tmi.tm[ti0->tmi.whichTMU]->startAddress,
+ GR_MIPMAPLEVELMASK_BOTH,&(ti0->info));
+
+ grTexClampMode(ti1->tmi.whichTMU,ti1->sClamp,ti1->tClamp);
+ grTexFilterMode(ti1->tmi.whichTMU,ti1->minFilt,ti1->maxFilt);
+ grTexMipMapMode(ti1->tmi.whichTMU,ti1->mmMode,FXFALSE);
+ grTexSource(ti1->tmi.whichTMU,ti1->tmi.tm[ti1->tmi.whichTMU]->startAddress,
+ GR_MIPMAPLEVELMASK_BOTH,&(ti1->info));
+
+#undef T0_NOT_IN_TMU
+#undef T1_NOT_IN_TMU
+#undef T0_IN_TMU0
+#undef T1_IN_TMU0
+#undef T0_IN_TMU1
+#undef T1_IN_TMU1
+}
+
+static void fxSetupTextureDoubleTMU(GLcontext *ctx)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GrCombineLocal_t localc,locala;
+ tfxTexInfo *ti0,*ti1;
+ struct gl_texture_object *tObj0=ctx->Texture.Unit[0].CurrentD[2];
+ struct gl_texture_object *tObj1=ctx->Texture.Unit[1].CurrentD[2];
+ GLuint envmode,ifmt,unitsmode;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxSetupTextureDoubleTMU(...) Start\n");
+ }
+
+ ti0=(tfxTexInfo *)tObj0->DriverData;
+ fxTexValidate(ctx,tObj0);
+
+ ti1=(tfxTexInfo *)tObj1->DriverData;
+ fxTexValidate(ctx,tObj1);
+
+ fxSetupDoubleTMU(fxMesa,tObj0,tObj1);
+
+ unitsmode=fxGetTexSetConfiguration(ctx,tObj0,tObj1);
+
+ if(fxMesa->lastUnitsMode==unitsmode)
+ return;
+
+ fxMesa->lastUnitsMode=unitsmode;
+
+ fxMesa->stw_hint_state |= GR_STWHINT_ST_DIFF_TMU1;
+ FX_grHints(GR_HINT_STWHINT, fxMesa->stw_hint_state);
+
+ envmode=unitsmode & FX_UM_E_ENVMODE;
+ ifmt=unitsmode & FX_UM_E_IFMT;
+
+ if(unitsmode & FX_UM_ALPHA_ITERATED)
+ locala=GR_COMBINE_LOCAL_ITERATED;
+ else
+ locala=GR_COMBINE_LOCAL_CONSTANT;
+
+ if(unitsmode & FX_UM_COLOR_ITERATED)
+ localc=GR_COMBINE_LOCAL_ITERATED;
+ else
+ localc=GR_COMBINE_LOCAL_CONSTANT;
+
+
+ if (MESA_VERBOSE & (VERBOSE_DRIVER|VERBOSE_TEXTURE))
+ fprintf(stderr, "fxMesa: fxSetupTextureDoubleTMU, envmode is %s/%s\n",
+ gl_lookup_enum_by_nr(ctx->Texture.Unit[0].EnvMode),
+ gl_lookup_enum_by_nr(ctx->Texture.Unit[1].EnvMode));
+
+
+ fxMesa->tmuSrc=FX_TMU_BOTH;
+ switch(envmode) {
+ case (FX_UM_E0_MODULATE | FX_UM_E1_MODULATE):
+ {
+ GLboolean isalpha[FX_NUM_TMU];
+
+ if(ti0->baseLevelInternalFormat==GL_ALPHA)
+ isalpha[ti0->tmi.whichTMU]=GL_TRUE;
+ else
+ isalpha[ti0->tmi.whichTMU]=GL_FALSE;
+
+ if(ti1->baseLevelInternalFormat==GL_ALPHA)
+ isalpha[ti1->tmi.whichTMU]=GL_TRUE;
+ else
+ isalpha[ti1->tmi.whichTMU]=GL_FALSE;
+
+ if(isalpha[FX_TMU1])
+ grTexCombine(GR_TMU1,
+ GR_COMBINE_FUNCTION_ZERO,GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ FXTRUE,FXFALSE);
+ else
+ grTexCombine(GR_TMU1,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ FXFALSE,FXFALSE);
+
+ if(isalpha[FX_TMU0])
+ grTexCombine(GR_TMU0,
+ GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_ONE,
+ GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL,
+ FXFALSE,FXFALSE);
+ else
+ grTexCombine(GR_TMU0,
+ GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL,
+ GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL,
+ FXFALSE,FXFALSE);
+
+ grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,
+ GR_COMBINE_FACTOR_LOCAL,
+ localc,
+ GR_COMBINE_OTHER_TEXTURE,
+ FXFALSE);
+
+ grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,
+ GR_COMBINE_FACTOR_LOCAL,
+ locala,
+ GR_COMBINE_OTHER_TEXTURE,
+ FXFALSE);
+ break;
+ }
+ case (FX_UM_E0_REPLACE | FX_UM_E1_BLEND): /* Only for GLQuake */
+ if(ti1->tmi.whichTMU==FX_TMU1) {
+ grTexCombine(GR_TMU1,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ FXTRUE,FXFALSE);
+
+ grTexCombine(GR_TMU0,
+ GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL,
+ GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL,
+ FXFALSE,FXFALSE);
+ } else {
+ grTexCombine(GR_TMU1,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ FXFALSE,FXFALSE);
+
+ grTexCombine(GR_TMU0,
+ GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_ONE_MINUS_LOCAL,
+ GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_ONE_MINUS_LOCAL,
+ FXFALSE,FXFALSE);
+ }
+
+ grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ locala,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+
+ grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,
+ GR_COMBINE_FACTOR_ONE,
+ localc,
+ GR_COMBINE_OTHER_TEXTURE,
+ FXFALSE);
+ break;
+ case (FX_UM_E0_REPLACE | FX_UM_E1_MODULATE): /* Quake 2 and 3 */
+ if(ti1->tmi.whichTMU==FX_TMU1) {
+ grTexCombine(GR_TMU1,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_FUNCTION_ZERO,GR_COMBINE_FACTOR_NONE,
+ FXFALSE,FXTRUE);
+
+ grTexCombine(GR_TMU0,
+ GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL,
+ GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL,
+ FXFALSE,FXFALSE);
+
+ } else {
+ grTexCombine(GR_TMU1,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ GR_COMBINE_FUNCTION_LOCAL,GR_COMBINE_FACTOR_NONE,
+ FXFALSE,FXFALSE);
+
+ grTexCombine(GR_TMU0,
+ GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_LOCAL,
+ GR_COMBINE_FUNCTION_BLEND_OTHER,GR_COMBINE_FACTOR_ONE,
+ FXFALSE,FXFALSE);
+ }
+
+ if(ti0->baseLevelInternalFormat==GL_RGB)
+ grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ locala,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+ else
+ grAlphaCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,
+ GR_COMBINE_FACTOR_ONE,
+ locala,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+
+
+ grColorCombine(GR_COMBINE_FUNCTION_SCALE_OTHER,
+ GR_COMBINE_FACTOR_ONE,
+ localc,
+ GR_COMBINE_OTHER_TEXTURE,
+ FXFALSE);
+ break;
+ }
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxSetupTextureDoubleTMU(...) End\n");
+ }
+}
+
+/************************* No Texture ***************************/
+
+static void fxSetupTextureNone(GLcontext *ctx)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GrCombineLocal_t localc,locala;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxSetupTextureNone(...)\n");
+ }
+
+ if((ctx->Light.ShadeModel==GL_SMOOTH) ||
+ (ctx->Point.SmoothFlag) ||
+ (ctx->Line.SmoothFlag) ||
+ (ctx->Polygon.SmoothFlag))
+ locala=GR_COMBINE_LOCAL_ITERATED;
+ else
+ locala=GR_COMBINE_LOCAL_CONSTANT;
+
+ if(ctx->Light.ShadeModel==GL_SMOOTH)
+ localc=GR_COMBINE_LOCAL_ITERATED;
+ else
+ localc=GR_COMBINE_LOCAL_CONSTANT;
+
+ grAlphaCombine(GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ locala,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+
+ grColorCombine(GR_COMBINE_FUNCTION_LOCAL,
+ GR_COMBINE_FACTOR_NONE,
+ localc,
+ GR_COMBINE_OTHER_NONE,
+ FXFALSE);
+
+ fxMesa->lastUnitsMode=FX_UM_NONE;
+}
+
+/* See below.
+ */
+static GLboolean fxMultipassTexture( struct vertex_buffer *, GLuint );
+
+
+
+/************************************************************************/
+/************************** Texture Mode SetUp **************************/
+/************************************************************************/
+
+void fxSetupTexture(GLcontext *ctx)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLuint tex2Denabled;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxSetupTexture(...)\n");
+ }
+
+ /* Disable multipass texturing.
+ */
+ ctx->Driver.MultipassFunc = 0;
+
+ /* Texture Combine, Color Combine and Alpha Combine.
+ */
+ tex2Denabled = (ctx->Texture.ReallyEnabled & TEXTURE0_2D);
+
+ if (fxMesa->emulateTwoTMUs)
+ tex2Denabled |= (ctx->Texture.ReallyEnabled & TEXTURE1_2D);
+
+ switch(tex2Denabled) {
+ case TEXTURE0_2D:
+ fxSetupTextureSingleTMU(ctx,0);
+ break;
+ case TEXTURE1_2D:
+ fxSetupTextureSingleTMU(ctx,1);
+ break;
+ case (TEXTURE0_2D|TEXTURE1_2D):
+ if (fxMesa->haveTwoTMUs)
+ fxSetupTextureDoubleTMU(ctx);
+ else {
+ if (MESA_VERBOSE&VERBOSE_DRIVER)
+ fprintf(stderr, "fxmesa: enabling fake multitexture\n");
+
+ fxSetupTextureSingleTMU(ctx,0);
+ ctx->Driver.MultipassFunc = fxMultipassTexture;
+ }
+ break;
+ default:
+ fxSetupTextureNone(ctx);
+ break;
+ }
+}
+
+/************************************************************************/
+/**************************** Blend SetUp *******************************/
+/************************************************************************/
+
+/* XXX consider supporting GL_INGR_blend_func_separate */
+void fxDDBlendFunc(GLcontext *ctx, GLenum sfactor, GLenum dfactor)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxUnitsState *us=&fxMesa->unitsState;
+ GrAlphaBlendFnc_t sfact,dfact,asfact,adfact;
+
+ /* From the Glide documentation:
+ For alpha source and destination blend function factor
+ parameters, Voodoo Graphics supports only
+ GR_BLEND_ZERO and GR_BLEND_ONE.
+ */
+
+ switch(sfactor) {
+ case GL_ZERO:
+ asfact=sfact=GR_BLEND_ZERO;
+ break;
+ case GL_ONE:
+ asfact=sfact=GR_BLEND_ONE;
+ break;
+ case GL_DST_COLOR:
+ sfact=GR_BLEND_DST_COLOR;
+ asfact=GR_BLEND_ONE;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ sfact=GR_BLEND_ONE_MINUS_DST_COLOR;
+ asfact=GR_BLEND_ONE;
+ break;
+ case GL_SRC_ALPHA:
+ sfact=GR_BLEND_SRC_ALPHA;
+ asfact=GR_BLEND_ONE;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ sfact=GR_BLEND_ONE_MINUS_SRC_ALPHA;
+ asfact=GR_BLEND_ONE;
+ break;
+ case GL_DST_ALPHA:
+ sfact=GR_BLEND_DST_ALPHA;
+ asfact=GR_BLEND_ONE;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ sfact=GR_BLEND_ONE_MINUS_DST_ALPHA;
+ asfact=GR_BLEND_ONE;
+ break;
+ case GL_SRC_ALPHA_SATURATE:
+ sfact=GR_BLEND_ALPHA_SATURATE;
+ asfact=GR_BLEND_ONE;
+ break;
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ /* USELESS */
+ asfact=sfact=GR_BLEND_ONE;
+ break;
+ default:
+ asfact=sfact=GR_BLEND_ONE;
+ break;
+ }
+
+ if((sfact!=us->blendSrcFuncRGB) ||
+ (asfact!=us->blendSrcFuncAlpha)) {
+ us->blendSrcFuncRGB=sfact;
+ us->blendSrcFuncAlpha=asfact;
+ fxMesa->new_state |= FX_NEW_BLEND;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ }
+
+ switch(dfactor) {
+ case GL_ZERO:
+ adfact=dfact=GR_BLEND_ZERO;
+ break;
+ case GL_ONE:
+ adfact=dfact=GR_BLEND_ONE;
+ break;
+ case GL_SRC_COLOR:
+ dfact=GR_BLEND_SRC_COLOR;
+ adfact=GR_BLEND_ZERO;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ dfact=GR_BLEND_ONE_MINUS_SRC_COLOR;
+ adfact=GR_BLEND_ZERO;
+ break;
+ case GL_SRC_ALPHA:
+ dfact=GR_BLEND_SRC_ALPHA;
+ adfact=GR_BLEND_ZERO;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ dfact=GR_BLEND_ONE_MINUS_SRC_ALPHA;
+ adfact=GR_BLEND_ZERO;
+ break;
+ case GL_DST_ALPHA:
+ dfact=GR_BLEND_DST_ALPHA;
+ adfact=GR_BLEND_ZERO;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ dfact=GR_BLEND_ONE_MINUS_DST_ALPHA;
+ adfact=GR_BLEND_ZERO;
+ break;
+ case GL_SRC_ALPHA_SATURATE:
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ /* USELESS */
+ adfact=dfact=GR_BLEND_ZERO;
+ break;
+ default:
+ adfact=dfact=GR_BLEND_ZERO;
+ break;
+ }
+
+ if((dfact!=us->blendDstFuncRGB) ||
+ (adfact!=us->blendDstFuncAlpha)) {
+ us->blendDstFuncRGB=dfact;
+ us->blendDstFuncAlpha=adfact;
+ fxMesa->new_state |= FX_NEW_BLEND;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ }
+}
+
+void fxSetupBlend(GLcontext *ctx)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxUnitsState *us=&fxMesa->unitsState;
+
+ if(us->blendEnabled)
+ grAlphaBlendFunction(us->blendSrcFuncRGB,us->blendDstFuncRGB,
+ us->blendSrcFuncAlpha,us->blendDstFuncAlpha);
+ else
+ grAlphaBlendFunction(GR_BLEND_ONE,GR_BLEND_ZERO,GR_BLEND_ONE,GR_BLEND_ZERO);
+}
+
+/************************************************************************/
+/************************** Alpha Test SetUp ****************************/
+/************************************************************************/
+
+void fxDDAlphaFunc(GLcontext *ctx, GLenum func, GLclampf ref)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxUnitsState *us=&fxMesa->unitsState;
+ GrCmpFnc_t newfunc;
+
+ switch(func) {
+ case GL_NEVER:
+ newfunc=GR_CMP_NEVER;
+ break;
+ case GL_LESS:
+ newfunc=GR_CMP_LESS;
+ break;
+ case GL_EQUAL:
+ newfunc=GR_CMP_EQUAL;
+ break;
+ case GL_LEQUAL:
+ newfunc=GR_CMP_LEQUAL;
+ break;
+ case GL_GREATER:
+ newfunc=GR_CMP_GREATER;
+ break;
+ case GL_NOTEQUAL:
+ newfunc=GR_CMP_NOTEQUAL;
+ break;
+ case GL_GEQUAL:
+ newfunc=GR_CMP_GEQUAL;
+ break;
+ case GL_ALWAYS:
+ newfunc=GR_CMP_ALWAYS;
+ break;
+ default:
+ fprintf(stderr,"fx Driver: internal error in fxDDAlphaFunc()\n");
+ fxCloseHardware();
+ exit(-1);
+ break;
+ }
+
+ if(newfunc!=us->alphaTestFunc) {
+ us->alphaTestFunc=newfunc;
+ fxMesa->new_state |= FX_NEW_ALPHA;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ }
+
+ if(ctx->Color.AlphaRef!=us->alphaTestRefValue) {
+ us->alphaTestRefValue=ctx->Color.AlphaRef;
+ fxMesa->new_state |= FX_NEW_ALPHA;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ }
+}
+
+static void fxSetupAlphaTest(GLcontext *ctx)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxUnitsState *us=&fxMesa->unitsState;
+
+ if(us->alphaTestEnabled) {
+ grAlphaTestFunction(us->alphaTestFunc);
+ grAlphaTestReferenceValue(us->alphaTestRefValue);
+ } else
+ grAlphaTestFunction(GR_CMP_ALWAYS);
+}
+
+/************************************************************************/
+/************************** Depth Test SetUp ****************************/
+/************************************************************************/
+
+void fxDDDepthFunc(GLcontext *ctx, GLenum func)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxUnitsState *us=&fxMesa->unitsState;
+ GrCmpFnc_t dfunc;
+
+ switch(func) {
+ case GL_NEVER:
+ dfunc=GR_CMP_NEVER;
+ break;
+ case GL_LESS:
+ dfunc=GR_CMP_LESS;
+ break;
+ case GL_GEQUAL:
+ dfunc=GR_CMP_GEQUAL;
+ break;
+ case GL_LEQUAL:
+ dfunc=GR_CMP_LEQUAL;
+ break;
+ case GL_GREATER:
+ dfunc=GR_CMP_GREATER;
+ break;
+ case GL_NOTEQUAL:
+ dfunc=GR_CMP_NOTEQUAL;
+ break;
+ case GL_EQUAL:
+ dfunc=GR_CMP_EQUAL;
+ break;
+ case GL_ALWAYS:
+ dfunc=GR_CMP_ALWAYS;
+ break;
+ default:
+ fprintf(stderr,"fx Driver: internal error in fxDDDepthFunc()\n");
+ fxCloseHardware();
+ exit(-1);
+ break;
+ }
+
+ if(dfunc!=us->depthTestFunc) {
+ us->depthTestFunc=dfunc;
+ fxMesa->new_state |= FX_NEW_DEPTH;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ }
+
+}
+
+void fxDDDepthMask(GLcontext *ctx, GLboolean flag)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxUnitsState *us=&fxMesa->unitsState;
+
+ if(flag!=us->depthMask) {
+ us->depthMask=flag;
+ fxMesa->new_state |= FX_NEW_DEPTH;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ }
+}
+
+void fxSetupDepthTest(GLcontext *ctx)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxUnitsState *us=&fxMesa->unitsState;
+
+ if(us->depthTestEnabled)
+ grDepthBufferFunction(us->depthTestFunc);
+ else
+ grDepthBufferFunction(GR_CMP_ALWAYS);
+
+ grDepthMask(us->depthMask);
+}
+
+/************************************************************************/
+/**************************** Color Mask SetUp **************************/
+/************************************************************************/
+
+GLboolean fxDDColorMask(GLcontext *ctx,
+ GLboolean r, GLboolean g,
+ GLboolean b, GLboolean a )
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ fxMesa->new_state |= FX_NEW_COLOR_MASK;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ (void) r; (void) g; (void) b; (void) a;
+ return 1;
+}
+
+static void fxSetupColorMask(GLcontext *ctx)
+{
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+ grColorMask(ctx->Color.ColorMask[RCOMP] ||
+ ctx->Color.ColorMask[GCOMP] ||
+ ctx->Color.ColorMask[BCOMP],
+ ctx->Color.ColorMask[ACOMP] && fxMesa->haveAlphaBuffer);
+}
+
+
+
+/************************************************************************/
+/**************************** Fog Mode SetUp ****************************/
+/************************************************************************/
+
+void fxFogTableGenerate(GLcontext *ctx)
+{
+ int i;
+ float f,eyez;
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+
+ for(i=0;i<FX_grGetInteger(FX_FOG_TABLE_ENTRIES);i++) {
+ eyez=guFogTableIndexToW(i);
+
+ switch(ctx->Fog.Mode) {
+ case GL_LINEAR:
+ f=(ctx->Fog.End-eyez)/(ctx->Fog.End-ctx->Fog.Start);
+ break;
+ case GL_EXP:
+ f=exp(-ctx->Fog.Density*eyez);
+ break;
+ case GL_EXP2:
+ f=exp(-ctx->Fog.Density*ctx->Fog.Density*eyez*eyez);
+ break;
+ default: /* That should never happen */
+ f=0.0f;
+ break;
+ }
+
+ fxMesa->fogTable[i]=(GrFog_t)((1.0f-CLAMP(f,0.0f,1.0f))*255.0f);
+ }
+}
+
+void fxSetupFog(GLcontext *ctx, GLboolean forceTableRebuild)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+
+ if(ctx->Fog.Enabled && ctx->FogMode==FOG_FRAGMENT) {
+ GLubyte col[4];
+ grFogMode(GR_FOG_WITH_TABLE);
+
+ col[0]=(unsigned int)(255*ctx->Fog.Color[0]);
+ col[1]=(unsigned int)(255*ctx->Fog.Color[1]);
+ col[2]=(unsigned int)(255*ctx->Fog.Color[2]);
+ col[3]=(unsigned int)(255*ctx->Fog.Color[3]);
+
+ grFogColorValue(FXCOLOR4(col));
+
+ if(forceTableRebuild ||
+ (fxMesa->fogTableMode!=ctx->Fog.Mode) ||
+ (fxMesa->fogDensity!=ctx->Fog.Density)) {
+ fxFogTableGenerate(ctx);
+
+ fxMesa->fogTableMode=ctx->Fog.Mode;
+ fxMesa->fogDensity=ctx->Fog.Density;
+ }
+
+ grFogTable(fxMesa->fogTable);
+ } else
+ grFogMode(GR_FOG_DISABLE);
+}
+
+void fxDDFogfv( GLcontext *ctx, GLenum pname, const GLfloat *params )
+{
+ FX_CONTEXT(ctx)->new_state |= FX_NEW_FOG;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+}
+
+/************************************************************************/
+/************************** Scissor Test SetUp **************************/
+/************************************************************************/
+
+static void fxSetupScissor(GLcontext *ctx)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+
+ if (ctx->Scissor.Enabled) {
+ int ymin, ymax;
+
+ ymin=ctx->Scissor.Y;
+ ymax=ctx->Scissor.Y+ctx->Scissor.Height;
+
+ if (ymin<0) ymin=0;
+
+ if (ymax>fxMesa->height) ymax=fxMesa->height;
+
+ grClipWindow(ctx->Scissor.X,
+ ymin,
+ ctx->Scissor.X+ctx->Scissor.Width,
+ ymax);
+ } else
+ grClipWindow(0,0,fxMesa->width,fxMesa->height);
+}
+
+void fxDDScissor( GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h )
+{
+ FX_CONTEXT(ctx)->new_state |= FX_NEW_SCISSOR;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+}
+
+/************************************************************************/
+/*************************** Cull mode setup ****************************/
+/************************************************************************/
+
+
+void fxDDCullFace(GLcontext *ctx, GLenum mode)
+{
+ (void) mode;
+ FX_CONTEXT(ctx)->new_state |= FX_NEW_CULL;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+}
+
+void fxDDFrontFace(GLcontext *ctx, GLenum mode)
+{
+ (void) mode;
+ FX_CONTEXT(ctx)->new_state |= FX_NEW_CULL;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+}
+
+
+void fxSetupCull(GLcontext *ctx)
+{
+ if(ctx->Polygon.CullFlag) {
+ switch(ctx->Polygon.CullFaceMode) {
+ case GL_BACK:
+ if(ctx->Polygon.FrontFace==GL_CCW)
+ grCullMode(GR_CULL_NEGATIVE);
+ else
+ grCullMode(GR_CULL_POSITIVE);
+ break;
+ case GL_FRONT:
+ if(ctx->Polygon.FrontFace==GL_CCW)
+ grCullMode(GR_CULL_POSITIVE);
+ else
+ grCullMode(GR_CULL_NEGATIVE);
+ break;
+ case GL_FRONT_AND_BACK:
+ grCullMode(GR_CULL_DISABLE);
+ break;
+ default:
+ break;
+ }
+ } else
+ grCullMode(GR_CULL_DISABLE);
+}
+
+
+/************************************************************************/
+/****************************** DD Enable ******************************/
+/************************************************************************/
+
+void fxDDEnable(GLcontext *ctx, GLenum cap, GLboolean state)
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ tfxUnitsState *us=&fxMesa->unitsState;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxDDEnable(...)\n");
+ }
+
+ switch(cap) {
+ case GL_ALPHA_TEST:
+ if(state!=us->alphaTestEnabled) {
+ us->alphaTestEnabled=state;
+ fxMesa->new_state |= FX_NEW_ALPHA;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ }
+ break;
+ case GL_BLEND:
+ if(state!=us->blendEnabled) {
+ us->blendEnabled=state;
+ fxMesa->new_state |= FX_NEW_BLEND;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ }
+ break;
+ case GL_DEPTH_TEST:
+ if(state!=us->depthTestEnabled) {
+ us->depthTestEnabled=state;
+ fxMesa->new_state |= FX_NEW_DEPTH;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ }
+ break;
+ case GL_SCISSOR_TEST:
+ fxMesa->new_state |= FX_NEW_SCISSOR;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ break;
+ case GL_FOG:
+ fxMesa->new_state |= FX_NEW_FOG;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ break;
+ case GL_CULL_FACE:
+ fxMesa->new_state |= FX_NEW_CULL;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ break;
+ case GL_LINE_SMOOTH:
+ case GL_POINT_SMOOTH:
+ case GL_POLYGON_SMOOTH:
+ case GL_TEXTURE_2D:
+ fxMesa->new_state |= FX_NEW_TEXTURING;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+ break;
+ default:
+ ; /* XXX no-op??? */
+ }
+}
+
+/************************************************************************/
+/******************** Fake Multitexture Support *************************/
+/************************************************************************/
+
+/* Its considered cheeky to try to fake ARB multitexture by doing
+ * multipass rendering, because it is not possible to emulate the full
+ * spec in this way. The fact is that the voodoo 2 supports only a
+ * subset of the possible multitexturing modes, and it is possible to
+ * support almost the same subset using multipass blending on the
+ * voodoo 1. In all other cases for both voodoo 1 and 2, we fall back
+ * to software rendering, satisfying the spec if not the user.
+ */
+static GLboolean fxMultipassTexture( struct vertex_buffer *VB, GLuint pass )
+{
+ GLcontext *ctx = VB->ctx;
+ fxVertex *v = FX_DRIVER_DATA(VB)->verts;
+ fxVertex *last = FX_DRIVER_DATA(VB)->last_vert;
+ fxMesaContext fxMesa = FX_CONTEXT(ctx);
+
+ switch (pass) {
+ case 1:
+ if (MESA_VERBOSE&(VERBOSE_DRIVER|VERBOSE_PIPELINE|VERBOSE_TEXTURE))
+ fprintf(stderr, "fxmesa: Second texture pass\n");
+
+ for ( ; v != last ; v++) {
+ v->f[S0COORD] = v->f[S1COORD];
+ v->f[T0COORD] = v->f[T1COORD];
+ }
+
+ fxMesa->restoreUnitsState = fxMesa->unitsState;
+ fxMesa->tmu_source[0] = 1;
+
+ if (ctx->Depth.Mask) {
+ switch (ctx->Depth.Func) {
+ case GL_NEVER:
+ case GL_ALWAYS:
+ break;
+ default:
+ fxDDDepthFunc( ctx, GL_EQUAL );
+ break;
+ }
+
+ fxDDDepthMask( ctx, GL_FALSE );
+ }
+
+ if (ctx->Texture.Unit[1].EnvMode == GL_MODULATE) {
+ fxDDEnable( ctx, GL_BLEND, GL_TRUE );
+ fxDDBlendFunc( ctx, GL_DST_COLOR, GL_ZERO );
+ }
+
+ fxSetupTextureSingleTMU( ctx, 1 );
+ fxSetupBlend( ctx );
+ fxSetupDepthTest( ctx );
+ break;
+
+ case 2:
+ /* Restore original state.
+ */
+ fxMesa->tmu_source[0] = 0;
+ fxMesa->unitsState = fxMesa->restoreUnitsState;
+ fxMesa->setupdone &= ~SETUP_TMU0;
+ fxSetupTextureSingleTMU( ctx, 0 );
+ fxSetupBlend( ctx );
+ fxSetupDepthTest( ctx );
+ break;
+ }
+
+ return pass == 1;
+}
+
+
+/************************************************************************/
+/************************** Changes to units state **********************/
+/************************************************************************/
+
+
+/* All units setup is handled under texture setup.
+ */
+void fxDDShadeModel(GLcontext *ctx, GLenum mode)
+{
+ FX_CONTEXT(ctx)->new_state |= FX_NEW_TEXTURING;
+ ctx->Driver.RenderStart = fxSetupFXUnits;
+}
+
+
+
+/************************************************************************/
+/****************************** Units SetUp *****************************/
+/************************************************************************/
+void gl_print_fx_state_flags( const char *msg, GLuint flags )
+{
+ fprintf(stderr,
+ "%s: (0x%x) %s%s%s%s%s%s%s\n",
+ msg,
+ flags,
+ (flags & FX_NEW_TEXTURING) ? "texture, " : "",
+ (flags & FX_NEW_BLEND) ? "blend, " : "",
+ (flags & FX_NEW_ALPHA) ? "alpha, " : "",
+ (flags & FX_NEW_FOG) ? "fog, " : "",
+ (flags & FX_NEW_SCISSOR) ? "scissor, " : "",
+ (flags & FX_NEW_COLOR_MASK) ? "colormask, " : "",
+ (flags & FX_NEW_CULL) ? "cull, " : "");
+}
+
+void fxSetupFXUnits( GLcontext *ctx )
+{
+ fxMesaContext fxMesa=(fxMesaContext)ctx->DriverCtx;
+ GLuint newstate = fxMesa->new_state;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER)
+ gl_print_fx_state_flags("fxmesa: fxSetupFXUnits", newstate);
+
+ if (newstate) {
+ if (newstate & FX_NEW_TEXTURING)
+ fxSetupTexture(ctx);
+
+ if (newstate & FX_NEW_BLEND)
+ fxSetupBlend(ctx);
+
+ if (newstate & FX_NEW_ALPHA)
+ fxSetupAlphaTest(ctx);
+
+ if (newstate & FX_NEW_DEPTH)
+ fxSetupDepthTest(ctx);
+
+ if (newstate & FX_NEW_FOG)
+ fxSetupFog(ctx,GL_FALSE);
+
+ if (newstate & FX_NEW_SCISSOR)
+ fxSetupScissor(ctx);
+
+ if (newstate & FX_NEW_COLOR_MASK)
+ fxSetupColorMask(ctx);
+
+ if (newstate & FX_NEW_CULL)
+ fxSetupCull(ctx);
+
+ fxMesa->new_state = 0;
+ ctx->Driver.RenderStart = 0;
+ }
+}
+
+
+
+#else
+
+
+/*
+ * Need this to provide at least one external definition.
+ */
+
+int gl_fx_dummy_function_setup(void)
+{
+ return 0;
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/fxtexman.c b/src/mesa/drivers/glide/fxtexman.c
new file mode 100644
index 0000000000..5ee145e3cb
--- /dev/null
+++ b/src/mesa/drivers/glide/fxtexman.c
@@ -0,0 +1,579 @@
+/* -*- mode: C; tab-width:8; -*-
+
+ fxtexman.c - 3Dfx VooDoo texture memory functions
+*/
+
+/*
+ * 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.
+ *
+ * See the file fxapi.c for more informations about authors
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#if defined(FX)
+
+#include "fxdrv.h"
+
+static tfxTMFreeNode *fxTMNewTMFreeNode(FxU32 start, FxU32 end)
+{
+ tfxTMFreeNode *tmn;
+
+ if(!(tmn=malloc(sizeof(tfxTMFreeNode)))) {
+ fprintf(stderr,"fx Driver: out of memory !\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ tmn->next=NULL;
+ tmn->startAddress=start;
+ tmn->endAddress=end;
+
+ return tmn;
+}
+
+static void fxTMUInit(fxMesaContext fxMesa, int tmu)
+{
+ tfxTMFreeNode *tmn,*tmntmp;
+ FxU32 start,end,blockstart,blockend;
+
+ start=grTexMinAddress(tmu);
+ end=grTexMaxAddress(tmu);
+
+ if(fxMesa->verbose) {
+ fprintf(stderr,"%s configuration:",(tmu==FX_TMU0) ? "TMU0" : "TMU1");
+ fprintf(stderr," Lower texture memory address (%u)\n",(unsigned int)start);
+ fprintf(stderr," Higher texture memory address (%u)\n",(unsigned int)end);
+ fprintf(stderr," Splitting Texture memory in 2Mb blocks:\n");
+ }
+
+ fxMesa->freeTexMem[tmu]=end-start;
+ fxMesa->tmFree[tmu]=NULL;
+ fxMesa->tmAlloc[tmu]=NULL;
+
+ blockstart=start;
+ while(blockstart<=end) {
+ if(blockstart+0x1fffff>end)
+ blockend=end;
+ else
+ blockend=blockstart+0x1fffff;
+
+ if(fxMesa->verbose)
+ fprintf(stderr," %07u-%07u\n",(unsigned int)blockstart,(unsigned int)blockend);
+
+ tmn=fxTMNewTMFreeNode(blockstart,blockend);
+
+ if(fxMesa->tmFree[tmu]) {
+ for(tmntmp=fxMesa->tmFree[tmu];tmntmp->next!=NULL;tmntmp=tmntmp->next){};
+ tmntmp->next=tmn;
+ } else
+ fxMesa->tmFree[tmu]=tmn;
+
+ blockstart+=0x1fffff+1;
+ }
+}
+
+void fxTMInit(fxMesaContext fxMesa)
+{
+ fxTMUInit(fxMesa,FX_TMU0);
+
+ if(fxMesa->haveTwoTMUs)
+ fxTMUInit(fxMesa,FX_TMU1);
+
+ fxMesa->texBindNumber=0;
+}
+
+static struct gl_texture_object *fxTMFindOldestTMBlock(fxMesaContext fxMesa,
+ tfxTMAllocNode *tmalloc,
+ GLuint texbindnumber)
+{
+ GLuint age,oldestage,lasttimeused;
+ struct gl_texture_object *oldesttexobj;
+
+ (void)fxMesa;
+ oldesttexobj=tmalloc->tObj;
+ oldestage=0;
+
+ while(tmalloc) {
+ lasttimeused=((tfxTexInfo *)(tmalloc->tObj->DriverData))->tmi.lastTimeUsed;
+
+ if(lasttimeused>texbindnumber)
+ age=texbindnumber+(UINT_MAX-lasttimeused+1); /* TO DO: check */
+ else
+ age=texbindnumber-lasttimeused;
+
+ if(age>=oldestage) {
+ oldestage=age;
+ oldesttexobj=tmalloc->tObj;
+ }
+
+ tmalloc=tmalloc->next;
+ }
+
+ return oldesttexobj;
+}
+
+static GLboolean fxTMFreeOldTMBlock(fxMesaContext fxMesa, GLint tmu)
+{
+ struct gl_texture_object *oldesttexobj;
+
+ if(!fxMesa->tmAlloc[tmu])
+ return GL_FALSE;
+
+ oldesttexobj=fxTMFindOldestTMBlock(fxMesa,fxMesa->tmAlloc[tmu],fxMesa->texBindNumber);
+
+ fxTMMoveOutTM(fxMesa,oldesttexobj);
+
+ return GL_TRUE;
+}
+
+static tfxTMFreeNode *fxTMExtractTMFreeBlock(tfxTMFreeNode *tmfree, int texmemsize,
+ GLboolean *success, FxU32 *startadr)
+{
+ int blocksize;
+
+ /* TO DO: cut recursion */
+
+ if(!tmfree) {
+ *success=GL_FALSE;
+ return NULL;
+ }
+
+ blocksize=(int)tmfree->endAddress-(int)tmfree->startAddress+1;
+
+ if(blocksize==texmemsize) {
+ tfxTMFreeNode *nexttmfree;
+
+ *success=GL_TRUE;
+ *startadr=tmfree->startAddress;
+
+ nexttmfree=tmfree->next;
+ free(tmfree);
+
+ return nexttmfree;
+ }
+
+ if(blocksize>texmemsize) {
+ *success=GL_TRUE;
+ *startadr=tmfree->startAddress;
+
+ tmfree->startAddress+=texmemsize;
+
+ return tmfree;
+ }
+
+ tmfree->next=fxTMExtractTMFreeBlock(tmfree->next,texmemsize,success,startadr);
+
+ return tmfree;
+}
+
+static tfxTMAllocNode *fxTMGetTMBlock(fxMesaContext fxMesa, struct gl_texture_object *tObj,
+ GLint tmu, int texmemsize)
+{
+ tfxTMFreeNode *newtmfree;
+ tfxTMAllocNode *newtmalloc;
+ GLboolean success;
+ FxU32 startadr;
+
+ for(;;) { /* TO DO: improve performaces */
+ newtmfree=fxTMExtractTMFreeBlock(fxMesa->tmFree[tmu],texmemsize,&success,&startadr);
+
+ if(success) {
+ fxMesa->tmFree[tmu]=newtmfree;
+
+ fxMesa->freeTexMem[tmu]-=texmemsize;
+
+ if(!(newtmalloc=malloc(sizeof(tfxTMAllocNode)))) {
+ fprintf(stderr,"fx Driver: out of memory !\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ newtmalloc->next=fxMesa->tmAlloc[tmu];
+ newtmalloc->startAddress=startadr;
+ newtmalloc->endAddress=startadr+texmemsize-1;
+ newtmalloc->tObj=tObj;
+
+ fxMesa->tmAlloc[tmu]=newtmalloc;
+
+ return newtmalloc;
+ }
+
+ if(!fxTMFreeOldTMBlock(fxMesa,tmu)) {
+ fprintf(stderr,"fx Driver: internal error in fxTMGetTMBlock()\n");
+ fprintf(stderr," TMU: %d Size: %d\n",tmu,texmemsize);
+
+ fxCloseHardware();
+ exit(-1);
+ }
+ }
+}
+
+void fxTMMoveInTM(fxMesaContext fxMesa, struct gl_texture_object *tObj, GLint where)
+{
+ tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData;
+ int i,l;
+ int texmemsize;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxTMMoveInTM(%d)\n",tObj->Name);
+ }
+
+ fxMesa->stats.reqTexUpload++;
+
+ if(!ti->validated) {
+ fprintf(stderr,"fx Driver: internal error in fxTMMoveInTM() -> not validated\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ if(ti->tmi.isInTM)
+ return;
+
+ if (MESA_VERBOSE&(VERBOSE_DRIVER|VERBOSE_TEXTURE)) {
+ fprintf(stderr,"fxmesa: downloading %x (%d) in texture memory in %d\n",(GLuint)tObj,tObj->Name,where);
+ }
+
+ ti->tmi.whichTMU=(FxU32)where;
+
+ switch(where) {
+ case FX_TMU0:
+ case FX_TMU1:
+ texmemsize=(int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_BOTH,&(ti->info));
+ ti->tmi.tm[where]=fxTMGetTMBlock(fxMesa,tObj,where,texmemsize);
+ fxMesa->stats.memTexUpload+=texmemsize;
+
+ for(i=FX_largeLodValue(ti->info),l=ti->minLevel;i<=FX_smallLodValue(ti->info);i++,l++)
+ grTexDownloadMipMapLevel(where,
+ ti->tmi.tm[where]->startAddress,FX_valueToLod(i),
+ FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info),
+ ti->info.format,GR_MIPMAPLEVELMASK_BOTH,
+ ti->tmi.mipmapLevel[l].data);
+ break;
+ case FX_TMU_SPLIT: /* TO DO: alternate even/odd TMU0/TMU1 */
+ texmemsize=(int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_ODD,&(ti->info));
+ ti->tmi.tm[FX_TMU0]=fxTMGetTMBlock(fxMesa,tObj,FX_TMU0,texmemsize);
+ fxMesa->stats.memTexUpload+=texmemsize;
+
+ texmemsize=(int)grTexTextureMemRequired(GR_MIPMAPLEVELMASK_EVEN,&(ti->info));
+ ti->tmi.tm[FX_TMU1]=fxTMGetTMBlock(fxMesa,tObj,FX_TMU1,texmemsize);
+ fxMesa->stats.memTexUpload+=texmemsize;
+
+ for(i=FX_largeLodValue(ti->info),l=ti->minLevel;i<=FX_smallLodValue(ti->info);i++,l++) {
+ grTexDownloadMipMapLevel(GR_TMU0,ti->tmi.tm[FX_TMU0]->startAddress,FX_valueToLod(i),
+ FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info),
+ ti->info.format,GR_MIPMAPLEVELMASK_ODD,
+ ti->tmi.mipmapLevel[l].data);
+
+ grTexDownloadMipMapLevel(GR_TMU1,ti->tmi.tm[FX_TMU1]->startAddress,FX_valueToLod(i),
+ FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info),
+ ti->info.format,GR_MIPMAPLEVELMASK_EVEN,
+ ti->tmi.mipmapLevel[l].data);
+ }
+ break;
+ default:
+ fprintf(stderr,"fx Driver: internal error in fxTMMoveInTM() -> wrong tmu (%d)\n",where);
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ fxMesa->stats.texUpload++;
+
+ ti->tmi.isInTM=GL_TRUE;
+}
+
+void fxTMReloadMipMapLevel(fxMesaContext fxMesa, struct gl_texture_object *tObj, GLint level)
+{
+ tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData;
+ GrLOD_t lodlevel;
+ GLint tmu;
+
+ if(!ti->validated) {
+ fprintf(stderr,"fx Driver: internal error in fxTMReloadMipMapLevel() -> not validated\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ tmu=(int)ti->tmi.whichTMU;
+ fxTMMoveInTM(fxMesa,tObj,tmu);
+
+ fxTexGetInfo(ti->tmi.mipmapLevel[0].width,ti->tmi.mipmapLevel[0].height,
+ &lodlevel,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
+
+ switch(tmu) {
+ case FX_TMU0:
+ case FX_TMU1:
+ grTexDownloadMipMapLevel(tmu,
+ ti->tmi.tm[tmu]->startAddress,FX_valueToLod(FX_lodToValue(lodlevel)+level),
+ FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info),
+ ti->info.format,GR_MIPMAPLEVELMASK_BOTH,
+ ti->tmi.mipmapLevel[level].data);
+ break;
+ case FX_TMU_SPLIT: /* TO DO: alternate even/odd TMU0/TMU1 */
+ grTexDownloadMipMapLevel(GR_TMU0,
+ ti->tmi.tm[GR_TMU0]->startAddress,FX_valueToLod(FX_lodToValue(lodlevel)+level),
+ FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info),
+ ti->info.format,GR_MIPMAPLEVELMASK_ODD,
+ ti->tmi.mipmapLevel[level].data);
+
+ grTexDownloadMipMapLevel(GR_TMU1,
+ ti->tmi.tm[GR_TMU1]->startAddress,FX_valueToLod(FX_lodToValue(lodlevel)+level),
+ FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info),
+ ti->info.format,GR_MIPMAPLEVELMASK_EVEN,
+ ti->tmi.mipmapLevel[level].data);
+ break;
+ default:
+ fprintf(stderr,"fx Driver: internal error in fxTMReloadMipMapLevel() -> wrong tmu (%d)\n",tmu);
+ fxCloseHardware();
+ exit(-1);
+ }
+}
+
+void fxTMReloadSubMipMapLevel(fxMesaContext fxMesa, struct gl_texture_object *tObj,
+ GLint level, GLint yoffset, GLint height)
+{
+ tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData;
+ GrLOD_t lodlevel;
+ unsigned short *data;
+ GLint tmu;
+
+ if(!ti->validated) {
+ fprintf(stderr,"fx Driver: internal error in fxTMReloadSubMipMapLevel() -> not validated\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ tmu=(int)ti->tmi.whichTMU;
+ fxTMMoveInTM(fxMesa,tObj,tmu);
+
+ fxTexGetInfo(ti->tmi.mipmapLevel[0].width,ti->tmi.mipmapLevel[0].height,
+ &lodlevel,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
+
+ if((ti->info.format==GR_TEXFMT_INTENSITY_8) ||
+ (ti->info.format==GR_TEXFMT_P_8) ||
+ (ti->info.format==GR_TEXFMT_ALPHA_8))
+ data=ti->tmi.mipmapLevel[level].data+((yoffset*ti->tmi.mipmapLevel[level].width)>>1);
+ else
+ data=ti->tmi.mipmapLevel[level].data+yoffset*ti->tmi.mipmapLevel[level].width;
+
+ switch(tmu) {
+ case FX_TMU0:
+ case FX_TMU1:
+ grTexDownloadMipMapLevelPartial(tmu,
+ ti->tmi.tm[tmu]->startAddress,FX_valueToLod(FX_lodToValue(lodlevel)+level),
+ FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info),
+ ti->info.format,GR_MIPMAPLEVELMASK_BOTH,
+ data,
+ yoffset,yoffset+height-1);
+ break;
+ case FX_TMU_SPLIT: /* TO DO: alternate even/odd TMU0/TMU1 */
+ grTexDownloadMipMapLevelPartial(GR_TMU0,
+ ti->tmi.tm[FX_TMU0]->startAddress,FX_valueToLod(FX_lodToValue(lodlevel)+level),
+ FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info),
+ ti->info.format,GR_MIPMAPLEVELMASK_ODD,
+ data,
+ yoffset,yoffset+height-1);
+
+ grTexDownloadMipMapLevelPartial(GR_TMU1,
+ ti->tmi.tm[FX_TMU1]->startAddress,FX_valueToLod(FX_lodToValue(lodlevel)+level),
+ FX_largeLodLog2(ti->info),FX_aspectRatioLog2(ti->info),
+ ti->info.format,GR_MIPMAPLEVELMASK_EVEN,
+ data,
+ yoffset,yoffset+height-1);
+ break;
+ default:
+ fprintf(stderr,"fx Driver: internal error in fxTMReloadSubMipMapLevel() -> wrong tmu (%d)\n",tmu);
+ fxCloseHardware();
+ exit(-1);
+ }
+}
+
+static tfxTMAllocNode *fxTMFreeTMAllocBlock(tfxTMAllocNode *tmalloc,
+ tfxTMAllocNode *tmunalloc)
+{
+ if(!tmalloc)
+ return NULL;
+
+ if(tmalloc==tmunalloc) {
+ tfxTMAllocNode *newtmalloc;
+
+ newtmalloc=tmalloc->next;
+ free(tmalloc);
+
+ return newtmalloc;
+ }
+
+ tmalloc->next=fxTMFreeTMAllocBlock(tmalloc->next,tmunalloc);
+
+ return tmalloc;
+}
+
+static tfxTMFreeNode *fxTMAddTMFree(tfxTMFreeNode *tmfree, FxU32 startadr, FxU32 endadr)
+{
+ if(!tmfree)
+ return fxTMNewTMFreeNode(startadr,endadr);
+
+ if((endadr+1==tmfree->startAddress) && (tmfree->startAddress & 0x1fffff)) {
+ tmfree->startAddress=startadr;
+
+ return tmfree;
+ }
+
+ if((startadr-1==tmfree->endAddress) && (startadr & 0x1fffff)) {
+ tmfree->endAddress=endadr;
+
+ if((tmfree->next && (endadr+1==tmfree->next->startAddress) &&
+ (tmfree->next->startAddress & 0x1fffff))) {
+ tfxTMFreeNode *nexttmfree;
+
+ tmfree->endAddress=tmfree->next->endAddress;
+
+ nexttmfree=tmfree->next->next;
+ free(tmfree->next);
+
+ tmfree->next=nexttmfree;
+ }
+
+
+ return tmfree;
+ }
+
+ if(startadr<tmfree->startAddress) {
+ tfxTMFreeNode *newtmfree;
+
+ newtmfree=fxTMNewTMFreeNode(startadr,endadr);
+ newtmfree->next=tmfree;
+
+ return newtmfree;
+ }
+
+ tmfree->next=fxTMAddTMFree(tmfree->next,startadr,endadr);
+
+ return tmfree;
+}
+
+static void fxTMFreeTMBlock(fxMesaContext fxMesa, GLint tmu, tfxTMAllocNode *tmalloc)
+{
+ FxU32 startadr,endadr;
+
+ startadr=tmalloc->startAddress;
+ endadr=tmalloc->endAddress;
+
+ fxMesa->tmAlloc[tmu]=fxTMFreeTMAllocBlock(fxMesa->tmAlloc[tmu],tmalloc);
+
+ fxMesa->tmFree[tmu]=fxTMAddTMFree(fxMesa->tmFree[tmu],startadr,endadr);
+
+ fxMesa->freeTexMem[tmu]+=endadr-startadr+1;
+}
+
+void fxTMMoveOutTM(fxMesaContext fxMesa, struct gl_texture_object *tObj)
+{
+ tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData;
+
+ if (MESA_VERBOSE&VERBOSE_DRIVER) {
+ fprintf(stderr,"fxmesa: fxTMMoveOutTM(%x (%d))\n",(GLuint)tObj,tObj->Name);
+ }
+
+ if(!ti->tmi.isInTM)
+ return;
+
+ switch(ti->tmi.whichTMU) {
+ case FX_TMU0:
+ case FX_TMU1:
+ fxTMFreeTMBlock(fxMesa,(int)ti->tmi.whichTMU,ti->tmi.tm[ti->tmi.whichTMU]);
+ break;
+ case FX_TMU_SPLIT:
+ fxTMFreeTMBlock(fxMesa,FX_TMU0,ti->tmi.tm[FX_TMU0]);
+ fxTMFreeTMBlock(fxMesa,FX_TMU1,ti->tmi.tm[FX_TMU1]);
+ break;
+ default:
+ fprintf(stderr,"fx Driver: internal error in fxTMMoveOutTM()\n");
+ fxCloseHardware();
+ exit(-1);
+ }
+
+ ti->tmi.whichTMU=FX_TMU_NONE;
+ ti->tmi.isInTM=GL_FALSE;
+}
+
+void fxTMFreeTexture(fxMesaContext fxMesa, struct gl_texture_object *tObj)
+{
+ tfxTexInfo *ti=(tfxTexInfo *)tObj->DriverData;
+ int i;
+
+ fxTMMoveOutTM(fxMesa,tObj);
+
+ for(i=0;i<MAX_TEXTURE_LEVELS;i++) {
+ if(ti->tmi.mipmapLevel[i].used &&
+ ti->tmi.mipmapLevel[i].translated)
+ free(ti->tmi.mipmapLevel[i].data);
+
+ (void)ti->tmi.mipmapLevel[i].data;
+ }
+}
+
+void fxTMFreeAllFreeNode(tfxTMFreeNode *fn)
+{
+ if(!fn)
+ return;
+
+ if(fn->next)
+ fxTMFreeAllFreeNode(fn->next);
+
+ free(fn);
+}
+
+void fxTMFreeAllAllocNode(tfxTMAllocNode *an)
+{
+ if(!an)
+ return;
+
+ if(an->next)
+ fxTMFreeAllAllocNode(an->next);
+
+ free(an);
+}
+
+void fxTMClose(fxMesaContext fxMesa)
+{
+ fxTMFreeAllFreeNode(fxMesa->tmFree[FX_TMU0]);
+ fxTMFreeAllAllocNode(fxMesa->tmAlloc[FX_TMU0]);
+ fxMesa->tmFree[FX_TMU0] = NULL;
+ fxMesa->tmAlloc[FX_TMU0] = NULL;
+ if(fxMesa->haveTwoTMUs) {
+ fxTMFreeAllFreeNode(fxMesa->tmFree[FX_TMU1]);
+ fxTMFreeAllAllocNode(fxMesa->tmAlloc[FX_TMU1]);
+ fxMesa->tmFree[FX_TMU1] = NULL;
+ fxMesa->tmAlloc[FX_TMU1] = NULL;
+ }
+}
+
+
+#else
+
+
+/*
+ * Need this to provide at least one external definition.
+ */
+
+int gl_fx_dummy_function_texman(void)
+{
+ return 0;
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/glide/fxwgl.c b/src/mesa/drivers/glide/fxwgl.c
new file mode 100644
index 0000000000..cbea79aecd
--- /dev/null
+++ b/src/mesa/drivers/glide/fxwgl.c
@@ -0,0 +1,806 @@
+/* fxwgl.c - Microsoft wgl functions emulation for
+ * 3Dfx VooDoo/Mesa interface
+ */
+
+/*
+ * 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.
+ *
+ * See the file fxapi.c for more informations about authors
+ *
+ */
+
+#ifdef __WIN32__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <windows.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+#ifdef __cplusplus
+ }
+#endif
+
+#include <stdio.h>
+#include <GL/fxmesa.h>
+#include "fxdrv.h"
+
+#define MAX_MESA_ATTRS 20
+
+struct __extensions__
+{
+ PROC proc;
+ char *name;
+};
+
+struct __pixelformat__
+{
+ PIXELFORMATDESCRIPTOR pfd;
+ GLint mesaAttr[MAX_MESA_ATTRS];
+};
+
+WINGDIAPI void GLAPIENTRY gl3DfxSetPaletteEXT(GLuint *);
+
+static struct __extensions__ ext[] = {
+
+#ifdef GL_EXT_polygon_offset
+ { (PROC)glPolygonOffsetEXT, "glPolygonOffsetEXT" },
+#endif
+ { (PROC)glBlendEquationEXT, "glBlendEquationEXT" },
+ { (PROC)glBlendColorEXT, "glBlendColorExt" },
+ { (PROC)glVertexPointerEXT, "glVertexPointerEXT" },
+ { (PROC)glNormalPointerEXT, "glNormalPointerEXT" },
+ { (PROC)glColorPointerEXT, "glColorPointerEXT" },
+ { (PROC)glIndexPointerEXT, "glIndexPointerEXT" },
+ { (PROC)glTexCoordPointerEXT, "glTexCoordPointer" },
+ { (PROC)glEdgeFlagPointerEXT, "glEdgeFlagPointerEXT" },
+ { (PROC)glGetPointervEXT, "glGetPointervEXT" },
+ { (PROC)glArrayElementEXT, "glArrayElementEXT" },
+ { (PROC)glDrawArraysEXT, "glDrawArrayEXT" },
+ { (PROC)glAreTexturesResidentEXT, "glAreTexturesResidentEXT" },
+ { (PROC)glBindTextureEXT, "glBindTextureEXT" },
+ { (PROC)glDeleteTexturesEXT, "glDeleteTexturesEXT" },
+ { (PROC)glGenTexturesEXT, "glGenTexturesEXT" },
+ { (PROC)glIsTextureEXT, "glIsTextureEXT" },
+ { (PROC)glPrioritizeTexturesEXT, "glPrioritizeTexturesEXT" },
+ { (PROC)glCopyTexSubImage3DEXT, "glCopyTexSubImage3DEXT" },
+ { (PROC)glTexImage3DEXT, "glTexImage3DEXT" },
+ { (PROC)glTexSubImage3DEXT, "glTexSubImage3DEXT" },
+ { (PROC)gl3DfxSetPaletteEXT, "3DFX_set_global_palette" },
+ { (PROC)glColorTableEXT, "glColorTableEXT" },
+ { (PROC)glColorSubTableEXT, "glColorSubTableEXT" },
+ { (PROC)glGetColorTableEXT, "glGetColorTableEXT" },
+ { (PROC)glGetColorTableParameterfvEXT, "glGetColorTableParameterfvEXT" },
+ { (PROC)glGetColorTableParameterivEXT, "glGetColorTableParameterivEXT" },
+ { (PROC)glPointParameterfEXT, "glPointParameterfEXT" },
+ { (PROC)glPointParameterfvEXT, "glPointParameterfvEXT" },
+ { (PROC)glBlendFuncSeparateINGR, "glBlendFuncSeparateINGR" },
+ { (PROC)glLockArraysEXT, "glLockArraysEXT" },
+ { (PROC)glUnlockArraysEXT, "glUnlockArraysEXT" }
+};
+
+static int qt_ext = sizeof(ext) / sizeof(ext[0]);
+
+struct __pixelformat__ pix[] =
+{
+ /* None */
+ {
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|
+ PFD_DOUBLEBUFFER|PFD_SWAP_COPY,
+ PFD_TYPE_RGBA,
+ 32,
+ 8,0,8,8,8,16,0,24,
+ 0,0,0,0,0,
+ 0,
+ 0,
+ 0,
+ PFD_MAIN_PLANE,
+ 0,0,0,0
+ },
+ {
+ FXMESA_DOUBLEBUFFER,
+ FXMESA_ALPHA_SIZE, 0,
+ FXMESA_DEPTH_SIZE, 0,
+ FXMESA_STENCIL_SIZE, 0,
+ FXMESA_ACCUM_SIZE, 0,
+ FXMESA_NONE
+ }
+ },
+
+ /* Alpha */
+ {
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|
+ PFD_DOUBLEBUFFER|PFD_SWAP_COPY,
+ PFD_TYPE_RGBA,
+ 32,
+ 8,0,8,8,8,16,8,24,
+ 0,0,0,0,0,
+ 0,
+ 0,
+ 0,
+ PFD_MAIN_PLANE,
+ 0,0,0,0
+ },
+ {
+ FXMESA_DOUBLEBUFFER,
+ FXMESA_ALPHA_SIZE, 8,
+ FXMESA_DEPTH_SIZE, 0,
+ FXMESA_STENCIL_SIZE, 0,
+ FXMESA_ACCUM_SIZE, 0,
+ FXMESA_NONE
+ }
+ },
+
+ /* Depth */
+ {
+ {
+ sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|
+ PFD_DOUBLEBUFFER|PFD_SWAP_COPY,
+ PFD_TYPE_RGBA,
+ 32,
+ 8,0,8,8,8,16,0,24,
+ 0,0,0,0,0,
+ 16,
+ 0,
+ 0,
+ PFD_MAIN_PLANE,
+ 0,0,0,0
+ },
+ {
+ FXMESA_DOUBLEBUFFER,
+ FXMESA_ALPHA_SIZE, 0,
+ FXMESA_DEPTH_SIZE, 16,
+ FXMESA_STENCIL_SIZE, 0,
+ FXMESA_ACCUM_SIZE, 0,
+ FXMESA_NONE
+ }
+ }
+};
+static int qt_pix = sizeof(pix) / sizeof(pix[0]);
+
+static fxMesaContext ctx = NULL;
+static WNDPROC hWNDOldProc;
+static int curPFD = 0;
+static HDC hDC;
+static HWND hWND;
+
+static GLboolean haveDualHead;
+
+/* For the in-window-rendering hack */
+
+static GLboolean gdiWindowHack;
+static GLboolean gdiWindowHackEna;
+static void *dibSurfacePtr;
+static BITMAPINFO *dibBMI;
+static HBITMAP dibHBM;
+static HWND dibWnd;
+
+LONG GLAPIENTRY __wglMonitor(HWND hwnd,UINT message,UINT wParam,LONG lParam)
+
+{
+ long ret; /* Now gives the resized window at the end to hWNDOldProc */
+
+ if(ctx && hwnd == hWND) {
+ switch(message) {
+ case WM_PAINT:
+ case WM_MOVE:
+ break;
+ case WM_DISPLAYCHANGE:
+ case WM_SIZE:
+ if (wParam != SIZE_MINIMIZED) {
+ static int moving = 0;
+ if (!moving) {
+ if(fxQueryHardware()!=GR_SSTTYPE_VOODOO) {
+ if(!grSstControl(GR_CONTROL_RESIZE)) {
+ moving = 1;
+ SetWindowPos(hwnd, 0, 0, 0, 300, 300, SWP_NOMOVE|SWP_NOZORDER);
+ moving = 0;
+ if(!grSstControl(GR_CONTROL_RESIZE)) {
+ /*MessageBox(0,_T("Error changing windowsize"),_T("fxMESA"),MB_OK);*/
+ PostMessage(hWND,WM_CLOSE,0,0);
+ }
+ }
+ }
+
+ /* Do the clipping in the glide library */
+ grClipWindow(0,0,grSstScreenWidth(),grSstScreenHeight());
+ /* And let the new size set in the context */
+ fxMesaUpdateScreenSize(ctx);
+ }
+ }
+ break;
+ case WM_ACTIVATE:
+ if((fxQueryHardware()==GR_SSTTYPE_VOODOO) &&
+ (!gdiWindowHack) &&
+ (!haveDualHead)) {
+ WORD fActive = LOWORD(wParam);
+ BOOL fMinimized = (BOOL) HIWORD(wParam);
+
+ if((fActive == WA_INACTIVE) || fMinimized)
+ grSstControl(GR_CONTROL_DEACTIVATE);
+ else
+ grSstControl(GR_CONTROL_ACTIVATE);
+ }
+ break;
+ case WM_SHOWWINDOW:
+ break;
+ case WM_SYSCHAR:
+ if(gdiWindowHackEna && (VK_RETURN == wParam)) {
+ if(gdiWindowHack) {
+ gdiWindowHack = GL_FALSE;
+ grSstControl(GR_CONTROL_ACTIVATE);
+ } else {
+ gdiWindowHack = GL_TRUE;
+ grSstControl(GR_CONTROL_DEACTIVATE);
+ }
+ }
+ break;
+ }
+ }
+
+ /* Finaly call the hWNDOldProc, which handles the resize witch the
+ now changed window sizes */
+ ret = CallWindowProc( hWNDOldProc, hwnd, message, wParam, lParam );
+
+ return(ret);
+}
+
+BOOL GLAPIENTRY wglCopyContext(HGLRC hglrcSrc,HGLRC hglrcDst,UINT mask)
+{
+ return(FALSE);
+}
+
+HGLRC GLAPIENTRY wglCreateContext(HDC hdc)
+{
+ HWND hWnd;
+ WNDPROC oldProc;
+ int error;
+
+ if(ctx) {
+ SetLastError(0);
+ return(NULL);
+ }
+
+ if(!(hWnd = WindowFromDC(hdc))) {
+ SetLastError(0);
+ return(NULL);
+ }
+
+ if(curPFD == 0) {
+ SetLastError(0);
+ return(NULL);
+ }
+
+ if((oldProc = (WNDPROC)GetWindowLong(hWnd,GWL_WNDPROC)) != __wglMonitor) {
+ hWNDOldProc = oldProc;
+ SetWindowLong(hWnd,GWL_WNDPROC,(LONG)__wglMonitor);
+ }
+
+#ifndef FX_SILENT
+ freopen("MESA.LOG","w",stderr);
+#endif
+
+ ShowWindow(hWnd, SW_SHOWNORMAL);
+ SetForegroundWindow(hWnd);
+ Sleep(100); /* an hack for win95 */
+
+ if(fxQueryHardware() == GR_SSTTYPE_VOODOO) {
+ RECT cliRect;
+
+ GetClientRect(hWnd,&cliRect);
+ error = !(ctx = fxMesaCreateBestContext((GLuint)hWnd,cliRect.right,cliRect.bottom,
+ pix[curPFD - 1].mesaAttr));
+
+ if(!error) {
+ /* create the DIB section for windowed rendering */
+ DWORD *p;
+
+ dibWnd = hWnd;
+
+ hDC = GetDC(dibWnd);
+
+ dibBMI = (BITMAPINFO*) malloc( sizeof(BITMAPINFO) + (256*sizeof(RGBQUAD)));
+
+ memset(dibBMI,0,sizeof(BITMAPINFO) + (256*sizeof(RGBQUAD)));
+
+ dibBMI->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ dibBMI->bmiHeader.biWidth = ctx->width;
+ dibBMI->bmiHeader.biHeight = -ctx->height;
+ dibBMI->bmiHeader.biPlanes = (short)1;
+ dibBMI->bmiHeader.biBitCount = (short)16;
+ dibBMI->bmiHeader.biCompression = BI_BITFIELDS;
+ dibBMI->bmiHeader.biSizeImage = 0;
+ dibBMI->bmiHeader.biXPelsPerMeter = 0;
+ dibBMI->bmiHeader.biYPelsPerMeter = 0;
+ dibBMI->bmiHeader.biClrUsed = 3;
+ dibBMI->bmiHeader.biClrImportant = 3;
+
+ p = (DWORD*)dibBMI->bmiColors;
+ p[0] = 0xF800;
+ p[1] = 0x07E0;
+ p[2] = 0x001F;
+
+ dibHBM = CreateDIBSection(hDC, dibBMI, DIB_RGB_COLORS, &dibSurfacePtr, NULL, 0);
+
+ ReleaseDC(dibWnd, hDC);
+
+ gdiWindowHackEna = (dibHBM != NULL ? GL_TRUE : GL_FALSE);
+
+ if (!getenv("MESA_WGL_FX") || !strcmp(getenv("MESA_WGL_FX"),"fullscreen"))
+ gdiWindowHack = GL_FALSE;
+ else {
+ gdiWindowHack = GL_TRUE;
+ grSstControl(GR_CONTROL_DEACTIVATE);
+ }
+ }
+ } else {
+ /* For the Voodoo Rush */
+
+ if(getenv("MESA_WGL_FX") && !strcmp(getenv("MESA_WGL_FX"),"fullscreen")) {
+ RECT cliRect;
+
+ GetClientRect(hWnd,&cliRect);
+ error = !(ctx = fxMesaCreateBestContext((GLuint)hWnd,cliRect.right,cliRect.bottom,
+ pix[curPFD - 1].mesaAttr));
+ } else
+ error = !(ctx = fxMesaCreateContext((GLuint)hWnd,GR_RESOLUTION_NONE,GR_REFRESH_75Hz,
+ pix[curPFD - 1].mesaAttr));
+ }
+
+ if(getenv("SST_DUALHEAD"))
+ haveDualHead=((atoi(getenv("SST_DUALHEAD"))==1) ? GL_TRUE:GL_FALSE);
+ else
+ haveDualHead=GL_FALSE;
+
+ if(error) {
+ SetLastError(0);
+ return(NULL);
+ }
+
+ hDC = hdc;
+ hWND = hWnd;
+
+ /* Required by the OpenGL Optimizer 1.1 (is it a Optimizer bug ?) */
+ wglMakeCurrent(hdc,(HGLRC)1);
+
+ return((HGLRC)1);
+}
+
+HGLRC GLAPIENTRY wglCreateLayerContext(HDC hdc,int iLayerPlane)
+{
+ SetLastError(0);
+ return(NULL);
+}
+
+BOOL GLAPIENTRY wglDeleteContext(HGLRC hglrc)
+{
+ if(ctx && hglrc == (HGLRC)1) {
+ if (gdiWindowHackEna) {
+ DeleteObject(dibHBM);
+ free(dibBMI);
+
+ dibSurfacePtr = NULL;
+ dibBMI = NULL;
+ dibHBM = NULL;
+ dibWnd = NULL;
+ }
+
+ fxMesaDestroyContext(ctx);
+
+ SetWindowLong(WindowFromDC(hDC),GWL_WNDPROC,(LONG)hWNDOldProc);
+
+ ctx = NULL;
+ hDC = 0;
+ return(TRUE);
+ }
+
+ SetLastError(0);
+
+ return(FALSE);
+}
+
+HGLRC GLAPIENTRY wglGetCurrentContext(VOID)
+{
+ if(ctx)
+ return((HGLRC)1);
+
+ SetLastError(0);
+ return(NULL);
+}
+
+HDC GLAPIENTRY wglGetCurrentDC(VOID)
+{
+ if(ctx)
+ return(hDC);
+
+ SetLastError(0);
+ return(NULL);
+}
+
+PROC GLAPIENTRY wglGetProcAddress(LPCSTR lpszProc)
+{
+ int i;
+
+ /*fprintf(stderr,"fxMesa: looking for extension %s\n",lpszProc);
+ fflush(stderr);*/
+
+ for(i = 0;i < qt_ext;i++)
+ if(!strcmp(lpszProc,ext[i].name)) {
+ /*fprintf(stderr,"fxMesa: found extension %s\n",lpszProc);
+ fflush(stderr);*/
+
+ return(ext[i].proc);
+ }
+ SetLastError(0);
+ return(NULL);
+}
+
+BOOL GLAPIENTRY wglMakeCurrent(HDC hdc,HGLRC hglrc)
+{
+ if((hdc==NULL) && (hglrc==NULL))
+ return(TRUE);
+
+ if(!ctx || hglrc != (HGLRC)1 || WindowFromDC(hdc) != hWND) {
+ SetLastError(0);
+ return(FALSE);
+ }
+
+ hDC = hdc;
+
+ fxMesaMakeCurrent(ctx);
+
+ return(TRUE);
+}
+
+BOOL GLAPIENTRY wglShareLists(HGLRC hglrc1,HGLRC hglrc2)
+{
+ if(!ctx || hglrc1 != (HGLRC)1 || hglrc1 != hglrc2) {
+ SetLastError(0);
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+BOOL GLAPIENTRY wglUseFontBitmaps(HDC fontDevice, DWORD firstChar, DWORD numChars, DWORD listBase)
+{
+#define VERIFY(a) a
+
+ TEXTMETRIC metric;
+ BITMAPINFO *dibInfo;
+ HDC bitDevice;
+ COLORREF tempColor;
+ int i;
+
+ VERIFY(GetTextMetrics(fontDevice, &metric));
+
+ dibInfo = (BITMAPINFO *) calloc(sizeof(BITMAPINFO) + sizeof(RGBQUAD), 1);
+ dibInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ dibInfo->bmiHeader.biPlanes = 1;
+ dibInfo->bmiHeader.biBitCount = 1;
+ dibInfo->bmiHeader.biCompression = BI_RGB;
+
+ bitDevice = CreateCompatibleDC(fontDevice);
+ // HDC bitDevice = CreateDC("DISPLAY", NULL, NULL, NULL);
+ // VERIFY(bitDevice);
+
+ // Swap fore and back colors so the bitmap has the right polarity
+ tempColor = GetBkColor(bitDevice);
+ SetBkColor(bitDevice, GetTextColor(bitDevice));
+ SetTextColor(bitDevice, tempColor);
+
+ // Place chars based on base line
+ VERIFY(SetTextAlign(bitDevice, TA_BASELINE) >= 0);
+
+ for(i = 0; i < numChars; i++) {
+ SIZE size;
+ char curChar;
+ int charWidth,charHeight,bmapWidth,bmapHeight,numBytes,res;
+ HBITMAP bitObject;
+ HGDIOBJ origBmap;
+ unsigned char *bmap;
+
+ curChar = i + firstChar;
+
+ // Find how high/wide this character is
+ VERIFY(GetTextExtentPoint32(bitDevice, &curChar, 1, &size));
+
+ // Create the output bitmap
+ charWidth = size.cx;
+ charHeight = size.cy;
+ bmapWidth = ((charWidth + 31) / 32) * 32; // Round up to the next multiple of 32 bits
+ bmapHeight = charHeight;
+ bitObject = CreateCompatibleBitmap(bitDevice,
+ bmapWidth,
+ bmapHeight);
+ //VERIFY(bitObject);
+
+ // Assign the output bitmap to the device
+ origBmap = SelectObject(bitDevice, bitObject);
+ VERIFY(origBmap);
+
+ VERIFY( PatBlt( bitDevice, 0, 0, bmapWidth, bmapHeight,BLACKNESS ) );
+
+ // Use our source font on the device
+ VERIFY(SelectObject(bitDevice, GetCurrentObject(fontDevice,OBJ_FONT)));
+
+ // Draw the character
+ VERIFY(TextOut(bitDevice, 0, metric.tmAscent, &curChar, 1));
+
+ // Unselect our bmap object
+ VERIFY(SelectObject(bitDevice, origBmap));
+
+ // Convert the display dependant representation to a 1 bit deep DIB
+ numBytes = (bmapWidth * bmapHeight) / 8;
+ bmap = malloc(numBytes);
+ dibInfo->bmiHeader.biWidth = bmapWidth;
+ dibInfo->bmiHeader.biHeight = bmapHeight;
+ res = GetDIBits(bitDevice, bitObject, 0, bmapHeight, bmap,
+ dibInfo,
+ DIB_RGB_COLORS);
+ //VERIFY(res);
+
+ // Create the GL object
+ glNewList(i + listBase, GL_COMPILE);
+ glBitmap(bmapWidth, bmapHeight, 0.0, metric.tmDescent,
+ charWidth, 0.0,
+ bmap);
+ glEndList();
+ // CheckGL();
+
+ // Destroy the bmap object
+ DeleteObject(bitObject);
+
+ // Deallocate the bitmap data
+ free(bmap);
+ }
+
+ // Destroy the DC
+ VERIFY(DeleteDC(bitDevice));
+
+ free(dibInfo);
+
+ return TRUE;
+#undef VERIFY
+}
+
+BOOL GLAPIENTRY wglUseFontBitmapsW(HDC hdc,DWORD first,DWORD count,DWORD listBase)
+{
+ return(FALSE);
+}
+
+BOOL GLAPIENTRY wglUseFontOutlinesA(HDC hdc,DWORD first,DWORD count,
+ DWORD listBase,FLOAT deviation,
+ FLOAT extrusion,int format,
+ LPGLYPHMETRICSFLOAT lpgmf)
+{
+ SetLastError(0);
+ return(FALSE);
+}
+
+BOOL GLAPIENTRY wglUseFontOutlinesW(HDC hdc,DWORD first,DWORD count,
+ DWORD listBase,FLOAT deviation,
+ FLOAT extrusion,int format,
+ LPGLYPHMETRICSFLOAT lpgmf)
+{
+ SetLastError(0);
+ return(FALSE);
+}
+
+
+BOOL GLAPIENTRY wglSwapLayerBuffers(HDC hdc,UINT fuPlanes)
+{
+ if(ctx && WindowFromDC(hdc) == hWND) {
+ fxMesaSwapBuffers();
+
+ return(TRUE);
+ }
+
+ SetLastError(0);
+ return(FALSE);
+}
+
+int GLAPIENTRY wglChoosePixelFormat(HDC hdc,
+ CONST PIXELFORMATDESCRIPTOR *ppfd)
+{
+ int i,best=-1,qt_valid_pix;
+
+ qt_valid_pix = qt_pix;
+
+ if(ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR) || ppfd->nVersion != 1) {
+ SetLastError(0);
+ return(0);
+ }
+
+ for(i = 0;i < qt_valid_pix;i++) {
+ if((ppfd->dwFlags & PFD_DRAW_TO_WINDOW) && !(pix[i].pfd.dwFlags & PFD_DRAW_TO_WINDOW))
+ continue;
+ if((ppfd->dwFlags & PFD_DRAW_TO_BITMAP) && !(pix[i].pfd.dwFlags & PFD_DRAW_TO_BITMAP))
+ continue;
+ if((ppfd->dwFlags & PFD_SUPPORT_GDI) && !(pix[i].pfd.dwFlags & PFD_SUPPORT_GDI))
+ continue;
+ if((ppfd->dwFlags & PFD_SUPPORT_OPENGL) && !(pix[i].pfd.dwFlags & PFD_SUPPORT_OPENGL))
+ continue;
+ if(!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) &&
+ ((ppfd->dwFlags & PFD_DOUBLEBUFFER) != (pix[i].pfd.dwFlags & PFD_DOUBLEBUFFER)))
+ continue;
+ if(!(ppfd->dwFlags & PFD_STEREO_DONTCARE) &&
+ ((ppfd->dwFlags & PFD_STEREO) != (pix[i].pfd.dwFlags & PFD_STEREO)))
+ continue;
+
+ if (ppfd->cDepthBits > 0 && pix[i].pfd.cDepthBits == 0)
+ continue; /* need depth buffer */
+
+ if (ppfd->cAlphaBits > 0 && pix[i].pfd.cAlphaBits == 0)
+ continue; /* need alpha buffer */
+
+ if(ppfd->iPixelType == pix[i].pfd.iPixelType) {
+ best = i + 1;
+ break;
+ }
+ }
+
+ if(best == -1) {
+ SetLastError(0);
+ return(0);
+ }
+
+ return(best);
+}
+
+int GLAPIENTRY ChoosePixelFormat(HDC hdc,
+ CONST PIXELFORMATDESCRIPTOR *ppfd)
+{
+ return wglChoosePixelFormat(hdc,ppfd);
+}
+
+int GLAPIENTRY wglDescribePixelFormat(HDC hdc,int iPixelFormat,UINT nBytes,
+ LPPIXELFORMATDESCRIPTOR ppfd)
+{
+ int qt_valid_pix;
+
+ qt_valid_pix = qt_pix;
+
+ if(iPixelFormat < 1 || iPixelFormat > qt_valid_pix ||
+ ((nBytes != sizeof(PIXELFORMATDESCRIPTOR)) && (nBytes != 0))) {
+ SetLastError(0);
+ return(0);
+ }
+
+ if(nBytes != 0)
+ *ppfd = pix[iPixelFormat - 1].pfd;
+
+ return(qt_valid_pix);
+}
+
+int GLAPIENTRY DescribePixelFormat(HDC hdc,int iPixelFormat,UINT nBytes,
+ LPPIXELFORMATDESCRIPTOR ppfd)
+{
+ return wglDescribePixelFormat(hdc,iPixelFormat,nBytes,ppfd);
+}
+
+int GLAPIENTRY wglGetPixelFormat(HDC hdc)
+{
+ if(curPFD == 0) {
+ SetLastError(0);
+ return(0);
+ }
+
+ return(curPFD);
+}
+
+int GLAPIENTRY GetPixelFormat(HDC hdc)
+{
+ return wglGetPixelFormat(hdc);
+}
+
+BOOL GLAPIENTRY wglSetPixelFormat(HDC hdc,int iPixelFormat,
+ CONST PIXELFORMATDESCRIPTOR *ppfd)
+{
+ int qt_valid_pix;
+
+ qt_valid_pix = qt_pix;
+
+ if(iPixelFormat < 1 || iPixelFormat > qt_valid_pix || ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR)) {
+ SetLastError(0);
+ return(FALSE);
+ }
+ curPFD = iPixelFormat;
+
+ return(TRUE);
+}
+
+BOOL GLAPIENTRY wglSwapBuffers(HDC hdc)
+{
+ if(!ctx) {
+ SetLastError(0);
+ return(FALSE);
+ }
+
+ fxMesaSwapBuffers();
+
+ if(gdiWindowHack) {
+ GLuint width=ctx->width;
+ GLuint height=ctx->height;
+
+ HDC hdcScreen = GetDC(dibWnd);
+ HDC hdcDIBSection = CreateCompatibleDC(hdcScreen);
+ HBITMAP holdBitmap = (HBITMAP) SelectObject(hdcDIBSection, dibHBM);
+
+ grLfbReadRegion(GR_BUFFER_FRONTBUFFER, 0, 0,
+ width, height,
+ width * 2,
+ dibSurfacePtr);
+
+ /* Since the hardware is configured for GR_COLORFORMAT_ABGR the pixel data is
+ * going to come out as BGR 565, which is reverse of what we need for blitting
+ * to screen, so we need to convert it here pixel-by-pixel (ick). This loop would NOT
+ * be required if the color format was changed to GR_COLORFORMAT_ARGB, but I do
+ * not know the ramifications of that, so this will work until that is resolved.
+ *
+ * This routine CRIES out for MMX implementation, however since that's not
+ * guaranteed to be running on MMX enabled hardware so I'm not going to do
+ * that. I'm just going to try to make a reasonably efficient C
+ * version. -TAJ
+ *
+ * This routine drops frame rate by <1 fps on a 200Mhz MMX processor with a 640x480
+ * display. Obviously, it's performance hit will be higher on larger displays and
+ * less on smaller displays. To support the window-hack display this is probably fine.
+ */
+ {
+ unsigned long *pixel = dibSurfacePtr;
+ unsigned long count = (width * height) / 2;
+
+ while (count--)
+ {
+ *pixel++ = (*pixel & 0x07e007e0) /* greens */
+ | ((*pixel & 0xf800f800) >> 11) /* swap blues */
+ | ((*pixel & 0x001f001f) << 11) /* swap reds */
+ ;
+ }
+ }
+
+ BitBlt(hdcScreen, 0, 0,
+ width, height,
+ hdcDIBSection,
+ 0, 0, SRCCOPY);
+
+ ReleaseDC(dibWnd, hdcScreen);
+ SelectObject(hdcDIBSection, holdBitmap);
+ DeleteDC(hdcDIBSection);
+ }
+
+ return(TRUE);
+}
+
+BOOL GLAPIENTRY SetPixelFormat(HDC hdc, int iPixelFormat,
+ CONST PIXELFORMATDESCRIPTOR *ppfd)
+{
+ return wglSetPixelFormat(hdc,iPixelFormat,ppfd);
+}
+
+BOOL GLAPIENTRY SwapBuffers(HDC hdc)
+{
+ return wglSwapBuffers(hdc);
+}
+
+#endif /* FX */
diff --git a/src/mesa/drivers/osmesa/osmesa.c b/src/mesa/drivers/osmesa/osmesa.c
new file mode 100644
index 0000000000..25bba5b5e8
--- /dev/null
+++ b/src/mesa/drivers/osmesa/osmesa.c
@@ -0,0 +1,1594 @@
+/* $Id: osmesa.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+/*
+ * Off-Screen Mesa rendering / Rendering into client memory space
+ */
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <stdlib.h>
+#include <string.h>
+#include "GL/osmesa.h"
+#include "context.h"
+#include "depth.h"
+#include "macros.h"
+#include "matrix.h"
+#include "types.h"
+#include "vb.h"
+#endif
+
+
+struct osmesa_context {
+ GLcontext *gl_ctx; /* The core GL/Mesa context */
+ GLvisual *gl_visual; /* Describes the buffers */
+ GLframebuffer *gl_buffer; /* Depth, stencil, accum, etc buffers */
+ GLenum format; /* either GL_RGBA or GL_COLOR_INDEX */
+ void *buffer; /* the image buffer */
+ GLint width, height; /* size of image buffer */
+ GLuint pixel; /* current color index or RGBA pixel value */
+ GLuint clearpixel; /* pixel for clearing the color buffer */
+ GLint rowlength; /* number of pixels per row */
+ GLint userRowLength; /* user-specified number of pixels per row */
+ GLint rshift, gshift; /* bit shifts for RGBA formats */
+ GLint bshift, ashift;
+ GLint rind, gind, bind; /* index offsets for RGBA formats */
+ void *rowaddr[MAX_HEIGHT]; /* address of first pixel in each image row */
+ GLboolean yup; /* TRUE -> Y increases upward */
+ /* FALSE -> Y increases downward */
+};
+
+
+
+#ifdef THREADS
+
+#include "mthreads.h" /* Mesa platform independent threads interface */
+
+static MesaTSD osmesa_ctx_tsd;
+
+static void osmesa_ctx_thread_init() {
+ MesaInitTSD(&osmesa_ctx_tsd);
+}
+
+static OSMesaContext osmesa_get_thread_context( void ) {
+ return (OSMesaContext) MesaGetTSD(&osmesa_ctx_tsd);
+}
+
+static void osmesa_set_thread_context( OSMesaContext ctx ) {
+ MesaSetTSD(&osmesa_ctx_tsd, ctx, osmesa_ctx_thread_init);
+}
+
+
+#else
+ /* One current context for address space, all threads */
+ static OSMesaContext Current = NULL;
+#endif
+
+
+
+/* A forward declaration: */
+static void osmesa_update_state( GLcontext *ctx );
+
+
+
+/**********************************************************************/
+/***** Public Functions *****/
+/**********************************************************************/
+
+
+/*
+ * Create an Off-Screen Mesa rendering context. The only attribute needed is
+ * an RGBA vs Color-Index mode flag.
+ *
+ * Input: format - either GL_RGBA or GL_COLOR_INDEX
+ * sharelist - specifies another OSMesaContext with which to share
+ * display lists. NULL indicates no sharing.
+ * Return: an OSMesaContext or 0 if error
+ */
+OSMesaContext GLAPIENTRY OSMesaCreateContext( GLenum format, OSMesaContext sharelist )
+{
+ OSMesaContext osmesa;
+ GLint rshift, gshift, bshift, ashift;
+ GLint rind, gind, bind;
+ GLint indexBits, alphaBits;
+ GLboolean rgbmode;
+ GLboolean swalpha;
+ GLuint i4 = 1;
+ GLubyte *i1 = (GLubyte *) &i4;
+ GLint little_endian = *i1;
+
+ swalpha = GL_FALSE;
+ rind = gind = bind = 0;
+ if (format==OSMESA_COLOR_INDEX) {
+ indexBits = 8;
+ rshift = gshift = bshift = ashift = 0;
+ rgbmode = GL_FALSE;
+ }
+ else if (format==OSMESA_RGBA) {
+ indexBits = 0;
+ alphaBits = 8;
+ if (little_endian) {
+ rshift = 0;
+ gshift = 8;
+ bshift = 16;
+ ashift = 24;
+ }
+ else {
+ rshift = 24;
+ gshift = 16;
+ bshift = 8;
+ ashift = 0;
+ }
+ rgbmode = GL_TRUE;
+ }
+ else if (format==OSMESA_BGRA) {
+ indexBits = 0;
+ alphaBits = 8;
+ if (little_endian) {
+ ashift = 0;
+ rshift = 8;
+ gshift = 16;
+ bshift = 24;
+ }
+ else {
+ bshift = 24;
+ gshift = 16;
+ rshift = 8;
+ ashift = 0;
+ }
+ rgbmode = GL_TRUE;
+ }
+ else if (format==OSMESA_ARGB) {
+ indexBits = 0;
+ alphaBits = 8;
+ if (little_endian) {
+ bshift = 0;
+ gshift = 8;
+ rshift = 16;
+ ashift = 24;
+ }
+ else {
+ ashift = 24;
+ rshift = 16;
+ gshift = 8;
+ bshift = 0;
+ }
+ rgbmode = GL_TRUE;
+ }
+ else if (format==OSMESA_RGB) {
+ indexBits = 0;
+ alphaBits = 0;
+ bshift = 0;
+ gshift = 8;
+ rshift = 16;
+ ashift = 24;
+ bind = 2;
+ gind = 1;
+ rind = 0;
+ rgbmode = GL_TRUE;
+ swalpha = GL_TRUE;
+ }
+ else if (format==OSMESA_BGR) {
+ indexBits = 0;
+ alphaBits = 0;
+ bshift = 0;
+ gshift = 8;
+ rshift = 16;
+ ashift = 24;
+ bind = 0;
+ gind = 1;
+ rind = 2;
+ rgbmode = GL_TRUE;
+ swalpha = GL_TRUE;
+ }
+ else {
+ return NULL;
+ }
+
+
+ osmesa = (OSMesaContext) calloc( 1, sizeof(struct osmesa_context) );
+ if (osmesa) {
+ osmesa->gl_visual = gl_create_visual( rgbmode,
+ swalpha, /* software alpha */
+ GL_FALSE, /* double buffer */
+ GL_FALSE, /* stereo */
+ DEPTH_BITS,
+ STENCIL_BITS,
+ ACCUM_BITS,
+ indexBits,
+ 8, 8, 8, alphaBits );
+ if (!osmesa->gl_visual) {
+ return NULL;
+ }
+
+ osmesa->gl_ctx = gl_create_context( osmesa->gl_visual,
+ sharelist ? sharelist->gl_ctx : (GLcontext *) NULL,
+ (void *) osmesa, GL_TRUE );
+ if (!osmesa->gl_ctx) {
+ gl_destroy_visual( osmesa->gl_visual );
+ free(osmesa);
+ return NULL;
+ }
+ osmesa->gl_buffer = gl_create_framebuffer( osmesa->gl_visual );
+ if (!osmesa->gl_buffer) {
+ gl_destroy_visual( osmesa->gl_visual );
+ gl_destroy_context( osmesa->gl_ctx );
+ free(osmesa);
+ return NULL;
+ }
+ osmesa->format = format;
+ osmesa->buffer = NULL;
+ osmesa->width = 0;
+ osmesa->height = 0;
+ osmesa->pixel = 0;
+ osmesa->clearpixel = 0;
+ osmesa->userRowLength = 0;
+ osmesa->rowlength = 0;
+ osmesa->yup = GL_TRUE;
+ osmesa->rshift = rshift;
+ osmesa->gshift = gshift;
+ osmesa->bshift = bshift;
+ osmesa->ashift = ashift;
+ osmesa->rind = rind;
+ osmesa->gind = gind;
+ osmesa->bind = bind;
+ }
+ return osmesa;
+}
+
+
+
+/*
+ * Destroy an Off-Screen Mesa rendering context.
+ *
+ * Input: ctx - the context to destroy
+ */
+void GLAPIENTRY OSMesaDestroyContext( OSMesaContext ctx )
+{
+ if (ctx) {
+ gl_destroy_visual( ctx->gl_visual );
+ gl_destroy_framebuffer( ctx->gl_buffer );
+ gl_destroy_context( ctx->gl_ctx );
+ free( ctx );
+ }
+}
+
+
+
+/*
+ * Recompute the values of the context's rowaddr array.
+ */
+static void compute_row_addresses( OSMesaContext ctx )
+{
+ GLint i;
+
+ if (ctx->yup) {
+ /* Y=0 is bottom line of window */
+ if (ctx->format==OSMESA_COLOR_INDEX) {
+ /* 1-byte CI mode */
+ GLubyte *origin = (GLubyte *) ctx->buffer;
+ for (i=0;i<MAX_HEIGHT;i++) {
+ ctx->rowaddr[i] = origin + i * ctx->rowlength;
+ }
+ }
+ else {
+ if ((ctx->format==OSMESA_RGB) || (ctx->format==OSMESA_BGR)) {
+ /* 3-byte RGB mode */
+ GLubyte *origin = (GLubyte *) ctx->buffer;
+ for (i=0;i<MAX_HEIGHT;i++) {
+ ctx->rowaddr[i] = origin + (i * (ctx->rowlength*3));
+ }
+ } else {
+ /* 4-byte RGBA mode */
+ GLuint *origin = (GLuint *) ctx->buffer;
+ for (i=0;i<MAX_HEIGHT;i++) {
+ ctx->rowaddr[i] = origin + i * ctx->rowlength;
+ }
+ }
+ }
+ }
+ else {
+ /* Y=0 is top line of window */
+ if (ctx->format==OSMESA_COLOR_INDEX) {
+ /* 1-byte CI mode */
+ GLubyte *origin = (GLubyte *) ctx->buffer;
+ for (i=0;i<MAX_HEIGHT;i++) {
+ ctx->rowaddr[i] = origin + (ctx->height-i-1) * ctx->rowlength;
+ }
+ }
+ else {
+ if ((ctx->format==OSMESA_RGB) || (ctx->format==OSMESA_BGR)) {
+ /* 3-byte RGB mode */
+ GLubyte *origin = (GLubyte *) ctx->buffer;
+ for (i=0;i<MAX_HEIGHT;i++) {
+ ctx->rowaddr[i] = origin + ((ctx->height-i-1) * (ctx->rowlength*3));
+ }
+ } else {
+ /* 4-byte RGBA mode */
+ GLuint *origin = (GLuint *) ctx->buffer;
+ for (i=0;i<MAX_HEIGHT;i++) {
+ ctx->rowaddr[i] = origin + (ctx->height-i-1) * ctx->rowlength;
+ }
+ }
+ }
+ }
+}
+
+
+/*
+ * Bind an OSMesaContext to an image buffer. The image buffer is just a
+ * block of memory which the client provides. Its size must be at least
+ * as large as width*height*sizeof(type). Its address should be a multiple
+ * of 4 if using RGBA mode.
+ *
+ * Image data is stored in the order of glDrawPixels: row-major order
+ * with the lower-left image pixel stored in the first array position
+ * (ie. bottom-to-top).
+ *
+ * Since the only type initially supported is GL_UNSIGNED_BYTE, if the
+ * context is in RGBA mode, each pixel will be stored as a 4-byte RGBA
+ * value. If the context is in color indexed mode, each pixel will be
+ * stored as a 1-byte value.
+ *
+ * If the context's viewport hasn't been initialized yet, it will now be
+ * initialized to (0,0,width,height).
+ *
+ * Input: ctx - the rendering context
+ * buffer - the image buffer memory
+ * type - data type for pixel components, only GL_UNSIGNED_BYTE
+ * supported now
+ * width, height - size of image buffer in pixels, at least 1
+ * Return: GL_TRUE if success, GL_FALSE if error because of invalid ctx,
+ * invalid buffer address, type!=GL_UNSIGNED_BYTE, width<1, height<1,
+ * width>internal limit or height>internal limit.
+ */
+GLboolean GLAPIENTRY OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type,
+ GLsizei width, GLsizei height )
+{
+ if (!ctx || !buffer || type!=GL_UNSIGNED_BYTE
+ || width<1 || height<1 || width>MAX_WIDTH || height>MAX_HEIGHT) {
+ return GL_FALSE;
+ }
+
+ osmesa_update_state( ctx->gl_ctx );
+ gl_make_current( ctx->gl_ctx, ctx->gl_buffer );
+
+ ctx->buffer = buffer;
+ ctx->width = width;
+ ctx->height = height;
+ if (ctx->userRowLength)
+ ctx->rowlength = ctx->userRowLength;
+ else
+ ctx->rowlength = width;
+
+#ifdef THREADS
+ /* Set current context for the calling thread */
+ osmesa_set_thread_context(ctx);
+#else
+ /* Set current context for the address space, all threads */
+ Current = ctx;
+#endif
+
+ compute_row_addresses( ctx );
+
+ /* init viewport */
+ if (ctx->gl_ctx->Viewport.Width==0) {
+ /* initialize viewport and scissor box to buffer size */
+ gl_Viewport( ctx->gl_ctx, 0, 0, width, height );
+ ctx->gl_ctx->Scissor.Width = width;
+ ctx->gl_ctx->Scissor.Height = height;
+ }
+
+ return GL_TRUE;
+}
+
+
+
+
+OSMesaContext GLAPIENTRY OSMesaGetCurrentContext( void )
+{
+#ifdef THREADS
+ /* Return current handle for the calling thread */
+ return osmesa_get_thread_context();
+#else
+ /* Return current handle for the address space, all threads */
+ return Current;
+#endif
+}
+
+
+
+void GLAPIENTRY OSMesaPixelStore( GLint pname, GLint value )
+{
+ OSMesaContext ctx = OSMesaGetCurrentContext();
+
+ switch (pname) {
+ case OSMESA_ROW_LENGTH:
+ if (value<0) {
+ gl_error( ctx->gl_ctx, GL_INVALID_VALUE,
+ "OSMesaPixelStore(value)" );
+ return;
+ }
+ ctx->userRowLength = value;
+ ctx->rowlength = value;
+ break;
+ case OSMESA_Y_UP:
+ ctx->yup = value ? GL_TRUE : GL_FALSE;
+ break;
+ default:
+ gl_error( ctx->gl_ctx, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" );
+ return;
+ }
+
+ compute_row_addresses( ctx );
+}
+
+
+void GLAPIENTRY OSMesaGetIntegerv( GLint pname, GLint *value )
+{
+ OSMesaContext ctx = OSMesaGetCurrentContext();
+
+ switch (pname) {
+ case OSMESA_WIDTH:
+ *value = ctx->width;
+ return;
+ case OSMESA_HEIGHT:
+ *value = ctx->height;
+ return;
+ case OSMESA_FORMAT:
+ *value = ctx->format;
+ return;
+ case OSMESA_TYPE:
+ *value = GL_UNSIGNED_BYTE;
+ return;
+ case OSMESA_ROW_LENGTH:
+ *value = ctx->rowlength;
+ return;
+ case OSMESA_Y_UP:
+ *value = ctx->yup;
+ return;
+ default:
+ gl_error( ctx->gl_ctx, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)" );
+ return;
+ }
+}
+
+
+
+/*
+ * Return the depth buffer associated with an OSMesa context.
+ * Input: c - the OSMesa context
+ * Output: width, height - size of buffer in pixels
+ * bytesPerValue - bytes per depth value (2 or 4)
+ * buffer - pointer to depth buffer values
+ * Return: GL_TRUE or GL_FALSE to indicate success or failure.
+ */
+GLboolean GLAPIENTRY OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
+ GLint *bytesPerValue, void **buffer )
+{
+ if ((!c->gl_buffer) || (!c->gl_buffer->Depth)) {
+ *width = 0;
+ *height = 0;
+ *bytesPerValue = 0;
+ *buffer = 0;
+ return GL_FALSE;
+ }
+ else {
+ *width = c->gl_buffer->Width;
+ *height = c->gl_buffer->Height;
+ *bytesPerValue = sizeof(GLdepth);
+ *buffer = c->gl_buffer->Depth;
+ return GL_TRUE;
+ }
+}
+
+
+
+
+/**********************************************************************/
+/*** Device Driver Functions ***/
+/**********************************************************************/
+
+
+/*
+ * Useful macros:
+ */
+#define PACK_RGBA(R,G,B,A) ( ((R) << osmesa->rshift) \
+ | ((G) << osmesa->gshift) \
+ | ((B) << osmesa->bshift) \
+ | ((A) << osmesa->ashift) )
+
+#define PACK_RGBA2(R,G,B,A) ( ((R) << rshift) \
+ | ((G) << gshift) \
+ | ((B) << bshift) \
+ | ((A) << ashift) )
+
+#define UNPACK_RED(P) (((P) >> osmesa->rshift) & 0xff)
+#define UNPACK_GREEN(P) (((P) >> osmesa->gshift) & 0xff)
+#define UNPACK_BLUE(P) (((P) >> osmesa->bshift) & 0xff)
+#define UNPACK_ALPHA(P) (((P) >> osmesa->ashift) & 0xff)
+
+#define PIXELADDR1(X,Y) ((GLubyte *) osmesa->rowaddr[Y] + (X))
+#define PIXELADDR3(X,Y) ((GLubyte *) osmesa->rowaddr[Y] + ((X)*3))
+#define PIXELADDR4(X,Y) ((GLuint *) osmesa->rowaddr[Y] + (X))
+
+
+
+
+static GLboolean set_buffer( GLcontext *ctx, GLenum mode )
+{
+ (void) ctx;
+ if (mode==GL_FRONT_LEFT) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
+
+static void clear_index( GLcontext *ctx, GLuint index )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ osmesa->clearpixel = index;
+}
+
+
+
+static void clear_color( GLcontext *ctx,
+ GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ osmesa->clearpixel = PACK_RGBA( r, g, b, a );
+}
+
+
+
+static GLbitfield clear( GLcontext *ctx, GLbitfield mask, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ if (mask & GL_COLOR_BUFFER_BIT) {
+ if (osmesa->format==OSMESA_COLOR_INDEX) {
+ if (all) {
+ /* Clear whole CI buffer */
+ MEMSET(osmesa->buffer, osmesa->clearpixel,
+ osmesa->rowlength * osmesa->height);
+ }
+ else {
+ /* Clear part of CI buffer */
+ GLint i, j;
+ for (i=0;i<height;i++) {
+ GLubyte *ptr1 = PIXELADDR1( x, (y+i) );
+ for (j=0;j<width;j++) {
+ *ptr1++ = osmesa->clearpixel;
+ }
+ }
+ }
+ }
+ else if ((osmesa->format==OSMESA_RGB)||(osmesa->format==OSMESA_BGR)) {
+ GLubyte rval = UNPACK_RED(osmesa->clearpixel);
+ GLubyte gval = UNPACK_GREEN(osmesa->clearpixel);
+ GLubyte bval = UNPACK_BLUE(osmesa->clearpixel);
+ GLint rind = osmesa->rind;
+ GLint gind = osmesa->gind;
+ GLint bind = osmesa->bind;
+ if (all) {
+ GLuint i, n;
+ GLubyte *ptr3 = (GLubyte *) osmesa->buffer;
+ /* Clear whole RGB buffer */
+ n = osmesa->rowlength * osmesa->height;
+ for (i=0;i<n;i++) {
+ ptr3[rind] = rval;
+ ptr3[gind] = gval;
+ ptr3[bind] = bval;
+ ptr3 += 3;
+ }
+ }
+ else {
+ /* Clear part of RGB buffer */
+ GLint i, j;
+ for (i=0;i<height;i++) {
+ GLubyte *ptr3 = PIXELADDR3( x, (y+i) );
+ for (j=0;j<width;j++) {
+ ptr3[rind] = rval;
+ ptr3[gind] = gval;
+ ptr3[bind] = bval;
+ ptr3 += 3;
+ }
+ }
+ }
+ }
+ else {
+ if (all) {
+ /* Clear whole RGBA buffer */
+ GLuint i, n, *ptr4;
+ n = osmesa->rowlength * osmesa->height;
+ ptr4 = (GLuint *) osmesa->buffer;
+ for (i=0;i<n;i++) {
+ *ptr4++ = osmesa->clearpixel;
+ }
+ }
+ else {
+ /* Clear part of RGBA buffer */
+ GLint i, j;
+ for (i=0;i<height;i++) {
+ GLuint *ptr4 = PIXELADDR4( x, (y+i) );
+ for (j=0;j<width;j++) {
+ *ptr4++ = osmesa->clearpixel;
+ }
+ }
+ }
+ }
+ }
+ return mask & (~GL_COLOR_BUFFER_BIT);
+}
+
+
+
+static void set_index( GLcontext *ctx, GLuint index )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ osmesa->pixel = index;
+}
+
+
+
+static void set_color( GLcontext *ctx,
+ GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ osmesa->pixel = PACK_RGBA( r, g, b, a );
+}
+
+
+
+static void buffer_size( GLcontext *ctx, GLuint *width, GLuint *height )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ *width = osmesa->width;
+ *height = osmesa->height;
+}
+
+
+/**********************************************************************/
+/***** Read/write spans/arrays of RGBA pixels *****/
+/**********************************************************************/
+
+/* Write RGBA pixels to an RGBA (or permuted) buffer. */
+static void write_rgba_span( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ CONST GLubyte rgba[][4], const GLubyte mask[] )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLuint *ptr4 = PIXELADDR4( x, y );
+ GLuint i;
+ GLint rshift = osmesa->rshift;
+ GLint gshift = osmesa->gshift;
+ GLint bshift = osmesa->bshift;
+ GLint ashift = osmesa->ashift;
+ if (mask) {
+ for (i=0;i<n;i++,ptr4++) {
+ if (mask[i]) {
+ *ptr4 = PACK_RGBA2( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] );
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++,ptr4++) {
+ *ptr4 = PACK_RGBA2( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] );
+ }
+ }
+}
+
+
+/* Write RGBA pixels to an RGBA buffer. This is the fastest span-writer. */
+static void write_rgba_span_rgba( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ CONST GLubyte rgba[][4],
+ const GLubyte mask[] )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLuint *ptr4 = PIXELADDR4( x, y );
+ const GLuint *rgba4 = (const GLuint *) rgba;
+ GLuint i;
+ if (mask) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ ptr4[i] = rgba4[i];
+ }
+ }
+ }
+ else {
+ MEMCPY( ptr4, rgba4, n * 4 );
+ }
+}
+
+
+/* Write RGB pixels to an RGBA (or permuted) buffer. */
+static void write_rgb_span( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ CONST GLubyte rgb[][3], const GLubyte mask[] )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLuint *ptr4 = PIXELADDR4( x, y );
+ GLuint i;
+ GLint rshift = osmesa->rshift;
+ GLint gshift = osmesa->gshift;
+ GLint bshift = osmesa->bshift;
+ GLint ashift = osmesa->ashift;
+ if (mask) {
+ for (i=0;i<n;i++,ptr4++) {
+ if (mask[i]) {
+ *ptr4 = PACK_RGBA2( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], 255 );
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++,ptr4++) {
+ *ptr4 = PACK_RGBA2( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], 255);
+ }
+ }
+}
+
+
+
+static void write_monocolor_span( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte mask[] )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLuint *ptr4 = PIXELADDR4(x,y);
+ GLuint i;
+ for (i=0;i<n;i++,ptr4++) {
+ if (mask[i]) {
+ *ptr4 = osmesa->pixel;
+ }
+ }
+}
+
+
+
+static void write_rgba_pixels( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ CONST GLubyte rgba[][4], const GLubyte mask[] )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLuint i;
+ GLint rshift = osmesa->rshift;
+ GLint gshift = osmesa->gshift;
+ GLint bshift = osmesa->bshift;
+ GLint ashift = osmesa->ashift;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLuint *ptr4 = PIXELADDR4(x[i],y[i]);
+ *ptr4 = PACK_RGBA2( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] );
+ }
+ }
+}
+
+
+
+static void write_monocolor_pixels( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte mask[] )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLuint *ptr4 = PIXELADDR4(x[i],y[i]);
+ *ptr4 = osmesa->pixel;
+ }
+ }
+}
+
+
+static void read_rgba_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLuint i;
+ GLuint *ptr4 = PIXELADDR4(x,y);
+ for (i=0;i<n;i++) {
+ GLuint pixel = *ptr4++;
+ rgba[i][RCOMP] = UNPACK_RED(pixel);
+ rgba[i][GCOMP] = UNPACK_GREEN(pixel);
+ rgba[i][BCOMP] = UNPACK_BLUE(pixel);
+ rgba[i][ACOMP] = UNPACK_ALPHA(pixel);
+ }
+}
+
+
+/* Read RGBA pixels from an RGBA buffer */
+static void read_rgba_span_rgba( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLuint *ptr4 = PIXELADDR4(x,y);
+ MEMCPY( rgba, ptr4, n * 4 * sizeof(GLubyte) );
+}
+
+
+static void read_rgba_pixels( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[] )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLuint *ptr4 = PIXELADDR4(x[i],y[i]);
+ GLuint pixel = *ptr4;
+ rgba[i][RCOMP] = UNPACK_RED(pixel);
+ rgba[i][GCOMP] = UNPACK_GREEN(pixel);
+ rgba[i][BCOMP] = UNPACK_BLUE(pixel);
+ rgba[i][ACOMP] = UNPACK_ALPHA(pixel);
+ }
+ }
+}
+
+/**********************************************************************/
+/***** 3 byte RGB pixel support funcs *****/
+/**********************************************************************/
+
+/* Write RGBA pixels to an RGB or BGR buffer. */
+static void write_rgba_span3( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ CONST GLubyte rgba[][4], const GLubyte mask[] )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLubyte *ptr3 = PIXELADDR3( x, y);
+ GLuint i;
+ GLint rind = osmesa->rind;
+ GLint gind = osmesa->gind;
+ GLint bind = osmesa->bind;
+ if (mask) {
+ for (i=0;i<n;i++,ptr3+=3) {
+ if (mask[i]) {
+ ptr3[rind] = rgba[i][RCOMP];
+ ptr3[gind] = rgba[i][GCOMP];
+ ptr3[bind] = rgba[i][BCOMP];
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++,ptr3+=3) {
+ ptr3[rind] = rgba[i][RCOMP];
+ ptr3[gind] = rgba[i][GCOMP];
+ ptr3[bind] = rgba[i][BCOMP];
+ }
+ }
+}
+
+/* Write RGB pixels to an RGB or BGR buffer. */
+static void write_rgb_span3( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ CONST GLubyte rgb[][3], const GLubyte mask[] )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLubyte *ptr3 = PIXELADDR3( x, y);
+ GLuint i;
+ GLint rind = osmesa->rind;
+ GLint gind = osmesa->gind;
+ GLint bind = osmesa->bind;
+ if (mask) {
+ for (i=0;i<n;i++,ptr3+=3) {
+ if (mask[i]) {
+ ptr3[rind] = rgb[i][RCOMP];
+ ptr3[gind] = rgb[i][GCOMP];
+ ptr3[bind] = rgb[i][BCOMP];
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++,ptr3+=3) {
+ ptr3[rind] = rgb[i][RCOMP];
+ ptr3[gind] = rgb[i][GCOMP];
+ ptr3[bind] = rgb[i][BCOMP];
+ }
+ }
+}
+
+
+static void write_monocolor_span3( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte mask[] )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+
+ GLubyte rval = UNPACK_RED(osmesa->pixel);
+ GLubyte gval = UNPACK_GREEN(osmesa->pixel);
+ GLubyte bval = UNPACK_BLUE(osmesa->pixel);
+ GLint rind = osmesa->rind;
+ GLint gind = osmesa->gind;
+ GLint bind = osmesa->bind;
+
+
+ GLubyte *ptr3 = PIXELADDR3( x, y);
+ GLuint i;
+ for (i=0;i<n;i++,ptr3+=3) {
+ if (mask[i]) {
+ ptr3[rind] = rval;
+ ptr3[gind] = gval;
+ ptr3[bind] = bval;
+ }
+ }
+}
+
+static void write_rgba_pixels3( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ CONST GLubyte rgba[][4], const GLubyte mask[] )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLuint i;
+ GLint rind = osmesa->rind;
+ GLint gind = osmesa->gind;
+ GLint bind = osmesa->bind;
+
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLubyte *ptr3 = PIXELADDR3(x[i],y[i]);
+ ptr3[rind] = rgba[i][RCOMP];
+ ptr3[gind] = rgba[i][GCOMP];
+ ptr3[bind] = rgba[i][BCOMP];
+ }
+ }
+}
+
+static void write_monocolor_pixels3( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte mask[] )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLuint i;
+ GLint rind = osmesa->rind;
+ GLint gind = osmesa->gind;
+ GLint bind = osmesa->bind;
+ GLubyte rval = UNPACK_RED(osmesa->pixel);
+ GLubyte gval = UNPACK_GREEN(osmesa->pixel);
+ GLubyte bval = UNPACK_BLUE(osmesa->pixel);
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLubyte *ptr3 = PIXELADDR3(x[i],y[i]);
+ ptr3[rind] = rval;
+ ptr3[gind] = gval;
+ ptr3[bind] = bval;
+ }
+ }
+}
+
+static void read_rgba_span3( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLuint i;
+ GLint rind = osmesa->rind;
+ GLint gind = osmesa->gind;
+ GLint bind = osmesa->bind;
+ GLubyte *ptr3 = PIXELADDR3( x, y);
+ for (i=0;i<n;i++,ptr3+=3) {
+ rgba[i][RCOMP] = ptr3[rind];
+ rgba[i][GCOMP] = ptr3[gind];
+ rgba[i][BCOMP] = ptr3[bind];
+ rgba[i][ACOMP] = 0;
+ }
+}
+
+static void read_rgba_pixels3( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[] )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLuint i;
+ GLint rind = osmesa->rind;
+ GLint gind = osmesa->gind;
+ GLint bind = osmesa->bind;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLubyte *ptr3 = PIXELADDR3(x[i],y[i]);
+ rgba[i][RCOMP] = ptr3[rind];
+ rgba[i][GCOMP] = ptr3[gind];
+ rgba[i][BCOMP] = ptr3[bind];
+ rgba[i][ACOMP] = 0;
+ }
+ }
+}
+
+
+/**********************************************************************/
+/***** Read/write spans/arrays of CI pixels *****/
+/**********************************************************************/
+
+/* Write 32-bit color index to buffer */
+static void write_index32_span( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLuint index[], const GLubyte mask[] )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLubyte *ptr1 = PIXELADDR1(x,y);
+ GLuint i;
+ if (mask) {
+ for (i=0;i<n;i++,ptr1++) {
+ if (mask[i]) {
+ *ptr1 = (GLubyte) index[i];
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++,ptr1++) {
+ *ptr1 = (GLubyte) index[i];
+ }
+ }
+}
+
+
+/* Write 8-bit color index to buffer */
+static void write_index8_span( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte index[], const GLubyte mask[] )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLubyte *ptr1 = PIXELADDR1(x,y);
+ GLuint i;
+ if (mask) {
+ for (i=0;i<n;i++,ptr1++) {
+ if (mask[i]) {
+ *ptr1 = (GLubyte) index[i];
+ }
+ }
+ }
+ else {
+ MEMCPY( ptr1, index, n );
+ }
+}
+
+
+static void write_monoindex_span( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte mask[] )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLubyte *ptr1 = PIXELADDR1(x,y);
+ GLuint i;
+ for (i=0;i<n;i++,ptr1++) {
+ if (mask[i]) {
+ *ptr1 = (GLubyte) osmesa->pixel;
+ }
+ }
+}
+
+
+static void write_index_pixels( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLuint index[], const GLubyte mask[] )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLubyte *ptr1 = PIXELADDR1(x[i],y[i]);
+ *ptr1 = (GLubyte) index[i];
+ }
+ }
+}
+
+
+static void write_monoindex_pixels( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte mask[] )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLubyte *ptr1 = PIXELADDR1(x[i],y[i]);
+ *ptr1 = (GLubyte) osmesa->pixel;
+ }
+ }
+}
+
+
+static void read_index_span( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLuint index[] )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLuint i;
+ GLubyte *ptr1 = PIXELADDR1(x,y);
+ for (i=0;i<n;i++,ptr1++) {
+ index[i] = (GLuint) *ptr1;
+ }
+}
+
+
+static void read_index_pixels( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint index[], const GLubyte mask[] )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ if (mask[i] ) {
+ GLubyte *ptr1 = PIXELADDR1(x[i],y[i]);
+ index[i] = (GLuint) *ptr1;
+ }
+ }
+}
+
+
+
+/**********************************************************************/
+/***** Optimized line rendering *****/
+/**********************************************************************/
+
+
+/*
+ * Draw a flat-shaded, RGB line into an osmesa buffer.
+ */
+static void flat_rgba_line( GLcontext *ctx,
+ GLuint vert0, GLuint vert1, GLuint pvert )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLubyte *color = ctx->VB->ColorPtr->data[pvert];
+ unsigned long pixel = PACK_RGBA( color[0], color[1], color[2], color[3] );
+
+#define INTERP_XY 1
+#define CLIP_HACK 1
+#define PLOT(X,Y) { GLuint *ptr4 = PIXELADDR4(X,Y); *ptr4 = pixel; }
+
+#ifdef WIN32
+#include "..\linetemp.h"
+#else
+#include "linetemp.h"
+#endif
+}
+
+
+/*
+ * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer.
+ */
+static void flat_rgba_z_line( GLcontext *ctx,
+ GLuint vert0, GLuint vert1, GLuint pvert )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLubyte *color = ctx->VB->ColorPtr->data[pvert];
+ unsigned long pixel = PACK_RGBA( color[0], color[1], color[2], color[3] );
+
+#define INTERP_XY 1
+#define INTERP_Z 1
+#define CLIP_HACK 1
+#define PLOT(X,Y) \
+ if (Z < *zPtr) { \
+ GLuint *ptr4 = PIXELADDR4(X,Y); \
+ *ptr4 = pixel; \
+ *zPtr = Z; \
+ }
+
+#ifdef WIN32
+#include "..\linetemp.h"
+#else
+#include "linetemp.h"
+#endif
+}
+
+
+/*
+ * Draw a flat-shaded, alpha-blended, RGB line into an osmesa buffer.
+ */
+static void flat_blend_rgba_line( GLcontext *ctx,
+ GLuint vert0, GLuint vert1, GLuint pvert )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ struct vertex_buffer *VB = ctx->VB;
+ GLint rshift = osmesa->rshift;
+ GLint gshift = osmesa->gshift;
+ GLint bshift = osmesa->bshift;
+ GLint avalue = VB->ColorPtr->data[pvert][3];
+ GLint msavalue = 255 - avalue;
+ GLint rvalue = VB->ColorPtr->data[pvert][0]*avalue;
+ GLint gvalue = VB->ColorPtr->data[pvert][1]*avalue;
+ GLint bvalue = VB->ColorPtr->data[pvert][2]*avalue;
+
+#define INTERP_XY 1
+#define CLIP_HACK 1
+#define PLOT(X,Y) \
+ { GLuint *ptr4 = PIXELADDR4(X,Y); \
+ GLuint pixel = 0; \
+ pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift);\
+ pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift);\
+ pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift);\
+ *ptr4 = pixel; \
+ }
+
+#ifdef WIN32
+#include "..\linetemp.h"
+#else
+#include "linetemp.h"
+#endif
+}
+
+/*
+ * Draw a flat-shaded, Z-less, alpha-blended, RGB line into an osmesa buffer.
+ */
+static void flat_blend_rgba_z_line( GLcontext *ctx,
+ GLuint vert0, GLuint vert1, GLuint pvert )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ struct vertex_buffer *VB = ctx->VB;
+ GLint rshift = osmesa->rshift;
+ GLint gshift = osmesa->gshift;
+ GLint bshift = osmesa->bshift;
+ GLint avalue = VB->ColorPtr->data[pvert][3];
+ GLint msavalue = 256 - avalue;
+ GLint rvalue = VB->ColorPtr->data[pvert][0]*avalue;
+ GLint gvalue = VB->ColorPtr->data[pvert][1]*avalue;
+ GLint bvalue = VB->ColorPtr->data[pvert][2]*avalue;
+
+#define INTERP_XY 1
+#define INTERP_Z 1
+#define CLIP_HACK 1
+#define PLOT(X,Y) \
+ if (Z < *zPtr) { \
+ { GLuint *ptr4 = PIXELADDR4(X,Y); \
+ GLuint pixel = 0; \
+ pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift);\
+ pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift);\
+ pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift);\
+ *ptr4 = pixel; \
+ } \
+ }
+
+#ifdef WIN32
+#include "..\linetemp.h"
+#else
+#include "linetemp.h"
+#endif
+}
+
+/*
+ * Draw a flat-shaded, Z-less, alpha-blended, RGB line into an osmesa buffer.
+ */
+static void flat_blend_rgba_z_line_write( GLcontext *ctx,
+ GLuint vert0, GLuint vert1, GLuint pvert )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ struct vertex_buffer *VB = ctx->VB;
+ GLint rshift = osmesa->rshift;
+ GLint gshift = osmesa->gshift;
+ GLint bshift = osmesa->bshift;
+ GLint avalue = VB->ColorPtr->data[pvert][3];
+ GLint msavalue = 256 - avalue;
+ GLint rvalue = VB->ColorPtr->data[pvert][0]*avalue;
+ GLint gvalue = VB->ColorPtr->data[pvert][1]*avalue;
+ GLint bvalue = VB->ColorPtr->data[pvert][2]*avalue;
+
+#define INTERP_XY 1
+#define INTERP_Z 1
+#define CLIP_HACK 1
+#define PLOT(X,Y) \
+ if (Z < *zPtr) { \
+ { GLuint *ptr4 = PIXELADDR4(X,Y); \
+ GLuint pixel = 0; \
+ pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift);\
+ pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift);\
+ pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift);\
+ *ptr4 = pixel; \
+ } \
+ *zPtr = Z; \
+ }
+
+#ifdef WIN32
+#include "..\linetemp.h"
+#else
+#include "linetemp.h"
+#endif
+}
+
+
+/*
+ * Analyze context state to see if we can provide a fast line drawing
+ * function, like those in lines.c. Otherwise, return NULL.
+ */
+static line_func choose_line_function( GLcontext *ctx )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+
+ if (ctx->Line.SmoothFlag) return NULL;
+ if (ctx->Texture.Enabled) return NULL;
+ if (ctx->Light.ShadeModel!=GL_FLAT) return NULL;
+
+ if (ctx->Line.Width==1.0F
+ && ctx->Line.StippleFlag==GL_FALSE) {
+
+ if (ctx->RasterMask==DEPTH_BIT
+ && ctx->Depth.Func==GL_LESS
+ && ctx->Depth.Mask==GL_TRUE) {
+ switch(osmesa->format) {
+ case OSMESA_RGBA:
+ case OSMESA_BGRA:
+ case OSMESA_ARGB:
+ return flat_rgba_z_line;
+ default:
+ return NULL;
+ }
+ }
+
+ if (ctx->RasterMask==0) {
+ switch(osmesa->format) {
+ case OSMESA_RGBA:
+ case OSMESA_BGRA:
+ case OSMESA_ARGB:
+ return flat_rgba_line;
+ default:
+ return NULL;
+ }
+ }
+
+ if (ctx->RasterMask==(DEPTH_BIT|BLEND_BIT)
+ && ctx->Depth.Func==GL_LESS
+ && ctx->Depth.Mask==GL_TRUE
+ && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA
+ && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA
+ && ctx->Color.BlendSrcA==GL_SRC_ALPHA
+ && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA
+ && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
+ switch(osmesa->format) {
+ case OSMESA_RGBA:
+ case OSMESA_BGRA:
+ case OSMESA_ARGB:
+ return flat_blend_rgba_z_line_write;
+ default:
+ return NULL;
+ }
+ }
+
+ if (ctx->RasterMask==(DEPTH_BIT|BLEND_BIT)
+ && ctx->Depth.Func==GL_LESS
+ && ctx->Depth.Mask==GL_FALSE
+ && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA
+ && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA
+ && ctx->Color.BlendSrcA==GL_SRC_ALPHA
+ && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA
+ && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
+ switch(osmesa->format) {
+ case OSMESA_RGBA:
+ case OSMESA_BGRA:
+ case OSMESA_ARGB:
+ return flat_blend_rgba_z_line;
+ default:
+ return NULL;
+ }
+ }
+
+ if (ctx->RasterMask==BLEND_BIT
+ && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA
+ && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA
+ && ctx->Color.BlendSrcA==GL_SRC_ALPHA
+ && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA
+ && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
+ switch(osmesa->format) {
+ case OSMESA_RGBA:
+ case OSMESA_BGRA:
+ case OSMESA_ARGB:
+ return flat_blend_rgba_line;
+ default:
+ return NULL;
+ }
+ }
+
+ }
+ return NULL;
+}
+
+
+/**********************************************************************/
+/***** Optimized triangle rendering *****/
+/**********************************************************************/
+
+
+/*
+ * Smooth-shaded, z-less triangle, RGBA color.
+ */
+static void smooth_rgba_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+ GLint rshift = osmesa->rshift;
+ GLint gshift = osmesa->gshift;
+ GLint bshift = osmesa->bshift;
+ GLint ashift = osmesa->ashift;
+ (void) pv;
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define INTERP_ALPHA 1
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+{ \
+ GLint i, len = RIGHT-LEFT; \
+ GLuint *img = PIXELADDR4(LEFT,Y); \
+ for (i=0;i<len;i++,img++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ *img = PACK_RGBA2( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb), FixedToInt(ffa) ); \
+ zRow[i] = z; \
+ } \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; ffa += fdadx;\
+ ffz += fdzdx; \
+ } \
+}
+#ifdef WIN32
+#include "..\tritemp.h"
+#else
+#include "tritemp.h"
+#endif
+}
+
+
+
+
+/*
+ * Flat-shaded, z-less triangle, RGBA color.
+ */
+static void flat_rgba_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define SETUP_CODE \
+ GLubyte r = VB->ColorPtr->data[pv][0]; \
+ GLubyte g = VB->ColorPtr->data[pv][1]; \
+ GLubyte b = VB->ColorPtr->data[pv][2]; \
+ GLubyte a = VB->ColorPtr->data[pv][3]; \
+ GLuint pixel = PACK_RGBA(r,g,b,a);
+
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+{ \
+ GLint i, len = RIGHT-LEFT; \
+ GLuint *img = PIXELADDR4(LEFT,Y); \
+ for (i=0;i<len;i++,img++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ *img = pixel; \
+ zRow[i] = z; \
+ } \
+ ffz += fdzdx; \
+ } \
+}
+#ifdef WIN32
+#include "..\tritemp.h"
+#else
+#include "tritemp.h"
+#endif
+}
+
+
+
+/*
+ * Return pointer to an accelerated triangle function if possible.
+ */
+static triangle_func choose_triangle_function( GLcontext *ctx )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+
+ if ((osmesa->format==OSMESA_RGB)||(osmesa->format==OSMESA_BGR)) return NULL;
+
+ if (ctx->Polygon.SmoothFlag) return NULL;
+ if (ctx->Polygon.StippleFlag) return NULL;
+ if (ctx->Texture.Enabled) return NULL;
+
+ if (ctx->RasterMask==DEPTH_BIT
+ && ctx->Depth.Func==GL_LESS
+ && ctx->Depth.Mask==GL_TRUE
+ && osmesa->format!=OSMESA_COLOR_INDEX) {
+ if (ctx->Light.ShadeModel==GL_SMOOTH) {
+ return smooth_rgba_z_triangle;
+ }
+ else {
+ return flat_rgba_z_triangle;
+ }
+ }
+ return NULL;
+}
+
+
+
+static const GLubyte *get_string( GLcontext *ctx, GLenum name )
+{
+ (void) ctx;
+ switch (name) {
+ case GL_RENDERER:
+ return (const GLubyte *) "Mesa OffScreen";
+ default:
+ return NULL;
+ }
+}
+
+
+static void osmesa_update_state( GLcontext *ctx )
+{
+ OSMesaContext osmesa = (OSMesaContext) ctx->DriverCtx;
+
+ ctx->Driver.GetString = get_string;
+ ctx->Driver.UpdateState = osmesa_update_state;
+
+ ctx->Driver.SetBuffer = set_buffer;
+ ctx->Driver.Color = set_color;
+ ctx->Driver.Index = set_index;
+ ctx->Driver.ClearIndex = clear_index;
+ ctx->Driver.ClearColor = clear_color;
+ ctx->Driver.Clear = clear;
+
+ ctx->Driver.GetBufferSize = buffer_size;
+
+ ctx->Driver.PointsFunc = NULL;
+ ctx->Driver.LineFunc = choose_line_function( ctx );
+ ctx->Driver.TriangleFunc = choose_triangle_function( ctx );
+
+
+ /* RGB(A) span/pixel functions */
+ if ((osmesa->format==OSMESA_RGB) || (osmesa->format==OSMESA_BGR)) {
+ /* 3 bytes / pixel in frame buffer */
+ ctx->Driver.WriteRGBASpan = write_rgba_span3;
+ ctx->Driver.WriteRGBSpan = write_rgb_span3;
+ ctx->Driver.WriteRGBAPixels = write_rgba_pixels3;
+ ctx->Driver.WriteMonoRGBASpan = write_monocolor_span3;
+ ctx->Driver.WriteMonoRGBAPixels = write_monocolor_pixels3;
+ ctx->Driver.ReadRGBASpan = read_rgba_span3;
+ ctx->Driver.ReadRGBAPixels = read_rgba_pixels3;
+ }
+ else {
+ /* 4 bytes / pixel in frame buffer */
+ if (osmesa->format==OSMESA_RGBA
+ && RCOMP==0 && GCOMP==1 && BCOMP==2 && ACOMP==3)
+ ctx->Driver.WriteRGBASpan = write_rgba_span_rgba;
+ else
+ ctx->Driver.WriteRGBASpan = write_rgba_span;
+ ctx->Driver.WriteRGBSpan = write_rgb_span;
+ ctx->Driver.WriteRGBAPixels = write_rgba_pixels;
+ ctx->Driver.WriteMonoRGBASpan = write_monocolor_span;
+ ctx->Driver.WriteMonoRGBAPixels = write_monocolor_pixels;
+ if (osmesa->format==OSMESA_RGBA
+ && RCOMP==0 && GCOMP==1 && BCOMP==2 && ACOMP==3)
+ ctx->Driver.ReadRGBASpan = read_rgba_span_rgba;
+ else
+ ctx->Driver.ReadRGBASpan = read_rgba_span;
+ ctx->Driver.ReadRGBAPixels = read_rgba_pixels;
+ }
+
+ /* CI span/pixel functions */
+ ctx->Driver.WriteCI32Span = write_index32_span;
+ ctx->Driver.WriteCI8Span = write_index8_span;
+ ctx->Driver.WriteMonoCISpan = write_monoindex_span;
+ ctx->Driver.WriteCI32Pixels = write_index_pixels;
+ ctx->Driver.WriteMonoCIPixels = write_monoindex_pixels;
+ ctx->Driver.ReadCI32Span = read_index_span;
+ ctx->Driver.ReadCI32Pixels = read_index_pixels;
+}
diff --git a/src/mesa/drivers/svga/svgamesa.c b/src/mesa/drivers/svga/svgamesa.c
new file mode 100644
index 0000000000..4c4d9f793e
--- /dev/null
+++ b/src/mesa/drivers/svga/svgamesa.c
@@ -0,0 +1,540 @@
+/* $Id: svgamesa.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.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.
+ */
+
+
+
+/*
+ * Linux SVGA/Mesa interface.
+ *
+ * This interface is not finished! Still have to implement pixel
+ * reading functions and double buffering. Then, look into accelerated
+ * line and polygon rendering. And, clean up a bunch of other stuff.
+ * Any volunteers?
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#ifdef SVGA
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include <vga.h>
+#include "GL/svgamesa.h"
+#include "context.h"
+#include "matrix.h"
+#include "types.h"
+#endif
+
+
+struct svgamesa_context {
+ GLcontext *gl_ctx; /* the core Mesa context */
+ GLvisual *gl_vis; /* describes the color buffer */
+ GLframebuffer *gl_buffer; /* the ancillary buffers */
+ GLuint index; /* current color index */
+ GLint red, green, blue; /* current rgb color */
+ GLint width, height; /* size of color buffer */
+ GLint depth; /* bits per pixel (8,16,24 or 32) */
+};
+
+
+static SVGAMesaContext SVGAMesa = NULL; /* the current context */
+
+
+
+/*
+ * Convert Mesa window Y coordinate to VGA screen Y coordinate:
+ */
+#define FLIP(Y) (SVGAMesa->height-(Y)-1)
+
+
+
+/**********************************************************************/
+/***** Miscellaneous functions *****/
+/**********************************************************************/
+
+
+static void get_buffer_size( GLcontext *ctx, GLuint *width, GLuint *height )
+{
+ *width = SVGAMesa->width = vga_getxdim();
+ *height = SVGAMesa->height = vga_getydim();
+}
+
+
+/* Set current color index */
+static void set_index( GLcontext *ctx, GLuint index )
+{
+ SVGAMesa->index = index;
+ vga_setcolor( index );
+}
+
+
+/* Set current drawing color */
+static void set_color( GLcontext *ctx,
+ GLubyte red, GLubyte green,
+ GLubyte blue, GLubyte alpha )
+{
+ SVGAMesa->red = red;
+ SVGAMesa->green = green;
+ SVGAMesa->blue = blue;
+ vga_setrgbcolor( red, green, blue );
+}
+
+
+static void clear_index( GLcontext *ctx, GLuint index )
+{
+ /* TODO: Implements glClearIndex() */
+}
+
+
+static void clear_color( GLcontext *ctx,
+ GLubyte red, GLubyte green,
+ GLubyte blue, GLubyte alpha )
+{
+ /* TODO: Implements glClearColor() */
+}
+
+
+static GLbitfield clear( GLcontext *ctx, GLbitfield mask, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height )
+{
+ if (mask & GL_COLOR_BUFFER_BIT) {
+ vga_clear();
+ }
+ return mask & (~GL_COLOR_BUFFER_BIT);
+}
+
+
+static GLboolean set_buffer( GLcontext *ctx, GLenum buffer )
+{
+ /* TODO: implement double buffering and use this function to select */
+ /* between front and back buffers. */
+ if (buffer == GL_FRONT_LEFT)
+ return GL_TRUE;
+ else if (buffer == GL_BACK_LEFT)
+ return GL_TRUE;
+ else
+ return GL_FALSE;
+}
+
+
+
+
+/**********************************************************************/
+/***** Write spans of pixels *****/
+/**********************************************************************/
+
+
+static void write_ci32_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLuint index[], const GLubyte mask[] )
+{
+ int i;
+ y = FLIP(y);
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ vga_setcolor( index[i] );
+ vga_drawpixel( x, y );
+ }
+ }
+}
+
+static void write_ci8_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLubyte index[], const GLubyte mask[] )
+{
+ int i;
+ y = FLIP(y);
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ vga_setcolor( index[i] );
+ vga_drawpixel( x, y );
+ }
+ }
+}
+
+
+
+static void write_mono_ci_span( const GLcontext *ctx, GLuint n,
+ GLint x, GLint y, const GLubyte mask[] )
+{
+ int i;
+ y = FLIP(y);
+ /* use current color index */
+ vga_setcolor( SVGAMesa->index );
+ for (i=0;i<n;i++,x++) {
+ if (mask[i]) {
+ vga_drawpixel( x, y );
+ }
+ }
+}
+
+
+
+static void write_rgba_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4], const GLubyte mask[] )
+{
+ int i;
+ y=FLIP(y);
+ if (mask) {
+ /* draw some pixels */
+ for (i=0; i<n; i++, x++) {
+ if (mask[i]) {
+ vga_setrgbcolor( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ vga_drawpixel( x, y );
+ }
+ }
+ }
+ else {
+ /* draw all pixels */
+ for (i=0; i<n; i++, x++) {
+ vga_setrgbcolor( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ vga_drawpixel( x, y );
+ }
+ }
+}
+
+
+
+static void write_mono_rgba_span( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte mask[])
+{
+ int i;
+ y=FLIP(y);
+ /* use current rgb color */
+ vga_setrgbcolor( SVGAMesa->red, SVGAMesa->green, SVGAMesa->blue );
+ for (i=0; i<n; i++, x++) {
+ if (mask[i]) {
+ vga_drawpixel( x, y );
+ }
+ }
+}
+
+
+
+/**********************************************************************/
+/***** Read spans of pixels *****/
+/**********************************************************************/
+
+
+static void read_ci32_span( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLuint index[])
+{
+ int i;
+ y = FLIP(y);
+ for (i=0; i<n; i++,x++) {
+ index[i] = vga_getpixel( x, y );
+ }
+}
+
+
+
+static void read_rgba_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ int i;
+ for (i=0; i<n; i++, x++) {
+ /* TODO */
+ }
+}
+
+
+
+/**********************************************************************/
+/***** Write arrays of pixels *****/
+/**********************************************************************/
+
+
+static void write_ci32_pixels( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLuint index[], const GLubyte mask[] )
+{
+ int i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ vga_setcolor( index[i] );
+ vga_drawpixel( x[i], FLIP(y[i]) );
+ }
+ }
+}
+
+
+static void write_mono_ci_pixels( const GLcontext *ctx, GLuint n,
+ const GLint x[], const GLint y[],
+ const GLubyte mask[] )
+{
+ int i;
+ /* use current color index */
+ vga_setcolor( SVGAMesa->index );
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ vga_drawpixel( x[i], FLIP(y[i]) );
+ }
+ }
+}
+
+
+
+static void write_rgba_pixels( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte rgba[][4], const GLubyte mask[] )
+{
+ int i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ vga_setrgbcolor( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ vga_drawpixel( x[i], FLIP(y[i]) );
+ }
+ }
+}
+
+
+
+static void write_mono_rgba_pixels( const GLcontext *ctx,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLubyte mask[] )
+{
+ int i;
+ /* use current rgb color */
+ vga_setrgbcolor( SVGAMesa->red, SVGAMesa->green, SVGAMesa->blue );
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ vga_drawpixel( x[i], FLIP(y[i]) );
+ }
+ }
+}
+
+
+
+
+/**********************************************************************/
+/***** Read arrays of pixels *****/
+/**********************************************************************/
+
+/* Read an array of color index pixels. */
+static void read_ci32_pixels( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint index[], const GLubyte mask[] )
+{
+ int i;
+ for (i=0; i<n; i++,x++) {
+ index[i] = vga_getpixel( x[i], FLIP(y[i]) );
+ }
+}
+
+
+
+static void read_rgba_pixels( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[] )
+{
+ /* TODO */
+}
+
+
+
+static void svgamesa_update_state( GLcontext *ctx )
+{
+ /* Initialize all the pointers in the DD struct. Do this whenever */
+ /* a new context is made current or we change buffers via set_buffer! */
+
+ ctx->Driver.UpdateState = svgamesa_update_state;
+
+ ctx->Driver.ClearIndex = clear_index;
+ ctx->Driver.ClearColor = clear_color;
+ ctx->Driver.Clear = clear;
+
+ ctx->Driver.Index = set_index;
+ ctx->Driver.Color = set_color;
+
+ ctx->Driver.SetBuffer = set_buffer;
+ ctx->Driver.GetBufferSize = get_buffer_size;
+
+ ctx->Driver.PointsFunc = NULL;
+ ctx->Driver.LineFunc = NULL;
+ ctx->Driver.TriangleFunc = NULL;
+
+ /* Pixel/span writing functions: */
+ /* TODO: use different funcs for 8, 16, 32-bit depths */
+ ctx->Driver.WriteRGBASpan = write_rgba_span;
+ ctx->Driver.WriteMonoRGBASpan = write_mono_rgba_span;
+ ctx->Driver.WriteRGBAPixels = write_rgba_pixels;
+ ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels;
+ ctx->Driver.WriteCI32Span = write_ci32_span;
+ ctx->Driver.WriteCI8Span = write_ci8_span;
+ ctx->Driver.WriteMonoCISpan = write_mono_ci_span;
+ ctx->Driver.WriteCI32Pixels = write_ci32_pixels;
+ ctx->Driver.WriteMonoCIPixels = write_mono_ci_pixels;
+
+ /* Pixel/span reading functions: */
+ /* TODO: use different funcs for 8, 16, 32-bit depths */
+ ctx->Driver.ReadCI32Span = read_ci32_span;
+ ctx->Driver.ReadRGBASpan = read_rgba_span;
+ ctx->Driver.ReadCI32Pixels = read_ci32_pixels;
+ ctx->Driver.ReadRGBAPixels = read_rgba_pixels;
+}
+
+
+
+/*
+ * Create a new VGA/Mesa context and return a handle to it.
+ */
+SVGAMesaContext SVGAMesaCreateContext( GLboolean doubleBuffer )
+{
+ SVGAMesaContext ctx;
+ GLboolean rgb_flag;
+ GLfloat redscale, greenscale, bluescale, alphascale;
+ GLboolean alpha_flag = GL_FALSE;
+ int colors;
+ GLint index_bits;
+ GLint redbits, greenbits, bluebits, alphabits;
+
+ /* determine if we're in RGB or color index mode */
+ colors = vga_getcolors();
+ if (colors==32768) {
+ rgb_flag = GL_TRUE;
+ redscale = greenscale = bluescale = alphascale = 255.0;
+ redbits = greenbits = bluebits = 8;
+ alphabits = 0;
+ index_bits = 0;
+ }
+ else if (colors==256) {
+ rgb_flag = GL_FALSE;
+ redscale = greenscale = bluescale = alphascale = 0.0;
+ redbits = greenbits = bluebits = alphabits = 0;
+ index_bits = 8;
+ }
+ else {
+ printf(">16 bit color not implemented yet!\n");
+ return NULL;
+ }
+
+ ctx = (SVGAMesaContext) calloc( 1, sizeof(struct svgamesa_context) );
+ if (!ctx) {
+ return NULL;
+ }
+
+ ctx->gl_vis = gl_create_visual( rgb_flag,
+ alpha_flag,
+ doubleBuffer,
+ GL_FALSE, /* stereo */
+ 16, /* depth_size */
+ 8, /* stencil_size */
+ 16, /* accum_size */
+ index_bits,
+ redbits, greenbits,
+ bluebits, alphabits );
+
+ ctx->gl_ctx = gl_create_context( ctx->gl_vis,
+ NULL, /* share list context */
+ (void *) ctx, GL_TRUE );
+
+ ctx->gl_buffer = gl_create_framebuffer( ctx->gl_vis );
+
+ ctx->index = 1;
+ ctx->red = ctx->green = ctx->blue = 255;
+
+ ctx->width = ctx->height = 0; /* temporary until first "make-current" */
+
+ return ctx;
+}
+
+
+
+
+/*
+ * Destroy the given VGA/Mesa context.
+ */
+void SVGAMesaDestroyContext( SVGAMesaContext ctx )
+{
+ if (ctx) {
+ gl_destroy_visual( ctx->gl_vis );
+ gl_destroy_context( ctx->gl_ctx );
+ gl_destroy_framebuffer( ctx->gl_buffer );
+ free( ctx );
+ if (ctx==SVGAMesa) {
+ SVGAMesa = NULL;
+ }
+ }
+}
+
+
+
+/*
+ * Make the specified VGA/Mesa context the current one.
+ */
+void SVGAMesaMakeCurrent( SVGAMesaContext ctx )
+{
+ SVGAMesa = ctx;
+ svgamesa_update_state( ctx->gl_ctx );
+ gl_make_current( ctx->gl_ctx, ctx->gl_buffer );
+
+ if (ctx->width==0 || ctx->height==0) {
+ /* setup initial viewport */
+ ctx->width = vga_getxdim();
+ ctx->height = vga_getydim();
+ gl_Viewport( ctx->gl_ctx, 0, 0, ctx->width, ctx->height );
+ }
+}
+
+
+
+/*
+ * Return a handle to the current VGA/Mesa context.
+ */
+SVGAMesaContext SVGAMesaGetCurrentContext( void )
+{
+ return SVGAMesa;
+}
+
+
+/*
+ * Swap front/back buffers for current context if double buffered.
+ */
+void SVGAMesaSwapBuffers( void )
+{
+ FLUSH_VB( SVGAMesa->gl_ctx, "swap buffers" );
+ if (SVGAMesa->gl_vis->DBflag) {
+ vga_flip();
+ }
+}
+
+
+#else
+
+/*
+ * Need this to provide at least one external definition when SVGA is
+ * not defined on the compiler command line.
+ */
+
+int gl_svga_dummy_function(void)
+{
+ return 0;
+}
+
+#endif /*SVGA*/
+
diff --git a/src/mesa/drivers/windows/colors.h b/src/mesa/drivers/windows/colors.h
new file mode 100644
index 0000000000..40ead3040f
--- /dev/null
+++ b/src/mesa/drivers/windows/colors.h
@@ -0,0 +1,499 @@
+/* File name : colors.h
+ * Version : 2.3
+ *
+ * Header file for display driver for Mesa 2.3 under
+ * Windows95 and WindowsNT
+ * This file defines macros and global variables needed
+ * for converting color format
+ *
+ * Copyright (C) 1996- Li Wei
+ * Address : Institute of Artificial Intelligence
+ * : & Robotics
+ * : Xi'an Jiaotong University
+ * Email : liwei@aiar.xjtu.edu.cn
+ * Web page : http://sun.aiar.xjtu.edu.cn
+ *
+ * This file and its associations are partially based on the
+ * Windows NT driver for Mesa, written by Mark Leaming
+ * (mark@rsinc.com).
+ */
+
+/* $Log: ddcolors.h 1997/6/14 by Li Wei(liwei@aiar.xjtu.edu.cn)
+ * Macros for pixel format defined
+ */
+
+/*
+ * $Log: colors.h,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 1.2 1999/01/03 03:08:57 brianp
+ * Ted Jump's changes
+ *
+ * Revision 1.1 1999/01/03 03:08:12 brianp
+ * Initial revision
+ *
+ * Revision 2.0.2 1997/4/30 15:58:00 CST by Li Wei(liwei@aiar.xjtu.edu.cn)
+ * Add LUTs need for dithering
+ */
+
+/*
+ * $Log: colors.h,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 1.2 1999/01/03 03:08:57 brianp
+ * Ted Jump's changes
+ *
+ * Revision 1.1 1999/01/03 03:08:12 brianp
+ * Initial revision
+ *
+ * Revision 2.0.1 1997/4/29 15:52:00 CST by Li Wei(liwei@aiar.xjtu.edu.cn)
+ * Add BGR8 Macro
+ */
+
+/*
+ * $Log: colors.h,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 1.2 1999/01/03 03:08:57 brianp
+ * Ted Jump's changes
+ *
+ * Revision 1.1 1999/01/03 03:08:12 brianp
+ * Initial revision
+ *
+ * Revision 2.0 1996/11/15 10:55:00 CST by Li Wei(liwei@aiar.xjtu.edu.cn)
+ * Initial revision
+ */
+/* Values for wmesa->pixelformat: */
+
+#define PF_8A8B8G8R 3 /* 32-bit TrueColor: 8-A, 8-B, 8-G, 8-R */
+#define PF_8R8G8B 4 /* 32-bit TrueColor: 8-R, 8-G, 8-B */
+#define PF_5R6G5B 5 /* 16-bit TrueColor: 5-R, 6-G, 5-B bits */
+#define PF_DITHER8 6 /* Dithered RGB using a lookup table */
+#define PF_LOOKUP 7 /* Undithered RGB using a lookup table */
+#define PF_GRAYSCALE 10 /* Grayscale or StaticGray */
+#define PF_BADFORMAT 11
+#define PF_INDEX8 12
+
+char ColorMap16[] = {
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
+0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,
+0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x04,
+0x05,0x05,0x05,0x05,0x05,0x05,0x05,0x05,
+0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,
+0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,
+0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+0x09,0x09,0x09,0x09,0x09,0x09,0x09,0x09,
+0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,0x0A,
+0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,0x0B,
+0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,
+0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D,
+0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,
+0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
+0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,
+0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
+0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12,
+0x13,0x13,0x13,0x13,0x13,0x13,0x13,0x13,
+0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,
+0x15,0x15,0x15,0x15,0x15,0x15,0x15,0x15,
+0x16,0x16,0x16,0x16,0x16,0x16,0x16,0x16,
+0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,
+0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
+0x19,0x19,0x19,0x19,0x19,0x19,0x19,0x19,
+0x1A,0x1A,0x1A,0x1A,0x1A,0x1A,0x1A,0x1A,
+0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,
+0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,0x1C,
+0x1D,0x1D,0x1D,0x1D,0x1D,0x1D,0x1D,0x1D,
+0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,0x1E,
+0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F};
+
+#define BGR8(r,g,b) (unsigned)(((BYTE)(b & 0xc0 | (g & 0xe0)>>2 | (r & 0xe0)>>5)))
+#ifdef DDRAW
+#define BGR16(r,g,b) ((WORD)(((BYTE)(ColorMap16[b]) | ((BYTE)(g&0xfc) << 3)) | (((WORD)(BYTE)(ColorMap16[r])) << 11)))
+#else
+#define BGR16(r,g,b) ((WORD)(((BYTE)(ColorMap16[b]) | ((BYTE)(ColorMap16[g]) << 5)) | (((WORD)(BYTE)(ColorMap16[r])) << 10)))
+#endif
+#define BGR24(r,g,b) (unsigned long)(((DWORD)(((BYTE)(b)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(r))<<16))) << 8)
+#define BGR32(r,g,b) (unsigned long)((DWORD)(((BYTE)(b)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(r))<<16)))
+
+
+
+/*
+ * If pixelformat==PF_8A8B8G8R:
+ */
+#define PACK_8A8B8G8R( R, G, B, A ) \
+ ( ((A) << 24) | ((B) << 16) | ((G) << 8) | (R) )
+
+
+/*
+ * If pixelformat==PF_8R8G8B:
+ */
+#define PACK_8R8G8B( R, G, B) ( ((R) << 16) | ((G) << 8) | (B) )
+
+
+/*
+ * If pixelformat==PF_5R6G5B:
+ */
+
+
+#ifdef DDRAW
+#define PACK_5R6G5B( R, G, B) ((WORD)(((BYTE)(ColorMap16[B]) | ((BYTE)(G&0xfc) << 3)) | (((WORD)(BYTE)(ColorMap16[R])) << 11)))
+#else
+#define PACK_5R6G5B( R, G, B) ((WORD)(((BYTE)(ColorMap16[B]) | ((BYTE)(ColorMap16[G]) << 5)) | (((WORD)(BYTE)(ColorMap16[R])) << 10)))
+#endif
+/*----------------------------------------------------------------------------
+
+Division lookup tables. These tables compute 0-255 divided by 51 and
+modulo 51. These tables could approximate gamma correction.
+
+*/
+
+char unsigned const aDividedBy51Rounded[256] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+};
+
+char unsigned const aDividedBy51[256] =
+{
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5,
+};
+
+char unsigned const aModulo51[256] =
+{
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
+ 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 0, 1, 2, 3, 4, 5, 6,
+ 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
+ 44, 45, 46, 47, 48, 49, 50, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+ 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+ 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 0, 1, 2, 3,
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
+ 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 0,
+};
+
+/*----------------------------------------------------------------------------
+
+Multiplication LUTs. These compute 0-5 times 6 and 36.
+
+*/
+
+char unsigned const aTimes6[6] =
+{
+ 0, 6, 12, 18, 24, 30
+};
+
+char unsigned const aTimes36[6] =
+{
+ 0, 36, 72, 108, 144, 180
+};
+
+
+/*----------------------------------------------------------------------------
+
+Dither matrices for 8 bit to 2.6 bit halftones.
+
+*/
+
+char unsigned const aHalftone16x16[256] =
+{
+ 0, 44, 9, 41, 3, 46, 12, 43, 1, 44, 10, 41, 3, 46, 12, 43,
+ 34, 16, 25, 19, 37, 18, 28, 21, 35, 16, 26, 19, 37, 18, 28, 21,
+ 38, 6, 47, 3, 40, 9, 50, 6, 38, 7, 47, 4, 40, 9, 49, 6,
+ 22, 28, 13, 31, 25, 31, 15, 34, 22, 29, 13, 32, 24, 31, 15, 34,
+ 2, 46, 12, 43, 1, 45, 10, 42, 2, 45, 11, 42, 1, 45, 11, 42,
+ 37, 18, 27, 21, 35, 17, 26, 20, 36, 17, 27, 20, 36, 17, 26, 20,
+ 40, 8, 49, 5, 38, 7, 48, 4, 39, 8, 48, 5, 39, 7, 48, 4,
+ 24, 30, 15, 33, 23, 29, 13, 32, 23, 30, 14, 33, 23, 29, 14, 32,
+ 2, 46, 12, 43, 0, 44, 10, 41, 3, 47, 12, 44, 0, 44, 10, 41,
+ 37, 18, 27, 21, 35, 16, 25, 19, 37, 19, 28, 22, 35, 16, 25, 19,
+ 40, 9, 49, 5, 38, 7, 47, 4, 40, 9, 50, 6, 38, 6, 47, 3,
+ 24, 30, 15, 34, 22, 29, 13, 32, 25, 31, 15, 34, 22, 28, 13, 31,
+ 1, 45, 11, 42, 2, 46, 11, 42, 1, 45, 10, 41, 2, 46, 11, 43,
+ 36, 17, 26, 20, 36, 17, 27, 21, 35, 16, 26, 20, 36, 18, 27, 21,
+ 39, 8, 48, 4, 39, 8, 49, 5, 38, 7, 48, 4, 39, 8, 49, 5,
+ 23, 29, 14, 33, 24, 30, 14, 33, 23, 29, 13, 32, 24, 30, 14, 33,
+};
+
+char unsigned const aHalftone8x8[64] =
+{
+ 0, 38, 9, 47, 2, 40, 11, 50,
+ 25, 12, 35, 22, 27, 15, 37, 24,
+ 6, 44, 3, 41, 8, 47, 5, 43,
+ 31, 19, 28, 15, 34, 21, 31, 18,
+ 1, 39, 11, 49, 0, 39, 10, 48,
+ 27, 14, 36, 23, 26, 13, 35, 23,
+ 7, 46, 4, 43, 7, 45, 3, 42,
+ 33, 20, 30, 17, 32, 19, 29, 16,
+};
+
+char unsigned const aHalftone4x4_1[16] =
+{
+ 0, 25, 6, 31,
+ 38, 12, 44, 19,
+ 9, 35, 3, 28,
+ 47, 22, 41, 15
+};
+
+char unsigned const aHalftone4x4_2[16] =
+{
+ 41, 3, 9, 28,
+ 35, 15, 22, 47,
+ 6, 25, 38, 0,
+ 19, 44, 31, 12
+};
+
+/***************************************************************************
+ aWinGHalftoneTranslation
+
+ Translates a 2.6 bit-per-pixel halftoned representation into the
+ slightly rearranged WinG Halftone Palette.
+*/
+
+char unsigned const aWinGHalftoneTranslation[216] =
+{
+ 0,
+ 29,
+ 30,
+ 31,
+ 32,
+ 249,
+ 33,
+ 34,
+ 35,
+ 36,
+ 37,
+ 38,
+ 39,
+ 40,
+ 41,
+ 42,
+ 43,
+ 44,
+ 45,
+ 46,
+ 47,
+ 48,
+ 49,
+ 50,
+ 51,
+ 52,
+ 53,
+ 54,
+ 55,
+ 56,
+ 250,
+ 250,
+ 57,
+ 58,
+ 59,
+ 251,
+ 60,
+ 61,
+ 62,
+ 63,
+ 64,
+ 65,
+ 66,
+ 67,
+ 68,
+ 69,
+ 70,
+ 71,
+ 72,
+ 73,
+ 74,
+ 75,
+ 76,
+ 77,
+ 78,
+ 79,
+ 80,
+ 81,
+ 82,
+ 83,
+ 84,
+ 85,
+ 86,
+ 87,
+ 88,
+ 89,
+ 250,
+ 90,
+ 91,
+ 92,
+ 93,
+ 94,
+ 95,
+ 96,
+ 97,
+ 98,
+ 99,
+ 100,
+ 101,
+ 102,
+ 103,
+ 104,
+ 105,
+ 106,
+ 107,
+ 108,
+ 109,
+ 110,
+ 111,
+ 227,
+ 112,
+ 113,
+ 114,
+ 115,
+ 116,
+ 117,
+ 118,
+ 119,
+ 151,
+ 120,
+ 121,
+ 122,
+ 123,
+ 124,
+ 228,
+ 125,
+ 126,
+ 229,
+ 133,
+ 162,
+ 135,
+ 131,
+ 132,
+ 137,
+ 166,
+ 134,
+ 140,
+ 130,
+ 136,
+ 143,
+ 138,
+ 139,
+ 174,
+ 141,
+ 142,
+ 177,
+ 129,
+ 144,
+ 145,
+ 146,
+ 147,
+ 148,
+ 149,
+ 150,
+ 157,
+ 152,
+ 153,
+ 154,
+ 155,
+ 156,
+ 192,
+ 158,
+ 159,
+ 160,
+ 161,
+ 196,
+ 163,
+ 164,
+ 165,
+ 127,
+ 199,
+ 167,
+ 168,
+ 169,
+ 170,
+ 171,
+ 172,
+ 173,
+ 207,
+ 175,
+ 176,
+ 210,
+ 178,
+ 179,
+ 180,
+ 181,
+ 182,
+ 183,
+ 184,
+ 185,
+ 186,
+ 187,
+ 188,
+ 189,
+ 190,
+ 191,
+ 224,
+ 193,
+ 194,
+ 195,
+ 252,
+ 252,
+ 197,
+ 198,
+ 128,
+ 253,
+ 252,
+ 200,
+ 201,
+ 202,
+ 203,
+ 204,
+ 205,
+ 206,
+ 230,
+ 208,
+ 209,
+ 231,
+ 211,
+ 212,
+ 213,
+ 214,
+ 215,
+ 216,
+ 217,
+ 218,
+ 219,
+ 220,
+ 221,
+ 222,
+ 254,
+ 223,
+ 232,
+ 225,
+ 226,
+ 255,
+}; \ No newline at end of file
diff --git a/src/mesa/drivers/windows/mesa_extend.c b/src/mesa/drivers/windows/mesa_extend.c
new file mode 100644
index 0000000000..933e3badd3
--- /dev/null
+++ b/src/mesa/drivers/windows/mesa_extend.c
@@ -0,0 +1,211 @@
+/* File: mesa_extend.c for wmesa-2.3
+ Written by Li Wei (liwei@aiar.xjtu.edu.cn)
+*/
+
+/*******************************************************************
+ Users can use the following keys to control the view
+
+ The following four key combinations can shift the view correspondingly,
+ function in both stereo and normal mode.
+ Ctrl+left arrow
+ Ctrl+right arrow
+ Ctrl+up arrow
+ Ctrl+down arrow
+
+ F (captital letter) shift the camera far from objects
+ N (captital letter) shift the camera near from objects
+ S (captital letter) toggle between normal and stereo mode
+ I (captital letter) increase the distance between two views
+ D (captital letter) decrease the distance between two views
+
+ if the Key function defined by user maps any key appearing above, it will be
+ masked by the program. Hence, user should either modify his own code or
+ modify function defaultKeyProc at the end of this file
+*******************************************************************/
+
+/* Log 6/14, 1997
+ * revision 1.01
+ * struct DisplayOptions defined for tk_ddmesa.c to read the initial file
+ */
+
+#include "mesa_extend.h"
+#include "gltk.h"
+#include <stdio.h>
+#ifndef NO_STEREO
+ #include "stereo.h"
+#endif
+#ifndef NO_PARALLEL
+// #include "parallel.h"
+#endif
+
+GLenum (*userKeyProc) (int, GLenum) = NULL;
+
+GLfloat viewDistance = 1.0;
+GLfloat deltaView = 0.1;
+GLfloat deltaShift = 0.1;
+
+GLuint viewShift = SHIFT_NONE;
+GLuint viewTag = 0 ;
+
+GLenum imageRendered = GL_FALSE;
+
+GLenum glImageRendered()
+{
+ return imageRendered;
+}
+
+//Code added by Li Wei to enable stereo display
+GLenum defaultKeyProc(int key, GLenum mask )
+{
+ GLenum flag = GL_FALSE ;
+ if(mask & TK_CONTROL){
+ flag = GL_TRUE ;
+ switch(key){
+ case TK_LEFT:
+ viewShift = SHIFT_LEFT;
+ break;
+ case TK_RIGHT:
+ viewShift = SHIFT_RIGHT;
+ break;
+ case TK_UP:
+ viewShift = SHIFT_UP;
+ break;
+ case TK_DOWN:
+ viewShift = SHIFT_DOWN;
+ break;
+ default:
+ flag = GL_FALSE ;
+ }
+ }
+ if(flag == GL_FALSE){
+ flag = GL_TRUE ;
+ switch(key){
+ case TK_F:
+ viewShift = SHIFT_FAR;
+ break;
+ case TK_N:
+ viewShift = SHIFT_NEAR;
+ break;
+
+#if !defined(NO_STEREO)
+ case TK_D:
+ viewDistance-= deltaView;
+ break;
+ case TK_I:
+ viewDistance+= deltaView;
+ break;
+ case TK_S:
+ toggleStereoMode();
+ break;
+#endif
+
+#if !defined(NO_PARALLEL)
+ case TK_P:
+ if(machineType == MASTER)
+ toggleParallelMode();
+ break;
+#endif
+ default:
+ flag = GL_FALSE;
+ }
+ }
+
+ if(userKeyProc)
+ flag=flag||(*userKeyProc)(key, mask);
+
+#if !defined(NO_PARALLEL)
+ if(parallelFlag&&key!=TK_P&&machineType == MASTER){
+ PRKeyDown(key,mask);
+ }
+#endif
+
+ return flag;
+}
+
+/* The following function implemented key board control of the display,
+ availabe even in normal mode so long the driver is linked into exe file.
+*/
+void shiftView()
+{
+ GLfloat cm[16];
+ if(viewShift != SHIFT_NONE){
+/* glGetFloatv(GL_MODELVIEW_MATRIX,cm);
+ glMatrixMode(GL_MODELVIEW);
+*/
+ GLint matrix_mode;
+ glGetIntegerv(GL_MATRIX_MODE,&matrix_mode);
+/* if(matrix_mode!=GL_PROJECTION)
+ glMatrixMode(GL_PROJECTION);
+ glGetFloatv(GL_PROJECTION_MATRIX,cm);
+ glLoadIdentity();
+ switch(viewShift){
+ case SHIFT_LEFT:
+ glTranslatef(-deltaShift,0,0);
+ break;
+ case SHIFT_RIGHT:
+ glTranslatef(deltaShift,0,0);
+ break;
+ case SHIFT_UP:
+ glTranslatef(0,deltaShift,0);
+ break;
+ case SHIFT_DOWN:
+ glTranslatef(0,-deltaShift,0);
+ break;
+ case SHIFT_FAR:
+ glTranslatef(0,0,-deltaShift);
+ break;
+ case SHIFT_NEAR:
+ glTranslatef(0,0,deltaShift);
+ break;
+ }
+
+ viewShift = SHIFT_NONE;
+ glMultMatrixf( cm );
+ if(matrix_mode!=GL_PROJECTION)
+ glMatrixMode(matrix_mode);
+
+ }
+*/
+ if(matrix_mode!=GL_MODELVIEW)
+ glMatrixMode(GL_MODELVIEW);
+ glGetFloatv(GL_MODELVIEW_MATRIX,cm);
+ glLoadIdentity();
+ switch(viewShift){
+ case SHIFT_LEFT:
+ glTranslatef(-deltaShift,0,0);
+ break;
+ case SHIFT_RIGHT:
+ glTranslatef(deltaShift,0,0);
+ break;
+ case SHIFT_UP:
+ glTranslatef(0,deltaShift,0);
+ break;
+ case SHIFT_DOWN:
+ glTranslatef(0,-deltaShift,0);
+ break;
+ case SHIFT_FAR:
+ glTranslatef(0,0,-deltaShift);
+ break;
+ case SHIFT_NEAR:
+ glTranslatef(0,0,deltaShift);
+ break;
+ }
+
+ viewShift = SHIFT_NONE;
+ glMultMatrixf( cm );
+ if(matrix_mode!=GL_MODELVIEW)
+ glMatrixMode(matrix_mode);
+
+ }
+}
+
+
+void getDisplayOptions( void)
+{
+ displayOptions.stereo = GetPrivateProfileInt("DISPLAY", "STEREO",1,"ddmesa.ini" );
+ displayOptions.fullScreen = GetPrivateProfileInt("DISPLAY", "FULLSCREEN",0,"ddmesa.ini" );
+ displayOptions.mode = GetPrivateProfileInt("DISPLAY", "MODE",1, "ddmesa.ini");
+ displayOptions.bpp = GetPrivateProfileInt("DISPLAY", "BPP", 32, "ddmesa.ini");
+
+}
+//end modification
diff --git a/src/mesa/drivers/windows/mesa_extend.h b/src/mesa/drivers/windows/mesa_extend.h
new file mode 100644
index 0000000000..66a8a77d65
--- /dev/null
+++ b/src/mesa/drivers/windows/mesa_extend.h
@@ -0,0 +1,43 @@
+/* mesa_extend.h
+ * for wmesa-2.3
+ * Written by Li Wei (liwei@aiar.xjtu.edu.cn)
+ */
+
+/* Log 6/14, 1997
+ * revision 1.01
+ * struct DisplayOptions defined for tk_ddmesa.c to read the initial file
+ */
+
+#include <GL/gl.h>
+#include <stdlib.h>
+#include <windows.h>
+#include <winbase.h>
+
+typedef enum SHIFT{ SHIFT_NONE, SHIFT_LEFT,SHIFT_RIGHT,SHIFT_UP,SHIFT_DOWN,SHIFT_FAR,SHIFT_NEAR};
+
+extern GLfloat deltaView ;
+
+extern GLuint viewShift;
+
+extern GLenum glImageRendered();
+
+extern GLenum imageRendered ;
+
+extern GLfloat deltaView ;
+
+extern GLfloat deltaShift;
+
+void shiftView( void );
+
+struct DISPLAY_OPTIONS {
+ int stereo;
+ int fullScreen;
+ int mode;
+ int bpp;
+};
+
+extern struct DISPLAY_OPTIONS displayOptions;
+extern void getDisplayOptions( void);
+
+GLenum defaultKeyProc(int, GLenum);
+extern GLenum (*userKeyProc) (int, GLenum);
diff --git a/src/mesa/drivers/windows/stereo.h b/src/mesa/drivers/windows/stereo.h
new file mode 100644
index 0000000000..544af54235
--- /dev/null
+++ b/src/mesa/drivers/windows/stereo.h
@@ -0,0 +1,47 @@
+/* File name stereov.h
+ header file for stereo display driver
+***************************************************************
+* WMesa *
+* version 2.3 *
+* *
+* By *
+* Li Wei *
+* Institute of Artificial Intelligence & Robotics *
+* Xi'an Jiaotong University *
+* Email: liwei@aiar.xjtu.edu.cn *
+* Web page: http://sun.aiar.xjtu.edu.cn *
+* *
+* July 7th, 1997 *
+***************************************************************
+
+*/
+#if defined( __WIN32__) || defined (WIN32)
+ #include <windows.h>
+#endif
+
+typedef enum VIEW_INDICATOR { FIRST, SECOND};
+
+#define MAXIMUM_DISPLAY_LIST 99
+
+extern GLenum stereoBuffer;
+
+extern GLint displayList;
+
+extern GLint stereo_flag ;
+
+extern GLfloat viewDistance;
+
+extern GLuint viewTag;
+
+extern GLuint displayListBase;
+
+extern GLuint numOfLists;
+
+extern GLenum stereoCompile;
+
+extern GLenum stereoShowing;
+
+extern void glShowStereo(GLuint list);
+
+extern void toggleStereoMode();
+
diff --git a/src/mesa/drivers/windows/wgl.c b/src/mesa/drivers/windows/wgl.c
new file mode 100644
index 0000000000..d5f577dd81
--- /dev/null
+++ b/src/mesa/drivers/windows/wgl.c
@@ -0,0 +1,518 @@
+/* $Id: wgl.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+* 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.
+*
+*/
+
+/*
+* File name : wgl.c
+* WGL stuff. Added by Oleg Letsinsky, ajl@ultersys.ru
+* Some things originated from the 3Dfx WGL functions
+*/
+
+#ifdef WIN32
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <windows.h>
+
+#include <GL/gl.h>
+#include <GL/glu.h>
+
+#ifdef __cplusplus
+}
+#endif
+
+#include <stdio.h>
+#include <tchar.h>
+#include "wmesadef.h"
+#include "GL/wmesa.h"
+#include "types.h"
+
+#define MAX_MESA_ATTRS 20
+
+struct __extensions__
+{
+ PROC proc;
+ char *name;
+};
+
+struct __pixelformat__
+{
+ PIXELFORMATDESCRIPTOR pfd;
+ GLboolean doubleBuffered;
+};
+
+struct __extensions__ ext[] = {
+
+#ifdef GL_EXT_polygon_offset
+ { (PROC)glPolygonOffsetEXT, "glPolygonOffsetEXT" },
+#endif
+ { (PROC)glBlendEquationEXT, "glBlendEquationEXT" },
+ { (PROC)glBlendColorEXT, "glBlendColorExt" },
+ { (PROC)glVertexPointerEXT, "glVertexPointerEXT" },
+ { (PROC)glNormalPointerEXT, "glNormalPointerEXT" },
+ { (PROC)glColorPointerEXT, "glColorPointerEXT" },
+ { (PROC)glIndexPointerEXT, "glIndexPointerEXT" },
+ { (PROC)glTexCoordPointerEXT, "glTexCoordPointer" },
+ { (PROC)glEdgeFlagPointerEXT, "glEdgeFlagPointerEXT" },
+ { (PROC)glGetPointervEXT, "glGetPointervEXT" },
+ { (PROC)glArrayElementEXT, "glArrayElementEXT" },
+ { (PROC)glDrawArraysEXT, "glDrawArrayEXT" },
+ { (PROC)glAreTexturesResidentEXT, "glAreTexturesResidentEXT" },
+ { (PROC)glBindTextureEXT, "glBindTextureEXT" },
+ { (PROC)glDeleteTexturesEXT, "glDeleteTexturesEXT" },
+ { (PROC)glGenTexturesEXT, "glGenTexturesEXT" },
+ { (PROC)glIsTextureEXT, "glIsTextureEXT" },
+ { (PROC)glPrioritizeTexturesEXT, "glPrioritizeTexturesEXT" },
+ { (PROC)glCopyTexSubImage3DEXT, "glCopyTexSubImage3DEXT" },
+ { (PROC)glTexImage3DEXT, "glTexImage3DEXT" },
+ { (PROC)glTexSubImage3DEXT, "glTexSubImage3DEXT" },
+ { (PROC)glColorTableEXT, "glColorTableEXT" },
+ { (PROC)glColorSubTableEXT, "glColorSubTableEXT" },
+ { (PROC)glGetColorTableEXT, "glGetColorTableEXT" },
+ { (PROC)glGetColorTableParameterfvEXT, "glGetColorTableParameterfvEXT" },
+ { (PROC)glGetColorTableParameterivEXT, "glGetColorTableParameterivEXT" },
+ { (PROC)glPointParameterfEXT, "glPointParameterfEXT" },
+ { (PROC)glPointParameterfvEXT, "glPointParameterfvEXT" },
+ { (PROC)glBlendFuncSeparateINGR, "glBlendFuncSeparateINGR" },
+ { (PROC)glLockArraysEXT, "glLockArraysEXT" },
+ { (PROC)glUnlockArraysEXT, "glUnlockArraysEXT" }
+};
+
+int qt_ext = sizeof(ext) / sizeof(ext[0]);
+
+struct __pixelformat__ pix[] =
+{
+ { { sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_GENERIC_FORMAT|PFD_DOUBLEBUFFER|PFD_SWAP_COPY,
+ PFD_TYPE_RGBA,
+ 24, 8, 0, 8, 8, 8, 16, 8, 24,
+ 0, 0, 0, 0, 0, 16, 8, 0, 0, 0, 0, 0, 0 },
+ GL_TRUE
+ },
+ { { sizeof(PIXELFORMATDESCRIPTOR), 1,
+ PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_GENERIC_FORMAT,
+ PFD_TYPE_RGBA,
+ 24, 8, 0, 8, 8, 8, 16, 8, 24,
+ 0, 0, 0, 0, 0, 16, 8, 0, 0, 0, 0, 0, 0 },
+ GL_FALSE
+ },
+};
+
+int qt_pix = sizeof(pix) / sizeof(pix[0]);
+
+typedef struct {
+ WMesaContext ctx;
+ HDC hdc;
+} MesaWglCtx;
+
+#define MESAWGL_CTX_MAX_COUNT 20
+
+static MesaWglCtx wgl_ctx[MESAWGL_CTX_MAX_COUNT];
+
+static unsigned ctx_count = 0;
+static unsigned ctx_current = -1;
+static unsigned curPFD = 0;
+
+GLAPI BOOL GLWINAPI wglCopyContext(HGLRC hglrcSrc,HGLRC hglrcDst,UINT mask)
+{
+ return(FALSE);
+}
+
+GLAPI HGLRC GLWINAPI wglCreateContext(HDC hdc)
+{
+ HWND hWnd;
+ int i = 0;
+ if(!(hWnd = WindowFromDC(hdc)))
+ {
+ SetLastError(0);
+ return(NULL);
+ }
+ if (!ctx_count)
+ {
+ for(i=0;i<MESAWGL_CTX_MAX_COUNT;i++)
+ {
+ wgl_ctx[i].ctx = NULL;
+ wgl_ctx[i].hdc = NULL;
+ }
+ }
+ for( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ )
+ {
+ if ( wgl_ctx[i].ctx == NULL )
+ {
+ wgl_ctx[i].ctx = WMesaCreateContext( hWnd, NULL, GL_TRUE,
+ pix[curPFD-1].doubleBuffered );
+ if (wgl_ctx[i].ctx == NULL)
+ break;
+ wgl_ctx[i].hdc = hdc;
+ ctx_count++;
+ return ((HGLRC)wgl_ctx[i].ctx);
+ }
+ }
+ SetLastError(0);
+ return(NULL);
+}
+
+GLAPI BOOL GLWINAPI wglDeleteContext(HGLRC hglrc)
+{
+ int i;
+ for ( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ )
+ {
+ if ( wgl_ctx[i].ctx == (PWMC) hglrc )
+ {
+ WMesaMakeCurrent((PWMC) hglrc);
+ WMesaDestroyContext();
+ wgl_ctx[i].ctx = NULL;
+ wgl_ctx[i].hdc = NULL;
+ ctx_count--;
+ return(TRUE);
+ }
+ }
+ SetLastError(0);
+ return(FALSE);
+}
+
+GLAPI HGLRC GLWINAPI wglCreateLayerContext(HDC hdc,int iLayerPlane)
+{
+ SetLastError(0);
+ return(NULL);
+}
+
+GLAPI HGLRC GLWINAPI wglGetCurrentContext(VOID)
+{
+ if (ctx_current < 0)
+ return 0;
+ else
+ return (HGLRC) wgl_ctx[ctx_current].ctx;
+}
+
+GLAPI HDC GLWINAPI wglGetCurrentDC(VOID)
+{
+ if (ctx_current < 0)
+ return 0;
+ else
+ return wgl_ctx[ctx_current].hdc;
+}
+
+GLAPI BOOL GLWINAPI wglMakeCurrent(HDC hdc,HGLRC hglrc)
+{
+ int i;
+
+ /* new code suggested by Andy Sy */
+ if (!hdc || !hglrc) {
+ WMesaMakeCurrent(NULL);
+ ctx_current = -1;
+ return TRUE;
+ }
+
+ for ( i = 0; i < MESAWGL_CTX_MAX_COUNT; i++ )
+ {
+ if ( wgl_ctx[i].ctx == (PWMC) hglrc )
+ {
+ wgl_ctx[i].hdc = hdc;
+ WMesaMakeCurrent( (WMesaContext) hglrc );
+ ctx_current = i;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+GLAPI BOOL GLWINAPI wglShareLists(HGLRC hglrc1,HGLRC hglrc2)
+{
+ return(TRUE);
+}
+
+
+static FIXED FixedFromDouble(double d)
+{
+ long l = (long) (d * 65536L);
+ return *(FIXED *)&l;
+}
+
+
+GLAPI BOOL GLWINAPI wglUseFontBitmapsA(HDC hdc, DWORD first,
+ DWORD count, DWORD listBase)
+{
+ int i;
+ GLuint font_list;
+ DWORD size;
+ GLYPHMETRICS gm;
+ HANDLE hBits;
+ LPSTR lpBits;
+ MAT2 mat;
+
+ if (first<0)
+ return FALSE;
+ if (count<0)
+ return FALSE;
+ if (listBase<0)
+ return FALSE;
+
+ font_list = glGenLists( count );
+ if(font_list == 0)
+ return FALSE;
+
+ mat.eM11 = FixedFromDouble(1);
+ mat.eM12 = FixedFromDouble(0);
+ mat.eM21 = FixedFromDouble(0);
+ mat.eM22 = FixedFromDouble(1);
+
+ memset(&gm,0,sizeof(gm));
+
+ for (i = 0; i < count; i++)
+ {
+ glNewList( font_list+i, GL_COMPILE );
+
+ /* allocate space for the bitmap/outline */
+ size = GetGlyphOutline(hdc, first + i, GGO_BITMAP, &gm, 0, NULL, &mat);
+ if (size == GDI_ERROR)
+ {
+ DWORD err;
+ err = GetLastError();
+ return(FALSE);
+ }
+
+ hBits = GlobalAlloc(GHND, size);
+ lpBits = GlobalLock(hBits);
+
+ GetGlyphOutline(hdc, /* handle to device context */
+ first + i, /* character to query */
+ GGO_BITMAP, /* format of data to return */
+ &gm, /* pointer to structure for metrics */
+ size, /* size of buffer for data */
+ lpBits, /* pointer to buffer for data */
+ &mat /* pointer to transformation */
+ /* matrix structure */
+ );
+
+ if (*lpBits == GDI_ERROR)
+ {
+ DWORD err;
+ err = GetLastError();
+
+ GlobalUnlock(hBits);
+ GlobalFree(hBits);
+
+ return(FALSE);
+ }
+
+ glBitmap(gm.gmBlackBoxX,gm.gmBlackBoxY,
+ gm.gmptGlyphOrigin.x,
+ gm.gmptGlyphOrigin.y,
+ gm.gmCellIncX,gm.gmCellIncY,
+ (const GLubyte * )lpBits);
+
+ GlobalUnlock(hBits);
+ GlobalFree(hBits);
+
+ glEndList( );
+ }
+
+ return TRUE;
+}
+
+GLAPI BOOL GLWINAPI wglUseFontBitmapsW(HDC hdc,DWORD first,DWORD count,DWORD listBase)
+{
+ return FALSE;
+}
+
+GLAPI BOOL GLWINAPI wglUseFontOutlinesA(HDC hdc,DWORD first,DWORD count,
+ DWORD listBase,FLOAT deviation,
+ FLOAT extrusion,int format,
+ LPGLYPHMETRICSFLOAT lpgmf)
+{
+ SetLastError(0);
+ return(FALSE);
+}
+
+GLAPI BOOL GLWINAPI wglUseFontOutlinesW(HDC hdc,DWORD first,DWORD count,
+ DWORD listBase,FLOAT deviation,
+ FLOAT extrusion,int format,
+ LPGLYPHMETRICSFLOAT lpgmf)
+{
+ SetLastError(0);
+ return(FALSE);
+}
+
+GLAPI BOOL GLWINAPI wglDescribeLayerPlane(HDC hdc,int iPixelFormat,
+ int iLayerPlane,UINT nBytes,
+ LPLAYERPLANEDESCRIPTOR plpd)
+{
+ SetLastError(0);
+ return(FALSE);
+}
+
+GLAPI int GLWINAPI wglSetLayerPaletteEntries(HDC hdc,int iLayerPlane,
+ int iStart,int cEntries,
+ CONST COLORREF *pcr)
+{
+ SetLastError(0);
+ return(0);
+}
+
+GLAPI int GLWINAPI wglGetLayerPaletteEntries(HDC hdc,int iLayerPlane,
+ int iStart,int cEntries,
+ COLORREF *pcr)
+{
+ SetLastError(0);
+ return(0);
+}
+
+GLAPI BOOL GLWINAPI wglRealizeLayerPalette(HDC hdc,int iLayerPlane,BOOL bRealize)
+{
+ SetLastError(0);
+ return(FALSE);
+}
+
+GLAPI BOOL GLWINAPI wglSwapLayerBuffers(HDC hdc,UINT fuPlanes)
+{
+ if( !hdc )
+ {
+ WMesaSwapBuffers();
+ return(TRUE);
+ }
+ SetLastError(0);
+ return(FALSE);
+}
+
+GLAPI int GLWINAPI wglChoosePixelFormat(HDC hdc,
+ CONST PIXELFORMATDESCRIPTOR *ppfd)
+{
+ int i,best = -1,bestdelta = 0x7FFFFFFF,delta,qt_valid_pix;
+
+ qt_valid_pix = qt_pix;
+ if(ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR) || ppfd->nVersion != 1)
+ {
+ SetLastError(0);
+ return(0);
+ }
+ for(i = 0;i < qt_valid_pix;i++)
+ {
+ delta = 0;
+ if(
+ (ppfd->dwFlags & PFD_DRAW_TO_WINDOW) &&
+ !(pix[i].pfd.dwFlags & PFD_DRAW_TO_WINDOW))
+ continue;
+ if(
+ (ppfd->dwFlags & PFD_DRAW_TO_BITMAP) &&
+ !(pix[i].pfd.dwFlags & PFD_DRAW_TO_BITMAP))
+ continue;
+ if(
+ (ppfd->dwFlags & PFD_SUPPORT_GDI) &&
+ !(pix[i].pfd.dwFlags & PFD_SUPPORT_GDI))
+ continue;
+ if(
+ (ppfd->dwFlags & PFD_SUPPORT_OPENGL) &&
+ !(pix[i].pfd.dwFlags & PFD_SUPPORT_OPENGL))
+ continue;
+ if(
+ !(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) &&
+ ((ppfd->dwFlags & PFD_DOUBLEBUFFER) != (pix[i].pfd.dwFlags & PFD_DOUBLEBUFFER)))
+ continue;
+ if(
+ !(ppfd->dwFlags & PFD_STEREO_DONTCARE) &&
+ ((ppfd->dwFlags & PFD_STEREO) != (pix[i].pfd.dwFlags & PFD_STEREO)))
+ continue;
+ if(ppfd->iPixelType != pix[i].pfd.iPixelType)
+ delta++;
+ if(delta < bestdelta)
+ {
+ best = i + 1;
+ bestdelta = delta;
+ if(bestdelta == 0)
+ break;
+ }
+ }
+ if(best == -1)
+ {
+ SetLastError(0);
+ return(0);
+ }
+ return(best);
+}
+
+GLAPI int GLWINAPI wglDescribePixelFormat(HDC hdc,int iPixelFormat,UINT nBytes,
+ LPPIXELFORMATDESCRIPTOR ppfd)
+{
+ int qt_valid_pix;
+
+ qt_valid_pix = qt_pix;
+ if(iPixelFormat < 1 || iPixelFormat > qt_valid_pix || nBytes != sizeof(PIXELFORMATDESCRIPTOR))
+ {
+ SetLastError(0);
+ return(0);
+ }
+ *ppfd = pix[iPixelFormat - 1].pfd;
+ return(qt_valid_pix);
+}
+
+/*
+* GetProcAddress - return the address of an appropriate extension
+*/
+GLAPI PROC GLWINAPI wglGetProcAddress(LPCSTR lpszProc)
+{
+ int i;
+ for(i = 0;i < qt_ext;i++)
+ if(!strcmp(lpszProc,ext[i].name))
+ return(ext[i].proc);
+
+ SetLastError(0);
+ return(NULL);
+}
+
+GLAPI int GLWINAPI wglGetPixelFormat(HDC hdc)
+{
+ if(curPFD == 0)
+ {
+ SetLastError(0);
+ return(0);
+ }
+ return(curPFD);
+}
+
+GLAPI BOOL GLWINAPI wglSetPixelFormat(HDC hdc,int iPixelFormat,
+ PIXELFORMATDESCRIPTOR *ppfd)
+{
+ int qt_valid_pix;
+
+ qt_valid_pix = qt_pix;
+ if(iPixelFormat < 1 || iPixelFormat > qt_valid_pix || ppfd->nSize != sizeof(PIXELFORMATDESCRIPTOR))
+ {
+ SetLastError(0);
+ return(FALSE);
+ }
+ curPFD = iPixelFormat;
+ return(TRUE);
+}
+
+GLAPI BOOL GLWINAPI wglSwapBuffers(HDC hdc)
+{
+ if (ctx_current < 0)
+ return FALSE;
+
+ if(wgl_ctx[ctx_current].ctx == NULL) {
+ SetLastError(0);
+ return(FALSE);
+ }
+ WMesaSwapBuffers();
+ return(TRUE);
+}
+
+#endif /* WIN32 */
diff --git a/src/mesa/drivers/windows/wing32.def b/src/mesa/drivers/windows/wing32.def
new file mode 100644
index 0000000000..ac8fc1dfb6
--- /dev/null
+++ b/src/mesa/drivers/windows/wing32.def
@@ -0,0 +1,12 @@
+EXPORTS
+ WinGBitBlt@32
+ WinGCreateBitmap@12
+ WinGCreateDC@0
+ WinGCreateHalftoneBrush@12
+ WinGCreateHalftonePalette@0
+ WinGGetDIBColorTable@16
+ WinGGetDIBPointer@8
+ WinGRecommendDIBFormat@4
+ WinGSetDIBColorTable@16
+ WinGStretchBlt@40
+
diff --git a/src/mesa/drivers/windows/wmesa.c b/src/mesa/drivers/windows/wmesa.c
new file mode 100644
index 0000000000..d2c0a56b26
--- /dev/null
+++ b/src/mesa/drivers/windows/wmesa.c
@@ -0,0 +1,3021 @@
+/* $Id: wmesa.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+* File name : wmesa.c
+* Version : 2.3
+*
+* Display driver for Mesa 2.3 under
+* Windows95 and WindowsNT
+*
+* Copyright (C) 1996- Li Wei
+* Address : Institute of Artificial Intelligence
+* : & Robotics
+* : Xi'an Jiaotong University
+* Email : liwei@aiar.xjtu.edu.cn
+* Web page : http://sun.aiar.xjtu.edu.cn
+*
+* This file and its associations are partially borrowed from the
+* Windows NT driver for Mesa 1.8 , written by Mark Leaming
+* (mark@rsinc.com).
+*/
+
+
+/*
+ * $Log: wmesa.c,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 3.10 1999/06/15 01:35:06 brianp
+ * small change to wmSetPixel() from TWILMOT@cpr.fr
+ *
+ * Revision 3.9 1999/05/11 19:06:01 brianp
+ * fixed a few VB->Index bugs (mikec@ensoniq.com)
+ *
+ * Revision 3.8 1999/05/08 15:15:23 brianp
+ * various updates from mikec@ensoniq.com
+ *
+ * Revision 3.7 1999/04/01 01:27:34 brianp
+ * always flip Y coord in read_rgba_span()
+ *
+ * Revision 3.6 1999/03/28 21:17:27 brianp
+ * updated SetBuffer driver function
+ *
+ * Revision 3.5 1999/03/16 01:36:42 brianp
+ * patched dither() to check if Current is NULL, per xzhou@nyx.net
+ *
+ * Revision 3.4 1999/02/25 14:12:33 keithw
+ * Merged in kw3 patch
+ *
+ * Revision 3.3 1999/01/03 03:08:57 brianp
+ * Ted Jump's changes
+ *
+ * Revision 3.2 1998/08/29 00:26:01
+ * updated for Mesa 3.0 to accomodate EGCS-Mingw32 build
+ *
+ * Revision 3.1 1998/06/11 01:42:08 brianp
+ * updated for Mesa 3.0 device driver interface (but not tested)
+ *
+ * Revision 3.0 1998/06/11 01:18:25 brianp
+ * initial revision
+ *
+ */
+
+
+#define WMESA_STEREO_C
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <GL/wmesa.h>
+#include "mesa_extend.h"
+#include "colors.h"
+#include "macros.h"
+#include "context.h"
+#include "dd.h"
+#include "xform.h"
+#include "vb.h"
+#include "matrix.h"
+#include "depth.h"
+#include "wmesadef.h"
+
+#pragma warning ( disable : 4133 4761 )
+
+#ifdef PROFILE
+// #include "profile.h"
+#endif
+
+#ifdef DITHER
+#include <wing.h>
+#endif
+
+#ifdef __CYGWIN32__
+#include "macros.h"
+#include <string.h>
+#define CopyMemory memcpy
+#endif
+
+#if !defined(NO_STEREO)
+
+#include "gl\glu.h"
+#include "stereo.h"
+
+#endif
+#if !defined(NO_PARALLEL)
+// #include "parallel.h"
+#endif
+
+struct DISPLAY_OPTIONS displayOptions;
+
+GLenum stereoCompile = GL_FALSE ;
+GLenum stereoShowing = GL_FALSE ;
+GLenum stereoBuffer = GL_FALSE;
+#if !defined(NO_STEREO)
+GLint displayList = MAXIMUM_DISPLAY_LIST ;
+#endif
+GLint stereo_flag = 0 ;
+
+/* end of added code*/
+
+static PWMC Current = NULL;
+WMesaContext WC = NULL;
+
+#ifdef NDEBUG
+#define assert(ignore) ((void) 0)
+#else
+void Mesa_Assert(void *Cond,void *File,unsigned Line)
+{
+ char Msg[512];
+ sprintf(Msg,"%s %s %d",Cond,File,Line);
+ MessageBox(NULL,Msg,"Assertion failed.",MB_OK);
+ exit(1);
+}
+#define assert(e) if (!e) Mesa_Assert(#e,__FILE__,__LINE__);
+#endif
+
+//#define DD_GETDC (Current->hDC )
+#define DD_GETDC ((Current->db_flag) ? Current->dib.hDC : Current->hDC )
+//#define DD_GETDC ((Current->db_flag) ? Current->hDCPrimary : Current->hDCBack )
+#define DD_RELEASEDC
+
+//#define BEGINGDICALL if(Current->rgb_flag)wmFlushBits(Current);
+#define BEGINGDICALL
+//#define ENDGDICALL if(Current->rgb_flag)wmGetBits(Current);
+#define ENDGDICALL
+
+//#define FLIP(Y) (Current->dither_flag? Y : Current->height-(Y)-1)
+//#define FLIP(Y) (Current->height-(Y)-1)
+//#define FLIP(Y) Y
+/*
+ * XXX Why only flip Y coord if single buffered???
+ */
+#define FLIP(Y) (Current->db_flag? Y: Current->height-(Y)-1)
+#define STARTPROFILE
+#define ENDPROFILE(PARA)
+
+#define DITHER_RGB_TO_8BIT_SETUP \
+GLubyte pixelDithered;
+
+#define DITHER_RGB_TO_8BIT(red, green, blue, pixel, scanline) \
+{ \
+ char unsigned redtemp, greentemp, bluetemp, paletteindex; \
+ redtemp = aDividedBy51[red] \
+ + (aModulo51[red] > aHalftone8x8[(pixel%8)*8 \
+ + scanline%8]); \
+ greentemp = aDividedBy51[(char unsigned)green] \
+ + (aModulo51[green] > aHalftone8x8[ \
+ (pixel%8)*8 + scanline%8]); \
+ bluetemp = aDividedBy51[(char unsigned)blue] \
+ + (aModulo51[blue] > aHalftone8x8[ \
+ (pixel%8)*8 +scanline%8]); \
+ paletteindex = redtemp + aTimes6[greentemp] + aTimes36[bluetemp]; \
+ pixelDithered = aWinGHalftoneTranslation[paletteindex]; \
+}
+
+
+#ifdef DDRAW
+static BOOL DDInit( WMesaContext wc, HWND hwnd);
+static void DDFree( WMesaContext wc);
+static HRESULT DDRestoreAll( WMesaContext wc );
+static void DDDeleteOffScreen(WMesaContext wc);
+static BOOL DDCreateOffScreen(WMesaContext wc);
+#endif
+
+static void FlushToFile(PWMC pwc, PSTR szFile);
+
+BOOL wmCreateBackingStore(PWMC pwc, long lxSize, long lySize);
+BOOL wmDeleteBackingStore(PWMC pwc);
+void wmCreatePalette( PWMC pwdc );
+BOOL wmSetDibColors(PWMC pwc);
+void wmSetPixel(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b);
+
+void wmCreateDIBSection(
+ HDC hDC,
+ PWMC pwc, // handle of device context
+ CONST BITMAPINFO *pbmi, // address of structure containing bitmap size, format, and color data
+ UINT iUsage // color data type indicator: RGB values or palette indices
+ );
+
+
+void WMesaViewport( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height );
+
+
+static triangle_func choose_triangle_function( GLcontext *ctx );
+
+
+static void wmSetPixelFormat( PWMC wc, HDC hDC)
+{
+ if(wc->rgb_flag)
+ wc->cColorBits = GetDeviceCaps(hDC, BITSPIXEL);
+ else
+ wc->cColorBits = 8;
+ switch(wc->cColorBits){
+ case 8:
+ if(wc->dither_flag != GL_TRUE)
+ wc->pixelformat = PF_INDEX8;
+ else
+ wc->pixelformat = PF_DITHER8;
+ break;
+ case 16:
+ wc->pixelformat = PF_5R6G5B;
+ break;
+ case 32:
+ wc->pixelformat = PF_8R8G8B;
+ break;
+ default:
+ wc->pixelformat = PF_BADFORMAT;
+ }
+}
+
+//
+// This function sets the color table of a DIB section
+// to match that of the destination DC
+//
+BOOL /*WINAPI*/ wmSetDibColors(PWMC pwc)
+{
+ RGBQUAD *pColTab, *pRGB;
+ PALETTEENTRY *pPal, *pPE;
+ int i, nColors;
+ BOOL bRet=TRUE;
+ DWORD dwErr=0;
+
+ /* Build a color table in the DIB that maps to the
+ selected palette in the DC.
+ */
+ nColors = 1 << pwc->cColorBits;
+ pPal = (PALETTEENTRY *)malloc( nColors * sizeof(PALETTEENTRY));
+ memset( pPal, 0, nColors * sizeof(PALETTEENTRY) );
+ GetPaletteEntries( pwc->hGLPalette, 0, nColors, pPal );
+ pColTab = (RGBQUAD *)malloc( nColors * sizeof(RGBQUAD));
+ for (i = 0, pRGB = pColTab, pPE = pPal; i < nColors; i++, pRGB++, pPE++) {
+ pRGB->rgbRed = pPE->peRed;
+ pRGB->rgbGreen = pPE->peGreen;
+ pRGB->rgbBlue = pPE->peBlue;
+ }
+ if(pwc->db_flag)
+ bRet = SetDIBColorTable(pwc->dib.hDC, 0, nColors, pColTab );
+
+ if(!bRet)
+ dwErr = GetLastError();
+
+ free( pColTab );
+ free( pPal );
+
+ return(bRet);
+}
+
+
+//
+// Free up the dib section that was created
+//
+BOOL wmDeleteBackingStore(PWMC pwc)
+{
+ SelectObject(pwc->dib.hDC, pwc->hOldBitmap);
+ DeleteDC(pwc->dib.hDC);
+ DeleteObject(pwc->hbmDIB);
+ UnmapViewOfFile(pwc->dib.base);
+ CloseHandle(pwc->dib.hFileMap);
+ return TRUE;
+}
+
+
+//
+// This function creates the DIB section that is used for combined
+// GL and GDI calls
+//
+BOOL /*WINAPI*/ wmCreateBackingStore(PWMC pwc, long lxSize, long lySize)
+{
+ HDC hdc = pwc->hDC;
+ LPBITMAPINFO pbmi = &(pwc->bmi);
+ int iUsage;
+
+ pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ pbmi->bmiHeader.biWidth = lxSize;
+ pbmi->bmiHeader.biHeight= -lySize;
+ pbmi->bmiHeader.biPlanes = 1;
+ if(pwc->rgb_flag)
+ pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwc->hDC, BITSPIXEL);
+ else
+ pbmi->bmiHeader.biBitCount = 8;
+ pbmi->bmiHeader.biCompression = BI_RGB;
+ pbmi->bmiHeader.biSizeImage = 0;
+ pbmi->bmiHeader.biXPelsPerMeter = 0;
+ pbmi->bmiHeader.biYPelsPerMeter = 0;
+ pbmi->bmiHeader.biClrUsed = 0;
+ pbmi->bmiHeader.biClrImportant = 0;
+
+ iUsage = (pbmi->bmiHeader.biBitCount <= 8) ? DIB_PAL_COLORS : DIB_RGB_COLORS;
+
+ pwc->cColorBits = pbmi->bmiHeader.biBitCount;
+ pwc->ScanWidth = pwc->pitch = lxSize;
+
+ wmCreateDIBSection(hdc, pwc, pbmi, iUsage);
+
+ if ((iUsage == DIB_PAL_COLORS) && !(pwc->hGLPalette)) {
+ wmCreatePalette( pwc );
+ wmSetDibColors( pwc );
+ }
+ wmSetPixelFormat(pwc, pwc->hDC);
+ return(TRUE);
+
+}
+
+
+//
+// This function copies one scan line in a DIB section to another
+//
+BOOL WINAPI wmSetDIBits(PWMC pwc, UINT uiScanWidth, UINT uiNumScans, UINT nBypp, UINT uiNewWidth, LPBYTE pBits)
+{
+ UINT uiScans = 0;
+ LPBYTE pDest = pwc->pbPixels;
+ DWORD dwNextScan = uiScanWidth;
+ DWORD dwNewScan = uiNewWidth;
+ DWORD dwScanWidth = (uiScanWidth * nBypp);
+
+ //
+ // We need to round up to the nearest DWORD
+ // and multiply by the number of bytes per
+ // pixel
+ //
+ dwNextScan = (((dwNextScan * nBypp)+ 3) & ~3);
+ dwNewScan = (((dwNewScan * nBypp)+ 3) & ~3);
+
+ for(uiScans = 0; uiScans < uiNumScans; uiScans++){
+ CopyMemory(pDest, pBits, dwScanWidth);
+ pBits += dwNextScan;
+ pDest += dwNewScan;
+ }
+
+ return(TRUE);
+
+}
+
+
+BOOL wmFlush(PWMC pwc);
+
+/*
+* Useful macros:
+Modified from file osmesa.c
+*/
+
+
+#define PIXELADDR(X,Y) ((GLubyte *)Current->pbPixels + (Current->height-Y-1)* Current->ScanWidth + (X)*nBypp)
+#define PIXELADDR1( X, Y ) \
+((GLubyte *)wmesa->pbPixels + (wmesa->height-Y-1)* wmesa->ScanWidth + (X))
+#define PIXELADDR2( X, Y ) \
+((GLubyte *)wmesa->pbPixels + (wmesa->height-Y-1)* wmesa->ScanWidth + (X)*2)
+#define PIXELADDR4( X, Y ) \
+((GLubyte *)wmesa->pbPixels + (wmesa->height-Y-1)* wmesa->ScanWidth + (X)*4)
+
+
+BYTE DITHER_RGB_2_8BIT( int r, int g, int b, int x, int y);
+
+/* Finish all pending operations and synchronize. */
+static void finish(GLcontext* ctx)
+{
+ /* No op */
+}
+
+
+//
+// We cache all gl draw routines until a flush is made
+//
+static void flush(GLcontext* ctx)
+{
+ STARTPROFILE
+ if((Current->rgb_flag /*&& !(Current->dib.fFlushed)*/&&!(Current->db_flag))
+ ||(!Current->rgb_flag))
+ {
+ wmFlush(Current);
+ }
+ ENDPROFILE(flush)
+
+}
+
+
+
+/*
+* Set the color index used to clear the color buffer.
+*/
+static void clear_index(GLcontext* ctx, GLuint index)
+{
+ STARTPROFILE
+ Current->clearpixel = index;
+ ENDPROFILE(clear_index)
+}
+
+
+
+/*
+* Set the color used to clear the color buffer.
+*/
+static void clear_color( GLcontext* ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+ STARTPROFILE
+ Current->clearpixel=RGB(r, g, b );
+ ENDPROFILE(clear_color)
+}
+
+
+
+/*
+* Clear the specified region of the color buffer using the clear color
+* or index as specified by one of the two functions above.
+*/
+//static void clear(GLcontext* ctx,
+// GLboolean all,GLint x, GLint y, GLint width, GLint height )
+// TODO: I modified this function to match the prototype in dd.h. (swansma@geocities.com)
+// dd.h does not explain what the return type is so I could not set this to the proper
+// value.
+static GLbitfield clear(GLcontext* ctx, GLbitfield mask,
+ GLboolean all, GLint x, GLint y, GLint width, GLint height)
+{
+ DWORD dwColor;
+ WORD wColor;
+ BYTE bColor;
+ LPDWORD lpdw = (LPDWORD)Current->pbPixels;
+ LPWORD lpw = (LPWORD)Current->pbPixels;
+ LPBYTE lpb = Current->pbPixels;
+ int lines;
+
+ STARTPROFILE
+
+ if (all){
+ x=y=0;
+ width=Current->width;
+ height=Current->height;
+ }
+ if(Current->db_flag==GL_TRUE){
+ UINT nBypp = Current->cColorBits / 8;
+ int i = 0;
+ int iSize = 0;
+
+ if(nBypp ==1 ){
+ /* Need rectification */
+ iSize = Current->width/4;
+ bColor = BGR8(GetRValue(Current->clearpixel),
+ GetGValue(Current->clearpixel),
+ GetBValue(Current->clearpixel));
+ wColor = MAKEWORD(bColor,bColor);
+ dwColor = MAKELONG(wColor, wColor);
+ }
+ if(nBypp == 2){
+ iSize = Current->width / 2;
+ wColor = BGR16(GetRValue(Current->clearpixel),
+ GetGValue(Current->clearpixel),
+ GetBValue(Current->clearpixel));
+ dwColor = MAKELONG(wColor, wColor);
+ }
+ else if(nBypp == 4){
+ iSize = Current->width;
+ dwColor = BGR32(GetRValue(Current->clearpixel),
+ GetGValue(Current->clearpixel),
+ GetBValue(Current->clearpixel));
+ }
+
+ while(i < iSize){
+ *lpdw = dwColor;
+ lpdw++;
+ i++;
+ }
+
+ //
+ // This is the 24bit case
+ //
+ if (nBypp == 3) {
+ iSize = Current->width *3/4;
+ dwColor = BGR24(GetRValue(Current->clearpixel),
+ GetGValue(Current->clearpixel),
+ GetBValue(Current->clearpixel));
+ while(i < iSize){
+ *lpdw = dwColor;
+ lpb += nBypp;
+ lpdw = (LPDWORD)lpb;
+ i++;
+ }
+ }
+
+ i = 0;
+ if (stereo_flag)
+ lines = height /2;
+ else
+ lines = height;
+ do {
+ memcpy(lpb, Current->pbPixels, iSize*4);
+ lpb += Current->ScanWidth;
+ i++;
+ }
+ while (i<lines-1);
+ }
+ else { // For single buffer
+ HDC DC=DD_GETDC;
+ HPEN Pen=CreatePen(PS_SOLID,1,Current->clearpixel);
+ HBRUSH Brush=CreateSolidBrush(Current->clearpixel);
+ HPEN Old_Pen=SelectObject(DC,Pen);
+ HBRUSH Old_Brush=SelectObject(DC,Brush);
+ Rectangle(DC,x,y,x+width,y+height);
+ SelectObject(DC,Old_Pen);
+ SelectObject(DC,Old_Brush);
+ DeleteObject(Pen);
+ DeleteObject(Brush);
+ DD_RELEASEDC;
+ }
+
+
+
+ ENDPROFILE(clear)
+
+ return mask; // TODO: I doubt this is correct. dd.h doesn't explain what this should
+ // be...
+}
+
+
+
+/* Set the current color index. */
+static void set_index(GLcontext* ctx, GLuint index)
+{
+ STARTPROFILE
+ Current->pixel=index;
+ ENDPROFILE(set_index)
+}
+
+
+
+/* Set the current RGBA color. */
+static void set_color( GLcontext* ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+ STARTPROFILE
+ Current->pixel = RGB( r, g, b );
+ ENDPROFILE(set_color)
+}
+
+
+
+/* Set the index mode bitplane mask. */
+static GLboolean index_mask(GLcontext* ctx, GLuint mask)
+{
+ /* can't implement */
+ return GL_FALSE;
+}
+
+
+
+/* Set the RGBA drawing mask. */
+static GLboolean color_mask( GLcontext* ctx,
+ GLboolean rmask, GLboolean gmask,
+ GLboolean bmask, GLboolean amask)
+{
+ /* can't implement */
+ return GL_FALSE;
+}
+
+
+
+/*
+* Set the pixel logic operation. Return GL_TRUE if the device driver
+* can perform the operation, otherwise return GL_FALSE. If GL_FALSE
+* is returned, the logic op will be done in software by Mesa.
+*/
+GLboolean logicop( GLcontext* ctx, GLenum op )
+{
+ /* can't implement */
+ return GL_FALSE;
+}
+
+
+static void dither( GLcontext* ctx, GLboolean enable )
+{
+ if (!Current)
+ return;
+
+ if(enable == GL_FALSE){
+ Current->dither_flag = GL_FALSE;
+ if(Current->cColorBits == 8)
+ Current->pixelformat = PF_INDEX8;
+ }
+ else{
+ if (Current->rgb_flag && Current->cColorBits == 8){
+ Current->pixelformat = PF_DITHER8;
+ Current->dither_flag = GL_TRUE;
+ }
+ else
+ Current->dither_flag = GL_FALSE;
+ }
+}
+
+
+
+static GLboolean set_buffer( GLcontext* ctx, GLenum mode )
+{
+ STARTPROFILE
+ /* TODO: this could be better */
+ if (mode==GL_FRONT_LEFT || mode==GL_BACK_LEFT) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+ ENDPROFILE(set_buffer)
+}
+
+
+
+/* Return characteristics of the output buffer. */
+static void buffer_size( GLcontext* ctx, GLuint *width, GLuint *height )
+{
+ int New_Size;
+ RECT CR;
+
+ STARTPROFILE
+ GetClientRect(Current->Window,&CR);
+
+ *width=CR.right;
+ *height=CR.bottom;
+
+ New_Size=((*width)!=Current->width) || ((*height)!=Current->height);
+
+ if (New_Size){
+ Current->width=*width;
+ Current->height=*height;
+ Current->ScanWidth=Current->width;
+ if ((Current->ScanWidth%sizeof(long))!=0)
+ Current->ScanWidth+=(sizeof(long)-(Current->ScanWidth%sizeof(long)));
+
+ if (Current->db_flag){
+#ifdef DDRAW
+ DDDeleteOffScreen(Current);
+ DDCreateOffScreen(Current);
+#else
+ if (Current->rgb_flag==GL_TRUE && Current->dither_flag!=GL_TRUE){
+ wmDeleteBackingStore(Current);
+ wmCreateBackingStore(Current, Current->width, Current->height);
+ }
+#endif
+ }
+
+ // Resize OsmesaBuffer if in Parallel mode
+#if !defined(NO_PARALLEL)
+ if(parallelFlag)
+ PRSizeRenderBuffer(Current->width, Current->height,Current->ScanWidth,
+ Current->rgb_flag == GL_TRUE ? Current->pbPixels: Current->ScreenMem);
+#endif
+ }
+ ENDPROFILE(buffer_size)
+}
+
+
+
+/**********************************************************************/
+/***** Accelerated point, line, polygon rendering *****/
+/**********************************************************************/
+
+
+static void fast_rgb_points( GLcontext* ctx, GLuint first, GLuint last )
+{
+ GLuint i;
+ // HDC DC=DD_GETDC;
+ PWMC pwc = Current;
+
+ STARTPROFILE
+
+ if (0 /*Current->gl_ctx->VB->MonoColor*/) {
+ /* all drawn with current color */
+ for (i=first;i<=last;i++) {
+ if (!Current->gl_ctx->VB->ClipMask[i]) {
+ int x, y;
+ x = (GLint) Current->gl_ctx->VB->Win.data[i][0];
+ y = FLIP( (GLint) Current->gl_ctx->VB->Win.data[i][1] );
+ wmSetPixel(pwc, y,x,GetRValue(Current->pixel),
+ GetGValue(Current->pixel), GetBValue(Current->pixel));
+ }
+ }
+ }
+ else {
+ /* draw points of different colors */
+ for (i=first;i<=last;i++) {
+ if (!Current->gl_ctx->VB->ClipMask[i]) {
+ int x, y;
+ unsigned long pixel=RGB(Current->gl_ctx->VB->ColorPtr->data[i][0]*255.0,
+ Current->gl_ctx->VB->ColorPtr->data[i][1]*255.0,
+ Current->gl_ctx->VB->ColorPtr->data[i][2]*255.0);
+ x = (GLint) Current->gl_ctx->VB->Win.data[i][0];
+ y = FLIP( (GLint) Current->gl_ctx->VB->Win.data[i][1] );
+ wmSetPixel(pwc, y,x,Current->gl_ctx->VB->ColorPtr->data[i][0]*255.0,
+ Current->gl_ctx->VB->ColorPtr->data[i][1]*255.0,
+ Current->gl_ctx->VB->ColorPtr->data[i][2]*255.0);
+ }
+ }
+ }
+ // DD_RELEASEDC;
+ ENDPROFILE(fast_rgb_points)
+}
+
+
+
+/* Return pointer to accerated points function */
+extern points_func choose_points_function( GLcontext* ctx )
+{
+ STARTPROFILE
+ if (ctx->Point.Size==1.0 && !ctx->Point.SmoothFlag && ctx->RasterMask==0
+ && !ctx->Texture.Enabled && ctx->Visual->RGBAflag) {
+ ENDPROFILE(choose_points_function)
+ return fast_rgb_points;
+ }
+ else {
+ ENDPROFILE(choose_points_function)
+ return NULL;
+ }
+}
+
+
+
+/* Draw a line using the color specified by Current->gl_ctx->VB->ColorPtr->data[pv] */
+static void fast_flat_rgb_line( GLcontext* ctx, GLuint v0, GLuint v1, GLuint pv )
+{
+ STARTPROFILE
+ int x0, y0, x1, y1;
+ unsigned long pixel;
+ HDC DC=DD_GETDC;
+ HPEN Pen;
+ HPEN Old_Pen;
+
+ if (0 /*Current->gl_ctx->VB->MonoColor*/) {
+ pixel = Current->pixel; /* use current color */
+ }
+ else {
+ pixel = RGB(Current->gl_ctx->VB->ColorPtr->data[pv][0]*255.0, Current->gl_ctx->VB->ColorPtr->data[pv][1]*255.0, Current->gl_ctx->VB->ColorPtr->data[pv][2]*255.0);
+ }
+
+ x0 = (int) Current->gl_ctx->VB->Win.data[v0][0];
+ y0 = FLIP( (int) Current->gl_ctx->VB->Win.data[v0][1] );
+ x1 = (int) Current->gl_ctx->VB->Win.data[v1][0];
+ y1 = FLIP( (int) Current->gl_ctx->VB->Win.data[v1][1] );
+
+
+ BEGINGDICALL
+
+ Pen=CreatePen(PS_SOLID,1,pixel);
+ Old_Pen=SelectObject(DC,Pen);
+ MoveToEx(DC,x0,y0,NULL);
+ LineTo(DC,x1,y1);
+ SelectObject(DC,Old_Pen);
+ DeleteObject(Pen);
+ DD_RELEASEDC;
+
+ ENDGDICALL
+
+ ENDPROFILE(fast_flat_rgb_line)
+}
+
+
+
+/* Return pointer to accerated line function */
+static line_func choose_line_function( GLcontext* ctx )
+{
+ STARTPROFILE
+ if (ctx->Line.Width==1.0 && !ctx->Line.SmoothFlag && !ctx->Line.StippleFlag
+ && ctx->Light.ShadeModel==GL_FLAT && ctx->RasterMask==0
+ && !ctx->Texture.Enabled && Current->rgb_flag) {
+ ENDPROFILE(choose_line_function)
+ return fast_flat_rgb_line;
+ }
+ else {
+ ENDPROFILE(choose_line_function)
+ return NULL;
+ }
+}
+
+
+/**********************************************************************/
+/***** Span-based pixel drawing *****/
+/**********************************************************************/
+
+
+/* Write a horizontal span of 32-bit color-index pixels with a boolean mask. */
+static void write_ci32_span( const GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLuint index[],
+ const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ PBYTE Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i]=index[i];
+ ENDPROFILE(write_ci32_span)
+}
+
+
+/* Write a horizontal span of 8-bit color-index pixels with a boolean mask. */
+static void write_ci8_span( const GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte index[],
+ const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ PBYTE Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i]=index[i];
+ ENDPROFILE(write_ci8_span)
+}
+
+
+
+/*
+* Write a horizontal span of pixels with a boolean mask. The current
+* color index is used for all pixels.
+*/
+static void write_mono_ci_span(const GLcontext* ctx,
+ GLuint n,GLint x,GLint y,
+ const GLubyte mask[])
+{
+ STARTPROFILE
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i]=Current->pixel;
+ ENDPROFILE(write_mono_ci_span)
+}
+
+/*
+ * To improve the performance of this routine, frob the data into an actual
+ * scanline and call bitblt on the complete scan line instead of SetPixel.
+ */
+
+/* Write a horizontal span of RGBA color pixels with a boolean mask. */
+static void write_rgba_span( const GLcontext* ctx, GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4], const GLubyte mask[] )
+{
+ STARTPROFILE
+ PWMC pwc = Current;
+
+ if (pwc->rgb_flag==GL_TRUE)
+ {
+ GLuint i;
+ HDC DC=DD_GETDC;
+ y=FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, y, x + i, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ wmSetPixel(pwc, y, x + i, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ DD_RELEASEDC;
+ }
+ else
+ {
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
+ y = FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i] = GetNearestPaletteIndex(Current->hPal,RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]));
+ }
+ else {
+ for (i=0; i<n; i++)
+ Mem[i] = GetNearestPaletteIndex(Current->hPal,RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]));
+ }
+ }
+ ENDPROFILE(write_rgba_span)
+
+}
+
+/* Write a horizontal span of RGB color pixels with a boolean mask. */
+static void write_rgb_span( const GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgb[][3], const GLubyte mask[] )
+{
+ STARTPROFILE
+ PWMC pwc = Current;
+
+ if (pwc->rgb_flag==GL_TRUE)
+ {
+ GLuint i;
+ HDC DC=DD_GETDC;
+ y=FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, y, x + i, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ wmSetPixel(pwc, y, x + i, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+ }
+ DD_RELEASEDC;
+ }
+ else
+ {
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
+ y = FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i] = GetNearestPaletteIndex(Current->hPal,RGB(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]));
+ }
+ else {
+ for (i=0; i<n; i++)
+ Mem[i] = GetNearestPaletteIndex(Current->hPal,RGB(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]));
+ }
+ }
+ ENDPROFILE(write_rgb_span)
+
+}
+
+/*
+* Write a horizontal span of pixels with a boolean mask. The current color
+* is used for all pixels.
+*/
+static void write_mono_rgba_span( const GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte mask[])
+{
+ STARTPROFILE
+ GLuint i;
+ HDC DC=DD_GETDC;
+ PWMC pwc = Current;
+ assert(Current->rgb_flag==GL_TRUE);
+ y=FLIP(y);
+ if(Current->rgb_flag==GL_TRUE){
+ for (i=0; i<n; i++)
+ if (mask[i])
+ // Trying
+ wmSetPixel(pwc,y,x+i,GetRValue(Current->pixel), GetGValue(Current->pixel), GetBValue(Current->pixel));
+ }
+ else {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ SetPixel(DC, y, x+i, Current->pixel);
+ }
+ DD_RELEASEDC;
+ ENDPROFILE(write_mono_rgba_span)
+}
+
+
+
+/**********************************************************************/
+/***** Array-based pixel drawing *****/
+/**********************************************************************/
+
+
+/* Write an array of 32-bit index pixels with a boolean mask. */
+static void write_ci32_pixels( const GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLuint index[], const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ BYTE *Mem=Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i];
+ *Mem = index[i];
+ }
+ }
+ ENDPROFILE(write_ci32_pixels)
+}
+
+
+
+/*
+* Write an array of pixels with a boolean mask. The current color
+* index is used for all pixels.
+*/
+static void write_mono_ci_pixels( const GLcontext* ctx,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ BYTE *Mem=Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i];
+ *Mem = Current->pixel;
+ }
+ }
+ ENDPROFILE(write_mono_ci_pixels)
+}
+
+
+
+/* Write an array of RGBA pixels with a boolean mask. */
+static void write_rgba_pixels( const GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte rgba[][4], const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ PWMC pwc = Current;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, FLIP(y[i]),x[i],rgba[i][RCOMP],rgba[i][GCOMP],rgba[i][BCOMP]);
+ DD_RELEASEDC;
+ ENDPROFILE(write_rgba_pixels)
+}
+
+
+
+/*
+* Write an array of pixels with a boolean mask. The current color
+* is used for all pixels.
+*/
+static void write_mono_rgba_pixels( const GLcontext* ctx,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ PWMC pwc = Current;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, FLIP(y[i]),x[i],GetRValue(Current->pixel),
+ GetGValue(Current->pixel), GetBValue(Current->pixel));
+ DD_RELEASEDC;
+ ENDPROFILE(write_mono_rgba_pixels)
+}
+
+
+
+/**********************************************************************/
+/***** Read spans/arrays of pixels *****/
+/**********************************************************************/
+
+
+/* Read a horizontal span of color-index pixels. */
+static void read_ci32_span( const GLcontext* ctx, GLuint n, GLint x, GLint y,
+ GLuint index[])
+{
+ STARTPROFILE
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ index[i]=Mem[i];
+ ENDPROFILE(read_ci32_span)
+}
+
+
+
+
+/* Read an array of color index pixels. */
+static void read_ci32_pixels( const GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint indx[], const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ indx[i]=*(Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i]);
+ }
+ }
+ ENDPROFILE(read_ci32_pixels)
+}
+
+
+
+/* Read a horizontal span of color pixels. */
+static void read_rgba_span( const GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ STARTPROFILE
+ UINT i;
+ COLORREF Color;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ /* y=FLIP(y);*/
+ y = Current->height - y - 1;
+ for (i=0; i<n; i++) {
+ Color=GetPixel(DC,x+i,y);
+ rgba[i][RCOMP] = GetRValue(Color);
+ rgba[i][GCOMP] = GetGValue(Color);
+ rgba[i][BCOMP] = GetBValue(Color);
+ rgba[i][ACOMP] = 255;
+ }
+ DD_RELEASEDC;
+// Brian P. Has mentioned to comment this out.
+// memset(alpha,0,n*sizeof(GLubyte));
+ ENDPROFILE(read_rgba_span)
+}
+
+
+/* Read an array of color pixels. */
+static void read_rgba_pixels( const GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ COLORREF Color;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ Color=GetPixel(DC,x[i],FLIP(y[i]));
+ rgba[i][RCOMP] = GetRValue(Color);
+ rgba[i][GCOMP] = GetGValue(Color);
+ rgba[i][BCOMP] = GetBValue(Color);
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ DD_RELEASEDC;
+// Brian P. has mentioned to comment this out.
+// memset(alpha,0,n*sizeof(GLint));
+ ENDPROFILE(read_rgba_pixels)
+}
+
+
+
+/**********************************************************************/
+/**********************************************************************/
+
+
+static const char *renderer_string(void)
+{
+ return "Windows";
+}
+
+
+
+void setup_DD_pointers( GLcontext* ctx )
+{
+ ctx->Driver.RendererString = renderer_string;
+ ctx->Driver.UpdateState = setup_DD_pointers;
+ ctx->Driver.GetBufferSize = buffer_size;
+ ctx->Driver.Finish = finish;
+ ctx->Driver.Flush = flush;
+
+ ctx->Driver.ClearIndex = clear_index;
+ ctx->Driver.ClearColor = clear_color;
+ ctx->Driver.Clear = clear;
+
+ ctx->Driver.Index = set_index;
+ ctx->Driver.Color = set_color;
+ ctx->Driver.IndexMask = index_mask;
+ ctx->Driver.ColorMask = color_mask;
+
+ ctx->Driver.LogicOp = logicop;
+ ctx->Driver.Dither = dither;
+
+ ctx->Driver.SetBuffer = set_buffer;
+ ctx->Driver.GetBufferSize = buffer_size;
+
+ ctx->Driver.PointsFunc = choose_points_function(ctx);
+ ctx->Driver.LineFunc = choose_line_function(ctx);
+ ctx->Driver.TriangleFunc = choose_triangle_function( ctx );
+
+ /* Pixel/span writing functions: */
+ ctx->Driver.WriteRGBASpan = write_rgba_span;
+ ctx->Driver.WriteRGBSpan = write_rgb_span;
+ ctx->Driver.WriteMonoRGBASpan = write_mono_rgba_span;
+ ctx->Driver.WriteRGBAPixels = write_rgba_pixels;
+ ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels;
+ ctx->Driver.WriteCI32Span = write_ci32_span;
+ ctx->Driver.WriteCI8Span = write_ci8_span;
+ ctx->Driver.WriteMonoCISpan = write_mono_ci_span;
+ ctx->Driver.WriteCI32Pixels = write_ci32_pixels;
+ ctx->Driver.WriteMonoCIPixels = write_mono_ci_pixels;
+
+ ctx->Driver.ReadCI32Span = read_ci32_span;
+ ctx->Driver.ReadRGBASpan = read_rgba_span;
+ ctx->Driver.ReadCI32Pixels = read_ci32_pixels;
+ ctx->Driver.ReadRGBAPixels = read_rgba_pixels;
+}
+
+
+/**********************************************************************/
+/***** WMesa API Functions *****/
+/**********************************************************************/
+
+
+
+#define PAL_SIZE 256
+static void GetPalette(HPALETTE Pal,RGBQUAD *aRGB)
+{
+ STARTPROFILE
+ int i;
+ HDC hdc;
+ struct
+ {
+ WORD Version;
+ WORD NumberOfEntries;
+ PALETTEENTRY aEntries[PAL_SIZE];
+ } Palette =
+ {
+ 0x300,
+ PAL_SIZE
+ };
+ hdc=GetDC(NULL);
+ if (Pal!=NULL)
+ GetPaletteEntries(Pal,0,PAL_SIZE,Palette.aEntries);
+ else
+ GetSystemPaletteEntries(hdc,0,PAL_SIZE,Palette.aEntries);
+ if (GetSystemPaletteUse(hdc) == SYSPAL_NOSTATIC)
+ {
+ for(i = 0; i <PAL_SIZE; i++)
+ Palette.aEntries[i].peFlags = PC_RESERVED;
+ Palette.aEntries[255].peRed = 255;
+ Palette.aEntries[255].peGreen = 255;
+ Palette.aEntries[255].peBlue = 255;
+ Palette.aEntries[255].peFlags = 0;
+ Palette.aEntries[0].peRed = 0;
+ Palette.aEntries[0].peGreen = 0;
+ Palette.aEntries[0].peBlue = 0;
+ Palette.aEntries[0].peFlags = 0;
+ }
+ else
+ {
+ int nStaticColors;
+ int nUsableColors;
+ nStaticColors = GetDeviceCaps(hdc, NUMCOLORS)/2;
+ for (i=0; i<nStaticColors; i++)
+ Palette.aEntries[i].peFlags = 0;
+ nUsableColors = PAL_SIZE-nStaticColors;
+ for (; i<nUsableColors; i++)
+ Palette.aEntries[i].peFlags = PC_RESERVED;
+ for (; i<PAL_SIZE-nStaticColors; i++)
+ Palette.aEntries[i].peFlags = PC_RESERVED;
+ for (i=PAL_SIZE-nStaticColors; i<PAL_SIZE; i++)
+ Palette.aEntries[i].peFlags = 0;
+ }
+ ReleaseDC(NULL,hdc);
+ for (i=0; i<PAL_SIZE; i++)
+ {
+ aRGB[i].rgbRed=Palette.aEntries[i].peRed;
+ aRGB[i].rgbGreen=Palette.aEntries[i].peGreen;
+ aRGB[i].rgbBlue=Palette.aEntries[i].peBlue;
+ aRGB[i].rgbReserved=Palette.aEntries[i].peFlags;
+ }
+ ENDPROFILE(GetPalette)
+}
+
+
+WMesaContext WMesaCreateContext( HWND hWnd, HPALETTE* Pal,
+ GLboolean rgb_flag,
+ GLboolean db_flag )
+{
+ RECT CR;
+ WMesaContext c;
+ GLboolean true_color_flag;
+ c = (struct wmesa_context * ) calloc(1,sizeof(struct wmesa_context));
+ if (!c)
+ return NULL;
+
+ c->Window=hWnd;
+ c->hDC = GetDC(hWnd);
+ true_color_flag = GetDeviceCaps(c->hDC, BITSPIXEL) > 8;
+#ifdef DDRAW
+ if(true_color_flag) c->rgb_flag = rgb_flag = GL_TRUE;
+#endif
+
+
+#ifdef DITHER
+ if ((true_color_flag==GL_FALSE) && (rgb_flag == GL_TRUE)){
+ c->dither_flag = GL_TRUE;
+ c->hPalHalfTone = WinGCreateHalftonePalette();
+ }
+ else
+ c->dither_flag = GL_FALSE;
+#else
+ c->dither_flag = GL_FALSE;
+#endif
+
+
+ if (rgb_flag==GL_FALSE)
+ {
+ c->rgb_flag = GL_FALSE;
+ // c->pixel = 1;
+ c->db_flag = db_flag =GL_TRUE; // WinG requires double buffering
+ printf("Single buffer is not supported in color index mode, setting to double buffer.\n");
+ }
+ else
+ {
+ c->rgb_flag = GL_TRUE;
+ // c->pixel = 0;
+ }
+ GetClientRect(c->Window,&CR);
+ c->width=CR.right;
+ c->height=CR.bottom;
+ if (db_flag)
+ {
+ c->db_flag = 1;
+ /* Double buffered */
+#ifndef DDRAW
+ // if (c->rgb_flag==GL_TRUE && c->dither_flag != GL_TRUE )
+ {
+ wmCreateBackingStore(c, c->width, c->height);
+
+ }
+#endif
+ }
+ else
+ {
+ /* Single Buffered */
+ if (c->rgb_flag)
+ c->db_flag = 0;
+ }
+#ifdef DDRAW
+ if (DDInit(c,hWnd) == GL_FALSE) {
+ free( (void *) c );
+ exit(1);
+ }
+#endif
+
+
+ c->gl_visual = gl_create_visual(rgb_flag,
+ GL_FALSE, /* software alpha */
+ db_flag, /* db_flag */
+ GL_FALSE, /* stereo */
+ 16, /* depth_bits */
+ 8, /* stencil_bits */
+ 8, /* accum_bits */
+ 0, /* index bits */
+ 8,8,8,8 ); /* r, g, b, a bits */
+
+ if (!c->gl_visual) {
+ return NULL;
+ }
+
+ /* allocate a new Mesa context */
+ c->gl_ctx = gl_create_context( c->gl_visual, NULL, c, GL_TRUE);
+
+ if (!c->gl_ctx) {
+ gl_destroy_visual( c->gl_visual );
+ free(c);
+ return NULL;
+ }
+
+ c->gl_buffer = gl_create_framebuffer( c->gl_visual );
+ if (!c->gl_buffer) {
+ gl_destroy_visual( c->gl_visual );
+ gl_destroy_context( c->gl_ctx );
+ free(c);
+ return NULL;
+ }
+
+ c->gl_ctx->Driver.UpdateState = setup_DD_pointers;
+
+ // setup_DD_pointers(c->gl_ctx);
+
+ return c;
+}
+
+void WMesaDestroyContext( void )
+{
+ WMesaContext c = Current;
+ ReleaseDC(c->Window,c->hDC);
+ WC = c;
+ if(c->hPalHalfTone != NULL)
+ DeleteObject(c->hPalHalfTone);
+ gl_destroy_visual( c->gl_visual );
+ gl_destroy_framebuffer( c->gl_buffer );
+ gl_destroy_context( c->gl_ctx );
+
+ if (c->db_flag)
+#ifdef DDRAW
+ DDFree(c);
+#else
+ wmDeleteBackingStore(c);
+#endif
+ free( (void *) c );
+ //Following code is added to enable parallel render
+ // Parallel render only work in double buffer mode
+#if !defined(NO_PARALLEL)
+ if(parallelMachine)
+ PRDestroyRenderBuffer();
+#endif
+ // End modification
+}
+
+
+
+void /*APIENTRY*/ WMesaMakeCurrent( WMesaContext c )
+{
+ if(!c){
+ Current = c;
+ return;
+ }
+
+ //
+ // A little optimization
+ // If it already is current,
+ // don't set it again
+ //
+ if(Current == c)
+ return;
+
+ //gl_set_context( c->gl_ctx );
+ gl_make_current(c->gl_ctx, c->gl_buffer);
+ setup_DD_pointers(c->gl_ctx);
+ Current = c;
+ if (Current->gl_ctx->Viewport.Width==0) {
+ /* initialize viewport to window size */
+ gl_Viewport( Current->gl_ctx,
+ 0, 0, Current->width, Current->height );
+ }
+ if ((c->cColorBits <= 8 ) && (c->rgb_flag == GL_TRUE)){
+ WMesaPaletteChange(c->hPalHalfTone);
+ }
+}
+
+
+
+void /*APIENTRY*/ WMesaSwapBuffers( void )
+{
+ HDC DC = Current->hDC;
+ if (Current->db_flag)
+ wmFlush(Current);
+}
+
+
+
+void /*APIENTRY*/ WMesaPaletteChange(HPALETTE Pal)
+{
+ int vRet;
+ LPPALETTEENTRY pPal;
+ if (Current && (Current->rgb_flag==GL_FALSE || Current->dither_flag == GL_TRUE))
+ {
+ pPal = (PALETTEENTRY *)malloc( 256 * sizeof(PALETTEENTRY));
+ Current->hPal=Pal;
+ // GetPaletteEntries( Pal, 0, 256, pPal );
+ GetPalette( Pal, pPal );
+#ifdef DDRAW
+ Current->lpDD->lpVtbl->CreatePalette(Current->lpDD,DDPCAPS_8BIT,
+ pPal, &(Current->lpDDPal), NULL);
+ if (Current->lpDDPal)
+ Current->lpDDSPrimary->lpVtbl->SetPalette(Current->lpDDSPrimary,Current->lpDDPal);
+#else
+ vRet = SetDIBColorTable(Current->dib.hDC,0,256,pPal);
+#endif
+ free( pPal );
+ }
+
+}
+
+
+
+
+static unsigned char threeto8[8] = {
+ 0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377
+};
+
+static unsigned char twoto8[4] = {
+ 0, 0x55, 0xaa, 0xff
+};
+
+static unsigned char oneto8[2] = {
+ 0, 255
+};
+
+static unsigned char componentFromIndex(UCHAR i, UINT nbits, UINT shift)
+{
+ unsigned char val;
+
+ val = i >> shift;
+ switch (nbits) {
+
+ case 1:
+ val &= 0x1;
+ return oneto8[val];
+
+ case 2:
+ val &= 0x3;
+ return twoto8[val];
+
+ case 3:
+ val &= 0x7;
+ return threeto8[val];
+
+ default:
+ return 0;
+ }
+}
+
+void /*WINAPI*/ wmCreatePalette( PWMC pwdc )
+{
+ /* Create a compressed and re-expanded 3:3:2 palette */
+ int i;
+ LOGPALETTE *pPal;
+ BYTE rb, rs, gb, gs, bb, bs;
+
+ pwdc->nColors = 0x100;
+
+ pPal = (PLOGPALETTE)malloc(sizeof(LOGPALETTE) + pwdc->nColors * sizeof(PALETTEENTRY));
+ memset( pPal, 0, sizeof(LOGPALETTE) + pwdc->nColors * sizeof(PALETTEENTRY) );
+
+ pPal->palVersion = 0x300;
+
+ rb = REDBITS;
+ rs = REDSHIFT;
+ gb = GREENBITS;
+ gs = GREENSHIFT;
+ bb = BLUEBITS;
+ bs = BLUESHIFT;
+
+ if (pwdc->db_flag) {
+
+ /* Need to make two palettes: one for the screen DC and one for the DIB. */
+ pPal->palNumEntries = pwdc->nColors;
+ for (i = 0; i < pwdc->nColors; i++) {
+ pPal->palPalEntry[i].peRed = componentFromIndex( i, rb, rs );
+ pPal->palPalEntry[i].peGreen = componentFromIndex( i, gb, gs );
+ pPal->palPalEntry[i].peBlue = componentFromIndex( i, bb, bs );
+ pPal->palPalEntry[i].peFlags = 0;
+ }
+ pwdc->hGLPalette = CreatePalette( pPal );
+ pwdc->hPalette = CreatePalette( pPal );
+ }
+
+ else {
+ pPal->palNumEntries = pwdc->nColors;
+ for (i = 0; i < pwdc->nColors; i++) {
+ pPal->palPalEntry[i].peRed = componentFromIndex( i, rb, rs );
+ pPal->palPalEntry[i].peGreen = componentFromIndex( i, gb, gs );
+ pPal->palPalEntry[i].peBlue = componentFromIndex( i, bb, bs );
+ pPal->palPalEntry[i].peFlags = 0;
+ }
+ pwdc->hGLPalette = CreatePalette( pPal );
+ }
+
+ free(pPal);
+
+}
+
+void /*WINAPI*/ wmSetPixel(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b)
+{
+ if (Current->db_flag) {
+ LPBYTE lpb = pwc->pbPixels;
+ LPDWORD lpdw;
+ LPWORD lpw;
+ UINT nBypp = pwc->cColorBits >> 3;
+ UINT nOffset = iPixel % nBypp;
+
+ // Move the pixel buffer pointer to the scanline that we
+ // want to access
+
+ // pwc->dib.fFlushed = FALSE;
+
+ lpb += pwc->ScanWidth * iScanLine;
+ // Now move to the desired pixel
+ lpb += iPixel * nBypp;
+ lpb = PIXELADDR(iPixel, iScanLine);
+ lpdw = (LPDWORD)lpb;
+ lpw = (LPWORD)lpb;
+
+ if(nBypp == 1){
+ if(pwc->dither_flag)
+ *lpb = DITHER_RGB_2_8BIT(r,g,b,iScanLine,iPixel);
+ else
+ *lpb = BGR8(r,g,b);
+ }
+ else if(nBypp == 2)
+ *lpw = BGR16(r,g,b);
+ else if (nBypp == 3){
+ *lpdw = BGR24(r,g,b);
+ }
+ else if (nBypp == 4)
+ *lpdw = BGR32(r,g,b);
+ }
+ else{
+ SetPixel(Current->hDC, iPixel, iScanLine, RGB(r,g,b));
+ DD_RELEASEDC;
+ }
+}
+
+void /*WINAPI*/ wmCreateDIBSection(
+ HDC hDC,
+ PWMC pwc, // handle of device context
+ CONST BITMAPINFO *pbmi, // address of structure containing bitmap size, format, and color data
+ UINT iUsage // color data type indicator: RGB values or palette indices
+ )
+{
+ DWORD dwSize = 0;
+ DWORD dwScanWidth;
+ UINT nBypp = pwc->cColorBits / 8;
+ HDC hic;
+
+ dwScanWidth = (((pwc->ScanWidth * nBypp)+ 3) & ~3);
+
+ pwc->ScanWidth =pwc->pitch = dwScanWidth;
+
+ if (stereo_flag)
+ pwc->ScanWidth = 2* pwc->pitch;
+
+ dwSize = sizeof(BITMAPINFO) + (dwScanWidth * pwc->height);
+
+ pwc->dib.hFileMap = CreateFileMapping((HANDLE)PAGE_FILE,
+ NULL,
+ PAGE_READWRITE | SEC_COMMIT,
+ 0,
+ dwSize,
+ NULL);
+
+ if (!pwc->dib.hFileMap)
+ return;
+
+ pwc->dib.base = MapViewOfFile(pwc->dib.hFileMap,
+ FILE_MAP_ALL_ACCESS,
+ 0,
+ 0,
+ 0);
+
+ if(!pwc->dib.base){
+ CloseHandle(pwc->dib.hFileMap);
+ return;
+ }
+
+ // pwc->pbPixels = pwc->addrOffScreen = ((LPBYTE)pwc->dib.base) + sizeof(BITMAPINFO);
+
+ // pwc->dib.hDC = CreateCompatibleDC(hDC);
+
+ CopyMemory(pwc->dib.base, pbmi, sizeof(BITMAPINFO));
+
+ hic = CreateIC("display", NULL, NULL, NULL);
+ pwc->dib.hDC = CreateCompatibleDC(hic);
+
+
+ /* pwc->hbmDIB = CreateDIBitmap(hic,
+ &(pwc->bmi.bmiHeader),
+ CBM_INIT,
+ pwc->pbPixels,
+ &(pwc->bmi),
+ DIB_RGB_COLORS);
+ */
+ pwc->hbmDIB = CreateDIBSection(hic,
+ &(pwc->bmi),
+ (iUsage ? DIB_PAL_COLORS : DIB_RGB_COLORS),
+ &(pwc->pbPixels),
+ pwc->dib.hFileMap,
+ 0);
+ /*
+ pwc->hbmDIB = CreateDIBSection(hic,
+ &(pwc->bmi),
+ DIB_RGB_COLORS,
+ &(pwc->pbPixels),
+ pwc->dib.hFileMap,
+ 0);
+ */
+ pwc->ScreenMem = pwc->addrOffScreen = pwc->pbPixels;
+ pwc->hOldBitmap = SelectObject(pwc->dib.hDC, pwc->hbmDIB);
+
+ DeleteDC(hic);
+
+ return;
+
+}
+
+//
+// Blit memory DC to screen DC
+//
+BOOL /*WINAPI*/ wmFlush(PWMC pwc)
+{
+ BOOL bRet = 0;
+ DWORD dwErr = 0;
+#ifdef DDRAW
+ HRESULT ddrval;
+#endif
+
+ // Now search through the torus frames and mark used colors
+ if(pwc->db_flag){
+#ifdef DDRAW
+ if (pwc->lpDDSOffScreen == NULL)
+ if(DDCreateOffScreen(pwc) == GL_FALSE)
+ return;
+
+ pwc->lpDDSOffScreen->lpVtbl->Unlock(pwc->lpDDSOffScreen, NULL);
+
+ while( 1 )
+ {
+ ddrval = pwc->lpDDSPrimary->lpVtbl->Blt( pwc->lpDDSPrimary,
+ &(pwc->rectSurface), pwc->lpDDSOffScreen, &(pwc->rectOffScreen), 0, NULL );
+
+ if( ddrval == DD_OK )
+ {
+ break;
+ }
+ if( ddrval == DDERR_SURFACELOST )
+ {
+ if(!DDRestoreAll(pwc))
+ {
+ break;
+ }
+ }
+ if( ddrval != DDERR_WASSTILLDRAWING )
+ {
+ break;
+ }
+ }
+
+ while (pwc->lpDDSOffScreen->lpVtbl->Lock(pwc->lpDDSOffScreen,
+ NULL, &(pwc->ddsd), 0, NULL) == DDERR_WASSTILLDRAWING)
+ ;
+
+ if(ddrval != DD_OK)
+ dwErr = GetLastError();
+#else
+ bRet = BitBlt(pwc->hDC, 0, 0, pwc->width, pwc->height,
+ pwc->dib.hDC, 0, 0, SRCCOPY);
+#endif
+ }
+
+ return(TRUE);
+
+}
+
+
+// The following code is added by Li Wei to enable stereo display
+
+#if !defined(NO_STEREO)
+
+void WMesaShowStereo(GLuint list)
+{
+
+ GLbitfield mask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
+ GLfloat cm[16];
+ GLint matrix_mode;
+ // Must use double Buffer
+ if( ! Current-> db_flag )
+ return;
+
+
+ glGetIntegerv(GL_MATRIX_MODE,&matrix_mode);
+
+ // glPushMatrix(); //****
+ WMesaViewport(Current->gl_ctx,0,Current->height/2,Current->width,Current->height/2);
+ // Current->gl_ctx->NewState = 0;
+
+ // glViewport(0,0,Current->width,Current->height/2);
+ if(matrix_mode!=GL_MODELVIEW)
+ glMatrixMode(GL_MODELVIEW);
+
+ glGetFloatv(GL_MODELVIEW_MATRIX,cm);
+ glLoadIdentity();
+ gluLookAt(viewDistance/2,0.0,0.0 ,
+ viewDistance/2,0.0,-1.0,
+ 0.0,1.0,0.0 );
+ // glTranslatef(viewDistance/2.0,0.,0.);
+ glMultMatrixf( cm );
+
+ Current->ScreenMem = Current->pbPixels = Current->addrOffScreen;
+ //glPushMatrix();
+ glCallList( list );
+ //glPopMatrix();
+
+ glGetFloatv(GL_MODELVIEW_MATRIX,cm);
+ glLoadIdentity();
+ gluLookAt(-viewDistance/2,0.0,0.0 ,
+ -viewDistance/2,0.0,-1.0,
+ 0.0,1.0,0.0 );
+ // glTranslatef(-viewDistance/2.0,0.,0.);
+ glMultMatrixf(cm);
+
+ Current->ScreenMem = Current->pbPixels = Current->addrOffScreen + Current->pitch;
+ glCallList(list);
+ if(matrix_mode!=GL_MODELVIEW)
+ glMatrixMode(matrix_mode);
+
+ // glPopMatrix();
+ glFlush();
+
+ WMesaViewport(Current->gl_ctx,0,0,Current->width,Current->height);
+ // Current->gl_ctx->NewState = 0;
+ WMesaSwapBuffers();
+
+}
+
+void toggleStereoMode()
+{
+ if(!Current->db_flag)
+ return;
+ if(!stereo_flag){
+ stereo_flag = 1;
+ if(stereoBuffer==GL_FALSE)
+#if !defined(NO_PARALLEL)
+ if(!parallelFlag)
+#endif
+ {
+ Current->ScanWidth = Current->pitch*2;
+ }
+ }
+ else {
+ stereo_flag = 0;
+#if !defined(NO_PARALLEL)
+ if(!parallelFlag)
+#endif
+ Current->ScanWidth = Current->pitch;
+ Current->pbPixels = Current->addrOffScreen;
+ }
+}
+
+/* if in stereo mode, the following function is called */
+void glShowStereo(GLuint list)
+{
+ WMesaShowStereo(list);
+}
+
+#endif // End if NO_STEREO not defined
+
+#if !defined(NO_PARALLEL)
+
+void toggleParallelMode(void)
+{
+ if(!parallelFlag){
+ parallelFlag = GL_TRUE;
+ if(parallelMachine==GL_FALSE){
+ PRCreateRenderBuffer( Current->rgb_flag? GL_RGBA :GL_COLOR_INDEX,
+ Current->cColorBits/8,
+ Current->width ,Current->height,
+ Current->ScanWidth,
+ Current->rgb_flag? Current->pbPixels: Current->ScreenMem);
+ parallelMachine = GL_TRUE;
+ }
+ }
+ else {
+ parallelFlag = GL_FALSE;
+ if(parallelMachine==GL_TRUE){
+ PRDestroyRenderBuffer();
+ parallelMachine=GL_FALSE;
+ ReadyForNextFrame = GL_TRUE;
+ }
+
+ /***********************************************
+ // Seems something wrong!!!!
+ ************************************************/
+
+ WMesaMakeCurrent(Current);
+#if !defined(NO_STEREO)
+ stereo_flag = GL_FALSE ;
+#endif
+ }
+}
+
+void PRShowRenderResult(void)
+{
+ int flag = 0;
+ if(!glImageRendered())
+ return;
+
+ if (parallelFlag)
+ {
+ WMesaSwapBuffers();
+ }
+
+}
+#endif //End if NO_PARALLEL not defined
+
+//end modification
+
+BYTE DITHER_RGB_2_8BIT( int red, int green, int blue, int pixel, int scanline)
+{
+ char unsigned redtemp, greentemp, bluetemp, paletteindex;
+
+ //*** now, look up each value in the halftone matrix
+ //*** using an 8x8 ordered dither.
+ redtemp = aDividedBy51[red]
+ + (aModulo51[red] > aHalftone8x8[(pixel%8)*8
+ + scanline%8]);
+ greentemp = aDividedBy51[(char unsigned)green]
+ + (aModulo51[green] > aHalftone8x8[
+ (pixel%8)*8 + scanline%8]);
+ bluetemp = aDividedBy51[(char unsigned)blue]
+ + (aModulo51[blue] > aHalftone8x8[
+ (pixel%8)*8 +scanline%8]);
+
+ //*** recombine the halftoned rgb values into a palette index
+ paletteindex =
+ redtemp + aTimes6[greentemp] + aTimes36[bluetemp];
+
+ //*** and translate through the wing halftone palette
+ //*** translation vector to give the correct value.
+ return aWinGHalftoneTranslation[paletteindex];
+}
+
+#ifdef DDRAW
+/*
+* restoreAll
+*
+* restore all lost objects
+*/
+HRESULT DDRestoreAll( WMesaContext wc )
+{
+ HRESULT ddrval;
+
+ ddrval = wc->lpDDSPrimary->lpVtbl->Restore(wc->lpDDSPrimary);
+ if( ddrval == DD_OK )
+ {
+ ddrval = wc->lpDDSOffScreen->lpVtbl->Restore(wc->lpDDSOffScreen);
+ }
+ return ddrval;
+
+} /* restoreAll */
+
+
+ /*
+ * This function is called if the initialization function fails
+*/
+BOOL initFail( HWND hwnd, WMesaContext wc )
+{
+ DDFree(wc);
+ MessageBox( hwnd, "DirectDraw Init FAILED", "", MB_OK );
+ return FALSE;
+
+} /* initFail */
+
+
+static void DDDeleteOffScreen(WMesaContext wc)
+{
+ if( wc->lpDDSOffScreen != NULL )
+ {
+ wc->lpDDSOffScreen->lpVtbl->Unlock(wc->lpDDSOffScreen,NULL);
+ wc->lpDDSOffScreen->lpVtbl->Release(wc->lpDDSOffScreen);
+ wc->lpDDSOffScreen = NULL;
+ }
+
+}
+
+static void DDFreePrimarySurface(WMesaContext wc)
+{
+ if( wc->lpDDSPrimary != NULL )
+ {
+ if(wc->db_flag == GL_FALSE)
+ wc->lpDDSPrimary->lpVtbl->ReleaseDC(wc->lpDDSPrimary, wc->hDC);
+ wc->lpDDSPrimary->lpVtbl->Release(wc->lpDDSPrimary);
+ wc->lpDDSPrimary = NULL;
+ }
+}
+
+static BOOL DDCreatePrimarySurface(WMesaContext wc)
+{
+ HRESULT ddrval;
+ DDSCAPS ddscaps;
+ wc->ddsd.dwSize = sizeof( wc->ddsd );
+ wc->ddsd.dwFlags = DDSD_CAPS;
+ wc->ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+
+ ddrval = wc->lpDD->lpVtbl->CreateSurface( wc->lpDD,&(wc->ddsd), &(wc->lpDDSPrimary), NULL );
+ if( ddrval != DD_OK )
+ {
+ return initFail(wc->hwnd , wc);
+ }
+ if(wc->db_flag == GL_FALSE)
+ wc->lpDDSPrimary->lpVtbl->GetDC(wc->lpDDSPrimary, wc->hDC);
+ return TRUE;
+}
+
+static BOOL DDCreateOffScreen(WMesaContext wc)
+{
+ POINT pt;
+ HRESULT ddrval;
+ if(wc->lpDD == NULL)
+ return FALSE;
+ GetClientRect( wc->hwnd, &(wc->rectOffScreen) );
+ wc->ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
+ wc->ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
+ wc->ddsd.dwHeight = wc->rectOffScreen.bottom - wc->rectOffScreen.top;
+ wc->ddsd.dwWidth = wc->rectOffScreen.right - wc->rectOffScreen.left;
+
+ ddrval = wc->lpDD->lpVtbl->CreateSurface( wc->lpDD, &(wc->ddsd), &(wc->lpDDSOffScreen), NULL );
+ if( ddrval != DD_OK )
+ {
+ return FALSE;
+ }
+
+ while (wc->lpDDSOffScreen->lpVtbl->Lock(wc->lpDDSOffScreen,NULL, &(wc->ddsd), 0, NULL) == DDERR_WASSTILLDRAWING)
+ ;
+ // while ((ddrval = wc->lpDDSOffScreen->lpVtbl->Lock(wc->lpDDSOffScreen,NULL, &(wc->ddsd), DDLOCK_SURFACEMEMORYPTR , NULL)) != DD_OK)
+ ;
+ if(wc->ddsd.lpSurface==NULL)
+ return initFail(wc->hwnd, wc);
+
+ wc->ScreenMem = wc->pbPixels = wc->addrOffScreen = (PBYTE)(wc->ddsd.lpSurface);
+ wc->ScanWidth = wc->pitch = wc->ddsd.lPitch;
+ if (stereo_flag)
+ wc->ScanWidth = wc->ddsd.lPitch*2;
+
+ GetClientRect( wc->hwnd, &(wc->rectSurface) );
+ pt.x = pt.y = 0;
+ ClientToScreen( wc->hwnd, &pt );
+ OffsetRect(&(wc->rectSurface), pt.x, pt.y);
+ wmSetPixelFormat(wc, wc->hDC);
+ return TRUE;
+}
+
+/*
+* doInit - do work required for every instance of the application:
+* create the window, initialize data
+*/
+static BOOL DDInit( WMesaContext wc, HWND hwnd)
+{
+ HRESULT ddrval;
+ DWORD dwFrequency;
+
+ LPDIRECTDRAW lpDD; // DirectDraw object
+ LPDIRECTDRAW2 lpDD2;
+
+
+ wc->fullScreen = displayOptions.fullScreen;
+ wc->gMode = displayOptions.mode;
+ wc->hwnd = hwnd;
+ stereo_flag = displayOptions.stereo;
+ if(wc->db_flag!= GL_TRUE)
+ stereo_flag = GL_FALSE;
+ /*
+ * create the main DirectDraw object
+ */
+ ddrval = DirectDrawCreate( NULL, &(wc->lpDD), NULL );
+ if( ddrval != DD_OK )
+ {
+ return initFail(hwnd,wc);
+ }
+
+ // Get exclusive mode if requested
+ if(wc->fullScreen)
+ {
+ ddrval = wc->lpDD->lpVtbl->SetCooperativeLevel( wc->lpDD, hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
+ }
+ else
+ {
+ ddrval = wc->lpDD->lpVtbl->SetCooperativeLevel( wc->lpDD, hwnd, DDSCL_NORMAL );
+ }
+ if( ddrval != DD_OK )
+ {
+ return initFail(hwnd , wc);
+ }
+
+
+ /* ddrval = wc->lpDD->lpVtbl->QueryInterface(wc->lpDD, IID_IDirectDraw2,
+ (LPVOID *)((wc->lpDD2)));
+
+ */
+ if(ddrval != DD_OK)
+ return initFail(hwnd , wc);
+
+
+ //ddrval = wc->lpDD->lpVtbl->GetDisplayMode( wc->lpDD, &(wc->ddsd));
+ // wc->lpDD2->lpVtbl->GetMonitorFrequency(wc->lpDD, &dwFrequency);
+ switch( wc->gMode )
+ {
+ case 1: ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 640, 480, displayOptions.bpp); break;
+ case 2: ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 800, 600, displayOptions.bpp); break;
+ case 3: ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 1024, 768, displayOptions.bpp); break;
+ case 4: ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 1152, 864, displayOptions.bpp); break;
+ case 5: ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 1280, 1024, displayOptions.bpp); break;
+ }
+
+ if( ddrval != DD_OK )
+ {
+ printf("Can't modify display mode, current mode used\n");
+ // return initFail(hwnd , wc);
+ }
+ //ddrval = wc->lpDD->lpVtbl->GetDisplayMode( wc->lpDD, &(wc->ddsd));
+ switch(ddrval){
+ case DDERR_INVALIDOBJECT:
+ break;
+ case DDERR_INVALIDPARAMS:
+ break;
+ case DDERR_UNSUPPORTEDMODE:
+ ;
+ }
+
+ if(DDCreatePrimarySurface(wc) == GL_FALSE)
+ return initFail(hwnd, wc);
+
+ if(wc->db_flag)
+ return DDCreateOffScreen(wc);
+} /* DDInit */
+
+static void DDFree( WMesaContext wc)
+{
+ if( wc->lpDD != NULL )
+ {
+ DDFreePrimarySurface(wc);
+ DDDeleteOffScreen(wc);
+ wc->lpDD->lpVtbl->Release(wc->lpDD);
+ wc->lpDD = NULL;
+ }
+ // Clean up the screen on exit
+ RedrawWindow( NULL, NULL, NULL, RDW_INVALIDATE | RDW_ERASE |
+ RDW_ALLCHILDREN );
+
+}
+#endif
+
+void WMesaMove(void)
+{
+ WMesaContext wc = Current;
+ POINT pt;
+ if (Current != NULL){
+ GetClientRect( wc->hwnd, &(wc->rectSurface) );
+ pt.x = pt.y = 0;
+ ClientToScreen( wc->hwnd, &pt );
+ OffsetRect(&(wc->rectSurface), pt.x, pt.y);
+ }
+}
+
+
+
+/*
+* Like PACK_8A8B8G8R() but don't use alpha. This is usually an acceptable
+* shortcut.
+*/
+#define PACK_8B8G8R( R, G, B ) ( ((B) << 16) | ((G) << 8) | (R) )
+
+
+/**********************************************************************/
+/*** Triangle rendering ***/
+/**********************************************************************/
+
+/*
+ * XImage, smooth, depth-buffered, PF_8A8B8G8R triangle.
+ */
+static void smooth_8A8B8G8R_z_triangle( GLcontext *ctx,
+ GLuint v0, GLuint v1, GLuint v2,
+ GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = PACK_8B8G8R( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb) ); \
+ zRow[i] = z; \
+ } \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ ffz += fdzdx; \
+ } \
+ }
+
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+ #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+/*
+* XImage, smooth, depth-buffered, PF_8R8G8B triangle.
+*/
+static void smooth_8R8G8B_z_triangle( GLcontext *ctx,
+ GLuint v0, GLuint v1, GLuint v2,
+ GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = PACK_8R8G8B( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb) ); \
+ zRow[i] = z; \
+ } \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+ #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+
+/*
+* XImage, smooth, depth-buffered, PF_5R6G5B triangle.
+*/
+static void smooth_5R6G5B_z_triangle( GLcontext *ctx,
+ GLuint v0, GLuint v1, GLuint v2,
+ GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y)
+#define PIXEL_TYPE GLushort
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = PACK_5R6G5B( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb) ); \
+ zRow[i] = z; \
+ } \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+ #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+/*
+* XImage, flat, depth-buffered, PF_8A8B8G8R triangle.
+*/
+static void flat_8A8B8G8R_z_triangle( GLcontext *ctx, GLuint v0,
+ GLuint v1, GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ unsigned long p = PACK_8B8G8R( VB->ColorPtr->data[pv][0], \
+ VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2] );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = p; \
+ zRow[i] = z; \
+ } \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+ #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+/*
+* XImage, flat, depth-buffered, PF_8R8G8B triangle.
+*/
+static void flat_8R8G8B_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ unsigned long p = PACK_8R8G8B( VB->ColorPtr->data[pv][0], \
+ VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2] );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = p; \
+ zRow[i] = z; \
+ } \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+ #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+/*
+* XImage, flat, depth-buffered, PF_5R6G5B triangle.
+*/
+static void flat_5R6G5B_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y)
+#define PIXEL_TYPE GLushort
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ unsigned long p = PACK_5R6G5B( VB->ColorPtr->data[pv][0], \
+ VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2] );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = p; \
+ zRow[i] = z; \
+ } \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+ #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+/*
+* XImage, smooth, NON-depth-buffered, PF_8A8B8G8R triangle.
+*/
+static void smooth_8A8B8G8R_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = PACK_8B8G8R( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb) ); \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+ #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+/*
+* XImage, smooth, NON-depth-buffered, PF_8R8G8B triangle.
+*/
+static void smooth_8R8G8B_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = PACK_8R8G8B( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb) ); \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+ #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+/*
+* XImage, smooth, NON-depth-buffered, PF_5R6G5B triangle.
+*/
+static void smooth_5R6G5B_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y)
+#define PIXEL_TYPE GLushort
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = PACK_5R6G5B( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb) ); \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+ #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+
+/*
+* XImage, flat, NON-depth-buffered, PF_8A8B8G8R triangle.
+*/
+static void flat_8A8B8G8R_triangle( GLcontext *ctx, GLuint v0,
+ GLuint v1, GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ unsigned long p = PACK_8B8G8R( VB->ColorPtr->data[pv][0], \
+ VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2] );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = p; \
+ } \
+ }
+
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+ #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+/*
+* XImage, flat, NON-depth-buffered, PF_8R8G8B triangle.
+*/
+static void flat_8R8G8B_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ unsigned long p = PACK_8R8G8B( VB->ColorPtr->data[pv][0], \
+ VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2] );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = p; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+ #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+/*
+* XImage, flat, NON-depth-buffered, PF_5R6G5B triangle.
+*/
+static void flat_5R6G5B_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y)
+#define PIXEL_TYPE GLushort
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ unsigned long p = PACK_5R6G5B( VB->ColorPtr->data[pv][0], \
+ VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2] );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = p; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+ #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+/*
+* XImage, smooth, depth-buffered, 8-bit PF_LOOKUP triangle.
+*/
+
+static void smooth_ci_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define INTERP_INDEX 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = FixedToInt(ffi); \
+ zRow[i] = z; \
+ } \
+ ffi += fdidx; \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+ #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+/*
+* XImage, flat, depth-buffered, 8-bit PF_LOOKUP triangle.
+*/
+
+static void flat_ci_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ GLuint index = VB->IndexPtr->data[pv]; \
+ (*ctx->Driver.Index)( ctx, index );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = index; \
+ zRow[i] = z; \
+ } \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+ #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+
+/*
+* XImage, smooth, NON-depth-buffered, 8-bit PF_LOOKUP triangle.
+*/
+
+static void smooth_ci_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define INTERP_INDEX 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = FixedToInt(ffi); \
+ ffi += fdidx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+ #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+/*
+* XImage, flat, NON-depth-buffered, 8-bit PF_LOOKUP triangle.
+*/
+static void flat_ci_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ GLuint index = VB->IndexPtr->data[pv]; \
+ (*ctx->Driver.Index)( ctx, index );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = index; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+ #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+/*
+* XImage, smooth, depth-buffered, 8-bit, PF_DITHER8 triangle.
+*/
+static void smooth_DITHER8_z_triangle( GLcontext *ctx,
+ GLuint v0, GLuint v1, GLuint v2,
+ GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+ DITHER_RGB_TO_8BIT_SETUP
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, xx = LEFT, yy = FLIP(Y), len = RIGHT-LEFT; \
+ for (i=0;i<len;i++,xx++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ DITHER_RGB_TO_8BIT( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb), xx, yy); \
+ pRow[i] = pixelDithered; \
+ zRow[i] = z; \
+ } \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+ #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+/*
+* XImage, flat, depth-buffered, 8-bit PF_DITHER triangle.
+*/
+static void flat_DITHER8_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+ DITHER_RGB_TO_8BIT_SETUP
+#define INTERP_Z 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, xx = LEFT, yy = FLIP(Y), len = RIGHT-LEFT; \
+ for (i=0;i<len;i++,xx++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ DITHER_RGB_TO_8BIT( VB->ColorPtr->data[pv][0], \
+ VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2], xx, yy); \
+ pRow[i] = pixelDithered; \
+ zRow[i] = z; \
+ } \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+ #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+/*
+* XImage, smooth, NON-depth-buffered, 8-bit PF_DITHER triangle.
+*/
+static void smooth_DITHER8_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+ DITHER_RGB_TO_8BIT_SETUP
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx, yy = FLIP(Y); \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ DITHER_RGB_TO_8BIT( VB->ColorPtr->data[pv][0], VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2], xx, yy);\
+ *pixel = pixelDithered; \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+ #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+/*
+* XImage, flat, NON-depth-buffered, 8-bit PF_DITHER triangle.
+*/
+
+static void flat_DITHER8_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+ DITHER_RGB_TO_8BIT_SETUP
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx, yy = FLIP(Y); \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ DITHER_RGB_TO_8BIT( VB->ColorPtr->data[pv][0], \
+ VB->ColorPtr->data[pv][1], VB->ColorPtr->data[pv][2], xx, yy); \
+ *pixel = pixelDithered; \
+ } \
+ }
+#ifdef __MINGW32__
+ #include "tritemp.h"
+#else
+
+ #ifdef WIN32
+ #include "..\tritemp.h"
+ #else
+ #include "tritemp.h"
+ #endif
+#endif
+}
+
+
+
+
+static triangle_func choose_triangle_function( GLcontext *ctx )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+ int depth = wmesa->cColorBits;
+
+ if (ctx->Polygon.SmoothFlag) return NULL;
+ if (ctx->Texture.Enabled) return NULL;
+ if (!wmesa->db_flag) return NULL;
+ /*if (wmesa->xm_buffer->buffer==XIMAGE)*/ {
+ if ( ctx->Light.ShadeModel==GL_SMOOTH
+ && ctx->RasterMask==DEPTH_BIT
+ && ctx->Depth.Func==GL_LESS
+ && ctx->Depth.Mask==GL_TRUE
+ && ctx->Polygon.StippleFlag==GL_FALSE) {
+ switch (wmesa->pixelformat) {
+ case PF_8A8B8G8R:
+ return smooth_8A8B8G8R_z_triangle;
+ case PF_8R8G8B:
+ return smooth_8R8G8B_z_triangle;
+ case PF_5R6G5B:
+ return smooth_5R6G5B_z_triangle;
+ case PF_DITHER8:
+ return smooth_DITHER8_z_triangle;
+ case PF_INDEX8:
+ return smooth_ci_z_triangle;
+ default:
+ return NULL;
+ }
+ }
+ if ( ctx->Light.ShadeModel==GL_FLAT
+ && ctx->RasterMask==DEPTH_BIT
+ && ctx->Depth.Func==GL_LESS
+ && ctx->Depth.Mask==GL_TRUE
+ && ctx->Polygon.StippleFlag==GL_FALSE) {
+ switch (wmesa->pixelformat) {
+ case PF_8A8B8G8R:
+ return flat_8A8B8G8R_z_triangle;
+ case PF_8R8G8B:
+ return flat_8R8G8B_z_triangle;
+ case PF_5R6G5B:
+ return flat_5R6G5B_z_triangle;
+ case PF_DITHER8:
+ return flat_DITHER8_z_triangle;
+ case PF_INDEX8:
+ return flat_ci_z_triangle;
+ default:
+ return NULL;
+ }
+ }
+ if ( ctx->RasterMask==0 /* no depth test */
+ && ctx->Light.ShadeModel==GL_SMOOTH
+ && ctx->Polygon.StippleFlag==GL_FALSE) {
+ switch (wmesa->pixelformat) {
+ case PF_8A8B8G8R:
+ return smooth_8A8B8G8R_triangle;
+ case PF_8R8G8B:
+ return smooth_8R8G8B_triangle;
+ case PF_5R6G5B:
+ return smooth_5R6G5B_triangle;
+ case PF_DITHER8:
+ return smooth_DITHER8_triangle;
+ case PF_INDEX8:
+ return smooth_ci_triangle;
+ default:
+ return NULL;
+ }
+ }
+
+ if ( ctx->RasterMask==0 /* no depth test */
+ && ctx->Light.ShadeModel==GL_FLAT
+ && ctx->Polygon.StippleFlag==GL_FALSE) {
+ switch (wmesa->pixelformat) {
+ case PF_8A8B8G8R:
+ return flat_8A8B8G8R_triangle;
+ case PF_8R8G8B:
+ return flat_8R8G8B_triangle;
+ case PF_5R6G5B:
+ return flat_5R6G5B_triangle;
+ case PF_DITHER8:
+ return flat_DITHER8_triangle;
+ case PF_INDEX8:
+ return flat_ci_triangle;
+ default:
+ return NULL;
+ }
+ }
+
+ return NULL;
+ }
+}
+
+/*
+* Define a new viewport and reallocate auxillary buffers if the size of
+* the window (color buffer) has changed.
+*/
+void WMesaViewport( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height )
+{
+ /* Save viewport */
+ ctx->Viewport.X = x;
+ ctx->Viewport.Width = width;
+ ctx->Viewport.Y = y;
+ ctx->Viewport.Height = height;
+
+ /* compute scale and bias values */
+/* Pre-Keith 3.1 changes
+ ctx->Viewport.Map.m[Sx] = (GLfloat) width / 2.0F;
+ ctx->Viewport.Map.m[Tx] = ctx->Viewport.Sx + x;
+ ctx->Viewport.Map.m[Sy] = (GLfloat) height / 2.0F;
+ ctx->Viewport.Map.m[Ty] = ctx->Viewport.Sy + y;
+*/
+ ctx->Viewport.WindowMap.m[MAT_SX] = (GLfloat) width / 2.0F;
+ ctx->Viewport.WindowMap.m[MAT_TX] = ctx->Viewport.WindowMap.m[MAT_SX] + x;
+ ctx->Viewport.WindowMap.m[MAT_SY] = (GLfloat) height / 2.0F;
+ ctx->Viewport.WindowMap.m[MAT_TY] = ctx->Viewport.WindowMap.m[MAT_SY] + y;
+}
diff --git a/src/mesa/drivers/windows/wmesaBackup.c b/src/mesa/drivers/windows/wmesaBackup.c
new file mode 100644
index 0000000000..57269fbadb
--- /dev/null
+++ b/src/mesa/drivers/windows/wmesaBackup.c
@@ -0,0 +1,2879 @@
+/* $Id: wmesaBackup.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+* File name : wmesa.c
+* Version : 2.3
+*
+* Display driver for Mesa 2.3 under
+* Windows95 and WindowsNT
+*
+* Copyright (C) 1996- Li Wei
+* Address : Institute of Artificial Intelligence
+* : & Robotics
+* : Xi'an Jiaotong University
+* Email : liwei@aiar.xjtu.edu.cn
+* Web page : http://sun.aiar.xjtu.edu.cn
+*
+* This file and its associations are partially borrowed from the
+* Windows NT driver for Mesa 1.8 , written by Mark Leaming
+* (mark@rsinc.com).
+*/
+
+
+/*
+ * $Log: wmesaBackup.c,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 1.1 1999/01/03 03:08:57 brianp
+ * Initial revision
+ *
+ * Revision 3.1 1998/06/11 01:42:08 brianp
+ * updated for Mesa 3.0 device driver interface (but not tested)
+ *
+ * Revision 3.0 1998/06/11 01:18:25 brianp
+ * initial revision
+ *
+ */
+
+
+#define WMESA_STEREO_C
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <GL/wmesa.h>
+#include "mesa_extend.h"
+#include "colors.h"
+#include "macros.h"
+#include "context.h"
+#include "dd.h"
+#include "xform.h"
+#include "vb.h"
+#include "matrix.h"
+#include "depth.h"
+#include "wmesadef.h"
+
+#pragma warning ( disable : 4133 4761 )
+
+#ifdef PROFILE
+// #include "profile.h"
+#endif
+
+#ifdef DITHER
+#include <wing.h>
+#endif
+
+#ifdef __CYGWIN32__
+#include "macros.h"
+#include <string.h>
+#define CopyMemory memcpy
+#endif
+
+#if !defined(NO_STEREO)
+
+#include "gl\glu.h"
+#include "stereo.h"
+
+#endif
+#if !defined(NO_PARALLEL)
+// #include "parallel.h"
+#endif
+
+struct DISPLAY_OPTIONS displayOptions;
+
+GLenum stereoCompile = GL_FALSE ;
+GLenum stereoShowing = GL_FALSE ;
+GLenum stereoBuffer = GL_FALSE;
+#if !defined(NO_STEREO)
+GLint displayList = MAXIMUM_DISPLAY_LIST ;
+#endif
+GLint stereo_flag = 0 ;
+
+/* end of added code*/
+
+static PWMC Current = NULL;
+WMesaContext WC = NULL;
+
+#ifdef NDEBUG
+#define assert(ignore) ((void) 0)
+#else
+void Mesa_Assert(void *Cond,void *File,unsigned Line)
+{
+ char Msg[512];
+ sprintf(Msg,"%s %s %d",Cond,File,Line);
+ MessageBox(NULL,Msg,"Assertion failed.",MB_OK);
+ exit(1);
+}
+#define assert(e) if (!e) Mesa_Assert(#e,__FILE__,__LINE__);
+#endif
+
+//#define DD_GETDC (Current->hDC )
+#define DD_GETDC ((Current->db_flag) ? Current->dib.hDC : Current->hDC )
+//#define DD_GETDC ((Current->db_flag) ? Current->hDCPrimary : Current->hDCBack )
+#define DD_RELEASEDC
+
+//#define BEGINGDICALL if(Current->rgb_flag)wmFlushBits(Current);
+#define BEGINGDICALL
+//#define ENDGDICALL if(Current->rgb_flag)wmGetBits(Current);
+#define ENDGDICALL
+
+//#define FLIP(Y) (Current->dither_flag? Y : Current->height-(Y)-1)
+//#define FLIP(Y) (Current->height-(Y)-1)
+//#define FLIP(Y) Y
+#define FLIP(Y) (Current->db_flag? Y: Current->height-(Y)-1)
+#define STARTPROFILE
+#define ENDPROFILE(PARA)
+
+#define DITHER_RGB_TO_8BIT_SETUP \
+GLubyte pixelDithered;
+
+#define DITHER_RGB_TO_8BIT(red, green, blue, pixel, scanline) \
+{ \
+ char unsigned redtemp, greentemp, bluetemp, paletteindex; \
+ redtemp = aDividedBy51[red] \
+ + (aModulo51[red] > aHalftone8x8[(pixel%8)*8 \
+ + scanline%8]); \
+ greentemp = aDividedBy51[(char unsigned)green] \
+ + (aModulo51[green] > aHalftone8x8[ \
+ (pixel%8)*8 + scanline%8]); \
+ bluetemp = aDividedBy51[(char unsigned)blue] \
+ + (aModulo51[blue] > aHalftone8x8[ \
+ (pixel%8)*8 +scanline%8]); \
+ paletteindex = redtemp + aTimes6[greentemp] + aTimes36[bluetemp]; \
+ pixelDithered = aWinGHalftoneTranslation[paletteindex]; \
+}
+
+
+#ifdef DDRAW
+static BOOL DDInit( WMesaContext wc, HWND hwnd);
+static void DDFree( WMesaContext wc);
+static HRESULT DDRestoreAll( WMesaContext wc );
+static void DDDeleteOffScreen(WMesaContext wc);
+static BOOL DDCreateOffScreen(WMesaContext wc);
+#endif
+
+static void FlushToFile(PWMC pwc, PSTR szFile);
+
+BOOL wmCreateBackingStore(PWMC pwc, long lxSize, long lySize);
+BOOL wmDeleteBackingStore(PWMC pwc);
+void wmCreatePalette( PWMC pwdc );
+BOOL wmSetDibColors(PWMC pwc);
+void wmSetPixel(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b);
+
+void wmCreateDIBSection(
+ HDC hDC,
+ PWMC pwc, // handle of device context
+ CONST BITMAPINFO *pbmi, // address of structure containing bitmap size, format, and color data
+ UINT iUsage // color data type indicator: RGB values or palette indices
+ );
+
+
+void WMesaViewport( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height );
+
+
+static triangle_func choose_triangle_function( GLcontext *ctx );
+
+
+static void wmSetPixelFormat( PWMC wc, HDC hDC)
+{
+ if(wc->rgb_flag)
+ wc->cColorBits = GetDeviceCaps(hDC, BITSPIXEL);
+ else
+ wc->cColorBits = 8;
+ switch(wc->cColorBits){
+ case 8:
+ if(wc->dither_flag != GL_TRUE)
+ wc->pixelformat = PF_INDEX8;
+ else
+ wc->pixelformat = PF_DITHER8;
+ break;
+ case 16:
+ wc->pixelformat = PF_5R6G5B;
+ break;
+ case 32:
+ wc->pixelformat = PF_8R8G8B;
+ break;
+ default:
+ wc->pixelformat = PF_BADFORMAT;
+ }
+}
+
+//
+// This function sets the color table of a DIB section
+// to match that of the destination DC
+//
+BOOL /*WINAPI*/ wmSetDibColors(PWMC pwc)
+{
+ RGBQUAD *pColTab, *pRGB;
+ PALETTEENTRY *pPal, *pPE;
+ int i, nColors;
+ BOOL bRet=TRUE;
+ DWORD dwErr=0;
+
+ /* Build a color table in the DIB that maps to the
+ selected palette in the DC.
+ */
+ nColors = 1 << pwc->cColorBits;
+ pPal = (PALETTEENTRY *)malloc( nColors * sizeof(PALETTEENTRY));
+ memset( pPal, 0, nColors * sizeof(PALETTEENTRY) );
+ GetPaletteEntries( pwc->hGLPalette, 0, nColors, pPal );
+ pColTab = (RGBQUAD *)malloc( nColors * sizeof(RGBQUAD));
+ for (i = 0, pRGB = pColTab, pPE = pPal; i < nColors; i++, pRGB++, pPE++) {
+ pRGB->rgbRed = pPE->peRed;
+ pRGB->rgbGreen = pPE->peGreen;
+ pRGB->rgbBlue = pPE->peBlue;
+ }
+ if(pwc->db_flag)
+ bRet = SetDIBColorTable(pwc->dib.hDC, 0, nColors, pColTab );
+
+ if(!bRet)
+ dwErr = GetLastError();
+
+ free( pColTab );
+ free( pPal );
+
+ return(bRet);
+}
+
+
+//
+// Free up the dib section that was created
+//
+BOOL wmDeleteBackingStore(PWMC pwc)
+{
+ SelectObject(pwc->dib.hDC, pwc->hOldBitmap);
+ DeleteDC(pwc->dib.hDC);
+ DeleteObject(pwc->hbmDIB);
+ UnmapViewOfFile(pwc->dib.base);
+ CloseHandle(pwc->dib.hFileMap);
+ return TRUE;
+}
+
+
+//
+// This function creates the DIB section that is used for combined
+// GL and GDI calls
+//
+BOOL /*WINAPI*/ wmCreateBackingStore(PWMC pwc, long lxSize, long lySize)
+{
+ HDC hdc = pwc->hDC;
+ LPBITMAPINFO pbmi = &(pwc->bmi);
+ int iUsage;
+
+ pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ pbmi->bmiHeader.biWidth = lxSize;
+ pbmi->bmiHeader.biHeight= -lySize;
+ pbmi->bmiHeader.biPlanes = 1;
+ if(pwc->rgb_flag)
+ pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwc->hDC, BITSPIXEL);
+ else
+ pbmi->bmiHeader.biBitCount = 8;
+ pbmi->bmiHeader.biCompression = BI_RGB;
+ pbmi->bmiHeader.biSizeImage = 0;
+ pbmi->bmiHeader.biXPelsPerMeter = 0;
+ pbmi->bmiHeader.biYPelsPerMeter = 0;
+ pbmi->bmiHeader.biClrUsed = 0;
+ pbmi->bmiHeader.biClrImportant = 0;
+
+ iUsage = (pbmi->bmiHeader.biBitCount <= 8) ? DIB_PAL_COLORS : DIB_RGB_COLORS;
+
+ pwc->cColorBits = pbmi->bmiHeader.biBitCount;
+ pwc->ScanWidth = pwc->pitch = lxSize;
+
+ wmCreateDIBSection(hdc, pwc, pbmi, iUsage);
+
+ if ((iUsage == DIB_PAL_COLORS) && !(pwc->hGLPalette)) {
+ wmCreatePalette( pwc );
+ wmSetDibColors( pwc );
+ }
+ wmSetPixelFormat(pwc, pwc->hDC);
+ return(TRUE);
+
+}
+
+
+//
+// This function copies one scan line in a DIB section to another
+//
+BOOL GLWINAPI wmSetDIBits(PWMC pwc, UINT uiScanWidth, UINT uiNumScans, UINT nBypp, UINT uiNewWidth, LPBYTE pBits)
+{
+ UINT uiScans = 0;
+ LPBYTE pDest = pwc->pbPixels;
+ DWORD dwNextScan = uiScanWidth;
+ DWORD dwNewScan = uiNewWidth;
+ DWORD dwScanWidth = (uiScanWidth * nBypp);
+
+ //
+ // We need to round up to the nearest DWORD
+ // and multiply by the number of bytes per
+ // pixel
+ //
+ dwNextScan = (((dwNextScan * nBypp)+ 3) & ~3);
+ dwNewScan = (((dwNewScan * nBypp)+ 3) & ~3);
+
+ for(uiScans = 0; uiScans < uiNumScans; uiScans++){
+ CopyMemory(pDest, pBits, dwScanWidth);
+ pBits += dwNextScan;
+ pDest += dwNewScan;
+ }
+
+ return(TRUE);
+
+}
+
+
+BOOL wmFlush(PWMC pwc);
+
+/*
+* Useful macros:
+Modified from file osmesa.c
+*/
+
+
+#define PIXELADDR(X,Y) ((GLubyte *)Current->pbPixels + (Current->height-Y-1)* Current->ScanWidth + (X)*nBypp)
+#define PIXELADDR1( X, Y ) \
+((GLubyte *)wmesa->pbPixels + (wmesa->height-Y-1)* wmesa->ScanWidth + (X))
+#define PIXELADDR2( X, Y ) \
+((GLubyte *)wmesa->pbPixels + (wmesa->height-Y-1)* wmesa->ScanWidth + (X)*2)
+#define PIXELADDR4( X, Y ) \
+((GLubyte *)wmesa->pbPixels + (wmesa->height-Y-1)* wmesa->ScanWidth + (X)*4)
+
+
+BYTE DITHER_RGB_2_8BIT( int r, int g, int b, int x, int y);
+
+/* Finish all pending operations and synchronize. */
+static void finish(GLcontext* ctx)
+{
+ /* No op */
+}
+
+
+//
+// We cache all gl draw routines until a flush is made
+//
+static void flush(GLcontext* ctx)
+{
+ STARTPROFILE
+ if((Current->rgb_flag /*&& !(Current->dib.fFlushed)*/&&!(Current->db_flag))
+ ||(!Current->rgb_flag))
+ {
+ wmFlush(Current);
+ }
+ ENDPROFILE(flush)
+
+}
+
+
+
+/*
+* Set the color index used to clear the color buffer.
+*/
+static void clear_index(GLcontext* ctx, GLuint index)
+{
+ STARTPROFILE
+ Current->clearpixel = index;
+ ENDPROFILE(clear_index)
+}
+
+
+
+/*
+* Set the color used to clear the color buffer.
+*/
+static void clear_color( GLcontext* ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+ STARTPROFILE
+ Current->clearpixel=RGB(r, g, b );
+ ENDPROFILE(clear_color)
+}
+
+
+
+/*
+* Clear the specified region of the color buffer using the clear color
+* or index as specified by one of the two functions above.
+*/
+//static void clear(GLcontext* ctx,
+// GLboolean all,GLint x, GLint y, GLint width, GLint height )
+// TODO: I modified this function to match the prototype in dd.h. (swansma@geocities.com)
+// dd.h does not explain what the return type is so I could not set this to the proper
+// value.
+static GLbitfield clear(GLcontext* ctx, GLbitfield mask,
+ GLboolean all, GLint x, GLint y, GLint width, GLint height)
+{
+ DWORD dwColor;
+ WORD wColor;
+ BYTE bColor;
+ LPDWORD lpdw = (LPDWORD)Current->pbPixels;
+ LPWORD lpw = (LPWORD)Current->pbPixels;
+ LPBYTE lpb = Current->pbPixels;
+ int lines;
+
+ STARTPROFILE
+
+ if (all){
+ x=y=0;
+ width=Current->width;
+ height=Current->height;
+ }
+ if(Current->db_flag==GL_TRUE){
+ UINT nBypp = Current->cColorBits / 8;
+ int i = 0;
+ int iSize = 0;
+
+ if(nBypp ==1 ){
+ /* Need rectification */
+ iSize = Current->width/4;
+ bColor = BGR8(GetRValue(Current->clearpixel),
+ GetGValue(Current->clearpixel),
+ GetBValue(Current->clearpixel));
+ wColor = MAKEWORD(bColor,bColor);
+ dwColor = MAKELONG(wColor, wColor);
+ }
+ if(nBypp == 2){
+ iSize = Current->width / 2;
+ wColor = BGR16(GetRValue(Current->clearpixel),
+ GetGValue(Current->clearpixel),
+ GetBValue(Current->clearpixel));
+ dwColor = MAKELONG(wColor, wColor);
+ }
+ else if(nBypp == 4){
+ iSize = Current->width;
+ dwColor = BGR32(GetRValue(Current->clearpixel),
+ GetGValue(Current->clearpixel),
+ GetBValue(Current->clearpixel));
+ }
+
+ while(i < iSize){
+ *lpdw = dwColor;
+ lpdw++;
+ i++;
+ }
+
+ //
+ // This is the 24bit case
+ //
+ if (nBypp == 3) {
+ iSize = Current->width *3/4;
+ dwColor = BGR24(GetRValue(Current->clearpixel),
+ GetGValue(Current->clearpixel),
+ GetBValue(Current->clearpixel));
+ while(i < iSize){
+ *lpdw = dwColor;
+ lpb += nBypp;
+ lpdw = (LPDWORD)lpb;
+ i++;
+ }
+ }
+
+ i = 0;
+ if (stereo_flag)
+ lines = height /2;
+ else
+ lines = height;
+ do {
+ memcpy(lpb, Current->pbPixels, iSize*4);
+ lpb += Current->ScanWidth;
+ i++;
+ }
+ while (i<lines-1);
+ }
+ else { // For single buffer
+ HDC DC=DD_GETDC;
+ HPEN Pen=CreatePen(PS_SOLID,1,Current->clearpixel);
+ HBRUSH Brush=CreateSolidBrush(Current->clearpixel);
+ HPEN Old_Pen=SelectObject(DC,Pen);
+ HBRUSH Old_Brush=SelectObject(DC,Brush);
+ Rectangle(DC,x,y,x+width,y+height);
+ SelectObject(DC,Old_Pen);
+ SelectObject(DC,Old_Brush);
+ DeleteObject(Pen);
+ DeleteObject(Brush);
+ DD_RELEASEDC;
+ }
+
+
+
+ ENDPROFILE(clear)
+
+ return mask; // TODO: I doubt this is correct. dd.h doesn't explain what this should
+ // be...
+}
+
+
+
+/* Set the current color index. */
+static void set_index(GLcontext* ctx, GLuint index)
+{
+ STARTPROFILE
+ Current->pixel=index;
+ ENDPROFILE(set_index)
+}
+
+
+
+/* Set the current RGBA color. */
+static void set_color( GLcontext* ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+ STARTPROFILE
+ Current->pixel = RGB( r, g, b );
+ ENDPROFILE(set_color)
+}
+
+
+
+/* Set the index mode bitplane mask. */
+static GLboolean index_mask(GLcontext* ctx, GLuint mask)
+{
+ /* can't implement */
+ return GL_FALSE;
+}
+
+
+
+/* Set the RGBA drawing mask. */
+static GLboolean color_mask( GLcontext* ctx,
+ GLboolean rmask, GLboolean gmask,
+ GLboolean bmask, GLboolean amask)
+{
+ /* can't implement */
+ return GL_FALSE;
+}
+
+
+
+/*
+* Set the pixel logic operation. Return GL_TRUE if the device driver
+* can perform the operation, otherwise return GL_FALSE. If GL_FALSE
+* is returned, the logic op will be done in software by Mesa.
+*/
+GLboolean logicop( GLcontext* ctx, GLenum op )
+{
+ /* can't implement */
+ return GL_FALSE;
+}
+
+
+static void dither( GLcontext* ctx, GLboolean enable )
+{
+ if(enable == GL_FALSE){
+ Current->dither_flag = GL_FALSE;
+ if(Current->cColorBits == 8)
+ Current->pixelformat = PF_INDEX8;
+ }
+ else{
+ if (Current->rgb_flag && Current->cColorBits == 8){
+ Current->pixelformat = PF_DITHER8;
+ Current->dither_flag = GL_TRUE;
+ }
+ else
+ Current->dither_flag = GL_FALSE;
+ }
+}
+
+
+
+static GLboolean set_buffer( GLcontext* ctx, GLenum mode )
+{
+ STARTPROFILE
+ /* TODO: this could be better */
+ if (mode==GL_FRONT || mode==GL_BACK) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+ ENDPROFILE(set_buffer)
+}
+
+
+
+/* Return characteristics of the output buffer. */
+static void buffer_size( GLcontext* ctx, GLuint *width, GLuint *height )
+{
+ int New_Size;
+ RECT CR;
+
+ STARTPROFILE
+ GetClientRect(Current->Window,&CR);
+
+ *width=CR.right;
+ *height=CR.bottom;
+
+ New_Size=((*width)!=Current->width) || ((*height)!=Current->height);
+
+ if (New_Size){
+ Current->width=*width;
+ Current->height=*height;
+ Current->ScanWidth=Current->width;
+ if ((Current->ScanWidth%sizeof(long))!=0)
+ Current->ScanWidth+=(sizeof(long)-(Current->ScanWidth%sizeof(long)));
+
+ if (Current->db_flag){
+#ifdef DDRAW
+ DDDeleteOffScreen(Current);
+ DDCreateOffScreen(Current);
+#else
+ if (Current->rgb_flag==GL_TRUE && Current->dither_flag!=GL_TRUE){
+ wmDeleteBackingStore(Current);
+ wmCreateBackingStore(Current, Current->width, Current->height);
+ }
+#endif
+ }
+
+ // Resize OsmesaBuffer if in Parallel mode
+#if !defined(NO_PARALLEL)
+ if(parallelFlag)
+ PRSizeRenderBuffer(Current->width, Current->height,Current->ScanWidth,
+ Current->rgb_flag == GL_TRUE ? Current->pbPixels: Current->ScreenMem);
+#endif
+ }
+ ENDPROFILE(buffer_size)
+}
+
+
+
+/**********************************************************************/
+/***** Accelerated point, line, polygon rendering *****/
+/**********************************************************************/
+
+
+static void fast_rgb_points( GLcontext* ctx, GLuint first, GLuint last )
+{
+ GLuint i;
+ // HDC DC=DD_GETDC;
+ PWMC pwc = Current;
+
+ STARTPROFILE
+
+ if (Current->gl_ctx->VB->MonoColor) {
+ /* all drawn with current color */
+ for (i=first;i<=last;i++) {
+ if (!Current->gl_ctx->VB->ClipMask[i]) {
+ int x, y;
+ x = (GLint) Current->gl_ctx->VB->Win[i][0];
+ y = FLIP( (GLint) Current->gl_ctx->VB->Win[i][1] );
+ wmSetPixel(pwc, y,x,GetRValue(Current->pixel),
+ GetGValue(Current->pixel), GetBValue(Current->pixel));
+ }
+ }
+ }
+ else {
+ /* draw points of different colors */
+ for (i=first;i<=last;i++) {
+ if (!Current->gl_ctx->VB->ClipMask[i]) {
+ int x, y;
+ unsigned long pixel=RGB(Current->gl_ctx->VB->Color[i][0]*255.0,
+ Current->gl_ctx->VB->Color[i][1]*255.0,
+ Current->gl_ctx->VB->Color[i][2]*255.0);
+ x = (GLint) Current->gl_ctx->VB->Win[i][0];
+ y = FLIP( (GLint) Current->gl_ctx->VB->Win[i][1] );
+ wmSetPixel(pwc, y,x,Current->gl_ctx->VB->Color[i][0]*255.0,
+ Current->gl_ctx->VB->Color[i][1]*255.0,
+ Current->gl_ctx->VB->Color[i][2]*255.0);
+ }
+ }
+ }
+ // DD_RELEASEDC;
+ ENDPROFILE(fast_rgb_points)
+}
+
+
+
+/* Return pointer to accerated points function */
+extern points_func choose_points_function( GLcontext* ctx )
+{
+ STARTPROFILE
+ if (ctx->Point.Size==1.0 && !ctx->Point.SmoothFlag && ctx->RasterMask==0
+ && !ctx->Texture.Enabled && ctx->Visual->RGBAflag) {
+ ENDPROFILE(choose_points_function)
+ return fast_rgb_points;
+ }
+ else {
+ ENDPROFILE(choose_points_function)
+ return NULL;
+ }
+}
+
+
+
+/* Draw a line using the color specified by Current->gl_ctx->VB->Color[pv] */
+static void fast_flat_rgb_line( GLcontext* ctx, GLuint v0, GLuint v1, GLuint pv )
+{
+ STARTPROFILE
+ int x0, y0, x1, y1;
+ unsigned long pixel;
+ HDC DC=DD_GETDC;
+ HPEN Pen;
+ HPEN Old_Pen;
+
+ if (Current->gl_ctx->VB->MonoColor) {
+ pixel = Current->pixel; /* use current color */
+ }
+ else {
+ pixel = RGB(Current->gl_ctx->VB->Color[pv][0]*255.0, Current->gl_ctx->VB->Color[pv][1]*255.0, Current->gl_ctx->VB->Color[pv][2]*255.0);
+ }
+
+ x0 = (int) Current->gl_ctx->VB->Win[v0][0];
+ y0 = FLIP( (int) Current->gl_ctx->VB->Win[v0][1] );
+ x1 = (int) Current->gl_ctx->VB->Win[v1][0];
+ y1 = FLIP( (int) Current->gl_ctx->VB->Win[v1][1] );
+
+
+ BEGINGDICALL
+
+ Pen=CreatePen(PS_SOLID,1,pixel);
+ Old_Pen=SelectObject(DC,Pen);
+ MoveToEx(DC,x0,y0,NULL);
+ LineTo(DC,x1,y1);
+ SelectObject(DC,Old_Pen);
+ DeleteObject(Pen);
+ DD_RELEASEDC;
+
+ ENDGDICALL
+
+ ENDPROFILE(fast_flat_rgb_line)
+}
+
+
+
+/* Return pointer to accerated line function */
+static line_func choose_line_function( GLcontext* ctx )
+{
+ STARTPROFILE
+ if (ctx->Line.Width==1.0 && !ctx->Line.SmoothFlag && !ctx->Line.StippleFlag
+ && ctx->Light.ShadeModel==GL_FLAT && ctx->RasterMask==0
+ && !ctx->Texture.Enabled && Current->rgb_flag) {
+ ENDPROFILE(choose_line_function)
+ return fast_flat_rgb_line;
+ }
+ else {
+ ENDPROFILE(choose_line_function)
+ return NULL;
+ }
+}
+
+
+/**********************************************************************/
+/***** Span-based pixel drawing *****/
+/**********************************************************************/
+
+
+/* Write a horizontal span of 32-bit color-index pixels with a boolean mask. */
+static void write_ci32_span( const GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLuint index[],
+ const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ PBYTE Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i]=index[i];
+ ENDPROFILE(write_ci32_span)
+}
+
+
+/* Write a horizontal span of 8-bit color-index pixels with a boolean mask. */
+static void write_ci8_span( const GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte index[],
+ const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ PBYTE Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i]=index[i];
+ ENDPROFILE(write_ci8_span)
+}
+
+
+
+/*
+* Write a horizontal span of pixels with a boolean mask. The current
+* color index is used for all pixels.
+*/
+static void write_mono_ci_span(const GLcontext* ctx,
+ GLuint n,GLint x,GLint y,
+ const GLubyte mask[])
+{
+ STARTPROFILE
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i]=Current->pixel;
+ ENDPROFILE(write_mono_ci_span)
+}
+
+/*
+ * To improve the performance of this routine, frob the data into an actual
+ * scanline and call bitblt on the complete scan line instead of SetPixel.
+ */
+
+/* Write a horizontal span of RGBA color pixels with a boolean mask. */
+static void write_rgba_span( const GLcontext* ctx, GLuint n, GLint x, GLint y,
+ const GLubyte rgba[][4], const GLubyte mask[] )
+{
+ STARTPROFILE
+ PWMC pwc = Current;
+
+ if (pwc->rgb_flag==GL_TRUE)
+ {
+ GLuint i;
+ HDC DC=DD_GETDC;
+ y=FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, y, x + i, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ wmSetPixel(pwc, y, x + i, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] );
+ }
+ DD_RELEASEDC;
+ }
+ else
+ {
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
+ y = FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i] = GetNearestPaletteIndex(Current->hPal,RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]));
+ }
+ else {
+ for (i=0; i<n; i++)
+ Mem[i] = GetNearestPaletteIndex(Current->hPal,RGB(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]));
+ }
+ }
+ ENDPROFILE(write_rgba_span)
+
+}
+
+/* Write a horizontal span of RGB color pixels with a boolean mask. */
+static void write_rgb_span( const GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte rgb[][3], const GLubyte mask[] )
+{
+ STARTPROFILE
+ PWMC pwc = Current;
+
+ if (pwc->rgb_flag==GL_TRUE)
+ {
+ GLuint i;
+ HDC DC=DD_GETDC;
+ y=FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, y, x + i, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
+ }
+ else {
+ for (i=0; i<n; i++)
+ wmSetPixel(pwc, y, x + i, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP] );
+ }
+ DD_RELEASEDC;
+ }
+ else
+ {
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
+ y = FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i] = GetNearestPaletteIndex(Current->hPal,RGB(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]));
+ }
+ else {
+ for (i=0; i<n; i++)
+ Mem[i] = GetNearestPaletteIndex(Current->hPal,RGB(rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]));
+ }
+ }
+ ENDPROFILE(write_rgb_span)
+
+}
+
+/*
+* Write a horizontal span of pixels with a boolean mask. The current color
+* is used for all pixels.
+*/
+static void write_mono_rgba_span( const GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte mask[])
+{
+ STARTPROFILE
+ GLuint i;
+ HDC DC=DD_GETDC;
+ PWMC pwc = Current;
+ assert(Current->rgb_flag==GL_TRUE);
+ y=FLIP(y);
+ if(Current->rgb_flag==GL_TRUE){
+ for (i=0; i<n; i++)
+ if (mask[i])
+ // Trying
+ wmSetPixel(pwc,y,x+i,GetRValue(Current->pixel), GetGValue(Current->pixel), GetBValue(Current->pixel));
+ }
+ else {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ SetPixel(DC, y, x+i, Current->pixel);
+ }
+ DD_RELEASEDC;
+ ENDPROFILE(write_mono_rgba_span)
+}
+
+
+
+/**********************************************************************/
+/***** Array-based pixel drawing *****/
+/**********************************************************************/
+
+
+/* Write an array of 32-bit index pixels with a boolean mask. */
+static void write_ci32_pixels( const GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLuint index[], const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ BYTE *Mem=Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i];
+ *Mem = index[i];
+ }
+ }
+ ENDPROFILE(write_ci32_pixels)
+}
+
+
+
+/*
+* Write an array of pixels with a boolean mask. The current color
+* index is used for all pixels.
+*/
+static void write_mono_ci_pixels( const GLcontext* ctx,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ BYTE *Mem=Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i];
+ *Mem = Current->pixel;
+ }
+ }
+ ENDPROFILE(write_mono_ci_pixels)
+}
+
+
+
+/* Write an array of RGBA pixels with a boolean mask. */
+static void write_rgba_pixels( const GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte rgba[][4], const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ PWMC pwc = Current;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, FLIP(y[i]),x[i],rgba[i][RCOMP],rgba[i][GCOMP],rgba[i][BCOMP]);
+ DD_RELEASEDC;
+ ENDPROFILE(write_rgba_pixels)
+}
+
+
+
+/*
+* Write an array of pixels with a boolean mask. The current color
+* is used for all pixels.
+*/
+static void write_mono_rgba_pixels( const GLcontext* ctx,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ PWMC pwc = Current;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, FLIP(y[i]),x[i],GetRValue(Current->pixel),
+ GetGValue(Current->pixel), GetBValue(Current->pixel));
+ DD_RELEASEDC;
+ ENDPROFILE(write_mono_rgba_pixels)
+}
+
+
+
+/**********************************************************************/
+/***** Read spans/arrays of pixels *****/
+/**********************************************************************/
+
+
+/* Read a horizontal span of color-index pixels. */
+static void read_ci32_span( const GLcontext* ctx, GLuint n, GLint x, GLint y,
+ GLuint index[])
+{
+ STARTPROFILE
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ index[i]=Mem[i];
+ ENDPROFILE(read_ci32_span)
+}
+
+
+
+
+/* Read an array of color index pixels. */
+static void read_ci32_pixels( const GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint indx[], const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ indx[i]=*(Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i]);
+ }
+ }
+ ENDPROFILE(read_ci32_pixels)
+}
+
+
+
+/* Read a horizontal span of color pixels. */
+static void read_rgba_span( const GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] )
+{
+ STARTPROFILE
+ UINT i;
+ COLORREF Color;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ y=FLIP(y);
+ for (i=0; i<n; i++) {
+ Color=GetPixel(DC,x+i,y);
+ rgba[i][RCOMP] = GetRValue(Color);
+ rgba[i][GCOMP] = GetGValue(Color);
+ rgba[i][BCOMP] = GetBValue(Color);
+ rgba[i][ACOMP] = 255;
+ }
+ DD_RELEASEDC;
+// Brian P. Has mentioned to comment this out.
+// memset(alpha,0,n*sizeof(GLubyte));
+ ENDPROFILE(read_rgba_span)
+}
+
+
+/* Read an array of color pixels. */
+static void read_rgba_pixels( const GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ COLORREF Color;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ Color=GetPixel(DC,x[i],FLIP(y[i]));
+ rgba[i][RCOMP] = GetRValue(Color);
+ rgba[i][GCOMP] = GetGValue(Color);
+ rgba[i][BCOMP] = GetBValue(Color);
+ rgba[i][ACOMP] = 255;
+ }
+ }
+ DD_RELEASEDC;
+// Brian P. has mentioned to comment this out.
+// memset(alpha,0,n*sizeof(GLint));
+ ENDPROFILE(read_rgba_pixels)
+}
+
+
+
+/**********************************************************************/
+/**********************************************************************/
+
+
+static const char *renderer_string(void)
+{
+ return "Windows";
+}
+
+
+
+void setup_DD_pointers( GLcontext* ctx )
+{
+ ctx->Driver.RendererString = renderer_string;
+ ctx->Driver.UpdateState = setup_DD_pointers;
+ ctx->Driver.GetBufferSize = buffer_size;
+ ctx->Driver.Finish = finish;
+ ctx->Driver.Flush = flush;
+
+ ctx->Driver.ClearIndex = clear_index;
+ ctx->Driver.ClearColor = clear_color;
+ ctx->Driver.Clear = clear;
+
+ ctx->Driver.Index = set_index;
+ ctx->Driver.Color = set_color;
+ ctx->Driver.IndexMask = index_mask;
+ ctx->Driver.ColorMask = color_mask;
+
+ ctx->Driver.LogicOp = logicop;
+ ctx->Driver.Dither = dither;
+
+ ctx->Driver.SetBuffer = set_buffer;
+ ctx->Driver.GetBufferSize = buffer_size;
+
+ ctx->Driver.PointsFunc = choose_points_function(ctx);
+ ctx->Driver.LineFunc = choose_line_function(ctx);
+ ctx->Driver.TriangleFunc = choose_triangle_function( ctx );
+
+ /* Pixel/span writing functions: */
+ ctx->Driver.WriteRGBASpan = write_rgba_span;
+ ctx->Driver.WriteRGBSpan = write_rgb_span;
+ ctx->Driver.WriteMonoRGBASpan = write_mono_rgba_span;
+ ctx->Driver.WriteRGBAPixels = write_rgba_pixels;
+ ctx->Driver.WriteMonoRGBAPixels = write_mono_rgba_pixels;
+ ctx->Driver.WriteCI32Span = write_ci32_span;
+ ctx->Driver.WriteCI8Span = write_ci8_span;
+ ctx->Driver.WriteMonoCISpan = write_mono_ci_span;
+ ctx->Driver.WriteCI32Pixels = write_ci32_pixels;
+ ctx->Driver.WriteMonoCIPixels = write_mono_ci_pixels;
+
+ ctx->Driver.ReadCI32Span = read_ci32_span;
+ ctx->Driver.ReadRGBASpan = read_rgba_span;
+ ctx->Driver.ReadCI32Pixels = read_ci32_pixels;
+ ctx->Driver.ReadRGBAPixels = read_rgba_pixels;
+}
+
+
+/**********************************************************************/
+/***** WMesa API Functions *****/
+/**********************************************************************/
+
+
+
+#define PAL_SIZE 256
+static void GetPalette(HPALETTE Pal,RGBQUAD *aRGB)
+{
+ STARTPROFILE
+ int i;
+ HDC hdc;
+ struct
+ {
+ WORD Version;
+ WORD NumberOfEntries;
+ PALETTEENTRY aEntries[PAL_SIZE];
+ } Palette =
+ {
+ 0x300,
+ PAL_SIZE
+ };
+ hdc=GetDC(NULL);
+ if (Pal!=NULL)
+ GetPaletteEntries(Pal,0,PAL_SIZE,Palette.aEntries);
+ else
+ GetSystemPaletteEntries(hdc,0,PAL_SIZE,Palette.aEntries);
+ if (GetSystemPaletteUse(hdc) == SYSPAL_NOSTATIC)
+ {
+ for(i = 0; i <PAL_SIZE; i++)
+ Palette.aEntries[i].peFlags = PC_RESERVED;
+ Palette.aEntries[255].peRed = 255;
+ Palette.aEntries[255].peGreen = 255;
+ Palette.aEntries[255].peBlue = 255;
+ Palette.aEntries[255].peFlags = 0;
+ Palette.aEntries[0].peRed = 0;
+ Palette.aEntries[0].peGreen = 0;
+ Palette.aEntries[0].peBlue = 0;
+ Palette.aEntries[0].peFlags = 0;
+ }
+ else
+ {
+ int nStaticColors;
+ int nUsableColors;
+ nStaticColors = GetDeviceCaps(hdc, NUMCOLORS)/2;
+ for (i=0; i<nStaticColors; i++)
+ Palette.aEntries[i].peFlags = 0;
+ nUsableColors = PAL_SIZE-nStaticColors;
+ for (; i<nUsableColors; i++)
+ Palette.aEntries[i].peFlags = PC_RESERVED;
+ for (; i<PAL_SIZE-nStaticColors; i++)
+ Palette.aEntries[i].peFlags = PC_RESERVED;
+ for (i=PAL_SIZE-nStaticColors; i<PAL_SIZE; i++)
+ Palette.aEntries[i].peFlags = 0;
+ }
+ ReleaseDC(NULL,hdc);
+ for (i=0; i<PAL_SIZE; i++)
+ {
+ aRGB[i].rgbRed=Palette.aEntries[i].peRed;
+ aRGB[i].rgbGreen=Palette.aEntries[i].peGreen;
+ aRGB[i].rgbBlue=Palette.aEntries[i].peBlue;
+ aRGB[i].rgbReserved=Palette.aEntries[i].peFlags;
+ }
+ ENDPROFILE(GetPalette)
+}
+
+
+WMesaContext WMesaCreateContext( HWND hWnd,
+ HPALETTE* Pal,
+ GLboolean rgb_flag,
+ GLboolean db_flag )
+{
+ RECT CR;
+ WMesaContext c;
+ GLboolean true_color_flag;
+ c = (struct wmesa_context * ) calloc(1,sizeof(struct wmesa_context));
+ if (!c)
+ return NULL;
+
+ c->Window=hWnd;
+ c->hDC = GetDC(hWnd);
+ true_color_flag = GetDeviceCaps(c->hDC, BITSPIXEL) > 8;
+#ifdef DDRAW
+ if(true_color_flag) c->rgb_flag = rgb_flag = GL_TRUE;
+#endif
+
+
+#ifdef DITHER
+ if ((true_color_flag==GL_FALSE) && (rgb_flag == GL_TRUE)){
+ c->dither_flag = GL_TRUE;
+ c->hPalHalfTone = WinGCreateHalftonePalette();
+ }
+ else
+ c->dither_flag = GL_FALSE;
+#else
+ c->dither_flag = GL_FALSE;
+#endif
+
+
+ if (rgb_flag==GL_FALSE)
+ {
+ c->rgb_flag = GL_FALSE;
+ // c->pixel = 1;
+ c->db_flag = db_flag =GL_TRUE; // WinG requires double buffering
+ printf("Single buffer is not supported in color index mode, setting to double buffer.\n");
+ }
+ else
+ {
+ c->rgb_flag = GL_TRUE;
+ // c->pixel = 0;
+ }
+ GetClientRect(c->Window,&CR);
+ c->width=CR.right;
+ c->height=CR.bottom;
+ if (db_flag)
+ {
+ c->db_flag = 1;
+ /* Double buffered */
+#ifndef DDRAW
+ // if (c->rgb_flag==GL_TRUE && c->dither_flag != GL_TRUE )
+ {
+ wmCreateBackingStore(c, c->width, c->height);
+
+ }
+#endif
+ }
+ else
+ {
+ /* Single Buffered */
+ if (c->rgb_flag)
+ c->db_flag = 0;
+ }
+#ifdef DDRAW
+ if (DDInit(c,hWnd) == GL_FALSE) {
+ free( (void *) c );
+ exit(1);
+ }
+#endif
+
+
+ c->gl_visual = gl_create_visual(rgb_flag,
+ GL_FALSE, /* software alpha */
+ db_flag, /* db_flag */
+ GL_FALSE, /* stereo */
+ 16, /* depth_bits */
+ 8, /* stencil_bits */
+ 8, /* accum_bits */
+ 0, /* index bits */
+ 8,8,8,8 ); /* r, g, b, a bits */
+
+ if (!c->gl_visual) {
+ return NULL;
+ }
+
+ /* allocate a new Mesa context */
+ c->gl_ctx = gl_create_context( c->gl_visual, NULL, c, GL_TRUE);
+
+ if (!c->gl_ctx) {
+ gl_destroy_visual( c->gl_visual );
+ free(c);
+ return NULL;
+ }
+
+ c->gl_buffer = gl_create_framebuffer( c->gl_visual );
+ if (!c->gl_buffer) {
+ gl_destroy_visual( c->gl_visual );
+ gl_destroy_context( c->gl_ctx );
+ free(c);
+ return NULL;
+ }
+
+ c->gl_ctx->Driver.UpdateState = setup_DD_pointers;
+
+ // setup_DD_pointers(c->gl_ctx);
+
+ return c;
+}
+
+void WMesaDestroyContext( void )
+{
+ WMesaContext c = Current;
+ ReleaseDC(c->Window,c->hDC);
+ WC = c;
+ if(c->hPalHalfTone != NULL)
+ DeleteObject(c->hPalHalfTone);
+ gl_destroy_visual( c->gl_visual );
+ gl_destroy_framebuffer( c->gl_buffer );
+ gl_destroy_context( c->gl_ctx );
+
+ if (c->db_flag)
+#ifdef DDRAW
+ DDFree(c);
+#else
+ wmDeleteBackingStore(c);
+#endif
+ free( (void *) c );
+ //Following code is added to enable parallel render
+ // Parallel render only work in double buffer mode
+#if !defined(NO_PARALLEL)
+ if(parallelMachine)
+ PRDestroyRenderBuffer();
+#endif
+ // End modification
+}
+
+void WMesaMakeCurrent( WMesaContext c )
+{
+ if(!c){
+ Current = c;
+ return;
+ }
+
+ //
+ // A little optimization
+ // If it already is current,
+ // don't set it again
+ //
+ if(Current == c)
+ return;
+
+ //gl_set_context( c->gl_ctx );
+ gl_make_current(c->gl_ctx, c->gl_buffer);
+ setup_DD_pointers(c->gl_ctx);
+ Current = c;
+ if (Current->gl_ctx->Viewport.Width==0) {
+ /* initialize viewport to window size */
+ gl_Viewport( Current->gl_ctx,
+ 0, 0, Current->width, Current->height );
+ }
+ if ((c->cColorBits <= 8 ) && (c->rgb_flag == GL_TRUE)){
+ WMesaPaletteChange(c->hPalHalfTone);
+ }
+}
+
+void WMesaSwapBuffers( void )
+{
+ HDC DC = Current->hDC;
+ if (Current->db_flag)
+ wmFlush(Current);
+}
+
+void WMesaPaletteChange(HPALETTE Pal)
+{
+ int vRet;
+ LPPALETTEENTRY pPal;
+ if (Current && (Current->rgb_flag==GL_FALSE || Current->dither_flag == GL_TRUE))
+ {
+ pPal = (PALETTEENTRY *)malloc( 256 * sizeof(PALETTEENTRY));
+ Current->hPal=Pal;
+ // GetPaletteEntries( Pal, 0, 256, pPal );
+ GetPalette( Pal, pPal );
+#ifdef DDRAW
+ Current->lpDD->lpVtbl->CreatePalette(Current->lpDD,DDPCAPS_8BIT,
+ pPal, &(Current->lpDDPal), NULL);
+ if (Current->lpDDPal)
+ Current->lpDDSPrimary->lpVtbl->SetPalette(Current->lpDDSPrimary,Current->lpDDPal);
+#else
+ vRet = SetDIBColorTable(Current->dib.hDC,0,256,pPal);
+#endif
+ free( pPal );
+ }
+
+}
+
+static unsigned char threeto8[8] = {
+ 0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377
+};
+
+static unsigned char twoto8[4] = {
+ 0, 0x55, 0xaa, 0xff
+};
+
+static unsigned char oneto8[2] = {
+ 0, 255
+};
+
+static unsigned char componentFromIndex(UCHAR i, UINT nbits, UINT shift)
+{
+ unsigned char val;
+
+ val = i >> shift;
+ switch (nbits) {
+
+ case 1:
+ val &= 0x1;
+ return oneto8[val];
+
+ case 2:
+ val &= 0x3;
+ return twoto8[val];
+
+ case 3:
+ val &= 0x7;
+ return threeto8[val];
+
+ default:
+ return 0;
+ }
+}
+
+void wmCreatePalette( PWMC pwdc )
+{
+ /* Create a compressed and re-expanded 3:3:2 palette */
+ int i;
+ LOGPALETTE *pPal;
+ BYTE rb, rs, gb, gs, bb, bs;
+
+ pwdc->nColors = 0x100;
+
+ pPal = (PLOGPALETTE)malloc(sizeof(LOGPALETTE) + pwdc->nColors * sizeof(PALETTEENTRY));
+ memset( pPal, 0, sizeof(LOGPALETTE) + pwdc->nColors * sizeof(PALETTEENTRY) );
+
+ pPal->palVersion = 0x300;
+
+ rb = REDBITS;
+ rs = REDSHIFT;
+ gb = GREENBITS;
+ gs = GREENSHIFT;
+ bb = BLUEBITS;
+ bs = BLUESHIFT;
+
+ if (pwdc->db_flag) {
+
+ /* Need to make two palettes: one for the screen DC and one for the DIB. */
+ pPal->palNumEntries = pwdc->nColors;
+ for (i = 0; i < pwdc->nColors; i++) {
+ pPal->palPalEntry[i].peRed = componentFromIndex( i, rb, rs );
+ pPal->palPalEntry[i].peGreen = componentFromIndex( i, gb, gs );
+ pPal->palPalEntry[i].peBlue = componentFromIndex( i, bb, bs );
+ pPal->palPalEntry[i].peFlags = 0;
+ }
+ pwdc->hGLPalette = CreatePalette( pPal );
+ pwdc->hPalette = CreatePalette( pPal );
+ }
+
+ else {
+ pPal->palNumEntries = pwdc->nColors;
+ for (i = 0; i < pwdc->nColors; i++) {
+ pPal->palPalEntry[i].peRed = componentFromIndex( i, rb, rs );
+ pPal->palPalEntry[i].peGreen = componentFromIndex( i, gb, gs );
+ pPal->palPalEntry[i].peBlue = componentFromIndex( i, bb, bs );
+ pPal->palPalEntry[i].peFlags = 0;
+ }
+ pwdc->hGLPalette = CreatePalette( pPal );
+ }
+
+ free(pPal);
+
+}
+
+void wmSetPixel(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b)
+{
+ if(Current->db_flag){
+ LPBYTE lpb = pwc->pbPixels;
+ LPDWORD lpdw;
+ LPWORD lpw;
+ UINT nBypp = pwc->cColorBits / 8;
+ UINT nOffset = iPixel % nBypp;
+
+ // Move the pixel buffer pointer to the scanline that we
+ // want to access
+
+ // pwc->dib.fFlushed = FALSE;
+
+ lpb += pwc->ScanWidth * iScanLine;
+ // Now move to the desired pixel
+ lpb += iPixel * nBypp;
+ lpb = PIXELADDR(iPixel, iScanLine);
+ lpdw = (LPDWORD)lpb;
+ lpw = (LPWORD)lpb;
+
+ if(nBypp == 1){
+ if(pwc->dither_flag)
+ *lpb = DITHER_RGB_2_8BIT(r,g,b,iScanLine,iPixel);
+ else
+ *lpb = BGR8(r,g,b);
+ }
+ else if(nBypp == 2)
+ *lpw = BGR16(r,g,b);
+ else if (nBypp == 3){
+ *lpdw = BGR24(r,g,b);
+ }
+ else if (nBypp == 4)
+ *lpdw = BGR32(r,g,b);
+ }
+ else{
+ HDC DC = DD_GETDC;
+ SetPixel(DC, iPixel, iScanLine, RGB(r,g,b));
+ DD_RELEASEDC;
+ }
+}
+
+void wmCreateDIBSection( HDC hDC,
+ PWMC pwc, // handle of device context
+ CONST BITMAPINFO *pbmi, // address of structure containing bitmap size, format, and color data
+ UINT iUsage // color data type indicator: RGB values or palette indices
+ )
+{
+ DWORD dwSize = 0;
+ DWORD dwScanWidth;
+ UINT nBypp = pwc->cColorBits / 8;
+ HDC hic;
+
+ dwScanWidth = (((pwc->ScanWidth * nBypp)+ 3) & ~3);
+
+ pwc->ScanWidth =pwc->pitch = dwScanWidth;
+
+ if (stereo_flag)
+ pwc->ScanWidth = 2* pwc->pitch;
+
+ dwSize = sizeof(BITMAPINFO) + (dwScanWidth * pwc->height);
+
+ pwc->dib.hFileMap = CreateFileMapping((HANDLE)PAGE_FILE,
+ NULL,
+ PAGE_READWRITE | SEC_COMMIT,
+ 0,
+ dwSize,
+ NULL);
+
+ if (!pwc->dib.hFileMap)
+ return;
+
+ pwc->dib.base = MapViewOfFile(pwc->dib.hFileMap,
+ FILE_MAP_ALL_ACCESS,
+ 0,
+ 0,
+ 0);
+
+ if(!pwc->dib.base){
+ CloseHandle(pwc->dib.hFileMap);
+ return;
+ }
+
+ // pwc->pbPixels = pwc->addrOffScreen = ((LPBYTE)pwc->dib.base) + sizeof(BITMAPINFO);
+
+ // pwc->dib.hDC = CreateCompatibleDC(hDC);
+
+ CopyMemory(pwc->dib.base, pbmi, sizeof(BITMAPINFO));
+
+ hic = CreateIC("display", NULL, NULL, NULL);
+ pwc->dib.hDC = CreateCompatibleDC(hic);
+
+
+ /* pwc->hbmDIB = CreateDIBitmap(hic,
+ &(pwc->bmi.bmiHeader),
+ CBM_INIT,
+ pwc->pbPixels,
+ &(pwc->bmi),
+ DIB_RGB_COLORS);
+ */
+ pwc->hbmDIB = CreateDIBSection(hic,
+ &(pwc->bmi),
+ (iUsage ? DIB_PAL_COLORS : DIB_RGB_COLORS),
+ &(pwc->pbPixels),
+ pwc->dib.hFileMap,
+ 0);
+ /*
+ pwc->hbmDIB = CreateDIBSection(hic,
+ &(pwc->bmi),
+ DIB_RGB_COLORS,
+ &(pwc->pbPixels),
+ pwc->dib.hFileMap,
+ 0);
+ */
+ pwc->ScreenMem = pwc->addrOffScreen = pwc->pbPixels;
+ pwc->hOldBitmap = SelectObject(pwc->dib.hDC, pwc->hbmDIB);
+
+ DeleteDC(hic);
+
+ return;
+
+}
+
+//
+// Blit memory DC to screen DC
+//
+BOOL wmFlush(PWMC pwc)
+{
+ BOOL bRet = 0;
+ DWORD dwErr = 0;
+#ifdef DDRAW
+ HRESULT ddrval;
+#endif
+
+ // Now search through the torus frames and mark used colors
+ if(pwc->db_flag){
+#ifdef DDRAW
+ if (pwc->lpDDSOffScreen == NULL)
+ if(DDCreateOffScreen(pwc) == GL_FALSE)
+ return;
+
+ pwc->lpDDSOffScreen->lpVtbl->Unlock(pwc->lpDDSOffScreen, NULL);
+
+ while( 1 )
+ {
+ ddrval = pwc->lpDDSPrimary->lpVtbl->Blt( pwc->lpDDSPrimary,
+ &(pwc->rectSurface), pwc->lpDDSOffScreen, &(pwc->rectOffScreen), 0, NULL );
+
+ if( ddrval == DD_OK )
+ {
+ break;
+ }
+ if( ddrval == DDERR_SURFACELOST )
+ {
+ if(!DDRestoreAll(pwc))
+ {
+ break;
+ }
+ }
+ if( ddrval != DDERR_WASSTILLDRAWING )
+ {
+ break;
+ }
+ }
+
+ while (pwc->lpDDSOffScreen->lpVtbl->Lock(pwc->lpDDSOffScreen,
+ NULL, &(pwc->ddsd), 0, NULL) == DDERR_WASSTILLDRAWING)
+ ;
+
+ if(ddrval != DD_OK)
+ dwErr = GetLastError();
+#else
+ bRet = BitBlt(pwc->hDC, 0, 0, pwc->width, pwc->height,
+ pwc->dib.hDC, 0, 0, SRCCOPY);
+#endif
+ }
+
+ return(TRUE);
+
+}
+
+// The following code is added by Li Wei to enable stereo display
+
+#if !defined(NO_STEREO)
+
+void WMesaShowStereo(GLuint list)
+{
+
+ GLbitfield mask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
+ GLfloat cm[16];
+ GLint matrix_mode;
+ // Must use double Buffer
+ if( ! Current-> db_flag )
+ return;
+
+
+ glGetIntegerv(GL_MATRIX_MODE,&matrix_mode);
+
+ // glPushMatrix(); //****
+ WMesaViewport(Current->gl_ctx,0,Current->height/2,Current->width,Current->height/2);
+ // Current->gl_ctx->NewState = 0;
+
+ // glViewport(0,0,Current->width,Current->height/2);
+ if(matrix_mode!=GL_MODELVIEW)
+ glMatrixMode(GL_MODELVIEW);
+
+ glGetFloatv(GL_MODELVIEW_MATRIX,cm);
+ glLoadIdentity();
+ gluLookAt(viewDistance/2,0.0,0.0 ,
+ viewDistance/2,0.0,-1.0,
+ 0.0,1.0,0.0 );
+ // glTranslatef(viewDistance/2.0,0.,0.);
+ glMultMatrixf( cm );
+
+ Current->ScreenMem = Current->pbPixels = Current->addrOffScreen;
+ //glPushMatrix();
+ glCallList( list );
+ //glPopMatrix();
+
+ glGetFloatv(GL_MODELVIEW_MATRIX,cm);
+ glLoadIdentity();
+ gluLookAt(-viewDistance/2,0.0,0.0 ,
+ -viewDistance/2,0.0,-1.0,
+ 0.0,1.0,0.0 );
+ // glTranslatef(-viewDistance/2.0,0.,0.);
+ glMultMatrixf(cm);
+
+ Current->ScreenMem = Current->pbPixels = Current->addrOffScreen + Current->pitch;
+ glCallList(list);
+ if(matrix_mode!=GL_MODELVIEW)
+ glMatrixMode(matrix_mode);
+
+ // glPopMatrix();
+ glFlush();
+
+ WMesaViewport(Current->gl_ctx,0,0,Current->width,Current->height);
+ // Current->gl_ctx->NewState = 0;
+ WMesaSwapBuffers();
+
+}
+
+void toggleStereoMode()
+{
+ if(!Current->db_flag)
+ return;
+ if(!stereo_flag){
+ stereo_flag = 1;
+ if(stereoBuffer==GL_FALSE)
+#if !defined(NO_PARALLEL)
+ if(!parallelFlag)
+#endif
+ {
+ Current->ScanWidth = Current->pitch*2;
+ }
+ }
+ else {
+ stereo_flag = 0;
+#if !defined(NO_PARALLEL)
+ if(!parallelFlag)
+#endif
+ Current->ScanWidth = Current->pitch;
+ Current->pbPixels = Current->addrOffScreen;
+ }
+}
+
+/* if in stereo mode, the following function is called */
+void glShowStereo(GLuint list)
+{
+ WMesaShowStereo(list);
+}
+
+#endif // End if NO_STEREO not defined
+
+#if !defined(NO_PARALLEL)
+
+void toggleParallelMode(void)
+{
+ if(!parallelFlag){
+ parallelFlag = GL_TRUE;
+ if(parallelMachine==GL_FALSE){
+ PRCreateRenderBuffer( Current->rgb_flag? GL_RGBA :GL_COLOR_INDEX,
+ Current->cColorBits/8,
+ Current->width ,Current->height,
+ Current->ScanWidth,
+ Current->rgb_flag? Current->pbPixels: Current->ScreenMem);
+ parallelMachine = GL_TRUE;
+ }
+ }
+ else {
+ parallelFlag = GL_FALSE;
+ if(parallelMachine==GL_TRUE){
+ PRDestroyRenderBuffer();
+ parallelMachine=GL_FALSE;
+ ReadyForNextFrame = GL_TRUE;
+ }
+
+ /***********************************************
+ // Seems something wrong!!!!
+ ************************************************/
+
+ WMesaMakeCurrent(Current);
+#if !defined(NO_STEREO)
+ stereo_flag = GL_FALSE ;
+#endif
+ }
+}
+
+void PRShowRenderResult(void)
+{
+ int flag = 0;
+ if(!glImageRendered())
+ return;
+
+ if (parallelFlag)
+ {
+ WMesaSwapBuffers();
+ }
+
+}
+#endif //End if NO_PARALLEL not defined
+
+//end modification
+
+BYTE DITHER_RGB_2_8BIT( int red, int green, int blue, int pixel, int scanline)
+{
+ char unsigned redtemp, greentemp, bluetemp, paletteindex;
+
+ //*** now, look up each value in the halftone matrix
+ //*** using an 8x8 ordered dither.
+ redtemp = aDividedBy51[red]
+ + (aModulo51[red] > aHalftone8x8[(pixel%8)*8
+ + scanline%8]);
+ greentemp = aDividedBy51[(char unsigned)green]
+ + (aModulo51[green] > aHalftone8x8[
+ (pixel%8)*8 + scanline%8]);
+ bluetemp = aDividedBy51[(char unsigned)blue]
+ + (aModulo51[blue] > aHalftone8x8[
+ (pixel%8)*8 +scanline%8]);
+
+ //*** recombine the halftoned rgb values into a palette index
+ paletteindex =
+ redtemp + aTimes6[greentemp] + aTimes36[bluetemp];
+
+ //*** and translate through the wing halftone palette
+ //*** translation vector to give the correct value.
+ return aWinGHalftoneTranslation[paletteindex];
+}
+
+#ifdef DDRAW
+/*
+* restoreAll
+*
+* restore all lost objects
+*/
+static HRESULT DDRestoreAll( WMesaContext wc )
+{
+ HRESULT ddrval;
+
+ ddrval = wc->lpDDSPrimary->lpVtbl->Restore(wc->lpDDSPrimary);
+ if( ddrval == DD_OK )
+ {
+ ddrval = wc->lpDDSOffScreen->lpVtbl->Restore(wc->lpDDSOffScreen);
+ }
+ return ddrval;
+
+} /* restoreAll */
+
+
+ /*
+ * This function is called if the initialization function fails
+*/
+static BOOL initFail( HWND hwnd, WMesaContext wc )
+{
+ DDFree(wc);
+ MessageBox( hwnd, "DirectDraw Init FAILED", "", MB_OK );
+ return FALSE;
+
+} /* initFail */
+
+
+static void DDDeleteOffScreen(WMesaContext wc)
+{
+ if( wc->lpDDSOffScreen != NULL )
+ {
+ wc->lpDDSOffScreen->lpVtbl->Unlock(wc->lpDDSOffScreen,NULL);
+ wc->lpDDSOffScreen->lpVtbl->Release(wc->lpDDSOffScreen);
+ wc->lpDDSOffScreen = NULL;
+ }
+
+}
+
+static void DDFreePrimarySurface(WMesaContext wc)
+{
+ if( wc->lpDDSPrimary != NULL )
+ {
+ if(wc->db_flag == GL_FALSE)
+ wc->lpDDSPrimary->lpVtbl->ReleaseDC(wc->lpDDSPrimary, wc->hDC);
+ wc->lpDDSPrimary->lpVtbl->Release(wc->lpDDSPrimary);
+ wc->lpDDSPrimary = NULL;
+ }
+}
+
+static BOOL DDCreatePrimarySurface(WMesaContext wc)
+{
+ HRESULT ddrval;
+ DDSCAPS ddscaps;
+ wc->ddsd.dwSize = sizeof( wc->ddsd );
+ wc->ddsd.dwFlags = DDSD_CAPS;
+ wc->ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+
+ ddrval = wc->lpDD->lpVtbl->CreateSurface( wc->lpDD,&(wc->ddsd), &(wc->lpDDSPrimary), NULL );
+ if( ddrval != DD_OK )
+ {
+ return initFail(wc->hwnd , wc);
+ }
+ if(wc->db_flag == GL_FALSE)
+ wc->lpDDSPrimary->lpVtbl->GetDC(wc->lpDDSPrimary, wc->hDC);
+ return TRUE;
+}
+
+static BOOL DDCreateOffScreen(WMesaContext wc)
+{
+ POINT pt;
+ HRESULT ddrval;
+ if(wc->lpDD == NULL)
+ return FALSE;
+ GetClientRect( wc->hwnd, &(wc->rectOffScreen) );
+ wc->ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
+ wc->ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
+ wc->ddsd.dwHeight = wc->rectOffScreen.bottom - wc->rectOffScreen.top;
+ wc->ddsd.dwWidth = wc->rectOffScreen.right - wc->rectOffScreen.left;
+
+ ddrval = wc->lpDD->lpVtbl->CreateSurface( wc->lpDD, &(wc->ddsd), &(wc->lpDDSOffScreen), NULL );
+ if( ddrval != DD_OK )
+ {
+ return FALSE;
+ }
+
+ while (wc->lpDDSOffScreen->lpVtbl->Lock(wc->lpDDSOffScreen,NULL, &(wc->ddsd), 0, NULL) == DDERR_WASSTILLDRAWING)
+ ;
+ // while ((ddrval = wc->lpDDSOffScreen->lpVtbl->Lock(wc->lpDDSOffScreen,NULL, &(wc->ddsd), DDLOCK_SURFACEMEMORYPTR , NULL)) != DD_OK)
+ ;
+ if(wc->ddsd.lpSurface==NULL)
+ return initFail(wc->hwnd, wc);
+
+ wc->ScreenMem = wc->pbPixels = wc->addrOffScreen = (PBYTE)(wc->ddsd.lpSurface);
+ wc->ScanWidth = wc->pitch = wc->ddsd.lPitch;
+ if (stereo_flag)
+ wc->ScanWidth = wc->ddsd.lPitch*2;
+
+ GetClientRect( wc->hwnd, &(wc->rectSurface) );
+ pt.x = pt.y = 0;
+ ClientToScreen( wc->hwnd, &pt );
+ OffsetRect(&(wc->rectSurface), pt.x, pt.y);
+ wmSetPixelFormat(wc, wc->hDC);
+ return TRUE;
+}
+
+/*
+* doInit - do work required for every instance of the application:
+* create the window, initialize data
+*/
+static BOOL DDInit( WMesaContext wc, HWND hwnd)
+{
+ HRESULT ddrval;
+ DWORD dwFrequency;
+
+ LPDIRECTDRAW lpDD; // DirectDraw object
+ LPDIRECTDRAW2 lpDD2;
+
+
+ wc->fullScreen = displayOptions.fullScreen;
+ wc->gMode = displayOptions.mode;
+ wc->hwnd = hwnd;
+ stereo_flag = displayOptions.stereo;
+ if(wc->db_flag!= GL_TRUE)
+ stereo_flag = GL_FALSE;
+ /*
+ * create the main DirectDraw object
+ */
+ ddrval = DirectDrawCreate( NULL, &(wc->lpDD), NULL );
+ if( ddrval != DD_OK )
+ {
+ return initFail(hwnd,wc);
+ }
+
+ // Get exclusive mode if requested
+ if(wc->fullScreen)
+ {
+ ddrval = wc->lpDD->lpVtbl->SetCooperativeLevel( wc->lpDD, hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
+ }
+ else
+ {
+ ddrval = wc->lpDD->lpVtbl->SetCooperativeLevel( wc->lpDD, hwnd, DDSCL_NORMAL );
+ }
+ if( ddrval != DD_OK )
+ {
+ return initFail(hwnd , wc);
+ }
+
+
+ /* ddrval = wc->lpDD->lpVtbl->QueryInterface(wc->lpDD, IID_IDirectDraw2,
+ (LPVOID *)((wc->lpDD2)));
+
+ */
+ if(ddrval != DD_OK)
+ return initFail(hwnd , wc);
+
+
+ //ddrval = wc->lpDD->lpVtbl->GetDisplayMode( wc->lpDD, &(wc->ddsd));
+ // wc->lpDD2->lpVtbl->GetMonitorFrequency(wc->lpDD, &dwFrequency);
+ switch( wc->gMode )
+ {
+ case 1: ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 640, 480, displayOptions.bpp); break;
+ case 2: ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 800, 600, displayOptions.bpp); break;
+ case 3: ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 1024, 768, displayOptions.bpp); break;
+ case 4: ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 1152, 864, displayOptions.bpp); break;
+ case 5: ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 1280, 1024, displayOptions.bpp); break;
+ }
+
+ if( ddrval != DD_OK )
+ {
+ printf("Can't modify display mode, current mode used\n");
+ // return initFail(hwnd , wc);
+ }
+ //ddrval = wc->lpDD->lpVtbl->GetDisplayMode( wc->lpDD, &(wc->ddsd));
+ switch(ddrval){
+ case DDERR_INVALIDOBJECT:
+ break;
+ case DDERR_INVALIDPARAMS:
+ break;
+ case DDERR_UNSUPPORTEDMODE:
+ ;
+ }
+
+ if(DDCreatePrimarySurface(wc) == GL_FALSE)
+ return initFail(hwnd, wc);
+
+ if(wc->db_flag)
+ return DDCreateOffScreen(wc);
+} /* DDInit */
+
+static void DDFree( WMesaContext wc)
+{
+ if( wc->lpDD != NULL )
+ {
+ DDFreePrimarySurface(wc);
+ DDDeleteOffScreen(wc);
+ wc->lpDD->lpVtbl->Release(wc->lpDD);
+ wc->lpDD = NULL;
+ }
+ // Clean up the screen on exit
+ RedrawWindow( NULL, NULL, NULL, RDW_INVALIDATE | RDW_ERASE |
+ RDW_ALLCHILDREN );
+
+}
+#endif
+
+void WMesaMove(void)
+{
+ WMesaContext wc = Current;
+ POINT pt;
+ if (Current != NULL){
+ GetClientRect( wc->hwnd, &(wc->rectSurface) );
+ pt.x = pt.y = 0;
+ ClientToScreen( wc->hwnd, &pt );
+ OffsetRect(&(wc->rectSurface), pt.x, pt.y);
+ }
+}
+
+
+
+/*
+* Like PACK_8A8B8G8R() but don't use alpha. This is usually an acceptable
+* shortcut.
+*/
+#define PACK_8B8G8R( R, G, B ) ( ((B) << 16) | ((G) << 8) | (R) )
+
+
+/**********************************************************************/
+/*** Triangle rendering ***/
+/**********************************************************************/
+
+/*
+ * XImage, smooth, depth-buffered, PF_8A8B8G8R triangle.
+ */
+static void smooth_8A8B8G8R_z_triangle( GLcontext *ctx,
+ GLuint v0, GLuint v1, GLuint v2,
+ GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = PACK_8B8G8R( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb) ); \
+ zRow[i] = z; \
+ } \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef WIN32
+ #include "..\tritemp.h"
+#else
+ #include "tritemp.h"
+#endif
+}
+
+
+/*
+* XImage, smooth, depth-buffered, PF_8R8G8B triangle.
+*/
+static void smooth_8R8G8B_z_triangle( GLcontext *ctx,
+ GLuint v0, GLuint v1, GLuint v2,
+ GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = PACK_8R8G8B( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb) ); \
+ zRow[i] = z; \
+ } \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef WIN32
+ #include "..\tritemp.h"
+#else
+ #include "tritemp.h"
+#endif
+}
+
+
+
+/*
+* XImage, smooth, depth-buffered, PF_5R6G5B triangle.
+*/
+static void smooth_5R6G5B_z_triangle( GLcontext *ctx,
+ GLuint v0, GLuint v1, GLuint v2,
+ GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y)
+#define PIXEL_TYPE GLushort
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = PACK_5R6G5B( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb) ); \
+ zRow[i] = z; \
+ } \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef WIN32
+ #include "..\tritemp.h"
+#else
+ #include "tritemp.h"
+#endif
+}
+
+/*
+* XImage, flat, depth-buffered, PF_8A8B8G8R triangle.
+*/
+static void flat_8A8B8G8R_z_triangle( GLcontext *ctx, GLuint v0,
+ GLuint v1, GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ unsigned long p = PACK_8B8G8R( VB->Color[pv][0], \
+ VB->Color[pv][1], VB->Color[pv][2] );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = p; \
+ zRow[i] = z; \
+ } \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef WIN32
+ #include "..\tritemp.h"
+#else
+ #include "tritemp.h"
+#endif
+}
+
+
+/*
+* XImage, flat, depth-buffered, PF_8R8G8B triangle.
+*/
+static void flat_8R8G8B_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ unsigned long p = PACK_8R8G8B( VB->Color[pv][0], \
+ VB->Color[pv][1], VB->Color[pv][2] );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = p; \
+ zRow[i] = z; \
+ } \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef WIN32
+ #include "..\tritemp.h"
+#else
+ #include "tritemp.h"
+#endif
+}
+
+
+/*
+* XImage, flat, depth-buffered, PF_5R6G5B triangle.
+*/
+static void flat_5R6G5B_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y)
+#define PIXEL_TYPE GLushort
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ unsigned long p = PACK_5R6G5B( VB->Color[pv][0], \
+ VB->Color[pv][1], VB->Color[pv][2] );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = p; \
+ zRow[i] = z; \
+ } \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef WIN32
+ #include "..\tritemp.h"
+#else
+ #include "tritemp.h"
+#endif
+}
+
+
+/*
+* XImage, smooth, NON-depth-buffered, PF_8A8B8G8R triangle.
+*/
+static void smooth_8A8B8G8R_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = PACK_8B8G8R( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb) ); \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ } \
+ }
+#ifdef WIN32
+ #include "..\tritemp.h"
+#else
+ #include "tritemp.h"
+#endif
+}
+
+
+/*
+* XImage, smooth, NON-depth-buffered, PF_8R8G8B triangle.
+*/
+static void smooth_8R8G8B_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = PACK_8R8G8B( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb) ); \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ } \
+ }
+#ifdef WIN32
+ #include "..\tritemp.h"
+#else
+ #include "tritemp.h"
+#endif
+}
+
+
+/*
+* XImage, smooth, NON-depth-buffered, PF_5R6G5B triangle.
+*/
+static void smooth_5R6G5B_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y)
+#define PIXEL_TYPE GLushort
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = PACK_5R6G5B( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb) ); \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ } \
+ }
+#ifdef WIN32
+ #include "..\tritemp.h"
+#else
+ #include "tritemp.h"
+#endif
+}
+
+
+
+/*
+* XImage, flat, NON-depth-buffered, PF_8A8B8G8R triangle.
+*/
+static void flat_8A8B8G8R_triangle( GLcontext *ctx, GLuint v0,
+ GLuint v1, GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ unsigned long p = PACK_8B8G8R( VB->Color[pv][0], \
+ VB->Color[pv][1], VB->Color[pv][2] );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = p; \
+ } \
+ }
+#ifdef WIN32
+ #include "..\tritemp.h"
+#else
+ #include "tritemp.h"
+#endif
+}
+
+
+/*
+* XImage, flat, NON-depth-buffered, PF_8R8G8B triangle.
+*/
+static void flat_8R8G8B_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ unsigned long p = PACK_8R8G8B( VB->Color[pv][0], \
+ VB->Color[pv][1], VB->Color[pv][2] );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = p; \
+ } \
+ }
+#ifdef WIN32
+ #include "..\tritemp.h"
+#else
+ #include "tritemp.h"
+#endif
+}
+
+
+/*
+* XImage, flat, NON-depth-buffered, PF_5R6G5B triangle.
+*/
+static void flat_5R6G5B_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y)
+#define PIXEL_TYPE GLushort
+ //#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ unsigned long p = PACK_5R6G5B( VB->Color[pv][0], \
+ VB->Color[pv][1], VB->Color[pv][2] );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = p; \
+ } \
+ }
+#ifdef WIN32
+ #include "..\tritemp.h"
+#else
+ #include "tritemp.h"
+#endif
+}
+
+
+/*
+* XImage, smooth, depth-buffered, 8-bit PF_LOOKUP triangle.
+*/
+
+static void smooth_ci_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define INTERP_INDEX 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = FixedToInt(ffi); \
+ zRow[i] = z; \
+ } \
+ ffi += fdidx; \
+ ffz += fdzdx; \
+ } \
+ }
+
+#ifdef WIN32
+ #include "..\tritemp.h"
+#else
+ #include "tritemp.h"
+#endif
+}
+
+
+/*
+* XImage, flat, depth-buffered, 8-bit PF_LOOKUP triangle.
+*/
+
+static void flat_ci_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ GLuint index = VB->Index[pv]; \
+ if (!VB->MonoColor) { \
+ /* set the color index */ \
+ (*ctx->Driver.Index)( ctx, index ); \
+ }
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = index; \
+ zRow[i] = z; \
+ } \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef WIN32
+ #include "..\tritemp.h"
+#else
+ #include "tritemp.h"
+#endif
+}
+
+
+
+/*
+* XImage, smooth, NON-depth-buffered, 8-bit PF_LOOKUP triangle.
+*/
+
+static void smooth_ci_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define INTERP_INDEX 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = FixedToInt(ffi); \
+ ffi += fdidx; \
+ } \
+ }
+#ifdef WIN32
+ #include "..\tritemp.h"
+#else
+ #include "tritemp.h"
+#endif
+}
+
+
+/*
+* XImage, flat, NON-depth-buffered, 8-bit PF_LOOKUP triangle.
+*/
+static void flat_ci_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ GLuint index = VB->Index[pv]; \
+ if (!VB->MonoColor) { \
+ /* set the color index */ \
+ (*ctx->Driver.Index)( ctx, index ); \
+ }
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = index; \
+ } \
+ }
+#ifdef WIN32
+ #include "..\tritemp.h"
+#else
+ #include "tritemp.h"
+#endif
+}
+
+/*
+* XImage, smooth, depth-buffered, 8-bit, PF_DITHER8 triangle.
+*/
+static void smooth_DITHER8_z_triangle( GLcontext *ctx,
+ GLuint v0, GLuint v1, GLuint v2,
+ GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+ DITHER_RGB_TO_8BIT_SETUP
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, xx = LEFT, yy = FLIP(Y), len = RIGHT-LEFT; \
+ for (i=0;i<len;i++,xx++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ DITHER_RGB_TO_8BIT( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb), xx, yy); \
+ pRow[i] = pixelDithered; \
+ zRow[i] = z; \
+ } \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef WIN32
+ #include "..\tritemp.h"
+#else
+ #include "tritemp.h"
+#endif
+}
+
+/*
+* XImage, flat, depth-buffered, 8-bit PF_DITHER triangle.
+*/
+static void flat_DITHER8_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+ DITHER_RGB_TO_8BIT_SETUP
+#define INTERP_Z 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint i, xx = LEFT, yy = FLIP(Y), len = RIGHT-LEFT; \
+ for (i=0;i<len;i++,xx++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ DITHER_RGB_TO_8BIT( VB->Color[pv][0], \
+ VB->Color[pv][1], VB->Color[pv][2], xx, yy); \
+ pRow[i] = pixelDithered; \
+ zRow[i] = z; \
+ } \
+ ffz += fdzdx; \
+ } \
+ }
+#ifdef WIN32
+ #include "..\tritemp.h"
+#else
+ #include "tritemp.h"
+#endif
+}
+
+/*
+* XImage, smooth, NON-depth-buffered, 8-bit PF_DITHER triangle.
+*/
+static void smooth_DITHER8_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+ DITHER_RGB_TO_8BIT_SETUP
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx, yy = FLIP(Y); \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ DITHER_RGB_TO_8BIT( VB->Color[pv][0], VB->Color[pv][1], VB->Color[pv][2], xx, yy);\
+ *pixel = pixelDithered; \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ } \
+ }
+#ifdef WIN32
+ #include "..\tritemp.h"
+#else
+ #include "tritemp.h"
+#endif
+}
+
+/*
+* XImage, flat, NON-depth-buffered, 8-bit PF_DITHER triangle.
+*/
+
+static void flat_DITHER8_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+ DITHER_RGB_TO_8BIT_SETUP
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+ { \
+ GLint xx, yy = FLIP(Y); \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ DITHER_RGB_TO_8BIT( VB->Color[pv][0], \
+ VB->Color[pv][1], VB->Color[pv][2], xx, yy); \
+ *pixel = pixelDithered; \
+ } \
+ }
+#ifdef WIN32
+ #include "..\tritemp.h"
+#else
+ #include "tritemp.h"
+#endif
+}
+
+
+
+
+static triangle_func choose_triangle_function( GLcontext *ctx )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+ int depth = wmesa->cColorBits;
+
+ if (ctx->Polygon.SmoothFlag) return NULL;
+ if (ctx->Texture.Enabled) return NULL;
+ if (!wmesa->db_flag) return NULL;
+ /*if (wmesa->xm_buffer->buffer==XIMAGE)*/ {
+ if ( ctx->Light.ShadeModel==GL_SMOOTH
+ && ctx->RasterMask==DEPTH_BIT
+ && ctx->Depth.Func==GL_LESS
+ && ctx->Depth.Mask==GL_TRUE
+ && ctx->Polygon.StippleFlag==GL_FALSE) {
+ switch (wmesa->pixelformat) {
+ case PF_8A8B8G8R:
+ return smooth_8A8B8G8R_z_triangle;
+ case PF_8R8G8B:
+ return smooth_8R8G8B_z_triangle;
+ case PF_5R6G5B:
+ return smooth_5R6G5B_z_triangle;
+ case PF_DITHER8:
+ return smooth_DITHER8_z_triangle;
+ case PF_INDEX8:
+ return smooth_ci_z_triangle;
+ default:
+ return NULL;
+ }
+ }
+ if ( ctx->Light.ShadeModel==GL_FLAT
+ && ctx->RasterMask==DEPTH_BIT
+ && ctx->Depth.Func==GL_LESS
+ && ctx->Depth.Mask==GL_TRUE
+ && ctx->Polygon.StippleFlag==GL_FALSE) {
+ switch (wmesa->pixelformat) {
+ case PF_8A8B8G8R:
+ return flat_8A8B8G8R_z_triangle;
+ case PF_8R8G8B:
+ return flat_8R8G8B_z_triangle;
+ case PF_5R6G5B:
+ return flat_5R6G5B_z_triangle;
+ case PF_DITHER8:
+ return flat_DITHER8_z_triangle;
+ case PF_INDEX8:
+ return flat_ci_z_triangle;
+ default:
+ return NULL;
+ }
+ }
+ if ( ctx->RasterMask==0 /* no depth test */
+ && ctx->Light.ShadeModel==GL_SMOOTH
+ && ctx->Polygon.StippleFlag==GL_FALSE) {
+ switch (wmesa->pixelformat) {
+ case PF_8A8B8G8R:
+ return smooth_8A8B8G8R_triangle;
+ case PF_8R8G8B:
+ return smooth_8R8G8B_triangle;
+ case PF_5R6G5B:
+ return smooth_5R6G5B_triangle;
+ case PF_DITHER8:
+ return smooth_DITHER8_triangle;
+ case PF_INDEX8:
+ return smooth_ci_triangle;
+ default:
+ return NULL;
+ }
+ }
+
+ if ( ctx->RasterMask==0 /* no depth test */
+ && ctx->Light.ShadeModel==GL_FLAT
+ && ctx->Polygon.StippleFlag==GL_FALSE) {
+ switch (wmesa->pixelformat) {
+ case PF_8A8B8G8R:
+ return flat_8A8B8G8R_triangle;
+ case PF_8R8G8B:
+ return flat_8R8G8B_triangle;
+ case PF_5R6G5B:
+ return flat_5R6G5B_triangle;
+ case PF_DITHER8:
+ return flat_DITHER8_triangle;
+ case PF_INDEX8:
+ return flat_ci_triangle;
+ default:
+ return NULL;
+ }
+ }
+
+ return NULL;
+ }
+}
+
+/*
+* Define a new viewport and reallocate auxillary buffers if the size of
+* the window (color buffer) has changed.
+*/
+void WMesaViewport( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height )
+{
+ /* Save viewport */
+ ctx->Viewport.X = x;
+ ctx->Viewport.Width = width;
+ ctx->Viewport.Y = y;
+ ctx->Viewport.Height = height;
+
+ /* compute scale and bias values */
+ ctx->Viewport.Sx = (GLfloat) width / 2.0F;
+ ctx->Viewport.Tx = ctx->Viewport.Sx + x;
+ ctx->Viewport.Sy = (GLfloat) height / 2.0F;
+ ctx->Viewport.Ty = ctx->Viewport.Sy + y;
+}
diff --git a/src/mesa/drivers/windows/wmesaOld.c b/src/mesa/drivers/windows/wmesaOld.c
new file mode 100644
index 0000000000..afaeecebcf
--- /dev/null
+++ b/src/mesa/drivers/windows/wmesaOld.c
@@ -0,0 +1,2737 @@
+/*
+ * File name : wmesa.c
+ * Version : 2.3
+ *
+ * Display driver for Mesa 2.3 under
+ * Windows95 and WindowsNT
+ *
+ * Copyright (C) 1996- Li Wei
+ * Address : Institute of Artificial Intelligence
+ * : & Robotics
+ * : Xi'an Jiaotong University
+ * Email : liwei@aiar.xjtu.edu.cn
+ * Web page : http://sun.aiar.xjtu.edu.cn
+ *
+ * This file and its associations are partially borrowed from the
+ * Windows NT driver for Mesa 1.8 , written by Mark Leaming
+ * (mark@rsinc.com).
+ */
+
+
+/*
+ * $Log: wmesaOld.c,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 1.2 1999/01/03 03:08:57 brianp
+ * Ted Jump's changes
+ *
+ * Revision 1.0 1997/06/14 17:51:00 CST by Li Wei(liwei@aiar.xjtu.edu.cn)
+ * New display driver for Mesa 2.x using Microsoft Direct Draw
+ * Initial vision
+ */
+
+
+#define WMESA_STEREO_C
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <GL/wmesa.h>
+#include "wmesadef.h"
+#include "context.h"
+#include "dd.h"
+#include "xform.h"
+#include "vb.h"
+#include "matrix.h"
+#include "depth.h"
+
+#ifdef PROFILE
+// #include "profile.h"
+#endif
+
+#ifdef DITHER
+ #include <wing.h>
+#endif
+
+#ifdef __CYGWIN32__
+#include "macros.h"
+#include <string.h>
+#define CopyMemory memcpy
+#endif
+#include "mesa_extend.h"
+#include "colors.h"
+
+#if !defined(NO_STEREO)
+
+ #include "gl\glu.h"
+ #include "stereo.h"
+
+#endif
+#if !defined(NO_PARALLEL)
+// #include "parallel.h"
+#endif
+
+struct DISPLAY_OPTIONS displayOptions;
+
+GLenum stereoCompile = GL_FALSE ;
+GLenum stereoShowing = GL_FALSE ;
+GLenum stereoBuffer = GL_FALSE;
+#if !defined(NO_STEREO)
+GLint displayList = MAXIMUM_DISPLAY_LIST ;
+#endif
+GLint stereo_flag = 0 ;
+
+/* end of added code*/
+
+static PWMC Current = NULL;
+WMesaContext WC = NULL;
+
+#ifdef NDEBUG
+ #define assert(ignore) ((void) 0)
+#else
+ void Mesa_Assert(void *Cond,void *File,unsigned Line)
+ {
+ char Msg[512];
+ sprintf(Msg,"%s %s %d",Cond,File,Line);
+ MessageBox(NULL,Msg,"Assertion failed.",MB_OK);
+ exit(1);
+ }
+ #define assert(e) if (!e) Mesa_Assert(#e,__FILE__,__LINE__);
+#endif
+
+//#define DD_GETDC (Current->hDC )
+#define DD_GETDC ((Current->db_flag) ? Current->dib.hDC : Current->hDC )
+//#define DD_GETDC ((Current->db_flag) ? Current->hDCPrimary : Current->hDCBack )
+#define DD_RELEASEDC
+
+//#define BEGINGDICALL if(Current->rgb_flag)wmFlushBits(Current);
+#define BEGINGDICALL
+//#define ENDGDICALL if(Current->rgb_flag)wmGetBits(Current);
+#define ENDGDICALL
+
+//#define FLIP(Y) (Current->dither_flag? Y : Current->height-(Y)-1)
+//#define FLIP(Y) (Current->height-(Y)-1)
+//#define FLIP(Y) Y
+#define FLIP(Y) (Current->db_flag? Y: Current->height-(Y)-1)
+#define STARTPROFILE
+#define ENDPROFILE(PARA)
+
+#define DITHER_RGB_TO_8BIT_SETUP \
+ GLubyte pixelDithered;
+
+#define DITHER_RGB_TO_8BIT(red, green, blue, pixel, scanline) \
+{ \
+ char unsigned redtemp, greentemp, bluetemp, paletteindex; \
+ redtemp = aDividedBy51[red] \
+ + (aModulo51[red] > aHalftone8x8[(pixel%8)*8 \
+ + scanline%8]); \
+ greentemp = aDividedBy51[(char unsigned)green] \
+ + (aModulo51[green] > aHalftone8x8[ \
+ (pixel%8)*8 + scanline%8]); \
+ bluetemp = aDividedBy51[(char unsigned)blue] \
+ + (aModulo51[blue] > aHalftone8x8[ \
+ (pixel%8)*8 +scanline%8]); \
+ paletteindex = redtemp + aTimes6[greentemp] + aTimes36[bluetemp]; \
+ pixelDithered = aWinGHalftoneTranslation[paletteindex]; \
+}
+
+
+#ifdef DDRAW
+ static BOOL DDInit( WMesaContext wc, HWND hwnd);
+ static void DDFree( WMesaContext wc);
+ static HRESULT DDRestoreAll( WMesaContext wc );
+ static void DDDeleteOffScreen(WMesaContext wc);
+ static BOOL DDCreateOffScreen(WMesaContext wc);
+#endif
+
+static void FlushToFile(PWMC pwc, PSTR szFile);
+
+BOOL wmCreateBackingStore(PWMC pwc, long lxSize, long lySize);
+BOOL wmDeleteBackingStore(PWMC pwc);
+void wmCreatePalette( PWMC pwdc );
+BOOL wmSetDibColors(PWMC pwc);
+void wmSetPixel(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b);
+
+void wmCreateDIBSection(
+ HDC hDC,
+ PWMC pwc, // handle of device context
+ CONST BITMAPINFO *pbmi, // address of structure containing bitmap size, format, and color data
+ UINT iUsage // color data type indicator: RGB values or palette indices
+ );
+
+
+void WMesaViewport( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height );
+
+static triangle_func choose_triangle_function( GLcontext *ctx );
+
+static void wmSetPixelFormat( PWMC wc, HDC hDC)
+{
+ if(wc->rgb_flag)
+ wc->cColorBits = GetDeviceCaps(hDC, BITSPIXEL);
+ else
+ wc->cColorBits = 8;
+ switch(wc->cColorBits){
+ case 8:
+ if(wc->dither_flag != GL_TRUE)
+ wc->pixelformat = PF_INDEX8;
+ else
+ wc->pixelformat = PF_DITHER8;
+ break;
+ case 16:
+ wc->pixelformat = PF_5R6G5B;
+ break;
+ case 32:
+ wc->pixelformat = PF_8R8G8B;
+ break;
+ default:
+ wc->pixelformat = PF_BADFORMAT;
+ }
+}
+
+//
+// This function sets the color table of a DIB section
+// to match that of the destination DC
+//
+BOOL /*WINAPI*/ wmSetDibColors(PWMC pwc)
+{
+ RGBQUAD *pColTab, *pRGB;
+ PALETTEENTRY *pPal, *pPE;
+ int i, nColors;
+ BOOL bRet=TRUE;
+ DWORD dwErr=0;
+
+ /* Build a color table in the DIB that maps to the
+ selected palette in the DC.
+ */
+ nColors = 1 << pwc->cColorBits;
+ pPal = (PALETTEENTRY *)malloc( nColors * sizeof(PALETTEENTRY));
+ memset( pPal, 0, nColors * sizeof(PALETTEENTRY) );
+ GetPaletteEntries( pwc->hGLPalette, 0, nColors, pPal );
+ pColTab = (RGBQUAD *)malloc( nColors * sizeof(RGBQUAD));
+ for (i = 0, pRGB = pColTab, pPE = pPal; i < nColors; i++, pRGB++, pPE++) {
+ pRGB->rgbRed = pPE->peRed;
+ pRGB->rgbGreen = pPE->peGreen;
+ pRGB->rgbBlue = pPE->peBlue;
+ }
+ if(pwc->db_flag)
+ bRet = SetDIBColorTable(pwc->dib.hDC, 0, nColors, pColTab );
+
+ if(!bRet)
+ dwErr = GetLastError();
+
+ free( pColTab );
+ free( pPal );
+
+ return(bRet);
+}
+
+
+//
+// Free up the dib section that was created
+//
+BOOL wmDeleteBackingStore(PWMC pwc)
+{
+ SelectObject(pwc->dib.hDC, pwc->hOldBitmap);
+ DeleteDC(pwc->dib.hDC);
+ DeleteObject(pwc->hbmDIB);
+ UnmapViewOfFile(pwc->dib.base);
+ CloseHandle(pwc->dib.hFileMap);
+ return TRUE;
+}
+
+
+//
+// This function creates the DIB section that is used for combined
+// GL and GDI calls
+//
+BOOL /*WINAPI*/ wmCreateBackingStore(PWMC pwc, long lxSize, long lySize)
+{
+ HDC hdc = pwc->hDC;
+ LPBITMAPINFO pbmi = &(pwc->bmi);
+ int iUsage;
+
+ pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ pbmi->bmiHeader.biWidth = lxSize;
+ pbmi->bmiHeader.biHeight= -lySize;
+ pbmi->bmiHeader.biPlanes = 1;
+ if(pwc->rgb_flag)
+ pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwc->hDC, BITSPIXEL);
+ else
+ pbmi->bmiHeader.biBitCount = 8;
+ pbmi->bmiHeader.biCompression = BI_RGB;
+ pbmi->bmiHeader.biSizeImage = 0;
+ pbmi->bmiHeader.biXPelsPerMeter = 0;
+ pbmi->bmiHeader.biYPelsPerMeter = 0;
+ pbmi->bmiHeader.biClrUsed = 0;
+ pbmi->bmiHeader.biClrImportant = 0;
+
+ iUsage = (pbmi->bmiHeader.biBitCount <= 8) ? DIB_PAL_COLORS : DIB_RGB_COLORS;
+
+ pwc->cColorBits = pbmi->bmiHeader.biBitCount;
+ pwc->ScanWidth = pwc->pitch = lxSize;
+
+ wmCreateDIBSection(hdc, pwc, pbmi, iUsage);
+
+ if ((iUsage == DIB_PAL_COLORS) && !(pwc->hGLPalette)) {
+ wmCreatePalette( pwc );
+ wmSetDibColors( pwc );
+ }
+ wmSetPixelFormat(pwc, pwc->hDC);
+ return(TRUE);
+
+}
+
+
+//
+// This function copies one scan line in a DIB section to another
+//
+BOOL GLWINAPI wmSetDIBits(PWMC pwc, UINT uiScanWidth, UINT uiNumScans, UINT nBypp, UINT uiNewWidth, LPBYTE pBits)
+{
+ UINT uiScans = 0;
+ LPBYTE pDest = pwc->pbPixels;
+ DWORD dwNextScan = uiScanWidth;
+ DWORD dwNewScan = uiNewWidth;
+ DWORD dwScanWidth = (uiScanWidth * nBypp);
+
+ //
+ // We need to round up to the nearest DWORD
+ // and multiply by the number of bytes per
+ // pixel
+ //
+ dwNextScan = (((dwNextScan * nBypp)+ 3) & ~3);
+ dwNewScan = (((dwNewScan * nBypp)+ 3) & ~3);
+
+ for(uiScans = 0; uiScans < uiNumScans; uiScans++){
+ CopyMemory(pDest, pBits, dwScanWidth);
+ pBits += dwNextScan;
+ pDest += dwNewScan;
+ }
+
+ return(TRUE);
+
+}
+
+
+BOOL wmFlush(PWMC pwc);
+
+/*
+ * Useful macros:
+ Modified from file osmesa.c
+ */
+
+
+#define PIXELADDR(X,Y) ((GLubyte *)Current->pbPixels + (Current->height-Y-1)* Current->ScanWidth + (X)*nBypp)
+#define PIXELADDR1( X, Y ) \
+ ((GLubyte *)wmesa->pbPixels + (wmesa->height-Y-1)* wmesa->ScanWidth + (X))
+#define PIXELADDR2( X, Y ) \
+ ((GLubyte *)wmesa->pbPixels + (wmesa->height-Y-1)* wmesa->ScanWidth + (X)*2)
+#define PIXELADDR4( X, Y ) \
+ ((GLubyte *)wmesa->pbPixels + (wmesa->height-Y-1)* wmesa->ScanWidth + (X)*4)
+
+
+BYTE DITHER_RGB_2_8BIT( int r, int g, int b, int x, int y);
+
+/* Finish all pending operations and synchronize. */
+static void finish(GLcontext* ctx)
+{
+ /* No op */
+}
+
+
+//
+// We cache all gl draw routines until a flush is made
+//
+static void flush(GLcontext* ctx)
+{
+ STARTPROFILE
+ if((Current->rgb_flag /*&& !(Current->dib.fFlushed)*/&&!(Current->db_flag))
+ ||(!Current->rgb_flag))
+ {
+ wmFlush(Current);
+ }
+ ENDPROFILE(flush)
+
+}
+
+
+
+/*
+ * Set the color index used to clear the color buffer.
+ */
+static void clear_index(GLcontext* ctx, GLuint index)
+{
+ STARTPROFILE
+ Current->clearpixel = index;
+ ENDPROFILE(clear_index)
+}
+
+
+
+/*
+ * Set the color used to clear the color buffer.
+ */
+static void clear_color( GLcontext* ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+ STARTPROFILE
+ Current->clearpixel=RGB(r, g, b );
+ ENDPROFILE(clear_color)
+}
+
+
+
+/*
+ * Clear the specified region of the color buffer using the clear color
+ * or index as specified by one of the two functions above.
+ */
+static void clear(GLcontext* ctx,
+ GLboolean all,GLint x, GLint y, GLint width, GLint height )
+{
+ DWORD dwColor;
+ WORD wColor;
+ BYTE bColor;
+ LPDWORD lpdw = (LPDWORD)Current->pbPixels;
+ LPWORD lpw = (LPWORD)Current->pbPixels;
+ LPBYTE lpb = Current->pbPixels;
+ int lines;
+
+ STARTPROFILE
+
+ if (all){
+ x=y=0;
+ width=Current->width;
+ height=Current->height;
+ }
+ if(Current->db_flag==GL_TRUE){
+ UINT nBypp = Current->cColorBits / 8;
+ int i = 0;
+ int iSize;
+
+ if(nBypp ==1 ){
+ /* Need rectification */
+ iSize = Current->width/4;
+ bColor = BGR8(GetRValue(Current->clearpixel),
+ GetGValue(Current->clearpixel),
+ GetBValue(Current->clearpixel));
+ wColor = MAKEWORD(bColor,bColor);
+ dwColor = MAKELONG(wColor, wColor);
+ }
+ if(nBypp == 2){
+ iSize = Current->width / 2;
+ wColor = BGR16(GetRValue(Current->clearpixel),
+ GetGValue(Current->clearpixel),
+ GetBValue(Current->clearpixel));
+ dwColor = MAKELONG(wColor, wColor);
+ }
+ else if(nBypp == 4){
+ iSize = Current->width;
+ dwColor = BGR32(GetRValue(Current->clearpixel),
+ GetGValue(Current->clearpixel),
+ GetBValue(Current->clearpixel));
+ }
+
+ while(i < iSize){
+ *lpdw = dwColor;
+ lpdw++;
+ i++;
+ }
+
+ //
+ // This is the 24bit case
+ //
+ if (nBypp == 3) {
+ iSize = Current->width *3/4;
+ dwColor = BGR24(GetRValue(Current->clearpixel),
+ GetGValue(Current->clearpixel),
+ GetBValue(Current->clearpixel));
+ while(i < iSize){
+ *lpdw = dwColor;
+ lpb += nBypp;
+ lpdw = (LPDWORD)lpb;
+ i++;
+ }
+ }
+
+ i = 0;
+ if(stereo_flag) lines = height /2;
+ else lines = height;
+ do{
+ lpb += Current->ScanWidth;
+ memcpy(lpb, Current->pbPixels, iSize*4);
+ i++;
+ }
+ while(i<lines-1);
+ }
+ else{ // For single buffer
+ HDC DC=DD_GETDC;
+ HPEN Pen=CreatePen(PS_SOLID,1,Current->clearpixel);
+ HBRUSH Brush=CreateSolidBrush(Current->clearpixel);
+ HPEN Old_Pen=SelectObject(DC,Pen);
+ HBRUSH Old_Brush=SelectObject(DC,Brush);
+ Rectangle(DC,x,y,x+width,y+height);
+ SelectObject(DC,Old_Pen);
+ SelectObject(DC,Old_Brush);
+ DeleteObject(Pen);
+ DeleteObject(Brush);
+ DD_RELEASEDC;
+ }
+
+
+
+ ENDPROFILE(clear)
+}
+
+
+
+/* Set the current color index. */
+static void set_index(GLcontext* ctx, GLuint index)
+{
+ STARTPROFILE
+ Current->pixel=index;
+ ENDPROFILE(set_index)
+}
+
+
+
+/* Set the current RGBA color. */
+static void set_color( GLcontext* ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+ STARTPROFILE
+ Current->pixel = RGB( r, g, b );
+ ENDPROFILE(set_color)
+}
+
+
+
+/* Set the index mode bitplane mask. */
+static GLboolean index_mask(GLcontext* ctx, GLuint mask)
+{
+ /* can't implement */
+ return GL_FALSE;
+}
+
+
+
+/* Set the RGBA drawing mask. */
+static GLboolean color_mask( GLcontext* ctx,
+ GLboolean rmask, GLboolean gmask,
+ GLboolean bmask, GLboolean amask)
+{
+ /* can't implement */
+ return GL_FALSE;
+}
+
+
+
+/*
+ * Set the pixel logic operation. Return GL_TRUE if the device driver
+ * can perform the operation, otherwise return GL_FALSE. If GL_FALSE
+ * is returned, the logic op will be done in software by Mesa.
+ */
+GLboolean logicop( GLcontext* ctx, GLenum op )
+{
+ /* can't implement */
+ return GL_FALSE;
+}
+
+
+static void dither( GLcontext* ctx, GLboolean enable )
+{
+ if(enable == GL_FALSE){
+ Current->dither_flag = GL_FALSE;
+ if(Current->cColorBits == 8)
+ Current->pixelformat = PF_INDEX8;
+ }
+ else{
+ if (Current->rgb_flag && Current->cColorBits == 8){
+ Current->pixelformat = PF_DITHER8;
+ Current->dither_flag = GL_TRUE;
+ }
+ else
+ Current->dither_flag = GL_FALSE;
+ }
+}
+
+
+
+static GLboolean set_buffer( GLcontext* ctx, GLenum mode )
+{
+ STARTPROFILE
+ /* TODO: this could be better */
+ if (mode==GL_FRONT || mode==GL_BACK) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+ ENDPROFILE(set_buffer)
+}
+
+
+
+/* Return characteristics of the output buffer. */
+static void buffer_size( GLcontext* ctx, GLuint *width, GLuint *height /*, GLuint *depth */)
+{
+
+ int New_Size;
+ RECT CR;
+
+ STARTPROFILE
+ GetClientRect(Current->Window,&CR);
+
+ *width=CR.right;
+ *height=CR.bottom;
+// *depth = Current->depth;
+
+ New_Size=((*width)!=Current->width) || ((*height)!=Current->height);
+
+ if (New_Size){
+ Current->width=*width;
+ Current->height=*height;
+ Current->ScanWidth=Current->width;
+ if ((Current->ScanWidth%sizeof(long))!=0)
+ Current->ScanWidth+=(sizeof(long)-(Current->ScanWidth%sizeof(long)));
+
+ if (Current->db_flag){
+#ifdef DDRAW
+ DDDeleteOffScreen(Current);
+ DDCreateOffScreen(Current);
+#else
+ if (Current->rgb_flag==GL_TRUE && Current->dither_flag!=GL_TRUE){
+ wmDeleteBackingStore(Current);
+ wmCreateBackingStore(Current, Current->width, Current->height);
+ }
+#endif
+ }
+
+// Resize OsmesaBuffer if in Parallel mode
+#if !defined(NO_PARALLEL)
+ if(parallelFlag)
+ PRSizeRenderBuffer(Current->width, Current->height,Current->ScanWidth,
+ Current->rgb_flag == GL_TRUE ? Current->pbPixels: Current->ScreenMem);
+#endif
+ }
+ ENDPROFILE(buffer_size)
+}
+
+
+
+/**********************************************************************/
+/***** Accelerated point, line, polygon rendering *****/
+/**********************************************************************/
+
+
+static void fast_rgb_points( GLcontext* ctx, GLuint first, GLuint last )
+{
+ GLuint i;
+ // HDC DC=DD_GETDC;
+ PWMC pwc = Current;
+
+ STARTPROFILE
+
+ if (Current->gl_ctx->VB->MonoColor) {
+ /* all drawn with current color */
+ for (i=first;i<=last;i++) {
+ if (!Current->gl_ctx->VB->ClipMask[i]) {
+ int x, y;
+ x = (GLint) Current->gl_ctx->VB->Win[i][0];
+ y = FLIP( (GLint) Current->gl_ctx->VB->Win[i][1] );
+ wmSetPixel(pwc, y,x,GetRValue(Current->pixel),
+ GetGValue(Current->pixel), GetBValue(Current->pixel));
+ }
+ }
+ }
+ else {
+ /* draw points of different colors */
+ for (i=first;i<=last;i++) {
+ if (!Current->gl_ctx->VB->ClipMask[i]) {
+ int x, y;
+ unsigned long pixel=RGB(Current->gl_ctx->VB->Color[i][0]*255.0,
+ Current->gl_ctx->VB->Color[i][1]*255.0,
+ Current->gl_ctx->VB->Color[i][2]*255.0);
+ x = (GLint) Current->gl_ctx->VB->Win[i][0];
+ y = FLIP( (GLint) Current->gl_ctx->VB->Win[i][1] );
+ wmSetPixel(pwc, y,x,Current->gl_ctx->VB->Color[i][0]*255.0,
+ Current->gl_ctx->VB->Color[i][1]*255.0,
+ Current->gl_ctx->VB->Color[i][2]*255.0);
+ }
+ }
+ }
+// DD_RELEASEDC;
+ ENDPROFILE(fast_rgb_points)
+}
+
+
+
+/* Return pointer to accerated points function */
+extern points_func choose_points_function( GLcontext* ctx )
+{
+ STARTPROFILE
+ if (ctx->Point.Size==1.0 && !ctx->Point.SmoothFlag && ctx->RasterMask==0
+ && !ctx->Texture.Enabled && ctx->Visual->RGBAflag) {
+ ENDPROFILE(choose_points_function)
+ return fast_rgb_points;
+ }
+ else {
+ ENDPROFILE(choose_points_function)
+ return NULL;
+ }
+}
+
+
+
+/* Draw a line using the color specified by Current->gl_ctx->VB->Color[pv] */
+static void fast_flat_rgb_line( GLcontext* ctx, GLuint v0, GLuint v1, GLuint pv )
+{
+ STARTPROFILE
+ int x0, y0, x1, y1;
+ unsigned long pixel;
+ HDC DC=DD_GETDC;
+ HPEN Pen;
+ HPEN Old_Pen;
+
+ if (Current->gl_ctx->VB->MonoColor) {
+ pixel = Current->pixel; /* use current color */
+ }
+ else {
+ pixel = RGB(Current->gl_ctx->VB->Color[pv][0]*255.0, Current->gl_ctx->VB->Color[pv][1]*255.0, Current->gl_ctx->VB->Color[pv][2]*255.0);
+ }
+
+ x0 = (int) Current->gl_ctx->VB->Win[v0][0];
+ y0 = FLIP( (int) Current->gl_ctx->VB->Win[v0][1] );
+ x1 = (int) Current->gl_ctx->VB->Win[v1][0];
+ y1 = FLIP( (int) Current->gl_ctx->VB->Win[v1][1] );
+
+
+ BEGINGDICALL
+
+ Pen=CreatePen(PS_SOLID,1,pixel);
+ Old_Pen=SelectObject(DC,Pen);
+ MoveToEx(DC,x0,y0,NULL);
+ LineTo(DC,x1,y1);
+ SelectObject(DC,Old_Pen);
+ DeleteObject(Pen);
+ DD_RELEASEDC;
+
+ ENDGDICALL
+
+ ENDPROFILE(fast_flat_rgb_line)
+}
+
+
+
+/* Return pointer to accerated line function */
+static line_func choose_line_function( GLcontext* ctx )
+{
+ STARTPROFILE
+ if (ctx->Line.Width==1.0 && !ctx->Line.SmoothFlag && !ctx->Line.StippleFlag
+ && ctx->Light.ShadeModel==GL_FLAT && ctx->RasterMask==0
+ && !ctx->Texture.Enabled && Current->rgb_flag) {
+ ENDPROFILE(choose_line_function)
+ return fast_flat_rgb_line;
+ }
+ else {
+ ENDPROFILE(choose_line_function)
+ return NULL;
+ }
+}
+
+
+/**********************************************************************/
+/***** Span-based pixel drawing *****/
+/**********************************************************************/
+
+
+/* Write a horizontal span of color-index pixels with a boolean mask. */
+static void write_index_span( GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLuint index[],
+ const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ PBYTE Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i]=index[i];
+ ENDPROFILE(write_index_span)
+}
+
+
+
+/*
+ * Write a horizontal span of pixels with a boolean mask. The current
+ * color index is used for all pixels.
+ */
+static void write_monoindex_span(GLcontext* ctx,
+ GLuint n,GLint x,GLint y,
+ const GLubyte mask[])
+{
+ STARTPROFILE
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i]=Current->pixel;
+ ENDPROFILE(write_monoindex_span)
+}
+
+/*
+ To improve the performance of this routine, frob the data into an actual scanline
+ and call bitblt on the complete scan line instead of SetPixel.
+*/
+
+/* Write a horizontal span of color pixels with a boolean mask. */
+static void write_color_span( GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte
+ red[], const GLubyte green[],
+ const GLubyte blue[], const GLubyte alpha[],
+ const GLubyte mask[] )
+{
+ STARTPROFILE
+
+ PWMC pwc = Current;
+
+ if (pwc->rgb_flag==GL_TRUE)
+ {
+ GLuint i;
+ HDC DC=DD_GETDC;
+ y=FLIP(y);
+
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, y, x + i,red[i], green[i], blue[i]);
+ }
+
+ else {
+ for (i=0; i<n; i++)
+ wmSetPixel(pwc, y, x + i, red[i], green[i], blue[i]);
+ }
+
+ DD_RELEASEDC;
+
+ }
+
+ else
+ {
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
+ y=FLIP(y);
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i]=GetNearestPaletteIndex(Current->hPal,RGB(red[i],green[i],blue[i]));
+ }
+ else {
+ for (i=0; i<n; i++)
+ Mem[i]=GetNearestPaletteIndex(Current->hPal,RGB(red[i],green[i],blue[i]));
+ }
+ }
+ ENDPROFILE(write_color_span)
+
+}
+
+/*
+ * Write a horizontal span of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_monocolor_span( GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte mask[])
+{
+ STARTPROFILE
+ GLuint i;
+ HDC DC=DD_GETDC;
+ PWMC pwc = Current;
+
+ assert(Current->rgb_flag==GL_TRUE);
+ y=FLIP(y);
+
+ if(Current->rgb_flag==GL_TRUE){
+ for (i=0; i<n; i++)
+ if (mask[i])
+// Trying
+ wmSetPixel(pwc,y,x+i,GetRValue(Current->pixel), GetGValue(Current->pixel), GetBValue(Current->pixel));
+ }
+ else {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ SetPixel(DC, y, x+i, Current->pixel);
+ }
+
+ DD_RELEASEDC;
+
+ ENDPROFILE(write_monocolor_span)
+}
+
+
+
+/**********************************************************************/
+/***** Array-based pixel drawing *****/
+/**********************************************************************/
+
+
+/* Write an array of pixels with a boolean mask. */
+static void write_index_pixels( GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLuint index[], const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ BYTE *Mem=Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i];
+ *Mem = index[i];
+ }
+ }
+ ENDPROFILE(write_index_pixels)
+}
+
+
+
+/*
+ * Write an array of pixels with a boolean mask. The current color
+ * index is used for all pixels.
+ */
+static void write_monoindex_pixels( GLcontext* ctx,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ BYTE *Mem=Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i];
+ *Mem = Current->pixel;
+ }
+ }
+ ENDPROFILE(write_monoindex_pixels)
+}
+
+
+
+/* Write an array of pixels with a boolean mask. */
+static void write_color_pixels( GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte r[], const GLubyte g[],
+ const GLubyte b[], const GLubyte a[],
+ const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ PWMC pwc = Current;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, FLIP(y[i]),x[i],r[i],g[i],b[i]);
+ DD_RELEASEDC;
+ ENDPROFILE(write_color_pixels)
+}
+
+
+
+/*
+ * Write an array of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_monocolor_pixels( GLcontext* ctx,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ PWMC pwc = Current;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, FLIP(y[i]),x[i],GetRValue(Current->pixel),
+ GetGValue(Current->pixel), GetBValue(Current->pixel));
+ DD_RELEASEDC;
+ ENDPROFILE(write_monocolor_pixels)
+}
+
+
+
+/**********************************************************************/
+/***** Read spans/arrays of pixels *****/
+/**********************************************************************/
+
+
+/* Read a horizontal span of color-index pixels. */
+static void read_index_span( GLcontext* ctx, GLuint n, GLint x, GLint y, GLuint index[])
+{
+ STARTPROFILE
+ GLuint i;
+ BYTE *Mem=Current->ScreenMem+FLIP(y)*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ index[i]=Mem[i];
+ ENDPROFILE(read_index_span)
+
+}
+
+
+
+
+/* Read an array of color index pixels. */
+static void read_index_pixels( GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint indx[], const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ indx[i]=*(Current->ScreenMem+FLIP(y[i])*Current->ScanWidth+x[i]);
+ }
+ }
+ ENDPROFILE(read_index_pixels)
+}
+
+
+
+/* Read a horizontal span of color pixels. */
+static void read_color_span( GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ GLubyte red[], GLubyte green[],
+ GLubyte blue[], GLubyte alpha[] )
+{
+ STARTPROFILE
+ UINT i;
+ COLORREF Color;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ y=FLIP(y);
+ for (i=0; i<n; i++)
+ {
+ Color=GetPixel(DC,x+i,y);
+ red[i]=GetRValue(Color);
+ green[i]=GetGValue(Color);
+ blue[i]=GetBValue(Color);
+ alpha[i]=255;
+ }
+ DD_RELEASEDC;
+ memset(alpha,0,n*sizeof(GLint));
+ ENDPROFILE(read_color_span)
+}
+
+
+/* Read an array of color pixels. */
+static void read_color_pixels( GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte red[], GLubyte green[],
+ GLubyte blue[], GLubyte alpha[],
+ const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ COLORREF Color;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ Color=GetPixel(DC,x[i],FLIP(y[i]));
+ red[i]=GetRValue(Color);
+ green[i]=GetGValue(Color);
+ blue[i]=GetBValue(Color);
+ alpha[i]=255;
+ }
+ }
+ DD_RELEASEDC;
+ memset(alpha,0,n*sizeof(GLint));
+ ENDPROFILE(read_color_pixels)
+}
+
+
+
+/**********************************************************************/
+/**********************************************************************/
+
+
+
+void setup_DD_pointers( GLcontext* ctx )
+{
+ ctx->Driver.UpdateState = setup_DD_pointers;
+ ctx->Driver.GetBufferSize = buffer_size;
+ ctx->Driver.Finish = finish;
+ ctx->Driver.Flush = flush;
+
+ ctx->Driver.ClearIndex = clear_index;
+ ctx->Driver.ClearColor = clear_color;
+ ctx->Driver.Clear = clear;
+
+ ctx->Driver.Index = set_index;
+ ctx->Driver.Color = set_color;
+ ctx->Driver.IndexMask = index_mask;
+ ctx->Driver.ColorMask = color_mask;
+
+ ctx->Driver.LogicOp = logicop;
+ ctx->Driver.Dither = dither;
+
+ ctx->Driver.SetBuffer = set_buffer;
+ ctx->Driver.GetBufferSize = buffer_size;
+
+ ctx->Driver.PointsFunc = choose_points_function(ctx);
+ ctx->Driver.LineFunc = choose_line_function(ctx);
+ ctx->Driver.TriangleFunc = choose_triangle_function( ctx );
+
+ /* Pixel/span writing functions: */
+ ctx->Driver.WriteColorSpan = write_color_span;
+ ctx->Driver.WriteMonocolorSpan = write_monocolor_span;
+ ctx->Driver.WriteColorPixels = write_color_pixels;
+ ctx->Driver.WriteMonocolorPixels = write_monocolor_pixels;
+ ctx->Driver.WriteIndexSpan = write_index_span;
+ ctx->Driver.WriteMonoindexSpan = write_monoindex_span;
+ ctx->Driver.WriteIndexPixels = write_index_pixels;
+ ctx->Driver.WriteMonoindexPixels = write_monoindex_pixels;
+
+ /* Pixel/span reading functions: */
+ ctx->Driver.ReadIndexSpan = read_index_span;
+ ctx->Driver.ReadColorSpan = read_color_span;
+ ctx->Driver.ReadIndexPixels = read_index_pixels;
+ ctx->Driver.ReadColorPixels = read_color_pixels;
+}
+
+
+/**********************************************************************/
+/***** WMesa API Functions *****/
+/**********************************************************************/
+
+
+
+#define PAL_SIZE 256
+static void GetPalette(HPALETTE Pal,RGBQUAD *aRGB)
+{
+ STARTPROFILE
+ int i;
+ HDC hdc;
+ struct
+ {
+ WORD Version;
+ WORD NumberOfEntries;
+ PALETTEENTRY aEntries[PAL_SIZE];
+ } Palette =
+ {
+ 0x300,
+ PAL_SIZE
+ };
+ hdc=GetDC(NULL);
+ if (Pal!=NULL)
+ GetPaletteEntries(Pal,0,PAL_SIZE,Palette.aEntries);
+ else
+ GetSystemPaletteEntries(hdc,0,PAL_SIZE,Palette.aEntries);
+ if (GetSystemPaletteUse(hdc) == SYSPAL_NOSTATIC)
+ {
+ for(i = 0; i <PAL_SIZE; i++)
+ Palette.aEntries[i].peFlags = PC_RESERVED;
+ Palette.aEntries[255].peRed = 255;
+ Palette.aEntries[255].peGreen = 255;
+ Palette.aEntries[255].peBlue = 255;
+ Palette.aEntries[255].peFlags = 0;
+ Palette.aEntries[0].peRed = 0;
+ Palette.aEntries[0].peGreen = 0;
+ Palette.aEntries[0].peBlue = 0;
+ Palette.aEntries[0].peFlags = 0;
+ }
+ else
+ {
+ int nStaticColors;
+ int nUsableColors;
+ nStaticColors = GetDeviceCaps(hdc, NUMCOLORS)/2;
+ for (i=0; i<nStaticColors; i++)
+ Palette.aEntries[i].peFlags = 0;
+ nUsableColors = PAL_SIZE-nStaticColors;
+ for (; i<nUsableColors; i++)
+ Palette.aEntries[i].peFlags = PC_RESERVED;
+ for (; i<PAL_SIZE-nStaticColors; i++)
+ Palette.aEntries[i].peFlags = PC_RESERVED;
+ for (i=PAL_SIZE-nStaticColors; i<PAL_SIZE; i++)
+ Palette.aEntries[i].peFlags = 0;
+ }
+ ReleaseDC(NULL,hdc);
+ for (i=0; i<PAL_SIZE; i++)
+ {
+ aRGB[i].rgbRed=Palette.aEntries[i].peRed;
+ aRGB[i].rgbGreen=Palette.aEntries[i].peGreen;
+ aRGB[i].rgbBlue=Palette.aEntries[i].peBlue;
+ aRGB[i].rgbReserved=Palette.aEntries[i].peFlags;
+ }
+ ENDPROFILE(GetPalette)
+}
+
+
+WMesaContext WMesaCreateContext( HWND hWnd, HPALETTE* Pal,
+ GLboolean rgb_flag,
+ GLboolean db_flag )
+{
+ RECT CR;
+ WMesaContext c;
+ GLboolean true_color_flag;
+ c = (struct wmesa_context * ) calloc(1,sizeof(struct wmesa_context));
+ if (!c)
+ return NULL;
+
+ c->Window=hWnd;
+ c->hDC = GetDC(hWnd);
+ true_color_flag = GetDeviceCaps(c->hDC, BITSPIXEL) > 8;
+#ifdef DDRAW
+ if(true_color_flag) c->rgb_flag = rgb_flag = GL_TRUE;
+#endif
+
+
+#ifdef DITHER
+ if ((true_color_flag==GL_FALSE) && (rgb_flag == GL_TRUE)){
+ c->dither_flag = GL_TRUE;
+ c->hPalHalfTone = WinGCreateHalftonePalette();
+ }
+ else
+ c->dither_flag = GL_FALSE;
+#else
+ c->dither_flag = GL_FALSE;
+#endif
+
+
+ if (rgb_flag==GL_FALSE)
+ {
+ c->rgb_flag = GL_FALSE;
+// c->pixel = 1;
+ c->db_flag = db_flag =GL_TRUE; // WinG requires double buffering
+ printf("Single buffer is not supported in color index mode, setting to double buffer.\n");
+ }
+ else
+ {
+ c->rgb_flag = GL_TRUE;
+// c->pixel = 0;
+ }
+ GetClientRect(c->Window,&CR);
+ c->width=CR.right;
+ c->height=CR.bottom;
+ if (db_flag)
+ {
+ c->db_flag = 1;
+ /* Double buffered */
+#ifndef DDRAW
+// if (c->rgb_flag==GL_TRUE && c->dither_flag != GL_TRUE )
+ {
+ wmCreateBackingStore(c, c->width, c->height);
+
+ }
+#endif
+ }
+ else
+ {
+ /* Single Buffered */
+ if (c->rgb_flag)
+ c->db_flag = 0;
+ }
+#ifdef DDRAW
+ if (DDInit(c,hWnd) == GL_FALSE) {
+ free( (void *) c );
+ exit(1);
+ }
+#endif
+
+
+ c->gl_visual = gl_create_visual(rgb_flag,
+ GL_FALSE, /* software alpha */
+ db_flag, /* db_flag */
+ 16, /* depth_bits */
+ 8, /* stencil_bits */
+ 8, /* accum_bits */
+ 8,
+ 255.0, 255.0, 255.0, 255.0,
+ 8,8,8,8 );
+
+ if (!c->gl_visual) {
+ return NULL;
+ }
+
+ /* allocate a new Mesa context */
+ c->gl_ctx = gl_create_context( c->gl_visual, NULL,c);
+
+ if (!c->gl_ctx) {
+ gl_destroy_visual( c->gl_visual );
+ free(c);
+ return NULL;
+ }
+
+ c->gl_buffer = gl_create_framebuffer( c->gl_visual );
+ if (!c->gl_buffer) {
+ gl_destroy_visual( c->gl_visual );
+ gl_destroy_context( c->gl_ctx );
+ free(c);
+ return NULL;
+ }
+// setup_DD_pointers(c->gl_ctx);
+
+ return c;
+}
+
+void WMesaDestroyContext( void )
+{
+ WMesaContext c = Current;
+ ReleaseDC(c->Window,c->hDC);
+ WC = c;
+ if(c->hPalHalfTone != NULL)
+ DeleteObject(c->hPalHalfTone);
+ gl_destroy_visual( c->gl_visual );
+ gl_destroy_framebuffer( c->gl_buffer );
+ gl_destroy_context( c->gl_ctx );
+
+ if (c->db_flag)
+#ifdef DDRAW
+ DDFree(c);
+#else
+ wmDeleteBackingStore(c);
+#endif
+ free( (void *) c );
+//Following code is added to enable parallel render
+// Parallel render only work in double buffer mode
+#if !defined(NO_PARALLEL)
+ if(parallelMachine)
+ PRDestroyRenderBuffer();
+#endif
+// End modification
+}
+
+
+
+void /*APIENTRY*/ WMesaMakeCurrent( WMesaContext c )
+{
+ if(!c){
+ Current = c;
+ return;
+ }
+
+ //
+ // A little optimization
+ // If it already is current,
+ // don't set it again
+ //
+ if(Current == c)
+ return;
+
+ //gl_set_context( c->gl_ctx );
+ gl_make_current(c->gl_ctx, c->gl_buffer);
+ Current = c;
+ setup_DD_pointers(c->gl_ctx);
+ if (Current->gl_ctx->Viewport.Width==0) {
+ /* initialize viewport to window size */
+ gl_Viewport( Current->gl_ctx,
+ 0, 0, Current->width, Current->height );
+ }
+ if ((c->cColorBits <= 8 ) && (c->rgb_flag == GL_TRUE)){
+ WMesaPaletteChange(c->hPalHalfTone);
+ }
+}
+
+
+
+void /*APIENTRY*/ WMesaSwapBuffers( void )
+{
+ HDC DC = Current->hDC;
+ if (Current->db_flag)
+ wmFlush(Current);
+}
+
+
+
+void /*APIENTRY*/ WMesaPaletteChange(HPALETTE Pal)
+{
+ int vRet;
+ LPPALETTEENTRY pPal;
+ if (Current && (Current->rgb_flag==GL_FALSE || Current->dither_flag == GL_TRUE))
+ {
+ pPal = (PALETTEENTRY *)malloc( 256 * sizeof(PALETTEENTRY));
+ Current->hPal=Pal;
+// GetPaletteEntries( Pal, 0, 256, pPal );
+ GetPalette( Pal, pPal );
+#ifdef DDRAW
+ Current->lpDD->lpVtbl->CreatePalette(Current->lpDD,DDPCAPS_8BIT,
+ pPal, &(Current->lpDDPal), NULL);
+ if (Current->lpDDPal)
+ Current->lpDDSPrimary->lpVtbl->SetPalette(Current->lpDDSPrimary,Current->lpDDPal);
+#else
+ vRet = SetDIBColorTable(Current->dib.hDC,0,256,pPal);
+#endif
+ free( pPal );
+ }
+
+}
+
+
+
+
+static unsigned char threeto8[8] = {
+ 0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377
+};
+
+static unsigned char twoto8[4] = {
+ 0, 0x55, 0xaa, 0xff
+};
+
+static unsigned char oneto8[2] = {
+ 0, 255
+};
+
+static unsigned char componentFromIndex(UCHAR i, UINT nbits, UINT shift)
+{
+ unsigned char val;
+
+ val = i >> shift;
+ switch (nbits) {
+
+ case 1:
+ val &= 0x1;
+ return oneto8[val];
+
+ case 2:
+ val &= 0x3;
+ return twoto8[val];
+
+ case 3:
+ val &= 0x7;
+ return threeto8[val];
+
+ default:
+ return 0;
+ }
+}
+
+void /*WINAPI*/ wmCreatePalette( PWMC pwdc )
+{
+ /* Create a compressed and re-expanded 3:3:2 palette */
+ int i;
+ LOGPALETTE *pPal;
+ BYTE rb, rs, gb, gs, bb, bs;
+
+ pwdc->nColors = 0x100;
+
+ pPal = (PLOGPALETTE)malloc(sizeof(LOGPALETTE) + pwdc->nColors * sizeof(PALETTEENTRY));
+ memset( pPal, 0, sizeof(LOGPALETTE) + pwdc->nColors * sizeof(PALETTEENTRY) );
+
+ pPal->palVersion = 0x300;
+
+ rb = REDBITS;
+ rs = REDSHIFT;
+ gb = GREENBITS;
+ gs = GREENSHIFT;
+ bb = BLUEBITS;
+ bs = BLUESHIFT;
+
+ if (pwdc->db_flag) {
+
+ /* Need to make two palettes: one for the screen DC and one for the DIB. */
+ pPal->palNumEntries = pwdc->nColors;
+ for (i = 0; i < pwdc->nColors; i++) {
+ pPal->palPalEntry[i].peRed = componentFromIndex( i, rb, rs );
+ pPal->palPalEntry[i].peGreen = componentFromIndex( i, gb, gs );
+ pPal->palPalEntry[i].peBlue = componentFromIndex( i, bb, bs );
+ pPal->palPalEntry[i].peFlags = 0;
+ }
+ pwdc->hGLPalette = CreatePalette( pPal );
+ pwdc->hPalette = CreatePalette( pPal );
+ }
+
+ else {
+ pPal->palNumEntries = pwdc->nColors;
+ for (i = 0; i < pwdc->nColors; i++) {
+ pPal->palPalEntry[i].peRed = componentFromIndex( i, rb, rs );
+ pPal->palPalEntry[i].peGreen = componentFromIndex( i, gb, gs );
+ pPal->palPalEntry[i].peBlue = componentFromIndex( i, bb, bs );
+ pPal->palPalEntry[i].peFlags = 0;
+ }
+ pwdc->hGLPalette = CreatePalette( pPal );
+ }
+
+ free(pPal);
+
+}
+
+void /*WINAPI*/ wmSetPixel(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b)
+{
+ if(Current->db_flag){
+ LPBYTE lpb = pwc->pbPixels;
+ LPDWORD lpdw;
+ LPWORD lpw;
+ UINT nBypp = pwc->cColorBits / 8;
+ UINT nOffset = iPixel % nBypp;
+
+ // Move the pixel buffer pointer to the scanline that we
+ // want to access
+
+// pwc->dib.fFlushed = FALSE;
+
+ lpb += pwc->ScanWidth * iScanLine;
+ // Now move to the desired pixel
+ lpb += iPixel * nBypp;
+ lpb = PIXELADDR(iPixel, iScanLine);
+ lpdw = (LPDWORD)lpb;
+ lpw = (LPWORD)lpb;
+
+ if(nBypp == 1){
+ if(pwc->dither_flag)
+ *lpb = DITHER_RGB_2_8BIT(r,g,b,iScanLine,iPixel);
+ else
+ *lpb = BGR8(r,g,b);
+ }
+ else if(nBypp == 2)
+ *lpw = BGR16(r,g,b);
+ else if (nBypp == 3){
+ *lpdw = BGR24(r,g,b);
+ }
+ else if (nBypp == 4)
+ *lpdw = BGR32(r,g,b);
+ }
+ else{
+ HDC DC = DD_GETDC;
+ SetPixel(DC, iPixel, iScanLine, RGB(r,g,b));
+ DD_RELEASEDC;
+ }
+}
+
+void /*WINAPI*/ wmCreateDIBSection(
+ HDC hDC,
+ PWMC pwc, // handle of device context
+ CONST BITMAPINFO *pbmi, // address of structure containing bitmap size, format, and color data
+ UINT iUsage // color data type indicator: RGB values or palette indices
+)
+{
+ DWORD dwSize = 0;
+ DWORD dwScanWidth;
+ UINT nBypp = pwc->cColorBits / 8;
+ HDC hic;
+
+ dwScanWidth = (((pwc->ScanWidth * nBypp)+ 3) & ~3);
+
+ pwc->ScanWidth =pwc->pitch = dwScanWidth;
+
+ if (stereo_flag)
+ pwc->ScanWidth = 2* pwc->pitch;
+
+ dwSize = sizeof(BITMAPINFO) + (dwScanWidth * pwc->height);
+
+ pwc->dib.hFileMap = CreateFileMapping((HANDLE)PAGE_FILE,
+ NULL,
+ PAGE_READWRITE | SEC_COMMIT,
+ 0,
+ dwSize,
+ NULL);
+
+ if (!pwc->dib.hFileMap)
+ return;
+
+ pwc->dib.base = MapViewOfFile(pwc->dib.hFileMap,
+ FILE_MAP_ALL_ACCESS,
+ 0,
+ 0,
+ 0);
+
+ if(!pwc->dib.base){
+ CloseHandle(pwc->dib.hFileMap);
+ return;
+ }
+
+// pwc->pbPixels = pwc->addrOffScreen = ((LPBYTE)pwc->dib.base) + sizeof(BITMAPINFO);
+
+// pwc->dib.hDC = CreateCompatibleDC(hDC);
+
+ CopyMemory(pwc->dib.base, pbmi, sizeof(BITMAPINFO));
+
+ hic = CreateIC("display", NULL, NULL, NULL);
+ pwc->dib.hDC = CreateCompatibleDC(hic);
+
+
+/* pwc->hbmDIB = CreateDIBitmap(hic,
+ &(pwc->bmi.bmiHeader),
+ CBM_INIT,
+ pwc->pbPixels,
+ &(pwc->bmi),
+ DIB_RGB_COLORS);
+*/
+ pwc->hbmDIB = CreateDIBSection(hic,
+ &(pwc->bmi),
+ (iUsage ? DIB_PAL_COLORS : DIB_RGB_COLORS),
+ &(pwc->pbPixels),
+ pwc->dib.hFileMap,
+ 0);
+ /*
+ pwc->hbmDIB = CreateDIBSection(hic,
+ &(pwc->bmi),
+ DIB_RGB_COLORS,
+ &(pwc->pbPixels),
+ pwc->dib.hFileMap,
+ 0);
+ */
+ pwc->ScreenMem = pwc->addrOffScreen = pwc->pbPixels;
+ pwc->hOldBitmap = SelectObject(pwc->dib.hDC, pwc->hbmDIB);
+
+ DeleteDC(hic);
+
+ return;
+
+}
+
+//
+// Blit memory DC to screen DC
+//
+BOOL /*WINAPI*/ wmFlush(PWMC pwc)
+{
+ BOOL bRet = 0;
+ DWORD dwErr = 0;
+ HRESULT ddrval;
+
+ // Now search through the torus frames and mark used colors
+ if(pwc->db_flag){
+#ifdef DDRAW
+ if (pwc->lpDDSOffScreen == NULL)
+ if(DDCreateOffScreen(pwc) == GL_FALSE)
+ return;
+
+ pwc->lpDDSOffScreen->lpVtbl->Unlock(pwc->lpDDSOffScreen, NULL);
+
+ while( 1 )
+ {
+ ddrval = pwc->lpDDSPrimary->lpVtbl->Blt( pwc->lpDDSPrimary,
+ &(pwc->rectSurface), pwc->lpDDSOffScreen, &(pwc->rectOffScreen), 0, NULL );
+
+ if( ddrval == DD_OK )
+ {
+ break;
+ }
+ if( ddrval == DDERR_SURFACELOST )
+ {
+ if(!DDRestoreAll(pwc))
+ {
+ break;
+ }
+ }
+ if( ddrval != DDERR_WASSTILLDRAWING )
+ {
+ break;
+ }
+ }
+
+ while (pwc->lpDDSOffScreen->lpVtbl->Lock(pwc->lpDDSOffScreen,
+ NULL, &(pwc->ddsd), 0, NULL) == DDERR_WASSTILLDRAWING)
+ ;
+
+ if(ddrval != DD_OK)
+ dwErr = GetLastError();
+#else
+ bRet = BitBlt(pwc->hDC, 0, 0, pwc->width, pwc->height,
+ pwc->dib.hDC, 0, 0, SRCCOPY);
+#endif
+ }
+
+ return(TRUE);
+
+}
+
+
+// The following code is added by Li Wei to enable stereo display
+
+#if !defined(NO_STEREO)
+
+void WMesaShowStereo(GLuint list)
+{
+
+ GLbitfield mask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
+ GLfloat cm[16];
+ GLint matrix_mode;
+ // Must use double Buffer
+ if( ! Current-> db_flag )
+ return;
+
+
+ glGetIntegerv(GL_MATRIX_MODE,&matrix_mode);
+
+// glPushMatrix(); //****
+ WMesaViewport(Current->gl_ctx,0,Current->height/2,Current->width,Current->height/2);
+// Current->gl_ctx->NewState = 0;
+
+ // glViewport(0,0,Current->width,Current->height/2);
+ if(matrix_mode!=GL_MODELVIEW)
+ glMatrixMode(GL_MODELVIEW);
+
+ glGetFloatv(GL_MODELVIEW_MATRIX,cm);
+ glLoadIdentity();
+ gluLookAt(viewDistance/2,0.0,0.0 ,
+ viewDistance/2,0.0,-1.0,
+ 0.0,1.0,0.0 );
+// glTranslatef(viewDistance/2.0,0.,0.);
+ glMultMatrixf( cm );
+
+ Current->ScreenMem = Current->pbPixels = Current->addrOffScreen;
+ //glPushMatrix();
+ glCallList( list );
+ //glPopMatrix();
+
+ glGetFloatv(GL_MODELVIEW_MATRIX,cm);
+ glLoadIdentity();
+ gluLookAt(-viewDistance/2,0.0,0.0 ,
+ -viewDistance/2,0.0,-1.0,
+ 0.0,1.0,0.0 );
+// glTranslatef(-viewDistance/2.0,0.,0.);
+ glMultMatrixf(cm);
+
+ Current->ScreenMem = Current->pbPixels = Current->addrOffScreen + Current->pitch;
+ glCallList(list);
+ if(matrix_mode!=GL_MODELVIEW)
+ glMatrixMode(matrix_mode);
+
+// glPopMatrix();
+ glFlush();
+
+ WMesaViewport(Current->gl_ctx,0,0,Current->width,Current->height);
+// Current->gl_ctx->NewState = 0;
+ WMesaSwapBuffers();
+
+}
+
+void toggleStereoMode()
+{
+ if(!Current->db_flag)
+ return;
+ if(!stereo_flag){
+ stereo_flag = 1;
+ if(stereoBuffer==GL_FALSE)
+#if !defined(NO_PARALLEL)
+ if(!parallelFlag)
+#endif
+ {
+ Current->ScanWidth = Current->pitch*2;
+ }
+ }
+ else {
+ stereo_flag = 0;
+#if !defined(NO_PARALLEL)
+ if(!parallelFlag)
+#endif
+ Current->ScanWidth = Current->pitch;
+ Current->pbPixels = Current->addrOffScreen;
+ }
+}
+
+/* if in stereo mode, the following function is called */
+void glShowStereo(GLuint list)
+{
+ WMesaShowStereo(list);
+}
+
+#endif // End if NO_STEREO not defined
+
+#if !defined(NO_PARALLEL)
+
+void toggleParallelMode(void)
+{
+ if(!parallelFlag){
+ parallelFlag = GL_TRUE;
+ if(parallelMachine==GL_FALSE){
+ PRCreateRenderBuffer( Current->rgb_flag? GL_RGBA :GL_COLOR_INDEX,
+ Current->cColorBits/8,
+ Current->width ,Current->height,
+ Current->ScanWidth,
+ Current->rgb_flag? Current->pbPixels: Current->ScreenMem);
+ parallelMachine = GL_TRUE;
+ }
+ }
+ else {
+ parallelFlag = GL_FALSE;
+ if(parallelMachine==GL_TRUE){
+ PRDestroyRenderBuffer();
+ parallelMachine=GL_FALSE;
+ ReadyForNextFrame = GL_TRUE;
+ }
+
+/***********************************************
+// Seems something wrong!!!!
+************************************************/
+
+ WMesaMakeCurrent(Current);
+#if !defined(NO_STEREO)
+ stereo_flag = GL_FALSE ;
+#endif
+ }
+}
+
+void PRShowRenderResult(void)
+{
+ int flag = 0;
+if(!glImageRendered())
+ return;
+
+ if (parallelFlag)
+ {
+ WMesaSwapBuffers();
+ }
+
+}
+#endif //End if NO_PARALLEL not defined
+
+//end modification
+
+BYTE DITHER_RGB_2_8BIT( int red, int green, int blue, int pixel, int scanline)
+{
+ char unsigned redtemp, greentemp, bluetemp, paletteindex;
+
+ //*** now, look up each value in the halftone matrix
+ //*** using an 8x8 ordered dither.
+ redtemp = aDividedBy51[red]
+ + (aModulo51[red] > aHalftone8x8[(pixel%8)*8
+ + scanline%8]);
+ greentemp = aDividedBy51[(char unsigned)green]
+ + (aModulo51[green] > aHalftone8x8[
+ (pixel%8)*8 + scanline%8]);
+ bluetemp = aDividedBy51[(char unsigned)blue]
+ + (aModulo51[blue] > aHalftone8x8[
+ (pixel%8)*8 +scanline%8]);
+
+ //*** recombine the halftoned rgb values into a palette index
+ paletteindex =
+ redtemp + aTimes6[greentemp] + aTimes36[bluetemp];
+
+ //*** and translate through the wing halftone palette
+ //*** translation vector to give the correct value.
+ return aWinGHalftoneTranslation[paletteindex];
+}
+
+#ifdef DDRAW
+/*
+ * restoreAll
+ *
+ * restore all lost objects
+ */
+HRESULT DDRestoreAll( WMesaContext wc )
+{
+ HRESULT ddrval;
+
+ ddrval = wc->lpDDSPrimary->lpVtbl->Restore(wc->lpDDSPrimary);
+ if( ddrval == DD_OK )
+ {
+ ddrval = wc->lpDDSOffScreen->lpVtbl->Restore(wc->lpDDSOffScreen);
+ }
+ return ddrval;
+
+} /* restoreAll */
+
+
+/*
+ * This function is called if the initialization function fails
+ */
+BOOL initFail( HWND hwnd, WMesaContext wc )
+{
+ DDFree(wc);
+ MessageBox( hwnd, "DirectDraw Init FAILED", "", MB_OK );
+ return FALSE;
+
+} /* initFail */
+
+
+static void DDDeleteOffScreen(WMesaContext wc)
+{
+ if( wc->lpDDSOffScreen != NULL )
+ {
+ wc->lpDDSOffScreen->lpVtbl->Unlock(wc->lpDDSOffScreen,NULL);
+ wc->lpDDSOffScreen->lpVtbl->Release(wc->lpDDSOffScreen);
+ wc->lpDDSOffScreen = NULL;
+ }
+
+}
+
+static void DDFreePrimarySurface(WMesaContext wc)
+{
+ if( wc->lpDDSPrimary != NULL )
+ {
+ if(wc->db_flag == GL_FALSE)
+ wc->lpDDSPrimary->lpVtbl->ReleaseDC(wc->lpDDSPrimary, wc->hDC);
+ wc->lpDDSPrimary->lpVtbl->Release(wc->lpDDSPrimary);
+ wc->lpDDSPrimary = NULL;
+ }
+}
+
+static BOOL DDCreatePrimarySurface(WMesaContext wc)
+{
+ HRESULT ddrval;
+ DDSCAPS ddscaps;
+ wc->ddsd.dwSize = sizeof( wc->ddsd );
+ wc->ddsd.dwFlags = DDSD_CAPS;
+ wc->ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+
+ ddrval = wc->lpDD->lpVtbl->CreateSurface( wc->lpDD,&(wc->ddsd), &(wc->lpDDSPrimary), NULL );
+ if( ddrval != DD_OK )
+ {
+ return initFail(wc->hwnd , wc);
+ }
+ if(wc->db_flag == GL_FALSE)
+ wc->lpDDSPrimary->lpVtbl->GetDC(wc->lpDDSPrimary, wc->hDC);
+ return TRUE;
+}
+
+static BOOL DDCreateOffScreen(WMesaContext wc)
+{
+ POINT pt;
+ HRESULT ddrval;
+ if(wc->lpDD == NULL)
+ return FALSE;
+ GetClientRect( wc->hwnd, &(wc->rectOffScreen) );
+ wc->ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
+ wc->ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
+ wc->ddsd.dwHeight = wc->rectOffScreen.bottom - wc->rectOffScreen.top;
+ wc->ddsd.dwWidth = wc->rectOffScreen.right - wc->rectOffScreen.left;
+
+ ddrval = wc->lpDD->lpVtbl->CreateSurface( wc->lpDD, &(wc->ddsd), &(wc->lpDDSOffScreen), NULL );
+ if( ddrval != DD_OK )
+ {
+ return FALSE;
+ }
+
+ while (wc->lpDDSOffScreen->lpVtbl->Lock(wc->lpDDSOffScreen,NULL, &(wc->ddsd), 0, NULL) == DDERR_WASSTILLDRAWING)
+ ;
+// while ((ddrval = wc->lpDDSOffScreen->lpVtbl->Lock(wc->lpDDSOffScreen,NULL, &(wc->ddsd), DDLOCK_SURFACEMEMORYPTR , NULL)) != DD_OK)
+ ;
+ if(wc->ddsd.lpSurface==NULL)
+ return initFail(wc->hwnd, wc);
+
+ wc->ScreenMem = wc->pbPixels = wc->addrOffScreen = (PBYTE)(wc->ddsd.lpSurface);
+ wc->ScanWidth = wc->pitch = wc->ddsd.lPitch;
+ if (stereo_flag)
+ wc->ScanWidth = wc->ddsd.lPitch*2;
+
+ GetClientRect( wc->hwnd, &(wc->rectSurface) );
+ pt.x = pt.y = 0;
+ ClientToScreen( wc->hwnd, &pt );
+ OffsetRect(&(wc->rectSurface), pt.x, pt.y);
+ wmSetPixelFormat(wc, wc->hDC);
+ return TRUE;
+}
+
+/*
+ * doInit - do work required for every instance of the application:
+ * create the window, initialize data
+ */
+static BOOL DDInit( WMesaContext wc, HWND hwnd)
+{
+ HRESULT ddrval;
+ DWORD dwFrequency;
+
+ LPDIRECTDRAW lpDD; // DirectDraw object
+ LPDIRECTDRAW2 lpDD2;
+
+
+ wc->fullScreen = displayOptions.fullScreen;
+ wc->gMode = displayOptions.mode;
+ wc->hwnd = hwnd;
+ stereo_flag = displayOptions.stereo;
+ if(wc->db_flag!= GL_TRUE)
+ stereo_flag = GL_FALSE;
+ /*
+ * create the main DirectDraw object
+ */
+ ddrval = DirectDrawCreate( NULL, &(wc->lpDD), NULL );
+ if( ddrval != DD_OK )
+ {
+ return initFail(hwnd,wc);
+ }
+
+ // Get exclusive mode if requested
+ if(wc->fullScreen)
+ {
+ ddrval = wc->lpDD->lpVtbl->SetCooperativeLevel( wc->lpDD, hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
+ }
+ else
+ {
+ ddrval = wc->lpDD->lpVtbl->SetCooperativeLevel( wc->lpDD, hwnd, DDSCL_NORMAL );
+ }
+ if( ddrval != DD_OK )
+ {
+ return initFail(hwnd , wc);
+ }
+
+
+/* ddrval = wc->lpDD->lpVtbl->QueryInterface(wc->lpDD, IID_IDirectDraw2,
+ (LPVOID *)((wc->lpDD2)));
+
+*/
+ if(ddrval != DD_OK)
+ return initFail(hwnd , wc);
+
+
+ //ddrval = wc->lpDD->lpVtbl->GetDisplayMode( wc->lpDD, &(wc->ddsd));
+ // wc->lpDD2->lpVtbl->GetMonitorFrequency(wc->lpDD, &dwFrequency);
+ switch( wc->gMode )
+ {
+ case 1: ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 640, 480, displayOptions.bpp); break;
+ case 2: ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 800, 600, displayOptions.bpp); break;
+ case 3: ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 1024, 768, displayOptions.bpp); break;
+ case 4: ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 1152, 864, displayOptions.bpp); break;
+ case 5: ddrval = wc->lpDD->lpVtbl->SetDisplayMode( wc->lpDD, 1280, 1024, displayOptions.bpp); break;
+ }
+
+ if( ddrval != DD_OK )
+ {
+ printf("Can't modify display mode, current mode used\n");
+// return initFail(hwnd , wc);
+ }
+//ddrval = wc->lpDD->lpVtbl->GetDisplayMode( wc->lpDD, &(wc->ddsd));
+switch(ddrval){
+case DDERR_INVALIDOBJECT:
+ break;
+case DDERR_INVALIDPARAMS:
+ break;
+case DDERR_UNSUPPORTEDMODE:
+ ;
+}
+
+ if(DDCreatePrimarySurface(wc) == GL_FALSE)
+ return initFail(hwnd, wc);
+
+ if(wc->db_flag)
+ return DDCreateOffScreen(wc);
+} /* DDInit */
+
+static void DDFree( WMesaContext wc)
+{
+ if( wc->lpDD != NULL )
+ {
+ DDFreePrimarySurface(wc);
+ DDDeleteOffScreen(wc);
+ wc->lpDD->lpVtbl->Release(wc->lpDD);
+ wc->lpDD = NULL;
+ }
+ // Clean up the screen on exit
+ RedrawWindow( NULL, NULL, NULL, RDW_INVALIDATE | RDW_ERASE |
+ RDW_ALLCHILDREN );
+
+}
+#endif
+
+void WMesaMove(void)
+{
+ WMesaContext wc = Current;
+ POINT pt;
+ if (Current != NULL){
+ GetClientRect( wc->hwnd, &(wc->rectSurface) );
+ pt.x = pt.y = 0;
+ ClientToScreen( wc->hwnd, &pt );
+ OffsetRect(&(wc->rectSurface), pt.x, pt.y);
+ }
+}
+
+/*
+ * Like PACK_8A8B8G8R() but don't use alpha. This is usually an acceptable
+ * shortcut.
+ */
+#define PACK_8B8G8R( R, G, B ) ( ((B) << 16) | ((G) << 8) | (R) )
+
+
+/**********************************************************************/
+/*** Triangle rendering ***/
+/**********************************************************************/
+
+
+
+/*
+ * XImage, smooth, depth-buffered, PF_8A8B8G8R triangle.
+ */
+static void smooth_8A8B8G8R_z_triangle( GLcontext *ctx,
+ GLuint v0, GLuint v1, GLuint v2,
+ GLuint pv )
+{
+WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+//#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+{ \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = PACK_8B8G8R( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb) ); \
+ zRow[i] = z; \
+ } \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ ffz += fdzdx; \
+ } \
+}
+#include "tritemp.h"
+}
+
+
+/*
+ * XImage, smooth, depth-buffered, PF_8R8G8B triangle.
+ */
+static void smooth_8R8G8B_z_triangle( GLcontext *ctx,
+ GLuint v0, GLuint v1, GLuint v2,
+ GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+//#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+{ \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = PACK_8R8G8B( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb) ); \
+ zRow[i] = z; \
+ } \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ ffz += fdzdx; \
+ } \
+}
+#include "tritemp.h"
+}
+
+
+
+/*
+ * XImage, smooth, depth-buffered, PF_5R6G5B triangle.
+ */
+static void smooth_5R6G5B_z_triangle( GLcontext *ctx,
+ GLuint v0, GLuint v1, GLuint v2,
+ GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y)
+#define PIXEL_TYPE GLushort
+//#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+{ \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = PACK_5R6G5B( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb) ); \
+ zRow[i] = z; \
+ } \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ ffz += fdzdx; \
+ } \
+}
+#include "tritemp.h"
+}
+
+/*
+ * XImage, flat, depth-buffered, PF_8A8B8G8R triangle.
+ */
+static void flat_8A8B8G8R_z_triangle( GLcontext *ctx, GLuint v0,
+ GLuint v1, GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+//#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ unsigned long p = PACK_8B8G8R( VB->Color[pv][0], \
+ VB->Color[pv][1], VB->Color[pv][2] );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+{ \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = p; \
+ zRow[i] = z; \
+ } \
+ ffz += fdzdx; \
+ } \
+}
+#include "tritemp.h"
+}
+
+
+/*
+ * XImage, flat, depth-buffered, PF_8R8G8B triangle.
+ */
+static void flat_8R8G8B_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+//#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ unsigned long p = PACK_8R8G8B( VB->Color[pv][0], \
+ VB->Color[pv][1], VB->Color[pv][2] );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+{ \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = p; \
+ zRow[i] = z; \
+ } \
+ ffz += fdzdx; \
+ } \
+}
+#include "tritemp.h"
+}
+
+
+/*
+ * XImage, flat, depth-buffered, PF_5R6G5B triangle.
+ */
+static void flat_5R6G5B_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y)
+#define PIXEL_TYPE GLushort
+//#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ unsigned long p = PACK_5R6G5B( VB->Color[pv][0], \
+ VB->Color[pv][1], VB->Color[pv][2] );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+{ \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = p; \
+ zRow[i] = z; \
+ } \
+ ffz += fdzdx; \
+ } \
+}
+#include "tritemp.h"
+}
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, PF_8A8B8G8R triangle.
+ */
+static void smooth_8A8B8G8R_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+//#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+{ \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = PACK_8B8G8R( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb) ); \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ } \
+}
+#include "tritemp.h"
+}
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, PF_8R8G8B triangle.
+ */
+static void smooth_8R8G8B_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+//#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+{ \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = PACK_8R8G8B( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb) ); \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ } \
+}
+#include "tritemp.h"
+}
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, PF_5R6G5B triangle.
+ */
+static void smooth_5R6G5B_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y)
+#define PIXEL_TYPE GLushort
+//#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+{ \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = PACK_5R6G5B( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb) ); \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ } \
+}
+#include "tritemp.h"
+}
+
+
+
+/*
+ * XImage, flat, NON-depth-buffered, PF_8A8B8G8R triangle.
+ */
+static void flat_8A8B8G8R_triangle( GLcontext *ctx, GLuint v0,
+ GLuint v1, GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+//#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ unsigned long p = PACK_8B8G8R( VB->Color[pv][0], \
+ VB->Color[pv][1], VB->Color[pv][2] );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+{ \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = p; \
+ } \
+}
+#include "tritemp.h"
+}
+
+
+/*
+ * XImage, flat, NON-depth-buffered, PF_8R8G8B triangle.
+ */
+static void flat_8R8G8B_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define PIXEL_ADDRESS(X,Y) PIXELADDR4(X,Y)
+#define PIXEL_TYPE GLuint
+//#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ unsigned long p = PACK_8R8G8B( VB->Color[pv][0], \
+ VB->Color[pv][1], VB->Color[pv][2] );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+{ \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = p; \
+ } \
+}
+#include "tritemp.h"
+}
+
+
+/*
+ * XImage, flat, NON-depth-buffered, PF_5R6G5B triangle.
+ */
+static void flat_5R6G5B_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define PIXEL_ADDRESS(X,Y) PIXELADDR2(X,Y)
+#define PIXEL_TYPE GLushort
+//#define BYTES_PER_ROW (wmesa->xm_buffer->backimage->bytes_per_line)
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ unsigned long p = PACK_5R6G5B( VB->Color[pv][0], \
+ VB->Color[pv][1], VB->Color[pv][2] );
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+{ \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = p; \
+ } \
+}
+#include "tritemp.h"
+}
+
+
+/*
+ * XImage, smooth, depth-buffered, 8-bit PF_LOOKUP triangle.
+ */
+
+static void smooth_ci_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define INTERP_INDEX 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+{ \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = FixedToInt(ffi); \
+ zRow[i] = z; \
+ } \
+ ffi += fdidx; \
+ ffz += fdzdx; \
+ } \
+}
+
+#include "tritemp.h"
+}
+
+
+/*
+ * XImage, flat, depth-buffered, 8-bit PF_LOOKUP triangle.
+ */
+
+static void flat_ci_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ GLuint index = VB->Index[pv]; \
+ if (!VB->MonoColor) { \
+ /* set the color index */ \
+ (*ctx->Driver.Index)( ctx, index ); \
+ }
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+{ \
+ GLint i, len = RIGHT-LEFT; \
+ for (i=0;i<len;i++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ pRow[i] = index; \
+ zRow[i] = z; \
+ } \
+ ffz += fdzdx; \
+ } \
+}
+#include "tritemp.h"
+}
+
+
+
+/*
+ * XImage, smooth, NON-depth-buffered, 8-bit PF_LOOKUP triangle.
+ */
+
+static void smooth_ci_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define INTERP_INDEX 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+{ \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = FixedToInt(ffi); \
+ ffi += fdidx; \
+ } \
+}
+#include "tritemp.h"
+}
+
+
+/*
+ * XImage, flat, NON-depth-buffered, 8-bit PF_LOOKUP triangle.
+ */
+static void flat_ci_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+#define INTERP_Z 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define SETUP_CODE \
+ GLuint index = VB->Index[pv]; \
+ if (!VB->MonoColor) { \
+ /* set the color index */ \
+ (*ctx->Driver.Index)( ctx, index ); \
+ }
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+{ \
+ GLint xx; \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ *pixel = index; \
+ } \
+}
+#include "tritemp.h"
+}
+
+/*
+ * XImage, smooth, depth-buffered, 8-bit, PF_DITHER8 triangle.
+ */
+static void smooth_DITHER8_z_triangle( GLcontext *ctx,
+ GLuint v0, GLuint v1, GLuint v2,
+ GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+ DITHER_RGB_TO_8BIT_SETUP
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+{ \
+ GLint i, xx = LEFT, yy = FLIP(Y), len = RIGHT-LEFT; \
+ for (i=0;i<len;i++,xx++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ DITHER_RGB_TO_8BIT( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb), xx, yy); \
+ pRow[i] = pixelDithered; \
+ zRow[i] = z; \
+ } \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ ffz += fdzdx; \
+ } \
+}
+#include "tritemp.h"
+}
+
+/*
+ * XImage, flat, depth-buffered, 8-bit PF_DITHER triangle.
+ */
+static void flat_DITHER8_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+ DITHER_RGB_TO_8BIT_SETUP
+#define INTERP_Z 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+{ \
+ GLint i, xx = LEFT, yy = FLIP(Y), len = RIGHT-LEFT; \
+ for (i=0;i<len;i++,xx++) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ DITHER_RGB_TO_8BIT( VB->Color[pv][0], \
+ VB->Color[pv][1], VB->Color[pv][2], xx, yy); \
+ pRow[i] = pixelDithered; \
+ zRow[i] = z; \
+ } \
+ ffz += fdzdx; \
+ } \
+}
+#include "tritemp.h"
+}
+
+/*
+ * XImage, smooth, NON-depth-buffered, 8-bit PF_DITHER triangle.
+ */
+static void smooth_DITHER8_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+ DITHER_RGB_TO_8BIT_SETUP
+#define INTERP_RGB 1
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+{ \
+ GLint xx, yy = FLIP(Y); \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ DITHER_RGB_TO_8BIT( VB->Color[pv][0], VB->Color[pv][1], VB->Color[pv][2], xx, yy);\
+ *pixel = pixelDithered; \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; \
+ } \
+}
+#include "tritemp.h"
+}
+
+/*
+ * XImage, flat, NON-depth-buffered, 8-bit PF_DITHER triangle.
+ */
+
+static void flat_DITHER8_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+ DITHER_RGB_TO_8BIT_SETUP
+#define PIXEL_ADDRESS(X,Y) PIXELADDR1(X,Y)
+#define PIXEL_TYPE GLubyte
+#define BYTES_PER_ROW (wmesa->ScanWidth)
+
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+{ \
+ GLint xx, yy = FLIP(Y); \
+ PIXEL_TYPE *pixel = pRow; \
+ for (xx=LEFT;xx<RIGHT;xx++,pixel++) { \
+ DITHER_RGB_TO_8BIT( VB->Color[pv][0], \
+ VB->Color[pv][1], VB->Color[pv][2], xx, yy); \
+ *pixel = pixelDithered; \
+ } \
+}
+#include "tritemp.h"
+}
+
+
+
+
+static triangle_func choose_triangle_function( GLcontext *ctx )
+{
+ WMesaContext wmesa = (WMesaContext) ctx->DriverCtx;
+ int depth = wmesa->cColorBits;
+
+ if (ctx->Polygon.SmoothFlag) return NULL;
+ if (ctx->Texture.Enabled) return NULL;
+ if (!wmesa->db_flag) return NULL;
+ /*if (wmesa->xm_buffer->buffer==XIMAGE)*/ {
+ if ( ctx->Light.ShadeModel==GL_SMOOTH
+ && ctx->RasterMask==DEPTH_BIT
+ && ctx->Depth.Func==GL_LESS
+ && ctx->Depth.Mask==GL_TRUE
+ && ctx->Polygon.StippleFlag==GL_FALSE) {
+ switch (wmesa->pixelformat) {
+ case PF_8A8B8G8R:
+ return smooth_8A8B8G8R_z_triangle;
+ case PF_8R8G8B:
+ return smooth_8R8G8B_z_triangle;
+ case PF_5R6G5B:
+ return smooth_5R6G5B_z_triangle;
+ case PF_DITHER8:
+ return smooth_DITHER8_z_triangle;
+ case PF_INDEX8:
+ return smooth_ci_z_triangle;
+ default:
+ return NULL;
+ }
+ }
+ if ( ctx->Light.ShadeModel==GL_FLAT
+ && ctx->RasterMask==DEPTH_BIT
+ && ctx->Depth.Func==GL_LESS
+ && ctx->Depth.Mask==GL_TRUE
+ && ctx->Polygon.StippleFlag==GL_FALSE) {
+ switch (wmesa->pixelformat) {
+ case PF_8A8B8G8R:
+ return flat_8A8B8G8R_z_triangle;
+ case PF_8R8G8B:
+ return flat_8R8G8B_z_triangle;
+ case PF_5R6G5B:
+ return flat_5R6G5B_z_triangle;
+ case PF_DITHER8:
+ return flat_DITHER8_z_triangle;
+ case PF_INDEX8:
+ return flat_ci_z_triangle;
+ default:
+ return NULL;
+ }
+ }
+ if ( ctx->RasterMask==0 /* no depth test */
+ && ctx->Light.ShadeModel==GL_SMOOTH
+ && ctx->Polygon.StippleFlag==GL_FALSE) {
+ switch (wmesa->pixelformat) {
+ case PF_8A8B8G8R:
+ return smooth_8A8B8G8R_triangle;
+ case PF_8R8G8B:
+ return smooth_8R8G8B_triangle;
+ case PF_5R6G5B:
+ return smooth_5R6G5B_triangle;
+ case PF_DITHER8:
+ return smooth_DITHER8_triangle;
+ case PF_INDEX8:
+ return smooth_ci_triangle;
+ default:
+ return NULL;
+ }
+ }
+
+ if ( ctx->RasterMask==0 /* no depth test */
+ && ctx->Light.ShadeModel==GL_FLAT
+ && ctx->Polygon.StippleFlag==GL_FALSE) {
+ switch (wmesa->pixelformat) {
+ case PF_8A8B8G8R:
+ return flat_8A8B8G8R_triangle;
+ case PF_8R8G8B:
+ return flat_8R8G8B_triangle;
+ case PF_5R6G5B:
+ return flat_5R6G5B_triangle;
+ case PF_DITHER8:
+ return flat_DITHER8_triangle;
+ case PF_INDEX8:
+ return flat_ci_triangle;
+ default:
+ return NULL;
+ }
+ }
+
+ return NULL;
+ }
+}
+
+/*
+ * Define a new viewport and reallocate auxillary buffers if the size of
+ * the window (color buffer) has changed.
+ */
+void WMesaViewport( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height )
+{
+ /* Save viewport */
+ ctx->Viewport.X = x;
+ ctx->Viewport.Width = width;
+ ctx->Viewport.Y = y;
+ ctx->Viewport.Height = height;
+
+ /* compute scale and bias values */
+ ctx->Viewport.Sx = (GLfloat) width / 2.0F;
+ ctx->Viewport.Tx = ctx->Viewport.Sx + x;
+ ctx->Viewport.Sy = (GLfloat) height / 2.0F;
+ ctx->Viewport.Ty = ctx->Viewport.Sy + y;
+}
diff --git a/src/mesa/drivers/windows/wmesa_stereo.c b/src/mesa/drivers/windows/wmesa_stereo.c
new file mode 100644
index 0000000000..ea721a13b6
--- /dev/null
+++ b/src/mesa/drivers/windows/wmesa_stereo.c
@@ -0,0 +1,1872 @@
+/*
+ WMesa_stereo.c
+*/
+// Stereo display feature added by Li Wei
+// Updated 1996/10/06 11:16:15 CST
+// Paralell render feature added by Li Wei
+// liwei@aiar.xjtu.edu.cn
+// http://sun.aiar.xjtu.edu.cn
+
+#define WMESA_STEREO_C
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wmesadef.h>
+
+#include <GL\wmesa.h>
+#include "context.h"
+#include "dd.h"
+#include "xform.h"
+#include "vb.h"
+#include "matrix.h"
+#include "depth.h"
+
+#ifdef PROFILE
+ #include "profile.h"
+#endif
+
+#include <wing.h>
+
+// Code added by Li Wei to enable stereo display and Paralell render
+
+
+/*#include "mesa_extend.h"*/
+
+#if !defined(NO_STEREO)
+
+ #include "gl\glu.h"
+ #include "stereo.h"
+
+ PBYTE Buffer_Stereo;
+
+ void WMesaCreateStereoBuffer(void);
+
+ void WMesaInterleave( GLenum aView);
+
+ void WMesaDestroyStereoBuffer(void);
+
+ void WMesaShowStereo(GLuint list);
+#endif
+#if !defined(NO_PARALLEL)
+ #include "parallel.h"
+#endif
+
+/* end of added code*/
+
+/* Bit's used for dest: */
+#define FRONT_PIXMAP 1
+#define BACK_PIXMAP 2
+#define BACK_XIMAGE 4
+
+static PWMC Current = NULL;
+WMesaContext WC = NULL;
+
+#ifdef NDEBUG
+ #define assert(ignore) ((void) 0)
+#else
+ void Mesa_Assert(void *Cond,void *File,unsigned Line)
+ {
+ char Msg[512];
+ sprintf(Msg,"%s %s %d",Cond,File,Line);
+ MessageBox(NULL,Msg,"Assertion failed.",MB_OK);
+ exit(1);
+ }
+ #define assert(e) if (!e) Mesa_Assert(#e,__FILE__,__LINE__);
+#endif
+
+#define DD_GETDC ((Current->db_flag) ? Current->dib.hDC : Current->hDC )
+#define DD_RELEASEDC
+
+//#define BEGINGDICALL if(Current->rgb_flag)wmFlushBits(Current);
+#define BEGINGDICALL
+//#define ENDGDICALL if(Current->rgb_flag)wmGetBits(Current);
+#define ENDGDICALL
+
+#define FLIP(Y) (Current->height-(Y)-1)
+
+#define STARTPROFILE
+#define ENDPROFILE(PARA)
+
+static void FlushToFile(PWMC pwc, PSTR szFile);
+
+BOOL wmCreateBackingStore(PWMC pwc, long lxSize, long lySize);
+
+BOOL wmDeleteBackingStore(PWMC pwc);
+
+void wmCreatePalette( PWMC pwdc );
+BOOL wmSetDibColors(PWMC pwc);
+void wmSetPixel(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b);
+
+void wmCreateDIBSection(
+ HDC hDC,
+ PWMC pwc, // handle of device context
+ CONST BITMAPINFO *pbmi, // address of structure containing bitmap size, format, and color data
+ UINT iUsage // color data type indicator: RGB values or palette indices
+ );
+
+BOOL wmFlush(PWMC pwc);
+
+/*
+ * Useful macros:
+ Modified from file osmesa.c
+ */
+
+#define PIXELADDR(X,Y) ((GLbyte *)Current->pbPixels + (Current->height-Y)* Current->ScanWidth + (X)*nBypp)
+
+
+/* Finish all pending operations and synchronize. */
+static void finish(GLcontext* ctx)
+{
+ /* no op */
+}
+
+
+//
+// We cache all gl draw routines until a flush is made
+//
+static void flush(GLcontext* ctx)
+{
+ STARTPROFILE
+ if(Current->rgb_flag && !(Current->dib.fFlushed)&&!(Current->db_flag)){
+ wmFlush(Current);
+ }
+ ENDPROFILE(flush)
+
+}
+
+
+
+/*
+ * Set the color index used to clear the color buffer.
+ */
+static void clear_index(GLcontext* ctx, GLuint index)
+{
+ STARTPROFILE
+ Current->clearpixel = index;
+ ENDPROFILE(clear_index)
+}
+
+
+
+/*
+ * Set the color used to clear the color buffer.
+ */
+static void clear_color( GLcontext* ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+ STARTPROFILE
+ Current->clearpixel=RGB(r, g, b );
+ ENDPROFILE(clear_color)
+}
+
+
+
+/*
+ * Clear the specified region of the color buffer using the clear color
+ * or index as specified by one of the two functions above.
+ */
+static void clear(GLcontext* ctx,
+ GLboolean all,GLint x, GLint y, GLint width, GLint height )
+{
+ DWORD dwColor;
+ WORD wColor;
+ LPDWORD lpdw = (LPDWORD)Current->pbPixels;
+ LPWORD lpw = (LPWORD)Current->pbPixels;
+ LPBYTE lpb = Current->pbPixels;
+
+ STARTPROFILE
+
+ if (all){
+ x=y=0;
+ width=Current->width;
+ height=Current->height;
+ }
+ if (Current->rgb_flag==GL_TRUE){
+ if(Current->db_flag==GL_TRUE){
+ UINT nBypp = Current->cColorBits / 8;
+ int i = 0;
+ int iSize;
+
+ if(nBypp == 2){
+ iSize = (Current->width * Current->height) / nBypp;
+
+ wColor = BGR16(GetRValue(Current->clearpixel),
+ GetGValue(Current->clearpixel),
+ GetBValue(Current->clearpixel));
+ dwColor = MAKELONG(wColor, wColor);
+ }
+ else if(nBypp == 4){
+ iSize = (Current->width * Current->height);
+
+ dwColor = BGR32(GetRValue(Current->clearpixel),
+ GetGValue(Current->clearpixel),
+ GetBValue(Current->clearpixel));
+ }
+ //
+ // This is the 24bit case
+ //
+ else {
+
+ iSize = (Current->width * Current->height) / nBypp;
+
+ dwColor = BGR24(GetRValue(Current->clearpixel),
+ GetGValue(Current->clearpixel),
+ GetBValue(Current->clearpixel));
+
+
+ while(i < iSize){
+ *lpdw = dwColor;
+ lpb += nBypp;
+ lpdw = (LPDWORD)lpb;
+ i++;
+ }
+
+ // ENDPROFILE(clear)
+
+ return;
+ }
+
+ while(i < iSize){
+ *lpdw = dwColor;
+ lpdw++;
+ i++;
+ }
+ }
+ else{ // For single buffer
+ HDC DC=DD_GETDC;
+ HPEN Pen=CreatePen(PS_SOLID,1,Current->clearpixel);
+ HBRUSH Brush=CreateSolidBrush(Current->clearpixel);
+ HPEN Old_Pen=SelectObject(DC,Pen);
+ HBRUSH Old_Brush=SelectObject(DC,Brush);
+ Rectangle(DC,x,y,x+width,y+height);
+ SelectObject(DC,Old_Pen);
+ SelectObject(DC,Old_Brush);
+ DeleteObject(Pen);
+ DeleteObject(Brush);
+ DD_RELEASEDC;
+ }
+ }
+ else {
+ int i;
+ char *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
+ for (i=0; i<height; i++){
+ memset(Mem,Current->clearpixel,width);
+ Mem+=width;
+ }
+ }
+ ENDPROFILE(clear)
+}
+
+
+
+/* Set the current color index. */
+static void set_index(GLcontext* ctx, GLuint index)
+{
+ STARTPROFILE
+ Current->pixel=index;
+ ENDPROFILE(set_index)
+}
+
+
+
+/* Set the current RGBA color. */
+static void set_color( GLcontext* ctx, GLubyte r, GLubyte g, GLubyte b, GLubyte a )
+{
+ STARTPROFILE
+ Current->pixel = RGB( r, g, b );
+ ENDPROFILE(set_color)
+}
+
+
+
+/* Set the index mode bitplane mask. */
+static GLboolean index_mask(GLcontext* ctx, GLuint mask)
+{
+ /* can't implement */
+ return GL_FALSE;
+}
+
+
+
+/* Set the RGBA drawing mask. */
+static GLboolean color_mask( GLcontext* ctx,
+ GLboolean rmask, GLboolean gmask,
+ GLboolean bmask, GLboolean amask)
+{
+ /* can't implement */
+ return GL_FALSE;
+}
+
+
+
+/*
+ * Set the pixel logic operation. Return GL_TRUE if the device driver
+ * can perform the operation, otherwise return GL_FALSE. If GL_FALSE
+ * is returned, the logic op will be done in software by Mesa.
+ */
+GLboolean logicop( GLcontext* ctx, GLenum op )
+{
+ /* can't implement */
+ return GL_FALSE;
+}
+
+
+static void dither( GLcontext* ctx, GLboolean enable )
+{
+ /* No op */
+}
+
+
+
+static GLboolean set_buffer( GLcontext* ctx, GLenum mode )
+{
+ STARTPROFILE
+ /* TODO: this could be better */
+ if (mode==GL_FRONT || mode==GL_BACK) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+ ENDPROFILE(set_buffer)
+}
+
+
+
+/* Return characteristics of the output buffer. */
+static void buffer_size( GLcontext* ctx, GLuint *width, GLuint *height /*, GLuint *depth */)
+{
+
+ int New_Size;
+ RECT CR;
+
+ STARTPROFILE
+ GetClientRect(Current->Window,&CR);
+
+ *width=CR.right;
+ *height=CR.bottom;
+// *depth = Current->depth;
+
+ New_Size=((*width)!=Current->width) || ((*height)!=Current->height);
+
+ if (New_Size){
+ Current->width=*width;
+ Current->height=*height;
+ Current->ScanWidth=Current->width;
+ if ((Current->ScanWidth%sizeof(long))!=0)
+ Current->ScanWidth+=(sizeof(long)-(Current->ScanWidth%sizeof(long)));
+
+ if (Current->db_flag){
+ if (Current->rgb_flag==GL_TRUE){
+ wmDeleteBackingStore(Current);
+ wmCreateBackingStore(Current, Current->width, Current->height);
+ }
+ else{
+ Current->ScanWidth=Current->width;
+ if ((Current->ScanWidth%sizeof(long))!=0)
+ Current->ScanWidth+=(sizeof(long)-(Current->ScanWidth%sizeof(long)));
+
+ Current->IndexFormat->bmiHeader.biWidth=Current->width;
+
+ if (Current->IndexFormat->bmiHeader.biHeight<0)
+ Current->IndexFormat->bmiHeader.biHeight=-(Current->height);
+ else
+ Current->IndexFormat->bmiHeader.biHeight=Current->height;
+
+ Current->Compat_BM=WinGCreateBitmap(Current->dib.hDC,Current->IndexFormat,&((void *) Current->ScreenMem));
+
+ DeleteObject(SelectObject(Current->dib.hDC,Current->Compat_BM));
+ }
+//Code added by Li Wei to enable stereo display
+// Recreate stereo buffer when stereo_flag is TRUE while parallelFlag is FALSE
+#if !defined(NO_STEREO)
+ if(stereo_flag
+#if !defined(NO_PARALLEL)
+ &&!parallelFlag
+#endif
+ ) {
+ if(stereoBuffer == GL_TRUE)
+ WMesaDestroyStereoBuffer();
+ WMesaCreateStereoBuffer();
+ }
+#endif
+// Resize OsmesaBuffer if in Parallel mode
+#if !defined(NO_PARALLEL)
+ if(parallelFlag)
+ PRSizeRenderBuffer(Current->width, Current->height,Current->ScanWidth,
+ Current->rgb_flag == GL_TRUE ? Current->pbPixels: Current->ScreenMem);
+#endif
+//end modification
+
+ }
+ }
+
+ ENDPROFILE(buffer_size)
+}
+
+
+
+/**********************************************************************/
+/***** Accelerated point, line, polygon rendering *****/
+/**********************************************************************/
+
+
+static void fast_rgb_points( GLcontext* ctx, GLuint first, GLuint last )
+{
+ GLuint i;
+ // HDC DC=DD_GETDC;
+ PWMC pwc = Current;
+
+ STARTPROFILE
+
+ if (Current->gl_ctx->VB->MonoColor) {
+ /* all drawn with current color */
+ for (i=first;i<=last;i++) {
+ if (Current->gl_ctx->VB->ClipMask[i]==0) {
+ int x, y;
+ x = (GLint) Current->gl_ctx->VB->Win[i][0];
+ y = FLIP( (GLint) Current->gl_ctx->VB->Win[i][1] );
+ wmSetPixel(pwc, y,x,GetRValue(Current->pixel),
+ GetGValue(Current->pixel), GetBValue(Current->pixel));
+ }
+ }
+ }
+ else {
+ /* draw points of different colors */
+ for (i=first;i<=last;i++) {
+ if (Current->gl_ctx->VB->ClipMask[i]==0) {
+ int x, y;
+ unsigned long pixel=RGB(Current->gl_ctx->VB->Color[i][0]*255.0,
+ Current->gl_ctx->VB->Color[i][1]*255.0,
+ Current->gl_ctx->VB->Color[i][2]*255.0);
+ x = (GLint) Current->gl_ctx->VB->Win[i][0];
+ y = FLIP( (GLint) Current->gl_ctx->VB->Win[i][1] );
+ wmSetPixel(pwc, y,x,Current->gl_ctx->VB->Color[i][0]*255.0,
+ Current->gl_ctx->VB->Color[i][1]*255.0,
+ Current->gl_ctx->VB->Color[i][2]*255.0);
+ }
+ }
+ }
+// DD_RELEASEDC;
+ ENDPROFILE(fast_rgb_points)
+}
+
+
+
+/* Return pointer to accerated points function */
+extern points_func choose_points_function( GLcontext* ctx )
+{
+ STARTPROFILE
+ if (ctx->Point.Size==1.0 && !ctx->Point.SmoothFlag && ctx->RasterMask==0
+ && !ctx->Texture.Enabled && ctx->Visual->RGBAflag) {
+ ENDPROFILE(choose_points_function)
+ return fast_rgb_points;
+ }
+ else {
+ ENDPROFILE(choose_points_function)
+ return NULL;
+ }
+}
+
+
+
+/* Draw a line using the color specified by Current->gl_ctx->VB->Color[pv] */
+static void fast_flat_rgb_line( GLcontext* ctx, GLuint v0, GLuint v1, GLuint pv )
+{
+ STARTPROFILE
+ int x0, y0, x1, y1;
+ unsigned long pixel;
+ HDC DC=DD_GETDC;
+ HPEN Pen;
+ HPEN Old_Pen;
+
+ if (Current->gl_ctx->VB->MonoColor) {
+ pixel = Current->pixel; /* use current color */
+ }
+ else {
+ pixel = RGB(Current->gl_ctx->VB->Color[pv][0]*255.0, Current->gl_ctx->VB->Color[pv][1]*255.0, Current->gl_ctx->VB->Color[pv][2]*255.0);
+ }
+
+ x0 = (int) Current->gl_ctx->VB->Win[v0][0];
+ y0 = FLIP( (int) Current->gl_ctx->VB->Win[v0][1] );
+ x1 = (int) Current->gl_ctx->VB->Win[v1][0];
+ y1 = FLIP( (int) Current->gl_ctx->VB->Win[v1][1] );
+
+
+ BEGINGDICALL
+
+ Pen=CreatePen(PS_SOLID,1,pixel);
+ Old_Pen=SelectObject(DC,Pen);
+ MoveToEx(DC,x0,y0,NULL);
+ LineTo(DC,x1,y1);
+ SelectObject(DC,Old_Pen);
+ DeleteObject(Pen);
+ DD_RELEASEDC;
+
+ ENDGDICALL
+
+ ENDPROFILE(fast_flat_rgb_line)
+}
+
+
+
+/* Return pointer to accerated line function */
+static line_func choose_line_function( GLcontext* ctx )
+{
+ STARTPROFILE
+ if (ctx->Line.Width==1.0 && !ctx->Line.SmoothFlag && !ctx->Line.StippleFlag
+ && ctx->Light.ShadeModel==GL_FLAT && ctx->RasterMask==0
+ && !ctx->Texture.Enabled && Current->rgb_flag) {
+ ENDPROFILE(choose_line_function)
+ return fast_flat_rgb_line;
+ }
+ else {
+ ENDPROFILE(choose_line_function)
+ return NULL;
+ }
+}
+
+/**********************************************************************/
+/***** Optimized triangle rendering *****/
+/**********************************************************************/
+
+
+/*
+ * Smooth-shaded, z-less triangle, RGBA color.
+ */
+static void smooth_color_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+UINT nBypp = Current->cColorBits / 8;
+GLbyte* img;
+GLushort* img16;
+GLuint *img24 ,*img32;
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define INTERP_ALPHA 1
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+{ \
+ GLint i, len = RIGHT-LEFT; \
+ img = PIXELADDR(LEFT,Y); \
+ for (i=0;i<len;i++,img+=nBypp) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ img16 = img24 = img32 = img; \
+ if(nBypp == 2) \
+ *img16 = BGR16( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb)); \
+ if(nBypp == 3) \
+ *img24 = BGR24( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb)); \
+ if(nBypp == 4) \
+ *img32 = BGR32( FixedToInt(ffr), FixedToInt(ffg), \
+ FixedToInt(ffb)); \
+ zRow[i] = z; \
+ } \
+ ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; ffa += fdadx;\
+ ffz += fdzdx; \
+ } \
+}
+
+ #include "tritemp.h"
+ }
+
+
+
+
+/*
+ * Flat-shaded, z-less triangle, RGBA color.
+ */
+static void flat_color_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
+ GLuint v2, GLuint pv )
+{
+GLbyte* img;
+GLushort* img16;
+GLuint *img24, *img32;
+UINT nBypp = Current->cColorBits / 8;
+GLubyte r, g, b ;
+GLushort pixel16 = BGR16(r,g,b);
+GLuint pixel24 = BGR24(r,g,b);
+GLuint pixel32 = BGR32(r,g,b);
+
+#define INTERP_Z 1
+#define SETUP_CODE \
+ r = VB->Color[pv][0]; \
+ g = VB->Color[pv][1]; \
+ b = VB->Color[pv][2];
+
+#define INNER_LOOP( LEFT, RIGHT, Y ) \
+{ \
+ GLint i, len = RIGHT-LEFT; \
+ img = PIXELADDR(LEFT,Y); \
+ for (i=0;i<len;i++,img+=nBypp) { \
+ GLdepth z = FixedToDepth(ffz); \
+ if (z < zRow[i]) { \
+ img16 = img24 = img32 = img; \
+ if(nBypp == 2) \
+ *img16 = pixel16; \
+ if(nBypp == 3) \
+ *img24 = pixel24; \
+ if(nBypp == 4) \
+ *img32 = pixel32; \
+ zRow[i] = z; \
+ } \
+ ffz += fdzdx; \
+ } \
+}
+
+#include "tritemp.h"
+}
+
+
+
+/*
+ * Return pointer to an accelerated triangle function if possible.
+ */
+static triangle_func choose_triangle_function( GLcontext *ctx )
+{
+ if (ctx->Polygon.SmoothFlag) return NULL;
+ if (ctx->Polygon.StippleFlag) return NULL;
+ if (ctx->Texture.Enabled) return NULL;
+
+ if (ctx->RasterMask==DEPTH_BIT
+ && ctx->Depth.Func==GL_LESS
+ && ctx->Depth.Mask==GL_TRUE
+ && ctx->Visual->RGBAflag) {
+ if (ctx->Light.ShadeModel==GL_SMOOTH) {
+ return smooth_color_z_triangle;
+ }
+ else {
+ return flat_color_z_triangle;
+ }
+ }
+ return NULL;
+}
+
+
+/* Draw a convex polygon using color Current->gl_ctx->VB->Color[pv] */
+static void fast_flat_rgb_polygon( GLcontext* ctx, GLuint n, GLuint vlist[], GLuint pv )
+{
+ STARTPROFILE
+ POINT *Pts=(POINT *) malloc(n*sizeof(POINT));
+ HDC DC=DD_GETDC;
+ HPEN Pen;
+ HBRUSH Brush;
+ HPEN Old_Pen;
+ HBRUSH Old_Brush;
+ GLint pixel;
+ GLuint i;
+
+ if (Current->gl_ctx->VB->MonoColor) {
+ pixel = Current->pixel; /* use current color */
+ }
+ else {
+ pixel = RGB(Current->gl_ctx->VB->Color[pv][0]*255.0, Current->gl_ctx->VB->Color[pv][1]*255.0, Current->gl_ctx->VB->Color[pv][2]*255.0);
+ }
+
+ Pen=CreatePen(PS_SOLID,1,pixel);
+ Brush=CreateSolidBrush(pixel);
+ Old_Pen=SelectObject(DC,Pen);
+ Old_Brush=SelectObject(DC,Brush);
+
+ for (i=0; i<n; i++) {
+ int j = vlist[i];
+ Pts[i].x = (int) Current->gl_ctx->VB->Win[j][0];
+ Pts[i].y = FLIP( (int) Current->gl_ctx->VB->Win[j][1] );
+ }
+
+ BEGINGDICALL
+
+ Polygon(DC,Pts,n);
+ SelectObject(DC,Old_Pen);
+ SelectObject(DC,Old_Brush);
+ DeleteObject(Pen);
+ DeleteObject(Brush);
+ DD_RELEASEDC;
+ free(Pts);
+
+ ENDGDICALL
+
+ ENDPROFILE(fast_flat_rgb_polygon)
+}
+
+
+
+/* Return pointer to accerated polygon function */
+static polygon_func choose_polygon_function( GLcontext* ctx )
+{
+ STARTPROFILE
+ if (!ctx->Polygon.SmoothFlag && !ctx->Polygon.StippleFlag
+ && ctx->Light.ShadeModel==GL_FLAT && ctx->RasterMask==0
+ && !ctx->Texture.Enabled && Current->rgb_flag==GL_TRUE) {
+ ENDPROFILE(choose_polygon_function)
+ return fast_flat_rgb_polygon;
+ }
+ else {
+ ENDPROFILE(choose_polygon_function)
+ return NULL;
+ }
+}
+
+
+
+/**********************************************************************/
+/***** Span-based pixel drawing *****/
+/**********************************************************************/
+
+
+/* Write a horizontal span of color-index pixels with a boolean mask. */
+static void write_index_span( GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLuint index[],
+ const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ char *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i]=index[i];
+ ENDPROFILE(write_index_span)
+}
+
+
+
+/*
+ * Write a horizontal span of pixels with a boolean mask. The current
+ * color index is used for all pixels.
+ */
+static void write_monoindex_span(GLcontext* ctx,
+ GLuint n,GLint x,GLint y,
+ const GLubyte mask[])
+{
+ STARTPROFILE
+ GLuint i;
+ char *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i]=Current->pixel;
+ ENDPROFILE(write_monoindex_span)
+}
+
+/*
+ To improve the performance of this routine, frob the data into an actual scanline
+ and call bitblt on the complete scan line instead of SetPixel.
+*/
+
+/* Write a horizontal span of color pixels with a boolean mask. */
+static void write_color_span( GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte
+ red[], const GLubyte green[],
+ const GLubyte blue[], const GLubyte alpha[],
+ const GLubyte mask[] )
+{
+ STARTPROFILE
+
+ PWMC pwc = Current;
+
+ if (pwc->rgb_flag==GL_TRUE)
+ {
+ GLuint i;
+ HDC DC=DD_GETDC;
+ y=FLIP(y);
+
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, y, x + i,red[i], green[i], blue[i]);
+ }
+
+ else {
+ for (i=0; i<n; i++)
+ wmSetPixel(pwc, y, x + i, red[i], green[i], blue[i]);
+ }
+
+ DD_RELEASEDC;
+
+ }
+
+ else
+ {
+ GLuint i;
+ char *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
+ if (mask) {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ Mem[i]=GetNearestPaletteIndex(Current->hPal,RGB(red[i],green[i],blue[i]));
+ }
+ else {
+ for (i=0; i<n; i++)
+ Mem[i]=GetNearestPaletteIndex(Current->hPal,RGB(red[i],green[i],blue[i]));
+ }
+ }
+ ENDPROFILE(write_color_span)
+
+}
+
+/*
+ * Write a horizontal span of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_monocolor_span( GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLubyte mask[])
+{
+ STARTPROFILE
+ GLuint i;
+ HDC DC=DD_GETDC;
+ PWMC pwc = Current;
+
+ assert(Current->rgb_flag==GL_TRUE);
+ y=FLIP(y);
+
+ if(Current->rgb_flag==GL_TRUE){
+ for (i=0; i<n; i++)
+ if (mask[i])
+// Trying
+ wmSetPixel(pwc,y,x+i,GetRValue(Current->pixel), GetGValue(Current->pixel), GetBValue(Current->pixel));
+ }
+ else {
+ for (i=0; i<n; i++)
+ if (mask[i])
+ SetPixel(DC, y, x+i, Current->pixel);
+ }
+
+ DD_RELEASEDC;
+
+ ENDPROFILE(write_monocolor_span)
+}
+
+
+
+/**********************************************************************/
+/***** Array-based pixel drawing *****/
+/**********************************************************************/
+
+
+/* Write an array of pixels with a boolean mask. */
+static void write_index_pixels( GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLuint index[], const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ char *Mem=Current->ScreenMem+y[i]*Current->ScanWidth+x[i];
+ *Mem = index[i];
+ }
+ }
+ ENDPROFILE(write_index_pixels)
+}
+
+
+
+/*
+ * Write an array of pixels with a boolean mask. The current color
+ * index is used for all pixels.
+ */
+static void write_monoindex_pixels( GLcontext* ctx,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ char *Mem=Current->ScreenMem+y[i]*Current->ScanWidth+x[i];
+ *Mem = Current->pixel;
+ }
+ }
+ ENDPROFILE(write_monoindex_pixels)
+}
+
+
+
+/* Write an array of pixels with a boolean mask. */
+static void write_color_pixels( GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte r[], const GLubyte g[],
+ const GLubyte b[], const GLubyte a[],
+ const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ PWMC pwc = Current;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, FLIP(y[i]),x[i],r[i],g[i],b[i]);
+ DD_RELEASEDC;
+ ENDPROFILE(write_color_pixels)
+}
+
+
+
+/*
+ * Write an array of pixels with a boolean mask. The current color
+ * is used for all pixels.
+ */
+static void write_monocolor_pixels( GLcontext* ctx,
+ GLuint n,
+ const GLint x[], const GLint y[],
+ const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ PWMC pwc = Current;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ for (i=0; i<n; i++)
+ if (mask[i])
+ wmSetPixel(pwc, FLIP(y[i]),x[i],GetRValue(Current->pixel),
+ GetGValue(Current->pixel), GetBValue(Current->pixel));
+ DD_RELEASEDC;
+ ENDPROFILE(write_monocolor_pixels)
+}
+
+
+
+/**********************************************************************/
+/***** Read spans/arrays of pixels *****/
+/**********************************************************************/
+
+
+/* Read a horizontal span of color-index pixels. */
+static void read_index_span( GLcontext* ctx, GLuint n, GLint x, GLint y, GLuint index[])
+{
+ STARTPROFILE
+ GLuint i;
+ char *Mem=Current->ScreenMem+y*Current->ScanWidth+x;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++)
+ index[i]=Mem[i];
+ ENDPROFILE(read_index_span)
+
+}
+
+
+
+
+/* Read an array of color index pixels. */
+static void read_index_pixels( GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint indx[], const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ assert(Current->rgb_flag==GL_FALSE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ indx[i]=*(Current->ScreenMem+y[i]*Current->ScanWidth+x[i]);
+ }
+ }
+ ENDPROFILE(read_index_pixels)
+}
+
+
+
+/* Read a horizontal span of color pixels. */
+static void read_color_span( GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ GLubyte red[], GLubyte green[],
+ GLubyte blue[], GLubyte alpha[] )
+{
+ STARTPROFILE
+ UINT i;
+ COLORREF Color;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ y=FLIP(y);
+ for (i=0; i<n; i++)
+ {
+ Color=GetPixel(DC,x+i,y);
+ red[i]=GetRValue(Color);
+ green[i]=GetGValue(Color);
+ blue[i]=GetBValue(Color);
+ alpha[i]=255;
+ }
+ DD_RELEASEDC;
+ memset(alpha,0,n*sizeof(GLint));
+ ENDPROFILE(read_color_span)
+}
+
+
+/* Read an array of color pixels. */
+static void read_color_pixels( GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte red[], GLubyte green[],
+ GLubyte blue[], GLubyte alpha[],
+ const GLubyte mask[] )
+{
+ STARTPROFILE
+ GLuint i;
+ COLORREF Color;
+ HDC DC=DD_GETDC;
+ assert(Current->rgb_flag==GL_TRUE);
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ Color=GetPixel(DC,x[i],FLIP(y[i]));
+ red[i]=GetRValue(Color);
+ green[i]=GetGValue(Color);
+ blue[i]=GetBValue(Color);
+ alpha[i]=255;
+ }
+ }
+ DD_RELEASEDC;
+ memset(alpha,0,n*sizeof(GLint));
+ ENDPROFILE(read_color_pixels)
+}
+
+
+
+/**********************************************************************/
+/**********************************************************************/
+
+
+
+void setup_DD_pointers( GLcontext* ctx )
+{
+ ctx->Driver.Finish = finish;
+ ctx->Driver.Flush = flush;
+
+ ctx->Driver.ClearIndex = clear_index;
+ ctx->Driver.ClearColor = clear_color;
+ ctx->Driver.Clear = clear;
+
+ ctx->Driver.Index = set_index;
+ ctx->Driver.Color = set_color;
+ ctx->Driver.IndexMask = index_mask;
+ ctx->Driver.ColorMask = color_mask;
+
+ ctx->Driver.LogicOp = logicop;
+ ctx->Driver.Dither = dither;
+
+ ctx->Driver.SetBuffer = set_buffer;
+ ctx->Driver.GetBufferSize = buffer_size;
+
+ ctx->Driver.PointsFunc = choose_points_function(ctx);
+ ctx->Driver.LineFunc = choose_line_function(ctx);
+ ctx->Driver.TriangleFunc = choose_triangle_function( ctx );
+ // ctx->Driver.TriangleFunc = choose_polygon_function(ctx);
+
+ /* Pixel/span writing functions: */
+ ctx->Driver.WriteColorSpan = write_color_span;
+ ctx->Driver.WriteMonocolorSpan = write_monocolor_span;
+ ctx->Driver.WriteColorPixels = write_color_pixels;
+ ctx->Driver.WriteMonocolorPixels = write_monocolor_pixels;
+ ctx->Driver.WriteIndexSpan = write_index_span;
+ ctx->Driver.WriteMonoindexSpan = write_monoindex_span;
+ ctx->Driver.WriteIndexPixels = write_index_pixels;
+ ctx->Driver.WriteMonoindexPixels = write_monoindex_pixels;
+
+ /* Pixel/span reading functions: */
+ ctx->Driver.ReadIndexSpan = read_index_span;
+ ctx->Driver.ReadColorSpan = read_color_span;
+ ctx->Driver.ReadIndexPixels = read_index_pixels;
+ ctx->Driver.ReadColorPixels = read_color_pixels;
+}
+
+//
+// MesaGL32 is the DLL version of MesaGL for Win32
+//
+
+/**********************************************************************/
+/***** WMesa API Functions *****/
+/**********************************************************************/
+
+
+
+#define PAL_SIZE 256
+static void GetPalette(HPALETTE Pal,RGBQUAD *aRGB)
+{
+ STARTPROFILE
+ int i;
+ HDC hdc;
+ struct
+ {
+ WORD Version;
+ WORD NumberOfEntries;
+ PALETTEENTRY aEntries[PAL_SIZE];
+ } Palette =
+ {
+ 0x300,
+ PAL_SIZE
+ };
+ hdc=GetDC(NULL);
+ if (Pal!=NULL)
+ GetPaletteEntries(Pal,0,PAL_SIZE,Palette.aEntries);
+ else
+ GetSystemPaletteEntries(hdc,0,PAL_SIZE,Palette.aEntries);
+ if (GetSystemPaletteUse(hdc) == SYSPAL_NOSTATIC)
+ {
+ for(i = 0; i <PAL_SIZE; i++)
+ Palette.aEntries[i].peFlags = PC_RESERVED;
+ Palette.aEntries[255].peRed = 255;
+ Palette.aEntries[255].peGreen = 255;
+ Palette.aEntries[255].peBlue = 255;
+ Palette.aEntries[255].peFlags = 0;
+ Palette.aEntries[0].peRed = 0;
+ Palette.aEntries[0].peGreen = 0;
+ Palette.aEntries[0].peBlue = 0;
+ Palette.aEntries[0].peFlags = 0;
+ }
+ else
+ {
+ int nStaticColors;
+ int nUsableColors;
+ nStaticColors = GetDeviceCaps(hdc, NUMCOLORS)/2;
+ for (i=0; i<nStaticColors; i++)
+ Palette.aEntries[i].peFlags = 0;
+ nUsableColors = PAL_SIZE-nStaticColors;
+ for (; i<nUsableColors; i++)
+ Palette.aEntries[i].peFlags = PC_RESERVED;
+ for (; i<PAL_SIZE-nStaticColors; i++)
+ Palette.aEntries[i].peFlags = PC_RESERVED;
+ for (i=PAL_SIZE-nStaticColors; i<PAL_SIZE; i++)
+ Palette.aEntries[i].peFlags = 0;
+ }
+ ReleaseDC(NULL,hdc);
+ for (i=0; i<PAL_SIZE; i++)
+ {
+ aRGB[i].rgbRed=Palette.aEntries[i].peRed;
+ aRGB[i].rgbGreen=Palette.aEntries[i].peGreen;
+ aRGB[i].rgbBlue=Palette.aEntries[i].peBlue;
+ aRGB[i].rgbReserved=Palette.aEntries[i].peFlags;
+ }
+ ENDPROFILE(GetPalette)
+}
+
+
+WMesaContext /*APIENTRY*/ WMesaCreateContext( HWND hWnd, HPALETTE Pal,
+ /*HDC hDC,*/ GLboolean rgb_flag,
+ GLboolean db_flag )
+{
+ BITMAPINFO *Rec;
+ //HDC DC;
+ RECT CR;
+ WMesaContext c;
+
+ c = (struct wmesa_context * ) calloc(1,sizeof(struct wmesa_context));
+ if (!c)
+ return NULL;
+
+ c->Window=hWnd;
+ c->hDC = GetDC(hWnd);
+
+ if (rgb_flag==GL_FALSE)
+ {
+ c->rgb_flag = GL_FALSE;
+ c->pixel = 1;
+ db_flag=GL_TRUE; // WinG requires double buffering
+ //c->gl_ctx->BufferDepth = windepth;
+ }
+ else
+ {
+ c->rgb_flag = GL_TRUE;
+ c->pixel = 0;
+ }
+ GetClientRect(c->Window,&CR);
+ c->width=CR.right;
+ c->height=CR.bottom;
+ if (db_flag)
+ {
+ c->db_flag = 1;
+// c->hDC GetDC(c->Window);
+ /* Double buffered */
+ if (c->rgb_flag==GL_TRUE)
+ {
+ //DC = c->hDC = hDC;
+
+// DC = c->hDC = GetDC(c->Window);
+ wmCreateBackingStore(c, c->width, c->height);
+// ReleaseDC(c->Window,DC);
+ }
+ else
+ {
+ c->dib.hDC=WinGCreateDC();
+ Rec=(BITMAPINFO *) malloc(sizeof(BITMAPINFO)+(PAL_SIZE-1)*sizeof(RGBQUAD));
+ c->hPal=Pal;
+ GetPalette(Pal,Rec->bmiColors);
+ WinGRecommendDIBFormat(Rec);
+ Rec->bmiHeader.biWidth=c->width;
+ Rec->bmiHeader.biHeight*=c->height;
+ Rec->bmiHeader.biClrUsed=PAL_SIZE;
+ if (Rec->bmiHeader.biPlanes!=1 || Rec->bmiHeader.biBitCount!=8)
+ {
+ MessageBox(NULL,"Error.","This code presumes a 256 color, single plane, WinG Device.\n",MB_OK);
+ exit(1);
+ }
+ c->Compat_BM=WinGCreateBitmap(c->dib.hDC,Rec,&((void *) c->ScreenMem));
+ c->Old_Compat_BM=SelectObject(c->dib.hDC,c->Compat_BM);
+ WinGSetDIBColorTable(c->dib.hDC,0,PAL_SIZE,Rec->bmiColors);
+ c->IndexFormat=Rec;
+ c->ScanWidth=c->width;
+ c->cColorBits = 8;
+ if ((c->ScanWidth%sizeof(long))!=0)
+ c->ScanWidth+=(sizeof(long)-(c->ScanWidth%sizeof(long)));
+ }
+ }
+ else
+ {
+ /* Single Buffered */
+ c->db_flag = 0;
+
+// wmCreateBackingStore(c, c->width, c->height);
+ }
+
+
+
+ c->gl_visual = gl_create_visual(rgb_flag,
+ GL_FALSE, /* software alpha */
+ db_flag, /* db_flag */
+ 16, /* depth_bits */
+ 8, /* stencil_bits */
+ 8, /* accum_bits */
+ 8,
+ 255.0, 255.0, 255.0, 255.0 );
+
+ if (!c->gl_visual) {
+ return NULL;
+ }
+
+ /* allocate a new Mesa context */
+ c->gl_ctx = gl_create_context( c->gl_visual, NULL,c);
+
+ if (!c->gl_ctx) {
+ gl_destroy_visual( c->gl_visual );
+ free(c);
+ return NULL;
+ }
+
+ c->gl_buffer = gl_create_framebuffer( c->gl_visual );
+ if (!c->gl_buffer) {
+ gl_destroy_visual( c->gl_visual );
+ gl_destroy_context( c->gl_ctx );
+ free(c);
+ return NULL;
+ }
+// setup_DD_pointers(c->gl_ctx);
+
+ return c;
+}
+
+
+
+void /*APIENTRY*/ WMesaDestroyContext( void )
+{
+ WMesaContext c = Current;
+ ReleaseDC(c->Window,c->hDC);
+ WC = c;
+
+ gl_destroy_visual( c->gl_visual );
+ gl_destroy_framebuffer( c->gl_buffer );
+ gl_destroy_context( c->gl_ctx );
+
+ if (c->db_flag){
+ wmDeleteBackingStore(c);
+
+//Code added by Li Wei to enable parallel render
+#if !defined(NO_STEREO)
+ if(stereoBuffer==GL_TRUE){
+ WMesaDestroyStereoBuffer();
+ stereoBuffer=GL_FALSE;
+ }
+#endif
+// End modification
+ }
+ free( (void *) c );
+//Code added by Li Wei to enable parallel render
+// Parallel render only work in double buffer mode
+#if !defined(NO_PARALLEL)
+ if(parallelMachine)
+ PRDestroyRenderBuffer();
+#endif
+// End modification
+}
+
+
+
+void /*APIENTRY*/ WMesaMakeCurrent( WMesaContext c )
+{
+ if(!c){
+ Current = c;
+ return;
+ }
+
+ //
+ // A little optimization
+ // If it already is current,
+ // don't set it again
+ //
+ if(Current == c)
+ return;
+
+ //gl_set_context( c->gl_ctx );
+ gl_make_current(c->gl_ctx, c->gl_buffer);
+ Current = c;
+ setup_DD_pointers(c->gl_ctx);
+ if (Current->gl_ctx->Viewport.Width==0) {
+ /* initialize viewport to window size */
+ gl_Viewport( Current->gl_ctx,
+ 0, 0, Current->width, Current->height );
+ }
+}
+
+
+
+void /*APIENTRY*/ WMesaSwapBuffers( void )
+{
+ HDC DC = Current->hDC;
+ if (Current->db_flag)
+ {
+ if (Current->rgb_flag)
+ wmFlush(Current);
+ else
+ WinGBitBlt(DC,0,0,Current->width,Current->height,Current->dib.hDC,0,0);
+ }
+}
+
+
+
+void /*APIENTRY*/ WMesaPaletteChange(HPALETTE Pal)
+{
+ if (Current && Current->rgb_flag==GL_FALSE)
+ {
+ Current->hPal=Pal;
+ GetPalette(Pal,Current->IndexFormat->bmiColors);
+ WinGSetDIBColorTable(Current->dib.hDC,0,PAL_SIZE,Current->IndexFormat->bmiColors);
+ }
+}
+
+//
+// Free up the dib section that was created
+//
+BOOL wmDeleteBackingStore(PWMC pwc)
+{
+ SelectObject(pwc->dib.hDC, pwc->hOldBitmap);
+ DeleteDC(pwc->dib.hDC);
+ DeleteObject(pwc->hbmDIB);
+ UnmapViewOfFile(pwc->dib.base);
+ CloseHandle(pwc->dib.hFileMap);
+ return TRUE;
+}
+
+
+//
+// This function creates the DIB section that is used for combined
+// GL and GDI calls
+//
+BOOL /*WINAPI*/ wmCreateBackingStore(PWMC pwc, long lxSize, long lySize)
+{
+ HDC hdc = pwc->hDC;
+ LPBITMAPINFO pbmi = &(pwc->bmi);
+ int iUsage;
+
+ pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ pbmi->bmiHeader.biWidth = lxSize;
+ pbmi->bmiHeader.biHeight= -lySize;
+ pbmi->bmiHeader.biPlanes = 1;
+ pbmi->bmiHeader.biBitCount = GetDeviceCaps(pwc->hDC, BITSPIXEL);
+ pbmi->bmiHeader.biCompression = BI_RGB;
+ pbmi->bmiHeader.biSizeImage = 0;
+ pbmi->bmiHeader.biXPelsPerMeter = 0;
+ pbmi->bmiHeader.biYPelsPerMeter = 0;
+ pbmi->bmiHeader.biClrUsed = 0;
+ pbmi->bmiHeader.biClrImportant = 0;
+
+ iUsage = (pbmi->bmiHeader.biBitCount <= 8) ? DIB_PAL_COLORS : DIB_RGB_COLORS;
+
+ pwc->cColorBits = pbmi->bmiHeader.biBitCount;
+ pwc->ScanWidth = lxSize;
+
+ wmCreateDIBSection(hdc, pwc, pbmi, iUsage);
+
+ if ((iUsage == DIB_PAL_COLORS) && !(pwc->hGLPalette)) {
+ wmCreatePalette( pwc );
+ wmSetDibColors( pwc );
+ }
+
+ return(TRUE);
+
+}
+
+
+//
+// This function copies one scan line in a DIB section to another
+//
+BOOL GLWINAPI wmSetDIBits(PWMC pwc, UINT uiScanWidth, UINT uiNumScans, UINT nBypp, UINT uiNewWidth, LPBYTE pBits)
+{
+ UINT uiScans = 0;
+ LPBYTE pDest = pwc->pbPixels;
+ DWORD dwNextScan = uiScanWidth;
+ DWORD dwNewScan = uiNewWidth;
+ DWORD dwScanWidth = (uiScanWidth * nBypp);
+
+ //
+ // We need to round up to the nearest DWORD
+ // and multiply by the number of bytes per
+ // pixel
+ //
+ dwNextScan = (((dwNextScan * nBypp)+ 3) & ~3);
+ dwNewScan = (((dwNewScan * nBypp)+ 3) & ~3);
+
+ for(uiScans = 0; uiScans < uiNumScans; uiScans++){
+ CopyMemory(pDest, pBits, dwScanWidth);
+ pBits += dwNextScan;
+ pDest += dwNewScan;
+ }
+
+ return(TRUE);
+
+}
+
+BOOL GLWINAPI wmSetPixelFormat( PWMC pwdc, HDC hDC, DWORD dwFlags )
+{
+ return(TRUE);
+}
+
+static unsigned char threeto8[8] = {
+ 0, 0111>>1, 0222>>1, 0333>>1, 0444>>1, 0555>>1, 0666>>1, 0377
+};
+
+static unsigned char twoto8[4] = {
+ 0, 0x55, 0xaa, 0xff
+};
+
+static unsigned char oneto8[2] = {
+ 0, 255
+};
+
+static unsigned char componentFromIndex(UCHAR i, UINT nbits, UINT shift)
+{
+ unsigned char val;
+
+ val = i >> shift;
+ switch (nbits) {
+
+ case 1:
+ val &= 0x1;
+ return oneto8[val];
+
+ case 2:
+ val &= 0x3;
+ return twoto8[val];
+
+ case 3:
+ val &= 0x7;
+ return threeto8[val];
+
+ default:
+ return 0;
+ }
+}
+
+void /*WINAPI*/ wmCreatePalette( PWMC pwdc )
+{
+ /* Create a compressed and re-expanded 3:3:2 palette */
+ int i;
+ LOGPALETTE *pPal;
+ BYTE rb, rs, gb, gs, bb, bs;
+
+ pwdc->nColors = 0x100;
+
+ pPal = (PLOGPALETTE)malloc(sizeof(LOGPALETTE) + pwdc->nColors * sizeof(PALETTEENTRY));
+ memset( pPal, 0, sizeof(LOGPALETTE) + pwdc->nColors * sizeof(PALETTEENTRY) );
+
+ pPal->palVersion = 0x300;
+
+ rb = REDBITS;
+ rs = REDSHIFT;
+ gb = GREENBITS;
+ gs = GREENSHIFT;
+ bb = BLUEBITS;
+ bs = BLUESHIFT;
+
+ if (pwdc->db_flag) {
+
+ /* Need to make two palettes: one for the screen DC and one for the DIB. */
+ pPal->palNumEntries = pwdc->nColors;
+ for (i = 0; i < pwdc->nColors; i++) {
+ pPal->palPalEntry[i].peRed = componentFromIndex( i, rb, rs );
+ pPal->palPalEntry[i].peGreen = componentFromIndex( i, gb, gs );
+ pPal->palPalEntry[i].peBlue = componentFromIndex( i, bb, bs );
+ pPal->palPalEntry[i].peFlags = 0;
+ }
+ pwdc->hGLPalette = CreatePalette( pPal );
+ pwdc->hPalette = CreatePalette( pPal );
+ }
+
+ else {
+ pPal->palNumEntries = pwdc->nColors;
+ for (i = 0; i < pwdc->nColors; i++) {
+ pPal->palPalEntry[i].peRed = componentFromIndex( i, rb, rs );
+ pPal->palPalEntry[i].peGreen = componentFromIndex( i, gb, gs );
+ pPal->palPalEntry[i].peBlue = componentFromIndex( i, bb, bs );
+ pPal->palPalEntry[i].peFlags = 0;
+ }
+ pwdc->hGLPalette = CreatePalette( pPal );
+ }
+
+ free(pPal);
+
+}
+
+//
+// This function sets the color table of a DIB section
+// to match that of the destination DC
+//
+BOOL /*WINAPI*/ wmSetDibColors(PWMC pwc)
+{
+ RGBQUAD *pColTab, *pRGB;
+ PALETTEENTRY *pPal, *pPE;
+ int i, nColors;
+ BOOL bRet=TRUE;
+ DWORD dwErr=0;
+
+ /* Build a color table in the DIB that maps to the
+ selected palette in the DC.
+ */
+ nColors = 1 << pwc->cColorBits;
+ pPal = (PALETTEENTRY *)malloc( nColors * sizeof(PALETTEENTRY));
+ memset( pPal, 0, nColors * sizeof(PALETTEENTRY) );
+ GetPaletteEntries( pwc->hGLPalette, 0, nColors, pPal );
+ pColTab = (RGBQUAD *)malloc( nColors * sizeof(RGBQUAD));
+ for (i = 0, pRGB = pColTab, pPE = pPal; i < nColors; i++, pRGB++, pPE++) {
+ pRGB->rgbRed = pPE->peRed;
+ pRGB->rgbGreen = pPE->peGreen;
+ pRGB->rgbBlue = pPE->peBlue;
+ }
+ if(pwc->db_flag)
+ bRet = SetDIBColorTable(pwc->hDC, 0, nColors, pColTab );
+
+ if(!bRet)
+ dwErr = GetLastError();
+
+ free( pColTab );
+ free( pPal );
+
+ return(bRet);
+}
+
+void /*WINAPI*/ wmSetPixel(PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b)
+{
+ if(Current->db_flag){
+ LPBYTE lpb = pwc->pbPixels;
+ LPDWORD lpdw;
+ LPWORD lpw;
+ UINT nBypp = pwc->cColorBits / 8;
+ UINT nOffset = iPixel % nBypp;
+
+ // Move the pixel buffer pointer to the scanline that we
+ // want to access
+
+ pwc->dib.fFlushed = FALSE;
+
+ lpb += pwc->ScanWidth * iScanLine;
+ // Now move to the desired pixel
+ lpb += iPixel * nBypp;
+
+ lpdw = (LPDWORD)lpb;
+ lpw = (LPWORD)lpb;
+
+ if(nBypp == 2)
+ *lpw = BGR16(r,g,b);
+ else if (nBypp == 3){
+ *lpdw = BGR24(r,g,b);
+ }
+ else
+ *lpdw = BGR32(r,g,b);
+ }
+ else{
+ HDC DC = DD_GETDC;
+ SetPixel(DC, iPixel, iScanLine, RGB(r,g,b));
+ DD_RELEASEDC;
+ }
+}
+
+void /*WINAPI*/ wmCreateDIBSection(
+ HDC hDC,
+ PWMC pwc, // handle of device context
+ CONST BITMAPINFO *pbmi, // address of structure containing bitmap size, format, and color data
+ UINT iUsage // color data type indicator: RGB values or palette indices
+)
+{
+ DWORD dwSize = 0;
+ DWORD dwScanWidth;
+ UINT nBypp = pwc->cColorBits / 8;
+ HDC hic;
+
+ dwScanWidth = (((pwc->ScanWidth * nBypp)+ 3) & ~3);
+
+ pwc->ScanWidth = dwScanWidth;
+
+ dwSize = sizeof(BITMAPINFO) + (dwScanWidth * pwc->height);
+
+ pwc->dib.hFileMap = CreateFileMapping((HANDLE)PAGE_FILE,
+ NULL,
+ PAGE_READWRITE | SEC_COMMIT,
+ 0,
+ dwSize,
+ NULL);
+
+ if (!pwc->dib.hFileMap)
+ return;
+
+ pwc->dib.base = MapViewOfFile(pwc->dib.hFileMap,
+ FILE_MAP_ALL_ACCESS,
+ 0,
+ 0,
+ 0);
+
+ if(!pwc->dib.base){
+ CloseHandle(pwc->dib.hFileMap);
+ return;
+ }
+
+ pwc->pbPixels = ((LPBYTE)pwc->dib.base) + sizeof(BITMAPINFO);
+
+ pwc->dib.hDC = CreateCompatibleDC(hDC);
+
+ CopyMemory(pwc->dib.base, pbmi, sizeof(BITMAPINFO));
+
+ hic = CreateIC("display", NULL, NULL, NULL);
+
+/* pwc->hbmDIB = CreateDIBitmap(hic,
+ &(pwc->bmi.bmiHeader),
+ CBM_INIT,
+ pwc->pbPixels,
+ &(pwc->bmi),
+ DIB_RGB_COLORS);
+*/
+ pwc->hbmDIB = CreateDIBSection(hic,
+ &(pwc->bmi.bmiHeader),
+ DIB_RGB_COLORS,
+ &(pwc->pbPixels),
+ pwc->dib.hFileMap,
+ 0);
+ pwc->hOldBitmap = SelectObject(pwc->dib.hDC, pwc->hbmDIB);
+
+ DeleteDC(hic);
+
+ return;
+
+}
+
+//
+// Blit memory DC to screen DC
+//
+BOOL /*WINAPI*/ wmFlush(PWMC pwc)
+{
+ BOOL bRet = 0;
+ DWORD dwErr = 0;
+
+
+// wmFlushBits(pwc);
+
+ bRet = BitBlt(pwc->hDC, 0, 0, pwc->width, pwc->height,
+ pwc->dib.hDC, 0, 0, SRCCOPY);
+
+ if(!bRet)
+ dwErr = GetLastError();
+
+ pwc->dib.fFlushed = TRUE;
+
+ return(TRUE);
+
+}
+
+
+// The following code is added by Li Wei to enable stereo display
+
+#if !defined(NO_STEREO)
+
+void WMesaCreateStereoBuffer()
+{
+ /* Must use double buffer and not in parallelMode */
+ if (! Current->db_flag
+#if !defined(NO_PARALLEL)
+ || parallelFlag
+#endif
+ )
+ return;
+
+ Buffer_Stereo = malloc( Current->ScanWidth * Current->height);
+ ZeroMemory(Buffer_Stereo,Current->ScanWidth * Current->height);
+ stereoBuffer = GL_TRUE ;
+}
+
+void WMesaDestroyStereoBuffer()
+{
+ /* Must use double buffer and not in parallelMode */
+ if (! Current->db_flag
+#if !defined(NO_PARALLEL)
+ || parallelFlag
+#endif
+ )
+ return;
+ if(stereoBuffer){
+ free(Buffer_Stereo);
+ stereoBuffer = GL_FALSE ;
+ }
+}
+
+void WMesaInterleave(GLenum aView)
+{
+ int offset;
+ unsigned line;
+ LPBYTE dest;
+ LPBYTE src;
+ if(aView == FIRST)
+ offset = 0;
+ else offset = 1;
+
+ dest = Buffer_Stereo + offset * Current->ScanWidth;
+ if(Current->rgb_flag )
+ src = Current->pbPixels + Current->ScanWidth*(Current->height/2);
+ else
+ src = Current->ScreenMem;
+
+ for(line = 0; line<Current->height/2; line ++){
+ CopyMemory(dest, src, Current->ScanWidth);
+ dest += 2*Current->ScanWidth;
+ src += Current->ScanWidth;
+ }
+ if(aView == SECOND)
+ if(Current->rgb_flag)
+ CopyMemory(Current->pbPixels, Buffer_Stereo, Current->ScanWidth*Current->height);
+ else
+ CopyMemory(Current->ScreenMem, Buffer_Stereo, Current->ScanWidth*Current->height);
+}
+
+void WMesaShowStereo(GLuint list)
+{
+
+ GLbitfield mask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
+ GLfloat cm[16];
+ // Must use double Buffer
+ if( ! Current-> db_flag )
+ return;
+
+ glViewport(0,0,Current->width,Current->height/2);
+
+ glGetFloatv(GL_MODELVIEW_MATRIX,cm);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ gluLookAt(viewDistance/2,0.0,0.0 ,
+ viewDistance/2,0.0,-1.0,
+ 0.0,1.0,0.0 );
+ glMultMatrixf( cm );
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glCallList( list );
+ glPopMatrix();
+ glFlush();
+ WMesaInterleave( FIRST );
+
+ glGetFloatv(GL_MODELVIEW_MATRIX,cm);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ gluLookAt(-viewDistance/2,0.0,0.0 ,
+ -viewDistance/2,0.0,-1.0,
+ 0.0,1.0,0.0 );
+ glMultMatrixf(cm);
+ glMatrixMode(GL_MODELVIEW);
+ glCallList(list);
+ glFlush();
+ WMesaInterleave( SECOND );
+ glViewport(0,0,Current->width,Current->height);
+ WMesaSwapBuffers();
+
+}
+
+void toggleStereoMode()
+{
+ if(!Current->db_flag)
+ return;
+ if(!stereo_flag){
+ stereo_flag = 1;
+ if(stereoBuffer==GL_FALSE)
+#if !defined(NO_PARALLEL)
+ if(!parallelFlag)
+#endif
+ {
+ WMesaCreateStereoBuffer();
+ }
+ }
+ else {
+ stereo_flag = 0;
+ if(stereoBuffer==GL_TRUE)
+#if !defined(NO_PARALLEL)
+ if(!parallelFlag)
+#endif
+ if(stereoBuffer==GL_TRUE){
+ WMesaDestroyStereoBuffer();
+ }
+ }
+}
+
+/* if in stereo mode, the following function is called */
+void glShowStereo(GLuint list)
+{
+ WMesaShowStereo(list);
+}
+
+#endif // End if NO_STEREO not defined
+
+#if !defined(NO_PARALLEL)
+
+void toggleParallelMode(void)
+{
+ if(!parallelFlag){
+ parallelFlag = GL_TRUE;
+ if(parallelMachine==GL_FALSE){
+ PRCreateRenderBuffer( Current->rgb_flag? GL_RGBA :GL_COLOR_INDEX,
+ Current->cColorBits/8,
+ Current->width ,Current->height,
+ Current->ScanWidth,
+ Current->rgb_flag? Current->pbPixels: Current->ScreenMem);
+ parallelMachine = GL_TRUE;
+ }
+ }
+ else {
+ parallelFlag = GL_FALSE;
+ if(parallelMachine==GL_TRUE){
+ PRDestroyRenderBuffer();
+ parallelMachine=GL_FALSE;
+ ReadyForNextFrame = GL_TRUE;
+ }
+
+/***********************************************
+// Seems something wrong!!!!
+************************************************/
+
+ WMesaMakeCurrent(Current);
+#if !defined(NO_STEREO)
+ stereo_flag = GL_FALSE ;
+#endif
+ }
+}
+
+void PRShowRenderResult(void)
+{
+ int flag = 0;
+if(!glImageRendered())
+ return;
+
+ if (parallelFlag)
+ {
+ WMesaSwapBuffers();
+ }
+
+}
+#endif //End if NO_PARALLEL not defined
+
+//end modification
diff --git a/src/mesa/drivers/windows/wmesadef.h b/src/mesa/drivers/windows/wmesadef.h
new file mode 100644
index 0000000000..7cd4bb9a7d
--- /dev/null
+++ b/src/mesa/drivers/windows/wmesadef.h
@@ -0,0 +1,154 @@
+/* File name : wmesadef.h
+ * Version : 2.3
+ *
+ * Header file for display driver for Mesa 2.3 under
+ * Windows95, WindowsNT and Win32
+ *
+ * Copyright (C) 1996- Li Wei
+ * Address : Institute of Artificial Intelligence
+ * : & Robotics
+ * : Xi'an Jiaotong University
+ * Email : liwei@aiar.xjtu.edu.cn
+ * Web page : http://sun.aiar.xjtu.edu.cn
+ *
+ * This file and its associations are partially based on the
+ * Windows NT driver for Mesa, written by Mark Leaming
+ * (mark@rsinc.com).
+ */
+
+/*
+ * $Log: wmesadef.h,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 1.3 1999/01/03 03:08:57 brianp
+ * Ted Jump's changes
+ *
+ * Initial version 1997/6/14 CST by Li Wei(liwei@aiar.xjtu.edu.cn)
+ */
+
+/*
+ * $Log: wmesadef.h,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 1.3 1999/01/03 03:08:57 brianp
+ * Ted Jump's changes
+ *
+ * Revision 2.1 1996/11/15 10:54:00 CST by Li Wei(liwei@aiar.xjtu.edu.cn)
+ * a new element added to wmesa_context :
+ * dither_flag
+ */
+
+/*
+ * $Log: wmesadef.h,v $
+ * Revision 1.1 1999/08/19 00:55:42 jtg
+ * Initial revision
+ *
+ * Revision 1.3 1999/01/03 03:08:57 brianp
+ * Ted Jump's changes
+ *
+ * Revision 2.0 1996/11/15 10:54:00 CST by Li Wei(liwei@aiar.xjtu.edu.cn)
+ * Initial revision
+ */
+
+
+
+#ifndef DDMESADEF_H
+#define DDMESADEF_H
+
+#include <windows.h>
+#include <GL\gl.h>
+#include "context.h"
+#ifdef DDRAW
+ #include <ddraw.h>
+#endif
+//#include "profile.h"
+
+#define REDBITS 0x03
+#define REDSHIFT 0x00
+#define GREENBITS 0x03
+#define GREENSHIFT 0x03
+#define BLUEBITS 0x02
+#define BLUESHIFT 0x06
+
+typedef struct _dibSection{
+ HDC hDC;
+ HANDLE hFileMap;
+ BOOL fFlushed;
+ LPVOID base;
+}WMDIBSECTION, *PWMDIBSECTION;
+
+
+typedef struct wmesa_context{
+ GLcontext *gl_ctx; /* The core GL/Mesa context */
+ GLvisual *gl_visual; /* Describes the buffers */
+ GLframebuffer *gl_buffer; /* Depth, stencil, accum, etc buffers */
+
+
+ HWND Window;
+ HDC hDC;
+ HPALETTE hPalette;
+ HPALETTE hOldPalette;
+ HPEN hPen;
+ HPEN hOldPen;
+ HCURSOR hOldCursor;
+ COLORREF crColor;
+ // 3D projection stuff
+ RECT drawRect;
+ UINT uiDIBoffset;
+ // OpenGL stuff
+ HPALETTE hGLPalette;
+ GLuint width;
+ GLuint height;
+ GLuint ScanWidth;
+ GLboolean db_flag; //* double buffered?
+ GLboolean rgb_flag; //* RGB mode?
+ GLboolean dither_flag; //* use dither when 256 color mode for RGB?
+ GLuint depth; //* bits per pixel (1, 8, 24, etc)
+ ULONG pixel; // current color index or RGBA pixel value
+ ULONG clearpixel; //* pixel for clearing the color buffers
+ PBYTE ScreenMem; // WinG memory
+ BITMAPINFO *IndexFormat;
+ HPALETTE hPal; // Current Palette
+ HPALETTE hPalHalfTone;
+
+
+ WMDIBSECTION dib;
+ BITMAPINFO bmi;
+ HBITMAP hbmDIB;
+ HBITMAP hOldBitmap;
+ HBITMAP Old_Compat_BM;
+ HBITMAP Compat_BM; // Bitmap for double buffering
+ PBYTE pbPixels;
+ int nColors;
+ BYTE cColorBits;
+ int pixelformat;
+
+#ifdef DDRAW
+ LPDIRECTDRAW lpDD; // DirectDraw object
+// LPDIRECTDRAW2 lpDD2; // DirectDraw object
+ LPDIRECTDRAWSURFACE lpDDSPrimary; // DirectDraw primary surface
+ LPDIRECTDRAWSURFACE lpDDSOffScreen; // DirectDraw off screen surface
+ LPDIRECTDRAWPALETTE lpDDPal; // DirectDraw palette
+ BOOL bActive; // is application active?
+ DDSURFACEDESC ddsd;
+ int fullScreen;
+ int gMode ;
+#endif
+ RECT rectOffScreen;
+ RECT rectSurface;
+ HWND hwnd;
+ DWORD pitch;
+ PBYTE addrOffScreen;
+//#ifdef PROFILE
+// MESAPROF profile;
+//#endif
+} *PWMC;
+
+
+#define PAGE_FILE 0xffffffff
+
+
+
+#endif
diff --git a/src/mesa/drivers/x11/fakeglx.c b/src/mesa/drivers/x11/fakeglx.c
new file mode 100644
index 0000000000..12567fe19c
--- /dev/null
+++ b/src/mesa/drivers/x11/fakeglx.c
@@ -0,0 +1,1516 @@
+/* $Id: fakeglx.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+/*
+ * A pseudo-GLX implementation to allow OpenGL/GLX programs to work with Mesa.
+ * The Fake_glX*() functions implemented here are called from glxapi.c
+ *
+ * Thanks to the contributors:
+ *
+ * Initial version: Philip Brown (philb@CSUA.Berkeley.EDU)
+ * Better glXGetConfig() support: Armin Liebchen (liebchen@asylum.cs.utah.edu)
+ * Further visual-handling refinements: Wolfram Gloger
+ * (wmglo@Dent.MED.Uni-Muenchen.DE).
+ *
+ * Notes:
+ * Don't be fooled, stereo isn't supported yet.
+ */
+
+
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include "GL/gl.h"
+#include "GL/xmesa.h"
+#include "context.h"
+#include "config.h"
+#include "fakeglx.h"
+#include "macros.h"
+#include "types.h"
+#include "xmesaP.h"
+
+
+
+#define DONT_CARE -1
+
+
+
+#define MAX_VISUALS 100
+static XMesaVisual VisualTable[MAX_VISUALS];
+static int NumVisuals = 0;
+
+
+
+/*
+ * This struct and some code fragments borrowed
+ * from Mark Kilgard's GLUT library.
+ */
+typedef struct _OverlayInfo {
+ /* Avoid 64-bit portability problems by being careful to use
+ longs due to the way XGetWindowProperty is specified. Note
+ that these parameters are passed as CARD32s over X
+ protocol. */
+ unsigned long overlay_visual;
+ long transparent_type;
+ long value;
+ long layer;
+} OverlayInfo;
+
+
+
+/* Macro to handle c_class vs class field name in XVisualInfo struct */
+#if defined(__cplusplus) || defined(c_plusplus)
+#define CLASS c_class
+#else
+#define CLASS class
+#endif
+
+
+
+
+/*
+ * Test if the given XVisualInfo is usable for Mesa rendering.
+ */
+static GLboolean is_usable_visual( XVisualInfo *vinfo )
+{
+ switch (vinfo->CLASS) {
+ case StaticGray:
+ case GrayScale:
+ /* Any StaticGray/GrayScale visual works in RGB or CI mode */
+ return GL_TRUE;
+ case StaticColor:
+ case PseudoColor:
+ /* Any StaticColor/PseudoColor visual of at least 4 bits */
+ if (vinfo->depth>=4) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+ case TrueColor:
+ case DirectColor:
+ /* Any depth of TrueColor or DirectColor works in RGB mode */
+ return GL_TRUE;
+ default:
+ /* This should never happen */
+ return GL_FALSE;
+ }
+}
+
+
+
+/*
+ * Return the level (overlay, normal, underlay) of a given XVisualInfo.
+ * Input: dpy - the X display
+ * vinfo - the XVisualInfo to test
+ * Return: level of the visual:
+ * 0 = normal planes
+ * >0 = overlay planes
+ * <0 = underlay planes
+ */
+static int level_of_visual( Display *dpy, XVisualInfo *vinfo )
+{
+ Atom overlayVisualsAtom;
+ OverlayInfo *overlay_info = NULL;
+ int numOverlaysPerScreen;
+ Status status;
+ Atom actualType;
+ int actualFormat;
+ unsigned long sizeData, bytesLeft;
+ int i;
+
+ /*
+ * The SERVER_OVERLAY_VISUALS property on the root window contains
+ * a list of overlay visuals. Get that list now.
+ */
+ overlayVisualsAtom = XInternAtom(dpy,"SERVER_OVERLAY_VISUALS", True);
+ if (overlayVisualsAtom == None) {
+ return 0;
+ }
+
+ status = XGetWindowProperty(dpy, RootWindow( dpy, vinfo->screen ),
+ overlayVisualsAtom, 0L, (long) 10000, False,
+ overlayVisualsAtom, &actualType, &actualFormat,
+ &sizeData, &bytesLeft,
+ (unsigned char **) &overlay_info );
+
+ if (status != Success || actualType != overlayVisualsAtom ||
+ actualFormat != 32 || sizeData < 4) {
+ /* something went wrong */
+ XFree((void *) overlay_info);
+ return 0;
+ }
+
+ /* search the overlay visual list for the visual ID of interest */
+ numOverlaysPerScreen = (int) (sizeData / 4);
+ for (i=0;i<numOverlaysPerScreen;i++) {
+ OverlayInfo *ov;
+ ov = overlay_info + i;
+ if (ov->overlay_visual==vinfo->visualid) {
+ /* found the visual */
+ if (/*ov->transparent_type==1 &&*/ ov->layer!=0) {
+ int level = ov->layer;
+ XFree((void *) overlay_info);
+ return level;
+ }
+ else {
+ XFree((void *) overlay_info);
+ return 0;
+ }
+ }
+ }
+
+ /* The visual ID was not found in the overlay list. */
+ XFree((void *) overlay_info);
+ return 0;
+}
+
+
+
+
+/*
+ * Given an XVisualInfo and RGB, Double, and Depth buffer flags, save the
+ * configuration in our list of GLX visuals.
+ */
+static XMesaVisual
+save_glx_visual( Display *dpy, XVisualInfo *vinfo,
+ GLboolean rgbFlag, GLboolean alphaFlag, GLboolean dbFlag,
+ GLboolean stereoFlag,
+ GLint depth_size, GLint stencil_size,
+ GLint accum_size, GLint level )
+{
+ GLboolean ximageFlag = GL_TRUE;
+ XMesaVisual xmvis;
+ GLint i;
+ GLboolean comparePointers;
+
+ if (dbFlag) {
+ /* Check if the MESA_BACK_BUFFER env var is set */
+ char *backbuffer = getenv("MESA_BACK_BUFFER");
+ if (backbuffer) {
+ if (backbuffer[0]=='p' || backbuffer[0]=='P') {
+ ximageFlag = GL_FALSE;
+ }
+ else if (backbuffer[0]=='x' || backbuffer[0]=='X') {
+ ximageFlag = GL_TRUE;
+ }
+ else {
+ fprintf(stderr, "Mesa: invalid value for MESA_BACK_BUFFER ");
+ fprintf(stderr, "environment variable, using an XImage.\n");
+ }
+ }
+ }
+
+ /* Comparing IDs uses less memory but sometimes fails. */
+ /* XXX revisit this after 3.0 is finished. */
+ if (getenv("MESA_GLX_VISUAL_HACK"))
+ comparePointers = GL_TRUE;
+ else
+ comparePointers = GL_FALSE;
+
+ /* First check if a matching visual is already in the list */
+ for (i=0; i<NumVisuals; i++) {
+ XMesaVisual v = VisualTable[i];
+ if (v->display == dpy
+ && v->level == level
+ && v->ximage_flag == ximageFlag
+ && v->gl_visual->RGBAflag == rgbFlag
+ && v->gl_visual->DBflag == dbFlag
+ && v->gl_visual->StereoFlag == stereoFlag
+ && (v->gl_visual->AlphaBits > 0) == alphaFlag
+ && (v->gl_visual->DepthBits >= depth_size || depth_size == 0)
+ && (v->gl_visual->StencilBits >= stencil_size || stencil_size == 0)
+ && (v->gl_visual->AccumBits >= accum_size || accum_size == 0)) {
+ /* now either compare XVisualInfo pointers or visual IDs */
+ if ((!comparePointers && v->vishandle->visualid == vinfo->visualid)
+ || (comparePointers && v->vishandle == vinfo)) {
+ return v;
+ }
+ }
+ }
+
+ /* Create a new visual and add it to the list. */
+
+ if (NumVisuals>=MAX_VISUALS) {
+ fprintf( stderr, "GLX Error: maximum number of visuals exceeded\n");
+ return NULL;
+ }
+
+ xmvis = XMesaCreateVisual( dpy, vinfo, rgbFlag, alphaFlag, dbFlag,
+ stereoFlag, ximageFlag,
+ depth_size, stencil_size, accum_size, level );
+ if (xmvis) {
+ VisualTable[NumVisuals] = xmvis;
+ NumVisuals++;
+ }
+ return xmvis;
+}
+
+
+
+/*
+ * Create a GLX visual from a regular XVisualInfo.
+ */
+static XMesaVisual
+create_glx_visual( Display *dpy, XVisualInfo *visinfo )
+{
+ int vislevel;
+
+ vislevel = level_of_visual( dpy, visinfo );
+ if (vislevel) {
+ /* Configure this visual as a CI, single-buffered overlay */
+ return save_glx_visual( dpy, visinfo,
+ GL_FALSE, /* rgb */
+ GL_FALSE, /* alpha */
+ GL_FALSE, /* double */
+ GL_FALSE, /* stereo */
+ 0, /* depth bits */
+ 0, /* stencil bits */
+ 0, /* accum bits */
+ vislevel /* level */
+ );
+ }
+ else if (is_usable_visual( visinfo )) {
+ /* Configure this visual as RGB, double-buffered, depth-buffered. */
+ /* This is surely wrong for some people's needs but what else */
+ /* can be done? They should use glXChooseVisual(). */
+ return save_glx_visual( dpy, visinfo,
+ GL_TRUE, /* rgb */
+ GL_FALSE, /* alpha */
+ GL_TRUE, /* double */
+ GL_FALSE, /* stereo */
+ 8*sizeof(GLdepth),
+ 8*sizeof(GLstencil),
+ 8*sizeof(GLaccum),
+ 0 /* level */
+ );
+ }
+ else {
+ fprintf(stderr,"Mesa: error in glXCreateContext: bad visual\n");
+ return NULL;
+ }
+}
+
+
+
+/*
+ * Find the GLX visual associated with an XVisualInfo.
+ */
+static XMesaVisual
+find_glx_visual( Display *dpy, XVisualInfo *vinfo )
+{
+ int i;
+
+ /* First try to match pointers */
+ for (i=0;i<NumVisuals;i++) {
+ if (VisualTable[i]->display==dpy && VisualTable[i]->vishandle==vinfo) {
+ return VisualTable[i];
+ }
+ }
+ /* try to match visual id */
+ for (i=0;i<NumVisuals;i++) {
+ if (VisualTable[i]->display==dpy
+ && VisualTable[i]->visinfo->visualid == vinfo->visualid) {
+ return VisualTable[i];
+ }
+ }
+ return NULL;
+}
+
+
+
+/*
+ * Return the transparent pixel value for a GLX visual.
+ * Input: glxvis - the glx_visual
+ * Return: a pixel value or -1 if no transparent pixel
+ */
+static int transparent_pixel( XMesaVisual glxvis )
+{
+ Display *dpy = glxvis->display;
+ XVisualInfo *vinfo = glxvis->visinfo;
+ Atom overlayVisualsAtom;
+ OverlayInfo *overlay_info = NULL;
+ int numOverlaysPerScreen;
+ Status status;
+ Atom actualType;
+ int actualFormat;
+ unsigned long sizeData, bytesLeft;
+ int i;
+
+ /*
+ * The SERVER_OVERLAY_VISUALS property on the root window contains
+ * a list of overlay visuals. Get that list now.
+ */
+ overlayVisualsAtom = XInternAtom(dpy,"SERVER_OVERLAY_VISUALS", True);
+ if (overlayVisualsAtom == None) {
+ return -1;
+ }
+
+ status = XGetWindowProperty(dpy, RootWindow( dpy, vinfo->screen ),
+ overlayVisualsAtom, 0L, (long) 10000, False,
+ overlayVisualsAtom, &actualType, &actualFormat,
+ &sizeData, &bytesLeft,
+ (unsigned char **) &overlay_info );
+
+ if (status != Success || actualType != overlayVisualsAtom ||
+ actualFormat != 32 || sizeData < 4) {
+ /* something went wrong */
+ XFree((void *) overlay_info);
+ return -1;
+ }
+
+ /* search the overlay visual list for the visual ID of interest */
+ numOverlaysPerScreen = (int) (sizeData / 4);
+ for (i=0;i<numOverlaysPerScreen;i++) {
+ OverlayInfo *ov;
+ ov = overlay_info + i;
+ if (ov->overlay_visual==vinfo->visualid) {
+ /* found it! */
+ if (ov->transparent_type==0) {
+ /* type 0 indicates no transparency */
+ XFree((void *) overlay_info);
+ return -1;
+ }
+ else {
+ /* ov->value is the transparent pixel */
+ XFree((void *) overlay_info);
+ return ov->value;
+ }
+ }
+ }
+
+ /* The visual ID was not found in the overlay list. */
+ XFree((void *) overlay_info);
+ return -1;
+}
+
+
+
+/*
+ * Return number of bits set in n.
+ */
+static int bitcount( unsigned long n )
+{
+ int bits;
+ for (bits=0; n>0; n=n>>1) {
+ if (n&1) {
+ bits++;
+ }
+ }
+ return bits;
+}
+
+
+/*
+ * Try to get an X visual which matches the given arguments.
+ */
+static XVisualInfo *get_visual( Display *dpy, int scr,
+ unsigned int depth, int xclass )
+{
+ XVisualInfo temp, *vis;
+ long mask;
+ int n;
+ unsigned int default_depth;
+ int default_class;
+
+ mask = VisualScreenMask | VisualDepthMask | VisualClassMask;
+ temp.screen = scr;
+ temp.depth = depth;
+ temp.CLASS = xclass;
+
+ default_depth = DefaultDepth(dpy,scr);
+ default_class = DefaultVisual(dpy,scr)->CLASS;
+
+ if (depth==default_depth && xclass==default_class) {
+ /* try to get root window's visual */
+ temp.visualid = DefaultVisual(dpy,scr)->visualid;
+ mask |= VisualIDMask;
+ }
+
+ vis = XGetVisualInfo( dpy, mask, &temp, &n );
+
+ /* In case bits/pixel > 24, make sure color channels are still <=8 bits.
+ * An SGI Infinite Reality system, for example, can have 30bpp pixels:
+ * 10 bits per color channel. Mesa's limited to a max of 8 bits/channel.
+ */
+ if (vis && depth > 24 && (xclass==TrueColor || xclass==DirectColor)) {
+ if (bitcount(vis->red_mask) <= 8
+ && bitcount(vis->green_mask) <= 8
+ && bitcount(vis->blue_mask) <= 8) {
+ return vis;
+ }
+ else {
+ XFree((void *) vis);
+ return NULL;
+ }
+ }
+
+ return vis;
+}
+
+
+
+/*
+ * Retrieve the value of the given environment variable and find
+ * the X visual which matches it.
+ * Input: dpy - the display
+ * screen - the screen number
+ * varname - the name of the environment variable
+ * Return: an XVisualInfo pointer to NULL if error.
+ */
+static XVisualInfo *get_env_visual(Display *dpy, int scr, const char *varname)
+{
+ char value[100], type[100];
+ int depth, xclass = -1;
+ XVisualInfo *vis;
+
+ if (!getenv( varname )) {
+ return NULL;
+ }
+
+ strncpy( value, getenv(varname), 100 );
+ value[99] = 0;
+
+ sscanf( value, "%s %d", type, &depth );
+
+ if (strcmp(type,"TrueColor")==0) xclass = TrueColor;
+ else if (strcmp(type,"DirectColor")==0) xclass = DirectColor;
+ else if (strcmp(type,"PseudoColor")==0) xclass = PseudoColor;
+ else if (strcmp(type,"StaticColor")==0) xclass = StaticColor;
+ else if (strcmp(type,"GrayScale")==0) xclass = GrayScale;
+ else if (strcmp(type,"StaticGray")==0) xclass = StaticGray;
+
+ if (xclass>-1 && depth>0) {
+ vis = get_visual( dpy, scr, depth, xclass );
+ if (vis) {
+ return vis;
+ }
+ }
+
+ fprintf( stderr, "Mesa: GLX unable to find visual class=%s, depth=%d.\n",
+ type, depth );
+ return NULL;
+}
+
+
+
+/*
+ * Select an X visual which satisfies the RGBA/CI flag and minimum depth.
+ * Input: dpy, screen - X display and screen number
+ * rgba - GL_TRUE = RGBA mode, GL_FALSE = CI mode
+ * min_depth - minimum visual depth
+ * preferred_class - preferred GLX visual class or DONT_CARE
+ * Return: pointer to an XVisualInfo or NULL.
+ */
+static XVisualInfo *choose_x_visual( Display *dpy, int screen,
+ GLboolean rgba, int min_depth,
+ int preferred_class )
+{
+ XVisualInfo *vis;
+ int xclass, visclass;
+ int depth;
+
+ if (rgba) {
+ Atom hp_cr_maps = XInternAtom(dpy, "_HP_RGB_SMOOTH_MAP_LIST", True);
+ /* First see if the MESA_RGB_VISUAL env var is defined */
+ vis = get_env_visual( dpy, screen, "MESA_RGB_VISUAL" );
+ if (vis) {
+ return vis;
+ }
+ /* Otherwise, search for a suitable visual */
+ if (preferred_class==DONT_CARE) {
+ for (xclass=0;xclass<6;xclass++) {
+ switch (xclass) {
+ case 0: visclass = TrueColor; break;
+ case 1: visclass = DirectColor; break;
+ case 2: visclass = PseudoColor; break;
+ case 3: visclass = StaticColor; break;
+ case 4: visclass = GrayScale; break;
+ case 5: visclass = StaticGray; break;
+ }
+ if (min_depth==0) {
+ /* start with shallowest */
+ for (depth=0;depth<=32;depth++) {
+ if (visclass==TrueColor && depth==8 && !hp_cr_maps) {
+ /* Special case: try to get 8-bit PseudoColor before */
+ /* 8-bit TrueColor */
+ vis = get_visual( dpy, screen, 8, PseudoColor );
+ if (vis) {
+ return vis;
+ }
+ }
+ vis = get_visual( dpy, screen, depth, visclass );
+ if (vis) {
+ return vis;
+ }
+ }
+ }
+ else {
+ /* start with deepest */
+ for (depth=32;depth>=min_depth;depth--) {
+ if (visclass==TrueColor && depth==8 && !hp_cr_maps) {
+ /* Special case: try to get 8-bit PseudoColor before */
+ /* 8-bit TrueColor */
+ vis = get_visual( dpy, screen, 8, PseudoColor );
+ if (vis) {
+ return vis;
+ }
+ }
+ vis = get_visual( dpy, screen, depth, visclass );
+ if (vis) {
+ return vis;
+ }
+ }
+ }
+ }
+ }
+ else {
+ /* search for a specific visual class */
+ switch (preferred_class) {
+ case GLX_TRUE_COLOR_EXT: visclass = TrueColor; break;
+ case GLX_DIRECT_COLOR_EXT: visclass = DirectColor; break;
+ case GLX_PSEUDO_COLOR_EXT: visclass = PseudoColor; break;
+ case GLX_STATIC_COLOR_EXT: visclass = StaticColor; break;
+ case GLX_GRAY_SCALE_EXT: visclass = GrayScale; break;
+ case GLX_STATIC_GRAY_EXT: visclass = StaticGray; break;
+ default: return NULL;
+ }
+ if (min_depth==0) {
+ /* start with shallowest */
+ for (depth=0;depth<=32;depth++) {
+ vis = get_visual( dpy, screen, depth, visclass );
+ if (vis) {
+ return vis;
+ }
+ }
+ }
+ else {
+ /* start with deepest */
+ for (depth=32;depth>=min_depth;depth--) {
+ vis = get_visual( dpy, screen, depth, visclass );
+ if (vis) {
+ return vis;
+ }
+ }
+ }
+ }
+ }
+ else {
+ /* First see if the MESA_CI_VISUAL env var is defined */
+ vis = get_env_visual( dpy, screen, "MESA_CI_VISUAL" );
+ if (vis) {
+ return vis;
+ }
+ /* Otherwise, search for a suitable visual, starting with shallowest */
+ if (preferred_class==DONT_CARE) {
+ for (xclass=0;xclass<4;xclass++) {
+ switch (xclass) {
+ case 0: visclass = PseudoColor; break;
+ case 1: visclass = StaticColor; break;
+ case 2: visclass = GrayScale; break;
+ case 3: visclass = StaticGray; break;
+ }
+ /* try 8-bit up through 16-bit */
+ for (depth=8;depth<=16;depth++) {
+ vis = get_visual( dpy, screen, depth, visclass );
+ if (vis) {
+ return vis;
+ }
+ }
+ /* try min_depth up to 8-bit */
+ for (depth=min_depth;depth<8;depth++) {
+ vis = get_visual( dpy, screen, depth, visclass );
+ if (vis) {
+ return vis;
+ }
+ }
+ }
+ }
+ else {
+ /* search for a specific visual class */
+ switch (preferred_class) {
+ case GLX_TRUE_COLOR_EXT: visclass = TrueColor; break;
+ case GLX_DIRECT_COLOR_EXT: visclass = DirectColor; break;
+ case GLX_PSEUDO_COLOR_EXT: visclass = PseudoColor; break;
+ case GLX_STATIC_COLOR_EXT: visclass = StaticColor; break;
+ case GLX_GRAY_SCALE_EXT: visclass = GrayScale; break;
+ case GLX_STATIC_GRAY_EXT: visclass = StaticGray; break;
+ default: return NULL;
+ }
+ /* try 8-bit up through 16-bit */
+ for (depth=8;depth<=16;depth++) {
+ vis = get_visual( dpy, screen, depth, visclass );
+ if (vis) {
+ return vis;
+ }
+ }
+ /* try min_depth up to 8-bit */
+ for (depth=min_depth;depth<8;depth++) {
+ vis = get_visual( dpy, screen, depth, visclass );
+ if (vis) {
+ return vis;
+ }
+ }
+ }
+ }
+
+ /* didn't find a visual */
+ return NULL;
+}
+
+
+
+/*
+ * Find the deepest X over/underlay visual of at least min_depth.
+ * Input: dpy, screen - X display and screen number
+ * level - the over/underlay level
+ * trans_type - transparent pixel type: GLX_NONE_EXT,
+ * GLX_TRANSPARENT_RGB_EXT, GLX_TRANSPARENT_INDEX_EXT,
+ * or DONT_CARE
+ * trans_value - transparent pixel value or DONT_CARE
+ * min_depth - minimum visual depth
+ * preferred_class - preferred GLX visual class or DONT_CARE
+ * Return: pointer to an XVisualInfo or NULL.
+ */
+static XVisualInfo *choose_x_overlay_visual( Display *dpy, int scr,
+ int level, int trans_type,
+ int trans_value,
+ int min_depth,
+ int preferred_class )
+{
+ Atom overlayVisualsAtom;
+ OverlayInfo *overlay_info;
+ int numOverlaysPerScreen;
+ Status status;
+ Atom actualType;
+ int actualFormat;
+ unsigned long sizeData, bytesLeft;
+ int i;
+ XVisualInfo *deepvis;
+ int deepest;
+
+ /*DEBUG int tt, tv; */
+
+ switch (preferred_class) {
+ case GLX_TRUE_COLOR_EXT: preferred_class = TrueColor; break;
+ case GLX_DIRECT_COLOR_EXT: preferred_class = DirectColor; break;
+ case GLX_PSEUDO_COLOR_EXT: preferred_class = PseudoColor; break;
+ case GLX_STATIC_COLOR_EXT: preferred_class = StaticColor; break;
+ case GLX_GRAY_SCALE_EXT: preferred_class = GrayScale; break;
+ case GLX_STATIC_GRAY_EXT: preferred_class = StaticGray; break;
+ default: preferred_class = DONT_CARE;
+ }
+
+ /*
+ * The SERVER_OVERLAY_VISUALS property on the root window contains
+ * a list of overlay visuals. Get that list now.
+ */
+ overlayVisualsAtom = XInternAtom(dpy,"SERVER_OVERLAY_VISUALS", True);
+ if (overlayVisualsAtom == (Atom) None) {
+ return NULL;
+ }
+
+ status = XGetWindowProperty(dpy, RootWindow( dpy, scr ),
+ overlayVisualsAtom, 0L, (long) 10000, False,
+ overlayVisualsAtom, &actualType, &actualFormat,
+ &sizeData, &bytesLeft,
+ (unsigned char **) &overlay_info );
+
+ if (status != Success || actualType != overlayVisualsAtom ||
+ actualFormat != 32 || sizeData < 4) {
+ /* something went wrong */
+ return NULL;
+ }
+
+ /* Search for the deepest overlay which satisifies all criteria. */
+ deepest = min_depth;
+ deepvis = NULL;
+
+ numOverlaysPerScreen = (int) (sizeData / 4);
+ for (i=0;i<numOverlaysPerScreen;i++) {
+ XVisualInfo *vislist, vistemplate;
+ int count;
+ OverlayInfo *ov;
+ ov = overlay_info + i;
+
+ if (ov->layer!=level) {
+ /* failed overlay level criteria */
+ continue;
+ }
+ if (!(trans_type==DONT_CARE
+ || (trans_type==GLX_TRANSPARENT_INDEX_EXT
+ && ov->transparent_type>0)
+ || (trans_type==GLX_NONE_EXT && ov->transparent_type==0))) {
+ /* failed transparent pixel type criteria */
+ continue;
+ }
+ if (trans_value!=DONT_CARE && trans_value!=ov->value) {
+ /* failed transparent pixel value criteria */
+ continue;
+ }
+
+ /* get XVisualInfo and check the depth */
+ vistemplate.visualid = ov->overlay_visual;
+ vistemplate.screen = scr;
+ vislist = XGetVisualInfo( dpy, VisualIDMask | VisualScreenMask,
+ &vistemplate, &count );
+
+ if (count!=1) {
+ /* something went wrong */
+ continue;
+ }
+ if (preferred_class!=DONT_CARE && preferred_class!=vislist->CLASS) {
+ /* wrong visual class */
+ continue;
+ }
+
+ if (deepvis==NULL || vislist->depth > deepest) {
+ /* YES! found a satisfactory visual */
+ if (deepvis) {
+ free( deepvis );
+ }
+ deepest = vislist->depth;
+ deepvis = vislist;
+ /* DEBUG tt = ov->transparent_type;*/
+ /* DEBUG tv = ov->value; */
+ }
+ }
+
+/*DEBUG
+ if (deepvis) {
+ printf("chose 0x%x: layer=%d depth=%d trans_type=%d trans_value=%d\n",
+ deepvis->visualid, level, deepvis->depth, tt, tv );
+ }
+*/
+ return deepvis;
+}
+
+
+
+XVisualInfo *Fake_glXChooseVisual( Display *dpy, int screen, int *list )
+{
+ int *parselist;
+ XVisualInfo *vis;
+ int min_ci = 0;
+ int min_red=0, min_green=0, min_blue=0;
+ GLboolean rgb_flag = GL_FALSE;
+ GLboolean alpha_flag = GL_FALSE;
+ GLboolean double_flag = GL_FALSE;
+ GLboolean stereo_flag = GL_FALSE;
+ GLint depth_size = 0;
+ GLint stencil_size = 0;
+ GLint accum_size = 0;
+ int level = 0;
+ int visual_type = DONT_CARE;
+ int trans_type = DONT_CARE;
+ int trans_value = DONT_CARE;
+
+ parselist = list;
+
+ while (*parselist) {
+
+ switch (*parselist) {
+ case GLX_USE_GL:
+ /* ignore */
+ parselist++;
+ break;
+ case GLX_BUFFER_SIZE:
+ parselist++;
+ min_ci = *parselist++;
+ break;
+ case GLX_LEVEL:
+ parselist++;
+ level = *parselist++;
+ break;
+ case GLX_RGBA:
+ rgb_flag = GL_TRUE;
+ parselist++;
+ break;
+ case GLX_DOUBLEBUFFER:
+ double_flag = GL_TRUE;
+ parselist++;
+ break;
+ case GLX_STEREO:
+ stereo_flag = GL_TRUE;
+ return NULL;
+ case GLX_AUX_BUFFERS:
+ /* ignore */
+ parselist++;
+ parselist++;
+ break;
+ case GLX_RED_SIZE:
+ parselist++;
+ min_red = *parselist++;
+ break;
+ case GLX_GREEN_SIZE:
+ parselist++;
+ min_green = *parselist++;
+ break;
+ case GLX_BLUE_SIZE:
+ parselist++;
+ min_blue = *parselist++;
+ break;
+ case GLX_ALPHA_SIZE:
+ parselist++;
+ {
+ GLint size = *parselist++;
+ alpha_flag = size>0 ? 1 : 0;
+ }
+ break;
+ case GLX_DEPTH_SIZE:
+ parselist++;
+ depth_size = *parselist++;
+ break;
+ case GLX_STENCIL_SIZE:
+ parselist++;
+ stencil_size = *parselist++;
+ break;
+ case GLX_ACCUM_RED_SIZE:
+ case GLX_ACCUM_GREEN_SIZE:
+ case GLX_ACCUM_BLUE_SIZE:
+ case GLX_ACCUM_ALPHA_SIZE:
+ parselist++;
+ {
+ GLint size = *parselist++;
+ accum_size = MAX2( accum_size, size );
+ }
+ break;
+
+ /*
+ * GLX_EXT_visual_info extension
+ */
+ case GLX_X_VISUAL_TYPE_EXT:
+ parselist++;
+ visual_type = *parselist++;
+ break;
+ case GLX_TRANSPARENT_TYPE_EXT:
+ parselist++;
+ trans_type = *parselist++;
+ break;
+ case GLX_TRANSPARENT_INDEX_VALUE_EXT:
+ parselist++;
+ trans_value = *parselist++;
+ break;
+ case GLX_TRANSPARENT_RED_VALUE_EXT:
+ case GLX_TRANSPARENT_GREEN_VALUE_EXT:
+ case GLX_TRANSPARENT_BLUE_VALUE_EXT:
+ case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
+ /* ignore */
+ parselist++;
+ parselist++;
+ break;
+
+ case None:
+ break;
+ default:
+ /* undefined attribute */
+ return NULL;
+ }
+ }
+
+ /*
+ * Since we're only simulating the GLX extension this function will never
+ * find any real GL visuals. Instead, all we can do is try to find an RGB
+ * or CI visual of appropriate depth. Other requested attributes such as
+ * double buffering, depth buffer, etc. will be associated with the X
+ * visual and stored in the VisualTable[].
+ */
+ if (level==0) {
+ /* normal color planes */
+ if (rgb_flag) {
+ /* Get an RGB visual */
+ int min_rgb = min_red + min_green + min_blue;
+ if (min_rgb>1 && min_rgb<8) {
+ /* a special case to be sure we can get a monochrome visual */
+ min_rgb = 1;
+ }
+ vis = choose_x_visual( dpy, screen, rgb_flag, min_rgb, visual_type );
+ }
+ else {
+ /* Get a color index visual */
+ vis = choose_x_visual( dpy, screen, rgb_flag, min_ci, visual_type );
+ accum_size = 0;
+ }
+ }
+ else {
+ /* over/underlay planes */
+ vis = choose_x_overlay_visual( dpy, screen, level, trans_type,
+ trans_value, min_ci, visual_type );
+ }
+
+ if (vis) {
+ if (!save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag,
+ stereo_flag,
+ depth_size, stencil_size, accum_size, level ))
+ return NULL;
+ }
+
+ return vis;
+}
+
+
+
+
+GLXContext Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
+ GLXContext share_list, Bool direct )
+{
+ XMesaVisual glxvis;
+ XMesaContext xmctx;
+
+ /* deallocate unused windows/buffers */
+ XMesaGarbageCollect();
+
+ glxvis = find_glx_visual( dpy, visinfo );
+ if (!glxvis) {
+ /* This visual wasn't found with glXChooseVisual() */
+ glxvis = create_glx_visual( dpy, visinfo );
+ if (!glxvis) {
+ /* unusable visual */
+ return NULL;
+ }
+ }
+
+ xmctx = XMesaCreateContext( glxvis, (XMesaContext) share_list );
+ if (xmctx) {
+ /* set the direct/indirect flag */
+ xmctx->direct = direct;
+ }
+ return (GLXContext) xmctx;
+}
+
+
+static GLXDrawable MakeCurrent_PrevDrawable = 0;
+static GLXContext MakeCurrent_PrevContext = 0;
+static XMesaBuffer MakeCurrent_PrevBuffer = 0;
+
+Bool Fake_glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx )
+{
+ if (ctx && drawable) {
+ XMesaBuffer buffer;
+
+ if (drawable==MakeCurrent_PrevDrawable && ctx==MakeCurrent_PrevContext) {
+ buffer = MakeCurrent_PrevBuffer;
+ }
+ else {
+ buffer = XMesaFindBuffer( dpy, drawable );
+ }
+ if (!buffer) {
+ /* drawable must be a new window! */
+ buffer = XMesaCreateWindowBuffer2( ctx->xm_visual, drawable, ctx );
+ if (!buffer) {
+ /* Out of memory, or context/drawable depth mismatch */
+ return False;
+ }
+ }
+ MakeCurrent_PrevContext = ctx;
+ MakeCurrent_PrevDrawable = drawable;
+ MakeCurrent_PrevBuffer = buffer;
+
+ /* Now make current! */
+ return (Bool) XMesaMakeCurrent( (XMesaContext) ctx, buffer );
+ }
+ else if (!ctx && !drawable) {
+ /* release current context w/out assigning new one. */
+ XMesaMakeCurrent( NULL, NULL );
+ MakeCurrent_PrevContext = 0;
+ MakeCurrent_PrevDrawable = 0;
+ MakeCurrent_PrevBuffer = 0;
+ return True;
+ }
+ else {
+ /* ctx XOR drawable is NULL, this is an error */
+ return False;
+ }
+}
+
+
+
+GLXPixmap Fake_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo,
+ Pixmap pixmap )
+{
+ XMesaVisual v;
+ XMesaBuffer b;
+
+ v = find_glx_visual( dpy, visinfo );
+ if (!v) {
+ v = create_glx_visual( dpy, visinfo );
+ if (!v) {
+ /* unusable visual */
+ return 0;
+ }
+ }
+
+ b = XMesaCreatePixmapBuffer( v, pixmap, 0 );
+ if (!b) {
+ return 0;
+ }
+ return b->frontbuffer;
+}
+
+
+#ifdef GLX_MESA_pixmap_colormap
+
+GLXPixmap Fake_glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo,
+ Pixmap pixmap, Colormap cmap )
+{
+ XMesaVisual v;
+ XMesaBuffer b;
+
+ v = find_glx_visual( dpy, visinfo );
+ if (!v) {
+ v = create_glx_visual( dpy, visinfo );
+ if (!v) {
+ /* unusable visual */
+ return 0;
+ }
+ }
+
+ b = XMesaCreatePixmapBuffer( v, pixmap, cmap );
+ if (!b) {
+ return 0;
+ }
+ return b->frontbuffer;
+}
+
+#endif
+
+
+void Fake_glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap )
+{
+ XMesaBuffer b = XMesaFindBuffer(dpy, pixmap);
+ if (b) {
+ XMesaDestroyBuffer(b);
+ }
+ else if (getenv("MESA_DEBUG")) {
+ fprintf( stderr, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n");
+ }
+}
+
+
+void Fake_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
+ GLuint mask )
+{
+ XMesaContext xm_src = (XMesaContext) src;
+ XMesaContext xm_dst = (XMesaContext) dst;
+ (void) dpy;
+ gl_copy_context( xm_src->gl_ctx, xm_dst->gl_ctx, mask );
+}
+
+
+
+Bool Fake_glXQueryExtension( Display *dpy, int *errorb, int *event )
+{
+ /* Mesa's GLX isn't really an X extension but we try to act like one. */
+ (void) dpy;
+ (void) errorb;
+ (void) event;
+ return True;
+}
+
+
+void _kw_ungrab_all( Display *dpy )
+{
+ XUngrabPointer( dpy, CurrentTime );
+ XUngrabKeyboard( dpy, CurrentTime );
+}
+
+
+void Fake_glXDestroyContext( Display *dpy, GLXContext ctx )
+{
+ (void) dpy;
+ MakeCurrent_PrevContext = 0;
+ MakeCurrent_PrevDrawable = 0;
+ MakeCurrent_PrevBuffer = 0;
+ XMesaDestroyContext( (XMesaContext) ctx );
+ XMesaGarbageCollect();
+}
+
+
+
+Bool Fake_glXIsDirect( Display *dpy, GLXContext ctx )
+{
+ (void) dpy;
+ return ((XMesaContext) ctx)->direct;
+}
+
+
+
+void Fake_glXSwapBuffers( Display *dpy, GLXDrawable drawable )
+{
+ XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
+ static GLXDrawable last = 0;
+ static Window window = 0;
+ if (drawable != last && 0) {
+ XSetWindowAttributes cwa;
+
+ _kw_ungrab_all( dpy );
+ cwa.override_redirect = 0;
+ XChangeWindowAttributes( dpy, drawable, CWOverrideRedirect,
+ &cwa );
+/* printf("KW: Ungrab display %s\n", DisplayString(dpy)); */
+
+
+/* last = drawable; */
+
+
+ if (!window) {
+ XSetWindowAttributes cwa;
+
+ if ((window = XCreateSimpleWindow( dpy,
+ RootWindow( dpy, 0 ),
+ 10,10,100,100, 0,
+ WhitePixel( dpy, 0 ),
+ BlackPixel( dpy, 0 ))) == 0)
+ {
+ printf("Failed to open radar window\n");
+ abort();
+ }
+
+ cwa.event_mask = (PointerMotionMask |
+ ButtonPressMask |
+ ButtonReleaseMask |
+ KeyPressMask |
+ KeyReleaseMask |
+ ExposureMask );
+
+ XChangeWindowAttributes( dpy, window,
+ CWEventMask,
+ &cwa );
+
+ XMapWindow( dpy, window );
+ XFlush( dpy );
+ }
+ }
+ if (buffer) {
+ XMesaSwapBuffers(buffer);
+ }
+ else if (getenv("MESA_DEBUG")) {
+ fprintf(stderr, "Mesa Warning: glXSwapBuffers: invalid drawable\n");
+ }
+}
+
+
+void Fake_glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable,
+ int x, int y, int width, int height )
+{
+ XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
+ if (buffer) {
+ XMesaCopySubBuffer(buffer, x, y, width, height);
+ }
+ else if (getenv("MESA_DEBUG")) {
+ fprintf(stderr, "Mesa Warning: glXCopySubBufferMESA: invalid drawable\n");
+ }
+}
+
+
+
+Bool Fake_glXQueryVersion( Display *dpy, int *maj, int *min )
+{
+ (void) dpy;
+ /* Return GLX version, not Mesa version */
+ *maj = 1;
+ *min = 1;
+ return True;
+}
+
+
+
+/*
+ * Query the GLX attributes of the given XVisualInfo.
+ */
+int Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo,
+ int attrib, int *value )
+{
+ XMesaVisual glxvis;
+
+ glxvis = find_glx_visual( dpy, visinfo );
+ if (!glxvis) {
+ /* this visual wasn't obtained with glXChooseVisual */
+ glxvis = create_glx_visual( dpy, visinfo );
+ if (!glxvis) {
+ /* this visual can't be used for GL rendering */
+ if (attrib==GLX_USE_GL) {
+ *value = (int) False;
+ return 0;
+ }
+ else {
+ /*fprintf( stderr, "Mesa: Error in glXGetConfig: bad visual\n");*/
+ return GLX_BAD_VISUAL;
+ }
+ }
+ }
+
+ switch(attrib) {
+ case GLX_USE_GL:
+ *value = (int) True;
+ return 0;
+ case GLX_BUFFER_SIZE:
+ *value = visinfo->depth;
+ return 0;
+ case GLX_LEVEL:
+ *value = glxvis->level;
+ return 0;
+ case GLX_RGBA:
+ if (glxvis->gl_visual->RGBAflag) {
+ *value = True;
+ }
+ else {
+ *value = False;
+ }
+ return 0;
+ case GLX_DOUBLEBUFFER:
+ *value = (int) glxvis->gl_visual->DBflag;
+ return 0;
+ case GLX_STEREO:
+ *value = (int) glxvis->gl_visual->StereoFlag;
+ return 0;
+ case GLX_AUX_BUFFERS:
+ *value = (int) False;
+ return 0;
+ case GLX_RED_SIZE:
+ *value = glxvis->gl_visual->RedBits;
+ return 0;
+ case GLX_GREEN_SIZE:
+ *value = glxvis->gl_visual->GreenBits;
+ return 0;
+ case GLX_BLUE_SIZE:
+ *value = glxvis->gl_visual->BlueBits;
+ return 0;
+ case GLX_ALPHA_SIZE:
+ *value = glxvis->gl_visual->AlphaBits;
+ return 0;
+ case GLX_DEPTH_SIZE:
+ *value = glxvis->gl_visual->DepthBits;
+ return 0;
+ case GLX_STENCIL_SIZE:
+ *value = glxvis->gl_visual->StencilBits;
+ return 0;
+ case GLX_ACCUM_RED_SIZE:
+ case GLX_ACCUM_GREEN_SIZE:
+ case GLX_ACCUM_BLUE_SIZE:
+ *value = glxvis->gl_visual->AccumBits;
+ return 0;
+ case GLX_ACCUM_ALPHA_SIZE:
+ if (glxvis->gl_visual->AlphaBits > 0)
+ *value = glxvis->gl_visual->AccumBits;
+ else
+ *value = 0;
+ return 0;
+
+ /*
+ * GLX_EXT_visual_info extension
+ */
+ case GLX_X_VISUAL_TYPE_EXT:
+ switch (glxvis->visinfo->CLASS) {
+ case StaticGray: *value = GLX_STATIC_GRAY_EXT; return 0;
+ case GrayScale: *value = GLX_GRAY_SCALE_EXT; return 0;
+ case StaticColor: *value = GLX_STATIC_GRAY_EXT; return 0;
+ case PseudoColor: *value = GLX_PSEUDO_COLOR_EXT; return 0;
+ case TrueColor: *value = GLX_TRUE_COLOR_EXT; return 0;
+ case DirectColor: *value = GLX_DIRECT_COLOR_EXT; return 0;
+ }
+ return 0;
+ case GLX_TRANSPARENT_TYPE_EXT:
+ if (glxvis->level==0) {
+ /* normal planes */
+ *value = GLX_NONE_EXT;
+ }
+ else if (glxvis->level>0) {
+ /* overlay */
+ if (glxvis->gl_visual->RGBAflag) {
+ *value = GLX_TRANSPARENT_RGB_EXT;
+ }
+ else {
+ *value = GLX_TRANSPARENT_INDEX_EXT;
+ }
+ }
+ else if (glxvis->level<0) {
+ /* underlay */
+ *value = GLX_NONE_EXT;
+ }
+ return 0;
+ case GLX_TRANSPARENT_INDEX_VALUE_EXT:
+ {
+ int pixel = transparent_pixel( glxvis );
+ if (pixel>=0) {
+ *value = pixel;
+ }
+ /* else undefined */
+ }
+ return 0;
+ case GLX_TRANSPARENT_RED_VALUE_EXT:
+ /* undefined */
+ return 0;
+ case GLX_TRANSPARENT_GREEN_VALUE_EXT:
+ /* undefined */
+ return 0;
+ case GLX_TRANSPARENT_BLUE_VALUE_EXT:
+ /* undefined */
+ return 0;
+ case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
+ /* undefined */
+ return 0;
+
+ /*
+ * Extensions
+ */
+ default:
+ return GLX_BAD_ATTRIBUTE;
+ }
+}
+
+
+
+GLXContext Fake_glXGetCurrentContext( void )
+{
+ return (GLXContext) XMesaGetCurrentContext();
+}
+
+
+
+GLXDrawable Fake_glXGetCurrentDrawable( void )
+{
+ XMesaBuffer b = XMesaGetCurrentBuffer();
+ if (b) {
+ return b->frontbuffer;
+ }
+ else {
+ return 0;
+ }
+}
+
+
+void Fake_glXWaitGL( void )
+{
+ XMesaContext xmesa = XMesaGetCurrentContext();
+ XMesaFlush( xmesa );
+}
+
+
+
+void Fake_glXWaitX( void )
+{
+ XMesaContext xmesa = XMesaGetCurrentContext();
+ XMesaFlush( xmesa );
+}
+
+
+
+#define EXTENSIONS "GLX_MESA_pixmap_colormap GLX_EXT_visual_info GLX_MESA_release_buffers GLX_MESA_copy_sub_buffer GLX_SGI_video_sync"
+
+
+/* GLX 1.1 and later */
+const char *Fake_glXQueryExtensionsString( Display *dpy, int screen )
+{
+ static char *extensions = EXTENSIONS;
+ (void) dpy;
+ (void) screen;
+ return extensions;
+}
+
+
+
+/* GLX 1.1 and later */
+const char *Fake_glXQueryServerString( Display *dpy, int screen, int name )
+{
+ static char *extensions = EXTENSIONS;
+ static char *vendor = "Brian Paul";
+ static char *version = "1.1 Mesa 3.0";
+
+ (void) dpy;
+ (void) screen;
+
+ switch (name) {
+ case GLX_EXTENSIONS:
+ return extensions;
+ case GLX_VENDOR:
+ return vendor;
+ case GLX_VERSION:
+ return version;
+ default:
+ return NULL;
+ }
+}
+
+
+
+/* GLX 1.1 and later */
+const char *Fake_glXGetClientString( Display *dpy, int name )
+{
+ static char *extensions = EXTENSIONS;
+ static char *vendor = "Brian Paul";
+ static char *version = "1.1 Mesa 3.0";
+
+ (void) dpy;
+
+ switch (name) {
+ case GLX_EXTENSIONS:
+ return extensions;
+ case GLX_VENDOR:
+ return vendor;
+ case GLX_VERSION:
+ return version;
+ default:
+ return NULL;
+ }
+}
+
+
+
+/*
+ * Release the depth, stencil, accum buffers attached to a GLXDrawable
+ * (a window or pixmap) prior to destroying the GLXDrawable.
+ */
+Bool Fake_glXReleaseBuffersMESA( Display *dpy, GLXDrawable d )
+{
+ XMesaBuffer b = XMesaFindBuffer(dpy, d);
+ if (b) {
+ XMesaDestroyBuffer(b);
+ return True;
+ }
+ return False;
+}
+
+
+/* Silence compiler warnings */
+void Fake_glXDummyFunc( void )
+{
+ (void) kernel8;
+ (void) DitherValues;
+ (void) HPCR_DRGB;
+ (void) kernel1;
+}
diff --git a/src/mesa/drivers/x11/glxapi.c b/src/mesa/drivers/x11/glxapi.c
new file mode 100644
index 0000000000..b65bada72b
--- /dev/null
+++ b/src/mesa/drivers/x11/glxapi.c
@@ -0,0 +1,405 @@
+/* $Id: glxapi.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+/*
+ * GLX API functions which either call fake or real GLX implementations
+ *
+ * To enable real GLX encoding the REALGLX preprocessor symbol should be
+ * defined on the command line.
+ */
+
+
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include "GL/glx.h"
+#include "fakeglx.h"
+#include "realglx.h"
+
+
+#ifdef REALGLX
+static Display *CurrentDisplay = NULL;
+#endif
+
+
+/*
+ * This functions determines whether a call to a glX*() function should
+ * be routed to the "fake" (Mesa) or "real" (GLX-encoder) functions.
+ * Input: dpy - the X display.
+ * Return: GL_TRUE if the given display supports the real GLX extension,
+ * GL_FALSE otherwise.
+ */
+static GLboolean display_has_glx( Display *dpy )
+{
+ /* TODO: we should use a lookup table to avoid calling XQueryExtension
+ * every time.
+ */
+ int ignore;
+ if (XQueryExtension( dpy, "GLX", &ignore, &ignore, &ignore )) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
+
+
+XVisualInfo *glXChooseVisual( Display *dpy, int screen, int *list )
+{
+#ifdef REALGLX
+ if (display_has_glx(dpy))
+ return Real_glXChooseVisual( dpy, screen, list );
+ else
+#endif
+ return Fake_glXChooseVisual( dpy, screen, list );
+}
+
+
+
+int glXGetConfig( Display *dpy, XVisualInfo *visinfo, int attrib, int *value )
+{
+#ifdef REALGLX
+ if (display_has_glx(dpy))
+ return Real_glXGetConfig( dpy, visinfo, attrib, value );
+ else
+#endif
+ return Fake_glXGetConfig( dpy, visinfo, attrib, value );
+}
+
+
+
+GLXContext glXCreateContext( Display *dpy, XVisualInfo *visinfo,
+ GLXContext shareList, Bool direct )
+{
+#ifdef REALGLX
+ if (display_has_glx(dpy))
+ return Real_glXCreateContext( dpy, visinfo, shareList, direct );
+ else
+#endif
+ return Fake_glXCreateContext( dpy, visinfo, shareList, direct );
+}
+
+
+
+void glXDestroyContext( Display *dpy, GLXContext ctx )
+{
+#ifdef REALGLX
+ if (display_has_glx(dpy))
+ Real_glXDestroyContext( dpy, ctx );
+ else
+#endif
+ Fake_glXDestroyContext( dpy, ctx );
+}
+
+
+
+void glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
+ GLuint mask )
+{
+#ifdef REALGLX
+ if (display_has_glx(dpy))
+ Real_glXCopyContext( dpy, src, dst, mask );
+ else
+#endif
+ Fake_glXCopyContext( dpy, src, dst, mask );
+}
+
+
+
+Bool glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx )
+{
+#ifdef REALGLX
+ if (display_has_glx(dpy)) {
+ if (Real_glXMakeCurrent( dpy, drawable, ctx )) {
+ CurrentDisplay = dpy;
+ return True;
+ }
+ else {
+ return False;
+ }
+ }
+ else {
+ if (Fake_glXMakeCurrent( dpy, drawable, ctx )) {
+ CurrentDisplay = dpy;
+ return True;
+ }
+ else {
+ return False;
+ }
+ }
+#else
+ return Fake_glXMakeCurrent( dpy, drawable, ctx );
+#endif
+}
+
+
+
+GLXContext glXGetCurrentContext( void )
+{
+#ifdef REALGLX
+ if (display_has_glx(CurrentDisplay))
+ return Real_glXGetCurrentContext();
+ else
+#endif
+ return Fake_glXGetCurrentContext();
+}
+
+
+
+GLXDrawable glXGetCurrentDrawable( void )
+{
+#ifdef REALGLX
+ if (display_has_glx(CurrentDisplay))
+ return Real_glXGetCurrentDrawable();
+ else
+#endif
+ return Fake_glXGetCurrentDrawable();
+}
+
+
+
+GLXPixmap glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo,
+ Pixmap pixmap )
+{
+#ifdef REALGLX
+ if (display_has_glx(dpy))
+ return Real_glXCreateGLXPixmap( dpy, visinfo, pixmap );
+ else
+#endif
+ return Fake_glXCreateGLXPixmap( dpy, visinfo, pixmap );
+}
+
+
+void glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap )
+{
+#ifdef REALGLX
+ if (display_has_glx(dpy))
+ Real_glXDestroyGLXPixmap( dpy, pixmap );
+ else
+#endif
+ Fake_glXDestroyGLXPixmap( dpy, pixmap );
+}
+
+
+
+Bool glXQueryExtension( Display *dpy, int *errorb, int *event )
+{
+#ifdef REALGLX
+ if (display_has_glx(dpy))
+ return Real_glXQueryExtension( dpy, errorb, event );
+ else
+#endif
+ return Fake_glXQueryExtension( dpy, errorb, event );
+}
+
+
+
+Bool glXIsDirect( Display *dpy, GLXContext ctx )
+{
+#ifdef REALGLX
+ if (display_has_glx(dpy))
+ return Real_glXIsDirect( dpy, ctx );
+ else
+#endif
+ return Fake_glXIsDirect( dpy, ctx );
+}
+
+
+
+void glXSwapBuffers( Display *dpy, GLXDrawable drawable )
+{
+#ifdef REALGLX
+ if (display_has_glx(dpy))
+ Real_glXSwapBuffers( dpy, drawable );
+ else
+#endif
+ Fake_glXSwapBuffers( dpy, drawable );
+}
+
+
+
+void glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable,
+ int x, int y, int width, int height )
+{
+#ifdef REALGLX
+ /* can't implement! */
+ return;
+#endif
+ Fake_glXCopySubBufferMESA( dpy, drawable, x, y, width, height );
+}
+
+
+
+Bool glXQueryVersion( Display *dpy, int *maj, int *min )
+{
+#ifdef REALGLX
+ if (display_has_glx(dpy))
+ return Real_glXQueryVersion( dpy, maj, min );
+ else
+#endif
+ return Fake_glXQueryVersion( dpy, maj, min );
+}
+
+
+
+void glXUseXFont( Font font, int first, int count, int listBase )
+{
+#ifdef REALGLX
+ if (display_has_glx(CurrentDisplay))
+ Real_glXUseXFont( font, first, count, listBase );
+ else
+#endif
+ Fake_glXUseXFont( font, first, count, listBase );
+}
+
+
+void glXWaitGL( void )
+{
+#ifdef REALGLX
+ if (display_has_glx(CurrentDisplay))
+ Real_glXWaitGL();
+ else
+#endif
+ Fake_glXWaitGL();
+}
+
+
+
+void glXWaitX( void )
+{
+#ifdef REALGLX
+ if (display_has_glx(CurrentDisplay))
+ Real_glXWaitX();
+ else
+#endif
+ Fake_glXWaitX();
+}
+
+
+
+/* GLX 1.1 and later */
+const char *glXQueryExtensionsString( Display *dpy, int screen )
+{
+#ifdef REALGLX
+ if (display_has_glx(dpy))
+ return Real_glXQueryExtensionsString( dpy, screen );
+ else
+#endif
+ return Fake_glXQueryExtensionsString( dpy, screen );
+}
+
+
+
+/* GLX 1.1 and later */
+const char *glXQueryServerString( Display *dpy, int screen, int name )
+{
+#ifdef REALGLX
+ if (display_has_glx(dpy))
+ return Real_glXQueryServerString( dpy, screen, name );
+ else
+#endif
+ return Fake_glXQueryServerString( dpy, screen, name );
+}
+
+
+
+/* GLX 1.1 and later */
+const char *glXGetClientString( Display *dpy, int name )
+{
+#ifdef REALGLX
+ if (display_has_glx(dpy))
+ return Real_glXGetClientString( dpy, name );
+ else
+#endif
+ return Fake_glXGetClientString( dpy, name );
+}
+
+
+
+#ifdef GLX_MESA_release_buffers
+Bool glXReleaseBuffersMESA( Display *dpy, Window w )
+{
+#ifdef REALGLX
+ if (display_has_glx(dpy))
+ return GL_FALSE;
+ else
+#endif
+ return Fake_glXReleaseBuffersMESA( dpy, w );
+}
+#endif
+
+
+#ifdef GLX_MESA_pixmap_colormap
+GLXPixmap glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo,
+ Pixmap pixmap, Colormap cmap )
+{
+#ifdef REALGLX
+ if (display_has_glx(dpy))
+ return 0;
+ else
+#endif
+ return Fake_glXCreateGLXPixmapMESA( dpy, visinfo, pixmap, cmap );
+}
+#endif
+
+
+
+#ifdef GLX_SGI_video_sync
+
+/*
+ * This function doesn't really do anything. But, at least one
+ * application uses the function so this stub is useful.
+ */
+int glXGetVideoSyncSGI(unsigned int *count)
+{
+ static unsigned int counter = 0;
+ *count = counter++;
+ return 0;
+}
+
+
+/*
+ * Again, this is really just a stub function.
+ */
+int glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
+{
+ static unsigned int counter = 0;
+ while (counter % divisor != remainder)
+ counter++;
+ *count = counter;
+ return 0;
+}
+
+#endif
diff --git a/src/mesa/drivers/x11/realglx.c b/src/mesa/drivers/x11/realglx.c
new file mode 100644
index 0000000000..79a280419a
--- /dev/null
+++ b/src/mesa/drivers/x11/realglx.c
@@ -0,0 +1,239 @@
+/* $Id: realglx.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+/*
+ * Real GLX-encoder functions. Called from glxapi.c
+ *
+ * Steven Parker's code for the GLX client API functions should be
+ * put in this file.
+ *
+ * Also, the main API functions in api.c should somehow hook into the
+ * GLX-encoding functions...
+ */
+
+
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include "realglx.h"
+
+
+
+XVisualInfo *Real_glXChooseVisual( Display *dpy, int screen, int *list )
+{
+ (void) dpy;
+ (void) screen;
+ (void) list;
+ return 0;
+}
+
+
+
+int Real_glXGetConfig( Display *dpy, XVisualInfo *visinfo,
+ int attrib, int *value )
+{
+ (void) dpy;
+ (void) visinfo;
+ (void) attrib;
+ (void) value;
+ return 0;
+}
+
+
+
+GLXContext Real_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
+ GLXContext shareList, Bool direct )
+{
+ (void) dpy;
+ (void) visinfo;
+ (void) shareList;
+ (void) direct;
+ return 0;
+}
+
+
+
+void Real_glXDestroyContext( Display *dpy, GLXContext ctx )
+{
+ (void) dpy;
+ (void) ctx;
+}
+
+
+
+void Real_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
+ GLuint mask )
+{
+ (void) dpy;
+ (void) src;
+ (void) dst;
+ (void) mask;
+}
+
+
+
+Bool Real_glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx )
+{
+ (void) dpy;
+ (void) drawable;
+ (void) ctx;
+ return 0;
+}
+
+
+
+GLXContext Real_glXGetCurrentContext( void )
+{
+ return 0;
+}
+
+
+
+GLXDrawable Real_glXGetCurrentDrawable( void )
+{
+ return 0;
+}
+
+
+
+GLXPixmap Real_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo,
+ Pixmap pixmap )
+{
+ (void) dpy;
+ (void) visinfo;
+ (void) pixmap;
+ return 0;
+}
+
+
+void Real_glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap )
+{
+ (void) dpy;
+ (void) pixmap;
+}
+
+
+
+Bool Real_glXQueryExtension( Display *dpy, int *errorb, int *event )
+{
+ (void) dpy;
+ (void) errorb;
+ (void) event;
+ return 0;
+}
+
+
+
+Bool Real_glXIsDirect( Display *dpy, GLXContext ctx )
+{
+ (void) dpy;
+ (void) ctx;
+ return 0;
+}
+
+
+
+void Real_glXSwapBuffers( Display *dpy, GLXDrawable drawable )
+{
+ (void) dpy;
+ (void) drawable;
+}
+
+
+
+Bool Real_glXQueryVersion( Display *dpy, int *maj, int *min )
+{
+ (void) dpy;
+ (void) maj;
+ (void) min;
+ return 0;
+}
+
+
+
+void Real_glXUseXFont( Font font, int first, int count, int listBase )
+{
+ (void) font;
+ (void) first;
+ (void) count;
+ (void) listBase;
+}
+
+
+typedef struct {
+ struct {
+ int major_opcode;
+ } codes;
+
+
+
+} XExtDisplayInfo;
+
+
+void Real_glXWaitGL( void )
+{
+}
+
+
+
+void Real_glXWaitX( void )
+{
+}
+
+
+
+/* GLX 1.1 and later */
+const char *Real_glXQueryExtensionsString( Display *dpy, int screen )
+{
+ (void) dpy;
+ (void) screen;
+ return 0;
+}
+
+
+
+/* GLX 1.1 and later */
+const char *Real_glXQueryServerString( Display *dpy, int screen, int name )
+{
+ (void) dpy;
+ (void) screen;
+ (void) name;
+ return 0;
+}
+
+
+
+/* GLX 1.1 and later */
+const char *Real_glXGetClientString( Display *dpy, int name )
+{
+ (void) dpy;
+ (void) name;
+ return 0;
+}
diff --git a/src/mesa/drivers/x11/realglx.h b/src/mesa/drivers/x11/realglx.h
new file mode 100644
index 0000000000..9587db60c9
--- /dev/null
+++ b/src/mesa/drivers/x11/realglx.h
@@ -0,0 +1,111 @@
+/* $Id: realglx.h,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef REALGLX_H
+#define REALGLX_H
+
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include "GL/glx.h"
+
+
+
+extern XVisualInfo *Real_glXChooseVisual( Display *dpy,
+ int screen, int *list );
+
+
+extern int Real_glXGetConfig( Display *dpy, XVisualInfo *visinfo,
+ int attrib, int *value );
+
+
+extern GLXContext Real_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
+ GLXContext shareList, Bool direct );
+
+
+extern void Real_glXDestroyContext( Display *dpy, GLXContext ctx );
+
+
+extern void Real_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
+ GLuint mask );
+
+
+extern Bool Real_glXMakeCurrent( Display *dpy, GLXDrawable drawable,
+ GLXContext ctx );
+
+
+extern GLXContext Real_glXGetCurrentContext( void );
+
+
+extern GLXDrawable Real_glXGetCurrentDrawable( void );
+
+
+extern GLXPixmap Real_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo,
+ Pixmap pixmap );
+
+
+extern void Real_glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap );
+
+
+extern Bool Real_glXQueryExtension( Display *dpy, int *errorb, int *event );
+
+
+extern Bool Real_glXIsDirect( Display *dpy, GLXContext ctx );
+
+
+extern void Real_glXSwapBuffers( Display *dpy, GLXDrawable drawable );
+
+
+extern Bool Real_glXQueryVersion( Display *dpy, int *maj, int *min );
+
+
+extern void Real_glXUseXFont( Font font, int first, int count, int listBase );
+
+
+extern void Real_glXWaitGL( void );
+
+
+extern void Real_glXWaitX( void );
+
+
+/* GLX 1.1 and later */
+extern const char *Real_glXQueryExtensionsString( Display *dpy, int screen );
+
+
+/* GLX 1.1 and later */
+extern const char *Real_glXQueryServerString( Display *dpy, int screen,
+ int name );
+
+
+/* GLX 1.1 and later */
+extern const char *Real_glXGetClientString( Display *dpy, int name );
+
+
+#endif
diff --git a/src/mesa/drivers/x11/xfonts.c b/src/mesa/drivers/x11/xfonts.c
new file mode 100644
index 0000000000..c0e0a5fcd0
--- /dev/null
+++ b/src/mesa/drivers/x11/xfonts.c
@@ -0,0 +1,398 @@
+/* $Id: xfonts.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+/* xfonts.c -- glXUseXFont() for Mesa written by
+ * Copyright (C) 1995 Thorsten.Ohl @ Physik.TH-Darmstadt.de
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include "GL/gl.h"
+#include "GL/glx.h"
+#include "GL/xmesa.h"
+#include "context.h"
+#include "fakeglx.h"
+#include "macros.h"
+#include "xmesaP.h"
+
+/* Some debugging info. */
+
+#ifdef DEBUG
+#undef _R
+#undef _G
+#undef _B
+#include <ctype.h>
+
+int debug_xfonts = 0;
+
+static void
+dump_char_struct (XCharStruct *ch, char *prefix)
+{
+ printf ("%slbearing = %d, rbearing = %d, width = %d\n",
+ prefix, ch->lbearing, ch->rbearing, ch->width);
+ printf ("%sascent = %d, descent = %d, attributes = %u\n",
+ prefix, ch->ascent, ch->descent, (unsigned int) ch->attributes);
+}
+
+static void
+dump_font_struct (XFontStruct *font)
+{
+ printf ("ascent = %d, descent = %d\n", font->ascent, font->descent);
+ printf ("char_or_byte2 = (%u,%u)\n",
+ font->min_char_or_byte2, font->max_char_or_byte2);
+ printf ("byte1 = (%u,%u)\n", font->min_byte1, font->max_byte1);
+ printf ("all_chars_exist = %s\n", font->all_chars_exist ? "True" :
+"False");
+ printf ("default_char = %c (\\%03o)\n",
+ (char) (isprint (font->default_char) ? font->default_char : ' '),
+ font->default_char);
+ dump_char_struct (&font->min_bounds, "min> ");
+ dump_char_struct (&font->max_bounds, "max> ");
+#if 0
+ for (c = font->min_char_or_byte2; c <= font->max_char_or_byte2; c++)
+ {
+ char prefix[8];
+ sprintf (prefix, "%d> ", c);
+ dump_char_struct (&font->per_char[c], prefix);
+ }
+#endif
+}
+
+static void
+dump_bitmap (unsigned int width, unsigned int height, GLubyte *bitmap)
+{
+ unsigned int x, y;
+
+ printf (" ");
+ for (x = 0; x < 8*width; x++)
+ printf ("%o", 7 - (x % 8));
+ putchar ('\n');
+ for (y = 0; y < height; y++)
+ {
+ printf ("%3o:", y);
+ for (x = 0; x < 8*width; x++)
+ putchar ((bitmap[width*(height - y - 1) + x/8] & (1 << (7 - (x %
+8))))
+ ? '*' : '.');
+ printf (" ");
+ for (x = 0; x < width; x++)
+ printf ("0x%02x, ", bitmap[width*(height - y - 1) + x]);
+ putchar ('\n');
+ }
+}
+#endif /* DEBUG */
+
+
+/* Implementation. */
+
+/* Fill a BITMAP with a character C from thew current font
+ in the graphics context GC. WIDTH is the width in bytes
+ and HEIGHT is the height in bits.
+
+ Note that the generated bitmaps must be used with
+
+ 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);
+
+ Possible optimizations:
+
+ * use only one reusable pixmap with the maximum dimensions.
+ * draw the entire font into a single pixmap (careful with
+ proportional fonts!).
+*/
+
+
+/*
+ * Generate OpenGL-compatible bitmap.
+ */
+static void
+fill_bitmap (Display *dpy, Window win, GC gc,
+ unsigned int width, unsigned int height,
+ int x0, int y0, unsigned int c, GLubyte *bitmap)
+{
+ XImage *image;
+ unsigned int x, y;
+ Pixmap pixmap;
+ XChar2b char2b;
+
+ pixmap = XCreatePixmap (dpy, win, 8*width, height, 1);
+ XSetForeground(dpy, gc, 0);
+ XFillRectangle (dpy, pixmap, gc, 0, 0, 8*width, height);
+ XSetForeground(dpy, gc, 1);
+
+ char2b.byte1 = (c >> 8) & 0xff;
+ char2b.byte2 = (c & 0xff);
+
+ XDrawString16 (dpy, pixmap, gc, x0, y0, &char2b, 1);
+
+ image = XGetImage (dpy, pixmap, 0, 0, 8*width, height, 1, XYPixmap);
+ if (image) {
+ /* Fill the bitmap (X11 and OpenGL are upside down wrt each other). */
+ for (y = 0; y < height; y++)
+ for (x = 0; x < 8*width; x++)
+ if (XGetPixel (image, x, y))
+ bitmap[width*(height - y - 1) + x/8] |= (1 << (7 - (x % 8)));
+ XDestroyImage (image);
+ }
+
+ XFreePixmap (dpy, pixmap);
+}
+
+/*
+ * determine if a given glyph is valid and return the
+ * corresponding XCharStruct.
+ */
+static XCharStruct *isvalid(XFontStruct *fs, int which)
+{
+ unsigned int rows,pages;
+ int byte1,byte2;
+ int i,valid = 1;
+
+ rows = fs->max_byte1 - fs->min_byte1 + 1;
+ pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;
+
+ if (rows == 1) {
+ /* "linear" fonts */
+ if ((fs->min_char_or_byte2 > which) ||
+ (fs->max_char_or_byte2 < which)) valid = 0;
+ } else {
+ /* "matrix" fonts */
+ byte2 = which & 0xff;
+ byte1 = which >> 8;
+ if ((fs->min_char_or_byte2 > byte2) ||
+ (fs->max_char_or_byte2 < byte2) ||
+ (fs->min_byte1 > byte1) ||
+ (fs->max_byte1 < byte1)) valid = 0;
+ }
+
+ if (valid) {
+ if (fs->per_char) {
+ if (rows == 1) {
+ /* "linear" fonts */
+ return(fs->per_char + (which-fs->min_char_or_byte2) );
+ } else {
+ /* "matrix" fonts */
+ i = ((byte1 - fs->min_byte1) * pages) +
+ (byte2 - fs->min_char_or_byte2);
+ return(fs->per_char + i);
+ }
+ } else {
+ return(&fs->min_bounds);
+ }
+ }
+ return(NULL);
+}
+
+
+void Fake_glXUseXFont( Font font, int first, int count, int listbase )
+{
+ XMesaContext CC;
+ Display *dpy;
+ Window win;
+ Pixmap pixmap;
+ GC gc;
+ XGCValues values;
+ unsigned long valuemask;
+ XFontStruct *fs;
+
+ GLint swapbytes, lsbfirst, rowlength;
+ GLint skiprows, skippixels, alignment;
+
+ unsigned int max_width, max_height, max_bm_width, max_bm_height;
+ GLubyte *bm;
+
+ int i;
+
+ CC = XMesaGetCurrentContext();
+ dpy = CC->display;
+ win = CC->xm_buffer->frontbuffer;
+
+ fs = XQueryFont (dpy, font);
+ if (!fs)
+ {
+ gl_error (CC->gl_ctx, GL_INVALID_VALUE,
+ "Couldn't get font structure information");
+ return;
+ }
+
+ /* Allocate a bitmap that can fit all characters. */
+ max_width = fs->max_bounds.rbearing - fs->min_bounds.lbearing;
+ max_height = fs->max_bounds.ascent + fs->max_bounds.descent;
+ max_bm_width = (max_width + 7) / 8;
+ max_bm_height = max_height;
+
+ bm = (GLubyte *) malloc ((max_bm_width * max_bm_height) * sizeof
+(GLubyte));
+ if (!bm) {
+ XFreeFontInfo( NULL, fs, 0 );
+ gl_error (CC->gl_ctx, GL_OUT_OF_MEMORY,
+ "Couldn't allocate bitmap in glXUseXFont()");
+ return;
+ }
+
+#if 0
+ /* get the page info */
+ pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1;
+ firstchar = (fs->min_byte1 << 8) + fs->min_char_or_byte2;
+ lastchar = (fs->max_byte1 << 8) + fs->max_char_or_byte2;
+ rows = fs->max_byte1 - fs->min_byte1 + 1;
+ unsigned int first_char, last_char, pages, rows;
+#endif
+
+ /* Save the current packing mode for bitmaps. */
+ glGetIntegerv (GL_UNPACK_SWAP_BYTES, &swapbytes);
+ glGetIntegerv (GL_UNPACK_LSB_FIRST, &lsbfirst);
+ glGetIntegerv (GL_UNPACK_ROW_LENGTH, &rowlength);
+ glGetIntegerv (GL_UNPACK_SKIP_ROWS, &skiprows);
+ glGetIntegerv (GL_UNPACK_SKIP_PIXELS, &skippixels);
+ glGetIntegerv (GL_UNPACK_ALIGNMENT, &alignment);
+
+ /* Enforce a standard packing mode which is compatible with
+ fill_bitmap() from above. This is actually the default mode,
+ except for the (non)alignment. */
+ 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);
+
+ pixmap = XCreatePixmap (dpy, win, 10, 10, 1);
+ values.foreground = BlackPixel (dpy, DefaultScreen (dpy));
+ values.background = WhitePixel (dpy, DefaultScreen (dpy));
+ values.font = fs->fid;
+ valuemask = GCForeground | GCBackground | GCFont;
+ gc = XCreateGC (dpy, pixmap, valuemask, &values);
+ XFreePixmap (dpy, pixmap);
+
+#ifdef DEBUG
+ if (debug_xfonts)
+ dump_font_struct (fs);
+#endif
+
+ for (i = 0; i < count; i++)
+ {
+ unsigned int width, height, bm_width, bm_height;
+ GLfloat x0, y0, dx, dy;
+ XCharStruct *ch;
+ int x, y;
+ unsigned int c = first + i;
+ int list = listbase + i;
+ int valid;
+
+ /* check on index validity and get the bounds */
+ ch = isvalid(fs, c);
+ if (!ch) {
+ ch = &fs->max_bounds;
+ valid = 0;
+ } else {
+ valid = 1;
+ }
+
+#ifdef DEBUG
+ if (debug_xfonts) {
+ char s[7];
+ sprintf (s, isprint (c) ? "%c> " : "\\%03o> ", c);
+ dump_char_struct (ch, s);
+ }
+#endif
+
+ /* glBitmap()' parameters:
+ straight from the glXUseXFont(3) manpage. */
+ width = ch->rbearing - ch->lbearing;
+ height = ch->ascent + ch->descent;
+ x0 = - ch->lbearing;
+ y0 = ch->descent - 1;
+ dx = ch->width;
+ dy = 0;
+
+ /* X11's starting point. */
+ x = - ch->lbearing;
+ y = ch->ascent;
+
+ /* Round the width to a multiple of eight. We will use this also
+ for the pixmap for capturing the X11 font. This is slightly
+ inefficient, but it makes the OpenGL part real easy. */
+ bm_width = (width + 7) / 8;
+ bm_height = height;
+
+ glNewList (list, GL_COMPILE);
+ if (valid && (bm_width > 0) && (bm_height > 0)) {
+
+ MEMSET (bm, '\0', bm_width * bm_height);
+ fill_bitmap (dpy, win, gc, bm_width, bm_height, x, y, c, bm);
+
+ glBitmap (width, height, x0, y0, dx, dy, bm);
+#ifdef DEBUG
+ if (debug_xfonts) {
+ printf ("width/height = %u/%u\n", width, height);
+ printf ("bm_width/bm_height = %u/%u\n", bm_width,
+bm_height);
+ dump_bitmap (bm_width, bm_height, bm);
+ }
+#endif
+ } else {
+ glBitmap (0, 0, 0.0, 0.0, dx, dy, NULL);
+ }
+ glEndList ();
+ }
+
+ free (bm);
+ XFreeFontInfo( NULL, fs, 0 );
+ XFreeGC (dpy, gc);
+
+ /* Restore saved packing modes. */
+ glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes);
+ glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, alignment);
+}
+
+void xmesa_xfonts_dummy( void )
+{
+ /* silence unused var warnings */
+ (void) kernel8;
+ (void) DitherValues;
+ (void) HPCR_DRGB;
+ (void) kernel1;
+}
+
+/* The End. */
diff --git a/src/mesa/drivers/x11/xmesaP.h b/src/mesa/drivers/x11/xmesaP.h
new file mode 100644
index 0000000000..256a47f0a6
--- /dev/null
+++ b/src/mesa/drivers/x11/xmesaP.h
@@ -0,0 +1,499 @@
+/* $Id: xmesaP.h,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+#ifndef XMESAP_H
+#define XMESAP_H
+
+
+#ifdef XFree86Server
+#include "xf86glx_util.h"
+#else
+#ifdef SHM
+#include <X11/extensions/XShm.h>
+#endif
+#endif
+#include "GL/xmesa.h"
+#include "types.h"
+#ifdef FX
+#include "GL/fxmesa.h"
+#include "../FX/fxdrv.h"
+#endif
+
+
+/* for PF_8R8G8B24 pixel format */
+typedef struct {
+ GLubyte b;
+ GLubyte g;
+ GLubyte r;
+} bgr_t;
+
+
+/*
+ * "Derived" from gl_visual. Basically corresponds to an XVisualInfo.
+ */
+struct xmesa_visual {
+ GLvisual *gl_visual; /* Device independent visual parameters */
+ XMesaDisplay *display; /* The X11 display */
+#ifndef XFree86Server
+ XVisualInfo *vishandle; /* The pointer returned by glXChooseVisual */
+#endif
+ XMesaVisualInfo visinfo; /* X's visual info */
+
+ GLint level; /* 0=normal, 1=overlay, etc */
+
+ GLboolean ximage_flag; /* Use XImage for back buffer (not pixmap)? */
+
+ GLuint dithered_pf; /* Pixel format when dithering */
+ GLuint undithered_pf; /* Pixel format when not dithering */
+
+ GLfloat RedGamma; /* Gamma values, 1.0 is default */
+ GLfloat GreenGamma;
+ GLfloat BlueGamma;
+
+ GLint rmult, gmult, bmult; /* Range of color values */
+ GLint index_bits; /* Bits per pixel in CI mode */
+
+ /* For PF_TRUECOLOR */
+ GLint rshift, gshift, bshift;/* Pixel color component shifts */
+ GLubyte Kernel[16]; /* Dither kernel */
+ unsigned long RtoPixel[512]; /* RGB to pixel conversion */
+ unsigned long GtoPixel[512];
+ unsigned long BtoPixel[512];
+ GLubyte PixelToR[256]; /* Pixel to RGB conversion */
+ GLubyte PixelToG[256];
+ GLubyte PixelToB[256];
+
+ /* For PF_HPCR */
+ short hpcr_rgbTbl[3][256];
+ GLboolean hpcr_clear_flag;
+ GLubyte hpcr_clear_ximage_pattern[2][16];
+ XMesaImage *hpcr_clear_ximage;
+ XMesaPixmap hpcr_clear_pixmap;
+
+ /* For PF_1BIT */
+ int bitFlip;
+};
+
+
+
+/*
+ * "Derived" from gl_context. Basically corresponds to a GLXContext.
+ */
+struct xmesa_context {
+ GLcontext *gl_ctx; /* the core library context */
+ XMesaVisual xm_visual; /* Describes the buffers */
+ XMesaBuffer xm_buffer; /* current framebuffer */
+
+ XMesaDisplay *display; /* == xm_visual->display */
+ GLboolean swapbytes; /* Host byte order != display byte order? */
+ GLboolean direct; /* Direct rendering context? */
+
+ GLuint pixelformat; /* Current pixel format */
+
+ GLubyte red, green, blue, alpha; /* current drawing color */
+ unsigned long pixel; /* current drawing pixel value */
+
+ GLubyte clearcolor[4]; /* current clearing color */
+ unsigned long clearpixel; /* current clearing pixel value */
+};
+
+
+
+/*
+ * "Derived" from gl_buffer. Basically corresponds to a GLXDrawable.
+ */
+struct xmesa_buffer {
+ GLboolean wasCurrent; /* was ever the current buffer? */
+ GLframebuffer *gl_buffer; /* depth, stencil, accum, etc buffers */
+ XMesaVisual xm_visual; /* the X/Mesa visual */
+
+ XMesaContext xm_context; /* the context associated with this buffer */
+ XMesaDisplay *display;
+ GLboolean pixmap_flag; /* is the buffer a Pixmap? */
+ XMesaDrawable frontbuffer; /* either a window or pixmap */
+ XMesaPixmap backpixmap; /* back buffer Pixmap */
+ XMesaImage *backimage; /* back buffer simulated XImage */
+
+ XMesaDrawable buffer; /* the current buffer, either equal to */
+ /* frontbuffer, backpixmap or XIMAGE (None) */
+
+ XMesaColormap cmap; /* the X colormap */
+
+ GLint db_state; /* 0 = single buffered */
+ /* BACK_PIXMAP = use Pixmap for back buffer */
+ /* BACK_XIMAGE = use XImage for back buffer */
+
+#ifndef XFree86Server
+ GLuint shm; /* X Shared Memory extension status: */
+ /* 0 = not available */
+ /* 1 = XImage support available */
+ /* 2 = Pixmap support available too */
+#ifdef SHM
+ XShmSegmentInfo shminfo;
+#endif
+#endif
+
+ XMesaImage *rowimage; /* Used for optimized span writing */
+
+ GLuint width, height; /* size of buffer */
+
+ GLint bottom; /* used for FLIP macro below */
+ GLubyte *ximage_origin1; /* used for PIXELADDR1 macro */
+ GLint ximage_width1;
+ GLushort *ximage_origin2; /* used for PIXELADDR2 macro */
+ GLint ximage_width2;
+ bgr_t *ximage_origin3; /* used for PIXELADDR3 macro */
+ GLint ximage_width3;
+ GLuint *ximage_origin4; /* used for PIXELADDR4 macro */
+ GLint ximage_width4;
+
+ XMesaPixmap stipple_pixmap; /* For polygon stippling */
+ XMesaGC stipple_gc; /* For polygon stippling */
+
+ XMesaGC gc1; /* GC for infrequent color changes */
+ XMesaGC gc2; /* GC for frequent color changes */
+ XMesaGC cleargc; /* GC for clearing the color buffer */
+
+ /* The following are here instead of in the XMesaVisual
+ * because they depend on the window's colormap.
+ */
+
+ /* For PF_DITHER, PF_LOOKUP, PF_GRAYSCALE */
+ unsigned long color_table[576]; /* RGB -> pixel value */
+
+ /* For PF_DITHER, PF_LOOKUP, PF_GRAYSCALE */
+ GLubyte pixel_to_r[65536]; /* pixel value -> red */
+ GLubyte pixel_to_g[65536]; /* pixel value -> green */
+ GLubyte pixel_to_b[65536]; /* pixel value -> blue */
+
+ /* Used to do XAllocColor/XFreeColors accounting: */
+ int num_alloced;
+ unsigned long alloced_colors[256];
+
+#ifdef FX
+ /* For 3Dfx Glide only */
+ GLboolean FXisHackUsable; /* Can we render into window? */
+ GLboolean FXwindowHack; /* Are we rendering into a window? */
+ fxMesaContext FXctx;
+#endif
+
+ struct xmesa_buffer *Next; /* Linked list pointer: */
+};
+
+
+
+/* Values for xmesa->dest: */
+#define FRONT_PIXMAP 1
+#define BACK_PIXMAP 2
+#define BACK_XIMAGE 4
+
+
+/* Values for xmesa->pixelformat: */
+#define PF_INDEX 1 /* Color Index mode */
+#define PF_TRUECOLOR 2 /* TrueColor or DirectColor, any depth */
+#define PF_TRUEDITHER 3 /* TrueColor with dithering */
+#define PF_8A8B8G8R 4 /* 32-bit TrueColor: 8-A, 8-B, 8-G, 8-R */
+#define PF_8R8G8B 5 /* 32-bit TrueColor: 8-R, 8-G, 8-B bits */
+#define PF_5R6G5B 6 /* 16-bit TrueColor: 5-R, 6-G, 5-B bits */
+#define PF_DITHER 7 /* Color-mapped RGB with dither */
+#define PF_LOOKUP 8 /* Color-mapped RGB without dither */
+#define PF_HPCR 9 /* HP Color Recovery (ad@lms.be 30/08/95) */
+#define PF_1BIT 10 /* monochrome dithering of RGB */
+#define PF_GRAYSCALE 11 /* Grayscale or StaticGray */
+#define PF_8R8G8B24 12 /* 24-bit TrueColor: 8-R, 8-G, 8-B bits */
+#define PF_DITHER_5R6G5B 13 /* 16-bit dithered TrueColor: 5-R, 6-G, 5-B */
+
+
+/*
+ * If pixelformat==PF_TRUECOLOR:
+ */
+#define PACK_TRUECOLOR( PIXEL, R, G, B ) \
+ PIXEL = xmesa->xm_visual->RtoPixel[R] \
+ | xmesa->xm_visual->GtoPixel[G] \
+ | xmesa->xm_visual->BtoPixel[B]; \
+
+
+/*
+ * If pixelformat==PF_TRUEDITHER:
+ */
+#define PACK_TRUEDITHER( PIXEL, X, Y, R, G, B ) \
+{ \
+ int d = xmesa->xm_visual->Kernel[((X)&3) | (((Y)&3)<<2)]; \
+ PIXEL = xmesa->xm_visual->RtoPixel[(R)+d] \
+ | xmesa->xm_visual->GtoPixel[(G)+d] \
+ | xmesa->xm_visual->BtoPixel[(B)+d]; \
+}
+
+
+
+/*
+ * If pixelformat==PF_8A8B8G8R:
+ */
+#define PACK_8A8B8G8R( R, G, B, A ) \
+ ( ((A) << 24) | ((B) << 16) | ((G) << 8) | (R) )
+
+
+/*
+ * Like PACK_8A8B8G8R() but don't use alpha. This is usually an acceptable
+ * shortcut.
+ */
+#define PACK_8B8G8R( R, G, B ) ( ((B) << 16) | ((G) << 8) | (R) )
+
+
+
+/*
+ * If pixelformat==PF_8R8G8B:
+ */
+#define PACK_8R8G8B( R, G, B) ( ((R) << 16) | ((G) << 8) | (B) )
+
+
+/*
+ * If pixelformat==PF_5R6G5B:
+ */
+#define PACK_5R6G5B( R, G, B) ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
+
+
+
+/*
+ * If pixelformat==PF_DITHER:
+ *
+ * Improved 8-bit RGB dithering code contributed by Bob Mercier
+ * (mercier@hollywood.cinenet.net). Thanks Bob!
+ */
+#undef _R
+#undef _G
+#undef _B
+#ifdef DITHER666
+# define _R 6
+# define _G 6
+# define _B 6
+# define _MIX(r,g,b) (((r)*_G+(g))*_B+(b))
+#else
+# define _R 5
+# define _G 9
+# define _B 5
+# define _MIX(r,g,b) ( ((g)<<6) | ((b)<<3) | (r) )
+#endif
+#define _DX 4
+#define _DY 4
+#define _D (_DX*_DY)
+
+/*#define _DITH(C,c,d) (((unsigned)((_D*(C-1)+1)*c+d))/(_D*256))*/
+#define _DITH(C,c,d) (((unsigned)((_D*(C-1)+1)*c+d)) >> 12)
+
+#define MAXC 256
+static int kernel8[_DY*_DX] = {
+ 0 * MAXC, 8 * MAXC, 2 * MAXC, 10 * MAXC,
+ 12 * MAXC, 4 * MAXC, 14 * MAXC, 6 * MAXC,
+ 3 * MAXC, 11 * MAXC, 1 * MAXC, 9 * MAXC,
+ 15 * MAXC, 7 * MAXC, 13 * MAXC, 5 * MAXC,
+};
+/*static int __d;*/
+
+/* Dither for random X,Y */
+#define DITHER_SETUP \
+ int __d; \
+ unsigned long *ctable = xmesa->xm_buffer->color_table;
+
+#define DITHER( X, Y, R, G, B ) \
+ (__d = kernel8[(((Y)&3)<<2) | ((X)&3)], \
+ ctable[_MIX(_DITH(_R, (R), __d), \
+ _DITH(_G, (G), __d), \
+ _DITH(_B, (B), __d))])
+
+/* Dither for random X, fixed Y */
+#define XDITHER_SETUP(Y) \
+ int __d; \
+ unsigned long *ctable = xmesa->xm_buffer->color_table; \
+ int *kernel = &kernel8[ ((Y)&3) << 2 ];
+
+#define XDITHER( X, R, G, B ) \
+ (__d = kernel[(X)&3], \
+ ctable[_MIX(_DITH(_R, (R), __d), \
+ _DITH(_G, (G), __d), \
+ _DITH(_B, (B), __d))])
+
+
+
+/*
+ * Dithering for flat-shaded triangles. Precompute all 16 possible
+ * pixel values given the triangle's RGB color. Contributed by Martin Shenk.
+ */
+static GLushort DitherValues[16]; /* array of (up to) 16-bit pixel values */
+
+#define FLAT_DITHER_SETUP( R, G, B ) \
+ { \
+ unsigned long *ctable = xmesa->xm_buffer->color_table; \
+ int msdr = (_D*((_R)-1)+1) * (R); \
+ int msdg = (_D*((_G)-1)+1) * (G); \
+ int msdb = (_D*((_B)-1)+1) * (B); \
+ int i; \
+ for (i=0;i<16;i++) { \
+ int k = kernel8[i]; \
+ int j = _MIX( (msdr+k)>>12, (msdg+k)>>12, (msdb+k)>>12 ); \
+ DitherValues[i] = (GLushort) ctable[j]; \
+ } \
+ }
+
+#define FLAT_DITHER_ROW_SETUP(Y) \
+ GLushort *ditherRow = DitherValues + ( ((Y)&3) << 2);
+
+#define FLAT_DITHER(X) ditherRow[(X)&3]
+
+
+
+/*
+ * If pixelformat==PF_LOOKUP:
+ */
+#define _DITH0(C,c) (((unsigned)((_D*(C-1)+1)*c)) >> 12)
+
+#define LOOKUP_SETUP \
+ unsigned long *ctable = xmesa->xm_buffer->color_table
+
+#define LOOKUP( R, G, B ) \
+ ctable[_MIX(_DITH0(_R, (R)), \
+ _DITH0(_G, (G)), \
+ _DITH0(_B, (B)))]
+
+
+
+/*
+ * If pixelformat==PF_HPCR:
+ *
+ * HP Color Recovery dithering (ad@lms.be 30/08/95)
+ * HP has on it's 8-bit 700-series computers, a feature called
+ * 'Color Recovery'. This allows near 24-bit output (so they say).
+ * It is enabled by selecting the 8-bit TrueColor visual AND
+ * corresponding colormap (see tkInitWindow) AND doing some special
+ * dither.
+ */
+static const short HPCR_DRGB[3][2][16] = {
+{
+ { 16, -4, 1,-11, 14, -6, 3, -9, 15, -5, 2,-10, 13, -7, 4, -8},
+ {-15, 5, 0, 12,-13, 7, -2, 10,-14, 6, -1, 11,-12, 8, -3, 9}
+},
+{
+ {-11, 15, -7, 3, -8, 14, -4, 2,-10, 16, -6, 4, -9, 13, -5, 1},
+ { 12,-14, 8, -2, 9,-13, 5, -1, 11,-15, 7, -3, 10,-12, 6, 0}
+},
+{
+ { 6,-18, 26,-14, 2,-22, 30,-10, 8,-16, 28,-12, 4,-20, 32, -8},
+ { -4, 20,-24, 16, 0, 24,-28, 12, -6, 18,-26, 14, -2, 22,-30, 10}
+}
+};
+
+#define DITHER_HPCR( X, Y, R, G, B ) \
+ ( ((xmesa->xm_visual->hpcr_rgbTbl[0][R] + HPCR_DRGB[0][(Y)&1][(X)&15]) & 0xE0) \
+ |(((xmesa->xm_visual->hpcr_rgbTbl[1][G] + HPCR_DRGB[1][(Y)&1][(X)&15]) & 0xE0)>>3) \
+ | ((xmesa->xm_visual->hpcr_rgbTbl[2][B] + HPCR_DRGB[2][(Y)&1][(X)&15])>>6) \
+ )
+
+
+
+/*
+ * If pixelformat==PF_1BIT:
+ */
+static int const kernel1[16] = {
+ 0*47, 9*47, 4*47, 12*47, /* 47 = (255*3)/16 */
+ 6*47, 2*47, 14*47, 8*47,
+ 10*47, 1*47, 5*47, 11*47,
+ 7*47, 13*47, 3*47, 15*47 };
+
+#define SETUP_1BIT int bitFlip = xmesa->xm_visual->bitFlip
+#define DITHER_1BIT( X, Y, R, G, B ) \
+ (( ((int)(R)+(int)(G)+(int)(B)) > kernel1[(((Y)&3) << 2) | ((X)&3)] ) ^ bitFlip)
+
+
+
+/*
+ * If pixelformat==PF_GRAYSCALE:
+ */
+#define GRAY_RGB( R, G, B ) xmesa->xm_buffer->color_table[((R) + (G) + (B))/3]
+
+
+
+#define XIMAGE None
+
+
+/*
+ * Converts a GL window Y coord to an X window Y coord:
+ */
+#define FLIP(Y) (xmesa->xm_buffer->bottom-(Y))
+
+
+/*
+ * Return the address of a 1, 2 or 4-byte pixel in the back XImage:
+ * X==0 is left, Y==0 is bottom.
+ */
+#define PIXELADDR1( X, Y ) \
+ ( xmesa->xm_buffer->ximage_origin1 - (Y) * xmesa->xm_buffer->ximage_width1 + (X) )
+
+#define PIXELADDR2( X, Y ) \
+ ( xmesa->xm_buffer->ximage_origin2 - (Y) * xmesa->xm_buffer->ximage_width2 + (X) )
+
+#define PIXELADDR3( X, Y ) \
+ ( xmesa->xm_buffer->ximage_origin3 - (Y) * xmesa->xm_buffer->ximage_width3 + (X) )
+
+#define PIXELADDR4( X, Y ) \
+ ( xmesa->xm_buffer->ximage_origin4 - (Y) * xmesa->xm_buffer->ximage_width4 + (X) )
+
+
+
+/*
+ * External functions:
+ */
+
+extern unsigned long xmesa_color_to_pixel( XMesaContext xmesa,
+ GLubyte r, GLubyte g, GLubyte b, GLubyte a );
+
+extern void xmesa_alloc_back_buffer( XMesaBuffer b );
+
+extern void xmesa_update_state( GLcontext *ctx );
+
+extern points_func xmesa_get_points_func( GLcontext *ctx );
+
+extern line_func xmesa_get_line_func( GLcontext *ctx );
+
+extern triangle_func xmesa_get_triangle_func( GLcontext *ctx );
+
+
+/* XXX this is a hack to implement shared display lists with 3Dfx */
+extern XMesaBuffer XMesaCreateWindowBuffer2( XMesaVisual v,
+ XMesaWindow w,
+ XMesaContext c );
+
+
+/*
+ * These are the extra routines required for integration with XFree86.
+ * None of these routines should be user visible. -KEM
+ */
+extern void XMesaSetVisualDisplay( XMesaDisplay *dpy, XMesaVisual v );
+extern GLboolean XMesaForceCurrent(XMesaContext c);
+extern GLboolean XMesaLoseCurrent(XMesaContext c);
+extern void XMesaReset( void );
+
+#endif
diff --git a/src/mesa/main/Imakefile b/src/mesa/main/Imakefile
new file mode 100644
index 0000000000..115f16c8c3
--- /dev/null
+++ b/src/mesa/main/Imakefile
@@ -0,0 +1,127 @@
+#define DoNormalLib NO
+#define DoSharedLib YES
+#define DoDebugLib NO
+#define DoProfileLib NO
+#define LibName MESAGL
+#define SoRev SOX11REV
+#define LibHeaders NO
+
+#include <Threads.tmpl>
+
+REQUIREDLIBS = $(X11ROOT)\\XFree86\\lib\\ Xext X11
+BUILDLIBDIR = $(TOP)\\lib
+
+INCLUDES = -I$(TOP)\\include
+
+SRCS = \
+accum.c \
+alpha.c \
+alphabuf.c \
+api1.c \
+api2.c \
+attrib.c \
+bitmap.c \
+blend.c \
+bresenhm.c \
+clip.c \
+context.c \
+copypix.c \
+dd.c \
+depth.c \
+draw.c \
+drawpix.c \
+enable.c \
+eval2.c \
+feedback.c \
+fog.c \
+fortran.c \
+get.c \
+hash.c \
+glx.c \
+interp.c \
+light.c \
+lines.c \
+list.c \
+logic.c \
+masking.c \
+misc.c \
+osmesa.c \
+pb.c \
+pixel.c \
+points.c \
+polygons.c \
+readpix.c \
+scissor.c \
+span.c \
+stencil.c \
+svgamesa.c \
+texture.c \
+varray.c \
+vb.c \
+vertex.c \
+xfonts.c \
+xform.c \
+xmesa1.c \
+xmesa2.c \
+xmesa3.c
+
+OBJS = \
+accum.o \
+alpha.o \
+alphabuf.o \
+api1.o \
+api2.o \
+attrib.o \
+bitmap.o \
+blend.o \
+bresenhm.o \
+clip.o \
+context.o \
+copypix.o \
+dd.o \
+depth.o \
+draw.o \
+drawpix.o \
+enable.o \
+eval2.o \
+feedback.o \
+fog.o \
+fortran.o \
+get.o \
+hash.o \
+glx.o \
+interp.o \
+light.o \
+lines.o \
+list.o \
+logic.o \
+masking.o \
+misc.o \
+osmesa.o \
+pb.o \
+pixel.o \
+points.o \
+polygons.o \
+readpix.o \
+scissor.o \
+span.o \
+stencil.o \
+svgamesa.o \
+texture.o \
+varray.o \
+vb.o \
+vertex.o \
+xfonts.o \
+xform.o \
+xmesa1.o \
+xmesa2.o \
+xmesa3.o
+xmesa4.o
+
+LINTLIBS =
+
+#include <Library.tmpl>
+
+DependTarget()
+
+ \ No newline at end of file
diff --git a/src/mesa/main/KNOWN_BUGS b/src/mesa/main/KNOWN_BUGS
new file mode 100644
index 0000000000..9c9076bfed
--- /dev/null
+++ b/src/mesa/main/KNOWN_BUGS
@@ -0,0 +1,20 @@
+$Id: KNOWN_BUGS,v 1.1 1999/08/19 00:55:41 jtg Exp $
+
+
+Performance issues with EXT_point_parameters & quake2
+
+
+Broken drivers:
+
+ --> After integration of the changes in kw3, only the X and FX
+drivers are known to work. Windows and D3D are known to be broken,
+and all others are suspected to be broken. Please test your driver
+and update this entry when more is known.
+
+
+
+Separate specular color interpolation isn't implemented for points and
+lines. Also, will have to add specular color add to pb.c (pixel buffer
+code).
+
+
diff --git a/src/mesa/main/Makefile.DJ b/src/mesa/main/Makefile.DJ
new file mode 100644
index 0000000000..27c3556ab9
--- /dev/null
+++ b/src/mesa/main/Makefile.DJ
@@ -0,0 +1,95 @@
+# $Id: Makefile.DJ,v 1.1 1999/08/19 00:55:41 jtg Exp $
+
+# Makefile for core library for MS-DOS using djgpp
+
+# Mesa 3-D graphics library
+# Version: 3.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.
+
+
+# $Log: Makefile.DJ,v $
+# Revision 1.1 1999/08/19 00:55:41 jtg
+# Initial revision
+#
+# Revision 1.1 1999/01/01 14:35:09 brianp
+# Initial revision
+#
+
+
+
+##### MACROS #####
+
+VPATH = RCS
+
+INCDIR = ..\include
+LIBDIR = ..\lib
+
+# Want UniVBE (Display Doctor) Support, Scitech Software www.scitechsoft.com
+# Set -I to point to scitech include files.
+# Haven`t finished doing univbe version for djgpp
+#CFLAGS += -DUNIVBE -D__DOS__ -D__MSDOS32__ -IC:\scitech\include
+CFLAGS += -D__DOS__ -D__MSDOS32__
+
+CORE_SOURCES = accum.c alpha.c alphabuf.c api1.c api2.c apiext.c attrib.c \
+ bitmap.c blend.c clip.c colortab.c context.c copypix.c depth.c \
+ dlist.c drawpix.c enable.c eval.c feedback.c fog.c \
+ get.c hash.c image.c light.c lines.c logic.c masking.c matrix.c \
+ misc.c mmath.c mthreads.c pb.c pixel.c points.c pointers.c polygon.c \
+ quads.c rastpos.c readpix.c rect.c scissor.c shade.c span.c \
+ stencil.c teximage.c texobj.c texstate.c texture.c triangle.c \
+ varray.c winpos.c vb.c vbfill.c vbrender.c vbxform.c xform.c \
+ zoom.c
+
+DRIVER_SOURCES = DOS\dosmesa.c
+
+SOURCES = $(CORE_SOURCES) $(DRIVER_SOURCES)
+
+OBJECTS = $(SOURCES:.c=.o)
+
+#CFLAGS += -g
+
+##### RULES #####
+
+.c.o:
+ gcc -c -DDOSVGA -I$(INCDIR) $(CFLAGS) $<
+
+##### TARGETS #####
+
+GL_LIB = dosmesa.a
+
+default: $(LIBDIR)/$(GL_LIB)
+
+clean:
+ -del *.o
+
+MAKELIB = AR ruv
+RANLIB = ls
+
+# Make the library
+$(LIBDIR)/$(GL_LIB): $(OBJECTS)
+ $(MAKELIB) $(GL_LIB) $(OBJECTS)
+ copy $(GL_LIB) $(LIBDIR)\$(GL_LIB)
+
+include depend.dos
+#
+
+# Run 'make depend' to update the dependencies if you change what's included
+# by any source file.
+#
+dep: $(SOURCES)
+ makedep -fdepend -Y -I../include $(SOURCES)
+
diff --git a/src/mesa/main/Makefile.X11 b/src/mesa/main/Makefile.X11
new file mode 100644
index 0000000000..e6419b555a
--- /dev/null
+++ b/src/mesa/main/Makefile.X11
@@ -0,0 +1,243 @@
+# $Id: Makefile.X11,v 1.1 1999/08/19 00:55:41 jtg Exp $
+
+# Mesa 3-D graphics library
+# Version: 3.1
+# Copyright (C) 1995-1999 Brian Paul
+
+# Makefile for core library
+
+
+##### MACROS #####
+
+VPATH = RCS
+
+INCDIR = ../include
+LIBDIR = ../lib
+
+CORE_SOURCES = \
+ accum.c \
+ alpha.c \
+ alphabuf.c \
+ api1.c \
+ api2.c \
+ apiext.c \
+ attrib.c \
+ bbox.c \
+ bitmap.c \
+ blend.c \
+ clip.c \
+ colortab.c \
+ config.c \
+ context.c \
+ copypix.c \
+ cva.c \
+ debug_xform.c \
+ depth.c \
+ dlist.c \
+ drawpix.c \
+ enable.c \
+ enums.c \
+ eval.c \
+ extensions.c \
+ feedback.c \
+ fog.c \
+ get.c \
+ hash.c \
+ image.c \
+ light.c \
+ lines.c \
+ logic.c \
+ masking.c \
+ matrix.c \
+ misc.c \
+ mmath.c \
+ mthreads.c \
+ pb.c \
+ pixel.c \
+ pipeline.c \
+ points.c \
+ pointers.c \
+ polygon.c \
+ quads.c \
+ rastpos.c \
+ readpix.c \
+ rect.c \
+ scissor.c \
+ shade.c \
+ span.c \
+ stages.c \
+ stencil.c \
+ teximage.c \
+ texobj.c \
+ texstate.c \
+ texture.c \
+ translate.c \
+ triangle.c \
+ varray.c \
+ vb.c \
+ vbcull.c \
+ vbfill.c \
+ vbindirect.c \
+ vbrender.c \
+ vbxform.c \
+ vector.c \
+ winpos.c \
+ xform.c \
+ zoom.c \
+ X86/x86.c \
+ X86/common_x86.c \
+ X86/3dnow.c
+
+DRIVER_SOURCES = \
+ X/glxapi.c \
+ X/fakeglx.c \
+ X/realglx.c \
+ X/xfonts.c \
+ X/xmesa1.c \
+ X/xmesa2.c \
+ X/xmesa3.c \
+ X/xmesa4.c \
+ OSmesa/osmesa.c \
+ SVGA/svgamesa.c \
+ FX/fxapi.c \
+ FX/fxclip.c \
+ FX/fxcva.c \
+ FX/fxdd.c \
+ FX/fxddspan.c \
+ FX/fxddtex.c \
+ FX/fxfastpath.c \
+ FX/fxpipeline.c \
+ FX/fxrender.c \
+ FX/fxsanity.c \
+ FX/fxsetup.c \
+ FX/fxtexman.c \
+ FX/fxtrifuncs.c \
+ FX/fxvsetup.c \
+ FX/fxglidew.c
+# GGI/ggimesa.c
+
+ASM_SOURCES =
+
+ADDITIONAL_OBJ =
+
+OBJECTS = $(ASM_SOURCES:.S=.o) \
+ $(CORE_SOURCES:.c=.o) \
+ $(DRIVER_SOURCES:.c=.o) \
+ $(ADDITIONAL_OBJ)
+
+
+#who put these here!?!
+#GL_LIB = libMesaGL.so
+#GLU_LIB = libMesaGLU.so
+#GLUT_LIB = libglut.so
+#CC = gcc
+#INCLUDES=-I. -I../include -I/usr/X11R6/include -I/usr/include/glide -I/usr/local/glide/include
+
+
+##### RULES #####
+
+.c.o:
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+
+.S.o:
+ $(CC) -c $(CFLAGS) $< -o $@
+
+
+# UGH! These rules shouldn't be needed but IRIX's make (and others?) needs them
+X/glxapi.o: X/glxapi.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+X/fakeglx.o: X/fakeglx.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+X/realglx.o: X/realglx.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+X/xfonts.o: X/xfonts.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+X/xmesa1.o: X/xmesa1.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+X/xmesa2.o: X/xmesa2.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+X/xmesa3.o: X/xmesa3.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+X/xmesa4.o: X/xmesa4.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+SVGA/svgamesa.o: SVGA/svgamesa.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+OSmesa/osmesa.o: OSmesa/osmesa.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxapi.o: FX/fxapi.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxclip.o: FX/fxclip.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxcva.o: FX/fxcva.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxdd.o: FX/fxdd.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxddspan.o: FX/fxddspan.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxddtex.o: FX/fxddtex.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxfastpath.o: FX/fxfastpath.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxpipeline.o: FX/fxpipeline.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxrender.o: FX/fxrender.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxsanity.o: FX/fxsanity.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxsetup.o: FX/fxsetup.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxtrifuncs.o: FX/fxtrifuncs.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxtexman.o: FX/fxtexman.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxvsetup.o: FX/fxvsetup.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/fxglidew.o: FX/fxglidew.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+FX/X86/fx_3dnow_fastpath.o: FX/X86/fx_3dnow_fastpath.S FX/X86/fx_regoff.h
+FX/X86/fx_regoff.h: FX/X86/fx_gen_regoff
+ $< > $@
+FX/X86/fx_gen_regoff : FX/X86/fx_gen_regoff.c
+ $(CC) -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+GGI/ggimesa.o: GGI/ggimesa.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+X86/x86.o: X86/x86.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+X86/common_x86.o: X86/common_x86.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+X86/3dnow.o: X86/3dnow.c
+ $(CC) -c -I. -I$(INCDIR) $(CFLAGS) $< -o $@
+
+
+##### TARGETS #####
+
+#default:
+# @echo "Specify a target configuration"
+
+clean:
+ -rm *.o *~ */*.o */*~
+
+targets: $(LIBDIR)/$(GL_LIB)
+
+# Make the library
+$(LIBDIR)/$(GL_LIB): $(OBJECTS)
+ $(MAKELIB) $(GL_LIB) $(MAJOR) $(MINOR) $(OBJECTS)
+ rm -f $(LIBDIR)/$(GL_LIB)*
+ mv $(GL_LIB)* $(LIBDIR)
+
+
+include ../Make-config
+
+include depend
+
+
+
+#
+# Run 'make dep' to update the dependencies if you change what's included
+# by any source file.
+#
+dep: $(CORE_SOURCES) $(DRIVER_SOURCES)
+ makedepend -fdepend -Y -I../include -DGGI -DSVGA -DFX $(CORE_SOURCES) $(DRIVER_SOURCES)
+
+tags:
+ etags `find . -name \*.[ch]` `find ../include`
diff --git a/src/mesa/main/accum.c b/src/mesa/main/accum.c
new file mode 100644
index 0000000000..29a8a134f2
--- /dev/null
+++ b/src/mesa/main/accum.c
@@ -0,0 +1,495 @@
+/* $Id: accum.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <assert.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include "accum.h"
+#include "context.h"
+#include "macros.h"
+#include "masking.h"
+#include "span.h"
+#include "types.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+/*
+ * Accumulation buffer notes
+ *
+ * Normally, accumulation buffer values are GLshorts with values in
+ * [-32767, 32767] which represent floating point colors in [-1, 1],
+ * as suggested by the OpenGL specification.
+ *
+ * We optimize for the common case used for full-scene antialiasing:
+ * // start with accum buffer cleared to zero
+ * glAccum(GL_LOAD, w); // or GL_ACCUM the first image
+ * glAccum(GL_ACCUM, w);
+ * ...
+ * glAccum(GL_ACCUM, w);
+ * glAccum(GL_RETURN, 1.0);
+ * That is, we start with an empty accumulation buffer and accumulate
+ * n images, each with weight w = 1/n.
+ * In this scenario, we can simply store unscaled integer values in
+ * the accum buffer instead of scaled integers. We'll also keep track
+ * of the w value so when we do GL_RETURN we simply divide the accumulated
+ * values by n (=1/w).
+ * This lets us avoid _many_ int->float->int conversions.
+ */
+
+
+
+void gl_alloc_accum_buffer( GLcontext *ctx )
+{
+ GLint n;
+
+ if (ctx->Buffer->Accum) {
+ free( ctx->Buffer->Accum );
+ ctx->Buffer->Accum = NULL;
+ }
+
+ /* allocate accumulation buffer if not already present */
+ n = ctx->Buffer->Width * ctx->Buffer->Height * 4 * sizeof(GLaccum);
+ ctx->Buffer->Accum = (GLaccum *) malloc( n );
+ if (!ctx->Buffer->Accum) {
+ /* unable to setup accumulation buffer */
+ gl_error( ctx, GL_OUT_OF_MEMORY, "glAccum" );
+ }
+ ctx->IntegerAccumMode = GL_TRUE;
+ ctx->IntegerAccumScaler = 0.0;
+}
+
+
+
+void gl_ClearAccum( GLcontext *ctx,
+ GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glAccum");
+
+ ctx->Accum.ClearColor[0] = CLAMP( red, -1.0, 1.0 );
+ ctx->Accum.ClearColor[1] = CLAMP( green, -1.0, 1.0 );
+ ctx->Accum.ClearColor[2] = CLAMP( blue, -1.0, 1.0 );
+ ctx->Accum.ClearColor[3] = CLAMP( alpha, -1.0, 1.0 );
+}
+
+
+
+/*
+ * This is called when we fall out of optimized/unscaled accum buffer mode.
+ * That is, we convert each unscaled accum buffer value into a scaled value
+ * representing the range[-1, 1].
+ */
+static void rescale_accum( GLcontext *ctx )
+{
+ const GLuint n = ctx->Buffer->Width * ctx->Buffer->Height * 4;
+ const GLfloat s = ctx->IntegerAccumScaler * (32767.0 / 255.0);
+ GLaccum *accum = ctx->Buffer->Accum;
+ GLuint i;
+
+ assert(ctx->IntegerAccumMode);
+ assert(sizeof(GLchan) == 1); /* if not true, 255.0 above must be fixed */
+ assert(accum);
+
+ for (i = 0; i < n; i++) {
+ accum[i] = (GLaccum) (accum[i] * s);
+ }
+
+ ctx->IntegerAccumMode = GL_FALSE;
+}
+
+
+
+void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value )
+{
+ GLuint xpos, ypos, width, height, width4;
+ GLfloat acc_scale;
+ GLubyte rgba[MAX_WIDTH][4];
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glAccum");
+
+ if (ctx->Visual->AccumBits==0 || !ctx->Buffer->Accum) {
+ /* No accumulation buffer! */
+ gl_warning(ctx, "Calling glAccum() without an accumulation buffer");
+ return;
+ }
+
+ if (sizeof(GLaccum)==1) {
+ acc_scale = 127.0;
+ }
+ else if (sizeof(GLaccum)==2) {
+ acc_scale = 32767.0;
+ }
+ else {
+ /* sizeof(GLaccum) > 2 (Cray) */
+ acc_scale = (float) SHRT_MAX;
+ }
+
+ if (ctx->NewState)
+ gl_update_state( ctx );
+
+ /* Determine region to operate upon. */
+ if (ctx->Scissor.Enabled) {
+ xpos = ctx->Scissor.X;
+ ypos = ctx->Scissor.Y;
+ width = ctx->Scissor.Width;
+ height = ctx->Scissor.Height;
+ }
+ else {
+ /* whole window */
+ xpos = 0;
+ ypos = 0;
+ width = ctx->Buffer->Width;
+ height = ctx->Buffer->Height;
+ }
+
+ width4 = 4 * width;
+
+ switch (op) {
+ case GL_ADD:
+ {
+ const GLaccum intVal = (GLaccum) (value * acc_scale);
+ GLuint j;
+ /* May have to leave optimized accum buffer mode */
+ if (ctx->IntegerAccumMode)
+ rescale_accum(ctx);
+ for (j = 0; j < height; j++) {
+ GLaccum * acc = ctx->Buffer->Accum + ypos * width4 + 4 * xpos;
+ GLuint i;
+ for (i = 0; i < width4; i++) {
+ acc[i] += intVal;
+ }
+ ypos++;
+ }
+ }
+ break;
+
+ case GL_MULT:
+ {
+ GLuint j;
+ /* May have to leave optimized accum buffer mode */
+ if (ctx->IntegerAccumMode)
+ rescale_accum(ctx);
+ for (j = 0; j < height; j++) {
+ GLaccum *acc = ctx->Buffer->Accum + ypos * width4 + 4 * xpos;
+ GLuint i;
+ for (i = 0; i < width4; i++) {
+ acc[i] = (GLaccum) ( (GLfloat) acc[i] * value );
+ }
+ ypos++;
+ }
+ }
+ break;
+
+ case GL_ACCUM:
+ (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.DriverReadBuffer );
+
+ /* May have to leave optimized accum buffer mode */
+ if (ctx->IntegerAccumScaler == 0.0 && value > 0.0 && value <= 1.0)
+ ctx->IntegerAccumScaler = value;
+ if (ctx->IntegerAccumMode && value != ctx->IntegerAccumScaler)
+ rescale_accum(ctx);
+
+ if (ctx->IntegerAccumMode) {
+ /* simply add integer color values into accum buffer */
+ GLuint j;
+ GLaccum *acc = ctx->Buffer->Accum + ypos * width4 + xpos * 4;
+ assert(ctx->IntegerAccumScaler > 0.0);
+ assert(ctx->IntegerAccumScaler <= 1.0);
+ for (j = 0; j < height; j++) {
+
+ GLuint i, i4;
+ gl_read_rgba_span(ctx, width, xpos, ypos, rgba);
+ for (i = i4 = 0; i < width; i++, i4+=4) {
+ acc[i4+0] += rgba[i][RCOMP];
+ acc[i4+1] += rgba[i][GCOMP];
+ acc[i4+2] += rgba[i][BCOMP];
+ acc[i4+3] += rgba[i][ACOMP];
+ }
+ acc += width4;
+ ypos++;
+ }
+ }
+ else {
+ /* scaled integer accum buffer */
+ const GLfloat rscale = value * acc_scale / 255.0;
+ const GLfloat gscale = value * acc_scale / 255.0;
+ const GLfloat bscale = value * acc_scale / 255.0;
+ const GLfloat ascale = value * acc_scale / 255.0;
+ GLuint j;
+ for (j=0;j<height;j++) {
+ GLaccum *acc = ctx->Buffer->Accum + ypos * width4 + xpos * 4;
+ GLuint i;
+ gl_read_rgba_span(ctx, width, xpos, ypos, rgba);
+ for (i=0;i<width;i++) {
+ *acc += (GLaccum) ( (GLfloat) rgba[i][RCOMP] * rscale ); acc++;
+ *acc += (GLaccum) ( (GLfloat) rgba[i][GCOMP] * gscale ); acc++;
+ *acc += (GLaccum) ( (GLfloat) rgba[i][BCOMP] * bscale ); acc++;
+ *acc += (GLaccum) ( (GLfloat) rgba[i][ACOMP] * ascale ); acc++;
+ }
+ ypos++;
+ }
+ }
+ (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer );
+ break;
+
+ case GL_LOAD:
+ (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.DriverReadBuffer );
+
+ /* This is a change to go into optimized accum buffer mode */
+ if (value > 0.0 && value <= 1.0) {
+ ctx->IntegerAccumMode = GL_TRUE;
+ ctx->IntegerAccumScaler = value;
+ }
+ else {
+ ctx->IntegerAccumMode = GL_FALSE;
+ ctx->IntegerAccumScaler = 0.0;
+ }
+
+ if (ctx->IntegerAccumMode) {
+ /* just copy values into accum buffer */
+ GLuint j;
+ GLaccum *acc = ctx->Buffer->Accum + ypos * width4 + xpos * 4;
+ assert(ctx->IntegerAccumScaler > 0.0);
+ assert(ctx->IntegerAccumScaler <= 1.0);
+ for (j = 0; j < height; j++) {
+ GLuint i, i4;
+ gl_read_rgba_span(ctx, width, xpos, ypos, rgba);
+ for (i = i4 = 0; i < width; i++, i4 += 4) {
+ acc[i4+0] = rgba[i][RCOMP];
+ acc[i4+1] = rgba[i][GCOMP];
+ acc[i4+2] = rgba[i][BCOMP];
+ acc[i4+3] = rgba[i][ACOMP];
+ }
+ acc += width4;
+ ypos++;
+ }
+ }
+ else {
+ /* scaled integer accum buffer */
+ const GLfloat rscale = value * acc_scale / 255.0;
+ const GLfloat gscale = value * acc_scale / 255.0;
+ const GLfloat bscale = value * acc_scale / 255.0;
+ const GLfloat ascale = value * acc_scale / 255.0;
+ GLuint i, j;
+ for (j = 0; j < height; j++) {
+ GLaccum *acc = ctx->Buffer->Accum + ypos * width4 + xpos * 4;
+ gl_read_rgba_span(ctx, width, xpos, ypos, rgba);
+ for (i=0;i<width;i++) {
+ *acc++ = (GLaccum) ( (GLfloat) rgba[i][RCOMP] * rscale );
+ *acc++ = (GLaccum) ( (GLfloat) rgba[i][GCOMP] * gscale );
+ *acc++ = (GLaccum) ( (GLfloat) rgba[i][BCOMP] * bscale );
+ *acc++ = (GLaccum) ( (GLfloat) rgba[i][ACOMP] * ascale );
+ }
+ ypos++;
+ }
+ }
+ (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer );
+ break;
+
+ case GL_RETURN:
+ /* May have to leave optimized accum buffer mode */
+ if (ctx->IntegerAccumMode && value != 1.0)
+ rescale_accum(ctx);
+
+ if (ctx->IntegerAccumMode) {
+ /* build lookup table to avoid integer divides */
+ GLint divisor = (GLint) ((1.0F / ctx->IntegerAccumScaler) + 0.5F);
+ static GLubyte divTable[32768];
+ static GLint prevDivisor = 0.0;
+ GLuint j;
+ if (divisor != prevDivisor) {
+ assert(divisor * 256 <= 32768);
+ for (j = 0; j < divisor * 256; j++)
+ divTable[j] = j / divisor;
+ prevDivisor = divisor;
+ }
+
+ assert(ctx->IntegerAccumScaler > 0.0);
+ assert(ctx->IntegerAccumScaler <= 1.0);
+ for (j = 0; j < height; j++) {
+ const GLaccum *acc = ctx->Buffer->Accum + ypos * width4 + xpos*4;
+ GLuint i, i4;
+ for (i = i4 = 0; i < width; i++, i4 += 4) {
+ ASSERT(acc[i4+0] < divisor * 256);
+ ASSERT(acc[i4+1] < divisor * 256);
+ ASSERT(acc[i4+2] < divisor * 256);
+ ASSERT(acc[i4+3] < divisor * 256);
+ rgba[i][RCOMP] = divTable[acc[i4+0]];
+ rgba[i][GCOMP] = divTable[acc[i4+1]];
+ rgba[i][BCOMP] = divTable[acc[i4+2]];
+ rgba[i][ACOMP] = divTable[acc[i4+3]];
+ }
+ if (ctx->Color.SWmasking) {
+ gl_mask_rgba_span( ctx, width, xpos, ypos, rgba );
+ }
+ (*ctx->Driver.WriteRGBASpan)( ctx, width, xpos, ypos,
+ (const GLubyte (*)[4])rgba, NULL );
+ ypos++;
+ }
+ }
+ else {
+ const GLfloat rscale = value / acc_scale * 255.0F;
+ const GLfloat gscale = value / acc_scale * 255.0F;
+ const GLfloat bscale = value / acc_scale * 255.0F;
+ const GLfloat ascale = value / acc_scale * 255.0F;
+ GLuint i, j;
+ for (j=0;j<height;j++) {
+ const GLaccum *acc = ctx->Buffer->Accum + ypos * width4 + xpos*4;
+ for (i=0;i<width;i++) {
+ GLint r, g, b, a;
+ r = (GLint) ( (GLfloat) (*acc++) * rscale + 0.5F );
+ g = (GLint) ( (GLfloat) (*acc++) * gscale + 0.5F );
+ b = (GLint) ( (GLfloat) (*acc++) * bscale + 0.5F );
+ a = (GLint) ( (GLfloat) (*acc++) * ascale + 0.5F );
+ rgba[i][RCOMP] = CLAMP( r, 0, 255 );
+ rgba[i][GCOMP] = CLAMP( g, 0, 255 );
+ rgba[i][BCOMP] = CLAMP( b, 0, 255 );
+ rgba[i][ACOMP] = CLAMP( a, 0, 255 );
+ }
+ if (ctx->Color.SWmasking) {
+ gl_mask_rgba_span( ctx, width, xpos, ypos, rgba );
+ }
+ (*ctx->Driver.WriteRGBASpan)( ctx, width, xpos, ypos,
+ (const GLubyte (*)[4])rgba, NULL );
+ ypos++;
+ }
+ }
+ break;
+
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glAccum" );
+ }
+}
+
+
+
+/*
+ * Clear the accumulation Buffer.
+ */
+void gl_clear_accum_buffer( GLcontext *ctx )
+{
+ GLuint buffersize;
+ GLfloat acc_scale;
+
+ if (ctx->Visual->AccumBits==0) {
+ /* No accumulation buffer! */
+ return;
+ }
+
+ if (sizeof(GLaccum)==1) {
+ acc_scale = 127.0;
+ }
+ else if (sizeof(GLaccum)==2) {
+ acc_scale = 32767.0;
+ }
+ else {
+ /* sizeof(GLaccum) > 2 (Cray) */
+ acc_scale = (float) SHRT_MAX;
+ }
+
+ /* number of pixels */
+ buffersize = ctx->Buffer->Width * ctx->Buffer->Height;
+
+ if (!ctx->Buffer->Accum) {
+ /* try to alloc accumulation buffer */
+ ctx->Buffer->Accum = (GLaccum *)
+ malloc( buffersize * 4 * sizeof(GLaccum) );
+ }
+
+ if (ctx->Buffer->Accum) {
+ if (ctx->Scissor.Enabled) {
+ /* Limit clear to scissor box */
+ GLaccum r, g, b, a;
+ GLint i, j;
+ GLint width, height;
+ GLaccum *row;
+ r = (GLaccum) (ctx->Accum.ClearColor[0] * acc_scale);
+ g = (GLaccum) (ctx->Accum.ClearColor[1] * acc_scale);
+ b = (GLaccum) (ctx->Accum.ClearColor[2] * acc_scale);
+ a = (GLaccum) (ctx->Accum.ClearColor[3] * acc_scale);
+ /* size of region to clear */
+ width = 4 * (ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1);
+ height = ctx->Buffer->Ymax - ctx->Buffer->Ymin + 1;
+ /* ptr to first element to clear */
+ row = ctx->Buffer->Accum
+ + 4 * (ctx->Buffer->Ymin * ctx->Buffer->Width
+ + ctx->Buffer->Xmin);
+ for (j=0;j<height;j++) {
+ for (i=0;i<width;i+=4) {
+ row[i+0] = r;
+ row[i+1] = g;
+ row[i+2] = b;
+ row[i+3] = a;
+ }
+ row += 4 * ctx->Buffer->Width;
+ }
+ }
+ else {
+ /* clear whole buffer */
+ if (ctx->Accum.ClearColor[0]==0.0 &&
+ ctx->Accum.ClearColor[1]==0.0 &&
+ ctx->Accum.ClearColor[2]==0.0 &&
+ ctx->Accum.ClearColor[3]==0.0) {
+ /* Black */
+ MEMSET( ctx->Buffer->Accum, 0, buffersize * 4 * sizeof(GLaccum) );
+ }
+ else {
+ /* Not black */
+ GLaccum *acc, r, g, b, a;
+ GLuint i;
+
+ acc = ctx->Buffer->Accum;
+ r = (GLaccum) (ctx->Accum.ClearColor[0] * acc_scale);
+ g = (GLaccum) (ctx->Accum.ClearColor[1] * acc_scale);
+ b = (GLaccum) (ctx->Accum.ClearColor[2] * acc_scale);
+ a = (GLaccum) (ctx->Accum.ClearColor[3] * acc_scale);
+ for (i=0;i<buffersize;i++) {
+ *acc++ = r;
+ *acc++ = g;
+ *acc++ = b;
+ *acc++ = a;
+ }
+ }
+ }
+
+ /* update optimized accum state vars */
+ if (ctx->Accum.ClearColor[0] == 0.0 && ctx->Accum.ClearColor[1] == 0.0 &&
+ ctx->Accum.ClearColor[2] == 0.0 && ctx->Accum.ClearColor[3] == 0.0) {
+ ctx->IntegerAccumMode = GL_TRUE;
+ ctx->IntegerAccumScaler = 0.0; /* denotes empty accum buffer */
+ }
+ else {
+ ctx->IntegerAccumMode = GL_FALSE;
+ }
+ }
+}
diff --git a/src/mesa/main/accum.h b/src/mesa/main/accum.h
new file mode 100644
index 0000000000..dd641da456
--- /dev/null
+++ b/src/mesa/main/accum.h
@@ -0,0 +1,51 @@
+/* $Id: accum.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef ACCUM_H
+#define ACCUM_H
+
+
+#include "types.h"
+
+
+extern void gl_alloc_accum_buffer( GLcontext *ctx );
+
+
+extern void gl_Accum( GLcontext *ctx, GLenum op, GLfloat value );
+
+
+extern void gl_ClearAccum( GLcontext *ctx, GLfloat red, GLfloat green,
+ GLfloat blue, GLfloat alpha );
+
+
+extern void gl_clear_accum_buffer( GLcontext *ctx );
+
+
+#endif
diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c
new file mode 100644
index 0000000000..78f4d05b2c
--- /dev/null
+++ b/src/mesa/main/attrib.c
@@ -0,0 +1,863 @@
+/* $Id: attrib.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "attrib.h"
+#include "context.h"
+#include "enable.h"
+#include "enums.h"
+#include "macros.h"
+#include "misc.h"
+#include "simple_list.h"
+#include "texstate.h"
+#include "types.h"
+#ifdef XFree86Server
+#undef MISC_H
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+#define MALLOC_STRUCT(T) (struct T *) malloc( sizeof(struct T) )
+
+
+
+/*
+ * Allocate a new attribute state node. These nodes have a
+ * "kind" value and a pointer to a struct of state data.
+ */
+static struct gl_attrib_node *new_attrib_node( GLbitfield kind )
+{
+ struct gl_attrib_node *an;
+
+ an = (struct gl_attrib_node *) malloc( sizeof(struct gl_attrib_node) );
+ if (an) {
+ an->kind = kind;
+ }
+ return an;
+}
+
+
+
+/*
+ * Copy texture object state from one texture object to another.
+ */
+static void copy_texobj_state( struct gl_texture_object *dest,
+ const struct gl_texture_object *src )
+{
+ /*
+ dest->Name = src->Name;
+ dest->Dimensions = src->Dimensions;
+ */
+ dest->Priority = src->Priority;
+ dest->BorderColor[0] = src->BorderColor[0];
+ dest->BorderColor[1] = src->BorderColor[1];
+ dest->BorderColor[2] = src->BorderColor[2];
+ dest->BorderColor[3] = src->BorderColor[3];
+ dest->WrapS = src->WrapS;
+ dest->WrapT = src->WrapT;
+ dest->WrapR = src->WrapR;
+ dest->MinFilter = src->MinFilter;
+ dest->MagFilter = src->MagFilter;
+ dest->MinLod = src->MinLod;
+ dest->MaxLod = src->MaxLod;
+ dest->BaseLevel = src->BaseLevel;
+ dest->MaxLevel = src->MaxLevel;
+ dest->P = src->P;
+ dest->M = src->M;
+ dest->MinMagThresh = src->MinMagThresh;
+ memcpy( dest->Palette, src->Palette,
+ sizeof(GLubyte) * MAX_TEXTURE_PALETTE_SIZE * 4 );
+ dest->PaletteSize = src->PaletteSize;
+ dest->PaletteIntFormat = src->PaletteIntFormat;
+ dest->PaletteFormat = src->PaletteFormat;
+ dest->Complete = src->Complete;
+ dest->SampleFunc = src->SampleFunc;
+}
+
+
+
+void gl_PushAttrib( GLcontext* ctx, GLbitfield mask )
+{
+ struct gl_attrib_node *newnode;
+ struct gl_attrib_node *head;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPushAttrib");
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ fprintf(stderr, "glPushAttrib %x\n", mask);
+
+ if (ctx->AttribStackDepth>=MAX_ATTRIB_STACK_DEPTH) {
+ gl_error( ctx, GL_STACK_OVERFLOW, "glPushAttrib" );
+ return;
+ }
+
+ /* Build linked list of attribute nodes which save all attribute */
+ /* groups specified by the mask. */
+ head = NULL;
+
+ if (mask & GL_ACCUM_BUFFER_BIT) {
+ struct gl_accum_attrib *attr;
+ attr = MALLOC_STRUCT( gl_accum_attrib );
+ MEMCPY( attr, &ctx->Accum, sizeof(struct gl_accum_attrib) );
+ newnode = new_attrib_node( GL_ACCUM_BUFFER_BIT );
+ newnode->data = attr;
+ newnode->next = head;
+ head = newnode;
+ }
+
+ if (mask & GL_COLOR_BUFFER_BIT) {
+ struct gl_colorbuffer_attrib *attr;
+ attr = MALLOC_STRUCT( gl_colorbuffer_attrib );
+ MEMCPY( attr, &ctx->Color, sizeof(struct gl_colorbuffer_attrib) );
+ newnode = new_attrib_node( GL_COLOR_BUFFER_BIT );
+ newnode->data = attr;
+ newnode->next = head;
+ head = newnode;
+ }
+
+ if (mask & GL_CURRENT_BIT) {
+ struct gl_current_attrib *attr;
+ attr = MALLOC_STRUCT( gl_current_attrib );
+ MEMCPY( attr, &ctx->Current, sizeof(struct gl_current_attrib) );
+ newnode = new_attrib_node( GL_CURRENT_BIT );
+ newnode->data = attr;
+ newnode->next = head;
+ head = newnode;
+ }
+
+ if (mask & GL_DEPTH_BUFFER_BIT) {
+ struct gl_depthbuffer_attrib *attr;
+ attr = MALLOC_STRUCT( gl_depthbuffer_attrib );
+ MEMCPY( attr, &ctx->Depth, sizeof(struct gl_depthbuffer_attrib) );
+ newnode = new_attrib_node( GL_DEPTH_BUFFER_BIT );
+ newnode->data = attr;
+ newnode->next = head;
+ head = newnode;
+ }
+
+ if (mask & GL_ENABLE_BIT) {
+ struct gl_enable_attrib *attr;
+ GLuint i;
+ attr = MALLOC_STRUCT( gl_enable_attrib );
+ /* Copy enable flags from all other attributes into the enable struct. */
+ attr->AlphaTest = ctx->Color.AlphaEnabled;
+ attr->AutoNormal = ctx->Eval.AutoNormal;
+ attr->Blend = ctx->Color.BlendEnabled;
+ for (i=0;i<MAX_CLIP_PLANES;i++) {
+ attr->ClipPlane[i] = ctx->Transform.ClipEnabled[i];
+ }
+ attr->ColorMaterial = ctx->Light.ColorMaterialEnabled;
+ attr->CullFace = ctx->Polygon.CullFlag;
+ attr->DepthTest = ctx->Depth.Test;
+ attr->Dither = ctx->Color.DitherFlag;
+ attr->Fog = ctx->Fog.Enabled;
+ for (i=0;i<MAX_LIGHTS;i++) {
+ attr->Light[i] = ctx->Light.Light[i].Enabled;
+ }
+ attr->Lighting = ctx->Light.Enabled;
+ attr->LineSmooth = ctx->Line.SmoothFlag;
+ attr->LineStipple = ctx->Line.StippleFlag;
+ attr->IndexLogicOp = ctx->Color.IndexLogicOpEnabled;
+ attr->ColorLogicOp = ctx->Color.ColorLogicOpEnabled;
+ attr->Map1Color4 = ctx->Eval.Map1Color4;
+ attr->Map1Index = ctx->Eval.Map1Index;
+ attr->Map1Normal = ctx->Eval.Map1Normal;
+ attr->Map1TextureCoord1 = ctx->Eval.Map1TextureCoord1;
+ attr->Map1TextureCoord2 = ctx->Eval.Map1TextureCoord2;
+ attr->Map1TextureCoord3 = ctx->Eval.Map1TextureCoord3;
+ attr->Map1TextureCoord4 = ctx->Eval.Map1TextureCoord4;
+ attr->Map1Vertex3 = ctx->Eval.Map1Vertex3;
+ attr->Map1Vertex4 = ctx->Eval.Map1Vertex4;
+ attr->Map2Color4 = ctx->Eval.Map2Color4;
+ attr->Map2Index = ctx->Eval.Map2Index;
+ attr->Map2Normal = ctx->Eval.Map2Normal;
+ attr->Map2TextureCoord1 = ctx->Eval.Map2TextureCoord1;
+ attr->Map2TextureCoord2 = ctx->Eval.Map2TextureCoord2;
+ attr->Map2TextureCoord3 = ctx->Eval.Map2TextureCoord3;
+ attr->Map2TextureCoord4 = ctx->Eval.Map2TextureCoord4;
+ attr->Map2Vertex3 = ctx->Eval.Map2Vertex3;
+ attr->Map2Vertex4 = ctx->Eval.Map2Vertex4;
+ attr->Normalize = ctx->Transform.Normalize;
+ attr->PointSmooth = ctx->Point.SmoothFlag;
+ attr->PolygonOffsetPoint = ctx->Polygon.OffsetPoint;
+ attr->PolygonOffsetLine = ctx->Polygon.OffsetLine;
+ attr->PolygonOffsetFill = ctx->Polygon.OffsetFill;
+ attr->PolygonSmooth = ctx->Polygon.SmoothFlag;
+ attr->PolygonStipple = ctx->Polygon.StippleFlag;
+ attr->RescaleNormals = ctx->Transform.RescaleNormals;
+ attr->Scissor = ctx->Scissor.Enabled;
+ attr->Stencil = ctx->Stencil.Enabled;
+ attr->Texture = ctx->Texture.Enabled;
+ for (i=0; i<MAX_TEXTURE_UNITS; i++) {
+ attr->TexGen[i] = ctx->Texture.Unit[i].TexGenEnabled;
+ }
+ newnode = new_attrib_node( GL_ENABLE_BIT );
+ newnode->data = attr;
+ newnode->next = head;
+ head = newnode;
+ }
+
+ if (mask & GL_EVAL_BIT) {
+ struct gl_eval_attrib *attr;
+ attr = MALLOC_STRUCT( gl_eval_attrib );
+ MEMCPY( attr, &ctx->Eval, sizeof(struct gl_eval_attrib) );
+ newnode = new_attrib_node( GL_EVAL_BIT );
+ newnode->data = attr;
+ newnode->next = head;
+ head = newnode;
+ }
+
+ if (mask & GL_FOG_BIT) {
+ struct gl_fog_attrib *attr;
+ attr = MALLOC_STRUCT( gl_fog_attrib );
+ MEMCPY( attr, &ctx->Fog, sizeof(struct gl_fog_attrib) );
+ newnode = new_attrib_node( GL_FOG_BIT );
+ newnode->data = attr;
+ newnode->next = head;
+ head = newnode;
+ }
+
+ if (mask & GL_HINT_BIT) {
+ struct gl_hint_attrib *attr;
+ attr = MALLOC_STRUCT( gl_hint_attrib );
+ MEMCPY( attr, &ctx->Hint, sizeof(struct gl_hint_attrib) );
+ newnode = new_attrib_node( GL_HINT_BIT );
+ newnode->data = attr;
+ newnode->next = head;
+ head = newnode;
+ }
+
+ if (mask & GL_LIGHTING_BIT) {
+ struct gl_light_attrib *attr;
+ attr = MALLOC_STRUCT( gl_light_attrib );
+ MEMCPY( attr, &ctx->Light, sizeof(struct gl_light_attrib) );
+ newnode = new_attrib_node( GL_LIGHTING_BIT );
+ newnode->data = attr;
+ newnode->next = head;
+ head = newnode;
+ }
+
+ if (mask & GL_LINE_BIT) {
+ struct gl_line_attrib *attr;
+ attr = MALLOC_STRUCT( gl_line_attrib );
+ MEMCPY( attr, &ctx->Line, sizeof(struct gl_line_attrib) );
+ newnode = new_attrib_node( GL_LINE_BIT );
+ newnode->data = attr;
+ newnode->next = head;
+ head = newnode;
+ }
+
+ if (mask & GL_LIST_BIT) {
+ struct gl_list_attrib *attr;
+ attr = MALLOC_STRUCT( gl_list_attrib );
+ MEMCPY( attr, &ctx->List, sizeof(struct gl_list_attrib) );
+ newnode = new_attrib_node( GL_LIST_BIT );
+ newnode->data = attr;
+ newnode->next = head;
+ head = newnode;
+ }
+
+ if (mask & GL_PIXEL_MODE_BIT) {
+ struct gl_pixel_attrib *attr;
+ attr = MALLOC_STRUCT( gl_pixel_attrib );
+ MEMCPY( attr, &ctx->Pixel, sizeof(struct gl_pixel_attrib) );
+ newnode = new_attrib_node( GL_PIXEL_MODE_BIT );
+ newnode->data = attr;
+ newnode->next = head;
+ head = newnode;
+ }
+
+ if (mask & GL_POINT_BIT) {
+ struct gl_point_attrib *attr;
+ attr = MALLOC_STRUCT( gl_point_attrib );
+ MEMCPY( attr, &ctx->Point, sizeof(struct gl_point_attrib) );
+ newnode = new_attrib_node( GL_POINT_BIT );
+ newnode->data = attr;
+ newnode->next = head;
+ head = newnode;
+ }
+
+ if (mask & GL_POLYGON_BIT) {
+ struct gl_polygon_attrib *attr;
+ attr = MALLOC_STRUCT( gl_polygon_attrib );
+ MEMCPY( attr, &ctx->Polygon, sizeof(struct gl_polygon_attrib) );
+ newnode = new_attrib_node( GL_POLYGON_BIT );
+ newnode->data = attr;
+ newnode->next = head;
+ head = newnode;
+ }
+
+ if (mask & GL_POLYGON_STIPPLE_BIT) {
+ GLuint *stipple;
+ stipple = (GLuint *) malloc( 32*sizeof(GLuint) );
+ MEMCPY( stipple, ctx->PolygonStipple, 32*sizeof(GLuint) );
+ newnode = new_attrib_node( GL_POLYGON_STIPPLE_BIT );
+ newnode->data = stipple;
+ newnode->next = head;
+ head = newnode;
+ }
+
+ if (mask & GL_SCISSOR_BIT) {
+ struct gl_scissor_attrib *attr;
+ attr = MALLOC_STRUCT( gl_scissor_attrib );
+ MEMCPY( attr, &ctx->Scissor, sizeof(struct gl_scissor_attrib) );
+ newnode = new_attrib_node( GL_SCISSOR_BIT );
+ newnode->data = attr;
+ newnode->next = head;
+ head = newnode;
+ }
+
+ if (mask & GL_STENCIL_BUFFER_BIT) {
+ struct gl_stencil_attrib *attr;
+ attr = MALLOC_STRUCT( gl_stencil_attrib );
+ MEMCPY( attr, &ctx->Stencil, sizeof(struct gl_stencil_attrib) );
+ newnode = new_attrib_node( GL_STENCIL_BUFFER_BIT );
+ newnode->data = attr;
+ newnode->next = head;
+ head = newnode;
+ }
+
+ if (mask & GL_TEXTURE_BIT) {
+ struct gl_texture_attrib *attr;
+ GLuint u;
+ /* Take care of texture object reference counters */
+ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
+ ctx->Texture.Unit[u].CurrentD[1]->RefCount++;
+ ctx->Texture.Unit[u].CurrentD[2]->RefCount++;
+ ctx->Texture.Unit[u].CurrentD[3]->RefCount++;
+ }
+ attr = MALLOC_STRUCT( gl_texture_attrib );
+ MEMCPY( attr, &ctx->Texture, sizeof(struct gl_texture_attrib) );
+ /* copy state of the currently bound texture objects */
+ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
+ copy_texobj_state(&attr->Unit[u].Saved1D, attr->Unit[u].CurrentD[1]);
+ copy_texobj_state(&attr->Unit[u].Saved2D, attr->Unit[u].CurrentD[2]);
+ copy_texobj_state(&attr->Unit[u].Saved3D, attr->Unit[u].CurrentD[3]);
+ }
+ newnode = new_attrib_node( GL_TEXTURE_BIT );
+ newnode->data = attr;
+ newnode->next = head;
+ head = newnode;
+ }
+
+ if (mask & GL_TRANSFORM_BIT) {
+ struct gl_transform_attrib *attr;
+ attr = MALLOC_STRUCT( gl_transform_attrib );
+ MEMCPY( attr, &ctx->Transform, sizeof(struct gl_transform_attrib) );
+ newnode = new_attrib_node( GL_TRANSFORM_BIT );
+ newnode->data = attr;
+ newnode->next = head;
+ head = newnode;
+ }
+
+ if (mask & GL_VIEWPORT_BIT) {
+ struct gl_viewport_attrib *attr;
+ attr = MALLOC_STRUCT( gl_viewport_attrib );
+ MEMCPY( attr, &ctx->Viewport, sizeof(struct gl_viewport_attrib) );
+ newnode = new_attrib_node( GL_VIEWPORT_BIT );
+ newnode->data = attr;
+ newnode->next = head;
+ head = newnode;
+ }
+
+ ctx->AttribStack[ctx->AttribStackDepth] = head;
+ ctx->AttribStackDepth++;
+}
+
+
+
+/*
+ * This function is kind of long just because we have to call a lot
+ * of device driver functions to update device driver state.
+ */
+void gl_PopAttrib( GLcontext* ctx )
+{
+ struct gl_attrib_node *attr, *next;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPopAttrib");
+
+
+ if (ctx->AttribStackDepth==0) {
+ gl_error( ctx, GL_STACK_UNDERFLOW, "glPopAttrib" );
+ return;
+ }
+
+ ctx->AttribStackDepth--;
+ attr = ctx->AttribStack[ctx->AttribStackDepth];
+
+ while (attr) {
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ fprintf(stderr, "glPopAttrib %s\n", gl_lookup_enum_by_nr(attr->kind));
+
+ switch (attr->kind) {
+ case GL_ACCUM_BUFFER_BIT:
+ MEMCPY( &ctx->Accum, attr->data, sizeof(struct gl_accum_attrib) );
+ break;
+ case GL_COLOR_BUFFER_BIT:
+ {
+ GLenum oldDrawBuffer = ctx->Color.DrawBuffer;
+ GLenum oldAlphaFunc = ctx->Color.AlphaFunc;
+ GLubyte oldAlphaRef = ctx->Color.AlphaRef;
+ GLenum oldBlendSrc = ctx->Color.BlendSrcRGB;
+ GLenum oldBlendDst = ctx->Color.BlendDstRGB;
+ MEMCPY( &ctx->Color, attr->data,
+ sizeof(struct gl_colorbuffer_attrib) );
+ if (ctx->Color.DrawBuffer != oldDrawBuffer) {
+ gl_DrawBuffer(ctx, ctx->Color.DrawBuffer);
+ }
+ if ((ctx->Color.AlphaFunc != oldAlphaFunc ||
+ ctx->Color.AlphaRef != oldAlphaRef) &&
+ ctx->Driver.AlphaFunc)
+ (*ctx->Driver.AlphaFunc)( ctx, ctx->Color.AlphaFunc,
+ ctx->Color.AlphaRef / 255.0F);
+ if ((ctx->Color.BlendSrcRGB != oldBlendSrc ||
+ ctx->Color.BlendSrcRGB != oldBlendDst) &&
+ ctx->Driver.BlendFunc)
+ (*ctx->Driver.BlendFunc)( ctx, ctx->Color.BlendSrcRGB,
+ ctx->Color.BlendDstRGB);
+ }
+ break;
+ case GL_CURRENT_BIT:
+ MEMCPY( &ctx->Current, attr->data,
+ sizeof(struct gl_current_attrib) );
+ break;
+ case GL_DEPTH_BUFFER_BIT:
+ {
+ GLenum oldDepthFunc = ctx->Depth.Func;
+ GLboolean oldDepthMask = ctx->Depth.Mask;
+ GLfloat oldDepthClear = ctx->Depth.Clear;
+ MEMCPY( &ctx->Depth, attr->data,
+ sizeof(struct gl_depthbuffer_attrib) );
+ if (ctx->Depth.Func != oldDepthFunc && ctx->Driver.DepthFunc)
+ (*ctx->Driver.DepthFunc)( ctx, ctx->Depth.Func );
+ if (ctx->Depth.Mask != oldDepthMask && ctx->Driver.DepthMask)
+ (*ctx->Driver.DepthMask)( ctx, ctx->Depth.Mask );
+ if (ctx->Depth.Clear != oldDepthClear && ctx->Driver.ClearDepth)
+ (*ctx->Driver.ClearDepth)( ctx, ctx->Depth.Clear );
+ }
+ break;
+ case GL_ENABLE_BIT:
+ {
+ const struct gl_enable_attrib *enable;
+ enable = (const struct gl_enable_attrib *) attr->data;
+
+#define TEST_AND_UPDATE(VALUE, NEWVALUE, ENUM) \
+ if ((VALUE) != (NEWVALUE)) { \
+ gl_set_enable( ctx, ENUM, (NEWVALUE) ); \
+ }
+
+ TEST_AND_UPDATE(ctx->Color.AlphaEnabled, enable->AlphaTest, GL_ALPHA_TEST);
+ TEST_AND_UPDATE(ctx->Transform.Normalize, enable->AutoNormal, GL_NORMALIZE);
+ TEST_AND_UPDATE(ctx->Color.BlendEnabled, enable->Blend, GL_BLEND);
+ {
+ GLuint i;
+ for (i=0;i<MAX_CLIP_PLANES;i++) {
+ if (ctx->Transform.ClipEnabled[i] != enable->ClipPlane[i])
+ gl_set_enable( ctx, (GLenum) (GL_CLIP_PLANE0 + i), enable->ClipPlane[i] );
+ }
+ }
+ TEST_AND_UPDATE(ctx->Light.ColorMaterialEnabled, enable->ColorMaterial, GL_COLOR_MATERIAL);
+ TEST_AND_UPDATE(ctx->Polygon.CullFlag, enable->CullFace, GL_CULL_FACE);
+ TEST_AND_UPDATE(ctx->Color.DitherFlag, enable->Dither, GL_DITHER);
+ TEST_AND_UPDATE(ctx->Fog.Enabled, enable->Fog, GL_FOG);
+ TEST_AND_UPDATE(ctx->Light.Enabled, enable->Lighting, GL_LIGHTING);
+ TEST_AND_UPDATE(ctx->Line.SmoothFlag, enable->LineSmooth, GL_LINE_SMOOTH);
+ TEST_AND_UPDATE(ctx->Line.StippleFlag, enable->LineStipple, GL_LINE_STIPPLE);
+ TEST_AND_UPDATE(ctx->Color.IndexLogicOpEnabled, enable->IndexLogicOp, GL_INDEX_LOGIC_OP);
+ TEST_AND_UPDATE(ctx->Color.ColorLogicOpEnabled, enable->ColorLogicOp, GL_COLOR_LOGIC_OP);
+ TEST_AND_UPDATE(ctx->Eval.Map1Color4, enable->Map1Color4, GL_MAP1_COLOR_4);
+ TEST_AND_UPDATE(ctx->Eval.Map1Index, enable->Map1Index, GL_MAP1_INDEX);
+ TEST_AND_UPDATE(ctx->Eval.Map1Normal, enable->Map1Normal, GL_MAP1_NORMAL);
+ TEST_AND_UPDATE(ctx->Eval.Map1TextureCoord1, enable->Map1TextureCoord1, GL_MAP1_TEXTURE_COORD_1);
+ TEST_AND_UPDATE(ctx->Eval.Map1TextureCoord2, enable->Map1TextureCoord2, GL_MAP1_TEXTURE_COORD_2);
+ TEST_AND_UPDATE(ctx->Eval.Map1TextureCoord3, enable->Map1TextureCoord3, GL_MAP1_TEXTURE_COORD_3);
+ TEST_AND_UPDATE(ctx->Eval.Map1TextureCoord4, enable->Map1TextureCoord4, GL_MAP1_TEXTURE_COORD_4);
+ TEST_AND_UPDATE(ctx->Eval.Map1Vertex3, enable->Map1Vertex3, GL_MAP1_VERTEX_3);
+ TEST_AND_UPDATE(ctx->Eval.Map1Vertex4, enable->Map1Vertex4, GL_MAP1_VERTEX_4);
+ TEST_AND_UPDATE(ctx->Eval.Map2Color4, enable->Map2Color4, GL_MAP2_COLOR_4);
+ TEST_AND_UPDATE(ctx->Eval.Map2Index, enable->Map2Index, GL_MAP2_INDEX);
+ TEST_AND_UPDATE(ctx->Eval.Map2Normal, enable->Map2Normal, GL_MAP2_NORMAL);
+ TEST_AND_UPDATE(ctx->Eval.Map2TextureCoord1, enable->Map2TextureCoord1, GL_MAP2_TEXTURE_COORD_1);
+ TEST_AND_UPDATE(ctx->Eval.Map2TextureCoord2, enable->Map2TextureCoord2, GL_MAP2_TEXTURE_COORD_2);
+ TEST_AND_UPDATE(ctx->Eval.Map2TextureCoord3, enable->Map2TextureCoord3, GL_MAP2_TEXTURE_COORD_3);
+ TEST_AND_UPDATE(ctx->Eval.Map2TextureCoord4, enable->Map2TextureCoord4, GL_MAP2_TEXTURE_COORD_4);
+ TEST_AND_UPDATE(ctx->Eval.Map2Vertex3, enable->Map2Vertex3, GL_MAP2_VERTEX_3);
+ TEST_AND_UPDATE(ctx->Eval.Map2Vertex4, enable->Map2Vertex4, GL_MAP2_VERTEX_4);
+ TEST_AND_UPDATE(ctx->Transform.Normalize, enable->Normalize, GL_NORMALIZE);
+ TEST_AND_UPDATE(ctx->Transform.RescaleNormals, enable->RescaleNormals, GL_RESCALE_NORMAL_EXT);
+ TEST_AND_UPDATE(ctx->Point.SmoothFlag, enable->PointSmooth, GL_POINT_SMOOTH);
+ TEST_AND_UPDATE(ctx->Polygon.OffsetPoint, enable->PolygonOffsetPoint, GL_POLYGON_OFFSET_POINT);
+ TEST_AND_UPDATE(ctx->Polygon.OffsetLine, enable->PolygonOffsetLine, GL_POLYGON_OFFSET_LINE);
+ TEST_AND_UPDATE(ctx->Polygon.OffsetFill, enable->PolygonOffsetFill, GL_POLYGON_OFFSET_FILL);
+ TEST_AND_UPDATE(ctx->Polygon.SmoothFlag, enable->PolygonSmooth, GL_POLYGON_SMOOTH);
+ TEST_AND_UPDATE(ctx->Polygon.StippleFlag, enable->PolygonStipple, GL_POLYGON_STIPPLE);
+ TEST_AND_UPDATE(ctx->Scissor.Enabled, enable->Scissor, GL_SCISSOR_TEST);
+ TEST_AND_UPDATE(ctx->Stencil.Enabled, enable->Stencil, GL_STENCIL_TEST);
+ if (ctx->Texture.Enabled != enable->Texture) {
+ ctx->Texture.Enabled = enable->Texture;
+ if (ctx->Driver.Enable) {
+ if (ctx->Driver.ActiveTexture)
+ (*ctx->Driver.ActiveTexture)( ctx, 0 );
+ (*ctx->Driver.Enable)( ctx, GL_TEXTURE_1D, (GLboolean) (enable->Texture & TEXTURE0_1D) );
+ (*ctx->Driver.Enable)( ctx, GL_TEXTURE_2D, (GLboolean) (enable->Texture & TEXTURE0_2D) );
+ (*ctx->Driver.Enable)( ctx, GL_TEXTURE_3D, (GLboolean) (enable->Texture & TEXTURE0_3D) );
+ if (ctx->Driver.ActiveTexture)
+ (*ctx->Driver.ActiveTexture)( ctx, 1 );
+ (*ctx->Driver.Enable)( ctx, GL_TEXTURE_1D, (GLboolean) (enable->Texture & TEXTURE1_1D) );
+ (*ctx->Driver.Enable)( ctx, GL_TEXTURE_2D, (GLboolean) (enable->Texture & TEXTURE1_2D) );
+ (*ctx->Driver.Enable)( ctx, GL_TEXTURE_3D, (GLboolean) (enable->Texture & TEXTURE1_3D) );
+ if (ctx->Driver.ActiveTexture)
+ (*ctx->Driver.ActiveTexture)( ctx, ctx->Texture.CurrentUnit );
+ }
+ }
+#undef TEST_AND_UPDATE
+ {
+ GLuint i;
+ for (i=0; i<MAX_TEXTURE_UNITS; i++) {
+ if (ctx->Texture.Unit[i].TexGenEnabled != enable->TexGen[i]) {
+ ctx->Texture.Unit[i].TexGenEnabled = enable->TexGen[i];
+
+ /* ctx->Enabled recalculated in state change
+ processing */
+
+ if (ctx->Driver.Enable) {
+ if (ctx->Driver.ActiveTexture)
+ (*ctx->Driver.ActiveTexture)( ctx, i );
+ if (enable->TexGen[i] & S_BIT)
+ (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_S, GL_TRUE);
+ else
+ (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_S, GL_FALSE);
+ if (enable->TexGen[i] & T_BIT)
+ (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_T, GL_TRUE);
+ else
+ (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_T, GL_FALSE);
+ if (enable->TexGen[i] & R_BIT)
+ (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_R, GL_TRUE);
+ else
+ (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_R, GL_FALSE);
+ if (enable->TexGen[i] & Q_BIT)
+ (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_Q, GL_TRUE);
+ else
+ (*ctx->Driver.Enable)( ctx, GL_TEXTURE_GEN_Q, GL_FALSE);
+ }
+ }
+ }
+ if (ctx->Driver.ActiveTexture)
+ (*ctx->Driver.ActiveTexture)( ctx, ctx->Texture.CurrentUnit );
+ }
+ }
+ break;
+ case GL_EVAL_BIT:
+ MEMCPY( &ctx->Eval, attr->data, sizeof(struct gl_eval_attrib) );
+ break;
+ case GL_FOG_BIT:
+ {
+ GLboolean anyChange = (memcmp( &ctx->Fog, attr->data, sizeof(struct gl_fog_attrib) ) != 0);
+ MEMCPY( &ctx->Fog, attr->data, sizeof(struct gl_fog_attrib) );
+ if (anyChange && ctx->Driver.Fogfv) {
+ const GLfloat mode = ctx->Fog.Mode;
+ const GLfloat density = ctx->Fog.Density;
+ const GLfloat start = ctx->Fog.Start;
+ const GLfloat end = ctx->Fog.End;
+ const GLfloat index = ctx->Fog.Index;
+ (*ctx->Driver.Fogfv)( ctx, GL_FOG_MODE, &mode);
+ (*ctx->Driver.Fogfv)( ctx, GL_FOG_DENSITY, &density );
+ (*ctx->Driver.Fogfv)( ctx, GL_FOG_START, &start );
+ (*ctx->Driver.Fogfv)( ctx, GL_FOG_END, &end );
+ (*ctx->Driver.Fogfv)( ctx, GL_FOG_INDEX, &index );
+ (*ctx->Driver.Fogfv)( ctx, GL_FOG_COLOR, ctx->Fog.Color );
+ }
+ ctx->Enabled &= ENABLE_FOG;
+ if (ctx->Fog.Enabled) ctx->Enabled |= ENABLE_FOG;
+ }
+ break;
+ case GL_HINT_BIT:
+ MEMCPY( &ctx->Hint, attr->data, sizeof(struct gl_hint_attrib) );
+ if (ctx->Driver.Hint) {
+ (*ctx->Driver.Hint)( ctx, GL_PERSPECTIVE_CORRECTION_HINT,
+ ctx->Hint.PerspectiveCorrection );
+ (*ctx->Driver.Hint)( ctx, GL_POINT_SMOOTH_HINT,
+ ctx->Hint.PointSmooth);
+ (*ctx->Driver.Hint)( ctx, GL_LINE_SMOOTH_HINT,
+ ctx->Hint.LineSmooth );
+ (*ctx->Driver.Hint)( ctx, GL_POLYGON_SMOOTH_HINT,
+ ctx->Hint.PolygonSmooth );
+ (*ctx->Driver.Hint)( ctx, GL_FOG_HINT, ctx->Hint.Fog );
+ }
+ break;
+ case GL_LIGHTING_BIT:
+ MEMCPY( &ctx->Light, attr->data, sizeof(struct gl_light_attrib) );
+ if (ctx->Driver.Enable) {
+ GLuint i;
+ for (i = 0; i < MAX_LIGHTS; i++) {
+ GLenum light = (GLenum) (GL_LIGHT0 + i);
+ (*ctx->Driver.Enable)( ctx, light, ctx->Light.Light[i].Enabled );
+ }
+ (*ctx->Driver.Enable)( ctx, GL_LIGHTING, ctx->Light.Enabled );
+ }
+ ctx->Enabled &= ENABLE_LIGHT;
+ if (ctx->Light.Enabled && !is_empty_list(&ctx->Light.EnabledList))
+ ctx->Enabled |= ENABLE_LIGHT;
+ break;
+ case GL_LINE_BIT:
+ MEMCPY( &ctx->Line, attr->data, sizeof(struct gl_line_attrib) );
+ if (ctx->Driver.Enable) {
+ (*ctx->Driver.Enable)( ctx, GL_LINE_SMOOTH, ctx->Line.SmoothFlag );
+ (*ctx->Driver.Enable)( ctx, GL_LINE_STIPPLE, ctx->Line.StippleFlag );
+ }
+ break;
+ case GL_LIST_BIT:
+ MEMCPY( &ctx->List, attr->data, sizeof(struct gl_list_attrib) );
+ break;
+ case GL_PIXEL_MODE_BIT:
+ MEMCPY( &ctx->Pixel, attr->data, sizeof(struct gl_pixel_attrib) );
+ break;
+ case GL_POINT_BIT:
+ MEMCPY( &ctx->Point, attr->data, sizeof(struct gl_point_attrib) );
+ if (ctx->Driver.Enable)
+ (*ctx->Driver.Enable)( ctx, GL_POINT_SMOOTH, ctx->Point.SmoothFlag );
+ break;
+ case GL_POLYGON_BIT:
+ {
+ GLenum oldFrontMode = ctx->Polygon.FrontMode;
+ GLenum oldBackMode = ctx->Polygon.BackMode;
+ MEMCPY( &ctx->Polygon, attr->data,
+ sizeof(struct gl_polygon_attrib) );
+ if ((ctx->Polygon.FrontMode != oldFrontMode ||
+ ctx->Polygon.BackMode != oldBackMode) &&
+ ctx->Driver.PolygonMode) {
+ (*ctx->Driver.PolygonMode)( ctx, GL_FRONT, ctx->Polygon.FrontMode);
+ (*ctx->Driver.PolygonMode)( ctx, GL_BACK, ctx->Polygon.BackMode);
+ }
+ if (ctx->Driver.CullFace)
+ ctx->Driver.CullFace( ctx, ctx->Polygon.CullFaceMode );
+
+ if (ctx->Driver.FrontFace)
+ ctx->Driver.FrontFace( ctx, ctx->Polygon.FrontFace );
+
+ if (ctx->Driver.Enable)
+ (*ctx->Driver.Enable)( ctx, GL_POLYGON_SMOOTH, ctx->Polygon.SmoothFlag );
+ }
+ break;
+ case GL_POLYGON_STIPPLE_BIT:
+ MEMCPY( ctx->PolygonStipple, attr->data, 32*sizeof(GLuint) );
+ break;
+ case GL_SCISSOR_BIT:
+ MEMCPY( &ctx->Scissor, attr->data,
+ sizeof(struct gl_scissor_attrib) );
+ if (ctx->Driver.Enable)
+ (*ctx->Driver.Enable)( ctx, GL_SCISSOR_TEST, ctx->Scissor.Enabled );
+ if (ctx->Driver.Scissor)
+ ctx->Driver.Scissor( ctx, ctx->Scissor.X, ctx->Scissor.Y,
+ ctx->Scissor.Width, ctx->Scissor.Height );
+ break;
+ case GL_STENCIL_BUFFER_BIT:
+ MEMCPY( &ctx->Stencil, attr->data,
+ sizeof(struct gl_stencil_attrib) );
+ if (ctx->Driver.StencilFunc)
+ (*ctx->Driver.StencilFunc)( ctx, ctx->Stencil.Function,
+ ctx->Stencil.Ref, ctx->Stencil.ValueMask);
+ if (ctx->Driver.StencilMask)
+ (*ctx->Driver.StencilMask)( ctx, ctx->Stencil.WriteMask );
+ if (ctx->Driver.StencilOp)
+ (*ctx->Driver.StencilOp)( ctx, ctx->Stencil.FailFunc,
+ ctx->Stencil.ZFailFunc, ctx->Stencil.ZPassFunc);
+ if (ctx->Driver.ClearStencil)
+ (*ctx->Driver.ClearStencil)( ctx, ctx->Stencil.Clear );
+ if (ctx->Driver.Enable)
+ (*ctx->Driver.Enable)( ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled );
+ break;
+ case GL_TRANSFORM_BIT:
+ MEMCPY( &ctx->Transform, attr->data,
+ sizeof(struct gl_transform_attrib) );
+ if (ctx->Driver.Enable) {
+ (*ctx->Driver.Enable)( ctx, GL_NORMALIZE, ctx->Transform.Normalize );
+ (*ctx->Driver.Enable)( ctx, GL_RESCALE_NORMAL_EXT, ctx->Transform.RescaleNormals );
+ }
+ ctx->Enabled &= ~(ENABLE_NORMALIZE|ENABLE_RESCALE);
+ if (ctx->Transform.Normalize) ctx->Enabled |= ENABLE_NORMALIZE;
+ if (ctx->Transform.RescaleNormals) ctx->Enabled |= ENABLE_RESCALE;
+ break;
+ case GL_TEXTURE_BIT:
+ /* Take care of texture object reference counters */
+ {
+ GLuint u;
+ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
+ ctx->Texture.Unit[u].CurrentD[1]->RefCount--;
+ ctx->Texture.Unit[u].CurrentD[2]->RefCount--;
+ ctx->Texture.Unit[u].CurrentD[3]->RefCount--;
+ }
+ MEMCPY( &ctx->Texture, attr->data,
+ sizeof(struct gl_texture_attrib) );
+ /* restore state of the currently bound texture objects */
+ for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
+ copy_texobj_state( ctx->Texture.Unit[u].CurrentD[1],
+ &(ctx->Texture.Unit[u].Saved1D) );
+ copy_texobj_state( ctx->Texture.Unit[u].CurrentD[2],
+ &(ctx->Texture.Unit[u].Saved2D) );
+ copy_texobj_state( ctx->Texture.Unit[u].CurrentD[3],
+ &(ctx->Texture.Unit[u].Saved3D) );
+ gl_put_texobj_on_dirty_list( ctx, ctx->Texture.Unit[u].CurrentD[1] );
+ gl_put_texobj_on_dirty_list( ctx, ctx->Texture.Unit[u].CurrentD[2] );
+ gl_put_texobj_on_dirty_list( ctx, ctx->Texture.Unit[u].CurrentD[3] );
+
+ }
+ }
+ break;
+ case GL_VIEWPORT_BIT:
+ MEMCPY( &ctx->Viewport, attr->data,
+ sizeof(struct gl_viewport_attrib) );
+ if (ctx->Driver.Viewport) {
+ (*ctx->Driver.Viewport)( ctx, ctx->Viewport.X, ctx->Viewport.Y,
+ ctx->Viewport.Width, ctx->Viewport.Height );
+ }
+ if (ctx->Driver.DepthRange) {
+ (*ctx->Driver.DepthRange)( ctx, ctx->Viewport.Near,
+ ctx->Viewport.Far );
+ }
+ break;
+ default:
+ gl_problem( ctx, "Bad attrib flag in PopAttrib");
+ break;
+ }
+
+ next = attr->next;
+ free( (void *) attr->data );
+ free( (void *) attr );
+ attr = next;
+ }
+
+ ctx->NewState = NEW_ALL;
+}
+
+
+#define GL_CLIENT_PACK_BIT (1<<20)
+#define GL_CLIENT_UNPACK_BIT (1<<21)
+
+
+void gl_PushClientAttrib( GLcontext *ctx, GLbitfield mask )
+{
+ struct gl_attrib_node *newnode;
+ struct gl_attrib_node *head;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPushClientAttrib");
+
+ if (ctx->ClientAttribStackDepth>=MAX_CLIENT_ATTRIB_STACK_DEPTH) {
+ gl_error( ctx, GL_STACK_OVERFLOW, "glPushClientAttrib" );
+ return;
+ }
+
+ /* Build linked list of attribute nodes which save all attribute */
+ /* groups specified by the mask. */
+ head = NULL;
+
+ if (mask & GL_CLIENT_PIXEL_STORE_BIT) {
+ struct gl_pixelstore_attrib *attr;
+ /* packing attribs */
+ attr = MALLOC_STRUCT( gl_pixelstore_attrib );
+ MEMCPY( attr, &ctx->Pack, sizeof(struct gl_pixelstore_attrib) );
+ newnode = new_attrib_node( GL_CLIENT_PACK_BIT );
+ newnode->data = attr;
+ newnode->next = head;
+ head = newnode;
+ /* unpacking attribs */
+ attr = MALLOC_STRUCT( gl_pixelstore_attrib );
+ MEMCPY( attr, &ctx->Unpack, sizeof(struct gl_pixelstore_attrib) );
+ newnode = new_attrib_node( GL_CLIENT_UNPACK_BIT );
+ newnode->data = attr;
+ newnode->next = head;
+ head = newnode;
+ }
+ if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) {
+ struct gl_array_attrib *attr;
+ attr = MALLOC_STRUCT( gl_array_attrib );
+ MEMCPY( attr, &ctx->Array, sizeof(struct gl_array_attrib) );
+ newnode = new_attrib_node( GL_CLIENT_VERTEX_ARRAY_BIT );
+ newnode->data = attr;
+ newnode->next = head;
+ head = newnode;
+ }
+
+ ctx->ClientAttribStack[ctx->ClientAttribStackDepth] = head;
+ ctx->ClientAttribStackDepth++;
+}
+
+
+
+
+void gl_PopClientAttrib( GLcontext *ctx )
+{
+ struct gl_attrib_node *attr, *next;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPopClientAttrib");
+
+ if (ctx->ClientAttribStackDepth==0) {
+ gl_error( ctx, GL_STACK_UNDERFLOW, "glPopClientAttrib" );
+ return;
+ }
+
+ ctx->ClientAttribStackDepth--;
+ attr = ctx->ClientAttribStack[ctx->ClientAttribStackDepth];
+
+ while (attr) {
+ switch (attr->kind) {
+ case GL_CLIENT_PACK_BIT:
+ MEMCPY( &ctx->Pack, attr->data,
+ sizeof(struct gl_pixelstore_attrib) );
+ break;
+ case GL_CLIENT_UNPACK_BIT:
+ MEMCPY( &ctx->Unpack, attr->data,
+ sizeof(struct gl_pixelstore_attrib) );
+ break;
+ case GL_CLIENT_VERTEX_ARRAY_BIT:
+ MEMCPY( &ctx->Array, attr->data,
+ sizeof(struct gl_array_attrib) );
+ break;
+ default:
+ gl_problem( ctx, "Bad attrib flag in PopClientAttrib");
+ break;
+ }
+
+ next = attr->next;
+ free( (void *) attr->data );
+ free( (void *) attr );
+ attr = next;
+ }
+
+ ctx->NewState = NEW_ALL;
+}
+
diff --git a/src/mesa/main/attrib.h b/src/mesa/main/attrib.h
new file mode 100644
index 0000000000..0661c26123
--- /dev/null
+++ b/src/mesa/main/attrib.h
@@ -0,0 +1,47 @@
+/* $Id: attrib.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef ATTRIB_H
+#define ATTRIB_h
+
+
+#include "types.h"
+
+
+extern void gl_PushAttrib( GLcontext* ctx, GLbitfield mask );
+
+extern void gl_PopAttrib( GLcontext* ctx );
+
+extern void gl_PushClientAttrib( GLcontext *ctx, GLbitfield mask );
+
+extern void gl_PopClientAttrib( GLcontext *ctx );
+
+
+#endif
diff --git a/src/mesa/main/blend.c b/src/mesa/main/blend.c
new file mode 100644
index 0000000000..10119ac3b3
--- /dev/null
+++ b/src/mesa/main/blend.c
@@ -0,0 +1,812 @@
+/* $Id: blend.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "alphabuf.h"
+#include "blend.h"
+#include "context.h"
+#include "enums.h"
+#include "macros.h"
+#include "pb.h"
+#include "span.h"
+#include "types.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+void gl_BlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glBlendFunc");
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ fprintf(stderr, "glBlendFunc %s %s\n",
+ gl_lookup_enum_by_nr(sfactor),
+ gl_lookup_enum_by_nr(dfactor));
+
+ switch (sfactor) {
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_SRC_ALPHA_SATURATE:
+ case GL_CONSTANT_COLOR:
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ case GL_CONSTANT_ALPHA:
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ ctx->Color.BlendSrcRGB = ctx->Color.BlendSrcA = sfactor;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glBlendFunc(sfactor)" );
+ return;
+ }
+
+ switch (dfactor) {
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_CONSTANT_COLOR:
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ case GL_CONSTANT_ALPHA:
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ ctx->Color.BlendDstRGB = ctx->Color.BlendDstA = dfactor;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glBlendFunc(dfactor)" );
+ return;
+ }
+
+ if (ctx->Driver.BlendFunc) {
+ (*ctx->Driver.BlendFunc)( ctx, sfactor, dfactor );
+ }
+
+ ctx->Color.BlendFunc = NULL;
+ ctx->NewState |= NEW_RASTER_OPS;
+}
+
+
+/* GL_INGR_blend_func_separate */
+void
+gl_BlendFuncSeparate( GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB,
+ GLenum sfactorA, GLenum dfactorA )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glBlendFuncSeparate");
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ fprintf(stderr, "glBlendFuncSeperate %s %s %s %s\n",
+ gl_lookup_enum_by_nr(sfactorRGB),
+ gl_lookup_enum_by_nr(dfactorRGB),
+ gl_lookup_enum_by_nr(sfactorA),
+ gl_lookup_enum_by_nr(dfactorA));
+
+ switch (sfactorRGB) {
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_SRC_ALPHA_SATURATE:
+ case GL_CONSTANT_COLOR:
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ case GL_CONSTANT_ALPHA:
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ ctx->Color.BlendSrcRGB = sfactorRGB;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorRGB)" );
+ return;
+ }
+
+ switch (dfactorRGB) {
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_CONSTANT_COLOR:
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ case GL_CONSTANT_ALPHA:
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ ctx->Color.BlendDstRGB = dfactorRGB;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorRGB)" );
+ return;
+ }
+
+ switch (sfactorA) {
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_SRC_ALPHA_SATURATE:
+ case GL_CONSTANT_COLOR:
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ case GL_CONSTANT_ALPHA:
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ ctx->Color.BlendSrcA = sfactorA;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(sfactorA)" );
+ return;
+ }
+
+ switch (dfactorA) {
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_CONSTANT_COLOR:
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ case GL_CONSTANT_ALPHA:
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ ctx->Color.BlendDstA = dfactorA;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glBlendFuncSeparate(dfactorA)" );
+ return;
+ }
+
+ ctx->Color.BlendFunc = NULL;
+ ctx->NewState |= NEW_RASTER_OPS;
+}
+
+
+
+/* This is really an extension function! */
+void gl_BlendEquation( GLcontext *ctx, GLenum mode )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glBlendEquation");
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ fprintf(stderr, "glBlendEquation %s\n",
+ gl_lookup_enum_by_nr(mode));
+
+
+ switch (mode) {
+ case GL_MIN_EXT:
+ case GL_MAX_EXT:
+ case GL_LOGIC_OP:
+ case GL_FUNC_ADD_EXT:
+ case GL_FUNC_SUBTRACT_EXT:
+ case GL_FUNC_REVERSE_SUBTRACT_EXT:
+ ctx->Color.BlendEquation = mode;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glBlendEquation" );
+ return;
+ }
+
+ /* This is needed to support 1.1's RGB logic ops AND
+ * 1.0's blending logicops.
+ */
+ if (mode==GL_LOGIC_OP && ctx->Color.BlendEnabled) {
+ ctx->Color.ColorLogicOpEnabled = GL_TRUE;
+ }
+ else {
+ ctx->Color.ColorLogicOpEnabled = GL_FALSE;
+ }
+
+ ctx->Color.BlendFunc = NULL;
+ ctx->NewState |= NEW_RASTER_OPS;
+}
+
+
+
+void gl_BlendColor( GLcontext *ctx, GLclampf red, GLclampf green,
+ GLclampf blue, GLclampf alpha )
+{
+ ctx->Color.BlendColor[0] = CLAMP( red, 0.0, 1.0 );
+ ctx->Color.BlendColor[1] = CLAMP( green, 0.0, 1.0 );
+ ctx->Color.BlendColor[2] = CLAMP( blue, 0.0, 1.0 );
+ ctx->Color.BlendColor[3] = CLAMP( alpha, 0.0, 1.0 );
+}
+
+
+
+/*
+ * Common transparency blending mode.
+ */
+static void blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLubyte rgba[][4], CONST GLubyte dest[][4] )
+{
+ GLuint i;
+ ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
+ ASSERT(ctx->Color.BlendSrcRGB==GL_SRC_ALPHA);
+ ASSERT(ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA);
+ (void) ctx;
+
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLint t = rgba[i][ACOMP]; /* t in [0,255] */
+ if (t == 0) {
+ rgba[i][RCOMP] = dest[i][RCOMP];
+ rgba[i][GCOMP] = dest[i][GCOMP];
+ rgba[i][BCOMP] = dest[i][BCOMP];
+ rgba[i][ACOMP] = dest[i][ACOMP];
+ }
+ else if (t == 255) {
+ /* no-op */
+ }
+ else {
+ GLint s = 255 - t;
+ GLint r = (rgba[i][RCOMP] * t + dest[i][RCOMP] * s) >> 8;
+ GLint g = (rgba[i][GCOMP] * t + dest[i][GCOMP] * s) >> 8;
+ GLint b = (rgba[i][BCOMP] * t + dest[i][BCOMP] * s) >> 8;
+ GLint a = (rgba[i][ACOMP] * t + dest[i][ACOMP] * s) >> 8;
+ ASSERT(r <= 255);
+ ASSERT(g <= 255);
+ ASSERT(b <= 255);
+ ASSERT(a <= 255);
+ rgba[i][RCOMP] = r;
+ rgba[i][GCOMP] = g;
+ rgba[i][BCOMP] = b;
+ rgba[i][ACOMP] = a;
+ }
+ }
+ }
+}
+
+
+
+/*
+ * Add src and dest.
+ */
+static void blend_add( GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLubyte rgba[][4], CONST GLubyte dest[][4] )
+{
+ GLuint i;
+ ASSERT(ctx->Color.BlendEquation==GL_FUNC_ADD_EXT);
+ ASSERT(ctx->Color.BlendSrcRGB==GL_ONE);
+ ASSERT(ctx->Color.BlendDstRGB==GL_ONE);
+ (void) ctx;
+
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLint r = rgba[i][RCOMP] + dest[i][RCOMP];
+ GLint g = rgba[i][GCOMP] + dest[i][GCOMP];
+ GLint b = rgba[i][BCOMP] + dest[i][BCOMP];
+ GLint a = rgba[i][ACOMP] + dest[i][ACOMP];
+ rgba[i][RCOMP] = MIN2( r, 255 );
+ rgba[i][GCOMP] = MIN2( g, 255 );
+ rgba[i][BCOMP] = MIN2( b, 255 );
+ rgba[i][ACOMP] = MIN2( a, 255 );
+ }
+ }
+}
+
+
+
+/*
+ * Blend min function (for GL_EXT_blend_minmax)
+ */
+static void blend_min( GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLubyte rgba[][4], CONST GLubyte dest[][4] )
+{
+ GLuint i;
+ ASSERT(ctx->Color.BlendEquation==GL_MIN_EXT);
+ (void) ctx;
+
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ rgba[i][RCOMP] = MIN2( rgba[i][RCOMP], dest[i][RCOMP] );
+ rgba[i][GCOMP] = MIN2( rgba[i][GCOMP], dest[i][GCOMP] );
+ rgba[i][BCOMP] = MIN2( rgba[i][BCOMP], dest[i][BCOMP] );
+ rgba[i][ACOMP] = MIN2( rgba[i][ACOMP], dest[i][ACOMP] );
+ }
+ }
+}
+
+
+
+/*
+ * Blend max function (for GL_EXT_blend_minmax)
+ */
+static void blend_max( GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLubyte rgba[][4], CONST GLubyte dest[][4] )
+{
+ GLuint i;
+ ASSERT(ctx->Color.BlendEquation==GL_MAX_EXT);
+ (void) ctx;
+
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ rgba[i][RCOMP] = MAX2( rgba[i][RCOMP], dest[i][RCOMP] );
+ rgba[i][GCOMP] = MAX2( rgba[i][GCOMP], dest[i][GCOMP] );
+ rgba[i][BCOMP] = MAX2( rgba[i][BCOMP], dest[i][BCOMP] );
+ rgba[i][ACOMP] = MAX2( rgba[i][ACOMP], dest[i][ACOMP] );
+ }
+ }
+}
+
+
+
+/*
+ * Modulate: result = src * dest
+ */
+static void blend_modulate( GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLubyte rgba[][4], CONST GLubyte dest[][4] )
+{
+ GLuint i;
+ (void) ctx;
+
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLint r = (rgba[i][RCOMP] * dest[i][RCOMP]) >> 8;
+ GLint g = (rgba[i][GCOMP] * dest[i][GCOMP]) >> 8;
+ GLint b = (rgba[i][BCOMP] * dest[i][BCOMP]) >> 8;
+ GLint a = (rgba[i][ACOMP] * dest[i][ACOMP]) >> 8;
+ rgba[i][RCOMP] = r;
+ rgba[i][GCOMP] = g;
+ rgba[i][BCOMP] = b;
+ rgba[i][ACOMP] = a;
+ }
+ }
+}
+
+
+
+/*
+ * General case blend pixels.
+ * Input: n - number of pixels
+ * mask - the usual write mask
+ * In/Out: rgba - the incoming and modified pixels
+ * Input: dest - the pixels from the dest color buffer
+ */
+static void blend_general( GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLubyte rgba[][4], CONST GLubyte dest[][4] )
+{
+ GLfloat rscale = 1.0F / 255.0F;
+ GLfloat gscale = 1.0F / 255.0F;
+ GLfloat bscale = 1.0F / 255.0F;
+ GLfloat ascale = 1.0F / 255.0F;
+ GLuint i;
+
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLint Rs, Gs, Bs, As; /* Source colors */
+ GLint Rd, Gd, Bd, Ad; /* Dest colors */
+ GLfloat sR, sG, sB, sA; /* Source scaling */
+ GLfloat dR, dG, dB, dA; /* Dest scaling */
+ GLfloat r, g, b, a;
+
+ /* Source Color */
+ Rs = rgba[i][RCOMP];
+ Gs = rgba[i][GCOMP];
+ Bs = rgba[i][BCOMP];
+ As = rgba[i][ACOMP];
+
+ /* Frame buffer color */
+ Rd = dest[i][RCOMP];
+ Gd = dest[i][GCOMP];
+ Bd = dest[i][BCOMP];
+ Ad = dest[i][ACOMP];
+
+ /* Source RGB factor */
+ switch (ctx->Color.BlendSrcRGB) {
+ case GL_ZERO:
+ sR = sG = sB = 0.0F;
+ break;
+ case GL_ONE:
+ sR = sG = sB = 1.0F;
+ break;
+ case GL_DST_COLOR:
+ sR = (GLfloat) Rd * rscale;
+ sG = (GLfloat) Gd * gscale;
+ sB = (GLfloat) Bd * bscale;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ sR = 1.0F - (GLfloat) Rd * rscale;
+ sG = 1.0F - (GLfloat) Gd * gscale;
+ sB = 1.0F - (GLfloat) Bd * bscale;
+ break;
+ case GL_SRC_ALPHA:
+ sR = sG = sB = (GLfloat) As * ascale;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ sR = sG = sB = (GLfloat) 1.0F - (GLfloat) As * ascale;
+ break;
+ case GL_DST_ALPHA:
+ sR = sG = sB = (GLfloat) Ad * ascale;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ sR = sG = sB = 1.0F - (GLfloat) Ad * ascale;
+ break;
+ case GL_SRC_ALPHA_SATURATE:
+ if (As < 1.0F - (GLfloat) Ad * ascale) {
+ sR = sG = sB = (GLfloat) As * ascale;
+ }
+ else {
+ sR = sG = sB = 1.0F - (GLfloat) Ad * ascale;
+ }
+ break;
+ case GL_CONSTANT_COLOR:
+ sR = ctx->Color.BlendColor[0];
+ sG = ctx->Color.BlendColor[1];
+ sB = ctx->Color.BlendColor[2];
+ break;
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ sR = 1.0F - ctx->Color.BlendColor[0];
+ sG = 1.0F - ctx->Color.BlendColor[1];
+ sB = 1.0F - ctx->Color.BlendColor[2];
+ break;
+ case GL_CONSTANT_ALPHA:
+ sR = sG = sB = ctx->Color.BlendColor[3];
+ break;
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ sR = sG = sB = 1.0F - ctx->Color.BlendColor[3];
+ break;
+ default:
+ /* this should never happen */
+ gl_problem(ctx, "Bad blend source RGB factor in do_blend");
+ return;
+ }
+
+ /* Source Alpha factor */
+ switch (ctx->Color.BlendSrcA) {
+ case GL_ZERO:
+ sA = 0.0F;
+ break;
+ case GL_ONE:
+ sA = 1.0F;
+ break;
+ case GL_DST_COLOR:
+ sA = (GLfloat) Ad * ascale;
+ break;
+ case GL_ONE_MINUS_DST_COLOR:
+ sA = 1.0F - (GLfloat) Ad * ascale;
+ break;
+ case GL_SRC_ALPHA:
+ sA = (GLfloat) As * ascale;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ sA = (GLfloat) 1.0F - (GLfloat) As * ascale;
+ break;
+ case GL_DST_ALPHA:
+ sA =(GLfloat) Ad * ascale;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ sA = 1.0F - (GLfloat) Ad * ascale;
+ break;
+ case GL_SRC_ALPHA_SATURATE:
+ sA = 1.0;
+ break;
+ case GL_CONSTANT_COLOR:
+ sA = ctx->Color.BlendColor[3];
+ break;
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ sA = 1.0F - ctx->Color.BlendColor[3];
+ break;
+ case GL_CONSTANT_ALPHA:
+ sA = ctx->Color.BlendColor[3];
+ break;
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ sA = 1.0F - ctx->Color.BlendColor[3];
+ break;
+ default:
+ /* this should never happen */
+ gl_problem(ctx, "Bad blend source A factor in do_blend");
+ }
+
+ /* Dest RGB factor */
+ switch (ctx->Color.BlendDstRGB) {
+ case GL_ZERO:
+ dR = dG = dB = 0.0F;
+ break;
+ case GL_ONE:
+ dR = dG = dB = 1.0F;
+ break;
+ case GL_SRC_COLOR:
+ dR = (GLfloat) Rs * rscale;
+ dG = (GLfloat) Gs * gscale;
+ dB = (GLfloat) Bs * bscale;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ dR = 1.0F - (GLfloat) Rs * rscale;
+ dG = 1.0F - (GLfloat) Gs * gscale;
+ dB = 1.0F - (GLfloat) Bs * bscale;
+ break;
+ case GL_SRC_ALPHA:
+ dR = dG = dB = (GLfloat) As * ascale;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ dR = dG = dB = (GLfloat) 1.0F - (GLfloat) As * ascale;
+ break;
+ case GL_DST_ALPHA:
+ dR = dG = dB = (GLfloat) Ad * ascale;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ dR = dG = dB = 1.0F - (GLfloat) Ad * ascale;
+ break;
+ case GL_CONSTANT_COLOR:
+ dR = ctx->Color.BlendColor[0];
+ dG = ctx->Color.BlendColor[1];
+ dB = ctx->Color.BlendColor[2];
+ break;
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ dR = 1.0F - ctx->Color.BlendColor[0];
+ dG = 1.0F - ctx->Color.BlendColor[1];
+ dB = 1.0F - ctx->Color.BlendColor[2];
+ break;
+ case GL_CONSTANT_ALPHA:
+ dR = dG = dB = ctx->Color.BlendColor[3];
+ break;
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ dR = dG = dB = 1.0F - ctx->Color.BlendColor[3] * ascale;
+ break;
+ default:
+ /* this should never happen */
+ gl_problem(ctx, "Bad blend dest RGB factor in do_blend");
+ }
+
+ /* Dest Alpha factor */
+ switch (ctx->Color.BlendDstA) {
+ case GL_ZERO:
+ dA = 0.0F;
+ break;
+ case GL_ONE:
+ dA = 1.0F;
+ break;
+ case GL_SRC_COLOR:
+ dA = (GLfloat) As * ascale;
+ break;
+ case GL_ONE_MINUS_SRC_COLOR:
+ dA = 1.0F - (GLfloat) As * ascale;
+ break;
+ case GL_SRC_ALPHA:
+ dA = (GLfloat) As * ascale;
+ break;
+ case GL_ONE_MINUS_SRC_ALPHA:
+ dA = (GLfloat) 1.0F - (GLfloat) As * ascale;
+ break;
+ case GL_DST_ALPHA:
+ dA = (GLfloat) Ad * ascale;
+ break;
+ case GL_ONE_MINUS_DST_ALPHA:
+ dA = 1.0F - (GLfloat) Ad * ascale;
+ break;
+ case GL_CONSTANT_COLOR:
+ dA = ctx->Color.BlendColor[3];
+ break;
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ dA = 1.0F - ctx->Color.BlendColor[3];
+ break;
+ case GL_CONSTANT_ALPHA:
+ dA = ctx->Color.BlendColor[3];
+ break;
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ dA = 1.0F - ctx->Color.BlendColor[3] * ascale;
+ break;
+ default:
+ /* this should never happen */
+ gl_problem(ctx, "Bad blend dest A factor in do_blend");
+ return;
+ }
+
+ /* Due to round-off problems we have to clamp against zero. */
+ /* Optimization: we don't have to do this for all src & dst factors */
+ if (dA < 0.0F) dA = 0.0F;
+ if (dR < 0.0F) dR = 0.0F;
+ if (dG < 0.0F) dG = 0.0F;
+ if (dB < 0.0F) dB = 0.0F;
+ if (sA < 0.0F) sA = 0.0F;
+ if (sR < 0.0F) sR = 0.0F;
+ if (sG < 0.0F) sG = 0.0F;
+ if (sB < 0.0F) sB = 0.0F;
+
+ ASSERT( sR <= 1.0 );
+ ASSERT( sG <= 1.0 );
+ ASSERT( sB <= 1.0 );
+ ASSERT( sA <= 1.0 );
+ ASSERT( dR <= 1.0 );
+ ASSERT( dG <= 1.0 );
+ ASSERT( dB <= 1.0 );
+ ASSERT( dA <= 1.0 );
+
+ /* compute blended color */
+ if (ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
+ r = Rs * sR + Rd * dR;
+ g = Gs * sG + Gd * dG;
+ b = Bs * sB + Bd * dB;
+ a = As * sA + Ad * dA;
+ }
+ else if (ctx->Color.BlendEquation==GL_FUNC_SUBTRACT_EXT) {
+ r = Rs * sR - Rd * dR;
+ g = Gs * sG - Gd * dG;
+ b = Bs * sB - Bd * dB;
+ a = As * sA - Ad * dA;
+ }
+ else if (ctx->Color.BlendEquation==GL_FUNC_REVERSE_SUBTRACT_EXT) {
+ r = Rd * dR - Rs * sR;
+ g = Gd * dG - Gs * sG;
+ b = Bd * dB - Bs * sB;
+ a = Ad * dA - As * sA;
+ }
+
+ /* final clamping */
+ rgba[i][RCOMP] = (GLint) CLAMP( r, 0.0F, 255.0F );
+ rgba[i][GCOMP] = (GLint) CLAMP( g, 0.0F, 255.0F );
+ rgba[i][BCOMP] = (GLint) CLAMP( b, 0.0F, 255.0F );
+ rgba[i][ACOMP] = (GLint) CLAMP( a, 0.0F, 255.0F );
+ }
+ }
+}
+
+
+
+#if defined(USE_MMX_ASM)
+#include "X86/mmx.h"
+#include "X86/common_x86asm.h"
+#endif
+
+
+/*
+ * Analyze current blending parameters to pick fastest blending function.
+ * Result: the ctx->Color.BlendFunc pointer is updated.
+ */
+static void set_blend_function( GLcontext *ctx )
+{
+ const GLenum eq = ctx->Color.BlendEquation;
+ const GLenum srcRGB = ctx->Color.BlendSrcRGB;
+ const GLenum dstRGB = ctx->Color.BlendDstRGB;
+ const GLenum srcA = ctx->Color.BlendSrcA;
+ const GLenum dstA = ctx->Color.BlendDstA;
+
+#if defined(USE_MMX_ASM)
+ /* Hmm. A table here would have 12^4 == way too many entries.
+ * Provide a hook for MMX instead.
+ */
+ if (gl_x86_cpu_features & GL_CPU_MMX) {
+ gl_mmx_set_blend_function (ctx);
+ } else
+#endif
+ if (srcRGB != srcA || dstRGB != dstA) {
+ ctx->Color.BlendFunc = blend_general;
+ }
+ else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_SRC_ALPHA
+ && dstRGB==GL_ONE_MINUS_SRC_ALPHA) {
+ ctx->Color.BlendFunc = blend_transparency;
+ }
+ else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_ONE && dstRGB==GL_ONE) {
+ ctx->Color.BlendFunc = blend_add;
+ }
+ else if (((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_REVERSE_SUBTRACT_EXT)
+ && (srcRGB==GL_ZERO && dstRGB==GL_SRC_COLOR))
+ ||
+ ((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_SUBTRACT_EXT)
+ && (srcRGB==GL_DST_COLOR && dstRGB==GL_ZERO))) {
+ ctx->Color.BlendFunc = blend_modulate;
+ }
+ else if (eq==GL_MIN_EXT) {
+ ctx->Color.BlendFunc = blend_min;
+ }
+ else if (eq==GL_MAX_EXT) {
+ ctx->Color.BlendFunc = blend_max;
+ }
+ else {
+ ctx->Color.BlendFunc = blend_general;
+ }
+}
+
+
+
+/*
+ * Apply the blending operator to a span of pixels.
+ * Input: n - number of pixels in span
+ * x, y - location of leftmost pixel in span in window coords.
+ * mask - boolean mask indicating which pixels to blend.
+ * In/Out: rgba - pixel values
+ */
+void gl_blend_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4], const GLubyte mask[] )
+{
+ GLubyte dest[MAX_WIDTH][4];
+
+ /* Check if device driver can do the work */
+ if (ctx->Color.BlendEquation==GL_LOGIC_OP && !ctx->Color.SWLogicOpEnabled) {
+ return;
+ }
+
+ /* Read span of current frame buffer pixels */
+ gl_read_rgba_span( ctx, n, x, y, dest );
+
+ if (!ctx->Color.BlendFunc)
+ set_blend_function(ctx);
+
+ (*ctx->Color.BlendFunc)( ctx, n, mask, rgba, (const GLubyte (*)[4])dest );
+}
+
+
+
+
+
+/*
+ * Apply the blending operator to an array of pixels.
+ * Input: n - number of pixels in span
+ * x, y - array of pixel locations
+ * mask - boolean mask indicating which pixels to blend.
+ * In/Out: rgba - pixel values
+ */
+void gl_blend_pixels( GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[] )
+{
+ GLubyte dest[PB_SIZE][4];
+
+ /* Check if device driver can do the work */
+ if (ctx->Color.BlendEquation==GL_LOGIC_OP && !ctx->Color.SWLogicOpEnabled) {
+ return;
+ }
+
+ /* Read pixels from current color buffer */
+ (*ctx->Driver.ReadRGBAPixels)( ctx, n, x, y, dest, mask );
+
+ if (ctx->RasterMask & ALPHABUF_BIT) {
+ gl_read_alpha_pixels( ctx, n, x, y, dest, mask );
+ }
+ else {
+ GLuint i;
+ for (i=0; i<n; i++) {
+ dest[i][ACOMP] = 255;
+ }
+ }
+
+ if (!ctx->Color.BlendFunc)
+ set_blend_function(ctx);
+
+ (*ctx->Color.BlendFunc)( ctx, n, mask, rgba, (const GLubyte (*)[4])dest );
+}
diff --git a/src/mesa/main/blend.h b/src/mesa/main/blend.h
new file mode 100644
index 0000000000..837ea9d6bf
--- /dev/null
+++ b/src/mesa/main/blend.h
@@ -0,0 +1,68 @@
+/* $Id: blend.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef BLEND_H
+#define BLEND_H
+
+
+#include "types.h"
+
+
+
+extern void
+gl_blend_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4], const GLubyte mask[] );
+
+
+extern void
+gl_blend_pixels( GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[] );
+
+
+extern void
+gl_BlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor );
+
+
+extern void
+gl_BlendFuncSeparate( GLcontext *ctx, GLenum sfactorRGB, GLenum dfactorRGB,
+ GLenum sfactorA, GLenum dfactorA );
+
+
+extern void
+gl_BlendEquation( GLcontext *ctx, GLenum mode );
+
+
+extern void
+gl_BlendColor( GLcontext *ctx, GLclampf red, GLclampf green,
+ GLclampf blue, GLclampf alpha );
+
+
+#endif
diff --git a/src/mesa/main/clip.c b/src/mesa/main/clip.c
new file mode 100644
index 0000000000..9feaf2472e
--- /dev/null
+++ b/src/mesa/main/clip.c
@@ -0,0 +1,460 @@
+/* $Id: clip.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <string.h>
+#include <stdlib.h>
+#include "clip.h"
+#include "context.h"
+#include "macros.h"
+#include "matrix.h"
+#include "mmath.h"
+#include "types.h"
+#include "vb.h"
+#include "xform.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+
+
+/* Linear interpolation between A and B: */
+#define LINTERP( T, A, B ) ( (A) + (T) * ( (B) - (A) ) )
+
+
+
+#define INTERP_SZ( t, vec, to, a, b, sz ) \
+do { \
+ switch (sz) { \
+ case 4: vec[to][3] = LINTERP( t, vec[a][3], vec[b][3] ); \
+ case 3: vec[to][2] = LINTERP( t, vec[a][2], vec[b][2] ); \
+ case 2: vec[to][1] = LINTERP( t, vec[a][1], vec[b][1] ); \
+ case 1: vec[to][0] = LINTERP( t, vec[a][0], vec[b][0] ); \
+ } \
+} while(0)
+
+
+
+
+#define CLIP_RGBA0 0x1
+#define CLIP_RGBA1 0x2
+#define CLIP_TEX0 0x4
+#define CLIP_TEX1 0x8
+#define CLIP_INDEX0 0x10
+#define CLIP_INDEX1 0x20
+#define CLIP_EDGE 0x40
+
+/* This is sparsely populated: */
+static clip_interp_func clip_interp_tab[0x80];
+
+#define IND 0
+#define NAME clip_nil
+#include "interp_tmp.h"
+
+#define IND (CLIP_RGBA0)
+#define NAME clipRGBA0
+#include "interp_tmp.h"
+
+#define IND (CLIP_RGBA0|CLIP_RGBA1)
+#define NAME clipRGBA0_RGBA1
+#include "interp_tmp.h"
+
+#define IND (CLIP_TEX0|CLIP_RGBA0)
+#define NAME clipTEX0_RGBA0
+#include "interp_tmp.h"
+
+#define IND (CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1)
+#define NAME clipTEX0_RGBA0_RGBA1
+#include "interp_tmp.h"
+
+#define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0)
+#define NAME clipTEX1_TEX0_RGBA0
+#include "interp_tmp.h"
+
+#define IND (CLIP_TEX0)
+#define NAME clipTEX0
+#include "interp_tmp.h"
+
+#define IND (CLIP_TEX1|CLIP_TEX0)
+#define NAME clipTEX1_TEX0
+#include "interp_tmp.h"
+
+#define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1)
+#define NAME clipTEX1_TEX0_RGBA0_RGBA1
+#include "interp_tmp.h"
+
+#define IND (CLIP_INDEX0)
+#define NAME clipINDEX0
+#include "interp_tmp.h"
+
+#define IND (CLIP_INDEX0|CLIP_INDEX1)
+#define NAME clipINDEX0_INDEX1
+#include "interp_tmp.h"
+
+#define IND (CLIP_RGBA0|CLIP_EDGE)
+#define NAME clipRGBA0_EDGE
+#include "interp_tmp.h"
+
+#define IND (CLIP_RGBA0|CLIP_RGBA1|CLIP_EDGE)
+#define NAME clipRGBA0_RGBA1_EDGE
+#include "interp_tmp.h"
+
+#define IND (CLIP_TEX0|CLIP_RGBA0|CLIP_EDGE)
+#define NAME clipTEX0_RGBA0_EDGE
+#include "interp_tmp.h"
+
+#define IND (CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1|CLIP_EDGE)
+#define NAME clipTEX0_RGBA0_RGBA1_EDGE
+#include "interp_tmp.h"
+
+#define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_EDGE)
+#define NAME clipTEX1_TEX0_RGBA0_EDGE
+#include "interp_tmp.h"
+
+#define IND (CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1|CLIP_EDGE)
+#define NAME clipTEX1_TEX0_RGBA0_RGBA1_EDGE
+#include "interp_tmp.h"
+
+#define IND (CLIP_INDEX0|CLIP_EDGE)
+#define NAME clipINDEX0_EDGE
+#include "interp_tmp.h"
+
+#define IND (CLIP_INDEX0|CLIP_INDEX1|CLIP_EDGE)
+#define NAME clipINDEX0_INDEX1_EDGE
+#include "interp_tmp.h"
+
+
+
+
+/**********************************************************************/
+/* Get/Set User clip-planes. */
+/**********************************************************************/
+
+
+
+void gl_ClipPlane( GLcontext* ctx, GLenum plane, const GLfloat *equation )
+{
+ GLint p;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glClipPlane");
+
+ p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
+ if (p<0 || p>=MAX_CLIP_PLANES) {
+ gl_error( ctx, GL_INVALID_ENUM, "glClipPlane" );
+ return;
+ }
+
+ /*
+ * The equation is transformed by the transpose of the inverse of the
+ * current modelview matrix and stored in the resulting eye coordinates.
+ *
+ * KW: Eqn is then transformed to the current clip space, where user
+ * clipping now takes place. The clip-space equations are recalculated
+ * whenever the projection matrix changes.
+ */
+ if (ctx->ModelView.flags & MAT_DIRTY_ALL_OVER) {
+ gl_matrix_analyze( &ctx->ModelView );
+ }
+ gl_transform_vector( ctx->Transform.EyeUserPlane[p], equation,
+ ctx->ModelView.inv );
+
+
+ if (ctx->Transform.ClipEnabled[p]) {
+ ctx->NewState |= NEW_USER_CLIP;
+
+ if (ctx->ProjectionMatrix.flags & MAT_DIRTY_ALL_OVER) {
+ gl_matrix_analyze( &ctx->ProjectionMatrix );
+ }
+ gl_transform_vector( ctx->Transform.ClipUserPlane[p],
+ ctx->Transform.EyeUserPlane[p],
+ ctx->ProjectionMatrix.inv );
+ }
+}
+
+
+void gl_update_userclip( GLcontext *ctx )
+{
+ GLuint p;
+
+ for (p = 0 ; p < MAX_CLIP_PLANES ; p++) {
+ if (ctx->Transform.ClipEnabled[p]) {
+ gl_transform_vector( ctx->Transform.ClipUserPlane[p],
+ ctx->Transform.EyeUserPlane[p],
+ ctx->ProjectionMatrix.inv );
+ }
+ }
+}
+
+void gl_GetClipPlane( GLcontext* ctx, GLenum plane, GLdouble *equation )
+{
+ GLint p;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx, "glGetClipPlane");
+
+
+ p = (GLint) (plane - GL_CLIP_PLANE0);
+ if (p<0 || p>=MAX_CLIP_PLANES) {
+ gl_error( ctx, GL_INVALID_ENUM, "glGetClipPlane" );
+ return;
+ }
+
+ equation[0] = (GLdouble) ctx->Transform.EyeUserPlane[p][0];
+ equation[1] = (GLdouble) ctx->Transform.EyeUserPlane[p][1];
+ equation[2] = (GLdouble) ctx->Transform.EyeUserPlane[p][2];
+ equation[3] = (GLdouble) ctx->Transform.EyeUserPlane[p][3];
+}
+
+
+
+
+/**********************************************************************/
+/* View volume clipping. */
+/**********************************************************************/
+
+
+/*
+ * Clip a point against the view volume.
+ * Input: v - vertex-vector describing the point to clip
+ * Return: 0 = outside view volume
+ * 1 = inside view volume
+ */
+GLuint gl_viewclip_point( const GLfloat v[] )
+{
+ if ( v[0] > v[3] || v[0] < -v[3]
+ || v[1] > v[3] || v[1] < -v[3]
+ || v[2] > v[3] || v[2] < -v[3] ) {
+ return 0;
+ }
+ else {
+ return 1;
+ }
+}
+
+/*
+ * Clip a point against the user clipping planes.
+ * Input: v - vertex-vector describing the point to clip.
+ * Return: 0 = point was clipped
+ * 1 = point not clipped
+ */
+GLuint gl_userclip_point( GLcontext* ctx, const GLfloat v[] )
+{
+ GLuint p;
+
+ for (p=0;p<MAX_CLIP_PLANES;p++) {
+ if (ctx->Transform.ClipEnabled[p]) {
+ GLfloat dot = v[0] * ctx->Transform.ClipUserPlane[p][0]
+ + v[1] * ctx->Transform.ClipUserPlane[p][1]
+ + v[2] * ctx->Transform.ClipUserPlane[p][2]
+ + v[3] * ctx->Transform.ClipUserPlane[p][3];
+ if (dot < 0.0F) {
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+
+
+
+clip_poly_func gl_poly_clip_tab[5];
+clip_line_func gl_line_clip_tab[5];
+
+
+#if defined(__i386__)
+#define NEGATIVE(x) ((*(int *)&x)<0)
+#else
+#define NEGATIVE(x) (x < 0)
+#endif
+
+#define W(i) coord[i][3]
+#define Z(i) coord[i][2]
+#define Y(i) coord[i][1]
+#define X(i) coord[i][0]
+#define SIZE 4
+#define TAG(x) x##_4
+#include "clip_funcs.h"
+
+
+#define W(i) 1.0
+#define Z(i) coord[i][2]
+#define Y(i) coord[i][1]
+#define X(i) coord[i][0]
+#define SIZE 3
+#define TAG(x) x##_3
+#include "clip_funcs.h"
+
+#define W(i) 1.0
+#define Z(i) 0.0
+#define Y(i) coord[i][1]
+#define X(i) coord[i][0]
+#define SIZE 2
+#define TAG(x) x##_2
+#include "clip_funcs.h"
+
+#define USER_CLIPTEST(NAME, SZ) \
+static void NAME( struct vertex_buffer *VB ) \
+{ \
+ GLcontext *ctx = VB->ctx; \
+ GLubyte *clipMask = VB->ClipMask; \
+ GLubyte *userClipMask = VB->UserClipMask; \
+ GLuint start = VB->Start; \
+ GLuint count = VB->Count; \
+ GLuint p, i; \
+ GLubyte bit; \
+ \
+ \
+ for (bit = 1, p = 0; p < MAX_CLIP_PLANES ; p++, bit *=2) \
+ if (ctx->Transform.ClipEnabled[p]) { \
+ GLuint nr = 0; \
+ const GLfloat a = ctx->Transform.ClipUserPlane[p][0]; \
+ const GLfloat b = ctx->Transform.ClipUserPlane[p][1]; \
+ const GLfloat c = ctx->Transform.ClipUserPlane[p][2]; \
+ const GLfloat d = ctx->Transform.ClipUserPlane[p][3]; \
+ GLfloat *coord = VB->ClipPtr->start; \
+ GLuint stride = VB->ClipPtr->stride; \
+ \
+ for (i = start ; i < count ; i++, STRIDE_F(coord, stride)) { \
+ GLfloat dp = coord[0] * a + coord[1] * b; \
+ if (SZ > 2) dp += coord[2] * c; \
+ if (SZ > 3) dp += coord[3] * d; else dp += d; \
+ \
+ if (dp < 0) { \
+ clipMask[i] |= CLIP_USER_BIT; \
+ userClipMask[i] |= bit; \
+ nr++; \
+ } \
+ } \
+ \
+ if (nr > 0) { \
+ VB->ClipOrMask |= CLIP_USER_BIT; \
+ VB->CullMode |= CLIP_MASK_ACTIVE; \
+ if (nr == count - start) { \
+ VB->ClipAndMask |= CLIP_USER_BIT; \
+ VB->Culled = 1; \
+ return; \
+ } \
+ } \
+ } \
+}
+
+
+USER_CLIPTEST(userclip2, 2)
+USER_CLIPTEST(userclip3, 3)
+USER_CLIPTEST(userclip4, 4)
+
+static void (*(usercliptab[5]))( struct vertex_buffer * ) = {
+ 0,
+ 0,
+ userclip2,
+ userclip3,
+ userclip4
+};
+
+void gl_user_cliptest( struct vertex_buffer *VB )
+{
+ usercliptab[VB->ClipPtr->size]( VB );
+}
+
+
+
+static clip_interp_func get_interp_func( GLcontext *ctx )
+{
+ GLuint mask = 0;
+
+ if (ctx->Visual->RGBAflag)
+ {
+ if (ctx->Light.ShadeModel==GL_SMOOTH)
+ {
+ mask |= CLIP_RGBA0;
+
+ if (ctx->TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_SEPERATE_SPECULAR))
+ mask |= CLIP_RGBA1;
+ }
+
+ if (ctx->Texture.ReallyEnabled & 0xf0)
+ mask |= CLIP_TEX1|CLIP_TEX0;
+
+ if (ctx->Texture.ReallyEnabled & 0xf)
+ mask |= CLIP_TEX0;
+ }
+ else if (ctx->Light.ShadeModel==GL_SMOOTH)
+ {
+ mask |= CLIP_INDEX0;
+
+ if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE)
+ mask |= CLIP_INDEX1;
+ }
+
+
+ return clip_interp_tab[mask];
+}
+
+
+void gl_update_clipmask( GLcontext *ctx )
+{
+ ctx->ClipInterpFunc = get_interp_func( ctx );
+}
+
+void gl_init_clip(void)
+{
+ init_clip_funcs_4();
+ init_clip_funcs_3();
+ init_clip_funcs_2();
+
+ clip_interp_tab[0] = clip_nil;
+ clip_interp_tab[CLIP_RGBA0] = clipRGBA0;
+ clip_interp_tab[CLIP_RGBA0|CLIP_RGBA1] = clipRGBA0_RGBA1;
+ clip_interp_tab[CLIP_TEX0|CLIP_RGBA0] = clipTEX0_RGBA0;
+ clip_interp_tab[CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1] = clipTEX0_RGBA0_RGBA1;
+ clip_interp_tab[CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0] = clipTEX1_TEX0_RGBA0;
+ clip_interp_tab[CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1] = clipTEX1_TEX0_RGBA0_RGBA1;
+
+ clip_interp_tab[CLIP_TEX0] = clipTEX0;
+ clip_interp_tab[CLIP_TEX1|CLIP_TEX0] = clipTEX1_TEX0;
+
+ clip_interp_tab[CLIP_INDEX0] = clipINDEX0;
+ clip_interp_tab[CLIP_INDEX0|CLIP_INDEX1] = clipINDEX0_INDEX1;
+
+ clip_interp_tab[CLIP_RGBA0|CLIP_EDGE] = clipRGBA0_EDGE;
+ clip_interp_tab[CLIP_RGBA0|CLIP_RGBA1|CLIP_EDGE] = clipRGBA0_RGBA1_EDGE;
+ clip_interp_tab[CLIP_TEX0|CLIP_RGBA0|CLIP_EDGE] = clipTEX0_RGBA0_EDGE;
+ clip_interp_tab[CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1|CLIP_EDGE] = clipTEX0_RGBA0_RGBA1_EDGE;
+ clip_interp_tab[CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_EDGE] = clipTEX1_TEX0_RGBA0_EDGE;
+ clip_interp_tab[CLIP_TEX1|CLIP_TEX0|CLIP_RGBA0|CLIP_RGBA1|CLIP_EDGE] = clipTEX1_TEX0_RGBA0_RGBA1_EDGE;
+ clip_interp_tab[CLIP_INDEX0|CLIP_EDGE] = clipINDEX0_EDGE;
+ clip_interp_tab[CLIP_INDEX0|CLIP_INDEX1|CLIP_EDGE] = clipINDEX0_INDEX1_EDGE;
+}
+
diff --git a/src/mesa/main/clip.h b/src/mesa/main/clip.h
new file mode 100644
index 0000000000..03e09ca7e5
--- /dev/null
+++ b/src/mesa/main/clip.h
@@ -0,0 +1,105 @@
+/* $Id: clip.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef CLIP_H
+#define CLIP_H
+
+
+#include "types.h"
+
+
+
+#ifdef DEBUG
+# define GL_VIEWCLIP_POINT( V ) gl_viewclip_point( V )
+#else
+# define GL_VIEWCLIP_POINT( V ) \
+ ( (V)[0] <= (V)[3] && (V)[0] >= -(V)[3] \
+ && (V)[1] <= (V)[3] && (V)[1] >= -(V)[3] \
+ && (V)[2] <= (V)[3] && (V)[2] >= -(V)[3] )
+#endif
+
+
+
+typedef GLuint (*clip_line_func)( struct vertex_buffer *VB,
+ GLuint *i, GLuint *j,
+ GLubyte mask);
+typedef GLuint (*clip_poly_func)( struct vertex_buffer *VB,
+ GLuint n, GLuint vlist[],
+ GLubyte mask );
+
+
+extern clip_poly_func gl_poly_clip_tab[5];
+extern clip_line_func gl_line_clip_tab[5];
+
+extern void gl_init_clip(void);
+
+
+extern GLuint gl_viewclip_point( const GLfloat v[] );
+
+
+
+extern GLuint gl_userclip_point( GLcontext* ctx, const GLfloat v[] );
+
+
+extern void gl_user_cliptest( struct vertex_buffer *VB );
+
+
+extern void gl_ClipPlane( GLcontext* ctx,
+ GLenum plane, const GLfloat *equation );
+
+extern void gl_GetClipPlane( GLcontext* ctx,
+ GLenum plane, GLdouble *equation );
+
+
+/*
+ * Clipping interpolation functions
+ */
+
+extern void gl_clip_interp_all( struct vertex_buffer *VB,
+ GLuint dst, GLfloat t, GLuint in, GLuint out );
+
+extern void gl_clip_interp_color_tex( struct vertex_buffer *VB,
+ GLuint dst, GLfloat t, GLuint in, GLuint out );
+
+extern void gl_clip_interp_tex( struct vertex_buffer *VB,
+ GLuint dst, GLfloat t, GLuint in, GLuint out );
+
+extern void gl_clip_interp_color( struct vertex_buffer *VB,
+ GLuint dst, GLfloat t, GLuint in, GLuint out );
+
+extern void gl_clip_interp_none( struct vertex_buffer *VB,
+ GLuint dst, GLfloat t, GLuint in, GLuint out );
+
+
+extern void gl_update_userclip( GLcontext *ctx );
+
+extern void gl_update_clipmask( GLcontext *ctx );
+
+#endif
diff --git a/src/mesa/main/colortab.c b/src/mesa/main/colortab.c
new file mode 100644
index 0000000000..22d785ba51
--- /dev/null
+++ b/src/mesa/main/colortab.c
@@ -0,0 +1,312 @@
+/* $Id: colortab.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include "colortab.h"
+#include "context.h"
+#include "macros.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+
+/*
+ * Return GL_TRUE if k is a power of two, else return GL_FALSE.
+ */
+static GLboolean power_of_two( GLint k )
+{
+ GLint i, m = 1;
+ for (i=0; i<32; i++) {
+ if (k == m)
+ return GL_TRUE;
+ m = m << 1;
+ }
+ return GL_FALSE;
+}
+
+
+static GLint decode_internal_format( GLint format )
+{
+ switch (format) {
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return GL_ALPHA;
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return GL_LUMINANCE;
+ 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:
+ return GL_LUMINANCE_ALPHA;
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ return GL_INTENSITY;
+ case 3:
+ case GL_RGB:
+ case GL_R3_G3_B2:
+ case GL_RGB4:
+ case GL_RGB5:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return GL_RGB;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA2:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return GL_RGBA;
+ default:
+ return -1; /* error */
+ }
+}
+
+
+void gl_ColorTable( GLcontext *ctx, GLenum target,
+ GLenum internalFormat, struct gl_image *table )
+{
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ struct gl_texture_object *texObj;
+ GLboolean proxy = GL_FALSE;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glColorTable");
+
+ if (decode_internal_format(internalFormat) < 0) {
+ gl_error( ctx, GL_INVALID_ENUM, "glColorTable(internalFormat)" );
+ return;
+ }
+
+ switch (target) {
+ case GL_TEXTURE_1D:
+ texObj = texUnit->CurrentD[1];
+ break;
+ case GL_TEXTURE_2D:
+ texObj = texUnit->CurrentD[2];
+ break;
+ case GL_TEXTURE_3D_EXT:
+ texObj = texUnit->CurrentD[3];
+ break;
+ case GL_PROXY_TEXTURE_1D:
+ texObj = ctx->Texture.Proxy1D;
+ proxy = GL_TRUE;
+ break;
+ case GL_PROXY_TEXTURE_2D:
+ texObj = ctx->Texture.Proxy2D;
+ proxy = GL_TRUE;
+ break;
+ case GL_PROXY_TEXTURE_3D_EXT:
+ texObj = ctx->Texture.Proxy3D;
+ proxy = GL_TRUE;
+ break;
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ texObj = NULL;
+ break;
+ default:
+ gl_error(ctx, GL_INVALID_ENUM, "glColorTableEXT(target)");
+ return;
+ }
+
+ /* internalformat = just like glTexImage */
+
+ if (table->Width < 1 || table->Width > MAX_TEXTURE_PALETTE_SIZE
+ || !power_of_two(table->Width)) {
+ gl_error(ctx, GL_INVALID_VALUE, "glColorTableEXT(width)");
+ if (proxy) {
+ texObj->PaletteSize = 0;
+ texObj->PaletteIntFormat = (GLenum) 0;
+ texObj->PaletteFormat = (GLenum) 0;
+ }
+ return;
+ }
+
+ if (texObj) {
+ /* per-texture object palette */
+ texObj->PaletteSize = table->Width;
+ texObj->PaletteIntFormat = internalFormat;
+ texObj->PaletteFormat = (GLenum) decode_internal_format(internalFormat);
+ if (!proxy) {
+ MEMCPY(texObj->Palette, table->Data, table->Width*table->Components);
+ if (ctx->Driver.UpdateTexturePalette) {
+ (*ctx->Driver.UpdateTexturePalette)( ctx, texObj );
+ }
+ }
+ }
+ else {
+ /* shared texture palette */
+ ctx->Texture.PaletteSize = table->Width;
+ ctx->Texture.PaletteIntFormat = internalFormat;
+ ctx->Texture.PaletteFormat = (GLenum) decode_internal_format(internalFormat);
+ MEMCPY(ctx->Texture.Palette, table->Data, table->Width*table->Components);
+ if (ctx->Driver.UpdateTexturePalette) {
+ (*ctx->Driver.UpdateTexturePalette)( ctx, NULL );
+ }
+ }
+}
+
+
+
+void gl_ColorSubTable( GLcontext *ctx, GLenum target,
+ GLsizei start, struct gl_image *data )
+{
+ /* XXX TODO */
+ gl_problem(ctx, "glColorSubTableEXT not implemented");
+ (void) target;
+ (void) start;
+ (void) data;
+}
+
+
+
+void gl_GetColorTable( GLcontext *ctx, GLenum target, GLenum format,
+ GLenum type, GLvoid *table )
+{
+ ASSERT_OUTSIDE_BEGIN_END(ctx, "glGetBooleanv");
+
+ switch (target) {
+ case GL_TEXTURE_1D:
+ break;
+ case GL_TEXTURE_2D:
+ break;
+ case GL_TEXTURE_3D_EXT:
+ break;
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ break;
+ default:
+ gl_error(ctx, GL_INVALID_ENUM, "glGetColorTableEXT(target)");
+ return;
+ }
+
+ gl_problem(ctx, "glGetColorTableEXT not implemented!");
+ (void) format;
+ (void) type;
+ (void) table;
+}
+
+
+
+void gl_GetColorTableParameterfv( GLcontext *ctx, GLenum target,
+ GLenum pname, GLfloat *params )
+{
+ GLint iparams[10];
+
+ gl_GetColorTableParameteriv( ctx, target, pname, iparams );
+ *params = (GLfloat) iparams[0];
+}
+
+
+
+void gl_GetColorTableParameteriv( GLcontext *ctx, GLenum target,
+ GLenum pname, GLint *params )
+{
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ struct gl_texture_object *texObj;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx, "glGetColorTableParameter");
+
+ switch (target) {
+ case GL_TEXTURE_1D:
+ texObj = texUnit->CurrentD[1];
+ break;
+ case GL_TEXTURE_2D:
+ texObj = texUnit->CurrentD[2];
+ break;
+ case GL_TEXTURE_3D_EXT:
+ texObj = texUnit->CurrentD[3];
+ break;
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ texObj = NULL;
+ break;
+ default:
+ gl_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameter(target)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_COLOR_TABLE_FORMAT_EXT:
+ if (texObj)
+ *params = texObj->PaletteIntFormat;
+ else
+ *params = ctx->Texture.PaletteIntFormat;
+ break;
+ case GL_COLOR_TABLE_WIDTH_EXT:
+ if (texObj)
+ *params = texObj->PaletteSize;
+ else
+ *params = ctx->Texture.PaletteSize;
+ break;
+ case GL_COLOR_TABLE_RED_SIZE_EXT:
+ *params = 8;
+ break;
+ case GL_COLOR_TABLE_GREEN_SIZE_EXT:
+ *params = 8;
+ break;
+ case GL_COLOR_TABLE_BLUE_SIZE_EXT:
+ *params = 8;
+ break;
+ case GL_COLOR_TABLE_ALPHA_SIZE_EXT:
+ *params = 8;
+ break;
+ case GL_COLOR_TABLE_LUMINANCE_SIZE_EXT:
+ *params = 8;
+ break;
+ case GL_COLOR_TABLE_INTENSITY_SIZE_EXT:
+ *params = 8;
+ break;
+ default:
+ gl_error(ctx, GL_INVALID_ENUM, "glGetColorTableParameter" );
+ return;
+ }
+}
+
+
diff --git a/src/mesa/main/colortab.h b/src/mesa/main/colortab.h
new file mode 100644
index 0000000000..8e75f13dac
--- /dev/null
+++ b/src/mesa/main/colortab.h
@@ -0,0 +1,55 @@
+/* $Id: colortab.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef COLORTAB_H
+#define COLORTAB_H
+
+
+#include "types.h"
+
+
+extern void gl_ColorTable( GLcontext *ctx, GLenum target,
+ GLenum internalformat,
+ struct gl_image *table );
+
+extern void gl_ColorSubTable( GLcontext *ctx, GLenum target,
+ GLsizei start, struct gl_image *data );
+
+extern void gl_GetColorTable( GLcontext *ctx, GLenum target, GLenum format,
+ GLenum type, GLvoid *table );
+
+extern void gl_GetColorTableParameterfv( GLcontext *ctx, GLenum target,
+ GLenum pname, GLfloat *params );
+
+extern void gl_GetColorTableParameteriv( GLcontext *ctx, GLenum target,
+ GLenum pname, GLint *params );
+
+
+#endif
diff --git a/src/mesa/main/config.h b/src/mesa/main/config.h
new file mode 100644
index 0000000000..0b35aba7dc
--- /dev/null
+++ b/src/mesa/main/config.h
@@ -0,0 +1,222 @@
+/* $Id: config.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+
+/*
+ * Tunable configuration parameters.
+ */
+
+
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#ifdef HAVE_CONFIG_H
+#include "conf.h"
+#endif
+
+/*
+ *
+ * OpenGL implementation limits
+ *
+ */
+
+
+/* Maximum modelview matrix stack depth: */
+#define MAX_MODELVIEW_STACK_DEPTH 32
+
+/* Maximum projection matrix stack depth: */
+#define MAX_PROJECTION_STACK_DEPTH 32
+
+/* Maximum texture matrix stack depth: */
+#define MAX_TEXTURE_STACK_DEPTH 10
+
+/* Maximum attribute stack depth: */
+#define MAX_ATTRIB_STACK_DEPTH 16
+
+/* Maximum client attribute stack depth: */
+#define MAX_CLIENT_ATTRIB_STACK_DEPTH 16
+
+/* Maximum recursion depth of display list calls: */
+#define MAX_LIST_NESTING 64
+
+/* Maximum number of lights: */
+#define MAX_LIGHTS 8
+
+/* Maximum user-defined clipping planes: */
+#define MAX_CLIP_PLANES 6
+
+/* Maximum pixel map lookup table size: */
+#define MAX_PIXEL_MAP_TABLE 256
+
+/* Number of auxillary color buffers: */
+#define NUM_AUX_BUFFERS 0
+
+/* Maximum order (degree) of curves: */
+#ifdef AMIGA
+# define MAX_EVAL_ORDER 12
+#else
+# define MAX_EVAL_ORDER 30
+#endif
+
+/* Maximum Name stack depth */
+#define MAX_NAME_STACK_DEPTH 64
+
+/* Min and Max point sizes and granularity */
+#define MIN_POINT_SIZE 1.0
+#define MAX_POINT_SIZE 10.0
+#define POINT_SIZE_GRANULARITY 0.1
+
+/* Min and Max line widths and granularity */
+#define MIN_LINE_WIDTH 1.0
+#define MAX_LINE_WIDTH 10.0
+#define LINE_WIDTH_GRANULARITY 1.0
+
+/* Max texture palette size */
+#define MAX_TEXTURE_PALETTE_SIZE 256
+
+/* Number of texture levels */
+#define MAX_TEXTURE_LEVELS 12
+
+/* Number of texture units - GL_ARB_multitexture */
+#define MAX_TEXTURE_UNITS 2
+
+/* Maximum viewport size: */
+#define MAX_WIDTH 1600
+#define MAX_HEIGHT 1200
+
+/* Maxmimum size for CVA. May be overridden by the drivers. */
+#define MAX_ARRAY_LOCK_SIZE 3000
+
+
+/*
+ *
+ * Mesa-specific parameters
+ *
+ */
+
+
+/*
+ * Bits per accumulation buffer color component: 8 or 16
+ */
+#define ACCUM_BITS 16
+
+
+#ifdef MESAD3D
+ /* Mesa / Direct3D driver only */
+ extern float g_DepthScale, g_MaxDepth;
+# define DEPTH_BITS 32
+# define DEPTH_SCALE g_DepthScale
+# define MAX_DEPTH g_MaxDepth
+#else
+ /*
+ * Bits per depth buffer value: 16 or 32
+ */
+# define DEPTH_BITS 16
+# if DEPTH_BITS==16
+# define MAX_DEPTH 0xffff
+# define DEPTH_SCALE 65535.0F
+# elif DEPTH_BITS==32
+# define MAX_DEPTH 0x3fffffff
+# define DEPTH_SCALE ((GLfloat) MAX_DEPTH)
+# else
+# error "illegal number of depth bits"
+# endif
+#endif
+
+
+/*
+ * Bits per stencil value: 8
+ */
+#define STENCIL_BITS 8
+
+
+/*
+ * Bits per color channel (must be 8 at this time!)
+ */
+#define CHAN_BITS 8
+
+
+
+/*
+ * Color channel component order
+ * (changes will almost certainly cause problems at this time)
+ */
+#define RCOMP 0
+#define GCOMP 1
+#define BCOMP 2
+#define ACOMP 3
+
+
+
+/* Vertex buffer size. KW: no restrictions on the divisibility of
+ * this number, though things may go better for you if you choose a
+ * value of 12n + 3.
+ */
+
+#define VB_START 3
+
+#if defined(FX) && !defined(MITS)
+# define VB_MAX 72 + VB_START /* better performance */
+#else
+# define VB_MAX 480 + VB_START
+#endif
+
+/*
+ * Actual vertex buffer size.
+ *
+ * Arrays must also accomodate new vertices from clipping, and
+ * potential overflow from primitives which don't fit into neatly into
+ * VB_MAX vertices. (This only happens when mixed primitives are
+ * sharing the vb).
+ */
+#define VB_MAX_CLIPPED_VERTS (2 * (6 + MAX_CLIP_PLANES))
+#define VB_SIZE (VB_MAX + VB_MAX_CLIPPED_VERTS)
+
+
+/*
+ *
+ * For X11 driver only:
+ *
+ */
+
+/*
+ * When defined, use 6x6x6 dithering instead of 5x9x5.
+ * 5x9x5 better for general colors, 6x6x6 better for grayscale.
+ */
+/*#define DITHER666*/
+
+
+
+typedef struct gl_context GLcontext;
+
+extern void gl_read_config_file( struct gl_context *ctx );
+
+#endif
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
new file mode 100644
index 0000000000..55c7467821
--- /dev/null
+++ b/src/mesa/main/context.c
@@ -0,0 +1,2388 @@
+/* $Id: context.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+/*
+ * If multi-threading is enabled (-DTHREADS) then each thread has it's
+ * own rendering context. A thread obtains the pointer to its GLcontext
+ * with the gl_get_thread_context() function. Otherwise, the global
+ * pointer, CC, points to the current context used by all threads in
+ * the address space.
+ */
+
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "accum.h"
+#include "alphabuf.h"
+#include "api.h"
+#include "clip.h"
+#include "context.h"
+#include "cva.h"
+#include "depth.h"
+#include "dlist.h"
+#include "eval.h"
+#include "enums.h"
+#include "fog.h"
+#include "hash.h"
+#include "light.h"
+#include "lines.h"
+#include "dlist.h"
+#include "macros.h"
+#include "matrix.h"
+#include "mmath.h"
+#include "pb.h"
+#include "pipeline.h"
+#include "points.h"
+#include "pointers.h"
+#include "quads.h"
+#include "shade.h"
+#include "simple_list.h"
+#include "stencil.h"
+#include "stages.h"
+#include "triangle.h"
+#include "translate.h"
+#include "teximage.h"
+#include "texobj.h"
+#include "texstate.h"
+#include "texture.h"
+#include "types.h"
+#include "varray.h"
+#include "vb.h"
+#include "vbcull.h"
+#include "vbfill.h"
+#include "vbrender.h"
+#include "vbxform.h"
+#include "xform.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+
+/**********************************************************************/
+/***** Context and Thread management *****/
+/**********************************************************************/
+
+
+#ifdef THREADS
+
+#include "mthreads.h" /* Mesa platform independent threads interface */
+
+static MesaTSD mesa_ctx_tsd;
+
+static void mesa_ctx_thread_init() {
+ MesaInitTSD(&mesa_ctx_tsd);
+}
+
+GLcontext *gl_get_thread_context( void ) {
+ return (GLcontext *) MesaGetTSD(&mesa_ctx_tsd);
+}
+
+static void set_thread_context( GLcontext *ctx ) {
+ MesaSetTSD(&mesa_ctx_tsd, ctx, mesa_ctx_thread_init);
+}
+
+
+#else
+
+/* One Current Context pointer for all threads in the address space */
+GLcontext *CC = NULL;
+struct immediate *CURRENT_INPUT = NULL;
+
+#endif /*THREADS*/
+
+
+
+
+/**********************************************************************/
+/***** Profiling functions *****/
+/**********************************************************************/
+
+#ifdef PROFILE
+
+#include <sys/times.h>
+#include <sys/param.h>
+
+
+/*
+ * Return system time in seconds.
+ * NOTE: this implementation may not be very portable!
+ */
+GLdouble gl_time( void )
+{
+ static GLdouble prev_time = 0.0;
+ static GLdouble time;
+ struct tms tm;
+ clock_t clk;
+
+ clk = times(&tm);
+
+#ifdef CLK_TCK
+ time = (double)clk / (double)CLK_TCK;
+#else
+ time = (double)clk / (double)HZ;
+#endif
+
+ if (time>prev_time) {
+ prev_time = time;
+ return time;
+ }
+ else {
+ return prev_time;
+ }
+}
+
+/*
+ * Reset the timing/profiling counters
+ */
+static void init_timings( GLcontext *ctx )
+{
+ ctx->BeginEndCount = 0;
+ ctx->BeginEndTime = 0.0;
+ ctx->VertexCount = 0;
+ ctx->VertexTime = 0.0;
+ ctx->PointCount = 0;
+ ctx->PointTime = 0.0;
+ ctx->LineCount = 0;
+ ctx->LineTime = 0.0;
+ ctx->PolygonCount = 0;
+ ctx->PolygonTime = 0.0;
+ ctx->ClearCount = 0;
+ ctx->ClearTime = 0.0;
+ ctx->SwapCount = 0;
+ ctx->SwapTime = 0.0;
+}
+
+
+/*
+ * Print the accumulated timing/profiling data.
+ */
+static void print_timings( GLcontext *ctx )
+{
+ GLdouble beginendrate;
+ GLdouble vertexrate;
+ GLdouble pointrate;
+ GLdouble linerate;
+ GLdouble polygonrate;
+ GLdouble overhead;
+ GLdouble clearrate;
+ GLdouble swaprate;
+ GLdouble avgvertices;
+
+ if (ctx->BeginEndTime>0.0) {
+ beginendrate = ctx->BeginEndCount / ctx->BeginEndTime;
+ }
+ else {
+ beginendrate = 0.0;
+ }
+ if (ctx->VertexTime>0.0) {
+ vertexrate = ctx->VertexCount / ctx->VertexTime;
+ }
+ else {
+ vertexrate = 0.0;
+ }
+ if (ctx->PointTime>0.0) {
+ pointrate = ctx->PointCount / ctx->PointTime;
+ }
+ else {
+ pointrate = 0.0;
+ }
+ if (ctx->LineTime>0.0) {
+ linerate = ctx->LineCount / ctx->LineTime;
+ }
+ else {
+ linerate = 0.0;
+ }
+ if (ctx->PolygonTime>0.0) {
+ polygonrate = ctx->PolygonCount / ctx->PolygonTime;
+ }
+ else {
+ polygonrate = 0.0;
+ }
+ if (ctx->ClearTime>0.0) {
+ clearrate = ctx->ClearCount / ctx->ClearTime;
+ }
+ else {
+ clearrate = 0.0;
+ }
+ if (ctx->SwapTime>0.0) {
+ swaprate = ctx->SwapCount / ctx->SwapTime;
+ }
+ else {
+ swaprate = 0.0;
+ }
+
+ if (ctx->BeginEndCount>0) {
+ avgvertices = (GLdouble) ctx->VertexCount / (GLdouble) ctx->BeginEndCount;
+ }
+ else {
+ avgvertices = 0.0;
+ }
+
+ overhead = ctx->BeginEndTime - ctx->VertexTime - ctx->PointTime
+ - ctx->LineTime - ctx->PolygonTime;
+
+
+ printf(" Count Time (s) Rate (/s) \n");
+ printf("--------------------------------------------------------\n");
+ printf("glBegin/glEnd %7d %8.3f %10.3f\n",
+ ctx->BeginEndCount, ctx->BeginEndTime, beginendrate);
+ printf(" vertexes transformed %7d %8.3f %10.3f\n",
+ ctx->VertexCount, ctx->VertexTime, vertexrate );
+ printf(" points rasterized %7d %8.3f %10.3f\n",
+ ctx->PointCount, ctx->PointTime, pointrate );
+ printf(" lines rasterized %7d %8.3f %10.3f\n",
+ ctx->LineCount, ctx->LineTime, linerate );
+ printf(" polygons rasterized %7d %8.3f %10.3f\n",
+ ctx->PolygonCount, ctx->PolygonTime, polygonrate );
+ printf(" overhead %8.3f\n", overhead );
+ printf("glClear %7d %8.3f %10.3f\n",
+ ctx->ClearCount, ctx->ClearTime, clearrate );
+ printf("SwapBuffers %7d %8.3f %10.3f\n",
+ ctx->SwapCount, ctx->SwapTime, swaprate );
+ printf("\n");
+
+ printf("Average number of vertices per begin/end: %8.3f\n", avgvertices );
+}
+#endif
+
+
+
+
+
+/**********************************************************************/
+/***** Context allocation, initialization, destroying *****/
+/**********************************************************************/
+
+
+/*
+ * This function just calls all the various one-time-init functions in Mesa.
+ */
+static void one_time_init( void )
+{
+ static GLboolean alreadyCalled = GL_FALSE;
+ if (!alreadyCalled) {
+ gl_init_clip();
+ gl_init_eval();
+ gl_init_fog();
+ gl_init_math();
+ gl_init_lists();
+ gl_init_shade();
+ gl_init_texture();
+ gl_init_transformation();
+ gl_init_translate();
+ gl_init_vbrender();
+ gl_init_vbxform();
+ alreadyCalled = GL_TRUE;
+ }
+#if defined(DEBUG) && defined(__DATE__) && defined(__TIME__)
+ fprintf(stderr, "Mesa DEBUG build %s %s\n", __DATE__, __TIME__);
+#endif
+}
+
+
+/*
+ * Allocate and initialize a shared context state structure.
+ */
+static struct gl_shared_state *alloc_shared_state( void )
+{
+ GLuint i;
+ struct gl_shared_state *ss;
+ GLboolean outOfMemory;
+
+ ss = (struct gl_shared_state*) calloc( 1, sizeof(struct gl_shared_state) );
+ if (!ss)
+ return NULL;
+
+ ss->DisplayList = NewHashTable();
+
+ ss->TexObjects = NewHashTable();
+
+ /* Default Texture objects */
+ outOfMemory = GL_FALSE;
+ for (i=0;i<MAX_TEXTURE_UNITS;i++) {
+ GLuint d;
+ for (d = 1 ; d <= 3 ; d++) {
+ ss->DefaultD[d][i] = gl_alloc_texture_object(ss, 0, d);
+ if (!ss->DefaultD[d][i]) {
+ outOfMemory = GL_TRUE;
+ break;
+ }
+ ss->DefaultD[d][i]->RefCount++; /* don't free if not in use */
+ }
+ }
+
+ if (!ss->DisplayList || !ss->TexObjects || outOfMemory) {
+ /* Ran out of memory at some point. Free everything and return NULL */
+ if (ss->DisplayList)
+ DeleteHashTable(ss->DisplayList);
+ if (ss->TexObjects)
+ DeleteHashTable(ss->TexObjects);
+ for (i=0;i<MAX_TEXTURE_UNITS;i++) {
+ if (ss->DefaultD[1][i])
+ gl_free_texture_object(ss, ss->DefaultD[1][i]);
+ if (ss->DefaultD[2][i])
+ gl_free_texture_object(ss, ss->DefaultD[2][i]);
+ if (ss->DefaultD[3][i])
+ gl_free_texture_object(ss, ss->DefaultD[3][i]);
+ }
+ free(ss);
+ return NULL;
+ }
+ else {
+ return ss;
+ }
+}
+
+
+/*
+ * Deallocate a shared state context and all children structures.
+ */
+static void free_shared_state( GLcontext *ctx, struct gl_shared_state *ss )
+{
+ /* Free display lists */
+ while (1) {
+ GLuint list = HashFirstEntry(ss->DisplayList);
+ if (list) {
+ gl_destroy_list(ctx, list);
+ }
+ else {
+ break;
+ }
+ }
+ DeleteHashTable(ss->DisplayList);
+
+ /* Free texture objects */
+ while (ss->TexObjectList)
+ {
+ if (ctx->Driver.DeleteTexture)
+ (*ctx->Driver.DeleteTexture)( ctx, ss->TexObjectList );
+ /* this function removes from linked list too! */
+ gl_free_texture_object(ss, ss->TexObjectList);
+ }
+ DeleteHashTable(ss->TexObjects);
+
+ free(ss);
+}
+
+
+
+
+
+
+/*
+ * Initialize the nth light. Note that the defaults for light 0 are
+ * different than the other lights.
+ */
+static void init_light( struct gl_light *l, GLuint n )
+{
+ make_empty_list( l );
+
+ ASSIGN_4V( l->Ambient, 0.0, 0.0, 0.0, 1.0 );
+ if (n==0) {
+ ASSIGN_4V( l->Diffuse, 1.0, 1.0, 1.0, 1.0 );
+ ASSIGN_4V( l->Specular, 1.0, 1.0, 1.0, 1.0 );
+ }
+ else {
+ ASSIGN_4V( l->Diffuse, 0.0, 0.0, 0.0, 1.0 );
+ ASSIGN_4V( l->Specular, 0.0, 0.0, 0.0, 1.0 );
+ }
+ ASSIGN_4V( l->EyePosition, 0.0, 0.0, 1.0, 0.0 );
+ ASSIGN_3V( l->EyeDirection, 0.0, 0.0, -1.0 );
+ l->SpotExponent = 0.0;
+ gl_compute_spot_exp_table( l );
+ l->SpotCutoff = 180.0;
+ l->CosCutoff = 0.0; /* KW: -ve values not admitted */
+ l->ConstantAttenuation = 1.0;
+ l->LinearAttenuation = 0.0;
+ l->QuadraticAttenuation = 0.0;
+ l->Enabled = GL_FALSE;
+}
+
+
+
+static void init_lightmodel( struct gl_lightmodel *lm )
+{
+ ASSIGN_4V( lm->Ambient, 0.2, 0.2, 0.2, 1.0 );
+ lm->LocalViewer = GL_FALSE;
+ lm->TwoSide = GL_FALSE;
+ lm->ColorControl = GL_SINGLE_COLOR;
+}
+
+
+static void init_material( struct gl_material *m )
+{
+ ASSIGN_4V( m->Ambient, 0.2, 0.2, 0.2, 1.0 );
+ ASSIGN_4V( m->Diffuse, 0.8, 0.8, 0.8, 1.0 );
+ ASSIGN_4V( m->Specular, 0.0, 0.0, 0.0, 1.0 );
+ ASSIGN_4V( m->Emission, 0.0, 0.0, 0.0, 1.0 );
+ m->Shininess = 0.0;
+ m->AmbientIndex = 0;
+ m->DiffuseIndex = 1;
+ m->SpecularIndex = 1;
+}
+
+
+
+static void init_texture_unit( GLcontext *ctx, GLuint unit )
+{
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+
+ texUnit->EnvMode = GL_MODULATE;
+ ASSIGN_4V( texUnit->EnvColor, 0.0, 0.0, 0.0, 0.0 );
+ texUnit->TexGenEnabled = 0;
+ texUnit->GenModeS = GL_EYE_LINEAR;
+ texUnit->GenModeT = GL_EYE_LINEAR;
+ texUnit->GenModeR = GL_EYE_LINEAR;
+ texUnit->GenModeQ = GL_EYE_LINEAR;
+ /* Yes, these plane coefficients are correct! */
+ ASSIGN_4V( texUnit->ObjectPlaneS, 1.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->ObjectPlaneT, 0.0, 1.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->ObjectPlaneR, 0.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->ObjectPlaneQ, 0.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->EyePlaneS, 1.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->EyePlaneT, 0.0, 1.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->EyePlaneR, 0.0, 0.0, 0.0, 0.0 );
+ ASSIGN_4V( texUnit->EyePlaneQ, 0.0, 0.0, 0.0, 0.0 );
+
+ texUnit->CurrentD[1] = ctx->Shared->DefaultD[1][unit];
+ texUnit->CurrentD[2] = ctx->Shared->DefaultD[2][unit];
+ texUnit->CurrentD[3] = ctx->Shared->DefaultD[3][unit];
+}
+
+
+static void init_fallback_arrays( GLcontext *ctx )
+{
+ struct gl_client_array *cl;
+ GLuint i;
+
+ cl = &ctx->Fallback.Normal;
+ cl->Size = 3;
+ cl->Type = GL_FLOAT;
+ cl->Stride = 0;
+ cl->StrideB = 0;
+ cl->Ptr = (void *) ctx->Current.Normal;
+ cl->Enabled = 1;
+
+ cl = &ctx->Fallback.Color;
+ cl->Size = 4;
+ cl->Type = GL_UNSIGNED_BYTE;
+ cl->Stride = 0;
+ cl->StrideB = 0;
+ cl->Ptr = (void *) ctx->Current.ByteColor;
+ cl->Enabled = 1;
+
+ cl = &ctx->Fallback.Index;
+ cl->Size = 1;
+ cl->Type = GL_UNSIGNED_INT;
+ cl->Stride = 0;
+ cl->StrideB = 0;
+ cl->Ptr = (void *) &ctx->Current.Index;
+ cl->Enabled = 1;
+
+ for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++) {
+ cl = &ctx->Fallback.TexCoord[i];
+ cl->Size = 4;
+ cl->Type = GL_FLOAT;
+ cl->Stride = 0;
+ cl->StrideB = 0;
+ cl->Ptr = (void *) ctx->Current.Texcoord[i];
+ cl->Enabled = 1;
+ }
+
+ cl = &ctx->Fallback.EdgeFlag;
+ cl->Size = 1;
+ cl->Type = GL_UNSIGNED_BYTE;
+ cl->Stride = 0;
+ cl->StrideB = 0;
+ cl->Ptr = (void *) &ctx->Current.EdgeFlag;
+ cl->Enabled = 1;
+}
+
+/* Initialize a 1-D evaluator map */
+static void init_1d_map( struct gl_1d_map *map, int n, const float *initial )
+{
+ map->Order = 1;
+ map->u1 = 0.0;
+ map->u2 = 1.0;
+ map->Points = (GLfloat *) malloc(n * sizeof(GLfloat));
+ if (map->Points) {
+ GLint i;
+ for (i=0;i<n;i++)
+ map->Points[i] = initial[i];
+ }
+ map->Retain = GL_FALSE;
+}
+
+
+/* Initialize a 2-D evaluator map */
+static void init_2d_map( struct gl_2d_map *map, int n, const float *initial )
+{
+ map->Uorder = 1;
+ map->Vorder = 1;
+ map->u1 = 0.0;
+ map->u2 = 1.0;
+ map->v1 = 0.0;
+ map->v2 = 1.0;
+ map->Points = (GLfloat *) malloc(n * sizeof(GLfloat));
+ if (map->Points) {
+ GLint i;
+ for (i=0;i<n;i++)
+ map->Points[i] = initial[i];
+ }
+ map->Retain = GL_FALSE;
+}
+
+
+
+/*
+ * Initialize a gl_context structure to default values.
+ */
+static void initialize_context( GLcontext *ctx )
+{
+ GLuint i, j;
+
+ if (ctx) {
+ /* Constants, may be overriden by device driver */
+ ctx->Const.MaxTextureLevels = MAX_TEXTURE_LEVELS;
+ ctx->Const.MaxTextureSize = 1 << (MAX_TEXTURE_LEVELS - 1);
+ ctx->Const.MaxTextureUnits = MAX_TEXTURE_UNITS;
+ ctx->Const.MaxArrayLockSize = MAX_ARRAY_LOCK_SIZE;
+
+
+ /* Modelview matrix */
+ gl_matrix_ctr( &ctx->ModelView );
+ gl_matrix_alloc_inv( &ctx->ModelView );
+
+ ctx->ModelViewStackDepth = 0;
+ for (i = 0 ; i < MAX_MODELVIEW_STACK_DEPTH ; i++) {
+ gl_matrix_ctr( &ctx->ModelViewStack[i] );
+ gl_matrix_alloc_inv( &ctx->ModelViewStack[i] );
+ }
+
+ /* Projection matrix - need inv for user clipping in clip space*/
+ gl_matrix_ctr( &ctx->ProjectionMatrix );
+ gl_matrix_alloc_inv( &ctx->ProjectionMatrix );
+
+ gl_matrix_ctr( &ctx->ModelProjectMatrix );
+ gl_matrix_ctr( &ctx->ModelProjectWinMatrix );
+ ctx->ModelProjectWinMatrixUptodate = GL_FALSE;
+
+ ctx->ProjectionStackDepth = 0;
+ ctx->NearFarStack[0][0] = 1.0; /* These values seem weird by make */
+ ctx->NearFarStack[0][1] = 0.0; /* sense mathematically. */
+
+ for (i = 0 ; i < MAX_PROJECTION_STACK_DEPTH ; i++) {
+ gl_matrix_ctr( &ctx->ProjectionStack[i] );
+ gl_matrix_alloc_inv( &ctx->ProjectionStack[i] );
+ }
+
+ /* Texture matrix */
+ for (i=0; i<MAX_TEXTURE_UNITS; i++) {
+ gl_matrix_ctr( &ctx->TextureMatrix[i] );
+ ctx->TextureStackDepth[i] = 0;
+ for (j = 0 ; j < MAX_TEXTURE_STACK_DEPTH ; j++) {
+ ctx->TextureStack[i][j].inv = 0;
+ }
+ }
+
+ /* Accumulate buffer group */
+ ASSIGN_4V( ctx->Accum.ClearColor, 0.0, 0.0, 0.0, 0.0 );
+
+ /* Color buffer group */
+ ctx->Color.IndexMask = 0xffffffff;
+ ctx->Color.ColorMask[0] = 0xff;
+ ctx->Color.ColorMask[1] = 0xff;
+ ctx->Color.ColorMask[2] = 0xff;
+ ctx->Color.ColorMask[3] = 0xff;
+ ctx->Color.SWmasking = GL_FALSE;
+ ctx->Color.ClearIndex = 0;
+ ASSIGN_4V( ctx->Color.ClearColor, 0.0, 0.0, 0.0, 0.0 );
+ ctx->Color.DrawBuffer = GL_FRONT;
+ ctx->Color.AlphaEnabled = GL_FALSE;
+ ctx->Color.AlphaFunc = GL_ALWAYS;
+ ctx->Color.AlphaRef = 0;
+ ctx->Color.BlendEnabled = GL_FALSE;
+ ctx->Color.BlendSrcRGB = GL_ONE;
+ ctx->Color.BlendDstRGB = GL_ZERO;
+ ctx->Color.BlendSrcA = GL_ONE;
+ ctx->Color.BlendDstA = GL_ZERO;
+ ctx->Color.BlendEquation = GL_FUNC_ADD_EXT;
+ ctx->Color.BlendFunc = NULL; /* this pointer set only when needed */
+ ASSIGN_4V( ctx->Color.BlendColor, 0.0, 0.0, 0.0, 0.0 );
+ ctx->Color.IndexLogicOpEnabled = GL_FALSE;
+ ctx->Color.ColorLogicOpEnabled = GL_FALSE;
+ ctx->Color.SWLogicOpEnabled = GL_FALSE;
+ ctx->Color.LogicOp = GL_COPY;
+ ctx->Color.DitherFlag = GL_TRUE;
+ ctx->Color.MultiDrawBuffer = GL_FALSE;
+
+ /* Current group */
+ ASSIGN_4V( ctx->Current.ByteColor, 255, 255, 255, 255);
+ ctx->Current.Index = 1;
+ for (i=0; i<MAX_TEXTURE_UNITS; i++)
+ ASSIGN_4V( ctx->Current.Texcoord[i], 0.0, 0.0, 0.0, 1.0 );
+ ASSIGN_4V( ctx->Current.RasterPos, 0.0, 0.0, 0.0, 1.0 );
+ ctx->Current.RasterDistance = 0.0;
+ ASSIGN_4V( ctx->Current.RasterColor, 1.0, 1.0, 1.0, 1.0 );
+ ctx->Current.RasterIndex = 1;
+ for (i=0; i<MAX_TEXTURE_UNITS; i++)
+ ASSIGN_4V( ctx->Current.RasterMultiTexCoord[i], 0.0, 0.0, 0.0, 1.0 );
+ ctx->Current.RasterTexCoord = ctx->Current.RasterMultiTexCoord[0];
+ ctx->Current.RasterPosValid = GL_TRUE;
+ ctx->Current.EdgeFlag = GL_TRUE;
+ ASSIGN_3V( ctx->Current.Normal, 0.0, 0.0, 1.0 );
+ ctx->Current.Primitive = (GLenum) (GL_POLYGON + 1);
+
+ ctx->Current.Flag = (VERT_NORM|VERT_INDEX|VERT_RGBA|VERT_EDGE|
+ VERT_TEX0_1|VERT_TEX1_1|VERT_MATERIAL);
+
+ init_fallback_arrays( ctx );
+
+ /* Depth buffer group */
+ ctx->Depth.Test = GL_FALSE;
+ ctx->Depth.Clear = 1.0;
+ ctx->Depth.Func = GL_LESS;
+ ctx->Depth.Mask = GL_TRUE;
+
+ /* Evaluators group */
+ ctx->Eval.Map1Color4 = GL_FALSE;
+ ctx->Eval.Map1Index = GL_FALSE;
+ ctx->Eval.Map1Normal = GL_FALSE;
+ ctx->Eval.Map1TextureCoord1 = GL_FALSE;
+ ctx->Eval.Map1TextureCoord2 = GL_FALSE;
+ ctx->Eval.Map1TextureCoord3 = GL_FALSE;
+ ctx->Eval.Map1TextureCoord4 = GL_FALSE;
+ ctx->Eval.Map1Vertex3 = GL_FALSE;
+ ctx->Eval.Map1Vertex4 = GL_FALSE;
+ ctx->Eval.Map2Color4 = GL_FALSE;
+ ctx->Eval.Map2Index = GL_FALSE;
+ ctx->Eval.Map2Normal = GL_FALSE;
+ ctx->Eval.Map2TextureCoord1 = GL_FALSE;
+ ctx->Eval.Map2TextureCoord2 = GL_FALSE;
+ ctx->Eval.Map2TextureCoord3 = GL_FALSE;
+ ctx->Eval.Map2TextureCoord4 = GL_FALSE;
+ ctx->Eval.Map2Vertex3 = GL_FALSE;
+ ctx->Eval.Map2Vertex4 = GL_FALSE;
+ ctx->Eval.AutoNormal = GL_FALSE;
+ ctx->Eval.MapGrid1un = 1;
+ ctx->Eval.MapGrid1u1 = 0.0;
+ ctx->Eval.MapGrid1u2 = 1.0;
+ ctx->Eval.MapGrid2un = 1;
+ ctx->Eval.MapGrid2vn = 1;
+ ctx->Eval.MapGrid2u1 = 0.0;
+ ctx->Eval.MapGrid2u2 = 1.0;
+ ctx->Eval.MapGrid2v1 = 0.0;
+ ctx->Eval.MapGrid2v2 = 1.0;
+
+ /* Evaluator data */
+ {
+ static GLfloat vertex[4] = { 0.0, 0.0, 0.0, 1.0 };
+ static GLfloat normal[3] = { 0.0, 0.0, 1.0 };
+ static GLfloat index[1] = { 1.0 };
+ static GLfloat color[4] = { 1.0, 1.0, 1.0, 1.0 };
+ static GLfloat texcoord[4] = { 0.0, 0.0, 0.0, 1.0 };
+
+ init_1d_map( &ctx->EvalMap.Map1Vertex3, 3, vertex );
+ init_1d_map( &ctx->EvalMap.Map1Vertex4, 4, vertex );
+ init_1d_map( &ctx->EvalMap.Map1Index, 1, index );
+ init_1d_map( &ctx->EvalMap.Map1Color4, 4, color );
+ init_1d_map( &ctx->EvalMap.Map1Normal, 3, normal );
+ init_1d_map( &ctx->EvalMap.Map1Texture1, 1, texcoord );
+ init_1d_map( &ctx->EvalMap.Map1Texture2, 2, texcoord );
+ init_1d_map( &ctx->EvalMap.Map1Texture3, 3, texcoord );
+ init_1d_map( &ctx->EvalMap.Map1Texture4, 4, texcoord );
+
+ init_2d_map( &ctx->EvalMap.Map2Vertex3, 3, vertex );
+ init_2d_map( &ctx->EvalMap.Map2Vertex4, 4, vertex );
+ init_2d_map( &ctx->EvalMap.Map2Index, 1, index );
+ init_2d_map( &ctx->EvalMap.Map2Color4, 4, color );
+ init_2d_map( &ctx->EvalMap.Map2Normal, 3, normal );
+ init_2d_map( &ctx->EvalMap.Map2Texture1, 1, texcoord );
+ init_2d_map( &ctx->EvalMap.Map2Texture2, 2, texcoord );
+ init_2d_map( &ctx->EvalMap.Map2Texture3, 3, texcoord );
+ init_2d_map( &ctx->EvalMap.Map2Texture4, 4, texcoord );
+ }
+
+ /* Fog group */
+ ctx->Fog.Enabled = GL_FALSE;
+ ctx->Fog.Mode = GL_EXP;
+ ASSIGN_4V( ctx->Fog.Color, 0.0, 0.0, 0.0, 0.0 );
+ ctx->Fog.Index = 0.0;
+ ctx->Fog.Density = 1.0;
+ ctx->Fog.Start = 0.0;
+ ctx->Fog.End = 1.0;
+
+ /* Hint group */
+ ctx->Hint.PerspectiveCorrection = GL_DONT_CARE;
+ ctx->Hint.PointSmooth = GL_DONT_CARE;
+ ctx->Hint.LineSmooth = GL_DONT_CARE;
+ ctx->Hint.PolygonSmooth = GL_DONT_CARE;
+ ctx->Hint.Fog = GL_DONT_CARE;
+
+ ctx->Hint.AllowDrawWin = GL_TRUE;
+ ctx->Hint.AllowDrawSpn = GL_TRUE;
+ ctx->Hint.AllowDrawMem = GL_TRUE;
+ ctx->Hint.StrictLighting = GL_TRUE;
+
+ /* Pipeline */
+ gl_pipeline_init( ctx );
+ gl_cva_init( ctx );
+
+ /* Extensions */
+ gl_extensions_ctr( ctx );
+
+ ctx->AllowVertexCull = 0;
+
+ /* Lighting group */
+ for (i=0;i<MAX_LIGHTS;i++) {
+ init_light( &ctx->Light.Light[i], i );
+ }
+ make_empty_list( &ctx->Light.EnabledList );
+
+ init_lightmodel( &ctx->Light.Model );
+ init_material( &ctx->Light.Material[0] );
+ init_material( &ctx->Light.Material[1] );
+ ctx->Light.ShadeModel = GL_SMOOTH;
+ ctx->Light.Enabled = GL_FALSE;
+ ctx->Light.ColorMaterialFace = GL_FRONT_AND_BACK;
+ ctx->Light.ColorMaterialMode = GL_AMBIENT_AND_DIFFUSE;
+ ctx->Light.ColorMaterialBitmask
+ = gl_material_bitmask( ctx,
+ GL_FRONT_AND_BACK,
+ GL_AMBIENT_AND_DIFFUSE, ~0, 0 );
+
+ ctx->Light.ColorMaterialEnabled = GL_FALSE;
+
+ /* Line group */
+ ctx->Line.SmoothFlag = GL_FALSE;
+ ctx->Line.StippleFlag = GL_FALSE;
+ ctx->Line.Width = 1.0;
+ ctx->Line.StipplePattern = 0xffff;
+ ctx->Line.StippleFactor = 1;
+
+ /* Display List group */
+ ctx->List.ListBase = 0;
+
+ /* Pixel group */
+ ctx->Pixel.RedBias = 0.0;
+ ctx->Pixel.RedScale = 1.0;
+ ctx->Pixel.GreenBias = 0.0;
+ ctx->Pixel.GreenScale = 1.0;
+ ctx->Pixel.BlueBias = 0.0;
+ ctx->Pixel.BlueScale = 1.0;
+ ctx->Pixel.AlphaBias = 0.0;
+ ctx->Pixel.AlphaScale = 1.0;
+ ctx->Pixel.ScaleOrBiasRGBA = GL_FALSE;
+ ctx->Pixel.DepthBias = 0.0;
+ ctx->Pixel.DepthScale = 1.0;
+ ctx->Pixel.IndexOffset = 0;
+ ctx->Pixel.IndexShift = 0;
+ ctx->Pixel.ZoomX = 1.0;
+ ctx->Pixel.ZoomY = 1.0;
+ ctx->Pixel.MapColorFlag = GL_FALSE;
+ ctx->Pixel.MapStencilFlag = GL_FALSE;
+ ctx->Pixel.MapStoSsize = 1;
+ ctx->Pixel.MapItoIsize = 1;
+ ctx->Pixel.MapItoRsize = 1;
+ ctx->Pixel.MapItoGsize = 1;
+ ctx->Pixel.MapItoBsize = 1;
+ ctx->Pixel.MapItoAsize = 1;
+ ctx->Pixel.MapRtoRsize = 1;
+ ctx->Pixel.MapGtoGsize = 1;
+ ctx->Pixel.MapBtoBsize = 1;
+ ctx->Pixel.MapAtoAsize = 1;
+ ctx->Pixel.MapStoS[0] = 0;
+ ctx->Pixel.MapItoI[0] = 0;
+ ctx->Pixel.MapItoR[0] = 0.0;
+ ctx->Pixel.MapItoG[0] = 0.0;
+ ctx->Pixel.MapItoB[0] = 0.0;
+ ctx->Pixel.MapItoA[0] = 0.0;
+ ctx->Pixel.MapItoR8[0] = 0;
+ ctx->Pixel.MapItoG8[0] = 0;
+ ctx->Pixel.MapItoB8[0] = 0;
+ ctx->Pixel.MapItoA8[0] = 0;
+ ctx->Pixel.MapRtoR[0] = 0.0;
+ ctx->Pixel.MapGtoG[0] = 0.0;
+ ctx->Pixel.MapBtoB[0] = 0.0;
+ ctx->Pixel.MapAtoA[0] = 0.0;
+
+ /* Point group */
+ ctx->Point.SmoothFlag = GL_FALSE;
+ ctx->Point.Size = 1.0;
+ ctx->Point.Params[0] = 1.0;
+ ctx->Point.Params[1] = 0.0;
+ ctx->Point.Params[2] = 0.0;
+ ctx->Point.Attenuated = GL_FALSE;
+ ctx->Point.MinSize = 0.0;
+ ctx->Point.MaxSize = (GLfloat) MAX_POINT_SIZE;
+ ctx->Point.Threshold = 1.0;
+
+ /* Polygon group */
+ ctx->Polygon.CullFlag = GL_FALSE;
+ ctx->Polygon.CullFaceMode = GL_BACK;
+ ctx->Polygon.FrontFace = GL_CCW;
+ ctx->Polygon.FrontBit = 0;
+ ctx->Polygon.FrontMode = GL_FILL;
+ ctx->Polygon.BackMode = GL_FILL;
+ ctx->Polygon.Unfilled = GL_FALSE;
+ ctx->Polygon.SmoothFlag = GL_FALSE;
+ ctx->Polygon.StippleFlag = GL_FALSE;
+ ctx->Polygon.OffsetFactor = 0.0F;
+ ctx->Polygon.OffsetUnits = 0.0F;
+ ctx->Polygon.OffsetPoint = GL_FALSE;
+ ctx->Polygon.OffsetLine = GL_FALSE;
+ ctx->Polygon.OffsetFill = GL_FALSE;
+
+ /* Polygon Stipple group */
+ MEMSET( ctx->PolygonStipple, 0xff, 32*sizeof(GLuint) );
+
+ /* Scissor group */
+ ctx->Scissor.Enabled = GL_FALSE;
+ ctx->Scissor.X = 0;
+ ctx->Scissor.Y = 0;
+ ctx->Scissor.Width = 0;
+ ctx->Scissor.Height = 0;
+
+ /* Stencil group */
+ ctx->Stencil.Enabled = GL_FALSE;
+ ctx->Stencil.Function = GL_ALWAYS;
+ ctx->Stencil.FailFunc = GL_KEEP;
+ ctx->Stencil.ZPassFunc = GL_KEEP;
+ ctx->Stencil.ZFailFunc = GL_KEEP;
+ ctx->Stencil.Ref = 0;
+ ctx->Stencil.ValueMask = 0xff;
+ ctx->Stencil.Clear = 0;
+ ctx->Stencil.WriteMask = 0xff;
+
+ /* Texture group */
+ ctx->Texture.CurrentUnit = 0; /* multitexture */
+ ctx->Texture.CurrentTransformUnit = 0; /* multitexture */
+ ctx->Texture.Enabled = 0;
+
+ for (i=0; i<MAX_TEXTURE_UNITS; i++)
+ init_texture_unit( ctx, i );
+
+ ctx->Texture.SharedPalette = GL_FALSE;
+ ctx->Texture.Palette[0] = 255;
+ ctx->Texture.Palette[1] = 255;
+ ctx->Texture.Palette[2] = 255;
+ ctx->Texture.Palette[3] = 255;
+ ctx->Texture.PaletteSize = 1;
+ ctx->Texture.PaletteIntFormat = GL_RGBA;
+ ctx->Texture.PaletteFormat = GL_RGBA;
+
+ /* Transformation group */
+ ctx->Transform.MatrixMode = GL_MODELVIEW;
+ ctx->Transform.Normalize = GL_FALSE;
+ ctx->Transform.RescaleNormals = GL_FALSE;
+ for (i=0;i<MAX_CLIP_PLANES;i++) {
+ ctx->Transform.ClipEnabled[i] = GL_FALSE;
+ ASSIGN_4V( ctx->Transform.EyeUserPlane[i], 0.0, 0.0, 0.0, 0.0 );
+ }
+ ctx->Transform.AnyClip = GL_FALSE;
+
+ /* Viewport group */
+ ctx->Viewport.X = 0;
+ ctx->Viewport.Y = 0;
+ ctx->Viewport.Width = 0;
+ ctx->Viewport.Height = 0;
+ ctx->Viewport.Near = 0.0;
+ ctx->Viewport.Far = 1.0;
+ gl_matrix_ctr(&ctx->Viewport.WindowMap);
+
+#define Sz 10
+#define Tz 14
+ ctx->Viewport.WindowMap.m[Sz] = 0.5 * DEPTH_SCALE;
+ ctx->Viewport.WindowMap.m[Tz] = 0.5 * DEPTH_SCALE;
+#undef Sz
+#undef Tz
+
+ ctx->Viewport.WindowMap.flags = MAT_FLAG_GENERAL_SCALE|MAT_FLAG_TRANSLATION;
+ ctx->Viewport.WindowMap.type = MATRIX_3D_NO_ROT;
+
+ /* Vertex arrays */
+ ctx->Array.Vertex.Size = 4;
+ ctx->Array.Vertex.Type = GL_FLOAT;
+ ctx->Array.Vertex.Stride = 0;
+ ctx->Array.Vertex.StrideB = 0;
+ ctx->Array.Vertex.Ptr = NULL;
+ ctx->Array.Vertex.Enabled = GL_FALSE;
+ ctx->Array.Normal.Type = GL_FLOAT;
+ ctx->Array.Normal.Stride = 0;
+ ctx->Array.Normal.StrideB = 0;
+ ctx->Array.Normal.Ptr = NULL;
+ ctx->Array.Normal.Enabled = GL_FALSE;
+ ctx->Array.Color.Size = 4;
+ ctx->Array.Color.Type = GL_FLOAT;
+ ctx->Array.Color.Stride = 0;
+ ctx->Array.Color.StrideB = 0;
+ ctx->Array.Color.Ptr = NULL;
+ ctx->Array.Color.Enabled = GL_FALSE;
+ ctx->Array.Index.Type = GL_FLOAT;
+ ctx->Array.Index.Stride = 0;
+ ctx->Array.Index.StrideB = 0;
+ ctx->Array.Index.Ptr = NULL;
+ ctx->Array.Index.Enabled = GL_FALSE;
+ for (i = 0; i < MAX_TEXTURE_UNITS; i++) {
+ ctx->Array.TexCoord[i].Size = 4;
+ ctx->Array.TexCoord[i].Type = GL_FLOAT;
+ ctx->Array.TexCoord[i].Stride = 0;
+ ctx->Array.TexCoord[i].StrideB = 0;
+ ctx->Array.TexCoord[i].Ptr = NULL;
+ ctx->Array.TexCoord[i].Enabled = GL_FALSE;
+ }
+ ctx->Array.TexCoordInterleaveFactor = 1;
+ ctx->Array.EdgeFlag.Stride = 0;
+ ctx->Array.EdgeFlag.StrideB = 0;
+ ctx->Array.EdgeFlag.Ptr = NULL;
+ ctx->Array.EdgeFlag.Enabled = GL_FALSE;
+ ctx->Array.ActiveTexture = 0; /* GL_ARB_multitexture */
+
+ /* Pixel transfer */
+ ctx->Pack.Alignment = 4;
+ ctx->Pack.RowLength = 0;
+ ctx->Pack.SkipPixels = 0;
+ ctx->Pack.SkipRows = 0;
+ ctx->Pack.SwapBytes = GL_FALSE;
+ ctx->Pack.LsbFirst = GL_FALSE;
+ ctx->Unpack.Alignment = 4;
+ ctx->Unpack.RowLength = 0;
+ ctx->Unpack.SkipPixels = 0;
+ ctx->Unpack.SkipRows = 0;
+ ctx->Unpack.SwapBytes = GL_FALSE;
+ ctx->Unpack.LsbFirst = GL_FALSE;
+
+ /* Feedback */
+ ctx->Feedback.Type = GL_2D; /* TODO: verify */
+ ctx->Feedback.Buffer = NULL;
+ ctx->Feedback.BufferSize = 0;
+ ctx->Feedback.Count = 0;
+
+ /* Selection/picking */
+ ctx->Select.Buffer = NULL;
+ ctx->Select.BufferSize = 0;
+ ctx->Select.BufferCount = 0;
+ ctx->Select.Hits = 0;
+ ctx->Select.NameStackDepth = 0;
+
+ /* Optimized Accum buffer */
+ ctx->IntegerAccumMode = GL_TRUE;
+ ctx->IntegerAccumScaler = 0.0;
+
+ /* multitexture */
+ ctx->TexCoordUnit = 0;
+
+ /* Renderer and client attribute stacks */
+ ctx->AttribStackDepth = 0;
+ ctx->ClientAttribStackDepth = 0;
+
+ /*** Miscellaneous ***/
+ ctx->NewState = NEW_ALL;
+ ctx->RenderMode = GL_RENDER;
+ ctx->StippleCounter = 0;
+ ctx->NeedNormals = GL_FALSE;
+ ctx->DoViewportMapping = GL_TRUE;
+
+ ctx->NeedEyeCoords = GL_FALSE;
+ ctx->NeedEyeNormals = GL_FALSE;
+ ctx->vb_proj_matrix = &ctx->ModelProjectMatrix;
+
+ /* Display list */
+ ctx->CallDepth = 0;
+ ctx->ExecuteFlag = GL_TRUE;
+ ctx->CompileFlag = GL_FALSE;
+ ctx->CurrentListPtr = NULL;
+ ctx->CurrentBlock = NULL;
+ ctx->CurrentListNum = 0;
+ ctx->CurrentPos = 0;
+
+ ctx->ErrorValue = (GLenum) GL_NO_ERROR;
+
+ ctx->CatchSignals = GL_TRUE;
+
+ /* For debug/development only */
+ ctx->NoRaster = getenv("MESA_NO_RASTER") ? GL_TRUE : GL_FALSE;
+
+ /* Dither disable */
+ ctx->NoDither = getenv("MESA_NO_DITHER") ? GL_TRUE : GL_FALSE;
+ if (ctx->NoDither) {
+ if (getenv("MESA_DEBUG")) {
+ fprintf(stderr, "MESA_NO_DITHER set - dithering disabled\n");
+ }
+ ctx->Color.DitherFlag = GL_FALSE;
+ }
+ }
+}
+
+
+
+/*
+ * Allocate a new GLvisual object.
+ * Input: rgbFlag - GL_TRUE=RGB(A) mode, GL_FALSE=Color Index mode
+ * alphaFlag - alloc software alpha buffers?
+ * dbFlag - double buffering?
+ * stereoFlag - stereo buffer?
+ * depthFits - requested minimum bits per depth buffer value
+ * stencilFits - requested minimum bits per stencil buffer value
+ * accumFits - requested minimum bits per accum buffer component
+ * indexFits - number of bits per pixel if rgbFlag==GL_FALSE
+ * red/green/blue/alphaFits - number of bits per color component
+ * in frame buffer for RGB(A) mode.
+ * Return: pointer to new GLvisual or NULL if requested parameters can't
+ * be met.
+ */
+GLvisual *gl_create_visual( GLboolean rgbFlag,
+ GLboolean alphaFlag,
+ GLboolean dbFlag,
+ GLboolean stereoFlag,
+ GLint depthBits,
+ GLint stencilBits,
+ GLint accumBits,
+ GLint indexBits,
+ GLint redBits,
+ GLint greenBits,
+ GLint blueBits,
+ GLint alphaBits )
+{
+ GLvisual *vis;
+
+ if (depthBits > (GLint) (8*sizeof(GLdepth))) {
+ /* can't meet depth buffer requirements */
+ return NULL;
+ }
+ if (stencilBits > (GLint) (8*sizeof(GLstencil))) {
+ /* can't meet stencil buffer requirements */
+ return NULL;
+ }
+ if (accumBits > (GLint) (8*sizeof(GLaccum))) {
+ /* can't meet accum buffer requirements */
+ return NULL;
+ }
+
+ vis = (GLvisual *) calloc( 1, sizeof(GLvisual) );
+ if (!vis) {
+ return NULL;
+ }
+
+ vis->RGBAflag = rgbFlag;
+ vis->DBflag = dbFlag;
+ vis->StereoFlag = stereoFlag;
+ vis->RedBits = redBits;
+ vis->GreenBits = greenBits;
+ vis->BlueBits = blueBits;
+ vis->AlphaBits = alphaFlag ? 8*sizeof(GLubyte) : alphaBits;
+
+ vis->IndexBits = indexBits;
+ vis->DepthBits = (depthBits>0) ? 8*sizeof(GLdepth) : 0;
+ vis->AccumBits = (accumBits>0) ? 8*sizeof(GLaccum) : 0;
+ vis->StencilBits = (stencilBits>0) ? 8*sizeof(GLstencil) : 0;
+
+ vis->SoftwareAlpha = alphaFlag;
+
+ return vis;
+}
+
+
+
+void gl_destroy_visual( GLvisual *vis )
+{
+ free( vis );
+}
+
+
+
+/*
+ * Allocate the proxy textures. If we run out of memory part way through
+ * the allocations clean up and return GL_FALSE.
+ * Return: GL_TRUE=success, GL_FALSE=failure
+ */
+static GLboolean alloc_proxy_textures( GLcontext *ctx )
+{
+ GLboolean out_of_memory;
+ GLint i;
+
+ ctx->Texture.Proxy1D = gl_alloc_texture_object(NULL, 0, 1);
+ if (!ctx->Texture.Proxy1D) {
+ return GL_FALSE;
+ }
+
+ ctx->Texture.Proxy2D = gl_alloc_texture_object(NULL, 0, 2);
+ if (!ctx->Texture.Proxy2D) {
+ gl_free_texture_object(NULL, ctx->Texture.Proxy1D);
+ return GL_FALSE;
+ }
+
+ ctx->Texture.Proxy3D = gl_alloc_texture_object(NULL, 0, 3);
+ if (!ctx->Texture.Proxy3D) {
+ gl_free_texture_object(NULL, ctx->Texture.Proxy1D);
+ gl_free_texture_object(NULL, ctx->Texture.Proxy2D);
+ return GL_FALSE;
+ }
+
+ out_of_memory = GL_FALSE;
+ for (i=0;i<MAX_TEXTURE_LEVELS;i++) {
+ ctx->Texture.Proxy1D->Image[i] = gl_alloc_texture_image();
+ ctx->Texture.Proxy2D->Image[i] = gl_alloc_texture_image();
+ ctx->Texture.Proxy3D->Image[i] = gl_alloc_texture_image();
+ if (!ctx->Texture.Proxy1D->Image[i]
+ || !ctx->Texture.Proxy2D->Image[i]
+ || !ctx->Texture.Proxy3D->Image[i]) {
+ out_of_memory = GL_TRUE;
+ }
+ }
+ if (out_of_memory) {
+ for (i=0;i<MAX_TEXTURE_LEVELS;i++) {
+ if (ctx->Texture.Proxy1D->Image[i]) {
+ gl_free_texture_image(ctx->Texture.Proxy1D->Image[i]);
+ }
+ if (ctx->Texture.Proxy2D->Image[i]) {
+ gl_free_texture_image(ctx->Texture.Proxy2D->Image[i]);
+ }
+ if (ctx->Texture.Proxy3D->Image[i]) {
+ gl_free_texture_image(ctx->Texture.Proxy3D->Image[i]);
+ }
+ }
+ gl_free_texture_object(NULL, ctx->Texture.Proxy1D);
+ gl_free_texture_object(NULL, ctx->Texture.Proxy2D);
+ gl_free_texture_object(NULL, ctx->Texture.Proxy3D);
+ return GL_FALSE;
+ }
+ else {
+ return GL_TRUE;
+ }
+}
+
+
+
+#define MALLOC_STRUCT(T) (struct T *) malloc( sizeof(struct T) )
+
+/*
+ * Allocate and initialize a GLcontext structure.
+ * Input: visual - a GLvisual pointer
+ * sharelist - another context to share display lists with or NULL
+ * driver_ctx - pointer to device driver's context state struct
+ * Return: pointer to a new gl_context struct or NULL if error.
+ */
+GLcontext *gl_create_context( GLvisual *visual,
+ GLcontext *share_list,
+ void *driver_ctx,
+ GLboolean direct )
+{
+ GLcontext *ctx;
+ GLuint i;
+
+ (void) direct; /* not used */
+
+ /* do some implementation tests */
+ assert( sizeof(GLbyte) == 1 );
+ assert( sizeof(GLshort) >= 2 );
+ assert( sizeof(GLint) >= 4 );
+ assert( sizeof(GLubyte) == 1 );
+ assert( sizeof(GLushort) >= 2 );
+ assert( sizeof(GLuint) >= 4 );
+
+ /* misc one-time initializations */
+ one_time_init();
+
+ ctx = (GLcontext *) calloc( 1, sizeof(GLcontext) );
+ if (!ctx) {
+ return NULL;
+ }
+
+ ctx->DriverCtx = driver_ctx;
+ ctx->Visual = visual;
+ ctx->Buffer = NULL;
+
+ ctx->VB = gl_vb_create_for_immediate( ctx );
+ if (!ctx->VB) {
+ free( ctx );
+ return NULL;
+ }
+ ctx->input = ctx->VB->IM;
+
+ ctx->PB = gl_alloc_pb();
+ if (!ctx->PB) {
+ free( ctx->VB );
+ free( ctx );
+ return NULL;
+ }
+
+ if (share_list) {
+ /* share the group of display lists of another context */
+ ctx->Shared = share_list->Shared;
+ }
+ else {
+ /* allocate new group of display lists */
+ ctx->Shared = alloc_shared_state();
+ if (!ctx->Shared) {
+ free(ctx->VB);
+ free(ctx->PB);
+ free(ctx);
+ return NULL;
+ }
+ }
+ ctx->Shared->RefCount++;
+
+ initialize_context( ctx );
+ gl_reset_vb( ctx->VB );
+ gl_reset_input( ctx );
+
+
+ ctx->ShineTabList = MALLOC_STRUCT( gl_shine_tab );
+ make_empty_list( ctx->ShineTabList );
+
+ for (i = 0 ; i < 10 ; i++) {
+ struct gl_shine_tab *s = MALLOC_STRUCT( gl_shine_tab );
+ s->shininess = -1;
+ s->refcount = 0;
+ insert_at_tail( ctx->ShineTabList, s );
+ }
+
+ for (i = 0 ; i < 4 ; i++) {
+ ctx->ShineTable[i] = ctx->ShineTabList->prev;
+ ctx->ShineTable[i]->refcount++;
+ }
+
+ if (visual->DBflag) {
+ ctx->Color.DrawBuffer = GL_BACK;
+ ctx->Color.DriverDrawBuffer = GL_BACK_LEFT;
+ ctx->Color.DrawDestMask = BACK_LEFT_BIT;
+ ctx->Pixel.ReadBuffer = GL_BACK;
+ ctx->Pixel.DriverReadBuffer = GL_BACK_LEFT;
+ }
+ else {
+ ctx->Color.DrawBuffer = GL_FRONT;
+ ctx->Color.DriverDrawBuffer = GL_FRONT_LEFT;
+ ctx->Color.DrawDestMask = FRONT_LEFT_BIT;
+ ctx->Pixel.ReadBuffer = GL_FRONT;
+ ctx->Pixel.DriverReadBuffer = GL_FRONT_LEFT;
+ }
+
+#ifdef PROFILE
+ init_timings( ctx );
+#endif
+
+#ifdef GL_VERSION_1_1
+ if (!alloc_proxy_textures(ctx)) {
+ free_shared_state(ctx, ctx->Shared);
+ free(ctx->VB);
+ free(ctx->PB);
+ free(ctx);
+ return NULL;
+ }
+#endif
+
+ gl_init_api_function_pointers( ctx );
+ ctx->API = ctx->Exec; /* GL_EXECUTE is default */
+
+ return ctx;
+}
+
+/* Just reads the config files...
+ */
+void gl_context_initialize( GLcontext *ctx )
+{
+ gl_read_config_file( ctx );
+}
+
+
+
+
+/*
+ * Destroy a gl_context structure.
+ */
+void gl_destroy_context( GLcontext *ctx )
+{
+ if (ctx) {
+
+ GLuint i;
+ struct gl_shine_tab *s, *tmps;
+
+#ifdef PROFILE
+ if (getenv("MESA_PROFILE")) {
+ print_timings( ctx );
+ }
+#endif
+
+ gl_matrix_dtr( &ctx->ModelView );
+ for (i = 0 ; i < MAX_MODELVIEW_STACK_DEPTH ; i++) {
+ gl_matrix_dtr( &ctx->ModelViewStack[i] );
+ }
+
+
+ free( ctx->PB );
+ free( ctx->VB );
+
+ ctx->Shared->RefCount--;
+ assert(ctx->Shared->RefCount>=0);
+ if (ctx->Shared->RefCount==0) {
+ /* free shared state */
+ free_shared_state( ctx, ctx->Shared );
+ }
+
+ foreach_s( s, tmps, ctx->ShineTabList ) {
+ free( s );
+ }
+ free( ctx->ShineTabList );
+
+ /* Free proxy texture objects */
+ gl_free_texture_object( NULL, ctx->Texture.Proxy1D );
+ gl_free_texture_object( NULL, ctx->Texture.Proxy2D );
+ gl_free_texture_object( NULL, ctx->Texture.Proxy3D );
+
+ /* Free evaluator data */
+ if (ctx->EvalMap.Map1Vertex3.Points)
+ free( ctx->EvalMap.Map1Vertex3.Points );
+ if (ctx->EvalMap.Map1Vertex4.Points)
+ free( ctx->EvalMap.Map1Vertex4.Points );
+ if (ctx->EvalMap.Map1Index.Points)
+ free( ctx->EvalMap.Map1Index.Points );
+ if (ctx->EvalMap.Map1Color4.Points)
+ free( ctx->EvalMap.Map1Color4.Points );
+ if (ctx->EvalMap.Map1Normal.Points)
+ free( ctx->EvalMap.Map1Normal.Points );
+ if (ctx->EvalMap.Map1Texture1.Points)
+ free( ctx->EvalMap.Map1Texture1.Points );
+ if (ctx->EvalMap.Map1Texture2.Points)
+ free( ctx->EvalMap.Map1Texture2.Points );
+ if (ctx->EvalMap.Map1Texture3.Points)
+ free( ctx->EvalMap.Map1Texture3.Points );
+ if (ctx->EvalMap.Map1Texture4.Points)
+ free( ctx->EvalMap.Map1Texture4.Points );
+
+ if (ctx->EvalMap.Map2Vertex3.Points)
+ free( ctx->EvalMap.Map2Vertex3.Points );
+ if (ctx->EvalMap.Map2Vertex4.Points)
+ free( ctx->EvalMap.Map2Vertex4.Points );
+ if (ctx->EvalMap.Map2Index.Points)
+ free( ctx->EvalMap.Map2Index.Points );
+ if (ctx->EvalMap.Map2Color4.Points)
+ free( ctx->EvalMap.Map2Color4.Points );
+ if (ctx->EvalMap.Map2Normal.Points)
+ free( ctx->EvalMap.Map2Normal.Points );
+ if (ctx->EvalMap.Map2Texture1.Points)
+ free( ctx->EvalMap.Map2Texture1.Points );
+ if (ctx->EvalMap.Map2Texture2.Points)
+ free( ctx->EvalMap.Map2Texture2.Points );
+ if (ctx->EvalMap.Map2Texture3.Points)
+ free( ctx->EvalMap.Map2Texture3.Points );
+ if (ctx->EvalMap.Map2Texture4.Points)
+ free( ctx->EvalMap.Map2Texture4.Points );
+
+ free( (void *) ctx );
+
+#ifndef THREADS
+ if (ctx==CC) {
+ CC = NULL;
+ CURRENT_INPUT = NULL;
+ }
+#endif
+
+ }
+}
+
+
+
+/*
+ * Create a new framebuffer. A GLframebuffer is a struct which
+ * encapsulates the depth, stencil and accum buffers and related
+ * parameters.
+ * Input: visual - a GLvisual pointer
+ * Return: pointer to new GLframebuffer struct or NULL if error.
+ */
+GLframebuffer *gl_create_framebuffer( GLvisual *visual )
+{
+ GLframebuffer *buffer;
+
+ buffer = (GLframebuffer *) calloc( 1, sizeof(GLframebuffer) );
+ if (!buffer) {
+ return NULL;
+ }
+
+ buffer->Visual = visual;
+
+ return buffer;
+}
+
+
+
+/*
+ * Free a framebuffer struct and its buffers.
+ */
+void gl_destroy_framebuffer( GLframebuffer *buffer )
+{
+ if (buffer) {
+ if (buffer->Depth) {
+ free( buffer->Depth );
+ }
+ if (buffer->Accum) {
+ free( buffer->Accum );
+ }
+ if (buffer->Stencil) {
+ free( buffer->Stencil );
+ }
+ if (buffer->FrontLeftAlpha) {
+ free( buffer->FrontLeftAlpha );
+ }
+ if (buffer->BackLeftAlpha) {
+ free( buffer->BackLeftAlpha );
+ }
+ if (buffer->FrontRightAlpha) {
+ free( buffer->FrontRightAlpha );
+ }
+ if (buffer->BackRightAlpha) {
+ free( buffer->BackRightAlpha );
+ }
+ free(buffer);
+ }
+}
+
+
+
+/*
+ * Set the current context, binding the given frame buffer to the context.
+ */
+void gl_make_current( GLcontext *ctx, GLframebuffer *buffer )
+{
+ GET_CONTEXT;
+
+ /* Flush the old context
+ */
+ if (CC) {
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(CC, "gl_make_current");
+ }
+
+#ifdef THREADS
+ /* TODO: unbind old buffer from context? */
+ set_thread_context( ctx );
+#else
+ if (CC && CC->Buffer) {
+ /* unbind frame buffer from context */
+ CC->Buffer = NULL;
+ }
+ CC = ctx;
+ if (ctx) {
+ SET_IMMEDIATE(ctx, ctx->input);
+ }
+#endif
+
+ if (MESA_VERBOSE) fprintf(stderr, "gl_make_current()\n");
+
+ if (ctx && buffer) {
+ /* TODO: check if ctx and buffer's visual match??? */
+ ctx->Buffer = buffer; /* Bind the frame buffer to the context */
+ ctx->NewState = NEW_ALL; /* just to be safe */
+ gl_update_state( ctx );
+ }
+}
+
+
+/*
+ * Return current context handle.
+ */
+GLcontext *gl_get_current_context( void )
+{
+#ifdef THREADS
+ return gl_get_thread_context();
+#else
+ return CC;
+#endif
+}
+
+
+
+/*
+ * Copy attribute groups from one context to another.
+ * Input: src - source context
+ * dst - destination context
+ * mask - bitwise OR of GL_*_BIT flags
+ */
+void gl_copy_context( const GLcontext *src, GLcontext *dst, GLuint mask )
+{
+ if (mask & GL_ACCUM_BUFFER_BIT) {
+ MEMCPY( &dst->Accum, &src->Accum, sizeof(struct gl_accum_attrib) );
+ }
+ if (mask & GL_COLOR_BUFFER_BIT) {
+ MEMCPY( &dst->Color, &src->Color, sizeof(struct gl_colorbuffer_attrib) );
+ }
+ if (mask & GL_CURRENT_BIT) {
+ MEMCPY( &dst->Current, &src->Current, sizeof(struct gl_current_attrib) );
+ }
+ if (mask & GL_DEPTH_BUFFER_BIT) {
+ MEMCPY( &dst->Depth, &src->Depth, sizeof(struct gl_depthbuffer_attrib) );
+ }
+ if (mask & GL_ENABLE_BIT) {
+ /* no op */
+ }
+ if (mask & GL_EVAL_BIT) {
+ MEMCPY( &dst->Eval, &src->Eval, sizeof(struct gl_eval_attrib) );
+ }
+ if (mask & GL_FOG_BIT) {
+ MEMCPY( &dst->Fog, &src->Fog, sizeof(struct gl_fog_attrib) );
+ }
+ if (mask & GL_HINT_BIT) {
+ MEMCPY( &dst->Hint, &src->Hint, sizeof(struct gl_hint_attrib) );
+ }
+ if (mask & GL_LIGHTING_BIT) {
+ MEMCPY( &dst->Light, &src->Light, sizeof(struct gl_light_attrib) );
+/* gl_reinit_light_attrib( &dst->Light ); */
+ }
+ if (mask & GL_LINE_BIT) {
+ MEMCPY( &dst->Line, &src->Line, sizeof(struct gl_line_attrib) );
+ }
+ if (mask & GL_LIST_BIT) {
+ MEMCPY( &dst->List, &src->List, sizeof(struct gl_list_attrib) );
+ }
+ if (mask & GL_PIXEL_MODE_BIT) {
+ MEMCPY( &dst->Pixel, &src->Pixel, sizeof(struct gl_pixel_attrib) );
+ }
+ if (mask & GL_POINT_BIT) {
+ MEMCPY( &dst->Point, &src->Point, sizeof(struct gl_point_attrib) );
+ }
+ if (mask & GL_POLYGON_BIT) {
+ MEMCPY( &dst->Polygon, &src->Polygon, sizeof(struct gl_polygon_attrib) );
+ }
+ if (mask & GL_POLYGON_STIPPLE_BIT) {
+ /* Use loop instead of MEMCPY due to problem with Portland Group's
+ * C compiler. Reported by John Stone.
+ */
+ int i;
+ for (i=0;i<32;i++) {
+ dst->PolygonStipple[i] = src->PolygonStipple[i];
+ }
+ }
+ if (mask & GL_SCISSOR_BIT) {
+ MEMCPY( &dst->Scissor, &src->Scissor, sizeof(struct gl_scissor_attrib) );
+ }
+ if (mask & GL_STENCIL_BUFFER_BIT) {
+ MEMCPY( &dst->Stencil, &src->Stencil, sizeof(struct gl_stencil_attrib) );
+ }
+ if (mask & GL_TEXTURE_BIT) {
+ MEMCPY( &dst->Texture, &src->Texture, sizeof(struct gl_texture_attrib) );
+ }
+ if (mask & GL_TRANSFORM_BIT) {
+ MEMCPY( &dst->Transform, &src->Transform, sizeof(struct gl_transform_attrib) );
+ }
+ if (mask & GL_VIEWPORT_BIT) {
+ MEMCPY( &dst->Viewport, &src->Viewport, sizeof(struct gl_viewport_attrib) );
+ }
+}
+
+
+
+/*
+ * Someday a GLS library or OpenGL-like debugger may call this function
+ * to register it's own set of API entry points.
+ * Input: ctx - the context to set API pointers for
+ * api - if NULL, restore original API pointers
+ * else, set API function table to this table.
+ */
+void gl_set_api_table( GLcontext *ctx, const struct gl_api_table *api )
+{
+ if (api) {
+ MEMCPY( &ctx->API, api, sizeof(struct gl_api_table) );
+ }
+ else {
+ MEMCPY( &ctx->API, &ctx->Exec, sizeof(struct gl_api_table) );
+ }
+}
+
+
+
+
+/**********************************************************************/
+/***** Miscellaneous functions *****/
+/**********************************************************************/
+
+
+/*
+ * This function is called when the Mesa user has stumbled into a code
+ * path which may not be implemented fully or correctly.
+ */
+void gl_problem( const GLcontext *ctx, const char *s )
+{
+ fprintf( stderr, "Mesa implementation error: %s\n", s );
+ fprintf( stderr, "Report to mesa-bugs@mesa3d.org\n" );
+ (void) ctx;
+}
+
+
+
+/*
+ * This is called to inform the user that he or she has tried to do
+ * something illogical or if there's likely a bug in their program
+ * (like enabled depth testing without a depth buffer).
+ */
+void gl_warning( const GLcontext *ctx, const char *s )
+{
+ GLboolean debug;
+#ifdef DEBUG
+ debug = GL_TRUE;
+#else
+ if (getenv("MESA_DEBUG")) {
+ debug = GL_TRUE;
+ }
+ else {
+ debug = GL_FALSE;
+ }
+#endif
+ if (debug) {
+ fprintf( stderr, "Mesa warning: %s\n", s );
+ }
+ (void) ctx;
+}
+
+
+
+void gl_compile_error( GLcontext *ctx, GLenum error, const char *s )
+{
+ if (ctx->CompileFlag)
+ gl_save_error( ctx, error, s );
+
+ if (ctx->ExecuteFlag)
+ gl_error( ctx, error, s );
+}
+
+
+/*
+ * This is Mesa's error handler. Normally, all that's done is the updating
+ * of the current error value. If Mesa is compiled with -DDEBUG or if the
+ * environment variable "MESA_DEBUG" is defined then a real error message
+ * is printed to stderr.
+ * Input: error - the error value
+ * s - a diagnostic string
+ */
+void gl_error( GLcontext *ctx, GLenum error, const char *s )
+{
+ GLboolean debug;
+
+#ifdef DEBUG
+ debug = GL_TRUE;
+#else
+ if (getenv("MESA_DEBUG")) {
+ debug = GL_TRUE;
+ }
+ else {
+ debug = GL_FALSE;
+ }
+#endif
+
+ if (debug) {
+ char errstr[1000];
+
+ switch (error) {
+ case GL_NO_ERROR:
+ strcpy( errstr, "GL_NO_ERROR" );
+ break;
+ case GL_INVALID_VALUE:
+ strcpy( errstr, "GL_INVALID_VALUE" );
+ break;
+ case GL_INVALID_ENUM:
+ strcpy( errstr, "GL_INVALID_ENUM" );
+ break;
+ case GL_INVALID_OPERATION:
+ strcpy( errstr, "GL_INVALID_OPERATION" );
+ break;
+ case GL_STACK_OVERFLOW:
+ strcpy( errstr, "GL_STACK_OVERFLOW" );
+ break;
+ case GL_STACK_UNDERFLOW:
+ strcpy( errstr, "GL_STACK_UNDERFLOW" );
+ break;
+ case GL_OUT_OF_MEMORY:
+ strcpy( errstr, "GL_OUT_OF_MEMORY" );
+ break;
+ default:
+ strcpy( errstr, "unknown" );
+ break;
+ }
+ fprintf( stderr, "Mesa user error: %s in %s\n", errstr, s );
+ }
+
+ if (ctx->ErrorValue==GL_NO_ERROR) {
+ ctx->ErrorValue = error;
+ }
+
+ /* Call device driver's error handler, if any. This is used on the Mac. */
+ if (ctx->Driver.Error) {
+ (*ctx->Driver.Error)( ctx );
+ }
+}
+
+
+
+/*
+ * Execute a glGetError command
+ */
+GLenum gl_GetError( GLcontext *ctx )
+{
+ GLenum e = ctx->ErrorValue;
+
+ ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL( ctx, "glGetError", 0);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ fprintf(stderr, "glGetError <-- %s\n", gl_lookup_enum_by_nr(e));
+
+ ctx->ErrorValue = (GLenum) GL_NO_ERROR;
+ return e;
+}
+
+
+
+void gl_ResizeBuffersMESA( GLcontext *ctx )
+{
+ GLuint buf_width, buf_height;
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ fprintf(stderr, "glResizeBuffersMESA\n");
+
+ /* ask device driver for size of output buffer */
+ (*ctx->Driver.GetBufferSize)( ctx, &buf_width, &buf_height );
+
+ /* see if size of device driver's color buffer (window) has changed */
+ if (ctx->Buffer->Width == (GLint) buf_width &&
+ ctx->Buffer->Height == (GLint) buf_height)
+ return;
+
+ ctx->NewState |= NEW_RASTER_OPS; /* to update scissor / window bounds */
+
+ /* save buffer size */
+ ctx->Buffer->Width = buf_width;
+ ctx->Buffer->Height = buf_height;
+
+ /* Reallocate other buffers if needed. */
+ if (ctx->Visual->DepthBits>0) {
+ /* reallocate depth buffer */
+ (*ctx->Driver.AllocDepthBuffer)( ctx );
+ }
+ if (ctx->Visual->StencilBits>0) {
+ /* reallocate stencil buffer */
+ gl_alloc_stencil_buffer( ctx );
+ }
+ if (ctx->Visual->AccumBits>0) {
+ /* reallocate accum buffer */
+ gl_alloc_accum_buffer( ctx );
+ }
+ if (ctx->Visual->SoftwareAlpha) {
+ gl_alloc_alpha_buffers( ctx );
+ }
+}
+
+
+
+
+/**********************************************************************/
+/***** State update logic *****/
+/**********************************************************************/
+
+
+/*
+ * Since the device driver may or may not support pixel logic ops we
+ * have to make some extensive tests to determine whether or not
+ * software-implemented logic operations have to be used.
+ */
+static void update_pixel_logic( GLcontext *ctx )
+{
+ if (ctx->Visual->RGBAflag) {
+ /* RGBA mode blending w/ Logic Op */
+ if (ctx->Color.ColorLogicOpEnabled) {
+ if (ctx->Driver.LogicOp
+ && (*ctx->Driver.LogicOp)( ctx, ctx->Color.LogicOp )) {
+ /* Device driver can do logic, don't have to do it in software */
+ ctx->Color.SWLogicOpEnabled = GL_FALSE;
+ }
+ else {
+ /* Device driver can't do logic op so we do it in software */
+ ctx->Color.SWLogicOpEnabled = GL_TRUE;
+ }
+ }
+ else {
+ /* no logic op */
+ if (ctx->Driver.LogicOp) {
+ (void) (*ctx->Driver.LogicOp)( ctx, GL_COPY );
+ }
+ ctx->Color.SWLogicOpEnabled = GL_FALSE;
+ }
+ }
+ else {
+ /* CI mode Logic Op */
+ if (ctx->Color.IndexLogicOpEnabled) {
+ if (ctx->Driver.LogicOp
+ && (*ctx->Driver.LogicOp)( ctx, ctx->Color.LogicOp )) {
+ /* Device driver can do logic, don't have to do it in software */
+ ctx->Color.SWLogicOpEnabled = GL_FALSE;
+ }
+ else {
+ /* Device driver can't do logic op so we do it in software */
+ ctx->Color.SWLogicOpEnabled = GL_TRUE;
+ }
+ }
+ else {
+ /* no logic op */
+ if (ctx->Driver.LogicOp) {
+ (void) (*ctx->Driver.LogicOp)( ctx, GL_COPY );
+ }
+ ctx->Color.SWLogicOpEnabled = GL_FALSE;
+ }
+ }
+}
+
+
+
+/*
+ * Check if software implemented RGBA or Color Index masking is needed.
+ */
+static void update_pixel_masking( GLcontext *ctx )
+{
+ if (ctx->Visual->RGBAflag) {
+ GLuint *colorMask = (GLuint *) ctx->Color.ColorMask;
+ if (*colorMask == 0xffffffff) {
+ /* disable masking */
+ if (ctx->Driver.ColorMask) {
+ (void) (*ctx->Driver.ColorMask)( ctx, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
+ }
+ ctx->Color.SWmasking = GL_FALSE;
+ }
+ else {
+ /* Ask driver to do color masking, if it can't then
+ * do it in software
+ */
+ GLboolean red = ctx->Color.ColorMask[RCOMP] ? GL_TRUE : GL_FALSE;
+ GLboolean green = ctx->Color.ColorMask[GCOMP] ? GL_TRUE : GL_FALSE;
+ GLboolean blue = ctx->Color.ColorMask[BCOMP] ? GL_TRUE : GL_FALSE;
+ GLboolean alpha = ctx->Color.ColorMask[ACOMP] ? GL_TRUE : GL_FALSE;
+ if (ctx->Driver.ColorMask
+ && (*ctx->Driver.ColorMask)( ctx, red, green, blue, alpha )) {
+ ctx->Color.SWmasking = GL_FALSE;
+ }
+ else {
+ ctx->Color.SWmasking = GL_TRUE;
+ }
+ }
+ }
+ else {
+ if (ctx->Color.IndexMask==0xffffffff) {
+ /* disable masking */
+ if (ctx->Driver.IndexMask) {
+ (void) (*ctx->Driver.IndexMask)( ctx, 0xffffffff );
+ }
+ ctx->Color.SWmasking = GL_FALSE;
+ }
+ else {
+ /* Ask driver to do index masking, if it can't then
+ * do it in software
+ */
+ if (ctx->Driver.IndexMask
+ && (*ctx->Driver.IndexMask)( ctx, ctx->Color.IndexMask )) {
+ ctx->Color.SWmasking = GL_FALSE;
+ }
+ else {
+ ctx->Color.SWmasking = GL_TRUE;
+ }
+ }
+ }
+}
+
+
+static void update_fog_mode( GLcontext *ctx )
+{
+ if (ctx->Fog.Enabled) {
+ if (ctx->Texture.Enabled)
+ ctx->FogMode = FOG_FRAGMENT;
+ else if (ctx->Hint.Fog == GL_NICEST)
+ ctx->FogMode = FOG_FRAGMENT;
+ else
+ ctx->FogMode = FOG_VERTEX;
+
+ if (ctx->Driver.GetParameteri)
+ if ((ctx->Driver.GetParameteri)( ctx, DD_HAVE_HARDWARE_FOG ))
+ ctx->FogMode = FOG_FRAGMENT;
+ }
+ else {
+ ctx->FogMode = FOG_NONE;
+ }
+}
+
+
+/*
+ * Recompute the value of ctx->RasterMask, etc. according to
+ * the current context.
+ */
+static void update_rasterflags( GLcontext *ctx )
+{
+ ctx->RasterMask = 0;
+
+ if (ctx->Color.AlphaEnabled) ctx->RasterMask |= ALPHATEST_BIT;
+ if (ctx->Color.BlendEnabled) ctx->RasterMask |= BLEND_BIT;
+ if (ctx->Depth.Test) ctx->RasterMask |= DEPTH_BIT;
+ if (ctx->FogMode==FOG_FRAGMENT) ctx->RasterMask |= FOG_BIT;
+ if (ctx->Color.SWLogicOpEnabled) ctx->RasterMask |= LOGIC_OP_BIT;
+ if (ctx->Scissor.Enabled) ctx->RasterMask |= SCISSOR_BIT;
+ if (ctx->Stencil.Enabled) ctx->RasterMask |= STENCIL_BIT;
+ if (ctx->Color.SWmasking) ctx->RasterMask |= MASKING_BIT;
+
+ if (ctx->Visual->SoftwareAlpha && ctx->Color.ColorMask[ACOMP]
+ && ctx->Color.DrawBuffer != GL_NONE)
+ ctx->RasterMask |= ALPHABUF_BIT;
+
+ if ( ctx->Viewport.X<0
+ || ctx->Viewport.X + ctx->Viewport.Width > ctx->Buffer->Width
+ || ctx->Viewport.Y<0
+ || ctx->Viewport.Y + ctx->Viewport.Height > ctx->Buffer->Height) {
+ ctx->RasterMask |= WINCLIP_BIT;
+ }
+
+ /* If we're not drawing to exactly one color buffer set the
+ * MULTI_DRAW_BIT flag. Also set it if we're drawing to no
+ * buffers or the RGBA or CI mask disables all writes.
+ */
+
+ ctx->TriangleCaps &= ~DD_MULTIDRAW;
+
+ if (ctx->Color.MultiDrawBuffer) {
+ ctx->RasterMask |= MULTI_DRAW_BIT;
+ ctx->TriangleCaps |= DD_MULTIDRAW;
+ }
+ else if (ctx->Color.DrawBuffer==GL_NONE) {
+ ctx->RasterMask |= MULTI_DRAW_BIT;
+ ctx->TriangleCaps |= DD_MULTIDRAW;
+ }
+ else if (ctx->Visual->RGBAflag && ctx->Color.ColorMask==0) {
+ /* all RGBA channels disabled */
+ ctx->RasterMask |= MULTI_DRAW_BIT;
+ ctx->TriangleCaps |= DD_MULTIDRAW;
+ ctx->Color.DrawDestMask = 0;
+ }
+ else if (!ctx->Visual->RGBAflag && ctx->Color.IndexMask==0) {
+ /* all color index bits disabled */
+ ctx->RasterMask |= MULTI_DRAW_BIT;
+ ctx->TriangleCaps |= DD_MULTIDRAW;
+ ctx->Color.DrawDestMask = 0;
+ }
+}
+
+
+void gl_print_state( const char *msg, GLuint state )
+{
+ fprintf(stderr,
+ "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+ msg,
+ state,
+ (state & NEW_LIGHTING) ? "lighting, " : "",
+ (state & NEW_RASTER_OPS) ? "raster-ops, " : "",
+ (state & NEW_TEXTURING) ? "texturing, " : "",
+ (state & NEW_POLYGON) ? "polygon, " : "",
+ (state & NEW_DRVSTATE0) ? "driver-0, " : "",
+ (state & NEW_DRVSTATE1) ? "driver-1, " : "",
+ (state & NEW_DRVSTATE2) ? "driver-2, " : "",
+ (state & NEW_DRVSTATE3) ? "driver-3, " : "",
+ (state & NEW_MODELVIEW) ? "modelview, " : "",
+ (state & NEW_PROJECTION) ? "projection, " : "",
+ (state & NEW_TEXTURE_MATRIX) ? "texture-matrix, " : "",
+ (state & NEW_USER_CLIP) ? "user-clip, " : "",
+ (state & NEW_TEXTURE_ENV) ? "texture-env, " : "",
+ (state & NEW_CLIENT_STATE) ? "client-state, " : "",
+ (state & NEW_FOG) ? "fog, " : "",
+ (state & NEW_NORMAL_TRANSFORM) ? "normal-transform, " : "",
+ (state & NEW_VIEWPORT) ? "viewport, " : "",
+ (state & NEW_TEXTURE_ENABLE) ? "texture-enable, " : "");
+}
+
+void gl_print_enable_flags( const char *msg, GLuint flags )
+{
+ fprintf(stderr,
+ "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s\n",
+ msg,
+ flags,
+ (flags & ENABLE_TEX0) ? "tex-0, " : "",
+ (flags & ENABLE_TEX1) ? "tex-1, " : "",
+ (flags & ENABLE_LIGHT) ? "light, " : "",
+ (flags & ENABLE_FOG) ? "fog, " : "",
+ (flags & ENABLE_USERCLIP) ? "userclip, " : "",
+ (flags & ENABLE_TEXGEN0) ? "tex-gen-0, " : "",
+ (flags & ENABLE_TEXGEN1) ? "tex-gen-1, " : "",
+ (flags & ENABLE_TEXMAT0) ? "tex-mat-0, " : "",
+ (flags & ENABLE_TEXMAT1) ? "tex-mat-1, " : "",
+ (flags & ENABLE_NORMALIZE) ? "normalize, " : "",
+ (flags & ENABLE_RESCALE) ? "rescale, " : "");
+}
+
+
+/*
+ * If ctx->NewState is non-zero then this function MUST be called before
+ * rendering any primitive. Basically, function pointers and miscellaneous
+ * flags are updated to reflect the current state of the state machine.
+ */
+void gl_update_state( GLcontext *ctx )
+{
+ GLuint i;
+
+ if (MESA_VERBOSE & VERBOSE_STATE)
+ gl_print_state("", ctx->NewState);
+
+ if (ctx->NewState & NEW_CLIENT_STATE)
+ gl_update_client_state( ctx );
+
+ if ((ctx->NewState & NEW_TEXTURE_ENABLE) &&
+ (ctx->Enabled & ENABLE_TEX_ANY) != ctx->Texture.Enabled)
+ ctx->NewState |= NEW_TEXTURING | NEW_RASTER_OPS;
+
+ if (ctx->NewState & NEW_TEXTURE_ENV) {
+ if (ctx->Texture.Unit[0].EnvMode == ctx->Texture.Unit[0].LastEnvMode &&
+ ctx->Texture.Unit[1].EnvMode == ctx->Texture.Unit[1].LastEnvMode)
+ ctx->NewState &= ~NEW_TEXTURE_ENV;
+ ctx->Texture.Unit[0].LastEnvMode = ctx->Texture.Unit[0].EnvMode;
+ ctx->Texture.Unit[1].LastEnvMode = ctx->Texture.Unit[1].EnvMode;
+ }
+
+ if ((ctx->NewState & ~(NEW_CLIENT_STATE|NEW_TEXTURE_ENABLE)) == 0)
+ goto finished;
+
+ if (ctx->NewState & NEW_TEXTURE_MATRIX) {
+ ctx->Enabled &= ~(ENABLE_TEXMAT0|ENABLE_TEXMAT1);
+
+ for (i=0; i < MAX_TEXTURE_UNITS; i++) {
+ if (ctx->TextureMatrix[i].flags & MAT_DIRTY_ALL_OVER)
+ {
+ gl_matrix_analyze( &ctx->TextureMatrix[i] );
+ ctx->TextureMatrix[i].flags &= ~MAT_DIRTY_DEPENDENTS;
+
+ if (ctx->Texture.Unit[i].Enabled &&
+ ctx->TextureMatrix[i].type != MATRIX_IDENTITY)
+ ctx->Enabled |= ENABLE_TEXMAT0 << i;
+ }
+ }
+ }
+
+ if (ctx->NewState & NEW_TEXTURING) {
+ ctx->Texture.NeedNormals = GL_FALSE;
+ gl_update_dirty_texobjs(ctx);
+ ctx->Enabled &= ~(ENABLE_TEXGEN0|ENABLE_TEXGEN1);
+ ctx->Texture.ReallyEnabled = 0;
+
+ for (i=0; i < MAX_TEXTURE_UNITS; i++) {
+ if (ctx->Texture.Unit[i].Enabled) {
+ gl_update_texture_unit( ctx, &ctx->Texture.Unit[i] );
+
+ ctx->Texture.ReallyEnabled |=
+ ctx->Texture.Unit[i].ReallyEnabled<<(i*4);
+
+ if (ctx->Texture.Unit[i].GenFlags != 0) {
+ ctx->Enabled |= ENABLE_TEXGEN0 << i;
+
+ if (ctx->Texture.Unit[i].GenFlags & TEXGEN_NEED_NORMALS)
+ {
+ ctx->Texture.NeedNormals = GL_TRUE;
+ ctx->Texture.NeedEyeCoords = GL_TRUE;
+ }
+
+ if (ctx->Texture.Unit[i].GenFlags & TEXGEN_NEED_EYE_COORD)
+ {
+ ctx->Texture.NeedEyeCoords = GL_TRUE;
+ }
+ }
+ }
+ }
+
+ ctx->Texture.Enabled = ctx->Enabled & ENABLE_TEX_ANY;
+ ctx->NeedNormals = (ctx->Light.Enabled || ctx->Texture.NeedNormals);
+ }
+
+ if (ctx->NewState & (NEW_RASTER_OPS | NEW_LIGHTING)) {
+ if (ctx->NewState & NEW_RASTER_OPS) {
+ update_pixel_logic(ctx);
+ update_pixel_masking(ctx);
+ update_fog_mode(ctx);
+ update_rasterflags(ctx);
+ if (ctx->Driver.Dither) {
+ (*ctx->Driver.Dither)( ctx, ctx->Color.DitherFlag );
+ }
+
+ /* Check if incoming colors can be modified during rasterization */
+ if (ctx->Fog.Enabled ||
+ ctx->Texture.Enabled ||
+ ctx->Color.BlendEnabled ||
+ ctx->Color.SWmasking ||
+ ctx->Color.SWLogicOpEnabled) {
+ ctx->MutablePixels = GL_TRUE;
+ }
+ else {
+ ctx->MutablePixels = GL_FALSE;
+ }
+
+ /* update scissor region */
+
+ ctx->Buffer->Xmin = 0;
+ ctx->Buffer->Ymin = 0;
+ ctx->Buffer->Xmax = ctx->Buffer->Width-1;
+ ctx->Buffer->Ymax = ctx->Buffer->Height-1;
+ if (ctx->Scissor.Enabled) {
+ if (ctx->Scissor.X > ctx->Buffer->Xmin) {
+ ctx->Buffer->Xmin = ctx->Scissor.X;
+ }
+ if (ctx->Scissor.Y > ctx->Buffer->Ymin) {
+ ctx->Buffer->Ymin = ctx->Scissor.Y;
+ }
+ if (ctx->Scissor.X + ctx->Scissor.Width - 1 < ctx->Buffer->Xmax) {
+ ctx->Buffer->Xmax = ctx->Scissor.X + ctx->Scissor.Width - 1;
+ }
+ if (ctx->Scissor.Y + ctx->Scissor.Height - 1 < ctx->Buffer->Ymax) {
+ ctx->Buffer->Ymax = ctx->Scissor.Y + ctx->Scissor.Height - 1;
+ }
+ }
+
+ /*
+ * Update Device Driver interface
+ */
+ ctx->Driver.AllocDepthBuffer = gl_alloc_depth_buffer;
+ if (ctx->Depth.Mask) {
+ switch (ctx->Depth.Func) {
+ case GL_LESS:
+ ctx->Driver.DepthTestSpan = gl_depth_test_span_less;
+ ctx->Driver.DepthTestPixels = gl_depth_test_pixels_less;
+ break;
+ case GL_GREATER:
+ ctx->Driver.DepthTestSpan = gl_depth_test_span_greater;
+ ctx->Driver.DepthTestPixels = gl_depth_test_pixels_greater;
+ break;
+ default:
+ ctx->Driver.DepthTestSpan = gl_depth_test_span_generic;
+ ctx->Driver.DepthTestPixels = gl_depth_test_pixels_generic;
+ }
+ }
+ else {
+ ctx->Driver.DepthTestSpan = gl_depth_test_span_generic;
+ ctx->Driver.DepthTestPixels = gl_depth_test_pixels_generic;
+ }
+ ctx->Driver.ReadDepthSpanFloat = gl_read_depth_span_float;
+ ctx->Driver.ReadDepthSpanInt = gl_read_depth_span_int;
+ }
+
+ if (ctx->NewState & NEW_LIGHTING) {
+ ctx->TriangleCaps &= ~(DD_TRI_LIGHT_TWOSIDE|DD_EARLY_CULL);
+ if (ctx->Light.Enabled) {
+ if (ctx->Light.Model.TwoSide)
+ ctx->TriangleCaps |= (DD_TRI_LIGHT_TWOSIDE|DD_EARLY_CULL);
+ gl_update_lighting(ctx);
+ }
+ }
+ }
+
+ if (ctx->NewState & (NEW_POLYGON | NEW_LIGHTING)) {
+
+
+ if (ctx->NewState & NEW_POLYGON) {
+ /* Setup CullBits bitmask */
+ if (ctx->Polygon.CullFlag) {
+ switch(ctx->Polygon.CullFaceMode) {
+ case GL_FRONT:
+ ctx->Polygon.CullBits = 2;
+ break;
+ case GL_BACK:
+ ctx->Polygon.CullBits = 1;
+ break;
+ default:
+ case GL_FRONT_AND_BACK:
+ ctx->Polygon.CullBits = 3;
+ break;
+ }
+ }
+ else
+ ctx->Polygon.CullBits = 3;
+
+ /* Any Polygon offsets enabled? */
+ ctx->TriangleCaps &= ~DD_TRI_OFFSET;
+
+ if (ctx->Polygon.OffsetPoint ||
+ ctx->Polygon.OffsetLine ||
+ ctx->Polygon.OffsetFill)
+ ctx->TriangleCaps |= DD_TRI_OFFSET;
+
+ /* reset Z offsets now */
+ ctx->PointZoffset = 0.0;
+ ctx->LineZoffset = 0.0;
+ ctx->PolygonZoffset = 0.0;
+ }
+ }
+
+ if (ctx->NewState & ~(NEW_CLIENT_STATE|NEW_TEXTURE_ENABLE|
+ NEW_DRIVER_STATE|NEW_USER_CLIP|
+ NEW_POLYGON))
+ gl_update_clipmask(ctx);
+
+ if (ctx->NewState & (NEW_LIGHTING|
+ NEW_RASTER_OPS|
+ NEW_TEXTURING|
+ NEW_TEXTURE_ENV|
+ NEW_POLYGON|
+ NEW_DRVSTATE0|
+ NEW_DRVSTATE1|
+ NEW_DRVSTATE2|
+ NEW_DRVSTATE3|
+ NEW_USER_CLIP))
+ {
+ ctx->IndirectTriangles = ctx->TriangleCaps & ~ctx->Driver.TriangleCaps;
+ ctx->IndirectTriangles |= DD_SW_RASTERIZE;
+
+ ctx->Driver.PointsFunc = NULL;
+ ctx->Driver.LineFunc = NULL;
+ ctx->Driver.TriangleFunc = NULL;
+ ctx->Driver.QuadFunc = NULL;
+ ctx->Driver.RectFunc = NULL;
+ ctx->Driver.RenderVBClippedTab = NULL;
+ ctx->Driver.RenderVBCulledTab = NULL;
+ ctx->Driver.RenderVBRawTab = NULL;
+
+ /*
+ * Here the driver sets up all the ctx->Driver function pointers to
+ * it's specific, private functions.
+ */
+ ctx->Driver.UpdateState(ctx);
+
+ /*
+ * In case the driver didn't hook in an optimized point, line or
+ * triangle function we'll now select "core/fallback" point, line
+ * and triangle functions.
+ */
+ if (ctx->IndirectTriangles & DD_SW_RASTERIZE) {
+ gl_set_point_function(ctx);
+ gl_set_line_function(ctx);
+ gl_set_triangle_function(ctx);
+ gl_set_quad_function(ctx);
+ }
+
+ gl_set_render_vb_function(ctx);
+ }
+
+ /* Should only be calc'd when !need_eye_coords and not culling.
+ */
+ if (ctx->NewState & (NEW_MODELVIEW|NEW_PROJECTION)) {
+ if (ctx->NewState & NEW_MODELVIEW) {
+ gl_matrix_analyze( &ctx->ModelView );
+ ctx->ProjectionMatrix.flags &= ~MAT_DIRTY_DEPENDENTS;
+ }
+
+ if (ctx->NewState & NEW_PROJECTION) {
+ gl_matrix_analyze( &ctx->ProjectionMatrix );
+ ctx->ProjectionMatrix.flags &= ~MAT_DIRTY_DEPENDENTS;
+
+ if (ctx->Transform.AnyClip) {
+ gl_update_userclip( ctx );
+ }
+ }
+
+ gl_calculate_model_project_matrix( ctx );
+ ctx->ModelProjectWinMatrixUptodate = 0;
+ }
+
+ /* Figure out whether we can light in object space or not. If we
+ * can, find the current positions of the lights in object space
+ */
+ if ((ctx->Enabled & (ENABLE_POINT_ATTEN | ENABLE_LIGHT |
+ ENABLE_TEXGEN0 | ENABLE_TEXGEN1)) &&
+ (ctx->NewState & (NEW_LIGHTING |
+ NEW_MODELVIEW |
+ NEW_PROJECTION |
+ NEW_TEXTURING |
+ NEW_RASTER_OPS |
+ NEW_USER_CLIP)))
+ {
+ GLboolean oldcoord, oldnorm;
+
+ oldcoord = ctx->NeedEyeCoords;
+ oldnorm = ctx->NeedEyeNormals;
+
+ ctx->NeedNormals = (ctx->Light.Enabled || ctx->Texture.NeedNormals);
+ ctx->NeedEyeCoords = ((ctx->Fog.Enabled && ctx->Hint.Fog != GL_NICEST) ||
+ ctx->Point.Attenuated);
+ ctx->NeedEyeNormals = GL_FALSE;
+
+ if (ctx->Light.Enabled) {
+ if (ctx->Light.Flags & LIGHT_POSITIONAL) {
+ /* Need length for attenuation */
+ if (!TEST_MAT_FLAGS( &ctx->ModelView, MAT_FLAGS_LENGTH_PRESERVING))
+ ctx->NeedEyeCoords = GL_TRUE;
+ } else if (ctx->Light.NeedVertices) {
+ /* Need angle for spot calculations */
+ if (!TEST_MAT_FLAGS( &ctx->ModelView, MAT_FLAGS_ANGLE_PRESERVING))
+ ctx->NeedEyeCoords = GL_TRUE;
+ }
+ ctx->NeedEyeNormals = ctx->NeedEyeCoords;
+ }
+ if (ctx->Texture.Enabled || ctx->RenderMode==GL_FEEDBACK) {
+ if (ctx->Texture.NeedEyeCoords) ctx->NeedEyeCoords = GL_TRUE;
+ if (ctx->Texture.NeedNormals)
+ ctx->NeedNormals = ctx->NeedEyeNormals = GL_TRUE;
+ }
+
+ ctx->vb_proj_matrix = &ctx->ModelProjectMatrix;
+
+ if (ctx->NeedEyeCoords)
+ ctx->vb_proj_matrix = &ctx->ProjectionMatrix;
+
+ if (ctx->Light.Enabled) {
+ gl_update_lighting_function(ctx);
+
+ if ( (ctx->NewState & NEW_LIGHTING) ||
+ ((ctx->NewState & (NEW_MODELVIEW| NEW_PROJECTION)) &&
+ !ctx->NeedEyeCoords) ||
+ oldcoord != ctx->NeedEyeCoords ||
+ oldnorm != ctx->NeedEyeNormals) {
+ gl_compute_light_positions(ctx);
+ }
+
+ ctx->rescale_factor = 1.0F;
+
+ if (ctx->ModelView.flags & (MAT_FLAG_UNIFORM_SCALE |
+ MAT_FLAG_GENERAL_SCALE |
+ MAT_FLAG_GENERAL_3D |
+ MAT_FLAG_GENERAL) )
+
+ {
+ GLfloat *m = ctx->ModelView.inv;
+ GLfloat f = m[2]*m[2] + m[6]*m[6] + m[10]*m[10];
+ if (f > 1e-12 && (f-1)*(f-1) > 1e-12)
+ ctx->rescale_factor = 1.0/GL_SQRT(f);
+ }
+ }
+
+ gl_update_normal_transform( ctx );
+ }
+
+ finished:
+ gl_update_pipelines(ctx);
+ ctx->NewState = 0;
+}
diff --git a/src/mesa/main/context.h b/src/mesa/main/context.h
new file mode 100644
index 0000000000..f136da42b2
--- /dev/null
+++ b/src/mesa/main/context.h
@@ -0,0 +1,167 @@
+/* $Id: context.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef CONTEXT_H
+#define CONTEXT_H
+
+
+#include "types.h"
+
+
+
+#ifdef THREADS
+ /*
+ * A seperate GLcontext for each thread
+ */
+ extern GLcontext *gl_get_thread_context( void );
+#else
+ /*
+ * All threads use same pointer to current context.
+ */
+ extern GLcontext *CC;
+ extern struct immediate *CURRENT_INPUT;
+#endif
+
+
+
+/*
+ * There are three Mesa datatypes which are meant to be used by device
+ * drivers:
+ * GLcontext: this contains the Mesa rendering state
+ * GLvisual: this describes the color buffer (rgb vs. ci), whether
+ * or not there's a depth buffer, stencil buffer, etc.
+ * GLframebuffer: contains pointers to the depth buffer, stencil
+ * buffer, accum buffer and alpha buffers.
+ *
+ * These types should be encapsulated by corresponding device driver
+ * datatypes. See xmesa.h and xmesaP.h for an example.
+ *
+ * In OOP terms, GLcontext, GLvisual, and GLframebuffer are base classes
+ * which the device driver must derive from.
+ *
+ * The following functions create and destroy these datatypes.
+ */
+
+
+/*
+ * Create/destroy a GLvisual. A GLvisual is like a GLX visual. It describes
+ * the colorbuffer, depth buffer, stencil buffer and accum buffer which will
+ * be used by the GL context and framebuffer.
+ */
+extern GLvisual *gl_create_visual( GLboolean rgbFlag,
+ GLboolean alphaFlag,
+ GLboolean dbFlag,
+ GLboolean stereoFlag,
+ GLint depthBits,
+ GLint stencilBits,
+ GLint accumBits,
+ GLint indexBits,
+ GLint redBits,
+ GLint greenBits,
+ GLint blueBits,
+ GLint alphaBits );
+
+extern void gl_destroy_visual( GLvisual *vis );
+
+
+/*
+ * Create/destroy a GLcontext. A GLcontext is like a GLX context. It
+ * contains the rendering state.
+ */
+extern GLcontext *gl_create_context( GLvisual *visual,
+ GLcontext *share_list,
+ void *driver_ctx,
+ GLboolean direct);
+
+extern void gl_destroy_context( GLcontext *ctx );
+
+/* Called by the driver after both the context and driver are fully
+ * initialized. Currently just reads the config file.
+ */
+extern void gl_context_initialize( GLcontext *ctx );
+
+/*
+ * Create/destroy a GLframebuffer. A GLframebuffer is like a GLX drawable.
+ * It bundles up the depth buffer, stencil buffer and accum buffers into a
+ * single entity.
+ */
+extern GLframebuffer *gl_create_framebuffer( GLvisual *visual );
+
+extern void gl_destroy_framebuffer( GLframebuffer *buffer );
+
+
+
+extern void gl_make_current( GLcontext *ctx, GLframebuffer *buffer );
+
+extern GLcontext *gl_get_current_context(void);
+
+extern void gl_copy_context(const GLcontext *src, GLcontext *dst, GLuint mask);
+
+extern void gl_set_api_table( GLcontext *ctx, const struct gl_api_table *api );
+
+
+
+/*
+ * GL_MESA_resize_buffers extension
+ */
+extern void gl_ResizeBuffersMESA( GLcontext *ctx );
+
+
+
+/*
+ * Miscellaneous
+ */
+
+extern void gl_problem( const GLcontext *ctx, const char *s );
+
+extern void gl_warning( const GLcontext *ctx, const char *s );
+
+extern void gl_error( GLcontext *ctx, GLenum error, const char *s );
+extern void gl_compile_error( GLcontext *ctx, GLenum error, const char *s );
+
+extern GLenum gl_GetError( GLcontext *ctx );
+
+
+extern void gl_update_state( GLcontext *ctx );
+
+
+/* for debugging */
+extern void gl_print_state( const char *msg, GLuint state );
+
+/* for debugging */
+extern void gl_print_enable_flags( const char *msg, GLuint flags );
+
+
+#ifdef PROFILE
+extern GLdouble gl_time( void );
+#endif
+
+
+#endif
diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h
new file mode 100644
index 0000000000..479d73edd1
--- /dev/null
+++ b/src/mesa/main/dd.h
@@ -0,0 +1,635 @@
+/* $Id: dd.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+#ifndef DD_INCLUDED
+#define DD_INCLUDED
+
+
+#include "macros.h"
+
+
+struct gl_pixelstore_attrib;
+
+
+struct vertex_buffer;
+struct immediate;
+struct gl_pipeline_stage;
+
+
+/* THIS FILE ONLY INCLUDED BY types.h !!!!! */
+
+
+/*
+ * Device Driver (DD) interface
+ *
+ *
+ * All device driver functions are accessed through pointers in the
+ * dd_function_table struct (defined below) which is stored in the GLcontext
+ * struct. Since the device driver is strictly accessed trough a table of
+ * function pointers we can:
+ * 1. switch between a number of different device drivers at runtime.
+ * 2. use optimized functions dependant on current rendering state or
+ * frame buffer configuration.
+ *
+ * The function pointers in the dd_function_table struct are divided into
+ * two groups: mandatory and optional.
+ * Mandatory functions have to be implemented by every device driver.
+ * Optional functions may or may not be implemented by the device driver.
+ * The optional functions provide ways to take advantage of special hardware
+ * or optimized algorithms.
+ *
+ * The function pointers in the dd_function_table struct are first
+ * initialized in the "MakeCurrent" function. The "MakeCurrent" function
+ * is a little different in each device driver. See the X/Mesa, GLX, or
+ * OS/Mesa drivers for examples.
+ *
+ * Later, Mesa may call the dd_function_table's UpdateState() function.
+ * This function should initialize the dd_function_table's pointers again.
+ * The UpdateState() function is called whenever the core (GL) rendering
+ * state is changed in a way which may effect rasterization. For example,
+ * the TriangleFunc() pointer may have to point to different functions
+ * depending on whether smooth or flat shading is enabled.
+ *
+ * Note that the first argument to every device driver function is a
+ * GLcontext *. In turn, the GLcontext->DriverCtx pointer points to
+ * the driver-specific context struct. See the X/Mesa or OS/Mesa interface
+ * for an example.
+ *
+ * For more information about writing a device driver see the ddsample.c
+ * file and other device drivers (xmesa[123].c, osmesa.c, etc) for examples.
+ *
+ *
+ * Look below in the dd_function_table struct definition for descriptions
+ * of each device driver function.
+ *
+ *
+ * In the future more function pointers may be added for glReadPixels
+ * glCopyPixels, etc.
+ *
+ *
+ * Notes:
+ * ------
+ * RGBA = red/green/blue/alpha
+ * CI = color index (color mapped mode)
+ * mono = all pixels have the same color or index
+ *
+ * The write_ functions all take an array of mask flags which indicate
+ * whether or not the pixel should be written. One special case exists
+ * in the write_color_span function: if the mask array is NULL, then
+ * draw all pixels. This is an optimization used for glDrawPixels().
+ *
+ * IN ALL CASES:
+ * X coordinates start at 0 at the left and increase to the right
+ * Y coordinates start at 0 at the bottom and increase upward
+ *
+ */
+
+
+
+
+/* Used by the GetParameteri device driver function */
+#define DD_HAVE_HARDWARE_FOG 3
+
+
+
+
+
+/*
+ * Device Driver function table.
+ */
+struct dd_function_table {
+
+ /**********************************************************************
+ *** Mandatory functions: these functions must be implemented by ***
+ *** every device driver. ***
+ **********************************************************************/
+
+ const char * (*RendererString)(void);
+ /*
+ * Return a string which uniquely identifies this device driver.
+ * The string should contain no whitespace. Examples: "X11" "OffScreen"
+ * "MSWindows" "SVGA".
+ * NOTE: This function will be obsolete in favor of GetString in the future!
+ */
+
+ void (*UpdateState)( GLcontext *ctx );
+ /*
+ * UpdateState() is called whenver Mesa thinks the device driver should
+ * update its state and/or the other pointers (such as PointsFunc,
+ * LineFunc, or TriangleFunc).
+ */
+
+ void (*ClearIndex)( GLcontext *ctx, GLuint index );
+ /*
+ * Called whenever glClearIndex() is called. Set the index for clearing
+ * the color buffer.
+ */
+
+ void (*ClearColor)( GLcontext *ctx, GLubyte red, GLubyte green,
+ GLubyte blue, GLubyte alpha );
+ /*
+ * Called whenever glClearColor() is called. Set the color for clearing
+ * the color buffer.
+ */
+
+ GLbitfield (*Clear)( GLcontext *ctx, GLbitfield mask, GLboolean all,
+ GLint x, GLint y, GLint width, GLint height );
+ /* Clear the color/depth/stencil/accum buffer(s).
+ * 'mask' indicates which buffers need to be cleared. Return a bitmask
+ * indicating which buffers weren't cleared by the driver function.
+ * If 'all' is true then the clear the whole buffer, else clear the
+ * region defined by (x,y,width,height).
+ */
+
+ void (*Index)( GLcontext *ctx, GLuint index );
+ /*
+ * Sets current color index for drawing flat-shaded primitives.
+ */
+
+ void (*Color)( GLcontext *ctx,
+ GLubyte red, GLubyte green, GLubyte glue, GLubyte alpha );
+ /*
+ * Sets current color for drawing flat-shaded primitives.
+ */
+
+ GLboolean (*SetBuffer)( GLcontext *ctx, GLenum buffer );
+ /*
+ * Selects the color buffer(s) for reading and writing.
+ * The following values must be accepted when applicable:
+ * GL_FRONT_LEFT - this buffer always exists
+ * GL_BACK_LEFT - when double buffering
+ * GL_FRONT_RIGHT - when using stereo
+ * GL_BACK_RIGHT - when using stereo and double buffering
+ * The folowing values may optionally be accepted. Return GL_TRUE
+ * if accepted, GL_FALSE if not accepted. In practice, only drivers
+ * which can write to multiple color buffers at once should accept
+ * these values.
+ * GL_FRONT - write to front left and front right if it exists
+ * GL_BACK - write to back left and back right if it exists
+ * GL_LEFT - write to front left and back left if it exists
+ * GL_RIGHT - write to right left and back right if they exist
+ * GL_FRONT_AND_BACK - write to all four buffers if they exist
+ * GL_NONE - disable buffer write in device driver.
+ */
+
+ void (*GetBufferSize)( GLcontext *ctx,
+ GLuint *width, GLuint *height );
+ /*
+ * Returns the width and height of the current color buffer.
+ */
+
+
+ /***
+ *** Functions for writing pixels to the frame buffer:
+ ***/
+
+ void (*WriteRGBASpan)( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ CONST GLubyte rgba[][4], const GLubyte mask[] );
+ void (*WriteRGBSpan)( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ CONST GLubyte rgb[][3], const GLubyte mask[] );
+ /* Write a horizontal run of RGB[A] pixels. The later version is only
+ * used to accelerate GL_RGB, GL_UNSIGNED_BYTE glDrawPixels() calls.
+ */
+
+ void (*WriteMonoRGBASpan)( const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLubyte mask[] );
+ /* Write a horizontal run of mono-RGBA pixels.
+ */
+
+ void (*WriteRGBAPixels)( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ CONST GLubyte rgba[][4], const GLubyte mask[] );
+ /* Write array of RGBA pixels at random locations.
+ */
+
+ void (*WriteMonoRGBAPixels)( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte mask[] );
+ /* Write an array of mono-RGBA pixels at random locations.
+ */
+
+ void (*WriteCI32Span)( const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLuint index[], const GLubyte mask[] );
+ void (*WriteCI8Span)( const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLubyte index[], const GLubyte mask[] );
+ /* Write a horizontal run of CI pixels. 32 or 8bpp.
+ */
+
+ void (*WriteMonoCISpan)( const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLubyte mask[] );
+ /* Write a horizontal run of mono-CI pixels.
+ */
+
+ void (*WriteCI32Pixels)( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLuint index[], const GLubyte mask[] );
+ /*
+ * Write a random array of CI pixels.
+ */
+
+ void (*WriteMonoCIPixels)( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLubyte mask[] );
+ /*
+ * Write a random array of mono-CI pixels.
+ */
+
+
+ /***
+ *** Functions to read pixels from frame buffer:
+ ***/
+
+ void (*ReadCI32Span)( const GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLuint index[] );
+ /* Read a horizontal run of color index pixels.
+ */
+
+ void (*ReadRGBASpan)( const GLcontext *ctx, GLuint n, GLint x, GLint y,
+ GLubyte rgba[][4] );
+ /* Read a horizontal run of RGBA pixels.
+ */
+
+ void (*ReadCI32Pixels)( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLuint indx[], const GLubyte mask[] );
+ /* Read a random array of CI pixels.
+ */
+
+ void (*ReadRGBAPixels)( const GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte rgba[][4], const GLubyte mask[] );
+ /* Read a random array of RGBA pixels.
+ */
+
+
+ /**********************************************************************
+ *** Optional functions: these functions may or may not be ***
+ *** implemented by the device driver. If the device driver ***
+ *** doesn't implement them it should never touch these pointers ***
+ *** since Mesa will either set them to NULL or point them at a ***
+ *** fall-back function. ***
+ **********************************************************************/
+
+ const char * (*ExtensionString)( GLcontext *ctx );
+ /* Return a space-separated list of extensions for this driver.
+ * NOTE: This function will be obsolete in favor of GetString in the future!
+ */
+
+ const GLubyte * (*GetString)( GLcontext *ctx, GLenum name );
+ /* Return a string as needed by glGetString().
+ * NOTE: This will replace the ExtensionString and RendererString
+ * functions in the future!
+ */
+
+ void (*Finish)( GLcontext *ctx );
+ /*
+ * Called whenever glFinish() is called.
+ */
+
+ void (*Flush)( GLcontext *ctx );
+ /*
+ * Called whenever glFlush() is called.
+ */
+
+ GLboolean (*IndexMask)( GLcontext *ctx, GLuint mask );
+ /*
+ * Implements glIndexMask() if possible, else return GL_FALSE.
+ */
+
+ GLboolean (*ColorMask)( GLcontext *ctx,
+ GLboolean rmask, GLboolean gmask,
+ GLboolean bmask, GLboolean amask );
+ /*
+ * Implements glColorMask() if possible, else return GL_FALSE.
+ */
+
+ GLboolean (*LogicOp)( GLcontext *ctx, GLenum op );
+ /*
+ * Implements glLogicOp() if possible, else return GL_FALSE.
+ */
+
+ void (*Dither)( GLcontext *ctx, GLboolean enable );
+ /*
+ * Enable/disable dithering.
+ * NOTE: This function will be removed in the future in favor
+ * of the "Enable" driver function.
+ */
+
+ void (*Error)( GLcontext *ctx );
+ /*
+ * Called whenever an error is generated. ctx->ErrorValue contains
+ * the error value.
+ */
+
+ void (*NearFar)( GLcontext *ctx, GLfloat nearVal, GLfloat farVal );
+ /*
+ * Called from glFrustum and glOrtho to tell device driver the
+ * near and far clipping plane Z values. The 3Dfx driver, for example,
+ * uses this.
+ */
+
+ GLint (*GetParameteri)( const GLcontext *ctx, GLint param );
+ /* Query the device driver to get an integer parameter.
+ * Current parameters:
+ * DD_MAX_TEXTURE_SIZE return maximum texture size
+ *
+ * DD_MAX_TEXTURES number of texture sets/stages, usually 1
+ *
+ * DD_HAVE_HARDWARE_FOG the driver should return 1 (0 otherwise)
+ * when the hardware support per fragment
+ * fog for free (like the Voodoo Graphics)
+ * so the Mesa core will start to ever use
+ * per fragment fog
+ */
+
+
+ /***
+ *** For supporting hardware Z buffers:
+ ***/
+
+ void (*AllocDepthBuffer)( GLcontext *ctx );
+ /*
+ * Called when the depth buffer must be allocated or possibly resized.
+ */
+
+ GLuint (*DepthTestSpan)( GLcontext *ctx,
+ GLuint n, GLint x, GLint y, const GLdepth z[],
+ GLubyte mask[] );
+ void (*DepthTestPixels)( GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLdepth z[], GLubyte mask[] );
+ /*
+ * Apply the depth buffer test to an span/array of pixels and return
+ * an updated pixel mask. This function is not used when accelerated
+ * point, line, polygon functions are used.
+ */
+
+ void (*ReadDepthSpanFloat)( GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLfloat depth[]);
+ void (*ReadDepthSpanInt)( GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLdepth depth[] );
+ /*
+ * Return depth values as integers for glReadPixels.
+ * Floats should be returned in the range [0,1].
+ * Ints (GLdepth) values should be in the range [0,MAXDEPTH].
+ */
+
+
+ /***
+ *** Accelerated point, line, polygon, glDrawPixels and glBitmap functions:
+ ***/
+
+ points_func PointsFunc;
+ line_func LineFunc;
+ triangle_func TriangleFunc;
+ quad_func QuadFunc;
+ rect_func RectFunc;
+
+
+ GLboolean (*DrawPixels)( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLvoid *pixels );
+ /* Device driver hook for optimized glDrawPixels. 'unpack' describes how
+ * to unpack the source image data.
+ */
+
+ GLboolean (*Bitmap)( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ const struct gl_pixelstore_attrib *unpack,
+ const GLubyte *bitmap );
+ /* Device driver hook for optimized glBitmap. 'unpack' describes how
+ * to unpack the source image data.
+ */
+
+ void (*RenderStart)( GLcontext *ctx );
+ void (*RenderFinish)( GLcontext *ctx );
+ /* KW: These replace Begin and End, and have more relaxed semantics.
+ * They are called prior-to and after one or more vb flush, and are
+ * thus decoupled from the gl_begin/gl_end pairs, which are possibly
+ * more frequent. If a begin/end pair covers >1 vertex buffer, these
+ * are called at most once for the pair. (a bit broken at present)
+ */
+
+ void (*RasterSetup)( struct vertex_buffer *VB, GLuint start, GLuint end );
+ /* This function, if not NULL, is called whenever new window coordinates
+ * are put in the vertex buffer. The vertices in question are those n
+ * such that start <= n < end.
+ * The device driver can convert the window coords to its own specialized
+ * format. The 3Dfx driver uses this.
+ *
+ * Note: Deprecated in favour of RegisterPipelineStages, below.
+ */
+
+
+ render_func *RenderVBClippedTab;
+ render_func *RenderVBCulledTab;
+ render_func *RenderVBRawTab;
+ /* These function tables allow the device driver to rasterize an
+ * entire begin/end group of primitives at once. See the
+ * gl_render_vb() function in vbrender.c for more details.
+ */
+
+
+ GLuint TriangleCaps;
+ /* Holds a list of the reasons why we might normally want to call
+ * render_triangle, but which are in fact implemented by the
+ * driver. The FX driver sets this to DD_TRI_CULL, and will soon
+ * implement DD_TRI_OFFSET.
+ */
+
+
+ GLboolean (*MultipassFunc)( struct vertex_buffer *VB, GLuint passno );
+ /* Driver may request additional render passes by returning GL_TRUE
+ * when this function is called. This function will be called
+ * after the first pass, and passes will be made until the function
+ * returns GL_FALSE. If no function is registered, only one pass
+ * is made.
+ *
+ * This function will be first invoked with passno == 1.
+ */
+
+ /***
+ *** Texture mapping functions:
+ ***/
+
+ void (*TexEnv)( GLcontext *ctx, GLenum pname, const GLfloat *param );
+ /*
+ * Called whenever glTexEnv*() is called.
+ * Pname will be one of GL_TEXTURE_ENV_MODE or GL_TEXTURE_ENV_COLOR.
+ * If pname is GL_TEXTURE_ENV_MODE then param will be one
+ * of GL_MODULATE, GL_BLEND, GL_DECAL, or GL_REPLACE.
+ */
+
+ void (*TexImage)( GLcontext *ctx, GLenum target,
+ struct gl_texture_object *tObj, GLint level,
+ GLint internalFormat,
+ const struct gl_texture_image *image );
+ /*
+ * Called whenever a texture object's image is changed.
+ * texObject is the number of the texture object being changed.
+ * level indicates the mipmap level.
+ * internalFormat is the format in which the texture is to be stored.
+ * image is a pointer to a gl_texture_image struct which contains
+ * the actual image data.
+ */
+
+ void (*TexSubImage)( GLcontext *ctx, GLenum target,
+ struct gl_texture_object *tObj, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLint internalFormat,
+ const struct gl_texture_image *image );
+ /*
+ * Called from glTexSubImage() to define a sub-region of a texture.
+ */
+
+ void (*TexParameter)( GLcontext *ctx, GLenum target,
+ struct gl_texture_object *tObj,
+ GLenum pname, const GLfloat *params );
+ /*
+ * Called whenever glTexParameter*() is called.
+ * target is GL_TEXTURE_1D or GL_TEXTURE_2D
+ * texObject is the texture object to modify
+ * pname is one of GL_TEXTURE_MIN_FILTER, GL_TEXTURE_MAG_FILTER,
+ * GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T, or GL_TEXTURE_BORDER_COLOR.
+ * params is dependant on pname. See man glTexParameter.
+ */
+
+ void (*BindTexture)( GLcontext *ctx, GLenum target,
+ struct gl_texture_object *tObj );
+ /*
+ * Called whenever glBindTexture() is called. This specifies which
+ * texture is to be the current one. No dirty flags will be set.
+ */
+
+ void (*DeleteTexture)( GLcontext *ctx, struct gl_texture_object *tObj );
+ /*
+ * Called when a texture object is about to be deallocated. Driver
+ * should free anything attached to the DriverData pointers.
+ */
+
+ void (*UpdateTexturePalette)( GLcontext *ctx,
+ struct gl_texture_object *tObj );
+ /*
+ * Called when the texture's color lookup table is changed.
+ * If tObj is NULL then the shared texture palette ctx->Texture.Palette
+ * was changed.
+ */
+
+ void (*UseGlobalTexturePalette)( GLcontext *ctx, GLboolean state );
+ /*
+ * Called via glEnable/Disable(GL_SHARED_TEXTURE_PALETTE_EXT)
+ */
+
+ void (*ActiveTexture)( GLcontext *ctx, GLuint texUnitNumber );
+ /*
+ * Called by glActiveTextureARB to set current texture unit.
+ */
+
+
+ /***
+ *** NEW in Mesa 3.x
+ ***/
+
+ void (*RegisterVB)( struct vertex_buffer *VB );
+ void (*UnregisterVB)( struct vertex_buffer *VB );
+ /* Do any processing (eg allocate memory) required to set up a new
+ * vertex_buffer.
+ */
+
+
+ void (*ResetVB)( struct vertex_buffer *VB );
+ void (*ResetCvaVB)( struct vertex_buffer *VB, GLuint stages );
+ /* Do any reset operations necessary to the driver data associated
+ * with these vertex buffers.
+ */
+
+ GLuint RenderVectorFlags;
+ /* What do the render tables require of the vectors they deal
+ * with?
+ */
+
+ GLuint (*RegisterPipelineStages)( struct gl_pipeline_stage *out,
+ const struct gl_pipeline_stage *in,
+ GLuint nr );
+ /* Register new pipeline stages, or modify existing ones. See also
+ * the OptimizePipeline() functions.
+ */
+
+
+ GLboolean (*BuildPrecalcPipeline)( GLcontext *ctx );
+ GLboolean (*BuildEltPipeline)( GLcontext *ctx );
+ /* Perform the full pipeline build, or return false.
+ */
+
+
+ void (*OptimizePrecalcPipeline)( GLcontext *ctx, struct gl_pipeline *pipe );
+ void (*OptimizeImmediatePipeline)( GLcontext *ctx, struct gl_pipeline *pipe);
+ /* Check to see if a fast path exists for this combination of stages
+ * in the precalc and immediate (elt) pipelines.
+ */
+
+
+ /*
+ * State-changing functions (drawing functions are above)
+ *
+ * These functions are called by their corresponding OpenGL API functions.
+ * They're ALSO called by the gl_PopAttrib() function!!!
+ * May add more functions like these to the device driver in the future.
+ * This should reduce the amount of state checking that
+ * the driver's UpdateState() function must do.
+ */
+ void (*AlphaFunc)(GLcontext *ctx, GLenum func, GLclampf ref);
+ void (*BlendFunc)(GLcontext *ctx, GLenum sfactor, GLenum dfactor);
+ void (*ClearDepth)(GLcontext *ctx, GLclampd d);
+ void (*CullFace)(GLcontext *ctx, GLenum mode);
+ void (*FrontFace)(GLcontext *ctx, GLenum mode);
+ void (*DepthFunc)(GLcontext *ctx, GLenum func);
+ void (*DepthMask)(GLcontext *ctx, GLboolean flag);
+ void (*DepthRange)(GLcontext *ctx, GLclampd nearval, GLclampd farval);
+ void (*Enable)(GLcontext* ctx, GLenum cap, GLboolean state);
+ void (*Fogfv)(GLcontext *ctx, GLenum pname, const GLfloat *params);
+ void (*Hint)(GLcontext *ctx, GLenum target, GLenum mode);
+ void (*PolygonMode)(GLcontext *ctx, GLenum face, GLenum mode);
+ void (*Scissor)(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h);
+ void (*ShadeModel)(GLcontext *ctx, GLenum mode);
+ void (*ClearStencil)(GLcontext *ctx, GLint s);
+ void (*StencilFunc)(GLcontext *ctx, GLenum func, GLint ref, GLuint mask);
+ void (*StencilMask)(GLcontext *ctx, GLuint mask);
+ void (*StencilOp)(GLcontext *ctx, GLenum fail, GLenum zfail, GLenum zpass);
+ void (*Viewport)(GLcontext *ctx, GLint x, GLint y, GLsizei w, GLsizei h);
+};
+
+
+
+#endif
+
diff --git a/src/mesa/main/depth.c b/src/mesa/main/depth.c
new file mode 100644
index 0000000000..6d5a2be237
--- /dev/null
+++ b/src/mesa/main/depth.c
@@ -0,0 +1,879 @@
+/* $Id: depth.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+/*
+ * Depth buffer functions
+ */
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "context.h"
+#include "enums.h"
+#include "depth.h"
+#include "macros.h"
+#include "types.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+
+/**********************************************************************/
+/***** API Functions *****/
+/**********************************************************************/
+
+
+
+void gl_ClearDepth( GLcontext* ctx, GLclampd depth )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glClearDepth");
+ ctx->Depth.Clear = (GLfloat) CLAMP( depth, 0.0, 1.0 );
+ if (ctx->Driver.ClearDepth)
+ (*ctx->Driver.ClearDepth)( ctx, ctx->Depth.Clear );
+}
+
+
+
+void gl_DepthFunc( GLcontext* ctx, GLenum func )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDepthFunc");
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ fprintf(stderr, "glDepthFunc %s\n", gl_lookup_enum_by_nr(func));
+
+
+ switch (func) {
+ case GL_NEVER:
+ case GL_LESS: /* (default) pass if incoming z < stored z */
+ case GL_GEQUAL:
+ case GL_LEQUAL:
+ case GL_GREATER:
+ case GL_NOTEQUAL:
+ case GL_EQUAL:
+ case GL_ALWAYS:
+ if (ctx->Depth.Func != func) {
+ ctx->Depth.Func = func;
+ ctx->NewState |= NEW_RASTER_OPS;
+ if (ctx->Driver.DepthFunc) {
+ (*ctx->Driver.DepthFunc)( ctx, func );
+ }
+ }
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glDepth.Func" );
+ }
+}
+
+
+
+void gl_DepthMask( GLcontext* ctx, GLboolean flag )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDepthMask");
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ fprintf(stderr, "glDepthMask %d\n", flag);
+
+ /*
+ * GL_TRUE indicates depth buffer writing is enabled (default)
+ * GL_FALSE indicates depth buffer writing is disabled
+ */
+ if (ctx->Depth.Mask != flag) {
+ ctx->Depth.Mask = flag;
+ ctx->NewState |= NEW_RASTER_OPS;
+ if (ctx->Driver.DepthMask) {
+ (*ctx->Driver.DepthMask)( ctx, flag );
+ }
+ }
+}
+
+
+
+/**********************************************************************/
+/***** Depth Testing Functions *****/
+/**********************************************************************/
+
+
+/*
+ * Depth test horizontal spans of fragments. These functions are called
+ * via ctx->Driver.depth_test_span only.
+ *
+ * Input: n - number of pixels in the span
+ * x, y - location of leftmost pixel in span in window coords
+ * z - array [n] of integer depth values
+ * In/Out: mask - array [n] of flags (1=draw pixel, 0=don't draw)
+ * Return: number of pixels which passed depth test
+ */
+
+
+/*
+ * glDepthFunc( any ) and glDepthMask( GL_TRUE or GL_FALSE ).
+ */
+GLuint gl_depth_test_span_generic( GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLdepth z[],
+ GLubyte mask[] )
+{
+ GLdepth *zptr = Z_ADDRESS( ctx, x, y );
+ GLubyte *m = mask;
+ GLuint i;
+ GLuint passed = 0;
+
+ /* switch cases ordered from most frequent to less frequent */
+ switch (ctx->Depth.Func) {
+ case GL_LESS:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0; i<n; i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] < *zptr) {
+ /* pass */
+ *zptr = z[i];
+ passed++;
+ }
+ else {
+ /* fail */
+ *m = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ for (i=0; i<n; i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] < *zptr) {
+ /* pass */
+ passed++;
+ }
+ else {
+ *m = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_LEQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] <= *zptr) {
+ *zptr = z[i];
+ passed++;
+ }
+ else {
+ *m = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] <= *zptr) {
+ /* pass */
+ passed++;
+ }
+ else {
+ *m = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_GEQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] >= *zptr) {
+ *zptr = z[i];
+ passed++;
+ }
+ else {
+ *m = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] >= *zptr) {
+ /* pass */
+ passed++;
+ }
+ else {
+ *m = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_GREATER:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] > *zptr) {
+ *zptr = z[i];
+ passed++;
+ }
+ else {
+ *m = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] > *zptr) {
+ /* pass */
+ passed++;
+ }
+ else {
+ *m = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_NOTEQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] != *zptr) {
+ *zptr = z[i];
+ passed++;
+ }
+ else {
+ *m = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] != *zptr) {
+ /* pass */
+ passed++;
+ }
+ else {
+ *m = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_EQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] == *zptr) {
+ *zptr = z[i];
+ passed++;
+ }
+ else {
+ *m =0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ if (z[i] == *zptr) {
+ /* pass */
+ passed++;
+ }
+ else {
+ *m =0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_ALWAYS:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0;i<n;i++,zptr++,m++) {
+ if (*m) {
+ *zptr = z[i];
+ passed++;
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer or mask */
+ passed = n;
+ }
+ break;
+ case GL_NEVER:
+ for (i=0;i<n;i++) {
+ mask[i] = 0;
+ }
+ break;
+ default:
+ gl_problem(ctx, "Bad depth func in gl_depth_test_span_generic");
+ } /*switch*/
+
+ return passed;
+}
+
+
+
+/*
+ * glDepthFunc(GL_LESS) and glDepthMask(GL_TRUE).
+ */
+GLuint gl_depth_test_span_less( GLcontext* ctx,
+ GLuint n, GLint x, GLint y, const GLdepth z[],
+ GLubyte mask[] )
+{
+ GLdepth *zptr = Z_ADDRESS( ctx, x, y );
+ GLuint i;
+ GLuint passed = 0;
+
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ if (z[i] < zptr[i]) {
+ /* pass */
+ zptr[i] = z[i];
+ passed++;
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ return passed;
+}
+
+
+/*
+ * glDepthFunc(GL_GREATER) and glDepthMask(GL_TRUE).
+ */
+GLuint gl_depth_test_span_greater( GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ const GLdepth z[],
+ GLubyte mask[] )
+{
+ GLdepth *zptr = Z_ADDRESS( ctx, x, y );
+ GLuint i;
+ GLuint passed = 0;
+
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ if (z[i] > zptr[i]) {
+ /* pass */
+ zptr[i] = z[i];
+ passed++;
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ return passed;
+}
+
+
+
+/*
+ * Depth test an array of randomly positioned fragments.
+ */
+
+
+#define ZADDR_SETUP GLdepth *depthbuffer = ctx->Buffer->Depth; \
+ GLint width = ctx->Buffer->Width;
+
+#define ZADDR( X, Y ) (depthbuffer + (Y) * width + (X) )
+
+
+
+/*
+ * glDepthFunc( any ) and glDepthMask( GL_TRUE or GL_FALSE ).
+ */
+void gl_depth_test_pixels_generic( GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLdepth z[], GLubyte mask[] )
+{
+ register GLdepth *zptr;
+ register GLuint i;
+
+ /* switch cases ordered from most frequent to less frequent */
+ switch (ctx->Depth.Func) {
+ case GL_LESS:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ zptr = Z_ADDRESS(ctx,x[i],y[i]);
+ if (z[i] < *zptr) {
+ /* pass */
+ *zptr = z[i];
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ zptr = Z_ADDRESS(ctx,x[i],y[i]);
+ if (z[i] < *zptr) {
+ /* pass */
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_LEQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ zptr = Z_ADDRESS(ctx,x[i],y[i]);
+ if (z[i] <= *zptr) {
+ /* pass */
+ *zptr = z[i];
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ zptr = Z_ADDRESS(ctx,x[i],y[i]);
+ if (z[i] <= *zptr) {
+ /* pass */
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_GEQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ zptr = Z_ADDRESS(ctx,x[i],y[i]);
+ if (z[i] >= *zptr) {
+ /* pass */
+ *zptr = z[i];
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ zptr = Z_ADDRESS(ctx,x[i],y[i]);
+ if (z[i] >= *zptr) {
+ /* pass */
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_GREATER:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ zptr = Z_ADDRESS(ctx,x[i],y[i]);
+ if (z[i] > *zptr) {
+ /* pass */
+ *zptr = z[i];
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ zptr = Z_ADDRESS(ctx,x[i],y[i]);
+ if (z[i] > *zptr) {
+ /* pass */
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_NOTEQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ zptr = Z_ADDRESS(ctx,x[i],y[i]);
+ if (z[i] != *zptr) {
+ /* pass */
+ *zptr = z[i];
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ zptr = Z_ADDRESS(ctx,x[i],y[i]);
+ if (z[i] != *zptr) {
+ /* pass */
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_EQUAL:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ zptr = Z_ADDRESS(ctx,x[i],y[i]);
+ if (z[i] == *zptr) {
+ /* pass */
+ *zptr = z[i];
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ zptr = Z_ADDRESS(ctx,x[i],y[i]);
+ if (z[i] == *zptr) {
+ /* pass */
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+ }
+ break;
+ case GL_ALWAYS:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ zptr = Z_ADDRESS(ctx,x[i],y[i]);
+ *zptr = z[i];
+ }
+ }
+ }
+ else {
+ /* Don't update Z buffer or mask */
+ }
+ break;
+ case GL_NEVER:
+ /* depth test never passes */
+ for (i=0;i<n;i++) {
+ mask[i] = 0;
+ }
+ break;
+ default:
+ gl_problem(ctx, "Bad depth func in gl_depth_test_pixels_generic");
+ } /*switch*/
+}
+
+
+
+/*
+ * glDepthFunc( GL_LESS ) and glDepthMask( GL_TRUE ).
+ */
+void gl_depth_test_pixels_less( GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLdepth z[], GLubyte mask[] )
+{
+ GLdepth *zptr;
+ GLuint i;
+
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ zptr = Z_ADDRESS(ctx,x[i],y[i]);
+ if (z[i] < *zptr) {
+ /* pass */
+ *zptr = z[i];
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+}
+
+
+/*
+ * glDepthFunc( GL_GREATER ) and glDepthMask( GL_TRUE ).
+ */
+void gl_depth_test_pixels_greater( GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLdepth z[], GLubyte mask[] )
+{
+ GLdepth *zptr;
+ GLuint i;
+
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ zptr = Z_ADDRESS(ctx,x[i],y[i]);
+ if (z[i] > *zptr) {
+ /* pass */
+ *zptr = z[i];
+ }
+ else {
+ /* fail */
+ mask[i] = 0;
+ }
+ }
+ }
+}
+
+
+
+
+/**********************************************************************/
+/***** Read Depth Buffer *****/
+/**********************************************************************/
+
+
+/*
+ * Return a span of depth values from the depth buffer as floats in [0,1].
+ * This function is only called through Driver.read_depth_span_float()
+ * Input: n - how many pixels
+ * x,y - location of first pixel
+ * Output: depth - the array of depth values
+ */
+void gl_read_depth_span_float( GLcontext* ctx,
+ GLuint n, GLint x, GLint y, GLfloat depth[] )
+{
+ GLdepth *zptr;
+ GLfloat scale;
+ GLuint i;
+
+ scale = 1.0F / DEPTH_SCALE;
+
+ if (ctx->Buffer->Depth) {
+ zptr = Z_ADDRESS( ctx, x, y );
+ for (i=0;i<n;i++) {
+ depth[i] = (GLfloat) zptr[i] * scale;
+ }
+ }
+ else {
+ for (i=0;i<n;i++) {
+ depth[i] = 0.0F;
+ }
+ }
+}
+
+
+/*
+ * Return a span of depth values from the depth buffer as integers in
+ * [0,MAX_DEPTH].
+ * This function is only called through Driver.read_depth_span_int()
+ * Input: n - how many pixels
+ * x,y - location of first pixel
+ * Output: depth - the array of depth values
+ */
+void gl_read_depth_span_int( GLcontext* ctx,
+ GLuint n, GLint x, GLint y, GLdepth depth[] )
+{
+ if (ctx->Buffer->Depth) {
+ GLdepth *zptr = Z_ADDRESS( ctx, x, y );
+ MEMCPY( depth, zptr, n * sizeof(GLdepth) );
+ }
+ else {
+ GLuint i;
+ for (i=0;i<n;i++) {
+ depth[i] = 0;
+ }
+ }
+}
+
+
+
+/**********************************************************************/
+/***** Allocate and Clear Depth Buffer *****/
+/**********************************************************************/
+
+
+
+/*
+ * Allocate a new depth buffer. If there's already a depth buffer allocated
+ * it will be free()'d. The new depth buffer will be uniniitalized.
+ * This function is only called through Driver.alloc_depth_buffer.
+ */
+void gl_alloc_depth_buffer( GLcontext* ctx )
+{
+ /* deallocate current depth buffer if present */
+ if (ctx->Buffer->Depth) {
+ free(ctx->Buffer->Depth);
+ ctx->Buffer->Depth = NULL;
+ }
+
+ /* allocate new depth buffer, but don't initialize it */
+ ctx->Buffer->Depth = (GLdepth *) malloc( ctx->Buffer->Width
+ * ctx->Buffer->Height
+ * sizeof(GLdepth) );
+ if (!ctx->Buffer->Depth) {
+ /* out of memory */
+ ctx->Depth.Test = GL_FALSE;
+ gl_error( ctx, GL_OUT_OF_MEMORY, "Couldn't allocate depth buffer" );
+ }
+}
+
+
+
+
+/*
+ * Clear the depth buffer. If the depth buffer doesn't exist yet we'll
+ * allocate it now.
+ * This function is only called through Driver.clear_depth_buffer.
+ */
+void gl_clear_depth_buffer( GLcontext* ctx )
+{
+ GLdepth clear_value = (GLdepth) (ctx->Depth.Clear * DEPTH_SCALE);
+
+ if (ctx->Visual->DepthBits==0 || !ctx->Buffer->Depth || !ctx->Depth.Mask) {
+ /* no depth buffer, or writing to it is disabled */
+ return;
+ }
+
+ /* The loops in this function have been written so the IRIX 5.3
+ * C compiler can unroll them. Hopefully other compilers can too!
+ */
+
+ if (ctx->Scissor.Enabled) {
+ /* only clear scissor region */
+ GLint y;
+ for (y=ctx->Buffer->Ymin; y<=ctx->Buffer->Ymax; y++) {
+ GLdepth *d = Z_ADDRESS( ctx, ctx->Buffer->Xmin, y );
+ GLint n = ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1;
+ do {
+ *d++ = clear_value;
+ n--;
+ } while (n);
+ }
+ }
+ else {
+ /* clear whole buffer */
+ if (sizeof(GLdepth)==2 && (clear_value&0xff)==(clear_value>>8)) {
+ /* lower and upper bytes of clear_value are same, use MEMSET */
+ MEMSET( ctx->Buffer->Depth, clear_value&0xff,
+ 2*ctx->Buffer->Width*ctx->Buffer->Height);
+ }
+ else {
+ GLdepth *d = ctx->Buffer->Depth;
+ GLint n = ctx->Buffer->Width * ctx->Buffer->Height;
+ while (n>=16) {
+ d[0] = clear_value; d[1] = clear_value;
+ d[2] = clear_value; d[3] = clear_value;
+ d[4] = clear_value; d[5] = clear_value;
+ d[6] = clear_value; d[7] = clear_value;
+ d[8] = clear_value; d[9] = clear_value;
+ d[10] = clear_value; d[11] = clear_value;
+ d[12] = clear_value; d[13] = clear_value;
+ d[14] = clear_value; d[15] = clear_value;
+ d += 16;
+ n -= 16;
+ }
+ while (n>0) {
+ *d++ = clear_value;
+ n--;
+ }
+ }
+ }
+}
+
+
+
diff --git a/src/mesa/main/depth.h b/src/mesa/main/depth.h
new file mode 100644
index 0000000000..559afc64fb
--- /dev/null
+++ b/src/mesa/main/depth.h
@@ -0,0 +1,98 @@
+/* $Id: depth.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef DEPTH_H
+#define DEPTH_H
+
+
+#include "types.h"
+
+
+/*
+ * Return the address of the Z-buffer value for window coordinate (x,y):
+ */
+#define Z_ADDRESS( CTX, X, Y ) \
+ ((CTX)->Buffer->Depth + (CTX)->Buffer->Width * (Y) + (X))
+
+
+
+
+extern GLuint
+gl_depth_test_span_generic( GLcontext* ctx, GLuint n, GLint x, GLint y,
+ const GLdepth z[], GLubyte mask[] );
+
+extern GLuint
+gl_depth_test_span_less( GLcontext* ctx, GLuint n, GLint x, GLint y,
+ const GLdepth z[], GLubyte mask[] );
+
+extern GLuint
+gl_depth_test_span_greater( GLcontext* ctx, GLuint n, GLint x, GLint y,
+ const GLdepth z[], GLubyte mask[] );
+
+
+
+extern void
+gl_depth_test_pixels_generic( GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLdepth z[], GLubyte mask[] );
+
+extern void
+gl_depth_test_pixels_less( GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLdepth z[], GLubyte mask[] );
+
+extern void
+gl_depth_test_pixels_greater( GLcontext* ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLdepth z[], GLubyte mask[] );
+
+
+extern void gl_read_depth_span_float( GLcontext* ctx,
+ GLuint n, GLint x, GLint y,
+ GLfloat depth[] );
+
+
+extern void gl_read_depth_span_int( GLcontext* ctx, GLuint n, GLint x, GLint y,
+ GLdepth depth[] );
+
+
+extern void gl_alloc_depth_buffer( GLcontext* ctx );
+
+
+extern void gl_clear_depth_buffer( GLcontext* ctx );
+
+
+extern void gl_ClearDepth( GLcontext* ctx, GLclampd depth );
+
+extern void gl_DepthFunc( GLcontext* ctx, GLenum func );
+
+extern void gl_DepthMask( GLcontext* ctx, GLboolean flag );
+
+#endif
diff --git a/src/mesa/main/descrip.mms b/src/mesa/main/descrip.mms
new file mode 100644
index 0000000000..d6ab05799d
--- /dev/null
+++ b/src/mesa/main/descrip.mms
@@ -0,0 +1,156 @@
+# Makefile for core library for VMS
+# contributed by Jouk Jansen joukj@crys.chem.uva.nl
+# Last revision : 3 May 1999
+
+.first
+ define gl [-.include.gl]
+
+.include [-]mms-config.
+
+##### MACROS #####
+
+VPATH = RCS
+
+INCDIR = [-.include]
+LIBDIR = [-.lib]
+CFLAGS = /include=($(INCDIR),[])/define=(FBIND=1)
+
+CORE_SOURCES = accum.c alpha.c alphabuf.c api1.c api2.c apiext.c attrib.c \
+bitmap.c blend.c clip.c colortab.c context.c copypix.c depth.c \
+dlist.c drawpix.c enable.c eval.c feedback.c fog.c \
+get.c hash.c image.c light.c lines.c logic.c masking.c matrix.c \
+misc.c mmath.c mthreads.c pb.c pixel.c points.c pointers.c polygon.c \
+quads.c rastpos.c readpix.c rect.c scissor.c shade.c span.c \
+stencil.c teximage.c texobj.c texstate.c texture.c translate.c triangle.c \
+varray.c winpos.c vb.c vbcull.c vbfill.c vbrender.c vbxform.c xform.c \
+zoom.c bbox.c cva.c vector.c vbindirect.c config.c enums.c extensions.c \
+pipeline.c [.x86]x86.c
+
+DRIVER_SOURCES = [.x]glxapi.c [.x]fakeglx.c [.x]realglx.c [.x]xfonts.c \
+[.x]xmesa1.c [.x]xmesa2.c [.x]xmesa3.c [.x]xmesa4.c \
+[.osmesa]osmesa.c \
+[.svga]svgamesa.c \
+[.fx]fxapi.c [.fx]fxdd.c [.fx]fxddtex.c [.fx]fxvsetup.c [.fx]fxsetup.c \
+[.fx]fxtrifuncs.c \
+[.fx]fxrender.c [.fx]fxtexman.c [.fx]fxddspan.c [.fx]fxcva.c
+
+ASM_SOURCES =
+
+OBJECTS =\
+accum.obj,alpha.obj,alphabuf.obj,api1.obj,api2.obj,apiext.obj,attrib.obj,\
+bitmap.obj,blend.obj,clip.obj,colortab.obj,context.obj,copypix.obj,depth.obj,\
+dlist.obj,drawpix.obj,enable.obj,eval.obj,feedback.obj,fog.obj
+
+
+OBJECTS3=get.obj,hash.obj,image.obj,light.obj,lines.obj,logic.obj,masking.obj,matrix.obj,\
+misc.obj,mmath.obj,mthreads.obj,pb.obj,pixel.obj,points.obj,pointers.obj,polygon.obj,\
+quads.obj,rastpos.obj,readpix.obj,rect.obj,scissor.obj,shade.obj,span.obj
+
+
+OBJECTS4=stencil.obj,teximage.obj,texobj.obj,texstate.obj,texture.obj,translate.obj,\
+triangle.obj,varray.obj,winpos.obj,vb.obj,vbcull.obj,vbfill.obj,vbrender.obj
+
+OBJECTS6=vbxform.obj,xform.obj,zoom.obj,bbox.obj,cva.obj,vector.obj,vbindirect.obj,\
+ config.obj,enums.obj,extensions.obj,pipeline.obj,[.x86]x86.obj
+
+OBJECTS2=[.x]glxapi.obj,[.x]fakeglx.obj,[.x]realglx.obj,[.x]xfonts.obj,\
+[.x]xmesa1.obj,[.x]xmesa2.obj,[.x]xmesa3.obj,[.x]xmesa4.obj,\
+[.osmesa]osmesa.obj,\
+[.svga]svgamesa.obj
+
+OBJECTS5=[.fx]fxapi.obj,[.fx]fxdd.obj,[.fx]fxddtex.obj,[.fx]fxvsetup.obj,\
+[.fx]fxsetup.obj,\
+[.fx]fxtrifuncs.obj,\
+[.fx]fxrender.obj,[.fx]fxtexman.obj,[.fx]fxddspan.obj,[.fx]fxcva.obj
+
+##### RULES #####
+
+VERSION=Mesa V3.1
+
+##### TARGETS #####
+# Make the library
+$(LIBDIR)$(GL_LIB) : $(OBJECTS),$(OBJECTS2) $(OBJECTS3) $(OBJECTS4)\
+ $(OBJECTS5) $(OBJECTS6)
+.ifdef SHARE
+ @ WRITE_ SYS$OUTPUT " generating mesagl1.opt"
+ @ OPEN_/WRITE FILE mesagl1.opt
+ @ WRITE_ FILE "!"
+ @ WRITE_ FILE "! mesagl1.opt generated by DESCRIP.$(MMS_EXT)"
+ @ WRITE_ FILE "!"
+ @ WRITE_ FILE "IDENTIFICATION=""$(VERSION)"""
+ @ WRITE_ FILE "GSMATCH=LEQUAL,3,1
+ @ WRITE_ FILE "$(OBJECTS)"
+ @ WRITE_ FILE "$(OBJECTS3)"
+ @ WRITE_ FILE "$(OBJECTS4)"
+ @ WRITE_ FILE "$(OBJECTS6)"
+ @ WRITE_ FILE "$(OBJECTS2)"
+ @ WRITE_ FILE "$(OBJECTS5)"
+ @ WRITE_ FILE "SYS$SHARE:DECW$XEXTLIBSHR/SHARE"
+ @ WRITE_ FILE "SYS$SHARE:DECW$XLIBSHR/SHARE"
+ @ CLOSE_ FILE
+ @ WRITE_ SYS$OUTPUT " generating mesagl.map ..."
+ @ LINK_/NODEB/NOSHARE/NOEXE/MAP=mesagl.map/FULL mesagl1.opt/OPT
+ @ WRITE_ SYS$OUTPUT " analyzing mesagl.map ..."
+ @ @[-.vms]ANALYZE_MAP.COM mesagl.map mesagl.opt
+ @ WRITE_ SYS$OUTPUT " linking $(GL_LIB) ..."
+ @ LINK_/NODEB/SHARE=$(GL_LIB)/MAP=mesagl.map/FULL mesagl1.opt/opt,mesagl.opt/opt
+.else
+ @ $(MAKELIB) $(GL_LIB) $(OBJECTS)
+ @ library $(GL_LIB) $(OBJECTS2)
+ @ library $(GL_LIB) $(OBJECTS3)
+ @ library $(GL_LIB) $(OBJECTS4)
+ @ library $(GL_LIB) $(OBJECTS5)
+ @ library $(GL_LIB) $(OBJECTS6)
+.endif
+ @ rename $(GL_LIB)* $(LIBDIR)
+
+clean :
+ purge
+ delete *.obj;*
+
+triangle.obj : triangle.c
+
+[.x86]x86.obj : [.x86]x86.c
+ $(CC) $(CFLAGS) /obj=[.x86]x86.obj [.x86]x86.c
+[.x]glxapi.obj : [.x]glxapi.c
+ $(CC) $(CFLAGS) /obj=[.x]glxapi.obj [.x]glxapi.c
+[.x]fakeglx.obj : [.x]fakeglx.c
+ $(CC) $(CFLAGS) /obj=[.x]fakeglx.obj [.x]fakeglx.c
+[.x]realglx.obj : [.x]realglx.c
+ $(CC) $(CFLAGS) /obj=[.x]realglx.obj [.x]realglx.c
+[.x]xfonts.obj : [.x]xfonts.c
+ $(CC) $(CFLAGS) /obj=[.x]xfonts.obj [.x]xfonts.c
+[.x]xmesa1.obj : [.x]xmesa1.c
+ $(CC) $(CFLAGS) /obj=[.x]xmesa1.obj [.x]xmesa1.c
+[.x]xmesa2.obj : [.x]xmesa2.c
+ $(CC) $(CFLAGS) /obj=[.x]xmesa2.obj [.x]xmesa2.c
+[.x]xmesa3.obj : [.x]xmesa3.c
+ $(CC) $(CFLAGS) /obj=[.x]xmesa3.obj [.x]xmesa3.c
+[.x]xmesa4.obj : [.x]xmesa4.c
+ $(CC) $(CFLAGS) /obj=[.x]xmesa4.obj [.x]xmesa4.c
+[.osmesa]osmesa.obj : [.osmesa]osmesa.c
+ $(CC) $(CFLAGS) /obj=[.osmesa]osmesa.obj [.osmesa]osmesa.c
+[.svga]svgamesa.obj : [.svga]svgamesa.c
+ $(CC) $(CFLAGS) /obj=[.svga]svgamesa.obj [.svga]svgamesa.c
+[.fx]fxapi.obj : [.fx]fxapi.c
+ $(CC) $(CFLAGS) /obj=[.fx]fxapi.obj [.fx]fxapi.c
+[.fx]fxcva.obj : [.fx]fxcva.c
+ $(CC) $(CFLAGS) /obj=[.fx]fxcva.obj [.fx]fxcva.c
+[.fx]fxdd.obj : [.fx]fxdd.c
+ $(CC) $(CFLAGS) /obj=[.fx]fxdd.obj [.fx]fxdd.c
+[.fx]fxddtex.obj : [.fx]fxddtex.c
+ $(CC) $(CFLAGS) /obj=[.fx]fxddtex.obj [.fx]fxddtex.c
+[.fx]fxvsetup.obj : [.fx]fxvsetup.c
+ $(CC) $(CFLAGS) /obj=[.fx]fxvsetup.obj [.fx]fxvsetup.c
+[.fx]fxsetup.obj : [.fx]fxsetup.c
+ $(CC) $(CFLAGS) /obj=[.fx]fxsetup.obj [.fx]fxsetup.c
+[.fx]fxtrifuncs.obj : [.fx]fxtrifuncs.c
+ $(CC) $(CFLAGS) /obj=[.fx]fxtrifuncs.obj [.fx]fxtrifuncs.c
+[.fx]fxrender.obj : [.fx]fxrender.c
+ $(CC) $(CFLAGS) /obj=[.fx]fxrender.obj [.fx]fxrender.c
+[.fx]fxtexman.obj : [.fx]fxtexman.c
+ $(CC) $(CFLAGS) /obj=[.fx]fxtexman.obj [.fx]fxtexman.c
+[.fx]fxddspan.obj : [.fx]fxddspan.c
+ $(CC) $(CFLAGS) /obj=[.fx]fxddspan.obj [.fx]fxddspan.c
+
+.include mms_depend.
diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c
new file mode 100644
index 0000000000..001de0367b
--- /dev/null
+++ b/src/mesa/main/dlist.c
@@ -0,0 +1,3501 @@
+/* $Id: dlist.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "accum.h"
+#include "api.h"
+#include "alpha.h"
+#include "attrib.h"
+#include "bitmap.h"
+#include "bbox.h"
+#include "blend.h"
+#include "clip.h"
+#include "colortab.h"
+#include "context.h"
+#include "copypix.h"
+#include "depth.h"
+#include "drawpix.h"
+#include "enable.h"
+#include "enums.h"
+#include "eval.h"
+#include "feedback.h"
+#include "fog.h"
+#include "get.h"
+#include "hash.h"
+#include "image.h"
+#include "light.h"
+#include "lines.h"
+#include "dlist.h"
+#include "logic.h"
+#include "macros.h"
+#include "masking.h"
+#include "matrix.h"
+#include "misc.h"
+#include "pipeline.h"
+#include "pixel.h"
+#include "points.h"
+#include "polygon.h"
+#include "rastpos.h"
+#include "readpix.h"
+#include "rect.h"
+#include "scissor.h"
+#include "stencil.h"
+#include "texobj.h"
+#include "teximage.h"
+#include "texstate.h"
+#include "types.h"
+#include "varray.h"
+#include "vb.h"
+#include "vbfill.h"
+#include "vbxform.h"
+#include "winpos.h"
+#include "xform.h"
+#ifdef XFree86Server
+#undef MISC_H
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+
+/*
+Functions which aren't compiled but executed immediately:
+ glIsList
+ glGenLists
+ glDeleteLists
+ glEndList
+ glFeedbackBuffer
+ glSelectBuffer
+ glRenderMode
+ glReadPixels
+ glPixelStore
+ glFlush
+ glFinish
+ glIsEnabled
+ glGet*
+
+Functions which cause errors if called while compiling a display list:
+ glNewList
+*/
+
+
+
+/*
+ * Display list instructions are stored as sequences of "nodes". Nodes
+ * are allocated in blocks. Each block has BLOCK_SIZE nodes. Blocks
+ * are linked together with a pointer.
+ */
+
+
+/* How many nodes to allocate at a time:
+ * - reduced now that we hold vertices etc. elsewhere.
+ */
+#define BLOCK_SIZE 64
+
+
+/*
+ * Display list opcodes.
+ *
+ * The fact that these identifiers are assigned consecutive
+ * integer values starting at 0 is very important, see InstSize array usage)
+ *
+ * KW: Commented out opcodes now handled by vertex-cassettes.
+ */
+typedef enum {
+ OPCODE_ACCUM,
+ OPCODE_ALPHA_FUNC,
+ OPCODE_BIND_TEXTURE,
+ OPCODE_BITMAP,
+ OPCODE_BLEND_COLOR,
+ OPCODE_BLEND_EQUATION,
+ OPCODE_BLEND_FUNC,
+ OPCODE_BLEND_FUNC_SEPARATE,
+ OPCODE_CALL_LIST,
+ OPCODE_CALL_LIST_OFFSET,
+ OPCODE_CLEAR,
+ OPCODE_CLEAR_ACCUM,
+ OPCODE_CLEAR_COLOR,
+ OPCODE_CLEAR_DEPTH,
+ OPCODE_CLEAR_INDEX,
+ OPCODE_CLEAR_STENCIL,
+ OPCODE_CLIP_PLANE,
+ OPCODE_COLOR_MASK,
+ OPCODE_COLOR_MATERIAL,
+ OPCODE_COLOR_TABLE,
+ OPCODE_COLOR_SUB_TABLE,
+ OPCODE_COPY_PIXELS,
+ OPCODE_COPY_TEX_IMAGE1D,
+ OPCODE_COPY_TEX_IMAGE2D,
+ OPCODE_COPY_TEX_IMAGE3D,
+ OPCODE_COPY_TEX_SUB_IMAGE1D,
+ OPCODE_COPY_TEX_SUB_IMAGE2D,
+ OPCODE_COPY_TEX_SUB_IMAGE3D,
+ OPCODE_CULL_FACE,
+ OPCODE_DEPTH_FUNC,
+ OPCODE_DEPTH_MASK,
+ OPCODE_DEPTH_RANGE,
+ OPCODE_DISABLE,
+ OPCODE_DRAW_BUFFER,
+ OPCODE_DRAW_PIXELS,
+ OPCODE_ENABLE,
+ OPCODE_EVALCOORD1,
+ OPCODE_EVALCOORD2,
+ OPCODE_EVALMESH1,
+ OPCODE_EVALMESH2,
+ OPCODE_EVALPOINT1,
+ OPCODE_EVALPOINT2,
+ OPCODE_FOG,
+ OPCODE_FRONT_FACE,
+ OPCODE_FRUSTUM,
+ OPCODE_HINT,
+ OPCODE_INDEX_MASK,
+ OPCODE_INIT_NAMES,
+ OPCODE_LIGHT,
+ OPCODE_LIGHT_MODEL,
+ OPCODE_LINE_STIPPLE,
+ OPCODE_LINE_WIDTH,
+ OPCODE_LIST_BASE,
+ OPCODE_LOAD_IDENTITY,
+ OPCODE_LOAD_MATRIX,
+ OPCODE_LOAD_NAME,
+ OPCODE_LOGIC_OP,
+ OPCODE_MAP1,
+ OPCODE_MAP2,
+ OPCODE_MAPGRID1,
+ OPCODE_MAPGRID2,
+ OPCODE_MATRIX_MODE,
+ OPCODE_MULT_MATRIX,
+ OPCODE_ORTHO,
+ OPCODE_PASSTHROUGH,
+ OPCODE_PIXEL_MAP,
+ OPCODE_PIXEL_TRANSFER,
+ OPCODE_PIXEL_ZOOM,
+ OPCODE_POINT_SIZE,
+ OPCODE_POINT_PARAMETERS,
+ OPCODE_POLYGON_MODE,
+ OPCODE_POLYGON_STIPPLE,
+ OPCODE_POLYGON_OFFSET,
+ OPCODE_POP_ATTRIB,
+ OPCODE_POP_MATRIX,
+ OPCODE_POP_NAME,
+ OPCODE_PRIORITIZE_TEXTURE,
+ OPCODE_PUSH_ATTRIB,
+ OPCODE_PUSH_MATRIX,
+ OPCODE_PUSH_NAME,
+ OPCODE_RASTER_POS,
+ OPCODE_RECTF,
+ OPCODE_READ_BUFFER,
+ OPCODE_SCALE,
+ OPCODE_SCISSOR,
+ OPCODE_SELECT_TEXTURE_SGIS,
+ OPCODE_SELECT_TEXTURE_COORD_SET,
+ OPCODE_SHADE_MODEL,
+ OPCODE_STENCIL_FUNC,
+ OPCODE_STENCIL_MASK,
+ OPCODE_STENCIL_OP,
+ OPCODE_TEXENV,
+ OPCODE_TEXGEN,
+ OPCODE_TEXPARAMETER,
+ OPCODE_TEX_IMAGE1D,
+ OPCODE_TEX_IMAGE2D,
+ OPCODE_TEX_IMAGE3D,
+ OPCODE_TEX_SUB_IMAGE1D,
+ OPCODE_TEX_SUB_IMAGE2D,
+ OPCODE_TEX_SUB_IMAGE3D,
+ OPCODE_TRANSLATE,
+ OPCODE_VIEWPORT,
+ OPCODE_WINDOW_POS,
+ /* GL_ARB_multitexture */
+ OPCODE_ACTIVE_TEXTURE,
+ OPCODE_CLIENT_ACTIVE_TEXTURE,
+ /* The following three are meta instructions */
+ OPCODE_ERROR, /* raise compiled-in error */
+ OPCODE_VERTEX_CASSETTE, /* render prebuilt vertex buffer */
+ OPCODE_CONTINUE,
+ OPCODE_END_OF_LIST
+} OpCode;
+
+
+/*
+ * Each instruction in the display list is stored as a sequence of
+ * contiguous nodes in memory.
+ * Each node is the union of a variety of datatypes.
+ */
+union node {
+ OpCode opcode;
+ GLboolean b;
+ GLbitfield bf;
+ GLubyte ub;
+ GLshort s;
+ GLushort us;
+ GLint i;
+ GLuint ui;
+ GLenum e;
+ GLfloat f;
+ GLvoid *data;
+ void *next; /* If prev node's opcode==OPCODE_CONTINUE */
+};
+
+
+
+/* Number of nodes of storage needed for each instruction: */
+static GLuint InstSize[ OPCODE_END_OF_LIST+1 ];
+
+
+
+/**********************************************************************/
+/***** Private *****/
+/**********************************************************************/
+
+
+/*
+ * Allocate space for a display list instruction.
+ * Input: opcode - type of instruction
+ * argcount - number of arguments following the instruction
+ * Return: pointer to first node in the instruction
+ */
+static Node *alloc_instruction( GLcontext *ctx, OpCode opcode, GLint argcount )
+{
+ Node *n, *newblock;
+ GLuint count = InstSize[opcode];
+
+ assert( (GLint) count == argcount+1 );
+
+ if (ctx->CurrentPos + count + 2 > BLOCK_SIZE) {
+ /* This block is full. Allocate a new block and chain to it */
+ n = ctx->CurrentBlock + ctx->CurrentPos;
+ n[0].opcode = OPCODE_CONTINUE;
+ newblock = (Node *) malloc( sizeof(Node) * BLOCK_SIZE );
+ if (!newblock) {
+ gl_error( ctx, GL_OUT_OF_MEMORY, "Building display list" );
+ return NULL;
+ }
+ n[1].next = (Node *) newblock;
+ ctx->CurrentBlock = newblock;
+ ctx->CurrentPos = 0;
+ }
+
+ n = ctx->CurrentBlock + ctx->CurrentPos;
+ ctx->CurrentPos += count;
+
+ n[0].opcode = opcode;
+
+ return n;
+}
+
+
+
+/*
+ * Make an empty display list. This is used by glGenLists() to
+ * reserver display list IDs.
+ */
+static Node *make_empty_list( void )
+{
+ Node *n = (Node *) malloc( sizeof(Node) );
+ n[0].opcode = OPCODE_END_OF_LIST;
+ return n;
+}
+
+
+
+/*
+ * Destroy all nodes in a display list.
+ * Input: list - display list number
+ */
+void gl_destroy_list( GLcontext *ctx, GLuint list )
+{
+ Node *n, *block;
+ GLboolean done;
+
+ if (list==0)
+ return;
+
+ block = (Node *) HashLookup(ctx->Shared->DisplayList, list);
+ n = block;
+
+ done = block ? GL_FALSE : GL_TRUE;
+ while (!done) {
+ switch (n[0].opcode) {
+ /* special cases first */
+ case OPCODE_VERTEX_CASSETTE:
+ if ( ! -- ((struct immediate *) n[1].data)->ref_count )
+ gl_immediate_free( (struct immediate *) n[1].data );
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_MAP1:
+ gl_free_control_points( ctx, n[1].e, (GLfloat *) n[6].data );
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_MAP2:
+ gl_free_control_points( ctx, n[1].e, (GLfloat *) n[10].data );
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_DRAW_PIXELS:
+ gl_free_image( (struct gl_image *) n[1].data );
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_BITMAP:
+ gl_free_image( (struct gl_image *) n[7].data );
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_COLOR_TABLE:
+ gl_free_image( (struct gl_image *) n[3].data );
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_COLOR_SUB_TABLE:
+ gl_free_image( (struct gl_image *) n[3].data );
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_POLYGON_STIPPLE:
+ free( n[1].data );
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_TEX_IMAGE1D:
+ gl_free_image( (struct gl_image *) n[8].data );
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_TEX_IMAGE2D:
+ gl_free_image( (struct gl_image *) n[9].data );
+ n += InstSize[n[0].opcode];
+ break;
+ case OPCODE_TEX_SUB_IMAGE1D:
+ {
+ struct gl_image *image;
+ image = (struct gl_image *) n[7].data;
+ gl_free_image( image );
+ }
+ break;
+ case OPCODE_TEX_SUB_IMAGE2D:
+ {
+ struct gl_image *image;
+ image = (struct gl_image *) n[9].data;
+ gl_free_image( image );
+ }
+ break;
+ case OPCODE_CONTINUE:
+ n = (Node *) n[1].next;
+ free( block );
+ block = n;
+ break;
+ case OPCODE_END_OF_LIST:
+ free( block );
+ done = GL_TRUE;
+ break;
+ default:
+ /* Most frequent case */
+ n += InstSize[n[0].opcode];
+ break;
+ }
+ }
+
+ HashRemove(ctx->Shared->DisplayList, list);
+}
+
+
+
+/*
+ * Translate the nth element of list from type to GLuint.
+ */
+static GLuint translate_id( GLsizei n, GLenum type, const GLvoid *list )
+{
+ GLbyte *bptr;
+ GLubyte *ubptr;
+ GLshort *sptr;
+ GLushort *usptr;
+ GLint *iptr;
+ GLuint *uiptr;
+ GLfloat *fptr;
+
+ switch (type) {
+ case GL_BYTE:
+ bptr = (GLbyte *) list;
+ return (GLuint) *(bptr+n);
+ case GL_UNSIGNED_BYTE:
+ ubptr = (GLubyte *) list;
+ return (GLuint) *(ubptr+n);
+ case GL_SHORT:
+ sptr = (GLshort *) list;
+ return (GLuint) *(sptr+n);
+ case GL_UNSIGNED_SHORT:
+ usptr = (GLushort *) list;
+ return (GLuint) *(usptr+n);
+ case GL_INT:
+ iptr = (GLint *) list;
+ return (GLuint) *(iptr+n);
+ case GL_UNSIGNED_INT:
+ uiptr = (GLuint *) list;
+ return (GLuint) *(uiptr+n);
+ case GL_FLOAT:
+ fptr = (GLfloat *) list;
+ return (GLuint) *(fptr+n);
+ case GL_2_BYTES:
+ ubptr = ((GLubyte *) list) + 2*n;
+ return (GLuint) *ubptr * 256 + (GLuint) *(ubptr+1);
+ case GL_3_BYTES:
+ ubptr = ((GLubyte *) list) + 3*n;
+ return (GLuint) *ubptr * 65536
+ + (GLuint) *(ubptr+1) * 256
+ + (GLuint) *(ubptr+2);
+ case GL_4_BYTES:
+ ubptr = ((GLubyte *) list) + 4*n;
+ return (GLuint) *ubptr * 16777216
+ + (GLuint) *(ubptr+1) * 65536
+ + (GLuint) *(ubptr+2) * 256
+ + (GLuint) *(ubptr+3);
+ default:
+ return 0;
+ }
+}
+
+
+
+
+/**********************************************************************/
+/***** Public *****/
+/**********************************************************************/
+
+void gl_init_lists( void )
+{
+ static int init_flag = 0;
+
+ if (init_flag==0) {
+ InstSize[OPCODE_ACCUM] = 3;
+ InstSize[OPCODE_ALPHA_FUNC] = 3;
+ InstSize[OPCODE_BIND_TEXTURE] = 3;
+ InstSize[OPCODE_BITMAP] = 8;
+ InstSize[OPCODE_BLEND_COLOR] = 5;
+ InstSize[OPCODE_BLEND_EQUATION] = 2;
+ InstSize[OPCODE_BLEND_FUNC] = 3;
+ InstSize[OPCODE_BLEND_FUNC_SEPARATE] = 5;
+ InstSize[OPCODE_CALL_LIST] = 2;
+ InstSize[OPCODE_CALL_LIST_OFFSET] = 2;
+ InstSize[OPCODE_CLEAR] = 2;
+ InstSize[OPCODE_CLEAR_ACCUM] = 5;
+ InstSize[OPCODE_CLEAR_COLOR] = 5;
+ InstSize[OPCODE_CLEAR_DEPTH] = 2;
+ InstSize[OPCODE_CLEAR_INDEX] = 2;
+ InstSize[OPCODE_CLEAR_STENCIL] = 2;
+ InstSize[OPCODE_CLIP_PLANE] = 6;
+ InstSize[OPCODE_COLOR_MASK] = 5;
+ InstSize[OPCODE_COLOR_MATERIAL] = 3;
+ InstSize[OPCODE_COLOR_TABLE] = 4;
+ InstSize[OPCODE_COLOR_SUB_TABLE] = 4;
+ InstSize[OPCODE_COPY_PIXELS] = 6;
+ InstSize[OPCODE_COPY_TEX_IMAGE1D] = 8;
+ InstSize[OPCODE_COPY_TEX_IMAGE2D] = 9;
+ InstSize[OPCODE_COPY_TEX_SUB_IMAGE1D] = 7;
+ InstSize[OPCODE_COPY_TEX_SUB_IMAGE2D] = 9;
+ InstSize[OPCODE_COPY_TEX_SUB_IMAGE3D] = 10;
+ InstSize[OPCODE_CULL_FACE] = 2;
+ InstSize[OPCODE_DEPTH_FUNC] = 2;
+ InstSize[OPCODE_DEPTH_MASK] = 2;
+ InstSize[OPCODE_DEPTH_RANGE] = 3;
+ InstSize[OPCODE_DISABLE] = 2;
+ InstSize[OPCODE_DRAW_BUFFER] = 2;
+ InstSize[OPCODE_DRAW_PIXELS] = 2;
+ InstSize[OPCODE_ENABLE] = 2;
+ InstSize[OPCODE_EVALCOORD1] = 2;
+ InstSize[OPCODE_EVALCOORD2] = 3;
+ InstSize[OPCODE_EVALMESH1] = 4;
+ InstSize[OPCODE_EVALMESH2] = 6;
+ InstSize[OPCODE_EVALPOINT1] = 2;
+ InstSize[OPCODE_EVALPOINT2] = 3;
+ InstSize[OPCODE_FOG] = 6;
+ InstSize[OPCODE_FRONT_FACE] = 2;
+ InstSize[OPCODE_FRUSTUM] = 7;
+ InstSize[OPCODE_HINT] = 3;
+ InstSize[OPCODE_INDEX_MASK] = 2;
+ InstSize[OPCODE_INIT_NAMES] = 1;
+ InstSize[OPCODE_LIGHT] = 7;
+ InstSize[OPCODE_LIGHT_MODEL] = 6;
+ InstSize[OPCODE_LINE_STIPPLE] = 3;
+ InstSize[OPCODE_LINE_WIDTH] = 2;
+ InstSize[OPCODE_LIST_BASE] = 2;
+ InstSize[OPCODE_LOAD_IDENTITY] = 1;
+ InstSize[OPCODE_LOAD_MATRIX] = 17;
+ InstSize[OPCODE_LOAD_NAME] = 2;
+ InstSize[OPCODE_LOGIC_OP] = 2;
+ InstSize[OPCODE_MAP1] = 7;
+ InstSize[OPCODE_MAP2] = 11;
+ InstSize[OPCODE_MAPGRID1] = 4;
+ InstSize[OPCODE_MAPGRID2] = 7;
+ InstSize[OPCODE_MATRIX_MODE] = 2;
+ InstSize[OPCODE_MULT_MATRIX] = 17;
+ InstSize[OPCODE_ORTHO] = 7;
+ InstSize[OPCODE_PASSTHROUGH] = 2;
+ InstSize[OPCODE_PIXEL_MAP] = 4;
+ InstSize[OPCODE_PIXEL_TRANSFER] = 3;
+ InstSize[OPCODE_PIXEL_ZOOM] = 3;
+ InstSize[OPCODE_POINT_SIZE] = 2;
+ InstSize[OPCODE_POINT_PARAMETERS] = 5;
+ InstSize[OPCODE_POLYGON_MODE] = 3;
+ InstSize[OPCODE_POLYGON_STIPPLE] = 2;
+ InstSize[OPCODE_POLYGON_OFFSET] = 3;
+ InstSize[OPCODE_POP_ATTRIB] = 1;
+ InstSize[OPCODE_POP_MATRIX] = 1;
+ InstSize[OPCODE_POP_NAME] = 1;
+ InstSize[OPCODE_PRIORITIZE_TEXTURE] = 3;
+ InstSize[OPCODE_PUSH_ATTRIB] = 2;
+ InstSize[OPCODE_PUSH_MATRIX] = 1;
+ InstSize[OPCODE_PUSH_NAME] = 2;
+ InstSize[OPCODE_RASTER_POS] = 5;
+ InstSize[OPCODE_RECTF] = 5;
+ InstSize[OPCODE_READ_BUFFER] = 2;
+ InstSize[OPCODE_SCALE] = 4;
+ InstSize[OPCODE_SCISSOR] = 5;
+ InstSize[OPCODE_STENCIL_FUNC] = 4;
+ InstSize[OPCODE_STENCIL_MASK] = 2;
+ InstSize[OPCODE_STENCIL_OP] = 4;
+ InstSize[OPCODE_SHADE_MODEL] = 2;
+ InstSize[OPCODE_TEXENV] = 7;
+ InstSize[OPCODE_TEXGEN] = 7;
+ InstSize[OPCODE_TEXPARAMETER] = 7;
+ InstSize[OPCODE_TEX_IMAGE1D] = 9;
+ InstSize[OPCODE_TEX_IMAGE2D] = 10;
+ InstSize[OPCODE_TEX_IMAGE3D] = 11;
+ InstSize[OPCODE_TEX_SUB_IMAGE1D] = 8;
+ InstSize[OPCODE_TEX_SUB_IMAGE2D] = 10;
+ InstSize[OPCODE_TEX_SUB_IMAGE3D] = 12;
+ InstSize[OPCODE_TRANSLATE] = 4;
+ InstSize[OPCODE_VIEWPORT] = 5;
+ InstSize[OPCODE_WINDOW_POS] = 5;
+ InstSize[OPCODE_CONTINUE] = 2;
+ InstSize[OPCODE_ERROR] = 3;
+ InstSize[OPCODE_VERTEX_CASSETTE] = 2;
+ InstSize[OPCODE_END_OF_LIST] = 1;
+ /* GL_ARB_multitexture */
+ InstSize[OPCODE_ACTIVE_TEXTURE] = 2;
+ InstSize[OPCODE_CLIENT_ACTIVE_TEXTURE] = 2;
+ }
+ init_flag = 1;
+}
+
+
+/*
+ * Display List compilation functions
+ */
+
+
+
+static void save_Accum( GLcontext *ctx, GLenum op, GLfloat value )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_ACCUM, 2 );
+ if (n) {
+ n[1].e = op;
+ n[2].f = value;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.Accum)( ctx, op, value );
+ }
+}
+
+
+static void save_AlphaFunc( GLcontext *ctx, GLenum func, GLclampf ref )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_ALPHA_FUNC, 2 );
+ if (n) {
+ n[1].e = func;
+ n[2].f = (GLfloat) ref;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.AlphaFunc)( ctx, func, ref );
+ }
+}
+
+static void save_BindTexture( GLcontext *ctx, GLenum target, GLuint texture )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_BIND_TEXTURE, 2 );
+ if (n) {
+ n[1].e = target;
+ n[2].ui = texture;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.BindTexture)( ctx, target, texture );
+ }
+}
+
+
+static void save_Bitmap( GLcontext *ctx,
+ GLsizei width, GLsizei height,
+ GLfloat xorig, GLfloat yorig,
+ GLfloat xmove, GLfloat ymove,
+ const GLubyte *bitmap,
+ const struct gl_pixelstore_attrib *packing )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_BITMAP, 7 );
+ if (n) {
+ struct gl_image *image = gl_unpack_bitmap( ctx, width, height,
+ bitmap, packing );
+ if (image) {
+ image->RefCount = 1;
+ }
+ n[1].i = (GLint) width;
+ n[2].i = (GLint) height;
+ n[3].f = xorig;
+ n[4].f = yorig;
+ n[5].f = xmove;
+ n[6].f = ymove;
+ n[7].data = (void *) image;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.Bitmap)( ctx, width, height,
+ xorig, yorig, xmove, ymove, bitmap, packing );
+ }
+}
+
+
+static void save_BlendEquation( GLcontext *ctx, GLenum mode )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_BLEND_EQUATION, 1 );
+ if (n) {
+ n[1].e = mode;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.BlendEquation)( ctx, mode );
+ }
+}
+
+
+static void save_BlendFunc( GLcontext *ctx, GLenum sfactor, GLenum dfactor )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_BLEND_FUNC, 2 );
+ if (n) {
+ n[1].e = sfactor;
+ n[2].e = dfactor;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.BlendFunc)( ctx, sfactor, dfactor );
+ }
+}
+
+
+static void save_BlendFuncSeparate( GLcontext *ctx,
+ GLenum sfactorRGB, GLenum dfactorRGB,
+ GLenum sfactorA, GLenum dfactorA)
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_BLEND_FUNC_SEPARATE, 4 );
+ if (n) {
+ n[1].e = sfactorRGB;
+ n[2].e = dfactorRGB;
+ n[3].e = sfactorA;
+ n[4].e = dfactorA;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.BlendFuncSeparate)( ctx, sfactorRGB, dfactorRGB,
+ sfactorA, dfactorA);
+ }
+}
+
+
+static void save_BlendColor( GLcontext *ctx, GLfloat red, GLfloat green,
+ GLfloat blue, GLfloat alpha )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_BLEND_COLOR, 4 );
+ if (n) {
+ n[1].f = red;
+ n[2].f = green;
+ n[3].f = blue;
+ n[4].f = alpha;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.BlendColor)( ctx, red, green, blue, alpha );
+ }
+}
+
+
+static void save_CallList( GLcontext *ctx, GLuint list )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_CALL_LIST, 1 );
+ if (n) {
+ n[1].ui = list;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.CallList)( ctx, list );
+ }
+}
+
+
+static void save_CallLists( GLcontext *ctx,
+ GLsizei n, GLenum type, const GLvoid *lists )
+{
+ GLint i;
+ FLUSH_VB(ctx, "dlist");
+
+ for (i=0;i<n;i++) {
+ GLuint list = translate_id( i, type, lists );
+ Node *n = alloc_instruction( ctx, OPCODE_CALL_LIST_OFFSET, 1 );
+ if (n) {
+ n[1].ui = list;
+ }
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.CallLists)( ctx, n, type, lists );
+ }
+}
+
+
+static void save_Clear( GLcontext *ctx, GLbitfield mask )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_CLEAR, 1 );
+ if (n) {
+ n[1].bf = mask;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.Clear)( ctx, mask );
+ }
+}
+
+
+static void save_ClearAccum( GLcontext *ctx, GLfloat red, GLfloat green,
+ GLfloat blue, GLfloat alpha )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_CLEAR_ACCUM, 4 );
+ if (n) {
+ n[1].f = red;
+ n[2].f = green;
+ n[3].f = blue;
+ n[4].f = alpha;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.ClearAccum)( ctx, red, green, blue, alpha );
+ }
+}
+
+
+static void save_ClearColor( GLcontext *ctx, GLclampf red, GLclampf green,
+ GLclampf blue, GLclampf alpha )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_CLEAR_COLOR, 4 );
+ if (n) {
+ n[1].f = red;
+ n[2].f = green;
+ n[3].f = blue;
+ n[4].f = alpha;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.ClearColor)( ctx, red, green, blue, alpha );
+ }
+}
+
+
+static void save_ClearDepth( GLcontext *ctx, GLclampd depth )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_CLEAR_DEPTH, 1 );
+ if (n) {
+ n[1].f = (GLfloat) depth;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.ClearDepth)( ctx, depth );
+ }
+}
+
+
+static void save_ClearIndex( GLcontext *ctx, GLfloat c )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_CLEAR_INDEX, 1 );
+ if (n) {
+ n[1].f = c;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.ClearIndex)( ctx, c );
+ }
+}
+
+
+static void save_ClearStencil( GLcontext *ctx, GLint s )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_CLEAR_STENCIL, 1 );
+ if (n) {
+ n[1].i = s;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.ClearStencil)( ctx, s );
+ }
+}
+
+
+static void save_ClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *equ )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_CLIP_PLANE, 5 );
+ if (n) {
+ n[1].e = plane;
+ n[2].f = equ[0];
+ n[3].f = equ[1];
+ n[4].f = equ[2];
+ n[5].f = equ[3];
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.ClipPlane)( ctx, plane, equ );
+ }
+}
+
+
+
+static void save_ColorMask( GLcontext *ctx, GLboolean red, GLboolean green,
+ GLboolean blue, GLboolean alpha )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_COLOR_MASK, 4 );
+ if (n) {
+ n[1].b = red;
+ n[2].b = green;
+ n[3].b = blue;
+ n[4].b = alpha;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.ColorMask)( ctx, red, green, blue, alpha );
+ }
+}
+
+
+static void save_ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_COLOR_MATERIAL, 2 );
+ if (n) {
+ n[1].e = face;
+ n[2].e = mode;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.ColorMaterial)( ctx, face, mode );
+ }
+}
+
+
+static void save_ColorTable( GLcontext *ctx, GLenum target, GLenum internalFormat,
+ struct gl_image *table )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_COLOR_TABLE, 3 );
+ if (n) {
+ n[1].e = target;
+ n[2].e = internalFormat;
+ n[3].data = (GLvoid *) table;
+ if (table) {
+ /* must retain this image */
+ table->RefCount = 1;
+ }
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.ColorTable)( ctx, target, internalFormat, table );
+ }
+}
+
+
+static void save_ColorSubTable( GLcontext *ctx, GLenum target,
+ GLsizei start, struct gl_image *data )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_COLOR_SUB_TABLE, 3 );
+ if (n) {
+ n[1].e = target;
+ n[2].i = start;
+ n[3].data = (GLvoid *) data;
+ if (data) {
+ /* must retain this image */
+ data->RefCount = 1;
+ }
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.ColorSubTable)( ctx, target, start, data );
+ }
+}
+
+
+
+static void save_CopyPixels( GLcontext *ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height, GLenum type )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_COPY_PIXELS, 5 );
+ if (n) {
+ n[1].i = x;
+ n[2].i = y;
+ n[3].i = (GLint) width;
+ n[4].i = (GLint) height;
+ n[5].e = type;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.CopyPixels)( ctx, x, y, width, height, type );
+ }
+}
+
+
+
+static void save_CopyTexImage1D( GLcontext *ctx,
+ GLenum target, GLint level,
+ GLenum internalformat,
+ GLint x, GLint y, GLsizei width,
+ GLint border )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_COPY_TEX_IMAGE1D, 7 );
+ if (n) {
+ n[1].e = target;
+ n[2].i = level;
+ n[3].e = internalformat;
+ n[4].i = x;
+ n[5].i = y;
+ n[6].i = width;
+ n[7].i = border;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.CopyTexImage1D)( ctx, target, level, internalformat,
+ x, y, width, border );
+ }
+}
+
+
+static void save_CopyTexImage2D( GLcontext *ctx,
+ GLenum target, GLint level,
+ GLenum internalformat,
+ GLint x, GLint y, GLsizei width,
+ GLsizei height, GLint border )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_COPY_TEX_IMAGE2D, 8 );
+ if (n) {
+ n[1].e = target;
+ n[2].i = level;
+ n[3].e = internalformat;
+ n[4].i = x;
+ n[5].i = y;
+ n[6].i = width;
+ n[7].i = height;
+ n[8].i = border;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.CopyTexImage2D)( ctx, target, level, internalformat,
+ x, y, width, height, border );
+ }
+}
+
+
+
+static void save_CopyTexSubImage1D( GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint x, GLint y,
+ GLsizei width )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_COPY_TEX_SUB_IMAGE1D, 6 );
+ if (n) {
+ n[1].e = target;
+ n[2].i = level;
+ n[3].i = xoffset;
+ n[4].i = x;
+ n[5].i = y;
+ n[6].i = width;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.CopyTexSubImage1D)( ctx, target, level, xoffset, x, y, width );
+ }
+}
+
+
+static void save_CopyTexSubImage2D( GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLint x, GLint y,
+ GLsizei width, GLint height )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_COPY_TEX_SUB_IMAGE2D, 8 );
+ if (n) {
+ n[1].e = target;
+ n[2].i = level;
+ n[3].i = xoffset;
+ n[4].i = yoffset;
+ n[5].i = x;
+ n[6].i = y;
+ n[7].i = width;
+ n[8].i = height;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.CopyTexSubImage2D)( ctx, target, level, xoffset, yoffset,
+ x, y, width, height );
+ }
+}
+
+
+static void save_CopyTexSubImage3DEXT( GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLint x, GLint y,
+ GLsizei width, GLint height )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_COPY_TEX_SUB_IMAGE3D, 9 );
+ if (n) {
+ n[1].e = target;
+ n[2].i = level;
+ n[3].i = xoffset;
+ n[4].i = yoffset;
+ n[5].i = zoffset;
+ n[6].i = x;
+ n[7].i = y;
+ n[8].i = width;
+ n[9].i = height;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.CopyTexSubImage3DEXT)( ctx, target, level, xoffset, yoffset, zoffset,
+ x, y, width, height );
+ }
+}
+
+
+static void save_CullFace( GLcontext *ctx, GLenum mode )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_CULL_FACE, 1 );
+ if (n) {
+ n[1].e = mode;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.CullFace)( ctx, mode );
+ }
+}
+
+
+static void save_DepthFunc( GLcontext *ctx, GLenum func )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_DEPTH_FUNC, 1 );
+ if (n) {
+ n[1].e = func;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.DepthFunc)( ctx, func );
+ }
+}
+
+
+static void save_DepthMask( GLcontext *ctx, GLboolean mask )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_DEPTH_MASK, 1 );
+ if (n) {
+ n[1].b = mask;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.DepthMask)( ctx, mask );
+ }
+}
+
+
+static void save_DepthRange( GLcontext *ctx, GLclampd nearval, GLclampd farval )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_DEPTH_RANGE, 2 );
+ if (n) {
+ n[1].f = (GLfloat) nearval;
+ n[2].f = (GLfloat) farval;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.DepthRange)( ctx, nearval, farval );
+ }
+}
+
+
+static void save_Disable( GLcontext *ctx, GLenum cap )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_DISABLE, 1 );
+ if (n) {
+ n[1].e = cap;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.Disable)( ctx, cap );
+ }
+}
+
+
+static void save_DrawBuffer( GLcontext *ctx, GLenum mode )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_DRAW_BUFFER, 1 );
+ if (n) {
+ n[1].e = mode;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.DrawBuffer)( ctx, mode );
+ }
+}
+
+
+static void save_DrawPixels( GLcontext *ctx, struct gl_image *image )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_DRAW_PIXELS, 1 );
+ if (n) {
+ n[1].data = (GLvoid *) image;
+ }
+ if (image) {
+ image->RefCount = 1;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.DrawPixels)( ctx, image );
+ }
+}
+
+
+
+static void save_Enable( GLcontext *ctx, GLenum cap )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_ENABLE, 1 );
+ if (n) {
+ n[1].e = cap;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.Enable)( ctx, cap );
+ }
+}
+
+
+
+static void save_EvalMesh1( GLcontext *ctx,
+ GLenum mode, GLint i1, GLint i2 )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_EVALMESH1, 3 );
+ if (n) {
+ n[1].e = mode;
+ n[2].i = i1;
+ n[3].i = i2;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.EvalMesh1)( ctx, mode, i1, i2 );
+ }
+}
+
+
+static void save_EvalMesh2( GLcontext *ctx,
+ GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2 )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_EVALMESH2, 5 );
+ if (n) {
+ n[1].e = mode;
+ n[2].i = i1;
+ n[3].i = i2;
+ n[4].i = j1;
+ n[5].i = j2;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.EvalMesh2)( ctx, mode, i1, i2, j1, j2 );
+ }
+}
+
+
+
+
+static void save_Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *params )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_FOG, 5 );
+ if (n) {
+ n[1].e = pname;
+ n[2].f = params[0];
+ n[3].f = params[1];
+ n[4].f = params[2];
+ n[5].f = params[3];
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.Fogfv)( ctx, pname, params );
+ }
+}
+
+
+static void save_FrontFace( GLcontext *ctx, GLenum mode )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_FRONT_FACE, 1 );
+ if (n) {
+ n[1].e = mode;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.FrontFace)( ctx, mode );
+ }
+}
+
+
+static void save_Frustum( GLcontext *ctx, GLdouble left, GLdouble right,
+ GLdouble bottom, GLdouble top,
+ GLdouble nearval, GLdouble farval )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_FRUSTUM, 6 );
+ if (n) {
+ n[1].f = left;
+ n[2].f = right;
+ n[3].f = bottom;
+ n[4].f = top;
+ n[5].f = nearval;
+ n[6].f = farval;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.Frustum)( ctx, left, right, bottom, top, nearval, farval );
+ }
+}
+
+
+static GLboolean save_Hint( GLcontext *ctx, GLenum target, GLenum mode )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_HINT, 2 );
+ if (n) {
+ n[1].e = target;
+ n[2].e = mode;
+ }
+ if (ctx->ExecuteFlag) {
+ return (*ctx->Exec.Hint)( ctx, target, mode );
+ }
+ return GL_TRUE; /* not queried */
+}
+
+
+
+static void save_IndexMask( GLcontext *ctx, GLuint mask )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_INDEX_MASK, 1 );
+ if (n) {
+ n[1].ui = mask;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.IndexMask)( ctx, mask );
+ }
+}
+
+
+static void save_InitNames( GLcontext *ctx )
+{
+ FLUSH_VB(ctx, "dlist");
+ (void) alloc_instruction( ctx, OPCODE_INIT_NAMES, 0 );
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.InitNames)( ctx );
+ }
+}
+
+
+static void save_Lightfv( GLcontext *ctx, GLenum light, GLenum pname,
+ const GLfloat *params, GLint numparams )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_LIGHT, 6 );
+ if (OPCODE_LIGHT) {
+ GLint i;
+ n[1].e = light;
+ n[2].e = pname;
+ for (i=0;i<numparams;i++) {
+ n[3+i].f = params[i];
+ }
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.Lightfv)( ctx, light, pname, params, numparams );
+ }
+}
+
+
+static void save_LightModelfv( GLcontext *ctx,
+ GLenum pname, const GLfloat *params )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_LIGHT_MODEL, 5 );
+ if (n) {
+ n[1].e = pname;
+ n[2].f = params[0];
+ n[3].f = params[1];
+ n[4].f = params[2];
+ n[5].f = params[3];
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.LightModelfv)( ctx, pname, params );
+ }
+}
+
+
+static void save_LineStipple( GLcontext *ctx, GLint factor, GLushort pattern )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_LINE_STIPPLE, 2 );
+ if (n) {
+ n[1].i = factor;
+ n[2].us = pattern;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.LineStipple)( ctx, factor, pattern );
+ }
+}
+
+
+static void save_LineWidth( GLcontext *ctx, GLfloat width )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_LINE_WIDTH, 1 );
+ if (n) {
+ n[1].f = width;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.LineWidth)( ctx, width );
+ }
+}
+
+
+static void save_ListBase( GLcontext *ctx, GLuint base )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_LIST_BASE, 1 );
+ if (n) {
+ n[1].ui = base;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.ListBase)( ctx, base );
+ }
+}
+
+
+static void save_LoadIdentity( GLcontext *ctx )
+{
+ FLUSH_VB(ctx, "dlist");
+ (void) alloc_instruction( ctx, OPCODE_LOAD_IDENTITY, 0 );
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.LoadIdentity)( ctx );
+ }
+}
+
+
+static void save_LoadMatrixf( GLcontext *ctx, const GLfloat *m )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_LOAD_MATRIX, 16 );
+ if (n) {
+ GLuint i;
+ for (i=0;i<16;i++) {
+ n[1+i].f = m[i];
+ }
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.LoadMatrixf)( ctx, m );
+ }
+}
+
+
+static void save_LoadName( GLcontext *ctx, GLuint name )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_LOAD_NAME, 1 );
+ if (n) {
+ n[1].ui = name;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.LoadName)( ctx, name );
+ }
+}
+
+
+static void save_LogicOp( GLcontext *ctx, GLenum opcode )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_LOGIC_OP, 1 );
+ if (n) {
+ n[1].e = opcode;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.LogicOp)( ctx, opcode );
+ }
+}
+
+
+static void save_Map1f( GLcontext *ctx,
+ GLenum target, GLfloat u1, GLfloat u2, GLint stride,
+ GLint order, const GLfloat *points, GLboolean retain )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_MAP1, 6 );
+ if (n) {
+ n[1].e = target;
+ n[2].f = u1;
+ n[3].f = u2;
+ n[4].i = stride;
+ n[5].i = order;
+ n[6].data = (void *) points;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.Map1f)( ctx, target, u1, u2, stride, order, points, GL_TRUE );
+ }
+ (void) retain;
+}
+
+
+static void save_Map2f( GLcontext *ctx, GLenum target,
+ GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
+ GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
+ const GLfloat *points, GLboolean retain )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_MAP2, 10 );
+ if (n) {
+ n[1].e = target;
+ n[2].f = u1;
+ n[3].f = u2;
+ n[4].f = v1;
+ n[5].f = v2;
+ n[6].i = ustride;
+ n[7].i = vstride;
+ n[8].i = uorder;
+ n[9].i = vorder;
+ n[10].data = (void *) points;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.Map2f)( ctx, target,
+ u1, u2, ustride, uorder,
+ v1, v2, vstride, vorder, points, GL_TRUE );
+ }
+ (void) retain;
+}
+
+
+static void save_MapGrid1f( GLcontext *ctx, GLint un, GLfloat u1, GLfloat u2 )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_MAPGRID1, 3 );
+ if (n) {
+ n[1].i = un;
+ n[2].f = u1;
+ n[3].f = u2;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.MapGrid1f)( ctx, un, u1, u2 );
+ }
+}
+
+
+static void save_MapGrid2f( GLcontext *ctx,
+ GLint un, GLfloat u1, GLfloat u2,
+ GLint vn, GLfloat v1, GLfloat v2 )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_MAPGRID2, 6 );
+ if (n) {
+ n[1].i = un;
+ n[2].f = u1;
+ n[3].f = u2;
+ n[4].i = vn;
+ n[5].f = v1;
+ n[6].f = v2;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.MapGrid2f)( ctx, un, u1, u2, vn, v1, v2 );
+ }
+}
+
+
+static void save_MatrixMode( GLcontext *ctx, GLenum mode )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_MATRIX_MODE, 1 );
+ if (n) {
+ n[1].e = mode;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.MatrixMode)( ctx, mode );
+ }
+}
+
+
+static void save_MultMatrixf( GLcontext *ctx, const GLfloat *m )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_MULT_MATRIX, 16 );
+ if (n) {
+ GLuint i;
+ for (i=0;i<16;i++) {
+ n[1+i].f = m[i];
+ }
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.MultMatrixf)( ctx, m );
+ }
+}
+
+
+static void save_NewList( GLcontext *ctx, GLuint list, GLenum mode )
+{
+ /* It's an error to call this function while building a display list */
+ gl_error( ctx, GL_INVALID_OPERATION, "glNewList" );
+ (void) list;
+ (void) mode;
+}
+
+
+
+static void save_Ortho( GLcontext *ctx, GLdouble left, GLdouble right,
+ GLdouble bottom, GLdouble top,
+ GLdouble nearval, GLdouble farval )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_ORTHO, 6 );
+ if (n) {
+ n[1].f = left;
+ n[2].f = right;
+ n[3].f = bottom;
+ n[4].f = top;
+ n[5].f = nearval;
+ n[6].f = farval;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.Ortho)( ctx, left, right, bottom, top, nearval, farval );
+ }
+}
+
+
+static void save_PixelMapfv( GLcontext *ctx,
+ GLenum map, GLint mapsize, const GLfloat *values )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_PIXEL_MAP, 3 );
+ if (n) {
+ n[1].e = map;
+ n[2].i = mapsize;
+ n[3].data = (void *) malloc( mapsize * sizeof(GLfloat) );
+ MEMCPY( n[3].data, (void *) values, mapsize * sizeof(GLfloat) );
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.PixelMapfv)( ctx, map, mapsize, values );
+ }
+}
+
+
+static void save_PixelTransferf( GLcontext *ctx, GLenum pname, GLfloat param )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_PIXEL_TRANSFER, 2 );
+ if (n) {
+ n[1].e = pname;
+ n[2].f = param;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.PixelTransferf)( ctx, pname, param );
+ }
+}
+
+
+static void save_PixelZoom( GLcontext *ctx, GLfloat xfactor, GLfloat yfactor )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_PIXEL_ZOOM, 2 );
+ if (n) {
+ n[1].f = xfactor;
+ n[2].f = yfactor;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.PixelZoom)( ctx, xfactor, yfactor );
+ }
+}
+
+
+static void save_PointParameterfvEXT( GLcontext *ctx, GLenum pname,
+ const GLfloat *params)
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_POINT_PARAMETERS, 4 );
+ if (n) {
+ n[1].e = pname;
+ n[2].f = params[0];
+ n[3].f = params[1];
+ n[4].f = params[2];
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.PointParameterfvEXT)( ctx, pname, params );
+ }
+}
+
+
+static void save_PointSize( GLcontext *ctx, GLfloat size )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_POINT_SIZE, 1 );
+ if (n) {
+ n[1].f = size;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.PointSize)( ctx, size );
+ }
+}
+
+
+static void save_PolygonMode( GLcontext *ctx, GLenum face, GLenum mode )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_POLYGON_MODE, 2 );
+ if (n) {
+ n[1].e = face;
+ n[2].e = mode;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.PolygonMode)( ctx, face, mode );
+ }
+}
+
+
+/*
+ * Polygon stipple must have been upacked already!
+ */
+static void save_PolygonStipple( GLcontext *ctx, const GLuint *pattern )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_POLYGON_STIPPLE, 1 );
+ if (n) {
+ void *data;
+ n[1].data = malloc( 32 * 4 );
+ data = n[1].data; /* This needed for Acorn compiler */
+ MEMCPY( data, pattern, 32 * 4 );
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.PolygonStipple)( ctx, pattern );
+ }
+}
+
+
+static void save_PolygonOffset( GLcontext *ctx, GLfloat factor, GLfloat units )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_POLYGON_OFFSET, 2 );
+ if (n) {
+ n[1].f = factor;
+ n[2].f = units;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.PolygonOffset)( ctx, factor, units );
+ }
+}
+
+
+static void save_PopAttrib( GLcontext *ctx )
+{
+ FLUSH_VB(ctx, "dlist");
+ (void) alloc_instruction( ctx, OPCODE_POP_ATTRIB, 0 );
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.PopAttrib)( ctx );
+ }
+}
+
+
+static void save_PopMatrix( GLcontext *ctx )
+{
+ FLUSH_VB(ctx, "dlist");
+ (void) alloc_instruction( ctx, OPCODE_POP_MATRIX, 0 );
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.PopMatrix)( ctx );
+ }
+}
+
+
+static void save_PopName( GLcontext *ctx )
+{
+ FLUSH_VB(ctx, "dlist");
+ (void) alloc_instruction( ctx, OPCODE_POP_NAME, 0 );
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.PopName)( ctx );
+ }
+}
+
+
+static void save_PrioritizeTextures( GLcontext *ctx,
+ GLsizei num, const GLuint *textures,
+ const GLclampf *priorities )
+{
+ GLint i;
+ FLUSH_VB(ctx, "dlist");
+
+ for (i=0;i<num;i++) {
+ Node *n;
+ n = alloc_instruction( ctx, OPCODE_PRIORITIZE_TEXTURE, 2 );
+ if (n) {
+ n[1].ui = textures[i];
+ n[2].f = priorities[i];
+ }
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.PrioritizeTextures)( ctx, num, textures, priorities );
+ }
+}
+
+
+static void save_PushAttrib( GLcontext *ctx, GLbitfield mask )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_PUSH_ATTRIB, 1 );
+ if (n) {
+ n[1].bf = mask;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.PushAttrib)( ctx, mask );
+ }
+}
+
+
+static void save_PushMatrix( GLcontext *ctx )
+{
+ FLUSH_VB(ctx, "dlist");
+ (void) alloc_instruction( ctx, OPCODE_PUSH_MATRIX, 0 );
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.PushMatrix)( ctx );
+ }
+}
+
+
+static void save_PushName( GLcontext *ctx, GLuint name )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_PUSH_NAME, 1 );
+ if (n) {
+ n[1].ui = name;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.PushName)( ctx, name );
+ }
+}
+
+
+static void save_RasterPos4f( GLcontext *ctx,
+ GLfloat x, GLfloat y, GLfloat z, GLfloat w )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_RASTER_POS, 4 );
+ if (n) {
+ n[1].f = x;
+ n[2].f = y;
+ n[3].f = z;
+ n[4].f = w;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.RasterPos4f)( ctx, x, y, z, w );
+ }
+}
+
+
+static void save_PassThrough( GLcontext *ctx, GLfloat token )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_PASSTHROUGH, 1 );
+ if (n) {
+ n[1].f = token;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.PassThrough)( ctx, token );
+ }
+}
+
+
+static void save_ReadBuffer( GLcontext *ctx, GLenum mode )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_READ_BUFFER, 1 );
+ if (n) {
+ n[1].e = mode;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.ReadBuffer)( ctx, mode );
+ }
+}
+
+
+static void save_Rectf( GLcontext *ctx,
+ GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_RECTF, 4 );
+ if (n) {
+ n[1].f = x1;
+ n[2].f = y1;
+ n[3].f = x2;
+ n[4].f = y2;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.Rectf)( ctx, x1, y1, x2, y2 );
+ }
+}
+
+
+static void save_Rotatef( GLcontext *ctx, GLfloat angle,
+ GLfloat x, GLfloat y, GLfloat z )
+{
+ GLfloat m[16];
+ gl_rotation_matrix( angle, x, y, z, m );
+ save_MultMatrixf( ctx, m ); /* save and maybe execute */
+}
+
+
+static void save_Scalef( GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_SCALE, 3 );
+ if (n) {
+ n[1].f = x;
+ n[2].f = y;
+ n[3].f = z;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.Scalef)( ctx, x, y, z );
+ }
+}
+
+
+static void save_Scissor( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_SCISSOR, 4 );
+ if (n) {
+ n[1].i = x;
+ n[2].i = y;
+ n[3].i = width;
+ n[4].i = height;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.Scissor)( ctx, x, y, width, height );
+ }
+}
+
+
+static void save_ShadeModel( GLcontext *ctx, GLenum mode )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_SHADE_MODEL, 1 );
+ if (n) {
+ n[1].e = mode;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.ShadeModel)( ctx, mode );
+ }
+}
+
+
+static void save_StencilFunc( GLcontext *ctx, GLenum func, GLint ref, GLuint mask )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_STENCIL_FUNC, 3 );
+ if (n) {
+ n[1].e = func;
+ n[2].i = ref;
+ n[3].ui = mask;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.StencilFunc)( ctx, func, ref, mask );
+ }
+}
+
+
+static void save_StencilMask( GLcontext *ctx, GLuint mask )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_STENCIL_MASK, 1 );
+ if (n) {
+ n[1].ui = mask;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.StencilMask)( ctx, mask );
+ }
+}
+
+
+static void save_StencilOp( GLcontext *ctx,
+ GLenum fail, GLenum zfail, GLenum zpass )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_STENCIL_OP, 3 );
+ if (n) {
+ n[1].e = fail;
+ n[2].e = zfail;
+ n[3].e = zpass;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.StencilOp)( ctx, fail, zfail, zpass );
+ }
+}
+
+
+
+
+static void save_TexEnvfv( GLcontext *ctx,
+ GLenum target, GLenum pname, const GLfloat *params )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_TEXENV, 6 );
+ if (n) {
+ n[1].e = target;
+ n[2].e = pname;
+ n[3].f = params[0];
+ n[4].f = params[1];
+ n[5].f = params[2];
+ n[6].f = params[3];
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.TexEnvfv)( ctx, target, pname, params );
+ }
+}
+
+
+static void save_TexGenfv( GLcontext *ctx,
+ GLenum coord, GLenum pname, const GLfloat *params )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_TEXGEN, 6 );
+ if (n) {
+ n[1].e = coord;
+ n[2].e = pname;
+ n[3].f = params[0];
+ n[4].f = params[1];
+ n[5].f = params[2];
+ n[6].f = params[3];
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.TexGenfv)( ctx, coord, pname, params );
+ }
+}
+
+
+static void save_TexParameterfv( GLcontext *ctx, GLenum target,
+ GLenum pname, const GLfloat *params )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_TEXPARAMETER, 6 );
+ if (n) {
+ n[1].e = target;
+ n[2].e = pname;
+ n[3].f = params[0];
+ n[4].f = params[1];
+ n[5].f = params[2];
+ n[6].f = params[3];
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.TexParameterfv)( ctx, target, pname, params );
+ }
+}
+
+
+static void save_TexImage1D( GLcontext *ctx, GLenum target,
+ GLint level, GLint components,
+ GLsizei width, GLint border,
+ GLenum format, GLenum type,
+ struct gl_image *teximage )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_TEX_IMAGE1D, 8 );
+ if (n) {
+ n[1].e = target;
+ n[2].i = level;
+ n[3].i = components;
+ n[4].i = (GLint) width;
+ n[5].i = border;
+ n[6].e = format;
+ n[7].e = type;
+ n[8].data = teximage;
+ if (teximage) {
+ /* this prevents gl_TexImage2D() from freeing the image */
+ teximage->RefCount = 1;
+ }
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.TexImage1D)( ctx, target, level, components, width,
+ border, format, type, teximage );
+ }
+}
+
+
+static void save_TexImage2D( GLcontext *ctx, GLenum target,
+ GLint level, GLint components,
+ GLsizei width, GLsizei height, GLint border,
+ GLenum format, GLenum type,
+ struct gl_image *teximage )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_TEX_IMAGE2D, 9 );
+ if (n) {
+ n[1].e = target;
+ n[2].i = level;
+ n[3].i = components;
+ n[4].i = (GLint) width;
+ n[5].i = (GLint) height;
+ n[6].i = border;
+ n[7].e = format;
+ n[8].e = type;
+ n[9].data = teximage;
+ if (teximage) {
+ /* this prevents gl_TexImage2D() from freeing the image */
+ teximage->RefCount = 1;
+ }
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.TexImage2D)( ctx, target, level, components, width,
+ height, border, format, type, teximage );
+ }
+}
+
+
+static void save_TexImage3DEXT( GLcontext *ctx, GLenum target,
+ GLint level, GLint components,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLint border,
+ GLenum format, GLenum type,
+ struct gl_image *teximage )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_TEX_IMAGE3D, 10 );
+ if (n) {
+ n[1].e = target;
+ n[2].i = level;
+ n[3].i = components;
+ n[4].i = (GLint) width;
+ n[5].i = (GLint) height;
+ n[6].i = (GLint) depth;
+ n[7].i = border;
+ n[8].e = format;
+ n[9].e = type;
+ n[10].data = teximage;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.TexImage3DEXT)( ctx, target, level, components, width,
+ height, depth, border, format, type, teximage );
+ }
+}
+
+
+static void save_TexSubImage1D( GLcontext *ctx,
+ GLenum target, GLint level, GLint xoffset,
+ GLsizei width, GLenum format, GLenum type,
+ struct gl_image *image )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_TEX_SUB_IMAGE1D, 7 );
+ if (n) {
+ n[1].e = target;
+ n[2].i = level;
+ n[3].i = xoffset;
+ n[4].i = (GLint) width;
+ n[5].e = format;
+ n[6].e = type;
+ n[7].data = image;
+ if (image)
+ image->RefCount = 1;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.TexSubImage1D)( ctx, target, level, xoffset, width,
+ format, type, image );
+ }
+}
+
+
+static void save_TexSubImage2D( GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ struct gl_image *image )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_TEX_SUB_IMAGE2D, 9 );
+ if (n) {
+ n[1].e = target;
+ n[2].i = level;
+ n[3].i = xoffset;
+ n[4].i = yoffset;
+ n[5].i = (GLint) width;
+ n[6].i = (GLint) height;
+ n[7].e = format;
+ n[8].e = type;
+ n[9].data = image;
+ if (image)
+ image->RefCount = 1;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.TexSubImage2D)( ctx, target, level, xoffset, yoffset,
+ width, height, format, type, image );
+ }
+}
+
+
+static void save_TexSubImage3DEXT( GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type,
+ struct gl_image *image )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_TEX_SUB_IMAGE3D, 11 );
+ if (n) {
+ n[1].e = target;
+ n[2].i = level;
+ n[3].i = xoffset;
+ n[4].i = yoffset;
+ n[5].i = zoffset;
+ n[6].i = (GLint) width;
+ n[7].i = (GLint) height;
+ n[8].i = (GLint) depth;
+ n[9].e = format;
+ n[10].e = type;
+ n[11].data = image;
+ if (image)
+ image->RefCount = 1;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.TexSubImage3DEXT)( ctx, target, level, xoffset, yoffset, zoffset,
+ width, height, depth, format, type, image );
+ }
+}
+
+
+static void save_Translatef( GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_TRANSLATE, 3 );
+ if (n) {
+ n[1].f = x;
+ n[2].f = y;
+ n[3].f = z;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.Translatef)( ctx, x, y, z );
+ }
+}
+
+
+
+static void save_Viewport( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_VIEWPORT, 4 );
+ if (n) {
+ n[1].i = x;
+ n[2].i = y;
+ n[3].i = (GLint) width;
+ n[4].i = (GLint) height;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.Viewport)( ctx, x, y, width, height );
+ }
+}
+
+
+static void save_WindowPos4fMESA( GLcontext *ctx,
+ GLfloat x, GLfloat y, GLfloat z, GLfloat w )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_WINDOW_POS, 4 );
+ if (n) {
+ n[1].f = x;
+ n[2].f = y;
+ n[3].f = z;
+ n[4].f = w;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.WindowPos4fMESA)( ctx, x, y, z, w );
+ }
+}
+
+
+
+
+
+
+/* GL_ARB_multitexture */
+static void save_ActiveTexture( GLcontext *ctx, GLenum target )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_ACTIVE_TEXTURE, 1 );
+ if (n) {
+ n[1].e = target;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.ActiveTexture)( ctx, target );
+ }
+}
+
+
+/* GL_ARB_multitexture */
+static void save_ClientActiveTexture( GLcontext *ctx, GLenum target )
+{
+ Node *n;
+ FLUSH_VB(ctx, "dlist");
+ n = alloc_instruction( ctx, OPCODE_CLIENT_ACTIVE_TEXTURE, 1 );
+ if (n) {
+ n[1].e = target;
+ }
+ if (ctx->ExecuteFlag) {
+ (*ctx->Exec.ClientActiveTexture)( ctx, target );
+ }
+}
+
+
+
+
+
+void gl_compile_cassette( GLcontext *ctx )
+{
+ Node *n = alloc_instruction( ctx, OPCODE_VERTEX_CASSETTE, 1 );
+ struct immediate *new_im = gl_immediate_alloc(ctx);
+ struct immediate *im = ctx->input;
+
+ if (!n || !new_im) {
+ if (n) free(n);
+ if (new_im) gl_immediate_free(new_im);
+ return;
+ }
+
+ /* Do some easy optimizations of the cassette. If current value of
+ * clip volume hint is GL_FASTEST, we are not clipping anyway, so
+ * don't calculate the bounds. But - they will not be calculated
+ * later even if the hint is changed, so this is a slightly odd
+ * behaviour.
+ */
+ if (ctx->Hint.ClipVolumeClipping != GL_FASTEST &&
+ im->v.Obj.size < 4 &&
+ im->Count > 15)
+ {
+ im->Bounds = (GLfloat (*)[3]) malloc(6 * sizeof(GLfloat));
+ (gl_calc_bound_tab[im->v.Obj.size])( im->Bounds, &im->v.Obj );
+ }
+
+
+ n[1].data = (void *)im;
+ SET_IMMEDIATE( ctx, new_im );
+}
+
+/* KW: Compile commands
+ *
+ * Will appear in the list before the vertex buffer containing the
+ * command that provoked the error. I don't see this as a problem.
+ */
+void gl_save_error( GLcontext *ctx, GLenum error, const char *s )
+{
+ Node *n;
+ n = alloc_instruction( ctx, OPCODE_ERROR, 2 );
+ if (n) {
+ n[1].e = error;
+ n[2].data = (void *) s;
+ }
+ /* execute already done */
+}
+
+/**********************************************************************/
+/* Display list execution */
+/**********************************************************************/
+
+
+/*
+ * Execute a display list. Note that the ListBase offset must have already
+ * been added before calling this function. I.e. the list argument is
+ * the absolute list number, not relative to ListBase.
+ * Input: list - display list number
+ */
+static void execute_list( GLcontext *ctx, GLuint list )
+{
+ Node *n;
+ GLboolean done;
+ OpCode opcode;
+
+ if (!gl_IsList(ctx,list))
+ return;
+
+/* mesa_print_display_list( list ); */
+
+ ctx->CallDepth++;
+
+ n = (Node *) HashLookup(ctx->Shared->DisplayList, list);
+
+ done = GL_FALSE;
+ while (!done) {
+ opcode = n[0].opcode;
+
+ switch (opcode) {
+ case OPCODE_ERROR:
+ gl_error( ctx, n[1].e, (const char *) n[2].data );
+ break;
+ case OPCODE_VERTEX_CASSETTE:
+ if (ctx->NewState)
+ gl_update_state(ctx);
+ if (!ctx->CVA.elt.pipeline_valid)
+ gl_build_immediate_pipeline( ctx );
+ gl_fixup_cassette( ctx, (struct immediate *) n[1].data );
+ gl_execute_cassette( ctx, (struct immediate *) n[1].data );
+ break;
+ case OPCODE_ACCUM:
+ gl_Accum( ctx, n[1].e, n[2].f );
+ break;
+ case OPCODE_ALPHA_FUNC:
+ gl_AlphaFunc( ctx, n[1].e, n[2].f );
+ break;
+ case OPCODE_BIND_TEXTURE:
+ gl_BindTexture( ctx, n[1].e, n[2].ui );
+ break;
+ case OPCODE_BITMAP:
+ {
+ static struct gl_pixelstore_attrib defaultPacking = {
+ 1, /* Alignment */
+ 0, /* RowLength */
+ 0, /* SkipPixels */
+ 0, /* SkipRows */
+ 0, /* ImageHeight */
+ 0, /* SkipImages */
+ GL_FALSE, /* SwapBytes */
+ GL_FALSE /* LsbFirst */
+ };
+ const struct gl_image *image = (struct gl_image *) n[7].data;
+ const GLubyte *bitmap = image ? image->Data : NULL;
+ gl_Bitmap( ctx, (GLsizei) n[1].i, (GLsizei) n[2].i,
+ n[3].f, n[4].f, n[5].f, n[6].f,
+ bitmap, &defaultPacking );
+ }
+ break;
+ case OPCODE_BLEND_COLOR:
+ gl_BlendColor( ctx, n[1].f, n[2].f, n[3].f, n[4].f );
+ break;
+ case OPCODE_BLEND_EQUATION:
+ gl_BlendEquation( ctx, n[1].e );
+ break;
+ case OPCODE_BLEND_FUNC:
+ gl_BlendFunc( ctx, n[1].e, n[2].e );
+ break;
+ case OPCODE_BLEND_FUNC_SEPARATE:
+ gl_BlendFuncSeparate( ctx, n[1].e, n[2].e, n[3].e, n[4].e );
+ break;
+ case OPCODE_CALL_LIST:
+ /* Generated by glCallList(), don't add ListBase */
+ if (ctx->CallDepth<MAX_LIST_NESTING) {
+ execute_list( ctx, n[1].ui );
+ }
+ break;
+ case OPCODE_CALL_LIST_OFFSET:
+ /* Generated by glCallLists() so we must add ListBase */
+ if (ctx->CallDepth<MAX_LIST_NESTING) {
+ execute_list( ctx, ctx->List.ListBase + n[1].ui );
+ }
+ break;
+ case OPCODE_CLEAR:
+ gl_Clear( ctx, n[1].bf );
+ break;
+ case OPCODE_CLEAR_COLOR:
+ gl_ClearColor( ctx, n[1].f, n[2].f, n[3].f, n[4].f );
+ break;
+ case OPCODE_CLEAR_ACCUM:
+ gl_ClearAccum( ctx, n[1].f, n[2].f, n[3].f, n[4].f );
+ break;
+ case OPCODE_CLEAR_DEPTH:
+ gl_ClearDepth( ctx, (GLclampd) n[1].f );
+ break;
+ case OPCODE_CLEAR_INDEX:
+ gl_ClearIndex( ctx, n[1].ui );
+ break;
+ case OPCODE_CLEAR_STENCIL:
+ gl_ClearStencil( ctx, n[1].i );
+ break;
+ case OPCODE_CLIP_PLANE:
+ {
+ GLfloat equ[4];
+ equ[0] = n[2].f;
+ equ[1] = n[3].f;
+ equ[2] = n[4].f;
+ equ[3] = n[5].f;
+ gl_ClipPlane( ctx, n[1].e, equ );
+ }
+ break;
+ case OPCODE_COLOR_MASK:
+ gl_ColorMask( ctx, n[1].b, n[2].b, n[3].b, n[4].b );
+ break;
+ case OPCODE_COLOR_MATERIAL:
+ gl_ColorMaterial( ctx, n[1].e, n[2].e );
+ break;
+ case OPCODE_COLOR_TABLE:
+ gl_ColorTable( ctx, n[1].e, n[2].e, (struct gl_image *) n[3].data);
+ break;
+ case OPCODE_COLOR_SUB_TABLE:
+ gl_ColorSubTable( ctx, n[1].e, n[2].i,
+ (struct gl_image *) n[3].data);
+ break;
+ case OPCODE_COPY_PIXELS:
+ gl_CopyPixels( ctx, n[1].i, n[2].i,
+ (GLsizei) n[3].i, (GLsizei) n[4].i, n[5].e );
+ break;
+ case OPCODE_COPY_TEX_IMAGE1D:
+ gl_CopyTexImage1D( ctx, n[1].e, n[2].i, n[3].e, n[4].i,
+ n[5].i, n[6].i, n[7].i );
+ break;
+ case OPCODE_COPY_TEX_IMAGE2D:
+ gl_CopyTexImage2D( ctx, n[1].e, n[2].i, n[3].e, n[4].i,
+ n[5].i, n[6].i, n[7].i, n[8].i );
+ break;
+ case OPCODE_COPY_TEX_SUB_IMAGE1D:
+ gl_CopyTexSubImage1D( ctx, n[1].e, n[2].i, n[3].i, n[4].i,
+ n[5].i, n[6].i );
+ break;
+ case OPCODE_COPY_TEX_SUB_IMAGE2D:
+ gl_CopyTexSubImage2D( ctx, n[1].e, n[2].i, n[3].i, n[4].i,
+ n[5].i, n[6].i, n[7].i, n[8].i );
+ break;
+ case OPCODE_COPY_TEX_SUB_IMAGE3D:
+ gl_CopyTexSubImage3DEXT( ctx, n[1].e, n[2].i, n[3].i, n[4].i,
+ n[5].i, n[6].i, n[7].i, n[8].i , n[9].i);
+ break;
+ case OPCODE_CULL_FACE:
+ gl_CullFace( ctx, n[1].e );
+ break;
+ case OPCODE_DEPTH_FUNC:
+ gl_DepthFunc( ctx, n[1].e );
+ break;
+ case OPCODE_DEPTH_MASK:
+ gl_DepthMask( ctx, n[1].b );
+ break;
+ case OPCODE_DEPTH_RANGE:
+ gl_DepthRange( ctx, (GLclampd) n[1].f, (GLclampd) n[2].f );
+ break;
+ case OPCODE_DISABLE:
+ gl_Disable( ctx, n[1].e );
+ break;
+ case OPCODE_DRAW_BUFFER:
+ gl_DrawBuffer( ctx, n[1].e );
+ break;
+ case OPCODE_DRAW_PIXELS:
+ gl_DrawPixels( ctx, (struct gl_image *) n[1].data );
+ break;
+ case OPCODE_ENABLE:
+ gl_Enable( ctx, n[1].e );
+ break;
+ case OPCODE_EVALMESH1:
+ gl_EvalMesh1( ctx, n[1].e, n[2].i, n[3].i );
+ break;
+ case OPCODE_EVALMESH2:
+ gl_EvalMesh2( ctx, n[1].e, n[2].i, n[3].i, n[4].i, n[5].i );
+ break;
+ case OPCODE_FOG:
+ {
+ GLfloat p[4];
+ p[0] = n[2].f;
+ p[1] = n[3].f;
+ p[2] = n[4].f;
+ p[3] = n[5].f;
+ gl_Fogfv( ctx, n[1].e, p );
+ }
+ break;
+ case OPCODE_FRONT_FACE:
+ gl_FrontFace( ctx, n[1].e );
+ break;
+ case OPCODE_FRUSTUM:
+ gl_Frustum( ctx, n[1].f, n[2].f, n[3].f, n[4].f, n[5].f, n[6].f );
+ break;
+ case OPCODE_HINT:
+ gl_Hint( ctx, n[1].e, n[2].e );
+ break;
+ case OPCODE_INDEX_MASK:
+ gl_IndexMask( ctx, n[1].ui );
+ break;
+ case OPCODE_INIT_NAMES:
+ gl_InitNames( ctx );
+ break;
+ case OPCODE_LIGHT:
+ {
+ GLfloat p[4];
+ p[0] = n[3].f;
+ p[1] = n[4].f;
+ p[2] = n[5].f;
+ p[3] = n[6].f;
+ gl_Lightfv( ctx, n[1].e, n[2].e, p, 4 );
+ }
+ break;
+ case OPCODE_LIGHT_MODEL:
+ {
+ GLfloat p[4];
+ p[0] = n[2].f;
+ p[1] = n[3].f;
+ p[2] = n[4].f;
+ p[3] = n[5].f;
+ gl_LightModelfv( ctx, n[1].e, p );
+ }
+ break;
+ case OPCODE_LINE_STIPPLE:
+ gl_LineStipple( ctx, n[1].i, n[2].us );
+ break;
+ case OPCODE_LINE_WIDTH:
+ gl_LineWidth( ctx, n[1].f );
+ break;
+ case OPCODE_LIST_BASE:
+ gl_ListBase( ctx, n[1].ui );
+ break;
+ case OPCODE_LOAD_IDENTITY:
+ gl_LoadIdentity( ctx );
+ break;
+ case OPCODE_LOAD_MATRIX:
+ if (sizeof(Node)==sizeof(GLfloat)) {
+ gl_LoadMatrixf( ctx, &n[1].f );
+ }
+ else {
+ GLfloat m[16];
+ GLuint i;
+ for (i=0;i<16;i++) {
+ m[i] = n[1+i].f;
+ }
+ gl_LoadMatrixf( ctx, m );
+ }
+ break;
+ case OPCODE_LOAD_NAME:
+ gl_LoadName( ctx, n[1].ui );
+ break;
+ case OPCODE_LOGIC_OP:
+ gl_LogicOp( ctx, n[1].e );
+ break;
+ case OPCODE_MAP1:
+ gl_Map1f( ctx, n[1].e, n[2].f, n[3].f,
+ n[4].i, n[5].i, (GLfloat *) n[6].data, GL_TRUE );
+ break;
+ case OPCODE_MAP2:
+ gl_Map2f( ctx, n[1].e,
+ n[2].f, n[3].f, /* u1, u2 */
+ n[6].i, n[8].i, /* ustride, uorder */
+ n[4].f, n[5].f, /* v1, v2 */
+ n[7].i, n[9].i, /* vstride, vorder */
+ (GLfloat *) n[10].data,
+ GL_TRUE);
+ break;
+ case OPCODE_MAPGRID1:
+ gl_MapGrid1f( ctx, n[1].i, n[2].f, n[3].f );
+ break;
+ case OPCODE_MAPGRID2:
+ gl_MapGrid2f( ctx, n[1].i, n[2].f, n[3].f, n[4].i, n[5].f, n[6].f);
+ break;
+ case OPCODE_MATRIX_MODE:
+ gl_MatrixMode( ctx, n[1].e );
+ break;
+ case OPCODE_MULT_MATRIX:
+ if (sizeof(Node)==sizeof(GLfloat)) {
+ gl_MultMatrixf( ctx, &n[1].f );
+ }
+ else {
+ GLfloat m[16];
+ GLuint i;
+ for (i=0;i<16;i++) {
+ m[i] = n[1+i].f;
+ }
+ gl_MultMatrixf( ctx, m );
+ }
+ break;
+ case OPCODE_ORTHO:
+ gl_Ortho( ctx, n[1].f, n[2].f, n[3].f, n[4].f, n[5].f, n[6].f );
+ break;
+ case OPCODE_PASSTHROUGH:
+ gl_PassThrough( ctx, n[1].f );
+ break;
+ case OPCODE_PIXEL_MAP:
+ gl_PixelMapfv( ctx, n[1].e, n[2].i, (GLfloat *) n[3].data );
+ break;
+ case OPCODE_PIXEL_TRANSFER:
+ gl_PixelTransferf( ctx, n[1].e, n[2].f );
+ break;
+ case OPCODE_PIXEL_ZOOM:
+ gl_PixelZoom( ctx, n[1].f, n[2].f );
+ break;
+ case OPCODE_POINT_SIZE:
+ gl_PointSize( ctx, n[1].f );
+ break;
+ case OPCODE_POINT_PARAMETERS:
+ {
+ GLfloat params[3];
+ params[0] = n[2].f;
+ params[1] = n[3].f;
+ params[2] = n[4].f;
+ gl_PointParameterfvEXT( ctx, n[1].e, params );
+ }
+ break;
+ case OPCODE_POLYGON_MODE:
+ gl_PolygonMode( ctx, n[1].e, n[2].e );
+ break;
+ case OPCODE_POLYGON_STIPPLE:
+ gl_PolygonStipple( ctx, (GLuint *) n[1].data );
+ break;
+ case OPCODE_POLYGON_OFFSET:
+ gl_PolygonOffset( ctx, n[1].f, n[2].f );
+ break;
+ case OPCODE_POP_ATTRIB:
+ gl_PopAttrib( ctx );
+ break;
+ case OPCODE_POP_MATRIX:
+ gl_PopMatrix( ctx );
+ break;
+ case OPCODE_POP_NAME:
+ gl_PopName( ctx );
+ break;
+ case OPCODE_PRIORITIZE_TEXTURE:
+ gl_PrioritizeTextures( ctx, 1, &n[1].ui, &n[2].f );
+ break;
+ case OPCODE_PUSH_ATTRIB:
+ gl_PushAttrib( ctx, n[1].bf );
+ break;
+ case OPCODE_PUSH_MATRIX:
+ gl_PushMatrix( ctx );
+ break;
+ case OPCODE_PUSH_NAME:
+ gl_PushName( ctx, n[1].ui );
+ break;
+ case OPCODE_RASTER_POS:
+ gl_RasterPos4f( ctx, n[1].f, n[2].f, n[3].f, n[4].f );
+ break;
+ case OPCODE_READ_BUFFER:
+ gl_ReadBuffer( ctx, n[1].e );
+ break;
+ case OPCODE_RECTF:
+ gl_Rectf( ctx, n[1].f, n[2].f, n[3].f, n[4].f );
+ break;
+ case OPCODE_SCALE:
+ gl_Scalef( ctx, n[1].f, n[2].f, n[3].f );
+ break;
+ case OPCODE_SCISSOR:
+ gl_Scissor( ctx, n[1].i, n[2].i, n[3].i, n[4].i );
+ break;
+ case OPCODE_SHADE_MODEL:
+ gl_ShadeModel( ctx, n[1].e );
+ break;
+ case OPCODE_STENCIL_FUNC:
+ gl_StencilFunc( ctx, n[1].e, n[2].i, n[3].ui );
+ break;
+ case OPCODE_STENCIL_MASK:
+ gl_StencilMask( ctx, n[1].ui );
+ break;
+ case OPCODE_STENCIL_OP:
+ gl_StencilOp( ctx, n[1].e, n[2].e, n[3].e );
+ break;
+ case OPCODE_TEXENV:
+ {
+ GLfloat params[4];
+ params[0] = n[3].f;
+ params[1] = n[4].f;
+ params[2] = n[5].f;
+ params[3] = n[6].f;
+ gl_TexEnvfv( ctx, n[1].e, n[2].e, params );
+ }
+ break;
+ case OPCODE_TEXGEN:
+ {
+ GLfloat params[4];
+ params[0] = n[3].f;
+ params[1] = n[4].f;
+ params[2] = n[5].f;
+ params[3] = n[6].f;
+ gl_TexGenfv( ctx, n[1].e, n[2].e, params );
+ }
+ break;
+ case OPCODE_TEXPARAMETER:
+ {
+ GLfloat params[4];
+ params[0] = n[3].f;
+ params[1] = n[4].f;
+ params[2] = n[5].f;
+ params[3] = n[6].f;
+ gl_TexParameterfv( ctx, n[1].e, n[2].e, params );
+ }
+ break;
+ case OPCODE_TEX_IMAGE1D:
+ gl_TexImage1D( ctx,
+ n[1].e, /* target */
+ n[2].i, /* level */
+ n[3].i, /* components */
+ n[4].i, /* width */
+ n[5].e, /* border */
+ n[6].e, /* format */
+ n[7].e, /* type */
+ (struct gl_image *) n[8].data );
+ break;
+ case OPCODE_TEX_IMAGE2D:
+ gl_TexImage2D( ctx,
+ n[1].e, /* target */
+ n[2].i, /* level */
+ n[3].i, /* components */
+ n[4].i, /* width */
+ n[5].i, /* height */
+ n[6].e, /* border */
+ n[7].e, /* format */
+ n[8].e, /* type */
+ (struct gl_image *) n[9].data );
+ break;
+ case OPCODE_TEX_IMAGE3D:
+ gl_TexImage3DEXT( ctx,
+ n[1].e, /* target */
+ n[2].i, /* level */
+ n[3].i, /* components */
+ n[4].i, /* width */
+ n[5].i, /* height */
+ n[6].i, /* depth */
+ n[7].e, /* border */
+ n[8].e, /* format */
+ n[9].e, /* type */
+ (struct gl_image *) n[10].data );
+ break;
+ case OPCODE_TEX_SUB_IMAGE1D:
+ gl_TexSubImage1D( ctx, n[1].e, n[2].i, n[3].i, n[4].i, n[5].e,
+ n[6].e, (struct gl_image *) n[7].data );
+ break;
+ case OPCODE_TEX_SUB_IMAGE2D:
+ gl_TexSubImage2D( ctx, n[1].e, n[2].i, n[3].i, n[4].i, n[5].e,
+ n[6].i, n[7].e, n[8].e,
+ (struct gl_image *) n[9].data );
+ break;
+ case OPCODE_TEX_SUB_IMAGE3D:
+ gl_TexSubImage3DEXT( ctx, n[1].e, n[2].i, n[3].i, n[4].i, n[5].i,
+ n[6].i, n[7].i, n[8].i, n[9].e, n[10].e,
+ (struct gl_image *) n[11].data );
+ break;
+ case OPCODE_TRANSLATE:
+ gl_Translatef( ctx, n[1].f, n[2].f, n[3].f );
+ break;
+ case OPCODE_VIEWPORT:
+ gl_Viewport( ctx,
+ n[1].i, n[2].i, (GLsizei) n[3].i, (GLsizei) n[4].i );
+ break;
+ case OPCODE_WINDOW_POS:
+ gl_WindowPos4fMESA( ctx, n[1].f, n[2].f, n[3].f, n[4].f );
+ break;
+ case OPCODE_ACTIVE_TEXTURE: /* GL_ARB_multitexture */
+ gl_ActiveTexture( ctx, n[1].e );
+ break;
+ case OPCODE_CLIENT_ACTIVE_TEXTURE: /* GL_ARB_multitexture */
+ gl_ClientActiveTexture( ctx, n[1].e );
+ break;
+ case OPCODE_CONTINUE:
+ n = (Node *) n[1].next;
+ break;
+ case OPCODE_END_OF_LIST:
+ done = GL_TRUE;
+ break;
+ default:
+ {
+ char msg[1000];
+ sprintf(msg, "Error in execute_list: opcode=%d", (int) opcode);
+ gl_problem( ctx, msg );
+ }
+ done = GL_TRUE;
+ }
+
+ /* increment n to point to next compiled command */
+ if (opcode!=OPCODE_CONTINUE) {
+ n += InstSize[opcode];
+ }
+
+ }
+ ctx->CallDepth--;
+}
+
+
+
+
+
+/**********************************************************************/
+/* GL functions */
+/**********************************************************************/
+
+
+
+
+/*
+ * Test if a display list number is valid.
+ */
+GLboolean gl_IsList( GLcontext *ctx, GLuint list )
+{
+ if (list > 0 && HashLookup(ctx->Shared->DisplayList, list)) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
+
+
+/*
+ * Delete a sequence of consecutive display lists.
+ */
+void gl_DeleteLists( GLcontext *ctx, GLuint list, GLsizei range )
+{
+ GLuint i;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDeleteLists");
+ if (range<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glDeleteLists" );
+ return;
+ }
+ for (i=list;i<list+range;i++) {
+ gl_destroy_list( ctx, i );
+ }
+}
+
+
+
+/*
+ * Return a display list number, n, such that lists n through n+range-1
+ * are free.
+ */
+GLuint gl_GenLists( GLcontext *ctx, GLsizei range )
+{
+ GLuint base;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, "glGenLists", 0);
+ if (range<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glGenLists" );
+ return 0;
+ }
+ if (range==0) {
+ return 0;
+ }
+
+ base = HashFindFreeKeyBlock(ctx->Shared->DisplayList, range);
+ if (base) {
+ /* reserve the list IDs by with empty/dummy lists */
+ GLint i;
+ for (i=0; i<range; i++) {
+ HashInsert(ctx->Shared->DisplayList, base+i, make_empty_list());
+ }
+ }
+ return base;
+}
+
+
+
+/*
+ * Begin a new display list.
+ */
+void gl_NewList( GLcontext *ctx, GLuint list, GLenum mode )
+{
+ struct immediate *IM;
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glNewList");
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ fprintf(stderr, "glNewList %u %s\n", list, gl_lookup_enum_by_nr(mode));
+
+ if (list==0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glNewList" );
+ return;
+ }
+
+ if (mode!=GL_COMPILE && mode!=GL_COMPILE_AND_EXECUTE) {
+ gl_error( ctx, GL_INVALID_ENUM, "glNewList" );
+ return;
+ }
+
+ if (ctx->CurrentListPtr) {
+ /* already compiling a display list */
+ gl_error( ctx, GL_INVALID_OPERATION, "glNewList" );
+ return;
+ }
+
+ /* Allocate new display list */
+ ctx->CurrentListNum = list;
+ ctx->CurrentBlock = (Node *) malloc( sizeof(Node) * BLOCK_SIZE );
+ ctx->CurrentListPtr = ctx->CurrentBlock;
+ ctx->CurrentPos = 0;
+
+ IM = gl_immediate_alloc( ctx );
+ SET_IMMEDIATE( ctx, IM );
+ gl_reset_input( ctx );
+
+ ctx->CompileFlag = GL_TRUE;
+ ctx->CompileCVAFlag = GL_FALSE;
+ ctx->ExecuteFlag = (mode == GL_COMPILE_AND_EXECUTE);
+ ctx->API = ctx->Save; /* Switch the API function pointers */
+}
+
+
+
+/*
+ * End definition of current display list.
+ */
+void gl_EndList( GLcontext *ctx )
+{
+ if (MESA_VERBOSE&VERBOSE_API)
+ fprintf(stderr, "glEndList\n");
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx, "glEndList" );
+
+ /* Check that a list is under construction */
+ if (!ctx->CurrentListPtr) {
+ gl_error( ctx, GL_INVALID_OPERATION, "glEndList" );
+ return;
+ }
+
+ (void) alloc_instruction( ctx, OPCODE_END_OF_LIST, 0 );
+
+
+
+ /* Destroy old list, if any */
+ gl_destroy_list(ctx, ctx->CurrentListNum);
+ /* Install the list */
+ HashInsert(ctx->Shared->DisplayList, ctx->CurrentListNum, ctx->CurrentListPtr);
+
+ ctx->CurrentListNum = 0;
+ ctx->CurrentListPtr = NULL;
+ ctx->ExecuteFlag = GL_TRUE;
+ ctx->CompileFlag = GL_FALSE;
+ /* ctx->CompileCVAFlag = ...; */
+
+ /* KW: Put back the old input pointer.
+ */
+ free( ctx->input );
+ SET_IMMEDIATE( ctx, ctx->VB->IM );
+
+ ctx->API = ctx->Exec; /* Switch the API function pointers */
+}
+
+
+
+void gl_CallList( GLcontext *ctx, GLuint list )
+{
+ /* VERY IMPORTANT: Save the CompileFlag status, turn it off, */
+ /* execute the display list, and restore the CompileFlag. */
+ GLboolean save_compile_flag;
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ fprintf(stderr, "glCallList %u\n", list);
+
+
+ save_compile_flag = ctx->CompileFlag;
+ ctx->CompileFlag = GL_FALSE;
+
+ FLUSH_VB( ctx, "call list" );
+
+/* mesa_print_display_list( list ); */
+
+ execute_list( ctx, list );
+ ctx->CompileFlag = save_compile_flag;
+
+ /* also restore API function pointers to point to "save" versions */
+ if (save_compile_flag)
+ ctx->API = ctx->Save;
+
+
+/* RESET_IMMEDIATE( ctx ); */
+}
+
+
+
+/*
+ * Execute glCallLists: call multiple display lists.
+ */
+void gl_CallLists( GLcontext *ctx,
+ GLsizei n, GLenum type, const GLvoid *lists )
+{
+ GLuint list;
+ GLint i;
+ GLboolean save_compile_flag;
+
+ /* Save the CompileFlag status, turn it off, execute display list,
+ * and restore the CompileFlag.
+ */
+ save_compile_flag = ctx->CompileFlag;
+ ctx->CompileFlag = GL_FALSE;
+
+ FLUSH_VB( ctx, "call lists" );
+
+ for (i=0;i<n;i++) {
+ list = translate_id( i, type, lists );
+ execute_list( ctx, ctx->List.ListBase + list );
+ }
+
+ ctx->CompileFlag = save_compile_flag;
+
+ /* also restore API function pointers to point to "save" versions */
+ if (save_compile_flag)
+ ctx->API = ctx->Save;
+
+
+/* RESET_IMMEDIATE( ctx ); */
+}
+
+
+
+/*
+ * Set the offset added to list numbers in glCallLists.
+ */
+void gl_ListBase( GLcontext *ctx, GLuint base )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glListBase");
+ ctx->List.ListBase = base;
+}
+
+
+
+
+
+
+/*
+ * Assign all the pointers in 'table' to point to Mesa's display list
+ * building functions.
+ */
+void gl_init_dlist_pointers( struct gl_api_table *table )
+{
+ table->Accum = save_Accum;
+ table->AlphaFunc = save_AlphaFunc;
+ table->AreTexturesResident = gl_AreTexturesResident;
+ table->BindTexture = save_BindTexture;
+ table->Bitmap = save_Bitmap;
+ table->BlendColor = save_BlendColor;
+ table->BlendEquation = save_BlendEquation;
+ table->BlendFunc = save_BlendFunc;
+ table->BlendFuncSeparate = save_BlendFuncSeparate;
+ table->CallList = save_CallList;
+ table->CallLists = save_CallLists;
+ table->Clear = save_Clear;
+ table->ClearAccum = save_ClearAccum;
+ table->ClearColor = save_ClearColor;
+ table->ClearDepth = save_ClearDepth;
+ table->ClearIndex = save_ClearIndex;
+ table->ClearStencil = save_ClearStencil;
+ table->ClipPlane = save_ClipPlane;
+ table->ColorMask = save_ColorMask;
+ table->ColorMaterial = save_ColorMaterial;
+ table->ColorTable = save_ColorTable;
+ table->ColorSubTable = save_ColorSubTable;
+ table->CopyPixels = save_CopyPixels;
+ table->CopyTexImage1D = save_CopyTexImage1D;
+ table->CopyTexImage2D = save_CopyTexImage2D;
+ table->CopyTexSubImage1D = save_CopyTexSubImage1D;
+ table->CopyTexSubImage2D = save_CopyTexSubImage2D;
+ table->CopyTexSubImage3DEXT = save_CopyTexSubImage3DEXT;
+ table->CullFace = save_CullFace;
+ table->DeleteLists = gl_DeleteLists; /* NOT SAVED */
+ table->DeleteTextures = gl_DeleteTextures; /* NOT SAVED */
+ table->DepthFunc = save_DepthFunc;
+ table->DepthMask = save_DepthMask;
+ table->DepthRange = save_DepthRange;
+ table->Disable = save_Disable;
+ table->DisableClientState = gl_DisableClientState; /* NOT SAVED */
+ table->DrawBuffer = save_DrawBuffer;
+ table->DrawPixels = save_DrawPixels;
+ table->Enable = save_Enable;
+ table->Error = gl_save_error;
+ table->EnableClientState = gl_EnableClientState; /* NOT SAVED */
+ table->EndList = gl_EndList; /* NOT SAVED */
+ table->EvalMesh1 = save_EvalMesh1;
+ table->EvalMesh2 = save_EvalMesh2;
+ table->FeedbackBuffer = gl_FeedbackBuffer; /* NOT SAVED */
+ table->Finish = gl_Finish; /* NOT SAVED */
+ table->Flush = gl_Flush; /* NOT SAVED */
+ table->Fogfv = save_Fogfv;
+ table->FrontFace = save_FrontFace;
+ table->Frustum = save_Frustum;
+ table->GenLists = gl_GenLists; /* NOT SAVED */
+ table->GenTextures = gl_GenTextures; /* NOT SAVED */
+
+ /* NONE OF THESE COMMANDS ARE COMPILED INTO DISPLAY LISTS */
+ table->GetBooleanv = gl_GetBooleanv;
+ table->GetClipPlane = gl_GetClipPlane;
+ table->GetColorTable = gl_GetColorTable;
+ table->GetColorTableParameteriv = gl_GetColorTableParameteriv;
+ table->GetDoublev = gl_GetDoublev;
+ table->GetError = gl_GetError;
+ table->GetFloatv = gl_GetFloatv;
+ table->GetIntegerv = gl_GetIntegerv;
+ table->GetString = gl_GetString;
+ table->GetLightfv = gl_GetLightfv;
+ table->GetLightiv = gl_GetLightiv;
+ table->GetMapdv = gl_GetMapdv;
+ table->GetMapfv = gl_GetMapfv;
+ table->GetMapiv = gl_GetMapiv;
+ table->GetMaterialfv = gl_GetMaterialfv;
+ table->GetMaterialiv = gl_GetMaterialiv;
+ table->GetPixelMapfv = gl_GetPixelMapfv;
+ table->GetPixelMapuiv = gl_GetPixelMapuiv;
+ table->GetPixelMapusv = gl_GetPixelMapusv;
+ table->GetPointerv = gl_GetPointerv;
+ table->GetPolygonStipple = gl_GetPolygonStipple;
+ table->GetTexEnvfv = gl_GetTexEnvfv;
+ table->GetTexEnviv = gl_GetTexEnviv;
+ table->GetTexGendv = gl_GetTexGendv;
+ table->GetTexGenfv = gl_GetTexGenfv;
+ table->GetTexGeniv = gl_GetTexGeniv;
+ table->GetTexImage = gl_GetTexImage;
+ table->GetTexLevelParameterfv = gl_GetTexLevelParameterfv;
+ table->GetTexLevelParameteriv = gl_GetTexLevelParameteriv;
+ table->GetTexParameterfv = gl_GetTexParameterfv;
+ table->GetTexParameteriv = gl_GetTexParameteriv;
+
+ table->Hint = save_Hint;
+ table->IndexMask = save_IndexMask;
+ table->InitNames = save_InitNames;
+ table->IsEnabled = gl_IsEnabled; /* NOT SAVED */
+ table->IsTexture = gl_IsTexture; /* NOT SAVED */
+ table->IsList = gl_IsList; /* NOT SAVED */
+ table->LightModelfv = save_LightModelfv;
+ table->Lightfv = save_Lightfv;
+ table->LineStipple = save_LineStipple;
+ table->LineWidth = save_LineWidth;
+ table->ListBase = save_ListBase;
+ table->LoadIdentity = save_LoadIdentity;
+ table->LoadMatrixf = save_LoadMatrixf;
+ table->LoadName = save_LoadName;
+ table->LogicOp = save_LogicOp;
+ table->Map1f = save_Map1f;
+ table->Map2f = save_Map2f;
+ table->MapGrid1f = save_MapGrid1f;
+ table->MapGrid2f = save_MapGrid2f;
+ table->MatrixMode = save_MatrixMode;
+ table->MultMatrixf = save_MultMatrixf;
+ table->NewList = save_NewList;
+ table->Ortho = save_Ortho;
+ table->PointParameterfvEXT = save_PointParameterfvEXT;
+ table->PassThrough = save_PassThrough;
+ table->PixelMapfv = save_PixelMapfv;
+ table->PixelStorei = gl_PixelStorei; /* NOT SAVED */
+ table->PixelTransferf = save_PixelTransferf;
+ table->PixelZoom = save_PixelZoom;
+ table->PointSize = save_PointSize;
+ table->PolygonMode = save_PolygonMode;
+ table->PolygonOffset = save_PolygonOffset;
+ table->PolygonStipple = save_PolygonStipple;
+ table->PopAttrib = save_PopAttrib;
+ table->PopClientAttrib = gl_PopClientAttrib; /* NOT SAVED */
+ table->PopMatrix = save_PopMatrix;
+ table->PopName = save_PopName;
+ table->PrioritizeTextures = save_PrioritizeTextures;
+ table->PushAttrib = save_PushAttrib;
+ table->PushClientAttrib = gl_PushClientAttrib; /* NOT SAVED */
+ table->PushMatrix = save_PushMatrix;
+ table->PushName = save_PushName;
+ table->RasterPos4f = save_RasterPos4f;
+ table->ReadBuffer = save_ReadBuffer;
+ table->ReadPixels = gl_ReadPixels; /* NOT SAVED */
+ table->Rectf = save_Rectf;
+ table->RenderMode = gl_RenderMode; /* NOT SAVED */
+ table->Rotatef = save_Rotatef;
+ table->Scalef = save_Scalef;
+ table->Scissor = save_Scissor;
+ table->SelectBuffer = gl_SelectBuffer; /* NOT SAVED */
+ table->ShadeModel = save_ShadeModel;
+ table->StencilFunc = save_StencilFunc;
+ table->StencilMask = save_StencilMask;
+ table->StencilOp = save_StencilOp;
+ table->TexEnvfv = save_TexEnvfv;
+ table->TexGenfv = save_TexGenfv;
+ table->TexImage1D = save_TexImage1D;
+ table->TexImage2D = save_TexImage2D;
+ table->TexImage3DEXT = save_TexImage3DEXT;
+ table->TexSubImage1D = save_TexSubImage1D;
+ table->TexSubImage2D = save_TexSubImage2D;
+ table->TexSubImage3DEXT = save_TexSubImage3DEXT;
+ table->TexParameterfv = save_TexParameterfv;
+ table->Translatef = save_Translatef;
+ table->Viewport = save_Viewport;
+
+ /* GL_MESA_window_pos extension */
+ table->WindowPos4fMESA = save_WindowPos4fMESA;
+
+ /* GL_MESA_resize_buffers extension */
+ table->ResizeBuffersMESA = gl_ResizeBuffersMESA;
+
+ /* GL_ARB_multitexture */
+ table->ActiveTexture = save_ActiveTexture;
+ table->ClientActiveTexture = save_ClientActiveTexture;
+}
+
+
+
+/***
+ *** Debugging code
+ ***/
+static const char *enum_string( GLenum k )
+{
+ return gl_lookup_enum_by_nr( k );
+}
+
+
+/*
+ * Print the commands in a display list. For debugging only.
+ * TODO: many commands aren't handled yet.
+ */
+static void print_list( GLcontext *ctx, FILE *f, GLuint list )
+{
+ Node *n;
+ GLboolean done;
+ OpCode opcode;
+
+ if (!glIsList(list)) {
+ fprintf(f,"%u is not a display list ID\n",list);
+ return;
+ }
+
+ n = (Node *) HashLookup(ctx->Shared->DisplayList, list);
+
+ fprintf( f, "START-LIST %u, address %p\n", list, (void*)n );
+
+ done = n ? GL_FALSE : GL_TRUE;
+ while (!done) {
+ opcode = n[0].opcode;
+
+ switch (opcode) {
+ case OPCODE_ACCUM:
+ fprintf(f,"accum %s %g\n", enum_string(n[1].e), n[2].f );
+ break;
+ case OPCODE_BITMAP:
+ fprintf(f,"Bitmap %d %d %g %g %g %g %p\n", n[1].i, n[2].i,
+ n[3].f, n[4].f, n[5].f, n[6].f, (void *) n[7].data );
+ break;
+ case OPCODE_CALL_LIST:
+ fprintf(f,"CallList %d\n", (int) n[1].ui );
+ break;
+ case OPCODE_CALL_LIST_OFFSET:
+ fprintf(f,"CallList %d + offset %u = %u\n", (int) n[1].ui,
+ ctx->List.ListBase, ctx->List.ListBase + n[1].ui );
+ break;
+ case OPCODE_DISABLE:
+ fprintf(f,"Disable %s\n", enum_string(n[1].e));
+ break;
+ case OPCODE_ENABLE:
+ fprintf(f,"Enable %s\n", enum_string(n[1].e));
+ break;
+ case OPCODE_FRUSTUM:
+ fprintf(f,"Frustum %g %g %g %g %g %g\n",
+ n[1].f, n[2].f, n[3].f, n[4].f, n[5].f, n[6].f );
+ break;
+ case OPCODE_LINE_STIPPLE:
+ fprintf(f,"LineStipple %d %x\n", n[1].i, (int) n[2].us );
+ break;
+ case OPCODE_LOAD_IDENTITY:
+ fprintf(f,"LoadIdentity\n");
+ break;
+ case OPCODE_LOAD_MATRIX:
+ fprintf(f,"LoadMatrix\n");
+ fprintf(f," %8f %8f %8f %8f\n", n[1].f, n[5].f, n[9].f, n[13].f);
+ fprintf(f," %8f %8f %8f %8f\n", n[2].f, n[6].f, n[10].f, n[14].f);
+ fprintf(f," %8f %8f %8f %8f\n", n[3].f, n[7].f, n[11].f, n[15].f);
+ fprintf(f," %8f %8f %8f %8f\n", n[4].f, n[8].f, n[12].f, n[16].f);
+ break;
+ case OPCODE_MULT_MATRIX:
+ fprintf(f,"MultMatrix (or Rotate)\n");
+ fprintf(f," %8f %8f %8f %8f\n", n[1].f, n[5].f, n[9].f, n[13].f);
+ fprintf(f," %8f %8f %8f %8f\n", n[2].f, n[6].f, n[10].f, n[14].f);
+ fprintf(f," %8f %8f %8f %8f\n", n[3].f, n[7].f, n[11].f, n[15].f);
+ fprintf(f," %8f %8f %8f %8f\n", n[4].f, n[8].f, n[12].f, n[16].f);
+ break;
+ case OPCODE_ORTHO:
+ fprintf(f,"Ortho %g %g %g %g %g %g\n",
+ n[1].f, n[2].f, n[3].f, n[4].f, n[5].f, n[6].f );
+ break;
+ case OPCODE_POP_ATTRIB:
+ fprintf(f,"PopAttrib\n");
+ break;
+ case OPCODE_POP_MATRIX:
+ fprintf(f,"PopMatrix\n");
+ break;
+ case OPCODE_POP_NAME:
+ fprintf(f,"PopName\n");
+ break;
+ case OPCODE_PUSH_ATTRIB:
+ fprintf(f,"PushAttrib %x\n", n[1].bf );
+ break;
+ case OPCODE_PUSH_MATRIX:
+ fprintf(f,"PushMatrix\n");
+ break;
+ case OPCODE_PUSH_NAME:
+ fprintf(f,"PushName %d\n", (int) n[1].ui );
+ break;
+ case OPCODE_RASTER_POS:
+ fprintf(f,"RasterPos %g %g %g %g\n", n[1].f, n[2].f,n[3].f,n[4].f);
+ break;
+ case OPCODE_RECTF:
+ fprintf( f, "Rectf %g %g %g %g\n", n[1].f, n[2].f, n[3].f, n[4].f);
+ break;
+ case OPCODE_SCALE:
+ fprintf(f,"Scale %g %g %g\n", n[1].f, n[2].f, n[3].f );
+ break;
+ case OPCODE_TRANSLATE:
+ fprintf(f,"Translate %g %g %g\n", n[1].f, n[2].f, n[3].f );
+ break;
+
+ /*
+ * meta opcodes/commands
+ */
+ case OPCODE_ERROR:
+ fprintf(f,"Error: %s %s\n", enum_string(n[1].e), (const char *)n[2].data );
+ break;
+ case OPCODE_VERTEX_CASSETTE:
+ fprintf(f,"VERTEX-CASSETTE, id %u, %u elements\n",
+ ((struct immediate *) n[1].data)->id,
+ ((struct immediate *) n[1].data)->Count - VB_START );
+ break;
+ case OPCODE_CONTINUE:
+ fprintf(f,"DISPLAY-LIST-CONTINUE\n");
+ n = (Node *) n[1].next;
+ break;
+ case OPCODE_END_OF_LIST:
+ fprintf(f,"END-LIST %u\n", list);
+ done = GL_TRUE;
+ break;
+ default:
+ if (opcode < 0 || opcode > OPCODE_END_OF_LIST) {
+ fprintf(f,"ERROR IN DISPLAY LIST: opcode = %d, address = %p\n",
+ opcode, (void*) n);
+ return;
+ }
+ else {
+ fprintf(f,"command %d, %u operands\n",opcode,InstSize[opcode]);
+ }
+ }
+
+ /* increment n to point to next compiled command */
+ if (opcode!=OPCODE_CONTINUE) {
+ n += InstSize[opcode];
+ }
+ }
+}
+
+
+
+
+
+
+
+
+/*
+ * Clients may call this function to help debug display list problems.
+ * This function is _ONLY_FOR_DEBUGGING_PURPOSES_. It may be removed,
+ * changed, or break in the future without notice.
+ */
+void mesa_print_display_list( GLuint list )
+{
+ GET_CONTEXT;
+ print_list( CC, stdout, list );
+}
diff --git a/src/mesa/main/dlist.h b/src/mesa/main/dlist.h
new file mode 100644
index 0000000000..c5a5918190
--- /dev/null
+++ b/src/mesa/main/dlist.h
@@ -0,0 +1,79 @@
+/* $Id: dlist.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef DLIST_H
+#define DLIST_H
+
+
+#include "types.h"
+
+struct display_list {
+ union node *nodes;
+ GLuint OrFlag;
+ struct gl_current_attrib outputs;
+};
+
+struct display_list_compilation {
+ struct display_list *list;
+ union node *current_block;
+ GLuint current_pos;
+};
+
+
+extern void gl_init_lists( void );
+
+extern void gl_destroy_list( GLcontext *ctx, GLuint list );
+
+extern void gl_CallList( GLcontext *ctx, GLuint list );
+
+extern void gl_CallLists( GLcontext *ctx,
+ GLsizei n, GLenum type, const GLvoid *lists );
+
+extern void gl_DeleteLists( GLcontext *ctx, GLuint list, GLsizei range );
+
+extern void gl_EndList( GLcontext *ctx );
+
+extern GLuint gl_GenLists( GLcontext *ctx, GLsizei range );
+
+extern GLboolean gl_IsList( GLcontext *ctx, GLuint list );
+
+extern void gl_ListBase( GLcontext *ctx, GLuint base );
+
+extern void gl_NewList( GLcontext *ctx, GLuint list, GLenum mode );
+
+extern void gl_init_dlist_pointers( struct gl_api_table *table );
+
+
+extern void gl_compile_cassette( GLcontext *ctx );
+
+extern void gl_save_error( GLcontext *ctx, GLenum error, const char *s );
+
+
+#endif
diff --git a/src/mesa/main/drawpix.c b/src/mesa/main/drawpix.c
new file mode 100644
index 0000000000..a78f345a81
--- /dev/null
+++ b/src/mesa/main/drawpix.c
@@ -0,0 +1,946 @@
+/* $Id: drawpix.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "context.h"
+#include "drawpix.h"
+#include "feedback.h"
+#include "image.h"
+#include "macros.h"
+#include "mmath.h"
+#include "pixel.h"
+#include "span.h"
+#include "stencil.h"
+#include "types.h"
+#include "zoom.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+
+/* TODO: apply texture mapping to fragments */
+
+
+/*
+ * Try to do a fast glDrawPixels. Conditions include:
+ * not using a display list
+ * simple pixel unpacking
+ * no raster ops
+ * etc....
+ * Return: GL_TRUE if success, GL_FALSE if slow path must be used instead
+ */
+GLboolean gl_direct_DrawPixels( GLcontext *ctx,
+ const struct gl_pixelstore_attrib *unpack,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels )
+{
+ GLubyte rgb[MAX_WIDTH][3];
+ GLubyte rgba[MAX_WIDTH][4];
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, "glDrawPixels",
+ GL_FALSE);
+
+
+ if (!ctx->Current.RasterPosValid) {
+ /* no-op */
+ return GL_TRUE;
+ }
+
+ if (ctx->NewState) {
+ gl_update_state(ctx);
+ }
+
+ /* see if device driver can do the drawpix */
+ if (ctx->Driver.DrawPixels) {
+ GLint x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
+ GLint y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
+ if ((*ctx->Driver.DrawPixels)(ctx, x, y, width, height, format, type,
+ unpack, pixels))
+ return GL_TRUE;
+ }
+
+ if ((ctx->RasterMask&(~(SCISSOR_BIT|WINCLIP_BIT)))==0
+ && ctx->Pixel.RedBias==0.0 && ctx->Pixel.RedScale==1.0
+ && ctx->Pixel.GreenBias==0.0 && ctx->Pixel.GreenScale==1.0
+ && ctx->Pixel.BlueBias==0.0 && ctx->Pixel.BlueScale==1.0
+ && ctx->Pixel.AlphaBias==0.0 && ctx->Pixel.AlphaScale==1.0
+ && ctx->Pixel.IndexShift==0 && ctx->Pixel.IndexOffset==0
+ && ctx->Pixel.MapColorFlag==0
+ && unpack->Alignment==1
+ && !unpack->SwapBytes
+ && !unpack->LsbFirst) {
+
+ GLint destX = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
+ GLint destY = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
+ GLint drawWidth = width; /* actual width drawn */
+ GLint drawHeight = height; /* actual height drawn */
+ GLint skipPixels = unpack->SkipPixels;
+ GLint skipRows = unpack->SkipRows;
+ GLint rowLength;
+ GLdepth zSpan[MAX_WIDTH]; /* only used when zooming */
+ GLint zoomY0;
+
+ if (unpack->RowLength > 0)
+ rowLength = unpack->RowLength;
+ else
+ rowLength = width;
+
+ /* If we're not using pixel zoom then do all clipping calculations
+ * now. Otherwise, we'll let the gl_write_zoomed_*_span() functions
+ * handle the clipping.
+ */
+ if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
+ /* horizontal clipping */
+ if (destX < ctx->Buffer->Xmin) {
+ skipPixels += (ctx->Buffer->Xmin - destX);
+ drawWidth -= (ctx->Buffer->Xmin - destX);
+ destX = ctx->Buffer->Xmin;
+ }
+ if (destX + drawWidth > ctx->Buffer->Xmax)
+ drawWidth -= (destX + drawWidth - ctx->Buffer->Xmax - 1);
+ if (drawWidth <= 0)
+ return GL_TRUE;
+
+ /* vertical clipping */
+ if (destY < ctx->Buffer->Ymin) {
+ skipRows += (ctx->Buffer->Ymin - destY);
+ drawHeight -= (ctx->Buffer->Ymin - destY);
+ destY = ctx->Buffer->Ymin;
+ }
+ if (destY + drawHeight > ctx->Buffer->Ymax)
+ drawHeight -= (destY + drawHeight - ctx->Buffer->Ymax - 1);
+ if (drawHeight <= 0)
+ return GL_TRUE;
+ }
+ else {
+ /* setup array of fragment Z value to pass to zoom function */
+ GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
+ GLint i;
+ assert(drawWidth < MAX_WIDTH);
+ for (i=0; i<drawWidth; i++)
+ zSpan[i] = z;
+
+ /* save Y value of first row */
+ zoomY0 = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
+ }
+
+
+ /*
+ * Ready to draw!
+ * The window region at (destX, destY) of size (drawWidth, drawHeight)
+ * will be written to.
+ * We'll take pixel data from buffer pointed to by "pixels" but we'll
+ * skip "skipRows" rows and skip "skipPixels" pixels/row.
+ */
+
+ if (format==GL_RGBA && type==GL_UNSIGNED_BYTE) {
+ if (ctx->Visual->RGBAflag) {
+ GLubyte *src = (GLubyte *) pixels
+ + (skipRows * rowLength + skipPixels) * 4;
+ if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
+ /* no zooming */
+ GLint row;
+ for (row=0; row<drawHeight; row++) {
+ (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
+ (void *) src, NULL);
+ src += rowLength * 4;
+ destY++;
+ }
+ }
+ else {
+ /* with zooming */
+ GLint row;
+ for (row=0; row<drawHeight; row++) {
+ gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
+ zSpan, (void *) src, zoomY0);
+ src += rowLength * 4;
+ destY++;
+ }
+ }
+ }
+ return GL_TRUE;
+ }
+ else if (format==GL_RGB && type==GL_UNSIGNED_BYTE) {
+ if (ctx->Visual->RGBAflag) {
+ GLubyte *src = (GLubyte *) pixels
+ + (skipRows * rowLength + skipPixels) * 3;
+ if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
+ GLint row;
+ for (row=0; row<drawHeight; row++) {
+ (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
+ (void *) src, NULL);
+ src += rowLength * 3;
+ destY++;
+ }
+ }
+ else {
+ /* with zooming */
+ GLint row;
+ for (row=0; row<drawHeight; row++) {
+ gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY,
+ zSpan, (void *) src, zoomY0);
+ src += rowLength * 3;
+ destY++;
+ }
+ }
+ }
+ return GL_TRUE;
+ }
+ else if (format==GL_LUMINANCE && type==GL_UNSIGNED_BYTE) {
+ if (ctx->Visual->RGBAflag) {
+ GLubyte *src = (GLubyte *) pixels
+ + (skipRows * rowLength + skipPixels);
+ if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
+ /* no zooming */
+ GLint row;
+ assert(drawWidth < MAX_WIDTH);
+ for (row=0; row<drawHeight; row++) {
+ GLint i;
+ for (i=0;i<drawWidth;i++) {
+ rgb[i][0] = src[i];
+ rgb[i][1] = src[i];
+ rgb[i][2] = src[i];
+ }
+ (*ctx->Driver.WriteRGBSpan)(ctx, drawWidth, destX, destY,
+ (void *) rgb, NULL);
+ src += rowLength;
+ destY++;
+ }
+ }
+ else {
+ /* with zooming */
+ GLint row;
+ assert(drawWidth < MAX_WIDTH);
+ for (row=0; row<drawHeight; row++) {
+ GLint i;
+ for (i=0;i<drawWidth;i++) {
+ rgb[i][0] = src[i];
+ rgb[i][1] = src[i];
+ rgb[i][2] = src[i];
+ }
+ gl_write_zoomed_rgb_span(ctx, drawWidth, destX, destY,
+ zSpan, (void *) rgb, zoomY0);
+ src += rowLength;
+ destY++;
+ }
+ }
+ }
+ return GL_TRUE;
+ }
+ else if (format==GL_LUMINANCE_ALPHA && type==GL_UNSIGNED_BYTE) {
+ if (ctx->Visual->RGBAflag) {
+ GLubyte *src = (GLubyte *) pixels
+ + (skipRows * rowLength + skipPixels)*2;
+ if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
+ /* no zooming */
+ GLint row;
+ assert(drawWidth < MAX_WIDTH);
+ for (row=0; row<drawHeight; row++) {
+ GLint i;
+ GLubyte *ptr = src;
+ for (i=0;i<drawWidth;i++) {
+ rgba[i][0] = *ptr;
+ rgba[i][1] = *ptr;
+ rgba[i][2] = *ptr++;
+ rgba[i][3] = *ptr++;
+ }
+ (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
+ (void *) rgba, NULL);
+ src += rowLength*2;
+ destY++;
+ }
+ }
+ else {
+ /* with zooming */
+ GLint row;
+ assert(drawWidth < MAX_WIDTH);
+ for (row=0; row<drawHeight; row++) {
+ GLubyte *ptr = src;
+ GLint i;
+ for (i=0;i<drawWidth;i++) {
+ rgba[i][0] = *ptr;
+ rgba[i][1] = *ptr;
+ rgba[i][2] = *ptr++;
+ rgba[i][3] = *ptr++;
+ }
+ gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
+ zSpan, (void *) rgba, zoomY0);
+ src += rowLength*2;
+ destY++;
+ }
+ }
+ }
+ return GL_TRUE;
+ }
+ else if (format==GL_COLOR_INDEX && type==GL_UNSIGNED_BYTE) {
+ GLubyte *src = (GLubyte *) pixels + skipRows * rowLength + skipPixels;
+ if (ctx->Visual->RGBAflag) {
+ /* convert CI data to RGBA */
+ if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
+ /* no zooming */
+ GLint row;
+ for (row=0; row<drawHeight; row++) {
+ assert(drawWidth < MAX_WIDTH);
+ gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
+ (*ctx->Driver.WriteRGBASpan)(ctx, drawWidth, destX, destY,
+ (const GLubyte (*)[4])rgba,
+ NULL);
+ src += rowLength;
+ destY++;
+ }
+ return GL_TRUE;
+ }
+ else {
+ /* with zooming */
+ GLint row;
+ for (row=0; row<drawHeight; row++) {
+ assert(drawWidth < MAX_WIDTH);
+ gl_map_ci8_to_rgba(ctx, drawWidth, src, rgba);
+ gl_write_zoomed_rgba_span(ctx, drawWidth, destX, destY,
+ zSpan, (void *) rgba, zoomY0);
+ src += rowLength;
+ destY++;
+ }
+ return GL_TRUE;
+ }
+ }
+ else {
+ /* write CI data to CI frame buffer */
+ GLint row;
+ if (ctx->Pixel.ZoomX==1.0F && ctx->Pixel.ZoomY==1.0F) {
+ /* no zooming */
+ for (row=0; row<drawHeight; row++) {
+ (*ctx->Driver.WriteCI8Span)(ctx, drawWidth, destX, destY,
+ src, NULL);
+ src += rowLength;
+ destY++;
+ }
+ return GL_TRUE;
+ }
+ else {
+ /* with zooming */
+ return GL_FALSE;
+ }
+ }
+ }
+ else {
+ /* can't handle this pixel format and/or data type here */
+ return GL_FALSE;
+ }
+ }
+ else {
+ /* can't do direct render, have to use slow path */
+ return GL_FALSE;
+ }
+}
+
+
+
+/*
+ * Do glDrawPixels of index pixels.
+ */
+static void draw_index_pixels( GLcontext *ctx, GLint x, GLint y,
+ const struct gl_image *image )
+{
+ GLint width, height, widthInBytes;
+ const GLint desty = y;
+ GLint i, j;
+ GLdepth zspan[MAX_WIDTH];
+ const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
+
+ assert(image);
+ assert(image->Format == GL_COLOR_INDEX);
+
+ width = image->Width;
+ height = image->Height;
+ if (image->Type == GL_BITMAP)
+ widthInBytes = (width + 7) / 8;
+ else
+ widthInBytes = width;
+
+ /* Fragment depth values */
+ if (ctx->Depth.Test) {
+ GLdepth zval = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
+ for (i=0;i<width;i++) {
+ zspan[i] = zval;
+ }
+ }
+
+ /* process the image row by row */
+ for (i=0;i<height;i++,y++) {
+ GLuint ispan[MAX_WIDTH];
+
+ /* convert to uints */
+ switch (image->Type) {
+ case GL_UNSIGNED_BYTE:
+ {
+ GLubyte *src = (GLubyte *) image->Data + i * width;
+ for (j=0;j<width;j++) {
+ ispan[j] = (GLuint) *src++;
+ }
+ }
+ break;
+ case GL_FLOAT:
+ {
+ GLfloat *src = (GLfloat *) image->Data + i * width;
+ for (j=0;j<width;j++) {
+ ispan[j] = (GLuint) (GLint) *src++;
+ }
+ }
+ break;
+ case GL_BITMAP:
+ {
+ GLubyte *src = (GLubyte *) image->Data + i * widthInBytes;
+ for (j=0;j<width;j++) {
+ ispan[j] = ( src[j >> 3] >> (7 - (j & 0x7)) ) & 1;
+ }
+ }
+ break;
+ default:
+ gl_problem( ctx, "draw_index_pixels type" );
+ return;
+ }
+
+ /* apply shift and offset */
+ if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift) {
+ gl_shift_and_offset_ci( ctx, width, ispan );
+ }
+
+ if (ctx->Visual->RGBAflag) {
+ /* Convert index to RGBA and write to frame buffer */
+ GLubyte rgba[MAX_WIDTH][4];
+ gl_map_ci_to_rgba( ctx, width, ispan, rgba );
+ if (zoom) {
+ gl_write_zoomed_rgba_span( ctx, width, x, y, zspan,
+ (const GLubyte (*)[4])rgba, desty );
+ }
+ else {
+ gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
+ }
+ }
+ else {
+ /* optionally apply index map then write to frame buffer */
+ if (ctx->Pixel.MapColorFlag) {
+ gl_map_ci(ctx, width, ispan);
+ }
+ if (zoom) {
+ gl_write_zoomed_index_span( ctx, width, x, y, zspan, ispan, desty );
+ }
+ else {
+ gl_write_index_span( ctx, width, x, y, zspan, ispan, GL_BITMAP );
+ }
+ }
+ }
+
+}
+
+
+
+/*
+ * Do glDrawPixels of stencil image. The image datatype may either
+ * be GLubyte or GLbitmap.
+ */
+static void draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y,
+ const struct gl_image *image )
+{
+ GLint widthInBytes, width, height;
+ const GLint desty = y;
+ GLint i;
+ const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
+
+ assert(image);
+ assert(image->Format == GL_STENCIL_INDEX);
+ assert(image->Type == GL_UNSIGNED_BYTE || image->Type == GL_BITMAP);
+
+ if (image->Type == GL_UNSIGNED_BYTE)
+ widthInBytes = image->Width;
+ else
+ widthInBytes = (image->Width + 7) / 8;
+ width = image->Width;
+ height = image->Height;
+
+ /* process the image row by row */
+ for (i=0;i<height;i++,y++) {
+ GLstencil *src = (GLstencil*)image->Data + i * widthInBytes;
+ GLstencil *stencilValues;
+ GLstencil stencilCopy[MAX_WIDTH];
+
+ if (image->Type == GL_BITMAP) {
+ /* convert bitmap data to GLubyte (0 or 1) data */
+ GLint j;
+ for (j = 0; j < width; j++) {
+ stencilCopy[j] = ( src[j >> 3] >> (7 - (j & 0x7)) ) & 1;
+ }
+ src = stencilCopy;
+ }
+
+ if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift
+ || ctx->Pixel.MapStencilFlag) {
+
+ /* make copy of stencil values */
+ if (src != stencilCopy)
+ MEMCPY( stencilCopy, src, width * sizeof(GLstencil));
+
+ /* apply shift and offset */
+ if (ctx->Pixel.IndexOffset || ctx->Pixel.IndexShift) {
+ gl_shift_and_offset_stencil( ctx, width, stencilCopy );
+ }
+
+ /* mapping */
+ if (ctx->Pixel.MapStencilFlag) {
+ gl_map_stencil( ctx, width, stencilCopy );
+ }
+
+ stencilValues = stencilCopy;
+ }
+ else {
+ /* use stencil values in-place */
+ stencilValues = src;
+ }
+
+ /* write stencil values to stencil buffer */
+ if (zoom) {
+ gl_write_zoomed_stencil_span( ctx, (GLuint) width, x, y,
+ stencilValues, desty );
+ }
+ else {
+ gl_write_stencil_span( ctx, (GLuint) width, x, y, stencilValues );
+ }
+ }
+}
+
+
+
+/*
+ * Do a glDrawPixels of depth values.
+ */
+static void draw_depth_pixels( GLcontext *ctx, GLint x, GLint y,
+ const struct gl_image *image )
+{
+ GLint width, height;
+ const GLint desty = y;
+ GLubyte rgba[MAX_WIDTH][4];
+ GLuint ispan[MAX_WIDTH];
+ const GLboolean bias_or_scale = ctx->Pixel.DepthBias!=0.0 || ctx->Pixel.DepthScale!=1.0;
+ const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
+
+ assert(image);
+ assert(image->Format == GL_DEPTH_COMPONENT);
+
+ width = image->Width;
+ height = image->Height;
+
+ /* Color or index */
+ if (ctx->Visual->RGBAflag) {
+ GLint r = (GLint) (ctx->Current.RasterColor[0] * 255.0F);
+ GLint g = (GLint) (ctx->Current.RasterColor[1] * 255.0F);
+ GLint b = (GLint) (ctx->Current.RasterColor[2] * 255.0F);
+ GLint a = (GLint) (ctx->Current.RasterColor[3] * 255.0F);
+ GLint i;
+ for (i=0; i<width; i++) {
+ rgba[i][RCOMP] = r;
+ rgba[i][GCOMP] = g;
+ rgba[i][BCOMP] = b;
+ rgba[i][ACOMP] = a;
+ }
+ }
+ else {
+ GLint i;
+ for (i=0;i<width;i++) {
+ ispan[i] = ctx->Current.RasterIndex;
+ }
+ }
+
+ if (image->Type==GL_UNSIGNED_SHORT && sizeof(GLdepth)==sizeof(GLushort)
+ && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) {
+ /* Special case: directly write 16-bit depth values */
+ GLint j;
+ for (j=0;j<height;j++,y++) {
+ GLdepth *zptr = (GLdepth *) image->Data + j * width;
+ gl_write_rgba_span( ctx, width, x, y, zptr, rgba, GL_BITMAP );
+ }
+ }
+ else if (image->Type==GL_UNSIGNED_INT && sizeof(GLdepth)==sizeof(GLuint)
+ && !bias_or_scale && !zoom && ctx->Visual->RGBAflag) {
+ /* Special case: directly write 32-bit depth values */
+ GLint i, j;
+ /* Compute shift value to scale 32-bit uints down to depth values. */
+ GLuint shift = 0;
+ GLuint max = MAX_DEPTH;
+ while ((max&0x80000000)==0) {
+ max = max << 1;
+ shift++;
+ }
+ for (j=0;j<height;j++,y++) {
+ GLdepth zspan[MAX_WIDTH];
+ GLuint *zptr = (GLuint *) image->Data + j * width;
+ for (i=0;i<width;i++) {
+ zspan[i] = zptr[i] >> shift;
+ }
+ gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
+ }
+ }
+ else {
+ /* General case (slower) */
+ GLint i, j;
+
+ /* process image row by row */
+ for (i=0;i<height;i++,y++) {
+ GLfloat depth[MAX_WIDTH];
+ GLdepth zspan[MAX_WIDTH];
+
+ switch (image->Type) {
+ case GL_UNSIGNED_SHORT:
+ {
+ GLushort *src = (GLushort *) image->Data + i * width;
+ for (j=0;j<width;j++) {
+ depth[j] = USHORT_TO_FLOAT( *src++ );
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ {
+ GLuint *src = (GLuint *) image->Data + i * width;
+ for (j=0;j<width;j++) {
+ depth[j] = UINT_TO_FLOAT( *src++ );
+ }
+ }
+ break;
+ case GL_FLOAT:
+ {
+ GLfloat *src = (GLfloat *) image->Data + i * width;
+ for (j=0;j<width;j++) {
+ depth[j] = *src++;
+ }
+ }
+ break;
+ default:
+ gl_problem(ctx, "Bad type in draw_depth_pixels");
+ return;
+ }
+
+ /* apply depth scale and bias */
+ if (ctx->Pixel.DepthScale!=1.0 || ctx->Pixel.DepthBias!=0.0) {
+ for (j=0;j<width;j++) {
+ depth[j] = depth[j] * ctx->Pixel.DepthScale + ctx->Pixel.DepthBias;
+ }
+ }
+
+ /* clamp depth values to [0,1] and convert from floats to integers */
+ for (j=0;j<width;j++) {
+ zspan[j] = (GLdepth) (CLAMP( depth[j], 0.0F, 1.0F ) * DEPTH_SCALE);
+ }
+
+ if (ctx->Visual->RGBAflag) {
+ if (zoom) {
+ gl_write_zoomed_rgba_span( ctx, width, x, y, zspan,
+ (const GLubyte (*)[4])rgba, desty );
+ }
+ else {
+ gl_write_rgba_span( ctx, width, x, y, zspan, rgba, GL_BITMAP );
+ }
+ }
+ else {
+ if (zoom) {
+ gl_write_zoomed_index_span( ctx, width, x, y, zspan,
+ ispan, GL_BITMAP );
+ }
+ else {
+ gl_write_index_span( ctx, width, x, y, zspan, ispan, GL_BITMAP );
+ }
+ }
+
+ }
+ }
+}
+
+
+
+/* Simple unpacking parameters: */
+static struct gl_pixelstore_attrib NoUnpack = {
+ 1, /* Alignment */
+ 0, /* RowLength */
+ 0, /* SkipPixels */
+ 0, /* SkipRows */
+ 0, /* ImageHeight */
+ 0, /* SkipImages */
+ GL_FALSE, /* SwapBytes */
+ GL_FALSE /* LsbFirst */
+};
+
+
+/*
+ * Do glDrawPixels of RGBA pixels.
+ */
+static void draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y,
+ const struct gl_image *image )
+{
+ GLint width, height;
+ GLint i, j;
+ const GLint desty = y;
+ GLdepth zspan[MAX_WIDTH];
+ GLboolean quickDraw;
+ const GLboolean zoom = ctx->Pixel.ZoomX!=1.0 || ctx->Pixel.ZoomY!=1.0;
+
+ assert(image);
+
+ /* Try an optimized glDrawPixels first */
+ if (gl_direct_DrawPixels(ctx, &NoUnpack, image->Width, image->Height,
+ image->Format, image->Type, image->Data ))
+ return;
+
+ width = image->Width;
+ height = image->Height;
+
+ /* Fragment depth values */
+ if (ctx->Depth.Test) {
+ /* fill in array of z values */
+ GLdepth z = (GLdepth) (ctx->Current.RasterPos[2] * DEPTH_SCALE);
+ for (i=0;i<width;i++) {
+ zspan[i] = z;
+ }
+ }
+
+ if (ctx->RasterMask==0 && !zoom && x>=0 && y>=0
+ && x+width<=ctx->Buffer->Width && y+height<=ctx->Buffer->Height) {
+ quickDraw = GL_TRUE;
+ }
+ else {
+ quickDraw = GL_FALSE;
+ }
+
+ {
+ /* General solution */
+ GLboolean r_flag, g_flag, b_flag, a_flag, l_flag;
+ GLuint components;
+ GLubyte rgba[MAX_WIDTH][4];
+ GLfloat rf[MAX_WIDTH];
+ GLfloat gf[MAX_WIDTH];
+ GLfloat bf[MAX_WIDTH];
+ DEFARRAY(GLfloat,af,MAX_WIDTH);
+ CHECKARRAY(af,return);
+
+ r_flag = g_flag = b_flag = a_flag = l_flag = GL_FALSE;
+ switch (image->Format) {
+ case GL_RED:
+ r_flag = GL_TRUE;
+ components = 1;
+ break;
+ case GL_GREEN:
+ g_flag = GL_TRUE;
+ components = 1;
+ break;
+ case GL_BLUE:
+ b_flag = GL_TRUE;
+ components = 1;
+ break;
+ case GL_ALPHA:
+ a_flag = GL_TRUE;
+ components = 1;
+ break;
+ case GL_RGB:
+ r_flag = g_flag = b_flag = GL_TRUE;
+ components = 3;
+ break;
+ case GL_LUMINANCE:
+ l_flag = GL_TRUE;
+ components = 1;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ l_flag = a_flag = GL_TRUE;
+ components = 2;
+ break;
+ case GL_RGBA:
+ r_flag = g_flag = b_flag = a_flag = GL_TRUE;
+ components = 4;
+ break;
+ default:
+ gl_problem(ctx, "Bad type in draw_rgba_pixels");
+ goto cleanup;
+ }
+
+ /* process the image row by row */
+ for (i=0;i<height;i++,y++) {
+ /* convert to floats */
+ switch (image->Type) {
+ case GL_UNSIGNED_BYTE:
+ {
+ GLubyte *src = (GLubyte *) image->Data + i * width * components;
+ for (j=0;j<width;j++) {
+ if (l_flag) {
+ rf[j] = gf[j] = bf[j] = UBYTE_TO_FLOAT(*src++);
+ }
+ else {
+ rf[j] = r_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
+ gf[j] = g_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
+ bf[j] = b_flag ? UBYTE_TO_FLOAT(*src++) : 0.0;
+ }
+ af[j] = a_flag ? UBYTE_TO_FLOAT(*src++) : 1.0;
+ }
+ }
+ break;
+ case GL_FLOAT:
+ {
+ GLfloat *src = (GLfloat *) image->Data + i * width * components;
+ for (j=0;j<width;j++) {
+ if (l_flag) {
+ rf[j] = gf[j] = bf[j] = *src++;
+ }
+ else {
+ rf[j] = r_flag ? *src++ : 0.0;
+ gf[j] = g_flag ? *src++ : 0.0;
+ bf[j] = b_flag ? *src++ : 0.0;
+ }
+ af[j] = a_flag ? *src++ : 1.0;
+ }
+ }
+ break;
+ default:
+ gl_problem( ctx, "draw_rgba_pixels type" );
+ goto cleanup;
+ }
+
+ /* apply scale and bias */
+ if (ctx->Pixel.ScaleOrBiasRGBA) {
+ gl_scale_and_bias_color(ctx, width, rf, gf, bf, af);
+ }
+
+ /* apply pixel mappings */
+ if (ctx->Pixel.MapColorFlag) {
+ gl_map_color(ctx, width, rf, gf, bf, af);
+ }
+
+ /* convert to integers */
+ for (j=0;j<width;j++) {
+ rgba[j][RCOMP] = (GLint) (rf[j] * 255.0F);
+ rgba[j][GCOMP] = (GLint) (gf[j] * 255.0F);
+ rgba[j][BCOMP] = (GLint) (bf[j] * 255.0F);
+ rgba[j][ACOMP] = (GLint) (af[j] * 255.0F);
+ }
+
+ /* write to frame buffer */
+ if (quickDraw) {
+ (*ctx->Driver.WriteRGBASpan)( ctx, width, x, y,
+ (const GLubyte (*)[4])rgba, NULL);
+ }
+ else if (zoom) {
+ gl_write_zoomed_rgba_span( ctx, width, x, y, zspan,
+ (const GLubyte (*)[4])rgba, desty );
+ }
+ else {
+ gl_write_rgba_span( ctx, (GLuint) width, x, y, zspan, rgba, GL_BITMAP);
+ }
+ }
+cleanup:
+ UNDEFARRAY(af);
+ }
+}
+
+
+
+/*
+ * Execute glDrawPixels
+ */
+void gl_DrawPixels( GLcontext* ctx, struct gl_image *image )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawPixels");
+
+
+ if (gl_image_error_test( ctx, image, "glDrawPixels" ))
+ return;
+
+ if (ctx->RenderMode==GL_RENDER) {
+ GLint x, y;
+ if (!ctx->Current.RasterPosValid) {
+ return;
+ }
+
+ x = (GLint) (ctx->Current.RasterPos[0] + 0.5F);
+ y = (GLint) (ctx->Current.RasterPos[1] + 0.5F);
+
+ switch (image->Format) {
+ case GL_COLOR_INDEX:
+ draw_index_pixels( ctx, x, y, image );
+ break;
+ case GL_STENCIL_INDEX:
+ draw_stencil_pixels( ctx, x, y, image );
+ break;
+ case GL_DEPTH_COMPONENT:
+ draw_depth_pixels( ctx, x, y, image );
+ break;
+ case GL_RED:
+ case GL_GREEN:
+ case GL_BLUE:
+ case GL_ALPHA:
+ case GL_RGB:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_RGBA:
+ draw_rgba_pixels( ctx, x, y, image );
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glDrawPixels" );
+ return;
+ }
+ }
+ else if (ctx->RenderMode==GL_FEEDBACK) {
+ if (ctx->Current.RasterPosValid) {
+ GLfloat color[4];
+ GLfloat texcoord[4], invq;
+ UBYTE_RGBA_TO_FLOAT_RGBA(color, ctx->Current.ByteColor);
+ invq = 1.0F / ctx->Current.Texcoord[0][3];
+ texcoord[0] = ctx->Current.Texcoord[0][0] * invq;
+ texcoord[1] = ctx->Current.Texcoord[0][1] * invq;
+ texcoord[2] = ctx->Current.Texcoord[0][2] * invq;
+ texcoord[3] = ctx->Current.Texcoord[0][3];
+ FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_DRAW_PIXEL_TOKEN );
+ gl_feedback_vertex( ctx,
+ ctx->Current.RasterPos[0],
+ ctx->Current.RasterPos[1],
+ ctx->Current.RasterPos[2],
+ ctx->Current.RasterPos[3],
+ color, ctx->Current.Index, texcoord );
+ }
+ }
+ else if (ctx->RenderMode==GL_SELECT) {
+ if (ctx->Current.RasterPosValid) {
+ gl_update_hitflag( ctx, ctx->Current.RasterPos[2] );
+ }
+ }
+}
+
diff --git a/src/mesa/main/drawpix.h b/src/mesa/main/drawpix.h
new file mode 100644
index 0000000000..cb517ced03
--- /dev/null
+++ b/src/mesa/main/drawpix.h
@@ -0,0 +1,54 @@
+/* $Id: drawpix.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef DRAWPIXELS_H
+#define DRAWPIXELS_H
+
+
+#include "types.h"
+
+
+extern GLboolean
+gl_direct_DrawPixels( GLcontext *ctx,
+ const struct gl_pixelstore_attrib *unpack,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type, const GLvoid *pixels );
+
+
+#if 000
+extern void gl_DrawPixels( GLcontext *ctx, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, const GLvoid *pixels );
+#endif
+
+
+extern void gl_DrawPixels( GLcontext *ctx, struct gl_image *image );
+
+
+#endif
diff --git a/src/mesa/main/enable.c b/src/mesa/main/enable.c
new file mode 100644
index 0000000000..7f661fb75f
--- /dev/null
+++ b/src/mesa/main/enable.c
@@ -0,0 +1,699 @@
+/* $Id: enable.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <string.h>
+#include <stdio.h>
+#include "context.h"
+#include "enable.h"
+#include "light.h"
+#include "macros.h"
+#include "matrix.h"
+#include "mmath.h"
+#include "simple_list.h"
+#include "types.h"
+#include "vbfill.h"
+#include "xform.h"
+#include "enums.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+
+/*
+ * Perform glEnable and glDisable calls.
+ */
+void gl_set_enable( GLcontext *ctx, GLenum cap, GLboolean state )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx, "gl_enable/disable" );
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ fprintf(stderr, "%s %s (%x)\n",
+ state ? "glEnable" : "glDisable",
+ gl_lookup_enum_by_nr(cap),
+ ctx->NewState);
+
+ switch (cap) {
+ case GL_ALPHA_TEST:
+ if (ctx->Color.AlphaEnabled!=state) {
+ ctx->Color.AlphaEnabled = state;
+ ctx->NewState |= NEW_RASTER_OPS;
+ }
+ break;
+ case GL_AUTO_NORMAL:
+ ctx->Eval.AutoNormal = state;
+ break;
+ case GL_BLEND:
+ if (ctx->Color.BlendEnabled!=state) {
+ ctx->Color.BlendEnabled = state;
+ /* The following needed to accomodate 1.0 RGB logic op blending */
+ if (ctx->Color.BlendEquation==GL_LOGIC_OP && state) {
+ ctx->Color.ColorLogicOpEnabled = GL_TRUE;
+ }
+ else {
+ ctx->Color.ColorLogicOpEnabled = GL_FALSE;
+ }
+ ctx->NewState |= NEW_RASTER_OPS;
+ }
+ 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:
+ if (cap >= GL_CLIP_PLANE0 &&
+ cap <= GL_CLIP_PLANE5 &&
+ ctx->Transform.ClipEnabled[cap-GL_CLIP_PLANE0] != state)
+ {
+ GLuint p = cap-GL_CLIP_PLANE0;
+
+ ctx->Transform.ClipEnabled[p] = state;
+ ctx->NewState |= NEW_USER_CLIP;
+
+ if (state) {
+ ctx->Enabled |= ENABLE_USERCLIP;
+ ctx->Transform.AnyClip++;
+
+ if (ctx->ProjectionMatrix.flags & MAT_DIRTY_ALL_OVER) {
+ gl_matrix_analyze( &ctx->ProjectionMatrix );
+ }
+
+ gl_transform_vector( ctx->Transform.ClipUserPlane[p],
+ ctx->Transform.EyeUserPlane[p],
+ ctx->ProjectionMatrix.inv );
+ } else {
+ if (--ctx->Transform.AnyClip == 0)
+ ctx->Enabled &= ~ENABLE_USERCLIP;
+ }
+ }
+ break;
+ case GL_COLOR_MATERIAL:
+ if (ctx->Light.ColorMaterialEnabled!=state) {
+ ctx->Light.ColorMaterialEnabled = state;
+ ctx->NewState |= NEW_LIGHTING;
+ }
+ break;
+ case GL_CULL_FACE:
+ if (ctx->Polygon.CullFlag!=state) {
+ ctx->Polygon.CullFlag = state;
+ ctx->TriangleCaps ^= DD_TRI_CULL;
+ ctx->NewState |= NEW_POLYGON;
+ }
+ break;
+ case GL_DEPTH_TEST:
+ if (state && ctx->Visual->DepthBits==0) {
+ gl_warning(ctx,"glEnable(GL_DEPTH_TEST) but no depth buffer");
+ return;
+ }
+ if (ctx->Depth.Test!=state) {
+ ctx->Depth.Test = state;
+ ctx->NewState |= NEW_RASTER_OPS;
+ }
+ break;
+ case GL_DITHER:
+ if (ctx->NoDither) {
+ /* MESA_NO_DITHER env var */
+ state = GL_FALSE;
+ }
+ if (ctx->Color.DitherFlag!=state) {
+ ctx->Color.DitherFlag = state;
+ ctx->NewState |= NEW_RASTER_OPS;
+ }
+ break;
+ case GL_FOG:
+ if (ctx->Fog.Enabled!=state) {
+ ctx->Fog.Enabled = state;
+ ctx->Enabled ^= ENABLE_FOG;
+ ctx->NewState |= NEW_FOG;
+ }
+ 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:
+ if (ctx->Light.Light[cap-GL_LIGHT0].Enabled != state)
+ {
+ ctx->Light.Light[cap-GL_LIGHT0].Enabled = state;
+
+ if (state) {
+ insert_at_tail(&ctx->Light.EnabledList,
+ &ctx->Light.Light[cap-GL_LIGHT0]);
+ if (ctx->Light.Enabled)
+ ctx->Enabled |= ENABLE_LIGHT;
+ } else {
+ remove_from_list(&ctx->Light.Light[cap-GL_LIGHT0]);
+ if (is_empty_list(&ctx->Light.EnabledList))
+ ctx->Enabled &= ~ENABLE_LIGHT;
+ }
+
+ ctx->NewState |= NEW_LIGHTING;
+ }
+ break;
+ case GL_LIGHTING:
+ if (ctx->Light.Enabled!=state) {
+ ctx->Light.Enabled = state;
+ ctx->Enabled &= ~ENABLE_LIGHT;
+ if (state && !is_empty_list(&ctx->Light.EnabledList))
+ ctx->Enabled |= ENABLE_LIGHT;
+ ctx->NewState |= NEW_LIGHTING;
+ }
+ break;
+ case GL_LINE_SMOOTH:
+ if (ctx->Line.SmoothFlag!=state) {
+ ctx->Line.SmoothFlag = state;
+ ctx->NewState |= NEW_RASTER_OPS;
+ }
+ break;
+ case GL_LINE_STIPPLE:
+ if (ctx->Line.StippleFlag!=state) {
+ ctx->Line.StippleFlag = state;
+ ctx->TriangleCaps ^= DD_LINE_STIPPLE;
+ ctx->NewState |= NEW_RASTER_OPS;
+ }
+ break;
+ case GL_INDEX_LOGIC_OP:
+ if (ctx->Color.IndexLogicOpEnabled!=state) {
+ ctx->Color.IndexLogicOpEnabled = state;
+ ctx->NewState |= NEW_RASTER_OPS;
+ }
+ break;
+ case GL_COLOR_LOGIC_OP:
+ if (ctx->Color.ColorLogicOpEnabled!=state) {
+ ctx->Color.ColorLogicOpEnabled = state;
+ ctx->NewState |= NEW_RASTER_OPS;
+ }
+ break;
+ case GL_MAP1_COLOR_4:
+ ctx->Eval.Map1Color4 = state;
+ break;
+ case GL_MAP1_INDEX:
+ ctx->Eval.Map1Index = state;
+ break;
+ case GL_MAP1_NORMAL:
+ ctx->Eval.Map1Normal = state;
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ ctx->Eval.Map1TextureCoord1 = state;
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ ctx->Eval.Map1TextureCoord2 = state;
+ break;
+ case GL_MAP1_TEXTURE_COORD_3:
+ ctx->Eval.Map1TextureCoord3 = state;
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ ctx->Eval.Map1TextureCoord4 = state;
+ break;
+ case GL_MAP1_VERTEX_3:
+ ctx->Eval.Map1Vertex3 = state;
+ break;
+ case GL_MAP1_VERTEX_4:
+ ctx->Eval.Map1Vertex4 = state;
+ break;
+ case GL_MAP2_COLOR_4:
+ ctx->Eval.Map2Color4 = state;
+ break;
+ case GL_MAP2_INDEX:
+ ctx->Eval.Map2Index = state;
+ break;
+ case GL_MAP2_NORMAL:
+ ctx->Eval.Map2Normal = state;
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ ctx->Eval.Map2TextureCoord1 = state;
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ ctx->Eval.Map2TextureCoord2 = state;
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ ctx->Eval.Map2TextureCoord3 = state;
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ ctx->Eval.Map2TextureCoord4 = state;
+ break;
+ case GL_MAP2_VERTEX_3:
+ ctx->Eval.Map2Vertex3 = state;
+ break;
+ case GL_MAP2_VERTEX_4:
+ ctx->Eval.Map2Vertex4 = state;
+ break;
+ case GL_NORMALIZE:
+ if (ctx->Transform.Normalize != state) {
+ ctx->Transform.Normalize = state;
+ ctx->NewState |= NEW_NORMAL_TRANSFORM|NEW_LIGHTING;
+ ctx->Enabled ^= ENABLE_NORMALIZE;
+ }
+ break;
+ case GL_POINT_SMOOTH:
+ if (ctx->Point.SmoothFlag!=state) {
+ ctx->Point.SmoothFlag = state;
+ ctx->NewState |= NEW_RASTER_OPS;
+ }
+ break;
+ case GL_POLYGON_SMOOTH:
+ if (ctx->Polygon.SmoothFlag!=state) {
+ ctx->Polygon.SmoothFlag = state;
+ ctx->NewState |= NEW_RASTER_OPS;
+ }
+ break;
+ case GL_POLYGON_STIPPLE:
+ if (ctx->Polygon.StippleFlag!=state) {
+ ctx->Polygon.StippleFlag = state;
+ ctx->TriangleCaps ^= DD_TRI_STIPPLE;
+ ctx->NewState |= NEW_RASTER_OPS;
+ }
+ break;
+ case GL_POLYGON_OFFSET_POINT:
+ if (ctx->Polygon.OffsetPoint!=state) {
+ ctx->Polygon.OffsetPoint = state;
+ ctx->NewState |= NEW_POLYGON;
+ }
+ break;
+ case GL_POLYGON_OFFSET_LINE:
+ if (ctx->Polygon.OffsetLine!=state) {
+ ctx->Polygon.OffsetLine = state;
+ ctx->NewState |= NEW_POLYGON;
+ }
+ break;
+ case GL_POLYGON_OFFSET_FILL:
+ /*case GL_POLYGON_OFFSET_EXT:*/
+ if (ctx->Polygon.OffsetFill!=state) {
+ ctx->Polygon.OffsetFill = state;
+ ctx->NewState |= NEW_POLYGON;
+ }
+ break;
+ case GL_RESCALE_NORMAL_EXT:
+ if (ctx->Transform.RescaleNormals != state) {
+ ctx->Transform.RescaleNormals = state;
+ ctx->NewState |= NEW_NORMAL_TRANSFORM|NEW_LIGHTING;
+ ctx->Enabled ^= ENABLE_RESCALE;
+ }
+ break;
+ case GL_SCISSOR_TEST:
+ if (ctx->Scissor.Enabled!=state) {
+ ctx->Scissor.Enabled = state;
+ ctx->NewState |= NEW_RASTER_OPS;
+ }
+ break;
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ ctx->Texture.SharedPalette = state;
+ if (ctx->Driver.UseGlobalTexturePalette)
+ (*ctx->Driver.UseGlobalTexturePalette)( ctx, state );
+ break;
+ case GL_STENCIL_TEST:
+ if (state && ctx->Visual->StencilBits==0) {
+ gl_warning(ctx, "glEnable(GL_STENCIL_TEST) but no stencil buffer");
+ return;
+ }
+ if (ctx->Stencil.Enabled!=state) {
+ ctx->Stencil.Enabled = state;
+ ctx->NewState |= NEW_RASTER_OPS;
+ }
+ break;
+ case GL_TEXTURE_1D:
+ if (ctx->Visual->RGBAflag) {
+ const GLuint curr = ctx->Texture.CurrentUnit;
+ const GLuint flag = TEXTURE0_1D << (curr * 4);
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[curr];
+ ctx->NewState |= NEW_TEXTURE_ENABLE;
+ if (state) {
+ texUnit->Enabled |= TEXTURE0_1D;
+ ctx->Enabled |= flag;
+ }
+ else {
+ texUnit->Enabled &= ~TEXTURE0_1D;
+ ctx->Enabled &= ~flag;
+ }
+ }
+ break;
+ case GL_TEXTURE_2D:
+ if (ctx->Visual->RGBAflag) {
+ const GLuint curr = ctx->Texture.CurrentUnit;
+ const GLuint flag = TEXTURE0_2D << (curr * 4);
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[curr];
+ ctx->NewState |= NEW_TEXTURE_ENABLE;
+ if (state) {
+ texUnit->Enabled |= TEXTURE0_2D;
+ ctx->Enabled |= flag;
+ }
+ else {
+ texUnit->Enabled &= ~TEXTURE0_2D;
+ ctx->Enabled &= ~flag;
+ }
+ }
+ break;
+ case GL_TEXTURE_3D:
+ if (ctx->Visual->RGBAflag) {
+ const GLuint curr = ctx->Texture.CurrentUnit;
+ const GLuint flag = TEXTURE0_3D << (curr * 4);
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[curr];
+ ctx->NewState |= NEW_TEXTURE_ENABLE;
+ if (state) {
+ texUnit->Enabled |= TEXTURE0_3D;
+ ctx->Enabled |= flag;
+ }
+ else {
+ texUnit->Enabled &= ~TEXTURE0_3D;
+ ctx->Enabled &= ~flag;
+ }
+ }
+ break;
+ case GL_TEXTURE_GEN_Q:
+ {
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ if (state)
+ texUnit->TexGenEnabled |= Q_BIT;
+ else
+ texUnit->TexGenEnabled &= ~Q_BIT;
+ ctx->NewState |= NEW_TEXTURING;
+ }
+ break;
+ case GL_TEXTURE_GEN_R:
+ {
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ if (state)
+ texUnit->TexGenEnabled |= R_BIT;
+ else
+ texUnit->TexGenEnabled &= ~R_BIT;
+ ctx->NewState |= NEW_TEXTURING;
+ }
+ break;
+ case GL_TEXTURE_GEN_S:
+ {
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ if (state)
+ texUnit->TexGenEnabled |= S_BIT;
+ else
+ texUnit->TexGenEnabled &= ~S_BIT;
+ ctx->NewState |= NEW_TEXTURING;
+ }
+ break;
+ case GL_TEXTURE_GEN_T:
+ {
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ if (state)
+ texUnit->TexGenEnabled |= T_BIT;
+ else
+ texUnit->TexGenEnabled &= ~T_BIT;
+ ctx->NewState |= NEW_TEXTURING;
+ }
+ break;
+
+ /*
+ * CLIENT STATE!!!
+ */
+ case GL_VERTEX_ARRAY:
+ ctx->Array.Vertex.Enabled = state;
+ break;
+ case GL_NORMAL_ARRAY:
+ ctx->Array.Normal.Enabled = state;
+ break;
+ case GL_COLOR_ARRAY:
+ ctx->Array.Color.Enabled = state;
+ break;
+ case GL_INDEX_ARRAY:
+ ctx->Array.Index.Enabled = state;
+ break;
+ case GL_TEXTURE_COORD_ARRAY:
+ ctx->Array.TexCoord[ctx->TexCoordUnit].Enabled = state;
+ break;
+ case GL_EDGE_FLAG_ARRAY:
+ ctx->Array.EdgeFlag.Enabled = state;
+ break;
+
+ default:
+ if (state) {
+ gl_error( ctx, GL_INVALID_ENUM, "glEnable" );
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM, "glDisable" );
+ }
+ return;
+ }
+
+ if (ctx->Driver.Enable) {
+ (*ctx->Driver.Enable)( ctx, cap, state );
+ }
+}
+
+
+
+
+void gl_Enable( GLcontext* ctx, GLenum cap )
+{
+ gl_set_enable( ctx, cap, GL_TRUE );
+}
+
+
+
+void gl_Disable( GLcontext* ctx, GLenum cap )
+{
+ gl_set_enable( ctx, cap, GL_FALSE );
+}
+
+
+
+GLboolean gl_IsEnabled( GLcontext* ctx, GLenum cap )
+{
+ switch (cap) {
+ case GL_ALPHA_TEST:
+ return ctx->Color.AlphaEnabled;
+ case GL_AUTO_NORMAL:
+ return ctx->Eval.AutoNormal;
+ case GL_BLEND:
+ return ctx->Color.BlendEnabled;
+ case GL_CLIP_PLANE0:
+ case GL_CLIP_PLANE1:
+ case GL_CLIP_PLANE2:
+ case GL_CLIP_PLANE3:
+ case GL_CLIP_PLANE4:
+ case GL_CLIP_PLANE5:
+ return ctx->Transform.ClipEnabled[cap-GL_CLIP_PLANE0];
+ case GL_COLOR_MATERIAL:
+ return ctx->Light.ColorMaterialEnabled;
+ case GL_CULL_FACE:
+ return ctx->Polygon.CullFlag;
+ case GL_DEPTH_TEST:
+ return ctx->Depth.Test;
+ case GL_DITHER:
+ return ctx->Color.DitherFlag;
+ case GL_FOG:
+ return ctx->Fog.Enabled;
+ case GL_LIGHTING:
+ return ctx->Light.Enabled;
+ case GL_LIGHT0:
+ case GL_LIGHT1:
+ case GL_LIGHT2:
+ case GL_LIGHT3:
+ case GL_LIGHT4:
+ case GL_LIGHT5:
+ case GL_LIGHT6:
+ case GL_LIGHT7:
+ return ctx->Light.Light[cap-GL_LIGHT0].Enabled;
+ case GL_LINE_SMOOTH:
+ return ctx->Line.SmoothFlag;
+ case GL_LINE_STIPPLE:
+ return ctx->Line.StippleFlag;
+ case GL_INDEX_LOGIC_OP:
+ return ctx->Color.IndexLogicOpEnabled;
+ case GL_COLOR_LOGIC_OP:
+ return ctx->Color.ColorLogicOpEnabled;
+ case GL_MAP1_COLOR_4:
+ return ctx->Eval.Map1Color4;
+ case GL_MAP1_INDEX:
+ return ctx->Eval.Map1Index;
+ case GL_MAP1_NORMAL:
+ return ctx->Eval.Map1Normal;
+ case GL_MAP1_TEXTURE_COORD_1:
+ return ctx->Eval.Map1TextureCoord1;
+ case GL_MAP1_TEXTURE_COORD_2:
+ return ctx->Eval.Map1TextureCoord2;
+ case GL_MAP1_TEXTURE_COORD_3:
+ return ctx->Eval.Map1TextureCoord3;
+ case GL_MAP1_TEXTURE_COORD_4:
+ return ctx->Eval.Map1TextureCoord4;
+ case GL_MAP1_VERTEX_3:
+ return ctx->Eval.Map1Vertex3;
+ case GL_MAP1_VERTEX_4:
+ return ctx->Eval.Map1Vertex4;
+ case GL_MAP2_COLOR_4:
+ return ctx->Eval.Map2Color4;
+ case GL_MAP2_INDEX:
+ return ctx->Eval.Map2Index;
+ case GL_MAP2_NORMAL:
+ return ctx->Eval.Map2Normal;
+ case GL_MAP2_TEXTURE_COORD_1:
+ return ctx->Eval.Map2TextureCoord1;
+ case GL_MAP2_TEXTURE_COORD_2:
+ return ctx->Eval.Map2TextureCoord2;
+ case GL_MAP2_TEXTURE_COORD_3:
+ return ctx->Eval.Map2TextureCoord3;
+ case GL_MAP2_TEXTURE_COORD_4:
+ return ctx->Eval.Map2TextureCoord4;
+ case GL_MAP2_VERTEX_3:
+ return ctx->Eval.Map2Vertex3;
+ case GL_MAP2_VERTEX_4:
+ return ctx->Eval.Map2Vertex4;
+ case GL_NORMALIZE:
+ return ctx->Transform.Normalize;
+ case GL_POINT_SMOOTH:
+ return ctx->Point.SmoothFlag;
+ case GL_POLYGON_SMOOTH:
+ return ctx->Polygon.SmoothFlag;
+ case GL_POLYGON_STIPPLE:
+ return ctx->Polygon.StippleFlag;
+ case GL_POLYGON_OFFSET_POINT:
+ return ctx->Polygon.OffsetPoint;
+ case GL_POLYGON_OFFSET_LINE:
+ return ctx->Polygon.OffsetLine;
+ case GL_POLYGON_OFFSET_FILL:
+ /*case GL_POLYGON_OFFSET_EXT:*/
+ return ctx->Polygon.OffsetFill;
+ case GL_RESCALE_NORMAL_EXT:
+ return ctx->Transform.RescaleNormals;
+ case GL_SCISSOR_TEST:
+ return ctx->Scissor.Enabled;
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ return ctx->Texture.SharedPalette;
+ case GL_STENCIL_TEST:
+ return ctx->Stencil.Enabled;
+ case GL_TEXTURE_1D:
+ {
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ return (texUnit->Enabled & TEXTURE0_1D) ? GL_TRUE : GL_FALSE;
+ }
+ case GL_TEXTURE_2D:
+ {
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ return (texUnit->Enabled & TEXTURE0_2D) ? GL_TRUE : GL_FALSE;
+ }
+ case GL_TEXTURE_3D:
+ {
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ return (texUnit->Enabled & TEXTURE0_2D) ? GL_TRUE : GL_FALSE;
+ }
+ case GL_TEXTURE_GEN_Q:
+ {
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ return (texUnit->TexGenEnabled & Q_BIT) ? GL_TRUE : GL_FALSE;
+ }
+ case GL_TEXTURE_GEN_R:
+ {
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ return (texUnit->TexGenEnabled & R_BIT) ? GL_TRUE : GL_FALSE;
+ }
+ case GL_TEXTURE_GEN_S:
+ {
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ return (texUnit->TexGenEnabled & S_BIT) ? GL_TRUE : GL_FALSE;
+ }
+ case GL_TEXTURE_GEN_T:
+ {
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ return (texUnit->TexGenEnabled & T_BIT) ? GL_TRUE : GL_FALSE;
+ }
+
+ /*
+ * CLIENT STATE!!!
+ */
+ case GL_VERTEX_ARRAY:
+ return ctx->Array.Vertex.Enabled;
+ case GL_NORMAL_ARRAY:
+ return ctx->Array.Normal.Enabled;
+ case GL_COLOR_ARRAY:
+ return ctx->Array.Color.Enabled;
+ case GL_INDEX_ARRAY:
+ return ctx->Array.Index.Enabled;
+ case GL_TEXTURE_COORD_ARRAY:
+ return ctx->Array.TexCoord[ctx->TexCoordUnit].Enabled;
+ case GL_EDGE_FLAG_ARRAY:
+ return ctx->Array.EdgeFlag.Enabled;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glIsEnabled" );
+ return GL_FALSE;
+ }
+}
+
+
+
+
+static void gl_client_state( GLcontext *ctx, GLenum cap, GLboolean state )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx,
+ (state
+ ? "glEnableClientState"
+ : "glDisableClientState") );
+
+ switch (cap) {
+ case GL_VERTEX_ARRAY:
+ ctx->Array.Vertex.Enabled = state;
+ break;
+ case GL_NORMAL_ARRAY:
+ ctx->Array.Normal.Enabled = state;
+ break;
+ case GL_COLOR_ARRAY:
+ ctx->Array.Color.Enabled = state;
+ break;
+ case GL_INDEX_ARRAY:
+ ctx->Array.Index.Enabled = state;
+ break;
+ case GL_TEXTURE_COORD_ARRAY:
+ ctx->Array.TexCoord[ctx->TexCoordUnit].Enabled = state;
+ break;
+ case GL_EDGE_FLAG_ARRAY:
+ ctx->Array.EdgeFlag.Enabled = state;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glEnable/DisableClientState" );
+ }
+
+ ctx->NewState |= NEW_CLIENT_STATE;
+}
+
+
+
+void gl_EnableClientState( GLcontext *ctx, GLenum cap )
+{
+ gl_client_state( ctx, cap, GL_TRUE );
+}
+
+
+
+void gl_DisableClientState( GLcontext *ctx, GLenum cap )
+{
+ gl_client_state( ctx, cap, GL_FALSE );
+}
+
diff --git a/src/mesa/main/enable.h b/src/mesa/main/enable.h
new file mode 100644
index 0000000000..92a916a984
--- /dev/null
+++ b/src/mesa/main/enable.h
@@ -0,0 +1,51 @@
+/* $Id: enable.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef ENABLE_H
+#define ENABLE_H
+
+
+#include "types.h"
+
+
+extern void gl_set_enable( GLcontext* ctx, GLenum cap, GLboolean state );
+
+extern void gl_Disable( GLcontext* ctx, GLenum cap );
+
+extern void gl_Enable( GLcontext* ctx, GLenum cap );
+
+extern GLboolean gl_IsEnabled( GLcontext* ctx, GLenum cap );
+
+extern void gl_EnableClientState( GLcontext *ctx, GLenum cap );
+
+extern void gl_DisableClientState( GLcontext *ctx, GLenum cap );
+
+
+#endif
diff --git a/src/mesa/main/enums.c b/src/mesa/main/enums.c
new file mode 100644
index 0000000000..69b520ef40
--- /dev/null
+++ b/src/mesa/main/enums.c
@@ -0,0 +1,893 @@
+/* $Id: enums.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+#include "GL/gl.h"
+#include "enums.h"
+#include <stdlib.h>
+#include <string.h>
+
+
+typedef struct {
+ const char *c;
+ int n;
+} enum_elt;
+
+enum_elt all_enums[] =
+{
+ /* Boolean values */
+ { "GL_FALSE", 0 },
+ { "GL_TRUE", 1 },
+
+ /* Data types */
+ { "GL_BYTE", 0x1400 },
+ { "GL_UNSIGNED_BYTE", 0x1401 },
+ { "GL_SHORT", 0x1402 },
+ { "GL_UNSIGNED_SHORT", 0x1403 },
+ { "GL_INT", 0x1404 },
+ { "GL_UNSIGNED_INT", 0x1405 },
+ { "GL_FLOAT", 0x1406 },
+ { "GL_DOUBLE", 0x140A },
+ { "GL_2_BYTES", 0x1407 },
+ { "GL_3_BYTES", 0x1408 },
+ { "GL_4_BYTES", 0x1409 },
+
+ /* Primitives */
+ { "GL_LINES", 0x0001 },
+ { "GL_POINTS", 0x0000 },
+ { "GL_LINE_STRIP", 0x0003 },
+ { "GL_LINE_LOOP", 0x0002 },
+ { "GL_TRIANGLES", 0x0004 },
+ { "GL_TRIANGLE_STRIP", 0x0005 },
+ { "GL_TRIANGLE_FAN", 0x0006 },
+ { "GL_QUADS", 0x0007 },
+ { "GL_QUAD_STRIP", 0x0008 },
+ { "GL_POLYGON", 0x0009 },
+ { "GL_EDGE_FLAG", 0x0B43 },
+
+ /* Vertex Arrays */
+ { "GL_VERTEX_ARRAY", 0x8074 },
+ { "GL_NORMAL_ARRAY", 0x8075 },
+ { "GL_COLOR_ARRAY", 0x8076 },
+ { "GL_INDEX_ARRAY", 0x8077 },
+ { "GL_TEXTURE_COORD_ARRAY", 0x8078 },
+ { "GL_EDGE_FLAG_ARRAY", 0x8079 },
+ { "GL_VERTEX_ARRAY_SIZE", 0x807A },
+ { "GL_VERTEX_ARRAY_TYPE", 0x807B },
+ { "GL_VERTEX_ARRAY_STRIDE", 0x807C },
+ { "GL_NORMAL_ARRAY_TYPE", 0x807E },
+ { "GL_NORMAL_ARRAY_STRIDE", 0x807F },
+ { "GL_COLOR_ARRAY_SIZE", 0x8081 },
+ { "GL_COLOR_ARRAY_TYPE", 0x8082 },
+ { "GL_COLOR_ARRAY_STRIDE", 0x8083 },
+ { "GL_INDEX_ARRAY_TYPE", 0x8085 },
+ { "GL_INDEX_ARRAY_STRIDE", 0x8086 },
+ { "GL_TEXTURE_COORD_ARRAY_SIZE", 0x8088 },
+ { "GL_TEXTURE_COORD_ARRAY_TYPE", 0x8089 },
+ { "GL_TEXTURE_COORD_ARRAY_STRIDE", 0x808A },
+ { "GL_EDGE_FLAG_ARRAY_STRIDE", 0x808C },
+ { "GL_VERTEX_ARRAY_POINTER", 0x808E },
+ { "GL_NORMAL_ARRAY_POINTER", 0x808F },
+ { "GL_COLOR_ARRAY_POINTER", 0x8090 },
+ { "GL_INDEX_ARRAY_POINTER", 0x8091 },
+ { "GL_TEXTURE_COORD_ARRAY_POINTER", 0x8092 },
+ { "GL_EDGE_FLAG_ARRAY_POINTER", 0x8093 },
+ { "GL_V2F", 0x2A20 },
+ { "GL_V3F", 0x2A21 },
+ { "GL_C4UB_V2F", 0x2A22 },
+ { "GL_C4UB_V3F", 0x2A23 },
+ { "GL_C3F_V3F", 0x2A24 },
+ { "GL_N3F_V3F", 0x2A25 },
+ { "GL_C4F_N3F_V3F", 0x2A26 },
+ { "GL_T2F_V3F", 0x2A27 },
+ { "GL_T4F_V4F", 0x2A28 },
+ { "GL_T2F_C4UB_V3F", 0x2A29 },
+ { "GL_T2F_C3F_V3F", 0x2A2A },
+ { "GL_T2F_N3F_V3F", 0x2A2B },
+ { "GL_T2F_C4F_N3F_V3F", 0x2A2C },
+ { "GL_T4F_C4F_N3F_V4F", 0x2A2D },
+
+ /* Matrix Mode */
+ { "GL_MATRIX_MODE", 0x0BA0 },
+ { "GL_MODELVIEW", 0x1700 },
+ { "GL_PROJECTION", 0x1701 },
+ { "GL_TEXTURE", 0x1702 },
+
+ /* Points */
+ { "GL_POINT_SMOOTH", 0x0B10 },
+ { "GL_POINT_SIZE", 0x0B11 },
+ { "GL_POINT_SIZE_GRANULARITY ", 0x0B13 },
+ { "GL_POINT_SIZE_RANGE", 0x0B12 },
+
+ /* Lines */
+ { "GL_LINE_SMOOTH", 0x0B20 },
+ { "GL_LINE_STIPPLE", 0x0B24 },
+ { "GL_LINE_STIPPLE_PATTERN", 0x0B25 },
+ { "GL_LINE_STIPPLE_REPEAT", 0x0B26 },
+ { "GL_LINE_WIDTH", 0x0B21 },
+ { "GL_LINE_WIDTH_GRANULARITY", 0x0B23 },
+ { "GL_LINE_WIDTH_RANGE", 0x0B22 },
+
+ /* Polygons */
+ { "GL_POINT", 0x1B00 },
+ { "GL_LINE", 0x1B01 },
+ { "GL_FILL", 0x1B02 },
+ { "GL_CCW", 0x0901 },
+ { "GL_CW", 0x0900 },
+ { "GL_FRONT", 0x0404 },
+ { "GL_BACK", 0x0405 },
+ { "GL_CULL_FACE", 0x0B44 },
+ { "GL_CULL_FACE_MODE", 0x0B45 },
+ { "GL_POLYGON_SMOOTH", 0x0B41 },
+ { "GL_POLYGON_STIPPLE", 0x0B42 },
+ { "GL_FRONT_FACE", 0x0B46 },
+ { "GL_POLYGON_MODE", 0x0B40 },
+ { "GL_POLYGON_OFFSET_FACTOR", 0x8038 },
+ { "GL_POLYGON_OFFSET_UNITS", 0x2A00 },
+ { "GL_POLYGON_OFFSET_POINT", 0x2A01 },
+ { "GL_POLYGON_OFFSET_LINE", 0x2A02 },
+ { "GL_POLYGON_OFFSET_FILL", 0x8037 },
+
+ /* Display Lists */
+ { "GL_COMPILE", 0x1300 },
+ { "GL_COMPILE_AND_EXECUTE", 0x1301 },
+ { "GL_LIST_BASE", 0x0B32 },
+ { "GL_LIST_INDEX", 0x0B33 },
+ { "GL_LIST_MODE", 0x0B30 },
+
+ /* Depth buffer */
+ { "GL_NEVER", 0x0200 },
+ { "GL_LESS", 0x0201 },
+ { "GL_GEQUAL", 0x0206 },
+ { "GL_LEQUAL", 0x0203 },
+ { "GL_GREATER", 0x0204 },
+ { "GL_NOTEQUAL", 0x0205 },
+ { "GL_EQUAL", 0x0202 },
+ { "GL_ALWAYS", 0x0207 },
+ { "GL_DEPTH_TEST", 0x0B71 },
+ { "GL_DEPTH_BITS", 0x0D56 },
+ { "GL_DEPTH_CLEAR_VALUE", 0x0B73 },
+ { "GL_DEPTH_FUNC", 0x0B74 },
+ { "GL_DEPTH_RANGE", 0x0B70 },
+ { "GL_DEPTH_WRITEMASK", 0x0B72 },
+ { "GL_DEPTH_COMPONENT", 0x1902 },
+
+ /* Lighting */
+ { "GL_LIGHTING", 0x0B50 },
+ { "GL_LIGHT0", 0x4000 },
+ { "GL_LIGHT1", 0x4001 },
+ { "GL_LIGHT2", 0x4002 },
+ { "GL_LIGHT3", 0x4003 },
+ { "GL_LIGHT4", 0x4004 },
+ { "GL_LIGHT5", 0x4005 },
+ { "GL_LIGHT6", 0x4006 },
+ { "GL_LIGHT7", 0x4007 },
+ { "GL_SPOT_EXPONENT", 0x1205 },
+ { "GL_SPOT_CUTOFF", 0x1206 },
+ { "GL_CONSTANT_ATTENUATION", 0x1207 },
+ { "GL_LINEAR_ATTENUATION", 0x1208 },
+ { "GL_QUADRATIC_ATTENUATION", 0x1209 },
+ { "GL_AMBIENT", 0x1200 },
+ { "GL_DIFFUSE", 0x1201 },
+ { "GL_SPECULAR", 0x1202 },
+ { "GL_SHININESS", 0x1601 },
+ { "GL_EMISSION", 0x1600 },
+ { "GL_POSITION", 0x1203 },
+ { "GL_SPOT_DIRECTION", 0x1204 },
+ { "GL_AMBIENT_AND_DIFFUSE", 0x1602 },
+ { "GL_COLOR_INDEXES", 0x1603 },
+ { "GL_LIGHT_MODEL_TWO_SIDE", 0x0B52 },
+ { "GL_LIGHT_MODEL_LOCAL_VIEWER", 0x0B51 },
+ { "GL_LIGHT_MODEL_AMBIENT", 0x0B53 },
+ { "GL_FRONT_AND_BACK", 0x0408 },
+ { "GL_SHADE_MODEL", 0x0B54 },
+ { "GL_FLAT", 0x1D00 },
+ { "GL_SMOOTH", 0x1D01 },
+ { "GL_COLOR_MATERIAL", 0x0B57 },
+ { "GL_COLOR_MATERIAL_FACE", 0x0B55 },
+ { "GL_COLOR_MATERIAL_PARAMETER", 0x0B56 },
+ { "GL_NORMALIZE", 0x0BA1 },
+
+ /* User clipping planes */
+ { "GL_CLIP_PLANE0", 0x3000 },
+ { "GL_CLIP_PLANE1", 0x3001 },
+ { "GL_CLIP_PLANE2", 0x3002 },
+ { "GL_CLIP_PLANE3", 0x3003 },
+ { "GL_CLIP_PLANE4", 0x3004 },
+ { "GL_CLIP_PLANE5", 0x3005 },
+
+ /* Accumulation buffer */
+ { "GL_ACCUM_RED_BITS", 0x0D58 },
+ { "GL_ACCUM_GREEN_BITS", 0x0D59 },
+ { "GL_ACCUM_BLUE_BITS", 0x0D5A },
+ { "GL_ACCUM_ALPHA_BITS", 0x0D5B },
+ { "GL_ACCUM_CLEAR_VALUE", 0x0B80 },
+ { "GL_ACCUM", 0x0100 },
+ { "GL_ADD", 0x0104 },
+ { "GL_LOAD", 0x0101 },
+ { "GL_MULT", 0x0103 },
+ { "GL_RETURN", 0x0102 },
+
+ /* Alpha testing */
+ { "GL_ALPHA_TEST", 0x0BC0 },
+ { "GL_ALPHA_TEST_REF", 0x0BC2 },
+ { "GL_ALPHA_TEST_FUNC", 0x0BC1 },
+
+ /* Blending */
+ { "GL_BLEND", 0x0BE2 },
+ { "GL_BLEND_SRC", 0x0BE1 },
+ { "GL_BLEND_DST", 0x0BE0 },
+ { "GL_ZERO", 0 },
+ { "GL_ONE", 1 },
+ { "GL_SRC_COLOR", 0x0300 },
+ { "GL_ONE_MINUS_SRC_COLOR", 0x0301 },
+ { "GL_DST_COLOR", 0x0306 },
+ { "GL_ONE_MINUS_DST_COLOR", 0x0307 },
+ { "GL_SRC_ALPHA", 0x0302 },
+ { "GL_ONE_MINUS_SRC_ALPHA", 0x0303 },
+ { "GL_DST_ALPHA", 0x0304 },
+ { "GL_ONE_MINUS_DST_ALPHA", 0x0305 },
+ { "GL_SRC_ALPHA_SATURATE", 0x0308 },
+ { "GL_CONSTANT_COLOR", 0x8001 },
+ { "GL_ONE_MINUS_CONSTANT_COLOR", 0x8002 },
+ { "GL_CONSTANT_ALPHA", 0x8003 },
+ { "GL_ONE_MINUS_CONSTANT_ALPHA", 0x8004 },
+
+ /* Render Mode */
+ { "GL_FEEDBACK", 0x1C01 },
+ { "GL_RENDER", 0x1C00 },
+ { "GL_SELECT", 0x1C02 },
+
+ /* Feedback */
+ { "GL_2D", 0x0600 },
+ { "GL_3D", 0x0601 },
+ { "GL_3D_COLOR", 0x0602 },
+ { "GL_3D_COLOR_TEXTURE", 0x0603 },
+ { "GL_4D_COLOR_TEXTURE", 0x0604 },
+ { "GL_POINT_TOKEN", 0x0701 },
+ { "GL_LINE_TOKEN", 0x0702 },
+ { "GL_LINE_RESET_TOKEN", 0x0707 },
+ { "GL_POLYGON_TOKEN", 0x0703 },
+ { "GL_BITMAP_TOKEN", 0x0704 },
+ { "GL_DRAW_PIXEL_TOKEN", 0x0705 },
+ { "GL_COPY_PIXEL_TOKEN", 0x0706 },
+ { "GL_PASS_THROUGH_TOKEN", 0x0700 },
+ { "GL_FEEDBACK_BUFFER_POINTER", 0x0DF0 },
+ { "GL_FEEDBACK_BUFFER_SIZE", 0x0DF1 },
+ { "GL_FEEDBACK_BUFFER_TYPE", 0x0DF2 },
+
+ /* Selection */
+ { "GL_SELECTION_BUFFER_POINTER", 0x0DF3 },
+ { "GL_SELECTION_BUFFER_SIZE", 0x0DF4 },
+
+ /* Fog */
+ { "GL_FOG", 0x0B60 },
+ { "GL_FOG_MODE", 0x0B65 },
+ { "GL_FOG_DENSITY", 0x0B62 },
+ { "GL_FOG_COLOR", 0x0B66 },
+ { "GL_FOG_INDEX", 0x0B61 },
+ { "GL_FOG_START", 0x0B63 },
+ { "GL_FOG_END", 0x0B64 },
+ { "GL_LINEAR", 0x2601 },
+ { "GL_EXP", 0x0800 },
+ { "GL_EXP2", 0x0801 },
+
+ /* Logic Ops */
+ { "GL_LOGIC_OP", 0x0BF1 },
+ { "GL_INDEX_LOGIC_OP", 0x0BF1 },
+ { "GL_COLOR_LOGIC_OP", 0x0BF2 },
+ { "GL_LOGIC_OP_MODE", 0x0BF0 },
+ { "GL_CLEAR", 0x1500 },
+ { "GL_SET", 0x150F },
+ { "GL_COPY", 0x1503 },
+ { "GL_COPY_INVERTED", 0x150C },
+ { "GL_NOOP", 0x1505 },
+ { "GL_INVERT", 0x150A },
+ { "GL_AND", 0x1501 },
+ { "GL_NAND", 0x150E },
+ { "GL_OR", 0x1507 },
+ { "GL_NOR", 0x1508 },
+ { "GL_XOR", 0x1506 },
+ { "GL_EQUIV", 0x1509 },
+ { "GL_AND_REVERSE", 0x1502 },
+ { "GL_AND_INVERTED", 0x1504 },
+ { "GL_OR_REVERSE", 0x150B },
+ { "GL_OR_INVERTED", 0x150D },
+
+ /* Stencil */
+ { "GL_STENCIL_TEST", 0x0B90 },
+ { "GL_STENCIL_WRITEMASK", 0x0B98 },
+ { "GL_STENCIL_BITS", 0x0D57 },
+ { "GL_STENCIL_FUNC", 0x0B92 },
+ { "GL_STENCIL_VALUE_MASK", 0x0B93 },
+ { "GL_STENCIL_REF", 0x0B97 },
+ { "GL_STENCIL_FAIL", 0x0B94 },
+ { "GL_STENCIL_PASS_DEPTH_PASS", 0x0B96 },
+ { "GL_STENCIL_PASS_DEPTH_FAIL", 0x0B95 },
+ { "GL_STENCIL_CLEAR_VALUE", 0x0B91 },
+ { "GL_STENCIL_INDEX", 0x1901 },
+ { "GL_KEEP", 0x1E00 },
+ { "GL_REPLACE", 0x1E01 },
+ { "GL_INCR", 0x1E02 },
+ { "GL_DECR", 0x1E03 },
+
+ /* Buffers, Pixel Drawing/Reading */
+ { "GL_NONE", 0 },
+ { "GL_LEFT", 0x0406 },
+ { "GL_RIGHT", 0x0407 },
+ { "GL_FRONT_LEFT", 0x0400 },
+ { "GL_FRONT_RIGHT", 0x0401 },
+ { "GL_BACK_LEFT", 0x0402 },
+ { "GL_BACK_RIGHT", 0x0403 },
+ { "GL_AUX0", 0x0409 },
+ { "GL_AUX1", 0x040A },
+ { "GL_AUX2", 0x040B },
+ { "GL_AUX3", 0x040C },
+ { "GL_COLOR_INDEX", 0x1900 },
+ { "GL_RED", 0x1903 },
+ { "GL_GREEN", 0x1904 },
+ { "GL_BLUE", 0x1905 },
+ { "GL_ALPHA", 0x1906 },
+ { "GL_LUMINANCE", 0x1909 },
+ { "GL_LUMINANCE_ALPHA", 0x190A },
+ { "GL_ALPHA_BITS", 0x0D55 },
+ { "GL_RED_BITS", 0x0D52 },
+ { "GL_GREEN_BITS", 0x0D53 },
+ { "GL_BLUE_BITS", 0x0D54 },
+ { "GL_INDEX_BITS", 0x0D51 },
+ { "GL_SUBPIXEL_BITS", 0x0D50 },
+ { "GL_AUX_BUFFERS", 0x0C00 },
+ { "GL_READ_BUFFER", 0x0C02 },
+ { "GL_DRAW_BUFFER", 0x0C01 },
+ { "GL_DOUBLEBUFFER", 0x0C32 },
+ { "GL_STEREO", 0x0C33 },
+ { "GL_BITMAP", 0x1A00 },
+ { "GL_COLOR", 0x1800 },
+ { "GL_DEPTH", 0x1801 },
+ { "GL_STENCIL", 0x1802 },
+ { "GL_DITHER", 0x0BD0 },
+ { "GL_RGB", 0x1907 },
+ { "GL_RGBA", 0x1908 },
+
+ /* Implementation limits */
+ { "GL_MAX_LIST_NESTING", 0x0B31 },
+ { "GL_MAX_ATTRIB_STACK_DEPTH", 0x0D35 },
+ { "GL_MAX_MODELVIEW_STACK_DEPTH", 0x0D36 },
+ { "GL_MAX_NAME_STACK_DEPTH", 0x0D37 },
+ { "GL_MAX_PROJECTION_STACK_DEPTH", 0x0D38 },
+ { "GL_MAX_TEXTURE_STACK_DEPTH", 0x0D39 },
+ { "GL_MAX_EVAL_ORDER", 0x0D30 },
+ { "GL_MAX_LIGHTS", 0x0D31 },
+ { "GL_MAX_CLIP_PLANES", 0x0D32 },
+ { "GL_MAX_TEXTURE_SIZE", 0x0D33 },
+ { "GL_MAX_PIXEL_MAP_TABLE", 0x0D34 },
+ { "GL_MAX_VIEWPORT_DIMS", 0x0D3A },
+ { "GL_MAX_CLIENT_ATTRIB_STACK_DEPTH", 0x0D3B },
+
+
+ { "GL_ATTRIB_STACK_DEPTH", 0x0BB0 },
+ { "GL_CLIENT_ATTRIB_STACK_DEPTH", 0x0BB1 },
+ { "GL_COLOR_CLEAR_VALUE", 0x0C22 },
+ { "GL_COLOR_WRITEMASK", 0x0C23 },
+ { "GL_CURRENT_INDEX", 0x0B01 },
+ { "GL_CURRENT_COLOR", 0x0B00 },
+ { "GL_CURRENT_NORMAL", 0x0B02 },
+ { "GL_CURRENT_RASTER_COLOR", 0x0B04 },
+ { "GL_CURRENT_RASTER_DISTANCE", 0x0B09 },
+ { "GL_CURRENT_RASTER_INDEX", 0x0B05 },
+ { "GL_CURRENT_RASTER_POSITION", 0x0B07 },
+ { "GL_CURRENT_RASTER_TEXTURE_COORDS", 0x0B06},
+ { "GL_CURRENT_RASTER_POSITION_VALID", 0x0B08 },
+ { "GL_CURRENT_TEXTURE_COORDS", 0x0B03 },
+ { "GL_INDEX_CLEAR_VALUE", 0x0C20 },
+ { "GL_INDEX_MODE", 0x0C30 },
+ { "GL_INDEX_WRITEMASK", 0x0C21 },
+ { "GL_MODELVIEW_MATRIX", 0x0BA6 },
+ { "GL_MODELVIEW_STACK_DEPTH", 0x0BA3 },
+ { "GL_NAME_STACK_DEPTH", 0x0D70 },
+ { "GL_PROJECTION_MATRIX", 0x0BA7 },
+ { "GL_PROJECTION_STACK_DEPTH", 0x0BA4 },
+ { "GL_RENDER_MODE", 0x0C40 },
+ { "GL_RGBA_MODE", 0x0C31 },
+ { "GL_TEXTURE_MATRIX", 0x0BA8 },
+ { "GL_TEXTURE_STACK_DEPTH", 0x0BA5 },
+ { "GL_VIEWPORT", 0x0BA2 },
+
+
+ /* Evaluators */
+ { "GL_AUTO_NORMAL", 0x0D80 },
+ { "GL_MAP1_COLOR_4", 0x0D90 },
+ { "GL_MAP1_GRID_DOMAIN", 0x0DD0 },
+ { "GL_MAP1_GRID_SEGMENTS", 0x0DD1 },
+ { "GL_MAP1_INDEX", 0x0D91 },
+ { "GL_MAP1_NORMAL", 0x0D92 },
+ { "GL_MAP1_TEXTURE_COORD_1", 0x0D93 },
+ { "GL_MAP1_TEXTURE_COORD_2", 0x0D94 },
+ { "GL_MAP1_TEXTURE_COORD_3", 0x0D95 },
+ { "GL_MAP1_TEXTURE_COORD_4", 0x0D96 },
+ { "GL_MAP1_VERTEX_3", 0x0D97 },
+ { "GL_MAP1_VERTEX_4", 0x0D98 },
+ { "GL_MAP2_COLOR_4", 0x0DB0 },
+ { "GL_MAP2_GRID_DOMAIN", 0x0DD2 },
+ { "GL_MAP2_GRID_SEGMENTS", 0x0DD3 },
+ { "GL_MAP2_INDEX", 0x0DB1 },
+ { "GL_MAP2_NORMAL", 0x0DB2 },
+ { "GL_MAP2_TEXTURE_COORD_1", 0x0DB3 },
+ { "GL_MAP2_TEXTURE_COORD_2", 0x0DB4 },
+ { "GL_MAP2_TEXTURE_COORD_3", 0x0DB5 },
+ { "GL_MAP2_TEXTURE_COORD_4", 0x0DB6 },
+ { "GL_MAP2_VERTEX_3", 0x0DB7 },
+ { "GL_MAP2_VERTEX_4", 0x0DB8 },
+ { "GL_COEFF", 0x0A00 },
+ { "GL_DOMAIN", 0x0A02 },
+ { "GL_ORDER", 0x0A01 },
+
+ /* Hints */
+ { "GL_FOG_HINT", 0x0C54 },
+ { "GL_LINE_SMOOTH_HINT", 0x0C52 },
+ { "GL_PERSPECTIVE_CORRECTION_HINT", 0x0C50 },
+ { "GL_POINT_SMOOTH_HINT", 0x0C51 },
+ { "GL_POLYGON_SMOOTH_HINT", 0x0C53 },
+ { "GL_DONT_CARE", 0x1100 },
+ { "GL_FASTEST", 0x1101 },
+ { "GL_NICEST", 0x1102 },
+
+ /* Scissor box */
+ { "GL_SCISSOR_TEST", 0x0C11 },
+ { "GL_SCISSOR_BOX", 0x0C10 },
+
+ /* Pixel Mode / Transfer */
+ { "GL_MAP_COLOR", 0x0D10 },
+ { "GL_MAP_STENCIL", 0x0D11 },
+ { "GL_INDEX_SHIFT", 0x0D12 },
+ { "GL_INDEX_OFFSET", 0x0D13 },
+ { "GL_RED_SCALE", 0x0D14 },
+ { "GL_RED_BIAS", 0x0D15 },
+ { "GL_GREEN_SCALE", 0x0D18 },
+ { "GL_GREEN_BIAS", 0x0D19 },
+ { "GL_BLUE_SCALE", 0x0D1A },
+ { "GL_BLUE_BIAS", 0x0D1B },
+ { "GL_ALPHA_SCALE", 0x0D1C },
+ { "GL_ALPHA_BIAS", 0x0D1D },
+ { "GL_DEPTH_SCALE", 0x0D1E },
+ { "GL_DEPTH_BIAS", 0x0D1F },
+ { "GL_PIXEL_MAP_S_TO_S_SIZE", 0x0CB1 },
+ { "GL_PIXEL_MAP_I_TO_I_SIZE", 0x0CB0 },
+ { "GL_PIXEL_MAP_I_TO_R_SIZE", 0x0CB2 },
+ { "GL_PIXEL_MAP_I_TO_G_SIZE", 0x0CB3 },
+ { "GL_PIXEL_MAP_I_TO_B_SIZE", 0x0CB4 },
+ { "GL_PIXEL_MAP_I_TO_A_SIZE", 0x0CB5 },
+ { "GL_PIXEL_MAP_R_TO_R_SIZE", 0x0CB6 },
+ { "GL_PIXEL_MAP_G_TO_G_SIZE", 0x0CB7 },
+ { "GL_PIXEL_MAP_B_TO_B_SIZE", 0x0CB8 },
+ { "GL_PIXEL_MAP_A_TO_A_SIZE", 0x0CB9 },
+ { "GL_PIXEL_MAP_S_TO_S", 0x0C71 },
+ { "GL_PIXEL_MAP_I_TO_I", 0x0C70 },
+ { "GL_PIXEL_MAP_I_TO_R", 0x0C72 },
+ { "GL_PIXEL_MAP_I_TO_G", 0x0C73 },
+ { "GL_PIXEL_MAP_I_TO_B", 0x0C74 },
+ { "GL_PIXEL_MAP_I_TO_A", 0x0C75 },
+ { "GL_PIXEL_MAP_R_TO_R", 0x0C76 },
+ { "GL_PIXEL_MAP_G_TO_G", 0x0C77 },
+ { "GL_PIXEL_MAP_B_TO_B", 0x0C78 },
+ { "GL_PIXEL_MAP_A_TO_A", 0x0C79 },
+ { "GL_PACK_ALIGNMENT", 0x0D05 },
+ { "GL_PACK_LSB_FIRST", 0x0D01 },
+ { "GL_PACK_ROW_LENGTH", 0x0D02 },
+ { "GL_PACK_SKIP_PIXELS", 0x0D04 },
+ { "GL_PACK_SKIP_ROWS", 0x0D03 },
+ { "GL_PACK_SWAP_BYTES", 0x0D00 },
+ { "GL_UNPACK_ALIGNMENT", 0x0CF5 },
+ { "GL_UNPACK_LSB_FIRST", 0x0CF1 },
+ { "GL_UNPACK_ROW_LENGTH", 0x0CF2 },
+ { "GL_UNPACK_SKIP_PIXELS", 0x0CF4 },
+ { "GL_UNPACK_SKIP_ROWS", 0x0CF3 },
+ { "GL_UNPACK_SWAP_BYTES", 0x0CF0 },
+ { "GL_ZOOM_X", 0x0D16 },
+ { "GL_ZOOM_Y", 0x0D17 },
+
+ /* Texture mapping */
+ { "GL_TEXTURE_ENV", 0x2300 },
+ { "GL_TEXTURE_ENV_MODE", 0x2200 },
+ { "GL_TEXTURE_1D", 0x0DE0 },
+ { "GL_TEXTURE_2D", 0x0DE1 },
+ { "GL_TEXTURE_WRAP_S", 0x2802 },
+ { "GL_TEXTURE_WRAP_T", 0x2803 },
+ { "GL_TEXTURE_MAG_FILTER", 0x2800 },
+ { "GL_TEXTURE_MIN_FILTER", 0x2801 },
+ { "GL_TEXTURE_ENV_COLOR", 0x2201 },
+ { "GL_TEXTURE_GEN_S", 0x0C60 },
+ { "GL_TEXTURE_GEN_T", 0x0C61 },
+ { "GL_TEXTURE_GEN_MODE", 0x2500 },
+ { "GL_TEXTURE_BORDER_COLOR", 0x1004 },
+ { "GL_TEXTURE_WIDTH", 0x1000 },
+ { "GL_TEXTURE_HEIGHT", 0x1001 },
+ { "GL_TEXTURE_BORDER", 0x1005 },
+ { "GL_TEXTURE_COMPONENTS", 0x1003 },
+ { "GL_TEXTURE_RED_SIZE", 0x805C },
+ { "GL_TEXTURE_GREEN_SIZE", 0x805D },
+ { "GL_TEXTURE_BLUE_SIZE", 0x805E },
+ { "GL_TEXTURE_ALPHA_SIZE", 0x805F },
+ { "GL_TEXTURE_LUMINANCE_SIZE", 0x8060 },
+ { "GL_TEXTURE_INTENSITY_SIZE", 0x8061 },
+ { "GL_NEAREST_MIPMAP_NEAREST", 0x2700 },
+ { "GL_NEAREST_MIPMAP_LINEAR", 0x2702 },
+ { "GL_LINEAR_MIPMAP_NEAREST", 0x2701 },
+ { "GL_LINEAR_MIPMAP_LINEAR", 0x2703 },
+ { "GL_OBJECT_LINEAR", 0x2401 },
+ { "GL_OBJECT_PLANE", 0x2501 },
+ { "GL_EYE_LINEAR", 0x2400 },
+ { "GL_EYE_PLANE", 0x2502 },
+ { "GL_SPHERE_MAP", 0x2402 },
+ { "GL_DECAL", 0x2101 },
+ { "GL_MODULATE", 0x2100 },
+ { "GL_NEAREST", 0x2600 },
+ { "GL_REPEAT", 0x2901 },
+ { "GL_CLAMP", 0x2900 },
+ { "GL_S", 0x2000 },
+ { "GL_T", 0x2001 },
+ { "GL_R", 0x2002 },
+ { "GL_Q", 0x2003 },
+ { "GL_TEXTURE_GEN_R", 0x0C62 },
+ { "GL_TEXTURE_GEN_Q", 0x0C63 },
+
+ /* GL 1.1 texturing */
+ { "GL_PROXY_TEXTURE_1D", 0x8063 },
+ { "GL_PROXY_TEXTURE_2D", 0x8064 },
+ { "GL_TEXTURE_PRIORITY", 0x8066 },
+ { "GL_TEXTURE_RESIDENT", 0x8067 },
+ { "GL_TEXTURE_BINDING_1D", 0x8068 },
+ { "GL_TEXTURE_BINDING_2D", 0x8069 },
+ { "GL_TEXTURE_INTERNAL_FORMAT", 0x1003 },
+
+ /* GL 1.2 texturing */
+ { "GL_PACK_SKIP_IMAGES", 0x806B },
+ { "GL_PACK_IMAGE_HEIGHT", 0x806C },
+ { "GL_UNPACK_SKIP_IMAGES", 0x806D },
+ { "GL_UNPACK_IMAGE_HEIGHT", 0x806E },
+ { "GL_TEXTURE_3D", 0x806F },
+ { "GL_PROXY_TEXTURE_3D", 0x8070 },
+ { "GL_TEXTURE_DEPTH", 0x8071 },
+ { "GL_TEXTURE_WRAP_R", 0x8072 },
+ { "GL_MAX_3D_TEXTURE_SIZE", 0x8073 },
+ { "GL_TEXTURE_BINDING_3D", 0x806A },
+
+ /* Internal texture formats (GL 1.1) */
+ { "GL_ALPHA4", 0x803B },
+ { "GL_ALPHA8", 0x803C },
+ { "GL_ALPHA12", 0x803D },
+ { "GL_ALPHA16", 0x803E },
+ { "GL_LUMINANCE4", 0x803F },
+ { "GL_LUMINANCE8", 0x8040 },
+ { "GL_LUMINANCE12", 0x8041 },
+ { "GL_LUMINANCE16", 0x8042 },
+ { "GL_LUMINANCE4_ALPHA4", 0x8043 },
+ { "GL_LUMINANCE6_ALPHA2", 0x8044 },
+ { "GL_LUMINANCE8_ALPHA8", 0x8045 },
+ { "GL_LUMINANCE12_ALPHA4", 0x8046 },
+ { "GL_LUMINANCE12_ALPHA12", 0x8047 },
+ { "GL_LUMINANCE16_ALPHA16", 0x8048 },
+ { "GL_INTENSITY", 0x8049 },
+ { "GL_INTENSITY4", 0x804A },
+ { "GL_INTENSITY8", 0x804B },
+ { "GL_INTENSITY12", 0x804C },
+ { "GL_INTENSITY16", 0x804D },
+ { "GL_R3_G3_B2", 0x2A10 },
+ { "GL_RGB4", 0x804F },
+ { "GL_RGB5", 0x8050 },
+ { "GL_RGB8", 0x8051 },
+ { "GL_RGB10", 0x8052 },
+ { "GL_RGB12", 0x8053 },
+ { "GL_RGB16", 0x8054 },
+ { "GL_RGBA2", 0x8055 },
+ { "GL_RGBA4", 0x8056 },
+ { "GL_RGB5_A1", 0x8057 },
+ { "GL_RGBA8", 0x8058 },
+ { "GL_RGB10_A2", 0x8059 },
+ { "GL_RGBA12", 0x805A },
+ { "GL_RGBA16", 0x805B },
+
+ /* Utility */
+ { "GL_VENDOR", 0x1F00 },
+ { "GL_RENDERER", 0x1F01 },
+ { "GL_VERSION", 0x1F02 },
+ { "GL_EXTENSIONS", 0x1F03 },
+
+ /* Errors */
+ { "GL_INVALID_VALUE", 0x0501 },
+ { "GL_INVALID_ENUM", 0x0500 },
+ { "GL_INVALID_OPERATION", 0x0502 },
+ { "GL_STACK_OVERFLOW", 0x0503 },
+ { "GL_STACK_UNDERFLOW", 0x0504 },
+ { "GL_OUT_OF_MEMORY", 0x0505 },
+
+ /*
+ * Extensions
+ */
+
+ { "GL_CONSTANT_COLOR_EXT", 0x8001 },
+ { "GL_ONE_MINUS_CONSTANT_COLOR_EXT", 0x8002 },
+ { "GL_CONSTANT_ALPHA_EXT", 0x8003 },
+ { "GL_ONE_MINUS_CONSTANT_ALPHA_EXT", 0x8004 },
+ { "GL_BLEND_EQUATION_EXT", 0x8009 },
+ { "GL_MIN_EXT", 0x8007 },
+ { "GL_MAX_EXT", 0x8008 },
+ { "GL_FUNC_ADD_EXT", 0x8006 },
+ { "GL_FUNC_SUBTRACT_EXT", 0x800A },
+ { "GL_FUNC_REVERSE_SUBTRACT_EXT", 0x800B },
+ { "GL_BLEND_COLOR_EXT", 0x8005 },
+
+ { "GL_POLYGON_OFFSET_EXT", 0x8037 },
+ { "GL_POLYGON_OFFSET_FACTOR_EXT", 0x8038 },
+ { "GL_POLYGON_OFFSET_BIAS_EXT", 0x8039 },
+
+
+ { "GL_VERTEX_ARRAY_EXT", 0x8074 },
+ { "GL_NORMAL_ARRAY_EXT", 0x8075 },
+ { "GL_COLOR_ARRAY_EXT", 0x8076 },
+ { "GL_INDEX_ARRAY_EXT", 0x8077 },
+ { "GL_TEXTURE_COORD_ARRAY_EXT", 0x8078 },
+ { "GL_EDGE_FLAG_ARRAY_EXT", 0x8079 },
+ { "GL_VERTEX_ARRAY_SIZE_EXT", 0x807A },
+ { "GL_VERTEX_ARRAY_TYPE_EXT", 0x807B },
+ { "GL_VERTEX_ARRAY_STRIDE_EXT", 0x807C },
+ { "GL_VERTEX_ARRAY_COUNT_EXT", 0x807D },
+ { "GL_NORMAL_ARRAY_TYPE_EXT", 0x807E },
+ { "GL_NORMAL_ARRAY_STRIDE_EXT", 0x807F },
+ { "GL_NORMAL_ARRAY_COUNT_EXT", 0x8080 },
+ { "GL_COLOR_ARRAY_SIZE_EXT", 0x8081 },
+ { "GL_COLOR_ARRAY_TYPE_EXT", 0x8082 },
+ { "GL_COLOR_ARRAY_STRIDE_EXT", 0x8083 },
+ { "GL_COLOR_ARRAY_COUNT_EXT", 0x8084 },
+ { "GL_INDEX_ARRAY_TYPE_EXT", 0x8085 },
+ { "GL_INDEX_ARRAY_STRIDE_EXT", 0x8086 },
+ { "GL_INDEX_ARRAY_COUNT_EXT", 0x8087 },
+ { "GL_TEXTURE_COORD_ARRAY_SIZE_EXT", 0x8088 },
+ { "GL_TEXTURE_COORD_ARRAY_TYPE_EXT", 0x8089 },
+ { "GL_TEXTURE_COORD_ARRAY_STRIDE_EXT", 0x808A },
+ { "GL_TEXTURE_COORD_ARRAY_COUNT_EXT", 0x808B },
+ { "GL_EDGE_FLAG_ARRAY_STRIDE_EXT", 0x808C },
+ { "GL_EDGE_FLAG_ARRAY_COUNT_EXT", 0x808D },
+ { "GL_VERTEX_ARRAY_POINTER_EXT", 0x808E },
+ { "GL_NORMAL_ARRAY_POINTER_EXT", 0x808F },
+ { "GL_COLOR_ARRAY_POINTER_EXT", 0x8090 },
+ { "GL_INDEX_ARRAY_POINTER_EXT", 0x8091 },
+ { "GL_TEXTURE_COORD_ARRAY_POINTER_EXT", 0x8092 },
+ { "GL_EDGE_FLAG_ARRAY_POINTER_EXT", 0x8093 },
+
+ { "GL_TEXTURE_PRIORITY_EXT", 0x8066 },
+ { "GL_TEXTURE_RESIDENT_EXT", 0x8067 },
+ { "GL_TEXTURE_1D_BINDING_EXT", 0x8068 },
+ { "GL_TEXTURE_2D_BINDING_EXT", 0x8069 },
+
+ { "GL_PACK_SKIP_IMAGES_EXT", 0x806B },
+ { "GL_PACK_IMAGE_HEIGHT_EXT", 0x806C },
+ { "GL_UNPACK_SKIP_IMAGES_EXT", 0x806D },
+ { "GL_UNPACK_IMAGE_HEIGHT_EXT", 0x806E },
+ { "GL_TEXTURE_3D_EXT", 0x806F },
+ { "GL_PROXY_TEXTURE_3D_EXT", 0x8070 },
+ { "GL_TEXTURE_DEPTH_EXT", 0x8071 },
+ { "GL_TEXTURE_WRAP_R_EXT", 0x8072 },
+ { "GL_MAX_3D_TEXTURE_SIZE_EXT", 0x8073 },
+ { "GL_TEXTURE_3D_BINDING_EXT", 0x806A },
+
+ { "GL_TABLE_TOO_LARGE_EXT", 0x8031 },
+ { "GL_COLOR_TABLE_FORMAT_EXT", 0x80D8 },
+ { "GL_COLOR_TABLE_WIDTH_EXT", 0x80D9 },
+ { "GL_COLOR_TABLE_RED_SIZE_EXT", 0x80DA },
+ { "GL_COLOR_TABLE_GREEN_SIZE_EXT", 0x80DB },
+ { "GL_COLOR_TABLE_BLUE_SIZE_EXT", 0x80DC },
+ { "GL_COLOR_TABLE_ALPHA_SIZE_EXT", 0x80DD },
+ { "GL_COLOR_TABLE_LUMINANCE_SIZE_EXT", 0x80DE },
+ { "GL_COLOR_TABLE_INTENSITY_SIZE_EXT", 0x80DF },
+ { "GL_TEXTURE_INDEX_SIZE_EXT", 0x80ED },
+ { "GL_COLOR_INDEX1_EXT", 0x80E2 },
+ { "GL_COLOR_INDEX2_EXT", 0x80E3 },
+ { "GL_COLOR_INDEX4_EXT", 0x80E4 },
+ { "GL_COLOR_INDEX8_EXT", 0x80E5 },
+ { "GL_COLOR_INDEX12_EXT", 0x80E6 },
+ { "GL_COLOR_INDEX16_EXT", 0x80E7 },
+
+ { "GL_SHARED_TEXTURE_PALETTE_EXT", 0x81FB },
+
+ { "GL_POINT_SIZE_MIN_EXT", 0x8126 },
+ { "GL_POINT_SIZE_MAX_EXT", 0x8127 },
+ { "GL_POINT_FADE_THRESHOLD_SIZE_EXT", 0x8128 },
+ { "GL_DISTANCE_ATTENUATION_EXT", 0x8129 },
+
+ { "GL_RESCALE_NORMAL_EXT", 0x803A },
+
+ { "GL_ABGR_EXT", 0x8000 },
+
+ { "GL_INCR_WRAP_EXT", 0x8507 },
+ { "GL_DECR_WRAP_EXT", 0x8508 },
+
+ { "GL_CLAMP_TO_EDGE_SGIS", 0x812F },
+
+ { "GL_BLEND_DST_RGB_INGR", 0x80C8 },
+ { "GL_BLEND_SRC_RGB_INGR", 0x80C9 },
+ { "GL_BLEND_DST_ALPHA_INGR", 0x80CA },
+ { "GL_BLEND_SRC_ALPHA_INGR", 0x80CB },
+
+ { "GL_RESCALE_NORMAL", 0x803A },
+ { "GL_CLAMP_TO_EDGE", 0x812F },
+ { "GL_MAX_ELEMENTS_VERTICES", 0xF0E8 },
+ { "GL_MAX_ELEMENTS_INDICES", 0xF0E9 },
+ { "GL_BGR", 0x80E0 },
+ { "GL_BGRA", 0x80E1 },
+ { "GL_UNSIGNED_BYTE_3_3_2", 0x8032 },
+ { "GL_UNSIGNED_BYTE_2_3_3_REV", 0x8362 },
+ { "GL_UNSIGNED_SHORT_5_6_5", 0x8363 },
+ { "GL_UNSIGNED_SHORT_5_6_5_REV", 0x8364 },
+ { "GL_UNSIGNED_SHORT_4_4_4_4", 0x8033 },
+ { "GL_UNSIGNED_SHORT_4_4_4_4_REV", 0x8365 },
+ { "GL_UNSIGNED_SHORT_5_5_5_1", 0x8034 },
+ { "GL_UNSIGNED_SHORT_1_5_5_5_REV", 0x8366 },
+ { "GL_UNSIGNED_INT_8_8_8_8", 0x8035 },
+ { "GL_UNSIGNED_INT_8_8_8_8_REV", 0x8367 },
+ { "GL_UNSIGNED_INT_10_10_10_2", 0x8036 },
+ { "GL_UNSIGNED_INT_2_10_10_10_REV", 0x8368 },
+ { "GL_LIGHT_MODEL_COLOR_CONTROL", 0x81F8 },
+ { "GL_SINGLE_COLOR", 0x81F9 },
+ { "GL_SEPARATE_SPECULAR_COLOR", 0x81FA },
+ { "GL_TEXTURE_MIN_LOD", 0x813A },
+ { "GL_TEXTURE_MAX_LOD", 0x813B },
+ { "GL_TEXTURE_BASE_LEVEL", 0x813C },
+ { "GL_TEXTURE_MAX_LEVEL", 0x813D },
+
+ { "GL_TEXTURE0_ARB", 0x84C0 },
+ { "GL_TEXTURE1_ARB", 0x84C1 },
+ { "GL_TEXTURE2_ARB", 0x84C2 },
+ { "GL_TEXTURE3_ARB", 0x84C3 },
+ { "GL_ACTIVE_TEXTURE_ARB", 0x84E0 },
+ { "GL_CLIENT_ACTIVE_TEXTURE_ARB", 0x84E1 },
+ { "GL_MAX_TEXTURE_UNITS_ARB", 0x84E2 },
+
+ { "GL_NORMAL_MAP_NV", 0x8511 },
+ { "GL_REFLECTION_MAP_NV", 0x8512 },
+
+ { "GL_PREFER_DOUBLEBUFFER_HINT_PGI", 107000 },
+ { "GL_STRICT_DEPTHFUNC_HINT_PGI", 107030 },
+ { "GL_STRICT_LIGHTING_HINT_PGI", 107031 },
+ { "GL_STRICT_SCISSOR_HINT_PGI", 107032 },
+ { "GL_FULL_STIPPLE_HINT_PGI", 107033 },
+ { "GL_NATIVE_GRAPHICS_BEGIN_HINT_PGI", 107011 },
+ { "GL_NATIVE_GRAPHICS_END_HINT_PGI", 107012 },
+ { "GL_CONSERVE_MEMORY_HINT_PGI", 107005 },
+ { "GL_RECLAIM_MEMORY_HINT_PGI", 107006 },
+ { "GL_ALWAYS_FAST_HINT_PGI", 107020 },
+ { "GL_ALWAYS_SOFT_HINT_PGI", 107021 },
+ { "GL_ALLOW_DRAW_OBJ_HINT_PGI", 107022 },
+ { "GL_ALLOW_DRAW_WIN_HINT_PGI", 107023 },
+ { "GL_ALLOW_DRAW_FRG_HINT_PGI", 107024 },
+ { "GL_ALLOW_DRAW_SPN_HINT_PGI", 107024 },
+ { "GL_ALLOW_DRAW_MEM_HINT_PGI", 107025 },
+ { "GL_CLIP_NEAR_HINT_PGI", 107040 },
+ { "GL_CLIP_FAR_HINT_PGI", 107041 },
+ { "GL_WIDE_LINE_HINT_PGI", 107042 },
+ { "GL_BACK_NORMALS_HINT_PGI", 107043 },
+ { "GL_NATIVE_GRAPHICS_HANDLE_PGI", 107010 },
+
+ /* GL_EXT_compiled_vertex_array */
+ { "GL_ARRAY_ELEMENT_LOCK_FIRST_SGI", 0x81A8},
+ { "GL_ARRAY_ELEMENT_LOCK_COUNT_SGI", 0x81A9},
+
+ /* GL_EXT_clip_volume_hint */
+ { "GL_CLIP_VOLUME_CLIPPING_HINT_EXT", 0x80F0}
+
+};
+
+#define Elements(x) sizeof(x)/sizeof(*x)
+
+typedef int (GLWINAPIV *cfunc)(const void *, const void *);
+
+static enum_elt **index1 = 0;
+static int sorted = 0;
+
+static int compar_name( const enum_elt *a, const enum_elt *b )
+{
+ return strcmp(a->c, b->c);
+}
+
+
+/* note the extra level of indirection
+ */
+static int compar_nr( const enum_elt **a, const enum_elt **b )
+{
+ return (*a)->n - (*b)->n;
+}
+
+
+static void sort_enums( void )
+{
+ int i;
+ index1 = (enum_elt **)malloc( Elements(all_enums) * sizeof(enum_elt *) );
+ sorted = 1;
+
+ qsort( all_enums, Elements(all_enums), sizeof(*all_enums),
+ (cfunc) compar_name );
+
+ for (i = 0 ; i < Elements(all_enums) ; i++)
+ index1[i] = &all_enums[i];
+
+ qsort( index1, Elements(all_enums), sizeof(*index1), (cfunc) compar_nr );
+}
+
+
+
+int gl_lookup_enum_by_name( const char *symbol )
+{
+ enum_elt tmp;
+ enum_elt *e;
+
+ if (!sorted)
+ sort_enums();
+
+ if (!symbol)
+ return 0;
+
+ tmp.c = symbol;
+ e = (enum_elt *)bsearch( &tmp, all_enums, Elements(all_enums),
+ sizeof(*all_enums), (cfunc) compar_name );
+
+ return e ? e->n : -1;
+}
+
+
+const char *gl_lookup_enum_by_nr( int nr )
+{
+ enum_elt tmp, *e, **f;
+
+ if (!sorted)
+ sort_enums();
+
+ tmp.n = nr;
+ e = &tmp;
+
+ f = (enum_elt **)bsearch( &e, index1, Elements(all_enums),
+ sizeof(*index1), (cfunc) compar_nr );
+
+ return f ? (*f)->c : "(unknown)";
+}
+
+
+#if 0
+int main()
+{
+ int i;
+ static const char *test[] = {
+ "GL_POLYGON",
+ "GL_TRUE",
+ "GL_BANANA",
+ "GL_REFLECTION_MAP_NV",
+ };
+
+ for (i = 0 ; i < Elements(test) ; i++) {
+ int d = gl_lookup_enum_by_name( test[i] );
+ printf("%s --> %d --> %s\n", test[i], d, gl_lookup_enum_by_nr( d ));
+ }
+}
+#endif
diff --git a/src/mesa/main/enums.h b/src/mesa/main/enums.h
new file mode 100644
index 0000000000..028c9b4654
--- /dev/null
+++ b/src/mesa/main/enums.h
@@ -0,0 +1,34 @@
+/* $Id: enums.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+#ifndef _ENUMS_H_
+#define _ENUMS_H_
+
+extern const char *gl_lookup_enum_by_nr( int nr );
+extern int gl_lookup_enum_by_name( const char *symbol );
+
+#endif
diff --git a/src/mesa/main/eval.c b/src/mesa/main/eval.c
new file mode 100644
index 0000000000..74604a21c4
--- /dev/null
+++ b/src/mesa/main/eval.c
@@ -0,0 +1,2725 @@
+/* $Id: eval.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+/*
+ * eval.c was written by
+ * Bernd Barsuhn (bdbarsuh@cip.informatik.uni-erlangen.de) and
+ * Volker Weiss (vrweiss@cip.informatik.uni-erlangen.de).
+ *
+ * My original implementation of evaluators was simplistic and didn't
+ * compute surface normal vectors properly. Bernd and Volker applied
+ * used more sophisticated methods to get better results.
+ *
+ * Thanks guys!
+ */
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include "context.h"
+#include "eval.h"
+#include "macros.h"
+#include "mmath.h"
+#include "types.h"
+#include "vbcull.h"
+#include "vbfill.h"
+#include "vbxform.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+static GLfloat inv_tab[MAX_EVAL_ORDER];
+
+/*
+ * Do one-time initialization for evaluators.
+ */
+void gl_init_eval( void )
+{
+ static int init_flag = 0;
+ GLuint i;
+
+ /* Compute a table of nCr (combination) values used by the
+ * Bernstein polynomial generator.
+ */
+
+ /* KW: precompute 1/x for useful x.
+ */
+ if (init_flag==0)
+ {
+ for (i = 1 ; i < MAX_EVAL_ORDER ; i++)
+ inv_tab[i] = 1.0 / i;
+ }
+
+ init_flag = 1;
+}
+
+
+
+/*
+ * Horner scheme for Bezier curves
+ *
+ * Bezier curves can be computed via a Horner scheme.
+ * Horner is numerically less stable than the de Casteljau
+ * algorithm, but it is faster. For curves of degree n
+ * the complexity of Horner is O(n) and de Casteljau is O(n^2).
+ * Since stability is not important for displaying curve
+ * points I decided to use the Horner scheme.
+ *
+ * A cubic Bezier curve with control points b0, b1, b2, b3 can be
+ * written as
+ *
+ * (([3] [3] ) [3] ) [3]
+ * c(t) = (([0]*s*b0 + [1]*t*b1)*s + [2]*t^2*b2)*s + [3]*t^2*b3
+ *
+ * [n]
+ * where s=1-t and the binomial coefficients [i]. These can
+ * be computed iteratively using the identity:
+ *
+ * [n] [n ] [n]
+ * [i] = (n-i+1)/i * [i-1] and [0] = 1
+ */
+
+
+static void
+horner_bezier_curve(const GLfloat *cp, GLfloat *out, GLfloat t,
+ GLuint dim, GLuint order)
+{
+ GLfloat s, powert;
+ GLuint i, k, bincoeff;
+
+ if(order >= 2)
+ {
+ bincoeff = order-1;
+ s = 1.0-t;
+
+ for(k=0; k<dim; k++)
+ out[k] = s*cp[k] + bincoeff*t*cp[dim+k];
+
+ for(i=2, cp+=2*dim, powert=t*t; i<order; i++, powert*=t, cp +=dim)
+ {
+ bincoeff *= order-i;
+ bincoeff *= inv_tab[i];
+
+ for(k=0; k<dim; k++)
+ out[k] = s*out[k] + bincoeff*powert*cp[k];
+ }
+ }
+ else /* order=1 -> constant curve */
+ {
+ for(k=0; k<dim; k++)
+ out[k] = cp[k];
+ }
+}
+
+/*
+ * Tensor product Bezier surfaces
+ *
+ * Again the Horner scheme is used to compute a point on a
+ * TP Bezier surface. First a control polygon for a curve
+ * on the surface in one parameter direction is computed,
+ * then the point on the curve for the other parameter
+ * direction is evaluated.
+ *
+ * To store the curve control polygon additional storage
+ * for max(uorder,vorder) points is needed in the
+ * control net cn.
+ */
+
+static void
+horner_bezier_surf(GLfloat *cn, GLfloat *out, GLfloat u, GLfloat v,
+ GLuint dim, GLuint uorder, GLuint vorder)
+{
+ GLfloat *cp = cn + uorder*vorder*dim;
+ GLuint i, uinc = vorder*dim;
+
+ if(vorder > uorder)
+ {
+ if(uorder >= 2)
+ {
+ GLfloat s, poweru;
+ GLuint j, k, bincoeff;
+
+ /* Compute the control polygon for the surface-curve in u-direction */
+ for(j=0; j<vorder; j++)
+ {
+ GLfloat *ucp = &cn[j*dim];
+
+ /* Each control point is the point for parameter u on a */
+ /* curve defined by the control polygons in u-direction */
+ bincoeff = uorder-1;
+ s = 1.0-u;
+
+ for(k=0; k<dim; k++)
+ cp[j*dim+k] = s*ucp[k] + bincoeff*u*ucp[uinc+k];
+
+ for(i=2, ucp+=2*uinc, poweru=u*u; i<uorder;
+ i++, poweru*=u, ucp +=uinc)
+ {
+ bincoeff *= uorder-i;
+ bincoeff *= inv_tab[i];
+
+ for(k=0; k<dim; k++)
+ cp[j*dim+k] = s*cp[j*dim+k] + bincoeff*poweru*ucp[k];
+ }
+ }
+
+ /* Evaluate curve point in v */
+ horner_bezier_curve(cp, out, v, dim, vorder);
+ }
+ else /* uorder=1 -> cn defines a curve in v */
+ horner_bezier_curve(cn, out, v, dim, vorder);
+ }
+ else /* vorder <= uorder */
+ {
+ if(vorder > 1)
+ {
+ GLuint i;
+
+ /* Compute the control polygon for the surface-curve in u-direction */
+ for(i=0; i<uorder; i++, cn += uinc)
+ {
+ /* For constant i all cn[i][j] (j=0..vorder) are located */
+ /* on consecutive memory locations, so we can use */
+ /* horner_bezier_curve to compute the control points */
+
+ horner_bezier_curve(cn, &cp[i*dim], v, dim, vorder);
+ }
+
+ /* Evaluate curve point in u */
+ horner_bezier_curve(cp, out, u, dim, uorder);
+ }
+ else /* vorder=1 -> cn defines a curve in u */
+ horner_bezier_curve(cn, out, u, dim, uorder);
+ }
+}
+
+/*
+ * The direct de Casteljau algorithm is used when a point on the
+ * surface and the tangent directions spanning the tangent plane
+ * should be computed (this is needed to compute normals to the
+ * surface). In this case the de Casteljau algorithm approach is
+ * nicer because a point and the partial derivatives can be computed
+ * at the same time. To get the correct tangent length du and dv
+ * must be multiplied with the (u2-u1)/uorder-1 and (v2-v1)/vorder-1.
+ * Since only the directions are needed, this scaling step is omitted.
+ *
+ * De Casteljau needs additional storage for uorder*vorder
+ * values in the control net cn.
+ */
+
+static void
+de_casteljau_surf(GLfloat *cn, GLfloat *out, GLfloat *du, GLfloat *dv,
+ GLfloat u, GLfloat v, GLuint dim,
+ GLuint uorder, GLuint vorder)
+{
+ GLfloat *dcn = cn + uorder*vorder*dim;
+ GLfloat us = 1.0-u, vs = 1.0-v;
+ GLuint h, i, j, k;
+ GLuint minorder = uorder < vorder ? uorder : vorder;
+ GLuint uinc = vorder*dim;
+ GLuint dcuinc = vorder;
+
+ /* Each component is evaluated separately to save buffer space */
+ /* This does not drasticaly decrease the performance of the */
+ /* algorithm. If additional storage for (uorder-1)*(vorder-1) */
+ /* points would be available, the components could be accessed */
+ /* in the innermost loop which could lead to less cache misses. */
+
+#define CN(I,J,K) cn[(I)*uinc+(J)*dim+(K)]
+#define DCN(I, J) dcn[(I)*dcuinc+(J)]
+ if(minorder < 3)
+ {
+ if(uorder==vorder)
+ {
+ for(k=0; k<dim; k++)
+ {
+ /* Derivative direction in u */
+ du[k] = vs*(CN(1,0,k) - CN(0,0,k)) +
+ v*(CN(1,1,k) - CN(0,1,k));
+
+ /* Derivative direction in v */
+ dv[k] = us*(CN(0,1,k) - CN(0,0,k)) +
+ u*(CN(1,1,k) - CN(1,0,k));
+
+ /* bilinear de Casteljau step */
+ out[k] = us*(vs*CN(0,0,k) + v*CN(0,1,k)) +
+ u*(vs*CN(1,0,k) + v*CN(1,1,k));
+ }
+ }
+ else if(minorder == uorder)
+ {
+ for(k=0; k<dim; k++)
+ {
+ /* bilinear de Casteljau step */
+ DCN(1,0) = CN(1,0,k) - CN(0,0,k);
+ DCN(0,0) = us*CN(0,0,k) + u*CN(1,0,k);
+
+ for(j=0; j<vorder-1; j++)
+ {
+ /* for the derivative in u */
+ DCN(1,j+1) = CN(1,j+1,k) - CN(0,j+1,k);
+ DCN(1,j) = vs*DCN(1,j) + v*DCN(1,j+1);
+
+ /* for the `point' */
+ DCN(0,j+1) = us*CN(0,j+1,k) + u*CN(1,j+1,k);
+ DCN(0,j) = vs*DCN(0,j) + v*DCN(0,j+1);
+ }
+
+ /* remaining linear de Casteljau steps until the second last step */
+ for(h=minorder; h<vorder-1; h++)
+ for(j=0; j<vorder-h; j++)
+ {
+ /* for the derivative in u */
+ DCN(1,j) = vs*DCN(1,j) + v*DCN(1,j+1);
+
+ /* for the `point' */
+ DCN(0,j) = vs*DCN(0,j) + v*DCN(0,j+1);
+ }
+
+ /* derivative direction in v */
+ dv[k] = DCN(0,1) - DCN(0,0);
+
+ /* derivative direction in u */
+ du[k] = vs*DCN(1,0) + v*DCN(1,1);
+
+ /* last linear de Casteljau step */
+ out[k] = vs*DCN(0,0) + v*DCN(0,1);
+ }
+ }
+ else /* minorder == vorder */
+ {
+ for(k=0; k<dim; k++)
+ {
+ /* bilinear de Casteljau step */
+ DCN(0,1) = CN(0,1,k) - CN(0,0,k);
+ DCN(0,0) = vs*CN(0,0,k) + v*CN(0,1,k);
+ for(i=0; i<uorder-1; i++)
+ {
+ /* for the derivative in v */
+ DCN(i+1,1) = CN(i+1,1,k) - CN(i+1,0,k);
+ DCN(i,1) = us*DCN(i,1) + u*DCN(i+1,1);
+
+ /* for the `point' */
+ DCN(i+1,0) = vs*CN(i+1,0,k) + v*CN(i+1,1,k);
+ DCN(i,0) = us*DCN(i,0) + u*DCN(i+1,0);
+ }
+
+ /* remaining linear de Casteljau steps until the second last step */
+ for(h=minorder; h<uorder-1; h++)
+ for(i=0; i<uorder-h; i++)
+ {
+ /* for the derivative in v */
+ DCN(i,1) = us*DCN(i,1) + u*DCN(i+1,1);
+
+ /* for the `point' */
+ DCN(i,0) = us*DCN(i,0) + u*DCN(i+1,0);
+ }
+
+ /* derivative direction in u */
+ du[k] = DCN(1,0) - DCN(0,0);
+
+ /* derivative direction in v */
+ dv[k] = us*DCN(0,1) + u*DCN(1,1);
+
+ /* last linear de Casteljau step */
+ out[k] = us*DCN(0,0) + u*DCN(1,0);
+ }
+ }
+ }
+ else if(uorder == vorder)
+ {
+ for(k=0; k<dim; k++)
+ {
+ /* first bilinear de Casteljau step */
+ for(i=0; i<uorder-1; i++)
+ {
+ DCN(i,0) = us*CN(i,0,k) + u*CN(i+1,0,k);
+ for(j=0; j<vorder-1; j++)
+ {
+ DCN(i,j+1) = us*CN(i,j+1,k) + u*CN(i+1,j+1,k);
+ DCN(i,j) = vs*DCN(i,j) + v*DCN(i,j+1);
+ }
+ }
+
+ /* remaining bilinear de Casteljau steps until the second last step */
+ for(h=2; h<minorder-1; h++)
+ for(i=0; i<uorder-h; i++)
+ {
+ DCN(i,0) = us*DCN(i,0) + u*DCN(i+1,0);
+ for(j=0; j<vorder-h; j++)
+ {
+ DCN(i,j+1) = us*DCN(i,j+1) + u*DCN(i+1,j+1);
+ DCN(i,j) = vs*DCN(i,j) + v*DCN(i,j+1);
+ }
+ }
+
+ /* derivative direction in u */
+ du[k] = vs*(DCN(1,0) - DCN(0,0)) +
+ v*(DCN(1,1) - DCN(0,1));
+
+ /* derivative direction in v */
+ dv[k] = us*(DCN(0,1) - DCN(0,0)) +
+ u*(DCN(1,1) - DCN(1,0));
+
+ /* last bilinear de Casteljau step */
+ out[k] = us*(vs*DCN(0,0) + v*DCN(0,1)) +
+ u*(vs*DCN(1,0) + v*DCN(1,1));
+ }
+ }
+ else if(minorder == uorder)
+ {
+ for(k=0; k<dim; k++)
+ {
+ /* first bilinear de Casteljau step */
+ for(i=0; i<uorder-1; i++)
+ {
+ DCN(i,0) = us*CN(i,0,k) + u*CN(i+1,0,k);
+ for(j=0; j<vorder-1; j++)
+ {
+ DCN(i,j+1) = us*CN(i,j+1,k) + u*CN(i+1,j+1,k);
+ DCN(i,j) = vs*DCN(i,j) + v*DCN(i,j+1);
+ }
+ }
+
+ /* remaining bilinear de Casteljau steps until the second last step */
+ for(h=2; h<minorder-1; h++)
+ for(i=0; i<uorder-h; i++)
+ {
+ DCN(i,0) = us*DCN(i,0) + u*DCN(i+1,0);
+ for(j=0; j<vorder-h; j++)
+ {
+ DCN(i,j+1) = us*DCN(i,j+1) + u*DCN(i+1,j+1);
+ DCN(i,j) = vs*DCN(i,j) + v*DCN(i,j+1);
+ }
+ }
+
+ /* last bilinear de Casteljau step */
+ DCN(2,0) = DCN(1,0) - DCN(0,0);
+ DCN(0,0) = us*DCN(0,0) + u*DCN(1,0);
+ for(j=0; j<vorder-1; j++)
+ {
+ /* for the derivative in u */
+ DCN(2,j+1) = DCN(1,j+1) - DCN(0,j+1);
+ DCN(2,j) = vs*DCN(2,j) + v*DCN(2,j+1);
+
+ /* for the `point' */
+ DCN(0,j+1) = us*DCN(0,j+1 ) + u*DCN(1,j+1);
+ DCN(0,j) = vs*DCN(0,j) + v*DCN(0,j+1);
+ }
+
+ /* remaining linear de Casteljau steps until the second last step */
+ for(h=minorder; h<vorder-1; h++)
+ for(j=0; j<vorder-h; j++)
+ {
+ /* for the derivative in u */
+ DCN(2,j) = vs*DCN(2,j) + v*DCN(2,j+1);
+
+ /* for the `point' */
+ DCN(0,j) = vs*DCN(0,j) + v*DCN(0,j+1);
+ }
+
+ /* derivative direction in v */
+ dv[k] = DCN(0,1) - DCN(0,0);
+
+ /* derivative direction in u */
+ du[k] = vs*DCN(2,0) + v*DCN(2,1);
+
+ /* last linear de Casteljau step */
+ out[k] = vs*DCN(0,0) + v*DCN(0,1);
+ }
+ }
+ else /* minorder == vorder */
+ {
+ for(k=0; k<dim; k++)
+ {
+ /* first bilinear de Casteljau step */
+ for(i=0; i<uorder-1; i++)
+ {
+ DCN(i,0) = us*CN(i,0,k) + u*CN(i+1,0,k);
+ for(j=0; j<vorder-1; j++)
+ {
+ DCN(i,j+1) = us*CN(i,j+1,k) + u*CN(i+1,j+1,k);
+ DCN(i,j) = vs*DCN(i,j) + v*DCN(i,j+1);
+ }
+ }
+
+ /* remaining bilinear de Casteljau steps until the second last step */
+ for(h=2; h<minorder-1; h++)
+ for(i=0; i<uorder-h; i++)
+ {
+ DCN(i,0) = us*DCN(i,0) + u*DCN(i+1,0);
+ for(j=0; j<vorder-h; j++)
+ {
+ DCN(i,j+1) = us*DCN(i,j+1) + u*DCN(i+1,j+1);
+ DCN(i,j) = vs*DCN(i,j) + v*DCN(i,j+1);
+ }
+ }
+
+ /* last bilinear de Casteljau step */
+ DCN(0,2) = DCN(0,1) - DCN(0,0);
+ DCN(0,0) = vs*DCN(0,0) + v*DCN(0,1);
+ for(i=0; i<uorder-1; i++)
+ {
+ /* for the derivative in v */
+ DCN(i+1,2) = DCN(i+1,1) - DCN(i+1,0);
+ DCN(i,2) = us*DCN(i,2) + u*DCN(i+1,2);
+
+ /* for the `point' */
+ DCN(i+1,0) = vs*DCN(i+1,0) + v*DCN(i+1,1);
+ DCN(i,0) = us*DCN(i,0) + u*DCN(i+1,0);
+ }
+
+ /* remaining linear de Casteljau steps until the second last step */
+ for(h=minorder; h<uorder-1; h++)
+ for(i=0; i<uorder-h; i++)
+ {
+ /* for the derivative in v */
+ DCN(i,2) = us*DCN(i,2) + u*DCN(i+1,2);
+
+ /* for the `point' */
+ DCN(i,0) = us*DCN(i,0) + u*DCN(i+1,0);
+ }
+
+ /* derivative direction in u */
+ du[k] = DCN(1,0) - DCN(0,0);
+
+ /* derivative direction in v */
+ dv[k] = us*DCN(0,2) + u*DCN(1,2);
+
+ /* last linear de Casteljau step */
+ out[k] = us*DCN(0,0) + u*DCN(1,0);
+ }
+ }
+#undef DCN
+#undef CN
+}
+
+/*
+ * Return the number of components per control point for any type of
+ * evaluator. Return 0 if bad target.
+ */
+
+static GLint components( GLenum target )
+{
+ switch (target) {
+ case GL_MAP1_VERTEX_3: return 3;
+ case GL_MAP1_VERTEX_4: return 4;
+ case GL_MAP1_INDEX: return 1;
+ case GL_MAP1_COLOR_4: return 4;
+ case GL_MAP1_NORMAL: return 3;
+ case GL_MAP1_TEXTURE_COORD_1: return 1;
+ case GL_MAP1_TEXTURE_COORD_2: return 2;
+ case GL_MAP1_TEXTURE_COORD_3: return 3;
+ case GL_MAP1_TEXTURE_COORD_4: return 4;
+ case GL_MAP2_VERTEX_3: return 3;
+ case GL_MAP2_VERTEX_4: return 4;
+ case GL_MAP2_INDEX: return 1;
+ case GL_MAP2_COLOR_4: return 4;
+ case GL_MAP2_NORMAL: return 3;
+ case GL_MAP2_TEXTURE_COORD_1: return 1;
+ case GL_MAP2_TEXTURE_COORD_2: return 2;
+ case GL_MAP2_TEXTURE_COORD_3: return 3;
+ case GL_MAP2_TEXTURE_COORD_4: return 4;
+ default: return 0;
+ }
+}
+
+
+/**********************************************************************/
+/*** Copy and deallocate control points ***/
+/**********************************************************************/
+
+
+/*
+ * Copy 1-parametric evaluator control points from user-specified
+ * memory space to a buffer of contiguous control points.
+ * Input: see glMap1f for details
+ * Return: pointer to buffer of contiguous control points or NULL if out
+ * of memory.
+ */
+GLfloat *gl_copy_map_points1f( GLenum target,
+ GLint ustride, GLint uorder,
+ const GLfloat *points )
+{
+ GLfloat *buffer, *p;
+ GLint i, k, size = components(target);
+
+ if (!points || size==0) {
+ return NULL;
+ }
+
+ buffer = (GLfloat *) malloc(uorder * size * sizeof(GLfloat));
+
+ if(buffer)
+ for(i=0, p=buffer; i<uorder; i++, points+=ustride)
+ for(k=0; k<size; k++)
+ *p++ = points[k];
+
+ return buffer;
+}
+
+
+
+/*
+ * Same as above but convert doubles to floats.
+ */
+GLfloat *gl_copy_map_points1d( GLenum target,
+ GLint ustride, GLint uorder,
+ const GLdouble *points )
+{
+ GLfloat *buffer, *p;
+ GLint i, k, size = components(target);
+
+ if (!points || size==0) {
+ return NULL;
+ }
+
+ buffer = (GLfloat *) malloc(uorder * size * sizeof(GLfloat));
+
+ if(buffer)
+ for(i=0, p=buffer; i<uorder; i++, points+=ustride)
+ for(k=0; k<size; k++)
+ *p++ = (GLfloat) points[k];
+
+ return buffer;
+}
+
+
+
+/*
+ * Copy 2-parametric evaluator control points from user-specified
+ * memory space to a buffer of contiguous control points.
+ * Additional memory is allocated to be used by the horner and
+ * de Casteljau evaluation schemes.
+ *
+ * Input: see glMap2f for details
+ * Return: pointer to buffer of contiguous control points or NULL if out
+ * of memory.
+ */
+GLfloat *gl_copy_map_points2f( GLenum target,
+ GLint ustride, GLint uorder,
+ GLint vstride, GLint vorder,
+ const GLfloat *points )
+{
+ GLfloat *buffer, *p;
+ GLint i, j, k, size, dsize, hsize;
+ GLint uinc;
+
+ size = components(target);
+
+ if (!points || size==0) {
+ return NULL;
+ }
+
+ /* max(uorder, vorder) additional points are used in */
+ /* horner evaluation and uorder*vorder additional */
+ /* values are needed for de Casteljau */
+ dsize = (uorder == 2 && vorder == 2)? 0 : uorder*vorder;
+ hsize = (uorder > vorder ? uorder : vorder)*size;
+
+ if(hsize>dsize)
+ buffer = (GLfloat *) malloc((uorder*vorder*size+hsize)*sizeof(GLfloat));
+ else
+ buffer = (GLfloat *) malloc((uorder*vorder*size+dsize)*sizeof(GLfloat));
+
+ /* compute the increment value for the u-loop */
+ uinc = ustride - vorder*vstride;
+
+ if (buffer)
+ for (i=0, p=buffer; i<uorder; i++, points += uinc)
+ for (j=0; j<vorder; j++, points += vstride)
+ for (k=0; k<size; k++)
+ *p++ = points[k];
+
+ return buffer;
+}
+
+
+
+/*
+ * Same as above but convert doubles to floats.
+ */
+GLfloat *gl_copy_map_points2d(GLenum target,
+ GLint ustride, GLint uorder,
+ GLint vstride, GLint vorder,
+ const GLdouble *points )
+{
+ GLfloat *buffer, *p;
+ GLint i, j, k, size, hsize, dsize;
+ GLint uinc;
+
+ size = components(target);
+
+ if (!points || size==0) {
+ return NULL;
+ }
+
+ /* max(uorder, vorder) additional points are used in */
+ /* horner evaluation and uorder*vorder additional */
+ /* values are needed for de Casteljau */
+ dsize = (uorder == 2 && vorder == 2)? 0 : uorder*vorder;
+ hsize = (uorder > vorder ? uorder : vorder)*size;
+
+ if(hsize>dsize)
+ buffer = (GLfloat *) malloc((uorder*vorder*size+hsize)*sizeof(GLfloat));
+ else
+ buffer = (GLfloat *) malloc((uorder*vorder*size+dsize)*sizeof(GLfloat));
+
+ /* compute the increment value for the u-loop */
+ uinc = ustride - vorder*vstride;
+
+ if (buffer)
+ for (i=0, p=buffer; i<uorder; i++, points += uinc)
+ for (j=0; j<vorder; j++, points += vstride)
+ for (k=0; k<size; k++)
+ *p++ = (GLfloat) points[k];
+
+ return buffer;
+}
+
+
+/*
+ * This function is called by the display list deallocator function to
+ * specify that a given set of control points are no longer needed.
+ */
+void gl_free_control_points( GLcontext* ctx, GLenum target, GLfloat *data )
+{
+ struct gl_1d_map *map1 = NULL;
+ struct gl_2d_map *map2 = NULL;
+
+ switch (target) {
+ case GL_MAP1_VERTEX_3:
+ map1 = &ctx->EvalMap.Map1Vertex3;
+ break;
+ case GL_MAP1_VERTEX_4:
+ map1 = &ctx->EvalMap.Map1Vertex4;
+ break;
+ case GL_MAP1_INDEX:
+ map1 = &ctx->EvalMap.Map1Index;
+ break;
+ case GL_MAP1_COLOR_4:
+ map1 = &ctx->EvalMap.Map1Color4;
+ break;
+ case GL_MAP1_NORMAL:
+ map1 = &ctx->EvalMap.Map1Normal;
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ map1 = &ctx->EvalMap.Map1Texture1;
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ map1 = &ctx->EvalMap.Map1Texture2;
+ break;
+ case GL_MAP1_TEXTURE_COORD_3:
+ map1 = &ctx->EvalMap.Map1Texture3;
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ map1 = &ctx->EvalMap.Map1Texture4;
+ break;
+ case GL_MAP2_VERTEX_3:
+ map2 = &ctx->EvalMap.Map2Vertex3;
+ break;
+ case GL_MAP2_VERTEX_4:
+ map2 = &ctx->EvalMap.Map2Vertex4;
+ break;
+ case GL_MAP2_INDEX:
+ map2 = &ctx->EvalMap.Map2Index;
+ break;
+ case GL_MAP2_COLOR_4:
+ map2 = &ctx->EvalMap.Map2Color4;
+ break;
+ case GL_MAP2_NORMAL:
+ map2 = &ctx->EvalMap.Map2Normal;
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ map2 = &ctx->EvalMap.Map2Texture1;
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ map2 = &ctx->EvalMap.Map2Texture2;
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ map2 = &ctx->EvalMap.Map2Texture3;
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ map2 = &ctx->EvalMap.Map2Texture4;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "gl_free_control_points" );
+ return;
+ }
+
+ if (map1) {
+ if (data==map1->Points) {
+ /* The control points in the display list are currently */
+ /* being used so we can mark them as discard-able. */
+ map1->Retain = GL_FALSE;
+ }
+ else {
+ /* The control points in the display list are not currently */
+ /* being used. */
+ free( data );
+ }
+ }
+ if (map2) {
+ if (data==map2->Points) {
+ /* The control points in the display list are currently */
+ /* being used so we can mark them as discard-able. */
+ map2->Retain = GL_FALSE;
+ }
+ else {
+ /* The control points in the display list are not currently */
+ /* being used. */
+ free( data );
+ }
+ }
+
+}
+
+
+
+/**********************************************************************/
+/*** API entry points ***/
+/**********************************************************************/
+
+
+/*
+ * Note that the array of control points must be 'unpacked' at this time.
+ * Input: retain - if TRUE, this control point data is also in a display
+ * list and can't be freed until the list is freed.
+ */
+void gl_Map1f( GLcontext* ctx, GLenum target,
+ GLfloat u1, GLfloat u2, GLint stride,
+ GLint order, const GLfloat *points, GLboolean retain )
+{
+ GLint k;
+
+ if (!points) {
+ gl_error( ctx, GL_OUT_OF_MEMORY, "glMap1f" );
+ return;
+ }
+
+ /* may be a new stride after copying control points */
+ stride = components( target );
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glMap1");
+
+ if (u1==u2) {
+ gl_error( ctx, GL_INVALID_VALUE, "glMap1(u1,u2)" );
+ return;
+ }
+
+ if (order<1 || order>MAX_EVAL_ORDER) {
+ gl_error( ctx, GL_INVALID_VALUE, "glMap1(order)" );
+ return;
+ }
+
+ k = components( target );
+ if (k==0) {
+ gl_error( ctx, GL_INVALID_ENUM, "glMap1(target)" );
+ }
+
+ if (stride < k) {
+ gl_error( ctx, GL_INVALID_VALUE, "glMap1(stride)" );
+ return;
+ }
+
+ switch (target) {
+ case GL_MAP1_VERTEX_3:
+ ctx->EvalMap.Map1Vertex3.Order = order;
+ ctx->EvalMap.Map1Vertex3.u1 = u1;
+ ctx->EvalMap.Map1Vertex3.u2 = u2;
+ ctx->EvalMap.Map1Vertex3.du = 1.0 / (u2 - u1);
+ if (ctx->EvalMap.Map1Vertex3.Points
+ && !ctx->EvalMap.Map1Vertex3.Retain) {
+ free( ctx->EvalMap.Map1Vertex3.Points );
+ }
+ ctx->EvalMap.Map1Vertex3.Points = (GLfloat *) points;
+ ctx->EvalMap.Map1Vertex3.Retain = retain;
+ break;
+ case GL_MAP1_VERTEX_4:
+ ctx->EvalMap.Map1Vertex4.Order = order;
+ ctx->EvalMap.Map1Vertex4.u1 = u1;
+ ctx->EvalMap.Map1Vertex4.u2 = u2;
+ ctx->EvalMap.Map1Vertex4.du = 1.0 / (u2 - u1);
+ if (ctx->EvalMap.Map1Vertex4.Points
+ && !ctx->EvalMap.Map1Vertex4.Retain) {
+ free( ctx->EvalMap.Map1Vertex4.Points );
+ }
+ ctx->EvalMap.Map1Vertex4.Points = (GLfloat *) points;
+ ctx->EvalMap.Map1Vertex4.Retain = retain;
+ break;
+ case GL_MAP1_INDEX:
+ ctx->EvalMap.Map1Index.Order = order;
+ ctx->EvalMap.Map1Index.u1 = u1;
+ ctx->EvalMap.Map1Index.u2 = u2;
+ ctx->EvalMap.Map1Index.du = 1.0 / (u2 - u1);
+ if (ctx->EvalMap.Map1Index.Points
+ && !ctx->EvalMap.Map1Index.Retain) {
+ free( ctx->EvalMap.Map1Index.Points );
+ }
+ ctx->EvalMap.Map1Index.Points = (GLfloat *) points;
+ ctx->EvalMap.Map1Index.Retain = retain;
+ break;
+ case GL_MAP1_COLOR_4:
+ ctx->EvalMap.Map1Color4.Order = order;
+ ctx->EvalMap.Map1Color4.u1 = u1;
+ ctx->EvalMap.Map1Color4.u2 = u2;
+ ctx->EvalMap.Map1Color4.du = 1.0 / (u2 - u1);
+ if (ctx->EvalMap.Map1Color4.Points
+ && !ctx->EvalMap.Map1Color4.Retain) {
+ free( ctx->EvalMap.Map1Color4.Points );
+ }
+ ctx->EvalMap.Map1Color4.Points = (GLfloat *) points;
+ ctx->EvalMap.Map1Color4.Retain = retain;
+ break;
+ case GL_MAP1_NORMAL:
+ ctx->EvalMap.Map1Normal.Order = order;
+ ctx->EvalMap.Map1Normal.u1 = u1;
+ ctx->EvalMap.Map1Normal.u2 = u2;
+ ctx->EvalMap.Map1Normal.du = 1.0 / (u2 - u1);
+ if (ctx->EvalMap.Map1Normal.Points
+ && !ctx->EvalMap.Map1Normal.Retain) {
+ free( ctx->EvalMap.Map1Normal.Points );
+ }
+ ctx->EvalMap.Map1Normal.Points = (GLfloat *) points;
+ ctx->EvalMap.Map1Normal.Retain = retain;
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ ctx->EvalMap.Map1Texture1.Order = order;
+ ctx->EvalMap.Map1Texture1.u1 = u1;
+ ctx->EvalMap.Map1Texture1.u2 = u2;
+ ctx->EvalMap.Map1Texture1.du = 1.0 / (u2 - u1);
+ if (ctx->EvalMap.Map1Texture1.Points
+ && !ctx->EvalMap.Map1Texture1.Retain) {
+ free( ctx->EvalMap.Map1Texture1.Points );
+ }
+ ctx->EvalMap.Map1Texture1.Points = (GLfloat *) points;
+ ctx->EvalMap.Map1Texture1.Retain = retain;
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ ctx->EvalMap.Map1Texture2.Order = order;
+ ctx->EvalMap.Map1Texture2.u1 = u1;
+ ctx->EvalMap.Map1Texture2.u2 = u2;
+ ctx->EvalMap.Map1Texture2.du = 1.0 / (u2 - u1);
+ if (ctx->EvalMap.Map1Texture2.Points
+ && !ctx->EvalMap.Map1Texture2.Retain) {
+ free( ctx->EvalMap.Map1Texture2.Points );
+ }
+ ctx->EvalMap.Map1Texture2.Points = (GLfloat *) points;
+ ctx->EvalMap.Map1Texture2.Retain = retain;
+ break;
+ case GL_MAP1_TEXTURE_COORD_3:
+ ctx->EvalMap.Map1Texture3.Order = order;
+ ctx->EvalMap.Map1Texture3.u1 = u1;
+ ctx->EvalMap.Map1Texture3.u2 = u2;
+ ctx->EvalMap.Map1Texture3.du = 1.0 / (u2 - u1);
+ if (ctx->EvalMap.Map1Texture3.Points
+ && !ctx->EvalMap.Map1Texture3.Retain) {
+ free( ctx->EvalMap.Map1Texture3.Points );
+ }
+ ctx->EvalMap.Map1Texture3.Points = (GLfloat *) points;
+ ctx->EvalMap.Map1Texture3.Retain = retain;
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ ctx->EvalMap.Map1Texture4.Order = order;
+ ctx->EvalMap.Map1Texture4.u1 = u1;
+ ctx->EvalMap.Map1Texture4.u2 = u2;
+ ctx->EvalMap.Map1Texture4.du = 1.0 / (u2 - u1);
+ if (ctx->EvalMap.Map1Texture4.Points
+ && !ctx->EvalMap.Map1Texture4.Retain) {
+ free( ctx->EvalMap.Map1Texture4.Points );
+ }
+ ctx->EvalMap.Map1Texture4.Points = (GLfloat *) points;
+ ctx->EvalMap.Map1Texture4.Retain = retain;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glMap1(target)" );
+ }
+}
+
+
+
+
+/*
+ * Note that the array of control points must be 'unpacked' at this time.
+ * Input: retain - if TRUE, this control point data is also in a display
+ * list and can't be freed until the list is freed.
+ */
+void gl_Map2f( GLcontext* ctx, GLenum target,
+ GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
+ GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
+ const GLfloat *points, GLboolean retain )
+{
+ GLint k;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glMap2");
+
+ if (u1==u2) {
+ gl_error( ctx, GL_INVALID_VALUE, "glMap2(u1,u2)" );
+ return;
+ }
+
+ if (v1==v2) {
+ gl_error( ctx, GL_INVALID_VALUE, "glMap2(v1,v2)" );
+ return;
+ }
+
+ if (uorder<1 || uorder>MAX_EVAL_ORDER) {
+ gl_error( ctx, GL_INVALID_VALUE, "glMap2(uorder)" );
+ return;
+ }
+
+ if (vorder<1 || vorder>MAX_EVAL_ORDER) {
+ gl_error( ctx, GL_INVALID_VALUE, "glMap2(vorder)" );
+ return;
+ }
+
+ k = components( target );
+ if (k==0) {
+ gl_error( ctx, GL_INVALID_ENUM, "glMap2(target)" );
+ }
+
+ if (ustride < k) {
+ gl_error( ctx, GL_INVALID_VALUE, "glMap2(ustride)" );
+ return;
+ }
+ if (vstride < k) {
+ gl_error( ctx, GL_INVALID_VALUE, "glMap2(vstride)" );
+ return;
+ }
+
+ switch (target) {
+ case GL_MAP2_VERTEX_3:
+ ctx->EvalMap.Map2Vertex3.Uorder = uorder;
+ ctx->EvalMap.Map2Vertex3.u1 = u1;
+ ctx->EvalMap.Map2Vertex3.u2 = u2;
+ ctx->EvalMap.Map2Vertex3.du = 1.0 / (u2 - u1);
+ ctx->EvalMap.Map2Vertex3.Vorder = vorder;
+ ctx->EvalMap.Map2Vertex3.v1 = v1;
+ ctx->EvalMap.Map2Vertex3.v2 = v2;
+ ctx->EvalMap.Map2Vertex3.dv = 1.0 / (v2 - v1);
+ if (ctx->EvalMap.Map2Vertex3.Points
+ && !ctx->EvalMap.Map2Vertex3.Retain) {
+ free( ctx->EvalMap.Map2Vertex3.Points );
+ }
+ ctx->EvalMap.Map2Vertex3.Retain = retain;
+ ctx->EvalMap.Map2Vertex3.Points = (GLfloat *) points;
+ break;
+ case GL_MAP2_VERTEX_4:
+ ctx->EvalMap.Map2Vertex4.Uorder = uorder;
+ ctx->EvalMap.Map2Vertex4.u1 = u1;
+ ctx->EvalMap.Map2Vertex4.u2 = u2;
+ ctx->EvalMap.Map2Vertex4.du = 1.0 / (u2 - u1);
+ ctx->EvalMap.Map2Vertex4.Vorder = vorder;
+ ctx->EvalMap.Map2Vertex4.v1 = v1;
+ ctx->EvalMap.Map2Vertex4.v2 = v2;
+ ctx->EvalMap.Map2Vertex4.dv = 1.0 / (v2 - v1);
+ if (ctx->EvalMap.Map2Vertex4.Points
+ && !ctx->EvalMap.Map2Vertex4.Retain) {
+ free( ctx->EvalMap.Map2Vertex4.Points );
+ }
+ ctx->EvalMap.Map2Vertex4.Points = (GLfloat *) points;
+ ctx->EvalMap.Map2Vertex4.Retain = retain;
+ break;
+ case GL_MAP2_INDEX:
+ ctx->EvalMap.Map2Index.Uorder = uorder;
+ ctx->EvalMap.Map2Index.u1 = u1;
+ ctx->EvalMap.Map2Index.u2 = u2;
+ ctx->EvalMap.Map2Index.du = 1.0 / (u2 - u1);
+ ctx->EvalMap.Map2Index.Vorder = vorder;
+ ctx->EvalMap.Map2Index.v1 = v1;
+ ctx->EvalMap.Map2Index.v2 = v2;
+ ctx->EvalMap.Map2Index.dv = 1.0 / (v2 - v1);
+ if (ctx->EvalMap.Map2Index.Points
+ && !ctx->EvalMap.Map2Index.Retain) {
+ free( ctx->EvalMap.Map2Index.Points );
+ }
+ ctx->EvalMap.Map2Index.Retain = retain;
+ ctx->EvalMap.Map2Index.Points = (GLfloat *) points;
+ break;
+ case GL_MAP2_COLOR_4:
+ ctx->EvalMap.Map2Color4.Uorder = uorder;
+ ctx->EvalMap.Map2Color4.u1 = u1;
+ ctx->EvalMap.Map2Color4.u2 = u2;
+ ctx->EvalMap.Map2Color4.du = 1.0 / (u2 - u1);
+ ctx->EvalMap.Map2Color4.Vorder = vorder;
+ ctx->EvalMap.Map2Color4.v1 = v1;
+ ctx->EvalMap.Map2Color4.v2 = v2;
+ ctx->EvalMap.Map2Color4.dv = 1.0 / (v2 - v1);
+ if (ctx->EvalMap.Map2Color4.Points
+ && !ctx->EvalMap.Map2Color4.Retain) {
+ free( ctx->EvalMap.Map2Color4.Points );
+ }
+ ctx->EvalMap.Map2Color4.Retain = retain;
+ ctx->EvalMap.Map2Color4.Points = (GLfloat *) points;
+ break;
+ case GL_MAP2_NORMAL:
+ ctx->EvalMap.Map2Normal.Uorder = uorder;
+ ctx->EvalMap.Map2Normal.u1 = u1;
+ ctx->EvalMap.Map2Normal.u2 = u2;
+ ctx->EvalMap.Map2Normal.du = 1.0 / (u2 - u1);
+ ctx->EvalMap.Map2Normal.Vorder = vorder;
+ ctx->EvalMap.Map2Normal.v1 = v1;
+ ctx->EvalMap.Map2Normal.v2 = v2;
+ ctx->EvalMap.Map2Normal.dv = 1.0 / (v2 - v1);
+ if (ctx->EvalMap.Map2Normal.Points
+ && !ctx->EvalMap.Map2Normal.Retain) {
+ free( ctx->EvalMap.Map2Normal.Points );
+ }
+ ctx->EvalMap.Map2Normal.Retain = retain;
+ ctx->EvalMap.Map2Normal.Points = (GLfloat *) points;
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ ctx->EvalMap.Map2Texture1.Uorder = uorder;
+ ctx->EvalMap.Map2Texture1.u1 = u1;
+ ctx->EvalMap.Map2Texture1.u2 = u2;
+ ctx->EvalMap.Map2Texture1.du = 1.0 / (u2 - u1);
+ ctx->EvalMap.Map2Texture1.Vorder = vorder;
+ ctx->EvalMap.Map2Texture1.v1 = v1;
+ ctx->EvalMap.Map2Texture1.v2 = v2;
+ ctx->EvalMap.Map2Texture1.dv = 1.0 / (v2 - v1);
+ if (ctx->EvalMap.Map2Texture1.Points
+ && !ctx->EvalMap.Map2Texture1.Retain) {
+ free( ctx->EvalMap.Map2Texture1.Points );
+ }
+ ctx->EvalMap.Map2Texture1.Retain = retain;
+ ctx->EvalMap.Map2Texture1.Points = (GLfloat *) points;
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ ctx->EvalMap.Map2Texture2.Uorder = uorder;
+ ctx->EvalMap.Map2Texture2.u1 = u1;
+ ctx->EvalMap.Map2Texture2.u2 = u2;
+ ctx->EvalMap.Map2Texture2.du = 1.0 / (u2 - u1);
+ ctx->EvalMap.Map2Texture2.Vorder = vorder;
+ ctx->EvalMap.Map2Texture2.v1 = v1;
+ ctx->EvalMap.Map2Texture2.v2 = v2;
+ ctx->EvalMap.Map2Texture2.dv = 1.0 / (v2 - v1);
+ if (ctx->EvalMap.Map2Texture2.Points
+ && !ctx->EvalMap.Map2Texture2.Retain) {
+ free( ctx->EvalMap.Map2Texture2.Points );
+ }
+ ctx->EvalMap.Map2Texture2.Retain = retain;
+ ctx->EvalMap.Map2Texture2.Points = (GLfloat *) points;
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ ctx->EvalMap.Map2Texture3.Uorder = uorder;
+ ctx->EvalMap.Map2Texture3.u1 = u1;
+ ctx->EvalMap.Map2Texture3.u2 = u2;
+ ctx->EvalMap.Map2Texture3.du = 1.0 / (u2 - u1);
+ ctx->EvalMap.Map2Texture3.Vorder = vorder;
+ ctx->EvalMap.Map2Texture3.v1 = v1;
+ ctx->EvalMap.Map2Texture3.v2 = v2;
+ ctx->EvalMap.Map2Texture3.dv = 1.0 / (v2 - v1);
+ if (ctx->EvalMap.Map2Texture3.Points
+ && !ctx->EvalMap.Map2Texture3.Retain) {
+ free( ctx->EvalMap.Map2Texture3.Points );
+ }
+ ctx->EvalMap.Map2Texture3.Retain = retain;
+ ctx->EvalMap.Map2Texture3.Points = (GLfloat *) points;
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ ctx->EvalMap.Map2Texture4.Uorder = uorder;
+ ctx->EvalMap.Map2Texture4.u1 = u1;
+ ctx->EvalMap.Map2Texture4.u2 = u2;
+ ctx->EvalMap.Map2Texture4.du = 1.0 / (u2 - u1);
+ ctx->EvalMap.Map2Texture4.Vorder = vorder;
+ ctx->EvalMap.Map2Texture4.v1 = v1;
+ ctx->EvalMap.Map2Texture4.v2 = v2;
+ ctx->EvalMap.Map2Texture4.dv = 1.0 / (v2 - v1);
+ if (ctx->EvalMap.Map2Texture4.Points
+ && !ctx->EvalMap.Map2Texture4.Retain) {
+ free( ctx->EvalMap.Map2Texture4.Points );
+ }
+ ctx->EvalMap.Map2Texture4.Retain = retain;
+ ctx->EvalMap.Map2Texture4.Points = (GLfloat *) points;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glMap2(target)" );
+ }
+}
+
+
+
+
+
+void gl_GetMapdv( GLcontext* ctx, GLenum target, GLenum query, GLdouble *v )
+{
+ GLint i, n;
+ GLfloat *data;
+
+ switch (query) {
+ case GL_COEFF:
+ switch (target) {
+ case GL_MAP1_COLOR_4:
+ data = ctx->EvalMap.Map1Color4.Points;
+ n = ctx->EvalMap.Map1Color4.Order * 4;
+ break;
+ case GL_MAP1_INDEX:
+ data = ctx->EvalMap.Map1Index.Points;
+ n = ctx->EvalMap.Map1Index.Order;
+ break;
+ case GL_MAP1_NORMAL:
+ data = ctx->EvalMap.Map1Normal.Points;
+ n = ctx->EvalMap.Map1Normal.Order * 3;
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ data = ctx->EvalMap.Map1Texture1.Points;
+ n = ctx->EvalMap.Map1Texture1.Order * 1;
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ data = ctx->EvalMap.Map1Texture2.Points;
+ n = ctx->EvalMap.Map1Texture2.Order * 2;
+ break;
+ case GL_MAP1_TEXTURE_COORD_3:
+ data = ctx->EvalMap.Map1Texture3.Points;
+ n = ctx->EvalMap.Map1Texture3.Order * 3;
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ data = ctx->EvalMap.Map1Texture4.Points;
+ n = ctx->EvalMap.Map1Texture4.Order * 4;
+ break;
+ case GL_MAP1_VERTEX_3:
+ data = ctx->EvalMap.Map1Vertex3.Points;
+ n = ctx->EvalMap.Map1Vertex3.Order * 3;
+ break;
+ case GL_MAP1_VERTEX_4:
+ data = ctx->EvalMap.Map1Vertex4.Points;
+ n = ctx->EvalMap.Map1Vertex4.Order * 4;
+ break;
+ case GL_MAP2_COLOR_4:
+ data = ctx->EvalMap.Map2Color4.Points;
+ n = ctx->EvalMap.Map2Color4.Uorder
+ * ctx->EvalMap.Map2Color4.Vorder * 4;
+ break;
+ case GL_MAP2_INDEX:
+ data = ctx->EvalMap.Map2Index.Points;
+ n = ctx->EvalMap.Map2Index.Uorder
+ * ctx->EvalMap.Map2Index.Vorder;
+ break;
+ case GL_MAP2_NORMAL:
+ data = ctx->EvalMap.Map2Normal.Points;
+ n = ctx->EvalMap.Map2Normal.Uorder
+ * ctx->EvalMap.Map2Normal.Vorder * 3;
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ data = ctx->EvalMap.Map2Texture1.Points;
+ n = ctx->EvalMap.Map2Texture1.Uorder
+ * ctx->EvalMap.Map2Texture1.Vorder * 1;
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ data = ctx->EvalMap.Map2Texture2.Points;
+ n = ctx->EvalMap.Map2Texture2.Uorder
+ * ctx->EvalMap.Map2Texture2.Vorder * 2;
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ data = ctx->EvalMap.Map2Texture3.Points;
+ n = ctx->EvalMap.Map2Texture3.Uorder
+ * ctx->EvalMap.Map2Texture3.Vorder * 3;
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ data = ctx->EvalMap.Map2Texture4.Points;
+ n = ctx->EvalMap.Map2Texture4.Uorder
+ * ctx->EvalMap.Map2Texture4.Vorder * 4;
+ break;
+ case GL_MAP2_VERTEX_3:
+ data = ctx->EvalMap.Map2Vertex3.Points;
+ n = ctx->EvalMap.Map2Vertex3.Uorder
+ * ctx->EvalMap.Map2Vertex3.Vorder * 3;
+ break;
+ case GL_MAP2_VERTEX_4:
+ data = ctx->EvalMap.Map2Vertex4.Points;
+ n = ctx->EvalMap.Map2Vertex4.Uorder
+ * ctx->EvalMap.Map2Vertex4.Vorder * 4;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetMapdv(target)" );
+ return;
+ }
+ if (data) {
+ for (i=0;i<n;i++) {
+ v[i] = data[i];
+ }
+ }
+ break;
+ case GL_ORDER:
+ switch (target) {
+ case GL_MAP1_COLOR_4:
+ *v = ctx->EvalMap.Map1Color4.Order;
+ break;
+ case GL_MAP1_INDEX:
+ *v = ctx->EvalMap.Map1Index.Order;
+ break;
+ case GL_MAP1_NORMAL:
+ *v = ctx->EvalMap.Map1Normal.Order;
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ *v = ctx->EvalMap.Map1Texture1.Order;
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ *v = ctx->EvalMap.Map1Texture2.Order;
+ break;
+ case GL_MAP1_TEXTURE_COORD_3:
+ *v = ctx->EvalMap.Map1Texture3.Order;
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ *v = ctx->EvalMap.Map1Texture4.Order;
+ break;
+ case GL_MAP1_VERTEX_3:
+ *v = ctx->EvalMap.Map1Vertex3.Order;
+ break;
+ case GL_MAP1_VERTEX_4:
+ *v = ctx->EvalMap.Map1Vertex4.Order;
+ break;
+ case GL_MAP2_COLOR_4:
+ v[0] = ctx->EvalMap.Map2Color4.Uorder;
+ v[1] = ctx->EvalMap.Map2Color4.Vorder;
+ break;
+ case GL_MAP2_INDEX:
+ v[0] = ctx->EvalMap.Map2Index.Uorder;
+ v[1] = ctx->EvalMap.Map2Index.Vorder;
+ break;
+ case GL_MAP2_NORMAL:
+ v[0] = ctx->EvalMap.Map2Normal.Uorder;
+ v[1] = ctx->EvalMap.Map2Normal.Vorder;
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ v[0] = ctx->EvalMap.Map2Texture1.Uorder;
+ v[1] = ctx->EvalMap.Map2Texture1.Vorder;
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ v[0] = ctx->EvalMap.Map2Texture2.Uorder;
+ v[1] = ctx->EvalMap.Map2Texture2.Vorder;
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ v[0] = ctx->EvalMap.Map2Texture3.Uorder;
+ v[1] = ctx->EvalMap.Map2Texture3.Vorder;
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ v[0] = ctx->EvalMap.Map2Texture4.Uorder;
+ v[1] = ctx->EvalMap.Map2Texture4.Vorder;
+ break;
+ case GL_MAP2_VERTEX_3:
+ v[0] = ctx->EvalMap.Map2Vertex3.Uorder;
+ v[1] = ctx->EvalMap.Map2Vertex3.Vorder;
+ break;
+ case GL_MAP2_VERTEX_4:
+ v[0] = ctx->EvalMap.Map2Vertex4.Uorder;
+ v[1] = ctx->EvalMap.Map2Vertex4.Vorder;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetMapdv(target)" );
+ return;
+ }
+ break;
+ case GL_DOMAIN:
+ switch (target) {
+ case GL_MAP1_COLOR_4:
+ v[0] = ctx->EvalMap.Map1Color4.u1;
+ v[1] = ctx->EvalMap.Map1Color4.u2;
+ break;
+ case GL_MAP1_INDEX:
+ v[0] = ctx->EvalMap.Map1Index.u1;
+ v[1] = ctx->EvalMap.Map1Index.u2;
+ break;
+ case GL_MAP1_NORMAL:
+ v[0] = ctx->EvalMap.Map1Normal.u1;
+ v[1] = ctx->EvalMap.Map1Normal.u2;
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ v[0] = ctx->EvalMap.Map1Texture1.u1;
+ v[1] = ctx->EvalMap.Map1Texture1.u2;
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ v[0] = ctx->EvalMap.Map1Texture2.u1;
+ v[1] = ctx->EvalMap.Map1Texture2.u2;
+ break;
+ case GL_MAP1_TEXTURE_COORD_3:
+ v[0] = ctx->EvalMap.Map1Texture3.u1;
+ v[1] = ctx->EvalMap.Map1Texture3.u2;
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ v[0] = ctx->EvalMap.Map1Texture4.u1;
+ v[1] = ctx->EvalMap.Map1Texture4.u2;
+ break;
+ case GL_MAP1_VERTEX_3:
+ v[0] = ctx->EvalMap.Map1Vertex3.u1;
+ v[1] = ctx->EvalMap.Map1Vertex3.u2;
+ break;
+ case GL_MAP1_VERTEX_4:
+ v[0] = ctx->EvalMap.Map1Vertex4.u1;
+ v[1] = ctx->EvalMap.Map1Vertex4.u2;
+ break;
+ case GL_MAP2_COLOR_4:
+ v[0] = ctx->EvalMap.Map2Color4.u1;
+ v[1] = ctx->EvalMap.Map2Color4.u2;
+ v[2] = ctx->EvalMap.Map2Color4.v1;
+ v[3] = ctx->EvalMap.Map2Color4.v2;
+ break;
+ case GL_MAP2_INDEX:
+ v[0] = ctx->EvalMap.Map2Index.u1;
+ v[1] = ctx->EvalMap.Map2Index.u2;
+ v[2] = ctx->EvalMap.Map2Index.v1;
+ v[3] = ctx->EvalMap.Map2Index.v2;
+ break;
+ case GL_MAP2_NORMAL:
+ v[0] = ctx->EvalMap.Map2Normal.u1;
+ v[1] = ctx->EvalMap.Map2Normal.u2;
+ v[2] = ctx->EvalMap.Map2Normal.v1;
+ v[3] = ctx->EvalMap.Map2Normal.v2;
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ v[0] = ctx->EvalMap.Map2Texture1.u1;
+ v[1] = ctx->EvalMap.Map2Texture1.u2;
+ v[2] = ctx->EvalMap.Map2Texture1.v1;
+ v[3] = ctx->EvalMap.Map2Texture1.v2;
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ v[0] = ctx->EvalMap.Map2Texture2.u1;
+ v[1] = ctx->EvalMap.Map2Texture2.u2;
+ v[2] = ctx->EvalMap.Map2Texture2.v1;
+ v[3] = ctx->EvalMap.Map2Texture2.v2;
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ v[0] = ctx->EvalMap.Map2Texture3.u1;
+ v[1] = ctx->EvalMap.Map2Texture3.u2;
+ v[2] = ctx->EvalMap.Map2Texture3.v1;
+ v[3] = ctx->EvalMap.Map2Texture3.v2;
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ v[0] = ctx->EvalMap.Map2Texture4.u1;
+ v[1] = ctx->EvalMap.Map2Texture4.u2;
+ v[2] = ctx->EvalMap.Map2Texture4.v1;
+ v[3] = ctx->EvalMap.Map2Texture4.v2;
+ break;
+ case GL_MAP2_VERTEX_3:
+ v[0] = ctx->EvalMap.Map2Vertex3.u1;
+ v[1] = ctx->EvalMap.Map2Vertex3.u2;
+ v[2] = ctx->EvalMap.Map2Vertex3.v1;
+ v[3] = ctx->EvalMap.Map2Vertex3.v2;
+ break;
+ case GL_MAP2_VERTEX_4:
+ v[0] = ctx->EvalMap.Map2Vertex4.u1;
+ v[1] = ctx->EvalMap.Map2Vertex4.u2;
+ v[2] = ctx->EvalMap.Map2Vertex4.v1;
+ v[3] = ctx->EvalMap.Map2Vertex4.v2;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetMapdv(target)" );
+ }
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetMapdv(query)" );
+ }
+}
+
+
+void gl_GetMapfv( GLcontext* ctx, GLenum target, GLenum query, GLfloat *v )
+{
+ GLint i, n;
+ GLfloat *data;
+
+ switch (query) {
+ case GL_COEFF:
+ switch (target) {
+ case GL_MAP1_COLOR_4:
+ data = ctx->EvalMap.Map1Color4.Points;
+ n = ctx->EvalMap.Map1Color4.Order * 4;
+ break;
+ case GL_MAP1_INDEX:
+ data = ctx->EvalMap.Map1Index.Points;
+ n = ctx->EvalMap.Map1Index.Order;
+ break;
+ case GL_MAP1_NORMAL:
+ data = ctx->EvalMap.Map1Normal.Points;
+ n = ctx->EvalMap.Map1Normal.Order * 3;
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ data = ctx->EvalMap.Map1Texture1.Points;
+ n = ctx->EvalMap.Map1Texture1.Order * 1;
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ data = ctx->EvalMap.Map1Texture2.Points;
+ n = ctx->EvalMap.Map1Texture2.Order * 2;
+ break;
+ case GL_MAP1_TEXTURE_COORD_3:
+ data = ctx->EvalMap.Map1Texture3.Points;
+ n = ctx->EvalMap.Map1Texture3.Order * 3;
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ data = ctx->EvalMap.Map1Texture4.Points;
+ n = ctx->EvalMap.Map1Texture4.Order * 4;
+ break;
+ case GL_MAP1_VERTEX_3:
+ data = ctx->EvalMap.Map1Vertex3.Points;
+ n = ctx->EvalMap.Map1Vertex3.Order * 3;
+ break;
+ case GL_MAP1_VERTEX_4:
+ data = ctx->EvalMap.Map1Vertex4.Points;
+ n = ctx->EvalMap.Map1Vertex4.Order * 4;
+ break;
+ case GL_MAP2_COLOR_4:
+ data = ctx->EvalMap.Map2Color4.Points;
+ n = ctx->EvalMap.Map2Color4.Uorder
+ * ctx->EvalMap.Map2Color4.Vorder * 4;
+ break;
+ case GL_MAP2_INDEX:
+ data = ctx->EvalMap.Map2Index.Points;
+ n = ctx->EvalMap.Map2Index.Uorder
+ * ctx->EvalMap.Map2Index.Vorder;
+ break;
+ case GL_MAP2_NORMAL:
+ data = ctx->EvalMap.Map2Normal.Points;
+ n = ctx->EvalMap.Map2Normal.Uorder
+ * ctx->EvalMap.Map2Normal.Vorder * 3;
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ data = ctx->EvalMap.Map2Texture1.Points;
+ n = ctx->EvalMap.Map2Texture1.Uorder
+ * ctx->EvalMap.Map2Texture1.Vorder * 1;
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ data = ctx->EvalMap.Map2Texture2.Points;
+ n = ctx->EvalMap.Map2Texture2.Uorder
+ * ctx->EvalMap.Map2Texture2.Vorder * 2;
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ data = ctx->EvalMap.Map2Texture3.Points;
+ n = ctx->EvalMap.Map2Texture3.Uorder
+ * ctx->EvalMap.Map2Texture3.Vorder * 3;
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ data = ctx->EvalMap.Map2Texture4.Points;
+ n = ctx->EvalMap.Map2Texture4.Uorder
+ * ctx->EvalMap.Map2Texture4.Vorder * 4;
+ break;
+ case GL_MAP2_VERTEX_3:
+ data = ctx->EvalMap.Map2Vertex3.Points;
+ n = ctx->EvalMap.Map2Vertex3.Uorder
+ * ctx->EvalMap.Map2Vertex3.Vorder * 3;
+ break;
+ case GL_MAP2_VERTEX_4:
+ data = ctx->EvalMap.Map2Vertex4.Points;
+ n = ctx->EvalMap.Map2Vertex4.Uorder
+ * ctx->EvalMap.Map2Vertex4.Vorder * 4;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetMapfv(target)" );
+ return;
+ }
+ if (data) {
+ for (i=0;i<n;i++) {
+ v[i] = data[i];
+ }
+ }
+ break;
+ case GL_ORDER:
+ switch (target) {
+ case GL_MAP1_COLOR_4:
+ *v = ctx->EvalMap.Map1Color4.Order;
+ break;
+ case GL_MAP1_INDEX:
+ *v = ctx->EvalMap.Map1Index.Order;
+ break;
+ case GL_MAP1_NORMAL:
+ *v = ctx->EvalMap.Map1Normal.Order;
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ *v = ctx->EvalMap.Map1Texture1.Order;
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ *v = ctx->EvalMap.Map1Texture2.Order;
+ break;
+ case GL_MAP1_TEXTURE_COORD_3:
+ *v = ctx->EvalMap.Map1Texture3.Order;
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ *v = ctx->EvalMap.Map1Texture4.Order;
+ break;
+ case GL_MAP1_VERTEX_3:
+ *v = ctx->EvalMap.Map1Vertex3.Order;
+ break;
+ case GL_MAP1_VERTEX_4:
+ *v = ctx->EvalMap.Map1Vertex4.Order;
+ break;
+ case GL_MAP2_COLOR_4:
+ v[0] = ctx->EvalMap.Map2Color4.Uorder;
+ v[1] = ctx->EvalMap.Map2Color4.Vorder;
+ break;
+ case GL_MAP2_INDEX:
+ v[0] = ctx->EvalMap.Map2Index.Uorder;
+ v[1] = ctx->EvalMap.Map2Index.Vorder;
+ break;
+ case GL_MAP2_NORMAL:
+ v[0] = ctx->EvalMap.Map2Normal.Uorder;
+ v[1] = ctx->EvalMap.Map2Normal.Vorder;
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ v[0] = ctx->EvalMap.Map2Texture1.Uorder;
+ v[1] = ctx->EvalMap.Map2Texture1.Vorder;
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ v[0] = ctx->EvalMap.Map2Texture2.Uorder;
+ v[1] = ctx->EvalMap.Map2Texture2.Vorder;
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ v[0] = ctx->EvalMap.Map2Texture3.Uorder;
+ v[1] = ctx->EvalMap.Map2Texture3.Vorder;
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ v[0] = ctx->EvalMap.Map2Texture4.Uorder;
+ v[1] = ctx->EvalMap.Map2Texture4.Vorder;
+ break;
+ case GL_MAP2_VERTEX_3:
+ v[0] = ctx->EvalMap.Map2Vertex3.Uorder;
+ v[1] = ctx->EvalMap.Map2Vertex3.Vorder;
+ break;
+ case GL_MAP2_VERTEX_4:
+ v[0] = ctx->EvalMap.Map2Vertex4.Uorder;
+ v[1] = ctx->EvalMap.Map2Vertex4.Vorder;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetMapfv(target)" );
+ return;
+ }
+ break;
+ case GL_DOMAIN:
+ switch (target) {
+ case GL_MAP1_COLOR_4:
+ v[0] = ctx->EvalMap.Map1Color4.u1;
+ v[1] = ctx->EvalMap.Map1Color4.u2;
+ break;
+ case GL_MAP1_INDEX:
+ v[0] = ctx->EvalMap.Map1Index.u1;
+ v[1] = ctx->EvalMap.Map1Index.u2;
+ break;
+ case GL_MAP1_NORMAL:
+ v[0] = ctx->EvalMap.Map1Normal.u1;
+ v[1] = ctx->EvalMap.Map1Normal.u2;
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ v[0] = ctx->EvalMap.Map1Texture1.u1;
+ v[1] = ctx->EvalMap.Map1Texture1.u2;
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ v[0] = ctx->EvalMap.Map1Texture2.u1;
+ v[1] = ctx->EvalMap.Map1Texture2.u2;
+ break;
+ case GL_MAP1_TEXTURE_COORD_3:
+ v[0] = ctx->EvalMap.Map1Texture3.u1;
+ v[1] = ctx->EvalMap.Map1Texture3.u2;
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ v[0] = ctx->EvalMap.Map1Texture4.u1;
+ v[1] = ctx->EvalMap.Map1Texture4.u2;
+ break;
+ case GL_MAP1_VERTEX_3:
+ v[0] = ctx->EvalMap.Map1Vertex3.u1;
+ v[1] = ctx->EvalMap.Map1Vertex3.u2;
+ break;
+ case GL_MAP1_VERTEX_4:
+ v[0] = ctx->EvalMap.Map1Vertex4.u1;
+ v[1] = ctx->EvalMap.Map1Vertex4.u2;
+ break;
+ case GL_MAP2_COLOR_4:
+ v[0] = ctx->EvalMap.Map2Color4.u1;
+ v[1] = ctx->EvalMap.Map2Color4.u2;
+ v[2] = ctx->EvalMap.Map2Color4.v1;
+ v[3] = ctx->EvalMap.Map2Color4.v2;
+ break;
+ case GL_MAP2_INDEX:
+ v[0] = ctx->EvalMap.Map2Index.u1;
+ v[1] = ctx->EvalMap.Map2Index.u2;
+ v[2] = ctx->EvalMap.Map2Index.v1;
+ v[3] = ctx->EvalMap.Map2Index.v2;
+ break;
+ case GL_MAP2_NORMAL:
+ v[0] = ctx->EvalMap.Map2Normal.u1;
+ v[1] = ctx->EvalMap.Map2Normal.u2;
+ v[2] = ctx->EvalMap.Map2Normal.v1;
+ v[3] = ctx->EvalMap.Map2Normal.v2;
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ v[0] = ctx->EvalMap.Map2Texture1.u1;
+ v[1] = ctx->EvalMap.Map2Texture1.u2;
+ v[2] = ctx->EvalMap.Map2Texture1.v1;
+ v[3] = ctx->EvalMap.Map2Texture1.v2;
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ v[0] = ctx->EvalMap.Map2Texture2.u1;
+ v[1] = ctx->EvalMap.Map2Texture2.u2;
+ v[2] = ctx->EvalMap.Map2Texture2.v1;
+ v[3] = ctx->EvalMap.Map2Texture2.v2;
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ v[0] = ctx->EvalMap.Map2Texture3.u1;
+ v[1] = ctx->EvalMap.Map2Texture3.u2;
+ v[2] = ctx->EvalMap.Map2Texture3.v1;
+ v[3] = ctx->EvalMap.Map2Texture3.v2;
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ v[0] = ctx->EvalMap.Map2Texture4.u1;
+ v[1] = ctx->EvalMap.Map2Texture4.u2;
+ v[2] = ctx->EvalMap.Map2Texture4.v1;
+ v[3] = ctx->EvalMap.Map2Texture4.v2;
+ break;
+ case GL_MAP2_VERTEX_3:
+ v[0] = ctx->EvalMap.Map2Vertex3.u1;
+ v[1] = ctx->EvalMap.Map2Vertex3.u2;
+ v[2] = ctx->EvalMap.Map2Vertex3.v1;
+ v[3] = ctx->EvalMap.Map2Vertex3.v2;
+ break;
+ case GL_MAP2_VERTEX_4:
+ v[0] = ctx->EvalMap.Map2Vertex4.u1;
+ v[1] = ctx->EvalMap.Map2Vertex4.u2;
+ v[2] = ctx->EvalMap.Map2Vertex4.v1;
+ v[3] = ctx->EvalMap.Map2Vertex4.v2;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetMapfv(target)" );
+ }
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetMapfv(query)" );
+ }
+}
+
+
+void gl_GetMapiv( GLcontext* ctx, GLenum target, GLenum query, GLint *v )
+{
+ GLuint i, n;
+ GLfloat *data;
+
+ switch (query) {
+ case GL_COEFF:
+ switch (target) {
+ case GL_MAP1_COLOR_4:
+ data = ctx->EvalMap.Map1Color4.Points;
+ n = ctx->EvalMap.Map1Color4.Order * 4;
+ break;
+ case GL_MAP1_INDEX:
+ data = ctx->EvalMap.Map1Index.Points;
+ n = ctx->EvalMap.Map1Index.Order;
+ break;
+ case GL_MAP1_NORMAL:
+ data = ctx->EvalMap.Map1Normal.Points;
+ n = ctx->EvalMap.Map1Normal.Order * 3;
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ data = ctx->EvalMap.Map1Texture1.Points;
+ n = ctx->EvalMap.Map1Texture1.Order * 1;
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ data = ctx->EvalMap.Map1Texture2.Points;
+ n = ctx->EvalMap.Map1Texture2.Order * 2;
+ break;
+ case GL_MAP1_TEXTURE_COORD_3:
+ data = ctx->EvalMap.Map1Texture3.Points;
+ n = ctx->EvalMap.Map1Texture3.Order * 3;
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ data = ctx->EvalMap.Map1Texture4.Points;
+ n = ctx->EvalMap.Map1Texture4.Order * 4;
+ break;
+ case GL_MAP1_VERTEX_3:
+ data = ctx->EvalMap.Map1Vertex3.Points;
+ n = ctx->EvalMap.Map1Vertex3.Order * 3;
+ break;
+ case GL_MAP1_VERTEX_4:
+ data = ctx->EvalMap.Map1Vertex4.Points;
+ n = ctx->EvalMap.Map1Vertex4.Order * 4;
+ break;
+ case GL_MAP2_COLOR_4:
+ data = ctx->EvalMap.Map2Color4.Points;
+ n = ctx->EvalMap.Map2Color4.Uorder
+ * ctx->EvalMap.Map2Color4.Vorder * 4;
+ break;
+ case GL_MAP2_INDEX:
+ data = ctx->EvalMap.Map2Index.Points;
+ n = ctx->EvalMap.Map2Index.Uorder
+ * ctx->EvalMap.Map2Index.Vorder;
+ break;
+ case GL_MAP2_NORMAL:
+ data = ctx->EvalMap.Map2Normal.Points;
+ n = ctx->EvalMap.Map2Normal.Uorder
+ * ctx->EvalMap.Map2Normal.Vorder * 3;
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ data = ctx->EvalMap.Map2Texture1.Points;
+ n = ctx->EvalMap.Map2Texture1.Uorder
+ * ctx->EvalMap.Map2Texture1.Vorder * 1;
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ data = ctx->EvalMap.Map2Texture2.Points;
+ n = ctx->EvalMap.Map2Texture2.Uorder
+ * ctx->EvalMap.Map2Texture2.Vorder * 2;
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ data = ctx->EvalMap.Map2Texture3.Points;
+ n = ctx->EvalMap.Map2Texture3.Uorder
+ * ctx->EvalMap.Map2Texture3.Vorder * 3;
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ data = ctx->EvalMap.Map2Texture4.Points;
+ n = ctx->EvalMap.Map2Texture4.Uorder
+ * ctx->EvalMap.Map2Texture4.Vorder * 4;
+ break;
+ case GL_MAP2_VERTEX_3:
+ data = ctx->EvalMap.Map2Vertex3.Points;
+ n = ctx->EvalMap.Map2Vertex3.Uorder
+ * ctx->EvalMap.Map2Vertex3.Vorder * 3;
+ break;
+ case GL_MAP2_VERTEX_4:
+ data = ctx->EvalMap.Map2Vertex4.Points;
+ n = ctx->EvalMap.Map2Vertex4.Uorder
+ * ctx->EvalMap.Map2Vertex4.Vorder * 4;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetMapiv(target)" );
+ return;
+ }
+ if (data) {
+ for (i=0;i<n;i++) {
+ v[i] = ROUNDF(data[i]);
+ }
+ }
+ break;
+ case GL_ORDER:
+ switch (target) {
+ case GL_MAP1_COLOR_4:
+ *v = ctx->EvalMap.Map1Color4.Order;
+ break;
+ case GL_MAP1_INDEX:
+ *v = ctx->EvalMap.Map1Index.Order;
+ break;
+ case GL_MAP1_NORMAL:
+ *v = ctx->EvalMap.Map1Normal.Order;
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ *v = ctx->EvalMap.Map1Texture1.Order;
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ *v = ctx->EvalMap.Map1Texture2.Order;
+ break;
+ case GL_MAP1_TEXTURE_COORD_3:
+ *v = ctx->EvalMap.Map1Texture3.Order;
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ *v = ctx->EvalMap.Map1Texture4.Order;
+ break;
+ case GL_MAP1_VERTEX_3:
+ *v = ctx->EvalMap.Map1Vertex3.Order;
+ break;
+ case GL_MAP1_VERTEX_4:
+ *v = ctx->EvalMap.Map1Vertex4.Order;
+ break;
+ case GL_MAP2_COLOR_4:
+ v[0] = ctx->EvalMap.Map2Color4.Uorder;
+ v[1] = ctx->EvalMap.Map2Color4.Vorder;
+ break;
+ case GL_MAP2_INDEX:
+ v[0] = ctx->EvalMap.Map2Index.Uorder;
+ v[1] = ctx->EvalMap.Map2Index.Vorder;
+ break;
+ case GL_MAP2_NORMAL:
+ v[0] = ctx->EvalMap.Map2Normal.Uorder;
+ v[1] = ctx->EvalMap.Map2Normal.Vorder;
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ v[0] = ctx->EvalMap.Map2Texture1.Uorder;
+ v[1] = ctx->EvalMap.Map2Texture1.Vorder;
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ v[0] = ctx->EvalMap.Map2Texture2.Uorder;
+ v[1] = ctx->EvalMap.Map2Texture2.Vorder;
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ v[0] = ctx->EvalMap.Map2Texture3.Uorder;
+ v[1] = ctx->EvalMap.Map2Texture3.Vorder;
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ v[0] = ctx->EvalMap.Map2Texture4.Uorder;
+ v[1] = ctx->EvalMap.Map2Texture4.Vorder;
+ break;
+ case GL_MAP2_VERTEX_3:
+ v[0] = ctx->EvalMap.Map2Vertex3.Uorder;
+ v[1] = ctx->EvalMap.Map2Vertex3.Vorder;
+ break;
+ case GL_MAP2_VERTEX_4:
+ v[0] = ctx->EvalMap.Map2Vertex4.Uorder;
+ v[1] = ctx->EvalMap.Map2Vertex4.Vorder;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetMapiv(target)" );
+ return;
+ }
+ break;
+ case GL_DOMAIN:
+ switch (target) {
+ case GL_MAP1_COLOR_4:
+ v[0] = ROUNDF(ctx->EvalMap.Map1Color4.u1);
+ v[1] = ROUNDF(ctx->EvalMap.Map1Color4.u2);
+ break;
+ case GL_MAP1_INDEX:
+ v[0] = ROUNDF(ctx->EvalMap.Map1Index.u1);
+ v[1] = ROUNDF(ctx->EvalMap.Map1Index.u2);
+ break;
+ case GL_MAP1_NORMAL:
+ v[0] = ROUNDF(ctx->EvalMap.Map1Normal.u1);
+ v[1] = ROUNDF(ctx->EvalMap.Map1Normal.u2);
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ v[0] = ROUNDF(ctx->EvalMap.Map1Texture1.u1);
+ v[1] = ROUNDF(ctx->EvalMap.Map1Texture1.u2);
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ v[0] = ROUNDF(ctx->EvalMap.Map1Texture2.u1);
+ v[1] = ROUNDF(ctx->EvalMap.Map1Texture2.u2);
+ break;
+ case GL_MAP1_TEXTURE_COORD_3:
+ v[0] = ROUNDF(ctx->EvalMap.Map1Texture3.u1);
+ v[1] = ROUNDF(ctx->EvalMap.Map1Texture3.u2);
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ v[0] = ROUNDF(ctx->EvalMap.Map1Texture4.u1);
+ v[1] = ROUNDF(ctx->EvalMap.Map1Texture4.u2);
+ break;
+ case GL_MAP1_VERTEX_3:
+ v[0] = ROUNDF(ctx->EvalMap.Map1Vertex3.u1);
+ v[1] = ROUNDF(ctx->EvalMap.Map1Vertex3.u2);
+ break;
+ case GL_MAP1_VERTEX_4:
+ v[0] = ROUNDF(ctx->EvalMap.Map1Vertex4.u1);
+ v[1] = ROUNDF(ctx->EvalMap.Map1Vertex4.u2);
+ break;
+ case GL_MAP2_COLOR_4:
+ v[0] = ROUNDF(ctx->EvalMap.Map2Color4.u1);
+ v[1] = ROUNDF(ctx->EvalMap.Map2Color4.u2);
+ v[2] = ROUNDF(ctx->EvalMap.Map2Color4.v1);
+ v[3] = ROUNDF(ctx->EvalMap.Map2Color4.v2);
+ break;
+ case GL_MAP2_INDEX:
+ v[0] = ROUNDF(ctx->EvalMap.Map2Index.u1);
+ v[1] = ROUNDF(ctx->EvalMap.Map2Index.u2);
+ v[2] = ROUNDF(ctx->EvalMap.Map2Index.v1);
+ v[3] = ROUNDF(ctx->EvalMap.Map2Index.v2);
+ break;
+ case GL_MAP2_NORMAL:
+ v[0] = ROUNDF(ctx->EvalMap.Map2Normal.u1);
+ v[1] = ROUNDF(ctx->EvalMap.Map2Normal.u2);
+ v[2] = ROUNDF(ctx->EvalMap.Map2Normal.v1);
+ v[3] = ROUNDF(ctx->EvalMap.Map2Normal.v2);
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ v[0] = ROUNDF(ctx->EvalMap.Map2Texture1.u1);
+ v[1] = ROUNDF(ctx->EvalMap.Map2Texture1.u2);
+ v[2] = ROUNDF(ctx->EvalMap.Map2Texture1.v1);
+ v[3] = ROUNDF(ctx->EvalMap.Map2Texture1.v2);
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ v[0] = ROUNDF(ctx->EvalMap.Map2Texture2.u1);
+ v[1] = ROUNDF(ctx->EvalMap.Map2Texture2.u2);
+ v[2] = ROUNDF(ctx->EvalMap.Map2Texture2.v1);
+ v[3] = ROUNDF(ctx->EvalMap.Map2Texture2.v2);
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ v[0] = ROUNDF(ctx->EvalMap.Map2Texture3.u1);
+ v[1] = ROUNDF(ctx->EvalMap.Map2Texture3.u2);
+ v[2] = ROUNDF(ctx->EvalMap.Map2Texture3.v1);
+ v[3] = ROUNDF(ctx->EvalMap.Map2Texture3.v2);
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ v[0] = ROUNDF(ctx->EvalMap.Map2Texture4.u1);
+ v[1] = ROUNDF(ctx->EvalMap.Map2Texture4.u2);
+ v[2] = ROUNDF(ctx->EvalMap.Map2Texture4.v1);
+ v[3] = ROUNDF(ctx->EvalMap.Map2Texture4.v2);
+ break;
+ case GL_MAP2_VERTEX_3:
+ v[0] = ROUNDF(ctx->EvalMap.Map2Vertex3.u1);
+ v[1] = ROUNDF(ctx->EvalMap.Map2Vertex3.u2);
+ v[2] = ROUNDF(ctx->EvalMap.Map2Vertex3.v1);
+ v[3] = ROUNDF(ctx->EvalMap.Map2Vertex3.v2);
+ break;
+ case GL_MAP2_VERTEX_4:
+ v[0] = ROUNDF(ctx->EvalMap.Map2Vertex4.u1);
+ v[1] = ROUNDF(ctx->EvalMap.Map2Vertex4.u2);
+ v[2] = ROUNDF(ctx->EvalMap.Map2Vertex4.v1);
+ v[3] = ROUNDF(ctx->EvalMap.Map2Vertex4.v2);
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetMapiv(target)" );
+ }
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetMapiv(query)" );
+ }
+}
+
+
+
+void eval_points1( GLfloat outcoord[][4],
+ GLfloat coord[][4],
+ const GLuint *flags,
+ GLfloat du, GLfloat u1 )
+{
+ GLuint i;
+ for (i = VB_START ; !(flags[i] & VERT_END_VB) ; i++)
+ if (flags[i] & VERT_EVAL_P1)
+ outcoord[i][0] = coord[i][0] * du + u1;
+ else if (flags[i] & VERT_EVAL_ANY) {
+ outcoord[i][0] = coord[i][0];
+ outcoord[i][1] = coord[i][1];
+ }
+}
+
+void eval_points2( GLfloat outcoord[][4],
+ GLfloat coord[][4],
+ const GLuint *flags,
+ GLfloat du, GLfloat u1,
+ GLfloat dv, GLfloat v1 )
+{
+ GLuint i;
+ for (i = VB_START ; !(flags[i] & VERT_END_VB) ; i++)
+ if (flags[i] & VERT_EVAL_P2) {
+ outcoord[i][0] = coord[i][0] * du + u1;
+ outcoord[i][1] = coord[i][1] * dv + v1;
+ } else if (flags[i] & VERT_EVAL_ANY) {
+ outcoord[i][0] = coord[i][0];
+ outcoord[i][1] = coord[i][1];
+ }
+}
+
+
+static const GLubyte dirty_flags[5] = {
+ 0, /* not possible */
+ VEC_DIRTY_0,
+ VEC_DIRTY_1,
+ VEC_DIRTY_2,
+ VEC_DIRTY_3
+};
+
+
+GLvector4f *eval1_4f( GLvector4f *dest,
+ GLfloat coord[][4],
+ const GLuint *flags,
+ GLuint dimension,
+ struct gl_1d_map *map )
+{
+ const GLfloat u1 = map->u1;
+ const GLfloat du = map->du;
+ GLfloat (*to)[4] = dest->data;
+ GLuint i;
+
+ for (i = VB_START ; !(flags[i] & VERT_END_VB) ; i++)
+ if (flags[i] & (VERT_EVAL_C1|VERT_EVAL_P1)) {
+ GLfloat u = (coord[i][0] - u1) * du;
+ ASSIGN_4V(to[i], 0,0,0,1);
+ horner_bezier_curve(map->Points, to[i], u, dimension, map->Order);
+ }
+
+ dest->count = i;
+ dest->size = MAX2(dest->size, dimension);
+ dest->flags |= dirty_flags[dimension];
+ return dest;
+}
+
+
+GLvector1ui *eval1_1ui( GLvector1ui *dest,
+ GLfloat coord[][4],
+ const GLuint *flags,
+ struct gl_1d_map *map )
+{
+ const GLfloat u1 = map->u1;
+ const GLfloat du = map->du;
+ GLuint *to = dest->data;
+ GLuint i;
+
+ for (i = VB_START ; !(flags[i] & VERT_END_VB) ; i++)
+ if (flags[i] & (VERT_EVAL_C1|VERT_EVAL_P1)) {
+ GLfloat u = (coord[i][0] - u1) * du;
+ GLfloat tmp;
+ horner_bezier_curve(map->Points, &tmp, u, 1, map->Order);
+ to[i] = (GLuint) (GLint) tmp;
+ }
+
+ dest->count = i;
+ return dest;
+}
+
+GLvector3f *eval1_norm( GLvector3f *dest,
+ GLfloat coord[][4],
+ GLuint *flags, /* not const */
+ struct gl_1d_map *map )
+{
+ const GLfloat u1 = map->u1;
+ const GLfloat du = map->du;
+ GLfloat (*to)[3] = dest->data;
+ GLuint i;
+
+ for (i = VB_START ; !(flags[i] & VERT_END_VB) ; i++)
+ if (flags[i] & (VERT_EVAL_C1|VERT_EVAL_P1)) {
+ GLfloat u = (coord[i][0] - u1) * du;
+ horner_bezier_curve(map->Points, to[i], u, 3, map->Order);
+ flags[i+1] |= VERT_NORM; /* reset */
+ }
+
+ dest->count = i;
+ return dest;
+}
+
+GLvector4ub *eval1_color( GLvector4ub *dest,
+ GLfloat coord[][4],
+ GLuint *flags, /* not const */
+ struct gl_1d_map *map )
+{
+ const GLfloat u1 = map->u1;
+ const GLfloat du = map->du;
+ GLubyte (*to)[4] = dest->data;
+ GLuint i;
+
+ for (i = VB_START ; !(flags[i] & VERT_END_VB) ; i++)
+ if (flags[i] & (VERT_EVAL_C1|VERT_EVAL_P1)) {
+ GLfloat u = (coord[i][0] - u1) * du;
+ GLfloat fcolor[4];
+ horner_bezier_curve(map->Points, fcolor, u, 4, map->Order);
+ FLOAT_RGBA_TO_UBYTE_RGBA(to[i], fcolor);
+ flags[i+1] |= VERT_RGBA; /* reset */
+ }
+
+ dest->count = i;
+ return dest;
+}
+
+
+
+
+GLvector4f *eval2_obj_norm( GLvector4f *obj_ptr,
+ GLvector3f *norm_ptr,
+ GLfloat coord[][4],
+ GLuint *flags,
+ GLuint dimension,
+ struct gl_2d_map *map )
+{
+ const GLfloat u1 = map->u1;
+ const GLfloat du = map->du;
+ const GLfloat v1 = map->v1;
+ const GLfloat dv = map->dv;
+ GLfloat (*obj)[4] = obj_ptr->data;
+ GLfloat (*normal)[3] = norm_ptr->data;
+ GLuint i;
+
+ for (i = VB_START ; !(flags[i] & VERT_END_VB) ; i++)
+ if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) {
+ GLfloat u = (coord[i][0] - u1) * du;
+ GLfloat v = (coord[i][1] - v1) * dv;
+ GLfloat du[4], dv[4];
+
+ ASSIGN_4V(obj[i], 0,0,0,1);
+ de_casteljau_surf(map->Points, obj[i], du, dv, u, v, dimension,
+ map->Uorder, map->Vorder);
+
+ CROSS3(normal[i], du, dv);
+ NORMALIZE_3FV(normal[i]);
+ flags[i+1] |= VERT_NORM;
+ }
+
+ obj_ptr->count = i;
+ obj_ptr->size = MAX2(obj_ptr->size, dimension);
+ obj_ptr->flags |= dirty_flags[dimension];
+ return obj_ptr;
+}
+
+
+GLvector4f *eval2_4f( GLvector4f *dest,
+ GLfloat coord[][4],
+ const GLuint *flags,
+ GLuint dimension,
+ struct gl_2d_map *map )
+{
+ const GLfloat u1 = map->u1;
+ const GLfloat du = map->du;
+ const GLfloat v1 = map->v1;
+ const GLfloat dv = map->dv;
+ GLfloat (*to)[4] = dest->data;
+ GLuint i;
+
+ for (i = VB_START ; !(flags[i] & VERT_END_VB) ; i++)
+ if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) {
+ GLfloat u = (coord[i][0] - u1) * du;
+ GLfloat v = (coord[i][1] - v1) * dv;
+ horner_bezier_surf(map->Points, to[i], u, v, dimension,
+ map->Uorder, map->Vorder);
+ }
+
+ dest->count = i;
+ dest->size = MAX2(dest->size, dimension);
+ dest->flags |= dirty_flags[dimension];
+ return dest;
+}
+
+
+GLvector3f *eval2_norm( GLvector3f *dest,
+ GLfloat coord[][4],
+ GLuint *flags,
+ struct gl_2d_map *map )
+{
+ const GLfloat u1 = map->u1;
+ const GLfloat du = map->du;
+ const GLfloat v1 = map->v1;
+ const GLfloat dv = map->dv;
+ GLfloat (*to)[3] = dest->data;
+ GLuint i;
+
+ for (i = VB_START ; !(flags[i] & VERT_END_VB) ; i++)
+ if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) {
+ GLfloat u = (coord[i][0] - u1) * du;
+ GLfloat v = (coord[i][1] - v1) * dv;
+ horner_bezier_surf(map->Points, to[i], u, v, 3,
+ map->Uorder, map->Vorder);
+ flags[i+1] |= VERT_NORM; /* reset */
+ }
+
+ dest->count = i;
+ return dest;
+}
+
+
+GLvector1ui *eval2_1ui( GLvector1ui *dest,
+ GLfloat coord[][4],
+ const GLuint *flags,
+ struct gl_2d_map *map )
+{
+ const GLfloat u1 = map->u1;
+ const GLfloat du = map->du;
+ const GLfloat v1 = map->v1;
+ const GLfloat dv = map->dv;
+ GLuint *to = dest->data;
+ GLuint i;
+
+ for (i = VB_START ; !(flags[i] & VERT_END_VB) ; i++)
+ if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) {
+ GLfloat u = (coord[i][0] - u1) * du;
+ GLfloat v = (coord[i][1] - v1) * dv;
+ GLfloat tmp;
+ horner_bezier_surf(map->Points, &tmp, u, v, 1,
+ map->Uorder, map->Vorder);
+
+ to[i] = (GLuint) (GLint) tmp;
+ }
+
+ dest->count = i;
+ return dest;
+}
+
+
+
+GLvector4ub *eval2_color( GLvector4ub *dest,
+ GLfloat coord[][4],
+ GLuint *flags,
+ struct gl_2d_map *map )
+{
+ const GLfloat u1 = map->u1;
+ const GLfloat du = map->du;
+ const GLfloat v1 = map->v1;
+ const GLfloat dv = map->dv;
+ GLubyte (*to)[4] = dest->data;
+ GLuint i;
+
+ for (i = VB_START ; !(flags[i] & VERT_END_VB) ; i++)
+ if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) {
+ GLfloat u = (coord[i][0] - u1) * du;
+ GLfloat v = (coord[i][1] - v1) * dv;
+ GLfloat fcolor[4];
+ horner_bezier_surf(map->Points, fcolor, u, v, 4,
+ map->Uorder, map->Vorder);
+ FLOAT_RGBA_TO_UBYTE_RGBA(to[i], fcolor);
+ flags[i+1] |= VERT_RGBA; /* reset */
+ }
+
+ dest->count = i;
+ return dest;
+}
+
+
+GLvector4f *copy_4f( GLvector4f *out, CONST GLvector4f *in,
+ const GLuint *flags)
+{
+ GLfloat (*to)[4] = out->data;
+ GLfloat (*from)[4] = in->data;
+ GLuint i;
+
+ for ( i = VB_START ; !(flags[i] & VERT_END_VB) ; i++)
+ if (!(flags[i] & VERT_EVAL_ANY))
+ COPY_4FV( to[i], from[i] );
+
+ return out;
+}
+
+GLvector3f *copy_3f( GLvector3f *out, CONST GLvector3f *in,
+ const GLuint *flags)
+{
+ GLfloat (*to)[3] = out->data;
+ GLfloat (*from)[3] = in->data;
+ GLuint i;
+
+ for ( i = VB_START ; !(flags[i] & VERT_END_VB) ; i++)
+ if (!(flags[i] & VERT_EVAL_ANY))
+ COPY_3V( to[i], from[i] );
+
+ return out;
+}
+
+GLvector4ub *copy_4ub( GLvector4ub *out, CONST GLvector4ub *in,
+ const GLuint *flags )
+{
+ GLubyte (*to)[4] = out->data;
+ GLubyte (*from)[4] = in->data;
+ GLuint i;
+
+ for ( i = VB_START ; !(flags[i] & VERT_END_VB) ; i++)
+ if (!(flags[i] & VERT_EVAL_ANY))
+ COPY_4UBV( to[i], from[i] );
+
+ return out;
+}
+
+GLvector1ui *copy_1ui( GLvector1ui *out, CONST GLvector1ui *in,
+ const GLuint *flags )
+{
+ GLuint *to = out->data;
+ CONST GLuint *from = in->data;
+ GLuint i;
+
+ for ( i = VB_START ; !(flags[i] & VERT_END_VB) ; i++)
+ if (!(flags[i] & VERT_EVAL_ANY))
+ to[i] = from[i];
+
+ return out;
+}
+
+
+/* KW: Rewrote this to perform eval on a whole buffer at once.
+ * Only evaluates active data items, and avoids scribbling
+ * the source buffer if we are running from a display list.
+ *
+ * If the user (in this case looser) sends eval coordinates
+ * or runs a display list containing eval coords with no
+ * vertex maps enabled, we have to either copy all non-eval
+ * data to a new buffer, or find a way of working around
+ * the eval data. I choose the second option.
+ *
+ * KW: This code not reached by cva - use IM to access storage.
+ */
+void gl_eval_vb( struct vertex_buffer *VB )
+{
+ struct immediate *IM = VB->IM;
+ GLcontext *ctx = VB->ctx;
+ GLuint req = ctx->CVA.elt.inputs;
+ GLfloat (*coord)[4] = VB->ObjPtr->data;
+ GLuint *flags = VB->Flag;
+ GLuint new_flags = 0;
+
+
+ GLuint any_eval1 = VB->OrFlag & (VERT_EVAL_C1|VERT_EVAL_P1);
+ GLuint any_eval2 = VB->OrFlag & (VERT_EVAL_C2|VERT_EVAL_P2);
+ GLuint all_eval = VB->AndFlag & VERT_EVAL_ANY;
+
+ /* Handle the degenerate cases.
+ */
+ if (any_eval1 && !ctx->Eval.Map1Vertex4 && !ctx->Eval.Map1Vertex3) {
+ VB->PurgeFlags |= (VERT_EVAL_C1|VERT_EVAL_P1);
+ VB->EarlyCull = 0;
+ any_eval1 = GL_FALSE;
+ }
+
+ if (any_eval2 && !ctx->Eval.Map2Vertex4 && !ctx->Eval.Map2Vertex3) {
+ VB->PurgeFlags |= (VERT_EVAL_C2|VERT_EVAL_P2);
+ VB->EarlyCull = 0;
+ any_eval2 = GL_FALSE;
+ }
+
+ /* KW: This really is a degenerate case - doing this disables
+ * culling, and causes dummy values for the missing vertices to be
+ * transformed and clip tested. It also forces the individual
+ * cliptesting of each primitive in vb_render. I wish there was a
+ * nice alternative, but I can't say I want to put effort into
+ * optimizing such a bad usage of the library - I'd much rather
+ * work on useful changes.
+ */
+ if (VB->PurgeFlags) {
+ if (!any_eval1 && !any_eval2 && all_eval) VB->Count = VB_START;
+ gl_purge_vertices( VB );
+ if (!any_eval1 && !any_eval2) return;
+ } else
+ VB->IndirectCount = VB->Count;
+
+ /* Translate points into coords.
+ */
+ if (any_eval1 && (VB->OrFlag & VERT_EVAL_P1))
+ {
+ eval_points1( IM->Obj, coord, flags,
+ ctx->Eval.MapGrid1du,
+ ctx->Eval.MapGrid1u1);
+
+ coord = IM->Obj;
+ }
+
+ if (any_eval2 && (VB->OrFlag & VERT_EVAL_P2))
+ {
+ eval_points2( IM->Obj, coord, flags,
+ ctx->Eval.MapGrid2du,
+ ctx->Eval.MapGrid2u1,
+ ctx->Eval.MapGrid2dv,
+ ctx->Eval.MapGrid2v1 );
+
+ coord = IM->Obj;
+ }
+
+ /* Perform the evaluations on active data elements.
+ */
+ if (req & VERT_INDEX)
+ {
+ GLvector1ui *in_index = VB->IndexPtr;
+ GLvector1ui *out_index = &IM->v.Index;
+
+ if (ctx->Eval.Map1Index && any_eval1)
+ VB->IndexPtr = eval1_1ui( out_index, coord, flags,
+ &ctx->EvalMap.Map1Index );
+
+ if (ctx->Eval.Map2Index && any_eval2)
+ VB->IndexPtr = eval2_1ui( out_index, coord, flags,
+ &ctx->EvalMap.Map2Index );
+
+ if (VB->IndexPtr != in_index) {
+ new_flags |= VERT_INDEX;
+ if (!all_eval)
+ VB->IndexPtr = copy_1ui( out_index, in_index, flags );
+ }
+ }
+
+ if (req & VERT_RGBA)
+ {
+ GLvector4ub *in_color = VB->ColorPtr;
+ GLvector4ub *out_color = &IM->v.Color;
+
+ if (ctx->Eval.Map1Color4 && any_eval1)
+ VB->ColorPtr = eval1_color( out_color, coord, flags,
+ &ctx->EvalMap.Map1Color4 );
+
+ if (ctx->Eval.Map2Color4 && any_eval2)
+ VB->ColorPtr = eval2_color( out_color, coord, flags,
+ &ctx->EvalMap.Map2Color4 );
+
+ if (VB->ColorPtr != in_color) {
+ new_flags |= VERT_RGBA;
+ if (!all_eval)
+ VB->ColorPtr = copy_4ub( out_color, in_color, flags );
+ }
+
+ VB->Color[0] = VB->Color[1] = VB->ColorPtr;
+ }
+
+
+ if (req & VERT_NORM)
+ {
+ GLvector3f *in_normal = VB->NormalPtr;
+ GLvector3f *out_normal = &IM->v.Normal;
+
+ if (ctx->Eval.Map1Normal && any_eval1)
+ VB->NormalPtr = eval1_norm( out_normal, coord, flags,
+ &ctx->EvalMap.Map1Normal );
+
+ if (ctx->Eval.Map2Normal && any_eval2)
+ VB->NormalPtr = eval2_norm( out_normal, coord, flags,
+ &ctx->EvalMap.Map2Normal );
+
+ if (VB->NormalPtr != in_normal) {
+ new_flags |= VERT_NORM;
+ if (!all_eval)
+ VB->NormalPtr = copy_3f( out_normal, in_normal, flags );
+ }
+ }
+
+
+ if (req & VERT_TEX_ANY(0))
+ {
+ GLvector4f *tc = VB->TexCoordPtr[0];
+ GLvector4f *in = tc;
+ GLvector4f *out = &IM->v.TexCoord[0];
+
+ if (any_eval1) {
+ if (ctx->Eval.Map1TextureCoord4)
+ tc = eval1_4f( out, coord, flags, 4, &ctx->EvalMap.Map1Texture4);
+ else if (ctx->Eval.Map1TextureCoord3)
+ tc = eval1_4f( out, coord, flags, 3, &ctx->EvalMap.Map1Texture3);
+ else if (ctx->Eval.Map1TextureCoord2)
+ tc = eval1_4f( out, coord, flags, 2, &ctx->EvalMap.Map1Texture2);
+ else if (ctx->Eval.Map1TextureCoord1)
+ tc = eval1_4f( out, coord, flags, 1, &ctx->EvalMap.Map1Texture1);
+ }
+
+ if (any_eval2) {
+ if (ctx->Eval.Map2TextureCoord4)
+ tc = eval2_4f( out, coord, flags, 4, &ctx->EvalMap.Map2Texture4);
+ else if (ctx->Eval.Map2TextureCoord3)
+ tc = eval2_4f( out, coord, flags, 3, &ctx->EvalMap.Map2Texture3);
+ else if (ctx->Eval.Map2TextureCoord2)
+ tc = eval2_4f( out, coord, flags, 2, &ctx->EvalMap.Map2Texture2);
+ else if (ctx->Eval.Map2TextureCoord1)
+ tc = eval2_4f( out, coord, flags, 1, &ctx->EvalMap.Map2Texture1);
+ }
+
+ if (tc != in) {
+ new_flags |= VERT_TEX_ANY(0); /* fix for sizes.. */
+ if (!all_eval)
+ tc = copy_4f( out, in, flags );
+ }
+
+ VB->TexCoordPtr[0] = tc;
+ }
+
+
+ {
+ GLvector4f *in = VB->ObjPtr;
+ GLvector4f *out = &IM->v.Obj;
+ GLvector4f *obj = in;
+
+ if (any_eval1) {
+ if (ctx->Eval.Map1Vertex4)
+ obj = eval1_4f( out, coord, flags, 4, &ctx->EvalMap.Map1Vertex4);
+ else
+ obj = eval1_4f( out, coord, flags, 3, &ctx->EvalMap.Map1Vertex3);
+ }
+
+ if (any_eval2) {
+ if (ctx->Eval.Map2Vertex4)
+ {
+ if (ctx->Eval.AutoNormal && (req & VERT_NORM))
+ obj = eval2_obj_norm( out, VB->NormalPtr, coord, flags, 4,
+ &ctx->EvalMap.Map2Vertex4 );
+ else
+ obj = eval2_4f( out, coord, flags, 4,
+ &ctx->EvalMap.Map2Vertex4);
+ }
+ else if (ctx->Eval.Map2Vertex3)
+ {
+ if (ctx->Eval.AutoNormal && (req & VERT_NORM))
+ obj = eval2_obj_norm( out, VB->NormalPtr, coord, flags, 3,
+ &ctx->EvalMap.Map2Vertex3 );
+ else
+ obj = eval2_4f( out, coord, flags, 3,
+ &ctx->EvalMap.Map2Vertex3 );
+ }
+ }
+
+ if (obj != in && !all_eval)
+ obj = copy_4f( out, in, flags );
+
+ VB->ObjPtr = obj;
+ }
+
+ if (new_flags) {
+ GLuint *oldflags = VB->Flag;
+ GLuint *flags = VB->Flag = VB->EvaluatedFlags;
+ GLuint i;
+ GLuint count = VB->Count;
+
+ if (!flags) {
+ VB->EvaluatedFlags = (GLuint *)malloc(VB->Size * sizeof(GLuint));
+ flags = VB->Flag = VB->EvaluatedFlags;
+ }
+
+ if (all_eval) {
+ for (i = 0 ; i < count ; i++)
+ flags[i] = oldflags[i] | new_flags;
+ VB->AndFlag |= new_flags;
+ } else {
+ GLuint andflag = ~0;
+ for (i = 0 ; i < count ; i++) {
+ if (oldflags[i] & VERT_EVAL_ANY)
+ flags[i] = oldflags[i] | new_flags;
+ andflag &= flags[i];
+ }
+ VB->AndFlag = andflag;
+ }
+ }
+}
+
+
+void gl_MapGrid1f( GLcontext* ctx, GLint un, GLfloat u1, GLfloat u2 )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glMapGrid1f");
+
+ if (un<1) {
+ gl_error( ctx, GL_INVALID_VALUE, "glMapGrid1f" );
+ return;
+ }
+ ctx->Eval.MapGrid1un = un;
+ ctx->Eval.MapGrid1u1 = u1;
+ ctx->Eval.MapGrid1u2 = u2;
+ ctx->Eval.MapGrid1du = (u2 - u1) / (GLfloat) un;
+}
+
+
+void gl_MapGrid2f( GLcontext* ctx, GLint un, GLfloat u1, GLfloat u2,
+ GLint vn, GLfloat v1, GLfloat v2 )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glMapGrid2f");
+ if (un<1) {
+ gl_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(un)" );
+ return;
+ }
+ if (vn<1) {
+ gl_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(vn)" );
+ return;
+ }
+ ctx->Eval.MapGrid2un = un;
+ ctx->Eval.MapGrid2u1 = u1;
+ ctx->Eval.MapGrid2u2 = u2;
+ ctx->Eval.MapGrid2du = (u2 - u1) / (GLfloat) un;
+ ctx->Eval.MapGrid2vn = vn;
+ ctx->Eval.MapGrid2v1 = v1;
+ ctx->Eval.MapGrid2v2 = v2;
+ ctx->Eval.MapGrid2dv = (v2 - v1) / (GLfloat) vn;
+}
+
+
+
+void gl_EvalMesh1( GLcontext* ctx, GLenum mode, GLint i1, GLint i2 )
+{
+ GLint i;
+ GLfloat u, du;
+ GLenum prim;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glEvalMesh1");
+
+ switch (mode) {
+ case GL_POINT:
+ prim = GL_POINTS;
+ break;
+ case GL_LINE:
+ prim = GL_LINE_STRIP;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glEvalMesh1(mode)" );
+ return;
+ }
+
+ /* No effect if vertex maps disabled.
+ */
+ if (!ctx->Eval.Map1Vertex4 && !ctx->Eval.Map1Vertex3)
+ return;
+
+ du = ctx->Eval.MapGrid1du;
+ u = ctx->Eval.MapGrid1u1 + i1 * du;
+
+ /* KW: Could short-circuit this to avoid the immediate mechanism.
+ */
+ RESET_IMMEDIATE(ctx);
+
+ gl_Begin( ctx, prim );
+ for (i=i1;i<=i2;i++,u+=du) {
+ gl_EvalCoord1f( ctx, u );
+ }
+ gl_End(ctx);
+}
+
+
+
+void gl_EvalMesh2( GLcontext* ctx,
+ GLenum mode,
+ GLint i1, GLint i2,
+ GLint j1, GLint j2 )
+{
+ GLint i, j;
+ GLfloat u, du, v, dv, v1, u1;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glEvalMesh2");
+
+ /* No effect if vertex maps disabled.
+ */
+ if (!ctx->Eval.Map2Vertex4 && !ctx->Eval.Map2Vertex3)
+ return;
+
+ du = ctx->Eval.MapGrid2du;
+ dv = ctx->Eval.MapGrid2dv;
+ v1 = ctx->Eval.MapGrid2v1 + j1 * dv;
+ u1 = ctx->Eval.MapGrid2u1 + i1 * du;
+
+ RESET_IMMEDIATE(ctx);
+
+ switch (mode) {
+ case GL_POINT:
+ gl_Begin( ctx, GL_POINTS );
+ for (v=v1,j=j1;j<=j2;j++,v+=dv) {
+ for (u=u1,i=i1;i<=i2;i++,u+=du) {
+ gl_EvalCoord2f( ctx, u, v );
+ }
+ }
+ gl_End(ctx);
+ break;
+ case GL_LINE:
+ for (v=v1,j=j1;j<=j2;j++,v+=dv) {
+ gl_Begin( ctx, GL_LINE_STRIP );
+ for (u=u1,i=i1;i<=i2;i++,u+=du) {
+ gl_EvalCoord2f( ctx, u, v );
+ }
+ gl_End(ctx);
+ }
+ for (u=u1,i=i1;i<=i2;i++,u+=du) {
+ gl_Begin( ctx, GL_LINE_STRIP );
+ for (v=v1,j=j1;j<=j2;j++,v+=dv) {
+ gl_EvalCoord2f( ctx, u, v );
+ }
+ gl_End(ctx);
+ }
+ break;
+ case GL_FILL:
+ for (v=v1,j=j1;j<j2;j++,v+=dv) {
+ /* NOTE: a quad strip can't be used because the four */
+ /* can't be guaranteed to be coplanar! */
+ gl_Begin( ctx, GL_TRIANGLE_STRIP );
+ for (u=u1,i=i1;i<=i2;i++,u+=du) {
+ gl_EvalCoord2f( ctx, u, v );
+ gl_EvalCoord2f( ctx, u, v+dv );
+ }
+ gl_End(ctx);
+ }
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glEvalMesh2(mode)" );
+ return;
+ }
+}
+
diff --git a/src/mesa/main/eval.h b/src/mesa/main/eval.h
new file mode 100644
index 0000000000..cde76b08dd
--- /dev/null
+++ b/src/mesa/main/eval.h
@@ -0,0 +1,95 @@
+/* $Id: eval.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+#ifndef EVAL_H
+#define EVAL_H
+
+
+#include "types.h"
+
+
+extern void gl_init_eval( void );
+
+
+extern void gl_free_control_points( GLcontext *ctx,
+ GLenum target, GLfloat *data );
+
+
+extern GLfloat *gl_copy_map_points1f( GLenum target,
+ GLint ustride, GLint uorder,
+ const GLfloat *points );
+
+extern GLfloat *gl_copy_map_points1d( GLenum target,
+ GLint ustride, GLint uorder,
+ const GLdouble *points );
+
+extern GLfloat *gl_copy_map_points2f( GLenum target,
+ GLint ustride, GLint uorder,
+ GLint vstride, GLint vorder,
+ const GLfloat *points );
+
+extern GLfloat *gl_copy_map_points2d(GLenum target,
+ GLint ustride, GLint uorder,
+ GLint vstride, GLint vorder,
+ const GLdouble *points );
+
+
+extern void gl_Map1f( GLcontext* ctx,
+ GLenum target, GLfloat u1, GLfloat u2, GLint stride,
+ GLint order, const GLfloat *points, GLboolean retain );
+
+extern void gl_Map2f( GLcontext* ctx, GLenum target,
+ GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
+ GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
+ const GLfloat *points, GLboolean retain );
+
+
+
+extern void gl_MapGrid1f( GLcontext* ctx, GLint un, GLfloat u1, GLfloat u2 );
+
+extern void gl_MapGrid2f( GLcontext* ctx,
+ GLint un, GLfloat u1, GLfloat u2,
+ GLint vn, GLfloat v1, GLfloat v2 );
+
+extern void gl_GetMapdv( GLcontext* ctx,
+ GLenum target, GLenum query, GLdouble *v );
+
+extern void gl_GetMapfv( GLcontext* ctx,
+ GLenum target, GLenum query, GLfloat *v );
+
+extern void gl_GetMapiv( GLcontext* ctx,
+ GLenum target, GLenum query, GLint *v );
+
+extern void gl_EvalMesh1( GLcontext* ctx, GLenum mode, GLint i1, GLint i2 );
+
+extern void gl_EvalMesh2( GLcontext* ctx, GLenum mode,
+ GLint i1, GLint i2, GLint j1, GLint j2 );
+
+extern void gl_eval_vb( struct vertex_buffer *VB );
+
+
+#endif
diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c
new file mode 100644
index 0000000000..55687294d1
--- /dev/null
+++ b/src/mesa/main/extensions.c
@@ -0,0 +1,196 @@
+/* $Id: extensions.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+#include <stdlib.h>
+#include "extensions.h"
+#include "simple_list.h"
+#include "types.h"
+
+#define MAX_EXT_NAMELEN 80
+#define MALLOC_STRUCT(T) (struct T *) malloc( sizeof(struct T) )
+
+struct extension {
+ struct extension *next, *prev;
+ int enabled;
+ char name[MAX_EXT_NAMELEN+1];
+ void (*notify)( GLcontext *, GLboolean );
+};
+
+
+
+static struct { int enabled; const char *name; } default_extensions[] = {
+ { ALWAYS_ENABLED, "GL_EXT_blend_color" },
+ { ALWAYS_ENABLED, "GL_EXT_blend_minmax" },
+ { ALWAYS_ENABLED, "GL_EXT_blend_logic_op" },
+ { ALWAYS_ENABLED, "GL_EXT_blend_subtract" },
+ { ALWAYS_ENABLED, "GL_EXT_paletted_texture" },
+ { DEFAULT_ON, "GL_EXT_point_parameters" },
+ { ALWAYS_ENABLED, "GL_EXT_polygon_offset" },
+ { ALWAYS_ENABLED, "GL_EXT_vertex_array" },
+ { ALWAYS_ENABLED, "GL_EXT_texture_object" },
+ { DEFAULT_ON, "GL_EXT_texture3D" },
+ { ALWAYS_ENABLED, "GL_MESA_window_pos" },
+ { ALWAYS_ENABLED, "GL_MESA_resize_buffers" },
+ { ALWAYS_ENABLED, "GL_EXT_shared_texture_palette" },
+ { ALWAYS_ENABLED, "GL_EXT_rescale_normal" },
+ { ALWAYS_ENABLED, "GL_EXT_abgr" },
+ { ALWAYS_ENABLED, "GL_SGIS_texture_edge_clamp" },
+ { ALWAYS_ENABLED, "GL_EXT_stencil_wrap" },
+ { ALWAYS_ENABLED, "GL_INGR_blend_func_separate" },
+ { DEFAULT_ON, "GL_ARB_multitexture" },
+ { ALWAYS_ENABLED, "GL_NV_texgen_reflection" },
+ { DEFAULT_ON, "GL_PGI_misc_hints" },
+ { DEFAULT_ON, "GL_EXT_compiled_vertex_array" },
+ { DEFAULT_OFF, "GL_EXT_vertex_array_set" },
+ { DEFAULT_ON, "GL_EXT_clip_volume_hint" },
+};
+
+
+int gl_extensions_add( GLcontext *ctx,
+ int state,
+ const char *name,
+ void (*notify)() )
+{
+ (void) notify;
+
+ if (ctx->Extensions.ext_string == 0)
+ {
+ struct extension *t = MALLOC_STRUCT(extension);
+ t->enabled = state;
+ strncpy(t->name, name, MAX_EXT_NAMELEN);
+ t->name[MAX_EXT_NAMELEN] = 0;
+ t->notify = (void (*)(GLcontext *, GLboolean)) notify;
+ insert_at_tail( ctx->Extensions.ext_list, t );
+ return 0;
+ }
+ return 1;
+}
+
+
+static int set_extension( GLcontext *ctx, const char *name, GLuint state )
+{
+ struct extension *i;
+ foreach( i, ctx->Extensions.ext_list )
+ if (strncmp(i->name, name, MAX_EXT_NAMELEN) == 0)
+ break;
+
+ if (i == ctx->Extensions.ext_list) return 1;
+
+ if (i->enabled && !(i->enabled & ALWAYS_ENABLED))
+ {
+ if (i->notify) i->notify( ctx, state );
+ i->enabled = state;
+ }
+
+ return 0;
+}
+
+
+int gl_extensions_enable( GLcontext *ctx, const char *name )
+{
+ if (ctx->Extensions.ext_string == 0)
+ return set_extension( ctx, name, 1 );
+ return 1;
+}
+
+
+int gl_extensions_disable( GLcontext *ctx, const char *name )
+{
+ if (ctx->Extensions.ext_string == 0)
+ return set_extension( ctx, name, 0 );
+ return 1;
+}
+
+
+void gl_extensions_dtr( GLcontext *ctx )
+{
+ struct extension *i, *nexti;
+
+ if (ctx->Extensions.ext_string) {
+ free( ctx->Extensions.ext_string );
+ ctx->Extensions.ext_string = 0;
+ }
+
+ if (ctx->Extensions.ext_list) {
+ foreach_s( i, nexti, ctx->Extensions.ext_list ) {
+ free( i );
+ }
+
+ free(ctx->Extensions.ext_list);
+ ctx->Extensions.ext_list = 0;
+ }
+}
+
+
+void gl_extensions_ctr( GLcontext *ctx )
+{
+ GLuint i;
+
+ ctx->Extensions.ext_string = 0;
+ ctx->Extensions.ext_list = MALLOC_STRUCT(extension);
+ make_empty_list( ctx->Extensions.ext_list );
+
+ for (i = 0 ; i < Elements(default_extensions) ; i++) {
+ gl_extensions_add( ctx,
+ default_extensions[i].enabled,
+ default_extensions[i].name,
+ 0 );
+ }
+}
+
+
+const char *gl_extensions_get_string( GLcontext *ctx )
+{
+ if (ctx->Extensions.ext_string == 0)
+ {
+ struct extension *i;
+ char *str;
+ GLuint len = 0;
+ foreach (i, ctx->Extensions.ext_list)
+ if (i->enabled)
+ len += strlen(i->name) + 1;
+
+ if (len == 0)
+ return "";
+
+ str = (char *)malloc(len * sizeof(char));
+ ctx->Extensions.ext_string = str;
+
+ foreach (i, ctx->Extensions.ext_list)
+ if (i->enabled) {
+ strcpy(str, i->name);
+ str += strlen(str);
+ *str++ = ' ';
+ }
+
+ *(str-1) = 0;
+ }
+
+ return ctx->Extensions.ext_string;
+}
+
+
diff --git a/src/mesa/main/extensions.h b/src/mesa/main/extensions.h
new file mode 100644
index 0000000000..a19dc47920
--- /dev/null
+++ b/src/mesa/main/extensions.h
@@ -0,0 +1,56 @@
+/* $Id: extensions.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+#ifndef _EXTENSIONS_H_
+#define _EXTENSIONS_H_
+
+struct gl_context;
+struct extension;
+
+struct gl_extensions {
+ char *ext_string;
+ struct extension *ext_list;
+};
+
+#define DEFAULT_OFF 0x0
+#define DEFAULT_ON 0x1
+#define ALWAYS_ENABLED 0x2
+
+/* Return 0 on success.
+ */
+extern int gl_extensions_add( struct gl_context *ctx, int state,
+ const char *name, void (*notify)() );
+
+extern int gl_extensions_enable( struct gl_context *ctx, const char *name );
+extern int gl_extensions_disable( struct gl_context *ctx, const char *name );
+extern void gl_extensions_dtr( struct gl_context *ctx );
+extern void gl_extensions_ctr( struct gl_context *ctx );
+extern const char *gl_extensions_get_string( struct gl_context *ctx );
+
+#endif
+
+
diff --git a/src/mesa/main/feedback.c b/src/mesa/main/feedback.c
new file mode 100644
index 0000000000..4251aae01a
--- /dev/null
+++ b/src/mesa/main/feedback.c
@@ -0,0 +1,395 @@
+/* $Id: feedback.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <assert.h>
+#include <stdio.h>
+#include "context.h"
+#include "enums.h"
+#include "feedback.h"
+#include "macros.h"
+#include "types.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+
+#define FB_3D 0x01
+#define FB_4D 0x02
+#define FB_INDEX 0x04
+#define FB_COLOR 0x08
+#define FB_TEXTURE 0X10
+
+
+
+void
+gl_FeedbackBuffer( GLcontext *ctx, GLsizei size, GLenum type, GLfloat *buffer )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx, "glFeedbackBuffer" );
+
+ if (ctx->RenderMode==GL_FEEDBACK) {
+ gl_error( ctx, GL_INVALID_OPERATION, "glFeedbackBuffer" );
+ return;
+ }
+
+ if (size<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(size<0)" );
+ return;
+ }
+ if (!buffer) {
+ gl_error( ctx, GL_INVALID_VALUE, "glFeedbackBuffer(buffer==NULL)" );
+ ctx->Feedback.BufferSize = 0;
+ return;
+ }
+
+ switch (type) {
+ case GL_2D:
+ ctx->Feedback.Mask = 0;
+ ctx->Feedback.Type = type;
+ break;
+ case GL_3D:
+ ctx->Feedback.Mask = FB_3D;
+ ctx->Feedback.Type = type;
+ break;
+ case GL_3D_COLOR:
+ ctx->Feedback.Mask = FB_3D
+ | (ctx->Visual->RGBAflag ? FB_COLOR : FB_INDEX);
+ ctx->Feedback.Type = type;
+ break;
+ case GL_3D_COLOR_TEXTURE:
+ ctx->Feedback.Mask = FB_3D
+ | (ctx->Visual->RGBAflag ? FB_COLOR : FB_INDEX)
+ | FB_TEXTURE;
+ ctx->Feedback.Type = type;
+ break;
+ case GL_4D_COLOR_TEXTURE:
+ ctx->Feedback.Mask = FB_3D | FB_4D
+ | (ctx->Visual->RGBAflag ? FB_COLOR : FB_INDEX)
+ | FB_TEXTURE;
+ ctx->Feedback.Type = type;
+ break;
+ default:
+ ctx->Feedback.Mask = 0;
+ gl_error( ctx, GL_INVALID_ENUM, "glFeedbackBuffer" );
+ }
+
+ ctx->Feedback.BufferSize = size;
+ ctx->Feedback.Buffer = buffer;
+ ctx->Feedback.Count = 0;
+}
+
+
+
+void gl_PassThrough( GLcontext *ctx, GLfloat token )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPassThrough");
+
+ if (ctx->RenderMode==GL_FEEDBACK) {
+ FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_PASS_THROUGH_TOKEN );
+ FEEDBACK_TOKEN( ctx, token );
+ }
+}
+
+
+
+/*
+ * Put a vertex into the feedback buffer.
+ */
+void gl_feedback_vertex( GLcontext *ctx,
+ GLfloat x, GLfloat y, GLfloat z, GLfloat w,
+ const GLfloat color[4], GLfloat index,
+ const GLfloat texcoord[4] )
+{
+ FEEDBACK_TOKEN( ctx, x );
+ FEEDBACK_TOKEN( ctx, y );
+ if (ctx->Feedback.Mask & FB_3D) {
+ FEEDBACK_TOKEN( ctx, z );
+ }
+ if (ctx->Feedback.Mask & FB_4D) {
+ FEEDBACK_TOKEN( ctx, w );
+ }
+ if (ctx->Feedback.Mask & FB_INDEX) {
+ FEEDBACK_TOKEN( ctx, index );
+ }
+ if (ctx->Feedback.Mask & FB_COLOR) {
+ FEEDBACK_TOKEN( ctx, color[0] );
+ FEEDBACK_TOKEN( ctx, color[1] );
+ FEEDBACK_TOKEN( ctx, color[2] );
+ FEEDBACK_TOKEN( ctx, color[3] );
+ }
+ if (ctx->Feedback.Mask & FB_TEXTURE) {
+ FEEDBACK_TOKEN( ctx, texcoord[0] );
+ FEEDBACK_TOKEN( ctx, texcoord[1] );
+ FEEDBACK_TOKEN( ctx, texcoord[2] );
+ FEEDBACK_TOKEN( ctx, texcoord[3] );
+ }
+}
+
+
+
+/**********************************************************************/
+/* Selection */
+/**********************************************************************/
+
+
+/*
+ * NOTE: this function can't be put in a display list.
+ */
+void gl_SelectBuffer( GLcontext *ctx, GLsizei size, GLuint *buffer )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glSelectBuffer");
+ if (ctx->RenderMode==GL_SELECT) {
+ gl_error( ctx, GL_INVALID_OPERATION, "glSelectBuffer" );
+ }
+ ctx->Select.Buffer = buffer;
+ ctx->Select.BufferSize = size;
+ ctx->Select.BufferCount = 0;
+
+ ctx->Select.HitFlag = GL_FALSE;
+ ctx->Select.HitMinZ = 1.0;
+ ctx->Select.HitMaxZ = 0.0;
+}
+
+
+#define WRITE_RECORD( CTX, V ) \
+ if (CTX->Select.BufferCount < CTX->Select.BufferSize) { \
+ CTX->Select.Buffer[CTX->Select.BufferCount] = (V); \
+ } \
+ CTX->Select.BufferCount++;
+
+
+
+void gl_update_hitflag( GLcontext *ctx, GLfloat z )
+{
+ ctx->Select.HitFlag = GL_TRUE;
+ if (z < ctx->Select.HitMinZ) {
+ ctx->Select.HitMinZ = z;
+ }
+ if (z > ctx->Select.HitMaxZ) {
+ ctx->Select.HitMaxZ = z;
+ }
+}
+
+
+
+static void write_hit_record( GLcontext *ctx )
+{
+ GLuint i;
+ GLuint zmin, zmax, zscale = (~0u);
+
+ /* HitMinZ and HitMaxZ are in [0,1]. Multiply these values by */
+ /* 2^32-1 and round to nearest unsigned integer. */
+
+ assert( ctx != NULL ); /* this line magically fixes a SunOS 5.x/gcc bug */
+ zmin = (GLuint) ((GLfloat) zscale * ctx->Select.HitMinZ);
+ zmax = (GLuint) ((GLfloat) zscale * ctx->Select.HitMaxZ);
+
+ WRITE_RECORD( ctx, ctx->Select.NameStackDepth );
+ WRITE_RECORD( ctx, zmin );
+ WRITE_RECORD( ctx, zmax );
+ for (i=0;i<ctx->Select.NameStackDepth;i++) {
+ WRITE_RECORD( ctx, ctx->Select.NameStack[i] );
+ }
+
+ ctx->Select.Hits++;
+ ctx->Select.HitFlag = GL_FALSE;
+ ctx->Select.HitMinZ = 1.0;
+ ctx->Select.HitMaxZ = -1.0;
+}
+
+
+
+void gl_InitNames( GLcontext *ctx )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glInitNames");
+ /* Record the hit before the HitFlag is wiped out again. */
+ if (ctx->RenderMode==GL_SELECT) {
+ if (ctx->Select.HitFlag) {
+ write_hit_record( ctx );
+ }
+ }
+ ctx->Select.NameStackDepth = 0;
+ ctx->Select.HitFlag = GL_FALSE;
+ ctx->Select.HitMinZ = 1.0;
+ ctx->Select.HitMaxZ = 0.0;
+}
+
+
+
+void gl_LoadName( GLcontext *ctx, GLuint name )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLoadName");
+ if (ctx->RenderMode!=GL_SELECT) {
+ return;
+ }
+ if (ctx->Select.NameStackDepth==0) {
+ gl_error( ctx, GL_INVALID_OPERATION, "glLoadName" );
+ return;
+ }
+ if (ctx->Select.HitFlag) {
+ write_hit_record( ctx );
+ }
+ if (ctx->Select.NameStackDepth<MAX_NAME_STACK_DEPTH) {
+ ctx->Select.NameStack[ctx->Select.NameStackDepth-1] = name;
+ }
+ else {
+ ctx->Select.NameStack[MAX_NAME_STACK_DEPTH-1] = name;
+ }
+}
+
+
+void gl_PushName( GLcontext *ctx, GLuint name )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPushName");
+ if (ctx->RenderMode!=GL_SELECT) {
+ return;
+ }
+ if (ctx->Select.HitFlag) {
+ write_hit_record( ctx );
+ }
+ if (ctx->Select.NameStackDepth<MAX_NAME_STACK_DEPTH) {
+ ctx->Select.NameStack[ctx->Select.NameStackDepth++] = name;
+ }
+ else {
+ gl_error( ctx, GL_STACK_OVERFLOW, "glPushName" );
+ }
+}
+
+
+
+void gl_PopName( GLcontext *ctx )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPopName");
+ if (ctx->RenderMode!=GL_SELECT) {
+ return;
+ }
+ if (ctx->Select.HitFlag) {
+ write_hit_record( ctx );
+ }
+ if (ctx->Select.NameStackDepth>0) {
+ ctx->Select.NameStackDepth--;
+ }
+ else {
+ gl_error( ctx, GL_STACK_UNDERFLOW, "glPopName" );
+ }
+}
+
+
+
+/**********************************************************************/
+/* Render Mode */
+/**********************************************************************/
+
+
+
+/*
+ * NOTE: this function can't be put in a display list.
+ */
+GLint gl_RenderMode( GLcontext *ctx, GLenum mode )
+{
+ GLint result;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, "glRenderMode", 0);
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ fprintf(stderr, "glRenderMode %s\n", gl_lookup_enum_by_nr(mode));
+
+ ctx->TriangleCaps &= ~(DD_FEEDBACK|DD_SELECT);
+
+ switch (ctx->RenderMode) {
+ case GL_RENDER:
+ result = 0;
+ break;
+ case GL_SELECT:
+ if (ctx->Select.HitFlag) {
+ write_hit_record( ctx );
+ }
+ if (ctx->Select.BufferCount > ctx->Select.BufferSize) {
+ /* overflow */
+#ifdef DEBUG
+ gl_warning(ctx, "Feedback buffer overflow");
+#endif
+ result = -1;
+ }
+ else {
+ result = ctx->Select.Hits;
+ }
+ ctx->Select.BufferCount = 0;
+ ctx->Select.Hits = 0;
+ ctx->Select.NameStackDepth = 0;
+ break;
+ case GL_FEEDBACK:
+ if (ctx->Feedback.Count > ctx->Feedback.BufferSize) {
+ /* overflow */
+ result = -1;
+ }
+ else {
+ result = ctx->Feedback.Count;
+ }
+ ctx->Feedback.Count = 0;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glRenderMode" );
+ return 0;
+ }
+
+ switch (mode) {
+ case GL_RENDER:
+ break;
+ case GL_SELECT:
+ ctx->TriangleCaps |= DD_SELECT;
+ if (ctx->Select.BufferSize==0) {
+ /* haven't called glSelectBuffer yet */
+ gl_error( ctx, GL_INVALID_OPERATION, "glRenderMode" );
+ }
+ break;
+ case GL_FEEDBACK:
+ ctx->TriangleCaps |= DD_FEEDBACK;
+ if (ctx->Feedback.BufferSize==0) {
+ /* haven't called glFeedbackBuffer yet */
+ gl_error( ctx, GL_INVALID_OPERATION, "glRenderMode" );
+ }
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glRenderMode" );
+ return 0;
+ }
+
+
+ ctx->RenderMode = mode;
+ ctx->NewState |= NEW_ALL;
+
+ return result;
+}
+
diff --git a/src/mesa/main/feedback.h b/src/mesa/main/feedback.h
new file mode 100644
index 0000000000..99a4b7aeb1
--- /dev/null
+++ b/src/mesa/main/feedback.h
@@ -0,0 +1,74 @@
+/* $Id: feedback.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef FEEDBACK_H
+#define FEEDBACK_H
+
+
+#include "types.h"
+
+
+#define FEEDBACK_TOKEN( CTX, T ) \
+ if (CTX->Feedback.Count < CTX->Feedback.BufferSize) { \
+ CTX->Feedback.Buffer[CTX->Feedback.Count] = (T); \
+ } \
+ CTX->Feedback.Count++;
+
+
+extern void gl_feedback_vertex( GLcontext *ctx,
+ GLfloat x, GLfloat y, GLfloat z, GLfloat w,
+ const GLfloat color[4], GLfloat index,
+ const GLfloat texcoord[4] );
+
+
+extern void gl_update_hitflag( GLcontext *ctx, GLfloat z );
+
+
+extern void gl_PassThrough( GLcontext *ctx, GLfloat token );
+
+extern void gl_FeedbackBuffer( GLcontext *ctx, GLsizei size,
+ GLenum type, GLfloat *buffer );
+
+extern void gl_SelectBuffer( GLcontext *ctx, GLsizei size, GLuint *buffer );
+
+extern void gl_InitNames( GLcontext *ctx );
+
+extern void gl_LoadName( GLcontext *ctx, GLuint name );
+
+extern void gl_PushName( GLcontext *ctx, GLuint name );
+
+extern void gl_PopName( GLcontext *ctx );
+
+extern GLint gl_RenderMode( GLcontext *ctx, GLenum mode );
+
+
+
+#endif
+
diff --git a/src/mesa/main/fog.c b/src/mesa/main/fog.c
new file mode 100644
index 0000000000..1579c8c47c
--- /dev/null
+++ b/src/mesa/main/fog.c
@@ -0,0 +1,327 @@
+/* $Id: fog.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <math.h>
+#include <stdlib.h>
+#include "context.h"
+#include "fog.h"
+#include "macros.h"
+#include "mmath.h"
+#include "types.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+
+void gl_Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *params )
+{
+ GLenum m;
+
+ switch (pname) {
+ case GL_FOG_MODE:
+ m = (GLenum) (GLint) *params;
+ if (m==GL_LINEAR || m==GL_EXP || m==GL_EXP2) {
+ ctx->Fog.Mode = m;
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM, "glFog" );
+ return;
+ }
+ break;
+ case GL_FOG_DENSITY:
+ if (*params<0.0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glFog" );
+ return;
+ }
+ else {
+ ctx->Fog.Density = *params;
+ }
+ break;
+ case GL_FOG_START:
+#if 0
+ /* Prior to OpenGL 1.1, this was an error */
+ if (*params<0.0F) {
+ gl_error( ctx, GL_INVALID_VALUE, "glFog(GL_FOG_START)" );
+ return;
+ }
+#endif
+ ctx->Fog.Start = *params;
+ break;
+ case GL_FOG_END:
+#if 0
+ /* Prior to OpenGL 1.1, this was an error */
+ if (*params<0.0F) {
+ gl_error( ctx, GL_INVALID_VALUE, "glFog(GL_FOG_END)" );
+ return;
+ }
+#endif
+ ctx->Fog.End = *params;
+ break;
+ case GL_FOG_INDEX:
+ ctx->Fog.Index = *params;
+ break;
+ case GL_FOG_COLOR:
+ ctx->Fog.Color[0] = params[0];
+ ctx->Fog.Color[1] = params[1];
+ ctx->Fog.Color[2] = params[2];
+ ctx->Fog.Color[3] = params[3];
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glFog" );
+ return;
+ }
+
+ if (ctx->Driver.Fogfv) {
+ (*ctx->Driver.Fogfv)( ctx, pname, params );
+ }
+
+ ctx->NewState |= NEW_FOG;
+}
+
+
+typedef void (*fog_func)( struct vertex_buffer *VB, GLuint side,
+ GLubyte flag );
+
+
+static fog_func fog_ci_tab[2];
+static fog_func fog_rgba_tab[2];
+
+/*
+ * Compute the fogged color for an array of vertices.
+ * Input: n - number of vertices
+ * v - array of vertices
+ * color - the original vertex colors
+ * Output: color - the fogged colors
+ *
+ */
+#define TAG(x) x##_raw
+#define CULLCHECK
+#define IDX 0
+#include "fog_tmp.h"
+
+#define TAG(x) x##_masked
+#define CULLCHECK if (cullmask[i]&flag)
+#define IDX 1
+#include "fog_tmp.h"
+
+void gl_init_fog( void )
+{
+ init_fog_tab_masked();
+ init_fog_tab_raw();
+}
+
+/*
+ * Compute fog for the vertices in the vertex buffer.
+ */
+void gl_fog_vertices( struct vertex_buffer *VB )
+{
+ GLcontext *ctx = VB->ctx;
+ GLuint i = VB->CullMode & 1;
+
+ if (ctx->Visual->RGBAflag) {
+ /* Fog RGB colors */
+ if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
+ fog_rgba_tab[i]( VB, 0, VERT_FACE_FRONT );
+ fog_rgba_tab[i]( VB, 1, VERT_FACE_REAR );
+ } else {
+ fog_rgba_tab[i]( VB, 0, VERT_FACE_FRONT|VERT_FACE_REAR );
+ }
+ }
+ else {
+ /* Fog color indexes */
+ if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
+ fog_ci_tab[i]( VB, 0, VERT_FACE_FRONT );
+ fog_ci_tab[i]( VB, 1, VERT_FACE_REAR );
+ } else {
+ fog_ci_tab[i]( VB, 0, VERT_FACE_FRONT|VERT_FACE_REAR );
+ }
+ }
+}
+
+/*
+ * Apply fog to an array of RGBA pixels.
+ * Input: n - number of pixels
+ * z - array of integer depth values
+ * red, green, blue, alpha - pixel colors
+ * Output: red, green, blue, alpha - fogged pixel colors
+ */
+void gl_fog_rgba_pixels( const GLcontext *ctx,
+ GLuint n, const GLdepth z[], GLubyte rgba[][4] )
+{
+ GLfloat c = ctx->ProjectionMatrix.m[10];
+ GLfloat d = ctx->ProjectionMatrix.m[14];
+ GLuint i;
+
+ GLfloat rFog = ctx->Fog.Color[0] * 255.0F;
+ GLfloat gFog = ctx->Fog.Color[1] * 255.0F;
+ GLfloat bFog = ctx->Fog.Color[2] * 255.0F;
+
+ GLfloat tz = ctx->Viewport.WindowMap.m[MAT_TZ];
+ GLfloat szInv = 1.0F / ctx->Viewport.WindowMap.m[MAT_SZ];
+
+ switch (ctx->Fog.Mode) {
+ case GL_LINEAR:
+ {
+ GLfloat fogEnd = ctx->Fog.End;
+ GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
+ for (i=0;i<n;i++) {
+ GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
+ GLfloat eyez = -d / (c+ndcz);
+ GLfloat f, g;
+ if (eyez < 0.0) eyez = -eyez;
+ f = (fogEnd - eyez) * fogScale;
+ f = CLAMP( f, 0.0F, 1.0F );
+ g = 1.0F - f;
+ rgba[i][RCOMP] = (GLint) (f * rgba[i][RCOMP] + g * rFog);
+ rgba[i][GCOMP] = (GLint) (f * rgba[i][GCOMP] + g * gFog);
+ rgba[i][BCOMP] = (GLint) (f * rgba[i][BCOMP] + g * bFog);
+ }
+ }
+ break;
+ case GL_EXP:
+ for (i=0;i<n;i++) {
+ GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
+ GLfloat eyez = d / (c+ndcz);
+ GLfloat f, g;
+ if (eyez < 0.0)
+ eyez = -eyez;
+ f = exp( -ctx->Fog.Density * eyez );
+ g = 1.0F - f;
+ rgba[i][RCOMP] = (GLint) (f * rgba[i][RCOMP] + g * rFog);
+ rgba[i][GCOMP] = (GLint) (f * rgba[i][GCOMP] + g * gFog);
+ rgba[i][BCOMP] = (GLint) (f * rgba[i][BCOMP] + g * bFog);
+ }
+ break;
+ case GL_EXP2:
+ {
+ GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
+ for (i=0;i<n;i++) {
+ GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
+ GLfloat eyez = d / (c+ndcz);
+ GLfloat f, g;
+ GLfloat tmp = negDensitySquared * eyez * eyez;
+#ifdef __alpha__
+ /* XXX this underflow check may be needed for other systems */
+ if (tmp < FLT_MIN_10_EXP)
+ f = exp( FLT_MIN_10_EXP );
+ else
+#endif
+ f = exp( tmp );
+ g = 1.0F - f;
+ rgba[i][RCOMP] = (GLint) (f * rgba[i][RCOMP] + g * rFog);
+ rgba[i][GCOMP] = (GLint) (f * rgba[i][GCOMP] + g * gFog);
+ rgba[i][BCOMP] = (GLint) (f * rgba[i][BCOMP] + g * bFog);
+ }
+ }
+ break;
+ default:
+ gl_problem(ctx, "Bad fog mode in gl_fog_rgba_pixels");
+ return;
+ }
+}
+
+
+
+
+/*
+ * Apply fog to an array of color index pixels.
+ * Input: n - number of pixels
+ * z - array of integer depth values
+ * index - pixel color indexes
+ * Output: index - fogged pixel color indexes
+ */
+void gl_fog_ci_pixels( const GLcontext *ctx,
+ GLuint n, const GLdepth z[], GLuint index[] )
+{
+ GLfloat c = ctx->ProjectionMatrix.m[10];
+ GLfloat d = ctx->ProjectionMatrix.m[14];
+ GLuint i;
+
+ GLfloat tz = ctx->Viewport.WindowMap.m[MAT_TZ];
+ GLfloat szInv = 1.0F / ctx->Viewport.WindowMap.m[MAT_SZ];
+
+ switch (ctx->Fog.Mode) {
+ case GL_LINEAR:
+ {
+ GLfloat fogEnd = ctx->Fog.End;
+ GLfloat fogScale = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
+ for (i=0;i<n;i++) {
+ GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
+ GLfloat eyez = -d / (c+ndcz);
+ GLfloat f;
+ if (eyez < 0.0) eyez = -eyez;
+ f = (fogEnd - eyez) * fogScale;
+ f = CLAMP( f, 0.0F, 1.0F );
+ index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
+ }
+ }
+ break;
+ case GL_EXP:
+ for (i=0;i<n;i++) {
+ GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
+ GLfloat eyez = -d / (c+ndcz);
+ GLfloat f;
+ if (eyez < 0.0)
+ eyez = -eyez;
+ f = exp( -ctx->Fog.Density * eyez );
+ f = CLAMP( f, 0.0F, 1.0F );
+ index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
+ }
+ break;
+ case GL_EXP2:
+ {
+ GLfloat negDensitySquared = -ctx->Fog.Density * ctx->Fog.Density;
+ for (i=0;i<n;i++) {
+ GLfloat ndcz = ((GLfloat) z[i] - tz) * szInv;
+ GLfloat eyez = -d / (c+ndcz);
+ GLfloat tmp, f;
+ if (eyez < 0.0)
+ eyez = -eyez;
+ tmp = negDensitySquared * eyez * eyez;
+#ifdef __alpha__
+ /* XXX this underflow check may be needed for other systems */
+ if (tmp < FLT_MIN_10_EXP)
+ f = exp( FLT_MIN_10_EXP );
+ else
+#endif
+ f = exp( tmp );
+ f = CLAMP( f, 0.0F, 1.0F );
+ index[i] = (GLuint) ((GLfloat) index[i] + (1.0F-f) * ctx->Fog.Index);
+ }
+ }
+ break;
+ default:
+ gl_problem(ctx, "Bad fog mode in gl_fog_ci_pixels");
+ return;
+ }
+}
+
diff --git a/src/mesa/main/fog.h b/src/mesa/main/fog.h
new file mode 100644
index 0000000000..cf9dcebaf7
--- /dev/null
+++ b/src/mesa/main/fog.h
@@ -0,0 +1,51 @@
+/* $Id: fog.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+#ifndef FOG_H
+#define FOG_H
+
+
+#include "types.h"
+
+
+extern void gl_Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *params );
+
+
+extern void gl_fog_vertices( struct vertex_buffer *VB );
+
+extern void gl_fog_rgba_pixels( const GLcontext *ctx,
+ GLuint n, const GLdepth z[],
+ GLubyte rgba[][4] );
+
+extern void gl_fog_ci_pixels( const GLcontext *ctx,
+ GLuint n, const GLdepth z[], GLuint indx[] );
+
+
+extern void gl_init_fog( void );
+
+#endif
diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c
new file mode 100644
index 0000000000..65a682c547
--- /dev/null
+++ b/src/mesa/main/get.c
@@ -0,0 +1,3692 @@
+/* $Id: get.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include "context.h"
+#include "enable.h"
+#include "enums.h"
+#include "get.h"
+#include "macros.h"
+#include "mmath.h"
+#include "types.h"
+#include "vb.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+
+#define FLOAT_TO_BOOL(X) ( (X)==0.0F ? GL_FALSE : GL_TRUE )
+#define INT_TO_BOOL(I) ( (I)==0 ? GL_FALSE : GL_TRUE )
+#define ENUM_TO_BOOL(E) ( (E)==0 ? GL_FALSE : GL_TRUE )
+
+#ifdef SPECIALCAST
+/* Needed for an Amiga compiler */
+#define ENUM_TO_FLOAT(X) ((GLfloat)(GLint)(X))
+#define ENUM_TO_DOUBLE(X) ((GLdouble)(GLint)(X))
+#else
+/* all other compilers */
+#define ENUM_TO_FLOAT(X) ((GLfloat)(X))
+#define ENUM_TO_DOUBLE(X) ((GLdouble)(X))
+#endif
+
+
+
+void gl_GetBooleanv( GLcontext *ctx, GLenum pname, GLboolean *params )
+{
+ GLuint i;
+ GLuint texUnit = ctx->Texture.CurrentUnit;
+ GLuint texTransformUnit = ctx->Texture.CurrentTransformUnit;
+ const struct gl_texture_unit *textureUnit = &ctx->Texture.Unit[texUnit];
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetBooleanv");
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ fprintf(stderr, "glGetBooleanv %s\n", gl_lookup_enum_by_nr(pname));
+
+ switch (pname) {
+ case GL_ACCUM_RED_BITS:
+ case GL_ACCUM_GREEN_BITS:
+ case GL_ACCUM_BLUE_BITS:
+ case GL_ACCUM_ALPHA_BITS:
+ *params = INT_TO_BOOL(ctx->Visual->AccumBits);
+ break;
+ case GL_ACCUM_CLEAR_VALUE:
+ params[0] = FLOAT_TO_BOOL(ctx->Accum.ClearColor[0]);
+ params[1] = FLOAT_TO_BOOL(ctx->Accum.ClearColor[1]);
+ params[2] = FLOAT_TO_BOOL(ctx->Accum.ClearColor[2]);
+ params[3] = FLOAT_TO_BOOL(ctx->Accum.ClearColor[3]);
+ break;
+ case GL_ALPHA_BIAS:
+ *params = FLOAT_TO_BOOL(ctx->Pixel.AlphaBias);
+ break;
+ case GL_ALPHA_BITS:
+ *params = INT_TO_BOOL(ctx->Visual->AlphaBits);
+ break;
+ case GL_ALPHA_SCALE:
+ *params = FLOAT_TO_BOOL(ctx->Pixel.AlphaScale);
+ break;
+ case GL_ALPHA_TEST:
+ *params = ctx->Color.AlphaEnabled;
+ break;
+ case GL_ALPHA_TEST_FUNC:
+ *params = ENUM_TO_BOOL(ctx->Color.AlphaFunc);
+ break;
+ case GL_ALPHA_TEST_REF:
+ *params = FLOAT_TO_BOOL((GLfloat) ctx->Color.AlphaRef / 255.0);
+ break;
+ case GL_ATTRIB_STACK_DEPTH:
+ *params = INT_TO_BOOL(ctx->AttribStackDepth);
+ break;
+ case GL_AUTO_NORMAL:
+ *params = ctx->Eval.AutoNormal;
+ break;
+ case GL_AUX_BUFFERS:
+ *params = (NUM_AUX_BUFFERS) ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_BLEND:
+ *params = ctx->Color.BlendEnabled;
+ break;
+ case GL_BLEND_DST:
+ *params = ENUM_TO_BOOL(ctx->Color.BlendDstRGB);
+ break;
+ case GL_BLEND_SRC:
+ *params = ENUM_TO_BOOL(ctx->Color.BlendSrcRGB);
+ break;
+ case GL_BLEND_SRC_RGB_INGR:
+ *params = ENUM_TO_BOOL(ctx->Color.BlendSrcRGB);
+ break;
+ case GL_BLEND_DST_RGB_INGR:
+ *params = ENUM_TO_BOOL(ctx->Color.BlendDstRGB);
+ break;
+ case GL_BLEND_SRC_ALPHA_INGR:
+ *params = ENUM_TO_BOOL(ctx->Color.BlendSrcA);
+ break;
+ case GL_BLEND_DST_ALPHA_INGR:
+ *params = ENUM_TO_BOOL(ctx->Color.BlendDstA);
+ break;
+ case GL_BLEND_EQUATION_EXT:
+ *params = ENUM_TO_BOOL( ctx->Color.BlendEquation );
+ break;
+ case GL_BLEND_COLOR_EXT:
+ params[0] = FLOAT_TO_BOOL( ctx->Color.BlendColor[0] );
+ params[1] = FLOAT_TO_BOOL( ctx->Color.BlendColor[1] );
+ params[2] = FLOAT_TO_BOOL( ctx->Color.BlendColor[2] );
+ params[3] = FLOAT_TO_BOOL( ctx->Color.BlendColor[3] );
+ break;
+ case GL_BLUE_BIAS:
+ *params = FLOAT_TO_BOOL(ctx->Pixel.BlueBias);
+ break;
+ case GL_BLUE_BITS:
+ *params = INT_TO_BOOL( ctx->Visual->BlueBits );
+ break;
+ case GL_BLUE_SCALE:
+ *params = FLOAT_TO_BOOL(ctx->Pixel.BlueScale);
+ break;
+ case GL_CLIENT_ATTRIB_STACK_DEPTH:
+ *params = INT_TO_BOOL(ctx->ClientAttribStackDepth);
+ 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:
+ *params = ctx->Transform.ClipEnabled[pname-GL_CLIP_PLANE0];
+ break;
+ case GL_COLOR_CLEAR_VALUE:
+ params[0] = FLOAT_TO_BOOL(ctx->Color.ClearColor[0]);
+ params[1] = FLOAT_TO_BOOL(ctx->Color.ClearColor[1]);
+ params[2] = FLOAT_TO_BOOL(ctx->Color.ClearColor[2]);
+ params[3] = FLOAT_TO_BOOL(ctx->Color.ClearColor[3]);
+ break;
+ case GL_COLOR_MATERIAL:
+ *params = ctx->Light.ColorMaterialEnabled;
+ break;
+ case GL_COLOR_MATERIAL_FACE:
+ *params = ENUM_TO_BOOL(ctx->Light.ColorMaterialFace);
+ break;
+ case GL_COLOR_MATERIAL_PARAMETER:
+ *params = ENUM_TO_BOOL(ctx->Light.ColorMaterialMode);
+ break;
+ case GL_COLOR_WRITEMASK:
+ params[0] = ctx->Color.ColorMask[RCOMP] ? GL_TRUE : GL_FALSE;
+ params[1] = ctx->Color.ColorMask[GCOMP] ? GL_TRUE : GL_FALSE;
+ params[2] = ctx->Color.ColorMask[BCOMP] ? GL_TRUE : GL_FALSE;
+ params[3] = ctx->Color.ColorMask[ACOMP] ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_CULL_FACE:
+ *params = ctx->Polygon.CullFlag;
+ break;
+ case GL_CULL_FACE_MODE:
+ *params = ENUM_TO_BOOL(ctx->Polygon.CullFaceMode);
+ break;
+ case GL_CURRENT_COLOR:
+ params[0] = INT_TO_BOOL(ctx->Current.ByteColor[0]);
+ params[1] = INT_TO_BOOL(ctx->Current.ByteColor[1]);
+ params[2] = INT_TO_BOOL(ctx->Current.ByteColor[2]);
+ params[3] = INT_TO_BOOL(ctx->Current.ByteColor[3]);
+ break;
+ case GL_CURRENT_INDEX:
+ *params = INT_TO_BOOL(ctx->Current.Index);
+ break;
+ case GL_CURRENT_NORMAL:
+ params[0] = FLOAT_TO_BOOL(ctx->Current.Normal[0]);
+ params[1] = FLOAT_TO_BOOL(ctx->Current.Normal[1]);
+ params[2] = FLOAT_TO_BOOL(ctx->Current.Normal[2]);
+ break;
+ case GL_CURRENT_RASTER_COLOR:
+ params[0] = FLOAT_TO_BOOL(ctx->Current.RasterColor[0]);
+ params[1] = FLOAT_TO_BOOL(ctx->Current.RasterColor[1]);
+ params[2] = FLOAT_TO_BOOL(ctx->Current.RasterColor[2]);
+ params[3] = FLOAT_TO_BOOL(ctx->Current.RasterColor[3]);
+ break;
+ case GL_CURRENT_RASTER_DISTANCE:
+ *params = FLOAT_TO_BOOL(ctx->Current.RasterDistance);
+ break;
+ case GL_CURRENT_RASTER_INDEX:
+ *params = FLOAT_TO_BOOL(ctx->Current.RasterIndex);
+ break;
+ case GL_CURRENT_RASTER_POSITION:
+ params[0] = FLOAT_TO_BOOL(ctx->Current.RasterPos[0]);
+ params[1] = FLOAT_TO_BOOL(ctx->Current.RasterPos[1]);
+ params[2] = FLOAT_TO_BOOL(ctx->Current.RasterPos[2]);
+ params[3] = FLOAT_TO_BOOL(ctx->Current.RasterPos[3]);
+ break;
+ case GL_CURRENT_RASTER_TEXTURE_COORDS:
+ params[0] = FLOAT_TO_BOOL(ctx->Current.RasterMultiTexCoord[texTransformUnit][0]);
+ params[1] = FLOAT_TO_BOOL(ctx->Current.RasterMultiTexCoord[texTransformUnit][1]);
+ params[2] = FLOAT_TO_BOOL(ctx->Current.RasterMultiTexCoord[texTransformUnit][2]);
+ params[3] = FLOAT_TO_BOOL(ctx->Current.RasterMultiTexCoord[texTransformUnit][3]);
+ break;
+ case GL_CURRENT_RASTER_POSITION_VALID:
+ *params = ctx->Current.RasterPosValid;
+ break;
+ case GL_CURRENT_TEXTURE_COORDS:
+ params[0] = FLOAT_TO_BOOL(ctx->Current.Texcoord[texTransformUnit][0]);
+ params[1] = FLOAT_TO_BOOL(ctx->Current.Texcoord[texTransformUnit][1]);
+ params[2] = FLOAT_TO_BOOL(ctx->Current.Texcoord[texTransformUnit][2]);
+ params[3] = FLOAT_TO_BOOL(ctx->Current.Texcoord[texTransformUnit][3]);
+ break;
+ case GL_DEPTH_BIAS:
+ *params = FLOAT_TO_BOOL(ctx->Pixel.DepthBias);
+ break;
+ case GL_DEPTH_BITS:
+ *params = INT_TO_BOOL(ctx->Visual->DepthBits);
+ break;
+ case GL_DEPTH_CLEAR_VALUE:
+ *params = FLOAT_TO_BOOL(ctx->Depth.Clear);
+ break;
+ case GL_DEPTH_FUNC:
+ *params = ENUM_TO_BOOL(ctx->Depth.Func);
+ break;
+ case GL_DEPTH_RANGE:
+ params[0] = FLOAT_TO_BOOL(ctx->Viewport.Near);
+ params[1] = FLOAT_TO_BOOL(ctx->Viewport.Far);
+ break;
+ case GL_DEPTH_SCALE:
+ *params = FLOAT_TO_BOOL(ctx->Pixel.DepthScale);
+ break;
+ case GL_DEPTH_TEST:
+ *params = ctx->Depth.Test;
+ break;
+ case GL_DEPTH_WRITEMASK:
+ *params = ctx->Depth.Mask;
+ break;
+ case GL_DITHER:
+ *params = ctx->Color.DitherFlag;
+ break;
+ case GL_DOUBLEBUFFER:
+ *params = ctx->Visual->DBflag;
+ break;
+ case GL_DRAW_BUFFER:
+ *params = ENUM_TO_BOOL(ctx->Color.DrawBuffer);
+ break;
+ case GL_EDGE_FLAG:
+ *params = ctx->Current.EdgeFlag;
+ break;
+ case GL_FEEDBACK_BUFFER_SIZE:
+ /* TODO: is this right? Or, return number of entries in buffer? */
+ *params = INT_TO_BOOL(ctx->Feedback.BufferSize);
+ break;
+ case GL_FEEDBACK_BUFFER_TYPE:
+ *params = INT_TO_BOOL(ctx->Feedback.Type);
+ break;
+ case GL_FOG:
+ *params = ctx->Fog.Enabled;
+ break;
+ case GL_FOG_COLOR:
+ params[0] = FLOAT_TO_BOOL(ctx->Fog.Color[0]);
+ params[1] = FLOAT_TO_BOOL(ctx->Fog.Color[1]);
+ params[2] = FLOAT_TO_BOOL(ctx->Fog.Color[2]);
+ params[3] = FLOAT_TO_BOOL(ctx->Fog.Color[3]);
+ break;
+ case GL_FOG_DENSITY:
+ *params = FLOAT_TO_BOOL(ctx->Fog.Density);
+ break;
+ case GL_FOG_END:
+ *params = FLOAT_TO_BOOL(ctx->Fog.End);
+ break;
+ case GL_FOG_HINT:
+ *params = ENUM_TO_BOOL(ctx->Hint.Fog);
+ break;
+ case GL_FOG_INDEX:
+ *params = FLOAT_TO_BOOL(ctx->Fog.Index);
+ break;
+ case GL_FOG_MODE:
+ *params = ENUM_TO_BOOL(ctx->Fog.Mode);
+ break;
+ case GL_FOG_START:
+ *params = FLOAT_TO_BOOL(ctx->Fog.End);
+ break;
+ case GL_FRONT_FACE:
+ *params = ENUM_TO_BOOL(ctx->Polygon.FrontFace);
+ break;
+ case GL_GREEN_BIAS:
+ *params = FLOAT_TO_BOOL(ctx->Pixel.GreenBias);
+ break;
+ case GL_GREEN_BITS:
+ *params = INT_TO_BOOL( ctx->Visual->GreenBits );
+ break;
+ case GL_GREEN_SCALE:
+ *params = FLOAT_TO_BOOL(ctx->Pixel.GreenScale);
+ break;
+ case GL_INDEX_BITS:
+ *params = INT_TO_BOOL( ctx->Visual->IndexBits );
+ break;
+ case GL_INDEX_CLEAR_VALUE:
+ *params = INT_TO_BOOL(ctx->Color.ClearIndex);
+ break;
+ case GL_INDEX_MODE:
+ *params = ctx->Visual->RGBAflag ? GL_FALSE : GL_TRUE;
+ break;
+ case GL_INDEX_OFFSET:
+ *params = INT_TO_BOOL(ctx->Pixel.IndexOffset);
+ break;
+ case GL_INDEX_SHIFT:
+ *params = INT_TO_BOOL(ctx->Pixel.IndexShift);
+ break;
+ case GL_INDEX_WRITEMASK:
+ *params = INT_TO_BOOL(ctx->Color.IndexMask);
+ 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:
+ *params = ctx->Light.Light[pname-GL_LIGHT0].Enabled;
+ break;
+ case GL_LIGHTING:
+ *params = ctx->Light.Enabled;
+ break;
+ case GL_LIGHT_MODEL_AMBIENT:
+ params[0] = FLOAT_TO_BOOL(ctx->Light.Model.Ambient[0]);
+ params[1] = FLOAT_TO_BOOL(ctx->Light.Model.Ambient[1]);
+ params[2] = FLOAT_TO_BOOL(ctx->Light.Model.Ambient[2]);
+ params[3] = FLOAT_TO_BOOL(ctx->Light.Model.Ambient[3]);
+ break;
+ case GL_LIGHT_MODEL_COLOR_CONTROL:
+ params[0] = ENUM_TO_BOOL(ctx->Light.Model.ColorControl);
+ break;
+ case GL_LIGHT_MODEL_LOCAL_VIEWER:
+ *params = ctx->Light.Model.LocalViewer;
+ break;
+ case GL_LIGHT_MODEL_TWO_SIDE:
+ *params = ctx->Light.Model.TwoSide;
+ break;
+ case GL_LINE_SMOOTH:
+ *params = ctx->Line.SmoothFlag;
+ break;
+ case GL_LINE_SMOOTH_HINT:
+ *params = ENUM_TO_BOOL(ctx->Hint.LineSmooth);
+ break;
+ case GL_LINE_STIPPLE:
+ *params = ctx->Line.StippleFlag;
+ break;
+ case GL_LINE_STIPPLE_PATTERN:
+ *params = INT_TO_BOOL(ctx->Line.StipplePattern);
+ break;
+ case GL_LINE_STIPPLE_REPEAT:
+ *params = INT_TO_BOOL(ctx->Line.StippleFactor);
+ break;
+ case GL_LINE_WIDTH:
+ *params = FLOAT_TO_BOOL(ctx->Line.Width);
+ break;
+ case GL_LINE_WIDTH_GRANULARITY:
+ *params = FLOAT_TO_BOOL(LINE_WIDTH_GRANULARITY);
+ break;
+ case GL_LINE_WIDTH_RANGE:
+ params[0] = FLOAT_TO_BOOL(MIN_LINE_WIDTH);
+ params[1] = FLOAT_TO_BOOL(MAX_LINE_WIDTH);
+ break;
+ case GL_LIST_BASE:
+ *params = INT_TO_BOOL(ctx->List.ListBase);
+ break;
+ case GL_LIST_INDEX:
+ *params = INT_TO_BOOL( ctx->CurrentListNum );
+ break;
+ case GL_LIST_MODE:
+ *params = ENUM_TO_BOOL( ctx->ExecuteFlag
+ ? GL_COMPILE_AND_EXECUTE : GL_COMPILE );
+ break;
+ case GL_INDEX_LOGIC_OP:
+ *params = ctx->Color.IndexLogicOpEnabled;
+ break;
+ case GL_COLOR_LOGIC_OP:
+ *params = ctx->Color.ColorLogicOpEnabled;
+ break;
+ case GL_LOGIC_OP_MODE:
+ *params = ENUM_TO_BOOL(ctx->Color.LogicOp);
+ break;
+ case GL_MAP1_COLOR_4:
+ *params = ctx->Eval.Map1Color4;
+ break;
+ case GL_MAP1_GRID_DOMAIN:
+ params[0] = FLOAT_TO_BOOL(ctx->Eval.MapGrid1u1);
+ params[1] = FLOAT_TO_BOOL(ctx->Eval.MapGrid1u2);
+ break;
+ case GL_MAP1_GRID_SEGMENTS:
+ *params = INT_TO_BOOL(ctx->Eval.MapGrid1un);
+ break;
+ case GL_MAP1_INDEX:
+ *params = ctx->Eval.Map1Index;
+ break;
+ case GL_MAP1_NORMAL:
+ *params = ctx->Eval.Map1Normal;
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ *params = ctx->Eval.Map1TextureCoord1;
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ *params = ctx->Eval.Map1TextureCoord2;
+ break;
+ case GL_MAP1_TEXTURE_COORD_3:
+ *params = ctx->Eval.Map1TextureCoord3;
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ *params = ctx->Eval.Map1TextureCoord4;
+ break;
+ case GL_MAP1_VERTEX_3:
+ *params = ctx->Eval.Map1Vertex3;
+ break;
+ case GL_MAP1_VERTEX_4:
+ *params = ctx->Eval.Map1Vertex4;
+ break;
+ case GL_MAP2_COLOR_4:
+ *params = ctx->Eval.Map2Color4;
+ break;
+ case GL_MAP2_GRID_DOMAIN:
+ params[0] = FLOAT_TO_BOOL(ctx->Eval.MapGrid2u1);
+ params[1] = FLOAT_TO_BOOL(ctx->Eval.MapGrid2u2);
+ params[2] = FLOAT_TO_BOOL(ctx->Eval.MapGrid2v1);
+ params[3] = FLOAT_TO_BOOL(ctx->Eval.MapGrid2v2);
+ break;
+ case GL_MAP2_GRID_SEGMENTS:
+ params[0] = INT_TO_BOOL(ctx->Eval.MapGrid2un);
+ params[1] = INT_TO_BOOL(ctx->Eval.MapGrid2vn);
+ break;
+ case GL_MAP2_INDEX:
+ *params = ctx->Eval.Map2Index;
+ break;
+ case GL_MAP2_NORMAL:
+ *params = ctx->Eval.Map2Normal;
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ *params = ctx->Eval.Map2TextureCoord1;
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ *params = ctx->Eval.Map2TextureCoord2;
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ *params = ctx->Eval.Map2TextureCoord3;
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ *params = ctx->Eval.Map2TextureCoord4;
+ break;
+ case GL_MAP2_VERTEX_3:
+ *params = ctx->Eval.Map2Vertex3;
+ break;
+ case GL_MAP2_VERTEX_4:
+ *params = ctx->Eval.Map2Vertex4;
+ break;
+ case GL_MAP_COLOR:
+ *params = ctx->Pixel.MapColorFlag;
+ break;
+ case GL_MAP_STENCIL:
+ *params = ctx->Pixel.MapStencilFlag;
+ break;
+ case GL_MATRIX_MODE:
+ *params = ENUM_TO_BOOL( ctx->Transform.MatrixMode );
+ break;
+ case GL_MAX_ATTRIB_STACK_DEPTH:
+ *params = INT_TO_BOOL(MAX_ATTRIB_STACK_DEPTH);
+ break;
+ case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH:
+ *params = INT_TO_BOOL( MAX_CLIENT_ATTRIB_STACK_DEPTH);
+ break;
+ case GL_MAX_CLIP_PLANES:
+ *params = INT_TO_BOOL(MAX_CLIP_PLANES);
+ break;
+ case GL_MAX_ELEMENTS_VERTICES: /* GL_VERSION_1_2 */
+ *params = INT_TO_BOOL(VB_MAX);
+ break;
+ case GL_MAX_ELEMENTS_INDICES: /* GL_VERSION_1_2 */
+ *params = INT_TO_BOOL(VB_MAX);
+ break;
+ case GL_MAX_EVAL_ORDER:
+ *params = INT_TO_BOOL(MAX_EVAL_ORDER);
+ break;
+ case GL_MAX_LIGHTS:
+ *params = INT_TO_BOOL(MAX_LIGHTS);
+ break;
+ case GL_MAX_LIST_NESTING:
+ *params = INT_TO_BOOL(MAX_LIST_NESTING);
+ break;
+ case GL_MAX_MODELVIEW_STACK_DEPTH:
+ *params = INT_TO_BOOL(MAX_MODELVIEW_STACK_DEPTH);
+ break;
+ case GL_MAX_NAME_STACK_DEPTH:
+ *params = INT_TO_BOOL(MAX_NAME_STACK_DEPTH);
+ break;
+ case GL_MAX_PIXEL_MAP_TABLE:
+ *params = INT_TO_BOOL(MAX_PIXEL_MAP_TABLE);
+ break;
+ case GL_MAX_PROJECTION_STACK_DEPTH:
+ *params = INT_TO_BOOL(MAX_PROJECTION_STACK_DEPTH);
+ break;
+ case GL_MAX_TEXTURE_SIZE:
+ case GL_MAX_3D_TEXTURE_SIZE:
+ *params = INT_TO_BOOL(ctx->Const.MaxTextureSize);
+ break;
+ case GL_MAX_TEXTURE_STACK_DEPTH:
+ *params = INT_TO_BOOL(MAX_TEXTURE_STACK_DEPTH);
+ break;
+ case GL_MAX_VIEWPORT_DIMS:
+ params[0] = INT_TO_BOOL(MAX_WIDTH);
+ params[1] = INT_TO_BOOL(MAX_HEIGHT);
+ break;
+ case GL_MODELVIEW_MATRIX:
+ for (i=0;i<16;i++) {
+ params[i] = FLOAT_TO_BOOL(ctx->ModelView.m[i]);
+ }
+ break;
+ case GL_MODELVIEW_STACK_DEPTH:
+ *params = INT_TO_BOOL(ctx->ModelViewStackDepth + 1);
+ break;
+ case GL_NAME_STACK_DEPTH:
+ *params = INT_TO_BOOL(ctx->Select.NameStackDepth);
+ break;
+ case GL_NORMALIZE:
+ *params = ctx->Transform.Normalize;
+ break;
+ case GL_PACK_ALIGNMENT:
+ *params = INT_TO_BOOL(ctx->Pack.Alignment);
+ break;
+ case GL_PACK_LSB_FIRST:
+ *params = ctx->Pack.LsbFirst;
+ break;
+ case GL_PACK_ROW_LENGTH:
+ *params = INT_TO_BOOL(ctx->Pack.RowLength);
+ break;
+ case GL_PACK_SKIP_PIXELS:
+ *params = INT_TO_BOOL(ctx->Pack.SkipPixels);
+ break;
+ case GL_PACK_SKIP_ROWS:
+ *params = INT_TO_BOOL(ctx->Pack.SkipRows);
+ break;
+ case GL_PACK_SWAP_BYTES:
+ *params = ctx->Pack.SwapBytes;
+ break;
+ case GL_PACK_SKIP_IMAGES_EXT:
+ *params = ctx->Pack.SkipImages;
+ break;
+ case GL_PACK_IMAGE_HEIGHT_EXT:
+ *params = ctx->Pack.ImageHeight;
+ break;
+ case GL_PERSPECTIVE_CORRECTION_HINT:
+ *params = ENUM_TO_BOOL(ctx->Hint.PerspectiveCorrection);
+ break;
+ case GL_PIXEL_MAP_A_TO_A_SIZE:
+ *params = INT_TO_BOOL(ctx->Pixel.MapAtoAsize);
+ break;
+ case GL_PIXEL_MAP_B_TO_B_SIZE:
+ *params = INT_TO_BOOL(ctx->Pixel.MapBtoBsize);
+ break;
+ case GL_PIXEL_MAP_G_TO_G_SIZE:
+ *params = INT_TO_BOOL(ctx->Pixel.MapGtoGsize);
+ break;
+ case GL_PIXEL_MAP_I_TO_A_SIZE:
+ *params = INT_TO_BOOL(ctx->Pixel.MapItoAsize);
+ break;
+ case GL_PIXEL_MAP_I_TO_B_SIZE:
+ *params = INT_TO_BOOL(ctx->Pixel.MapItoBsize);
+ break;
+ case GL_PIXEL_MAP_I_TO_G_SIZE:
+ *params = INT_TO_BOOL(ctx->Pixel.MapItoGsize);
+ break;
+ case GL_PIXEL_MAP_I_TO_I_SIZE:
+ *params = INT_TO_BOOL(ctx->Pixel.MapItoIsize);
+ break;
+ case GL_PIXEL_MAP_I_TO_R_SIZE:
+ *params = INT_TO_BOOL(ctx->Pixel.MapItoRsize);
+ break;
+ case GL_PIXEL_MAP_R_TO_R_SIZE:
+ *params = INT_TO_BOOL(ctx->Pixel.MapRtoRsize);
+ break;
+ case GL_PIXEL_MAP_S_TO_S_SIZE:
+ *params = INT_TO_BOOL(ctx->Pixel.MapStoSsize);
+ break;
+ case GL_POINT_SIZE:
+ *params = FLOAT_TO_BOOL(ctx->Point.Size );
+ break;
+ case GL_POINT_SIZE_GRANULARITY:
+ *params = FLOAT_TO_BOOL(POINT_SIZE_GRANULARITY );
+ break;
+ case GL_POINT_SIZE_RANGE:
+ params[0] = FLOAT_TO_BOOL(MIN_POINT_SIZE );
+ params[1] = FLOAT_TO_BOOL(MAX_POINT_SIZE );
+ break;
+ case GL_POINT_SMOOTH:
+ *params = ctx->Point.SmoothFlag;
+ break;
+ case GL_POINT_SMOOTH_HINT:
+ *params = ENUM_TO_BOOL(ctx->Hint.PointSmooth);
+ break;
+ case GL_POINT_SIZE_MIN_EXT:
+ *params = FLOAT_TO_BOOL(ctx->Point.MinSize);
+ break;
+ case GL_POINT_SIZE_MAX_EXT:
+ *params = FLOAT_TO_BOOL(ctx->Point.MaxSize);
+ break;
+ case GL_POINT_FADE_THRESHOLD_SIZE_EXT:
+ *params = FLOAT_TO_BOOL(ctx->Point.Threshold);
+ break;
+ case GL_DISTANCE_ATTENUATION_EXT:
+ params[0] = FLOAT_TO_BOOL(ctx->Point.Params[0]);
+ params[1] = FLOAT_TO_BOOL(ctx->Point.Params[1]);
+ params[2] = FLOAT_TO_BOOL(ctx->Point.Params[2]);
+ break;
+ case GL_POLYGON_MODE:
+ params[0] = ENUM_TO_BOOL(ctx->Polygon.FrontMode);
+ params[1] = ENUM_TO_BOOL(ctx->Polygon.BackMode);
+ break;
+#ifdef GL_EXT_polygon_offset
+ case GL_POLYGON_OFFSET_BIAS_EXT:
+ *params = FLOAT_TO_BOOL( ctx->Polygon.OffsetUnits );
+ break;
+#endif
+ case GL_POLYGON_OFFSET_FACTOR:
+ *params = FLOAT_TO_BOOL( ctx->Polygon.OffsetFactor );
+ break;
+ case GL_POLYGON_OFFSET_UNITS:
+ *params = FLOAT_TO_BOOL( ctx->Polygon.OffsetUnits );
+ break;
+ case GL_POLYGON_SMOOTH:
+ *params = ctx->Polygon.SmoothFlag;
+ break;
+ case GL_POLYGON_SMOOTH_HINT:
+ *params = ENUM_TO_BOOL(ctx->Hint.PolygonSmooth);
+ break;
+ case GL_POLYGON_STIPPLE:
+ *params = ctx->Polygon.StippleFlag;
+ break;
+ case GL_PROJECTION_MATRIX:
+ for (i=0;i<16;i++) {
+ params[i] = FLOAT_TO_BOOL(ctx->ProjectionMatrix.m[i]);
+ }
+ break;
+ case GL_PROJECTION_STACK_DEPTH:
+ *params = INT_TO_BOOL(ctx->ProjectionStackDepth + 1);
+ break;
+ case GL_READ_BUFFER:
+ *params = ENUM_TO_BOOL(ctx->Pixel.ReadBuffer);
+ break;
+ case GL_RED_BIAS:
+ *params = FLOAT_TO_BOOL(ctx->Pixel.RedBias);
+ break;
+ case GL_RED_BITS:
+ *params = INT_TO_BOOL( ctx->Visual->RedBits );
+ break;
+ case GL_RED_SCALE:
+ *params = FLOAT_TO_BOOL(ctx->Pixel.RedScale);
+ break;
+ case GL_RENDER_MODE:
+ *params = ENUM_TO_BOOL(ctx->RenderMode);
+ break;
+ case GL_RGBA_MODE:
+ *params = ctx->Visual->RGBAflag;
+ break;
+ case GL_SCISSOR_BOX:
+ params[0] = INT_TO_BOOL(ctx->Scissor.X);
+ params[1] = INT_TO_BOOL(ctx->Scissor.Y);
+ params[2] = INT_TO_BOOL(ctx->Scissor.Width);
+ params[3] = INT_TO_BOOL(ctx->Scissor.Height);
+ break;
+ case GL_SCISSOR_TEST:
+ *params = ctx->Scissor.Enabled;
+ break;
+ case GL_SELECTION_BUFFER_SIZE:
+ *params = INT_TO_BOOL(ctx->Select.BufferSize);
+ break;
+ case GL_SHADE_MODEL:
+ *params = ENUM_TO_BOOL(ctx->Light.ShadeModel);
+ break;
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ *params = ctx->Texture.SharedPalette;
+ break;
+ case GL_STENCIL_BITS:
+ *params = INT_TO_BOOL(ctx->Visual->StencilBits);
+ break;
+ case GL_STENCIL_CLEAR_VALUE:
+ *params = INT_TO_BOOL(ctx->Stencil.Clear);
+ break;
+ case GL_STENCIL_FAIL:
+ *params = ENUM_TO_BOOL(ctx->Stencil.FailFunc);
+ break;
+ case GL_STENCIL_FUNC:
+ *params = ENUM_TO_BOOL(ctx->Stencil.Function);
+ break;
+ case GL_STENCIL_PASS_DEPTH_FAIL:
+ *params = ENUM_TO_BOOL(ctx->Stencil.ZFailFunc);
+ break;
+ case GL_STENCIL_PASS_DEPTH_PASS:
+ *params = ENUM_TO_BOOL(ctx->Stencil.ZPassFunc);
+ break;
+ case GL_STENCIL_REF:
+ *params = INT_TO_BOOL(ctx->Stencil.Ref);
+ break;
+ case GL_STENCIL_TEST:
+ *params = ctx->Stencil.Enabled;
+ break;
+ case GL_STENCIL_VALUE_MASK:
+ *params = INT_TO_BOOL(ctx->Stencil.ValueMask);
+ break;
+ case GL_STENCIL_WRITEMASK:
+ *params = INT_TO_BOOL(ctx->Stencil.WriteMask);
+ break;
+ case GL_STEREO:
+ *params = ctx->Visual->StereoFlag;
+ break;
+ case GL_SUBPIXEL_BITS:
+ *params = INT_TO_BOOL(0); /* TODO */
+ break;
+ case GL_TEXTURE_1D:
+ *params = gl_IsEnabled( ctx, GL_TEXTURE_1D );
+ break;
+ case GL_TEXTURE_2D:
+ *params = gl_IsEnabled( ctx, GL_TEXTURE_2D );
+ break;
+ case GL_TEXTURE_3D:
+ *params = gl_IsEnabled( ctx, GL_TEXTURE_3D );
+ break;
+ case GL_TEXTURE_BINDING_1D:
+ *params = INT_TO_BOOL(textureUnit->CurrentD[1]->Name);
+ break;
+ case GL_TEXTURE_BINDING_2D:
+ *params = INT_TO_BOOL(textureUnit->CurrentD[2]->Name);
+ break;
+ case GL_TEXTURE_BINDING_3D:
+ *params = INT_TO_BOOL(textureUnit->CurrentD[3]->Name);
+ break;
+ case GL_TEXTURE_ENV_COLOR:
+ {
+ params[0] = FLOAT_TO_BOOL(textureUnit->EnvColor[0]);
+ params[1] = FLOAT_TO_BOOL(textureUnit->EnvColor[1]);
+ params[2] = FLOAT_TO_BOOL(textureUnit->EnvColor[2]);
+ params[3] = FLOAT_TO_BOOL(textureUnit->EnvColor[3]);
+ }
+ break;
+ case GL_TEXTURE_ENV_MODE:
+ *params = ENUM_TO_BOOL(textureUnit->EnvMode);
+ break;
+ case GL_TEXTURE_GEN_S:
+ *params = (textureUnit->TexGenEnabled & S_BIT) ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_TEXTURE_GEN_T:
+ *params = (textureUnit->TexGenEnabled & T_BIT) ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_TEXTURE_GEN_R:
+ *params = (textureUnit->TexGenEnabled & R_BIT) ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_TEXTURE_GEN_Q:
+ *params = (textureUnit->TexGenEnabled & Q_BIT) ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_TEXTURE_MATRIX:
+ for (i=0;i<16;i++) {
+ params[i] =
+ FLOAT_TO_BOOL(ctx->TextureMatrix[texTransformUnit].m[i]);
+ }
+ break;
+ case GL_TEXTURE_STACK_DEPTH:
+ *params = INT_TO_BOOL(ctx->TextureStackDepth[texTransformUnit] + 1);
+ break;
+ case GL_UNPACK_ALIGNMENT:
+ *params = INT_TO_BOOL(ctx->Unpack.Alignment);
+ break;
+ case GL_UNPACK_LSB_FIRST:
+ *params = ctx->Unpack.LsbFirst;
+ break;
+ case GL_UNPACK_ROW_LENGTH:
+ *params = INT_TO_BOOL(ctx->Unpack.RowLength);
+ break;
+ case GL_UNPACK_SKIP_PIXELS:
+ *params = INT_TO_BOOL(ctx->Unpack.SkipPixels);
+ break;
+ case GL_UNPACK_SKIP_ROWS:
+ *params = INT_TO_BOOL(ctx->Unpack.SkipRows);
+ break;
+ case GL_UNPACK_SWAP_BYTES:
+ *params = ctx->Unpack.SwapBytes;
+ break;
+ case GL_UNPACK_SKIP_IMAGES_EXT:
+ *params = ctx->Unpack.SkipImages;
+ break;
+ case GL_UNPACK_IMAGE_HEIGHT_EXT:
+ *params = ctx->Unpack.ImageHeight;
+ break;
+ case GL_VIEWPORT:
+ params[0] = INT_TO_BOOL(ctx->Viewport.X);
+ params[1] = INT_TO_BOOL(ctx->Viewport.Y);
+ params[2] = INT_TO_BOOL(ctx->Viewport.Width);
+ params[3] = INT_TO_BOOL(ctx->Viewport.Height);
+ break;
+ case GL_ZOOM_X:
+ *params = FLOAT_TO_BOOL(ctx->Pixel.ZoomX);
+ break;
+ case GL_ZOOM_Y:
+ *params = FLOAT_TO_BOOL(ctx->Pixel.ZoomY);
+ break;
+ case GL_VERTEX_ARRAY_SIZE:
+ *params = INT_TO_BOOL(ctx->Array.Vertex.Size);
+ break;
+ case GL_VERTEX_ARRAY_TYPE:
+ *params = ENUM_TO_BOOL(ctx->Array.Vertex.Type);
+ break;
+ case GL_VERTEX_ARRAY_STRIDE:
+ *params = INT_TO_BOOL(ctx->Array.Vertex.Stride);
+ break;
+ case GL_VERTEX_ARRAY_COUNT_EXT:
+ *params = INT_TO_BOOL(0);
+ break;
+ case GL_NORMAL_ARRAY_TYPE:
+ *params = ENUM_TO_BOOL(ctx->Array.Normal.Type);
+ break;
+ case GL_NORMAL_ARRAY_STRIDE:
+ *params = INT_TO_BOOL(ctx->Array.Normal.Stride);
+ break;
+ case GL_NORMAL_ARRAY_COUNT_EXT:
+ *params = INT_TO_BOOL(0);
+ break;
+ case GL_COLOR_ARRAY_SIZE:
+ *params = INT_TO_BOOL(ctx->Array.Color.Size);
+ break;
+ case GL_COLOR_ARRAY_TYPE:
+ *params = ENUM_TO_BOOL(ctx->Array.Color.Type);
+ break;
+ case GL_COLOR_ARRAY_STRIDE:
+ *params = INT_TO_BOOL(ctx->Array.Color.Stride);
+ break;
+ case GL_COLOR_ARRAY_COUNT_EXT:
+ *params = INT_TO_BOOL(0);
+ break;
+ case GL_INDEX_ARRAY_TYPE:
+ *params = ENUM_TO_BOOL(ctx->Array.Index.Type);
+ break;
+ case GL_INDEX_ARRAY_STRIDE:
+ *params = INT_TO_BOOL(ctx->Array.Index.Stride);
+ break;
+ case GL_INDEX_ARRAY_COUNT_EXT:
+ *params = INT_TO_BOOL(0);
+ break;
+ case GL_TEXTURE_COORD_ARRAY_SIZE:
+ *params = INT_TO_BOOL(ctx->Array.TexCoord[texUnit].Size);
+ break;
+ case GL_TEXTURE_COORD_ARRAY_TYPE:
+ *params = ENUM_TO_BOOL(ctx->Array.TexCoord[texUnit].Type);
+ break;
+ case GL_TEXTURE_COORD_ARRAY_STRIDE:
+ *params = INT_TO_BOOL(ctx->Array.TexCoord[texUnit].Stride);
+ break;
+ case GL_TEXTURE_COORD_ARRAY_COUNT_EXT:
+ *params = INT_TO_BOOL(0);
+ break;
+ case GL_EDGE_FLAG_ARRAY_STRIDE:
+ *params = INT_TO_BOOL(ctx->Array.EdgeFlag.Stride);
+ break;
+ case GL_EDGE_FLAG_ARRAY_EXT:
+ *params = INT_TO_BOOL(0);
+ break;
+
+ case GL_MAX_TEXTURE_UNITS_ARB:
+ *params = ctx->Const.MaxTextureUnits;
+ break;
+ case GL_ACTIVE_TEXTURE_ARB:
+ *params = INT_TO_BOOL(GL_TEXTURE0_ARB + ctx->Texture.CurrentUnit);
+ break;
+ case GL_CLIENT_ACTIVE_TEXTURE_ARB:
+ *params = INT_TO_BOOL(GL_TEXTURE0_ARB + ctx->Array.ActiveTexture);
+ break;
+
+
+ /* GL_PGI_misc_hints */
+ case GL_STRICT_DEPTHFUNC_HINT_PGI:
+ *params = ENUM_TO_BOOL(GL_NICEST);
+ break;
+ case GL_STRICT_LIGHTING_HINT_PGI:
+ *params = ENUM_TO_BOOL(ctx->Hint.StrictLighting);
+ break;
+ case GL_STRICT_SCISSOR_HINT_PGI:
+ case GL_FULL_STIPPLE_HINT_PGI:
+ *params = ENUM_TO_BOOL(GL_TRUE);
+ break;
+ case GL_CONSERVE_MEMORY_HINT_PGI:
+ *params = ENUM_TO_BOOL(GL_FALSE);
+ break;
+ case GL_ALWAYS_FAST_HINT_PGI:
+ *params = (GLboolean) (ctx->Hint.AllowDrawWin == GL_TRUE &&
+ ctx->Hint.AllowDrawSpn == GL_FALSE &&
+ ctx->Hint.AllowDrawMem == GL_FALSE);
+ break;
+ case GL_ALWAYS_SOFT_HINT_PGI:
+ *params = (GLboolean) (ctx->Hint.AllowDrawWin == GL_TRUE &&
+ ctx->Hint.AllowDrawSpn == GL_TRUE &&
+ ctx->Hint.AllowDrawMem == GL_TRUE);
+ break;
+ case GL_ALLOW_DRAW_OBJ_HINT_PGI:
+ *params = (GLboolean) GL_TRUE;
+ break;
+ case GL_ALLOW_DRAW_WIN_HINT_PGI:
+ *params = (GLboolean) ctx->Hint.AllowDrawWin;
+ break;
+ case GL_ALLOW_DRAW_SPN_HINT_PGI:
+ *params = (GLboolean) ctx->Hint.AllowDrawSpn;
+ break;
+ case GL_ALLOW_DRAW_MEM_HINT_PGI:
+ *params = (GLboolean) ctx->Hint.AllowDrawMem;
+ break;
+ case GL_CLIP_NEAR_HINT_PGI:
+ case GL_CLIP_FAR_HINT_PGI:
+ *params = ENUM_TO_BOOL(GL_TRUE);
+ break;
+ case GL_WIDE_LINE_HINT_PGI:
+ *params = ENUM_TO_BOOL(GL_DONT_CARE);
+ break;
+ case GL_BACK_NORMALS_HINT_PGI:
+ *params = ENUM_TO_BOOL(GL_TRUE);
+ break;
+ case GL_NATIVE_GRAPHICS_HANDLE_PGI:
+ *params = 0;
+ break;
+ default:
+ printf("invalid enum: %x\n", pname);
+ gl_error( ctx, GL_INVALID_ENUM, "glGetBooleanv" );
+ }
+}
+
+
+
+
+void gl_GetDoublev( GLcontext *ctx, GLenum pname, GLdouble *params )
+{
+ GLuint i;
+ GLuint texUnit = ctx->Texture.CurrentUnit;
+ GLuint texTransformUnit = ctx->Texture.CurrentTransformUnit;
+ const struct gl_texture_unit *textureUnit = &ctx->Texture.Unit[texUnit];
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetDoublev");
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ fprintf(stderr, "glGetDoublev %s\n", gl_lookup_enum_by_nr(pname));
+
+ switch (pname) {
+ case GL_ACCUM_RED_BITS:
+ case GL_ACCUM_GREEN_BITS:
+ case GL_ACCUM_BLUE_BITS:
+ case GL_ACCUM_ALPHA_BITS:
+ *params = (GLdouble) ctx->Visual->AccumBits;
+ break;
+ case GL_ACCUM_CLEAR_VALUE:
+ params[0] = (GLdouble) ctx->Accum.ClearColor[0];
+ params[1] = (GLdouble) ctx->Accum.ClearColor[1];
+ params[2] = (GLdouble) ctx->Accum.ClearColor[2];
+ params[3] = (GLdouble) ctx->Accum.ClearColor[3];
+ break;
+ case GL_ALPHA_BIAS:
+ *params = (GLdouble) ctx->Pixel.AlphaBias;
+ break;
+ case GL_ALPHA_BITS:
+ *params = (GLdouble) ctx->Visual->AlphaBits;
+ break;
+ case GL_ALPHA_SCALE:
+ *params = (GLdouble) ctx->Pixel.AlphaScale;
+ break;
+ case GL_ALPHA_TEST:
+ *params = (GLdouble) ctx->Color.AlphaEnabled;
+ break;
+ case GL_ALPHA_TEST_FUNC:
+ *params = ENUM_TO_DOUBLE(ctx->Color.AlphaFunc);
+ break;
+ case GL_ALPHA_TEST_REF:
+ *params = (GLdouble) ctx->Color.AlphaRef / 255.0;
+ break;
+ case GL_ATTRIB_STACK_DEPTH:
+ *params = (GLdouble ) (ctx->AttribStackDepth);
+ break;
+ case GL_AUTO_NORMAL:
+ *params = (GLdouble) ctx->Eval.AutoNormal;
+ break;
+ case GL_AUX_BUFFERS:
+ *params = (GLdouble) NUM_AUX_BUFFERS;
+ break;
+ case GL_BLEND:
+ *params = (GLdouble) ctx->Color.BlendEnabled;
+ break;
+ case GL_BLEND_DST:
+ *params = ENUM_TO_DOUBLE(ctx->Color.BlendDstRGB);
+ break;
+ case GL_BLEND_SRC:
+ *params = ENUM_TO_DOUBLE(ctx->Color.BlendSrcRGB);
+ break;
+ case GL_BLEND_SRC_RGB_INGR:
+ *params = ENUM_TO_DOUBLE(ctx->Color.BlendSrcRGB);
+ break;
+ case GL_BLEND_DST_RGB_INGR:
+ *params = ENUM_TO_DOUBLE(ctx->Color.BlendDstRGB);
+ break;
+ case GL_BLEND_SRC_ALPHA_INGR:
+ *params = ENUM_TO_DOUBLE(ctx->Color.BlendSrcA);
+ break;
+ case GL_BLEND_DST_ALPHA_INGR:
+ *params = ENUM_TO_DOUBLE(ctx->Color.BlendDstA);
+ break;
+ case GL_BLEND_EQUATION_EXT:
+ *params = ENUM_TO_DOUBLE(ctx->Color.BlendEquation);
+ break;
+ case GL_BLEND_COLOR_EXT:
+ params[0] = (GLdouble) ctx->Color.BlendColor[0];
+ params[1] = (GLdouble) ctx->Color.BlendColor[1];
+ params[2] = (GLdouble) ctx->Color.BlendColor[2];
+ params[3] = (GLdouble) ctx->Color.BlendColor[3];
+ break;
+ case GL_BLUE_BIAS:
+ *params = (GLdouble) ctx->Pixel.BlueBias;
+ break;
+ case GL_BLUE_BITS:
+ *params = (GLdouble) ctx->Visual->BlueBits;
+ break;
+ case GL_BLUE_SCALE:
+ *params = (GLdouble) ctx->Pixel.BlueScale;
+ break;
+ case GL_CLIENT_ATTRIB_STACK_DEPTH:
+ *params = (GLdouble) (ctx->ClientAttribStackDepth);
+ 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:
+ *params = (GLdouble) ctx->Transform.ClipEnabled[pname-GL_CLIP_PLANE0];
+ break;
+ case GL_COLOR_CLEAR_VALUE:
+ params[0] = (GLdouble) ctx->Color.ClearColor[0];
+ params[1] = (GLdouble) ctx->Color.ClearColor[1];
+ params[2] = (GLdouble) ctx->Color.ClearColor[2];
+ params[3] = (GLdouble) ctx->Color.ClearColor[3];
+ break;
+ case GL_COLOR_MATERIAL:
+ *params = (GLdouble) ctx->Light.ColorMaterialEnabled;
+ break;
+ case GL_COLOR_MATERIAL_FACE:
+ *params = ENUM_TO_DOUBLE(ctx->Light.ColorMaterialFace);
+ break;
+ case GL_COLOR_MATERIAL_PARAMETER:
+ *params = ENUM_TO_DOUBLE(ctx->Light.ColorMaterialMode);
+ break;
+ case GL_COLOR_WRITEMASK:
+ params[0] = ctx->Color.ColorMask[RCOMP] ? 1.0 : 0.0;
+ params[1] = ctx->Color.ColorMask[GCOMP] ? 1.0 : 0.0;
+ params[2] = ctx->Color.ColorMask[BCOMP] ? 1.0 : 0.0;
+ params[3] = ctx->Color.ColorMask[ACOMP] ? 1.0 : 0.0;
+ break;
+ case GL_CULL_FACE:
+ *params = (GLdouble) ctx->Polygon.CullFlag;
+ break;
+ case GL_CULL_FACE_MODE:
+ *params = ENUM_TO_DOUBLE(ctx->Polygon.CullFaceMode);
+ break;
+ case GL_CURRENT_COLOR:
+ params[0] = UBYTE_COLOR_TO_FLOAT_COLOR(ctx->Current.ByteColor[0]);
+ params[1] = UBYTE_COLOR_TO_FLOAT_COLOR(ctx->Current.ByteColor[1]);
+ params[2] = UBYTE_COLOR_TO_FLOAT_COLOR(ctx->Current.ByteColor[2]);
+ params[3] = UBYTE_COLOR_TO_FLOAT_COLOR(ctx->Current.ByteColor[3]);
+ break;
+ case GL_CURRENT_INDEX:
+ *params = (GLdouble) ctx->Current.Index;
+ break;
+ case GL_CURRENT_NORMAL:
+ params[0] = (GLdouble) ctx->Current.Normal[0];
+ params[1] = (GLdouble) ctx->Current.Normal[1];
+ params[2] = (GLdouble) ctx->Current.Normal[2];
+ break;
+ case GL_CURRENT_RASTER_COLOR:
+ params[0] = (GLdouble) ctx->Current.RasterColor[0];
+ params[1] = (GLdouble) ctx->Current.RasterColor[1];
+ params[2] = (GLdouble) ctx->Current.RasterColor[2];
+ params[3] = (GLdouble) ctx->Current.RasterColor[3];
+ break;
+ case GL_CURRENT_RASTER_DISTANCE:
+ params[0] = (GLdouble) ctx->Current.RasterDistance;
+ break;
+ case GL_CURRENT_RASTER_INDEX:
+ *params = (GLdouble) ctx->Current.RasterIndex;
+ break;
+ case GL_CURRENT_RASTER_POSITION:
+ params[0] = (GLdouble) ctx->Current.RasterPos[0];
+ params[1] = (GLdouble) ctx->Current.RasterPos[1];
+ params[2] = (GLdouble) ctx->Current.RasterPos[2];
+ params[3] = (GLdouble) ctx->Current.RasterPos[3];
+ break;
+ case GL_CURRENT_RASTER_TEXTURE_COORDS:
+ params[0] = (GLdouble) ctx->Current.RasterMultiTexCoord[texTransformUnit][0];
+ params[1] = (GLdouble) ctx->Current.RasterMultiTexCoord[texTransformUnit][1];
+ params[2] = (GLdouble) ctx->Current.RasterMultiTexCoord[texTransformUnit][2];
+ params[3] = (GLdouble) ctx->Current.RasterMultiTexCoord[texTransformUnit][3];
+ break;
+ case GL_CURRENT_RASTER_POSITION_VALID:
+ *params = (GLdouble) ctx->Current.RasterPosValid;
+ break;
+ case GL_CURRENT_TEXTURE_COORDS:
+ params[0] = (GLdouble) ctx->Current.Texcoord[texTransformUnit][0];
+ params[1] = (GLdouble) ctx->Current.Texcoord[texTransformUnit][1];
+ params[2] = (GLdouble) ctx->Current.Texcoord[texTransformUnit][2];
+ params[3] = (GLdouble) ctx->Current.Texcoord[texTransformUnit][3];
+ break;
+ case GL_DEPTH_BIAS:
+ *params = (GLdouble) ctx->Pixel.DepthBias;
+ break;
+ case GL_DEPTH_BITS:
+ *params = (GLdouble) ctx->Visual->DepthBits;
+ break;
+ case GL_DEPTH_CLEAR_VALUE:
+ *params = (GLdouble) ctx->Depth.Clear;
+ break;
+ case GL_DEPTH_FUNC:
+ *params = ENUM_TO_DOUBLE(ctx->Depth.Func);
+ break;
+ case GL_DEPTH_RANGE:
+ params[0] = (GLdouble) ctx->Viewport.Near;
+ params[1] = (GLdouble) ctx->Viewport.Far;
+ break;
+ case GL_DEPTH_SCALE:
+ *params = (GLdouble) ctx->Pixel.DepthScale;
+ break;
+ case GL_DEPTH_TEST:
+ *params = (GLdouble) ctx->Depth.Test;
+ break;
+ case GL_DEPTH_WRITEMASK:
+ *params = (GLdouble) ctx->Depth.Mask;
+ break;
+ case GL_DITHER:
+ *params = (GLdouble) ctx->Color.DitherFlag;
+ break;
+ case GL_DOUBLEBUFFER:
+ *params = (GLdouble) ctx->Visual->DBflag;
+ break;
+ case GL_DRAW_BUFFER:
+ *params = ENUM_TO_DOUBLE(ctx->Color.DrawBuffer);
+ break;
+ case GL_EDGE_FLAG:
+ *params = (GLdouble) ctx->Current.EdgeFlag;
+ break;
+ case GL_FEEDBACK_BUFFER_SIZE:
+ /* TODO: is this right? Or, return number of entries in buffer? */
+ *params = (GLdouble) ctx->Feedback.BufferSize;
+ break;
+ case GL_FEEDBACK_BUFFER_TYPE:
+ *params = ENUM_TO_DOUBLE(ctx->Feedback.Type);
+ break;
+ case GL_FOG:
+ *params = (GLdouble) ctx->Fog.Enabled;
+ break;
+ case GL_FOG_COLOR:
+ params[0] = (GLdouble) ctx->Fog.Color[0];
+ params[1] = (GLdouble) ctx->Fog.Color[1];
+ params[2] = (GLdouble) ctx->Fog.Color[2];
+ params[3] = (GLdouble) ctx->Fog.Color[3];
+ break;
+ case GL_FOG_DENSITY:
+ *params = (GLdouble) ctx->Fog.Density;
+ break;
+ case GL_FOG_END:
+ *params = (GLdouble) ctx->Fog.End;
+ break;
+ case GL_FOG_HINT:
+ *params = ENUM_TO_DOUBLE(ctx->Hint.Fog);
+ break;
+ case GL_FOG_INDEX:
+ *params = (GLdouble) ctx->Fog.Index;
+ break;
+ case GL_FOG_MODE:
+ *params = ENUM_TO_DOUBLE(ctx->Fog.Mode);
+ break;
+ case GL_FOG_START:
+ *params = (GLdouble) ctx->Fog.Start;
+ break;
+ case GL_FRONT_FACE:
+ *params = ENUM_TO_DOUBLE(ctx->Polygon.FrontFace);
+ break;
+ case GL_GREEN_BIAS:
+ *params = (GLdouble) ctx->Pixel.GreenBias;
+ break;
+ case GL_GREEN_BITS:
+ *params = (GLdouble) ctx->Visual->GreenBits;
+ break;
+ case GL_GREEN_SCALE:
+ *params = (GLdouble) ctx->Pixel.GreenScale;
+ break;
+ case GL_INDEX_BITS:
+ *params = (GLdouble) ctx->Visual->IndexBits;
+ break;
+ case GL_INDEX_CLEAR_VALUE:
+ *params = (GLdouble) ctx->Color.ClearIndex;
+ break;
+ case GL_INDEX_MODE:
+ *params = ctx->Visual->RGBAflag ? 0.0 : 1.0;
+ break;
+ case GL_INDEX_OFFSET:
+ *params = (GLdouble) ctx->Pixel.IndexOffset;
+ break;
+ case GL_INDEX_SHIFT:
+ *params = (GLdouble) ctx->Pixel.IndexShift;
+ break;
+ case GL_INDEX_WRITEMASK:
+ *params = (GLdouble) ctx->Color.IndexMask;
+ 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:
+ *params = (GLdouble) ctx->Light.Light[pname-GL_LIGHT0].Enabled;
+ break;
+ case GL_LIGHTING:
+ *params = (GLdouble) ctx->Light.Enabled;
+ break;
+ case GL_LIGHT_MODEL_AMBIENT:
+ params[0] = (GLdouble) ctx->Light.Model.Ambient[0];
+ params[1] = (GLdouble) ctx->Light.Model.Ambient[1];
+ params[2] = (GLdouble) ctx->Light.Model.Ambient[2];
+ params[3] = (GLdouble) ctx->Light.Model.Ambient[3];
+ break;
+ case GL_LIGHT_MODEL_COLOR_CONTROL:
+ params[0] = (GLdouble) ctx->Light.Model.ColorControl;
+ break;
+ case GL_LIGHT_MODEL_LOCAL_VIEWER:
+ *params = (GLdouble) ctx->Light.Model.LocalViewer;
+ break;
+ case GL_LIGHT_MODEL_TWO_SIDE:
+ *params = (GLdouble) ctx->Light.Model.TwoSide;
+ break;
+ case GL_LINE_SMOOTH:
+ *params = (GLdouble) ctx->Line.SmoothFlag;
+ break;
+ case GL_LINE_SMOOTH_HINT:
+ *params = ENUM_TO_DOUBLE(ctx->Hint.LineSmooth);
+ break;
+ case GL_LINE_STIPPLE:
+ *params = (GLdouble) ctx->Line.StippleFlag;
+ break;
+ case GL_LINE_STIPPLE_PATTERN:
+ *params = (GLdouble) ctx->Line.StipplePattern;
+ break;
+ case GL_LINE_STIPPLE_REPEAT:
+ *params = (GLdouble) ctx->Line.StippleFactor;
+ break;
+ case GL_LINE_WIDTH:
+ *params = (GLdouble) ctx->Line.Width;
+ break;
+ case GL_LINE_WIDTH_GRANULARITY:
+ *params = (GLdouble) LINE_WIDTH_GRANULARITY;
+ break;
+ case GL_LINE_WIDTH_RANGE:
+ params[0] = (GLdouble) MIN_LINE_WIDTH;
+ params[1] = (GLdouble) MAX_LINE_WIDTH;
+ break;
+ case GL_LIST_BASE:
+ *params = (GLdouble) ctx->List.ListBase;
+ break;
+ case GL_LIST_INDEX:
+ *params = (GLdouble) ctx->CurrentListNum;
+ break;
+ case GL_LIST_MODE:
+ *params = ctx->ExecuteFlag ? ENUM_TO_DOUBLE(GL_COMPILE_AND_EXECUTE)
+ : ENUM_TO_DOUBLE(GL_COMPILE);
+ break;
+ case GL_INDEX_LOGIC_OP:
+ *params = (GLdouble) ctx->Color.IndexLogicOpEnabled;
+ break;
+ case GL_COLOR_LOGIC_OP:
+ *params = (GLdouble) ctx->Color.ColorLogicOpEnabled;
+ break;
+ case GL_LOGIC_OP_MODE:
+ *params = ENUM_TO_DOUBLE(ctx->Color.LogicOp);
+ break;
+ case GL_MAP1_COLOR_4:
+ *params = (GLdouble) ctx->Eval.Map1Color4;
+ break;
+ case GL_MAP1_GRID_DOMAIN:
+ params[0] = (GLdouble) ctx->Eval.MapGrid1u1;
+ params[1] = (GLdouble) ctx->Eval.MapGrid1u2;
+ break;
+ case GL_MAP1_GRID_SEGMENTS:
+ *params = (GLdouble) ctx->Eval.MapGrid1un;
+ break;
+ case GL_MAP1_INDEX:
+ *params = (GLdouble) ctx->Eval.Map1Index;
+ break;
+ case GL_MAP1_NORMAL:
+ *params = (GLdouble) ctx->Eval.Map1Normal;
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ *params = (GLdouble) ctx->Eval.Map1TextureCoord1;
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ *params = (GLdouble) ctx->Eval.Map1TextureCoord2;
+ break;
+ case GL_MAP1_TEXTURE_COORD_3:
+ *params = (GLdouble) ctx->Eval.Map1TextureCoord3;
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ *params = (GLdouble) ctx->Eval.Map1TextureCoord4;
+ break;
+ case GL_MAP1_VERTEX_3:
+ *params = (GLdouble) ctx->Eval.Map1Vertex3;
+ break;
+ case GL_MAP1_VERTEX_4:
+ *params = (GLdouble) ctx->Eval.Map1Vertex4;
+ break;
+ case GL_MAP2_COLOR_4:
+ *params = (GLdouble) ctx->Eval.Map2Color4;
+ break;
+ case GL_MAP2_GRID_DOMAIN:
+ params[0] = (GLdouble) ctx->Eval.MapGrid2u1;
+ params[1] = (GLdouble) ctx->Eval.MapGrid2u2;
+ params[2] = (GLdouble) ctx->Eval.MapGrid2v1;
+ params[3] = (GLdouble) ctx->Eval.MapGrid2v2;
+ break;
+ case GL_MAP2_GRID_SEGMENTS:
+ params[0] = (GLdouble) ctx->Eval.MapGrid2un;
+ params[1] = (GLdouble) ctx->Eval.MapGrid2vn;
+ break;
+ case GL_MAP2_INDEX:
+ *params = (GLdouble) ctx->Eval.Map2Index;
+ break;
+ case GL_MAP2_NORMAL:
+ *params = (GLdouble) ctx->Eval.Map2Normal;
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ *params = (GLdouble) ctx->Eval.Map2TextureCoord1;
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ *params = (GLdouble) ctx->Eval.Map2TextureCoord2;
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ *params = (GLdouble) ctx->Eval.Map2TextureCoord3;
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ *params = (GLdouble) ctx->Eval.Map2TextureCoord4;
+ break;
+ case GL_MAP2_VERTEX_3:
+ *params = (GLdouble) ctx->Eval.Map2Vertex3;
+ break;
+ case GL_MAP2_VERTEX_4:
+ *params = (GLdouble) ctx->Eval.Map2Vertex4;
+ break;
+ case GL_MAP_COLOR:
+ *params = (GLdouble) ctx->Pixel.MapColorFlag;
+ break;
+ case GL_MAP_STENCIL:
+ *params = (GLdouble) ctx->Pixel.MapStencilFlag;
+ break;
+ case GL_MATRIX_MODE:
+ *params = ENUM_TO_DOUBLE(ctx->Transform.MatrixMode);
+ break;
+ case GL_MAX_ATTRIB_STACK_DEPTH:
+ *params = (GLdouble) MAX_ATTRIB_STACK_DEPTH;
+ break;
+ case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH:
+ *params = (GLdouble) MAX_CLIENT_ATTRIB_STACK_DEPTH;
+ break;
+ case GL_MAX_CLIP_PLANES:
+ *params = (GLdouble) MAX_CLIP_PLANES;
+ break;
+ case GL_MAX_ELEMENTS_VERTICES: /* GL_VERSION_1_2 */
+ *params = (GLdouble) VB_MAX;
+ break;
+ case GL_MAX_ELEMENTS_INDICES: /* GL_VERSION_1_2 */
+ *params = (GLdouble) VB_MAX;
+ break;
+ case GL_MAX_EVAL_ORDER:
+ *params = (GLdouble) MAX_EVAL_ORDER;
+ break;
+ case GL_MAX_LIGHTS:
+ *params = (GLdouble) MAX_LIGHTS;
+ break;
+ case GL_MAX_LIST_NESTING:
+ *params = (GLdouble) MAX_LIST_NESTING;
+ break;
+ case GL_MAX_MODELVIEW_STACK_DEPTH:
+ *params = (GLdouble) MAX_MODELVIEW_STACK_DEPTH;
+ break;
+ case GL_MAX_NAME_STACK_DEPTH:
+ *params = (GLdouble) MAX_NAME_STACK_DEPTH;
+ break;
+ case GL_MAX_PIXEL_MAP_TABLE:
+ *params = (GLdouble) MAX_PIXEL_MAP_TABLE;
+ break;
+ case GL_MAX_PROJECTION_STACK_DEPTH:
+ *params = (GLdouble) MAX_PROJECTION_STACK_DEPTH;
+ break;
+ case GL_MAX_TEXTURE_SIZE:
+ case GL_MAX_3D_TEXTURE_SIZE:
+ *params = (GLdouble) ctx->Const.MaxTextureSize;
+ break;
+ case GL_MAX_TEXTURE_STACK_DEPTH:
+ *params = (GLdouble) MAX_TEXTURE_STACK_DEPTH;
+ break;
+ case GL_MAX_VIEWPORT_DIMS:
+ params[0] = (GLdouble) MAX_WIDTH;
+ params[1] = (GLdouble) MAX_HEIGHT;
+ break;
+ case GL_MODELVIEW_MATRIX:
+ for (i=0;i<16;i++) {
+ params[i] = (GLdouble) ctx->ModelView.m[i];
+ }
+ break;
+ case GL_MODELVIEW_STACK_DEPTH:
+ *params = (GLdouble) (ctx->ModelViewStackDepth + 1);
+ break;
+ case GL_NAME_STACK_DEPTH:
+ *params = (GLdouble) ctx->Select.NameStackDepth;
+ break;
+ case GL_NORMALIZE:
+ *params = (GLdouble) ctx->Transform.Normalize;
+ break;
+ case GL_PACK_ALIGNMENT:
+ *params = (GLdouble) ctx->Pack.Alignment;
+ break;
+ case GL_PACK_LSB_FIRST:
+ *params = (GLdouble) ctx->Pack.LsbFirst;
+ break;
+ case GL_PACK_ROW_LENGTH:
+ *params = (GLdouble) ctx->Pack.RowLength;
+ break;
+ case GL_PACK_SKIP_PIXELS:
+ *params = (GLdouble) ctx->Pack.SkipPixels;
+ break;
+ case GL_PACK_SKIP_ROWS:
+ *params = (GLdouble) ctx->Pack.SkipRows;
+ break;
+ case GL_PACK_SWAP_BYTES:
+ *params = (GLdouble) ctx->Pack.SwapBytes;
+ break;
+ case GL_PACK_SKIP_IMAGES_EXT:
+ *params = (GLdouble) ctx->Pack.SkipImages;
+ break;
+ case GL_PACK_IMAGE_HEIGHT_EXT:
+ *params = (GLdouble) ctx->Pack.ImageHeight;
+ break;
+ case GL_PERSPECTIVE_CORRECTION_HINT:
+ *params = ENUM_TO_DOUBLE(ctx->Hint.PerspectiveCorrection);
+ break;
+ case GL_PIXEL_MAP_A_TO_A_SIZE:
+ *params = (GLdouble) ctx->Pixel.MapAtoAsize;
+ break;
+ case GL_PIXEL_MAP_B_TO_B_SIZE:
+ *params = (GLdouble) ctx->Pixel.MapBtoBsize;
+ break;
+ case GL_PIXEL_MAP_G_TO_G_SIZE:
+ *params = (GLdouble) ctx->Pixel.MapGtoGsize;
+ break;
+ case GL_PIXEL_MAP_I_TO_A_SIZE:
+ *params = (GLdouble) ctx->Pixel.MapItoAsize;
+ break;
+ case GL_PIXEL_MAP_I_TO_B_SIZE:
+ *params = (GLdouble) ctx->Pixel.MapItoBsize;
+ break;
+ case GL_PIXEL_MAP_I_TO_G_SIZE:
+ *params = (GLdouble) ctx->Pixel.MapItoGsize;
+ break;
+ case GL_PIXEL_MAP_I_TO_I_SIZE:
+ *params = (GLdouble) ctx->Pixel.MapItoIsize;
+ break;
+ case GL_PIXEL_MAP_I_TO_R_SIZE:
+ *params = (GLdouble) ctx->Pixel.MapItoRsize;
+ break;
+ case GL_PIXEL_MAP_R_TO_R_SIZE:
+ *params = (GLdouble) ctx->Pixel.MapRtoRsize;
+ break;
+ case GL_PIXEL_MAP_S_TO_S_SIZE:
+ *params = (GLdouble) ctx->Pixel.MapStoSsize;
+ break;
+ case GL_POINT_SIZE:
+ *params = (GLdouble) ctx->Point.Size;
+ break;
+ case GL_POINT_SIZE_GRANULARITY:
+ *params = (GLdouble) POINT_SIZE_GRANULARITY;
+ break;
+ case GL_POINT_SIZE_RANGE:
+ params[0] = (GLdouble) MIN_POINT_SIZE;
+ params[1] = (GLdouble) MAX_POINT_SIZE;
+ break;
+ case GL_POINT_SMOOTH:
+ *params = (GLdouble) ctx->Point.SmoothFlag;
+ break;
+ case GL_POINT_SMOOTH_HINT:
+ *params = ENUM_TO_DOUBLE(ctx->Hint.PointSmooth);
+ break;
+ case GL_POINT_SIZE_MIN_EXT:
+ *params = (GLdouble) (ctx->Point.MinSize);
+ break;
+ case GL_POINT_SIZE_MAX_EXT:
+ *params = (GLdouble) (ctx->Point.MaxSize);
+ break;
+ case GL_POINT_FADE_THRESHOLD_SIZE_EXT:
+ *params = (GLdouble) (ctx->Point.Threshold);
+ break;
+ case GL_DISTANCE_ATTENUATION_EXT:
+ params[0] = (GLdouble) (ctx->Point.Params[0]);
+ params[1] = (GLdouble) (ctx->Point.Params[1]);
+ params[2] = (GLdouble) (ctx->Point.Params[2]);
+ break;
+ case GL_POLYGON_MODE:
+ params[0] = ENUM_TO_DOUBLE(ctx->Polygon.FrontMode);
+ params[1] = ENUM_TO_DOUBLE(ctx->Polygon.BackMode);
+ break;
+#ifdef GL_EXT_polygon_offset
+ case GL_POLYGON_OFFSET_BIAS_EXT:
+ *params = (GLdouble) ctx->Polygon.OffsetUnits;
+ break;
+#endif
+ case GL_POLYGON_OFFSET_FACTOR:
+ *params = (GLdouble) ctx->Polygon.OffsetFactor;
+ break;
+ case GL_POLYGON_OFFSET_UNITS:
+ *params = (GLdouble) ctx->Polygon.OffsetUnits;
+ break;
+ case GL_POLYGON_SMOOTH:
+ *params = (GLdouble) ctx->Polygon.SmoothFlag;
+ break;
+ case GL_POLYGON_SMOOTH_HINT:
+ *params = ENUM_TO_DOUBLE(ctx->Hint.PolygonSmooth);
+ break;
+ case GL_POLYGON_STIPPLE:
+ *params = (GLdouble) ctx->Polygon.StippleFlag;
+ break;
+ case GL_PROJECTION_MATRIX:
+ for (i=0;i<16;i++) {
+ params[i] = (GLdouble) ctx->ProjectionMatrix.m[i];
+ }
+ break;
+ case GL_PROJECTION_STACK_DEPTH:
+ *params = (GLdouble) (ctx->ProjectionStackDepth + 1);
+ break;
+ case GL_READ_BUFFER:
+ *params = ENUM_TO_DOUBLE(ctx->Pixel.ReadBuffer);
+ break;
+ case GL_RED_BIAS:
+ *params = (GLdouble) ctx->Pixel.RedBias;
+ break;
+ case GL_RED_BITS:
+ *params = (GLdouble) ctx->Visual->RedBits;
+ break;
+ case GL_RED_SCALE:
+ *params = (GLdouble) ctx->Pixel.RedScale;
+ break;
+ case GL_RENDER_MODE:
+ *params = ENUM_TO_DOUBLE(ctx->RenderMode);
+ break;
+ case GL_RGBA_MODE:
+ *params = (GLdouble) ctx->Visual->RGBAflag;
+ break;
+ case GL_SCISSOR_BOX:
+ params[0] = (GLdouble) ctx->Scissor.X;
+ params[1] = (GLdouble) ctx->Scissor.Y;
+ params[2] = (GLdouble) ctx->Scissor.Width;
+ params[3] = (GLdouble) ctx->Scissor.Height;
+ break;
+ case GL_SCISSOR_TEST:
+ *params = (GLdouble) ctx->Scissor.Enabled;
+ break;
+ case GL_SELECTION_BUFFER_SIZE:
+ *params = (GLdouble) ctx->Select.BufferSize;
+ break;
+ case GL_SHADE_MODEL:
+ *params = ENUM_TO_DOUBLE(ctx->Light.ShadeModel);
+ break;
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ *params = (GLdouble) ctx->Texture.SharedPalette;
+ break;
+ case GL_STENCIL_BITS:
+ *params = (GLdouble) ctx->Visual->StencilBits;
+ break;
+ case GL_STENCIL_CLEAR_VALUE:
+ *params = (GLdouble) ctx->Stencil.Clear;
+ break;
+ case GL_STENCIL_FAIL:
+ *params = ENUM_TO_DOUBLE(ctx->Stencil.FailFunc);
+ break;
+ case GL_STENCIL_FUNC:
+ *params = ENUM_TO_DOUBLE(ctx->Stencil.Function);
+ break;
+ case GL_STENCIL_PASS_DEPTH_FAIL:
+ *params = ENUM_TO_DOUBLE(ctx->Stencil.ZFailFunc);
+ break;
+ case GL_STENCIL_PASS_DEPTH_PASS:
+ *params = ENUM_TO_DOUBLE(ctx->Stencil.ZPassFunc);
+ break;
+ case GL_STENCIL_REF:
+ *params = (GLdouble) ctx->Stencil.Ref;
+ break;
+ case GL_STENCIL_TEST:
+ *params = (GLdouble) ctx->Stencil.Enabled;
+ break;
+ case GL_STENCIL_VALUE_MASK:
+ *params = (GLdouble) ctx->Stencil.ValueMask;
+ break;
+ case GL_STENCIL_WRITEMASK:
+ *params = (GLdouble) ctx->Stencil.WriteMask;
+ break;
+ case GL_STEREO:
+ *params = (GLdouble) ctx->Visual->StereoFlag;
+ break;
+ case GL_SUBPIXEL_BITS:
+ *params = 0.0; /* TODO */
+ break;
+ case GL_TEXTURE_1D:
+ *params = gl_IsEnabled(ctx, GL_TEXTURE_1D) ? 1.0 : 0.0;
+ break;
+ case GL_TEXTURE_2D:
+ *params = gl_IsEnabled(ctx, GL_TEXTURE_2D) ? 1.0 : 0.0;
+ break;
+ case GL_TEXTURE_3D:
+ *params = gl_IsEnabled(ctx, GL_TEXTURE_3D) ? 1.0 : 0.0;
+ break;
+ case GL_TEXTURE_BINDING_1D:
+ *params = (GLdouble) textureUnit->CurrentD[1]->Name;
+ break;
+ case GL_TEXTURE_BINDING_2D:
+ *params = (GLdouble) textureUnit->CurrentD[2]->Name;
+ break;
+ case GL_TEXTURE_BINDING_3D:
+ *params = (GLdouble) textureUnit->CurrentD[3]->Name;
+ break;
+ case GL_TEXTURE_ENV_COLOR:
+ params[0] = (GLdouble) textureUnit->EnvColor[0];
+ params[1] = (GLdouble) textureUnit->EnvColor[1];
+ params[2] = (GLdouble) textureUnit->EnvColor[2];
+ params[3] = (GLdouble) textureUnit->EnvColor[3];
+ break;
+ case GL_TEXTURE_ENV_MODE:
+ *params = ENUM_TO_DOUBLE(textureUnit->EnvMode);
+ break;
+ case GL_TEXTURE_GEN_S:
+ *params = (textureUnit->TexGenEnabled & S_BIT) ? 1.0 : 0.0;
+ break;
+ case GL_TEXTURE_GEN_T:
+ *params = (textureUnit->TexGenEnabled & T_BIT) ? 1.0 : 0.0;
+ break;
+ case GL_TEXTURE_GEN_R:
+ *params = (textureUnit->TexGenEnabled & R_BIT) ? 1.0 : 0.0;
+ break;
+ case GL_TEXTURE_GEN_Q:
+ *params = (textureUnit->TexGenEnabled & Q_BIT) ? 1.0 : 0.0;
+ break;
+ case GL_TEXTURE_MATRIX:
+ for (i=0;i<16;i++) {
+ params[i] = (GLdouble) ctx->TextureMatrix[texTransformUnit].m[i];
+ }
+ break;
+ case GL_TEXTURE_STACK_DEPTH:
+ *params = (GLdouble) (ctx->TextureStackDepth[texTransformUnit] + 1);
+ break;
+ case GL_UNPACK_ALIGNMENT:
+ *params = (GLdouble) ctx->Unpack.Alignment;
+ break;
+ case GL_UNPACK_LSB_FIRST:
+ *params = (GLdouble) ctx->Unpack.LsbFirst;
+ break;
+ case GL_UNPACK_ROW_LENGTH:
+ *params = (GLdouble) ctx->Unpack.RowLength;
+ break;
+ case GL_UNPACK_SKIP_PIXELS:
+ *params = (GLdouble) ctx->Unpack.SkipPixels;
+ break;
+ case GL_UNPACK_SKIP_ROWS:
+ *params = (GLdouble) ctx->Unpack.SkipRows;
+ break;
+ case GL_UNPACK_SWAP_BYTES:
+ *params = (GLdouble) ctx->Unpack.SwapBytes;
+ break;
+ case GL_UNPACK_SKIP_IMAGES_EXT:
+ *params = (GLdouble) ctx->Unpack.SkipImages;
+ break;
+ case GL_UNPACK_IMAGE_HEIGHT_EXT:
+ *params = (GLdouble) ctx->Unpack.ImageHeight;
+ break;
+ case GL_VIEWPORT:
+ params[0] = (GLdouble) ctx->Viewport.X;
+ params[1] = (GLdouble) ctx->Viewport.Y;
+ params[2] = (GLdouble) ctx->Viewport.Width;
+ params[3] = (GLdouble) ctx->Viewport.Height;
+ break;
+ case GL_ZOOM_X:
+ *params = (GLdouble) ctx->Pixel.ZoomX;
+ break;
+ case GL_ZOOM_Y:
+ *params = (GLdouble) ctx->Pixel.ZoomY;
+ break;
+ case GL_VERTEX_ARRAY_SIZE:
+ *params = (GLdouble) ctx->Array.Vertex.Size;
+ break;
+ case GL_VERTEX_ARRAY_TYPE:
+ *params = ENUM_TO_DOUBLE(ctx->Array.Vertex.Type);
+ break;
+ case GL_VERTEX_ARRAY_STRIDE:
+ *params = (GLdouble) ctx->Array.Vertex.Stride;
+ break;
+ case GL_VERTEX_ARRAY_COUNT_EXT:
+ *params = 0.0;
+ break;
+ case GL_NORMAL_ARRAY_TYPE:
+ *params = ENUM_TO_DOUBLE(ctx->Array.Normal.Type);
+ break;
+ case GL_NORMAL_ARRAY_STRIDE:
+ *params = (GLdouble) ctx->Array.Normal.Stride;
+ break;
+ case GL_NORMAL_ARRAY_COUNT_EXT:
+ *params = 0.0;
+ break;
+ case GL_COLOR_ARRAY_SIZE:
+ *params = (GLdouble) ctx->Array.Color.Size;
+ break;
+ case GL_COLOR_ARRAY_TYPE:
+ *params = ENUM_TO_DOUBLE(ctx->Array.Color.Type);
+ break;
+ case GL_COLOR_ARRAY_STRIDE:
+ *params = (GLdouble) ctx->Array.Color.Stride;
+ break;
+ case GL_COLOR_ARRAY_COUNT_EXT:
+ *params = 0.0;
+ break;
+ case GL_INDEX_ARRAY_TYPE:
+ *params = ENUM_TO_DOUBLE(ctx->Array.Index.Type);
+ break;
+ case GL_INDEX_ARRAY_STRIDE:
+ *params = (GLdouble) ctx->Array.Index.Stride;
+ break;
+ case GL_INDEX_ARRAY_COUNT_EXT:
+ *params = 0.0;
+ break;
+ case GL_TEXTURE_COORD_ARRAY_SIZE:
+ *params = (GLdouble) ctx->Array.TexCoord[texUnit].Size;
+ break;
+ case GL_TEXTURE_COORD_ARRAY_TYPE:
+ *params = ENUM_TO_DOUBLE(ctx->Array.TexCoord[texUnit].Type);
+ break;
+ case GL_TEXTURE_COORD_ARRAY_STRIDE:
+ *params = (GLdouble) ctx->Array.TexCoord[texUnit].Stride;
+ break;
+ case GL_TEXTURE_COORD_ARRAY_COUNT_EXT:
+ *params = 0.0;
+ break;
+ case GL_EDGE_FLAG_ARRAY_STRIDE:
+ *params = (GLdouble) ctx->Array.EdgeFlag.Stride;
+ break;
+ case GL_EDGE_FLAG_ARRAY_COUNT_EXT:
+ *params = 0.0;
+ break;
+
+ case GL_MAX_TEXTURE_UNITS_ARB:
+ *params = (GLdouble) ctx->Const.MaxTextureUnits;
+ break;
+ case GL_ACTIVE_TEXTURE_ARB:
+ *params = (GLdouble) (GL_TEXTURE0_ARB + ctx->Texture.CurrentUnit);
+ break;
+ case GL_CLIENT_ACTIVE_TEXTURE_ARB:
+ *params = (GLdouble) (GL_TEXTURE0_ARB + ctx->Array.ActiveTexture);
+ break;
+
+
+ /* GL_PGI_misc_hints */
+ case GL_STRICT_DEPTHFUNC_HINT_PGI:
+ *params = ENUM_TO_DOUBLE(GL_NICEST);
+ break;
+ case GL_STRICT_LIGHTING_HINT_PGI:
+ *params = ENUM_TO_DOUBLE(ctx->Hint.StrictLighting);
+ break;
+ case GL_STRICT_SCISSOR_HINT_PGI:
+ case GL_FULL_STIPPLE_HINT_PGI:
+ *params = ENUM_TO_DOUBLE(GL_TRUE);
+ break;
+ case GL_CONSERVE_MEMORY_HINT_PGI:
+ *params = ENUM_TO_DOUBLE(GL_FALSE);
+ break;
+ case GL_ALWAYS_FAST_HINT_PGI:
+ *params = (GLdouble) (ctx->Hint.AllowDrawWin == GL_TRUE &&
+ ctx->Hint.AllowDrawSpn == GL_FALSE &&
+ ctx->Hint.AllowDrawMem == GL_FALSE);
+ break;
+ case GL_ALWAYS_SOFT_HINT_PGI:
+ *params = (GLdouble) (ctx->Hint.AllowDrawWin == GL_TRUE &&
+ ctx->Hint.AllowDrawSpn == GL_TRUE &&
+ ctx->Hint.AllowDrawMem == GL_TRUE);
+ break;
+ case GL_ALLOW_DRAW_OBJ_HINT_PGI:
+ *params = (GLdouble) GL_TRUE;
+ break;
+ case GL_ALLOW_DRAW_WIN_HINT_PGI:
+ *params = (GLdouble) ctx->Hint.AllowDrawWin;
+ break;
+ case GL_ALLOW_DRAW_SPN_HINT_PGI:
+ *params = (GLdouble) ctx->Hint.AllowDrawSpn;
+ break;
+ case GL_ALLOW_DRAW_MEM_HINT_PGI:
+ *params = (GLdouble) ctx->Hint.AllowDrawMem;
+ break;
+ case GL_CLIP_NEAR_HINT_PGI:
+ case GL_CLIP_FAR_HINT_PGI:
+ *params = ENUM_TO_DOUBLE(GL_TRUE);
+ break;
+ case GL_WIDE_LINE_HINT_PGI:
+ *params = ENUM_TO_DOUBLE(GL_DONT_CARE);
+ break;
+ case GL_BACK_NORMALS_HINT_PGI:
+ *params = ENUM_TO_DOUBLE(GL_TRUE);
+ break;
+ case GL_NATIVE_GRAPHICS_HANDLE_PGI:
+ *params = 0;
+ break;
+
+
+
+ default:
+ printf("invalid enum: %x\n", pname);
+ gl_error( ctx, GL_INVALID_ENUM, "glGetDoublev" );
+ }
+}
+
+
+
+
+void gl_GetFloatv( GLcontext *ctx, GLenum pname, GLfloat *params )
+{
+ GLuint i;
+ GLuint texUnit = ctx->Texture.CurrentUnit;
+ GLuint texTransformUnit = ctx->Texture.CurrentTransformUnit;
+ const struct gl_texture_unit *textureUnit = &ctx->Texture.Unit[texUnit];
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetFloatv");
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ fprintf(stderr, "glGetFloatv %s\n", gl_lookup_enum_by_nr(pname));
+
+ switch (pname) {
+ case GL_ACCUM_RED_BITS:
+ case GL_ACCUM_GREEN_BITS:
+ case GL_ACCUM_BLUE_BITS:
+ case GL_ACCUM_ALPHA_BITS:
+ *params = (GLfloat) ctx->Visual->AccumBits;
+ break;
+ case GL_ACCUM_CLEAR_VALUE:
+ params[0] = ctx->Accum.ClearColor[0];
+ params[1] = ctx->Accum.ClearColor[1];
+ params[2] = ctx->Accum.ClearColor[2];
+ params[3] = ctx->Accum.ClearColor[3];
+ break;
+ case GL_ALPHA_BIAS:
+ *params = ctx->Pixel.AlphaBias;
+ break;
+ case GL_ALPHA_BITS:
+ *params = (GLfloat) ctx->Visual->AlphaBits;
+ break;
+ case GL_ALPHA_SCALE:
+ *params = ctx->Pixel.AlphaScale;
+ break;
+ case GL_ALPHA_TEST:
+ *params = (GLfloat) ctx->Color.AlphaEnabled;
+ break;
+ case GL_ALPHA_TEST_FUNC:
+ *params = ENUM_TO_FLOAT(ctx->Color.AlphaFunc);
+ break;
+ case GL_ALPHA_TEST_REF:
+ *params = (GLfloat) ctx->Color.AlphaRef / 255.0;
+ break;
+ case GL_ATTRIB_STACK_DEPTH:
+ *params = (GLfloat) (ctx->AttribStackDepth);
+ break;
+ case GL_AUTO_NORMAL:
+ *params = (GLfloat) ctx->Eval.AutoNormal;
+ break;
+ case GL_AUX_BUFFERS:
+ *params = (GLfloat) NUM_AUX_BUFFERS;
+ break;
+ case GL_BLEND:
+ *params = (GLfloat) ctx->Color.BlendEnabled;
+ break;
+ case GL_BLEND_DST:
+ *params = ENUM_TO_FLOAT(ctx->Color.BlendDstRGB);
+ break;
+ case GL_BLEND_SRC:
+ *params = ENUM_TO_FLOAT(ctx->Color.BlendSrcRGB);
+ break;
+ case GL_BLEND_SRC_RGB_INGR:
+ *params = ENUM_TO_FLOAT(ctx->Color.BlendSrcRGB);
+ break;
+ case GL_BLEND_DST_RGB_INGR:
+ *params = ENUM_TO_FLOAT(ctx->Color.BlendDstRGB);
+ break;
+ case GL_BLEND_SRC_ALPHA_INGR:
+ *params = ENUM_TO_FLOAT(ctx->Color.BlendSrcA);
+ break;
+ case GL_BLEND_DST_ALPHA_INGR:
+ *params = ENUM_TO_FLOAT(ctx->Color.BlendDstA);
+ break;
+ case GL_BLEND_EQUATION_EXT:
+ *params = ENUM_TO_FLOAT(ctx->Color.BlendEquation);
+ break;
+ case GL_BLEND_COLOR_EXT:
+ params[0] = ctx->Color.BlendColor[0];
+ params[1] = ctx->Color.BlendColor[1];
+ params[2] = ctx->Color.BlendColor[2];
+ params[3] = ctx->Color.BlendColor[3];
+ break;
+ case GL_BLUE_BIAS:
+ *params = ctx->Pixel.BlueBias;
+ break;
+ case GL_BLUE_BITS:
+ *params = (GLfloat) ctx->Visual->BlueBits;
+ break;
+ case GL_BLUE_SCALE:
+ *params = ctx->Pixel.BlueScale;
+ break;
+ case GL_CLIENT_ATTRIB_STACK_DEPTH:
+ *params = (GLfloat) (ctx->ClientAttribStackDepth);
+ 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:
+ *params = (GLfloat) ctx->Transform.ClipEnabled[pname-GL_CLIP_PLANE0];
+ break;
+ case GL_COLOR_CLEAR_VALUE:
+ params[0] = (GLfloat) ctx->Color.ClearColor[0];
+ params[1] = (GLfloat) ctx->Color.ClearColor[1];
+ params[2] = (GLfloat) ctx->Color.ClearColor[2];
+ params[3] = (GLfloat) ctx->Color.ClearColor[3];
+ break;
+ case GL_COLOR_MATERIAL:
+ *params = (GLfloat) ctx->Light.ColorMaterialEnabled;
+ break;
+ case GL_COLOR_MATERIAL_FACE:
+ *params = ENUM_TO_FLOAT(ctx->Light.ColorMaterialFace);
+ break;
+ case GL_COLOR_MATERIAL_PARAMETER:
+ *params = ENUM_TO_FLOAT(ctx->Light.ColorMaterialMode);
+ break;
+ case GL_COLOR_WRITEMASK:
+ params[0] = ctx->Color.ColorMask[RCOMP] ? 1.0F : 0.0F;
+ params[1] = ctx->Color.ColorMask[GCOMP] ? 1.0F : 0.0F;
+ params[2] = ctx->Color.ColorMask[BCOMP] ? 1.0F : 0.0F;
+ params[3] = ctx->Color.ColorMask[ACOMP] ? 1.0F : 0.0F;
+ break;
+ case GL_CULL_FACE:
+ *params = (GLfloat) ctx->Polygon.CullFlag;
+ break;
+ case GL_CULL_FACE_MODE:
+ *params = ENUM_TO_FLOAT(ctx->Polygon.CullFaceMode);
+ break;
+ case GL_CURRENT_COLOR:
+ UBYTE_RGBA_TO_FLOAT_RGBA(params, ctx->Current.ByteColor);
+ break;
+ case GL_CURRENT_INDEX:
+ *params = (GLfloat) ctx->Current.Index;
+ break;
+ case GL_CURRENT_NORMAL:
+ params[0] = ctx->Current.Normal[0];
+ params[1] = ctx->Current.Normal[1];
+ params[2] = ctx->Current.Normal[2];
+ break;
+ case GL_CURRENT_RASTER_COLOR:
+ params[0] = ctx->Current.RasterColor[0];
+ params[1] = ctx->Current.RasterColor[1];
+ params[2] = ctx->Current.RasterColor[2];
+ params[3] = ctx->Current.RasterColor[3];
+ break;
+ case GL_CURRENT_RASTER_DISTANCE:
+ params[0] = ctx->Current.RasterDistance;
+ break;
+ case GL_CURRENT_RASTER_INDEX:
+ *params = (GLfloat) ctx->Current.RasterIndex;
+ break;
+ case GL_CURRENT_RASTER_POSITION:
+ params[0] = ctx->Current.RasterPos[0];
+ params[1] = ctx->Current.RasterPos[1];
+ params[2] = ctx->Current.RasterPos[2];
+ params[3] = ctx->Current.RasterPos[3];
+ break;
+ case GL_CURRENT_RASTER_TEXTURE_COORDS:
+ params[0] = ctx->Current.RasterMultiTexCoord[texTransformUnit][0];
+ params[1] = ctx->Current.RasterMultiTexCoord[texTransformUnit][1];
+ params[2] = ctx->Current.RasterMultiTexCoord[texTransformUnit][2];
+ params[3] = ctx->Current.RasterMultiTexCoord[texTransformUnit][3];
+ break;
+ case GL_CURRENT_RASTER_POSITION_VALID:
+ *params = (GLfloat) ctx->Current.RasterPosValid;
+ break;
+ case GL_CURRENT_TEXTURE_COORDS:
+ params[0] = (GLfloat) ctx->Current.Texcoord[texTransformUnit][0];
+ params[1] = (GLfloat) ctx->Current.Texcoord[texTransformUnit][1];
+ params[2] = (GLfloat) ctx->Current.Texcoord[texTransformUnit][2];
+ params[3] = (GLfloat) ctx->Current.Texcoord[texTransformUnit][3];
+ break;
+ case GL_DEPTH_BIAS:
+ *params = (GLfloat) ctx->Pixel.DepthBias;
+ break;
+ case GL_DEPTH_BITS:
+ *params = (GLfloat) ctx->Visual->DepthBits;
+ break;
+ case GL_DEPTH_CLEAR_VALUE:
+ *params = (GLfloat) ctx->Depth.Clear;
+ break;
+ case GL_DEPTH_FUNC:
+ *params = ENUM_TO_FLOAT(ctx->Depth.Func);
+ break;
+ case GL_DEPTH_RANGE:
+ params[0] = (GLfloat) ctx->Viewport.Near;
+ params[1] = (GLfloat) ctx->Viewport.Far;
+ break;
+ case GL_DEPTH_SCALE:
+ *params = (GLfloat) ctx->Pixel.DepthScale;
+ break;
+ case GL_DEPTH_TEST:
+ *params = (GLfloat) ctx->Depth.Test;
+ break;
+ case GL_DEPTH_WRITEMASK:
+ *params = (GLfloat) ctx->Depth.Mask;
+ break;
+ case GL_DITHER:
+ *params = (GLfloat) ctx->Color.DitherFlag;
+ break;
+ case GL_DOUBLEBUFFER:
+ *params = (GLfloat) ctx->Visual->DBflag;
+ break;
+ case GL_DRAW_BUFFER:
+ *params = ENUM_TO_FLOAT(ctx->Color.DrawBuffer);
+ break;
+ case GL_EDGE_FLAG:
+ *params = (GLfloat) ctx->Current.EdgeFlag;
+ break;
+ case GL_FEEDBACK_BUFFER_SIZE:
+ /* TODO: is this right? Or, return number of entries in buffer? */
+ *params = (GLfloat) ctx->Feedback.BufferSize;
+ break;
+ case GL_FEEDBACK_BUFFER_TYPE:
+ *params = ENUM_TO_FLOAT(ctx->Feedback.Type);
+ break;
+ case GL_FOG:
+ *params = (GLfloat) ctx->Fog.Enabled;
+ break;
+ case GL_FOG_COLOR:
+ params[0] = ctx->Fog.Color[0];
+ params[1] = ctx->Fog.Color[1];
+ params[2] = ctx->Fog.Color[2];
+ params[3] = ctx->Fog.Color[3];
+ break;
+ case GL_FOG_DENSITY:
+ *params = ctx->Fog.Density;
+ break;
+ case GL_FOG_END:
+ *params = ctx->Fog.End;
+ break;
+ case GL_FOG_HINT:
+ *params = ENUM_TO_FLOAT(ctx->Hint.Fog);
+ break;
+ case GL_FOG_INDEX:
+ *params = ctx->Fog.Index;
+ break;
+ case GL_FOG_MODE:
+ *params = ENUM_TO_FLOAT(ctx->Fog.Mode);
+ break;
+ case GL_FOG_START:
+ *params = ctx->Fog.Start;
+ break;
+ case GL_FRONT_FACE:
+ *params = ENUM_TO_FLOAT(ctx->Polygon.FrontFace);
+ break;
+ case GL_GREEN_BIAS:
+ *params = (GLfloat) ctx->Pixel.GreenBias;
+ break;
+ case GL_GREEN_BITS:
+ *params = (GLfloat) ctx->Visual->GreenBits;
+ break;
+ case GL_GREEN_SCALE:
+ *params = (GLfloat) ctx->Pixel.GreenScale;
+ break;
+ case GL_INDEX_BITS:
+ *params = (GLfloat) ctx->Visual->IndexBits;
+ break;
+ case GL_INDEX_CLEAR_VALUE:
+ *params = (GLfloat) ctx->Color.ClearIndex;
+ break;
+ case GL_INDEX_MODE:
+ *params = ctx->Visual->RGBAflag ? 0.0F : 1.0F;
+ break;
+ case GL_INDEX_OFFSET:
+ *params = (GLfloat) ctx->Pixel.IndexOffset;
+ break;
+ case GL_INDEX_SHIFT:
+ *params = (GLfloat) ctx->Pixel.IndexShift;
+ break;
+ case GL_INDEX_WRITEMASK:
+ *params = (GLfloat) ctx->Color.IndexMask;
+ 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:
+ *params = (GLfloat) ctx->Light.Light[pname-GL_LIGHT0].Enabled;
+ break;
+ case GL_LIGHTING:
+ *params = (GLfloat) ctx->Light.Enabled;
+ break;
+ case GL_LIGHT_MODEL_AMBIENT:
+ params[0] = ctx->Light.Model.Ambient[0];
+ params[1] = ctx->Light.Model.Ambient[1];
+ params[2] = ctx->Light.Model.Ambient[2];
+ params[3] = ctx->Light.Model.Ambient[3];
+ break;
+ case GL_LIGHT_MODEL_COLOR_CONTROL:
+ params[0] = ENUM_TO_FLOAT(ctx->Light.Model.ColorControl);
+ break;
+ case GL_LIGHT_MODEL_LOCAL_VIEWER:
+ *params = (GLfloat) ctx->Light.Model.LocalViewer;
+ break;
+ case GL_LIGHT_MODEL_TWO_SIDE:
+ *params = (GLfloat) ctx->Light.Model.TwoSide;
+ break;
+ case GL_LINE_SMOOTH:
+ *params = (GLfloat) ctx->Line.SmoothFlag;
+ break;
+ case GL_LINE_SMOOTH_HINT:
+ *params = ENUM_TO_FLOAT(ctx->Hint.LineSmooth);
+ break;
+ case GL_LINE_STIPPLE:
+ *params = (GLfloat) ctx->Line.StippleFlag;
+ break;
+ case GL_LINE_STIPPLE_PATTERN:
+ *params = (GLfloat) ctx->Line.StipplePattern;
+ break;
+ case GL_LINE_STIPPLE_REPEAT:
+ *params = (GLfloat) ctx->Line.StippleFactor;
+ break;
+ case GL_LINE_WIDTH:
+ *params = (GLfloat) ctx->Line.Width;
+ break;
+ case GL_LINE_WIDTH_GRANULARITY:
+ *params = (GLfloat) LINE_WIDTH_GRANULARITY;
+ break;
+ case GL_LINE_WIDTH_RANGE:
+ params[0] = (GLfloat) MIN_LINE_WIDTH;
+ params[1] = (GLfloat) MAX_LINE_WIDTH;
+ break;
+ case GL_LIST_BASE:
+ *params = (GLfloat) ctx->List.ListBase;
+ break;
+ case GL_LIST_INDEX:
+ *params = (GLfloat) ctx->CurrentListNum;
+ break;
+ case GL_LIST_MODE:
+ *params = ctx->ExecuteFlag ? ENUM_TO_FLOAT(GL_COMPILE_AND_EXECUTE)
+ : ENUM_TO_FLOAT(GL_COMPILE);
+ break;
+ case GL_INDEX_LOGIC_OP:
+ *params = (GLfloat) ctx->Color.IndexLogicOpEnabled;
+ break;
+ case GL_COLOR_LOGIC_OP:
+ *params = (GLfloat) ctx->Color.ColorLogicOpEnabled;
+ break;
+ case GL_LOGIC_OP_MODE:
+ *params = ENUM_TO_FLOAT(ctx->Color.LogicOp);
+ break;
+ case GL_MAP1_COLOR_4:
+ *params = (GLfloat) ctx->Eval.Map1Color4;
+ break;
+ case GL_MAP1_GRID_DOMAIN:
+ params[0] = ctx->Eval.MapGrid1u1;
+ params[1] = ctx->Eval.MapGrid1u2;
+ break;
+ case GL_MAP1_GRID_SEGMENTS:
+ *params = (GLfloat) ctx->Eval.MapGrid1un;
+ break;
+ case GL_MAP1_INDEX:
+ *params = (GLfloat) ctx->Eval.Map1Index;
+ break;
+ case GL_MAP1_NORMAL:
+ *params = (GLfloat) ctx->Eval.Map1Normal;
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ *params = (GLfloat) ctx->Eval.Map1TextureCoord1;
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ *params = (GLfloat) ctx->Eval.Map1TextureCoord2;
+ break;
+ case GL_MAP1_TEXTURE_COORD_3:
+ *params = (GLfloat) ctx->Eval.Map1TextureCoord3;
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ *params = (GLfloat) ctx->Eval.Map1TextureCoord4;
+ break;
+ case GL_MAP1_VERTEX_3:
+ *params = (GLfloat) ctx->Eval.Map1Vertex3;
+ break;
+ case GL_MAP1_VERTEX_4:
+ *params = (GLfloat) ctx->Eval.Map1Vertex4;
+ break;
+ case GL_MAP2_COLOR_4:
+ *params = (GLfloat) ctx->Eval.Map2Color4;
+ break;
+ case GL_MAP2_GRID_DOMAIN:
+ params[0] = ctx->Eval.MapGrid2u1;
+ params[1] = ctx->Eval.MapGrid2u2;
+ params[2] = ctx->Eval.MapGrid2v1;
+ params[3] = ctx->Eval.MapGrid2v2;
+ break;
+ case GL_MAP2_GRID_SEGMENTS:
+ params[0] = (GLfloat) ctx->Eval.MapGrid2un;
+ params[1] = (GLfloat) ctx->Eval.MapGrid2vn;
+ break;
+ case GL_MAP2_INDEX:
+ *params = (GLfloat) ctx->Eval.Map2Index;
+ break;
+ case GL_MAP2_NORMAL:
+ *params = (GLfloat) ctx->Eval.Map2Normal;
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ *params = ctx->Eval.Map2TextureCoord1;
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ *params = ctx->Eval.Map2TextureCoord2;
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ *params = ctx->Eval.Map2TextureCoord3;
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ *params = ctx->Eval.Map2TextureCoord4;
+ break;
+ case GL_MAP2_VERTEX_3:
+ *params = (GLfloat) ctx->Eval.Map2Vertex3;
+ break;
+ case GL_MAP2_VERTEX_4:
+ *params = (GLfloat) ctx->Eval.Map2Vertex4;
+ break;
+ case GL_MAP_COLOR:
+ *params = (GLfloat) ctx->Pixel.MapColorFlag;
+ break;
+ case GL_MAP_STENCIL:
+ *params = (GLfloat) ctx->Pixel.MapStencilFlag;
+ break;
+ case GL_MATRIX_MODE:
+ *params = ENUM_TO_FLOAT(ctx->Transform.MatrixMode);
+ break;
+ case GL_MAX_ATTRIB_STACK_DEPTH:
+ *params = (GLfloat) MAX_ATTRIB_STACK_DEPTH;
+ break;
+ case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH:
+ *params = (GLfloat) MAX_CLIENT_ATTRIB_STACK_DEPTH;
+ break;
+ case GL_MAX_CLIP_PLANES:
+ *params = (GLfloat) MAX_CLIP_PLANES;
+ break;
+ case GL_MAX_ELEMENTS_VERTICES: /* GL_VERSION_1_2 */
+ *params = (GLfloat) VB_MAX;
+ break;
+ case GL_MAX_ELEMENTS_INDICES: /* GL_VERSION_1_2 */
+ *params = (GLfloat) VB_MAX;
+ break;
+ case GL_MAX_EVAL_ORDER:
+ *params = (GLfloat) MAX_EVAL_ORDER;
+ break;
+ case GL_MAX_LIGHTS:
+ *params = (GLfloat) MAX_LIGHTS;
+ break;
+ case GL_MAX_LIST_NESTING:
+ *params = (GLfloat) MAX_LIST_NESTING;
+ break;
+ case GL_MAX_MODELVIEW_STACK_DEPTH:
+ *params = (GLfloat) MAX_MODELVIEW_STACK_DEPTH;
+ break;
+ case GL_MAX_NAME_STACK_DEPTH:
+ *params = (GLfloat) MAX_NAME_STACK_DEPTH;
+ break;
+ case GL_MAX_PIXEL_MAP_TABLE:
+ *params = (GLfloat) MAX_PIXEL_MAP_TABLE;
+ break;
+ case GL_MAX_PROJECTION_STACK_DEPTH:
+ *params = (GLfloat) MAX_PROJECTION_STACK_DEPTH;
+ break;
+ case GL_MAX_TEXTURE_SIZE:
+ case GL_MAX_3D_TEXTURE_SIZE:
+ *params = (GLfloat) ctx->Const.MaxTextureSize;
+ break;
+ case GL_MAX_TEXTURE_STACK_DEPTH:
+ *params = (GLfloat) MAX_TEXTURE_STACK_DEPTH;
+ break;
+ case GL_MAX_VIEWPORT_DIMS:
+ params[0] = (GLfloat) MAX_WIDTH;
+ params[1] = (GLfloat) MAX_HEIGHT;
+ break;
+ case GL_MODELVIEW_MATRIX:
+ for (i=0;i<16;i++) {
+ params[i] = ctx->ModelView.m[i];
+ }
+ break;
+ case GL_MODELVIEW_STACK_DEPTH:
+ *params = (GLfloat) (ctx->ModelViewStackDepth + 1);
+ break;
+ case GL_NAME_STACK_DEPTH:
+ *params = (GLfloat) ctx->Select.NameStackDepth;
+ break;
+ case GL_NORMALIZE:
+ *params = (GLfloat) ctx->Transform.Normalize;
+ break;
+ case GL_PACK_ALIGNMENT:
+ *params = (GLfloat) ctx->Pack.Alignment;
+ break;
+ case GL_PACK_LSB_FIRST:
+ *params = (GLfloat) ctx->Pack.LsbFirst;
+ break;
+ case GL_PACK_ROW_LENGTH:
+ *params = (GLfloat) ctx->Pack.RowLength;
+ break;
+ case GL_PACK_SKIP_PIXELS:
+ *params = (GLfloat) ctx->Pack.SkipPixels;
+ break;
+ case GL_PACK_SKIP_ROWS:
+ *params = (GLfloat) ctx->Pack.SkipRows;
+ break;
+ case GL_PACK_SWAP_BYTES:
+ *params = (GLfloat) ctx->Pack.SwapBytes;
+ break;
+ case GL_PACK_SKIP_IMAGES_EXT:
+ *params = (GLfloat) ctx->Pack.SkipImages;
+ break;
+ case GL_PACK_IMAGE_HEIGHT_EXT:
+ *params = (GLfloat) ctx->Pack.ImageHeight;
+ break;
+ case GL_PERSPECTIVE_CORRECTION_HINT:
+ *params = ENUM_TO_FLOAT(ctx->Hint.PerspectiveCorrection);
+ break;
+ case GL_PIXEL_MAP_A_TO_A_SIZE:
+ *params = (GLfloat) ctx->Pixel.MapAtoAsize;
+ break;
+ case GL_PIXEL_MAP_B_TO_B_SIZE:
+ *params = (GLfloat) ctx->Pixel.MapBtoBsize;
+ break;
+ case GL_PIXEL_MAP_G_TO_G_SIZE:
+ *params = (GLfloat) ctx->Pixel.MapGtoGsize;
+ break;
+ case GL_PIXEL_MAP_I_TO_A_SIZE:
+ *params = (GLfloat) ctx->Pixel.MapItoAsize;
+ break;
+ case GL_PIXEL_MAP_I_TO_B_SIZE:
+ *params = (GLfloat) ctx->Pixel.MapItoBsize;
+ break;
+ case GL_PIXEL_MAP_I_TO_G_SIZE:
+ *params = (GLfloat) ctx->Pixel.MapItoGsize;
+ break;
+ case GL_PIXEL_MAP_I_TO_I_SIZE:
+ *params = (GLfloat) ctx->Pixel.MapItoIsize;
+ break;
+ case GL_PIXEL_MAP_I_TO_R_SIZE:
+ *params = (GLfloat) ctx->Pixel.MapItoRsize;
+ break;
+ case GL_PIXEL_MAP_R_TO_R_SIZE:
+ *params = (GLfloat) ctx->Pixel.MapRtoRsize;
+ break;
+ case GL_PIXEL_MAP_S_TO_S_SIZE:
+ *params = (GLfloat) ctx->Pixel.MapStoSsize;
+ break;
+ case GL_POINT_SIZE:
+ *params = (GLfloat) ctx->Point.Size;
+ break;
+ case GL_POINT_SIZE_GRANULARITY:
+ *params = (GLfloat) POINT_SIZE_GRANULARITY;
+ break;
+ case GL_POINT_SIZE_RANGE:
+ params[0] = (GLfloat) MIN_POINT_SIZE;
+ params[1] = (GLfloat) MAX_POINT_SIZE;
+ break;
+ case GL_POINT_SMOOTH:
+ *params = (GLfloat) ctx->Point.SmoothFlag;
+ break;
+ case GL_POINT_SMOOTH_HINT:
+ *params = ENUM_TO_FLOAT(ctx->Hint.PointSmooth);
+ break;
+ case GL_POINT_SIZE_MIN_EXT:
+ *params = (GLfloat) (ctx->Point.MinSize);
+ break;
+ case GL_POINT_SIZE_MAX_EXT:
+ *params = (GLfloat) (ctx->Point.MaxSize);
+ break;
+ case GL_POINT_FADE_THRESHOLD_SIZE_EXT:
+ *params = (GLfloat) (ctx->Point.Threshold);
+ break;
+ case GL_DISTANCE_ATTENUATION_EXT:
+ params[0] = (GLfloat) (ctx->Point.Params[0]);
+ params[1] = (GLfloat) (ctx->Point.Params[1]);
+ params[2] = (GLfloat) (ctx->Point.Params[2]);
+ break;
+ case GL_POLYGON_MODE:
+ params[0] = ENUM_TO_FLOAT(ctx->Polygon.FrontMode);
+ params[1] = ENUM_TO_FLOAT(ctx->Polygon.BackMode);
+ break;
+#ifdef GL_EXT_polygon_offset
+ case GL_POLYGON_OFFSET_BIAS_EXT:
+ *params = ctx->Polygon.OffsetUnits;
+ break;
+#endif
+ case GL_POLYGON_OFFSET_FACTOR:
+ *params = ctx->Polygon.OffsetFactor;
+ break;
+ case GL_POLYGON_OFFSET_UNITS:
+ *params = ctx->Polygon.OffsetUnits;
+ break;
+ case GL_POLYGON_SMOOTH:
+ *params = (GLfloat) ctx->Polygon.SmoothFlag;
+ break;
+ case GL_POLYGON_SMOOTH_HINT:
+ *params = ENUM_TO_FLOAT(ctx->Hint.PolygonSmooth);
+ break;
+ case GL_POLYGON_STIPPLE:
+ *params = (GLfloat) ctx->Polygon.StippleFlag;
+ break;
+ case GL_PROJECTION_MATRIX:
+ for (i=0;i<16;i++) {
+ params[i] = ctx->ProjectionMatrix.m[i];
+ }
+ break;
+ case GL_PROJECTION_STACK_DEPTH:
+ *params = (GLfloat) (ctx->ProjectionStackDepth + 1);
+ break;
+ case GL_READ_BUFFER:
+ *params = ENUM_TO_FLOAT(ctx->Pixel.ReadBuffer);
+ break;
+ case GL_RED_BIAS:
+ *params = ctx->Pixel.RedBias;
+ break;
+ case GL_RED_BITS:
+ *params = (GLfloat) ctx->Visual->RedBits;
+ break;
+ case GL_RED_SCALE:
+ *params = ctx->Pixel.RedScale;
+ break;
+ case GL_RENDER_MODE:
+ *params = ENUM_TO_FLOAT(ctx->RenderMode);
+ break;
+ case GL_RGBA_MODE:
+ *params = (GLfloat) ctx->Visual->RGBAflag;
+ break;
+ case GL_SCISSOR_BOX:
+ params[0] = (GLfloat) ctx->Scissor.X;
+ params[1] = (GLfloat) ctx->Scissor.Y;
+ params[2] = (GLfloat) ctx->Scissor.Width;
+ params[3] = (GLfloat) ctx->Scissor.Height;
+ break;
+ case GL_SCISSOR_TEST:
+ *params = (GLfloat) ctx->Scissor.Enabled;
+ break;
+ case GL_SELECTION_BUFFER_SIZE:
+ *params = (GLfloat) ctx->Select.BufferSize;
+ break;
+ case GL_SHADE_MODEL:
+ *params = ENUM_TO_FLOAT(ctx->Light.ShadeModel);
+ break;
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ *params = (GLfloat) ctx->Texture.SharedPalette;
+ break;
+ case GL_STENCIL_BITS:
+ *params = (GLfloat) ctx->Visual->StencilBits;
+ break;
+ case GL_STENCIL_CLEAR_VALUE:
+ *params = (GLfloat) ctx->Stencil.Clear;
+ break;
+ case GL_STENCIL_FAIL:
+ *params = ENUM_TO_FLOAT(ctx->Stencil.FailFunc);
+ break;
+ case GL_STENCIL_FUNC:
+ *params = ENUM_TO_FLOAT(ctx->Stencil.Function);
+ break;
+ case GL_STENCIL_PASS_DEPTH_FAIL:
+ *params = ENUM_TO_FLOAT(ctx->Stencil.ZFailFunc);
+ break;
+ case GL_STENCIL_PASS_DEPTH_PASS:
+ *params = ENUM_TO_FLOAT(ctx->Stencil.ZPassFunc);
+ break;
+ case GL_STENCIL_REF:
+ *params = (GLfloat) ctx->Stencil.Ref;
+ break;
+ case GL_STENCIL_TEST:
+ *params = (GLfloat) ctx->Stencil.Enabled;
+ break;
+ case GL_STENCIL_VALUE_MASK:
+ *params = (GLfloat) ctx->Stencil.ValueMask;
+ break;
+ case GL_STENCIL_WRITEMASK:
+ *params = (GLfloat) ctx->Stencil.WriteMask;
+ break;
+ case GL_STEREO:
+ *params = (GLfloat) ctx->Visual->StereoFlag;
+ break;
+ case GL_SUBPIXEL_BITS:
+ *params = 0.0F; /* TODO */
+ break;
+ case GL_TEXTURE_1D:
+ *params = gl_IsEnabled(ctx, GL_TEXTURE_1D) ? 1.0 : 0.0;
+ break;
+ case GL_TEXTURE_2D:
+ *params = gl_IsEnabled(ctx, GL_TEXTURE_2D) ? 1.0 : 0.0;
+ break;
+ case GL_TEXTURE_3D:
+ *params = gl_IsEnabled(ctx, GL_TEXTURE_3D) ? 1.0 : 0.0;
+ break;
+ case GL_TEXTURE_BINDING_1D:
+ *params = (GLfloat) textureUnit->CurrentD[1]->Name;
+ break;
+ case GL_TEXTURE_BINDING_2D:
+ *params = (GLfloat) textureUnit->CurrentD[2]->Name;
+ break;
+ case GL_TEXTURE_BINDING_3D:
+ *params = (GLfloat) textureUnit->CurrentD[2]->Name;
+ break;
+ case GL_TEXTURE_ENV_COLOR:
+ params[0] = textureUnit->EnvColor[0];
+ params[1] = textureUnit->EnvColor[1];
+ params[2] = textureUnit->EnvColor[2];
+ params[3] = textureUnit->EnvColor[3];
+ break;
+ case GL_TEXTURE_ENV_MODE:
+ *params = ENUM_TO_FLOAT(textureUnit->EnvMode);
+ break;
+ case GL_TEXTURE_GEN_S:
+ *params = (textureUnit->TexGenEnabled & S_BIT) ? 1.0 : 0.0;
+ break;
+ case GL_TEXTURE_GEN_T:
+ *params = (textureUnit->TexGenEnabled & T_BIT) ? 1.0 : 0.0;
+ break;
+ case GL_TEXTURE_GEN_R:
+ *params = (textureUnit->TexGenEnabled & R_BIT) ? 1.0 : 0.0;
+ break;
+ case GL_TEXTURE_GEN_Q:
+ *params = (textureUnit->TexGenEnabled & Q_BIT) ? 1.0 : 0.0;
+ break;
+ case GL_TEXTURE_MATRIX:
+ for (i=0;i<16;i++) {
+ params[i] = ctx->TextureMatrix[texTransformUnit].m[i];
+ }
+ break;
+ case GL_TEXTURE_STACK_DEPTH:
+ *params = (GLfloat) (ctx->TextureStackDepth[texTransformUnit] + 1);
+ break;
+ case GL_UNPACK_ALIGNMENT:
+ *params = (GLfloat) ctx->Unpack.Alignment;
+ break;
+ case GL_UNPACK_LSB_FIRST:
+ *params = (GLfloat) ctx->Unpack.LsbFirst;
+ break;
+ case GL_UNPACK_ROW_LENGTH:
+ *params = (GLfloat) ctx->Unpack.RowLength;
+ break;
+ case GL_UNPACK_SKIP_PIXELS:
+ *params = (GLfloat) ctx->Unpack.SkipPixels;
+ break;
+ case GL_UNPACK_SKIP_ROWS:
+ *params = (GLfloat) ctx->Unpack.SkipRows;
+ break;
+ case GL_UNPACK_SWAP_BYTES:
+ *params = (GLfloat) ctx->Unpack.SwapBytes;
+ break;
+ case GL_UNPACK_SKIP_IMAGES_EXT:
+ *params = (GLfloat) ctx->Unpack.SkipImages;
+ break;
+ case GL_UNPACK_IMAGE_HEIGHT_EXT:
+ *params = (GLfloat) ctx->Unpack.ImageHeight;
+ break;
+ case GL_VIEWPORT:
+ params[0] = (GLfloat) ctx->Viewport.X;
+ params[1] = (GLfloat) ctx->Viewport.Y;
+ params[2] = (GLfloat) ctx->Viewport.Width;
+ params[3] = (GLfloat) ctx->Viewport.Height;
+ break;
+ case GL_ZOOM_X:
+ *params = (GLfloat) ctx->Pixel.ZoomX;
+ break;
+ case GL_ZOOM_Y:
+ *params = (GLfloat) ctx->Pixel.ZoomY;
+ break;
+ case GL_VERTEX_ARRAY_SIZE:
+ *params = (GLfloat) ctx->Array.Vertex.Size;
+ break;
+ case GL_VERTEX_ARRAY_TYPE:
+ *params = ENUM_TO_FLOAT(ctx->Array.Vertex.Type);
+ break;
+ case GL_VERTEX_ARRAY_STRIDE:
+ *params = (GLfloat) ctx->Array.Vertex.Stride;
+ break;
+ case GL_VERTEX_ARRAY_COUNT_EXT:
+ *params = 0.0;
+ break;
+ case GL_NORMAL_ARRAY_TYPE:
+ *params = ENUM_TO_FLOAT(ctx->Array.Normal.Type);
+ break;
+ case GL_NORMAL_ARRAY_STRIDE:
+ *params = (GLfloat) ctx->Array.Normal.Stride;
+ break;
+ case GL_NORMAL_ARRAY_COUNT_EXT:
+ *params = 0.0;
+ break;
+ case GL_COLOR_ARRAY_SIZE:
+ *params = (GLfloat) ctx->Array.Color.Size;
+ break;
+ case GL_COLOR_ARRAY_TYPE:
+ *params = ENUM_TO_FLOAT(ctx->Array.Color.Type);
+ break;
+ case GL_COLOR_ARRAY_STRIDE:
+ *params = (GLfloat) ctx->Array.Color.Stride;
+ break;
+ case GL_COLOR_ARRAY_COUNT_EXT:
+ *params = 0.0;
+ break;
+ case GL_INDEX_ARRAY_TYPE:
+ *params = ENUM_TO_FLOAT(ctx->Array.Index.Type);
+ break;
+ case GL_INDEX_ARRAY_STRIDE:
+ *params = (GLfloat) ctx->Array.Index.Stride;
+ break;
+ case GL_INDEX_ARRAY_COUNT_EXT:
+ *params = 0.0;
+ break;
+ case GL_TEXTURE_COORD_ARRAY_SIZE:
+ *params = (GLfloat) ctx->Array.TexCoord[texUnit].Size;
+ break;
+ case GL_TEXTURE_COORD_ARRAY_TYPE:
+ *params = ENUM_TO_FLOAT(ctx->Array.TexCoord[texUnit].Type);
+ break;
+ case GL_TEXTURE_COORD_ARRAY_STRIDE:
+ *params = (GLfloat) ctx->Array.TexCoord[texUnit].Stride;
+ break;
+ case GL_TEXTURE_COORD_ARRAY_COUNT_EXT:
+ *params = 0.0;
+ break;
+ case GL_EDGE_FLAG_ARRAY_STRIDE:
+ *params = (GLfloat) ctx->Array.EdgeFlag.Stride;
+ break;
+ case GL_EDGE_FLAG_ARRAY_COUNT_EXT:
+ *params = 0.0;
+ break;
+
+ case GL_MAX_TEXTURE_UNITS_ARB:
+ *params = (GLfloat) ctx->Const.MaxTextureUnits;
+ break;
+ case GL_ACTIVE_TEXTURE_ARB:
+ *params = (GLfloat) (GL_TEXTURE0_ARB + ctx->Texture.CurrentUnit);
+ break;
+ case GL_CLIENT_ACTIVE_TEXTURE_ARB:
+ *params = (GLfloat) (GL_TEXTURE0_ARB + ctx->Array.ActiveTexture);
+ break;
+
+ /* GL_PGI_misc_hints */
+ case GL_STRICT_DEPTHFUNC_HINT_PGI:
+ *params = ENUM_TO_FLOAT(GL_NICEST);
+ break;
+ case GL_STRICT_LIGHTING_HINT_PGI:
+ *params = ENUM_TO_FLOAT(ctx->Hint.StrictLighting);
+ break;
+ case GL_STRICT_SCISSOR_HINT_PGI:
+ case GL_FULL_STIPPLE_HINT_PGI:
+ *params = ENUM_TO_FLOAT(GL_TRUE);
+ break;
+ case GL_CONSERVE_MEMORY_HINT_PGI:
+ *params = ENUM_TO_FLOAT(GL_FALSE);
+ break;
+ case GL_ALWAYS_FAST_HINT_PGI:
+ *params = (GLfloat) (ctx->Hint.AllowDrawWin == GL_TRUE &&
+ ctx->Hint.AllowDrawSpn == GL_FALSE &&
+ ctx->Hint.AllowDrawMem == GL_FALSE);
+ break;
+ case GL_ALWAYS_SOFT_HINT_PGI:
+ *params = (GLfloat) (ctx->Hint.AllowDrawWin == GL_TRUE &&
+ ctx->Hint.AllowDrawSpn == GL_TRUE &&
+ ctx->Hint.AllowDrawMem == GL_TRUE);
+ break;
+ case GL_ALLOW_DRAW_OBJ_HINT_PGI:
+ *params = (GLfloat) GL_TRUE;
+ break;
+ case GL_ALLOW_DRAW_WIN_HINT_PGI:
+ *params = (GLfloat) ctx->Hint.AllowDrawWin;
+ break;
+ case GL_ALLOW_DRAW_SPN_HINT_PGI:
+ *params = (GLfloat) ctx->Hint.AllowDrawSpn;
+ break;
+ case GL_ALLOW_DRAW_MEM_HINT_PGI:
+ *params = (GLfloat) ctx->Hint.AllowDrawMem;
+ break;
+ case GL_CLIP_NEAR_HINT_PGI:
+ case GL_CLIP_FAR_HINT_PGI:
+ *params = ENUM_TO_FLOAT(GL_TRUE);
+ break;
+ case GL_WIDE_LINE_HINT_PGI:
+ *params = ENUM_TO_FLOAT(GL_DONT_CARE);
+ break;
+ case GL_BACK_NORMALS_HINT_PGI:
+ *params = ENUM_TO_FLOAT(GL_TRUE);
+ break;
+ case GL_NATIVE_GRAPHICS_HANDLE_PGI:
+ *params = 0;
+ break;
+
+ default:
+ printf("invalid enum: %x\n", pname);
+ gl_error( ctx, GL_INVALID_ENUM, "glGetFloatv" );
+ }
+}
+
+
+
+
+void gl_GetIntegerv( GLcontext *ctx, GLenum pname, GLint *params )
+{
+ GLuint i;
+ GLuint texUnit = ctx->Texture.CurrentUnit;
+ GLuint texTransformUnit = ctx->Texture.CurrentTransformUnit;
+ const struct gl_texture_unit *textureUnit = &ctx->Texture.Unit[texUnit];
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetIntegerv");
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ fprintf(stderr, "glGetIntegerv %s\n", gl_lookup_enum_by_nr(pname));
+
+ switch (pname) {
+ case GL_ACCUM_RED_BITS:
+ case GL_ACCUM_GREEN_BITS:
+ case GL_ACCUM_BLUE_BITS:
+ case GL_ACCUM_ALPHA_BITS:
+ *params = (GLint) ctx->Visual->AccumBits;
+ break;
+ case GL_ACCUM_CLEAR_VALUE:
+ params[0] = FLOAT_TO_INT( ctx->Accum.ClearColor[0] );
+ params[1] = FLOAT_TO_INT( ctx->Accum.ClearColor[1] );
+ params[2] = FLOAT_TO_INT( ctx->Accum.ClearColor[2] );
+ params[3] = FLOAT_TO_INT( ctx->Accum.ClearColor[3] );
+ break;
+ case GL_ALPHA_BIAS:
+ *params = (GLint) ctx->Pixel.AlphaBias;
+ break;
+ case GL_ALPHA_BITS:
+ *params = ctx->Visual->AlphaBits;
+ break;
+ case GL_ALPHA_SCALE:
+ *params = (GLint) ctx->Pixel.AlphaScale;
+ break;
+ case GL_ALPHA_TEST:
+ *params = (GLint) ctx->Color.AlphaEnabled;
+ break;
+ case GL_ALPHA_TEST_REF:
+ *params = FLOAT_TO_INT( (GLfloat) ctx->Color.AlphaRef / 255.0 );
+ break;
+ case GL_ALPHA_TEST_FUNC:
+ *params = (GLint) ctx->Color.AlphaFunc;
+ break;
+ case GL_ATTRIB_STACK_DEPTH:
+ *params = (GLint) (ctx->AttribStackDepth);
+ break;
+ case GL_AUTO_NORMAL:
+ *params = (GLint) ctx->Eval.AutoNormal;
+ break;
+ case GL_AUX_BUFFERS:
+ *params = (GLint) NUM_AUX_BUFFERS;
+ break;
+ case GL_BLEND:
+ *params = (GLint) ctx->Color.BlendEnabled;
+ break;
+ case GL_BLEND_DST:
+ *params = (GLint) ctx->Color.BlendDstRGB;
+ break;
+ case GL_BLEND_SRC:
+ *params = (GLint) ctx->Color.BlendSrcRGB;
+ break;
+ case GL_BLEND_SRC_RGB_INGR:
+ *params = (GLint) ctx->Color.BlendSrcRGB;
+ break;
+ case GL_BLEND_DST_RGB_INGR:
+ *params = (GLint) ctx->Color.BlendDstRGB;
+ break;
+ case GL_BLEND_SRC_ALPHA_INGR:
+ *params = (GLint) ctx->Color.BlendSrcA;
+ break;
+ case GL_BLEND_DST_ALPHA_INGR:
+ *params = (GLint) ctx->Color.BlendDstA;
+ break;
+ case GL_BLEND_EQUATION_EXT:
+ *params = (GLint) ctx->Color.BlendEquation;
+ break;
+ case GL_BLEND_COLOR_EXT:
+ params[0] = FLOAT_TO_INT( ctx->Color.BlendColor[0] );
+ params[1] = FLOAT_TO_INT( ctx->Color.BlendColor[1] );
+ params[2] = FLOAT_TO_INT( ctx->Color.BlendColor[2] );
+ params[3] = FLOAT_TO_INT( ctx->Color.BlendColor[3] );
+ break;
+ case GL_BLUE_BIAS:
+ *params = (GLint) ctx->Pixel.BlueBias;
+ break;
+ case GL_BLUE_BITS:
+ *params = (GLint) ctx->Visual->BlueBits;
+ break;
+ case GL_BLUE_SCALE:
+ *params = (GLint) ctx->Pixel.BlueScale;
+ break;
+ case GL_CLIENT_ATTRIB_STACK_DEPTH:
+ *params = (GLint) (ctx->ClientAttribStackDepth);
+ 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:
+ i = (GLint) (pname - GL_CLIP_PLANE0);
+ *params = (GLint) ctx->Transform.ClipEnabled[i];
+ break;
+ case GL_COLOR_CLEAR_VALUE:
+ params[0] = FLOAT_TO_INT( ctx->Color.ClearColor[0] );
+ params[1] = FLOAT_TO_INT( ctx->Color.ClearColor[1] );
+ params[2] = FLOAT_TO_INT( ctx->Color.ClearColor[2] );
+ params[3] = FLOAT_TO_INT( ctx->Color.ClearColor[3] );
+ break;
+ case GL_COLOR_MATERIAL:
+ *params = (GLint) ctx->Light.ColorMaterialEnabled;
+ break;
+ case GL_COLOR_MATERIAL_FACE:
+ *params = (GLint) ctx->Light.ColorMaterialFace;
+ break;
+ case GL_COLOR_MATERIAL_PARAMETER:
+ *params = (GLint) ctx->Light.ColorMaterialMode;
+ break;
+ case GL_COLOR_WRITEMASK:
+ params[0] = ctx->Color.ColorMask[RCOMP] ? 1 : 0;
+ params[1] = ctx->Color.ColorMask[GCOMP] ? 1 : 0;
+ params[2] = ctx->Color.ColorMask[BCOMP] ? 1 : 0;
+ params[3] = ctx->Color.ColorMask[ACOMP] ? 1 : 0;
+ break;
+ case GL_CULL_FACE:
+ *params = (GLint) ctx->Polygon.CullFlag;
+ break;
+ case GL_CULL_FACE_MODE:
+ *params = (GLint) ctx->Polygon.CullFaceMode;
+ break;
+ case GL_CURRENT_COLOR:
+ params[0] = FLOAT_TO_INT( UBYTE_COLOR_TO_FLOAT_COLOR( ctx->Current.ByteColor[0] ) );
+ params[1] = FLOAT_TO_INT( UBYTE_COLOR_TO_FLOAT_COLOR( ctx->Current.ByteColor[1] ) );
+ params[2] = FLOAT_TO_INT( UBYTE_COLOR_TO_FLOAT_COLOR( ctx->Current.ByteColor[2] ) );
+ params[3] = FLOAT_TO_INT( UBYTE_COLOR_TO_FLOAT_COLOR( ctx->Current.ByteColor[3] ) );
+ break;
+ case GL_CURRENT_INDEX:
+ *params = (GLint) ctx->Current.Index;
+ break;
+ case GL_CURRENT_NORMAL:
+ params[0] = FLOAT_TO_INT( ctx->Current.Normal[0] );
+ params[1] = FLOAT_TO_INT( ctx->Current.Normal[1] );
+ params[2] = FLOAT_TO_INT( ctx->Current.Normal[2] );
+ break;
+ case GL_CURRENT_RASTER_COLOR:
+ params[0] = FLOAT_TO_INT( ctx->Current.RasterColor[0] );
+ params[1] = FLOAT_TO_INT( ctx->Current.RasterColor[1] );
+ params[2] = FLOAT_TO_INT( ctx->Current.RasterColor[2] );
+ params[3] = FLOAT_TO_INT( ctx->Current.RasterColor[3] );
+ break;
+ case GL_CURRENT_RASTER_DISTANCE:
+ params[0] = (GLint) ctx->Current.RasterDistance;
+ break;
+ case GL_CURRENT_RASTER_INDEX:
+ *params = (GLint) ctx->Current.RasterIndex;
+ break;
+ case GL_CURRENT_RASTER_POSITION:
+ params[0] = (GLint) ctx->Current.RasterPos[0];
+ params[1] = (GLint) ctx->Current.RasterPos[1];
+ params[2] = (GLint) ctx->Current.RasterPos[2];
+ params[3] = (GLint) ctx->Current.RasterPos[3];
+ break;
+ case GL_CURRENT_RASTER_TEXTURE_COORDS:
+ params[0] = (GLint) ctx->Current.RasterMultiTexCoord[texTransformUnit][0];
+ params[1] = (GLint) ctx->Current.RasterMultiTexCoord[texTransformUnit][1];
+ params[2] = (GLint) ctx->Current.RasterMultiTexCoord[texTransformUnit][2];
+ params[3] = (GLint) ctx->Current.RasterMultiTexCoord[texTransformUnit][3];
+ break;
+ case GL_CURRENT_RASTER_POSITION_VALID:
+ *params = (GLint) ctx->Current.RasterPosValid;
+ break;
+ case GL_CURRENT_TEXTURE_COORDS:
+ params[0] = (GLint) ctx->Current.Texcoord[texTransformUnit][0];
+ params[1] = (GLint) ctx->Current.Texcoord[texTransformUnit][1];
+ params[2] = (GLint) ctx->Current.Texcoord[texTransformUnit][2];
+ params[3] = (GLint) ctx->Current.Texcoord[texTransformUnit][3];
+ break;
+ case GL_DEPTH_BIAS:
+ *params = (GLint) ctx->Pixel.DepthBias;
+ break;
+ case GL_DEPTH_BITS:
+ *params = ctx->Visual->DepthBits;
+ break;
+ case GL_DEPTH_CLEAR_VALUE:
+ *params = (GLint) ctx->Depth.Clear;
+ break;
+ case GL_DEPTH_FUNC:
+ *params = (GLint) ctx->Depth.Func;
+ break;
+ case GL_DEPTH_RANGE:
+ params[0] = (GLint) ctx->Viewport.Near;
+ params[1] = (GLint) ctx->Viewport.Far;
+ break;
+ case GL_DEPTH_SCALE:
+ *params = (GLint) ctx->Pixel.DepthScale;
+ break;
+ case GL_DEPTH_TEST:
+ *params = (GLint) ctx->Depth.Test;
+ break;
+ case GL_DEPTH_WRITEMASK:
+ *params = (GLint) ctx->Depth.Mask;
+ break;
+ case GL_DITHER:
+ *params = (GLint) ctx->Color.DitherFlag;
+ break;
+ case GL_DOUBLEBUFFER:
+ *params = (GLint) ctx->Visual->DBflag;
+ break;
+ case GL_DRAW_BUFFER:
+ *params = (GLint) ctx->Color.DrawBuffer;
+ break;
+ case GL_EDGE_FLAG:
+ *params = (GLint) ctx->Current.EdgeFlag;
+ break;
+ case GL_FEEDBACK_BUFFER_SIZE:
+ /* TODO: is this right? Or, return number of entries in buffer? */
+ *params = ctx->Feedback.BufferSize;
+ break;
+ case GL_FEEDBACK_BUFFER_TYPE:
+ *params = ctx->Feedback.Type;
+ break;
+ case GL_FOG:
+ *params = (GLint) ctx->Fog.Enabled;
+ break;
+ case GL_FOG_COLOR:
+ params[0] = FLOAT_TO_INT( ctx->Fog.Color[0] );
+ params[1] = FLOAT_TO_INT( ctx->Fog.Color[1] );
+ params[2] = FLOAT_TO_INT( ctx->Fog.Color[2] );
+ params[3] = FLOAT_TO_INT( ctx->Fog.Color[3] );
+ break;
+ case GL_FOG_DENSITY:
+ *params = (GLint) ctx->Fog.Density;
+ break;
+ case GL_FOG_END:
+ *params = (GLint) ctx->Fog.End;
+ break;
+ case GL_FOG_HINT:
+ *params = (GLint) ctx->Hint.Fog;
+ break;
+ case GL_FOG_INDEX:
+ *params = (GLint) ctx->Fog.Index;
+ break;
+ case GL_FOG_MODE:
+ *params = (GLint) ctx->Fog.Mode;
+ break;
+ case GL_FOG_START:
+ *params = (GLint) ctx->Fog.Start;
+ break;
+ case GL_FRONT_FACE:
+ *params = (GLint) ctx->Polygon.FrontFace;
+ break;
+ case GL_GREEN_BIAS:
+ *params = (GLint) ctx->Pixel.GreenBias;
+ break;
+ case GL_GREEN_BITS:
+ *params = (GLint) ctx->Visual->GreenBits;
+ break;
+ case GL_GREEN_SCALE:
+ *params = (GLint) ctx->Pixel.GreenScale;
+ break;
+ case GL_INDEX_BITS:
+ *params = (GLint) ctx->Visual->IndexBits;
+ break;
+ case GL_INDEX_CLEAR_VALUE:
+ *params = (GLint) ctx->Color.ClearIndex;
+ break;
+ case GL_INDEX_MODE:
+ *params = ctx->Visual->RGBAflag ? 0 : 1;
+ break;
+ case GL_INDEX_OFFSET:
+ *params = ctx->Pixel.IndexOffset;
+ break;
+ case GL_INDEX_SHIFT:
+ *params = ctx->Pixel.IndexShift;
+ break;
+ case GL_INDEX_WRITEMASK:
+ *params = (GLint) ctx->Color.IndexMask;
+ 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:
+ *params = (GLint) ctx->Light.Light[pname-GL_LIGHT0].Enabled;
+ break;
+ case GL_LIGHTING:
+ *params = (GLint) ctx->Light.Enabled;
+ break;
+ case GL_LIGHT_MODEL_AMBIENT:
+ params[0] = FLOAT_TO_INT( ctx->Light.Model.Ambient[0] );
+ params[1] = FLOAT_TO_INT( ctx->Light.Model.Ambient[1] );
+ params[2] = FLOAT_TO_INT( ctx->Light.Model.Ambient[2] );
+ params[3] = FLOAT_TO_INT( ctx->Light.Model.Ambient[3] );
+ break;
+ case GL_LIGHT_MODEL_COLOR_CONTROL:
+ params[0] = (GLint) ctx->Light.Model.ColorControl;
+ break;
+ case GL_LIGHT_MODEL_LOCAL_VIEWER:
+ *params = (GLint) ctx->Light.Model.LocalViewer;
+ break;
+ case GL_LIGHT_MODEL_TWO_SIDE:
+ *params = (GLint) ctx->Light.Model.TwoSide;
+ break;
+ case GL_LINE_SMOOTH:
+ *params = (GLint) ctx->Line.SmoothFlag;
+ break;
+ case GL_LINE_SMOOTH_HINT:
+ *params = (GLint) ctx->Hint.LineSmooth;
+ break;
+ case GL_LINE_STIPPLE:
+ *params = (GLint) ctx->Line.StippleFlag;
+ break;
+ case GL_LINE_STIPPLE_PATTERN:
+ *params = (GLint) ctx->Line.StipplePattern;
+ break;
+ case GL_LINE_STIPPLE_REPEAT:
+ *params = (GLint) ctx->Line.StippleFactor;
+ break;
+ case GL_LINE_WIDTH:
+ *params = (GLint) ctx->Line.Width;
+ break;
+ case GL_LINE_WIDTH_GRANULARITY:
+ *params = (GLint) LINE_WIDTH_GRANULARITY;
+ break;
+ case GL_LINE_WIDTH_RANGE:
+ params[0] = (GLint) MIN_LINE_WIDTH;
+ params[1] = (GLint) MAX_LINE_WIDTH;
+ break;
+ case GL_LIST_BASE:
+ *params = (GLint) ctx->List.ListBase;
+ break;
+ case GL_LIST_INDEX:
+ *params = (GLint) ctx->CurrentListNum;
+ break;
+ case GL_LIST_MODE:
+ *params = ctx->ExecuteFlag ? (GLint) GL_COMPILE_AND_EXECUTE
+ : (GLint) GL_COMPILE;
+ break;
+ case GL_INDEX_LOGIC_OP:
+ *params = (GLint) ctx->Color.IndexLogicOpEnabled;
+ break;
+ case GL_COLOR_LOGIC_OP:
+ *params = (GLint) ctx->Color.ColorLogicOpEnabled;
+ break;
+ case GL_LOGIC_OP_MODE:
+ *params = (GLint) ctx->Color.LogicOp;
+ break;
+ case GL_MAP1_COLOR_4:
+ *params = (GLint) ctx->Eval.Map1Color4;
+ break;
+ case GL_MAP1_GRID_DOMAIN:
+ params[0] = (GLint) ctx->Eval.MapGrid1u1;
+ params[1] = (GLint) ctx->Eval.MapGrid1u2;
+ break;
+ case GL_MAP1_GRID_SEGMENTS:
+ *params = (GLint) ctx->Eval.MapGrid1un;
+ break;
+ case GL_MAP1_INDEX:
+ *params = (GLint) ctx->Eval.Map1Index;
+ break;
+ case GL_MAP1_NORMAL:
+ *params = (GLint) ctx->Eval.Map1Normal;
+ break;
+ case GL_MAP1_TEXTURE_COORD_1:
+ *params = (GLint) ctx->Eval.Map1TextureCoord1;
+ break;
+ case GL_MAP1_TEXTURE_COORD_2:
+ *params = (GLint) ctx->Eval.Map1TextureCoord2;
+ break;
+ case GL_MAP1_TEXTURE_COORD_3:
+ *params = (GLint) ctx->Eval.Map1TextureCoord3;
+ break;
+ case GL_MAP1_TEXTURE_COORD_4:
+ *params = (GLint) ctx->Eval.Map1TextureCoord4;
+ break;
+ case GL_MAP1_VERTEX_3:
+ *params = (GLint) ctx->Eval.Map1Vertex3;
+ break;
+ case GL_MAP1_VERTEX_4:
+ *params = (GLint) ctx->Eval.Map1Vertex4;
+ break;
+ case GL_MAP2_COLOR_4:
+ *params = (GLint) ctx->Eval.Map2Color4;
+ break;
+ case GL_MAP2_GRID_DOMAIN:
+ params[0] = (GLint) ctx->Eval.MapGrid2u1;
+ params[1] = (GLint) ctx->Eval.MapGrid2u2;
+ params[2] = (GLint) ctx->Eval.MapGrid2v1;
+ params[3] = (GLint) ctx->Eval.MapGrid2v2;
+ break;
+ case GL_MAP2_GRID_SEGMENTS:
+ params[0] = (GLint) ctx->Eval.MapGrid2un;
+ params[1] = (GLint) ctx->Eval.MapGrid2vn;
+ break;
+ case GL_MAP2_INDEX:
+ *params = (GLint) ctx->Eval.Map2Index;
+ break;
+ case GL_MAP2_NORMAL:
+ *params = (GLint) ctx->Eval.Map2Normal;
+ break;
+ case GL_MAP2_TEXTURE_COORD_1:
+ *params = (GLint) ctx->Eval.Map2TextureCoord1;
+ break;
+ case GL_MAP2_TEXTURE_COORD_2:
+ *params = (GLint) ctx->Eval.Map2TextureCoord2;
+ break;
+ case GL_MAP2_TEXTURE_COORD_3:
+ *params = (GLint) ctx->Eval.Map2TextureCoord3;
+ break;
+ case GL_MAP2_TEXTURE_COORD_4:
+ *params = (GLint) ctx->Eval.Map2TextureCoord4;
+ break;
+ case GL_MAP2_VERTEX_3:
+ *params = (GLint) ctx->Eval.Map2Vertex3;
+ break;
+ case GL_MAP2_VERTEX_4:
+ *params = (GLint) ctx->Eval.Map2Vertex4;
+ break;
+ case GL_MAP_COLOR:
+ *params = (GLint) ctx->Pixel.MapColorFlag;
+ break;
+ case GL_MAP_STENCIL:
+ *params = (GLint) ctx->Pixel.MapStencilFlag;
+ break;
+ case GL_MATRIX_MODE:
+ *params = (GLint) ctx->Transform.MatrixMode;
+ break;
+ case GL_MAX_ATTRIB_STACK_DEPTH:
+ *params = (GLint) MAX_ATTRIB_STACK_DEPTH;
+ break;
+ case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH:
+ *params = (GLint) MAX_CLIENT_ATTRIB_STACK_DEPTH;
+ break;
+ case GL_MAX_CLIP_PLANES:
+ *params = (GLint) MAX_CLIP_PLANES;
+ break;
+ case GL_MAX_ELEMENTS_VERTICES: /* GL_VERSION_1_2 */
+ *params = VB_MAX;
+ break;
+ case GL_MAX_ELEMENTS_INDICES: /* GL_VERSION_1_2 */
+ *params = VB_MAX;
+ break;
+ case GL_MAX_EVAL_ORDER:
+ *params = (GLint) MAX_EVAL_ORDER;
+ break;
+ case GL_MAX_LIGHTS:
+ *params = (GLint) MAX_LIGHTS;
+ break;
+ case GL_MAX_LIST_NESTING:
+ *params = (GLint) MAX_LIST_NESTING;
+ break;
+ case GL_MAX_MODELVIEW_STACK_DEPTH:
+ *params = (GLint) MAX_MODELVIEW_STACK_DEPTH;
+ break;
+ case GL_MAX_NAME_STACK_DEPTH:
+ *params = (GLint) MAX_NAME_STACK_DEPTH;
+ break;
+ case GL_MAX_PIXEL_MAP_TABLE:
+ *params = (GLint) MAX_PIXEL_MAP_TABLE;
+ break;
+ case GL_MAX_PROJECTION_STACK_DEPTH:
+ *params = (GLint) MAX_PROJECTION_STACK_DEPTH;
+ break;
+ case GL_MAX_TEXTURE_SIZE:
+ case GL_MAX_3D_TEXTURE_SIZE:
+ *params = ctx->Const.MaxTextureSize;
+ break;
+ case GL_MAX_TEXTURE_STACK_DEPTH:
+ *params = (GLint) MAX_TEXTURE_STACK_DEPTH;
+ break;
+ case GL_MAX_VIEWPORT_DIMS:
+ params[0] = (GLint) MAX_WIDTH;
+ params[1] = (GLint) MAX_HEIGHT;
+ break;
+ case GL_MODELVIEW_MATRIX:
+ for (i=0;i<16;i++) {
+ params[i] = (GLint) ctx->ModelView.m[i];
+ }
+ break;
+ case GL_MODELVIEW_STACK_DEPTH:
+ *params = (GLint) (ctx->ModelViewStackDepth + 1);
+ break;
+ case GL_NAME_STACK_DEPTH:
+ *params = (GLint) ctx->Select.NameStackDepth;
+ break;
+ case GL_NORMALIZE:
+ *params = (GLint) ctx->Transform.Normalize;
+ break;
+ case GL_PACK_ALIGNMENT:
+ *params = ctx->Pack.Alignment;
+ break;
+ case GL_PACK_LSB_FIRST:
+ *params = (GLint) ctx->Pack.LsbFirst;
+ break;
+ case GL_PACK_ROW_LENGTH:
+ *params = ctx->Pack.RowLength;
+ break;
+ case GL_PACK_SKIP_PIXELS:
+ *params = ctx->Pack.SkipPixels;
+ break;
+ case GL_PACK_SKIP_ROWS:
+ *params = ctx->Pack.SkipRows;
+ break;
+ case GL_PACK_SWAP_BYTES:
+ *params = (GLint) ctx->Pack.SwapBytes;
+ break;
+ case GL_PACK_SKIP_IMAGES_EXT:
+ *params = ctx->Pack.SkipImages;
+ break;
+ case GL_PACK_IMAGE_HEIGHT_EXT:
+ *params = ctx->Pack.ImageHeight;
+ break;
+ case GL_PERSPECTIVE_CORRECTION_HINT:
+ *params = (GLint) ctx->Hint.PerspectiveCorrection;
+ break;
+ case GL_PIXEL_MAP_A_TO_A_SIZE:
+ *params = ctx->Pixel.MapAtoAsize;
+ break;
+ case GL_PIXEL_MAP_B_TO_B_SIZE:
+ *params = ctx->Pixel.MapBtoBsize;
+ break;
+ case GL_PIXEL_MAP_G_TO_G_SIZE:
+ *params = ctx->Pixel.MapGtoGsize;
+ break;
+ case GL_PIXEL_MAP_I_TO_A_SIZE:
+ *params = ctx->Pixel.MapItoAsize;
+ break;
+ case GL_PIXEL_MAP_I_TO_B_SIZE:
+ *params = ctx->Pixel.MapItoBsize;
+ break;
+ case GL_PIXEL_MAP_I_TO_G_SIZE:
+ *params = ctx->Pixel.MapItoGsize;
+ break;
+ case GL_PIXEL_MAP_I_TO_I_SIZE:
+ *params = ctx->Pixel.MapItoIsize;
+ break;
+ case GL_PIXEL_MAP_I_TO_R_SIZE:
+ *params = ctx->Pixel.MapItoRsize;
+ break;
+ case GL_PIXEL_MAP_R_TO_R_SIZE:
+ *params = ctx->Pixel.MapRtoRsize;
+ break;
+ case GL_PIXEL_MAP_S_TO_S_SIZE:
+ *params = ctx->Pixel.MapStoSsize;
+ break;
+ case GL_POINT_SIZE:
+ *params = (GLint) ctx->Point.Size;
+ break;
+ case GL_POINT_SIZE_GRANULARITY:
+ *params = (GLint) POINT_SIZE_GRANULARITY;
+ break;
+ case GL_POINT_SIZE_RANGE:
+ params[0] = (GLint) MIN_POINT_SIZE;
+ params[1] = (GLint) MAX_POINT_SIZE;
+ break;
+ case GL_POINT_SMOOTH:
+ *params = (GLint) ctx->Point.SmoothFlag;
+ break;
+ case GL_POINT_SMOOTH_HINT:
+ *params = (GLint) ctx->Hint.PointSmooth;
+ break;
+ case GL_POINT_SIZE_MIN_EXT:
+ *params = (GLint) (ctx->Point.MinSize);
+ break;
+ case GL_POINT_SIZE_MAX_EXT:
+ *params = (GLint) (ctx->Point.MaxSize);
+ break;
+ case GL_POINT_FADE_THRESHOLD_SIZE_EXT:
+ *params = (GLint) (ctx->Point.Threshold);
+ break;
+ case GL_DISTANCE_ATTENUATION_EXT:
+ params[0] = (GLint) (ctx->Point.Params[0]);
+ params[1] = (GLint) (ctx->Point.Params[1]);
+ params[2] = (GLint) (ctx->Point.Params[2]);
+ break;
+ case GL_POLYGON_MODE:
+ params[0] = (GLint) ctx->Polygon.FrontMode;
+ params[1] = (GLint) ctx->Polygon.BackMode;
+ break;
+#ifdef GL_EXT_polygon_offset
+ case GL_POLYGON_OFFSET_BIAS_EXT:
+ *params = (GLint) ctx->Polygon.OffsetUnits;
+ break;
+#endif
+ case GL_POLYGON_OFFSET_FACTOR:
+ *params = (GLint) ctx->Polygon.OffsetFactor;
+ break;
+ case GL_POLYGON_OFFSET_UNITS:
+ *params = (GLint) ctx->Polygon.OffsetUnits;
+ break;
+ case GL_POLYGON_SMOOTH:
+ *params = (GLint) ctx->Polygon.SmoothFlag;
+ break;
+ case GL_POLYGON_SMOOTH_HINT:
+ *params = (GLint) ctx->Hint.PolygonSmooth;
+ break;
+ case GL_POLYGON_STIPPLE:
+ *params = (GLint) ctx->Polygon.StippleFlag;
+ break;
+ case GL_PROJECTION_MATRIX:
+ for (i=0;i<16;i++) {
+ params[i] = (GLint) ctx->ProjectionMatrix.m[i];
+ }
+ break;
+ case GL_PROJECTION_STACK_DEPTH:
+ *params = (GLint) (ctx->ProjectionStackDepth + 1);
+ break;
+ case GL_READ_BUFFER:
+ *params = (GLint) ctx->Pixel.ReadBuffer;
+ break;
+ case GL_RED_BIAS:
+ *params = (GLint) ctx->Pixel.RedBias;
+ break;
+ case GL_RED_BITS:
+ *params = (GLint) ctx->Visual->RedBits;
+ break;
+ case GL_RED_SCALE:
+ *params = (GLint) ctx->Pixel.RedScale;
+ break;
+ case GL_RENDER_MODE:
+ *params = (GLint) ctx->RenderMode;
+ break;
+ case GL_RGBA_MODE:
+ *params = (GLint) ctx->Visual->RGBAflag;
+ break;
+ case GL_SCISSOR_BOX:
+ params[0] = (GLint) ctx->Scissor.X;
+ params[1] = (GLint) ctx->Scissor.Y;
+ params[2] = (GLint) ctx->Scissor.Width;
+ params[3] = (GLint) ctx->Scissor.Height;
+ break;
+ case GL_SCISSOR_TEST:
+ *params = (GLint) ctx->Scissor.Enabled;
+ break;
+ case GL_SELECTION_BUFFER_SIZE:
+ *params = (GLint) ctx->Select.BufferSize;
+ break;
+ case GL_SHADE_MODEL:
+ *params = (GLint) ctx->Light.ShadeModel;
+ break;
+ case GL_SHARED_TEXTURE_PALETTE_EXT:
+ *params = (GLint) ctx->Texture.SharedPalette;
+ break;
+ case GL_STENCIL_BITS:
+ *params = ctx->Visual->StencilBits;
+ break;
+ case GL_STENCIL_CLEAR_VALUE:
+ *params = (GLint) ctx->Stencil.Clear;
+ break;
+ case GL_STENCIL_FAIL:
+ *params = (GLint) ctx->Stencil.FailFunc;
+ break;
+ case GL_STENCIL_FUNC:
+ *params = (GLint) ctx->Stencil.Function;
+ break;
+ case GL_STENCIL_PASS_DEPTH_FAIL:
+ *params = (GLint) ctx->Stencil.ZFailFunc;
+ break;
+ case GL_STENCIL_PASS_DEPTH_PASS:
+ *params = (GLint) ctx->Stencil.ZPassFunc;
+ break;
+ case GL_STENCIL_REF:
+ *params = (GLint) ctx->Stencil.Ref;
+ break;
+ case GL_STENCIL_TEST:
+ *params = (GLint) ctx->Stencil.Enabled;
+ break;
+ case GL_STENCIL_VALUE_MASK:
+ *params = (GLint) ctx->Stencil.ValueMask;
+ break;
+ case GL_STENCIL_WRITEMASK:
+ *params = (GLint) ctx->Stencil.WriteMask;
+ break;
+ case GL_STEREO:
+ *params = (GLint) ctx->Visual->StereoFlag;
+ break;
+ case GL_SUBPIXEL_BITS:
+ *params = 0; /* TODO */
+ break;
+ case GL_TEXTURE_1D:
+ *params = gl_IsEnabled(ctx, GL_TEXTURE_1D) ? 1 : 0;
+ break;
+ case GL_TEXTURE_2D:
+ *params = gl_IsEnabled(ctx, GL_TEXTURE_2D) ? 1 : 0;
+ break;
+ case GL_TEXTURE_3D:
+ *params = gl_IsEnabled(ctx, GL_TEXTURE_3D) ? 1 : 0;
+ break;
+ case GL_TEXTURE_BINDING_1D:
+ *params = textureUnit->CurrentD[1]->Name;
+ break;
+ case GL_TEXTURE_BINDING_2D:
+ *params = textureUnit->CurrentD[2]->Name;
+ break;
+ case GL_TEXTURE_BINDING_3D:
+ *params = textureUnit->CurrentD[3]->Name;
+ break;
+ case GL_TEXTURE_ENV_COLOR:
+ params[0] = FLOAT_TO_INT( textureUnit->EnvColor[0] );
+ params[1] = FLOAT_TO_INT( textureUnit->EnvColor[1] );
+ params[2] = FLOAT_TO_INT( textureUnit->EnvColor[2] );
+ params[3] = FLOAT_TO_INT( textureUnit->EnvColor[3] );
+ break;
+ case GL_TEXTURE_ENV_MODE:
+ *params = (GLint) textureUnit->EnvMode;
+ break;
+ case GL_TEXTURE_GEN_S:
+ *params = (textureUnit->TexGenEnabled & S_BIT) ? 1 : 0;
+ break;
+ case GL_TEXTURE_GEN_T:
+ *params = (textureUnit->TexGenEnabled & T_BIT) ? 1 : 0;
+ break;
+ case GL_TEXTURE_GEN_R:
+ *params = (textureUnit->TexGenEnabled & R_BIT) ? 1 : 0;
+ break;
+ case GL_TEXTURE_GEN_Q:
+ *params = (textureUnit->TexGenEnabled & Q_BIT) ? 1 : 0;
+ break;
+ case GL_TEXTURE_MATRIX:
+ for (i=0;i<16;i++) {
+ params[i] = (GLint) ctx->TextureMatrix[texTransformUnit].m[i];
+ }
+ break;
+ case GL_TEXTURE_STACK_DEPTH:
+ *params = (GLint) (ctx->TextureStackDepth[texTransformUnit] + 1);
+ break;
+ case GL_UNPACK_ALIGNMENT:
+ *params = ctx->Unpack.Alignment;
+ break;
+ case GL_UNPACK_LSB_FIRST:
+ *params = (GLint) ctx->Unpack.LsbFirst;
+ break;
+ case GL_UNPACK_ROW_LENGTH:
+ *params = ctx->Unpack.RowLength;
+ break;
+ case GL_UNPACK_SKIP_PIXELS:
+ *params = ctx->Unpack.SkipPixels;
+ break;
+ case GL_UNPACK_SKIP_ROWS:
+ *params = ctx->Unpack.SkipRows;
+ break;
+ case GL_UNPACK_SWAP_BYTES:
+ *params = (GLint) ctx->Unpack.SwapBytes;
+ break;
+ case GL_UNPACK_SKIP_IMAGES_EXT:
+ *params = ctx->Unpack.SkipImages;
+ break;
+ case GL_UNPACK_IMAGE_HEIGHT_EXT:
+ *params = ctx->Unpack.ImageHeight;
+ break;
+ case GL_VIEWPORT:
+ params[0] = (GLint) ctx->Viewport.X;
+ params[1] = (GLint) ctx->Viewport.Y;
+ params[2] = (GLint) ctx->Viewport.Width;
+ params[3] = (GLint) ctx->Viewport.Height;
+ break;
+ case GL_ZOOM_X:
+ *params = (GLint) ctx->Pixel.ZoomX;
+ break;
+ case GL_ZOOM_Y:
+ *params = (GLint) ctx->Pixel.ZoomY;
+ break;
+ case GL_VERTEX_ARRAY_SIZE:
+ *params = ctx->Array.Vertex.Size;
+ break;
+ case GL_VERTEX_ARRAY_TYPE:
+ *params = ctx->Array.Vertex.Type;
+ break;
+ case GL_VERTEX_ARRAY_STRIDE:
+ *params = ctx->Array.Vertex.Stride;
+ break;
+ case GL_VERTEX_ARRAY_COUNT_EXT:
+ *params = 0;
+ break;
+ case GL_NORMAL_ARRAY_TYPE:
+ *params = ctx->Array.Normal.Type;
+ break;
+ case GL_NORMAL_ARRAY_STRIDE:
+ *params = ctx->Array.Normal.Stride;
+ break;
+ case GL_NORMAL_ARRAY_COUNT_EXT:
+ *params = 0;
+ break;
+ case GL_COLOR_ARRAY_SIZE:
+ *params = ctx->Array.Color.Size;
+ break;
+ case GL_COLOR_ARRAY_TYPE:
+ *params = ctx->Array.Color.Type;
+ break;
+ case GL_COLOR_ARRAY_STRIDE:
+ *params = ctx->Array.Color.Stride;
+ break;
+ case GL_COLOR_ARRAY_COUNT_EXT:
+ *params = 0;
+ break;
+ case GL_INDEX_ARRAY_TYPE:
+ *params = ctx->Array.Index.Type;
+ break;
+ case GL_INDEX_ARRAY_STRIDE:
+ *params = ctx->Array.Index.Stride;
+ break;
+ case GL_INDEX_ARRAY_COUNT_EXT:
+ *params = 0;
+ break;
+ case GL_TEXTURE_COORD_ARRAY_SIZE:
+ *params = ctx->Array.TexCoord[texUnit].Size;
+ break;
+ case GL_TEXTURE_COORD_ARRAY_TYPE:
+ *params = ctx->Array.TexCoord[texUnit].Type;
+ break;
+ case GL_TEXTURE_COORD_ARRAY_STRIDE:
+ *params = ctx->Array.TexCoord[texUnit].Stride;
+ break;
+ case GL_TEXTURE_COORD_ARRAY_COUNT_EXT:
+ *params = 0;
+ break;
+ case GL_EDGE_FLAG_ARRAY_STRIDE:
+ *params = ctx->Array.EdgeFlag.Stride;
+ break;
+ case GL_EDGE_FLAG_ARRAY_COUNT_EXT:
+ *params = 0;
+ break;
+
+ case GL_MAX_TEXTURE_UNITS_ARB:
+ *params = ctx->Const.MaxTextureUnits;
+ break;
+ case GL_ACTIVE_TEXTURE_ARB:
+ *params = GL_TEXTURE0_ARB + ctx->Texture.CurrentUnit;
+ break;
+ case GL_CLIENT_ACTIVE_TEXTURE_ARB:
+ *params = GL_TEXTURE0_ARB + ctx->Array.ActiveTexture;
+ break;
+
+
+ /* GL_PGI_misc_hints */
+ case GL_STRICT_DEPTHFUNC_HINT_PGI:
+ *params = (GL_NICEST);
+ break;
+ case GL_STRICT_LIGHTING_HINT_PGI:
+ *params = (ctx->Hint.StrictLighting);
+ break;
+ case GL_STRICT_SCISSOR_HINT_PGI:
+ case GL_FULL_STIPPLE_HINT_PGI:
+ *params = (GL_TRUE);
+ break;
+ case GL_CONSERVE_MEMORY_HINT_PGI:
+ *params = (GL_FALSE);
+ break;
+ case GL_ALWAYS_FAST_HINT_PGI:
+ *params = (ctx->Hint.AllowDrawWin == GL_TRUE &&
+ ctx->Hint.AllowDrawSpn == GL_FALSE &&
+ ctx->Hint.AllowDrawMem == GL_FALSE);
+ break;
+ case GL_ALWAYS_SOFT_HINT_PGI:
+ *params = (ctx->Hint.AllowDrawWin == GL_TRUE &&
+ ctx->Hint.AllowDrawSpn == GL_TRUE &&
+ ctx->Hint.AllowDrawMem == GL_TRUE);
+ break;
+ case GL_ALLOW_DRAW_OBJ_HINT_PGI:
+ *params = GL_TRUE;
+ break;
+ case GL_ALLOW_DRAW_WIN_HINT_PGI:
+ *params = ctx->Hint.AllowDrawWin;
+ break;
+ case GL_ALLOW_DRAW_SPN_HINT_PGI:
+ *params = ctx->Hint.AllowDrawSpn;
+ break;
+ case GL_ALLOW_DRAW_MEM_HINT_PGI:
+ *params = ctx->Hint.AllowDrawMem;
+ break;
+ case GL_CLIP_NEAR_HINT_PGI:
+ case GL_CLIP_FAR_HINT_PGI:
+ *params = GL_TRUE;
+ break;
+ case GL_WIDE_LINE_HINT_PGI:
+ *params = GL_DONT_CARE;
+ break;
+ case GL_BACK_NORMALS_HINT_PGI:
+ *params = (GL_TRUE);
+ break;
+ case GL_NATIVE_GRAPHICS_HANDLE_PGI:
+ *params = 0;
+ break;
+
+ /* GL_EXT_compiled_vertex_array
+ */
+ case GL_ARRAY_ELEMENT_LOCK_FIRST_SGI:
+ *params = ctx->Array.LockFirst;
+ break;
+
+ case GL_ARRAY_ELEMENT_LOCK_COUNT_SGI:
+ *params = ctx->Array.LockCount;
+ break;
+
+ default:
+ printf("invalid enum: %x\n", pname);
+ gl_error( ctx, GL_INVALID_ENUM, "glGetIntegerv" );
+ }
+}
+
+
+
+void gl_GetPointerv( GLcontext *ctx, GLenum pname, GLvoid **params )
+{
+ GLuint texUnit = ctx->Texture.CurrentUnit;
+ /*GLuint texTransformUnit = ctx->Texture.CurrentTransformUnit;*/
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ fprintf(stderr, "glGetPointerv %s\n", gl_lookup_enum_by_nr(pname));
+
+ switch (pname) {
+ case GL_VERTEX_ARRAY_POINTER:
+ *params = ctx->Array.Vertex.Ptr;
+ break;
+ case GL_NORMAL_ARRAY_POINTER:
+ *params = ctx->Array.Normal.Ptr;
+ break;
+ case GL_COLOR_ARRAY_POINTER:
+ *params = ctx->Array.Color.Ptr;
+ break;
+ case GL_INDEX_ARRAY_POINTER:
+ *params = ctx->Array.Index.Ptr;
+ break;
+ case GL_TEXTURE_COORD_ARRAY_POINTER:
+ *params = ctx->Array.TexCoord[texUnit].Ptr;
+ break;
+ case GL_EDGE_FLAG_ARRAY_POINTER:
+ *params = ctx->Array.EdgeFlag.Ptr;
+ break;
+ case GL_FEEDBACK_BUFFER_POINTER:
+ *params = ctx->Feedback.Buffer;
+ break;
+ case GL_SELECTION_BUFFER_POINTER:
+ *params = ctx->Select.Buffer;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetPointerv" );
+ return;
+ }
+}
diff --git a/src/mesa/main/get.h b/src/mesa/main/get.h
new file mode 100644
index 0000000000..c4e55041f6
--- /dev/null
+++ b/src/mesa/main/get.h
@@ -0,0 +1,48 @@
+/* $Id: get.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef GET_H
+#define GET_H
+
+
+#include "types.h"
+
+
+extern void gl_GetBooleanv( GLcontext *ctx, GLenum pname, GLboolean *params );
+
+extern void gl_GetDoublev( GLcontext *ctx, GLenum pname, GLdouble *params );
+
+extern void gl_GetFloatv( GLcontext *ctx, GLenum pname, GLfloat *params );
+
+extern void gl_GetIntegerv( GLcontext *ctx, GLenum pname, GLint *params );
+
+
+#endif
+
diff --git a/src/mesa/main/hash.c b/src/mesa/main/hash.c
new file mode 100644
index 0000000000..3d533c82e8
--- /dev/null
+++ b/src/mesa/main/hash.c
@@ -0,0 +1,295 @@
+/* $Id: hash.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "hash.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+/*
+ * Generic hash table. Only dependency is the GLuint datatype.
+ *
+ * This is used to implement display list and texture object lookup.
+ * NOTE: key=0 is illegal.
+ */
+
+
+#define TABLE_SIZE 1024
+
+struct HashEntry {
+ GLuint Key;
+ void *Data;
+ struct HashEntry *Next;
+};
+
+struct HashTable {
+ struct HashEntry *Table[TABLE_SIZE];
+ GLuint MaxKey;
+};
+
+
+
+/*
+ * Return pointer to a new, empty hash table.
+ */
+struct HashTable *NewHashTable(void)
+{
+ return (struct HashTable *) calloc(sizeof (struct HashTable), 1);
+}
+
+
+
+/*
+ * Delete a hash table.
+ */
+void DeleteHashTable(struct HashTable *table)
+{
+ GLuint i;
+ assert(table);
+ for (i=0;i<TABLE_SIZE;i++) {
+ struct HashEntry *entry = table->Table[i];
+ while (entry) {
+ struct HashEntry *next = entry->Next;
+ free(entry);
+ entry = next;
+ }
+ }
+ free(table);
+}
+
+
+
+/*
+ * Lookup an entry in the hash table.
+ * Input: table - the hash table
+ * key - the key
+ * Return: user data pointer or NULL if key not in table
+ */
+void *HashLookup(const struct HashTable *table, GLuint key)
+{
+ GLuint pos;
+ const struct HashEntry *entry;
+
+ assert(table);
+ assert(key);
+
+ pos = key & (TABLE_SIZE-1);
+ entry = table->Table[pos];
+ while (entry) {
+ if (entry->Key == key) {
+ return entry->Data;
+ }
+ entry = entry->Next;
+ }
+ return NULL;
+}
+
+
+
+/*
+ * Insert into the hash table. If an entry with this key already exists
+ * we'll replace the existing entry.
+ * Input: table - the hash table
+ * key - the key (not zero)
+ * data - pointer to user data
+ */
+void HashInsert(struct HashTable *table, GLuint key, void *data)
+{
+ /* search for existing entry with this key */
+ GLuint pos;
+ struct HashEntry *entry;
+
+ assert(table);
+ assert(key);
+
+ if (key > table->MaxKey)
+ table->MaxKey = key;
+
+ pos = key & (TABLE_SIZE-1);
+ entry = table->Table[pos];
+ while (entry) {
+ if (entry->Key == key) {
+ /* replace entry's data */
+ entry->Data = data;
+ return;
+ }
+ entry = entry->Next;
+ }
+
+ /* alloc and insert new table entry */
+ entry = (struct HashEntry *) calloc(sizeof(struct HashEntry), 1);
+ entry->Key = key;
+ entry->Data = data;
+ entry->Next = table->Table[pos];
+ table->Table[pos] = entry;
+}
+
+
+
+/*
+ * Remove an entry from the hash table.
+ * Input: table - the hash table
+ * key - key of entry to remove
+ */
+void HashRemove(struct HashTable *table, GLuint key)
+{
+ GLuint pos;
+ struct HashEntry *entry, *prev;
+
+ assert(table);
+ assert(key);
+
+ pos = key & (TABLE_SIZE-1);
+ prev = NULL;
+ entry = table->Table[pos];
+ while (entry) {
+ if (entry->Key == key) {
+ /* found it! */
+ if (prev) {
+ prev->Next = entry->Next;
+ }
+ else {
+ table->Table[pos] = entry->Next;
+ }
+ free(entry);
+ return;
+ }
+ prev = entry;
+ entry = entry->Next;
+ }
+}
+
+
+
+/*
+ * Return the key of the "first" entry in the hash table.
+ * By calling this function until zero is returned we can get
+ * the keys of all entries in the table.
+ */
+GLuint HashFirstEntry(const struct HashTable *table)
+{
+ GLuint pos;
+ assert(table);
+ for (pos=0; pos < TABLE_SIZE; pos++) {
+ if (table->Table[pos])
+ return table->Table[pos]->Key;
+ }
+ return 0;
+}
+
+
+
+/*
+ * Dump contents of hash table for debugging.
+ */
+void HashPrint(const struct HashTable *table)
+{
+ GLuint i;
+ assert(table);
+ for (i=0;i<TABLE_SIZE;i++) {
+ const struct HashEntry *entry = table->Table[i];
+ while (entry) {
+ printf("%u %p\n", entry->Key, entry->Data);
+ entry = entry->Next;
+ }
+ }
+}
+
+
+
+/*
+ * Find a block of 'numKeys' adjacent unused hash keys.
+ * Input: table - the hash table
+ * numKeys - number of keys needed
+ * Return: startint key of free block or 0 if failure
+ */
+GLuint HashFindFreeKeyBlock(const struct HashTable *table, GLuint numKeys)
+{
+ GLuint maxKey = ~((GLuint) 0);
+ if (maxKey - numKeys > table->MaxKey) {
+ /* the quick solution */
+ return table->MaxKey + 1;
+ }
+ else {
+ /* the slow solution */
+ GLuint freeCount = 0;
+ GLuint freeStart = 0;
+ GLuint key;
+ for (key=0; key!=maxKey; key++) {
+ if (HashLookup(table, key)) {
+ /* darn, this key is already in use */
+ freeCount = 0;
+ freeStart = key+1;
+ }
+ else {
+ /* this key not in use, check if we've found enough */
+ freeCount++;
+ if (freeCount == numKeys) {
+ return freeStart;
+ }
+ }
+ }
+ /* cannot allocate a block of numKeys consecutive keys */
+ return 0;
+ }
+}
+
+
+
+#ifdef HASH_TEST_HARNESS
+int main(int argc, char *argv[])
+{
+ int a, b, c;
+ struct HashTable *t;
+
+ printf("&a = %p\n", &a);
+ printf("&b = %p\n", &b);
+
+ t = NewHashTable();
+ HashInsert(t, 501, &a);
+ HashInsert(t, 10, &c);
+ HashInsert(t, 0xfffffff8, &b);
+ HashPrint(t);
+ printf("Find 501: %p\n", HashLookup(t,501));
+ printf("Find 1313: %p\n", HashLookup(t,1313));
+ printf("Find block of 100: %d\n", HashFindFreeKeyBlock(t, 100));
+ DeleteHashTable(t);
+
+ return 0;
+}
+#endif
diff --git a/src/mesa/main/hash.h b/src/mesa/main/hash.h
new file mode 100644
index 0000000000..a38159ce09
--- /dev/null
+++ b/src/mesa/main/hash.h
@@ -0,0 +1,59 @@
+/* $Id: hash.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef HASH_H
+#define HASH_H
+
+
+#include "GL/gl.h"
+
+
+struct HashTable;
+
+
+
+extern struct HashTable *NewHashTable(void);
+
+extern void DeleteHashTable(struct HashTable *table);
+
+extern void *HashLookup(const struct HashTable *table, GLuint key);
+
+extern void HashInsert(struct HashTable *table, GLuint key, void *data);
+
+extern void HashRemove(struct HashTable *table, GLuint key);
+
+extern GLuint HashFirstEntry(const struct HashTable *table);
+
+extern void HashPrint(const struct HashTable *table);
+
+extern GLuint HashFindFreeKeyBlock(const struct HashTable *table, GLuint numKeys);
+
+
+#endif
diff --git a/src/mesa/main/image.c b/src/mesa/main/image.c
new file mode 100644
index 0000000000..46c33a67d9
--- /dev/null
+++ b/src/mesa/main/image.c
@@ -0,0 +1,2417 @@
+/* $Id: image.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include "context.h"
+#include "image.h"
+#include "macros.h"
+#include "mmath.h"
+#include "pixel.h"
+#include "types.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+
+/*
+ * Flip the 8 bits in each byte of the given array.
+ */
+void gl_flip_bytes( GLubyte *p, GLuint n )
+{
+ register GLuint i, a, b;
+
+ for (i=0;i<n;i++) {
+ b = (GLuint) p[i];
+ a = ((b & 0x01) << 7) |
+ ((b & 0x02) << 5) |
+ ((b & 0x04) << 3) |
+ ((b & 0x08) << 1) |
+ ((b & 0x10) >> 1) |
+ ((b & 0x20) >> 3) |
+ ((b & 0x40) >> 5) |
+ ((b & 0x80) >> 7);
+ p[i] = (GLubyte) a;
+ }
+}
+
+
+/*
+ * Flip the order of the 2 bytes in each word in the given array.
+ */
+void gl_swap2( GLushort *p, GLuint n )
+{
+ register GLuint i;
+
+ for (i=0;i<n;i++) {
+ p[i] = (p[i] >> 8) | ((p[i] << 8) & 0xff00);
+ }
+}
+
+
+
+/*
+ * Flip the order of the 4 bytes in each word in the given array.
+ */
+void gl_swap4( GLuint *p, GLuint n )
+{
+ register GLuint i, a, b;
+
+ for (i=0;i<n;i++) {
+ b = p[i];
+ a = (b >> 24)
+ | ((b >> 8) & 0xff00)
+ | ((b << 8) & 0xff0000)
+ | ((b << 24) & 0xff000000);
+ p[i] = a;
+ }
+}
+
+
+
+
+/*
+ * Return the size, in bytes, of the given GL datatype.
+ * Return 0 if GL_BITMAP.
+ * Return -1 if invalid type enum.
+ */
+GLint gl_sizeof_type( GLenum type )
+{
+ switch (type) {
+ case GL_BITMAP:
+ return 0;
+ case GL_UNSIGNED_BYTE:
+ return sizeof(GLubyte);
+ case GL_BYTE:
+ return sizeof(GLbyte);
+ case GL_UNSIGNED_SHORT:
+ return sizeof(GLushort);
+ case GL_SHORT:
+ return sizeof(GLshort);
+ case GL_UNSIGNED_INT:
+ return sizeof(GLuint);
+ case GL_INT:
+ return sizeof(GLint);
+ case GL_FLOAT:
+ return sizeof(GLfloat);
+ default:
+ return -1;
+ }
+}
+
+
+/*
+ * Same as gl_sizeof_packed_type() but we also accept the
+ * packed pixel format datatypes.
+ */
+GLint gl_sizeof_packed_type( GLenum type )
+{
+ switch (type) {
+ case GL_BITMAP:
+ return 0;
+ case GL_UNSIGNED_BYTE:
+ return sizeof(GLubyte);
+ case GL_BYTE:
+ return sizeof(GLbyte);
+ case GL_UNSIGNED_SHORT:
+ return sizeof(GLushort);
+ case GL_SHORT:
+ return sizeof(GLshort);
+ case GL_UNSIGNED_INT:
+ return sizeof(GLuint);
+ case GL_INT:
+ return sizeof(GLint);
+ case GL_FLOAT:
+ return sizeof(GLfloat);
+ case GL_UNSIGNED_BYTE_3_3_2:
+ return sizeof(GLubyte);
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ return sizeof(GLubyte);
+ case GL_UNSIGNED_SHORT_5_6_5:
+ return sizeof(GLshort);
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ return sizeof(GLshort);
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ return sizeof(GLshort);
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ return sizeof(GLshort);
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ return sizeof(GLshort);
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ return sizeof(GLshort);
+ case GL_UNSIGNED_INT_8_8_8_8:
+ return sizeof(GLuint);
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ return sizeof(GLuint);
+ case GL_UNSIGNED_INT_10_10_10_2:
+ return sizeof(GLuint);
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return sizeof(GLuint);
+ default:
+ return -1;
+ }
+}
+
+
+
+/*
+ * Return the number of components in a GL enum pixel type.
+ * Return -1 if bad format.
+ */
+GLint gl_components_in_format( GLenum format )
+{
+ switch (format) {
+ 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:
+ case GL_STENCIL_INDEX:
+ case GL_DEPTH_COMPONENT:
+ case GL_RED:
+ case GL_GREEN:
+ case GL_BLUE:
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ return 1;
+ case GL_LUMINANCE_ALPHA:
+ return 2;
+ case GL_RGB:
+ return 3;
+ case GL_RGBA:
+ return 4;
+ case GL_BGR:
+ return 3;
+ case GL_BGRA:
+ return 4;
+ case GL_ABGR_EXT:
+ return 4;
+ default:
+ return -1;
+ }
+}
+
+
+/*
+ * Return bytes per pixel for given format and type
+ * Return -1 if bad format or type.
+ */
+GLint gl_bytes_per_pixel( GLenum format, GLenum type )
+{
+ GLint comps = gl_components_in_format( format );
+ if (comps < 0)
+ return -1;
+
+ switch (type) {
+ case GL_BITMAP:
+ return 0; /* special case */
+ case GL_BYTE:
+ case GL_UNSIGNED_BYTE:
+ return comps * sizeof(GLubyte);
+ case GL_SHORT:
+ case GL_UNSIGNED_SHORT:
+ return comps * sizeof(GLshort);
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ return comps * sizeof(GLint);
+ case GL_FLOAT:
+ return comps * sizeof(GLfloat);
+ case GL_UNSIGNED_BYTE_3_3_2:
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ if (format == GL_RGB || format == GL_BGR)
+ return sizeof(GLubyte);
+ else
+ return -1; /* error */
+ case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ if (format == GL_RGB || format == GL_BGR)
+ return sizeof(GLshort);
+ else
+ return -1; /* error */
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ if (format == GL_RGBA || format == GL_BGRA || format == GL_ABGR_EXT)
+ return sizeof(GLushort);
+ else
+ return -1;
+ case GL_UNSIGNED_INT_8_8_8_8:
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ case GL_UNSIGNED_INT_10_10_10_2:
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ if (format == GL_RGBA || format == GL_BGRA || format == GL_ABGR_EXT)
+ return sizeof(GLuint);
+ else
+ return -1;
+ default:
+ return -1;
+ }
+}
+
+
+/*
+ * Test if the given pixel format and type are legal.
+ * Return GL_TRUE for legal, GL_FALSE for illegal.
+ */
+GLboolean gl_is_legal_format_and_type( GLenum format, GLenum type )
+{
+ switch (format) {
+ case GL_COLOR_INDEX:
+ case GL_STENCIL_INDEX:
+ switch (type) {
+ case GL_BITMAP:
+ case GL_BYTE:
+ case GL_UNSIGNED_BYTE:
+ case GL_SHORT:
+ case GL_UNSIGNED_SHORT:
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ case GL_FLOAT:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+ case GL_RED:
+ case GL_GREEN:
+ case GL_BLUE:
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE_ALPHA:
+ case GL_DEPTH_COMPONENT:
+ case GL_BGR:
+ switch (type) {
+ case GL_BYTE:
+ case GL_UNSIGNED_BYTE:
+ case GL_SHORT:
+ case GL_UNSIGNED_SHORT:
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ case GL_FLOAT:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+ case GL_RGB:
+ switch (type) {
+ case GL_BYTE:
+ case GL_UNSIGNED_BYTE:
+ case GL_SHORT:
+ case GL_UNSIGNED_SHORT:
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ case GL_FLOAT:
+ case GL_UNSIGNED_BYTE_3_3_2:
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+ case GL_RGBA:
+ case GL_BGRA:
+ case GL_ABGR_EXT:
+ switch (type) {
+ case GL_BYTE:
+ case GL_UNSIGNED_BYTE:
+ case GL_SHORT:
+ case GL_UNSIGNED_SHORT:
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ case GL_FLOAT:
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ case GL_UNSIGNED_INT_8_8_8_8:
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ case GL_UNSIGNED_INT_10_10_10_2:
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ return GL_TRUE;
+ default:
+ return GL_FALSE;
+ }
+ default:
+ ; /* fall-through */
+ }
+ return GL_FALSE;
+}
+
+
+
+/*
+ * Return the address of a pixel in an image (actually a volume).
+ * Pixel unpacking/packing parameters are observed according to 'packing'.
+ * Input: image - start of image data
+ * width, height - size of image
+ * format - image format
+ * type - pixel component type
+ * packing - the pixelstore attributes
+ * img - which image in the volume (0 for 1D or 2D images)
+ * row, column - location of pixel in the image
+ * Return: address of pixel at (image,row,column) in image or NULL if error.
+ */
+GLvoid *gl_pixel_addr_in_image( const struct gl_pixelstore_attrib *packing,
+ const GLvoid *image, GLsizei width,
+ GLsizei height, GLenum format, GLenum type,
+ GLint img, GLint row, GLint column )
+{
+ GLint alignment; /* 1, 2 or 4 */
+ GLint pixels_per_row;
+ GLint rows_per_image;
+ GLint skiprows;
+ GLint skippixels;
+ GLint skipimages; /* for 3-D volume images */
+ GLubyte *pixel_addr;
+
+ alignment = packing->Alignment;
+ if (packing->RowLength > 0) {
+ pixels_per_row = packing->RowLength;
+ }
+ else {
+ pixels_per_row = width;
+ }
+ if (packing->ImageHeight > 0) {
+ rows_per_image = packing->ImageHeight;
+ }
+ else {
+ rows_per_image = height;
+ }
+ skiprows = packing->SkipRows;
+ skippixels = packing->SkipPixels;
+ skipimages = packing->SkipImages;
+
+ if (type==GL_BITMAP) {
+ /* BITMAP data */
+ GLint comp_per_pixel; /* components per pixel */
+ GLint bytes_per_comp; /* bytes per component */
+ GLint bytes_per_row;
+ GLint bytes_per_image;
+
+ /* Compute bytes per component */
+ bytes_per_comp = gl_sizeof_packed_type( type );
+ if (bytes_per_comp<0) {
+ return NULL;
+ }
+
+ /* Compute number of components per pixel */
+ comp_per_pixel = gl_components_in_format( format );
+ if (comp_per_pixel<0 && type != GL_BITMAP) {
+ return NULL;
+ }
+
+ bytes_per_row = alignment
+ * CEILING( comp_per_pixel*pixels_per_row, 8*alignment );
+
+ bytes_per_image = bytes_per_row * rows_per_image;
+
+ pixel_addr = (GLubyte *) image
+ + (skipimages + img) * bytes_per_image
+ + (skiprows + row) * bytes_per_row
+ + (skippixels + column) / 8;
+ }
+ else {
+ /* Non-BITMAP data */
+ GLint bytes_per_pixel, bytes_per_row, remainder, bytes_per_image;
+
+ bytes_per_pixel = gl_bytes_per_pixel( format, type );
+
+ /* The pixel type and format should have been error checked earlier */
+ assert(bytes_per_pixel > 0);
+
+ bytes_per_row = pixels_per_row * bytes_per_pixel;
+ remainder = bytes_per_row % alignment;
+ if (remainder > 0)
+ bytes_per_row += (alignment - remainder);
+
+ ASSERT(bytes_per_row % alignment == 0);
+
+ bytes_per_image = bytes_per_row * rows_per_image;
+
+ /* compute final pixel address */
+ pixel_addr = (GLubyte *) image
+ + (skipimages + img) * bytes_per_image
+ + (skiprows + row) * bytes_per_row
+ + (skippixels + column) * bytes_per_pixel;
+ }
+
+ return (GLvoid *) pixel_addr;
+}
+
+
+
+/*
+ * Allocate a new gl_image. All fields are initialized to zero.
+ */
+static struct gl_image *alloc_image( void )
+{
+ return (struct gl_image *) calloc(sizeof(struct gl_image), 1);
+}
+
+
+
+/*
+ * Allocate a new gl_image with the error flag set.
+ */
+static struct gl_image *alloc_error_image( GLint width, GLint height,
+ GLint depth, GLenum format,
+ GLenum type )
+{
+ struct gl_image *image = alloc_image();
+ if (image) {
+ image->Width = width;
+ image->Height = height;
+ image->Depth = depth;
+ image->Format = format;
+ image->Type = type;
+ image->ErrorFlag = GL_TRUE;
+ }
+ return image;
+}
+
+
+
+/*
+ * Free a gl_image.
+ */
+void gl_free_image( struct gl_image *image )
+{
+ if (image->Data) {
+ free(image->Data);
+ }
+ free(image);
+}
+
+
+
+/*
+ * Do error checking on an image. If there's an error, register it and
+ * return GL_TRUE, else return GL_FALSE.
+ */
+GLboolean gl_image_error_test( GLcontext *ctx, const struct gl_image *image,
+ const char *msg )
+{
+ if (!image) {
+ gl_error( ctx, GL_OUT_OF_MEMORY, msg );
+ return GL_TRUE;
+ }
+ if (image->Width <= 0 || image->Height <= 0 || image->Depth <= 0) {
+ gl_error( ctx, GL_INVALID_VALUE, msg );
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
+
+
+/*
+ * Unpack a depth-buffer image storing values as GLshort, GLuint, or GLfloats.
+ * Input: type - datatype of src depth image
+ * Return pointer to a new gl_image structure.
+ *
+ * Notes: if the source image type is GLushort then the gl_image will
+ * also store GLushorts. If the src image type is GLuint then the gl_image
+ * will also store GLuints. For all other src image types the gl_image
+ * will store GLfloats. The integer cases can later be optimized.
+ */
+static struct gl_image *
+unpack_depth_image( GLcontext *ctx, GLenum type, GLint width, GLint height,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing)
+
+{
+ struct gl_image *image;
+ GLfloat *fDst;
+ GLushort *sDst;
+ GLuint *iDst;
+ GLint i, j;
+
+ image = alloc_image();
+ if (image) {
+ image->Width = width;
+ image->Height = height;
+ image->Depth = 1;
+ image->Components = 1;
+ image->Format = GL_DEPTH_COMPONENT;
+ if (type==GL_UNSIGNED_SHORT) {
+ image->Type = GL_UNSIGNED_SHORT;
+ image->Data = malloc( width * height * sizeof(GLushort));
+ }
+ else if (type==GL_UNSIGNED_INT) {
+ image->Type = GL_UNSIGNED_INT;
+ image->Data = malloc( width * height * sizeof(GLuint));
+ }
+ else {
+ image->Type = GL_FLOAT;
+ image->Data = malloc( width * height * sizeof(GLfloat));
+ }
+ image->RefCount = 0;
+ if (!image->Data)
+ return image;
+ }
+ else {
+ return NULL;
+ }
+
+ fDst = (GLfloat *) image->Data;
+ sDst = (GLushort *) image->Data;
+ iDst = (GLuint *) image->Data;
+
+ for (i=0;i<height;i++) {
+ GLvoid *src = gl_pixel_addr_in_image( packing, pixels,
+ width, height,
+ GL_DEPTH_COMPONENT, type,
+ 0, i, 0 );
+ if (!src) {
+ return image;
+ }
+
+ switch (type) {
+ case GL_BYTE:
+ assert(image->Type == GL_FLOAT);
+ for (j=0; j<width; j++) {
+ *fDst++ = BYTE_TO_FLOAT(((GLbyte*)src)[j]);
+ }
+ break;
+ case GL_UNSIGNED_BYTE:
+ assert(image->Type == GL_FLOAT);
+ for (j=0; j<width; j++) {
+ *fDst++ = UBYTE_TO_FLOAT(((GLubyte*)src)[j]);
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ assert(image->Type == GL_UNSIGNED_SHORT);
+ MEMCPY( sDst, src, width * sizeof(GLushort) );
+ if (packing->SwapBytes) {
+ gl_swap2( sDst, width );
+ }
+ sDst += width;
+ break;
+ case GL_SHORT:
+ assert(image->Type == GL_FLOAT);
+ if (packing->SwapBytes) {
+ for (j=0;j<width;j++) {
+ GLshort value = ((GLshort*)src)[j];
+ value = ((value >> 8) & 0xff) | ((value&0xff) << 8);
+ *fDst++ = SHORT_TO_FLOAT(value);
+ }
+ }
+ else {
+ for (j=0;j<width;j++) {
+ *fDst++ = SHORT_TO_FLOAT(((GLshort*)src)[j]);
+ }
+ }
+ break;
+ case GL_INT:
+ assert(image->Type == GL_FLOAT);
+ if (packing->SwapBytes) {
+ for (j=0;j<width;j++) {
+ GLint value = ((GLint*)src)[j];
+ value = ((value >> 24) & 0x000000ff) |
+ ((value >> 8) & 0x0000ff00) |
+ ((value << 8) & 0x00ff0000) |
+ ((value << 24) & 0xff000000);
+ *fDst++ = INT_TO_FLOAT(value);
+ }
+ }
+ else {
+ for (j=0;j<width;j++) {
+ *fDst++ = INT_TO_FLOAT(((GLint*)src)[j]);
+ }
+ }
+ iDst += width;
+ break;
+ case GL_UNSIGNED_INT:
+ assert(image->Type == GL_UNSIGNED_INT);
+ MEMCPY( iDst, src, width * sizeof(GLuint) );
+ if (packing->SwapBytes) {
+ gl_swap4( iDst, width );
+ }
+ iDst += width;
+ break;
+ case GL_FLOAT:
+ assert(image->Type == GL_FLOAT);
+ MEMCPY( fDst, src, width * sizeof(GLfloat) );
+ if (packing->SwapBytes) {
+ gl_swap4( (GLuint*) fDst, width );
+ }
+ fDst += width;
+ break;
+ default:
+ gl_problem(ctx, "unpack_depth_image type" );
+ return image;
+ }
+ }
+
+ return image;
+}
+
+
+
+/*
+ * Unpack a stencil image. Store as GLubytes in a gl_image structure.
+ * Return: pointer to new gl_image structure.
+ */
+static struct gl_image *
+unpack_stencil_image( GLcontext *ctx, GLenum type, GLint width, GLint height,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing )
+{
+ struct gl_image *image;
+ GLubyte *dst;
+ GLint i, j;
+
+ assert(sizeof(GLstencil) == sizeof(GLubyte));
+
+ image = alloc_image();
+ if (image) {
+ image->Width = width;
+ image->Height = height;
+ image->Depth = 1;
+ image->Components = 1;
+ image->Format = GL_STENCIL_INDEX;
+ image->Type = GL_UNSIGNED_BYTE;
+ image->Data = malloc( width * height * sizeof(GLubyte));
+ image->RefCount = 0;
+ if (!image->Data)
+ return image;
+ }
+ else {
+ return NULL;
+ }
+
+ dst = (GLubyte *) image->Data;
+
+ for (i=0;i<height;i++) {
+ GLvoid *src = gl_pixel_addr_in_image( packing, pixels,
+ width, height,
+ GL_STENCIL_INDEX, type,
+ 0, i, 0 );
+ if (!src) {
+ return image;
+ }
+
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ case GL_BYTE:
+ MEMCPY( dst, src, width * sizeof(GLubyte) );
+ dst += width * sizeof(GLubyte);
+ break;
+ case GL_UNSIGNED_SHORT:
+ case GL_SHORT:
+ if (packing->SwapBytes) {
+ /* grab upper byte */
+ for (j=0; j < width; j++) {
+ *dst++ = (((GLushort*)src)[j] & 0xff00) >> 8;
+ }
+ }
+ else {
+ for (j=0; j < width; j++) {
+ *dst++ = (((GLushort*)src)[j]) & 0xff;
+ }
+ }
+ break;
+ case GL_INT:
+ if (packing->SwapBytes) {
+ /* grab upper byte */
+ for (j=0; j < width; j++) {
+ *dst++ = (((GLuint*)src)[j] & 0xff000000) >> 8;
+ }
+ }
+ else {
+ for (j=0; j < width; j++) {
+ *dst++ = (((GLuint*)src)[j]) & 0xff;
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ if (packing->SwapBytes) {
+ /* grab upper byte */
+ for (j=0; j < width; j++) {
+ *dst++ = (((GLuint*)src)[j] & 0xff000000) >> 8;
+ }
+ }
+ else {
+ for (j=0; j < width; j++) {
+ *dst++ = (((GLuint*)src)[j]) & 0xff;
+ }
+ }
+ break;
+ case GL_FLOAT:
+ if (packing->SwapBytes) {
+ for (j=0; j < width; j++) {
+ GLfloat fvalue;
+ GLint value = ((GLuint*)src)[j];
+ value = ((value & 0xff000000) >> 24)
+ | ((value & 0x00ff0000) >> 8)
+ | ((value & 0x0000ff00) << 8)
+ | ((value & 0x000000ff) << 24);
+ fvalue = *((GLfloat*) &value);
+ *dst++ = ((GLint) fvalue) & 0xff;
+ }
+ }
+ else {
+ for (j=0; j < width; j++) {
+ GLfloat fvalue = ((GLfloat *)src)[j];
+ *dst++ = ((GLint) fvalue) & 0xff;
+ }
+ }
+ break;
+ default:
+ gl_problem(ctx, "unpack_stencil_image type" );
+ return image;
+ }
+ }
+
+ return image;
+}
+
+
+
+/*
+ * Unpack a bitmap, return a new gl_image struct.
+ */
+static struct gl_image *
+unpack_bitmap( GLcontext *ctx, GLenum format, GLint width, GLint height,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing )
+{
+ struct gl_image *image;
+ GLint bytes, i, width_in_bytes;
+ GLubyte *buffer, *dst;
+
+ assert(format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX);
+
+ /* Alloc dest storage */
+ bytes = ((width+7)/8 * height);
+ if (bytes>0 && pixels!=NULL) {
+ buffer = (GLubyte *) malloc( bytes );
+ if (!buffer) {
+ return NULL;
+ }
+ /* Copy/unpack pixel data to buffer */
+ width_in_bytes = CEILING( width, 8 );
+ dst = buffer;
+ for (i=0; i<height; i++) {
+ GLvoid *src = gl_pixel_addr_in_image( packing, pixels,
+ width, height,
+ GL_COLOR_INDEX, GL_BITMAP,
+ 0, i, 0 );
+ if (!src) {
+ free(buffer);
+ return NULL;
+ }
+ MEMCPY( dst, src, width_in_bytes );
+ dst += width_in_bytes;
+ }
+ /* Bit flipping */
+ if (packing->LsbFirst) {
+ gl_flip_bytes( buffer, bytes );
+ }
+ }
+ else {
+ /* a 'null' bitmap */
+ buffer = NULL;
+ }
+
+ image = alloc_image();
+ if (image) {
+ image->Width = width;
+ image->Height = height;
+ image->Depth = 1;
+ image->Components = 0;
+ image->Format = format;
+ image->Type = GL_BITMAP;
+ image->Data = buffer;
+ image->RefCount = 0;
+ }
+ else {
+ free( buffer );
+ return NULL;
+ }
+
+ return image;
+}
+
+
+
+/*
+ * Unpack a 32x32 pixel polygon stipple from user memory using the
+ * current pixel unpack settings.
+ */
+void gl_unpack_polygon_stipple( const GLcontext *ctx,
+ const GLubyte *pattern, GLuint dest[32] )
+{
+ GLint i;
+ for (i = 0; i < 32; i++) {
+ GLubyte *src = (GLubyte *) gl_pixel_addr_in_image( &ctx->Unpack, pattern,
+ 32, 32, GL_COLOR_INDEX, GL_BITMAP, 0, i, 0 );
+ dest[i] = (src[0] << 24)
+ | (src[1] << 16)
+ | (src[2] << 8)
+ | (src[3] );
+ }
+
+ /* Bit flipping within each byte */
+ if (ctx->Unpack.LsbFirst) {
+ gl_flip_bytes( (GLubyte *) dest, 32 * 4 );
+ }
+}
+
+
+
+/*
+ * Pack polygon stipple into user memory given current pixel packing
+ * settings.
+ */
+void gl_pack_polygon_stipple( const GLcontext *ctx,
+ const GLuint pattern[32],
+ GLubyte *dest )
+{
+ GLint i;
+ for (i = 0; i < 32; i++) {
+ GLubyte *dst = (GLubyte *) gl_pixel_addr_in_image( &ctx->Pack, dest,
+ 32, 32, GL_COLOR_INDEX, GL_BITMAP, 0, i, 0 );
+ dst[0] = (pattern[i] >> 24) & 0xff;
+ dst[1] = (pattern[i] >> 16) & 0xff;
+ dst[2] = (pattern[i] >> 8) & 0xff;
+ dst[3] = (pattern[i] ) & 0xff;
+
+ /* Bit flipping within each byte */
+ if (ctx->Pack.LsbFirst) {
+ gl_flip_bytes( (GLubyte *) dst, 4 );
+ }
+ }
+}
+
+
+
+/*
+ * Unpack an RGBA or CI image and store it as unsigned bytes
+ */
+static struct gl_image *
+unpack_ubyte_image( GLcontext *ctx, GLint width, GLint height,
+ GLint depth, GLenum format, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing )
+{
+ struct gl_image *image;
+ GLint width_in_bytes;
+ GLint components;
+ GLubyte *buffer, *dst;
+ GLint i, d;
+
+ components = gl_components_in_format( format );
+
+ width_in_bytes = width * components * sizeof(GLubyte);
+ buffer = (GLubyte *) malloc( height * width_in_bytes * depth );
+ if (!buffer) {
+ return NULL;
+ }
+
+ /* Copy/unpack pixel data to buffer */
+ dst = buffer;
+ for (d=0; d<depth; d++ ) {
+ for (i=0;i<height;i++) {
+ GLubyte *src = (GLubyte *) gl_pixel_addr_in_image( packing,
+ pixels, width, height, format, GL_UNSIGNED_BYTE,
+ d, i, 0 );
+ if (!src) {
+ free(buffer);
+ return NULL;
+ }
+ MEMCPY( dst, src, width_in_bytes );
+ dst += width_in_bytes;
+ }
+ }
+
+ if (format == GL_BGR) {
+ /* swap order of every ubyte triplet from BGR to RGB */
+ for (i=0; i<width*height; i++) {
+ GLubyte b = buffer[i*3+0];
+ GLubyte r = buffer[i*3+2];
+ buffer[i*3+0] = r;
+ buffer[i*3+2] = b;
+ }
+ }
+ else if (format == GL_BGRA) {
+ /* swap order of every ubyte quadruplet from BGRA to RGBA */
+ for (i=0; i<width*height; i++) {
+ GLubyte b = buffer[i*4+0];
+ GLubyte r = buffer[i*4+2];
+ buffer[i*4+0] = r;
+ buffer[i*4+2] = b;
+ }
+ }
+ else if (format == GL_ABGR_EXT) {
+ /* swap order of every ubyte quadruplet from ABGR to RGBA */
+ for (i=0; i<width*height; i++) {
+ GLubyte a = buffer[i*4+0];
+ GLubyte b = buffer[i*4+1];
+ GLubyte g = buffer[i*4+2];
+ GLubyte r = buffer[i*4+3];
+ buffer[i*4+0] = r;
+ buffer[i*4+1] = g;
+ buffer[i*4+2] = b;
+ buffer[i*4+3] = a;
+ }
+ }
+
+
+ image = alloc_image();
+ if (image) {
+ image->Width = width;
+ image->Height = height;
+ image->Depth = depth;
+ image->Components = components;
+ if (format == GL_BGR)
+ image->Format = GL_RGB;
+ else if (format == GL_BGRA)
+ image->Format = GL_RGBA;
+ else if (format == GL_ABGR_EXT)
+ image->Format = GL_RGBA;
+ else
+ image->Format = format;
+ image->Type = GL_UNSIGNED_BYTE;
+ image->Data = buffer;
+ image->RefCount = 0;
+ }
+ else {
+ free( buffer );
+ }
+
+ return image;
+}
+
+
+
+/*
+ * Unpack a color image storing image as GLfloats
+ */
+static struct gl_image *
+unpack_float_image( GLcontext *ctx, GLint width, GLint height, GLint depth,
+ GLenum format, GLenum type, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing )
+{
+ struct gl_image *image;
+ GLfloat *dst;
+ GLint elems_per_row;
+ GLint components;
+ GLint i, j, d;
+ GLboolean normalize;
+
+ assert(type != GL_BITMAP);
+
+ components = gl_components_in_format( format );
+ assert(components > 0); /* should have been caught earlier */
+
+ if (!gl_is_legal_format_and_type( format, type )) {
+ /* bad pixel type for format, make dummy image */
+ image = alloc_image();
+ if (image) {
+ image->Width = width;
+ image->Height = height;
+ image->Depth = depth;
+ image->Components = components;
+ image->Format = format;
+ image->Type = type;
+ image->Data = NULL;
+ image->RefCount = 0;
+ }
+ return image;
+ }
+
+ elems_per_row = width * components;
+
+ image = alloc_image();
+ if (image) {
+ image->Width = width;
+ image->Height = height;
+ image->Depth = depth;
+ image->Components = components;
+ if (format == GL_BGR)
+ image->Format = GL_RGB;
+ else if (format == GL_BGRA)
+ image->Format = GL_RGBA;
+ else if (format == GL_ABGR_EXT)
+ image->Format = GL_RGBA;
+ else
+ image->Format = format;
+ image->Type = GL_FLOAT;
+ image->Data = malloc( elems_per_row * height * depth * sizeof(GLfloat));
+ image->RefCount = 0;
+ if (!image->Data)
+ return image;
+ }
+ else {
+ return NULL;
+ }
+
+ normalize = (format != GL_COLOR_INDEX) && (format != GL_STENCIL_INDEX);
+
+ dst = (GLfloat *) image->Data;
+
+ for (d=0; d<depth; d++) {
+ for (i=0;i<height;i++) {
+ GLvoid *src = gl_pixel_addr_in_image( packing, pixels,
+ width, height,
+ format, type,
+ d, i, 0 );
+ if (!src) {
+ return image;
+ }
+
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ {
+ GLubyte *ubsrc = (GLubyte *) src;
+ if (normalize) {
+ for (j=0;j<elems_per_row;j++) {
+ *dst++ = UBYTE_TO_FLOAT(ubsrc[j]);
+ }
+ }
+ else {
+ for (j=0;j<elems_per_row;j++) {
+ *dst++ = (GLfloat) ubsrc[j];
+ }
+ }
+ }
+ break;
+ case GL_BYTE:
+ if (normalize) {
+ for (j=0;j<elems_per_row;j++) {
+ *dst++ = BYTE_TO_FLOAT(((GLbyte*)src)[j]);
+ }
+ }
+ else {
+ for (j=0;j<elems_per_row;j++) {
+ *dst++ = (GLfloat) ((GLbyte*)src)[j];
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ if (packing->SwapBytes) {
+ for (j=0;j<elems_per_row;j++) {
+ GLushort value = ((GLushort*)src)[j];
+ value = ((value >> 8) & 0xff) | ((value&0xff) << 8);
+ if (normalize) {
+ *dst++ = USHORT_TO_FLOAT(value);
+ }
+ else {
+ *dst++ = (GLfloat) value;
+ }
+ }
+ }
+ else {
+ if (normalize) {
+ for (j=0;j<elems_per_row;j++) {
+ *dst++ = USHORT_TO_FLOAT(((GLushort*)src)[j]);
+ }
+ }
+ else {
+ for (j=0;j<elems_per_row;j++) {
+ *dst++ = (GLfloat) ((GLushort*)src)[j];
+ }
+ }
+ }
+ break;
+ case GL_SHORT:
+ if (packing->SwapBytes) {
+ for (j=0;j<elems_per_row;j++) {
+ GLshort value = ((GLshort*)src)[j];
+ value = ((value >> 8) & 0xff) | ((value&0xff) << 8);
+ if (normalize) {
+ *dst++ = SHORT_TO_FLOAT(value);
+ }
+ else {
+ *dst++ = (GLfloat) value;
+ }
+ }
+ }
+ else {
+ if (normalize) {
+ for (j=0;j<elems_per_row;j++) {
+ *dst++ = SHORT_TO_FLOAT(((GLshort*)src)[j]);
+ }
+ }
+ else {
+ for (j=0;j<elems_per_row;j++) {
+ *dst++ = (GLfloat) ((GLshort*)src)[j];
+ }
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ if (packing->SwapBytes) {
+ GLuint value;
+ for (j=0;j<elems_per_row;j++) {
+ value = ((GLuint*)src)[j];
+ value = ((value & 0xff000000) >> 24)
+ | ((value & 0x00ff0000) >> 8)
+ | ((value & 0x0000ff00) << 8)
+ | ((value & 0x000000ff) << 24);
+ if (normalize) {
+ *dst++ = UINT_TO_FLOAT(value);
+ }
+ else {
+ *dst++ = (GLfloat) value;
+ }
+ }
+ }
+ else {
+ if (normalize) {
+ for (j=0;j<elems_per_row;j++) {
+ *dst++ = UINT_TO_FLOAT(((GLuint*)src)[j]);
+ }
+ }
+ else {
+ for (j=0;j<elems_per_row;j++) {
+ *dst++ = (GLfloat) ((GLuint*)src)[j];
+ }
+ }
+ }
+ break;
+ case GL_INT:
+ if (packing->SwapBytes) {
+ GLint value;
+ for (j=0;j<elems_per_row;j++) {
+ value = ((GLint*)src)[j];
+ value = ((value & 0xff000000) >> 24)
+ | ((value & 0x00ff0000) >> 8)
+ | ((value & 0x0000ff00) << 8)
+ | ((value & 0x000000ff) << 24);
+ if (normalize) {
+ *dst++ = INT_TO_FLOAT(value);
+ }
+ else {
+ *dst++ = (GLfloat) value;
+ }
+ }
+ }
+ else {
+ if (normalize) {
+ for (j=0;j<elems_per_row;j++) {
+ *dst++ = INT_TO_FLOAT(((GLint*)src)[j]);
+ }
+ }
+ else {
+ for (j=0;j<elems_per_row;j++) {
+ *dst++ = (GLfloat) ((GLint*)src)[j];
+ }
+ }
+ }
+ break;
+ case GL_FLOAT:
+ if (packing->SwapBytes) {
+ GLint value;
+ for (j=0;j<elems_per_row;j++) {
+ value = ((GLuint*)src)[j];
+ value = ((value & 0xff000000) >> 24)
+ | ((value & 0x00ff0000) >> 8)
+ | ((value & 0x0000ff00) << 8)
+ | ((value & 0x000000ff) << 24);
+ *dst++ = *((GLfloat*) &value);
+ }
+ }
+ else {
+ MEMCPY( dst, src, elems_per_row*sizeof(GLfloat) );
+ dst += elems_per_row;
+ }
+ break;
+ case GL_UNSIGNED_BYTE_3_3_2:
+ {
+ GLubyte *ubsrc = (GLubyte *) src;
+ for (j=0;j<width;j++) {
+ GLubyte p = ubsrc[j];
+ *dst++ = ((p >> 5) ) * (1.0F / 7.0F); /* red */
+ *dst++ = ((p >> 2) & 0x7) * (1.0F / 7.0F); /* green */
+ *dst++ = ((p ) & 0x3) * (1.0F / 3.0F); /* blue */
+ }
+ }
+ break;
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ {
+ GLubyte *ubsrc = (GLubyte *) src;
+ for (j=0;j<width;j++) {
+ GLubyte p = ubsrc[j];
+ *dst++ = ((p ) & 0x7) * (1.0F / 7.0F); /* red */
+ *dst++ = ((p >> 3) & 0x7) * (1.0F / 7.0F); /* green */
+ *dst++ = ((p >> 6) ) * (1.0F / 3.0F); /* blue */
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ {
+ GLushort *ussrc = (GLushort *) src;
+ for (j=0;j<width;j++) {
+ GLushort p = ussrc[j];
+ *dst++ = ((p >> 11) ) * (1.0F / 31.0F); /* red */
+ *dst++ = ((p >> 5) & 0x3f) * (1.0F / 63.0F); /* green */
+ *dst++ = ((p ) & 0x1f) * (1.0F / 31.0F); /* blue */
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ {
+ GLushort *ussrc = (GLushort *) src;
+ for (j=0;j<width;j++) {
+ GLushort p = ussrc[j];
+ *dst++ = ((p ) & 0x1f) * (1.0F / 31.0F); /* red */
+ *dst++ = ((p >> 5) & 0x3f) * (1.0F / 63.0F); /* green */
+ *dst++ = ((p >> 11) ) * (1.0F / 31.0F); /* blue */
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ {
+ GLushort *ussrc = (GLushort *) src;
+ for (j=0;j<width;j++) {
+ GLushort p = ussrc[j];
+ *dst++ = ((p >> 12) ) * (1.0F / 15.0F); /* red */
+ *dst++ = ((p >> 8) & 0xf) * (1.0F / 15.0F); /* green */
+ *dst++ = ((p >> 4) & 0xf) * (1.0F / 15.0F); /* blue */
+ *dst++ = ((p ) & 0xf) * (1.0F / 15.0F); /* alpha */
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ {
+ GLushort *ussrc = (GLushort *) src;
+ for (j=0;j<width;j++) {
+ GLushort p = ussrc[j];
+ *dst++ = ((p ) & 0xf) * (1.0F / 15.0F); /* red */
+ *dst++ = ((p >> 4) & 0xf) * (1.0F / 15.0F); /* green */
+ *dst++ = ((p >> 8) & 0xf) * (1.0F / 15.0F); /* blue */
+ *dst++ = ((p >> 12) ) * (1.0F / 15.0F); /* alpha */
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ {
+ GLushort *ussrc = (GLushort *) src;
+ for (j=0;j<width;j++) {
+ GLushort p = ussrc[j];
+ *dst++ = ((p >> 11) ) * (1.0F / 31.0F); /* red */
+ *dst++ = ((p >> 6) & 0x1f) * (1.0F / 31.0F); /* green */
+ *dst++ = ((p >> 1) & 0x1f) * (1.0F / 31.0F); /* blue */
+ *dst++ = ((p ) & 0x1) * (1.0F / 1.0F); /* alpha */
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ {
+ GLushort *ussrc = (GLushort *) src;
+ for (j=0;j<width;j++) {
+ GLushort p = ussrc[j];
+ *dst++ = ((p ) & 0x1f) * (1.0F / 31.0F); /* red */
+ *dst++ = ((p >> 5) & 0x1f) * (1.0F / 31.0F); /* green */
+ *dst++ = ((p >> 10) & 0x1f) * (1.0F / 31.0F); /* blue */
+ *dst++ = ((p >> 15) ) * (1.0F / 1.0F); /* alpha */
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8:
+ {
+ GLuint *uisrc = (GLuint *) src;
+ for (j=0;j<width;j++) {
+ GLuint p = uisrc[j];
+ *dst++ = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 24) );
+ *dst++ = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 16) & 0xff);
+ *dst++ = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 8) & 0xff);
+ *dst++ = UBYTE_COLOR_TO_FLOAT_COLOR((p ) & 0xff);
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ {
+ GLuint *uisrc = (GLuint *) src;
+ for (j=0;j<width;j++) {
+ GLuint p = uisrc[j];
+ *dst++ = UBYTE_COLOR_TO_FLOAT_COLOR((p ) & 0xff);
+ *dst++ = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 8) & 0xff);
+ *dst++ = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 16) & 0xff);
+ *dst++ = UBYTE_COLOR_TO_FLOAT_COLOR((p >> 24) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT_10_10_10_2:
+ {
+ GLuint *uisrc = (GLuint *) src;
+ for (j=0;j<width;j++) {
+ GLuint p = uisrc[j];
+ *dst++ = ((p >> 22) ) * (1.0F / 1023.0F); /* r */
+ *dst++ = ((p >> 12) & 0x3ff) * (1.0F / 1023.0F); /* g */
+ *dst++ = ((p >> 2) & 0x3ff) * (1.0F / 1023.0F); /* b */
+ *dst++ = ((p ) & 0x3 ) * (1.0F / 3.0F); /* a */
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ {
+ GLuint *uisrc = (GLuint *) src;
+ for (j=0;j<width;j++) {
+ GLuint p = uisrc[j];
+ *dst++ = ((p ) & 0x3ff) * (1.0F / 1023.0F); /* r*/
+ *dst++ = ((p >> 10) & 0x3ff) * (1.0F / 1023.0F); /* g */
+ *dst++ = ((p >> 20) & 0x3ff) * (1.0F / 1023.0F); /* b */
+ *dst++ = ((p >> 30) ) * (1.0F / 3.0F); /* a */
+ }
+ }
+ break;
+ default:
+ gl_problem(ctx, "unpack_float_image type" );
+ return image;
+ }
+ }
+ }
+
+ if (format == GL_BGR) {
+ /* swap order of every float triplet from BGR to RGBA */
+ GLfloat *buffer = (GLfloat *) image->Data;
+ for (i=0; i<width*height*depth; i++) {
+ GLfloat b = buffer[i*3+0];
+ GLfloat r = buffer[i*3+2];
+ buffer[i*3+0] = r;
+ buffer[i*3+2] = b;
+ }
+ }
+ else if (format == GL_BGRA) {
+ /* swap order of every float quadruplet from BGRA to RGBA */
+ GLfloat *buffer = (GLfloat *) image->Data;
+ for (i=0; i<width*height*depth; i++) {
+ GLfloat b = buffer[i*4+0];
+ GLfloat r = buffer[i*4+2];
+ buffer[i*4+0] = r;
+ buffer[i*4+2] = b;
+ }
+ }
+ else if (format == GL_ABGR_EXT) {
+ /* swap order of every float quadruplet from ABGR to RGBA */
+ GLfloat *buffer = (GLfloat *) image->Data;
+ for (i=0; i<width*height*depth; i++) {
+ GLfloat a = buffer[i*4+0];
+ GLfloat b = buffer[i*4+1];
+ GLfloat g = buffer[i*4+2];
+ GLfloat r = buffer[i*4+3];
+ buffer[i*4+0] = r;
+ buffer[i*4+1] = g;
+ buffer[i*4+2] = b;
+ buffer[i*4+3] = a;
+ }
+ }
+
+ return image;
+}
+
+
+
+/*
+ * Unpack a bitmap image, using current glPixelStore parameters,
+ * making a new gl_image.
+ */
+struct gl_image *gl_unpack_bitmap( GLcontext *ctx,
+ GLsizei width, GLsizei height,
+ const GLubyte *bitmap,
+ const struct gl_pixelstore_attrib *packing )
+{
+ return gl_unpack_image( ctx, width, height,
+ GL_COLOR_INDEX, GL_BITMAP, bitmap, packing );
+}
+
+
+
+/*
+ * Unpack a 2-D image from user's buffer. Return pointer to new
+ * gl_image struct.
+ *
+ * Input: width, height - size in pixels
+ * format - format of incoming pixel data
+ * type - datatype of incoming pixel data
+ * pixels - pointer to unpacked image in user buffer
+ */
+struct gl_image *gl_unpack_image( GLcontext *ctx,
+ GLint width, GLint height,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing )
+{
+ return gl_unpack_image3D( ctx, width, height, 1,
+ format, type, pixels, packing );
+}
+
+
+
+/*
+ * Unpack a 1, 2 or 3-D image from user-supplied address, returning a
+ * pointer to a new gl_image struct.
+ * This function is always called by a higher-level unpack function such
+ * as gl_unpack_texsubimage() or gl_unpack_bitmap().
+ *
+ * Input: width, height, depth - size in pixels
+ * format - format of incoming pixel data
+ * type - datatype of incoming pixel data
+ * pixels - pointer to unpacked image.
+ */
+struct gl_image *gl_unpack_image3D( GLcontext *ctx,
+ GLint width, GLint height, GLint depth,
+ GLenum format, GLenum type,
+ const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing)
+{
+ if (width <= 0 || height <= 0 || depth <= 0) {
+ return alloc_error_image(width, height, depth, format, type);
+ }
+
+ if (type==GL_BITMAP) {
+ if (format != GL_COLOR_INDEX && format != GL_STENCIL_INDEX) {
+ return alloc_error_image(width, height, depth, format, type);
+ }
+ else {
+ return unpack_bitmap( ctx, format, width, height, pixels, packing );
+ }
+ }
+ else if (format==GL_DEPTH_COMPONENT) {
+ /* TODO: pack as GLdepth values (GLushort or GLuint) */
+ return unpack_depth_image( ctx, type, width, height, pixels, packing );
+ }
+ else if (format==GL_STENCIL_INDEX) {
+ /* TODO: pack as GLstencil (GLubyte or GLushort) */
+ return unpack_stencil_image( ctx, type, width, height, pixels, packing );
+ }
+ else if (type==GL_UNSIGNED_BYTE) {
+ /* upack, convert to GLubytes */
+ return unpack_ubyte_image( ctx, width, height, depth, format, pixels, packing );
+ }
+ else {
+ /* upack, convert to floats */
+ return unpack_float_image( ctx, width, height, depth,
+ format, type, pixels, packing );
+ }
+
+ /* never get here */
+ /*return NULL;*/
+}
+
+
+/*
+ * Apply pixel-transfer operations (scale, bias, mapping) to a single row
+ * of a gl_image. Put resulting color components into result array.
+ */
+void gl_scale_bias_map_image_data( const GLcontext *ctx,
+ const struct gl_image *image,
+ GLint row, GLubyte result[] )
+{
+ GLint start, i;
+
+ assert(ctx);
+ assert(image);
+ assert(result);
+ assert(row >= 0);
+
+ start = row * image->Width * image->Components;
+
+ for (i=0; i < image->Width; i++) {
+ GLint pos = start+i;
+ GLfloat red, green, blue, alpha;
+ if (image->Type == GL_UNSIGNED_BYTE) {
+ const GLubyte *data = (GLubyte *) image->Data;
+ switch (image->Format) {
+ case GL_RED:
+ red = data[pos] * (1.0F/255.0F);
+ green = 0;
+ blue = 0;
+ alpha = 0;
+ break;
+ case GL_RGB:
+ red = data[pos*3+0] * (1.0F/255.0F);
+ green = data[pos*3+1] * (1.0F/255.0F);
+ blue = data[pos*3+2] * (1.0F/255.0F);
+ alpha = 0;
+ break;
+ default:
+ gl_problem(ctx, "bad image format in gl_scale...image_data");
+ return;
+ }
+ }
+ else if (image->Type == GL_FLOAT) {
+ const GLubyte *data = (GLubyte *) image->Data;
+ switch (image->Format) {
+ case GL_RED:
+ red = data[pos];
+ green = 0;
+ blue = 0;
+ alpha = 0;
+ break;
+ case GL_RGB:
+ red = data[pos*3+0];
+ green = data[pos*3+1];
+ blue = data[pos*3+2];
+ alpha = 0;
+ break;
+ default:
+ gl_problem(ctx, "bad image format in gl_scale...image_data");
+ return;
+ }
+ }
+ else {
+ gl_problem(ctx, "Bad image type in gl_scale_...image_data");
+ return;
+ }
+
+ assert(red >= 0.0 && red <= 1.0);
+ assert(green >= 0.0 && green <= 1.0);
+ assert(blue >= 0.0 && blue <= 1.0);
+ assert(alpha >= 0.0 && alpha <= 1.0);
+
+ /*
+ if (scale or bias) {
+
+
+ }
+ if (mapping) {
+
+ }
+ */
+
+ result[i*4+0] = (GLubyte) (red * 255.0);
+ result[i*4+1] = (GLubyte) (green * 255.0);
+ result[i*4+2] = (GLubyte) (blue * 255.0);
+ result[i*4+3] = (GLubyte) (alpha * 255.0);
+ }
+}
+
+
+
+/*
+ * Pack the given RGBA span into client memory at 'dest' address
+ * in the given pixel format and type.
+ * Optionally apply the enabled pixel transfer ops.
+ * Pack into memory using the given packing params struct.
+ * This is used by glReadPixels and glGetTexImage?D()
+ * Input: ctx - the context
+ * n - number of pixels in the span
+ * rgba - the pixels
+ * format - dest packing format
+ * type - dest packing datatype
+ * destination - destination packing address
+ * packing - pixel packing parameters
+ * applyTransferOps - apply scale/bias/lookup-table ops?
+ */
+void gl_pack_rgba_span( const GLcontext *ctx,
+ GLuint n, CONST GLubyte rgba[][4],
+ GLenum format, GLenum type, GLvoid *destination,
+ const struct gl_pixelstore_attrib *packing,
+ GLboolean applyTransferOps )
+{
+ /* Test for optimized case first */
+ if (!ctx->Pixel.ScaleOrBiasRGBA && !ctx->Pixel.MapColorFlag &&
+ format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
+ /* simple case */
+ MEMCPY( destination, rgba, n * 4 * sizeof(GLubyte) );
+ }
+ else {
+ GLfloat red[MAX_WIDTH], green[MAX_WIDTH], blue[MAX_WIDTH];
+ GLfloat alpha[MAX_WIDTH], luminance[MAX_WIDTH];
+ GLfloat rscale = 1.0F / 255.0F;
+ GLfloat gscale = 1.0F / 255.0F;
+ GLfloat bscale = 1.0F / 255.0F;
+ GLfloat ascale = 1.0F / 255.0F;
+ GLuint i;
+
+ assert( n < MAX_WIDTH );
+
+ /* convert color components to floating point */
+ for (i=0;i<n;i++) {
+ red[i] = rgba[i][RCOMP] * rscale;
+ green[i] = rgba[i][GCOMP] * gscale;
+ blue[i] = rgba[i][BCOMP] * bscale;
+ alpha[i] = rgba[i][ACOMP] * ascale;
+ }
+
+ /*
+ * Apply scale, bias and lookup-tables if enabled.
+ */
+ if (applyTransferOps) {
+ if (ctx->Pixel.ScaleOrBiasRGBA) {
+ gl_scale_and_bias_color( ctx, n, red, green, blue, alpha );
+ }
+ if (ctx->Pixel.MapColorFlag) {
+ gl_map_color( ctx, n, red, green, blue, alpha );
+ }
+ }
+
+ if (format==GL_LUMINANCE || format==GL_LUMINANCE_ALPHA) {
+ for (i=0;i<n;i++) {
+ GLfloat sum = red[i] + green[i] + blue[i];
+ luminance[i] = CLAMP( sum, 0.0F, 1.0F );
+ }
+ }
+
+ /*
+ * Pack/store the pixels. Ugh! Lots of cases!!!
+ */
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ {
+ GLubyte *dst = (GLubyte *) destination;
+ switch (format) {
+ case GL_RED:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_UBYTE(red[i]);
+ break;
+ case GL_GREEN:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_UBYTE(green[i]);
+ break;
+ case GL_BLUE:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_UBYTE(blue[i]);
+ break;
+ case GL_ALPHA:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_UBYTE(alpha[i]);
+ break;
+ case GL_LUMINANCE:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_UBYTE(luminance[i]);
+ break;
+ case GL_LUMINANCE_ALPHA:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = FLOAT_TO_UBYTE(luminance[i]);
+ dst[i*2+1] = FLOAT_TO_UBYTE(alpha[i]);
+ }
+ break;
+ case GL_RGB:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = FLOAT_TO_UBYTE(red[i]);
+ dst[i*3+1] = FLOAT_TO_UBYTE(green[i]);
+ dst[i*3+2] = FLOAT_TO_UBYTE(blue[i]);
+ }
+ break;
+ case GL_RGBA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_UBYTE(red[i]);
+ dst[i*4+1] = FLOAT_TO_UBYTE(green[i]);
+ dst[i*4+2] = FLOAT_TO_UBYTE(blue[i]);
+ dst[i*4+3] = FLOAT_TO_UBYTE(alpha[i]);
+ }
+ break;
+ case GL_BGR:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = FLOAT_TO_UBYTE(blue[i]);
+ dst[i*3+1] = FLOAT_TO_UBYTE(green[i]);
+ dst[i*3+2] = FLOAT_TO_UBYTE(red[i]);
+ }
+ break;
+ case GL_BGRA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_UBYTE(blue[i]);
+ dst[i*4+1] = FLOAT_TO_UBYTE(green[i]);
+ dst[i*4+2] = FLOAT_TO_UBYTE(red[i]);
+ dst[i*4+3] = FLOAT_TO_UBYTE(alpha[i]);
+ }
+ break;
+ case GL_ABGR_EXT:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_UBYTE(alpha[i]);
+ dst[i*4+1] = FLOAT_TO_UBYTE(blue[i]);
+ dst[i*4+2] = FLOAT_TO_UBYTE(green[i]);
+ dst[i*4+3] = FLOAT_TO_UBYTE(red[i]);
+ }
+ break;
+ default:
+ gl_problem(ctx, "bad format in gl_pack_rgba_span\n");
+ }
+ }
+ break;
+ case GL_BYTE:
+ {
+ GLbyte *dst = (GLbyte *) destination;
+ switch (format) {
+ case GL_RED:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_BYTE(red[i]);
+ break;
+ case GL_GREEN:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_BYTE(green[i]);
+ break;
+ case GL_BLUE:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_BYTE(blue[i]);
+ break;
+ case GL_ALPHA:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_BYTE(alpha[i]);
+ break;
+ case GL_LUMINANCE:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_BYTE(luminance[i]);
+ break;
+ case GL_LUMINANCE_ALPHA:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = FLOAT_TO_BYTE(luminance[i]);
+ dst[i*2+1] = FLOAT_TO_BYTE(alpha[i]);
+ }
+ break;
+ case GL_RGB:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = FLOAT_TO_BYTE(red[i]);
+ dst[i*3+1] = FLOAT_TO_BYTE(green[i]);
+ dst[i*3+2] = FLOAT_TO_BYTE(blue[i]);
+ }
+ break;
+ case GL_RGBA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_BYTE(red[i]);
+ dst[i*4+1] = FLOAT_TO_BYTE(green[i]);
+ dst[i*4+2] = FLOAT_TO_BYTE(blue[i]);
+ dst[i*4+3] = FLOAT_TO_BYTE(alpha[i]);
+ }
+ break;
+ case GL_BGR:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = FLOAT_TO_BYTE(blue[i]);
+ dst[i*3+1] = FLOAT_TO_BYTE(green[i]);
+ dst[i*3+2] = FLOAT_TO_BYTE(red[i]);
+ }
+ break;
+ case GL_BGRA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_BYTE(blue[i]);
+ dst[i*4+1] = FLOAT_TO_BYTE(green[i]);
+ dst[i*4+2] = FLOAT_TO_BYTE(red[i]);
+ dst[i*4+3] = FLOAT_TO_BYTE(alpha[i]);
+ }
+ case GL_ABGR_EXT:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_BYTE(alpha[i]);
+ dst[i*4+1] = FLOAT_TO_BYTE(blue[i]);
+ dst[i*4+2] = FLOAT_TO_BYTE(green[i]);
+ dst[i*4+3] = FLOAT_TO_BYTE(red[i]);
+ }
+ break;
+ default:
+ gl_problem(ctx, "bad format in gl_pack_rgba_span\n");
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ {
+ GLushort *dst = (GLushort *) destination;
+ switch (format) {
+ case GL_RED:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_USHORT(red[i]);
+ break;
+ case GL_GREEN:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_USHORT(green[i]);
+ break;
+ case GL_BLUE:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_USHORT(blue[i]);
+ break;
+ case GL_ALPHA:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_USHORT(alpha[i]);
+ break;
+ case GL_LUMINANCE:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_USHORT(luminance[i]);
+ break;
+ case GL_LUMINANCE_ALPHA:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = FLOAT_TO_USHORT(luminance[i]);
+ dst[i*2+1] = FLOAT_TO_USHORT(alpha[i]);
+ }
+ break;
+ case GL_RGB:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = FLOAT_TO_USHORT(red[i]);
+ dst[i*3+1] = FLOAT_TO_USHORT(green[i]);
+ dst[i*3+2] = FLOAT_TO_USHORT(blue[i]);
+ }
+ break;
+ case GL_RGBA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_USHORT(red[i]);
+ dst[i*4+1] = FLOAT_TO_USHORT(green[i]);
+ dst[i*4+2] = FLOAT_TO_USHORT(blue[i]);
+ dst[i*4+3] = FLOAT_TO_USHORT(alpha[i]);
+ }
+ break;
+ case GL_BGR:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = FLOAT_TO_USHORT(blue[i]);
+ dst[i*3+1] = FLOAT_TO_USHORT(green[i]);
+ dst[i*3+2] = FLOAT_TO_USHORT(red[i]);
+ }
+ break;
+ case GL_BGRA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_USHORT(blue[i]);
+ dst[i*4+1] = FLOAT_TO_USHORT(green[i]);
+ dst[i*4+2] = FLOAT_TO_USHORT(red[i]);
+ dst[i*4+3] = FLOAT_TO_USHORT(alpha[i]);
+ }
+ break;
+ case GL_ABGR_EXT:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_USHORT(alpha[i]);
+ dst[i*4+1] = FLOAT_TO_USHORT(blue[i]);
+ dst[i*4+2] = FLOAT_TO_USHORT(green[i]);
+ dst[i*4+3] = FLOAT_TO_USHORT(red[i]);
+ }
+ break;
+ default:
+ gl_problem(ctx, "bad format in gl_pack_rgba_span\n");
+ }
+ if (packing->SwapBytes) {
+ gl_swap2( (GLushort *) dst, n );
+ }
+ }
+ break;
+ case GL_SHORT:
+ {
+ GLshort *dst = (GLshort *) destination;
+ switch (format) {
+ case GL_RED:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_SHORT(red[i]);
+ break;
+ case GL_GREEN:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_SHORT(green[i]);
+ break;
+ case GL_BLUE:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_SHORT(blue[i]);
+ break;
+ case GL_ALPHA:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_SHORT(alpha[i]);
+ break;
+ case GL_LUMINANCE:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_SHORT(luminance[i]);
+ break;
+ case GL_LUMINANCE_ALPHA:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = FLOAT_TO_SHORT(luminance[i]);
+ dst[i*2+1] = FLOAT_TO_SHORT(alpha[i]);
+ }
+ break;
+ case GL_RGB:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = FLOAT_TO_SHORT(red[i]);
+ dst[i*3+1] = FLOAT_TO_SHORT(green[i]);
+ dst[i*3+2] = FLOAT_TO_SHORT(blue[i]);
+ }
+ break;
+ case GL_RGBA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_SHORT(red[i]);
+ dst[i*4+1] = FLOAT_TO_SHORT(green[i]);
+ dst[i*4+2] = FLOAT_TO_SHORT(blue[i]);
+ dst[i*4+3] = FLOAT_TO_SHORT(alpha[i]);
+ }
+ break;
+ case GL_BGR:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = FLOAT_TO_SHORT(blue[i]);
+ dst[i*3+1] = FLOAT_TO_SHORT(green[i]);
+ dst[i*3+2] = FLOAT_TO_SHORT(red[i]);
+ }
+ break;
+ case GL_BGRA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_SHORT(blue[i]);
+ dst[i*4+1] = FLOAT_TO_SHORT(green[i]);
+ dst[i*4+2] = FLOAT_TO_SHORT(red[i]);
+ dst[i*4+3] = FLOAT_TO_SHORT(alpha[i]);
+ }
+ case GL_ABGR_EXT:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_SHORT(alpha[i]);
+ dst[i*4+1] = FLOAT_TO_SHORT(blue[i]);
+ dst[i*4+2] = FLOAT_TO_SHORT(green[i]);
+ dst[i*4+3] = FLOAT_TO_SHORT(red[i]);
+ }
+ break;
+ default:
+ gl_problem(ctx, "bad format in gl_pack_rgba_span\n");
+ }
+ if (packing->SwapBytes) {
+ gl_swap2( (GLushort *) dst, n );
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ {
+ GLuint *dst = (GLuint *) destination;
+ switch (format) {
+ case GL_RED:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_UINT(red[i]);
+ break;
+ case GL_GREEN:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_UINT(green[i]);
+ break;
+ case GL_BLUE:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_UINT(blue[i]);
+ break;
+ case GL_ALPHA:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_UINT(alpha[i]);
+ break;
+ case GL_LUMINANCE:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_UINT(luminance[i]);
+ break;
+ case GL_LUMINANCE_ALPHA:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = FLOAT_TO_UINT(luminance[i]);
+ dst[i*2+1] = FLOAT_TO_UINT(alpha[i]);
+ }
+ break;
+ case GL_RGB:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = FLOAT_TO_UINT(red[i]);
+ dst[i*3+1] = FLOAT_TO_UINT(green[i]);
+ dst[i*3+2] = FLOAT_TO_UINT(blue[i]);
+ }
+ break;
+ case GL_RGBA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_UINT(red[i]);
+ dst[i*4+1] = FLOAT_TO_UINT(green[i]);
+ dst[i*4+2] = FLOAT_TO_UINT(blue[i]);
+ dst[i*4+3] = FLOAT_TO_UINT(alpha[i]);
+ }
+ break;
+ case GL_BGR:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = FLOAT_TO_UINT(blue[i]);
+ dst[i*3+1] = FLOAT_TO_UINT(green[i]);
+ dst[i*3+2] = FLOAT_TO_UINT(red[i]);
+ }
+ break;
+ case GL_BGRA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_UINT(blue[i]);
+ dst[i*4+1] = FLOAT_TO_UINT(green[i]);
+ dst[i*4+2] = FLOAT_TO_UINT(red[i]);
+ dst[i*4+3] = FLOAT_TO_UINT(alpha[i]);
+ }
+ break;
+ case GL_ABGR_EXT:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_UINT(alpha[i]);
+ dst[i*4+1] = FLOAT_TO_UINT(blue[i]);
+ dst[i*4+2] = FLOAT_TO_UINT(green[i]);
+ dst[i*4+3] = FLOAT_TO_UINT(red[i]);
+ }
+ break;
+ default:
+ gl_problem(ctx, "bad format in gl_pack_rgba_span\n");
+ }
+ if (packing->SwapBytes) {
+ gl_swap4( (GLuint *) dst, n );
+ }
+ }
+ break;
+ case GL_INT:
+ {
+ GLint *dst = (GLint *) destination;
+ switch (format) {
+ case GL_RED:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_INT(red[i]);
+ break;
+ case GL_GREEN:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_INT(green[i]);
+ break;
+ case GL_BLUE:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_INT(blue[i]);
+ break;
+ case GL_ALPHA:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_INT(alpha[i]);
+ break;
+ case GL_LUMINANCE:
+ for (i=0;i<n;i++)
+ dst[i] = FLOAT_TO_INT(luminance[i]);
+ break;
+ case GL_LUMINANCE_ALPHA:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = FLOAT_TO_INT(luminance[i]);
+ dst[i*2+1] = FLOAT_TO_INT(alpha[i]);
+ }
+ break;
+ case GL_RGB:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = FLOAT_TO_INT(red[i]);
+ dst[i*3+1] = FLOAT_TO_INT(green[i]);
+ dst[i*3+2] = FLOAT_TO_INT(blue[i]);
+ }
+ break;
+ case GL_RGBA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_INT(red[i]);
+ dst[i*4+1] = FLOAT_TO_INT(green[i]);
+ dst[i*4+2] = FLOAT_TO_INT(blue[i]);
+ dst[i*4+3] = FLOAT_TO_INT(alpha[i]);
+ }
+ break;
+ case GL_BGR:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = FLOAT_TO_INT(blue[i]);
+ dst[i*3+1] = FLOAT_TO_INT(green[i]);
+ dst[i*3+2] = FLOAT_TO_INT(red[i]);
+ }
+ break;
+ case GL_BGRA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_INT(blue[i]);
+ dst[i*4+1] = FLOAT_TO_INT(green[i]);
+ dst[i*4+2] = FLOAT_TO_INT(red[i]);
+ dst[i*4+3] = FLOAT_TO_INT(alpha[i]);
+ }
+ break;
+ case GL_ABGR_EXT:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = FLOAT_TO_INT(alpha[i]);
+ dst[i*4+1] = FLOAT_TO_INT(blue[i]);
+ dst[i*4+2] = FLOAT_TO_INT(green[i]);
+ dst[i*4+3] = FLOAT_TO_INT(red[i]);
+ }
+ break;
+ default:
+ gl_problem(ctx, "bad format in gl_pack_rgba_span\n");
+ }
+ if (packing->SwapBytes) {
+ gl_swap4( (GLuint *) dst, n );
+ }
+ }
+ break;
+ case GL_FLOAT:
+ {
+ GLfloat *dst = (GLfloat *) destination;
+ switch (format) {
+ case GL_RED:
+ for (i=0;i<n;i++)
+ dst[i] = red[i];
+ break;
+ case GL_GREEN:
+ for (i=0;i<n;i++)
+ dst[i] = green[i];
+ break;
+ case GL_BLUE:
+ for (i=0;i<n;i++)
+ dst[i] = blue[i];
+ break;
+ case GL_ALPHA:
+ for (i=0;i<n;i++)
+ dst[i] = alpha[i];
+ break;
+ case GL_LUMINANCE:
+ for (i=0;i<n;i++)
+ dst[i] = luminance[i];
+ break;
+ case GL_LUMINANCE_ALPHA:
+ for (i=0;i<n;i++) {
+ dst[i*2+0] = luminance[i];
+ dst[i*2+1] = alpha[i];
+ }
+ break;
+ case GL_RGB:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = red[i];
+ dst[i*3+1] = green[i];
+ dst[i*3+2] = blue[i];
+ }
+ break;
+ case GL_RGBA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = red[i];
+ dst[i*4+1] = green[i];
+ dst[i*4+2] = blue[i];
+ dst[i*4+3] = alpha[i];
+ }
+ break;
+ case GL_BGR:
+ for (i=0;i<n;i++) {
+ dst[i*3+0] = blue[i];
+ dst[i*3+1] = green[i];
+ dst[i*3+2] = red[i];
+ }
+ break;
+ case GL_BGRA:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = blue[i];
+ dst[i*4+1] = green[i];
+ dst[i*4+2] = red[i];
+ dst[i*4+3] = alpha[i];
+ }
+ break;
+ case GL_ABGR_EXT:
+ for (i=0;i<n;i++) {
+ dst[i*4+0] = alpha[i];
+ dst[i*4+1] = blue[i];
+ dst[i*4+2] = green[i];
+ dst[i*4+3] = red[i];
+ }
+ break;
+ default:
+ gl_problem(ctx, "bad format in gl_pack_rgba_span\n");
+ }
+ if (packing->SwapBytes) {
+ gl_swap4( (GLuint *) dst, n );
+ }
+ }
+ break;
+ case GL_UNSIGNED_BYTE_3_3_2:
+ if (format == GL_RGB) {
+ GLubyte *dst = (GLubyte *) destination;
+ for (i=0;i<n;i++) {
+ dst[i] = (((GLint) (red[i] * 7.0F)) << 5)
+ | (((GLint) (green[i] * 7.0F)) << 2)
+ | (((GLint) (blue[i] * 3.0F)) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_BYTE_2_3_3_REV:
+ if (format == GL_RGB) {
+ GLubyte *dst = (GLubyte *) destination;
+ for (i=0;i<n;i++) {
+ dst[i] = (((GLint) (red[i] * 7.0F)) )
+ | (((GLint) (green[i] * 7.0F)) << 3)
+ | (((GLint) (blue[i] * 3.0F)) << 5);
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5:
+ if (format == GL_RGB) {
+ GLushort *dst = (GLushort *) destination;
+ for (i=0;i<n;i++) {
+ dst[i] = (((GLint) (red[i] * 31.0F)) << 11)
+ | (((GLint) (green[i] * 63.0F)) << 5)
+ | (((GLint) (blue[i] * 31.0F)) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_6_5_REV:
+ if (format == GL_RGB) {
+ GLushort *dst = (GLushort *) destination;
+ for (i=0;i<n;i++) {
+ dst[i] = (((GLint) (red[i] * 31.0F)) )
+ | (((GLint) (green[i] * 63.0F)) << 5)
+ | (((GLint) (blue[i] * 31.0F)) << 11);
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ if (format == GL_RGB) {
+ GLushort *dst = (GLushort *) destination;
+ for (i=0;i<n;i++) {
+ dst[i] = (((GLint) (red[i] * 15.0F)) << 12)
+ | (((GLint) (green[i] * 15.0F)) << 8)
+ | (((GLint) (blue[i] * 15.0F)) << 4)
+ | (((GLint) (alpha[i] * 15.0F)) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV:
+ if (format == GL_RGB) {
+ GLushort *dst = (GLushort *) destination;
+ for (i=0;i<n;i++) {
+ dst[i] = (((GLint) (red[i] * 15.0F)) )
+ | (((GLint) (green[i] * 15.0F)) << 4)
+ | (((GLint) (blue[i] * 15.0F)) << 8)
+ | (((GLint) (alpha[i] * 15.0F)) << 12);
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ if (format == GL_RGB) {
+ GLushort *dst = (GLushort *) destination;
+ for (i=0;i<n;i++) {
+ dst[i] = (((GLint) (red[i] * 31.0F)) << 11)
+ | (((GLint) (green[i] * 31.0F)) << 6)
+ | (((GLint) (blue[i] * 31.0F)) << 1)
+ | (((GLint) (alpha[i] * 1.0F)) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV:
+ if (format == GL_RGB) {
+ GLushort *dst = (GLushort *) destination;
+ for (i=0;i<n;i++) {
+ dst[i] = (((GLint) (red[i] * 31.0F)) )
+ | (((GLint) (green[i] * 31.0F)) << 5)
+ | (((GLint) (blue[i] * 31.0F)) << 10)
+ | (((GLint) (alpha[i] * 1.0F)) << 15);
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8:
+ if (format == GL_RGBA) {
+ GLuint *dst = (GLuint *) destination;
+ for (i=0;i<n;i++) {
+ dst[i] = (((GLuint) (red[i] * 255.0F)) << 24)
+ | (((GLuint) (green[i] * 255.0F)) << 16)
+ | (((GLuint) (blue[i] * 255.0F)) << 8)
+ | (((GLuint) (alpha[i] * 255.0F)) );
+ }
+ }
+ else if (format == GL_BGRA) {
+ GLuint *dst = (GLuint *) destination;
+ for (i=0;i<n;i++) {
+ dst[i] = (((GLuint) (blue[i] * 255.0F)) << 24)
+ | (((GLuint) (green[i] * 255.0F)) << 16)
+ | (((GLuint) (red[i] * 255.0F)) << 8)
+ | (((GLuint) (alpha[i] * 255.0F)) );
+ }
+ }
+ else if (format == GL_ABGR_EXT) {
+ GLuint *dst = (GLuint *) destination;
+ for (i=0;i<n;i++) {
+ dst[i] = (((GLuint) (alpha[i] * 255.0F)) << 24)
+ | (((GLuint) (blue[i] * 255.0F)) << 16)
+ | (((GLuint) (green[i] * 255.0F)) << 8)
+ | (((GLuint) (red[i] * 255.0F)) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT_8_8_8_8_REV:
+ if (format == GL_RGBA) {
+ GLuint *dst = (GLuint *) destination;
+ for (i=0;i<n;i++) {
+ dst[i] = (((GLuint) (red[i] * 255.0F)) )
+ | (((GLuint) (green[i] * 255.0F)) << 8)
+ | (((GLuint) (blue[i] * 255.0F)) << 16)
+ | (((GLuint) (alpha[i] * 255.0F)) << 24);
+ }
+ }
+ else if (format == GL_BGRA) {
+ GLuint *dst = (GLuint *) destination;
+ for (i=0;i<n;i++) {
+ dst[i] = (((GLuint) (blue[i] * 255.0F)) )
+ | (((GLuint) (green[i] * 255.0F)) << 8)
+ | (((GLuint) (red[i] * 255.0F)) << 16)
+ | (((GLuint) (alpha[i] * 255.0F)) << 24);
+ }
+ }
+ else if (format == GL_ABGR_EXT) {
+ GLuint *dst = (GLuint *) destination;
+ for (i=0;i<n;i++) {
+ dst[i] = (((GLuint) (alpha[i] * 255.0F)) )
+ | (((GLuint) (blue[i] * 255.0F)) << 8)
+ | (((GLuint) (green[i] * 255.0F)) << 16)
+ | (((GLuint) (red[i] * 255.0F)) << 24);
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT_10_10_10_2:
+ if (format == GL_RGBA) {
+ GLuint *dst = (GLuint *) destination;
+ for (i=0;i<n;i++) {
+ dst[i] = (((GLuint) (red[i] * 1023.0F)) << 22)
+ | (((GLuint) (green[i] * 1023.0F)) << 12)
+ | (((GLuint) (blue[i] * 1023.0F)) << 2)
+ | (((GLuint) (alpha[i] * 3.0F)) );
+ }
+ }
+ else if (format == GL_BGRA) {
+ GLuint *dst = (GLuint *) destination;
+ for (i=0;i<n;i++) {
+ dst[i] = (((GLuint) (blue[i] * 1023.0F)) << 22)
+ | (((GLuint) (green[i] * 1023.0F)) << 12)
+ | (((GLuint) (red[i] * 1023.0F)) << 2)
+ | (((GLuint) (alpha[i] * 3.0F)) );
+ }
+ }
+ else if (format == GL_ABGR_EXT) {
+ GLuint *dst = (GLuint *) destination;
+ for (i=0;i<n;i++) {
+ dst[i] = (((GLuint) (alpha[i] * 1023.0F)) << 22)
+ | (((GLuint) (blue[i] * 1023.0F)) << 12)
+ | (((GLuint) (green[i] * 1023.0F)) << 2)
+ | (((GLuint) (red[i] * 3.0F)) );
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ if (format == GL_RGBA) {
+ GLuint *dst = (GLuint *) destination;
+ for (i=0;i<n;i++) {
+ dst[i] = (((GLuint) (red[i] * 1023.0F)) )
+ | (((GLuint) (green[i] * 1023.0F)) << 10)
+ | (((GLuint) (blue[i] * 1023.0F)) << 20)
+ | (((GLuint) (alpha[i] * 3.0F)) << 30);
+ }
+ }
+ else if (format == GL_BGRA) {
+ GLuint *dst = (GLuint *) destination;
+ for (i=0;i<n;i++) {
+ dst[i] = (((GLuint) (blue[i] * 1023.0F)) )
+ | (((GLuint) (green[i] * 1023.0F)) << 10)
+ | (((GLuint) (red[i] * 1023.0F)) << 20)
+ | (((GLuint) (alpha[i] * 3.0F)) << 30);
+ }
+ }
+ else if (format == GL_ABGR_EXT) {
+ GLuint *dst = (GLuint *) destination;
+ for (i=0;i<n;i++) {
+ dst[i] = (((GLuint) (alpha[i] * 1023.0F)) )
+ | (((GLuint) (blue[i] * 1023.0F)) << 10)
+ | (((GLuint) (green[i] * 1023.0F)) << 20)
+ | (((GLuint) (red[i] * 3.0F)) << 30);
+ }
+ }
+ break;
+ default:
+ gl_problem( ctx, "bad type in gl_pack_rgba_span" );
+ }
+ }
+}
diff --git a/src/mesa/main/image.h b/src/mesa/main/image.h
new file mode 100644
index 0000000000..3fd2ca8b33
--- /dev/null
+++ b/src/mesa/main/image.h
@@ -0,0 +1,109 @@
+/* $Id: image.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef IMAGE_H
+#define IMAGE_H
+
+
+#include "types.h"
+
+
+extern void gl_flip_bytes( GLubyte *p, GLuint n );
+
+
+extern void gl_swap2( GLushort *p, GLuint n );
+
+extern void gl_swap4( GLuint *p, GLuint n );
+
+
+extern GLint gl_sizeof_type( GLenum type );
+
+extern GLint gl_sizeof_packed_type( GLenum type );
+
+extern GLint gl_components_in_format( GLenum format );
+
+extern GLint gl_bytes_per_pixel( GLenum format, GLenum type );
+
+extern GLboolean gl_is_legal_format_and_type( GLenum format, GLenum type );
+
+
+extern GLvoid *
+gl_pixel_addr_in_image( const struct gl_pixelstore_attrib *packing,
+ const GLvoid *image, GLsizei width,
+ GLsizei height, GLenum format, GLenum type,
+ GLint img, GLint row, GLint column );
+
+
+extern struct gl_image *
+gl_unpack_bitmap( GLcontext *ctx, GLsizei width, GLsizei height,
+ const GLubyte *bitmap,
+ const struct gl_pixelstore_attrib *packing );
+
+
+extern void gl_unpack_polygon_stipple( const GLcontext *ctx,
+ const GLubyte *pattern,
+ GLuint dest[32] );
+
+
+extern void gl_pack_polygon_stipple( const GLcontext *ctx,
+ const GLuint pattern[32],
+ GLubyte *dest );
+
+
+extern struct gl_image *
+gl_unpack_image( GLcontext *ctx, GLint width, GLint height,
+ GLenum srcFormat, GLenum srcType, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing );
+
+
+
+struct gl_image *
+gl_unpack_image3D( GLcontext *ctx, GLint width, GLint height,GLint depth,
+ GLenum srcFormat, GLenum srcType, const GLvoid *pixels,
+ const struct gl_pixelstore_attrib *packing );
+
+
+extern void
+gl_pack_rgba_span( const GLcontext *ctx,
+ GLuint n, CONST GLubyte rgba[][4],
+ GLenum format, GLenum type, GLvoid *dest,
+ const struct gl_pixelstore_attrib *packing,
+ GLboolean applyTransferOps );
+
+
+extern void gl_free_image( struct gl_image *image );
+
+
+extern GLboolean gl_image_error_test( GLcontext *ctx,
+ const struct gl_image *image,
+ const char *msg );
+
+
+#endif
diff --git a/src/mesa/main/light.c b/src/mesa/main/light.c
new file mode 100644
index 0000000000..cc396f85a5
--- /dev/null
+++ b/src/mesa/main/light.c
@@ -0,0 +1,1183 @@
+/* $Id: light.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <assert.h>
+#include <float.h>
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "context.h"
+#include "enums.h"
+#include "light.h"
+#include "macros.h"
+#include "matrix.h"
+#include "mmath.h"
+#include "simple_list.h"
+#include "types.h"
+#include "vb.h"
+#include "xform.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+
+void gl_ShadeModel( GLcontext *ctx, GLenum mode )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glShadeModel");
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ fprintf(stderr, "glShadeModel %s\n", gl_lookup_enum_by_nr(mode));
+
+ switch (mode) {
+ case GL_FLAT:
+ case GL_SMOOTH:
+ if (ctx->Light.ShadeModel!=mode) {
+ ctx->Light.ShadeModel = mode;
+ ctx->TriangleCaps ^= DD_FLATSHADE;
+ ctx->NewState |= NEW_RASTER_OPS;
+ }
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glShadeModel" );
+ }
+
+ if (ctx->Driver.ShadeModel)
+ (*ctx->Driver.ShadeModel)( ctx, mode );
+}
+
+
+
+void gl_Lightfv( GLcontext *ctx,
+ GLenum light, GLenum pname, const GLfloat *params,
+ GLint nparams )
+{
+ GLint l;
+
+ (void) nparams;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLight");
+
+ l = (GLint) (light - GL_LIGHT0);
+
+ if (l<0 || l>=MAX_LIGHTS) {
+ gl_error( ctx, GL_INVALID_ENUM, "glLight" );
+ return;
+ }
+
+ switch (pname) {
+ case GL_AMBIENT:
+ COPY_4V( ctx->Light.Light[l].Ambient, params );
+ break;
+ case GL_DIFFUSE:
+ COPY_4V( ctx->Light.Light[l].Diffuse, params );
+ break;
+ case GL_SPECULAR:
+ COPY_4V( ctx->Light.Light[l].Specular, params );
+ break;
+ case GL_POSITION:
+ /* transform position by ModelView matrix */
+ TRANSFORM_POINT( ctx->Light.Light[l].EyePosition,
+ ctx->ModelView.m,
+ params );
+ break;
+ case GL_SPOT_DIRECTION:
+ /* transform direction by inverse modelview */
+ if (ctx->ModelView.flags & MAT_DIRTY_INVERSE) {
+ gl_matrix_analyze( &ctx->ModelView );
+ }
+ TRANSFORM_NORMAL( ctx->Light.Light[l].EyeDirection,
+ params,
+ ctx->ModelView.inv );
+ break;
+ case GL_SPOT_EXPONENT:
+ if (params[0]<0.0 || params[0]>128.0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glLight" );
+ return;
+ }
+ if (ctx->Light.Light[l].SpotExponent != params[0]) {
+ ctx->Light.Light[l].SpotExponent = params[0];
+ gl_compute_spot_exp_table( &ctx->Light.Light[l] );
+ }
+ break;
+ case GL_SPOT_CUTOFF:
+ if ((params[0]<0.0 || params[0]>90.0) && params[0]!=180.0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glLight" );
+ return;
+ }
+ ctx->Light.Light[l].SpotCutoff = params[0];
+ ctx->Light.Light[l].CosCutoff = cos(params[0]*DEG2RAD);
+ if (ctx->Light.Light[l].CosCutoff < 0)
+ ctx->Light.Light[l].CosCutoff = 0;
+ break;
+ case GL_CONSTANT_ATTENUATION:
+ if (params[0]<0.0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glLight" );
+ return;
+ }
+ ctx->Light.Light[l].ConstantAttenuation = params[0];
+ break;
+ case GL_LINEAR_ATTENUATION:
+ if (params[0]<0.0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glLight" );
+ return;
+ }
+ ctx->Light.Light[l].LinearAttenuation = params[0];
+ break;
+ case GL_QUADRATIC_ATTENUATION:
+ if (params[0]<0.0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glLight" );
+ return;
+ }
+ ctx->Light.Light[l].QuadraticAttenuation = params[0];
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glLight" );
+ break;
+ }
+
+ ctx->NewState |= NEW_LIGHTING;
+}
+
+
+
+void gl_GetLightfv( GLcontext *ctx,
+ GLenum light, GLenum pname, GLfloat *params )
+{
+ GLint l = (GLint) (light - GL_LIGHT0);
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetLight");
+
+ if (l<0 || l>=MAX_LIGHTS) {
+ gl_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
+ return;
+ }
+
+ switch (pname) {
+ case GL_AMBIENT:
+ COPY_4V( params, ctx->Light.Light[l].Ambient );
+ break;
+ case GL_DIFFUSE:
+ COPY_4V( params, ctx->Light.Light[l].Diffuse );
+ break;
+ case GL_SPECULAR:
+ COPY_4V( params, ctx->Light.Light[l].Specular );
+ break;
+ case GL_POSITION:
+ COPY_4V( params, ctx->Light.Light[l].EyePosition );
+ break;
+ case GL_SPOT_DIRECTION:
+ COPY_3V( params, ctx->Light.Light[l].EyeDirection );
+ break;
+ case GL_SPOT_EXPONENT:
+ params[0] = ctx->Light.Light[l].SpotExponent;
+ break;
+ case GL_SPOT_CUTOFF:
+ params[0] = ctx->Light.Light[l].SpotCutoff;
+ break;
+ case GL_CONSTANT_ATTENUATION:
+ params[0] = ctx->Light.Light[l].ConstantAttenuation;
+ break;
+ case GL_LINEAR_ATTENUATION:
+ params[0] = ctx->Light.Light[l].LinearAttenuation;
+ break;
+ case GL_QUADRATIC_ATTENUATION:
+ params[0] = ctx->Light.Light[l].QuadraticAttenuation;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetLightfv" );
+ break;
+ }
+}
+
+
+
+void gl_GetLightiv( GLcontext *ctx, GLenum light, GLenum pname, GLint *params )
+{
+ GLint l = (GLint) (light - GL_LIGHT0);
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetLight");
+
+ if (l<0 || l>=MAX_LIGHTS) {
+ gl_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
+ return;
+ }
+
+ switch (pname) {
+ case GL_AMBIENT:
+ params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[0]);
+ params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[1]);
+ params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[2]);
+ params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Ambient[3]);
+ break;
+ case GL_DIFFUSE:
+ params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[0]);
+ params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[1]);
+ params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[2]);
+ params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Diffuse[3]);
+ break;
+ case GL_SPECULAR:
+ params[0] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[0]);
+ params[1] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[1]);
+ params[2] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[2]);
+ params[3] = FLOAT_TO_INT(ctx->Light.Light[l].Specular[3]);
+ break;
+ case GL_POSITION:
+ params[0] = (GLint) ctx->Light.Light[l].EyePosition[0];
+ params[1] = (GLint) ctx->Light.Light[l].EyePosition[1];
+ params[2] = (GLint) ctx->Light.Light[l].EyePosition[2];
+ params[3] = (GLint) ctx->Light.Light[l].EyePosition[3];
+ break;
+ case GL_SPOT_DIRECTION:
+ params[0] = (GLint) ctx->Light.Light[l].EyeDirection[0];
+ params[1] = (GLint) ctx->Light.Light[l].EyeDirection[1];
+ params[2] = (GLint) ctx->Light.Light[l].EyeDirection[2];
+ break;
+ case GL_SPOT_EXPONENT:
+ params[0] = (GLint) ctx->Light.Light[l].SpotExponent;
+ break;
+ case GL_SPOT_CUTOFF:
+ params[0] = (GLint) ctx->Light.Light[l].SpotCutoff;
+ break;
+ case GL_CONSTANT_ATTENUATION:
+ params[0] = (GLint) ctx->Light.Light[l].ConstantAttenuation;
+ break;
+ case GL_LINEAR_ATTENUATION:
+ params[0] = (GLint) ctx->Light.Light[l].LinearAttenuation;
+ break;
+ case GL_QUADRATIC_ATTENUATION:
+ params[0] = (GLint) ctx->Light.Light[l].QuadraticAttenuation;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetLightiv" );
+ break;
+ }
+}
+
+
+
+/**********************************************************************/
+/*** Light Model ***/
+/**********************************************************************/
+
+
+void gl_LightModelfv( GLcontext *ctx, GLenum pname, const GLfloat *params )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLightModel");
+
+ switch (pname) {
+ case GL_LIGHT_MODEL_AMBIENT:
+ COPY_4V( ctx->Light.Model.Ambient, params );
+ break;
+ case GL_LIGHT_MODEL_LOCAL_VIEWER:
+ if (params[0]==0.0)
+ ctx->Light.Model.LocalViewer = GL_FALSE;
+ else
+ ctx->Light.Model.LocalViewer = GL_TRUE;
+ break;
+ case GL_LIGHT_MODEL_TWO_SIDE:
+ if (params[0]==0.0)
+ ctx->Light.Model.TwoSide = GL_FALSE;
+ else
+ ctx->Light.Model.TwoSide = GL_TRUE;
+ break;
+ case GL_LIGHT_MODEL_COLOR_CONTROL:
+ ctx->TriangleCaps &= ~DD_SEPERATE_SPECULAR;
+ if (params[0] == (GLfloat) GL_SINGLE_COLOR)
+ ctx->Light.Model.ColorControl = GL_SINGLE_COLOR;
+ else if (params[0] == (GLfloat) GL_SEPARATE_SPECULAR_COLOR) {
+ ctx->Light.Model.ColorControl = GL_SEPARATE_SPECULAR_COLOR;
+ ctx->TriangleCaps |= DD_SEPERATE_SPECULAR;
+ } else
+ gl_error( ctx, GL_INVALID_ENUM, "glLightModel(param)" );
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glLightModel" );
+ break;
+ }
+ ctx->NewState |= NEW_LIGHTING;
+}
+
+
+
+
+/********** MATERIAL **********/
+
+
+/*
+ * Given a face and pname value (ala glColorMaterial), compute a bitmask
+ * of the targeted material values.
+ */
+GLuint gl_material_bitmask( GLcontext *ctx, GLenum face, GLenum pname,
+ GLuint legal,
+ const char *where )
+{
+ GLuint bitmask = 0;
+
+ /* Make a bitmask indicating what material attribute(s) we're updating */
+ switch (pname) {
+ case GL_EMISSION:
+ bitmask |= FRONT_EMISSION_BIT | BACK_EMISSION_BIT;
+ break;
+ case GL_AMBIENT:
+ bitmask |= FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT;
+ break;
+ case GL_DIFFUSE:
+ bitmask |= FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT;
+ break;
+ case GL_SPECULAR:
+ bitmask |= FRONT_SPECULAR_BIT | BACK_SPECULAR_BIT;
+ break;
+ case GL_SHININESS:
+ bitmask |= FRONT_SHININESS_BIT | BACK_SHININESS_BIT;
+ break;
+ case GL_AMBIENT_AND_DIFFUSE:
+ bitmask |= FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT;
+ bitmask |= FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT;
+ break;
+ case GL_COLOR_INDEXES:
+ bitmask |= FRONT_INDEXES_BIT | BACK_INDEXES_BIT;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, where );
+ return 0;
+ }
+
+ if (face==GL_FRONT) {
+ bitmask &= FRONT_MATERIAL_BITS;
+ }
+ else if (face==GL_BACK) {
+ bitmask &= BACK_MATERIAL_BITS;
+ }
+ else if (face != GL_FRONT_AND_BACK) {
+ gl_error( ctx, GL_INVALID_ENUM, where );
+ return 0;
+ }
+
+ if (bitmask & ~legal) {
+ gl_error( ctx, GL_INVALID_ENUM, where );
+ return 0;
+ }
+
+ return bitmask;
+}
+
+
+
+
+
+
+/*
+ * Check if the global material has to be updated with info that was
+ * associated with a vertex via glMaterial.
+ * This function is used when any material values get changed between
+ * glBegin/glEnd either by calling glMaterial() or by calling glColor()
+ * when GL_COLOR_MATERIAL is enabled.
+ *
+ * KW: Added code here to keep the precomputed variables uptodate.
+ * This means we can use the faster shade functions when using
+ * GL_COLOR_MATERIAL, and we can also now use the precomputed
+ * values in the slower shading functions, which further offsets
+ * the cost of doing this here.
+ */
+void gl_update_material( GLcontext *ctx,
+ struct gl_material *src,
+ GLuint bitmask )
+{
+ struct gl_light *light, *list = &ctx->Light.EnabledList;
+ GLfloat tmp[4];
+
+ if (ctx->Light.ColorMaterialEnabled)
+ bitmask &= ~ctx->Light.ColorMaterialBitmask;
+
+ if (!bitmask)
+ return;
+
+ if (bitmask & FRONT_AMBIENT_BIT) {
+ struct gl_material *mat = &ctx->Light.Material[0];
+ SUB_3V( tmp, src[0].Ambient, mat->Ambient );
+ ACC_SCALE_3V( ctx->Light.BaseColor[0], ctx->Light.Model.Ambient, tmp);
+ foreach (light, list) {
+ ACC_SCALE_3V( ctx->Light.BaseColor[0], light->Ambient, tmp );
+ }
+ COPY_4FV( mat->Ambient, src[0].Ambient );
+ }
+ if (bitmask & BACK_AMBIENT_BIT) {
+ struct gl_material *mat = &ctx->Light.Material[1];
+ SUB_3V( tmp, src[1].Ambient, mat->Ambient );
+ ACC_SCALE_3V( ctx->Light.BaseColor[1], ctx->Light.Model.Ambient, tmp);
+ foreach (light, list) {
+ ACC_SCALE_3V( ctx->Light.BaseColor[0], light->Ambient, tmp );
+ }
+ COPY_4FV( mat->Ambient, src[1].Ambient );
+ }
+ if (bitmask & FRONT_DIFFUSE_BIT) {
+ struct gl_material *mat = &ctx->Light.Material[0];
+ SUB_3V( tmp, src[0].Diffuse, mat->Diffuse );
+ foreach (light, list) {
+ ACC_SCALE_3V( light->MatDiffuse[0], light->Diffuse, tmp );
+ }
+ COPY_4FV( mat->Diffuse, src[0].Diffuse );
+ FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[0], mat->Diffuse[3]);
+ }
+ if (bitmask & BACK_DIFFUSE_BIT) {
+ struct gl_material *mat = &ctx->Light.Material[1];
+ SUB_3V( tmp, src[1].Diffuse, mat->Diffuse );
+ foreach (light, list) {
+ ACC_SCALE_3V( light->MatDiffuse[1], light->Diffuse, tmp );
+ }
+ COPY_4FV( mat->Diffuse, src[1].Diffuse );
+ FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[1], mat->Diffuse[3]);
+ }
+ if (bitmask & FRONT_SPECULAR_BIT) {
+ struct gl_material *mat = &ctx->Light.Material[0];
+ SUB_3V( tmp, src[0].Specular, mat->Specular );
+ foreach (light, list) {
+ if (light->Flags & LIGHT_SPECULAR) {
+ ACC_SCALE_3V( light->MatSpecular[0], light->Specular, tmp );
+ light->IsMatSpecular[0] =
+ (LEN_SQUARED_3FV(light->MatSpecular[0]) > 1e-16);
+ }
+ }
+ COPY_4FV( mat->Specular, src[0].Specular );
+ }
+ if (bitmask & BACK_SPECULAR_BIT) {
+ struct gl_material *mat = &ctx->Light.Material[1];
+ SUB_3V( tmp, src[1].Specular, mat->Specular );
+ foreach (light, list) {
+ if (light->Flags & LIGHT_SPECULAR) {
+ ACC_SCALE_3V( light->MatSpecular[1], light->Specular, tmp );
+ light->IsMatSpecular[1] =
+ (LEN_SQUARED_3FV(light->MatSpecular[1]) > 1e-16);
+ }
+ }
+ COPY_4FV( mat->Specular, src[1].Specular );
+ }
+ if (bitmask & FRONT_EMISSION_BIT) {
+ struct gl_material *mat = &ctx->Light.Material[0];
+ SUB_3V( tmp, src[0].Emission, mat->Emission );
+ ACC_3V( ctx->Light.BaseColor[0], tmp );
+ COPY_4FV( mat->Emission, src[0].Emission );
+ }
+ if (bitmask & BACK_EMISSION_BIT) {
+ struct gl_material *mat = &ctx->Light.Material[1];
+ SUB_3V( tmp, src[1].Emission, mat->Emission );
+ ACC_3V( ctx->Light.BaseColor[1], tmp );
+ COPY_4FV( mat->Emission, src[1].Emission );
+ }
+ if (bitmask & FRONT_SHININESS_BIT) {
+ GLfloat shininess = ctx->Light.Material[0].Shininess = src[0].Shininess;
+ gl_compute_shine_table( ctx, 0, shininess );
+ gl_compute_shine_table( ctx, 2, shininess * .5 );
+ }
+ if (bitmask & BACK_SHININESS_BIT) {
+ GLfloat shininess = ctx->Light.Material[1].Shininess = src[1].Shininess;
+ gl_compute_shine_table( ctx, 1, shininess );
+ gl_compute_shine_table( ctx, 3, shininess * .5 );
+ }
+ if (bitmask & FRONT_INDEXES_BIT) {
+ ctx->Light.Material[0].AmbientIndex = src[0].AmbientIndex;
+ ctx->Light.Material[0].DiffuseIndex = src[0].DiffuseIndex;
+ ctx->Light.Material[0].SpecularIndex = src[0].SpecularIndex;
+ }
+ if (bitmask & BACK_INDEXES_BIT) {
+ ctx->Light.Material[1].AmbientIndex = src[1].AmbientIndex;
+ ctx->Light.Material[1].DiffuseIndex = src[1].DiffuseIndex;
+ ctx->Light.Material[1].SpecularIndex = src[1].SpecularIndex;
+ }
+
+}
+
+
+
+
+
+
+void gl_update_color_material( GLcontext *ctx,
+ const GLubyte rgba[4] )
+{
+ struct gl_light *light, *list = &ctx->Light.EnabledList;
+ GLuint bitmask = ctx->Light.ColorMaterialBitmask;
+ GLfloat tmp[4], color[4];
+
+ UBYTE_RGBA_TO_FLOAT_RGBA( color, rgba );
+
+ if (bitmask & FRONT_AMBIENT_BIT) {
+ struct gl_material *mat = &ctx->Light.Material[0];
+ SUB_3V( tmp, color, mat->Ambient );
+ ACC_SCALE_3V( ctx->Light.BaseColor[0], ctx->Light.Model.Ambient, tmp);
+ foreach (light, list) {
+ ACC_SCALE_3V( ctx->Light.BaseColor[0], light->Ambient, tmp );
+ }
+ COPY_4FV( mat->Ambient, color );
+ }
+
+ if (bitmask & BACK_AMBIENT_BIT) {
+ struct gl_material *mat = &ctx->Light.Material[1];
+ SUB_3V( tmp, color, mat->Ambient );
+ ACC_SCALE_3V( ctx->Light.BaseColor[1], ctx->Light.Model.Ambient, tmp);
+ foreach (light, list) {
+ ACC_SCALE_3V( ctx->Light.BaseColor[0], light->Ambient, tmp );
+ }
+ COPY_4FV( mat->Ambient, color );
+ }
+
+ if (bitmask & FRONT_DIFFUSE_BIT) {
+ struct gl_material *mat = &ctx->Light.Material[0];
+ SUB_3V( tmp, color, mat->Diffuse );
+ foreach (light, list) {
+ ACC_SCALE_3V( light->MatDiffuse[0], light->Diffuse, tmp );
+ }
+ COPY_4FV( mat->Diffuse, color );
+ FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[0], mat->Diffuse[3]);
+ }
+
+ if (bitmask & BACK_DIFFUSE_BIT) {
+ struct gl_material *mat = &ctx->Light.Material[1];
+ SUB_3V( tmp, color, mat->Diffuse );
+ foreach (light, list) {
+ ACC_SCALE_3V( light->MatDiffuse[1], light->Diffuse, tmp );
+ }
+ COPY_4FV( mat->Diffuse, color );
+ FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[1], mat->Diffuse[3]);
+ }
+
+ if (bitmask & FRONT_SPECULAR_BIT) {
+ struct gl_material *mat = &ctx->Light.Material[0];
+ SUB_3V( tmp, color, mat->Specular );
+ foreach (light, list) {
+ if (light->Flags & LIGHT_SPECULAR) {
+ ACC_SCALE_3V( light->MatSpecular[0], light->Specular, tmp );
+ light->IsMatSpecular[0] =
+ (LEN_SQUARED_3FV(light->MatSpecular[0]) > 1e-16);
+ }
+ }
+ COPY_4FV( mat->Specular, color );
+ }
+ if (bitmask & BACK_SPECULAR_BIT) {
+ struct gl_material *mat = &ctx->Light.Material[1];
+ SUB_3V( tmp, color, mat->Specular );
+ foreach (light, list) {
+ if (light->Flags & LIGHT_SPECULAR) {
+ ACC_SCALE_3V( light->MatSpecular[1], light->Specular, tmp );
+ light->IsMatSpecular[1] =
+ (LEN_SQUARED_3FV(light->MatSpecular[1]) > 1e-16);
+ }
+ }
+ COPY_4FV( mat->Specular, color );
+ }
+ if (bitmask & FRONT_EMISSION_BIT) {
+ struct gl_material *mat = &ctx->Light.Material[0];
+ SUB_3V( tmp, color, mat->Emission );
+ ACC_3V( ctx->Light.BaseColor[0], tmp );
+ COPY_4FV( mat->Emission, color );
+ }
+ if (bitmask & BACK_EMISSION_BIT) {
+ struct gl_material *mat = &ctx->Light.Material[1];
+ SUB_3V( tmp, color, mat->Emission );
+ ACC_3V( ctx->Light.BaseColor[1], tmp );
+ COPY_4FV( mat->Emission, color );
+ }
+}
+
+
+
+
+void gl_ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
+{
+ GLuint bitmask;
+ GLuint legal = (FRONT_EMISSION_BIT | BACK_EMISSION_BIT |
+ FRONT_SPECULAR_BIT | BACK_SPECULAR_BIT |
+ FRONT_DIFFUSE_BIT | BACK_DIFFUSE_BIT |
+ FRONT_AMBIENT_BIT | BACK_AMBIENT_BIT);
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glColorMaterial");
+
+ bitmask = gl_material_bitmask( ctx, face, mode, legal, "glColorMaterial" );
+
+ if (bitmask != 0) {
+ ctx->Light.ColorMaterialBitmask = bitmask;
+ ctx->Light.ColorMaterialFace = face;
+ ctx->Light.ColorMaterialMode = mode;
+ }
+}
+
+
+
+/* KW: This is now called directly (ie by name) from the glMaterial*
+ * API functions.
+ */
+void gl_Materialfv( GLcontext *ctx,
+ GLenum face, GLenum pname, const GLfloat *params )
+{
+ struct immediate *IM;
+ struct gl_material *mat;
+ GLuint bitmask;
+ GLuint count;
+
+ bitmask = gl_material_bitmask( ctx, face, pname, ~0, "gl_Materialfv" );
+ if (bitmask == 0)
+ return;
+
+ IM = ctx->input;
+ count = IM->Count;
+
+ if (!(IM->Flag[count] & VERT_MATERIAL)) {
+ IM->Flag[count] |= VERT_MATERIAL;
+ IM->MaterialMask[count] = 0;
+ }
+
+ IM->MaterialMask[count] |= bitmask;
+ mat = IM->Material[count];
+ IM->LastMaterial = count;
+
+ if (bitmask & FRONT_AMBIENT_BIT) {
+ COPY_4FV( mat[0].Ambient, params );
+ }
+ if (bitmask & BACK_AMBIENT_BIT) {
+ COPY_4FV( mat[1].Ambient, params );
+ }
+ if (bitmask & FRONT_DIFFUSE_BIT) {
+ COPY_4FV( mat[0].Diffuse, params );
+ }
+ if (bitmask & BACK_DIFFUSE_BIT) {
+ COPY_4FV( mat[1].Diffuse, params );
+ }
+ if (bitmask & FRONT_SPECULAR_BIT) {
+ COPY_4FV( mat[0].Specular, params );
+ }
+ if (bitmask & BACK_SPECULAR_BIT) {
+ COPY_4FV( mat[1].Specular, params );
+ }
+ if (bitmask & FRONT_EMISSION_BIT) {
+ COPY_4FV( mat[0].Emission, params );
+ }
+ if (bitmask & BACK_EMISSION_BIT) {
+ COPY_4FV( mat[1].Emission, params );
+ }
+ if (bitmask & FRONT_SHININESS_BIT) {
+ GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F );
+ mat[0].Shininess = shininess;
+ }
+ if (bitmask & BACK_SHININESS_BIT) {
+ GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F );
+ mat[1].Shininess = shininess;
+ }
+ if (bitmask & FRONT_INDEXES_BIT) {
+ mat[0].AmbientIndex = params[0];
+ mat[0].DiffuseIndex = params[1];
+ mat[0].SpecularIndex = params[2];
+ }
+ if (bitmask & BACK_INDEXES_BIT) {
+ mat[1].AmbientIndex = params[0];
+ mat[1].DiffuseIndex = params[1];
+ mat[1].SpecularIndex = params[2];
+ }
+}
+
+
+
+
+void gl_GetMaterialfv( GLcontext *ctx,
+ GLenum face, GLenum pname, GLfloat *params )
+{
+ GLuint f;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetMaterialfv");
+
+ if (face==GL_FRONT) {
+ f = 0;
+ }
+ else if (face==GL_BACK) {
+ f = 1;
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(face)" );
+ return;
+ }
+ switch (pname) {
+ case GL_AMBIENT:
+ COPY_4FV( params, ctx->Light.Material[f].Ambient );
+ break;
+ case GL_DIFFUSE:
+ COPY_4FV( params, ctx->Light.Material[f].Diffuse );
+ break;
+ case GL_SPECULAR:
+ COPY_4FV( params, ctx->Light.Material[f].Specular );
+ break;
+ case GL_EMISSION:
+ COPY_4FV( params, ctx->Light.Material[f].Emission );
+ break;
+ case GL_SHININESS:
+ *params = ctx->Light.Material[f].Shininess;
+ break;
+ case GL_COLOR_INDEXES:
+ params[0] = ctx->Light.Material[f].AmbientIndex;
+ params[1] = ctx->Light.Material[f].DiffuseIndex;
+ params[2] = ctx->Light.Material[f].SpecularIndex;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
+ }
+}
+
+
+
+void gl_GetMaterialiv( GLcontext *ctx,
+ GLenum face, GLenum pname, GLint *params )
+{
+ GLuint f;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetMaterialiv");
+
+ if (face==GL_FRONT) {
+ f = 0;
+ }
+ else if (face==GL_BACK) {
+ f = 1;
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialiv(face)" );
+ return;
+ }
+ switch (pname) {
+ case GL_AMBIENT:
+ params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[0] );
+ params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[1] );
+ params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[2] );
+ params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Ambient[3] );
+ break;
+ case GL_DIFFUSE:
+ params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[0] );
+ params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[1] );
+ params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[2] );
+ params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Diffuse[3] );
+ break;
+ case GL_SPECULAR:
+ params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[0] );
+ params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[1] );
+ params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[2] );
+ params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Specular[3] );
+ break;
+ case GL_EMISSION:
+ params[0] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[0] );
+ params[1] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[1] );
+ params[2] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[2] );
+ params[3] = FLOAT_TO_INT( ctx->Light.Material[f].Emission[3] );
+ break;
+ case GL_SHININESS:
+ *params = ROUNDF( ctx->Light.Material[f].Shininess );
+ break;
+ case GL_COLOR_INDEXES:
+ params[0] = ROUNDF( ctx->Light.Material[f].AmbientIndex );
+ params[1] = ROUNDF( ctx->Light.Material[f].DiffuseIndex );
+ params[2] = ROUNDF( ctx->Light.Material[f].SpecularIndex );
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
+ }
+}
+
+
+
+
+/**********************************************************************/
+/***** Lighting computation *****/
+/**********************************************************************/
+
+
+/*
+ * Notes:
+ * When two-sided lighting is enabled we compute the color (or index)
+ * for both the front and back side of the primitive. Then, when the
+ * orientation of the facet is later learned, we can determine which
+ * color (or index) to use for rendering.
+ *
+ * KW: We now know orientation in advance and only shade for
+ * the side or sides which are actually required.
+ *
+ * Variables:
+ * n = normal vector
+ * V = vertex position
+ * P = light source position
+ * Pe = (0,0,0,1)
+ *
+ * Precomputed:
+ * IF P[3]==0 THEN
+ * // light at infinity
+ * IF local_viewer THEN
+ * VP_inf_norm = unit vector from V to P // Precompute
+ * ELSE
+ * // eye at infinity
+ * h_inf_norm = Normalize( VP + <0,0,1> ) // Precompute
+ * ENDIF
+ * ENDIF
+ *
+ * Functions:
+ * Normalize( v ) = normalized vector v
+ * Magnitude( v ) = length of vector v
+ */
+
+
+
+/*
+ * Whenever the spotlight exponent for a light changes we must call
+ * this function to recompute the exponent lookup table.
+ */
+void gl_compute_spot_exp_table( struct gl_light *l )
+{
+ int i;
+ double exponent = l->SpotExponent;
+ double tmp = 0;
+ int clamp = 0;
+
+ l->SpotExpTable[0][0] = 0.0;
+
+ for (i=EXP_TABLE_SIZE-1;i>0;i--) {
+ if (clamp == 0) {
+ tmp = pow(i/(double)(EXP_TABLE_SIZE-1), exponent);
+ if (tmp < FLT_MIN*100.0) {
+ tmp = 0.0;
+ clamp = 1;
+ }
+ }
+ l->SpotExpTable[i][0] = tmp;
+ }
+ for (i=0;i<EXP_TABLE_SIZE-1;i++) {
+ l->SpotExpTable[i][1] = l->SpotExpTable[i+1][0] - l->SpotExpTable[i][0];
+ }
+ l->SpotExpTable[EXP_TABLE_SIZE-1][1] = 0.0;
+}
+
+
+
+
+/* Calculate a new shine table. Doing this here saves a branch in
+ * lighting, and the cost of doing it early may be partially offset
+ * by keeping a MRU cache of shine tables for various shine values.
+ */
+static void compute_shine_table( struct gl_shine_tab *tab, GLfloat shininess )
+{
+ int i;
+ GLfloat *m = tab->tab;
+
+ m[0] = 0;
+ if (shininess == 0) {
+ for (i = 1 ; i <= SHINE_TABLE_SIZE ; i++)
+ m[i] = 1;
+ } else {
+ for (i = 1 ; i <= SHINE_TABLE_SIZE ; i++) {
+ double t = pow( i/(GLfloat)SHINE_TABLE_SIZE, shininess );
+ m[i] = 0;
+ if (t > 1e-20) m[i] = t;
+ }
+ }
+
+ tab->shininess = shininess;
+}
+
+#define DISTSQR(a,b) ((a-b)*(a-b))
+
+void gl_compute_shine_table( GLcontext *ctx, GLuint i, GLfloat shininess )
+{
+ struct gl_shine_tab *list = ctx->ShineTabList;
+ struct gl_shine_tab *s;
+
+ foreach(s, list)
+ if ( DISTSQR(s->shininess, shininess) < 1e-4 )
+ break;
+
+ if (s == list)
+ {
+ foreach(s, list)
+ if (s->refcount == 0) break;
+
+ compute_shine_table( s, shininess );
+ }
+
+ ctx->ShineTable[i]->refcount--;
+ ctx->ShineTable[i] = s;
+ move_to_tail( list, s );
+ s->refcount++;
+}
+
+
+
+
+void gl_reinit_light_attrib( GLcontext *ctx, struct gl_light_attrib *l )
+{
+ GLuint i;
+
+ if (ctx->ShineTable[0]->shininess != l->Material[0].Shininess) {
+ gl_compute_shine_table( ctx, 0, l->Material[0].Shininess );
+ gl_compute_shine_table( ctx, 2, l->Material[0].Shininess * .5 );
+ }
+
+ if (ctx->ShineTable[1]->shininess != l->Material[1].Shininess) {
+ gl_compute_shine_table( ctx, 1, l->Material[1].Shininess );
+ gl_compute_shine_table( ctx, 3, l->Material[1].Shininess * .5 );
+ }
+
+ make_empty_list( &l->EnabledList );
+ for (i = 0 ; i < MAX_LIGHTS ; i++) {
+ if (l->Light[i].Enabled)
+ insert_at_tail( &l->EnabledList, &l->Light[i] );
+ }
+}
+
+
+
+/*
+ * Examine current lighting parameters to determine if the optimized lighting
+ * function can be used.
+ * Also, precompute some lighting values such as the products of light
+ * source and material ambient, diffuse and specular coefficients.
+ */
+void gl_update_lighting( GLcontext *ctx )
+{
+ struct gl_light *light;
+
+ ctx->Light.Flags = 0;
+
+ foreach(light, &ctx->Light.EnabledList) {
+
+ light->Flags = 0;
+
+ if (light->EyePosition[3] != 0.0F)
+ light->Flags |= LIGHT_POSITIONAL;
+
+ if (LEN_SQUARED_3FV(light->Specular) > 1e-16)
+ light->Flags |= LIGHT_SPECULAR;
+
+ if (light->SpotCutoff != 180.0F)
+ light->Flags |= LIGHT_SPOT;
+
+ ctx->Light.Flags |= light->Flags;
+ }
+
+ ctx->Light.NeedVertices =
+ ((ctx->Light.Flags & (LIGHT_POSITIONAL|LIGHT_SPOT)) ||
+ (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) ||
+ (ctx->Light.Model.LocalViewer && (ctx->Light.Flags & LIGHT_SPECULAR)));
+
+
+ /* Precompute some shading values.
+ */
+ if (ctx->Visual->RGBAflag)
+ {
+ GLuint sides = ((ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) ? 2 : 1);
+ GLuint side;
+ for (side=0; side < sides; side++) {
+ struct gl_material *mat = &ctx->Light.Material[side];
+
+ COPY_3V(ctx->Light.BaseColor[side], mat->Emission);
+ ACC_SCALE_3V(ctx->Light.BaseColor[side],
+ ctx->Light.Model.Ambient,
+ mat->Ambient);
+
+ FLOAT_COLOR_TO_UBYTE_COLOR(ctx->Light.BaseAlpha[side],
+ ctx->Light.Material[side].Diffuse[3] );
+ }
+
+ foreach (light, &ctx->Light.EnabledList) {
+ for (side=0; side< sides; side++) {
+ struct gl_material *mat = &ctx->Light.Material[side];
+ SCALE_3V( light->MatDiffuse[side], light->Diffuse, mat->Diffuse );
+ SCALE_3V( light->MatAmbient[side], light->Ambient, mat->Ambient );
+ ACC_3V( ctx->Light.BaseColor[side], light->MatAmbient[side] );
+ if (light->Flags & LIGHT_SPECULAR)
+ {
+ SCALE_3V( light->MatSpecular[side], light->Specular,
+ mat->Specular);
+ light->IsMatSpecular[side] =
+ (LEN_SQUARED_3FV(light->MatSpecular[side]) > 1e-16);
+ }
+ else
+ light->IsMatSpecular[side] = 0;
+ }
+ }
+ }
+ else
+ {
+ static GLfloat ci[3] = { .30, .59, .11 };
+
+ foreach(light, &ctx->Light.EnabledList) {
+ light->dli = DOT3(ci, light->Diffuse);
+ light->sli = DOT3(ci, light->Specular);
+ }
+ }
+}
+
+/* Need to seriously restrict the circumstances under which these
+ * calc's are performed.
+ */
+void gl_compute_light_positions( GLcontext *ctx )
+{
+ struct gl_light *light;
+
+ if (ctx->Light.NeedVertices && !ctx->Light.Model.LocalViewer) {
+ GLfloat eye_z[3] = { 0, 0, 1 };
+ if (!ctx->NeedEyeCoords) {
+ TRANSFORM_NORMAL( ctx->EyeZDir, eye_z, ctx->ModelView.m );
+ } else {
+ COPY_3V( ctx->EyeZDir, eye_z );
+ }
+ }
+
+ foreach (light, &ctx->Light.EnabledList) {
+
+ if (!ctx->NeedEyeCoords) {
+ TRANSFORM_POINT( light->Position, ctx->ModelView.inv,
+ light->EyePosition );
+ } else {
+ COPY_4FV( light->Position, light->EyePosition );
+ }
+
+ if (!(light->Flags & LIGHT_POSITIONAL))
+ {
+ /* VP (VP) = Normalize( Position ) */
+ COPY_3V( light->VP_inf_norm, light->Position );
+ NORMALIZE_3FV( light->VP_inf_norm );
+
+ if (!ctx->Light.Model.LocalViewer)
+ {
+ /* h_inf_norm = Normalize( V_to_P + <0,0,1> ) */
+ ADD_3V( light->h_inf_norm, light->VP_inf_norm, ctx->EyeZDir);
+ NORMALIZE_3FV( light->h_inf_norm );
+ }
+
+ light->VP_inf_spot_attenuation = 1.0;
+ }
+
+ if (light->Flags & LIGHT_SPOT)
+ {
+ if (ctx->NeedEyeNormals) {
+ COPY_3V( light->NormDirection, light->EyeDirection );
+ } else {
+ TRANSFORM_NORMAL( light->NormDirection,
+ light->EyeDirection,
+ ctx->ModelView.m);
+ }
+
+ NORMALIZE_3FV( light->NormDirection );
+
+
+ /* Unlikely occurrance?
+ */
+ if (!(light->Flags & LIGHT_POSITIONAL)) {
+ GLfloat PV_dot_dir = - DOT3(light->VP_inf_norm,
+ light->NormDirection);
+
+ if (PV_dot_dir > light->CosCutoff) {
+ double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
+ int k = (int) x;
+ light->VP_inf_spot_attenuation =
+ (light->SpotExpTable[k][0] +
+ (x-k)*light->SpotExpTable[k][1]);
+ }
+ else
+ light->VP_inf_spot_attenuation = 0;
+ }
+ }
+ }
+}
+
+
+
+
+
+void gl_update_normal_transform( GLcontext *ctx )
+{
+ GLuint new_flag = 0;
+ normal_func *last = ctx->NormalTransform;
+
+ ctx->vb_rescale_factor = 1.0;
+
+ if (ctx->NeedEyeCoords) {
+ if (ctx->NeedNormals) {
+ GLuint transform = NORM_TRANSFORM_NO_ROT;
+
+ if (ctx->ModelView.flags & (MAT_FLAG_GENERAL |
+ MAT_FLAG_ROTATION |
+ MAT_FLAG_GENERAL_3D |
+ MAT_FLAG_PERSPECTIVE))
+ transform = NORM_TRANSFORM;
+
+
+ new_flag = ctx->NewState & NEW_MODELVIEW;
+ ctx->vb_rescale_factor = ctx->rescale_factor;
+
+ if (ctx->Transform.Normalize)
+ {
+ ctx->NormalTransform = gl_normal_tab[transform | NORM_NORMALIZE];
+ }
+ else if (ctx->Transform.RescaleNormals &&
+ ctx->rescale_factor != 1.0)
+ {
+ ctx->NormalTransform = gl_normal_tab[transform | NORM_RESCALE];
+ }
+ else
+ {
+ ctx->NormalTransform = gl_normal_tab[transform];
+ }
+ } else {
+ ctx->NormalTransform = 0;
+ }
+ }
+ else {
+ if (ctx->NeedNormals) {
+ ctx->vb_rescale_factor = 1.0/ctx->rescale_factor;
+
+ if (ctx->Transform.Normalize)
+ {
+ ctx->NormalTransform = gl_normal_tab[NORM_NORMALIZE];
+ }
+ else if (!ctx->Transform.RescaleNormals &&
+ ctx->rescale_factor != 1.0)
+ {
+ ctx->NormalTransform = gl_normal_tab[NORM_RESCALE];
+ }
+ else
+ {
+ ctx->NormalTransform = 0;
+ }
+ } else {
+ ctx->NormalTransform = 0;
+ }
+ }
+
+ if (last != ctx->NormalTransform || new_flag)
+ ctx->NewState |= NEW_NORMAL_TRANSFORM;
+}
+
diff --git a/src/mesa/main/light.h b/src/mesa/main/light.h
new file mode 100644
index 0000000000..18d25e9828
--- /dev/null
+++ b/src/mesa/main/light.h
@@ -0,0 +1,103 @@
+/* $Id: light.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef LIGHT_H
+#define LIGHT_H
+
+
+#include "types.h"
+
+struct gl_shine_tab {
+ struct gl_shine_tab *next, *prev;
+ GLfloat tab[SHINE_TABLE_SIZE+1];
+ GLfloat shininess;
+ GLuint refcount;
+};
+
+
+extern void gl_ShadeModel( GLcontext *ctx, GLenum mode );
+
+extern void gl_ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode );
+
+extern void gl_Lightfv( GLcontext *ctx,
+ GLenum light, GLenum pname, const GLfloat *params,
+ GLint nparams );
+
+extern void gl_LightModelfv( GLcontext *ctx,
+ GLenum pname, const GLfloat *params );
+
+
+extern GLuint gl_material_bitmask( GLcontext *ctx,
+ GLenum face, GLenum pname,
+ GLuint legal,
+ const char * );
+
+extern void gl_set_material( GLcontext *ctx, GLuint bitmask,
+ const GLfloat *params);
+
+extern void gl_Materialfv( GLcontext *ctx,
+ GLenum face, GLenum pname, const GLfloat *params );
+
+
+
+extern void gl_GetLightfv( GLcontext *ctx,
+ GLenum light, GLenum pname, GLfloat *params );
+
+extern void gl_GetLightiv( GLcontext *ctx,
+ GLenum light, GLenum pname, GLint *params );
+
+
+extern void gl_GetMaterialfv( GLcontext *ctx,
+ GLenum face, GLenum pname, GLfloat *params );
+
+extern void gl_GetMaterialiv( GLcontext *ctx,
+ GLenum face, GLenum pname, GLint *params );
+
+
+extern void gl_compute_spot_exp_table( struct gl_light *l );
+
+extern void gl_compute_shine_table( GLcontext *ctx, GLuint i,
+ GLfloat shininess );
+
+extern void gl_update_lighting( GLcontext *ctx );
+
+extern void gl_compute_light_positions( GLcontext *ctx );
+
+extern void gl_update_normal_transform( GLcontext *ctx );
+
+extern void gl_update_material( GLcontext *ctx,
+ struct gl_material *m,
+ GLuint bitmask );
+
+extern void gl_update_color_material( GLcontext *ctx, const GLubyte rgba[4] );
+
+
+#endif
+
diff --git a/src/mesa/main/lines.c b/src/mesa/main/lines.c
new file mode 100644
index 0000000000..ed671d7a82
--- /dev/null
+++ b/src/mesa/main/lines.c
@@ -0,0 +1,1146 @@
+/* $Id: lines.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <assert.h>
+#include "context.h"
+#include "depth.h"
+#include "feedback.h"
+#include "lines.h"
+#include "macros.h"
+#include "mmath.h"
+#include "pb.h"
+#include "texstate.h"
+#include "types.h"
+#include "vb.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+
+void gl_LineWidth( GLcontext *ctx, GLfloat width )
+{
+ if (width<=0.0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glLineWidth" );
+ return;
+ }
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLineWidth");
+
+ if (ctx->Line.Width != width) {
+ ctx->Line.Width = width;
+ ctx->TriangleCaps &= ~DD_LINE_WIDTH;
+ if (width != 1.0) ctx->TriangleCaps |= DD_LINE_WIDTH;
+ ctx->NewState |= NEW_RASTER_OPS;
+ }
+}
+
+
+
+void gl_LineStipple( GLcontext *ctx, GLint factor, GLushort pattern )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glLineStipple");
+ ctx->Line.StippleFactor = CLAMP( factor, 1, 256 );
+ ctx->Line.StipplePattern = pattern;
+ ctx->NewState |= NEW_RASTER_OPS;
+}
+
+
+
+/**********************************************************************/
+/***** Rasterization *****/
+/**********************************************************************/
+
+
+/*
+ * There are 4 pairs (RGBA, CI) of line drawing functions:
+ * 1. simple: width=1 and no special rasterization functions (fastest)
+ * 2. flat: width=1, non-stippled, flat-shaded, any raster operations
+ * 3. smooth: width=1, non-stippled, smooth-shaded, any raster operations
+ * 4. general: any other kind of line (slowest)
+ */
+
+
+/*
+ * All line drawing functions have the same arguments:
+ * v1, v2 - indexes of first and second endpoints into vertex buffer arrays
+ * pv - provoking vertex: which vertex color/index to use for flat shading.
+ */
+
+
+
+static void feedback_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv )
+{
+ struct vertex_buffer *VB = ctx->VB;
+ GLfloat x1, y1, z1, w1;
+ GLfloat x2, y2, z2, w2;
+ GLfloat tex1[4], tex2[4], invq;
+ GLuint texUnit = ctx->Texture.CurrentTransformUnit;
+
+ x1 = VB->Win.data[v1][0];
+ y1 = VB->Win.data[v1][1];
+ z1 = VB->Win.data[v1][2] / DEPTH_SCALE;
+ w1 = (VB->ClipPtr->size == 4 ? VEC_ELT(VB->ClipPtr, GLfloat, v1)[3] : 1.0);
+
+ x2 = VB->Win.data[v2][0];
+ y2 = VB->Win.data[v2][1];
+ z2 = VB->Win.data[v2][2] / DEPTH_SCALE;
+ w2 = (VB->ClipPtr->size == 4 ? VEC_ELT(VB->ClipPtr, GLfloat, v2)[3] : 1.0);
+
+
+ if (VB->TexCoordPtr[texUnit]->size == 4) {
+ invq = (VB->TexCoordPtr[texUnit]->data[v1][3]==0.0
+ ? 1.0
+ : 1.0F / VB->TexCoordPtr[texUnit]->data[v1][3]);
+
+ tex1[0] = VB->TexCoordPtr[texUnit]->data[v1][0] * invq;
+ tex1[1] = VB->TexCoordPtr[texUnit]->data[v1][1] * invq;
+ tex1[2] = VB->TexCoordPtr[texUnit]->data[v1][2] * invq;
+ tex1[3] = VB->TexCoordPtr[texUnit]->data[v1][3];
+
+ invq = (VB->TexCoordPtr[texUnit]->data[v2][3]==0.0
+ ? 1.0
+ : 1.0F / VB->TexCoordPtr[texUnit]->data[v2][3]);
+
+ tex2[0] = VB->TexCoordPtr[texUnit]->data[v2][0] * invq;
+ tex2[1] = VB->TexCoordPtr[texUnit]->data[v2][1] * invq;
+ tex2[2] = VB->TexCoordPtr[texUnit]->data[v2][2] * invq;
+ tex2[3] = VB->TexCoordPtr[texUnit]->data[v2][3];
+ } else {
+ ASSIGN_4V(tex1, 0,0,0,1);
+ ASSIGN_4V(tex2, 0,0,0,1);
+ COPY_SZ_4V(tex1,
+ VB->TexCoordPtr[texUnit]->size,
+ VB->TexCoordPtr[texUnit]->data[v1]);
+ COPY_SZ_4V(tex2,
+ VB->TexCoordPtr[texUnit]->size,
+ VB->TexCoordPtr[texUnit]->data[v2]);
+ }
+
+
+ if (ctx->StippleCounter==0) {
+ FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_LINE_RESET_TOKEN );
+ }
+ else {
+ FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_LINE_TOKEN );
+ }
+
+ {
+ GLfloat color[4];
+ GLubyte *ubc = VB->ColorPtr->data[pv];
+ GLuint index = VB->IndexPtr->data[pv];
+
+ UBYTE_RGBA_TO_FLOAT_RGBA( color, ubc );
+ gl_feedback_vertex( ctx, x1,y1,z1,w1, color, (GLfloat) index, tex1 );
+ gl_feedback_vertex( ctx, x2,y2,z2,w2, color, (GLfloat) index, tex2 );
+ }
+
+ ctx->StippleCounter++;
+}
+
+
+
+static void select_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv )
+{
+ (void) pv;
+ gl_update_hitflag( ctx, ctx->VB->Win.data[v1][2] / DEPTH_SCALE );
+ gl_update_hitflag( ctx, ctx->VB->Win.data[v2][2] / DEPTH_SCALE );
+}
+
+
+
+#if MAX_WIDTH > MAX_HEIGHT
+# define MAXPOINTS MAX_WIDTH
+#else
+# define MAXPOINTS MAX_HEIGHT
+#endif
+
+
+/* Flat, color index line */
+static void flat_ci_line( GLcontext *ctx,
+ GLuint vert0, GLuint vert1, GLuint pvert )
+{
+ GLint count;
+ GLint *pbx = ctx->PB->x;
+ GLint *pby = ctx->PB->y;
+ PB_SET_INDEX( ctx, ctx->PB, ctx->VB->IndexPtr->data[pvert] );
+ count = ctx->PB->count;
+
+#define INTERP_XY 1
+
+#define PLOT(X,Y) \
+ pbx[count] = X; \
+ pby[count] = Y; \
+ count++;
+
+#include "linetemp.h"
+
+ ctx->PB->count = count;
+ PB_CHECK_FLUSH( ctx, ctx->PB );
+}
+
+
+
+/* Flat, color index line with Z interpolation/testing */
+static void flat_ci_z_line( GLcontext *ctx,
+ GLuint vert0, GLuint vert1, GLuint pvert )
+{
+ GLint count;
+ GLint *pbx = ctx->PB->x;
+ GLint *pby = ctx->PB->y;
+ GLdepth *pbz = ctx->PB->z;
+ PB_SET_INDEX( ctx, ctx->PB, ctx->VB->IndexPtr->data[pvert] );
+ count = ctx->PB->count;
+
+#define INTERP_XY 1
+#define INTERP_Z 1
+
+#define PLOT(X,Y) \
+ pbx[count] = X; \
+ pby[count] = Y; \
+ pbz[count] = Z; \
+ count++;
+
+#include "linetemp.h"
+
+ ctx->PB->count = count;
+ PB_CHECK_FLUSH( ctx, ctx->PB );
+}
+
+
+
+/* Flat-shaded, RGBA line */
+static void flat_rgba_line( GLcontext *ctx,
+ GLuint vert0, GLuint vert1, GLuint pvert )
+{
+ GLint count;
+ GLint *pbx = ctx->PB->x;
+ GLint *pby = ctx->PB->y;
+ GLubyte *color = ctx->VB->ColorPtr->data[pvert];
+ PB_SET_COLOR( ctx, ctx->PB, color[0], color[1], color[2], color[3] );
+ count = ctx->PB->count;
+
+#define INTERP_XY 1
+
+#define PLOT(X,Y) \
+ pbx[count] = X; \
+ pby[count] = Y; \
+ count++;
+
+#include "linetemp.h"
+
+ ctx->PB->count = count;
+ PB_CHECK_FLUSH( ctx, ctx->PB );
+}
+
+
+
+/* Flat-shaded, RGBA line with Z interpolation/testing */
+static void flat_rgba_z_line( GLcontext *ctx,
+ GLuint vert0, GLuint vert1, GLuint pvert )
+{
+ GLint count;
+ GLint *pbx = ctx->PB->x;
+ GLint *pby = ctx->PB->y;
+ GLdepth *pbz = ctx->PB->z;
+ GLubyte *color = ctx->VB->ColorPtr->data[pvert];
+ PB_SET_COLOR( ctx, ctx->PB, color[0], color[1], color[2], color[3] );
+ count = ctx->PB->count;
+
+#define INTERP_XY 1
+#define INTERP_Z 1
+
+#define PLOT(X,Y) \
+ pbx[count] = X; \
+ pby[count] = Y; \
+ pbz[count] = Z; \
+ count++;
+
+#include "linetemp.h"
+
+ ctx->PB->count = count;
+ PB_CHECK_FLUSH( ctx, ctx->PB );
+}
+
+
+
+/* Smooth shaded, color index line */
+static void smooth_ci_line( GLcontext *ctx,
+ GLuint vert0, GLuint vert1, GLuint pvert )
+{
+ GLint count = ctx->PB->count;
+ GLint *pbx = ctx->PB->x;
+ GLint *pby = ctx->PB->y;
+ GLuint *pbi = ctx->PB->i;
+ (void) pvert;
+
+#define INTERP_XY 1
+#define INTERP_INDEX 1
+
+#define PLOT(X,Y) \
+ pbx[count] = X; \
+ pby[count] = Y; \
+ pbi[count] = I; \
+ count++;
+
+#include "linetemp.h"
+
+ ctx->PB->count = count;
+ PB_CHECK_FLUSH( ctx, ctx->PB );
+}
+
+
+
+/* Smooth shaded, color index line with Z interpolation/testing */
+static void smooth_ci_z_line( GLcontext *ctx,
+ GLuint vert0, GLuint vert1, GLuint pvert )
+{
+ GLint count = ctx->PB->count;
+ GLint *pbx = ctx->PB->x;
+ GLint *pby = ctx->PB->y;
+ GLdepth *pbz = ctx->PB->z;
+ GLuint *pbi = ctx->PB->i;
+ (void) pvert;
+
+#define INTERP_XY 1
+#define INTERP_Z 1
+#define INTERP_INDEX 1
+
+#define PLOT(X,Y) \
+ pbx[count] = X; \
+ pby[count] = Y; \
+ pbz[count] = Z; \
+ pbi[count] = I; \
+ count++;
+
+#include "linetemp.h"
+
+ ctx->PB->count = count;
+ PB_CHECK_FLUSH( ctx, ctx->PB );
+}
+
+
+
+/* Smooth-shaded, RGBA line */
+static void smooth_rgba_line( GLcontext *ctx,
+ GLuint vert0, GLuint vert1, GLuint pvert )
+{
+ GLint count = ctx->PB->count;
+ GLint *pbx = ctx->PB->x;
+ GLint *pby = ctx->PB->y;
+ GLubyte (*pbrgba)[4] = ctx->PB->rgba;
+ (void) pvert;
+
+#define INTERP_XY 1
+#define INTERP_RGB 1
+#define INTERP_ALPHA 1
+
+#define PLOT(X,Y) \
+ pbx[count] = X; \
+ pby[count] = Y; \
+ pbrgba[count][RCOMP] = FixedToInt(r0); \
+ pbrgba[count][GCOMP] = FixedToInt(g0); \
+ pbrgba[count][BCOMP] = FixedToInt(b0); \
+ pbrgba[count][ACOMP] = FixedToInt(a0); \
+ count++;
+
+#include "linetemp.h"
+
+ ctx->PB->count = count;
+ PB_CHECK_FLUSH( ctx, ctx->PB );
+}
+
+
+
+/* Smooth-shaded, RGBA line with Z interpolation/testing */
+static void smooth_rgba_z_line( GLcontext *ctx,
+ GLuint vert0, GLuint vert1, GLuint pvert )
+{
+ GLint count = ctx->PB->count;
+ GLint *pbx = ctx->PB->x;
+ GLint *pby = ctx->PB->y;
+ GLdepth *pbz = ctx->PB->z;
+ GLubyte (*pbrgba)[4] = ctx->PB->rgba;
+ (void) pvert;
+
+#define INTERP_XY 1
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define INTERP_ALPHA 1
+
+#define PLOT(X,Y) \
+ pbx[count] = X; \
+ pby[count] = Y; \
+ pbz[count] = Z; \
+ pbrgba[count][RCOMP] = FixedToInt(r0); \
+ pbrgba[count][GCOMP] = FixedToInt(g0); \
+ pbrgba[count][BCOMP] = FixedToInt(b0); \
+ pbrgba[count][ACOMP] = FixedToInt(a0); \
+ count++;
+
+#include "linetemp.h"
+
+ ctx->PB->count = count;
+ PB_CHECK_FLUSH( ctx, ctx->PB );
+}
+
+
+#define CHECK_FULL(count) \
+ if (count >= PB_SIZE-MAX_WIDTH) { \
+ ctx->PB->count = count; \
+ gl_flush_pb(ctx); \
+ count = ctx->PB->count; \
+ }
+
+
+
+/* Smooth shaded, color index, any width, maybe stippled */
+static void general_smooth_ci_line( GLcontext *ctx,
+ GLuint vert0, GLuint vert1, GLuint pvert )
+{
+ GLint count = ctx->PB->count;
+ GLint *pbx = ctx->PB->x;
+ GLint *pby = ctx->PB->y;
+ GLdepth *pbz = ctx->PB->z;
+ GLuint *pbi = ctx->PB->i;
+ (void) pvert;
+
+ if (ctx->Line.StippleFlag) {
+ /* stippled */
+#define INTERP_XY 1
+#define INTERP_Z 1
+#define INTERP_INDEX 1
+#define WIDE 1
+#define STIPPLE 1
+#define PLOT(X,Y) \
+ pbx[count] = X; \
+ pby[count] = Y; \
+ pbz[count] = Z; \
+ pbi[count] = I; \
+ count++; \
+ CHECK_FULL(count);
+#include "linetemp.h"
+ }
+ else {
+ /* unstippled */
+ if (ctx->Line.Width==2.0F) {
+ /* special case: unstippled and width=2 */
+#define INTERP_XY 1
+#define INTERP_Z 1
+#define INTERP_INDEX 1
+#define XMAJOR_PLOT(X,Y) \
+ pbx[count] = X; pbx[count+1] = X; \
+ pby[count] = Y; pby[count+1] = Y+1; \
+ pbz[count] = Z; pbz[count+1] = Z; \
+ pbi[count] = I; pbi[count+1] = I; \
+ count += 2; \
+ CHECK_FULL(count);
+#define YMAJOR_PLOT(X,Y) \
+ pbx[count] = X; pbx[count+1] = X+1; \
+ pby[count] = Y; pby[count+1] = Y; \
+ pbz[count] = Z; pbz[count+1] = Z; \
+ pbi[count] = I; pbi[count+1] = I; \
+ count += 2; \
+ CHECK_FULL(count);
+#include "linetemp.h"
+ }
+ else {
+ /* unstippled, any width */
+#define INTERP_XY 1
+#define INTERP_Z 1
+#define INTERP_INDEX 1
+#define WIDE 1
+#define PLOT(X,Y) \
+ pbx[count] = X; \
+ pby[count] = Y; \
+ pbz[count] = Z; \
+ pbi[count] = I; \
+ count++; \
+ CHECK_FULL(count);
+#include "linetemp.h"
+ }
+ }
+
+ ctx->PB->count = count;
+ PB_CHECK_FLUSH( ctx, ctx->PB );
+}
+
+
+/* Flat shaded, color index, any width, maybe stippled */
+static void general_flat_ci_line( GLcontext *ctx,
+ GLuint vert0, GLuint vert1, GLuint pvert )
+{
+ GLint count;
+ GLint *pbx = ctx->PB->x;
+ GLint *pby = ctx->PB->y;
+ GLdepth *pbz = ctx->PB->z;
+ PB_SET_INDEX( ctx, ctx->PB, ctx->VB->IndexPtr->data[pvert] );
+ count = ctx->PB->count;
+
+ if (ctx->Line.StippleFlag) {
+ /* stippled, any width */
+#define INTERP_XY 1
+#define INTERP_Z 1
+#define WIDE 1
+#define STIPPLE 1
+#define PLOT(X,Y) \
+ pbx[count] = X; \
+ pby[count] = Y; \
+ pbz[count] = Z; \
+ count++; \
+ CHECK_FULL(count);
+#include "linetemp.h"
+ }
+ else {
+ /* unstippled */
+ if (ctx->Line.Width==2.0F) {
+ /* special case: unstippled and width=2 */
+#define INTERP_XY 1
+#define INTERP_Z 1
+#define XMAJOR_PLOT(X,Y) \
+ pbx[count] = X; pbx[count+1] = X; \
+ pby[count] = Y; pby[count+1] = Y+1; \
+ pbz[count] = Z; pbz[count+1] = Z; \
+ count += 2; \
+ CHECK_FULL(count);
+#define YMAJOR_PLOT(X,Y) \
+ pbx[count] = X; pbx[count+1] = X+1; \
+ pby[count] = Y; pby[count+1] = Y; \
+ pbz[count] = Z; pbz[count+1] = Z; \
+ count += 2; \
+ CHECK_FULL(count);
+#include "linetemp.h"
+ }
+ else {
+ /* unstippled, any width */
+#define INTERP_XY 1
+#define INTERP_Z 1
+#define WIDE 1
+#define PLOT(X,Y) \
+ pbx[count] = X; \
+ pby[count] = Y; \
+ pbz[count] = Z; \
+ count++; \
+ CHECK_FULL(count);
+#include "linetemp.h"
+ }
+ }
+
+ ctx->PB->count = count;
+ PB_CHECK_FLUSH( ctx, ctx->PB );
+}
+
+
+
+static void general_smooth_rgba_line( GLcontext *ctx,
+ GLuint vert0, GLuint vert1, GLuint pvert)
+{
+ GLint count = ctx->PB->count;
+ GLint *pbx = ctx->PB->x;
+ GLint *pby = ctx->PB->y;
+ GLdepth *pbz = ctx->PB->z;
+ GLubyte (*pbrgba)[4] = ctx->PB->rgba;
+ (void) pvert;
+
+ if (ctx->Line.StippleFlag) {
+ /* stippled */
+#define INTERP_XY 1
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define INTERP_ALPHA 1
+#define WIDE 1
+#define STIPPLE 1
+#define PLOT(X,Y) \
+ pbx[count] = X; \
+ pby[count] = Y; \
+ pbz[count] = Z; \
+ pbrgba[count][RCOMP] = FixedToInt(r0); \
+ pbrgba[count][GCOMP] = FixedToInt(g0); \
+ pbrgba[count][BCOMP] = FixedToInt(b0); \
+ pbrgba[count][ACOMP] = FixedToInt(a0); \
+ count++; \
+ CHECK_FULL(count);
+#include "linetemp.h"
+ }
+ else {
+ /* unstippled */
+ if (ctx->Line.Width==2.0F) {
+ /* special case: unstippled and width=2 */
+#define INTERP_XY 1
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define INTERP_ALPHA 1
+#define XMAJOR_PLOT(X,Y) \
+ pbx[count] = X; pbx[count+1] = X; \
+ pby[count] = Y; pby[count+1] = Y+1; \
+ pbz[count] = Z; pbz[count+1] = Z; \
+ pbrgba[count][RCOMP] = FixedToInt(r0); \
+ pbrgba[count][GCOMP] = FixedToInt(g0); \
+ pbrgba[count][BCOMP] = FixedToInt(b0); \
+ pbrgba[count][ACOMP] = FixedToInt(a0); \
+ pbrgba[count+1][RCOMP] = FixedToInt(r0); \
+ pbrgba[count+1][GCOMP] = FixedToInt(g0); \
+ pbrgba[count+1][BCOMP] = FixedToInt(b0); \
+ pbrgba[count+1][ACOMP] = FixedToInt(a0); \
+ count += 2; \
+ CHECK_FULL(count);
+#define YMAJOR_PLOT(X,Y) \
+ pbx[count] = X; pbx[count+1] = X+1; \
+ pby[count] = Y; pby[count+1] = Y; \
+ pbz[count] = Z; pbz[count+1] = Z; \
+ pbrgba[count][RCOMP] = FixedToInt(r0); \
+ pbrgba[count][GCOMP] = FixedToInt(g0); \
+ pbrgba[count][BCOMP] = FixedToInt(b0); \
+ pbrgba[count][ACOMP] = FixedToInt(a0); \
+ pbrgba[count+1][RCOMP] = FixedToInt(r0); \
+ pbrgba[count+1][GCOMP] = FixedToInt(g0); \
+ pbrgba[count+1][BCOMP] = FixedToInt(b0); \
+ pbrgba[count+1][ACOMP] = FixedToInt(a0); \
+ count += 2; \
+ CHECK_FULL(count);
+#include "linetemp.h"
+ }
+ else {
+ /* unstippled, any width */
+#define INTERP_XY 1
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define INTERP_ALPHA 1
+#define WIDE 1
+#define PLOT(X,Y) \
+ pbx[count] = X; \
+ pby[count] = Y; \
+ pbz[count] = Z; \
+ pbrgba[count][RCOMP] = FixedToInt(r0); \
+ pbrgba[count][GCOMP] = FixedToInt(g0); \
+ pbrgba[count][BCOMP] = FixedToInt(b0); \
+ pbrgba[count][ACOMP] = FixedToInt(a0); \
+ count++; \
+ CHECK_FULL(count);
+#include "linetemp.h"
+ }
+ }
+
+ ctx->PB->count = count;
+ PB_CHECK_FLUSH( ctx, ctx->PB );
+}
+
+
+static void general_flat_rgba_line( GLcontext *ctx,
+ GLuint vert0, GLuint vert1, GLuint pvert )
+{
+ GLint count;
+ GLint *pbx = ctx->PB->x;
+ GLint *pby = ctx->PB->y;
+ GLdepth *pbz = ctx->PB->z;
+ GLubyte *color = ctx->VB->ColorPtr->data[pvert];
+ PB_SET_COLOR( ctx, ctx->PB, color[0], color[1], color[2], color[3] );
+ count = ctx->PB->count;
+
+ if (ctx->Line.StippleFlag) {
+ /* stippled */
+#define INTERP_XY 1
+#define INTERP_Z 1
+#define WIDE 1
+#define STIPPLE 1
+#define PLOT(X,Y) \
+ pbx[count] = X; \
+ pby[count] = Y; \
+ pbz[count] = Z; \
+ count++; \
+ CHECK_FULL(count);
+#include "linetemp.h"
+ }
+ else {
+ /* unstippled */
+ if (ctx->Line.Width==2.0F) {
+ /* special case: unstippled and width=2 */
+#define INTERP_XY 1
+#define INTERP_Z 1
+#define XMAJOR_PLOT(X,Y) \
+ pbx[count] = X; pbx[count+1] = X; \
+ pby[count] = Y; pby[count+1] = Y+1; \
+ pbz[count] = Z; pbz[count+1] = Z; \
+ count += 2; \
+ CHECK_FULL(count);
+#define YMAJOR_PLOT(X,Y) \
+ pbx[count] = X; pbx[count+1] = X+1; \
+ pby[count] = Y; pby[count+1] = Y; \
+ pbz[count] = Z; pbz[count+1] = Z; \
+ count += 2; \
+ CHECK_FULL(count);
+#include "linetemp.h"
+ }
+ else {
+ /* unstippled, any width */
+#define INTERP_XY 1
+#define INTERP_Z 1
+#define WIDE 1
+#define PLOT(X,Y) \
+ pbx[count] = X; \
+ pby[count] = Y; \
+ pbz[count] = Z; \
+ count++; \
+ CHECK_FULL(count);
+#include "linetemp.h"
+ }
+ }
+
+ ctx->PB->count = count;
+ PB_CHECK_FLUSH( ctx, ctx->PB );
+}
+
+
+/* Flat-shaded, textured, any width, maybe stippled */
+static void flat_textured_line( GLcontext *ctx,
+ GLuint vert0, GLuint vert1, GLuint pv )
+{
+ GLint count;
+ GLint *pbx = ctx->PB->x;
+ GLint *pby = ctx->PB->y;
+ GLdepth *pbz = ctx->PB->z;
+ GLfloat *pbs = ctx->PB->s[0];
+ GLfloat *pbt = ctx->PB->t[0];
+ GLfloat *pbu = ctx->PB->u[0];
+ GLubyte *color = ctx->VB->ColorPtr->data[pv];
+ PB_SET_COLOR( ctx, ctx->PB, color[0], color[1], color[2], color[3] );
+ count = ctx->PB->count;
+
+ if (ctx->Line.StippleFlag) {
+ /* stippled */
+#define INTERP_XY 1
+#define INTERP_Z 1
+#define INTERP_STUV0 1
+#define WIDE 1
+#define STIPPLE 1
+#define PLOT(X,Y) \
+ { \
+ pbx[count] = X; \
+ pby[count] = Y; \
+ pbz[count] = Z; \
+ pbs[count] = s; \
+ pbt[count] = t; \
+ pbu[count] = u; \
+ count++; \
+ CHECK_FULL(count); \
+ }
+#include "linetemp.h"
+ }
+ else {
+ /* unstippled */
+#define INTERP_XY 1
+#define INTERP_Z 1
+#define INTERP_STUV0 1
+#define WIDE 1
+#define PLOT(X,Y) \
+ { \
+ pbx[count] = X; \
+ pby[count] = Y; \
+ pbz[count] = Z; \
+ pbs[count] = s; \
+ pbt[count] = t; \
+ pbu[count] = u; \
+ count++; \
+ CHECK_FULL(count); \
+ }
+#include "linetemp.h"
+ }
+
+ ctx->PB->count = count;
+ PB_CHECK_FLUSH( ctx, ctx->PB );
+}
+
+
+
+/* Smooth-shaded, textured, any width, maybe stippled */
+static void smooth_textured_line( GLcontext *ctx,
+ GLuint vert0, GLuint vert1, GLuint pvert )
+{
+ GLint count = ctx->PB->count;
+ GLint *pbx = ctx->PB->x;
+ GLint *pby = ctx->PB->y;
+ GLdepth *pbz = ctx->PB->z;
+ GLfloat *pbs = ctx->PB->s[0];
+ GLfloat *pbt = ctx->PB->t[0];
+ GLfloat *pbu = ctx->PB->u[0];
+ GLubyte (*pbrgba)[4] = ctx->PB->rgba;
+ (void) pvert;
+
+ if (ctx->Line.StippleFlag) {
+ /* stippled */
+#define INTERP_XY 1
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define INTERP_ALPHA 1
+#define INTERP_STUV0 1
+#define WIDE 1
+#define STIPPLE 1
+#define PLOT(X,Y) \
+ { \
+ pbx[count] = X; \
+ pby[count] = Y; \
+ pbz[count] = Z; \
+ pbs[count] = s; \
+ pbt[count] = t; \
+ pbu[count] = u; \
+ pbrgba[count][RCOMP] = FixedToInt(r0); \
+ pbrgba[count][GCOMP] = FixedToInt(g0); \
+ pbrgba[count][BCOMP] = FixedToInt(b0); \
+ pbrgba[count][ACOMP] = FixedToInt(a0); \
+ count++; \
+ CHECK_FULL(count); \
+ }
+#include "linetemp.h"
+ }
+ else {
+ /* unstippled */
+#define INTERP_XY 1
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define INTERP_ALPHA 1
+#define INTERP_STUV0 1
+#define WIDE 1
+#define PLOT(X,Y) \
+ { \
+ pbx[count] = X; \
+ pby[count] = Y; \
+ pbz[count] = Z; \
+ pbs[count] = s; \
+ pbt[count] = t; \
+ pbu[count] = u; \
+ pbrgba[count][RCOMP] = FixedToInt(r0); \
+ pbrgba[count][GCOMP] = FixedToInt(g0); \
+ pbrgba[count][BCOMP] = FixedToInt(b0); \
+ pbrgba[count][ACOMP] = FixedToInt(a0); \
+ count++; \
+ CHECK_FULL(count); \
+ }
+#include "linetemp.h"
+ }
+
+ ctx->PB->count = count;
+ PB_CHECK_FLUSH( ctx, ctx->PB );
+}
+
+
+/* Smooth-shaded, multitextured, any width, maybe stippled, separate specular
+ * color interpolation.
+ */
+static void smooth_multitextured_line( GLcontext *ctx,
+ GLuint vert0, GLuint vert1, GLuint pvert )
+{
+ GLint count = ctx->PB->count;
+ GLint *pbx = ctx->PB->x;
+ GLint *pby = ctx->PB->y;
+ GLdepth *pbz = ctx->PB->z;
+ GLfloat *pbs = ctx->PB->s[0];
+ GLfloat *pbt = ctx->PB->t[0];
+ GLfloat *pbu = ctx->PB->u[0];
+ GLfloat *pbs1 = ctx->PB->s[1];
+ GLfloat *pbt1 = ctx->PB->t[1];
+ GLfloat *pbu1 = ctx->PB->u[1];
+ GLubyte (*pbrgba)[4] = ctx->PB->rgba;
+ GLubyte (*pbspec)[3] = ctx->PB->spec;
+ (void) pvert;
+
+ if (ctx->Line.StippleFlag) {
+ /* stippled */
+#define INTERP_XY 1
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define INTERP_SPEC 1
+#define INTERP_ALPHA 1
+#define INTERP_STUV0 1
+#define INTERP_STUV1 1
+#define WIDE 1
+#define STIPPLE 1
+#define PLOT(X,Y) \
+ { \
+ pbx[count] = X; \
+ pby[count] = Y; \
+ pbz[count] = Z; \
+ pbs[count] = s; \
+ pbt[count] = t; \
+ pbu[count] = u; \
+ pbs1[count] = s1; \
+ pbt1[count] = t1; \
+ pbu1[count] = u1; \
+ pbrgba[count][RCOMP] = FixedToInt(r0); \
+ pbrgba[count][GCOMP] = FixedToInt(g0); \
+ pbrgba[count][BCOMP] = FixedToInt(b0); \
+ pbrgba[count][ACOMP] = FixedToInt(a0); \
+ pbspec[count][RCOMP] = FixedToInt(sr0); \
+ pbspec[count][GCOMP] = FixedToInt(sg0); \
+ pbspec[count][BCOMP] = FixedToInt(sb0); \
+ count++; \
+ CHECK_FULL(count); \
+ }
+#include "linetemp.h"
+ }
+ else {
+ /* unstippled */
+#define INTERP_XY 1
+#define INTERP_Z 1
+#define INTERP_RGB 1
+#define INTERP_SPEC 1
+#define INTERP_ALPHA 1
+#define INTERP_STUV0 1
+#define INTERP_STUV1 1
+#define WIDE 1
+#define PLOT(X,Y) \
+ { \
+ pbx[count] = X; \
+ pby[count] = Y; \
+ pbz[count] = Z; \
+ pbs[count] = s; \
+ pbt[count] = t; \
+ pbu[count] = u; \
+ pbs1[count] = s1; \
+ pbt1[count] = t1; \
+ pbu1[count] = u1; \
+ pbrgba[count][RCOMP] = FixedToInt(r0); \
+ pbrgba[count][GCOMP] = FixedToInt(g0); \
+ pbrgba[count][BCOMP] = FixedToInt(b0); \
+ pbrgba[count][ACOMP] = FixedToInt(a0); \
+ pbspec[count][RCOMP] = FixedToInt(sr0); \
+ pbspec[count][GCOMP] = FixedToInt(sg0); \
+ pbspec[count][BCOMP] = FixedToInt(sb0); \
+ count++; \
+ CHECK_FULL(count); \
+ }
+#include "linetemp.h"
+ }
+
+ ctx->PB->count = count;
+ PB_CHECK_FLUSH( ctx, ctx->PB );
+}
+
+
+/*
+ * Antialiased RGBA line
+ *
+ * This AA line function isn't terribly efficient but it's pretty
+ * straight-forward to understand. Also, it doesn't exactly conform
+ * to the specification.
+ */
+static void aa_rgba_line( GLcontext *ctx,
+ GLuint vert0, GLuint vert1, GLuint pvert )
+{
+#define INTERP_RGBA 1
+#define PLOT(x, y) { PB_WRITE_RGBA_PIXEL( pb, (x), (y), z, red, green, blue, coverage ); }
+#include "lnaatemp.h"
+}
+
+/*
+ * Antialiased Textured RGBA line
+ *
+ * This AA line function isn't terribly efficient but it's pretty
+ * straight-forward to understand. Also, it doesn't exactly conform
+ * to the specification.
+ */
+static void aa_tex_rgba_line( GLcontext *ctx,
+ GLuint vert0, GLuint vert1, GLuint pvert )
+{
+#define INTERP_RGBA 1
+#define INTERP_STUV0 1
+#define PLOT(x, y) \
+ { \
+ PB_WRITE_TEX_PIXEL( pb, (x), (y), z, red, green, blue, coverage, \
+ s, t, u ); \
+ }
+#include "lnaatemp.h"
+}
+
+
+/*
+ * Antialiased Multitextured RGBA line
+ *
+ * This AA line function isn't terribly efficient but it's pretty
+ * straight-forward to understand. Also, it doesn't exactly conform
+ * to the specification.
+ */
+static void aa_multitex_rgba_line( GLcontext *ctx,
+ GLuint vert0, GLuint vert1, GLuint pvert )
+{
+#define INTERP_RGBA 1
+#define INTERP_SPEC 1
+#define INTERP_STUV0 1
+#define INTERP_STUV1 1
+#define PLOT(x, y) \
+ { \
+ PB_WRITE_MULTITEX_SPEC_PIXEL( pb, (x), (y), z, \
+ red, green, blue, coverage, specRed, specGreen, specBlue, \
+ s, t, u, s1, t1, u1 ); \
+ }
+#include "lnaatemp.h"
+}
+
+
+/*
+ * Antialiased CI line. Same comments for RGBA antialiased lines apply.
+ */
+static void aa_ci_line( GLcontext *ctx,
+ GLuint vert0, GLuint vert1, GLuint pvert )
+{
+#define INTERP_INDEX 1
+#define PLOT(x, y) \
+ { \
+ PB_WRITE_CI_PIXEL( pb, (x), (y), z, index + coverage ); \
+ }
+#include "lnaatemp.h"
+}
+
+
+/*
+ * Null rasterizer for measuring transformation speed.
+ */
+static void null_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv )
+{
+ (void) ctx;
+ (void) v1;
+ (void) v2;
+ (void) pv;
+}
+
+
+/*
+ * Determine which line drawing function to use given the current
+ * rendering context.
+ */
+void gl_set_line_function( GLcontext *ctx )
+{
+ GLboolean rgbmode = ctx->Visual->RGBAflag;
+ /* TODO: antialiased lines */
+
+ if (ctx->RenderMode==GL_RENDER) {
+ if (ctx->NoRaster) {
+ ctx->Driver.LineFunc = null_line;
+ return;
+ }
+ if (ctx->Driver.LineFunc) {
+ /* Device driver will draw lines. */
+ return;
+ }
+
+ if (ctx->Line.SmoothFlag) {
+ /* antialiased lines */
+ if (rgbmode) {
+ if (ctx->Texture.ReallyEnabled) {
+ if (ctx->Texture.ReallyEnabled >= TEXTURE1_1D
+ || ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR)
+ /* Multitextured! */
+ ctx->Driver.LineFunc = aa_multitex_rgba_line;
+ else
+ ctx->Driver.LineFunc = aa_tex_rgba_line;
+ } else {
+ ctx->Driver.LineFunc = aa_rgba_line;
+ }
+ }
+ else {
+ ctx->Driver.LineFunc = aa_ci_line;
+ }
+ }
+ else if (ctx->Texture.ReallyEnabled) {
+ if (ctx->Texture.ReallyEnabled >= TEXTURE1_1D
+ || ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) {
+ /* multi-texture and/or separate specular color */
+ ctx->Driver.LineFunc = smooth_multitextured_line;
+ }
+ else {
+ if (ctx->Light.ShadeModel==GL_SMOOTH) {
+ ctx->Driver.LineFunc = smooth_textured_line;
+ }
+ else {
+ ctx->Driver.LineFunc = flat_textured_line;
+ }
+ }
+ }
+ else if (ctx->Line.Width!=1.0 || ctx->Line.StippleFlag
+ || ctx->Line.SmoothFlag) {
+ if (ctx->Light.ShadeModel==GL_SMOOTH) {
+ if (rgbmode)
+ ctx->Driver.LineFunc = general_smooth_rgba_line;
+ else
+ ctx->Driver.LineFunc = general_smooth_ci_line;
+ }
+ else {
+ if (rgbmode)
+ ctx->Driver.LineFunc = general_flat_rgba_line;
+ else
+ ctx->Driver.LineFunc = general_flat_ci_line;
+ }
+ }
+ else {
+ if (ctx->Light.ShadeModel==GL_SMOOTH) {
+ /* Width==1, non-stippled, smooth-shaded */
+ if (ctx->Depth.Test
+ || (ctx->Fog.Enabled && ctx->Hint.Fog==GL_NICEST)) {
+ if (rgbmode)
+ ctx->Driver.LineFunc = smooth_rgba_z_line;
+ else
+ ctx->Driver.LineFunc = smooth_ci_z_line;
+ }
+ else {
+ if (rgbmode)
+ ctx->Driver.LineFunc = smooth_rgba_line;
+ else
+ ctx->Driver.LineFunc = smooth_ci_line;
+ }
+ }
+ else {
+ /* Width==1, non-stippled, flat-shaded */
+ if (ctx->Depth.Test
+ || (ctx->Fog.Enabled && ctx->Hint.Fog==GL_NICEST)) {
+ if (rgbmode)
+ ctx->Driver.LineFunc = flat_rgba_z_line;
+ else
+ ctx->Driver.LineFunc = flat_ci_z_line;
+ }
+ else {
+ if (rgbmode)
+ ctx->Driver.LineFunc = flat_rgba_line;
+ else
+ ctx->Driver.LineFunc = flat_ci_line;
+ }
+ }
+ }
+ }
+ else if (ctx->RenderMode==GL_FEEDBACK) {
+ ctx->Driver.LineFunc = feedback_line;
+ }
+ else {
+ /* GL_SELECT mode */
+ ctx->Driver.LineFunc = select_line;
+ }
+}
+
diff --git a/src/mesa/main/lines.h b/src/mesa/main/lines.h
new file mode 100644
index 0000000000..f85a7a4910
--- /dev/null
+++ b/src/mesa/main/lines.h
@@ -0,0 +1,45 @@
+/* $Id: lines.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef LINES_H
+#define LINES_H
+
+
+#include "types.h"
+
+
+extern void gl_LineWidth( GLcontext *ctx, GLfloat width );
+
+extern void gl_LineStipple( GLcontext *ctx, GLint factor, GLushort pattern );
+
+extern void gl_set_line_function( GLcontext *ctx );
+
+
+#endif
diff --git a/src/mesa/main/macros.h b/src/mesa/main/macros.h
new file mode 100644
index 0000000000..61e8974836
--- /dev/null
+++ b/src/mesa/main/macros.h
@@ -0,0 +1,546 @@
+/* $Id: macros.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+/*
+ * A collection of useful macros.
+ */
+
+
+#ifndef MACROS_H
+#define MACROS_H
+
+
+#include <math.h>
+#include <string.h>
+
+
+#ifdef DEBUG
+# include <assert.h>
+# define ASSERT(X) assert(X)
+#else
+# define ASSERT(X)
+#endif
+
+
+#if defined(__GNUC__) || defined(__MWERKS__)
+#define INLINE __inline__
+#elif defined(__MSC__)
+#define INLINE __inline
+#else
+#define INLINE
+#endif
+
+
+/* Stepping a GLfloat pointer by a byte stride
+ */
+#define STRIDE_F(p, i) (p = (GLfloat *)((GLubyte *)p + i))
+#define STRIDE_UI(p, i) (p = (GLuint *)((GLubyte *)p + i))
+#define STRIDE_T(p, t, i) (p = (t *)((GLubyte *)p + i))
+
+
+/* Limits: */
+#define MAX_GLUSHORT 0xffff
+#define MAX_GLUINT 0xffffffff
+
+
+#define ZERO_2V( DST ) (DST)[0] = (DST)[1] = 0
+#define ZERO_3V( DST ) (DST)[0] = (DST)[1] = (DST)[2] = 0
+#define ZERO_4V( DST ) (DST)[0] = (DST)[1] = (DST)[2] = (DST)[3] = 0
+
+
+/* Copy short vectors: */
+#define COPY_2V( DST, SRC ) \
+do { \
+ (DST)[0] = (SRC)[0]; \
+ (DST)[1] = (SRC)[1]; \
+} while (0)
+
+
+#define COPY_3V( DST, SRC ) \
+do { \
+ (DST)[0] = (SRC)[0]; \
+ (DST)[1] = (SRC)[1]; \
+ (DST)[2] = (SRC)[2]; \
+} while (0)
+
+#define COPY_4V( DST, SRC ) \
+do { \
+ (DST)[0] = (SRC)[0]; \
+ (DST)[1] = (SRC)[1]; \
+ (DST)[2] = (SRC)[2]; \
+ (DST)[3] = (SRC)[3]; \
+} while (0)
+
+
+#define COPY_2FV( DST, SRC ) \
+do { \
+ const GLfloat *_tmp = (SRC); \
+ (DST)[0] = _tmp[0]; \
+ (DST)[1] = _tmp[1]; \
+} while (0)
+
+
+#define COPY_3FV( DST, SRC ) \
+do { \
+ const GLfloat *_tmp = (SRC); \
+ (DST)[0] = _tmp[0]; \
+ (DST)[1] = _tmp[1]; \
+ (DST)[2] = _tmp[2]; \
+} while (0)
+
+#define COPY_4FV( DST, SRC ) \
+do { \
+ const GLfloat *_tmp = (SRC); \
+ (DST)[0] = _tmp[0]; \
+ (DST)[1] = _tmp[1]; \
+ (DST)[2] = _tmp[2]; \
+ (DST)[3] = _tmp[3]; \
+} while (0)
+
+
+
+#define COPY_SZ_4V(DST, SZ, SRC) \
+do { \
+ switch (SZ) { \
+ case 4: (DST)[3] = (SRC)[3]; \
+ case 3: (DST)[2] = (SRC)[2]; \
+ case 2: (DST)[1] = (SRC)[1]; \
+ case 1: (DST)[0] = (SRC)[0]; \
+ } \
+} while(0)
+
+#define SUB_4V( DST, SRCA, SRCB ) \
+do { \
+ (DST)[0] = (SRCA)[0] - (SRCB)[0]; \
+ (DST)[1] = (SRCA)[1] - (SRCB)[1]; \
+ (DST)[2] = (SRCA)[2] - (SRCB)[2]; \
+ (DST)[3] = (SRCA)[3] - (SRCB)[3]; \
+} while (0)
+
+#define ADD_4V( DST, SRCA, SRCB ) \
+do { \
+ (DST)[0] = (SRCA)[0] + (SRCB)[0]; \
+ (DST)[1] = (SRCA)[1] + (SRCB)[1]; \
+ (DST)[2] = (SRCA)[2] + (SRCB)[2]; \
+ (DST)[3] = (SRCA)[3] + (SRCB)[3]; \
+} while (0)
+
+#define SCALE_4V( DST, SRCA, SRCB ) \
+do { \
+ (DST)[0] = (SRCA)[0] * (SRCB)[0]; \
+ (DST)[1] = (SRCA)[1] * (SRCB)[1]; \
+ (DST)[2] = (SRCA)[2] * (SRCB)[2]; \
+ (DST)[3] = (SRCA)[3] * (SRCB)[3]; \
+} while (0)
+
+#define ACC_4V( DST, SRC ) \
+do { \
+ (DST)[0] += (SRC)[0]; \
+ (DST)[1] += (SRC)[1]; \
+ (DST)[2] += (SRC)[2]; \
+ (DST)[3] += (SRC)[3]; \
+} while (0)
+
+#define ACC_SCALE_4V( DST, SRCA, SRCB ) \
+do { \
+ (DST)[0] += (SRCA)[0] * (SRCB)[0]; \
+ (DST)[1] += (SRCA)[1] * (SRCB)[1]; \
+ (DST)[2] += (SRCA)[2] * (SRCB)[2]; \
+ (DST)[3] += (SRCA)[3] * (SRCB)[3]; \
+} while (0)
+
+#define ACC_SCALE_SCALAR_4V( DST, S, SRCB ) \
+do { \
+ (DST)[0] += S * (SRCB)[0]; \
+ (DST)[1] += S * (SRCB)[1]; \
+ (DST)[2] += S * (SRCB)[2]; \
+ (DST)[3] += S * (SRCB)[3]; \
+} while (0)
+
+#define SCALE_SCALAR_4V( DST, S, SRCB ) \
+do { \
+ (DST)[0] = S * (SRCB)[0]; \
+ (DST)[1] = S * (SRCB)[1]; \
+ (DST)[2] = S * (SRCB)[2]; \
+ (DST)[3] = S * (SRCB)[3]; \
+} while (0)
+
+
+#define SELF_SCALE_SCALAR_4V( DST, S ) \
+do { \
+ (DST)[0] *= S; \
+ (DST)[1] *= S; \
+ (DST)[2] *= S; \
+ (DST)[3] *= S; \
+} while (0)
+
+
+/*
+ * Similarly for 3-vectors.
+ */
+#define SUB_3V( DST, SRCA, SRCB ) \
+do { \
+ (DST)[0] = (SRCA)[0] - (SRCB)[0]; \
+ (DST)[1] = (SRCA)[1] - (SRCB)[1]; \
+ (DST)[2] = (SRCA)[2] - (SRCB)[2]; \
+} while (0)
+
+#define ADD_3V( DST, SRCA, SRCB ) \
+do { \
+ (DST)[0] = (SRCA)[0] + (SRCB)[0]; \
+ (DST)[1] = (SRCA)[1] + (SRCB)[1]; \
+ (DST)[2] = (SRCA)[2] + (SRCB)[2]; \
+} while (0)
+
+#define SCALE_3V( DST, SRCA, SRCB ) \
+do { \
+ (DST)[0] = (SRCA)[0] * (SRCB)[0]; \
+ (DST)[1] = (SRCA)[1] * (SRCB)[1]; \
+ (DST)[2] = (SRCA)[2] * (SRCB)[2]; \
+} while (0)
+
+#define ACC_3V( DST, SRC ) \
+do { \
+ (DST)[0] += (SRC)[0]; \
+ (DST)[1] += (SRC)[1]; \
+ (DST)[2] += (SRC)[2]; \
+} while (0)
+
+#define ACC_SCALE_3V( DST, SRCA, SRCB ) \
+do { \
+ (DST)[0] += (SRCA)[0] * (SRCB)[0]; \
+ (DST)[1] += (SRCA)[1] * (SRCB)[1]; \
+ (DST)[2] += (SRCA)[2] * (SRCB)[2]; \
+} while (0)
+
+#define SCALE_SCALAR_3V( DST, S, SRCB ) \
+do { \
+ (DST)[0] = S * (SRCB)[0]; \
+ (DST)[1] = S * (SRCB)[1]; \
+ (DST)[2] = S * (SRCB)[2]; \
+} while (0)
+
+#define ACC_SCALE_SCALAR_3V( DST, S, SRCB ) \
+do { \
+ (DST)[0] += S * (SRCB)[0]; \
+ (DST)[1] += S * (SRCB)[1]; \
+ (DST)[2] += S * (SRCB)[2]; \
+} while (0)
+
+#define SELF_SCALE_SCALAR_3V( DST, S ) \
+do { \
+ (DST)[0] *= S; \
+ (DST)[1] *= S; \
+ (DST)[2] *= S; \
+} while (0)
+
+#define ACC_SCALAR_3V( DST, S ) \
+do { \
+ (DST)[0] += S; \
+ (DST)[1] += S; \
+ (DST)[2] += S; \
+} while (0)
+
+/* And also for 2-vectors
+ */
+#define SUB_2V( DST, SRCA, SRCB ) \
+do { \
+ (DST)[0] = (SRCA)[0] - (SRCB)[0]; \
+ (DST)[1] = (SRCA)[1] - (SRCB)[1]; \
+} while (0)
+
+#define ADD_2V( DST, SRCA, SRCB ) \
+do { \
+ (DST)[0] = (SRCA)[0] + (SRCB)[0]; \
+ (DST)[1] = (SRCA)[1] + (SRCB)[1]; \
+} while (0)
+
+#define SCALE_2V( DST, SRCA, SRCB ) \
+do { \
+ (DST)[0] = (SRCA)[0] * (SRCB)[0]; \
+ (DST)[1] = (SRCA)[1] * (SRCB)[1]; \
+} while (0)
+
+#define ACC_2V( DST, SRC ) \
+do { \
+ (DST)[0] += (SRC)[0]; \
+ (DST)[1] += (SRC)[1]; \
+} while (0)
+
+#define ACC_SCALE_2V( DST, SRCA, SRCB ) \
+do { \
+ (DST)[0] += (SRCA)[0] * (SRCB)[0]; \
+ (DST)[1] += (SRCA)[1] * (SRCB)[1]; \
+} while (0)
+
+#define SCALE_SCALAR_2V( DST, S, SRCB ) \
+do { \
+ (DST)[0] = S * (SRCB)[0]; \
+ (DST)[1] = S * (SRCB)[1]; \
+} while (0)
+
+#define ACC_SCALE_SCALAR_2V( DST, S, SRCB ) \
+do { \
+ (DST)[0] += S * (SRCB)[0]; \
+ (DST)[1] += S * (SRCB)[1]; \
+} while (0)
+
+#define SELF_SCALE_SCALAR_2V( DST, S ) \
+do { \
+ (DST)[0] *= S; \
+ (DST)[1] *= S; \
+} while (0)
+
+#define ACC_SCALAR_2V( DST, S ) \
+do { \
+ (DST)[0] += S; \
+ (DST)[1] += S; \
+} while (0)
+
+
+
+/*
+ * Copy a vector of 4 GLubytes from SRC to DST.
+ */
+#define COPY_4UBV(DST, SRC) \
+do { \
+ if (sizeof(GLuint)==4*sizeof(GLubyte)) { \
+ *((GLuint*)(DST)) = *((GLuint*)(SRC)); \
+ } \
+ else { \
+ (DST)[0] = (SRC)[0]; \
+ (DST)[1] = (SRC)[1]; \
+ (DST)[2] = (SRC)[2]; \
+ (DST)[3] = (SRC)[3]; \
+ } \
+} while (0)
+
+
+/* Assign scalers to short vectors: */
+#define ASSIGN_2V( V, V0, V1 ) \
+do { V[0] = V0; V[1] = V1; } while(0)
+
+#define ASSIGN_3V( V, V0, V1, V2 ) \
+do { V[0] = V0; V[1] = V1; V[2] = V2; } while(0)
+
+#define ASSIGN_4V( V, V0, V1, V2, V3 ) \
+do { \
+ V[0] = V0; \
+ V[1] = V1; \
+ V[2] = V2; \
+ V[3] = V3; \
+} while(0)
+
+
+
+
+/* Absolute value (for Int, Float, Double): */
+#define ABSI(X) ((X) < 0 ? -(X) : (X))
+#define ABSF(X) ((X) < 0.0F ? -(X) : (X))
+#define ABSD(X) ((X) < 0.0 ? -(X) : (X))
+
+
+
+/* Round a floating-point value to the nearest integer: */
+#define ROUNDF(X) ( (X)<0.0F ? ((GLint) ((X)-0.5F)) : ((GLint) ((X)+0.5F)) )
+
+
+/* Compute ceiling of integer quotient of A divided by B: */
+#define CEILING( A, B ) ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
+
+
+/* Clamp X to [MIN,MAX]: */
+#define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) )
+
+/* Assign X to CLAMP(X, MIN, MAX) */
+#define CLAMP_SELF(x, mn, mx) \
+ ( (x)<(mn) ? ((x) = (mn)) : ((x)>(mx) ? ((x)=(mx)) : (x)) )
+
+
+
+/* Min of two values: */
+#define MIN2( A, B ) ( (A)<(B) ? (A) : (B) )
+
+
+/* MAX of two values: */
+#define MAX2( A, B ) ( (A)>(B) ? (A) : (B) )
+
+/* Dot product of two 2-element vectors */
+#define DOT2( a, b ) ( (a)[0]*(b)[0] + (a)[1]*(b)[1] )
+
+/* Dot product of two 3-element vectors */
+#define DOT3( a, b ) ( (a)[0]*(b)[0] + (a)[1]*(b)[1] + (a)[2]*(b)[2] )
+
+
+/* Dot product of two 4-element vectors */
+#define DOT4( a, b ) ( (a)[0]*(b)[0] + (a)[1]*(b)[1] + \
+ (a)[2]*(b)[2] + (a)[3]*(b)[3] )
+
+#define DOT4V(v,a,b,c,d) (v[0]*a + v[1]*b + v[2]*c + v[3]*d)
+
+
+#define CROSS3(n, u, v) \
+do { \
+ (n)[0] = (u)[1]*(v)[2] - (u)[2]*(v)[1]; \
+ (n)[1] = (u)[2]*(v)[0] - (u)[0]*(v)[2]; \
+ (n)[2] = (u)[0]*(v)[1] - (u)[1]*(v)[0]; \
+} while (0)
+
+
+/*
+ * Integer / float conversion for colors, normals, etc.
+ */
+
+
+
+
+#define BYTE_TO_UBYTE(b) (b < 0 ? 0 : (GLubyte) b)
+#define SHORT_TO_UBYTE(s) (s < 0 ? 0 : (GLubyte) (s >> 7))
+#define USHORT_TO_UBYTE(s) (GLubyte) (s >> 8)
+#define INT_TO_UBYTE(i) (i < 0 ? 0 : (GLubyte) (i >> 23))
+#define UINT_TO_UBYTE(i) (GLubyte) (i >> 24)
+
+
+
+
+/* Convert GLubyte in [0,255] to GLfloat in [0.0,1.0] */
+#define UBYTE_TO_FLOAT(B) ((GLfloat) (B) * (1.0F / 255.0F))
+
+/* Convert GLfloat in [0.0,1.0] to GLubyte in [0,255] */
+#define FLOAT_TO_UBYTE(X) ((GLubyte) (GLint) (((X)) * 255.0F))
+
+
+/* Convert GLbyte in [-128,127] to GLfloat in [-1.0,1.0] */
+#define BYTE_TO_FLOAT(B) ((2.0F * (B) + 1.0F) * (1.0F/255.0F))
+
+/* Convert GLfloat in [-1.0,1.0] to GLbyte in [-128,127] */
+#define FLOAT_TO_BYTE(X) ( (((GLint) (255.0F * (X))) - 1) / 2 )
+
+
+/* Convert GLushort in [0,65536] to GLfloat in [0.0,1.0] */
+#define USHORT_TO_FLOAT(S) ((GLfloat) (S) * (1.0F / 65535.0F))
+
+/* Convert GLfloat in [0.0,1.0] to GLushort in [0,65536] */
+#define FLOAT_TO_USHORT(X) ((GLushort) (GLint) ((X) * 65535.0F))
+
+
+/* Convert GLshort in [-32768,32767] to GLfloat in [-1.0,1.0] */
+#define SHORT_TO_FLOAT(S) ((2.0F * (S) + 1.0F) * (1.0F/65535.0F))
+
+/* Convert GLfloat in [0.0,1.0] to GLshort in [-32768,32767] */
+#define FLOAT_TO_SHORT(X) ( (((GLint) (65535.0F * (X))) - 1) / 2 )
+
+
+/* Convert GLuint in [0,4294967295] to GLfloat in [0.0,1.0] */
+#define UINT_TO_FLOAT(U) ((GLfloat) (U) * (1.0F / 4294967295.0F))
+
+/* Convert GLfloat in [0.0,1.0] to GLuint in [0,4294967295] */
+#define FLOAT_TO_UINT(X) ((GLuint) ((X) * 4294967295.0))
+
+
+/* Convert GLint in [-2147483648,2147483647] to GLfloat in [-1.0,1.0] */
+#define INT_TO_FLOAT(I) ((2.0F * (I) + 1.0F) * (1.0F/4294967294.0F))
+
+/* Convert GLfloat in [-1.0,1.0] to GLint in [-2147483648,2147483647] */
+/* causes overflow:
+#define FLOAT_TO_INT(X) ( (((GLint) (4294967294.0F * (X))) - 1) / 2 )
+*/
+/* a close approximation: */
+#define FLOAT_TO_INT(X) ( (GLint) (2147483647.0 * (X)) )
+
+
+
+/* Memory copy: */
+#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
+
+
+/* Memory set: */
+#ifdef SUNOS4
+#define MEMSET( DST, VAL, N ) \
+ memset( (char *) (DST), (int) (VAL), (int) (N) )
+#else
+#define MEMSET( DST, VAL, N ) \
+ memset( (void *) (DST), (int) (VAL), (size_t) (N) )
+#endif
+
+
+/* MACs and BeOS don't support static larger than 32kb, so... */
+#if defined(macintosh) && !defined(__MRC__)
+ extern char *AGLAlloc(int size);
+ extern void AGLFree(char* ptr);
+# define DEFARRAY(TYPE,NAME,SIZE) TYPE *NAME = (TYPE*)AGLAlloc(sizeof(TYPE)*(SIZE))
+# define DEFMARRAY(TYPE,NAME,SIZE1,SIZE2) TYPE (*NAME)[SIZE2] = (TYPE(*)[SIZE2])AGLAlloc(sizeof(TYPE)*(SIZE1)*(SIZE2))
+# define CHECKARRAY(NAME,CMD) do {if (!(NAME)) {CMD;}} while (0)
+# define UNDEFARRAY(NAME) do {if ((NAME)) {AGLFree((char*)NAME);} }while (0)
+#elif defined(__BEOS__)
+# define DEFARRAY(TYPE,NAME,SIZE) TYPE *NAME = (TYPE*)malloc(sizeof(TYPE)*(SIZE))
+# define DEFMARRAY(TYPE,NAME,SIZE1,SIZE2) TYPE (*NAME)[SIZE2] = (TYPE(*)[SIZE2])malloc(sizeof(TYPE)*(SIZE1)*(SIZE2))
+# define CHECKARRAY(NAME,CMD) do {if (!(NAME)) {CMD;}} while (0)
+# define UNDEFARRAY(NAME) do {if ((NAME)) {free((char*)NAME);} }while (0)
+#else
+# define DEFARRAY(TYPE,NAME,SIZE) TYPE NAME[SIZE]
+# define DEFMARRAY(TYPE,NAME,SIZE1,SIZE2) TYPE NAME[SIZE1][SIZE2]
+# define CHECKARRAY(NAME,CMD) do {} while(0)
+# define UNDEFARRAY(NAME)
+#endif
+
+
+/* Some compilers don't like some of Mesa's const usage */
+#ifdef NO_CONST
+# define CONST
+#else
+# define CONST const
+#endif
+
+
+
+/* Pi */
+#ifndef M_PI
+#define M_PI (3.1415926)
+#endif
+
+
+/* Degrees to radians conversion: */
+#define DEG2RAD (M_PI/180.0)
+
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+
+#endif /*MACROS_H*/
diff --git a/src/mesa/main/matrix.c b/src/mesa/main/matrix.c
new file mode 100644
index 0000000000..c6459947fe
--- /dev/null
+++ b/src/mesa/main/matrix.c
@@ -0,0 +1,1438 @@
+/* $Id: matrix.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+/*
+ * Matrix operations
+ *
+ *
+ * NOTES:
+ * 1. 4x4 transformation matrices are stored in memory in column major order.
+ * 2. Points/vertices are to be thought of as column vectors.
+ * 3. Transformation of a point p by a matrix M is: p' = M * p
+ *
+ */
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "context.h"
+#include "enums.h"
+#include "macros.h"
+#include "matrix.h"
+#include "mmath.h"
+#include "types.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+static const char *types[] = {
+ "MATRIX_GENERAL",
+ "MATRIX_IDENTITY",
+ "MATRIX_3D_NO_ROT",
+ "MATRIX_PERSPECTIVE",
+ "MATRIX_2D",
+ "MATRIX_2D_NO_ROT",
+ "MATRIX_3D"
+};
+static void matmul4( GLfloat *product, const GLfloat *a, const GLfloat *b );
+
+
+static GLfloat Identity[16] = {
+ 1.0, 0.0, 0.0, 0.0,
+ 0.0, 1.0, 0.0, 0.0,
+ 0.0, 0.0, 1.0, 0.0,
+ 0.0, 0.0, 0.0, 1.0
+};
+
+
+static void print_matrix_floats( const GLfloat m[16] )
+{
+ int i;
+ for (i=0;i<4;i++) {
+ fprintf(stderr,"\t%f %f %f %f\n", m[i], m[4+i], m[8+i], m[12+i] );
+ }
+}
+
+void gl_print_matrix( const GLmatrix *m )
+{
+ fprintf(stderr, "Matrix type: %s, flags: %x\n", types[m->type], m->flags);
+ print_matrix_floats(m->m);
+#if 1
+ fprintf(stderr, "Inverse: \n");
+ if (m->inv) {
+ GLfloat prod[16];
+ print_matrix_floats(m->inv);
+ matmul4(prod, m->m, m->inv);
+ fprintf(stderr, "Mat * Inverse:\n");
+ print_matrix_floats(prod);
+ } else
+ fprintf(stderr, " - not available\n");
+#endif
+}
+
+
+
+/*
+ * This matmul was contributed by Thomas Malik
+ *
+ * Perform a 4x4 matrix multiplication (product = a x b).
+ * Input: a, b - matrices to multiply
+ * Output: product - product of a and b
+ * WARNING: (product != b) assumed
+ * NOTE: (product == a) allowed
+ *
+ * KW: 4*16 = 64 muls
+ */
+#define A(row,col) a[(col<<2)+row]
+#define B(row,col) b[(col<<2)+row]
+#define P(row,col) product[(col<<2)+row]
+
+static void matmul4( GLfloat *product, const GLfloat *a, const GLfloat *b )
+{
+ GLint i;
+ for (i = 0; i < 4; i++) {
+ GLfloat ai0=A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3);
+ P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
+ P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
+ P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
+ P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3);
+ }
+}
+
+
+
+
+/* Multiply two matrices known to occupy only the top three rows,
+ * such as typical modelling matrices, and ortho matrices.
+ *
+ * KW: 3*9 = 27 muls
+ */
+static void matmul34( GLfloat *product, const GLfloat *a, const GLfloat *b )
+{
+ GLint i;
+ for (i = 0; i < 3; i++) {
+ GLfloat ai0=A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3);
+ P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0);
+ P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1);
+ P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2);
+ P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3;
+ }
+ P(3,0) = 0;
+ P(3,1) = 0;
+ P(3,2) = 0;
+ P(3,3) = 1;
+}
+
+static void matmul4fd( GLfloat *product, const GLfloat *a, const GLdouble *b )
+{
+ GLint i;
+ for (i = 0; i < 4; i++) {
+ GLfloat ai0=A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3);
+ P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
+ P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
+ P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
+ P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3);
+ }
+}
+
+#undef A
+#undef B
+#undef P
+
+
+
+#define SWAP_ROWS(a, b) { GLfloat *_tmp = a; (a)=(b); (b)=_tmp; }
+#define MAT(m,r,c) (m)[(c)*4+(r)]
+
+/*
+ * 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_general( GLmatrix *mat )
+{
+ const GLfloat *m = mat->m;
+ GLfloat *out = mat->inv;
+ GLfloat wtmp[4][8];
+ GLfloat m0, m1, m2, m3, s;
+ GLfloat *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 SWAP_ROWS
+
+/* Adapted from graphics gems II.
+ */
+GLboolean invert_matrix_3d_general( GLmatrix *mat )
+{
+ const GLfloat *in = mat->m;
+ GLfloat *out = mat->inv;
+ GLfloat pos, neg, t;
+ GLfloat det;
+
+ /* Calculate the determinant of upper left 3x3 submatrix and
+ * determine if the matrix is singular.
+ */
+ pos = neg = 0.0;
+ t = MAT(in,0,0) * MAT(in,1,1) * MAT(in,2,2);
+ if (t >= 0.0) pos += t; else neg += t;
+
+ t = MAT(in,1,0) * MAT(in,2,1) * MAT(in,0,2);
+ if (t >= 0.0) pos += t; else neg += t;
+
+ t = MAT(in,2,0) * MAT(in,0,1) * MAT(in,1,2);
+ if (t >= 0.0) pos += t; else neg += t;
+
+ t = -MAT(in,2,0) * MAT(in,1,1) * MAT(in,0,2);
+ if (t >= 0.0) pos += t; else neg += t;
+
+ t = -MAT(in,1,0) * MAT(in,0,1) * MAT(in,2,2);
+ if (t >= 0.0) pos += t; else neg += t;
+
+ t = -MAT(in,0,0) * MAT(in,2,1) * MAT(in,1,2);
+ if (t >= 0.0) pos += t; else neg += t;
+
+ det = pos + neg;
+
+ if (det*det < 1e-25)
+ return GL_FALSE;
+
+ det = 1.0 / det;
+ MAT(out,0,0) = ( (MAT(in,1,1)*MAT(in,2,2) - MAT(in,2,1)*MAT(in,1,2) )*det);
+ MAT(out,0,1) = (- (MAT(in,0,1)*MAT(in,2,2) - MAT(in,2,1)*MAT(in,0,2) )*det);
+ MAT(out,0,2) = ( (MAT(in,0,1)*MAT(in,1,2) - MAT(in,1,1)*MAT(in,0,2) )*det);
+ MAT(out,1,0) = (- (MAT(in,1,0)*MAT(in,2,2) - MAT(in,2,0)*MAT(in,1,2) )*det);
+ MAT(out,1,1) = ( (MAT(in,0,0)*MAT(in,2,2) - MAT(in,2,0)*MAT(in,0,2) )*det);
+ MAT(out,1,2) = (- (MAT(in,0,0)*MAT(in,1,2) - MAT(in,1,0)*MAT(in,0,2) )*det);
+ MAT(out,2,0) = ( (MAT(in,1,0)*MAT(in,2,1) - MAT(in,2,0)*MAT(in,1,1) )*det);
+ MAT(out,2,1) = (- (MAT(in,0,0)*MAT(in,2,1) - MAT(in,2,0)*MAT(in,0,1) )*det);
+ MAT(out,2,2) = ( (MAT(in,0,0)*MAT(in,1,1) - MAT(in,1,0)*MAT(in,0,1) )*det);
+
+ /* Do the translation part */
+ MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0) +
+ MAT(in,1,3) * MAT(out,0,1) +
+ MAT(in,2,3) * MAT(out,0,2) );
+ MAT(out,1,3) = - (MAT(in,0,3) * MAT(out,1,0) +
+ MAT(in,1,3) * MAT(out,1,1) +
+ MAT(in,2,3) * MAT(out,1,2) );
+ MAT(out,2,3) = - (MAT(in,0,3) * MAT(out,2,0) +
+ MAT(in,1,3) * MAT(out,2,1) +
+ MAT(in,2,3) * MAT(out,2,2) );
+
+ return GL_TRUE;
+}
+
+
+static GLboolean invert_matrix_3d( GLmatrix *mat )
+{
+ const GLfloat *in = mat->m;
+ GLfloat *out = mat->inv;
+
+ if (!TEST_MAT_FLAGS(mat, MAT_FLAGS_ANGLE_PRESERVING))
+ {
+ return invert_matrix_3d_general( mat );
+ }
+
+ if (mat->flags & MAT_FLAG_UNIFORM_SCALE)
+ {
+ GLfloat scale = (MAT(in,0,0) * MAT(in,0,0) +
+ MAT(in,0,1) * MAT(in,0,1) +
+ MAT(in,0,2) * MAT(in,0,2));
+
+ if (scale == 0.0)
+ return GL_FALSE;
+
+ scale = 1.0 / scale;
+
+ /* Transpose and scale the 3 by 3 upper-left submatrix. */
+ MAT(out,0,0) = scale * MAT(in,0,0);
+ MAT(out,1,0) = scale * MAT(in,0,1);
+ MAT(out,2,0) = scale * MAT(in,0,2);
+ MAT(out,0,1) = scale * MAT(in,1,0);
+ MAT(out,1,1) = scale * MAT(in,1,1);
+ MAT(out,2,1) = scale * MAT(in,1,2);
+ MAT(out,0,2) = scale * MAT(in,2,0);
+ MAT(out,1,2) = scale * MAT(in,2,1);
+ MAT(out,2,2) = scale * MAT(in,2,2);
+ }
+ else if (mat->flags & MAT_FLAG_ROTATION)
+ {
+ /* Transpose the 3 by 3 upper-left submatrix. */
+ MAT(out,0,0) = MAT(in,0,0);
+ MAT(out,1,0) = MAT(in,0,1);
+ MAT(out,2,0) = MAT(in,0,2);
+ MAT(out,0,1) = MAT(in,1,0);
+ MAT(out,1,1) = MAT(in,1,1);
+ MAT(out,2,1) = MAT(in,1,2);
+ MAT(out,0,2) = MAT(in,2,0);
+ MAT(out,1,2) = MAT(in,2,1);
+ MAT(out,2,2) = MAT(in,2,2);
+ }
+ else /* pure translation */
+ {
+ MEMCPY( out, Identity, sizeof(Identity) );
+ MAT(out,0,3) = - MAT(in,0,3);
+ MAT(out,1,3) = - MAT(in,1,3);
+ MAT(out,2,3) = - MAT(in,2,3);
+ return GL_TRUE;
+ }
+
+ if (mat->flags & MAT_FLAG_TRANSLATION)
+ {
+ /* Do the translation part */
+ MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0) +
+ MAT(in,1,3) * MAT(out,0,1) +
+ MAT(in,2,3) * MAT(out,0,2) );
+ MAT(out,1,3) = - (MAT(in,0,3) * MAT(out,1,0) +
+ MAT(in,1,3) * MAT(out,1,1) +
+ MAT(in,2,3) * MAT(out,1,2) );
+ MAT(out,2,3) = - (MAT(in,0,3) * MAT(out,2,0) +
+ MAT(in,1,3) * MAT(out,2,1) +
+ MAT(in,2,3) * MAT(out,2,2) );
+ }
+ else
+ {
+ MAT(out,0,3) = MAT(out,1,3) = MAT(out,2,3) = 0.0;
+ }
+
+ return GL_TRUE;
+}
+
+
+
+static GLboolean invert_matrix_identity( GLmatrix *mat )
+{
+ MEMCPY( mat->inv, Identity, sizeof(Identity) );
+ return GL_TRUE;
+}
+
+
+static GLboolean invert_matrix_3d_no_rot( GLmatrix *mat )
+{
+ const GLfloat *in = mat->m;
+ GLfloat *out = mat->inv;
+
+ if (MAT(in,0,0) == 0 || MAT(in,1,1) == 0 || MAT(in,2,2) == 0 )
+ return GL_FALSE;
+
+ MEMCPY( out, Identity, 16 * sizeof(GLfloat) );
+ MAT(out,0,0) = 1.0 / MAT(in,0,0);
+ MAT(out,1,1) = 1.0 / MAT(in,1,1);
+ MAT(out,2,2) = 1.0 / MAT(in,2,2);
+
+ if (mat->flags & MAT_FLAG_TRANSLATION)
+ {
+ MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0));
+ MAT(out,1,3) = - (MAT(in,1,3) * MAT(out,1,1));
+ MAT(out,2,3) = - (MAT(in,2,3) * MAT(out,2,2));
+ }
+
+ return GL_TRUE;
+}
+
+
+static GLboolean invert_matrix_2d_no_rot( GLmatrix *mat )
+{
+ const GLfloat *in = mat->m;
+ GLfloat *out = mat->inv;
+
+ if (MAT(in,0,0) == 0 || MAT(in,1,1) == 0)
+ return GL_FALSE;
+
+ MEMCPY( out, Identity, 16 * sizeof(GLfloat) );
+ MAT(out,0,0) = 1.0 / MAT(in,0,0);
+ MAT(out,1,1) = 1.0 / MAT(in,1,1);
+
+ if (mat->flags & MAT_FLAG_TRANSLATION)
+ {
+ MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0));
+ MAT(out,1,3) = - (MAT(in,1,3) * MAT(out,1,1));
+ }
+
+ return GL_TRUE;
+}
+
+
+static GLboolean invert_matrix_perspective( GLmatrix *mat )
+{
+ const GLfloat *in = mat->m;
+ GLfloat *out = mat->inv;
+
+ if (MAT(in,2,3) == 0)
+ return GL_FALSE;
+
+ MEMCPY( out, Identity, 16 * sizeof(GLfloat) );
+
+ MAT(out,0,0) = 1.0 / MAT(in,0,0);
+ MAT(out,1,1) = 1.0 / MAT(in,1,1);
+
+ MAT(out,0,3) = MAT(in,0,2);
+ MAT(out,1,3) = MAT(in,1,2);
+
+ MAT(out,2,2) = 0;
+ MAT(out,2,3) = -1;
+
+ MAT(out,3,2) = 1.0 / MAT(in,2,3);
+ MAT(out,3,3) = MAT(in,2,2) * MAT(out,3,2);
+
+ return GL_TRUE;
+}
+
+
+typedef GLboolean (*inv_mat_func)( GLmatrix *mat );
+
+static inv_mat_func inv_mat_tab[7] = {
+ invert_matrix_general,
+ invert_matrix_identity,
+ invert_matrix_3d_no_rot,
+ invert_matrix_perspective,
+ invert_matrix_3d, /* lazy! */
+ invert_matrix_2d_no_rot,
+ invert_matrix_3d
+};
+
+
+GLboolean gl_matrix_invert( GLmatrix *mat )
+{
+ if (inv_mat_tab[mat->type](mat)) {
+#if 0
+ GLmatrix m; m.inv = 0; m.type = 0; m.flags = 0;
+ matmul4( m.m, mat->m, mat->inv );
+ printf("inverted matrix of type %s:\n", types[mat->type]);
+ gl_print_matrix( mat );
+ gl_print_matrix( &m );
+#endif
+ return GL_TRUE;
+ } else {
+ MEMCPY( mat->inv, Identity, sizeof(Identity) );
+ return GL_FALSE;
+ }
+}
+
+
+
+/*
+ * Generate a 4x4 transformation matrix from glRotate parameters.
+ */
+void gl_rotation_matrix( GLfloat angle, GLfloat x, GLfloat y, GLfloat z,
+ GLfloat m[] )
+{
+ /* This function contributed by Erich Boleyn (erich@uruk.org) */
+ GLfloat mag, s, c;
+ GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c;
+
+ s = sin( angle * DEG2RAD );
+ c = cos( angle * DEG2RAD );
+
+ mag = GL_SQRT( x*x + y*y + z*z );
+
+ if (mag == 0.0) {
+ /* generate an identity matrix and return */
+ MEMCPY(m, Identity, sizeof(GLfloat)*16);
+ return;
+ }
+
+ x /= mag;
+ y /= mag;
+ z /= mag;
+
+#define M(row,col) m[col*4+row]
+
+ /*
+ * Arbitrary axis rotation matrix.
+ *
+ * This is composed of 5 matrices, Rz, Ry, T, Ry', Rz', multiplied
+ * like so: Rz * Ry * T * Ry' * Rz'. T is the final rotation
+ * (which is about the X-axis), and the two composite transforms
+ * Ry' * Rz' and Rz * Ry are (respectively) the rotations necessary
+ * from the arbitrary axis to the X-axis then back. They are
+ * all elementary rotations.
+ *
+ * Rz' is a rotation about the Z-axis, to bring the axis vector
+ * into the x-z plane. Then Ry' is applied, rotating about the
+ * Y-axis to bring the axis vector parallel with the X-axis. The
+ * rotation about the X-axis is then performed. Ry and Rz are
+ * simply the respective inverse transforms to bring the arbitrary
+ * axis back to it's original orientation. The first transforms
+ * Rz' and Ry' are considered inverses, since the data from the
+ * arbitrary axis gives you info on how to get to it, not how
+ * to get away from it, and an inverse must be applied.
+ *
+ * The basic calculation used is to recognize that the arbitrary
+ * axis vector (x, y, z), since it is of unit length, actually
+ * represents the sines and cosines of the angles to rotate the
+ * X-axis to the same orientation, with theta being the angle about
+ * Z and phi the angle about Y (in the order described above)
+ * as follows:
+ *
+ * cos ( theta ) = x / sqrt ( 1 - z^2 )
+ * sin ( theta ) = y / sqrt ( 1 - z^2 )
+ *
+ * cos ( phi ) = sqrt ( 1 - z^2 )
+ * sin ( phi ) = z
+ *
+ * Note that cos ( phi ) can further be inserted to the above
+ * formulas:
+ *
+ * cos ( theta ) = x / cos ( phi )
+ * sin ( theta ) = y / sin ( phi )
+ *
+ * ...etc. Because of those relations and the standard trigonometric
+ * relations, it is pssible to reduce the transforms down to what
+ * is used below. It may be that any primary axis chosen will give the
+ * same results (modulo a sign convention) using thie method.
+ *
+ * Particularly nice is to notice that all divisions that might
+ * have caused trouble when parallel to certain planes or
+ * axis go away with care paid to reducing the expressions.
+ * After checking, it does perform correctly under all cases, since
+ * in all the cases of division where the denominator would have
+ * been zero, the numerator would have been zero as well, giving
+ * the expected result.
+ */
+
+ xx = x * x;
+ yy = y * y;
+ zz = z * z;
+ xy = x * y;
+ yz = y * z;
+ zx = z * x;
+ xs = x * s;
+ ys = y * s;
+ zs = z * s;
+ one_c = 1.0F - c;
+
+ M(0,0) = (one_c * xx) + c;
+ M(0,1) = (one_c * xy) - zs;
+ M(0,2) = (one_c * zx) + ys;
+ M(0,3) = 0.0F;
+
+ M(1,0) = (one_c * xy) + zs;
+ M(1,1) = (one_c * yy) + c;
+ M(1,2) = (one_c * yz) - xs;
+ M(1,3) = 0.0F;
+
+ M(2,0) = (one_c * zx) - ys;
+ M(2,1) = (one_c * yz) + xs;
+ M(2,2) = (one_c * zz) + c;
+ M(2,3) = 0.0F;
+
+ M(3,0) = 0.0F;
+ M(3,1) = 0.0F;
+ M(3,2) = 0.0F;
+ M(3,3) = 1.0F;
+
+#undef M
+}
+
+#define ZERO(x) (1<<x)
+#define ONE(x) (1<<(x+16))
+
+#define MASK_NO_TRX (ZERO(12) | ZERO(13) | ZERO(14))
+#define MASK_NO_2D_SCALE ( ONE(0) | ONE(5))
+
+#define MASK_IDENTITY ( ONE(0) | ZERO(4) | ZERO(8) | ZERO(12) |\
+ ZERO(1) | ONE(5) | ZERO(9) | ZERO(13) |\
+ ZERO(2) | ZERO(6) | ONE(10) | ZERO(14) |\
+ ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) )
+
+#define MASK_2D_NO_ROT ( ZERO(4) | ZERO(8) | \
+ ZERO(1) | ZERO(9) | \
+ ZERO(2) | ZERO(6) | ONE(10) | ZERO(14) |\
+ ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) )
+
+#define MASK_2D ( ZERO(8) | \
+ ZERO(9) | \
+ ZERO(2) | ZERO(6) | ONE(10) | ZERO(14) |\
+ ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) )
+
+
+#define MASK_3D_NO_ROT ( ZERO(4) | ZERO(8) | \
+ ZERO(1) | ZERO(9) | \
+ ZERO(2) | ZERO(6) | \
+ ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) )
+
+#define MASK_3D ( \
+ \
+ \
+ ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) )
+
+
+#define MASK_PERSPECTIVE ( ZERO(4) | ZERO(12) |\
+ ZERO(1) | ZERO(13) |\
+ ZERO(2) | ZERO(6) | \
+ ZERO(3) | ZERO(7) | ZERO(15) )
+
+#define SQ(x) ((x)*(x))
+
+/* Determine type and flags from scratch. This is expensive enough to
+ * only want to do it once.
+ */
+static void analyze_from_scratch( GLmatrix *mat )
+{
+ const GLfloat *m = mat->m;
+ GLuint mask = 0;
+ GLuint i;
+
+ for (i = 0 ; i < 16 ; i++)
+ {
+ if (m[i] == 0.0) mask |= (1<<i);
+ }
+
+ if (m[0] == 1.0F) mask |= (1<<16);
+ if (m[5] == 1.0F) mask |= (1<<21);
+ if (m[10] == 1.0F) mask |= (1<<26);
+ if (m[15] == 1.0F) mask |= (1<<31);
+
+ mat->flags &= ~MAT_FLAGS_GEOMETRY;
+
+ /* Check for translation - no-one really cares
+ */
+ if ((mask & MASK_NO_TRX) != MASK_NO_TRX)
+ mat->flags |= MAT_FLAG_TRANSLATION;
+
+ /* Do the real work
+ */
+ if (mask == MASK_IDENTITY) {
+ mat->type = MATRIX_IDENTITY;
+ }
+ else if ((mask & MASK_2D_NO_ROT) == MASK_2D_NO_ROT)
+ {
+ mat->type = MATRIX_2D_NO_ROT;
+
+ if ((mask & MASK_NO_2D_SCALE) != MASK_NO_2D_SCALE)
+ mat->flags = MAT_FLAG_GENERAL_SCALE;
+ }
+ else if ((mask & MASK_2D) == MASK_2D)
+ {
+ GLfloat mm = DOT2(m, m);
+ GLfloat m4m4 = DOT2(m+4,m+4);
+ GLfloat mm4 = DOT2(m,m+4);
+
+ mat->type = MATRIX_2D;
+
+ /* Check for scale */
+ if (SQ(mm-1) > SQ(1e-6) ||
+ SQ(m4m4-1) > SQ(1e-6))
+ mat->flags |= MAT_FLAG_GENERAL_SCALE;
+
+ /* Check for rotation */
+ if (SQ(mm4) > SQ(1e-6))
+ mat->flags |= MAT_FLAG_GENERAL_3D;
+ else
+ mat->flags |= MAT_FLAG_ROTATION;
+
+ }
+ else if ((mask & MASK_3D_NO_ROT) == MASK_3D_NO_ROT)
+ {
+ mat->type = MATRIX_3D_NO_ROT;
+
+ /* Check for scale */
+ if (SQ(m[0]-m[5]) < SQ(1e-6) &&
+ SQ(m[0]-m[10]) < SQ(1e-6)) {
+ if (SQ(m[0]-1.0) > SQ(1e-6))
+ mat->flags |= MAT_FLAG_UNIFORM_SCALE;
+ } else
+ mat->flags |= MAT_FLAG_GENERAL_SCALE;
+ }
+ else if ((mask & MASK_3D) == MASK_3D)
+ {
+ GLfloat c1 = DOT3(m,m);
+ GLfloat c2 = DOT3(m+4,m+4);
+ GLfloat c3 = DOT3(m+8,m+8);
+ GLfloat d1 = DOT3(m, m+4);
+ GLfloat cp[3];
+
+ mat->type = MATRIX_3D;
+
+ /* Check for scale */
+ if (SQ(c1-c2) < SQ(1e-6) && SQ(c1-c3) < SQ(1e-6)) {
+ if (SQ(c1-1.0) > SQ(1e-6))
+ mat->flags |= MAT_FLAG_UNIFORM_SCALE;
+ /* else no scale at all */
+ } else
+ mat->flags |= MAT_FLAG_GENERAL_SCALE;
+
+ /* Check for rotation */
+ if (SQ(d1) < SQ(1e-6)) {
+ CROSS3( cp, m, m+4 );
+ SUB_3V( cp, cp, (m+8) );
+ if (LEN_SQUARED_3FV(cp) < SQ(1e-6))
+ mat->flags |= MAT_FLAG_ROTATION;
+ else
+ mat->flags |= MAT_FLAG_GENERAL_3D;
+ }
+ else
+ mat->flags |= MAT_FLAG_GENERAL_3D; /* shear, etc */
+ }
+ else if ((mask & MASK_PERSPECTIVE) == MASK_PERSPECTIVE && m[11]==-1.0F)
+ {
+ mat->type = MATRIX_PERSPECTIVE;
+ mat->flags |= MAT_FLAG_GENERAL;
+ }
+ else {
+ mat->type = MATRIX_GENERAL;
+ mat->flags |= MAT_FLAG_GENERAL;
+ }
+}
+
+
+/* Analyse a matrix given that its flags are accurate - this is the
+ * more common operation, hopefully.
+ */
+static void analyze_from_flags( GLmatrix *mat )
+{
+ const GLfloat *m = mat->m;
+
+ if (TEST_MAT_FLAGS(mat, 0)) {
+ mat->type = MATRIX_IDENTITY;
+ }
+ else if (TEST_MAT_FLAGS(mat, (MAT_FLAG_TRANSLATION |
+ MAT_FLAG_UNIFORM_SCALE |
+ MAT_FLAG_GENERAL_SCALE)))
+ {
+ if ( m[10]==1.0F && m[14]==0.0F ) {
+ mat->type = MATRIX_2D_NO_ROT;
+ }
+ else {
+ mat->type = MATRIX_3D_NO_ROT;
+ }
+ }
+ else if (TEST_MAT_FLAGS(mat, MAT_FLAGS_3D)) {
+ if ( m[ 8]==0.0F
+ && m[ 9]==0.0F
+ && m[2]==0.0F && m[6]==0.0F && m[10]==1.0F && m[14]==0.0F)
+ {
+ mat->type = MATRIX_2D;
+ }
+ else
+ {
+ mat->type = MATRIX_3D;
+ }
+ }
+ else if ( m[4]==0.0F && m[12]==0.0F
+ && m[1]==0.0F && m[13]==0.0F
+ && m[2]==0.0F && m[6]==0.0F
+ && m[3]==0.0F && m[7]==0.0F && m[11]==-1.0F && m[15]==0.0F)
+ {
+ mat->type = MATRIX_PERSPECTIVE;
+ }
+ else {
+ mat->type = MATRIX_GENERAL;
+ }
+
+}
+
+
+void gl_matrix_analyze( GLmatrix *mat )
+{
+ if (mat->flags & MAT_DIRTY_TYPE) {
+ if (mat->flags & MAT_DIRTY_FLAGS)
+ analyze_from_scratch( mat );
+ else
+ analyze_from_flags( mat );
+ }
+
+ if (mat->inv && (mat->flags & MAT_DIRTY_INVERSE)) {
+ gl_matrix_invert( mat );
+ }
+
+ mat->flags &= ~(MAT_DIRTY_FLAGS|
+ MAT_DIRTY_TYPE|
+ MAT_DIRTY_INVERSE);
+}
+
+
+#define GET_ACTIVE_MATRIX(ctx, mat, flags, where) \
+do { \
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, where); \
+ if (MESA_VERBOSE&VERBOSE_API) fprintf(stderr, "%s\n", where); \
+ switch (ctx->Transform.MatrixMode) { \
+ case GL_MODELVIEW: \
+ mat = &ctx->ModelView; \
+ flags |= NEW_MODELVIEW; \
+ break; \
+ case GL_PROJECTION: \
+ mat = &ctx->ProjectionMatrix; \
+ flags |= NEW_PROJECTION; \
+ break; \
+ case GL_TEXTURE: \
+ mat = &ctx->TextureMatrix[ctx->Texture.CurrentTransformUnit]; \
+ flags |= NEW_TEXTURE_MATRIX; \
+ break; \
+ default: \
+ gl_problem(ctx, where); \
+ } \
+} while (0)
+
+
+void gl_Frustum( GLcontext *ctx,
+ GLdouble left, GLdouble right,
+ GLdouble bottom, GLdouble top,
+ GLdouble nearval, GLdouble farval )
+{
+ GLfloat x, y, a, b, c, d;
+ GLfloat m[16];
+ GLmatrix *mat = 0;
+
+ GET_ACTIVE_MATRIX( ctx, mat, ctx->NewState, "glFrustrum" );
+
+ if (nearval<=0.0 || farval<=0.0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glFrustum(near or far)" );
+ }
+
+ 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); /* error? */
+
+#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
+
+
+ gl_mat_mul_floats( mat, m, MAT_FLAG_PERSPECTIVE );
+
+
+ if (ctx->Transform.MatrixMode == GL_PROJECTION)
+ {
+ /* Need to keep a stack of near/far values in case the user push/pops
+ * the projection matrix stack so that we can call Driver.NearFar()
+ * after a pop.
+ */
+ ctx->NearFarStack[ctx->ProjectionStackDepth][0] = nearval;
+ ctx->NearFarStack[ctx->ProjectionStackDepth][1] = farval;
+
+ if (ctx->Driver.NearFar) {
+ (*ctx->Driver.NearFar)( ctx, nearval, farval );
+ }
+ }
+}
+
+
+void gl_Ortho( GLcontext *ctx,
+ GLdouble left, GLdouble right,
+ GLdouble bottom, GLdouble top,
+ GLdouble nearval, GLdouble farval )
+{
+ GLfloat x, y, z;
+ GLfloat tx, ty, tz;
+ GLfloat m[16];
+ GLmatrix *mat = 0;
+
+ GET_ACTIVE_MATRIX( ctx, mat, ctx->NewState, "glOrtho" );
+
+ x = 2.0 / (right-left);
+ y = 2.0 / (top-bottom);
+ z = -2.0 / (farval-nearval);
+ tx = -(right+left) / (right-left);
+ ty = -(top+bottom) / (top-bottom);
+ tz = -(farval+nearval) / (farval-nearval);
+
+#define M(row,col) m[col*4+row]
+ M(0,0) = x; M(0,1) = 0.0F; M(0,2) = 0.0F; M(0,3) = tx;
+ M(1,0) = 0.0F; M(1,1) = y; M(1,2) = 0.0F; M(1,3) = ty;
+ M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = z; M(2,3) = tz;
+ M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = 0.0F; M(3,3) = 1.0F;
+#undef M
+
+ gl_mat_mul_floats( mat, m, (MAT_FLAG_GENERAL_SCALE|MAT_FLAG_TRANSLATION));
+
+ if (ctx->Driver.NearFar) {
+ (*ctx->Driver.NearFar)( ctx, nearval, farval );
+ }
+}
+
+
+void gl_MatrixMode( GLcontext *ctx, GLenum mode )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glMatrixMode");
+ switch (mode) {
+ case GL_MODELVIEW:
+ case GL_PROJECTION:
+ case GL_TEXTURE:
+ ctx->Transform.MatrixMode = mode;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glMatrixMode" );
+ }
+}
+
+
+
+void gl_PushMatrix( GLcontext *ctx )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPushMatrix");
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ fprintf(stderr, "glPushMatrix %s\n",
+ gl_lookup_enum_by_nr(ctx->Transform.MatrixMode));
+
+ switch (ctx->Transform.MatrixMode) {
+ case GL_MODELVIEW:
+ if (ctx->ModelViewStackDepth>=MAX_MODELVIEW_STACK_DEPTH-1) {
+ gl_error( ctx, GL_STACK_OVERFLOW, "glPushMatrix");
+ return;
+ }
+ gl_matrix_copy( &ctx->ModelViewStack[ctx->ModelViewStackDepth++],
+ &ctx->ModelView );
+ break;
+ case GL_PROJECTION:
+ if (ctx->ProjectionStackDepth>=MAX_PROJECTION_STACK_DEPTH) {
+ gl_error( ctx, GL_STACK_OVERFLOW, "glPushMatrix");
+ return;
+ }
+ gl_matrix_copy( &ctx->ProjectionStack[ctx->ProjectionStackDepth++],
+ &ctx->ProjectionMatrix );
+
+ /* Save near and far projection values */
+ ctx->NearFarStack[ctx->ProjectionStackDepth][0]
+ = ctx->NearFarStack[ctx->ProjectionStackDepth-1][0];
+ ctx->NearFarStack[ctx->ProjectionStackDepth][1]
+ = ctx->NearFarStack[ctx->ProjectionStackDepth-1][1];
+ break;
+ case GL_TEXTURE:
+ {
+ GLuint t = ctx->Texture.CurrentTransformUnit;
+ if (ctx->TextureStackDepth[t] >= MAX_TEXTURE_STACK_DEPTH) {
+ gl_error( ctx, GL_STACK_OVERFLOW, "glPushMatrix");
+ return;
+ }
+ gl_matrix_copy( &ctx->TextureStack[t][ctx->TextureStackDepth[t]++],
+ &ctx->TextureMatrix[t] );
+ }
+ break;
+ default:
+ gl_problem(ctx, "Bad matrix mode in gl_PushMatrix");
+ }
+}
+
+
+
+void gl_PopMatrix( GLcontext *ctx )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPopMatrix");
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ fprintf(stderr, "glPopMatrix %s\n",
+ gl_lookup_enum_by_nr(ctx->Transform.MatrixMode));
+
+ switch (ctx->Transform.MatrixMode) {
+ case GL_MODELVIEW:
+ if (ctx->ModelViewStackDepth==0) {
+ gl_error( ctx, GL_STACK_UNDERFLOW, "glPopMatrix");
+ return;
+ }
+ gl_matrix_copy( &ctx->ModelView,
+ &ctx->ModelViewStack[--ctx->ModelViewStackDepth] );
+ ctx->NewState |= NEW_MODELVIEW;
+ break;
+ case GL_PROJECTION:
+ if (ctx->ProjectionStackDepth==0) {
+ gl_error( ctx, GL_STACK_UNDERFLOW, "glPopMatrix");
+ return;
+ }
+
+ gl_matrix_copy( &ctx->ProjectionMatrix,
+ &ctx->ProjectionStack[--ctx->ProjectionStackDepth] );
+ ctx->NewState |= NEW_PROJECTION;
+
+ /* Device driver near/far values */
+ {
+ GLfloat nearVal = ctx->NearFarStack[ctx->ProjectionStackDepth][0];
+ GLfloat farVal = ctx->NearFarStack[ctx->ProjectionStackDepth][1];
+ if (ctx->Driver.NearFar) {
+ (*ctx->Driver.NearFar)( ctx, nearVal, farVal );
+ }
+ }
+ break;
+ case GL_TEXTURE:
+ {
+ GLuint t = ctx->Texture.CurrentTransformUnit;
+ if (ctx->TextureStackDepth[t]==0) {
+ gl_error( ctx, GL_STACK_UNDERFLOW, "glPopMatrix");
+ return;
+ }
+ gl_matrix_copy(&ctx->TextureMatrix[t],
+ &ctx->TextureStack[t][--ctx->TextureStackDepth[t]]);
+ }
+ break;
+ default:
+ gl_problem(ctx, "Bad matrix mode in gl_PopMatrix");
+ }
+}
+
+
+
+void gl_LoadIdentity( GLcontext *ctx )
+{
+ GLmatrix *mat = 0;
+ GET_ACTIVE_MATRIX(ctx, mat, ctx->NewState, "glLoadIdentity");
+
+ MEMCPY( mat->m, Identity, 16*sizeof(GLfloat) );
+
+ if (mat->inv)
+ MEMCPY( mat->inv, Identity, 16*sizeof(GLfloat) );
+
+ mat->type = MATRIX_IDENTITY;
+
+ /* Have to set this to dirty to make sure we recalculate the
+ * combined matrix later. The update_matrix in this case is a
+ * shortcircuit anyway...
+ */
+ mat->flags = MAT_DIRTY_DEPENDENTS;
+}
+
+
+void gl_LoadMatrixf( GLcontext *ctx, const GLfloat *m )
+{
+ GLmatrix *mat = 0;
+ GET_ACTIVE_MATRIX(ctx, mat, ctx->NewState, "glLoadMatrix");
+
+ MEMCPY( mat->m, m, 16*sizeof(GLfloat) );
+ mat->flags = (MAT_FLAG_GENERAL | MAT_DIRTY_ALL_OVER);
+
+ if (ctx->Transform.MatrixMode == GL_PROJECTION) {
+
+#define M(row,col) m[col*4+row]
+ GLfloat c = M(2,2);
+ GLfloat d = M(2,3);
+#undef M
+ GLfloat n = (c == 1.0 ? 0.0 : d / (c - 1.0));
+ GLfloat f = (c == -1.0 ? 1.0 : d / (c + 1.0));
+
+ /* Need to keep a stack of near/far values in case the user
+ * push/pops the projection matrix stack so that we can call
+ * Driver.NearFar() after a pop.
+ */
+ ctx->NearFarStack[ctx->ProjectionStackDepth][0] = n;
+ ctx->NearFarStack[ctx->ProjectionStackDepth][1] = f;
+
+ if (ctx->Driver.NearFar) {
+ (*ctx->Driver.NearFar)( ctx, n, f );
+ }
+ }
+}
+
+
+
+/*
+ * Multiply the active matrix by an arbitary matrix.
+ */
+void gl_MultMatrixf( GLcontext *ctx, const GLfloat *m )
+{
+ GLmatrix *mat = 0;
+ GET_ACTIVE_MATRIX( ctx, mat, ctx->NewState, "glMultMatrix" );
+ matmul4( mat->m, mat->m, m );
+ mat->flags = (MAT_FLAG_GENERAL | MAT_DIRTY_ALL_OVER);
+}
+
+
+/*
+ * Multiply the active matrix by an arbitary matrix.
+ */
+void gl_MultMatrixd( GLcontext *ctx, const GLdouble *m )
+{
+ GLmatrix *mat = 0;
+ GET_ACTIVE_MATRIX( ctx, mat, ctx->NewState, "glMultMatrix" );
+ matmul4fd( mat->m, mat->m, m );
+ mat->flags = (MAT_FLAG_GENERAL | MAT_DIRTY_ALL_OVER);
+}
+
+
+
+
+/*
+ * Multiply a matrix by an array of floats with known properties.
+ */
+void gl_mat_mul_floats( GLmatrix *mat, const GLfloat *m, GLuint flags )
+{
+ mat->flags |= (flags |
+ MAT_DIRTY_TYPE |
+ MAT_DIRTY_INVERSE |
+ MAT_DIRTY_DEPENDENTS);
+
+ if (TEST_MAT_FLAGS(mat, MAT_FLAGS_3D))
+ matmul34( mat->m, mat->m, m );
+ else
+ matmul4( mat->m, mat->m, m );
+
+}
+
+/*
+ * Multiply a matrix by an array of floats with known properties.
+ */
+void gl_mat_mul_mat( GLmatrix *mat, const GLmatrix *m )
+{
+ mat->flags |= (m->flags |
+ MAT_DIRTY_TYPE |
+ MAT_DIRTY_INVERSE |
+ MAT_DIRTY_DEPENDENTS);
+
+ if (TEST_MAT_FLAGS(mat, MAT_FLAGS_3D))
+ matmul34( mat->m, mat->m, m->m );
+ else
+ matmul4( mat->m, mat->m, m->m );
+}
+
+
+
+/*
+ * Execute a glRotate call
+ */
+void gl_Rotatef( GLcontext *ctx,
+ GLfloat angle, GLfloat x, GLfloat y, GLfloat z )
+{
+ GLfloat m[16];
+ if (angle != 0.0F) {
+ GLmatrix *mat = 0;
+ GET_ACTIVE_MATRIX( ctx, mat, ctx->NewState, "glRotate" );
+
+ gl_rotation_matrix( angle, x, y, z, m );
+ gl_mat_mul_floats( mat, m, MAT_FLAG_ROTATION );
+ }
+}
+
+/*
+ * Execute a glScale call
+ */
+void gl_Scalef( GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z )
+{
+ GLmatrix *mat = 0;
+ GLfloat *m;
+ GET_ACTIVE_MATRIX(ctx, mat, ctx->NewState, "glScale");
+
+ m = mat->m;
+ m[0] *= x; m[4] *= y; m[8] *= z;
+ m[1] *= x; m[5] *= y; m[9] *= z;
+ m[2] *= x; m[6] *= y; m[10] *= z;
+ m[3] *= x; m[7] *= y; m[11] *= z;
+
+ if (fabs(x - y) < 1e-8 && fabs(x - z) < 1e-8)
+ mat->flags |= MAT_FLAG_UNIFORM_SCALE;
+ else
+ mat->flags |= MAT_FLAG_GENERAL_SCALE;
+
+ mat->flags |= (MAT_DIRTY_TYPE |
+ MAT_DIRTY_INVERSE |
+ MAT_DIRTY_DEPENDENTS);
+}
+
+/*
+ * Execute a glTranslate call
+ */
+void gl_Translatef( GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z )
+{
+ GLmatrix *mat = 0;
+ GLfloat *m;
+ GET_ACTIVE_MATRIX(ctx, mat, ctx->NewState, "glTranslate");
+ m = mat->m;
+ m[12] = m[0] * x + m[4] * y + m[8] * z + m[12];
+ m[13] = m[1] * x + m[5] * y + m[9] * z + m[13];
+ m[14] = m[2] * x + m[6] * y + m[10] * z + m[14];
+ m[15] = m[3] * x + m[7] * y + m[11] * z + m[15];
+
+ mat->flags |= (MAT_FLAG_TRANSLATION |
+ MAT_DIRTY_TYPE |
+ MAT_DIRTY_INVERSE |
+ MAT_DIRTY_DEPENDENTS);
+}
+
+
+/*
+ * Define a new viewport and reallocate auxillary buffers if the size of
+ * the window (color buffer) has changed.
+ */
+void gl_Viewport( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glViewport");
+
+ if (width<0 || height<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glViewport" );
+ return;
+ }
+
+ if (MESA_VERBOSE & VERBOSE_API)
+ fprintf(stderr, "glViewport %d %d %d %d\n", x, y, width, height);
+
+ /* clamp width, and height to implementation dependent range */
+ width = CLAMP( width, 1, MAX_WIDTH );
+ height = CLAMP( height, 1, MAX_HEIGHT );
+
+ /* Save viewport */
+ ctx->Viewport.X = x;
+ ctx->Viewport.Width = width;
+ ctx->Viewport.Y = y;
+ ctx->Viewport.Height = height;
+
+ /* compute scale and bias values */
+ ctx->Viewport.WindowMap.m[MAT_SX] = (GLfloat) width / 2.0F;
+ ctx->Viewport.WindowMap.m[MAT_TX] = ctx->Viewport.WindowMap.m[MAT_SX] + x;
+ ctx->Viewport.WindowMap.m[MAT_SY] = (GLfloat) height / 2.0F;
+ ctx->Viewport.WindowMap.m[MAT_TY] = ctx->Viewport.WindowMap.m[MAT_SY] + y;
+
+ ctx->ModelProjectWinMatrixUptodate = GL_FALSE;
+ ctx->NewState |= NEW_VIEWPORT;
+
+ /* Check if window/buffer has been resized and if so, reallocate the
+ * ancillary buffers.
+ */
+ gl_ResizeBuffersMESA(ctx);
+
+
+ ctx->RasterMask &= WINCLIP_BIT;
+
+ if ( ctx->Viewport.X<0
+ || ctx->Viewport.X + ctx->Viewport.Width > ctx->Buffer->Width
+ || ctx->Viewport.Y<0
+ || ctx->Viewport.Y + ctx->Viewport.Height > ctx->Buffer->Height) {
+ ctx->RasterMask |= WINCLIP_BIT;
+ }
+
+
+ if (ctx->Driver.Viewport) {
+ (*ctx->Driver.Viewport)( ctx, x, y, width, height );
+ }
+}
+
+
+
+void gl_DepthRange( GLcontext *ctx, GLclampd nearval, GLclampd farval )
+{
+ /*
+ * nearval - specifies mapping of the near clipping plane to window
+ * coordinates, default is 0
+ * farval - specifies mapping of the far clipping plane to window
+ * coordinates, default is 1
+ *
+ * After clipping and div by w, z coords are in -1.0 to 1.0,
+ * corresponding to near and far clipping planes. glDepthRange
+ * specifies a linear mapping of the normalized z coords in
+ * this range to window z coords.
+ */
+ GLfloat n, f;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDepthRange");
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ fprintf(stderr, "glDepthRange %f %f\n", nearval, farval);
+
+ n = (GLfloat) CLAMP( nearval, 0.0, 1.0 );
+ f = (GLfloat) CLAMP( farval, 0.0, 1.0 );
+
+ ctx->Viewport.Near = n;
+ ctx->Viewport.Far = f;
+ ctx->Viewport.WindowMap.m[MAT_SZ] = DEPTH_SCALE * ((f - n) / 2.0);
+ ctx->Viewport.WindowMap.m[MAT_TZ] = DEPTH_SCALE * ((f - n) / 2.0 + n);
+
+ ctx->ModelProjectWinMatrixUptodate = GL_FALSE;
+
+ if (ctx->Driver.DepthRange) {
+ (*ctx->Driver.DepthRange)( ctx, nearval, farval );
+ }
+}
+
+
+void gl_calculate_model_project_matrix( GLcontext *ctx )
+{
+ gl_matrix_mul( &ctx->ModelProjectMatrix,
+ &ctx->ProjectionMatrix,
+ &ctx->ModelView );
+
+ gl_matrix_analyze( &ctx->ModelProjectMatrix );
+}
+
+
+void gl_matrix_ctr( GLmatrix *m )
+{
+ m->inv = 0;
+ MEMCPY( m->m, Identity, sizeof(Identity));
+ m->type = MATRIX_IDENTITY;
+ m->flags = MAT_DIRTY_DEPENDENTS;
+}
+
+void gl_matrix_dtr( GLmatrix *m )
+{
+ if (m->inv != 0) {
+ free(m->inv);
+ m->inv = 0;
+ }
+}
+
+void gl_matrix_alloc_inv( GLmatrix *m )
+{
+ if (m->inv == 0) {
+ m->inv = (GLfloat *)malloc(16*sizeof(GLfloat));
+ MEMCPY( m->inv, Identity, 16 * sizeof(GLfloat) );
+ }
+}
+
+void gl_matrix_copy( GLmatrix *to, const GLmatrix *from )
+{
+ MEMCPY( to->m, from->m, sizeof(Identity));
+ to->flags = from->flags | MAT_DIRTY_DEPENDENTS;
+ to->type = from->type;
+
+ if (to->inv != 0) {
+ if (from->inv == 0) {
+ gl_matrix_invert( to );
+ } else {
+ MEMCPY(to->inv, from->inv, sizeof(GLfloat)*16);
+ }
+ }
+}
+
+void gl_matrix_mul( GLmatrix *dest, const GLmatrix *a, const GLmatrix *b )
+{
+ dest->flags = (a->flags |
+ b->flags |
+ MAT_DIRTY_TYPE |
+ MAT_DIRTY_INVERSE |
+ MAT_DIRTY_DEPENDENTS);
+
+ if (TEST_MAT_FLAGS(dest, MAT_FLAGS_3D))
+ matmul34( dest->m, a->m, b->m );
+ else
+ matmul4( dest->m, a->m, b->m );
+}
diff --git a/src/mesa/main/matrix.h b/src/mesa/main/matrix.h
new file mode 100644
index 0000000000..f89993e316
--- /dev/null
+++ b/src/mesa/main/matrix.h
@@ -0,0 +1,115 @@
+/* $Id: matrix.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef MATRIX_H
+#define MATRIX_H
+
+
+#include "GL/gl.h"
+#include "config.h"
+
+typedef struct {
+ GLfloat m[16];
+ GLfloat *inv; /* optional */
+ GLuint flags;
+ GLuint type;
+} GLmatrix;
+
+#ifdef VMS
+#define gl_calculate_model_project_matrix gl_calculate_model_project_matr
+#endif
+
+
+extern void gl_rotation_matrix( GLfloat angle, GLfloat x, GLfloat y, GLfloat z,
+ GLfloat m[] );
+
+
+
+extern void gl_Frustum( GLcontext *ctx,
+ GLdouble left, GLdouble right,
+ GLdouble bottom, GLdouble top,
+ GLdouble nearval, GLdouble farval );
+
+extern void gl_Ortho( GLcontext *ctx,
+ GLdouble left, GLdouble right,
+ GLdouble bottom, GLdouble top,
+ GLdouble nearval, GLdouble farval );
+
+extern void gl_PushMatrix( GLcontext *ctx );
+
+extern void gl_PopMatrix( GLcontext *ctx );
+
+extern void gl_LoadIdentity( GLcontext *ctx );
+
+extern void gl_LoadMatrixf( GLcontext *ctx, const GLfloat *m );
+
+extern void gl_MatrixMode( GLcontext *ctx, GLenum mode );
+
+extern void gl_MultMatrixf( GLcontext *ctx, const GLfloat *m );
+
+extern void gl_mat_mul_floats( GLmatrix *mat, const GLfloat *m, GLuint flags );
+extern void gl_mat_mul_mat( GLmatrix *mat, const GLmatrix *mat2 );
+
+extern void gl_Rotatef( GLcontext *ctx,
+ GLfloat angle, GLfloat x, GLfloat y, GLfloat z );
+
+extern void gl_Scalef( GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z );
+
+extern void gl_Translatef( GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z );
+
+extern void gl_Viewport( GLcontext *ctx,
+ GLint x, GLint y, GLsizei width, GLsizei height );
+
+extern void gl_DepthRange( GLcontext* ctx, GLclampd nearval, GLclampd farval );
+
+
+
+
+
+extern void gl_calculate_model_project_matrix( GLcontext *ctx );
+
+
+extern void gl_matrix_ctr( GLmatrix *m );
+
+extern void gl_matrix_dtr( GLmatrix *m );
+
+extern void gl_matrix_alloc_inv( GLmatrix *m );
+
+extern void gl_matrix_copy( GLmatrix *to, const GLmatrix *from );
+
+extern void gl_matrix_mul( GLmatrix *dest,
+ const GLmatrix *a,
+ const GLmatrix *b );
+
+extern void gl_matrix_analyze( GLmatrix *mat );
+
+
+
+#endif
diff --git a/src/mesa/main/mesa.conf b/src/mesa/main/mesa.conf
new file mode 100644
index 0000000000..d24ee6bd9f
--- /dev/null
+++ b/src/mesa/main/mesa.conf
@@ -0,0 +1,74 @@
+;; -*-lisp-*-
+;;
+;; KW: New mesa configuration file, syntax following a lisp style.
+;;
+;; valid syntax:
+;;
+;; (include filename)
+;; - not implemented
+;;
+;; (config-mesa version configs)
+;;
+;; where:
+;; version - is the version number of mesa for which the configuration
+;; was written. Future versions will use this to check for upwards
+;; compatibility. There is however no guarentee that old configurations
+;; will continue to be respected.
+;;
+;; configs - is a list of valid configuration lists, as specified by:
+;;
+;; (set-var variable value) - not implemented, use to augment env vars
+;; (set-env variable value) - not implemented, use to augment env vars
+;; (default-hint variable value)
+;; (disable-extension name)
+;;
+;; Mesa will look for an environment variable MESA_CONFIG, and try to
+;; execute that profile. Otherwise, it will fallback to the profile
+;; with the same name as the current mesa version. As default
+;; profiles should normally be empty or near-empty, this should be
+;; sufficiently powerful.
+;;
+
+
+;; Default profile - should normally be an empty list of
+;; configurations.
+;;
+(config-mesa mesa3.1beta1 ())
+
+
+
+;; Really is an empty config.
+;;
+(config-mesa empty ())
+
+
+
+;; Turn off some compliance for the sake of speed.
+;;
+(config-mesa quake2
+ (
+ ;; Quake2 likes this extension, but it really hurts performance if
+ ;; you don't also disable software fallbacks, below. (And do
+ ;; something else to stop the eye-space calculations too...)
+ ;;
+ (disable-extension GL_EXT_point_parameters)
+
+ ;; These hints are honoured only by the 3dfx driver - the X driver
+ ;; continues to function even if you specify hardware-only
+ ;; rendering.
+ ;;
+ ;(default-hint GL_ALLOW_DRAW_OBJ_HINT_PGI GL_TRUE) ; wishful thinking
+ ;(default-hint GL_ALLOW_DRAW_WIN_HINT_PGI GL_TRUE) ; allow 3dfx hardware...
+ ;(default-hint GL_ALLOW_DRAW_SPN_HINT_PGI GL_FALSE) ; no software spans
+ ;(default-hint GL_ALLOW_DRAW_MEM_HINT_PGI GL_FALSE) ; no softare pixels
+
+ ;; Lock in the hints specified above.
+ ;;
+ (disable-extension GL_PGI_misc_hints)))
+
+
+
+
+
+
+
diff --git a/src/mesa/main/pixel.c b/src/mesa/main/pixel.c
new file mode 100644
index 0000000000..316c357af1
--- /dev/null
+++ b/src/mesa/main/pixel.c
@@ -0,0 +1,774 @@
+/* $Id: pixel.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+/*
+ * glPixelStore, glPixelTransfer, glPixelMap, glPixelZoom, etc.
+ */
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "context.h"
+#include "macros.h"
+#include "pixel.h"
+#include "types.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+
+/**********************************************************************/
+/***** glPixelZoom *****/
+/**********************************************************************/
+
+
+
+void gl_PixelZoom( GLcontext *ctx, GLfloat xfactor, GLfloat yfactor )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPixelZoom");
+
+ ctx->Pixel.ZoomX = xfactor;
+ ctx->Pixel.ZoomY = yfactor;
+}
+
+
+
+/**********************************************************************/
+/***** glPixelStore *****/
+/**********************************************************************/
+
+
+void gl_PixelStorei( GLcontext *ctx, GLenum pname, GLint param )
+{
+ /* NOTE: this call can't be compiled into the display list */
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPixelStore");
+
+
+ switch (pname) {
+ case GL_PACK_SWAP_BYTES:
+ ctx->Pack.SwapBytes = param ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_PACK_LSB_FIRST:
+ ctx->Pack.LsbFirst = param ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_PACK_ROW_LENGTH:
+ if (param<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
+ }
+ else {
+ ctx->Pack.RowLength = param;
+ }
+ break;
+ case GL_PACK_IMAGE_HEIGHT:
+ if (param<0)
+ gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
+ else
+ ctx->Pack.ImageHeight = param;
+ break;
+ case GL_PACK_SKIP_PIXELS:
+ if (param<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
+ }
+ else {
+ ctx->Pack.SkipPixels = param;
+ }
+ break;
+ case GL_PACK_SKIP_ROWS:
+ if (param<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
+ }
+ else {
+ ctx->Pack.SkipRows = param;
+ }
+ break;
+ case GL_PACK_ALIGNMENT:
+ if (param==1 || param==2 || param==4 || param==8) {
+ ctx->Pack.Alignment = param;
+ }
+ else {
+ gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
+ }
+ break;
+ case GL_UNPACK_SWAP_BYTES:
+ ctx->Unpack.SwapBytes = param ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_UNPACK_LSB_FIRST:
+ ctx->Unpack.LsbFirst = param ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_UNPACK_ROW_LENGTH:
+ if (param<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
+ }
+ else {
+ ctx->Unpack.RowLength = param;
+ }
+ break;
+ case GL_UNPACK_IMAGE_HEIGHT:
+ if (param<0)
+ gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
+ else
+ ctx->Unpack.ImageHeight = param;
+ break;
+ case GL_UNPACK_SKIP_PIXELS:
+ if (param<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
+ }
+ else {
+ ctx->Unpack.SkipPixels = param;
+ }
+ break;
+ case GL_UNPACK_SKIP_ROWS:
+ if (param<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glPixelStore(param)" );
+ }
+ else {
+ ctx->Unpack.SkipRows = param;
+ }
+ break;
+ case GL_UNPACK_ALIGNMENT:
+ if (param==1 || param==2 || param==4 || param==8) {
+ ctx->Unpack.Alignment = param;
+ }
+ else {
+ gl_error( ctx, GL_INVALID_VALUE, "glPixelStore" );
+ }
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glPixelStore" );
+ }
+}
+
+
+
+
+
+/**********************************************************************/
+/***** glPixelMap *****/
+/**********************************************************************/
+
+
+
+void gl_PixelMapfv( GLcontext *ctx,
+ GLenum map, GLint mapsize, const GLfloat *values )
+{
+ GLint i;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPixelMapfv");
+
+
+ if (mapsize<0 || mapsize>MAX_PIXEL_MAP_TABLE) {
+ gl_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
+ return;
+ }
+
+ if (map>=GL_PIXEL_MAP_S_TO_S && map<=GL_PIXEL_MAP_I_TO_A) {
+ /* test that mapsize is a power of two */
+ GLuint p;
+ GLboolean ok = GL_FALSE;
+ for (p=1; p<=MAX_PIXEL_MAP_TABLE; p=p<<1) {
+ if ( (p&mapsize) == p ) {
+ ok = GL_TRUE;
+ break;
+ }
+ }
+ if (!ok) {
+ gl_error( ctx, GL_INVALID_VALUE, "glPixelMapfv(mapsize)" );
+ return;
+ }
+ }
+
+ switch (map) {
+ case GL_PIXEL_MAP_S_TO_S:
+ ctx->Pixel.MapStoSsize = mapsize;
+ for (i=0;i<mapsize;i++) {
+ ctx->Pixel.MapStoS[i] = (GLint) values[i];
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_I:
+ ctx->Pixel.MapItoIsize = mapsize;
+ for (i=0;i<mapsize;i++) {
+ ctx->Pixel.MapItoI[i] = (GLint) values[i];
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_R:
+ ctx->Pixel.MapItoRsize = mapsize;
+ for (i=0;i<mapsize;i++) {
+ GLfloat val = CLAMP( values[i], 0.0, 1.0 );
+ ctx->Pixel.MapItoR[i] = val;
+ ctx->Pixel.MapItoR8[i] = (GLint) (val * 255.0F);
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_G:
+ ctx->Pixel.MapItoGsize = mapsize;
+ for (i=0;i<mapsize;i++) {
+ GLfloat val = CLAMP( values[i], 0.0, 1.0 );
+ ctx->Pixel.MapItoG[i] = val;
+ ctx->Pixel.MapItoG8[i] = (GLint) (val * 255.0F);
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_B:
+ ctx->Pixel.MapItoBsize = mapsize;
+ for (i=0;i<mapsize;i++) {
+ GLfloat val = CLAMP( values[i], 0.0, 1.0 );
+ ctx->Pixel.MapItoB[i] = val;
+ ctx->Pixel.MapItoB8[i] = (GLint) (val * 255.0F);
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_A:
+ ctx->Pixel.MapItoAsize = mapsize;
+ for (i=0;i<mapsize;i++) {
+ GLfloat val = CLAMP( values[i], 0.0, 1.0 );
+ ctx->Pixel.MapItoA[i] = val;
+ ctx->Pixel.MapItoA8[i] = (GLint) (val * 255.0F);
+ }
+ break;
+ case GL_PIXEL_MAP_R_TO_R:
+ ctx->Pixel.MapRtoRsize = mapsize;
+ for (i=0;i<mapsize;i++) {
+ ctx->Pixel.MapRtoR[i] = CLAMP( values[i], 0.0, 1.0 );
+ }
+ break;
+ case GL_PIXEL_MAP_G_TO_G:
+ ctx->Pixel.MapGtoGsize = mapsize;
+ for (i=0;i<mapsize;i++) {
+ ctx->Pixel.MapGtoG[i] = CLAMP( values[i], 0.0, 1.0 );
+ }
+ break;
+ case GL_PIXEL_MAP_B_TO_B:
+ ctx->Pixel.MapBtoBsize = mapsize;
+ for (i=0;i<mapsize;i++) {
+ ctx->Pixel.MapBtoB[i] = CLAMP( values[i], 0.0, 1.0 );
+ }
+ break;
+ case GL_PIXEL_MAP_A_TO_A:
+ ctx->Pixel.MapAtoAsize = mapsize;
+ for (i=0;i<mapsize;i++) {
+ ctx->Pixel.MapAtoA[i] = CLAMP( values[i], 0.0, 1.0 );
+ }
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glPixelMapfv(map)" );
+ }
+}
+
+
+
+
+
+void gl_GetPixelMapfv( GLcontext *ctx, GLenum map, GLfloat *values )
+{
+ GLint i;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx, "glGetPixelMapfv");
+
+ switch (map) {
+ case GL_PIXEL_MAP_I_TO_I:
+ for (i=0;i<ctx->Pixel.MapItoIsize;i++) {
+ values[i] = (GLfloat) ctx->Pixel.MapItoI[i];
+ }
+ break;
+ case GL_PIXEL_MAP_S_TO_S:
+ for (i=0;i<ctx->Pixel.MapStoSsize;i++) {
+ values[i] = (GLfloat) ctx->Pixel.MapStoS[i];
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_R:
+ MEMCPY(values,ctx->Pixel.MapItoR,ctx->Pixel.MapItoRsize*sizeof(GLfloat));
+ break;
+ case GL_PIXEL_MAP_I_TO_G:
+ MEMCPY(values,ctx->Pixel.MapItoG,ctx->Pixel.MapItoGsize*sizeof(GLfloat));
+ break;
+ case GL_PIXEL_MAP_I_TO_B:
+ MEMCPY(values,ctx->Pixel.MapItoB,ctx->Pixel.MapItoBsize*sizeof(GLfloat));
+ break;
+ case GL_PIXEL_MAP_I_TO_A:
+ MEMCPY(values,ctx->Pixel.MapItoA,ctx->Pixel.MapItoAsize*sizeof(GLfloat));
+ break;
+ case GL_PIXEL_MAP_R_TO_R:
+ MEMCPY(values,ctx->Pixel.MapRtoR,ctx->Pixel.MapRtoRsize*sizeof(GLfloat));
+ break;
+ case GL_PIXEL_MAP_G_TO_G:
+ MEMCPY(values,ctx->Pixel.MapGtoG,ctx->Pixel.MapGtoGsize*sizeof(GLfloat));
+ break;
+ case GL_PIXEL_MAP_B_TO_B:
+ MEMCPY(values,ctx->Pixel.MapBtoB,ctx->Pixel.MapBtoBsize*sizeof(GLfloat));
+ break;
+ case GL_PIXEL_MAP_A_TO_A:
+ MEMCPY(values,ctx->Pixel.MapAtoA,ctx->Pixel.MapAtoAsize*sizeof(GLfloat));
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetPixelMapfv" );
+ }
+}
+
+
+void gl_GetPixelMapuiv( GLcontext *ctx, GLenum map, GLuint *values )
+{
+ GLint i;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx, "glGetPixelMapfv");
+
+ switch (map) {
+ case GL_PIXEL_MAP_I_TO_I:
+ MEMCPY(values, ctx->Pixel.MapItoI, ctx->Pixel.MapItoIsize*sizeof(GLint));
+ break;
+ case GL_PIXEL_MAP_S_TO_S:
+ MEMCPY(values, ctx->Pixel.MapStoS, ctx->Pixel.MapStoSsize*sizeof(GLint));
+ break;
+ case GL_PIXEL_MAP_I_TO_R:
+ for (i=0;i<ctx->Pixel.MapItoRsize;i++) {
+ values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoR[i] );
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_G:
+ for (i=0;i<ctx->Pixel.MapItoGsize;i++) {
+ values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoG[i] );
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_B:
+ for (i=0;i<ctx->Pixel.MapItoBsize;i++) {
+ values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoB[i] );
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_A:
+ for (i=0;i<ctx->Pixel.MapItoAsize;i++) {
+ values[i] = FLOAT_TO_UINT( ctx->Pixel.MapItoA[i] );
+ }
+ break;
+ case GL_PIXEL_MAP_R_TO_R:
+ for (i=0;i<ctx->Pixel.MapRtoRsize;i++) {
+ values[i] = FLOAT_TO_UINT( ctx->Pixel.MapRtoR[i] );
+ }
+ break;
+ case GL_PIXEL_MAP_G_TO_G:
+ for (i=0;i<ctx->Pixel.MapGtoGsize;i++) {
+ values[i] = FLOAT_TO_UINT( ctx->Pixel.MapGtoG[i] );
+ }
+ break;
+ case GL_PIXEL_MAP_B_TO_B:
+ for (i=0;i<ctx->Pixel.MapBtoBsize;i++) {
+ values[i] = FLOAT_TO_UINT( ctx->Pixel.MapBtoB[i] );
+ }
+ break;
+ case GL_PIXEL_MAP_A_TO_A:
+ for (i=0;i<ctx->Pixel.MapAtoAsize;i++) {
+ values[i] = FLOAT_TO_UINT( ctx->Pixel.MapAtoA[i] );
+ }
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetPixelMapfv" );
+ }
+}
+
+
+void gl_GetPixelMapusv( GLcontext *ctx, GLenum map, GLushort *values )
+{
+ GLint i;
+
+ ASSERT_OUTSIDE_BEGIN_END(ctx, "glGetPixelMapfv");
+
+ switch (map) {
+ case GL_PIXEL_MAP_I_TO_I:
+ for (i=0;i<ctx->Pixel.MapItoIsize;i++) {
+ values[i] = (GLushort) ctx->Pixel.MapItoI[i];
+ }
+ break;
+ case GL_PIXEL_MAP_S_TO_S:
+ for (i=0;i<ctx->Pixel.MapStoSsize;i++) {
+ values[i] = (GLushort) ctx->Pixel.MapStoS[i];
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_R:
+ for (i=0;i<ctx->Pixel.MapItoRsize;i++) {
+ values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapItoR[i] );
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_G:
+ for (i=0;i<ctx->Pixel.MapItoGsize;i++) {
+ values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapItoG[i] );
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_B:
+ for (i=0;i<ctx->Pixel.MapItoBsize;i++) {
+ values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapItoB[i] );
+ }
+ break;
+ case GL_PIXEL_MAP_I_TO_A:
+ for (i=0;i<ctx->Pixel.MapItoAsize;i++) {
+ values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapItoA[i] );
+ }
+ break;
+ case GL_PIXEL_MAP_R_TO_R:
+ for (i=0;i<ctx->Pixel.MapRtoRsize;i++) {
+ values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapRtoR[i] );
+ }
+ break;
+ case GL_PIXEL_MAP_G_TO_G:
+ for (i=0;i<ctx->Pixel.MapGtoGsize;i++) {
+ values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapGtoG[i] );
+ }
+ break;
+ case GL_PIXEL_MAP_B_TO_B:
+ for (i=0;i<ctx->Pixel.MapBtoBsize;i++) {
+ values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapBtoB[i] );
+ }
+ break;
+ case GL_PIXEL_MAP_A_TO_A:
+ for (i=0;i<ctx->Pixel.MapAtoAsize;i++) {
+ values[i] = FLOAT_TO_USHORT( ctx->Pixel.MapAtoA[i] );
+ }
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetPixelMapfv" );
+ }
+}
+
+
+
+/**********************************************************************/
+/***** glPixelTransfer *****/
+/**********************************************************************/
+
+
+/*
+ * Implements glPixelTransfer[fi] whether called immediately or from a
+ * display list.
+ */
+void gl_PixelTransferf( GLcontext *ctx, GLenum pname, GLfloat param )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPixelTransfer");
+
+
+ switch (pname) {
+ case GL_MAP_COLOR:
+ ctx->Pixel.MapColorFlag = param ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_MAP_STENCIL:
+ ctx->Pixel.MapStencilFlag = param ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_INDEX_SHIFT:
+ ctx->Pixel.IndexShift = (GLint) param;
+ break;
+ case GL_INDEX_OFFSET:
+ ctx->Pixel.IndexOffset = (GLint) param;
+ break;
+ case GL_RED_SCALE:
+ ctx->Pixel.RedScale = param;
+ break;
+ case GL_RED_BIAS:
+ ctx->Pixel.RedBias = param;
+ break;
+ case GL_GREEN_SCALE:
+ ctx->Pixel.GreenScale = param;
+ break;
+ case GL_GREEN_BIAS:
+ ctx->Pixel.GreenBias = param;
+ break;
+ case GL_BLUE_SCALE:
+ ctx->Pixel.BlueScale = param;
+ break;
+ case GL_BLUE_BIAS:
+ ctx->Pixel.BlueBias = param;
+ break;
+ case GL_ALPHA_SCALE:
+ ctx->Pixel.AlphaScale = param;
+ break;
+ case GL_ALPHA_BIAS:
+ ctx->Pixel.AlphaBias = param;
+ break;
+ case GL_DEPTH_SCALE:
+ ctx->Pixel.DepthScale = param;
+ break;
+ case GL_DEPTH_BIAS:
+ ctx->Pixel.DepthBias = param;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glPixelTransfer(pname)" );
+ return;
+ }
+
+ if (ctx->Pixel.RedScale!=1.0F || ctx->Pixel.RedBias!=0.0F ||
+ ctx->Pixel.GreenScale!=1.0F || ctx->Pixel.GreenBias!=0.0F ||
+ ctx->Pixel.BlueScale!=1.0F || ctx->Pixel.BlueBias!=0.0F ||
+ ctx->Pixel.AlphaScale!=1.0F || ctx->Pixel.AlphaBias!=0.0F) {
+ ctx->Pixel.ScaleOrBiasRGBA = GL_TRUE;
+ }
+ else {
+ ctx->Pixel.ScaleOrBiasRGBA = GL_FALSE;
+ }
+}
+
+
+
+
+/*
+ * Pixel processing functions
+ */
+
+
+/*
+ * Apply scale and bias factors to an array of RGBA pixels.
+ */
+void gl_scale_and_bias_color( const GLcontext *ctx, GLuint n,
+ GLfloat red[], GLfloat green[],
+ GLfloat blue[], GLfloat alpha[] )
+{
+ GLuint i;
+ for (i=0;i<n;i++) {
+ GLfloat r = red[i] * ctx->Pixel.RedScale + ctx->Pixel.RedBias;
+ GLfloat g = green[i] * ctx->Pixel.GreenScale + ctx->Pixel.GreenBias;
+ GLfloat b = blue[i] * ctx->Pixel.BlueScale + ctx->Pixel.BlueBias;
+ GLfloat a = alpha[i] * ctx->Pixel.AlphaScale + ctx->Pixel.AlphaBias;
+ red[i] = CLAMP( r, 0.0F, 1.0F );
+ green[i] = CLAMP( g, 0.0F, 1.0F );
+ blue[i] = CLAMP( b, 0.0F, 1.0F );
+ alpha[i] = CLAMP( a, 0.0F, 1.0F );
+ }
+}
+
+
+/*
+ * Apply scale and bias factors to an array of RGBA pixels.
+ */
+void gl_scale_and_bias_rgba( const GLcontext *ctx, GLuint n, GLubyte rgba[][4] )
+{
+ GLfloat rbias = ctx->Pixel.RedBias * 255.0F;
+ GLfloat gbias = ctx->Pixel.GreenBias * 255.0F;
+ GLfloat bbias = ctx->Pixel.BlueBias * 255.0F;
+ GLfloat abias = ctx->Pixel.AlphaBias * 255.0F;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ GLint r = (GLint) (rgba[i][RCOMP] * ctx->Pixel.RedScale + rbias);
+ GLint g = (GLint) (rgba[i][GCOMP] * ctx->Pixel.GreenScale + gbias);
+ GLint b = (GLint) (rgba[i][BCOMP] * ctx->Pixel.BlueScale + bbias);
+ GLint a = (GLint) (rgba[i][ACOMP] * ctx->Pixel.AlphaScale + abias);
+ rgba[i][RCOMP] = CLAMP( r, 0, 255 );
+ rgba[i][GCOMP] = CLAMP( g, 0, 255 );
+ rgba[i][BCOMP] = CLAMP( b, 0, 255 );
+ rgba[i][ACOMP] = CLAMP( a, 0, 255 );
+ }
+}
+
+
+/*
+ * Apply pixel mapping to an array of RGBA pixels.
+ */
+void gl_map_rgba( const GLcontext *ctx, GLuint n, GLubyte rgba[][4] )
+{
+ GLfloat rscale = (ctx->Pixel.MapRtoRsize - 1) / 255.0F;
+ GLfloat gscale = (ctx->Pixel.MapGtoGsize - 1) / 255.0F;
+ GLfloat bscale = (ctx->Pixel.MapBtoBsize - 1) / 255.0F;
+ GLfloat ascale = (ctx->Pixel.MapAtoAsize - 1) / 255.0F;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ GLint ir = (GLint) (rgba[i][RCOMP] * rscale);
+ GLint ig = (GLint) (rgba[i][GCOMP] * gscale);
+ GLint ib = (GLint) (rgba[i][BCOMP] * bscale);
+ GLint ia = (GLint) (rgba[i][ACOMP] * ascale);
+ rgba[i][RCOMP] = (GLint) (ctx->Pixel.MapRtoR[ir] * 255.0F);
+ rgba[i][GCOMP] = (GLint) (ctx->Pixel.MapGtoG[ig] * 255.0F);
+ rgba[i][BCOMP] = (GLint) (ctx->Pixel.MapBtoB[ib] * 255.0F);
+ rgba[i][ACOMP] = (GLint) (ctx->Pixel.MapAtoA[ia] * 255.0F);
+ }
+}
+
+
+/*
+ * Apply pixel mapping to an array of RGBA pixels.
+ */
+void gl_map_color( const GLcontext *ctx, GLuint n,
+ GLfloat red[], GLfloat green[],
+ GLfloat blue[], GLfloat alpha[] )
+{
+ GLfloat rscale = ctx->Pixel.MapRtoRsize-1;
+ GLfloat gscale = ctx->Pixel.MapGtoGsize-1;
+ GLfloat bscale = ctx->Pixel.MapBtoBsize-1;
+ GLfloat ascale = ctx->Pixel.MapAtoAsize-1;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ red[i] = ctx->Pixel.MapRtoR[ (GLint) (red[i] * rscale) ];
+ green[i] = ctx->Pixel.MapGtoG[ (GLint) (green[i] * gscale) ];
+ blue[i] = ctx->Pixel.MapBtoB[ (GLint) (blue[i] * bscale) ];
+ alpha[i] = ctx->Pixel.MapAtoA[ (GLint) (alpha[i] * ascale) ];
+ }
+}
+
+
+
+/*
+ * Apply color index shift and offset to an array of pixels.
+ */
+void gl_shift_and_offset_ci( const GLcontext *ctx, GLuint n, GLuint indexes[] )
+{
+ GLint shift = ctx->Pixel.IndexShift;
+ GLint offset = ctx->Pixel.IndexOffset;
+ GLuint i;
+ if (shift > 0) {
+ for (i=0;i<n;i++) {
+ indexes[i] = (indexes[i] << shift) + offset;
+ }
+ }
+ else if (shift < 0) {
+ shift = -shift;
+ for (i=0;i<n;i++) {
+ indexes[i] = (indexes[i] >> shift) + offset;
+ }
+ }
+ else {
+ for (i=0;i<n;i++) {
+ indexes[i] = indexes[i] + offset;
+ }
+ }
+}
+
+
+/*
+ * Apply color index mapping to color indexes.
+ */
+void gl_map_ci( const GLcontext *ctx, GLuint n, GLuint index[] )
+{
+ GLuint mask = ctx->Pixel.MapItoIsize - 1;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ index[i] = ctx->Pixel.MapItoI[ index[i] & mask ];
+ }
+}
+
+
+/*
+ * Map color indexes to rgb values.
+ */
+void gl_map_ci_to_rgba( const GLcontext *ctx, GLuint n, const GLuint index[],
+ GLubyte rgba[][4] )
+{
+ GLuint rmask = ctx->Pixel.MapItoRsize - 1;
+ GLuint gmask = ctx->Pixel.MapItoGsize - 1;
+ GLuint bmask = ctx->Pixel.MapItoBsize - 1;
+ GLuint amask = ctx->Pixel.MapItoAsize - 1;
+ const GLubyte *rMap = ctx->Pixel.MapItoR8;
+ const GLubyte *gMap = ctx->Pixel.MapItoG8;
+ const GLubyte *bMap = ctx->Pixel.MapItoB8;
+ const GLubyte *aMap = ctx->Pixel.MapItoA8;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ rgba[i][RCOMP] = rMap[index[i] & rmask];
+ rgba[i][GCOMP] = gMap[index[i] & gmask];
+ rgba[i][BCOMP] = bMap[index[i] & bmask];
+ rgba[i][ACOMP] = aMap[index[i] & amask];
+ }
+}
+
+
+/*
+ * Map 8-bit color indexes to rgb values.
+ */
+void gl_map_ci8_to_rgba( const GLcontext *ctx, GLuint n, const GLubyte index[],
+ GLubyte rgba[][4] )
+{
+ GLuint rmask = ctx->Pixel.MapItoRsize - 1;
+ GLuint gmask = ctx->Pixel.MapItoGsize - 1;
+ GLuint bmask = ctx->Pixel.MapItoBsize - 1;
+ GLuint amask = ctx->Pixel.MapItoAsize - 1;
+ const GLubyte *rMap = ctx->Pixel.MapItoR8;
+ const GLubyte *gMap = ctx->Pixel.MapItoG8;
+ const GLubyte *bMap = ctx->Pixel.MapItoB8;
+ const GLubyte *aMap = ctx->Pixel.MapItoA8;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ rgba[i][RCOMP] = rMap[index[i] & rmask];
+ rgba[i][GCOMP] = gMap[index[i] & gmask];
+ rgba[i][BCOMP] = bMap[index[i] & bmask];
+ rgba[i][ACOMP] = aMap[index[i] & amask];
+ }
+}
+
+
+void gl_map_ci_to_color( const GLcontext *ctx, GLuint n, const GLuint index[],
+ GLfloat r[], GLfloat g[],
+ GLfloat b[], GLfloat a[] )
+{
+ GLuint rmask = ctx->Pixel.MapItoRsize - 1;
+ GLuint gmask = ctx->Pixel.MapItoGsize - 1;
+ GLuint bmask = ctx->Pixel.MapItoBsize - 1;
+ GLuint amask = ctx->Pixel.MapItoAsize - 1;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ r[i] = ctx->Pixel.MapItoR[index[i] & rmask];
+ g[i] = ctx->Pixel.MapItoG[index[i] & gmask];
+ b[i] = ctx->Pixel.MapItoB[index[i] & bmask];
+ a[i] = ctx->Pixel.MapItoA[index[i] & amask];
+ }
+}
+
+
+
+void gl_shift_and_offset_stencil( const GLcontext *ctx, GLuint n,
+ GLstencil stencil[] )
+{
+ GLuint i;
+ GLint shift = ctx->Pixel.IndexShift;
+ GLint offset = ctx->Pixel.IndexOffset;
+ if (shift > 0) {
+ for (i=0;i<n;i++) {
+ stencil[i] = (stencil[i] << shift) + offset;
+ }
+ }
+ else if (shift < 0) {
+ shift = -shift;
+ for (i=0;i<n;i++) {
+ stencil[i] = (stencil[i] >> shift) + offset;
+ }
+ }
+ else {
+ for (i=0;i<n;i++) {
+ stencil[i] = stencil[i] + offset;
+ }
+ }
+
+}
+
+
+
+void gl_map_stencil( const GLcontext *ctx, GLuint n, GLstencil stencil[] )
+{
+ GLuint mask = ctx->Pixel.MapStoSsize - 1;
+ GLuint i;
+ for (i=0;i<n;i++) {
+ stencil[i] = ctx->Pixel.MapStoS[ stencil[i] & mask ];
+ }
+}
+
diff --git a/src/mesa/main/pixel.h b/src/mesa/main/pixel.h
new file mode 100644
index 0000000000..c592d06853
--- /dev/null
+++ b/src/mesa/main/pixel.h
@@ -0,0 +1,111 @@
+/* $Id: pixel.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef PIXEL_H
+#define PIXEL_H
+
+
+#include "types.h"
+
+
+/*
+ * API functions
+ */
+
+
+extern void gl_GetPixelMapfv( GLcontext *ctx, GLenum map, GLfloat *values );
+
+extern void gl_GetPixelMapuiv( GLcontext *ctx, GLenum map, GLuint *values );
+
+extern void gl_GetPixelMapusv( GLcontext *ctx, GLenum map, GLushort *values );
+
+
+extern void gl_PixelMapfv( GLcontext *ctx,
+ GLenum map, GLint mapsize, const GLfloat *values );
+
+extern void gl_PixelStorei( GLcontext *ctx, GLenum pname, GLint param );
+
+extern void gl_PixelTransferf( GLcontext *ctx, GLenum pname, GLfloat param );
+
+extern void gl_PixelZoom( GLcontext *ctx, GLfloat xfactor, GLfloat yfactor );
+
+
+/*
+ * Pixel processing functions
+ */
+
+extern void gl_scale_and_bias_color( const GLcontext *ctx, GLuint n,
+ GLfloat red[], GLfloat green[],
+ GLfloat blue[], GLfloat alpha[] );
+
+
+extern void gl_scale_and_bias_rgba( const GLcontext *ctx, GLuint n,
+ GLubyte rgba[][4] );
+
+
+extern void gl_map_rgba( const GLcontext *ctx, GLuint n, GLubyte rgba[][4] );
+
+
+extern void gl_map_color( const GLcontext *ctx, GLuint n,
+ GLfloat red[], GLfloat green[],
+ GLfloat blue[], GLfloat alpha[] );
+
+
+extern void gl_shift_and_offset_ci( const GLcontext *ctx, GLuint n,
+ GLuint indexes[] );
+
+
+extern void gl_map_ci( const GLcontext *ctx, GLuint n, GLuint index[] );
+
+
+extern void gl_map_ci_to_rgba( const GLcontext *ctx,
+ GLuint n, const GLuint index[],
+ GLubyte rgba[][4] );
+
+
+extern void gl_map_ci8_to_rgba( const GLcontext *ctx,
+ GLuint n, const GLubyte index[],
+ GLubyte rgba[][4] );
+
+
+extern void gl_map_ci_to_color( const GLcontext *ctx,
+ GLuint n, const GLuint index[],
+ GLfloat r[], GLfloat g[],
+ GLfloat b[], GLfloat a[] );
+
+
+extern void gl_shift_and_offset_stencil( const GLcontext *ctx, GLuint n,
+ GLstencil indexes[] );
+
+
+extern void gl_map_stencil( const GLcontext *ctx, GLuint n, GLstencil index[] );
+
+
+#endif
diff --git a/src/mesa/main/points.c b/src/mesa/main/points.c
new file mode 100644
index 0000000000..928acc8891
--- /dev/null
+++ b/src/mesa/main/points.c
@@ -0,0 +1,1344 @@
+/* $Id: points.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include "context.h"
+#include "feedback.h"
+#include "macros.h"
+#include "pb.h"
+#include "span.h"
+#include "texstate.h"
+#include "types.h"
+#include "vb.h"
+#include "mmath.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+
+void gl_PointSize( GLcontext *ctx, GLfloat size )
+{
+ if (size<=0.0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glPointSize" );
+ return;
+ }
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPointSize");
+
+ if (ctx->Point.Size != size) {
+ ctx->Point.Size = size;
+ ctx->TriangleCaps &= DD_POINT_SIZE;
+ if (size != 1.0) ctx->TriangleCaps |= DD_POINT_SIZE;
+ ctx->NewState |= NEW_RASTER_OPS;
+ }
+}
+
+
+
+void gl_PointParameterfvEXT( GLcontext *ctx, GLenum pname,
+ const GLfloat *params)
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPointParameterfvEXT");
+ if(pname==GL_DISTANCE_ATTENUATION_EXT) {
+ GLboolean tmp = ctx->Point.Attenuated;
+ COPY_3V(ctx->Point.Params,params);
+ ctx->Point.Attenuated = (params[0] != 1.0 ||
+ params[1] != 0.0 ||
+ params[2] != 0.0);
+
+ if (tmp != ctx->Point.Attenuated) {
+ ctx->Enabled ^= ENABLE_POINT_ATTEN;
+ ctx->TriangleCaps ^= DD_POINT_ATTEN;
+ ctx->NewState |= NEW_RASTER_OPS;
+ }
+ } else {
+ if (*params<0.0 ) {
+ gl_error( ctx, GL_INVALID_VALUE, "glPointParameterfvEXT" );
+ return;
+ }
+ switch (pname) {
+ case GL_POINT_SIZE_MIN_EXT:
+ ctx->Point.MinSize=*params;
+ break;
+ case GL_POINT_SIZE_MAX_EXT:
+ ctx->Point.MaxSize=*params;
+ break;
+ case GL_POINT_FADE_THRESHOLD_SIZE_EXT:
+ ctx->Point.Threshold=*params;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glPointParameterfvEXT" );
+ return;
+ }
+ }
+ ctx->NewState |= NEW_RASTER_OPS;
+}
+
+
+/**********************************************************************/
+/***** Rasterization *****/
+/**********************************************************************/
+
+
+/*
+ * There are 3 pairs (RGBA, CI) of point rendering functions:
+ * 1. simple: size=1 and no special rasterization functions (fastest)
+ * 2. size1: size=1 and any rasterization functions
+ * 3. general: any size and rasterization functions (slowest)
+ *
+ * All point rendering functions take the same two arguments: first and
+ * last which specify that the points specified by VB[first] through
+ * VB[last] are to be rendered.
+ */
+
+
+
+/*
+ * Put points in feedback buffer.
+ */
+static void feedback_points( GLcontext *ctx, GLuint first, GLuint last )
+{
+ struct vertex_buffer *VB = ctx->VB;
+ GLuint texUnit = ctx->Texture.CurrentTransformUnit;
+ GLuint tsize = VB->TexCoordPtr[texUnit]->size;
+ GLuint i;
+ GLfloat texcoord[4];
+
+ ASSIGN_4V(texcoord, 0,0,0,1);
+
+ for (i=first;i<=last;i++) {
+ if (VB->ClipMask[i]==0) {
+ GLfloat x, y, z, w, invq;
+ GLfloat color[4];
+ x = VB->Win.data[i][0];
+ y = VB->Win.data[i][1];
+ z = VB->Win.data[i][2] / DEPTH_SCALE;
+ w = VB->ClipPtr->data[i][3];
+
+ if (tsize == 4) {
+ invq = 1.0F / VB->TexCoordPtr[texUnit]->data[i][3];
+ texcoord[0] = VB->TexCoordPtr[texUnit]->data[i][0] * invq;
+ texcoord[1] = VB->TexCoordPtr[texUnit]->data[i][1] * invq;
+ texcoord[2] = VB->TexCoordPtr[texUnit]->data[i][2] * invq;
+ texcoord[3] = VB->TexCoordPtr[texUnit]->data[i][3];
+ } else {
+ COPY_SZ_4V(texcoord, tsize, VB->TexCoordPtr[texUnit]->data[i]);
+ }
+
+ FEEDBACK_TOKEN( ctx, (GLfloat) (GLint) GL_POINT_TOKEN );
+
+ UBYTE_RGBA_TO_FLOAT_RGBA( color, VB->ColorPtr->data[i] );
+
+ gl_feedback_vertex( ctx, x, y, z, w, color,
+ (GLfloat) VB->IndexPtr->data[i], texcoord
+);
+ }
+ }
+}
+
+
+
+/*
+ * Put points in selection buffer.
+ */
+static void select_points( GLcontext *ctx, GLuint first, GLuint last )
+{
+ struct vertex_buffer *VB = ctx->VB;
+ GLuint i;
+
+ for (i=first;i<=last;i++) {
+ if (VB->ClipMask[i]==0) {
+ gl_update_hitflag( ctx, VB->Win.data[i][2] / DEPTH_SCALE );
+ }
+ }
+}
+
+
+/*
+ * CI points with size == 1.0
+ */
+void size1_ci_points( GLcontext *ctx, GLuint first, GLuint last )
+{
+ struct vertex_buffer *VB = ctx->VB;
+ struct pixel_buffer *PB = ctx->PB;
+ GLfloat *win;
+ GLint *pbx = PB->x, *pby = PB->y;
+ GLdepth *pbz = PB->z;
+ GLuint *pbi = PB->i;
+ GLuint pbcount = PB->count;
+ GLuint i;
+
+ win = &VB->Win.data[first][0];
+ for (i=first;i<=last;i++) {
+ if (VB->ClipMask[i]==0) {
+ pbx[pbcount] = (GLint) win[0];
+ pby[pbcount] = (GLint) win[1];
+ pbz[pbcount] = (GLint) (win[2] + ctx->PointZoffset);
+ pbi[pbcount] = VB->IndexPtr->data[i];
+ pbcount++;
+ }
+ win += 3;
+ }
+ PB->count = pbcount;
+ PB_CHECK_FLUSH(ctx, PB);
+}
+
+
+
+/*
+ * RGBA points with size == 1.0
+ */
+static void size1_rgba_points( GLcontext *ctx, GLuint first, GLuint last )
+{
+ struct vertex_buffer *VB = ctx->VB;
+ struct pixel_buffer *PB = ctx->PB;
+ GLuint i;
+
+ for (i=first;i<=last;i++) {
+ if (VB->ClipMask[i]==0) {
+ GLint x, y, z;
+ GLint red, green, blue, alpha;
+
+ x = (GLint) VB->Win.data[i][0];
+ y = (GLint) VB->Win.data[i][1];
+ z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset);
+
+ red = VB->ColorPtr->data[i][0];
+ green = VB->ColorPtr->data[i][1];
+ blue = VB->ColorPtr->data[i][2];
+ alpha = VB->ColorPtr->data[i][3];
+
+ PB_WRITE_RGBA_PIXEL( PB, x, y, z, red, green, blue, alpha );
+ }
+ }
+ PB_CHECK_FLUSH(ctx,PB);
+}
+
+
+
+/*
+ * General CI points.
+ */
+static void general_ci_points( GLcontext *ctx, GLuint first, GLuint last )
+{
+ struct vertex_buffer *VB = ctx->VB;
+ struct pixel_buffer *PB = ctx->PB;
+ GLuint i;
+ GLint isize = (GLint) (CLAMP(ctx->Point.Size,MIN_POINT_SIZE,MAX_POINT_SIZE) + 0.5F);
+ GLint radius = isize >> 1;
+
+ for (i=first;i<=last;i++) {
+ if (VB->ClipMask[i]==0) {
+ GLint x, y, z;
+ GLint x0, x1, y0, y1;
+ GLint ix, iy;
+
+ x = (GLint) VB->Win.data[i][0];
+ y = (GLint) VB->Win.data[i][1];
+ z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset);
+
+ if (isize & 1) {
+ /* odd size */
+ x0 = x - radius;
+ x1 = x + radius;
+ y0 = y - radius;
+ y1 = y + radius;
+ }
+ else {
+ /* even size */
+ x0 = (GLint) (x + 1.5F) - radius;
+ x1 = x0 + isize - 1;
+ y0 = (GLint) (y + 1.5F) - radius;
+ y1 = y0 + isize - 1;
+ }
+
+ PB_SET_INDEX( ctx, PB, VB->IndexPtr->data[i] );
+
+ for (iy=y0;iy<=y1;iy++) {
+ for (ix=x0;ix<=x1;ix++) {
+ PB_WRITE_PIXEL( PB, ix, iy, z );
+ }
+ }
+ PB_CHECK_FLUSH(ctx,PB);
+ }
+ }
+}
+
+
+/*
+ * General RGBA points.
+ */
+static void general_rgba_points( GLcontext *ctx, GLuint first, GLuint last )
+{
+ struct vertex_buffer *VB = ctx->VB;
+ struct pixel_buffer *PB = ctx->PB;
+ GLuint i;
+ GLint isize = (GLint) (CLAMP(ctx->Point.Size,MIN_POINT_SIZE,MAX_POINT_SIZE) + 0.5F);
+ GLint radius = isize >> 1;
+
+ for (i=first;i<=last;i++) {
+ if (VB->ClipMask[i]==0) {
+ GLint x, y, z;
+ GLint x0, x1, y0, y1;
+ GLint ix, iy;
+
+ x = (GLint) VB->Win.data[i][0];
+ y = (GLint) VB->Win.data[i][1];
+ z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset);
+
+ if (isize & 1) {
+ /* odd size */
+ x0 = x - radius;
+ x1 = x + radius;
+ y0 = y - radius;
+ y1 = y + radius;
+ }
+ else {
+ /* even size */
+ x0 = (GLint) (x + 1.5F) - radius;
+ x1 = x0 + isize - 1;
+ y0 = (GLint) (y + 1.5F) - radius;
+ y1 = y0 + isize - 1;
+ }
+
+ PB_SET_COLOR( ctx, PB,
+ VB->ColorPtr->data[i][0],
+ VB->ColorPtr->data[i][1],
+ VB->ColorPtr->data[i][2],
+ VB->ColorPtr->data[i][3] );
+
+ for (iy=y0;iy<=y1;iy++) {
+ for (ix=x0;ix<=x1;ix++) {
+ PB_WRITE_PIXEL( PB, ix, iy, z );
+ }
+ }
+ PB_CHECK_FLUSH(ctx,PB);
+ }
+ }
+}
+
+
+
+
+/*
+ * Textured RGBA points.
+ */
+static void textured_rgba_points( GLcontext *ctx, GLuint first, GLuint last )
+{
+ struct vertex_buffer *VB = ctx->VB;
+ struct pixel_buffer *PB = ctx->PB;
+ GLuint i;
+
+ for (i=first;i<=last;i++) {
+ if (VB->ClipMask[i]==0) {
+ GLint x, y, z;
+ GLint x0, x1, y0, y1;
+ GLint ix, iy;
+ GLint isize, radius;
+ GLint red, green, blue, alpha;
+ GLfloat s, t, u;
+
+ x = (GLint) VB->Win.data[i][0];
+ y = (GLint) VB->Win.data[i][1];
+ z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset);
+
+ isize = (GLint)
+ (CLAMP(ctx->Point.Size,MIN_POINT_SIZE,MAX_POINT_SIZE) + 0.5F);
+ if (isize<1) {
+ isize = 1;
+ }
+ radius = isize >> 1;
+
+ if (isize & 1) {
+ /* odd size */
+ x0 = x - radius;
+ x1 = x + radius;
+ y0 = y - radius;
+ y1 = y + radius;
+ }
+ else {
+ /* even size */
+ x0 = (GLint) (x + 1.5F) - radius;
+ x1 = x0 + isize - 1;
+ y0 = (GLint) (y + 1.5F) - radius;
+ y1 = y0 + isize - 1;
+ }
+
+ red = VB->ColorPtr->data[i][0];
+ green = VB->ColorPtr->data[i][1];
+ blue = VB->ColorPtr->data[i][2];
+ alpha = VB->ColorPtr->data[i][3];
+
+ switch (VB->TexCoordPtr[0]->size) {
+ case 4:
+ s = VB->TexCoordPtr[0]->data[i][0]/VB->TexCoordPtr[0]->data[i][3];
+ t = VB->TexCoordPtr[0]->data[i][1]/VB->TexCoordPtr[0]->data[i][3];
+ u = VB->TexCoordPtr[0]->data[i][2]/VB->TexCoordPtr[0]->data[i][3];
+ break;
+ case 3:
+ s = VB->TexCoordPtr[0]->data[i][0];
+ t = VB->TexCoordPtr[0]->data[i][1];
+ u = VB->TexCoordPtr[0]->data[i][2];
+ break;
+ case 2:
+ s = VB->TexCoordPtr[0]->data[i][0];
+ t = VB->TexCoordPtr[0]->data[i][1];
+ u = 0.0;
+ break;
+ case 1:
+ s = VB->TexCoordPtr[0]->data[i][0];
+ t = 0.0;
+ u = 0.0;
+ break;
+ }
+
+
+
+
+/* don't think this is needed
+ PB_SET_COLOR( red, green, blue, alpha );
+*/
+
+ for (iy=y0;iy<=y1;iy++) {
+ for (ix=x0;ix<=x1;ix++) {
+ PB_WRITE_TEX_PIXEL( PB, ix, iy, z, red, green, blue, alpha, s, t, u );
+ }
+ }
+ PB_CHECK_FLUSH(ctx,PB);
+ }
+ }
+}
+
+
+/*
+ * Multitextured RGBA points.
+ */
+static void multitextured_rgba_points( GLcontext *ctx, GLuint first, GLuint last )
+{
+ struct vertex_buffer *VB = ctx->VB;
+ struct pixel_buffer *PB = ctx->PB;
+ GLuint i;
+
+ for (i=first;i<=last;i++) {
+ if (VB->ClipMask[i]==0) {
+ GLint x, y, z;
+ GLint x0, x1, y0, y1;
+ GLint ix, iy;
+ GLint isize, radius;
+ GLint red, green, blue, alpha;
+ GLfloat s, t, u;
+ GLfloat s1, t1, u1;
+
+ x = (GLint) VB->Win.data[i][0];
+ y = (GLint) VB->Win.data[i][1];
+ z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset);
+
+ isize = (GLint)
+ (CLAMP(ctx->Point.Size,MIN_POINT_SIZE,MAX_POINT_SIZE) + 0.5F);
+ if (isize<1) {
+ isize = 1;
+ }
+ radius = isize >> 1;
+
+ if (isize & 1) {
+ /* odd size */
+ x0 = x - radius;
+ x1 = x + radius;
+ y0 = y - radius;
+ y1 = y + radius;
+ }
+ else {
+ /* even size */
+ x0 = (GLint) (x + 1.5F) - radius;
+ x1 = x0 + isize - 1;
+ y0 = (GLint) (y + 1.5F) - radius;
+ y1 = y0 + isize - 1;
+ }
+
+ red = VB->ColorPtr->data[i][0];
+ green = VB->ColorPtr->data[i][1];
+ blue = VB->ColorPtr->data[i][2];
+ alpha = VB->ColorPtr->data[i][3];
+
+ switch (VB->TexCoordPtr[0]->size) {
+ case 4:
+ s = VB->TexCoordPtr[0]->data[i][0]/VB->TexCoordPtr[0]->data[i][3];
+ t = VB->TexCoordPtr[0]->data[i][1]/VB->TexCoordPtr[0]->data[i][3];
+ u = VB->TexCoordPtr[0]->data[i][2]/VB->TexCoordPtr[0]->data[i][3];
+ break;
+ case 3:
+ s = VB->TexCoordPtr[0]->data[i][0];
+ t = VB->TexCoordPtr[0]->data[i][1];
+ u = VB->TexCoordPtr[0]->data[i][2];
+ break;
+ case 2:
+ s = VB->TexCoordPtr[0]->data[i][0];
+ t = VB->TexCoordPtr[0]->data[i][1];
+ u = 0.0;
+ break;
+ case 1:
+ s = VB->TexCoordPtr[0]->data[i][0];
+ t = 0.0;
+ u = 0.0;
+ break;
+ }
+
+ switch (VB->TexCoordPtr[1]->size) {
+ case 4:
+ s1 = VB->TexCoordPtr[1]->data[i][0]/VB->TexCoordPtr[1]->data[i][3];
+ t1 = VB->TexCoordPtr[1]->data[i][1]/VB->TexCoordPtr[1]->data[i][3];
+ u1 = VB->TexCoordPtr[1]->data[i][2]/VB->TexCoordPtr[1]->data[i][3];
+ break;
+ case 3:
+ s1 = VB->TexCoordPtr[1]->data[i][0];
+ t1 = VB->TexCoordPtr[1]->data[i][1];
+ u1 = VB->TexCoordPtr[1]->data[i][2];
+ break;
+ case 2:
+ s1 = VB->TexCoordPtr[1]->data[i][0];
+ t1 = VB->TexCoordPtr[1]->data[i][1];
+ u1 = 0.0;
+ break;
+ case 1:
+ s1 = VB->TexCoordPtr[1]->data[i][0];
+ t1 = 0.0;
+ u1 = 0.0;
+ break;
+ }
+
+ for (iy=y0;iy<=y1;iy++) {
+ for (ix=x0;ix<=x1;ix++) {
+ PB_WRITE_MULTITEX_PIXEL( PB, ix, iy, z, red, green, blue, alpha, s, t, u, s1, t1, u1 );
+ }
+ }
+ PB_CHECK_FLUSH(ctx,PB);
+ }
+ }
+}
+
+
+
+
+/*
+ * Antialiased points with or without texture mapping.
+ */
+static void antialiased_rgba_points( GLcontext *ctx,
+ GLuint first, GLuint last )
+{
+ struct vertex_buffer *VB = ctx->VB;
+ struct pixel_buffer *PB = ctx->PB;
+ GLuint i;
+ GLfloat radius, rmin, rmax, rmin2, rmax2, cscale;
+
+ radius = CLAMP( ctx->Point.Size, MIN_POINT_SIZE, MAX_POINT_SIZE ) * 0.5F;
+ rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */
+ rmax = radius + 0.7071F;
+ rmin2 = rmin*rmin;
+ rmax2 = rmax*rmax;
+ cscale = 256.0F / (rmax2-rmin2);
+
+ if (ctx->Texture.ReallyEnabled) {
+ for (i=first;i<=last;i++) {
+ if (VB->ClipMask[i]==0) {
+ GLint xmin, ymin, xmax, ymax;
+ GLint x, y, z;
+ GLint red, green, blue, alpha;
+ GLfloat s, t, u;
+ GLfloat s1, t1, u1;
+
+ xmin = (GLint) (VB->Win.data[i][0] - radius);
+ xmax = (GLint) (VB->Win.data[i][0] + radius);
+ ymin = (GLint) (VB->Win.data[i][1] - radius);
+ ymax = (GLint) (VB->Win.data[i][1] + radius);
+ z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset);
+
+ red = VB->ColorPtr->data[i][0];
+ green = VB->ColorPtr->data[i][1];
+ blue = VB->ColorPtr->data[i][2];
+
+ switch (VB->TexCoordPtr[0]->size) {
+ case 4:
+ s = (VB->TexCoordPtr[0]->data[i][0]/
+ VB->TexCoordPtr[0]->data[i][3]);
+ t = (VB->TexCoordPtr[0]->data[i][1]/
+ VB->TexCoordPtr[0]->data[i][3]);
+ u = (VB->TexCoordPtr[0]->data[i][2]/
+ VB->TexCoordPtr[0]->data[i][3]);
+ break;
+ case 3:
+ s = VB->TexCoordPtr[0]->data[i][0];
+ t = VB->TexCoordPtr[0]->data[i][1];
+ u = VB->TexCoordPtr[0]->data[i][2];
+ break;
+ case 2:
+ s = VB->TexCoordPtr[0]->data[i][0];
+ t = VB->TexCoordPtr[0]->data[i][1];
+ u = 0.0;
+ break;
+ case 1:
+ s = VB->TexCoordPtr[0]->data[i][0];
+ t = 0.0;
+ u = 0.0;
+ break;
+ }
+
+ if (ctx->Texture.ReallyEnabled >= TEXTURE1_1D) {
+ /* Multitextured! This is probably a slow enough path that
+ there's no reason to specialize the multitexture case. */
+ switch (VB->TexCoordPtr[1]->size) {
+ case 4:
+ s1 = ( VB->TexCoordPtr[1]->data[i][0] /
+ VB->TexCoordPtr[1]->data[i][3]);
+ t1 = ( VB->TexCoordPtr[1]->data[i][1] /
+ VB->TexCoordPtr[1]->data[i][3]);
+ u1 = ( VB->TexCoordPtr[1]->data[i][2] /
+ VB->TexCoordPtr[1]->data[i][3]);
+ break;
+ case 3:
+ s1 = VB->TexCoordPtr[1]->data[i][0];
+ t1 = VB->TexCoordPtr[1]->data[i][1];
+ u1 = VB->TexCoordPtr[1]->data[i][2];
+ break;
+ case 2:
+ s1 = VB->TexCoordPtr[1]->data[i][0];
+ t1 = VB->TexCoordPtr[1]->data[i][1];
+ u1 = 0.0;
+ break;
+ case 1:
+ s1 = VB->TexCoordPtr[1]->data[i][0];
+ t1 = 0.0;
+ u1 = 0.0;
+ break;
+ }
+ }
+
+ for (y=ymin;y<=ymax;y++) {
+ for (x=xmin;x<=xmax;x++) {
+ GLfloat dx = x/*+0.5F*/ - VB->Win.data[i][0];
+ GLfloat dy = y/*+0.5F*/ - VB->Win.data[i][1];
+ GLfloat dist2 = dx*dx + dy*dy;
+ if (dist2<rmax2) {
+ alpha = VB->ColorPtr->data[i][3];
+ if (dist2>=rmin2) {
+ GLint coverage = (GLint) (256.0F-(dist2-rmin2)*cscale);
+ /* coverage is in [0,256] */
+ alpha = (alpha * coverage) >> 8;
+ }
+ if (ctx->Texture.ReallyEnabled >= TEXTURE1_1D) {
+ PB_WRITE_MULTITEX_PIXEL( PB, x,y,z, red, green, blue,
+ alpha, s, t, u, s1, t1, u1 );
+ } else {
+ PB_WRITE_TEX_PIXEL( PB, x,y,z, red, green, blue,
+ alpha, s, t, u );
+ }
+ }
+ }
+ }
+
+ PB_CHECK_FLUSH(ctx,PB);
+ }
+ }
+ }
+ else {
+ /* Not texture mapped */
+ for (i=first;i<=last;i++) {
+ if (VB->ClipMask[i]==0) {
+ GLint xmin, ymin, xmax, ymax;
+ GLint x, y, z;
+ GLint red, green, blue, alpha;
+
+ xmin = (GLint) (VB->Win.data[i][0] - radius);
+ xmax = (GLint) (VB->Win.data[i][0] + radius);
+ ymin = (GLint) (VB->Win.data[i][1] - radius);
+ ymax = (GLint) (VB->Win.data[i][1] + radius);
+ z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset);
+
+ red = VB->ColorPtr->data[i][0];
+ green = VB->ColorPtr->data[i][1];
+ blue = VB->ColorPtr->data[i][2];
+
+ for (y=ymin;y<=ymax;y++) {
+ for (x=xmin;x<=xmax;x++) {
+ GLfloat dx = x/*+0.5F*/ - VB->Win.data[i][0];
+ GLfloat dy = y/*+0.5F*/ - VB->Win.data[i][1];
+ GLfloat dist2 = dx*dx + dy*dy;
+ if (dist2<rmax2) {
+ alpha = VB->ColorPtr->data[i][3];
+ if (dist2>=rmin2) {
+ GLint coverage = (GLint) (256.0F-(dist2-rmin2)*cscale);
+ /* coverage is in [0,256] */
+ alpha = (alpha * coverage) >> 8;
+ }
+ PB_WRITE_RGBA_PIXEL( PB, x, y, z, red, green, blue,
+ alpha );
+ }
+ }
+ }
+ PB_CHECK_FLUSH(ctx,PB);
+ }
+ }
+ }
+}
+
+
+
+/*
+ * Null rasterizer for measuring transformation speed.
+ */
+static void null_points( GLcontext *ctx, GLuint first, GLuint last )
+{
+ (void) ctx;
+ (void) first;
+ (void) last;
+}
+
+
+
+/* Definition of the functions for GL_EXT_point_parameters */
+
+/* Calculates the distance attenuation formula of a vector of points in
+ * eye space coordinates
+ */
+static void dist3(GLfloat *out, GLuint first, GLuint last,
+ const GLcontext *ctx, const GLvector4f *v)
+{
+ GLuint stride = v->stride;
+ GLfloat *p = VEC_ELT(v, GLfloat, first);
+ GLuint i;
+
+ for (i = first ; i <= last ; i++, STRIDE_F(p, stride) )
+ {
+ GLfloat dist = GL_SQRT(p[0]*p[0]+p[1]*p[1]+p[2]*p[2]);
+ out[i] = 1/(ctx->Point.Params[0]+
+ dist * (ctx->Point.Params[1] +
+ dist * ctx->Point.Params[2]));
+ }
+}
+
+static void dist2(GLfloat *out, GLuint first, GLuint last,
+ const GLcontext *ctx, const GLvector4f *v)
+{
+ GLuint stride = v->stride;
+ GLfloat *p = VEC_ELT(v, GLfloat, first);
+ GLuint i;
+
+ for (i = first ; i <= last ; i++, STRIDE_F(p, stride) )
+ {
+ GLfloat dist = GL_SQRT(p[0]*p[0]+p[1]*p[1]);
+ out[i] = 1/(ctx->Point.Params[0]+
+ dist * (ctx->Point.Params[1] +
+ dist * ctx->Point.Params[2]));
+ }
+}
+
+
+typedef void (*dist_func)(GLfloat *out, GLuint first, GLuint last,
+ const GLcontext *ctx, const GLvector4f *v);
+
+
+static dist_func eye_dist_tab[5] = {
+ 0,
+ 0,
+ dist2,
+ dist3,
+ dist3
+};
+
+
+static void clip_dist(GLfloat *out, GLuint first, GLuint last,
+ const GLcontext *ctx, GLvector4f *clip)
+{
+ /* this is never called */
+ gl_problem(NULL, "clip_dist() called - dead code!\n");
+
+ (void) out;
+ (void) first;
+ (void) last;
+ (void) ctx;
+ (void) clip;
+
+#if 0
+ GLuint i;
+ const GLfloat *from = (GLfloat *)clip_vec->start;
+ const GLuint stride = clip_vec->stride;
+
+ for (i = first ; i <= last ; i++ )
+ {
+ GLfloat dist = win[i][2];
+ out[i] = 1/(ctx->Point.Params[0]+
+ dist * (ctx->Point.Params[1] +
+ dist * ctx->Point.Params[2]));
+ }
+#endif
+}
+
+
+
+/*
+ * Distance Attenuated General CI points.
+ */
+static void dist_atten_general_ci_points( GLcontext *ctx, GLuint first,
+ GLuint last )
+{
+ struct vertex_buffer *VB = ctx->VB;
+ struct pixel_buffer *PB = ctx->PB;
+ GLuint i;
+ GLfloat psize,dsize;
+ GLfloat dist[VB_SIZE];
+ psize=CLAMP(ctx->Point.Size,MIN_POINT_SIZE,MAX_POINT_SIZE);
+
+ if (ctx->NeedEyeCoords)
+ (eye_dist_tab[VB->EyePtr->size])( dist, first, last, ctx, VB->EyePtr );
+ else
+ clip_dist( dist, first, last, ctx, VB->ClipPtr );
+
+ for (i=first;i<=last;i++) {
+ if (VB->ClipMask[i]==0) {
+ GLint x, y, z;
+ GLint x0, x1, y0, y1;
+ GLint ix, iy;
+ GLint isize, radius;
+
+ x = (GLint) VB->Win.data[i][0];
+ y = (GLint) VB->Win.data[i][1];
+ z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset);
+
+ dsize=psize*dist[i];
+ if(dsize>=ctx->Point.Threshold) {
+ isize=(GLint) (MIN2(dsize,ctx->Point.MaxSize)+0.5F);
+ } else {
+ isize=(GLint) (MAX2(ctx->Point.Threshold,ctx->Point.MinSize)+0.5F);
+ }
+ radius = isize >> 1;
+
+ if (isize & 1) {
+ /* odd size */
+ x0 = x - radius;
+ x1 = x + radius;
+ y0 = y - radius;
+ y1 = y + radius;
+ }
+ else {
+ /* even size */
+ x0 = (GLint) (x + 1.5F) - radius;
+ x1 = x0 + isize - 1;
+ y0 = (GLint) (y + 1.5F) - radius;
+ y1 = y0 + isize - 1;
+ }
+
+ PB_SET_INDEX( ctx, PB, VB->IndexPtr->data[i] );
+
+ for (iy=y0;iy<=y1;iy++) {
+ for (ix=x0;ix<=x1;ix++) {
+ PB_WRITE_PIXEL( PB, ix, iy, z );
+ }
+ }
+ PB_CHECK_FLUSH(ctx,PB);
+ }
+ }
+}
+
+/*
+ * Distance Attenuated General RGBA points.
+ */
+static void dist_atten_general_rgba_points( GLcontext *ctx, GLuint first,
+ GLuint last )
+{
+ struct vertex_buffer *VB = ctx->VB;
+ struct pixel_buffer *PB = ctx->PB;
+ GLuint i;
+ GLubyte alpha;
+ GLfloat psize,dsize;
+ GLfloat dist[VB_SIZE];
+ psize=CLAMP(ctx->Point.Size,MIN_POINT_SIZE,MAX_POINT_SIZE);
+
+ if (ctx->NeedEyeCoords)
+ (eye_dist_tab[VB->EyePtr->size])( dist, first, last, ctx, VB->EyePtr );
+ else
+ clip_dist( dist, first, last, ctx, VB->ClipPtr );
+
+ for (i=first;i<=last;i++) {
+ if (VB->ClipMask[i]==0) {
+ GLint x, y, z;
+ GLint x0, x1, y0, y1;
+ GLint ix, iy;
+ GLint isize, radius;
+
+ x = (GLint) VB->Win.data[i][0];
+ y = (GLint) VB->Win.data[i][1];
+ z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset);
+ dsize=psize*dist[i];
+ if (dsize >= ctx->Point.Threshold) {
+ isize = (GLint) (MIN2(dsize,ctx->Point.MaxSize)+0.5F);
+ alpha = VB->ColorPtr->data[i][3];
+ }
+ else {
+ isize = (GLint) (MAX2(ctx->Point.Threshold,ctx->Point.MinSize)+0.5F);
+ dsize /= ctx->Point.Threshold;
+ alpha = (GLint) (VB->ColorPtr->data[i][3]* (dsize*dsize));
+ }
+ radius = isize >> 1;
+
+ if (isize & 1) {
+ /* odd size */
+ x0 = x - radius;
+ x1 = x + radius;
+ y0 = y - radius;
+ y1 = y + radius;
+ }
+ else {
+ /* even size */
+ x0 = (GLint) (x + 1.5F) - radius;
+ x1 = x0 + isize - 1;
+ y0 = (GLint) (y + 1.5F) - radius;
+ y1 = y0 + isize - 1;
+ }
+
+ PB_SET_COLOR( ctx, PB,
+ VB->ColorPtr->data[i][0],
+ VB->ColorPtr->data[i][1],
+ VB->ColorPtr->data[i][2],
+ alpha );
+
+ for (iy=y0;iy<=y1;iy++) {
+ for (ix=x0;ix<=x1;ix++) {
+ PB_WRITE_PIXEL( PB, ix, iy, z );
+ }
+ }
+ PB_CHECK_FLUSH(ctx,PB);
+ }
+ }
+}
+
+/*
+ * Distance Attenuated Textured RGBA points.
+ */
+static void dist_atten_textured_rgba_points( GLcontext *ctx, GLuint first,
+ GLuint last )
+{
+ struct vertex_buffer *VB = ctx->VB;
+ struct pixel_buffer *PB = ctx->PB;
+ GLuint i;
+ GLfloat psize,dsize;
+ GLfloat dist[VB_SIZE];
+ psize=CLAMP(ctx->Point.Size,MIN_POINT_SIZE,MAX_POINT_SIZE);
+
+ if (ctx->NeedEyeCoords)
+ (eye_dist_tab[VB->EyePtr->size])( dist, first, last, ctx, VB->EyePtr );
+ else
+ clip_dist( dist, first, last, ctx, VB->ClipPtr );
+
+ for (i=first;i<=last;i++) {
+ if (VB->ClipMask[i]==0) {
+ GLint x, y, z;
+ GLint x0, x1, y0, y1;
+ GLint ix, iy;
+ GLint isize, radius;
+ GLint red, green, blue, alpha;
+ GLfloat s, t, u;
+ GLfloat s1, t1, u1;
+
+ x = (GLint) VB->Win.data[i][0];
+ y = (GLint) VB->Win.data[i][1];
+ z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset);
+
+ dsize=psize*dist[i];
+ if(dsize>=ctx->Point.Threshold) {
+ isize=(GLint) (MIN2(dsize,ctx->Point.MaxSize)+0.5F);
+ alpha=VB->ColorPtr->data[i][3];
+ } else {
+ isize=(GLint) (MAX2(ctx->Point.Threshold,ctx->Point.MinSize)+0.5F);
+ dsize/=ctx->Point.Threshold;
+ alpha = (GLint) (VB->ColorPtr->data[i][3]* (dsize*dsize));
+ }
+
+ if (isize<1) {
+ isize = 1;
+ }
+ radius = isize >> 1;
+
+ if (isize & 1) {
+ /* odd size */
+ x0 = x - radius;
+ x1 = x + radius;
+ y0 = y - radius;
+ y1 = y + radius;
+ }
+ else {
+ /* even size */
+ x0 = (GLint) (x + 1.5F) - radius;
+ x1 = x0 + isize - 1;
+ y0 = (GLint) (y + 1.5F) - radius;
+ y1 = y0 + isize - 1;
+ }
+
+ red = VB->ColorPtr->data[i][0];
+ green = VB->ColorPtr->data[i][1];
+ blue = VB->ColorPtr->data[i][2];
+
+ switch (VB->TexCoordPtr[0]->size) {
+ case 4:
+ s = (VB->TexCoordPtr[0]->data[i][0]/
+ VB->TexCoordPtr[0]->data[i][3]);
+ t = (VB->TexCoordPtr[0]->data[i][1]/
+ VB->TexCoordPtr[0]->data[i][3]);
+ u = (VB->TexCoordPtr[0]->data[i][2]/
+ VB->TexCoordPtr[0]->data[i][3]);
+ break;
+ case 3:
+ s = VB->TexCoordPtr[0]->data[i][0];
+ t = VB->TexCoordPtr[0]->data[i][1];
+ u = VB->TexCoordPtr[0]->data[i][2];
+ break;
+ case 2:
+ s = VB->TexCoordPtr[0]->data[i][0];
+ t = VB->TexCoordPtr[0]->data[i][1];
+ u = 0.0;
+ break;
+ case 1:
+ s = VB->TexCoordPtr[0]->data[i][0];
+ t = 0.0;
+ u = 0.0;
+ break;
+ }
+
+ if (ctx->Texture.ReallyEnabled >= TEXTURE1_1D) {
+ /* Multitextured! This is probably a slow enough path that
+ there's no reason to specialize the multitexture case. */
+ switch (VB->TexCoordPtr[1]->size) {
+ case 4:
+ s1 = ( VB->TexCoordPtr[1]->data[i][0] /
+ VB->TexCoordPtr[1]->data[i][3] );
+ t1 = ( VB->TexCoordPtr[1]->data[i][1] /
+ VB->TexCoordPtr[1]->data[i][3] );
+ u1 = ( VB->TexCoordPtr[1]->data[i][2] /
+ VB->TexCoordPtr[1]->data[i][3] );
+ break;
+ case 3:
+ s1 = VB->TexCoordPtr[1]->data[i][0];
+ t1 = VB->TexCoordPtr[1]->data[i][1];
+ u1 = VB->TexCoordPtr[1]->data[i][2];
+ break;
+ case 2:
+ s1 = VB->TexCoordPtr[1]->data[i][0];
+ t1 = VB->TexCoordPtr[1]->data[i][1];
+ u1 = 0.0;
+ break;
+ case 1:
+ s1 = VB->TexCoordPtr[1]->data[i][0];
+ t1 = 0.0;
+ u1 = 0.0;
+ break;
+ }
+ }
+
+/* don't think this is needed
+ PB_SET_COLOR( red, green, blue, alpha );
+*/
+
+ for (iy=y0;iy<=y1;iy++) {
+ for (ix=x0;ix<=x1;ix++) {
+ if (ctx->Texture.ReallyEnabled >= TEXTURE1_1D) {
+ PB_WRITE_MULTITEX_PIXEL( PB, ix, iy, z, red, green, blue, alpha, s, t, u, s1, t1, u1 );
+ } else {
+ PB_WRITE_TEX_PIXEL( PB, ix, iy, z, red, green, blue, alpha, s, t, u );
+ }
+ }
+ }
+ PB_CHECK_FLUSH(ctx,PB);
+ }
+ }
+}
+
+/*
+ * Distance Attenuated Antialiased points with or without texture mapping.
+ */
+static void dist_atten_antialiased_rgba_points( GLcontext *ctx,
+ GLuint first, GLuint last )
+{
+ struct vertex_buffer *VB = ctx->VB;
+ struct pixel_buffer *PB = ctx->PB;
+ GLuint i;
+ GLfloat radius, rmin, rmax, rmin2, rmax2, cscale;
+ GLfloat psize,dsize,alphaf;
+ GLfloat dist[VB_SIZE];
+ psize=CLAMP(ctx->Point.Size,MIN_POINT_SIZE,MAX_POINT_SIZE);
+
+ if (ctx->NeedEyeCoords)
+ (eye_dist_tab[VB->EyePtr->size])( dist, first, last, ctx, VB->EyePtr );
+ else
+ clip_dist( dist, first, last, ctx, VB->ClipPtr );
+
+ if (ctx->Texture.ReallyEnabled) {
+ for (i=first;i<=last;i++) {
+ if (VB->ClipMask[i]==0) {
+ GLint xmin, ymin, xmax, ymax;
+ GLint x, y, z;
+ GLint red, green, blue, alpha;
+ GLfloat s, t, u;
+ GLfloat s1, t1, u1;
+
+ dsize=psize*dist[i];
+ if(dsize>=ctx->Point.Threshold) {
+ radius=(MIN2(dsize,ctx->Point.MaxSize)*0.5F);
+ alphaf=1.0;
+ } else {
+ radius=(MAX2(ctx->Point.Threshold,ctx->Point.MinSize)*0.5F);
+ dsize/=ctx->Point.Threshold;
+ alphaf=(dsize*dsize);
+ }
+ rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */
+ rmax = radius + 0.7071F;
+ rmin2 = rmin*rmin;
+ rmax2 = rmax*rmax;
+ cscale = 256.0F / (rmax2-rmin2);
+
+ xmin = (GLint) (VB->Win.data[i][0] - radius);
+ xmax = (GLint) (VB->Win.data[i][0] + radius);
+ ymin = (GLint) (VB->Win.data[i][1] - radius);
+ ymax = (GLint) (VB->Win.data[i][1] + radius);
+ z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset);
+
+ red = VB->ColorPtr->data[i][0];
+ green = VB->ColorPtr->data[i][1];
+ blue = VB->ColorPtr->data[i][2];
+
+ switch (VB->TexCoordPtr[0]->size) {
+ case 4:
+ s = (VB->TexCoordPtr[0]->data[i][0]/
+ VB->TexCoordPtr[0]->data[i][3]);
+ t = (VB->TexCoordPtr[0]->data[i][1]/
+ VB->TexCoordPtr[0]->data[i][3]);
+ u = (VB->TexCoordPtr[0]->data[i][2]/
+ VB->TexCoordPtr[0]->data[i][3]);
+ break;
+ case 3:
+ s = VB->TexCoordPtr[0]->data[i][0];
+ t = VB->TexCoordPtr[0]->data[i][1];
+ u = VB->TexCoordPtr[0]->data[i][2];
+ break;
+ case 2:
+ s = VB->TexCoordPtr[0]->data[i][0];
+ t = VB->TexCoordPtr[0]->data[i][1];
+ u = 0.0;
+ break;
+ case 1:
+ s = VB->TexCoordPtr[0]->data[i][0];
+ t = 0.0;
+ u = 0.0;
+ break;
+ }
+
+ if (ctx->Texture.ReallyEnabled >= TEXTURE1_1D) {
+ /* Multitextured! This is probably a slow enough path that
+ there's no reason to specialize the multitexture case. */
+ switch (VB->TexCoordPtr[1]->size) {
+ case 4:
+ s1 = ( VB->TexCoordPtr[1]->data[i][0] /
+ VB->TexCoordPtr[1]->data[i][3] );
+ t1 = ( VB->TexCoordPtr[1]->data[i][1] /
+ VB->TexCoordPtr[1]->data[i][3] );
+ u1 = ( VB->TexCoordPtr[1]->data[i][2] /
+ VB->TexCoordPtr[1]->data[i][3] );
+ break;
+ case 3:
+ s1 = VB->TexCoordPtr[1]->data[i][0];
+ t1 = VB->TexCoordPtr[1]->data[i][1];
+ u1 = VB->TexCoordPtr[1]->data[i][2];
+ break;
+ case 2:
+ s1 = VB->TexCoordPtr[1]->data[i][0];
+ t1 = VB->TexCoordPtr[1]->data[i][1];
+ u1 = 0.0;
+ break;
+ case 1:
+ s1 = VB->TexCoordPtr[1]->data[i][0];
+ t1 = 0.0;
+ u1 = 0.0;
+ break;
+ }
+ }
+
+ for (y=ymin;y<=ymax;y++) {
+ for (x=xmin;x<=xmax;x++) {
+ GLfloat dx = x/*+0.5F*/ - VB->Win.data[i][0];
+ GLfloat dy = y/*+0.5F*/ - VB->Win.data[i][1];
+ GLfloat dist2 = dx*dx + dy*dy;
+ if (dist2<rmax2) {
+ alpha = VB->ColorPtr->data[i][3];
+ if (dist2>=rmin2) {
+ GLint coverage = (GLint) (256.0F-(dist2-rmin2)*cscale);
+ /* coverage is in [0,256] */
+ alpha = (alpha * coverage) >> 8;
+ }
+ alpha = (GLint) (alpha * alphaf);
+ if (ctx->Texture.ReallyEnabled >= TEXTURE1_1D) {
+ PB_WRITE_MULTITEX_PIXEL( PB, x,y,z, red, green, blue, alpha, s, t, u, s1, t1, u1 );
+ } else {
+ PB_WRITE_TEX_PIXEL( PB, x,y,z, red, green, blue, alpha, s, t, u );
+ }
+ }
+ }
+ }
+ PB_CHECK_FLUSH(ctx,PB);
+ }
+ }
+ }
+ else {
+ /* Not texture mapped */
+ for (i=first;i<=last;i++) {
+ if (VB->ClipMask[i]==0) {
+ GLint xmin, ymin, xmax, ymax;
+ GLint x, y, z;
+ GLint red, green, blue, alpha;
+
+ dsize=psize*dist[i];
+ if(dsize>=ctx->Point.Threshold) {
+ radius=(MIN2(dsize,ctx->Point.MaxSize)*0.5F);
+ alphaf=1.0;
+ } else {
+ radius=(MAX2(ctx->Point.Threshold,ctx->Point.MinSize)*0.5F);
+ dsize/=ctx->Point.Threshold;
+ alphaf=(dsize*dsize);
+ }
+ rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */
+ rmax = radius + 0.7071F;
+ rmin2 = rmin*rmin;
+ rmax2 = rmax*rmax;
+ cscale = 256.0F / (rmax2-rmin2);
+
+ xmin = (GLint) (VB->Win.data[i][0] - radius);
+ xmax = (GLint) (VB->Win.data[i][0] + radius);
+ ymin = (GLint) (VB->Win.data[i][1] - radius);
+ ymax = (GLint) (VB->Win.data[i][1] + radius);
+ z = (GLint) (VB->Win.data[i][2] + ctx->PointZoffset);
+
+ red = VB->ColorPtr->data[i][0];
+ green = VB->ColorPtr->data[i][1];
+ blue = VB->ColorPtr->data[i][2];
+
+ for (y=ymin;y<=ymax;y++) {
+ for (x=xmin;x<=xmax;x++) {
+ GLfloat dx = x/*+0.5F*/ - VB->Win.data[i][0];
+ GLfloat dy = y/*+0.5F*/ - VB->Win.data[i][1];
+ GLfloat dist2 = dx*dx + dy*dy;
+ if (dist2<rmax2) {
+ alpha = VB->ColorPtr->data[i][3];
+ if (dist2>=rmin2) {
+ GLint coverage = (GLint) (256.0F-(dist2-rmin2)*cscale);
+ /* coverage is in [0,256] */
+ alpha = (alpha * coverage) >> 8;
+ }
+ alpha = (GLint) (alpha * alphaf);
+ PB_WRITE_RGBA_PIXEL( PB, x, y, z, red, green, blue, alpha )
+ ;
+ }
+ }
+ }
+ PB_CHECK_FLUSH(ctx,PB);
+ }
+ }
+ }
+}
+
+
+/*
+ * Examine the current context to determine which point drawing function
+ * should be used.
+ */
+void gl_set_point_function( GLcontext *ctx )
+{
+ GLboolean rgbmode = ctx->Visual->RGBAflag;
+
+ if (ctx->RenderMode==GL_RENDER) {
+ if (ctx->NoRaster) {
+ ctx->Driver.PointsFunc = null_points;
+ return;
+ }
+ if (ctx->Driver.PointsFunc) {
+ /* Device driver will draw points. */
+ ctx->IndirectTriangles &= ~DD_POINT_SW_RASTERIZE;
+ return;
+ }
+
+ if (!ctx->Point.Attenuated) {
+ if (ctx->Point.SmoothFlag && rgbmode) {
+ ctx->Driver.PointsFunc = antialiased_rgba_points;
+ }
+ else if (ctx->Texture.ReallyEnabled) {
+ if (ctx->Texture.ReallyEnabled >= TEXTURE1_1D) {
+ ctx->Driver.PointsFunc = multitextured_rgba_points;
+ }
+ else {
+ ctx->Driver.PointsFunc = textured_rgba_points;
+ }
+ }
+ else if (ctx->Point.Size==1.0) {
+ /* size=1, any raster ops */
+ if (rgbmode)
+ ctx->Driver.PointsFunc = size1_rgba_points;
+ else
+ ctx->Driver.PointsFunc = size1_ci_points;
+ }
+ else {
+ /* every other kind of point rendering */
+ if (rgbmode)
+ ctx->Driver.PointsFunc = general_rgba_points;
+ else
+ ctx->Driver.PointsFunc = general_ci_points;
+ }
+ }
+ else if(ctx->Point.SmoothFlag && rgbmode) {
+ ctx->Driver.PointsFunc = dist_atten_antialiased_rgba_points;
+ }
+ else if (ctx->Texture.ReallyEnabled) {
+ ctx->Driver.PointsFunc = dist_atten_textured_rgba_points;
+ }
+ else {
+ /* every other kind of point rendering */
+ if (rgbmode)
+ ctx->Driver.PointsFunc = dist_atten_general_rgba_points;
+ else
+ ctx->Driver.PointsFunc = dist_atten_general_ci_points;
+ }
+ }
+ else if (ctx->RenderMode==GL_FEEDBACK) {
+ ctx->Driver.PointsFunc = feedback_points;
+ }
+ else {
+ /* GL_SELECT mode */
+ ctx->Driver.PointsFunc = select_points;
+ }
+
+}
+
diff --git a/src/mesa/main/points.h b/src/mesa/main/points.h
new file mode 100644
index 0000000000..a53ce9b2d2
--- /dev/null
+++ b/src/mesa/main/points.h
@@ -0,0 +1,45 @@
+/* $Id: points.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef POINTS_H
+#define POINTS_H
+
+
+#include "types.h"
+
+
+extern void gl_PointSize( GLcontext *ctx, GLfloat size );
+
+extern void gl_set_point_function( GLcontext *ctx );
+
+extern void gl_PointParameterfvEXT( GLcontext *ctx, GLenum pname,
+ const GLfloat *params );
+
+#endif
diff --git a/src/mesa/main/polygon.c b/src/mesa/main/polygon.c
new file mode 100644
index 0000000000..83690035ff
--- /dev/null
+++ b/src/mesa/main/polygon.c
@@ -0,0 +1,177 @@
+/* $Id: polygon.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "context.h"
+#include "image.h"
+#include "enums.h"
+#include "macros.h"
+#include "polygon.h"
+#include "types.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+
+void gl_CullFace( GLcontext *ctx, GLenum mode )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCullFace");
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ fprintf(stderr, "glCullFace %s\n", gl_lookup_enum_by_nr(mode));
+
+ if (mode!=GL_FRONT && mode!=GL_BACK && mode!=GL_FRONT_AND_BACK) {
+ gl_error( ctx, GL_INVALID_ENUM, "glCullFace" );
+ return;
+ }
+
+ ctx->Polygon.CullFaceMode = mode;
+ ctx->NewState |= NEW_POLYGON;
+
+ if (ctx->Driver.CullFace)
+ ctx->Driver.CullFace( ctx, mode );
+}
+
+
+
+void gl_FrontFace( GLcontext *ctx, GLenum mode )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glFrontFace");
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ fprintf(stderr, "glFrontFace %s\n", gl_lookup_enum_by_nr(mode));
+
+ if (mode!=GL_CW && mode!=GL_CCW) {
+ gl_error( ctx, GL_INVALID_ENUM, "glFrontFace" );
+ return;
+ }
+ ctx->Polygon.FrontFace = mode;
+ ctx->Polygon.FrontBit = (mode == GL_CW);
+
+ if (ctx->Driver.FrontFace)
+ ctx->Driver.FrontFace( ctx, mode );
+}
+
+
+
+void gl_PolygonMode( GLcontext *ctx, GLenum face, GLenum mode )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPolygonMode");
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ fprintf(stderr, "glPolygonMode %s %s\n",
+ gl_lookup_enum_by_nr(face),
+ gl_lookup_enum_by_nr(mode));
+
+ if (face!=GL_FRONT && face!=GL_BACK && face!=GL_FRONT_AND_BACK) {
+ gl_error( ctx, GL_INVALID_ENUM, "glPolygonMode(face)" );
+ return;
+ }
+ else if (mode!=GL_POINT && mode!=GL_LINE && mode!=GL_FILL) {
+ gl_error( ctx, GL_INVALID_ENUM, "glPolygonMode(mode)" );
+ return;
+ }
+
+ if (face==GL_FRONT || face==GL_FRONT_AND_BACK) {
+ ctx->Polygon.FrontMode = mode;
+ }
+ if (face==GL_BACK || face==GL_FRONT_AND_BACK) {
+ ctx->Polygon.BackMode = mode;
+ }
+
+ /* Compute a handy "shortcut" value: */
+ ctx->TriangleCaps &= ~DD_TRI_UNFILLED;
+ ctx->Polygon.Unfilled = GL_FALSE;
+
+ if (ctx->Polygon.FrontMode!=GL_FILL || ctx->Polygon.BackMode!=GL_FILL) {
+ ctx->Polygon.Unfilled = GL_TRUE;
+ ctx->TriangleCaps |= DD_TRI_UNFILLED;
+ }
+ else {
+ ctx->Polygon.Unfilled = GL_FALSE;
+ }
+
+ ctx->NewState |= (NEW_POLYGON | NEW_RASTER_OPS);
+
+ if (ctx->Driver.PolygonMode) {
+ (*ctx->Driver.PolygonMode)( ctx, face, mode );
+ }
+}
+
+
+
+/*
+ * NOTE: stipple pattern has already been unpacked.
+ */
+void gl_PolygonStipple( GLcontext *ctx, const GLuint pattern[32] )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPolygonStipple");
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ fprintf(stderr, "glPolygonStipple\n");
+
+ MEMCPY( ctx->PolygonStipple, pattern, 32 * 4 );
+
+ if (ctx->Polygon.StippleFlag) {
+ ctx->NewState |= NEW_RASTER_OPS;
+ }
+}
+
+
+
+void gl_GetPolygonStipple( GLcontext *ctx, GLubyte *dest )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPolygonOffset");
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ fprintf(stderr, "glGetPolygonStipple\n");
+
+ gl_pack_polygon_stipple( ctx, ctx->PolygonStipple, dest );
+}
+
+
+
+void gl_PolygonOffset( GLcontext *ctx,
+ GLfloat factor, GLfloat units )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPolygonOffset");
+
+ if (MESA_VERBOSE&VERBOSE_API)
+ fprintf(stderr, "glPolygonOffset %f %f\n", factor, units);
+
+ ctx->Polygon.OffsetFactor = factor;
+ ctx->Polygon.OffsetUnits = units;
+}
+
diff --git a/src/mesa/main/polygon.h b/src/mesa/main/polygon.h
new file mode 100644
index 0000000000..ac591bbda4
--- /dev/null
+++ b/src/mesa/main/polygon.h
@@ -0,0 +1,53 @@
+/* $Id: polygon.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef POLYGON_H
+#define POLYGON_H
+
+
+#include "types.h"
+
+
+extern void gl_CullFace( GLcontext *ctx, GLenum mode );
+
+extern void gl_FrontFace( GLcontext *ctx, GLenum mode );
+
+extern void gl_PolygonMode( GLcontext *ctx, GLenum face, GLenum mode );
+
+extern void gl_PolygonOffset( GLcontext *ctx,
+ GLfloat factor, GLfloat units );
+
+extern void gl_PolygonStipple( GLcontext *ctx, const GLuint pattern[32] );
+
+extern void gl_GetPolygonStipple( GLcontext *ctx, GLubyte *mask );
+
+
+#endif
+
diff --git a/src/mesa/main/rastpos.c b/src/mesa/main/rastpos.c
new file mode 100644
index 0000000000..000af375ba
--- /dev/null
+++ b/src/mesa/main/rastpos.c
@@ -0,0 +1,227 @@
+/* $Id: rastpos.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <assert.h>
+#include "clip.h"
+#include "feedback.h"
+#include "light.h"
+#include "macros.h"
+#include "matrix.h"
+#include "mmath.h"
+#include "shade.h"
+#include "types.h"
+#include "xform.h"
+#include "context.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+
+/*
+ * Caller: context->API.RasterPos4f
+ */
+void gl_RasterPos4f( GLcontext *ctx,
+ GLfloat x, GLfloat y, GLfloat z, GLfloat w )
+{
+ GLfloat v[4], eye[4], clip[4], ndc[3], d;
+
+ /* KW: Added this test, which is in the spec. We can't do this
+ * outside begin/end any more because the ctx->Current values
+ * aren't uptodate during that period.
+ */
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx, "glRasterPos" );
+
+ if (ctx->NewState)
+ gl_update_state( ctx );
+
+ ASSIGN_4V( v, x, y, z, w );
+ TRANSFORM_POINT( eye, ctx->ModelView.m, v );
+
+ /* raster color */
+ if (ctx->Light.Enabled)
+ {
+ /*GLfloat *vert;*/
+ GLfloat *norm, eyenorm[3];
+ GLfloat *objnorm = ctx->Current.Normal;
+
+ /* Not needed???
+ vert = (ctx->NeedEyeCoords ? eye : v);
+ */
+
+ if (ctx->NeedEyeNormals) {
+ GLfloat *inv = ctx->ModelView.inv;
+ TRANSFORM_NORMAL( eyenorm, objnorm, inv );
+ norm = eyenorm;
+ } else {
+ norm = objnorm;
+ }
+
+ gl_shade_rastpos( ctx, v, norm,
+ ctx->Current.RasterColor,
+ &ctx->Current.RasterIndex );
+
+ }
+ else {
+ /* use current color or index */
+ if (ctx->Visual->RGBAflag) {
+ UBYTE_RGBA_TO_FLOAT_RGBA(ctx->Current.RasterColor,
+ ctx->Current.ByteColor);
+ }
+ else {
+ ctx->Current.RasterIndex = ctx->Current.Index;
+ }
+ }
+
+ /* compute raster distance */
+ ctx->Current.RasterDistance =
+ GL_SQRT( eye[0]*eye[0] + eye[1]*eye[1] + eye[2]*eye[2] );
+
+ /* apply projection matrix: clip = Proj * eye */
+ TRANSFORM_POINT( clip, ctx->ProjectionMatrix.m, eye );
+
+ /* clip to view volume */
+ if (gl_viewclip_point( clip )==0) {
+ ctx->Current.RasterPosValid = GL_FALSE;
+ return;
+ }
+
+ /* clip to user clipping planes */
+ if ( ctx->Transform.AnyClip &&
+ gl_userclip_point(ctx, clip) == 0)
+ {
+ ctx->Current.RasterPosValid = GL_FALSE;
+ return;
+ }
+
+ /* ndc = clip / W */
+ ASSERT( clip[3]!=0.0 );
+ d = 1.0F / clip[3];
+ ndc[0] = clip[0] * d;
+ ndc[1] = clip[1] * d;
+ ndc[2] = clip[2] * d;
+
+ ctx->Current.RasterPos[0] = (ndc[0] * ctx->Viewport.WindowMap.m[MAT_SX] +
+ ctx->Viewport.WindowMap.m[MAT_TX]);
+ ctx->Current.RasterPos[1] = (ndc[1] * ctx->Viewport.WindowMap.m[MAT_SY] +
+ ctx->Viewport.WindowMap.m[MAT_TY]);
+ ctx->Current.RasterPos[2] = (ndc[2] * ctx->Viewport.WindowMap.m[MAT_SZ] +
+ ctx->Viewport.WindowMap.m[MAT_TZ]) / DEPTH_SCALE;
+ ctx->Current.RasterPos[3] = clip[3];
+ ctx->Current.RasterPosValid = GL_TRUE;
+
+ /* FOG??? */
+
+ {
+ GLuint texSet;
+ for (texSet=0; texSet<MAX_TEXTURE_UNITS; texSet++) {
+ COPY_4FV( ctx->Current.RasterMultiTexCoord[texSet],
+ ctx->Current.Texcoord[texSet] );
+ }
+ }
+
+ if (ctx->RenderMode==GL_SELECT) {
+ gl_update_hitflag( ctx, ctx->Current.RasterPos[2] );
+ }
+
+}
+
+
+
+/*
+ * This is a MESA extension function. Pretty much just like glRasterPos
+ * except we don't apply the modelview or projection matrices; specify a
+ * window coordinate directly.
+ * Caller: context->API.WindowPos4fMESA pointer.
+ */
+void gl_windowpos( GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z, GLfloat w )
+{
+ /* KW: Assume that like rasterpos, this must be outside begin/end.
+ */
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx, "glWindowPosMESA" );
+
+ /* set raster position */
+ ctx->Current.RasterPos[0] = x;
+ ctx->Current.RasterPos[1] = y;
+ ctx->Current.RasterPos[2] = CLAMP( z, 0.0F, 1.0F );
+ ctx->Current.RasterPos[3] = w;
+
+ ctx->Current.RasterPosValid = GL_TRUE;
+
+ /* raster color */
+ if (0 && ctx->Light.Enabled) {
+
+ /* KW: I don't see how this can work - would have to take the
+ * inverse of the projection matrix or the combined
+ * modelProjection matrix, transform point and normal, and
+ * do the lighting. Those inverses are not used for
+ * anything else. This is not an object-space lighting
+ * issue - what this is trying to do is something like
+ * clip-space or window-space lighting...
+ *
+ * Anyway, since the implementation was never correct, I'm
+ * not fixing it now - just use the unlit color.
+ */
+
+ /* KW: As a reprise, we now *do* keep the inverse of the projection
+ * matrix, so it is not infeasible to try to swim up stream
+ * in this manner. I still don't want to implement it,
+ * however.
+ */
+ }
+ else {
+ /* use current color or index */
+ if (ctx->Visual->RGBAflag) {
+ UBYTE_RGBA_TO_FLOAT_RGBA(ctx->Current.RasterColor,
+ ctx->Current.ByteColor);
+ }
+ else {
+ ctx->Current.RasterIndex = ctx->Current.Index;
+ }
+ }
+
+ ctx->Current.RasterDistance = 0.0;
+
+ {
+ GLuint texSet;
+ for (texSet=0; texSet<MAX_TEXTURE_UNITS; texSet++) {
+ COPY_4FV( ctx->Current.RasterMultiTexCoord[texSet],
+ ctx->Current.Texcoord[texSet] );
+ }
+ }
+
+ if (ctx->RenderMode==GL_SELECT) {
+ gl_update_hitflag( ctx, ctx->Current.RasterPos[2] );
+ }
+}
diff --git a/src/mesa/main/rastpos.h b/src/mesa/main/rastpos.h
new file mode 100644
index 0000000000..44dfbab0d6
--- /dev/null
+++ b/src/mesa/main/rastpos.h
@@ -0,0 +1,48 @@
+/* $Id: rastpos.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef RASTPOS_H
+#define RASTPOS_H
+
+
+#include "types.h"
+
+
+extern void gl_RasterPos4f( GLcontext *ctx,
+ GLfloat x, GLfloat y, GLfloat z, GLfloat w );
+
+
+extern void gl_windowpos( GLcontext *ctx,
+ GLfloat x, GLfloat y, GLfloat z, GLfloat w );
+
+
+
+#endif
+
diff --git a/src/mesa/main/simple_list.h b/src/mesa/main/simple_list.h
new file mode 100644
index 0000000000..994d955b7f
--- /dev/null
+++ b/src/mesa/main/simple_list.h
@@ -0,0 +1,99 @@
+/* $Id: simple_list.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+/* Simple macros for typesafe, intrusive lists.
+ * (C) 1997, Keith Whitwell
+ *
+ * Intended to work with a list sentinal which is created as an empty
+ * list. Insert & delete are O(1).
+ */
+
+
+#ifndef _SIMPLE_LIST_H
+#define _SIMPLE_LIST_H
+
+#define remove_from_list(elem) \
+do { \
+ (elem)->next->prev = (elem)->prev; \
+ (elem)->prev->next = (elem)->next; \
+} while (0)
+
+#define insert_at_head(list, elem) \
+do { \
+ (elem)->prev = list; \
+ (elem)->next = (list)->next; \
+ (list)->next->prev = elem; \
+ (list)->next = elem; \
+} while(0)
+
+#define insert_at_tail(list, elem) \
+do { \
+ (elem)->next = list; \
+ (elem)->prev = (list)->prev; \
+ (list)->prev->next = elem; \
+ (list)->prev = elem; \
+} while(0)
+
+#define move_to_head(list, elem) \
+do { \
+ remove_from_list(elem); \
+ insert_at_head(list, elem); \
+} while (0)
+
+#define move_to_tail(list, elem) \
+do { \
+ remove_from_list(elem); \
+ insert_at_tail(list, elem); \
+} while (0)
+
+
+#define make_empty_list(sentinal) \
+do { \
+ (sentinal)->next = sentinal; \
+ (sentinal)->prev = sentinal; \
+} while (0)
+
+
+#define first_elem(list) ((list)->next)
+#define last_elem(list) ((list)->prev)
+#define next_elem(elem) ((elem)->next)
+#define prev_elem(elem) ((elem)->prev)
+#define at_end(list, elem) ((elem) == (list))
+#define is_empty_list(list) ((list)->next == (list))
+
+#define foreach(ptr, list) \
+ for( ptr=(list)->next ; ptr!=list ; ptr=(ptr)->next )
+
+/* Kludgey - Lets you unlink the current value during a list
+ * traversal. Useful for free()-ing a list, element
+ * by element.
+ */
+#define foreach_s(ptr, t, list) \
+ for(ptr=(list)->next,t=(ptr)->next; list != ptr; ptr=t, t=(t)->next)
+
+
+#endif
+
diff --git a/src/mesa/main/stencil.c b/src/mesa/main/stencil.c
new file mode 100644
index 0000000000..69bd70188b
--- /dev/null
+++ b/src/mesa/main/stencil.c
@@ -0,0 +1,1107 @@
+/* $Id: stencil.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <stdlib.h>
+#include <string.h>
+#include "context.h"
+#include "macros.h"
+#include "pb.h"
+#include "stencil.h"
+#include "types.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+#if STENCIL_BITS==8
+# define STENCIL_MAX 0xff
+#elif STENCIL_BITS==16
+# define STENCIL_MAX 0xffff
+#else
+ illegal number of stencil bits
+#endif
+
+
+
+/*
+ * Return the address of a stencil buffer value given the window coords:
+ */
+#define STENCIL_ADDRESS(X,Y) (ctx->Buffer->Stencil + ctx->Buffer->Width * (Y) + (X))
+
+
+void gl_ClearStencil( GLcontext *ctx, GLint s )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glClearStencil");
+ ctx->Stencil.Clear = (GLstencil) s;
+
+ if (ctx->Driver.ClearStencil) {
+ (*ctx->Driver.ClearStencil)( ctx, s );
+ }
+}
+
+
+
+void gl_StencilFunc( GLcontext *ctx, GLenum func, GLint ref, GLuint mask )
+{
+ GLint maxref;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glStencilFunc");
+
+ switch (func) {
+ case GL_NEVER:
+ case GL_LESS:
+ case GL_LEQUAL:
+ case GL_GREATER:
+ case GL_GEQUAL:
+ case GL_EQUAL:
+ case GL_NOTEQUAL:
+ case GL_ALWAYS:
+ ctx->Stencil.Function = func;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glStencilFunc" );
+ return;
+ }
+
+ maxref = (1 << STENCIL_BITS) - 1;
+ ctx->Stencil.Ref = CLAMP( ref, 0, maxref );
+ ctx->Stencil.ValueMask = mask;
+
+ if (ctx->Driver.StencilFunc) {
+ (*ctx->Driver.StencilFunc)( ctx, func, ctx->Stencil.Ref, mask );
+ }
+}
+
+
+
+void gl_StencilMask( GLcontext *ctx, GLuint mask )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glStencilMask");
+ ctx->Stencil.WriteMask = (GLstencil) mask;
+
+ if (ctx->Driver.StencilMask) {
+ (*ctx->Driver.StencilMask)( ctx, mask );
+ }
+}
+
+
+
+void gl_StencilOp( GLcontext *ctx, GLenum fail, GLenum zfail, GLenum zpass )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glStencilOp");
+ switch (fail) {
+ case GL_KEEP:
+ case GL_ZERO:
+ case GL_REPLACE:
+ case GL_INCR:
+ case GL_DECR:
+ case GL_INVERT:
+ case GL_INCR_WRAP_EXT:
+ case GL_DECR_WRAP_EXT:
+ ctx->Stencil.FailFunc = fail;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glStencilOp" );
+ return;
+ }
+ switch (zfail) {
+ case GL_KEEP:
+ case GL_ZERO:
+ case GL_REPLACE:
+ case GL_INCR:
+ case GL_DECR:
+ case GL_INVERT:
+ case GL_INCR_WRAP_EXT:
+ case GL_DECR_WRAP_EXT:
+ ctx->Stencil.ZFailFunc = zfail;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glStencilOp" );
+ return;
+ }
+ switch (zpass) {
+ case GL_KEEP:
+ case GL_ZERO:
+ case GL_REPLACE:
+ case GL_INCR:
+ case GL_DECR:
+ case GL_INVERT:
+ case GL_INCR_WRAP_EXT:
+ case GL_DECR_WRAP_EXT:
+ ctx->Stencil.ZPassFunc = zpass;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glStencilOp" );
+ return;
+ }
+
+ if (ctx->Driver.StencilOp) {
+ (*ctx->Driver.StencilOp)( ctx, fail, zfail, zpass );
+ }
+}
+
+
+
+/* Stencil Logic:
+
+IF stencil test fails THEN
+ Don't write the pixel (RGBA,Z)
+ Execute FailOp
+ELSE
+ Write the pixel
+ENDIF
+
+Perform Depth Test
+
+IF depth test passes OR no depth buffer THEN
+ Execute ZPass
+ Write the pixel
+ELSE
+ Execute ZFail
+ENDIF
+
+*/
+
+
+
+
+/*
+ * Apply the given stencil operator for each pixel in the span whose
+ * mask flag is set.
+ * Input: n - number of pixels in the span
+ * x, y - location of leftmost pixel in the span
+ * oper - the stencil buffer operator
+ * mask - array [n] of flag: 1=apply operator, 0=don't apply operator
+ */
+static void apply_stencil_op_to_span( GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ GLenum oper, GLubyte mask[] )
+{
+ const GLstencil ref = ctx->Stencil.Ref;
+ const GLstencil wrtmask = ctx->Stencil.WriteMask;
+ const GLstencil invmask = ~ctx->Stencil.WriteMask;
+ GLstencil *stencil = STENCIL_ADDRESS( x, y );
+ GLuint i;
+
+ switch (oper) {
+ case GL_KEEP:
+ /* do nothing */
+ break;
+ case GL_ZERO:
+ if (invmask==0) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ stencil[i] = 0;
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ stencil[i] = stencil[i] & invmask;
+ }
+ }
+ }
+ break;
+ case GL_REPLACE:
+ if (invmask==0) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ stencil[i] = ref;
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil s = stencil[i];
+ stencil[i] = (invmask & s ) | (wrtmask & ref);
+ }
+ }
+ }
+ break;
+ case GL_INCR:
+ if (invmask==0) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil s = stencil[i];
+ if (s < STENCIL_MAX) {
+ stencil[i] = s+1;
+ }
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ /* VERIFY logic of adding 1 to a write-masked value */
+ GLstencil s = stencil[i];
+ if (s < STENCIL_MAX) {
+ stencil[i] = (invmask & s) | (wrtmask & (s+1));
+ }
+ }
+ }
+ }
+ break;
+ case GL_DECR:
+ if (invmask==0) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil s = stencil[i];
+ if (s>0) {
+ stencil[i] = s-1;
+ }
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ /* VERIFY logic of subtracting 1 to a write-masked value */
+ GLstencil s = stencil[i];
+ if (s>0) {
+ stencil[i] = (invmask & s) | (wrtmask & (s-1));
+ }
+ }
+ }
+ }
+ break;
+ case GL_INCR_WRAP_EXT:
+ if (invmask==0) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ stencil[i]++;
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil s = stencil[i];
+ stencil[i] = (invmask & s) | (wrtmask & (stencil[i]+1));
+ }
+ }
+ }
+ break;
+ case GL_DECR_WRAP_EXT:
+ if (invmask==0) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ stencil[i]--;
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil s = stencil[i];
+ stencil[i] = (invmask & s) | (wrtmask & (stencil[i]-1));
+ }
+ }
+ }
+ break;
+ case GL_INVERT:
+ if (invmask==0) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil s = stencil[i];
+ stencil[i] = ~s;
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil s = stencil[i];
+ stencil[i] = (invmask & s) | (wrtmask & ~s);
+ }
+ }
+ }
+ break;
+ default:
+ gl_problem(ctx, "Bad stencilop in apply_stencil_op_to_span");
+ }
+}
+
+
+
+
+/*
+ * Apply stencil test to a span of pixels before depth buffering.
+ * Input: n - number of pixels in the span
+ * x, y - coordinate of left-most pixel in the span
+ * mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel
+ * Output: mask - pixels which fail the stencil test will have their
+ * mask flag set to 0.
+ * Return: 0 = all pixels failed, 1 = zero or more pixels passed.
+ */
+GLint gl_stencil_span( GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLubyte mask[] )
+{
+ GLubyte fail[MAX_WIDTH];
+ GLint allfail = 0;
+ GLuint i;
+ GLstencil r, s;
+ GLstencil *stencil;
+
+ stencil = STENCIL_ADDRESS( x, y );
+
+ /*
+ * Perform stencil test. The results of this operation are stored
+ * in the fail[] array:
+ * IF fail[i] is non-zero THEN
+ * the stencil fail operator is to be applied
+ * ELSE
+ * the stencil fail operator is not to be applied
+ * ENDIF
+ */
+ switch (ctx->Stencil.Function) {
+ case GL_NEVER:
+ /* always fail */
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ mask[i] = 0;
+ fail[i] = 1;
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ allfail = 1;
+ break;
+ case GL_LESS:
+ r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ s = stencil[i] & ctx->Stencil.ValueMask;
+ if (r < s) {
+ /* passed */
+ fail[i] = 0;
+ }
+ else {
+ fail[i] = 1;
+ mask[i] = 0;
+ }
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ break;
+ case GL_LEQUAL:
+ r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ s = stencil[i] & ctx->Stencil.ValueMask;
+ if (r <= s) {
+ /* pass */
+ fail[i] = 0;
+ }
+ else {
+ fail[i] = 1;
+ mask[i] = 0;
+ }
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ break;
+ case GL_GREATER:
+ r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ s = stencil[i] & ctx->Stencil.ValueMask;
+ if (r > s) {
+ /* passed */
+ fail[i] = 0;
+ }
+ else {
+ fail[i] = 1;
+ mask[i] = 0;
+ }
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ break;
+ case GL_GEQUAL:
+ r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ s = stencil[i] & ctx->Stencil.ValueMask;
+ if (r >= s) {
+ /* passed */
+ fail[i] = 0;
+ }
+ else {
+ fail[i] = 1;
+ mask[i] = 0;
+ }
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ break;
+ case GL_EQUAL:
+ r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ s = stencil[i] & ctx->Stencil.ValueMask;
+ if (r == s) {
+ /* passed */
+ fail[i] = 0;
+ }
+ else {
+ fail[i] = 1;
+ mask[i] = 0;
+ }
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ break;
+ case GL_NOTEQUAL:
+ r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ s = stencil[i] & ctx->Stencil.ValueMask;
+ if (r != s) {
+ /* passed */
+ fail[i] = 0;
+ }
+ else {
+ fail[i] = 1;
+ mask[i] = 0;
+ }
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ break;
+ case GL_ALWAYS:
+ /* always pass */
+ for (i=0;i<n;i++) {
+ fail[i] = 0;
+ }
+ break;
+ default:
+ gl_problem(ctx, "Bad stencil func in gl_stencil_span");
+ return 0;
+ }
+
+ apply_stencil_op_to_span( ctx, n, x, y, ctx->Stencil.FailFunc, fail );
+
+ return (allfail) ? 0 : 1;
+}
+
+
+
+
+/*
+ * Apply the combination depth-buffer/stencil operator to a span of pixels.
+ * Input: n - number of pixels in the span
+ * x, y - location of leftmost pixel in span
+ * z - array [n] of z values
+ * Input: mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
+ * Output: mask - array [n] of flags (1=depth test passed, 0=failed)
+ */
+void gl_depth_stencil_span( GLcontext *ctx,
+ GLuint n, GLint x, GLint y, const GLdepth z[],
+ GLubyte mask[] )
+{
+ if (ctx->Depth.Test==GL_FALSE) {
+ /*
+ * No depth buffer, just apply zpass stencil function to active pixels.
+ */
+ apply_stencil_op_to_span( ctx, n, x, y, ctx->Stencil.ZPassFunc, mask );
+ }
+ else {
+ /*
+ * Perform depth buffering, then apply zpass or zfail stencil function.
+ */
+ GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH];
+ GLuint i;
+
+ /* init pass and fail masks to zero, copy mask[] to oldmask[] */
+ for (i=0;i<n;i++) {
+ passmask[i] = failmask[i] = 0;
+ oldmask[i] = mask[i];
+ }
+
+ /* apply the depth test */
+ if (ctx->Driver.DepthTestSpan)
+ (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
+
+ /* set the stencil pass/fail flags according to result of depth test */
+ for (i=0;i<n;i++) {
+ if (oldmask[i]) {
+ if (mask[i]) {
+ passmask[i] = 1;
+ }
+ else {
+ failmask[i] = 1;
+ }
+ }
+ }
+
+ /* apply the pass and fail operations */
+ apply_stencil_op_to_span( ctx, n, x, y, ctx->Stencil.ZFailFunc, failmask );
+ apply_stencil_op_to_span( ctx, n, x, y, ctx->Stencil.ZPassFunc, passmask );
+ }
+}
+
+
+
+
+/*
+ * Apply the given stencil operator for each pixel in the array whose
+ * mask flag is set.
+ * Input: n - number of pixels in the span
+ * x, y - array of [n] pixels
+ * operator - the stencil buffer operator
+ * mask - array [n] of flag: 1=apply operator, 0=don't apply operator
+ */
+static void apply_stencil_op_to_pixels( GLcontext *ctx,
+ GLuint n, const GLint x[],
+ const GLint y[],
+ GLenum oper, GLubyte mask[] )
+{
+ GLuint i;
+ GLstencil ref;
+ GLstencil wrtmask, invmask;
+
+ wrtmask = ctx->Stencil.WriteMask;
+ invmask = ~ctx->Stencil.WriteMask;
+
+ ref = ctx->Stencil.Ref;
+
+ switch (oper) {
+ case GL_KEEP:
+ /* do nothing */
+ break;
+ case GL_ZERO:
+ if (invmask==0) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
+ *sptr = 0;
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
+ *sptr = invmask & *sptr;
+ }
+ }
+ }
+ break;
+ case GL_REPLACE:
+ if (invmask==0) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
+ *sptr = ref;
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
+ *sptr = (invmask & *sptr ) | (wrtmask & ref);
+ }
+ }
+ }
+ break;
+ case GL_INCR:
+ if (invmask==0) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
+ if (*sptr < STENCIL_MAX) {
+ *sptr = *sptr + 1;
+ }
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
+ if (*sptr < STENCIL_MAX) {
+ *sptr = (invmask & *sptr) | (wrtmask & (*sptr+1));
+ }
+ }
+ }
+ }
+ break;
+ case GL_DECR:
+ if (invmask==0) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
+ if (*sptr>0) {
+ *sptr = *sptr - 1;
+ }
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
+ if (*sptr>0) {
+ *sptr = (invmask & *sptr) | (wrtmask & (*sptr-1));
+ }
+ }
+ }
+ }
+ break;
+ case GL_INCR_WRAP_EXT:
+ if (invmask==0) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
+ *sptr = *sptr + 1;
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
+ *sptr = (invmask & *sptr) | (wrtmask & (*sptr+1));
+ }
+ }
+ }
+ break;
+ case GL_DECR_WRAP_EXT:
+ if (invmask==0) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
+ *sptr = *sptr - 1;
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
+ *sptr = (invmask & *sptr) | (wrtmask & (*sptr-1));
+ }
+ }
+ }
+ break;
+ case GL_INVERT:
+ if (invmask==0) {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
+ *sptr = ~*sptr;
+ }
+ }
+ }
+ else {
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
+ *sptr = (invmask & *sptr) | (wrtmask & ~*sptr);
+ }
+ }
+ }
+ break;
+ default:
+ gl_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels");
+ }
+}
+
+
+
+/*
+ * Apply stencil test to an array of pixels before depth buffering.
+ * Input: n - number of pixels in the span
+ * x, y - array of [n] pixels to stencil
+ * mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel
+ * Output: mask - pixels which fail the stencil test will have their
+ * mask flag set to 0.
+ * Return: 0 = all pixels failed, 1 = zero or more pixels passed.
+ */
+GLint gl_stencil_pixels( GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte mask[] )
+{
+ GLubyte fail[PB_SIZE];
+ GLstencil r, s;
+ GLuint i;
+ GLint allfail = 0;
+
+ /*
+ * Perform stencil test. The results of this operation are stored
+ * in the fail[] array:
+ * IF fail[i] is non-zero THEN
+ * the stencil fail operator is to be applied
+ * ELSE
+ * the stencil fail operator is not to be applied
+ * ENDIF
+ */
+
+ switch (ctx->Stencil.Function) {
+ case GL_NEVER:
+ /* always fail */
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ mask[i] = 0;
+ fail[i] = 1;
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ allfail = 1;
+ break;
+ case GL_LESS:
+ r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
+ s = *sptr & ctx->Stencil.ValueMask;
+ if (r < s) {
+ /* passed */
+ fail[i] = 0;
+ }
+ else {
+ fail[i] = 1;
+ mask[i] = 0;
+ }
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ break;
+ case GL_LEQUAL:
+ r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
+ s = *sptr & ctx->Stencil.ValueMask;
+ if (r <= s) {
+ /* pass */
+ fail[i] = 0;
+ }
+ else {
+ fail[i] = 1;
+ mask[i] = 0;
+ }
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ break;
+ case GL_GREATER:
+ r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
+ s = *sptr & ctx->Stencil.ValueMask;
+ if (r > s) {
+ /* passed */
+ fail[i] = 0;
+ }
+ else {
+ fail[i] = 1;
+ mask[i] = 0;
+ }
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ break;
+ case GL_GEQUAL:
+ r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
+ s = *sptr & ctx->Stencil.ValueMask;
+ if (r >= s) {
+ /* passed */
+ fail[i] = 0;
+ }
+ else {
+ fail[i] = 1;
+ mask[i] = 0;
+ }
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ break;
+ case GL_EQUAL:
+ r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
+ s = *sptr & ctx->Stencil.ValueMask;
+ if (r == s) {
+ /* passed */
+ fail[i] = 0;
+ }
+ else {
+ fail[i] = 1;
+ mask[i] = 0;
+ }
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ break;
+ case GL_NOTEQUAL:
+ r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
+ for (i=0;i<n;i++) {
+ if (mask[i]) {
+ GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
+ s = *sptr & ctx->Stencil.ValueMask;
+ if (r != s) {
+ /* passed */
+ fail[i] = 0;
+ }
+ else {
+ fail[i] = 1;
+ mask[i] = 0;
+ }
+ }
+ else {
+ fail[i] = 0;
+ }
+ }
+ break;
+ case GL_ALWAYS:
+ /* always pass */
+ for (i=0;i<n;i++) {
+ fail[i] = 0;
+ }
+ break;
+ default:
+ gl_problem(ctx, "Bad stencil func in gl_stencil_pixels");
+ return 0;
+ }
+
+ apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc, fail );
+
+ return (allfail) ? 0 : 1;
+}
+
+
+
+
+/*
+ * Apply the combination depth-buffer/stencil operator to a span of pixels.
+ * Input: n - number of pixels in the span
+ * x, y - array of [n] pixels to stencil
+ * z - array [n] of z values
+ * Input: mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
+ * Output: mask - array [n] of flags (1=depth test passed, 0=failed)
+ */
+void gl_depth_stencil_pixels( GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLdepth z[], GLubyte mask[] )
+{
+ if (ctx->Depth.Test==GL_FALSE) {
+ /*
+ * No depth buffer, just apply zpass stencil function to active pixels.
+ */
+ apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.ZPassFunc, mask );
+ }
+ else {
+ /*
+ * Perform depth buffering, then apply zpass or zfail stencil function.
+ */
+ GLubyte passmask[PB_SIZE], failmask[PB_SIZE], oldmask[PB_SIZE];
+ GLuint i;
+
+ /* init pass and fail masks to zero */
+ for (i=0;i<n;i++) {
+ passmask[i] = failmask[i] = 0;
+ oldmask[i] = mask[i];
+ }
+
+ /* apply the depth test */
+ if (ctx->Driver.DepthTestPixels)
+ (*ctx->Driver.DepthTestPixels)( ctx, n, x, y, z, mask );
+
+ /* set the stencil pass/fail flags according to result of depth test */
+ for (i=0;i<n;i++) {
+ if (oldmask[i]) {
+ if (mask[i]) {
+ passmask[i] = 1;
+ }
+ else {
+ failmask[i] = 1;
+ }
+ }
+ }
+
+ /* apply the pass and fail operations */
+ apply_stencil_op_to_pixels( ctx, n, x, y,
+ ctx->Stencil.ZFailFunc, failmask );
+ apply_stencil_op_to_pixels( ctx, n, x, y,
+ ctx->Stencil.ZPassFunc, passmask );
+ }
+
+}
+
+
+
+/*
+ * Return a span of stencil values from the stencil buffer.
+ * Input: n - how many pixels
+ * x,y - location of first pixel
+ * Output: stencil - the array of stencil values
+ */
+void gl_read_stencil_span( GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLstencil stencil[] )
+{
+ if (ctx->Buffer->Stencil) {
+ const GLstencil *s = STENCIL_ADDRESS( x, y );
+#if STENCIL_BITS == 8
+ MEMCPY( stencil, s, n * sizeof(GLstencil) );
+#else
+ GLuint i;
+ for (i=0;i<n;i++)
+ stencil[i] = s[i];
+#endif
+ }
+}
+
+
+
+/*
+ * Write a span of stencil values to the stencil buffer.
+ * Input: n - how many pixels
+ * x,y - location of first pixel
+ * stencil - the array of stencil values
+ */
+void gl_write_stencil_span( GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLstencil stencil[] )
+{
+ if (ctx->Buffer->Stencil) {
+ GLstencil *s = STENCIL_ADDRESS( x, y );
+#if STENCIL_BITS == 8
+ MEMCPY( s, stencil, n * sizeof(GLstencil) );
+#else
+ GLuint i;
+ for (i=0;i<n;i++)
+ s[i] = stencil[i];
+#endif
+ }
+}
+
+
+
+/*
+ * Allocate a new stencil buffer. If there's an old one it will be
+ * deallocated first. The new stencil buffer will be uninitialized.
+ */
+void gl_alloc_stencil_buffer( GLcontext *ctx )
+{
+ GLuint buffersize = ctx->Buffer->Width * ctx->Buffer->Height;
+
+ /* deallocate current stencil buffer if present */
+ if (ctx->Buffer->Stencil) {
+ free(ctx->Buffer->Stencil);
+ ctx->Buffer->Stencil = NULL;
+ }
+
+ /* allocate new stencil buffer */
+ ctx->Buffer->Stencil = (GLstencil *) malloc(buffersize * sizeof(GLstencil));
+ if (!ctx->Buffer->Stencil) {
+ /* out of memory */
+ ctx->Stencil.Enabled = GL_FALSE;
+ gl_error( ctx, GL_OUT_OF_MEMORY, "gl_alloc_stencil_buffer" );
+ }
+}
+
+
+
+
+/*
+ * Clear the stencil buffer. If the stencil buffer doesn't exist yet we'll
+ * allocate it now.
+ */
+void gl_clear_stencil_buffer( GLcontext *ctx )
+{
+ if (ctx->Visual->StencilBits==0 || !ctx->Buffer->Stencil) {
+ /* no stencil buffer */
+ return;
+ }
+
+ if (ctx->Scissor.Enabled) {
+ /* clear scissor region only */
+ GLint y;
+ GLint width = ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1;
+ for (y=ctx->Buffer->Ymin; y<=ctx->Buffer->Ymax; y++) {
+ GLstencil *ptr = STENCIL_ADDRESS( ctx->Buffer->Xmin, y );
+#if STENCIL_BITS==8
+ MEMSET( ptr, ctx->Stencil.Clear, width * sizeof(GLstencil) );
+#else
+ GLint x;
+ for (x = 0; x < width; x++)
+ ptr[x] = ctx->Stencil.Clear;
+#endif
+ }
+ }
+ else {
+ /* clear whole stencil buffer */
+#if STENCIL_BITS==8
+ MEMSET( ctx->Buffer->Stencil, ctx->Stencil.Clear,
+ ctx->Buffer->Width * ctx->Buffer->Height * sizeof(GLstencil) );
+#else
+ GLuint i;
+ GLuint pixels = ctx->Buffer->Width * ctx->Buffer->Height;
+ GLstencil *buffer = ctx->Buffer->Stencil;
+ for (i = 0; i < pixels; i++)
+ ptr[i] = ctx->Stencil.Clear;
+#endif
+ }
+}
diff --git a/src/mesa/main/stencil.h b/src/mesa/main/stencil.h
new file mode 100644
index 0000000000..989cd988fe
--- /dev/null
+++ b/src/mesa/main/stencil.h
@@ -0,0 +1,88 @@
+/* $Id: stencil.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef STENCIL_H
+#define STENCIL_H
+
+
+#include "types.h"
+
+
+extern void gl_ClearStencil( GLcontext *ctx, GLint s );
+
+
+extern void gl_StencilFunc( GLcontext *ctx, GLenum func,
+ GLint ref, GLuint mask );
+
+
+extern void gl_StencilMask( GLcontext *ctx, GLuint mask );
+
+
+extern void gl_StencilOp( GLcontext *ctx, GLenum fail,
+ GLenum zfail, GLenum zpass );
+
+
+
+extern GLint gl_stencil_span( GLcontext *ctx,
+ GLuint n, GLint x, GLint y, GLubyte mask[] );
+
+
+extern void gl_depth_stencil_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
+ const GLdepth z[], GLubyte mask[] );
+
+
+extern GLint gl_stencil_pixels( GLcontext *ctx,
+ GLuint n, const GLint x[], const GLint y[],
+ GLubyte mask[] );
+
+
+extern void gl_depth_stencil_pixels( GLcontext *ctx,
+ GLuint n, const GLint x[],
+ const GLint y[], const GLdepth z[],
+ GLubyte mask[] );
+
+
+extern void gl_read_stencil_span( GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ GLstencil stencil[] );
+
+
+extern void gl_write_stencil_span( GLcontext *ctx,
+ GLuint n, GLint x, GLint y,
+ const GLstencil stencil[] );
+
+
+extern void gl_alloc_stencil_buffer( GLcontext *ctx );
+
+
+extern void gl_clear_stencil_buffer( GLcontext *ctx );
+
+
+#endif
diff --git a/src/mesa/main/teximage.c b/src/mesa/main/teximage.c
new file mode 100644
index 0000000000..f2f301e398
--- /dev/null
+++ b/src/mesa/main/teximage.c
@@ -0,0 +1,2344 @@
+/* $Id: teximage.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "context.h"
+#include "image.h"
+#include "macros.h"
+#include "mmath.h"
+#include "span.h"
+#include "teximage.h"
+#include "texstate.h"
+#include "types.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+/*
+ * NOTES:
+ *
+ * The internal texture storage convension is an array of N GLubytes
+ * where N = width * height * components. There is no padding.
+ */
+
+
+
+
+/*
+ * Compute log base 2 of n.
+ * If n isn't an exact power of two return -1.
+ * If n<0 return -1.
+ */
+static int logbase2( int n )
+{
+ GLint i = 1;
+ GLint log2 = 0;
+
+ if (n<0) {
+ return -1;
+ }
+
+ while ( n > i ) {
+ i *= 2;
+ log2++;
+ }
+ if (i != n) {
+ return -1;
+ }
+ else {
+ return log2;
+ }
+}
+
+
+
+/*
+ * Given an internal texture format enum or 1, 2, 3, 4 return the
+ * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
+ * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return -1 if
+ * invalid enum.
+ */
+static GLint decode_internal_format( GLint format )
+{
+ switch (format) {
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return GL_ALPHA;
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return GL_LUMINANCE;
+ 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:
+ return GL_LUMINANCE_ALPHA;
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ return GL_INTENSITY;
+ case 3:
+ case GL_RGB:
+ case GL_R3_G3_B2:
+ case GL_RGB4:
+ case GL_RGB5:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return GL_RGB;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA2:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return GL_RGBA;
+ 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 GL_COLOR_INDEX;
+ default:
+ return -1; /* error */
+ }
+}
+
+
+
+/*
+ * Given an internal texture format enum or 1, 2, 3, 4 return the
+ * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
+ * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the
+ * number of components for the format. Return -1 if invalid enum.
+ */
+static GLint components_in_intformat( GLint format )
+{
+ switch (format) {
+ case GL_ALPHA:
+ case GL_ALPHA4:
+ case GL_ALPHA8:
+ case GL_ALPHA12:
+ case GL_ALPHA16:
+ return 1;
+ case 1:
+ case GL_LUMINANCE:
+ case GL_LUMINANCE4:
+ case GL_LUMINANCE8:
+ case GL_LUMINANCE12:
+ case GL_LUMINANCE16:
+ return 1;
+ 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:
+ return 2;
+ case GL_INTENSITY:
+ case GL_INTENSITY4:
+ case GL_INTENSITY8:
+ case GL_INTENSITY12:
+ case GL_INTENSITY16:
+ return 1;
+ case 3:
+ case GL_RGB:
+ case GL_R3_G3_B2:
+ case GL_RGB4:
+ case GL_RGB5:
+ case GL_RGB8:
+ case GL_RGB10:
+ case GL_RGB12:
+ case GL_RGB16:
+ return 3;
+ case 4:
+ case GL_RGBA:
+ case GL_RGBA2:
+ case GL_RGBA4:
+ case GL_RGB5_A1:
+ case GL_RGBA8:
+ case GL_RGB10_A2:
+ case GL_RGBA12:
+ case GL_RGBA16:
+ return 4;
+ 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 1;
+ default:
+ return -1; /* error */
+ }
+}
+
+
+
+struct gl_texture_image *gl_alloc_texture_image( void )
+{
+ return (struct gl_texture_image *) calloc( 1, sizeof(struct gl_texture_image) );
+}
+
+
+
+void gl_free_texture_image( struct gl_texture_image *teximage )
+{
+ if (teximage->Data) {
+ free( teximage->Data );
+ }
+ free( teximage );
+}
+
+
+
+/*
+ * Examine the texImage->Format field and set the Red, Green, Blue, etc
+ * texel component sizes to default values.
+ * These fields are set only here by core Mesa but device drivers may
+ * overwritting these fields to indicate true texel resolution.
+ */
+static void set_teximage_component_sizes( struct gl_texture_image *texImage )
+{
+ switch (texImage->Format) {
+ case GL_ALPHA:
+ texImage->RedBits = 0;
+ texImage->GreenBits = 0;
+ texImage->BlueBits = 0;
+ texImage->AlphaBits = 8;
+ texImage->IntensityBits = 0;
+ texImage->LuminanceBits = 0;
+ texImage->IndexBits = 0;
+ break;
+ case GL_LUMINANCE:
+ texImage->RedBits = 0;
+ texImage->GreenBits = 0;
+ texImage->BlueBits = 0;
+ texImage->AlphaBits = 0;
+ texImage->IntensityBits = 0;
+ texImage->LuminanceBits = 8;
+ texImage->IndexBits = 0;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ texImage->RedBits = 0;
+ texImage->GreenBits = 0;
+ texImage->BlueBits = 0;
+ texImage->AlphaBits = 8;
+ texImage->IntensityBits = 0;
+ texImage->LuminanceBits = 8;
+ texImage->IndexBits = 0;
+ break;
+ case GL_INTENSITY:
+ texImage->RedBits = 0;
+ texImage->GreenBits = 0;
+ texImage->BlueBits = 0;
+ texImage->AlphaBits = 0;
+ texImage->IntensityBits = 8;
+ texImage->LuminanceBits = 0;
+ texImage->IndexBits = 0;
+ break;
+ case GL_RGB:
+ texImage->RedBits = 8;
+ texImage->GreenBits = 8;
+ texImage->BlueBits = 8;
+ texImage->AlphaBits = 0;
+ texImage->IntensityBits = 0;
+ texImage->LuminanceBits = 0;
+ texImage->IndexBits = 0;
+ break;
+ case GL_RGBA:
+ texImage->RedBits = 8;
+ texImage->GreenBits = 8;
+ texImage->BlueBits = 8;
+ texImage->AlphaBits = 8;
+ texImage->IntensityBits = 0;
+ texImage->LuminanceBits = 0;
+ texImage->IndexBits = 0;
+ break;
+ case GL_COLOR_INDEX:
+ texImage->RedBits = 0;
+ texImage->GreenBits = 0;
+ texImage->BlueBits = 0;
+ texImage->AlphaBits = 0;
+ texImage->IntensityBits = 0;
+ texImage->LuminanceBits = 0;
+ texImage->IndexBits = 8;
+ break;
+ default:
+ gl_problem(NULL, "unexpected format in set_teximage_component_sizes");
+ }
+}
+
+
+/* Need this to prevent an out-of-bounds memory access when using
+ * X86 optimized code.
+ */
+#ifdef USE_X86_ASM
+# define EXTRA_BYTE 1
+#else
+# define EXTRA_BYTE 0
+#endif
+
+
+/*
+ * Given a gl_image, apply the pixel transfer scale, bias, and mapping
+ * to produce a gl_texture_image. Convert image data to GLubytes.
+ * Input: image - the incoming gl_image
+ * internalFormat - desired format of resultant texture
+ * border - texture border width (0 or 1)
+ * Return: pointer to a gl_texture_image or NULL if an error occurs.
+ */
+static struct gl_texture_image *
+image_to_texture( GLcontext *ctx, const struct gl_image *image,
+ GLint internalFormat, GLint border )
+{
+ GLint components;
+ struct gl_texture_image *texImage;
+ GLint numPixels, pixel;
+ GLboolean scaleOrBias;
+
+ assert(image);
+ assert(image->Width>0);
+ assert(image->Height>0);
+ assert(image->Depth>0);
+
+ /* internalFormat = decode_internal_format(internalFormat);*/
+ components = components_in_intformat(internalFormat);
+ numPixels = image->Width * image->Height * image->Depth;
+
+ texImage = gl_alloc_texture_image();
+ if (!texImage)
+ return NULL;
+
+ texImage->Format = (GLenum) decode_internal_format(internalFormat);
+ set_teximage_component_sizes( texImage );
+ texImage->IntFormat = (GLenum) internalFormat;
+ texImage->Border = border;
+ texImage->Width = image->Width;
+ texImage->Height = image->Height;
+ texImage->Depth = image->Depth;
+ texImage->WidthLog2 = logbase2(image->Width - 2*border);
+ if (image->Height==1) /* 1-D texture */
+ texImage->HeightLog2 = 0;
+ else
+ texImage->HeightLog2 = logbase2(image->Height - 2*border);
+ if (image->Depth==1) /* 2-D texture */
+ texImage->DepthLog2 = 0;
+ else
+ texImage->DepthLog2 = logbase2(image->Depth - 2*border);
+ texImage->Width2 = 1 << texImage->WidthLog2;
+ texImage->Height2 = 1 << texImage->HeightLog2;
+ texImage->Depth2 = 1 << texImage->DepthLog2;
+ texImage->MaxLog2 = MAX2( texImage->WidthLog2, texImage->HeightLog2 );
+ texImage->Data = (GLubyte *) malloc( numPixels * components + EXTRA_BYTE );
+
+ if (!texImage->Data) {
+ /* out of memory */
+ gl_free_texture_image( texImage );
+ return NULL;
+ }
+
+ /* Determine if scaling and/or biasing is needed */
+ if (ctx->Pixel.RedScale!=1.0F || ctx->Pixel.RedBias!=0.0F ||
+ ctx->Pixel.GreenScale!=1.0F || ctx->Pixel.GreenBias!=0.0F ||
+ ctx->Pixel.BlueScale!=1.0F || ctx->Pixel.BlueBias!=0.0F ||
+ ctx->Pixel.AlphaScale!=1.0F || ctx->Pixel.AlphaBias!=0.0F) {
+ scaleOrBias = GL_TRUE;
+ }
+ else {
+ scaleOrBias = GL_FALSE;
+ }
+
+ switch (image->Type) {
+ case GL_BITMAP:
+ {
+ GLint shift = ctx->Pixel.IndexShift;
+ GLint offset = ctx->Pixel.IndexOffset;
+ /* MapIto[RGBA]Size must be powers of two */
+ GLint rMask = ctx->Pixel.MapItoRsize-1;
+ GLint gMask = ctx->Pixel.MapItoGsize-1;
+ GLint bMask = ctx->Pixel.MapItoBsize-1;
+ GLint aMask = ctx->Pixel.MapItoAsize-1;
+ GLint i, j;
+ GLubyte *srcPtr = (GLubyte *) image->Data;
+
+ assert( image->Format==GL_COLOR_INDEX );
+
+ for (j=0; j<image->Height; j++) {
+ GLubyte bitMask = 128;
+ for (i=0; i<image->Width; i++) {
+ GLint index;
+ GLubyte red, green, blue, alpha;
+
+ /* Fetch image color index */
+ index = (*srcPtr & bitMask) ? 1 : 0;
+ bitMask = bitMask >> 1;
+ if (bitMask==0) {
+ bitMask = 128;
+ srcPtr++;
+ }
+ /* apply index shift and offset */
+ if (shift>=0) {
+ index = (index << shift) + offset;
+ }
+ else {
+ index = (index >> -shift) + offset;
+ }
+ /* convert index to RGBA */
+ red = (GLint) (ctx->Pixel.MapItoR[index & rMask] * 255.0F);
+ green = (GLint) (ctx->Pixel.MapItoG[index & gMask] * 255.0F);
+ blue = (GLint) (ctx->Pixel.MapItoB[index & bMask] * 255.0F);
+ alpha = (GLint) (ctx->Pixel.MapItoA[index & aMask] * 255.0F);
+
+ /* store texel (components are GLubytes in [0,255]) */
+ pixel = j * image->Width + i;
+ switch (texImage->Format) {
+ case GL_ALPHA:
+ texImage->Data[pixel] = alpha;
+ break;
+ case GL_LUMINANCE:
+ texImage->Data[pixel] = red;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ texImage->Data[pixel*2+0] = red;
+ texImage->Data[pixel*2+1] = alpha;
+ break;
+ case GL_INTENSITY:
+ texImage->Data[pixel] = red;
+ break;
+ case GL_RGB:
+ texImage->Data[pixel*3+0] = red;
+ texImage->Data[pixel*3+1] = green;
+ texImage->Data[pixel*3+2] = blue;
+ break;
+ case GL_RGBA:
+ texImage->Data[pixel*4+0] = red;
+ texImage->Data[pixel*4+1] = green;
+ texImage->Data[pixel*4+2] = blue;
+ texImage->Data[pixel*4+3] = alpha;
+ break;
+ default:
+ gl_problem(ctx,"Bad format in image_to_texture");
+ return NULL;
+ }
+ }
+ if (bitMask!=128) {
+ srcPtr++;
+ }
+ }
+ }
+ break;
+
+ case GL_UNSIGNED_BYTE:
+ if (image->Format == texImage->Format && !scaleOrBias && !ctx->Pixel.MapColorFlag) {
+ switch (image->Format) {
+ case GL_COLOR_INDEX:
+ if (decode_internal_format(internalFormat)!=GL_COLOR_INDEX) {
+ /* convert color index to RGBA */
+ for (pixel=0; pixel<numPixels; pixel++) {
+ GLint index = ((GLubyte*)image->Data)[pixel];
+ index = (GLint) (255.0F * ctx->Pixel.MapItoR[index]);
+ texImage->Data[pixel] = index;
+ }
+ numPixels = 0;
+ break;
+ }
+ case GL_ALPHA:
+ case GL_LUMINANCE:
+ case GL_INTENSITY:
+ MEMCPY(texImage->Data, image->Data, numPixels * 1);
+ numPixels = 0;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ MEMCPY(texImage->Data, image->Data, numPixels * 2);
+ numPixels = 0;
+ break;
+ case GL_RGB:
+ MEMCPY(texImage->Data, image->Data, numPixels * 3);
+ numPixels = 0;
+ break;
+ case GL_RGBA:
+ MEMCPY(texImage->Data, image->Data, numPixels * 4);
+ numPixels = 0;
+ break;
+ default:
+ break;
+ }
+ }
+ for (pixel=0; pixel<numPixels; pixel++) {
+ GLubyte red, green, blue, alpha;
+ switch (image->Format) {
+ case GL_COLOR_INDEX:
+ if (decode_internal_format(internalFormat)==GL_COLOR_INDEX) {
+ /* a paletted texture */
+ GLint index = ((GLubyte*)image->Data)[pixel];
+ red = index;
+ }
+ else {
+ /* convert color index to RGBA */
+ GLint index = ((GLubyte*)image->Data)[pixel];
+ red = (GLint) (255.0F * ctx->Pixel.MapItoR[index]);
+ green = (GLint) (255.0F * ctx->Pixel.MapItoG[index]);
+ blue = (GLint) (255.0F * ctx->Pixel.MapItoB[index]);
+ alpha = (GLint) (255.0F * ctx->Pixel.MapItoA[index]);
+ }
+ break;
+ case GL_RGB:
+ /* Fetch image RGBA values */
+ red = ((GLubyte*) image->Data)[pixel*3+0];
+ green = ((GLubyte*) image->Data)[pixel*3+1];
+ blue = ((GLubyte*) image->Data)[pixel*3+2];
+ alpha = 255;
+ break;
+ case GL_RGBA:
+ red = ((GLubyte*) image->Data)[pixel*4+0];
+ green = ((GLubyte*) image->Data)[pixel*4+1];
+ blue = ((GLubyte*) image->Data)[pixel*4+2];
+ alpha = ((GLubyte*) image->Data)[pixel*4+3];
+ break;
+ case GL_RED:
+ red = ((GLubyte*) image->Data)[pixel];
+ green = 0;
+ blue = 0;
+ alpha = 255;
+ break;
+ case GL_GREEN:
+ red = 0;
+ green = ((GLubyte*) image->Data)[pixel];
+ blue = 0;
+ alpha = 255;
+ break;
+ case GL_BLUE:
+ red = 0;
+ green = 0;
+ blue = ((GLubyte*) image->Data)[pixel];
+ alpha = 255;
+ break;
+ case GL_ALPHA:
+ red = 0;
+ green = 0;
+ blue = 0;
+ alpha = ((GLubyte*) image->Data)[pixel];
+ break;
+ case GL_LUMINANCE:
+ red = ((GLubyte*) image->Data)[pixel];
+ green = red;
+ blue = red;
+ alpha = 255;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ red = ((GLubyte*) image->Data)[pixel*2+0];
+ green = red;
+ blue = red;
+ alpha = ((GLubyte*) image->Data)[pixel*2+1];
+ break;
+ default:
+ gl_problem(ctx,"Bad format (2) in image_to_texture");
+ return NULL;
+ }
+
+ if (scaleOrBias || ctx->Pixel.MapColorFlag) {
+ /* Apply RGBA scale and bias */
+ GLfloat r = UBYTE_COLOR_TO_FLOAT_COLOR(red);
+ GLfloat g = UBYTE_COLOR_TO_FLOAT_COLOR(green);
+ GLfloat b = UBYTE_COLOR_TO_FLOAT_COLOR(blue);
+ GLfloat a = UBYTE_COLOR_TO_FLOAT_COLOR(alpha);
+ if (scaleOrBias) {
+ /* r,g,b,a now in [0,1] */
+ r = r * ctx->Pixel.RedScale + ctx->Pixel.RedBias;
+ g = g * ctx->Pixel.GreenScale + ctx->Pixel.GreenBias;
+ b = b * ctx->Pixel.BlueScale + ctx->Pixel.BlueBias;
+ a = a * ctx->Pixel.AlphaScale + ctx->Pixel.AlphaBias;
+ r = CLAMP( r, 0.0F, 1.0F );
+ g = CLAMP( g, 0.0F, 1.0F );
+ b = CLAMP( b, 0.0F, 1.0F );
+ a = CLAMP( a, 0.0F, 1.0F );
+ }
+ /* Apply pixel maps */
+ if (ctx->Pixel.MapColorFlag) {
+ GLint ir = (GLint) (r*ctx->Pixel.MapRtoRsize);
+ GLint ig = (GLint) (g*ctx->Pixel.MapGtoGsize);
+ GLint ib = (GLint) (b*ctx->Pixel.MapBtoBsize);
+ GLint ia = (GLint) (a*ctx->Pixel.MapAtoAsize);
+ r = ctx->Pixel.MapRtoR[ir];
+ g = ctx->Pixel.MapGtoG[ig];
+ b = ctx->Pixel.MapBtoB[ib];
+ a = ctx->Pixel.MapAtoA[ia];
+ }
+ red = (GLint) (r * 255.0F);
+ green = (GLint) (g * 255.0F);
+ blue = (GLint) (b * 255.0F);
+ alpha = (GLint) (a * 255.0F);
+ }
+
+ /* store texel (components are GLubytes in [0,255]) */
+ switch (texImage->Format) {
+ case GL_COLOR_INDEX:
+ texImage->Data[pixel] = red; /* really an index */
+ break;
+ case GL_ALPHA:
+ texImage->Data[pixel] = alpha;
+ break;
+ case GL_LUMINANCE:
+ texImage->Data[pixel] = red;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ texImage->Data[pixel*2+0] = red;
+ texImage->Data[pixel*2+1] = alpha;
+ break;
+ case GL_INTENSITY:
+ texImage->Data[pixel] = red;
+ break;
+ case GL_RGB:
+ texImage->Data[pixel*3+0] = red;
+ texImage->Data[pixel*3+1] = green;
+ texImage->Data[pixel*3+2] = blue;
+ break;
+ case GL_RGBA:
+ texImage->Data[pixel*4+0] = red;
+ texImage->Data[pixel*4+1] = green;
+ texImage->Data[pixel*4+2] = blue;
+ texImage->Data[pixel*4+3] = alpha;
+ break;
+ default:
+ gl_problem(ctx,"Bad format (3) in image_to_texture");
+ return NULL;
+ }
+ }
+ break;
+
+ case GL_FLOAT:
+ for (pixel=0; pixel<numPixels; pixel++) {
+ GLfloat red, green, blue, alpha;
+ switch (image->Format) {
+ case GL_COLOR_INDEX:
+ if (decode_internal_format(internalFormat)==GL_COLOR_INDEX) {
+ /* a paletted texture */
+ GLint index = (GLint) ((GLfloat*) image->Data)[pixel];
+ red = index;
+ }
+ else {
+ GLint shift = ctx->Pixel.IndexShift;
+ GLint offset = ctx->Pixel.IndexOffset;
+ /* MapIto[RGBA]Size must be powers of two */
+ GLint rMask = ctx->Pixel.MapItoRsize-1;
+ GLint gMask = ctx->Pixel.MapItoGsize-1;
+ GLint bMask = ctx->Pixel.MapItoBsize-1;
+ GLint aMask = ctx->Pixel.MapItoAsize-1;
+ /* Fetch image color index */
+ GLint index = (GLint) ((GLfloat*) image->Data)[pixel];
+ /* apply index shift and offset */
+ if (shift>=0) {
+ index = (index << shift) + offset;
+ }
+ else {
+ index = (index >> -shift) + offset;
+ }
+ /* convert index to RGBA */
+ red = ctx->Pixel.MapItoR[index & rMask];
+ green = ctx->Pixel.MapItoG[index & gMask];
+ blue = ctx->Pixel.MapItoB[index & bMask];
+ alpha = ctx->Pixel.MapItoA[index & aMask];
+ }
+ break;
+ case GL_RGB:
+ /* Fetch image RGBA values */
+ red = ((GLfloat*) image->Data)[pixel*3+0];
+ green = ((GLfloat*) image->Data)[pixel*3+1];
+ blue = ((GLfloat*) image->Data)[pixel*3+2];
+ alpha = 1.0;
+ break;
+ case GL_RGBA:
+ red = ((GLfloat*) image->Data)[pixel*4+0];
+ green = ((GLfloat*) image->Data)[pixel*4+1];
+ blue = ((GLfloat*) image->Data)[pixel*4+2];
+ alpha = ((GLfloat*) image->Data)[pixel*4+3];
+ break;
+ case GL_RED:
+ red = ((GLfloat*) image->Data)[pixel];
+ green = 0.0;
+ blue = 0.0;
+ alpha = 1.0;
+ break;
+ case GL_GREEN:
+ red = 0.0;
+ green = ((GLfloat*) image->Data)[pixel];
+ blue = 0.0;
+ alpha = 1.0;
+ break;
+ case GL_BLUE:
+ red = 0.0;
+ green = 0.0;
+ blue = ((GLfloat*) image->Data)[pixel];
+ alpha = 1.0;
+ break;
+ case GL_ALPHA:
+ red = 0.0;
+ green = 0.0;
+ blue = 0.0;
+ alpha = ((GLfloat*) image->Data)[pixel];
+ break;
+ case GL_LUMINANCE:
+ red = ((GLfloat*) image->Data)[pixel];
+ green = red;
+ blue = red;
+ alpha = 1.0;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ red = ((GLfloat*) image->Data)[pixel*2+0];
+ green = red;
+ blue = red;
+ alpha = ((GLfloat*) image->Data)[pixel*2+1];
+ break;
+ default:
+ gl_problem(ctx,"Bad format (4) in image_to_texture");
+ return NULL;
+ }
+
+ if (image->Format!=GL_COLOR_INDEX) {
+ /* Apply RGBA scale and bias */
+ if (scaleOrBias) {
+ red = red * ctx->Pixel.RedScale + ctx->Pixel.RedBias;
+ green = green * ctx->Pixel.GreenScale + ctx->Pixel.GreenBias;
+ blue = blue * ctx->Pixel.BlueScale + ctx->Pixel.BlueBias;
+ alpha = alpha * ctx->Pixel.AlphaScale + ctx->Pixel.AlphaBias;
+ red = CLAMP( red, 0.0F, 1.0F );
+ green = CLAMP( green, 0.0F, 1.0F );
+ blue = CLAMP( blue, 0.0F, 1.0F );
+ alpha = CLAMP( alpha, 0.0F, 1.0F );
+ }
+ /* Apply pixel maps */
+ if (ctx->Pixel.MapColorFlag) {
+ GLint ir = (GLint) (red *ctx->Pixel.MapRtoRsize);
+ GLint ig = (GLint) (green*ctx->Pixel.MapGtoGsize);
+ GLint ib = (GLint) (blue *ctx->Pixel.MapBtoBsize);
+ GLint ia = (GLint) (alpha*ctx->Pixel.MapAtoAsize);
+ red = ctx->Pixel.MapRtoR[ir];
+ green = ctx->Pixel.MapGtoG[ig];
+ blue = ctx->Pixel.MapBtoB[ib];
+ alpha = ctx->Pixel.MapAtoA[ia];
+ }
+ }
+
+ /* store texel (components are GLubytes in [0,255]) */
+ switch (texImage->Format) {
+ case GL_COLOR_INDEX:
+ /* a paletted texture */
+ texImage->Data[pixel] = (GLint) (red * 255.0F);
+ break;
+ case GL_ALPHA:
+ texImage->Data[pixel] = (GLint) (alpha * 255.0F);
+ break;
+ case GL_LUMINANCE:
+ texImage->Data[pixel] = (GLint) (red * 255.0F);
+ break;
+ case GL_LUMINANCE_ALPHA:
+ texImage->Data[pixel*2+0] = (GLint) (red * 255.0F);
+ texImage->Data[pixel*2+1] = (GLint) (alpha * 255.0F);
+ break;
+ case GL_INTENSITY:
+ texImage->Data[pixel] = (GLint) (red * 255.0F);
+ break;
+ case GL_RGB:
+ texImage->Data[pixel*3+0] = (GLint) (red * 255.0F);
+ texImage->Data[pixel*3+1] = (GLint) (green * 255.0F);
+ texImage->Data[pixel*3+2] = (GLint) (blue * 255.0F);
+ break;
+ case GL_RGBA:
+ texImage->Data[pixel*4+0] = (GLint) (red * 255.0F);
+ texImage->Data[pixel*4+1] = (GLint) (green * 255.0F);
+ texImage->Data[pixel*4+2] = (GLint) (blue * 255.0F);
+ texImage->Data[pixel*4+3] = (GLint) (alpha * 255.0F);
+ break;
+ default:
+ gl_problem(ctx,"Bad format (5) in image_to_texture");
+ return NULL;
+ }
+ }
+ break;
+
+ default:
+ gl_problem(ctx, "Bad image type in image_to_texture");
+ return NULL;
+ }
+
+ return texImage;
+}
+
+
+
+/*
+ * glTexImage[123]D can accept a NULL image pointer. In this case we
+ * create a texture image with unspecified image contents per the OpenGL
+ * spec.
+ */
+static struct gl_texture_image *
+make_null_texture( GLcontext *ctx, GLenum internalFormat,
+ GLsizei width, GLsizei height, GLsizei depth, GLint border )
+{
+ GLint components;
+ struct gl_texture_image *texImage;
+ GLint numPixels;
+ (void) ctx;
+
+ /*internalFormat = decode_internal_format(internalFormat);*/
+ components = components_in_intformat(internalFormat);
+ numPixels = width * height * depth;
+
+ texImage = gl_alloc_texture_image();
+ if (!texImage)
+ return NULL;
+
+ texImage->Format = (GLenum) decode_internal_format(internalFormat);
+ set_teximage_component_sizes( texImage );
+ texImage->IntFormat = internalFormat;
+ texImage->Border = border;
+ texImage->Width = width;
+ texImage->Height = height;
+ texImage->Depth = depth;
+ texImage->WidthLog2 = logbase2(width - 2*border);
+ if (height==1) /* 1-D texture */
+ texImage->HeightLog2 = 0;
+ else
+ texImage->HeightLog2 = logbase2(height - 2*border);
+ if (depth==1) /* 2-D texture */
+ texImage->DepthLog2 = 0;
+ else
+ texImage->DepthLog2 = logbase2(depth - 2*border);
+ texImage->Width2 = 1 << texImage->WidthLog2;
+ texImage->Height2 = 1 << texImage->HeightLog2;
+ texImage->Depth2 = 1 << texImage->DepthLog2;
+ texImage->MaxLog2 = MAX2( texImage->WidthLog2, texImage->HeightLog2 );
+
+ /* XXX should we really allocate memory for the image or let it be NULL? */
+ /*texImage->Data = NULL;*/
+
+ texImage->Data = (GLubyte *) malloc( numPixels * components + EXTRA_BYTE );
+
+ /*
+ * Let's see if anyone finds this. If glTexImage2D() is called with
+ * a NULL image pointer then load the texture image with something
+ * interesting instead of leaving it indeterminate.
+ */
+ if (texImage->Data) {
+ char message[8][32] = {
+ " X X XXXXX XXX X ",
+ " XX XX X X X X X ",
+ " X X X X X X X ",
+ " X X XXXX XXX XXXXX ",
+ " X X X X X X ",
+ " X X X X X X X ",
+ " X X XXXXX XXX X X ",
+ " "
+ };
+
+ GLubyte *imgPtr = texImage->Data;
+ GLint i, j, k;
+ for (i=0;i<height;i++) {
+ GLint srcRow = 7 - i % 8;
+ for (j=0;j<width;j++) {
+ GLint srcCol = j % 32;
+ GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
+ for (k=0;k<components;k++) {
+ *imgPtr++ = texel;
+ }
+ }
+ }
+ }
+
+ return texImage;
+}
+
+
+
+/*
+ * Test glTexImage() parameters for errors.
+ * Input:
+ * dimensions - must be 1 or 2 or 3
+ * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
+ */
+static GLboolean texture_error_check( GLcontext *ctx, GLenum target,
+ GLint level, GLint internalFormat,
+ GLenum format, GLenum type,
+ GLint dimensions,
+ GLint width, GLint height,
+ GLint depth, GLint border )
+{
+ GLboolean isProxy;
+ GLint iformat;
+
+ if (dimensions == 1) {
+ isProxy = (target == GL_PROXY_TEXTURE_1D);
+ if (target != GL_TEXTURE_1D && !isProxy) {
+ gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
+ return GL_TRUE;
+ }
+ }
+ else if (dimensions == 2) {
+ isProxy = (target == GL_PROXY_TEXTURE_2D);
+ if (target != GL_TEXTURE_2D && !isProxy) {
+ gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
+ return GL_TRUE;
+ }
+ }
+ else if (dimensions == 3) {
+ isProxy = (target == GL_PROXY_TEXTURE_3D);
+ if (target != GL_TEXTURE_3D && !isProxy) {
+ gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
+ return GL_TRUE;
+ }
+ }
+ else {
+ gl_problem( ctx, "bad dims in texture_error_check" );
+ return GL_TRUE;
+ }
+
+ /* Border */
+ if (border!=0 && border!=1) {
+ if (!isProxy) {
+ if (dimensions == 1)
+ gl_error( ctx, GL_INVALID_VALUE, "glTexImage1D(border)" );
+ else if (dimensions == 2)
+ gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(border)" );
+ else if (dimensions == 3)
+ gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(border)" );
+ }
+ return GL_TRUE;
+ }
+
+ /* Width */
+ if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
+ || logbase2( width - 2 * border ) < 0) {
+ if (!isProxy) {
+ if (dimensions == 1)
+ gl_error( ctx, GL_INVALID_VALUE, "glTexImage1D(width)" );
+ else if (dimensions == 2)
+ gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(width)" );
+ else if (dimensions == 3)
+ gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(width)" );
+ }
+ return GL_TRUE;
+ }
+
+ /* Height */
+ if (dimensions >= 2) {
+ if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
+ || logbase2( height - 2 * border ) < 0) {
+ if (!isProxy) {
+ if (dimensions == 2)
+ gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(height)" );
+ else if (dimensions == 3)
+ gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(height)" );
+ return GL_TRUE;
+ }
+ }
+ }
+
+ /* Depth */
+ if (dimensions >= 3) {
+ if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize
+ || logbase2( depth - 2 * border ) < 0) {
+ if (!isProxy) {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(depth)" );
+ }
+ return GL_TRUE;
+ }
+ }
+
+ /* Level */
+ if (level<0 || level>=ctx->Const.MaxTextureLevels) {
+ if (dimensions == 1)
+ gl_error( ctx, GL_INVALID_VALUE, "glTexImage1D(level)" );
+ else if (dimensions == 2)
+ gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(level)" );
+ else if (dimensions == 3)
+ gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(level)" );
+ return GL_TRUE;
+ }
+
+ iformat = decode_internal_format( internalFormat );
+ if (iformat < 0) {
+ if (dimensions == 1)
+ gl_error( ctx, GL_INVALID_VALUE, "glTexImage1D(internalFormat)" );
+ else if (dimensions == 2)
+ gl_error( ctx, GL_INVALID_VALUE, "glTexImage2D(internalFormat)" );
+ else if (dimensions == 3)
+ gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(internalFormat)" );
+ return GL_TRUE;
+ }
+
+ if (!gl_is_legal_format_and_type( format, type )) {
+ if (dimensions == 1)
+ gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(format or type)");
+ else if (dimensions == 2)
+ gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(format or type)");
+ else if (dimensions == 3)
+ gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(format or type)");
+ return GL_TRUE;
+ }
+
+ /* if we get here, the parameters are OK */
+ return GL_FALSE;
+}
+
+
+
+/*
+ * Called from the API. Note that width includes the border.
+ */
+void gl_TexImage1D( GLcontext *ctx,
+ GLenum target, GLint level, GLint internalformat,
+ GLsizei width, GLint border, GLenum format,
+ GLenum type, struct gl_image *image )
+{
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D");
+
+ if (target==GL_TEXTURE_1D) {
+ struct gl_texture_image *teximage;
+ if (texture_error_check( ctx, target, level, internalformat,
+ format, type, 1, width, 1, 1, border )) {
+ /* error in texture image was detected */
+ return;
+ }
+
+ /* free current texture image, if any */
+ if (texUnit->CurrentD[1]->Image[level]) {
+ gl_free_texture_image( texUnit->CurrentD[1]->Image[level] );
+ }
+
+ /* make new texture from source image */
+ if (image) {
+ teximage = image_to_texture(ctx, image, internalformat, border);
+ }
+ else {
+ teximage = make_null_texture(ctx, (GLenum) internalformat,
+ width, 1, 1, border);
+ }
+
+ /* install new texture image */
+
+ texUnit->CurrentD[1]->Image[level] = teximage;
+ gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] );
+ ctx->NewState |= NEW_TEXTURING;
+
+ /* free the source image */
+ if (image && image->RefCount==0) {
+ /* if RefCount>0 then image must be in a display list */
+ gl_free_image(image);
+ }
+
+ /* tell driver about change */
+ if (ctx->Driver.TexImage) {
+ (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D,
+ texUnit->CurrentD[1],
+ level, internalformat, teximage );
+ }
+ }
+ else if (target==GL_PROXY_TEXTURE_1D) {
+ /* Proxy texture: check for errors and update proxy state */
+ if (texture_error_check( ctx, target, level, internalformat,
+ format, type, 1, width, 1, 1, border )) {
+ if (level>=0 && level<ctx->Const.MaxTextureLevels) {
+ MEMSET( ctx->Texture.Proxy1D->Image[level], 0,
+ sizeof(struct gl_texture_image) );
+ }
+ }
+ else {
+ ctx->Texture.Proxy1D->Image[level]->Format = (GLenum) format;
+ set_teximage_component_sizes( ctx->Texture.Proxy1D->Image[level] );
+ ctx->Texture.Proxy1D->Image[level]->IntFormat = (GLenum) internalformat;
+ ctx->Texture.Proxy1D->Image[level]->Border = border;
+ ctx->Texture.Proxy1D->Image[level]->Width = width;
+ ctx->Texture.Proxy1D->Image[level]->Height = 1;
+ ctx->Texture.Proxy1D->Image[level]->Depth = 1;
+ }
+ if (image && image->RefCount==0) {
+ /* if RefCount>0 then image must be in a display list */
+ gl_free_image(image);
+ }
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
+ return;
+ }
+}
+
+
+
+
+/*
+ * Called by the API or display list executor.
+ * Note that width and height include the border.
+ */
+void gl_TexImage2D( GLcontext *ctx,
+ GLenum target, GLint level, GLint internalformat,
+ GLsizei width, GLsizei height, GLint border,
+ GLenum format, GLenum type,
+ struct gl_image *image )
+{
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D");
+
+ if (target==GL_TEXTURE_2D) {
+ struct gl_texture_image *teximage;
+ if (texture_error_check( ctx, target, level, internalformat,
+ format, type, 2, width, height, 1, border )) {
+ /* error in texture image was detected */
+ return;
+ }
+
+ /* free current texture image, if any */
+ if (texUnit->CurrentD[2]->Image[level]) {
+ gl_free_texture_image( texUnit->CurrentD[2]->Image[level] );
+ }
+
+ /* make new texture from source image */
+ if (image) {
+ teximage = image_to_texture(ctx, image, internalformat, border);
+ }
+ else {
+ teximage = make_null_texture(ctx, (GLenum) internalformat,
+ width, height, 1, border);
+ }
+
+ /* install new texture image */
+ texUnit->CurrentD[2]->Image[level] = teximage;
+ gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[2] );
+ ctx->NewState |= NEW_TEXTURING;
+
+ /* free the source image */
+ if (image && image->RefCount==0) {
+ /* if RefCount>0 then image must be in a display list */
+ gl_free_image(image);
+ }
+
+ /* tell driver about change */
+ if (ctx->Driver.TexImage) {
+ (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D,
+ texUnit->CurrentD[2],
+ level, internalformat, teximage );
+ }
+ }
+ else if (target==GL_PROXY_TEXTURE_2D) {
+ /* Proxy texture: check for errors and update proxy state */
+ if (texture_error_check( ctx, target, level, internalformat,
+ format, type, 2, width, height, 1, border )) {
+ if (level>=0 && level<ctx->Const.MaxTextureLevels) {
+ MEMSET( ctx->Texture.Proxy2D->Image[level], 0,
+ sizeof(struct gl_texture_image) );
+ }
+ }
+ else {
+ ctx->Texture.Proxy2D->Image[level]->Format = (GLenum) format;
+ set_teximage_component_sizes( ctx->Texture.Proxy2D->Image[level] );
+ ctx->Texture.Proxy2D->Image[level]->IntFormat = (GLenum) internalformat;
+ ctx->Texture.Proxy2D->Image[level]->Border = border;
+ ctx->Texture.Proxy2D->Image[level]->Width = width;
+ ctx->Texture.Proxy2D->Image[level]->Height = height;
+ ctx->Texture.Proxy2D->Image[level]->Depth = 1;
+ }
+ if (image && image->RefCount==0) {
+ /* if RefCount>0 then image must be in a display list */
+ gl_free_image(image);
+ }
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
+ return;
+ }
+}
+
+
+
+/*
+ * Called by the API or display list executor.
+ * Note that width and height include the border.
+ */
+void gl_TexImage3DEXT( GLcontext *ctx,
+ GLenum target, GLint level, GLint internalformat,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLint border, GLenum format, GLenum type,
+ struct gl_image *image )
+{
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3DEXT");
+
+ if (target==GL_TEXTURE_3D_EXT) {
+ struct gl_texture_image *teximage;
+ if (texture_error_check( ctx, target, level, internalformat,
+ format, type, 3, width, height, depth,
+ border )) {
+ /* error in texture image was detected */
+ return;
+ }
+
+ /* free current texture image, if any */
+ if (texUnit->CurrentD[3]->Image[level]) {
+ gl_free_texture_image( texUnit->CurrentD[3]->Image[level] );
+ }
+
+ /* make new texture from source image */
+ if (image) {
+ teximage = image_to_texture(ctx, image, internalformat, border);
+ }
+ else {
+ teximage = make_null_texture(ctx, (GLenum) internalformat,
+ width, height, depth, border);
+ }
+
+ /* install new texture image */
+ texUnit->CurrentD[3]->Image[level] = teximage;
+ gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[3] );
+ ctx->NewState |= NEW_TEXTURING;
+
+ /* free the source image */
+ if (image && image->RefCount==0) {
+ /* if RefCount>0 then image must be in a display list */
+ gl_free_image(image);
+ }
+
+ /* tell driver about change */
+ if (ctx->Driver.TexImage) {
+ (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D_EXT,
+ texUnit->CurrentD[3],
+ level, internalformat, teximage );
+ }
+ }
+ else if (target==GL_PROXY_TEXTURE_3D_EXT) {
+ /* Proxy texture: check for errors and update proxy state */
+ if (texture_error_check( ctx, target, level, internalformat,
+ format, type, 3, width, height, depth,
+ border )) {
+ if (level>=0 && level<ctx->Const.MaxTextureLevels) {
+ MEMSET( ctx->Texture.Proxy3D->Image[level], 0,
+ sizeof(struct gl_texture_image) );
+ }
+ }
+ else {
+ ctx->Texture.Proxy3D->Image[level]->Format = (GLenum) format;
+ set_teximage_component_sizes( ctx->Texture.Proxy3D->Image[level] );
+ ctx->Texture.Proxy3D->Image[level]->IntFormat = (GLenum) internalformat;
+ ctx->Texture.Proxy3D->Image[level]->Border = border;
+ ctx->Texture.Proxy3D->Image[level]->Width = width;
+ ctx->Texture.Proxy3D->Image[level]->Height = height;
+ ctx->Texture.Proxy3D->Image[level]->Depth = depth;
+ }
+ if (image && image->RefCount==0) {
+ /* if RefCount>0 then image must be in a display list */
+ gl_free_image(image);
+ }
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM, "glTexImage3DEXT(target)" );
+ return;
+ }
+}
+
+
+
+void gl_GetTexImage( GLcontext *ctx, GLenum target, GLint level, GLenum format,
+ GLenum type, GLvoid *pixels )
+{
+ const struct gl_texture_object *texObj;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage");
+
+ if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
+ gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
+ return;
+ }
+
+ if (gl_sizeof_type(type) <= 0) {
+ gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
+ return;
+ }
+
+ if (gl_components_in_format(format) <= 0) {
+ gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
+ return;
+ }
+
+ if (!pixels)
+ return; /* XXX generate an error??? */
+
+ switch (target) {
+ case GL_TEXTURE_1D:
+ texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1];
+ break;
+ case GL_TEXTURE_2D:
+ texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2];
+ break;
+ case GL_TEXTURE_3D:
+ texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3];
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(target)" );
+ return;
+ }
+
+ if (texObj->Image[level] && texObj->Image[level]->Data) {
+ const struct gl_texture_image *texImage = texObj->Image[level];
+ GLint width = texImage->Width;
+ GLint height = texImage->Height;
+ GLint row;
+
+ for (row = 0; row < height; row++) {
+ /* compute destination address in client memory */
+ GLvoid *dest = gl_pixel_addr_in_image( &ctx->Unpack, pixels,
+ width, height,
+ format, type, 0, row, 0);
+
+ assert(dest);
+ if (texImage->Format == GL_RGBA) {
+ const GLubyte *src = texImage->Data + row * width * 4 * sizeof(GLubyte);
+ gl_pack_rgba_span( ctx, width, (void *) src, format, type, dest,
+ &ctx->Pack, GL_TRUE );
+ }
+ else {
+ /* fetch RGBA row from texture image then pack it in client mem */
+ GLubyte rgba[MAX_WIDTH][4];
+ GLint i;
+ const GLubyte *src;
+ switch (texImage->Format) {
+ case GL_ALPHA:
+ src = texImage->Data + row * width * sizeof(GLubyte);
+ for (i = 0; i < width; i++) {
+ rgba[i][RCOMP] = 255;
+ rgba[i][GCOMP] = 255;
+ rgba[i][BCOMP] = 255;
+ rgba[i][ACOMP] = src[i];
+ }
+ break;
+ case GL_LUMINANCE:
+ src = texImage->Data + row * width * sizeof(GLubyte);
+ for (i = 0; i < width; i++) {
+ rgba[i][RCOMP] = src[i];
+ rgba[i][GCOMP] = src[i];
+ rgba[i][BCOMP] = src[i];
+ rgba[i][ACOMP] = 255;
+ }
+ break;
+ case GL_LUMINANCE_ALPHA:
+ src = texImage->Data + row * 2 * width * sizeof(GLubyte);
+ for (i = 0; i < width; i++) {
+ rgba[i][RCOMP] = src[i*2+0];
+ rgba[i][GCOMP] = src[i*2+0];
+ rgba[i][BCOMP] = src[i*2+0];
+ rgba[i][ACOMP] = src[i*2+1];
+ }
+ break;
+ case GL_INTENSITY:
+ src = texImage->Data + row * width * sizeof(GLubyte);
+ for (i = 0; i < width; i++) {
+ rgba[i][RCOMP] = src[i];
+ rgba[i][GCOMP] = src[i];
+ rgba[i][BCOMP] = src[i];
+ rgba[i][ACOMP] = 255;
+ }
+ break;
+ case GL_RGB:
+ src = texImage->Data + row * 3 * width * sizeof(GLubyte);
+ for (i = 0; i < width; i++) {
+ rgba[i][RCOMP] = src[i*3+0];
+ rgba[i][GCOMP] = src[i*3+1];
+ rgba[i][BCOMP] = src[i*3+2];
+ rgba[i][ACOMP] = 255;
+ }
+ break;
+ case GL_RGBA:
+ /* this special case should have been handled above! */
+ gl_problem( ctx, "error 1 in gl_GetTexImage" );
+ break;
+ case GL_COLOR_INDEX:
+ gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
+ break;
+ default:
+ gl_problem( ctx, "bad format in gl_GetTexImage" );
+ }
+ gl_pack_rgba_span( ctx, width, (const GLubyte (*)[4])rgba,
+ format, type, dest, &ctx->Pack, GL_TRUE );
+ }
+ }
+ }
+}
+
+
+
+/*
+ * Unpack the image data given to glTexSubImage[12]D.
+ * This function is just a wrapper for gl_unpack_image() but it does
+ * some extra error checking.
+ */
+struct gl_image *
+gl_unpack_texsubimage( GLcontext *ctx, GLint width, GLint height,
+ GLenum format, GLenum type, const GLvoid *pixels )
+{
+ if (type==GL_BITMAP && format!=GL_COLOR_INDEX) {
+ return NULL;
+ }
+
+ if (format==GL_STENCIL_INDEX || format==GL_DEPTH_COMPONENT){
+ return NULL;
+ }
+
+ if (gl_sizeof_type(type)<=0) {
+ return NULL;
+ }
+
+ return gl_unpack_image3D( ctx, width, height, 1, format, type, pixels, &ctx->Unpack );
+}
+
+
+/*
+ * Unpack the image data given to glTexSubImage3D.
+ * This function is just a wrapper for gl_unpack_image() but it does
+ * some extra error checking.
+ */
+struct gl_image *
+gl_unpack_texsubimage3D( GLcontext *ctx, GLint width, GLint height,
+ GLint depth, GLenum format, GLenum type,
+ const GLvoid *pixels )
+{
+ if (type==GL_BITMAP && format!=GL_COLOR_INDEX) {
+ return NULL;
+ }
+
+ if (format==GL_STENCIL_INDEX || format==GL_DEPTH_COMPONENT){
+ return NULL;
+ }
+
+ if (gl_sizeof_type(type)<=0) {
+ return NULL;
+ }
+
+ return gl_unpack_image3D( ctx, width, height, depth, format, type, pixels,
+ &ctx->Unpack );
+}
+
+
+
+void gl_TexSubImage1D( GLcontext *ctx,
+ GLenum target, GLint level, GLint xoffset,
+ GLsizei width, GLenum format, GLenum type,
+ struct gl_image *image )
+{
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ struct gl_texture_image *destTex;
+
+ if (target!=GL_TEXTURE_1D) {
+ gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
+ return;
+ }
+ if (level<0 || level>=ctx->Const.MaxTextureLevels) {
+ gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(level)" );
+ return;
+ }
+
+ destTex = texUnit->CurrentD[1]->Image[level];
+ if (!destTex) {
+ gl_error( ctx, GL_INVALID_OPERATION, "glTexSubImage1D" );
+ return;
+ }
+
+ if (xoffset < -((GLint)destTex->Border)) {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage1D(xoffset)" );
+ return;
+ }
+ if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage1D(xoffset+width)" );
+ return;
+ }
+
+ if (image) {
+ /* unpacking must have been error-free */
+ GLint texcomponents = components_in_intformat(destTex->Format);
+
+ if (image->Type==GL_UNSIGNED_BYTE && texcomponents==image->Components) {
+ /* Simple case, just byte copy image data into texture image */
+ /* row by row. */
+ GLubyte *dst = destTex->Data + texcomponents * xoffset;
+ GLubyte *src = (GLubyte *) image->Data;
+ MEMCPY( dst, src, width * texcomponents );
+ }
+ else {
+ /* General case, convert image pixels into texels, scale, bias, etc */
+ struct gl_texture_image *subTexImg = image_to_texture(ctx, image,
+ destTex->IntFormat, destTex->Border);
+ GLubyte *dst = destTex->Data + texcomponents * xoffset;
+ GLubyte *src = subTexImg->Data;
+ MEMCPY( dst, src, width * texcomponents );
+ gl_free_texture_image(subTexImg);
+ }
+
+ /* if the image's reference count is zero, delete it now */
+ if (image->RefCount==0) {
+ gl_free_image(image);
+ }
+
+ gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] );
+
+ /* tell driver about change */
+ if (ctx->Driver.TexSubImage) {
+ (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_1D,
+ texUnit->CurrentD[1], level,
+ xoffset,0,width,1,
+ texUnit->CurrentD[1]->Image[level]->IntFormat,
+ destTex );
+ }
+ else {
+ if (ctx->Driver.TexImage) {
+ (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D, texUnit->CurrentD[1], level,
+ texUnit->CurrentD[1]->Image[level]->IntFormat,
+ destTex );
+ }
+ }
+ }
+ else {
+ /* if no image, an error must have occured, do more testing now */
+ GLint components, size;
+
+ if (width<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage1D(width)" );
+ return;
+ }
+ if (type==GL_BITMAP && format!=GL_COLOR_INDEX) {
+ gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(format)" );
+ return;
+ }
+ components = components_in_intformat( format );
+ if (components<0 || format==GL_STENCIL_INDEX
+ || format==GL_DEPTH_COMPONENT){
+ gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(format)" );
+ return;
+ }
+ size = gl_sizeof_type( type );
+ if (size<=0) {
+ gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(type)" );
+ return;
+ }
+ /* if we get here, probably ran out of memory during unpacking */
+ gl_error( ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D" );
+ }
+}
+
+
+
+void gl_TexSubImage2D( GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ struct gl_image *image )
+{
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ struct gl_texture_image *destTex;
+
+ if (target!=GL_TEXTURE_2D) {
+ gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
+ return;
+ }
+ if (level<0 || level>=ctx->Const.MaxTextureLevels) {
+ gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)" );
+ return;
+ }
+
+ destTex = texUnit->CurrentD[2]->Image[level];
+ if (!destTex) {
+ gl_error( ctx, GL_INVALID_OPERATION, "glTexSubImage2D" );
+ return;
+ }
+
+ if (xoffset < -((GLint)destTex->Border)) {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(xoffset)" );
+ return;
+ }
+ if (yoffset < -((GLint)destTex->Border)) {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(yoffset)" );
+ return;
+ }
+ if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(xoffset+width)" );
+ return;
+ }
+ if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(yoffset+height)" );
+ return;
+ }
+
+ if (image) {
+ /* unpacking must have been error-free */
+ GLint texcomponents = components_in_intformat(destTex->Format);
+
+ if (image->Type==GL_UNSIGNED_BYTE && texcomponents==image->Components) {
+ /* Simple case, just byte copy image data into texture image */
+ /* row by row. */
+ GLubyte *dst = destTex->Data
+ + (yoffset * destTex->Width + xoffset) * texcomponents;
+ GLubyte *src = (GLubyte *) image->Data;
+ GLint j;
+ for (j=0;j<height;j++) {
+ MEMCPY( dst, src, width * texcomponents );
+ dst += destTex->Width * texcomponents * sizeof(GLubyte);
+ src += width * texcomponents * sizeof(GLubyte);
+ }
+ }
+ else {
+ /* General case, convert image pixels into texels, scale, bias, etc */
+ struct gl_texture_image *subTexImg = image_to_texture(ctx, image,
+ destTex->IntFormat, destTex->Border);
+ GLubyte *dst = destTex->Data
+ + (yoffset * destTex->Width + xoffset) * texcomponents;
+ GLubyte *src = subTexImg->Data;
+ GLint j;
+ for (j=0;j<height;j++) {
+ MEMCPY( dst, src, width * texcomponents );
+ dst += destTex->Width * texcomponents * sizeof(GLubyte);
+ src += width * texcomponents * sizeof(GLubyte);
+ }
+ gl_free_texture_image(subTexImg);
+ }
+
+ /* if the image's reference count is zero, delete it now */
+ if (image->RefCount==0) {
+ gl_free_image(image);
+ }
+
+ gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[2] );
+
+ /* tell driver about change */
+ if (ctx->Driver.TexSubImage) {
+ (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], level,
+ xoffset, yoffset, width, height,
+ texUnit->CurrentD[2]->Image[level]->IntFormat,
+ destTex );
+ }
+ else {
+ if (ctx->Driver.TexImage) {
+ (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], level,
+ texUnit->CurrentD[2]->Image[level]->IntFormat,
+ destTex );
+ }
+ }
+ }
+ else {
+ /* if no image, an error must have occured, do more testing now */
+ GLint components, size;
+
+ if (width<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(width)" );
+ return;
+ }
+ if (height<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage2D(height)" );
+ return;
+ }
+ if (type==GL_BITMAP && format!=GL_COLOR_INDEX) {
+ gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(format)" );
+ return;
+ }
+ components = gl_components_in_format( format );
+ if (components<0 || format==GL_STENCIL_INDEX
+ || format==GL_DEPTH_COMPONENT){
+ gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(format)" );
+ return;
+ }
+ size = gl_sizeof_packed_type( type );
+ if (size<=0) {
+ gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(type)" );
+ return;
+ }
+ /* if we get here, probably ran out of memory during unpacking */
+ gl_error( ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D" );
+ }
+}
+
+
+
+void gl_TexSubImage3DEXT( GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type,
+ struct gl_image *image )
+{
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ struct gl_texture_image *destTex;
+
+ if (target!=GL_TEXTURE_3D_EXT) {
+ gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(target)" );
+ return;
+ }
+ if (level<0 || level>=ctx->Const.MaxTextureLevels) {
+ gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(level)" );
+ return;
+ }
+
+ destTex = texUnit->CurrentD[3]->Image[level];
+ if (!destTex) {
+ gl_error( ctx, GL_INVALID_OPERATION, "glTexSubImage3DEXT" );
+ return;
+ }
+
+ if (xoffset < -((GLint)destTex->Border)) {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(xoffset)" );
+ return;
+ }
+ if (yoffset < -((GLint)destTex->Border)) {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(yoffset)" );
+ return;
+ }
+ if (zoffset < -((GLint)destTex->Border)) {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(zoffset)" );
+ return;
+ }
+ if (xoffset + width > (GLint) (destTex->Width+destTex->Border)) {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(xoffset+width)" );
+ return;
+ }
+ if (yoffset + height > (GLint) (destTex->Height+destTex->Border)) {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(yoffset+height)" );
+ return;
+ }
+ if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(zoffset+depth)" );
+ return;
+ }
+
+ if (image) {
+ /* unpacking must have been error-free */
+ GLint texcomponents = components_in_intformat(destTex->Format);
+ GLint dstRectArea = destTex->Width * destTex->Height;
+ GLint srcRectArea = width * height;
+
+ if (image->Type==GL_UNSIGNED_BYTE && texcomponents==image->Components) {
+ /* Simple case, just byte copy image data into texture image */
+ /* row by row. */
+ GLubyte *dst = destTex->Data
+ + (zoffset * dstRectArea + yoffset * destTex->Width + xoffset)
+ * texcomponents;
+ GLubyte *src = (GLubyte *) image->Data;
+ GLint j, k;
+ for(k=0;k<depth; k++) {
+ for (j=0;j<height;j++) {
+ MEMCPY( dst, src, width * texcomponents );
+ dst += destTex->Width * texcomponents;
+ src += width * texcomponents;
+ }
+ dst += dstRectArea * texcomponents * sizeof(GLubyte);
+ src += srcRectArea * texcomponents * sizeof(GLubyte);
+ }
+ }
+ else {
+ /* General case, convert image pixels into texels, scale, bias, etc */
+ struct gl_texture_image *subTexImg = image_to_texture(ctx, image,
+ destTex->IntFormat, destTex->Border);
+ GLubyte *dst = destTex->Data
+ + (zoffset * dstRectArea + yoffset * destTex->Width + xoffset)
+ * texcomponents;
+ GLubyte *src = subTexImg->Data;
+ GLint j, k;
+ for(k=0;k<depth; k++) {
+ for (j=0;j<height;j++) {
+ MEMCPY( dst, src, width * texcomponents );
+ dst += destTex->Width * texcomponents;
+ src += width * texcomponents;
+ }
+ dst += dstRectArea * texcomponents * sizeof(GLubyte);
+ src += srcRectArea * texcomponents * sizeof(GLubyte);
+ }
+ gl_free_texture_image(subTexImg);
+ }
+ /* if the image's reference count is zero, delete it now */
+ if (image->RefCount==0) {
+ gl_free_image(image);
+ }
+
+ gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[3] );
+
+ /* tell driver about change */
+ if (ctx->Driver.TexImage) {
+ (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D_EXT, texUnit->CurrentD[3],
+ level, texUnit->CurrentD[3]->Image[level]->IntFormat,
+ destTex );
+ }
+ }
+ else {
+ /* if no image, an error must have occured, do more testing now */
+ GLint components, size;
+
+ if (width<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(width)" );
+ return;
+ }
+ if (height<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(height)" );
+ return;
+ }
+ if (depth<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexSubImage3DEXT(depth)" );
+ return;
+ }
+ if (type==GL_BITMAP && format!=GL_COLOR_INDEX) {
+ gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(format)" );
+ return;
+ }
+ components = components_in_intformat( format );
+ if (components<0 || format==GL_STENCIL_INDEX
+ || format==GL_DEPTH_COMPONENT){
+ gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(format)" );
+ return;
+ }
+ size = gl_sizeof_type( type );
+ if (size<=0) {
+ gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3DEXT(type)" );
+ return;
+ }
+ /* if we get here, probably ran out of memory during unpacking */
+ gl_error( ctx, GL_OUT_OF_MEMORY, "glTexSubImage3DEXT" );
+ }
+}
+
+
+
+/*
+ * Read an RGBA image from the frame buffer.
+ * Input: ctx - the context
+ * x, y - lower left corner
+ * width, height - size of region to read
+ * format - one of GL_RED, GL_RGB, GL_LUMINANCE, etc.
+ * Return: gl_image pointer or NULL if out of memory
+ */
+static struct gl_image *read_color_image( GLcontext *ctx, GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format )
+{
+ struct gl_image *image;
+ GLubyte *imgptr;
+ GLint components;
+ GLint i, j;
+
+ components = components_in_intformat( format );
+
+ /*
+ * Allocate image struct and image data buffer
+ */
+ image = (struct gl_image *) malloc( sizeof(struct gl_image) );
+ if (image) {
+ image->Width = width;
+ image->Height = height;
+ image->Depth = 1;
+ image->Components = components;
+ image->Format = format;
+ image->Type = GL_UNSIGNED_BYTE;
+ image->RefCount = 0;
+ image->Data = (GLubyte *) malloc( width * height * components );
+ if (!image->Data) {
+ free(image);
+ return NULL;
+ }
+ }
+ else {
+ return NULL;
+ }
+
+ imgptr = (GLubyte *) image->Data;
+
+ /* Select buffer to read from */
+ (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.DriverReadBuffer );
+
+ for (j=0;j<height;j++) {
+ GLubyte rgba[MAX_WIDTH][4];
+ gl_read_rgba_span( ctx, width, x, y+j, rgba );
+
+ switch (format) {
+ case GL_ALPHA:
+ for (i=0;i<width;i++) {
+ *imgptr++ = rgba[i][ACOMP];
+ }
+ break;
+ case GL_LUMINANCE:
+ for (i=0;i<width;i++) {
+ *imgptr++ = rgba[i][RCOMP];
+ }
+ break;
+ case GL_LUMINANCE_ALPHA:
+ for (i=0;i<width;i++) {
+ *imgptr++ = rgba[i][RCOMP];
+ *imgptr++ = rgba[i][ACOMP];
+ }
+ break;
+ case GL_INTENSITY:
+ for (i=0;i<width;i++) {
+ *imgptr++ = rgba[i][RCOMP];
+ }
+ break;
+ case GL_RGB:
+ for (i=0;i<width;i++) {
+ *imgptr++ = rgba[i][RCOMP];
+ *imgptr++ = rgba[i][GCOMP];
+ *imgptr++ = rgba[i][BCOMP];
+ }
+ break;
+ case GL_RGBA:
+ for (i=0;i<width;i++) {
+ *imgptr++ = rgba[i][RCOMP];
+ *imgptr++ = rgba[i][GCOMP];
+ *imgptr++ = rgba[i][BCOMP];
+ *imgptr++ = rgba[i][ACOMP];
+ }
+ break;
+ default:
+ gl_problem(ctx, "Bad format in read_color_image");
+ break;
+ } /*switch*/
+
+ } /*for*/
+
+ /* Restore drawing buffer */
+ (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer );
+
+ return image;
+}
+
+
+
+
+void gl_CopyTexImage1D( GLcontext *ctx,
+ GLenum target, GLint level,
+ GLenum internalformat,
+ GLint x, GLint y,
+ GLsizei width, GLint border )
+{
+ GLint format;
+ struct gl_image *teximage;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D");
+ if (target!=GL_TEXTURE_1D) {
+ gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
+ return;
+ }
+ if (level<0 || level>=ctx->Const.MaxTextureLevels) {
+ gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(level)" );
+ return;
+ }
+ if (border!=0 && border!=1) {
+ gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(border)" );
+ return;
+ }
+ if (width < 2*border || width > 2 + ctx->Const.MaxTextureSize || width<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(width)" );
+ return;
+ }
+ format = decode_internal_format( internalformat );
+ if (format<0 || (internalformat>=1 && internalformat<=4)) {
+ gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage1D(format)" );
+ return;
+ }
+
+ teximage = read_color_image( ctx, x, y, width, 1, (GLenum) format );
+ if (!teximage) {
+ gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
+ return;
+ }
+
+ gl_TexImage1D( ctx, target, level, internalformat, width,
+ border, GL_RGBA, GL_UNSIGNED_BYTE, teximage );
+
+ /* teximage was freed in gl_TexImage1D */
+}
+
+
+
+void gl_CopyTexImage2D( GLcontext *ctx,
+ GLenum target, GLint level, GLenum internalformat,
+ GLint x, GLint y, GLsizei width, GLsizei height,
+ GLint border )
+{
+ GLint format;
+ struct gl_image *teximage;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D");
+ if (target!=GL_TEXTURE_2D) {
+ gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
+ return;
+ }
+ if (level<0 || level>=ctx->Const.MaxTextureLevels) {
+ gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(level)" );
+ return;
+ }
+ if (border!=0 && border!=1) {
+ gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(border)" );
+ return;
+ }
+ if (width<2*border || width>2+ctx->Const.MaxTextureSize || width<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width)" );
+ return;
+ }
+ if (height<2*border || height>2+ctx->Const.MaxTextureSize || height<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(height)" );
+ return;
+ }
+ format = decode_internal_format( internalformat );
+ if (format<0 || (internalformat>=1 && internalformat<=4)) {
+ gl_error( ctx, GL_INVALID_VALUE, "glCopyTexImage2D(format)" );
+ return;
+ }
+
+ teximage = read_color_image( ctx, x, y, width, height, (GLenum) format );
+ if (!teximage) {
+ gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
+ return;
+ }
+
+ gl_TexImage2D( ctx, target, level, internalformat, width, height,
+ border, GL_RGBA, GL_UNSIGNED_BYTE, teximage );
+
+ /* teximage was freed in gl_TexImage2D */
+}
+
+
+
+
+/*
+ * Do the work of glCopyTexSubImage[123]D.
+ * TODO: apply pixel bias scale and mapping.
+ */
+static void copy_tex_sub_image( GLcontext *ctx, struct gl_texture_image *dest,
+ GLint width, GLint height,
+ GLint srcx, GLint srcy,
+ GLint dstx, GLint dsty, GLint zoffset )
+{
+ GLint i, j;
+ GLint format, components, rectarea;
+ GLint texwidth, texheight;
+
+ texwidth = dest->Width;
+ texheight = dest->Height;
+ rectarea = texwidth * texheight;
+ zoffset *= rectarea;
+ format = dest->Format;
+ components = components_in_intformat( format );
+
+ /* Select buffer to read from */
+ (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Pixel.DriverReadBuffer );
+
+ for (j=0;j<height;j++) {
+ GLubyte rgba[MAX_WIDTH][4];
+ GLubyte *texptr;
+
+ gl_read_rgba_span( ctx, width, srcx, srcy+j, rgba );
+
+ texptr = dest->Data + ( zoffset + (dsty+j) * texwidth + dstx) * components;
+
+ switch (format) {
+ case GL_ALPHA:
+ for (i=0;i<width;i++) {
+ *texptr++ = rgba[i][ACOMP];
+ }
+ break;
+ case GL_LUMINANCE:
+ for (i=0;i<width;i++) {
+ *texptr++ = rgba[i][RCOMP];
+ }
+ break;
+ case GL_LUMINANCE_ALPHA:
+ for (i=0;i<width;i++) {
+ *texptr++ = rgba[i][RCOMP];
+ *texptr++ = rgba[i][ACOMP];
+ }
+ break;
+ case GL_INTENSITY:
+ for (i=0;i<width;i++) {
+ *texptr++ = rgba[i][RCOMP];
+ }
+ break;
+ case GL_RGB:
+ for (i=0;i<width;i++) {
+ *texptr++ = rgba[i][RCOMP];
+ *texptr++ = rgba[i][GCOMP];
+ *texptr++ = rgba[i][BCOMP];
+ }
+ break;
+ case GL_RGBA:
+ for (i=0;i<width;i++) {
+ *texptr++ = rgba[i][RCOMP];
+ *texptr++ = rgba[i][GCOMP];
+ *texptr++ = rgba[i][BCOMP];
+ *texptr++ = rgba[i][ACOMP];
+ }
+ break;
+ } /*switch*/
+ } /*for*/
+
+
+ /* Restore drawing buffer */
+ (void) (*ctx->Driver.SetBuffer)( ctx, ctx->Color.DriverDrawBuffer );
+}
+
+
+
+
+void gl_CopyTexSubImage1D( GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint x, GLint y, GLsizei width )
+{
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ struct gl_texture_image *teximage;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D");
+ if (target!=GL_TEXTURE_1D) {
+ gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
+ return;
+ }
+ if (level<0 || level>=ctx->Const.MaxTextureLevels) {
+ gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage1D(level)" );
+ return;
+ }
+ if (width<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage1D(width)" );
+ return;
+ }
+
+ teximage = texUnit->CurrentD[1]->Image[level];
+
+ if (teximage) {
+ if (xoffset < -((GLint)teximage->Border)) {
+ gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage1D(xoffset)" );
+ return;
+ }
+ /* NOTE: we're adding the border here, not subtracting! */
+ if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
+ gl_error( ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage1D(xoffset+width)" );
+ return;
+ }
+ if (teximage->Data) {
+ copy_tex_sub_image( ctx, teximage, width, 1, x, y, xoffset, 0, 0 );
+
+ /* tell driver about change */
+ if (ctx->Driver.TexSubImage) {
+ (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_1D,
+ texUnit->CurrentD[1], level,
+ xoffset,0,width,1,
+ teximage->IntFormat,
+ teximage );
+ }
+ else {
+ if (ctx->Driver.TexImage) {
+ (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D, texUnit->CurrentD[1], level,
+ teximage->IntFormat,
+ teximage );
+ }
+ }
+ }
+ }
+ else {
+ gl_error( ctx, GL_INVALID_OPERATION, "glCopyTexSubImage1D" );
+ }
+}
+
+
+
+void gl_CopyTexSubImage2D( GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLint x, GLint y, GLsizei width, GLsizei height )
+{
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ struct gl_texture_image *teximage;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D");
+ if (target!=GL_TEXTURE_2D) {
+ gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
+ return;
+ }
+ if (level<0 || level>=ctx->Const.MaxTextureLevels) {
+ gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(level)" );
+ return;
+ }
+ if (width<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(width)" );
+ return;
+ }
+ if (height<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(height)" );
+ return;
+ }
+
+ teximage = texUnit->CurrentD[2]->Image[level];
+
+ if (teximage) {
+ if (xoffset < -((GLint)teximage->Border)) {
+ gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(xoffset)" );
+ return;
+ }
+ if (yoffset < -((GLint)teximage->Border)) {
+ gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage2D(yoffset)" );
+ return;
+ }
+ /* NOTE: we're adding the border here, not subtracting! */
+ if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
+ gl_error( ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage2D(xoffset+width)" );
+ return;
+ }
+ if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) {
+ gl_error( ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage2D(yoffset+height)" );
+ return;
+ }
+
+ if (teximage->Data) {
+ copy_tex_sub_image( ctx, teximage, width, height,
+ x, y, xoffset, yoffset, 0 );
+ /* tell driver about change */
+ if (ctx->Driver.TexSubImage) {
+ (*ctx->Driver.TexSubImage)( ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], level,
+ xoffset, yoffset, width, height,
+ teximage->IntFormat,
+ teximage );
+ }
+ else {
+ if (ctx->Driver.TexImage) {
+ (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D, texUnit->CurrentD[2], level,
+ teximage->IntFormat,
+ teximage );
+ }
+ }
+ }
+ }
+ else {
+ gl_error( ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D" );
+ }
+}
+
+
+
+void gl_CopyTexSubImage3DEXT( GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLint x, GLint y, GLsizei width, GLsizei height )
+{
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ struct gl_texture_image *teximage;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3DEXT");
+ if (target!=GL_TEXTURE_2D) {
+ gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3DEXT(target)" );
+ return;
+ }
+ if (level<0 || level>=ctx->Const.MaxTextureLevels) {
+ gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(level)" );
+ return;
+ }
+ if (width<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(width)" );
+ return;
+ }
+ if (height<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(height)" );
+ return;
+ }
+
+ teximage = texUnit->CurrentD[3]->Image[level];
+ if (teximage) {
+ if (xoffset < -((GLint)teximage->Border)) {
+ gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(xoffset)" );
+ return;
+ }
+ if (yoffset < -((GLint)teximage->Border)) {
+ gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(yoffset)" );
+ return;
+ }
+ if (zoffset < -((GLint)teximage->Border)) {
+ gl_error( ctx, GL_INVALID_VALUE, "glCopyTexSubImage3DEXT(zoffset)" );
+ return;
+ }
+ /* NOTE: we're adding the border here, not subtracting! */
+ if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
+ gl_error( ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage3DEXT(xoffset+width)" );
+ return;
+ }
+ if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) {
+ gl_error( ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage3DEXT(yoffset+height)" );
+ return;
+ }
+ if (zoffset > (GLint) (teximage->Depth+teximage->Border)) {
+ gl_error( ctx, GL_INVALID_VALUE,
+ "glCopyTexSubImage3DEXT(zoffset+depth)" );
+ return;
+ }
+
+ if (teximage->Data) {
+ copy_tex_sub_image( ctx, teximage, width, height,
+ x, y, xoffset, yoffset, zoffset);
+
+ /* tell driver about change */
+ if (ctx->Driver.TexImage) {
+ (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D_EXT, texUnit->CurrentD[3],
+ level, teximage->IntFormat,
+ teximage );
+ }
+ }
+ }
+ else {
+ gl_error( ctx, GL_INVALID_OPERATION, "glCopyTexSubImage3DEXT" );
+ }
+}
+
diff --git a/src/mesa/main/teximage.h b/src/mesa/main/teximage.h
new file mode 100644
index 0000000000..eb72f961e5
--- /dev/null
+++ b/src/mesa/main/teximage.h
@@ -0,0 +1,186 @@
+/* $Id: teximage.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef TEXIMAGE_H
+#define TEXIMAGE_H
+
+
+#include "types.h"
+
+
+/*** Internal functions ***/
+
+
+extern struct gl_texture_image *gl_alloc_texture_image( void );
+
+
+extern void gl_free_texture_image( struct gl_texture_image *teximage );
+
+
+extern struct gl_image *
+gl_unpack_texsubimage( GLcontext *ctx, GLint width, GLint height,
+ GLenum format, GLenum type, const GLvoid *pixels );
+
+
+extern struct gl_image *
+gl_unpack_texsubimage3D( GLcontext *ctx, GLint width, GLint height,GLint depth,
+ GLenum format, GLenum type, const GLvoid *pixels );
+
+
+extern struct gl_texture_image *
+gl_unpack_texture( GLcontext *ctx,
+ GLint dimensions,
+ GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width, GLsizei height,
+ GLint border,
+ GLenum format, GLenum type,
+ const GLvoid *pixels );
+
+extern struct gl_texture_image *
+gl_unpack_texture3D( GLcontext *ctx,
+ GLint dimensions,
+ GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLint border,
+ GLenum format, GLenum type,
+ const GLvoid *pixels );
+
+
+extern void gl_tex_image_1D( GLcontext *ctx,
+ GLenum target, GLint level, GLint internalformat,
+ GLsizei width, GLint border, GLenum format,
+ GLenum type, const GLvoid *pixels );
+
+
+extern void gl_tex_image_2D( GLcontext *ctx,
+ GLenum target, GLint level, GLint internalformat,
+ GLsizei width, GLint height, GLint border,
+ GLenum format, GLenum type,
+ const GLvoid *pixels );
+
+extern void gl_tex_image_3D( GLcontext *ctx,
+ GLenum target, GLint level, GLint internalformat,
+ GLsizei width, GLint height, GLint depth,
+ GLint border,
+ GLenum format, GLenum type,
+ const GLvoid *pixels );
+
+
+/*** API entry points ***/
+
+
+extern void gl_TexImage1D( GLcontext *ctx,
+ GLenum target, GLint level, GLint internalformat,
+ GLsizei width, GLint border, GLenum format,
+ GLenum type, struct gl_image *teximage );
+
+
+extern void gl_TexImage2D( GLcontext *ctx,
+ GLenum target, GLint level, GLint internalformat,
+ GLsizei width, GLsizei height, GLint border,
+ GLenum format, GLenum type,
+ struct gl_image *teximage );
+
+
+extern void gl_TexImage3DEXT( GLcontext *ctx,
+ GLenum target, GLint level, GLint internalformat,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLint border,
+ GLenum format, GLenum type,
+ struct gl_image *teximage );
+
+
+extern void gl_GetTexImage( GLcontext *ctx, GLenum target, GLint level,
+ GLenum format, GLenum type, GLvoid *pixels );
+
+
+
+extern void gl_TexSubImage1D( GLcontext *ctx,
+ GLenum target, GLint level, GLint xoffset,
+ GLsizei width, GLenum format, GLenum type,
+ struct gl_image *image );
+
+
+extern void gl_TexSubImage2D( GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format, GLenum type,
+ struct gl_image *image );
+
+
+extern void gl_TexSubImage3DEXT( GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth,
+ GLenum format, GLenum type,
+ struct gl_image *image );
+
+
+extern void gl_CopyTexImage1D( GLcontext *ctx,
+ GLenum target, GLint level,
+ GLenum internalformat,
+ GLint x, GLint y,
+ GLsizei width, GLint border );
+
+
+extern void gl_CopyTexImage2D( GLcontext *ctx,
+ GLenum target, GLint level,
+ GLenum internalformat, GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLint border );
+
+
+extern void gl_CopyTexSubImage1D( GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint x, GLint y,
+ GLsizei width );
+
+
+extern void gl_CopyTexSubImage2D( GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height );
+
+
+extern void gl_CopyTexSubImage3DEXT( GLcontext *ctx,
+ GLenum target, GLint level,
+ GLint xoffset, GLint yoffset,
+ GLint zoffset,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height );
+
+#endif
+
diff --git a/src/mesa/main/texobj.c b/src/mesa/main/texobj.c
new file mode 100644
index 0000000000..78691d24f2
--- /dev/null
+++ b/src/mesa/main/texobj.c
@@ -0,0 +1,571 @@
+/* $Id: texobj.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "context.h"
+#include "enums.h"
+#include "hash.h"
+#include "macros.h"
+#include "teximage.h"
+#include "texstate.h"
+#include "texobj.h"
+#include "types.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+
+/*
+ * Allocate a new texture object and add it to the linked list of texture
+ * objects. If name>0 then also insert the new texture object into the hash
+ * table.
+ * Input: shared - the shared GL state structure to contain the texture object
+ * name - integer name for the texture object
+ * dimensions - either 1, 2 or 3
+ * Return: pointer to new texture object
+ */
+struct gl_texture_object *
+gl_alloc_texture_object( struct gl_shared_state *shared, GLuint name,
+ GLuint dimensions)
+{
+ struct gl_texture_object *obj;
+
+ assert(dimensions <= 3);
+
+ obj = (struct gl_texture_object *)
+ calloc(1,sizeof(struct gl_texture_object));
+ if (obj) {
+ /* init the non-zero fields */
+ obj->Name = name;
+ obj->Dimensions = dimensions;
+ obj->WrapS = GL_REPEAT;
+ obj->WrapT = GL_REPEAT;
+ obj->MinFilter = GL_NEAREST_MIPMAP_LINEAR;
+ obj->MagFilter = GL_LINEAR;
+ obj->MinLod = -1000.0;
+ obj->MaxLod = 1000.0;
+ obj->BaseLevel = 0;
+ obj->MaxLevel = 1000;
+ obj->MinMagThresh = 0.0F;
+ obj->Palette[0] = 255;
+ obj->Palette[1] = 255;
+ obj->Palette[2] = 255;
+ obj->Palette[3] = 255;
+ obj->PaletteSize = 1;
+ obj->PaletteIntFormat = GL_RGBA;
+ obj->PaletteFormat = GL_RGBA;
+
+ /* insert into linked list */
+ if (shared) {
+ obj->Next = shared->TexObjectList;
+ shared->TexObjectList = obj;
+ }
+
+ if (name > 0) {
+ /* insert into hash table */
+ HashInsert(shared->TexObjects, name, obj);
+ }
+ }
+ return obj;
+}
+
+
+/*
+ * Deallocate a texture object struct and remove it from the given
+ * shared GL state.
+ * Input: shared - the shared GL state to which the object belongs
+ * t - the texture object to delete
+ */
+void gl_free_texture_object( struct gl_shared_state *shared,
+ struct gl_texture_object *t )
+{
+ struct gl_texture_object *tprev, *tcurr;
+
+ assert(t);
+
+ /* Remove t from dirty list so we don't touch free'd memory later.
+ * Test for shared since Proxy texture aren't in global linked list.
+ */
+ if (shared)
+ gl_remove_texobj_from_dirty_list( shared, t );
+
+ /* unlink t from the linked list */
+ if (shared) {
+ tprev = NULL;
+ tcurr = shared->TexObjectList;
+ while (tcurr) {
+ if (tcurr==t) {
+ if (tprev) {
+ tprev->Next = t->Next;
+ }
+ else {
+ shared->TexObjectList = t->Next;
+ }
+ break;
+ }
+ tprev = tcurr;
+ tcurr = tcurr->Next;
+ }
+ }
+
+ if (t->Name) {
+ /* remove from hash table */
+ HashRemove(shared->TexObjects, t->Name);
+ }
+
+ /* free texture image */
+ {
+ GLuint i;
+ for (i=0;i<MAX_TEXTURE_LEVELS;i++) {
+ if (t->Image[i]) {
+ gl_free_texture_image( t->Image[i] );
+ }
+ }
+ }
+ /* free this object */
+ free( t );
+}
+
+
+
+/*
+ * Examine a texture object to determine if it is complete or not.
+ * The t->Complete flag will be set to GL_TRUE or GL_FALSE accordingly.
+ */
+void gl_test_texture_object_completeness( const GLcontext *ctx, struct gl_texture_object *t )
+{
+ t->Complete = GL_TRUE; /* be optimistic */
+
+ /* Always need level zero image */
+ if (!t->Image[0] || !t->Image[0]->Data) {
+ t->Complete = GL_FALSE;
+ return;
+ }
+
+ /* Compute number of mipmap levels */
+ if (t->Dimensions==1) {
+ t->P = t->Image[0]->WidthLog2;
+ }
+ else if (t->Dimensions==2) {
+ t->P = MAX2(t->Image[0]->WidthLog2, t->Image[0]->HeightLog2);
+ }
+ else if (t->Dimensions==3) {
+ GLint max = MAX2(t->Image[0]->WidthLog2, t->Image[0]->HeightLog2);
+ max = MAX2(max, (GLint)(t->Image[0]->DepthLog2));
+ t->P = max;
+ }
+
+ /* Compute M (see the 1.2 spec) used during mipmapping */
+ t->M = (GLfloat) (MIN2(t->MaxLevel, t->P) - t->BaseLevel);
+
+
+ if (t->MinFilter!=GL_NEAREST && t->MinFilter!=GL_LINEAR) {
+ /*
+ * Mipmapping: determine if we have a complete set of mipmaps
+ */
+ GLint i;
+ GLint minLevel = t->BaseLevel;
+ GLint maxLevel = MIN2(t->P, ctx->Const.MaxTextureLevels-1);
+ maxLevel = MIN2(maxLevel, t->MaxLevel);
+
+ if (minLevel > maxLevel) {
+ t->Complete = GL_FALSE;
+ return;
+ }
+
+ /* Test dimension-independent attributes */
+ for (i = minLevel; i <= maxLevel; i++) {
+ if (t->Image[i]) {
+ if (!t->Image[i]->Data) {
+ t->Complete = GL_FALSE;
+ return;
+ }
+ if (t->Image[i]->Format != t->Image[0]->Format) {
+ t->Complete = GL_FALSE;
+ return;
+ }
+ if (t->Image[i]->Border != t->Image[0]->Border) {
+ t->Complete = GL_FALSE;
+ return;
+ }
+ }
+ }
+
+ /* Test things which depend on number of texture image dimensions */
+ if (t->Dimensions==1) {
+ /* Test 1-D mipmaps */
+ GLuint width = t->Image[0]->Width2;
+ for (i=1; i<ctx->Const.MaxTextureLevels; i++) {
+ if (width>1) {
+ width /= 2;
+ }
+ if (i >= minLevel && i <= maxLevel) {
+ if (!t->Image[i]) {
+ t->Complete = GL_FALSE;
+ return;
+ }
+ if (!t->Image[i]->Data) {
+ t->Complete = GL_FALSE;
+ return;
+ }
+ if (t->Image[i]->Width2 != width ) {
+ t->Complete = GL_FALSE;
+ return;
+ }
+ }
+ if (width==1) {
+ return; /* found smallest needed mipmap, all done! */
+ }
+ }
+ }
+ else if (t->Dimensions==2) {
+ /* Test 2-D mipmaps */
+ GLuint width = t->Image[0]->Width2;
+ GLuint height = t->Image[0]->Height2;
+ for (i=1; i<ctx->Const.MaxTextureLevels; i++) {
+ if (width>1) {
+ width /= 2;
+ }
+ if (height>1) {
+ height /= 2;
+ }
+ if (i >= minLevel && i <= maxLevel) {
+ if (!t->Image[i]) {
+ t->Complete = GL_FALSE;
+ return;
+ }
+ if (t->Image[i]->Width2 != width) {
+ t->Complete = GL_FALSE;
+ return;
+ }
+ if (t->Image[i]->Height2 != height) {
+ t->Complete = GL_FALSE;
+ return;
+ }
+ if (width==1 && height==1) {
+ return; /* found smallest needed mipmap, all done! */
+ }
+ }
+ }
+ }
+ else if (t->Dimensions==3) {
+ /* Test 3-D mipmaps */
+ GLuint width = t->Image[0]->Width2;
+ GLuint height = t->Image[0]->Height2;
+ GLuint depth = t->Image[0]->Depth2;
+ for (i=1; i<ctx->Const.MaxTextureLevels; i++) {
+ if (width>1) {
+ width /= 2;
+ }
+ if (height>1) {
+ height /= 2;
+ }
+ if (depth>1) {
+ depth /= 2;
+ }
+ if (i >= minLevel && i <= maxLevel) {
+ if (!t->Image[i]) {
+ t->Complete = GL_FALSE;
+ return;
+ }
+ if (t->Image[i]->Width2 != width) {
+ t->Complete = GL_FALSE;
+ return;
+ }
+ if (t->Image[i]->Height2 != height) {
+ t->Complete = GL_FALSE;
+ return;
+ }
+ if (t->Image[i]->Depth2 != depth) {
+ t->Complete = GL_FALSE;
+ return;
+ }
+ }
+ if (width==1 && height==1 && depth==1) {
+ return; /* found smallest needed mipmap, all done! */
+ }
+ }
+ }
+ else {
+ /* Dimensions = ??? */
+ gl_problem(NULL, "Bug in gl_test_texture_object_completeness\n");
+ }
+ }
+}
+
+
+
+/*
+ * Execute glGenTextures
+ */
+void gl_GenTextures( GLcontext *ctx, GLsizei n, GLuint *texName )
+{
+ GLuint first;
+ GLint i;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGenTextures");
+ if (n<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glGenTextures" );
+ return;
+ }
+
+ first = HashFindFreeKeyBlock(ctx->Shared->TexObjects, n);
+
+ /* Return the texture names */
+ for (i=0;i<n;i++) {
+ texName[i] = first + i;
+ }
+
+ /* Allocate new, empty texture objects */
+ for (i=0;i<n;i++) {
+ GLuint name = first + i;
+ GLuint dims = 0;
+ (void) gl_alloc_texture_object(ctx->Shared, name, dims);
+ }
+}
+
+
+
+/*
+ * Execute glDeleteTextures
+ */
+void gl_DeleteTextures( GLcontext *ctx, GLsizei n, const GLuint *texName)
+{
+ GLint i;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDeleteTextures");
+
+ for (i=0;i<n;i++) {
+ struct gl_texture_object *t;
+ if (texName[i]>0) {
+ t = (struct gl_texture_object *)
+ HashLookup(ctx->Shared->TexObjects, texName[i]);
+ if (t) {
+ GLuint u;
+ for (u=0; u<MAX_TEXTURE_UNITS; u++) {
+ struct gl_texture_unit *unit = &ctx->Texture.Unit[u];
+ GLuint d;
+ for (d = 1 ; d <= 3 ; d++) {
+ if (unit->CurrentD[d]==t) {
+ unit->CurrentD[d] = ctx->Shared->DefaultD[d][u];
+ ctx->Shared->DefaultD[d][u]->RefCount++;
+ t->RefCount--;
+ assert( t->RefCount >= 0 );
+ }
+ }
+ }
+
+ /* tell device driver to delete texture */
+ if (ctx->Driver.DeleteTexture) {
+ (*ctx->Driver.DeleteTexture)( ctx, t );
+ }
+
+ if (t->RefCount==0) {
+ gl_free_texture_object(ctx->Shared, t);
+ }
+ }
+ }
+ }
+}
+
+
+
+/*
+ * Execute glBindTexture
+ */
+void gl_BindTexture( GLcontext *ctx, GLenum target, GLuint texName )
+{
+ GLuint unit = ctx->Texture.CurrentUnit;
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ struct gl_texture_object *oldTexObj;
+ struct gl_texture_object *newTexObj;
+ GLint dim;
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ fprintf(stderr, "glBindTexture %s %d\n",
+ gl_lookup_enum_by_nr(target), (GLint) texName);
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glBindTexture");
+
+ dim = target - GL_TEXTURE_1D;
+
+ if (dim < 0 || dim > 2) {
+ gl_error( ctx, GL_INVALID_ENUM, "glBindTexture" );
+ return;
+ }
+
+ dim++;
+ oldTexObj = texUnit->CurrentD[dim];
+
+ if (oldTexObj->Name == texName)
+ return;
+
+ if (texName == 0)
+ newTexObj = ctx->Shared->DefaultD[unit][dim];
+ else {
+ struct HashTable *hash = ctx->Shared->TexObjects;
+ newTexObj = (struct gl_texture_object *) HashLookup(hash, texName);
+
+ if (!newTexObj)
+ newTexObj = gl_alloc_texture_object(ctx->Shared, texName, dim);
+
+ if (newTexObj->Dimensions != dim) {
+ if (newTexObj->Dimensions) {
+ gl_error( ctx, GL_INVALID_OPERATION, "glBindTexture" );
+ return;
+ }
+ newTexObj->Dimensions = dim;
+ }
+ }
+
+ oldTexObj->RefCount--;
+ newTexObj->RefCount++;
+ texUnit->CurrentD[dim] = newTexObj;
+
+ /* If we've changed the CurrentD[123] texture object then update the
+ * ctx->Texture.Current pointer to point to the new texture object.
+ */
+ texUnit->Current = texUnit->CurrentD[texUnit->CurrentDimension];
+
+ /* Check if we may have to use a new triangle rasterizer */
+ if ((ctx->IndirectTriangles & DD_SW_RASTERIZE) &&
+ ( oldTexObj->WrapS != newTexObj->WrapS
+ || oldTexObj->WrapT != newTexObj->WrapT
+ || oldTexObj->WrapR != newTexObj->WrapR
+ || oldTexObj->MinFilter != newTexObj->MinFilter
+ || oldTexObj->MagFilter != newTexObj->MagFilter
+ || (oldTexObj->Image[0] && newTexObj->Image[0] &&
+ (oldTexObj->Image[0]->Format!=newTexObj->Image[0]->Format))))
+ {
+ ctx->NewState |= (NEW_RASTER_OPS | NEW_TEXTURING);
+ }
+
+ if (oldTexObj->Complete != newTexObj->Complete)
+ ctx->NewState |= NEW_TEXTURING;
+
+ /* Pass BindTexture call to device driver */
+ if (ctx->Driver.BindTexture) {
+ (*ctx->Driver.BindTexture)( ctx, target, newTexObj );
+ }
+}
+
+
+
+/*
+ * Execute glPrioritizeTextures
+ */
+void gl_PrioritizeTextures( GLcontext *ctx,
+ GLsizei n, const GLuint *texName,
+ const GLclampf *priorities )
+{
+ GLint i;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glPrioritizeTextures");
+ if (n<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glPrioritizeTextures" );
+ return;
+ }
+
+ for (i=0;i<n;i++) {
+ struct gl_texture_object *t;
+ if (texName[i]>0) {
+ t = (struct gl_texture_object *)
+ HashLookup(ctx->Shared->TexObjects, texName[i]);
+ if (t) {
+ t->Priority = CLAMP( priorities[i], 0.0F, 1.0F );
+ }
+ }
+ }
+}
+
+
+
+/*
+ * Execute glAreTexturesResident
+ */
+GLboolean gl_AreTexturesResident( GLcontext *ctx, GLsizei n,
+ const GLuint *texName,
+ GLboolean *residences )
+{
+ GLboolean resident = GL_TRUE;
+ GLint i;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx,
+ "glAreTexturesResident",
+ GL_FALSE);
+ if (n<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glAreTexturesResident(n)" );
+ return GL_FALSE;
+ }
+
+ for (i=0;i<n;i++) {
+ struct gl_texture_object *t;
+ if (texName[i]==0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glAreTexturesResident(textures)" );
+ return GL_FALSE;
+ }
+ t = (struct gl_texture_object *)
+ HashLookup(ctx->Shared->TexObjects, texName[i]);
+ if (t) {
+ /* we consider all valid texture objects to be resident */
+ residences[i] = GL_TRUE;
+ }
+ else {
+ gl_error( ctx, GL_INVALID_VALUE, "glAreTexturesResident(textures)" );
+ return GL_FALSE;
+ }
+ }
+ return resident;
+}
+
+
+
+/*
+ * Execute glIsTexture
+ */
+GLboolean gl_IsTexture( GLcontext *ctx, GLuint texture )
+{
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH_WITH_RETVAL(ctx, "glIsTextures",
+ GL_FALSE);
+ if (texture>0 && HashLookup(ctx->Shared->TexObjects, texture)) {
+ return GL_TRUE;
+ }
+ else {
+ return GL_FALSE;
+ }
+}
+
diff --git a/src/mesa/main/texobj.h b/src/mesa/main/texobj.h
new file mode 100644
index 0000000000..655c823753
--- /dev/null
+++ b/src/mesa/main/texobj.h
@@ -0,0 +1,85 @@
+/* $Id: texobj.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef TEXTOBJ_H
+#define TEXTOBJ_H
+
+
+#include "types.h"
+
+
+#ifdef VMS
+#define gl_test_texture_object_completeness gl_test_texture_object_complete
+#endif
+
+/*
+ * Internal functions
+ */
+
+extern struct gl_texture_object *
+gl_alloc_texture_object( struct gl_shared_state *shared, GLuint name,
+ GLuint dimensions );
+
+
+extern void gl_free_texture_object( struct gl_shared_state *shared,
+ struct gl_texture_object *t );
+
+
+extern void gl_test_texture_object_completeness( const GLcontext *ctx, struct gl_texture_object *t );
+
+
+/*
+ * API functions
+ */
+
+extern void gl_GenTextures( GLcontext *ctx, GLsizei n, GLuint *textures );
+
+
+extern void gl_DeleteTextures( GLcontext *ctx,
+ GLsizei n, const GLuint *textures);
+
+
+extern void gl_BindTexture( GLcontext *ctx, GLenum target, GLuint texture );
+
+
+extern void gl_PrioritizeTextures( GLcontext *ctx,
+ GLsizei n, const GLuint *textures,
+ const GLclampf *priorities );
+
+
+extern GLboolean gl_AreTexturesResident( GLcontext *ctx, GLsizei n,
+ const GLuint *textures,
+ GLboolean *residences );
+
+
+extern GLboolean gl_IsTexture( GLcontext *ctx, GLuint texture );
+
+
+#endif
diff --git a/src/mesa/main/texstate.c b/src/mesa/main/texstate.c
new file mode 100644
index 0000000000..eee5eaa0e4
--- /dev/null
+++ b/src/mesa/main/texstate.c
@@ -0,0 +1,1146 @@
+/* $Id: texstate.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <assert.h>
+#include <stdio.h>
+#include "context.h"
+#include "enums.h"
+#include "macros.h"
+#include "matrix.h"
+#include "texobj.h"
+#include "texstate.h"
+#include "texture.h"
+#include "types.h"
+#include "xform.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+
+#ifdef SPECIALCAST
+/* Needed for an Amiga compiler */
+#define ENUM_TO_FLOAT(X) ((GLfloat)(GLint)(X))
+#define ENUM_TO_DOUBLE(X) ((GLdouble)(GLint)(X))
+#else
+/* all other compilers */
+#define ENUM_TO_FLOAT(X) ((GLfloat)(X))
+#define ENUM_TO_DOUBLE(X) ((GLdouble)(X))
+#endif
+
+
+
+
+/**********************************************************************/
+/* Texture Environment */
+/**********************************************************************/
+
+
+void gl_TexEnvfv( GLcontext *ctx,
+ GLenum target, GLenum pname, const GLfloat *param )
+{
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexEnv");
+
+ if (target!=GL_TEXTURE_ENV) {
+ gl_error( ctx, GL_INVALID_ENUM, "glTexEnv(target)" );
+ return;
+ }
+
+ if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
+ fprintf(stderr, "glTexEnv %s %s %.1f(%s) ...\n",
+ gl_lookup_enum_by_nr(target),
+ gl_lookup_enum_by_nr(pname),
+ *param,
+ gl_lookup_enum_by_nr((GLenum) (GLint) *param));
+
+
+ if (pname==GL_TEXTURE_ENV_MODE) {
+ GLenum mode = (GLenum) (GLint) *param;
+ switch (mode) {
+ case GL_MODULATE:
+ case GL_BLEND:
+ case GL_DECAL:
+ case GL_REPLACE:
+ /* A small optimization for drivers */
+ if (texUnit->EnvMode == mode)
+ return;
+
+ if (MESA_VERBOSE & (VERBOSE_STATE|VERBOSE_TEXTURE))
+ fprintf(stderr, "glTexEnv: old mode %s, new mode %s\n",
+ gl_lookup_enum_by_nr(texUnit->EnvMode),
+ gl_lookup_enum_by_nr(mode));
+
+ texUnit->EnvMode = mode;
+ ctx->NewState |= NEW_TEXTURE_ENV;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_VALUE, "glTexEnv(param)" );
+ return;
+ }
+ }
+ else if (pname==GL_TEXTURE_ENV_COLOR) {
+ texUnit->EnvColor[0] = CLAMP( param[0], 0.0, 1.0 );
+ texUnit->EnvColor[1] = CLAMP( param[1], 0.0, 1.0 );
+ texUnit->EnvColor[2] = CLAMP( param[2], 0.0, 1.0 );
+ texUnit->EnvColor[3] = CLAMP( param[3], 0.0, 1.0 );
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM, "glTexEnv(pname)" );
+ return;
+ }
+
+ /* Tell device driver about the new texture environment */
+ if (ctx->Driver.TexEnv) {
+ (*ctx->Driver.TexEnv)( ctx, pname, param );
+ }
+}
+
+
+
+
+
+void gl_GetTexEnvfv( GLcontext *ctx,
+ GLenum target, GLenum pname, GLfloat *params )
+{
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ if (target!=GL_TEXTURE_ENV) {
+ gl_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(target)" );
+ return;
+ }
+ switch (pname) {
+ case GL_TEXTURE_ENV_MODE:
+ *params = ENUM_TO_FLOAT(texUnit->EnvMode);
+ break;
+ case GL_TEXTURE_ENV_COLOR:
+ COPY_4FV( params, texUnit->EnvColor );
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetTexEnvfv(pname)" );
+ }
+}
+
+
+void gl_GetTexEnviv( GLcontext *ctx,
+ GLenum target, GLenum pname, GLint *params )
+{
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ if (target!=GL_TEXTURE_ENV) {
+ gl_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(target)" );
+ return;
+ }
+ switch (pname) {
+ case GL_TEXTURE_ENV_MODE:
+ *params = (GLint) texUnit->EnvMode;
+ break;
+ case GL_TEXTURE_ENV_COLOR:
+ params[0] = FLOAT_TO_INT( texUnit->EnvColor[0] );
+ params[1] = FLOAT_TO_INT( texUnit->EnvColor[1] );
+ params[2] = FLOAT_TO_INT( texUnit->EnvColor[2] );
+ params[3] = FLOAT_TO_INT( texUnit->EnvColor[3] );
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetTexEnviv(pname)" );
+ }
+}
+
+
+
+
+/**********************************************************************/
+/* Texture Parameters */
+/**********************************************************************/
+
+
+void gl_TexParameterfv( GLcontext *ctx,
+ GLenum target, GLenum pname, const GLfloat *params )
+{
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ GLenum eparam = (GLenum) (GLint) params[0];
+ struct gl_texture_object *texObj;
+
+ if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
+ fprintf(stderr, "texPARAM %s %s %d...\n",
+ gl_lookup_enum_by_nr(target),
+ gl_lookup_enum_by_nr(pname),
+ eparam);
+
+
+ switch (target) {
+ case GL_TEXTURE_1D:
+ texObj = texUnit->CurrentD[1];
+ break;
+ case GL_TEXTURE_2D:
+ texObj = texUnit->CurrentD[2];
+ break;
+ case GL_TEXTURE_3D_EXT:
+ texObj = texUnit->CurrentD[3];
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glTexParameter(target)" );
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_MIN_FILTER:
+ /* A small optimization */
+ if (texObj->MinFilter == eparam)
+ return;
+
+ if (eparam==GL_NEAREST || eparam==GL_LINEAR
+ || eparam==GL_NEAREST_MIPMAP_NEAREST
+ || eparam==GL_LINEAR_MIPMAP_NEAREST
+ || eparam==GL_NEAREST_MIPMAP_LINEAR
+ || eparam==GL_LINEAR_MIPMAP_LINEAR) {
+ texObj->MinFilter = eparam;
+ ctx->NewState |= NEW_TEXTURING;
+ }
+ else {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
+ return;
+ }
+ break;
+ case GL_TEXTURE_MAG_FILTER:
+ /* A small optimization */
+ if (texObj->MagFilter == eparam)
+ return;
+
+ if (eparam==GL_NEAREST || eparam==GL_LINEAR) {
+ texObj->MagFilter = eparam;
+ ctx->NewState |= NEW_TEXTURING;
+ }
+ else {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
+ return;
+ }
+ break;
+ case GL_TEXTURE_WRAP_S:
+ if (texObj->WrapS == eparam)
+ return;
+
+ if (eparam==GL_CLAMP || eparam==GL_REPEAT || eparam==GL_CLAMP_TO_EDGE) {
+ texObj->WrapS = eparam;
+ ctx->NewState |= NEW_TEXTURING;
+ }
+ else {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
+ return;
+ }
+ break;
+ case GL_TEXTURE_WRAP_T:
+ if (texObj->WrapT == eparam)
+ return;
+
+ if (eparam==GL_CLAMP || eparam==GL_REPEAT || eparam==GL_CLAMP_TO_EDGE) {
+ texObj->WrapT = eparam;
+ ctx->NewState |= NEW_TEXTURING;
+ }
+ else {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
+ return;
+ }
+ break;
+ case GL_TEXTURE_WRAP_R_EXT:
+ if (texObj->WrapR == eparam)
+ return;
+
+ if (eparam==GL_CLAMP || eparam==GL_REPEAT || eparam==GL_CLAMP_TO_EDGE) {
+ texObj->WrapR = eparam;
+ ctx->NewState |= NEW_TEXTURING;
+ }
+ else {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
+ }
+ break;
+ case GL_TEXTURE_BORDER_COLOR:
+ texObj->BorderColor[0] = CLAMP((GLint)(params[0]*255.0), 0, 255);
+ texObj->BorderColor[1] = CLAMP((GLint)(params[1]*255.0), 0, 255);
+ texObj->BorderColor[2] = CLAMP((GLint)(params[2]*255.0), 0, 255);
+ texObj->BorderColor[3] = CLAMP((GLint)(params[3]*255.0), 0, 255);
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ texObj->MinLod = params[0];
+ ctx->NewState |= NEW_TEXTURING;
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ texObj->MaxLod = params[0];
+ ctx->NewState |= NEW_TEXTURING;
+ break;
+ case GL_TEXTURE_BASE_LEVEL:
+ if (params[0] < 0.0) {
+ gl_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
+ return;
+ }
+ texObj->BaseLevel = (GLint) params[0];
+ ctx->NewState |= NEW_TEXTURING;
+ break;
+ case GL_TEXTURE_MAX_LEVEL:
+ if (params[0] < 0.0) {
+ gl_error(ctx, GL_INVALID_VALUE, "glTexParameter(param)" );
+ return;
+ }
+ texObj->MaxLevel = (GLint) params[0];
+ ctx->NewState |= NEW_TEXTURING;
+ break;
+ case GL_TEXTURE_PRIORITY:
+ /* (keithh@netcomuk.co.uk) */
+ texObj->Priority = CLAMP( params[0], 0.0, 1.0 );
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glTexParameter(pname)" );
+ return;
+ }
+
+ gl_put_texobj_on_dirty_list( ctx, texObj );
+
+ if (ctx->Driver.TexParameter) {
+ (*ctx->Driver.TexParameter)( ctx, target, texObj, pname, params );
+ }
+}
+
+
+
+void gl_GetTexLevelParameterfv( GLcontext *ctx, GLenum target, GLint level,
+ GLenum pname, GLfloat *params )
+{
+ GLint iparam;
+ gl_GetTexLevelParameteriv( ctx, target, level, pname, &iparam );
+ *params = (GLfloat) iparam;
+}
+
+
+
+void gl_GetTexLevelParameteriv( GLcontext *ctx, GLenum target, GLint level,
+ GLenum pname, GLint *params )
+{
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ const struct gl_texture_image *img = NULL;
+ GLuint dimensions;
+
+ if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
+ gl_error( ctx, GL_INVALID_VALUE, "glGetTexLevelParameter[if]v" );
+ return;
+ }
+
+ switch (target) {
+ case GL_TEXTURE_1D:
+ img = texUnit->CurrentD[1]->Image[level];
+ dimensions = 1;
+ break;
+ case GL_TEXTURE_2D:
+ img = texUnit->CurrentD[2]->Image[level];
+ dimensions = 2;
+ break;
+ case GL_TEXTURE_3D:
+ img = texUnit->CurrentD[3]->Image[level];
+ dimensions = 3;
+ break;
+ case GL_PROXY_TEXTURE_1D:
+ img = ctx->Texture.Proxy1D->Image[level];
+ dimensions = 1;
+ break;
+ case GL_PROXY_TEXTURE_2D:
+ img = ctx->Texture.Proxy2D->Image[level];
+ dimensions = 2;
+ break;
+ case GL_PROXY_TEXTURE_3D:
+ img = ctx->Texture.Proxy3D->Image[level];
+ dimensions = 3;
+ break;
+ default:
+ gl_error(ctx, GL_INVALID_ENUM, "glGetTexLevelParameter[if]v(target)");
+ return;
+ }
+
+ if (!img) {
+ if (pname == GL_TEXTURE_COMPONENTS)
+ *params = 1;
+ else
+ *params = 0;
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_WIDTH:
+ *params = img->Width;
+ return;
+ case GL_TEXTURE_HEIGHT:
+ if (dimensions > 1) {
+ *params = img->Height;
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM,
+ "glGetTexLevelParameter[if]v(pname=GL_TEXTURE_HEIGHT)" );
+ }
+ return;
+ case GL_TEXTURE_DEPTH:
+ if (dimensions > 2) {
+ *params = img->Depth;
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM,
+ "glGetTexLevelParameter[if]v(pname=GL_TEXTURE_DEPTH)" );
+ }
+ return;
+ case GL_TEXTURE_COMPONENTS:
+ *params = img->IntFormat;
+ return;
+ case GL_TEXTURE_BORDER:
+ *params = img->Border;
+ return;
+ case GL_TEXTURE_RED_SIZE:
+ *params = img->RedBits;
+ return;
+ case GL_TEXTURE_GREEN_SIZE:
+ *params = img->GreenBits;
+ return;
+ case GL_TEXTURE_BLUE_SIZE:
+ *params = img->BlueBits;
+ return;
+ case GL_TEXTURE_ALPHA_SIZE:
+ *params = img->AlphaBits;
+ return;
+ case GL_TEXTURE_INTENSITY_SIZE:
+ *params = img->IntensityBits;
+ return;
+ case GL_TEXTURE_LUMINANCE_SIZE:
+ *params = img->LuminanceBits;
+ return;
+ case GL_TEXTURE_INDEX_SIZE_EXT:
+ *params = img->IndexBits;
+ return;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM,
+ "glGetTexLevelParameter[if]v(pname)" );
+ }
+}
+
+
+
+
+void gl_GetTexParameterfv( GLcontext *ctx,
+ GLenum target, GLenum pname, GLfloat *params )
+{
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ struct gl_texture_object *obj;
+
+ switch (target) {
+ case GL_TEXTURE_1D:
+ obj = texUnit->CurrentD[1];
+ break;
+ case GL_TEXTURE_2D:
+ obj = texUnit->CurrentD[2];
+ break;
+ case GL_TEXTURE_3D_EXT:
+ obj = texUnit->CurrentD[3];
+ break;
+ default:
+ gl_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(target)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_MAG_FILTER:
+ *params = ENUM_TO_FLOAT(obj->MagFilter);
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ *params = ENUM_TO_FLOAT(obj->MinFilter);
+ break;
+ case GL_TEXTURE_WRAP_S:
+ *params = ENUM_TO_FLOAT(obj->WrapS);
+ break;
+ case GL_TEXTURE_WRAP_T:
+ *params = ENUM_TO_FLOAT(obj->WrapT);
+ break;
+ case GL_TEXTURE_WRAP_R_EXT:
+ *params = ENUM_TO_FLOAT(obj->WrapR);
+ break;
+ case GL_TEXTURE_BORDER_COLOR:
+ params[0] = obj->BorderColor[0] / 255.0F;
+ params[1] = obj->BorderColor[1] / 255.0F;
+ params[2] = obj->BorderColor[2] / 255.0F;
+ params[3] = obj->BorderColor[3] / 255.0F;
+ break;
+ case GL_TEXTURE_RESIDENT:
+ *params = ENUM_TO_FLOAT(GL_TRUE);
+ break;
+ case GL_TEXTURE_PRIORITY:
+ *params = obj->Priority;
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ *params = obj->MinLod;
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ *params = obj->MaxLod;
+ break;
+ case GL_TEXTURE_BASE_LEVEL:
+ *params = obj->BaseLevel;
+ break;
+ case GL_TEXTURE_MAX_LEVEL:
+ *params = obj->MaxLevel;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetTexParameterfv(pname)" );
+ }
+}
+
+
+void gl_GetTexParameteriv( GLcontext *ctx,
+ GLenum target, GLenum pname, GLint *params )
+{
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
+ struct gl_texture_object *obj;
+
+ switch (target) {
+ case GL_TEXTURE_1D:
+ obj = texUnit->CurrentD[1];
+ break;
+ case GL_TEXTURE_2D:
+ obj = texUnit->CurrentD[2];
+ break;
+ case GL_TEXTURE_3D_EXT:
+ obj = texUnit->CurrentD[3];
+ break;
+ default:
+ gl_error(ctx, GL_INVALID_ENUM, "glGetTexParameterfv(target)");
+ return;
+ }
+
+ switch (pname) {
+ case GL_TEXTURE_MAG_FILTER:
+ *params = (GLint) obj->MagFilter;
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ *params = (GLint) obj->MinFilter;
+ break;
+ case GL_TEXTURE_WRAP_S:
+ *params = (GLint) obj->WrapS;
+ break;
+ case GL_TEXTURE_WRAP_T:
+ *params = (GLint) obj->WrapT;
+ break;
+ case GL_TEXTURE_WRAP_R_EXT:
+ *params = (GLint) obj->WrapR;
+ break;
+ case GL_TEXTURE_BORDER_COLOR:
+ {
+ GLfloat color[4];
+ color[0] = obj->BorderColor[0]/255.0;
+ color[1] = obj->BorderColor[1]/255.0;
+ color[2] = obj->BorderColor[2]/255.0;
+ color[3] = obj->BorderColor[3]/255.0;
+ params[0] = FLOAT_TO_INT( color[0] );
+ params[1] = FLOAT_TO_INT( color[1] );
+ params[2] = FLOAT_TO_INT( color[2] );
+ params[3] = FLOAT_TO_INT( color[3] );
+ }
+ break;
+ case GL_TEXTURE_RESIDENT:
+ *params = (GLint) GL_TRUE;
+ break;
+ case GL_TEXTURE_PRIORITY:
+ *params = (GLint) obj->Priority;
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ *params = (GLint) obj->MinLod;
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ *params = (GLint) obj->MaxLod;
+ break;
+ case GL_TEXTURE_BASE_LEVEL:
+ *params = obj->BaseLevel;
+ break;
+ case GL_TEXTURE_MAX_LEVEL:
+ *params = obj->MaxLevel;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetTexParameteriv(pname)" );
+ }
+}
+
+
+
+
+/**********************************************************************/
+/* Texture Coord Generation */
+/**********************************************************************/
+
+
+void gl_TexGenfv( GLcontext *ctx,
+ GLenum coord, GLenum pname, const GLfloat *params )
+{
+ GLuint tUnit = ctx->Texture.CurrentTransformUnit;
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[tUnit];
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexGenfv");
+
+ if (MESA_VERBOSE&(VERBOSE_API|VERBOSE_TEXTURE))
+ fprintf(stderr, "texGEN %s %s %x...\n",
+ gl_lookup_enum_by_nr(coord),
+ gl_lookup_enum_by_nr(pname),
+ *(int *)params);
+
+ switch( coord ) {
+ case GL_S:
+ if (pname==GL_TEXTURE_GEN_MODE) {
+ GLenum mode = (GLenum) (GLint) *params;
+ switch (mode) {
+ case GL_OBJECT_LINEAR:
+ texUnit->GenModeS = mode;
+ texUnit->GenBitS = TEXGEN_OBJ_LINEAR;
+ break;
+ case GL_EYE_LINEAR:
+ texUnit->GenModeS = mode;
+ texUnit->GenBitS = TEXGEN_EYE_LINEAR;
+ break;
+ case GL_REFLECTION_MAP_NV:
+ texUnit->GenModeS = mode;
+ texUnit->GenBitS = TEXGEN_REFLECTION_MAP_NV;
+ break;
+ case GL_NORMAL_MAP_NV:
+ texUnit->GenModeS = mode;
+ texUnit->GenBitS = TEXGEN_NORMAL_MAP_NV;
+ break;
+ case GL_SPHERE_MAP:
+ texUnit->GenModeS = mode;
+ texUnit->GenBitS = TEXGEN_SPHERE_MAP;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
+ return;
+ }
+ }
+ else if (pname==GL_OBJECT_PLANE) {
+ texUnit->ObjectPlaneS[0] = params[0];
+ texUnit->ObjectPlaneS[1] = params[1];
+ texUnit->ObjectPlaneS[2] = params[2];
+ texUnit->ObjectPlaneS[3] = params[3];
+ }
+ else if (pname==GL_EYE_PLANE) {
+ /* Transform plane equation by the inverse modelview matrix */
+ if (ctx->ModelView.flags & MAT_DIRTY_INVERSE) {
+ gl_matrix_analyze( &ctx->ModelView );
+ }
+ gl_transform_vector( texUnit->EyePlaneS, params,
+ ctx->ModelView.inv );
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" );
+ return;
+ }
+ break;
+ case GL_T:
+ if (pname==GL_TEXTURE_GEN_MODE) {
+ GLenum mode = (GLenum) (GLint) *params;
+ switch(mode) {
+ case GL_OBJECT_LINEAR:
+ texUnit->GenModeT = GL_OBJECT_LINEAR;
+ texUnit->GenBitT = TEXGEN_OBJ_LINEAR;
+ break;
+ case GL_EYE_LINEAR:
+ texUnit->GenModeT = GL_EYE_LINEAR;
+ texUnit->GenBitT = TEXGEN_EYE_LINEAR;
+ break;
+ case GL_REFLECTION_MAP_NV:
+ texUnit->GenModeT = GL_REFLECTION_MAP_NV;
+ texUnit->GenBitT = TEXGEN_REFLECTION_MAP_NV;
+ break;
+ case GL_NORMAL_MAP_NV:
+ texUnit->GenModeT = GL_NORMAL_MAP_NV;
+ texUnit->GenBitT = TEXGEN_NORMAL_MAP_NV;
+ break;
+ case GL_SPHERE_MAP:
+ texUnit->GenModeT = GL_SPHERE_MAP;
+ texUnit->GenBitT = TEXGEN_SPHERE_MAP;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
+ return;
+ }
+ }
+ else if (pname==GL_OBJECT_PLANE) {
+ texUnit->ObjectPlaneT[0] = params[0];
+ texUnit->ObjectPlaneT[1] = params[1];
+ texUnit->ObjectPlaneT[2] = params[2];
+ texUnit->ObjectPlaneT[3] = params[3];
+ }
+ else if (pname==GL_EYE_PLANE) {
+ /* Transform plane equation by the inverse modelview matrix */
+ if (ctx->ModelView.flags & MAT_DIRTY_INVERSE) {
+ gl_matrix_analyze( &ctx->ModelView );
+ }
+ gl_transform_vector( texUnit->EyePlaneT, params,
+ ctx->ModelView.inv );
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" );
+ return;
+ }
+ break;
+ case GL_R:
+ if (pname==GL_TEXTURE_GEN_MODE) {
+ GLenum mode = (GLenum) (GLint) *params;
+ switch (mode) {
+ case GL_OBJECT_LINEAR:
+ texUnit->GenModeR = GL_OBJECT_LINEAR;
+ texUnit->GenBitR = TEXGEN_OBJ_LINEAR;
+ break;
+ case GL_REFLECTION_MAP_NV:
+ texUnit->GenModeR = GL_REFLECTION_MAP_NV;
+ texUnit->GenBitR = TEXGEN_REFLECTION_MAP_NV;
+ break;
+ case GL_NORMAL_MAP_NV:
+ texUnit->GenModeR = GL_NORMAL_MAP_NV;
+ texUnit->GenBitR = TEXGEN_NORMAL_MAP_NV;
+ break;
+ case GL_EYE_LINEAR:
+ texUnit->GenModeR = GL_EYE_LINEAR;
+ texUnit->GenBitR = TEXGEN_EYE_LINEAR;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
+ return;
+ }
+ }
+ else if (pname==GL_OBJECT_PLANE) {
+ texUnit->ObjectPlaneR[0] = params[0];
+ texUnit->ObjectPlaneR[1] = params[1];
+ texUnit->ObjectPlaneR[2] = params[2];
+ texUnit->ObjectPlaneR[3] = params[3];
+ }
+ else if (pname==GL_EYE_PLANE) {
+ /* Transform plane equation by the inverse modelview matrix */
+ if (ctx->ModelView.flags & MAT_DIRTY_INVERSE) {
+ gl_matrix_analyze( &ctx->ModelView );
+ }
+ gl_transform_vector( texUnit->EyePlaneR, params,
+ ctx->ModelView.inv );
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" );
+ return;
+ }
+ break;
+ case GL_Q:
+ if (pname==GL_TEXTURE_GEN_MODE) {
+ GLenum mode = (GLenum) (GLint) *params;
+ switch (mode) {
+ case GL_OBJECT_LINEAR:
+ texUnit->GenModeQ = GL_OBJECT_LINEAR;
+ texUnit->GenBitQ = TEXGEN_OBJ_LINEAR;
+ break;
+ case GL_EYE_LINEAR:
+ texUnit->GenModeQ = GL_EYE_LINEAR;
+ texUnit->GenBitQ = TEXGEN_EYE_LINEAR;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(param)" );
+ return;
+ }
+ }
+ else if (pname==GL_OBJECT_PLANE) {
+ texUnit->ObjectPlaneQ[0] = params[0];
+ texUnit->ObjectPlaneQ[1] = params[1];
+ texUnit->ObjectPlaneQ[2] = params[2];
+ texUnit->ObjectPlaneQ[3] = params[3];
+ }
+ else if (pname==GL_EYE_PLANE) {
+ /* Transform plane equation by the inverse modelview matrix */
+ if (ctx->ModelView.flags & MAT_DIRTY_INVERSE) {
+ gl_matrix_analyze( &ctx->ModelView );
+ }
+ gl_transform_vector( texUnit->EyePlaneQ, params,
+ ctx->ModelView.inv );
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(pname)" );
+ return;
+ }
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glTexGenfv(coord)" );
+ return;
+ }
+
+ ctx->NewState |= NEW_TEXTURING;
+}
+
+
+
+void gl_GetTexGendv( GLcontext *ctx,
+ GLenum coord, GLenum pname, GLdouble *params )
+{
+ GLuint tUnit = ctx->Texture.CurrentTransformUnit;
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[tUnit];
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexGendv");
+
+ switch( coord ) {
+ case GL_S:
+ if (pname==GL_TEXTURE_GEN_MODE) {
+ params[0] = ENUM_TO_DOUBLE(texUnit->GenModeS);
+ }
+ else if (pname==GL_OBJECT_PLANE) {
+ COPY_4V( params, texUnit->ObjectPlaneS );
+ }
+ else if (pname==GL_EYE_PLANE) {
+ COPY_4V( params, texUnit->EyePlaneS );
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" );
+ return;
+ }
+ break;
+ case GL_T:
+ if (pname==GL_TEXTURE_GEN_MODE) {
+ params[0] = ENUM_TO_DOUBLE(texUnit->GenModeT);
+ }
+ else if (pname==GL_OBJECT_PLANE) {
+ COPY_4V( params, texUnit->ObjectPlaneT );
+ }
+ else if (pname==GL_EYE_PLANE) {
+ COPY_4V( params, texUnit->EyePlaneT );
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" );
+ return;
+ }
+ break;
+ case GL_R:
+ if (pname==GL_TEXTURE_GEN_MODE) {
+ params[0] = ENUM_TO_DOUBLE(texUnit->GenModeR);
+ }
+ else if (pname==GL_OBJECT_PLANE) {
+ COPY_4V( params, texUnit->ObjectPlaneR );
+ }
+ else if (pname==GL_EYE_PLANE) {
+ COPY_4V( params, texUnit->EyePlaneR );
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" );
+ return;
+ }
+ break;
+ case GL_Q:
+ if (pname==GL_TEXTURE_GEN_MODE) {
+ params[0] = ENUM_TO_DOUBLE(texUnit->GenModeQ);
+ }
+ else if (pname==GL_OBJECT_PLANE) {
+ COPY_4V( params, texUnit->ObjectPlaneQ );
+ }
+ else if (pname==GL_EYE_PLANE) {
+ COPY_4V( params, texUnit->EyePlaneQ );
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(pname)" );
+ return;
+ }
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetTexGendv(coord)" );
+ return;
+ }
+}
+
+
+
+void gl_GetTexGenfv( GLcontext *ctx,
+ GLenum coord, GLenum pname, GLfloat *params )
+{
+ GLuint tUnit = ctx->Texture.CurrentTransformUnit;
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[tUnit];
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexGenfv");
+
+ switch( coord ) {
+ case GL_S:
+ if (pname==GL_TEXTURE_GEN_MODE) {
+ params[0] = ENUM_TO_FLOAT(texUnit->GenModeS);
+ }
+ else if (pname==GL_OBJECT_PLANE) {
+ COPY_4V( params, texUnit->ObjectPlaneS );
+ }
+ else if (pname==GL_EYE_PLANE) {
+ COPY_4V( params, texUnit->EyePlaneS );
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" );
+ return;
+ }
+ break;
+ case GL_T:
+ if (pname==GL_TEXTURE_GEN_MODE) {
+ params[0] = ENUM_TO_FLOAT(texUnit->GenModeT);
+ }
+ else if (pname==GL_OBJECT_PLANE) {
+ COPY_4V( params, texUnit->ObjectPlaneT );
+ }
+ else if (pname==GL_EYE_PLANE) {
+ COPY_4V( params, texUnit->EyePlaneT );
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" );
+ return;
+ }
+ break;
+ case GL_R:
+ if (pname==GL_TEXTURE_GEN_MODE) {
+ params[0] = ENUM_TO_FLOAT(texUnit->GenModeR);
+ }
+ else if (pname==GL_OBJECT_PLANE) {
+ COPY_4V( params, texUnit->ObjectPlaneR );
+ }
+ else if (pname==GL_EYE_PLANE) {
+ COPY_4V( params, texUnit->EyePlaneR );
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" );
+ return;
+ }
+ break;
+ case GL_Q:
+ if (pname==GL_TEXTURE_GEN_MODE) {
+ params[0] = ENUM_TO_FLOAT(texUnit->GenModeQ);
+ }
+ else if (pname==GL_OBJECT_PLANE) {
+ COPY_4V( params, texUnit->ObjectPlaneQ );
+ }
+ else if (pname==GL_EYE_PLANE) {
+ COPY_4V( params, texUnit->EyePlaneQ );
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(pname)" );
+ return;
+ }
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetTexGenfv(coord)" );
+ return;
+ }
+}
+
+
+
+void gl_GetTexGeniv( GLcontext *ctx,
+ GLenum coord, GLenum pname, GLint *params )
+{
+ GLuint tUnit = ctx->Texture.CurrentTransformUnit;
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[tUnit];
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexGeniv");
+
+ switch( coord ) {
+ case GL_S:
+ if (pname==GL_TEXTURE_GEN_MODE) {
+ params[0] = texUnit->GenModeS;
+ }
+ else if (pname==GL_OBJECT_PLANE) {
+ COPY_4V( params, texUnit->ObjectPlaneS );
+ }
+ else if (pname==GL_EYE_PLANE) {
+ COPY_4V( params, texUnit->EyePlaneS );
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" );
+ return;
+ }
+ break;
+ case GL_T:
+ if (pname==GL_TEXTURE_GEN_MODE) {
+ params[0] = texUnit->GenModeT;
+ }
+ else if (pname==GL_OBJECT_PLANE) {
+ COPY_4V( params, texUnit->ObjectPlaneT );
+ }
+ else if (pname==GL_EYE_PLANE) {
+ COPY_4V( params, texUnit->EyePlaneT );
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" );
+ return;
+ }
+ break;
+ case GL_R:
+ if (pname==GL_TEXTURE_GEN_MODE) {
+ params[0] = texUnit->GenModeR;
+ }
+ else if (pname==GL_OBJECT_PLANE) {
+ COPY_4V( params, texUnit->ObjectPlaneR );
+ }
+ else if (pname==GL_EYE_PLANE) {
+ COPY_4V( params, texUnit->EyePlaneR );
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" );
+ return;
+ }
+ break;
+ case GL_Q:
+ if (pname==GL_TEXTURE_GEN_MODE) {
+ params[0] = texUnit->GenModeQ;
+ }
+ else if (pname==GL_OBJECT_PLANE) {
+ COPY_4V( params, texUnit->ObjectPlaneQ );
+ }
+ else if (pname==GL_EYE_PLANE) {
+ COPY_4V( params, texUnit->EyePlaneQ );
+ }
+ else {
+ gl_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(pname)" );
+ return;
+ }
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glGetTexGeniv(coord)" );
+ return;
+ }
+}
+
+
+/* GL_ARB_multitexture */
+void gl_ActiveTexture( GLcontext *ctx, GLenum target )
+{
+ GLint maxUnits = ctx->Const.MaxTextureUnits;
+
+ ASSERT_OUTSIDE_BEGIN_END( ctx, "glActiveTextureARB" );
+
+ if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
+ fprintf(stderr, "glActiveTexture %s\n",
+ gl_lookup_enum_by_nr(target));
+
+ if (target >= GL_TEXTURE0_ARB && target < GL_TEXTURE0_ARB + maxUnits) {
+ GLint texUnit = target - GL_TEXTURE0_ARB;
+ ctx->TexCoordUnit = texUnit;
+ ctx->Texture.CurrentUnit = texUnit;
+ ctx->Texture.CurrentTransformUnit = texUnit;
+ if (ctx->Driver.ActiveTexture) {
+ (*ctx->Driver.ActiveTexture)( ctx, (GLuint) texUnit );
+ }
+ }
+ else {
+ gl_error(ctx, GL_INVALID_OPERATION, "glActiveTextureARB(target)");
+ }
+}
+
+
+/* GL_ARB_multitexture */
+void gl_ClientActiveTexture( GLcontext *ctx, GLenum target )
+{
+ GLint maxUnits = ctx->Const.MaxTextureUnits;
+
+ ASSERT_OUTSIDE_BEGIN_END( ctx, "glClientActiveTextureARB" );
+
+ if (target >= GL_TEXTURE0_ARB && target < GL_TEXTURE0_ARB + maxUnits) {
+ GLint texUnit = target - GL_TEXTURE0_ARB;
+ ctx->Array.ActiveTexture = texUnit;
+ }
+ else {
+ gl_error(ctx, GL_INVALID_OPERATION, "glActiveTextureARB(target)");
+ }
+}
+
+
+
+/*
+ * Put the given texture object into the list of dirty texture objects.
+ * When a texture object is dirty we have to reexamine it for completeness
+ * and perhaps choose a different texture sampling function.
+ */
+void gl_put_texobj_on_dirty_list( GLcontext *ctx, struct gl_texture_object *t )
+{
+ ASSERT(ctx);
+ ASSERT(t);
+ /* Only insert if not already in the dirty list.
+ * The Dirty flag is only set iff the texture object is in the dirty list.
+ */
+ if (!t->Dirty) {
+ ASSERT(t->NextDirty == NULL);
+ t->Dirty = GL_TRUE;
+ t->NextDirty = ctx->Shared->DirtyTexObjList;
+ ctx->Shared->DirtyTexObjList = t;
+ }
+#ifdef DEBUG
+ else {
+ /* make sure t is in the list */
+ struct gl_texture_object *obj = ctx->Shared->DirtyTexObjList;
+ while (obj) {
+ if (obj == t) {
+ return;
+ }
+ obj = obj->NextDirty;
+ }
+ gl_problem(ctx, "Error in gl_put_texobj_on_dirty_list");
+ }
+#endif
+}
+
+
+/*
+ * Remove a texture object from the dirty texture list.
+ */
+void gl_remove_texobj_from_dirty_list( struct gl_shared_state *shared,
+ struct gl_texture_object *tObj )
+{
+ struct gl_texture_object *t, *prev = NULL;
+ ASSERT(shared);
+ ASSERT(tObj);
+ for (t = shared->DirtyTexObjList; t; t = t->NextDirty) {
+ if (t == tObj) {
+ if (prev) {
+ prev->NextDirty = t->NextDirty;
+ }
+ else {
+ shared->DirtyTexObjList = t->NextDirty;
+ }
+ return;
+ }
+ prev = t;
+ }
+}
+
+
+/*
+ * This is called by gl_update_state() if the NEW_TEXTURING bit in
+ * ctx->NewState is unit.
+ */
+void gl_update_dirty_texobjs( GLcontext *ctx )
+{
+ struct gl_texture_object *t, *next;
+ for (t = ctx->Shared->DirtyTexObjList; t; t = next) {
+ next = t->NextDirty;
+ gl_test_texture_object_completeness(ctx, t);
+ gl_set_texture_sampler(t);
+ t->NextDirty = NULL;
+ t->Dirty = GL_FALSE;
+ }
+ ctx->Shared->DirtyTexObjList = NULL;
+}
diff --git a/src/mesa/main/texstate.h b/src/mesa/main/texstate.h
new file mode 100644
index 0000000000..870693bfa7
--- /dev/null
+++ b/src/mesa/main/texstate.h
@@ -0,0 +1,112 @@
+/* $Id: texstate.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef TEXSTATE_H
+#define TEXSTATE_H
+
+
+#include "types.h"
+
+
+/*** Called from API ***/
+
+extern void gl_GetTexEnvfv( GLcontext *ctx,
+ GLenum target, GLenum pname, GLfloat *params );
+
+extern void gl_GetTexEnviv( GLcontext *ctx,
+ GLenum target, GLenum pname, GLint *params );
+
+extern void gl_GetTexGendv( GLcontext *ctx,
+ GLenum coord, GLenum pname, GLdouble *params );
+
+extern void gl_GetTexGenfv( GLcontext *ctx,
+ GLenum coord, GLenum pname, GLfloat *params );
+
+extern void gl_GetTexGeniv( GLcontext *ctx,
+ GLenum coord, GLenum pname, GLint *params );
+
+extern void gl_GetTexLevelParameterfv( GLcontext *ctx,
+ GLenum target, GLint level,
+ GLenum pname, GLfloat *params );
+
+extern void gl_GetTexLevelParameteriv( GLcontext *ctx,
+ GLenum target, GLint level,
+ GLenum pname, GLint *params );
+
+extern void gl_GetTexParameterfv( GLcontext *ctx, GLenum target,
+ GLenum pname, GLfloat *params );
+
+extern void gl_GetTexParameteriv( GLcontext *ctx,
+ GLenum target, GLenum pname, GLint *params );
+
+
+extern void gl_TexEnvfv( GLcontext *ctx,
+ GLenum target, GLenum pname, const GLfloat *param );
+
+
+extern void gl_TexParameterfv( GLcontext *ctx, GLenum target, GLenum pname,
+ const GLfloat *params );
+
+
+extern void gl_TexGenfv( GLcontext *ctx,
+ GLenum coord, GLenum pname, const GLfloat *params );
+
+
+
+extern void gl_SelectTextureTransform( GLcontext *ctx, GLenum target );
+
+
+/*
+ * GL_ARB_multitexture
+ */
+extern void gl_ActiveTexture( GLcontext *ctx, GLenum target );
+
+extern void gl_ClientActiveTexture( GLcontext *ctx, GLenum target );
+
+
+
+/*** Internal functions ***/
+
+extern void
+gl_put_texobj_on_dirty_list( GLcontext *ctx, struct gl_texture_object *t );
+
+#ifdef VMS
+#define gl_remove_texobj_from_dirty_list gl_remove_texobj_from_dirty_lis
+#endif
+extern void
+gl_remove_texobj_from_dirty_list( struct gl_shared_state *shared,
+ struct gl_texture_object *tObj );
+
+extern void
+gl_update_dirty_texobjs( GLcontext *ctx );
+
+
+#endif
+
diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c
new file mode 100644
index 0000000000..b63d6a7cce
--- /dev/null
+++ b/src/mesa/main/varray.c
@@ -0,0 +1,1259 @@
+/* $Id: varray.c,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+#ifdef PC_HEADER
+#include "all.h"
+#else
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "context.h"
+#include "api.h"
+#include "cva.h"
+#include "enable.h"
+#include "enums.h"
+#include "dlist.h"
+#include "light.h"
+#include "macros.h"
+#include "mmath.h"
+#include "pipeline.h"
+#include "texstate.h"
+#include "translate.h"
+#include "types.h"
+#include "varray.h"
+#include "vb.h"
+#include "vbfill.h"
+#include "vbrender.h"
+#include "vbindirect.h"
+#include "vbxform.h"
+#include "xform.h"
+#ifdef XFree86Server
+#include "GL/xf86glx.h"
+#endif
+#endif
+
+
+void GLAPIENTRY glVertexPointer(CTX_ARG GLint size, GLenum type, GLsizei stride,
+ const GLvoid *ptr )
+{
+ GLcontext *ctx;
+ GET_CONTEXT;
+ CHECK_CONTEXT;
+ ctx = CC;
+
+ if (size<2 || size>4) {
+ gl_error( ctx, GL_INVALID_VALUE, "glVertexPointer(size)" );
+ return;
+ }
+ if (stride<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glVertexPointer(stride)" );
+ return;
+ }
+
+ if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
+ fprintf(stderr, "glVertexPointer( sz %d type %s stride %d )\n", size,
+ gl_lookup_enum_by_nr( type ),
+ stride);
+
+ ctx->Array.Vertex.StrideB = stride;
+ if (!stride) {
+ switch (type) {
+ case GL_SHORT:
+ ctx->Array.Vertex.StrideB = size*sizeof(GLshort);
+ break;
+ case GL_INT:
+ ctx->Array.Vertex.StrideB = size*sizeof(GLint);
+ break;
+ case GL_FLOAT:
+ ctx->Array.Vertex.StrideB = size*sizeof(GLfloat);
+ break;
+ case GL_DOUBLE:
+ ctx->Array.Vertex.StrideB = size*sizeof(GLdouble);
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type)" );
+ return;
+ }
+ }
+ ctx->Array.Vertex.Size = size;
+ ctx->Array.Vertex.Type = type;
+ ctx->Array.Vertex.Stride = stride;
+ ctx->Array.Vertex.Ptr = (void *) ptr;
+ ctx->Array.VertexFunc = gl_trans_4f_tab[size][TYPE_IDX(type)];
+ ctx->Array.VertexEltFunc = gl_trans_elt_4f_tab[size][TYPE_IDX(type)];
+ ctx->Array.NewArrayState |= VERT_OBJ_ANY;
+ ctx->NewState |= NEW_CLIENT_STATE;
+}
+
+
+
+
+void GLAPIENTRY glNormalPointer(CTX_ARG GLenum type, GLsizei stride,
+ const GLvoid *ptr )
+{
+ GLcontext *ctx;
+ GET_CONTEXT;
+ CHECK_CONTEXT;
+ ctx = CC;
+
+ if (stride<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glNormalPointer(stride)" );
+ return;
+ }
+
+ if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
+ fprintf(stderr, "glNormalPointer( type %s stride %d )\n",
+ gl_lookup_enum_by_nr( type ),
+ stride);
+
+ ctx->Array.Normal.StrideB = stride;
+ if (!stride) {
+ switch (type) {
+ case GL_BYTE:
+ ctx->Array.Normal.StrideB = 3*sizeof(GLbyte);
+ break;
+ case GL_SHORT:
+ ctx->Array.Normal.StrideB = 3*sizeof(GLshort);
+ break;
+ case GL_INT:
+ ctx->Array.Normal.StrideB = 3*sizeof(GLint);
+ break;
+ case GL_FLOAT:
+ ctx->Array.Normal.StrideB = 3*sizeof(GLfloat);
+ break;
+ case GL_DOUBLE:
+ ctx->Array.Normal.StrideB = 3*sizeof(GLdouble);
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type)" );
+ return;
+ }
+ }
+ ctx->Array.Normal.Type = type;
+ ctx->Array.Normal.Stride = stride;
+ ctx->Array.Normal.Ptr = (void *) ptr;
+ ctx->Array.NormalFunc = gl_trans_3f_tab[TYPE_IDX(type)];
+ ctx->Array.NormalEltFunc = gl_trans_elt_3f_tab[TYPE_IDX(type)];
+ ctx->Array.NewArrayState |= VERT_NORM;
+ ctx->NewState |= NEW_CLIENT_STATE;
+}
+
+
+
+void GLAPIENTRY glColorPointer(CTX_ARG GLint size, GLenum type, GLsizei stride,
+ const GLvoid *ptr )
+{
+ GLcontext *ctx;
+ GET_CONTEXT;
+ CHECK_CONTEXT;
+ ctx = CC;
+ if (size<3 || size>4) {
+ gl_error( ctx, GL_INVALID_VALUE, "glColorPointer(size)" );
+ return;
+ }
+ if (stride<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glColorPointer(stride)" );
+ return;
+ }
+
+ if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
+ fprintf(stderr, "glColorPointer( sz %d type %s stride %d )\n", size,
+ gl_lookup_enum_by_nr( type ),
+ stride);
+
+ ctx->Array.Color.StrideB = stride;
+ if (!stride) {
+ switch (type) {
+ case GL_BYTE:
+ ctx->Array.Color.StrideB = size*sizeof(GLbyte);
+ break;
+ case GL_UNSIGNED_BYTE:
+ ctx->Array.Color.StrideB = size*sizeof(GLubyte);
+ break;
+ case GL_SHORT:
+ ctx->Array.Color.StrideB = size*sizeof(GLshort);
+ break;
+ case GL_UNSIGNED_SHORT:
+ ctx->Array.Color.StrideB = size*sizeof(GLushort);
+ break;
+ case GL_INT:
+ ctx->Array.Color.StrideB = size*sizeof(GLint);
+ break;
+ case GL_UNSIGNED_INT:
+ ctx->Array.Color.StrideB = size*sizeof(GLuint);
+ break;
+ case GL_FLOAT:
+ ctx->Array.Color.StrideB = size*sizeof(GLfloat);
+ break;
+ case GL_DOUBLE:
+ ctx->Array.Color.StrideB = size*sizeof(GLdouble);
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glColorPointer(type)" );
+ return;
+ }
+ }
+ ctx->Array.Color.Size = size;
+ ctx->Array.Color.Type = type;
+ ctx->Array.Color.Stride = stride;
+ ctx->Array.Color.Ptr = (void *) ptr;
+ ctx->Array.ColorFunc = gl_trans_4ub_tab[size][TYPE_IDX(type)];
+ ctx->Array.ColorEltFunc = gl_trans_elt_4ub_tab[size][TYPE_IDX(type)];
+ ctx->Array.NewArrayState |= VERT_RGBA;
+ ctx->NewState |= NEW_CLIENT_STATE;
+}
+
+
+
+void GLAPIENTRY glIndexPointer(CTX_ARG GLenum type, GLsizei stride,
+ const GLvoid *ptr )
+{
+ GLcontext *ctx;
+ GET_CONTEXT;
+ CHECK_CONTEXT;
+ ctx = CC;
+
+ if (stride<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glIndexPointer(stride)" );
+ return;
+ }
+
+ ctx->Array.Index.StrideB = stride;
+ if (!stride) {
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ ctx->Array.Index.StrideB = sizeof(GLubyte);
+ break;
+ case GL_SHORT:
+ ctx->Array.Index.StrideB = sizeof(GLshort);
+ break;
+ case GL_INT:
+ ctx->Array.Index.StrideB = sizeof(GLint);
+ break;
+ case GL_FLOAT:
+ ctx->Array.Index.StrideB = sizeof(GLfloat);
+ break;
+ case GL_DOUBLE:
+ ctx->Array.Index.StrideB = sizeof(GLdouble);
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glIndexPointer(type)" );
+ return;
+ }
+ }
+ ctx->Array.Index.Type = type;
+ ctx->Array.Index.Stride = stride;
+ ctx->Array.Index.Ptr = (void *) ptr;
+ ctx->Array.IndexFunc = gl_trans_1ui_tab[TYPE_IDX(type)];
+ ctx->Array.IndexEltFunc = gl_trans_elt_1ui_tab[TYPE_IDX(type)];
+ ctx->Array.NewArrayState |= VERT_INDEX;
+ ctx->NewState |= NEW_CLIENT_STATE;
+}
+
+
+
+void GLAPIENTRY glTexCoordPointer(CTX_ARG GLint size, GLenum type,
+ GLsizei stride, const GLvoid *ptr )
+{
+ GLuint texUnit;
+
+ GLcontext *ctx;
+ GET_CONTEXT;
+ CHECK_CONTEXT;
+ ctx = CC;
+
+ texUnit = ctx->TexCoordUnit;
+
+ if (size<1 || size>4) {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(size)" );
+ return;
+ }
+ if (stride<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(stride)" );
+ return;
+ }
+
+ if (MESA_VERBOSE&(VERBOSE_VARRAY|VERBOSE_API))
+ fprintf(stderr, "glTexCoordPointer( unit %u sz %d type %s stride %d )\n",
+ texUnit,
+ size,
+ gl_lookup_enum_by_nr( type ),
+ stride);
+
+ ctx->Array.TexCoord[texUnit].StrideB = stride;
+ if (!stride) {
+ switch (type) {
+ case GL_SHORT:
+ ctx->Array.TexCoord[texUnit].StrideB = size*sizeof(GLshort);
+ break;
+ case GL_INT:
+ ctx->Array.TexCoord[texUnit].StrideB = size*sizeof(GLint);
+ break;
+ case GL_FLOAT:
+ ctx->Array.TexCoord[texUnit].StrideB = size*sizeof(GLfloat);
+ break;
+ case GL_DOUBLE:
+ ctx->Array.TexCoord[texUnit].StrideB = size*sizeof(GLdouble);
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type)" );
+ return;
+ }
+ }
+ ctx->Array.TexCoord[texUnit].Size = size;
+ ctx->Array.TexCoord[texUnit].Type = type;
+ ctx->Array.TexCoord[texUnit].Stride = stride;
+ ctx->Array.TexCoord[texUnit].Ptr = (void *) ptr;
+
+ ctx->Array.TexCoordFunc[texUnit] = gl_trans_4f_tab[size][TYPE_IDX(type)];
+ ctx->Array.TexCoordEltFunc[texUnit] = gl_trans_elt_4f_tab[size][TYPE_IDX(type)];
+ ctx->Array.NewArrayState |= PIPE_TEX(texUnit);
+ ctx->NewState |= NEW_CLIENT_STATE;
+}
+
+
+
+
+void GLAPIENTRY glEdgeFlagPointer(CTX_ARG GLsizei stride, const void *vptr )
+{
+ const GLboolean *ptr = (GLboolean *)vptr;
+
+ GLcontext *ctx;
+ GET_CONTEXT;
+ CHECK_CONTEXT;
+ ctx = CC;
+
+ if (stride<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glEdgeFlagPointer(stride)" );
+ return;
+ }
+ ctx->Array.EdgeFlag.Stride = stride;
+ ctx->Array.EdgeFlag.StrideB = stride ? stride : sizeof(GLboolean);
+ ctx->Array.EdgeFlag.Ptr = (GLboolean *) ptr;
+ if (stride != sizeof(GLboolean)) {
+ ctx->Array.EdgeFlagFunc = gl_trans_1ub_tab[TYPE_IDX(GL_UNSIGNED_BYTE)];
+ } else {
+ ctx->Array.EdgeFlagFunc = 0;
+ }
+ ctx->Array.EdgeFlagEltFunc = gl_trans_elt_1ub_tab[TYPE_IDX(GL_UNSIGNED_BYTE)];
+ ctx->Array.NewArrayState |= VERT_EDGE;
+ ctx->NewState |= NEW_CLIENT_STATE;
+}
+
+
+/* Called only from gl_DrawElements
+ */
+void gl_CVAEltPointer( GLcontext *ctx, GLenum type, const GLvoid *ptr )
+{
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ ctx->CVA.Elt.StrideB = sizeof(GLubyte);
+ break;
+ case GL_UNSIGNED_SHORT:
+ ctx->CVA.Elt.StrideB = sizeof(GLushort);
+ break;
+ case GL_UNSIGNED_INT:
+ ctx->CVA.Elt.StrideB = sizeof(GLuint);
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glEltPointer(type)" );
+ return;
+ }
+ ctx->CVA.Elt.Type = type;
+ ctx->CVA.Elt.Stride = 0;
+ ctx->CVA.Elt.Ptr = (void *) ptr;
+ ctx->CVA.EltFunc = gl_trans_1ui_tab[TYPE_IDX(type)];
+ ctx->Array.NewArrayState |= VERT_ELT; /* ??? */
+}
+
+
+
+/* KW: Batch function to exec all the array elements in the input
+ * buffer prior to transform. Done only the first time a vertex
+ * buffer is executed or compiled.
+ */
+void gl_exec_array_elements( GLcontext *ctx, struct immediate *IM )
+{
+ GLuint *flags = IM->Flag;
+ GLuint *elts = IM->Elt;
+ GLuint count = IM->Count;
+ GLuint start = IM->Start;
+ GLuint translate = ctx->Array.Flags;
+ GLuint i;
+
+ if (translate & VERT_OBJ_ANY)
+ (ctx->Array.VertexEltFunc)( IM->Obj,
+ &ctx->Array.Vertex,
+ flags, elts, VERT_ELT,
+ start, count);
+
+ if (translate & VERT_NORM)
+ (ctx->Array.NormalEltFunc)( IM->Normal,
+ &ctx->Array.Normal,
+ flags, elts, (VERT_ELT|VERT_NORM),
+ start, count);
+
+ if (translate & VERT_EDGE)
+ (ctx->Array.EdgeFlagEltFunc)( IM->EdgeFlag,
+ &ctx->Array.EdgeFlag,
+ flags, elts, (VERT_ELT|VERT_EDGE),
+ start, count);
+
+ if (translate & VERT_RGBA)
+ (ctx->Array.ColorEltFunc)( IM->Color,
+ &ctx->Array.Color,
+ flags, elts, (VERT_ELT|VERT_RGBA),
+ start, count);
+
+ if (translate & VERT_INDEX)
+ (ctx->Array.IndexEltFunc)( IM->Index,
+ &ctx->Array.Index,
+ flags, elts, (VERT_ELT|VERT_INDEX),
+ start, count);
+
+ if (translate & VERT_TEX0_ANY)
+ (ctx->Array.TexCoordEltFunc[0])( IM->TexCoord[0],
+ &ctx->Array.TexCoord[0],
+ flags, elts, (VERT_ELT|VERT_TEX0_ANY),
+ start, count);
+
+ if (translate & VERT_TEX1_ANY)
+ (ctx->Array.TexCoordEltFunc[1])( IM->TexCoord[1],
+ &ctx->Array.TexCoord[1],
+ flags, elts, (VERT_ELT|VERT_TEX1_ANY),
+ start, count);
+
+ IM->OrFlag |= translate;
+
+ /* Lighting ignores the and-flag, so still need to do this.
+ */
+ if (IM->AndFlag & VERT_ELT) {
+ for (i = 0 ; i < count ; i++)
+ flags[i] |= translate;
+ IM->AndFlag |= translate;
+ } else {
+ GLuint andflag = ~0;
+ for (i = 0 ; i < count ; i++) {
+ if (flags[i] & VERT_ELT) flags[i] |= translate;
+ andflag &= flags[i];
+ }
+ IM->AndFlag = andflag;
+ }
+}
+
+
+
+/* KW: I think this is moving in the right direction, but it still feels
+ * like we are doing way too much work.
+ */
+void gl_DrawArrays( GLcontext *ctx, GLenum mode, GLint start, GLsizei count )
+{
+ struct vertex_buffer *VB = ctx->VB;
+ GLint i;
+
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawArrays");
+
+ if (count<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glDrawArrays(count)" );
+ return;
+ }
+
+ if (!ctx->CompileFlag && ctx->Array.Vertex.Enabled)
+ {
+ GLint remaining = count;
+ GLint i;
+ GLvector4f obj;
+ GLvector3f norm;
+ GLvector4f tc[MAX_TEXTURE_UNITS];
+ GLvector4ub col;
+ GLvector1ub edge;
+ GLvector1ui index;
+ GLuint update = 0, translate = 0;
+ struct vertex_array_pointers VSrc;
+ struct immediate *IM = VB->IM;
+ struct gl_client_array *client_data;
+ struct gl_pipeline *elt = &ctx->CVA.elt;
+ GLuint relock;
+ GLuint fallback, required;
+
+ if (ctx->NewState)
+ gl_update_state( ctx );
+
+ /* This will die miserably with CVA... Need more work to support this.
+ */
+ relock = ctx->CompileCVAFlag;
+ ctx->CompileCVAFlag = 0;
+
+ if (!elt->pipeline_valid || relock)
+ gl_build_immediate_pipeline( ctx );
+
+ required = elt->inputs;
+ fallback = (elt->inputs & ~ctx->Array.Summary);
+
+ VSrc.Color = &IM->v.Color;
+ VSrc.Index = &IM->v.Index;
+ VSrc.EdgeFlag = &IM->v.EdgeFlag;
+ VSrc.TexCoord[0] = &IM->v.TexCoord[0];
+ VSrc.TexCoord[1] = &IM->v.TexCoord[1];
+ VSrc.Obj = &IM->v.Obj;
+ VSrc.Normal = &IM->v.Normal;
+
+ if (required & VERT_RGBA)
+ {
+ client_data = &ctx->Array.Color;
+ if (fallback & VERT_RGBA)
+ client_data = &ctx->Fallback.Color;
+
+ if (client_data->Type == GL_UNSIGNED_BYTE &&
+ client_data->Size == 4)
+ {
+ VSrc.Color = &col;
+ col.data = (GLubyte (*)[4]) client_data->Ptr;
+ col.stride = client_data->StrideB;
+ col.flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE;
+ if (client_data->StrideB != 4 * sizeof(GLubyte))
+ col.flags ^= VEC_STRIDE_FLAGS;
+
+ update |= VERT_RGBA;
+ } else {
+ translate |= VERT_RGBA;
+ }
+ }
+
+ if (required & VERT_INDEX)
+ {
+ client_data = &ctx->Array.Index;
+ if (fallback & VERT_INDEX)
+ client_data = &ctx->Fallback.Index;
+
+ if (client_data->Type == GL_UNSIGNED_INT)
+ {
+ VSrc.Index = &index;
+ index.data = (GLuint *) client_data->Ptr;
+ index.stride = client_data->StrideB;
+ index.flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE;
+ if (client_data->StrideB != sizeof(GLuint))
+ index.flags ^= VEC_STRIDE_FLAGS;
+
+ update |= VERT_INDEX;
+ } else {
+ translate |= VERT_INDEX;
+ }
+ }
+
+ for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
+ {
+ GLuint flag = VERT_TEX_ANY(i);
+
+ if (required & flag) {
+
+ client_data = &ctx->Array.TexCoord[i];
+
+ if (fallback & flag)
+ {
+ client_data = &ctx->Fallback.TexCoord[i];
+ client_data->Size = gl_texcoord_size( ctx->Current.Flag, i );
+ }
+
+ if (client_data->Type == GL_FLOAT)
+ {
+ VSrc.TexCoord[i] = &tc[i];
+ tc[i].data = (GLfloat (*)[4]) client_data->Ptr;
+ tc[i].stride = client_data->StrideB;
+ tc[i].size = client_data->Size;
+ tc[i].flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE;
+ if (tc[i].stride |= 4 * sizeof(GLfloat))
+ tc[i].flags ^= VEC_STRIDE_FLAGS;
+ update |= flag;
+ } else {
+ translate |= flag;
+ }
+ }
+ }
+
+ if (ctx->Array.Flags != ctx->Array.Flag[0])
+ for (i = 0 ; i < VB_MAX ; i++)
+ ctx->Array.Flag[i] = ctx->Array.Flags;
+
+
+ if (ctx->Array.Vertex.Type == GL_FLOAT)
+ {
+ VSrc.Obj = &obj;
+ obj.data = (GLfloat (*)[4]) ctx->Array.Vertex.Ptr;
+ obj.stride = ctx->Array.Vertex.StrideB;
+ obj.size = ctx->Array.Vertex.Size;
+ obj.flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE;
+ if (obj.stride != 4 * sizeof(GLfloat))
+ obj.flags ^= VEC_STRIDE_FLAGS;
+
+ update |= VERT_OBJ_ANY;
+ }
+ else
+ {
+ translate |= VERT_OBJ_ANY;
+ }
+
+ if (required & VERT_NORM)
+ {
+ client_data = &ctx->Array.Normal;
+ if (fallback & VERT_NORM)
+ client_data = &ctx->Fallback.Normal;
+
+ if (client_data->Type == GL_FLOAT)
+ {
+ VSrc.Normal = &norm;
+ norm.flags = 0;
+ norm.data = (GLfloat (*)[3]) client_data->Ptr;
+ norm.stride = client_data->StrideB;
+ update |= VERT_NORM;
+ } else {
+ translate |= VERT_NORM;
+ }
+ }
+
+ if ( (required & VERT_EDGE) &&
+ (mode == GL_TRIANGLES ||
+ mode == GL_QUADS ||
+ mode == GL_POLYGON))
+ {
+ client_data = &ctx->Array.EdgeFlag;
+
+ if (fallback & VERT_EDGE)
+ client_data = &ctx->Fallback.EdgeFlag;
+
+ VSrc.EdgeFlag = &edge;
+ edge.data = (GLboolean *) client_data->Ptr;
+ edge.stride = client_data->StrideB;
+ edge.flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE;
+ if (edge.stride != sizeof(GLubyte))
+ edge.flags ^= VEC_STRIDE_FLAGS;
+
+ update |= VERT_EDGE;
+ }
+
+ VB->Primitive = IM->Primitive;
+ VB->NextPrimitive = IM->NextPrimitive;
+ VB->MaterialMask = IM->MaterialMask;
+ VB->Material = IM->Material;
+ VB->BoundsPtr = 0;
+
+ while (remaining > 0) {
+ GLint vbspace = VB_MAX - VB_START;
+ GLuint count, n;
+
+
+ if (vbspace >= remaining) {
+ n = remaining;
+ VB->LastPrimitive = VB_START + n;
+ } else {
+ n = vbspace;
+ VB->LastPrimitive = VB_START;
+ }
+
+ VB->CullMode = 0;
+
+
+ /* Update pointers.
+ */
+ if (update) {
+ if (update & VERT_OBJ_ANY)
+ obj.start = VEC_ELT(&obj, GLfloat, start);
+
+ if (update & VERT_NORM)
+ norm.start = VEC_ELT(&norm, GLfloat, start);
+
+ if (update & VERT_EDGE)
+ edge.start = VEC_ELT(&edge, GLubyte, start);
+
+ if (update & VERT_RGBA)
+ col.start = VEC_ELT(&col, GLubyte, start);
+
+ if (update & VERT_INDEX)
+ index.start = VEC_ELT(&index, GLuint, start);
+
+ if (update & VERT_TEX0_ANY)
+ tc[0].start = VEC_ELT(&tc[0], GLfloat, start);
+
+ if (update & VERT_TEX1_ANY)
+ tc[1].start = VEC_ELT(&tc[1], GLfloat, start);
+ }
+
+
+ /* Translate data to fix up type and stride.
+ */
+ if (translate) {
+ if (translate & VERT_OBJ_ANY) {
+ ctx->Array.VertexFunc( IM->Obj + VB_START,
+ &ctx->Array.Vertex, start, n );
+ }
+
+ if (translate & VERT_NORM) {
+ ctx->Array.NormalFunc( IM->Normal + VB_START,
+ &ctx->Array.Normal, start, n );
+ }
+
+ if (translate & VERT_EDGE) {
+ ctx->Array.EdgeFlagFunc( IM->EdgeFlag + VB_START,
+ &ctx->Array.EdgeFlag, start, n );
+ }
+
+ if (translate & VERT_RGBA) {
+ ctx->Array.ColorFunc( IM->Color + VB_START,
+ &ctx->Array.Color, start, n );
+ }
+
+ if (translate & VERT_INDEX) {
+ ctx->Array.IndexFunc( IM->Index + VB_START,
+ &ctx->Array.Index, start, n );
+ }
+
+ if (translate & VERT_TEX0_ANY) {
+ IM->v.TexCoord[0].size = tc[0].size;
+ ctx->Array.TexCoordFunc[0]( IM->TexCoord[0] + VB_START,
+ &ctx->Array.TexCoord[0], start, n );
+ }
+
+ if (translate & VERT_TEX1_ANY) {
+ IM->v.TexCoord[1].size = tc[1].size;
+ ctx->Array.TexCoordFunc[1]( IM->TexCoord[1] + VB_START,
+ &ctx->Array.TexCoord[1], start, n );
+ }
+ }
+
+
+ VB->ObjPtr = VSrc.Obj;
+ VB->NormalPtr = VSrc.Normal;
+ VB->Color[0] = VB->Color[1] = VB->ColorPtr = VSrc.Color;
+ VB->IndexPtr = VSrc.Index;
+ VB->EdgeFlagPtr = VSrc.EdgeFlag;
+ VB->TexCoordPtr[0] = VSrc.TexCoord[0];
+ VB->TexCoordPtr[1] = VSrc.TexCoord[1];
+
+ VB->Flag = ctx->Array.Flag;
+ VB->AndFlag = ctx->Array.Flags;
+ VB->OrFlag = ctx->Array.Flags;
+
+ count = VB->Count = VB_START + n;
+
+ VB->ObjPtr->count = count;
+ VB->NormalPtr->count = count;
+ VB->ColorPtr->count = count;
+ VB->IndexPtr->count = count;
+ VB->EdgeFlagPtr->count = count;
+ VB->TexCoordPtr[0]->count = count;
+ VB->TexCoordPtr[1]->count = count;
+
+ VB->Flag[count] |= VERT_END_VB;
+ VB->Flag[VB_START] |= VERT_NORM;
+/* VB->Flag[VB_START] |= (IM->Flag[vb_start] & VERT_MATERIAL); */
+
+ VB->NextPrimitive[VB->CopyStart] = VB->Count;
+ VB->Primitive[VB->CopyStart] = mode;
+
+ /* Transform and render.
+ */
+ gl_run_pipeline( VB );
+ gl_reset_vb( VB );
+
+ ctx->Array.Flag[count] = ctx->Array.Flags;
+ ctx->Array.Flag[VB_START] = ctx->Array.Flags;
+ IM->Flag[VB_START] = 0;
+
+ start += n;
+ remaining -= n;
+ }
+
+ ctx->CompileCVAFlag = relock;
+ }
+ else if (ctx->Array.Vertex.Enabled)
+ {
+ /* The GL_COMPILE and GL_COMPILE_AND_EXECUTE cases. These
+ * could be handled by the above code, but it gets a little
+ * complex.
+ */
+ /* No need to reset - never called from inside a display list */
+ gl_Begin( ctx, mode );
+ for (i=0;i<count;i++) {
+ gl_ArrayElement( ctx, start+i );
+ }
+ gl_End( ctx );
+ }
+ else
+ {
+ /* The degenerate case where vertices are not enabled - only
+ * need to process the very final array element, as all of the
+ * preceding ones would be overwritten anyway.
+ */
+ gl_Begin( ctx, mode );
+ gl_ArrayElement( ctx, start+count );
+ gl_End( ctx );
+ }
+}
+
+
+
+/* KW: Exactly fakes the effects of calling glArrayElement multiple times.
+ * Compilation is handled via. the IM->maybe_transform_vb() callback.
+ */
+#define DRAW_ELT(FUNC, TYPE) \
+static void FUNC( GLcontext *ctx, GLenum mode, \
+ TYPE *indices, GLuint count ) \
+{ \
+ GLuint i,j; \
+ \
+ if (count) gl_Begin( ctx, mode ); \
+ \
+ for (j = 0 ; j < count ; ) { \
+ GLuint nr = MIN2( VB_MAX, count - j + VB_START ); \
+ struct immediate *IM = ctx->input; \
+ GLuint sf = IM->Flag[VB_START]; \
+ GLuint flags = IM->ArrayOrFlags; \
+ \
+ for (i = VB_START ; i < nr ; i++) { \
+ IM->Elt[i] = (GLuint) *indices++; \
+ IM->Flag[i] = flags; \
+ } \
+ \
+ if (j == 0) IM->Flag[VB_START] |= sf; \
+ \
+ IM->Count = nr; \
+ j += nr - VB_START; \
+ \
+ if (j == count) gl_End( ctx ); \
+ \
+ IM->maybe_transform_vb( IM ); \
+ } \
+}
+
+DRAW_ELT( draw_elt_ubyte, GLubyte )
+DRAW_ELT( draw_elt_ushort, GLushort )
+DRAW_ELT( draw_elt_uint, GLuint )
+
+
+static GLuint natural_stride[0x10] =
+{
+ sizeof(GLbyte), /* 0 */
+ sizeof(GLubyte), /* 1 */
+ sizeof(GLshort), /* 2 */
+ sizeof(GLushort), /* 3 */
+ sizeof(GLint), /* 4 */
+ sizeof(GLuint), /* 5 */
+ sizeof(GLfloat), /* 6 */
+ 2 * sizeof(GLbyte), /* 7 */
+ 3 * sizeof(GLbyte), /* 8 */
+ 4 * sizeof(GLbyte), /* 9 */
+ sizeof(GLdouble), /* a */
+ 0, /* b */
+ 0, /* c */
+ 0, /* d */
+ 0, /* e */
+ 0 /* f */
+};
+
+void GLAPIENTRY glDrawElements(CTX_ARG GLenum mode, GLsizei count,
+ GLenum type, const GLvoid *indices )
+{
+ GLcontext *ctx;
+ struct gl_cva *cva;
+
+ GET_CONTEXT;
+ CHECK_CONTEXT;
+ ctx = CC;
+
+ cva = &ctx->CVA;
+ ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glDrawElements");
+
+ if (count<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glDrawElements(count)" );
+ return;
+ }
+
+ if (mode < 0 || mode > GL_POLYGON) {
+ gl_error( ctx, GL_INVALID_ENUM, "glDrawArrays(mode)" );
+ return;
+ }
+
+ if (type != GL_UNSIGNED_INT && type != GL_UNSIGNED_BYTE && type != GL_UNSIGNED_SHORT)
+ {
+ gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
+ return;
+ }
+
+ if (ctx->NewState)
+ gl_update_state(ctx);
+
+ if (ctx->CompileCVAFlag)
+ {
+#if defined(MESA_CVA_PROF)
+ force_init_prof();
+#endif
+
+ /* Treat VERT_ELT like a special client array.
+ */
+ ctx->Array.NewArrayState |= VERT_ELT;
+ ctx->Array.Summary |= VERT_ELT;
+ ctx->Array.Flags |= VERT_ELT;
+
+ cva->elt_mode = mode;
+ cva->elt_count = count;
+ cva->Elt.Type = type;
+ cva->Elt.Ptr = (void *) indices;
+ cva->Elt.StrideB = natural_stride[TYPE_IDX(type)];
+ cva->EltFunc = gl_trans_1ui_tab[TYPE_IDX(type)];
+
+ if (!cva->pre.pipeline_valid)
+ gl_build_precalc_pipeline( ctx );
+ else if (MESA_VERBOSE & VERBOSE_PIPELINE)
+ fprintf(stderr, ": dont rebuild\n");
+
+ gl_cva_force_precalc( ctx );
+
+ /* Did we 'precalculate' the render op?
+ */
+ if (ctx->CVA.pre.ops & PIPE_OP_RENDER) {
+ ctx->Array.NewArrayState |= VERT_ELT;
+ ctx->Array.Summary &= ~VERT_ELT;
+ ctx->Array.Flags &= ~VERT_ELT;
+ return;
+ }
+
+ if ( (MESA_VERBOSE&VERBOSE_VARRAY) )
+ printf("using immediate\n");
+ }
+
+
+ /* Otherwise, have to use the immediate path to render.
+ */
+ switch (type) {
+ case GL_UNSIGNED_BYTE:
+ {
+ GLubyte *ub_indices = (GLubyte *) indices;
+ if (ctx->Array.Summary & VERT_OBJ_ANY) {
+ draw_elt_ubyte( ctx, mode, ub_indices, count );
+ } else {
+ gl_ArrayElement( ctx, (GLuint) ub_indices[count-1] );
+ }
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ {
+ GLushort *us_indices = (GLushort *) indices;
+ if (ctx->Array.Summary & VERT_OBJ_ANY) {
+ draw_elt_ushort( ctx, mode, us_indices, count );
+ } else {
+ gl_ArrayElement( ctx, (GLuint) us_indices[count-1] );
+ }
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ {
+ GLuint *ui_indices = (GLuint *) indices;
+ if (ctx->Array.Summary & VERT_OBJ_ANY) {
+ draw_elt_uint( ctx, mode, ui_indices, count );
+ } else {
+ gl_ArrayElement( ctx, ui_indices[count-1] );
+ }
+ }
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
+ break;
+ }
+
+ if (ctx->CompileCVAFlag) {
+ ctx->Array.NewArrayState |= VERT_ELT;
+ ctx->Array.Summary &= ~VERT_ELT;
+ }
+}
+
+
+
+void GLAPIENTRY glInterleavedArrays(CTX_ARG GLenum format, GLsizei stride,
+ const GLvoid *pointer )
+{
+ GLcontext *ctx;
+ GLboolean tflag, cflag, nflag; /* enable/disable flags */
+ GLint tcomps, ccomps, vcomps; /* components per texcoord, color, vertex */
+
+ GLenum ctype; /* color type */
+ GLint coffset, noffset, voffset;/* color, normal, vertex offsets */
+ GLint defstride; /* default stride */
+ GLint c, f;
+ GLint coordUnitSave;
+
+ GET_CONTEXT;
+ CHECK_CONTEXT;
+ ctx = CC;
+
+
+ f = sizeof(GLfloat);
+ c = f * ((4*sizeof(GLubyte) + (f-1)) / f);
+
+ if (stride<0) {
+ gl_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
+ return;
+ }
+
+ switch (format) {
+ case GL_V2F:
+ tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
+ tcomps = 0; ccomps = 0; vcomps = 2;
+ voffset = 0;
+ defstride = 2*f;
+ break;
+ case GL_V3F:
+ tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_FALSE;
+ tcomps = 0; ccomps = 0; vcomps = 3;
+ voffset = 0;
+ defstride = 3*f;
+ break;
+ case GL_C4UB_V2F:
+ tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
+ tcomps = 0; ccomps = 4; vcomps = 2;
+ ctype = GL_UNSIGNED_BYTE;
+ coffset = 0;
+ voffset = c;
+ defstride = c + 2*f;
+ break;
+ case GL_C4UB_V3F:
+ tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
+ tcomps = 0; ccomps = 4; vcomps = 3;
+ ctype = GL_UNSIGNED_BYTE;
+ coffset = 0;
+ voffset = c;
+ defstride = c + 3*f;
+ break;
+ case GL_C3F_V3F:
+ tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_FALSE;
+ tcomps = 0; ccomps = 3; vcomps = 3;
+ ctype = GL_FLOAT;
+ coffset = 0;
+ voffset = 3*f;
+ defstride = 6*f;
+ break;
+ case GL_N3F_V3F:
+ tflag = GL_FALSE; cflag = GL_FALSE; nflag = GL_TRUE;
+ tcomps = 0; ccomps = 0; vcomps = 3;
+ noffset = 0;
+ voffset = 3*f;
+ defstride = 6*f;
+ break;
+ case GL_C4F_N3F_V3F:
+ tflag = GL_FALSE; cflag = GL_TRUE; nflag = GL_TRUE;
+ tcomps = 0; ccomps = 4; vcomps = 3;
+ ctype = GL_FLOAT;
+ coffset = 0;
+ noffset = 4*f;
+ voffset = 7*f;
+ defstride = 10*f;
+ break;
+ case GL_T2F_V3F:
+ tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
+ tcomps = 2; ccomps = 0; vcomps = 3;
+ voffset = 2*f;
+ defstride = 5*f;
+ break;
+ case GL_T4F_V4F:
+ tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_FALSE;
+ tcomps = 4; ccomps = 0; vcomps = 4;
+ voffset = 4*f;
+ defstride = 8*f;
+ break;
+ case GL_T2F_C4UB_V3F:
+ tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
+ tcomps = 2; ccomps = 4; vcomps = 3;
+ ctype = GL_UNSIGNED_BYTE;
+ coffset = 2*f;
+ voffset = c+2*f;
+ defstride = c+5*f;
+ break;
+ case GL_T2F_C3F_V3F:
+ tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_FALSE;
+ tcomps = 2; ccomps = 3; vcomps = 3;
+ ctype = GL_FLOAT;
+ coffset = 2*f;
+ voffset = 5*f;
+ defstride = 8*f;
+ break;
+ case GL_T2F_N3F_V3F:
+ tflag = GL_TRUE; cflag = GL_FALSE; nflag = GL_TRUE;
+ tcomps = 2; ccomps = 0; vcomps = 3;
+ noffset = 2*f;
+ voffset = 5*f;
+ defstride = 8*f;
+ break;
+ case GL_T2F_C4F_N3F_V3F:
+ tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
+ tcomps = 2; ccomps = 4; vcomps = 3;
+ ctype = GL_FLOAT;
+ coffset = 2*f;
+ noffset = 6*f;
+ voffset = 9*f;
+ defstride = 12*f;
+ break;
+ case GL_T4F_C4F_N3F_V4F:
+ tflag = GL_TRUE; cflag = GL_TRUE; nflag = GL_TRUE;
+ tcomps = 4; ccomps = 4; vcomps = 4;
+ ctype = GL_FLOAT;
+ coffset = 4*f;
+ noffset = 8*f;
+ voffset = 11*f;
+ defstride = 15*f;
+ break;
+ default:
+ gl_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
+ return;
+ }
+
+ if (stride==0) {
+ stride = defstride;
+ }
+
+ gl_DisableClientState( ctx, GL_EDGE_FLAG_ARRAY );
+ gl_DisableClientState( ctx, GL_INDEX_ARRAY );
+
+ /* Texcoords */
+ coordUnitSave = ctx->TexCoordUnit;
+ if (tflag) {
+ GLint i;
+ GLint factor = ctx->Array.TexCoordInterleaveFactor;
+ for (i = 0; i < factor; i++) {
+ gl_ActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + i) );
+ gl_EnableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
+ glTexCoordPointer(CTX_PRM tcomps, GL_FLOAT, stride,
+ (GLubyte *) pointer + i * coffset );
+ }
+ for (i = factor; i < ctx->Const.MaxTextureUnits; i++) {
+ gl_ActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + i) );
+ gl_DisableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
+ }
+ }
+ else {
+ GLint i;
+ for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
+ gl_ActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + i) );
+ gl_DisableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
+ }
+ }
+ /* Restore texture coordinate unit index */
+ gl_ActiveTexture( ctx, (GLenum) (GL_TEXTURE0_ARB + coordUnitSave) );
+
+
+ /* Color */
+ if (cflag) {
+ gl_EnableClientState( ctx, GL_COLOR_ARRAY );
+ glColorPointer(CTX_PRM ccomps, ctype, stride,
+ (GLubyte*) pointer + coffset );
+ }
+ else {
+ gl_DisableClientState( ctx, GL_COLOR_ARRAY );
+ }
+
+
+ /* Normals */
+ if (nflag) {
+ gl_EnableClientState( ctx, GL_NORMAL_ARRAY );
+ glNormalPointer(CTX_PRM GL_FLOAT, stride,
+ (GLubyte*) pointer + noffset );
+ }
+ else {
+ gl_DisableClientState( ctx, GL_NORMAL_ARRAY );
+ }
+
+ gl_EnableClientState( ctx, GL_VERTEX_ARRAY );
+ glVertexPointer(CTX_PRM vcomps, GL_FLOAT, stride,
+ (GLubyte *) pointer + voffset );
+}
+
+
+
+void GLAPIENTRY glDrawRangeElements(CTX_ARG GLenum mode, GLuint start,
+ GLuint end, GLsizei count,
+ GLenum type, const GLvoid *indices )
+{
+ GLcontext *ctx;
+ GET_CONTEXT;
+ CHECK_CONTEXT;
+ ctx = CC;
+
+ if (end < start) {
+ gl_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements( end < start )");
+ return;
+ }
+
+ if (!ctx->Array.LockCount && 2*count > 3*(end-start)) {
+ glLockArraysEXT(CTX_PRM start, end );
+ glDrawElements(CTX_PRM mode, count, type, indices );
+ glUnlockArraysEXT(CTX_VPRM );
+ } else {
+ glDrawElements(CTX_PRM mode, count, type, indices );
+ }
+}
+
+
+
+void gl_update_client_state( GLcontext *ctx )
+{
+ static GLuint sz_flags[5] = { 0,
+ 0,
+ VERT_OBJ_2,
+ VERT_OBJ_23,
+ VERT_OBJ_234 };
+
+ static GLuint tc_flags[5] = { 0,
+ VERT_TEX0_1,
+ VERT_TEX0_12,
+ VERT_TEX0_123,
+ VERT_TEX0_1234 };
+
+ ctx->Array.Flags = 0;
+ ctx->Array.Summary = 0;
+ ctx->input->ArrayIncr = 0;
+
+ if (ctx->Array.Normal.Enabled) ctx->Array.Flags |= VERT_NORM;
+ if (ctx->Array.Color.Enabled) ctx->Array.Flags |= VERT_RGBA;
+ if (ctx->Array.Index.Enabled) ctx->Array.Flags |= VERT_INDEX;
+ if (ctx->Array.EdgeFlag.Enabled) ctx->Array.Flags |= VERT_EDGE;
+ if (ctx->Array.Vertex.Enabled) {
+ ctx->Array.Flags |= sz_flags[ctx->Array.Vertex.Size];
+ ctx->input->ArrayIncr = 1;
+ }
+ if (ctx->Array.TexCoord[0].Enabled) {
+ ctx->Array.Flags |= tc_flags[ctx->Array.TexCoord[0].Size];
+ }
+ if (ctx->Array.TexCoord[1].Enabled) {
+ ctx->Array.Flags |= (tc_flags[ctx->Array.TexCoord[1].Size] << NR_TEXSIZE_BITS);
+ }
+
+ /* Not really important any more:
+ */
+ ctx->Array.Summary = ctx->Array.Flags & VERT_DATA;
+
+ ctx->input->ArrayOrFlags = (ctx->Array.Flags & VERT_OBJ_234) | VERT_ELT;
+ ctx->input->ArrayAndFlags = ~ctx->Array.Flags;
+ ctx->input->ArrayEltFlush = !(ctx->CompileCVAFlag);
+}
+
diff --git a/src/mesa/main/varray.h b/src/mesa/main/varray.h
new file mode 100644
index 0000000000..fc81a61c72
--- /dev/null
+++ b/src/mesa/main/varray.h
@@ -0,0 +1,113 @@
+/* $Id: varray.h,v 1.1 1999/08/19 00:55:41 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef VARRAY_H
+#define VARRAY_H
+
+
+#include "types.h"
+
+
+extern void gl_VertexPointer( GLcontext *ctx,
+ GLint size, GLenum type, GLsizei stride,
+ const GLvoid *ptr );
+
+
+extern void gl_NormalPointer( GLcontext *ctx,
+ GLenum type, GLsizei stride, const GLvoid *ptr );
+
+
+extern void gl_ColorPointer( GLcontext *ctx,
+ GLint size, GLenum type, GLsizei stride,
+ const GLvoid *ptr );
+
+
+extern void gl_IndexPointer( GLcontext *ctx,
+ GLenum type, GLsizei stride,
+ const GLvoid *ptr );
+
+
+extern void gl_TexCoordPointer( GLcontext *ctx,
+ GLint size, GLenum type, GLsizei stride,
+ const GLvoid *ptr );
+
+
+extern void gl_EdgeFlagPointer( GLcontext *ctx,
+ GLsizei stride, const GLboolean *ptr );
+
+
+extern void gl_GetPointerv( GLcontext *ctx, GLenum pname, GLvoid **params );
+
+
+
+extern void gl_DrawArrays( GLcontext *ctx,
+ GLenum mode, GLint first, GLsizei count );
+
+extern void gl_save_DrawArrays( GLcontext *ctx,
+ GLenum mode, GLint first, GLsizei count );
+
+
+extern void gl_DrawElements( GLcontext *ctx,
+ GLenum mode, GLsizei count,
+ GLenum type, const GLvoid *indices );
+
+extern void gl_save_DrawElements( GLcontext *ctx,
+ GLenum mode, GLsizei count,
+ GLenum type, const GLvoid *indices );
+
+
+extern void gl_InterleavedArrays( GLcontext *ctx,
+ GLenum format, GLsizei stride,
+ const GLvoid *pointer );
+
+extern void gl_save_InterleavedArrays( GLcontext *ctx,
+ GLenum format, GLsizei stride,
+ const GLvoid *pointer );
+
+
+extern void gl_DrawRangeElements( GLcontext *ctx, GLenum mode, GLuint start,
+ GLuint end, GLsizei count, GLenum type,
+ const GLvoid *indices );
+
+extern void gl_save_DrawRangeElements( GLcontext *ctx, GLenum mode,
+ GLuint start, GLuint end, GLsizei count,
+ GLenum type, const GLvoid *indices );
+
+
+
+extern void gl_exec_array_elements( GLcontext *ctx,
+ struct immediate *IM );
+
+extern void gl_update_client_state( GLcontext *ctx );
+
+#endif
+
+
+
diff --git a/src/mesa/x86/3dnow.c b/src/mesa/x86/3dnow.c
new file mode 100644
index 0000000000..f91a90b33f
--- /dev/null
+++ b/src/mesa/x86/3dnow.c
@@ -0,0 +1,168 @@
+/* $Id: 3dnow.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+/*
+ * 3DNow! optimizations contributed by
+ * Holger Waechtler <holger@akaflieg.extern.tu-berlin.de>
+ */
+#if defined(USE_3DNOW_ASM)
+#include "3dnow.h"
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "context.h"
+#include "types.h"
+#include "xform.h"
+
+#ifdef DEBUG
+#include "debug_xform.h"
+#endif
+
+
+
+
+#define XFORM_ARGS GLvector4f *to_vec, \
+ const GLmatrix *mat, \
+ const GLvector4f *from_vec, \
+ const GLubyte *mask, \
+ const GLubyte flag
+
+
+
+#define DECLARE_XFORM_GROUP(pfx, v, masked) \
+ extern void gl_##pfx##_transform_points##v##_general_##masked(XFORM_ARGS); \
+ extern void gl_##pfx##_transform_points##v##_identity_##masked(XFORM_ARGS); \
+ extern void gl_##pfx##_transform_points##v##_3d_no_rot_##masked(XFORM_ARGS); \
+ extern void gl_##pfx##_transform_points##v##_perspective_##masked(XFORM_ARGS);\
+ extern void gl_##pfx##_transform_points##v##_2d_##masked(XFORM_ARGS); \
+ extern void gl_##pfx##_transform_points##v##_2d_no_rot_##masked(XFORM_ARGS); \
+ extern void gl_##pfx##_transform_points##v##_3d_##masked(XFORM_ARGS);
+
+
+
+#define ASSIGN_XFORM_GROUP( pfx, cma, vsize, masked ) \
+ gl_transform_tab[cma][vsize][MATRIX_GENERAL] \
+ = gl_##pfx##_transform_points##vsize##_general_##masked; \
+ gl_transform_tab[cma][vsize][MATRIX_IDENTITY] \
+ = gl_##pfx##_transform_points##vsize##_identity_##masked; \
+ gl_transform_tab[cma][vsize][MATRIX_3D_NO_ROT] \
+ = gl_##pfx##_transform_points##vsize##_3d_no_rot_##masked; \
+ gl_transform_tab[cma][vsize][MATRIX_PERSPECTIVE] \
+ = gl_##pfx##_transform_points##vsize##_perspective_##masked; \
+ gl_transform_tab[cma][vsize][MATRIX_2D] \
+ = gl_##pfx##_transform_points##vsize##_2d_##masked; \
+ gl_transform_tab[cma][vsize][MATRIX_2D_NO_ROT] \
+ = gl_##pfx##_transform_points##vsize##_2d_no_rot_##masked; \
+ gl_transform_tab[cma][vsize][MATRIX_3D] \
+ = gl_##pfx##_transform_points##vsize##_3d_##masked;
+
+
+
+
+#define NORM_ARGS const GLmatrix *mat, \
+ GLfloat scale, \
+ const GLvector3f *in, \
+ const GLfloat *lengths, \
+ const GLubyte mask[], \
+ GLvector3f *dest
+
+
+
+#define DECLARE_NORM_GROUP(pfx, masked) \
+ extern void gl_##pfx##_rescale_normals_##masked## (NORM_ARGS); \
+ extern void gl_##pfx##_normalize_normals_##masked## (NORM_ARGS); \
+ extern void gl_##pfx##_transform_normals_##masked## (NORM_ARGS); \
+ extern void gl_##pfx##_transform_normals_no_rot_##masked## (NORM_ARGS); \
+ extern void gl_##pfx##_transform_rescale_normals_##masked## (NORM_ARGS); \
+ extern void gl_##pfx##_transform_rescale_normals_no_rot_##masked## (NORM_ARGS); \
+ extern void gl_##pfx##_transform_normalize_normals_##masked## (NORM_ARGS); \
+ extern void gl_##pfx##_transform_normalize_normals_no_rot_##masked## (NORM_ARGS);
+
+
+
+#define ASSIGN_NORM_GROUP( pfx, cma, masked ) \
+ gl_normal_tab[NORM_RESCALE][cma] = \
+ gl_##pfx##_rescale_normals_##masked##; \
+ gl_normal_tab[NORM_NORMALIZE][cma] = \
+ gl_##pfx##_normalize_normals_##masked##; \
+ gl_normal_tab[NORM_TRANSFORM][cma] = \
+ gl_##pfx##_transform_normals_##masked##; \
+ gl_normal_tab[NORM_TRANSFORM_NO_ROT][cma] = \
+ gl_##pfx##_transform_normals_no_rot_##masked##; \
+ gl_normal_tab[NORM_TRANSFORM | NORM_RESCALE][cma] = \
+ gl_##pfx##_transform_rescale_normals_##masked##; \
+ gl_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_RESCALE][cma] = \
+ gl_##pfx##_transform_rescale_normals_no_rot_##masked##; \
+ gl_normal_tab[NORM_TRANSFORM | NORM_NORMALIZE][cma] = \
+ gl_##pfx##_transform_normalize_normals_##masked##; \
+ gl_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE][cma] = \
+ gl_##pfx##_transform_normalize_normals_no_rot_##masked##;
+
+
+
+
+void gl_init_3dnow_asm_transforms (void)
+{
+ DECLARE_XFORM_GROUP( 3dnow, 1, raw )
+ DECLARE_XFORM_GROUP( 3dnow, 2, raw )
+ DECLARE_XFORM_GROUP( 3dnow, 3, raw )
+ DECLARE_XFORM_GROUP( 3dnow, 4, raw )
+
+ DECLARE_XFORM_GROUP( 3dnow, 1, masked )
+ DECLARE_XFORM_GROUP( 3dnow, 2, masked )
+ DECLARE_XFORM_GROUP( 3dnow, 3, masked )
+ DECLARE_XFORM_GROUP( 3dnow, 4, masked )
+
+ DECLARE_NORM_GROUP( 3dnow, raw )
+/* DECLARE_NORM_GROUP( 3dnow, masked )
+*/
+
+ ASSIGN_XFORM_GROUP( 3dnow, 0, 1, raw )
+ ASSIGN_XFORM_GROUP( 3dnow, 0, 2, raw )
+ ASSIGN_XFORM_GROUP( 3dnow, 0, 3, raw )
+ ASSIGN_XFORM_GROUP( 3dnow, 0, 4, raw )
+
+ ASSIGN_XFORM_GROUP( 3dnow, CULL_MASK_ACTIVE, 1, masked )
+ ASSIGN_XFORM_GROUP( 3dnow, CULL_MASK_ACTIVE, 2, masked )
+ ASSIGN_XFORM_GROUP( 3dnow, CULL_MASK_ACTIVE, 3, masked )
+ ASSIGN_XFORM_GROUP( 3dnow, CULL_MASK_ACTIVE, 4, masked )
+
+ ASSIGN_NORM_GROUP( 3dnow, 0, raw )
+/* ASSIGN_NORM_GROUP( 3dnow, CULL_MASK_ACTIVE, masked )
+*/
+
+#ifdef DEBUG
+ gl_test_all_transform_functions("3Dnow!");
+ gl_test_all_normal_transform_functions("3Dnow!");
+#endif
+}
+
+#endif
+
diff --git a/src/mesa/x86/3dnow.h b/src/mesa/x86/3dnow.h
new file mode 100644
index 0000000000..b06cc5b288
--- /dev/null
+++ b/src/mesa/x86/3dnow.h
@@ -0,0 +1,95 @@
+/* $Id: 3dnow.h,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+/*
+ * 3DNow! optimizations contributed by
+ * Holger Waechtler <holger@akaflieg.extern.tu-berlin.de>
+ */
+
+
+#ifndef _3dnow_h
+#define _3dnow_h
+
+
+
+#include "xform.h"
+
+
+void gl_init_3dnow_asm_transforms (void);
+
+
+
+
+#if 0
+GLvector4f *gl_project_points( GLvector4f *proj_vec,
+ const GLvector4f *clip_vec )
+{
+ __asm__ (
+ " femms \n"
+ " \n"
+ " movq (%0), %%mm0 # x1 | x0 \n"
+ " movq 8(%0), %%mm1 # oow | x2 \n"
+ " \n"
+ "1: movq %%mm1, %%mm2 # oow | x2 \n"
+ " addl %2, %0 # next point \n"
+ " \n"
+ " punpckhdq %%mm2, %%mm2 # oow | oow \n"
+ " addl $16, %1 # next point \n"
+ " \n"
+ " pfrcp %%mm2, %%mm3 # 1/oow | 1/oow \n"
+ " decl %3 \n"
+ " \n"
+ " pfmul %%mm3, %%mm0 # x1/oow | x0/oow \n"
+ " movq %%mm0, -16(%1) # write r0, r1 \n"
+ " \n"
+ " pfmul %%mm3, %%mm1 # 1 | x2/oow \n"
+ " movq (%0), %%mm0 # x1 | x0 \n"
+ " \n"
+ " movd %%mm1, 8(%1) # write r2 \n"
+ " movd %%mm3, 12(%1) # write r3 \n"
+ " \n"
+ " movq 8(%0), %%mm1 # oow | x2 \n"
+ " ja 1b \n"
+ " \n"
+ " femms \n"
+ " "
+ ::"a" (clip_vec->start),
+ "c" (proj_vec->start),
+ "g" (clip_vec->stride),
+ "d" (clip_vec->count)
+ );
+
+ proj_vec->flags |= VEC_SIZE_4;
+ proj_vec->size = 3;
+ proj_vec->count = clip_vec->count;
+ return proj_vec;
+}
+#endif
+
+
+
+#endif
diff --git a/src/mesa/x86/assyntax.h b/src/mesa/x86/assyntax.h
new file mode 100644
index 0000000000..3c922201dd
--- /dev/null
+++ b/src/mesa/x86/assyntax.h
@@ -0,0 +1,1629 @@
+#ifndef __ASSYNTAX_H__
+#define __ASSYNTAX_H__
+
+/*
+ * Copyright 1992 Vrije Universiteit, The Netherlands
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted, 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 the Vrije Universiteit not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. The Vrije Universiteit makes no
+ * representations about the suitability of this software for any purpose.
+ * It is provided "as is" without express or implied warranty.
+ *
+ * The Vrije Universiteit DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL The Vrije Universiteit 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.
+ */
+
+/*
+ * assyntax.h
+ *
+ * Select the syntax appropriate to the 386 assembler being used
+ * To add support for more assemblers add more columns to the CHOICE
+ * macro. Note that register names must also have uppercase names
+ * to avoid macro recursion. e.g., #define ah %ah recurses!
+ *
+ * NB 1. Some of the macros for certain assemblers imply that the code is to
+ * run in protected mode!! Caveat emptor.
+ *
+ * NB 2. 486 specific instructions are not included. This is to discourage
+ * their accidental use in code that is intended to run on 386 and 486
+ * systems.
+ *
+ * Supported assemblers:
+ *
+ * (a) AT&T SysVr4 as(1): define ATT_ASSEMBLER
+ * (b) GNU Assembler gas: define GNU_ASSEMBLER (default)
+ * (c) Amsterdam Compiler kit: define ACK_ASSEMBLER
+ * (d) The Netwide Assembler: define NASM_ASSEMBLER
+ * (e) Microsoft Assembler: define MASM_ASSEMBLER (UNTESTED!)
+ *
+ * The following naming conventions have been used to identify the various
+ * data types:
+ * _SR = segment register version
+ * Integer:
+ * _Q = quadword = 64 bits
+ * _L = long = 32 bits
+ * _W = short = 16 bits
+ * _B = byte = 8 bits
+ * Floating-point:
+ * _X = m80real = 80 bits
+ * _D = double = 64 bits
+ * _S = single = 32 bits
+ *
+ * Author: Gregory J. Sharp, Sept 1992
+ * Vrije Universiteit, Amsterdam, The Netherlands
+ *
+ * [support for Intel syntax added by Josh Vanderhoof, 1999]
+ */
+
+#if !(defined(NASM_ASSEMBLER) || defined(MASM_ASSEMBLER))
+
+#if !defined(ATT_ASSEMBLER) && !defined(GNU_ASSEMBLER) && !defined(ACK_ASSEMBLER)
+#define GNU_ASSEMBLER
+#endif
+
+#if (defined(__STDC__) && !defined(UNIXCPP)) || (defined (sun) && defined (i386) \
+ && defined (SVR4) && defined (__STDC__) && !defined (__GNUC__))
+#define CONCAT(x, y) x ## y
+#else
+#define CONCAT(x, y) x/**/y
+#endif
+
+#ifdef ACK_ASSEMBLER
+
+/* Assume we write code for 32-bit protected mode! */
+
+/* Redefine register names for GAS & AT&T assemblers */
+#define AL al
+#define AH ah
+#define AX ax
+#define EAX ax
+#define BL bl
+#define BH bh
+#define BX bx
+#define EBX bx
+#define CL cl
+#define CH ch
+#define CX cx
+#define ECX cx
+#define DL dl
+#define DH dh
+#define DX dx
+#define EDX dx
+#define BP bp
+#define EBP bp
+#define SI si
+#define ESI si
+#define DI di
+#define EDI di
+#define SP sp
+#define ESP sp
+#define CS cs
+#define SS ss
+#define DS ds
+#define ES es
+#define FS fs
+#define GS gs
+/* Control Registers */
+#define CR0 cr0
+#define CR1 cr1
+#define CR2 cr2
+#define CR3 cr3
+/* Debug Registers */
+#define DR0 dr0
+#define DR1 dr1
+#define DR2 dr2
+#define DR3 dr3
+#define DR4 dr4
+#define DR5 dr5
+#define DR6 dr6
+#define DR7 dr7
+/* Floating-point Stack */
+#define ST st
+
+#define AS_BEGIN .sect .text; .sect .rom; .sect .data; .sect .bss; .sect .text
+
+
+#define _WTOG o16 /* word toggle for _W instructions */
+#define _LTOG /* long toggle for _L instructions */
+#define ADDR_TOGGLE a16
+#define OPSZ_TOGGLE o16
+#define USE16 .use16
+#define USE32 .use32
+
+#define CHOICE(a,b,c) c
+
+#else /* AT&T or GAS */
+
+/* Redefine register names for GAS & AT&T assemblers */
+#define AL %al
+#define AH %ah
+#define AX %ax
+#define EAX %eax
+#define BL %bl
+#define BH %bh
+#define BX %bx
+#define EBX %ebx
+#define CL %cl
+#define CH %ch
+#define CX %cx
+#define ECX %ecx
+#define DL %dl
+#define DH %dh
+#define DX %dx
+#define EDX %edx
+#define BP %bp
+#define EBP %ebp
+#define SI %si
+#define ESI %esi
+#define DI %di
+#define EDI %edi
+#define SP %sp
+#define ESP %esp
+#define CS %cs
+#define SS %ss
+#define DS %ds
+#define ES %es
+#define FS %fs
+#define GS %gs
+/* Control Registers */
+#define CR0 %cr0
+#define CR1 %cr1
+#define CR2 %cr2
+#define CR3 %cr3
+/* Debug Registers */
+#define DR0 %db0
+#define DR1 %db1
+#define DR2 %db2
+#define DR3 %db3
+#define DR4 %db4
+#define DR5 %db5
+#define DR6 %db6
+#define DR7 %db7
+/* Floating-point Stack */
+#define ST %st
+/* MMX Registers */
+#define MM0 %mm0
+#define MM1 %mm1
+#define MM2 %mm2
+#define MM3 %mm3
+#define MM4 %mm4
+#define MM5 %mm5
+#define MM6 %mm6
+#define MM7 %mm7
+/* SSE Registers */
+#define XMM0 %xmm0
+#define XMM1 %xmm1
+#define XMM2 %xmm2
+#define XMM3 %xmm3
+#define XMM4 %xmm4
+#define XMM5 %xmm5
+#define XMM6 %xmm6
+#define XMM7 %xmm7
+
+#define AS_BEGIN
+#define USE16
+#define USE32
+
+#ifdef GNU_ASSEMBLER
+
+#define ADDR_TOGGLE aword
+#define OPSZ_TOGGLE word
+
+#define CHOICE(a,b,c) b
+
+#else
+/*
+ * AT&T ASSEMBLER SYNTAX
+ * *********************
+ */
+#define CHOICE(a,b,c) a
+
+#define ADDR_TOGGLE addr16
+#define OPSZ_TOGGLE data16
+
+#endif /* GNU_ASSEMBLER */
+#endif /* ACK_ASSEMBLER */
+
+
+#if defined(Lynx) || (defined(SYSV) || defined(SVR4)) && !defined(ACK_ASSEMBLER) \
+ || (defined(linux) || defined(__OS2ELF__)) && defined(__ELF__)
+#define GLNAME(a) a
+#else
+#define GLNAME(a) CONCAT(_,a)
+#endif
+
+
+ /****************************************/
+ /* */
+ /* Select the various choices */
+ /* */
+ /****************************************/
+
+
+/* Redefine assembler directives */
+/*********************************/
+#define GLOBL CHOICE(.globl, .globl, .extern)
+/*
+#define ALIGNTEXT32 CHOICE(.align 32, .align ARG2(5,0x90), .align 32)
+*/
+#define ALIGNTEXT32 CHOICE(.align 32, .balign 32, .align 32)
+#define ALIGNTEXT16 CHOICE(.align 16, .balign 16, .align 16)
+#define ALIGNTEXT8 CHOICE(.align 8, .balign 8, .align 8)
+#define ALIGNTEXT4 CHOICE(.align 4, .balign 4, .align 4)
+#define ALIGNTEXT2 CHOICE(.align 2, .balign 2, .align 2)
+/* ALIGNTEXT4ifNOP is the same as ALIGNTEXT4, but only if the space is
+ * guaranteed to be filled with NOPs. Otherwise it does nothing.
+ */
+#define ALIGNTEXT32ifNOP CHOICE(.align 32, .balign ARG2(32,0x90), /*can't do it*/)
+#define ALIGNTEXT16ifNOP CHOICE(.align 16, .balign ARG2(16,0x90), /*can't do it*/)
+#define ALIGNTEXT8ifNOP CHOICE(.align 8, .balign ARG2(8,0x90), /*can't do it*/)
+#define ALIGNTEXT4ifNOP CHOICE(.align 4, .balign ARG2(4,0x90), /*can't do it*/)
+#define ALIGNDATA32 CHOICE(.align 32, .balign ARG2(32,0x0), .align 32)
+#define ALIGNDATA16 CHOICE(.align 16, .balign ARG2(16,0x0), .align 16)
+#define ALIGNDATA8 CHOICE(.align 8, .balign ARG2(8,0x0), .align 8)
+#define ALIGNDATA4 CHOICE(.align 4, .balign ARG2(4,0x0), .align 4)
+#define ALIGNDATA2 CHOICE(.align 2, .balign ARG2(2,0x0), .align 2)
+#define FILE(s) CHOICE(.file s, .file s, .file s)
+#define STRING(s) CHOICE(.string s, .asciz s, .asciz s)
+#define D_LONG CHOICE(.long, .long, .data4)
+#define D_WORD CHOICE(.value, .short, .data2)
+#define D_BYTE CHOICE(.byte, .byte, .data1)
+#define SPACE CHOICE(.comm, .space, .space)
+#define COMM CHOICE(.comm, .comm, .comm)
+#define SEG_DATA CHOICE(.data, .data, .sect .data)
+#define SEG_TEXT CHOICE(.text, .text, .sect .text)
+#define SEG_BSS CHOICE(.bss, .bss, .sect .bss)
+
+#ifdef GNU_ASSEMBLER
+#define D_SPACE(n) . = . + n
+#else
+#define D_SPACE(n) .space n
+#endif
+
+/* Addressing Modes */
+/* Immediate Mode */
+#define ADDR(a) CHOICE(CONCAT($,a), CONCAT($,a), a)
+#define CONST(a) CHOICE(CONCAT($,a), CONCAT($,a), a)
+
+/* Indirect Mode */
+#define CONTENT(a) CHOICE(a, a, (a)) /* take contents of variable */
+#define REGIND(a) CHOICE((a), (a), (a)) /* Register a indirect */
+/* Register b indirect plus displacement a */
+#define REGOFF(a, b) CHOICE(a(b), a(b), a(b))
+/* Reg indirect Base + Index + Displacement - this is mainly for 16-bit mode
+ * which has no scaling
+ */
+#define REGBID(b,i,d) CHOICE(d(b,i), d(b,i), d(b)(i))
+/* Reg indirect Base + (Index * Scale) + Displacement */
+#define REGBISD(b,i,s,d) CHOICE(d(b,i,s), d(b,i,s), d(b)(i*s))
+/* Displaced Scaled Index: */
+#define REGDIS(d,i,s) CHOICE(d(,i,s), d(,i,s), d(i * s))
+/* Indexed Base: */
+#define REGBI(b,i) CHOICE((b,i), (b,i), (b)(i))
+/* Displaced Base: */
+#define REGDB(d,b) CHOICE(d(b), d(b), d(b))
+/* Variable indirect: */
+#define VARINDIRECT(var) CHOICE(*var, *var, (var))
+/* Use register contents as jump/call target: */
+#define CODEPTR(reg) CHOICE(*reg, *reg, reg)
+
+/* For expressions requiring bracketing
+ * eg. (CRT0_PM | CRT_EM)
+ */
+
+#define EXPR(a) CHOICE([a], (a), [a])
+#define ENOT(a) CHOICE(0!a, ~a, ~a)
+#define EMUL(a,b) CHOICE(a\*b, a*b, a*b)
+#define EDIV(a,b) CHOICE(a\/b, a/b, a/b)
+
+/*
+ * We have to beat the problem of commas within arguments to choice.
+ * eg. choice (add a,b, add b,a) will get argument mismatch. Luckily ANSI
+ * and other known cpp definitions evaluate arguments before substitution
+ * so the following works.
+ */
+#define ARG2(a, b) a,b
+#define ARG3(a,b,c) a,b,c
+
+/* Redefine assembler commands */
+#define AAA CHOICE(aaa, aaa, aaa)
+#define AAD CHOICE(aad, aad, aad)
+#define AAM CHOICE(aam, aam, aam)
+#define AAS CHOICE(aas, aas, aas)
+#define ADC_L(a, b) CHOICE(adcl ARG2(a,b), adcl ARG2(a,b), _LTOG adc ARG2(b,a))
+#define ADC_W(a, b) CHOICE(adcw ARG2(a,b), adcw ARG2(a,b), _WTOG adc ARG2(b,a))
+#define ADC_B(a, b) CHOICE(adcb ARG2(a,b), adcb ARG2(a,b), adcb ARG2(b,a))
+#define ADD_L(a, b) CHOICE(addl ARG2(a,b), addl ARG2(a,b), _LTOG add ARG2(b,a))
+#define ADD_W(a, b) CHOICE(addw ARG2(a,b), addw ARG2(a,b), _WTOG add ARG2(b,a))
+#define ADD_B(a, b) CHOICE(addb ARG2(a,b), addb ARG2(a,b), addb ARG2(b,a))
+#define AND_L(a, b) CHOICE(andl ARG2(a,b), andl ARG2(a,b), _LTOG and ARG2(b,a))
+#define AND_W(a, b) CHOICE(andw ARG2(a,b), andw ARG2(a,b), _WTOG and ARG2(b,a))
+#define AND_B(a, b) CHOICE(andb ARG2(a,b), andb ARG2(a,b), andb ARG2(b,a))
+#define ARPL(a,b) CHOICE(arpl ARG2(a,b), arpl ARG2(a,b), arpl ARG2(b,a))
+#define BOUND_L(a, b) CHOICE(boundl ARG2(a,b), boundl ARG2(b,a), _LTOG bound ARG2(b,a))
+#define BOUND_W(a, b) CHOICE(boundw ARG2(a,b), boundw ARG2(b,a), _WTOG bound ARG2(b,a))
+#define BSF_L(a, b) CHOICE(bsfl ARG2(a,b), bsfl ARG2(a,b), _LTOG bsf ARG2(b,a))
+#define BSF_W(a, b) CHOICE(bsfw ARG2(a,b), bsfw ARG2(a,b), _WTOG bsf ARG2(b,a))
+#define BSR_L(a, b) CHOICE(bsrl ARG2(a,b), bsrl ARG2(a,b), _LTOG bsr ARG2(b,a))
+#define BSR_W(a, b) CHOICE(bsrw ARG2(a,b), bsrw ARG2(a,b), _WTOG bsr ARG2(b,a))
+#define BT_L(a, b) CHOICE(btl ARG2(a,b), btl ARG2(a,b), _LTOG bt ARG2(b,a))
+#define BT_W(a, b) CHOICE(btw ARG2(a,b), btw ARG2(a,b), _WTOG bt ARG2(b,a))
+#define BTC_L(a, b) CHOICE(btcl ARG2(a,b), btcl ARG2(a,b), _LTOG btc ARG2(b,a))
+#define BTC_W(a, b) CHOICE(btcw ARG2(a,b), btcw ARG2(a,b), _WTOG btc ARG2(b,a))
+#define BTR_L(a, b) CHOICE(btrl ARG2(a,b), btrl ARG2(a,b), _LTOG btr ARG2(b,a))
+#define BTR_W(a, b) CHOICE(btrw ARG2(a,b), btrw ARG2(a,b), _WTOG btr ARG2(b,a))
+#define BTS_L(a, b) CHOICE(btsl ARG2(a,b), btsl ARG2(a,b), _LTOG bts ARG2(b,a))
+#define BTS_W(a, b) CHOICE(btsw ARG2(a,b), btsw ARG2(a,b), _WTOG bts ARG2(b,a))
+#define CALL(a) CHOICE(call a, call a, call a)
+#define CALLF(s,a) CHOICE(lcall ARG2(s,a), lcall ARG2(s,a), callf s:a)
+#define CBW CHOICE(cbtw, cbw, cbw)
+#define CWDE CHOICE(cwtd, cwde, cwde)
+#define CLC CHOICE(clc, clc, clc)
+#define CLD CHOICE(cld, cld, cld)
+#define CLI CHOICE(cli, cli, cli)
+#define CLTS CHOICE(clts, clts, clts)
+#define CMC CHOICE(cmc, cmc, cmc)
+#define CMP_L(a, b) CHOICE(cmpl ARG2(a,b), cmpl ARG2(a,b), _LTOG cmp ARG2(b,a))
+#define CMP_W(a, b) CHOICE(cmpw ARG2(a,b), cmpw ARG2(a,b), _WTOG cmp ARG2(b,a))
+#define CMP_B(a, b) CHOICE(cmpb ARG2(a,b), cmpb ARG2(a,b), cmpb ARG2(b,a))
+#define CMPS_L CHOICE(cmpsl, cmpsl, _LTOG cmps)
+#define CMPS_W CHOICE(cmpsw, cmpsw, _WTOG cmps)
+#define CMPS_B CHOICE(cmpsb, cmpsb, cmpsb)
+#define CWD CHOICE(cwtl, cwd, cwd)
+#define CDQ CHOICE(cltd, cdq, cdq)
+#define DAA CHOICE(daa, daa, daa)
+#define DAS CHOICE(das, das, das)
+#define DEC_L(a) CHOICE(decl a, decl a, _LTOG dec a)
+#define DEC_W(a) CHOICE(decw a, decw a, _WTOG dec a)
+#define DEC_B(a) CHOICE(decb a, decb a, decb a)
+#define DIV_L(a) CHOICE(divl a, divl a, div a)
+#define DIV_W(a) CHOICE(divw a, divw a, div a)
+#define DIV_B(a) CHOICE(divb a, divb a, divb a)
+#define ENTER(a,b) CHOICE(enter ARG2(a,b), enter ARG2(a,b), enter ARG2(b,a))
+#define HLT CHOICE(hlt, hlt, hlt)
+#define IDIV_L(a) CHOICE(idivl a, idivl a, _LTOG idiv a)
+#define IDIV_W(a) CHOICE(idivw a, idivw a, _WTOG idiv a)
+#define IDIV_B(a) CHOICE(idivb a, idivb a, idivb a)
+/* More forms than this for imul!! */
+#define IMUL_L(a, b) CHOICE(imull ARG2(a,b), imull ARG2(a,b), _LTOG imul ARG2(b,a))
+#define IMUL_W(a, b) CHOICE(imulw ARG2(a,b), imulw ARG2(a,b), _WTOG imul ARG2(b,a))
+#define IMUL_B(a) CHOICE(imulb a, imulb a, imulb a)
+#define IN_L CHOICE(inl (DX), inl ARG2(DX,EAX), _LTOG in DX)
+#define IN_W CHOICE(inw (DX), inw ARG2(DX,AX), _WTOG in DX)
+#define IN_B CHOICE(inb (DX), inb ARG2(DX,AL), inb DX)
+/* Please AS code writer: use the following ONLY, if you refer to ports<256
+ * directly, but not in IN1_W(DX), for instance, even if IN1_ looks nicer
+ */
+#if defined (sun)
+#define IN1_L(a) CHOICE(inl (a), inl ARG2(a,EAX), _LTOG in a)
+#define IN1_W(a) CHOICE(inw (a), inw ARG2(a,AX), _WTOG in a)
+#define IN1_B(a) CHOICE(inb (a), inb ARG2(a,AL), inb a)
+#else
+#define IN1_L(a) CHOICE(inl a, inl ARG2(a,EAX), _LTOG in a)
+#define IN1_W(a) CHOICE(inw a, inw ARG2(a,AX), _WTOG in a)
+#define IN1_B(a) CHOICE(inb a, inb ARG2(a,AL), inb a)
+#endif
+#define INC_L(a) CHOICE(incl a, incl a, _LTOG inc a)
+#define INC_W(a) CHOICE(incw a, incw a, _WTOG inc a)
+#define INC_B(a) CHOICE(incb a, incb a, incb a)
+#define INS_L CHOICE(insl, insl, _LTOG ins)
+#define INS_W CHOICE(insw, insw, _WTOG ins)
+#define INS_B CHOICE(insb, insb, insb)
+#define INT(a) CHOICE(int a, int a, int a)
+#define INT3 CHOICE(int CONST(3), int3, int CONST(3))
+#define INTO CHOICE(into, into, into)
+#define IRET CHOICE(iret, iret, iret)
+#define IRETD CHOICE(iret, iret, iretd)
+#define JA(a) CHOICE(ja a, ja a, ja a)
+#define JAE(a) CHOICE(jae a, jae a, jae a)
+#define JB(a) CHOICE(jb a, jb a, jb a)
+#define JBE(a) CHOICE(jbe a, jbe a, jbe a)
+#define JC(a) CHOICE(jc a, jc a, jc a)
+#define JE(a) CHOICE(je a, je a, je a)
+#define JG(a) CHOICE(jg a, jg a, jg a)
+#define JGE(a) CHOICE(jge a, jge a, jge a)
+#define JL(a) CHOICE(jl a, jl a, jl a)
+#define JLE(a) CHOICE(jle a, jle a, jle a)
+#define JNA(a) CHOICE(jna a, jna a, jna a)
+#define JNAE(a) CHOICE(jnae a, jnae a, jnae a)
+#define JNB(a) CHOICE(jnb a, jnb a, jnb a)
+#define JNBE(a) CHOICE(jnbe a, jnbe a, jnbe a)
+#define JNC(a) CHOICE(jnc a, jnc a, jnc a)
+#define JNE(a) CHOICE(jne a, jne a, jne a)
+#define JNG(a) CHOICE(jng a, jng a, jng a)
+#define JNGE(a) CHOICE(jnge a, jnge a, jnge a)
+#define JNL(a) CHOICE(jnl a, jnl a, jnl a)
+#define JNLE(a) CHOICE(jnle a, jnle a, jnle a)
+#define JNO(a) CHOICE(jno a, jno a, jno a)
+#define JNP(a) CHOICE(jnp a, jnp a, jnp a)
+#define JNS(a) CHOICE(jns a, jns a, jns a)
+#define JNZ(a) CHOICE(jnz a, jnz a, jnz a)
+#define JO(a) CHOICE(jo a, jo a, jo a)
+#define JP(a) CHOICE(jp a, jp a, jp a)
+#define JPE(a) CHOICE(jpe a, jpe a, jpe a)
+#define JPO(a) CHOICE(jpo a, jpo a, jpo a)
+#define JS(a) CHOICE(js a, js a, js a)
+#define JZ(a) CHOICE(jz a, jz a, jz a)
+#define JMP(a) CHOICE(jmp a, jmp a, jmp a)
+#define JMPF(s,a) CHOICE(ljmp ARG2(s,a), ljmp ARG2(s,a), jmpf s:a)
+#define LAHF CHOICE(lahf, lahf, lahf)
+#if !defined(_REAL_MODE) && !defined(_V86_MODE)
+#define LAR(a, b) CHOICE(lar ARG2(a, b), lar ARG2(a, b), lar ARG2(b, a))
+#endif
+#define LEA_L(a, b) CHOICE(leal ARG2(a,b), leal ARG2(a,b), _LTOG lea ARG2(b,a))
+#define LEA_W(a, b) CHOICE(leaw ARG2(a,b), leaw ARG2(a,b), _WTOG lea ARG2(b,a))
+#define LEAVE CHOICE(leave, leave, leave)
+#define LGDT(a) CHOICE(lgdt a, lgdt a, lgdt a)
+#define LIDT(a) CHOICE(lidt a, lidt a, lidt a)
+#define LDS(a, b) CHOICE(ldsl ARG2(a,b), lds ARG2(a,b), lds ARG2(b,a))
+#define LES(a, b) CHOICE(lesl ARG2(a,b), les ARG2(a,b), les ARG2(b,a))
+#define LFS(a, b) CHOICE(lfsl ARG2(a,b), lfs ARG2(a,b), lfs ARG2(b,a))
+#define LGS(a, b) CHOICE(lgsl ARG2(a,b), lgs ARG2(a,b), lgs ARG2(b,a))
+#define LSS(a, b) CHOICE(lssl ARG2(a,b), lss ARG2(a,b), lss ARG2(b,a))
+#define LLDT(a) CHOICE(lldt a, lldt a, lldt a)
+#define LMSW(a) CHOICE(lmsw a, lmsw a, lmsw a)
+#define LOCK CHOICE(lock, lock, lock)
+#define LODS_L CHOICE(lodsl, lodsl, _LTOG lods)
+#define LODS_W CHOICE(lodsw, lodsw, _WTOG lods)
+#define LODS_B CHOICE(lodsb, lodsb, lodsb)
+#define LOOP(a) CHOICE(loop a, loop a, loop a)
+#define LOOPE(a) CHOICE(loope a, loope a, loope a)
+#define LOOPZ(a) CHOICE(loopz a, loopz a, loopz a)
+#define LOOPNE(a) CHOICE(loopne a, loopne a, loopne a)
+#define LOOPNZ(a) CHOICE(loopnz a, loopnz a, loopnz a)
+#if !defined(_REAL_MODE) && !defined(_V86_MODE)
+#define LSL(a, b) CHOICE(lsl ARG2(a,b), lsl ARG2(a,b), lsl ARG2(b,a))
+#endif
+#define LTR(a) CHOICE(ltr a, ltr a, ltr a)
+#define MOV_SR(a, b) CHOICE(movw ARG2(a,b), mov ARG2(a,b), mov ARG2(b,a))
+#define MOV_L(a, b) CHOICE(movl ARG2(a,b), movl ARG2(a,b), _LTOG mov ARG2(b,a))
+#define MOV_W(a, b) CHOICE(movw ARG2(a,b), movw ARG2(a,b), _WTOG mov ARG2(b,a))
+#define MOV_B(a, b) CHOICE(movb ARG2(a,b), movb ARG2(a,b), movb ARG2(b,a))
+#define MOVS_L CHOICE(movsl, movsl, _LTOG movs)
+#define MOVS_W CHOICE(movsw, movsw, _WTOG movs)
+#define MOVS_B CHOICE(movsb, movsb, movsb)
+#define MOVSX_BL(a, b) CHOICE(movsbl ARG2(a,b), movsbl ARG2(a,b), movsx ARG2(b,a))
+#define MOVSX_BW(a, b) CHOICE(movsbw ARG2(a,b), movsbw ARG2(a,b), movsx ARG2(b,a))
+#define MOVSX_WL(a, b) CHOICE(movswl ARG2(a,b), movswl ARG2(a,b), movsx ARG2(b,a))
+#define MOVZX_BL(a, b) CHOICE(movzbl ARG2(a,b), movzbl ARG2(a,b), movzx ARG2(b,a))
+#define MOVZX_BW(a, b) CHOICE(movzbw ARG2(a,b), movzbw ARG2(a,b), movzx ARG2(b,a))
+#define MOVZX_WL(a, b) CHOICE(movzwl ARG2(a,b), movzwl ARG2(a,b), movzx ARG2(b,a))
+#define MUL_L(a) CHOICE(mull a, mull a, _LTOG mul a)
+#define MUL_W(a) CHOICE(mulw a, mulw a, _WTOG mul a)
+#define MUL_B(a) CHOICE(mulb a, mulb a, mulb a)
+#define NEG_L(a) CHOICE(negl a, negl a, _LTOG neg a)
+#define NEG_W(a) CHOICE(negw a, negw a, _WTOG neg a)
+#define NEG_B(a) CHOICE(negb a, negb a, negb a)
+#define NOP CHOICE(nop, nop, nop)
+#define NOT_L(a) CHOICE(notl a, notl a, _LTOG not a)
+#define NOT_W(a) CHOICE(notw a, notw a, _WTOG not a)
+#define NOT_B(a) CHOICE(notb a, notb a, notb a)
+#define OR_L(a,b) CHOICE(orl ARG2(a,b), orl ARG2(a,b), _LTOG or ARG2(b,a))
+#define OR_W(a,b) CHOICE(orw ARG2(a,b), orw ARG2(a,b), _WTOG or ARG2(b,a))
+#define OR_B(a,b) CHOICE(orb ARG2(a,b), orb ARG2(a,b), orb ARG2(b,a))
+#define OUT_L CHOICE(outl (DX), outl ARG2(EAX,DX), _LTOG out DX)
+#define OUT_W CHOICE(outw (DX), outw ARG2(AX,DX), _WTOG out DX)
+#define OUT_B CHOICE(outb (DX), outb ARG2(AL,DX), outb DX)
+/* Please AS code writer: use the following ONLY, if you refer to ports<256
+ * directly, but not in OUT1_W(DX), for instance, even if OUT1_ looks nicer
+ */
+#define OUT1_L(a) CHOICE(outl (a), outl ARG2(EAX,a), _LTOG out a)
+#define OUT1_W(a) CHOICE(outw (a), outw ARG2(AX,a), _WTOG out a)
+#define OUT1_B(a) CHOICE(outb (a), outb ARG2(AL,a), outb a)
+#define OUTS_L CHOICE(outsl, outsl, _LTOG outs)
+#define OUTS_W CHOICE(outsw, outsw, _WTOG outs)
+#define OUTS_B CHOICE(outsb, outsb, outsb)
+#define POP_SR(a) CHOICE(pop a, pop a, pop a)
+#define POP_L(a) CHOICE(popl a, popl a, _LTOG pop a)
+#define POP_W(a) CHOICE(popw a, popw a, _WTOG pop a)
+#define POPA_L CHOICE(popal, popal, _LTOG popa)
+#define POPA_W CHOICE(popaw, popaw, _WTOG popa)
+#define POPF_L CHOICE(popfl, popfl, _LTOG popf)
+#define POPF_W CHOICE(popfw, popfw, _WTOG popf)
+#define PUSH_SR(a) CHOICE(push a, push a, push a)
+#define PUSH_L(a) CHOICE(pushl a, pushl a, _LTOG push a)
+#define PUSH_W(a) CHOICE(pushw a, pushw a, _WTOG push a)
+#define PUSH_B(a) CHOICE(push a, pushb a, push a)
+#define PUSHA_L CHOICE(pushal, pushal, _LTOG pusha)
+#define PUSHA_W CHOICE(pushaw, pushaw, _WTOG pusha)
+#define PUSHF_L CHOICE(pushfl, pushfl, _LTOG pushf)
+#define PUSHF_W CHOICE(pushfw, pushfw, _WTOG pushf)
+#define RCL_L(a, b) CHOICE(rcll ARG2(a,b), rcll ARG2(a,b), _LTOG rcl ARG2(b,a))
+#define RCL_W(a, b) CHOICE(rclw ARG2(a,b), rclw ARG2(a,b), _WTOG rcl ARG2(b,a))
+#define RCL_B(a, b) CHOICE(rclb ARG2(a,b), rclb ARG2(a,b), rclb ARG2(b,a))
+#define RCR_L(a, b) CHOICE(rcrl ARG2(a,b), rcrl ARG2(a,b), _LTOG rcr ARG2(b,a))
+#define RCR_W(a, b) CHOICE(rcrw ARG2(a,b), rcrw ARG2(a,b), _WTOG rcr ARG2(b,a))
+#define RCR_B(a, b) CHOICE(rcrb ARG2(a,b), rcrb ARG2(a,b), rcrb ARG2(b,a))
+#define ROL_L(a, b) CHOICE(roll ARG2(a,b), roll ARG2(a,b), _LTOG rol ARG2(b,a))
+#define ROL_W(a, b) CHOICE(rolw ARG2(a,b), rolw ARG2(a,b), _WTOG rol ARG2(b,a))
+#define ROL_B(a, b) CHOICE(rolb ARG2(a,b), rolb ARG2(a,b), rolb ARG2(b,a))
+#define ROR_L(a, b) CHOICE(rorl ARG2(a,b), rorl ARG2(a,b), _LTOG ror ARG2(b,a))
+#define ROR_W(a, b) CHOICE(rorw ARG2(a,b), rorw ARG2(a,b), _WTOG ror ARG2(b,a))
+#define ROR_B(a, b) CHOICE(rorb ARG2(a,b), rorb ARG2(a,b), rorb ARG2(b,a))
+#define REP CHOICE(rep ;, rep ;, repe)
+#define REPE CHOICE(repz ;, repe ;, repe)
+#define REPNE CHOICE(repnz ;, repne ;, repne)
+#define REPNZ REPNE
+#define REPZ REPE
+#define RET CHOICE(ret, ret, ret)
+#define SAHF CHOICE(sahf, sahf, sahf)
+#define SAL_L(a, b) CHOICE(sall ARG2(a,b), sall ARG2(a,b), _LTOG sal ARG2(b,a))
+#define SAL_W(a, b) CHOICE(salw ARG2(a,b), salw ARG2(a,b), _WTOG sal ARG2(b,a))
+#define SAL_B(a, b) CHOICE(salb ARG2(a,b), salb ARG2(a,b), salb ARG2(b,a))
+#define SAR_L(a, b) CHOICE(sarl ARG2(a,b), sarl ARG2(a,b), _LTOG sar ARG2(b,a))
+#define SAR_W(a, b) CHOICE(sarw ARG2(a,b), sarw ARG2(a,b), _WTOG sar ARG2(b,a))
+#define SAR_B(a, b) CHOICE(sarb ARG2(a,b), sarb ARG2(a,b), sarb ARG2(b,a))
+#define SBB_L(a, b) CHOICE(sbbl ARG2(a,b), sbbl ARG2(a,b), _LTOG sbb ARG2(b,a))
+#define SBB_W(a, b) CHOICE(sbbw ARG2(a,b), sbbw ARG2(a,b), _WTOG sbb ARG2(b,a))
+#define SBB_B(a, b) CHOICE(sbbb ARG2(a,b), sbbb ARG2(a,b), sbbb ARG2(b,a))
+#define SCAS_L CHOICE(scasl, scasl, _LTOG scas)
+#define SCAS_W CHOICE(scasw, scasw, _WTOG scas)
+#define SCAS_B CHOICE(scasb, scasb, scasb)
+#define SETA(a) CHOICE(seta a, seta a, seta a)
+#define SETAE(a) CHOICE(setae a, setae a, setae a)
+#define SETB(a) CHOICE(setb a, setb a, setb a)
+#define SETBE(a) CHOICE(setbe a, setbe a, setbe a)
+#define SETC(a) CHOICE(setc a, setb a, setb a)
+#define SETE(a) CHOICE(sete a, sete a, sete a)
+#define SETG(a) CHOICE(setg a, setg a, setg a)
+#define SETGE(a) CHOICE(setge a, setge a, setge a)
+#define SETL(a) CHOICE(setl a, setl a, setl a)
+#define SETLE(a) CHOICE(setle a, setle a, setle a)
+#define SETNA(a) CHOICE(setna a, setna a, setna a)
+#define SETNAE(a) CHOICE(setnae a, setnae a, setnae a)
+#define SETNB(a) CHOICE(setnb a, setnb a, setnb a)
+#define SETNBE(a) CHOICE(setnbe a, setnbe a, setnbe a)
+#define SETNC(a) CHOICE(setnc a, setnb a, setnb a)
+#define SETNE(a) CHOICE(setne a, setne a, setne a)
+#define SETNG(a) CHOICE(setng a, setng a, setng a)
+#define SETNGE(a) CHOICE(setnge a, setnge a, setnge a)
+#define SETNL(a) CHOICE(setnl a, setnl a, setnl a)
+#define SETNLE(a) CHOICE(setnle a, setnle a, setnle a)
+#define SETNO(a) CHOICE(setno a, setno a, setno a)
+#define SETNP(a) CHOICE(setnp a, setnp a, setnp a)
+#define SETNS(a) CHOICE(setns a, setns a, setna a)
+#define SETNZ(a) CHOICE(setnz a, setnz a, setnz a)
+#define SETO(a) CHOICE(seto a, seto a, seto a)
+#define SETP(a) CHOICE(setp a, setp a, setp a)
+#define SETPE(a) CHOICE(setpe a, setpe a, setpe a)
+#define SETPO(a) CHOICE(setpo a, setpo a, setpo a)
+#define SETS(a) CHOICE(sets a, sets a, seta a)
+#define SETZ(a) CHOICE(setz a, setz a, setz a)
+#define SGDT(a) CHOICE(sgdt a, sgdt a, sgdt a)
+#define SIDT(a) CHOICE(sidt a, sidt a, sidt a)
+#define SHL_L(a, b) CHOICE(shll ARG2(a,b), shll ARG2(a,b), _LTOG shl ARG2(b,a))
+#define SHL_W(a, b) CHOICE(shlw ARG2(a,b), shlw ARG2(a,b), _WTOG shl ARG2(b,a))
+#define SHL_B(a, b) CHOICE(shlb ARG2(a,b), shlb ARG2(a,b), shlb ARG2(b,a))
+#define SHLD_L(a,b,c) CHOICE(shldl ARG3(a,b,c), shldl ARG3(a,b,c), _LTOG shld ARG3(c,b,a))
+#define SHLD2_L(a,b) CHOICE(shldl ARG2(a,b), shldl ARG3(CL,a,b), _LTOG shld ARG3(b,a,CL))
+#define SHLD_W(a,b,c) CHOICE(shldw ARG3(a,b,c), shldw ARG3(a,b,c), _WTOG shld ARG3(c,b,a))
+#define SHLD2_W(a,b) CHOICE(shldw ARG2(a,b), shldw ARG3(CL,a,b), _WTOG shld ARG3(b,a,CL))
+#define SHR_L(a, b) CHOICE(shrl ARG2(a,b), shrl ARG2(a,b), _LTOG shr ARG2(b,a))
+#define SHR_W(a, b) CHOICE(shrw ARG2(a,b), shrw ARG2(a,b), _WTOG shr ARG2(b,a))
+#define SHR_B(a, b) CHOICE(shrb ARG2(a,b), shrb ARG2(a,b), shrb ARG2(b,a))
+#define SHRD_L(a,b,c) CHOICE(shrdl ARG3(a,b,c), shrdl ARG3(a,b,c), _LTOG shrd ARG3(c,b,a))
+#define SHRD2_L(a,b) CHOICE(shrdl ARG2(a,b), shrdl ARG3(CL,a,b), _LTOG shrd ARG3(b,a,CL))
+#define SHRD_W(a,b,c) CHOICE(shrdw ARG3(a,b,c), shrdw ARG3(a,b,c), _WTOG shrd ARG3(c,b,a))
+#define SHRD2_W(a,b) CHOICE(shrdw ARG2(a,b), shrdw ARG3(CL,a,b), _WTOG shrd ARG3(b,a,CL))
+#define SLDT(a) CHOICE(sldt a, sldt a, sldt a)
+#define SMSW(a) CHOICE(smsw a, smsw a, smsw a)
+#define STC CHOICE(stc, stc, stc)
+#define STD CHOICE(std, std, std)
+#define STI CHOICE(sti, sti, sti)
+#define STOS_L CHOICE(stosl, stosl, _LTOG stos)
+#define STOS_W CHOICE(stosw, stosw, _WTOG stos)
+#define STOS_B CHOICE(stosb, stosb, stosb)
+#define STR(a) CHOICE(str a, str a, str a)
+#define SUB_L(a, b) CHOICE(subl ARG2(a,b), subl ARG2(a,b), _LTOG sub ARG2(b,a))
+#define SUB_W(a, b) CHOICE(subw ARG2(a,b), subw ARG2(a,b), _WTOG sub ARG2(b,a))
+#define SUB_B(a, b) CHOICE(subb ARG2(a,b), subb ARG2(a,b), subb ARG2(b,a))
+#define TEST_L(a, b) CHOICE(testl ARG2(a,b), testl ARG2(a,b), _LTOG test ARG2(b,a))
+#define TEST_W(a, b) CHOICE(testw ARG2(a,b), testw ARG2(a,b), _WTOG test ARG2(b,a))
+#define TEST_B(a, b) CHOICE(testb ARG2(a,b), testb ARG2(a,b), testb ARG2(b,a))
+#define VERR(a) CHOICE(verr a, verr a, verr a)
+#define VERW(a) CHOICE(verw a, verw a, verw a)
+#define WAIT CHOICE(wait, wait, wait)
+#define XCHG_L(a, b) CHOICE(xchgl ARG2(a,b), xchgl ARG2(a,b), _LTOG xchg ARG2(b,a))
+#define XCHG_W(a, b) CHOICE(xchgw ARG2(a,b), xchgw ARG2(a,b), _WTOG xchg ARG2(b,a))
+#define XCHG_B(a, b) CHOICE(xchgb ARG2(a,b), xchgb ARG2(a,b), xchgb ARG2(b,a))
+#define XLAT CHOICE(xlat, xlat, xlat)
+#define XOR_L(a, b) CHOICE(xorl ARG2(a,b), xorl ARG2(a,b), _LTOG xor ARG2(b,a))
+#define XOR_W(a, b) CHOICE(xorw ARG2(a,b), xorw ARG2(a,b), _WTOG xor ARG2(b,a))
+#define XOR_B(a, b) CHOICE(xorb ARG2(a,b), xorb ARG2(a,b), xorb ARG2(b,a))
+
+
+/* Floating Point Instructions */
+#define F2XM1 CHOICE(f2xm1, f2xm1, f2xm1)
+#define FABS CHOICE(fabs, fabs, fabs)
+#define FADD_D(a) CHOICE(faddl a, faddl a, faddd a)
+#define FADD_S(a) CHOICE(fadds a, fadds a, fadds a)
+#define FADD2(a, b) CHOICE(fadd ARG2(a,b), fadd ARG2(a,b), fadd ARG2(b,a))
+#define FADDP(a, b) CHOICE(faddp ARG2(a,b), faddp ARG2(a,b), faddp ARG2(b,a))
+#define FIADD_L(a) CHOICE(fiaddl a, fiaddl a, fiaddl a)
+#define FIADD_W(a) CHOICE(fiadd a, fiadds a, fiadds a)
+#define FBLD(a) CHOICE(fbld a, fbld a, fbld a)
+#define FBSTP(a) CHOICE(fbstp a, fbstp a, fbstp a)
+#define FCHS CHOICE(fchs, fchs, fchs)
+#define FCLEX CHOICE(fclex, wait; fnclex, wait; fclex)
+#define FNCLEX CHOICE(fnclex, fnclex, fclex)
+#define FCOM(a) CHOICE(fcom a, fcom a, fcom a)
+#define FCOM_D(a) CHOICE(fcoml a, fcoml a, fcomd a)
+#define FCOM_S(a) CHOICE(fcoms a, fcoms a, fcoms a)
+#define FCOMP(a) CHOICE(fcomp a, fcomp a, fcomp a)
+#define FCOMP_D(a) CHOICE(fcompl a, fcompl a, fcompd a)
+#define FCOMP_S(a) CHOICE(fcomps a, fcomps a, fcomps a)
+#define FCOMPP CHOICE(fcompp, fcompp, fcompp)
+#define FCOS CHOICE(fcos, fcos, fcos)
+#define FDECSTP CHOICE(fdecstp, fdecstp, fdecstp)
+#define FDIV_D(a) CHOICE(fdivl a, fdivl a, fdivd a)
+#define FDIV_S(a) CHOICE(fdivs a, fdivs a, fdivs a)
+#define FDIV2(a, b) CHOICE(fdiv ARG2(a,b), fdiv ARG2(a,b), fdiv ARG2(b,a))
+#define FDIVP(a, b) CHOICE(fdivp ARG2(a,b), fdivp ARG2(a,b), fdivp ARG2(b,a))
+#define FIDIV_L(a) CHOICE(fidivl a, fidivl a, fidivl a)
+#define FIDIV_W(a) CHOICE(fidiv a, fidivs a, fidivs a)
+#define FDIVR_D(a) CHOICE(fdivrl a, fdivrl a, fdivrd a)
+#define FDIVR_S(a) CHOICE(fdivrs a, fdivrs a, fdivrs a)
+#define FDIVR2(a, b) CHOICE(fdivr ARG2(a,b), fdivr ARG2(a,b), fdivr ARG2(b,a))
+#define FDIVRP(a, b) CHOICE(fdivrp ARG2(a,b), fdivrp ARG2(a,b), fdivrp ARG2(b,a))
+#define FIDIVR_L(a) CHOICE(fidivrl a, fidivrl a, fidivrl a)
+#define FIDIVR_W(a) CHOICE(fidivr a, fidivrs a, fidivrs a)
+#define FFREE(a) CHOICE(ffree a, ffree a, ffree a)
+#define FICOM_L(a) CHOICE(ficoml a, ficoml a, ficoml a)
+#define FICOM_W(a) CHOICE(ficom a, ficoms a, ficoms a)
+#define FICOMP_L(a) CHOICE(ficompl a, ficompl a, ficompl a)
+#define FICOMP_W(a) CHOICE(ficomp a, ficomps a, ficomps a)
+#define FILD_Q(a) CHOICE(fildll a, fildq a, fildq a)
+#define FILD_L(a) CHOICE(fildl a, fildl a, fildl a)
+#define FILD_W(a) CHOICE(fild a, filds a, filds a)
+#define FINCSTP CHOICE(fincstp, fincstp, fincstp)
+#define FINIT CHOICE(finit, wait; fninit, wait; finit)
+#define FNINIT CHOICE(fninit, fninit, finit)
+#define FIST_L(a) CHOICE(fistl a, fistl a, fistl a)
+#define FIST_W(a) CHOICE(fist a, fists a, fists a)
+#define FISTP_Q(a) CHOICE(fistpll a, fistpq a, fistpq a)
+#define FISTP_L(a) CHOICE(fistpl a, fistpl a, fistpl a)
+#define FISTP_W(a) CHOICE(fistp a, fistps a, fistps a)
+#define FLD_X(a) CHOICE(fldt a, fldt a, fldx a) /* 80 bit data type! */
+#define FLD_D(a) CHOICE(fldl a, fldl a, fldd a)
+#define FLD_S(a) CHOICE(flds a, flds a, flds a)
+#define FLD1 CHOICE(fld1, fld1, fld1)
+#define FLDL2T CHOICE(fldl2t, fldl2t, fldl2t)
+#define FLDL2E CHOICE(fldl2e, fldl2e, fldl2e)
+#define FLDPI CHOICE(fldpi, fldpi, fldpi)
+#define FLDLG2 CHOICE(fldlg2, fldlg2, fldlg2)
+#define FLDLN2 CHOICE(fldln2, fldln2, fldln2)
+#define FLDZ CHOICE(fldz, fldz, fldz)
+#define FLDCW(a) CHOICE(fldcw a, fldcw a, fldcw a)
+#define FLDENV(a) CHOICE(fldenv a, fldenv a, fldenv a)
+#define FMUL_S(a) CHOICE(fmuls a, fmuls a, fmuls a)
+#define FMUL_D(a) CHOICE(fmull a, fmull a, fmuld a)
+#define FMUL2(a, b) CHOICE(fmul ARG2(a,b), fmul ARG2(a,b), fmul ARG2(b,a))
+#define FMULP(a, b) CHOICE(fmulp ARG2(a,b), fmulp ARG2(a,b), fmulp ARG2(b,a))
+#define FIMUL_L(a) CHOICE(fimull a, fimull a, fimull a)
+#define FIMUL_W(a) CHOICE(fimul a, fimuls a, fimuls a)
+#define FNOP CHOICE(fnop, fnop, fnop)
+#define FPATAN CHOICE(fpatan, fpatan, fpatan)
+#define FPREM CHOICE(fprem, fprem, fprem)
+#define FPREM1 CHOICE(fprem1, fprem1, fprem1)
+#define FPTAN CHOICE(fptan, fptan, fptan)
+#define FRNDINT CHOICE(frndint, frndint, frndint)
+#define FRSTOR(a) CHOICE(frstor a, frstor a, frstor a)
+#define FSAVE(a) CHOICE(fsave a, wait; fnsave a, wait; fsave a)
+#define FNSAVE(a) CHOICE(fnsave a, fnsave a, fsave a)
+#define FSCALE CHOICE(fscale, fscale, fscale)
+#define FSIN CHOICE(fsin, fsin, fsin)
+#define FSINCOS CHOICE(fsincos, fsincos, fsincos)
+#define FSQRT CHOICE(fsqrt, fsqrt, fsqrt)
+#define FST_D(a) CHOICE(fstl a, fstl a, fstd a)
+#define FST_S(a) CHOICE(fsts a, fsts a, fsts a)
+#define FSTP_X(a) CHOICE(fstpt a, fstpt a, fstpx a)
+#define FSTP_D(a) CHOICE(fstpl a, fstpl a, fstpd a)
+#define FSTP_S(a) CHOICE(fstps a, fstps a, fstps a)
+#define FSTP(a) CHOICE(fstp a, fstp a, fstp a)
+#define FSTCW(a) CHOICE(fstcw a, wait; fnstcw a, wait; fstcw a)
+#define FNSTCW(a) CHOICE(fnstcw a, fnstcw a, fstcw a)
+#define FSTENV(a) CHOICE(fstenv a, wait; fnstenv a, fstenv a)
+#define FNSTENV(a) CHOICE(fnstenv a, fnstenv a, fstenv a)
+#define FSTSW(a) CHOICE(fstsw a, wait; fnstsw a, wait; fstsw a)
+#define FNSTSW(a) CHOICE(fnstsw a, fnstsw a, fstsw a)
+#define FSUB_S(a) CHOICE(fsubs a, fsubs a, fsubs a)
+#define FSUB_D(a) CHOICE(fsubl a, fsubl a, fsubd a)
+#define FSUB2(a, b) CHOICE(fsub ARG2(a,b), fsub ARG2(a,b), fsub ARG2(b,a))
+#define FSUBP(a, b) CHOICE(fsubp ARG2(a,b), fsubp ARG2(a,b), fsubp ARG2(b,a))
+#define FISUB_L(a) CHOICE(fisubl a, fisubl a, fisubl a)
+#define FISUB_W(a) CHOICE(fisub a, fisubs a, fisubs a)
+#define FSUBR_S(a) CHOICE(fsubrs a, fsubrs a, fsubrs a)
+#define FSUBR_D(a) CHOICE(fsubrl a, fsubrl a, fsubrd a)
+#define FSUBR2(a, b) CHOICE(fsubr ARG2(a,b), fsubr ARG2(a,b), fsubr ARG2(b,a))
+#define FSUBRP(a, b) CHOICE(fsubrp ARG2(a,b), fsubrp ARG2(a,b), fsubrp ARG2(b,a))
+#define FISUBR_L(a) CHOICE(fisubrl a, fisubrl a, fisubrl a)
+#define FISUBR_W(a) CHOICE(fisubr a, fisubrs a, fisubrs a)
+#define FTST CHOICE(ftst, ftst, ftst)
+#define FUCOM(a) CHOICE(fucom a, fucom a, fucom a)
+#define FUCOMP(a) CHOICE(fucomp a, fucomp a, fucomp a)
+#define FUCOMPP CHOICE(fucompp, fucompp, fucompp)
+#define FWAIT CHOICE(wait, wait, wait)
+#define FXAM CHOICE(fxam, fxam, fxam)
+#define FXCH(a) CHOICE(fxch a, fxch a, fxch a)
+#define FXTRACT CHOICE(fxtract, fxtract, fxtract)
+#define FYL2X CHOICE(fyl2x, fyl2x, fyl2x)
+#define FYL2XP1 CHOICE(fyl2xp1, fyl2xp1, fyl2xp1)
+
+/* New instructions */
+#define CPUID CHOICE(D_BYTE ARG2(15, 162), cpuid, D_BYTE ARG2(15, 162))
+#define RDTSC CHOICE(D_BYTE ARG2(15, 49), rdtsc, D_BYTE ARG2(15, 49))
+
+#else /* NASM_ASSEMBLER || MASM_ASSEMBLER is defined */
+
+ /****************************************/
+ /* */
+ /* Intel style assemblers. */
+ /* (NASM and MASM) */
+ /* */
+ /****************************************/
+
+#define P_EAX EAX
+#define L_EAX EAX
+#define W_AX AX
+#define B_AH AH
+#define B_AL AL
+
+#define P_EBX EBX
+#define L_EBX EBX
+#define W_BX BX
+#define B_BH BH
+#define B_BL BL
+
+#define P_ECX ECX
+#define L_ECX ECX
+#define W_CX CX
+#define B_CH CH
+#define B_CL CL
+
+#define P_EDX EDX
+#define L_EDX EDX
+#define W_DX DX
+#define B_DH DH
+#define B_DL DL
+
+#define P_EBP EBP
+#define L_EBP EBP
+#define W_BP BP
+
+#define P_ESI ESI
+#define L_ESI ESI
+#define W_SI SI
+
+#define P_EDI EDI
+#define L_EDI EDI
+#define W_DI DI
+
+#define P_ESP ESP
+#define L_ESP ESP
+#define W_SP SP
+
+#define W_CS CS
+#define W_SS SS
+#define W_DS DS
+#define W_ES ES
+#define W_FS FS
+#define W_GS GS
+
+#define X_ST ST
+#define D_ST ST
+#define L_ST ST
+
+#define P_MM0 mm0
+#define P_MM1 mm1
+#define P_MM2 mm2
+#define P_MM3 mm3
+#define P_MM4 mm4
+#define P_MM5 mm5
+#define P_MM6 mm6
+#define P_MM7 mm7
+
+#define P_XMM0 xmm0
+#define P_XMM1 xmm1
+#define P_XMM2 xmm2
+#define P_XMM3 xmm3
+#define P_XMM4 xmm4
+#define P_XMM5 xmm5
+#define P_XMM6 xmm6
+#define P_XMM7 xmm7
+
+#if defined(NASM_ASSEMBLER)
+
+#define ST(n) st ## n
+
+#define TBYTE_PTR tword
+#define QWORD_PTR qword
+#define DWORD_PTR dword
+#define WORD_PTR word
+#define BYTE_PTR byte
+
+#define OFFSET
+
+#define GLOBL GLOBAL
+#define ALIGNTEXT32 ALIGN 32
+#define ALIGNTEXT16 ALIGN 16
+#define ALIGNTEXT8 ALIGN 8
+#define ALIGNTEXT4 ALIGN 4
+#define ALIGNTEXT2 ALIGN 2
+#define ALIGNTEXT32ifNOP ALIGN 32
+#define ALIGNTEXT16ifNOP ALIGN 16
+#define ALIGNTEXT8ifNOP ALIGN 8
+#define ALIGNTEXT4ifNOP ALIGN 4
+#define ALIGNDATA32 ALIGN 32
+#define ALIGNDATA16 ALIGN 16
+#define ALIGNDATA8 ALIGN 8
+#define ALIGNDATA4 ALIGN 4
+#define ALIGNDATA2 ALIGN 2
+#define FILE(s)
+#define STRING(s) db s
+#define D_LONG dd
+#define D_WORD dw
+#define D_BYTE db
+/* #define SPACE */
+/* #define COMM */
+#define SEG_DATA SECTION .data
+#define SEG_TEXT SECTION .text
+#define SEG_BSS SECTION .bss
+
+#define D_SPACE(n) db n REP 0
+
+#define AS_BEGIN
+
+#define NEAR near /* Jcc's should be handled better than this... */
+
+#else /* MASM */
+
+#define TBYTE_PTR tbyte ptr
+#define QWORD_PTR qword ptr
+#define DWORD_PTR dword ptr
+#define WORD_PTR word ptr
+#define BYTE_PTR byte ptr
+
+#define OFFSET offset
+
+#define GLOBL GLOBAL
+#define ALIGNTEXT32 ALIGN 32
+#define ALIGNTEXT16 ALIGN 16
+#define ALIGNTEXT8 ALIGN 8
+#define ALIGNTEXT4 ALIGN 4
+#define ALIGNTEXT2 ALIGN 2
+#define ALIGNTEXT32ifNOP ALIGN 32
+#define ALIGNTEXT16ifNOP ALIGN 16
+#define ALIGNTEXT8ifNOP ALIGN 8
+#define ALIGNTEXT4ifNOP ALIGN 4
+#define ALIGNDATA32 ALIGN 32
+#define ALIGNDATA16 ALIGN 16
+#define ALIGNDATA8 ALIGN 8
+#define ALIGNDATA4 ALIGN 4
+#define ALIGNDATA2 ALIGN 2
+#define FILE(s)
+#define STRING(s) db s
+#define D_LONG dd
+#define D_WORD dw
+#define D_BYTE db
+/* #define SPACE */
+/* #define COMM */
+#define SEG_DATA .DATA
+#define SEG_TEXT .CODE
+#define SEG_BSS .DATA
+
+#define D_SPACE(n) db n REP 0
+
+#define AS_BEGIN
+
+#define NEAR
+
+#endif
+
+#if defined(Lynx) || (defined(SYSV) || defined(SVR4)) \
+|| (defined(linux) || defined(__OS2ELF__)) && defined(__ELF__)
+#define GLNAME(a) a
+#else
+#define GLNAME(a) _ ## a
+#endif
+
+/*
+ * Addressing Modes
+ */
+
+/* Immediate Mode */
+#define P_ADDR(a) OFFSET a
+#define X_ADDR(a) OFFSET a
+#define D_ADDR(a) OFFSET a
+#define L_ADDR(a) OFFSET a
+#define W_ADDR(a) OFFSET a
+#define B_ADDR(a) OFFSET a
+
+#define P_CONST(a) a
+#define X_CONST(a) a
+#define D_CONST(a) a
+#define L_CONST(a) a
+#define W_CONST(a) a
+#define B_CONST(a) a
+
+/* Indirect Mode */
+#define P_CONTENT(a) a
+#define X_CONTENT(a) TBYTE_PTR a
+#define D_CONTENT(a) QWORD_PTR a
+#define L_CONTENT(a) DWORD_PTR a
+#define W_CONTENT(a) WORD_PTR a
+#define B_CONTENT(a) BYTE_PTR a
+
+/* Register a indirect */
+#define P_REGIND(a) [a]
+#define X_REGIND(a) TBYTE_PTR [a]
+#define D_REGIND(a) QWORD_PTR [a]
+#define L_REGIND(a) DWORD_PTR [a]
+#define W_REGIND(a) WORD_PTR [a]
+#define B_REGIND(a) BYTE_PTR [a]
+
+/* Register b indirect plus displacement a */
+#define P_REGOFF(a, b) [a + b]
+#define X_REGOFF(a, b) TBYTE_PTR [a + b]
+#define D_REGOFF(a, b) QWORD_PTR [a + b]
+#define L_REGOFF(a, b) DWORD_PTR [a + b]
+#define W_REGOFF(a, b) WORD_PTR [a + b]
+#define B_REGOFF(a, b) BYTE_PTR [a + b]
+
+/* Reg indirect Base + Index + Displacement - this is mainly for 16-bit mode
+ * which has no scaling
+ */
+#define P_REGBID(b, i, d) [b + i + d]
+#define X_REGBID(b, i, d) TBYTE_PTR [b + i + d]
+#define D_REGBID(b, i, d) QWORD_PTR [b + i + d]
+#define L_REGBID(b, i, d) DWORD_PTR [b + i + d]
+#define W_REGBID(b, i, d) WORD_PTR [b + i + d]
+#define B_REGBID(b, i, d) BYTE_PTR [b + i + d]
+
+/* Reg indirect Base + (Index * Scale) + Displacement */
+#define P_REGBISD(b, i, s, d) [b + i * s + d]
+#define X_REGBISD(b, i, s, d) TBYTE_PTR [b + i * s + d]
+#define D_REGBISD(b, i, s, d) QWORD_PTR [b + i * s + d]
+#define L_REGBISD(b, i, s, d) DWORD_PTR [b + i * s + d]
+#define W_REGBISD(b, i, s, d) WORD_PTR [b + i * s + d]
+#define B_REGBISD(b, i, s, d) BYTE_PTR [b + i * s + d]
+
+/* Displaced Scaled Index: */
+#define P_REGDIS(d, i, s) [i * s + d]
+#define X_REGDIS(d, i, s) TBYTE_PTR [i * s + d]
+#define D_REGDIS(d, i, s) QWORD_PTR [i * s + d]
+#define L_REGDIS(d, i, s) DWORD_PTR [i * s + d]
+#define W_REGDIS(d, i, s) WORD_PTR [i * s + d]
+#define B_REGDIS(d, i, s) BYTE_PTR [i * s + d]
+
+/* Indexed Base: */
+#define P_REGBI(b, i) [b + i]
+#define X_REGBI(b, i) TBYTE_PTR [b + i]
+#define D_REGBI(b, i) QWORD_PTR [b + i]
+#define L_REGBI(b, i) DWORD_PTR [b + i]
+#define W_REGBI(b, i) WORD_PTR [b + i]
+#define B_REGBI(b, i) BYTE_PTR [b + i]
+
+/* Displaced Base: */
+#define P_REGDB(d, b) [b + d]
+#define X_REGDB(d, b) TBYTE_PTR [b + d]
+#define D_REGDB(d, b) QWORD_PTR [b + d]
+#define L_REGDB(d, b) DWORD_PTR [b + d]
+#define W_REGDB(d, b) WORD_PTR [b + d]
+#define B_REGDB(d, b) BYTE_PTR [b + d]
+
+/* Variable indirect: */
+#define VARINDIRECT(var) [var]
+
+/* Use register contents as jump/call target: */
+#define CODEPTR(reg) [reg]
+
+/*
+ * Redefine assembler commands
+ */
+
+#define P_(a) P_ ## a
+#define X_(a) X_ ## a
+#define D_(a) D_ ## a
+#define S_(a) L_ ## a
+#define L_(a) L_ ## a
+#define W_(a) W_ ## a
+#define B_(a) B_ ## a
+
+#define AAA aaa
+#define AAD aad
+#define AAM aam
+#define AAS aas
+#define ADC_L(a, b) adc L_(b), L_(a)
+#define ADC_W(a, b) adc W_(b), W_(a)
+#define ADC_B(a, b) adc B_(b), B_(a)
+#define ADD_L(a, b) add L_(b), L_(a)
+#define ADD_W(a, b) add W_(b), W_(a)
+#define ADD_B(a, b) add B_(b), B_(a)
+#define AND_L(a, b) and L_(b), L_(a)
+#define AND_W(a, b) and W_(b), W_(a)
+#define AND_B(a, b) and B_(b), B_(a)
+#define ARPL(a,b) arpl W_(b), a
+#define BOUND_L(a, b) bound L_(b), L_(a)
+#define BOUND_W(a, b) bound W_(b), W_(a)
+#define BSF_L(a, b) bsf L_(b), L_(a)
+#define BSF_W(a, b) bsf W_(b), W_(a)
+#define BSR_L(a, b) bsr L_(b), L_(a)
+#define BSR_W(a, b) bsr W_(b), W_(a)
+#define BT_L(a, b) bt L_(b), L_(a)
+#define BT_W(a, b) bt W_(b), W_(a)
+#define BTC_L(a, b) btc L_(b), L_(a)
+#define BTC_W(a, b) btc W_(b), W_(a)
+#define BTR_L(a, b) btr L_(b), L_(a)
+#define BTR_W(a, b) btr W_(b), W_(a)
+#define BTS_L(a, b) bts L_(b), L_(a)
+#define BTS_W(a, b) bts W_(b), W_(a)
+#define CALL(a) call a
+#define CALLF(s,a) call far s:a
+#define CBW cbw
+#define CWDE cwde
+#define CLC clc
+#define CLD cld
+#define CLI cli
+#define CLTS clts
+#define CMC cmc
+#define CMP_L(a, b) cmp L_(b), L_(a)
+#define CMP_W(a, b) cmp W_(b), W_(a)
+#define CMP_B(a, b) cmp B_(b), B_(a)
+#define CMPS_L cmpsd
+#define CMPS_W cmpsw
+#define CMPS_B cmpsb
+#define CWD cwd
+#define CDQ cdq
+#define DAA daa
+#define DAS das
+#define DEC_L(a) dec L_(a)
+#define DEC_W(a) dec W_(a)
+#define DEC_B(a) dec B_(a)
+#define DIV_L(a) div L_(a)
+#define DIV_W(a) div W_(a)
+#define DIV_B(a) div B_(a)
+#define ENTER(a,b) enter b, a
+#define HLT hlt
+#define IDIV_L(a) idiv L_(a)
+#define IDIV_W(a) idiv W_(a)
+#define IDIV_B(a) idiv B_(a)
+#define IMUL_L(a, b) imul L_(b), L_(a)
+#define IMUL_W(a, b) imul W_(b), W_(a)
+#define IMUL_B(a) imul B_(a)
+#define IN_L in EAX, DX
+#define IN_W in AX, DX
+#define IN_B in AL, DX
+#define IN1_L(a) in1 L_(a)
+#define IN1_W(a) in1 W_(a)
+#define IN1_B(a) in1 B_(a)
+#define INC_L(a) inc L_(a)
+#define INC_W(a) inc W_(a)
+#define INC_B(a) inc B_(a)
+#define INS_L ins
+#define INS_W ins
+#define INS_B ins
+#define INT(a) int B_(a)
+#define INT3 int3
+#define INTO into
+#define IRET iret
+#define IRETD iretd
+#define JA(a) ja NEAR a
+#define JAE(a) jae NEAR a
+#define JB(a) jb NEAR a
+#define JBE(a) jbe NEAR a
+#define JC(a) jc NEAR a
+#define JE(a) je NEAR a
+#define JG(a) jg NEAR a
+#define JGE(a) jge NEAR a
+#define JL(a) jl NEAR a
+#define JLE(a) jle NEAR a
+#define JNA(a) jna NEAR a
+#define JNAE(a) jnae NEAR a
+#define JNB(a) jnb NEAR a
+#define JNBE(a) jnbe NEAR a
+#define JNC(a) jnc NEAR a
+#define JNE(a) jne NEAR a
+#define JNG(a) jng NEAR a
+#define JNGE(a) jnge NEAR a
+#define JNL(a) jnl NEAR a
+#define JNLE(a) jnle NEAR a
+#define JNO(a) jno NEAR a
+#define JNP(a) jnp NEAR a
+#define JNS(a) jns NEAR a
+#define JNZ(a) jnz NEAR a
+#define JO(a) jo NEAR a
+#define JP(a) jp NEAR a
+#define JPE(a) jpe NEAR a
+#define JPO(a) jpo NEAR a
+#define JS(a) js NEAR a
+#define JZ(a) jz NEAR a
+#define JMP(a) jmp a
+#define JMPF(s,a) jmpf
+#define LAHF lahf
+#define LAR(a, b) lar b, a
+#define LEA_L(a, b) lea P_(b), P_(a)
+#define LEA_W(a, b) lea P_(b), P_(a)
+#define LEAVE leave
+#define LGDT(a) lgdt a
+#define LIDT(a) lidt a
+#define LDS(a, b) lds b, a
+#define LES(a, b) les b, a
+#define LFS(a, b) lfs b, a
+#define LGS(a, b) lgs b, a
+#define LSS(a, b) lss b, a
+#define LLDT(a) lldt a
+#define LMSW(a) lmsw a
+#define LOCK lock
+#define LODS_L lodsd
+#define LODS_W lodsw
+#define LODS_B lodsb
+#define LOOP(a) loop a
+#define LOOPE(a) loope a
+#define LOOPZ(a) loopz a
+#define LOOPNE(a) loopne a
+#define LOOPNZ(a) loopnz a
+#define LSL(a, b) lsl b, a
+#define LTR(a) ltr a
+#define MOV_SR(a, b) mov S_(b), S_(a)
+#define MOV_L(a, b) mov L_(b), L_(a)
+#define MOV_W(a, b) mov W_(b), W_(a)
+#define MOV_B(a, b) mov B_(b), B_(a)
+#define MOVS_L movsd
+#define MOVS_W movsw
+#define MOVS_B movsb
+#define MOVSX_BL(a, b) movsx B_(b), B_(a)
+#define MOVSX_BW(a, b) movsx B_(b), B_(a)
+#define MOVSX_WL(a, b) movsx W_(b), W_(a)
+#define MOVZX_BL(a, b) movzx B_(b), B_(a)
+#define MOVZX_BW(a, b) movzx B_(b), B_(a)
+#define MOVZX_WL(a, b) movzx W_(b), W_(a)
+#define MUL_L(a) mul L_(a)
+#define MUL_W(a) mul W_(a)
+#define MUL_B(a) mul B_(a)
+#define NEG_L(a) neg L_(a)
+#define NEG_W(a) neg W_(a)
+#define NEG_B(a) neg B_(a)
+#define NOP nop
+#define NOT_L(a) not L_(a)
+#define NOT_W(a) not W_(a)
+#define NOT_B(a) not B_(a)
+#define OR_L(a,b) or L_(b), L_(a)
+#define OR_W(a,b) or W_(b), W_(a)
+#define OR_B(a,b) or B_(b), B_(a)
+#define OUT_L out DX, EAX
+#define OUT_W out DX, AX
+#define OUT_B out DX, AL
+#define OUT1_L(a) out1 L_(a)
+#define OUT1_W(a) out1 W_(a)
+#define OUT1_B(a) out1 B_(a)
+#define OUTS_L outsd
+#define OUTS_W outsw
+#define OUTS_B outsb
+#define POP_SR(a) pop S_(a)
+#define POP_L(a) pop L_(a)
+#define POP_W(a) pop W_(a)
+#define POPA_L popad
+#define POPA_W popa
+#define POPF_L popfd
+#define POPF_W popf
+#define PUSH_SR(a) push S_(a)
+#define PUSH_L(a) push L_(a)
+#define PUSH_W(a) push W_(a)
+#define PUSH_B(a) push B_(a)
+#define PUSHA_L pushad
+#define PUSHA_W pusha
+#define PUSHF_L pushfd
+#define PUSHF_W pushf
+#define RCL_L(a, b) rcl L_(b), L_(a)
+#define RCL_W(a, b) rcl W_(b), W_(a)
+#define RCL_B(a, b) rcl B_(b), B_(a)
+#define RCR_L(a, b) rcr L_(b), L_(a)
+#define RCR_W(a, b) rcr W_(b), W_(a)
+#define RCR_B(a, b) rcr B_(b), B_(a)
+#define ROL_L(a, b) rol L_(b), L_(a)
+#define ROL_W(a, b) rol W_(b), W_(a)
+#define ROL_B(a, b) rol B_(b), B_(a)
+#define ROR_L(a, b) ror L_(b), L_(a)
+#define ROR_W(a, b) ror W_(b), W_(a)
+#define ROR_B(a, b) ror B_(b), B_(a)
+#define REP rep
+#define REPE repe
+#define REPNE repne
+#define REPNZ REPNE
+#define REPZ REPE
+#define RET ret
+#define SAHF sahf
+#define SAL_L(a, b) sal L_(b), L_(a)
+#define SAL_W(a, b) sal W_(b), W_(a)
+#define SAL_B(a, b) sal B_(b), B_(a)
+#define SAR_L(a, b) sar L_(b), L_(a)
+#define SAR_W(a, b) sar W_(b), W_(a)
+#define SAR_B(a, b) sar B_(b), B_(a)
+#define SBB_L(a, b) sbb L_(b), L_(a)
+#define SBB_W(a, b) sbb W_(b), W_(a)
+#define SBB_B(a, b) sbb B_(b), B_(a)
+#define SCAS_L scas
+#define SCAS_W scas
+#define SCAS_B scas
+#define SETA(a) seta a
+#define SETAE(a) setae a
+#define SETB(a) setb a
+#define SETBE(a) setbe a
+#define SETC(a) setc a
+#define SETE(a) sete a
+#define SETG(a) setg a
+#define SETGE(a) setge a
+#define SETL(a) setl a
+#define SETLE(a) setle a
+#define SETNA(a) setna a
+#define SETNAE(a) setnae a
+#define SETNB(a) setnb a
+#define SETNBE(a) setnbe a
+#define SETNC(a) setnc a
+#define SETNE(a) setne a
+#define SETNG(a) setng a
+#define SETNGE(a) setnge a
+#define SETNL(a) setnl a
+#define SETNLE(a) setnle a
+#define SETNO(a) setno a
+#define SETNP(a) setnp a
+#define SETNS(a) setns a
+#define SETNZ(a) setnz a
+#define SETO(a) seto a
+#define SETP(a) setp a
+#define SETPE(a) setpe a
+#define SETPO(a) setpo a
+#define SETS(a) sets a
+#define SETZ(a) setz a
+#define SGDT(a) sgdt a
+#define SIDT(a) sidt a
+#define SHL_L(a, b) shl L_(b), L_(a)
+#define SHL_W(a, b) shl W_(b), W_(a)
+#define SHL_B(a, b) shl B_(b), B_(a)
+#define SHLD_L(a,b,c) shld
+#define SHLD2_L(a,b) shld L_(b), L_(a)
+#define SHLD_W(a,b,c) shld
+#define SHLD2_W(a,b) shld W_(b), W_(a)
+#define SHR_L(a, b) shr L_(b), L_(a)
+#define SHR_W(a, b) shr W_(b), W_(a)
+#define SHR_B(a, b) shr B_(b), B_(a)
+#define SHRD_L(a,b,c) shrd
+#define SHRD2_L(a,b) shrd L_(b), L_(a)
+#define SHRD_W(a,b,c) shrd
+#define SHRD2_W(a,b) shrd W_(b), W_(a)
+#define SLDT(a) sldt a
+#define SMSW(a) smsw a
+#define STC stc
+#define STD std
+#define STI sti
+#define STOS_L stos
+#define STOS_W stos
+#define STOS_B stos
+#define STR(a) str a
+#define SUB_L(a, b) sub L_(b), L_(a)
+#define SUB_W(a, b) sub W_(b), W_(a)
+#define SUB_B(a, b) sub B_(b), B_(a)
+#define TEST_L(a, b) test L_(b), L_(a)
+#define TEST_W(a, b) test W_(b), W_(a)
+#define TEST_B(a, b) test B_(b), B_(a)
+#define VERR(a) verr a
+#define VERW(a) verw a
+#define WAIT wait
+#define XCHG_L(a, b) xchg L_(b), L_(a)
+#define XCHG_W(a, b) xchg W_(b), W_(a)
+#define XCHG_B(a, b) xchg B_(b), B_(a)
+#define XLAT xlat
+#define XOR_L(a, b) xor L_(b), L_(a)
+#define XOR_W(a, b) xor W_(b), W_(a)
+#define XOR_B(a, b) xor B_(b), B_(a)
+#define F2XM1 f2xm1
+#define FABS fabs
+#define FADD_D(a) fadd D_(a)
+#define FADD_S(a) fadd S_(a)
+#define FADD2(a, b) fadd b, a
+#define FADDP(a, b) faddp b, a
+#define FIADD_L(a) fiadd L_(a)
+#define FIADD_W(a) fiadd W_(a)
+#define FBLD(a) fbld a
+#define FBSTP(a) fbstp a
+#define FCHS fchs
+#define FCLEX fclex
+#define FNCLEX fnclex
+#define FCOM(a) fcom a
+#define FCOM_D(a) fcom D_(a)
+#define FCOM_S(a) fcom S_(a)
+#define FCOMP(a) fcomp a
+#define FCOMP_D(a) fcomp D_(a)
+#define FCOMP_S(a) fcomp S_(a)
+#define FCOMPP fcompp
+#define FCOS fcos
+#define FDECSTP fdecstp
+#define FDIV_D(a) fdiv D_(a)
+#define FDIV_S(a) fdiv S_(a)
+#define FDIV2(a, b) fdiv b, a
+#define FDIVP(a, b) fdivp b, a
+#define FIDIV_L(a) fidiv L_(a)
+#define FIDIV_W(a) fidiv W_(a)
+#define FDIVR_D(a) fdivr D_(a)
+#define FDIVR_S(a) fdivr S_(a)
+#define FDIVR2(a, b) fdivr b, a
+#define FDIVRP(a, b) fdivrp b, a
+#define FIDIVR_L(a) fidivr L_(a)
+#define FIDIVR_W(a) fidivr W_(a)
+#define FFREE(a) ffree a
+#define FICOM_L(a) ficom L_(a)
+#define FICOM_W(a) ficom W_(a)
+#define FICOMP_L(a) ficomp L_(a)
+#define FICOMP_W(a) ficomp W_(a)
+#define FILD_Q(a) fild D_(a)
+#define FILD_L(a) fild L_(a)
+#define FILD_W(a) fild W_(a)
+#define FINCSTP fincstp
+#define FINIT finit
+#define FNINIT fninit
+#define FIST_L(a) fist L_(a)
+#define FIST_W(a) fist W_(a)
+#define FISTP_Q(a) fistp D_(a)
+#define FISTP_L(a) fistp L_(a)
+#define FISTP_W(a) fistp W_(a)
+#define FLD_X(a) fld X_(a)
+#define FLD_D(a) fld D_(a)
+#define FLD_S(a) fld S_(a)
+#define FLD1 fld1
+#define FLDL2T fldl2t
+#define FLDL2E fldl2e
+#define FLDPI fldpi
+#define FLDLG2 fldlg2
+#define FLDLN2 fldln2
+#define FLDZ fldz
+#define FLDCW(a) fldcw a
+#define FLDENV(a) fldenv a
+#define FMUL_S(a) fmul S_(a)
+#define FMUL_D(a) fmul D_(a)
+#define FMUL2(a, b) fmul b, a
+#define FMULP(a, b) fmulp b, a
+#define FIMUL_L(a) fimul L_(a)
+#define FIMUL_W(a) fimul W_(a)
+#define FNOP fnop
+#define FPATAN fpatan
+#define FPREM fprem
+#define FPREM1 fprem1
+#define FPTAN fptan
+#define FRNDINT frndint
+#define FRSTOR(a) frstor a
+#define FSAVE(a) fsave a
+#define FNSAVE(a) fnsave a
+#define FSCALE fscale
+#define FSIN fsin
+#define FSINCOS fsincos
+#define FSQRT fsqrt
+#define FST_D(a) fst D_(a)
+#define FST_S(a) fst S_(a)
+#define FSTP_X(a) fstp X_(a)
+#define FSTP_D(a) fstp D_(a)
+#define FSTP_S(a) fstp S_(a)
+#define FSTP(a) fstp a
+#define FSTCW(a) fstcw a
+#define FNSTCW(a) fnstcw a
+#define FSTENV(a) fstenv a
+#define FNSTENV(a) fnstenv a
+#define FSTSW(a) fstsw a
+#define FNSTSW(a) fnstsw a
+#define FSUB_S(a) fsub S_(a)
+#define FSUB_D(a) fsub D_(a)
+#define FSUB2(a, b) fsub b, a
+#define FSUBP(a, b) fsubp b, a
+#define FISUB_L(a) fisub L_(a)
+#define FISUB_W(a) fisub W_(a)
+#define FSUBR_S(a) fsubr S_(a)
+#define FSUBR_D(a) fsubr D_(a)
+#define FSUBR2(a, b) fsubr b, a
+#define FSUBRP(a, b) fsubrp b, a
+#define FISUBR_L(a) fisubr L_(a)
+#define FISUBR_W(a) fisubr W_(a)
+#define FTST ftst
+#define FUCOM(a) fucom a
+#define FUCOMP(a) fucomp a
+#define FUCOMPP fucompp
+#define FWAIT fwait
+#define FXAM fxam
+#define FXCH(a) fxch a
+#define FXTRACT fxtract
+#define FYL2X fyl2x
+#define FYL2XP1 fyl2xp1
+
+/* New instructions */
+#define CPUID D_BYTE 15, 162
+#define RDTSC D_BYTE 15, 49
+
+#endif /* NASM_ASSEMBLER, MASM_ASSEMBLER */
+
+ /****************************************/
+ /* */
+ /* Extensions to x86 insn set - */
+ /* MMX, 3DNow! */
+ /* */
+ /****************************************/
+
+#if defined(NASM_ASSEMBLER) || defined(MASM_ASSEMBLER)
+#define P_ARG1(a) P_ ## a
+#define P_ARG2(a, b) P_ ## b, P_ ## a
+#define P_ARG3(a, b, c) P_ ## c, P_ ## b, P_ ## a
+#else
+#define P_ARG1(a) a
+#define P_ARG2(a, b) a, b
+#define P_ARG3(a, b) a, b, c
+#endif
+
+/* MMX */
+#define MOVD(a, b) movd P_ARG2(a, b)
+#define MOVQ(a, b) movq P_ARG2(a, b)
+
+#define PADDB(a, b) paddb P_ARG2(a, b)
+#define PADDW(a, b) paddw P_ARG2(a, b)
+#define PADDD(a, b) paddd P_ARG2(a, b)
+
+#define PADDSB(a, b) paddsb P_ARG2(a, b)
+#define PADDSW(a, b) paddsw P_ARG2(a, b)
+
+#define PADDUSB(a, b) paddusb P_ARG2(a, b)
+#define PADDUSW(a, b) paddusw P_ARG2(a, b)
+
+#define PSUBB(a, b) psubb P_ARG2(a, b)
+#define PSUBW(a, b) psubw P_ARG2(a, b)
+#define PSUBD(a, b) psubd P_ARG2(a, b)
+
+#define PSUBSB(a, b) psubsb P_ARG2(a, b)
+#define PSUBSW(a, b) psubsw P_ARG2(a, b)
+
+#define PSUBUSB(a, b) psubusb P_ARG2(a, b)
+#define PSUBUSW(a, b) psubusw P_ARG2(a, b)
+
+#define PCMPEQB(a, b) pcmpeqb P_ARG2(a, b)
+#define PCMPEQW(a, b) pcmpeqw P_ARG2(a, b)
+#define PCMPEQD(a, b) pcmpeqd P_ARG2(a, b)
+
+#define PCMPGTB(a, b) pcmpgtb P_ARG2(a, b)
+#define PCMPGTW(a, b) pcmpgtw P_ARG2(a, b)
+#define PCMPGTD(a, b) pcmpgtd P_ARG2(a, b)
+
+#define PMULHW(a, b) pmulhw P_ARG2(a, b)
+#define PMULLW(a, b) pmullw P_ARG2(a, b)
+
+#define PMADDWD(a, b) pmaddwd P_ARG2(a, b)
+
+#define PAND(a, b) pand P_ARG2(a, b)
+
+#define PANDN(a, b) pandn P_ARG2(a, b)
+
+#define POR(a, b) por P_ARG2(a, b)
+
+#define PXOR(a, b) pxor P_ARG2(a, b)
+
+#define PSRAW(a, b) psraw P_ARG2(a, b)
+#define PSRAD(a, b) psrad P_ARG2(a, b)
+
+#define PSRLW(a, b) psrlw P_ARG2(a, b)
+#define PSRLD(a, b) psrld P_ARG2(a, b)
+#define PSRLQ(a, b) psrlq P_ARG2(a, b)
+
+#define PSLLW(a, b) psllw P_ARG2(a, b)
+#define PSLLD(a, b) pslld P_ARG2(a, b)
+#define PSLLQ(a, b) psllq P_ARG2(a, b)
+
+#define PACKSSWB(a, b) packsswb P_ARG2(a, b)
+#define PACKSSDW(a, b) packssdw P_ARG2(a, b)
+#define PACKUSWB(a, b) packuswb P_ARG2(a, b)
+
+#define PUNPCKHBW(a, b) punpckhbw P_ARG2(a, b)
+#define PUNPCKHWD(a, b) punpckhwd P_ARG2(a, b)
+#define PUNPCKHDQ(a, b) punpckhdq P_ARG2(a, b)
+#define PUNPCKLBW(a, b) punpcklbw P_ARG2(a, b)
+#define PUNPCKLWD(a, b) punpcklwd P_ARG2(a, b)
+#define PUNPCKLDQ(a, b) punpckldq P_ARG2(a, b)
+
+#define EMMS emms
+
+/* AMD 3DNow! */
+#define PAVGUSB(a, b) pavgusb P_ARG2(a, b)
+#define PFADD(a, b) pfadd P_ARG2(a, b)
+#define PFSUB(a, b) pfsub P_ARG2(a, b)
+#define PFSUBR(a, b) pfsubr P_ARG2(a, b)
+#define PFACC(a, b) pfacc P_ARG2(a, b)
+#define PFCMPGE(a, b) pfcmpge P_ARG2(a, b)
+#define PFCMPGT(a, b) pfcmpgt P_ARG2(a, b)
+#define PFCMPEQ(a, b) pfcmpeq P_ARG2(a, b)
+#define PFMIN(a, b) pfmin P_ARG2(a, b)
+#define PFMAX(a, b) pfmax P_ARG2(a, b)
+#define PI2FD(a, b) pi2fd P_ARG2(a, b)
+#define PF2ID(a, b) pf2id P_ARG2(a, b)
+#define PFRCP(a, b) pfrcp P_ARG2(a, b)
+#define PFRSQRT(a, b) pfrsqrt P_ARG2(a, b)
+#define PFMUL(a, b) pfmul P_ARG2(a, b)
+#define PFRCPIT1(a, b) pfrcpit1 P_ARG2(a, b)
+#define PFRSQIT1(a, b) pfrsqit1 P_ARG2(a, b)
+#define PFRCPIT2(a, b) pfrcpit2 P_ARG2(a, b)
+#define PMULHRW(a, b) pmulhrw P_ARG2(a, b)
+
+#define FEMMS femms
+#define PREFETCH(a) prefetch P_ARG1(a)
+
+/* Intel SSE */
+#define ADDPS(a, b) addps P_ARG2(a, b)
+#define ADDSS(a, b) addss P_ARG2(a, b)
+#define ANDNPS(a, b) andnps P_ARG2(a, b)
+#define ANDPS(a, b) andps P_ARG2(a, b)
+/*
+ NASM only knows the pseudo ops for these.
+ #define CMPPS(a, b, c) cmpps P_ARG3(a, b, c)
+ #define CMPSS(a, b, c) cmpss P_ARG3(a, b, c)
+*/
+#define CMPEQPS(a, b) cmpeqps P_ARG3(a, b)
+#define CMPLTPS(a, b) cmpltps P_ARG3(a, b)
+#define CMPLEPS(a, b) cmpleps P_ARG3(a, b)
+#define CMPUNORDPS(a, b) cmpunordps P_ARG3(a, b)
+#define CMPNEQPS(a, b) cmpneqps P_ARG3(a, b)
+#define CMPNLTPS(a, b) cmpnltps P_ARG3(a, b)
+#define CMPNLEPS(a, b) cmpnleps P_ARG3(a, b)
+#define CMPORDPS(a, b) cmpordps P_ARG3(a, b)
+#define CMPEQSS(a, b) cmpeqss P_ARG3(a, b)
+#define CMPLTSS(a, b) cmpltss P_ARG3(a, b)
+#define CMPLESS(a, b) cmpless P_ARG3(a, b)
+#define CMPUNORDSS(a, b) cmpunordss P_ARG3(a, b)
+#define CMPNEQSS(a, b) cmpneqss P_ARG3(a, b)
+#define CMPNLTSS(a, b) cmpnltss P_ARG3(a, b)
+#define CMPNLESS(a, b) cmpnless P_ARG3(a, b)
+#define CMPORDSS(a, b) cmpordss P_ARG3(a, b)
+#define COMISS(a, b) comiss P_ARG2(a, b)
+#define CVTPI2PS(a, b) cvtpi2ps P_ARG2(a, b)
+#define CVTPS2PI(a, b) cvtps2pi P_ARG2(a, b)
+#define CVTSI2SS(a, b) cvtsi2ss P_ARG2(a, b)
+#define CVTSS2SI(a, b) cvtss2si P_ARG2(a, b)
+#define CVTTPS2PI(a, b) cvttps2pi P_ARG2(a, b)
+#define CVTTSS2SI(a, b) cvttss2si P_ARG2(a, b)
+#define DIVPS(a, b) divps P_ARG2(a, b)
+#define DIVSS(a, b) divss P_ARG2(a, b)
+#define FXRSTOR(a) fxrstor P_ARG1(a)
+#define FXSAVE(a) fxsave P_ARG1(a)
+#define LDMXCSR(a) ldmxcsr P_ARG1(a)
+#define MAXPS(a, b) maxps P_ARG2(a, b)
+#define MAXSS(a, b) maxss P_ARG2(a, b)
+#define MINPS(a, b) minps P_ARG2(a, b)
+#define MINSS(a, b) minss P_ARG2(a, b)
+#define MOVAPS(a, b) movaps P_ARG2(a, b)
+#define MOVHLPS(a, b) movhlps P_ARG2(a, b)
+#define MOVHPS(a, b) movhps P_ARG2(a, b)
+#define MOVLHPS(a, b) movlhps P_ARG2(a, b)
+#define MOVLPS(a, b) movlps P_ARG2(a, b)
+#define MOVMSKPS(a, b) movmskps P_ARG2(a, b)
+#define MOVSS(a, b) movss P_ARG2(a, b)
+#define MOVUPS(a, b) movups P_ARG2(a, b)
+#define MULPS(a, b) mulps P_ARG2(a, b)
+#define MULSS(a, b) mulss P_ARG2(a, b)
+#define ORPS(a, b) orps P_ARG2(a, b)
+#define RCPPS(a, b) rcpps P_ARG2(a, b)
+#define RCPSS(a, b) rcpss P_ARG2(a, b)
+#define RSQRTPS(a, b) rsqrtps P_ARG2(a, b)
+#define RSQRTSS(a, b) rsqrtss P_ARG2(a, b)
+#define SHUFPS(a, b, c) shufps P_ARG3(a, b, c)
+#define SQRTPS(a, b) sqrtps P_ARG2(a, b)
+#define SQRTSS(a, b) sqrtss P_ARG2(a, b)
+#define STMXCSR(a) stmxcsr P_ARG1(a)
+#define SUBPS(a, b) subps P_ARG2(a, b)
+#define UCOMISS(a, b) ucomiss P_ARG2(a, b)
+#define UNPCKHPS(a, b) unpckhps P_ARG2(a, b)
+#define UNPCKLPS(a, b) unpcklps P_ARG2(a, b)
+#define XORPS(a, b) xorps P_ARG2(a, b)
+
+
+#endif /* __ASSYNTAX_H__ */
diff --git a/src/mesa/x86/common_x86.c b/src/mesa/x86/common_x86.c
new file mode 100644
index 0000000000..7d30be94cf
--- /dev/null
+++ b/src/mesa/x86/common_x86.c
@@ -0,0 +1,77 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+/*
+ * Check CPU capabilities & initialize optimized funtions for this particular
+ * processor.
+ *
+ * Written by Holger Waechtler <holger@akaflieg.extern.tu-berlin.de>
+ */
+
+#include <stdlib.h>
+#include "common_x86asm.h"
+
+int gl_x86_cpu_features = 0;
+
+
+void gl_init_all_x86_asm (void)
+{
+#ifdef USE_X86_ASM
+ gl_x86_cpu_features = gl_identify_x86_cpu_features ();
+
+ if (gl_x86_cpu_features & GL_CPU_GenuineIntel) {
+ printf ("GenuineIntel cpu detected.\n");
+ }
+ gl_init_x86_asm_transforms ();
+
+
+#ifdef USE_MMX_ASM
+ if (gl_x86_cpu_features & GL_CPU_MMX) {
+ char *s = getenv( "MESA_NO_MMX" );
+ if (s == NULL) {
+ printf ("MMX cpu detected.\n");
+ } else {
+ gl_x86_cpu_features &= (!GL_CPU_MMX);
+ }
+ }
+#endif
+
+
+#ifdef USE_3DNOW_ASM
+ if (gl_x86_cpu_features & GL_CPU_3Dnow) {
+ char *s = getenv( "MESA_NO_3DNOW" );
+ if (s == NULL) {
+ printf ("3Dnow cpu detected.\n");
+ gl_init_3dnow_asm_transforms ();
+ } else {
+ gl_x86_cpu_features &= (!GL_CPU_3Dnow);
+ }
+ }
+#endif
+
+#endif
+}
+
diff --git a/src/mesa/x86/mmx.h b/src/mesa/x86/mmx.h
new file mode 100644
index 0000000000..c8c5eff302
--- /dev/null
+++ b/src/mesa/x86/mmx.h
@@ -0,0 +1,77 @@
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+
+
+
+
+#ifndef ASM_MMX_H
+#define ASM_MMX_H
+
+
+extern void
+gl_mmx_blend_transparency( GLcontext *ctx, GLuint n, const GLubyte mask[],
+ GLubyte rgba[][4], const GLubyte dest[][4] );
+
+
+void gl_mmx_set_blend_function( GLcontext *ctx )
+{
+ const GLenum eq = ctx->Color.BlendEquation;
+ const GLenum srcRGB = ctx->Color.BlendSrcRGB;
+ const GLenum dstRGB = ctx->Color.BlendDstRGB;
+ const GLenum srcA = ctx->Color.BlendSrcA;
+ const GLenum dstA = ctx->Color.BlendDstA;
+
+
+ if (srcRGB != srcA || dstRGB != dstA) {
+ ctx->Color.BlendFunc = blend_general;
+ }
+ else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_SRC_ALPHA
+ && dstRGB==GL_ONE_MINUS_SRC_ALPHA) {
+ ctx->Color.BlendFunc = gl_mmx_blend_transparency;
+ }
+ else if (eq==GL_FUNC_ADD_EXT && srcRGB==GL_ONE && dstRGB==GL_ONE) {
+ ctx->Color.BlendFunc = blend_add;
+ }
+ else if (((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_REVERSE_SUBTRACT_EXT)
+ && (srcRGB==GL_ZERO && dstRGB==GL_SRC_COLOR))
+ ||
+ ((eq==GL_FUNC_ADD_EXT || eq==GL_FUNC_SUBTRACT_EXT)
+ && (srcRGB==GL_DST_COLOR && dstRGB==GL_ZERO))) {
+ ctx->Color.BlendFunc = blend_modulate;
+ }
+ else if (eq==GL_MIN_EXT) {
+ ctx->Color.BlendFunc = blend_min;
+ }
+ else if (eq==GL_MAX_EXT) {
+ ctx->Color.BlendFunc = blend_max;
+ }
+ else {
+ ctx->Color.BlendFunc = blend_general;
+ }
+}
+
+
+#endif
diff --git a/src/mesa/x86/mmx_blend.S b/src/mesa/x86/mmx_blend.S
new file mode 100644
index 0000000000..7bd9ec3d24
--- /dev/null
+++ b/src/mesa/x86/mmx_blend.S
@@ -0,0 +1,363 @@
+#include "assyntax.h"
+
+
+#if !defined(NASM_ASSEMBLER) && !defined(MASM_ASSEMBLER)
+#define LLBL(a) .L ## a
+#else
+#define LLBL(a) a
+#endif
+
+
+SEG_TEXT
+
+
+ALIGNTEXT16
+GLOBL GLNAME(gl_mmx_blend_transparency)
+
+GLNAME( gl_mmx_blend_transparency ):
+ PUSH_L ( EBP )
+ MOV_L ( ESP, EBP )
+ SUB_L ( CONST(52), ESP )
+ PUSH_L ( EBX )
+ MOV_L ( CONST(16711680), REGOFF(-8, EBP) )
+ MOV_L ( CONST(16711680), REGOFF(-4, EBP) )
+ MOV_L ( CONST(0), REGOFF(-16, EBP) )
+ MOV_L ( CONST(-1), REGOFF(-12, EBP) )
+ MOV_L ( CONST(-1), REGOFF(-24, EBP) )
+ MOV_L ( CONST(0), REGOFF(-20, EBP) )
+ MOV_L ( REGOFF(24, EBP), EAX )
+ ADD_L ( CONST(4), EAX )
+ MOV_L ( EAX, EDX )
+ AND_L ( REGOFF(20, EBP), EDX )
+ MOV_L ( EDX, EAX )
+ AND_L ( CONST(4), EAX )
+ CMP_L ( CONST(8), EAX )
+ JNE ( LLBL(GMBT_2) )
+ MOV_L ( REGOFF(20, EBP), EAX )
+ ADD_L ( CONST(3), EAX )
+ XOR_L ( EDX, EDX )
+ MOV_B ( REGIND(EAX), DL )
+ MOV_L ( EDX, REGOFF(-32, EBP) )
+ MOV_L ( CONST(255), EAX )
+ MOV_L ( EAX, EBX )
+ SUB_L ( REGOFF(-32, EBP), EBX )
+ MOV_L ( EBX, REGOFF(-36, EBP) )
+ MOV_L ( REGOFF(20, EBP), EAX )
+ XOR_L ( EDX, EDX )
+ MOV_B ( REGIND(EAX), DL )
+ MOV_L ( EDX, EAX )
+ IMUL_L ( REGOFF(-32, EBP), EAX )
+ MOV_L ( REGOFF(24, EBP), EDX )
+ XOR_L ( ECX, ECX )
+ MOV_B ( REGIND(EDX), CL )
+ MOV_L ( ECX, EDX )
+ IMUL_L ( REGOFF(-36, EBP), EDX )
+ ADD_L ( EDX, EAX )
+ MOV_L ( EAX, EBX )
+ SAR_L ( CONST(8), EBX )
+ MOV_L ( EBX, REGOFF(-40, EBP) )
+ MOV_L ( REGOFF(20, EBP), EAX )
+ INC_L ( EAX )
+ XOR_L ( EDX, EDX )
+ MOV_B ( REGIND(EAX), DL )
+ MOV_L ( EDX, EAX )
+ IMUL_L ( REGOFF(-32, EBP), EAX )
+ MOV_L ( REGOFF(24, EBP), EDX )
+ INC_L ( EDX )
+ XOR_L ( ECX, ECX )
+ MOV_B ( REGIND(EDX), CL )
+ MOV_L ( ECX, EDX )
+ IMUL_L ( REGOFF(-36, EBP), EDX )
+ ADD_L ( EDX, EAX )
+ MOV_L ( EAX, EBX )
+ SAR_L ( CONST(8), EBX )
+ MOV_L ( EBX, REGOFF(-44, EBP) )
+ MOV_L ( REGOFF(20, EBP), EAX )
+ ADD_L ( CONST(2), EAX )
+ XOR_L ( EDX, EDX )
+ MOV_B ( REGIND(EAX), DL )
+ MOV_L ( EDX, EAX )
+ IMUL_L ( REGOFF(-32, EBP), EAX )
+ MOV_L ( REGOFF(24, EBP), EDX )
+ ADD_L ( CONST(2), EDX )
+ XOR_L ( ECX, ECX )
+ MOV_B ( REGIND(EDX), CL )
+ MOV_L ( ECX, EDX )
+ IMUL_L ( REGOFF(-36, EBP), EDX )
+ ADD_L ( EDX, EAX )
+ MOV_L ( EAX, EBX )
+ SAR_L ( CONST(8), EBX )
+ MOV_L ( EBX, REGOFF(-48, EBP) )
+ MOV_L ( REGOFF(20, EBP), EAX )
+ ADD_L ( CONST(3), EAX )
+ XOR_L ( EDX, EDX )
+ MOV_B ( REGIND(EAX), DL )
+ MOV_L ( EDX, EAX )
+ IMUL_L ( REGOFF(-32, EBP), EAX )
+ MOV_L ( REGOFF(24, EBP), EDX )
+ ADD_L ( CONST(3), EDX )
+ XOR_L ( ECX, ECX )
+ MOV_B ( REGIND(EDX), CL )
+ MOV_L ( ECX, EDX )
+ IMUL_L ( REGOFF(-36, EBP), EDX )
+ ADD_L ( EDX, EAX )
+ MOV_L ( EAX, EBX )
+ SAR_L ( CONST(8), EBX )
+ MOV_L ( EBX, REGOFF(-52, EBP) )
+ MOV_L ( REGOFF(20, EBP), EAX )
+ MOV_B ( REGOFF(-40, EBP), DL )
+ MOV_B ( DL, REGIND(EAX) )
+ MOV_L ( REGOFF(20, EBP), EAX )
+ INC_L ( EAX )
+ MOV_B ( REGOFF(-44, EBP), DL )
+ MOV_B ( DL, REGIND(EAX) )
+ MOV_L ( REGOFF(20, EBP), EAX )
+ ADD_L ( CONST(2), EAX )
+ MOV_B ( REGOFF(-48, EBP), DL )
+ MOV_B ( DL, REGIND(EAX) )
+ MOV_L ( REGOFF(20, EBP), EAX )
+ ADD_L ( CONST(3), EAX )
+ MOV_B ( REGOFF(-52, EBP), DL )
+ MOV_B ( DL, REGIND(EAX) )
+ INC_L ( REGOFF(16, EBP) )
+ ADD_L ( CONST(4), REGOFF(20, EBP) )
+ ADD_L ( CONST(4), REGOFF(24, EBP) )
+ DEC_L ( REGOFF(12, EBP) )
+LLBL( GMBT_2 ):
+
+ CMP_L ( CONST(0), REGOFF(12, EBP) )
+ JE ( LLBL(GMBT_3) )
+ MOV_L ( CONST(0), REGOFF(-28, EBP) )
+ALIGNTEXT4
+LLBL( GMBT_4 ):
+
+ MOV_L ( REGOFF(12, EBP), EDX )
+ MOV_L ( EDX, EAX )
+ SHR_L ( CONST(1), EAX )
+ CMP_L ( EAX, REGOFF(-28, EBP) )
+ JB ( LLBL(GMBT_7) )
+ JMP ( LLBL(GMBT_5) )
+ALIGNTEXT16
+LLBL( GMBT_7 ):
+
+ MOV_L ( REGOFF(-28, EBP), EAX )
+ LEA_L ( REGDIS(0,EAX,2), EDX )
+ MOV_L ( REGOFF(16, EBP), EAX )
+ CMP_B ( CONST(0), REGBI(EAX,EDX) )
+ JE ( LLBL(GMBT_6) )
+ MOV_L ( REGOFF(-28, EBP), EAX )
+ MOV_L ( EAX, EDX )
+ LEA_L ( REGDIS(0,EDX,8), ECX )
+ MOV_L ( ECX, EAX )
+ ADD_L ( REGOFF(20, EBP), EAX )
+ MOV_L ( REGOFF(-28, EBP), EDX )
+ MOV_L ( EDX, ECX )
+ LEA_L ( REGDIS(0,ECX,8), EDX )
+ MOV_L ( EDX, ECX )
+ ADD_L ( REGOFF(24, EBP), ECX )
+
+ MOVQ ( REGIND(EAX), MM4 )
+ PXOR ( MM5, MM5 )
+ MOVQ ( MM4, MM1 )
+ MOVQ ( REGIND(ECX), MM7 )
+ PUNPCKLBW ( MM5, MM1 )
+ MOVQ ( MM7, MM6 )
+ MOVQ ( MM1, MM0 )
+ PUNPCKLBW ( MM5, MM6 )
+ MOVQ ( MM1, MM2 )
+ PSRLQ ( CONST(48), MM0 )
+ PUNPCKHBW ( MM5, MM4 )
+ PACKSSDW ( MM0, MM0 )
+ MOVQ ( MM0, MM3 )
+ PUNPCKHBW ( MM5, MM7 )
+ PSLLQ ( CONST(16), MM3 )
+ POR ( REGOFF(-8, EBP), MM0 )
+ PUNPCKLWD ( MM6, MM1 )
+ PSUBW ( MM3, MM0 )
+ PUNPCKHWD ( MM6, MM2 )
+ MOVQ ( MM4, MM3 )
+ PSRLQ ( CONST(48), MM3 )
+ PACKSSDW ( MM3, MM3 )
+ MOVQ ( MM3, MM6 )
+ POR ( REGOFF(-8, EBP), MM3 )
+ PSLLQ ( CONST(16), MM6 )
+ PSUBW ( MM6, MM3 )
+ MOVQ ( MM4, MM5 )
+ PUNPCKLWD ( MM7, MM4 )
+ PUNPCKHWD ( MM7, MM5 )
+ PMADDWD ( MM0, MM1 )
+ PMADDWD ( MM3, MM4 )
+ PMADDWD ( MM0, MM2 )
+ PMADDWD ( MM3, MM5 )
+ PSRLD ( CONST(8), MM1 )
+ PSRLD ( CONST(8), MM2 )
+ PSRLD ( CONST(8), MM4 )
+ PACKSSDW ( MM2, MM1 )
+ PSRLD ( CONST(8), MM5 )
+ PACKUSWB ( MM1, MM1 )
+ PACKSSDW ( MM5, MM4 )
+ PAND ( REGOFF(-24, EBP), MM1 )
+ PACKUSWB ( MM4, MM4 )
+ PAND ( REGOFF(-16, EBP), MM4 )
+ POR ( MM1, MM4 )
+ MOVQ ( MM4, REGIND(EAX) )
+
+
+LLBL( GMBT_8 ):
+
+LLBL( GMBT_6 ):
+
+ INC_L ( REGOFF(-28, EBP) )
+ JMP ( LLBL(GMBT_4) )
+ALIGNTEXT16
+LLBL( GMBT_5 ):
+
+
+ EMMS
+
+LLBL( GMBT_3 ):
+
+ MOV_L ( REGOFF(12, EBP), EAX )
+ AND_L ( CONST(1), EAX )
+ TEST_L ( EAX, EAX )
+ JE ( LLBL(GMBT_9) )
+ MOV_L ( REGOFF(12, EBP), EAX )
+ LEA_L ( REGDIS(0,EAX,4), EDX )
+ MOV_L ( EDX, EAX )
+ ADD_L ( REGOFF(20, EBP), EAX )
+ LEA_L ( REGOFF(-1, EAX), EDX )
+ XOR_L ( EAX, EAX )
+ MOV_B ( REGIND(EDX), AL )
+ MOV_L ( EAX, REGOFF(-52, EBP) )
+ MOV_L ( CONST(255), EAX )
+ MOV_L ( EAX, EBX )
+ SUB_L ( REGOFF(-52, EBP), EBX )
+ MOV_L ( EBX, REGOFF(-48, EBP) )
+ MOV_L ( REGOFF(12, EBP), EAX )
+ LEA_L ( REGDIS(0,EAX,4), EDX )
+ MOV_L ( EDX, EAX )
+ ADD_L ( REGOFF(20, EBP), EAX )
+ LEA_L ( REGOFF(-4, EAX), EDX )
+ XOR_L ( ECX, ECX )
+ MOV_B ( REGIND(EDX), CL )
+ MOV_L ( ECX, EAX )
+ IMUL_L ( REGOFF(-52, EBP), EAX )
+ MOV_L ( REGOFF(12, EBP), EDX )
+ LEA_L ( REGDIS(0,EDX,4), ECX )
+ MOV_L ( ECX, EDX )
+ ADD_L ( REGOFF(24, EBP), EDX )
+ LEA_L ( REGOFF(-4, EDX), ECX )
+ XOR_L ( EDX, EDX )
+ MOV_B ( REGIND(ECX), DL )
+ MOV_L ( EDX, ECX )
+ IMUL_L ( REGOFF(-48, EBP), ECX )
+ ADD_L ( ECX, EAX )
+ MOV_L ( EAX, EBX )
+ SAR_L ( CONST(8), EBX )
+ MOV_L ( EBX, REGOFF(-44, EBP) )
+ MOV_L ( REGOFF(12, EBP), EAX )
+ LEA_L ( REGDIS(0,EAX,4), EDX )
+ MOV_L ( EDX, EAX )
+ ADD_L ( REGOFF(20, EBP), EAX )
+ LEA_L ( REGOFF(-3, EAX), EDX )
+ XOR_L ( ECX, ECX )
+ MOV_B ( REGIND(EDX), CL )
+ MOV_L ( ECX, EAX )
+ IMUL_L ( REGOFF(-52, EBP), EAX )
+ MOV_L ( REGOFF(12, EBP), EDX )
+ LEA_L ( REGDIS(0,EDX,4), ECX )
+ MOV_L ( ECX, EDX )
+ ADD_L ( REGOFF(24, EBP), EDX )
+ LEA_L ( REGOFF(-3, EDX), ECX )
+ XOR_L ( EDX, EDX )
+ MOV_B ( REGIND(ECX), DL )
+ MOV_L ( EDX, ECX )
+ IMUL_L ( REGOFF(-48, EBP), ECX )
+ ADD_L ( ECX, EAX )
+ MOV_L ( EAX, EBX )
+ SAR_L ( CONST(8), EBX )
+ MOV_L ( EBX, REGOFF(-40, EBP) )
+ MOV_L ( REGOFF(12, EBP), EAX )
+ LEA_L ( REGDIS(0,EAX,4), EDX )
+ MOV_L ( EDX, EAX )
+ ADD_L ( REGOFF(20, EBP), EAX )
+ LEA_L ( REGOFF(-2, EAX), EDX )
+ XOR_L ( ECX, ECX )
+ MOV_B ( REGIND(EDX), CL )
+ MOV_L ( ECX, EAX )
+ IMUL_L ( REGOFF(-52, EBP), EAX )
+ MOV_L ( REGOFF(12, EBP), EDX )
+ LEA_L ( REGDIS(0,EDX,4), ECX )
+ MOV_L ( ECX, EDX )
+ ADD_L ( REGOFF(24, EBP), EDX )
+ LEA_L ( REGOFF(-2, EDX), ECX )
+ XOR_L ( EDX, EDX )
+ MOV_B ( REGIND(ECX), DL )
+ MOV_L ( EDX, ECX )
+ IMUL_L ( REGOFF(-48, EBP), ECX )
+ ADD_L ( ECX, EAX )
+ MOV_L ( EAX, EBX )
+ SAR_L ( CONST(8), EBX )
+ MOV_L ( EBX, REGOFF(-36, EBP) )
+ MOV_L ( REGOFF(12, EBP), EAX )
+ LEA_L ( REGDIS(0,EAX,4), EDX )
+ MOV_L ( EDX, EAX )
+ ADD_L ( REGOFF(20, EBP), EAX )
+ LEA_L ( REGOFF(-1, EAX), EDX )
+ XOR_L ( ECX, ECX )
+ MOV_B ( REGIND(EDX), CL )
+ MOV_L ( ECX, EAX )
+ IMUL_L ( REGOFF(-52, EBP), EAX )
+ MOV_L ( REGOFF(12, EBP), EDX )
+ LEA_L ( REGDIS(0,EDX,4), ECX )
+ MOV_L ( ECX, EDX )
+ ADD_L ( REGOFF(24, EBP), EDX )
+ LEA_L ( REGOFF(-1, EDX), ECX )
+ XOR_L ( EDX, EDX )
+ MOV_B ( REGIND(ECX), DL )
+ MOV_L ( EDX, ECX )
+ IMUL_L ( REGOFF(-48, EBP), ECX )
+ ADD_L ( ECX, EAX )
+ MOV_L ( EAX, EBX )
+ SAR_L ( CONST(8), EBX )
+ MOV_L ( EBX, REGOFF(-32, EBP) )
+ MOV_L ( REGOFF(12, EBP), EAX )
+ LEA_L ( REGDIS(0,EAX,4), EDX )
+ MOV_L ( EDX, EAX )
+ ADD_L ( REGOFF(20, EBP), EAX )
+ LEA_L ( REGOFF(-4, EAX), EDX )
+ MOV_B ( REGOFF(-44, EBP), AL )
+ MOV_B ( AL, REGIND(EDX) )
+ MOV_L ( REGOFF(12, EBP), EAX )
+ LEA_L ( REGDIS(0,EAX,4), EDX )
+ MOV_L ( EDX, EAX )
+ ADD_L ( REGOFF(20, EBP), EAX )
+ LEA_L ( REGOFF(-3, EAX), EDX )
+ MOV_B ( REGOFF(-40, EBP), AL )
+ MOV_B ( AL, REGIND(EDX) )
+ MOV_L ( REGOFF(12, EBP), EAX )
+ LEA_L ( REGDIS(0,EAX,4), EDX )
+ MOV_L ( EDX, EAX )
+ ADD_L ( REGOFF(20, EBP), EAX )
+ LEA_L ( REGOFF(-2, EAX), EDX )
+ MOV_B ( REGOFF(-36, EBP), AL )
+ MOV_B ( AL, REGIND(EDX) )
+ MOV_L ( REGOFF(12, EBP), EAX )
+ LEA_L ( REGDIS(0,EAX,4), EDX )
+ MOV_L ( EDX, EAX )
+ ADD_L ( REGOFF(20, EBP), EAX )
+ LEA_L ( REGOFF(-1, EAX), EDX )
+ MOV_B ( REGOFF(-32, EBP), AL )
+ MOV_B ( AL, REGIND(EDX) )
+LLBL( GMBT_9 ):
+
+LLBL( GMBT_1 ):
+
+ MOV_L ( REGOFF(-56, EBP), EBX )
+ MOV_L ( EBP, ESP )
+ POP_L ( EBP )
+ RET
+
+
+
+
diff --git a/src/mesa/x86/x86.c b/src/mesa/x86/x86.c
new file mode 100644
index 0000000000..fe3bb34c91
--- /dev/null
+++ b/src/mesa/x86/x86.c
@@ -0,0 +1,107 @@
+/* $Id: x86.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+/*
+ * Intel x86 assembly code by Josh Vanderhoof
+ */
+
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "context.h"
+#include "types.h"
+#include "xform.h"
+#include "x86.h"
+
+
+
+#define XFORM_ARGS GLvector4f *to_vec, \
+ const GLmatrix *mat, \
+ const GLvector4f *from_vec, \
+ const GLubyte *mask, \
+ const GLubyte flag
+
+#define DECLARE_XFORM_GROUP(pfx, vsize, masked) \
+ extern void gl_##pfx##_transform_points##vsize##_general_##masked(XFORM_ARGS); \
+ extern void gl_##pfx##_transform_points##vsize##_identity_##masked(XFORM_ARGS); \
+ extern void gl_##pfx##_transform_points##vsize##_3d_no_rot_##masked(XFORM_ARGS); \
+ extern void gl_##pfx##_transform_points##vsize##_perspective_##masked(XFORM_ARGS); \
+ extern void gl_##pfx##_transform_points##vsize##_2d_##masked(XFORM_ARGS); \
+ extern void gl_##pfx##_transform_points##vsize##_2d_no_rot_##masked(XFORM_ARGS); \
+ extern void gl_##pfx##_transform_points##vsize##_3d_##masked(XFORM_ARGS);
+
+#define ASSIGN_XFORM_GROUP( pfx, cma, vsize, masked ) \
+ gl_transform_tab[cma][vsize][MATRIX_GENERAL] \
+ = gl_##pfx##_transform_points##vsize##_general_##masked; \
+ gl_transform_tab[cma][vsize][MATRIX_IDENTITY] \
+ = gl_##pfx##_transform_points##vsize##_identity_##masked; \
+ gl_transform_tab[cma][vsize][MATRIX_3D_NO_ROT] \
+ = gl_##pfx##_transform_points##vsize##_3d_no_rot_##masked; \
+ gl_transform_tab[cma][vsize][MATRIX_PERSPECTIVE] \
+ = gl_##pfx##_transform_points##vsize##_perspective_##masked; \
+ gl_transform_tab[cma][vsize][MATRIX_2D] \
+ = gl_##pfx##_transform_points##vsize##_2d_##masked; \
+ gl_transform_tab[cma][vsize][MATRIX_2D_NO_ROT] \
+ = gl_##pfx##_transform_points##vsize##_2d_no_rot_##masked; \
+ gl_transform_tab[cma][vsize][MATRIX_3D] \
+ = gl_##pfx##_transform_points##vsize##_3d_##masked;
+
+void gl_init_x86_asm_transforms( void )
+{
+#ifdef USE_X86_ASM
+ DECLARE_XFORM_GROUP( x86, 2, raw )
+ DECLARE_XFORM_GROUP( x86, 3, raw )
+ DECLARE_XFORM_GROUP( x86, 4, raw )
+ DECLARE_XFORM_GROUP( x86, 2, masked )
+ DECLARE_XFORM_GROUP( x86, 3, masked )
+ DECLARE_XFORM_GROUP( x86, 4, masked )
+
+ extern GLvector4f *gl_x86_cliptest_points4( GLvector4f *clip_vec,
+ GLvector4f *proj_vec,
+ GLubyte clipMask[],
+ GLubyte *orMask,
+ GLubyte *andMask );
+
+
+ ASSIGN_XFORM_GROUP( x86, 0, 2, raw )
+ ASSIGN_XFORM_GROUP( x86, 0, 3, raw )
+ ASSIGN_XFORM_GROUP( x86, 0, 4, raw )
+
+ ASSIGN_XFORM_GROUP( x86, CULL_MASK_ACTIVE, 2, masked )
+ ASSIGN_XFORM_GROUP( x86, CULL_MASK_ACTIVE, 3, masked )
+ ASSIGN_XFORM_GROUP( x86, CULL_MASK_ACTIVE, 4, masked )
+
+ gl_clip_tab[4] = gl_x86_cliptest_points4;
+
+#ifdef DEBUG
+ gl_test_all_transform_functions("x86");
+#endif
+
+#endif
+}
diff --git a/src/mesa/x86/x86.h b/src/mesa/x86/x86.h
new file mode 100644
index 0000000000..c7aca91c9f
--- /dev/null
+++ b/src/mesa/x86/x86.h
@@ -0,0 +1,37 @@
+/* $Id: x86.h,v 1.1 1999/08/19 00:55:42 jtg Exp $ */
+
+/*
+ * Mesa 3-D graphics library
+ * Version: 3.1
+ *
+ * Copyright (C) 1999 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.
+ */
+
+/*
+ * Intel x86 assembly code by Josh Vanderhoof
+ */
+
+
+#ifndef X86_H
+#define X86_H
+
+extern void gl_init_x86_asm_transforms(void);
+
+#endif