diff options
author | jtg <jtg> | 1999-08-19 00:55:39 +0000 |
---|---|---|
committer | jtg <jtg> | 1999-08-19 00:55:39 +0000 |
commit | afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1c (patch) | |
tree | 59d65b4da12fb5379224cf5f6b808fde91523c7f /src | |
parent | f2544d4920ce168bec9cd94d774b7ea5103a3d74 (diff) |
Initial revision
Diffstat (limited to 'src')
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 |